From cdc7bbd594a8bdb4e3c93adece29a24bd30276e8 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Sat, 2 Oct 2021 01:29:42 +0100 Subject: [PATCH] New upstream version 1.53.0+dfsg1 --- Cargo.lock | 654 +- Cargo.toml | 4 + RELEASES.md | 204 +- compiler/rustc/Cargo.toml | 10 +- compiler/rustc/src/main.rs | 15 +- compiler/rustc_apfloat/src/ieee.rs | 5 +- compiler/rustc_apfloat/src/lib.rs | 3 +- compiler/rustc_arena/src/lib.rs | 20 - compiler/rustc_ast/src/ast.rs | 69 +- compiler/rustc_ast/src/ast_like.rs | 102 +- compiler/rustc_ast/src/attr/mod.rs | 54 +- compiler/rustc_ast/src/expand/mod.rs | 2 +- compiler/rustc_ast/src/lib.rs | 8 +- compiler/rustc_ast/src/mut_visit.rs | 51 +- compiler/rustc_ast/src/token.rs | 23 +- compiler/rustc_ast/src/tokenstream.rs | 184 +- compiler/rustc_ast/src/visit.rs | 4 +- compiler/rustc_ast_lowering/src/expr.rs | 88 +- compiler/rustc_ast_lowering/src/item.rs | 19 +- compiler/rustc_ast_lowering/src/lib.rs | 84 +- .../rustc_ast_passes/src/ast_validation.rs | 86 +- compiler/rustc_ast_passes/src/feature_gate.rs | 78 +- compiler/rustc_ast_pretty/src/lib.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/mod.rs | 24 - compiler/rustc_ast_pretty/src/pprust/state.rs | 14 +- compiler/rustc_attr/src/lib.rs | 2 +- compiler/rustc_builtin_macros/src/asm.rs | 99 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 222 +- compiler/rustc_builtin_macros/src/derive.rs | 57 +- .../src/deriving/cmp/eq.rs | 4 +- .../src/deriving/generic/mod.rs | 23 +- .../src/global_allocator.rs | 32 +- compiler/rustc_builtin_macros/src/lib.rs | 3 +- .../rustc_builtin_macros/src/test_harness.rs | 12 +- .../.github/workflows/bootstrap_rustc.yml | 44 - .../.github/workflows/main.yml | 21 +- .../.github/workflows/rustc.yml | 82 + .../.vscode/settings.json | 2 +- compiler/rustc_codegen_cranelift/Cargo.lock | 40 +- compiler/rustc_codegen_cranelift/Cargo.toml | 5 +- compiler/rustc_codegen_cranelift/Readme.md | 76 +- compiler/rustc_codegen_cranelift/build.sh | 7 + .../build_sysroot/Cargo.lock | 16 +- .../build_sysroot/build_sysroot.sh | 2 +- .../rustc_codegen_cranelift/docs/env_vars.md | 5 +- .../rustc_codegen_cranelift/docs/usage.md | 66 + .../example/mini_core.rs | 1 + .../example/mini_core_hello_world.rs | 9 +- compiler/rustc_codegen_cranelift/prepare.sh | 1 - .../rustc_codegen_cranelift/rust-toolchain | 4 +- .../rustc_codegen_cranelift/scripts/cargo.sh | 2 +- .../rustc_codegen_cranelift/scripts/config.sh | 14 +- .../rustc_codegen_cranelift/scripts/rustup.sh | 2 +- .../scripts/setup_rust_fork.sh | 68 + .../scripts/test_bootstrap.sh | 62 +- .../scripts/test_rustc_tests.sh | 87 + .../rustc_codegen_cranelift/scripts/tests.sh | 45 +- .../src/abi/comments.rs | 27 +- .../rustc_codegen_cranelift/src/abi/mod.rs | 24 +- .../src/abi/pass_mode.rs | 7 +- .../src/abi/returning.rs | 6 +- .../rustc_codegen_cranelift/src/allocator.rs | 5 +- compiler/rustc_codegen_cranelift/src/base.rs | 63 +- .../src/codegen_i128.rs | 89 +- .../rustc_codegen_cranelift/src/common.rs | 3 +- .../src/compiler_builtins.rs | 41 + .../rustc_codegen_cranelift/src/constant.rs | 37 +- .../src/debuginfo/line_info.rs | 4 +- .../rustc_codegen_cranelift/src/driver/aot.rs | 22 +- .../rustc_codegen_cranelift/src/driver/jit.rs | 89 +- .../rustc_codegen_cranelift/src/driver/mod.rs | 8 +- .../rustc_codegen_cranelift/src/inline_asm.rs | 14 +- .../src/intrinsics/simd.rs | 4 +- compiler/rustc_codegen_cranelift/src/lib.rs | 39 +- .../rustc_codegen_cranelift/src/linkage.rs | 2 + .../rustc_codegen_cranelift/src/main_shim.rs | 11 +- .../rustc_codegen_cranelift/src/metadata.rs | 55 +- compiler/rustc_codegen_cranelift/src/num.rs | 8 +- .../src/optimize/stack2reg.rs | 89 +- .../rustc_codegen_cranelift/src/pointer.rs | 3 +- .../src/pretty_clif.rs | 24 +- compiler/rustc_codegen_cranelift/src/trap.rs | 3 +- .../src/value_and_place.rs | 19 +- .../rustc_codegen_cranelift/src/vtable.rs | 2 +- compiler/rustc_codegen_llvm/src/abi.rs | 58 +- compiler/rustc_codegen_llvm/src/asm.rs | 27 +- compiler/rustc_codegen_llvm/src/attributes.rs | 51 +- compiler/rustc_codegen_llvm/src/back/lto.rs | 5 +- compiler/rustc_codegen_llvm/src/back/write.rs | 20 +- compiler/rustc_codegen_llvm/src/base.rs | 5 +- compiler/rustc_codegen_llvm/src/builder.rs | 124 +- compiler/rustc_codegen_llvm/src/callee.rs | 19 +- compiler/rustc_codegen_llvm/src/context.rs | 47 +- .../src/coverageinfo/mapgen.rs | 233 +- .../src/coverageinfo/mod.rs | 164 +- .../rustc_codegen_llvm/src/debuginfo/doc.md | 180 + .../rustc_codegen_llvm/src/debuginfo/doc.rs | 179 - .../src/debuginfo/metadata.rs | 12 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 10 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 36 +- compiler/rustc_codegen_llvm/src/lib.rs | 4 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 55 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 91 +- compiler/rustc_codegen_llvm/src/mono_item.rs | 41 + compiler/rustc_codegen_ssa/Cargo.toml | 5 +- compiler/rustc_codegen_ssa/src/back/link.rs | 63 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 22 +- compiler/rustc_codegen_ssa/src/back/lto.rs | 3 +- .../src/back/symbol_export.rs | 7 +- compiler/rustc_codegen_ssa/src/back/write.rs | 15 +- compiler/rustc_codegen_ssa/src/base.rs | 28 +- .../rustc_codegen_ssa/src/coverageinfo/ffi.rs | 22 +- .../rustc_codegen_ssa/src/coverageinfo/map.rs | 102 +- compiler/rustc_codegen_ssa/src/lib.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 64 +- .../rustc_codegen_ssa/src/mir/constant.rs | 4 +- .../rustc_codegen_ssa/src/mir/coverageinfo.rs | 4 +- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 54 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 12 + compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 168 +- .../rustc_codegen_ssa/src/target_features.rs | 3 +- .../rustc_codegen_ssa/src/traits/builder.rs | 1 - .../src/traits/coverageinfo.rs | 18 +- compiler/rustc_codegen_ssa/src/traits/mod.rs | 4 +- compiler/rustc_data_structures/Cargo.toml | 10 +- .../rustc_data_structures/src/fingerprint.rs | 80 +- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_data_structures/src/memmap.rs | 47 + compiler/rustc_data_structures/src/sso/map.rs | 13 +- compiler/rustc_data_structures/src/svh.rs | 2 +- .../src/tagged_ptr/drop.rs | 9 - .../rustc_data_structures/src/thin_vec.rs | 49 + .../src/thin_vec/tests.rs | 42 + .../rustc_data_structures/src/work_queue.rs | 6 - compiler/rustc_driver/src/lib.rs | 17 +- compiler/rustc_driver/src/pretty.rs | 64 +- compiler/rustc_error_codes/src/error_codes.rs | 2 +- .../src/error_codes/E0128.md | 2 +- .../src/error_codes/E0136.md | 4 +- .../src/error_codes/E0137.md | 6 +- .../src/error_codes/E0379.md | 2 - .../src/error_codes/E0404.md | 26 +- .../src/error_codes/E0554.md | 4 +- .../src/error_codes/E0723.md | 20 - .../src/error_codes/E0754.md | 3 - .../src/error_codes/E0764.md | 2 - compiler/rustc_error_codes/src/lib.rs | 3 +- compiler/rustc_errors/src/diagnostic.rs | 60 +- .../rustc_errors/src/diagnostic_builder.rs | 27 - compiler/rustc_errors/src/emitter.rs | 43 +- compiler/rustc_errors/src/json.rs | 27 +- compiler/rustc_errors/src/lib.rs | 15 +- compiler/rustc_errors/src/registry.rs | 4 - compiler/rustc_errors/src/snippet.rs | 10 - compiler/rustc_errors/src/styled_buffer.rs | 89 +- compiler/rustc_expand/src/base.rs | 88 +- compiler/rustc_expand/src/build.rs | 11 - compiler/rustc_expand/src/config.rs | 121 +- compiler/rustc_expand/src/expand.rs | 103 +- compiler/rustc_expand/src/lib.rs | 3 +- compiler/rustc_expand/src/mbe.rs | 2 +- compiler/rustc_expand/src/mbe/macro_check.rs | 4 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 42 +- compiler/rustc_expand/src/mbe/quoted.rs | 19 +- compiler/rustc_expand/src/mbe/transcribe.rs | 4 +- compiler/rustc_expand/src/proc_macro.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 34 +- .../rustc_expand/src/tokenstream/tests.rs | 10 +- compiler/rustc_feature/src/accepted.rs | 6 +- compiler/rustc_feature/src/active.rs | 48 +- compiler/rustc_feature/src/builtin_attrs.rs | 25 +- compiler/rustc_feature/src/lib.rs | 2 +- compiler/rustc_feature/src/removed.rs | 13 + compiler/rustc_graphviz/src/lib.rs | 18 - compiler/rustc_graphviz/src/tests.rs | 2 +- compiler/rustc_hir/src/def.rs | 155 +- compiler/rustc_hir/src/definitions.rs | 7 +- compiler/rustc_hir/src/hir.rs | 37 +- compiler/rustc_hir/src/hir_id.rs | 1 + compiler/rustc_hir/src/intravisit.rs | 17 +- compiler/rustc_hir/src/lib.rs | 3 +- compiler/rustc_hir/src/pat_util.rs | 27 +- compiler/rustc_hir/src/stable_hash_impls.rs | 2 +- compiler/rustc_hir/src/weak_lang_items.rs | 4 +- compiler/rustc_hir_pretty/src/lib.rs | 71 +- .../rustc_incremental/src/assert_dep_graph.rs | 47 +- compiler/rustc_incremental/src/lib.rs | 4 +- .../src/persist/dirty_clean.rs | 44 +- .../src/persist/file_format.rs | 1 + compiler/rustc_incremental/src/persist/fs.rs | 4 + .../rustc_incremental/src/persist/load.rs | 6 +- compiler/rustc_incremental/src/persist/mod.rs | 1 + .../rustc_incremental/src/persist/save.rs | 105 +- compiler/rustc_index/Cargo.toml | 2 +- compiler/rustc_index/src/bit_set.rs | 8 +- compiler/rustc_index/src/lib.rs | 3 +- compiler/rustc_index/src/vec.rs | 6 +- .../src/infer/canonical/canonicalizer.rs | 4 +- .../src/infer/canonical/query_response.rs | 6 +- .../src/infer/canonical/substitute.rs | 9 +- compiler/rustc_infer/src/infer/combine.rs | 42 +- compiler/rustc_infer/src/infer/equate.rs | 6 +- .../src/infer/error_reporting/mod.rs | 75 +- .../infer/error_reporting/need_type_info.rs | 32 +- .../nice_region_error/find_anon_type.rs | 19 +- compiler/rustc_infer/src/infer/glb.rs | 6 +- .../src/infer/higher_ranked/mod.rs | 13 +- compiler/rustc_infer/src/infer/lub.rs | 6 +- compiler/rustc_infer/src/infer/mod.rs | 26 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 18 +- .../rustc_infer/src/infer/outlives/env.rs | 5 - .../src/infer/outlives/obligations.rs | 22 - .../src/infer/region_constraints/mod.rs | 40 - compiler/rustc_infer/src/infer/resolve.rs | 5 + compiler/rustc_infer/src/infer/sub.rs | 6 +- .../rustc_infer/src/infer/type_variable.rs | 56 +- compiler/rustc_infer/src/infer/undo_log.rs | 4 - compiler/rustc_infer/src/lib.rs | 6 +- .../src/traits/error_reporting/mod.rs | 3 +- compiler/rustc_infer/src/traits/mod.rs | 2 +- compiler/rustc_infer/src/traits/util.rs | 4 +- compiler/rustc_interface/Cargo.toml | 2 +- compiler/rustc_interface/src/callbacks.rs | 14 +- compiler/rustc_interface/src/passes.rs | 19 +- compiler/rustc_interface/src/queries.rs | 13 +- compiler/rustc_interface/src/tests.rs | 155 +- compiler/rustc_interface/src/util.rs | 25 +- compiler/rustc_lexer/src/lib.rs | 6 +- compiler/rustc_lint/src/builtin.rs | 106 +- compiler/rustc_lint/src/context.rs | 11 +- compiler/rustc_lint/src/early.rs | 1 + compiler/rustc_lint/src/levels.rs | 92 +- compiler/rustc_lint/src/lib.rs | 5 +- compiler/rustc_lint/src/non_ascii_idents.rs | 37 +- compiler/rustc_lint/src/types.rs | 8 +- compiler/rustc_lint_defs/src/builtin.rs | 194 +- compiler/rustc_lint_defs/src/lib.rs | 1 + compiler/rustc_llvm/build.rs | 14 - .../llvm-wrapper/ArchiveWrapper.cpp | 4 - .../llvm-wrapper/CoverageMappingWrapper.cpp | 7 + .../rustc_llvm/llvm-wrapper/LLVMWrapper.h | 7 - .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 84 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 69 +- compiler/rustc_llvm/src/lib.rs | 5 +- compiler/rustc_macros/src/symbols/tests.rs | 2 +- compiler/rustc_metadata/Cargo.toml | 1 - compiler/rustc_metadata/src/creader.rs | 57 +- compiler/rustc_metadata/src/lib.rs | 3 +- compiler/rustc_metadata/src/link_args.rs | 57 - compiler/rustc_metadata/src/locator.rs | 56 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 29 +- .../src/rmeta/decoder/cstore_impl.rs | 6 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 110 +- compiler/rustc_metadata/src/rmeta/mod.rs | 6 +- compiler/rustc_metadata/src/rmeta/table.rs | 3 +- .../rustc_middle/src/dep_graph/dep_node.rs | 36 +- compiler/rustc_middle/src/dep_graph/mod.rs | 7 +- .../rustc_middle/src/hir/map/collector.rs | 61 +- compiler/rustc_middle/src/hir/map/mod.rs | 35 +- compiler/rustc_middle/src/ich/hcx.rs | 5 - compiler/rustc_middle/src/ich/impls_syntax.rs | 2 +- compiler/rustc_middle/src/ich/impls_ty.rs | 9 +- compiler/rustc_middle/src/infer/canonical.rs | 19 +- compiler/rustc_middle/src/infer/unify_key.rs | 7 - compiler/rustc_middle/src/lib.rs | 5 +- .../src/middle/codegen_fn_attrs.rs | 6 +- compiler/rustc_middle/src/middle/limits.rs | 15 +- compiler/rustc_middle/src/middle/region.rs | 33 +- .../src/middle/resolve_lifetime.rs | 14 +- compiler/rustc_middle/src/middle/stability.rs | 6 - .../rustc_middle/src/mir/abstract_const.rs | 17 + compiler/rustc_middle/src/mir/coverage.rs | 28 +- .../rustc_middle/src/mir/interpret/error.rs | 4 +- .../rustc_middle/src/mir/interpret/queries.rs | 10 +- .../rustc_middle/src/mir/interpret/value.rs | 10 - compiler/rustc_middle/src/mir/mod.rs | 89 +- compiler/rustc_middle/src/mir/mono.rs | 9 +- compiler/rustc_middle/src/mir/query.rs | 10 +- compiler/rustc_middle/src/mir/terminator.rs | 2 +- compiler/rustc_middle/src/mir/traversal.rs | 4 - .../rustc_middle/src/mir/type_foldable.rs | 5 + compiler/rustc_middle/src/mir/visit.rs | 14 +- compiler/rustc_middle/src/query/mod.rs | 63 +- compiler/rustc_middle/src/traits/mod.rs | 17 +- compiler/rustc_middle/src/traits/query.rs | 14 +- compiler/rustc_middle/src/ty/_match.rs | 6 +- compiler/rustc_middle/src/ty/assoc.rs | 6 +- compiler/rustc_middle/src/ty/closure.rs | 19 +- compiler/rustc_middle/src/ty/codec.rs | 60 +- compiler/rustc_middle/src/ty/consts.rs | 29 +- compiler/rustc_middle/src/ty/consts/kind.rs | 19 +- compiler/rustc_middle/src/ty/context.rs | 89 +- compiler/rustc_middle/src/ty/erase_regions.rs | 7 +- compiler/rustc_middle/src/ty/error.rs | 65 +- compiler/rustc_middle/src/ty/flags.rs | 20 +- compiler/rustc_middle/src/ty/fold.rs | 293 +- compiler/rustc_middle/src/ty/generics.rs | 22 +- compiler/rustc_middle/src/ty/instance.rs | 10 +- compiler/rustc_middle/src/ty/layout.rs | 121 +- compiler/rustc_middle/src/ty/mod.rs | 110 +- .../src/ty/normalize_erasing_regions.rs | 11 +- compiler/rustc_middle/src/ty/print/mod.rs | 28 +- compiler/rustc_middle/src/ty/print/pretty.rs | 201 +- compiler/rustc_middle/src/ty/query/mod.rs | 7 +- .../src/ty/query/on_disk_cache.rs | 89 +- compiler/rustc_middle/src/ty/relate.rs | 88 +- .../rustc_middle/src/ty/structural_impls.rs | 28 +- compiler/rustc_middle/src/ty/sty.rs | 228 +- compiler/rustc_middle/src/ty/subst.rs | 11 +- compiler/rustc_middle/src/ty/trait_def.rs | 13 + compiler/rustc_middle/src/ty/util.rs | 243 +- compiler/rustc_middle/src/ty/walk.rs | 4 +- .../diagnostics/conflict_errors.rs | 37 +- .../diagnostics/explain_borrow.rs | 2 +- .../src/borrow_check/diagnostics/mod.rs | 58 +- .../diagnostics/outlives_suggestion.rs | 4 +- .../borrow_check/diagnostics/region_name.rs | 6 +- .../src/borrow_check/invalidation.rs | 11 +- compiler/rustc_mir/src/borrow_check/mod.rs | 11 +- .../src/borrow_check/places_conflict.rs | 3 +- .../src/borrow_check/region_infer/graphviz.rs | 2 +- .../borrow_check/type_check/input_output.rs | 6 + .../src/borrow_check/type_check/mod.rs | 12 +- .../src/borrow_check/universal_regions.rs | 48 +- .../rustc_mir/src/const_eval/eval_queries.rs | 10 + .../rustc_mir/src/const_eval/fn_queries.rs | 49 - compiler/rustc_mir/src/const_eval/machine.rs | 2 +- compiler/rustc_mir/src/const_eval/mod.rs | 2 +- .../src/dataflow/framework/cursor.rs | 4 - .../src/dataflow/framework/lattice.rs | 5 +- .../rustc_mir/src/dataflow/framework/mod.rs | 2 +- .../rustc_mir/src/dataflow/impls/borrows.rs | 3 +- .../src/dataflow/move_paths/builder.rs | 12 +- .../rustc_mir/src/interpret/eval_context.rs | 8 +- .../rustc_mir/src/interpret/intrinsics.rs | 3 +- .../src/interpret/intrinsics/type_name.rs | 2 +- compiler/rustc_mir/src/interpret/operand.rs | 14 +- compiler/rustc_mir/src/lib.rs | 4 +- .../rustc_mir/src/monomorphize/collector.rs | 104 +- compiler/rustc_mir/src/monomorphize/mod.rs | 4 +- .../src/monomorphize/polymorphize.rs | 6 +- .../src/transform/check_consts/ops.rs | 40 +- .../check_consts/post_drop_elaboration.rs | 8 +- .../src/transform/check_consts/qualifs.rs | 6 +- .../src/transform/check_consts/validation.rs | 36 +- .../src/transform/check_packed_ref.rs | 89 +- .../rustc_mir/src/transform/check_unsafety.rs | 193 +- .../rustc_mir/src/transform/const_prop.rs | 25 +- .../rustc_mir/src/transform/coverage/debug.rs | 7 +- .../rustc_mir/src/transform/coverage/mod.rs | 9 +- .../rustc_mir/src/transform/coverage/query.rs | 45 +- .../rustc_mir/src/transform/coverage/spans.rs | 22 +- .../rustc_mir/src/transform/coverage/tests.rs | 2 +- .../src/transform/deduplicate_blocks.rs | 8 +- compiler/rustc_mir/src/transform/dest_prop.rs | 4 +- compiler/rustc_mir/src/transform/generator.rs | 7 +- compiler/rustc_mir/src/transform/inline.rs | 2 +- .../rustc_mir/src/transform/match_branches.rs | 5 +- compiler/rustc_mir/src/transform/mod.rs | 10 +- .../rustc_mir/src/transform/promote_consts.rs | 90 +- .../rustc_mir/src/transform/remove_zsts.rs | 89 + .../src/transform/required_consts.rs | 2 +- compiler/rustc_mir/src/transform/simplify.rs | 83 +- compiler/rustc_mir/src/util/alignment.rs | 35 +- compiler/rustc_mir/src/util/find_self_call.rs | 2 +- .../rustc_mir/src/util/generic_graphviz.rs | 16 - compiler/rustc_mir/src/util/patch.rs | 10 - compiler/rustc_mir/src/util/pretty.rs | 22 +- compiler/rustc_mir_build/src/build/cfg.rs | 2 +- .../src/build/expr/as_place.rs | 8 +- .../src/build/expr/as_rvalue.rs | 4 +- .../rustc_mir_build/src/build/expr/into.rs | 60 +- .../rustc_mir_build/src/build/matches/mod.rs | 6 +- compiler/rustc_mir_build/src/build/mod.rs | 10 +- compiler/rustc_mir_build/src/build/scope.rs | 15 + compiler/rustc_mir_build/src/lib.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 24 +- compiler/rustc_mir_build/src/thir/mod.rs | 3 +- .../src/thir/pattern/const_to_pat.rs | 26 +- compiler/rustc_parse/src/lexer/mod.rs | 2 +- compiler/rustc_parse/src/lib.rs | 77 +- compiler/rustc_parse/src/parser/attr.rs | 22 +- .../rustc_parse/src/parser/attr_wrapper.rs | 494 +- .../rustc_parse/src/parser/diagnostics.rs | 32 +- compiler/rustc_parse/src/parser/expr.rs | 37 +- compiler/rustc_parse/src/parser/item.rs | 66 +- compiler/rustc_parse/src/parser/mod.rs | 182 +- .../rustc_parse/src/parser/nonterminal.rs | 39 +- compiler/rustc_parse/src/parser/pat.rs | 73 +- compiler/rustc_parse/src/parser/stmt.rs | 70 +- compiler/rustc_parse_format/src/lib.rs | 35 +- compiler/rustc_passes/src/check_attr.rs | 123 +- compiler/rustc_passes/src/dead.rs | 4 +- compiler/rustc_passes/src/entry.rs | 64 +- compiler/rustc_passes/src/hir_id_validator.rs | 13 - compiler/rustc_passes/src/intrinsicck.rs | 11 +- compiler/rustc_passes/src/lib.rs | 4 +- compiler/rustc_passes/src/liveness.rs | 13 +- .../rustc_passes/src/liveness/rwu_table.rs | 3 +- compiler/rustc_passes/src/region.rs | 15 +- compiler/rustc_passes/src/stability.rs | 14 +- compiler/rustc_privacy/src/lib.rs | 12 +- compiler/rustc_query_impl/src/keys.rs | 9 + compiler/rustc_query_impl/src/lib.rs | 3 +- compiler/rustc_query_impl/src/plumbing.rs | 35 +- .../rustc_query_impl/src/profiling_support.rs | 19 +- compiler/rustc_query_impl/src/stats.rs | 9 +- compiler/rustc_query_system/src/cache.rs | 8 - .../rustc_query_system/src/dep_graph/debug.rs | 15 +- .../src/dep_graph/dep_node.rs | 2 +- .../rustc_query_system/src/dep_graph/graph.rs | 959 +- .../rustc_query_system/src/dep_graph/mod.rs | 3 +- .../rustc_query_system/src/dep_graph/prev.rs | 5 - .../rustc_query_system/src/dep_graph/query.rs | 47 +- .../src/dep_graph/serialized.rs | 318 +- compiler/rustc_query_system/src/lib.rs | 3 +- .../rustc_query_system/src/query/caches.rs | 34 +- compiler/rustc_query_system/src/query/job.rs | 4 +- .../rustc_query_system/src/query/plumbing.rs | 27 +- .../rustc_resolve/src/build_reduced_graph.rs | 9 +- compiler/rustc_resolve/src/diagnostics.rs | 45 +- compiler/rustc_resolve/src/imports.rs | 4 +- compiler/rustc_resolve/src/late.rs | 84 +- .../rustc_resolve/src/late/diagnostics.rs | 29 +- compiler/rustc_resolve/src/late/lifetimes.rs | 1353 +- compiler/rustc_resolve/src/lib.rs | 377 +- compiler/rustc_resolve/src/macros.rs | 138 +- .../rustc_save_analysis/src/dump_visitor.rs | 24 +- compiler/rustc_save_analysis/src/lib.rs | 20 +- compiler/rustc_save_analysis/src/sig.rs | 7 +- compiler/rustc_serialize/src/json.rs | 19 + compiler/rustc_serialize/src/lib.rs | 3 +- compiler/rustc_serialize/src/opaque.rs | 102 +- compiler/rustc_serialize/src/serialize.rs | 2 + compiler/rustc_serialize/tests/leb128.rs | 1 - compiler/rustc_session/src/config.rs | 243 +- compiler/rustc_session/src/lib.rs | 4 +- compiler/rustc_session/src/options.rs | 285 +- compiler/rustc_session/src/parse.rs | 1 + compiler/rustc_session/src/session.rs | 216 +- compiler/rustc_session/src/utils.rs | 55 + compiler/rustc_span/src/def_id.rs | 2 + compiler/rustc_span/src/hygiene.rs | 30 +- compiler/rustc_span/src/lib.rs | 8 - compiler/rustc_span/src/symbol.rs | 20 +- compiler/rustc_symbol_mangling/src/legacy.rs | 2 +- compiler/rustc_symbol_mangling/src/lib.rs | 4 +- compiler/rustc_symbol_mangling/src/v0.rs | 6 +- compiler/rustc_target/README.md | 2 +- compiler/rustc_target/src/abi/call/mod.rs | 25 +- .../src/abi/call/{wasm32.rs => wasm.rs} | 27 +- .../src/abi/call/wasm32_bindgen_compat.rs | 29 - compiler/rustc_target/src/abi/mod.rs | 2 +- compiler/rustc_target/src/asm/arm.rs | 2 - compiler/rustc_target/src/asm/mod.rs | 4 +- compiler/rustc_target/src/asm/riscv.rs | 1 - compiler/rustc_target/src/asm/x86.rs | 7 +- compiler/rustc_target/src/lib.rs | 3 +- .../src/spec/aarch64_apple_darwin.rs | 5 +- .../rustc_target/src/spec/aarch64_fuchsia.rs | 3 +- .../src/spec/aarch64_linux_android.rs | 3 +- .../src/spec/aarch64_unknown_linux_gnu.rs | 7 +- compiler/rustc_target/src/spec/abi.rs | 15 +- .../rustc_target/src/spec/android_base.rs | 9 +- compiler/rustc_target/src/spec/apple_base.rs | 4 +- .../src/spec/armv7_linux_androideabi.rs | 2 +- .../src/spec/armv7_unknown_linux_gnueabi.rs | 1 - .../src/spec/armv7_unknown_linux_gnueabihf.rs | 1 - .../src/spec/armv7_unknown_linux_musleabi.rs | 1 - .../spec/armv7_unknown_linux_musleabihf.rs | 1 - .../src/spec/armv7_unknown_netbsd_eabihf.rs | 1 - .../src/spec/armv7_wrs_vxworks_eabihf.rs | 1 - .../rustc_target/src/spec/avr_gnu_base.rs | 22 +- .../rustc_target/src/spec/dragonfly_base.rs | 17 +- .../rustc_target/src/spec/freebsd_base.rs | 17 +- .../rustc_target/src/spec/fuchsia_base.rs | 2 - compiler/rustc_target/src/spec/haiku_base.rs | 1 - compiler/rustc_target/src/spec/hermit_base.rs | 5 +- .../src/spec/hermit_kernel_base.rs | 5 +- .../src/spec/hexagon_unknown_linux_musl.rs | 6 +- .../src/spec/i686_pc_windows_gnu.rs | 4 +- .../src/spec/i686_pc_windows_msvc.rs | 6 +- .../src/spec/i686_unknown_freebsd.rs | 2 +- .../src/spec/i686_unknown_linux_gnu.rs | 2 +- .../src/spec/i686_unknown_linux_musl.rs | 4 +- .../src/spec/i686_unknown_netbsd.rs | 2 +- .../src/spec/i686_unknown_openbsd.rs | 4 +- .../src/spec/i686_uwp_windows_gnu.rs | 4 +- .../rustc_target/src/spec/i686_wrs_vxworks.rs | 2 +- compiler/rustc_target/src/spec/l4re_base.rs | 7 +- compiler/rustc_target/src/spec/linux_base.rs | 20 +- .../src/spec/linux_kernel_base.rs | 11 +- compiler/rustc_target/src/spec/mod.rs | 213 +- compiler/rustc_target/src/spec/msvc_base.rs | 7 - compiler/rustc_target/src/spec/netbsd_base.rs | 15 +- .../rustc_target/src/spec/openbsd_base.rs | 17 +- .../src/spec/powerpc64_unknown_freebsd.rs | 2 +- .../src/spec/powerpc64_unknown_linux_gnu.rs | 2 +- .../src/spec/powerpc64_unknown_linux_musl.rs | 2 +- .../src/spec/powerpc64_wrs_vxworks.rs | 2 +- .../src/spec/powerpc64le_unknown_linux_gnu.rs | 2 +- .../spec/powerpc64le_unknown_linux_musl.rs | 2 +- .../src/spec/powerpc_unknown_linux_gnu.rs | 2 +- .../src/spec/powerpc_unknown_linux_gnuspe.rs | 2 +- .../src/spec/powerpc_unknown_linux_musl.rs | 2 +- .../src/spec/powerpc_unknown_netbsd.rs | 2 +- .../src/spec/powerpc_wrs_vxworks.rs | 4 +- .../src/spec/powerpc_wrs_vxworks_spe.rs | 4 +- compiler/rustc_target/src/spec/redox_base.rs | 20 +- .../src/spec/riscv32i_unknown_none_elf.rs | 1 - .../src/spec/riscv32imac_unknown_none_elf.rs | 1 - .../src/spec/riscv64gc_unknown_none_elf.rs | 1 - .../src/spec/riscv64imac_unknown_none_elf.rs | 1 - .../src/spec/sparc64_unknown_netbsd.rs | 2 +- .../src/spec/sparc64_unknown_openbsd.rs | 2 +- .../src/spec/sparc_unknown_linux_gnu.rs | 2 +- .../rustc_target/src/spec/tests/tests_impl.rs | 1 + .../src/spec/thumbv4t_none_eabi.rs | 3 - .../src/spec/thumbv7a_pc_windows_msvc.rs | 7 +- .../src/spec/thumbv7a_uwp_windows_msvc.rs | 1 - .../src/spec/thumbv7neon_linux_androideabi.rs | 2 +- .../thumbv7neon_unknown_linux_gnueabihf.rs | 1 - .../thumbv7neon_unknown_linux_musleabihf.rs | 1 - .../rustc_target/src/spec/uefi_msvc_base.rs | 6 +- .../rustc_target/src/spec/vxworks_base.rs | 19 +- .../src/spec/wasm32_unknown_emscripten.rs | 6 +- .../src/spec/wasm32_unknown_unknown.rs | 20 +- compiler/rustc_target/src/spec/wasm32_wasi.rs | 4 +- .../src/spec/wasm64_unknown_unknown.rs | 39 + .../src/spec/{wasm32_base.rs => wasm_base.rs} | 3 +- .../rustc_target/src/spec/windows_gnu_base.rs | 4 - .../src/spec/windows_uwp_msvc_base.rs | 6 +- .../src/spec/x86_64_apple_darwin.rs | 3 +- .../src/spec/x86_64_fortanix_unknown_sgx.rs | 7 +- .../rustc_target/src/spec/x86_64_fuchsia.rs | 3 +- .../src/spec/x86_64_linux_android.rs | 2 +- .../src/spec/x86_64_pc_windows_gnu.rs | 2 +- .../src/spec/x86_64_unknown_dragonfly.rs | 2 +- .../src/spec/x86_64_unknown_freebsd.rs | 5 +- .../src/spec/x86_64_unknown_linux_gnu.rs | 6 +- .../src/spec/x86_64_unknown_linux_gnux32.rs | 2 +- .../src/spec/x86_64_unknown_linux_musl.rs | 6 +- .../src/spec/x86_64_unknown_netbsd.rs | 2 +- .../spec/x86_64_unknown_none_linuxkernel.rs | 2 +- .../src/spec/x86_64_unknown_openbsd.rs | 2 +- .../src/spec/x86_64_unknown_redox.rs | 2 +- .../src/spec/x86_64_uwp_windows_gnu.rs | 2 +- .../src/spec/x86_64_wrs_vxworks.rs | 2 +- compiler/rustc_trait_selection/src/lib.rs | 3 +- .../rustc_trait_selection/src/opaque_types.rs | 4 +- .../src/traits/auto_trait.rs | 15 +- .../src/traits/coherence.rs | 40 +- .../src/traits/const_evaluatable.rs | 119 +- .../src/traits/error_reporting/mod.rs | 87 +- .../error_reporting/on_unimplemented.rs | 110 +- .../src/traits/error_reporting/suggestions.rs | 136 +- .../src/traits/fulfill.rs | 43 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/object_safety.rs | 27 +- .../src/traits/on_unimplemented.rs | 2 +- .../src/traits/project.rs | 5 +- .../src/traits/query/mod.rs | 2 +- .../src/traits/query/normalize.rs | 5 + .../query/type_op/implied_outlives_bounds.rs | 6 - .../src/traits/select/confirmation.rs | 11 +- .../src/traits/select/mod.rs | 54 +- .../src/traits/specialize/mod.rs | 4 +- .../rustc_trait_selection/src/traits/util.rs | 4 +- .../rustc_trait_selection/src/traits/wf.rs | 12 +- compiler/rustc_traits/src/chalk/db.rs | 7 +- compiler/rustc_traits/src/chalk/lowering.rs | 50 +- .../src/normalize_erasing_regions.rs | 27 +- compiler/rustc_ty_utils/src/common_traits.rs | 12 +- compiler/rustc_ty_utils/src/instance.rs | 2 +- compiler/rustc_ty_utils/src/lib.rs | 1 + .../rustc_ty_utils/src/representability.rs | 186 + compiler/rustc_ty_utils/src/ty.rs | 4 +- compiler/rustc_type_ir/src/lib.rs | 4 - compiler/rustc_typeck/Cargo.toml | 1 + compiler/rustc_typeck/src/astconv/errors.rs | 3 +- compiler/rustc_typeck/src/astconv/generics.rs | 36 +- compiler/rustc_typeck/src/astconv/mod.rs | 256 +- compiler/rustc_typeck/src/bounds.rs | 4 +- compiler/rustc_typeck/src/check/callee.rs | 3 +- compiler/rustc_typeck/src/check/cast.rs | 15 + compiler/rustc_typeck/src/check/check.rs | 38 +- compiler/rustc_typeck/src/check/closure.rs | 60 +- compiler/rustc_typeck/src/check/coercion.rs | 39 +- .../rustc_typeck/src/check/compare_method.rs | 185 +- compiler/rustc_typeck/src/check/demand.rs | 57 + compiler/rustc_typeck/src/check/dropck.rs | 6 +- .../rustc_typeck/src/check/expectation.rs | 4 +- compiler/rustc_typeck/src/check/expr.rs | 84 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 25 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 3 +- .../src/check/fn_ctxt/suggestions.rs | 59 +- .../rustc_typeck/src/check/gather_locals.rs | 13 +- .../src/check/generator_interior.rs | 13 +- compiler/rustc_typeck/src/check/intrinsic.rs | 29 +- .../rustc_typeck/src/check/method/confirm.rs | 14 +- compiler/rustc_typeck/src/check/method/mod.rs | 6 +- .../rustc_typeck/src/check/method/probe.rs | 30 +- .../rustc_typeck/src/check/method/suggest.rs | 111 +- compiler/rustc_typeck/src/check/mod.rs | 21 +- compiler/rustc_typeck/src/check/pat.rs | 2 +- compiler/rustc_typeck/src/check/upvar.rs | 132 +- compiler/rustc_typeck/src/check/wfcheck.rs | 94 +- compiler/rustc_typeck/src/check/writeback.rs | 4 +- .../src/coherence/inherent_impls_overlap.rs | 4 +- compiler/rustc_typeck/src/collect.rs | 153 +- compiler/rustc_typeck/src/collect/type_of.rs | 45 +- compiler/rustc_typeck/src/expr_use_visitor.rs | 30 +- compiler/rustc_typeck/src/impl_wf_check.rs | 2 +- compiler/rustc_typeck/src/lib.rs | 290 +- compiler/rustc_typeck/src/variance/solve.rs | 2 +- config.toml.example | 149 +- git-commit-hash | 2 +- library/alloc/Cargo.toml | 3 + library/alloc/benches/vec.rs | 110 +- library/alloc/src/boxed.rs | 2 +- library/alloc/src/collections/binary_heap.rs | 106 +- library/alloc/src/collections/btree/map.rs | 3 +- .../alloc/src/collections/btree/map/tests.rs | 2 - .../alloc/src/collections/btree/navigate.rs | 15 +- library/alloc/src/collections/btree/node.rs | 340 +- library/alloc/src/collections/btree/search.rs | 53 +- library/alloc/src/collections/btree/set.rs | 3 +- .../src/collections/vec_deque/into_iter.rs | 5 +- .../alloc/src/collections/vec_deque/iter.rs | 24 +- .../src/collections/vec_deque/iter_mut.rs | 24 +- .../alloc/src/collections/vec_deque/mod.rs | 74 +- library/alloc/src/fmt.rs | 11 +- library/alloc/src/lib.rs | 12 +- library/alloc/src/raw_vec.rs | 32 +- library/alloc/src/rc.rs | 78 +- library/alloc/src/slice.rs | 5 +- library/alloc/src/str.rs | 2 + library/alloc/src/string.rs | 39 +- library/alloc/src/sync.rs | 7 +- library/alloc/src/task.rs | 6 + library/alloc/src/tests.rs | 8 +- library/alloc/src/vec/mod.rs | 97 +- library/alloc/src/vec/source_iter_marker.rs | 69 +- library/alloc/src/vec/spec_extend.rs | 13 +- .../alloc/src/vec/spec_from_iter_nested.rs | 9 +- library/alloc/tests/binary_heap.rs | 19 +- library/alloc/tests/fmt.rs | 8 +- library/alloc/tests/lib.rs | 3 +- library/alloc/tests/vec.rs | 28 +- library/alloc/tests/vec_deque.rs | 18 + library/backtrace/.github/workflows/main.yml | 92 +- library/backtrace/Cargo.toml | 8 +- library/backtrace/README.md | 4 +- library/backtrace/crates/as-if-std/Cargo.toml | 2 +- .../backtrace/crates/backtrace-sys/Cargo.toml | 6 +- .../crates/macos_frames_test/tests/main.rs | 2 +- library/backtrace/src/lib.rs | 47 + library/backtrace/src/symbolize/gimli.rs | 362 +- .../symbolize/gimli/libs_dl_iterate_phdr.rs | 53 + .../src/symbolize/gimli/libs_haiku.rs | 47 + .../src/symbolize/gimli/libs_illumos.rs | 99 + .../src/symbolize/gimli/libs_libnx.rs | 27 + .../src/symbolize/gimli/libs_macos.rs | 146 + .../src/symbolize/gimli/libs_windows.rs | 89 + .../src/symbolize/gimli/mmap_unix.rs | 3 +- .../src/symbolize/gimli/mmap_windows.rs | 3 +- library/core/Cargo.toml | 6 + library/core/benches/fmt.rs | 8 +- library/core/benches/slice.rs | 13 + library/core/src/alloc/layout.rs | 2 +- library/core/src/any.rs | 6 +- library/core/src/array/iter.rs | 4 +- library/core/src/array/mod.rs | 62 +- library/core/src/ascii.rs | 2 +- library/core/src/cell.rs | 100 +- library/core/src/char/methods.rs | 35 +- library/core/src/char/mod.rs | 2 + library/core/src/cmp.rs | 49 +- library/core/src/convert/num.rs | 16 +- library/core/src/ffi.rs | 2 +- library/core/src/fmt/builders.rs | 30 +- library/core/src/fmt/float.rs | 19 +- library/core/src/fmt/mod.rs | 24 +- library/core/src/future/future.rs | 3 +- library/core/src/hash/mod.rs | 81 +- library/core/src/hint.rs | 2 +- library/core/src/intrinsics.rs | 4 +- library/core/src/iter/adapters/mod.rs | 26 + library/core/src/iter/adapters/peekable.rs | 8 +- library/core/src/iter/adapters/zip.rs | 35 +- library/core/src/iter/mod.rs | 2 + library/core/src/iter/range.rs | 43 +- library/core/src/iter/sources/empty.rs | 2 +- library/core/src/iter/traits/collect.rs | 1 + library/core/src/iter/traits/iterator.rs | 105 +- library/core/src/lib.rs | 19 +- library/core/src/macros/mod.rs | 2 - library/core/src/marker.rs | 2 +- library/core/src/mem/maybe_uninit.rs | 20 +- library/core/src/mem/mod.rs | 5 +- library/core/src/num/bignum.rs | 6 +- library/core/src/num/dec2flt/algorithm.rs | 10 +- library/core/src/num/dec2flt/mod.rs | 12 +- library/core/src/num/f32.rs | 3 +- library/core/src/num/f64.rs | 3 +- library/core/src/num/flt2dec/mod.rs | 32 +- library/core/src/num/int_macros.rs | 67 +- library/core/src/num/mod.rs | 26 + library/core/src/num/nonzero.rs | 38 +- library/core/src/num/uint_macros.rs | 87 +- library/core/src/ops/arith.rs | 26 +- library/core/src/ops/control_flow.rs | 32 +- library/core/src/ops/deref.rs | 2 +- library/core/src/ops/drop.rs | 2 +- library/core/src/ops/index.rs | 8 + library/core/src/ops/mod.rs | 7 + library/core/src/ops/try_trait.rs | 243 + library/core/src/option.rs | 199 +- library/core/src/pin.rs | 217 +- library/core/src/prelude/v1.rs | 2 - library/core/src/ptr/const_ptr.rs | 64 +- library/core/src/ptr/mod.rs | 131 +- library/core/src/ptr/mut_ptr.rs | 66 +- library/core/src/ptr/non_null.rs | 20 +- library/core/src/raw.rs | 4 + library/core/src/result.rs | 77 +- library/core/src/slice/ascii.rs | 95 +- library/core/src/slice/index.rs | 112 + library/core/src/slice/iter.rs | 10 +- library/core/src/slice/mod.rs | 61 +- library/core/src/slice/specialize.rs | 49 +- library/core/src/str/iter.rs | 26 +- library/core/src/str/mod.rs | 16 +- library/core/src/sync/atomic.rs | 35 +- library/core/src/task/poll.rs | 66 +- library/core/src/time.rs | 27 +- library/core/tests/array.rs | 20 +- library/core/tests/const_ptr.rs | 50 - library/core/tests/fmt/builders.rs | 7 +- library/core/tests/iter/adapters/chain.rs | 12 +- library/core/tests/lib.rs | 15 +- library/core/tests/mem.rs | 3 + library/core/tests/num/flt2dec/mod.rs | 246 +- library/core/tests/num/ieee754.rs | 158 + library/core/tests/num/mod.rs | 1 + library/core/tests/ptr.rs | 7 - library/core/tests/result.rs | 22 + library/core/tests/slice.rs | 43 + library/panic_abort/Cargo.toml | 4 + library/panic_abort/src/android.rs | 49 + library/panic_abort/src/lib.rs | 7 + library/panic_unwind/Cargo.toml | 3 + library/panic_unwind/src/lib.rs | 1 - library/proc_macro/src/lib.rs | 3 +- library/profiler_builtins/build.rs | 4 +- library/std/Cargo.toml | 7 +- library/std/src/collections/hash/map.rs | 19 +- library/std/src/collections/hash/set.rs | 2 +- library/std/src/env.rs | 47 +- library/std/src/error.rs | 23 +- library/std/src/ffi/c_str.rs | 8 +- library/std/src/ffi/c_str/tests.rs | 16 + library/std/src/ffi/os_str.rs | 36 +- library/std/src/fs.rs | 16 +- library/std/src/fs/tests.rs | 4 +- library/std/src/io/buffered/bufreader.rs | 2 +- library/std/src/io/buffered/bufwriter.rs | 4 +- library/std/src/io/buffered/linewriter.rs | 2 +- library/std/src/io/cursor.rs | 8 +- library/std/src/io/error.rs | 41 + library/std/src/io/error/tests.rs | 16 + library/std/src/io/impls.rs | 4 +- library/std/src/io/mod.rs | 34 +- library/std/src/io/stdio.rs | 53 +- library/std/src/io/tests.rs | 4 +- library/std/src/io/util.rs | 6 +- library/std/src/keyword_docs.rs | 26 +- library/std/src/lazy.rs | 2 +- library/std/src/lib.rs | 42 +- library/std/src/net/addr.rs | 40 +- library/std/src/net/ip.rs | 8 + library/std/src/net/mod.rs | 2 +- library/std/src/net/parser.rs | 14 +- library/std/src/net/parser/tests.rs | 8 + library/std/src/net/udp.rs | 2 +- library/std/src/path.rs | 28 +- library/std/src/prelude/mod.rs | 64 +- library/std/src/prelude/v1.rs | 2 - library/std/src/primitive_docs.rs | 128 +- library/std/src/process.rs | 12 +- library/std/src/rt.rs | 27 +- library/std/src/sync/barrier.rs | 2 +- library/std/src/sync/condvar.rs | 5 +- library/std/src/sync/mod.rs | 5 +- library/std/src/sync/mpsc/mod.rs | 8 +- library/std/src/sync/mutex.rs | 35 +- library/std/src/sync/once.rs | 4 +- .../std/src/{sys_common => sync}/poison.rs | 18 +- library/std/src/sync/rwlock.rs | 18 +- .../src/{sys_common => sys/common}/alloc.rs | 2 - library/std/src/sys/common/mod.rs | 13 + library/std/src/sys/hermit/args.rs | 15 +- library/std/src/sys/hermit/cmath.rs | 29 - library/std/src/sys/hermit/fd.rs | 9 +- library/std/src/sys/hermit/fs.rs | 74 +- library/std/src/sys/hermit/io.rs | 47 - library/std/src/sys/hermit/mod.rs | 27 +- library/std/src/sys/hermit/net.rs | 148 +- library/std/src/sys/hermit/os.rs | 12 +- library/std/src/sys/hermit/path.rs | 19 - library/std/src/sys/hermit/stack_overflow.rs | 5 - library/std/src/sys/hermit/stdio.rs | 8 +- library/std/src/sys/hermit/thread.rs | 2 +- .../std/src/sys/hermit/thread_local_key.rs | 26 - library/std/src/sys/mod.rs | 9 +- library/std/src/sys/sgx/abi/mem.rs | 5 +- library/std/src/sys/sgx/abi/mod.rs | 6 +- library/std/src/sys/sgx/args.rs | 9 +- library/std/src/sys/sgx/cmath.rs | 31 - library/std/src/sys/sgx/ext/arch.rs | 6 +- library/std/src/sys/sgx/ext/io.rs | 6 + library/std/src/sys/sgx/mod.rs | 26 +- library/std/src/sys/sgx/net.rs | 84 +- library/std/src/sys/sgx/os.rs | 7 +- library/std/src/sys/sgx/stack_overflow.rs | 4 - library/std/src/sys/sgx/thread.rs | 69 +- library/std/src/sys/unix/alloc.rs | 2 +- library/std/src/sys/unix/android.rs | 6 +- library/std/src/sys/unix/args.rs | 20 +- library/std/src/sys/unix/cmath.rs | 55 +- library/std/src/sys/unix/env.rs | 11 + library/std/src/sys/unix/ext/fs.rs | 34 +- library/std/src/sys/unix/ext/io.rs | 12 + library/std/src/sys/unix/ext/mod.rs | 38 + library/std/src/sys/unix/ext/net/addr.rs | 16 +- library/std/src/sys/unix/ext/net/ancillary.rs | 57 +- library/std/src/sys/unix/ext/net/datagram.rs | 3 + library/std/src/sys/unix/ext/net/listener.rs | 3 + library/std/src/sys/unix/ext/net/raw_fd.rs | 3 + library/std/src/sys/unix/ext/net/stream.rs | 3 + library/std/src/sys/unix/ext/process.rs | 11 +- library/std/src/sys/unix/ext/raw.rs | 6 +- library/std/src/sys/unix/fs.rs | 25 +- library/std/src/sys/unix/l4re.rs | 5 +- library/std/src/sys/unix/mod.rs | 95 +- library/std/src/sys/unix/net.rs | 15 +- library/std/src/sys/unix/os.rs | 40 +- library/std/src/sys/unix/process/mod.rs | 22 +- .../src/sys/unix/process/process_fuchsia.rs | 17 +- .../std/src/sys/unix/process/process_unix.rs | 76 +- .../sys/unix/process/process_unix/tests.rs | 4 +- .../process/process_vxworks.rs | 33 +- library/std/src/sys/unix/rand.rs | 29 +- library/std/src/sys/unix/rwlock.rs | 52 + library/std/src/sys/unix/thread.rs | 23 +- library/std/src/sys/unix/thread_local_dtor.rs | 6 + library/std/src/sys/unsupported/args.rs | 9 +- library/std/src/sys/unsupported/cmath.rs | 29 - library/std/src/sys/unsupported/common.rs | 19 +- library/std/src/sys/unsupported/fs.rs | 94 +- library/std/src/sys/unsupported/mod.rs | 2 +- library/std/src/sys/unsupported/net.rs | 140 +- library/std/src/sys/unsupported/os.rs | 15 +- library/std/src/sys/unsupported/pipe.rs | 17 +- library/std/src/sys/unsupported/process.rs | 26 +- .../std/src/sys/unsupported/stack_overflow.rs | 3 - library/std/src/sys/unsupported/thread.rs | 6 +- library/std/src/sys/vxworks/env.rs | 9 - library/std/src/sys/vxworks/mod.rs | 137 - library/std/src/sys/vxworks/process/mod.rs | 9 - library/std/src/sys/vxworks/rand.rs | 36 - .../std/src/sys/vxworks/thread_local_dtor.rs | 7 - library/std/src/sys/wasi/args.rs | 21 +- library/std/src/sys/wasi/ext/fs.rs | 8 +- library/std/src/sys/wasi/ext/io.rs | 21 + library/std/src/sys/wasi/fs.rs | 4 +- library/std/src/sys/wasi/mod.rs | 5 +- library/std/src/sys/wasi/net.rs | 8 +- library/std/src/sys/wasi/os.rs | 12 +- library/std/src/sys/wasi/thread.rs | 6 +- library/std/src/sys/wasm/args.rs | 20 +- library/std/src/sys/wasm/mod.rs | 4 +- library/std/src/sys/wasm/thread.rs | 6 +- library/std/src/sys/windows/alloc.rs | 239 +- library/std/src/sys/windows/alloc/tests.rs | 9 + library/std/src/sys/windows/args.rs | 18 +- library/std/src/sys/windows/c.rs | 7 - library/std/src/sys/windows/ext/io.rs | 12 + library/std/src/sys/windows/ext/process.rs | 4 + library/std/src/sys/windows/ext/thread.rs | 2 + library/std/src/sys/windows/fs.rs | 9 +- library/std/src/sys/windows/mod.rs | 18 +- library/std/src/sys/windows/net.rs | 31 +- library/std/src/sys/windows/process.rs | 30 +- library/std/src/sys/windows/stack_overflow.rs | 2 - .../std/src/sys/windows/stack_overflow_uwp.rs | 2 - library/std/src/sys/windows/stdio.rs | 12 +- library/std/src/sys_common/at_exit_imp.rs | 74 - library/std/src/sys_common/fs.rs | 10 +- library/std/src/sys_common/mod.rs | 65 +- library/std/src/sys_common/net.rs | 4 +- library/std/src/sys_common/os_str_bytes.rs | 14 +- library/std/src/sys_common/rt.rs | 64 + library/std/src/sys_common/rwlock.rs | 59 - .../std/src/thread/available_concurrency.rs | 10 +- library/std/src/thread/local.rs | 125 +- library/std/src/thread/local/tests.rs | 253 +- library/std/src/thread/mod.rs | 14 +- library/stdarch/.github/workflows/main.yml | 17 +- .../docker/i586-unknown-linux-gnu/Dockerfile | 2 +- .../docker/i686-unknown-linux-gnu/Dockerfile | 2 +- .../stdarch/ci/docker/wasm32-wasi/Dockerfile | 4 +- .../Dockerfile | 3 +- .../x86_64-unknown-linux-gnu/Dockerfile | 2 +- library/stdarch/ci/run.sh | 3 + .../crates/assert-instr-macro/src/lib.rs | 3 +- library/stdarch/crates/core_arch/avx512bw.md | 250 +- library/stdarch/crates/core_arch/avx512f.md | 4043 ++- .../stdarch/crates/core_arch/avx512vbmi2.md | 153 + library/stdarch/crates/core_arch/src/lib.rs | 12 +- library/stdarch/crates/core_arch/src/mod.rs | 2 +- library/stdarch/crates/core_arch/src/simd.rs | 1 + .../stdarch/crates/core_arch/src/x86/avx2.rs | 7 +- .../crates/core_arch/src/x86/avx512bf16.rs | 1573 + .../crates/core_arch/src/x86/avx512bw.rs | 6109 +++- .../crates/core_arch/src/x86/avx512f.rs | 30287 +++++++++++++--- .../crates/core_arch/src/x86/avx512vbmi.rs | 916 + .../crates/core_arch/src/x86/avx512vbmi2.rs | 3477 ++ .../crates/core_arch/src/x86/avx512vnni.rs | 939 + .../core_arch/src/x86/avx512vpclmulqdq.rs | 2 +- .../stdarch/crates/core_arch/src/x86/cpuid.rs | 33 +- .../stdarch/crates/core_arch/src/x86/fxsr.rs | 2 +- .../stdarch/crates/core_arch/src/x86/mod.rs | 168 +- .../crates/core_arch/src/x86/pclmulqdq.rs | 2 +- .../stdarch/crates/core_arch/src/x86/sse.rs | 5 +- .../stdarch/crates/core_arch/src/x86/sse2.rs | 2 +- .../stdarch/crates/core_arch/src/x86/test.rs | 4 +- .../stdarch/crates/core_arch/src/x86/xsave.rs | 2 +- .../crates/core_arch/src/x86_64/avx512f.rs | 7759 +++- .../crates/core_arch/src/x86_64/fxsr.rs | 2 +- .../crates/core_arch/src/x86_64/macros.rs | 32 + .../crates/core_arch/src/x86_64/mod.rs | 3 + .../crates/core_arch/src/x86_64/xsave.rs | 2 +- .../stdarch/crates/simd-test-macro/src/lib.rs | 1 + library/stdarch/crates/std_detect/Cargo.toml | 14 +- .../crates/std_detect/src/detect/arch/x86.rs | 2 +- .../crates/std_detect/src/detect/cache.rs | 17 +- .../crates/std_detect/src/detect/mod.rs | 6 +- .../src/detect/os/freebsd/auxvec.rs | 2 +- .../std_detect/src/detect/os/freebsd/mod.rs | 12 +- .../std_detect/src/detect/os/linux/aarch64.rs | 10 +- .../std_detect/src/detect/os/linux/arm.rs | 8 +- .../std_detect/src/detect/os/linux/auxvec.rs | 100 +- .../std_detect/src/detect/os/linux/cpuinfo.rs | 17 +- .../std_detect/src/detect/os/linux/mod.rs | 49 +- .../std_detect/src/detect/os/linux/powerpc.rs | 5 +- .../crates/std_detect/src/detect/os/x86.rs | 6 +- library/stdarch/crates/std_detect/src/lib.rs | 28 +- library/stdarch/crates/std_detect/src/mod.rs | 5 - .../crates/std_detect/tests/x86-specific.rs | 2 +- .../stdarch/crates/stdarch-test/src/lib.rs | 3 +- .../stdarch/crates/stdarch-verify/src/lib.rs | 10 +- .../crates/stdarch-verify/tests/x86-intel.rs | 31 + library/stdarch/examples/Cargo.toml | 5 + library/stdarch/examples/connect5.rs | 1272 + library/test/src/bench.rs | 28 +- library/test/src/event.rs | 6 +- library/test/src/helpers/exit_code.rs | 2 +- library/test/src/lib.rs | 62 +- library/test/src/tests.rs | 30 +- library/test/src/types.rs | 6 +- library/unwind/Cargo.toml | 2 + src/bootstrap/CHANGELOG.md | 1 + src/bootstrap/bootstrap.py | 248 +- src/bootstrap/builder.rs | 25 +- src/bootstrap/check.rs | 14 +- src/bootstrap/compile.rs | 28 +- src/bootstrap/config.rs | 155 +- src/bootstrap/configure.py | 7 +- src/bootstrap/defaults/config.codegen.toml | 2 + src/bootstrap/defaults/config.compiler.toml | 5 +- src/bootstrap/defaults/config.tools.toml | 16 + src/bootstrap/dist.rs | 98 +- src/bootstrap/doc.rs | 18 +- src/bootstrap/install.rs | 23 +- src/bootstrap/lib.rs | 2 +- src/bootstrap/native.rs | 77 +- src/bootstrap/setup.rs | 20 +- src/bootstrap/tarball.rs | 22 + src/bootstrap/test.rs | 104 +- src/bootstrap/tool.rs | 22 +- .../disabled/riscv64gc-linux/Dockerfile | 2 +- .../host-x86_64/dist-various-1/Dockerfile | 6 +- .../host-x86_64/dist-various-2/Dockerfile | 10 +- .../dist-various-2/build-solaris-toolchain.sh | 14 +- .../host-x86_64/dist-x86_64-musl/Dockerfile | 1 + .../host-x86_64/test-various/Dockerfile | 4 +- .../Dockerfile | 9 +- src/ci/github-actions/ci.yml | 4 +- src/ci/pgo.sh | 2 +- src/ci/scripts/install-clang.sh | 23 +- src/doc/book/COPYRIGHT | 8 +- src/doc/book/README.md | 9 +- .../listing-15-10/src/main.rs | 2 +- src/doc/book/src/ch01-03-hello-cargo.md | 2 +- .../src/ch02-00-guessing-game-tutorial.md | 5 +- src/doc/book/src/ch04-03-slices.md | 2 + ...04-extensible-concurrency-sync-and-send.md | 6 +- src/doc/embedded-book/src/intro/install.md | 20 +- .../embedded-book/src/intro/install/macos.md | 2 +- .../embedded-book/src/intro/install/verify.md | 6 +- .../src/intro/install/windows.md | 4 +- src/doc/embedded-book/src/start/exceptions.md | 8 +- src/doc/embedded-book/src/start/hardware.md | 26 +- src/doc/embedded-book/src/start/panicking.md | 2 +- src/doc/embedded-book/src/start/qemu.md | 2 +- .../embedded-book/src/start/semihosting.md | 8 +- .../src/unsorted/speed-vs-size.md | 4 +- src/doc/nomicon/src/send-and-sync.md | 177 + src/doc/reference/STYLE.md | 55 +- .../reference/src/attributes/diagnostics.md | 55 +- src/doc/reference/src/attributes/limits.md | 4 +- .../src/behavior-considered-undefined.md | 23 +- src/doc/reference/src/const_eval.md | 6 +- src/doc/reference/src/expressions.md | 5 +- .../reference/src/expressions/array-expr.md | 28 +- .../reference/src/expressions/await-expr.md | 36 +- .../reference/src/expressions/block-expr.md | 75 +- .../reference/src/expressions/call-expr.md | 22 +- .../reference/src/expressions/closure-expr.md | 42 +- .../reference/src/expressions/field-expr.md | 49 +- .../reference/src/expressions/grouped-expr.md | 11 +- src/doc/reference/src/expressions/if-expr.md | 4 +- .../reference/src/expressions/loop-expr.md | 3 +- .../reference/src/expressions/match-expr.md | 5 +- .../src/expressions/operator-expr.md | 14 +- .../reference/src/expressions/tuple-expr.md | 43 +- src/doc/reference/src/identifiers.md | 18 +- src/doc/reference/src/introduction.md | 2 +- src/doc/reference/src/items/functions.md | 4 +- src/doc/reference/src/items/traits.md | 35 +- src/doc/reference/src/items/type-aliases.md | 2 +- src/doc/reference/src/keywords.md | 1 + src/doc/reference/src/linkage.md | 15 +- src/doc/reference/src/macros-by-example.md | 8 +- src/doc/reference/src/patterns.md | 61 + src/doc/reference/src/statements.md | 4 +- src/doc/reference/src/types/pointer.md | 55 +- src/doc/reference/src/types/tuple.md | 41 +- .../custom_types/enum/testcase_linked_list.md | 3 + .../src/custom_types/structs.md | 5 +- .../src/error/option_unwrap.md | 48 +- src/doc/rust-by-example/src/expression.md | 4 +- .../src/generics/multi_bounds.md | 2 +- .../rust-by-example/src/generics/new_types.md | 5 +- .../src/hello/print/print_display.md | 4 +- .../rust-by-example/src/primitives/tuples.md | 2 +- .../src/scope/lifetime/static_lifetime.md | 2 +- .../src/scope/lifetime/trait.md | 6 +- .../src/scope/move/partial_move.md | 15 +- .../src/std/result/question_mark.md | 2 +- src/doc/rust-by-example/src/trait/iter.md | 5 +- src/doc/rust-by-example/src/types/cast.md | 13 +- .../rustc-dev-guide/.github/workflows/ci.yml | 3 +- .../.github/workflows/date-check.yml | 1 + src/doc/rustc-dev-guide/README.md | 2 +- src/doc/rustc-dev-guide/ci/linkcheck.sh | 2 +- .../examples/rustc-driver-example.rs | 8 +- .../rustc-driver-getting-diagnostics.rs | 5 +- .../rustc-driver-interacting-with-the-ast.rs | 11 +- .../src/appendix/bibliography.md | 1 + .../src/backend/updating-llvm.md | 20 +- .../src/building/how-to-build-and-run.md | 22 +- .../rustc-dev-guide/src/building/suggested.md | 75 +- src/doc/rustc-dev-guide/src/compiler-team.md | 42 +- src/doc/rustc-dev-guide/src/generics.md | 2 +- src/doc/rustc-dev-guide/src/git.md | 60 + src/doc/rustc-dev-guide/src/method-lookup.md | 37 +- src/doc/rustc-dev-guide/src/mir/debugging.md | 5 + src/doc/rustc-dev-guide/src/mir/mir_cfg.svg | 270 + .../rustc-dev-guide/src/mir/optimizations.md | 49 + .../src/rustc-driver-getting-diagnostics.md | 11 +- .../rustc-driver-interacting-with-the-ast.md | 13 +- src/doc/rustc-dev-guide/src/rustdoc.md | 9 +- src/doc/rustc-dev-guide/src/tests/adding.md | 22 +- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/codegen-options/index.md | 10 +- src/doc/rustc/src/platform-support.md | 8 +- src/doc/rustc/src/target-tier-policy.md | 639 + src/doc/rustc/src/targets/built-in.md | 2 +- src/doc/rustdoc/src/lints.md | 23 +- src/doc/rustdoc/src/unstable-features.md | 42 +- .../language-features/doc-notable-trait.md | 33 + .../src/language-features/doc-spotlight.md | 30 - .../src/language-features/lang-items.md | 2 +- .../src/language-features/link-args.md | 32 - .../src/language-features/non-ascii-idents.md | 48 - .../src/language-features/or-patterns.md | 36 - .../unstable-book/src/library-features/asm.md | 82 +- src/etc/lldb_providers.py | 14 +- src/librustdoc/Cargo.toml | 8 +- src/librustdoc/clean/auto_trait.rs | 3 +- src/librustdoc/clean/blanket_impl.rs | 19 +- src/librustdoc/clean/cfg.rs | 2 +- src/librustdoc/clean/inline.rs | 111 +- src/librustdoc/clean/mod.rs | 193 +- src/librustdoc/clean/types.rs | 634 +- src/librustdoc/clean/utils.rs | 90 +- src/librustdoc/config.rs | 84 +- src/librustdoc/core.rs | 81 +- src/librustdoc/doctest.rs | 122 +- src/librustdoc/doctree.rs | 6 +- src/librustdoc/fold.rs | 4 +- src/librustdoc/formats/cache.rs | 39 +- src/librustdoc/formats/item_type.rs | 58 +- src/librustdoc/formats/renderer.rs | 57 +- src/librustdoc/html/format.rs | 921 +- src/librustdoc/html/highlight.rs | 133 +- .../html/highlight/fixtures/dos_line.html | 2 +- .../html/highlight/fixtures/sample.html | 16 +- .../html/highlight/fixtures/sample.rs | 10 + src/librustdoc/html/layout.rs | 7 +- src/librustdoc/html/markdown.rs | 36 +- src/librustdoc/html/mod.rs | 3 + src/librustdoc/html/render/cache.rs | 57 +- src/librustdoc/html/render/context.rs | 228 +- src/librustdoc/html/render/mod.rs | 751 +- src/librustdoc/html/render/print_item.rs | 308 +- src/librustdoc/html/render/write_shared.rs | 378 +- src/librustdoc/html/sources.rs | 16 +- src/librustdoc/html/static/COPYRIGHT.txt | 15 +- .../html/static/SourceCodePro-It.ttf.woff | Bin 0 -> 58444 bytes .../static/SourceCodePro-Regular.ttf.woff | Bin 0 -> 68152 bytes .../html/static/SourceCodePro-Regular.woff | Bin 55472 -> 0 bytes .../static/SourceCodePro-Semibold.ttf.woff | Bin 0 -> 68080 bytes .../html/static/SourceCodePro-Semibold.woff | Bin 55360 -> 0 bytes .../html/static/SourceSerif4-Bold.ttf.woff | Bin 0 -> 110552 bytes .../html/static/SourceSerif4-It.ttf.woff | Bin 0 -> 78108 bytes ...Pro-LICENSE.md => SourceSerif4-LICENSE.md} | 2 +- .../html/static/SourceSerif4-Regular.ttf.woff | Bin 0 -> 103604 bytes .../html/static/SourceSerifPro-Bold.ttf.woff | Bin 93248 -> 0 bytes .../html/static/SourceSerifPro-It.ttf.woff | Bin 36200 -> 0 bytes .../static/SourceSerifPro-Regular.ttf.woff | Bin 88596 -> 0 bytes src/librustdoc/html/static/main.js | 2268 +- src/librustdoc/html/static/noscript.css | 5 + src/librustdoc/html/static/rustdoc.css | 206 +- src/librustdoc/html/static/search.js | 1515 + src/librustdoc/html/static/sidebar-items.js | 1 + src/librustdoc/html/static/storage.js | 19 +- src/librustdoc/html/static/themes/ayu.css | 15 +- src/librustdoc/html/static/themes/dark.css | 19 +- src/librustdoc/html/static/themes/light.css | 19 +- src/librustdoc/html/static_files.rs | 39 +- src/librustdoc/html/tests.rs | 44 + src/librustdoc/json/conversions.rs | 377 +- src/librustdoc/json/mod.rs | 49 +- src/librustdoc/lib.rs | 111 +- src/librustdoc/lint.rs | 15 +- src/librustdoc/passes/bare_urls.rs | 111 + .../passes/calculate_doc_coverage.rs | 48 +- .../passes/check_code_block_syntax.rs | 6 +- .../passes/collect_intra_doc_links.rs | 746 +- .../passes/collect_intra_doc_links/early.rs | 63 + src/librustdoc/passes/collect_trait_impls.rs | 11 +- src/librustdoc/passes/doc_test_lints.rs | 6 +- src/librustdoc/passes/html_tags.rs | 4 +- src/librustdoc/passes/mod.rs | 11 +- src/librustdoc/passes/non_autolinks.rs | 134 - src/librustdoc/passes/propagate_doc_cfg.rs | 4 +- src/librustdoc/passes/strip_hidden.rs | 4 +- src/librustdoc/visit_ast.rs | 28 +- src/rustdoc-json-types/lib.rs | 4 +- src/stage0.txt | 6 +- src/test/assembly/asm/aarch64-modifiers.rs | 2 +- src/test/assembly/asm/aarch64-types.rs | 2 +- src/test/assembly/asm/arm-modifiers.rs | 2 +- src/test/assembly/asm/arm-types.rs | 2 +- src/test/assembly/asm/hexagon-types.rs | 2 +- src/test/assembly/asm/mips-types.rs | 2 +- src/test/assembly/asm/nvptx-types.rs | 2 +- src/test/assembly/asm/riscv-types.rs | 2 +- src/test/assembly/asm/wasm-types.rs | 2 +- src/test/assembly/asm/x86-modifiers.rs | 2 +- src/test/assembly/asm/x86-types.rs | 11 +- .../assembly/panic-no-unwind-no-uwtable.rs | 8 + src/test/assembly/panic-unwind-no-uwtable.rs | 12 + src/test/assembly/static-relocation-model.rs | 44 + .../drop_in_place_intrinsic.rs | 2 +- .../item-collection/function-as-argument.rs | 2 +- .../item-collection/generic-drop-glue.rs | 2 +- .../instantiation-through-vtable.rs | 2 +- .../item-collection/non-generic-closures.rs | 2 +- .../item-collection/non-generic-drop-glue.rs | 2 +- .../trait-method-as-argument.rs | 2 +- .../item-collection/transitive-drop-glue.rs | 2 +- .../item-collection/tuple-drop-glue.rs | 2 +- .../partitioning/extern-drop-glue.rs | 2 +- .../partitioning/extern-generic.rs | 2 +- .../inlining-from-extern-crate.rs | 2 +- .../partitioning/local-drop-glue.rs | 2 +- .../local-inlining-but-not-all.rs | 2 +- .../partitioning/local-inlining.rs | 2 +- .../partitioning/local-transitive-inlining.rs | 2 +- .../methods-are-with-self-type.rs | 2 +- .../partitioning/shared-generics.rs | 2 +- .../partitioning/vtable-through-const.rs | 2 +- src/test/codegen/abi-efiapi.rs | 6 +- src/test/codegen/abi-repr-ext.rs | 2 +- src/test/codegen/abi-sysv64.rs | 18 +- src/test/codegen/abi-x86-interrupt.rs | 17 +- src/test/codegen/align-enum.rs | 2 +- src/test/codegen/align-struct.rs | 2 +- src/test/codegen/alloc-optimisation.rs | 2 +- src/test/codegen/asm-target-clobbers.rs | 21 + src/test/codegen/async-fn-debug-msvc.rs | 2 +- src/test/codegen/async-fn-debug.rs | 2 +- .../binary-search-index-no-bound-check.rs | 19 + src/test/codegen/c-variadic.rs | 2 +- .../codegen/cdylib-external-inline-fns.rs | 16 +- src/test/codegen/consts.rs | 2 +- src/test/codegen/dealloc-no-unwind.rs | 3 +- src/test/codegen/debug-compile-unit-path.rs | 2 +- src/test/codegen/default-requires-uwtable.rs | 15 + src/test/codegen/enum-debug-clike.rs | 2 +- src/test/codegen/enum-debug-niche-2.rs | 2 +- src/test/codegen/external-no-mangle-fns.rs | 24 +- src/test/codegen/fewer-names.rs | 4 +- src/test/codegen/ffi-const.rs | 2 +- src/test/codegen/ffi-pure.rs | 2 +- src/test/codegen/ffi-returns-twice.rs | 5 +- src/test/codegen/force-no-unwind-tables.rs | 11 + src/test/codegen/function-arguments.rs | 4 +- src/test/codegen/gdb_debug_script_load.rs | 2 +- src/test/codegen/generator-debug-msvc.rs | 2 +- src/test/codegen/generator-debug.rs | 2 +- src/test/codegen/inline-debuginfo.rs | 2 +- src/test/codegen/instrument-mcount.rs | 2 +- src/test/codegen/intrinsics/nontemporal.rs | 2 +- src/test/codegen/issue-32031.rs | 4 +- .../codegen/issue-44056-macos-tls-align.rs | 2 +- src/test/codegen/issue-73338-effecient-cmp.rs | 39 + .../codegen/issue-83623-SIMD-PartialEq.rs | 46 + src/test/codegen/issue-84268.rs | 23 + src/test/codegen/lto-removes-invokes.rs | 2 +- src/test/codegen/naked-functions.rs | 8 +- src/test/codegen/noalias-unpin.rs | 15 + src/test/codegen/optimize-attr-1.rs | 6 +- src/test/codegen/packed.rs | 4 +- .../codegen/panic-unwind-default-uwtable.rs | 6 + .../auxiliary/remap_path_prefix_aux.rs | 2 +- .../auxiliary/xcrate-generic.rs | 2 +- src/test/codegen/remap_path_prefix/main.rs | 2 +- src/test/codegen/repeat-trusted-len.rs | 2 +- .../codegen/repr-transparent-aggregates-1.rs | 18 +- .../codegen/repr-transparent-aggregates-2.rs | 2 +- .../codegen/repr-transparent-aggregates-3.rs | 2 +- src/test/codegen/repr-transparent.rs | 34 +- .../riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs | 2 +- .../codegen/riscv-abi/riscv64-lp64d-abi.rs | 2 +- .../riscv-abi/riscv64-lp64f-lp64d-abi.rs | 2 +- src/test/codegen/sanitizer-recover.rs | 10 +- src/test/codegen/scalar-pair-bool.rs | 10 +- .../simd-intrinsic-float-abs.rs | 14 +- .../simd-intrinsic-float-ceil.rs | 14 +- .../simd-intrinsic-float-cos.rs | 14 +- .../simd-intrinsic-float-exp.rs | 14 +- .../simd-intrinsic-float-exp2.rs | 14 +- .../simd-intrinsic-float-floor.rs | 14 +- .../simd-intrinsic-float-fma.rs | 14 +- .../simd-intrinsic-float-fsqrt.rs | 14 +- .../simd-intrinsic-float-log.rs | 14 +- .../simd-intrinsic-float-log10.rs | 14 +- .../simd-intrinsic-float-log2.rs | 14 +- .../simd-intrinsic-float-pow.rs | 14 +- .../simd-intrinsic-float-powi.rs | 14 +- .../simd-intrinsic-float-sin.rs | 14 +- ...intrinsic-generic-arithmetic-saturating.rs | 2 +- .../simd-intrinsic-generic-bitmask.rs | 2 +- .../simd-intrinsic-generic-gather.rs | 2 +- .../simd-intrinsic-generic-scatter.rs | 2 +- .../simd-intrinsic-transmute-array.rs | 3 +- .../codegen/staticlib-external-inline-fns.rs | 16 +- src/test/codegen/stores.rs | 2 +- src/test/codegen/target-cpu-on-functions.rs | 2 +- src/test/codegen/transmute-scalar.rs | 12 +- src/test/codegen/tune-cpu-on-functions.rs | 2 +- src/test/codegen/unwind-extern-imports.rs | 12 +- src/test/codegen/var-names.rs | 2 +- src/test/codegen/vec-in-place.rs | 14 + src/test/codegen/wasm_casts_nontrapping.rs | 162 - src/test/codegen/wasm_casts_trapping.rs | 23 +- src/test/debuginfo/borrowed-enum.rs | 2 - src/test/debuginfo/boxed-struct.rs | 2 - .../by-value-non-immediate-argument.rs | 1 - .../debuginfo/c-style-enum-in-composite.rs | 1 - src/test/debuginfo/c-style-enum.rs | 2 - .../destructured-for-loop-variable.rs | 2 - src/test/debuginfo/evec-in-struct.rs | 2 - src/test/debuginfo/extern-c-fn.rs | 13 +- .../debuginfo/function-arg-initialization.rs | 1 - .../debuginfo/gdb-pretty-struct-and-enums.rs | 1 - src/test/debuginfo/generator-objects.rs | 2 - .../generic-method-on-generic-struct.rs | 2 - .../debuginfo/generic-struct-style-enum.rs | 1 - src/test/debuginfo/generic-struct.rs | 2 - .../debuginfo/generic-tuple-style-enum.rs | 2 - src/test/debuginfo/issue-57822.rs | 1 - src/test/debuginfo/method-on-enum.rs | 1 - src/test/debuginfo/multi-byte-chars.rs | 2 - src/test/debuginfo/option-like-enum.rs | 1 - .../packed-struct-with-destructor.rs | 1 - src/test/debuginfo/packed-struct.rs | 1 - src/test/debuginfo/pretty-huge-vec.rs | 2 +- src/test/debuginfo/pretty-std-collections.rs | 1 - src/test/debuginfo/simd.rs | 1 - src/test/debuginfo/simple-struct.rs | 2 - src/test/debuginfo/struct-in-enum.rs | 1 - src/test/debuginfo/struct-in-struct.rs | 1 - src/test/debuginfo/struct-style-enum.rs | 2 - src/test/debuginfo/struct-with-destructor.rs | 2 - src/test/debuginfo/tuple-in-struct.rs | 2 - src/test/debuginfo/tuple-struct.rs | 2 - src/test/debuginfo/tuple-style-enum.rs | 2 - src/test/debuginfo/type-names.rs | 1 - .../var-captured-in-nested-closure.rs | 49 + .../var-captured-in-stack-closure.rs | 42 + src/test/debuginfo/vec-slices.rs | 2 - src/test/incremental/commandline-args.rs | 7 +- src/test/incremental/hashes/extern_mods.rs | 16 - .../incremental/hashes/function_interfaces.rs | 6 +- src/test/incremental/hashes/inherent_impls.rs | 6 +- src/test/incremental/ich_nested_items.rs | 1 + src/test/incremental/ich_resolve_results.rs | 1 + .../incremental/issue-80691-bad-eval-cache.rs | 184 + .../incremental/issue-84252-global-alloc.rs | 12 + .../auxiliary/invalid-span-helper-lib.rs | 11 + .../auxiliary/invalid-span-helper-mod.rs | 14 + .../auxiliary/respan.rs | 19 + .../invalid_span_main.rs | 24 + .../incremental/spans_significant_w_panic.rs | 2 +- ..._of_reborrow.SimplifyCfg-initial.after.mir | 28 +- ...row_and_cast.SimplifyCfg-initial.after.mir | 6 +- ...ignment.main.SimplifyCfg-initial.after.mir | 4 +- ..._allocation.main.ConstProp.after.32bit.mir | 2 +- ..._allocation.main.ConstProp.after.64bit.mir | 2 +- ...allocation2.main.ConstProp.after.32bit.mir | 2 +- ...allocation2.main.ConstProp.after.64bit.mir | 2 +- ...allocation3.main.ConstProp.after.32bit.mir | 2 +- ...allocation3.main.ConstProp.after.64bit.mir | 2 +- .../const_debuginfo.main.ConstDebugInfo.diff | 1 - ...motion_extern_static.BAR.PromoteTemps.diff | 4 +- ...motion_extern_static.FOO.PromoteTemps.diff | 4 +- .../const_prop/aggregate.main.ConstProp.diff | 2 +- .../array_index.main.ConstProp.32bit.diff | 2 +- .../array_index.main.ConstProp.64bit.diff | 2 +- .../bad_op_div_by_zero.main.ConstProp.diff | 2 +- .../bad_op_mod_by_zero.main.ConstProp.diff | 2 +- ...e_oob_for_slices.main.ConstProp.32bit.diff | 6 +- ...e_oob_for_slices.main.ConstProp.64bit.diff | 6 +- .../const_prop/boxes.main.ConstProp.diff | 2 +- .../const_prop/cast.main.ConstProp.diff | 2 +- .../checked_add.main.ConstProp.diff | 2 +- ..._prop_fails_gracefully.main.ConstProp.diff | 6 +- ...simplification.hello.PreCodegen.before.mir | 1 + .../discriminant.main.ConstProp.32bit.diff | 2 +- .../discriminant.main.ConstProp.64bit.diff | 2 +- .../const_prop/indirect.main.ConstProp.diff | 2 +- .../issue_66971.main.ConstProp.diff | 5 +- .../issue_67019.main.ConstProp.diff | 2 +- ...arge_array_index.main.ConstProp.32bit.diff | 2 +- ...arge_array_index.main.ConstProp.64bit.diff | 2 +- .../mutable_variable.main.ConstProp.diff | 2 +- ...ble_variable_aggregate.main.ConstProp.diff | 2 +- ...able_aggregate_mut_ref.main.ConstProp.diff | 2 +- ...aggregate_partial_read.main.ConstProp.diff | 2 +- ...table_variable_no_prop.main.ConstProp.diff | 4 +- ...variable_unprop_assign.main.ConstProp.diff | 2 +- ...es_into_variable.main.ConstProp.32bit.diff | 2 +- ...es_into_variable.main.ConstProp.64bit.diff | 2 +- .../read_immutable_static.main.ConstProp.diff | 2 +- .../const_prop/ref_deref.main.ConstProp.diff | 6 +- .../ref_deref.main.PromoteTemps.diff | 4 +- .../ref_deref_project.main.ConstProp.diff | 6 +- .../ref_deref_project.main.PromoteTemps.diff | 4 +- .../reify_fn_ptr.main.ConstProp.diff | 2 +- .../repeat.main.ConstProp.32bit.diff | 2 +- .../repeat.main.ConstProp.64bit.diff | 2 +- ...ar_literal_propagation.main.ConstProp.diff | 2 +- .../slice_len.main.ConstProp.32bit.diff | 6 +- .../slice_len.main.ConstProp.64bit.diff | 6 +- ...le_literal_propagation.main.ConstProp.diff | 2 +- .../const_prop_miscompile.bar.ConstProp.diff | 4 +- .../const_prop_miscompile.foo.ConstProp.diff | 2 +- .../branch.main.DestinationPropagation.diff | 2 +- ...gation_arg.bar.DestinationPropagation.diff | 2 +- ...gation_arg.baz.DestinationPropagation.diff | 2 +- ...gation_arg.foo.DestinationPropagation.diff | 2 +- .../cycle.main.DestinationPropagation.diff | 1 - .../union.main.DestinationPropagation.diff | 1 - .../mir-opt/early_otherwise_branch_68867.rs | 1 - ...h.before-SimplifyBranches-final.after.diff | 496 +- ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 322 +- src/test/mir-opt/exponential-or.rs | 2 - ....match_tuple.SimplifyCfg-initial.after.mir | 88 +- ...float_to_exponential_common.ConstProp.diff | 2 +- .../inline/inline_retag.bar.Inline.after.mir | 8 +- ...ine_scopes_parenting.main.Inline.after.mir | 1 - ...e_38669.main.SimplifyCfg-initial.after.mir | 2 +- .../mir-opt/issue_49232.main.mir_map.0.mir | 4 +- .../issue_72181.main.mir_map.0.32bit.mir | 2 +- .../issue_72181.main.mir_map.0.64bit.mir | 2 +- .../mir-opt/issue_72181_1.f.mir_map.0.mir | 2 +- .../mir-opt/issue_72181_1.main.mir_map.0.mir | 2 +- .../issue_73223.main.PreCodegen.32bit.diff | 4 +- .../issue_73223.main.PreCodegen.64bit.diff | 4 +- ..._73223.main.SimplifyArmIdentity.32bit.diff | 10 +- ..._73223.main.SimplifyArmIdentity.64bit.diff | 10 +- ...76432.test.SimplifyComparisonIntegral.diff | 2 +- src/test/mir-opt/issues/issue-75439.rs | 1 - ...e_75439.foo.MatchBranchSimplification.diff | 78 +- ....main.SimplifyCfg-promote-consts.after.mir | 2 +- ...trinsics.discriminant.LowerIntrinsics.diff | 12 +- ...fg-initial.after-ElaborateDrops.after.diff | 2 +- ...s.full_tested_match.PromoteTemps.after.mir | 6 +- ...full_tested_match2.PromoteTemps.before.mir | 2 +- ...h_false_edges.main.PromoteTemps.before.mir | 2 +- ...ch_test.main.SimplifyCfg-initial.after.mir | 6 +- ...s.foo.MatchBranchSimplification.32bit.diff | 2 +- ...s.foo.MatchBranchSimplification.64bit.diff | 2 +- ...nators.test.MultipleReturnTerminators.diff | 16 - ...egion_subtyping_basic.main.nll.0.32bit.mir | 6 +- ...egion_subtyping_basic.main.nll.0.64bit.mir | 6 +- ...receiver_ptr_mutability.main.mir_map.0.mir | 4 +- ...tch_guard.CleanupNonCodegenStatements.diff | 2 +- ...annot_opt_generic.RemoveUnneededDrops.diff | 3 +- ...ed_drops.dont_opt.RemoveUnneededDrops.diff | 3 +- ...nneeded_drops.opt.RemoveUnneededDrops.diff | 3 +- ....opt_generic_copy.RemoveUnneededDrops.diff | 3 +- ...ouch_unions.get_union.RemoveZsts.after.mir | 13 + .../mir-opt/remove_zsts_dont_touch_unions.rs | 19 + ...main.SimplifyCfg-elaborate-drops.after.mir | 4 +- ...imple_match.match_bool.mir_map.0.32bit.mir | 2 +- ...imple_match.match_bool.mir_map.0.64bit.mir | 2 +- ...entity.main.SimplifyArmIdentity.32bit.diff | 2 +- ...entity.main.SimplifyArmIdentity.64bit.diff | 2 +- ...ain.SimplifyBranches-after-const-prop.diff | 4 +- .../simplify_locals.c.SimplifyLocals.diff | 1 - .../simplify_locals.d1.SimplifyLocals.diff | 1 - .../simplify_locals.d2.SimplifyLocals.diff | 1 - .../simplify_locals.r.SimplifyLocals.diff | 1 - .../simplify_locals.t1.SimplifyLocals.diff | 1 - .../simplify_locals.t2.SimplifyLocals.diff | 1 - .../simplify_locals.t3.SimplifyLocals.diff | 1 - ..._locals_fixedpoint.foo.SimplifyLocals.diff | 6 +- ...ves_unused_consts.main.SimplifyLocals.diff | 5 - .../simplify_match.main.ConstProp.diff | 2 +- .../mir-opt/storage_ranges.main.nll.0.mir | 6 +- ...ls_access.main.SimplifyCfg-final.after.mir | 1 - ...ove_out.move_out_by_subslice.mir_map.0.mir | 2 +- ...y_move_out.move_out_from_end.mir_map.0.mir | 2 +- ...oops.change_loop_body.ConstProp.32bit.diff | 4 +- ...oops.change_loop_body.ConstProp.64bit.diff | 4 +- ...le_storage.while_loop.PreCodegen.after.mir | 20 +- .../coverage-reports/Makefile | 88 +- .../expected_show_coverage.async.txt | 16 +- .../expected_show_coverage.async2.txt | 115 + .../expected_show_coverage.closure.txt | 2 +- .../expected_show_coverage.continue.txt | 75 + .../expected_show_coverage.doctest.txt | 8 +- .../expected_show_coverage.inline.txt | 6 +- .../expected_show_coverage.issue-83601.txt | 22 + .../expected_show_coverage.loops_branches.txt | 70 +- .../expected_show_coverage.no_cov_crate.txt | 18 + .../expected_show_coverage.partial_eq.txt | 7 +- ...xpected_show_coverage.try_error_result.txt | 89 +- .../expected_show_coverage.unused.txt | 62 + .../expected_show_coverage.uses_crate.txt | 101 +- ...pected_show_coverage.uses_inline_crate.txt | 139 + .../coverage-spanview/Makefile | 96 - .../coverage-spanview/escape_url.py | 12 - ...ort.main.-------.InstrumentCoverage.0.html | 106 - ...ht_abort.-------.InstrumentCoverage.0.html | 163 - ...ert.main.-------.InstrumentCoverage.0.html | 102 - ...l_assert.-------.InstrumentCoverage.0.html | 97 - ...osure#0}.-------.InstrumentCoverage.0.html | 82 - .../async.c.-------.InstrumentCoverage.0.html | 80 - ...osure#0}.-------.InstrumentCoverage.0.html | 75 - .../async.d.-------.InstrumentCoverage.0.html | 74 - ...osure#0}.-------.InstrumentCoverage.0.html | 75 - .../async.e.-------.InstrumentCoverage.0.html | 74 - ...osure#0}.-------.InstrumentCoverage.0.html | 84 - ...osure#1}.-------.InstrumentCoverage.0.html | 84 - ...osure#2}.-------.InstrumentCoverage.0.html | 84 - ...osure#3}.-------.InstrumentCoverage.0.html | 75 - ...block_on.-------.InstrumentCoverage.0.html | 239 - ...osure#0}.-------.InstrumentCoverage.0.html | 75 - .../async.f.-------.InstrumentCoverage.0.html | 74 - ...osure#0}.-------.InstrumentCoverage.0.html | 75 - ...sync.foo.-------.InstrumentCoverage.0.html | 74 - ...osure#0}.-------.InstrumentCoverage.0.html | 82 - .../async.g.-------.InstrumentCoverage.0.html | 80 - ...osure#0}.-------.InstrumentCoverage.0.html | 82 - .../async.h.-------.InstrumentCoverage.0.html | 81 - ...osure#0}.-------.InstrumentCoverage.0.html | 91 - .../async.i.-------.InstrumentCoverage.0.html | 83 - ...sync.j-c.-------.InstrumentCoverage.0.html | 90 - ...sync.j-d.-------.InstrumentCoverage.0.html | 75 - ...sync.j-f.-------.InstrumentCoverage.0.html | 75 - .../async.j.-------.InstrumentCoverage.0.html | 108 - .../async.k.-------.InstrumentCoverage.0.html | 80 - .../async.l.-------.InstrumentCoverage.0.html | 80 - ...osure#0}.-------.InstrumentCoverage.0.html | 79 - .../async.m.-------.InstrumentCoverage.0.html | 74 - ...ync.main.-------.InstrumentCoverage.0.html | 190 - ...osure#0}.-------.InstrumentCoverage.0.html | 96 - ...sure#10}.-------.InstrumentCoverage.0.html | 96 - ...sure#11}.-------.InstrumentCoverage.0.html | 96 - ...osure#1}.-------.InstrumentCoverage.0.html | 96 - ...osure#2}.-------.InstrumentCoverage.0.html | 128 - ...osure#3}.-------.InstrumentCoverage.0.html | 91 - ...osure#4}.-------.InstrumentCoverage.0.html | 77 - ...osure#5}.-------.InstrumentCoverage.0.html | 115 - ...osure#6}.-------.InstrumentCoverage.0.html | 87 - ...osure#7}.-------.InstrumentCoverage.0.html | 115 - ...osure#8}.-------.InstrumentCoverage.0.html | 89 - ...osure#9}.-------.InstrumentCoverage.0.html | 89 - ...ure.main.-------.InstrumentCoverage.0.html | 10921 ------ ...ons.main.-------.InstrumentCoverage.0.html | 307 - ...ode.main.-------.InstrumentCoverage.0.html | 143 - ...nused_fn.-------.InstrumentCoverage.0.html | 143 - ..._library.-------.InstrumentCoverage.0.html | 143 - ...est.main.-------.InstrumentCoverage.0.html | 96 - ...doctests.-------.InstrumentCoverage.0.html | 113 - ...ait.main.-------.InstrumentCoverage.0.html | 152 - ...#0}-drop.-------.InstrumentCoverage.0.html | 133 - ...ics.main.-------.InstrumentCoverage.0.html | 237 - ...strength.-------.InstrumentCoverage.0.html | 85 - ...#1}-drop.-------.InstrumentCoverage.0.html | 133 - .../if.main.-------.InstrumentCoverage.0.html | 238 - ...lse.main.-------.InstrumentCoverage.0.html | 195 - ....display.-------.InstrumentCoverage.0.html | 161 - ...ne.error.-------.InstrumentCoverage.0.html | 79 - ...e.length.-------.InstrumentCoverage.0.html | 82 - ...ine.main.-------.InstrumentCoverage.0.html | 94 - ...ermutate.-------.InstrumentCoverage.0.html | 183 - ...utations.-------.InstrumentCoverage.0.html | 113 - ...ine.swap.-------.InstrumentCoverage.0.html | 173 - ...ait_func.-------.InstrumentCoverage.0.html | 93 - ...-in_func.-------.InstrumentCoverage.0.html | 203 - ...ait_func.-------.InstrumentCoverage.0.html | 101 - ...ems.main.-------.InstrumentCoverage.0.html | 189 - ...ean.main.-------.InstrumentCoverage.0.html | 259 - ...lue.main.-------.InstrumentCoverage.0.html | 128 - ...hes.main.-------.InstrumentCoverage.0.html | 161 - ...l#0}-fmt.-------.InstrumentCoverage.0.html | 100 - ...ern.main.-------.InstrumentCoverage.0.html | 259 - ...ops.main.-------.InstrumentCoverage.0.html | 166 - ...low.main.-------.InstrumentCoverage.0.html | 258 - ...overflow.-------.InstrumentCoverage.0.html | 394 - ...ind.main.-------.InstrumentCoverage.0.html | 102 - ...ht_panic.-------.InstrumentCoverage.0.html | 163 - ..._eq.main.-------.InstrumentCoverage.0.html | 295 - ...l#0}-new.-------.InstrumentCoverage.0.html | 108 - ...l#1}-cmp.-------.InstrumentCoverage.0.html | 74 - ...tial_cmp.-------.InstrumentCoverage.0.html | 74 - ...total_eq.-------.InstrumentCoverage.0.html | 75 - ...pl#6}-eq.-------.InstrumentCoverage.0.html | 74 - ...pl#6}-ne.-------.InstrumentCoverage.0.html | 74 - ...l#7}-fmt.-------.InstrumentCoverage.0.html | 110 - ...8}-clone.-------.InstrumentCoverage.0.html | 88 - ...oop.main.-------.InstrumentCoverage.0.html | 193 - ...tch.main.-------.InstrumentCoverage.0.html | 222 - ...oop.main.-------.InstrumentCoverage.0.html | 81 - ...ult.call.-------.InstrumentCoverage.0.html | 82 - ...ult.main.-------.InstrumentCoverage.0.html | 129 - ...function.-------.InstrumentCoverage.0.html | 115 - ...function.-------.InstrumentCoverage.0.html | 133 - ...function.-------.InstrumentCoverage.0.html | 115 - ...ib_crate.-------.InstrumentCoverage.0.html | 190 - ...function.-------.InstrumentCoverage.0.html | 133 - ...function.-------.InstrumentCoverage.0.html | 110 - ...function.-------.InstrumentCoverage.0.html | 133 - ...function.-------.InstrumentCoverage.0.html | 133 - ...function.-------.InstrumentCoverage.0.html | 133 - ...ate.main.-------.InstrumentCoverage.0.html | 193 - ...ile.main.-------.InstrumentCoverage.0.html | 82 - ...ret.main.-------.InstrumentCoverage.0.html | 130 - ...osure#0}.-------.InstrumentCoverage.0.html | 79 - ...osure#1}.-------.InstrumentCoverage.0.html | 81 - ...eld.main.-------.InstrumentCoverage.0.html | 138 - src/test/run-make-fulldeps/coverage/async.rs | 12 +- src/test/run-make-fulldeps/coverage/async2.rs | 69 + .../run-make-fulldeps/coverage/closure.rs | 2 +- .../run-make-fulldeps/coverage/continue.rs | 69 + .../coverage/coverage_tools.mk | 8 - .../run-make-fulldeps/coverage/issue-83601.rs | 14 + .../coverage/lib/used_crate.rs | 68 +- .../coverage/lib/used_inline_crate.rs | 90 + .../coverage/loops_branches.rs | 51 +- .../coverage/no_cov_crate.rs | 17 + .../coverage/try_error_result.rs | 84 +- src/test/run-make-fulldeps/coverage/unused.rs | 39 + .../run-make-fulldeps/coverage/uses_crate.rs | 2 +- .../coverage/uses_inline_crate.rs | 17 + .../incr-add-rust-src-component/Makefile | 2 +- .../run-make-fulldeps/issue-47551/Makefile | 9 + .../issue-47551/eh_frame-terminator.rs | 23 + .../run-make-fulldeps/issue-83045/Makefile | 33 + src/test/run-make-fulldeps/issue-83045/a.rs | 1 + src/test/run-make-fulldeps/issue-83045/b.rs | 1 + src/test/run-make-fulldeps/issue-83045/c.rs | 1 + .../link-args-order/Makefile | 2 +- .../link-args-order/empty.rs | 5 - .../unversioned-files.txt | 13 +- src/test/run-make/const_fn_mir/dump.mir | 1 + src/test/run-make/emit-shared-files/Makefile | 46 + src/test/run-make/emit-shared-files/x.rs | 1 + src/test/run-make/emit-shared-files/y.css | 0 src/test/run-make/emit-shared-files/z.css | 0 .../incr-prev-body-beyond-eof/Makefile | 10 +- src/test/run-make/issue-36710/Makefile | 15 +- .../issue-83112-incr-test-moved-file/Makefile | 8 +- .../run-make/unstable-flag-required/Makefile | 4 + .../run-make/unstable-flag-required/README.md | 3 + .../output-format-json.stderr | 2 + src/test/run-make/unstable-flag-required/x.rs | 1 + src/test/run-make/wasm-abi/Makefile | 7 + src/test/run-make/wasm-abi/foo.js | 22 + src/test/run-make/wasm-abi/foo.rs | 87 + src/test/rustdoc-gui/README.md | 12 + .../rustdoc-gui/check_info_sign_position.goml | 9 + src/test/rustdoc-gui/hash-item-expansion.goml | 18 + .../rustdoc-gui/impl-default-expansion.goml | 3 + src/test/rustdoc-gui/lib.rs | 35 +- src/test/rustdoc-gui/nojs-attr-pos.goml | 5 - ...rch-tab-selection-if-current-is-empty.goml | 21 + .../rustdoc-gui/trait-sidebar-item-order.goml | 7 + src/test/rustdoc-json/nested.rs | 4 +- .../rustdoc-json/reexport/in_root_and_mod.rs | 15 + .../reexport/in_root_and_mod_pub.rs | 20 + .../rustdoc-json/reexport/rename_private.rs | 14 + .../rustdoc-json/reexport/rename_public.rs | 2 +- .../rustdoc-json/reexport/simple_public.rs | 2 +- src/test/rustdoc-ui/auxiliary/panic-item.rs | 17 + src/test/rustdoc-ui/bare-urls.fixed | 60 + .../{url-improvements.rs => bare-urls.rs} | 16 +- ...l-improvements.stderr => bare-urls.stderr} | 93 +- .../rustdoc-ui/check-doc-alias-attr.stderr | 4 +- .../rustdoc-ui/commandline-argfile-missing.rs | 1 - src/test/rustdoc-ui/coverage/traits.rs | 14 +- src/test/rustdoc-ui/coverage/traits.stdout | 4 +- src/test/rustdoc-ui/doc-spotlight.fixed | 9 + src/test/rustdoc-ui/doc-spotlight.rs | 9 + src/test/rustdoc-ui/doc-spotlight.stderr | 14 + src/test/rustdoc-ui/intra-doc/anchors.rs | 4 + src/test/rustdoc-ui/intra-doc/anchors.stderr | 37 +- .../rustdoc-ui/intra-doc/double-anchor.stderr | 4 +- .../intra-doc/email-address-localhost.rs | 6 + .../intra-doc/email-address-localhost.stderr | 15 + .../intra-doc/private-from-crate-level.rs | 6 + .../intra-doc/private-from-crate-level.stderr | 11 + .../intra-doc/private.private.stderr | 18 +- .../intra-doc/private.public.stderr | 18 +- src/test/rustdoc-ui/intra-doc/private.rs | 10 +- .../intra-doc/unknown-disambiguator.rs | 13 + .../intra-doc/unknown-disambiguator.stderr | 45 + src/test/rustdoc-ui/invalid-theme-name.rs | 3 + src/test/rustdoc-ui/invalid-theme-name.stderr | 4 + .../rustdoc-ui/issue-83883-describe-lints.rs | 8 + .../issue-83883-describe-lints.stdout | 25 + .../rustdoc-ui/output-format-html-stable.rs | 4 + .../rustdoc-ui/renamed-lint-still-applies.rs | 5 + .../renamed-lint-still-applies.stderr | 23 +- src/test/rustdoc-ui/unknown-renamed-lints.rs | 6 +- .../rustdoc-ui/unknown-renamed-lints.stderr | 18 +- src/test/rustdoc-ui/unused-extern-crate.rs | 3 + src/test/rustdoc/assoc-item-cast.rs | 1 - src/test/rustdoc/assoc-types.rs | 10 +- src/test/rustdoc/async-fn.rs | 1 - src/test/rustdoc/attributes.rs | 10 +- src/test/rustdoc/auto_aliases.rs | 2 +- src/test/rustdoc/auxiliary/primitive-doc.rs | 6 + src/test/rustdoc/check-styled-link.rs | 2 +- src/test/rustdoc/const-display.rs | 2 - src/test/rustdoc/const-generics/add-impl.rs | 4 +- src/test/rustdoc/const-generics/const-impl.rs | 2 - src/test/rustdoc/const-generics/type-alias.rs | 1 - src/test/rustdoc/cross-crate-primitive-doc.rs | 9 + src/test/rustdoc/decl_macro.rs | 17 + src/test/rustdoc/default-trait-method-link.rs | 4 +- ...{doc-spotlight.rs => doc-notable_trait.rs} | 10 +- src/test/rustdoc/double-quote-escape.rs | 1 - src/test/rustdoc/duplicate-cfg.rs | 2 - .../rustdoc/duplicate_impls/issue-33054.rs | 4 +- src/test/rustdoc/empty-impls.rs | 19 + src/test/rustdoc/fn-type.rs | 2 - src/test/rustdoc/for-lifetime.rs | 2 - src/test/rustdoc/inline_cross/impl_trait.rs | 1 - src/test/rustdoc/intra-doc-crate/self.rs | 4 +- src/test/rustdoc/intra-doc/anchors.rs | 2 +- .../rustdoc/intra-doc/associated-defaults.rs | 9 +- .../rustdoc/intra-doc/associated-items.rs | 11 +- src/test/rustdoc/intra-doc/auxiliary/empty.rs | 1 + .../rustdoc/intra-doc/auxiliary/empty2.rs | 1 + .../auxiliary/issue-66159-1.rs | 0 src/test/rustdoc/intra-doc/basic.rs | 44 +- .../intra-doc/cross-crate/additional_doc.rs | 2 +- .../rustdoc/intra-doc/cross-crate/hidden.rs | 2 +- .../rustdoc/intra-doc/cross-crate/macro.rs | 1 - .../intra-doc/cross-crate/submodule-outer.rs | 4 +- .../rustdoc/intra-doc/cross-crate/traits.rs | 1 - .../intra-doc/disambiguators-removed.rs | 27 +- src/test/rustdoc/intra-doc/email-address.rs | 6 + .../rustdoc/intra-doc/enum-struct-field.rs | 2 +- .../extern-crate-only-used-in-link.rs | 19 + src/test/rustdoc/intra-doc/extern-type.rs | 2 +- src/test/rustdoc/intra-doc/issue-82209.rs | 2 +- src/test/rustdoc/intra-doc/mod-ambiguity.rs | 4 +- .../rustdoc/intra-doc/non-path-primitives.rs | 1 - src/test/rustdoc/intra-doc/prim-assoc.rs | 1 - .../intra-doc/prim-methods-external-core.rs | 1 - .../rustdoc/intra-doc/prim-methods-local.rs | 1 - src/test/rustdoc/intra-doc/prim-methods.rs | 1 - src/test/rustdoc/intra-doc/prim-precedence.rs | 5 +- .../intra-doc/primitive-non-default-impl.rs | 1 - src/test/rustdoc/intra-doc/private.rs | 17 +- src/test/rustdoc/intra-doc/proc-macro.rs | 10 +- src/test/rustdoc/intra-doc/pub-use.rs | 2 +- src/test/rustdoc/intra-doc/raw-ident-self.rs | 2 +- .../intra-doc/reexport-additional-docs.rs | 8 +- src/test/rustdoc/intra-doc/self.rs | 29 +- src/test/rustdoc/intra-doc/trait-impl.rs | 7 +- src/test/rustdoc/intra-doc/trait-item.rs | 3 +- src/test/rustdoc/intra-doc/true-false.rs | 1 - src/test/rustdoc/intra-link-self-cache.rs | 4 +- src/test/rustdoc/issue-21474.rs | 2 +- src/test/rustdoc/issue-28478.rs | 8 +- src/test/rustdoc/issue-29503.rs | 4 +- src/test/rustdoc/issue-45584.rs | 4 +- src/test/rustdoc/issue-50159.rs | 4 +- src/test/rustdoc/issue-51236.rs | 2 +- src/test/rustdoc/issue-53812.rs | 10 +- src/test/rustdoc/issue-54705.rs | 4 +- src/test/rustdoc/issue-55321.rs | 8 +- src/test/rustdoc/issue-55364.rs | 30 +- src/test/rustdoc/issue-56822.rs | 2 +- src/test/rustdoc/issue-60726.rs | 4 +- src/test/rustdoc/issue-66159.rs | 10 - src/test/rustdoc/issue-72340.rs | 2 +- src/test/rustdoc/issue-75588.rs | 1 - src/test/rustdoc/item-hide-threshold.rs | 156 + src/test/rustdoc/link-assoc-const.rs | 4 +- src/test/rustdoc/playground-arg.rs | 1 - src/test/rustdoc/playground.rs | 2 - src/test/rustdoc/prim-title.rs | 7 - src/test/rustdoc/primitive-link.rs | 1 - src/test/rustdoc/proc-macro.rs | 6 +- .../rustdoc/raw-ident-eliminate-r-hashtag.rs | 8 +- ...ability-tags-deprecated-and-portability.rs | 48 + ...stability-tags-unstable-and-portability.rs | 61 + src/test/rustdoc/smart-punct.rs | 2 - src/test/rustdoc/src-links-external.rs | 1 - src/test/rustdoc/struct-arg-pattern.rs | 10 + src/test/rustdoc/struct-field.rs | 7 +- src/test/rustdoc/synthetic_auto/basic.rs | 4 +- src/test/rustdoc/synthetic_auto/complex.rs | 2 +- src/test/rustdoc/synthetic_auto/lifetimes.rs | 4 +- src/test/rustdoc/synthetic_auto/manual.rs | 8 +- src/test/rustdoc/synthetic_auto/negative.rs | 4 +- src/test/rustdoc/synthetic_auto/nested.rs | 4 +- .../rustdoc/synthetic_auto/no-redundancy.rs | 2 +- src/test/rustdoc/synthetic_auto/project.rs | 4 +- .../synthetic_auto/self-referential.rs | 2 +- .../rustdoc/synthetic_auto/static-region.rs | 2 +- src/test/rustdoc/tab_title.rs | 44 + src/test/rustdoc/trait-attributes.rs | 7 +- .../trait-impl-items-links-and-anchors.rs | 65 + src/test/rustdoc/trait-self-link.rs | 2 +- .../auxiliary/lint-for-crate-rpass.rs | 2 +- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 2 +- .../anon-params-edition-hygiene.rs | 3 + .../subslice-patterns-const-eval-match.rs | 2 - src/test/ui/asm/bad-reg.rs | 2 + src/test/ui/asm/bad-reg.stderr | 20 +- src/test/ui/asm/const.rs | 38 +- src/test/ui/asm/inline-syntax.arm.stderr | 74 +- src/test/ui/asm/inline-syntax.rs | 29 +- src/test/ui/asm/inline-syntax.x86_64.stderr | 50 +- src/test/ui/asm/naked-invalid-attr.rs | 2 +- src/test/ui/asm/parse-error.rs | 6 + src/test/ui/asm/parse-error.stderr | 77 +- src/test/ui/asm/srcloc.rs | 4 +- src/test/ui/asm/sym.rs | 4 +- src/test/ui/asm/type-check-1.rs | 18 + src/test/ui/asm/type-check-1.stderr | 32 +- src/test/ui/asm/type-check-2.rs | 24 +- src/test/ui/asm/type-check-2.stderr | 50 +- src/test/ui/assign-imm-local-twice.rs | 2 +- src/test/ui/assign-imm-local-twice.stderr | 2 +- .../associated-const-in-trait.rs | 2 +- .../ambiguous-associated-type2.rs | 2 - .../ambiguous-associated-type2.stderr | 4 +- .../duplicate.full_tait.stderr | 142 +- .../duplicate.min_tait.stderr | 140 +- .../ui/associated-type-bounds/duplicate.rs | 2 - src/test/ui/associated-type-bounds/hrtb.rs | 65 + .../ui/associated-type-bounds/issue-79949.rs | 26 + .../ui/associated-type-bounds/issue-81193.rs | 15 + .../ui/associated-type-bounds/issue-83017.rs | 39 + .../associated-type-bounds/issue-83017.stderr | 27 + .../associated-types-coherence-failure.stderr | 4 +- .../defaults-specialization.stderr | 10 +- .../defaults-suitability.stderr | 8 +- ...mpl-trait-return-missing-constraint.stderr | 8 +- .../associated-types/impl-wf-cycle-1.stderr | 18 +- .../associated-types/impl-wf-cycle-2.stderr | 12 +- .../issue-23208.rs | 0 .../issue-27675-unchecked-bounds.stderr | 4 +- .../issue-31597.rs | 0 .../issue-43784-associated-type.stderr | 4 +- .../ui/associated-types/issue-44153.stderr | 8 +- .../ui/associated-types/issue-65774-1.stderr | 6 +- src/test/ui/async-await/async-trait-fn.rs | 4 + src/test/ui/async-await/async-trait-fn.stderr | 18 +- src/test/ui/async-await/issue-61452.stderr | 2 +- .../issue-61949-self-return-type.rs | 1 - .../issue-61949-self-return-type.stderr | 2 +- src/test/ui/async-await/issue-67651.stderr | 2 +- src/test/ui/async-await/issue-68523.rs | 1 - src/test/ui/async-await/issue-68523.stderr | 13 +- src/test/ui/async-await/issue-70818.stderr | 4 +- .../issue-72590-type-error-sized.stderr | 6 +- src/test/ui/async-await/issues/issue-64964.rs | 2 +- src/test/ui/async-await/large_moves.rs | 24 + src/test/ui/async-await/large_moves.stderr | 38 + .../ui/async-await/pin-needed-to-poll-2.rs | 48 + .../async-await/pin-needed-to-poll-2.stderr | 17 + src/test/ui/async-await/pin-needed-to-poll.rs | 47 + .../ui/async-await/pin-needed-to-poll.stderr | 22 + src/test/ui/attr-main-2.rs | 11 - src/test/ui/attr-main.rs | 8 - src/test/ui/attr.rs | 8 - .../ui/binding/issue-53114-safety-checks.rs | 8 +- .../binding/issue-53114-safety-checks.stderr | 68 +- src/test/ui/{ => binding}/shadow.rs | 0 src/test/ui/block-result/issue-22645.stderr | 6 +- ...or-patterns-slice-patterns-box-patterns.rs | 1 - ...atterns-slice-patterns-box-patterns.stderr | 34 +- src/test/ui/borrowck/borrowck-asm.stderr | 4 +- .../ui/borrowck/borrowck-describe-lvalue.rs | 2 - .../borrowck/borrowck-describe-lvalue.stderr | 64 +- ...orrowck-match-binding-is-assignment.stderr | 10 +- src/test/ui/borrowck/borrowck-union-borrow.rs | 2 - .../ui/borrowck/borrowck-union-borrow.stderr | 24 +- src/test/ui/borrowck/immutable-arg.stderr | 2 +- src/test/ui/borrowck/issue-45199.rs | 6 +- src/test/ui/borrowck/issue-45199.stderr | 6 +- src/test/ui/borrowck/or-patterns.rs | 2 - src/test/ui/borrowck/or-patterns.stderr | 24 +- ...ccess-during-reservation.nll_target.stderr | 4 +- ...o-phase-allow-access-during-reservation.rs | 2 - ...ion-sharing-interference.nll_target.stderr | 2 +- ...-phase-reservation-sharing-interference.rs | 2 - src/test/ui/bound-suggestions.fixed | 12 +- src/test/ui/bound-suggestions.stderr | 24 +- ...builtin-superkinds-double-superkind.stderr | 8 +- .../builtin-superkinds-in-metadata.stderr | 10 +- ...builtin-superkinds-typaram-not-send.stderr | 4 +- src/test/ui/cast/cast-ptr-to-int-const.rs | 22 +- src/test/ui/cast/cast-ptr-to-int-const.stderr | 21 - .../cast-ptr-to-int-const.with_feature.stderr | 19 + ...st-ptr-to-int-const.without_feature.stderr | 39 + src/test/ui/cast/fat-ptr-cast-rpass.rs | 4 +- src/test/ui/cast/issue-84213.fixed | 15 + src/test/ui/cast/issue-84213.rs | 15 + src/test/ui/cast/issue-84213.stderr | 25 + src/test/ui/cleanup-shortcircuit.rs | 3 + .../diagnostics/repr_packed.rs | 2 +- .../diagnostics/repr_packed.stderr | 8 +- .../migrations/insignificant_drop.fixed | 133 + .../migrations/insignificant_drop.rs | 31 +- .../migrations/insignificant_drop.stderr | 88 +- .../migrations/issue-78720.rs | 10 + .../migrations/issue-78720.stderr | 15 + .../migrations/migrations_rustfix.fixed | 40 + .../migrations/migrations_rustfix.rs | 40 + .../migrations/migrations_rustfix.stderr | 38 + .../migrations/precise.fixed | 56 + .../migrations/precise.rs | 34 +- .../migrations/precise.stderr | 39 +- .../migrations/significant_drop.fixed | 136 + .../migrations/significant_drop.rs | 31 +- .../migrations/significant_drop.stderr | 82 +- ...ds-cant-promote-superkind-in-struct.stderr | 4 +- .../ui/closures/closure-bounds-subtype.stderr | 4 +- src/test/ui/closures/issue-84128.rs | 16 + src/test/ui/closures/issue-84128.stderr | 15 + src/test/ui/codemap_tests/two_files.stderr | 5 +- src/test/ui/codemap_tests/unicode.stderr | 2 +- src/test/ui/codemap_tests/unicode_2.rs | 2 - src/test/ui/codemap_tests/unicode_2.stderr | 6 +- ...-conflicts-with-blanket-implemented.stderr | 2 +- ...onflicts-with-blanket-unimplemented.stderr | 2 +- ...conflicts-with-specific-cross-crate.stderr | 2 +- ...nflicts-with-specific-multidispatch.stderr | 2 +- ...anket-conflicts-with-specific-trait.stderr | 2 +- ...nce-blanket-conflicts-with-specific.stderr | 2 +- ...nce-conflicting-negative-trait-impl.stderr | 2 +- .../coherence-cross-crate-conflict.stderr | 2 +- ...erence-fn-covariant-bound-vs-static.stderr | 2 +- .../coherence-fn-implied-bounds.stderr | 2 +- .../ui/coherence/coherence-fn-inputs.stderr | 2 +- .../coherence-free-vs-bound-region.stderr | 2 +- .../ui/coherence/coherence-impls-copy.stderr | 6 +- .../ui/coherence/coherence-impls-send.stderr | 2 +- ...herence-no-direct-lifetime-dispatch.stderr | 2 +- .../coherence-overlap-all-t-and-tuple.stderr | 2 +- .../coherence-overlap-downstream.stderr | 4 +- .../coherence-overlap-issue-23516.stderr | 2 +- .../coherence-overlap-messages.stderr | 10 +- .../coherence-overlap-upstream.stderr | 2 +- ...oherence-projection-conflict-orphan.stderr | 2 +- ...erence-projection-conflict-ty-param.stderr | 2 +- .../coherence-projection-conflict.stderr | 2 +- .../ui/coherence/coherence-subtyping.stderr | 2 +- .../coherence/coherence-tuple-conflict.stderr | 2 +- .../coherence/coherence-wasm-bindgen.stderr | 2 +- ...y_like_err_fundamental_struct_tuple.stderr | 2 +- .../coherence_copy_like_err_struct.stderr | 2 +- .../coherence_copy_like_err_tuple.stderr | 2 +- src/test/ui/command-line-diagnostics.stderr | 2 +- src/test/ui/command/command-setgroups.rs | 1 - src/test/ui/commandline-argfile-missing.rs | 1 - src/test/ui/compare-method/bad-self-type.rs | 26 + .../ui/compare-method/bad-self-type.stderr | 46 + .../reordered-type-param.stderr | 6 +- .../const-argument-if-length.full.stderr | 4 +- .../const-argument-if-length.min.stderr | 2 +- .../cross_crate_predicate.stderr | 36 +- .../different-fn.stderr | 6 +- ...t-eagerly-error-in-is-const-evaluatable.rs | 17 + .../defaults/auxiliary/const_defaulty.rs | 15 + .../complex-generic-default-expr.full.stderr | 18 + .../complex-generic-default-expr.min.stderr | 20 + .../defaults/complex-generic-default-expr.rs | 14 + .../defaults/complex-unord-param.rs | 18 +- .../const-generics/defaults/const-default.rs | 30 + .../defaults/const-param-as-default-value.rs | 23 + .../defaults/const-param-in-ty-defaults.rs | 14 + .../defaults/default-annotation.rs | 20 + .../defaults/default-on-impl.full.stderr | 8 + .../defaults/default-on-impl.min.stderr | 8 + .../defaults/default-on-impl.rs | 11 + .../defaults/default-param-wf-concrete.rs | 5 + .../defaults/default-param-wf-concrete.stderr | 9 + .../ui/const-generics/defaults/external.rs | 29 + .../defaults/intermixed-lifetime.full.stderr | 2 +- .../defaults/intermixed-lifetime.min.stderr | 22 +- .../defaults/intermixed-lifetime.rs | 10 +- .../defaults/mismatch.full.stderr | 52 + .../defaults/mismatch.min.stderr | 52 + .../ui/const-generics/defaults/mismatch.rs | 24 + .../const-generics/defaults/needs-feature.rs | 2 +- .../defaults/pretty-printing-ast.rs | 13 + .../defaults/pretty-printing-ast.stdout | 20 + .../defaults/repr-c-issue-82792.rs | 14 + .../defaults/simple-defaults.min.stderr | 8 - .../defaults/simple-defaults.rs | 14 +- .../defaults/type-default-const-param-name.rs | 19 + .../defaults/wrong-order.full.stderr | 17 +- .../defaults/wrong-order.min.stderr | 6 +- .../ui/const-generics/defaults/wrong-order.rs | 6 +- src/test/ui/const-generics/diagnostics.stderr | 9 +- ....full.stderr => issue-56445-1.full.stderr} | 4 +- ...45.min.stderr => issue-56445-1.min.stderr} | 2 +- .../{issue-56445.rs => issue-56445-1.rs} | 0 .../ui/const-generics/issues/issue-56445-2.rs | 11 + .../issues/issue-56445-2.stderr | 14 + .../ui/const-generics/issues/issue-56445-3.rs | 12 + .../issues/issue-56445-3.stderr | 8 + .../issues/issue-61336-2.full.stderr | 4 +- .../issues/issue-61336-2.min.stderr | 4 +- .../issues/issue-61336.full.stderr | 4 +- .../issues/issue-61336.min.stderr | 4 +- .../issues/issue-64494.min.stderr | 2 +- .../issues/issue-69654-run-pass.rs | 2 +- .../issues/issue-69654-run-pass.stderr | 15 + .../ui/const-generics/issues/issue-69654.rs | 1 + .../const-generics/issues/issue-69654.stderr | 17 +- ...73-assoc-fn.rs => issue-70273-assoc-fn.rs} | 0 .../ui/const-generics/issues/issue-84408.rs | 38 + .../min_const_generics/const_default_first.rs | 9 + .../const_default_first.stderr | 8 + .../default_function_param.rs | 8 +- .../default_function_param.stderr | 12 +- ...s.stderr => invalid-patterns.32bit.stderr} | 28 +- .../invalid-patterns.64bit.stderr | 72 + .../min_const_generics/invalid-patterns.rs | 1 + .../type_and_const_defaults.rs | 27 + .../occurs-check/unused-substs-1.rs | 3 +- .../occurs-check/unused-substs-1.stderr | 17 + .../occurs-check/unused-substs-2.rs | 3 +- .../occurs-check/unused-substs-2.stderr | 9 + .../occurs-check/unused-substs-3.rs | 3 +- .../occurs-check/unused-substs-3.stderr | 12 + .../occurs-check/unused-substs-4.rs | 3 +- .../occurs-check/unused-substs-4.stderr | 9 + ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 19 +- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 13 +- .../params-in-ct-in-ty-param-lazy-norm.rs | 9 +- src/test/ui/const-ptr/out_of_bounds_read.rs | 16 - .../ui/const-ptr/out_of_bounds_read.stderr | 62 - .../needs_where_clause.stderr | 6 +- .../const_evaluatable/no_where_clause.stderr | 6 +- .../ui/consts/cast-discriminant-zst-enum.rs | 2 +- ...st-err4.stderr => const-err4.32bit.stderr} | 5 +- src/test/ui/consts/const-err4.64bit.stderr | 14 + src/test/ui/consts/const-err4.rs | 1 + .../consts/const-eval/auxiliary/stability.rs | 1 - .../const-eval/conditional_array_execution.rs | 2 +- .../const-eval/const-eval-query-stack.stderr | 2 +- ...nter-values-in-various-types.64bit.stderr} | 85 +- .../const-pointer-values-in-various-types.rs | 1 + src/test/ui/consts/const-eval/const_fn_ptr.rs | 1 - .../ui/consts/const-eval/const_fn_ptr.stderr | 10 +- .../ui/consts/const-eval/const_fn_ptr_fail.rs | 1 - .../const-eval/const_fn_ptr_fail.stderr | 2 +- .../consts/const-eval/const_fn_ptr_fail2.rs | 1 - .../const-eval/const_fn_ptr_fail2.stderr | 10 +- .../dont_promote_unstable_const_fn.rs | 1 - .../dont_promote_unstable_const_fn.stderr | 8 +- .../ui/consts/const-eval/double_promotion.rs | 2 +- .../const-eval/feature-gate-const_fn_union.rs | 2 - .../feature-gate-const_fn_union.stderr | 2 +- ...rr => alloc_intrinsic_uninit.32bit.stderr} | 5 +- .../heap/alloc_intrinsic_uninit.64bit.stderr | 14 + .../const-eval/heap/alloc_intrinsic_uninit.rs | 1 + src/test/ui/consts/const-eval/issue-44578.rs | 2 +- src/test/ui/consts/const-eval/issue-49296.rs | 2 +- .../const-eval/promoted_const_fn_fail.rs | 2 +- .../promoted_const_fn_fail_deny_const_err.rs | 2 +- ...h.stderr => ref_to_int_match.32bit.stderr} | 9 +- .../const-eval/ref_to_int_match.64bit.stderr | 26 + .../ui/consts/const-eval/ref_to_int_match.rs | 1 + .../consts/const-eval/simd/insert_extract.rs | 1 - ...st.stderr => transmute-const.32bit.stderr} | 5 +- .../const-eval/transmute-const.64bit.stderr | 14 + .../ui/consts/const-eval/transmute-const.rs | 1 + .../{ub-enum.stderr => ub-enum.32bit.stderr} | 39 + .../ui/consts/const-eval/ub-enum.64bit.stderr | 146 + src/test/ui/consts/const-eval/ub-enum.rs | 2 +- ...array.stderr => ub-int-array.32bit.stderr} | 9 + .../const-eval/ub-int-array.64bit.stderr | 54 + src/test/ui/consts/const-eval/ub-int-array.rs | 2 +- ...nonnull.stderr => ub-nonnull.32bit.stderr} | 34 +- .../consts/const-eval/ub-nonnull.64bit.stderr | 90 + src/test/ui/consts/const-eval/ub-nonnull.rs | 1 + ...ref-ptr.stderr => ub-ref-ptr.32bit.stderr} | 55 +- .../consts/const-eval/ub-ref-ptr.64bit.stderr | 124 + src/test/ui/consts/const-eval/ub-ref-ptr.rs | 1 + ...habit.stderr => ub-uninhabit.32bit.stderr} | 11 +- .../const-eval/ub-uninhabit.64bit.stderr | 32 + src/test/ui/consts/const-eval/ub-uninhabit.rs | 1 + ...b-upvars.stderr => ub-upvars.32bit.stderr} | 5 +- .../consts/const-eval/ub-upvars.64bit.stderr | 18 + src/test/ui/consts/const-eval/ub-upvars.rs | 1 + ...de-ptr.stderr => ub-wide-ptr.32bit.stderr} | 134 +- .../const-eval/ub-wide-ptr.64bit.stderr | 309 + src/test/ui/consts/const-eval/ub-wide-ptr.rs | 1 + .../const-eval/union-const-eval-field.rs | 2 +- .../const-eval/union-const-eval-field.stderr | 3 + src/test/ui/consts/const-eval/union-ice.rs | 2 +- .../ui/consts/const-eval/union-ice.stderr | 11 + ...{union-ub.stderr => union-ub.32bit.stderr} | 10 +- .../consts/const-eval/union-ub.64bit.stderr | 25 + src/test/ui/consts/const-eval/union-ub.rs | 1 + ...=> validate_uninhabited_zsts.32bit.stderr} | 1 + .../validate_uninhabited_zsts.64bit.stderr | 56 + .../const-eval/validate_uninhabited_zsts.rs | 2 +- src/test/ui/consts/const-fn-error.rs | 2 - src/test/ui/consts/const-fn-error.stderr | 14 +- src/test/ui/consts/const-fn-mismatch.rs | 2 - src/test/ui/consts/const-fn-mismatch.stderr | 2 +- src/test/ui/consts/const-fn-not-in-trait.rs | 4 +- .../ui/consts/const-fn-not-in-trait.stderr | 4 +- .../ui/consts/const-fn-not-safe-for-const.rs | 2 +- src/test/ui/consts/const-fn-type-name-any.rs | 1 - src/test/ui/consts/const-fn-type-name.rs | 1 - src/test/ui/consts/const-fn.rs | 3 +- src/test/ui/consts/const-int-unchecked.rs | 9 + src/test/ui/consts/const-int-unchecked.stderr | 24 +- .../const-mut-refs/const_mut_address_of.rs | 1 - .../consts/const-mut-refs/mut_ref_in_final.rs | 1 - .../const-mut-refs/mut_ref_in_final.stderr | 12 +- .../mut_ref_in_final_dynamic_check.rs | 1 - .../mut_ref_in_final_dynamic_check.stderr | 8 +- ...rr => const-points-to-static.32bit.stderr} | 7 +- .../const-points-to-static.64bit.stderr | 22 + src/test/ui/consts/const-points-to-static.rs | 4 +- .../const_constructor/const-construct-call.rs | 6 +- .../const_constructor_qpath.rs | 3 - src/test/ui/consts/const_discriminant.rs | 2 +- .../consts/const_fn_trait_bound.gated.stderr | 8 + src/test/ui/consts/const_fn_trait_bound.rs | 17 + .../consts/const_fn_trait_bound.stock.stderr | 30 + .../ui/consts/const_fn_unsize.gated.stderr | 8 + src/test/ui/consts/const_fn_unsize.rs | 16 + .../ui/consts/const_fn_unsize.stock.stderr | 12 + src/test/ui/consts/const_let_assign3.rs | 2 - src/test/ui/consts/const_let_assign3.stderr | 6 +- .../ui/consts/const_unsafe_unreachable.rs | 1 - .../ui/consts/const_unsafe_unreachable_ub.rs | 1 - .../consts/const_unsafe_unreachable_ub.stderr | 12 +- src/test/ui/consts/control-flow/basics.rs | 1 - src/test/ui/consts/issue-32829-2.rs | 2 - src/test/ui/consts/issue-32829-2.stderr | 6 +- src/test/ui/{issues => consts}/issue-52060.rs | 0 .../ui/{issues => consts}/issue-52060.stderr | 0 ...-63952.stderr => issue-63952.32bit.stderr} | 5 +- src/test/ui/consts/issue-63952.64bit.stderr | 20 + src/test/ui/consts/issue-63952.rs | 1 + ...-79690.stderr => issue-79690.64bit.stderr} | 5 +- src/test/ui/consts/issue-79690.rs | 1 + .../consts/min_const_fn/min_const_fn.stderr | 56 +- .../min_const_fn/min_const_fn_dyn.stderr | 12 +- .../min_const_fn_libstd_stability.rs | 2 +- .../min_const_unsafe_fn_libstd_stability.rs | 4 +- .../min_const_unsafe_fn_libstd_stability2.rs | 2 +- .../ui/{ => consts}/mir_check_nonconst.rs | 0 .../ui/{ => consts}/mir_check_nonconst.stderr | 0 ...r => const_refers_to_static2.32bit.stderr} | 18 +- .../const_refers_to_static2.64bit.stderr | 55 + .../miri_unleashed/const_refers_to_static2.rs | 7 +- ...refers_to_static_cross_crate.32bit.stderr} | 58 +- ..._refers_to_static_cross_crate.64bit.stderr | 184 + .../const_refers_to_static_cross_crate.rs | 7 +- ...rr => mutable_references_err.32bit.stderr} | 21 +- .../mutable_references_err.64bit.stderr | 56 + .../miri_unleashed/mutable_references_err.rs | 1 + src/test/ui/consts/offset_ub.rs | 1 - src/test/ui/consts/offset_ub.stderr | 44 +- src/test/ui/consts/promote-not.rs | 2 +- .../ui/consts/rustc-args-required-const.rs | 2 +- .../stable-precise-live-drops-in-libcore.rs | 2 +- .../std/{alloc.stderr => alloc.32bit.stderr} | 5 +- src/test/ui/consts/std/alloc.64bit.stderr | 14 + src/test/ui/consts/std/alloc.rs | 1 + .../ui/consts/unsizing-cast-non-null.stderr | 8 +- .../ui/consts/unstable-const-fn-in-libcore.rs | 2 +- ...err => validate_never_arrays.32bit.stderr} | 15 +- .../consts/validate_never_arrays.64bit.stderr | 36 + src/test/ui/consts/validate_never_arrays.rs | 1 + src/test/ui/copy-a-resource.stderr | 8 - src/test/ui/crate-loading/missing-std.rs | 11 + src/test/ui/crate-loading/missing-std.stderr | 13 + .../dep-graph/dep-graph-assoc-type-codegen.rs | 2 +- .../ui/dep-graph/dep-graph-caller-callee.rs | 2 +- src/test/ui/dep-graph/dep-graph-check-attr.rs | 20 + .../ui/dep-graph/dep-graph-check-attr.stderr | 26 + .../dep-graph/dep-graph-struct-signature.rs | 2 +- ...graph-trait-impl-two-traits-same-method.rs | 2 +- .../dep-graph-trait-impl-two-traits.rs | 2 +- src/test/ui/dep-graph/dep-graph-trait-impl.rs | 2 +- src/test/ui/dep-graph/dep-graph-type-alias.rs | 2 +- .../ui/dep-graph/dep-graph-variance-alias.rs | 2 +- src/test/ui/deprecation/deprecation-lint.rs | 1 - .../ui/deprecation/deprecation-lint.stderr | 246 +- .../rustc_deprecation-in-future.rs | 2 - .../rustc_deprecation-in-future.stderr | 6 +- src/test/ui/deref-suggestion.rs | 26 + src/test/ui/deref-suggestion.stderr | 39 +- .../derives/derive-assoc-type-not-impl.stderr | 8 - .../ui/derives/derive-macro-const-default.rs | 14 + .../ui/derives/deriving-with-repr-packed.rs | 2 +- .../derives/deriving-with-repr-packed.stderr | 12 +- .../bad-expr-lhs.rs | 0 .../bad-expr-lhs.stderr | 0 ...92-tuple-destructure-missing-parens.stderr | 33 +- src/test/ui/did_you_mean/pub-macro-rules.rs | 16 + .../ui/did_you_mean/pub-macro-rules.stderr | 8 + .../ui/did_you_mean/recursion_limit.stderr | 60 +- src/test/ui/dst/dst-bad-deep.stderr | 12 +- .../dst/dst-object-from-unsized-type.stderr | 4 +- .../entry-point/auxiliary/main_functions.rs | 1 + .../ui/entry-point/imported_main_conflict.rs | 7 + .../entry-point/imported_main_conflict.stderr | 18 + ...orted_main_const_fn_item_type_forbidden.rs | 12 + ...d_main_const_fn_item_type_forbidden.stderr | 17 + .../imported_main_const_forbidden.rs | 7 + .../imported_main_const_forbidden.stderr | 17 + .../imported_main_from_extern_crate.rs | 9 + .../imported_main_from_extern_crate.stderr | 10 + .../imported_main_from_inner_mod.rs | 9 + ...ed_main_unused_not_trigger_feature_gate.rs | 11 + src/test/ui/error-codes/E0063.rs | 2 - src/test/ui/error-codes/E0063.stderr | 8 +- src/test/ui/error-codes/E0106.stderr | 22 +- src/test/ui/error-codes/E0119.stderr | 2 +- src/test/ui/error-codes/E0128.stderr | 4 +- src/test/ui/error-codes/E0137.rs | 8 - src/test/ui/error-codes/E0137.stderr | 12 - src/test/ui/error-codes/E0275.stderr | 6 +- src/test/ui/error-codes/E0277-2.stderr | 18 +- src/test/ui/error-codes/E0277.stderr | 4 +- .../ui/error-codes/e0119/complex-impl.stderr | 2 +- .../e0119/conflict-with-std.stderr | 6 +- .../ui/error-codes/e0119/issue-23563.stderr | 2 +- .../ui/error-codes/e0119/issue-27403.stderr | 2 +- .../ui/error-codes/e0119/issue-28981.stderr | 2 +- .../ui/error-codes/e0119/so-37347311.stderr | 2 +- src/test/ui/export-fully-qualified.rs | 2 - src/test/ui/export-fully-qualified.stderr | 2 +- .../ui/extern/extern-types-unsized.stderr | 24 +- ...llow-unwind-when-calling-panic-directly.rs | 4 +- ...sue-64655-extern-rust-must-allow-unwind.rs | 4 +- src/test/ui/feature-gates/feature-gate-abi.rs | 26 +- .../ui/feature-gates/feature-gate-abi.stderr | 195 +- .../ui/feature-gates/feature-gate-const_fn.rs | 6 +- .../feature-gate-const_fn.stderr | 27 +- ...ate-default_type_parameter_fallback.stderr | 4 +- .../feature-gate-doc_notable_trait.rs | 4 + .../feature-gate-doc_notable_trait.stderr | 12 + .../feature-gate-doc_spotlight.rs | 4 - .../feature-gate-doc_spotlight.stderr | 12 - .../feature-gate-edition_macro_pats.rs | 8 - .../feature-gate-edition_macro_pats.stderr | 21 - ...ature-gate-generic_associated_types.stderr | 4 +- .../feature-gate-imported_main.rs | 6 + .../feature-gate-imported_main.stderr | 12 + .../feature-gate-in_band_lifetimes.stderr | 168 +- .../feature-gate-large-assignments.rs | 5 + .../feature-gate-large-assignments.stderr | 12 + .../feature-gates/feature-gate-link_args.rs | 17 - .../feature-gate-link_args.stderr | 30 - .../ui/feature-gates/feature-gate-main.rs | 2 - .../ui/feature-gates/feature-gate-main.stderr | 12 - .../feature-gate-min_const_fn.rs | 6 +- .../feature-gate-min_const_fn.stderr | 27 +- .../feature-gate-naked_functions.rs | 1 + .../feature-gate-naked_functions.stderr | 4 +- .../feature-gates/feature-gate-no_coverage.rs | 13 + .../feature-gate-no_coverage.stderr | 12 + .../feature-gate-non_ascii_idents.rs | 33 - .../feature-gate-non_ascii_idents.stderr | 120 - .../feature-gate-object_safe_for_dispatch.rs | 2 +- ...ature-gate-object_safe_for_dispatch.stderr | 6 +- ...ture-gate-overlapping_marker_traits.stderr | 2 +- .../feature-gate-pub_macro_rules.rs | 10 - .../feature-gate-pub_macro_rules.stderr | 39 - .../feature-gate-rustc-attrs-1.rs | 2 - .../feature-gate-rustc-attrs-1.stderr | 6 +- .../feature-gate-trivial_bounds.stderr | 6 +- .../feature-gate-unsized_fn_params.stderr | 4 +- .../feature-gate-unsized_locals.stderr | 4 +- .../ui/feature-gates/feature-gate-wasm_abi.rs | 7 + .../feature-gate-wasm_abi.stderr | 12 + ...sue-43106-gating-of-builtin-attrs-error.rs | 23 +- ...43106-gating-of-builtin-attrs-error.stderr | 111 +- .../issue-43106-gating-of-builtin-attrs.rs | 1 - ...issue-43106-gating-of-builtin-attrs.stderr | 416 +- .../feature-gates/thread-local-const-init.rs | 4 + .../thread-local-const-init.stderr | 13 + src/test/ui/{bad => fn}/bad-main.rs | 0 src/test/ui/{bad => fn}/bad-main.stderr | 0 .../issue-45729-unsafe-in-generator.rs | 0 .../issue-45729-unsafe-in-generator.stderr | 0 src/test/ui/generator/static-not-unpin.stderr | 2 + .../type-mismatch-signature-deduction.stderr | 6 +- .../gat-in-trait-path.rs | 3 +- .../gat-in-trait-path.stderr | 20 +- .../generic-associated-types/impl_bounds.rs | 3 + .../impl_bounds.stderr | 59 +- .../issue-67510-pass.rs | 3 +- .../issue-67510-pass.stderr | 20 +- .../issue-68641-check-gat-bounds.stderr | 4 +- .../issue-68642-broken-llvm-ir.stderr | 4 +- .../issue-68643-broken-mir.stderr | 4 +- .../issue-68644-codegen-selection.stderr | 4 +- .../issue-68645-codegen-fulfillment.stderr | 4 +- .../generic-associated-types/issue-70303.rs | 60 + .../generic-associated-types/issue-70304.rs | 63 + .../issue-70304.stderr | 15 + .../generic-associated-types/issue-71176.rs | 21 + .../issue-71176.stderr | 19 + .../issue-74824.stderr | 4 +- .../generic-associated-types/issue-76535.rs | 2 + .../issue-76535.stderr | 37 +- .../generic-associated-types/issue-78671.rs | 15 + .../issue-78671.stderr | 35 + .../generic-associated-types/issue-79422.rs | 3 +- .../issue-79422.stderr | 38 +- .../generic-associated-types/issue-79636-1.rs | 24 + .../issue-79636-1.stderr | 19 + .../generic-associated-types/issue-79636-2.rs | 18 + .../issue-79636-2.stderr | 19 + .../generic-associated-types/shadowing.stderr | 16 +- .../generic-associated-types/trait-objects.rs | 16 + .../trait-objects.stderr | 18 + .../bad-mid-path-type-params.rs | 0 .../bad-mid-path-type-params.stderr | 0 .../generic-function-item-where-type.rs | 6 + .../generic-function-item-where-type.stderr | 12 + .../generics/generic-non-trailing-defaults.rs | 6 +- .../generic-non-trailing-defaults.stderr | 8 +- .../generic-type-params-forward-mention.rs | 2 +- ...generic-type-params-forward-mention.stderr | 4 +- ...rrect-explicit-lifetime-name-needed.stderr | 22 +- .../ui/generics/wrong-number-of-args.stderr | 66 +- src/test/ui/hrtb/complex.rs | 28 + src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 6 +- src/test/ui/hygiene/trait_items.stderr | 3 + .../ui/impl-trait/auto-trait.full_tait.stderr | 2 +- .../ui/impl-trait/auto-trait.min_tait.stderr | 2 +- .../ui/impl-trait/bound-normalization-fail.rs | 1 - .../bound-normalization-fail.stderr | 20 +- src/test/ui/impl-trait/equality2.stderr | 6 +- .../impl-generic-mismatch-ab.stderr | 6 +- .../impl-trait-in-bindings-issue-73003.rs | 0 .../impl-trait-in-bindings-issue-73003.stderr | 0 .../impl-trait-in-bindings.rs | 0 .../impl-trait-in-bindings.stderr | 0 .../impl-trait/issue-55872-1.full_tait.stderr | 18 +- .../impl-trait/issue-55872-1.min_tait.stderr | 16 +- src/test/ui/impl-trait/issue-55872-1.rs | 1 - .../impl-trait/issue-55872-2.full_tait.stderr | 6 +- .../impl-trait/issue-55872-2.min_tait.stderr | 4 +- src/test/ui/impl-trait/issue-55872-2.rs | 1 - .../impl-trait/issue-55872.full_tait.stderr | 4 +- .../ui/impl-trait/issue-55872.min_tait.stderr | 2 +- src/test/ui/impl-trait/issue-55872.rs | 1 - .../issues/issue-70877.full_tait.stderr | 8 +- .../issues/issue-70877.min_tait.stderr | 8 +- ...sue-83929-impl-trait-in-generic-default.rs | 12 + ...83929-impl-trait-in-generic-default.stderr | 15 + .../negative-reasoning.full_tait.stderr | 2 +- .../negative-reasoning.min_tait.stderr | 2 +- .../no-method-suggested-traits.stderr | 8 + ...rojection-mismatch-in-impl-where-clause.rs | 20 + ...ction-mismatch-in-impl-where-clause.stderr | 15 + src/test/ui/impl-trait/trait_type.stderr | 7 +- src/test/ui/impl-trait/where-allowed.rs | 32 +- src/test/ui/impl-trait/where-allowed.stderr | 133 +- .../extern-prelude-extern-crate-fail.rs | 2 - .../extern-prelude-extern-crate-fail.stderr | 4 +- .../local-modularized-tricky-fail-2.rs | 56 +- .../local-modularized-tricky-fail-2.stderr | 63 +- .../local-modularized-tricky-fail-3.rs | 22 - .../local-modularized-tricky-fail-3.stderr | 43 - ....rs => local-modularized-tricky-pass-1.rs} | 0 .../local-modularized-tricky-pass-2.rs | 50 + src/test/ui/imports/tool-mod-child.rs | 7 + src/test/ui/imports/tool-mod-child.stderr | 28 + src/test/ui/inference/issue-81522.rs | 31 + src/test/ui/inference/issue-83606.rs | 10 + src/test/ui/inference/issue-83606.stderr | 11 + .../bad-intrinsic-monomorphization.rs | 0 .../bad-intrinsic-monomorphization.stderr | 0 src/test/ui/intrinsics/intrinsic-alignment.rs | 10 +- .../intrinsics/issue-84297-reifying-copy.rs | 9 + src/test/ui/issue-83639.rs | 6 + src/test/ui/issue-83639.stderr | 8 + src/test/ui/issue-85713-align-with-no-arg.rs | 6 + .../ui/issue-85713-align-with-no-arg.stderr | 15 + src/test/ui/issues/issue-13033.stderr | 2 +- src/test/ui/issues/issue-15487.rs | 13 - src/test/ui/issues/issue-18183.stderr | 4 +- src/test/ui/issues/issue-18400.stderr | 6 +- src/test/ui/issues/issue-20225.stderr | 21 +- src/test/ui/issues/issue-20413.stderr | 60 +- src/test/ui/issues/issue-21332.stderr | 7 +- src/test/ui/issues/issue-22872.stderr | 6 +- src/test/ui/issues/issue-23122-2.stderr | 6 +- src/test/ui/issues/issue-26812.rs | 2 +- src/test/ui/issues/issue-26812.stderr | 4 +- src/test/ui/issues/issue-27060-2.stderr | 2 +- src/test/ui/issues/issue-27060-rpass.rs | 8 +- src/test/ui/issues/issue-27060.rs | 14 +- src/test/ui/issues/issue-27060.stderr | 40 +- src/test/ui/issues/issue-2823.stderr | 8 - src/test/ui/issues/issue-28568.stderr | 2 +- src/test/ui/issues/issue-3214.rs | 2 - src/test/ui/issues/issue-3214.stderr | 8 +- src/test/ui/issues/issue-33941.stderr | 12 +- src/test/ui/issues/issue-35869.stderr | 20 +- src/test/ui/issues/issue-38821.stderr | 6 +- src/test/ui/issues/issue-39970.stderr | 8 +- src/test/ui/issues/issue-40827.stderr | 24 +- src/test/ui/issues/issue-41974.stderr | 2 +- src/test/ui/issues/issue-43189.stderr | 5 + src/test/ui/issues/issue-43355.stderr | 2 +- .../ui/issues/issue-43784-supertrait.stderr | 4 +- src/test/ui/issues/issue-44023.rs | 2 - src/test/ui/issues/issue-44023.stderr | 2 +- src/test/ui/issues/issue-45157.rs | 1 - src/test/ui/issues/issue-45157.stderr | 2 +- src/test/ui/issues/issue-47725.rs | 1 - src/test/ui/issues/issue-47725.stderr | 14 +- src/test/ui/issues/issue-48728.stderr | 2 +- src/test/ui/issues/issue-53251.rs | 2 - src/test/ui/issues/issue-53251.stderr | 8 +- src/test/ui/issues/issue-54044.rs | 1 - src/test/ui/issues/issue-54044.stderr | 6 +- src/test/ui/issues/issue-56175.stderr | 10 + src/test/ui/issues/issue-5883.rs | 6 +- src/test/ui/issues/issue-5883.stderr | 23 +- src/test/ui/issues/issue-60622.rs | 2 - src/test/ui/issues/issue-60622.stderr | 8 +- .../issue-69225-SCEVAddExpr-wrap-flag.rs | 1 + src/test/ui/issues/issue-69725.stderr | 8 - src/test/ui/issues/issue-7013.stderr | 6 +- src/test/ui/issues/issue-78720.rs | 2 +- src/test/ui/issues/issue-78720.stderr | 14 +- .../ui/issues/issue-82833-slice-miscompile.rs | 1 - src/test/ui/issues/issue-83048.rs | 5 + src/test/ui/issues/issue-83048.stderr | 9 + src/test/ui/issues/issue-83924.fixed | 20 + src/test/ui/issues/issue-83924.rs | 20 + src/test/ui/issues/issue-83924.stderr | 25 + src/test/ui/iterators/array-of-ranges.rs | 11 +- src/test/ui/iterators/array-of-ranges.stderr | 102 - src/test/ui/iterators/array.rs | 5 +- src/test/ui/iterators/array.stderr | 36 - .../ui/iterators/into-iter-on-arrays-2018.rs | 39 + .../iterators/into-iter-on-arrays-2018.stderr | 42 + .../ui/iterators/into-iter-on-arrays-2021.rs | 33 + src/test/ui/iterators/ranges.stderr | 6 +- src/test/ui/iterators/string.stderr | 2 +- .../kindck/kindck-impl-type-params-2.stderr | 6 +- .../kindck/kindck-impl-type-params.nll.stderr | 52 +- .../ui/kindck/kindck-impl-type-params.stderr | 52 +- .../kindck-inherited-copy-bound.curr.stderr | 6 +- ...copy-bound.object_safe_for_dispatch.stderr | 6 +- src/test/ui/kinds-of-primitive-impl.rs | 3 - src/test/ui/kinds-of-primitive-impl.stderr | 6 +- .../issue-83737-binders-across-types.rs | 14 + .../issue-83737-erasing-bound-vars.rs | 14 + ...invalid-associated-type-supertrait-hrtb.rs | 8 + ...lid-associated-type-supertrait-hrtb.stderr | 9 + .../issue-83907-invalid-fn-like-path.rs | 7 + .../issue-83907-invalid-fn-like-path.stderr | 17 + src/test/ui/lifetimes/issue-84398.rs | 20 + src/test/ui/lifetimes/issue-84604.rs | 9 + ...th-anon-regions-one-is-struct-2.nll.stderr | 2 +- .../liveness-assign-imm-local-notes.stderr | 8 +- ...ime-used-in-debug-macro-issue-70152.stderr | 20 +- .../bad-extern-link-attrs.rs | 0 .../bad-extern-link-attrs.stderr | 0 src/test/ui/linkage-attr/invalid-link-args.rs | 14 - ...-detect-extern-generated-name-collision.rs | 2 + ...e-detect-local-generated-name-collision.rs | 3 +- ...tect-local-generated-name-collision.stderr | 2 +- src/test/ui/{bad => lint}/bad-lint-cap.rs | 0 src/test/ui/{bad => lint}/bad-lint-cap.stderr | 0 src/test/ui/{bad => lint}/bad-lint-cap2.rs | 0 .../ui/{bad => lint}/bad-lint-cap2.stderr | 0 src/test/ui/{bad => lint}/bad-lint-cap3.rs | 0 .../ui/{bad => lint}/bad-lint-cap3.stderr | 0 .../ui/lint/dead-code/lint-dead-code-2.rs | 4 +- src/test/ui/{ => lint}/fn_must_use.rs | 0 src/test/ui/{ => lint}/fn_must_use.stderr | 0 .../lint/issue-54538-unused-parens-lint.fixed | 1 - .../ui/lint/issue-54538-unused-parens-lint.rs | 1 - .../issue-54538-unused-parens-lint.stderr | 50 +- .../issue-67691-unused-field-in-or-pattern.rs | 1 - ...ue-67691-unused-field-in-or-pattern.stderr | 14 +- src/test/ui/lint/issue-83477.rs | 16 + src/test/ui/lint/issue-83477.stderr | 30 + src/test/ui/lint/lint-deref-nullptr.rs | 38 + src/test/ui/lint/lint-deref-nullptr.stderr | 68 + ...-non-snake-case-no-lowercase-equivalent.rs | 1 - .../lint/lint-nonstandard-style-unicode-1.rs | 1 - .../lint-nonstandard-style-unicode-1.stderr | 14 +- .../lint/lint-nonstandard-style-unicode-2.rs | 1 - .../lint-nonstandard-style-unicode-2.stderr | 4 +- .../lint/lint-nonstandard-style-unicode-3.rs | 1 - .../lint-nonstandard-style-unicode-3.stderr | 2 +- src/test/ui/lint/lint-stability-deprecated.rs | 1 - .../ui/lint/lint-stability-deprecated.stderr | 218 +- .../lint-confusable-idents.rs | 1 - .../lint-confusable-idents.stderr | 6 +- .../lint-mixed-script-confusables-2.rs | 1 - .../lint-mixed-script-confusables.rs | 1 - .../lint-mixed-script-confusables.stderr | 8 +- .../lint-non-ascii-idents.rs | 1 - .../lint-non-ascii-idents.stderr | 8 +- .../lint-uncommon-codepoints.rs | 1 - .../lint-uncommon-codepoints.stderr | 8 +- src/test/ui/lint/special-upper-lower-cases.rs | 1 - .../ui/lint/special-upper-lower-cases.stderr | 8 +- src/test/ui/lint/unaligned_references.rs | 21 + src/test/ui/lint/unaligned_references.stderr | 36 +- .../unaligned_references_external_macro.rs | 3 +- ...unaligned_references_external_macro.stderr | 8 +- src/test/ui/lint/uninitialized-zeroed.rs | 1 - src/test/ui/lint/uninitialized-zeroed.stderr | 98 +- .../liveness-assign-imm-local-in-loop.rs | 2 +- .../liveness-assign-imm-local-in-loop.stderr | 2 +- .../liveness-assign-imm-local-in-op-eq.rs | 2 +- .../liveness-assign-imm-local-in-op-eq.stderr | 2 +- .../liveness-assign-imm-local-with-drop.rs | 2 +- ...liveness-assign-imm-local-with-drop.stderr | 2 +- .../liveness-assign-imm-local-with-init.rs | 2 +- ...liveness-assign-imm-local-with-init.stderr | 2 +- .../llvm-asm/llvm-asm-out-assign-imm.stderr | 2 +- src/test/ui/loops/loop-no-implicit-break.rs | 31 + .../ui/loops/loop-no-implicit-break.stderr | 47 + .../loops/loops-reject-duplicate-labels-2.rs | 1 - .../loops-reject-duplicate-labels-2.stderr | 16 +- .../ui/loops/loops-reject-duplicate-labels.rs | 1 - .../loops-reject-duplicate-labels.stderr | 16 +- src/test/ui/macros/attr-empty-expr.rs | 11 + src/test/ui/macros/attr-empty-expr.stderr | 20 + .../ui/macros/builtin-std-paths-fail.stderr | 40 +- src/test/ui/{ => macros}/concat-rpass.rs | 0 src/test/ui/macros/edition-macro-pats.rs | 8 +- src/test/ui/macros/issue-83340.rs | 8 + src/test/ui/macros/issue-83340.stderr | 8 + src/test/ui/macros/issue-83344.rs | 6 + src/test/ui/macros/issue-83344.stderr | 8 + .../ui/macros/issue-84195-lint-anon-const.rs | 14 + .../macros/issue-84195-lint-anon-const.stderr | 20 + .../macros/issue-85432-ungated-attr-macro.rs | 30 + .../macro-export-on-modularized-macros.rs | 11 - .../macro-export-on-modularized-macros.stderr | 14 - .../macro-or-patterns-back-compat.fixed | 24 + .../macros/macro-or-patterns-back-compat.rs | 24 + .../macro-or-patterns-back-compat.stderr | 32 + ...acro-pat-pattern-followed-by-or-in-2021.rs | 20 + ...-pat-pattern-followed-by-or-in-2021.stderr | 26 + .../macro-pat-pattern-followed-by-or.rs | 20 + .../macro-pat2021-pattern-followed-by-or.rs | 22 + ...acro-pat2021-pattern-followed-by-or.stderr | 26 + src/test/ui/macros/none-delim-lookahead.rs | 15 + src/test/ui/macros/pub-macro-rules-fail.rs | 28 - .../ui/macros/pub-macro-rules-fail.stderr | 48 - src/test/ui/macros/pub-macro-rules.rs | 20 - src/test/ui/main-wrong-location.rs | 2 +- src/test/ui/main-wrong-location.stderr | 4 +- src/test/ui/match/issue-72680.rs | 2 - src/test/ui/match/issue-82392.rs | 9 + src/test/ui/match/issue-82392.stdout | 20 + src/test/ui/match/issue-84434.rs | 18 + .../methods/method-call-lifetime-args-fail.rs | 2 - .../method-call-lifetime-args-fail.stderr | 72 +- .../issue-83499-input-output-iteration-ice.rs | 10 + ...ue-83499-input-output-iteration-ice.stderr | 21 + src/test/ui/mismatched_types/E0053.stderr | 7 +- .../issue-74918-missing-lifetime.rs | 2 +- .../issue-74918-missing-lifetime.stderr | 18 +- .../trait-impl-fn-incompatibility.stderr | 7 +- src/test/ui/multiple-main-2.rs | 9 - src/test/ui/multiple-main-2.stderr | 14 - src/test/ui/multiple-main-3.rs | 11 - src/test/ui/multiple-main-3.stderr | 14 - .../mut-pattern-internal-mutability.stderr | 2 +- src/test/ui/mut/mutable-enum-indirect.stderr | 6 +- .../ui/never_type/defaulted-never-note.rs | 4 +- .../ui/never_type/defaulted-never-note.stderr | 4 +- .../never-from-impl-is-reserved.stderr | 2 +- .../escape-argument-callee.stderr | 2 +- .../escape-argument.stderr | 2 +- ...pagate-approximated-fail-no-postdom.stderr | 2 +- .../propagate-approximated-ref.stderr | 2 +- ...er-to-static-comparing-against-free.stderr | 4 +- ...oximated-shorter-to-static-no-bound.stderr | 2 +- ...mated-shorter-to-static-wrong-bound.stderr | 2 +- .../propagate-approximated-val.stderr | 2 +- .../propagate-despite-same-free-region.stderr | 2 +- ...ail-to-approximate-longer-no-bounds.stderr | 2 +- ...-to-approximate-longer-wrong-bounds.stderr | 2 +- .../return-wrong-bound-region.stderr | 2 +- src/test/ui/nll/issue-51268.rs | 2 - src/test/ui/nll/issue-51268.stderr | 2 +- src/test/ui/nll/issue-57100.rs | 1 - src/test/ui/nll/issue-57100.stderr | 4 +- ...ram-closure-approximate-lower-bound.stderr | 4 +- src/test/ui/no-send-res-ports.stderr | 12 +- src/test/ui/no_send-enum.stderr | 6 +- src/test/ui/no_share-enum.stderr | 6 +- src/test/ui/non-copyable-void.stderr | 8 - .../ui/non-ice-error-on-worker-io-fail.rs | 1 - src/test/ui/noncopyable-class.stderr | 8 - src/test/ui/or-patterns/already-bound-name.rs | 2 - .../ui/or-patterns/already-bound-name.stderr | 30 +- src/test/ui/or-patterns/basic-switch.rs | 2 - src/test/ui/or-patterns/basic-switchint.rs | 2 - src/test/ui/or-patterns/bindings-runpass-1.rs | 2 - src/test/ui/or-patterns/bindings-runpass-2.rs | 2 - src/test/ui/or-patterns/box-patterns.rs | 1 - .../ui/or-patterns/consistent-bindings.rs | 2 - src/test/ui/or-patterns/const-fn.rs | 1 - .../exhaustiveness-non-exhaustive.rs | 1 - .../exhaustiveness-non-exhaustive.stderr | 6 +- .../ui/or-patterns/exhaustiveness-pass.rs | 1 - .../exhaustiveness-unreachable-pattern.rs | 1 - .../exhaustiveness-unreachable-pattern.stderr | 54 +- .../feature-gate-or_patterns-leading-for.rs | 8 - ...eature-gate-or_patterns-leading-for.stderr | 12 - .../feature-gate-or_patterns-leading-let.rs | 9 - ...eature-gate-or_patterns-leading-let.stderr | 18 - .../or-patterns/feature-gate-or_patterns.rs | 54 - .../feature-gate-or_patterns.stderr | 186 - .../ui/or-patterns/fn-param-wrap-parens.fixed | 1 - .../ui/or-patterns/fn-param-wrap-parens.rs | 1 - .../or-patterns/fn-param-wrap-parens.stderr | 2 +- src/test/ui/or-patterns/for-loop.rs | 2 - src/test/ui/or-patterns/if-let-while-let.rs | 2 - src/test/ui/or-patterns/inconsistent-modes.rs | 1 - .../ui/or-patterns/inconsistent-modes.stderr | 18 +- .../issue-67514-irrefutable-param.rs | 2 - .../issue-68785-irrefutable-param-with-at.rs | 2 - ...ve-been-expanded-earlier-non-exhaustive.rs | 2 - ...een-expanded-earlier-non-exhaustive.stderr | 4 +- ...69875-should-have-been-expanded-earlier.rs | 2 - ...ssue-70413-no-unreachable-pat-and-guard.rs | 1 - src/test/ui/or-patterns/let-pattern.rs | 2 - src/test/ui/or-patterns/macro-pat.rs | 2 - .../mismatched-bindings-async-fn.rs | 2 - .../mismatched-bindings-async-fn.stderr | 8 +- src/test/ui/or-patterns/missing-bindings.rs | 1 - .../ui/or-patterns/missing-bindings.stderr | 52 +- src/test/ui/or-patterns/mix-with-wild.rs | 1 - .../ui/or-patterns/multiple-pattern-typo.rs | 2 +- .../or-patterns-binding-type-mismatch.rs | 2 - .../or-patterns-binding-type-mismatch.stderr | 44 +- .../or-patterns-default-binding-modes.rs | 1 - .../or-patterns/or-patterns-syntactic-fail.rs | 2 - .../or-patterns-syntactic-fail.stderr | 10 +- .../or-patterns/or-patterns-syntactic-pass.rs | 2 - .../ui/or-patterns/remove-leading-vert.fixed | 1 - .../ui/or-patterns/remove-leading-vert.rs | 1 - .../ui/or-patterns/remove-leading-vert.stderr | 42 +- .../ui/or-patterns/search-via-bindings.rs | 2 - src/test/ui/or-patterns/slice-patterns.rs | 2 - src/test/ui/or-patterns/struct-like.rs | 2 - .../packed-struct-address-of-element.rs | 2 +- .../packed-struct-borrow-element-64bit.rs | 17 + .../packed-struct-borrow-element-64bit.stderr | 13 + .../ui/packed/packed-struct-borrow-element.rs | 10 +- .../packed-struct-borrow-element.stderr | 23 + .../ui/panic-runtime/two-panic-runtimes.rs | 1 - .../unwind-tables-panic-required.rs | 11 - .../unwind-tables-target-required.rs | 1 - src/test/ui/{bad => parser}/bad-crate-name.rs | 0 .../ui/{bad => parser}/bad-crate-name.stderr | 0 src/test/ui/parser/duplicate-visibility.rs | 2 - .../ui/parser/duplicate-visibility.stderr | 2 +- .../ui/{issues => parser}/issue-48508-aux.rs | 0 src/test/ui/{issues => parser}/issue-48508.rs | 1 - src/test/ui/parser/issue-63116.stderr | 6 +- .../issue-66357-unexpected-unreachable.rs | 2 - .../issue-66357-unexpected-unreachable.stderr | 4 +- ...68000-unicode-ident-after-missing-comma.rs | 0 ...0-unicode-ident-after-missing-comma.stderr | 0 src/test/ui/parser/issue-84117.rs | 9 + src/test/ui/parser/issue-84117.stderr | 49 + src/test/ui/parser/issue-8537.stderr | 2 +- ...ultibyte-char-use-seperator-issue-80134.rs | 2 - ...byte-char-use-seperator-issue-80134.stderr | 27 +- src/test/ui/parser/unicode-quote-chars.rs | 2 - src/test/ui/parser/unicode-quote-chars.stderr | 6 +- src/test/ui/parser/use-unclosed-brace.rs | 12 + src/test/ui/parser/use-unclosed-brace.stderr | 27 + .../variadic-ffi-semantic-restrictions.rs | 1 + .../variadic-ffi-semantic-restrictions.stderr | 68 +- .../or-patterns-box-patterns.rs | 1 - .../or-patterns-slice-patterns.rs | 1 - .../pattern/bindings-after-at/or-patterns.rs | 1 - .../pat-at-same-name-both.rs | 1 - .../pat-at-same-name-both.stderr | 20 +- .../ui/{issues => pattern}/issue-10392.rs | 0 .../borrowck-move-ref-pattern.stderr | 4 +- .../usefulness/refutable-pattern-errors.rs | 2 - .../refutable-pattern-errors.stderr | 4 +- src/test/ui/phantom-auto-trait.stderr | 38 +- .../privacy/associated-item-privacy-trait.rs | 2 - .../associated-item-privacy-trait.stderr | 60 +- src/test/ui/privacy/privacy-ns1.stderr | 3 + src/test/ui/privacy/privacy-ns2.stderr | 6 + src/test/ui/proc-macro/attr-complex-fn.stdout | 38 +- .../proc-macro/attribute-after-derive.stdout | 50 +- .../ui/proc-macro/auxiliary/issue-75801.rs | 13 + .../ui/proc-macro/auxiliary/issue-79825.rs | 14 + .../ui/proc-macro/auxiliary/issue-83510.rs | 19 + .../proc-macro/auxiliary/multiple-derives.rs | 22 + .../auxiliary/nested-macro-rules.rs | 9 +- .../auxiliary/nonterminal-recollect-attr.rs | 4 +- .../ui/proc-macro/auxiliary/test-macros.rs | 33 +- src/test/ui/proc-macro/cfg-eval-inner.rs | 39 + src/test/ui/proc-macro/cfg-eval-inner.stdout | 247 + src/test/ui/proc-macro/cfg-eval.rs | 9 +- src/test/ui/proc-macro/cfg-eval.stdout | 69 +- src/test/ui/proc-macro/derive-expand-order.rs | 14 + .../ui/proc-macro/derive-expand-order.stdout | 5 + .../ui/proc-macro/expand-to-derive.stdout | 47 +- src/test/ui/proc-macro/generate-mod.stderr | 12 +- .../group-compat-hack/group-compat-hack.rs | 9 +- .../group-compat-hack.stderr | 43 +- .../group-compat-hack.stdout | 13 +- .../js-sys-0.3.40/src/lib.rs | 7 + src/test/ui/proc-macro/inner-attrs.rs | 75 +- src/test/ui/proc-macro/inner-attrs.stderr | 56 + src/test/ui/proc-macro/inner-attrs.stdout | 931 +- src/test/ui/proc-macro/issue-36935.stderr | 16 +- .../issue-59191-replace-root-with-fn.rs | 1 - .../issue-59191-replace-root-with-fn.stderr | 13 +- src/test/ui/proc-macro/issue-75801.rs | 19 + src/test/ui/proc-macro/issue-75801.stderr | 12 + .../proc-macro/issue-75930-derive-cfg.stdout | 275 +- .../issue-78675-captured-inner-attrs.stdout | 21 +- src/test/ui/proc-macro/issue-79825.rs | 10 + src/test/ui/proc-macro/issue-81555.rs | 15 + .../issue-83469-global-alloc-invalid-stmt.rs | 10 + ...sue-83469-global-alloc-invalid-stmt.stderr | 8 + src/test/ui/proc-macro/issue-83510.rs | 11 + src/test/ui/proc-macro/issue-83510.stderr | 38 + .../proc-macro/macro-rules-derive-cfg.stdout | 73 +- src/test/ui/proc-macro/meta-macro-hygiene.rs | 1 - .../ui/proc-macro/meta-macro-hygiene.stdout | 3 +- .../ui/proc-macro/nested-derive-cfg.stdout | 47 +- src/test/ui/proc-macro/nested-macro-rules.rs | 10 +- .../ui/proc-macro/nested-macro-rules.stdout | 52 +- src/test/ui/proc-macro/nodelim-groups.stdout | 1 + .../proc-macro/nonterminal-recollect-attr.rs | 4 + .../nonterminal-recollect-attr.stdout | 72 + src/test/ui/proc-macro/simple-tuple.rs | 19 + src/test/ui/proc-macro/simple-tuple.stdout | 79 + src/test/ui/proc-macro/trait-fn-args-2015.rs | 2 + src/test/ui/proc-macro/weird-braces.stdout | 196 +- src/test/ui/recursion/issue-83150.rs | 11 + src/test/ui/recursion/issue-83150.stderr | 8 + .../recursion/recursive-requirements.stderr | 18 +- src/test/ui/regions/regions-enum-not-wf.rs | 2 - .../ui/regions/regions-enum-not-wf.stderr | 6 +- .../ui/regions/regions-name-undeclared.stderr | 40 +- src/test/ui/reify-intrinsic.rs | 10 +- src/test/ui/reify-intrinsic.stderr | 11 +- src/test/ui/resolve/auxiliary/issue-80079.rs | 18 + .../ui/{bad => resolve}/bad-env-capture.rs | 0 .../{bad => resolve}/bad-env-capture.stderr | 0 .../ui/{bad => resolve}/bad-env-capture2.rs | 0 .../{bad => resolve}/bad-env-capture2.stderr | 0 .../ui/{bad => resolve}/bad-env-capture3.rs | 0 .../{bad => resolve}/bad-env-capture3.stderr | 0 src/test/ui/{bad => resolve}/bad-expr-path.rs | 0 .../ui/{bad => resolve}/bad-expr-path.stderr | 0 .../ui/{bad => resolve}/bad-expr-path2.rs | 0 .../ui/{bad => resolve}/bad-expr-path2.stderr | 0 src/test/ui/{bad => resolve}/bad-module.rs | 0 .../ui/{bad => resolve}/bad-module.stderr | 0 .../{bad => resolve}/bad-type-env-capture.rs | 0 .../bad-type-env-capture.stderr | 0 src/test/ui/resolve/issue-3907.stderr | 5 +- src/test/ui/resolve/issue-5035-2.stderr | 4 +- src/test/ui/resolve/issue-5035.stderr | 14 +- src/test/ui/resolve/issue-80079.rs | 12 + src/test/ui/resolve/issue-80079.stderr | 9 + src/test/ui/resolve/issue-81508.rs | 22 + src/test/ui/resolve/issue-81508.stderr | 21 + src/test/ui/resolve/issue-82865.rs | 13 + src/test/ui/resolve/issue-82865.stderr | 21 + .../ui/{ => resolve}/no-implicit-prelude.rs | 0 .../{ => resolve}/no-implicit-prelude.stderr | 0 ...xed-closure-sugar-nonexistent-trait.stderr | 5 +- .../rfc-2091-track-caller/error-with-naked.rs | 1 + .../error-with-naked.stderr | 4 +- .../std-panic-locations.rs | 5 - .../regions-enum-not-wf.rs | 2 - .../regions-enum-not-wf.stderr | 6 +- .../crate_name_nonascii_forbidden-1.rs | 2 - .../crate_name_nonascii_forbidden-1.stderr | 2 +- .../crate_name_nonascii_forbidden-2.rs | 1 - .../crate_name_nonascii_forbidden-2.stderr | 2 +- .../extern_block_nonascii_forbidden.rs | 9 + .../extern_block_nonascii_forbidden.stderr | 34 + src/test/ui/rfc-2457/idents-normalized.rs | 1 - .../rfc-2457/mod_file_nonascii_forbidden.rs | 2 - .../mod_file_nonascii_forbidden.stderr | 6 +- .../mod_file_nonascii_with_path_allowed.rs | 1 - .../rfc-2457/mod_inline_nonascii_allowed.rs | 1 - .../rfc-2457/no_mangle_nonascii_forbidden.rs | 2 - .../no_mangle_nonascii_forbidden.stderr | 2 +- .../proc-macro-cannot-be-used.rs | 1 + .../proc-macro-cannot-be-used.stderr | 58 +- .../rfc-2632-const-trait-impl/assoc-type.rs | 1 - .../call-const-trait-method-fail.rs | 1 - .../call-const-trait-method-fail.stderr | 2 +- .../call-const-trait-method-pass.rs | 1 - .../call-generic-method-chain.rs | 2 +- .../call-generic-method-dup-bound.rs | 2 +- .../call-generic-method-fail.rs | 2 +- .../call-generic-method-nonconst-opt-out.rs | 2 +- .../call-generic-method-nonconst.rs | 1 - .../call-generic-method-pass.rs | 2 +- .../const-and-non-const-impl.stderr | 4 +- .../const-trait-bound-opt-out/feature-gate.rs | 2 +- .../generic-bound.rs | 2 +- .../hir-const-check.rs | 2 +- .../stability.stderr | 3 +- src/test/ui/rfc1623.nll.stderr | 6 +- .../rust-2018/trait-import-suggestions.stderr | 6 + .../ui/rustdoc/check-doc-alias-attr.stderr | 4 +- src/test/ui/sanitize/address.rs | 2 +- src/test/ui/sanitize/hwaddress.rs | 5 +- src/test/ui/sanitize/leak.rs | 2 +- src/test/ui/sanitize/memory.rs | 2 +- src/test/ui/sanitize/unsupported-target.rs | 3 +- .../ui/sanitize/unsupported-target.stderr | 2 +- ...point-at-arbitrary-self-type-method.stderr | 5 + ...at-arbitrary-self-type-trait-method.stderr | 5 + .../ui/shadowed/shadowed-trait-methods.stderr | 3 + ...intrinsic-generic-arithmetic-saturating.rs | 1 - ...insic-generic-arithmetic-saturating.stderr | 4 +- src/test/ui/simd/simd-intrinsic-float-math.rs | 27 +- .../simd/simd-intrinsic-generic-reduction.rs | 1 - .../simd-type-generic-monomorphisation.rs | 1 - src/test/ui/simd/simd-type.rs | 1 - src/test/ui/simd/simd-type.stderr | 12 +- src/test/ui/single-primitive-inherent-impl.rs | 2 - .../ui/single-primitive-inherent-impl.stderr | 2 +- ...afult-generic-associated-type-bound.stderr | 4 +- .../defaultimpl/specialization-wfcheck.stderr | 4 +- src/test/ui/specialization/issue-33017.rs | 45 + src/test/ui/specialization/issue-33017.stderr | 17 + .../ui/specialization/issue-38091-2.stderr | 6 +- src/test/ui/specialization/issue-39448.rs | 2 +- src/test/ui/specialization/issue-39448.stderr | 12 +- src/test/ui/specialization/issue-51892.rs | 19 + src/test/ui/specialization/issue-51892.stderr | 10 + src/test/ui/specialization/issue-52050.stderr | 2 +- .../issue-68830-spurious-diagnostics.rs | 23 + .../issue-68830-spurious-diagnostics.stderr | 9 + .../repeated_projection_type.stderr | 2 +- ...specialization-feature-gate-overlap.stderr | 2 +- .../specialization-overlap.stderr | 8 +- .../generics-default-stability-where.rs | 1 - .../generics-default-stability-where.stderr | 2 +- .../generics-default-stability.rs | 1 - .../generics-default-stability.stderr | 142 +- src/test/ui/{bad => static}/bad-const-type.rs | 0 .../ui/{bad => static}/bad-const-type.stderr | 0 .../{issues => structs-enums}/issue-1701.rs | 0 .../structure-constructor-type-mismatch.rs | 2 - ...structure-constructor-type-mismatch.stderr | 30 +- src/test/ui/substs-ppaux.normal.stderr | 6 +- src/test/ui/substs-ppaux.verbose.stderr | 6 +- ...adt-param-with-implicit-sized-bound.stderr | 2 +- src/test/ui/suggestions/as-ref-2.fixed | 13 + src/test/ui/suggestions/as-ref-2.rs | 13 + src/test/ui/suggestions/as-ref-2.stderr | 23 + src/test/ui/suggestions/as-ref.rs | 35 +- src/test/ui/suggestions/as-ref.stderr | 78 +- .../expected-boxed-future-isnt-pinned.stderr | 2 + .../import-trait-for-method-call.rs | 16 + .../import-trait-for-method-call.stderr | 36 + src/test/ui/suggestions/into-str.stderr | 1 + src/test/ui/suggestions/issue-82361.stderr | 8 +- src/test/ui/suggestions/issue-83892.fixed | 11 + src/test/ui/suggestions/issue-83892.rs | 11 + src/test/ui/suggestions/issue-83892.stderr | 14 + src/test/ui/suggestions/issue-83943.fixed | 9 + src/test/ui/suggestions/issue-83943.rs | 9 + src/test/ui/suggestions/issue-83943.stderr | 18 + .../missing-lifetimes-in-signature.nll.stderr | 92 - .../missing-lifetimes-in-signature.rs | 7 +- .../missing-lifetimes-in-signature.stderr | 107 +- .../missing-lifetime-specifier.stderr | 48 +- src/test/ui/suggestions/path-by-value.stderr | 4 +- src/test/ui/suggestions/path-display.stderr | 4 +- .../suggestions/restrict-type-argument.stderr | 24 +- src/test/ui/symbol-names/basic.legacy.stderr | 4 +- src/test/ui/symbol-names/impl1.legacy.stderr | 24 +- src/test/ui/symbol-names/impl1.rs | 1 - src/test/ui/symbol-names/impl1.stderr | 26 - src/test/ui/symbol-names/impl1.v0.stderr | 24 +- .../ui/symbol-names/issue-60925.legacy.stderr | 10 +- src/test/ui/symbol-names/issue-60925.rs | 1 - src/test/ui/symbol-names/issue-60925.stderr | 20 - .../ui/symbol-names/issue-60925.v0.stderr | 6 +- .../ui/symbol-names/issue-75326.legacy.stderr | 6 +- src/test/ui/symbol-names/issue-75326.rs | 1 - .../ui/symbol-names/issue-75326.v0.stderr | 6 +- .../ui/test-attrs/test-main-not-dead-attr.rs | 4 +- .../test-runner-hides-buried-main.rs | 4 +- .../ui/trait-impl-bound-suggestions.fixed | 2 +- .../ui/trait-impl-bound-suggestions.stderr | 4 +- src/test/ui/traits/alias/issue-83613.rs | 13 + src/test/ui/traits/alias/issue-83613.stderr | 23 + .../suggest-trait-alias-instead-of-type.fixed | 13 + .../suggest-trait-alias-instead-of-type.rs | 13 + ...suggest-trait-alias-instead-of-type.stderr | 14 + .../associated_type_bound/issue-51446.rs | 34 + .../bad-method-typaram-kind.rs | 0 .../bad-method-typaram-kind.stderr | 4 +- src/test/ui/{bad => traits}/bad-sized.rs | 0 src/test/ui/{bad => traits}/bad-sized.stderr | 0 .../ui/traits/bound/not-on-bare-trait.stderr | 4 +- .../ui/traits/cycle-cache-err-60010.stderr | 18 +- .../ui/traits/inductive-overflow/lifetime.rs | 3 +- .../traits/inductive-overflow/lifetime.stderr | 6 +- .../inductive-overflow/simultaneous.stderr | 6 +- .../inductive-overflow/supertrait.stderr | 6 +- .../inductive-overflow/two-traits.stderr | 4 +- .../traits/issue-33140-hack-boundaries.stderr | 14 +- src/test/ui/traits/issue-33140.stderr | 4 +- src/test/ui/{issues => traits}/issue-78372.rs | 0 .../ui/{issues => traits}/issue-78372.stderr | 0 src/test/ui/traits/item-privacy.stderr | 3 + ...licitly-unimplemented-error-message.stderr | 8 - .../negated-auto-traits-error.stderr | 12 +- .../rely-on-negative-impl-in-coherence.stderr | 2 +- ...lap-not-permitted-for-builtin-trait.stderr | 2 +- .../coherence-conflict.stderr | 2 +- .../ui/traits/suggest-where-clause.stderr | 10 +- ...rrect-variant-form-through-alias-caught.rs | 2 - ...t-variant-form-through-alias-caught.stderr | 10 +- .../bounds-are-checked-2.full_tait.stderr | 4 +- .../bounds-are-checked-2.min_tait.stderr | 4 +- ...eric_duplicate_param_use5.full_tait.stderr | 8 +- ...neric_duplicate_param_use5.min_tait.stderr | 8 +- ...eric_duplicate_param_use6.full_tait.stderr | 4 +- ...neric_duplicate_param_use6.min_tait.stderr | 4 +- ...eric_duplicate_param_use8.full_tait.stderr | 4 +- ...neric_duplicate_param_use8.min_tait.stderr | 4 +- ...eric_duplicate_param_use9.full_tait.stderr | 8 +- ...neric_duplicate_param_use9.min_tait.stderr | 8 +- ...generic_underconstrained2.full_tait.stderr | 8 +- .../generic_underconstrained2.min_tait.stderr | 8 +- ...ncoherent-assoc-imp-trait.full_tait.stderr | 2 +- ...incoherent-assoc-imp-trait.min_tait.stderr | 2 +- .../issue-52843.full_tait.stderr | 4 +- .../issue-52843.min_tait.stderr | 4 +- .../issue-53598.full_tait.stderr | 4 +- .../issue-53598.min_tait.stderr | 2 +- .../ui/type-alias-impl-trait/issue-53598.rs | 1 - .../issue-57700.full_tait.stderr | 4 +- .../issue-57700.min_tait.stderr | 2 +- .../ui/type-alias-impl-trait/issue-57700.rs | 1 - .../issue-63279.full_tait.stderr | 6 +- .../issue-63279.min_tait.stderr | 6 +- src/test/ui/type/type-check-defaults.stderr | 4 +- src/test/ui/{issues => typeck}/issue-65611.rs | 2 +- .../ui/{issues => typeck}/issue-65611.stderr | 0 src/test/ui/typeck/issue-75883.rs | 22 + src/test/ui/typeck/issue-75883.stderr | 52 + src/test/ui/typeck/issue-80779.rs | 13 + src/test/ui/typeck/issue-80779.stderr | 21 + ...ssue-83621-placeholder-static-in-extern.rs | 7 + ...-83621-placeholder-static-in-extern.stderr | 9 + src/test/ui/typeck/issue-84831.rs | 9 + src/test/ui/typeck/issue-84831.stderr | 26 + ...ck-default-trait-impl-negation-sync.stderr | 12 +- ...ypeck-default-trait-impl-send-param.stderr | 4 +- .../typeck/typeck-unsafe-always-share.stderr | 6 +- src/test/ui/typeof/type_mismatch.rs | 9 + src/test/ui/typeof/type_mismatch.stderr | 23 + src/test/ui/union/union-deref.rs | 1 - src/test/ui/union/union-deref.stderr | 12 +- src/test/ui/union/union-derive-clone.stderr | 8 - src/test/ui/union/union-derive.stderr | 36 +- src/test/ui/union/union-sized-field.stderr | 6 +- src/test/ui/unique-object-noncopyable.stderr | 8 - src/test/ui/unique-pinned-nocopy.stderr | 8 - ...fe-op-in-let-under-unsafe-under-closure.rs | 25 + ...c-2585-safe_packed_borrows-in-unsafe-fn.rs | 67 - ...85-safe_packed_borrows-in-unsafe-fn.stderr | 60 - .../issue-50940-with-feature.stderr | 6 +- .../ui/unsized-locals/unsized-exprs.stderr | 12 +- .../return-unsized-from-trait-method.rs | 2 - .../return-unsized-from-trait-method.stderr | 2 +- .../ui/unsized/unsized-bare-typaram.stderr | 2 +- src/test/ui/unsized/unsized-enum.stderr | 2 +- src/test/ui/unsized/unsized-enum2.stderr | 32 +- src/test/ui/unsized/unsized-fn-arg.fixed | 6 + src/test/ui/unsized/unsized-fn-arg.rs | 6 + src/test/ui/unsized/unsized-fn-arg.stderr | 17 + .../unsized-inherent-impl-self-type.stderr | 2 +- src/test/ui/unsized/unsized-struct.stderr | 10 +- .../unsized-trait-impl-self-type.stderr | 2 +- .../unsized-trait-impl-trait-arg.stderr | 2 +- .../ui/{ => unsized}/unsized-tuple-impls.rs | 0 src/test/ui/{ => unsized}/unsized.rs | 0 src/test/ui/{ => unsized}/unsized2.rs | 0 src/test/ui/{ => unsized}/unsized3-rpass.rs | 0 src/test/ui/{ => unsized}/unsized3.rs | 0 src/test/ui/{ => unsized}/unsized3.stderr | 36 +- src/test/ui/{ => unsized}/unsized5.rs | 0 src/test/ui/{ => unsized}/unsized5.stderr | 8 +- src/test/ui/{ => unsized}/unsized6.rs | 0 src/test/ui/{ => unsized}/unsized6.stderr | 34 +- src/test/ui/{ => unsized}/unsized7.rs | 0 src/test/ui/{ => unsized}/unsized7.stderr | 2 +- .../unused/unused-doc-comments-for-macros.rs | 17 + .../unused-doc-comments-for-macros.stderr | 31 + src/test/ui/{ => unused}/useless-comment.rs | 0 .../ui/{ => unused}/useless-comment.stderr | 0 src/test/ui/unwind-no-uwtable.rs | 34 + src/test/ui/utf8_idents-rpass.rs | 2 - src/test/ui/utf8_idents.rs | 13 +- src/test/ui/utf8_idents.stderr | 47 - src/test/ui/wf/wf-enum-bound.stderr | 4 +- .../wf/wf-enum-fields-struct-variant.stderr | 4 +- src/test/ui/wf/wf-enum-fields.stderr | 4 +- src/test/ui/wf/wf-fn-where-clause.stderr | 4 +- src/test/ui/wf/wf-in-fn-arg.stderr | 4 +- src/test/ui/wf/wf-in-fn-ret.stderr | 4 +- src/test/ui/wf/wf-in-fn-type-arg.stderr | 4 +- src/test/ui/wf/wf-in-fn-type-ret.stderr | 4 +- src/test/ui/wf/wf-in-fn-where-clause.stderr | 4 +- src/test/ui/wf/wf-in-obj-type-trait.stderr | 4 +- ...f-inherent-impl-method-where-clause.stderr | 4 +- .../wf/wf-inherent-impl-where-clause.stderr | 4 +- src/test/ui/wf/wf-struct-bound.stderr | 4 +- src/test/ui/wf/wf-struct-field.stderr | 4 +- .../wf/wf-trait-associated-type-bound.stderr | 4 +- src/test/ui/wf/wf-trait-bound.stderr | 4 +- src/test/ui/wf/wf-trait-superbound.stderr | 4 +- ...traints-are-local-for-inherent-impl.stderr | 4 +- ...onstraints-are-local-for-trait-impl.stderr | 4 +- src/test/ui/wrong-mul-method-signature.stderr | 21 +- src/tools/cargotest/main.rs | 50 +- .../clippy/.github/PULL_REQUEST_TEMPLATE.md | 5 +- .../clippy/.github/workflows/clippy_bors.yml | 13 +- src/tools/clippy/CHANGELOG.md | 181 +- src/tools/clippy/CONTRIBUTING.md | 30 +- src/tools/clippy/Cargo.toml | 4 +- src/tools/clippy/README.md | 2 +- src/tools/clippy/clippy_dev/src/fmt.rs | 4 +- .../src/{ra_setup.rs => ide_setup.rs} | 2 +- src/tools/clippy/clippy_dev/src/lib.rs | 18 +- src/tools/clippy/clippy_dev/src/main.rs | 8 +- src/tools/clippy/clippy_dev/src/new_lint.rs | 4 +- src/tools/clippy/clippy_lints/Cargo.toml | 5 +- .../src/absurd_extreme_comparisons.rs | 173 + .../clippy/clippy_lints/src/approx_const.rs | 2 +- .../clippy/clippy_lints/src/arithmetic.rs | 2 +- .../clippy/clippy_lints/src/as_conversions.rs | 3 +- .../clippy/clippy_lints/src/asm_syntax.rs | 2 +- .../src/assertions_on_constants.rs | 21 +- .../clippy/clippy_lints/src/assign_ops.rs | 11 +- .../clippy_lints/src/async_yields_async.rs | 4 +- .../clippy_lints/src/atomic_ordering.rs | 9 +- src/tools/clippy/clippy_lints/src/attrs.rs | 131 +- .../clippy_lints/src/await_holding_invalid.rs | 5 +- src/tools/clippy/clippy_lints/src/bit_mask.rs | 4 +- .../clippy_lints/src/blacklisted_name.rs | 2 +- .../src/blocks_in_if_conditions.rs | 11 +- .../src/bool_assert_comparison.rs | 75 + src/tools/clippy/clippy_lints/src/booleans.rs | 10 +- .../clippy/clippy_lints/src/bytecount.rs | 97 +- .../clippy_lints/src/cargo_common_metadata.rs | 13 +- ...se_sensitive_file_extension_comparisons.rs | 2 +- .../clippy_lints/src/casts/cast_lossless.rs | 6 +- .../src/casts/cast_possible_truncation.rs | 4 +- .../src/casts/cast_possible_wrap.rs | 4 +- .../src/casts/cast_precision_loss.rs | 4 +- .../src/casts/cast_ptr_alignment.rs | 9 +- .../clippy_lints/src/casts/cast_ref_to_mut.rs | 6 +- .../clippy_lints/src/casts/cast_sign_loss.rs | 15 +- .../clippy_lints/src/casts/char_lit_as_u8.rs | 7 +- .../src/casts/fn_to_numeric_cast.rs | 4 +- .../fn_to_numeric_cast_with_truncation.rs | 4 +- .../clippy/clippy_lints/src/casts/mod.rs | 5 +- .../clippy_lints/src/casts/ptr_as_ptr.rs | 13 +- .../src/casts/unnecessary_cast.rs | 22 +- .../clippy_lints/src/checked_conversions.rs | 35 +- .../clippy_lints/src/cognitive_complexity.rs | 8 +- .../clippy/clippy_lints/src/collapsible_if.rs | 8 +- .../clippy_lints/src/collapsible_match.rs | 32 +- .../clippy_lints/src/comparison_chain.rs | 14 +- src/tools/clippy/clippy_lints/src/copies.rs | 508 +- .../clippy/clippy_lints/src/copy_iterator.rs | 22 +- .../clippy/clippy_lints/src/create_dir.rs | 6 +- .../clippy/clippy_lints/src/dbg_macro.rs | 3 +- src/tools/clippy/clippy_lints/src/default.rs | 65 +- .../src/default_numeric_fallback.rs | 14 +- .../clippy_lints/src/deprecated_lints.rs | 68 +- .../clippy/clippy_lints/src/dereference.rs | 322 +- src/tools/clippy/clippy_lints/src/derive.rs | 98 +- .../clippy_lints/src/disallowed_method.rs | 3 +- src/tools/clippy/clippy_lints/src/doc.rs | 29 +- .../clippy_lints/src/double_comparison.rs | 9 +- .../clippy/clippy_lints/src/double_parens.rs | 8 +- .../clippy_lints/src/drop_forget_ref.rs | 6 +- .../clippy_lints/src/duration_subsec.rs | 10 +- .../clippy_lints/src/else_if_without_else.rs | 3 +- .../clippy/clippy_lints/src/empty_enum.rs | 2 +- src/tools/clippy/clippy_lints/src/entry.rs | 695 +- .../clippy/clippy_lints/src/enum_clike.rs | 2 +- .../clippy/clippy_lints/src/enum_variants.rs | 5 +- src/tools/clippy/clippy_lints/src/eq_op.rs | 22 +- .../clippy/clippy_lints/src/erasing_op.rs | 4 +- src/tools/clippy/clippy_lints/src/escape.rs | 6 +- .../clippy/clippy_lints/src/eta_reduction.rs | 31 +- .../clippy_lints/src/eval_order_dependence.rs | 23 +- .../clippy_lints/src/excessive_bools.rs | 15 +- .../clippy_lints/src/exhaustive_items.rs | 3 +- src/tools/clippy/clippy_lints/src/exit.rs | 21 +- .../clippy/clippy_lints/src/explicit_write.rs | 13 +- .../clippy_lints/src/fallible_impl_from.rs | 8 +- .../src/float_equality_without_abs.rs | 9 +- .../clippy/clippy_lints/src/float_literal.rs | 5 +- .../src/floating_point_arithmetic.rs | 45 +- src/tools/clippy/clippy_lints/src/format.rs | 59 +- .../clippy/clippy_lints/src/formatting.rs | 22 +- .../clippy/clippy_lints/src/from_over_into.rs | 11 +- .../clippy_lints/src/from_str_radix_10.rs | 7 +- .../clippy/clippy_lints/src/functions.rs | 736 - .../clippy/clippy_lints/src/functions/mod.rs | 267 + .../clippy_lints/src/functions/must_use.rs | 272 + .../src/functions/not_unsafe_ptr_arg_deref.rs | 124 + .../src/functions/result_unit_err.rs | 66 + .../src/functions/too_many_arguments.rs | 73 + .../src/functions/too_many_lines.rs | 68 + .../clippy_lints/src/future_not_send.rs | 7 +- .../clippy_lints/src/get_last_with_len.rs | 7 +- .../clippy/clippy_lints/src/identity_op.rs | 6 +- .../clippy/clippy_lints/src/if_let_mutex.rs | 32 +- .../clippy_lints/src/if_let_some_result.rs | 11 +- .../clippy/clippy_lints/src/if_not_else.rs | 3 +- .../src/if_then_some_else_none.rs | 116 + .../clippy_lints/src/implicit_hasher.rs | 378 + .../clippy_lints/src/implicit_return.rs | 8 +- .../src/implicit_saturating_sub.rs | 58 +- .../src/inconsistent_struct_constructor.rs | 21 +- .../clippy_lints/src/indexing_slicing.rs | 5 +- .../clippy/clippy_lints/src/infinite_iter.rs | 19 +- .../clippy/clippy_lints/src/inherent_impl.rs | 7 +- .../clippy_lints/src/inherent_to_string.rs | 8 +- .../src/inline_fn_without_body.rs | 4 +- .../clippy/clippy_lints/src/int_plus_one.rs | 4 +- .../clippy_lints/src/integer_division.rs | 2 +- .../src/invalid_upcast_comparisons.rs | 221 + .../src/items_after_statements.rs | 2 +- .../clippy_lints/src/large_const_arrays.rs | 2 +- .../clippy_lints/src/large_enum_variant.rs | 5 +- .../clippy_lints/src/large_stack_arrays.rs | 6 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 106 +- .../clippy/clippy_lints/src/let_if_seq.rs | 28 +- .../clippy/clippy_lints/src/let_underscore.rs | 7 +- src/tools/clippy/clippy_lints/src/lib.rs | 2533 +- .../clippy/clippy_lints/src/lifetimes.rs | 23 +- .../src/literal_representation.rs | 12 +- .../clippy_lints/src/loops/empty_loop.rs | 3 +- .../src/loops/explicit_counter_loop.rs | 6 +- .../src/loops/explicit_into_iter_loop.rs | 16 +- .../src/loops/explicit_iter_loop.rs | 17 +- .../clippy_lints/src/loops/for_kv_map.rs | 11 +- .../src/loops/for_loops_over_fallibles.rs | 4 +- .../clippy_lints/src/loops/iter_next_loop.rs | 6 +- .../clippy_lints/src/loops/manual_flatten.rs | 29 +- .../clippy_lints/src/loops/manual_memcpy.rs | 23 +- .../clippy/clippy_lints/src/loops/mod.rs | 35 +- .../clippy_lints/src/loops/mut_range_bound.rs | 8 +- .../src/loops/needless_collect.rs | 138 +- .../src/loops/needless_range_loop.rs | 106 +- .../clippy_lints/src/loops/never_loop.rs | 52 +- .../clippy_lints/src/loops/same_item_push.rs | 143 +- .../src/loops/single_element_loop.rs | 14 +- .../clippy/clippy_lints/src/loops/utils.rs | 36 +- .../src/loops/while_immutable_condition.rs | 21 +- .../clippy_lints/src/loops/while_let_loop.rs | 15 +- .../src/loops/while_let_on_iterator.rs | 27 +- .../clippy/clippy_lints/src/macro_use.rs | 11 +- .../clippy/clippy_lints/src/main_recursion.rs | 7 +- .../clippy_lints/src/manual_async_fn.rs | 6 +- .../clippy/clippy_lints/src/manual_map.rs | 133 +- .../clippy_lints/src/manual_non_exhaustive.rs | 24 +- .../clippy/clippy_lints/src/manual_ok_or.rs | 15 +- .../clippy/clippy_lints/src/manual_strip.rs | 17 +- .../clippy_lints/src/manual_unwrap_or.rs | 57 +- .../clippy/clippy_lints/src/map_clone.rs | 25 +- .../clippy/clippy_lints/src/map_err_ignore.rs | 5 +- .../clippy/clippy_lints/src/map_identity.rs | 21 +- .../clippy/clippy_lints/src/map_unit_fn.rs | 29 +- .../clippy_lints/src/match_on_vec_items.rs | 8 +- src/tools/clippy/clippy_lints/src/matches.rs | 695 +- .../clippy_lints/src/mem_discriminant.rs | 10 +- .../clippy/clippy_lints/src/mem_forget.rs | 5 +- .../clippy/clippy_lints/src/mem_replace.rs | 105 +- .../src/methods/bind_instead_of_map.rs | 173 +- .../clippy_lints/src/methods/bytes_nth.rs | 59 +- .../clippy_lints/src/methods/chars_cmp.rs | 54 + .../src/methods/chars_cmp_with_unwrap.rs | 44 + .../src/methods/chars_last_cmp.rs | 13 + .../src/methods/chars_last_cmp_with_unwrap.rs | 13 + .../src/methods/chars_next_cmp.rs | 8 + .../src/methods/chars_next_cmp_with_unwrap.rs | 8 + .../clippy_lints/src/methods/clone_on_copy.rs | 120 +- .../src/methods/clone_on_ref_ptr.rs | 13 +- .../src/methods/cloned_instead_of_copied.rs | 45 + .../src/methods/expect_fun_call.rs | 13 +- .../clippy_lints/src/methods/expect_used.rs | 7 +- .../src/methods/filetype_is_file.rs | 8 +- .../src/methods/filter_flat_map.rs | 21 - .../clippy_lints/src/methods/filter_map.rs | 223 +- .../src/methods/filter_map_flat_map.rs | 21 - .../src/methods/filter_map_identity.rs | 30 +- .../src/methods/filter_map_map.rs | 20 - .../src/methods/filter_map_next.rs | 18 +- .../clippy_lints/src/methods/filter_next.rs | 18 +- .../src/methods/flat_map_identity.rs | 27 +- .../src/methods/flat_map_option.rs | 34 + .../methods/from_iter_instead_of_collect.rs | 20 +- .../clippy_lints/src/methods/get_unwrap.rs | 29 +- .../src/methods/implicit_clone.rs | 32 +- .../src/methods/inefficient_to_string.rs | 18 +- .../src/methods/inspect_for_each.rs | 8 +- .../src/methods/into_iter_on_ref.rs | 51 +- .../src/methods/iter_cloned_collect.rs | 9 +- .../clippy_lints/src/methods/iter_count.rs | 16 +- .../src/methods/iter_next_slice.rs | 25 +- .../clippy_lints/src/methods/iter_nth.rs | 19 +- .../clippy_lints/src/methods/iter_nth_zero.rs | 13 +- .../src/methods/iter_skip_next.rs | 30 +- .../src/methods/iterator_step_by_zero.rs | 10 +- .../methods/manual_saturating_arithmetic.rs | 69 +- .../src/methods/map_collect_result_unit.rs | 14 +- .../clippy_lints/src/methods/map_flatten.rs | 26 +- .../clippy_lints/src/methods/map_unwrap_or.rs | 35 +- .../clippy/clippy_lints/src/methods/mod.rs | 714 +- .../clippy_lints/src/methods/ok_expect.rs | 9 +- .../src/methods/option_as_ref_deref.rs | 34 +- .../src/methods/option_map_or_none.rs | 32 +- .../src/methods/option_map_unwrap_or.rs | 29 +- .../clippy_lints/src/methods/or_fun_call.rs | 36 +- .../src/methods/search_is_some.rs | 131 +- .../src/methods/single_char_add_str.rs | 14 + .../src/methods/single_char_insert_string.rs | 5 +- .../src/methods/single_char_pattern.rs | 40 +- .../src/methods/single_char_push_string.rs | 5 +- .../src/methods/skip_while_next.rs | 8 +- .../src/methods/string_extend_chars.rs | 65 +- .../src/methods/suspicious_map.rs | 39 +- .../src/methods/uninit_assumed_init.rs | 20 +- .../src/methods/unnecessary_filter_map.rs | 46 +- .../src/methods/unnecessary_fold.rs | 50 +- .../src/methods/unnecessary_lazy_eval.rs | 17 +- .../clippy_lints/src/methods/unwrap_used.rs | 7 +- .../clippy_lints/src/methods/useless_asref.rs | 10 +- .../clippy/clippy_lints/src/methods/utils.rs | 75 + .../src/methods/wrong_self_convention.rs | 117 +- .../clippy_lints/src/methods/zst_offset.rs | 7 +- src/tools/clippy/clippy_lints/src/minmax.rs | 7 +- src/tools/clippy/clippy_lints/src/misc.rs | 154 +- .../clippy/clippy_lints/src/misc_early.rs | 3 +- .../clippy_lints/src/missing_const_for_fn.rs | 16 +- .../clippy/clippy_lints/src/missing_doc.rs | 21 +- .../clippy/clippy_lints/src/missing_inline.rs | 4 +- .../clippy_lints/src/modulo_arithmetic.rs | 5 +- .../src/multiple_crate_versions.rs | 3 +- src/tools/clippy/clippy_lints/src/mut_key.rs | 12 +- src/tools/clippy/clippy_lints/src/mut_mut.rs | 7 +- .../clippy/clippy_lints/src/mut_mutex_lock.rs | 3 +- .../clippy/clippy_lints/src/mut_reference.rs | 9 +- .../src/mutable_debug_assertion.rs | 3 +- .../clippy/clippy_lints/src/mutex_atomic.rs | 3 +- .../src/needless_arbitrary_self_type.rs | 3 +- .../clippy/clippy_lints/src/needless_bool.rs | 24 +- .../clippy_lints/src/needless_borrow.rs | 6 +- .../clippy_lints/src/needless_borrowed_ref.rs | 5 +- .../clippy_lints/src/needless_continue.rs | 4 +- .../clippy_lints/src/needless_for_each.rs | 167 + .../src/needless_pass_by_value.rs | 23 +- .../src/needless_question_mark.rs | 69 +- .../clippy_lints/src/needless_update.rs | 4 +- .../src/neg_cmp_op_on_partial_ord.rs | 15 +- .../clippy/clippy_lints/src/neg_multiply.rs | 8 +- .../clippy_lints/src/new_without_default.rs | 114 +- .../clippy/clippy_lints/src/no_effect.rs | 62 +- .../clippy/clippy_lints/src/non_copy_const.rs | 40 +- .../clippy_lints/src/non_expressive_names.rs | 2 +- .../src/non_octal_unix_permissions.rs | 106 + .../clippy/clippy_lints/src/open_options.rs | 8 +- .../clippy_lints/src/option_env_unwrap.rs | 7 +- .../clippy_lints/src/option_if_let_else.rs | 29 +- .../src/overflow_check_conditional.rs | 23 +- .../clippy_lints/src/panic_in_result_fn.rs | 10 +- .../clippy_lints/src/panic_unimplemented.rs | 12 +- .../clippy_lints/src/partialeq_ne_impl.rs | 3 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 20 +- .../src/path_buf_push_overwrite.rs | 5 +- .../clippy_lints/src/pattern_type_mismatch.rs | 26 +- .../clippy/clippy_lints/src/precedence.rs | 3 +- src/tools/clippy/clippy_lints/src/ptr.rs | 145 +- src/tools/clippy/clippy_lints/src/ptr_eq.rs | 20 +- .../clippy_lints/src/ptr_offset_with_cast.rs | 9 +- .../clippy/clippy_lints/src/question_mark.rs | 41 +- src/tools/clippy/clippy_lints/src/ranges.rs | 79 +- .../clippy_lints/src/redundant_clone.rs | 270 +- .../src/redundant_closure_call.rs | 23 +- .../clippy/clippy_lints/src/redundant_else.rs | 2 +- .../clippy_lints/src/redundant_field_names.rs | 7 +- .../clippy_lints/src/redundant_pub_crate.rs | 2 +- .../clippy_lints/src/redundant_slicing.rs | 40 +- .../src/redundant_static_lifetimes.rs | 8 +- .../clippy/clippy_lints/src/ref_option_ref.rs | 11 +- .../clippy/clippy_lints/src/reference.rs | 6 +- src/tools/clippy/clippy_lints/src/regex.rs | 7 +- .../clippy/clippy_lints/src/repeat_once.rs | 9 +- src/tools/clippy/clippy_lints/src/returns.rs | 27 +- .../clippy_lints/src/self_assignment.rs | 4 +- .../src/semicolon_if_nothing_returned.rs | 6 +- .../clippy/clippy_lints/src/serde_api.rs | 3 +- src/tools/clippy/clippy_lints/src/shadow.rs | 73 +- .../src/single_component_path_imports.rs | 150 +- .../src/size_of_in_element_count.rs | 7 +- .../src/slow_vector_initialization.rs | 88 +- .../clippy_lints/src/stable_sort_primitive.rs | 5 +- src/tools/clippy/clippy_lints/src/strings.rs | 58 +- .../src/suspicious_operation_groupings.rs | 23 +- .../clippy_lints/src/suspicious_trait_impl.rs | 12 +- src/tools/clippy/clippy_lints/src/swap.rs | 39 +- .../clippy_lints/src/tabs_in_doc_comments.rs | 35 +- .../clippy_lints/src/temporary_assignment.rs | 3 +- .../clippy_lints/src/to_digit_is_some.rs | 4 +- .../clippy_lints/src/to_string_in_display.rs | 7 +- .../clippy/clippy_lints/src/trait_bounds.rs | 8 +- .../src/transmute/crosspointer_transmute.rs | 2 +- .../clippy/clippy_lints/src/transmute/mod.rs | 6 +- .../src/transmute/transmute_float_to_int.rs | 7 +- .../src/transmute/transmute_int_to_bool.rs | 3 +- .../src/transmute/transmute_int_to_char.rs | 3 +- .../src/transmute/transmute_int_to_float.rs | 3 +- .../src/transmute/transmute_ptr_to_ptr.rs | 3 +- .../src/transmute/transmute_ptr_to_ref.rs | 3 +- .../src/transmute/transmute_ref_to_ref.rs | 4 +- .../transmutes_expressible_as_ptr_casts.rs | 3 +- .../transmute/unsound_collection_transmute.rs | 3 +- .../src/transmute/useless_transmute.rs | 3 +- .../clippy_lints/src/transmute/utils.rs | 6 +- .../src/transmute/wrong_transmute.rs | 2 +- .../clippy_lints/src/transmuting_null.rs | 22 +- src/tools/clippy/clippy_lints/src/try_err.rs | 45 +- .../clippy_lints/src/types/borrowed_box.rs | 21 +- .../clippy/clippy_lints/src/types/box_vec.rs | 4 +- .../clippy_lints/src/types/linked_list.rs | 4 +- .../clippy/clippy_lints/src/types/mod.rs | 1462 +- .../clippy_lints/src/types/option_option.rs | 4 +- .../clippy_lints/src/types/rc_buffer.rs | 7 +- .../src/types/redundant_allocation.rs | 8 +- .../clippy_lints/src/types/type_complexity.rs | 79 + .../clippy/clippy_lints/src/types/utils.rs | 8 +- .../clippy/clippy_lints/src/types/vec_box.rs | 12 +- .../src/undropped_manually_drops.rs | 6 +- src/tools/clippy/clippy_lints/src/unicode.rs | 4 +- .../src/unit_return_expecting_ord.rs | 17 +- .../src/unit_types/let_unit_value.rs | 39 + .../clippy/clippy_lints/src/unit_types/mod.rs | 107 + .../clippy_lints/src/unit_types/unit_arg.rs | 207 + .../clippy_lints/src/unit_types/unit_cmp.rs | 56 + .../clippy_lints/src/unit_types/utils.rs | 5 + .../clippy_lints/src/unnamed_address.rs | 13 +- .../src/unnecessary_self_imports.rs | 67 + .../clippy_lints/src/unnecessary_sort_by.rs | 55 +- .../clippy_lints/src/unnecessary_wraps.rs | 28 +- .../clippy_lints/src/unnested_or_patterns.rs | 47 +- .../src/unsafe_removed_from_name.rs | 2 +- .../clippy_lints/src/unused_io_amount.rs | 33 +- .../clippy/clippy_lints/src/unused_self.rs | 30 +- .../clippy/clippy_lints/src/unused_unit.rs | 6 +- src/tools/clippy/clippy_lints/src/unwrap.rs | 10 +- .../clippy_lints/src/unwrap_in_result.rs | 53 +- .../clippy_lints/src/upper_case_acronyms.rs | 27 +- src/tools/clippy/clippy_lints/src/use_self.rs | 20 +- .../clippy_lints/src/useless_conversion.rs | 63 +- .../clippy/clippy_lints/src/utils/author.rs | 98 +- .../clippy/clippy_lints/src/utils/conf.rs | 2 +- .../clippy_lints/src/utils/inspector.rs | 97 +- .../clippy_lints/src/utils/internal_lints.rs | 211 +- .../clippy/clippy_lints/src/utils/mod.rs | 2 - src/tools/clippy/clippy_lints/src/vec.rs | 59 +- .../clippy_lints/src/vec_init_then_push.rs | 38 +- .../clippy_lints/src/vec_resize_to_zero.rs | 11 +- .../clippy_lints/src/verbose_file_reads.rs | 4 +- .../clippy_lints/src/wildcard_dependencies.rs | 3 +- .../clippy_lints/src/wildcard_imports.rs | 4 +- src/tools/clippy/clippy_lints/src/write.rs | 315 +- .../clippy/clippy_lints/src/zero_div_zero.rs | 4 +- .../clippy_lints/src/zero_sized_map_values.rs | 7 +- src/tools/clippy/clippy_utils/Cargo.toml | 4 +- .../clippy/clippy_utils/src/ast_utils.rs | 46 +- src/tools/clippy/clippy_utils/src/attrs.rs | 11 +- src/tools/clippy/clippy_utils/src/consts.rs | 13 +- .../clippy/clippy_utils/src/diagnostics.rs | 29 +- .../clippy/clippy_utils/src/eager_or_lazy.rs | 3 +- .../clippy/clippy_utils/src/hir_utils.rs | 72 +- src/tools/clippy/clippy_utils/src/lib.rs | 1219 +- src/tools/clippy/clippy_utils/src/msrvs.rs | 29 + .../clippy_utils/src/numeric_literal.rs | 3 +- src/tools/clippy/clippy_utils/src/paths.rs | 36 +- src/tools/clippy/clippy_utils/src/ptr.rs | 3 +- .../clippy_utils/src/qualify_min_const_fn.rs | 54 +- src/tools/clippy/clippy_utils/src/source.rs | 429 + src/tools/clippy/clippy_utils/src/sugg.rs | 45 +- src/tools/clippy/clippy_utils/src/ty.rs | 324 + src/tools/clippy/clippy_utils/src/usage.rs | 12 +- src/tools/clippy/doc/adding_lints.md | 72 +- src/tools/clippy/doc/basics.md | 4 +- .../lintcheck-logs/lintcheck_crates_logs.txt | 180 +- src/tools/clippy/lintcheck/src/main.rs | 17 +- src/tools/clippy/rust-toolchain | 2 +- src/tools/clippy/src/driver.rs | 14 +- src/tools/clippy/tests/compile-test.rs | 25 +- .../clippy/tests/lint_message_convention.rs | 4 +- .../fail/src/main.stderr | 6 +- .../fail_publish/src/main.stderr | 6 +- .../fail_publish_true/src/main.stderr | 6 +- .../cargo_common_metadata/pass/Cargo.toml | 1 - .../collapsible_span_lint_calls.fixed | 48 +- .../collapsible_span_lint_calls.rs | 48 +- .../collapsible_span_lint_calls.stderr | 10 +- .../tests/ui-internal/if_chain_style.rs | 92 + .../tests/ui-internal/if_chain_style.stderr | 85 + .../ui-internal/match_type_on_diag_item.rs | 21 +- .../match_type_on_diag_item.stderr | 30 +- .../upper_case_acronyms.rs | 21 + .../upper_case_acronyms.stderr | 14 +- src/tools/clippy/tests/ui/asm_syntax.rs | 5 +- src/tools/clippy/tests/ui/asm_syntax.stderr | 10 +- .../clippy/tests/ui/bool_assert_comparison.rs | 59 + .../tests/ui/bool_assert_comparison.stderr | 112 + .../borrow_interior_mutable_const/others.rs | 6 +- .../others.stderr | 28 +- .../branches_sharing_code/shared_at_bottom.rs | 223 + .../shared_at_bottom.stderr | 143 + .../ui/branches_sharing_code/shared_at_top.rs | 114 + .../shared_at_top.stderr | 121 + .../shared_at_top_and_bottom.rs | 119 + .../shared_at_top_and_bottom.stderr | 154 + .../branches_sharing_code/valid_if_blocks.rs | 155 + .../valid_if_blocks.stderr | 101 + .../ui/checked_unwrap/complex_conditionals.rs | 2 +- .../complex_conditionals_nested.rs | 2 +- .../ui/checked_unwrap/simple_conditionals.rs | 2 +- src/tools/clippy/tests/ui/clone_on_copy.fixed | 34 +- src/tools/clippy/tests/ui/clone_on_copy.rs | 34 +- .../clippy/tests/ui/clone_on_copy.stderr | 30 +- .../clippy/tests/ui/clone_on_copy_mut.rs | 18 - .../tests/ui/cloned_instead_of_copied.fixed | 15 + .../tests/ui/cloned_instead_of_copied.rs | 15 + .../tests/ui/cloned_instead_of_copied.stderr | 34 + .../clippy/tests/ui/collapsible_match2.rs | 7 +- .../clippy/tests/ui/collapsible_match2.stderr | 20 +- src/tools/clippy/tests/ui/crashes/ice-5835.rs | 9 + .../clippy/tests/ui/crashes/ice-5835.stderr | 10 + .../clippy/tests/ui/crashes/ice-6251.stderr | 4 +- src/tools/clippy/tests/ui/crashes/ice-7012.rs | 17 + src/tools/clippy/tests/ui/crashes/ice-7126.rs | 14 + src/tools/clippy/tests/ui/crashes/ice-7169.rs | 9 + .../clippy/tests/ui/crashes/ice-7169.stderr | 10 + .../entrypoint_recursion.rs | 4 +- .../no_std_main_recursion.rs | 4 +- .../clippy/tests/ui/def_id_nocore.stderr | 3 +- .../tests/ui/default_numeric_fallback.rs | 1 + .../tests/ui/default_numeric_fallback.stderr | 48 +- src/tools/clippy/tests/ui/deprecated.rs | 1 + src/tools/clippy/tests/ui/deprecated.stderr | 36 +- src/tools/clippy/tests/ui/dereference.stderr | 70 - src/tools/clippy/tests/ui/derive.rs | 21 +- src/tools/clippy/tests/ui/derive.stderr | 30 +- src/tools/clippy/tests/ui/doc.rs | 21 +- .../clippy/tests/ui/empty_loop_no_std.rs | 4 +- src/tools/clippy/tests/ui/entry.fixed | 155 + src/tools/clippy/tests/ui/entry.rs | 159 + src/tools/clippy/tests/ui/entry.stderr | 186 + src/tools/clippy/tests/ui/entry_fixable.fixed | 15 - src/tools/clippy/tests/ui/entry_fixable.rs | 17 - .../clippy/tests/ui/entry_fixable.stderr | 12 - src/tools/clippy/tests/ui/entry_unfixable.rs | 73 - .../clippy/tests/ui/entry_unfixable.stderr | 57 - .../clippy/tests/ui/entry_with_else.fixed | 73 + src/tools/clippy/tests/ui/entry_with_else.rs | 60 + .../clippy/tests/ui/entry_with_else.stderr | 142 + src/tools/clippy/tests/ui/escape_analysis.rs | 4 +- ...nce.fixed => explicit_deref_methods.fixed} | 10 +- ...reference.rs => explicit_deref_methods.rs} | 2 + .../tests/ui/explicit_deref_methods.stderr | 76 + .../tests/ui/field_reassign_with_default.rs | 18 + .../ui/field_reassign_with_default.stderr | 26 +- src/tools/clippy/tests/ui/filter_methods.rs | 25 - .../clippy/tests/ui/filter_methods.stderr | 39 - .../clippy/tests/ui/flat_map_option.fixed | 13 + src/tools/clippy/tests/ui/flat_map_option.rs | 13 + .../clippy/tests/ui/flat_map_option.stderr | 16 + .../clippy/tests/ui/floating_point_log.fixed | 2 +- .../clippy/tests/ui/floating_point_log.stderr | 2 +- .../clippy/tests/ui/for_loop_fixable.fixed | 26 + src/tools/clippy/tests/ui/for_loop_fixable.rs | 26 + src/tools/clippy/tests/ui/format.fixed | 4 + src/tools/clippy/tests/ui/format.rs | 4 + src/tools/clippy/tests/ui/format.stderr | 8 +- .../clippy/tests/ui/from_over_into.stderr | 2 +- .../clippy/tests/ui/from_str_radix_10.stderr | 2 +- .../clippy/tests/ui/if_same_then_else.rs | 3 +- .../clippy/tests/ui/if_same_then_else.stderr | 88 +- .../clippy/tests/ui/if_same_then_else2.rs | 3 +- .../clippy/tests/ui/if_same_then_else2.stderr | 106 +- .../clippy/tests/ui/if_then_some_else_none.rs | 104 + .../tests/ui/if_then_some_else_none.stderr | 61 + src/tools/clippy/tests/ui/implicit_clone.rs | 2 +- .../ui/inconsistent_struct_constructor.fixed | 13 + .../ui/inconsistent_struct_constructor.rs | 13 + .../ui/inconsistent_struct_constructor.stderr | 8 +- .../clippy/tests/ui/into_iter_on_ref.fixed | 2 +- src/tools/clippy/tests/ui/into_iter_on_ref.rs | 2 +- .../tests/ui/invalid_null_ptr_usage.fixed | 49 + .../clippy/tests/ui/invalid_null_ptr_usage.rs | 49 + .../tests/ui/invalid_null_ptr_usage.stderr | 154 + .../clippy/tests/ui/iter_cloned_collect.fixed | 4 + .../clippy/tests/ui/iter_cloned_collect.rs | 4 + .../tests/ui/iter_cloned_collect.stderr | 8 +- .../clippy/tests/ui/len_without_is_empty.rs | 99 +- .../tests/ui/len_without_is_empty.stderr | 79 +- src/tools/clippy/tests/ui/let_if_seq.rs | 3 +- src/tools/clippy/tests/ui/let_if_seq.stderr | 8 +- .../tests/ui/{dlist.rs => linkedlist.rs} | 3 + .../ui/{dlist.stderr => linkedlist.stderr} | 32 +- .../clippy/tests/ui/macro_use_imports.fixed | 6 +- .../clippy/tests/ui/macro_use_imports.rs | 6 +- src/tools/clippy/tests/ui/manual_flatten.rs | 22 + .../clippy/tests/ui/manual_flatten.stderr | 85 +- .../clippy/tests/ui/manual_map_option.fixed | 25 + .../clippy/tests/ui/manual_map_option.rs | 33 + .../clippy/tests/ui/manual_map_option.stderr | 62 +- .../manual_memcpy/with_loop_counters.stderr | 2 +- .../clippy/tests/ui/manual_unwrap_or.fixed | 27 + src/tools/clippy/tests/ui/manual_unwrap_or.rs | 30 + .../clippy/tests/ui/manual_unwrap_or.stderr | 12 +- .../clippy/tests/ui/match_ref_pats.stderr | 16 +- .../tests/ui/match_single_binding2.fixed | 37 + .../clippy/tests/ui/match_single_binding2.rs | 37 + .../tests/ui/match_single_binding2.stderr | 34 + .../match_wildcard_for_single_variants.fixed | 68 + .../ui/match_wildcard_for_single_variants.rs | 68 + .../match_wildcard_for_single_variants.stderr | 44 +- src/tools/clippy/tests/ui/mem_replace.fixed | 29 + src/tools/clippy/tests/ui/mem_replace.rs | 29 + src/tools/clippy/tests/ui/mem_replace.stderr | 78 +- .../clippy/tests/ui/min_rust_version_attr.rs | 10 + .../tests/ui/min_rust_version_attr.stderr | 8 +- .../missing_const_for_fn/auxiliary/helper.rs | 8 + .../ui/missing_const_for_fn/cant_be_const.rs | 19 + .../ui/missing_const_for_fn/could_be_const.rs | 10 + .../could_be_const.stderr | 26 +- .../{doc_panics.rs => missing_panics_doc.rs} | 40 + ...anics.stderr => missing_panics_doc.stderr} | 54 +- .../clippy/tests/ui/needless_bool/simple.rs | 3 +- .../tests/ui/needless_bool/simple.stderr | 8 +- .../tests/ui/needless_collect_indirect.stderr | 45 +- .../tests/ui/needless_for_each_fixable.fixed | 113 + .../tests/ui/needless_for_each_fixable.rs | 113 + .../tests/ui/needless_for_each_fixable.stderr | 123 + .../tests/ui/needless_for_each_unfixable.rs | 14 + .../ui/needless_for_each_unfixable.stderr | 29 + .../tests/ui/needless_question_mark.fixed | 83 +- .../clippy/tests/ui/needless_question_mark.rs | 83 +- .../tests/ui/needless_question_mark.stderr | 23 +- .../clippy/tests/ui/needless_return.fixed | 99 +- src/tools/clippy/tests/ui/needless_return.rs | 99 +- .../clippy/tests/ui/needless_return.stderr | 122 +- src/tools/clippy/tests/ui/new_ret_no_self.rs | 10 + .../clippy/tests/ui/new_without_default.rs | 15 + .../tests/ui/new_without_default.stderr | 38 +- .../tests/ui/non_octal_unix_permissions.fixed | 33 + .../tests/ui/non_octal_unix_permissions.rs | 33 + .../ui/non_octal_unix_permissions.stderr | 28 + .../clippy/tests/ui/option_filter_map.fixed | 23 + .../clippy/tests/ui/option_filter_map.rs | 25 + .../clippy/tests/ui/option_filter_map.stderr | 56 + src/tools/clippy/tests/ui/option_option.rs | 3 + .../clippy/tests/ui/option_option.stderr | 38 +- src/tools/clippy/tests/ui/or_fun_call.fixed | 17 + src/tools/clippy/tests/ui/or_fun_call.rs | 17 + src/tools/clippy/tests/ui/or_fun_call.stderr | 20 +- .../ui/panic_in_result_fn_debug_assertions.rs | 23 +- ...panic_in_result_fn_debug_assertions.stderr | 57 - src/tools/clippy/tests/ui/panicking_macros.rs | 14 +- src/tools/clippy/tests/ui/print.stderr | 12 +- .../clippy/tests/ui/print_literal.stderr | 70 +- .../clippy/tests/ui/redundant_clone.fixed | 24 + src/tools/clippy/tests/ui/redundant_clone.rs | 24 + .../clippy/tests/ui/redundant_clone.stderr | 20 +- ...edundant_pattern_matching_drop_order.fixed | 58 + .../redundant_pattern_matching_drop_order.rs | 58 + ...dundant_pattern_matching_drop_order.stderr | 171 + .../redundant_pattern_matching_option.fixed | 7 +- .../ui/redundant_pattern_matching_option.rs | 7 +- .../redundant_pattern_matching_option.stderr | 38 +- .../ui/redundant_pattern_matching_poll.fixed | 7 +- .../ui/redundant_pattern_matching_poll.rs | 7 +- .../ui/redundant_pattern_matching_poll.stderr | 36 +- .../redundant_pattern_matching_result.fixed | 3 +- .../ui/redundant_pattern_matching_result.rs | 3 +- .../redundant_pattern_matching_result.stderr | 44 +- .../clippy/tests/ui/redundant_slicing.rs | 29 +- .../clippy/tests/ui/redundant_slicing.stderr | 32 +- src/tools/clippy/tests/ui/ref_option_ref.rs | 2 +- .../clippy/tests/ui/ref_option_ref.stderr | 2 +- src/tools/clippy/tests/ui/repl_uninit.rs | 4 +- .../clippy/tests/ui/result_unit_error.stderr | 20 +- src/tools/clippy/tests/ui/same_item_push.rs | 7 + src/tools/clippy/tests/ui/search_is_some.rs | 37 +- .../clippy/tests/ui/search_is_some.stderr | 44 +- .../tests/ui/search_is_some_fixable.fixed | 35 +- .../clippy/tests/ui/search_is_some_fixable.rs | 35 +- .../tests/ui/search_is_some_fixable.stderr | 92 +- .../ui/single_component_path_imports.fixed | 13 + .../tests/ui/single_component_path_imports.rs | 13 + .../ui/single_component_path_imports.stderr | 12 +- .../single_component_path_imports_macro.fixed | 21 + .../ui/single_component_path_imports_macro.rs | 21 + ...single_component_path_imports_macro.stderr | 10 + ...gle_component_path_imports_nested_first.rs | 17 + ...component_path_imports_nested_first.stderr | 25 + ...ingle_component_path_imports_self_after.rs | 16 + ...ngle_component_path_imports_self_before.rs | 17 + .../clippy/tests/ui/single_element_loop.fixed | 5 + .../clippy/tests/ui/single_element_loop.rs | 4 + .../tests/ui/single_element_loop.stderr | 18 +- src/tools/clippy/tests/ui/single_match.rs | 8 + src/tools/clippy/tests/ui/single_match.stderr | 11 +- .../tests/ui/stable_sort_primitive.fixed | 2 +- .../clippy/tests/ui/stable_sort_primitive.rs | 2 +- .../clippy/tests/ui/string_lit_as_bytes.fixed | 8 +- .../clippy/tests/ui/string_lit_as_bytes.rs | 8 +- .../tests/ui/string_lit_as_bytes.stderr | 22 +- .../tests/ui/suspicious_else_formatting.rs | 26 + .../ui/suspicious_else_formatting.stderr | 39 +- src/tools/clippy/tests/ui/suspicious_map.rs | 27 + .../clippy/tests/ui/suspicious_map.stderr | 10 +- src/tools/clippy/tests/ui/try_err.fixed | 8 + src/tools/clippy/tests/ui/try_err.rs | 8 + src/tools/clippy/tests/ui/try_err.stderr | 8 +- .../{complex_types.rs => type_complexity.rs} | 0 ...ex_types.stderr => type_complexity.stderr} | 30 +- src/tools/clippy/tests/ui/uninit.rs | 5 +- src/tools/clippy/tests/ui/uninit.stderr | 8 +- .../clippy/tests/ui/unnecessary_cast.stderr | 10 +- .../tests/ui/unnecessary_self_imports.fixed | 10 + .../tests/ui/unnecessary_self_imports.rs | 10 + .../tests/ui/unnecessary_self_imports.stderr | 23 + .../tests/ui/unnested_or_patterns.fixed | 1 - .../clippy/tests/ui/unnested_or_patterns.rs | 1 - .../tests/ui/unnested_or_patterns.stderr | 32 +- .../tests/ui/unnested_or_patterns2.fixed | 1 - .../clippy/tests/ui/unnested_or_patterns2.rs | 1 - .../tests/ui/unnested_or_patterns2.stderr | 16 +- .../clippy/tests/ui/unnested_or_patterns3.rs | 6 - src/tools/clippy/tests/ui/unused_io_amount.rs | 41 +- .../clippy/tests/ui/unused_io_amount.stderr | 30 +- .../clippy/tests/ui/upper_case_acronyms.rs | 18 + .../tests/ui/upper_case_acronyms.stderr | 8 +- src/tools/clippy/tests/ui/use_self.fixed | 6 +- src/tools/clippy/tests/ui/use_self.rs | 6 +- src/tools/clippy/tests/ui/vec.fixed | 16 + src/tools/clippy/tests/ui/vec.rs | 16 + src/tools/clippy/tests/ui/vec.stderr | 44 +- src/tools/clippy/tests/ui/vec_box_sized.fixed | 2 + src/tools/clippy/tests/ui/vec_box_sized.rs | 2 + .../clippy/tests/ui/vec_box_sized.stderr | 26 +- .../tests/ui/while_let_on_iterator.fixed | 1 - .../clippy/tests/ui/while_let_on_iterator.rs | 1 - .../tests/ui/while_let_on_iterator.stderr | 14 +- .../tests/ui/wildcard_enum_match_arm.fixed | 3 +- .../tests/ui/wildcard_enum_match_arm.rs | 1 + .../tests/ui/wildcard_enum_match_arm.stderr | 12 +- .../clippy/tests/ui/write_literal.stderr | 70 +- src/tools/clippy/tests/ui/write_literal_2.rs | 27 + .../clippy/tests/ui/write_literal_2.stderr | 107 + .../clippy/tests/ui/wrong_self_convention.rs | 27 + .../tests/ui/wrong_self_convention.stderr | 111 +- .../clippy/tests/ui/wrong_self_convention2.rs | 44 + .../tests/ui/wrong_self_convention2.stderr | 11 + .../tests/ui/wrong_self_conventions_mut.rs | 30 + .../ui/wrong_self_conventions_mut.stderr | 19 + src/tools/compiletest/src/common.rs | 14 +- src/tools/compiletest/src/header.rs | 36 +- src/tools/compiletest/src/header/tests.rs | 18 + src/tools/compiletest/src/main.rs | 5 +- src/tools/compiletest/src/runtest.rs | 31 +- src/tools/compiletest/src/tests.rs | 7 + src/tools/compiletest/src/util.rs | 9 + src/tools/jsondocck/Cargo.toml | 1 + src/tools/jsondocck/src/cache.rs | 10 +- src/tools/jsondocck/src/main.rs | 20 +- src/tools/linkchecker/main.rs | 2 - src/tools/rust-demangler/Cargo.toml | 6 +- src/tools/rust-demangler/README.md | 36 + src/tools/rust-demangler/src/lib.rs | 21 + src/tools/rust-demangler/{ => src}/main.rs | 41 +- src/tools/rust-demangler/tests/lib.rs | 84 + src/tools/rustc-workspace-hack/Cargo.toml | 4 +- src/tools/rustdoc-js/tester.js | 15 +- src/tools/rustdoc/Cargo.toml | 3 + .../rustfmt/.github/workflows/integration.yml | 13 +- src/tools/rustfmt/.github/workflows/linux.yml | 24 +- src/tools/rustfmt/.github/workflows/mac.yml | 20 +- .../rustfmt/.github/workflows/windows.yml | 27 +- src/tools/rustfmt/CHANGELOG.md | 16 + src/tools/rustfmt/Cargo.lock | 855 +- src/tools/rustfmt/Cargo.toml | 40 +- src/tools/rustfmt/Configurations.md | 134 +- .../rustfmt/config_proc_macro/src/lib.rs | 2 - src/tools/rustfmt/rust-toolchain | 4 +- src/tools/rustfmt/src/attr.rs | 6 +- src/tools/rustfmt/src/bin/main.rs | 8 +- src/tools/rustfmt/src/cargo-fmt/main.rs | 2 - src/tools/rustfmt/src/chains.rs | 2 +- src/tools/rustfmt/src/comment.rs | 20 +- src/tools/rustfmt/src/config/config_type.rs | 115 +- src/tools/rustfmt/src/config/file_lines.rs | 4 +- src/tools/rustfmt/src/config/mod.rs | 295 +- src/tools/rustfmt/src/config/options.rs | 6 +- src/tools/rustfmt/src/expr.rs | 146 +- src/tools/rustfmt/src/format-diff/main.rs | 3 +- .../rustfmt/src/format_report_formatter.rs | 146 +- src/tools/rustfmt/src/formatting.rs | 10 +- src/tools/rustfmt/src/git-rustfmt/main.rs | 4 - src/tools/rustfmt/src/items.rs | 37 +- src/tools/rustfmt/src/lib.rs | 38 +- src/tools/rustfmt/src/lists.rs | 2 +- src/tools/rustfmt/src/macros.rs | 10 +- src/tools/rustfmt/src/matches.rs | 21 +- src/tools/rustfmt/src/modules.rs | 215 +- src/tools/rustfmt/src/overflow.rs | 10 +- src/tools/rustfmt/src/patterns.rs | 10 +- src/tools/rustfmt/src/source_file.rs | 7 +- src/tools/rustfmt/src/spanned.rs | 4 +- src/tools/rustfmt/src/syntux/parser.rs | 45 +- src/tools/rustfmt/src/syntux/session.rs | 133 +- src/tools/rustfmt/src/test/mod.rs | 7 +- src/tools/rustfmt/src/utils.rs | 4 + src/tools/rustfmt/src/vertical.rs | 4 +- src/tools/rustfmt/src/visitor.rs | 36 +- .../source/configs/chain_width/always.rs | 23 + .../tests/source/configs/chain_width/small.rs | 23 + .../tests/source/configs/chain_width/tiny.rs | 21 + .../configs/use_small_heuristics/default.rs | 25 + .../configs/use_small_heuristics/off.rs | 25 + src/tools/rustfmt/tests/source/issue-4312.rs | 22 + src/tools/rustfmt/tests/source/issue-4427.rs | 31 + src/tools/rustfmt/tests/source/issue-4603.rs | 47 + src/tools/rustfmt/tests/source/match.rs | 2 +- .../target/configs/chain_width/always.rs | 29 + .../tests/target/configs/chain_width/small.rs | 32 + .../tests/target/configs/chain_width/tiny.rs | 26 + .../configs/use_small_heuristics/default.rs | 26 + .../configs/use_small_heuristics/off.rs | 25 + src/tools/rustfmt/tests/target/issue-3592.rs | 13 - src/tools/rustfmt/tests/target/issue-4312.rs | 22 + src/tools/rustfmt/tests/target/issue-4427.rs | 30 + src/tools/rustfmt/tests/target/issue-4603.rs | 47 + src/tools/rustfmt/tests/target/issue_4049.rs | 26 + src/tools/rustfmt/tests/target/match.rs | 1 - src/tools/tidy/Cargo.toml | 1 + src/tools/tidy/src/bins.rs | 169 +- src/tools/tidy/src/deps.rs | 6 +- src/tools/tidy/src/error_codes_check.rs | 40 +- src/tools/tidy/src/features.rs | 9 + src/tools/tidy/src/lib.rs | 3 +- src/tools/tidy/src/main.rs | 121 +- src/tools/tidy/src/pal.rs | 22 - src/tools/tidy/src/style.rs | 28 +- src/tools/tidy/src/ui_tests.rs | 4 +- src/version | 2 +- .../.cargo-checksum.json | 1 - vendor/annotate-snippets-0.6.1/CHANGELOG.md | 15 - vendor/annotate-snippets-0.6.1/Cargo.toml | 55 - vendor/annotate-snippets-0.6.1/LICENSE-APACHE | 201 - vendor/annotate-snippets-0.6.1/LICENSE-MIT | 19 - vendor/annotate-snippets-0.6.1/README.md | 88 - .../examples/expected_type.rs | 40 - .../examples/footer.rs | 37 - .../examples/format.rs | 58 - .../examples/multislice.rs | 34 - .../src/display_list/from_snippet.rs | 403 - .../src/display_list/mod.rs | 124 - .../src/display_list/structs.rs | 253 - .../src/formatter/mod.rs | 367 - .../src/formatter/style.rs | 98 - vendor/annotate-snippets-0.6.1/src/lib.rs | 54 - vendor/annotate-snippets-0.6.1/src/snippet.rs | 81 - .../src/stylesheets/color.rs | 43 - .../src/stylesheets/mod.rs | 11 - .../src/stylesheets/no_color.rs | 21 - .../annotate-snippets-0.6.1/tests/diff/mod.rs | 43 - .../tests/dl_from_snippet.rs | 256 - .../annotate-snippets-0.6.1/tests/fixtures.rs | 57 - .../no-color/multiline_annotation.txt | 14 - .../no-color/multiline_annotation.yaml | 38 - .../no-color/multiline_annotation2.txt | 9 - .../no-color/multiline_annotation2.yaml | 16 - .../no-color/multiple_annotations.txt | 14 - .../no-color/multiple_annotations.yaml | 23 - .../tests/fixtures/no-color/simple.txt | 9 - .../tests/fixtures/no-color/simple.yaml | 17 - .../tests/formatter.rs | 551 - .../tests/snippet/mod.rs | 105 - vendor/anyhow/.cargo-checksum.json | 2 +- vendor/anyhow/Cargo.toml | 5 +- vendor/anyhow/README.md | 4 +- vendor/anyhow/build.rs | 9 + vendor/anyhow/src/backtrace.rs | 377 +- vendor/anyhow/src/error.rs | 157 +- vendor/anyhow/src/fmt.rs | 4 +- vendor/anyhow/src/kind.rs | 3 - vendor/anyhow/src/lib.rs | 8 +- vendor/anyhow/src/ptr.rs | 107 +- vendor/anyhow/tests/ui/no-impl.stderr | 6 +- vendor/arrayref/.cargo-checksum.json | 1 - vendor/arrayref/Cargo.lock | 256 - vendor/arrayref/LICENSE | 26 - vendor/arrayref/README.md | 109 - vendor/arrayref/examples/array_refs.rs | 13 - .../examples/array_refs_with_const.rs | 18 - vendor/arrayref/examples/simple-case.rs | 15 - vendor/arrayref/src/lib.rs | 476 - vendor/arrayvec/.cargo-checksum.json | 2 +- vendor/arrayvec/CHANGELOG.md | 148 +- vendor/arrayvec/Cargo.toml | 7 +- vendor/arrayvec/README.md | 7 +- vendor/arrayvec/benches/arraystring.rs | 12 +- vendor/arrayvec/benches/extend.rs | 10 +- vendor/arrayvec/ci/miri.sh | 2 +- vendor/arrayvec/custom.css | 25 - vendor/arrayvec/src/array.rs | 151 - vendor/arrayvec/src/array_string.rs | 236 +- vendor/arrayvec/src/arrayvec.rs | 1232 + vendor/arrayvec/src/arrayvec_impl.rs | 86 + vendor/arrayvec/src/char.rs | 27 +- vendor/arrayvec/src/lib.rs | 1200 +- vendor/arrayvec/src/maybe_uninit.rs | 44 - vendor/arrayvec/src/utils.rs | 11 + vendor/arrayvec/tests/serde.rs | 12 +- vendor/arrayvec/tests/tests.rs | 196 +- vendor/base64/.cargo-checksum.json | 1 - vendor/base64/Cargo.lock | 621 - vendor/base64/Cargo.toml | 43 - vendor/base64/LICENSE-MIT | 21 - vendor/base64/README.md | 114 - vendor/base64/RELEASE-NOTES.md | 84 - vendor/base64/benches/benchmarks.rs | 160 - vendor/base64/examples/make_tables.rs | 116 - vendor/base64/icon_CLion.svg | 34 - vendor/base64/src/chunked_encoder.rs | 248 - vendor/base64/src/decode.rs | 862 - vendor/base64/src/display.rs | 88 - vendor/base64/src/encode.rs | 673 - vendor/base64/src/lib.rs | 203 - vendor/base64/src/tables.rs | 979 - vendor/base64/src/tests.rs | 79 - vendor/base64/src/write/encoder.rs | 355 - vendor/base64/src/write/encoder_tests.rs | 568 - vendor/base64/src/write/mod.rs | 6 - vendor/base64/tests/decode.rs | 310 - vendor/base64/tests/encode.rs | 105 - vendor/base64/tests/helpers.rs | 14 - vendor/base64/tests/tests.rs | 194 - vendor/blake2b_simd/.cargo-checksum.json | 1 - vendor/blake2b_simd/README.md | 42 - vendor/blake2b_simd/src/avx2.rs | 928 - vendor/blake2b_simd/src/blake2bp.rs | 570 - vendor/blake2b_simd/src/guts.rs | 565 - vendor/blake2b_simd/src/lib.rs | 674 - vendor/blake2b_simd/src/many.rs | 529 - vendor/blake2b_simd/src/portable.rs | 168 - vendor/blake2b_simd/src/sse41.rs | 460 - vendor/blake2b_simd/src/test.rs | 201 - vendor/bytecount/.cargo-checksum.json | 2 +- vendor/bytecount/Cargo.toml | 5 +- vendor/bytecount/ci/miri.sh | 15 + vendor/bytecount/src/integer_simd.rs | 2 +- vendor/bytecount/src/simd/generic.rs | 12 +- vendor/bytecount/src/simd/x86_avx2.rs | 2 +- vendor/bytecount/tests/check.rs | 27 +- vendor/constant_time_eq/.cargo-checksum.json | 1 - vendor/constant_time_eq/Cargo.toml | 25 - vendor/constant_time_eq/LICENSE.txt | 121 - vendor/constant_time_eq/README | 3 - vendor/constant_time_eq/benches/bench.rs | 29 - vendor/constant_time_eq/src/lib.rs | 105 - vendor/crossbeam-channel/.cargo-checksum.json | 2 +- vendor/crossbeam-channel/CHANGELOG.md | 4 + vendor/crossbeam-channel/Cargo.lock | 77 +- vendor/crossbeam-channel/Cargo.toml | 7 +- vendor/crossbeam-channel/LICENSE-THIRD-PARTY | 32 - vendor/crossbeam-channel/README.md | 10 +- .../crossbeam-channel/examples/stopwatch.rs | 4 +- vendor/crossbeam-channel/src/channel.rs | 10 +- vendor/crossbeam-channel/src/counter.rs | 14 +- vendor/crossbeam-channel/src/flavors/array.rs | 50 +- vendor/crossbeam-channel/src/flavors/at.rs | 23 +- vendor/crossbeam-channel/src/flavors/list.rs | 116 +- vendor/crossbeam-channel/src/flavors/mod.rs | 12 +- vendor/crossbeam-channel/src/flavors/never.rs | 21 +- vendor/crossbeam-channel/src/flavors/tick.rs | 21 +- vendor/crossbeam-channel/src/flavors/zero.rs | 41 +- vendor/crossbeam-channel/src/lib.rs | 11 +- vendor/crossbeam-channel/src/select.rs | 5 +- vendor/crossbeam-channel/src/utils.rs | 12 +- vendor/crossbeam-channel/src/waker.rs | 46 +- vendor/crossbeam-channel/tests/array.rs | 4 +- vendor/crossbeam-channel/tests/golang.rs | 57 +- vendor/crossbeam-channel/tests/list.rs | 4 +- vendor/crossbeam-channel/tests/ready.rs | 8 +- vendor/crossbeam-channel/tests/select.rs | 8 +- vendor/crossbeam-channel/tests/tick.rs | 2 + vendor/crossbeam-channel/tests/zero.rs | 2 +- vendor/dirs-sys/.cargo-checksum.json | 2 +- vendor/dirs-sys/Cargo.toml | 5 +- vendor/dirs-sys/src/lib.rs | 1 + vendor/fs_extra/.cargo-checksum.json | 1 - vendor/fs_extra/Cargo.toml | 25 - vendor/fs_extra/LICENSE | 21 - vendor/fs_extra/README.md | 134 - vendor/fs_extra/src/dir.rs | 1349 - vendor/fs_extra/src/error.rs | 158 - vendor/fs_extra/src/file.rs | 392 - vendor/fs_extra/src/lib.rs | 807 - vendor/fs_extra/tests/dir.rs | 4753 --- vendor/fs_extra/tests/file.rs | 1036 - vendor/fs_extra/tests/lib.rs | 3861 -- vendor/idna/.cargo-checksum.json | 2 +- vendor/idna/Cargo.toml | 2 +- vendor/idna/src/punycode.rs | 4 + vendor/idna/src/uts46.rs | 1 - vendor/idna/tests/unit.rs | 6 + vendor/ignore/.cargo-checksum.json | 2 +- vendor/ignore/Cargo.lock | 71 +- vendor/ignore/Cargo.toml | 6 +- vendor/ignore/README.md | 5 +- vendor/ignore/src/default_types.rs | 9 +- vendor/ignore/src/lib.rs | 65 + vendor/ignore/src/types.rs | 2 +- vendor/jobserver/.cargo-checksum.json | 2 +- vendor/jobserver/Cargo.toml | 2 +- vendor/jobserver/README.md | 2 +- vendor/jobserver/src/lib.rs | 8 +- vendor/jobserver/src/unix.rs | 45 +- vendor/jobserver/tests/client-of-myself.rs | 2 - vendor/jobserver/tests/client.rs | 15 +- vendor/jobserver/tests/helper.rs | 2 +- vendor/jobserver/tests/make-as-a-client.rs | 5 +- vendor/jobserver/tests/server.rs | 7 +- vendor/libc/.cargo-checksum.json | 2 +- vendor/libc/CONTRIBUTING.md | 18 +- vendor/libc/Cargo.toml | 2 +- vendor/libc/build.rs | 9 +- vendor/libc/rustfmt.toml | 4 +- vendor/libc/src/fuchsia/mod.rs | 585 +- vendor/libc/src/psp.rs | 888 +- vendor/libc/src/unix/bsd/apple/mod.rs | 322 +- .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 28 +- .../bsd/freebsdlike/freebsd/freebsd11/mod.rs | 6 +- .../bsd/freebsdlike/freebsd/freebsd12/mod.rs | 12 +- .../bsd/freebsdlike/freebsd/freebsd13/mod.rs | 12 +- .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 210 +- vendor/libc/src/unix/bsd/freebsdlike/mod.rs | 139 +- vendor/libc/src/unix/bsd/mod.rs | 76 +- vendor/libc/src/unix/bsd/netbsdlike/mod.rs | 73 +- .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 77 +- .../src/unix/bsd/netbsdlike/openbsd/mod.rs | 36 +- vendor/libc/src/unix/haiku/mod.rs | 150 +- vendor/libc/src/unix/haiku/native.rs | 167 +- vendor/libc/src/unix/hermit/mod.rs | 29 +- .../src/unix/linux_like/android/b32/mod.rs | 6 +- .../libc/src/unix/linux_like/android/mod.rs | 168 +- .../src/unix/linux_like/emscripten/mod.rs | 87 +- .../unix/linux_like/linux/arch/generic/mod.rs | 100 + .../unix/linux_like/linux/arch/mips/mod.rs | 96 + .../src/unix/linux_like/linux/arch/mod.rs | 15 + .../unix/linux_like/linux/arch/powerpc/mod.rs | 91 + .../unix/linux_like/linux/arch/sparc/mod.rs | 88 + .../unix/linux_like/linux/gnu/b32/arm/mod.rs | 42 +- .../unix/linux_like/linux/gnu/b32/mips/mod.rs | 66 +- .../src/unix/linux_like/linux/gnu/b32/mod.rs | 14 - .../unix/linux_like/linux/gnu/b32/powerpc.rs | 43 +- .../linux_like/linux/gnu/b32/riscv32/mod.rs | 65 +- .../linux_like/linux/gnu/b32/sparc/mod.rs | 42 +- .../unix/linux_like/linux/gnu/b32/x86/mod.rs | 55 +- .../linux_like/linux/gnu/b64/aarch64/mod.rs | 91 +- .../linux_like/linux/gnu/b64/mips64/mod.rs | 73 +- .../linux_like/linux/gnu/b64/powerpc64/mod.rs | 72 +- .../linux_like/linux/gnu/b64/riscv64/mod.rs | 71 +- .../unix/linux_like/linux/gnu/b64/s390x.rs | 61 +- .../linux_like/linux/gnu/b64/sparc64/mod.rs | 48 +- .../linux_like/linux/gnu/b64/x86_64/mod.rs | 92 +- .../linux/gnu/b64/x86_64/not_x32.rs | 17 + .../linux_like/linux/gnu/b64/x86_64/x32.rs | 17 + .../libc/src/unix/linux_like/linux/gnu/mod.rs | 99 +- vendor/libc/src/unix/linux_like/linux/mod.rs | 440 +- .../unix/linux_like/linux/musl/b32/arm/mod.rs | 53 +- .../unix/linux_like/linux/musl/b32/hexagon.rs | 48 +- .../linux_like/linux/musl/b32/mips/mod.rs | 47 +- .../unix/linux_like/linux/musl/b32/powerpc.rs | 53 +- .../unix/linux_like/linux/musl/b32/x86/mod.rs | 53 +- .../linux_like/linux/musl/b64/aarch64/mod.rs | 46 +- .../unix/linux_like/linux/musl/b64/mips64.rs | 68 +- .../src/unix/linux_like/linux/musl/b64/mod.rs | 6 +- .../linux_like/linux/musl/b64/powerpc64.rs | 46 +- .../unix/linux_like/linux/musl/b64/s390x.rs | 43 +- .../linux_like/linux/musl/b64/x86_64/mod.rs | 46 +- .../src/unix/linux_like/linux/musl/mod.rs | 8 +- .../unix/linux_like/linux/uclibc/arm/mod.rs | 32 +- .../linux/uclibc/mips/mips32/mod.rs | 4 +- .../unix/linux_like/linux/uclibc/mips/mod.rs | 53 - .../src/unix/linux_like/linux/uclibc/mod.rs | 3 +- .../linux_like/linux/uclibc/x86_64/mod.rs | 7 - vendor/libc/src/unix/linux_like/mod.rs | 130 +- vendor/libc/src/unix/mod.rs | 345 +- vendor/libc/src/unix/newlib/mod.rs | 36 +- vendor/libc/src/unix/newlib/no_align.rs | 2 +- vendor/libc/src/unix/newlib/xtensa/mod.rs | 21 +- vendor/libc/src/unix/redox/mod.rs | 50 +- vendor/libc/src/unix/solarish/compat.rs | 20 +- vendor/libc/src/unix/solarish/illumos.rs | 6 +- vendor/libc/src/unix/solarish/mod.rs | 203 +- vendor/libc/src/unix/solarish/solaris.rs | 11 +- vendor/libc/src/vxworks/mod.rs | 437 +- vendor/libc/src/wasi.rs | 285 +- vendor/libc/src/windows/gnu/mod.rs | 12 +- vendor/libc/src/windows/mod.rs | 167 +- vendor/libc/src/windows/msvc.rs | 6 +- vendor/libm/.cargo-checksum.json | 1 + vendor/libm/CHANGELOG.md | 97 + vendor/libm/CONTRIBUTING.md | 95 + vendor/{blake2b_simd => libm}/Cargo.toml | 38 +- vendor/{base64 => libm}/LICENSE-APACHE | 0 vendor/{socket2 => libm}/LICENSE-MIT | 2 +- vendor/libm/README.md | 58 + vendor/libm/azure-pipelines.yml | 73 + vendor/libm/build.rs | 444 + vendor/libm/ci/azure-install-rust.yml | 25 + .../aarch64-unknown-linux-gnu/Dockerfile | 10 + .../arm-unknown-linux-gnueabi/Dockerfile | 9 + .../arm-unknown-linux-gnueabihf/Dockerfile | 9 + .../armv7-unknown-linux-gnueabihf/Dockerfile | 9 + .../docker/i686-unknown-linux-gnu/Dockerfile | 4 + .../docker/mips-unknown-linux-gnu/Dockerfile | 12 + .../mips64-unknown-linux-gnuabi64/Dockerfile | 15 + .../Dockerfile | 14 + .../mipsel-unknown-linux-gnu/Dockerfile | 12 + .../powerpc-unknown-linux-gnu/Dockerfile | 12 + .../powerpc64-unknown-linux-gnu/Dockerfile | 13 + .../powerpc64le-unknown-linux-gnu/Dockerfile | 13 + .../x86_64-unknown-linux-gnu/Dockerfile | 4 + vendor/libm/ci/run-docker.sh | 37 + vendor/libm/ci/run.sh | 11 + vendor/libm/src/lib.rs | 642 + vendor/libm/src/math/acos.rs | 114 + vendor/libm/src/math/acosf.rs | 81 + vendor/libm/src/math/acosh.rs | 26 + vendor/libm/src/math/acoshf.rs | 25 + vendor/libm/src/math/asin.rs | 121 + vendor/libm/src/math/asinf.rs | 74 + vendor/libm/src/math/asinh.rs | 39 + vendor/libm/src/math/asinhf.rs | 38 + vendor/libm/src/math/atan.rs | 185 + vendor/libm/src/math/atan2.rs | 127 + vendor/libm/src/math/atan2f.rs | 92 + vendor/libm/src/math/atanf.rs | 113 + vendor/libm/src/math/atanh.rs | 36 + vendor/libm/src/math/atanhf.rs | 36 + vendor/libm/src/math/cbrt.rs | 114 + vendor/libm/src/math/cbrtf.rs | 76 + vendor/libm/src/math/ceil.rs | 51 + vendor/libm/src/math/ceilf.rs | 42 + vendor/libm/src/math/copysign.rs | 11 + vendor/libm/src/math/copysignf.rs | 11 + vendor/libm/src/math/cos.rs | 74 + vendor/libm/src/math/cosf.rs | 84 + vendor/libm/src/math/cosh.rs | 39 + vendor/libm/src/math/coshf.rs | 39 + vendor/libm/src/math/erf.rs | 317 + vendor/libm/src/math/erff.rs | 229 + vendor/libm/src/math/exp.rs | 155 + vendor/libm/src/math/exp10.rs | 21 + vendor/libm/src/math/exp10f.rs | 21 + vendor/libm/src/math/exp2.rs | 395 + vendor/libm/src/math/exp2f.rs | 136 + vendor/libm/src/math/expf.rs | 102 + vendor/libm/src/math/expm1.rs | 145 + vendor/libm/src/math/expm1f.rs | 135 + vendor/libm/src/math/expo2.rs | 15 + vendor/libm/src/math/fabs.rs | 18 + vendor/libm/src/math/fabsf.rs | 16 + vendor/libm/src/math/fdim.rs | 23 + vendor/libm/src/math/fdimf.rs | 23 + vendor/libm/src/math/fenv.rs | 33 + vendor/libm/src/math/floor.rs | 41 + vendor/libm/src/math/floorf.rs | 50 + vendor/libm/src/math/fma.rs | 207 + vendor/libm/src/math/fmaf.rs | 107 + vendor/libm/src/math/fmax.rs | 13 + vendor/libm/src/math/fmaxf.rs | 13 + vendor/libm/src/math/fmin.rs | 13 + vendor/libm/src/math/fminf.rs | 13 + vendor/libm/src/math/fmod.rs | 81 + vendor/libm/src/math/fmodf.rs | 90 + vendor/libm/src/math/frexp.rs | 20 + vendor/libm/src/math/frexpf.rs | 21 + vendor/libm/src/math/hypot.rs | 76 + vendor/libm/src/math/hypotf.rs | 44 + vendor/libm/src/math/ilogb.rs | 31 + vendor/libm/src/math/ilogbf.rs | 31 + vendor/libm/src/math/j0.rs | 422 + vendor/libm/src/math/j0f.rs | 359 + vendor/libm/src/math/j1.rs | 414 + vendor/libm/src/math/j1f.rs | 358 + vendor/libm/src/math/jn.rs | 343 + vendor/libm/src/math/jnf.rs | 259 + vendor/libm/src/math/k_cos.rs | 63 + vendor/libm/src/math/k_cosf.rs | 30 + vendor/libm/src/math/k_expo2.rs | 15 + vendor/libm/src/math/k_expo2f.rs | 15 + vendor/libm/src/math/k_sin.rs | 58 + vendor/libm/src/math/k_sinf.rs | 31 + vendor/libm/src/math/k_tan.rs | 107 + vendor/libm/src/math/k_tanf.rs | 47 + vendor/libm/src/math/ldexp.rs | 5 + vendor/libm/src/math/ldexpf.rs | 5 + vendor/libm/src/math/lgamma.rs | 5 + vendor/libm/src/math/lgamma_r.rs | 319 + vendor/libm/src/math/lgammaf.rs | 5 + vendor/libm/src/math/lgammaf_r.rs | 254 + vendor/libm/src/math/log.rs | 118 + vendor/libm/src/math/log10.rs | 118 + vendor/libm/src/math/log10f.rs | 92 + vendor/libm/src/math/log1p.rs | 144 + vendor/libm/src/math/log1pf.rs | 99 + vendor/libm/src/math/log2.rs | 107 + vendor/libm/src/math/log2f.rs | 88 + vendor/libm/src/math/logf.rs | 66 + vendor/libm/src/math/mod.rs | 342 + vendor/libm/src/math/modf.rs | 34 + vendor/libm/src/math/modff.rs | 33 + vendor/libm/src/math/pow.rs | 634 + vendor/libm/src/math/powf.rs | 343 + vendor/libm/src/math/rem_pio2.rs | 207 + vendor/libm/src/math/rem_pio2_large.rs | 471 + vendor/libm/src/math/rem_pio2f.rs | 63 + vendor/libm/src/math/remquo.rs | 97 + vendor/libm/src/math/remquof.rs | 96 + vendor/libm/src/math/round.rs | 37 + vendor/libm/src/math/roundf.rs | 35 + vendor/libm/src/math/scalbn.rs | 34 + vendor/libm/src/math/scalbnf.rs | 30 + vendor/libm/src/math/sin.rs | 86 + vendor/libm/src/math/sincos.rs | 59 + vendor/libm/src/math/sincosf.rs | 123 + vendor/libm/src/math/sinf.rs | 94 + vendor/libm/src/math/sinh.rs | 50 + vendor/libm/src/math/sinhf.rs | 31 + vendor/libm/src/math/sqrt.rs | 223 + vendor/libm/src/math/sqrtf.rs | 112 + vendor/libm/src/math/tan.rs | 71 + vendor/libm/src/math/tanf.rs | 79 + vendor/libm/src/math/tanh.rs | 54 + vendor/libm/src/math/tanhf.rs | 40 + vendor/libm/src/math/tgamma.rs | 207 + vendor/libm/src/math/tgammaf.rs | 5 + vendor/libm/src/math/trunc.rs | 41 + vendor/libm/src/math/truncf.rs | 41 + vendor/lock_api/.cargo-checksum.json | 2 +- vendor/lock_api/Cargo.toml | 2 +- vendor/lock_api/src/remutex.rs | 13 + vendor/memmap2/.cargo-checksum.json | 2 +- vendor/memmap2/CHANGELOG.md | 14 +- vendor/memmap2/Cargo.lock | 2 +- vendor/memmap2/Cargo.toml | 2 +- vendor/memmap2/src/lib.rs | 124 +- vendor/memmap2/src/unix.rs | 53 +- vendor/memmap2/src/windows.rs | 68 +- vendor/memoffset/.cargo-checksum.json | 2 +- vendor/memoffset/Cargo.toml | 3 +- vendor/memoffset/README.md | 5 - vendor/memoffset/build.rs | 3 + vendor/memoffset/src/lib.rs | 19 +- vendor/memoffset/src/offset_of.rs | 20 +- vendor/memoffset/src/raw_field.rs | 20 +- vendor/memoffset/src/span_of.rs | 42 +- vendor/miow/.cargo-checksum.json | 2 +- vendor/miow/CHANGELOG.md | 5 + vendor/miow/Cargo.toml | 10 +- vendor/miow/src/lib.rs | 6 - vendor/miow/src/net.rs | 16 +- vendor/miow/src/pipe.rs | 8 +- vendor/packed_simd/.cargo-checksum.json | 1 - vendor/packed_simd/src/codegen/shuffle.rs | 302 - vendor/packed_simd_2/.cargo-checksum.json | 1 + .../{packed_simd => packed_simd_2}/Cargo.toml | 33 +- .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 .../readme.md => packed_simd_2/README.md} | 111 +- .../{packed_simd => packed_simd_2}/bors.toml | 0 .../{packed_simd => packed_simd_2}/build.rs | 0 .../{packed_simd => packed_simd_2}/ci/all.sh | 23 +- .../ci/android-install-ndk.sh | 0 .../ci/android-install-sdk.sh | 0 .../ci/android-sysimage.sh | 0 .../ci/benchmark.sh | 0 .../ci/deploy_and_run_on_ios_simulator.rs | 0 .../docker/aarch64-linux-android/Dockerfile | 0 .../aarch64-unknown-linux-gnu/Dockerfile | 2 +- .../docker/arm-linux-androideabi/Dockerfile | 0 .../arm-unknown-linux-gnueabi/Dockerfile | 2 +- .../arm-unknown-linux-gnueabihf/Dockerfile | 2 +- .../armv7-unknown-linux-gnueabihf/Dockerfile | 2 +- .../docker/i586-unknown-linux-gnu/Dockerfile | 2 +- .../docker/i686-unknown-linux-gnu/Dockerfile | 2 +- .../docker/mips-unknown-linux-gnu/Dockerfile | 2 +- .../mips64-unknown-linux-gnuabi64/Dockerfile | 2 +- .../Dockerfile | 2 +- .../mipsel-unknown-linux-musl/Dockerfile | 4 +- .../powerpc-unknown-linux-gnu/Dockerfile | 3 +- .../powerpc64-unknown-linux-gnu/Dockerfile | 2 +- .../powerpc64le-unknown-linux-gnu/Dockerfile | 2 +- .../docker/s390x-unknown-linux-gnu/Dockerfile | 0 .../sparc64-unknown-linux-gnu/Dockerfile | 0 .../thumbv7neon-linux-androideabi/Dockerfile | 0 .../Dockerfile | 2 +- .../docker/wasm32-unknown-unknown/Dockerfile | 0 .../ci/docker/x86_64-linux-android/Dockerfile | 0 .../Dockerfile | 0 .../x86_64-unknown-linux-gnu/Dockerfile | 2 +- .../{packed_simd => packed_simd_2}/ci/dox.sh | 7 +- .../ci/linux-s390x.sh | 0 .../ci/linux-sparc64.sh | 0 .../ci/lld-shim.rs | 0 .../ci/max_line_width.sh | 0 .../ci/run-docker.sh | 0 .../{packed_simd => packed_simd_2}/ci/run.sh | 6 +- .../ci/run_examples.sh | 0 .../ci/runtest-android.rs | 0 .../ci/setup_benchmarks.sh | 3 - .../ci/test-runner-linux | 0 .../contributing.md | 0 .../perf-guide/book.toml | 0 .../perf-guide/src/SUMMARY.md | 0 .../perf-guide/src/ascii.css | 0 .../perf-guide/src/bound_checks.md | 0 .../perf-guide/src/float-math/approx.md | 0 .../perf-guide/src/float-math/fma.md | 0 .../perf-guide/src/float-math/fp.md | 0 .../perf-guide/src/float-math/svml.md | 0 .../perf-guide/src/introduction.md | 0 .../perf-guide/src/prof/linux.md | 0 .../perf-guide/src/prof/mca.md | 0 .../perf-guide/src/prof/profiling.md | 0 .../src/target-feature/attribute.md | 0 .../perf-guide/src/target-feature/features.md | 0 .../perf-guide/src/target-feature/inlining.md | 0 .../perf-guide/src/target-feature/practice.md | 0 .../perf-guide/src/target-feature/runtime.md | 0 .../src/target-feature/rustflags.md | 0 .../perf-guide/src/vert-hor-ops.md | 0 .../rust-toolchain | 0 .../rustfmt.toml | 0 .../{packed_simd => packed_simd_2}/src/api.rs | 1 + .../src/api/bit_manip.rs | 1 + .../src/api/bitmask.rs | 0 .../src/api/cast.rs | 8 +- .../src/api/cast/macros.rs | 0 .../src/api/cast/v128.rs | 2 +- .../src/api/cast/v16.rs | 2 +- .../src/api/cast/v256.rs | 2 +- .../src/api/cast/v32.rs | 2 +- .../src/api/cast/v512.rs | 2 +- .../src/api/cast/v64.rs | 2 +- .../src/api/cmp.rs | 0 .../src/api/cmp/eq.rs | 0 .../src/api/cmp/ord.rs | 0 .../src/api/cmp/partial_eq.rs | 9 +- .../src/api/cmp/partial_ord.rs | 0 .../src/api/cmp/vertical.rs | 0 .../src/api/default.rs | 2 + .../src/api/fmt.rs | 0 .../src/api/fmt/binary.rs | 14 +- .../src/api/fmt/debug.rs | 10 +- .../src/api/fmt/lower_hex.rs | 14 +- .../src/api/fmt/octal.rs | 14 +- .../src/api/fmt/upper_hex.rs | 14 +- .../src/api/from.rs | 0 .../src/api/from/from_array.rs | 2 + .../src/api/from/from_vector.rs | 0 .../src/api/hash.rs | 2 + .../src/api/into_bits.rs | 0 .../src/api/into_bits/arch_specific.rs | 3 +- .../src/api/into_bits/macros.rs | 0 .../src/api/into_bits/v128.rs | 2 +- .../src/api/into_bits/v16.rs | 2 +- .../src/api/into_bits/v256.rs | 2 +- .../src/api/into_bits/v32.rs | 2 +- .../src/api/into_bits/v512.rs | 2 +- .../src/api/into_bits/v64.rs | 2 +- .../src/api/math.rs | 0 .../src/api/math/float.rs | 3 + .../src/api/math/float/abs.rs | 0 .../src/api/math/float/consts.rs | 0 .../src/api/math/float/cos.rs | 0 .../src/api/math/float/exp.rs | 0 .../src/api/math/float/ln.rs | 0 .../src/api/math/float/mul_add.rs | 0 .../src/api/math/float/mul_adde.rs | 0 .../src/api/math/float/powf.rs | 0 .../src/api/math/float/recpre.rs | 0 .../src/api/math/float/rsqrte.rs | 0 .../src/api/math/float/sin.rs | 0 .../src/api/math/float/sqrt.rs | 0 .../src/api/math/float/sqrte.rs | 0 .../packed_simd_2/src/api/math/float/tanh.rs | 29 + .../src/api/minimal.rs | 0 .../src/api/minimal/iuf.rs | 9 +- .../src/api/minimal/mask.rs | 12 +- .../src/api/minimal/ptr.rs | 53 +- .../src/api/ops.rs | 0 .../src/api/ops/scalar_arithmetic.rs | 0 .../src/api/ops/scalar_bitwise.rs | 0 .../src/api/ops/scalar_mask_bitwise.rs | 0 .../src/api/ops/scalar_shifts.rs | 0 .../src/api/ops/vector_arithmetic.rs | 0 .../src/api/ops/vector_bitwise.rs | 0 .../src/api/ops/vector_float_min_max.rs | 5 + .../src/api/ops/vector_int_min_max.rs | 0 .../src/api/ops/vector_mask_bitwise.rs | 0 .../src/api/ops/vector_neg.rs | 0 .../src/api/ops/vector_rotates.rs | 0 .../src/api/ops/vector_shifts.rs | 0 .../src/api/ptr.rs | 0 .../src/api/ptr/gather_scatter.rs | 36 +- .../src/api/reductions.rs | 0 .../src/api/reductions/bitwise.rs | 0 .../src/api/reductions/float_arithmetic.rs | 13 +- .../src/api/reductions/integer_arithmetic.rs | 0 .../src/api/reductions/mask.rs | 11 +- .../src/api/reductions/min_max.rs | 4 + .../src/api/select.rs | 0 .../src/api/shuffle.rs | 0 .../src/api/shuffle1_dyn.rs | 0 .../src/api/slice.rs | 0 .../src/api/slice/from_slice.rs | 11 +- .../src/api/slice/write_to_slice.rs | 24 +- .../src/api/swap_bytes.rs | 0 .../src/codegen.rs | 3 + .../src/codegen/bit_manip.rs | 2 +- .../src/codegen/llvm.rs | 6 + .../src/codegen/math.rs | 0 .../src/codegen/math/float.rs | 3 +- .../src/codegen/math/float/abs.rs | 0 .../src/codegen/math/float/cos.rs | 0 .../src/codegen/math/float/cos_pi.rs | 0 .../src/codegen/math/float/exp.rs | 0 .../src/codegen/math/float/ln.rs | 0 .../src/codegen/math/float/macros.rs | 0 .../src/codegen/math/float/mul_add.rs | 0 .../src/codegen/math/float/mul_adde.rs | 0 .../src/codegen/math/float/powf.rs | 0 .../src/codegen/math/float/sin.rs | 0 .../src/codegen/math/float/sin_cos_pi.rs | 0 .../src/codegen/math/float/sin_pi.rs | 0 .../src/codegen/math/float/sqrt.rs | 0 .../src/codegen/math/float/sqrte.rs | 0 .../src/codegen/math/float/tanh.rs | 117 + .../src/codegen/pointer_sized_int.rs | 0 .../src/codegen/reductions.rs | 0 .../src/codegen/reductions/mask.rs | 0 .../src/codegen/reductions/mask/aarch64.rs | 0 .../src/codegen/reductions/mask/arm.rs | 0 .../src/codegen/reductions/mask/fallback.rs | 0 .../codegen/reductions/mask/fallback_impl.rs | 0 .../src/codegen/reductions/mask/x86.rs | 8 +- .../src/codegen/reductions/mask/x86/avx.rs | 0 .../src/codegen/reductions/mask/x86/avx2.rs | 0 .../src/codegen/reductions/mask/x86/sse.rs | 32 - .../src/codegen/reductions/mask/x86/sse2.rs | 0 vendor/packed_simd_2/src/codegen/shuffle.rs | 150 + .../src/codegen/shuffle1_dyn.rs | 35 +- .../src/codegen/swap_bytes.rs | 10 +- .../src/codegen/v128.rs | 0 .../src/codegen/v16.rs | 0 .../src/codegen/v256.rs | 0 .../src/codegen/v32.rs | 0 .../src/codegen/v512.rs | 0 .../src/codegen/v64.rs | 0 .../src/codegen/vPtr.rs | 2 + .../src/codegen/vSize.rs | 0 .../{packed_simd => packed_simd_2}/src/lib.rs | 37 +- .../src/masks.rs | 4 +- .../src/sealed.rs | 15 +- .../src/testing.rs | 0 .../src/testing/macros.rs | 0 .../src/testing/utils.rs | 25 +- .../src/v128.rs | 2 +- .../{packed_simd => packed_simd_2}/src/v16.rs | 0 .../src/v256.rs | 2 +- .../{packed_simd => packed_simd_2}/src/v32.rs | 0 .../src/v512.rs | 2 +- .../{packed_simd => packed_simd_2}/src/v64.rs | 2 +- .../src/vPtr.rs | 2 +- .../src/vSize.rs | 2 +- .../tests/endianness.rs | 62 +- vendor/proc-macro2/.cargo-checksum.json | 2 +- vendor/proc-macro2/Cargo.toml | 4 +- vendor/proc-macro2/src/fallback.rs | 19 +- vendor/proc-macro2/src/lib.rs | 39 +- vendor/proc-macro2/src/parse.rs | 191 +- vendor/proc-macro2/src/wrapper.rs | 24 +- vendor/proc-macro2/tests/test.rs | 20 +- vendor/rand/.cargo-checksum.json | 1 + vendor/rand/CHANGELOG.md | 667 + vendor/rand/COPYRIGHT | 12 + vendor/rand/Cargo.toml | 80 + vendor/{socket2 => rand}/LICENSE-APACHE | 4 +- vendor/rand/LICENSE-MIT | 26 + vendor/rand/README.md | 148 + vendor/rand/src/distributions/bernoulli.rs | 211 + vendor/rand/src/distributions/float.rs | 312 + vendor/rand/src/distributions/integer.rs | 279 + vendor/rand/src/distributions/mod.rs | 372 + vendor/rand/src/distributions/other.rs | 313 + vendor/rand/src/distributions/uniform.rs | 1625 + vendor/rand/src/distributions/utils.rs | 429 + vendor/rand/src/distributions/weighted.rs | 48 + .../rand/src/distributions/weighted_index.rs | 453 + vendor/rand/src/lib.rs | 215 + vendor/rand/src/prelude.rs | 34 + vendor/rand/src/rng.rs | 585 + vendor/rand/src/rngs/adapter/mod.rs | 15 + vendor/rand/src/rngs/adapter/read.rs | 157 + vendor/rand/src/rngs/adapter/reseeding.rs | 370 + vendor/rand/src/rngs/mock.rs | 87 + vendor/rand/src/rngs/mod.rs | 119 + vendor/rand/src/rngs/small.rs | 117 + vendor/rand/src/rngs/std.rs | 102 + vendor/rand/src/rngs/thread.rs | 142 + vendor/rand/src/rngs/xoshiro128plusplus.rs | 118 + vendor/rand/src/rngs/xoshiro256plusplus.rs | 122 + vendor/rand/src/seq/index.rs | 678 + vendor/rand/src/seq/mod.rs | 1359 + vendor/rand_chacha/.cargo-checksum.json | 1 + vendor/rand_chacha/CHANGELOG.md | 30 + vendor/rand_chacha/COPYRIGHT | 12 + vendor/rand_chacha/Cargo.toml | 37 + vendor/rand_chacha/LICENSE-APACHE | 201 + vendor/rand_chacha/LICENSE-MIT | 26 + vendor/rand_chacha/README.md | 48 + vendor/rand_chacha/src/chacha.rs | 509 + vendor/rand_chacha/src/guts.rs | 252 + vendor/rand_chacha/src/lib.rs | 33 + vendor/rand_core/.cargo-checksum.json | 1 + vendor/rand_core/CHANGELOG.md | 84 + vendor/rand_core/COPYRIGHT | 12 + vendor/rand_core/Cargo.toml | 44 + vendor/rand_core/LICENSE-APACHE | 201 + vendor/rand_core/LICENSE-MIT | 26 + vendor/rand_core/README.md | 81 + vendor/rand_core/src/block.rs | 431 + vendor/rand_core/src/error.rs | 228 + vendor/rand_core/src/impls.rs | 184 + vendor/rand_core/src/le.rs | 56 + vendor/rand_core/src/lib.rs | 497 + vendor/rand_core/src/os.rs | 85 + vendor/rand_hc/.cargo-checksum.json | 1 + vendor/rand_hc/CHANGELOG.md | 22 + vendor/rand_hc/COPYRIGHT | 12 + .../Cargo.toml | 19 +- vendor/rand_hc/LICENSE-APACHE | 201 + vendor/rand_hc/LICENSE-MIT | 25 + vendor/rand_hc/README.md | 44 + vendor/rand_hc/src/hc128.rs | 513 + vendor/rand_hc/src/lib.rs | 23 + vendor/redox_syscall/.cargo-checksum.json | 2 +- vendor/redox_syscall/Cargo.toml | 2 +- vendor/redox_syscall/src/arch/aarch64.rs | 159 +- vendor/redox_syscall/src/tests.rs | 7 +- vendor/redox_users-0.3.4/.cargo-checksum.json | 1 - vendor/redox_users-0.3.4/Cargo.toml | 30 - vendor/redox_users-0.3.4/LICENSE | 22 - vendor/redox_users-0.3.4/README.md | 23 - vendor/redox_users-0.3.4/src/lib.rs | 1349 - vendor/redox_users-0.3.4/tests/etc/group | 4 - vendor/redox_users-0.3.4/tests/etc/passwd | 3 - vendor/redox_users-0.3.4/tests/etc/shadow | 3 - vendor/regex-syntax/.cargo-checksum.json | 2 +- vendor/regex-syntax/Cargo.toml | 2 +- vendor/regex-syntax/src/lib.rs | 4 +- vendor/regex-syntax/src/unicode.rs | 2 +- vendor/regex-syntax/src/utf8.rs | 12 +- vendor/regex/.cargo-checksum.json | 2 +- vendor/regex/CHANGELOG.md | 41 + vendor/regex/Cargo.lock | 194 +- vendor/regex/Cargo.toml | 14 +- vendor/regex/README.md | 6 +- vendor/regex/UNICODE.md | 34 +- vendor/regex/src/backtrack.rs | 4 +- vendor/regex/src/cache.rs | 100 - vendor/regex/src/compile.rs | 17 +- vendor/regex/src/dfa.rs | 20 +- vendor/regex/src/exec.rs | 41 +- vendor/regex/src/expand.rs | 3 +- vendor/regex/src/lib.rs | 18 +- vendor/regex/src/pool.rs | 333 + vendor/regex/src/prog.rs | 19 +- vendor/regex/src/re_bytes.rs | 59 +- vendor/regex/src/re_set.rs | 2 +- vendor/regex/src/re_unicode.rs | 59 +- vendor/regex/src/sparse.rs | 2 +- vendor/regex/tests/consistent.rs | 5 +- vendor/regex/tests/crazy.rs | 5 +- vendor/regex/tests/macros_bytes.rs | 1 - vendor/regex/tests/macros_str.rs | 1 + vendor/regex/tests/regression_fuzz.rs | 12 + vendor/regex/tests/replace.rs | 98 + vendor/regex/tests/test_default.rs | 42 +- vendor/rust-argon2/.cargo-checksum.json | 1 - vendor/rust-argon2/CHANGELOG.md | 64 - vendor/rust-argon2/Cargo.toml | 40 - vendor/rust-argon2/LICENSE-MIT | 22 - vendor/rust-argon2/README.md | 85 - vendor/rust-argon2/src/argon2.rs | 720 - vendor/rust-argon2/src/block.rs | 142 - vendor/rust-argon2/src/common.rs | 92 - vendor/rust-argon2/src/config.rs | 106 - vendor/rust-argon2/src/context.rs | 214 - vendor/rust-argon2/src/core.rs | 461 - vendor/rust-argon2/src/decoded.rs | 35 - vendor/rust-argon2/src/encoding.rs | 400 - vendor/rust-argon2/src/error.rs | 118 - vendor/rust-argon2/src/lib.rs | 99 - vendor/rust-argon2/src/memory.rs | 120 - vendor/rust-argon2/src/result.rs | 13 - vendor/rust-argon2/src/thread_mode.rs | 56 - vendor/rust-argon2/src/variant.rs | 159 - vendor/rust-argon2/src/version.rs | 97 - vendor/rust-argon2/tests/integration_test.rs | 1073 - .../rustc-ap-rustc_arena/.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_arena/Cargo.toml | 23 - vendor/rustc-ap-rustc_arena/src/lib.rs | 745 - vendor/rustc-ap-rustc_arena/src/tests.rs | 214 - .../rustc-ap-rustc_ast/.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_ast/Cargo.toml | 56 - vendor/rustc-ap-rustc_ast/README.md | 9 - vendor/rustc-ap-rustc_ast/src/ast.rs | 2977 -- vendor/rustc-ap-rustc_ast/src/ast/tests.rs | 11 - vendor/rustc-ap-rustc_ast/src/attr/mod.rs | 717 - .../src/crate_disambiguator.rs | 35 - vendor/rustc-ap-rustc_ast/src/entry.rs | 7 - .../src/expand/allocator.rs | 53 - vendor/rustc-ap-rustc_ast/src/expand/mod.rs | 3 - vendor/rustc-ap-rustc_ast/src/lib.rs | 69 - vendor/rustc-ap-rustc_ast/src/mut_visit.rs | 1366 - vendor/rustc-ap-rustc_ast/src/node_id.rs | 34 - vendor/rustc-ap-rustc_ast/src/ptr.rs | 219 - vendor/rustc-ap-rustc_ast/src/token.rs | 908 - vendor/rustc-ap-rustc_ast/src/tokenstream.rs | 517 - .../rustc-ap-rustc_ast/src/util/classify.rs | 25 - .../rustc-ap-rustc_ast/src/util/comments.rs | 222 - .../src/util/comments/tests.rs | 43 - vendor/rustc-ap-rustc_ast/src/util/literal.rs | 315 - vendor/rustc-ap-rustc_ast/src/util/parser.rs | 404 - vendor/rustc-ap-rustc_ast/src/visit.rs | 915 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_ast_passes/Cargo.toml | 61 - .../src/ast_validation.rs | 1472 - .../src/feature_gate.rs | 748 - vendor/rustc-ap-rustc_ast_passes/src/lib.rs | 16 - .../src/node_count.rs | 140 - .../src/show_span.rs | 66 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_ast_pretty/Cargo.toml | 33 - .../rustc-ap-rustc_ast_pretty/src/helpers.rs | 38 - vendor/rustc-ap-rustc_ast_pretty/src/lib.rs | 9 - vendor/rustc-ap-rustc_ast_pretty/src/pp.rs | 629 - .../src/pprust/mod.rs | 99 - .../src/pprust/state.rs | 2893 -- .../src/pprust/tests.rs | 63 - .../rustc-ap-rustc_attr/.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_attr/Cargo.toml | 62 - vendor/rustc-ap-rustc_attr/src/builtin.rs | 1077 - vendor/rustc-ap-rustc_attr/src/lib.rs | 21 - .../.cargo-checksum.json | 1 - .../rustc-ap-rustc_data_structures/Cargo.toml | 102 - .../src/atomic_ref.rs | 26 - .../src/base_n.rs | 42 - .../src/base_n/tests.rs | 22 - .../src/binary_search_util/mod.rs | 69 - .../src/binary_search_util/tests.rs | 23 - .../src/box_region.rs | 169 - .../src/captures.rs | 10 - .../src/const_cstr.rs | 30 - .../src/fingerprint.rs | 219 - .../src/flock.rs | 214 - .../src/frozen.rs | 63 - .../src/functor.rs | 82 - .../rustc-ap-rustc_data_structures/src/fx.rs | 14 - .../src/graph/dominators/mod.rs | 137 - .../src/graph/dominators/tests.rs | 34 - .../src/graph/implementation/mod.rs | 366 - .../src/graph/implementation/tests.rs | 131 - .../src/graph/iterate/mod.rs | 303 - .../src/graph/iterate/tests.rs | 22 - .../src/graph/mod.rs | 86 - .../src/graph/reference.rs | 39 - .../src/graph/scc/mod.rs | 574 - .../src/graph/scc/tests.rs | 213 - .../src/graph/tests.rs | 73 - .../src/graph/vec_graph/mod.rs | 107 - .../src/graph/vec_graph/tests.rs | 42 - .../src/jobserver.rs | 40 - .../rustc-ap-rustc_data_structures/src/lib.rs | 136 - .../src/macros.rs | 45 - .../src/map_in_place.rs | 108 - .../src/obligation_forest/graphviz.rs | 90 - .../src/obligation_forest/mod.rs | 723 - .../src/obligation_forest/tests.rs | 484 - .../src/owning_ref/mod.rs | 1233 - .../src/owning_ref/tests.rs | 707 - .../src/profiling.rs | 654 - .../src/ptr_key.rs | 37 - .../src/sharded.rs | 168 - .../src/sip128.rs | 490 - .../src/sip128/tests.rs | 497 - .../src/small_c_str.rs | 68 - .../src/small_c_str/tests.rs | 45 - .../src/snapshot_map/mod.rs | 141 - .../src/snapshot_map/tests.rs | 43 - .../src/sorted_map.rs | 285 - .../src/sorted_map/index_map.rs | 217 - .../src/sorted_map/tests.rs | 222 - .../src/sso/either_iter.rs | 75 - .../src/sso/map.rs | 560 - .../src/sso/mod.rs | 6 - .../src/sso/set.rs | 237 - .../src/stable_hasher.rs | 583 - .../src/stable_hasher/tests.rs | 73 - .../src/stable_map.rs | 100 - .../src/stable_set.rs | 77 - .../src/stack.rs | 17 - .../src/steal.rs | 54 - .../rustc-ap-rustc_data_structures/src/svh.rs | 69 - .../src/sync.rs | 658 - .../src/tagged_ptr.rs | 157 - .../src/tagged_ptr/copy.rs | 183 - .../src/tagged_ptr/drop.rs | 142 - .../src/temp_dir.rs | 34 - .../src/thin_vec.rs | 82 - .../src/tiny_list.rs | 91 - .../src/tiny_list/tests.rs | 144 - .../src/transitive_relation.rs | 402 - .../src/transitive_relation/tests.rs | 354 - .../src/unhash.rs | 29 - .../src/vec_linked_list.rs | 70 - .../src/work_queue.rs | 50 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_errors/Cargo.toml | 63 - .../src/annotate_snippet_emitter_writer.rs | 182 - .../rustc-ap-rustc_errors/src/diagnostic.rs | 593 - .../src/diagnostic_builder.rs | 479 - vendor/rustc-ap-rustc_errors/src/emitter.rs | 2207 -- vendor/rustc-ap-rustc_errors/src/json.rs | 480 - .../rustc-ap-rustc_errors/src/json/tests.rs | 204 - vendor/rustc-ap-rustc_errors/src/lib.rs | 1107 - vendor/rustc-ap-rustc_errors/src/lock.rs | 93 - vendor/rustc-ap-rustc_errors/src/registry.rs | 29 - vendor/rustc-ap-rustc_errors/src/snippet.rs | 190 - .../src/styled_buffer.rs | 130 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_expand/Cargo.toml | 86 - vendor/rustc-ap-rustc_expand/src/base.rs | 1204 - vendor/rustc-ap-rustc_expand/src/build.rs | 572 - vendor/rustc-ap-rustc_expand/src/config.rs | 615 - vendor/rustc-ap-rustc_expand/src/expand.rs | 1745 - vendor/rustc-ap-rustc_expand/src/lib.rs | 48 - vendor/rustc-ap-rustc_expand/src/mbe.rs | 149 - .../src/mbe/macro_check.rs | 630 - .../src/mbe/macro_parser.rs | 761 - .../src/mbe/macro_rules.rs | 1185 - .../rustc-ap-rustc_expand/src/mbe/quoted.rs | 309 - .../src/mbe/transcribe.rs | 396 - vendor/rustc-ap-rustc_expand/src/module.rs | 315 - .../src/mut_visit/tests.rs | 73 - .../rustc-ap-rustc_expand/src/parse/tests.rs | 349 - .../rustc-ap-rustc_expand/src/placeholders.rs | 382 - .../rustc-ap-rustc_expand/src/proc_macro.rs | 232 - .../src/proc_macro_server.rs | 713 - vendor/rustc-ap-rustc_expand/src/tests.rs | 1012 - .../src/tokenstream/tests.rs | 109 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_feature/Cargo.toml | 30 - vendor/rustc-ap-rustc_feature/src/accepted.rs | 282 - vendor/rustc-ap-rustc_feature/src/active.rs | 669 - .../src/builtin_attrs.rs | 613 - vendor/rustc-ap-rustc_feature/src/lib.rs | 154 - vendor/rustc-ap-rustc_feature/src/removed.rs | 135 - vendor/rustc-ap-rustc_feature/src/tests.rs | 23 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_fs_util/Cargo.toml | 20 - vendor/rustc-ap-rustc_fs_util/src/lib.rs | 90 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_graphviz/src/lib.rs | 714 - vendor/rustc-ap-rustc_graphviz/src/tests.rs | 408 - .../rustc-ap-rustc_index/.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_index/Cargo.toml | 34 - vendor/rustc-ap-rustc_index/src/bit_set.rs | 1195 - .../rustc-ap-rustc_index/src/bit_set/tests.rs | 400 - vendor/rustc-ap-rustc_index/src/lib.rs | 10 - vendor/rustc-ap-rustc_index/src/vec.rs | 846 - vendor/rustc-ap-rustc_index/src/vec/tests.rs | 51 - .../.cargo-checksum.json | 1 - .../rustc-ap-rustc_lexer-705.0.0/Cargo.toml | 27 - .../src/cursor.rs | 84 - .../rustc-ap-rustc_lexer-705.0.0/src/lib.rs | 816 - .../rustc-ap-rustc_lexer-705.0.0/src/tests.rs | 287 - .../src/unescape.rs | 344 - .../src/unescape/tests.rs | 273 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_lint_defs/Cargo.toml | 47 - .../rustc-ap-rustc_lint_defs/src/builtin.rs | 3111 -- vendor/rustc-ap-rustc_lint_defs/src/lib.rs | 501 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_macros/Cargo.toml | 35 - .../rustc-ap-rustc_macros/src/hash_stable.rs | 131 - vendor/rustc-ap-rustc_macros/src/lib.rs | 51 - vendor/rustc-ap-rustc_macros/src/lift.rs | 52 - vendor/rustc-ap-rustc_macros/src/query.rs | 528 - vendor/rustc-ap-rustc_macros/src/serialize.rs | 290 - .../src/session_diagnostic.rs | 666 - vendor/rustc-ap-rustc_macros/src/symbols.rs | 237 - .../src/symbols/tests.rs | 102 - .../src/type_foldable.rs | 44 - .../rustc-ap-rustc_parse/.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_parse/Cargo.toml | 67 - vendor/rustc-ap-rustc_parse/src/lexer/mod.rs | 584 - .../src/lexer/tokentrees.rs | 300 - .../src/lexer/unescape_error_reporting.rs | 268 - .../src/lexer/unicode_chars.rs | 392 - vendor/rustc-ap-rustc_parse/src/lib.rs | 327 - .../rustc-ap-rustc_parse/src/parser/attr.rs | 318 - .../src/parser/diagnostics.rs | 1944 - .../rustc-ap-rustc_parse/src/parser/expr.rs | 2408 -- .../src/parser/generics.rs | 304 - .../rustc-ap-rustc_parse/src/parser/item.rs | 1924 - vendor/rustc-ap-rustc_parse/src/parser/mod.rs | 1424 - .../src/parser/nonterminal.rs | 171 - vendor/rustc-ap-rustc_parse/src/parser/pat.rs | 1036 - .../rustc-ap-rustc_parse/src/parser/path.rs | 585 - .../rustc-ap-rustc_parse/src/parser/stmt.rs | 509 - vendor/rustc-ap-rustc_parse/src/parser/ty.rs | 756 - .../rustc-ap-rustc_parse/src/validate_attr.rs | 164 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_serialize/Cargo.toml | 28 - .../src/collection_impls.rs | 315 - vendor/rustc-ap-rustc_serialize/src/json.rs | 2778 -- .../src/json/tests.rs | 147 - vendor/rustc-ap-rustc_serialize/src/leb128.rs | 156 - vendor/rustc-ap-rustc_serialize/src/lib.rs | 34 - vendor/rustc-ap-rustc_serialize/src/opaque.rs | 720 - .../rustc-ap-rustc_serialize/src/serialize.rs | 765 - vendor/rustc-ap-rustc_serialize/tests/json.rs | 1269 - .../rustc-ap-rustc_serialize/tests/leb128.rs | 94 - .../rustc-ap-rustc_serialize/tests/opaque.rs | 276 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_session/Cargo.toml | 71 - .../src/cgu_reuse_tracker.rs | 120 - .../rustc-ap-rustc_session/src/code_stats.rs | 193 - vendor/rustc-ap-rustc_session/src/config.rs | 2316 -- .../rustc-ap-rustc_session/src/filesearch.rs | 207 - vendor/rustc-ap-rustc_session/src/lib.rs | 29 - vendor/rustc-ap-rustc_session/src/options.rs | 1185 - vendor/rustc-ap-rustc_session/src/output.rs | 205 - vendor/rustc-ap-rustc_session/src/parse.rs | 242 - .../src/search_paths.rs | 95 - vendor/rustc-ap-rustc_session/src/session.rs | 1639 - vendor/rustc-ap-rustc_session/src/utils.rs | 55 - .../rustc-ap-rustc_span/.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_span/Cargo.toml | 63 - .../src/analyze_source_file.rs | 274 - .../src/analyze_source_file/tests.rs | 142 - .../src/caching_source_map_view.rs | 293 - vendor/rustc-ap-rustc_span/src/def_id.rs | 281 - vendor/rustc-ap-rustc_span/src/edition.rs | 84 - vendor/rustc-ap-rustc_span/src/fatal_error.rs | 26 - vendor/rustc-ap-rustc_span/src/hygiene.rs | 1425 - .../rustc-ap-rustc_span/src/lev_distance.rs | 110 - .../src/lev_distance/tests.rs | 56 - vendor/rustc-ap-rustc_span/src/lib.rs | 2008 - vendor/rustc-ap-rustc_span/src/source_map.rs | 1079 - .../src/source_map/tests.rs | 272 - .../rustc-ap-rustc_span/src/span_encoding.rs | 131 - vendor/rustc-ap-rustc_span/src/symbol.rs | 1783 - .../rustc-ap-rustc_span/src/symbol/tests.rs | 25 - vendor/rustc-ap-rustc_span/src/tests.rs | 40 - .../.cargo-checksum.json | 1 - vendor/rustc-ap-rustc_target/Cargo.toml | 45 - vendor/rustc-ap-rustc_target/README.md | 6 - .../src/abi/call/aarch64.rs | 86 - .../src/abi/call/amdgpu.rs | 35 - .../rustc-ap-rustc_target/src/abi/call/arm.rs | 97 - .../rustc-ap-rustc_target/src/abi/call/avr.rs | 59 - .../src/abi/call/hexagon.rs | 30 - .../src/abi/call/mips.rs | 54 - .../src/abi/call/mips64.rs | 160 - .../rustc-ap-rustc_target/src/abi/call/mod.rs | 650 - .../src/abi/call/msp430.rs | 39 - .../src/abi/call/nvptx.rs | 33 - .../src/abi/call/nvptx64.rs | 33 - .../src/abi/call/powerpc.rs | 30 - .../src/abi/call/powerpc64.rs | 141 - .../src/abi/call/riscv.rs | 354 - .../src/abi/call/s390x.rs | 79 - .../src/abi/call/sparc.rs | 54 - .../src/abi/call/sparc64.rs | 92 - .../src/abi/call/wasm32.rs | 58 - .../src/abi/call/wasm32_bindgen_compat.rs | 29 - .../rustc-ap-rustc_target/src/abi/call/x86.rs | 135 - .../src/abi/call/x86_64.rs | 248 - .../src/abi/call/x86_win64.rs | 40 - vendor/rustc-ap-rustc_target/src/abi/mod.rs | 1245 - .../rustc-ap-rustc_target/src/asm/aarch64.rs | 156 - vendor/rustc-ap-rustc_target/src/asm/arm.rs | 298 - .../rustc-ap-rustc_target/src/asm/hexagon.rs | 93 - vendor/rustc-ap-rustc_target/src/asm/mips.rs | 133 - vendor/rustc-ap-rustc_target/src/asm/mod.rs | 610 - vendor/rustc-ap-rustc_target/src/asm/nvptx.rs | 49 - vendor/rustc-ap-rustc_target/src/asm/riscv.rs | 147 - vendor/rustc-ap-rustc_target/src/asm/spirv.rs | 46 - vendor/rustc-ap-rustc_target/src/asm/wasm.rs | 46 - vendor/rustc-ap-rustc_target/src/asm/x86.rs | 427 - vendor/rustc-ap-rustc_target/src/lib.rs | 33 - .../src/spec/aarch64_apple_darwin.rs | 24 - .../src/spec/aarch64_apple_ios.rs | 31 - .../src/spec/aarch64_apple_ios_macabi.rs | 31 - .../src/spec/aarch64_apple_tvos.rs | 20 - .../src/spec/aarch64_be_unknown_linux_gnu.rs | 20 - .../aarch64_be_unknown_linux_gnu_ilp32.rs | 20 - .../src/spec/aarch64_fuchsia.rs | 14 - .../src/spec/aarch64_linux_android.rs | 19 - .../src/spec/aarch64_pc_windows_msvc.rs | 16 - .../src/spec/aarch64_unknown_freebsd.rs | 14 - .../src/spec/aarch64_unknown_hermit.rs | 14 - .../src/spec/aarch64_unknown_linux_gnu.rs | 18 - .../spec/aarch64_unknown_linux_gnu_ilp32.rs | 18 - .../src/spec/aarch64_unknown_linux_musl.rs | 18 - .../src/spec/aarch64_unknown_netbsd.rs | 15 - .../src/spec/aarch64_unknown_none.rs | 32 - .../spec/aarch64_unknown_none_softfloat.rs | 32 - .../src/spec/aarch64_unknown_openbsd.rs | 15 - .../src/spec/aarch64_unknown_redox.rs | 14 - .../src/spec/aarch64_uwp_windows_msvc.rs | 15 - .../src/spec/aarch64_wrs_vxworks.rs | 14 - vendor/rustc-ap-rustc_target/src/spec/abi.rs | 127 - .../src/spec/abi/tests.rs | 27 - .../src/spec/android_base.rs | 18 - .../src/spec/apple_base.rs | 86 - .../src/spec/apple_sdk_base.rs | 46 - .../src/spec/arm_base.rs | 6 - .../src/spec/arm_linux_androideabi.rs | 16 - .../src/spec/arm_unknown_linux_gnueabi.rs | 19 - .../src/spec/arm_unknown_linux_gnueabihf.rs | 19 - .../src/spec/arm_unknown_linux_musleabi.rs | 24 - .../src/spec/arm_unknown_linux_musleabihf.rs | 24 - .../src/spec/armebv7r_none_eabi.rs | 27 - .../src/spec/armebv7r_none_eabihf.rs | 28 - .../src/spec/armv4t_unknown_linux_gnueabi.rs | 21 - .../src/spec/armv5te_unknown_linux_gnueabi.rs | 21 - .../spec/armv5te_unknown_linux_musleabi.rs | 24 - .../spec/armv5te_unknown_linux_uclibceabi.rs | 20 - .../src/spec/armv6_unknown_freebsd.rs | 20 - .../src/spec/armv6_unknown_netbsd_eabihf.rs | 20 - .../src/spec/armv7_apple_ios.rs | 18 - .../src/spec/armv7_linux_androideabi.rs | 24 - .../src/spec/armv7_unknown_freebsd.rs | 20 - .../src/spec/armv7_unknown_linux_gnueabi.rs | 23 - .../src/spec/armv7_unknown_linux_gnueabihf.rs | 24 - .../src/spec/armv7_unknown_linux_musleabi.rs | 28 - .../spec/armv7_unknown_linux_musleabihf.rs | 27 - .../src/spec/armv7_unknown_netbsd_eabihf.rs | 21 - .../src/spec/armv7_wrs_vxworks_eabihf.rs | 19 - .../src/spec/armv7a_none_eabi.rs | 40 - .../src/spec/armv7a_none_eabihf.rs | 31 - .../src/spec/armv7r_none_eabi.rs | 25 - .../src/spec/armv7r_none_eabihf.rs | 26 - .../src/spec/armv7s_apple_ios.rs | 18 - .../src/spec/asmjs_unknown_emscripten.rs | 11 - .../src/spec/avr_gnu_base.rs | 48 - .../src/spec/avr_unknown_gnu_atmega328.rs | 5 - .../src/spec/crt_objects.rs | 147 - .../src/spec/dragonfly_base.rs | 31 - .../src/spec/freebsd_base.rs | 33 - .../src/spec/fuchsia_base.rs | 44 - .../src/spec/haiku_base.rs | 14 - .../src/spec/hermit_base.rs | 27 - .../src/spec/hermit_kernel_base.rs | 28 - .../src/spec/hexagon_unknown_linux_musl.rs | 33 - .../src/spec/i386_apple_ios.rs | 19 - .../src/spec/i386_unknown_linux_gnu.rs | 8 - .../src/spec/i486_unknown_linux_gnu.rs | 8 - .../src/spec/i586_pc_windows_msvc.rs | 8 - .../src/spec/i586_unknown_linux_gnu.rs | 8 - .../src/spec/i586_unknown_linux_musl.rs | 8 - .../src/spec/i686_apple_darwin.rs | 27 - .../src/spec/i686_linux_android.rs | 25 - .../src/spec/i686_pc_windows_gnu.rs | 28 - .../src/spec/i686_pc_windows_msvc.rs | 32 - .../src/spec/i686_unknown_freebsd.rs | 21 - .../src/spec/i686_unknown_haiku.rs | 19 - .../src/spec/i686_unknown_linux_gnu.rs | 19 - .../src/spec/i686_unknown_linux_musl.rs | 34 - .../src/spec/i686_unknown_netbsd.rs | 19 - .../src/spec/i686_unknown_openbsd.rs | 20 - .../src/spec/i686_unknown_uefi.rs | 89 - .../src/spec/i686_uwp_windows_gnu.rs | 27 - .../src/spec/i686_uwp_windows_msvc.rs | 18 - .../src/spec/i686_wrs_vxworks.rs | 19 - .../src/spec/illumos_base.rs | 50 - .../src/spec/l4re_base.rs | 31 - .../src/spec/linux_base.rs | 35 - .../src/spec/linux_gnu_base.rs | 5 - .../src/spec/linux_kernel_base.rs | 27 - .../src/spec/linux_musl_base.rs | 16 - .../src/spec/linux_uclibc_base.rs | 5 - .../src/spec/mips64_unknown_linux_gnuabi64.rs | 21 - .../spec/mips64_unknown_linux_muslabi64.rs | 17 - .../spec/mips64el_unknown_linux_gnuabi64.rs | 19 - .../spec/mips64el_unknown_linux_muslabi64.rs | 16 - .../src/spec/mips_unknown_linux_gnu.rs | 20 - .../src/spec/mips_unknown_linux_musl.rs | 17 - .../src/spec/mips_unknown_linux_uclibc.rs | 20 - .../src/spec/mipsel_sony_psp.rs | 37 - .../src/spec/mipsel_sony_psp_linker_script.ld | 34 - .../src/spec/mipsel_unknown_linux_gnu.rs | 19 - .../src/spec/mipsel_unknown_linux_musl.rs | 16 - .../src/spec/mipsel_unknown_linux_uclibc.rs | 19 - .../src/spec/mipsel_unknown_none.rs | 37 - .../src/spec/mipsisa32r6_unknown_linux_gnu.rs | 20 - .../spec/mipsisa32r6el_unknown_linux_gnu.rs | 19 - .../mipsisa64r6_unknown_linux_gnuabi64.rs | 21 - .../mipsisa64r6el_unknown_linux_gnuabi64.rs | 19 - vendor/rustc-ap-rustc_target/src/spec/mod.rs | 2042 -- .../src/spec/msp430_none_elf.rs | 59 - .../src/spec/msvc_base.rs | 36 - .../src/spec/netbsd_base.rs | 31 - .../src/spec/nvptx64_nvidia_cuda.rs | 67 - .../src/spec/openbsd_base.rs | 33 - .../src/spec/powerpc64_unknown_freebsd.rs | 17 - .../src/spec/powerpc64_unknown_linux_gnu.rs | 21 - .../src/spec/powerpc64_unknown_linux_musl.rs | 17 - .../src/spec/powerpc64_wrs_vxworks.rs | 17 - .../src/spec/powerpc64le_unknown_linux_gnu.rs | 16 - .../spec/powerpc64le_unknown_linux_musl.rs | 16 - .../src/spec/powerpc_unknown_linux_gnu.rs | 16 - .../src/spec/powerpc_unknown_linux_gnuspe.rs | 16 - .../src/spec/powerpc_unknown_linux_musl.rs | 16 - .../src/spec/powerpc_unknown_netbsd.rs | 16 - .../src/spec/powerpc_wrs_vxworks.rs | 17 - .../src/spec/powerpc_wrs_vxworks_spe.rs | 22 - .../src/spec/redox_base.rs | 37 - .../src/spec/riscv32gc_unknown_linux_gnu.rs | 19 - .../src/spec/riscv32i_unknown_none_elf.rs | 27 - .../src/spec/riscv32imac_unknown_none_elf.rs | 27 - .../src/spec/riscv32imc_unknown_none_elf.rs | 27 - .../src/spec/riscv64gc_unknown_linux_gnu.rs | 19 - .../src/spec/riscv64gc_unknown_none_elf.rs | 28 - .../src/spec/riscv64imac_unknown_none_elf.rs | 28 - .../src/spec/riscv_base.rs | 20 - .../src/spec/s390x_unknown_linux_gnu.rs | 23 - .../src/spec/solaris_base.rs | 17 - .../src/spec/sparc64_unknown_linux_gnu.rs | 17 - .../src/spec/sparc64_unknown_netbsd.rs | 17 - .../src/spec/sparc64_unknown_openbsd.rs | 18 - .../src/spec/sparc_unknown_linux_gnu.rs | 18 - .../src/spec/sparcv9_sun_solaris.rs | 23 - .../src/spec/tests/tests_impl.rs | 55 - .../src/spec/thumb_base.rs | 58 - .../src/spec/thumbv4t_none_eabi.rs | 58 - .../src/spec/thumbv6m_none_eabi.rs | 22 - .../src/spec/thumbv7a_pc_windows_msvc.rs | 38 - .../src/spec/thumbv7a_uwp_windows_msvc.rs | 24 - .../src/spec/thumbv7em_none_eabi.rs | 23 - .../src/spec/thumbv7em_none_eabihf.rs | 35 - .../src/spec/thumbv7m_none_eabi.rs | 14 - .../src/spec/thumbv7neon_linux_androideabi.rs | 24 - .../thumbv7neon_unknown_linux_gnueabihf.rs | 26 - .../thumbv7neon_unknown_linux_musleabihf.rs | 31 - .../src/spec/thumbv8m_base_none_eabi.rs | 20 - .../src/spec/thumbv8m_main_none_eabi.rs | 15 - .../src/spec/thumbv8m_main_none_eabihf.rs | 24 - .../src/spec/uefi_msvc_base.rs | 53 - .../src/spec/vxworks_base.rs | 40 - .../src/spec/wasm32_base.rs | 136 - .../src/spec/wasm32_unknown_emscripten.rs | 51 - .../src/spec/wasm32_unknown_unknown.rs | 49 - .../src/spec/wasm32_wasi.rs | 116 - .../src/spec/windows_gnu_base.rs | 97 - .../src/spec/windows_msvc_base.rs | 33 - .../src/spec/windows_uwp_gnu_base.rs | 37 - .../src/spec/windows_uwp_msvc_base.rs | 15 - .../src/spec/x86_64_apple_darwin.rs | 29 - .../src/spec/x86_64_apple_ios.rs | 18 - .../src/spec/x86_64_apple_ios_macabi.rs | 18 - .../src/spec/x86_64_apple_tvos.rs | 17 - .../src/spec/x86_64_fortanix_unknown_sgx.rs | 89 - .../src/spec/x86_64_fuchsia.rs | 17 - .../src/spec/x86_64_linux_android.rs | 20 - .../src/spec/x86_64_linux_kernel.rs | 26 - .../src/spec/x86_64_pc_windows_gnu.rs | 23 - .../src/spec/x86_64_pc_windows_msvc.rs | 17 - .../src/spec/x86_64_rumprun_netbsd.rs | 25 - .../src/spec/x86_64_sun_solaris.rs | 18 - .../src/spec/x86_64_unknown_dragonfly.rs | 18 - .../src/spec/x86_64_unknown_freebsd.rs | 18 - .../src/spec/x86_64_unknown_haiku.rs | 20 - .../src/spec/x86_64_unknown_hermit.rs | 18 - .../src/spec/x86_64_unknown_hermit_kernel.rs | 20 - .../src/spec/x86_64_unknown_illumos.rs | 19 - .../src/spec/x86_64_unknown_l4re_uclibc.rs | 16 - .../src/spec/x86_64_unknown_linux_gnu.rs | 18 - .../src/spec/x86_64_unknown_linux_gnux32.rs | 23 - .../src/spec/x86_64_unknown_linux_musl.rs | 19 - .../src/spec/x86_64_unknown_netbsd.rs | 18 - .../src/spec/x86_64_unknown_openbsd.rs | 18 - .../src/spec/x86_64_unknown_redox.rs | 18 - .../src/spec/x86_64_unknown_uefi.rs | 40 - .../src/spec/x86_64_uwp_windows_gnu.rs | 22 - .../src/spec/x86_64_uwp_windows_msvc.rs | 17 - .../src/spec/x86_64_wrs_vxworks.rs | 19 - vendor/serde/.cargo-checksum.json | 2 +- vendor/serde/Cargo.toml | 4 +- vendor/serde/src/lib.rs | 3 +- vendor/serde/src/ser/impls.rs | 55 +- vendor/serde_derive/.cargo-checksum.json | 2 +- vendor/serde_derive/Cargo.toml | 2 +- vendor/serde_derive/src/lib.rs | 2 +- vendor/shell-escape/.cargo-checksum.json | 1 + vendor/{arrayref => shell-escape}/Cargo.toml | 17 +- .../LICENSE-APACHE | 0 vendor/shell-escape/LICENSE-MIT | 25 + vendor/shell-escape/README.md | 23 + vendor/shell-escape/src/lib.rs | 135 + vendor/socket2/.cargo-checksum.json | 1 - vendor/socket2/Cargo.toml | 40 - vendor/socket2/README.md | 20 - vendor/socket2/SO_ACCEPTCONN.patch | 96 - vendor/socket2/TODO | 20 - vendor/socket2/check_targets.bash | 15 - vendor/socket2/diff.patch | 134 - vendor/socket2/src/lib.rs | 230 - vendor/socket2/src/sockaddr.rs | 324 - vendor/socket2/src/socket.rs | 1128 - vendor/socket2/src/sys/unix.rs | 1317 - vendor/socket2/src/sys/windows.rs | 1022 - vendor/socket2/src/tests.rs | 62 - vendor/socket2/src/utils.rs | 48 - vendor/syn/.cargo-checksum.json | 2 +- vendor/syn/Cargo.toml | 4 +- vendor/syn/README.md | 6 +- vendor/syn/src/attr.rs | 22 +- vendor/syn/src/custom_keyword.rs | 1 + vendor/syn/src/custom_punctuation.rs | 1 + vendor/syn/src/data.rs | 51 +- vendor/syn/src/derive.rs | 20 +- vendor/syn/src/error.rs | 2 +- vendor/syn/src/expr.rs | 401 +- vendor/syn/src/generics.rs | 12 +- vendor/syn/src/item.rs | 100 +- vendor/syn/src/lib.rs | 8 +- vendor/syn/src/lit.rs | 2 +- vendor/syn/src/pat.rs | 6 +- vendor/syn/src/path.rs | 116 +- vendor/syn/tests/common/eq.rs | 49 +- vendor/syn/tests/repo/mod.rs | 2 +- vendor/syn/tests/test_expr.rs | 18 + vendor/syn/tests/test_pat.rs | 10 +- vendor/syn/tests/test_precedence.rs | 13 +- vendor/tempfile/.cargo-checksum.json | 2 +- vendor/tempfile/Cargo.toml | 8 +- vendor/tempfile/NEWS | 12 + vendor/tempfile/README.md | 2 +- vendor/tempfile/src/dir.rs | 6 +- vendor/tempfile/src/file/mod.rs | 30 +- vendor/tempfile/src/lib.rs | 5 +- vendor/tempfile/src/util.rs | 6 +- vendor/tinyvec/.cargo-checksum.json | 2 +- vendor/tinyvec/CHANGELOG.md | 6 + vendor/tinyvec/Cargo.toml | 2 +- vendor/tinyvec/LICENSE-APACHE.md | 267 +- vendor/tinyvec/src/arrayvec.rs | 145 +- vendor/tinyvec/src/slicevec.rs | 72 +- vendor/tinyvec/src/tinyvec.rs | 89 +- vendor/tinyvec/tests/arrayvec.rs | 29 + vendor/tinyvec/tests/tinyvec.rs | 9 + .../tracing-attributes/.cargo-checksum.json | 2 +- vendor/tracing-attributes/CHANGELOG.md | 21 + vendor/tracing-attributes/Cargo.toml | 6 +- vendor/tracing-attributes/README.md | 4 +- vendor/tracing-attributes/src/lib.rs | 417 +- vendor/tracing-attributes/tests/async_fn.rs | 76 +- .../tracing-subscriber/.cargo-checksum.json | 2 +- vendor/tracing-subscriber/CHANGELOG.md | 26 + vendor/tracing-subscriber/Cargo.toml | 2 +- vendor/tracing-subscriber/README.md | 2 +- .../tracing-subscriber/src/fmt/fmt_layer.rs | 76 +- .../tracing-subscriber/src/fmt/format/mod.rs | 153 +- .../src/fmt/format/pretty.rs | 111 +- vendor/tracing-subscriber/src/fmt/mod.rs | 31 +- vendor/tracing-subscriber/src/fmt/time/mod.rs | 4 +- vendor/tracing-subscriber/src/lib.rs | 2 +- vendor/unicode-bidi/.cargo-checksum.json | 2 +- vendor/unicode-bidi/Cargo.toml | 29 +- vendor/unicode-bidi/README.md | 2 +- vendor/unicode-bidi/src/char_data/mod.rs | 2 +- vendor/unicode-bidi/src/deprecated.rs | 3 - vendor/unicode-bidi/src/explicit.rs | 8 +- vendor/unicode-bidi/src/implicit.rs | 11 +- vendor/unicode-bidi/src/level.rs | 5 +- vendor/unicode-bidi/src/lib.rs | 86 +- vendor/unicode-bidi/src/prepare.rs | 11 +- vendor/version_check/.cargo-checksum.json | 2 +- vendor/version_check/Cargo.toml | 2 +- vendor/version_check/src/lib.rs | 146 +- vendor/walkdir/.cargo-checksum.json | 2 +- vendor/walkdir/Cargo.toml | 2 +- vendor/walkdir/README.md | 4 +- vendor/walkdir/src/error.rs | 2 +- vendor/walkdir/src/lib.rs | 42 +- vendor/walkdir/src/tests/recursive.rs | 45 +- vendor/yansi-term/.cargo-checksum.json | 1 + vendor/yansi-term/Cargo.lock | 166 + vendor/yansi-term/Cargo.toml | 47 + .../owning_ref/LICENSE => yansi-term/LICENCE} | 2 +- vendor/yansi-term/README.md | 119 + vendor/yansi-term/examples/256_colours.rs | 76 + vendor/yansi-term/examples/basic_colours.rs | 18 + vendor/yansi-term/examples/overwrite.rs | 18 + vendor/yansi-term/examples/rgb_colours.rs | 23 + vendor/yansi-term/src/ansi.rs | 290 + vendor/yansi-term/src/display.rs | 80 + vendor/yansi-term/src/lib.rs | 168 + vendor/yansi-term/src/style.rs | 541 + vendor/yansi-term/src/windows.rs | 61 + version | 2 +- 5143 files changed, 153447 insertions(+), 227854 deletions(-) delete mode 100644 compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml create mode 100644 compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml create mode 100644 compiler/rustc_codegen_cranelift/docs/usage.md create mode 100644 compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh create mode 100755 compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh create mode 100644 compiler/rustc_codegen_cranelift/src/compiler_builtins.rs create mode 100644 compiler/rustc_codegen_llvm/src/debuginfo/doc.md delete mode 100644 compiler/rustc_codegen_llvm/src/debuginfo/doc.rs create mode 100644 compiler/rustc_data_structures/src/memmap.rs create mode 100644 compiler/rustc_data_structures/src/thin_vec/tests.rs delete mode 100644 compiler/rustc_error_codes/src/error_codes/E0723.md delete mode 100644 compiler/rustc_metadata/src/link_args.rs create mode 100644 compiler/rustc_mir/src/transform/remove_zsts.rs rename compiler/rustc_target/src/abi/call/{wasm32.rs => wasm.rs} (66%) delete mode 100644 compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs create mode 100644 compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs rename compiler/rustc_target/src/spec/{wasm32_base.rs => wasm_base.rs} (99%) create mode 100644 compiler/rustc_ty_utils/src/representability.rs create mode 100644 library/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs create mode 100644 library/backtrace/src/symbolize/gimli/libs_haiku.rs create mode 100644 library/backtrace/src/symbolize/gimli/libs_illumos.rs create mode 100644 library/backtrace/src/symbolize/gimli/libs_libnx.rs create mode 100644 library/backtrace/src/symbolize/gimli/libs_macos.rs create mode 100644 library/backtrace/src/symbolize/gimli/libs_windows.rs create mode 100644 library/core/src/ops/try_trait.rs create mode 100644 library/core/tests/num/ieee754.rs create mode 100644 library/panic_abort/src/android.rs rename library/std/src/{sys_common => sync}/poison.rs (94%) rename library/std/src/{sys_common => sys/common}/alloc.rs (98%) create mode 100644 library/std/src/sys/common/mod.rs delete mode 100644 library/std/src/sys/hermit/cmath.rs delete mode 100644 library/std/src/sys/hermit/io.rs delete mode 100644 library/std/src/sys/hermit/path.rs delete mode 100644 library/std/src/sys/hermit/stack_overflow.rs delete mode 100644 library/std/src/sys/hermit/thread_local_key.rs delete mode 100644 library/std/src/sys/sgx/cmath.rs delete mode 100644 library/std/src/sys/sgx/stack_overflow.rs rename library/std/src/sys/{vxworks => unix}/process/process_vxworks.rs (88%) delete mode 100644 library/std/src/sys/unsupported/cmath.rs delete mode 100644 library/std/src/sys/unsupported/stack_overflow.rs delete mode 100644 library/std/src/sys/vxworks/env.rs delete mode 100644 library/std/src/sys/vxworks/mod.rs delete mode 100644 library/std/src/sys/vxworks/process/mod.rs delete mode 100644 library/std/src/sys/vxworks/rand.rs delete mode 100644 library/std/src/sys/vxworks/thread_local_dtor.rs create mode 100644 library/std/src/sys/windows/alloc/tests.rs delete mode 100644 library/std/src/sys_common/at_exit_imp.rs create mode 100644 library/std/src/sys_common/rt.rs create mode 100644 library/stdarch/crates/core_arch/avx512vbmi2.md create mode 100644 library/stdarch/crates/core_arch/src/x86/avx512bf16.rs create mode 100644 library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs create mode 100644 library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs create mode 100644 library/stdarch/crates/core_arch/src/x86/avx512vnni.rs create mode 100644 library/stdarch/crates/core_arch/src/x86_64/macros.rs delete mode 100644 library/stdarch/crates/std_detect/src/mod.rs create mode 100644 library/stdarch/examples/connect5.rs create mode 100644 src/bootstrap/defaults/config.tools.toml rename src/ci/docker/host-x86_64/{x86_64-gnu-llvm-9 => x86_64-gnu-llvm-10}/Dockerfile (91%) create mode 100644 src/doc/rustc-dev-guide/src/mir/mir_cfg.svg create mode 100644 src/doc/rustc/src/target-tier-policy.md create mode 100644 src/doc/unstable-book/src/language-features/doc-notable-trait.md delete mode 100644 src/doc/unstable-book/src/language-features/doc-spotlight.md delete mode 100644 src/doc/unstable-book/src/language-features/link-args.md delete mode 100644 src/doc/unstable-book/src/language-features/non-ascii-idents.md delete mode 100644 src/doc/unstable-book/src/language-features/or-patterns.md create mode 100644 src/librustdoc/html/static/SourceCodePro-It.ttf.woff create mode 100644 src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff delete mode 100644 src/librustdoc/html/static/SourceCodePro-Regular.woff create mode 100644 src/librustdoc/html/static/SourceCodePro-Semibold.ttf.woff delete mode 100644 src/librustdoc/html/static/SourceCodePro-Semibold.woff create mode 100644 src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff create mode 100644 src/librustdoc/html/static/SourceSerif4-It.ttf.woff rename src/librustdoc/html/static/{SourceSerifPro-LICENSE.md => SourceSerif4-LICENSE.md} (98%) create mode 100644 src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff delete mode 100644 src/librustdoc/html/static/SourceSerifPro-Bold.ttf.woff delete mode 100644 src/librustdoc/html/static/SourceSerifPro-It.ttf.woff delete mode 100644 src/librustdoc/html/static/SourceSerifPro-Regular.ttf.woff create mode 100644 src/librustdoc/html/static/search.js create mode 100644 src/librustdoc/html/static/sidebar-items.js create mode 100644 src/librustdoc/html/tests.rs create mode 100644 src/librustdoc/passes/bare_urls.rs create mode 100644 src/librustdoc/passes/collect_intra_doc_links/early.rs delete mode 100644 src/librustdoc/passes/non_autolinks.rs create mode 100644 src/test/assembly/panic-no-unwind-no-uwtable.rs create mode 100644 src/test/assembly/panic-unwind-no-uwtable.rs create mode 100644 src/test/assembly/static-relocation-model.rs create mode 100644 src/test/codegen/asm-target-clobbers.rs create mode 100644 src/test/codegen/binary-search-index-no-bound-check.rs create mode 100644 src/test/codegen/default-requires-uwtable.rs create mode 100644 src/test/codegen/force-no-unwind-tables.rs create mode 100644 src/test/codegen/issue-73338-effecient-cmp.rs create mode 100644 src/test/codegen/issue-83623-SIMD-PartialEq.rs create mode 100644 src/test/codegen/issue-84268.rs create mode 100644 src/test/codegen/noalias-unpin.rs create mode 100644 src/test/codegen/panic-unwind-default-uwtable.rs create mode 100644 src/test/codegen/vec-in-place.rs delete mode 100644 src/test/codegen/wasm_casts_nontrapping.rs create mode 100644 src/test/incremental/issue-80691-bad-eval-cache.rs create mode 100644 src/test/incremental/issue-84252-global-alloc.rs create mode 100644 src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs create mode 100644 src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs create mode 100644 src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs create mode 100644 src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs create mode 100644 src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir create mode 100644 src/test/mir-opt/remove_zsts_dont_touch_unions.rs create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.continue.txt create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-83601.txt create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.no_cov_crate.txt create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.unused.txt create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/Makefile delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/escape_url.py delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#1}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#2}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#3}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-d.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-f.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.k.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.l.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#10}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#11}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#1}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#2}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#3}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#4}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#5}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#6}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#7}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#8}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#9}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.{impl#0}-drop.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#0}-set_strength.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#1}-drop.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-InTrait-default_trait_func.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-in_func.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-{impl#0}-trait_func.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loop_break_value/loop_break_value.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#0}-new.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#1}-cmp.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#4}-assert_receiver_is_total_eq.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#8}-clone.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_generic_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_bin_crate_generic_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_this_lib_crate_generic_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_with_same_type_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#0}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#1}.-------.InstrumentCoverage.0.html delete mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage/async2.rs create mode 100644 src/test/run-make-fulldeps/coverage/continue.rs create mode 100644 src/test/run-make-fulldeps/coverage/issue-83601.rs create mode 100644 src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs create mode 100644 src/test/run-make-fulldeps/coverage/no_cov_crate.rs create mode 100644 src/test/run-make-fulldeps/coverage/unused.rs create mode 100644 src/test/run-make-fulldeps/coverage/uses_inline_crate.rs create mode 100644 src/test/run-make-fulldeps/issue-47551/Makefile create mode 100644 src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs create mode 100644 src/test/run-make-fulldeps/issue-83045/Makefile create mode 100644 src/test/run-make-fulldeps/issue-83045/a.rs create mode 100644 src/test/run-make-fulldeps/issue-83045/b.rs create mode 100644 src/test/run-make-fulldeps/issue-83045/c.rs create mode 100644 src/test/run-make/emit-shared-files/Makefile create mode 100644 src/test/run-make/emit-shared-files/x.rs create mode 100644 src/test/run-make/emit-shared-files/y.css create mode 100644 src/test/run-make/emit-shared-files/z.css create mode 100644 src/test/run-make/unstable-flag-required/Makefile create mode 100644 src/test/run-make/unstable-flag-required/README.md create mode 100644 src/test/run-make/unstable-flag-required/output-format-json.stderr create mode 100644 src/test/run-make/unstable-flag-required/x.rs create mode 100644 src/test/run-make/wasm-abi/Makefile create mode 100644 src/test/run-make/wasm-abi/foo.js create mode 100644 src/test/run-make/wasm-abi/foo.rs create mode 100644 src/test/rustdoc-gui/README.md create mode 100644 src/test/rustdoc-gui/check_info_sign_position.goml create mode 100644 src/test/rustdoc-gui/hash-item-expansion.goml create mode 100644 src/test/rustdoc-gui/impl-default-expansion.goml delete mode 100644 src/test/rustdoc-gui/nojs-attr-pos.goml create mode 100644 src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml create mode 100644 src/test/rustdoc-gui/trait-sidebar-item-order.goml create mode 100644 src/test/rustdoc-json/reexport/in_root_and_mod.rs create mode 100644 src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs create mode 100644 src/test/rustdoc-json/reexport/rename_private.rs create mode 100644 src/test/rustdoc-ui/auxiliary/panic-item.rs create mode 100644 src/test/rustdoc-ui/bare-urls.fixed rename src/test/rustdoc-ui/{url-improvements.rs => bare-urls.rs} (84%) rename src/test/rustdoc-ui/{url-improvements.stderr => bare-urls.stderr} (63%) create mode 100644 src/test/rustdoc-ui/doc-spotlight.fixed create mode 100644 src/test/rustdoc-ui/doc-spotlight.rs create mode 100644 src/test/rustdoc-ui/doc-spotlight.stderr create mode 100644 src/test/rustdoc-ui/intra-doc/email-address-localhost.rs create mode 100644 src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr create mode 100644 src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs create mode 100644 src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr create mode 100644 src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs create mode 100644 src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr create mode 100644 src/test/rustdoc-ui/invalid-theme-name.rs create mode 100644 src/test/rustdoc-ui/invalid-theme-name.stderr create mode 100644 src/test/rustdoc-ui/issue-83883-describe-lints.rs create mode 100644 src/test/rustdoc-ui/issue-83883-describe-lints.stdout create mode 100644 src/test/rustdoc-ui/output-format-html-stable.rs create mode 100644 src/test/rustdoc-ui/unused-extern-crate.rs create mode 100644 src/test/rustdoc/auxiliary/primitive-doc.rs create mode 100644 src/test/rustdoc/cross-crate-primitive-doc.rs rename src/test/rustdoc/{doc-spotlight.rs => doc-notable_trait.rs} (78%) create mode 100644 src/test/rustdoc/empty-impls.rs create mode 100644 src/test/rustdoc/intra-doc/auxiliary/empty.rs create mode 100644 src/test/rustdoc/intra-doc/auxiliary/empty2.rs rename src/test/rustdoc/{ => intra-doc}/auxiliary/issue-66159-1.rs (100%) create mode 100644 src/test/rustdoc/intra-doc/email-address.rs create mode 100644 src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs delete mode 100644 src/test/rustdoc/issue-66159.rs create mode 100644 src/test/rustdoc/item-hide-threshold.rs delete mode 100644 src/test/rustdoc/prim-title.rs create mode 100644 src/test/rustdoc/reexport-stability-tags-deprecated-and-portability.rs create mode 100644 src/test/rustdoc/reexport-stability-tags-unstable-and-portability.rs create mode 100644 src/test/rustdoc/struct-arg-pattern.rs create mode 100644 src/test/rustdoc/tab_title.rs create mode 100644 src/test/rustdoc/trait-impl-items-links-and-anchors.rs create mode 100644 src/test/ui/associated-type-bounds/hrtb.rs create mode 100644 src/test/ui/associated-type-bounds/issue-79949.rs create mode 100644 src/test/ui/associated-type-bounds/issue-81193.rs create mode 100644 src/test/ui/associated-type-bounds/issue-83017.rs create mode 100644 src/test/ui/associated-type-bounds/issue-83017.stderr rename src/test/ui/{issues => associated-types}/issue-23208.rs (100%) rename src/test/ui/{issues => associated-types}/issue-31597.rs (100%) create mode 100644 src/test/ui/async-await/large_moves.rs create mode 100644 src/test/ui/async-await/large_moves.stderr create mode 100644 src/test/ui/async-await/pin-needed-to-poll-2.rs create mode 100644 src/test/ui/async-await/pin-needed-to-poll-2.stderr create mode 100644 src/test/ui/async-await/pin-needed-to-poll.rs create mode 100644 src/test/ui/async-await/pin-needed-to-poll.stderr delete mode 100644 src/test/ui/attr-main-2.rs delete mode 100644 src/test/ui/attr-main.rs delete mode 100644 src/test/ui/attr.rs rename src/test/ui/{ => binding}/shadow.rs (100%) delete mode 100644 src/test/ui/cast/cast-ptr-to-int-const.stderr create mode 100644 src/test/ui/cast/cast-ptr-to-int-const.with_feature.stderr create mode 100644 src/test/ui/cast/cast-ptr-to-int-const.without_feature.stderr create mode 100644 src/test/ui/cast/issue-84213.fixed create mode 100644 src/test/ui/cast/issue-84213.rs create mode 100644 src/test/ui/cast/issue-84213.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed create mode 100644 src/test/ui/closures/issue-84128.rs create mode 100644 src/test/ui/closures/issue-84128.stderr create mode 100644 src/test/ui/compare-method/bad-self-type.rs create mode 100644 src/test/ui/compare-method/bad-self-type.stderr create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs create mode 100644 src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.rs create mode 100644 src/test/ui/const-generics/defaults/const-default.rs create mode 100644 src/test/ui/const-generics/defaults/const-param-as-default-value.rs create mode 100644 src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs create mode 100644 src/test/ui/const-generics/defaults/default-annotation.rs create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.full.stderr create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.min.stderr create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.rs create mode 100644 src/test/ui/const-generics/defaults/default-param-wf-concrete.rs create mode 100644 src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr create mode 100644 src/test/ui/const-generics/defaults/external.rs create mode 100644 src/test/ui/const-generics/defaults/mismatch.full.stderr create mode 100644 src/test/ui/const-generics/defaults/mismatch.min.stderr create mode 100644 src/test/ui/const-generics/defaults/mismatch.rs create mode 100644 src/test/ui/const-generics/defaults/pretty-printing-ast.rs create mode 100644 src/test/ui/const-generics/defaults/pretty-printing-ast.stdout create mode 100644 src/test/ui/const-generics/defaults/repr-c-issue-82792.rs delete mode 100644 src/test/ui/const-generics/defaults/simple-defaults.min.stderr create mode 100644 src/test/ui/const-generics/defaults/type-default-const-param-name.rs rename src/test/ui/const-generics/issues/{issue-56445.full.stderr => issue-56445-1.full.stderr} (92%) rename src/test/ui/const-generics/issues/{issue-56445.min.stderr => issue-56445-1.min.stderr} (91%) rename src/test/ui/const-generics/issues/{issue-56445.rs => issue-56445-1.rs} (100%) create mode 100644 src/test/ui/const-generics/issues/issue-56445-2.rs create mode 100644 src/test/ui/const-generics/issues/issue-56445-2.stderr create mode 100644 src/test/ui/const-generics/issues/issue-56445-3.rs create mode 100644 src/test/ui/const-generics/issues/issue-56445-3.stderr create mode 100644 src/test/ui/const-generics/issues/issue-69654-run-pass.stderr rename src/test/ui/const-generics/issues/{issue70273-assoc-fn.rs => issue-70273-assoc-fn.rs} (100%) create mode 100644 src/test/ui/const-generics/issues/issue-84408.rs create mode 100644 src/test/ui/const-generics/min_const_generics/const_default_first.rs create mode 100644 src/test/ui/const-generics/min_const_generics/const_default_first.stderr rename src/test/ui/const-generics/min_const_generics/{invalid-patterns.stderr => invalid-patterns.32bit.stderr} (75%) create mode 100644 src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr create mode 100644 src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs create mode 100644 src/test/ui/const-generics/occurs-check/unused-substs-1.stderr create mode 100644 src/test/ui/const-generics/occurs-check/unused-substs-2.stderr create mode 100644 src/test/ui/const-generics/occurs-check/unused-substs-3.stderr create mode 100644 src/test/ui/const-generics/occurs-check/unused-substs-4.stderr delete mode 100644 src/test/ui/const-ptr/out_of_bounds_read.rs delete mode 100644 src/test/ui/const-ptr/out_of_bounds_read.stderr rename src/test/ui/consts/{const-err4.stderr => const-err4.32bit.stderr} (76%) create mode 100644 src/test/ui/consts/const-err4.64bit.stderr rename src/test/ui/consts/const-eval/{const-pointer-values-in-various-types.stderr => const-pointer-values-in-various-types.64bit.stderr} (83%) rename src/test/ui/consts/const-eval/heap/{alloc_intrinsic_uninit.stderr => alloc_intrinsic_uninit.32bit.stderr} (76%) create mode 100644 src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr rename src/test/ui/consts/const-eval/{ref_to_int_match.stderr => ref_to_int_match.32bit.stderr} (74%) create mode 100644 src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr rename src/test/ui/consts/const-eval/{transmute-const.stderr => transmute-const.32bit.stderr} (76%) create mode 100644 src/test/ui/consts/const-eval/transmute-const.64bit.stderr rename src/test/ui/consts/const-eval/{ub-enum.stderr => ub-enum.32bit.stderr} (79%) create mode 100644 src/test/ui/consts/const-eval/ub-enum.64bit.stderr rename src/test/ui/consts/const-eval/{ub-int-array.stderr => ub-int-array.32bit.stderr} (76%) create mode 100644 src/test/ui/consts/const-eval/ub-int-array.64bit.stderr rename src/test/ui/consts/const-eval/{ub-nonnull.stderr => ub-nonnull.32bit.stderr} (78%) create mode 100644 src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr rename src/test/ui/consts/const-eval/{ub-ref-ptr.stderr => ub-ref-ptr.32bit.stderr} (73%) create mode 100644 src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr rename src/test/ui/consts/const-eval/{ub-uninhabit.stderr => ub-uninhabit.32bit.stderr} (81%) create mode 100644 src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr rename src/test/ui/consts/const-eval/{ub-upvars.stderr => ub-upvars.32bit.stderr} (77%) create mode 100644 src/test/ui/consts/const-eval/ub-upvars.64bit.stderr rename src/test/ui/consts/const-eval/{ub-wide-ptr.stderr => ub-wide-ptr.32bit.stderr} (73%) create mode 100644 src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr rename src/test/ui/consts/const-eval/{union-ub.stderr => union-ub.32bit.stderr} (75%) create mode 100644 src/test/ui/consts/const-eval/union-ub.64bit.stderr rename src/test/ui/consts/const-eval/{validate_uninhabited_zsts.stderr => validate_uninhabited_zsts.32bit.stderr} (97%) create mode 100644 src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr rename src/test/ui/consts/{const-points-to-static.stderr => const-points-to-static.32bit.stderr} (74%) create mode 100644 src/test/ui/consts/const-points-to-static.64bit.stderr create mode 100644 src/test/ui/consts/const_fn_trait_bound.gated.stderr create mode 100644 src/test/ui/consts/const_fn_trait_bound.rs create mode 100644 src/test/ui/consts/const_fn_trait_bound.stock.stderr create mode 100644 src/test/ui/consts/const_fn_unsize.gated.stderr create mode 100644 src/test/ui/consts/const_fn_unsize.rs create mode 100644 src/test/ui/consts/const_fn_unsize.stock.stderr rename src/test/ui/{issues => consts}/issue-52060.rs (100%) rename src/test/ui/{issues => consts}/issue-52060.stderr (100%) rename src/test/ui/consts/{issue-63952.stderr => issue-63952.32bit.stderr} (77%) create mode 100644 src/test/ui/consts/issue-63952.64bit.stderr rename src/test/ui/consts/{issue-79690.stderr => issue-79690.64bit.stderr} (68%) rename src/test/ui/{ => consts}/mir_check_nonconst.rs (100%) rename src/test/ui/{ => consts}/mir_check_nonconst.stderr (100%) rename src/test/ui/consts/miri_unleashed/{const_refers_to_static2.stderr => const_refers_to_static2.32bit.stderr} (74%) create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr rename src/test/ui/consts/miri_unleashed/{const_refers_to_static_cross_crate.stderr => const_refers_to_static_cross_crate.32bit.stderr} (75%) create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr rename src/test/ui/consts/miri_unleashed/{mutable_references_err.stderr => mutable_references_err.32bit.stderr} (72%) create mode 100644 src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr rename src/test/ui/consts/std/{alloc.stderr => alloc.32bit.stderr} (79%) create mode 100644 src/test/ui/consts/std/alloc.64bit.stderr rename src/test/ui/consts/{validate_never_arrays.stderr => validate_never_arrays.32bit.stderr} (75%) create mode 100644 src/test/ui/consts/validate_never_arrays.64bit.stderr create mode 100644 src/test/ui/crate-loading/missing-std.rs create mode 100644 src/test/ui/crate-loading/missing-std.stderr create mode 100644 src/test/ui/dep-graph/dep-graph-check-attr.rs create mode 100644 src/test/ui/dep-graph/dep-graph-check-attr.stderr create mode 100644 src/test/ui/derives/derive-macro-const-default.rs rename src/test/ui/{bad => destructuring-assignment}/bad-expr-lhs.rs (100%) rename src/test/ui/{bad => destructuring-assignment}/bad-expr-lhs.stderr (100%) create mode 100644 src/test/ui/did_you_mean/pub-macro-rules.rs create mode 100644 src/test/ui/did_you_mean/pub-macro-rules.stderr create mode 100644 src/test/ui/entry-point/auxiliary/main_functions.rs create mode 100644 src/test/ui/entry-point/imported_main_conflict.rs create mode 100644 src/test/ui/entry-point/imported_main_conflict.stderr create mode 100644 src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs create mode 100644 src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr create mode 100644 src/test/ui/entry-point/imported_main_const_forbidden.rs create mode 100644 src/test/ui/entry-point/imported_main_const_forbidden.stderr create mode 100644 src/test/ui/entry-point/imported_main_from_extern_crate.rs create mode 100644 src/test/ui/entry-point/imported_main_from_extern_crate.stderr create mode 100644 src/test/ui/entry-point/imported_main_from_inner_mod.rs create mode 100644 src/test/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs delete mode 100644 src/test/ui/error-codes/E0137.rs delete mode 100644 src/test/ui/error-codes/E0137.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs create mode 100644 src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_spotlight.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-imported_main.rs create mode 100644 src/test/ui/feature-gates/feature-gate-imported_main.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-large-assignments.rs create mode 100644 src/test/ui/feature-gates/feature-gate-large-assignments.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-link_args.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-link_args.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-main.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-main.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-no_coverage.rs create mode 100644 src/test/ui/feature-gates/feature-gate-no_coverage.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-wasm_abi.rs create mode 100644 src/test/ui/feature-gates/feature-gate-wasm_abi.stderr create mode 100644 src/test/ui/feature-gates/thread-local-const-init.rs create mode 100644 src/test/ui/feature-gates/thread-local-const-init.stderr rename src/test/ui/{bad => fn}/bad-main.rs (100%) rename src/test/ui/{bad => fn}/bad-main.stderr (100%) rename src/test/ui/{issues => generator}/issue-45729-unsafe-in-generator.rs (100%) rename src/test/ui/{issues => generator}/issue-45729-unsafe-in-generator.stderr (100%) create mode 100644 src/test/ui/generic-associated-types/issue-70303.rs create mode 100644 src/test/ui/generic-associated-types/issue-70304.rs create mode 100644 src/test/ui/generic-associated-types/issue-70304.stderr create mode 100644 src/test/ui/generic-associated-types/issue-71176.rs create mode 100644 src/test/ui/generic-associated-types/issue-71176.stderr create mode 100644 src/test/ui/generic-associated-types/issue-78671.rs create mode 100644 src/test/ui/generic-associated-types/issue-78671.stderr create mode 100644 src/test/ui/generic-associated-types/issue-79636-1.rs create mode 100644 src/test/ui/generic-associated-types/issue-79636-1.stderr create mode 100644 src/test/ui/generic-associated-types/issue-79636-2.rs create mode 100644 src/test/ui/generic-associated-types/issue-79636-2.stderr create mode 100644 src/test/ui/generic-associated-types/trait-objects.rs create mode 100644 src/test/ui/generic-associated-types/trait-objects.stderr rename src/test/ui/{bad => generics}/bad-mid-path-type-params.rs (100%) rename src/test/ui/{bad => generics}/bad-mid-path-type-params.stderr (100%) create mode 100644 src/test/ui/generics/generic-function-item-where-type.rs create mode 100644 src/test/ui/generics/generic-function-item-where-type.stderr create mode 100644 src/test/ui/hrtb/complex.rs rename src/test/ui/{ => impl-trait}/impl-trait-in-bindings-issue-73003.rs (100%) rename src/test/ui/{ => impl-trait}/impl-trait-in-bindings-issue-73003.stderr (100%) rename src/test/ui/{ => impl-trait}/impl-trait-in-bindings.rs (100%) rename src/test/ui/{ => impl-trait}/impl-trait-in-bindings.stderr (100%) create mode 100644 src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs create mode 100644 src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr create mode 100644 src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs create mode 100644 src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr delete mode 100644 src/test/ui/imports/local-modularized-tricky-fail-3.rs delete mode 100644 src/test/ui/imports/local-modularized-tricky-fail-3.stderr rename src/test/ui/imports/{local-modularized-tricky-pass.rs => local-modularized-tricky-pass-1.rs} (100%) create mode 100644 src/test/ui/imports/local-modularized-tricky-pass-2.rs create mode 100644 src/test/ui/imports/tool-mod-child.rs create mode 100644 src/test/ui/imports/tool-mod-child.stderr create mode 100644 src/test/ui/inference/issue-81522.rs create mode 100644 src/test/ui/inference/issue-83606.rs create mode 100644 src/test/ui/inference/issue-83606.stderr rename src/test/ui/{bad => intrinsics}/bad-intrinsic-monomorphization.rs (100%) rename src/test/ui/{bad => intrinsics}/bad-intrinsic-monomorphization.stderr (100%) create mode 100644 src/test/ui/intrinsics/issue-84297-reifying-copy.rs create mode 100644 src/test/ui/issue-83639.rs create mode 100644 src/test/ui/issue-83639.stderr create mode 100644 src/test/ui/issue-85713-align-with-no-arg.rs create mode 100644 src/test/ui/issue-85713-align-with-no-arg.stderr delete mode 100644 src/test/ui/issues/issue-15487.rs create mode 100644 src/test/ui/issues/issue-83048.rs create mode 100644 src/test/ui/issues/issue-83048.stderr create mode 100644 src/test/ui/issues/issue-83924.fixed create mode 100644 src/test/ui/issues/issue-83924.rs create mode 100644 src/test/ui/issues/issue-83924.stderr delete mode 100644 src/test/ui/iterators/array-of-ranges.stderr delete mode 100644 src/test/ui/iterators/array.stderr create mode 100644 src/test/ui/iterators/into-iter-on-arrays-2018.rs create mode 100644 src/test/ui/iterators/into-iter-on-arrays-2018.stderr create mode 100644 src/test/ui/iterators/into-iter-on-arrays-2021.rs create mode 100644 src/test/ui/lifetimes/issue-83737-binders-across-types.rs create mode 100644 src/test/ui/lifetimes/issue-83737-erasing-bound-vars.rs create mode 100644 src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs create mode 100644 src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr create mode 100644 src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.rs create mode 100644 src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr create mode 100644 src/test/ui/lifetimes/issue-84398.rs create mode 100644 src/test/ui/lifetimes/issue-84604.rs rename src/test/ui/{bad => linkage-attr}/bad-extern-link-attrs.rs (100%) rename src/test/ui/{bad => linkage-attr}/bad-extern-link-attrs.stderr (100%) delete mode 100644 src/test/ui/linkage-attr/invalid-link-args.rs rename src/test/ui/{bad => lint}/bad-lint-cap.rs (100%) rename src/test/ui/{bad => lint}/bad-lint-cap.stderr (100%) rename src/test/ui/{bad => lint}/bad-lint-cap2.rs (100%) rename src/test/ui/{bad => lint}/bad-lint-cap2.stderr (100%) rename src/test/ui/{bad => lint}/bad-lint-cap3.rs (100%) rename src/test/ui/{bad => lint}/bad-lint-cap3.stderr (100%) rename src/test/ui/{ => lint}/fn_must_use.rs (100%) rename src/test/ui/{ => lint}/fn_must_use.stderr (100%) create mode 100644 src/test/ui/lint/issue-83477.rs create mode 100644 src/test/ui/lint/issue-83477.stderr create mode 100644 src/test/ui/lint/lint-deref-nullptr.rs create mode 100644 src/test/ui/lint/lint-deref-nullptr.stderr create mode 100644 src/test/ui/loops/loop-no-implicit-break.rs create mode 100644 src/test/ui/loops/loop-no-implicit-break.stderr create mode 100644 src/test/ui/macros/attr-empty-expr.rs create mode 100644 src/test/ui/macros/attr-empty-expr.stderr rename src/test/ui/{ => macros}/concat-rpass.rs (100%) create mode 100644 src/test/ui/macros/issue-83340.rs create mode 100644 src/test/ui/macros/issue-83340.stderr create mode 100644 src/test/ui/macros/issue-83344.rs create mode 100644 src/test/ui/macros/issue-83344.stderr create mode 100644 src/test/ui/macros/issue-84195-lint-anon-const.rs create mode 100644 src/test/ui/macros/issue-84195-lint-anon-const.stderr create mode 100644 src/test/ui/macros/issue-85432-ungated-attr-macro.rs delete mode 100644 src/test/ui/macros/macro-export-on-modularized-macros.rs delete mode 100644 src/test/ui/macros/macro-export-on-modularized-macros.stderr create mode 100644 src/test/ui/macros/macro-or-patterns-back-compat.fixed create mode 100644 src/test/ui/macros/macro-or-patterns-back-compat.rs create mode 100644 src/test/ui/macros/macro-or-patterns-back-compat.stderr create mode 100644 src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs create mode 100644 src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr create mode 100644 src/test/ui/macros/macro-pat-pattern-followed-by-or.rs create mode 100644 src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs create mode 100644 src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr create mode 100644 src/test/ui/macros/none-delim-lookahead.rs delete mode 100644 src/test/ui/macros/pub-macro-rules-fail.rs delete mode 100644 src/test/ui/macros/pub-macro-rules-fail.stderr delete mode 100644 src/test/ui/macros/pub-macro-rules.rs create mode 100644 src/test/ui/match/issue-82392.rs create mode 100644 src/test/ui/match/issue-82392.stdout create mode 100644 src/test/ui/match/issue-84434.rs create mode 100644 src/test/ui/mir/issue-83499-input-output-iteration-ice.rs create mode 100644 src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr delete mode 100644 src/test/ui/multiple-main-2.rs delete mode 100644 src/test/ui/multiple-main-2.stderr delete mode 100644 src/test/ui/multiple-main-3.rs delete mode 100644 src/test/ui/multiple-main-3.stderr delete mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs delete mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr delete mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs delete mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr delete mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns.rs delete mode 100644 src/test/ui/or-patterns/feature-gate-or_patterns.stderr create mode 100644 src/test/ui/packed/packed-struct-borrow-element-64bit.rs create mode 100644 src/test/ui/packed/packed-struct-borrow-element-64bit.stderr create mode 100644 src/test/ui/packed/packed-struct-borrow-element.stderr delete mode 100644 src/test/ui/panic-runtime/unwind-tables-panic-required.rs rename src/test/ui/{bad => parser}/bad-crate-name.rs (100%) rename src/test/ui/{bad => parser}/bad-crate-name.stderr (100%) rename src/test/ui/{issues => parser}/issue-48508-aux.rs (100%) rename src/test/ui/{issues => parser}/issue-48508.rs (95%) rename src/test/ui/{issues => parser}/issue-68000-unicode-ident-after-missing-comma.rs (100%) rename src/test/ui/{issues => parser}/issue-68000-unicode-ident-after-missing-comma.stderr (100%) create mode 100644 src/test/ui/parser/issue-84117.rs create mode 100644 src/test/ui/parser/issue-84117.stderr create mode 100644 src/test/ui/parser/use-unclosed-brace.rs create mode 100644 src/test/ui/parser/use-unclosed-brace.stderr rename src/test/ui/{issues => pattern}/issue-10392.rs (100%) create mode 100644 src/test/ui/proc-macro/auxiliary/issue-75801.rs create mode 100644 src/test/ui/proc-macro/auxiliary/issue-79825.rs create mode 100644 src/test/ui/proc-macro/auxiliary/issue-83510.rs create mode 100644 src/test/ui/proc-macro/auxiliary/multiple-derives.rs create mode 100644 src/test/ui/proc-macro/cfg-eval-inner.rs create mode 100644 src/test/ui/proc-macro/cfg-eval-inner.stdout create mode 100644 src/test/ui/proc-macro/derive-expand-order.rs create mode 100644 src/test/ui/proc-macro/derive-expand-order.stdout create mode 100644 src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs create mode 100644 src/test/ui/proc-macro/inner-attrs.stderr create mode 100644 src/test/ui/proc-macro/issue-75801.rs create mode 100644 src/test/ui/proc-macro/issue-75801.stderr create mode 100644 src/test/ui/proc-macro/issue-79825.rs create mode 100644 src/test/ui/proc-macro/issue-81555.rs create mode 100644 src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs create mode 100644 src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr create mode 100644 src/test/ui/proc-macro/issue-83510.rs create mode 100644 src/test/ui/proc-macro/issue-83510.stderr create mode 100644 src/test/ui/proc-macro/nonterminal-recollect-attr.stdout create mode 100644 src/test/ui/proc-macro/simple-tuple.rs create mode 100644 src/test/ui/proc-macro/simple-tuple.stdout create mode 100644 src/test/ui/recursion/issue-83150.rs create mode 100644 src/test/ui/recursion/issue-83150.stderr create mode 100644 src/test/ui/resolve/auxiliary/issue-80079.rs rename src/test/ui/{bad => resolve}/bad-env-capture.rs (100%) rename src/test/ui/{bad => resolve}/bad-env-capture.stderr (100%) rename src/test/ui/{bad => resolve}/bad-env-capture2.rs (100%) rename src/test/ui/{bad => resolve}/bad-env-capture2.stderr (100%) rename src/test/ui/{bad => resolve}/bad-env-capture3.rs (100%) rename src/test/ui/{bad => resolve}/bad-env-capture3.stderr (100%) rename src/test/ui/{bad => resolve}/bad-expr-path.rs (100%) rename src/test/ui/{bad => resolve}/bad-expr-path.stderr (100%) rename src/test/ui/{bad => resolve}/bad-expr-path2.rs (100%) rename src/test/ui/{bad => resolve}/bad-expr-path2.stderr (100%) rename src/test/ui/{bad => resolve}/bad-module.rs (100%) rename src/test/ui/{bad => resolve}/bad-module.stderr (100%) rename src/test/ui/{bad => resolve}/bad-type-env-capture.rs (100%) rename src/test/ui/{bad => resolve}/bad-type-env-capture.stderr (100%) create mode 100644 src/test/ui/resolve/issue-80079.rs create mode 100644 src/test/ui/resolve/issue-80079.stderr create mode 100644 src/test/ui/resolve/issue-81508.rs create mode 100644 src/test/ui/resolve/issue-81508.stderr create mode 100644 src/test/ui/resolve/issue-82865.rs create mode 100644 src/test/ui/resolve/issue-82865.stderr rename src/test/ui/{ => resolve}/no-implicit-prelude.rs (100%) rename src/test/ui/{ => resolve}/no-implicit-prelude.stderr (100%) create mode 100644 src/test/ui/rfc-2457/extern_block_nonascii_forbidden.rs create mode 100644 src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr create mode 100644 src/test/ui/specialization/issue-33017.rs create mode 100644 src/test/ui/specialization/issue-33017.stderr create mode 100644 src/test/ui/specialization/issue-51892.rs create mode 100644 src/test/ui/specialization/issue-51892.stderr create mode 100644 src/test/ui/specialization/issue-68830-spurious-diagnostics.rs create mode 100644 src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr rename src/test/ui/{bad => static}/bad-const-type.rs (100%) rename src/test/ui/{bad => static}/bad-const-type.stderr (100%) rename src/test/ui/{issues => structs-enums}/issue-1701.rs (100%) create mode 100644 src/test/ui/suggestions/as-ref-2.fixed create mode 100644 src/test/ui/suggestions/as-ref-2.rs create mode 100644 src/test/ui/suggestions/as-ref-2.stderr create mode 100644 src/test/ui/suggestions/import-trait-for-method-call.rs create mode 100644 src/test/ui/suggestions/import-trait-for-method-call.stderr create mode 100644 src/test/ui/suggestions/issue-83892.fixed create mode 100644 src/test/ui/suggestions/issue-83892.rs create mode 100644 src/test/ui/suggestions/issue-83892.stderr create mode 100644 src/test/ui/suggestions/issue-83943.fixed create mode 100644 src/test/ui/suggestions/issue-83943.rs create mode 100644 src/test/ui/suggestions/issue-83943.stderr delete mode 100644 src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr delete mode 100644 src/test/ui/symbol-names/impl1.stderr delete mode 100644 src/test/ui/symbol-names/issue-60925.stderr create mode 100644 src/test/ui/traits/alias/issue-83613.rs create mode 100644 src/test/ui/traits/alias/issue-83613.stderr create mode 100644 src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed create mode 100644 src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs create mode 100644 src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr create mode 100644 src/test/ui/traits/associated_type_bound/issue-51446.rs rename src/test/ui/{bad => traits}/bad-method-typaram-kind.rs (100%) rename src/test/ui/{bad => traits}/bad-method-typaram-kind.stderr (79%) rename src/test/ui/{bad => traits}/bad-sized.rs (100%) rename src/test/ui/{bad => traits}/bad-sized.stderr (100%) rename src/test/ui/{issues => traits}/issue-78372.rs (100%) rename src/test/ui/{issues => traits}/issue-78372.stderr (100%) rename src/test/ui/{issues => typeck}/issue-65611.rs (97%) rename src/test/ui/{issues => typeck}/issue-65611.stderr (100%) create mode 100644 src/test/ui/typeck/issue-75883.rs create mode 100644 src/test/ui/typeck/issue-75883.stderr create mode 100644 src/test/ui/typeck/issue-80779.rs create mode 100644 src/test/ui/typeck/issue-80779.stderr create mode 100644 src/test/ui/typeck/issue-83621-placeholder-static-in-extern.rs create mode 100644 src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr create mode 100644 src/test/ui/typeck/issue-84831.rs create mode 100644 src/test/ui/typeck/issue-84831.stderr create mode 100644 src/test/ui/typeof/type_mismatch.rs create mode 100644 src/test/ui/typeof/type_mismatch.stderr create mode 100644 src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs delete mode 100644 src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs delete mode 100644 src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr create mode 100644 src/test/ui/unsized/unsized-fn-arg.fixed create mode 100644 src/test/ui/unsized/unsized-fn-arg.rs create mode 100644 src/test/ui/unsized/unsized-fn-arg.stderr rename src/test/ui/{ => unsized}/unsized-tuple-impls.rs (100%) rename src/test/ui/{ => unsized}/unsized.rs (100%) rename src/test/ui/{ => unsized}/unsized2.rs (100%) rename src/test/ui/{ => unsized}/unsized3-rpass.rs (100%) rename src/test/ui/{ => unsized}/unsized3.rs (100%) rename src/test/ui/{ => unsized}/unsized3.stderr (74%) rename src/test/ui/{ => unsized}/unsized5.rs (100%) rename src/test/ui/{ => unsized}/unsized5.stderr (93%) rename src/test/ui/{ => unsized}/unsized6.rs (100%) rename src/test/ui/{ => unsized}/unsized6.stderr (85%) rename src/test/ui/{ => unsized}/unsized7.rs (100%) rename src/test/ui/{ => unsized}/unsized7.stderr (89%) create mode 100644 src/test/ui/unused/unused-doc-comments-for-macros.rs create mode 100644 src/test/ui/unused/unused-doc-comments-for-macros.stderr rename src/test/ui/{ => unused}/useless-comment.rs (100%) rename src/test/ui/{ => unused}/useless-comment.stderr (100%) create mode 100644 src/test/ui/unwind-no-uwtable.rs delete mode 100644 src/test/ui/utf8_idents.stderr rename src/tools/clippy/clippy_dev/src/{ra_setup.rs => ide_setup.rs} (97%) create mode 100644 src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs create mode 100644 src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs delete mode 100644 src/tools/clippy/clippy_lints/src/functions.rs create mode 100644 src/tools/clippy/clippy_lints/src/functions/mod.rs create mode 100644 src/tools/clippy/clippy_lints/src/functions/must_use.rs create mode 100644 src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs create mode 100644 src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs create mode 100644 src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs create mode 100644 src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs create mode 100644 src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs create mode 100644 src/tools/clippy/clippy_lints/src/implicit_hasher.rs create mode 100644 src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs delete mode 100644 src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs delete mode 100644 src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs delete mode 100644 src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/utils.rs create mode 100644 src/tools/clippy/clippy_lints/src/needless_for_each.rs create mode 100644 src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs create mode 100644 src/tools/clippy/clippy_lints/src/types/type_complexity.rs create mode 100644 src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs create mode 100644 src/tools/clippy/clippy_lints/src/unit_types/mod.rs create mode 100644 src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs create mode 100644 src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs create mode 100644 src/tools/clippy/clippy_lints/src/unit_types/utils.rs create mode 100644 src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs create mode 100644 src/tools/clippy/clippy_utils/src/msrvs.rs create mode 100644 src/tools/clippy/clippy_utils/src/source.rs create mode 100644 src/tools/clippy/clippy_utils/src/ty.rs create mode 100644 src/tools/clippy/tests/ui-internal/if_chain_style.rs create mode 100644 src/tools/clippy/tests/ui-internal/if_chain_style.stderr create mode 100644 src/tools/clippy/tests/ui/bool_assert_comparison.rs create mode 100644 src/tools/clippy/tests/ui/bool_assert_comparison.stderr create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr delete mode 100644 src/tools/clippy/tests/ui/clone_on_copy_mut.rs create mode 100644 src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed create mode 100644 src/tools/clippy/tests/ui/cloned_instead_of_copied.rs create mode 100644 src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr create mode 100644 src/tools/clippy/tests/ui/crashes/ice-5835.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-5835.stderr create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7012.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7126.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7169.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7169.stderr delete mode 100644 src/tools/clippy/tests/ui/dereference.stderr create mode 100644 src/tools/clippy/tests/ui/entry.fixed create mode 100644 src/tools/clippy/tests/ui/entry.rs create mode 100644 src/tools/clippy/tests/ui/entry.stderr delete mode 100644 src/tools/clippy/tests/ui/entry_fixable.fixed delete mode 100644 src/tools/clippy/tests/ui/entry_fixable.rs delete mode 100644 src/tools/clippy/tests/ui/entry_fixable.stderr delete mode 100644 src/tools/clippy/tests/ui/entry_unfixable.rs delete mode 100644 src/tools/clippy/tests/ui/entry_unfixable.stderr create mode 100644 src/tools/clippy/tests/ui/entry_with_else.fixed create mode 100644 src/tools/clippy/tests/ui/entry_with_else.rs create mode 100644 src/tools/clippy/tests/ui/entry_with_else.stderr rename src/tools/clippy/tests/ui/{dereference.fixed => explicit_deref_methods.fixed} (91%) rename src/tools/clippy/tests/ui/{dereference.rs => explicit_deref_methods.rs} (97%) create mode 100644 src/tools/clippy/tests/ui/explicit_deref_methods.stderr delete mode 100644 src/tools/clippy/tests/ui/filter_methods.rs delete mode 100644 src/tools/clippy/tests/ui/filter_methods.stderr create mode 100644 src/tools/clippy/tests/ui/flat_map_option.fixed create mode 100644 src/tools/clippy/tests/ui/flat_map_option.rs create mode 100644 src/tools/clippy/tests/ui/flat_map_option.stderr create mode 100644 src/tools/clippy/tests/ui/if_then_some_else_none.rs create mode 100644 src/tools/clippy/tests/ui/if_then_some_else_none.stderr create mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed create mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs create mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr rename src/tools/clippy/tests/ui/{dlist.rs => linkedlist.rs} (90%) rename src/tools/clippy/tests/ui/{dlist.stderr => linkedlist.stderr} (65%) create mode 100644 src/tools/clippy/tests/ui/match_single_binding2.fixed create mode 100644 src/tools/clippy/tests/ui/match_single_binding2.rs create mode 100644 src/tools/clippy/tests/ui/match_single_binding2.stderr create mode 100644 src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs rename src/tools/clippy/tests/ui/{doc_panics.rs => missing_panics_doc.rs} (74%) rename src/tools/clippy/tests/ui/{doc_panics.stderr => missing_panics_doc.stderr} (59%) create mode 100644 src/tools/clippy/tests/ui/needless_for_each_fixable.fixed create mode 100644 src/tools/clippy/tests/ui/needless_for_each_fixable.rs create mode 100644 src/tools/clippy/tests/ui/needless_for_each_fixable.stderr create mode 100644 src/tools/clippy/tests/ui/needless_for_each_unfixable.rs create mode 100644 src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr create mode 100644 src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed create mode 100644 src/tools/clippy/tests/ui/non_octal_unix_permissions.rs create mode 100644 src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr create mode 100644 src/tools/clippy/tests/ui/option_filter_map.fixed create mode 100644 src/tools/clippy/tests/ui/option_filter_map.rs create mode 100644 src/tools/clippy/tests/ui/option_filter_map.stderr delete mode 100644 src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.stderr create mode 100644 src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed create mode 100644 src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs create mode 100644 src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr create mode 100644 src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed create mode 100644 src/tools/clippy/tests/ui/single_component_path_imports_macro.rs create mode 100644 src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr create mode 100644 src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs create mode 100644 src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr create mode 100644 src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs create mode 100644 src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs rename src/tools/clippy/tests/ui/{complex_types.rs => type_complexity.rs} (100%) rename src/tools/clippy/tests/ui/{complex_types.stderr => type_complexity.stderr} (85%) create mode 100644 src/tools/clippy/tests/ui/unnecessary_self_imports.fixed create mode 100644 src/tools/clippy/tests/ui/unnecessary_self_imports.rs create mode 100644 src/tools/clippy/tests/ui/unnecessary_self_imports.stderr delete mode 100644 src/tools/clippy/tests/ui/unnested_or_patterns3.rs create mode 100644 src/tools/clippy/tests/ui/write_literal_2.rs create mode 100644 src/tools/clippy/tests/ui/write_literal_2.stderr create mode 100644 src/tools/clippy/tests/ui/wrong_self_convention2.rs create mode 100644 src/tools/clippy/tests/ui/wrong_self_convention2.stderr create mode 100644 src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs create mode 100644 src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr create mode 100644 src/tools/rust-demangler/README.md create mode 100644 src/tools/rust-demangler/src/lib.rs rename src/tools/rust-demangler/{ => src}/main.rs (76%) create mode 100644 src/tools/rust-demangler/tests/lib.rs create mode 100644 src/tools/rustfmt/tests/source/configs/chain_width/always.rs create mode 100644 src/tools/rustfmt/tests/source/configs/chain_width/small.rs create mode 100644 src/tools/rustfmt/tests/source/configs/chain_width/tiny.rs create mode 100644 src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs create mode 100644 src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4312.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4427.rs create mode 100644 src/tools/rustfmt/tests/source/issue-4603.rs create mode 100644 src/tools/rustfmt/tests/target/configs/chain_width/always.rs create mode 100644 src/tools/rustfmt/tests/target/configs/chain_width/small.rs create mode 100644 src/tools/rustfmt/tests/target/configs/chain_width/tiny.rs create mode 100644 src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs create mode 100644 src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs delete mode 100644 src/tools/rustfmt/tests/target/issue-3592.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4312.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4427.rs create mode 100644 src/tools/rustfmt/tests/target/issue-4603.rs create mode 100644 src/tools/rustfmt/tests/target/issue_4049.rs delete mode 100644 vendor/annotate-snippets-0.6.1/.cargo-checksum.json delete mode 100644 vendor/annotate-snippets-0.6.1/CHANGELOG.md delete mode 100644 vendor/annotate-snippets-0.6.1/Cargo.toml delete mode 100644 vendor/annotate-snippets-0.6.1/LICENSE-APACHE delete mode 100644 vendor/annotate-snippets-0.6.1/LICENSE-MIT delete mode 100644 vendor/annotate-snippets-0.6.1/README.md delete mode 100644 vendor/annotate-snippets-0.6.1/examples/expected_type.rs delete mode 100644 vendor/annotate-snippets-0.6.1/examples/footer.rs delete mode 100644 vendor/annotate-snippets-0.6.1/examples/format.rs delete mode 100644 vendor/annotate-snippets-0.6.1/examples/multislice.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/display_list/from_snippet.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/display_list/mod.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/display_list/structs.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/formatter/mod.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/formatter/style.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/lib.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/snippet.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/stylesheets/color.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/stylesheets/mod.rs delete mode 100644 vendor/annotate-snippets-0.6.1/src/stylesheets/no_color.rs delete mode 100644 vendor/annotate-snippets-0.6.1/tests/diff/mod.rs delete mode 100644 vendor/annotate-snippets-0.6.1/tests/dl_from_snippet.rs delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures.rs delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.txt delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.yaml delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.txt delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.yaml delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.txt delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.yaml delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.txt delete mode 100644 vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.yaml delete mode 100644 vendor/annotate-snippets-0.6.1/tests/formatter.rs delete mode 100644 vendor/annotate-snippets-0.6.1/tests/snippet/mod.rs delete mode 100644 vendor/arrayref/.cargo-checksum.json delete mode 100644 vendor/arrayref/Cargo.lock delete mode 100644 vendor/arrayref/LICENSE delete mode 100644 vendor/arrayref/README.md delete mode 100644 vendor/arrayref/examples/array_refs.rs delete mode 100644 vendor/arrayref/examples/array_refs_with_const.rs delete mode 100644 vendor/arrayref/examples/simple-case.rs delete mode 100644 vendor/arrayref/src/lib.rs mode change 100644 => 100755 vendor/arrayvec/ci/miri.sh delete mode 100644 vendor/arrayvec/custom.css delete mode 100644 vendor/arrayvec/src/array.rs create mode 100644 vendor/arrayvec/src/arrayvec.rs create mode 100644 vendor/arrayvec/src/arrayvec_impl.rs delete mode 100644 vendor/arrayvec/src/maybe_uninit.rs create mode 100644 vendor/arrayvec/src/utils.rs delete mode 100644 vendor/base64/.cargo-checksum.json delete mode 100644 vendor/base64/Cargo.lock delete mode 100644 vendor/base64/Cargo.toml delete mode 100644 vendor/base64/LICENSE-MIT delete mode 100644 vendor/base64/README.md delete mode 100644 vendor/base64/RELEASE-NOTES.md delete mode 100644 vendor/base64/benches/benchmarks.rs delete mode 100644 vendor/base64/examples/make_tables.rs delete mode 100644 vendor/base64/icon_CLion.svg delete mode 100644 vendor/base64/src/chunked_encoder.rs delete mode 100644 vendor/base64/src/decode.rs delete mode 100644 vendor/base64/src/display.rs delete mode 100644 vendor/base64/src/encode.rs delete mode 100644 vendor/base64/src/lib.rs delete mode 100644 vendor/base64/src/tables.rs delete mode 100644 vendor/base64/src/tests.rs delete mode 100644 vendor/base64/src/write/encoder.rs delete mode 100644 vendor/base64/src/write/encoder_tests.rs delete mode 100644 vendor/base64/src/write/mod.rs delete mode 100644 vendor/base64/tests/decode.rs delete mode 100644 vendor/base64/tests/encode.rs delete mode 100644 vendor/base64/tests/helpers.rs delete mode 100644 vendor/base64/tests/tests.rs delete mode 100644 vendor/blake2b_simd/.cargo-checksum.json delete mode 100644 vendor/blake2b_simd/README.md delete mode 100644 vendor/blake2b_simd/src/avx2.rs delete mode 100644 vendor/blake2b_simd/src/blake2bp.rs delete mode 100644 vendor/blake2b_simd/src/guts.rs delete mode 100644 vendor/blake2b_simd/src/lib.rs delete mode 100644 vendor/blake2b_simd/src/many.rs delete mode 100644 vendor/blake2b_simd/src/portable.rs delete mode 100644 vendor/blake2b_simd/src/sse41.rs delete mode 100644 vendor/blake2b_simd/src/test.rs create mode 100755 vendor/bytecount/ci/miri.sh delete mode 100644 vendor/constant_time_eq/.cargo-checksum.json delete mode 100644 vendor/constant_time_eq/Cargo.toml delete mode 100644 vendor/constant_time_eq/LICENSE.txt delete mode 100644 vendor/constant_time_eq/README delete mode 100644 vendor/constant_time_eq/benches/bench.rs delete mode 100644 vendor/constant_time_eq/src/lib.rs delete mode 100644 vendor/fs_extra/.cargo-checksum.json delete mode 100644 vendor/fs_extra/Cargo.toml delete mode 100644 vendor/fs_extra/LICENSE delete mode 100644 vendor/fs_extra/README.md delete mode 100644 vendor/fs_extra/src/dir.rs delete mode 100644 vendor/fs_extra/src/error.rs delete mode 100644 vendor/fs_extra/src/file.rs delete mode 100644 vendor/fs_extra/src/lib.rs delete mode 100644 vendor/fs_extra/tests/dir.rs delete mode 100644 vendor/fs_extra/tests/file.rs delete mode 100644 vendor/fs_extra/tests/lib.rs create mode 100644 vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs create mode 100644 vendor/libc/src/unix/linux_like/linux/arch/mips/mod.rs create mode 100644 vendor/libc/src/unix/linux_like/linux/arch/mod.rs create mode 100644 vendor/libc/src/unix/linux_like/linux/arch/powerpc/mod.rs create mode 100644 vendor/libc/src/unix/linux_like/linux/arch/sparc/mod.rs mode change 100644 => 100755 vendor/libc/src/vxworks/mod.rs create mode 100644 vendor/libm/.cargo-checksum.json create mode 100644 vendor/libm/CHANGELOG.md create mode 100644 vendor/libm/CONTRIBUTING.md rename vendor/{blake2b_simd => libm}/Cargo.toml (53%) rename vendor/{base64 => libm}/LICENSE-APACHE (100%) rename vendor/{socket2 => libm}/LICENSE-MIT (96%) create mode 100644 vendor/libm/README.md create mode 100644 vendor/libm/azure-pipelines.yml create mode 100644 vendor/libm/build.rs create mode 100644 vendor/libm/ci/azure-install-rust.yml create mode 100644 vendor/libm/ci/docker/aarch64-unknown-linux-gnu/Dockerfile create mode 100644 vendor/libm/ci/docker/arm-unknown-linux-gnueabi/Dockerfile create mode 100644 vendor/libm/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile create mode 100644 vendor/libm/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile create mode 100644 vendor/libm/ci/docker/i686-unknown-linux-gnu/Dockerfile create mode 100644 vendor/libm/ci/docker/mips-unknown-linux-gnu/Dockerfile create mode 100644 vendor/libm/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile create mode 100644 vendor/libm/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile create mode 100644 vendor/libm/ci/docker/mipsel-unknown-linux-gnu/Dockerfile create mode 100644 vendor/libm/ci/docker/powerpc-unknown-linux-gnu/Dockerfile create mode 100644 vendor/libm/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile create mode 100644 vendor/libm/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile create mode 100644 vendor/libm/ci/docker/x86_64-unknown-linux-gnu/Dockerfile create mode 100755 vendor/libm/ci/run-docker.sh create mode 100755 vendor/libm/ci/run.sh create mode 100644 vendor/libm/src/lib.rs create mode 100644 vendor/libm/src/math/acos.rs create mode 100644 vendor/libm/src/math/acosf.rs create mode 100644 vendor/libm/src/math/acosh.rs create mode 100644 vendor/libm/src/math/acoshf.rs create mode 100644 vendor/libm/src/math/asin.rs create mode 100644 vendor/libm/src/math/asinf.rs create mode 100644 vendor/libm/src/math/asinh.rs create mode 100644 vendor/libm/src/math/asinhf.rs create mode 100644 vendor/libm/src/math/atan.rs create mode 100644 vendor/libm/src/math/atan2.rs create mode 100644 vendor/libm/src/math/atan2f.rs create mode 100644 vendor/libm/src/math/atanf.rs create mode 100644 vendor/libm/src/math/atanh.rs create mode 100644 vendor/libm/src/math/atanhf.rs create mode 100644 vendor/libm/src/math/cbrt.rs create mode 100644 vendor/libm/src/math/cbrtf.rs create mode 100644 vendor/libm/src/math/ceil.rs create mode 100644 vendor/libm/src/math/ceilf.rs create mode 100644 vendor/libm/src/math/copysign.rs create mode 100644 vendor/libm/src/math/copysignf.rs create mode 100644 vendor/libm/src/math/cos.rs create mode 100644 vendor/libm/src/math/cosf.rs create mode 100644 vendor/libm/src/math/cosh.rs create mode 100644 vendor/libm/src/math/coshf.rs create mode 100644 vendor/libm/src/math/erf.rs create mode 100644 vendor/libm/src/math/erff.rs create mode 100644 vendor/libm/src/math/exp.rs create mode 100644 vendor/libm/src/math/exp10.rs create mode 100644 vendor/libm/src/math/exp10f.rs create mode 100644 vendor/libm/src/math/exp2.rs create mode 100644 vendor/libm/src/math/exp2f.rs create mode 100644 vendor/libm/src/math/expf.rs create mode 100644 vendor/libm/src/math/expm1.rs create mode 100644 vendor/libm/src/math/expm1f.rs create mode 100644 vendor/libm/src/math/expo2.rs create mode 100644 vendor/libm/src/math/fabs.rs create mode 100644 vendor/libm/src/math/fabsf.rs create mode 100644 vendor/libm/src/math/fdim.rs create mode 100644 vendor/libm/src/math/fdimf.rs create mode 100644 vendor/libm/src/math/fenv.rs create mode 100644 vendor/libm/src/math/floor.rs create mode 100644 vendor/libm/src/math/floorf.rs create mode 100644 vendor/libm/src/math/fma.rs create mode 100644 vendor/libm/src/math/fmaf.rs create mode 100644 vendor/libm/src/math/fmax.rs create mode 100644 vendor/libm/src/math/fmaxf.rs create mode 100644 vendor/libm/src/math/fmin.rs create mode 100644 vendor/libm/src/math/fminf.rs create mode 100644 vendor/libm/src/math/fmod.rs create mode 100644 vendor/libm/src/math/fmodf.rs create mode 100644 vendor/libm/src/math/frexp.rs create mode 100644 vendor/libm/src/math/frexpf.rs create mode 100644 vendor/libm/src/math/hypot.rs create mode 100644 vendor/libm/src/math/hypotf.rs create mode 100644 vendor/libm/src/math/ilogb.rs create mode 100644 vendor/libm/src/math/ilogbf.rs create mode 100644 vendor/libm/src/math/j0.rs create mode 100644 vendor/libm/src/math/j0f.rs create mode 100644 vendor/libm/src/math/j1.rs create mode 100644 vendor/libm/src/math/j1f.rs create mode 100644 vendor/libm/src/math/jn.rs create mode 100644 vendor/libm/src/math/jnf.rs create mode 100644 vendor/libm/src/math/k_cos.rs create mode 100644 vendor/libm/src/math/k_cosf.rs create mode 100644 vendor/libm/src/math/k_expo2.rs create mode 100644 vendor/libm/src/math/k_expo2f.rs create mode 100644 vendor/libm/src/math/k_sin.rs create mode 100644 vendor/libm/src/math/k_sinf.rs create mode 100644 vendor/libm/src/math/k_tan.rs create mode 100644 vendor/libm/src/math/k_tanf.rs create mode 100644 vendor/libm/src/math/ldexp.rs create mode 100644 vendor/libm/src/math/ldexpf.rs create mode 100644 vendor/libm/src/math/lgamma.rs create mode 100644 vendor/libm/src/math/lgamma_r.rs create mode 100644 vendor/libm/src/math/lgammaf.rs create mode 100644 vendor/libm/src/math/lgammaf_r.rs create mode 100644 vendor/libm/src/math/log.rs create mode 100644 vendor/libm/src/math/log10.rs create mode 100644 vendor/libm/src/math/log10f.rs create mode 100644 vendor/libm/src/math/log1p.rs create mode 100644 vendor/libm/src/math/log1pf.rs create mode 100644 vendor/libm/src/math/log2.rs create mode 100644 vendor/libm/src/math/log2f.rs create mode 100644 vendor/libm/src/math/logf.rs create mode 100644 vendor/libm/src/math/mod.rs create mode 100644 vendor/libm/src/math/modf.rs create mode 100644 vendor/libm/src/math/modff.rs create mode 100644 vendor/libm/src/math/pow.rs create mode 100644 vendor/libm/src/math/powf.rs create mode 100644 vendor/libm/src/math/rem_pio2.rs create mode 100644 vendor/libm/src/math/rem_pio2_large.rs create mode 100644 vendor/libm/src/math/rem_pio2f.rs create mode 100644 vendor/libm/src/math/remquo.rs create mode 100644 vendor/libm/src/math/remquof.rs create mode 100644 vendor/libm/src/math/round.rs create mode 100644 vendor/libm/src/math/roundf.rs create mode 100644 vendor/libm/src/math/scalbn.rs create mode 100644 vendor/libm/src/math/scalbnf.rs create mode 100644 vendor/libm/src/math/sin.rs create mode 100644 vendor/libm/src/math/sincos.rs create mode 100644 vendor/libm/src/math/sincosf.rs create mode 100644 vendor/libm/src/math/sinf.rs create mode 100644 vendor/libm/src/math/sinh.rs create mode 100644 vendor/libm/src/math/sinhf.rs create mode 100644 vendor/libm/src/math/sqrt.rs create mode 100644 vendor/libm/src/math/sqrtf.rs create mode 100644 vendor/libm/src/math/tan.rs create mode 100644 vendor/libm/src/math/tanf.rs create mode 100644 vendor/libm/src/math/tanh.rs create mode 100644 vendor/libm/src/math/tanhf.rs create mode 100644 vendor/libm/src/math/tgamma.rs create mode 100644 vendor/libm/src/math/tgammaf.rs create mode 100644 vendor/libm/src/math/trunc.rs create mode 100644 vendor/libm/src/math/truncf.rs create mode 100644 vendor/miow/CHANGELOG.md delete mode 100644 vendor/packed_simd/.cargo-checksum.json delete mode 100644 vendor/packed_simd/src/codegen/shuffle.rs create mode 100644 vendor/packed_simd_2/.cargo-checksum.json rename vendor/{packed_simd => packed_simd_2}/Cargo.toml (74%) rename vendor/{packed_simd => packed_simd_2}/LICENSE-APACHE (100%) rename vendor/{packed_simd => packed_simd_2}/LICENSE-MIT (100%) rename vendor/{packed_simd/readme.md => packed_simd_2/README.md} (53%) rename vendor/{packed_simd => packed_simd_2}/bors.toml (100%) rename vendor/{packed_simd => packed_simd_2}/build.rs (100%) rename vendor/{packed_simd => packed_simd_2}/ci/all.sh (76%) rename vendor/{packed_simd => packed_simd_2}/ci/android-install-ndk.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/android-install-sdk.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/android-sysimage.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/benchmark.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/deploy_and_run_on_ios_simulator.rs (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/aarch64-linux-android/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/aarch64-unknown-linux-gnu/Dockerfile (95%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/arm-linux-androideabi/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/arm-unknown-linux-gnueabi/Dockerfile (96%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile (95%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile (95%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/i586-unknown-linux-gnu/Dockerfile (88%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/i686-unknown-linux-gnu/Dockerfile (88%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/mips-unknown-linux-gnu/Dockerfile (88%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile (87%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile (86%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/mipsel-unknown-linux-musl/Dockerfile (82%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/powerpc-unknown-linux-gnu/Dockerfile (89%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile (96%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile (96%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/s390x-unknown-linux-gnu/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/sparc64-unknown-linux-gnu/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/thumbv7neon-linux-androideabi/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile (95%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/wasm32-unknown-unknown/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/x86_64-linux-android/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile (100%) rename vendor/{packed_simd => packed_simd_2}/ci/docker/x86_64-unknown-linux-gnu/Dockerfile (90%) rename vendor/{packed_simd => packed_simd_2}/ci/dox.sh (83%) rename vendor/{packed_simd => packed_simd_2}/ci/linux-s390x.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/linux-sparc64.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/lld-shim.rs (100%) rename vendor/{packed_simd => packed_simd_2}/ci/max_line_width.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/run-docker.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/run.sh (92%) rename vendor/{packed_simd => packed_simd_2}/ci/run_examples.sh (100%) rename vendor/{packed_simd => packed_simd_2}/ci/runtest-android.rs (100%) rename vendor/{packed_simd => packed_simd_2}/ci/setup_benchmarks.sh (72%) rename vendor/{packed_simd => packed_simd_2}/ci/test-runner-linux (100%) rename vendor/{packed_simd => packed_simd_2}/contributing.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/book.toml (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/SUMMARY.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/ascii.css (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/bound_checks.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/float-math/approx.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/float-math/fma.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/float-math/fp.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/float-math/svml.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/introduction.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/prof/linux.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/prof/mca.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/prof/profiling.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/target-feature/attribute.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/target-feature/features.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/target-feature/inlining.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/target-feature/practice.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/target-feature/runtime.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/target-feature/rustflags.md (100%) rename vendor/{packed_simd => packed_simd_2}/perf-guide/src/vert-hor-ops.md (100%) rename vendor/{packed_simd => packed_simd_2}/rust-toolchain (100%) rename vendor/{packed_simd => packed_simd_2}/rustfmt.toml (100%) rename vendor/{packed_simd => packed_simd_2}/src/api.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/bit_manip.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/bitmask.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast.rs (95%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast/macros.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast/v128.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast/v16.rs (97%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast/v256.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast/v32.rs (98%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast/v512.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/cast/v64.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/cmp.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/cmp/eq.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/cmp/ord.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/cmp/partial_eq.rs (89%) rename vendor/{packed_simd => packed_simd_2}/src/api/cmp/partial_ord.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/cmp/vertical.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/default.rs (88%) rename vendor/{packed_simd => packed_simd_2}/src/api/fmt.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/fmt/binary.rs (86%) rename vendor/{packed_simd => packed_simd_2}/src/api/fmt/debug.rs (91%) rename vendor/{packed_simd => packed_simd_2}/src/api/fmt/lower_hex.rs (86%) rename vendor/{packed_simd => packed_simd_2}/src/api/fmt/octal.rs (86%) rename vendor/{packed_simd => packed_simd_2}/src/api/fmt/upper_hex.rs (86%) rename vendor/{packed_simd => packed_simd_2}/src/api/from.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/from/from_array.rs (97%) rename vendor/{packed_simd => packed_simd_2}/src/api/from/from_vector.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/hash.rs (93%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/arch_specific.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/macros.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/v128.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/v16.rs (94%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/v256.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/v32.rs (96%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/v512.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/api/into_bits/v64.rs (98%) rename vendor/{packed_simd => packed_simd_2}/src/api/math.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float.rs (97%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/abs.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/consts.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/cos.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/exp.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/ln.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/mul_add.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/mul_adde.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/powf.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/recpre.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/rsqrte.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/sin.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/sqrt.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/math/float/sqrte.rs (100%) create mode 100644 vendor/packed_simd_2/src/api/math/float/tanh.rs rename vendor/{packed_simd => packed_simd_2}/src/api/minimal.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/minimal/iuf.rs (96%) rename vendor/{packed_simd => packed_simd_2}/src/api/minimal/mask.rs (95%) rename vendor/{packed_simd => packed_simd_2}/src/api/minimal/ptr.rs (97%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/scalar_arithmetic.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/scalar_bitwise.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/scalar_mask_bitwise.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/scalar_shifts.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_arithmetic.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_bitwise.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_float_min_max.rs (91%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_int_min_max.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_mask_bitwise.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_neg.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_rotates.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ops/vector_shifts.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ptr.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/ptr/gather_scatter.rs (85%) rename vendor/{packed_simd => packed_simd_2}/src/api/reductions.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/reductions/bitwise.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/reductions/float_arithmetic.rs (95%) rename vendor/{packed_simd => packed_simd_2}/src/api/reductions/integer_arithmetic.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/reductions/mask.rs (92%) rename vendor/{packed_simd => packed_simd_2}/src/api/reductions/min_max.rs (98%) rename vendor/{packed_simd => packed_simd_2}/src/api/select.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/shuffle.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/shuffle1_dyn.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/slice.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/api/slice/from_slice.rs (97%) rename vendor/{packed_simd => packed_simd_2}/src/api/slice/write_to_slice.rs (92%) rename vendor/{packed_simd => packed_simd_2}/src/api/swap_bytes.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen.rs (91%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/bit_manip.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/llvm.rs (94%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float.rs (80%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/abs.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/cos.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/cos_pi.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/exp.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/ln.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/macros.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/mul_add.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/mul_adde.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/powf.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/sin.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/sin_cos_pi.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/sin_pi.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/sqrt.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/math/float/sqrte.rs (100%) create mode 100644 vendor/packed_simd_2/src/codegen/math/float/tanh.rs rename vendor/{packed_simd => packed_simd_2}/src/codegen/pointer_sized_int.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/aarch64.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/arm.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/fallback.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/fallback_impl.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/x86.rs (95%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/x86/avx.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/x86/avx2.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/x86/sse.rs (53%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/reductions/mask/x86/sse2.rs (100%) create mode 100644 vendor/packed_simd_2/src/codegen/shuffle.rs rename vendor/{packed_simd => packed_simd_2}/src/codegen/shuffle1_dyn.rs (91%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/swap_bytes.rs (92%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/v128.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/v16.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/v256.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/v32.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/v512.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/v64.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/vPtr.rs (89%) rename vendor/{packed_simd => packed_simd_2}/src/codegen/vSize.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/lib.rs (93%) rename vendor/{packed_simd => packed_simd_2}/src/masks.rs (96%) rename vendor/{packed_simd => packed_simd_2}/src/sealed.rs (77%) rename vendor/{packed_simd => packed_simd_2}/src/testing.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/testing/macros.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/testing/utils.rs (86%) rename vendor/{packed_simd => packed_simd_2}/src/v128.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/v16.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/v256.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/v32.rs (100%) rename vendor/{packed_simd => packed_simd_2}/src/v512.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/v64.rs (99%) rename vendor/{packed_simd => packed_simd_2}/src/vPtr.rs (98%) rename vendor/{packed_simd => packed_simd_2}/src/vSize.rs (97%) rename vendor/{packed_simd => packed_simd_2}/tests/endianness.rs (85%) create mode 100644 vendor/rand/.cargo-checksum.json create mode 100644 vendor/rand/CHANGELOG.md create mode 100644 vendor/rand/COPYRIGHT create mode 100644 vendor/rand/Cargo.toml rename vendor/{socket2 => rand}/LICENSE-APACHE (99%) create mode 100644 vendor/rand/LICENSE-MIT create mode 100644 vendor/rand/README.md create mode 100644 vendor/rand/src/distributions/bernoulli.rs create mode 100644 vendor/rand/src/distributions/float.rs create mode 100644 vendor/rand/src/distributions/integer.rs create mode 100644 vendor/rand/src/distributions/mod.rs create mode 100644 vendor/rand/src/distributions/other.rs create mode 100644 vendor/rand/src/distributions/uniform.rs create mode 100644 vendor/rand/src/distributions/utils.rs create mode 100644 vendor/rand/src/distributions/weighted.rs create mode 100644 vendor/rand/src/distributions/weighted_index.rs create mode 100644 vendor/rand/src/lib.rs create mode 100644 vendor/rand/src/prelude.rs create mode 100644 vendor/rand/src/rng.rs create mode 100644 vendor/rand/src/rngs/adapter/mod.rs create mode 100644 vendor/rand/src/rngs/adapter/read.rs create mode 100644 vendor/rand/src/rngs/adapter/reseeding.rs create mode 100644 vendor/rand/src/rngs/mock.rs create mode 100644 vendor/rand/src/rngs/mod.rs create mode 100644 vendor/rand/src/rngs/small.rs create mode 100644 vendor/rand/src/rngs/std.rs create mode 100644 vendor/rand/src/rngs/thread.rs create mode 100644 vendor/rand/src/rngs/xoshiro128plusplus.rs create mode 100644 vendor/rand/src/rngs/xoshiro256plusplus.rs create mode 100644 vendor/rand/src/seq/index.rs create mode 100644 vendor/rand/src/seq/mod.rs create mode 100644 vendor/rand_chacha/.cargo-checksum.json create mode 100644 vendor/rand_chacha/CHANGELOG.md create mode 100644 vendor/rand_chacha/COPYRIGHT create mode 100644 vendor/rand_chacha/Cargo.toml create mode 100644 vendor/rand_chacha/LICENSE-APACHE create mode 100644 vendor/rand_chacha/LICENSE-MIT create mode 100644 vendor/rand_chacha/README.md create mode 100644 vendor/rand_chacha/src/chacha.rs create mode 100644 vendor/rand_chacha/src/guts.rs create mode 100644 vendor/rand_chacha/src/lib.rs create mode 100644 vendor/rand_core/.cargo-checksum.json create mode 100644 vendor/rand_core/CHANGELOG.md create mode 100644 vendor/rand_core/COPYRIGHT create mode 100644 vendor/rand_core/Cargo.toml create mode 100644 vendor/rand_core/LICENSE-APACHE create mode 100644 vendor/rand_core/LICENSE-MIT create mode 100644 vendor/rand_core/README.md create mode 100644 vendor/rand_core/src/block.rs create mode 100644 vendor/rand_core/src/error.rs create mode 100644 vendor/rand_core/src/impls.rs create mode 100644 vendor/rand_core/src/le.rs create mode 100644 vendor/rand_core/src/lib.rs create mode 100644 vendor/rand_core/src/os.rs create mode 100644 vendor/rand_hc/.cargo-checksum.json create mode 100644 vendor/rand_hc/CHANGELOG.md create mode 100644 vendor/rand_hc/COPYRIGHT rename vendor/{rustc-ap-rustc_graphviz => rand_hc}/Cargo.toml (54%) create mode 100644 vendor/rand_hc/LICENSE-APACHE create mode 100644 vendor/rand_hc/LICENSE-MIT create mode 100644 vendor/rand_hc/README.md create mode 100644 vendor/rand_hc/src/hc128.rs create mode 100644 vendor/rand_hc/src/lib.rs delete mode 100644 vendor/redox_users-0.3.4/.cargo-checksum.json delete mode 100644 vendor/redox_users-0.3.4/Cargo.toml delete mode 100644 vendor/redox_users-0.3.4/LICENSE delete mode 100644 vendor/redox_users-0.3.4/README.md delete mode 100644 vendor/redox_users-0.3.4/src/lib.rs delete mode 100644 vendor/redox_users-0.3.4/tests/etc/group delete mode 100644 vendor/redox_users-0.3.4/tests/etc/passwd delete mode 100644 vendor/redox_users-0.3.4/tests/etc/shadow delete mode 100644 vendor/regex/src/cache.rs create mode 100644 vendor/regex/src/pool.rs delete mode 100644 vendor/rust-argon2/.cargo-checksum.json delete mode 100644 vendor/rust-argon2/CHANGELOG.md delete mode 100644 vendor/rust-argon2/Cargo.toml delete mode 100644 vendor/rust-argon2/LICENSE-MIT delete mode 100644 vendor/rust-argon2/README.md delete mode 100644 vendor/rust-argon2/src/argon2.rs delete mode 100644 vendor/rust-argon2/src/block.rs delete mode 100644 vendor/rust-argon2/src/common.rs delete mode 100644 vendor/rust-argon2/src/config.rs delete mode 100644 vendor/rust-argon2/src/context.rs delete mode 100644 vendor/rust-argon2/src/core.rs delete mode 100644 vendor/rust-argon2/src/decoded.rs delete mode 100644 vendor/rust-argon2/src/encoding.rs delete mode 100644 vendor/rust-argon2/src/error.rs delete mode 100644 vendor/rust-argon2/src/lib.rs delete mode 100644 vendor/rust-argon2/src/memory.rs delete mode 100644 vendor/rust-argon2/src/result.rs delete mode 100644 vendor/rust-argon2/src/thread_mode.rs delete mode 100644 vendor/rust-argon2/src/variant.rs delete mode 100644 vendor/rust-argon2/src/version.rs delete mode 100644 vendor/rust-argon2/tests/integration_test.rs delete mode 100644 vendor/rustc-ap-rustc_arena/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_arena/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_arena/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_arena/src/tests.rs delete mode 100644 vendor/rustc-ap-rustc_ast/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_ast/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_ast/README.md delete mode 100644 vendor/rustc-ap-rustc_ast/src/ast.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/ast/tests.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/attr/mod.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/crate_disambiguator.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/entry.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/expand/allocator.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/expand/mod.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/mut_visit.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/node_id.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/ptr.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/token.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/tokenstream.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/util/classify.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/util/comments.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/util/comments/tests.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/util/literal.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/util/parser.rs delete mode 100644 vendor/rustc-ap-rustc_ast/src/visit.rs delete mode 100644 vendor/rustc-ap-rustc_ast_passes/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_ast_passes/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_ast_passes/src/ast_validation.rs delete mode 100644 vendor/rustc-ap-rustc_ast_passes/src/feature_gate.rs delete mode 100644 vendor/rustc-ap-rustc_ast_passes/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_ast_passes/src/node_count.rs delete mode 100644 vendor/rustc-ap-rustc_ast_passes/src/show_span.rs delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/src/helpers.rs delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/src/pp.rs delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/src/pprust/mod.rs delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/src/pprust/state.rs delete mode 100644 vendor/rustc-ap-rustc_ast_pretty/src/pprust/tests.rs delete mode 100644 vendor/rustc-ap-rustc_attr/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_attr/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_attr/src/builtin.rs delete mode 100644 vendor/rustc-ap-rustc_attr/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_data_structures/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/atomic_ref.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/base_n.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/base_n/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/binary_search_util/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/binary_search_util/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/box_region.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/captures.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/const_cstr.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/fingerprint.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/flock.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/frozen.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/functor.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/fx.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/dominators/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/dominators/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/implementation/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/implementation/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/iterate/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/iterate/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/reference.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/scc/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/scc/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/jobserver.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/macros.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/map_in_place.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/obligation_forest/graphviz.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/obligation_forest/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/obligation_forest/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/owning_ref/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/owning_ref/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/profiling.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/ptr_key.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sharded.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sip128.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sip128/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/small_c_str.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/small_c_str/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/snapshot_map/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/snapshot_map/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sorted_map.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sorted_map/index_map.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sorted_map/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sso/either_iter.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sso/map.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sso/mod.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sso/set.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/stable_hasher.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/stable_hasher/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/stable_map.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/stable_set.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/stack.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/steal.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/svh.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/sync.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/tagged_ptr.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/copy.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/drop.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/temp_dir.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/thin_vec.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/tiny_list.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/tiny_list/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/transitive_relation.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/transitive_relation/tests.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/unhash.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/vec_linked_list.rs delete mode 100644 vendor/rustc-ap-rustc_data_structures/src/work_queue.rs delete mode 100644 vendor/rustc-ap-rustc_errors/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_errors/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_errors/src/annotate_snippet_emitter_writer.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/diagnostic.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/diagnostic_builder.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/emitter.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/json.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/json/tests.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/lock.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/registry.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/snippet.rs delete mode 100644 vendor/rustc-ap-rustc_errors/src/styled_buffer.rs delete mode 100644 vendor/rustc-ap-rustc_expand/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_expand/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_expand/src/base.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/build.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/config.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/expand.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/mbe.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/mbe/macro_check.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/mbe/macro_parser.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/mbe/macro_rules.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/mbe/quoted.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/mbe/transcribe.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/module.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/mut_visit/tests.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/parse/tests.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/placeholders.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/proc_macro.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/proc_macro_server.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/tests.rs delete mode 100644 vendor/rustc-ap-rustc_expand/src/tokenstream/tests.rs delete mode 100644 vendor/rustc-ap-rustc_feature/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_feature/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_feature/src/accepted.rs delete mode 100644 vendor/rustc-ap-rustc_feature/src/active.rs delete mode 100644 vendor/rustc-ap-rustc_feature/src/builtin_attrs.rs delete mode 100644 vendor/rustc-ap-rustc_feature/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_feature/src/removed.rs delete mode 100644 vendor/rustc-ap-rustc_feature/src/tests.rs delete mode 100644 vendor/rustc-ap-rustc_fs_util/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_fs_util/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_fs_util/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_graphviz/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_graphviz/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_graphviz/src/tests.rs delete mode 100644 vendor/rustc-ap-rustc_index/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_index/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_index/src/bit_set.rs delete mode 100644 vendor/rustc-ap-rustc_index/src/bit_set/tests.rs delete mode 100644 vendor/rustc-ap-rustc_index/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_index/src/vec.rs delete mode 100644 vendor/rustc-ap-rustc_index/src/vec/tests.rs delete mode 100644 vendor/rustc-ap-rustc_lexer-705.0.0/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_lexer-705.0.0/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_lexer-705.0.0/src/cursor.rs delete mode 100644 vendor/rustc-ap-rustc_lexer-705.0.0/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_lexer-705.0.0/src/tests.rs delete mode 100644 vendor/rustc-ap-rustc_lexer-705.0.0/src/unescape.rs delete mode 100644 vendor/rustc-ap-rustc_lexer-705.0.0/src/unescape/tests.rs delete mode 100644 vendor/rustc-ap-rustc_lint_defs/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_lint_defs/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_lint_defs/src/builtin.rs delete mode 100644 vendor/rustc-ap-rustc_lint_defs/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_macros/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_macros/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_macros/src/hash_stable.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/lift.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/query.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/serialize.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/session_diagnostic.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/symbols.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/symbols/tests.rs delete mode 100644 vendor/rustc-ap-rustc_macros/src/type_foldable.rs delete mode 100644 vendor/rustc-ap-rustc_parse/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_parse/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_parse/src/lexer/mod.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/lexer/tokentrees.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/lexer/unescape_error_reporting.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/lexer/unicode_chars.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/attr.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/diagnostics.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/expr.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/generics.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/item.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/mod.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/nonterminal.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/pat.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/path.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/stmt.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/parser/ty.rs delete mode 100644 vendor/rustc-ap-rustc_parse/src/validate_attr.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_serialize/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_serialize/src/collection_impls.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/src/json.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/src/json/tests.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/src/leb128.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/src/opaque.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/src/serialize.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/tests/json.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/tests/leb128.rs delete mode 100644 vendor/rustc-ap-rustc_serialize/tests/opaque.rs delete mode 100644 vendor/rustc-ap-rustc_session/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_session/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_session/src/cgu_reuse_tracker.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/code_stats.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/config.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/filesearch.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/options.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/output.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/parse.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/search_paths.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/session.rs delete mode 100644 vendor/rustc-ap-rustc_session/src/utils.rs delete mode 100644 vendor/rustc-ap-rustc_span/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_span/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_span/src/analyze_source_file.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/analyze_source_file/tests.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/caching_source_map_view.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/def_id.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/edition.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/fatal_error.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/hygiene.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/lev_distance.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/lev_distance/tests.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/source_map.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/source_map/tests.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/span_encoding.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/symbol.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/symbol/tests.rs delete mode 100644 vendor/rustc-ap-rustc_span/src/tests.rs delete mode 100644 vendor/rustc-ap-rustc_target/.cargo-checksum.json delete mode 100644 vendor/rustc-ap-rustc_target/Cargo.toml delete mode 100644 vendor/rustc-ap-rustc_target/README.md delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/aarch64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/amdgpu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/arm.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/avr.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/hexagon.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/mips.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/mips64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/mod.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/msp430.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/nvptx.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/nvptx64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/powerpc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/powerpc64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/riscv.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/s390x.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/sparc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/sparc64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/wasm32.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/wasm32_bindgen_compat.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/x86.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/x86_64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/call/x86_win64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/abi/mod.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/aarch64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/arm.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/hexagon.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/mips.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/mod.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/nvptx.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/riscv.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/spirv.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/wasm.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/asm/x86.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/lib.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_apple_darwin.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_apple_ios.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_apple_ios_macabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_apple_tvos.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_fuchsia.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_linux_android.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_pc_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_freebsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_hermit.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_netbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_none.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_none_softfloat.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_openbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_unknown_redox.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_uwp_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/aarch64_wrs_vxworks.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/abi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/abi/tests.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/android_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/apple_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/apple_sdk_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/arm_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/arm_linux_androideabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/arm_unknown_linux_gnueabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/arm_unknown_linux_musleabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/arm_unknown_linux_musleabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armebv7r_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armebv7r_none_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv6_unknown_freebsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_apple_ios.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_linux_androideabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_unknown_freebsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_unknown_linux_musleabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7a_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7a_none_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7r_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7r_none_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/armv7s_apple_ios.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/asmjs_unknown_emscripten.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/avr_gnu_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/avr_unknown_gnu_atmega328.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/crt_objects.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/dragonfly_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/freebsd_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/fuchsia_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/haiku_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/hermit_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/hermit_kernel_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/hexagon_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i386_apple_ios.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i386_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i486_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i586_pc_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i586_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i586_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_apple_darwin.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_linux_android.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_pc_windows_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_pc_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_unknown_freebsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_unknown_haiku.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_unknown_netbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_unknown_openbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_unknown_uefi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_uwp_windows_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_uwp_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/i686_wrs_vxworks.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/illumos_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/l4re_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/linux_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/linux_gnu_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/linux_kernel_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/linux_musl_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/linux_uclibc_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mips_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mips_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mips_unknown_linux_uclibc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsel_sony_psp.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsel_sony_psp_linker_script.ld delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsel_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsel_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsel_unknown_none.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/mod.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/msp430_none_elf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/msvc_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/netbsd_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/nvptx64_nvidia_cuda.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/openbsd_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc64_unknown_freebsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc64_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc64_wrs_vxworks.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc_unknown_netbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc_wrs_vxworks.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/redox_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv32i_unknown_none_elf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv32imac_unknown_none_elf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv32imc_unknown_none_elf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv64gc_unknown_none_elf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv64imac_unknown_none_elf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/riscv_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/s390x_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/solaris_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/sparc64_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/sparc64_unknown_netbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/sparc64_unknown_openbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/sparc_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/sparcv9_sun_solaris.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/tests/tests_impl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumb_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv4t_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv6m_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7em_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7em_none_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7m_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7neon_linux_androideabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv8m_base_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv8m_main_none_eabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/thumbv8m_main_none_eabihf.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/uefi_msvc_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/vxworks_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/wasm32_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/wasm32_unknown_emscripten.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/wasm32_unknown_unknown.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/wasm32_wasi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/windows_gnu_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/windows_msvc_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/windows_uwp_gnu_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/windows_uwp_msvc_base.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_apple_darwin.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_apple_ios.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_apple_ios_macabi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_apple_tvos.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_fuchsia.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_linux_android.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_linux_kernel.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_pc_windows_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_pc_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_rumprun_netbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_sun_solaris.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_dragonfly.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_freebsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_haiku.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_hermit.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_hermit_kernel.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_illumos.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_linux_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_linux_musl.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_netbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_openbsd.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_redox.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_unknown_uefi.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_uwp_windows_gnu.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_uwp_windows_msvc.rs delete mode 100644 vendor/rustc-ap-rustc_target/src/spec/x86_64_wrs_vxworks.rs create mode 100644 vendor/shell-escape/.cargo-checksum.json rename vendor/{arrayref => shell-escape}/Cargo.toml (62%) rename vendor/{rust-argon2 => shell-escape}/LICENSE-APACHE (100%) create mode 100644 vendor/shell-escape/LICENSE-MIT create mode 100644 vendor/shell-escape/README.md create mode 100644 vendor/shell-escape/src/lib.rs delete mode 100644 vendor/socket2/.cargo-checksum.json delete mode 100644 vendor/socket2/Cargo.toml delete mode 100644 vendor/socket2/README.md delete mode 100644 vendor/socket2/SO_ACCEPTCONN.patch delete mode 100644 vendor/socket2/TODO delete mode 100755 vendor/socket2/check_targets.bash delete mode 100644 vendor/socket2/diff.patch delete mode 100644 vendor/socket2/src/lib.rs delete mode 100644 vendor/socket2/src/sockaddr.rs delete mode 100644 vendor/socket2/src/socket.rs delete mode 100644 vendor/socket2/src/sys/unix.rs delete mode 100644 vendor/socket2/src/sys/windows.rs delete mode 100644 vendor/socket2/src/tests.rs delete mode 100644 vendor/socket2/src/utils.rs create mode 100644 vendor/yansi-term/.cargo-checksum.json create mode 100644 vendor/yansi-term/Cargo.lock create mode 100644 vendor/yansi-term/Cargo.toml rename vendor/{rustc-ap-rustc_data_structures/src/owning_ref/LICENSE => yansi-term/LICENCE} (96%) create mode 100644 vendor/yansi-term/README.md create mode 100644 vendor/yansi-term/examples/256_colours.rs create mode 100644 vendor/yansi-term/examples/basic_colours.rs create mode 100644 vendor/yansi-term/examples/overwrite.rs create mode 100644 vendor/yansi-term/examples/rgb_colours.rs create mode 100644 vendor/yansi-term/src/ansi.rs create mode 100644 vendor/yansi-term/src/display.rs create mode 100644 vendor/yansi-term/src/lib.rs create mode 100644 vendor/yansi-term/src/style.rs create mode 100644 vendor/yansi-term/src/windows.rs diff --git a/Cargo.lock b/Cargo.lock index e5a7b7d9b6..0939f19cdf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "addr2line" version = "0.14.0" @@ -56,20 +58,14 @@ dependencies = [ "url 2.1.1", ] -[[package]] -name = "annotate-snippets" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" -dependencies = [ - "ansi_term 0.11.0", -] - [[package]] name = "annotate-snippets" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" +dependencies = [ + "yansi-term", +] [[package]] name = "ansi_term" @@ -101,17 +97,11 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - [[package]] name = "arrayvec" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7" [[package]] name = "atty" @@ -130,12 +120,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "bitflags" version = "1.2.1" @@ -151,17 +135,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "blake2b_simd" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.7.3" @@ -252,11 +225,11 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecount" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e" +checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" dependencies = [ - "packed_simd", + "packed_simd_2", ] [[package]] @@ -279,7 +252,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" [[package]] name = "cargo" -version = "0.53.0" +version = "0.54.0" dependencies = [ "anyhow", "atty", @@ -287,11 +260,10 @@ dependencies = [ "cargo-platform", "cargo-test-macro", "cargo-test-support", + "cargo-util", "clap", - "core-foundation", "crates-io", - "crossbeam-utils 0.8.0", - "crypto-hash", + "crossbeam-utils 0.8.3", "curl", "curl-sys", "env_logger 0.8.1", @@ -313,7 +285,6 @@ dependencies = [ "libgit2-sys", "log", "memchr", - "miow 0.3.6", "num_cpus", "opener", "openssl", @@ -322,7 +293,6 @@ dependencies = [ "rand 0.8.3", "rustc-workspace-hack", "rustfix", - "same-file", "semver 0.10.0", "serde", "serde_ignored", @@ -396,8 +366,9 @@ version = "0.1.0" name = "cargo-test-support" version = "0.1.0" dependencies = [ - "cargo", + "anyhow", "cargo-test-macro", + "cargo-util", "filetime", "flate2", "git2", @@ -410,6 +381,26 @@ dependencies = [ "url 2.1.1", ] +[[package]] +name = "cargo-util" +version = "0.1.0" +dependencies = [ + "anyhow", + "core-foundation", + "crypto-hash", + "filetime", + "hex 0.4.2", + "jobserver", + "libc", + "log", + "miow 0.3.6", + "same-file", + "shell-escape", + "tempfile", + "walkdir", + "winapi 0.3.9", +] + [[package]] name = "cargo_metadata" version = "0.8.2" @@ -557,29 +548,44 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.52" +version = "0.1.53" dependencies = [ "cargo_metadata 0.12.0", "clippy-mini-macro-test", "clippy_lints", - "compiletest_rs 0.6.0", + "compiletest_rs", "derive-new", + "quote", "regex", "rustc-workspace-hack", "rustc_tools_util 0.2.0", "semver 0.11.0", "serde", + "syn", "tempfile", - "tester 0.9.0", + "tester", ] [[package]] name = "clippy-mini-macro-test" version = "0.2.0" +[[package]] +name = "clippy_dev" +version = "0.0.1" +dependencies = [ + "bytecount", + "clap", + "itertools 0.9.0", + "opener", + "regex", + "shell-escape", + "walkdir", +] + [[package]] name = "clippy_lints" -version = "0.1.52" +version = "0.1.53" dependencies = [ "cargo_metadata 0.12.0", "clippy_utils", @@ -587,13 +593,10 @@ dependencies = [ "itertools 0.9.0", "pulldown-cmark 0.8.0", "quine-mc_cluskey", - "quote", "regex-syntax", "rustc-semver", "semver 0.11.0", "serde", - "smallvec 1.6.1", - "syn", "toml", "unicode-normalization", "url 2.1.1", @@ -601,27 +604,16 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.52" +version = "0.1.53" dependencies = [ "if_chain", "itertools 0.9.0", "regex-syntax", "rustc-semver", "serde", - "smallvec 1.6.1", - "toml", "unicode-normalization", ] -[[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags", -] - [[package]] name = "cmake" version = "0.1.44" @@ -692,28 +684,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "compiletest_rs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f737835bfbbe29ed1ff82d5137520338d7ed5bf1a1d4b9c1c7c58bb45b8fa29" -dependencies = [ - "diff", - "filetime", - "getopts", - "libc", - "log", - "miow 0.3.6", - "regex", - "rustfix", - "serde", - "serde_derive", - "serde_json", - "tempfile", - "tester 0.7.0", - "winapi 0.3.9", -] - [[package]] name = "compiletest_rs" version = "0.6.0" @@ -733,22 +703,10 @@ dependencies = [ "serde_derive", "serde_json", "tempfile", - "tester 0.9.0", + "tester", "winapi 0.3.9", ] -[[package]] -name = "const_fn" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "core" version = "0.0.0" @@ -810,7 +768,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.3", ] [[package]] @@ -863,13 +821,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", "cfg-if 1.0.0", - "const_fn", "lazy_static", ] @@ -996,9 +953,9 @@ dependencies = [ [[package]] name = "directories" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fed639d60b58d0f53498ab13d26f621fd77569cc6edb031f4cc36a2ad9da0f" +checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" dependencies = [ "dirs-sys", ] @@ -1025,12 +982,12 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", - "redox_users 0.3.4", + "redox_users", "winapi 0.3.9", ] @@ -1041,7 +998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users 0.4.0", + "redox_users", "winapi 0.3.9", ] @@ -1086,6 +1043,26 @@ dependencies = [ "log", ] +[[package]] +name = "enum-iterator" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.6.2" @@ -1219,6 +1196,12 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "fs-err" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcd1163ae48bda72a20ae26d66a04d3094135cadab911cff418ae5e33f253431" + [[package]] name = "fs_extra" version = "1.1.0" @@ -1227,12 +1210,9 @@ checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" [[package]] name = "fst" -version = "0.3.5" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927fb434ff9f0115b215dc0efd2e4fbdd7448522a92a1aa37c77d6a2f8f1ebd6" -dependencies = [ - "byteorder", -] +checksum = "d79238883cf0307100b90aba4a755d8051a3182305dfe7f649a1e9dc0517006f" [[package]] name = "fuchsia-zircon" @@ -1425,6 +1405,18 @@ dependencies = [ "wasi", ] +[[package]] +name = "getset" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "gimli" version = "0.23.0" @@ -1622,11 +1614,11 @@ checksum = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d" [[package]] name = "ignore" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22dcbf2a4a289528dbef21686354904e1c694ac642610a9bff9e7df730d9ec72" +checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c" dependencies = [ - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "globset", "lazy_static", "log", @@ -1718,36 +1710,26 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" -[[package]] -name = "jemalloc-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45" -dependencies = [ - "cc", - "fs_extra", - "libc", -] - [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" dependencies = [ "libc", ] [[package]] name = "json" -version = "0.11.15" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c245af8786f6ac35f95ca14feca9119e71339aaab41e878e7cdd655c97e9e5" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" [[package]] name = "jsondocck" version = "0.1.0" dependencies = [ + "fs-err", "getopts", "jsonpath_lib", "lazy_static", @@ -1895,9 +1877,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" dependencies = [ "rustc-std-workspace-core", ] @@ -1916,6 +1898,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + [[package]] name = "libnghttp2-sys" version = "0.1.4+1.41.0" @@ -2145,7 +2133,7 @@ dependencies = [ "parking_lot", "perf-event-open-sys", "rustc-hash", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -2294,17 +2282,17 @@ name = "miri" version = "0.1.0" dependencies = [ "colored", - "compiletest_rs 0.5.0", - "env_logger 0.7.1", + "compiletest_rs", + "env_logger 0.8.1", "getrandom 0.2.0", "hex 0.4.2", "libc", "log", - "rand 0.7.3", + "rand 0.8.3", "rustc-workspace-hack", "rustc_version", "shell-escape", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -2459,18 +2447,20 @@ dependencies = [ ] [[package]] -name = "packed_simd" -version = "0.3.3" +name = "packed_simd_2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" +checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17" dependencies = [ "cfg-if 0.1.10", + "libm", ] [[package]] name = "panic_abort" version = "0.0.0" dependencies = [ + "alloc", "cfg-if 0.1.10", "compiler_builtins", "core", @@ -2507,9 +2497,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", "lock_api", @@ -2518,16 +2508,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", + "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.1.57", - "smallvec 1.6.1", + "redox_syscall 0.2.5", + "smallvec", "winapi 0.3.9", ] @@ -2765,9 +2754,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid", ] @@ -2855,9 +2844,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.44" +version = "2.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7972a124e2b24dce35eb19f81eced829faec0e8227a7d744bbb1089934d05399" +checksum = "e7cbda48a9124ed2e83766d2c15e3725710d344abca35fad8cf52341a55883b1" dependencies = [ "bitflags", "clap", @@ -3025,17 +3014,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_users" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" -dependencies = [ - "getrandom 0.1.14", - "redox_syscall 0.1.57", - "rust-argon2", -] - [[package]] name = "redox_users" version = "0.4.0" @@ -3097,6 +3075,7 @@ version = "1.41.0" dependencies = [ "anyhow", "cargo", + "cargo-util", "cargo_metadata 0.8.2", "clippy_lints", "crossbeam-channel", @@ -3105,7 +3084,7 @@ dependencies = [ "futures 0.3.12", "heck", "home", - "itertools 0.8.2", + "itertools 0.9.0", "jsonrpc-core", "lazy_static", "log", @@ -3140,14 +3119,14 @@ dependencies = [ [[package]] name = "rls-analysis" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534032993e1b60e5db934eab2dde54da7afd1e46c3465fddb2b29eb47cb1ed3a" +version = "0.18.2" dependencies = [ "derive-new", + "env_logger 0.7.1", "fst", - "itertools 0.8.2", + "itertools 0.9.0", "json", + "lazy_static", "log", "rls-data", "rls-span", @@ -3211,18 +3190,6 @@ dependencies = [ "rls-span", ] -[[package]] -name = "rust-argon2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" -dependencies = [ - "base64", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils 0.7.2", -] - [[package]] name = "rust-demangler" version = "0.0.1" @@ -3242,18 +3209,19 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93575affa286089b92c8208aea4e60fe9fdd251a619a09b566d6e4e2cc123212" +checksum = "526610f47139efa440178239553b59ea805ff57a532b4e295c71d2a9b18fd676" dependencies = [ - "smallvec 1.6.1", + "rustc-ap-rustc_data_structures", + "smallvec", ] [[package]] name = "rustc-ap-rustc_ast" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c700f2d3b25aa8d6446dd2936048737b08b2d547bd86e2a70afa9fee4e9c522" +checksum = "cf6a9dda0804a7243b0282e3b75a8cf4654c7a61f033e587751941e1fe39391b" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -3262,73 +3230,37 @@ dependencies = [ "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "smallvec 1.6.1", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_ast_passes" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e01f63e5259ee397bbe2e395d34a2e6b6b24f10c184d30fbbee1dcd7117f4f3" -dependencies = [ - "itertools 0.9.0", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", + "smallvec", "tracing", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d644c69c55deb24257cb0cb5261265fe5134f6f545e9062e1c18b07e422c68" +checksum = "82f5019be8b41a58664169fd2f4b1a37fe82705681db394b76419e4e87d40ab1" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", "tracing", ] -[[package]] -name = "rustc-ap-rustc_attr" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "797fc68816d5396870f04e03d35164f5275d2502403239d4caec7ce063683f41" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", -] - [[package]] name = "rustc-ap-rustc_data_structures" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d840c4e6198b57982a54543ae604d634c7ceb7107f0c75970b88ebaff077ac5" +checksum = "a701717fb14549331085756b9741ae3b4bf35808489f1887d72c1d0e0fe52b77" dependencies = [ "arrayvec", "bitflags", "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "ena", "indexmap", "jobserver", "libc", "measureme", + "memmap2", "parking_lot", "rustc-ap-rustc_graphviz", "rustc-ap-rustc_index", @@ -3337,7 +3269,7 @@ dependencies = [ "rustc-hash", "rustc-rayon", "rustc-rayon-core", - "smallvec 1.6.1", + "smallvec", "stable_deref_trait", "stacker", "tempfile", @@ -3347,11 +3279,11 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f2f99bdc828ad417636d9016611dc9047b641fadcb7f533b8b0e9616d81f90b" +checksum = "e3182ce85e8bfc96443475547f2f5aa2b5e67655d9b88721795f36f0ba9e265a" dependencies = [ - "annotate-snippets 0.8.0", + "annotate-snippets", "atty", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_lint_defs", @@ -3365,35 +3297,11 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rustc-ap-rustc_expand" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27008b4c7ded287bf5cb20b84d6d5a6566329140f2e2bc8f6e68b37a34898595" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_passes", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "smallvec 1.6.1", - "tracing", -] - [[package]] name = "rustc-ap-rustc_feature" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb47b53670f1263ed1389dda932d5b5a6daf98579c1f076c2ee7d7f22709b7c" +checksum = "eed033b93270126ef60963c3ebbd0e026bf53b985172b6366c7b0e7881c9d507" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -3401,21 +3309,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdaddc4bae5ffab17037553e172f5014686db600050429aaa60aec14fe780e84" +checksum = "28ee6531986a205101e09fd143d7bf31897388f33b1814d4bcc45fd62211dca6" [[package]] name = "rustc-ap-rustc_graphviz" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d73c72543311e88786f7380a3bfd946395579c1a0c0441a879a97fcdea79130" +checksum = "3398fddc0e23d2db89c036f8952ddf78cadc597f7059752116e69483e164a5b6" [[package]] name = "rustc-ap-rustc_index" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bba8d74ed4bad44a5b4264cf2a51ad0bd458ed56caa5bb090e989b8002ec6327" +checksum = "dca4e27eb5b701f6bbd47d8fc9d242378fca3e4107a519a28415c2989c4a3bd3" dependencies = [ "arrayvec", "rustc-ap-rustc_macros", @@ -3424,18 +3332,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a030d00510966cd31e13dca5e6c1bd40d303a932c54eca40e854188bca8c49e" +checksum = "786bbfe9d4d5264294c1819dbf1497a2480b583d5eda1ca9ae22e12d6661f5df" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_lint_defs" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff95da1b5d979183ef5c285817ba6cc67a1ac11296ef1e87b1b5bbaf57213c" +checksum = "be2f045e2b999c154ec505d5fea69c994b742f3ebd2f552d11a6c81723921e47" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_data_structures", @@ -3448,9 +3356,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3ed7401bf6f5a256d58cd0e1c1e2e77eec25e60a0d7ad75313962edcb4e396" +checksum = "27789cd26d6b9e2fdfa68a262a20664d79ca67d31a3886d40fb88ebf6935869c" dependencies = [ "proc-macro2", "quote", @@ -3460,9 +3368,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609a624baffa3f99847d57d30c96ee6732ce0912f8df4be239b6fd91533910d6" +checksum = "1dc331f4958350679679e619d63a891e8d5d34ef99087068c89aa9e657d52caa" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -3473,26 +3381,26 @@ dependencies = [ "rustc-ap-rustc_lexer", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", "unicode-normalization", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc232e2a351d8131c8f1386ce372ee22ef7b1b0b897bbf817a8ce4792029a564" +checksum = "e9a6824a462c4c1a379e911b0faf86d303a54bcf8673d4cc445195085966a4a4" dependencies = [ "indexmap", - "smallvec 1.6.1", + "smallvec", ] [[package]] name = "rustc-ap-rustc_session" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18acf94c820cd0c64ee1cbd811fd1f4d5ba18987c457c88771359b90cb1a12f5" +checksum = "a782a5f6ada0dbe089c6416ad0104f0b8a8bdb4bd26ea95e5fefaec67aed5e8a" dependencies = [ "bitflags", "getopts", @@ -3512,9 +3420,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3479f453a38b6a5572938d035fc2b3cb6ec379c57f598b8682b512eb90c7858" +checksum = "a257546cb264b250c7abdb81239bb02f18a274a966211755a3ea89411b122214" dependencies = [ "cfg-if 0.1.10", "md-5", @@ -3532,9 +3440,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "705.0.0" +version = "718.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cacaf829778cf07bb97a9f4604896789de12392175f3743e74a30ed370f1c1" +checksum = "b5a72dd689421bcb5750f3ed0dedf367076e714ef0ba56c02ed391b9a8582862" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -3565,9 +3473,10 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" name = "rustc-main" version = "0.0.0" dependencies = [ - "jemalloc-sys", "rustc_codegen_ssa", "rustc_driver", + "tikv-jemalloc-sys", + "tikv-jemallocator", ] [[package]] @@ -3626,15 +3535,15 @@ name = "rustc-workspace-hack" version = "1.0.0" dependencies = [ "byteorder", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "libc", "libz-sys", "proc-macro2", "quote", + "rand_core 0.5.1", "serde", "serde_json", - "smallvec 0.6.14", - "smallvec 1.6.1", + "smallvec", "syn", "url 2.1.1", "winapi 0.3.9", @@ -3645,7 +3554,7 @@ name = "rustc_apfloat" version = "0.0.0" dependencies = [ "bitflags", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -3653,7 +3562,7 @@ name = "rustc_arena" version = "0.0.0" dependencies = [ "rustc_data_structures", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -3667,7 +3576,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3685,7 +3594,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3748,7 +3657,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3777,7 +3686,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "snap", "tracing", ] @@ -3791,7 +3700,6 @@ dependencies = [ "itertools 0.9.0", "jobserver", "libc", - "memmap2", "pathdiff", "rustc_apfloat", "rustc_ast", @@ -3820,12 +3728,13 @@ dependencies = [ "arrayvec", "bitflags", "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.3", "ena", "indexmap", "jobserver", "libc", "measureme", + "memmap2", "parking_lot", "rustc-hash", "rustc-rayon", @@ -3834,7 +3743,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_serialize", - "smallvec 1.6.1", + "smallvec", "stable_deref_trait", "stacker", "tempfile", @@ -3885,7 +3794,7 @@ version = "0.0.0" name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets 0.8.0", + "annotate-snippets", "atty", "rustc_data_structures", "rustc_lint_defs", @@ -3917,7 +3826,7 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -3949,7 +3858,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4007,7 +3916,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4051,7 +3960,7 @@ dependencies = [ "rustc_traits", "rustc_ty_utils", "rustc_typeck", - "smallvec 1.6.1", + "smallvec", "tempfile", "tracing", "winapi 0.3.9", @@ -4125,7 +4034,6 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "libc", - "memmap2", "rustc_ast", "rustc_attr", "rustc_data_structures", @@ -4141,7 +4049,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "snap", "stable_deref_trait", "tracing", @@ -4173,7 +4081,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_type_ir", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4204,7 +4112,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4227,7 +4135,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4244,7 +4152,7 @@ dependencies = [ "rustc_lexer", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", "unicode-normalization", ] @@ -4345,7 +4253,7 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4369,7 +4277,7 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4398,7 +4306,7 @@ version = "0.0.0" dependencies = [ "indexmap", "rustc_macros", - "smallvec 1.6.1", + "smallvec", ] [[package]] @@ -4495,7 +4403,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4515,7 +4423,7 @@ dependencies = [ "rustc_middle", "rustc_span", "rustc_trait_selection", - "smallvec 1.6.1", + "smallvec", "tracing", ] @@ -4565,17 +4473,18 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "smallvec 1.6.1", + "rustc_ty_utils", + "smallvec", "tracing", ] [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver 0.9.0", + "semver 0.11.0", ] [[package]] @@ -4592,7 +4501,7 @@ dependencies = [ "rustdoc-json-types", "serde", "serde_json", - "smallvec 1.6.1", + "smallvec", "tempfile", "tracing", "tracing-subscriber", @@ -4642,9 +4551,9 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.36" +version = "1.4.37" dependencies = [ - "annotate-snippets 0.6.1", + "annotate-snippets", "anyhow", "bytecount", "cargo_metadata 0.8.2", @@ -4658,15 +4567,6 @@ dependencies = [ "lazy_static", "log", "regex", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_expand", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", @@ -4793,18 +4693,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.118" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.118" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" dependencies = [ "proc-macro2", "quote", @@ -4939,15 +4839,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -[[package]] -name = "smallvec" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] - [[package]] name = "smallvec" version = "1.6.1" @@ -5012,10 +4903,22 @@ dependencies = [ "profiler_builtins", "rand 0.7.3", "rustc-demangle", + "std_detect", "unwind", "wasi", ] +[[package]] +name = "std_detect" +version = "0.1.5" +dependencies = [ + "cfg-if 0.1.10", + "compiler_builtins", + "libc", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + [[package]] name = "string_cache" version = "0.8.0" @@ -5100,9 +5003,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.38" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" +checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" dependencies = [ "proc-macro2", "quote", @@ -5135,14 +5038,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "rand 0.7.3", - "redox_syscall 0.1.57", + "rand 0.8.3", + "redox_syscall 0.2.5", "remove_dir_all", "winapi 0.3.9", ] @@ -5221,17 +5124,6 @@ dependencies = [ "term 0.0.0", ] -[[package]] -name = "tester" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee72ec31009a42b53de9a6b7d8f462b493ab3b1e4767bda1fcdbb52127f13b6c" -dependencies = [ - "getopts", - "libc", - "term 0.6.1", -] - [[package]] name = "tester" version = "0.9.0" @@ -5288,6 +5180,7 @@ name = "tidy" version = "0.1.0" dependencies = [ "cargo_metadata 0.11.1", + "crossbeam-utils 0.8.3", "lazy_static", "regex", "walkdir", @@ -5297,6 +5190,27 @@ dependencies = [ name = "tier-check" version = "0.1.0" +[[package]] +name = "tikv-jemalloc-sys" +version = "0.4.1+5.2.1-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a26331b05179d4cb505c8d6814a7e18d298972f0a551b0e3cefccff927f86d3" +dependencies = [ + "cc", + "fs_extra", + "libc", +] + +[[package]] +name = "tikv-jemallocator" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c14a5a604eb8715bc5785018a37d00739b180bcf609916ddf4393d33d49ccdf" +dependencies = [ + "libc", + "tikv-jemalloc-sys", +] + [[package]] name = "time" version = "0.1.43" @@ -5444,7 +5358,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", - "smallvec 1.6.1", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -5644,12 +5558,17 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "3.1.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce50d8996df1f85af15f2cd8d33daae6e479575123ef4314a51a70a230739cb" +checksum = "dfbc87f9a7a9d61b15d51d1d3547284f67b6b4f1494ce3fc5814c101f35a5183" dependencies = [ - "bitflags", + "anyhow", "chrono", + "enum-iterator", + "getset", + "git2", + "rustversion", + "thiserror", ] [[package]] @@ -5797,3 +5716,12 @@ checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi 0.3.9", +] diff --git a/Cargo.toml b/Cargo.toml index f961d3e9b9..327afe35c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "src/rustdoc-json-types", "src/tools/cargotest", "src/tools/clippy", + "src/tools/clippy/clippy_dev", "src/tools/compiletest", "src/tools/error_index_generator", "src/tools/linkchecker", @@ -45,6 +46,8 @@ exclude = [ # not all `Cargo.toml` files are available, so we exclude the `x` binary, # so it can be invoked before the current checkout is set up. "src/tools/x", + # stdarch has its own Cargo workspace + "library/stdarch", ] [profile.release.package.compiler_builtins] @@ -88,6 +91,7 @@ object.debug = 0 # vendored copy. [patch."https://github.com/rust-lang/cargo"] cargo = { path = "src/tools/cargo" } +cargo-util = { path = "src/tools/cargo/crates/cargo-util" } [patch."https://github.com/rust-lang/rustfmt"] # Similar to Cargo above we want the RLS to use a vendored version of `rustfmt` diff --git a/RELEASES.md b/RELEASES.md index 02778204a4..28b0c5c458 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,205 @@ +Version 1.53.0 (2021-06-17) +============================ + +Language +----------------------- +- [You can now use unicode for identifiers.][83799] This allows multilingual + identifiers but still doesn't allow glyphs that are not considered characters + such as `◆` or `🦀`. More specifically you can now use any identifier that + matches the UAX #31 "Unicode Identifier and Pattern Syntax" standard. This + is the same standard as languages like Python, however Rust uses NFC + normalization which may be different from other languages. +- [You can now specify "or patterns" inside pattern matches.][79278] + Previously you could only use `|` (OR) on complete patterns. E.g. + ```rust + let x = Some(2u8); + // Before + matches!(x, Some(1) | Some(2)); + // Now + matches!(x, Some(1 | 2)); + ``` +- [Added the `:pat_param` `macro_rules!` matcher.][83386] This matcher + has the same semantics as the `:pat` matcher. This is to allow `:pat` + to change semantics to being a pattern fragment in a future edition. + +Compiler +----------------------- +- [Updated the minimum external LLVM version to LLVM 10.][83387] +- [Added Tier 3\* support for the `wasm64-unknown-unknown` target.][80525] +- [Improved debuginfo for closures and async functions on Windows MSVC.][83941] + +\* Refer to Rust's [platform support page][platform-support-doc] for more +information on Rust's tiered platform support. + +Libraries +----------------------- +- [Abort messages will now forward to `android_set_abort_message` on + Android platforms when available.][81469] +- [`slice::IterMut<'_, T>` now implements `AsRef<[T]>`][82771] +- [Arrays of any length now implement `IntoIterator`.][84147] + Currently calling `.into_iter()` as a method on an array will + return `impl Iterator`, but this may change in a + future edition to change `Item` to `T`. Calling `IntoIterator::into_iter` + directly on arrays will provide `impl Iterator` as expected. +- [`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] +- [You can now index into slices using `(Bound, Bound)`.][77704] +- [Add the `BITS` associated constant to all numeric types.][82565] + +Stabilised APIs +--------------- +- [`AtomicBool::fetch_update`] +- [`AtomicPtr::fetch_update`] +- [`BTreeMap::retain`] +- [`BTreeSet::retain`] +- [`BufReader::seek_relative`] +- [`DebugStruct::non_exhaustive`] +- [`Duration::MAX`] +- [`Duration::ZERO`] +- [`Duration::is_zero`] +- [`Duration::saturating_add`] +- [`Duration::saturating_mul`] +- [`Duration::saturating_sub`] +- [`ErrorKind::Unsupported`] +- [`Option::insert`] +- [`Ordering::is_eq`] +- [`Ordering::is_ge`] +- [`Ordering::is_gt`] +- [`Ordering::is_le`] +- [`Ordering::is_lt`] +- [`Ordering::is_ne`] +- [`OsStr::is_ascii`] +- [`OsStr::make_ascii_lowercase`] +- [`OsStr::make_ascii_uppercase`] +- [`OsStr::to_ascii_lowercase`] +- [`OsStr::to_ascii_uppercase`] +- [`Peekable::peek_mut`] +- [`Rc::decrement_strong_count`] +- [`Rc::increment_strong_count`] +- [`Vec::extend_from_within`] +- [`array::from_mut`] +- [`array::from_ref`] +- [`char::MAX`] +- [`char::REPLACEMENT_CHARACTER`] +- [`char::UNICODE_VERSION`] +- [`char::decode_utf16`] +- [`char::from_digit`] +- [`char::from_u32_unchecked`] +- [`char::from_u32`] +- [`cmp::max_by_key`] +- [`cmp::max_by`] +- [`cmp::min_by_key`] +- [`cmp::min_by`] +- [`f32::is_subnormal`] +- [`f64::is_subnormal`] + +Cargo +----------------------- +- [Cargo now supports git repositories where the default `HEAD` branch is not + "master".][cargo/9392] This also includes a switch to the version 3 `Cargo.lock` format + which can handle default branches correctly. +- [macOS targets now default to `unpacked` split-debuginfo.][cargo/9298] +- [The `authors` field is no longer included in `Cargo.toml` for new + projects.][cargo/9282] + +Rustdoc +----------------------- +- [Added the `rustdoc::bare_urls` lint that warns when you have URLs + without hyperlinks.][81764] + +Compatibility Notes +------------------- +- [Implement token-based handling of attributes during expansion][82608] +- [`Ipv4::from_str` will now reject octal format IP addresses in addition + to rejecting hexadecimal IP addresses.][83652] The octal format can lead + to confusion and potential security vulnerabilities and [is no + longer recommended][ietf6943]. + + +Internal Only +------------- +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of rustc and +related tools. + +- [Rework the `std::sys::windows::alloc` implementation.][83065] +- [rustdoc: Don't enter an infer_ctxt in get_blanket_impls for impls that aren't blanket impls.][82864] +- [rustdoc: Only look at blanket impls in `get_blanket_impls`][83681] +- [Rework rustdoc const type][82873] + +[83386]: https://github.com/rust-lang/rust/pull/83386 +[82771]: https://github.com/rust-lang/rust/pull/82771 +[84147]: https://github.com/rust-lang/rust/pull/84147 +[84082]: https://github.com/rust-lang/rust/pull/84082 +[83799]: https://github.com/rust-lang/rust/pull/83799 +[83681]: https://github.com/rust-lang/rust/pull/83681 +[83652]: https://github.com/rust-lang/rust/pull/83652 +[83387]: https://github.com/rust-lang/rust/pull/83387 +[82873]: https://github.com/rust-lang/rust/pull/82873 +[82864]: https://github.com/rust-lang/rust/pull/82864 +[82608]: https://github.com/rust-lang/rust/pull/82608 +[82565]: https://github.com/rust-lang/rust/pull/82565 +[80525]: https://github.com/rust-lang/rust/pull/80525 +[79278]: https://github.com/rust-lang/rust/pull/79278 +[78618]: https://github.com/rust-lang/rust/pull/78618 +[77704]: https://github.com/rust-lang/rust/pull/77704 +[83941]: https://github.com/rust-lang/rust/pull/83941 +[83065]: https://github.com/rust-lang/rust/pull/83065 +[81764]: https://github.com/rust-lang/rust/pull/81764 +[81469]: https://github.com/rust-lang/rust/pull/81469 +[cargo/9298]: https://github.com/rust-lang/cargo/pull/9298 +[cargo/9282]: https://github.com/rust-lang/cargo/pull/9282 +[cargo/9392]: https://github.com/rust-lang/cargo/pull/9392 +[`char::MAX`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.MAX +[`char::REPLACEMENT_CHARACTER`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.REPLACEMENT_CHARACTER +[`char::UNICODE_VERSION`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.UNICODE_VERSION +[`char::decode_utf16`]: https://doc.rust-lang.org/std/primitive.char.html#method.decode_utf16 +[`char::from_u32`]: https://doc.rust-lang.org/std/primitive.char.html#method.from_u32 +[`char::from_u32_unchecked`]: https://doc.rust-lang.org/std/primitive.char.html#method.from_u32_unchecked +[`char::from_digit`]: https://doc.rust-lang.org/std/primitive.char.html#method.from_digit +[`AtomicBool::fetch_update`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.fetch_update +[`AtomicPtr::fetch_update`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicPtr.html#method.fetch_update +[`BTreeMap::retain`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.retain +[`BTreeSet::retain`]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html#method.retain +[`BufReader::seek_relative`]: https://doc.rust-lang.org/std/io/struct.BufReader.html#method.seek_relative +[`DebugStruct::non_exhaustive`]: https://doc.rust-lang.org/std/fmt/struct.DebugStruct.html#method.finish_non_exhaustive +[`Duration::MAX`]: https://doc.rust-lang.org/std/time/struct.Duration.html#associatedconstant.MAX +[`Duration::ZERO`]: https://doc.rust-lang.org/std/time/struct.Duration.html#associatedconstant.ZERO +[`Duration::is_zero`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.is_zero +[`Duration::saturating_add`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.saturating_add +[`Duration::saturating_mul`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.saturating_mul +[`Duration::saturating_sub`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.saturating_sub +[`ErrorKind::Unsupported`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.Unsupported +[`Option::insert`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.insert +[`Ordering::is_eq`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_eq +[`Ordering::is_ge`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_ge +[`Ordering::is_gt`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_gt +[`Ordering::is_le`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_le +[`Ordering::is_lt`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_lt +[`Ordering::is_ne`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_ne +[`OsStr::eq_ignore_ascii_case`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.eq_ignore_ascii_case +[`OsStr::is_ascii`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.is_ascii +[`OsStr::make_ascii_lowercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.make_ascii_lowercase +[`OsStr::make_ascii_uppercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.make_ascii_uppercase +[`OsStr::to_ascii_lowercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_ascii_lowercase +[`OsStr::to_ascii_uppercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_ascii_uppercase +[`Peekable::peek_mut`]: https://doc.rust-lang.org/std/iter/struct.Peekable.html#method.peek_mut +[`Rc::decrement_strong_count`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.increment_strong_count +[`Rc::increment_strong_count`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.increment_strong_count +[`Vec::extend_from_within`]: https://doc.rust-lang.org/beta/std/vec/struct.Vec.html#method.extend_from_within +[`array::from_mut`]: https://doc.rust-lang.org/beta/std/array/fn.from_mut.html +[`array::from_ref`]: https://doc.rust-lang.org/beta/std/array/fn.from_ref.html +[`cmp::max_by_key`]: https://doc.rust-lang.org/beta/std/cmp/fn.max_by_key.html +[`cmp::max_by`]: https://doc.rust-lang.org/beta/std/cmp/fn.max_by.html +[`cmp::min_by_key`]: https://doc.rust-lang.org/beta/std/cmp/fn.min_by_key.html +[`cmp::min_by`]: https://doc.rust-lang.org/beta/std/cmp/fn.min_by.html +[`f32::is_subnormal`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_subnormal +[`f64::is_subnormal`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_subnormal +[ietf6943]: https://datatracker.ietf.org/doc/html/rfc6943#section-3.1.1 + + Version 1.52.1 (2021-05-10) ============================ @@ -79,7 +281,7 @@ The following previously stable APIs are now `const`. Rustdoc ------- - [Rustdoc lints are now treated as a tool lint, meaning that - lints are now prefixed with `rustdoc::` (e.g. `#[warn(rustdoc::non_autolinks)]`).][80527] + lints are now prefixed with `rustdoc::` (e.g. `#[warn(rustdoc::broken_intra_doc_links)]`).][80527] Using the old style is still allowed, and will become a warning in a future release. - [Rustdoc now supports argument files.][82261] diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 6e6c0c71a1..ca6055c46a 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -11,12 +11,16 @@ rustc_driver = { path = "../rustc_driver" } # crate is intended to be used by codegen backends, which may not be in-tree. rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } -[dependencies.jemalloc-sys] -version = '0.3.0' +[dependencies.tikv-jemalloc-sys] +version = '0.4.0' optional = true features = ['unprefixed_malloc_on_supported_platforms'] +[dependencies.tikv-jemallocator] +version = '0.4.0' +optional = true + [features] -jemalloc = ['jemalloc-sys'] +jemalloc = ['tikv-jemalloc-sys', 'tikv-jemallocator'] llvm = ['rustc_driver/llvm'] max_level_info = ['rustc_driver/max_level_info'] diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 859028957d..c80fab9949 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,3 +1,16 @@ +// Configure jemalloc as the `global_allocator` when configured. This is +// so that we use the sized deallocation apis jemalloc provides +// (namely `sdallocx`). +// +// The symbol overrides documented below are also performed so that we can +// ensure that we use a consistent allocator across the rustc <-> llvm boundary +#[cfg(feature = "jemalloc")] +#[global_allocator] +static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; + +#[cfg(feature = "tikv-jemalloc-sys")] +use tikv_jemalloc_sys as jemalloc_sys; + fn main() { // Pull in jemalloc when enabled. // @@ -7,7 +20,7 @@ fn main() { // dynamic libraries. That means to pull in jemalloc we actually need to // reference allocation symbols one way or another (as this file is the only // object code in the rustc executable). - #[cfg(feature = "jemalloc-sys")] + #[cfg(feature = "tikv-jemalloc-sys")] { use std::os::raw::{c_int, c_void}; diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs index 71bcb8f090..96277950cf 100644 --- a/compiler/rustc_apfloat/src/ieee.rs +++ b/compiler/rustc_apfloat/src/ieee.rs @@ -2273,6 +2273,7 @@ impl Loss { mod sig { use super::{limbs_for_bits, ExpInt, Limb, Loss, LIMB_BITS}; use core::cmp::Ordering; + use core::iter; use core::mem; pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool { @@ -2483,7 +2484,7 @@ mod sig { pub(super) fn add(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb { assert!(c <= 1); - for (a, &b) in a.iter_mut().zip(b) { + for (a, &b) in iter::zip(a, b) { let (r, overflow) = a.overflowing_add(b); let (r, overflow2) = r.overflowing_add(c); *a = r; @@ -2497,7 +2498,7 @@ mod sig { pub(super) fn sub(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb { assert!(c <= 1); - for (a, &b) in a.iter_mut().zip(b) { + for (a, &b) in iter::zip(a, b) { let (r, overflow) = a.overflowing_sub(b); let (r, overflow2) = r.overflowing_sub(c); *a = r; diff --git a/compiler/rustc_apfloat/src/lib.rs b/compiler/rustc_apfloat/src/lib.rs index 4a845fcb69..c648147d10 100644 --- a/compiler/rustc_apfloat/src/lib.rs +++ b/compiler/rustc_apfloat/src/lib.rs @@ -33,8 +33,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![no_std] #![forbid(unsafe_code)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #[macro_use] extern crate alloc; diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index c3198fb104..c3e4945c44 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -236,26 +236,6 @@ impl TypedArena { start_ptr } - /// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable - /// reference to it. Will panic if passed a zero-sized types. - /// - /// Panics: - /// - /// - Zero-sized types - /// - Zero-length slices - #[inline] - pub fn alloc_slice(&self, slice: &[T]) -> &mut [T] - where - T: Copy, - { - unsafe { - let len = slice.len(); - let start_ptr = self.alloc_raw_slice(len); - slice.as_ptr().copy_to_nonoverlapping(start_ptr, len); - slice::from_raw_parts_mut(start_ptr, len) - } - } - #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { assert!(mem::size_of::() != 0); diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7e82d7ff77..e7f19f06eb 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -100,6 +100,7 @@ pub struct Path { } impl PartialEq for Path { + #[inline] fn eq(&self, symbol: &Symbol) -> bool { self.segments.len() == 1 && { self.segments[0].ident.name == *symbol } } @@ -762,14 +763,6 @@ pub enum Mutability { } impl Mutability { - /// Returns `MutMutable` only if both `self` and `other` are mutable. - pub fn and(self, other: Self) -> Self { - match self { - Mutability::Mut => other, - Mutability::Not => Mutability::Not, - } - } - pub fn invert(self) -> Self { match self { Mutability::Mut => Mutability::Not, @@ -1353,7 +1346,7 @@ pub enum ExprKind { Field(P, Ident), /// An indexing operation (e.g., `foo[2]`). Index(P, P), - /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assingment). + /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assignment). Range(Option>, Option>, RangeLimits), /// An underscore, used in destructuring assignment to ignore a value. Underscore, @@ -1722,13 +1715,6 @@ impl FloatTy { FloatTy::F64 => sym::f64, } } - - pub fn bit_width(self) -> u64 { - match self { - FloatTy::F32 => 32, - FloatTy::F64 => 64, - } - } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -1764,29 +1750,6 @@ impl IntTy { IntTy::I128 => sym::i128, } } - - pub fn bit_width(&self) -> Option { - Some(match *self { - IntTy::Isize => return None, - IntTy::I8 => 8, - IntTy::I16 => 16, - IntTy::I32 => 32, - IntTy::I64 => 64, - IntTy::I128 => 128, - }) - } - - pub fn normalize(&self, target_width: u32) -> Self { - match self { - IntTy::Isize => match target_width { - 16 => IntTy::I16, - 32 => IntTy::I32, - 64 => IntTy::I64, - _ => unreachable!(), - }, - _ => *self, - } - } } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)] @@ -1822,29 +1785,6 @@ impl UintTy { UintTy::U128 => sym::u128, } } - - pub fn bit_width(&self) -> Option { - Some(match *self { - UintTy::Usize => return None, - UintTy::U8 => 8, - UintTy::U16 => 16, - UintTy::U32 => 32, - UintTy::U64 => 64, - UintTy::U128 => 128, - }) - } - - pub fn normalize(&self, target_width: u32) -> Self { - match self { - UintTy::Usize => match target_width { - 16 => UintTy::U16, - 32 => UintTy::U32, - 64 => UintTy::U64, - _ => unreachable!(), - }, - _ => *self, - } - } } /// A constraint on an associated type (e.g., `A = Bar` in `Foo` or @@ -2059,7 +1999,7 @@ pub enum InlineAsmOperand { out_expr: Option>, }, Const { - expr: P, + anon_const: AnonConst, }, Sym { expr: P, @@ -2215,9 +2155,6 @@ pub struct FnDecl { } impl FnDecl { - pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Param::to_self) - } pub fn has_self(&self) -> bool { self.inputs.get(0).map_or(false, Param::is_self) } diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs index 63bc7c49a9..945a44ab66 100644 --- a/compiler/rustc_ast/src/ast_like.rs +++ b/compiler/rustc_ast/src/ast_like.rs @@ -1,20 +1,32 @@ use super::ptr::P; +use super::token::Nonterminal; use super::tokenstream::LazyTokenStream; use super::{Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant}; -use super::{AssocItem, Expr, ForeignItem, Item, Local}; +use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt}; use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility}; use super::{AttrVec, Attribute, Stmt, StmtKind}; +use std::fmt::Debug; + /// An `AstLike` represents an AST node (or some wrapper around /// and AST node) which stores some combination of attributes /// and tokens. -pub trait AstLike: Sized { +pub trait AstLike: Sized + Debug { + /// This is `true` if this `AstLike` might support 'custom' (proc-macro) inner + /// attributes. Attributes like `#![cfg]` and `#![cfg_attr]` are not + /// considered 'custom' attributes + /// + /// If this is `false`, then this `AstLike` definitely does + /// not support 'custom' inner attributes, which enables some optimizations + /// during token collection. + const SUPPORTS_CUSTOM_INNER_ATTRS: bool; fn attrs(&self) -> &[Attribute]; fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)); fn tokens_mut(&mut self) -> Option<&mut Option>; } impl AstLike for P { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS; fn attrs(&self) -> &[Attribute] { (**self).attrs() } @@ -26,6 +38,55 @@ impl AstLike for P { } } +impl AstLike for crate::token::Nonterminal { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; + fn attrs(&self) -> &[Attribute] { + match self { + Nonterminal::NtItem(item) => item.attrs(), + Nonterminal::NtStmt(stmt) => stmt.attrs(), + Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.attrs(), + Nonterminal::NtPat(_) + | Nonterminal::NtTy(_) + | Nonterminal::NtMeta(_) + | Nonterminal::NtPath(_) + | Nonterminal::NtVis(_) + | Nonterminal::NtTT(_) + | Nonterminal::NtBlock(_) + | Nonterminal::NtIdent(..) + | Nonterminal::NtLifetime(_) => &[], + } + } + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + match self { + Nonterminal::NtItem(item) => item.visit_attrs(f), + Nonterminal::NtStmt(stmt) => stmt.visit_attrs(f), + Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.visit_attrs(f), + Nonterminal::NtPat(_) + | Nonterminal::NtTy(_) + | Nonterminal::NtMeta(_) + | Nonterminal::NtPath(_) + | Nonterminal::NtVis(_) + | Nonterminal::NtTT(_) + | Nonterminal::NtBlock(_) + | Nonterminal::NtIdent(..) + | Nonterminal::NtLifetime(_) => {} + } + } + fn tokens_mut(&mut self) -> Option<&mut Option> { + match self { + Nonterminal::NtItem(item) => item.tokens_mut(), + Nonterminal::NtStmt(stmt) => stmt.tokens_mut(), + Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), + Nonterminal::NtPat(pat) => pat.tokens_mut(), + Nonterminal::NtTy(ty) => ty.tokens_mut(), + Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), + Nonterminal::NtPath(path) => path.tokens_mut(), + Nonterminal::NtVis(vis) => vis.tokens_mut(), + _ => panic!("Called tokens_mut on {:?}", self), + } + } +} + fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec)) { crate::mut_visit::visit_clobber(attrs, |attrs| { let mut vec = attrs.into(); @@ -35,6 +96,10 @@ fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec)) { } impl AstLike for StmtKind { + // This might be an `StmtKind::Item`, which contains + // an item that supports inner attrs + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; + fn attrs(&self) -> &[Attribute] { match self { StmtKind::Local(local) => local.attrs(), @@ -66,6 +131,8 @@ impl AstLike for StmtKind { } impl AstLike for Stmt { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = StmtKind::SUPPORTS_CUSTOM_INNER_ATTRS; + fn attrs(&self) -> &[Attribute] { self.kind.attrs() } @@ -79,6 +146,8 @@ impl AstLike for Stmt { } impl AstLike for Attribute { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + fn attrs(&self) -> &[Attribute] { &[] } @@ -94,6 +163,8 @@ impl AstLike for Attribute { } impl AstLike for Option { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS; + fn attrs(&self) -> &[Attribute] { self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[]) } @@ -127,8 +198,13 @@ impl VecOrAttrVec for AttrVec { } macro_rules! derive_has_tokens_and_attrs { - ($($ty:path),*) => { $( + ( + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner_attrs:literal; + $($ty:path),* + ) => { $( impl AstLike for $ty { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner_attrs; + fn attrs(&self) -> &[Attribute] { &self.attrs } @@ -140,6 +216,7 @@ macro_rules! derive_has_tokens_and_attrs { fn tokens_mut(&mut self) -> Option<&mut Option> { Some(&mut self.tokens) } + } )* } } @@ -147,6 +224,8 @@ macro_rules! derive_has_tokens_and_attrs { macro_rules! derive_has_attrs_no_tokens { ($($ty:path),*) => { $( impl AstLike for $ty { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + fn attrs(&self) -> &[Attribute] { &self.attrs } @@ -165,12 +244,13 @@ macro_rules! derive_has_attrs_no_tokens { macro_rules! derive_has_tokens_no_attrs { ($($ty:path),*) => { $( impl AstLike for $ty { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + fn attrs(&self) -> &[Attribute] { &[] } fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec)) {} - fn tokens_mut(&mut self) -> Option<&mut Option> { Some(&mut self.tokens) } @@ -178,10 +258,18 @@ macro_rules! derive_has_tokens_no_attrs { )* } } -// These AST nodes support both inert and active -// attributes, so they also have tokens. +// These ast nodes support both active and inert attributes, +// so they have tokens collected to pass to proc macros +derive_has_tokens_and_attrs! { + // Both `Item` and `AssocItem` can have bodies, which + // can contain inner attributes + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; + Item, AssocItem, ForeignItem +} + derive_has_tokens_and_attrs! { - Item, Expr, Local, AssocItem, ForeignItem + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + Local, MacCallStmt, Expr } // These ast nodes only support inert attributes, so they don't diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 2c5e180f80..41121d095f 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -6,7 +6,9 @@ use crate::ast::{Lit, LitKind}; use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem}; use crate::ast::{Path, PathSegment}; use crate::token::{self, CommentKind, Token}; -use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree, TreeAndSpacing}; +use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; +use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing}; +use crate::tokenstream::{LazyTokenStream, TokenStream}; use rustc_index::bit_set::GrowableBitSet; use rustc_span::source_map::BytePos; @@ -100,16 +102,7 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.is_word()) } - /// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`. - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - - /// Returns `true` if `self` is a `MetaItem` and the meta item is a list. - pub fn is_meta_item_list(&self) -> bool { - self.meta_item_list().is_some() - } - + /// See [`MetaItem::name_value_literal_span`]. pub fn name_value_literal_span(&self) -> Option { self.meta_item()?.name_value_literal_span() } @@ -165,31 +158,6 @@ impl Attribute { false } } - - pub fn is_meta_item_list(&self) -> bool { - self.meta_item_list().is_some() - } - - /// Indicates if the attribute is a `ValueString`. - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - - /// This is used in case you want the value span instead of the whole attribute. Example: - /// - /// ```text - /// #[doc(alias = "foo")] - /// ``` - /// - /// In here, it'll return a span for `"foo"`. - pub fn name_value_literal_span(&self) -> Option { - match self.kind { - AttrKind::Normal(ref item, _) => { - item.meta(self.span).and_then(|meta| meta.name_value_literal_span()) - } - AttrKind::DocComment(..) => None, - } - } } impl MetaItem { @@ -236,10 +204,6 @@ impl MetaItem { self.path == name } - pub fn is_value_str(&self) -> bool { - self.value_str().is_some() - } - /// This is used in case you want the value span instead of the whole attribute. Example: /// /// ```text @@ -306,14 +270,18 @@ impl Attribute { } } - pub fn tokens(&self) -> TokenStream { + pub fn tokens(&self) -> AttrAnnotatedTokenStream { match self.kind { AttrKind::Normal(_, ref tokens) => tokens .as_ref() .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self)) .create_token_stream(), - AttrKind::DocComment(comment_kind, data) => TokenStream::from(TokenTree::Token( - Token::new(token::DocComment(comment_kind, self.style, data), self.span), + AttrKind::DocComment(comment_kind, data) => AttrAnnotatedTokenStream::from(( + AttrAnnotatedTokenTree::Token(Token::new( + token::DocComment(comment_kind, self.style, data), + self.span, + )), + Spacing::Alone, )), } } diff --git a/compiler/rustc_ast/src/expand/mod.rs b/compiler/rustc_ast/src/expand/mod.rs index eebfc38bdf..2ee1bfe0ae 100644 --- a/compiler/rustc_ast/src/expand/mod.rs +++ b/compiler/rustc_ast/src/expand/mod.rs @@ -1,3 +1,3 @@ -//! Definitions shared by macros / syntax extensions and e.g. librustc_middle. +//! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`. pub mod allocator; diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 03ec4b8a44..ffec28a395 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -10,13 +10,15 @@ )] #![feature(box_syntax)] #![feature(box_patterns)] -#![feature(const_fn)] // For the `transmute` in `P::new` +#![cfg_attr(bootstrap, feature(const_fn))] // For the `transmute` in `P::new` +#![cfg_attr(not(bootstrap), feature(const_fn_unsize))] // For the `transmute` in `P::new` #![feature(const_fn_transmute)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] +#![feature(iter_zip)] #![feature(label_break_value)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] @@ -58,7 +60,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// 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 librustc_middle. +/// instead of implementing everything in `rustc_middle`. pub trait HashStableContext: rustc_span::HashStableContext { fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher); } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index f426f2c7fe..05f57f978c 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -630,6 +630,33 @@ pub fn noop_flat_map_param(mut param: Param, vis: &mut T) -> Smal smallvec![param] } +// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. +pub fn visit_attr_annotated_tt(tt: &mut AttrAnnotatedTokenTree, vis: &mut T) { + match tt { + AttrAnnotatedTokenTree::Token(token) => { + visit_token(token, vis); + } + AttrAnnotatedTokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => { + vis.visit_span(open); + vis.visit_span(close); + visit_attr_annotated_tts(tts, vis); + } + AttrAnnotatedTokenTree::Attributes(data) => { + for attr in &mut *data.attrs { + match &mut attr.kind { + AttrKind::Normal(_, attr_tokens) => { + visit_lazy_tts(attr_tokens, vis); + } + AttrKind::DocComment(..) => { + vis.visit_span(&mut attr.span); + } + } + } + visit_lazy_tts_opt_mut(Some(&mut data.tokens), vis); + } + } +} + // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. pub fn visit_tt(tt: &mut TokenTree, vis: &mut T) { match tt { @@ -652,16 +679,30 @@ pub fn visit_tts(TokenStream(tts): &mut TokenStream, vis: &mut T) } } -pub fn visit_lazy_tts(lazy_tts: &mut Option, vis: &mut T) { +pub fn visit_attr_annotated_tts( + AttrAnnotatedTokenStream(tts): &mut AttrAnnotatedTokenStream, + vis: &mut T, +) { + if vis.token_visiting_enabled() && !tts.is_empty() { + let tts = Lrc::make_mut(tts); + visit_vec(tts, |(tree, _is_joint)| visit_attr_annotated_tt(tree, vis)); + } +} + +pub fn visit_lazy_tts_opt_mut(lazy_tts: Option<&mut LazyTokenStream>, vis: &mut T) { if vis.token_visiting_enabled() { - visit_opt(lazy_tts, |lazy_tts| { + if let Some(lazy_tts) = lazy_tts { let mut tts = lazy_tts.create_token_stream(); - visit_tts(&mut tts, vis); + visit_attr_annotated_tts(&mut tts, vis); *lazy_tts = LazyTokenStream::new(tts); - }) + } } } +pub fn visit_lazy_tts(lazy_tts: &mut Option, vis: &mut T) { + visit_lazy_tts_opt_mut(lazy_tts.as_mut(), vis); +} + // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. // Applies ident visitor if it's an ident; applies other visits to interpolated nodes. // In practice the ident part is not actually used by specific visitors right now, @@ -1252,7 +1293,6 @@ pub fn noop_visit_expr( match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } - | InlineAsmOperand::Const { expr, .. } | InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr), InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -1265,6 +1305,7 @@ pub fn noop_visit_expr( vis.visit_expr(out_expr); } } + InlineAsmOperand::Const { anon_const, .. } => vis.visit_anon_const(anon_const), } } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 7e58426d27..15f46ef5d7 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -688,16 +688,12 @@ pub enum NonterminalKind { Item, Block, Stmt, - Pat2018 { - /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the - /// edition of the span. This is used for diagnostics. - inferred: bool, - }, - Pat2021 { - /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the + PatParam { + /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the /// edition of the span. This is used for diagnostics. inferred: bool, }, + PatWithOr, Expr, Ty, Ident, @@ -722,12 +718,11 @@ impl NonterminalKind { sym::stmt => NonterminalKind::Stmt, sym::pat => match edition() { Edition::Edition2015 | Edition::Edition2018 => { - NonterminalKind::Pat2018 { inferred: true } + NonterminalKind::PatParam { inferred: true } } - Edition::Edition2021 => NonterminalKind::Pat2021 { inferred: true }, + Edition::Edition2021 => NonterminalKind::PatWithOr, }, - sym::pat2018 => NonterminalKind::Pat2018 { inferred: false }, - sym::pat2021 => NonterminalKind::Pat2021 { inferred: false }, + sym::pat_param => NonterminalKind::PatParam { inferred: false }, sym::expr => NonterminalKind::Expr, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, @@ -745,10 +740,8 @@ impl NonterminalKind { NonterminalKind::Item => sym::item, NonterminalKind::Block => sym::block, NonterminalKind::Stmt => sym::stmt, - NonterminalKind::Pat2018 { inferred: false } => sym::pat2018, - NonterminalKind::Pat2021 { inferred: false } => sym::pat2021, - NonterminalKind::Pat2018 { inferred: true } - | NonterminalKind::Pat2021 { inferred: true } => sym::pat, + NonterminalKind::PatParam { inferred: false } => sym::pat_param, + NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, NonterminalKind::Expr => sym::expr, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index c5c3142602..2d463a4588 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -14,6 +14,7 @@ //! ownership of the original. use crate::token::{self, DelimToken, Token, TokenKind}; +use crate::AttrVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{self, Lrc}; @@ -89,10 +90,6 @@ impl TokenTree { } } - pub fn joint(self) -> TokenStream { - TokenStream::new(vec![(self, Spacing::Joint)]) - } - pub fn token(kind: TokenKind, span: Span) -> TokenTree { TokenTree::Token(Token::new(kind, span)) } @@ -127,11 +124,11 @@ where } pub trait CreateTokenStream: sync::Send + sync::Sync { - fn create_token_stream(&self) -> TokenStream; + fn create_token_stream(&self) -> AttrAnnotatedTokenStream; } -impl CreateTokenStream for TokenStream { - fn create_token_stream(&self) -> TokenStream { +impl CreateTokenStream for AttrAnnotatedTokenStream { + fn create_token_stream(&self) -> AttrAnnotatedTokenStream { self.clone() } } @@ -147,14 +144,14 @@ impl LazyTokenStream { LazyTokenStream(Lrc::new(Box::new(inner))) } - pub fn create_token_stream(&self) -> TokenStream { + pub fn create_token_stream(&self) -> AttrAnnotatedTokenStream { self.0.create_token_stream() } } impl fmt::Debug for LazyTokenStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt("LazyTokenStream", f) + write!(f, "LazyTokenStream({:?})", self.create_token_stream()) } } @@ -177,12 +174,151 @@ impl HashStable for LazyTokenStream { } } +/// A `AttrAnnotatedTokenStream` is similar to a `TokenStream`, but with extra +/// information about the tokens for attribute targets. This is used +/// during expansion to perform early cfg-expansion, and to process attributes +/// during proc-macro invocations. +#[derive(Clone, Debug, Default, Encodable, Decodable)] +pub struct AttrAnnotatedTokenStream(pub Lrc>); + +/// Like `TokenTree`, but for `AttrAnnotatedTokenStream` +#[derive(Clone, Debug, Encodable, Decodable)] +pub enum AttrAnnotatedTokenTree { + Token(Token), + Delimited(DelimSpan, DelimToken, AttrAnnotatedTokenStream), + /// Stores the attributes for an attribute target, + /// along with the tokens for that attribute target. + /// See `AttributesData` for more information + Attributes(AttributesData), +} + +impl AttrAnnotatedTokenStream { + pub fn new(tokens: Vec<(AttrAnnotatedTokenTree, Spacing)>) -> AttrAnnotatedTokenStream { + AttrAnnotatedTokenStream(Lrc::new(tokens)) + } + + /// Converts this `AttrAnnotatedTokenStream` to a plain `TokenStream + /// During conversion, `AttrAnnotatedTokenTree::Attributes` get 'flattened' + /// back to a `TokenStream` of the form `outer_attr attr_target`. + /// If there are inner attributes, they are inserted into the proper + /// place in the attribute target tokens. + pub fn to_tokenstream(&self) -> TokenStream { + let trees: Vec<_> = self + .0 + .iter() + .flat_map(|tree| match &tree.0 { + AttrAnnotatedTokenTree::Token(inner) => { + smallvec![(TokenTree::Token(inner.clone()), tree.1)].into_iter() + } + AttrAnnotatedTokenTree::Delimited(span, delim, stream) => smallvec![( + TokenTree::Delimited(*span, *delim, stream.to_tokenstream()), + tree.1, + )] + .into_iter(), + AttrAnnotatedTokenTree::Attributes(data) => { + let mut outer_attrs = Vec::new(); + let mut inner_attrs = Vec::new(); + let attrs: Vec<_> = data.attrs.clone().into(); + for attr in attrs { + match attr.style { + crate::AttrStyle::Outer => { + assert!( + inner_attrs.len() == 0, + "Found outer attribute {:?} after inner attrs {:?}", + attr, + inner_attrs + ); + outer_attrs.push(attr); + } + crate::AttrStyle::Inner => { + inner_attrs.push(attr); + } + } + } + + let mut target_tokens: Vec<_> = data + .tokens + .create_token_stream() + .to_tokenstream() + .0 + .iter() + .cloned() + .collect(); + if !inner_attrs.is_empty() { + let mut found = false; + // Check the last two trees (to account for a trailing semi) + for (tree, _) in target_tokens.iter_mut().rev().take(2) { + if let TokenTree::Delimited(span, delim, delim_tokens) = tree { + // Inner attributes are only supported on extern blocks, functions, impls, + // and modules. All of these have their inner attributes placed at + // the beginning of the rightmost outermost braced group: + // e.g. fn foo() { #![my_attr} } + // + // Therefore, we can insert them back into the right location + // without needing to do any extra position tracking. + // + // Note: Outline modules are an exception - they can + // have attributes like `#![my_attr]` at the start of a file. + // Support for custom attributes in this position is not + // properly implemented - we always synthesize fake tokens, + // so we never reach this code. + + let mut builder = TokenStreamBuilder::new(); + for inner_attr in &inner_attrs { + builder.push(inner_attr.tokens().to_tokenstream()); + } + builder.push(delim_tokens.clone()); + *tree = TokenTree::Delimited(*span, *delim, builder.build()); + found = true; + break; + } + } + + assert!( + found, + "Failed to find trailing delimited group in: {:?}", + target_tokens + ); + } + let mut flat: SmallVec<[_; 1]> = SmallVec::new(); + for attr in outer_attrs { + // FIXME: Make this more efficient + flat.extend(attr.tokens().to_tokenstream().0.clone().iter().cloned()); + } + flat.extend(target_tokens); + flat.into_iter() + } + }) + .collect(); + TokenStream::new(trees) + } +} + +/// Stores the tokens for an attribute target, along +/// with its attributes. +/// +/// This is constructed during parsing when we need to capture +/// tokens. +/// +/// For example, `#[cfg(FALSE)] struct Foo {}` would +/// have an `attrs` field containing the `#[cfg(FALSE)]` attr, +/// and a `tokens` field storing the (unparesd) tokens `struct Foo {}` +#[derive(Clone, Debug, Encodable, Decodable)] +pub struct AttributesData { + /// Attributes, both outer and inner. + /// These are stored in the original order that they were parsed in. + pub attrs: AttrVec, + /// The underlying tokens for the attribute target that `attrs` + /// are applied to + pub tokens: LazyTokenStream, +} + /// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. /// /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for -/// backwards compatability. +/// backwards compatibility. #[derive(Clone, Debug, Default, Encodable, Decodable)] pub struct TokenStream(pub(crate) Lrc>); @@ -239,6 +375,12 @@ impl TokenStream { } } +impl From<(AttrAnnotatedTokenTree, Spacing)> for AttrAnnotatedTokenStream { + fn from((tree, spacing): (AttrAnnotatedTokenTree, Spacing)) -> AttrAnnotatedTokenStream { + AttrAnnotatedTokenStream::new(vec![(tree, spacing)]) + } +} + impl From for TokenStream { fn from(tree: TokenTree) -> TokenStream { TokenStream::new(vec![(tree, Spacing::Alone)]) @@ -278,14 +420,6 @@ impl TokenStream { self.0.len() } - pub fn span(&self) -> Option { - match &**self.0 { - [] => None, - [(tt, _)] => Some(tt.span()), - [(tt_start, _), .., (tt_end, _)] => Some(tt_start.span().to(tt_end.span())), - } - } - pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream { match streams.len() { 0 => TokenStream::default(), @@ -325,10 +459,6 @@ impl TokenStream { } } - pub fn trees_ref(&self) -> CursorRef<'_> { - CursorRef::new(self) - } - pub fn trees(&self) -> Cursor { self.clone().into_trees() } @@ -341,7 +471,7 @@ impl TokenStream { pub fn eq_unspanned(&self, other: &TokenStream) -> bool { let mut t1 = self.trees(); let mut t2 = other.trees(); - for (t1, t2) in t1.by_ref().zip(t2.by_ref()) { + for (t1, t2) in iter::zip(&mut t1, &mut t2) { if !t1.eq_unspanned(&t2) { return false; } @@ -427,10 +557,6 @@ pub struct CursorRef<'t> { } impl<'t> CursorRef<'t> { - fn new(stream: &TokenStream) -> CursorRef<'_> { - CursorRef { stream, index: 0 } - } - fn next_with_spacing(&mut self) -> Option<&'t TreeAndSpacing> { self.stream.0.get(self.index).map(|tree| { self.index += 1; @@ -477,6 +603,10 @@ impl Cursor { } } + pub fn index(&self) -> usize { + self.index + } + pub fn append(&mut self, new_stream: TokenStream) { if new_stream.is_empty() { return; diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index b1ad29e4ad..3f35919ae6 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -835,7 +835,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } - | InlineAsmOperand::Const { expr, .. } | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr), InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -848,6 +847,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(out_expr); } } + InlineAsmOperand::Const { anon_const, .. } => { + visitor.visit_anon_const(anon_const) + } } } } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 32fb8d1c8f..75dfe951c9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1411,9 +1411,9 @@ impl<'hir> LoweringContext<'_, 'hir> { out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)), } } - InlineAsmOperand::Const { ref expr } => { - hir::InlineAsmOperand::Const { expr: self.lower_expr_mut(expr) } - } + InlineAsmOperand::Const { ref anon_const } => hir::InlineAsmOperand::Const { + anon_const: self.lower_anon_const(anon_const), + }, InlineAsmOperand::Sym { ref expr } => { hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) } } @@ -1499,46 +1499,64 @@ impl<'hir> LoweringContext<'_, 'hir> { // previous iteration. required_features.clear(); - // Validate register classes against currently enabled target - // features. We check that at least one type is available for - // the current target. let reg_class = reg.reg_class(); if reg_class == asm::InlineAsmRegClass::Err { continue; } - for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) { - if let Some(feature) = feature { - if self.sess.target_features.contains(&Symbol::intern(feature)) { + + // We ignore target feature requirements for clobbers: if the + // feature is disabled then the compiler doesn't care what we + // do with the registers. + // + // Note that this is only possible for explicit register + // operands, which cannot be used in the asm string. + let is_clobber = matches!( + op, + hir::InlineAsmOperand::Out { + reg: asm::InlineAsmRegOrRegClass::Reg(_), + late: _, + expr: None + } + ); + + if !is_clobber { + // Validate register classes against currently enabled target + // features. We check that at least one type is available for + // the current target. + for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) { + if let Some(feature) = feature { + if self.sess.target_features.contains(&Symbol::intern(feature)) { + required_features.clear(); + break; + } else { + required_features.push(feature); + } + } else { required_features.clear(); break; - } else { - required_features.push(feature); } - } else { - required_features.clear(); - break; - } - } - // We are sorting primitive strs here and can use unstable sort here - required_features.sort_unstable(); - required_features.dedup(); - match &required_features[..] { - [] => {} - [feature] => { - let msg = format!( - "register class `{}` requires the `{}` target feature", - reg_class.name(), - feature - ); - sess.struct_span_err(op_sp, &msg).emit(); } - features => { - let msg = format!( - "register class `{}` requires at least one target feature: {}", - reg_class.name(), - features.join(", ") - ); - sess.struct_span_err(op_sp, &msg).emit(); + // We are sorting primitive strs here and can use unstable sort here + required_features.sort_unstable(); + required_features.dedup(); + match &required_features[..] { + [] => {} + [feature] => { + let msg = format!( + "register class `{}` requires the `{}` target feature", + reg_class.name(), + feature + ); + sess.struct_span_err(op_sp, &msg).emit(); + } + features => { + let msg = format!( + "register class `{}` requires at least one target feature: {}", + reg_class.name(), + features.join(", ") + ); + sess.struct_span_err(op_sp, &msg).emit(); + } } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index edd0c5fb96..5fd8f7eb33 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -18,6 +18,7 @@ use rustc_target::spec::abi; use smallvec::{smallvec, SmallVec}; use tracing::debug; +use std::iter; use std::mem; pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { @@ -206,7 +207,7 @@ impl<'hir> LoweringContext<'_, 'hir> { UseTreeKind::Glob => {} UseTreeKind::Simple(_, id1, id2) => { for (_, &id) in - self.expect_full_res_from_use(base_id).skip(1).zip([id1, id2].iter()) + iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { vec.push(id); } @@ -537,7 +538,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // won't be dealing with macros in the rest of the compiler. // Essentially a single `use` which imports two names is desugared into // two imports. - for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) { + for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) { let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { @@ -835,9 +836,17 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names))) } AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, Some(ref body))) => { - let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); - let (generics, sig) = - self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id); + let asyncness = sig.header.asyncness; + let body_id = + self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body)); + let (generics, sig) = self.lower_method_sig( + generics, + sig, + trait_item_def_id, + false, + asyncness.opt_return_id(), + i.id, + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id))) } AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref default)) => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f9872f84e1..44056df4ab 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -31,13 +31,14 @@ //! in the HIR, especially for multiple identifiers. #![feature(crate_visibility_modifier)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(box_patterns)] +#![feature(iter_zip)] #![recursion_limit = "256"] use rustc_ast::node_id::NodeMap; -use rustc_ast::token::{self, DelimToken, Nonterminal, Token}; -use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, DelimSpan, TokenStream, TokenTree}; +use rustc_ast::token::{self, Token}; +use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree}; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::walk_list; use rustc_ast::{self as ast, *}; @@ -55,7 +56,7 @@ use rustc_hir::{ConstArg, GenericArg, ParamName}; use rustc_index::vec::{Idx, IndexVec}; use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; -use rustc_session::parse::ParseSess; +use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind}; @@ -92,7 +93,7 @@ struct LoweringContext<'a, 'hir: 'a> { /// HACK(Centril): there is a cyclic dependency between the parser and lowering /// if we don't have this function pointer. To avoid that dependency so that - /// librustc_middle is independent of the parser, we use dynamic dispatch here. + /// `rustc_middle` is independent of the parser, we use dynamic dispatch here. nt_to_tokenstream: NtToTokenstream, /// Used to allocate HIR nodes. @@ -212,8 +213,6 @@ pub trait ResolverAstLowering { ) -> LocalDefId; } -type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream; - /// 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)] @@ -402,42 +401,6 @@ enum AnonymousLifetimeMode { PassThrough, } -struct TokenStreamLowering<'a> { - parse_sess: &'a ParseSess, - synthesize_tokens: CanSynthesizeMissingTokens, - nt_to_tokenstream: NtToTokenstream, -} - -impl<'a> TokenStreamLowering<'a> { - fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream { - tokens.into_trees().flat_map(|tree| self.lower_token_tree(tree).into_trees()).collect() - } - - fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream { - match tree { - TokenTree::Token(token) => self.lower_token(token), - TokenTree::Delimited(span, delim, tts) => { - TokenTree::Delimited(span, delim, self.lower_token_stream(tts)).into() - } - } - } - - fn lower_token(&mut self, token: Token) -> TokenStream { - match token.kind { - token::Interpolated(nt) => { - let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens); - TokenTree::Delimited( - DelimSpan::from_single(token.span), - DelimToken::NoDelim, - self.lower_token_stream(tts), - ) - .into() - } - _ => TokenTree::Token(token).into(), - } - } -} - impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_crate(mut self, c: &Crate) -> hir::Crate<'hir> { /// Full-crate AST visitor that inserts into a fresh @@ -520,10 +483,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } self.visit_fn_ret_ty(&f.decl.output) } - TyKind::ImplTrait(def_node_id, _) => { - self.lctx.allocate_hir_id_counter(def_node_id); - visit::walk_ty(self, t); - } _ => visit::walk_ty(self, t), } } @@ -572,7 +531,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } hir::Crate { - item: hir::CrateItem { module, span: c.span }, + 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), items: self.items, @@ -1040,12 +999,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - let tokens = TokenStreamLowering { + let tokens = FlattenNonterminals { parse_sess: &self.sess.parse_sess, synthesize_tokens: CanSynthesizeMissingTokens::Yes, nt_to_tokenstream: self.nt_to_tokenstream, } - .lower_token(token.clone()); + .process_token(token.clone()); MacArgs::Eq(eq_span, unwrap_single_token(self.sess, tokens, token.span)) } } @@ -1056,12 +1015,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: TokenStream, synthesize_tokens: CanSynthesizeMissingTokens, ) -> TokenStream { - TokenStreamLowering { + FlattenNonterminals { parse_sess: &self.sess.parse_sess, synthesize_tokens, nt_to_tokenstream: self.nt_to_tokenstream, } - .lower_token_stream(tokens) + .process_token_stream(tokens) } /// Given an associated type constraint like one of these: @@ -1431,14 +1390,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Add a definition for the in-band `Param`. let def_id = self.resolver.local_def_id(def_node_id); - self.allocate_hir_id_counter(def_node_id); - - let hir_bounds = self.with_hir_id_owner(def_node_id, |this| { - this.lower_param_bounds( - bounds, - ImplTraitContext::Universal(in_band_ty_params, parent_def_id), - ) - }); + let hir_bounds = self.lower_param_bounds( + bounds, + ImplTraitContext::Universal(in_band_ty_params, parent_def_id), + ); // Set the name to `impl Bound1 + Bound2`. let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); in_band_ty_params.push(hir::GenericParam { @@ -2266,13 +2221,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty( - x, - ImplTraitContext::OtherOpaqueTy { - capturable_lifetimes: &mut FxHashSet::default(), - origin: hir::OpaqueTyOrigin::Misc, - }, - ) + self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other)) }), synthetic: param .attrs @@ -2290,7 +2239,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { this.lower_ty(&ty, ImplTraitContext::disallowed()) }); let default = default.as_ref().map(|def| self.lower_anon_const(def)); - (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default }) } }; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 563bcda519..6d6438920c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -532,6 +532,25 @@ impl<'a> AstValidator<'a> { } } + /// An item in `extern { ... }` cannot use non-ascii identifier. + fn check_foreign_item_ascii_only(&self, ident: Ident) { + let symbol_str = ident.as_str(); + if !symbol_str.is_ascii() { + let n = 83942; + self.err_handler() + .struct_span_err( + ident.span, + "items in `extern` blocks cannot use non-ascii identifiers", + ) + .span_label(self.current_extern_span(), "in this `extern` block") + .note(&format!( + "This limitation may be lifted in the future; see issue #{} for more information", + n, n, + )) + .emit(); + } + } + /// Reject C-varadic type unless the function is foreign, /// or free and `unsafe extern "C"` semantically. fn check_c_varadic_type(&self, fk: FnKind<'a>) { @@ -592,7 +611,7 @@ impl<'a> AstValidator<'a> { self.session, ident.span, E0754, - "trying to load file for module `{}` with non ascii identifer name", + "trying to load file for module `{}` with non-ascii identifier name", ident.name ) .help("consider using `#[path]` attribute to specify filesystem path") @@ -735,7 +754,7 @@ fn validate_generic_param_order( GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - let unordered = sess.features_untracked().const_generics; + let unordered = sess.features_untracked().unordered_const_ty_params(); (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty))) } }; @@ -1103,15 +1122,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(fi.span, *def); self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header); + self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::TyAlias(box TyAliasKind(def, generics, bounds, body)) => { self.check_defaultness(fi.span, *def); self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span)); self.check_type_no_bounds(bounds, "`extern` blocks"); self.check_foreign_ty_genericless(generics); + self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::Static(_, _, body) => { self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); + self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::MacCall(..) => {} } @@ -1150,20 +1172,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_generics(&mut self, generics: &'a Generics) { - let mut prev_ty_default = None; + let cg_defaults = self.session.features_untracked().const_generics_defaults; + + let mut prev_param_default = None; for param in &generics.params { match param.kind { GenericParamKind::Lifetime => (), - GenericParamKind::Type { default: Some(_), .. } => { - prev_ty_default = Some(param.ident.span); + GenericParamKind::Type { default: Some(_), .. } + | GenericParamKind::Const { default: Some(_), .. } => { + prev_param_default = Some(param.ident.span); } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - if let Some(span) = prev_ty_default { + if let Some(span) = prev_param_default { let mut err = self.err_handler().struct_span_err( span, - "type parameters with a default must be trailing", + "generic parameters with a default must be trailing", ); - if matches!(param.kind, GenericParamKind::Const { .. }) { + if matches!(param.kind, GenericParamKind::Const { .. }) && !cg_defaults { err.note( "using type defaults and const parameters \ in the same parameter list is currently not permitted", @@ -1188,8 +1213,41 @@ impl<'a> Visitor<'a> for AstValidator<'a> { deny_equality_constraints(self, predicate, generics); } } - - visit::walk_generics(self, generics) + walk_list!(self, visit_generic_param, &generics.params); + for predicate in &generics.where_clause.predicates { + match predicate { + WherePredicate::BoundPredicate(bound_pred) => { + // A type binding, eg `for<'c> Foo: Send+Clone+'c` + self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); + + // This is slightly complicated. Our representation for poly-trait-refs contains a single + // binder and thus we only allow a single level of quantification. However, + // the syntax of Rust permits quantification in two places in where clauses, + // e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are + // defined, then error. + if !bound_pred.bound_generic_params.is_empty() { + for bound in &bound_pred.bounds { + match bound { + GenericBound::Trait(t, _) => { + if !t.bound_generic_params.is_empty() { + struct_span_err!( + self.err_handler(), + t.span, + E0316, + "nested quantification of lifetimes" + ) + .emit(); + } + } + GenericBound::Outlives(_) => {} + } + } + } + } + _ => {} + } + self.visit_where_predicate(predicate); + } } fn visit_generic_param(&mut self, param: &'a GenericParam) { @@ -1238,14 +1296,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_pat(self, pat) } - fn visit_where_predicate(&mut self, p: &'a WherePredicate) { - if let &WherePredicate::BoundPredicate(ref bound_predicate) = p { - // A type binding, eg `for<'c> Foo: Send+Clone+'c` - self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params); - } - visit::walk_where_predicate(self, p); - } - fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) { self.check_late_bound_lifetime_defs(&t.bound_generic_params); visit::walk_poly_trait_ref(self, t, m); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0ca9c12f4c..da516f5cb4 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -8,7 +8,7 @@ use rustc_feature::{Features, GateIssue}; use rustc_session::parse::{feature_err, feature_err_issue}; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; use rustc_span::Span; use tracing::debug; @@ -196,6 +196,14 @@ impl<'a> PostExpansionVisitor<'a> { "thiscall-unwind ABI is experimental and subject to change" ); } + "wasm" => { + gate_feature_post!( + &self, + wasm_abi, + span, + "wasm ABI is experimental and subject to change" + ); + } abi => self .sess .parse_sess @@ -313,24 +321,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { include => external_doc cfg => doc_cfg masked => doc_masked - spotlight => doc_spotlight + notable_trait => doc_notable_trait keyword => doc_keyword ); } } } - fn visit_name(&mut self, sp: Span, name: Symbol) { - if !name.as_str().is_ascii() { - gate_feature_post!( - &self, - non_ascii_idents, - self.sess.parse_sess.source_map().guess_head_span(sp), - "non-ascii idents are not fully supported" - ); - } - } - fn visit_item(&mut self, i: &'a ast::Item) { match i.kind { ast::ItemKind::ForeignMod(ref foreign_module) => { @@ -358,16 +355,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { over time" ); } - if self.sess.contains_name(&i.attrs[..], sym::main) { - gate_feature_post!( - &self, - main, - i.span, - "declaration of a non-standard `#[main]` \ - function may change over time, for now \ - a top-level `fn main()` is required" - ); - } } ast::ItemKind::Struct(..) => { @@ -599,12 +586,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { let is_fn = match i.kind { - ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => { - if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { - gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); - } - true - } + ast::AssocItemKind::Fn(_) => true, ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( @@ -686,7 +668,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { "to use an async block, remove the `||`: `async {`" ); gate_all!(generators, "yield syntax is experimental"); - gate_all!(or_patterns, "or-patterns syntax is experimental"); gate_all!(raw_ref_op, "raw address of syntax is experimental"); gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental"); gate_all!(const_trait_impl, "const trait impls are experimental"); @@ -705,7 +686,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { // involved, so we only emit errors where there are no other parsing errors. gate_all!(destructuring_assignment, "destructuring assignments are unstable"); } - gate_all!(pub_macro_rules, "`pub` on `macro_rules` items is unstable"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). @@ -741,16 +721,46 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { } fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { + use rustc_errors::Applicability; + if !sess.opts.unstable_features.is_nightly_build() { + let lang_features = &sess.features_untracked().declared_lang_features; for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) { - struct_span_err!( + let mut err = struct_span_err!( sess.parse_sess.span_diagnostic, attr.span, E0554, "`#![feature]` may not be used on the {} release channel", option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)") - ) - .emit(); + ); + let mut all_stable = true; + for ident in + attr.meta_item_list().into_iter().flatten().map(|nested| nested.ident()).flatten() + { + let name = ident.name; + let stable_since = lang_features + .iter() + .flat_map(|&(feature, _, since)| if feature == name { since } else { None }) + .next(); + if let Some(since) = stable_since { + err.help(&format!( + "the feature `{}` has been stable since {} and no longer requires \ + an attribute to enable", + name, since + )); + } else { + all_stable = false; + } + } + if all_stable { + err.span_suggestion( + attr.span, + "remove the attribute", + String::new(), + Applicability::MachineApplicable, + ); + } + err.emit(); } } } diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index d869baad01..67b66284f6 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -1,6 +1,6 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(box_patterns)] #![recursion_limit = "256"] diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs index b88699f6ee..976725b308 100644 --- a/compiler/rustc_ast_pretty/src/pprust/mod.rs +++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs @@ -22,10 +22,6 @@ pub fn token_to_string(token: &Token) -> String { State::new().token_to_string(token) } -pub fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String { - State::new().token_to_string_ext(token, convert_dollar_crate) -} - pub fn ty_to_string(ty: &ast::Ty) -> String { State::new().ty_to_string(ty) } @@ -50,18 +46,10 @@ pub fn tts_to_string(tokens: &TokenStream) -> String { State::new().tts_to_string(tokens) } -pub fn stmt_to_string(stmt: &ast::Stmt) -> String { - State::new().stmt_to_string(stmt) -} - pub fn item_to_string(i: &ast::Item) -> String { State::new().item_to_string(i) } -pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String { - State::new().generic_params_to_string(generic_params) -} - pub fn path_to_string(p: &ast::Path) -> String { State::new().path_to_string(p) } @@ -74,26 +62,14 @@ pub fn vis_to_string(v: &ast::Visibility) -> String { State::new().vis_to_string(v) } -pub fn block_to_string(blk: &ast::Block) -> String { - State::new().block_to_string(blk) -} - pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String { State::new().meta_list_item_to_string(li) } -pub fn attr_item_to_string(ai: &ast::AttrItem) -> String { - State::new().attr_item_to_string(ai) -} - pub fn attribute_to_string(attr: &ast::Attribute) -> String { State::new().attribute_to_string(attr) } -pub fn param_to_string(arg: &ast::Param) -> String { - State::new().param_to_string(arg) -} - pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { State::new().to_string(f) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cb6f567c55..789d2c296e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2149,10 +2149,10 @@ impl<'a> State<'a> { None => s.word("_"), } } - InlineAsmOperand::Const { expr } => { + InlineAsmOperand::Const { anon_const } => { s.word("const"); s.space(); - s.print_expr(expr); + s.print_expr(&anon_const.value); } InlineAsmOperand::Sym { expr } => { s.word("sym"); @@ -2292,10 +2292,6 @@ impl<'a> State<'a> { } } - pub fn print_usize(&mut self, i: usize) { - self.s.word(i.to_string()) - } - crate fn print_name(&mut self, name: Symbol) { self.s.word(name.to_string()); self.ann.post(self, AnnNode::Name(&name)) @@ -2659,8 +2655,10 @@ impl<'a> State<'a> { s.word_space(":"); s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): print the `default` value here + if let Some(ref default) = default { + s.s.space(); + s.word_space("="); + s.print_expr(&default.value); } } } diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 149a950f7d..ab68d24e4b 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -4,7 +4,7 @@ //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax` //! to this crate. -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 8d8b3f4f6a..fd976b119b 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -7,11 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_expand::base::{self, *}; use rustc_parse::parser::Parser; use rustc_parse_format as parse; -use rustc_span::{ - symbol::{kw, sym, Symbol}, - BytePos, -}; +use rustc_session::lint; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{InnerSpan, Span}; +use rustc_target::asm::InlineAsmArch; struct AsmArgs { templates: Vec>, @@ -137,8 +136,8 @@ fn parse_args<'a>( ast::InlineAsmOperand::InOut { reg, expr, late: true } } } else if p.eat_keyword(kw::Const) { - let expr = p.parse_expr()?; - ast::InlineAsmOperand::Const { expr } + let anon_const = p.parse_anon_const_expr()?; + ast::InlineAsmOperand::Const { anon_const } } else if p.eat_keyword(sym::sym) { let expr = p.parse_expr()?; match expr.kind { @@ -402,8 +401,6 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P, sp: Span, args: AsmArgs) -> P { - if let Some(span) = check_syntax_directive(snippet, ".intel_syntax") { - let span = template_span.from_inner(span); - let mut err = ecx.struct_span_err(span, "intel syntax is the default syntax on this target, and trying to use this directive may cause issues"); - err.span_suggestion( - span, - "remove this assembler directive", - "".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - } - - if let Some(span) = check_syntax_directive(snippet, ".att_syntax") { - let span = template_span.from_inner(span); - let mut err = ecx.struct_span_err(span, "using the .att_syntax directive may cause issues, use the att_syntax option instead"); - let asm_end = sp.hi() - BytePos(2); - let suggestions = vec![ - (span, "".to_string()), - ( - Span::new(asm_end, asm_end, sp.ctxt()), - ", options(att_syntax)".to_string(), - ), - ]; - err.multipart_suggestion( - "remove the assembler directive and replace it with options(att_syntax)", - suggestions, - Applicability::MachineApplicable, - ); - err.emit(); + if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch { + let find_span = |needle: &str| -> Span { + if let Some(snippet) = &template_snippet { + if let Some(pos) = snippet.find(needle) { + let end = pos + + &snippet[pos..] + .find(|c| matches!(c, '\n' | ';' | '\\' | '"')) + .unwrap_or(snippet[pos..].len() - 1); + let inner = InnerSpan::new(pos, end); + return template_sp.from_inner(inner); } } - ast::LlvmAsmDialect::Att => { - if let Some(span) = check_syntax_directive(snippet, ".att_syntax") { - let span = template_span.from_inner(span); - let mut err = ecx.struct_span_err(span, "att syntax is the default syntax on this target, and trying to use this directive may cause issues"); - err.span_suggestion( - span, - "remove this assembler directive", - "".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - } + template_sp + }; - // Use of .intel_syntax is ignored - } + if template_str.contains(".intel_syntax") { + ecx.parse_sess().buffer_lint( + lint::builtin::BAD_ASM_STYLE, + find_span(".intel_syntax"), + ecx.resolver.lint_node_id(ecx.current_expansion.id), + "avoid using `.intel_syntax`, Intel syntax is the default", + ); + } + if template_str.contains(".att_syntax") { + ecx.parse_sess().buffer_lint( + lint::builtin::BAD_ASM_STYLE, + find_span(".att_syntax"), + ecx.resolver.lint_node_id(ecx.current_expansion.id), + "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead", + ); } } @@ -690,15 +667,3 @@ pub fn expand_asm<'cx>( } } } - -fn check_syntax_directive>(piece: S, syntax: &str) -> Option { - let piece = piece.as_ref(); - if let Some(idx) = piece.find(syntax) { - let end = - idx + &piece[idx..].find(|c| matches!(c, '\n' | ';')).unwrap_or(piece[idx..].len()); - // Offset by one because these represent the span with the " removed - Some(InnerSpan::new(idx + 1, end + 1)) - } else { - None - } -} diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 025872df01..79dc857074 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -1,11 +1,18 @@ use crate::util::check_builtin_macro_attribute; -use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, AstLike}; +use rustc_ast as ast; +use rustc_ast::mut_visit::MutVisitor; +use rustc_ast::tokenstream::CanSynthesizeMissingTokens; +use rustc_ast::visit::Visitor; +use rustc_ast::{mut_visit, visit}; +use rustc_ast::{AstLike, Attribute}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::config::StripUnconfigured; use rustc_expand::configure; +use rustc_parse::parser::ForceCollect; +use rustc_session::utils::FlattenNonterminals; + +use rustc_ast::ptr::P; use rustc_span::symbol::sym; use rustc_span::Span; use smallvec::SmallVec; @@ -22,74 +29,179 @@ crate fn expand( crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec { let mut visitor = CfgEval { - cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false }, + cfg: &mut StripUnconfigured { + sess: ecx.sess, + features: ecx.ecfg.features, + config_tokens: true, + }, }; - let mut annotatable = visitor.configure_annotatable(annotatable); - if visitor.cfg.modified { - // Erase the tokens if cfg-stripping modified the item - // This will cause us to synthesize fake tokens - // when `nt_to_tokenstream` is called on this item. - if let Some(tokens) = annotatable.tokens_mut() { - *tokens = None; + let annotatable = visitor.configure_annotatable(annotatable); + vec![annotatable] +} + +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 + match annotatable { + Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()), + Annotatable::TraitItem(item) => { + Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap()) + } + Annotatable::ImplItem(item) => { + Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap()) + } + Annotatable::ForeignItem(item) => { + Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap()) } + Annotatable::Stmt(stmt) => { + Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap())) + } + Annotatable::Expr(mut expr) => Annotatable::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()) + } + Annotatable::PatField(fp) => { + Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap()) + } + 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()) + } + Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()), + } +} + +struct CfgFinder { + has_cfg_or_cfg_attr: bool, +} + +impl CfgFinder { + fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool { + let mut finder = CfgFinder { has_cfg_or_cfg_attr: false }; + match annotatable { + Annotatable::Item(item) => finder.visit_item(&item), + Annotatable::TraitItem(item) => finder.visit_assoc_item(&item, visit::AssocCtxt::Trait), + Annotatable::ImplItem(item) => finder.visit_assoc_item(&item, visit::AssocCtxt::Impl), + Annotatable::ForeignItem(item) => finder.visit_foreign_item(&item), + Annotatable::Stmt(stmt) => finder.visit_stmt(&stmt), + Annotatable::Expr(expr) => finder.visit_expr(&expr), + Annotatable::Arm(arm) => finder.visit_arm(&arm), + Annotatable::ExprField(field) => finder.visit_expr_field(&field), + Annotatable::PatField(field) => finder.visit_pat_field(&field), + Annotatable::GenericParam(param) => finder.visit_generic_param(¶m), + Annotatable::Param(param) => finder.visit_param(¶m), + Annotatable::FieldDef(field) => finder.visit_field_def(&field), + Annotatable::Variant(variant) => finder.visit_variant(&variant), + }; + finder.has_cfg_or_cfg_attr } - vec![annotatable] } -struct CfgEval<'a> { - cfg: StripUnconfigured<'a>, +impl<'ast> visit::Visitor<'ast> for CfgFinder { + fn visit_attribute(&mut self, attr: &'ast Attribute) { + // We want short-circuiting behavior, so don't use the '|=' operator. + self.has_cfg_or_cfg_attr = self.has_cfg_or_cfg_attr + || attr + .ident() + .map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr); + } } -impl CfgEval<'_> { +impl CfgEval<'_, '_> { fn configure(&mut self, node: T) -> Option { self.cfg.configure(node) } - fn configure_annotatable(&mut self, 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 - match annotatable { - Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()), - Annotatable::TraitItem(item) => { - Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap()) - } - Annotatable::ImplItem(item) => { - Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap()) - } - Annotatable::ForeignItem(item) => { - Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap()) - } - Annotatable::Stmt(stmt) => { - Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap())) - } - Annotatable::Expr(mut expr) => Annotatable::Expr({ - self.visit_expr(&mut expr); - expr - }), - Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()), - Annotatable::ExprField(field) => { - Annotatable::ExprField(self.flat_map_expr_field(field).pop().unwrap()) - } - Annotatable::PatField(fp) => { - Annotatable::PatField(self.flat_map_pat_field(fp).pop().unwrap()) - } - Annotatable::GenericParam(param) => { - Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap()) - } - Annotatable::Param(param) => { - Annotatable::Param(self.flat_map_param(param).pop().unwrap()) - } - Annotatable::FieldDef(sf) => { - Annotatable::FieldDef(self.flat_map_field_def(sf).pop().unwrap()) + pub fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> 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; + } + + // The majority of parsed attribute targets will never need to have early cfg-expansion + // run (e.g. they are not part of a `#[derive]` or `#[cfg_eval]` macro inoput). + // Therefore, we normally do not capture the necessary information about `#[cfg]` + // and `#[cfg_attr]` attributes during parsing. + // + // Therefore, when we actually *do* run early cfg-expansion, we need to tokenize + // and re-parse the attribute target, this time capturing information about + // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization + // process is lossless, so this process is invisible to proc-macros. + + // FIXME - get rid of this clone + let nt = annotatable.clone().into_nonterminal(); + + let mut orig_tokens = rustc_parse::nt_to_tokenstream( + &nt, + &self.cfg.sess.parse_sess, + CanSynthesizeMissingTokens::No, + ); + + // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`) + // to `None`-delimited groups containing the corresponding tokens. This + // is normally delayed until the proc-macro server actually needs to + // provide a `TokenKind::Interpolated` to a proc-macro. We do this earlier, + // so that we can handle cases like: + // + // ```rust + // #[cfg_eval] #[cfg] $item + //``` + // + // where `$item` is `#[cfg_attr] struct Foo {}`. We want to make + // sure to evaluate *all* `#[cfg]` and `#[cfg_attr]` attributes - the simplest + // way to do this is to do a single parse of a stream without any nonterminals. + let mut flatten = FlattenNonterminals { + nt_to_tokenstream: rustc_parse::nt_to_tokenstream, + parse_sess: &self.cfg.sess.parse_sess, + synthesize_tokens: CanSynthesizeMissingTokens::No, + }; + orig_tokens = flatten.process_token_stream(orig_tokens); + + // Re-parse the tokens, setting the `capture_cfg` flag to save extra information + // to the captured `AttrAnnotatedTokenStream` (specifically, we capture + // `AttrAnnotatedTokenTree::AttributesData` for all occurences of `#[cfg]` and `#[cfg_attr]`) + let mut parser = + rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None); + parser.capture_cfg = true; + annotatable = match annotatable { + Annotatable::Item(_) => { + Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap()) } - Annotatable::Variant(v) => { - Annotatable::Variant(self.flat_map_variant(v).pop().unwrap()) + Annotatable::TraitItem(_) => Annotatable::TraitItem( + parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ), + Annotatable::ImplItem(_) => Annotatable::ImplItem( + parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ), + Annotatable::ForeignItem(_) => Annotatable::ForeignItem( + parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ), + Annotatable::Stmt(_) => { + Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap())) } - } + Annotatable::Expr(_) => Annotatable::Expr(parser.parse_expr_force_collect().unwrap()), + _ => unreachable!(), + }; + + // Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring + // our attribute target will correctly the tokens as well. + flat_map_annotatable(self, annotatable) } } -impl MutVisitor for CfgEval<'_> { +impl MutVisitor for CfgEval<'_, '_> { fn visit_expr(&mut self, expr: &mut P) { self.cfg.configure_expr(expr); mut_visit::noop_visit_expr(expr, self); diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 0da2c1c102..1bb050a40c 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,6 +1,6 @@ use crate::cfg_eval::cfg_eval; -use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{self as ast, attr, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_feature::AttributeTemplate; @@ -26,32 +26,39 @@ impl MultiItemModifier for Expander { return ExpandResult::Ready(vec![item]); } - let template = - AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; - let attr = ecx.attribute(meta_item.clone()); - validate_attr::check_builtin_attribute(&sess.parse_sess, &attr, sym::derive, template); + let result = + ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { + let template = + AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; + let attr = attr::mk_attr_outer(meta_item.clone()); + validate_attr::check_builtin_attribute( + &sess.parse_sess, + &attr, + sym::derive, + template, + ); - let derives: Vec<_> = attr - .meta_item_list() - .unwrap_or_default() - .into_iter() - .filter_map(|nested_meta| match nested_meta { - NestedMetaItem::MetaItem(meta) => Some(meta), - NestedMetaItem::Literal(lit) => { - // Reject `#[derive("Debug")]`. - report_unexpected_literal(sess, &lit); - None - } - }) - .map(|meta| { - // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths. - report_path_args(sess, &meta); - meta.path - }) - .collect(); + attr.meta_item_list() + .unwrap_or_default() + .into_iter() + .filter_map(|nested_meta| match nested_meta { + NestedMetaItem::MetaItem(meta) => Some(meta), + NestedMetaItem::Literal(lit) => { + // Reject `#[derive("Debug")]`. + report_unexpected_literal(sess, &lit); + None + } + }) + .map(|meta| { + // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths. + report_path_args(sess, &meta); + meta.path + }) + .map(|path| (path, None)) + .collect() + }); - // FIXME: Try to cache intermediate results to avoid collecting same paths multiple times. - match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) { + match result { Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)), Err(Indeterminate) => ExpandResult::Retry(item), } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 79f35ad581..54ab88dc3f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -15,10 +15,12 @@ pub fn expand_deriving_eq( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { + let span = cx.with_def_site_ctxt(span); let inline = cx.meta_word(span, sym::inline); let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span)); let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]); - let attrs = vec![cx.attribute(inline), cx.attribute(doc)]; + let no_coverage = cx.meta_word(span, sym::no_coverage); + let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)]; let trait_def = TraitDef { span, attributes: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index da85cc73ff..a3decff3ae 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -541,7 +541,7 @@ impl<'a> TraitDef<'a> { self.generics.to_generics(cx, self.span, type_ident, generics); // Create the generic parameters - params.extend(generics.params.iter().map(|param| match param.kind { + params.extend(generics.params.iter().map(|param| match ¶m.kind { GenericParamKind::Lifetime { .. } => param.clone(), GenericParamKind::Type { .. } => { // I don't think this can be moved out of the loop, since @@ -561,7 +561,18 @@ impl<'a> TraitDef<'a> { cx.typaram(self.span, param.ident, vec![], bounds, None) } - GenericParamKind::Const { .. } => param.clone(), + GenericParamKind::Const { ty, kw_span, .. } => { + let const_nodefault_kind = GenericParamKind::Const { + ty: ty.clone(), + kw_span: kw_span.clone(), + + // We can't have default values inside impl block + default: None, + }; + let mut param_clone = param.clone(); + param_clone.kind = const_nodefault_kind; + param_clone + } })); // and similarly for where clauses @@ -1034,7 +1045,7 @@ impl<'a> MethodDef<'a> { // make a series of nested matches, to destructure the // structs. This is actually right-to-left, but it shouldn't // matter. - for (arg_expr, pat) in self_args.iter().zip(patterns) { + for (arg_expr, pat) in iter::zip(self_args, patterns) { body = cx.expr_match( trait_.span, arg_expr.clone(), @@ -1351,7 +1362,7 @@ impl<'a> MethodDef<'a> { let mut discriminant_test = cx.expr_bool(sp, true); let mut first_ident = None; - for (&ident, self_arg) in vi_idents.iter().zip(&self_args) { + for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) { let self_addr = cx.expr_addr_of(sp, self_arg.clone()); let variant_value = deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]); @@ -1571,9 +1582,7 @@ impl<'a> TraitDef<'a> { let subpats = self.create_subpatterns(cx, paths, mutbl, use_temporaries); let pattern = match *struct_def { VariantData::Struct(..) => { - let field_pats = subpats - .into_iter() - .zip(&ident_exprs) + let field_pats = iter::zip(subpats, &ident_exprs) .map(|(pat, &(sp, ident, ..))| { if ident.is_none() { cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 9b43c11f0f..a97cac7e51 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -14,31 +14,31 @@ pub fn expand( ecx: &mut ExtCtxt<'_>, _span: Span, meta_item: &ast::MetaItem, - mut item: Annotatable, + item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator); - let not_static = |item: Annotatable| { + let orig_item = item.clone(); + let not_static = || { ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics"); - vec![item] + vec![orig_item.clone()] }; - let orig_item = item.clone(); - let mut is_stmt = false; // Allow using `#[global_allocator]` on an item statement - if let Annotatable::Stmt(stmt) = &item { - if let StmtKind::Item(item_) = &stmt.kind { - item = Annotatable::Item(item_.clone()); - is_stmt = true; - } - } - - let item = match item { + // FIXME - if we get deref patterns, use them to reduce duplication here + let (item, is_stmt) = match &item { Annotatable::Item(item) => match item.kind { - ItemKind::Static(..) => item, - _ => return not_static(Annotatable::Item(item)), + ItemKind::Static(..) => (item, false), + _ => return not_static(), + }, + Annotatable::Stmt(stmt) => match &stmt.kind { + StmtKind::Item(item_) => match item_.kind { + ItemKind::Static(..) => (item_, true), + _ => return not_static(), + }, + _ => return not_static(), }, - _ => return not_static(item), + _ => return not_static(), }; // Generate a bunch of new items using the AllocFnFactory diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index a46a5502b2..d7926ed0e0 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -7,8 +7,9 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![recursion_limit = "256"] diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 28e8259784..c8a7ff67b4 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -142,7 +142,7 @@ fn entry_point_type(sess: &Session, item: &ast::Item, depth: usize) -> EntryPoin ast::ItemKind::Fn(..) => { if sess.contains_name(&item.attrs, sym::start) { EntryPointType::Start - } else if sess.contains_name(&item.attrs, sym::main) { + } else if sess.contains_name(&item.attrs, sym::rustc_main) { EntryPointType::MainAttr } else if item.ident.name == sym::main { if depth == 1 { @@ -187,7 +187,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { let attrs = attrs .into_iter() .filter(|attr| { - !self.sess.check_name(attr, sym::main) + !self.sess.check_name(attr, sym::rustc_main) && !self.sess.check_name(attr, sym::start) }) .chain(iter::once(allow_dead_code)) @@ -220,7 +220,7 @@ fn generate_test_harness( let expn_id = ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::TestHarness, - &[sym::main, sym::test, sym::rustc_attrs], + &[sym::test, sym::rustc_attrs], None, ); let def_site = DUMMY_SP.with_def_site_ctxt(expn_id); @@ -247,7 +247,7 @@ fn generate_test_harness( /// By default this expands to /// /// ``` -/// #[main] +/// #[rustc_main] /// pub fn main() { /// extern crate test; /// test::test_main_static(&[ @@ -297,8 +297,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None))); - // #[main] - let main_meta = ecx.meta_word(sp, sym::main); + // #[rustc_main] + let main_meta = ecx.meta_word(sp, sym::rustc_main); let main_attr = ecx.attribute(main_meta); // pub fn main() { ... } diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml deleted file mode 100644 index 8c94a0aa5e..0000000000 --- a/compiler/rustc_codegen_cranelift/.github/workflows/bootstrap_rustc.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Bootstrap rustc using cg_clif - -on: - - push - -jobs: - bootstrap_rustc: - runs-on: ubuntu-latest - - 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" - ./prepare.sh - - - name: Test - run: | - # Enable backtraces for easier debugging - export RUST_BACKTRACE=1 - - ./scripts/test_bootstrap.sh diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index e6d3375fb1..2ac516381c 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -7,11 +7,18 @@ on: jobs: build: runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + - os: macos-latest + # cross-compile from Linux to Windows using mingw + - os: ubuntu-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - uses: actions/checkout@v2 @@ -36,6 +43,12 @@ jobs: path: target key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + - name: Install MinGW toolchain and wine + if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + run: | + sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable + rustup target add x86_64-pc-windows-gnu + - name: Prepare dependencies run: | git config --global user.email "user@example.com" @@ -43,6 +56,8 @@ jobs: ./prepare.sh - name: Test + env: + TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} run: | # Enable backtraces for easier debugging export RUST_BACKTRACE=1 @@ -51,12 +66,16 @@ jobs: export COMPILE_RUNS=2 export RUN_RUNS=2 + # Enable extra checks + export CG_CLIF_ENABLE_VERIFIER=1 + ./test.sh - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build - name: Upload prebuilt cg_clif + if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' uses: actions/upload-artifact@v2 with: name: cg_clif-${{ runner.os }} diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml new file mode 100644 index 0000000000..e01a92598b --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml @@ -0,0 +1,82 @@ +name: Various rustc tests + +on: + - push + +jobs: + bootstrap_rustc: + runs-on: ubuntu-latest + + 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" + ./prepare.sh + + - name: Test + run: | + # Enable backtraces for easier debugging + export RUST_BACKTRACE=1 + + ./scripts/test_bootstrap.sh + rustc_test_suite: + runs-on: ubuntu-latest + + 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" + ./prepare.sh + + - name: Test + run: | + # Enable backtraces for easier debugging + export RUST_BACKTRACE=1 + + ./scripts/test_rustc_tests.sh diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json index a13d5931ff..0cd576e160 100644 --- a/compiler/rustc_codegen_cranelift/.vscode/settings.json +++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json @@ -2,7 +2,7 @@ // source for rustc_* is not included in the rust-src component; disable the errors about this "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "macro-error"], "rust-analyzer.assist.importMergeBehavior": "last", - "rust-analyzer.cargo.loadOutDirsFromCheck": true, + "rust-analyzer.cargo.runBuildScripts": true, "rust-analyzer.linkedProjects": [ "./Cargo.toml", //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 76d9f0d27c..dc1cd336e1 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -39,16 +39,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "byteorder", "cranelift-bforest", @@ -65,8 +65,8 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -74,18 +74,18 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" [[package]] name = "cranelift-entity" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" [[package]] name = "cranelift-frontend" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-codegen", "log", @@ -95,8 +95,8 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "anyhow", "cranelift-codegen", @@ -113,8 +113,8 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "anyhow", "cranelift-codegen", @@ -125,8 +125,8 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "cranelift-codegen", "target-lexicon", @@ -134,8 +134,8 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.72.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0" dependencies = [ "anyhow", "cranelift-codegen", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 9861af1f8e..60946ab280 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -16,7 +16,7 @@ cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime/", branch cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" } target-lexicon = "0.11.0" gimli = { version = "0.23.0", default-features = false, features = ["write"]} -object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "write", "coff", "elf", "macho", "pe"] } +object = { version = "0.23.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" @@ -75,3 +75,6 @@ debug = false [profile.release.package.syn] opt-level = 0 debug = false + +[package.metadata.rust-analyzer] +rustc_private = true diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 6fa5eebdc2..ffe1d9a1e6 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -34,70 +34,19 @@ rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo bui 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`). -### Cargo - In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo.sh run -``` - -This should build and run your project with rustc_codegen_cranelift instead of the usual LLVM backend. - -### Rustc - -> You should prefer using the Cargo method. - -```bash -$ $cg_clif_dir/build/bin/cg_clif my_crate.rs -``` - -### Jit mode - -In jit mode cg_clif will immediately execute your code without creating an executable file. - -> This requires all dependencies to be available as dynamic library. -> The jit mode will probably need cargo integration to make this possible. - -```bash -$ $cg_clif_dir/build/cargo.sh jit -``` - -or - -```bash -$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs -``` - -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. - -```bash -$ $cg_clif_dir/build/cargo.sh lazy-jit +$ $cg_clif_dir/build/cargo.sh build ``` -### Shell - -These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit. - -```bash -function jit_naked() { - echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic -} - -function jit() { - jit_naked "fn main() { $@ }" -} +This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. -function jit_calc() { - jit 'println!("0x{:x}", ' $@ ');'; -} -``` +For additional ways to use rustc_codegen_cranelift like the JIT mode see [usage.md](docs/usage.md). ## Env vars -[see env_vars.md](docs/env_vars.md) +See [env_vars.md](docs/env_vars.md) for all env vars used by rustc_codegen_cranelift. ## Not yet supported @@ -106,3 +55,20 @@ function jit_calc() { `llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You have to specify specific registers instead. * SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work) + +## 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 shall be dual licensed as above, without any +additional terms or conditions. diff --git a/compiler/rustc_codegen_cranelift/build.sh b/compiler/rustc_codegen_cranelift/build.sh index 090349e54b..76bc188433 100755 --- a/compiler/rustc_codegen_cranelift/build.sh +++ b/compiler/rustc_codegen_cranelift/build.sh @@ -55,6 +55,7 @@ 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 @@ -64,12 +65,18 @@ case "$build_sysroot" in ;; "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/ ;; *) diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index a7650ab995..09c5d7590a 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock @@ -16,9 +16,9 @@ dependencies = [ [[package]] name = "adler" -version = "0.2.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -110,9 +110,9 @@ 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" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -132,18 +132,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" dependencies = [ "rustc-std-workspace-core", ] [[package]] name = "miniz_oxide" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", "autocfg", diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh index 636aa5f3f3..0354304e55 100755 --- a/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh +++ b/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh @@ -28,7 +28,7 @@ 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=2" cargo build --target "$TARGET_TRIPLE" --release + CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target "$TARGET_TRIPLE" --release else sysroot_channel='debug' cargo build --target "$TARGET_TRIPLE" diff --git a/compiler/rustc_codegen_cranelift/docs/env_vars.md b/compiler/rustc_codegen_cranelift/docs/env_vars.md index f0a0a6ad42..f7fde1b4f3 100644 --- a/compiler/rustc_codegen_cranelift/docs/env_vars.md +++ b/compiler/rustc_codegen_cranelift/docs/env_vars.md @@ -8,5 +8,8 @@ to make it possible to use incremental mode for all analyses performed by rustc without caching object files when their content should have been changed by a change to cg_clif.
CG_CLIF_DISPLAY_CG_TIME
-
If "1", display the time it took to perform codegen for a crate
+
If "1", display the time it took to perform codegen for a crate.
+
CG_CLIF_ENABLE_VERIFIER
+
Enable the Cranelift ir verifier for all compilation passes. If not set it will only run once + before passing the clif ir to Cranelift for compilation. diff --git a/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md new file mode 100644 index 0000000000..3eee3b554e --- /dev/null +++ b/compiler/rustc_codegen_cranelift/docs/usage.md @@ -0,0 +1,66 @@ +# Usage + +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`). + +## Cargo + +In the directory with your project (where you can do the usual `cargo build`), run: + +```bash +$ $cg_clif_dir/build/cargo.sh build +``` + +This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. + +## Rustc + +> You should prefer using the Cargo method. + +```bash +$ $cg_clif_dir/build/bin/cg_clif my_crate.rs +``` + +## Jit mode + +In jit mode cg_clif will immediately execute your code without creating an executable file. + +> This requires all dependencies to be available as dynamic library. +> The jit mode will probably need cargo integration to make this possible. + +```bash +$ $cg_clif_dir/build/cargo.sh jit +``` + +or + +```bash +$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs +``` + +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. + +```bash +$ $cg_clif_dir/build/cargo.sh lazy-jit +``` + +## Shell + +These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit. + +```bash +function jit_naked() { + echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic +} + +function jit() { + jit_naked "fn main() { $@ }" +} + +function jit_calc() { + jit 'println!("0x{:x}", ' $@ ');'; +} +``` diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 7c6d7fc106..c4834c8040 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -621,6 +621,7 @@ struct PanicLocation { } #[no_mangle] +#[cfg(not(windows))] pub fn get_tls() -> u8 { #[thread_local] static A: u8 = 42; diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 237f4d11d5..ea37ca98b5 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -1,7 +1,4 @@ -#![feature( - no_core, start, lang_items, box_syntax, never_type, linkage, - extern_types, thread_local -)] +#![feature(no_core, lang_items, box_syntax, never_type, linkage, extern_types, thread_local)] #![no_core] #![allow(dead_code, non_camel_case_types)] @@ -239,7 +236,7 @@ fn main() { assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); - #[cfg(not(jit))] + #[cfg(not(any(jit, windows)))] { extern { #[linkage = "extern_weak"] @@ -292,7 +289,7 @@ fn main() { from_decimal_string(); - #[cfg(not(jit))] + #[cfg(not(any(jit, windows)))] test_tls(); #[cfg(all(not(jit), target_os = "linux"))] diff --git a/compiler/rustc_codegen_cranelift/prepare.sh b/compiler/rustc_codegen_cranelift/prepare.sh index ee995ffcfa..64c097261c 100755 --- a/compiler/rustc_codegen_cranelift/prepare.sh +++ b/compiler/rustc_codegen_cranelift/prepare.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash set -e -rustup component add rust-src rustc-dev llvm-tools-preview ./build_sysroot/prepare_sysroot_src.sh cargo install hyperfine || echo "Skipping hyperfine install" diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 908ca52135..2917fc7ee3 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1 +1,3 @@ -nightly-2021-03-05 +[toolchain] +channel = "nightly-2021-03-29" +components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.sh b/compiler/rustc_codegen_cranelift/scripts/cargo.sh index 669d2d45b7..1daa5a78f7 100755 --- a/compiler/rustc_codegen_cranelift/scripts/cargo.sh +++ b/compiler/rustc_codegen_cranelift/scripts/cargo.sh @@ -4,7 +4,7 @@ dir=$(dirname "$0") source "$dir/config.sh" # read nightly compiler from rust-toolchain file -TOOLCHAIN=$(cat "$dir/rust-toolchain") +TOOLCHAIN=$(cat "$dir/rust-toolchain" | grep channel | sed "s/channel = \"\(.*\)\"/\1/") cmd=$1 shift || true diff --git a/compiler/rustc_codegen_cranelift/scripts/config.sh b/compiler/rustc_codegen_cranelift/scripts/config.sh index c2ed2bf256..99b302ee1d 100644 --- a/compiler/rustc_codegen_cranelift/scripts/config.sh +++ b/compiler/rustc_codegen_cranelift/scripts/config.sh @@ -2,15 +2,7 @@ set -e -unamestr=$(uname) -if [[ "$unamestr" == 'Linux' || "$unamestr" == 'FreeBSD' ]]; then - dylib_ext='so' -elif [[ "$unamestr" == 'Darwin' ]]; then - dylib_ext='dylib' -else - echo "Unsupported os" - exit 1 -fi +dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -) if echo "$RUSTC_WRAPPER" | grep sccache; then echo @@ -24,10 +16,10 @@ 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/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$dir +'-Zcodegen-backend='$dir'/lib/'$dylib' --sysroot '$dir # FIXME fix `#[linkage = "extern_weak"]` without this -if [[ "$unamestr" == 'Darwin' ]]; then +if [[ "$(uname)" == 'Darwin' ]]; then export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" fi diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index 694945a87c..fa7557653d 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -8,7 +8,7 @@ case $1 in echo "=> Installing new nightly" rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists - echo "nightly-${TOOLCHAIN}" > rust-toolchain + sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain rustup component add rustfmt || true echo "=> Uninstalling all old nighlies" diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh new file mode 100644 index 0000000000..e8bedf625f --- /dev/null +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -0,0 +1,68 @@ +#!/bin/bash +set -e + +./build.sh +source build/config.sh + +echo "[SETUP] Rust fork" +git clone https://github.com/rust-lang/rust.git || true +pushd rust +git fetch +git checkout -- . +git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" + +git apply - < config.toml < config.toml < res.txt - diff -u res.txt examples/regexdna-output.txt + ../build/cargo.sh 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 \ + | grep -v "Spawned thread" > res.txt + diff -u res.txt examples/regexdna-output.txt + fi - echo "[TEST] rust-lang/regex tests" - ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + 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 + else + echo "[AOT] rust-lang/regex tests" + ../build/cargo.sh build --tests --target $TARGET_TRIPLE + fi popd } diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs index c3cf90e1e7..5fbaed7283 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs @@ -11,9 +11,11 @@ use cranelift_codegen::entity::EntityRef; use crate::prelude::*; pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { - fx.add_global_comment( - "kind loc.idx param pass mode ty".to_string(), - ); + if fx.clif_comments.enabled() { + fx.add_global_comment( + "kind loc.idx param pass mode ty".to_string(), + ); + } } pub(super) fn add_arg_comment<'tcx>( @@ -25,6 +27,10 @@ pub(super) fn add_arg_comment<'tcx>( arg_abi_mode: PassMode, arg_layout: TyAndLayout<'tcx>, ) { + if !fx.clif_comments.enabled() { + return; + } + let local = if let Some(local) = local { Cow::Owned(format!("{:?}", local)) } else { @@ -59,10 +65,12 @@ pub(super) fn add_arg_comment<'tcx>( } pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { - fx.add_global_comment(String::new()); - fx.add_global_comment( - "kind local ty size align (abi,pref)".to_string(), - ); + if fx.clif_comments.enabled() { + fx.add_global_comment(String::new()); + fx.add_global_comment( + "kind local ty size align (abi,pref)".to_string(), + ); + } } pub(super) fn add_local_place_comments<'tcx>( @@ -70,6 +78,9 @@ pub(super) fn add_local_place_comments<'tcx>( place: CPlace<'tcx>, local: Local, ) { + if !fx.clif_comments.enabled() { + return; + } let TyAndLayout { ty, layout } = place.layout(); let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } = layout; @@ -90,7 +101,7 @@ pub(super) fn add_local_place_comments<'tcx>( } else { Cow::Borrowed("") }; - match ptr.base_and_offset() { + match ptr.debug_base_and_offset() { (crate::pointer::PointerBase::Addr(addr), offset) => { ("reuse", format!("storage={}{}{}", addr, offset, meta).into()) } diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index b158d73f3a..0e7829eaa2 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -1,6 +1,5 @@ //! Handling of everything related to the calling convention. Also fills `fx.local_map`. -#[cfg(debug_assertions)] mod comments; mod pass_mode; mod returning; @@ -75,8 +74,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { let func_id = import_function(self.tcx, self.cx.module, inst); let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func); - #[cfg(debug_assertions)] - self.add_comment(func_ref, format!("{:?}", inst)); + if self.clif_comments.enabled() { + self.add_comment(func_ref, format!("{:?}", inst)); + } func_ref } @@ -92,8 +92,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { let func_id = self.cx.module.declare_function(&name, Linkage::Import, &sig).unwrap(); let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func); let call_inst = self.bcx.ins().call(func_ref, args); - #[cfg(debug_assertions)] - { + if self.clif_comments.enabled() { self.add_comment(call_inst, format!("easy_call {}", name)); } let results = self.bcx.inst_results(call_inst); @@ -149,7 +148,6 @@ fn make_local_place<'tcx>( CPlace::new_stack_slot(fx, layout) }; - #[cfg(debug_assertions)] self::comments::add_local_place_comments(fx, place, local); place @@ -163,7 +161,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ let ssa_analyzed = crate::analyze::analyze(fx); - #[cfg(debug_assertions)] self::comments::add_args_header_comment(fx); let mut block_params_iter = fx.bcx.func.dfg.block_params(start_block).to_vec().into_iter(); @@ -228,7 +225,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ fx.fn_abi = Some(fn_abi); assert!(block_params_iter.next().is_none(), "arg_value left behind"); - #[cfg(debug_assertions)] self::comments::add_locals_header_comment(fx); for (local, arg_kind, ty) in func_params { @@ -256,7 +252,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ CPlace::for_ptr(addr, val.layout()) }; - #[cfg(debug_assertions)] self::comments::add_local_place_comments(fx, place, local); assert_eq!(fx.local_map.push(place), local); @@ -392,8 +387,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let (func_ref, first_arg) = match instance { // Trait object call Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => { - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { let nop_inst = fx.bcx.ins().nop(); fx.add_comment( nop_inst, @@ -414,8 +408,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( // Indirect call None => { - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { let nop_inst = fx.bcx.ins().nop(); fx.add_comment(nop_inst, "indirect call"); } @@ -477,10 +470,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( // FIXME find a cleaner way to support varargs if fn_sig.c_variadic { if !matches!(fn_sig.abi, Abi::C { .. }) { - fx.tcx.sess.span_fatal( - span, - &format!("Variadic call for non-C abi {:?}", fn_sig.abi), - ); + fx.tcx.sess.span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi)); } let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); let abi_params = call_args diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index d58f952f53..7c27596519 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -208,7 +208,7 @@ pub(super) fn from_casted_value<'tcx>( }); let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0)); let mut offset = 0; - let mut block_params_iter = block_params.into_iter().copied(); + let mut block_params_iter = block_params.iter().copied(); for param in abi_params { let val = ptr.offset_i64(fx, offset).store( fx, @@ -248,8 +248,8 @@ pub(super) fn adjust_arg_for_abi<'tcx>( /// as necessary. pub(super) fn cvalue_for_param<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] local: Option, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] local_field: Option, + local: Option, + local_field: Option, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, block_params_iter: &mut impl Iterator, ) -> Option> { @@ -263,7 +263,6 @@ pub(super) fn cvalue_for_param<'tcx>( }) .collect::>(); - #[cfg(debug_assertions)] crate::abi::comments::add_arg_comment( fx, "arg", diff --git a/compiler/rustc_codegen_cranelift/src/abi/returning.rs b/compiler/rustc_codegen_cranelift/src/abi/returning.rs index 9fa066df69..e1c53224b4 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/returning.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/returning.rs @@ -84,10 +84,6 @@ pub(super) fn codegen_return_param<'tcx>( } }; - #[cfg(not(debug_assertions))] - let _ = ret_param; - - #[cfg(debug_assertions)] crate::abi::comments::add_arg_comment( fx, "ret", @@ -146,7 +142,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx, T>( let results = fx .bcx .inst_results(call_inst) - .into_iter() + .iter() .copied() .collect::>(); let result = diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index efb64233ef..f60645a9f9 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -3,6 +3,7 @@ use crate::prelude::*; +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_span::symbol::sym; @@ -92,7 +93,7 @@ fn codegen_inner( bcx.finalize(); } module - .define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {}) + .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {}) .unwrap(); unwind_context.add_function(func_id, &ctx, module.isa()); } @@ -132,7 +133,7 @@ fn codegen_inner( bcx.finalize(); } module - .define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {}) + .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {}) .unwrap(); unwind_context.add_function(func_id, &ctx, module.isa()); } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 8b5ae9e054..b34a29c25b 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -1,5 +1,6 @@ //! Codegen of a single function +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiExt; @@ -7,11 +8,7 @@ use rustc_target::abi::call::FnAbi; use crate::prelude::*; -pub(crate) fn codegen_fn<'tcx>( - cx: &mut crate::CodegenCx<'_, 'tcx>, - instance: Instance<'tcx>, - linkage: Linkage, -) { +pub(crate) fn codegen_fn<'tcx>(cx: &mut crate::CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) { let tcx = cx.tcx; let _inst_guard = @@ -23,7 +20,7 @@ pub(crate) fn codegen_fn<'tcx>( // Declare function let name = tcx.symbol_name(instance).name.to_string(); let sig = get_function_sig(tcx, cx.module.isa().triple(), instance); - let func_id = cx.module.declare_function(&name, linkage, &sig).unwrap(); + let func_id = cx.module.declare_function(&name, Linkage::Local, &sig).unwrap(); cx.cached_context.clear(); @@ -131,7 +128,7 @@ pub(crate) fn codegen_fn<'tcx>( let module = &mut cx.module; tcx.sess.time("define function", || { module - .define_function(func_id, context, &mut cranelift_codegen::binemit::NullTrapSink {}) + .define_function(func_id, context, &mut NullTrapSink {}, &mut NullStackMapSink {}) .unwrap() }); @@ -219,8 +216,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { codegen_stmt(fx, block, stmt); } - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { let mut terminator_head = "\n".to_string(); bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap(); let inst = fx.bcx.func.layout.last_inst(block).unwrap(); @@ -433,12 +429,14 @@ fn codegen_stmt<'tcx>( fx.set_debug_loc(stmt.source_info); - #[cfg(false_debug_assertions)] + #[cfg(disabled)] match &stmt.kind { StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful _ => { - let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap(); - fx.add_comment(inst, format!("{:?}", stmt)); + if fx.clif_comments.enabled() { + let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap(); + fx.add_comment(inst, format!("{:?}", stmt)); + } } } @@ -464,16 +462,16 @@ fn codegen_stmt<'tcx>( let val = crate::constant::codegen_tls_ref(fx, def_id, lval.layout()); lval.write_cvalue(fx, val); } - Rvalue::BinaryOp(bin_op, box (ref lhs, ref rhs)) => { - let lhs = codegen_operand(fx, lhs); - let rhs = codegen_operand(fx, rhs); + Rvalue::BinaryOp(bin_op, ref lhs_rhs) => { + let lhs = codegen_operand(fx, &lhs_rhs.0); + let rhs = codegen_operand(fx, &lhs_rhs.1); let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs); lval.write_cvalue(fx, res); } - Rvalue::CheckedBinaryOp(bin_op, box (ref lhs, ref rhs)) => { - let lhs = codegen_operand(fx, lhs); - let rhs = codegen_operand(fx, rhs); + Rvalue::CheckedBinaryOp(bin_op, ref lhs_rhs) => { + let lhs = codegen_operand(fx, &lhs_rhs.0); + let rhs = codegen_operand(fx, &lhs_rhs.1); let res = if !fx.tcx.sess.overflow_checks() { let val = @@ -659,7 +657,9 @@ fn codegen_stmt<'tcx>( .val .try_to_bits(fx.tcx.data_layout.pointer_size) .unwrap(); - if fx.clif_type(operand.layout().ty) == Some(types::I8) { + if operand.layout().size.bytes() == 0 { + // Do nothing for ZST's + } else if fx.clif_type(operand.layout().ty) == Some(types::I8) { let times = fx.bcx.ins().iconst(fx.pointer_type, times as i64); // FIXME use emit_small_memset where possible let addr = lval.to_ptr().get_addr(fx); @@ -832,25 +832,18 @@ fn codegen_stmt<'tcx>( } } StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"), - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { - src, - dst, - count, - }) => { - let dst = codegen_operand(fx, dst); + StatementKind::CopyNonOverlapping(inner) => { + let dst = codegen_operand(fx, &inner.dst); let pointee = dst - .layout() - .pointee_info_at(fx, rustc_target::abi::Size::ZERO) - .expect("Expected pointer"); + .layout() + .pointee_info_at(fx, rustc_target::abi::Size::ZERO) + .expect("Expected pointer"); let dst = dst.load_scalar(fx); - let src = codegen_operand(fx, src).load_scalar(fx); - let count = codegen_operand(fx, count).load_scalar(fx); + let src = codegen_operand(fx, &inner.src).load_scalar(fx); + let count = codegen_operand(fx, &inner.count).load_scalar(fx); let elem_size: u64 = pointee.size.bytes(); - let bytes = if elem_size != 1 { - fx.bcx.ins().imul_imm(count, elem_size as i64) - } else { - count - }; + let bytes = + if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, bytes); } } diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index ae75e6508c..ffe1922ab9 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -32,18 +32,56 @@ pub(crate) fn maybe_codegen<'tcx>( BinOp::Add | BinOp::Sub if !checked => None, BinOp::Mul if !checked => { let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + if fx.tcx.sess.target.is_like_windows { + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + let args = + [ret_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + fx.lib_call( + "__multi3", + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::new(pointer_ty(fx.tcx)), + ], + vec![], + &args, + ); + Some(ret_place.to_cvalue(fx)) + } else { + Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + } } BinOp::Add | BinOp::Sub | BinOp::Mul => { assert!(checked); let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); - let param_types = vec![ - AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), - AbiParam::new(types::I128), - AbiParam::new(types::I128), - ]; - let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let (param_types, args) = if fx.tcx.sess.target.is_like_windows { + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + ( + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::new(pointer_ty(fx.tcx)), + ], + [out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)], + ) + } else { + ( + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(types::I128), + AbiParam::new(types::I128), + ], + [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)], + ) + }; let name = match (bin_op, is_signed) { (BinOp::Add, false) => "__rust_u128_addo", (BinOp::Add, true) => "__rust_i128_addo", @@ -57,20 +95,33 @@ pub(crate) fn maybe_codegen<'tcx>( Some(out_place.to_cvalue(fx)) } BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), - BinOp::Div => { + BinOp::Div | BinOp::Rem => { assert!(!checked); - if is_signed { - Some(fx.easy_call("__divti3", &[lhs, rhs], fx.tcx.types.i128)) - } else { - Some(fx.easy_call("__udivti3", &[lhs, rhs], fx.tcx.types.u128)) - } - } - BinOp::Rem => { - assert!(!checked); - if is_signed { - Some(fx.easy_call("__modti3", &[lhs, rhs], fx.tcx.types.i128)) + let name = match (bin_op, is_signed) { + (BinOp::Div, false) => "__udivti3", + (BinOp::Div, true) => "__divti3", + (BinOp::Rem, false) => "__umodti3", + (BinOp::Rem, true) => "__modti3", + _ => unreachable!(), + }; + if fx.tcx.sess.target.is_like_windows { + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + let ret = fx.lib_call( + name, + vec![AbiParam::new(pointer_ty(fx.tcx)), AbiParam::new(pointer_ty(fx.tcx))], + vec![AbiParam::new(types::I64X2)], + &args, + )[0]; + // FIXME use bitcast instead of store to get from i64x2 to i128 + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); + Some(ret_place.to_cvalue(fx)) } else { - Some(fx.easy_call("__umodti3", &[lhs, rhs], fx.tcx.types.u128)) + Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty)) } } BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 6a4a6744a5..b5874f6253 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -361,8 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { let _ = self.cx.module.define_data(msg_id, &data_ctx); let local_msg_id = self.cx.module.declare_data_in_func(msg_id, self.bcx.func); - #[cfg(debug_assertions)] - { + if self.clif_comments.enabled() { self.add_comment(local_msg_id, msg); } self.bcx.ins().global_value(self.pointer_type, local_msg_id) diff --git a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs new file mode 100644 index 0000000000..177f850afb --- /dev/null +++ b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs @@ -0,0 +1,41 @@ +macro builtin_functions($register:ident; $(fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;)*) { + #[cfg(feature = "jit")] + #[allow(improper_ctypes)] + extern "C" { + $(fn $name($($arg_name: $arg_ty),*) -> $ret_ty;)* + } + + #[cfg(feature = "jit")] + pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) { + for &(name, val) in &[$((stringify!($name), $name as *const u8)),*] { + builder.symbol(name, val); + } + } +} + +builtin_functions! { + register_functions_for_jit; + + // integers + fn __multi3(a: i128, b: i128) -> i128; + fn __udivti3(n: u128, d: u128) -> u128; + fn __divti3(n: i128, d: i128) -> i128; + fn __umodti3(n: u128, d: u128) -> u128; + fn __modti3(n: i128, d: i128) -> i128; + fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool); + fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool); + fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool); + fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool); + fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool); + fn __rust_i128_mulo(a: i128, b: i128) -> (i128, bool); + + // floats + fn __floattisf(i: i128) -> f32; + fn __floattidf(i: i128) -> f64; + fn __floatuntisf(i: u128) -> f32; + fn __floatuntidf(i: u128) -> f64; + fn __fixsfti(f: f32) -> i128; + fn __fixdfti(f: f64) -> i128; + fn __fixunssfti(f: f32) -> u128; + fn __fixunsdfti(f: f64) -> u128; +} diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 9d93370b7d..fcd41c8446 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -45,9 +45,9 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool { }; match const_.val { ConstKind::Value(_) => {} - ConstKind::Unevaluated(def, ref substs, promoted) => { + ConstKind::Unevaluated(unevaluated) => { if let Err(err) = - fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) + fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { all_constants_ok = false; match err { @@ -85,8 +85,9 @@ pub(crate) fn codegen_tls_ref<'tcx>( ) -> CValue<'tcx> { let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("tls {:?}", def_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("tls {:?}", def_id)); + } let tls_ptr = fx.bcx.ins().tls_value(fx.pointer_type, local_data_id); CValue::by_val(tls_ptr, layout) } @@ -98,8 +99,9 @@ fn codegen_static_ref<'tcx>( ) -> CPlace<'tcx> { let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", def_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", def_id)); + } let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id); assert!(!layout.is_unsized(), "unsized statics aren't supported"); assert!( @@ -122,14 +124,16 @@ pub(crate) fn codegen_constant<'tcx>( }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, - ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => { + ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if fx.tcx.is_static(def.did) => + { assert!(substs.is_empty()); assert!(promoted.is_none()); return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx); } - ConstKind::Unevaluated(def, ref substs, promoted) => { - match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) { + ConstKind::Unevaluated(unevaluated) => { + match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { Ok(const_val) => const_val, Err(_) => { span_bug!(constant.span, "erroneous constant not captured by required_consts"); @@ -183,8 +187,9 @@ pub(crate) fn codegen_const_value<'tcx>( data_id_for_alloc_id(fx.cx.module, ptr.alloc_id, alloc.mutability); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id)); + 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)) => { @@ -199,8 +204,9 @@ pub(crate) fn codegen_const_value<'tcx>( let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", def_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", def_id)); + } fx.bcx.ins().global_value(fx.pointer_type, local_data_id) } None => bug!("missing allocation {:?}", ptr.alloc_id), @@ -241,8 +247,9 @@ fn pointer_for_allocation<'tcx>( let data_id = data_id_for_alloc_id(fx.cx.module, alloc_id, alloc.mutability); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(local_data_id, format!("{:?}", alloc_id)); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", alloc_id)); + } let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id); crate::pointer::Pointer::new(global_ptr) } diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs index 30ed356c76..8578ab33ce 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs @@ -39,11 +39,11 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] { #[cfg(unix)] { use std::os::unix::ffi::OsStrExt; - return path.as_bytes(); + path.as_bytes() } #[cfg(not(unix))] { - return path.to_str().unwrap().as_bytes(); + path.to_str().unwrap().as_bytes() } } diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index b87dcc4192..ed3bdedddc 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -119,11 +119,10 @@ fn module_codegen( tcx.sess.opts.debuginfo != DebugInfo::None, ); super::predefine_mono_items(&mut cx, &mono_items); - for (mono_item, (linkage, visibility)) in mono_items { - let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility); + for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst, linkage)); + cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst)); } MonoItem::Static(def_id) => { crate::constant::codegen_static(&mut cx.constants_cx, def_id) @@ -163,6 +162,21 @@ pub(super) fn run_aot( metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box<(CodegenResults, FxHashMap)> { + use rustc_span::symbol::sym; + + 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); + let windows_subsystem = subsystem.map(|subsystem| { + if subsystem != sym::windows && subsystem != sym::console { + tcx.sess.fatal(&format!( + "invalid windows subsystem `{}`, only \ + `windows` and `console` are allowed", + subsystem + )); + } + subsystem.to_string() + }); + let mut work_products = FxHashMap::default(); let cgus = if tcx.sess.opts.output_types.should_codegen() { @@ -280,7 +294,7 @@ pub(super) fn run_aot( allocator_module, metadata_module, metadata, - windows_subsystem: None, // Windows is not yet supported + windows_subsystem, linker_info: LinkerInfo::new(tcx), crate_info: CrateInfo::new(tcx), }, diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 245df03ffb..f585ebca9d 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -5,8 +5,10 @@ use std::cell::RefCell; use std::ffi::CString; use std::os::raw::{c_char, c_int}; +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; +use rustc_session::config::EntryFnType; use cranelift_jit::{JITBuilder, JITModule}; @@ -28,20 +30,11 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { let mut jit_builder = JITBuilder::with_isa(crate::build_isa(tcx.sess), cranelift_module::default_libcall_names()); jit_builder.hotswap(matches!(backend_config.codegen_mode, CodegenMode::JitLazy)); + crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); jit_builder.symbols(imported_symbols); let mut jit_module = JITModule::new(jit_builder); assert_eq!(pointer_ty(tcx), jit_module.target_config().pointer_type()); - let sig = Signature { - params: vec![ - AbiParam::new(jit_module.target_config().pointer_type()), - 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)), - }; - let main_func_id = jit_module.declare_function("main", Linkage::Import, &sig).unwrap(); - let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); let mono_items = cgus .iter() @@ -55,15 +48,12 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { super::time(tcx, "codegen mono items", || { super::predefine_mono_items(&mut cx, &mono_items); - for (mono_item, (linkage, visibility)) in mono_items { - let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility); + for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => match backend_config.codegen_mode { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { - cx.tcx - .sess - .time("codegen fn", || crate::base::codegen_fn(&mut cx, inst, linkage)); + cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst)); } CodegenMode::JitLazy => codegen_shim(&mut cx, inst), }, @@ -86,24 +76,17 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { tcx.sess.fatal("Inline asm is not supported in JIT mode"); } - crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context); crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context); tcx.sess.abort_if_errors(); jit_module.finalize_definitions(); - let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_module) }; - let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id); - println!( "Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed" ); - let f: extern "C" fn(c_int, *const *const c_char) -> c_int = - unsafe { ::std::mem::transmute(finalized_main) }; - let args = ::std::env::var("CG_CLIF_JIT_ARGS").unwrap_or_else(|_| String::new()); let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string()) .chain(args.split(' ')) @@ -118,12 +101,58 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { BACKEND_CONFIG.with(|tls_backend_config| { assert!(tls_backend_config.borrow_mut().replace(backend_config).is_none()) }); - CURRENT_MODULE - .with(|current_module| assert!(current_module.borrow_mut().replace(jit_module).is_none())); - let ret = f(args.len() as c_int, argv.as_ptr()); + let (main_def_id, entry_ty) = tcx.entry_fn(LOCAL_CRATE).unwrap(); + let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx); + + match entry_ty { + EntryFnType::Main => { + // FIXME set program arguments somehow - std::process::exit(ret); + let main_sig = Signature { + params: vec![], + returns: vec![], + call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), + }; + let main_func_id = jit_module + .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &main_sig) + .unwrap(); + let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id); + + CURRENT_MODULE.with(|current_module| { + assert!(current_module.borrow_mut().replace(jit_module).is_none()) + }); + + let f: extern "C" fn() = unsafe { ::std::mem::transmute(finalized_main) }; + f(); + std::process::exit(0); + } + EntryFnType::Start => { + let start_sig = Signature { + params: vec![ + AbiParam::new(jit_module.target_config().pointer_type()), + 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)), + }; + let start_func_id = jit_module + .declare_function(tcx.symbol_name(instance).name, Linkage::Import, &start_sig) + .unwrap(); + let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); + + CURRENT_MODULE.with(|current_module| { + assert!(current_module.borrow_mut().replace(jit_module).is_none()) + }); + + 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); + } + } } #[no_mangle] @@ -144,8 +173,7 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 jit_module.prepare_for_function_redefine(func_id).unwrap(); let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module, false); - tcx.sess - .time("codegen fn", || crate::base::codegen_fn(&mut cx, instance, Linkage::Export)); + tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance)); let (global_asm, _debug_context, unwind_context) = cx.finalize(); assert!(global_asm.is_empty()); @@ -220,7 +248,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { imported_symbols } -pub(super) fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) { +fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) { let tcx = cx.tcx; let pointer_type = cx.module.target_config().pointer_type(); @@ -267,7 +295,8 @@ pub(super) fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'t .define_function( func_id, &mut Context::for_function(trampoline), - &mut cranelift_codegen::binemit::NullTrapSink {}, + &mut NullTrapSink {}, + &mut NullStackMapSink {}, ) .unwrap(); } diff --git a/compiler/rustc_codegen_cranelift/src/driver/mod.rs b/compiler/rustc_codegen_cranelift/src/driver/mod.rs index b994f28ffe..d49182a07b 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/mod.rs @@ -44,13 +44,19 @@ fn predefine_mono_items<'tcx>( mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))], ) { cx.tcx.sess.time("predefine functions", || { + let is_compiler_builtins = cx.tcx.is_compiler_builtins(LOCAL_CRATE); for &(mono_item, (linkage, visibility)) in mono_items { match mono_item { MonoItem::Fn(instance) => { let name = cx.tcx.symbol_name(instance).name.to_string(); let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name)); let sig = get_function_sig(cx.tcx, cx.module.isa().triple(), instance); - let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility); + let linkage = crate::linkage::get_clif_linkage( + mono_item, + linkage, + visibility, + is_compiler_builtins, + ); cx.module.declare_function(&name, linkage, &sig).unwrap(); } MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {} diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 5b3df2bd38..1fb5e86aed 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -20,6 +20,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( if template.is_empty() { // Black box return; + } else if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + let true_ = fx.bcx.ins().iconst(types::I32, 1); + fx.bcx.ins().trapnz(true_, TrapCode::User(1)); + return; } let mut slot_size = Size::from_bytes(0); @@ -193,8 +197,9 @@ fn call_inline_asm<'tcx>( offset: None, size: u32::try_from(slot_size.bytes()).unwrap(), }); - #[cfg(debug_assertions)] - fx.add_comment(stack_slot, "inline asm scratch slot"); + if fx.clif_comments.enabled() { + fx.add_comment(stack_slot, "inline asm scratch slot"); + } let inline_asm_func = fx .cx @@ -210,8 +215,9 @@ fn call_inline_asm<'tcx>( ) .unwrap(); let inline_asm_func = fx.cx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func); - #[cfg(debug_assertions)] - fx.add_comment(inline_asm_func, asm_name); + if fx.clif_comments.enabled() { + fx.add_comment(inline_asm_func, asm_name); + } for (_reg, offset, value) in inputs { fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 86df71a0df..27fc2abedc 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -88,7 +88,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let idx_bytes = match idx_const { ConstValue::ByRef { alloc, offset } => { let ptr = Pointer::new(AllocId(0 /* dummy */), offset); - let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */); + let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */); alloc.get_bytes(fx, ptr, size).unwrap() } _ => unreachable!("{:?}", idx_const), @@ -277,5 +277,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // simd_select // simd_rem // simd_neg + // simd_trunc + // simd_floor } } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 8edb883ccb..720d2a1253 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -1,13 +1,4 @@ -#![feature( - rustc_private, - decl_macro, - type_alias_impl_trait, - associated_type_bounds, - never_type, - try_blocks, - box_patterns, - hash_drain_filter -)] +#![feature(rustc_private, decl_macro, never_type, hash_drain_filter)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] @@ -57,6 +48,7 @@ mod base; mod cast; mod codegen_i128; mod common; +mod compiler_builtins; mod constant; mod debuginfo; mod discriminant; @@ -224,8 +216,10 @@ pub struct CraneliftCodegenBackend { impl CodegenBackend for CraneliftCodegenBackend { fn init(&self, sess: &Session) { - if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode { - sess.warn("LTO is not supported. You may get a linker error."); + use rustc_session::config::Lto; + match sess.lto() { + Lto::No | Lto::ThinLocal => {} + Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."), } } @@ -240,9 +234,9 @@ impl CodegenBackend for CraneliftCodegenBackend { vec![] } - fn codegen_crate<'tcx>( + fn codegen_crate( &self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box { @@ -252,9 +246,7 @@ impl CodegenBackend for CraneliftCodegenBackend { BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) .unwrap_or_else(|err| tcx.sess.fatal(&err)) }; - let res = driver::codegen_crate(tcx, metadata, need_metadata_module, config); - - res + driver::codegen_crate(tcx, metadata, need_metadata_module, config) } fn join_codegen( @@ -300,9 +292,9 @@ fn build_isa(sess: &Session) -> Box { let mut flags_builder = settings::builder(); flags_builder.enable("is_pic").unwrap(); flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided - flags_builder - .set("enable_verifier", if cfg!(debug_assertions) { "true" } else { "false" }) - .unwrap(); + let enable_verifier = + cfg!(debug_assertions) || std::env::var("CG_CLIF_ENABLE_VERIFIER").is_ok(); + flags_builder.set("enable_verifier", if enable_verifier { "true" } else { "false" }).unwrap(); let tls_model = match target_triple.binary_format { BinaryFormat::Elf => "elf_gd", @@ -314,18 +306,17 @@ fn build_isa(sess: &Session) -> Box { flags_builder.set("enable_simd", "true").unwrap(); + flags_builder.set("enable_llvm_abi_extensions", "true").unwrap(); + use rustc_session::config::OptLevel; match sess.opts.optimize { OptLevel::No => { flags_builder.set("opt_level", "none").unwrap(); } OptLevel::Less | OptLevel::Default => {} - OptLevel::Aggressive => { + OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => { flags_builder.set("opt_level", "speed_and_size").unwrap(); } - OptLevel::Size | OptLevel::SizeMin => { - sess.warn("Optimizing for size is not supported. Just ignoring the request"); - } } let flags = settings::Flags::new(flags_builder); diff --git a/compiler/rustc_codegen_cranelift/src/linkage.rs b/compiler/rustc_codegen_cranelift/src/linkage.rs index dc1e2107ce..a564a59f72 100644 --- a/compiler/rustc_codegen_cranelift/src/linkage.rs +++ b/compiler/rustc_codegen_cranelift/src/linkage.rs @@ -6,8 +6,10 @@ pub(crate) fn get_clif_linkage( mono_item: MonoItem<'_>, linkage: RLinkage, visibility: Visibility, + is_compiler_builtins: bool, ) -> Linkage { match (linkage, visibility) { + (RLinkage::External, Visibility::Default) if is_compiler_builtins => Linkage::Hidden, (RLinkage::External, Visibility::Default) => Linkage::Export, (RLinkage::Internal, Visibility::Default) => Linkage::Local, (RLinkage::External, Visibility::Hidden) => Linkage::Hidden, diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index 62e551b186..dc86290b3f 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -1,3 +1,4 @@ +use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_hir::LangItem; use rustc_session::config::EntryFnType; @@ -12,7 +13,7 @@ pub(crate) fn maybe_create_entry_wrapper( ) { let (main_def_id, use_start_lang_item) = match tcx.entry_fn(LOCAL_CRATE) { Some((def_id, entry_ty)) => ( - def_id.to_def_id(), + def_id, match entry_ty { EntryFnType::Main => true, EntryFnType::Start => false, @@ -100,12 +101,8 @@ pub(crate) fn maybe_create_entry_wrapper( bcx.seal_all_blocks(); bcx.finalize(); } - m.define_function( - cmain_func_id, - &mut ctx, - &mut cranelift_codegen::binemit::NullTrapSink {}, - ) - .unwrap(); + m.define_function(cmain_func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {}) + .unwrap(); unwind_context.add_function(cmain_func_id, &ctx, m.isa()); } } diff --git a/compiler/rustc_codegen_cranelift/src/metadata.rs b/compiler/rustc_codegen_cranelift/src/metadata.rs index 190c4f45cc..dbdc8cbad4 100644 --- a/compiler/rustc_codegen_cranelift/src/metadata.rs +++ b/compiler/rustc_codegen_cranelift/src/metadata.rs @@ -1,10 +1,10 @@ //! Reading and writing of the rustc metadata for rlibs and dylibs -use std::convert::TryFrom; use std::fs::File; use std::path::Path; use rustc_codegen_ssa::METADATA_FILENAME; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::rustc_erase_owner; use rustc_data_structures::sync::MetadataRef; @@ -17,38 +17,43 @@ use crate::backend::WriteMetadata; pub(crate) struct CraneliftMetadataLoader; +fn load_metadata_with( + path: &Path, + f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>, +) -> Result { + let file = File::open(path).map_err(|e| format!("{:?}", e))?; + let data = unsafe { Mmap::map(file) }.map_err(|e| format!("{:?}", e))?; + let metadata = OwningRef::new(data).try_map(f)?; + return Ok(rustc_erase_owner!(metadata.map_owner_box())); +} + impl MetadataLoader for CraneliftMetadataLoader { fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result { - let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?); - // Iterate over all entries in the archive: - while let Some(entry_result) = archive.next_entry() { - let mut entry = entry_result.map_err(|e| format!("{:?}", e))?; - if entry.header().identifier() == METADATA_FILENAME.as_bytes() { - let mut buf = Vec::with_capacity( - usize::try_from(entry.header().size()) - .expect("Rlib metadata file too big to load into memory."), - ); - ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?; - let buf: OwningRef, [u8]> = OwningRef::new(buf); - return Ok(rustc_erase_owner!(buf.map_owner_box())); + load_metadata_with(path, |data| { + let archive = object::read::archive::ArchiveFile::parse(&*data) + .map_err(|e| format!("{:?}", e))?; + + for entry_result in archive.members() { + let entry = entry_result.map_err(|e| format!("{:?}", e))?; + if entry.name() == METADATA_FILENAME.as_bytes() { + return Ok(entry.data()); + } } - } - Err("couldn't find metadata entry".to_string()) + Err("couldn't find metadata entry".to_string()) + }) } fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result { use object::{Object, ObjectSection}; - let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?; - let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?; - let buf = file - .section_by_name(".rustc") - .ok_or("no .rustc section")? - .data() - .map_err(|e| format!("failed to read .rustc section: {:?}", e))? - .to_owned(); - let buf: OwningRef, [u8]> = OwningRef::new(buf); - Ok(rustc_erase_owner!(buf.map_owner_box())) + + load_metadata_with(path, |data| { + let file = object::File::parse(&data).map_err(|e| format!("parse: {:?}", e))?; + file.section_by_name(".rustc") + .ok_or("no .rustc section")? + .data() + .map_err(|e| format!("failed to read .rustc section: {:?}", e)) + }) } } diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index da49e1c6c9..2ebf30da2d 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -166,13 +166,11 @@ pub(crate) fn codegen_int_binop<'tcx>( BinOp::Shl => { let lhs_ty = fx.bcx.func.dfg.value_type(lhs); let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let actual_shift = clif_intcast(fx, actual_shift, types::I8, false); fx.bcx.ins().ishl(lhs, actual_shift) } BinOp::Shr => { let lhs_ty = fx.bcx.func.dfg.value_type(lhs); let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let actual_shift = clif_intcast(fx, actual_shift, types::I8, false); if signed { fx.bcx.ins().sshr(lhs, actual_shift) } else { @@ -387,7 +385,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>( let lhs = in_lhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx); - return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs); + codegen_compare_bin_op(fx, bin_op, false, lhs, rhs) } BinOp::Offset => { let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty; @@ -396,10 +394,10 @@ pub(crate) fn codegen_ptr_binop<'tcx>( let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64); let base_val = base.load_scalar(fx); let res = fx.bcx.ins().iadd(base_val, ptr_diff); - return CValue::by_val(res, base.layout()); + CValue::by_val(res, base.layout()) } _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs), - }; + } } else { let (lhs_ptr, lhs_extra) = in_lhs.load_scalar_pair(fx); let (rhs_ptr, rhs_extra) = in_rhs.load_scalar_pair(fx); diff --git a/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs b/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs index d111f37f5e..8bb02a3e55 100644 --- a/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs +++ b/compiler/rustc_codegen_cranelift/src/optimize/stack2reg.rs @@ -181,7 +181,6 @@ impl<'a> OptimizeContext<'a> { pub(super) fn optimize_function( ctx: &mut Context, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] clif_comments: &mut crate::pretty_clif::CommentWriter, ) { combine_stack_addr_with_load_store(&mut ctx.func); @@ -192,8 +191,7 @@ pub(super) fn optimize_function( remove_unused_stack_addr_and_stack_load(&mut opt_ctx); - #[cfg(debug_assertions)] - { + if clif_comments.enabled() { for (&OrdStackSlot(stack_slot), usage) in &opt_ctx.stack_slot_usage_map { clif_comments.add_comment(stack_slot, format!("used by: {:?}", usage)); } @@ -209,25 +207,27 @@ pub(super) fn optimize_function( for load in users.stack_load.clone().into_iter() { let potential_stores = users.potential_stores_for_load(&opt_ctx.ctx, load); - #[cfg(debug_assertions)] - for &store in &potential_stores { - clif_comments.add_comment( - load, - format!( - "Potential store -> load forwarding {} -> {} ({:?}, {:?})", - opt_ctx.ctx.func.dfg.display_inst(store, None), - opt_ctx.ctx.func.dfg.display_inst(load, None), - spatial_overlap(&opt_ctx.ctx.func, store, load), - temporal_order(&opt_ctx.ctx, store, load), - ), - ); + if clif_comments.enabled() { + for &store in &potential_stores { + clif_comments.add_comment( + load, + format!( + "Potential store -> load forwarding {} -> {} ({:?}, {:?})", + opt_ctx.ctx.func.dfg.display_inst(store, None), + opt_ctx.ctx.func.dfg.display_inst(load, None), + spatial_overlap(&opt_ctx.ctx.func, store, load), + temporal_order(&opt_ctx.ctx, store, load), + ), + ); + } } match *potential_stores { [] => { - #[cfg(debug_assertions)] - clif_comments - .add_comment(load, "[BUG?] Reading uninitialized memory".to_string()); + if clif_comments.enabled() { + clif_comments + .add_comment(load, "[BUG?] Reading uninitialized memory".to_string()); + } } [store] if spatial_overlap(&opt_ctx.ctx.func, store, load) == SpatialOverlap::Full @@ -237,9 +237,12 @@ pub(super) fn optimize_function( // Only one store could have been the origin of the value. let stored_value = opt_ctx.ctx.func.dfg.inst_args(store)[0]; - #[cfg(debug_assertions)] - clif_comments - .add_comment(load, format!("Store to load forward {} -> {}", store, load)); + if clif_comments.enabled() { + clif_comments.add_comment( + load, + format!("Store to load forward {} -> {}", store, load), + ); + } users.change_load_to_alias(&mut opt_ctx.ctx.func, load, stored_value); } @@ -250,33 +253,35 @@ pub(super) fn optimize_function( for store in users.stack_store.clone().into_iter() { let potential_loads = users.potential_loads_of_store(&opt_ctx.ctx, store); - #[cfg(debug_assertions)] - for &load in &potential_loads { - clif_comments.add_comment( - store, - format!( - "Potential load from store {} <- {} ({:?}, {:?})", - opt_ctx.ctx.func.dfg.display_inst(load, None), - opt_ctx.ctx.func.dfg.display_inst(store, None), - spatial_overlap(&opt_ctx.ctx.func, store, load), - temporal_order(&opt_ctx.ctx, store, load), - ), - ); + if clif_comments.enabled() { + for &load in &potential_loads { + clif_comments.add_comment( + store, + format!( + "Potential load from store {} <- {} ({:?}, {:?})", + opt_ctx.ctx.func.dfg.display_inst(load, None), + opt_ctx.ctx.func.dfg.display_inst(store, None), + spatial_overlap(&opt_ctx.ctx.func, store, load), + temporal_order(&opt_ctx.ctx, store, load), + ), + ); + } } if potential_loads.is_empty() { // Never loaded; can safely remove all stores and the stack slot. // FIXME also remove stores when there is always a next store before a load. - #[cfg(debug_assertions)] - clif_comments.add_comment( - store, - format!( - "Remove dead stack store {} of {}", - opt_ctx.ctx.func.dfg.display_inst(store, None), - stack_slot.0 - ), - ); + if clif_comments.enabled() { + clif_comments.add_comment( + store, + format!( + "Remove dead stack store {} of {}", + opt_ctx.ctx.func.dfg.display_inst(store, None), + stack_slot.0 + ), + ); + } users.remove_dead_store(&mut opt_ctx.ctx.func, store); } diff --git a/compiler/rustc_codegen_cranelift/src/pointer.rs b/compiler/rustc_codegen_cranelift/src/pointer.rs index 88a78f3214..31d827f83b 100644 --- a/compiler/rustc_codegen_cranelift/src/pointer.rs +++ b/compiler/rustc_codegen_cranelift/src/pointer.rs @@ -39,8 +39,7 @@ impl Pointer { Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) } } - #[cfg(debug_assertions)] - pub(crate) fn base_and_offset(self) -> (PointerBase, Offset32) { + pub(crate) fn debug_base_and_offset(self) -> (PointerBase, Offset32) { (self.base, self.offset) } diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 9c91b92e51..d22ea3772e 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -69,13 +69,15 @@ use crate::prelude::*; #[derive(Debug)] pub(crate) struct CommentWriter { + enabled: bool, global_comments: Vec, entity_comments: FxHashMap, } impl CommentWriter { pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { - let global_comments = if cfg!(debug_assertions) { + let enabled = should_write_ir(tcx); + let global_comments = if enabled { vec![ format!("symbol {}", tcx.symbol_name(instance).name), format!("instance {:?}", instance), @@ -86,13 +88,17 @@ impl CommentWriter { vec![] }; - CommentWriter { global_comments, entity_comments: FxHashMap::default() } + CommentWriter { enabled, global_comments, entity_comments: FxHashMap::default() } } } -#[cfg(debug_assertions)] impl CommentWriter { + pub(crate) fn enabled(&self) -> bool { + self.enabled + } + pub(crate) fn add_global_comment>(&mut self, comment: S) { + debug_assert!(self.enabled); self.global_comments.push(comment.into()); } @@ -101,6 +107,8 @@ impl CommentWriter { entity: E, comment: S, ) { + debug_assert!(self.enabled); + use std::collections::hash_map::Entry; match self.entity_comments.entry(entity.into()) { Entry::Occupied(mut occ) => { @@ -179,7 +187,6 @@ impl FuncWriter for &'_ CommentWriter { } } -#[cfg(debug_assertions)] impl FunctionCx<'_, '_, '_> { pub(crate) fn add_global_comment>(&mut self, comment: S) { self.clif_comments.add_global_comment(comment); @@ -198,8 +205,8 @@ pub(crate) fn should_write_ir(tcx: TyCtxt<'_>) -> bool { tcx.sess.opts.output_types.contains_key(&OutputType::LlvmAssembly) } -pub(crate) fn write_ir_file<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn write_ir_file( + tcx: TyCtxt<'_>, name: &str, write: impl FnOnce(&mut dyn Write) -> std::io::Result<()>, ) { @@ -217,10 +224,7 @@ pub(crate) fn write_ir_file<'tcx>( let clif_file_name = clif_output_dir.join(name); - let res: std::io::Result<()> = try { - let mut file = std::fs::File::create(clif_file_name)?; - write(&mut file)?; - }; + let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file)); if let Err(err) = res { tcx.sess.warn(&format!("error writing ir file: {}", err)); } diff --git a/compiler/rustc_codegen_cranelift/src/trap.rs b/compiler/rustc_codegen_cranelift/src/trap.rs index bb63d72add..1ab0703e98 100644 --- a/compiler/rustc_codegen_cranelift/src/trap.rs +++ b/compiler/rustc_codegen_cranelift/src/trap.rs @@ -17,8 +17,7 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) { ) .unwrap(); let puts = fx.cx.module.declare_func_in_func(puts, &mut fx.bcx.func); - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { fx.add_comment(puts, "puts"); } diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index cffaf79ded..b97d390098 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -2,7 +2,6 @@ use crate::prelude::*; -use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::immediates::Offset32; fn codegen_field<'tcx>( @@ -414,7 +413,7 @@ impl<'tcx> CPlace<'tcx> { self, fx: &mut FunctionCx<'_, '_, 'tcx>, from: CValue<'tcx>, - #[cfg_attr(not(debug_assertions), allow(unused_variables))] method: &'static str, + method: &'static str, ) { fn transmute_value<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -462,8 +461,7 @@ impl<'tcx> CPlace<'tcx> { assert_eq!(self.layout().size, from.layout().size); - #[cfg(debug_assertions)] - { + if fx.clif_comments.enabled() { use cranelift_codegen::cursor::{Cursor, CursorPosition}; let cur_block = match fx.bcx.cursor().position() { CursorPosition::After(block) => block, @@ -707,6 +705,19 @@ pub(crate) fn assert_assignable<'tcx>( } // dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed } + (&ty::Adt(adt_def_a, substs_a), &ty::Adt(adt_def_b, substs_b)) + if adt_def_a.did == adt_def_b.did => + { + let mut types_a = substs_a.types(); + let mut types_b = substs_b.types(); + loop { + match (types_a.next(), types_b.next()) { + (Some(a), Some(b)) => assert_assignable(fx, a, b), + (None, None) => return, + (Some(_), None) | (None, Some(_)) => panic!("{:#?}/{:#?}", from_ty, to_ty), + } + } + } _ => { assert_eq!( from_ty, to_ty, diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 4d2551a061..9053d1aa1b 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -1,6 +1,6 @@ //! Codegen vtables and vtable accesses. //! -//! See librustc_codegen_llvm/meth.rs for reference +//! See `rustc_codegen_ssa/src/meth.rs` for reference. // FIXME dedup this logic between miri, cg_llvm and cg_clif use crate::prelude::*; diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index d9393ffe53..fba5667784 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -41,12 +41,23 @@ impl ArgAttributeExt for ArgAttribute { } pub trait ArgAttributesExt { - fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value); - fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value); + fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value); + fn apply_attrs_to_callsite( + &self, + idx: AttributePlace, + cx: &CodegenCx<'_, '_>, + callsite: &Value, + ); +} + +fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool { + // While #84958 has been fixed, mutable noalias is not enabled by default + // in Rust 1.53 out of an abundance of caution. + cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(false) } impl ArgAttributesExt for ArgAttributes { - fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) { + fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -62,6 +73,9 @@ impl ArgAttributesExt for ArgAttributes { llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32); } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); + if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) { + llvm::Attribute::NoAlias.apply_llfn(idx, llfn); + } match self.arg_ext { ArgExtension::None => {} ArgExtension::Zext => { @@ -74,7 +88,12 @@ impl ArgAttributesExt for ArgAttributes { } } - fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) { + fn apply_attrs_to_callsite( + &self, + idx: AttributePlace, + cx: &CodegenCx<'_, '_>, + callsite: &Value, + ) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -98,6 +117,9 @@ impl ArgAttributesExt for ArgAttributes { ); } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); + if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) { + llvm::Attribute::NoAlias.apply_callsite(idx, callsite); + } match self.arg_ext { ArgExtension::None => {} ArgExtension::Zext => { @@ -419,13 +441,13 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { - attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), cx, llfn); i += 1; i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); @@ -480,18 +502,18 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite. let mut i = 0; - let mut apply = |attrs: &ArgAttributes| { - attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite); + let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| { + attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), cx, callsite); i += 1; i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite); + attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, &bx.cx, callsite); } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); - let i = apply(attrs); + let i = apply(bx.cx, attrs); unsafe { llvm::LLVMRustAddStructRetCallSiteAttr( callsite, @@ -517,12 +539,12 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } for arg in &self.args { if arg.pad.is_some() { - apply(&ArgAttributes::new()); + apply(bx.cx, &ArgAttributes::new()); } match arg.mode { PassMode::Ignore => {} PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => { - let i = apply(attrs); + let i = apply(bx.cx, attrs); unsafe { llvm::LLVMRustAddByValCallSiteAttr( callsite, @@ -533,22 +555,22 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } PassMode::Direct(ref attrs) | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => { - apply(attrs); + apply(bx.cx, attrs); } PassMode::Indirect { ref attrs, extra_attrs: Some(ref extra_attrs), on_stack: _, } => { - apply(attrs); - apply(extra_attrs); + apply(bx.cx, attrs); + apply(bx.cx, extra_attrs); } PassMode::Pair(ref a, ref b) => { - apply(a); - apply(b); + apply(bx.cx, a); + apply(bx.cx, b); } PassMode::Cast(_) => { - apply(&ArgAttributes::new()); + apply(bx.cx, &ArgAttributes::new()); } } } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index e7d359c4f1..84b091d8d4 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, span_bug}; -use rustc_span::{Pos, Span}; +use rustc_span::{Pos, Span, Symbol}; use rustc_target::abi::*; use rustc_target::asm::*; @@ -125,15 +125,39 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { // Collect the types of output operands let mut constraints = vec![]; + let mut clobbers = vec![]; let mut output_types = vec![]; let mut op_idx = FxHashMap::default(); for (idx, op) in operands.iter().enumerate() { match *op { InlineAsmOperandRef::Out { reg, late, place } => { + let is_target_supported = |reg_class: InlineAsmRegClass| { + for &(_, feature) in reg_class.supported_types(asm_arch) { + if let Some(feature) = feature { + if self.tcx.sess.target_features.contains(&Symbol::intern(feature)) + { + return true; + } + } else { + // Register class is unconditionally supported + return true; + } + } + false + }; + let mut layout = None; 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()) { + // 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 + // to actually allocate a register for the dummy output. + assert!(matches!(reg, InlineAsmRegOrRegClass::Reg(_))); + clobbers.push(format!("~{}", reg_to_llvm(reg, None))); + continue; } else { // If the output is discarded, we don't really care what // type is used. We're just using this to tell LLVM to @@ -244,6 +268,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } + constraints.append(&mut clobbers); if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) { match asm_arch { InlineAsmArch::AArch64 | InlineAsmArch::Arm => { diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 64ebe585dd..ede38b723c 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -11,9 +11,10 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::config::{OptLevel, SanitizerSet}; +use rustc_session::config::OptLevel; use rustc_session::Session; -use rustc_target::spec::StackProbeType; +use rustc_target::spec::abi::Abi; +use rustc_target::spec::{SanitizerSet, StackProbeType}; use crate::attributes; use crate::llvm::AttributePlace::Function; @@ -254,6 +255,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: attributes::emit_uwtable(llfn, true); } + // FIXME: none of these three functions interact with source level attributes. set_frame_pointer_elimination(cx, llfn); set_instrument_function(cx, llfn); set_probestack(cx, llfn); @@ -289,7 +291,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: // The target doesn't care; the subtarget reads our attribute. apply_tune_cpu_attr(cx, llfn); - let function_features = codegen_fn_attrs + let mut function_features = codegen_fn_attrs .target_features .iter() .map(|f| { @@ -301,23 +303,10 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) .collect::>(); - if !function_features.is_empty() { - let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess); - global_features.extend(function_features.into_iter()); - let features = global_features.join(","); - let val = CString::new(features).unwrap(); - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - cstr!("target-features"), - &val, - ); - } - // Note that currently the `wasm-import-module` doesn't do anything, but - // eventually LLVM 7 should read this and ferry the appropriate import - // module to the output file. - if cx.tcx.sess.target.arch == "wasm32" { + if cx.tcx.sess.target.is_like_wasm { + // If this function is an import from the environment but the wasm + // import has a specific module/name, apply them here. if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { llvm::AddFunctionAttrStringValue( llfn, @@ -336,6 +325,30 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: &name, ); } + + // The `"wasm"` abi on wasm targets automatically enables the + // `+multivalue` feature because the purpose of the wasm abi is to match + // the WebAssembly specification, which has this feature. This won't be + // needed when LLVM enables this `multivalue` feature by default. + if !cx.tcx.is_closure(instance.def_id()) { + let abi = cx.tcx.fn_sig(instance.def_id()).abi(); + if abi == Abi::Wasm { + function_features.push("+multivalue".to_string()); + } + } + } + + if !function_features.is_empty() { + let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess); + global_features.extend(function_features.into_iter()); + let features = global_features.join(","); + let val = CString::new(features).unwrap(); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr!("target-features"), + &val, + ); } } diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 5effe68752..4226ed7d99 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -24,6 +24,7 @@ use tracing::{debug, info}; use std::ffi::{CStr, CString}; use std::fs::File; use std::io; +use std::iter; use std::path::Path; use std::ptr; use std::slice; @@ -916,9 +917,7 @@ impl ThinLTOKeysMap { modules: &[llvm::ThinLTOModule], names: &[CString], ) -> Self { - let keys = modules - .iter() - .zip(names.iter()) + let keys = iter::zip(modules, names) .map(|(module, name)| { let key = build_string(|rust_str| unsafe { llvm::LLVMRustComputeLTOCacheKey(rust_str, module.identifier, data.0); diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 388dd7ce81..b628ae3ae3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -23,11 +23,11 @@ use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath}; +use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::InnerSpan; -use rustc_target::spec::{CodeModel, RelocModel, SplitDebuginfo}; +use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo}; use tracing::debug; use libc::{c_char, c_int, c_uint, c_void, size_t}; @@ -170,10 +170,7 @@ pub fn target_machine_factory( // On the wasm target once the `atomics` feature is enabled that means that // we're no longer single-threaded, or otherwise we don't want LLVM to // lower atomic operations to single-threaded operations. - if singlethread - && sess.target.llvm_target.contains("wasm32") - && sess.target_features.contains(&sym::atomics) - { + if singlethread && sess.target.is_like_wasm && sess.target_features.contains(&sym::atomics) { singlethread = false; } @@ -548,6 +545,15 @@ pub(crate) unsafe fn optimize( llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap()); continue; } + if pass_name == "insert-gcov-profiling" || pass_name == "instrprof" { + // Instrumentation must be inserted before optimization, + // otherwise LLVM may optimize some functions away which + // breaks llvm-cov. + // + // This mirrors what Clang does in lib/CodeGen/BackendUtil.cpp. + llvm::LLVMRustAddPass(mpm, find_pass(pass_name).unwrap()); + continue; + } if let Some(pass) = find_pass(pass_name) { extra_passes.push(pass); @@ -1041,7 +1047,7 @@ pub unsafe fn with_llvm_pmb( // thresholds copied from clang. match (opt_level, opt_size, inline_threshold) { (.., Some(t)) => { - llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32); + llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t); } (llvm::CodeGenOptLevel::Aggressive, ..) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275); diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index d5be3132de..6f6c649bb0 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -32,8 +32,9 @@ use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::middle::exported_symbols; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{DebugInfo, SanitizerSet}; +use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; +use rustc_target::spec::SanitizerSet; use std::ffi::CString; use std::time::Instant; @@ -143,7 +144,7 @@ pub fn compile_codegen_unit( // Finalize code coverage by injecting the coverage map. Note, the coverage map will // also be added to the `llvm.used` variable, created next. - if cx.sess().opts.debugging_opts.instrument_coverage { + if cx.sess().instrument_coverage() { cx.coverageinfo_finalize(); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index f4852c91e5..053cda1e7c 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2,6 +2,7 @@ use crate::common::Funclet; use crate::context::CodegenCx; use crate::llvm::{self, BasicBlock, False}; use crate::llvm::{AtomicOrdering, AtomicRmwBinOp, SynchronizationScope}; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -16,11 +17,12 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_target::abi::{self, Align, Size}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; +use std::iter; use std::ops::{Deref, Range}; use std::ptr; use tracing::debug; @@ -260,7 +262,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -268,7 +270,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -276,7 +278,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -284,7 +286,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -292,7 +294,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -668,81 +670,47 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - // WebAssembly has saturating floating point to integer casts if the - // `nontrapping-fptoint` target feature is activated. We'll use those if - // they are available. - if self.sess().target.arch == "wasm32" - && self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) - { + if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return Some(self.call(intrinsic, &[val], None)); - } + let name = format!("llvm.fptoui.sat.i{}.f{}", int_width, float_width); + let intrinsic = self.get_intrinsic(&name); + return Some(self.call(intrinsic, &[val], None)); } + None } fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - // WebAssembly has saturating floating point to integer casts if the - // `nontrapping-fptoint` target feature is activated. We'll use those if - // they are available. - if self.sess().target.arch == "wasm32" - && self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) - { + if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.saturate.signed.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.saturate.signed.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.saturate.signed.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.saturate.signed.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return Some(self.call(intrinsic, &[val], None)); - } + let name = format!("llvm.fptosi.sat.i{}.f{}", int_width, float_width); + let intrinsic = self.get_intrinsic(&name); + return Some(self.call(intrinsic, &[val], None)); } - None - } - fn fptosui_may_trap(&self, val: &'ll Value, dest_ty: &'ll Type) -> bool { - // Most of the time we'll be generating the `fptosi` or `fptoui` - // instruction for floating-point-to-integer conversions. These - // instructions by definition in LLVM do not trap. For the WebAssembly - // target, however, we'll lower in some cases to intrinsic calls instead - // which may trap. If we detect that this is a situation where we'll be - // using the intrinsics then we report that the call map trap, which - // callers might need to handle. - if !self.wasm_and_missing_nontrapping_fptoint() { - return false; - } - let src_ty = self.cx.val_ty(val); - let float_width = self.cx.float_width(src_ty); - let int_width = self.cx.int_width(dest_ty); - matches!((int_width, float_width), (32, 32) | (32, 64) | (64, 32) | (64, 64)) + None } fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - // When we can, use the native wasm intrinsics which have tighter - // codegen. Note that this has a semantic difference in that the - // intrinsic can trap whereas `fptoui` never traps. That difference, - // however, is handled by `fptosui_may_trap` above. + // On WebAssembly the `fptoui` and `fptosi` instructions currently have + // poor codegen. The reason for this is that the corresponding wasm + // instructions, `i32.trunc_f32_s` for example, will trap when the float + // is out-of-bounds, infinity, or nan. This means that LLVM + // automatically inserts control flow around `fptoui` and `fptosi` + // because the LLVM instruction `fptoui` is defined as producing a + // poison value, not having UB on out-of-bounds values. // - // Note that we skip the wasm intrinsics for vector types where `fptoui` - // must be used instead. - if self.wasm_and_missing_nontrapping_fptoint() { + // This method, however, is only used with non-saturating casts that + // have UB on out-of-bounds values. This means that it's ok if we use + // the raw wasm instruction since out-of-bounds values can do whatever + // we like. To ensure that LLVM picks the right instruction we choose + // the raw wasm intrinsic functions which avoid LLVM inserting all the + // other control flow automatically. + if self.sess().target.arch == "wasm32" { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -764,7 +732,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - if self.wasm_and_missing_nontrapping_fptoint() { + // see `fptoui` above for why wasm is different here + if self.sess().target.arch == "wasm32" { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -1241,14 +1210,14 @@ impl Builder<'a, 'll, 'tcx> { pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -1281,7 +1250,7 @@ impl Builder<'a, 'll, 'tcx> { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -1289,7 +1258,7 @@ impl Builder<'a, 'll, 'tcx> { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); - llvm::LLVMRustSetHasUnsafeAlgebra(instr); + llvm::LLVMRustSetFastMath(instr); instr } } @@ -1352,18 +1321,14 @@ impl Builder<'a, 'll, 'tcx> { let param_tys = self.cx.func_params_types(fn_ty); - let all_args_match = param_tys - .iter() - .zip(args.iter().map(|&v| self.val_ty(v))) + let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.val_ty(v))) .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty); if all_args_match { return Cow::Borrowed(args); } - let casted_args: Vec<_> = param_tys - .into_iter() - .zip(args.iter()) + let casted_args: Vec<_> = iter::zip(param_tys, args) .enumerate() .map(|(i, (expected_ty, &actual_val))| { let actual_ty = self.val_ty(actual_val); @@ -1423,8 +1388,11 @@ impl Builder<'a, 'll, 'tcx> { } } - fn wasm_and_missing_nontrapping_fptoint(&self) -> bool { - self.sess().target.arch == "wasm32" - && !self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) + fn fptoint_sat_broken_in_llvm(&self) -> bool { + match self.tcx.sess.target.arch.as_str() { + // FIXME - https://bugs.llvm.org/show_bug.cgi?id=50083 + "riscv64" => llvm_util::get_version() < (13, 0, 0), + _ => false, + } } } diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 367c1f4811..b26969a501 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -14,6 +14,7 @@ use tracing::debug; use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_target::spec::RelocModel; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. @@ -170,17 +171,19 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value } } } - } - // MinGW: For backward compatibility we rely on the linker to decide whether it - // should use dllimport for functions. - if cx.use_dll_storage_attrs - && tcx.is_dllimport_foreign_item(instance_def_id) - && tcx.sess.target.env != "gnu" - { - unsafe { + // MinGW: For backward compatibility we rely on the linker to decide whether it + // should use dllimport for functions. + if cx.use_dll_storage_attrs + && tcx.is_dllimport_foreign_item(instance_def_id) + && tcx.sess.target.env != "gnu" + { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); } + + if cx.tcx.sess.relocation_model() == RelocModel::Static { + llvm::LLVMRustSetDSOLocal(llfn, true); + } } llfn diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 21473f3b11..f5c54b11c0 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -79,7 +79,7 @@ pub struct CodegenCx<'ll, 'tcx> { pub pointee_infos: RefCell, Size), Option>>, pub isize_ty: &'ll Type, - pub coverage_cx: Option>, + pub coverage_cx: Option>, pub dbg_cx: Option>, eh_personality: Cell>, @@ -101,10 +101,6 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { } } -fn strip_x86_address_spaces(data_layout: String) -> String { - data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-") -} - fn strip_powerpc64_vectors(data_layout: String) -> String { data_layout.replace("-v256:256:256-v512:512:512", "") } @@ -119,11 +115,6 @@ pub unsafe fn create_module( let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); let mut target_data_layout = sess.target.data_layout.clone(); - if llvm_util::get_version() < (10, 0, 0) - && (sess.target.arch == "x86" || sess.target.arch == "x86_64") - { - target_data_layout = strip_x86_address_spaces(target_data_layout); - } if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" { target_data_layout = strip_powerpc64_vectors(target_data_layout); } @@ -280,7 +271,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - let coverage_cx = if tcx.sess.opts.debugging_opts.instrument_coverage { + let coverage_cx = if tcx.sess.instrument_coverage() { let covctx = coverageinfo::CrateCoverageContext::new(); Some(covctx) } else { @@ -331,7 +322,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } #[inline] - pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'tcx>> { + pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> { self.coverage_cx.as_ref() } } @@ -512,14 +503,6 @@ impl CodegenCx<'b, 'tcx> { let t_f32 = self.type_f32(); let t_f64 = self.type_f64(); - ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f64", fn(t_f64) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.signed.i32.f32", fn(t_f32) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.signed.i32.f64", fn(t_f64) -> t_i32); - ifn!("llvm.wasm.trunc.saturate.signed.i64.f32", fn(t_f32) -> t_i64); - ifn!("llvm.wasm.trunc.saturate.signed.i64.f64", fn(t_f64) -> t_i64); ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i64.f32", fn(t_f32) -> t_i64); @@ -529,6 +512,28 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.wasm.trunc.signed.i64.f32", fn(t_f32) -> t_i64); ifn!("llvm.wasm.trunc.signed.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptosi.sat.i8.f32", fn(t_f32) -> t_i8); + ifn!("llvm.fptosi.sat.i16.f32", fn(t_f32) -> t_i16); + ifn!("llvm.fptosi.sat.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.fptosi.sat.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.fptosi.sat.i128.f32", fn(t_f32) -> t_i128); + ifn!("llvm.fptosi.sat.i8.f64", fn(t_f64) -> t_i8); + ifn!("llvm.fptosi.sat.i16.f64", fn(t_f64) -> t_i16); + ifn!("llvm.fptosi.sat.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.fptosi.sat.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptosi.sat.i128.f64", fn(t_f64) -> t_i128); + + ifn!("llvm.fptoui.sat.i8.f32", fn(t_f32) -> t_i8); + ifn!("llvm.fptoui.sat.i16.f32", fn(t_f32) -> t_i16); + ifn!("llvm.fptoui.sat.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.fptoui.sat.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.fptoui.sat.i128.f32", fn(t_f32) -> t_i128); + ifn!("llvm.fptoui.sat.i8.f64", fn(t_f64) -> t_i8); + ifn!("llvm.fptoui.sat.i16.f64", fn(t_f64) -> t_i16); + ifn!("llvm.fptoui.sat.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.fptoui.sat.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.fptoui.sat.i128.f64", fn(t_f64) -> t_i128); + ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); @@ -712,7 +717,7 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.va_end", fn(i8p) -> void); ifn!("llvm.va_copy", fn(i8p, i8p) -> void); - if self.sess().opts.debugging_opts.instrument_coverage { + if self.sess().instrument_coverage() { ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void); } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 352638aa88..1faaa7e86f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -3,13 +3,13 @@ use crate::coverageinfo; use crate::llvm; use llvm::coverageinfo::CounterMappingRegion; -use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression, FunctionCoverage}; -use rustc_codegen_ssa::traits::ConstMethods; +use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression}; +use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_llvm::RustString; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::CodeRegion; -use rustc_middle::ty::{Instance, TyCtxt}; use rustc_span::Symbol; use std::ffi::CString; @@ -20,16 +20,17 @@ use tracing::debug; /// /// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3), /// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format) -/// and published in Rust's current (November 2020) fork of LLVM. This version is supported by the -/// LLVM coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM. +/// and published in Rust's November 2020 fork of LLVM. This version is supported by the LLVM +/// coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM. /// /// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with -/// version 3. Clang's implementation of Coverage Map generation was referenced when implementing -/// this Rust version, and though the format documentation is very explicit and detailed, some -/// undocumented details in Clang's implementation (that may or may not be important) were also -/// replicated for Rust's Coverage Map. +/// the same version. Clang's implementation of Coverage Map generation was referenced when +/// implementing this Rust version, and though the format documentation is very explicit and +/// detailed, some undocumented details in Clang's implementation (that may or may not be important) +/// were also replicated for Rust's Coverage Map. pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { let tcx = cx.tcx; + // Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3). // If not, the LLVM Version must be less than 11. let version = coverageinfo::mapping_version(); @@ -39,17 +40,24 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name()); - let mut function_coverage_map = match cx.coverage_context() { + // In order to show that unused functions have coverage counts of zero (0), LLVM requires the + // functions exist. Generate synthetic functions with a (required) single counter, and add the + // MIR `Coverage` code regions to the `function_coverage_map`, before calling + // `ctx.take_function_coverage_map()`. + if !tcx.sess.instrument_coverage_except_unused_functions() { + add_unused_functions(cx); + } + + let function_coverage_map = match cx.coverage_context() { Some(ctx) => ctx.take_function_coverage_map(), None => return, }; + if function_coverage_map.is_empty() { // This module has no functions with coverage instrumentation return; } - add_unreachable_coverage(tcx, &mut function_coverage_map); - let mut mapgen = CoverageMapGenerator::new(); // Encode coverage mappings and generate function records @@ -57,7 +65,8 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { for (instance, function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); let mangled_function_name = tcx.symbol_name(instance).to_string(); - let function_source_hash = function_coverage.source_hash(); + let source_hash = function_coverage.source_hash(); + let is_used = function_coverage.is_used(); let (expressions, counter_regions) = function_coverage.get_expressions_and_counter_regions(); @@ -69,7 +78,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { "Every `FunctionCoverage` should have at least one counter" ); - function_data.push((mangled_function_name, function_source_hash, coverage_mapping_buffer)); + function_data.push((mangled_function_name, source_hash, is_used, coverage_mapping_buffer)); } // Encode all filenames referenced by counters/expressions in this module @@ -84,13 +93,14 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { // Generate the LLVM IR representation of the coverage map and store it in a well-known global let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val); - for (mangled_function_name, function_source_hash, coverage_mapping_buffer) in function_data { + for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data { save_function_record( cx, mangled_function_name, - function_source_hash, + source_hash, filenames_ref, coverage_mapping_buffer, + is_used, ); } @@ -201,9 +211,10 @@ impl CoverageMapGenerator { fn save_function_record( cx: &CodegenCx<'ll, 'tcx>, mangled_function_name: String, - function_source_hash: u64, + source_hash: u64, filenames_ref: u64, coverage_mapping_buffer: Vec, + is_used: bool, ) { // Concatenate the encoded coverage mappings let coverage_mapping_size = coverage_mapping_buffer.len(); @@ -212,128 +223,124 @@ fn save_function_record( let func_name_hash = coverageinfo::hash_str(&mangled_function_name); let func_name_hash_val = cx.const_u64(func_name_hash); let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32); - let func_hash_val = cx.const_u64(function_source_hash); + let source_hash_val = cx.const_u64(source_hash); let filenames_ref_val = cx.const_u64(filenames_ref); let func_record_val = cx.const_struct( &[ func_name_hash_val, coverage_mapping_size_val, - func_hash_val, + source_hash_val, filenames_ref_val, coverage_mapping_val, ], /*packed=*/ true, ); - // At the present time, the coverage map for Rust assumes every instrumented function `is_used`. - // Note that Clang marks functions as "unused" in `CodeGenPGO::emitEmptyCounterMapping`. (See: - // https://github.com/rust-lang/llvm-project/blob/de02a75e398415bad4df27b4547c25b896c8bf3b/clang%2Flib%2FCodeGen%2FCodeGenPGO.cpp#L877-L878 - // for example.) - // - // It's not yet clear if or how this may be applied to Rust in the future, but the `is_used` - // argument is available and handled similarly. - let is_used = true; coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used); } /// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for /// the functions that went through codegen; such as public functions and "used" functions /// (functions referenced by other "used" or public items). Any other functions considered unused, -/// or "Unreachable" were still parsed and processed through the MIR stage. +/// or "Unreachable", were still parsed and processed through the MIR stage, but were not +/// codegenned. (Note that `-Clink-dead-code` can force some unused code to be codegenned, but +/// that flag is known to cause other errors, when combined with `-Z instrument-coverage`; and +/// `-Clink-dead-code` will not generate code for unused generic functions.) /// -/// We can find the unreachable functions by the set difference of all MIR `DefId`s (`tcx` query -/// `mir_keys`) minus the codegenned `DefId`s (`tcx` query `collect_and_partition_mono_items`). +/// We can find the unused functions (including generic functions) by the set difference of all MIR +/// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`tcx` query +/// `collect_and_partition_mono_items`). /// /// *HOWEVER* the codegenned `DefId`s are partitioned across multiple `CodegenUnit`s (CGUs), and /// this function is processing a `function_coverage_map` for the functions (`Instance`/`DefId`) -/// allocated to only one of those CGUs. We must NOT inject any "Unreachable" functions's -/// `CodeRegion`s more than once, so we have to pick which CGU's `function_coverage_map` to add -/// each "Unreachable" function to. -/// -/// Some constraints: -/// -/// 1. The file name of an "Unreachable" function must match the file name of the existing -/// codegenned (covered) function to which the unreachable code regions will be added. -/// 2. The function to which the unreachable code regions will be added must not be a generic -/// function (must not have type parameters) because the coverage tools will get confused -/// if the codegenned function has more than one instantiation and additional `CodeRegion`s -/// attached to only one of those instantiations. -fn add_unreachable_coverage<'tcx>( - tcx: TyCtxt<'tcx>, - function_coverage_map: &mut FxHashMap, FunctionCoverage<'tcx>>, -) { +/// allocated to only one of those CGUs. We must NOT inject any unused functions's `CodeRegion`s +/// more than once, so we have to pick a CGUs `function_coverage_map` into which the unused +/// function will be inserted. +fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { + let tcx = cx.tcx; + // FIXME(#79622): Can this solution be simplified and/or improved? Are there other sources // of compiler state data that might help (or better sources that could be exposed, but // aren't yet)? - // Note: If the crate *only* defines generic functions, there are no codegenerated non-generic - // functions to add any unreachable code to. In this case, the unreachable code regions will - // have no coverage, instead of having coverage with zero executions. - // - // This is probably still an improvement over Clang, which does not generate any coverage - // for uninstantiated template functions. + let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics(); - let has_non_generic_def_ids = - function_coverage_map.keys().any(|instance| instance.def.attrs(tcx).len() == 0); - - if !has_non_generic_def_ids { - // There are no non-generic functions to add unreachable `CodeRegion`s to - return; - } - - let all_def_ids: DefIdSet = - tcx.mir_keys(LOCAL_CRATE).iter().map(|local_def_id| local_def_id.to_def_id()).collect(); + let all_def_ids: DefIdSet = tcx + .mir_keys(LOCAL_CRATE) + .iter() + .filter_map(|local_def_id| { + let def_id = local_def_id.to_def_id(); + if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) { + return None; + } + Some(local_def_id.to_def_id()) + }) + .collect(); let codegenned_def_ids = tcx.codegened_and_inlined_items(LOCAL_CRATE); - let mut unreachable_def_ids_by_file: FxHashMap> = FxHashMap::default(); + let mut unused_def_ids_by_file: FxHashMap> = FxHashMap::default(); for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) { - // Make sure the non-codegenned (unreachable) function has a file_name + let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id); + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { + continue; + } + // Make sure the non-codegenned (unused) function has a file_name if let Some(non_codegenned_file_name) = tcx.covered_file_name(non_codegenned_def_id) { - let def_ids = unreachable_def_ids_by_file - .entry(*non_codegenned_file_name) - .or_insert_with(Vec::new); + let def_ids = + unused_def_ids_by_file.entry(*non_codegenned_file_name).or_insert_with(Vec::new); def_ids.push(non_codegenned_def_id); } } - if unreachable_def_ids_by_file.is_empty() { - // There are no unreachable functions with file names to add (in any CGU) + if unused_def_ids_by_file.is_empty() { + // There are no unused functions with file names to add (in any CGU) return; } - // Since there may be multiple `CodegenUnit`s, some codegenned_def_ids may be codegenned in a - // different CGU, and will be added to the function_coverage_map for each CGU. Determine which - // function_coverage_map has the responsibility for publishing unreachable coverage - // based on file name: + // Each `CodegenUnit` (CGU) has its own function_coverage_map, and generates a specific binary + // with its own coverage map. + // + // Each covered function `Instance` can be included in only one coverage map, produced from a + // specific function_coverage_map, from a specific CGU. + // + // Since unused functions did not generate code, they are not associated with any CGU yet. // - // For each covered file name, sort ONLY the non-generic codegenned_def_ids, and if - // covered_def_ids.contains(the first def_id) for a given file_name, add the unreachable code - // region in this function_coverage_map. Otherwise, ignore it and assume another CGU's - // function_coverage_map will be adding it (because it will be first for one, and only one, - // of them). + // To avoid injecting the unused functions in multiple coverage maps (for multiple CGUs) + // determine which function_coverage_map has the responsibility for publishing unreachable + // coverage, based on file name: For each unused function, find the CGU that generates the + // first function (based on sorted `DefId`) from the same file. + // + // Add a new `FunctionCoverage` to the `function_coverage_map`, with unreachable code regions + // for each region in it's MIR. + + // Convert the `HashSet` of `codegenned_def_ids` to a sortable vector, and sort them. let mut sorted_codegenned_def_ids: Vec = codegenned_def_ids.iter().map(|def_id| *def_id).collect(); sorted_codegenned_def_ids.sort_unstable(); let mut first_covered_def_id_by_file: FxHashMap = FxHashMap::default(); for &def_id in sorted_codegenned_def_ids.iter() { - // Only consider non-generic functions, to potentially add unreachable code regions - if tcx.generics_of(def_id).count() == 0 { - if let Some(covered_file_name) = tcx.covered_file_name(def_id) { - // Only add files known to have unreachable functions - if unreachable_def_ids_by_file.contains_key(covered_file_name) { - first_covered_def_id_by_file.entry(*covered_file_name).or_insert(def_id); - } + if let Some(covered_file_name) = tcx.covered_file_name(def_id) { + // Only add files known to have unused functions + if unused_def_ids_by_file.contains_key(covered_file_name) { + first_covered_def_id_by_file.entry(*covered_file_name).or_insert(def_id); } } } // Get the set of def_ids with coverage regions, known by *this* CoverageContext. - let cgu_covered_def_ids: DefIdSet = - function_coverage_map.keys().map(|instance| instance.def.def_id()).collect(); + let cgu_covered_def_ids: DefIdSet = match cx.coverage_context() { + Some(ctx) => ctx + .function_coverage_map + .borrow() + .keys() + .map(|&instance| instance.def.def_id()) + .collect(), + None => return, + }; - let mut cgu_covered_files: FxHashSet = first_covered_def_id_by_file + let cgu_covered_files: FxHashSet = first_covered_def_id_by_file .iter() .filter_map( |(&file_name, def_id)| { @@ -342,49 +349,13 @@ fn add_unreachable_coverage<'tcx>( ) .collect(); - // Find the first covered, non-generic function (instance) for each cgu_covered_file. Take the - // unreachable code regions for that file, and add them to the function. - // - // There are three `for` loops here, but (a) the lists have already been reduced to the minimum - // required values, the lists are further reduced (by `remove()` calls) when elements are no - // longer needed, and there are several opportunities to branch out of loops early. - for (instance, function_coverage) in function_coverage_map.iter_mut() { - if instance.def.attrs(tcx).len() > 0 { - continue; - } - // The covered function is not generic... - let covered_def_id = instance.def.def_id(); - if let Some(covered_file_name) = tcx.covered_file_name(covered_def_id) { - if !cgu_covered_files.remove(&covered_file_name) { - continue; - } - // The covered function's file is one of the files with unreachable code regions, so - // all of the unreachable code regions for this file will be added to this function. - for def_id in - unreachable_def_ids_by_file.remove(&covered_file_name).into_iter().flatten() - { - // Note, this loop adds an unreachable code regions for each MIR-derived region. - // Alternatively, we could add a single code region for the maximum span of all - // code regions here. - // - // Observed downsides of this approach are: - // - // 1. The coverage results will appear inconsistent compared with the same (or - // similar) code in a function that is reached. - // 2. If the function is unreachable from one crate but reachable when compiling - // another referencing crate (such as a cross-crate reference to a - // generic function or inlined function), actual coverage regions overlaid - // on a single larger code span of `Zero` coverage can appear confusing or - // wrong. Chaning the unreachable coverage from a `code_region` to a - // `gap_region` can help, but still can look odd with `0` line counts for - // lines between executed (> 0) lines (such as for blank lines or comments). - for ®ion in tcx.covered_code_regions(def_id) { - function_coverage.add_unreachable_region(region.clone()); - } - } - if cgu_covered_files.is_empty() { - break; - } + // For each file for which this CGU is responsible for adding unused function coverage, + // get the `def_id`s for each unused function (if any), define a synthetic function with a + // single LLVM coverage counter, and add the function's coverage `CodeRegion`s. to the + // function_coverage_map. + for covered_file_name in cgu_covered_files { + for def_id in unused_def_ids_by_file.remove(&covered_file_name).into_iter().flatten() { + cx.define_unused_fn(def_id); } } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index e47b8fde40..afc2bdbfd5 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,5 +1,6 @@ use crate::llvm; +use crate::abi::{Abi, FnAbi}; use crate::builder::Builder; use crate::common::CodegenCx; @@ -7,33 +8,47 @@ use libc::c_uint; use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage}; use rustc_codegen_ssa::traits::{ - BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, MiscMethods, StaticMethods, + BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, + MiscMethods, StaticMethods, }; use rustc_data_structures::fx::FxHashMap; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_llvm::RustString; +use rustc_middle::bug; use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, }; +use rustc_middle::ty; +use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Instance; use std::cell::RefCell; use std::ffi::CString; +use std::iter; use tracing::debug; pub mod mapgen; +const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START; + const VAR_ALIGN_BYTES: usize = 8; /// A context object for maintaining all state needed by the coverageinfo module. -pub struct CrateCoverageContext<'tcx> { +pub struct CrateCoverageContext<'ll, 'tcx> { // Coverage data for each instrumented function identified by DefId. pub(crate) function_coverage_map: RefCell, FunctionCoverage<'tcx>>>, + pub(crate) pgo_func_name_var_map: RefCell, &'ll llvm::Value>>, } -impl<'tcx> CrateCoverageContext<'tcx> { +impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { pub fn new() -> Self { - Self { function_coverage_map: Default::default() } + Self { + function_coverage_map: Default::default(), + pgo_func_name_var_map: Default::default(), + } } pub fn take_function_coverage_map(&self) -> FxHashMap, FunctionCoverage<'tcx>> { @@ -41,23 +56,47 @@ impl<'tcx> CrateCoverageContext<'tcx> { } } -impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> { +impl CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn coverageinfo_finalize(&self) { mapgen::finalize(self) } -} -impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { - /// Calls llvm::createPGOFuncNameVar() with the given function instance's mangled function name. - /// The LLVM API returns an llvm::GlobalVariable containing the function name, with the specific - /// variable name and linkage required by LLVM InstrProf source-based coverage instrumentation. - fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value { - let llfn = self.cx.get_fn(instance); - let mangled_fn_name = CString::new(self.tcx.symbol_name(instance).name) - .expect("error converting function name to C string"); - unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) } + fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value { + if let Some(coverage_context) = self.coverage_context() { + debug!("getting pgo_func_name_var for instance={:?}", instance); + let mut pgo_func_name_var_map = coverage_context.pgo_func_name_var_map.borrow_mut(); + pgo_func_name_var_map + .entry(instance) + .or_insert_with(|| create_pgo_func_name_var(self, instance)) + } else { + bug!("Could not get the `coverage_context`"); + } + } + + /// Functions with MIR-based coverage are normally codegenned _only_ if + /// called. LLVM coverage tools typically expect every function to be + /// defined (even if unused), with at least one call to LLVM intrinsic + /// `instrprof.increment`. + /// + /// Codegen a small function that will never be called, with one counter + /// that will never be incremented. + /// + /// For used/called functions, the coverageinfo was already added to the + /// `function_coverage_map` (keyed by function `Instance`) during codegen. + /// But in this case, since the unused function was _not_ previously + /// codegenned, collect the coverage `CodeRegion`s from the MIR and add + /// them. The first `CodeRegion` is used to add a single counter, with the + /// same counter ID used in the injected `instrprof.increment` intrinsic + /// call. Since the function is never called, all other `CodeRegion`s can be + /// added as `unreachable_region`s. + fn define_unused_fn(&self, def_id: DefId) { + let instance = declare_unused_fn(self, &def_id); + codegen_unused_fn_and_counter(self, instance); + add_unused_function_coverage(self, instance, def_id); } +} +impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn set_function_source_hash( &mut self, instance: Instance<'tcx>, @@ -145,6 +184,100 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } +fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx> { + let tcx = cx.tcx; + + let instance = Instance::new( + *def_id, + InternalSubsts::for_item(tcx, *def_id, |param, _| { + if let ty::GenericParamDefKind::Lifetime = param.kind { + tcx.lifetimes.re_erased.into() + } else { + tcx.mk_param_from_def(param) + } + }), + ); + + let llfn = cx.declare_fn( + &tcx.symbol_name(instance).name, + &FnAbi::of_fn_ptr( + cx, + ty::Binder::dummy(tcx.mk_fn_sig( + iter::once(tcx.mk_unit()), + tcx.mk_unit(), + false, + hir::Unsafety::Unsafe, + Abi::Rust, + )), + &[], + ), + ); + + llvm::set_linkage(llfn, llvm::Linkage::WeakAnyLinkage); + llvm::set_visibility(llfn, llvm::Visibility::Hidden); + + assert!(cx.instances.borrow_mut().insert(instance, llfn).is_none()); + + instance +} + +fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) { + let llfn = cx.get_fn(instance); + let mut bx = Builder::new_block(cx, llfn, "unused_function"); + let fn_name = bx.get_pgo_func_name_var(instance); + let hash = bx.const_u64(0); + let num_counters = bx.const_u32(1); + let index = bx.const_u32(u32::from(UNUSED_FUNCTION_COUNTER_ID)); + debug!( + "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, + index={:?}) for unused function: {:?}", + fn_name, hash, num_counters, index, instance + ); + bx.instrprof_increment(fn_name, hash, num_counters, index); + bx.ret_void(); +} + +fn add_unused_function_coverage( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + def_id: DefId, +) { + let tcx = cx.tcx; + + let mut function_coverage = FunctionCoverage::unused(tcx, instance); + for (index, &code_region) in tcx.covered_code_regions(def_id).iter().enumerate() { + if index == 0 { + // Insert at least one real counter so the LLVM CoverageMappingReader will find expected + // definitions. + function_coverage.add_counter(UNUSED_FUNCTION_COUNTER_ID, code_region.clone()); + } else { + function_coverage.add_unreachable_region(code_region.clone()); + } + } + + if let Some(coverage_context) = cx.coverage_context() { + coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage); + } else { + bug!("Could not get the `coverage_context`"); + } +} + +/// Calls llvm::createPGOFuncNameVar() with the given function instance's +/// mangled function name. The LLVM API returns an llvm::GlobalVariable +/// containing the function name, with the specific variable name and linkage +/// required by LLVM InstrProf source-based coverage instrumentation. Use +/// `bx.get_pgo_func_name_var()` to ensure the variable is only created once per +/// `Instance`. +fn create_pgo_func_name_var( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, +) -> &'ll llvm::Value { + let mangled_fn_name = CString::new(cx.tcx.symbol_name(instance).name) + .expect("error converting function name to C string"); + let llfn = cx.get_fn(instance); + unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) } +} + pub(crate) fn write_filenames_section_to_buffer<'a>( filenames: impl IntoIterator, buffer: &RustString, @@ -177,6 +310,7 @@ pub(crate) fn write_mapping_to_buffer( ); } } + pub(crate) fn hash_str(strval: &str) -> u64 { let strval = CString::new(strval).expect("null error converting hashable str to C string"); unsafe { llvm::LLVMRustCoverageHashCString(strval.as_ptr()) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/doc.md b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md new file mode 100644 index 0000000000..f983d09203 --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md @@ -0,0 +1,180 @@ +# Debug Info Module + +This module serves the purpose of generating debug symbols. We use LLVM's +[source level debugging](https://llvm.org/docs/SourceLevelDebugging.html) +features for generating the debug information. The general principle is +this: + +Given the right metadata in the LLVM IR, the LLVM code generator is able to +create DWARF debug symbols for the given code. The +[metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured +much like DWARF *debugging information entries* (DIE), representing type +information such as datatype layout, function signatures, block layout, +variable location and scope information, etc. It is the purpose of this +module to generate correct metadata and insert it into the LLVM IR. + +As the exact format of metadata trees may change between different LLVM +versions, we now use LLVM +[DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) +to create metadata where possible. This will hopefully ease the adaption of +this module to future LLVM versions. + +The public API of the module is a set of functions that will insert the +correct metadata into the LLVM IR when called with the right parameters. +The module is thus driven from an outside client with functions like +`debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`. + +Internally the module will try to reuse already created metadata by +utilizing a cache. The way to get a shared metadata node when needed is +thus to just call the corresponding function in this module: + + let file_metadata = file_metadata(cx, file); + +The function will take care of probing the cache for an existing node for +that exact file path. + +All private state used by the module is stored within either the +CrateDebugContext struct (owned by the CodegenCx) or the +FunctionDebugContext (owned by the FunctionCx). + +This file consists of three conceptual sections: +1. The public interface of the module +2. Module-internal metadata creation functions +3. Minor utility functions + + +## Recursive Types + +Some kinds of types, such as structs and enums can be recursive. That means +that the type definition of some type X refers to some other type which in +turn (transitively) refers to X. This introduces cycles into the type +referral graph. A naive algorithm doing an on-demand, depth-first traversal +of this graph when describing types, can get trapped in an endless loop +when it reaches such a cycle. + +For example, the following simple type for a singly-linked list... + +``` +struct List { + value: i32, + tail: Option>, +} +``` + +will generate the following callstack with a naive DFS algorithm: + +``` +describe(t = List) + describe(t = i32) + describe(t = Option>) + describe(t = Box) + describe(t = List) // at the beginning again... + ... +``` + +To break cycles like these, we use "forward declarations". That is, when +the algorithm encounters a possibly recursive type (any struct or enum), it +immediately creates a type description node and inserts it into the cache +*before* describing the members of the type. This type description is just +a stub (as type members are not described and added to it yet) but it +allows the algorithm to already refer to the type. After the stub is +inserted into the cache, the algorithm continues as before. If it now +encounters a recursive reference, it will hit the cache and does not try to +describe the type anew. + +This behavior is encapsulated in the 'RecursiveTypeDescription' enum, +which represents a kind of continuation, storing all state needed to +continue traversal at the type members after the type has been registered +with the cache. (This implementation approach might be a tad over- +engineered and may change in the future) + + +## Source Locations and Line Information + +In addition to data type descriptions the debugging information must also +allow to map machine code locations back to source code locations in order +to be useful. This functionality is also handled in this module. The +following functions allow to control source mappings: + ++ `set_source_location()` ++ `clear_source_location()` ++ `start_emitting_source_locations()` + +`set_source_location()` allows to set the current source location. All IR +instructions created after a call to this function will be linked to the +given source location, until another location is specified with +`set_source_location()` or the source location is cleared with +`clear_source_location()`. In the later case, subsequent IR instruction +will not be linked to any source location. As you can see, this is a +stateful API (mimicking the one in LLVM), so be careful with source +locations set by previous calls. It's probably best to not rely on any +specific state being present at a given point in code. + +One topic that deserves some extra attention is *function prologues*. At +the beginning of a function's machine code there are typically a few +instructions for loading argument values into allocas and checking if +there's enough stack space for the function to execute. This *prologue* is +not visible in the source code and LLVM puts a special PROLOGUE END marker +into the line table at the first non-prologue instruction of the function. +In order to find out where the prologue ends, LLVM looks for the first +instruction in the function body that is linked to a source location. So, +when generating prologue instructions we have to make sure that we don't +emit source location information until the 'real' function body begins. For +this reason, source location emission is disabled by default for any new +function being codegened and is only activated after a call to the third +function from the list above, `start_emitting_source_locations()`. This +function should be called right before regularly starting to codegen the +top-level block of the given function. + +There is one exception to the above rule: `llvm.dbg.declare` instruction +must be linked to the source location of the variable being declared. For +function parameters these `llvm.dbg.declare` instructions typically occur +in the middle of the prologue, however, they are ignored by LLVM's prologue +detection. The `create_argument_metadata()` and related functions take care +of linking the `llvm.dbg.declare` instructions to the correct source +locations even while source location emission is still disabled, so there +is no need to do anything special with source location handling here. + +## Unique Type Identification + +In order for link-time optimization to work properly, LLVM needs a unique +type identifier that tells it across compilation units which types are the +same as others. This type identifier is created by +`TypeMap::get_unique_type_id_of_type()` using the following algorithm: + +1. Primitive types have their name as ID + +2. Structs, enums and traits have a multipart identifier + + 1. The first part is the SVH (strict version hash) of the crate they + were originally defined in + + 2. The second part is the ast::NodeId of the definition in their + original crate + + 3. The final part is a concatenation of the type IDs of their concrete + type arguments if they are generic types. + +3. Tuple-, pointer-, and function types are structurally identified, which + means that they are equivalent if their component types are equivalent + (i.e., `(i32, i32)` is the same regardless in which crate it is used). + +This algorithm also provides a stable ID for types that are defined in one +crate but instantiated from metadata within another crate. We just have to +take care to always map crate and `NodeId`s back to the original crate +context. + +As a side-effect these unique type IDs also help to solve a problem arising +from lifetime parameters. Since lifetime parameters are completely omitted +in debuginfo, more than one `Ty` instance may map to the same debuginfo +type metadata, that is, some struct `Struct<'a>` may have N instantiations +with different concrete substitutions for `'a`, and thus there will be N +`Ty` instances for the type `Struct<'a>` even though it is not generic +otherwise. Unfortunately this means that we cannot use `ty::type_id()` as +cheap identifier for type metadata -- we have done this in the past, but it +led to unnecessary metadata duplication in the best case and LLVM +assertions in the worst. However, the unique type ID as described above +*can* be used as identifier. Since it is comparatively expensive to +construct, though, `ty::type_id()` is still used additionally as an +optimization for cases where the exact same type has been seen before +(which is most of the time). diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs b/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs deleted file mode 100644 index 10dd590652..0000000000 --- a/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs +++ /dev/null @@ -1,179 +0,0 @@ -//! # Debug Info Module -//! -//! This module serves the purpose of generating debug symbols. We use LLVM's -//! [source level debugging](https://llvm.org/docs/SourceLevelDebugging.html) -//! features for generating the debug information. The general principle is -//! this: -//! -//! Given the right metadata in the LLVM IR, the LLVM code generator is able to -//! create DWARF debug symbols for the given code. The -//! [metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured -//! much like DWARF *debugging information entries* (DIE), representing type -//! information such as datatype layout, function signatures, block layout, -//! variable location and scope information, etc. It is the purpose of this -//! module to generate correct metadata and insert it into the LLVM IR. -//! -//! As the exact format of metadata trees may change between different LLVM -//! versions, we now use LLVM -//! [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) -//! to create metadata where possible. This will hopefully ease the adaption of -//! this module to future LLVM versions. -//! -//! The public API of the module is a set of functions that will insert the -//! correct metadata into the LLVM IR when called with the right parameters. -//! The module is thus driven from an outside client with functions like -//! `debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`. -//! -//! Internally the module will try to reuse already created metadata by -//! utilizing a cache. The way to get a shared metadata node when needed is -//! thus to just call the corresponding function in this module: -//! -//! let file_metadata = file_metadata(cx, file); -//! -//! The function will take care of probing the cache for an existing node for -//! that exact file path. -//! -//! All private state used by the module is stored within either the -//! CrateDebugContext struct (owned by the CodegenCx) or the -//! FunctionDebugContext (owned by the FunctionCx). -//! -//! This file consists of three conceptual sections: -//! 1. The public interface of the module -//! 2. Module-internal metadata creation functions -//! 3. Minor utility functions -//! -//! -//! ## Recursive Types -//! -//! Some kinds of types, such as structs and enums can be recursive. That means -//! that the type definition of some type X refers to some other type which in -//! turn (transitively) refers to X. This introduces cycles into the type -//! referral graph. A naive algorithm doing an on-demand, depth-first traversal -//! of this graph when describing types, can get trapped in an endless loop -//! when it reaches such a cycle. -//! -//! For example, the following simple type for a singly-linked list... -//! -//! ``` -//! struct List { -//! value: i32, -//! tail: Option>, -//! } -//! ``` -//! -//! will generate the following callstack with a naive DFS algorithm: -//! -//! ``` -//! describe(t = List) -//! describe(t = i32) -//! describe(t = Option>) -//! describe(t = Box) -//! describe(t = List) // at the beginning again... -//! ... -//! ``` -//! -//! To break cycles like these, we use "forward declarations". That is, when -//! the algorithm encounters a possibly recursive type (any struct or enum), it -//! immediately creates a type description node and inserts it into the cache -//! *before* describing the members of the type. This type description is just -//! a stub (as type members are not described and added to it yet) but it -//! allows the algorithm to already refer to the type. After the stub is -//! inserted into the cache, the algorithm continues as before. If it now -//! encounters a recursive reference, it will hit the cache and does not try to -//! describe the type anew. -//! -//! This behavior is encapsulated in the 'RecursiveTypeDescription' enum, -//! which represents a kind of continuation, storing all state needed to -//! continue traversal at the type members after the type has been registered -//! with the cache. (This implementation approach might be a tad over- -//! engineered and may change in the future) -//! -//! -//! ## Source Locations and Line Information -//! -//! In addition to data type descriptions the debugging information must also -//! allow to map machine code locations back to source code locations in order -//! to be useful. This functionality is also handled in this module. The -//! following functions allow to control source mappings: -//! -//! + set_source_location() -//! + clear_source_location() -//! + start_emitting_source_locations() -//! -//! `set_source_location()` allows to set the current source location. All IR -//! instructions created after a call to this function will be linked to the -//! given source location, until another location is specified with -//! `set_source_location()` or the source location is cleared with -//! `clear_source_location()`. In the later case, subsequent IR instruction -//! will not be linked to any source location. As you can see, this is a -//! stateful API (mimicking the one in LLVM), so be careful with source -//! locations set by previous calls. It's probably best to not rely on any -//! specific state being present at a given point in code. -//! -//! One topic that deserves some extra attention is *function prologues*. At -//! the beginning of a function's machine code there are typically a few -//! instructions for loading argument values into allocas and checking if -//! there's enough stack space for the function to execute. This *prologue* is -//! not visible in the source code and LLVM puts a special PROLOGUE END marker -//! into the line table at the first non-prologue instruction of the function. -//! In order to find out where the prologue ends, LLVM looks for the first -//! instruction in the function body that is linked to a source location. So, -//! when generating prologue instructions we have to make sure that we don't -//! emit source location information until the 'real' function body begins. For -//! this reason, source location emission is disabled by default for any new -//! function being codegened and is only activated after a call to the third -//! function from the list above, `start_emitting_source_locations()`. This -//! function should be called right before regularly starting to codegen the -//! top-level block of the given function. -//! -//! There is one exception to the above rule: `llvm.dbg.declare` instruction -//! must be linked to the source location of the variable being declared. For -//! function parameters these `llvm.dbg.declare` instructions typically occur -//! in the middle of the prologue, however, they are ignored by LLVM's prologue -//! detection. The `create_argument_metadata()` and related functions take care -//! of linking the `llvm.dbg.declare` instructions to the correct source -//! locations even while source location emission is still disabled, so there -//! is no need to do anything special with source location handling here. -//! -//! ## Unique Type Identification -//! -//! In order for link-time optimization to work properly, LLVM needs a unique -//! type identifier that tells it across compilation units which types are the -//! same as others. This type identifier is created by -//! `TypeMap::get_unique_type_id_of_type()` using the following algorithm: -//! -//! (1) Primitive types have their name as ID -//! (2) Structs, enums and traits have a multipart identifier -//! -//! (1) The first part is the SVH (strict version hash) of the crate they -//! were originally defined in -//! -//! (2) The second part is the ast::NodeId of the definition in their -//! original crate -//! -//! (3) The final part is a concatenation of the type IDs of their concrete -//! type arguments if they are generic types. -//! -//! (3) Tuple-, pointer and function types are structurally identified, which -//! means that they are equivalent if their component types are equivalent -//! (i.e., (i32, i32) is the same regardless in which crate it is used). -//! -//! This algorithm also provides a stable ID for types that are defined in one -//! crate but instantiated from metadata within another crate. We just have to -//! take care to always map crate and `NodeId`s back to the original crate -//! context. -//! -//! As a side-effect these unique type IDs also help to solve a problem arising -//! from lifetime parameters. Since lifetime parameters are completely omitted -//! in debuginfo, more than one `Ty` instance may map to the same debuginfo -//! type metadata, that is, some struct `Struct<'a>` may have N instantiations -//! with different concrete substitutions for `'a`, and thus there will be N -//! `Ty` instances for the type `Struct<'a>` even though it is not generic -//! otherwise. Unfortunately this means that we cannot use `ty::type_id()` as -//! cheap identifier for type metadata -- we have done this in the past, but it -//! led to unnecessary metadata duplication in the best case and LLVM -//! assertions in the worst. However, the unique type ID as described above -//! *can* be used as identifier. Since it is comparatively expensive to -//! construct, though, `ty::type_id()` is still used additionally as an -//! optimization for cases where the exact same type has been seen before -//! (which is most of the time). diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index d5b32e58cc..e6fa852155 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1083,9 +1083,9 @@ pub fn compile_unit_metadata( ); } - // Insert `llvm.ident` metadata on the wasm32 targets since that will + // Insert `llvm.ident` metadata on the wasm targets since that will // get hooked up to the "producer" sections `processed-by` information. - if tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + if tcx.sess.target.is_like_wasm { let name_metadata = llvm::LLVMMDStringInContext( debug_context.llcontext, rustc_producer.as_ptr().cast(), @@ -1962,9 +1962,7 @@ fn prepare_enum_metadata( let discriminant_type_metadata = |discr: Primitive| { let enumerators_metadata: Vec<_> = match enum_type.kind() { - ty::Adt(def, _) => def - .discriminants(tcx) - .zip(&def.variants) + ty::Adt(def, _) => iter::zip(def.discriminants(tcx), &def.variants) .map(|((_, discr), v)| { let name = v.ident.as_str(); let is_unsigned = match discr.ty.kind() { @@ -2336,9 +2334,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr if substs.types().next().is_some() { let generics = cx.tcx.generics_of(def.did); let names = get_parameter_names(cx, generics); - let template_params: Vec<_> = substs - .iter() - .zip(names) + let template_params: Vec<_> = iter::zip(substs, names) .filter_map(|(kind, name)| { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 440e4d505f..b928e90373 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -1,5 +1,4 @@ -// See doc.rs for documentation. -mod doc; +#![doc = include_str!("doc.md")] use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; @@ -38,6 +37,7 @@ use rustc_target::abi::{LayoutOf, Primitive, Size}; use libc::c_uint; use smallvec::SmallVec; use std::cell::RefCell; +use std::iter; use tracing::debug; mod create_scope_map; @@ -344,7 +344,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { spflags |= DISPFlags::SPFlagOptimized; } if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) { - if id.to_def_id() == def_id { + if id == def_id { spflags |= DISPFlags::SPFlagMainSubprogram; } } @@ -449,9 +449,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // 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); - substs - .iter() - .zip(names) + iter::zip(substs, names) .filter_map(|(kind, name)| { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index af366f93b9..fc6c1abf4a 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1053,46 +1053,48 @@ fn generic_simd_intrinsic( let vec_ty = bx.type_vector(elem_ty, in_len); let (intr_name, fn_ty) = match name { - sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)), sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)), - sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), + sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), _ => return_error!("unrecognized intrinsic `{}`", name), }; - let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let f = bx.declare_cfn(&llvm_name, llvm::UnnamedAddr::No, fn_ty); let c = bx.call(f, &args.iter().map(|arg| arg.immediate()).collect::>(), None); - unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) }; Ok(c) } if std::matches!( name, - sym::simd_fsqrt - | sym::simd_fsin - | sym::simd_fcos + sym::simd_ceil | sym::simd_fabs - | sym::simd_floor - | sym::simd_ceil - | sym::simd_fexp + | sym::simd_fcos | sym::simd_fexp2 + | sym::simd_fexp | sym::simd_flog10 | sym::simd_flog2 | sym::simd_flog - | sym::simd_fpowi - | sym::simd_fpow + | sym::simd_floor | sym::simd_fma + | sym::simd_fpow + | sym::simd_fpowi + | sym::simd_fsin + | sym::simd_fsqrt + | sym::simd_round + | sym::simd_trunc ) { return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args); } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index d11c1592f9..5ca4b226c3 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,10 +8,12 @@ #![feature(bool_to_option)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] +#![feature(extended_key_value_attributes)] #![feature(extern_types)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] use back::write::{create_informational_target_machine, create_target_machine}; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 82cd1be3b3..32b1526f6e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -190,33 +190,6 @@ pub enum RealPredicate { RealPredicateTrue = 15, } -impl RealPredicate { - pub fn from_generic(realpred: rustc_codegen_ssa::common::RealPredicate) -> Self { - match realpred { - rustc_codegen_ssa::common::RealPredicate::RealPredicateFalse => { - RealPredicate::RealPredicateFalse - } - rustc_codegen_ssa::common::RealPredicate::RealOEQ => RealPredicate::RealOEQ, - rustc_codegen_ssa::common::RealPredicate::RealOGT => RealPredicate::RealOGT, - rustc_codegen_ssa::common::RealPredicate::RealOGE => RealPredicate::RealOGE, - rustc_codegen_ssa::common::RealPredicate::RealOLT => RealPredicate::RealOLT, - rustc_codegen_ssa::common::RealPredicate::RealOLE => RealPredicate::RealOLE, - rustc_codegen_ssa::common::RealPredicate::RealONE => RealPredicate::RealONE, - rustc_codegen_ssa::common::RealPredicate::RealORD => RealPredicate::RealORD, - rustc_codegen_ssa::common::RealPredicate::RealUNO => RealPredicate::RealUNO, - rustc_codegen_ssa::common::RealPredicate::RealUEQ => RealPredicate::RealUEQ, - rustc_codegen_ssa::common::RealPredicate::RealUGT => RealPredicate::RealUGT, - rustc_codegen_ssa::common::RealPredicate::RealUGE => RealPredicate::RealUGE, - rustc_codegen_ssa::common::RealPredicate::RealULT => RealPredicate::RealULT, - rustc_codegen_ssa::common::RealPredicate::RealULE => RealPredicate::RealULE, - rustc_codegen_ssa::common::RealPredicate::RealUNE => RealPredicate::RealUNE, - rustc_codegen_ssa::common::RealPredicate::RealPredicateTrue => { - RealPredicate::RealPredicateTrue - } - } - } -} - /// LLVMTypeKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] @@ -711,7 +684,7 @@ pub mod coverageinfo { } impl CounterMappingRegion { - pub fn code_region( + crate fn code_region( counter: coverage_map::Counter, file_id: u32, start_line: u32, @@ -731,7 +704,10 @@ pub mod coverageinfo { } } - pub fn expansion_region( + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + crate fn expansion_region( file_id: u32, expanded_file_id: u32, start_line: u32, @@ -751,7 +727,10 @@ pub mod coverageinfo { } } - pub fn skipped_region( + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + crate fn skipped_region( file_id: u32, start_line: u32, start_col: u32, @@ -770,7 +749,10 @@ pub mod coverageinfo { } } - pub fn gap_region( + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + crate fn gap_region( counter: coverage_map::Counter, file_id: u32, start_line: u32, @@ -1031,6 +1013,7 @@ extern "C" { pub fn LLVMSetSection(Global: &Value, Section: *const c_char); pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); + pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool); pub fn LLVMGetAlignment(Global: &Value) -> c_uint; pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint); pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass); @@ -1371,7 +1354,7 @@ extern "C" { pub fn LLVMBuildNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMBuildFNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMBuildNot(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; - pub fn LLVMRustSetHasUnsafeAlgebra(Instr: &Value); + pub fn LLVMRustSetFastMath(Instr: &Value); // Memory pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; @@ -2145,7 +2128,13 @@ extern "C" { pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine); - pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine); + pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; + pub fn LLVMRustGetTargetFeature( + T: &TargetMachine, + Index: size_t, + Feature: &mut *const c_char, + Desc: &mut *const c_char, + ); pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char; pub fn LLVMRustCreateTargetMachine( diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index c7dff41955..97684ca6c1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,5 +1,5 @@ use crate::back::write::create_informational_target_machine; -use crate::llvm; +use crate::{llvm, llvm_util}; use libc::c_int; use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxHashSet; @@ -10,6 +10,7 @@ use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; use std::ffi::{CStr, CString}; +use std::ptr; use std::slice; use std::str; use std::sync::atomic::{AtomicBool, Ordering}; @@ -83,6 +84,17 @@ unsafe fn configure_llvm(sess: &Session) { if !sess.opts.debugging_opts.no_generate_arange_section { add("-generate-arange-section", false); } + + // FIXME(nagisa): disable the machine outliner by default in LLVM versions 11, where it was + // introduced and up. + // + // This should remain in place until https://reviews.llvm.org/D103167 is fixed. If LLVM + // has been upgraded since, consider adjusting the version check below to contain an upper + // bound. + if llvm_util::get_version() >= (11, 0, 0) { + add("-enable-machine-outliner=never", false); + } + match sess.opts.debugging_opts.merge_functions.unwrap_or(sess.target.merge_functions) { MergeFunctions::Disabled | MergeFunctions::Trampolines => {} MergeFunctions::Aliases => { @@ -98,6 +110,9 @@ unsafe fn configure_llvm(sess: &Session) { // during inlining. Unfortunately these may block other optimizations. add("-preserve-alignment-assumptions-during-inlining=false", false); + // Use non-zero `import-instr-limit` multiplier for cold callsites. + add("-import-cold-multiplier=0.1", false); + for arg in sess_args { add(&(*arg), true); } @@ -189,15 +204,77 @@ pub fn print_passes() { } } +fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> { + let len = unsafe { llvm::LLVMRustGetTargetFeaturesCount(tm) }; + let mut ret = Vec::with_capacity(len); + for i in 0..len { + unsafe { + let mut feature = ptr::null(); + let mut desc = ptr::null(); + llvm::LLVMRustGetTargetFeature(tm, i, &mut feature, &mut desc); + if feature.is_null() || desc.is_null() { + bug!("LLVM returned a `null` target feature string"); + } + let feature = CStr::from_ptr(feature).to_str().unwrap_or_else(|e| { + bug!("LLVM returned a non-utf8 feature string: {}", e); + }); + let desc = CStr::from_ptr(desc).to_str().unwrap_or_else(|e| { + bug!("LLVM returned a non-utf8 feature string: {}", e); + }); + ret.push((feature, desc)); + } + } + ret +} + +fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) { + let mut target_features = llvm_target_features(tm); + let mut rustc_target_features = supported_target_features(sess) + .iter() + .filter_map(|(feature, _gate)| { + let llvm_feature = to_llvm_feature(sess, *feature); + // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. + target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| { + let (_f, desc) = target_features.remove(index); + (*feature, desc) + }) + }) + .collect::>(); + rustc_target_features.extend_from_slice(&[( + "crt-static", + "Enables C Run-time Libraries to be statically linked", + )]); + let max_feature_len = target_features + .iter() + .chain(rustc_target_features.iter()) + .map(|(feature, _desc)| feature.len()) + .max() + .unwrap_or(0); + + println!("Features supported by rustc for this target:"); + for (feature, desc) in &rustc_target_features { + println!(" {1:0$} - {2}.", max_feature_len, feature, desc); + } + println!("\nCode-generation features supported by LLVM for this target:"); + for (feature, desc) in &target_features { + println!(" {1:0$} - {2}.", max_feature_len, feature, desc); + } + if target_features.len() == 0 { + println!(" Target features listing is not supported by this LLVM version."); + } + println!("\nUse +feature to enable a feature, or -feature to disable it."); + println!("For example, rustc -C target-cpu=mycpu -C target-feature=+feature1,-feature2\n"); + println!("Code-generation features cannot be used in cfg or #[target_feature],"); + println!("and may be renamed or removed in a future version of LLVM or rustc.\n"); +} + pub(crate) fn print(req: PrintRequest, sess: &Session) { require_inited(); let tm = create_informational_target_machine(sess); - unsafe { - match req { - PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm), - PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm), - _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), - } + match req { + PrintRequest::TargetCPUs => unsafe { llvm::LLVMRustPrintTargetCPUs(tm) }, + PrintRequest::TargetFeatures => print_target_features(sess, tm), + _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), } } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 992e83d08f..fc1f364e9c 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -10,7 +10,9 @@ pub use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::FnAbiExt; use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_session::config::CrateType; use rustc_target::abi::LayoutOf; +use rustc_target::spec::RelocModel; use tracing::debug; impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -35,6 +37,9 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage)); llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility)); + if self.should_assume_dso_local(linkage, visibility) { + llvm::LLVMRustSetDSOLocal(g, true); + } } self.instances.borrow_mut().insert(instance, g); @@ -79,6 +84,42 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { attributes::from_fn_attrs(self, lldecl, instance); + unsafe { + if self.should_assume_dso_local(linkage, visibility) { + llvm::LLVMRustSetDSOLocal(lldecl, true); + } + } + self.instances.borrow_mut().insert(instance, lldecl); } } + +impl CodegenCx<'ll, 'tcx> { + /// Whether a definition (NB: not declaration!) can be assumed to be local to a group of + /// libraries that form a single DSO or executable. + pub(crate) unsafe fn should_assume_dso_local( + &self, + linkage: Linkage, + visibility: Visibility, + ) -> bool { + if matches!(linkage, Linkage::Internal | Linkage::Private) { + return true; + } + + if visibility != Visibility::Default && linkage != Linkage::ExternalWeak { + return true; + } + + // Static relocation model should force copy relocations everywhere. + if self.tcx.sess.relocation_model() == RelocModel::Static { + return true; + } + + // Symbols from executables can't really be imported any further. + if self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) { + return true; + } + + return false; + } +} diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 15dbbbd49a..7a3d715df6 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -11,11 +11,10 @@ test = false bitflags = "1.2.1" cc = "1.0.1" itertools = "0.9" -memmap2 = "0.2.1" tracing = "0.1" libc = "0.2.50" -jobserver = "0.1.11" -tempfile = "3.1" +jobserver = "0.1.22" +tempfile = "3.2" pathdiff = "0.2.0" rustc_serialize = { path = "../rustc_serialize" } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b11821b7db..ea75943d6f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::CrateNum; use rustc_middle::middle::cstore::{EncodedMetadata, LibSource}; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo}; -use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet}; +use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; @@ -16,7 +16,7 @@ use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; -use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target}; +use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; use super::archive::ArchiveBuilder; use super::command::Command; @@ -922,28 +922,20 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { .map(|channel| format!("-{}", channel)) .unwrap_or_default(); - match sess.opts.target_triple.triple() { - "aarch64-apple-darwin" | "x86_64-apple-darwin" => { - // On Apple platforms, the sanitizer is always built as a dylib, and - // LLVM will link to `@rpath/*.dylib`, so we need to specify an - // rpath to the library as well (the rpath should be absolute, see - // PR #41352 for details). - let filename = format!("rustc{}_rt.{}", channel, name); - let path = find_sanitizer_runtime(&sess, &filename); - let rpath = path.to_str().expect("non-utf8 component in path"); - linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); - linker.link_dylib(Symbol::intern(&filename)); - } - "aarch64-fuchsia" - | "aarch64-unknown-linux-gnu" - | "x86_64-fuchsia" - | "x86_64-unknown-freebsd" - | "x86_64-unknown-linux-gnu" => { - let filename = format!("librustc{}_rt.{}.a", channel, name); - let path = find_sanitizer_runtime(&sess, &filename).join(&filename); - linker.link_whole_rlib(&path); - } - _ => {} + if sess.target.is_like_osx { + // On Apple platforms, the sanitizer is always built as a dylib, and + // LLVM will link to `@rpath/*.dylib`, so we need to specify an + // rpath to the library as well (the rpath should be absolute, see + // PR #41352 for details). + let filename = format!("rustc{}_rt.{}", channel, name); + let path = find_sanitizer_runtime(&sess, &filename); + let rpath = path.to_str().expect("non-utf8 component in path"); + linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); + linker.link_dylib(Symbol::intern(&filename)); + } else { + let filename = format!("librustc{}_rt.{}.a", channel, name); + let path = find_sanitizer_runtime(&sess, &filename).join(&filename); + linker.link_whole_rlib(&path); } } @@ -1419,15 +1411,10 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty } } -/// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes. +/// Add arbitrary "user defined" args defined from command line. /// FIXME: Determine where exactly these args need to be inserted. -fn add_user_defined_link_args( - cmd: &mut dyn Linker, - sess: &Session, - codegen_results: &CodegenResults, -) { +fn add_user_defined_link_args(cmd: &mut dyn Linker, sess: &Session) { cmd.args(&sess.opts.cg.link_args); - cmd.args(&*codegen_results.crate_info.link_args); } /// Add arbitrary "late link" args defined by the target spec. @@ -1651,6 +1638,16 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( cmd.add_eh_frame_header(); } + // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER + // Make the binary compatible with data execution prevention schemes. + cmd.add_no_exec(); + + // NO-OPT-OUT, OBJECT-FILES-NO + // Avoid linking to dynamic libraries unless they satisfy some undefined symbols + // at the point at which they are specified on the command line. + // Must be passed before any dynamic libraries. + cmd.add_as_needed(); + // NO-OPT-OUT, OBJECT-FILES-NO if crt_objects_fallback { cmd.no_crt_objects(); @@ -1746,7 +1743,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( ); // OBJECT-FILES-NO, AUDIT-ORDER - if sess.opts.cg.profile_generate.enabled() || sess.opts.debugging_opts.instrument_coverage { + if sess.opts.cg.profile_generate.enabled() || sess.instrument_coverage() { cmd.pgo_gen(); } @@ -1759,7 +1756,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( add_rpath_args(cmd, sess, codegen_results, out_filename); // OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT - add_user_defined_link_args(cmd, sess, codegen_results); + add_user_defined_link_args(cmd, sess); // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER cmd.finalize(); diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index bb35e7ec89..77d8ab49ff 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -130,6 +130,8 @@ pub trait Linker { fn group_end(&mut self); fn linker_plugin_lto(&mut self); fn add_eh_frame_header(&mut self) {} + fn add_no_exec(&mut self) {} + fn add_as_needed(&mut self) {} fn finalize(&mut self); } @@ -184,7 +186,7 @@ impl<'a> GccLinker<'a> { // * On OSX they have their own linker, not binutils' // * For WebAssembly the only functional linker is LLD, which doesn't // support hint flags - !self.sess.target.is_like_osx && self.sess.target.arch != "wasm32" + !self.sess.target.is_like_osx && !self.sess.target.is_like_wasm } // Some platforms take hints about whether a library is static or dynamic. @@ -641,6 +643,20 @@ impl<'a> Linker for GccLinker<'a> { fn add_eh_frame_header(&mut self) { self.linker_arg("--eh-frame-hdr"); } + + fn add_no_exec(&mut self) { + if self.sess.target.is_like_windows { + self.linker_arg("--nxcompat"); + } else if self.sess.target.linker_is_gnu { + self.linker_arg("-znoexecstack"); + } + } + + fn add_as_needed(&mut self) { + if self.sess.target.linker_is_gnu { + self.linker_arg("--as-needed"); + } + } } pub struct MsvcLinker<'a> { @@ -878,6 +894,10 @@ impl<'a> Linker for MsvcLinker<'a> { fn linker_plugin_lto(&mut self) { // Do nothing } + + fn add_no_exec(&mut self) { + self.cmd.arg("/NXCOMPAT"); + } } pub struct EmLinker<'a> { diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index c6aea22a63..0ff0522946 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -2,6 +2,7 @@ use super::write::CodegenContext; use crate::traits::*; use crate::ModuleCodegen; +use rustc_data_structures::memmap::Mmap; use rustc_errors::FatalError; use std::ffi::CString; @@ -93,7 +94,7 @@ impl LtoModuleCodegen { pub enum SerializedModule { Local(M), FromRlib(Vec), - FromUncompressedFile(memmap2::Mmap), + FromUncompressedFile(Mmap), } impl SerializedModule { diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 9a6f8cde1b..b8f277c8ff 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -15,7 +15,8 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; use rustc_middle::ty::{SymbolName, TyCtxt}; -use rustc_session::config::{CrateType, SanitizerSet}; +use rustc_session::config::CrateType; +use rustc_target::spec::SanitizerSet; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(&tcx.sess.crate_types()) @@ -188,9 +189,7 @@ fn exported_symbols_provider_local( } } - if tcx.sess.opts.debugging_opts.instrument_coverage - || tcx.sess.opts.cg.profile_generate.enabled() - { + if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { // These are weak symbols that point to the profile version and the // profile name, which need to be treated as exported so LTO doesn't nix // them. diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 490b3d3311..c8688faa80 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -10,6 +10,7 @@ use crate::{ use crate::traits::*; use jobserver::{Acquired, Client}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::profiling::VerboseTimingGuard; @@ -27,12 +28,12 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel; use rustc_middle::ty::TyCtxt; use rustc_session::cgu_reuse_tracker::CguReuseTracker; use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType}; -use rustc_session::config::{Passes, SanitizerSet, SwitchWithOptPath}; +use rustc_session::config::{Passes, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; -use rustc_target::spec::{MergeFunctions, PanicStrategy}; +use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet}; use std::any::Any; use std::fs; @@ -106,7 +107,7 @@ pub struct ModuleConfig { pub vectorize_loop: bool, pub vectorize_slp: bool, pub merge_functions: bool, - pub inline_threshold: Option, + pub inline_threshold: Option, pub new_llvm_pass_manager: bool, pub emit_lifetime_markers: bool, } @@ -176,7 +177,7 @@ impl ModuleConfig { // The rustc option `-Zinstrument_coverage` injects intrinsic calls to // `llvm.instrprof.increment()`, which requires the LLVM `instrprof` pass. - if sess.opts.debugging_opts.instrument_coverage { + if sess.instrument_coverage() { passes.push("instrprof".to_owned()); } passes @@ -1093,7 +1094,7 @@ fn start_executing_work( // only place where we have access to the compiler `Session`. // - LLVM work can be done on any thread. // - Codegen can only happen on the main thread. - // - Each thread doing substantial work most be in possession of a `Token` + // - Each thread doing substantial work must be in possession of a `Token` // from the `Jobserver`. // - The compiler process always holds one `Token`. Any additional `Tokens` // have to be requested from the `Jobserver`. @@ -1145,7 +1146,7 @@ fn start_executing_work( // if possible. These two goals are at odds with each other: If memory // consumption were not an issue, we could just let the main thread produce // LLVM WorkItems at full speed, assuring maximal utilization of - // Tokens/LLVM worker threads. However, since codegen usual is faster + // Tokens/LLVM worker threads. However, since codegen is usually faster // than LLVM processing, the queue of LLVM WorkItems would fill up and each // WorkItem potentially holds on to a substantial amount of memory. // @@ -1958,7 +1959,7 @@ pub fn submit_pre_lto_module_to_llvm( .unwrap_or_else(|e| panic!("failed to open bitcode file `{}`: {}", bc_path.display(), e)); let mmap = unsafe { - memmap2::Mmap::map(&file).unwrap_or_else(|e| { + Mmap::map(file).unwrap_or_else(|e| { panic!("failed to mmap bitcode file `{}`: {}", bc_path.display(), e) }) }; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 08e31c3b37..e045a23eb0 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::{par_iter, ParallelIterator}; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; @@ -348,12 +348,29 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, ) -> Option { let main_def_id = cx.tcx().entry_fn(LOCAL_CRATE).map(|(def_id, _)| def_id)?; - let instance = Instance::mono(cx.tcx(), main_def_id.to_def_id()); + let main_is_local = main_def_id.is_local(); + let instance = Instance::mono(cx.tcx(), main_def_id); - if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) { + if main_is_local { // We want to create the wrapper in the same codegen unit as Rust's main // function. - return None; + if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) { + return None; + } + } else { + // FIXME: Add support for non-local main fn codegen + let span = cx.tcx().main_def.unwrap().span; + let n = 28937; + cx.sess() + .struct_span_err(span, "entry symbol `main` from foreign crate is not yet supported.") + .note(&format!( + "see issue #{} \ + for more information", + n, n, + )) + .emit(); + cx.sess().abort_if_errors(); + bug!(); } let main_llfn = cx.get_fn_addr(instance); @@ -366,7 +383,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, rust_main: Bx::Value, - rust_main_def_id: LocalDefId, + rust_main_def_id: DefId, use_start_lang_item: bool, ) -> Bx::Function { // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, @@ -754,7 +771,6 @@ impl CrateInfo { is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(), - link_args: tcx.link_args(LOCAL_CRATE), crate_name: Default::default(), used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic), used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic), diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs index af6c476292..962c01c2ee 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs @@ -24,21 +24,39 @@ pub enum CounterKind { pub struct Counter { // Important: The layout (order and types of fields) must match its C++ counterpart. pub kind: CounterKind, - pub id: u32, + id: u32, } impl Counter { + /// Constructs a new `Counter` of kind `Zero`. For this `CounterKind`, the + /// `id` is not used. pub fn zero() -> Self { Self { kind: CounterKind::Zero, id: 0 } } + /// Constructs a new `Counter` of kind `CounterValueReference`, and converts + /// the given 1-based counter_id to the required 0-based equivalent for + /// the `Counter` encoding. pub fn counter_value_reference(counter_id: CounterValueReference) -> Self { - Self { kind: CounterKind::CounterValueReference, id: counter_id.into() } + Self { kind: CounterKind::CounterValueReference, id: counter_id.zero_based_index() } } + /// Constructs a new `Counter` of kind `Expression`. pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self { Self { kind: CounterKind::Expression, id: mapped_expression_index.into() } } + + /// Returns true if the `Counter` kind is `Zero`. + pub fn is_zero(&self) -> bool { + matches!(self.kind, CounterKind::Zero) + } + + /// An explicitly-named function to get the ID value, making it more obvious + /// that the stored value is now 0-based. + pub fn zero_based_id(&self) -> u32 { + debug_assert!(!self.is_zero(), "`id` is undefined for CounterKind::Zero"); + self.id + } } /// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147) diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index af6482fdbc..4458fd6867 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -31,27 +31,44 @@ pub struct Expression { pub struct FunctionCoverage<'tcx> { instance: Instance<'tcx>, source_hash: u64, + is_used: bool, counters: IndexVec>, expressions: IndexVec>, unreachable_regions: Vec, } impl<'tcx> FunctionCoverage<'tcx> { + /// Creates a new set of coverage data for a used (called) function. pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + Self::create(tcx, instance, true) + } + + /// Creates a new set of coverage data for an unused (never called) function. + pub fn unused(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + Self::create(tcx, instance, false) + } + + fn create(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, is_used: bool) -> Self { let coverageinfo = tcx.coverageinfo(instance.def_id()); debug!( - "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}", - instance, coverageinfo + "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}. is_used={}", + instance, coverageinfo, is_used ); Self { instance, source_hash: 0, // will be set with the first `add_counter()` + is_used, counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), unreachable_regions: Vec::new(), } } + /// Returns true for a used (called) function, and false for an unused function. + pub fn is_used(&self) -> bool { + self.is_used + } + /// Sets the function source hash value. If called multiple times for the same function, all /// calls should have the same hash value. pub fn set_function_source_hash(&mut self, source_hash: u64) { @@ -128,8 +145,8 @@ impl<'tcx> FunctionCoverage<'tcx> { &'a self, ) -> (Vec, impl Iterator) { assert!( - self.source_hash != 0, - "No counters provided the source_hash for function: {:?}", + self.source_hash != 0 || !self.is_used, + "No counters provided the source_hash for used function: {:?}", self.instance ); @@ -146,9 +163,7 @@ impl<'tcx> FunctionCoverage<'tcx> { self.counters.iter_enumerated().filter_map(|(index, entry)| { // Option::map() will return None to filter out missing counters. This may happen // if, for example, a MIR-instrumented counter is removed during an optimization. - entry.as_ref().map(|region| { - (Counter::counter_value_reference(index as CounterValueReference), region) - }) + entry.as_ref().map(|region| (Counter::counter_value_reference(index), region)) }) } @@ -189,9 +204,15 @@ impl<'tcx> FunctionCoverage<'tcx> { if id == ExpressionOperandId::ZERO { Some(Counter::zero()) } else if id.index() < self.counters.len() { + debug_assert!( + id.index() > 0, + "ExpressionOperandId indexes for counters are 1-based, but this id={}", + id.index() + ); // Note: Some codegen-injected Counters may be only referenced by `Expression`s, // and may not have their own `CodeRegion`s, let index = CounterValueReference::from(id.index()); + // Note, the conversion to LLVM `Counter` adjusts the index to be zero-based. Some(Counter::counter_value_reference(index)) } else { let index = self.expression_index(u32::from(id)); @@ -216,19 +237,60 @@ impl<'tcx> FunctionCoverage<'tcx> { let optional_region = &expression.region; let Expression { lhs, op, rhs, .. } = *expression; - if let Some(Some((lhs_counter, rhs_counter))) = - id_to_counter(&new_indexes, lhs).map(|lhs_counter| { + if let Some(Some((lhs_counter, mut rhs_counter))) = id_to_counter(&new_indexes, lhs) + .map(|lhs_counter| { id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter)) }) { + if lhs_counter.is_zero() && op.is_subtract() { + // The left side of a subtraction was probably optimized out. As an example, + // a branch condition might be evaluated as a constant expression, and the + // branch could be removed, dropping unused counters in the process. + // + // Since counters are unsigned, we must assume the result of the expression + // can be no more and no less than zero. An expression known to evaluate to zero + // does not need to be added to the coverage map. + // + // Coverage test `loops_branches.rs` includes multiple variations of branches + // based on constant conditional (literal `true` or `false`), and demonstrates + // that the expected counts are still correct. + debug!( + "Expression subtracts from zero (assume unreachable): \ + original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", + original_index, lhs, op, rhs, optional_region, + ); + rhs_counter = Counter::zero(); + } debug_assert!( - (lhs_counter.id as usize) - < usize::max(self.counters.len(), self.expressions.len()) + lhs_counter.is_zero() + // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` + || ((lhs_counter.zero_based_id() as usize) + <= usize::max(self.counters.len(), self.expressions.len())), + "lhs id={} > both counters.len()={} and expressions.len()={} + ({:?} {:?} {:?})", + lhs_counter.zero_based_id(), + self.counters.len(), + self.expressions.len(), + lhs_counter, + op, + rhs_counter, ); + debug_assert!( - (rhs_counter.id as usize) - < usize::max(self.counters.len(), self.expressions.len()) + rhs_counter.is_zero() + // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` + || ((rhs_counter.zero_based_id() as usize) + <= usize::max(self.counters.len(), self.expressions.len())), + "rhs id={} > both counters.len()={} and expressions.len()={} + ({:?} {:?} {:?})", + rhs_counter.zero_based_id(), + self.counters.len(), + self.expressions.len(), + lhs_counter, + op, + rhs_counter, ); + // Both operands exist. `Expression` operands exist in `self.expressions` and have // been assigned a `new_index`. let mapped_expression_index = @@ -251,11 +313,15 @@ impl<'tcx> FunctionCoverage<'tcx> { expression_regions.push((Counter::expression(mapped_expression_index), region)); } } else { - debug!( - "Ignoring expression with one or more missing operands: \ - original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", - original_index, lhs, op, rhs, optional_region, - ) + bug!( + "expression has one or more missing operands \ + original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", + original_index, + lhs, + op, + rhs, + optional_region, + ); } } (counter_expressions, expression_regions.into_iter()) diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index ab9ea2f3e9..b761bb4e19 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -5,8 +5,9 @@ #![feature(try_blocks)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(associated_type_bounds)] +#![feature(iter_zip)] #![recursion_limit = "256"] #![feature(box_syntax)] @@ -137,7 +138,6 @@ pub struct CrateInfo { pub native_libraries: FxHashMap>, pub crate_name: FxHashMap, pub used_libraries: Vec, - pub link_args: Lrc>, pub used_crate_source: FxHashMap>, pub used_crates_static: Vec<(CrateNum, LibSource)>, pub used_crates_dynamic: Vec<(CrateNum, LibSource)>, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 04225ddd36..fd3f89a2ae 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -822,41 +822,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { InlineAsmOperandRef::InOut { reg, late, in_value, out_place } } mir::InlineAsmOperand::Const { ref value } => { - if let mir::Operand::Constant(constant) = value { - let const_value = self - .eval_mir_constant(constant) - .unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved")); - let ty = constant.ty(); - let size = bx.layout_of(ty).size; - let scalar = match const_value { - ConstValue::Scalar(s) => s, - _ => span_bug!( - span, - "expected Scalar for promoted asm const, but got {:#?}", - const_value - ), - }; - let value = scalar.assert_bits(size); - let string = match ty.kind() { - ty::Uint(_) => value.to_string(), - ty::Int(int_ty) => { - match int_ty.normalize(bx.tcx().sess.target.pointer_width) { - ty::IntTy::I8 => (value as i8).to_string(), - ty::IntTy::I16 => (value as i16).to_string(), - ty::IntTy::I32 => (value as i32).to_string(), - ty::IntTy::I64 => (value as i64).to_string(), - ty::IntTy::I128 => (value as i128).to_string(), - ty::IntTy::Isize => unreachable!(), - } + let const_value = self + .eval_mir_constant(value) + .unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved")); + let ty = value.ty(); + let size = bx.layout_of(ty).size; + let scalar = match const_value { + ConstValue::Scalar(s) => s, + _ => span_bug!( + span, + "expected Scalar for promoted asm const, but got {:#?}", + const_value + ), + }; + let value = scalar.assert_bits(size); + let string = match ty.kind() { + ty::Uint(_) => value.to_string(), + ty::Int(int_ty) => { + match int_ty.normalize(bx.tcx().sess.target.pointer_width) { + ty::IntTy::I8 => (value as i8).to_string(), + ty::IntTy::I16 => (value as i16).to_string(), + ty::IntTy::I32 => (value as i32).to_string(), + ty::IntTy::I64 => (value as i64).to_string(), + ty::IntTy::I128 => (value as i128).to_string(), + ty::IntTy::Isize => unreachable!(), } - ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(), - ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(), - _ => span_bug!(span, "asm const has bad type {}", ty), - }; - InlineAsmOperandRef::Const { string } - } else { - span_bug!(span, "asm const is not a constant"); - } + } + ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(), + ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(), + _ => span_bug!(span, "asm const has bad type {}", ty), + }; + InlineAsmOperandRef::Const { string } } mir::InlineAsmOperand::SymFn { ref value } => { let literal = self.monomorphize(value.literal); diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index aa41acc357..fa8a53e60b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -30,10 +30,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ConstantKind::Val(val, _) => return Ok(val), }; match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => self + ty::ConstKind::Unevaluated(ct) => self .cx .tcx() - .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None) + .const_eval_resolve(ty::ParamEnv::reveal_all(), ct, None) .map_err(|err| { self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); err diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index 5ab1baafb5..621ec0519c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -33,10 +33,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let coverageinfo = bx.tcx().coverageinfo(instance.def_id()); - let fn_name = bx.create_pgo_func_name_var(instance); + let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_source_hash); let num_counters = bx.const_u32(coverageinfo.num_counters); - let index = bx.const_u32(u32::from(id)); + let index = bx.const_u32(id.zero_based_index()); debug!( "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", fn_name, hash, num_counters, index, diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index a3f20abc82..6bb20545f0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -6,7 +6,7 @@ use rustc_middle::ty; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; -use rustc_target::abi::{LayoutOf, Size}; +use rustc_target::abi::Size; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; @@ -265,33 +265,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { None => continue, }; - let mut layout = base.layout; let mut direct_offset = Size::ZERO; // FIXME(eddyb) use smallvec here. let mut indirect_offsets = vec![]; + let mut place = base; for elem in &var.projection[..] { match *elem { mir::ProjectionElem::Deref => { indirect_offsets.push(Size::ZERO); - layout = bx.cx().layout_of( - layout - .ty - .builtin_deref(true) - .unwrap_or_else(|| { - span_bug!(var.source_info.span, "cannot deref `{}`", layout.ty) - }) - .ty, - ); + place = place.project_deref(bx); } mir::ProjectionElem::Field(field, _) => { let i = field.index(); let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset); - *offset += layout.fields.offset(i); - layout = layout.field(bx.cx(), i); + *offset += place.layout.fields.offset(i); + place = place.project_field(bx, i); } mir::ProjectionElem::Downcast(_, variant) => { - layout = layout.for_variant(bx.cx(), variant); + place = place.project_downcast(bx, variant); } _ => span_bug!( var.source_info.span, @@ -301,7 +293,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets); + // When targeting MSVC, create extra allocas for arguments instead of pointing multiple + // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records + // not DWARF and LLVM doesn't support translating the resulting + // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView. + // Creating extra allocas on the stack makes the resulting debug info simple enough + // that LLVM can generate correct CodeView records and thus the values appear in the + // debugger. (#83709) + let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc + && self.mir.local_kind(local) == mir::LocalKind::Arg + // LLVM can handle simple things but anything more complex than just a direct + // offset or one indirect offset of 0 is too complex for it to generate CV records + // correctly. + && (direct_offset != Size::ZERO + || !matches!(&indirect_offsets[..], [Size::ZERO] | [])); + + if should_create_individual_allocas { + // Create a variable which will be a pointer to the actual value + let ptr_ty = bx.tcx().mk_ty(ty::RawPtr(ty::TypeAndMut { + mutbl: mir::Mutability::Mut, + ty: place.layout.ty, + })); + let ptr_layout = bx.layout_of(ptr_ty); + let alloca = PlaceRef::alloca(bx, ptr_layout); + bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill")); + + // Write the pointer to the variable + bx.store(place.llval, alloca.llval, alloca.align); + + // Point the debug info to `*alloca` for the current variable + bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO]); + } else { + bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets); + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3f94547821..91df67b53d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -282,9 +282,7 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( IndexVec>, IndexVec>, ) { - block_bxs - .iter_enumerated() - .zip(cleanup_kinds) + iter::zip(block_bxs.iter_enumerated(), cleanup_kinds) .map(|((bb, &llbb), cleanup_kind)| { match *cleanup_kind { CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {} diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 66d9d1a1e0..a9e7ebf6d4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -402,6 +402,18 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { downcast } + pub fn project_deref>(&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>(&self, bx: &mut Bx) { bx.lifetime_start(self.llval, self.layout.size); } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 629cb64d43..9917c23f12 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -11,7 +11,7 @@ use rustc_apfloat::{ieee, Float, Round, Status}; use rustc_hir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::cast::{CastTy, IntTy}; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::sym; @@ -385,10 +385,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.inttoptr(usize_llval, ll_t_out) } (CastTy::Float, CastTy::Int(IntTy::I)) => { - cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out, cast) + cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out) } (CastTy::Float, CastTy::Int(_)) => { - cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out, cast) + cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out) } _ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty), }; @@ -790,7 +790,6 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( x: Bx::Value, float_ty: Bx::Type, int_ty: Bx::Type, - int_layout: TyAndLayout<'tcx>, ) -> Bx::Value { if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts { return if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; @@ -891,134 +890,39 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let int_min = bx.cx().const_uint_big(int_ty, int_min(signed, int_width) as u128); let zero = bx.cx().const_uint(int_ty, 0); - // The codegen here differs quite a bit depending on whether our builder's - // `fptosi` and `fptoui` instructions may trap for out-of-bounds values. If - // they don't trap then we can start doing everything inline with a - // `select` instruction because it's ok to execute `fptosi` and `fptoui` - // even if we don't use the results. - if !bx.fptosui_may_trap(x, int_ty) { - // Step 1 ... - let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; - let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); - let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); - - // Step 2: We use two comparisons and two selects, with %s1 being the - // result: - // %less_or_nan = fcmp ult %x, %f_min - // %greater = fcmp olt %x, %f_max - // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result - // %s1 = select %greater, int_ty::MAX, %s0 - // Note that %less_or_nan uses an *unordered* comparison. This - // comparison is true if the operands are not comparable (i.e., if x is - // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if - // x is NaN. - // - // Performance note: Unordered comparison can be lowered to a "flipped" - // comparison and a negation, and the negation can be merged into the - // select. Therefore, it not necessarily any more expensive than a - // ordered ("normal") comparison. Whether these optimizations will be - // performed is ultimately up to the backend, but at least x86 does - // perform them. - let s0 = bx.select(less_or_nan, int_min, fptosui_result); - let s1 = bx.select(greater, int_max, s0); - - // Step 3: NaN replacement. - // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. - // Therefore we only need to execute this step for signed integer types. - if signed { - // LLVM has no isNaN predicate, so we use (x == x) instead - let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); - bx.select(cmp, s1, zero) - } else { - s1 - } + // Step 1 ... + let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; + let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); + let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); + + // Step 2: We use two comparisons and two selects, with %s1 being the + // result: + // %less_or_nan = fcmp ult %x, %f_min + // %greater = fcmp olt %x, %f_max + // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result + // %s1 = select %greater, int_ty::MAX, %s0 + // Note that %less_or_nan uses an *unordered* comparison. This + // comparison is true if the operands are not comparable (i.e., if x is + // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if + // x is NaN. + // + // Performance note: Unordered comparison can be lowered to a "flipped" + // comparison and a negation, and the negation can be merged into the + // select. Therefore, it not necessarily any more expensive than a + // ordered ("normal") comparison. Whether these optimizations will be + // performed is ultimately up to the backend, but at least x86 does + // perform them. + let s0 = bx.select(less_or_nan, int_min, fptosui_result); + let s1 = bx.select(greater, int_max, s0); + + // Step 3: NaN replacement. + // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. + // Therefore we only need to execute this step for signed integer types. + if signed { + // LLVM has no isNaN predicate, so we use (x == x) instead + let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); + bx.select(cmp, s1, zero) } else { - // In this case we cannot execute `fptosi` or `fptoui` and then later - // discard the result. The builder is telling us that these instructions - // will trap on out-of-bounds values, so we need to use basic blocks and - // control flow to avoid executing the `fptosi` and `fptoui` - // instructions. - // - // The general idea of what we're constructing here is, for f64 -> i32: - // - // ;; block so far... %0 is the argument - // %result = alloca i32, align 4 - // %inbound_lower = fcmp oge double %0, 0xC1E0000000000000 - // %inbound_upper = fcmp ole double %0, 0x41DFFFFFFFC00000 - // ;; match (inbound_lower, inbound_upper) { - // ;; (true, true) => %0 can be converted without trapping - // ;; (false, false) => %0 is a NaN - // ;; (true, false) => %0 is too large - // ;; (false, true) => %0 is too small - // ;; } - // ;; - // ;; The (true, true) check, go to %convert if so. - // %inbounds = and i1 %inbound_lower, %inbound_upper - // br i1 %inbounds, label %convert, label %specialcase - // - // convert: - // %cvt = call i32 @llvm.wasm.trunc.signed.i32.f64(double %0) - // store i32 %cvt, i32* %result, align 4 - // br label %done - // - // specialcase: - // ;; Handle the cases where the number is NaN, too large or too small - // - // ;; Either (true, false) or (false, true) - // %is_not_nan = or i1 %inbound_lower, %inbound_upper - // ;; Figure out which saturated value we are interested in if not `NaN` - // %saturated = select i1 %inbound_lower, i32 2147483647, i32 -2147483648 - // ;; Figure out between saturated and NaN representations - // %result_nan = select i1 %is_not_nan, i32 %saturated, i32 0 - // store i32 %result_nan, i32* %result, align 4 - // br label %done - // - // done: - // %r = load i32, i32* %result, align 4 - // ;; ... - let done = bx.build_sibling_block("float_cast_done"); - let mut convert = bx.build_sibling_block("float_cast_convert"); - let mut specialcase = bx.build_sibling_block("float_cast_specialcase"); - - let result = PlaceRef::alloca(bx, int_layout); - result.storage_live(bx); - - // Use control flow to figure out whether we can execute `fptosi` in a - // basic block, or whether we go to a different basic block to implement - // the saturating logic. - let inbound_lower = bx.fcmp(RealPredicate::RealOGE, x, f_min); - let inbound_upper = bx.fcmp(RealPredicate::RealOLE, x, f_max); - let inbounds = bx.and(inbound_lower, inbound_upper); - bx.cond_br(inbounds, convert.llbb(), specialcase.llbb()); - - // Translation of the `convert` basic block - let cvt = if signed { convert.fptosi(x, int_ty) } else { convert.fptoui(x, int_ty) }; - convert.store(cvt, result.llval, result.align); - convert.br(done.llbb()); - - // Translation of the `specialcase` basic block. Note that like above - // we try to be a bit clever here for unsigned conversions. In those - // cases the `int_min` is zero so we don't need two select instructions, - // just one to choose whether we need `int_max` or not. If - // `inbound_lower` is true then we're guaranteed to not be `NaN` and - // since we're greater than zero we must be saturating to `int_max`. If - // `inbound_lower` is false then we're either NaN or less than zero, so - // we saturate to zero. - let result_nan = if signed { - let is_not_nan = specialcase.or(inbound_lower, inbound_upper); - let saturated = specialcase.select(inbound_lower, int_max, int_min); - specialcase.select(is_not_nan, saturated, zero) - } else { - specialcase.select(inbound_lower, int_max, int_min) - }; - specialcase.store(result_nan, result.llval, result.align); - specialcase.br(done.llbb()); - - // Translation of the `done` basic block, positioning ourselves to - // continue from that point as well. - *bx = done; - let ret = bx.load(result.llval, result.align); - result.storage_dead(bx); - ret + s1 } } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index fd18f42f2d..4e987908b4 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -26,6 +26,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("vfp2", Some(sym::arm_target_feature)), ("vfp3", Some(sym::arm_target_feature)), ("vfp4", Some(sym::arm_target_feature)), + ("fp-armv8", Some(sym::arm_target_feature)), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. @@ -160,7 +161,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt "mips" | "mips64" => MIPS_ALLOWED_FEATURES, "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, - "wasm32" => WASM_ALLOWED_FEATURES, + "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, _ => &[], } } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index d5bd278038..1bc05f30e5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -171,7 +171,6 @@ pub trait BuilderMethods<'a, 'tcx>: fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; - fn fptosui_may_trap(&self, val: Self::Value, dest_ty: Self::Type) -> bool; fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index 95bddfb4b4..cbf570dba4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -1,14 +1,26 @@ use super::BackendTypes; +use rustc_hir::def_id::DefId; use rustc_middle::mir::coverage::*; use rustc_middle::ty::Instance; -pub trait CoverageInfoMethods: BackendTypes { +pub trait CoverageInfoMethods<'tcx>: BackendTypes { fn coverageinfo_finalize(&self); + + /// Codegen a small function that will never be called, with one counter + /// that will never be incremented, that gives LLVM coverage tools a + /// function definition it needs in order to resolve coverage map references + /// to unused functions. This is necessary so unused functions will appear + /// as uncovered (coverage execution count `0`) in LLVM coverage reports. + fn define_unused_fn(&self, def_id: DefId); + + /// For LLVM codegen, returns a function-specific `Value` for a global + /// string, to hold the function name passed to LLVM intrinsic + /// `instrprof.increment()`. The `Value` is only created once per instance. + /// Multiple invocations with the same instance return the same `Value`. + fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; } pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { - fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; - /// Returns true if the function source hash was added to the coverage map (even if it had /// already been added, for this instance). Returns false *only* if `-Z instrument-coverage` is /// not enabled (a coverage map is not being generated). diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index 8ada6c1047..be2e0ea230 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -58,7 +58,7 @@ pub trait CodegenMethods<'tcx>: + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods + + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods + PreDefineMethods<'tcx> @@ -74,7 +74,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods + + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods + PreDefineMethods<'tcx> diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 2e5a86b14c..aa95ecbdaf 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" doctest = false [dependencies] -arrayvec = { version = "0.5.1", default-features = false } +arrayvec = { version = "0.7", default-features = false } ena = "0.14" indexmap = "1.5.1" tracing = "0.1" @@ -17,7 +17,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" } rustc_graphviz = { path = "../rustc_graphviz" } cfg-if = "0.1.2" -crossbeam-utils = { version = "0.7", features = ["nightly"] } +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" } @@ -28,11 +28,13 @@ bitflags = "1.2.1" measureme = "9.1.0" libc = "0.2" stacker = "0.1.12" -tempfile = "3.0.5" +tempfile = "3.2" [dependencies.parking_lot] version = "0.11" -features = ["nightly"] [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["fileapi", "psapi"] } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +memmap2 = "0.2.1" diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index 681b49e2ea..c0c0e7be3c 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -1,10 +1,7 @@ use crate::stable_hasher; -use rustc_serialize::{ - opaque::{self, EncodeResult, FileEncodeResult}, - Decodable, Encodable, -}; +use rustc_serialize::{Decodable, Encodable}; +use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use std::mem::{self, MaybeUninit}; #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)] #[repr(C)] @@ -64,14 +61,27 @@ impl Fingerprint { format!("{:x}{:x}", self.0, self.1) } - pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result { - let mut bytes: [MaybeUninit; 16] = MaybeUninit::uninit_array(); + #[inline] + pub fn to_le_bytes(&self) -> [u8; 16] { + // This seems to optimize to the same machine code as + // `unsafe { mem::transmute(*k) }`. Well done, LLVM! :) + let mut result = [0u8; 16]; + + let first_half: &mut [u8; 8] = (&mut result[0..8]).try_into().unwrap(); + *first_half = self.0.to_le_bytes(); - decoder.read_raw_bytes(&mut bytes)?; + let second_half: &mut [u8; 8] = (&mut result[8..16]).try_into().unwrap(); + *second_half = self.1.to_le_bytes(); - let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) }; + result + } - Ok(Fingerprint(u64::from_le(l), u64::from_le(r))) + #[inline] + pub fn from_le_bytes(bytes: [u8; 16]) -> Fingerprint { + Fingerprint( + u64::from_le_bytes(bytes[0..8].try_into().unwrap()), + u64::from_le_bytes(bytes[8..16].try_into().unwrap()), + ) } } @@ -130,55 +140,19 @@ impl stable_hasher::StableHasherResult for Fingerprint { impl_stable_hash_via_hash!(Fingerprint); impl Encodable for Fingerprint { + #[inline] fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.encode_fingerprint(self) + s.emit_raw_bytes(&self.to_le_bytes()[..])?; + Ok(()) } } impl Decodable for Fingerprint { + #[inline] fn decode(d: &mut D) -> Result { - d.decode_fingerprint() - } -} - -pub trait FingerprintEncoder: rustc_serialize::Encoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>; -} - -pub trait FingerprintDecoder: rustc_serialize::Decoder { - fn decode_fingerprint(&mut self) -> Result; -} - -impl FingerprintEncoder for E { - default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> { - panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::()); - } -} - -impl FingerprintEncoder for opaque::Encoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult { - let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) }; - self.emit_raw_bytes(&bytes); - Ok(()) - } -} - -impl FingerprintEncoder for opaque::FileEncoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> FileEncodeResult { - let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) }; - self.emit_raw_bytes(&bytes) - } -} - -impl FingerprintDecoder for D { - default fn decode_fingerprint(&mut self) -> Result { - panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::()); - } -} - -impl FingerprintDecoder for opaque::Decoder<'_> { - fn decode_fingerprint(&mut self) -> Result { - Fingerprint::decode_opaque(self) + let mut bytes = [0u8; 16]; + d.read_raw_bytes_into(&mut bytes[..])?; + Ok(Fingerprint::from_le_bytes(bytes)) } } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index fcb2bca7b4..adbb98fa75 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -13,7 +13,6 @@ #![feature(unboxed_closures)] #![feature(generator_trait)] #![feature(fn_traits)] -#![feature(int_bits_const)] #![feature(min_specialization)] #![feature(auto_traits)] #![feature(nll)] @@ -85,6 +84,7 @@ pub mod snapshot_map; pub mod stable_map; pub mod svh; pub use ena::snapshot_vec; +pub mod memmap; pub mod sorted_map; pub mod stable_set; #[macro_use] diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs new file mode 100644 index 0000000000..26b26415ee --- /dev/null +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -0,0 +1,47 @@ +use std::fs::File; +use std::io; +use std::ops::Deref; + +use crate::owning_ref::StableAddress; + +/// A trivial wrapper for [`memmap2::Mmap`] that implements [`StableAddress`]. +#[cfg(not(target_arch = "wasm32"))] +pub struct Mmap(memmap2::Mmap); + +#[cfg(target_arch = "wasm32")] +pub struct Mmap(Vec); + +#[cfg(not(target_arch = "wasm32"))] +impl Mmap { + #[inline] + pub unsafe fn map(file: File) -> io::Result { + memmap2::Mmap::map(&file).map(Mmap) + } +} + +#[cfg(target_arch = "wasm32")] +impl Mmap { + #[inline] + pub unsafe fn map(mut file: File) -> io::Result { + use std::io::Read; + + let mut data = Vec::new(); + file.read_to_end(&mut data)?; + Ok(Mmap(data)) + } +} + +impl Deref for Mmap { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + &*self.0 + } +} + +// SAFETY: On architectures other than WASM, mmap is used as backing storage. The address of this +// memory map is stable. On WASM, `Vec` is used as backing storage. The `Mmap` type doesn't +// export any function that can cause the `Vec` to be re-allocated. As such the address of the +// bytes inside this `Vec` is stable. +unsafe impl StableAddress for Mmap {} diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs index 06e8442d47..e249886e9b 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -18,11 +18,8 @@ use std::ops::Index; // for reasonably small arrays that stay // small in vast majority of cases. // -// '8' is choosen as a sane default, to be +// '8' is chosen as a sane default, to be // reevaluated later. -// -// Note: As of now ArrayVec design prevents -// us from making it user-customizable. const SSO_ARRAY_SIZE: usize = 8; /// Small-storage-optimized implementation of a map. @@ -70,7 +67,7 @@ const SSO_ARRAY_SIZE: usize = 8; #[derive(Clone)] pub enum SsoHashMap { - Array(ArrayVec<[(K, V); SSO_ARRAY_SIZE]>), + Array(ArrayVec<(K, V), SSO_ARRAY_SIZE>), Map(FxHashMap), } @@ -411,7 +408,7 @@ where impl IntoIterator for SsoHashMap { type IntoIter = EitherIter< - as IntoIterator>::IntoIter, + as IntoIterator>::IntoIter, as IntoIterator>::IntoIter, >; type Item = ::Item; @@ -441,7 +438,7 @@ fn adapt_array_mut_it(pair: &'a mut (K, V)) -> (&'a K, &'a mut V) { impl<'a, K, V> IntoIterator for &'a SsoHashMap { type IntoIter = EitherIter< std::iter::Map< - <&'a ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter, + <&'a ArrayVec<(K, V), 8> as IntoIterator>::IntoIter, fn(&'a (K, V)) -> (&'a K, &'a V), >, <&'a FxHashMap as IntoIterator>::IntoIter, @@ -459,7 +456,7 @@ impl<'a, K, V> IntoIterator for &'a SsoHashMap { impl<'a, K, V> IntoIterator for &'a mut SsoHashMap { type IntoIter = EitherIter< std::iter::Map< - <&'a mut ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter, + <&'a mut ArrayVec<(K, V), 8> as IntoIterator>::IntoIter, fn(&'a mut (K, V)) -> (&'a K, &'a mut V), >, <&'a mut FxHashMap as IntoIterator>::IntoIter, diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs index 02103de2e8..ce90fbacaa 100644 --- a/compiler/rustc_data_structures/src/svh.rs +++ b/compiler/rustc_data_structures/src/svh.rs @@ -19,7 +19,7 @@ pub struct Svh { impl Svh { /// Creates a new `Svh` given the hash. If you actually want to /// compute the SVH from some HIR, you want the `calculate_svh` - /// function found in `librustc_incremental`. + /// function found in `rustc_incremental`. pub fn new(hash: u64) -> Svh { Svh { hash } } diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs index 63f64beae5..d44ccd368b 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs @@ -42,18 +42,9 @@ where pub fn pointer_ref(&self) -> &P::Target { self.raw.pointer_ref() } - pub fn pointer_mut(&mut self) -> &mut P::Target - where - P: std::ops::DerefMut, - { - self.raw.pointer_mut() - } pub fn tag(&self) -> T { self.raw.tag() } - pub fn set_tag(&mut self, tag: T) { - self.raw.set_tag(tag); - } } impl std::ops::Deref for TaggedPtr diff --git a/compiler/rustc_data_structures/src/thin_vec.rs b/compiler/rustc_data_structures/src/thin_vec.rs index 4d673fd5cf..00e3047349 100644 --- a/compiler/rustc_data_structures/src/thin_vec.rs +++ b/compiler/rustc_data_structures/src/thin_vec.rs @@ -1,5 +1,7 @@ use crate::stable_hasher::{HashStable, StableHasher}; +use std::iter::FromIterator; + /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. @@ -10,6 +12,14 @@ impl ThinVec { pub fn new() -> Self { ThinVec(None) } + + pub fn iter(&self) -> std::slice::Iter<'_, T> { + self.into_iter() + } + + pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { + self.into_iter() + } } impl From> for ThinVec { @@ -46,6 +56,42 @@ impl ::std::ops::DerefMut for ThinVec { } } +impl FromIterator for ThinVec { + fn from_iter>(iter: I) -> Self { + // `Vec::from_iter()` should not allocate if the iterator is empty. + let vec: Vec<_> = iter.into_iter().collect(); + if vec.is_empty() { ThinVec(None) } else { ThinVec(Some(Box::new(vec))) } + } +} + +impl IntoIterator for ThinVec { + type Item = T; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + // This is still performant because `Vec::new()` does not allocate. + self.0.map_or_else(Vec::new, |ptr| *ptr).into_iter() + } +} + +impl<'a, T> IntoIterator for &'a ThinVec { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.as_ref().iter() + } +} + +impl<'a, T> IntoIterator for &'a mut ThinVec { + type Item = &'a mut T; + type IntoIter = std::slice::IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.as_mut().iter_mut() + } +} + impl Extend for ThinVec { fn extend>(&mut self, iter: I) { match *self { @@ -80,3 +126,6 @@ impl Default for ThinVec { Self(None) } } + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/thin_vec/tests.rs b/compiler/rustc_data_structures/src/thin_vec/tests.rs new file mode 100644 index 0000000000..5abfd93937 --- /dev/null +++ b/compiler/rustc_data_structures/src/thin_vec/tests.rs @@ -0,0 +1,42 @@ +use super::*; + +impl ThinVec { + fn into_vec(self) -> Vec { + self.into() + } +} + +#[test] +fn test_from_iterator() { + assert_eq!(std::iter::empty().collect::>().into_vec(), Vec::::new()); + assert_eq!(std::iter::once(42).collect::>().into_vec(), vec![42]); + assert_eq!(vec![1, 2].into_iter().collect::>().into_vec(), vec![1, 2]); + assert_eq!(vec![1, 2, 3].into_iter().collect::>().into_vec(), vec![1, 2, 3]); +} + +#[test] +fn test_into_iterator_owned() { + assert_eq!(ThinVec::new().into_iter().collect::>(), Vec::::new()); + assert_eq!(ThinVec::from(vec![1]).into_iter().collect::>(), vec![1]); + assert_eq!(ThinVec::from(vec![1, 2]).into_iter().collect::>(), vec![1, 2]); + assert_eq!(ThinVec::from(vec![1, 2, 3]).into_iter().collect::>(), vec![1, 2, 3]); +} + +#[test] +fn test_into_iterator_ref() { + assert_eq!(ThinVec::new().iter().collect::>(), Vec::<&String>::new()); + assert_eq!(ThinVec::from(vec![1]).iter().collect::>(), vec![&1]); + assert_eq!(ThinVec::from(vec![1, 2]).iter().collect::>(), vec![&1, &2]); + assert_eq!(ThinVec::from(vec![1, 2, 3]).iter().collect::>(), vec![&1, &2, &3]); +} + +#[test] +fn test_into_iterator_ref_mut() { + assert_eq!(ThinVec::new().iter_mut().collect::>(), Vec::<&mut String>::new()); + assert_eq!(ThinVec::from(vec![1]).iter_mut().collect::>(), vec![&mut 1]); + assert_eq!(ThinVec::from(vec![1, 2]).iter_mut().collect::>(), vec![&mut 1, &mut 2]); + assert_eq!( + ThinVec::from(vec![1, 2, 3]).iter_mut().collect::>(), + vec![&mut 1, &mut 2, &mut 3], + ); +} diff --git a/compiler/rustc_data_structures/src/work_queue.rs b/compiler/rustc_data_structures/src/work_queue.rs index cc562bc1e4..10317f1aff 100644 --- a/compiler/rustc_data_structures/src/work_queue.rs +++ b/compiler/rustc_data_structures/src/work_queue.rs @@ -41,10 +41,4 @@ impl WorkQueue { None } } - - /// Returns `true` if nothing is enqueued. - #[inline] - pub fn is_empty(&self) -> bool { - self.deque.is_empty() - } } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 25a78041c0..51699403a3 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -146,6 +146,7 @@ impl<'a, 'b> RunCompiler<'a, 'b> { pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self { Self { at_args, callbacks, file_loader: None, emitter: None, make_codegen_backend: None } } + /// Used by cg_clif. pub fn set_make_codegen_backend( &mut self, make_codegen_backend: Option< @@ -155,10 +156,12 @@ impl<'a, 'b> RunCompiler<'a, 'b> { self.make_codegen_backend = make_codegen_backend; self } + /// Used by RLS. pub fn set_emitter(&mut self, emitter: Option>) -> &mut Self { self.emitter = emitter; self } + /// Used by RLS. pub fn set_file_loader( &mut self, file_loader: Option>, @@ -792,7 +795,7 @@ pub fn version(binary: &str, matches: &getopts::Matches) { println!("host: {}", config::host_triple()); println!("release: {}", unw(util::release_str())); if cfg!(feature = "llvm") { - get_builtin_codegen_backend("llvm")().print_version(); + get_builtin_codegen_backend(&None, "llvm")().print_version(); } } } @@ -842,7 +845,8 @@ the command line flag directly. ); } -fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { +/// Write to stdout lint command options, together with a list of all available lints +pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { println!( " Available lint options: @@ -895,7 +899,12 @@ Available lint options: let print_lints = |lints: Vec<&Lint>| { for lint in lints { let name = lint.name_lower().replace("_", "-"); - println!(" {} {:7.7} {}", padded(&name), lint.default_level.as_str(), lint.desc); + println!( + " {} {:7.7} {}", + padded(&name), + lint.default_level(sess.edition()).as_str(), + lint.desc + ); } println!("\n"); }; @@ -1081,7 +1090,7 @@ pub fn handle_options(args: &[String]) -> Option { if cg_flags.iter().any(|x| *x == "passes=list") { if cfg!(feature = "llvm") { - get_builtin_codegen_backend("llvm")().print_passes(); + get_builtin_codegen_backend(&None, "llvm")().print_passes(); } return None; } diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 5512bd7445..e0c140b143 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -108,13 +108,6 @@ trait HirPrinterSupport<'hir>: pprust_hir::PpAnn { /// (Rust does not yet support upcasting from a trait object to /// an object for one of its super-traits.) fn pp_ann(&self) -> &dyn pprust_hir::PpAnn; - - /// Computes an user-readable representation of a path, if possible. - fn node_path(&self, id: hir::HirId) -> Option { - self.hir_map().and_then(|map| map.def_path_from_hir_id(id)).map(|path| { - path.data.into_iter().map(|elem| elem.data.to_string()).collect::>().join("::") - }) - } } struct NoAnn<'hir> { @@ -327,10 +320,6 @@ impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> { fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { self } - - fn node_path(&self, id: hir::HirId) -> Option { - Some(self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id())) - } } impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { @@ -471,21 +460,6 @@ pub fn print_after_hir_lowering<'tcx>( format!("{:#?}", krate) }), - ThirTree => { - let mut out = String::new(); - abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess); - debug!("pretty printing THIR tree"); - for did in tcx.body_owners() { - let hir = tcx.hir(); - let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(did))); - let arena = thir::Arena::default(); - let thir = - thir::build_thir(tcx, ty::WithOptConstParam::unknown(did), &arena, &body.value); - let _ = writeln!(out, "{:?}:\n{:#?}\n", did, thir); - } - out - } - _ => unreachable!(), }; @@ -501,18 +475,40 @@ fn print_with_analysis( ppm: PpMode, ofile: Option<&Path>, ) -> Result<(), ErrorReported> { - let mut out = Vec::new(); - tcx.analysis(LOCAL_CRATE)?; - match ppm { - Mir => write_mir_pretty(tcx, None, &mut out).unwrap(), - MirCFG => write_mir_graphviz(tcx, None, &mut out).unwrap(), + let out = match ppm { + Mir => { + let mut out = Vec::new(); + write_mir_pretty(tcx, None, &mut out).unwrap(); + String::from_utf8(out).unwrap() + } + + MirCFG => { + let mut out = Vec::new(); + write_mir_graphviz(tcx, None, &mut out).unwrap(); + String::from_utf8(out).unwrap() + } + + ThirTree => { + let mut out = String::new(); + abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess); + debug!("pretty printing THIR tree"); + for did in tcx.body_owners() { + let hir = tcx.hir(); + let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(did))); + let arena = thir::Arena::default(); + let thir = + thir::build_thir(tcx, ty::WithOptConstParam::unknown(did), &arena, &body.value); + let _ = writeln!(out, "{:?}:\n{:#?}\n", did, thir); + } + out + } + _ => unreachable!(), - } + }; - let out = std::str::from_utf8(&out).unwrap(); - write_or_print(out, ofile); + write_or_print(&out, ofile); Ok(()) } diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 4b52973432..41a1fa488d 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -416,7 +416,6 @@ 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"), -E0723: include_str!("./error_codes/E0723.md"), E0724: include_str!("./error_codes/E0724.md"), E0725: include_str!("./error_codes/E0725.md"), E0727: include_str!("./error_codes/E0727.md"), @@ -636,6 +635,7 @@ E0781: include_str!("./error_codes/E0781.md"), 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]` diff --git a/compiler/rustc_error_codes/src/error_codes/E0128.md b/compiler/rustc_error_codes/src/error_codes/E0128.md index 6f8dfe3a73..2ea8ae68ef 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0128.md +++ b/compiler/rustc_error_codes/src/error_codes/E0128.md @@ -7,7 +7,7 @@ struct Foo { field1: T, field2: U, } -// error: type parameters with a default cannot use forward declared +// error: generic parameters with a default cannot use forward declared // identifiers ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0136.md b/compiler/rustc_error_codes/src/error_codes/E0136.md index b91b52c074..15cf09a18c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0136.md +++ b/compiler/rustc_error_codes/src/error_codes/E0136.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + More than one `main` function was found. Erroneous code example: -```compile_fail,E0136 +```compile_fail fn main() { // ... } diff --git a/compiler/rustc_error_codes/src/error_codes/E0137.md b/compiler/rustc_error_codes/src/error_codes/E0137.md index 0a02913d23..d4e19170f3 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0137.md +++ b/compiler/rustc_error_codes/src/error_codes/E0137.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + More than one function was declared with the `#[main]` attribute. Erroneous code example: -```compile_fail,E0137 +```compile_fail #![feature(main)] #[main] @@ -16,7 +18,7 @@ This error indicates that the compiler found multiple functions with the `#[main]` attribute. This is an error because there must be a unique entry point into a Rust program. Example: -``` +```compile_fail #![feature(main)] #[main] diff --git a/compiler/rustc_error_codes/src/error_codes/E0379.md b/compiler/rustc_error_codes/src/error_codes/E0379.md index 930204847e..ab438e4144 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0379.md +++ b/compiler/rustc_error_codes/src/error_codes/E0379.md @@ -3,8 +3,6 @@ A trait method was declared const. Erroneous code example: ```compile_fail,E0379 -#![feature(const_fn)] - trait Foo { const fn bar() -> u32; // error! } diff --git a/compiler/rustc_error_codes/src/error_codes/E0404.md b/compiler/rustc_error_codes/src/error_codes/E0404.md index 1360cc99af..d6fa51e618 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0404.md +++ b/compiler/rustc_error_codes/src/error_codes/E0404.md @@ -8,14 +8,15 @@ struct Foo; struct Bar; impl Foo for Bar {} // error: `Foo` is not a trait +fn baz(t: T) {} // error: `Foo` is not a trait ``` Another erroneous code example: ```compile_fail,E0404 -struct Foo; +type Foo = Iterator; -fn bar(t: T) {} // error: `Foo` is not a trait +fn bar(t: T) {} // error: `Foo` is a type alias ``` Please verify that the trait's name was not misspelled or that the right @@ -30,14 +31,27 @@ struct Bar; impl Foo for Bar { // ok! // functions implementation } + +fn baz(t: T) {} // ok! ``` -or: +Alternatively, you could introduce a new trait with your desired restrictions +as a super trait: ``` -trait Foo { - // some functions -} +# trait Foo {} +# struct Bar; +# impl Foo for Bar {} +trait Qux: Foo {} // Anything that implements Qux also needs to implement Foo +fn baz(t: T) {} // also ok! +``` + +Finally, if you are on nightly and want to use a trait alias +instead of a type alias, you should use `#![feature(trait_alias)]`: + +``` +#![feature(trait_alias)] +trait Foo = Iterator; fn bar(t: T) {} // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0554.md b/compiler/rustc_error_codes/src/error_codes/E0554.md index e55fa4c6ed..3178bf2191 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0554.md +++ b/compiler/rustc_error_codes/src/error_codes/E0554.md @@ -4,8 +4,8 @@ beta compilers will not comply. Erroneous code example: ```ignore (depends on release channel) -#![feature(non_ascii_idents)] // error: `#![feature]` may not be used on the - // stable release channel +#![feature(lang_items)] // error: `#![feature]` may not be used on the + // stable release channel ``` If you need the feature, make sure to use a nightly release of the compiler diff --git a/compiler/rustc_error_codes/src/error_codes/E0723.md b/compiler/rustc_error_codes/src/error_codes/E0723.md deleted file mode 100644 index bc22442191..0000000000 --- a/compiler/rustc_error_codes/src/error_codes/E0723.md +++ /dev/null @@ -1,20 +0,0 @@ -An unstable feature in `const` contexts was used. - -Erroneous code example: - -```compile_fail,E0723 -const fn foo(_: T) { // error! - // ... -} -``` - -To enable this feature on a nightly version of rustc, add the `const_fn` -feature flag: - -``` -#![feature(const_fn)] - -const fn foo(_: T) { // ok! - // ... -} -``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0754.md b/compiler/rustc_error_codes/src/error_codes/E0754.md index 9f4b19cfda..acddb69aab 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0754.md +++ b/compiler/rustc_error_codes/src/error_codes/E0754.md @@ -3,7 +3,6 @@ A non-ASCII identifier was used in an invalid context. Erroneous code examples: ```compile_fail,E0754 -# #![feature(non_ascii_idents)] mod řųśť; // error! @@ -17,8 +16,6 @@ Non-ASCII can be used as module names if it is inlined or if a `#[path]` attribute is specified. For example: ``` -# #![feature(non_ascii_idents)] - mod řųśť { // ok! const IS_GREAT: bool = true; } diff --git a/compiler/rustc_error_codes/src/error_codes/E0764.md b/compiler/rustc_error_codes/src/error_codes/E0764.md index 0a2e2290e7..152627cf65 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0764.md +++ b/compiler/rustc_error_codes/src/error_codes/E0764.md @@ -3,7 +3,6 @@ A mutable reference was used in a constant. Erroneous code example: ```compile_fail,E0764 -#![feature(const_fn)] #![feature(const_mut_refs)] fn main() { @@ -27,7 +26,6 @@ Remember: you cannot use a function call inside a constant or static. However, you can totally use it in constant functions: ``` -#![feature(const_fn)] #![feature(const_mut_refs)] const fn foo(x: usize) -> usize { diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 14ddb3e207..f2432f6165 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -1,5 +1,4 @@ -#![cfg_attr(bootstrap, deny(invalid_codeblock_attributes))] -#![cfg_attr(not(bootstrap), deny(rustdoc::invalid_codeblock_attributes))] +#![deny(rustdoc::invalid_codeblock_attributes)] //! This library is used to gather all error codes into one place, //! the goal being to make their maintenance easier. diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index ce5b130dd9..b2f6a0c101 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -69,10 +69,6 @@ impl DiagnosticStyledString { pub fn highlighted>(t: S) -> DiagnosticStyledString { DiagnosticStyledString(vec![StringPart::Highlighted(t.into())]) } - - pub fn content(&self) -> String { - self.0.iter().map(|x| x.content()).collect::() - } } #[derive(Debug, PartialEq, Eq)] @@ -81,14 +77,6 @@ pub enum StringPart { Highlighted(String), } -impl StringPart { - pub fn content(&self) -> &str { - match self { - &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s, - } - } -} - impl Diagnostic { pub fn new(level: Level, message: &str) -> Self { Diagnostic::new_with_code(level, None, message) @@ -156,7 +144,7 @@ impl Diagnostic { self } - pub fn note_expected_found( + crate fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, expected: DiagnosticStyledString, @@ -166,7 +154,7 @@ impl Diagnostic { self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") } - pub fn note_unsuccessful_coercion( + crate fn note_unsuccessful_coercion( &mut self, expected: DiagnosticStyledString, found: DiagnosticStyledString, @@ -256,33 +244,33 @@ impl Diagnostic { /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. - pub fn span_note>(&mut self, sp: S, msg: &str) -> &mut Self { + crate fn span_note>(&mut self, sp: S, msg: &str) -> &mut Self { self.sub(Level::Note, msg, sp.into(), None); self } /// Add a warning attached to this diagnostic. - pub fn warn(&mut self, msg: &str) -> &mut Self { + crate fn warn(&mut self, msg: &str) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new(), None); self } /// Prints the span with a warning above it. /// This is like [`Diagnostic::warn()`], but it gets its own span. - pub fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self { + crate fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self { self.sub(Level::Warning, msg, sp.into(), None); self } /// Add a help message attached to this diagnostic. - pub fn help(&mut self, msg: &str) -> &mut Self { + crate fn help(&mut self, msg: &str) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new(), None); self } /// Prints the span with some help above it. /// This is like [`Diagnostic::help()`], but it gets its own span. - pub fn span_help>(&mut self, sp: S, msg: &str) -> &mut Self { + crate fn span_help>(&mut self, sp: S, msg: &str) -> &mut Self { self.sub(Level::Help, msg, sp.into(), None); self } @@ -311,36 +299,6 @@ impl Diagnostic { self } - /// Show multiple suggestions that have multiple parts. - /// See also [`Diagnostic::multipart_suggestion()`]. - pub fn multipart_suggestions( - &mut self, - msg: &str, - suggestions: Vec>, - applicability: Applicability, - ) -> &mut Self { - assert!(!suggestions.is_empty()); - for s in &suggestions { - assert!(!s.is_empty()); - } - self.suggestions.push(CodeSuggestion { - substitutions: suggestions - .into_iter() - .map(|suggestion| Substitution { - parts: suggestion - .into_iter() - .map(|(span, snippet)| SubstitutionPart { snippet, span }) - .collect(), - }) - .collect(), - msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, - applicability, - tool_metadata: Default::default(), - }); - self - } - /// Prints out a message with for a multipart suggestion without showing the suggested code. /// /// This is intended to be used for suggestions that are obvious in what the changes need to @@ -567,7 +525,7 @@ impl Diagnostic { self.code.clone() } - pub fn set_primary_message>(&mut self, msg: M) -> &mut Self { + crate fn set_primary_message>(&mut self, msg: M) -> &mut Self { self.message[0] = (msg.into(), Style::NoStyle); self } @@ -582,6 +540,8 @@ impl Diagnostic { /// Convenience function for internal use, clients should use one of the /// public methods above. + /// + /// Used by `proc_macro_server` for implementing `server::Diagnostic`. pub fn sub( &mut self, level: Level, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 79507e6152..282877d5dd 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -157,19 +157,6 @@ impl<'a> DiagnosticBuilder<'a> { buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); } - /// Convenience function for internal use, clients should use one of the - /// span_* methods instead. - pub fn sub>( - &mut self, - level: Level, - message: &str, - span: Option, - ) -> &mut Self { - let span = span.map(|s| s.into()).unwrap_or_else(MultiSpan::new); - self.0.diagnostic.sub(level, message, span, None); - self - } - /// Delay emission of this diagnostic as a bug. /// /// This can be useful in contexts where an error indicates a bug but @@ -270,20 +257,6 @@ impl<'a> DiagnosticBuilder<'a> { self } - /// See [`Diagnostic::multipart_suggestions()`]. - pub fn multipart_suggestions( - &mut self, - msg: &str, - suggestions: Vec>, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability); - self - } - /// See [`Diagnostic::tool_only_multipart_suggestion()`]. pub fn tool_only_multipart_suggestion( &mut self, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 9b6f67166b..a58caf2667 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -195,6 +195,9 @@ pub trait Emitter { fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {} + /// Emit list of unused externs + fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {} + /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { true @@ -434,9 +437,15 @@ pub trait Emitter { span: &mut MultiSpan, children: &mut Vec, ) { + let source_map = if let Some(ref sm) = source_map { + sm + } else { + return; + }; debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); - for span in iter::once(&mut *span).chain(children.iter_mut().map(|child| &mut child.span)) { - self.fix_multispan_in_extern_macros(source_map, span); + self.fix_multispan_in_extern_macros(source_map, span); + for child in children.iter_mut() { + self.fix_multispan_in_extern_macros(source_map, &mut child.span); } debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children); } @@ -444,16 +453,7 @@ pub trait Emitter { // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. // Since these locations are often difficult to read, // we move these spans from the external macros to their corresponding use site. - fn fix_multispan_in_extern_macros( - &self, - source_map: &Option>, - span: &mut MultiSpan, - ) { - let sm = match source_map { - Some(ref sm) => sm, - None => return, - }; - + fn fix_multispan_in_extern_macros(&self, source_map: &Lrc, span: &mut MultiSpan) { // First, find all the spans in external macros and point instead at their use site. let replacements: Vec<(Span, Span)> = span .primary_spans() @@ -461,7 +461,7 @@ pub trait Emitter { .copied() .chain(span.span_labels().iter().map(|sp_label| sp_label.span)) .filter_map(|sp| { - if !sp.is_dummy() && sm.is_imported(sp) { + if !sp.is_dummy() && source_map.is_imported(sp) { let maybe_callsite = sp.source_callsite(); if sp != maybe_callsite { return Some((sp, maybe_callsite)); @@ -1232,7 +1232,6 @@ impl EmitterWriter { is_secondary: bool, ) -> io::Result<()> { let mut buffer = StyledBuffer::new(); - let header_style = if is_secondary { Style::HeaderMsg } else { Style::MainHeaderMsg }; if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary && !self.short_message { @@ -1257,11 +1256,12 @@ impl EmitterWriter { buffer.append(0, &code, Style::Level(*level)); buffer.append(0, "]", Style::Level(*level)); } + let header_style = if is_secondary { Style::HeaderMsg } else { Style::MainHeaderMsg }; if *level != Level::FailureNote { buffer.append(0, ": ", header_style); } for &(ref text, _) in msg.iter() { - buffer.append(0, text, header_style); + buffer.append(0, &replace_tabs(text), header_style); } } @@ -1470,9 +1470,7 @@ impl EmitterWriter { let mut to_add = FxHashMap::default(); for (depth, style) in depths { - if multilines.get(&depth).is_some() { - multilines.remove(&depth); - } else { + if multilines.remove(&depth).is_none() { to_add.insert(depth, style); } } @@ -1726,14 +1724,13 @@ impl EmitterWriter { if !self.short_message { draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1); } - match emit_to_destination( + if let Err(e) = emit_to_destination( &buffer.render(), level, &mut self.dst, self.short_message, ) { - Ok(()) => (), - Err(e) => panic!("failed to emit error: {}", e), + panic!("failed to emit error: {}", e) } } if !self.short_message { @@ -2220,9 +2217,7 @@ pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { }; let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; // All the chars that differ in capitalization are confusable (above): - let confusable = found - .chars() - .zip(suggested.chars()) + let confusable = iter::zip(found.chars(), suggested.chars()) .filter(|(f, s)| f != s) .all(|(f, s)| (ascii_confusables.contains(&f) || ascii_confusables.contains(&s))); confusable && found.to_lowercase() == suggested.to_lowercase() diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index c27b39a9d6..4027700646 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -159,6 +159,19 @@ impl Emitter for JsonEmitter { } } + fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) { + let data = UnusedExterns { lint_level, unused_extern_names: unused_externs }; + let result = if self.pretty { + writeln!(&mut self.dst, "{}", as_pretty_json(&data)) + } else { + writeln!(&mut self.dst, "{}", as_json(&data)) + } + .and_then(|_| self.dst.flush()); + if let Err(e) = result { + panic!("failed to print unused externs: {:?}", e); + } + } + fn source_map(&self) -> Option<&Lrc> { Some(&self.sm) } @@ -322,6 +335,18 @@ struct FutureIncompatReport { future_incompat_report: Vec, } +// NOTE: Keep this in sync with the equivalent structs in rustdoc's +// doctest component (as well as cargo). +// We could unify this struct the one in rustdoc but they have different +// ownership semantics, so doing so would create wasteful allocations. +#[derive(Encodable)] +struct UnusedExterns<'a, 'b, 'c> { + /// The severity level of the unused dependencies lint + lint_level: &'a str, + /// List of unused externs by their names. + unused_extern_names: &'b [&'c str], +} + impl Diagnostic { fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { let sugg = diag.suggestions.iter().map(|sugg| Diagnostic { @@ -493,7 +518,7 @@ impl DiagnosticSpanLine { h_end: usize, ) -> DiagnosticSpanLine { DiagnosticSpanLine { - text: sf.get_line(index).map_or(String::new(), |l| l.into_owned()), + text: sf.get_line(index).map_or_else(String::new, |l| l.into_owned()), highlight_start: h_start, highlight_end: h_end, } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fa855f544e..f1a31f0d4f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,6 +6,7 @@ #![feature(crate_visibility_modifier)] #![feature(backtrace)] #![feature(extended_key_value_attributes)] +#![feature(iter_zip)] #![feature(nll)] #[macro_use] @@ -320,7 +321,7 @@ struct HandlerInner { /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid /// emitting the same diagnostic with extended help (`--teach`) twice, which - /// would be uneccessary repetition. + /// would be unnecessary repetition. taught_diagnostics: FxHashSet, /// Used to suggest rustc --explain @@ -690,10 +691,6 @@ impl Handler { db } - pub fn failure(&self, msg: &str) { - self.inner.borrow_mut().failure(msg); - } - pub fn fatal(&self, msg: &str) -> FatalError { self.inner.borrow_mut().fatal(msg) } @@ -768,6 +765,10 @@ impl Handler { self.inner.borrow_mut().emitter.emit_future_breakage_report(diags) } + pub fn emit_unused_externs(&self, lint_level: &str, unused_externs: &[&str]) { + self.inner.borrow_mut().emit_unused_externs(lint_level, unused_externs) + } + pub fn delay_as_bug(&self, diagnostic: Diagnostic) { self.inner.borrow_mut().delay_as_bug(diagnostic) } @@ -842,6 +843,10 @@ impl HandlerInner { self.emitter.emit_artifact_notification(path, artifact_type); } + fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) { + self.emitter.emit_unused_externs(lint_level, unused_externs); + } + fn treat_err_as_bug(&self) -> bool { self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c.get()) } diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs index b1d770d5bd..da764d993b 100644 --- a/compiler/rustc_errors/src/registry.rs +++ b/compiler/rustc_errors/src/registry.rs @@ -13,10 +13,6 @@ impl Registry { Registry { long_descriptions: long_descriptions.iter().copied().collect() } } - /// This will panic if an invalid error code is passed in - pub fn find_description(&self, code: &str) -> Option<&'static str> { - self.long_descriptions[code] - } /// Returns `InvalidErrorCode` if the code requested does not exist in the /// registry. Otherwise, returns an `Option` where `None` means the error /// code is valid but has no extended information. diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index acb88e57db..3fe02bd0ce 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -121,16 +121,6 @@ impl Annotation { matches!(self.annotation_type, AnnotationType::MultilineLine(_)) } - pub fn is_multiline(&self) -> bool { - matches!( - self.annotation_type, - AnnotationType::Multiline(_) - | AnnotationType::MultilineStart(_) - | AnnotationType::MultilineLine(_) - | AnnotationType::MultilineEnd(_) - ) - } - pub fn len(&self) -> usize { // Account for usize underflows if self.end_col > self.start_col { diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index ef71ee36ea..e262d95bb7 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -4,35 +4,49 @@ use crate::snippet::{Style, StyledString}; #[derive(Debug)] pub struct StyledBuffer { - text: Vec>, - styles: Vec>, + lines: Vec>, +} + +#[derive(Debug, Clone)] +struct StyledChar { + chr: char, + style: Style, +} + +impl StyledChar { + const SPACE: Self = StyledChar::new(' ', Style::NoStyle); + + const fn new(chr: char, style: Style) -> Self { + StyledChar { chr, style } + } } impl StyledBuffer { pub fn new() -> StyledBuffer { - StyledBuffer { text: vec![], styles: vec![] } + StyledBuffer { lines: vec![] } } + /// Returns content of `StyledBuffer` splitted by lines and line styles pub fn render(&self) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. - debug_assert!(self.text.iter().all(|r| !r.contains(&'\t'))); + debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; - for (row, row_style) in self.text.iter().zip(&self.styles) { + for styled_line in &self.lines { let mut current_style = Style::NoStyle; let mut current_text = String::new(); - for (&c, &s) in row.iter().zip(row_style) { - if s != current_style { + for sc in styled_line { + if sc.style != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); } - current_style = s; + current_style = sc.style; current_text = String::new(); } - current_text.push(c); + current_text.push(sc.chr); } if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); @@ -48,29 +62,25 @@ impl StyledBuffer { } fn ensure_lines(&mut self, line: usize) { - while line >= self.text.len() { - self.text.push(vec![]); - self.styles.push(vec![]); + if line >= self.lines.len() { + self.lines.resize(line + 1, Vec::new()); } } + /// Sets `chr` with `style` for given `line`, `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); - if col < self.text[line].len() { - self.text[line][col] = chr; - self.styles[line][col] = style; - } else { - let mut i = self.text[line].len(); - while i < col { - self.text[line].push(' '); - self.styles[line].push(Style::NoStyle); - i += 1; - } - self.text[line].push(chr); - self.styles[line].push(style); + if col >= self.lines[line].len() { + self.lines[line].resize(col + 1, StyledChar::SPACE); } + self.lines[line][col] = StyledChar::new(chr, style); } + /// Sets `string` with `style` for given `line`, starting from `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { let mut n = col; for c in string.chars() { @@ -79,32 +89,40 @@ impl StyledBuffer { } } + /// For given `line` inserts `string` with `style` before old content of that line, + /// adding lines if needed pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.chars().count(); - // Push the old content over to make room for new content - for _ in 0..string_len { - self.styles[line].insert(0, Style::NoStyle); - self.text[line].insert(0, ' '); + if !self.lines[line].is_empty() { + // Push the old content over to make room for new content + for _ in 0..string_len { + self.lines[line].insert(0, StyledChar::SPACE); + } } self.puts(line, 0, string, style); } + /// For given `line` inserts `string` with `style` after old content of that line, + /// adding lines if needed pub fn append(&mut self, line: usize, string: &str, style: Style) { - if line >= self.text.len() { + if line >= self.lines.len() { self.puts(line, 0, string, style); } else { - let col = self.text[line].len(); + let col = self.lines[line].len(); self.puts(line, col, string, style); } } pub fn num_lines(&self) -> usize { - self.text.len() + self.lines.len() } + /// Set `style` for `line`, `col_start..col_end` range if: + /// 1. That line and column range exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style_range( &mut self, line: usize, @@ -118,10 +136,13 @@ impl StyledBuffer { } } + /// Set `style` for `line`, `col` if: + /// 1. That line and column exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { - if let Some(ref mut line) = self.styles.get_mut(line) { - if let Some(s) = line.get_mut(col) { - if *s == Style::NoStyle || *s == Style::Quotation || overwrite { + if let Some(ref mut line) = self.lines.get_mut(line) { + if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { + if overwrite || *s == Style::NoStyle || *s == Style::Quotation { *s = style; } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 594b9a82ad..5950584281 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -3,7 +3,7 @@ use crate::module::DirOwnership; use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; -use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, LazyTokenStream, TokenStream}; +use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream}; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, Stability}; @@ -46,26 +46,26 @@ pub enum Annotatable { Variant(ast::Variant), } -impl AstLike for Annotatable { - fn attrs(&self) -> &[Attribute] { +impl Annotatable { + pub fn span(&self) -> Span { match *self { - Annotatable::Item(ref item) => &item.attrs, - Annotatable::TraitItem(ref trait_item) => &trait_item.attrs, - Annotatable::ImplItem(ref impl_item) => &impl_item.attrs, - Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs, - Annotatable::Stmt(ref stmt) => stmt.attrs(), - Annotatable::Expr(ref expr) => &expr.attrs, - Annotatable::Arm(ref arm) => &arm.attrs, - Annotatable::ExprField(ref field) => &field.attrs, - Annotatable::PatField(ref fp) => &fp.attrs, - Annotatable::GenericParam(ref gp) => &gp.attrs, - Annotatable::Param(ref p) => &p.attrs, - Annotatable::FieldDef(ref sf) => &sf.attrs, - Annotatable::Variant(ref v) => &v.attrs(), + Annotatable::Item(ref item) => item.span, + Annotatable::TraitItem(ref trait_item) => trait_item.span, + Annotatable::ImplItem(ref impl_item) => impl_item.span, + Annotatable::ForeignItem(ref foreign_item) => foreign_item.span, + Annotatable::Stmt(ref stmt) => stmt.span, + Annotatable::Expr(ref expr) => expr.span, + Annotatable::Arm(ref arm) => arm.span, + Annotatable::ExprField(ref field) => field.span, + Annotatable::PatField(ref fp) => fp.pat.span, + Annotatable::GenericParam(ref gp) => gp.ident.span, + Annotatable::Param(ref p) => p.span, + Annotatable::FieldDef(ref sf) => sf.span, + Annotatable::Variant(ref v) => v.span, } } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { match self { Annotatable::Item(item) => item.visit_attrs(f), Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f), @@ -83,44 +83,6 @@ impl AstLike for Annotatable { } } - fn tokens_mut(&mut self) -> Option<&mut Option> { - match self { - Annotatable::Item(item) => item.tokens_mut(), - Annotatable::TraitItem(trait_item) => trait_item.tokens_mut(), - Annotatable::ImplItem(impl_item) => impl_item.tokens_mut(), - Annotatable::ForeignItem(foreign_item) => foreign_item.tokens_mut(), - Annotatable::Stmt(stmt) => stmt.tokens_mut(), - Annotatable::Expr(expr) => expr.tokens_mut(), - Annotatable::Arm(arm) => arm.tokens_mut(), - Annotatable::ExprField(field) => field.tokens_mut(), - Annotatable::PatField(fp) => fp.tokens_mut(), - Annotatable::GenericParam(gp) => gp.tokens_mut(), - Annotatable::Param(p) => p.tokens_mut(), - Annotatable::FieldDef(sf) => sf.tokens_mut(), - Annotatable::Variant(v) => v.tokens_mut(), - } - } -} - -impl Annotatable { - pub fn span(&self) -> Span { - match *self { - Annotatable::Item(ref item) => item.span, - Annotatable::TraitItem(ref trait_item) => trait_item.span, - Annotatable::ImplItem(ref impl_item) => impl_item.span, - Annotatable::ForeignItem(ref foreign_item) => foreign_item.span, - Annotatable::Stmt(ref stmt) => stmt.span, - Annotatable::Expr(ref expr) => expr.span, - Annotatable::Arm(ref arm) => arm.span, - Annotatable::ExprField(ref field) => field.span, - Annotatable::PatField(ref fp) => fp.pat.span, - Annotatable::GenericParam(ref gp) => gp.ident.span, - Annotatable::Param(ref p) => p.span, - Annotatable::FieldDef(ref sf) => sf.span, - Annotatable::Variant(ref v) => v.span, - } - } - pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { match self { Annotatable::Item(item) => visitor.visit_item(item), @@ -139,7 +101,7 @@ impl Annotatable { } } - crate fn into_nonterminal(self) -> Nonterminal { + pub fn into_nonterminal(self) -> Nonterminal { match self { Annotatable::Item(item) => token::NtItem(item), Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { @@ -161,10 +123,7 @@ impl Annotatable { } crate fn into_tokens(self, sess: &ParseSess) -> TokenStream { - // Tokens of an attribute target may be invalidated by some outer `#[derive]` performing - // "full configuration" (attributes following derives on the same item should be the most - // common case), that's why synthesizing tokens is allowed. - nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::Yes) + nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No) } pub fn expect_item(self) -> P { @@ -868,6 +827,8 @@ impl SyntaxExtension { /// Error type that denotes indeterminacy. pub struct Indeterminate; +pub type DeriveResolutions = Vec<(ast::Path, Option>)>; + pub trait ResolverExpand { fn next_node_id(&mut self) -> NodeId; @@ -904,15 +865,12 @@ pub trait ResolverExpand { fn resolve_derives( &mut self, expn_id: ExpnId, - derives: Vec, 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, ast::Path)>>; + fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option; /// Path resolution logic for `#[cfg_accessible(path)]`. fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result; } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 3664ff3ae8..cb8b939828 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -253,17 +253,6 @@ impl<'a> ExtCtxt<'a> { let pathexpr = self.expr_path(self.path_global(sp, fn_path)); self.expr_call(sp, pathexpr, args) } - pub fn expr_method_call( - &self, - span: Span, - expr: P, - ident: Ident, - mut args: Vec>, - ) -> P { - args.insert(0, expr); - let segment = ast::PathSegment::from_ident(ident.with_span_pos(span)); - self.expr(span, ast::ExprKind::MethodCall(segment, args, span)) - } pub fn expr_block(&self, b: P) -> P { self.expr(b.span, ast::ExprKind::Block(b, None)) } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index a23731cf30..03c83f9c07 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -2,8 +2,10 @@ use rustc_ast::ptr::P; use rustc_ast::token::{DelimToken, Token, TokenKind}; -use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, Spacing, TokenStream, TokenTree}; -use rustc_ast::{self as ast, AstLike, AttrItem, Attribute, MetaItem}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; +use rustc_ast::tokenstream::{DelimSpan, Spacing}; +use rustc_ast::tokenstream::{LazyTokenStream, TokenTree}; +use rustc_ast::{self as ast, AstLike, AttrItem, AttrStyle, Attribute, MetaItem}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::map_in_place::MapInPlace; @@ -23,7 +25,10 @@ use rustc_span::{Span, DUMMY_SP}; pub struct StripUnconfigured<'a> { pub sess: &'a Session, pub features: Option<&'a Features>, - pub modified: bool, + /// If `true`, perform cfg-stripping on attached tokens. + /// This is only used for the input to derive macros, + /// which needs eager expansion of `cfg` and `cfg_attr` + pub config_tokens: bool, } fn get_features( @@ -194,7 +199,7 @@ fn get_features( // `cfg_attr`-process the crate's attributes and compute the crate's features. pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) { - let mut strip_unconfigured = StripUnconfigured { sess, features: None, modified: false }; + let mut strip_unconfigured = StripUnconfigured { sess, features: None, config_tokens: false }; let unconfigured_attrs = krate.attrs.clone(); let diag = &sess.parse_sess.span_diagnostic; @@ -241,24 +246,83 @@ impl<'a> StripUnconfigured<'a> { pub fn configure(&mut self, mut node: T) -> Option { self.process_cfg_attrs(&mut node); if self.in_cfg(node.attrs()) { + self.try_configure_tokens(&mut node); Some(node) } else { - self.modified = true; None } } + fn try_configure_tokens(&mut self, node: &mut T) { + if self.config_tokens { + if let Some(Some(tokens)) = node.tokens_mut() { + let attr_annotated_tokens = tokens.create_token_stream(); + *tokens = LazyTokenStream::new(self.configure_tokens(&attr_annotated_tokens)); + } + } + } + fn configure_krate_attrs( &mut self, mut attrs: Vec, ) -> Option> { attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); - if self.in_cfg(&attrs) { - Some(attrs) - } else { - self.modified = true; - None + if self.in_cfg(&attrs) { Some(attrs) } else { None } + } + + /// Performs cfg-expansion on `stream`, producing a new `AttrAnnotatedTokenStream`. + /// This is only used during the invocation of `derive` proc-macros, + /// which require that we cfg-expand their entire input. + /// Normal cfg-expansion operates on parsed AST nodes via the `configure` method + fn configure_tokens(&mut self, stream: &AttrAnnotatedTokenStream) -> AttrAnnotatedTokenStream { + fn can_skip(stream: &AttrAnnotatedTokenStream) -> bool { + stream.0.iter().all(|(tree, _spacing)| match tree { + AttrAnnotatedTokenTree::Attributes(_) => false, + AttrAnnotatedTokenTree::Token(_) => true, + AttrAnnotatedTokenTree::Delimited(_, _, inner) => can_skip(inner), + }) + } + + if can_skip(stream) { + return stream.clone(); } + + let trees: Vec<_> = stream + .0 + .iter() + .flat_map(|(tree, spacing)| match tree.clone() { + AttrAnnotatedTokenTree::Attributes(mut data) => { + let mut attrs: Vec<_> = std::mem::take(&mut data.attrs).into(); + attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); + data.attrs = attrs.into(); + + if self.in_cfg(&data.attrs) { + data.tokens = LazyTokenStream::new( + self.configure_tokens(&data.tokens.create_token_stream()), + ); + Some((AttrAnnotatedTokenTree::Attributes(data), *spacing)).into_iter() + } else { + None.into_iter() + } + } + AttrAnnotatedTokenTree::Delimited(sp, delim, mut inner) => { + inner = self.configure_tokens(&inner); + Some((AttrAnnotatedTokenTree::Delimited(sp, delim, inner), *spacing)) + .into_iter() + } + AttrAnnotatedTokenTree::Token(token) => { + if let TokenKind::Interpolated(nt) = token.kind { + panic!( + "Nonterminal should have been flattened at {:?}: {:?}", + token.span, nt + ); + } else { + Some((AttrAnnotatedTokenTree::Token(token), *spacing)).into_iter() + } + } + }) + .collect(); + AttrAnnotatedTokenStream::new(trees) } /// Parse and expand all `cfg_attr` attributes into a list of attributes @@ -285,9 +349,6 @@ impl<'a> StripUnconfigured<'a> { return vec![attr]; } - // A `#[cfg_attr]` either gets removed, or replaced with a new attribute - self.modified = true; - let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) { None => return vec![], Some(r) => r, @@ -311,7 +372,7 @@ impl<'a> StripUnconfigured<'a> { expanded_attrs .into_iter() .flat_map(|(item, span)| { - let orig_tokens = attr.tokens(); + let orig_tokens = attr.tokens().to_tokenstream(); // We are taking an attribute of the form `#[cfg_attr(pred, attr)]` // and producing an attribute of the form `#[attr]`. We @@ -321,25 +382,34 @@ impl<'a> StripUnconfigured<'a> { // Use the `#` in `#[cfg_attr(pred, attr)]` as the `#` token // for `attr` when we expand it to `#[attr]` - let pound_token = orig_tokens.trees().next().unwrap(); - if !matches!(pound_token, TokenTree::Token(Token { kind: TokenKind::Pound, .. })) { - panic!("Bad tokens for attribute {:?}", attr); + let mut orig_trees = orig_tokens.trees(); + let pound_token = match orig_trees.next().unwrap() { + TokenTree::Token(token @ Token { kind: TokenKind::Pound, .. }) => token, + _ => panic!("Bad tokens for attribute {:?}", attr), + }; + let pound_span = pound_token.span; + + let mut trees = vec![(AttrAnnotatedTokenTree::Token(pound_token), Spacing::Alone)]; + if attr.style == AttrStyle::Inner { + // For inner attributes, we do the same thing for the `!` in `#![some_attr]` + let bang_token = match orig_trees.next().unwrap() { + TokenTree::Token(token @ Token { kind: TokenKind::Not, .. }) => token, + _ => panic!("Bad tokens for attribute {:?}", attr), + }; + trees.push((AttrAnnotatedTokenTree::Token(bang_token), Spacing::Alone)); } // We don't really have a good span to use for the syntheized `[]` // in `#[attr]`, so just use the span of the `#` token. - let bracket_group = TokenTree::Delimited( - DelimSpan::from_single(pound_token.span()), + let bracket_group = AttrAnnotatedTokenTree::Delimited( + DelimSpan::from_single(pound_span), DelimToken::Bracket, item.tokens .as_ref() .unwrap_or_else(|| panic!("Missing tokens for {:?}", item)) .create_token_stream(), ); - let tokens = Some(LazyTokenStream::new(TokenStream::new(vec![ - (pound_token, Spacing::Alone), - (bracket_group, Spacing::Alone), - ]))); - + trees.push((bracket_group, Spacing::Alone)); + let tokens = Some(LazyTokenStream::new(AttrAnnotatedTokenStream::new(trees))); self.process_cfg_attr(attr::mk_attr_from_item(item, tokens, attr.style, span)) }) .collect() @@ -457,7 +527,8 @@ impl<'a> StripUnconfigured<'a> { self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg); } - self.process_cfg_attrs(expr) + self.process_cfg_attrs(expr); + self.try_configure_tokens(&mut *expr); } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 0992f59843..3347c93948 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -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, AttrItem, AttrStyle, Block, Inline, ItemKind, LitKind, MacArgs}; +use rustc_ast::{AstLike, AttrItem, Block, Inline, ItemKind, LitKind, MacArgs}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; @@ -20,9 +20,9 @@ use rustc_attr::{self as attr, is_builtin_attr}; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; -use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, GateOr, Parser, RecoverComma}; +use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser, RecoverComma}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; @@ -206,30 +206,36 @@ ast_fragments! { } } +pub enum SupportsMacroExpansion { + No, + Yes { supports_inner_attrs: bool }, +} + impl AstFragmentKind { crate fn dummy(self, span: Span) -> AstFragment { self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment") } - /// Fragment supports macro expansion and not just inert attributes, `cfg` and `cfg_attr`. - pub fn supports_macro_expansion(self) -> bool { + pub fn supports_macro_expansion(self) -> SupportsMacroExpansion { match self { AstFragmentKind::OptExpr | AstFragmentKind::Expr - | AstFragmentKind::Pat - | AstFragmentKind::Ty | AstFragmentKind::Stmts - | AstFragmentKind::Items + | AstFragmentKind::Ty + | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false }, + AstFragmentKind::Items | AstFragmentKind::TraitItems | AstFragmentKind::ImplItems - | AstFragmentKind::ForeignItems => true, + | AstFragmentKind::ForeignItems => { + SupportsMacroExpansion::Yes { supports_inner_attrs: true } + } AstFragmentKind::Arms | AstFragmentKind::Fields | AstFragmentKind::FieldPats | AstFragmentKind::GenericParams | AstFragmentKind::Params | AstFragmentKind::StructFields - | AstFragmentKind::Variants => false, + | AstFragmentKind::Variants => SupportsMacroExpansion::No, } } @@ -408,6 +414,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.article(), kind.descr() ), ); + // FIXME: this workaround issue #84569 + FatalError.raise(); } }; self.cx.trace_macros_diag(); @@ -485,6 +493,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let fragment_kind = invoc.fragment_kind; let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) { ExpandResult::Ready(fragment) => { + let mut derive_invocations = Vec::new(); let derive_placeholders = self .cx .resolver @@ -506,14 +515,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; - invocations.reserve(derives.len()); + derive_invocations.reserve(derives.len()); derives .into_iter() - .map(|(_exts, path)| { + .map(|(path, _exts)| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. let expn_id = ExpnId::fresh(None); - invocations.push(( + derive_invocations.push(( Invocation { kind: InvocationKind::Derive { path, @@ -540,7 +549,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }) .unwrap_or_default(); - self.collect_invocations(fragment, &derive_placeholders) + let (fragment, collected_invocations) = + self.collect_invocations(fragment, &derive_placeholders); + // We choose to expand any derive invocations associated with this macro invocation + // *before* any macro invocations collected from the output fragment + derive_invocations.extend(collected_invocations); + (fragment, derive_invocations) } ExpandResult::Retry(invoc) => { if force { @@ -599,10 +613,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let invocations = { let mut collector = InvocationCollector { + // Non-derive macro invocations cannot see the results of cfg expansion - they + // will either be removed along with the item, or invoked before the cfg/cfg_attr + // attribute is expanded. Therefore, we don't need to configure the tokens + // Derive macros *can* see the results of cfg-expansion - they are handled + // specially in `fully_expand_fragment` cfg: StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features, - modified: false, + config_tokens: false, }, cx: self.cx, invocations: Vec::new(), @@ -697,13 +716,26 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); - let tokens = match attr.style { - AttrStyle::Outer => item.into_tokens(&self.cx.sess.parse_sess), - // FIXME: Properly collect tokens for inner attributes - AttrStyle::Inner => rustc_parse::fake_token_stream( + let mut fake_tokens = false; + if let Annotatable::Item(item_inner) = &item { + if let ItemKind::Mod(_, mod_kind) = &item_inner.kind { + // FIXME: Collect tokens and use them instead of generating + // fake ones. These are unstable, so it needs to be + // fixed prior to stabilization + // Fake tokens when we are invoking an inner attribute, and: + fake_tokens = matches!(attr.style, ast::AttrStyle::Inner) && + // We are invoking an attribute on the crate root, or an outline + // module + (item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _))); + } + } + let tokens = if fake_tokens { + rustc_parse::fake_token_stream( &self.cx.sess.parse_sess, &item.into_nonterminal(), - ), + ) + } else { + item.into_tokens(&self.cx.sess.parse_sess) }; let attr_item = attr.unwrap_normal_item(); if let MacArgs::Eq(..) = attr_item.args { @@ -729,7 +761,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); } }; - fragment_kind.expect_from_annotatables(items) + if fragment_kind == AstFragmentKind::Expr && items.is_empty() { + let msg = + "removing an expression is not supported in this position"; + self.cx.span_err(span, msg); + fragment_kind.dummy(span) + } else { + fragment_kind.expect_from_annotatables(items) + } } Err(mut err) => { err.emit(); @@ -878,21 +917,21 @@ pub fn parse_ast_fragment<'a>( } AstFragmentKind::TraitItems => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_trait_item()? { + while let Some(item) = this.parse_trait_item(ForceCollect::No)? { items.extend(item); } AstFragment::TraitItems(items) } AstFragmentKind::ImplItems => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_impl_item()? { + while let Some(item) = this.parse_impl_item(ForceCollect::No)? { items.extend(item); } AstFragment::ImplItems(items) } AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_foreign_item()? { + while let Some(item) = this.parse_foreign_item(ForceCollect::No)? { items.extend(item); } AstFragment::ForeignItems(items) @@ -917,7 +956,7 @@ pub fn parse_ast_fragment<'a>( } AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?), AstFragmentKind::Pat => { - AstFragment::Pat(this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?) + AstFragment::Pat(this.parse_pat_allow_top_alt(None, RecoverComma::No)?) } AstFragmentKind::Arms | AstFragmentKind::Fields @@ -1054,13 +1093,23 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // since they will not be detected after macro expansion. fn check_attributes(&mut self, attrs: &[ast::Attribute]) { let features = self.cx.ecfg.features.unwrap(); - for attr in attrs.iter() { + let mut attrs = attrs.iter().peekable(); + let mut span: Option = None; + while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); validate_attr::check_meta(&self.cx.sess.parse_sess, attr); + + let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; + span = Some(current_span); + + if attrs.peek().map_or(false, |next_attr| next_attr.doc_str().is_some()) { + continue; + } + if attr.doc_str().is_some() { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( &UNUSED_DOC_COMMENTS, - attr.span, + current_span, ast::CRATE_NODE_ID, "unused doc comment", BuiltinLintDiagnostics::UnusedDocComment(attr.span), diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 1a93975533..5fb8586750 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -2,7 +2,8 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] -#![feature(or_patterns)] +#![feature(iter_zip)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index cbc4d14a65..5244ac36bb 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -69,7 +69,7 @@ enum KleeneOp { ZeroOrMore, /// Kleene plus (`+`) for one or more repetitions OneOrMore, - /// Kleene optional (`?`) for zero or one reptitions + /// Kleene optional (`?`) for zero or one repetitions ZeroOrOne, } diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 91add4f921..3497e5ad54 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -116,6 +116,8 @@ use rustc_span::{symbol::MacroRulesNormalizedIdent, MultiSpan, Span}; use smallvec::SmallVec; +use std::iter; + /// Stack represented as linked list. /// /// Those are used for environments because they grow incrementally and are not mutable. @@ -204,7 +206,7 @@ pub(super) fn check_meta_variables( sess.span_diagnostic.span_bug(span, "length mismatch between LHSes and RHSes") } let mut valid = true; - for (lhs, rhs) in lhses.iter().zip(rhses.iter()) { + for (lhs, rhs) in iter::zip(lhses, rhses) { let mut binders = Binders::default(); check_binders(sess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut valid); check_occurrences(sess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut valid); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 73fbde70bd..91d4a0f0d6 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -18,7 +18,8 @@ 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::SEMICOLON_IN_EXPRESSIONS_FROM_MACROS; +use rustc_lint_defs::builtin::{OR_PATTERNS_BACK_COMPAT, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS}; +use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::parser::Parser; use rustc_session::parse::ParseSess; use rustc_session::Session; @@ -951,8 +952,32 @@ fn check_matcher_core( // Now `last` holds the complete set of NT tokens that could // end the sequence before SUFFIX. Check that every one works with `suffix`. for token in &last.tokens { - if let TokenTree::MetaVarDecl(_, name, Some(kind)) = *token { + 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, + ), + ); + } + } + } + } match is_in_follow(next_token, kind) { IsInFollow::Yes => {} IsInFollow::No(possible) => { @@ -1080,7 +1105,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => { + NonterminalKind::PatParam { .. } => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1091,6 +1116,17 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } + NonterminalKind::PatWithOr { .. } => { + const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"]; + match tok { + TokenTree::Token(token) => match token.kind { + FatArrow | Comma | Eq => IsInFollow::Yes, + Ident(name, false) if name == kw::If || name == kw::In => IsInFollow::Yes, + _ => IsInFollow::No(TOKENS), + }, + _ => IsInFollow::No(TOKENS), + } + } NonterminalKind::Path | NonterminalKind::Ty => { const TOKENS: &[&str] = &[ "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`", diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index c8049495d2..aca02ef93f 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -6,8 +6,8 @@ use rustc_ast::tokenstream; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_feature::Features; -use rustc_session::parse::{feature_err, ParseSess}; -use rustc_span::symbol::{kw, sym, Ident}; +use rustc_session::parse::ParseSess; +use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; @@ -62,21 +62,6 @@ pub(super) fn parse( Some((frag, _)) => { let span = token.span.with_lo(start_sp.lo()); - match frag.name { - sym::pat2018 | sym::pat2021 => { - if !features.edition_macro_pats { - feature_err( - sess, - sym::edition_macro_pats, - frag.span, - "`pat2018` and `pat2021` are unstable.", - ) - .emit(); - } - } - _ => {} - } - let kind = token::NonterminalKind::from_symbol(frag.name, || { span.edition() diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index dde65d998d..f9e7c4254b 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -209,7 +209,7 @@ pub(super) fn transcribe<'a>( } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len` - // is the total number of reptitions we should generate. + // is the total number of repetitions we should generate. repeats.push((0, len)); // The first time we encounter the sequence we push it to the stack. It @@ -362,7 +362,7 @@ impl LockstepIterSize { /// appropriate meta-vars in `interpolations`. /// /// Note that if `repeats` does not match the exact correct depth of a meta-var, -/// `lookup_cur_matched` will return `None`, which is why this still works even in the presnece of +/// `lookup_cur_matched` will return `None`, which is why this still works even in the presence of /// multiple nested matcher sequences. fn lockstep_iter_size( tree: &mbe::TokenTree, diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 61b776ff2d..3f84979ac0 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -94,7 +94,7 @@ impl MultiItemModifier for ProcMacroDerive { { TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into() } else { - nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::Yes) + nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No) }; let server = proc_macro_server::Rustc::new(ecx); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index cb41bc8122..1ea26b4eab 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -739,9 +739,8 @@ fn ident_name_compatibility_hack( let time_macros_impl = macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs"); - if time_macros_impl - || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs")) - { + let js_sys = macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"); + if time_macros_impl || js_sys { let snippet = source_map.span_to_snippet(orig_span); if snippet.as_deref() == Ok("$name") { if time_macros_impl { @@ -754,8 +753,35 @@ fn ident_name_compatibility_hack( "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".to_string()) ); + return Some((*ident, *is_raw)); + } + if js_sys { + if let Some(c) = path + .components() + .flat_map(|c| c.as_os_str().to_str()) + .find(|c| c.starts_with("js-sys")) + { + let mut version = c.trim_start_matches("js-sys-").split("."); + if version.next() == Some("0") + && version.next() == Some("3") + && version + .next() + .and_then(|c| c.parse::().ok()) + .map_or(false, |v| v < 40) + { + rustc.sess.buffer_lint_with_diagnostic( + &PROC_MACRO_BACK_COMPAT, + orig_span, + ast::CRATE_NODE_ID, + "using an old version of `js-sys`", + BuiltinLintDiagnostics::ProcMacroBackCompat( + "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".to_string()) + ); + return Some((*ident, *is_raw)); + } + } } - return Some((*ident, *is_raw)); } } diff --git a/compiler/rustc_expand/src/tokenstream/tests.rs b/compiler/rustc_expand/src/tokenstream/tests.rs index 4e818e9feb..8b546e7e4a 100644 --- a/compiler/rustc_expand/src/tokenstream/tests.rs +++ b/compiler/rustc_expand/src/tokenstream/tests.rs @@ -1,7 +1,7 @@ use crate::tests::string_to_stream; use rustc_ast::token; -use rustc_ast::tokenstream::{TokenStream, TokenStreamBuilder, TokenTree}; +use rustc_ast::tokenstream::{Spacing, TokenStream, TokenStreamBuilder, TokenTree}; use rustc_span::with_default_session_globals; use rustc_span::{BytePos, Span, Symbol}; use smallvec::smallvec; @@ -14,6 +14,10 @@ fn sp(a: u32, b: u32) -> Span { Span::with_root_ctxt(BytePos(a), BytePos(b)) } +fn joint(tree: TokenTree) -> TokenStream { + TokenStream::new(vec![(tree, Spacing::Joint)]) +} + #[test] fn test_concat() { with_default_session_globals(|| { @@ -99,8 +103,8 @@ fn test_is_empty() { fn test_dotdotdot() { with_default_session_globals(|| { let mut builder = TokenStreamBuilder::new(); - builder.push(TokenTree::token(token::Dot, sp(0, 1)).joint()); - builder.push(TokenTree::token(token::Dot, sp(1, 2)).joint()); + builder.push(joint(TokenTree::token(token::Dot, sp(0, 1)))); + builder.push(joint(TokenTree::token(token::Dot, sp(1, 2)))); builder.push(TokenTree::token(token::Dot, sp(2, 3))); let stream = builder.build(); assert!(stream.eq_unspanned(&string_to_ts("..."))); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 9902b6cc9e..e8642a5274 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -276,7 +276,11 @@ declare_features! ( /// The smallest useful subset of `const_generics`. (accepted, min_const_generics, "1.51.0", Some(74878), None), /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block. - (accepted, unsafe_block_in_unsafe_fn, "1.51.0", Some(71668), None), + (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668), None), + /// Allows the use of or-patterns (e.g., `0 | 1`). + (accepted, or_patterns, "1.53.0", Some(54883), None), + /// Allows defining identifiers beyond ASCII. + (accepted, non_ascii_idents, "1.53.0", Some(55467), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 79ec9c2649..bc9f1039d6 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -63,6 +63,10 @@ macro_rules! declare_features { _ => panic!("`{}` was not listed in `declare_features`", feature), } } + + pub fn unordered_const_ty_params(&self) -> bool { + self.const_generics || self.const_generics_defaults + } } }; } @@ -134,9 +138,6 @@ declare_features! ( /// Allows using the `box $expr` syntax. (active, box_syntax, "1.0.0", Some(49733), None), - /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. - (active, main, "1.0.0", Some(29634), None), - /// Allows using `#[start]` on a function indicating that it is the program entrypoint. (active, start, "1.0.0", Some(29633), None), @@ -216,6 +217,10 @@ declare_features! ( /// Renamed from `optin_builtin_traits`. (active, auto_traits, "1.50.0", Some(13231), None), + /// Allows `#[doc(notable_trait)]`. + /// Renamed from `doc_spotlight`. + (active, doc_notable_trait, "1.52.0", Some(45040), None), + // no-tracking-issue-end // ------------------------------------------------------------------------- @@ -254,12 +259,6 @@ declare_features! ( // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - /// Allows using the `#[link_args]` attribute. - (active, link_args, "1.0.0", Some(29596), None), - - /// Allows defining identifiers beyond ASCII. - (active, non_ascii_idents, "1.0.0", Some(55467), None), - /// Allows using `#[plugin_registrar]` on functions. (active, plugin_registrar, "1.0.0", Some(29597), None), @@ -374,9 +373,6 @@ declare_features! ( /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), - /// Allows `#[doc(spotlight)]`. - (active, doc_spotlight, "1.22.0", Some(45040), None), - /// Allows `#[doc(include = "some-file")]`. (active, external_doc, "1.22.0", Some(44732), None), @@ -488,9 +484,6 @@ declare_features! ( /// Allows `impl Trait` to be used inside type aliases (RFC 2515). (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - /// Allows the use of or-patterns (e.g., `0 | 1`). - (active, or_patterns, "1.38.0", Some(54883), None), - /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (active, const_extern_fn, "1.40.0", Some(64926), None), @@ -614,9 +607,6 @@ declare_features! ( /// Allows arbitrary expressions in key-value attributes at parse time. (active, extended_key_value_attributes, "1.50.0", Some(78835), None), - /// `:pat2018` and `:pat2021` macro matchers. - (active, edition_macro_pats, "1.51.0", Some(54883), None), - /// Allows const generics to have default values (e.g. `struct Foo(...);`). (active, const_generics_defaults, "1.51.0", Some(44580), None), @@ -635,18 +625,34 @@ declare_features! ( /// Allows macro attributes to observe output of `#[derive]`. (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None), - /// Allows `pub` on `macro_rules` items. - (active, pub_macro_rules, "1.52.0", Some(78855), None), - /// Allows the use of type alias impl trait in function return positions (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), + // Allows setting the threshold for the `large_assignments` lint. + (active, large_assignments, "1.52.0", Some(83518), None), + /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. (active, c_unwind, "1.52.0", Some(74990), None), + /// Allows `extern "wasm" fn` + (active, wasm_abi, "1.53.0", Some(83788), None), + + /// Allows function attribute `#[no_coverage]`, to bypass coverage + /// instrumentation of that function. + (active, no_coverage, "1.53.0", Some(84605), None), + + /// Allows trait bounds in `const fn`. + (active, const_fn_trait_bound, "1.53.0", Some(57563), None), + + /// Allows unsizing coercions in `const fn`. + (active, const_fn_unsize, "1.53.0", Some(64992), None), + + /// Allows using imported `main` function + (active, imported_main, "1.53.0", Some(28937), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 072062dd61..a8719be84c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -227,8 +227,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), ), ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")), - ungated!(no_link, Normal, template!(Word)), - ungated!(repr, Normal, template!(List: "C")), + ungated!(no_link, AssumedUsed, template!(Word)), + ungated!(repr, AssumedUsed, template!(List: "C")), ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")), ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")), ungated!(no_mangle, AssumedUsed, template!(Word)), @@ -241,6 +241,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, experimental!(const_eval_limit) ), + gated!( + move_size_limit, CrateLevel, template!(NameValueStr: "N"), large_assignments, + experimental!(move_size_limit) + ), // Entry point: ungated!(main, Normal, template!(Word)), @@ -269,6 +273,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(List: "address, memory, thread"), experimental!(no_sanitize) ), + gated!(no_coverage, AssumedUsed, template!(Word), experimental!(no_coverage)), // FIXME: #14408 assume docs are used since rustdoc looks at them. ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")), @@ -279,11 +284,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Linking: gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)), - gated!( - link_args, Normal, template!(NameValueStr: "args"), - "the `link_args` attribute is experimental and not portable across platforms, \ - it is recommended to use `#[link(name = \"foo\")] instead", - ), gated!( link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib, experimental!(link_ordinal) @@ -322,7 +322,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "custom test frameworks are an unstable feature", ), // RFC #1268 - gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), + gated!(marker, AssumedUsed, template!(Word), marker_trait_attr, experimental!(marker)), gated!( thread_local, AssumedUsed, template!(Word), "`#[thread_local]` is an experimental feature, and does not currently handle destructors", @@ -541,6 +541,15 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_specialization_trait, Normal, template!(Word), "the `#[rustc_specialization_trait]` attribute is used to check specializations" ), + rustc_attr!( + rustc_main, Normal, template!(Word), + "the `#[rustc_main]` attribute is used internally to specify test entry point function", + ), + rustc_attr!( + rustc_skip_array_during_method_dispatch, Normal, template!(Word), + "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ + from method dispatch when the receiver is an array, for compatibility in editions < 2021." + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 2a7c2a02fb..654d240858 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -1,7 +1,7 @@ //! # Feature gates //! //! This crate declares the set of past and present unstable features in the compiler. -//! Feature gate checking itself is done in `librustc_ast_passes/feature_gate.rs` +//! Feature gate checking itself is done in `rustc_ast_passes/src/feature_gate.rs` //! at the moment. //! //! Features are enabled in programs via the crate-level attributes of diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index aff66053c9..fa8ef182ae 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -80,6 +80,11 @@ declare_features! ( Some("subsumed by `#![feature(allocator_internals)]`")), /// Allows identifying crates that contain sanitizer runtimes. (removed, sanitizer_runtime, "1.17.0", None, None, None), + /// Allows `#[doc(spotlight)]`. + /// The attribute was renamed to `#[doc(notable_trait)]` + /// and the feature to `doc_notable_trait`. + (removed, doc_spotlight, "1.22.0", Some(45040), None, + Some("renamed to `doc_notable_trait`")), (removed, proc_macro_mod, "1.27.0", Some(54727), None, Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, proc_macro_expr, "1.27.0", Some(54727), None, @@ -123,6 +128,14 @@ declare_features! ( /// Allows comparing raw pointers during const eval. (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None, Some("cannot be allowed in const eval in any meaningful way")), + /// Allows using the `#[link_args]` attribute. + (removed, link_args, "1.53.0", Some(29596), None, + Some("removed in favor of using `-C link-arg=ARG` on command line, \ + which is available from cargo build scripts with `cargo:rustc-link-arg` now")), + /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. + (removed, main, "1.53.0", Some(29634), None, None), + (removed, pub_macro_rules, "1.53.0", Some(78855), None, + Some("removed due to being incomplete, in particular it does not work across crates")), // ------------------------------------------------------------------------- // feature-group-end: removed features diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 9653ff022f..db70beb591 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -413,10 +413,6 @@ impl<'a> Id<'a> { pub fn as_slice(&'a self) -> &'a str { &*self.name } - - pub fn name(self) -> Cow<'a, str> { - self.name - } } /// Each instance of a type that implements `Label` maps to a @@ -484,10 +480,6 @@ impl<'a> LabelText<'a> { LabelStr(s.into()) } - pub fn escaped>>(s: S) -> LabelText<'a> { - EscStr(s.into()) - } - pub fn html>>(s: S) -> LabelText<'a> { HtmlStr(s.into()) } @@ -543,11 +535,6 @@ impl<'a> LabelText<'a> { } } - /// Puts `prefix` on a line above this label, with a blank line separator. - pub fn prefix_line(self, prefix: LabelText<'_>) -> LabelText<'static> { - prefix.suffix_line(self) - } - /// Puts `suffix` on a line below this label, with a blank line separator. pub fn suffix_line(self, suffix: LabelText<'_>) -> LabelText<'static> { let mut prefix = self.pre_escaped_content().into_owned(); @@ -602,11 +589,6 @@ pub enum RenderOption { DarkTheme, } -/// Returns vec holding all the default render options. -pub fn default_options() -> Vec { - vec![] -} - /// Renders directed graph `g` into the writer `w` in DOT syntax. /// (Simple wrapper around `render_opts` that passes a default set of options.) pub fn render<'a, N, E, G, W>(g: &'a G, w: &mut W) -> io::Result<()> diff --git a/compiler/rustc_graphviz/src/tests.rs b/compiler/rustc_graphviz/src/tests.rs index 70b8197f5e..a297bac86c 100644 --- a/compiler/rustc_graphviz/src/tests.rs +++ b/compiler/rustc_graphviz/src/tests.rs @@ -111,7 +111,7 @@ impl<'a> Labeller<'a> for LabelledGraph { fn node_label(&'a self, n: &Node) -> LabelText<'a> { match self.node_labels[*n] { Some(l) => LabelStr(l.into()), - None => LabelStr(id_name(n).name()), + None => LabelStr(id_name(n).name), } } fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> { diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index a81eb747a3..de10d88c1d 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -20,6 +20,7 @@ pub enum CtorOf { Variant, } +/// What kind of constructor something is. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum CtorKind { @@ -31,6 +32,7 @@ pub enum CtorKind { Fictive, } +/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum NonMacroAttrKind { @@ -47,33 +49,51 @@ pub enum NonMacroAttrKind { Registered, } +/// What kind of definition something is; e.g., `mod` vs `struct`. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum DefKind { // Type namespace Mod, - /// Refers to the struct itself, `DefKind::Ctor` refers to its constructor if it exists. + /// Refers to the struct itself, [`DefKind::Ctor`] refers to its constructor if it exists. Struct, Union, Enum, - /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists. + /// Refers to the variant itself, [`DefKind::Ctor`] refers to its constructor if it exists. Variant, Trait, - /// `type Foo = Bar;` + /// Type alias: `type Foo = Bar;` TyAlias, + /// Type from an `extern` block. ForeignTy, + /// Trait alias: `trait IntIterator = Iterator;` TraitAlias, + /// Associated type: `trait MyTrait { type Assoc; }` AssocTy, + /// Type parameter: the `T` in `struct Vec { ... }` TyParam, // Value namespace Fn, Const, + /// Constant generic parameter: `struct Foo { ... }` ConstParam, Static, /// Refers to the struct or enum variant's constructor. + /// + /// The reason `Ctor` exists in addition to [`DefKind::Struct`] and + /// [`DefKind::Variant`] is because structs and enum variants exist + /// in the *type* namespace, whereas struct and enum variant *constructors* + /// exist in the *value* namespace. + /// + /// You may wonder why enum variants exist in the type namespace as opposed + /// to the value namespace. Check out [RFC 2593] for intuition on why that is. + /// + /// [RFC 2593]: https://github.com/rust-lang/rfcs/pull/2593 Ctor(CtorOf, CtorKind), + /// Associated function: `impl MyStruct { fn associated() {} }` AssocFn, + /// Associated constant: `trait MyTrait { const ASSOC: usize; }` AssocConst, // Macro namespace @@ -82,11 +102,16 @@ pub enum DefKind { // Not namespaced (or they are, but we don't treat them so) ExternCrate, Use, + /// An `extern` block. ForeignMod, + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}` AnonConst, + /// Opaque type, aka `impl Trait`. OpaqueTy, Field, + /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, + /// A use of [`global_asm!`]. GlobalAsm, Impl, Closure, @@ -196,35 +221,130 @@ impl DefKind { } /// The resolution of a path or export. +/// +/// For every path or identifier in Rust, the compiler must determine +/// what the path refers to. This process is called name resolution, +/// and `Res` is the primary result of name resolution. +/// +/// For example, everything prefixed with `/* Res */` in this example has +/// an associated `Res`: +/// +/// ``` +/// fn str_to_string(s: & /* Res */ str) -> /* Res */ String { +/// /* Res */ String::from(/* Res */ s) +/// } +/// +/// /* Res */ str_to_string("hello"); +/// ``` +/// +/// The associated `Res`s will be: +/// +/// - `str` will resolve to [`Res::PrimTy`]; +/// - `String` will resolve to [`Res::Def`], and the `Res` will include the [`DefId`] +/// for `String` as defined in the standard library; +/// - `String::from` will also resolve to [`Res::Def`], with the [`DefId`] +/// pointing to `String::from`; +/// - `s` will resolve to [`Res::Local`]; +/// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`] +/// pointing to the definition of `str_to_string` in the current crate. +// #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum Res { + /// Definition having a unique ID (`DefId`), corresponds to something defined in user code. + /// + /// **Not bound to a specific namespace.** Def(DefKind, DefId), // Type namespace + /// A primitive type such as `i32` or `str`. + /// + /// **Belongs to the type namespace.** PrimTy(hir::PrimTy), - /// `Self`, with both an optional trait and impl `DefId`. + /// The `Self` type, optionally with the trait it is associated with + /// and optionally with the [`DefId`] of the impl it is associated with. + /// + /// **Belongs to the type namespace.** + /// + /// For example, the `Self` in /// - /// HACK(min_const_generics): impl self types also have an optional requirement to not mention + /// ``` + /// trait Foo { + /// fn foo() -> Box; + /// } + /// ``` + /// + /// would have the [`DefId`] of `Foo` associated with it. The `Self` in + /// + /// ``` + /// struct Bar; + /// + /// impl Bar { + /// fn new() -> Self { Bar } + /// } + /// ``` + /// + /// would have the [`DefId`] of the impl associated with it. Finally, the `Self` in + /// + /// ``` + /// impl Foo for Bar { + /// fn foo() -> Box { Box::new(Bar) } + /// } + /// ``` + /// + /// would have both the [`DefId`] of `Foo` and the [`DefId`] of the impl + /// associated with it. + /// + /// *See also [`Res::SelfCtor`].* + /// + /// ----- + /// + /// HACK(min_const_generics): impl self types also have an optional requirement to **not** mention /// any generic parameters to allow the following with `min_const_generics`: - /// ```rust - /// impl Foo { fn test() -> [u8; std::mem::size_of::()] {} } + /// ``` + /// impl Foo { fn test() -> [u8; std::mem::size_of::()] { todo!() } } /// ``` /// We do however allow `Self` in repeat expression even if it is generic to not break code /// which already works on stable while causing the `const_evaluatable_unchecked` future compat lint. /// /// FIXME(lazy_normalization_consts): Remove this bodge once that feature is stable. - SelfTy(Option /* trait */, Option<(DefId, bool)> /* impl */), - ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` + SelfTy( + /// Optionally, the trait associated with this `Self` type. + Option, + /// Optionally, the impl associated with this `Self` type. + Option<(DefId, bool)>, + ), + /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`. + /// + /// **Belongs to the type namespace.** + ToolMod, // Value namespace - SelfCtor(DefId /* impl */), // `DefId` refers to the impl + /// The `Self` constructor, along with the [`DefId`] + /// of the impl it is associated with. + /// + /// **Belongs to the value namespace.** + /// + /// *See also [`Res::SelfTy`].* + SelfCtor(DefId), + /// A local variable or function parameter. + /// + /// **Belongs to the value namespace.** Local(Id), // Macro namespace + /// An attribute that is *not* implemented via macro. + /// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives, + /// as opposed to `#[test]`, which is a builtin macro. + /// + /// **Belongs to the macro namespace.** NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` // All namespaces + /// Name resolution failed. We use a dummy `Res` variant so later phases + /// of the compiler won't crash and can instead report more errors. + /// + /// **Not bound to a specific namespace.** Err, } @@ -275,17 +395,26 @@ impl PartialRes { } } -/// Different kinds of symbols don't influence each other. -/// -/// Therefore, they have a separate universe (namespace). +/// Different kinds of symbols can coexist even if they share the same textual name. +/// Therefore, they each have a separate universe (known as a "namespace"). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum Namespace { + /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s + /// (and, by extension, crates). + /// + /// Note that the type namespace includes other items; this is not an + /// exhaustive list. TypeNS, + /// The value namespace includes `fn`s, `const`s, `static`s, and local variables (including function arguments). ValueNS, + /// The macro namespace includes `macro_rules!` macros, declarative `macro`s, + /// procedural macros, attribute macros, `derive` macros, and non-macro attributes + /// like `#[inline]` and `#[rustfmt::skip]`. MacroNS, } impl Namespace { + /// The English description of the namespace. pub fn descr(self) -> &'static str { match self { Self::TypeNS => "type", diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 3266dfac70..0f77de9fb2 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -87,6 +87,7 @@ impl DefPathTable { hash } + /// Used by librustdoc for fake DefIds. pub fn num_def_ids(&self) -> usize { self.index_to_key.len() } @@ -319,12 +320,6 @@ impl Definitions { self.table.def_path_hash(id.local_def_index) } - #[inline] - pub fn def_path_hash_to_def_id(&self, def_path_hash: DefPathHash) -> LocalDefId { - let local_def_index = self.table.def_path_hash_to_index[&def_path_hash]; - LocalDefId { local_def_index } - } - /// Returns the path from the crate root to `index`. The root /// nodes are not included in the path (i.e., this will be an /// empty vector for the crate root). For an inlined item, this diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d03584d49a..5baaaad737 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,5 +1,5 @@ // ignore-tidy-filelength -use crate::def::{CtorKind, DefKind, Namespace, Res}; +use crate::def::{CtorKind, DefKind, Res}; use crate::def_id::DefId; crate use crate::hir_id::HirId; use crate::{itemlikevisit, LangItem}; @@ -296,7 +296,9 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics }, + GenericArg::Const(_) => { + ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } + } } } } @@ -402,7 +404,7 @@ pub enum TraitBoundModifier { /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` @@ -625,13 +627,6 @@ pub struct ModuleItems { pub foreign_items: BTreeSet, } -/// A type representing only the top-level module. -#[derive(Encodable, Debug, HashStable_Generic)] -pub struct CrateItem<'hir> { - pub module: Mod<'hir>, - pub span: Span, -} - /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -640,7 +635,7 @@ pub struct CrateItem<'hir> { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(Debug)] pub struct Crate<'hir> { - pub item: CrateItem<'hir>, + pub item: Mod<'hir>, pub exported_macros: &'hir [MacroDef<'hir>], // Attributes from non-exported macros, kept only for collecting the library feature list. pub non_exported_macro_attrs: &'hir [Attribute], @@ -2118,15 +2113,6 @@ pub enum ImplItemKind<'hir> { TyAlias(&'hir Ty<'hir>), } -impl ImplItemKind<'_> { - pub fn namespace(&self) -> Namespace { - match self { - ImplItemKind::TyAlias(..) => Namespace::TypeNS, - ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS, - } - } -} - // The name of the associated type for `Fn` return types. pub const FN_OUTPUT_NAME: Symbol = sym::Output; @@ -2215,6 +2201,9 @@ impl PrimTy { Self::Str, ]; + /// Like [`PrimTy::name`], but returns a &str instead of a symbol. + /// + /// Used by clippy. pub fn name_str(self) -> &'static str { match self { PrimTy::Int(i) => i.name_str(), @@ -2360,7 +2349,7 @@ pub enum InlineAsmOperand<'hir> { out_expr: Option>, }, Const { - expr: Expr<'hir>, + anon_const: AnonConst, }, Sym { expr: Expr<'hir>, @@ -2569,7 +2558,7 @@ pub enum UseKind { /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the /// trait being referred to but just a unique `HirId` that serves as a key /// within the resolution map. -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub struct TraitRef<'hir> { pub path: &'hir Path<'hir>, // Don't hash the `ref_id`. It is tracked via the thing it is used to access. @@ -2588,7 +2577,7 @@ impl TraitRef<'_> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], @@ -2989,7 +2978,7 @@ pub enum Node<'hir> { GenericParam(&'hir GenericParam<'hir>), Visibility(&'hir Visibility<'hir>), - Crate(&'hir CrateItem<'hir>), + Crate(&'hir Mod<'hir>), } impl<'hir> Node<'hir> { diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index e0b3d9026a..0b25ebc27b 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -63,6 +63,7 @@ pub const CRATE_HIR_ID: HirId = HirId { local_id: ItemLocalId::from_u32(0), }; +/// N.B. This collection is currently unused, but will be used by #72015 and future PRs. #[derive(Clone, Default, Debug, Encodable, Decodable)] pub struct HirIdVec { map: IndexVec>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 701e4a6329..0ce04a77a5 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -98,7 +98,7 @@ where } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>), @@ -366,6 +366,9 @@ pub trait Visitor<'v>: Sized { fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) { walk_generic_param(self, p) } + fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) { + walk_const_param_default(self, ct) + } fn visit_generics(&mut self, g: &'v Generics<'v>) { walk_generics(self, g) } @@ -475,7 +478,7 @@ pub trait Visitor<'v>: Sized { /// Walks the contents of a crate. See also `Crate::visit_all_items`. pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { - visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID); + visitor.visit_mod(&krate.item, krate.item.inner, CRATE_HIR_ID); walk_list!(visitor, visit_macro_def, krate.exported_macros); for (&id, attrs) in krate.attrs.iter() { for a in *attrs { @@ -869,13 +872,17 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi GenericParamKind::Const { ref ty, ref default } => { visitor.visit_ty(ty); if let Some(ref default) = default { - visitor.visit_anon_const(default); + visitor.visit_const_param_default(param.hir_id, default); } } } walk_list!(visitor, visit_param_bound, param.bounds); } +pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v AnonConst) { + visitor.visit_anon_const(ct) +} + pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) { walk_list!(visitor, visit_generic_param, generics.params); walk_list!(visitor, visit_where_predicate, generics.where_clause.predicates); @@ -1182,7 +1189,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } - | InlineAsmOperand::Const { expr, .. } | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr), InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -1195,6 +1201,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) visitor.visit_expr(out_expr); } } + InlineAsmOperand::Const { anon_const, .. } => { + visitor.visit_anon_const(anon_const) + } } } } diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 45bb911130..65c99535c4 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -3,12 +3,11 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] -#![feature(const_fn)] // For the unsizing cast on `&[]` #![feature(const_panic)] #![feature(extended_key_value_attributes)] #![feature(in_band_lifetimes)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index 9e0a6aae24..b1f78a83e7 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -1,6 +1,7 @@ use crate::def::{CtorOf, DefKind, Res}; use crate::def_id::DefId; use crate::hir::{self, HirId, PatKind}; +use rustc_data_structures::stable_set::FxHashSet; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -89,26 +90,6 @@ impl hir::Pat<'_> { }) } - /// Checks if the pattern contains any patterns that bind something to - /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`. - pub fn contains_bindings(&self) -> bool { - self.satisfies(|p| matches!(p.kind, PatKind::Binding(..))) - } - - /// Checks if the pattern satisfies the given predicate on some sub-pattern. - fn satisfies(&self, pred: impl Fn(&hir::Pat<'_>) -> bool) -> bool { - let mut satisfies = false; - self.walk_short(|p| { - if pred(p) { - satisfies = true; - false // Found one, can short circuit now. - } else { - true - } - }); - satisfies - } - pub fn simple_ident(&self) -> Option { match self.kind { PatKind::Binding( @@ -138,8 +119,10 @@ impl hir::Pat<'_> { } _ => true, }); - variants.sort(); - variants.dedup(); + // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering + // the bounds + let mut duplicates = FxHashSet::default(); + variants.retain(|def_id| duplicates.insert(*def_id)); variants } diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 55e87663a1..0232654aaa 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -9,7 +9,7 @@ use rustc_span::def_id::{DefPathHash, LocalDefId}; /// 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 librustc_middle. +/// instead of implementing everything in `rustc_middle`. pub trait HashStableContext: rustc_ast::HashStableContext + rustc_target::HashStableContext { diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index b8cd15e7f0..58c3065240 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -18,8 +18,8 @@ pub static WEAK_ITEMS_REFS: SyncLazy> = SyncLazy::ne map }); -/// The `check_name` argument avoids the need for `librustc_hir` to depend on -/// `librustc_session`. +/// The `check_name` argument avoids the need for `rustc_hir` to depend on +/// `rustc_session`. pub fn link_name<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option where F: Fn(&'a ast::Attribute, Symbol) -> bool diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b37a3e19b8..77d083fc5e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] use rustc_ast as ast; @@ -170,7 +170,7 @@ pub fn print_crate<'a>( // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. - s.print_mod(&krate.item.module, s.attrs(hir::CRATE_HIR_ID)); + s.print_mod(&krate.item, s.attrs(hir::CRATE_HIR_ID)); s.print_remaining_comments(); s.s.eof() } @@ -221,10 +221,6 @@ pub fn bounds_to_string<'b>(bounds: impl IntoIterator) -> String { - to_string(NO_ANN, |s| s.print_param(arg)) -} - pub fn ty_to_string(ty: &hir::Ty<'_>) -> String { to_string(NO_ANN, |s| s.print_type(ty)) } @@ -1099,8 +1095,8 @@ impl<'a> State<'a> { fn print_else(&mut self, els: Option<&hir::Expr<'_>>) { match els { - Some(_else) => { - match _else.kind { + Some(else_) => { + match else_.kind { // "another else-if" hir::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); @@ -1118,6 +1114,26 @@ impl<'a> State<'a> { self.s.word(" else "); self.print_block(&b) } + hir::ExprKind::Match(ref expr, arms, _) => { + // else if let desugared to match + assert!(arms.len() == 2, "if let desugars to match with two arms"); + + self.s.word(" else "); + self.s.word("{"); + + self.cbox(INDENT_UNIT); + self.ibox(INDENT_UNIT); + self.word_nbsp("match"); + self.print_expr_as_cond(&expr); + self.s.space(); + self.bopen(); + for arm in arms { + self.print_arm(arm); + } + self.bclose(expr.span); + + self.s.word("}"); + } // BLEAH, constraints would be great here _ => { panic!("print_if saw if with weird alternative"); @@ -1574,10 +1590,10 @@ impl<'a> State<'a> { None => s.word("_"), } } - hir::InlineAsmOperand::Const { expr } => { + hir::InlineAsmOperand::Const { anon_const } => { s.word("const"); s.space(); - s.print_expr(expr); + s.print_anon_const(anon_const); } hir::InlineAsmOperand::Sym { expr } => { s.word("sym"); @@ -1701,21 +1717,10 @@ impl<'a> State<'a> { } } - pub fn print_usize(&mut self, i: usize) { - self.s.word(i.to_string()) - } - pub fn print_name(&mut self, name: Symbol) { self.print_ident(Ident::with_dummy_span(name)) } - pub fn print_for_decl(&mut self, loc: &hir::Local<'_>, coll: &hir::Expr<'_>) { - self.print_local_decl(loc); - self.s.space(); - self.word_space("in"); - self.print_expr(coll) - } - pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) { self.maybe_print_comment(path.span.lo()); @@ -2266,8 +2271,10 @@ impl<'a> State<'a> { GenericParamKind::Const { ref ty, ref default } => { self.word_space(":"); self.print_type(ty); - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): print the `default` value here + if let Some(ref default) = default { + self.s.space(); + self.word_space("="); + self.print_anon_const(&default) } } } @@ -2428,24 +2435,6 @@ impl<'a> State<'a> { } } - pub fn print_opt_abi_and_extern_if_nondefault(&mut self, opt_abi: Option) { - match opt_abi { - Some(Abi::Rust) => {} - Some(abi) => { - self.word_nbsp("extern"); - self.word_nbsp(abi.to_string()) - } - None => {} - } - } - - pub fn print_extern_opt_abi(&mut self, opt_abi: Option) { - if let Some(abi) = opt_abi { - self.word_nbsp("extern"); - self.word_nbsp(abi.to_string()) - } - } - pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) { self.s.word(visibility_qualified(vis, "")); diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index f1f69f1510..b5680beae1 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -40,8 +40,9 @@ use rustc_graphviz as dot; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_middle::dep_graph::debug::{DepNodeFilter, EdgeFilter}; -use rustc_middle::dep_graph::{DepGraphQuery, DepKind, DepNode, DepNodeExt}; +use rustc_middle::dep_graph::{ + DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, +}; use rustc_middle::hir::map::Map; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; @@ -54,7 +55,11 @@ use std::io::{BufWriter, Write}; pub fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.debugging_opts.dump_dep_graph { - dump_graph(tcx); + tcx.dep_graph.with_query(dump_graph); + } + + if !tcx.sess.opts.debugging_opts.query_dep_graph { + return; } // if the `rustc_attrs` feature is not enabled, then the @@ -196,29 +201,29 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou } return; } - let query = tcx.dep_graph.query(); - for &(_, source_def_id, ref source_dep_node) in if_this_changed { - let dependents = query.transitive_predecessors(source_dep_node); - for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { - if !dependents.contains(&target_dep_node) { - tcx.sess.span_err( - target_span, - &format!( - "no path from `{}` to `{}`", - tcx.def_path_str(source_def_id), - target_pass - ), - ); - } else { - tcx.sess.span_err(target_span, "OK"); + tcx.dep_graph.with_query(|query| { + for &(_, source_def_id, ref source_dep_node) in if_this_changed { + let dependents = query.transitive_predecessors(source_dep_node); + for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { + if !dependents.contains(&target_dep_node) { + tcx.sess.span_err( + target_span, + &format!( + "no path from `{}` to `{}`", + tcx.def_path_str(source_def_id), + target_pass + ), + ); + } else { + tcx.sess.span_err(target_span, "OK"); + } } } - } + }); } -fn dump_graph(tcx: TyCtxt<'_>) { +fn dump_graph(query: &DepGraphQuery) { let path: String = env::var("RUST_DEP_GRAPH").unwrap_or_else(|_| "dep_graph".to_string()); - let query = tcx.dep_graph.query(); let nodes = match env::var("RUST_DEP_GRAPH_FILTER") { Ok(string) => { diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 95456c07b1..f089cbcfca 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -14,7 +14,7 @@ mod assert_dep_graph; pub mod assert_module_sources; mod persist; -pub use assert_dep_graph::assert_dep_graph; +use assert_dep_graph::assert_dep_graph; pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir; pub use persist::delete_workproduct_files; pub use persist::finalize_session_directory; @@ -26,4 +26,4 @@ pub use persist::prepare_session_directory; pub use persist::save_dep_graph; pub use persist::save_work_product_index; pub use persist::LoadResult; -pub use persist::{load_dep_graph, DepGraphFuture}; +pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture}; diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 0b544b8ab4..e7bd488af8 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -14,7 +14,6 @@ //! the required condition is not met. use rustc_ast::{self as ast, Attribute, NestedMetaItem}; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -74,16 +73,6 @@ const BASE_STRUCT: &[&str] = &[label_strs::generics_of, label_strs::predicates_of, label_strs::type_of]; /// Trait definition `DepNode`s. -const BASE_TRAIT_DEF: &[&str] = &[ - label_strs::associated_item_def_ids, - label_strs::generics_of, - label_strs::object_safety_violations, - label_strs::predicates_of, - label_strs::specialization_graph_of, - label_strs::trait_def, - label_strs::trait_impls_of, -]; - /// Extra `DepNode`s for functions and methods. const EXTRA_ASSOCIATED: &[&str] = &[label_strs::associated_item]; @@ -118,10 +107,6 @@ const LABELS_IMPL: &[&[&str]] = &[BASE_HIR, BASE_IMPL]; /// Abstract data type (struct, enum, union) `DepNode`s. const LABELS_ADT: &[&[&str]] = &[BASE_HIR, BASE_STRUCT]; -/// Trait definition `DepNode`s. -#[allow(dead_code)] -const LABELS_TRAIT: &[&[&str]] = &[BASE_HIR, BASE_TRAIT_DEF]; - // FIXME: Struct/Enum/Unions Fields (there is currently no way to attach these) // // Fields are kind of separate from their containers, as they can change independently from @@ -148,6 +133,10 @@ impl Assertion { } pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { + if !tcx.sess.opts.debugging_opts.query_dep_graph { + return; + } + // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.features().rustc_attrs { return; @@ -391,10 +380,7 @@ impl DirtyCleanVisitor<'tcx> { fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - let current_fingerprint = self.get_fingerprint(&dep_node); - let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - - if current_fingerprint == prev_fingerprint { + if self.tcx.dep_graph.is_green(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess @@ -402,28 +388,10 @@ impl DirtyCleanVisitor<'tcx> { } } - fn get_fingerprint(&self, dep_node: &DepNode) -> Option { - if self.tcx.dep_graph.dep_node_exists(dep_node) { - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node); - Some(self.tcx.dep_graph.fingerprint_of(dep_node_index)) - } else { - None - } - } - fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - let current_fingerprint = self.get_fingerprint(&dep_node); - let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - - // if the node wasn't previously evaluated and now is (or vice versa), - // then the node isn't actually clean or dirty. - if (current_fingerprint == None) ^ (prev_fingerprint == None) { - return; - } - - if current_fingerprint != prev_fingerprint { + if self.tcx.dep_graph.is_red(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx .sess diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 374a9eb41e..b821ed6cff 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -15,6 +15,7 @@ use std::io::{self, Read}; use std::path::Path; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; +use rustc_serialize::Encoder; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index c7a6c1195c..30c6c408bc 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -122,6 +122,7 @@ mod tests; const LOCK_FILE_EXT: &str = ".lock"; const DEP_GRAPH_FILENAME: &str = "dep-graph.bin"; +const STAGING_DEP_GRAPH_FILENAME: &str = "dep-graph.part.bin"; const WORK_PRODUCTS_FILENAME: &str = "work-products.bin"; const QUERY_CACHE_FILENAME: &str = "query-cache.bin"; @@ -134,6 +135,9 @@ const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE; pub fn dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME) } +pub fn staging_dep_graph_path(sess: &Session) -> PathBuf { + in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME) +} pub fn dep_graph_path_from(incr_comp_session_dir: &Path) -> PathBuf { in_incr_comp_dir(incr_comp_session_dir, DEP_GRAPH_FILENAME) } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 2b5649bb05..2661afd7ff 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -5,7 +5,7 @@ use rustc_hir::definitions::Definitions; use rustc_middle::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::ty::query::OnDiskCache; use rustc_serialize::opaque::Decoder; -use rustc_serialize::Decodable as RustcDecodable; +use rustc_serialize::Decodable; use rustc_session::Session; use std::path::Path; @@ -104,7 +104,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { // Fortunately, we just checked that this isn't the case. let path = dep_graph_path_from(&sess.incr_comp_session_dir()); let report_incremental_info = sess.opts.debugging_opts.incremental_info; - let expected_hash = sess.opts.dep_tracking_hash(); + let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = FxHashMap::default(); let nightly_build = sess.is_nightly_build(); @@ -120,7 +120,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { // Decode the list of work_products let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos); let work_products: Vec = - RustcDecodable::decode(&mut work_product_decoder).unwrap_or_else(|e| { + Decodable::decode(&mut work_product_decoder).unwrap_or_else(|e| { let msg = format!( "Error decoding `work-products` from incremental \ compilation session directory: {}", diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index 8821b34b50..1336189bc0 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -18,6 +18,7 @@ pub use fs::prepare_session_directory; pub use load::load_query_result_cache; pub use load::LoadResult; pub use load::{load_dep_graph, DepGraphFuture}; +pub use save::build_dep_graph; pub use save::save_dep_graph; pub use save::save_work_product_index; pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 45d474b89b..1484088837 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::join; -use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{DepGraph, PreviousDepGraph, WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encodable as RustcEncodable; @@ -15,6 +15,9 @@ use super::file_format; use super::fs::*; use super::work_product; +/// Save and dump the DepGraph. +/// +/// No query must be invoked after this function. pub fn save_dep_graph(tcx: TyCtxt<'_>) { debug!("save_dep_graph()"); tcx.dep_graph.with_ignore(|| { @@ -29,6 +32,14 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { let query_cache_path = query_cache_path(sess); let dep_graph_path = dep_graph_path(sess); + let staging_dep_graph_path = staging_dep_graph_path(sess); + + sess.time("assert_dep_graph", || crate::assert_dep_graph(tcx)); + sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx)); + + if sess.opts.debugging_opts.incremental_info { + tcx.dep_graph.print_incremental_info() + } join( move || { @@ -36,16 +47,26 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { save_in(sess, query_cache_path, "query cache", |e| encode_query_cache(tcx, e)); }); }, - || { + move || { sess.time("incr_comp_persist_dep_graph", || { - save_in(sess, dep_graph_path, "dependency graph", |e| { - sess.time("incr_comp_encode_dep_graph", || encode_dep_graph(tcx, e)) - }); + if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) { + sess.err(&format!( + "failed to write dependency graph to `{}`: {}", + staging_dep_graph_path.display(), + err + )); + } + if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) { + sess.err(&format!( + "failed to move dependency graph from `{}` to `{}`: {}", + staging_dep_graph_path.display(), + dep_graph_path.display(), + err + )); + } }); }, ); - - dirty_clean::check_dirty_clean_annotations(tcx); }) } @@ -92,7 +113,7 @@ pub fn save_work_product_index( }); } -fn save_in(sess: &Session, path_buf: PathBuf, name: &str, encode: F) +pub(crate) fn save_in(sess: &Session, path_buf: PathBuf, name: &str, encode: F) where F: FnOnce(&mut FileEncoder) -> FileEncodeResult, { @@ -144,21 +165,6 @@ where debug!("save: data written to disk successfully"); } -fn encode_dep_graph(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult { - // First encode the commandline arguments hash - tcx.sess.opts.dep_tracking_hash().encode(encoder)?; - - if tcx.sess.opts.debugging_opts.incremental_info { - tcx.dep_graph.print_incremental_info(); - } - - // There is a tiny window between printing the incremental info above and encoding the dep - // graph below in which the dep graph could change, thus making the printed incremental info - // slightly out of date. If this matters to you, please feel free to submit a patch. :) - - tcx.sess.time("incr_comp_encode_serialized_dep_graph", || tcx.dep_graph.encode(encoder)) -} - fn encode_work_product_index( work_products: &FxHashMap, encoder: &mut FileEncoder, @@ -177,3 +183,56 @@ fn encode_work_product_index( fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult { tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder)) } + +pub fn build_dep_graph( + sess: &Session, + prev_graph: PreviousDepGraph, + prev_work_products: FxHashMap, +) -> Option { + if sess.opts.incremental.is_none() { + // No incremental compilation. + return None; + } + + // Stream the dep-graph to an alternate file, to avoid overwriting anything in case of errors. + let path_buf = staging_dep_graph_path(sess); + + let mut encoder = match FileEncoder::new(&path_buf) { + Ok(encoder) => encoder, + Err(err) => { + sess.err(&format!( + "failed to create dependency graph at `{}`: {}", + path_buf.display(), + err + )); + return None; + } + }; + + if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) { + sess.err(&format!( + "failed to write dependency graph header to `{}`: {}", + path_buf.display(), + err + )); + return None; + } + + // First encode the commandline arguments hash + if let Err(err) = sess.opts.dep_tracking_hash(false).encode(&mut encoder) { + sess.err(&format!( + "failed to write dependency graph hash `{}`: {}", + path_buf.display(), + err + )); + return None; + } + + Some(DepGraph::new( + prev_graph, + prev_work_products, + encoder, + sess.opts.debugging_opts.query_dep_graph, + sess.opts.debugging_opts.incremental_info, + )) +} diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index 6e1471df19..4b1f0b8647 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -8,6 +8,6 @@ edition = "2018" doctest = false [dependencies] -arrayvec = { version = "0.5.1", default-features = false } +arrayvec = { version = "0.7", default-features = false } rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 100824f4b9..d26ab1939e 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -356,7 +356,7 @@ where { assert_eq!(out_vec.len(), in_vec.len()); let mut changed = false; - for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) { + for (out_elem, in_elem) in iter::zip(out_vec, in_vec) { let old_val = *out_elem; let new_val = op(old_val, *in_elem); *out_elem = new_val; @@ -375,7 +375,7 @@ const SPARSE_MAX: usize = 8; #[derive(Clone, Debug)] pub struct SparseBitSet { domain_size: usize, - elems: ArrayVec<[T; SPARSE_MAX]>, + elems: ArrayVec, } impl SparseBitSet { @@ -842,7 +842,7 @@ impl BitMatrix { let (write_start, write_end) = self.range(write); let words = &mut self.words[..]; let mut changed = false; - for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) { + for (read_index, write_index) in iter::zip(read_start..read_end, write_start..write_end) { let word = words[write_index]; let new_word = word | words[read_index]; words[write_index] = new_word; @@ -858,7 +858,7 @@ impl BitMatrix { assert_eq!(with.domain_size(), self.num_columns); let (write_start, write_end) = self.range(write); let mut changed = false; - for (read_index, write_index) in (0..with.words().len()).zip(write_start..write_end) { + for (read_index, write_index) in iter::zip(0..with.words().len(), write_start..write_end) { let word = self.words[write_index]; let new_word = word | with.words()[read_index]; self.words[write_index] = new_word; diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 995034e81d..4c73b7bf61 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,7 +1,8 @@ #![feature(allow_internal_unstable)] -#![feature(const_fn)] +#![feature(bench_black_box)] #![feature(const_panic)] #![feature(extend_one)] +#![feature(iter_zip)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 3882818952..1b1a59a254 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -124,7 +124,8 @@ macro_rules! newtype_index { #[inline] $v const fn from_usize(value: usize) -> Self { - assert!(value <= ($max as usize)); + // FIXME: replace with `assert!(value <= ($max as usize));` once `const_panic` is stable + [()][(value > ($max as usize)) as usize]; unsafe { Self::from_u32_unchecked(value as u32) } @@ -132,7 +133,8 @@ macro_rules! newtype_index { #[inline] $v const fn from_u32(value: u32) -> Self { - assert!(value <= $max); + // FIXME: replace with `assert!(value <= $max);` once `const_panic` is stable + [()][(value > $max) as usize]; unsafe { Self::from_u32_unchecked(value) } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index aa4fd055d5..c68705da41 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -293,7 +293,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { self.tcx } - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -621,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { kind: ty::BrAnon(var.as_u32()) }; + let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) }; let region = ty::ReLateBound(self.binder_index, br); self.tcx().mk_region(region) } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 2ec9b9e0be..b8ecc94958 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -27,6 +27,7 @@ use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt}; use std::fmt::Debug; +use std::iter; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// This method is meant to be invoked as the final step of a canonical query @@ -418,7 +419,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // In terms of our example above, we are iterating over pairs like: // [(?A, Vec), ('static, '?1), (?B, ?0)] - for (original_value, result_value) in original_values.var_values.iter().zip(result_values) { + for (original_value, result_value) in iter::zip(&original_values.var_values, result_values) + { match result_value.unpack() { GenericArgKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... @@ -437,7 +439,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); - opt_values[br.assert_bound_var()] = Some(*original_value); + opt_values[br.var] = Some(*original_value); } } GenericArgKind::Const(result_value) => { diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs index 387f480814..553a11d439 100644 --- a/compiler/rustc_infer/src/infer/canonical/substitute.rs +++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs @@ -71,11 +71,10 @@ where if var_values.var_values.is_empty() { value } else { - let fld_r = - |br: ty::BoundRegion| match var_values.var_values[br.assert_bound_var()].unpack() { - GenericArgKind::Lifetime(l) => l, - r => bug!("{:?} is a region but value is {:?}", br, r), - }; + let fld_r = |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() { + GenericArgKind::Lifetime(l) => l, + r => bug!("{:?} is a region but value is {:?}", br, r), + }; let fld_t = |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() { GenericArgKind::Type(ty) => ty, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 5e11932eaf..30214e9420 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -191,7 +191,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { /// /// This also tests if the given const `ct` contains an inference variable which was previously /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct` - /// would result in an infinite type as we continously replace an inference variable + /// would result in an infinite type as we continuously replace an inference variable /// in `ct` with `ct` itself. /// /// This is especially important as unevaluated consts use their parents generics. @@ -543,15 +543,11 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { true } - fn visit_ct_substs(&self) -> bool { - true - } - fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -737,6 +733,16 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + })) + } _ => relate::super_relate_consts(self, c, c), } } @@ -822,10 +828,6 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { true } - fn visit_ct_substs(&self) -> bool { - true - } - fn relate_with_variance>( &mut self, _variance: ty::Variance, @@ -838,9 +840,9 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -959,6 +961,16 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { } } } + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + })) + } _ => relate::super_relate_consts(self, c, c), } } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 7c388b5503..45ba50bb63 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -124,9 +124,9 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index eeff48a639..a91bd9ce2f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -67,13 +67,13 @@ use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, - subst::{Subst, SubstsRef}, + subst::{GenericArgKind, Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::ControlFlow; -use std::{cmp, fmt}; +use std::{cmp, fmt, iter}; mod note; @@ -514,7 +514,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>>, ) -> Result { Err(NonTrivialPath) } @@ -957,33 +957,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> SubstsRef<'tcx> { let generics = self.tcx.generics_of(def_id); let mut num_supplied_defaults = 0; - let mut type_params = generics - .params - .iter() - .rev() - .filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => None, - ty::GenericParamDefKind::Type { has_default, .. } => { - Some((param.def_id, has_default)) - } - ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults) - }) - .peekable(); - let has_default = { - let has_default = type_params.peek().map(|(_, has_default)| has_default); - *has_default.unwrap_or(&false) - }; - if has_default { - let types = substs.types().rev(); - for ((def_id, has_default), actual) in type_params.zip(types) { - if !has_default { - break; + + let default_params = generics.params.iter().rev().filter_map(|param| match param.kind { + ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id), + ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id), + _ => None, + }); + for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) { + match actual.unpack() { + GenericArgKind::Const(c) => { + if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c { + break; + } } - if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { - break; + GenericArgKind::Type(ty) => { + if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty { + break; + } } - num_supplied_defaults += 1; + _ => break, } + num_supplied_defaults += 1; } let len = generics.params.len(); let mut generics = generics.clone(); @@ -1046,7 +1040,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let len1 = sig1.inputs().len(); let len2 = sig2.inputs().len(); if len1 == len2 { - for (i, (l, r)) in sig1.inputs().iter().zip(sig2.inputs().iter()).enumerate() { + for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() { let (x1, x2) = self.cmp(l, r); (values.0).0.extend(x1.0); (values.1).0.extend(x2.0); @@ -1167,12 +1161,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let common_len = cmp::min(len1, len2); let remainder1: Vec<_> = sub1.types().skip(common_len).collect(); let remainder2: Vec<_> = sub2.types().skip(common_len).collect(); - let common_default_params = remainder1 - .iter() - .rev() - .zip(remainder2.iter().rev()) - .filter(|(a, b)| a == b) - .count(); + let common_default_params = + iter::zip(remainder1.iter().rev(), remainder2.iter().rev()) + .filter(|(a, b)| a == b) + .count(); let len = sub1.len() - common_default_params; let consts_offset = len - sub1.consts().count(); @@ -1303,12 +1295,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { const SEPARATOR: &str = "::"; let separator_len = SEPARATOR.len(); - let split_idx: usize = t1_str - .split(SEPARATOR) - .zip(t2_str.split(SEPARATOR)) - .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str) - .map(|(mod_str, _)| mod_str.len() + separator_len) - .sum(); + let split_idx: usize = + iter::zip(t1_str.split(SEPARATOR), t2_str.split(SEPARATOR)) + .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str) + .map(|(mod_str, _)| mod_str.len() + separator_len) + .sum(); debug!( "cmp: separator_len={}, split_idx={}, min_len={}", @@ -1913,7 +1904,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .find_map(|(path, msg)| (&path_str == path).then_some(msg)) { let mut show_suggestion = true; - for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) { + for (exp_ty, found_ty) in + iter::zip(exp_substs.types(), found_substs.types()) + { match *exp_ty.kind() { ty::Ref(_, exp_ty, _) => { match (exp_ty.kind(), found_ty.kind()) { diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index d533e267fd..d9a1193aac 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -287,6 +287,7 @@ pub struct InferenceDiagnosticsData { pub struct InferenceDiagnosticsParentData { pub prefix: &'static str, pub name: String, + pub def_id: DefId, } pub enum UnderspecifiedArgKind { @@ -328,6 +329,7 @@ impl InferenceDiagnosticsParentData { Some(InferenceDiagnosticsParentData { prefix: tcx.def_kind(parent_def_id).descr(parent_def_id), name: parent_name, + def_id: parent_def_id, }) } } @@ -754,12 +756,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let (UnderspecifiedArgKind::Const { .. }, Some(parent_data)) = (&arg_data.kind, &arg_data.parent) { - err.span_suggestion_verbose( - span, - "consider specifying the const argument", - format!("{}::<{}>", parent_data.name, arg_data.name), - Applicability::MaybeIncorrect, - ); + let has_impl_trait = + self.tcx.generics_of(parent_data.def_id).params.iter().any(|param| { + matches!( + param.kind, + ty::GenericParamDefKind::Type { + synthetic: Some( + hir::SyntheticTyParamKind::ImplTrait + | hir::SyntheticTyParamKind::FromAttr, + ), + .. + } + ) + }); + + // (#83606): Do not emit a suggestion if the parent has an `impl Trait` + // as an argument otherwise it will cause the E0282 error. + if !has_impl_trait { + err.span_suggestion_verbose( + span, + "consider specifying the const argument", + format!("{}::<{}>", parent_data.name, arg_data.name), + Applicability::MaybeIncorrect, + ); + } } err.span_label( diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 35b9bc96f1..58eb1e9aa1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -115,7 +115,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // error. We will then search the function parameters for a bound // region at the right depth with the same index ( - Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), + Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)), ty::BrAnon(br_index), ) => { debug!( @@ -143,7 +143,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // error. We will then search the function parameters for a bound // region at the right depth with the same index ( - Some(rl::Region::LateBound(debruijn_index, id, _)), + Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _), ) => { debug!( @@ -162,8 +162,8 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { rl::Region::Static | rl::Region::Free(_, _) | rl::Region::EarlyBound(_, _, _) - | rl::Region::LateBound(_, _, _) - | rl::Region::LateBoundAnon(_, _), + | rl::Region::LateBound(_, _, _, _) + | rl::Region::LateBoundAnon(_, _, _), ) | None, _, @@ -217,7 +217,10 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> { fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { match (self.tcx.named_region(lifetime.hir_id), self.bound_region) { // the lifetime of the TyPath! - (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => { + ( + Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)), + ty::BrAnon(br_index), + ) => { if debruijn_index == self.current_index && anon_index == br_index { self.found_it = true; return; @@ -232,7 +235,7 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> { } } - (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => { + (Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _)) => { debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("id={:?}", id); debug!("def_id={:?}", def_id); @@ -246,8 +249,8 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> { Some( rl::Region::Static | rl::Region::EarlyBound(_, _, _) - | rl::Region::LateBound(_, _, _) - | rl::Region::LateBoundAnon(_, _) + | rl::Region::LateBound(_, _, _, _) + | rl::Region::LateBoundAnon(_, _, _) | rl::Region::Free(_, _), ) | None, diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index ccba904df9..02662043db 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -85,9 +85,9 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index e794903fca..d460222df8 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -11,10 +11,10 @@ use rustc_middle::ty::{self, Binder, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { pub fn higher_ranked_sub( &mut self, - a: Binder, - b: Binder, + a: Binder<'tcx, T>, + b: Binder<'tcx, T>, a_is_expected: bool, - ) -> RelateResult<'tcx, Binder> + ) -> RelateResult<'tcx, Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -50,7 +50,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder::bind(result)) + // We related `a_prime` and `b_prime`, which just had any bound vars + // replaced with placeholders or infer vars, respectively. Relating + // them should not introduce new bound vars. + Ok(ty::Binder::dummy(result)) }) } } @@ -66,7 +69,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// the [rustc dev guide]. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - pub fn replace_bound_vars_with_placeholders(&self, binder: ty::Binder) -> T + pub fn replace_bound_vars_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index 9f43fac091..4fa8f2f1a6 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -85,9 +85,9 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 3df58cb785..eaec6b46bc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -18,7 +18,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; -use rustc_middle::mir; use rustc_middle::mir::interpret::EvalToConstValueResult; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; @@ -1267,15 +1266,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.resolve_vars_if_possible(t).to_string() } - pub fn tys_to_string(&self, ts: &[Ty<'tcx>]) -> String { - let tstrs: Vec = ts.iter().map(|t| self.ty_to_string(*t)).collect(); - format!("({})", tstrs.join(", ")) - } - - pub fn trait_ref_to_string(&self, t: ty::TraitRef<'tcx>) -> String { - self.resolve_vars_if_possible(t).print_only_trait_path().to_string() - } - /// If `TyVar(vid)` resolves to a type, return that type. Else, return the /// universe index of `TyVar(vid)`. pub fn probe_ty_var(&self, vid: TyVid) -> Result, ty::UniverseIndex> { @@ -1416,7 +1406,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, span: Span, lbrct: LateBoundRegionConversionTime, - value: ty::Binder, + value: ty::Binder<'tcx, T>, ) -> (T, BTreeMap>) where T: TypeFoldable<'tcx>, @@ -1499,9 +1489,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn const_eval_resolve( &self, param_env: ty::ParamEnv<'tcx>, - def: ty::WithOptConstParam, - substs: SubstsRef<'tcx>, - promoted: Option, + ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { let mut original_values = OriginalQueryValues::default(); @@ -1510,7 +1498,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let (param_env, substs) = canonical.value; // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. - self.tcx.const_eval_resolve(param_env, def, substs, promoted, span) + self.tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, span) } /// If `typ` is a type variable of some kind, resolve it one level @@ -1707,14 +1695,6 @@ impl<'tcx> TypeTrace<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), values: Consts(ExpectedFound::new(a_is_expected, a, b)) } } - - pub fn dummy(tcx: TyCtxt<'tcx>) -> TypeTrace<'tcx> { - let err = tcx.ty_error(); - TypeTrace { - cause: ObligationCause::dummy(), - values: Types(ExpectedFound { expected: err, found: err }), - } - } } impl<'tcx> SubregionOrigin<'tcx> { diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index e5eb771603..077d2cc20a 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -157,7 +157,7 @@ where fn create_scope( &mut self, - value: ty::Binder>, + value: ty::Binder<'tcx, impl Relate<'tcx>>, universally_quantified: UniversallyQuantified, ) -> BoundRegionScope<'tcx> { let mut scope = BoundRegionScope::default(); @@ -279,7 +279,7 @@ where /// Relate a type inference variable with a value type. This works /// by creating a "generalization" G of the value where all the /// lifetimes are replaced with fresh inference values. This - /// genearlization G becomes the value of the inference variable, + /// generalization G becomes the value of the inference variable, /// and is then related in turn to the value. So e.g. if you had /// `vid = ?0` and `value = &'a u32`, we might first instantiate /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable, @@ -608,9 +608,9 @@ where fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -744,7 +744,7 @@ struct ScopeInstantiator<'me, 'tcx> { impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { fn visit_binder>( &mut self, - t: &ty::Binder, + t: &ty::Binder<'tcx, T>, ) -> ControlFlow { self.target_index.shift_in(1); t.super_visit_with(self); @@ -997,9 +997,9 @@ where fn binders( &mut self, - a: ty::Binder, - _: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + _: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 1a9e20e79f..9e04773c5f 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -92,11 +92,6 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { &self.region_bound_pairs_map } - /// Returns ownership of the `free_region_map`. - pub fn into_free_region_map(self) -> FreeRegionMap<'tcx> { - self.free_region_map - } - /// This is a hack to support the old-skool regionck, which /// processes region constraints from the main function and the /// closure together. In that context, when we enter a closure, we diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 16d86e6243..3e2978fd17 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -186,28 +186,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { } } } - - /// Processes a single ad-hoc region obligation that was not - /// registered in advance. - pub fn type_must_outlive( - &self, - region_bound_pairs: &RegionBoundPairs<'tcx>, - implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, - origin: infer::SubregionOrigin<'tcx>, - ty: Ty<'tcx>, - region: ty::Region<'tcx>, - ) { - let outlives = &mut TypeOutlives::new( - self, - self.tcx, - region_bound_pairs, - implicit_region_bound, - param_env, - ); - let ty = self.resolve_vars_if_possible(ty); - outlives.type_must_outlive(origin, ty, region); - } } /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 2902c41a6b..9ffcddfae9 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -309,31 +309,6 @@ pub struct RegionSnapshot { any_unifications: bool, } -/// When working with placeholder regions, we often wish to find all of -/// the regions that are either reachable from a placeholder region, or -/// which can reach a placeholder region, or both. We call such regions -/// *tainted* regions. This struct allows you to decide what set of -/// tainted regions you want. -#[derive(Debug)] -pub struct TaintDirections { - incoming: bool, - outgoing: bool, -} - -impl TaintDirections { - pub fn incoming() -> Self { - TaintDirections { incoming: true, outgoing: false } - } - - pub fn outgoing() -> Self { - TaintDirections { incoming: false, outgoing: true } - } - - pub fn both() -> Self { - TaintDirections { incoming: true, outgoing: true } - } -} - impl<'tcx> RegionConstraintStorage<'tcx> { pub fn new() -> Self { Self::default() @@ -472,11 +447,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { self.var_infos[vid].universe } - /// Returns the origin for the given variable. - pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { - self.var_infos[vid].origin - } - fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) { // cannot add constraints once regions are resolved debug!("RegionConstraintCollector: add_constraint({:?})", constraint); @@ -795,16 +765,6 @@ impl<'tcx> VerifyBound<'tcx> { VerifyBound::AnyBound(vec![self, vb]) } } - - pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> { - if self.must_hold() && vb.must_hold() { - self - } else if self.cannot_hold() && vb.cannot_hold() { - self - } else { - VerifyBound::AllBounds(vec![self, vb]) - } - } } impl<'tcx> RegionConstraintData<'tcx> { diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index d72be0134f..48b8ee1759 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,5 +1,6 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{FixupError, FixupResult, InferCtxt, Span}; +use rustc_middle::mir; use rustc_middle::ty::fold::{TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; @@ -46,6 +47,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { ct.super_fold_with(self) } } + + fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + constant.super_fold_with(self) + } } /// The opportunistic region resolver opportunistically resolves regions diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 6687198515..bf5f328233 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -162,9 +162,9 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 35b97fff3d..683c1df783 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -146,9 +146,7 @@ impl<'tcx> TypeVariableValue<'tcx> { } } -pub(crate) struct Instantiate { - vid: ty::TyVid, -} +pub(crate) struct Instantiate; pub(crate) struct Delegate; @@ -224,7 +222,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { // Hack: we only need this so that `types_escaping_snapshot` // can see what has been unified; see the Delegate impl for // more details. - self.undo_log.push(Instantiate { vid }); + self.undo_log.push(Instantiate); } /// Creates a new type variable. @@ -346,56 +344,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { ) } - /// Finds the set of type variables that existed *before* `s` - /// but which have only been unified since `s` started, and - /// return the types with which they were unified. So if we had - /// a type variable `V0`, then we started the snapshot, then we - /// created a type variable `V1`, unified `V0` with `T0`, and - /// unified `V1` with `T1`, this function would return `{T0}`. - pub fn types_escaping_snapshot(&mut self, s: &super::Snapshot<'tcx>) -> Vec> { - let mut new_elem_threshold = u32::MAX; - let mut escaping_types = Vec::new(); - let actions_since_snapshot = self.undo_log.actions_since_snapshot(s); - debug!("actions_since_snapshot.len() = {}", actions_since_snapshot.len()); - for i in 0..actions_since_snapshot.len() { - let actions_since_snapshot = self.undo_log.actions_since_snapshot(s); - match actions_since_snapshot[i] { - super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::NewElem(index))) => { - // if any new variables were created during the - // snapshot, remember the lower index (which will - // always be the first one we see). Note that this - // action must precede those variables being - // specified. - new_elem_threshold = cmp::min(new_elem_threshold, index as u32); - debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold); - } - - super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::Other( - Instantiate { vid, .. }, - ))) => { - if vid.index < new_elem_threshold { - // quick check to see if this variable was - // created since the snapshot started or not. - let mut eq_relations = ut::UnificationTable::with_log( - &mut self.storage.eq_relations, - &mut *self.undo_log, - ); - let escaping_type = match eq_relations.probe_value(vid) { - TypeVariableValue::Unknown { .. } => bug!(), - TypeVariableValue::Known { value } => value, - }; - escaping_types.push(escaping_type); - } - debug!("SpecifyVar({:?}) new_elem_threshold={}", vid, new_elem_threshold); - } - - _ => {} - } - } - - escaping_types - } - /// Returns indices of all variables that are not yet /// instantiated. pub fn unsolved_variables(&mut self) -> Vec { diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 4be0e7948f..f41e872e00 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -165,10 +165,6 @@ impl<'tcx> InferCtxtInner<'tcx> { } impl<'tcx> InferCtxtUndoLogs<'tcx> { - pub fn actions_since_snapshot(&self, snapshot: &Snapshot<'tcx>) -> &[UndoLog<'tcx>] { - &self.logs[snapshot.undo_len..] - } - pub fn start_snapshot(&mut self) -> Snapshot<'tcx> { self.num_open_snapshots += 1; Snapshot { undo_len: self.logs.len(), _marker: PhantomData } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index f9170ef5dc..15b4a7ed20 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -2,7 +2,7 @@ //! //! - **Type inference.** The type inference code can be found in the `infer` module; //! this code handles low-level equality and subtyping operations. The -//! type check pass in the compiler is found in the `librustc_typeck` crate. +//! type check pass in the compiler is found in the `rustc_typeck` crate. //! //! For more information about how rustc works, see the [rustc dev guide]. //! @@ -16,11 +16,11 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(extend_one)] +#![feature(iter_zip)] #![feature(never_type)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(in_band_lifetimes)] #![feature(control_flow_enum)] #![recursion_limit = "512"] // For rustdoc diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index ad15af9ab3..0ac4b6b25b 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use rustc_span::{MultiSpan, Span}; use std::fmt; +use std::iter; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_extra_impl_obligation( @@ -94,7 +95,7 @@ pub fn report_object_safety_error( note_span .push_span_label(trait_span, "this trait cannot be made into an object...".to_string()); } - for (span, msg) in multi_span.into_iter().zip(messages.into_iter()) { + for (span, msg) in iter::zip(multi_span, messages) { note_span.push_span_label(span, msg); } err.span_note( diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 0882d682e1..a33234a91f 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -128,7 +128,7 @@ impl<'tcx> FulfillmentError<'tcx> { } impl<'tcx> TraitObligation<'tcx> { - pub fn self_ty(&self) -> ty::Binder> { + pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.predicate.map_bound(|p| p.self_ty()) } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 87684c2715..1cde4802a4 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -305,9 +305,7 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>( Some(assoc_name), )); for (super_predicate, _) in super_predicates.predicates { - let bound_predicate = super_predicate.kind(); - let subst_predicate = super_predicate - .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder())); + let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() { stack.push(binder.value); } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 3bfe8da505..194464dd0b 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -45,7 +45,7 @@ rustc_query_impl = { path = "../rustc_query_impl" } rustc_resolve = { path = "../rustc_resolve" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } -tempfile = "3.0.5" +tempfile = "3.2" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["libloaderapi"] } diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 7fa1a3eb0f..3b852b8ccf 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -1,6 +1,6 @@ //! Throughout the compiler tree, there are several places which want to have //! access to state or queries while being inside crates that are dependencies -//! of librustc_middle. To facilitate this, we have the +//! of `rustc_middle`. To facilitate this, we have the //! `rustc_data_structures::AtomicRef` type, which allows us to setup a global //! static which can then be set in this file at program startup. //! @@ -13,8 +13,8 @@ use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS}; use rustc_middle::ty::tls; use std::fmt; -/// This is a callback from librustc_ast as it cannot access the implicit state -/// in librustc_middle otherwise. +/// This is a callback from `rustc_ast` as it cannot access the implicit state +/// in `rustc_middle` otherwise. fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { tls::with_opt(|tcx| { if let Some(tcx) = tcx { @@ -25,8 +25,8 @@ fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result }) } -/// This is a callback from librustc_ast as it cannot access the implicit state -/// in librustc_middle otherwise. It is used to when diagnostic messages are +/// This is a callback from `rustc_ast` as it cannot access the implicit state +/// in `rustc_middle` otherwise. It is used to when diagnostic messages are /// emitted and stores them in the current query, if there is one. fn track_diagnostic(diagnostic: &Diagnostic) { tls::with_context_opt(|icx| { @@ -39,8 +39,8 @@ fn track_diagnostic(diagnostic: &Diagnostic) { }) } -/// This is a callback from librustc_hir as it cannot access the implicit state -/// in librustc_middle otherwise. +/// This is a callback from `rustc_hir` as it cannot access the implicit state +/// in `rustc_middle` otherwise. fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "DefId({}:{}", def_id.krate, def_id.index.index())?; tls::with_opt(|opt_tcx| { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 94be7a03a9..02e62a2cee 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -15,8 +15,8 @@ use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_hir::Crate; -use rustc_index::vec::IndexVec; use rustc_lint::LintStore; +use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::middle; @@ -788,13 +788,7 @@ pub fn create_global_ctxt<'tcx>( callback(sess, &mut local_providers, &mut extern_providers); } - let queries = { - let crates = resolver_outputs.cstore.crates_untracked(); - let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); - let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); - providers[LOCAL_CRATE] = local_providers; - queries.get_or_init(|| TcxQueries::new(providers, extern_providers)) - }; + let queries = queries.get_or_init(|| TcxQueries::new(local_providers, extern_providers)); let gcx = sess.time("setup_global_ctxt", || { global_ctxt.get_or_init(|| { @@ -838,6 +832,12 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }); sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); + + let cstore = tcx + .cstore_as_any() + .downcast_ref::() + .expect("`tcx.cstore` is not a `CStore`"); + cstore.report_unused_deps(tcx); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { @@ -1028,9 +1028,6 @@ pub fn start_codegen<'tcx>( rustc_symbol_mangling::test::report_symbol_names(tcx); } - tcx.sess.time("assert_dep_graph", || rustc_incremental::assert_dep_graph(tcx)); - tcx.sess.time("serialize_dep_graph", || rustc_incremental::save_dep_graph(tcx)); - info!("Post-codegen\n{:?}", tcx.debug_stats()); if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 9c38d2b91a..bc94fb67ac 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -207,7 +207,13 @@ impl<'tcx> Queries<'tcx> { }) .open(self.session()) }); - DepGraph::new(prev_graph, prev_work_products) + + rustc_incremental::build_dep_graph( + self.session(), + prev_graph, + prev_work_products, + ) + .unwrap_or_else(DepGraph::new_disabled) } }) }) @@ -301,7 +307,7 @@ impl<'tcx> Queries<'tcx> { _ => return, }; - let attrs = &*tcx.get_attrs(def_id.to_def_id()); + let attrs = &*tcx.get_attrs(def_id); let attrs = attrs.iter().filter(|attr| tcx.sess.check_name(attr, sym::rustc_error)); for attr in attrs { match attr.meta_item_list() { @@ -435,6 +441,9 @@ impl Compiler { if self.session().opts.debugging_opts.query_stats { gcx.enter(rustc_query_impl::print_stats); } + + self.session() + .time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); } _timer = Some(self.session().timer("free_global_ctxt")); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 93ba2e6a4f..d8c1a7a268 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -2,12 +2,13 @@ use crate::interface::parse_cfgspecs; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; +use rustc_session::config::InstrumentCoverage; use rustc_session::config::Strip; use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::config::{ - Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel, + Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -17,7 +18,8 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel}; +use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel}; + use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; use std::num::NonZeroUsize; @@ -73,6 +75,27 @@ fn mk_map(entries: Vec<(K, V)>) -> BTreeMap { BTreeMap::from_iter(entries.into_iter()) } +fn assert_same_clone(x: &Options) { + assert_eq!(x.dep_tracking_hash(true), x.clone().dep_tracking_hash(true)); + assert_eq!(x.dep_tracking_hash(false), x.clone().dep_tracking_hash(false)); +} + +fn assert_same_hash(x: &Options, y: &Options) { + assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true)); + assert_eq!(x.dep_tracking_hash(false), y.dep_tracking_hash(false)); + // Check clone + assert_same_clone(x); + assert_same_clone(y); +} + +fn assert_different_hash(x: &Options, y: &Options) { + assert_ne!(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() { @@ -129,14 +152,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!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_different_hash(&v1, &v2); + assert_different_hash(&v1, &v3); + assert_different_hash(&v2, &v3); } #[test] @@ -154,10 +172,7 @@ fn test_output_types_tracking_hash_different_construction_order() { (OutputType::Exe, Some(PathBuf::from("./some/thing"))), ]); - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); } #[test] @@ -181,14 +196,9 @@ fn test_externs_tracking_hash_different_construction_order() { (String::from("d"), new_public_extern_entry(vec!["f", "e"])), ])); - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); + assert_same_hash(&v1, &v3); + assert_same_hash(&v2, &v3); } #[test] @@ -218,14 +228,9 @@ fn test_lints_tracking_hash_different_values() { (String::from("d"), Level::Deny), ]; - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_different_hash(&v1, &v2); + assert_different_hash(&v1, &v3); + assert_different_hash(&v2, &v3); } #[test] @@ -247,11 +252,7 @@ fn test_lints_tracking_hash_different_construction_order() { (String::from("d"), Level::Forbid), ]; - assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); } #[test] @@ -291,15 +292,9 @@ fn test_search_paths_tracking_hash_different_order() { v4.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v4.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON)); - assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); + assert_same_hash(&v1, &v3); + assert_same_hash(&v1, &v4); } #[test] @@ -337,15 +332,9 @@ fn test_native_libs_tracking_hash_different_values() { (String::from("c"), None, NativeLibKind::Unspecified), ]; - assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); - assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash()); + assert_different_hash(&v1, &v2); + assert_different_hash(&v1, &v3); + assert_different_hash(&v1, &v4); } #[test] @@ -373,14 +362,9 @@ fn test_native_libs_tracking_hash_different_order() { (String::from("b"), None, NativeLibKind::Framework), ]; - assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); - assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); - assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash()); - - // Check clone - assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash()); - assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash()); - assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash()); + assert_same_hash(&v1, &v2); + assert_same_hash(&v1, &v3); + assert_same_hash(&v2, &v3); } #[test] @@ -390,8 +374,9 @@ fn test_codegen_options_tracking_hash() { macro_rules! untracked { ($name: ident, $non_default_value: expr) => { + assert_ne!(opts.cg.$name, $non_default_value); opts.cg.$name = $non_default_value; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_same_hash(&reference, &opts); }; } @@ -404,7 +389,6 @@ fn test_codegen_options_tracking_hash() { untracked!(incremental, Some(String::from("abc"))); // `link_arg` is omitted because it just forwards to `link_args`. untracked!(link_args, vec![String::from("abc"), String::from("def")]); - untracked!(link_dead_code, Some(true)); untracked!(link_self_contained, Some(true)); untracked!(linker, Some(PathBuf::from("linker"))); untracked!(linker_flavor, Some(LinkerFlavor::Gcc)); @@ -416,8 +400,9 @@ fn test_codegen_options_tracking_hash() { macro_rules! tracked { ($name: ident, $non_default_value: expr) => { opts = reference.clone(); + assert_ne!(opts.cg.$name, $non_default_value); opts.cg.$name = $non_default_value; - assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_different_hash(&reference, &opts); }; } @@ -432,6 +417,7 @@ fn test_codegen_options_tracking_hash() { tracked!(force_unwind_tables, Some(true)); tracked!(inline_threshold, Some(0xf007ba11)); tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto); + tracked!(link_dead_code, Some(true)); tracked!(llvm_args, vec![String::from("1"), String::from("2")]); tracked!(lto, LtoCli::Fat); tracked!(metadata, vec![String::from("A"), String::from("B")]); @@ -453,6 +439,32 @@ fn test_codegen_options_tracking_hash() { tracked!(target_feature, String::from("all the features, all of them")); } +#[test] +fn test_top_level_options_tracked_no_crate() { + let reference = Options::default(); + let mut opts; + + macro_rules! tracked { + ($name: ident, $non_default_value: expr) => { + opts = reference.clone(); + assert_ne!(opts.$name, $non_default_value); + opts.$name = $non_default_value; + // The crate hash should be the same + assert_eq!(reference.dep_tracking_hash(true), opts.dep_tracking_hash(true)); + // The incremental hash should be different + assert_ne!(reference.dep_tracking_hash(false), opts.dep_tracking_hash(false)); + }; + } + + // Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash. + // This list is in alphabetical order. + tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]); + tracked!( + real_rust_source_base_dir, + Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into()) + ); +} + #[test] fn test_debugging_options_tracking_hash() { let reference = Options::default(); @@ -460,8 +472,9 @@ fn test_debugging_options_tracking_hash() { macro_rules! untracked { ($name: ident, $non_default_value: expr) => { + assert_ne!(opts.debugging_opts.$name, $non_default_value); opts.debugging_opts.$name = $non_default_value; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_same_hash(&reference, &opts); }; } @@ -470,8 +483,7 @@ fn test_debugging_options_tracking_hash() { untracked!(ast_json, true); untracked!(ast_json_noexpand, true); untracked!(borrowck, String::from("other")); - untracked!(borrowck_stats, true); - untracked!(deduplicate_diagnostics, true); + untracked!(deduplicate_diagnostics, false); untracked!(dep_tasks, true); untracked!(dont_buffer_diagnostics, true); untracked!(dump_dep_graph, true); @@ -515,7 +527,7 @@ fn test_debugging_options_tracking_hash() { untracked!(self_profile_events, Some(vec![String::new()])); untracked!(span_debug, true); untracked!(span_free_formats, true); - untracked!(strip, Strip::None); + untracked!(strip, Strip::Debuginfo); untracked!(terminal_width, Some(80)); untracked!(threads, 99); untracked!(time, true); @@ -532,8 +544,9 @@ fn test_debugging_options_tracking_hash() { macro_rules! tracked { ($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_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); + assert_different_hash(&reference, &opts); }; } @@ -560,13 +573,13 @@ fn test_debugging_options_tracking_hash() { tracked!(inline_mir, Some(true)); tracked!(inline_mir_threshold, Some(123)); tracked!(inline_mir_hint_threshold, Some(123)); - tracked!(instrument_coverage, true); + tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(link_only, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_opt_level, Some(4)); - tracked!(mutable_noalias, true); + tracked!(mutable_noalias, Some(true)); tracked!(new_llvm_pass_manager, true); tracked!(no_codegen, true); tracked!(no_generate_arange_section, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 341cfa4790..59488fc80a 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -265,7 +265,7 @@ pub fn get_codegen_backend(sopts: &config::Options) -> Box { let backend = match codegen_name { filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), - codegen_name => get_builtin_codegen_backend(codegen_name), + codegen_name => get_builtin_codegen_backend(&sopts.maybe_sysroot, codegen_name), }; unsafe { @@ -390,15 +390,21 @@ fn sysroot_candidates() -> Vec { } } -pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box { +pub fn get_builtin_codegen_backend( + maybe_sysroot: &Option, + backend_name: &str, +) -> fn() -> Box { match backend_name { #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, - _ => get_codegen_sysroot(backend_name), + _ => get_codegen_sysroot(maybe_sysroot, backend_name), } } -pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box { +pub fn get_codegen_sysroot( + maybe_sysroot: &Option, + backend_name: &str, +) -> fn() -> Box { // For now we only allow this function to be called once as it'll dlopen a // few things, which seems to work best if we only do that once. In // general this assertion never trips due to the once guard in `get_codegen_backend`, @@ -413,8 +419,9 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box fn() -> Box = None; - let expected_name = - format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")); + let expected_names = &[ + format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")), + format!("rustc_codegen_{}", backend_name), + ]; for entry in d.filter_map(|e| e.ok()) { let path = entry.path(); let filename = match path.file_name().and_then(|s| s.to_str()) { @@ -462,7 +471,7 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box bool { return false; } - if attr.is_value_str() { + if attr.value_str().is_some() { return true; } @@ -565,7 +567,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.span, "the", "crate"); + self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.inner, "the", "crate"); for macro_def in krate.exported_macros { let attrs = cx.tcx.hir().attrs(macro_def.hir_id()); @@ -857,11 +859,10 @@ declare_lint! { /// ``` /// /// This syntax is now a hard error in the 2018 edition. In the 2015 - /// edition, this lint is "allow" by default, because the old code is - /// still valid, and warning for all old code can be noisy. This lint + /// edition, this lint is "warn" by default. This lint /// enables the [`cargo fix`] tool with the `--edition` flag to /// automatically transition old code from the 2015 edition to 2018. The - /// tool will switch this lint to "warn" and will automatically apply the + /// tool will run this lint and automatically apply the /// suggested fix from the compiler (which is to add `_` to each /// parameter). This provides a completely automated way to update old /// code for a new edition. See [issue #41686] for more details. @@ -869,7 +870,7 @@ declare_lint! { /// [issue #41686]: https://github.com/rust-lang/rust/issues/41686 /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html pub ANONYMOUS_PARAMETERS, - Allow, + Warn, "detects anonymous parameters", @future_incompatible = FutureIncompatibleInfo { reference: "issue #41686 ", @@ -884,6 +885,10 @@ declare_lint_pass!( impl EarlyLintPass for AnonymousParameters { fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { + if cx.sess.edition() != Edition::Edition2015 { + // This is a hard error in future editions; avoid linting and erroring + return; + } if let ast::AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) = it.kind { for arg in sig.decl.inputs.iter() { if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind { @@ -989,7 +994,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi()))); } - if attrs.peek().map(|next_attr| next_attr.is_doc_comment()).unwrap_or_default() { + if attrs.peek().map_or(false, |next_attr| next_attr.is_doc_comment()) { continue; } @@ -2280,7 +2285,7 @@ declare_lint! { } declare_lint_pass!( - /// Check for used feature gates in `INCOMPLETE_FEATURES` in `librustc_feature/active.rs`. + /// Check for used feature gates in `INCOMPLETE_FEATURES` in `rustc_feature/src/active.rs`. IncompleteFeatures => [INCOMPLETE_FEATURES] ); @@ -2961,3 +2966,88 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { } } } + +declare_lint! { + /// The `deref_nullptr` lint detects when an null pointer is dereferenced, + /// which causes [undefined behavior]. + /// + /// ### Example + /// + /// ```rust,no_run + /// # #![allow(unused)] + /// use std::ptr; + /// unsafe { + /// let x = &*ptr::null::(); + /// let x = ptr::addr_of!(*ptr::null::()); + /// let x = *(0 as *const i32); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Dereferencing a null pointer causes [undefined behavior] even as a place expression, + /// like `&*(0 as *const i32)` or `addr_of!(*(0 as *const i32))`. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + pub DEREF_NULLPTR, + Warn, + "detects when an null pointer is dereferenced" +} + +declare_lint_pass!(DerefNullPtr => [DEREF_NULLPTR]); + +impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { + /// test if expression is a null ptr + fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + match &expr.kind { + rustc_hir::ExprKind::Cast(ref expr, ref ty) => { + if let rustc_hir::TyKind::Ptr(_) = ty.kind { + return is_zero(expr) || is_null_ptr(cx, expr); + } + } + // check for call to `core::ptr::null` or `core::ptr::null_mut` + rustc_hir::ExprKind::Call(ref path, _) => { + if let rustc_hir::ExprKind::Path(ref qpath) = path.kind { + if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() { + return cx.tcx.is_diagnostic_item(sym::ptr_null, def_id) + || cx.tcx.is_diagnostic_item(sym::ptr_null_mut, def_id); + } + } + } + _ => {} + } + false + } + + /// test if expression is the literal `0` + fn is_zero(expr: &hir::Expr<'_>) -> bool { + match &expr.kind { + rustc_hir::ExprKind::Lit(ref lit) => { + if let LitKind::Int(a, _) = lit.node { + return a == 0; + } + } + _ => {} + } + false + } + + if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind { + if let rustc_hir::UnOp::Deref = un_op { + if is_null_ptr(cx, expr_deref) { + cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| { + let mut err = lint.build("dereferencing a null pointer"); + err.span_label( + expr.span, + "this code causes undefined behavior when executed", + ); + err.emit(); + }); + } + } + } + } +} diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index c9de85a2f1..c1d6a4f1de 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -45,6 +45,7 @@ use rustc_target::abi::LayoutOf; use tracing::debug; use std::cell::Cell; +use std::iter; use std::slice; /// Information about the registered lints. @@ -176,6 +177,7 @@ impl LintStore { self.early_passes.push(Box::new(pass)); } + /// Used by clippy. pub fn register_pre_expansion_pass( &mut self, pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync, @@ -707,6 +709,9 @@ pub trait LintContext: Sized { BuiltinLintDiagnostics::ProcMacroBackCompat(note) => { db.note(¬e); } + BuiltinLintDiagnostics::OrPatternsBackCompat(span,suggestion) => { + db.span_suggestion(span, "use pat_param to preserve semantics", suggestion, Applicability::MachineApplicable); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); @@ -861,10 +866,12 @@ impl<'tcx> LateContext<'tcx> { /// // The given `def_id` is that of an `Option` type /// } /// ``` + /// + /// Used by clippy, but should be replaced by diagnostic items eventually. pub fn match_def_path(&self, def_id: DefId, path: &[Symbol]) -> bool { let names = self.get_def_path(def_id); - names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| a == b) + names.len() == path.len() && iter::zip(names, path).all(|(a, &b)| a == b) } /// Gets the absolute path of `def_id` as a vector of `Symbol`. @@ -905,7 +912,7 @@ impl<'tcx> LateContext<'tcx> { fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>>, ) -> Result { Ok(()) } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 647ecad046..54fcaef414 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -109,6 +109,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_anon_const(&mut self, c: &'a ast::AnonConst) { run_early_pass!(self, check_anon_const, c); + self.check_id(c.id); ast_visit::walk_anon_const(self, c); } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index a332c30078..54909381a1 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -236,10 +236,9 @@ impl<'s> LintLevelsBuilder<'s> { Some(lvl) => lvl, }; - let meta = unwrap_or!(attr.meta(), continue); self.sess.mark_attr_used(attr); - let mut metas = unwrap_or!(meta.meta_item_list(), continue); + let mut metas = unwrap_or!(attr.meta_item_list(), continue); if metas.is_empty() { // FIXME (#55112): issue unused-attributes lint for `#[level()]` @@ -255,8 +254,6 @@ impl<'s> LintLevelsBuilder<'s> { ast::MetaItemKind::Word => {} // actual lint names handled later ast::MetaItemKind::NameValue(ref name_value) => { if item.path == sym::reason { - // found reason, reslice meta list to exclude it - metas = &metas[0..metas.len() - 1]; // FIXME (#55112): issue unused-attributes lint if we thereby // don't have any lint names (`#[level(reason = "foo")]`) if let ast::LitKind::Str(rationale, _) = name_value.kind { @@ -275,6 +272,8 @@ impl<'s> LintLevelsBuilder<'s> { .span_label(name_value.span, "reason must be a string literal") .emit(); } + // found reason, reslice meta list to exclude it + metas.pop().unwrap(); } else { bad_attr(item.span) .span_label(item.span, "bad attribute argument") @@ -288,10 +287,10 @@ impl<'s> LintLevelsBuilder<'s> { } for li in metas { - let meta_item = match li.meta_item() { - Some(meta_item) if meta_item.is_word() => meta_item, + let sp = li.span(); + let mut meta_item = match li { + ast::NestedMetaItem::MetaItem(meta_item) if meta_item.is_word() => meta_item, _ => { - let sp = li.span(); let mut err = bad_attr(sp); let mut add_label = true; if let Some(item) = li.meta_item() { @@ -330,15 +329,19 @@ impl<'s> LintLevelsBuilder<'s> { continue; } - Some(tool_ident.name) + Some(meta_item.path.segments.remove(0).ident.name) } else { None }; - let name = meta_item.path.segments.last().expect("empty lint name").ident.name; - let lint_result = store.check_lint_name(&name.as_str(), tool_name); + let name = pprust::path_to_string(&meta_item.path); + let lint_result = store.check_lint_name(&name, tool_name); match &lint_result { CheckLintNameResult::Ok(ids) => { - let src = LintLevelSource::Node(name, li.span(), reason); + let src = LintLevelSource::Node( + meta_item.path.segments.last().expect("empty lint name").ident.name, + sp, + reason, + ); for &id in *ids { self.check_gated_lint(id, attr.span); self.insert_spec(&mut specs, id, (level, src)); @@ -351,7 +354,7 @@ impl<'s> LintLevelsBuilder<'s> { let complete_name = &format!("{}::{}", tool_name.unwrap(), name); let src = LintLevelSource::Node( Symbol::intern(complete_name), - li.span(), + sp, reason, ); for id in ids { @@ -367,7 +370,7 @@ impl<'s> LintLevelsBuilder<'s> { lint, lvl, src, - Some(li.span().into()), + Some(sp.into()), |lint| { let msg = format!( "lint name `{}` is deprecated \ @@ -376,7 +379,7 @@ impl<'s> LintLevelsBuilder<'s> { ); lint.build(&msg) .span_suggestion( - li.span(), + sp, "change it to", new_lint_name.to_string(), Applicability::MachineApplicable, @@ -387,7 +390,7 @@ impl<'s> LintLevelsBuilder<'s> { let src = LintLevelSource::Node( Symbol::intern(&new_lint_name), - li.span(), + sp, reason, ); for id in ids { @@ -414,12 +417,12 @@ impl<'s> LintLevelsBuilder<'s> { lint, renamed_lint_level, src, - Some(li.span().into()), + Some(sp.into()), |lint| { let mut err = lint.build(&msg); if let Some(new_name) = &renamed { err.span_suggestion( - li.span(), + sp, "use the new name", new_name.to_string(), Applicability::MachineApplicable, @@ -433,30 +436,23 @@ impl<'s> LintLevelsBuilder<'s> { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess); - struct_lint_level( - self.sess, - lint, - level, - src, - Some(li.span().into()), - |lint| { - let name = if let Some(tool_name) = tool_name { - format!("{}::{}", tool_name, name) - } else { - name.to_string() - }; - let mut db = lint.build(&format!("unknown lint: `{}`", name)); - if let Some(suggestion) = suggestion { - db.span_suggestion( - li.span(), - "did you mean", - suggestion.to_string(), - Applicability::MachineApplicable, - ); - } - db.emit(); - }, - ); + 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) + } else { + name.to_string() + }; + let mut db = lint.build(&format!("unknown lint: `{}`", name)); + if let Some(suggestion) = suggestion { + db.span_suggestion( + sp, + "did you mean", + suggestion.to_string(), + Applicability::MachineApplicable, + ); + } + db.emit(); + }); } } // If this lint was renamed, apply the new lint instead of ignoring the attribute. @@ -464,15 +460,15 @@ impl<'s> LintLevelsBuilder<'s> { // we don't warn about the name change. if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result { // Ignore any errors or warnings that happen because the new name is inaccurate - if let CheckLintNameResult::Ok(ids) = - store.check_lint_name(&new_name, tool_name) - { - let src = - LintLevelSource::Node(Symbol::intern(&new_name), li.span(), reason); + // 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) { + let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason); for &id in ids { self.check_gated_lint(id, attr.span); self.insert_spec(&mut specs, id, (level, src)); } + } else { + panic!("renamed lint does not exist: {}", new_name); } } } @@ -564,10 +560,6 @@ impl<'s> LintLevelsBuilder<'s> { self.id_to_set.insert(id, self.cur); } - pub fn build(self) -> LintLevelSets { - self.sets - } - pub fn build_map(self) -> LintLevelMap { LintLevelMap { sets: self.sets, id_to_set: self.id_to_set } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4c3dbcabc8..2f46969b02 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -33,9 +33,10 @@ #![feature(box_patterns)] #![feature(crate_visibility_modifier)] #![feature(iter_order_by)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] @@ -205,6 +206,7 @@ macro_rules! late_lint_mod_passes { UnreachablePub: UnreachablePub, ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, InvalidValue: InvalidValue, + DerefNullPtr: DerefNullPtr, ] ); }; @@ -325,6 +327,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { store.register_renamed("exceeding_bitshifts", "arithmetic_overflow"); store.register_renamed("redundant_semicolon", "redundant_semicolons"); store.register_renamed("overlapping_patterns", "overlapping_range_endpoints"); + store.register_renamed("safe_packed_borrows", "unaligned_references"); // 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 diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index a1c7e47e74..301e607fc5 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -10,7 +10,6 @@ declare_lint! { /// /// ```rust,compile_fail /// # #![allow(unused)] - /// #![feature(non_ascii_idents)] /// #![deny(non_ascii_idents)] /// fn main() { /// let föö = 1; @@ -21,14 +20,11 @@ declare_lint! { /// /// ### Explanation /// - /// Currently on stable Rust, identifiers must contain ASCII characters. - /// The [`non_ascii_idents`] nightly-only feature allows identifiers to - /// contain non-ASCII characters. This lint allows projects that wish to - /// retain the limit of only using ASCII characters to switch this lint to - /// "forbid" (for example to ease collaboration or for security reasons). + /// This lint allows projects that wish to retain the limit of only using + /// ASCII characters to switch this lint to "forbid" (for example to ease + /// collaboration or for security reasons). /// See [RFC 2457] for more details. /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html /// [RFC 2457]: https://github.com/rust-lang/rfcs/blob/master/text/2457-non-ascii-idents.md pub NON_ASCII_IDENTS, Allow, @@ -44,7 +40,6 @@ declare_lint! { /// /// ```rust /// # #![allow(unused)] - /// #![feature(non_ascii_idents)] /// const µ: f64 = 0.000001; /// ``` /// @@ -52,10 +47,8 @@ declare_lint! { /// /// ### Explanation /// - /// With the [`non_ascii_idents`] nightly-only feature enabled, - /// identifiers are allowed to use non-ASCII characters. This lint warns - /// about using characters which are not commonly used, and may cause - /// visual confusion. + /// This lint warns about using characters which are not commonly used, and may + /// cause visual confusion. /// /// This lint is triggered by identifiers that contain a codepoint that is /// not part of the set of "Allowed" codepoints as described by [Unicode® @@ -66,7 +59,6 @@ declare_lint! { /// that if you "forbid" this lint that existing code may fail in the /// future. /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html /// [TR39Allowed]: https://www.unicode.org/reports/tr39/#General_Security_Profile pub UNCOMMON_CODEPOINTS, Warn, @@ -81,8 +73,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(non_ascii_idents)] - /// /// // Latin Capital Letter E With Caron /// pub const Ě: i32 = 1; /// // Latin Capital Letter E With Breve @@ -93,10 +83,8 @@ declare_lint! { /// /// ### Explanation /// - /// With the [`non_ascii_idents`] nightly-only feature enabled, - /// identifiers are allowed to use non-ASCII characters. This lint warns - /// when different identifiers may appear visually similar, which can - /// cause confusion. + /// This lint warns when different identifiers may appear visually similar, + /// which can cause confusion. /// /// The confusable detection algorithm is based on [Unicode® Technical /// Standard #39 Unicode Security Mechanisms Section 4 Confusable @@ -110,7 +98,6 @@ declare_lint! { /// Beware that if you "forbid" this lint that existing code may fail in /// the future. /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html /// [TR39Confusable]: https://www.unicode.org/reports/tr39/#Confusable_Detection pub CONFUSABLE_IDENTS, Warn, @@ -127,8 +114,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(non_ascii_idents)] - /// /// // The Japanese katakana character エ can be confused with the Han character å·¥. /// const エ: &'static str = "アイウ"; /// ``` @@ -137,10 +122,8 @@ declare_lint! { /// /// ### Explanation /// - /// With the [`non_ascii_idents`] nightly-only feature enabled, - /// identifiers are allowed to use non-ASCII characters. This lint warns - /// when characters between different scripts may appear visually similar, - /// which can cause confusion. + /// This lint warns when characters between different scripts may appear + /// visually similar, which can cause confusion. /// /// If the crate contains other identifiers in the same script that have /// non-confusable characters, then this lint will *not* be issued. For @@ -152,8 +135,6 @@ declare_lint! { /// Note that the set of confusable characters may change over time. /// Beware that if you "forbid" this lint that existing code may fail in /// the future. - /// - /// [`non_ascii_idents`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/non-ascii-idents.html pub MIXED_SCRIPT_CONFUSABLES, Warn, "detects Unicode scripts whose mixed script confusables codepoints are solely used", diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 2d311cc32f..9c94bab04e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -17,6 +17,7 @@ use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; use std::cmp; +use std::iter; use std::ops::ControlFlow; use tracing::debug; @@ -1255,7 +1256,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(sig); - for (input_ty, input_hir) in sig.inputs().iter().zip(decl.inputs) { + for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false, false); } @@ -1355,10 +1356,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { layout ); - let (largest, slargest, largest_index) = enum_definition - .variants - .iter() - .zip(variants) + let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants) .map(|(variant, variant_layout)| { // Subtract the size of the enum tag. let bytes = variant_layout.size.bytes().saturating_sub(tag_size); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 005c4f9f6e..04e45e2351 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -547,7 +547,7 @@ declare_lint! { /// Also consider if you intended to use an _inner attribute_ (with a `!` /// such as `#![allow(unused)]`) which applies to the item the attribute /// is within, or an _outer attribute_ (without a `!` such as - /// `#[allow(unsued)]`) which applies to the item *following* the + /// `#[allow(unused)]`) which applies to the item *following* the /// attribute. /// /// [attributes]: https://doc.rust-lang.org/reference/attributes.html @@ -1057,6 +1057,7 @@ declare_lint! { /// unsafe { /// let foo = Foo { field1: 0, field2: 0 }; /// let _ = &foo.field1; + /// println!("{}", foo.field1); // An implicit `&` is added here, triggering the lint. /// } /// } /// ``` @@ -1065,20 +1066,20 @@ declare_lint! { /// /// ### Explanation /// - /// Creating a reference to an insufficiently aligned packed field is - /// [undefined behavior] and should be disallowed. - /// - /// This lint is "allow" by default because there is no stable - /// alternative, and it is not yet certain how widespread existing code - /// will trigger this lint. - /// - /// See [issue #27060] for more discussion. + /// Creating a reference to an insufficiently aligned packed field is [undefined behavior] and + /// should be disallowed. Using an `unsafe` block does not change anything about this. Instead, + /// the code should do a copy of the data in the packed field or use raw pointers and unaligned + /// accesses. See [issue #82523] for more information. /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - /// [issue #27060]: https://github.com/rust-lang/rust/issues/27060 + /// [issue #82523]: https://github.com/rust-lang/rust/issues/82523 pub UNALIGNED_REFERENCES, - Allow, + Warn, "detects unaligned references to fields of packed structs", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #82523 ", + edition: None, + }; report_in_external_macro } @@ -1150,49 +1151,6 @@ declare_lint! { "detects attempts to mutate a `const` item", } -declare_lint! { - /// The `safe_packed_borrows` lint detects borrowing a field in the - /// interior of a packed structure with alignment other than 1. - /// - /// ### Example - /// - /// ```rust - /// #[repr(packed)] - /// pub struct Unaligned(pub T); - /// - /// pub struct Foo { - /// start: u8, - /// data: Unaligned, - /// } - /// - /// fn main() { - /// let x = Foo { start: 0, data: Unaligned(1) }; - /// let y = &x.data.0; - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// This type of borrow is unsafe and can cause errors on some platforms - /// and violates some assumptions made by the compiler. This was - /// previously allowed unintentionally. This is a [future-incompatible] - /// lint to transition this to a hard error in the future. See [issue - /// #46043] for more details, including guidance on how to solve the - /// problem. - /// - /// [issue #46043]: https://github.com/rust-lang/rust/issues/46043 - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub SAFE_PACKED_BORROWS, - Warn, - "safe borrows of fields of packed structs were erroneously allowed", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #46043 ", - edition: None, - }; -} - declare_lint! { /// The `patterns_in_fns_without_body` lint detects `mut` identifier /// patterns as a parameter in functions without a body. @@ -1977,7 +1935,7 @@ declare_lint! { Warn, "detects proc macro derives using inaccessible names from parent modules", @future_incompatible = FutureIncompatibleInfo { - reference: "issue #50504 ", + reference: "issue #83583 ", edition: None, }; } @@ -2486,6 +2444,52 @@ declare_lint! { "using only a subset of a register for inline asm inputs", } +declare_lint! { + /// The `bad_asm_style` lint detects the use of the `.intel_syntax` and + /// `.att_syntax` directives. + /// + /// ### Example + /// + /// ```rust,ignore (fails on system llvm) + /// #![feature(asm)] + /// + /// fn main() { + /// #[cfg(target_arch="x86_64")] + /// unsafe { + /// asm!( + /// ".att_syntax", + /// "movl {0}, {0}", in(reg) 0usize + /// ); + /// } + /// } + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead + /// --> test.rs:7:14 + /// | + /// 7 | ".att_syntax", + /// | ^^^^^^^^^^^ + /// 8 | "movq {0}, {0}", out(reg) _, + /// 9 | ); + /// | - help: add option: `, options(att_syntax)` + /// | + /// = note: `#[warn(bad_asm_style)]` on by default + /// ``` + /// + /// ### Explanation + /// + /// On x86, `asm!` uses the intel assembly syntax by default. While this + /// can be switched using assembler directives like `.att_syntax`, using the + /// `att_syntax` option is recommended instead because it will also properly + /// prefix register placeholders with `%` as required by AT&T syntax. + pub BAD_ASM_STYLE, + Warn, + "incorrect use of inline assembly", +} + declare_lint! { /// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe /// functions without an explicit unsafe block. @@ -2518,9 +2522,10 @@ declare_lint! { /// /// The fix to this is to wrap the unsafe code in an `unsafe` block. /// - /// This lint is "allow" by default because it has not yet been - /// stabilized, and is not yet complete. See [RFC #2585] and [issue - /// #71668] for more details + /// This lint is "allow" by default since this will affect a large amount + /// of existing code, and the exact plan for increasing the severity is + /// still being considered. See [RFC #2585] and [issue #71668] for more + /// details. /// /// [`unsafe fn`]: https://doc.rust-lang.org/reference/unsafe-functions.html /// [`unsafe` block]: https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks @@ -2673,7 +2678,7 @@ declare_lint! { /// Statics with an uninhabited type can never be initialized, so they are impossible to define. /// However, this can be side-stepped with an `extern static`, leading to problems later in the /// compiler which assumes that there are no initialized uninhabited places (such as locals or - /// statics). This was accientally allowed, but is being phased out. + /// statics). This was accidentally allowed, but is being phased out. pub UNINHABITED_STATIC, Warn, "uninhabited static", @@ -2872,6 +2877,39 @@ declare_lint! { }; } +declare_lint! { + /// The `large_assignments` lint detects when objects of large + /// types are being moved around. + /// + /// ### Example + /// + /// ```rust,ignore (can crash on some platforms) + /// let x = [0; 50000]; + /// let y = x; + /// ``` + /// + /// produces: + /// + /// ```text + /// warning: moving a large value + /// --> $DIR/move-large.rs:1:3 + /// let y = x; + /// - Copied large value here + /// ``` + /// + /// ### Explanation + /// + /// When using a large type in a plain assignment or in a function + /// argument, idiomatic code can be inefficient. + /// Ideally appropriate optimizations would resolve this, but such + /// optimizations are only done in a best-effort manner. + /// This lint will trigger on all sites of large moves and thus allow the + /// user to resolve them in code. + pub LARGE_ASSIGNMENTS, + Warn, + "detects large moves or copies", +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -2907,7 +2945,6 @@ declare_lint_pass! { RENAMED_AND_REMOVED_LINTS, UNALIGNED_REFERENCES, CONST_ITEM_MUTATION, - SAFE_PACKED_BORROWS, PATTERNS_IN_FNS_WITHOUT_BODY, MISSING_FRAGMENT_SPECIFIER, LATE_BOUND_LIFETIME_ARGUMENTS, @@ -2941,6 +2978,7 @@ declare_lint_pass! { NONTRIVIAL_STRUCTURAL_MATCH, SOFT_UNSTABLE, INLINE_NO_SANITIZE, + BAD_ASM_STYLE, ASM_SUB_REGISTER, UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, @@ -2956,6 +2994,8 @@ declare_lint_pass! { DISJOINT_CAPTURE_DROP_REORDER, LEGACY_DERIVE_HELPERS, PROC_MACRO_BACK_COMPAT, + OR_PATTERNS_BACK_COMPAT, + LARGE_ASSIGNMENTS, ] } @@ -3133,3 +3173,37 @@ declare_lint! { }) }; } + +declare_lint! { + /// The `or_patterns_back_compat` lint detects usage of old versions of or-patterns. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(or_patterns_back_compat)] + /// macro_rules! match_any { + /// ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + /// match $expr { + /// $( + /// $( $pat => $expr_arm, )+ + /// )+ + /// } + /// }; + /// } + /// + /// fn main() { + /// let result: Result = Err(42); + /// let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + /// assert_eq!(int, 42); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In Rust 2021, the pat matcher will match new patterns, which include the | character. + pub OR_PATTERNS_BACK_COMPAT, + Allow, + "detects usage of old versions of or-patterns", +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 400b367095..70475563a4 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -267,6 +267,7 @@ pub enum BuiltinLintDiagnostics { LegacyDeriveHelpers(Span), ExternDepSpec(String, ExternDepSpec), ProcMacroBackCompat(String), + OrPatternsBackCompat(Span, String), } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 621363bed8..301ed639f3 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -88,16 +88,6 @@ fn main() { "riscv", ]; - let mut version_cmd = Command::new(&llvm_config); - version_cmd.arg("--version"); - let version_output = output(&mut version_cmd); - let mut parts = version_output.split('.').take(2).filter_map(|s| s.parse::().ok()); - let (major, _minor) = if let (Some(major), Some(minor)) = (parts.next(), parts.next()) { - (major, minor) - } else { - (8, 0) - }; - let required_components = &[ "ipo", "bitreader", @@ -123,10 +113,6 @@ fn main() { println!("cargo:rustc-cfg=llvm_component=\"{}\"", component); } - if major >= 9 { - println!("cargo:rustc-cfg=llvm_has_msp430_asm_parser"); - } - // Link in our own LLVM shims, compiled with the same flags as LLVM let mut cmd = Command::new(&llvm_config); cmd.arg("--cxxflags"); diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 2797fe8df4..97541e615d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -91,11 +91,7 @@ extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) { extern "C" LLVMRustArchiveIteratorRef LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) { Archive *Archive = RustArchive->getBinary(); -#if LLVM_VERSION_GE(10, 0) std::unique_ptr Err = std::make_unique(Error::success()); -#else - std::unique_ptr Err = llvm::make_unique(Error::success()); -#endif auto Cur = Archive->child_begin(*Err); if (*Err) { LLVMRustSetLastError(toString(std::move(*Err)).c_str()); diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index e97d96e3a4..35cca04b20 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -23,10 +23,17 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( const char* const Filenames[], size_t FilenamesLen, RustStringRef BufferOut) { +#if LLVM_VERSION_GE(13,0) + SmallVector FilenameRefs; + for (size_t i = 0; i < FilenamesLen; i++) { + FilenameRefs.push_back(std::string(Filenames[i])); + } +#else SmallVector FilenameRefs; for (size_t i = 0; i < FilenamesLen; i++) { FilenameRefs.push_back(StringRef(Filenames[i])); } +#endif auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter( makeArrayRef(FilenameRefs)); RawRustStringOstream OS(BufferOut); diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index f67e06706e..0b1b68d83b 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -33,13 +33,6 @@ (LLVM_VERSION_MAJOR > (major) || \ LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor)) -#define LLVM_VERSION_EQ(major, minor) \ - (LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR == (minor)) - -#define LLVM_VERSION_LE(major, minor) \ - (LLVM_VERSION_MAJOR < (major) || \ - LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor)) - #define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor))) #include "llvm/IR/LegacyPassManager.h" diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 51c80cf7df..617b2ed970 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -65,13 +65,9 @@ extern "C" void LLVMInitializePasses() { } extern "C" void LLVMTimeTraceProfilerInitialize() { -#if LLVM_VERSION_GE(10, 0) timeTraceProfilerInitialize( /* TimeTraceGranularity */ 0, /* ProcName */ "rustc"); -#else - timeTraceProfilerInitialize(); -#endif } extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { @@ -408,26 +404,21 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) { printf("\n"); } -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { +extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) { const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); const ArrayRef FeatTable = MCInfo->getFeatureTable(); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable); - - printf("Available features for this target:\n"); - for (auto &Feature : FeatTable) - printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); - printf("\nRust-specific features:\n"); - printf(" %-*s - %s.\n", - MaxFeatLen, - "crt-static", - "Enables libraries with C Run-time Libraries(CRT) to be statically linked" - ); - printf("\n"); + return FeatTable.size(); +} - printf("Use +feature to enable a feature, or -feature to disable it.\n" - "For example, rustc -C -target-cpu=mycpu -C " - "target-feature=+feature1,-feature2\n\n"); +extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index, + const char** Feature, const char** Desc) { + const TargetMachine *Target = unwrap(TM); + const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); + const ArrayRef FeatTable = MCInfo->getFeatureTable(); + const SubtargetFeatureKV Feat = FeatTable[Index]; + *Feature = Feat.Key; + *Desc = Feat.Desc; } #else @@ -436,9 +427,11 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) { printf("Target CPU help is not supported by this LLVM version.\n\n"); } -extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) { - printf("Target features help is not supported by this LLVM version.\n\n"); +extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef) { + return 0; } + +extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef, const char**, const char**) {} #endif extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { @@ -596,7 +589,6 @@ enum class LLVMRustFileType { ObjectFile, }; -#if LLVM_VERSION_GE(10, 0) static CodeGenFileType fromRust(LLVMRustFileType Type) { switch (Type) { case LLVMRustFileType::AssemblyFile: @@ -607,18 +599,6 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) { report_fatal_error("Bad FileType."); } } -#else -static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) { - switch (Type) { - case LLVMRustFileType::AssemblyFile: - return TargetMachine::CGFT_AssemblyFile; - case LLVMRustFileType::ObjectFile: - return TargetMachine::CGFT_ObjectFile; - default: - report_fatal_error("Bad FileType."); - } -} -#endif extern "C" LLVMRustResult LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, @@ -868,13 +848,11 @@ LLVMRustOptimizeWithNewPassManager( } ); #else -#if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back( [Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { MPM.addPass(MemorySanitizerPass(Options)); } ); -#endif OptimizerLastEPCallbacks.push_back( [Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(MemorySanitizerPass(Options)); @@ -892,13 +870,11 @@ LLVMRustOptimizeWithNewPassManager( } ); #else -#if LLVM_VERSION_GE(10, 0) PipelineStartEPCallbacks.push_back( [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { MPM.addPass(ThreadSanitizerPass()); } ); -#endif OptimizerLastEPCallbacks.push_back( [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(ThreadSanitizerPass()); @@ -989,13 +965,11 @@ LLVMRustOptimizeWithNewPassManager( MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); -# if LLVM_VERSION_GE(10, 0) if (PGOOpt) { PB.addPGOInstrPassesForO0( MPM, DebugPassManager, PGOOpt->Action == PGOOptions::IRInstr, /*IsCS=*/false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); } -# endif #endif } else { #if LLVM_VERSION_GE(12, 0) @@ -1366,11 +1340,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, int num_modules, const char **preserved_symbols, int num_symbols) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); -#else - auto Ret = llvm::make_unique(); -#endif // Load each module's summary and merge it into one combined index for (int i = 0; i < num_modules; i++) { @@ -1437,9 +1407,17 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, Ret->ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; }; +#if LLVM_VERSION_GE(13,0) + // Uses FromPrevailing visibility scheme which works for many binary + // formats. We probably could and should use ELF visibility scheme for many of + // our targets, however. + lto::Config conf; + thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage, + Ret->GUIDPreservedSymbols); +#else thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage, Ret->GUIDPreservedSymbols); - +#endif // Here we calculate an `ExportedGUIDs` set for use in the `isExported` // callback below. This callback below will dictate the linkage for all // summaries in the index, and we basically just only want to ensure that dead @@ -1455,7 +1433,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, ExportedGUIDs.insert(GUID); } } -#if LLVM_VERSION_GE(10, 0) auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) { const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); return (ExportList != Ret->ExportLists.end() && @@ -1463,15 +1440,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, ExportedGUIDs.count(VI.getGUID()); }; thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing); -#else - auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { - const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); - return (ExportList != Ret->ExportLists.end() && - ExportList->second.count(GUID)) || - ExportedGUIDs.count(GUID); - }; - thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported); -#endif return Ret.release(); } @@ -1628,11 +1596,7 @@ struct LLVMRustThinLTOBuffer { extern "C" LLVMRustThinLTOBuffer* LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); -#else - auto Ret = llvm::make_unique(); -#endif { raw_string_ostream OS(Ret->data); { diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index a853659540..2e135fbe2b 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -349,8 +349,10 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, F->setAttributes(PALNew); } -// enable fpmath flag UnsafeAlgebra -extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) { +// Enable a fast-math flag +// +// https://llvm.org/docs/LangRef.html#fast-math-flags +extern "C" void LLVMRustSetFastMath(LLVMValueRef V) { if (auto I = dyn_cast(unwrap(V))) { I->setFast(true); } @@ -382,9 +384,18 @@ LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target, LLVMValueRef Old, LLVMValueRef Source, LLVMAtomicOrdering Order, LLVMAtomicOrdering FailureOrder, LLVMBool Weak) { +#if LLVM_VERSION_GE(13,0) + // Rust probably knows the alignment of the target value and should be able to + // specify something more precise than MaybeAlign here. See also + // https://reviews.llvm.org/D97224 which may be a useful reference. + AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( + unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order), + fromRust(FailureOrder)); +#else AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg( unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order), fromRust(FailureOrder)); +#endif ACXI->setWeak(Weak); return wrap(ACXI); } @@ -532,11 +543,6 @@ static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { Result |= DINode::DIFlags::FlagAppleBlock; } -#if LLVM_VERSION_LT(10, 0) - if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) { - Result |= DINode::DIFlags::FlagBlockByrefStruct; - } -#endif if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { Result |= DINode::DIFlags::FlagVirtual; } @@ -901,9 +907,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( unwrapDI(Context), StringRef(Name, NameLen), StringRef(LinkageName, LinkageNameLen), unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, -#if LLVM_VERSION_GE(10, 0) /* isDefined */ true, -#endif InitExpr, unwrapDIPtr(Decl), /* templateParams */ nullptr, AlignInBits); @@ -1090,19 +1094,11 @@ inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **Ptr) { -#if LLVM_VERSION_GE(10, 0) auto NameOrErr = (*unwrap(SI))->getName(); if (!NameOrErr) report_fatal_error(NameOrErr.takeError()); *Ptr = NameOrErr->data(); return NameOrErr->size(); -#else - StringRef Ret; - if (std::error_code EC = (*unwrap(SI))->getName(Ret)) - report_fatal_error(EC.message()); - *Ptr = Ret.data(); - return Ret.size(); -#endif } // LLVMArrayType function does not support 64-bit ElementCount @@ -1304,9 +1300,19 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) +#if LLVM_VERSION_LT(13, 0) +using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy; +#else +using LLVMInlineAsmDiagHandlerTy = void*; +#endif + extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( - LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) { + LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) { + // Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting + // with LLVM 13 this function is gone. +#if LLVM_VERSION_LT(13, 0) unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); +#endif } extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, @@ -1441,47 +1447,28 @@ extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemCpy( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemCpy( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif } extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemMove( unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemMove( - unwrap(Dst), DstAlign, - unwrap(Src), SrcAlign, - unwrap(Size), IsVolatile)); -#endif } extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Val, LLVMValueRef Size, bool IsVolatile) { -#if LLVM_VERSION_GE(10, 0) return wrap(unwrap(B)->CreateMemSet( unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile)); -#else - return wrap(unwrap(B)->CreateMemSet( - unwrap(Dst), unwrap(Val), unwrap(Size), DstAlign, IsVolatile)); -#endif } extern "C" LLVMValueRef @@ -1661,17 +1648,17 @@ extern "C" void LLVMRustSetVisibility(LLVMValueRef V, LLVMSetVisibility(V, fromRust(RustVisibility)); } +extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) { + unwrap(Global)->setDSOLocal(is_dso_local); +} + struct LLVMRustModuleBuffer { std::string data; }; extern "C" LLVMRustModuleBuffer* LLVMRustModuleBufferCreate(LLVMModuleRef M) { -#if LLVM_VERSION_GE(10, 0) auto Ret = std::make_unique(); -#else - auto Ret = llvm::make_unique(); -#endif { raw_string_ostream OS(Ret->data); { diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 592010d78c..555aefb192 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -125,10 +125,7 @@ pub fn initialize_available_targets() { LLVMInitializeMSP430TargetInfo, LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetMC, - LLVMInitializeMSP430AsmPrinter - ); - init_target!( - all(llvm_component = "msp430", llvm_has_msp430_asm_parser), + LLVMInitializeMSP430AsmPrinter, LLVMInitializeMSP430AsmParser ); init_target!( diff --git a/compiler/rustc_macros/src/symbols/tests.rs b/compiler/rustc_macros/src/symbols/tests.rs index 82b4b87697..842d2a9771 100644 --- a/compiler/rustc_macros/src/symbols/tests.rs +++ b/compiler/rustc_macros/src/symbols/tests.rs @@ -43,7 +43,7 @@ fn test_symbols_macro(input: TokenStream, expected_errors: &[&str]) { "Macro generated a different number of errors than expected" ); - for (found_error, &expected_error) in found_errors.iter().zip(expected_errors.iter()) { + for (found_error, &expected_error) in found_errors.iter().zip(expected_errors) { let found_error_str = format!("{}", found_error); assert_eq!(found_error_str, expected_error); } diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 48effed927..29fa0b7006 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -11,7 +11,6 @@ doctest = false libc = "0.2" snap = "1" tracing = "0.1" -memmap2 = "0.2.1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_middle = { path = "../rustc_middle" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b5506acf73..e9ae22f8ce 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -46,6 +46,9 @@ pub struct CStore { /// This map is used to verify we get no hash conflicts between /// `StableCrateId` values. stable_crate_ids: FxHashMap, + + /// Unused externs of the crate + unused_externs: Vec, } pub struct CrateLoader<'a> { @@ -190,6 +193,27 @@ impl CStore { crate fn has_global_allocator(&self) -> bool { self.has_global_allocator } + + pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) { + // We put the check for the option before the lint_level_at_node call + // because the call mutates internal state and introducing it + // leads to some ui tests failing. + if !tcx.sess.opts.json_unused_externs { + return; + } + let level = tcx + .lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID) + .0; + if level != lint::Level::Allow { + let unused_externs = + self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::>(); + let unused_externs = unused_externs.iter().map(String::as_str).collect::>(); + tcx.sess + .parse_sess + .span_diagnostic + .emit_unused_externs(level.as_str(), &unused_externs); + } + } } impl<'a> CrateLoader<'a> { @@ -217,6 +241,7 @@ impl<'a> CrateLoader<'a> { allocator_kind: None, has_global_allocator: false, stable_crate_ids, + unused_externs: Vec::new(), }, used_extern_options: Default::default(), } @@ -350,7 +375,6 @@ impl<'a> CrateLoader<'a> { let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - self.verify_no_symbol_conflicts(&crate_root)?; let private_dep = self.sess.opts.externs.get(&name.as_str()).map_or(false, |e| e.is_private_dep); @@ -358,8 +382,6 @@ impl<'a> CrateLoader<'a> { // Claim this crate number and cache it let cnum = self.cstore.alloc_new_crate_num(); - self.verify_no_stable_crate_id_hash_conflicts(&crate_root, cnum)?; - info!( "register crate `{}` (cnum = {}. private_dep = {})", crate_root.name(), @@ -394,6 +416,14 @@ impl<'a> CrateLoader<'a> { None }; + // Perform some verification *after* resolve_crate_deps() above is + // known to have been successful. It seems that - in error cases - the + // cstore can be in a temporarily invalid state between cnum allocation + // and dependency resolution and the verification code would produce + // ICEs in that case (see #83045). + self.verify_no_symbol_conflicts(&crate_root)?; + self.verify_no_stable_crate_id_hash_conflicts(&crate_root, cnum)?; + let crate_metadata = CrateMetadata::new( self.sess, metadata, @@ -481,8 +511,11 @@ impl<'a> CrateLoader<'a> { if dep.is_none() { self.used_extern_options.insert(name); } - self.maybe_resolve_crate(name, dep_kind, dep) - .unwrap_or_else(|err| err.report(self.sess, span)) + self.maybe_resolve_crate(name, dep_kind, dep).unwrap_or_else(|err| { + let missing_core = + self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); + err.report(&self.sess, span, missing_core) + }) } fn maybe_resolve_crate<'b>( @@ -736,7 +769,7 @@ impl<'a> CrateLoader<'a> { } fn inject_profiler_runtime(&mut self, krate: &ast::Crate) { - if (self.sess.opts.debugging_opts.instrument_coverage + 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 @@ -899,11 +932,17 @@ impl<'a> CrateLoader<'a> { // Don't worry about pathless `--extern foo` sysroot references continue; } - if self.used_extern_options.contains(&Symbol::intern(name)) { + let name_interned = Symbol::intern(name); + if self.used_extern_options.contains(&name_interned) { continue; } // Got a real unused --extern + if self.sess.opts.json_unused_externs { + self.cstore.unused_externs.push(name_interned); + continue; + } + let diag = match self.sess.opts.extern_dep_specs.get(name) { Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()), None => { @@ -936,9 +975,9 @@ impl<'a> CrateLoader<'a> { self.inject_allocator_crate(krate); self.inject_panic_runtime(krate); - info!("{:?}", CrateDump(&self.cstore)); - self.report_unused_deps(krate); + + info!("{:?}", CrateDump(&self.cstore)); } pub fn process_extern_crate( diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 2560cfa746..c4d9e3f77f 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -5,7 +5,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_internals)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] @@ -26,7 +26,6 @@ pub use rmeta::{provide, provide_extern}; mod dependency_format; mod foreign_modules; -mod link_args; mod native_libs; mod rmeta; diff --git a/compiler/rustc_metadata/src/link_args.rs b/compiler/rustc_metadata/src/link_args.rs deleted file mode 100644 index 9e1ac33368..0000000000 --- a/compiler/rustc_metadata/src/link_args.rs +++ /dev/null @@ -1,57 +0,0 @@ -use rustc_hir as hir; -use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_middle::ty::TyCtxt; -use rustc_span::symbol::{sym, Symbol}; -use rustc_target::spec::abi::Abi; - -crate fn collect(tcx: TyCtxt<'_>) -> Vec { - let mut collector = Collector { tcx, args: Vec::new() }; - tcx.hir().krate().visit_all_item_likes(&mut collector); - - for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() { - if attr.has_name(sym::link_args) { - if let Some(linkarg) = attr.value_str() { - collector.add_link_args(linkarg); - } - } - } - - collector.args -} - -struct Collector<'tcx> { - tcx: TyCtxt<'tcx>, - args: Vec, -} - -impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { - fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - let abi = match it.kind { - hir::ItemKind::ForeignMod { abi, .. } => abi, - _ => return, - }; - if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { - return; - } - - // First, add all of the custom #[link_args] attributes - let sess = &self.tcx.sess; - for m in - self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| sess.check_name(a, sym::link_args)) - { - if let Some(linkarg) = m.value_str() { - self.add_link_args(linkarg); - } - } - } - - fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {} - fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {} - fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {} -} - -impl<'tcx> Collector<'tcx> { - fn add_link_args(&mut self, args: Symbol) { - self.args.extend(args.as_str().split(' ').filter(|s| !s.is_empty()).map(|s| s.to_string())) - } -} diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 39a39917f5..6e73609509 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -216,6 +216,7 @@ use crate::creader::Library; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; @@ -232,7 +233,6 @@ use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; use std::io::{Read, Result as IoResult, Write}; -use std::ops::Deref; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; use tracing::{debug, info, warn}; @@ -727,19 +727,6 @@ impl<'a> CrateLocator<'a> { } } -/// A trivial wrapper for `Mmap` that implements `StableDeref`. -struct StableDerefMmap(memmap2::Mmap); - -impl Deref for StableDerefMmap { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - self.0.deref() - } -} - -unsafe impl stable_deref_trait::StableDeref for StableDerefMmap {} - fn get_metadata_section( target: &Target, flavor: CrateFlavor, @@ -779,11 +766,11 @@ fn get_metadata_section( // mmap the file, because only a small fraction of it is read. let file = std::fs::File::open(filename) .map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?; - let mmap = unsafe { memmap2::Mmap::map(&file) }; + let mmap = unsafe { Mmap::map(file) }; let mmap = mmap .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?; - rustc_erase_owner!(OwningRef::new(StableDerefMmap(mmap)).map_owner_box()) + rustc_erase_owner!(OwningRef::new(mmap).map_owner_box()) } }; let blob = MetadataBlob::new(raw_bytes); @@ -803,7 +790,8 @@ pub fn find_plugin_registrar( ) -> (PathBuf, CrateDisambiguator) { match find_plugin_registrar_impl(sess, metadata_loader, name) { Ok(res) => res, - Err(err) => err.report(sess, span), + // `core` is always available if we got as far as loading plugins. + Err(err) => err.report(sess, span, false), } } @@ -896,7 +884,7 @@ crate enum CrateError { } impl CrateError { - crate fn report(self, sess: &Session, span: Span) -> ! { + crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! { let mut err = match self { CrateError::NonAsciiName(crate_name) => sess.struct_span_err( span, @@ -1081,7 +1069,37 @@ impl CrateError { if (crate_name == sym::std || crate_name == sym::core) && locator.triple != TargetTriple::from_triple(config::host_triple()) { - err.note(&format!("the `{}` target may not be installed", locator.triple)); + if missing_core { + err.note(&format!( + "the `{}` target may not be installed", + locator.triple + )); + } else { + err.note(&format!( + "the `{}` target may not support the standard library", + locator.triple + )); + } + if missing_core && std::env::var("RUSTUP_HOME").is_ok() { + err.help(&format!( + "consider downloading the target with `rustup target add {}`", + locator.triple + )); + } + // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. + // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. + // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help. + if !missing_core && span.is_dummy() { + let current_crate = + sess.opts.crate_name.as_deref().unwrap_or(""); + err.note(&format!( + "`std` is required by `{}` because it does not declare `#![no_std]`", + current_crate + )); + } + 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 { err.note(&"the compiler may have been built without the profiler runtime"); } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e9b8388c1c..6671cf6fea 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -7,7 +7,6 @@ use crate::rmeta::*; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell}; @@ -351,12 +350,6 @@ impl<'a, 'tcx> Decodable> for DefIndex { } } -impl<'a, 'tcx> FingerprintDecoder for DecodeContext<'a, 'tcx> { - fn decode_fingerprint(&mut self) -> Result { - Fingerprint::decode_opaque(&mut self.opaque) - } -} - impl<'a, 'tcx> Decodable> for SyntaxContext { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { let cdata = decoder.cdata(); @@ -413,17 +406,17 @@ impl<'a, 'tcx> Decodable> for ExpnId { impl<'a, 'tcx> Decodable> for Span { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { + let ctxt = SyntaxContext::decode(decoder)?; let tag = u8::decode(decoder)?; - if tag == TAG_INVALID_SPAN { - return Ok(DUMMY_SP); + if tag == TAG_PARTIAL_SPAN { + return Ok(DUMMY_SP.with_ctxt(ctxt)); } debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); let lo = BytePos::decode(decoder)?; let len = BytePos::decode(decoder)?; - let ctxt = SyntaxContext::decode(decoder)?; let hi = lo + len; let sess = if let Some(sess) = decoder.sess { @@ -764,6 +757,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { data.paren_sugar, data.has_auto_impl, data.is_marker, + data.skip_array_during_method_dispatch, data.specialization_kind, self.def_path_hash(item_id), ) @@ -774,6 +768,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { false, false, false, + false, ty::trait_def::TraitSpecializationKind::None, self.def_path_hash(item_id), ), @@ -960,6 +955,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) } + fn get_const_param_default( + &self, + tcx: TyCtxt<'tcx>, + id: DefIndex, + ) -> rustc_middle::ty::Const<'tcx> { + self.root.tables.const_defaults.get(self, id).unwrap().decode((self, tcx)) + } + /// Iterates over all the stability attributes in the given crate. fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" @@ -1614,7 +1617,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .map(Path::new) .filter(|_| { // Only spend time on further checks if we have what to translate *to*. - sess.real_rust_source_base_dir.is_some() + sess.opts.real_rust_source_base_dir.is_some() }) .filter(|virtual_dir| { // Don't translate away `/rustc/$hash` if we're still remapping to it, @@ -1626,11 +1629,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { debug!( "try_to_translate_virtual_to_real(name={:?}): \ virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}", - name, virtual_rust_source_base_dir, sess.real_rust_source_base_dir, + name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir, ); if let Some(virtual_dir) = virtual_rust_source_base_dir { - if let Some(real_dir) = &sess.real_rust_source_base_dir { + if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { if let rustc_span::FileName::Real(old_name) = name { if let rustc_span::RealFileName::Named(one_path) = old_name { if let Ok(rest) = one_path.strip_prefix(virtual_dir) { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0f860d11dc..bebee9dac3 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -1,6 +1,5 @@ use crate::creader::{CStore, LoadedMacro}; use crate::foreign_modules; -use crate::link_args; use crate::native_libs; use crate::rmeta::{self, encoder}; @@ -122,6 +121,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) } unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } + const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) } mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } @@ -294,10 +294,6 @@ pub fn provide(providers: &mut Providers) { foreign_modules::collect(tcx).into_iter().map(|m| (m.def_id, m)).collect(); Lrc::new(modules) }, - link_args: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(link_args::collect(tcx)) - }, // Returns a map from a sufficiently visible external item (i.e., an // external item that is visible from at least one local module) to a diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 254954c837..02fa6905a0 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,7 +1,6 @@ use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::*; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator}; @@ -116,6 +115,7 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { emit_f32(f32); emit_char(char); emit_str(&str); + emit_raw_bytes(&[u8]); } } @@ -184,11 +184,48 @@ impl<'a, 'tcx> Encodable> for ExpnId { impl<'a, 'tcx> Encodable> for Span { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { - if *self == rustc_span::DUMMY_SP { - return TAG_INVALID_SPAN.encode(s); + let span = self.data(); + + // Don't serialize any `SyntaxContext`s from a proc-macro crate, + // since we don't load proc-macro dependencies during serialization. + // This means that any hygiene information from macros used *within* + // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro + // definition) will be lost. + // + // This can show up in two ways: + // + // 1. Any hygiene information associated with identifier of + // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost. + // Since proc-macros can only be invoked from a different crate, + // real code should never need to care about this. + // + // 2. Using `Span::def_site` or `Span::mixed_site` will not + // include any hygiene information associated with the definition + // site. This means that a proc-macro cannot emit a `$crate` + // identifier which resolves to one of its dependencies, + // which also should never come up in practice. + // + // Additionally, this affects `Span::parent`, and any other + // span inspection APIs that would otherwise allow traversing + // the `SyntaxContexts` associated with a span. + // + // None of these user-visible effects should result in any + // cross-crate inconsistencies (getting one behavior in the same + // crate, and a different behavior in another crate) due to the + // limited surface that proc-macros can expose. + // + // IMPORTANT: If this is ever changed, be sure to update + // `rustc_span::hygiene::raw_encode_expn_id` to handle + // encoding `ExpnData` for proc-macro crates. + if s.is_proc_macro { + SyntaxContext::root().encode(s)?; + } else { + span.ctxt.encode(s)?; } - let span = self.data(); + if self.is_dummy() { + return TAG_PARTIAL_SPAN.encode(s); + } // The Span infrastructure should make sure that this invariant holds: debug_assert!(span.lo <= span.hi); @@ -203,7 +240,7 @@ impl<'a, 'tcx> Encodable> for Span { if !s.source_file_cache.0.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. - return TAG_INVALID_SPAN.encode(s); + return TAG_PARTIAL_SPAN.encode(s); } let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!"); @@ -259,43 +296,6 @@ impl<'a, 'tcx> Encodable> for Span { let len = hi - lo; len.encode(s)?; - // Don't serialize any `SyntaxContext`s from a proc-macro crate, - // since we don't load proc-macro dependencies during serialization. - // This means that any hygiene information from macros used *within* - // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro - // definition) will be lost. - // - // This can show up in two ways: - // - // 1. Any hygiene information associated with identifier of - // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost. - // Since proc-macros can only be invoked from a different crate, - // real code should never need to care about this. - // - // 2. Using `Span::def_site` or `Span::mixed_site` will not - // include any hygiene information associated with the definition - // site. This means that a proc-macro cannot emit a `$crate` - // identifier which resolves to one of its dependencies, - // which also should never come up in practice. - // - // Additionally, this affects `Span::parent`, and any other - // span inspection APIs that would otherwise allow traversing - // the `SyntaxContexts` associated with a span. - // - // None of these user-visible effects should result in any - // cross-crate inconsistencies (getting one behavior in the same - // crate, and a different behavior in another crate) due to the - // limited surface that proc-macros can expose. - // - // IMPORTANT: If this is ever changed, be sure to update - // `rustc_span::hygiene::raw_encode_expn_id` to handle - // encoding `ExpnData` for proc-macro crates. - if s.is_proc_macro { - SyntaxContext::root().encode(s)?; - } else { - span.ctxt.encode(s)?; - } - if tag == TAG_VALID_SPAN_FOREIGN { // This needs to be two lines to avoid holding the `s.source_file_cache` // while calling `cnum.encode(s)` @@ -307,12 +307,6 @@ impl<'a, 'tcx> Encodable> for Span { } } -impl<'a, 'tcx> FingerprintEncoder for EncodeContext<'a, 'tcx> { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { - self.opaque.encode_fingerprint(f) - } -} - impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = true; @@ -433,7 +427,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); - self.encode_info_for_mod(CRATE_DEF_ID, &krate.item.module); + self.encode_info_for_mod(CRATE_DEF_ID, &krate.item); // Proc-macro crates only export proc-macro items, which are looked // up using `proc_macro_data` @@ -1428,6 +1422,7 @@ impl EncodeContext<'a, 'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, + skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch, specialization_kind: trait_def.specialization_kind, }; @@ -1882,13 +1877,12 @@ impl EncodeContext<'a, 'tcx> { default.is_some(), ); } - GenericParamKind::Const { .. } => { - self.encode_info_for_generic_param( - def_id.to_def_id(), - EntryKind::ConstParam, - true, - ); - // FIXME(const_generics_defaults) + GenericParamKind::Const { ref default, .. } => { + let def_id = def_id.to_def_id(); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); + if default.is_some() { + record!(self.tables.const_defaults[def_id] <- self.tcx.const_param_default(def_id)) + } } } } @@ -2064,10 +2058,10 @@ pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); - encoder.emit_raw_bytes(METADATA_HEADER); + encoder.emit_raw_bytes(METADATA_HEADER).unwrap(); // Will be filled with the root position after encoding everything. - encoder.emit_raw_bytes(&[0, 0, 0, 0]); + encoder.emit_raw_bytes(&[0, 0, 0, 0]).unwrap(); let source_map_files = tcx.sess.source_map().files(); let source_file_cache = (source_map_files[0].clone(), 0); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 610528956d..959aa1719a 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -307,13 +307,14 @@ define_tables! { mir_for_ctfe: Table)>, promoted_mir: Table>)>, mir_abstract_consts: Table])>, + const_defaults: Table>>, unused_generic_params: Table>>, // `def_keys` and `def_path_hashes` represent a lazy version of a // `DefPathTable`. This allows us to avoid deserializing an entire // `DefPathTable` up front, since we may only ever use a few // definitions from any given crate. def_keys: Table>, - def_path_hashes: Table> + def_path_hashes: Table>, } #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)] @@ -384,6 +385,7 @@ struct TraitData { paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + skip_array_during_method_dispatch: bool, specialization_kind: ty::trait_def::TraitSpecializationKind, } @@ -448,4 +450,4 @@ struct GeneratorData<'tcx> { // Tags used for encoding Spans: const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_FOREIGN: u8 = 1; -const TAG_INVALID_SPAN: u8 = 2; +const TAG_PARTIAL_SPAN: u8 = 2; diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 03bd4170ea..62c0ce1584 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -2,6 +2,7 @@ use crate::rmeta::*; use rustc_index::vec::Idx; use rustc_serialize::opaque::Encoder; +use rustc_serialize::Encoder as _; use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; @@ -172,7 +173,7 @@ where pub(crate) fn encode(&self, buf: &mut Encoder) -> Lazy> { let pos = buf.position(); - buf.emit_raw_bytes(&self.bytes); + buf.emit_raw_bytes(&self.bytes).unwrap(); Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), self.bytes.len()) } } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index ba9d0a4073..aa54d1ae7b 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -32,8 +32,8 @@ //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro //! defines the `DepKind` enum. Each `DepKind` has its own parameters that are //! needed at runtime in order to construct a valid `DepNode` fingerprint. -//! However, only `CompileCodegenUnit` is constructed explicitly (with -//! `make_compile_codegen_unit`). +//! However, only `CompileCodegenUnit` and `CompileMonoItem` are constructed +//! explicitly (with `make_compile_codegen_unit` cq `make_compile_mono_item`). //! //! Because the macro sees what parameters a given `DepKind` requires, it can //! "infer" some properties for each kind of `DepNode`: @@ -46,15 +46,17 @@ //! `DefId` it was computed from. In other cases, too much information gets //! lost during fingerprint computation. //! -//! `make_compile_codegen_unit`, together with `DepNode::new()`, ensures that only -//! valid `DepNode` instances can be constructed. For example, the API does not -//! allow for constructing parameterless `DepNode`s with anything other -//! than a zeroed out fingerprint. More generally speaking, it relieves the -//! user of the `DepNode` API of having to know how to compute the expected -//! fingerprint for a given set of node parameters. +//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with +//! `DepNode::new()`, ensures that only valid `DepNode` instances can be +//! constructed. For example, the API does not allow for constructing +//! parameterless `DepNode`s with anything other than a zeroed out fingerprint. +//! More generally speaking, it relieves the user of the `DepNode` API of +//! having to know how to compute the expected fingerprint for a given set of +//! node parameters. //! //! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html +use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; @@ -175,6 +177,14 @@ pub mod dep_kind { can_reconstruct_query_key: || false, }; + pub const CompileMonoItem: DepKindStruct = DepKindStruct { + has_params: true, + is_anon: false, + is_eval_always: false, + + can_reconstruct_query_key: || false, + }; + macro_rules! define_query_dep_kinds { ($( [$($attrs:tt)*] @@ -251,6 +261,10 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below. [] CompileCodegenUnit(Symbol), + + // WARNING: if `MonoItem` is changed, make sure you update `make_compile_mono_item` below. + // Only used by rustc_codegen_cranelift + [] CompileMonoItem(MonoItem), ]); // WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys. @@ -259,6 +273,12 @@ crate fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode { DepNode::construct(tcx, DepKind::CompileCodegenUnit, &name) } +// WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys. +// Be very careful changing this type signature! +crate fn make_compile_mono_item(tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>) -> DepNode { + DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) +} + pub type DepNode = rustc_query_system::dep_graph::DepNode; // We keep a lot of `DepNode`s in memory during compilation. It's not diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index c688b23be1..31bea83295 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -8,18 +8,19 @@ use rustc_session::Session; mod dep_node; pub use rustc_query_system::dep_graph::{ - debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex, - WorkProduct, WorkProductId, + debug::DepNodeFilter, hash_result, DepContext, DepNodeColor, DepNodeIndex, + SerializedDepNodeIndex, WorkProduct, WorkProductId, }; -crate use dep_node::make_compile_codegen_unit; pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; +crate use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery; pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph; pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph; +pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter; impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index a3d891fd1b..57c1b9b82e 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -1,6 +1,6 @@ use crate::arena::Arena; use crate::hir::map::{Entry, HirOwnerData, Map}; -use crate::hir::{Owner, OwnerNodes, ParentedNode}; +use crate::hir::{AttributeMap, Owner, OwnerNodes, ParentedNode}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; use rustc_data_structures::fingerprint::Fingerprint; @@ -9,7 +9,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_INDEX; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{self, DefPathHash}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; @@ -58,18 +58,28 @@ fn insert_vec_map(map: &mut IndexVec>, k: K, v: V fn hash_body( hcx: &mut StableHashingContext<'_>, + def_id: LocalDefId, def_path_hash: DefPathHash, item_like: impl for<'a> HashStable>, + krate: &Crate<'_>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, ) -> Fingerprint { - let hash = { + // Hash of nodes. + let hash: Fingerprint = { let mut stable_hasher = StableHasher::new(); hcx.while_hashing_hir_bodies(true, |hcx| { item_like.hash_stable(hcx, &mut stable_hasher); }); stable_hasher.finish() }; - hir_body_nodes.push((def_path_hash, hash)); + // Hash for crate_hash. + let hash_with_attrs: Fingerprint = { + let mut hasher = StableHasher::new(); + hash.hash_stable(hcx, &mut hasher); + AttributeMap { map: &krate.attrs, prefix: def_id }.hash_stable(hcx, &mut hasher); + hasher.finish() + }; + hir_body_nodes.push((def_path_hash, hash_with_attrs)); hash } @@ -120,7 +130,14 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { attrs: _, } = *krate; - hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes) + hash_body( + &mut hcx, + CRATE_DEF_ID, + root_mod_def_path_hash, + item, + krate, + &mut hir_body_nodes, + ) }; let mut collector = NodeCollector { @@ -186,6 +203,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let crate_hash_input = ( ((node_hashes, upstream_crates), source_file_names), (commandline_args_hash, crate_disambiguator.to_fingerprint()), + &self.krate.non_exported_macro_attrs, ); let mut stable_hasher = StableHasher::new(); @@ -297,7 +315,14 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); + let hash = hash_body( + &mut self.hcx, + dep_node_owner, + def_path_hash, + item_like, + self.krate, + &mut self.hir_body_nodes, + ); self.current_dep_node_owner = dep_node_owner; f(self, hash); @@ -373,26 +398,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_generic_param(&mut self, param: &'hir GenericParam<'hir>) { - if let hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } = param.kind - { - debug_assert_eq!( - param.hir_id.owner, - self.definitions.opt_hir_id_to_local_def_id(param.hir_id).unwrap() - ); - self.with_dep_node_owner(param.hir_id.owner, param, |this, hash| { - this.insert_with_hash(param.span, param.hir_id, Node::GenericParam(param), hash); + self.insert(param.span, param.hir_id, Node::GenericParam(param)); + intravisit::walk_generic_param(self, param); + } - this.with_parent(param.hir_id, |this| { - intravisit::walk_generic_param(this, param); - }); - }); - } else { - self.insert(param.span, param.hir_id, Node::GenericParam(param)); - intravisit::walk_generic_param(self, param); - } + fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) { + self.with_parent(param, |this| intravisit::walk_const_param_default(this, ct)) } fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 9d00f0715a..4cd126988f 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -459,7 +459,7 @@ impl<'hir> Map<'hir> { let hir_id = self.local_def_id_to_hir_id(module); match self.get_entry(hir_id).node { Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id), - Node::Crate(item) => (&item.module, item.span, hir_id), + Node::Crate(item) => (&item, item.inner, hir_id), node => panic!("not a module: {:?}", node), } } @@ -550,24 +550,6 @@ impl<'hir> Map<'hir> { ParentHirIterator { current_id, map: self } } - /// Checks if the node is an argument. An argument is a local variable whose - /// immediate parent is an item or a closure. - pub fn is_argument(&self, id: HirId) -> bool { - match self.find(id) { - Some(Node::Binding(_)) => (), - _ => return false, - } - matches!( - self.find(self.get_parent_node(id)), - Some( - Node::Item(_) - | Node::TraitItem(_) - | Node::ImplItem(_) - | Node::Expr(Expr { kind: ExprKind::Closure(..), .. }), - ) - ) - } - /// Checks if the node is left-hand side of an assignment. pub fn is_lhs(&self, id: HirId) -> bool { match self.find(self.get_parent_node(id)) { @@ -779,17 +761,6 @@ impl<'hir> Map<'hir> { } } - pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData<'hir> { - match self.find(id) { - Some( - Node::Ctor(vd) - | Node::Item(Item { kind: ItemKind::Struct(vd, _) | ItemKind::Union(vd, _), .. }), - ) => vd, - Some(Node::Variant(variant)) => &variant.data, - _ => bug!("expected struct or variant, found {}", self.node_to_string(id)), - } - } - pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> { match self.find(id) { Some(Node::Variant(variant)) => variant, @@ -897,7 +868,7 @@ impl<'hir> Map<'hir> { Node::Visibility(v) => bug!("unexpected Visibility {:?}", v), Node::Local(local) => local.span, Node::MacroDef(macro_def) => macro_def.span, - Node::Crate(item) => item.span, + Node::Crate(item) => item.inner, }; Some(span) } @@ -972,7 +943,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe intravisit::walk_crate(&mut collector, tcx.untracked_crate); let crate_disambiguator = tcx.sess.local_crate_disambiguator(); - let cmdline_args = tcx.sess.opts.dep_tracking_hash(); + let cmdline_args = tcx.sess.opts.dep_tracking_hash(true); collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args) }; diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs index cf29d21927..b2fef731b7 100644 --- a/compiler/rustc_middle/src/ich/hcx.rs +++ b/compiler/rustc_middle/src/ich/hcx.rs @@ -119,11 +119,6 @@ impl<'a> StableHashingContext<'a> { Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans) } - #[inline] - pub fn sess(&self) -> &'a Session { - self.sess - } - #[inline] pub fn while_hashing_hir_bodies(&mut self, hash_bodies: bool, f: F) { let prev_hash_bodies = self.hash_bodies; diff --git a/compiler/rustc_middle/src/ich/impls_syntax.rs b/compiler/rustc_middle/src/ich/impls_syntax.rs index aacec86071..f53992172b 100644 --- a/compiler/rustc_middle/src/ich/impls_syntax.rs +++ b/compiler/rustc_middle/src/ich/impls_syntax.rs @@ -1,5 +1,5 @@ //! This module contains `HashStable` implementations for various data types -//! from librustc_ast in no particular order. +//! from `rustc_ast` in no particular order. use crate::ich::StableHashingContext; diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs index 573b514e84..8e53e4ba94 100644 --- a/compiler/rustc_middle/src/ich/impls_ty.rs +++ b/compiler/rustc_middle/src/ich/impls_ty.rs @@ -70,16 +70,16 @@ impl<'a> HashStable> for ty::RegionKind { ty::ReEmpty(universe) => { universe.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i) }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { db.hash_stable(hcx, hasher); i.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name) }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => { db.hash_stable(hcx, hasher); def_id.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => { db.hash_stable(hcx, hasher); } ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => { @@ -118,12 +118,13 @@ impl<'tcx> HashStable> for ty::BoundVar { } } -impl<'a, T> HashStable> for ty::Binder +impl<'a, 'tcx, T> HashStable> for ty::Binder<'tcx, T> where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.as_ref().skip_binder().hash_stable(hcx, hasher); + self.bound_vars().hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index e106db38b2..5df2f91f09 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -27,6 +27,7 @@ use crate::ty::{self, BoundVar, List, Region, TyCtxt}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; +use std::iter; use std::ops::Index; /// A "canonicalized" type `V` is one where all free inference @@ -227,20 +228,12 @@ impl Certainty { Certainty::Ambiguous => false, } } - - pub fn is_ambiguous(&self) -> bool { - !self.is_proven() - } } impl<'tcx, R> QueryResponse<'tcx, R> { pub fn is_proven(&self) -> bool { self.certainty.is_proven() } - - pub fn is_ambiguous(&self) -> bool { - !self.is_proven() - } } impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> { @@ -284,7 +277,7 @@ impl<'tcx, V> Canonical<'tcx, V> { } pub type QueryOutlivesConstraint<'tcx> = - ty::Binder, Region<'tcx>>>; + ty::Binder<'tcx, ty::OutlivesPredicate, Region<'tcx>>>; TrivialTypeFoldableAndLiftImpls! { for <'tcx> { @@ -315,16 +308,14 @@ impl<'tcx> CanonicalVarValues<'tcx> { use crate::ty::subst::GenericArgKind; CanonicalVarValues { - var_values: self - .var_values - .iter() - .zip(0..) + var_values: iter::zip(&self.var_values, 0..) .map(|(kind, i)| match kind.unpack() { GenericArgKind::Type(..) => { tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() } GenericArgKind::Lifetime(..) => { - let br = ty::BoundRegion { kind: ty::BrAnon(i) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } GenericArgKind::Const(ct) => tcx diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 8318bdefc8..641cf23781 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -97,13 +97,6 @@ impl<'tcx> ConstVariableValue<'tcx> { ConstVariableValue::Known { value } => Some(value), } } - - pub fn is_unknown(&self) -> bool { - match *self { - ConstVariableValue::Unknown { .. } => true, - ConstVariableValue::Known { .. } => false, - } - } } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 49765166c8..2ff271f398 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,8 +28,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(cmp_min_max_by)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(core_intrinsics)] #![feature(discriminant_kind)] @@ -37,7 +35,7 @@ #![feature(extern_types)] #![feature(nll)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(min_specialization)] #![feature(trusted_len)] #![feature(test)] @@ -50,6 +48,7 @@ #![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] +#![feature(iter_zip)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 5f2ffda642..fc3dafe99e 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -1,7 +1,7 @@ use crate::mir::mono::Linkage; use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; -use rustc_session::config::SanitizerSet; use rustc_span::symbol::Symbol; +use rustc_target::spec::SanitizerSet; #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)] pub struct CodegenFnAttrs { @@ -86,6 +86,10 @@ bitflags! { /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a /// function as an entry function from Non-Secure code. const CMSE_NONSECURE_ENTRY = 1 << 14; + /// `#[no_coverage]`: indicates that the function should be ignored by + /// the MIR `InstrumentCoverage` pass and not added to the coverage map + /// during codegen. + const NO_COVERAGE = 1 << 15; } } diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index 61f850c2fc..601198fd0d 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -1,4 +1,8 @@ -//! Registering limits, recursion_limit, type_length_limit and const_eval_limit +//! Registering limits: +//! * recursion_limit, +//! * move_size_limit, +//! * type_length_limit, and +//! * const_eval_limit //! //! There are various parts of the compiler that must impose arbitrary limits //! on how deeply they recurse to prevent stack overflow. Users can override @@ -8,13 +12,14 @@ use crate::bug; use rustc_ast as ast; use rustc_data_structures::sync::OnceCell; -use rustc_session::{Limit, Session}; +use rustc_session::Session; 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); } @@ -22,7 +27,7 @@ pub fn update_limits(sess: &Session, krate: &ast::Crate) { fn update_limit( sess: &Session, krate: &ast::Crate, - limit: &OnceCell, + limit: &OnceCell + std::fmt::Debug>, name: Symbol, default: usize, ) { @@ -34,7 +39,7 @@ fn update_limit( if let Some(s) = attr.value_str() { match s.as_str().parse() { Ok(n) => { - limit.set(Limit::new(n)).unwrap(); + limit.set(From::from(n)).unwrap(); return; } Err(e) => { @@ -63,5 +68,5 @@ fn update_limit( } } } - limit.set(Limit::new(default)).unwrap(); + limit.set(From::from(default)).unwrap(); } diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index eb48198991..f44267a404 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -235,18 +235,6 @@ pub struct ScopeTree { /// escape into 'static and should have no local cleanup scope. rvalue_scopes: FxHashMap>, - /// Encodes the hierarchy of fn bodies. Every fn body (including - /// closures) forms its own distinct region hierarchy, rooted in - /// the block that is the fn body. This map points from the ID of - /// that root block to the ID of the root block for the enclosing - /// fn, if any. Thus the map structures the fn bodies into a - /// hierarchy based on their lexical mapping. This is used to - /// handle the relationships between regions in a fn and in a - /// closure defined by that fn. See the "Modeling closures" - /// section of the README in infer::region_constraints for - /// more details. - closure_tree: FxHashMap, - /// If there are any `yield` nested within a scope, this map /// stores the `Span` of the last one and its index in the /// postorder of the Visitor traversal on the HIR. @@ -356,23 +344,6 @@ impl ScopeTree { self.destruction_scopes.get(&n).cloned() } - /// Records that `sub_closure` is defined within `sup_closure`. These IDs - /// should be the ID of the block that is the fn body, which is - /// also the root of the region hierarchy for that fn. - pub fn record_closure_parent( - &mut self, - sub_closure: hir::ItemLocalId, - sup_closure: hir::ItemLocalId, - ) { - debug!( - "record_closure_parent(sub_closure={:?}, sup_closure={:?})", - sub_closure, sup_closure - ); - assert!(sub_closure != sup_closure); - let previous = self.closure_tree.insert(sub_closure, sup_closure); - assert!(previous.is_none()); - } - pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) { debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.item_local_id()); @@ -430,6 +401,8 @@ impl ScopeTree { /// Returns `true` if `subscope` is equal to or is lexically nested inside `superscope`, and /// `false` otherwise. + /// + /// Used by clippy. pub fn is_subscope_of(&self, subscope: Scope, superscope: Scope) -> bool { let mut s = subscope; debug!("is_subscope_of({:?}, {:?})", subscope, superscope); @@ -472,7 +445,6 @@ impl<'a> HashStable> for ScopeTree { ref var_map, ref destruction_scopes, ref rvalue_scopes, - ref closure_tree, ref yield_in_scope, } = *self; @@ -486,7 +458,6 @@ impl<'a> HashStable> for ScopeTree { var_map.hash_stable(hcx, hasher); destruction_scopes.hash_stable(hcx, hasher); rvalue_scopes.hash_stable(hcx, hasher); - closure_tree.hash_stable(hcx, hasher); yield_in_scope.hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index 1b7d0e620a..aa6488b329 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -39,8 +39,13 @@ impl LifetimeDefOrigin { pub enum Region { Static, EarlyBound(/* index */ u32, /* lifetime decl */ DefId, LifetimeDefOrigin), - LateBound(ty::DebruijnIndex, /* lifetime decl */ DefId, LifetimeDefOrigin), - LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32), + LateBound( + ty::DebruijnIndex, + /* late-bound index */ u32, + /* lifetime decl */ DefId, + LifetimeDefOrigin, + ), + LateBoundAnon(ty::DebruijnIndex, /* late-bound index */ u32, /* anon index */ u32), Free(DefId, /* lifetime decl */ DefId), } @@ -79,8 +84,5 @@ pub struct ResolveLifetimes { /// (b) it DOES appear in the arguments. pub late_bound: FxHashMap>, - /// For each type and trait definition, maps type parameters - /// to the trait object lifetime defaults computed from them. - pub object_lifetime_defaults: - FxHashMap>>, + pub late_bound_vars: FxHashMap>>, } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 89ca8eed39..fc9a2970e0 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -29,12 +29,6 @@ pub enum StabilityLevel { Stable, } -impl StabilityLevel { - pub fn from_attr_level(level: &attr::StabilityLevel) -> Self { - if level.is_stable() { Stable } else { Unstable } - } -} - /// An entry in the `depr_map`. #[derive(Clone, HashStable, Debug)] pub struct DeprecationEntry { diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs index b85f1e6e5d..776a777b1b 100644 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ b/compiler/rustc_middle/src/mir/abstract_const.rs @@ -18,3 +18,20 @@ pub enum Node<'tcx> { UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum NotConstEvaluatable { + Error(rustc_errors::ErrorReported), + MentionsInfer, + MentionsParam, +} + +impl From for NotConstEvaluatable { + fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable { + NotConstEvaluatable::Error(e) + } +} + +TrivialTypeFoldableAndLiftImpls! { + NotConstEvaluatable, +} diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index eae02a8cbf..ddb1a84fe7 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -41,8 +41,16 @@ rustc_index::newtype_index! { } impl CounterValueReference { - // Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO. + /// Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO. pub const START: Self = Self::from_u32(1); + + /// Returns explicitly-requested zero-based version of the counter id, used + /// during codegen. LLVM expects zero-based indexes. + pub fn zero_based_index(&self) -> u32 { + let one_based_index = self.as_u32(); + debug_assert!(one_based_index > 0); + one_based_index - 1 + } } rustc_index::newtype_index! { @@ -117,17 +125,9 @@ impl CoverageKind { } } - pub fn is_counter(&self) -> bool { - matches!(self, Self::Counter { .. }) - } - pub fn is_expression(&self) -> bool { matches!(self, Self::Expression { .. }) } - - pub fn is_unreachable(&self) -> bool { - *self == Self::Unreachable - } } impl Debug for CoverageKind { @@ -183,3 +183,13 @@ pub enum Op { Subtract, Add, } + +impl Op { + pub fn is_add(&self) -> bool { + matches!(self, Self::Add) + } + + pub fn is_subtract(&self) -> bool { + matches!(self, Self::Subtract) + } +} diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index b2b969e9b3..cc0df12743 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -45,8 +45,8 @@ static_assert_size!(InterpErrorInfo<'_>, 8); /// Packages the kind of error we got from the const code interpreter /// up with a Rust-level backtrace of where the error occurred. -/// Thsese should always be constructed by calling `.into()` on -/// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*` +/// These should always be constructed by calling `.into()` on +/// a `InterpError`. In `rustc_mir::interpret`, we have `throw_err_*` /// macros for this. #[derive(Debug)] pub struct InterpErrorInfo<'tcx>(Box>); diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 3e7b93b32a..fa7c0670e8 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -1,7 +1,7 @@ use super::{ErrorHandled, EvalToConstValueResult, GlobalId}; use crate::mir; -use crate::ty::subst::{InternalSubsts, SubstsRef}; +use crate::ty::subst::InternalSubsts; use crate::ty::{self, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_span::Span; @@ -35,14 +35,12 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, - def: ty::WithOptConstParam, - substs: SubstsRef<'tcx>, - promoted: Option, + ct: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) { + match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { - let cid = GlobalId { instance, promoted }; + let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id(param_env, cid, span) } Ok(None) => Err(ErrorHandled::TooGeneric), diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 5172dfd041..888777a941 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -307,16 +307,6 @@ impl<'tcx, Tag> Scalar { .unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits())) } - #[inline] - pub fn from_i8(i: i8) -> Self { - Self::from_int(i, Size::from_bits(8)) - } - - #[inline] - pub fn from_i16(i: i16) -> Self { - Self::from_int(i, Size::from_bits(16)) - } - #[inline] pub fn from_i32(i: i32) -> Self { Self::from_int(i, Size::from_bits(32)) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 90fda9ec91..e22c0b40d5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -12,10 +12,10 @@ use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; +use rustc_hir::{self as hir, HirId}; use rustc_target::abi::{Size, VariantIdx}; use polonius_engine::Atom; @@ -379,24 +379,6 @@ impl<'tcx> Body<'tcx> { } } - /// Returns an iterator over all temporaries. - #[inline] - pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { - (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = Local::new(index); - if self.local_decls[local].is_user_variable() { None } else { Some(local) } - }) - } - - /// Returns an iterator over all user-declared locals. - #[inline] - pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { - (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = Local::new(index); - self.local_decls[local].is_user_variable().then_some(local) - }) - } - /// Returns an iterator over all user-declared mutable locals. #[inline] pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator + 'a { @@ -1231,7 +1213,7 @@ pub enum InlineAsmOperand<'tcx> { out_place: Option>, }, Const { - value: Operand<'tcx>, + value: Box>, }, SymFn { value: Box>, @@ -1500,7 +1482,7 @@ pub enum StatementKind<'tcx> { /// /// Note that this also is emitted for regular `let` bindings to ensure that locals that are /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` - FakeRead(FakeReadCause, Box>), + FakeRead(Box<(FakeReadCause, Place<'tcx>)>), /// Write the discriminant for a variant to the enum Place. SetDiscriminant { place: Box>, variant_index: VariantIdx }, @@ -1537,9 +1519,10 @@ pub enum StatementKind<'tcx> { AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), /// Marks the start of a "coverage region", injected with '-Zinstrument-coverage'. A - /// `CoverageInfo` statement carries metadata about the coverage region, used to inject a coverage - /// map into the binary. The `Counter` kind also generates executable code, to increment a - /// counter varible at runtime, each time the code region is executed. + /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage + /// map into the binary. If `Coverage::kind` is a `Counter`, the statement also generates + /// executable code, to increment a counter variable at runtime, each time the code region is + /// executed. Coverage(Box), /// Denotes a call to the intrinsic function copy_overlapping, where `src_dst` denotes the @@ -1592,7 +1575,12 @@ pub enum FakeReadCause { /// `let x: !; match x {}` doesn't generate any read of x so we need to /// generate a read of x to check that it is initialized and safe. - ForMatchedPlace, + /// + /// If a closure pattern matches a Place starting with an Upvar, then we introduce a + /// FakeRead for that Place outside the closure, in such a case this option would be + /// Some(closure_def_id). + /// Otherwise, the value of the optional DefId will be None. + ForMatchedPlace(Option), /// A fake read of the RefWithinGuard version of a bind-by-value variable /// in a match guard to ensure that it's value hasn't change by the time @@ -1611,7 +1599,12 @@ pub enum FakeReadCause { /// but in some cases it can affect the borrow checker, as in #53695. /// Therefore, we insert a "fake read" here to ensure that we get /// appropriate errors. - ForLet, + /// + /// If a closure pattern matches a Place starting with an Upvar, then we introduce a + /// FakeRead for that Place outside the closure, in such a case this option would be + /// Some(closure_def_id). + /// Otherwise, the value of the optional DefId will be None. + ForLet(Option), /// If we have an index expression like /// @@ -1635,7 +1628,9 @@ impl Debug for Statement<'_> { use self::StatementKind::*; match self.kind { Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv), - FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place), + FakeRead(box (ref cause, ref place)) => { + write!(fmt, "FakeRead({:?}, {:?})", cause, place) + } Retag(ref kind, ref place) => write!( fmt, "Retag({}{:?})", @@ -1953,6 +1948,29 @@ rustc_index::newtype_index! { } } +impl SourceScope { + /// Finds the original HirId this MIR item came from. + /// This is necessary after MIR optimizations, as otherwise we get a HirId + /// from the function that was inlined instead of the function call site. + pub fn lint_root( + self, + source_scopes: &IndexVec>, + ) -> Option { + let mut data = &source_scopes[self]; + // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it + // does not work as I thought it would. Needs more investigation and documentation. + while data.inlined.is_some() { + trace!(?data); + data = &source_scopes[data.parent_scope.unwrap()]; + } + trace!(?data); + match &data.local_data { + ClearCrossCrate::Set(data) => Some(data.lint_root), + ClearCrossCrate::Clear => None, + } + } +} + #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] pub struct SourceScopeData<'tcx> { pub span: Span, @@ -2328,7 +2346,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { CtorKind::Fn => fmt_tuple(fmt, &name), CtorKind::Fictive => { let mut struct_fmt = fmt.debug_struct(&name); - for (field, place) in variant_def.fields.iter().zip(places) { + for (field, place) in iter::zip(&variant_def.fields, places) { struct_fmt.field(&field.ident.as_str(), place); } struct_fmt.finish() @@ -2352,7 +2370,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let mut struct_fmt = fmt.debug_struct(&name); if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in upvars.keys().zip(places) { + for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); struct_fmt.field(&var_name.as_str(), place); } @@ -2371,7 +2389,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let mut struct_fmt = fmt.debug_struct(&name); if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in upvars.keys().zip(places) { + for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); struct_fmt.field(&var_name.as_str(), place); } @@ -2409,7 +2427,8 @@ pub struct Constant<'tcx> { pub literal: ConstantKind<'tcx>, } -#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +#[derive(Lift)] pub enum ConstantKind<'tcx> { /// This constant came from the type system Ty(&'tcx ty::Const<'tcx>), @@ -2708,7 +2727,13 @@ impl<'tcx> Display for Constant<'tcx> { ty::FnDef(..) => {} _ => write!(fmt, "const ")?, } - match self.literal { + Display::fmt(&self.literal, fmt) + } +} + +impl<'tcx> Display for ConstantKind<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + match *self { ConstantKind::Ty(c) => pretty_print_const(c, fmt, true), ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true), } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 6c2468b9ff..77f38e52ad 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -6,7 +6,7 @@ use rustc_data_structures::base_n; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::{HirId, ItemId}; use rustc_session::config::OptLevel; use rustc_span::source_map::Span; @@ -93,7 +93,7 @@ impl<'tcx> MonoItem<'tcx> { // indicator, then we'll be creating a globally shared version. if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator() || !instance.def.generates_cgu_internal_copy(tcx) - || Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id) + || Some(instance.def_id()) == entry_def_id { return InstantiationMode::GloballyShared { may_conflict: false }; } @@ -181,6 +181,11 @@ impl<'tcx> MonoItem<'tcx> { } .map(|hir_id| tcx.hir().span(hir_id)) } + + // Only used by rustc_codegen_cranelift + pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode { + crate::dep_graph::make_compile_mono_item(tcx, self) + } } impl<'a, 'tcx> HashStable> for MonoItem<'tcx> { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index bde4801801..fdd874c6f6 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -19,19 +19,11 @@ use super::{Field, SourceInfo}; #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub enum UnsafetyViolationKind { - /// Only permitted in regular `fn`s, prohibited in `const fn`s. + /// Unsafe operation outside `unsafe`. General, - /// Permitted both in `const fn`s and regular `fn`s. - GeneralAndConstFn, - /// Borrow of packed field. - /// Has to be handled as a lint for backwards compatibility. - BorrowPacked, /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block. /// Has to be handled as a lint for backwards compatibility. UnsafeFn, - /// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block. - /// Has to be handled as a lint for backwards compatibility. - UnsafeFnBorrowPacked, } #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 887dbefa9f..c8db4aeb44 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -67,7 +67,7 @@ impl SwitchTargets { /// /// Note that this may yield 0 elements. Only the `otherwise` branch is mandatory. pub fn iter(&self) -> SwitchTargetsIter<'_> { - SwitchTargetsIter { inner: self.values.iter().zip(self.targets.iter()) } + SwitchTargetsIter { inner: iter::zip(&self.values, &self.targets) } } /// Returns a slice with all possible jump targets (including the fallback target). diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 36e277d1a8..725448584d 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -264,10 +264,6 @@ impl<'a, 'tcx> ReversePostorder<'a, 'tcx> { ReversePostorder { body, blocks, idx: len } } - - pub fn reset(&mut self) { - self.idx = self.blocks.len(); - } } pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorder<'a, 'tcx> { diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index cb59927727..f3124e5bf4 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -348,6 +348,11 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { + #[inline(always)] + fn fold_with>(self, folder: &mut F) -> Self { + folder.fold_mir_const(self) + } + fn super_fold_with>(self, folder: &mut F) -> Self { match self { ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)), diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index be248ccabd..5516a045c1 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -380,7 +380,7 @@ macro_rules! make_mir_visitor { ) => { self.visit_assign(place, rvalue, location); } - StatementKind::FakeRead(_, place) => { + StatementKind::FakeRead(box (_, place)) => { self.visit_place( place, PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), @@ -584,8 +584,7 @@ macro_rules! make_mir_visitor { } => { for op in operands { match op { - InlineAsmOperand::In { value, .. } - | InlineAsmOperand::Const { value } => { + InlineAsmOperand::In { value, .. } => { self.visit_operand(value, location); } InlineAsmOperand::Out { place, .. } => { @@ -607,7 +606,8 @@ macro_rules! make_mir_visitor { ); } } - InlineAsmOperand::SymFn { value } => { + InlineAsmOperand::Const { value } + | InlineAsmOperand::SymFn { value } => { self.visit_constant(value, location); } InlineAsmOperand::SymStatic { def_id: _ } => {} @@ -1247,12 +1247,6 @@ impl PlaceContext { matches!(self, PlaceContext::MutatingUse(..)) } - /// Returns `true` if this place context represents a use that does not change the value. - #[inline] - pub fn is_nonmutating_use(&self) -> bool { - matches!(self, PlaceContext::NonMutatingUse(..)) - } - /// Returns `true` if this place context represents a use. #[inline] pub fn is_use(&self) -> bool { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ae367db019..7e62e10821 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -93,6 +93,12 @@ rustc_queries! { desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) } } + /// Given the def_id of a const-generic parameter, computes the associated default const + /// parameter. e.g. `fn example` called on `N` would return `3`. + query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> { + desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } + } + /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) } @@ -328,7 +334,10 @@ rustc_queries! { /// Returns the name of the file that contains the function body, if instrumented for coverage. query covered_file_name(key: DefId) -> Option { - desc { |tcx| "retrieving the covered file name, if instrumented, for `{}`", tcx.def_path_str(key) } + desc { + |tcx| "retrieving the covered file name, if instrumented, for `{}`", + tcx.def_path_str(key) + } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { key.is_local() } } @@ -336,7 +345,10 @@ rustc_queries! { /// Returns the `CodeRegions` for a function that has instrumented coverage, in case the /// function was optimized out before codegen, and before being added to the Coverage Map. query covered_code_regions(key: DefId) -> Vec<&'tcx mir::coverage::CodeRegion> { - desc { |tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`", tcx.def_path_str(key) } + desc { + |tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`", + tcx.def_path_str(key) + } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { key.is_local() } } @@ -552,7 +564,7 @@ rustc_queries! { } /// Collects the associated items defined on a trait or impl. - query associated_items(key: DefId) -> ty::AssociatedItems<'tcx> { + query associated_items(key: DefId) -> ty::AssocItems<'tcx> { storage(ArenaCacheSelector<'tcx>) desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) } } @@ -993,6 +1005,10 @@ rustc_queries! { query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } } + /// Query backing `TyS::is_unpin`. + query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Unpin`", env.value } + } /// Query backing `TyS::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } @@ -1039,6 +1055,8 @@ rustc_queries! { desc { "checking if the crate is_compiler_builtins" } } query has_global_allocator(_: CrateNum) -> bool { + // This query depends on untracked global state in CStore + eval_always fatal_cycle desc { "checking if the crate has_global_allocator" } } @@ -1176,7 +1194,7 @@ rustc_queries! { /// Identifies the entry-point (e.g., the `main` function) for a given /// crate, returning `None` if there is no entry point (such as for library crates). - query entry_fn(_: CrateNum) -> Option<(LocalDefId, EntryFnType)> { + query entry_fn(_: CrateNum) -> Option<(DefId, EntryFnType)> { desc { "looking up the entry function of a crate" } } query plugin_registrar_fn(_: CrateNum) -> Option { @@ -1237,13 +1255,19 @@ rustc_queries! { desc { |tcx| "native_library_kind({})", tcx.def_path_str(def_id) } } - query link_args(_: CrateNum) -> Lrc> { - eval_always - desc { "looking up link arguments for a crate" } + /// Does lifetime resolution, but does not descend into trait items. This + /// should only be used for resolving lifetimes of on trait definitions, + /// and is used to avoid cycles. Importantly, `resolve_lifetimes` still visits + /// the same lifetimes and is responsible for diagnostics. + /// See `rustc_resolve::late::lifetimes for details. + query resolve_lifetimes_trait_definition(_: LocalDefId) -> ResolveLifetimes { + storage(ArenaCacheSelector<'tcx>) + desc { "resolving lifetimes for a trait definition" } } - - /// Lifetime resolution. See `middle::resolve_lifetimes`. - query resolve_lifetimes(_: CrateNum) -> ResolveLifetimes { + /// Does lifetime resolution on items. Importantly, we can't resolve + /// lifetimes directly on things like trait methods, because of trait params. + /// See `rustc_resolve::late::lifetimes for details. + query resolve_lifetimes(_: LocalDefId) -> ResolveLifetimes { storage(ArenaCacheSelector<'tcx>) desc { "resolving lifetimes" } } @@ -1255,9 +1279,17 @@ rustc_queries! { Option<(LocalDefId, &'tcx FxHashSet)> { desc { "testing if a region is late bound" } } + /// For a given item (like a struct), gets the default lifetimes to be used + /// for each parameter if a trait object were to be passed for that parameter. + /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`. + /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`. query object_lifetime_defaults_map(_: LocalDefId) - -> Option<&'tcx FxHashMap>> { - desc { "looking up lifetime defaults for a region" } + -> Option> { + desc { "looking up lifetime defaults for a region on an item" } + } + query late_bound_vars_map(_: LocalDefId) + -> Option<&'tcx FxHashMap>> { + desc { "looking up late bound vars" } } query visibility(def_id: DefId) -> ty::Visibility { @@ -1451,6 +1483,13 @@ rustc_queries! { desc { "normalizing `{}`", goal.value } } + /// Do not call this query directly: invoke `normalize_erasing_regions` instead. + query normalize_mir_const_after_erasing_regions( + goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> + ) -> mir::ConstantKind<'tcx> { + desc { "normalizing `{}`", goal.value } + } + query implied_outlives_bounds( goal: CanonicalTyGoal<'tcx> ) -> Result< diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 0bd0a701fb..c9b73c6820 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -9,7 +9,7 @@ pub mod specialization_graph; mod structural_impls; use crate::infer::canonical::Canonical; -use crate::mir::interpret::ErrorHandled; +use crate::mir::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; @@ -323,6 +323,9 @@ pub enum ObligationCauseCode<'tcx> { /// #[feature(trivial_bounds)] is not enabled TrivialBound, + + /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` + OpaqueType, } impl ObligationCauseCode<'_> { @@ -341,7 +344,7 @@ impl ObligationCauseCode<'_> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ObligationCauseCode<'_>, 32); +static_assert_size!(ObligationCauseCode<'_>, 40); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum StatementAsExpression { @@ -398,7 +401,7 @@ pub enum SelectionError<'tcx> { ty::error::TypeError<'tcx>, ), TraitNotObjectSafe(DefId), - ConstEvalFailure(ErrorHandled), + NotConstEvaluatable(NotConstEvaluatable), Overflow, } @@ -667,6 +670,9 @@ pub enum ObjectSafetyViolation { /// Associated const. AssocConst(Symbol, Span), + + /// GAT + GAT(Symbol, Span), } impl ObjectSafetyViolation { @@ -712,6 +718,9 @@ impl ObjectSafetyViolation { format!("it contains associated `const` `{}`", name).into() } ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(), + ObjectSafetyViolation::GAT(name, _) => { + format!("it contains the generic associated type `{}`", name).into() + } } } @@ -770,6 +779,7 @@ impl ObjectSafetyViolation { ); } ObjectSafetyViolation::AssocConst(name, _) + | ObjectSafetyViolation::GAT(name, _) | ObjectSafetyViolation::Method(name, ..) => { err.help(&format!("consider moving `{}` to another trait", name)); } @@ -783,6 +793,7 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::SupertraitSelf(spans) | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(), ObjectSafetyViolation::AssocConst(_, span) + | ObjectSafetyViolation::GAT(_, span) | ObjectSafetyViolation::Method(_, _, span) if *span != DUMMY_SP => { diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index f9cadb3bb2..b0ab0c9ae5 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -3,7 +3,7 @@ //! which makes a canonical query by replacing unbound inference //! variables and regions, so that results can be reused more broadly. //! The providers for the queries defined here can be found in -//! `librustc_traits`. +//! `rustc_traits`. use crate::ich::StableHashingContext; use crate::infer::canonical::{Canonical, QueryResponse}; @@ -44,24 +44,12 @@ pub mod type_op { pub b: Ty<'tcx>, } - impl<'tcx> Eq<'tcx> { - pub fn new(a: Ty<'tcx>, b: Ty<'tcx>) -> Self { - Self { a, b } - } - } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] pub struct Subtype<'tcx> { pub sub: Ty<'tcx>, pub sup: Ty<'tcx>, } - impl<'tcx> Subtype<'tcx> { - pub fn new(sub: Ty<'tcx>, sup: Ty<'tcx>) -> Self { - Self { sub, sup } - } - } - #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)] pub struct ProvePredicate<'tcx> { pub predicate: Predicate<'tcx>, diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index a5962e3b3b..8e2c79701a 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -112,9 +112,9 @@ impl TypeRelation<'tcx> for Match<'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index d3770fa416..d005f63ed4 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -96,15 +96,15 @@ impl AssocKind { /// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is /// done only on items with the same name. #[derive(Debug, Clone, PartialEq, HashStable)] -pub struct AssociatedItems<'tcx> { +pub struct AssocItems<'tcx> { pub(super) items: SortedIndexMultiMap, } -impl<'tcx> AssociatedItems<'tcx> { +impl<'tcx> AssocItems<'tcx> { /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order. pub fn new(items_in_def_order: impl IntoIterator) -> Self { let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect(); - AssociatedItems { items } + AssocItems { items } } /// Returns a slice of associated items in the order they were defined. diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index c31a882c27..887a5831cd 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -6,7 +6,6 @@ use crate::ty; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::lang_items::LangItem; use rustc_span::Span; use super::{Ty, TyCtxt}; @@ -113,14 +112,6 @@ impl<'tcx> ClosureKind { // This is the initial value used when doing upvar inference. pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn; - pub fn trait_did(&self, tcx: TyCtxt<'tcx>) -> DefId { - match *self { - ClosureKind::Fn => tcx.require_lang_item(LangItem::Fn, None), - ClosureKind::FnMut => tcx.require_lang_item(LangItem::FnMut, None), - ClosureKind::FnOnce => tcx.require_lang_item(LangItem::FnOnce, None), - } - } - /// Returns `true` if a type that impls this closure kind /// must also implement `other`. pub fn extends(self, other: ty::ClosureKind) -> bool { @@ -169,7 +160,7 @@ impl CapturedPlace<'tcx> { } } - /// Returns the `LocalDefId` of the closure that captureed this Place + /// Returns the `LocalDefId` of the closure that captured this Place pub fn get_closure_local_def_id(&self) -> LocalDefId { match self.place.base { HirPlaceBase::Upvar(upvar_id) => upvar_id.closure_expr_id, @@ -377,12 +368,4 @@ impl BorrowKind { UniqueImmBorrow => hir::Mutability::Mut, } } - - pub fn to_user_str(&self) -> &'static str { - match *self { - MutBorrow => "mutable", - ImmBorrow => "immutable", - UniqueImmBorrow => "uniquely immutable", - } - } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index f796534c2e..d7767dc39c 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -120,8 +120,9 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable for Ty<'tcx> { } } -impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<'tcx, ty::PredicateKind<'tcx>> { fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.bound_vars().encode(e)?; encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands) } } @@ -188,7 +189,7 @@ pub trait TyDecoder<'tcx>: Decoder { } #[inline] -pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( +fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( decoder: &mut D, ) -> Result<&'tcx T, D::Error> where @@ -198,7 +199,7 @@ where } #[inline] -pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( +fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>( decoder: &mut D, ) -> Result<&'tcx [T], D::Error> where @@ -226,18 +227,22 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable for Ty<'tcx> { } } -impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder> { - fn decode(decoder: &mut D) -> Result>, D::Error> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<'tcx, ty::PredicateKind<'tcx>> { + fn decode(decoder: &mut D) -> Result>, D::Error> { + let bound_vars = Decodable::decode(decoder)?; // Handle shorthands first, if we have an usize > 0x80. - Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() { - let pos = decoder.read_usize()?; - assert!(pos >= SHORTHAND_OFFSET); - let shorthand = pos - SHORTHAND_OFFSET; - - decoder.with_position(shorthand, ty::PredicateKind::decode)? - } else { - ty::PredicateKind::decode(decoder)? - })) + Ok(ty::Binder::bind_with_vars( + if decoder.positioned_at_shorthand() { + let pos = decoder.read_usize()?; + assert!(pos >= SHORTHAND_OFFSET); + let shorthand = pos - SHORTHAND_OFFSET; + + decoder.with_position(shorthand, ty::PredicateKind::decode)? + } else { + ty::PredicateKind::decode(decoder)? + }, + bound_vars, + )) } } @@ -319,7 +324,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List> { } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> - for ty::List>> + for ty::List>> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; @@ -379,15 +384,23 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N } } +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List { + fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { + let len = decoder.read_usize()?; + Ok(decoder.tcx().mk_bound_variable_kinds((0..len).map(|_| Decodable::decode(decoder)))?) + } +} + impl_decodable_via_ref! { &'tcx ty::TypeckResults<'tcx>, &'tcx ty::List>, - &'tcx ty::List>>, + &'tcx ty::List>>, &'tcx Allocation, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion + &'tcx mir::coverage::CodeRegion, + &'tcx ty::List } #[macro_export] @@ -472,6 +485,11 @@ macro_rules! implement_ty_decoder { read_str -> Cow<'_, str>; } + #[inline] + fn read_raw_bytes_into(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.opaque.read_raw_bytes_into(bytes) + } + fn error(&mut self, err: &str) -> Self::Error { self.opaque.error(err) } @@ -483,14 +501,16 @@ macro_rules! implement_ty_decoder { macro_rules! impl_binder_encode_decode { ($($t:ty),+ $(,)?) => { $( - impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<$t> { + impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<'tcx, $t> { fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.bound_vars().encode(e)?; self.as_ref().skip_binder().encode(e) } } - impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<$t> { + impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<'tcx, $t> { fn decode(decoder: &mut D) -> Result { - Ok(ty::Binder::bind(Decodable::decode(decoder)?)) + let bound_vars = Decodable::decode(decoder)?; + Ok(ty::Binder::bind_with_vars(Decodable::decode(decoder)?, bound_vars)) } } )* diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 622f8e8ff6..c78151271c 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -5,7 +5,7 @@ use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{ParamEnv, ParamEnvAnd}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; mod int; @@ -98,18 +98,18 @@ impl<'tcx> Const<'tcx> { let name = tcx.hir().name(hir_id); ty::ConstKind::Param(ty::ParamConst::new(index, name)) } - _ => ty::ConstKind::Unevaluated( - def.to_global(), - InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - None, - ), + _ => ty::ConstKind::Unevaluated(ty::Unevaluated { + def: def.to_global(), + substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), + promoted: None, + }), }; tcx.mk_const(ty::Const { val, ty }) } - #[inline] /// Interns the given value as a constant. + #[inline] pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { tcx.mk_const(Self { val: ConstKind::Value(val), ty }) } @@ -202,3 +202,18 @@ impl<'tcx> Const<'tcx> { .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } } + +pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let default_def_id = match tcx.hir().get(hir_id) { + hir::Node::GenericParam(hir::GenericParam { + kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, + .. + }) => tcx.hir().local_def_id(ac.hir_id), + _ => span_bug!( + tcx.def_span(def_id), + "`const_param_default` expected a generic parameter with a constant" + ), + }; + Const::from_anon_const(tcx, default_def_id) +} diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 43e22ce8f8..875d8d00a9 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -12,10 +12,18 @@ use rustc_macros::HashStable; use rustc_target::abi::Size; use super::ScalarInt; +/// An unevaluated, potentially generic, constant. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Hash, HashStable)] +pub struct Unevaluated<'tcx> { + pub def: ty::WithOptConstParam, + pub substs: SubstsRef<'tcx>, + pub promoted: Option, +} /// Represents a constant in Rust. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] -#[derive(HashStable)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Hash, HashStable)] pub enum ConstKind<'tcx> { /// A const generic parameter. Param(ty::ParamConst), @@ -31,7 +39,7 @@ pub enum ConstKind<'tcx> { /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// variants when the code is monomorphic enough for that. - Unevaluated(ty::WithOptConstParam, SubstsRef<'tcx>, Option), + Unevaluated(Unevaluated<'tcx>), /// Used to hold computed value. Value(ConstValue<'tcx>), @@ -102,7 +110,7 @@ impl<'tcx> ConstKind<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option, ErrorReported>> { - if let ConstKind::Unevaluated(def, substs, promoted) = self { + if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self { use crate::mir::interpret::ErrorHandled; // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` @@ -132,7 +140,8 @@ impl<'tcx> ConstKind<'tcx> { let (param_env, substs) = param_env_and_substs.into_parts(); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - match tcx.const_eval_resolve(param_env, def, substs, promoted, None) { + match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None) + { // NOTE(eddyb) `val` contains no lifetimes/types/consts, // and we use the original type, so nothing from `substs` // (which may be identity substs, see above), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41a8bc10c8..b414618f7d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -20,8 +20,8 @@ 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, ParamConst, ParamTy, PolyFnSig, Predicate, - PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, + 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, }; use rustc_ast as ast; @@ -87,7 +87,8 @@ pub struct CtxtInterners<'tcx> { substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind>, - poly_existential_predicates: InternedSet<'tcx, List>>>, + poly_existential_predicates: + InternedSet<'tcx, List>>>, predicate: InternedSet<'tcx, PredicateInner<'tcx>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, @@ -95,6 +96,7 @@ pub struct CtxtInterners<'tcx> { const_: InternedSet<'tcx, Const<'tcx>>, /// Const allocations. allocation: InternedSet<'tcx, Allocation>, + bound_variable_kinds: InternedSet<'tcx, List>, } impl<'tcx> CtxtInterners<'tcx> { @@ -113,6 +115,7 @@ impl<'tcx> CtxtInterners<'tcx> { place_elems: Default::default(), const_: Default::default(), allocation: Default::default(), + bound_variable_kinds: Default::default(), } } @@ -136,7 +139,10 @@ impl<'tcx> CtxtInterners<'tcx> { } #[inline(never)] - fn intern_predicate(&self, kind: Binder>) -> &'tcx PredicateInner<'tcx> { + fn intern_predicate( + &self, + kind: Binder<'tcx, PredicateKind<'tcx>>, + ) -> &'tcx PredicateInner<'tcx> { self.predicate .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_predicate(kind); @@ -449,7 +455,7 @@ pub struct TypeckResults<'tcx> { /// Stores the type, expression, span and optional scope span of all types /// that are live across the yield of this generator (if a generator). - pub generator_interior_types: ty::Binder>>, + pub generator_interior_types: ty::Binder<'tcx, Vec>>, /// We sometimes treat byte string literals (which are of type `&[u8; N]`) /// as `&[u8]`, depending on the pattern in which they are used. @@ -789,7 +795,7 @@ impl CanonicalUserType<'tcx> { return false; } - user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { + iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { GenericArgKind::Type(ty) => match ty.kind() { ty::Bound(debruijn, b) => { @@ -804,7 +810,7 @@ impl CanonicalUserType<'tcx> { ty::ReLateBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(*debruijn, ty::INNERMOST); - cvar == br.assert_bound_var() + cvar == br.var } _ => false, }, @@ -1019,6 +1025,8 @@ pub struct GlobalCtxt<'tcx> { layout_interner: ShardedHashMap<&'tcx Layout, ()>, output_filenames: Arc, + + pub main_def: Option, } impl<'tcx> TyCtxt<'tcx> { @@ -1179,6 +1187,7 @@ impl<'tcx> TyCtxt<'tcx> { const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames.clone()), + main_def: resolutions.main_def, } } @@ -1616,10 +1625,11 @@ nop_lift! {allocation; &'a Allocation => &'tcx Allocation} nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>} nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} -nop_list_lift! {poly_existential_predicates; ty::Binder> => ty::Binder>} +nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} nop_list_lift! {projs; ProjectionKind => ProjectionKind} +nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} @@ -1965,8 +1975,8 @@ impl<'tcx> Hash for Interned<'tcx, PredicateInner<'tcx>> { } } -impl<'tcx> Borrow>> for Interned<'tcx, PredicateInner<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Binder> { +impl<'tcx> Borrow>> for Interned<'tcx, PredicateInner<'tcx>> { + fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } @@ -2072,10 +2082,11 @@ slice_interners!( substs: _intern_substs(GenericArg<'tcx>), canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: - _intern_poly_existential_predicates(ty::Binder>), + _intern_poly_existential_predicates(ty::Binder<'tcx, ExistentialPredicate<'tcx>>), predicates: _intern_predicates(Predicate<'tcx>), projs: _intern_projs(ProjectionKind), place_elems: _intern_place_elems(PlaceElem<'tcx>), + bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind), ); impl<'tcx> TyCtxt<'tcx> { @@ -2158,7 +2169,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_predicate(self, binder: Binder>) -> Predicate<'tcx> { + pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { let inner = self.interners.intern_predicate(binder); Predicate { inner } } @@ -2167,7 +2178,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn reuse_or_mk_predicate( self, pred: Predicate<'tcx>, - binder: Binder>, + binder: Binder<'tcx, PredicateKind<'tcx>>, ) -> Predicate<'tcx> { if pred.kind() != binder { self.mk_predicate(binder) } else { pred } } @@ -2221,7 +2232,7 @@ impl<'tcx> TyCtxt<'tcx> { let adt_def = self.adt_def(wrapper_def_id); let substs = InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => bug!(), + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), GenericParamDefKind::Type { has_default, .. } => { if param.index == 0 { ty_param.into() @@ -2288,11 +2299,6 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not }) } - #[inline] - pub fn mk_nil_ptr(self) -> Ty<'tcx> { - self.mk_imm_ptr(self.mk_unit()) - } - #[inline] pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { self.mk_ty(Array(ty, ty::Const::from_usize(self, n))) @@ -2339,7 +2345,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_dynamic( self, - obj: &'tcx List>>, + obj: &'tcx List>>, reg: ty::Region<'tcx>, ) -> Ty<'tcx> { self.mk_ty(Dynamic(obj, reg)) @@ -2366,7 +2372,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List>>) -> Ty<'tcx> { + pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List>>) -> Ty<'tcx> { self.mk_ty(GeneratorWitness(types)) } @@ -2416,7 +2422,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into() } GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into() } } @@ -2471,8 +2477,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn intern_poly_existential_predicates( self, - eps: &[ty::Binder>], - ) -> &'tcx List>> { + eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>], + ) -> &'tcx List>> { assert!(!eps.is_empty()); assert!( eps.array_windows() @@ -2517,6 +2523,13 @@ impl<'tcx> TyCtxt<'tcx> { if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) } } + pub fn intern_bound_variable_kinds( + self, + ts: &[ty::BoundVariableKind], + ) -> &'tcx List { + if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) } + } + pub fn mk_fn_sig( self, inputs: I, @@ -2538,8 +2551,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_poly_existential_predicates< I: InternAs< - [ty::Binder>], - &'tcx List>>, + [ty::Binder<'tcx, ExistentialPredicate<'tcx>>], + &'tcx List>>, >, >( self, @@ -2577,6 +2590,15 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned())) } + pub fn mk_bound_variable_kinds< + I: InternAs<[ty::BoundVariableKind], &'tcx List>, + >( + self, + iter: I, + ) -> I::Output { + iter.intern_with(|xs| self.intern_bound_variable_kinds(xs)) + } + /// Walks upwards from `id` to find a node which might change lint levels with attributes. /// It stops at `bound` and just returns it if reached. pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { @@ -2641,6 +2663,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn named_region(self, id: HirId) -> Option { + debug!(?id, "named_region"); self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) } @@ -2649,9 +2672,19 @@ impl<'tcx> TyCtxt<'tcx> { .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id)) } - pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> { + pub fn object_lifetime_defaults(self, id: HirId) -> Option> { self.object_lifetime_defaults_map(id.owner) - .and_then(|map| map.get(&id.local_id).map(|v| &**v)) + } + + pub fn late_bound_vars(self, id: HirId) -> &'tcx List { + self.mk_bound_variable_kinds( + self.late_bound_vars_map(id.owner) + .and_then(|map| map.get(&id.local_id).cloned()) + .unwrap_or_else(|| { + bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id) + }) + .iter(), + ) } } diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 4412ba9408..759d1a017a 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -1,3 +1,4 @@ +use crate::mir; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::{self, Ty, TyCtxt, TypeFlags}; @@ -43,7 +44,7 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } } - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -65,4 +66,8 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { _ => self.tcx.lifetimes.re_erased, } } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + c.super_fold_with(self) + } } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index f19cc99844..008e6d015e 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -36,6 +36,7 @@ pub enum TypeError<'tcx> { UnsafetyMismatch(ExpectedFound), AbiMismatch(ExpectedFound), Mutability, + ArgumentMutability(usize), TupleSize(ExpectedFound), FixedArraySize(ExpectedFound), ArgCount, @@ -46,6 +47,7 @@ pub enum TypeError<'tcx> { RegionsPlaceholderMismatch, Sorts(ExpectedFound>), + ArgumentSorts(ExpectedFound>, usize), IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), Traits(ExpectedFound), @@ -57,7 +59,9 @@ pub enum TypeError<'tcx> { CyclicTy(Ty<'tcx>), CyclicConst(&'tcx ty::Const<'tcx>), ProjectionMismatched(ExpectedFound), - ExistentialMismatch(ExpectedFound<&'tcx ty::List>>>), + ExistentialMismatch( + ExpectedFound<&'tcx ty::List>>>, + ), ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), @@ -108,7 +112,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { AbiMismatch(values) => { write!(f, "expected {} fn, found {} fn", values.expected, values.found) } - Mutability => write!(f, "types differ in mutability"), + ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"), TupleSize(values) => write!( f, "expected a tuple with {} element{}, \ @@ -140,7 +144,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { br_string(br) ), RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"), - Sorts(values) => ty::tls::with(|tcx| { + ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| { report_maybe_different( f, &values.expected.sort_string(tcx), @@ -197,10 +201,11 @@ impl<'tcx> TypeError<'tcx> { use self::TypeError::*; match self { CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | Mismatch | AbiMismatch(_) - | FixedArraySize(_) | Sorts(_) | IntMismatch(_) | FloatMismatch(_) - | VariadicMismatch(_) | TargetFeatureCast(_) => false, + | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) + | FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false, Mutability + | ArgumentMutability(_) | TupleSize(_) | ArgCount | RegionsDoesNotOutlive(..) @@ -337,7 +342,7 @@ impl<'tcx> TyCtxt<'tcx> { use self::TypeError::*; debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause); match err { - Sorts(values) => { + ArgumentSorts(values, _) | Sorts(values) => { match (values.expected.kind(), values.found.kind()) { (ty::Closure(..), ty::Closure(..)) => { db.note("no two closures, even if identical, have the same type"); @@ -509,13 +514,18 @@ impl Trait for X { "consider constraining the associated type `{}` to `{}`", values.found, values.expected, ); - if !self.suggest_constraint( + if !(self.suggest_constraining_opaque_associated_type( + db, + &msg, + proj_ty, + values.expected, + ) || self.suggest_constraint( db, &msg, body_owner_def_id, proj_ty, values.expected, - ) { + )) { db.help(&msg); db.note( "for more information, visit \ @@ -699,20 +709,7 @@ impl Trait for X { } } - if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { - // When the expected `impl Trait` is not defined in the current item, it will come from - // a return type. This can occur when dealing with `TryStream` (#71035). - if self.constrain_associated_type_structured_suggestion( - db, - self.def_span(def_id), - &assoc, - proj_ty.trait_ref_and_own_substs(self).1, - values.found, - &msg, - ) { - return; - } - } + self.suggest_constraining_opaque_associated_type(db, &msg, proj_ty, values.found); if self.point_at_associated_type(db, body_owner_def_id, values.found) { return; @@ -750,6 +747,30 @@ fn foo(&self) -> Self::T { String::new() } } } + /// When the expected `impl Trait` is not defined in the current item, it will come from + /// a return type. This can occur when dealing with `TryStream` (#71035). + fn suggest_constraining_opaque_associated_type( + self, + db: &mut DiagnosticBuilder<'_>, + msg: &str, + proj_ty: &ty::ProjectionTy<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + let assoc = self.associated_item(proj_ty.item_def_id); + if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { + self.constrain_associated_type_structured_suggestion( + db, + self.def_span(def_id), + &assoc, + proj_ty.trait_ref_and_own_substs(self).1, + ty, + &msg, + ) + } else { + false + } + } + fn point_at_methods_that_satisfy_associated_type( self, db: &mut DiagnosticBuilder<'_>, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 6ecd1ebf37..92288c8982 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -22,7 +22,7 @@ impl FlagComputation { result } - pub fn for_predicate(binder: ty::Binder>) -> FlagComputation { + pub fn for_predicate(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_predicate(binder); result @@ -53,12 +53,16 @@ impl FlagComputation { /// Adds the flags/depth from a set of types that appear within the current type, but within a /// region binder. - fn bound_computation(&mut self, value: ty::Binder, f: F) + fn bound_computation(&mut self, value: ty::Binder<'_, T>, f: F) where F: FnOnce(&mut Self, T), { let mut computation = FlagComputation::new(); + if !value.bound_vars().is_empty() { + computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND; + } + f(&mut computation, value.skip_binder()); self.add_flags(computation.flags); @@ -204,7 +208,7 @@ impl FlagComputation { } } - fn add_predicate(&mut self, binder: ty::Binder>) { + fn add_predicate(&mut self, binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) { self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); } @@ -270,10 +274,7 @@ impl FlagComputation { fn add_const(&mut self, c: &ty::Const<'_>) { self.add_ty(c.ty); match c.val { - ty::ConstKind::Unevaluated(_, substs, _) => { - self.add_substs(substs); - self.add_flags(TypeFlags::HAS_CT_PROJECTION); - } + ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated), ty::ConstKind::Infer(infer) => { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { @@ -297,6 +298,11 @@ impl FlagComputation { } } + fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) { + self.add_substs(ct.substs); + self.add_flags(TypeFlags::HAS_CT_PROJECTION); + } + fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); self.add_ty(projection.ty); diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index a6a1d1f73b..eb6d163312 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -30,11 +30,13 @@ //! //! These methods return true to indicate that the visitor has found what it is //! looking for, and does not need to visit anything else. +use crate::mir; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sso::SsoHashSet; use std::collections::BTreeMap; use std::fmt; use std::ops::ControlFlow; @@ -42,7 +44,7 @@ use std::ops::ControlFlow; /// This trait is implemented for every type that can be folded. /// Basically, every type that has a corresponding method in `TypeFolder`. /// -/// To implement this conveniently, use the derive macro located in librustc_macros. +/// To implement this conveniently, use the derive macro located in `rustc_macros`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn super_fold_with>(self, folder: &mut F) -> Self; fn fold_with>(self, folder: &mut F) -> Self { @@ -161,7 +163,7 @@ impl TypeFoldable<'tcx> for hir::Constness { pub trait TypeFolder<'tcx>: Sized { fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; - fn fold_binder(&mut self, t: Binder) -> Binder + fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -179,12 +181,19 @@ pub trait TypeFolder<'tcx>: Sized { fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { c.super_fold_with(self) } + + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + bug!("most type folders should not be folding MIR datastructures: {:?}", c) + } } pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { t.super_visit_with(self) } @@ -322,7 +331,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_binder>( &mut self, - t: &Binder, + t: &Binder<'tcx, T>, ) -> ControlFlow { self.outer_index.shift_in(1); let result = t.as_ref().skip_binder().visit_with(self); @@ -400,7 +409,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &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); @@ -460,7 +472,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &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); @@ -538,7 +553,7 @@ impl<'tcx> TyCtxt<'tcx> { /// contain escaping bound types. pub fn replace_late_bound_regions( self, - value: Binder, + value: Binder<'tcx, T>, mut fld_r: F, ) -> (T, BTreeMap>) where @@ -588,7 +603,7 @@ impl<'tcx> TyCtxt<'tcx> { /// types. pub fn replace_bound_vars( self, - value: Binder, + value: Binder<'tcx, T>, mut fld_r: F, fld_t: G, fld_c: H, @@ -607,7 +622,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Replaces any late-bound regions bound in `value` with /// free variants attached to `all_outlive_scope`. - pub fn liberate_late_bound_regions(self, all_outlive_scope: DefId, value: ty::Binder) -> T + pub fn liberate_late_bound_regions( + self, + all_outlive_scope: DefId, + value: ty::Binder<'tcx, T>, + ) -> T where T: TypeFoldable<'tcx>, { @@ -620,13 +639,49 @@ impl<'tcx> TyCtxt<'tcx> { .0 } + pub fn shift_bound_var_indices(self, bound_vars: usize, value: T) -> T + where + T: TypeFoldable<'tcx>, + { + self.replace_escaping_bound_vars( + value, + |r| { + self.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars), + kind: r.kind, + }, + )) + }, + |t| { + self.mk_ty(ty::Bound( + ty::INNERMOST, + ty::BoundTy { + var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars), + kind: t.kind, + }, + )) + }, + |c, ty| { + self.mk_const(ty::Const { + val: ty::ConstKind::Bound( + ty::INNERMOST, + ty::BoundVar::from_usize(c.as_usize() + bound_vars), + ), + ty, + }) + }, + ) + } + /// Returns a set of all late-bound regions that are constrained /// by `value`, meaning that if we instantiate those LBR with /// variables and equate `value` with something else, those /// variables will also be equated. pub fn collect_constrained_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, ) -> FxHashSet where T: TypeFoldable<'tcx>, @@ -637,7 +692,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns a set of all late-bound regions that appear in `value` anywhere. pub fn collect_referenced_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, ) -> FxHashSet where T: TypeFoldable<'tcx>, @@ -647,7 +702,7 @@ impl<'tcx> TyCtxt<'tcx> { fn collect_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, just_constraint: bool, ) -> FxHashSet where @@ -661,7 +716,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also /// method lookup and a few other places where precise region relationships are not required. - pub fn erase_late_bound_regions(self, value: Binder) -> T + pub fn erase_late_bound_regions(self, value: Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { @@ -676,20 +731,205 @@ impl<'tcx> TyCtxt<'tcx> { /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization. - pub fn anonymize_late_bound_regions(self, sig: Binder) -> Binder + pub fn anonymize_late_bound_regions(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, { let mut counter = 0; - Binder::bind( - self.replace_late_bound_regions(sig, |_| { - let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; + let inner = self + .replace_late_bound_regions(sig, |_| { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon(counter), + }; let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); counter += 1; r }) - .0, - ) + .0; + let bound_vars = self.mk_bound_variable_kinds( + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + ); + Binder::bind_with_vars(inner, bound_vars) + } +} + +pub struct BoundVarsCollector<'tcx> { + binder_index: ty::DebruijnIndex, + vars: BTreeMap, + // 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 { + 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>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + 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 { + 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 { + 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, + binder_index: ty::DebruijnIndex, + // 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> ValidateBoundVars<'tcx> { + pub fn new(bound_vars: &'tcx ty::List) -> Self { + ValidateBoundVars { + bound_vars, + binder_index: ty::INNERMOST, + visited: SsoHashSet::default(), + } + } +} + +impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { + type BreakTy = (); + + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + 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 { + if t.outer_exclusive_binder < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::BREAK; + } + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + if self.bound_vars.len() <= bound_ty.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars); + } + let list_var = self.bound_vars[bound_ty.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Ty(kind) => { + if kind != bound_ty.kind { + bug!( + "Mismatched type kinds: {:?} doesn't var in list {:?}", + bound_ty.kind, + list_var + ); + } + } + _ => { + bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var) + } + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match r { + ty::ReLateBound(index, br) if *index == self.binder_index => { + if self.bound_vars.len() <= br.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", *br, self.bound_vars); + } + let list_var = self.bound_vars[br.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Region(kind) => { + if kind != br.kind { + bug!( + "Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})", + br.kind, + list_var, + self.bound_vars + ); + } + } + _ => bug!( + "Mismatched bound variable kinds! Expected region, found {:?}", + list_var + ), + } + } + + _ => (), + }; + + r.super_visit_with(self) } } @@ -719,7 +959,10 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &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); @@ -828,7 +1071,10 @@ struct HasEscapingVarsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { type BreakTy = FoundEscapingVars; - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); @@ -974,7 +1220,10 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.current_index.shift_in(1); let result = t.super_visit_with(self); self.current_index.shift_out(1); diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 79cd26f566..c8fdbc30d1 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -18,7 +18,9 @@ pub enum GenericParamDefKind { object_lifetime_default: ObjectLifetimeDefault, synthetic: Option, }, - Const, + Const { + has_default: bool, + }, } impl GenericParamDefKind { @@ -26,15 +28,15 @@ impl GenericParamDefKind { match self { GenericParamDefKind::Lifetime => "lifetime", GenericParamDefKind::Type { .. } => "type", - GenericParamDefKind::Const => "constant", + GenericParamDefKind::Const { .. } => "constant", } } pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { match self { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, - GenericParamDefKind::Const => { - ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } + GenericParamDefKind::Const { .. } => { + ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } } } } @@ -105,7 +107,7 @@ impl<'tcx> Generics { match param.kind { GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, GenericParamDefKind::Type { .. } => own_counts.types += 1, - GenericParamDefKind::Const => own_counts.consts += 1, + GenericParamDefKind::Const { .. } => own_counts.consts += 1, } } @@ -121,8 +123,8 @@ impl<'tcx> Generics { GenericParamDefKind::Type { has_default, .. } => { own_defaults.types += has_default as usize; } - GenericParamDefKind::Const => { - // FIXME(const_generics:defaults) + GenericParamDefKind::Const { has_default } => { + own_defaults.consts += has_default as usize; } } } @@ -146,7 +148,9 @@ impl<'tcx> Generics { pub fn own_requires_monomorphization(&self) -> bool { for param in &self.params { match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true, + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + return true; + } GenericParamDefKind::Lifetime => {} } } @@ -189,7 +193,7 @@ impl<'tcx> Generics { pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { let param = self.param_at(param.index as usize, tcx); match param.kind { - GenericParamDefKind::Const => param, + GenericParamDefKind::Const { .. } => param, _ => bug!("expected const parameter, but found another generic parameter"), } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 23cedfd499..41d953216e 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -216,9 +216,10 @@ impl<'tcx> InstanceDef<'tcx> { // drops of `Option::None` before LTO. We also respect the intent of // `#[inline]` on `Drop::drop` implementations. return ty.ty_adt_def().map_or(true, |adt_def| { - adt_def.destructor(tcx).map_or(adt_def.is_enum(), |dtor| { - tcx.codegen_fn_attrs(dtor.did).requests_inline() - }) + adt_def.destructor(tcx).map_or_else( + || adt_def.is_enum(), + |dtor| tcx.codegen_fn_attrs(dtor.did).requests_inline(), + ) }); } tcx.codegen_fn_attrs(self.def_id()).requests_inline() @@ -482,6 +483,7 @@ impl<'tcx> Instance<'tcx> { if let Some(substs) = self.substs_for_mir_body() { v.subst(tcx, substs) } else { *v } } + #[inline(always)] pub fn subst_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, @@ -593,7 +595,7 @@ fn polymorphize<'tcx>( }, // Simple case: If parameter is a const or type parameter.. - ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if + ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if // ..and is within range and unused.. unused.contains(param.index).unwrap_or(false) => // ..then use the identity for this parameter. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 814581a6cf..c2e9dba6c8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use crate::ich::StableHashingContext; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; @@ -11,7 +12,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; +use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ @@ -1251,13 +1252,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } else { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; - for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) { + for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) { let offsets = match layout_variant.fields { FieldsShape::Arbitrary { ref offsets, .. } => offsets, _ => bug!(), }; let mut fields = - field_layouts.iter().zip(offsets).filter(|p| !p.0.is_zst()); + iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); let (field, offset) = match (fields.next(), fields.next()) { (None, None) => continue, (Some(pair), None) => pair, @@ -1626,7 +1627,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { const INVALID_FIELD_IDX: u32 = !0; let mut combined_inverse_memory_index = vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()]; - let mut offsets_and_memory_index = offsets.into_iter().zip(memory_index); + let mut offsets_and_memory_index = iter::zip(offsets, memory_index); let combined_offsets = variant_fields .iter() .enumerate() @@ -2318,31 +2319,30 @@ where ty::Ref(_, ty, mt) if offset.bytes() == 0 => { let address_space = addr_space_of_ty(ty); let tcx = cx.tcx(); - let is_freeze = ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()); - let kind = match mt { - hir::Mutability::Not => { - if is_freeze { - PointerKind::Frozen - } else { - PointerKind::Shared + let kind = if tcx.sess.opts.optimize == OptLevel::No { + // Use conservative pointer kind if not optimizing. This saves us the + // Freeze/Unpin queries, and can save time in the codegen backend (noalias + // attributes in LLVM have compile-time cost even in unoptimized builds). + PointerKind::Shared + } else { + match mt { + hir::Mutability::Not => { + if ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()) { + PointerKind::Frozen + } else { + PointerKind::Shared + } } - } - hir::Mutability::Mut => { - // Previously we would only emit noalias annotations for LLVM >= 6 or in - // panic=abort mode. That was deemed right, as prior versions had many bugs - // in conjunction with unwinding, but later versions didn’t seem to have - // said issues. See issue #31681. - // - // Alas, later on we encountered a case where noalias would generate wrong - // code altogether even with recent versions of LLVM in *safe* code with no - // unwinding involved. See #54462. - // - // For now, do not enable mutable_noalias by default at all, while the - // issue is being figured out. - if tcx.sess.opts.debugging_opts.mutable_noalias { - PointerKind::UniqueBorrowed - } else { - PointerKind::Shared + hir::Mutability::Mut => { + // References to self-referential structures should not be considered + // noalias, as another pointer to the structure can be obtained, that + // is not based-on the original reference. We consider all !Unpin + // types to be potentially self-referential here. + if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) { + PointerKind::UniqueBorrowed + } else { + PointerKind::Shared + } } } }; @@ -2482,21 +2482,42 @@ impl<'tcx> ty::Instance<'tcx> { ty::Closure(def_id, substs) => { let sig = substs.as_closure().sig(); - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| { + let bound_vars = tcx.mk_bound_variable_kinds( + sig.bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + + let sig = sig.skip_binder(); + ty::Binder::bind_with_vars( tcx.mk_fn_sig( - iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + iter::once(env_ty).chain(sig.inputs().iter().cloned()), sig.output(), sig.c_variadic, sig.unsafety, sig.abi, - ) - }) + ), + bound_vars, + ) } ty::Generator(_, substs, _) => { let sig = substs.as_generator().poly_sig(); - let br = ty::BoundRegion { kind: ty::BrEnv }; + let bound_vars = tcx.mk_bound_variable_kinds( + sig.bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; let env_region = ty::ReLateBound(ty::INNERMOST, br); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); @@ -2505,21 +2526,21 @@ impl<'tcx> ty::Instance<'tcx> { let pin_substs = tcx.intern_substs(&[env_ty.into()]); let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); - sig.map_bound(|sig| { - let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = - tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - + let sig = sig.skip_binder(); + let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + ty::Binder::bind_with_vars( tcx.mk_fn_sig( [env_ty, sig.resume_ty].iter(), &ret_ty, false, hir::Unsafety::Normal, rustc_target::spec::abi::Abi::Rust, - ) - }) + ), + bound_vars, + ) } _ => bug!("unexpected type {:?} in Instance::fn_sig", ty), } @@ -2609,6 +2630,7 @@ fn fn_can_unwind( | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => false, @@ -2691,6 +2713,7 @@ where AmdGpuKernel => Conv::AmdGpuKernel, AvrInterrupt => Conv::AvrInterrupt, AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, + Wasm => Conv::C, // These API constants ought to be more specific... Cdecl => Conv::C, @@ -2775,10 +2798,14 @@ where // and can be marked as both `readonly` and `noalias`, as // LLVM's definition of `noalias` is based solely on memory // dependencies rather than pointer equality + // + // Due to miscompiles in LLVM < 12, we apply a separate NoAliasMutRef attribute + // for UniqueBorrowed arguments, so that the codegen backend can decide + // whether or not to actually emit the attribute. let no_alias = match kind { - PointerKind::Shared => false, + PointerKind::Shared | PointerKind::UniqueBorrowed => false, PointerKind::UniqueOwned => true, - PointerKind::Frozen | PointerKind::UniqueBorrowed => !is_return, + PointerKind::Frozen => !is_return, }; if no_alias { attrs.set(ArgAttribute::NoAlias); @@ -2787,6 +2814,10 @@ where if kind == PointerKind::Frozen && !is_return { attrs.set(ArgAttribute::ReadOnly); } + + if kind == PointerKind::UniqueBorrowed && !is_return { + attrs.set(ArgAttribute::NoAliasMutRef); + } } } }; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5bbf7b35d3..af49533753 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -55,7 +55,7 @@ pub use rustc_type_ir::*; pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; -pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, ValTree}; +pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree}; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, @@ -67,12 +67,12 @@ pub use self::sty::BoundRegionKind::*; pub use self::sty::RegionKind::*; pub use self::sty::TyKind::*; pub use self::sty::{ - Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, CanonicalPolyFnSig, - ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, - GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, - PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, - TyKind, TypeAndMut, UpvarSubsts, + Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind, + CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, + ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, + GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, + PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, + RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, }; pub use self::trait_def::TraitDef; @@ -124,6 +124,20 @@ pub struct ResolverOutputs { /// 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, + pub main_def: Option, +} + +#[derive(Clone, Copy)] +pub struct MainDefinition { + pub res: Res, + pub is_import: bool, + pub span: Span, +} + +impl MainDefinition { + pub fn opt_fn_def_id(self) -> Option { + if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } + } } /// The "header" of an impl is everything outside the body: a Self type, a trait @@ -302,7 +316,7 @@ impl<'tcx> TyS<'tcx> { // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyS<'_>, 32); +static_assert_size!(TyS<'_>, 40); impl<'tcx> Ord for TyS<'tcx> { fn cmp(&self, other: &TyS<'tcx>) -> Ordering { @@ -359,14 +373,14 @@ impl ty::EarlyBoundRegion { #[derive(Debug)] crate struct PredicateInner<'tcx> { - kind: Binder>, + kind: Binder<'tcx, PredicateKind<'tcx>>, flags: TypeFlags, /// See the comment for the corresponding field of [TyS]. outer_exclusive_binder: ty::DebruijnIndex, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateInner<'_>, 40); +static_assert_size!(PredicateInner<'_>, 48); #[derive(Clone, Copy, Lift)] pub struct Predicate<'tcx> { @@ -389,9 +403,9 @@ impl Hash for Predicate<'_> { impl<'tcx> Eq for Predicate<'tcx> {} impl<'tcx> Predicate<'tcx> { - /// Gets the inner `Binder>`. + /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] - pub fn kind(self) -> Binder> { + pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { self.inner.kind } } @@ -543,10 +557,33 @@ impl<'tcx> Predicate<'tcx> { // substitution code expects equal binding levels in the values // from the substitution and the value being substituted into, and // this trick achieves that). - let substs = trait_ref.skip_binder().substs; - let pred = self.kind().skip_binder(); - let new = pred.subst(tcx, substs); - tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new)) + + // Working through the second example: + // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] + // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] + // We want to end up with: + // for<'x, 'b> T: Bar1<'^0.0, '^0.1> + // To do this: + // 1) We must shift all bound vars in predicate by the length + // of trait ref's bound vars. So, we would end up with predicate like + // Self: Bar1<'a, '^0.1> + // 2) We can then apply the trait substs to this, ending up with + // T: Bar1<'^0.0, '^0.1> + // 3) Finally, to create the final bound vars, we concatenate the bound + // vars of the trait ref with those of the predicate: + // ['x, 'b] + let bound_pred = self.kind(); + let pred_bound_vars = bound_pred.bound_vars(); + let trait_bound_vars = trait_ref.bound_vars(); + // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> + let shifted_pred = + tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); + // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> + let new = shifted_pred.subst(tcx, trait_ref.skip_binder().substs); + // 3) ['x] + ['b] -> ['x, 'b] + let bound_vars = + tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars)); + tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) } } @@ -556,7 +593,7 @@ pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, } -pub type PolyTraitPredicate<'tcx> = ty::Binder>; +pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; impl<'tcx> TraitPredicate<'tcx> { pub fn def_id(self) -> DefId { @@ -574,7 +611,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder> { + pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound(|trait_ref| trait_ref.self_ty()) } } @@ -584,8 +621,8 @@ impl<'tcx> PolyTraitPredicate<'tcx> { pub struct OutlivesPredicate(pub A, pub B); // `A: B` pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder>; -pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder>; +pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; +pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] @@ -594,7 +631,7 @@ pub struct SubtypePredicate<'tcx> { pub a: Ty<'tcx>, pub b: Ty<'tcx>, } -pub type PolySubtypePredicate<'tcx> = ty::Binder>; +pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: @@ -615,25 +652,15 @@ pub struct ProjectionPredicate<'tcx> { pub ty: Ty<'tcx>, } -pub type PolyProjectionPredicate<'tcx> = Binder>; +pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; impl<'tcx> PolyProjectionPredicate<'tcx> { - /// Returns the `DefId` of the associated item being projected. - pub fn item_def_id(&self) -> DefId { - self.skip_binder().projection_ty.item_def_id - } - /// Returns the `DefId` of the trait of the associated item being projected. #[inline] pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { self.skip_binder().projection_ty.trait_def_id(tcx) } - #[inline] - pub fn projection_self_ty(&self) -> Binder> { - self.map_bound(|predicate| predicate.projection_ty.self_ty()) - } - /// Get the [PolyTraitRef] required for this projection to be well formed. /// Note that for generic associated types the predicates of the associated /// type also need to be checked. @@ -647,7 +674,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) } - pub fn ty(&self) -> Binder> { + pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> { self.map_bound(|predicate| predicate.ty) } @@ -681,7 +708,7 @@ pub trait ToPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; } -impl ToPredicate<'tcx> for Binder> { +impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(self) @@ -704,11 +731,11 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ConstnessAnd { - value: self.value.map_bound(|trait_ref| ty::TraitPredicate { trait_ref }), - constness: self.constness, - } - .to_predicate(tcx) + self.value + .map_bound(|trait_ref| { + PredicateKind::Trait(ty::TraitPredicate { trait_ref }, self.constness) + }) + .to_predicate(tcx) } } @@ -1039,10 +1066,6 @@ impl WithOptConstParam { None } - pub fn expect_local(self) -> WithOptConstParam { - self.as_local().unwrap() - } - pub fn is_local(self) -> bool { self.did.is_local() } @@ -1949,6 +1972,7 @@ pub fn provide(providers: &mut ty::query::Providers) { trait_impls_of: trait_def::trait_impls_of_provider, all_local_trait_impls: trait_def::all_local_trait_impls, type_uninhabited_from: inhabitedness::type_uninhabited_from, + const_param_default: consts::const_param_default, ..*providers }; } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 9d97815a5f..a4f736654a 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -7,6 +7,7 @@ //! `normalize_generic_arg_after_erasing_regions` query for each type //! or constant found within. (This underlying query is what is cached.) +use crate::mir; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; @@ -38,7 +39,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// If you have a `Binder`, you can do this to strip out the + /// If you have a `Binder<'tcx, T>`, you can do this to strip out the /// late-bound regions and then normalize the result, yielding up /// a `T` (with regions erased). This is appropriate when the /// binder is being instantiated at the call site. @@ -49,7 +50,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn normalize_erasing_late_bound_regions( self, param_env: ty::ParamEnv<'tcx>, - value: ty::Binder, + value: ty::Binder<'tcx, T>, ) -> T where T: TypeFoldable<'tcx>, @@ -101,4 +102,10 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { let arg = self.param_env.and(c.into()); self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const() } + + #[inline] + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + let arg = self.param_env.and(c); + self.tcx.normalize_mir_const_after_erasing_regions(arg) + } } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 77f1668893..13e2122a61 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -63,7 +63,7 @@ pub trait Printer<'tcx>: Sized { fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result; fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result; @@ -193,17 +193,19 @@ pub trait Printer<'tcx>: Sized { .params .iter() .rev() - .take_while(|param| { - match param.kind { - ty::GenericParamDefKind::Lifetime => false, - ty::GenericParamDefKind::Type { has_default, .. } => { - has_default - && substs[param.index as usize] - == GenericArg::from( - self.tcx().type_of(param.def_id).subst(self.tcx(), substs), - ) - } - ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults) + .take_while(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => false, + ty::GenericParamDefKind::Type { has_default, .. } => { + has_default + && substs[param.index as usize] + == GenericArg::from( + self.tcx().type_of(param.def_id).subst(self.tcx(), substs), + ) + } + ty::GenericParamDefKind::Const { has_default } => { + has_default + && substs[param.index as usize] + == GenericArg::from(self.tcx().const_param_default(param.def_id)) } }) .count(); @@ -344,7 +346,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> - for &'tcx ty::List>> + for &'tcx ty::List>> { type Output = P::DynExistential; type Error = P::Error; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 7946d17006..1989c91a87 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -4,6 +4,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -19,6 +20,7 @@ use std::char; use std::collections::BTreeMap; use std::convert::TryFrom; use std::fmt::{self, Write as _}; +use std::iter; use std::ops::{ControlFlow, Deref, DerefMut}; // `pretty` is a separate module only for organization. @@ -201,7 +203,7 @@ pub trait PrettyPrinter<'tcx>: self.print_def_path(def_id, substs) } - fn in_binder(self, value: &ty::Binder) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { @@ -210,7 +212,7 @@ pub trait PrettyPrinter<'tcx>: fn wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: F, ) -> Result where @@ -764,7 +766,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { // Generate the main trait ref, including associated types. let mut first = true; @@ -915,7 +917,7 @@ pub trait PrettyPrinter<'tcx>: } match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { if let Some(promoted) = promoted { p!(print_value_path(def.did, substs)); p!(write("::{:?}", promoted)); @@ -1223,7 +1225,7 @@ pub trait PrettyPrinter<'tcx>: CtorKind::Fictive => { p!(" {{ "); let mut first = true; - for (field_def, field) in variant_def.fields.iter().zip(fields) { + for (field_def, field) in iter::zip(&variant_def.fields, fields) { if !first { p!(", "); } @@ -1420,7 +1422,8 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } fn print_type(mut self, ty: Ty<'tcx>) -> Result { - if self.tcx.sess.type_length_limit().value_within_limit(self.printed_type_count) { + let type_length_limit = self.tcx.sess.type_length_limit(); + if type_length_limit.value_within_limit(self.printed_type_count) { self.printed_type_count += 1; self.pretty_print_type(ty) } else { @@ -1431,7 +1434,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { self.pretty_print_dyn_existential(predicates) } @@ -1570,7 +1573,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { Ok(self) } - fn in_binder(self, value: &ty::Binder) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { @@ -1579,7 +1582,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { fn wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: C, ) -> Result where @@ -1635,7 +1638,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { data.name != kw::Empty && data.name != kw::UnderscoreLifetime } - ty::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { @@ -1714,7 +1717,7 @@ impl FmtPrinter<'_, '_, F> { return Ok(self); } } - ty::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { @@ -1762,7 +1765,7 @@ impl FmtPrinter<'_, '_, F> { impl FmtPrinter<'_, 'tcx, F> { pub fn name_all_regions( mut self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, ) -> Result<(Self, (T, BTreeMap>)), fmt::Error> where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, @@ -1801,35 +1804,101 @@ impl FmtPrinter<'_, 'tcx, F> { define_scoped_cx!(self); let mut region_index = self.region_index; - let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| { - let _ = start_or_continue(&mut self, "for<", ", "); - let kind = match br.kind { - ty::BrNamed(_, name) => { - let _ = write!(self, "{}", name); - br.kind - } - ty::BrAnon(_) | ty::BrEnv => { - let name = loop { - let name = name_by_region_index(region_index); - region_index += 1; - if !self.used_region_names.contains(&name) { - break name; - } - }; - let _ = write!(self, "{}", name); - ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + // If we want to print verbosly, then print *all* binders, even if they + // 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() { + // anon index + 1 (BrEnv takes 0) -> name + let mut region_map: BTreeMap = 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); + } + ty::BoundVariableKind::Region(ty::BrAnon(i)) => { + let _ = start_or_continue(&mut self, "for<", ", "); + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !self.used_region_names.contains(&name) { + break name; + } + }; + let _ = write!(self, "{}", name); + region_map.insert(i + 1, name); + } + ty::BoundVariableKind::Region(ty::BrEnv) => { + let _ = start_or_continue(&mut self, "for<", ", "); + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !self.used_region_names.contains(&name) { + break name; + } + }; + let _ = write!(self, "{}", name); + region_map.insert(0, name); + } + _ => continue, } - }; - self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind })) - }); - start_or_continue(&mut self, "", "> ")?; + } + start_or_continue(&mut self, "", "> ")?; + + self.tcx.replace_late_bound_regions(value.clone(), |br| { + let kind = match br.kind { + ty::BrNamed(_, _) => br.kind, + ty::BrAnon(i) => { + let name = region_map[&(i + 1)]; + ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + } + ty::BrEnv => { + let name = region_map[&0]; + ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + } + }; + self.tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: br.var, kind }, + )) + }) + } else { + let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| { + let _ = start_or_continue(&mut self, "for<", ", "); + let kind = match br.kind { + ty::BrNamed(_, name) => { + let _ = write!(self, "{}", name); + br.kind + } + ty::BrAnon(_) | ty::BrEnv => { + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !self.used_region_names.contains(&name) { + break name; + } + }; + let _ = write!(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 + }; self.binder_depth += 1; self.region_index = region_index; Ok((self, new_value)) } - pub fn pretty_in_binder(self, value: &ty::Binder) -> Result + pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { @@ -1843,7 +1912,7 @@ impl FmtPrinter<'_, 'tcx, F> { pub fn pretty_wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: C, ) -> Result where @@ -1857,28 +1926,52 @@ impl FmtPrinter<'_, 'tcx, F> { Ok(inner) } - fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) + fn prepare_late_bound_region_info(&mut self, value: &ty::Binder<'tcx, T>) where T: TypeFoldable<'tcx>, { - struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> { + debug!("prepare_late_bound_region_info(value: {:?})", value); + + struct LateBoundRegionNameCollector<'a, 'tcx> { + used_region_names: &'a mut FxHashSet, + type_collector: SsoHashSet>, + } + + impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { + type BreakTy = (); + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) = *r { - self.0.insert(name); + 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); } r.super_visit_with(self) } + + // We collect types in order to prevent really large types from compiling for + // a really long time. See issue #83150 for why this is necessary. + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + debug!("LateBoundRegionNameCollector::visit_ty(ty: {:?}", ty); + let not_previously_inserted = self.type_collector.insert(ty); + if not_previously_inserted { + ty.super_visit_with(self) + } else { + ControlFlow::CONTINUE + } + } } self.used_region_names.clear(); - let mut collector = LateBoundRegionNameCollector(&mut self.used_region_names); + let mut collector = LateBoundRegionNameCollector { + used_region_names: &mut self.used_region_names, + type_collector: SsoHashSet::new(), + }; value.visit_with(&mut collector); self.region_index = 0; } } -impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder +impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> where T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>, { @@ -1965,28 +2058,28 @@ impl ty::TraitRef<'tcx> { } } -impl ty::Binder> { - pub fn print_only_trait_path(self) -> ty::Binder> { +impl ty::Binder<'tcx, ty::TraitRef<'tcx>> { + pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> { self.map_bound(|tr| tr.print_only_trait_path()) } } forward_display_to_print! { Ty<'tcx>, - &'tcx ty::List>>, + &'tcx ty::List>>, &'tcx ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder, ty::Region<'tcx>>>, - ty::Binder, ty::Region<'tcx>>>, + ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>, + ty::Binder<'tcx, ty::TraitRef<'tcx>>, + ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + ty::Binder<'tcx, ty::FnSig<'tcx>>, + ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, + ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, + ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, + ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, ty::OutlivesPredicate, ty::Region<'tcx>>, ty::OutlivesPredicate, ty::Region<'tcx>> diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 48e777f715..c170858ba8 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -217,8 +217,11 @@ macro_rules! define_callbacks { fn default() -> Self { Providers { $($name: |_, key| bug!( - "`tcx.{}({:?})` unsupported by its crate", - stringify!($name), key + "`tcx.{}({:?})` unsupported by its crate; \ + perhaps the `{}` query was never assigned a provider function", + stringify!($name), + key, + stringify!($name), ),)* } } diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 78193acc74..43b775f808 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -4,7 +4,6 @@ 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::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; use rustc_data_structures::thin_vec::ThinVec; @@ -17,7 +16,7 @@ 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}, + opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}, Decodable, Decoder, Encodable, Encoder, }; use rustc_session::{CrateDisambiguator, Session}; @@ -526,7 +525,7 @@ impl<'sess> OnDiskCache<'sess> { ) { let mut current_diagnostics = self.current_diagnostics.borrow_mut(); - let x = current_diagnostics.entry(dep_node_index).or_insert(Vec::new()); + let x = current_diagnostics.entry(dep_node_index).or_default(); x.extend(Into::>::into(diagnostics)); } @@ -913,12 +912,6 @@ impl<'a, 'tcx> Decodable> for DefId { } } -impl<'a, 'tcx> FingerprintDecoder for CacheDecoder<'a, 'tcx> { - fn decode_fingerprint(&mut self) -> Result { - Fingerprint::decode_opaque(&mut self.opaque) - } -} - impl<'a, 'tcx> Decodable> for &'tcx FxHashSet { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result { RefDecodable::decode(d) @@ -1011,12 +1004,6 @@ where } } -impl<'a, 'tcx, E: OpaqueEncoder> FingerprintEncoder for CacheEncoder<'a, 'tcx, E> { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), E::Error> { - self.encoder.encode_fingerprint(f) - } -} - impl<'a, 'tcx, E> Encodable> for SyntaxContext where E: 'a + OpaqueEncoder, @@ -1167,6 +1154,7 @@ where emit_f32(f32); emit_char(char); emit_str(&str); + emit_raw_bytes(&[u8]); } } @@ -1180,42 +1168,6 @@ impl<'a, 'tcx> Encodable> for [u8] { } } -// An integer that will always encode to 8 bytes. -struct IntEncodedWithFixedSize(u64); - -impl IntEncodedWithFixedSize { - pub const ENCODED_SIZE: usize = 8; -} - -impl Encodable for IntEncodedWithFixedSize { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - let start_pos = e.position(); - for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { - ((self.0 >> (i * 8)) as u8).encode(e)?; - } - let end_pos = e.position(); - assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - Ok(()) - } -} - -impl<'a> Decodable> for IntEncodedWithFixedSize { - fn decode(decoder: &mut opaque::Decoder<'a>) -> Result { - let mut value: u64 = 0; - let start_pos = decoder.position(); - - for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { - let byte: u8 = Decodable::decode(decoder)?; - value |= (byte as u64) << (i * 8); - } - - let end_pos = decoder.position(); - assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - - Ok(IntEncodedWithFixedSize(value)) - } -} - pub fn encode_query_results<'a, 'tcx, CTX, Q>( tcx: CTX, encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>, @@ -1233,20 +1185,27 @@ where assert!(Q::query_state(tcx).all_inactive()); let cache = Q::query_cache(tcx); - cache.iter_results(|results| { - for (key, value, dep_node) in results { - 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. - encoder.encode_tagged(dep_node, value)?; + 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); + } } } - Ok(()) - }) + }); + + res } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index b41bf70e88..b6f93c9bd5 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -33,15 +33,6 @@ pub trait TypeRelation<'tcx>: Sized { /// relation. Just affects error messages. fn a_is_expected(&self) -> bool; - /// Whether we should look into the substs of unevaluated constants - /// even if `feature(const_evaluatable_checked)` is active. - /// - /// This is needed in `combine` to prevent accidentially creating - /// infinite types as we abuse `TypeRelation` to walk a type there. - fn visit_ct_substs(&self) -> bool { - false - } - fn with_cause(&mut self, _cause: Cause, f: F) -> R where F: FnOnce(&mut Self) -> R, @@ -102,9 +93,9 @@ pub trait TypeRelation<'tcx>: Sized { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>; } @@ -149,7 +140,7 @@ pub fn relate_substs>( ) -> RelateResult<'tcx, SubstsRef<'tcx>> { let tcx = relation.tcx(); - let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| { + let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { let variance = variances.map_or(ty::Invariant, |v| v[i]); relation.relate_with_variance(variance, a, b) }); @@ -179,12 +170,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { return Err(TypeError::ArgCount); } - let inputs_and_output = a - .inputs() - .iter() - .cloned() - .zip(b.inputs().iter().cloned()) - .map(|x| (x, false)) + let inputs_and_output = iter::zip(a.inputs(), b.inputs()) + .map(|(&a, &b)| ((a, b), false)) .chain(iter::once(((a.output(), b.output()), true))) .map(|((a, b), is_output)| { if is_output { @@ -192,6 +179,12 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { } else { relation.relate_with_variance(ty::Contravariant, a, b) } + }) + .enumerate() + .map(|(i, r)| match r { + Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)), + Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)), + r => r, }); Ok(ty::FnSig { inputs_and_output: tcx.mk_type_list(inputs_and_output)?, @@ -308,7 +301,7 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> { assert_eq!(a.0.len(), b.0.len()); let tcx = relation.tcx(); - let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?; + let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?; Ok(GeneratorWitness(types)) } } @@ -432,9 +425,9 @@ pub fn super_relate_tys>( let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); match (sz_a, sz_b) { - (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( - expected_found(relation, sz_a_val, sz_b_val), - )), + (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( + TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), + ), _ => Err(err), } } @@ -449,7 +442,7 @@ pub fn super_relate_tys>( (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { Ok(tcx.mk_tup( - as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), + iter::zip(as_, bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), )?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) @@ -531,24 +524,26 @@ pub fn super_relate_consts>( check_const_value_eq(relation, a_val, b_val, a, b)? } - ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => { - tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) + if tcx.features().const_evaluatable_checked => + { + tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs))) } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `const_evaluatable_checked` can // be stabilized. - ( - ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted), - ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted), - ) if a_def == b_def && a_promoted == b_promoted => { + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) + if au.def == bu.def && au.promoted == bu.promoted => + { let substs = - relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?; + relation.relate_with_variance(ty::Variance::Invariant, au.substs, bu.substs)?; return Ok(tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated(a_def, substs, a_promoted), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: au.def, + substs, + promoted: au.promoted, + }), ty: a.ty, })); } @@ -591,9 +586,7 @@ fn check_const_value_eq>( // Both the variant and each field have to be equal. if a_destructured.variant == b_destructured.variant { - for (a_field, b_field) in - a_destructured.fields.iter().zip(b_destructured.fields.iter()) - { + for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) { relation.consts(a_field, b_field)?; } @@ -607,7 +600,7 @@ fn check_const_value_eq>( }) } -impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { +impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { fn relate>( relation: &mut R, a: Self, @@ -629,13 +622,12 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List Ok(ty::Binder::bind(Trait( - relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), - ))), - (Projection(a), Projection(b)) => Ok(ty::Binder::bind(Projection( + (Trait(a), Trait(b)) => Ok(ep_a + .rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))), + (Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection( relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), ))), (AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))), @@ -698,12 +690,12 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> { } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder { +impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> { fn relate>( relation: &mut R, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> { + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { relation.binders(a, b) } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 0ca94a9f18..7290c41d61 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -454,10 +454,16 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { } } -impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder { - type Lifted = ty::Binder; +impl<'a, 'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<'a, T> +where + >::Lifted: TypeFoldable<'tcx>, +{ + type Lifted = ty::Binder<'tcx, T::Lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - self.map_bound(|v| tcx.lift(v)).transpose() + let bound_vars = tcx.lift(self.bound_vars()); + tcx.lift(self.skip_binder()) + .zip(bound_vars) + .map(|(value, vars)| ty::Binder::bind_with_vars(value, vars)) } } @@ -581,6 +587,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { UnsafetyMismatch(x) => UnsafetyMismatch(x), AbiMismatch(x) => AbiMismatch(x), Mutability => Mutability, + ArgumentMutability(i) => ArgumentMutability(i), TupleSize(x) => TupleSize(x), FixedArraySize(x) => FixedArraySize(x), ArgCount => ArgCount, @@ -601,6 +608,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { CyclicTy(t) => return tcx.lift(t).map(|t| CyclicTy(t)), CyclicConst(ct) => return tcx.lift(ct).map(|ct| CyclicConst(ct)), ProjectionMismatched(x) => ProjectionMismatched(x), + ArgumentSorts(x, i) => return tcx.lift(x).map(|x| ArgumentSorts(x, i)), Sorts(x) => return tcx.lift(x).map(Sorts), ExistentialMismatch(x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(x) => return tcx.lift(x).map(ConstMismatch), @@ -749,7 +757,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { +impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { fn super_fold_with>(self, folder: &mut F) -> Self { self.map_bound(|ty| ty.fold_with(folder)) } @@ -767,7 +775,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { fn super_fold_with>(self, folder: &mut F) -> Self { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } @@ -1031,8 +1039,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { match self { ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), - ty::ConstKind::Unevaluated(did, substs, promoted) => { - ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { + def, + substs: substs.fold_with(folder), + promoted, + }) } ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) @@ -1045,7 +1057,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { match *self { ty::ConstKind::Infer(ic) => ic.visit_with(visitor), ty::ConstKind::Param(p) => p.visit_with(visitor), - ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor), + ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2cd969d7a1..691bfcc98d 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,6 +5,8 @@ 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, *}; use crate::ty::{ @@ -62,22 +64,10 @@ pub enum BoundRegionKind { #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] #[derive(HashStable)] pub struct BoundRegion { + pub var: BoundVar, pub kind: BoundRegionKind, } -impl BoundRegion { - /// When canonicalizing, we replace unbound inference variables and free - /// regions with anonymous late bound regions. This method asserts that - /// we have an anonymous late bound region, which hence may refer to - /// a canonical variable. - pub fn assert_bound_var(&self) -> BoundVar { - match self.kind { - BoundRegionKind::BrAnon(var) => BoundVar::from_u32(var), - _ => bug!("bound region is not anonymous"), - } - } -} - impl BoundRegionKind { pub fn is_named(&self) -> bool { match *self { @@ -90,7 +80,7 @@ impl BoundRegionKind { /// Defines the kinds of types. /// /// N.B., if you change this, you'll probably want to change the corresponding -/// AST structure in `librustc_ast/ast.rs` as well. +/// AST structure in `rustc_ast/src/ast.rs` as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)] #[derive(HashStable)] #[rustc_diagnostic_item = "TyKind"] @@ -160,8 +150,8 @@ pub enum TyKind<'tcx> { /// ``` FnPtr(PolyFnSig<'tcx>), - /// A trait, defined with `trait`. - Dynamic(&'tcx List>>, ty::Region<'tcx>), + /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. + Dynamic(&'tcx List>>, ty::Region<'tcx>), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. @@ -173,7 +163,7 @@ pub enum TyKind<'tcx> { /// A type representing the types stored inside a generator. /// This should only appear in GeneratorInteriors. - GeneratorWitness(Binder<&'tcx List>>), + GeneratorWitness(Binder<'tcx, &'tcx List>>), /// The never type `!`. Never, @@ -232,7 +222,7 @@ impl TyKind<'tcx> { // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyKind<'_>, 24); +static_assert_size!(TyKind<'_>, 32); /// A closure can be modeled as a struct that looks like: /// @@ -747,7 +737,7 @@ impl<'tcx> ExistentialPredicate<'tcx> { } } -impl<'tcx> Binder> { +impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { @@ -768,7 +758,7 @@ impl<'tcx> Binder> { } } -impl<'tcx> List>> { +impl<'tcx> List>> { /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) @@ -794,7 +784,7 @@ impl<'tcx> List>> { /// is `{Send, Sync}`, while there is no principal. These trait objects /// have a "trivial" vtable consisting of just the size, alignment, /// and destructor. - pub fn principal(&self) -> Option>> { + pub fn principal(&self) -> Option>> { self[0] .map_bound(|this| match this { ExistentialPredicate::Trait(tr) => Some(tr), @@ -810,7 +800,7 @@ impl<'tcx> List>> { #[inline] pub fn projection_bounds<'a>( &'a self, - ) -> impl Iterator>> + 'a { + ) -> impl Iterator>> + 'a { self.iter().filter_map(|predicate| { predicate .map_bound(|pred| match pred { @@ -875,10 +865,10 @@ impl<'tcx> TraitRef<'tcx> { } } -pub type PolyTraitRef<'tcx> = Binder>; +pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>; impl<'tcx> PolyTraitRef<'tcx> { - pub fn self_ty(&self) -> Binder> { + pub fn self_ty(&self) -> Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|tr| tr.self_ty()) } @@ -931,7 +921,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> { } } -pub type PolyExistentialTraitRef<'tcx> = Binder>; +pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>; impl<'tcx> PolyExistentialTraitRef<'tcx> { pub fn def_id(&self) -> DefId { @@ -947,52 +937,56 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable)] +pub enum BoundVariableKind { + Ty(BoundTyKind), + Region(BoundRegionKind), + Const, +} + /// Binder is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == -/// Binder`). Note that when we instantiate, +/// Binder<'tcx, TraitRef>`). Note that when we instantiate, /// erase, or otherwise "discharge" these bound vars, we change the -/// type from `Binder` to just `T` (see +/// type from `Binder<'tcx, T>` to just `T` (see /// e.g., `liberate_late_bound_regions`). /// /// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct Binder(T); +pub struct Binder<'tcx, T>(T, &'tcx List); -impl Binder { +impl<'tcx, T> Binder<'tcx, T> +where + T: TypeFoldable<'tcx>, +{ /// Wraps `value` in a binder, asserting that `value` does not /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. - pub fn dummy<'tcx>(value: T) -> Binder - where - T: TypeFoldable<'tcx>, - { + pub fn dummy(value: T) -> Binder<'tcx, T> { debug_assert!(!value.has_escaping_bound_vars()); - Binder(value) + Binder(value, ty::List::empty()) } /// Wraps `value` in a binder, binding higher-ranked vars (if any). - pub fn bind(value: T) -> Binder { - Binder(value) + 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)) } - /// Wraps `value` in a binder without actually binding any currently - /// unbound variables. - /// - /// Note that this will shift all debrujin indices of escaping bound variables - /// by 1 to avoid accidential captures. - pub fn wrap_nonbinding(tcx: TyCtxt<'tcx>, value: T) -> Binder - where - T: TypeFoldable<'tcx>, - { - if value.has_escaping_bound_vars() { - Binder::bind(super::fold::shift_vars(tcx, value, 1)) - } else { - Binder::dummy(value) + pub fn bind_with_vars(value: T, vars: &'tcx List) -> Binder<'tcx, T> { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(vars); + value.visit_with(&mut validator); } + Binder(value, vars) } +} +impl<'tcx, T> Binder<'tcx, T> { /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// De Bruijn indices and the like. It is usually better to @@ -1013,22 +1007,39 @@ impl Binder { self.0 } - pub fn as_ref(&self) -> Binder<&T> { - Binder(&self.0) + pub fn bound_vars(&self) -> &'tcx List { + self.1 } - pub fn map_bound_ref(&self, f: F) -> Binder + pub fn as_ref(&self) -> Binder<'tcx, &T> { + Binder(&self.0, self.1) + } + + pub fn map_bound_ref_unchecked(&self, f: F) -> Binder<'tcx, U> + where + F: FnOnce(&T) -> U, + { + let value = f(&self.0); + Binder(value, self.1) + } + + pub fn map_bound_ref>(&self, f: F) -> Binder<'tcx, U> where F: FnOnce(&T) -> U, { self.as_ref().map_bound(f) } - pub fn map_bound(self, f: F) -> Binder + pub fn map_bound>(self, f: F) -> Binder<'tcx, U> where F: FnOnce(T) -> U, { - Binder(f(self.0)) + let value = f(self.0); + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.1); + value.visit_with(&mut validator); + } + Binder(value, self.1) } /// Wraps a `value` in a binder, using the same bound variables as the @@ -1040,8 +1051,15 @@ impl Binder { /// don't actually track bound vars. However, semantically, it is different /// because bound vars aren't allowed to change here, whereas they are /// in `bind`. This may be (debug) asserted in the future. - pub fn rebind(&self, value: U) -> Binder { - Binder(value) + pub fn rebind(&self, value: U) -> Binder<'tcx, U> + where + U: TypeFoldable<'tcx>, + { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.bound_vars()); + value.visit_with(&mut validator); + } + Binder(value, self.1) } /// Unwraps and returns the value within, but only if it contains @@ -1054,45 +1072,32 @@ impl Binder { /// binders, but that would require adjusting the debruijn /// indices, and given the shallow binding structure we often use, /// would not be that useful.) - pub fn no_bound_vars<'tcx>(self) -> Option + pub fn no_bound_vars(self) -> Option where T: TypeFoldable<'tcx>, { if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } - /// Given two things that have the same binder level, - /// and an operation that wraps on their contents, executes the operation - /// and then wraps its result. - /// - /// `f` should consider bound regions at depth 1 to be free, and - /// anything it produces with bound regions at depth 1 will be - /// bound in the resulting return value. - pub fn fuse(self, u: Binder, f: F) -> Binder - where - F: FnOnce(T, U) -> R, - { - Binder(f(self.0, u.0)) - } - /// Splits the contents into two things that share the same binder /// level as the original, returning two distinct binders. /// /// `f` should consider bound regions at depth 1 to be free, and /// anything it produces with bound regions at depth 1 will be /// bound in the resulting return values. - pub fn split(self, f: F) -> (Binder, Binder) + pub fn split(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>) where F: FnOnce(T) -> (U, V), { let (u, v) = f(self.0); - (Binder(u), Binder(v)) + (Binder(u, self.1), Binder(v, self.1)) } } -impl Binder> { - pub fn transpose(self) -> Option> { - self.0.map(Binder) +impl<'tcx, T> Binder<'tcx, Option> { + pub fn transpose(self) -> Option> { + let bound_vars = self.1; + self.0.map(|v| Binder(v, bound_vars)) } } @@ -1155,19 +1160,7 @@ pub struct GenSig<'tcx> { pub return_ty: Ty<'tcx>, } -pub type PolyGenSig<'tcx> = Binder>; - -impl<'tcx> PolyGenSig<'tcx> { - pub fn resume_ty(&self) -> ty::Binder> { - self.map_bound_ref(|sig| sig.resume_ty) - } - pub fn yield_ty(&self) -> ty::Binder> { - self.map_bound_ref(|sig| sig.yield_ty) - } - pub fn return_ty(&self) -> ty::Binder> { - self.map_bound_ref(|sig| sig.return_ty) - } -} +pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>; /// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. @@ -1205,22 +1198,22 @@ impl<'tcx> FnSig<'tcx> { } } -pub type PolyFnSig<'tcx> = Binder>; +pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; impl<'tcx> PolyFnSig<'tcx> { #[inline] - pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { - self.map_bound_ref(|fn_sig| fn_sig.inputs()) + pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> { + self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) } #[inline] - pub fn input(&self, index: usize) -> ty::Binder> { + pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } - pub fn inputs_and_output(&self) -> ty::Binder<&'tcx List>> { + pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List>> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } #[inline] - pub fn output(&self) -> ty::Binder> { + pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.output()) } pub fn c_variadic(&self) -> bool { @@ -1234,7 +1227,7 @@ impl<'tcx> PolyFnSig<'tcx> { } } -pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; +pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] @@ -1248,10 +1241,6 @@ impl<'tcx> ParamTy { ParamTy { index, name } } - pub fn for_self() -> ParamTy { - ParamTy::new(0, kw::SelfUpper) - } - pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { ParamTy::new(def.index, def.name) } @@ -1269,7 +1258,7 @@ pub struct ParamConst { pub name: Symbol, } -impl<'tcx> ParamConst { +impl ParamConst { pub fn new(index: u32, name: Symbol) -> ParamConst { ParamConst { index, name } } @@ -1277,10 +1266,6 @@ impl<'tcx> ParamConst { pub fn for_def(def: &ty::GenericParamDef) -> ParamConst { ParamConst::new(def.index, def.name) } - - pub fn to_const(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - tcx.mk_const_param(self.index, self.name, ty) - } } pub type Region<'tcx> = &'tcx RegionKind; @@ -1486,7 +1471,7 @@ pub struct ExistentialProjection<'tcx> { pub ty: Ty<'tcx>, } -pub type PolyExistentialProjection<'tcx> = Binder>; +pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; impl<'tcx> ExistentialProjection<'tcx> { /// Extracts the underlying existential trait reference from this projection. @@ -1580,35 +1565,6 @@ impl RegionKind { } } - /// Adjusts any De Bruijn indices so as to make `to_binder` the - /// innermost binder. That is, if we have something bound at `to_binder`, - /// it will now be bound at INNERMOST. This is an appropriate thing to do - /// when moving a region out from inside binders: - /// - /// ``` - /// for<'a> fn(for<'b> for<'c> fn(&'a u32), _) - /// // Binder: D3 D2 D1 ^^ - /// ``` - /// - /// Here, the region `'a` would have the De Bruijn index D3, - /// because it is the bound 3 binders out. However, if we wanted - /// to refer to that region `'a` in the second argument (the `_`), - /// those two binders would not be in scope. In that case, we - /// might invoke `shift_out_to_binder(D3)`. This would adjust the - /// De Bruijn index of `'a` to D1 (the innermost binder). - /// - /// If we invoke `shift_out_to_binder` and the region is in fact - /// bound by one of the binders we are shifting out of, that is an - /// error (and should fail an assertion failure). - pub fn shifted_out_to_binder(&self, to_binder: ty::DebruijnIndex) -> RegionKind { - match *self { - ty::ReLateBound(debruijn, r) => { - ty::ReLateBound(debruijn.shifted_out_to_binder(to_binder), r) - } - r => r, - } - } - pub fn type_flags(&self) -> TypeFlags { let mut flags = TypeFlags::empty(); @@ -2160,7 +2116,7 @@ impl<'tcx> TyS<'tcx> { /// /// Note that during type checking, we use an inference variable /// to represent the closure kind, because it has not yet been - /// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`) + /// inferred. Once upvar inference (in `rustc_typeck/src/check/upvar.rs`) /// is complete, that type variable will be unified. pub fn to_opt_closure_kind(&self) -> Option { match self.kind() { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 5d1b976ae9..c84ca61122 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -1,5 +1,6 @@ // Type substitutions. +use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; @@ -448,7 +449,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.binders_passed += 1; let t = t.super_fold_with(self); self.binders_passed -= 1; @@ -503,6 +507,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { c.super_fold_with(self) } } + + #[inline] + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + c.super_fold_with(self) + } } impl<'a, 'tcx> SubstFolder<'a, 'tcx> { diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index ce17a724e2..e9b8883f29 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -35,6 +35,11 @@ pub struct TraitDef { /// and thus `impl`s of it are allowed to overlap. pub is_marker: bool, + /// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]` + /// attribute, indicating that editions before 2021 should not consider this trait + /// during method dispatch if the receiver is an array. + pub skip_array_during_method_dispatch: bool, + /// Used to determine whether the standard library is allowed to specialize /// on this trait. pub specialization_kind: TraitSpecializationKind, @@ -69,6 +74,12 @@ pub struct TraitImpls { non_blanket_impls: FxHashMap>, } +impl TraitImpls { + pub fn blanket_impls(&self) -> &[DefId] { + self.blanket_impls.as_slice() + } +} + impl<'tcx> TraitDef { pub fn new( def_id: DefId, @@ -76,6 +87,7 @@ impl<'tcx> TraitDef { paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + skip_array_during_method_dispatch: bool, specialization_kind: TraitSpecializationKind, def_path_hash: DefPathHash, ) -> TraitDef { @@ -85,6 +97,7 @@ impl<'tcx> TraitDef { paren_sugar, has_auto_impl, is_marker, + skip_array_during_method_dispatch, specialization_kind, def_path_hash, } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8edde8794e..e365928c15 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -18,10 +18,10 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; use rustc_target::abi::{Integer, Size, TargetDataLayout}; use smallvec::SmallVec; -use std::{cmp, fmt}; +use std::{fmt, iter}; #[derive(Copy, Clone, Debug)] pub struct Discr<'tcx> { @@ -135,21 +135,6 @@ impl IntTypeExt for attr::IntType { } } -/// Describes whether a type is representable. For types that are not -/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to -/// distinguish between types that are recursive with themselves and types that -/// contain a different recursive type. These cases can therefore be treated -/// differently when reporting errors. -/// -/// The ordering of the cases is significant. They are sorted so that cmp::max -/// will keep the "more erroneous" of two values. -#[derive(Clone, PartialOrd, Ord, Eq, PartialEq, Debug)] -pub enum Representability { - Representable, - ContainsRecursive, - SelfRecursive(Vec), -} - impl<'tcx> TyCtxt<'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. @@ -414,9 +399,7 @@ impl<'tcx> TyCtxt<'tcx> { _ => bug!(), }; - let result = item_substs - .iter() - .zip(impl_substs.iter()) + let result = iter::zip(item_substs, impl_substs) .filter(|&(_, k)| { match k.unpack() { GenericArgKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => { @@ -501,10 +484,9 @@ impl<'tcx> TyCtxt<'tcx> { self, closure_def_id: DefId, closure_substs: SubstsRef<'tcx>, - ) -> Option>> { + env_region: ty::RegionKind, + ) -> Option> { let closure_ty = self.mk_closure(closure_def_id, closure_substs); - let br = ty::BoundRegion { kind: ty::BrEnv }; - let env_region = ty::ReLateBound(ty::INNERMOST, br); let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { @@ -512,7 +494,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; - Some(ty::Binder::bind(env_ty)) + Some(env_ty) } /// Returns `true` if the node pointed to by `def_id` is a `static` item. @@ -701,7 +683,6 @@ impl<'tcx> ty::TyS<'tcx> { /// optimization as well as the rules around static values. Note /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. - // FIXME: use `TyCtxtAt` instead of separate `Span`. pub fn is_freeze(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self)) } @@ -741,6 +722,46 @@ impl<'tcx> ty::TyS<'tcx> { } } + /// Checks whether values of this type `T` implement the `Unpin` trait. + pub fn is_unpin(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self)) + } + + /// Fast path helper for testing if a type is `Unpin`. + /// + /// Returning true means the type is known to be `Unpin`. Returning + /// `false` means nothing -- could be `Unpin`, might not be. + fn is_trivially_unpin(&self) -> bool { + match self.kind() { + ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Bool + | ty::Char + | ty::Str + | ty::Never + | ty::Ref(..) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::Error(_) + | ty::FnPtr(_) => true, + ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_unpin), + ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), + ty::Adt(..) + | ty::Bound(..) + | ty::Closure(..) + | ty::Dynamic(..) + | ty::Foreign(_) + | ty::Generator(..) + | ty::GeneratorWitness(_) + | ty::Infer(_) + | ty::Opaque(..) + | ty::Param(_) + | ty::Placeholder(_) + | ty::Projection(_) => false, + } + } + /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely /// non-copy and *might* have a destructor attached; if it returns /// `false`, then `ty` definitely has no destructor (i.e., no drop glue). @@ -834,178 +855,6 @@ impl<'tcx> ty::TyS<'tcx> { } } - /// Check whether a type is representable. This means it cannot contain unboxed - /// structural recursion. This check is needed for structs and enums. - pub fn is_representable(&'tcx self, tcx: TyCtxt<'tcx>, sp: Span) -> Representability { - // Iterate until something non-representable is found - fn fold_repr>(iter: It) -> Representability { - iter.fold(Representability::Representable, |r1, r2| match (r1, r2) { - (Representability::SelfRecursive(v1), Representability::SelfRecursive(v2)) => { - Representability::SelfRecursive(v1.into_iter().chain(v2).collect()) - } - (r1, r2) => cmp::max(r1, r2), - }) - } - - fn are_inner_types_recursive<'tcx>( - tcx: TyCtxt<'tcx>, - sp: Span, - seen: &mut Vec>, - representable_cache: &mut FxHashMap, Representability>, - ty: Ty<'tcx>, - ) -> Representability { - match ty.kind() { - Tuple(..) => { - // Find non representable - fold_repr(ty.tuple_fields().map(|ty| { - is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) - })) - } - // Fixed-length vectors. - // FIXME(#11924) Behavior undecided for zero-length vectors. - Array(ty, _) => { - is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) - } - Adt(def, substs) => { - // Find non representable fields with their spans - fold_repr(def.all_fields().map(|field| { - let ty = field.ty(tcx, substs); - let span = match field - .did - .as_local() - .map(|id| tcx.hir().local_def_id_to_hir_id(id)) - .and_then(|id| tcx.hir().find(id)) - { - Some(hir::Node::Field(field)) => field.ty.span, - _ => sp, - }; - match is_type_structurally_recursive( - tcx, - span, - seen, - representable_cache, - ty, - ) { - Representability::SelfRecursive(_) => { - Representability::SelfRecursive(vec![span]) - } - x => x, - } - })) - } - Closure(..) => { - // this check is run on type definitions, so we don't expect - // to see closure types - bug!("requires check invoked on inapplicable type: {:?}", ty) - } - _ => Representability::Representable, - } - } - - fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool { - match *ty.kind() { - Adt(ty_def, _) => ty_def == def, - _ => false, - } - } - - // Does the type `ty` directly (without indirection through a pointer) - // contain any types on stack `seen`? - fn is_type_structurally_recursive<'tcx>( - tcx: TyCtxt<'tcx>, - sp: Span, - seen: &mut Vec>, - representable_cache: &mut FxHashMap, Representability>, - ty: Ty<'tcx>, - ) -> Representability { - debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp); - if let Some(representability) = representable_cache.get(ty) { - debug!( - "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}", - ty, sp, representability - ); - return representability.clone(); - } - - let representability = - is_type_structurally_recursive_inner(tcx, sp, seen, representable_cache, ty); - - representable_cache.insert(ty, representability.clone()); - representability - } - - fn is_type_structurally_recursive_inner<'tcx>( - tcx: TyCtxt<'tcx>, - sp: Span, - seen: &mut Vec>, - representable_cache: &mut FxHashMap, Representability>, - ty: Ty<'tcx>, - ) -> Representability { - match ty.kind() { - Adt(def, _) => { - { - // Iterate through stack of previously seen types. - let mut iter = seen.iter(); - - // The first item in `seen` is the type we are actually curious about. - // We want to return SelfRecursive if this type contains itself. - // It is important that we DON'T take generic parameters into account - // for this check, so that Bar in this example counts as SelfRecursive: - // - // struct Foo; - // struct Bar { x: Bar } - - if let Some(&seen_type) = iter.next() { - if same_struct_or_enum(seen_type, *def) { - debug!("SelfRecursive: {:?} contains {:?}", seen_type, ty); - return Representability::SelfRecursive(vec![sp]); - } - } - - // We also need to know whether the first item contains other types - // that are structurally recursive. If we don't catch this case, we - // will recurse infinitely for some inputs. - // - // It is important that we DO take generic parameters into account - // here, so that code like this is considered SelfRecursive, not - // ContainsRecursive: - // - // struct Foo { Option> } - - for &seen_type in iter { - if ty::TyS::same_type(ty, seen_type) { - debug!("ContainsRecursive: {:?} contains {:?}", seen_type, ty); - return Representability::ContainsRecursive; - } - } - } - - // For structs and enums, track all previously seen types by pushing them - // onto the 'seen' stack. - seen.push(ty); - let out = are_inner_types_recursive(tcx, sp, seen, representable_cache, ty); - seen.pop(); - out - } - _ => { - // No need to push in other cases. - are_inner_types_recursive(tcx, sp, seen, representable_cache, ty) - } - } - } - - debug!("is_type_representable: {:?}", self); - - // To avoid a stack overflow when checking an enum variant or struct that - // contains a different, structurally recursive type, maintain a stack - // of seen types and check recursion for each of them (issues #3008, #3779). - let mut seen: Vec> = Vec::new(); - let mut representable_cache = FxHashMap::default(); - let r = is_type_structurally_recursive(tcx, sp, &mut seen, &mut representable_cache, self); - debug!("is_type_representable: {:?} is {:?}", self, r); - r - } - /// Peel off all reference types in this type until there are none left. /// /// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`. diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index bb7fc661d2..c2fe5f1ef3 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -195,8 +195,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {} - ty::ConstKind::Unevaluated(_, substs, _) => { - stack.extend(substs.iter().rev()); + ty::ConstKind::Unevaluated(ct) => { + stack.extend(ct.substs.iter().rev()); } } } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index eb942b195b..9f19a474ca 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -197,7 +197,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } } - FnSelfUseKind::Normal { self_arg, implicit_into_iter } => { + FnSelfUseKind::Normal { + self_arg, + implicit_into_iter, + is_option_or_result, + } => { if implicit_into_iter { err.span_label( fn_call_span, @@ -215,6 +219,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ), ); } + if is_option_or_result { + err.span_suggestion_verbose( + fn_call_span.shrink_to_lo(), + "consider calling `.as_ref()` to borrow the type's contents", + "as_ref().".to_string(), + Applicability::MachineApplicable, + ); + } // Avoid pointing to the same function in multiple different // error messages. if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) @@ -264,7 +276,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() { let sess = self.infcx.tcx.sess; - if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) { + let ty = used_place.ty(self.body, self.infcx.tcx).ty; + // If we have a `&mut` ref, we need to reborrow. + if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() { + // If we are in a loop this will be suggested later. + if !is_loop_move { + err.span_suggestion_verbose( + move_span.shrink_to_lo(), + &format!( + "consider creating a fresh reborrow of {} here", + self.describe_place(moved_place.as_ref()) + .map(|n| format!("`{}`", n)) + .unwrap_or_else(|| "the mutable reference".to_string()), + ), + format!("&mut *"), + Applicability::MachineApplicable, + ); + } + } else if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) { err.span_suggestion( move_span, "consider borrowing to avoid moving into the for loop", @@ -1664,7 +1693,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if decl.can_be_made_mutable() { err.span_suggestion( decl.source_info.span, - "make this binding mutable", + "consider making this binding mutable", format!("mut {}", name), Applicability::MachineApplicable, ); @@ -1728,7 +1757,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { match statement { - Statement { kind: StatementKind::FakeRead(cause, box place), .. } + Statement { kind: StatementKind::FakeRead(box (cause, place)), .. } if *place == self.place => { self.cause = Some(*cause); diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs index 06e3f4b91f..2a388b8a72 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs @@ -515,7 +515,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let block = &self.body.basic_blocks()[location.block]; let kind = if let Some(&Statement { - kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), + kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)), .. }) = block.statements.get(location.statement_index) { diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index ec561fa385..aa9f18d999 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -7,8 +7,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItemGroup; use rustc_hir::GeneratorKind; use rustc_middle::mir::{ - AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place, - PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, + AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand, + Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt}; @@ -18,6 +18,7 @@ use rustc_span::{ Span, }; use rustc_target::abi::VariantIdx; +use std::iter; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; @@ -501,7 +502,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // lifetimes without names with the value `'0`. match ty.kind() { ty::Ref( - ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), _, _, @@ -522,7 +523,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let region = match ty.kind() { ty::Ref(region, _, _) => { match region { - ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { printer.region_highlight_mode.highlighting_bound_region(*br, counter) } @@ -572,7 +573,13 @@ pub(super) enum UseSpans<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub(super) enum FnSelfUseKind<'tcx> { /// A normal method call of the form `receiver.foo(a, b, c)` - Normal { self_arg: Ident, implicit_into_iter: bool }, + Normal { + self_arg: Ident, + implicit_into_iter: bool, + /// Whether the self type of the method call has an `.as_ref()` method. + /// Used for better diagnostics. + is_option_or_result: bool, + }, /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)` FnOnceCall, /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`) @@ -794,6 +801,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } + // StatementKind::FakeRead only contains a def_id if they are introduced as a result + // of pattern matching within a closure. + if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind { + match cause { + FakeReadCause::ForMatchedPlace(Some(closure_def_id)) + | FakeReadCause::ForLet(Some(closure_def_id)) => { + debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place); + let places = &[Operand::Move(*place)]; + if let Some((args_span, generator_kind, var_span)) = + self.closure_span(closure_def_id, moved_place, places) + { + return ClosureUse { generator_kind, args_span, var_span }; + } + } + _ => {} + } + } + let normal_ret = if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) { PatUse(stmt.source_info.span) @@ -881,7 +906,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn_call_span.desugaring_kind(), Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) ); - FnSelfUseKind::Normal { self_arg, implicit_into_iter } + let parent_self_ty = parent + .filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl) + .and_then(|did| match tcx.type_of(did).kind() { + ty::Adt(def, ..) => Some(def.did), + _ => None, + }); + let is_option_or_result = parent_self_ty.map_or(false, |def_id| { + tcx.is_diagnostic_item(sym::option_type, def_id) + || tcx.is_diagnostic_item(sym::result_type, def_id) + }); + FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result } }); return FnSelfUse { @@ -970,13 +1005,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr { - for (captured_place, place) in self - .infcx - .tcx - .typeck(def_id.expect_local()) - .closure_min_captures_flattened(def_id) - .zip(places) - { + for (captured_place, place) in iter::zip( + self.infcx.tcx.typeck(def_id.expect_local()).closure_min_captures_flattened(def_id), + places, + ) { let upvar_hir_id = captured_place.get_root_variable(); //FIXME(project-rfc-2229#8): Use better span from captured_place let span = self.infcx.tcx.upvars_mentioned(local_did)?[&upvar_hir_id].span; diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs index 7505e6e2dd..7dc3434bf3 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs @@ -1,4 +1,4 @@ -//! Contains utilities for generating suggestions for borrowck errors related to unsatisified +//! Contains utilities for generating suggestions for borrowck errors related to unsatisfied //! outlives constraints. use std::collections::BTreeMap; @@ -157,7 +157,7 @@ impl OutlivesSuggestionBuilder { debug!("Collected {:?}: {:?}", fr, outlived_fr); // Add to set of constraints for final help note. - self.constraints_to_add.entry(fr).or_insert(Vec::new()).push(outlived_fr); + self.constraints_to_add.entry(fr).or_default().push(outlived_fr); } /// Emit an intermediate note on the given `Diagnostic` if the involved regions are diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs index 03738f1b40..1f168c612f 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs @@ -1,4 +1,5 @@ use std::fmt::{self, Display}; +use std::iter; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; @@ -536,7 +537,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // just worry about trying to match up the rustc type // with the HIR types: (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { - search_stack.extend(elem_tys.iter().map(|k| k.expect_ty()).zip(*elem_hir_tys)); + search_stack + .extend(iter::zip(elem_tys.iter().map(|k| k.expect_ty()), *elem_hir_tys)); } (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty)) @@ -611,7 +613,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { args: &'hir hir::GenericArgs<'hir>, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>, ) -> Option<&'hir hir::Lifetime> { - for (kind, hir_arg) in substs.iter().zip(args.args) { + for (kind, hir_arg) in iter::zip(substs, args.args) { match (kind.unpack(), hir_arg) { (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => { if r.to_region_vid() == needle_fr { diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_mir/src/borrow_check/invalidation.rs index 17c4f3c649..e621bafb67 100644 --- a/compiler/rustc_mir/src/borrow_check/invalidation.rs +++ b/compiler/rustc_mir/src/borrow_check/invalidation.rs @@ -5,6 +5,7 @@ use rustc_middle::mir::{BorrowKind, Mutability, Operand}; use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; use rustc_middle::mir::{Statement, StatementKind}; use rustc_middle::ty::TyCtxt; +use std::iter; use crate::dataflow::indexes::BorrowIndex; @@ -62,14 +63,14 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.mutate_place(location, *lhs, Shallow(None), JustWrite); } - StatementKind::FakeRead(_, _) => { + StatementKind::FakeRead(box (_, _)) => { // Only relevant for initialized/liveness/safety checks. } StatementKind::SetDiscriminant { place, variant_index: _ } => { self.mutate_place(location, **place, Shallow(None), JustWrite); } StatementKind::LlvmInlineAsm(asm) => { - for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) { + for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) { if o.is_indirect { // FIXME(eddyb) indirect inline asm outputs should // be encoded through MIR place derefs instead. @@ -203,8 +204,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } => { for op in operands { match *op { - InlineAsmOperand::In { reg: _, ref value } - | InlineAsmOperand::Const { ref value } => { + InlineAsmOperand::In { reg: _, ref value } => { self.consume_operand(location, value); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { @@ -218,7 +218,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.mutate_place(location, out_place, Shallow(None), JustWrite); } } - InlineAsmOperand::SymFn { value: _ } + InlineAsmOperand::Const { value: _ } + | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } } diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 5b8bb7257e..2d1d83b165 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -25,6 +25,7 @@ use either::Either; use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; +use std::iter; use std::mem; use std::rc::Rc; @@ -573,7 +574,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc self.mutate_place(location, (*lhs, span), Shallow(None), JustWrite, flow_state); } - StatementKind::FakeRead(_, box ref place) => { + StatementKind::FakeRead(box (_, ref place)) => { // Read for match doesn't access any memory and is used to // assert that a place is safe and live. So we don't have to // do any checks here. @@ -595,7 +596,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc self.mutate_place(location, (**place, span), Shallow(None), JustWrite, flow_state); } StatementKind::LlvmInlineAsm(ref asm) => { - for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) { + for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) { if o.is_indirect { // FIXME(eddyb) indirect inline asm outputs should // be encoded through MIR place derefs instead. @@ -733,8 +734,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc } => { for op in operands { match *op { - InlineAsmOperand::In { reg: _, ref value } - | InlineAsmOperand::Const { ref value } => { + InlineAsmOperand::In { reg: _, ref value } => { self.consume_operand(loc, (value, span), flow_state); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { @@ -760,7 +760,8 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc ); } } - InlineAsmOperand::SymFn { value: _ } + InlineAsmOperand::Const { value: _ } + | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } } diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_mir/src/borrow_check/places_conflict.rs index 02c7b7dc20..3654b51949 100644 --- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs +++ b/compiler/rustc_mir/src/borrow_check/places_conflict.rs @@ -5,6 +5,7 @@ use rustc_hir as hir; use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, TyCtxt}; use std::cmp::max; +use std::iter; /// When checking if a place conflicts with another place, this enum is used to influence decisions /// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`. @@ -139,7 +140,7 @@ fn place_components_conflict<'tcx>( // loop invariant: borrow_c is always either equal to access_c or disjoint from it. for (i, (borrow_c, &access_c)) in - borrow_place.projection.iter().zip(access_place.projection.iter()).enumerate() + iter::zip(borrow_place.projection, access_place.projection).enumerate() { debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c); let borrow_proj_base = &borrow_place.projection[..i]; diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs b/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs index a272e922a5..7156612f47 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs @@ -1,5 +1,5 @@ //! This module provides linkage between RegionInferenceContext and -//! librustc_graphviz traits, specialized to attaching borrowck analysis +//! `rustc_graphviz` traits, specialized to attaching borrowck analysis //! data to rendered labels. use std::borrow::Cow; diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs index 77d9136622..1bb447d105 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs @@ -70,6 +70,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Equate expected input tys with those in the MIR. for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() { + if argument_index + 1 >= body.local_decls.len() { + self.tcx() + .sess + .delay_span_bug(body.span, "found more normalized_input_ty than local_decls"); + break; + } // In MIR, argument N is stored in local N+1. let local = Local::new(argument_index + 1); diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index cce1549cb2..d27fcb2f26 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -97,7 +97,7 @@ mod relate_tys; /// Type checks the given `mir` in the context of the inference /// context `infcx`. Returns any region constraints that have yet to -/// be proven. This result is includes liveness constraints that +/// be proven. This result includes liveness constraints that /// ensure that regions appearing in the types of all local variables /// are live at all points where that local variable may later be /// used. @@ -316,14 +316,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { let tcx = self.tcx(); let maybe_uneval = match constant.literal { ConstantKind::Ty(ct) => match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { - Some((def, substs, promoted)) - } + ty::ConstKind::Unevaluated(uv) => Some(uv), _ => None, }, _ => None, }; - if let Some((def, substs, promoted)) = maybe_uneval { + if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval { if let Some(promoted) = promoted { let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, promoted: &Body<'tcx>, @@ -1772,7 +1770,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } - for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() { + for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { @@ -2030,7 +2028,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { traits::ObligationCauseCode::RepeatVec(is_const_fn), ), self.param_env, - ty::Binder::bind(ty::TraitRef::new( + ty::Binder::dummy(ty::TraitRef::new( self.tcx().require_lang_item( LangItem::Copy, Some(self.last_span), diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs index 4b1acc1cd1..c2ac1e289c 100644 --- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs +++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs @@ -580,7 +580,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); let subst_mapping = - identity_substs.regions().zip(fr_substs.regions().map(|r| r.to_region_vid())); + iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid())); UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect() } } @@ -589,31 +589,45 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { &self, indices: &UniversalRegionIndices<'tcx>, defining_ty: DefiningTy<'tcx>, - ) -> ty::Binder<&'tcx ty::List>> { + ) -> ty::Binder<'tcx, &'tcx ty::List>> { let tcx = self.infcx.tcx; match defining_ty { DefiningTy::Closure(def_id, substs) => { assert_eq!(self.mir_def.did.to_def_id(), def_id); let closure_sig = substs.as_closure().sig(); let inputs_and_output = closure_sig.inputs_and_output(); - let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| { - // The "inputs" of the closure in the - // signature appear as a tuple. The MIR side - // flattens this tuple. - let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); - assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); - let inputs = match tuplized_inputs[0].kind() { - ty::Tuple(inputs) => inputs, - _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), - }; + let bound_vars = tcx.mk_bound_variable_kinds( + inputs_and_output + .bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BrEnv, + }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + + // The "inputs" of the closure in the + // signature appear as a tuple. The MIR side + // flattens this tuple. + let (&output, tuplized_inputs) = + inputs_and_output.skip_binder().split_last().unwrap(); + assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); + let inputs = match tuplized_inputs[0].kind() { + ty::Tuple(inputs) => inputs, + _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), + }; + ty::Binder::bind_with_vars( tcx.mk_type_list( iter::once(closure_ty) .chain(inputs.iter().map(|k| k.expect_ty())) .chain(iter::once(output)), - ) - }) + ), + bound_vars, + ) } DefiningTy::Generator(def_id, substs, movability) => { @@ -657,7 +671,7 @@ trait InferCtxtExt<'tcx> { &self, origin: NllRegionVariableOrigin, all_outlive_scope: LocalDefId, - value: ty::Binder, + value: ty::Binder<'tcx, T>, indices: &mut UniversalRegionIndices<'tcx>, ) -> T where @@ -686,7 +700,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { &self, origin: NllRegionVariableOrigin, all_outlive_scope: LocalDefId, - value: ty::Binder, + value: ty::Binder<'tcx, T>, indices: &mut UniversalRegionIndices<'tcx>, ) -> T where diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index fa234ff5fe..d51adc8864 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -5,6 +5,7 @@ use crate::interpret::{ Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar, ScalarMaybeUninit, StackPopCleanup, }; +use crate::util::pretty::display_allocation; use rustc_errors::ErrorReported; use rustc_hir::def::DefKind; @@ -360,6 +361,15 @@ pub fn eval_to_allocation_raw_provider<'tcx>( "it is undefined behavior to use this value", |mut diag| { diag.note(note_on_undefined_behavior_error()); + diag.note(&format!( + "the raw bytes of the constant ({}", + display_allocation( + *ecx.tcx, + ecx.tcx + .global_alloc(mplace.ptr.assert_ptr().alloc_id) + .unwrap_memory() + ) + )); diag.emit(); }, )) diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs index 8c18dfcb8d..40419a4d20 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs @@ -1,4 +1,3 @@ -use rustc_attr as attr; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::hir::map::blocks::FnLikeNode; @@ -34,54 +33,6 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { } } -/// Returns `true` if this function must conform to `min_const_fn` -pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - // Bail out if the signature doesn't contain `const` - if !tcx.is_const_fn_raw(def_id) { - return false; - } - - if tcx.features().staged_api { - // In order for a libstd function to be considered min_const_fn - // it needs to be stable and have no `rustc_const_unstable` attribute. - match tcx.lookup_const_stability(def_id) { - // `rustc_const_unstable` functions don't need to conform. - Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false, - None => { - if let Some(stab) = tcx.lookup_stability(def_id) { - if stab.level.is_stable() { - tcx.sess.delay_span_bug( - tcx.def_span(def_id), - "stable const functions must have either `rustc_const_stable` or \ - `rustc_const_unstable` attribute", - ); - // While we errored above, because we don't know if we need to conform, we - // err on the "safe" side and require min_const_fn. - true - } else { - // Unstable functions need not conform to min_const_fn. - false - } - } else { - // Internal functions are forced to conform to min_const_fn. - // Annotate the internal function with a const stability attribute if - // you need to use unstable features. - // Note: this is an arbitrary choice that does not affect stability or const - // safety or anything, it just changes whether we need to annotate some - // internal functions with `rustc_const_stable` or with `rustc_const_unstable` - true - } - } - // Everything else needs to conform, because it would be callable from - // other `min_const_fn` functions. - _ => true, - } - } else { - // users enabling the `const_fn` feature gate can do what they want - !tcx.features().const_fn - } -} - pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { let parent_id = tcx.hir().get_parent_did(hir_id); if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false } diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs index 61785a5272..8e9148f5b6 100644 --- a/compiler/rustc_mir/src/const_eval/machine.rs +++ b/compiler/rustc_mir/src/const_eval/machine.rs @@ -53,7 +53,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { /// Extra machine state for CTFE, and the Machine instance pub struct CompileTimeInterpreter<'mir, 'tcx> { /// For now, the number of terminators that can be evaluated before we throw a resource - /// exhuastion error. + /// exhaustion error. /// /// Setting this to `0` disables the limit and allows the interpreter to run forever. pub steps_remaining: usize, diff --git a/compiler/rustc_mir/src/const_eval/mod.rs b/compiler/rustc_mir/src/const_eval/mod.rs index 77531ae2c5..3f14efc920 100644 --- a/compiler/rustc_mir/src/const_eval/mod.rs +++ b/compiler/rustc_mir/src/const_eval/mod.rs @@ -110,7 +110,7 @@ fn const_to_valtree_inner<'tcx>( let variant = ecx.read_discriminant(&place.into()).unwrap().1; - branches(def.variants[variant].fields.len(), Some(variant)) + branches(def.variants[variant].fields.len(), def.is_enum().then_some(variant)) } ty::Never diff --git a/compiler/rustc_mir/src/dataflow/framework/cursor.rs b/compiler/rustc_mir/src/dataflow/framework/cursor.rs index 4942bed656..c000e49c14 100644 --- a/compiler/rustc_mir/src/dataflow/framework/cursor.rs +++ b/compiler/rustc_mir/src/dataflow/framework/cursor.rs @@ -64,10 +64,6 @@ where } } - pub fn body(&self) -> &'mir mir::Body<'tcx> { - self.body - } - /// Returns the underlying `Results`. pub fn results(&self) -> &Results<'tcx, A> { &self.results.borrow() diff --git a/compiler/rustc_mir/src/dataflow/framework/lattice.rs b/compiler/rustc_mir/src/dataflow/framework/lattice.rs index e7ef9267db..f937b31f4c 100644 --- a/compiler/rustc_mir/src/dataflow/framework/lattice.rs +++ b/compiler/rustc_mir/src/dataflow/framework/lattice.rs @@ -40,6 +40,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; +use std::iter; /// A [partially ordered set][poset] that has a [least upper bound][lub] for any pair of elements /// in the set. @@ -110,7 +111,7 @@ impl JoinSemiLattice for IndexVec { assert_eq!(self.len(), other.len()); let mut changed = false; - for (a, b) in self.iter_mut().zip(other.iter()) { + for (a, b) in iter::zip(self, other) { changed |= a.join(b); } changed @@ -122,7 +123,7 @@ impl MeetSemiLattice for IndexVec { assert_eq!(self.len(), other.len()); let mut changed = false; - for (a, b) in self.iter_mut().zip(other.iter()) { + for (a, b) in iter::zip(self, other) { changed |= a.meet(b); } changed diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir/src/dataflow/framework/mod.rs index 3f7808c209..344d7b9bec 100644 --- a/compiler/rustc_mir/src/dataflow/framework/mod.rs +++ b/compiler/rustc_mir/src/dataflow/framework/mod.rs @@ -510,7 +510,7 @@ impl EffectIndex { } } - /// Returns `true` if the effect at `self` should be applied eariler than the effect at `other` + /// Returns `true` if the effect at `self` should be applied earlier than the effect at `other` /// in forward order. fn precedes_in_forward_order(self, other: Self) -> bool { let ord = self diff --git a/compiler/rustc_mir/src/dataflow/impls/borrows.rs b/compiler/rustc_mir/src/dataflow/impls/borrows.rs index f24d0f0266..c92cff1433 100644 --- a/compiler/rustc_mir/src/dataflow/impls/borrows.rs +++ b/compiler/rustc_mir/src/dataflow/impls/borrows.rs @@ -11,6 +11,7 @@ use crate::borrow_check::{ use crate::dataflow::{self, fmt::DebugWithContext, GenKill}; use std::fmt; +use std::iter; rustc_index::newtype_index! { pub struct BorrowIndex { @@ -292,7 +293,7 @@ impl<'tcx> dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { } mir::StatementKind::LlvmInlineAsm(ref asm) => { - for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) { + for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) { if !kind.is_indirect && !kind.is_rw { self.kill_borrows_on_place(trans, *output); } diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs index 1ddd81e779..994b403abf 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs @@ -4,6 +4,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use smallvec::{smallvec, SmallVec}; +use std::iter; use std::mem; use super::abs_domain::Lift; @@ -292,11 +293,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } self.gather_rvalue(rval); } - StatementKind::FakeRead(_, place) => { - self.create_move_path(**place); + StatementKind::FakeRead(box (_, place)) => { + self.create_move_path(*place); } StatementKind::LlvmInlineAsm(ref asm) => { - for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) { + for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) { if !kind.is_indirect { self.gather_init(output.as_ref(), InitKind::Deep); } @@ -424,7 +425,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { for op in operands { match *op { InlineAsmOperand::In { reg: _, ref value } - | InlineAsmOperand::Const { ref value } => { + => { self.gather_operand(value); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { @@ -440,7 +441,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.gather_init(out_place.as_ref(), InitKind::Deep); } } - InlineAsmOperand::SymFn { value: _ } + InlineAsmOperand::Const { value: _ } + | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } } diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 149a9f81ea..2d83d6cfbd 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -232,6 +232,8 @@ impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> { /// this frame (can happen e.g. during frame initialization, and during unwinding on /// frames without cleanup code). /// We basically abuse `Result` as `Either`. + /// + /// Used by priroda. pub fn current_loc(&self) -> Result { self.loc } @@ -459,11 +461,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty.size.truncate(value) } - #[inline] - pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx, self.param_env) - } - #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { ty.is_freeze(self.tcx, self.param_env) @@ -527,6 +524,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + #[inline(always)] pub fn layout_of_local( &self, frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index 25c3c2c632..d74ef66a4b 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -171,8 +171,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; let val = self.tcx.const_eval_global_id(self.param_env, gid, Some(self.tcx.span))?; - let const_ = ty::Const { val: ty::ConstKind::Value(val), ty }; - let val = self.const_to_op(&const_, None)?; + let val = self.const_val_to_op(val, ty, Some(dest.layout))?; self.copy_op(&val, dest)?; } diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs index e1ec4cc5e9..ae5e78ee33 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs @@ -74,7 +74,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { let mut first = true; for p in predicates { diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 28933493a2..e5bc932026 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -77,14 +77,6 @@ impl<'tcx, Tag> Immediate { pub fn to_scalar(self) -> InterpResult<'tcx, Scalar> { self.to_scalar_or_uninit().check_init() } - - #[inline] - pub fn to_scalar_pair(self) -> InterpResult<'tcx, (Scalar, Scalar)> { - match self { - Immediate::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"), - Immediate::ScalarPair(a, b) => Ok((a.check_init()?, b.check_init()?)), - } - } } // ScalarPair needs a type to interpret, so we often have an immediate and a type together @@ -233,7 +225,7 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - /// Normalice `place.ptr` to a `Pointer` if this is a place and not a ZST. + /// 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( @@ -560,7 +552,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match val.val { ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)), - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { let instance = self.resolve(def, substs)?; Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()) } @@ -578,7 +570,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { match val { mir::ConstantKind::Ty(ct) => self.const_to_op(ct, layout), - mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, ty, None), + mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, ty, layout), } } diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index bf4eeb408e..f9adc27116 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -11,12 +11,12 @@ Rust MIR: a lowered representation of Rust. #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(map_try_insert)] #![feature(min_specialization)] @@ -26,7 +26,7 @@ Rust MIR: a lowered representation of Rust. #![feature(stmt_expr_attributes)] #![feature(trait_alias)] #![feature(option_get_or_insert_default)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(once_cell)] #![feature(control_flow_enum)] #![recursion_limit = "256"] diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 911224d8c1..fdefc89067 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -59,11 +59,15 @@ //! //! ### Discovering roots //! -//! The roots of the mono item graph correspond to the non-generic +//! The roots of the mono item graph correspond to the public non-generic //! syntactic items in the source code. We find them by walking the HIR of the -//! crate, and whenever we hit upon a function, method, or static item, we -//! create a mono item consisting of the items DefId and, since we only -//! consider non-generic items, an empty type-substitution set. +//! crate, and whenever we hit upon a public function, method, or static item, +//! we create a mono item consisting of the items DefId and, since we only +//! consider non-generic items, an empty type-substitution set. (In eager +//! collection mode, during incremental compilation, all non-generic functions +//! are considered as roots, as well as when the `-Clink-dead-code` option is +//! specified. Functions marked `#[no_mangle]` and functions called by inlinable +//! functions also always act as roots.) //! //! ### Finding neighbor nodes //! Given a mono item node, we can discover neighbors by inspecting its @@ -184,7 +188,6 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{AllocId, ConstValue}; use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; @@ -193,8 +196,11 @@ use rustc_middle::mir::{self, Local, Location}; use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; +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_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; +use rustc_target::abi::Size; use smallvec::SmallVec; use std::iter; use std::ops::Range; @@ -638,6 +644,35 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.super_rvalue(rvalue, location); } + /// This does not walk the constant, as it has been handled entirely here and trying + /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily + /// work, as some constants cannot be represented in the type system. + fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) { + let literal = self.monomorphize(constant.literal); + let val = match literal { + mir::ConstantKind::Val(val, _) => val, + mir::ConstantKind::Ty(ct) => match ct.val { + ty::ConstKind::Value(val) => val, + ty::ConstKind::Unevaluated(ct) => { + let param_env = ty::ParamEnv::reveal_all(); + match self.tcx.const_eval_resolve(param_env, ct, None) { + // The `monomorphize` call should have evaluated that constant already. + Ok(val) => val, + Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => return, + Err(ErrorHandled::TooGeneric) => span_bug!( + self.body.source_info(location).span, + "collection encountered polymorphic constant: {:?}", + literal + ), + } + } + _ => return, + }, + }; + collect_const_value(self.tcx, val, self.output); + self.visit_ty(literal.ty(), TyContext::Location(location)); + } + fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) { debug!("visiting const {:?} @ {:?}", *constant, location); @@ -646,9 +681,15 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match substituted_constant.val { ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output), - ty::ConstKind::Unevaluated(def, substs, promoted) => { - match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) { - Ok(val) => collect_const_value(self.tcx, val, self.output), + ty::ConstKind::Unevaluated(unevaluated) => { + match self.tcx.const_eval_resolve(param_env, unevaluated, None) { + // The `monomorphize` call should have evaluated that constant already. + Ok(val) => span_bug!( + self.body.source_info(location).span, + "collection encountered the unevaluated constant {} which evaluated to {:?}", + substituted_constant, + val + ), Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {} Err(ErrorHandled::TooGeneric) => span_bug!( self.body.source_info(location).span, @@ -714,6 +755,46 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.super_terminator(terminator, location); } + fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) { + self.super_operand(operand, location); + let limit = self.tcx.sess.move_size_limit(); + if limit == 0 { + return; + } + let limit = Size::from_bytes(limit); + let ty = operand.ty(self.body, self.tcx); + let ty = self.monomorphize(ty); + let layout = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)); + if let Ok(layout) = layout { + if layout.size > limit { + debug!(?layout); + let source_info = self.body.source_info(location); + debug!(?source_info); + let lint_root = source_info.scope.lint_root(&self.body.source_scopes); + debug!(?lint_root); + let lint_root = match lint_root { + Some(lint_root) => lint_root, + // This happens when the issue is in a function from a foreign crate that + // we monomorphized in the current crate. We can't get a `HirId` for things + // in other crates. + // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root + // but correct span? This would make the lint at least accept crate-level lint attributes. + None => return, + }; + self.tcx.struct_span_lint_hir( + LARGE_ASSIGNMENTS, + lint_root, + source_info.span, + |lint| { + let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes())); + err.span_label(source_info.span, "value moved from here"); + err.emit() + }, + ); + } + } + } + fn visit_local( &mut self, _place_local: &Local, @@ -985,7 +1066,7 @@ struct RootCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, mode: MonoItemCollectionMode, output: &'a mut Vec>>, - entry_fn: Option<(LocalDefId, EntryFnType)>, + entry_fn: Option<(DefId, EntryFnType)>, } impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { @@ -1073,7 +1154,7 @@ impl RootCollector<'_, 'v> { && match self.mode { MonoItemCollectionMode::Eager => true, MonoItemCollectionMode::Lazy => { - self.entry_fn.map(|(id, _)| id) == Some(def_id) + self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id) || self.tcx.is_reachable_non_generic(def_id) || self .tcx @@ -1175,7 +1256,8 @@ fn create_mono_items_for_default_impls<'tcx>( let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } + | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize] } }); diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs index d2586f0f84..9ca4b6687f 100644 --- a/compiler/rustc_mir/src/monomorphize/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/mod.rs @@ -8,14 +8,14 @@ pub mod collector; pub mod partitioning; pub mod polymorphize; -pub fn custom_coerce_unsize_info<'tcx>( +fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxt<'tcx>, source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); - let trait_ref = ty::Binder::bind(ty::TraitRef { + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id, substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]), }); diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index 05b0e3a7da..30e758c7fd 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(def, _, Some(p)) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)}) // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => @@ -310,10 +310,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.visit_body(&promoted[p]); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(def, unevaluated_substs, None) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) if self.tcx.def_kind(def.did) == DefKind::AnonConst => { - self.visit_child_body(def.did, unevaluated_substs); + self.visit_child_body(def.did, substs); ControlFlow::CONTINUE } _ => c.super_visit_with(self), diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index a18c1f7452..ffeaaf60a3 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -540,12 +540,17 @@ impl NonConstOp for UnionAccess { pub struct UnsizingCast; impl NonConstOp for UnsizingCast { fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - mcf_status_in_item(ccx) + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_unsize) + } } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - mcf_build_error( - ccx, + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_unsize, span, "unsizing casts to types besides slices are not allowed in const fn", ) @@ -642,12 +647,17 @@ pub mod ty { } fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - mcf_status_in_item(ccx) + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_trait_bound) + } } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - mcf_build_error( - ccx, + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_trait_bound, span, "trait bounds other than `Sized` on const fn parameters are unstable", ) @@ -672,21 +682,3 @@ pub mod ty { } } } - -fn mcf_status_in_item(ccx: &ConstCx<'_, '_>) -> Status { - if ccx.const_kind() != hir::ConstContext::ConstFn { - Status::Allowed - } else { - Status::Unstable(sym::const_fn) - } -} - -fn mcf_build_error(ccx: &ConstCx<'_, 'tcx>, span: Span, msg: &str) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!(ccx.tcx.sess, span, E0723, "{}", msg); - err.note( - "see issue #57563 \ - for more information", - ); - err.help("add `#![feature(const_fn)]` to the crate attributes to enable"); - err -} diff --git a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs index 1a2d932ba1..057092b8ef 100644 --- a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs @@ -79,7 +79,9 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { mir::TerminatorKind::Drop { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) { - return; + bug!( + "Drop elaboration left behind a Drop for a type that does not need dropping" + ); } if dropped_place.is_indirect() { @@ -87,6 +89,10 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { return; } + // Drop elaboration is not precise enough to accept code like + // `src/test/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option>` is + // initialized with `None` and never changed, it still emits drop glue. + // Hence we additionally check the qualifs here to allow more code to pass. if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) { // Use the span where the dropped local was declared for the error. let span = self.body.local_decls[dropped_place.local].source_info.span; diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs index 748f65cba2..ac8c748ea8 100644 --- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs @@ -29,11 +29,11 @@ pub fn in_any_value_of_ty( /// Normally, we would determine what qualifications apply to each type and error when an illegal /// operation is performed on such a type. However, this was found to be too imprecise, especially /// in the presence of `enum`s. If only a single variant of an enum has a certain qualification, we -/// needn't reject code unless it actually constructs and operates on the qualifed variant. +/// needn't reject code unless it actually constructs and operates on the qualified variant. /// /// To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a /// type-based one). Qualifications propagate structurally across variables: If a local (or a -/// projection of a local) is assigned a qualifed value, that local itself becomes qualifed. +/// projection of a local) is assigned a qualified value, that local itself becomes qualified. pub trait Qualif { /// The name of the file used to debug the dataflow analysis that computes this qualif. const ANALYSIS_NAME: &'static str; @@ -247,7 +247,7 @@ where // Check the qualifs of the value of `const` items. if let Some(ct) = constant.literal.const_for_ty() { - if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val { + if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val { assert!(promoted.is_none()); // Don't peek inside trait associated constants. if cx.tcx.trait_of_item(def.did).is_none() { diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 1ad7b8fbbd..63fc66f2b9 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -1,6 +1,6 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. -use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported}; +use rustc_errors::{Applicability, Diagnostic, ErrorReported}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem}; use rustc_index::bit_set::BitSet; @@ -234,13 +234,11 @@ impl Validator<'mir, 'tcx> { if self.is_const_stable_const_fn() { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) { - struct_span_err!( - self.ccx.tcx.sess, - self.span, - E0723, - "trait methods cannot be stable const fn" - ) - .emit(); + self.ccx + .tcx + .sess + .struct_span_err(self.span, "trait methods cannot be stable const fn") + .emit(); } } @@ -428,7 +426,7 @@ impl Validator<'mir, 'tcx> { ty::PredicateKind::Subtype(_) => { bug!("subtype predicate on function: {:#?}", predicate) } - ty::PredicateKind::Trait(pred, constness) => { + ty::PredicateKind::Trait(pred, _constness) => { if Some(pred.def_id()) == tcx.lang_items().sized_trait() { continue; } @@ -442,16 +440,7 @@ impl Validator<'mir, 'tcx> { // arguments when determining importance. let kind = LocalKind::Arg; - if constness == hir::Constness::Const { - self.check_op_spanned(ops::ty::TraitBound(kind), span); - } else if !tcx.features().const_fn - || self.ccx.is_const_stable_const_fn() - { - // HACK: We shouldn't need the conditional above, but trait - // bounds on containing impl blocks are wrongly being marked as - // "not-const". - self.check_op_spanned(ops::ty::TraitBound(kind), span); - } + self.check_op_spanned(ops::ty::TraitBound(kind), span); } // other kinds of bounds are either tautologies // or cause errors in other passes @@ -850,9 +839,12 @@ 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), - }), + Binder::bind( + TraitPredicate { + trait_ref: TraitRef::from_method(tcx, trait_id, substs), + }, + tcx, + ), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff --git a/compiler/rustc_mir/src/transform/check_packed_ref.rs b/compiler/rustc_mir/src/transform/check_packed_ref.rs index ee88daa83e..13b7221046 100644 --- a/compiler/rustc_mir/src/transform/check_packed_ref.rs +++ b/compiler/rustc_mir/src/transform/check_packed_ref.rs @@ -1,11 +1,18 @@ +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; +use rustc_span::symbol::sym; use crate::transform::MirPass; use crate::util; +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { unsafe_derive_on_repr_packed, ..*providers }; +} + pub struct CheckPackedRef; impl<'tcx> MirPass<'tcx> for CheckPackedRef { @@ -24,6 +31,41 @@ struct PackedRefChecker<'a, 'tcx> { source_info: SourceInfo, } +fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { + let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + + tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| { + // FIXME: when we make this a hard error, this should have its + // own error code. + let message = if tcx.generics_of(def_id).own_requires_monomorphization() { + "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ + type or const parameters (error E0133)" + .to_string() + } else { + "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ + does not derive Copy (error E0133)" + .to_string() + }; + lint.build(&message).emit() + }); +} + +fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + debug!("builtin_derive_def_id({:?})", def_id); + if let Some(impl_def_id) = tcx.impl_of_method(def_id) { + if tcx.has_attr(impl_def_id, sym::automatically_derived) { + debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); + Some(impl_def_id) + } else { + debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); + None + } + } else { + debug!("builtin_derive_def_id({:?}) - not a method", def_id); + None + } +} + impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Make sure we know where in the MIR we are. @@ -40,26 +82,33 @@ impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - let source_info = self.source_info; - let lint_root = self.body.source_scopes[source_info.scope] - .local_data - .as_ref() - .assert_crate_local() - .lint_root; - self.tcx.struct_span_lint_hir( - UNALIGNED_REFERENCES, - lint_root, - source_info.span, - |lint| { - lint.build("reference to packed field is unaligned") - .note( - "fields of packed structs are not properly aligned, and creating \ - a misaligned reference is undefined behavior (even if that \ - reference is never dereferenced)", - ) - .emit() - }, - ); + let def_id = self.body.source.instance.def_id(); + if let Some(impl_def_id) = builtin_derive_def_id(self.tcx, def_id) { + // If a method is defined in the local crate, + // the impl containing that method should also be. + self.tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local()); + } else { + let source_info = self.source_info; + let lint_root = self.body.source_scopes[source_info.scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; + self.tcx.struct_span_lint_hir( + UNALIGNED_REFERENCES, + lint_root, + source_info.span, + |lint| { + lint.build("reference to packed field is unaligned") + .note( + "fields of packed structs are not properly aligned, and creating \ + a misaligned reference is undefined behavior (even if that \ + reference is never dereferenced)", + ) + .emit() + }, + ); + } } } } diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs index 532d201e05..955be8cc81 100644 --- a/compiler/rustc_mir/src/transform/check_unsafety.rs +++ b/compiler/rustc_mir/src/transform/check_unsafety.rs @@ -10,20 +10,15 @@ 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::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; +use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; -use rustc_span::symbol::sym; use std::ops::Bound; -use crate::const_eval::is_min_const_fn; -use crate::util; - pub struct UnsafetyChecker<'a, 'tcx> { body: &'a Body<'tcx>, body_did: LocalDefId, const_context: bool, - min_const_fn: bool, violations: Vec, source_info: SourceInfo, tcx: TyCtxt<'tcx>, @@ -36,21 +31,15 @@ pub struct UnsafetyChecker<'a, 'tcx> { impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { fn new( const_context: bool, - min_const_fn: bool, body: &'a Body<'tcx>, body_did: LocalDefId, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Self { - // sanity check - if min_const_fn { - assert!(const_context); - } Self { body, body_did, const_context, - min_const_fn, violations: vec![], source_info: SourceInfo::outermost(body.span), tcx, @@ -86,7 +75,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { let sig = func_ty.fn_sig(self.tcx); if let hir::Unsafety::Unsafe = sig.unsafety() { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::CallToUnsafeFunction, ) } @@ -136,7 +125,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { match self.tcx.layout_scalar_valid_range(def.did) { (Bound::Unbounded, Bound::Unbounded) => {} _ => self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::InitializingTypeWith, ), } @@ -182,18 +171,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.check_mut_borrowing_layout_constrained_field(*place, context.is_mutating_use()); } - // Check for borrows to packed fields. - // `is_disaligned` already traverses the place to consider all projections after the last - // `Deref`, so this only needs to be called once at the top level. - if context.is_borrow() { - if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - self.require_unsafe( - UnsafetyViolationKind::BorrowPacked, - UnsafetyViolationDetails::BorrowOfPackedField, - ); - } - } - // Some checks below need the extra metainfo of the local declaration. let decl = &self.body.local_decls[place.local]; @@ -227,7 +204,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { let base_ty = base.ty(self.body, self.tcx).ty; if base_ty.is_unsafe_ptr() { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::DerefOfRawPointer, ) } @@ -272,7 +249,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { ); if !nodrop { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::AssignToDroppingUnionField, ); } else { @@ -280,7 +257,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } } else { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::AccessToUnionField, ) } @@ -291,6 +268,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) { + // Violations can turn out to be `UnsafeFn` during analysis, but they should not start out as such. + assert_ne!(kind, UnsafetyViolationKind::UnsafeFn); + let source_info = self.source_info; let lint_root = self.body.source_scopes[self.source_info.scope] .local_data @@ -317,25 +297,14 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { // `unsafe` blocks are required in safe code Safety::Safe => { for violation in violations { - let mut violation = *violation; match violation.kind { - UnsafetyViolationKind::GeneralAndConstFn - | UnsafetyViolationKind::General => {} - UnsafetyViolationKind::BorrowPacked => { - if self.min_const_fn { - // const fns don't need to be backwards compatible and can - // emit these violations as a hard error instead of a backwards - // compat lint - violation.kind = UnsafetyViolationKind::General; - } - } - UnsafetyViolationKind::UnsafeFn - | UnsafetyViolationKind::UnsafeFnBorrowPacked => { + UnsafetyViolationKind::General => {} + UnsafetyViolationKind::UnsafeFn => { bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") } } - if !self.violations.contains(&violation) { - self.violations.push(violation) + if !self.violations.contains(violation) { + self.violations.push(*violation) } } false @@ -345,11 +314,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { for violation in violations { let mut violation = *violation; - if violation.kind == UnsafetyViolationKind::BorrowPacked { - violation.kind = UnsafetyViolationKind::UnsafeFnBorrowPacked; - } else { - violation.kind = UnsafetyViolationKind::UnsafeFn; - } + violation.kind = UnsafetyViolationKind::UnsafeFn; if !self.violations.contains(&violation) { self.violations.push(violation) } @@ -362,31 +327,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { if !violations.is_empty() { self.used_unsafe.insert(hir_id); } - // only some unsafety is allowed in const fn - if self.min_const_fn { - for violation in violations { - match violation.kind { - // these unsafe things are stable in const fn - UnsafetyViolationKind::GeneralAndConstFn => {} - // these things are forbidden in const fns - UnsafetyViolationKind::General - | UnsafetyViolationKind::BorrowPacked => { - let mut violation = *violation; - // const fns don't need to be backwards compatible and can - // emit these violations as a hard error instead of a backwards - // compat lint - violation.kind = UnsafetyViolationKind::General; - if !self.violations.contains(&violation) { - self.violations.push(violation) - } - } - UnsafetyViolationKind::UnsafeFn - | UnsafetyViolationKind::UnsafeFnBorrowPacked => bug!( - "`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context" - ), - } - } - } true } }; @@ -424,7 +364,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { } else { continue; }; - self.require_unsafe(UnsafetyViolationKind::GeneralAndConstFn, details); + self.require_unsafe(UnsafetyViolationKind::General, details); } } } @@ -442,7 +382,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { // Is `callee_features` a subset of `calling_features`? if !callee_features.iter().all(|feature| self_features.contains(feature)) { self.require_unsafe( - UnsafetyViolationKind::GeneralAndConstFn, + UnsafetyViolationKind::General, UnsafetyViolationDetails::CallToFunctionWith, ) } @@ -464,7 +404,6 @@ pub(crate) fn provide(providers: &mut Providers) { ty::WithOptConstParam { did, const_param_did: Some(param_did) }, ) }, - unsafe_derive_on_repr_packed, ..*providers }; } @@ -525,15 +464,12 @@ 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, min_const_fn) = match tcx.hir().body_owner_kind(id) { - hir::BodyOwnerKind::Closure => (false, false), - hir::BodyOwnerKind::Fn => { - (tcx.is_const_fn_raw(def.did.to_def_id()), is_min_const_fn(tcx, def.did.to_def_id())) - } - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false), + 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, min_const_fn, body, def.did, tcx, param_env); + let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env); checker.visit_body(&body); check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks); @@ -544,25 +480,6 @@ fn unsafety_check_result<'tcx>( }) } -fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - - tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| { - // FIXME: when we make this a hard error, this should have its - // own error code. - let message = if tcx.generics_of(def_id).own_requires_monomorphization() { - "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ - type or const parameters (error E0133)" - .to_string() - } else { - "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ - does not derive Copy (error E0133)" - .to_string() - }; - lint.build(&message).emit() - }); -} - /// Returns the `HirId` for an enclosing scope that is also `unsafe`. fn is_enclosed( tcx: TyCtxt<'_>, @@ -609,22 +526,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet, id }); } -fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - debug!("builtin_derive_def_id({:?})", def_id); - if let Some(impl_def_id) = tcx.impl_of_method(def_id) { - if tcx.has_attr(impl_def_id, sym::automatically_derived) { - debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); - Some(impl_def_id) - } else { - debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); - None - } - } else { - debug!("builtin_derive_def_id({:?}) - not a method", def_id); - None - } -} - pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { debug!("check_unsafety({:?})", def_id); @@ -643,7 +544,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" }; match kind { - UnsafetyViolationKind::GeneralAndConstFn | UnsafetyViolationKind::General => { + UnsafetyViolationKind::General => { // once struct_span_err!( tcx.sess, @@ -657,27 +558,6 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { .note(note) .emit(); } - UnsafetyViolationKind::BorrowPacked => { - if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id.to_def_id()) { - // If a method is defined in the local crate, - // the impl containing that method should also be. - tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local()); - } else { - tcx.struct_span_lint_hir( - SAFE_PACKED_BORROWS, - lint_root, - source_info.span, - |lint| { - lint.build(&format!( - "{} is unsafe and requires unsafe{} block (error E0133)", - description, unsafe_fn_msg, - )) - .note(note) - .emit() - }, - ) - } - } UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir( UNSAFE_OP_IN_UNSAFE_FN, lint_root, @@ -692,35 +572,6 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { .emit(); }, ), - UnsafetyViolationKind::UnsafeFnBorrowPacked => { - // When `unsafe_op_in_unsafe_fn` is disallowed, the behavior of safe and unsafe functions - // should be the same in terms of warnings and errors. Therefore, with `#[warn(safe_packed_borrows)]`, - // a safe packed borrow should emit a warning *but not an error* in an unsafe function, - // just like in a safe function, even if `unsafe_op_in_unsafe_fn` is `deny`. - // - // Also, `#[warn(unsafe_op_in_unsafe_fn)]` can't cause any new errors. Therefore, with - // `#[deny(safe_packed_borrows)]` and `#[warn(unsafe_op_in_unsafe_fn)]`, a packed borrow - // should only issue a warning for the sake of backwards compatibility. - // - // The solution those 2 expectations is to always take the minimum of both lints. - // This prevent any new errors (unless both lints are explicitly set to `deny`). - let lint = if tcx.lint_level_at_node(SAFE_PACKED_BORROWS, lint_root).0 - <= tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, lint_root).0 - { - SAFE_PACKED_BORROWS - } else { - UNSAFE_OP_IN_UNSAFE_FN - }; - tcx.struct_span_lint_hir(&lint, lint_root, source_info.span, |lint| { - lint.build(&format!( - "{} is unsafe and requires unsafe block (error E0133)", - description, - )) - .span_label(source_info.span, description) - .note(note) - .emit(); - }) - } } } diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index cc8669d970..5968bbbfca 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -13,9 +13,9 @@ use rustc_middle::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc_middle::mir::{ - AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, ConstantKind, Local, LocalDecl, - LocalKind, Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, - Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, + AssertKind, BasicBlock, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, LocalKind, + Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, + StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; @@ -440,18 +440,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } fn lint_root(&self, source_info: SourceInfo) -> Option { - let mut data = &self.source_scopes[source_info.scope]; - // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it - // does not work as I thought it would. Needs more investigation and documentation. - while data.inlined.is_some() { - trace!(?data); - data = &self.source_scopes[data.parent_scope.unwrap()]; - } - trace!(?data); - match &data.local_data { - ClearCrossCrate::Set(data) => Some(data.lint_root), - ClearCrossCrate::Clear => None, - } + source_info.scope.lint_root(&self.source_scopes) } fn use_ecx(&mut self, f: F) -> Option @@ -491,7 +480,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let lint_only = match c.literal { ConstantKind::Ty(ct) => match ct.val { // Promoteds must lint and not error as the user didn't ask for them - ConstKind::Unevaluated(_, _, Some(_)) => true, + ConstKind::Unevaluated(ty::Unevaluated { + def: _, + substs: _, + promoted: Some(_), + }) => true, // Out of backwards compatibility we cannot report hard errors in unused // generic functions using associated constants of the generic parameters. _ => c.literal.needs_subst(), diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index aabfee53ac..4836148309 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -121,6 +121,7 @@ use rustc_middle::mir::coverage::*; use rustc_middle::mir::{self, BasicBlock, TerminatorKind}; use rustc_middle::ty::TyCtxt; +use std::iter; use std::lazy::SyncOnceCell; pub const NESTED_INDENT: &str = " "; @@ -703,9 +704,7 @@ pub(super) fn dump_coverage_graphviz( let edge_counters = from_terminator .successors() .map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); - edge_labels - .iter() - .zip(edge_counters) + iter::zip(&edge_labels, edge_counters) .map(|(label, some_counter)| { if let Some(counter) = some_counter { format!("{}\n{}", label, debug_counters.format_counter(counter)) @@ -817,7 +816,7 @@ fn bcb_to_string_sections( sections } -/// Returns a simple string representation of a `TerminatorKind` variant, indenpendent of any +/// Returns a simple string representation of a `TerminatorKind` variant, independent of any /// values it might hold. pub(super) fn term_type(kind: &TerminatorKind<'tcx>) -> &'static str { match kind { diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index 93133e9b7f..eaeb44289c 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -23,6 +23,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::hir; use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::ich::StableHashingContext; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::*; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator, @@ -87,6 +88,11 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { _ => {} } + let codegen_fn_attrs = tcx.codegen_fn_attrs(mir_source.def_id()); + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { + return; + } + trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); @@ -111,7 +117,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let body_span = hir_body.value.span; let source_file = source_map.lookup_source_file(body_span.lo()); let fn_sig_span = match some_fn_sig.filter(|fn_sig| { - Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.hi())) + fn_sig.span.ctxt() == body_span.ctxt() + && Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.lo())) }) { Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()), None => body_span.shrink_to_lo(), diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs index de8447f197..2ba9d1bdc0 100644 --- a/compiler/rustc_mir/src/transform/coverage/query.rs +++ b/compiler/rustc_mir/src/transform/coverage/query.rs @@ -6,10 +6,9 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; -/// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each -/// counter) and `FunctionCoverage::new()` (to extract the coverage map metadata from the MIR). +/// A `query` provider for retrieving coverage information injected into MIR. pub(crate) fn provide(providers: &mut Providers) { - providers.coverageinfo = |tcx, def_id| coverageinfo_from_mir(tcx, def_id); + providers.coverageinfo = |tcx, def_id| coverageinfo(tcx, def_id); providers.covered_file_name = |tcx, def_id| covered_file_name(tcx, def_id); providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id); } @@ -121,7 +120,7 @@ impl CoverageVisitor { } } -fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo { +fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo { let mir_body = mir_body(tcx, def_id); let mut coverage_visitor = CoverageVisitor { @@ -139,29 +138,22 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo } fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { - let body = mir_body(tcx, def_id); - for bb_data in body.basic_blocks().iter() { - for statement in bb_data.statements.iter() { - if let StatementKind::Coverage(box ref coverage) = statement.kind { - if let Some(code_region) = coverage.code_region.as_ref() { - if is_inlined(body, statement) { - continue; + if tcx.is_mir_available(def_id) { + let body = mir_body(tcx, def_id); + for bb_data in body.basic_blocks().iter() { + for statement in bb_data.statements.iter() { + if let StatementKind::Coverage(box ref coverage) = statement.kind { + if let Some(code_region) = coverage.code_region.as_ref() { + if is_inlined(body, statement) { + continue; + } + return Some(code_region.file_name); } - return Some(code_region.file_name); } } } } - None -} - -/// This function ensures we obtain the correct MIR for the given item irrespective of -/// whether that means const mir or runtime mir. For `const fn` this opts for runtime -/// mir. -fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> { - let id = ty::WithOptConstParam::unknown(def_id); - let def = ty::InstanceDef::Item(id); - tcx.instance_mir(def) + return None; } fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> { @@ -188,3 +180,12 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { let scope_data = &body.source_scopes[statement.source_info.scope]; scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() } + +/// This function ensures we obtain the correct MIR for the given item irrespective of +/// whether that means const mir or runtime mir. For `const fn` this opts for runtime +/// mir. +fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> { + let id = ty::WithOptConstParam::unknown(def_id); + let def = ty::InstanceDef::Item(id); + tcx.instance_mir(def) +} diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs index e7097ce861..2041109eb3 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir/src/transform/coverage/spans.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use rustc_span::source_map::original_sp; -use rustc_span::{BytePos, Span, SyntaxContext}; +use rustc_span::{BytePos, Span}; use std::cmp::Ordering; @@ -240,7 +240,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { /// to be). pub(super) fn generate_coverage_spans( mir_body: &'a mir::Body<'tcx>, - fn_sig_span: Span, + fn_sig_span: Span, // Ensured to be same SourceFile and SyntaxContext as `body_span` body_span: Span, basic_coverage_blocks: &'a CoverageGraph, ) -> Vec { @@ -683,10 +683,10 @@ pub(super) fn filtered_statement_span( // and `_1` is the `Place` for `somenum`. // // If and when the Issue is resolved, remove this special case match pattern: - StatementKind::FakeRead(cause, _) if cause == FakeReadCause::ForGuardBinding => None, + StatementKind::FakeRead(box (cause, _)) if cause == FakeReadCause::ForGuardBinding => None, // Retain spans from all other statements - StatementKind::FakeRead(_, _) // Not including `ForGuardBinding` + StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` | StatementKind::CopyNonOverlapping(..) | StatementKind::Assign(_) | StatementKind::SetDiscriminant { .. } @@ -717,11 +717,21 @@ pub(super) fn filtered_terminator_span( | TerminatorKind::FalseEdge { .. } | TerminatorKind::Goto { .. } => None, + // Call `func` operand can have a more specific span when part of a chain of calls + | TerminatorKind::Call { ref func, .. } => { + let mut span = terminator.source_info.span; + if let mir::Operand::Constant(box constant) = func { + if constant.span.lo() > span.lo() { + span = span.with_lo(constant.span.lo()); + } + } + Some(function_source_span(span, body_span)) + } + // Retain spans from all other terminators TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Return - | TerminatorKind::Call { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseUnwind { .. } @@ -733,6 +743,6 @@ pub(super) fn filtered_terminator_span( #[inline] fn function_source_span(span: Span, body_span: Span) -> Span { - let span = original_sp(span, body_span).with_ctxt(SyntaxContext::root()); + let span = original_sp(span, body_span).with_ctxt(body_span.ctxt()); if body_span.contains(span) { span } else { body_span } } diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir/src/transform/coverage/tests.rs index 7a9bfaad88..dee112443d 100644 --- a/compiler/rustc_mir/src/transform/coverage/tests.rs +++ b/compiler/rustc_mir/src/transform/coverage/tests.rs @@ -17,7 +17,7 @@ //! Also note, some basic features of `Span` also rely on the `Span`s own "session globals", which //! 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 comparitively simpler. The easiest way is to wrap the test in a closure argument +//! 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(); })`. use super::counters; diff --git a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs index e102512e1f..c41e71e09a 100644 --- a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs +++ b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs @@ -1,7 +1,7 @@ //! This pass finds basic blocks that are completely equal, //! and replaces all uses with just one of them. -use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher}; +use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter}; use crate::transform::MirPass; @@ -115,11 +115,7 @@ impl<'tcx, 'a> PartialEq for BasicBlockHashable<'tcx, 'a> { fn eq(&self, other: &Self) -> bool { self.basic_block_data.statements.len() == other.basic_block_data.statements.len() && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind - && self - .basic_block_data - .statements - .iter() - .zip(&other.basic_block_data.statements) + && iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements) .all(|(x, y)| statement_eq(&x.kind, &y.kind)) } } diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 6656deac96..29df86ca6c 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -720,9 +720,6 @@ impl Conflicts<'a> { } } } - InlineAsmOperand::Const { value } => { - assert!(value.place().is_none()); - } InlineAsmOperand::InOut { reg: _, late: _, @@ -731,6 +728,7 @@ impl Conflicts<'a> { } | InlineAsmOperand::In { reg: _, value: _ } | InlineAsmOperand::Out { reg: _, late: _, place: None } + | InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } | InlineAsmOperand::SymStatic { def_id: _ } => {} } diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs index c85e9b9b93..003003a8ab 100644 --- a/compiler/rustc_mir/src/transform/generator.rs +++ b/compiler/rustc_mir/src/transform/generator.rs @@ -751,9 +751,10 @@ fn sanitize_witness<'tcx>( span_bug!( body.span, "Broken MIR: generator contains type {} in MIR, \ - but typeck only knows about {}", - decl.ty, - witness, + but typeck only knows about {} and {:?}", + decl_ty, + allowed, + allowed_upvars ); } } diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index 12fdbd6582..b6f80763bc 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -630,7 +630,7 @@ impl Inliner<'tcx> { caller_body.required_consts.extend( callee_body.required_consts.iter().copied().filter(|&ct| { match ct.literal.const_for_ty() { - Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)), + Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_)), None => true, } }), diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index d04a7011ab..f7a9835353 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -1,6 +1,7 @@ use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use std::iter; use super::simplify::simplify_cfg; @@ -83,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { if first_stmts.len() != scnd_stmts.len() { continue; } - for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) { + for (f, s) in iter::zip(first_stmts, scnd_stmts) { match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. (f_s, s_s) if f_s == s_s => {} @@ -113,7 +114,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { // and bb_idx has a different terminator from both of them. let (from, first, second) = bbs.pick3_mut(bb_idx, first, second); - let new_stmts = first.statements.iter().zip(second.statements.iter()).map(|(f, s)| { + let new_stmts = iter::zip(&first.statements, &second.statements).map(|(f, s)| { match (&f.kind, &s.kind) { (f_s, s_s) if f_s == s_s => (*f).clone(), diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 13546442f6..5c49ee69ed 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -44,6 +44,7 @@ pub mod promote_consts; pub mod remove_noop_landing_pads; pub mod remove_storage_markers; pub mod remove_unneeded_drops; +pub mod remove_zsts; pub mod required_consts; pub mod rustc_peek; pub mod simplify; @@ -58,6 +59,7 @@ pub use rustc_middle::mir::MirSource; pub(crate) fn provide(providers: &mut Providers) { self::check_unsafety::provide(providers); + self::check_packed_ref::provide(providers); *providers = Providers { mir_keys, mir_const, @@ -313,11 +315,8 @@ fn mir_promoted( &simplify::SimplifyCfg::new("promote-consts"), ]; - let opt_coverage: &[&dyn MirPass<'tcx>] = if tcx.sess.opts.debugging_opts.instrument_coverage { - &[&coverage::InstrumentCoverage] - } else { - &[] - }; + let opt_coverage: &[&dyn MirPass<'tcx>] = + if tcx.sess.instrument_coverage() { &[&coverage::InstrumentCoverage] } else { &[] }; run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]); @@ -494,6 +493,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // The main optimizations that we do on MIR. let optimizations: &[&dyn MirPass<'tcx>] = &[ &remove_storage_markers::RemoveStorageMarkers, + &remove_zsts::RemoveZsts, &const_goto::ConstGoto, &remove_unneeded_drops::RemoveUnneededDrops, &match_branches::MatchBranchSimplification, diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 7db790cf32..1bbaf833c4 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -108,9 +108,6 @@ pub enum Candidate { /// the attribute currently provides the semantic requirement that arguments /// must be constant. Argument { bb: BasicBlock, index: usize }, - - /// `const` operand in asm!. - InlineAsm { bb: BasicBlock, index: usize }, } impl Candidate { @@ -118,16 +115,14 @@ impl Candidate { fn forces_explicit_promotion(&self) -> bool { match self { Candidate::Ref(_) => false, - Candidate::Argument { .. } | Candidate::InlineAsm { .. } => true, + Candidate::Argument { .. } => true, } } fn source_info(&self, body: &Body<'_>) -> SourceInfo { match self { Candidate::Ref(location) => *body.source_info(*location), - Candidate::Argument { bb, .. } | Candidate::InlineAsm { bb, .. } => { - *body.source_info(body.terminator_loc(*bb)) - } + Candidate::Argument { bb, .. } => *body.source_info(body.terminator_loc(*bb)), } } } @@ -217,36 +212,25 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { self.super_terminator(terminator, location); - match terminator.kind { - TerminatorKind::Call { ref func, .. } => { - if let ty::FnDef(def_id, _) = *func.ty(self.ccx.body, self.ccx.tcx).kind() { - let fn_sig = self.ccx.tcx.fn_sig(def_id); - if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { - let name = self.ccx.tcx.item_name(def_id); - // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles. - if name.as_str().starts_with("simd_shuffle") { - self.candidates - .push(Candidate::Argument { bb: location.block, index: 2 }); - - return; // Don't double count `simd_shuffle` candidates - } - } + if let TerminatorKind::Call { ref func, .. } = terminator.kind { + if let ty::FnDef(def_id, _) = *func.ty(self.ccx.body, self.ccx.tcx).kind() { + let fn_sig = self.ccx.tcx.fn_sig(def_id); + if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { + let name = self.ccx.tcx.item_name(def_id); + // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles. + if name.as_str().starts_with("simd_shuffle") { + self.candidates.push(Candidate::Argument { bb: location.block, index: 2 }); - if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) { - for index in constant_args { - self.candidates.push(Candidate::Argument { bb: location.block, index }); - } + return; // Don't double count `simd_shuffle` candidates } } - } - TerminatorKind::InlineAsm { ref operands, .. } => { - for (index, op) in operands.iter().enumerate() { - if let InlineAsmOperand::Const { .. } = op { - self.candidates.push(Candidate::InlineAsm { bb: location.block, index }) + + if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) { + for index in constant_args { + self.candidates.push(Candidate::Argument { bb: location.block, index }); } } } - _ => {} } } } @@ -335,18 +319,6 @@ impl<'tcx> Validator<'_, 'tcx> { _ => bug!(), } } - Candidate::InlineAsm { bb, index } => { - assert!(self.explicit); - - let terminator = self.body[bb].terminator(); - match &terminator.kind { - TerminatorKind::InlineAsm { operands, .. } => match &operands[index] { - InlineAsmOperand::Const { value } => self.validate_operand(value), - _ => bug!(), - }, - _ => bug!(), - } - } } } @@ -818,9 +790,7 @@ pub fn validate_candidates( } match candidate { - Candidate::Argument { bb, index } | Candidate::InlineAsm { bb, index } - if !is_promotable => - { + Candidate::Argument { bb, index } if !is_promotable => { let span = ccx.body[bb].terminator().source_info.span; let msg = format!("argument {} is required to be a constant", index + 1); ccx.tcx.sess.span_err(span, &msg); @@ -1001,17 +971,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { literal: tcx .mk_const(ty::Const { ty, - val: ty::ConstKind::Unevaluated( + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, - InternalSubsts::for_item(tcx, def.did, |param, _| { + substs: InternalSubsts::for_item(tcx, def.did, |param, _| { if let ty::GenericParamDefKind::Lifetime = param.kind { tcx.lifetimes.re_erased.into() } else { tcx.mk_param_from_def(param) } }), - Some(promoted_id), - ), + promoted: Some(promoted_id), + }), }) .into(), })) @@ -1089,24 +1059,6 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { _ => bug!(), } } - Candidate::InlineAsm { bb, index } => { - let terminator = blocks[bb].terminator_mut(); - match terminator.kind { - TerminatorKind::InlineAsm { ref mut operands, .. } => { - match &mut operands[index] { - InlineAsmOperand::Const { ref mut value } => { - let ty = value.ty(local_decls, self.tcx); - let span = terminator.source_info.span; - - Rvalue::Use(mem::replace(value, promoted_operand(ty, span))) - } - _ => bug!(), - } - } - - _ => bug!(), - } - } } }; @@ -1161,7 +1113,7 @@ pub fn promote_candidates<'tcx>( } } } - Candidate::Argument { .. } | Candidate::InlineAsm { .. } => {} + Candidate::Argument { .. } => {} } // Declare return place local so that `mir::Body::new` doesn't complain. diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir/src/transform/remove_zsts.rs new file mode 100644 index 0000000000..70f7538dd5 --- /dev/null +++ b/compiler/rustc_mir/src/transform/remove_zsts.rs @@ -0,0 +1,89 @@ +//! Removes assignments to ZST places. + +use crate::transform::MirPass; +use rustc_middle::mir::tcx::PlaceTy; +use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind}; +use rustc_middle::ty::{self, Ty, TyCtxt}; + +pub struct RemoveZsts; + +impl<'tcx> MirPass<'tcx> for RemoveZsts { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if tcx.sess.mir_opt_level() < 3 { + return; + } + let param_env = tcx.param_env(body.source.def_id()); + let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + for block in basic_blocks.iter_mut() { + for statement in block.statements.iter_mut() { + match statement.kind { + StatementKind::Assign(box (place, _)) => { + let place_ty = place.ty(local_decls, tcx).ty; + if !maybe_zst(place_ty) { + continue; + } + let layout = match tcx.layout_of(param_env.and(place_ty)) { + Ok(layout) => layout, + Err(_) => continue, + }; + if !layout.is_zst() { + continue; + } + if involves_a_union(place, local_decls, tcx) { + continue; + } + if tcx.consider_optimizing(|| { + format!( + "RemoveZsts - Place: {:?} SourceInfo: {:?}", + place, statement.source_info + ) + }) { + statement.make_nop(); + } + } + _ => {} + } + } + } + } +} + +/// A cheap, approximate check to avoid unnecessary `layout_of` calls. +fn maybe_zst(ty: Ty<'_>) -> bool { + match ty.kind() { + // maybe ZST (could be more precise) + ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true, + // definitely ZST + ty::FnDef(..) | ty::Never => true, + // unreachable or can't be ZST + _ => false, + } +} + +/// Miri lazily allocates memory for locals on assignment, +/// so we must preserve writes to unions and union fields, +/// or it will ICE on reads of those fields. +fn involves_a_union<'tcx>( + place: Place<'tcx>, + local_decls: &LocalDecls<'tcx>, + tcx: TyCtxt<'tcx>, +) -> bool { + let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty); + if is_union(place_ty.ty) { + return true; + } + for elem in place.projection { + place_ty = place_ty.projection_ty(tcx, elem); + if is_union(place_ty.ty) { + return true; + } + } + return false; +} + +fn is_union(ty: Ty<'_>) -> bool { + match ty.kind() { + ty::Adt(def, _) if def.is_union() => true, + _ => false, + } +} diff --git a/compiler/rustc_mir/src/transform/required_consts.rs b/compiler/rustc_mir/src/transform/required_consts.rs index 2b518bd3a4..8b64ad65ab 100644 --- a/compiler/rustc_mir/src/transform/required_consts.rs +++ b/compiler/rustc_mir/src/transform/required_consts.rs @@ -15,7 +15,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { if let Some(ct) = constant.literal.const_for_ty() { - if let ConstKind::Unevaluated(_, _, _) = ct.val { + if let ConstKind::Unevaluated(_) = ct.val { self.required_consts.push(*constant); } } diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index d2314a9ba1..65e2d096b2 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -31,10 +31,10 @@ use crate::transform::MirPass; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::ParamEnv; use rustc_middle::ty::TyCtxt; use smallvec::SmallVec; -use std::{borrow::Cow, convert::TryInto}; +use std::borrow::Cow; +use std::convert::TryInto; pub struct SimplifyCfg { label: String, @@ -326,7 +326,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals { pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { // First, we're going to get a count of *actual* uses for every `Local`. - let mut used_locals = UsedLocals::new(body, tcx); + let mut used_locals = UsedLocals::new(body); // Next, we're going to remove any `Local` with zero actual uses. When we remove those // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals` @@ -336,8 +336,7 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { remove_unused_definitions(&mut used_locals, body); // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s. - let arg_count = body.arg_count.try_into().unwrap(); - let map = make_local_map(&mut body.local_decls, &used_locals, arg_count); + let map = make_local_map(&mut body.local_decls, &used_locals); // Only bother running the `LocalUpdater` if we actually found locals to remove. if map.iter().any(Option::is_none) { @@ -350,61 +349,54 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { } /// Construct the mapping while swapping out unused stuff out from the `vec`. -fn make_local_map<'tcx, V>( +fn make_local_map( local_decls: &mut IndexVec, - used_locals: &UsedLocals<'tcx>, - arg_count: u32, + used_locals: &UsedLocals, ) -> IndexVec> { - let mut map: IndexVec> = IndexVec::from_elem(None, local_decls); + let mut map: IndexVec> = IndexVec::from_elem(None, &*local_decls); let mut used = Local::new(0); for alive_index in local_decls.indices() { - // When creating the local map treat the `RETURN_PLACE` and arguments as used. - if alive_index.as_u32() <= arg_count || used_locals.is_used(alive_index) { - map[alive_index] = Some(used); - if alive_index != used { - local_decls.swap(alive_index, used); - } - used.increment_by(1); + // `is_used` treats the `RETURN_PLACE` and arguments as used. + if !used_locals.is_used(alive_index) { + continue; } + + map[alive_index] = Some(used); + if alive_index != used { + local_decls.swap(alive_index, used); + } + used.increment_by(1); } local_decls.truncate(used.index()); map } /// Keeps track of used & unused locals. -struct UsedLocals<'tcx> { +struct UsedLocals { increment: bool, + arg_count: u32, use_count: IndexVec, - is_static: bool, - local_decls: IndexVec>, - param_env: ParamEnv<'tcx>, - tcx: TyCtxt<'tcx>, } -impl UsedLocals<'tcx> { +impl UsedLocals { /// Determines which locals are used & unused in the given body. - fn new(body: &Body<'tcx>, tcx: TyCtxt<'tcx>) -> Self { - let def_id = body.source.def_id(); - let is_static = tcx.is_static(def_id); - let param_env = tcx.param_env(def_id); - let local_decls = body.local_decls.clone(); + fn new(body: &Body<'_>) -> Self { let mut this = Self { increment: true, + arg_count: body.arg_count.try_into().unwrap(), use_count: IndexVec::from_elem(0, &body.local_decls), - is_static, - local_decls, - param_env, - tcx, }; this.visit_body(body); this } /// Checks if local is used. + /// + /// Return place and arguments are always considered used. fn is_used(&self, local: Local) -> bool { trace!("is_used({:?}): use_count: {:?}", local, self.use_count[local]); - self.use_count[local] != 0 + local.as_u32() <= self.arg_count || self.use_count[local] != 0 } /// Updates the use counts to reflect the removal of given statement. @@ -422,7 +414,9 @@ impl UsedLocals<'tcx> { // A use, not a definition. self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location); } else { - // A definition. Although, it still might use other locals for indexing. + // A definition. The base local itself is not visited, so this occurrence is not counted + // toward its use count. There might be other locals still, used in an indexing + // projection. self.super_projection( place.as_ref(), PlaceContext::MutatingUse(MutatingUseContext::Projection), @@ -432,7 +426,7 @@ impl UsedLocals<'tcx> { } } -impl Visitor<'tcx> for UsedLocals<'tcx> { +impl Visitor<'_> for UsedLocals { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::LlvmInlineAsm(..) @@ -459,21 +453,7 @@ impl Visitor<'tcx> for UsedLocals<'tcx> { } } - fn visit_local(&mut self, local: &Local, ctx: PlaceContext, _location: Location) { - debug!("local: {:?} is_static: {:?}, ctx: {:?}", local, self.is_static, ctx); - // Do not count _0 as a used in `return;` if it is a ZST. - let return_place = *local == RETURN_PLACE - && matches!(ctx, PlaceContext::NonMutatingUse(visit::NonMutatingUseContext::Move)); - if !self.is_static && return_place { - let ty = self.local_decls[*local].ty; - let param_env_and = self.param_env.and(ty); - if let Ok(layout) = self.tcx.layout_of(param_env_and) { - debug!("layout.is_zst: {:?}", layout.is_zst()); - if layout.is_zst() { - return; - } - } - } + fn visit_local(&mut self, local: &Local, _ctx: PlaceContext, _location: Location) { if self.increment { self.use_count[*local] += 1; } else { @@ -484,10 +464,7 @@ impl Visitor<'tcx> for UsedLocals<'tcx> { } /// Removes unused definitions. Updates the used locals to reflect the changes made. -fn remove_unused_definitions<'a, 'tcx>( - used_locals: &'a mut UsedLocals<'tcx>, - body: &mut Body<'tcx>, -) { +fn remove_unused_definitions<'a, 'tcx>(used_locals: &'a mut UsedLocals, body: &mut Body<'tcx>) { // The use counts are updated as we remove the statements. A local might become unused // during the retain operation, leading to a temporary inconsistency (storage statements or // definitions referencing the local might remain). For correctness it is crucial that this diff --git a/compiler/rustc_mir/src/util/alignment.rs b/compiler/rustc_mir/src/util/alignment.rs index f567c9cfaa..5d4ca871fa 100644 --- a/compiler/rustc_mir/src/util/alignment.rs +++ b/compiler/rustc_mir/src/util/alignment.rs @@ -1,5 +1,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; +use rustc_target::abi::Align; /// Returns `true` if this place is allowed to be less aligned /// than its containing struct (because it is within a packed @@ -14,17 +15,25 @@ where L: HasLocalDecls<'tcx>, { debug!("is_disaligned({:?})", place); - if !is_within_packed(tcx, local_decls, place) { - debug!("is_disaligned({:?}) - not within packed", place); - return false; - } + let pack = match is_within_packed(tcx, local_decls, place) { + None => { + debug!("is_disaligned({:?}) - not within packed", place); + return false; + } + Some(pack) => pack, + }; let ty = place.ty(local_decls, tcx).ty; match tcx.layout_raw(param_env.and(ty)) { - Ok(layout) if layout.align.abi.bytes() == 1 => { - // if the alignment is 1, the type can't be further - // disaligned. - debug!("is_disaligned({:?}) - align = 1", place); + Ok(layout) if layout.align.abi <= pack => { + // If the packed alignment is greater or equal to the field alignment, the type won't be + // further disaligned. + debug!( + "is_disaligned({:?}) - align = {}, packed = {}; not disaligned", + place, + layout.align.abi.bytes(), + pack.bytes() + ); false } _ => { @@ -34,7 +43,11 @@ where } } -fn is_within_packed<'tcx, L>(tcx: TyCtxt<'tcx>, local_decls: &L, place: Place<'tcx>) -> bool +fn is_within_packed<'tcx, L>( + tcx: TyCtxt<'tcx>, + local_decls: &L, + place: Place<'tcx>, +) -> Option where L: HasLocalDecls<'tcx>, { @@ -45,7 +58,7 @@ where ProjectionElem::Field(..) => { let ty = place_base.ty(local_decls, tcx).ty; match ty.kind() { - ty::Adt(def, _) if def.repr.packed() => return true, + ty::Adt(def, _) => return def.repr.pack, _ => {} } } @@ -53,5 +66,5 @@ where } } - false + None } diff --git a/compiler/rustc_mir/src/util/find_self_call.rs b/compiler/rustc_mir/src/util/find_self_call.rs index ddda98d161..33ad128eee 100644 --- a/compiler/rustc_mir/src/util/find_self_call.rs +++ b/compiler/rustc_mir/src/util/find_self_call.rs @@ -3,7 +3,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; -/// Checks if the specified `local` is used as the `self` prameter of a method call +/// Checks if the specified `local` is used as the `self` parameter of a method call /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is /// returned. pub fn find_self_call<'tcx>( diff --git a/compiler/rustc_mir/src/util/generic_graphviz.rs b/compiler/rustc_mir/src/util/generic_graphviz.rs index fd41e28226..21c18b28e2 100644 --- a/compiler/rustc_mir/src/util/generic_graphviz.rs +++ b/compiler/rustc_mir/src/util/generic_graphviz.rs @@ -40,22 +40,6 @@ impl< } } - pub fn new_subgraph( - graph: &'a G, - graphviz_name: &str, - node_content_fn: NodeContentFn, - edge_labels_fn: EdgeLabelsFn, - ) -> Self { - Self { - graph, - is_subgraph: true, - graphviz_name: graphviz_name.to_owned(), - graph_label: None, - node_content_fn, - edge_labels_fn, - } - } - pub fn set_graph_label(&mut self, graph_label: &str) { self.graph_label = Some(graph_label.to_owned()); } diff --git a/compiler/rustc_mir/src/util/patch.rs b/compiler/rustc_mir/src/util/patch.rs index 6566a996fe..d09195f53a 100644 --- a/compiler/rustc_mir/src/util/patch.rs +++ b/compiler/rustc_mir/src/util/patch.rs @@ -13,7 +13,6 @@ pub struct MirPatch<'tcx> { new_locals: Vec>, resume_block: BasicBlock, next_local: usize, - make_nop: Vec, } impl<'tcx> MirPatch<'tcx> { @@ -25,7 +24,6 @@ impl<'tcx> MirPatch<'tcx> { new_locals: vec![], next_local: body.local_decls.len(), resume_block: START_BLOCK, - make_nop: vec![], }; // make sure the MIR we create has a resume block. It is @@ -117,15 +115,7 @@ impl<'tcx> MirPatch<'tcx> { self.add_statement(loc, StatementKind::Assign(box (place, rv))); } - pub fn make_nop(&mut self, loc: Location) { - self.make_nop.push(loc); - } - pub fn apply(self, body: &mut Body<'tcx>) { - debug!("MirPatch: make nops at: {:?}", self.make_nop); - for loc in self.make_nop { - body.make_statement_nop(loc); - } debug!( "MirPatch: {:?} new temps, starting from index {}: {:?}", self.new_locals.len(), diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 1bf010ffca..3b88aec16b 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -452,7 +452,11 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { match literal { ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)), ConstantKind::Val(val, ty) => { - self.push(&format!("+ literal: {:?}, {}", 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 + )) } } } @@ -465,7 +469,21 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { if use_verbose(ty) { self.push("ty::Const"); self.push(&format!("+ ty: {:?}", ty)); - self.push(&format!("+ val: {:?}", val)); + let val = match val { + ty::ConstKind::Param(p) => format!("Param({})", p), + ty::ConstKind::Infer(infer) => format!("Infer({:?})", infer), + ty::ConstKind::Bound(idx, var) => format!("Bound({:?}, {:?})", idx, var), + ty::ConstKind::Placeholder(ph) => format!("PlaceHolder({:?})", ph), + ty::ConstKind::Unevaluated(uv) => format!( + "Unevaluated({}, {:?}, {:?})", + self.tcx.def_path_str(uv.def.did), + uv.substs, + uv.promoted + ), + ty::ConstKind::Value(val) => format!("Value({:?})", val), + ty::ConstKind::Error(_) => format!("Error"), + }; + self.push(&format!("+ val: {}", val)); } } diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index e562e52f84..fd4a783d12 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -80,7 +80,7 @@ impl<'tcx> CFG<'tcx> { cause: FakeReadCause, place: Place<'tcx>, ) { - let kind = StatementKind::FakeRead(cause, box place); + let kind = StatementKind::FakeRead(box (cause, place)); let stmt = Statement { source_info, kind }; self.push(block, stmt); } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index fbc9c30fe5..1053890e61 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -17,6 +17,8 @@ use rustc_target::abi::VariantIdx; use rustc_index::vec::Idx; +use std::iter; + /// The "outermost" place that holds this value. #[derive(Copy, Clone, Debug, PartialEq)] crate enum PlaceBase { @@ -78,7 +80,7 @@ crate struct PlaceBuilder<'tcx> { /// The projections are truncated to represent a path that might be captured by a /// closure/generator. This implies the vector returned from this function doesn't contain /// ProjectionElems `Downcast`, `ConstantIndex`, `Index`, or `Subslice` because those will never be -/// part of a path that is captued by a closure. We stop applying projections once we see the first +/// part of a path that is captured by a closure. We stop applying projections once we see the first /// projection that isn't captured by a closure. fn convert_to_hir_projections_and_truncate_for_capture<'tcx>( mir_projections: &[PlaceElem<'tcx>], @@ -140,7 +142,7 @@ fn is_ancestor_or_same_capture( return false; } - proj_possible_ancestor.iter().zip(proj_capture).all(|(a, b)| a == b) + iter::zip(proj_possible_ancestor, proj_capture).all(|(a, b)| a == b) } /// Computes the index of a capture within the desugared closure provided the closure's @@ -576,7 +578,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Lower a captured upvar. Note we might not know the actual capture index, /// so we create a place starting from `PlaceBase::Upvar`, which will be resolved - /// once all projections that allow us to indentify a capture have been applied. + /// once all projections that allow us to identify a capture have been applied. fn lower_captured_upvar( &mut self, block: BasicBlock, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 7f24a41b00..689b27150e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -179,7 +179,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // match x { _ => () } // fake read of `x` // }; // ``` - // FIXME(RFC2229): Remove feature gate once diagnostics are improved + // + // FIXME(RFC2229, rust#85435): Remove feature gate once diagnostics are + // improved and unsafe checking works properly in closure bodies again. if this.tcx.features().capture_disjoint_fields { for (thir_place, cause, hir_id) in fake_reads.into_iter() { let place_builder = diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index fc92e8019c..1e7ed3d95d 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -10,6 +10,7 @@ use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; +use std::iter; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which @@ -110,18 +111,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::LogicalOp { op, lhs, rhs } => { // And: // - // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block] - // | | (false) - // +----------false-----------+------------------> [false_block] + // [block: If(lhs)] -true-> [else_block: dest = (rhs)] + // | (false) + // [shortcurcuit_block: dest = false] // // Or: // - // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block] - // | (true) | (false) - // [true_block] [false_block] + // [block: If(lhs)] -false-> [else_block: dest = (rhs)] + // | (true) + // [shortcurcuit_block: dest = true] - let (true_block, false_block, mut else_block, join_block) = ( - this.cfg.start_new_block(), + let (shortcircuit_block, mut else_block, join_block) = ( this.cfg.start_new_block(), this.cfg.start_new_block(), this.cfg.start_new_block(), @@ -129,41 +129,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let lhs = unpack!(block = this.as_local_operand(block, lhs)); let blocks = match op { - LogicalOp::And => (else_block, false_block), - LogicalOp::Or => (true_block, else_block), + LogicalOp::And => (else_block, shortcircuit_block), + LogicalOp::Or => (shortcircuit_block, else_block), }; let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1); this.cfg.terminate(block, source_info, term); - let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); - let term = TerminatorKind::if_(this.tcx, rhs, true_block, false_block); - this.cfg.terminate(else_block, source_info, term); - this.cfg.push_assign_constant( - true_block, + shortcircuit_block, source_info, destination, Constant { span: expr_span, user_ty: None, - literal: ty::Const::from_bool(this.tcx, true).into(), + literal: match op { + LogicalOp::And => ty::Const::from_bool(this.tcx, false).into(), + LogicalOp::Or => ty::Const::from_bool(this.tcx, true).into(), + }, }, ); + this.cfg.goto(shortcircuit_block, source_info, join_block); - this.cfg.push_assign_constant( - false_block, - source_info, - destination, - Constant { - span: expr_span, - user_ty: None, - literal: ty::Const::from_bool(this.tcx, false).into(), - }, - ); + let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); + this.cfg.push_assign(else_block, source_info, destination, Rvalue::Use(rhs)); + this.cfg.goto(else_block, source_info, join_block); - // Link up both branches: - this.cfg.goto(true_block, source_info, join_block); - this.cfg.goto(false_block, source_info, join_block); join_block.unit() } ExprKind::Loop { body } => { @@ -286,9 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that // reads it from the base. - field_names - .into_iter() - .zip(field_types.into_iter()) + iter::zip(field_names, *field_types) .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), None => { @@ -367,9 +355,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }), } } - thir::InlineAsmOperand::Const { expr } => mir::InlineAsmOperand::Const { - value: unpack!(block = this.as_local_operand(block, expr)), - }, + thir::InlineAsmOperand::Const { value, span } => { + mir::InlineAsmOperand::Const { + value: box Constant { span, user_ty: None, literal: value.into() }, + } + } thir::InlineAsmOperand::SymFn { expr } => { mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) } } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 73fd3f0feb..0e422dc3c6 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // uninhabited value. If we get never patterns, those will check that // the place is initialized, and so this read would only be used to // check safety. - let cause_matched_place = FakeReadCause::ForMatchedPlace; + let cause_matched_place = FakeReadCause::ForMatchedPlace(None); let source_info = self.source_info(scrutinee_span); if let Ok(scrutinee_builder) = @@ -400,7 +400,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); - self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet, place); + self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet(None), place); self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() @@ -435,7 +435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Inject a fake read, see comments on `FakeReadCause::ForLet`. let pattern_source_info = self.source_info(irrefutable_pat.span); - let cause_let = FakeReadCause::ForLet; + let cause_let = FakeReadCause::ForLet(None); self.cfg.push_fake_read(block, pattern_source_info, cause_let, place); let ty_source_info = self.source_info(user_ty_span); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index af4aaef902..f944e5f8f0 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -252,8 +252,13 @@ fn liberated_closure_env_ty( _ => bug!("closure expr does not have closure type: {:?}", closure_ty), }; - let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap(); - tcx.erase_late_bound_regions(closure_env_ty) + let bound_vars = + tcx.mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrEnv))); + let br = + ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap(); + tcx.erase_late_bound_regions(ty::Binder::bind_with_vars(closure_env_ty, bound_vars)) } #[derive(Debug, PartialEq, Eq)] @@ -604,6 +609,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: LocalDefId, abi: Abi) -> bo | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => true, diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index b637b9b70b..41fc925c04 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -618,6 +618,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } else { assert!(value.is_none(), "`return` and `break` should have a destination"); + if self.tcx.sess.instrument_coverage() { + // Unlike `break` and `return`, which push an `Assign` statement to MIR, from which + // a Coverage code region can be generated, `continue` needs no `Assign`; but + // without one, the `InstrumentCoverage` MIR pass cannot generate a code region for + // `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR. + self.add_dummy_assignment(&span, block, source_info); + } } let region_scope = self.scopes.breakable_scopes[break_index].region_scope; @@ -643,6 +650,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.start_new_block().unit() } + // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue` + // statement. + fn add_dummy_assignment(&mut self, span: &Span, block: BasicBlock, source_info: SourceInfo) { + let local_decl = LocalDecl::new(self.tcx.mk_unit(), *span).internal(); + let temp_place = Place::from(self.local_decls.push(local_decl)); + self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx); + } + crate fn exit_top_scope( &mut self, mut block: BasicBlock, diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index b1591d8ba3..da9a0b08e8 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -4,13 +4,13 @@ #![feature(array_windows)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] +#![feature(iter_zip)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 200a5fc104..924278e1a7 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -503,8 +503,12 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { in_expr: self.mirror_expr(in_expr), out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), }, - hir::InlineAsmOperand::Const { ref expr } => { - InlineAsmOperand::Const { expr: self.mirror_expr(expr) } + hir::InlineAsmOperand::Const { ref anon_const } => { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + let span = self.tcx.hir().span(anon_const.hir_id); + + InlineAsmOperand::Const { value, span } } hir::InlineAsmOperand::Sym { ref expr } => { let qpath = match expr.kind { @@ -707,11 +711,11 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(self.tcx(), did); let lhs = mk_const(self.tcx().mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(did), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: ty::WithOptConstParam::unknown(did), substs, - None, - ), + promoted: None, + }), ty: var_ty, })); let bin = @@ -905,11 +909,11 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { literal: self.tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(def_id), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id), substs, - None, - ), + promoted: None, + }), ty: self.typeck_results().node_type(expr.hir_id), }), user_ty, diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index 6f20195db0..f4596d523d 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -374,7 +374,8 @@ pub enum InlineAsmOperand<'thir, 'tcx> { out_expr: Option<&'thir Expr<'thir, 'tcx>>, }, Const { - expr: &'thir Expr<'thir, 'tcx>, + value: &'tcx Const<'tcx>, + span: Span, }, SymFn { expr: &'thir Expr<'thir, 'tcx>, diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index ef1419b5b7..c0624c805a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -246,6 +246,18 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { }) } + fn field_pats( + &self, + vals: impl Iterator>, + ) -> Result>, FallbackToConstRef> { + vals.enumerate() + .map(|(idx, val)| { + let field = Field::new(idx); + Ok(FieldPat { field, pattern: self.recur(val, false)? }) + }) + .collect() + } + // Recursive helper for `to_pat`; invoke that (instead of calling this directly). fn recur( &self, @@ -257,16 +269,6 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { let tcx = self.tcx(); let param_env = self.param_env; - let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| -> Result<_, _> { - vals.iter() - .enumerate() - .map(|(idx, val)| { - let field = Field::new(idx); - Ok(FieldPat { field, pattern: self.recur(val, false)? }) - }) - .collect() - }; - let kind = match cv.ty.kind() { ty::Float(_) => { tcx.struct_span_lint_hir( @@ -361,12 +363,12 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { variant_index: destructured .variant .expect("destructed const of adt without variant id"), - subpatterns: field_pats(destructured.fields)?, + subpatterns: self.field_pats(destructured.fields.iter().copied())?, } } ty::Tuple(_) | ty::Adt(_, _) => { let destructured = tcx.destructure_const(param_env.and(cv)); - PatKind::Leaf { subpatterns: field_pats(destructured.fields)? } + PatKind::Leaf { subpatterns: self.field_pats(destructured.fields.iter().copied())? } } ty::Array(..) => PatKind::Array { prefix: tcx diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 4bf870eb7c..bd8dfd678a 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -128,7 +128,7 @@ impl<'a> StringReader<'a> { } /// Turns simple `rustc_lexer::TokenKind` enum into a rich - /// `librustc_ast::TokenKind`. This turns strings into interned + /// `rustc_ast::TokenKind`. This turns strings into interned /// symbols and runs additional validation. fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Option { Some(match token { diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 001b52b56f..905077a48e 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,17 +1,21 @@ //! The main parser interface. +#![feature(array_windows)] #![feature(crate_visibility_modifier)] #![feature(bindings_after_at)] #![feature(iter_order_by)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(box_syntax)] #![feature(box_patterns)] #![recursion_limit = "256"] use rustc_ast as ast; -use rustc_ast::token::{self, Nonterminal}; -use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens, LazyTokenStream, TokenStream}; +use rustc_ast::token::{self, Nonterminal, Token, TokenKind}; +use rustc_ast::tokenstream::{self, AttributesData, CanSynthesizeMissingTokens, LazyTokenStream}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; +use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_ast::AstLike; +use rustc_ast::Attribute; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diagnostic, FatalError, Level, PResult}; @@ -21,8 +25,6 @@ use rustc_span::{FileName, SourceFile, Span}; use std::path::Path; use std::str; -use tracing::debug; - pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments"); #[macro_use] @@ -255,19 +257,23 @@ pub fn nt_to_tokenstream( // before we fall back to the stringification. let convert_tokens = - |tokens: Option<&LazyTokenStream>| tokens.as_ref().map(|t| t.create_token_stream()); + |tokens: Option<&LazyTokenStream>| Some(tokens?.create_token_stream().to_tokenstream()); let tokens = match *nt { - Nonterminal::NtItem(ref item) => prepend_attrs(sess, &item.attrs, nt, item.tokens.as_ref()), + Nonterminal::NtItem(ref item) => prepend_attrs(&item.attrs, item.tokens.as_ref()), Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()), Nonterminal::NtStmt(ref stmt) => { - let do_prepend = |tokens| prepend_attrs(sess, stmt.attrs(), nt, tokens); if let ast::StmtKind::Empty = stmt.kind { - let tokens: TokenStream = - tokenstream::TokenTree::token(token::Semi, stmt.span).into(); - do_prepend(Some(&LazyTokenStream::new(tokens))) + let tokens = AttrAnnotatedTokenStream::new(vec![( + tokenstream::AttrAnnotatedTokenTree::Token(Token::new( + TokenKind::Semi, + stmt.span, + )), + Spacing::Alone, + )]); + prepend_attrs(&stmt.attrs(), Some(&LazyTokenStream::new(tokens))) } else { - do_prepend(stmt.tokens()) + prepend_attrs(&stmt.attrs(), stmt.tokens()) } } Nonterminal::NtPat(ref pat) => convert_tokens(pat.tokens.as_ref()), @@ -283,10 +289,7 @@ pub fn nt_to_tokenstream( Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()), Nonterminal::NtTT(ref tt) => Some(tt.clone().into()), Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => { - if expr.tokens.is_none() { - debug!("missing tokens for expr {:?}", expr); - } - prepend_attrs(sess, &expr.attrs, nt, expr.tokens.as_ref()) + prepend_attrs(&expr.attrs, expr.tokens.as_ref()) } }; @@ -295,34 +298,30 @@ pub fn nt_to_tokenstream( } else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) { return fake_token_stream(sess, nt); } else { - panic!("Missing tokens for nt at {:?}: {:?}", nt.span(), pprust::nonterminal_to_string(nt)); + panic!( + "Missing tokens for nt {:?} at {:?}: {:?}", + nt, + nt.span(), + pprust::nonterminal_to_string(nt) + ); } } +fn prepend_attrs(attrs: &[Attribute], tokens: Option<&LazyTokenStream>) -> Option { + let tokens = tokens?; + if attrs.is_empty() { + return Some(tokens.create_token_stream().to_tokenstream()); + } + let attr_data = AttributesData { attrs: attrs.to_vec().into(), tokens: tokens.clone() }; + let wrapped = AttrAnnotatedTokenStream::new(vec![( + AttrAnnotatedTokenTree::Attributes(attr_data), + Spacing::Alone, + )]); + Some(wrapped.to_tokenstream()) +} + pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream { let source = pprust::nonterminal_to_string(nt); let filename = FileName::macro_expansion_source_code(&source); parse_stream_from_source_str(filename, source, sess, Some(nt.span())) } - -fn prepend_attrs( - sess: &ParseSess, - attrs: &[ast::Attribute], - nt: &Nonterminal, - tokens: Option<&tokenstream::LazyTokenStream>, -) -> Option { - if attrs.is_empty() { - return Some(tokens?.create_token_stream()); - } - let mut builder = tokenstream::TokenStreamBuilder::new(); - for attr in attrs { - // FIXME: Correctly handle tokens for inner attributes. - // For now, we fall back to reparsing the original AST node - if attr.style == ast::AttrStyle::Inner { - return Some(fake_token_stream(sess, nt)); - } - builder.push(attr.tokens()); - } - builder.push(tokens?.create_token_stream()); - Some(builder.build()) -} diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 95d4a48b84..ee6ff4dba3 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,10 +1,11 @@ -use super::{AttrWrapper, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, Parser, PathStyle}; use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Nonterminal}; use rustc_ast_pretty::pprust; use rustc_errors::{error_code, PResult}; use rustc_span::{sym, Span}; +use std::convert::TryInto; use tracing::debug; @@ -29,6 +30,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { let mut attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; + let start_pos = self.token_cursor.num_next_calls; loop { debug!("parse_outer_attributes: self.token={:?}", self.token); let attr = if self.check(&token::Pound) { @@ -74,7 +76,7 @@ impl<'a> Parser<'a> { break; } } - Ok(AttrWrapper::new(attrs)) + Ok(AttrWrapper::new(attrs.into(), start_pos)) } /// Matches `attribute = # ! [ meta_item ]`. @@ -177,6 +179,7 @@ impl<'a> Parser<'a> { crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = vec![]; loop { + let start_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); // Only try to parse if it is an inner attribute (has `!`). let attr = if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) { Some(self.parse_attribute(InnerAttrPolicy::Permitted)?) @@ -191,6 +194,18 @@ impl<'a> Parser<'a> { None }; if let Some(attr) = attr { + let end_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); + // If we are currently capturing tokens, mark the location of this inner attribute. + // If capturing ends up creating a `LazyTokenStream`, we will include + // this replace range with it, removing the inner attribute from the final + // `AttrAnnotatedTokenStream`. Inner attributes are stored in the parsed AST note. + // During macro expansion, they are selectively inserted back into the + // token stream (the first inner attribute is remoevd each time we invoke the + // corresponding macro). + let range = start_pos..end_pos; + if let Capturing::Yes = self.capture_state.capturing { + self.capture_state.inner_attr_ranges.insert(attr.id, (range, vec![])); + } attrs.push(attr); } else { break; @@ -311,6 +326,9 @@ pub fn maybe_needs_tokens(attrs: &[ast::Attribute]) -> bool { // One of the attributes may either itself be a macro, // or expand to macro attributes (`cfg_attr`). attrs.iter().any(|attr| { + if attr.is_doc_comment() { + return false; + } attr.ident().map_or(true, |ident| { ident.name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(ident.name) }) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 7512f46988..35759a396e 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -1,12 +1,14 @@ -use super::attr; -use super::{ForceCollect, Parser, TokenCursor, TrailingToken}; -use rustc_ast::token::{self, Token, TokenKind}; -use rustc_ast::tokenstream::{CreateTokenStream, TokenStream, TokenTree, TreeAndSpacing}; -use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, Spacing}; -use rustc_ast::AstLike; +use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken}; +use rustc_ast::token::{self, DelimToken, Token, TokenKind}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttributesData, CreateTokenStream}; +use rustc_ast::tokenstream::{AttrAnnotatedTokenTree, DelimSpan, LazyTokenStream, Spacing}; use rustc_ast::{self as ast}; +use rustc_ast::{AstLike, AttrVec, Attribute}; use rustc_errors::PResult; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{sym, Span, DUMMY_SP}; + +use std::convert::TryInto; +use std::ops::Range; /// A wrapper type to ensure that the parser handles outer attributes correctly. /// When we parse outer attributes, we need to ensure that we capture tokens @@ -23,23 +25,158 @@ use rustc_span::{Span, DUMMY_SP}; /// cannot directly access the `attrs` field #[derive(Debug, Clone)] pub struct AttrWrapper { - attrs: Vec, + attrs: AttrVec, + // The start of the outer attributes in the token cursor. + // This allows us to create a `ReplaceRange` for the entire attribute + // target, including outer attributes. + start_pos: usize, } +// This struct is passed around very frequently, +// so make sure it doesn't accidentally get larger +#[cfg(target_arch = "x86_64")] +rustc_data_structures::static_assert_size!(AttrWrapper, 16); + impl AttrWrapper { - pub fn empty() -> AttrWrapper { - AttrWrapper { attrs: vec![] } + pub(super) fn new(attrs: AttrVec, start_pos: usize) -> AttrWrapper { + AttrWrapper { attrs, start_pos } } - pub fn new(attrs: Vec) -> AttrWrapper { - AttrWrapper { attrs } + pub fn empty() -> AttrWrapper { + AttrWrapper { attrs: AttrVec::new(), start_pos: usize::MAX } } // FIXME: Delay span bug here? - pub(crate) fn take_for_recovery(self) -> Vec { + pub(crate) fn take_for_recovery(self) -> AttrVec { self.attrs } + + // FIXME: require passing an NT to prevent misuse of this method + pub(crate) fn prepend_to_nt_inner(self, attrs: &mut Vec) { + let mut self_attrs: Vec<_> = self.attrs.into(); + std::mem::swap(attrs, &mut self_attrs); + attrs.extend(self_attrs); + } + pub fn is_empty(&self) -> bool { self.attrs.is_empty() } + + pub fn maybe_needs_tokens(&self) -> bool { + crate::parser::attr::maybe_needs_tokens(&self.attrs) + } +} + +/// Returns `true` if `attrs` contains a `cfg` or `cfg_attr` attribute +fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool { + // NOTE: Builtin attributes like `cfg` and `cfg_attr` cannot be renamed via imports. + // Therefore, the absence of a literal `cfg` or `cfg_attr` guarantees that + // we don't need to do any eager expansion. + attrs.iter().any(|attr| { + attr.ident().map_or(false, |ident| ident.name == sym::cfg || ident.name == sym::cfg_attr) + }) +} + +// Produces a `TokenStream` on-demand. Using `cursor_snapshot` +// and `num_calls`, we can reconstruct the `TokenStream` seen +// by the callback. This allows us to avoid producing a `TokenStream` +// if it is never needed - for example, a captured `macro_rules!` +// argument that is never passed to a proc macro. +// In practice token stream creation happens rarely compared to +// calls to `collect_tokens` (see some statistics in #78736), +// so we are doing as little up-front work as possible. +// +// This also makes `Parser` very cheap to clone, since +// there is no intermediate collection buffer to clone. +#[derive(Clone)] +struct LazyTokenStreamImpl { + start_token: (Token, Spacing), + cursor_snapshot: TokenCursor, + num_calls: usize, + break_last_token: bool, + replace_ranges: Box<[ReplaceRange]>, +} + +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(LazyTokenStreamImpl, 144); + +impl CreateTokenStream for LazyTokenStreamImpl { + fn create_token_stream(&self) -> AttrAnnotatedTokenStream { + // The token produced by the final call to `next` or `next_desugared` + // was not actually consumed by the callback. The combination + // of chaining the initial token and using `take` produces the desired + // result - we produce an empty `TokenStream` if no calls were made, + // and omit the final token otherwise. + let mut cursor_snapshot = self.cursor_snapshot.clone(); + let tokens = + std::iter::once((FlatToken::Token(self.start_token.0.clone()), self.start_token.1)) + .chain((0..self.num_calls).map(|_| { + let token = if cursor_snapshot.desugar_doc_comments { + cursor_snapshot.next_desugared() + } else { + cursor_snapshot.next() + }; + (FlatToken::Token(token.0), token.1) + })) + .take(self.num_calls); + + if !self.replace_ranges.is_empty() { + let mut tokens: Vec<_> = tokens.collect(); + let mut replace_ranges = self.replace_ranges.clone(); + replace_ranges.sort_by_key(|(range, _)| range.start); + + #[cfg(debug_assertions)] + { + for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() { + assert!( + range.end <= next_range.start || range.end >= next_range.end, + "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", + range, + tokens, + next_range, + next_tokens, + ); + } + } + + // Process the replace ranges, starting from the highest start + // position and working our way back. If have tokens like: + // + // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }` + // + // Then we will generate replace ranges for both + // the `#[cfg(FALSE)] field: bool` and the entire + // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }` + // + // By starting processing from the replace range with the greatest + // start position, we ensure that any replace range which encloses + // another replace range will capture the *replaced* tokens for the inner + // range, not the original tokens. + for (range, new_tokens) in replace_ranges.iter().rev() { + assert!(!range.is_empty(), "Cannot replace an empty range: {:?}", range); + // Replace ranges are only allowed to decrease the number of tokens. + assert!( + range.len() >= new_tokens.len(), + "Range {:?} has greater len than {:?}", + range, + new_tokens + ); + + // Replace any removed tokens with `FlatToken::Empty`. + // This keeps the total length of `tokens` constant throughout the + // replacement process, allowing us to use all of the `ReplaceRanges` entries + // without adjusting indices. + let filler = std::iter::repeat((FlatToken::Empty, Spacing::Alone)) + .take(range.len() - new_tokens.len()); + + tokens.splice( + (range.start as usize)..(range.end as usize), + new_tokens.clone().into_iter().chain(filler), + ); + } + make_token_stream(tokens.into_iter(), self.break_last_token) + } else { + make_token_stream(tokens, self.break_last_token) + } + } } impl<'a> Parser<'a> { @@ -65,81 +202,195 @@ impl<'a> Parser<'a> { force_collect: ForceCollect, f: impl FnOnce(&mut Self, Vec) -> PResult<'a, (R, TrailingToken)>, ) -> PResult<'a, R> { - if matches!(force_collect, ForceCollect::No) && !attr::maybe_needs_tokens(&attrs.attrs) { - return Ok(f(self, attrs.attrs)?.0); + // We only bail out when nothing could possibly observe the collected tokens: + // 1. We cannot be force collecting tokens (since force-collecting requires tokens + // by definition + if matches!(force_collect, ForceCollect::No) + // None of our outer attributes can require tokens (e.g. a proc-macro) + && !attrs.maybe_needs_tokens() + // If our target supports custom inner attributes, then we cannot bail + // out early, since we may need to capture tokens for a custom inner attribute + // invocation. + && !R::SUPPORTS_CUSTOM_INNER_ATTRS + // Never bail out early in `capture_cfg` mode, since there might be `#[cfg]` + // or `#[cfg_attr]` attributes. + && !self.capture_cfg + { + return Ok(f(self, attrs.attrs.into())?.0); } + let start_token = (self.token.clone(), self.token_spacing); let cursor_snapshot = self.token_cursor.clone(); - let (mut ret, trailing_token) = f(self, attrs.attrs)?; - let tokens = match ret.tokens_mut() { - Some(tokens) if tokens.is_none() => tokens, - _ => return Ok(ret), - }; + let has_outer_attrs = !attrs.attrs.is_empty(); + let prev_capturing = std::mem::replace(&mut self.capture_state.capturing, Capturing::Yes); + let replace_ranges_start = self.capture_state.replace_ranges.len(); + + let ret = f(self, attrs.attrs.into()); + + self.capture_state.capturing = prev_capturing; + + let (mut ret, trailing) = ret?; - // Produces a `TokenStream` on-demand. Using `cursor_snapshot` - // and `num_calls`, we can reconstruct the `TokenStream` seen - // by the callback. This allows us to avoid producing a `TokenStream` - // if it is never needed - for example, a captured `macro_rules!` - // argument that is never passed to a proc macro. - // In practice token stream creation happens rarely compared to - // calls to `collect_tokens` (see some statistics in #78736), - // so we are doing as little up-front work as possible. - // - // This also makes `Parser` very cheap to clone, since - // there is no intermediate collection buffer to clone. - #[derive(Clone)] - struct LazyTokenStreamImpl { - start_token: (Token, Spacing), - cursor_snapshot: TokenCursor, - num_calls: usize, - desugar_doc_comments: bool, - append_unglued_token: Option, + // When we're not in `capture-cfg` mode, then bail out early if: + // 1. Our target doesn't support tokens at all (e.g we're parsing an `NtIdent`) + // so there's nothing for us to do. + // 2. Our target already has tokens set (e.g. we've parsed something + // like `#[my_attr] $item`. The actual parsing code takes care of prepending + // any attributes to the nonterminal, so we don't need to modify the + // already captured tokens. + // Note that this check is independent of `force_collect`- if we already + // have tokens, or can't even store them, then there's never a need to + // force collection of new tokens. + if !self.capture_cfg && matches!(ret.tokens_mut(), None | Some(Some(_))) { + return Ok(ret); } - impl CreateTokenStream for LazyTokenStreamImpl { - fn create_token_stream(&self) -> TokenStream { - // The token produced by the final call to `next` or `next_desugared` - // was not actually consumed by the callback. The combination - // of chaining the initial token and using `take` produces the desired - // result - we produce an empty `TokenStream` if no calls were made, - // and omit the final token otherwise. - let mut cursor_snapshot = self.cursor_snapshot.clone(); - let tokens = std::iter::once(self.start_token.clone()) - .chain((0..self.num_calls).map(|_| { - if self.desugar_doc_comments { - cursor_snapshot.next_desugared() - } else { - cursor_snapshot.next() - } - })) - .take(self.num_calls); - - make_token_stream(tokens, self.append_unglued_token.clone()) + + // This is very similar to the bail out check at the start of this function. + // Now that we've parsed an AST node, we have more information available. + if matches!(force_collect, ForceCollect::No) + // We now have inner attributes available, so this check is more precise + // than `attrs.maybe_needs_tokens()` at the start of the function. + // As a result, we don't need to check `R::SUPPORTS_CUSTOM_INNER_ATTRS` + && !crate::parser::attr::maybe_needs_tokens(ret.attrs()) + // Subtle: We call `has_cfg_or_cfg_attr` with the attrs from `ret`. + // This ensures that we consider inner attributes (e.g. `#![cfg]`), + // which require us to have tokens available + // We also call `has_cfg_or_cfg_attr` at the beginning of this function, + // but we only bail out if there's no possibility of inner attributes + // (!R::SUPPORTS_CUSTOM_INNER_ATTRS) + // We only catpure about `#[cfg]` or `#[cfg_attr]` in `capture_cfg` + // mode - during normal parsing, we don't need any special capturing + // for those attributes, since they're builtin. + && !(self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs())) + { + return Ok(ret); + } + + let mut inner_attr_replace_ranges = Vec::new(); + // Take the captured ranges for any inner attributes that we parsed. + for inner_attr in ret.attrs().iter().filter(|a| a.style == ast::AttrStyle::Inner) { + if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) { + inner_attr_replace_ranges.push(attr_range); + } else { + self.sess + .span_diagnostic + .delay_span_bug(inner_attr.span, "Missing token range for attribute"); } } - let mut num_calls = self.token_cursor.num_next_calls - cursor_snapshot.num_next_calls; - match trailing_token { + let replace_ranges_end = self.capture_state.replace_ranges.len(); + + let cursor_snapshot_next_calls = cursor_snapshot.num_next_calls; + let mut end_pos = self.token_cursor.num_next_calls; + + // Capture a trailing token if requested by the callback 'f' + match trailing { TrailingToken::None => {} TrailingToken::Semi => { assert_eq!(self.token.kind, token::Semi); - num_calls += 1; + end_pos += 1; } TrailingToken::MaybeComma => { if self.token.kind == token::Comma { - num_calls += 1; + end_pos += 1; } } } - *tokens = Some(LazyTokenStream::new(LazyTokenStreamImpl { + // If we 'broke' the last token (e.g. breaking a '>>' token to two '>' tokens), + // then extend the range of captured tokens to include it, since the parser + // was not actually bumped past it. When the `LazyTokenStream` gets converted + // into a `AttrAnnotatedTokenStream`, we will create the proper token. + if self.token_cursor.break_last_token { + assert_eq!( + trailing, + TrailingToken::None, + "Cannot set `break_last_token` and have trailing token" + ); + end_pos += 1; + } + + let num_calls = end_pos - cursor_snapshot_next_calls; + + // If we have no attributes, then we will never need to + // use any replace ranges. + let replace_ranges: Box<[ReplaceRange]> = if ret.attrs().is_empty() && !self.capture_cfg { + Box::new([]) + } else { + // Grab any replace ranges that occur *inside* the current AST node. + // We will perform the actual replacement when we convert the `LazyTokenStream` + // to a `AttrAnnotatedTokenStream` + let start_calls: u32 = cursor_snapshot_next_calls.try_into().unwrap(); + self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] + .iter() + .cloned() + .chain(inner_attr_replace_ranges.clone().into_iter()) + .map(|(range, tokens)| { + ((range.start - start_calls)..(range.end - start_calls), tokens) + }) + .collect() + }; + + let tokens = LazyTokenStream::new(LazyTokenStreamImpl { start_token, num_calls, cursor_snapshot, - desugar_doc_comments: self.desugar_doc_comments, - append_unglued_token: self.token_cursor.append_unglued_token.clone(), - })); + break_last_token: self.token_cursor.break_last_token, + replace_ranges, + }); + + // If we support tokens at all + if let Some(target_tokens) = ret.tokens_mut() { + if let Some(target_tokens) = target_tokens { + assert!( + !self.capture_cfg, + "Encountered existing tokens with capture_cfg set: {:?}", + target_tokens + ); + } else { + // Store se our newly captured tokens into the AST node + *target_tokens = Some(tokens.clone()); + }; + } + let final_attrs = ret.attrs(); + + // If `capture_cfg` is set and we're inside a recursive call to + // `collect_tokens_trailing_token`, then we need to register a replace range + // if we have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager cfg-expansion + // on the captured token stream. + if self.capture_cfg + && matches!(self.capture_state.capturing, Capturing::Yes) + && has_cfg_or_cfg_attr(&final_attrs) + { + let attr_data = AttributesData { attrs: final_attrs.to_vec().into(), tokens }; + + // Replace the entire AST node that we just parsed, including attributes, + // with a `FlatToken::AttrTarget`. If this AST node is inside an item + // that has `#[derive]`, then this will allow us to cfg-expand this + // AST node. + let start_pos = + if has_outer_attrs { attrs.start_pos } else { cursor_snapshot_next_calls }; + let new_tokens = vec![(FlatToken::AttrTarget(attr_data), Spacing::Alone)]; + + assert!( + !self.token_cursor.break_last_token, + "Should not have unglued last token with cfg attr" + ); + let range: Range = (start_pos.try_into().unwrap())..(end_pos.try_into().unwrap()); + self.capture_state.replace_ranges.push((range, new_tokens)); + self.capture_state.replace_ranges.extend(inner_attr_replace_ranges); + } + + // Only clear our `replace_ranges` when we're finished capturing entirely. + if matches!(self.capture_state.capturing, Capturing::No) { + self.capture_state.replace_ranges.clear(); + // We don't clear `inner_attr_ranges`, as doing so repeatedly + // had a measureable performance impact. Most inner attributes that + // we insert will get removed - when we drop the parser, we'll free + // up the memory used by any attributes that we didn't remove from the map. + } Ok(ret) } } @@ -147,43 +398,112 @@ impl<'a> Parser<'a> { /// Converts a flattened iterator of tokens (including open and close delimiter tokens) /// into a `TokenStream`, creating a `TokenTree::Delimited` for each matching pair /// of open and close delims. +// FIXME(#67062): Currently, we don't parse `None`-delimited groups correctly, +// which can cause us to end up with mismatched `None` delimiters in our +// captured tokens. This function contains several hacks to work around this - +// essentially, we throw away mismatched `None` delimiters when we encounter them. +// Once we properly parse `None` delimiters, they can be captured just like any +// other tokens, and these hacks can be removed. fn make_token_stream( - tokens: impl Iterator, - append_unglued_token: Option, -) -> TokenStream { + mut iter: impl Iterator, + break_last_token: bool, +) -> AttrAnnotatedTokenStream { #[derive(Debug)] struct FrameData { open: Span, - inner: Vec<(TokenTree, Spacing)>, + open_delim: DelimToken, + inner: Vec<(AttrAnnotatedTokenTree, Spacing)>, } - let mut stack = vec![FrameData { open: DUMMY_SP, inner: vec![] }]; - for (token, spacing) in tokens { + let mut stack = + vec![FrameData { open: DUMMY_SP, open_delim: DelimToken::NoDelim, inner: vec![] }]; + let mut token_and_spacing = iter.next(); + while let Some((token, spacing)) = token_and_spacing { match token { - Token { kind: TokenKind::OpenDelim(_), span } => { - stack.push(FrameData { open: span, inner: vec![] }); + FlatToken::Token(Token { kind: TokenKind::OpenDelim(delim), span }) => { + stack.push(FrameData { open: span, open_delim: delim, inner: vec![] }); } - Token { kind: TokenKind::CloseDelim(delim), span } => { - let frame_data = stack.pop().expect("Token stack was empty!"); + FlatToken::Token(Token { kind: TokenKind::CloseDelim(delim), span }) => { + // HACK: If we enconter a mismatched `None` delimiter at the top + // level, just ignore it. + if matches!(delim, DelimToken::NoDelim) + && (stack.len() == 1 + || !matches!(stack.last_mut().unwrap().open_delim, DelimToken::NoDelim)) + { + token_and_spacing = iter.next(); + continue; + } + let frame_data = stack + .pop() + .unwrap_or_else(|| panic!("Token stack was empty for token: {:?}", token)); + + // HACK: If our current frame has a mismatched opening `None` delimiter, + // merge our current frame with the one above it. That is, transform + // `[ { < first second } third ]` into `[ { first second } third ]` + if !matches!(delim, DelimToken::NoDelim) + && matches!(frame_data.open_delim, DelimToken::NoDelim) + { + stack.last_mut().unwrap().inner.extend(frame_data.inner); + // Process our closing delimiter again, this time at the previous + // frame in the stack + token_and_spacing = Some((token, spacing)); + continue; + } + + assert_eq!( + frame_data.open_delim, delim, + "Mismatched open/close delims: open={:?} close={:?}", + frame_data.open, span + ); let dspan = DelimSpan::from_pair(frame_data.open, span); - let stream = TokenStream::new(frame_data.inner); - let delimited = TokenTree::Delimited(dspan, delim, stream); + let stream = AttrAnnotatedTokenStream::new(frame_data.inner); + let delimited = AttrAnnotatedTokenTree::Delimited(dspan, delim, stream); stack .last_mut() - .unwrap_or_else(|| panic!("Bottom token frame is missing for tokens!")) + .unwrap_or_else(|| { + panic!("Bottom token frame is missing for token: {:?}", token) + }) .inner .push((delimited, Spacing::Alone)); } - token => { - stack - .last_mut() - .expect("Bottom token frame is missing!") - .inner - .push((TokenTree::Token(token), spacing)); - } + FlatToken::Token(token) => stack + .last_mut() + .expect("Bottom token frame is missing!") + .inner + .push((AttrAnnotatedTokenTree::Token(token), spacing)), + FlatToken::AttrTarget(data) => stack + .last_mut() + .expect("Bottom token frame is missing!") + .inner + .push((AttrAnnotatedTokenTree::Attributes(data), spacing)), + FlatToken::Empty => {} } + token_and_spacing = iter.next(); + } + // HACK: If we don't have a closing `None` delimiter for our last + // frame, merge the frame with the top-level frame. That is, + // turn `< first second` into `first second` + if stack.len() == 2 && stack[1].open_delim == DelimToken::NoDelim { + let temp_buf = stack.pop().unwrap(); + stack.last_mut().unwrap().inner.extend(temp_buf.inner); } let mut final_buf = stack.pop().expect("Missing final buf!"); - final_buf.inner.extend(append_unglued_token); + if break_last_token { + let (last_token, spacing) = final_buf.inner.pop().unwrap(); + if let AttrAnnotatedTokenTree::Token(last_token) = last_token { + let unglued_first = last_token.kind.break_two_token_op().unwrap().0; + + // A 'unglued' token is always two ASCII characters + let mut first_span = last_token.span.shrink_to_lo(); + first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1)); + + final_buf.inner.push(( + AttrAnnotatedTokenTree::Token(Token::new(unglued_first, first_span)), + spacing, + )); + } else { + panic!("Unexpected last token {:?}", last_token) + } + } assert!(stack.is_empty(), "Stack should be empty: final_buf={:?} stack={:?}", final_buf, stack); - TokenStream::new(final_buf.inner) + AttrAnnotatedTokenStream::new(final_buf.inner) } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 77e85c06ff..70a5ac6f15 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -666,21 +666,23 @@ impl<'a> Parser<'a> { ); match x { Ok((_, _, false)) => { - self.bump(); // `>` - match self.parse_expr() { - Ok(_) => { - e.span_suggestion_verbose( - binop.span.shrink_to_lo(), - TURBOFISH_SUGGESTION_STR, - "::".to_string(), - Applicability::MaybeIncorrect, - ); - e.emit(); - *expr = self.mk_expr_err(expr.span.to(self.prev_token.span)); - return Ok(()); - } - Err(mut err) => { - err.cancel(); + if self.eat(&token::Gt) { + match self.parse_expr() { + Ok(_) => { + e.span_suggestion_verbose( + binop.span.shrink_to_lo(), + TURBOFISH_SUGGESTION_STR, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + e.emit(); + *expr = + self.mk_expr_err(expr.span.to(self.prev_token.span)); + return Ok(()); + } + Err(mut err) => { + err.cancel(); + } } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a3f2a8b3c5..e155b3fa77 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,4 +1,4 @@ -use super::pat::{GateOr, RecoverComma, PARAM_EXPECTED}; +use super::pat::{RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken}; @@ -92,7 +92,22 @@ impl<'a> Parser<'a> { self.parse_expr_res(Restrictions::empty(), None) } - pub(super) fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> { + /// Parses an expression, forcing tokens to be collected + pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P> { + // If we have outer attributes, then the call to `collect_tokens_trailing_token` + // will be made for us. + if matches!(self.token.kind, TokenKind::Pound | TokenKind::DocComment(..)) { + self.parse_expr() + } else { + // If we don't have outer attributes, then we need to ensure + // that collection happens by using `collect_tokens_no_attrs`. + // Expression don't support custom inner attributes, so `parse_expr` + // will never try to collect tokens if we don't have outer attributes. + self.collect_tokens_no_attrs(|this| this.parse_expr()) + } + } + + pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> { self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value }) } @@ -1803,7 +1818,7 @@ impl<'a> Parser<'a> { /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; - let pat = self.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::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()) @@ -1866,7 +1881,7 @@ impl<'a> Parser<'a> { _ => None, }; - let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; if !self.eat_keyword(kw::In) { self.error_missing_in_for_loop(); } @@ -2073,7 +2088,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, GateOr::No, RecoverComma::Yes)?; + let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; let guard = if this.eat_keyword(kw::If) { let if_span = this.prev_token.span; let cond = this.parse_expr()?; @@ -2566,19 +2581,17 @@ impl<'a> Parser<'a> { attrs: AttrWrapper, f: impl FnOnce(&mut Self, Vec) -> PResult<'a, P>, ) -> PResult<'a, P> { - // FIXME - come up with a nice way to properly forward `ForceCollect`from - // the nonterminal parsing code. TThis approach iscorrect, but will cause - // us to unnecessarily capture tokens for exprs that have only builtin - // attributes. Revisit this before #![feature(stmt_expr_attributes)] is stabilized - let force_collect = if attrs.is_empty() { ForceCollect::No } else { ForceCollect::Yes }; - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let res = f(this, attrs)?; let trailing = if this.restrictions.contains(Restrictions::STMT_EXPR) && this.token.kind == token::Semi { TrailingToken::Semi } else { - TrailingToken::None + // FIXME - pass this through from the place where we know + // we need a comma, rather than assuming that `#[attr] expr,` + // always captures a trailing comma + TrailingToken::MaybeComma }; Ok((res, trailing)) }) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 70dbaa53d3..acf3867cf8 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -103,20 +103,11 @@ impl<'a> Parser<'a> { // over when we bump the parser if let token::Interpolated(nt) = &self.token.kind { if let token::NtItem(item) = &**nt { - let item = item.clone(); - - return self.collect_tokens_trailing_token( - attrs, - force_collect, - |this, mut attrs| { - let mut item = item; - mem::swap(&mut item.attrs, &mut attrs); - item.attrs.extend(attrs); - // Bump the parser so the we capture the token::Interpolated - this.bump(); - Ok((Some(item.into_inner()), TrailingToken::None)) - }, - ); + let mut item = item.clone(); + self.bump(); + + attrs.prepend_to_nt_inner(&mut item.attrs); + return Ok(Some(item.into_inner())); } }; @@ -530,7 +521,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item())?; + let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?; let item_kind = match ty_second { Some(ty_second) => { @@ -718,22 +709,32 @@ impl<'a> Parser<'a> { } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - let items = self.parse_item_list(attrs, |p| p.parse_trait_item())?; + let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?; Ok((ident, ItemKind::Trait(box TraitKind(is_auto, unsafety, tps, bounds, items)))) } } - pub fn parse_impl_item(&mut self) -> PResult<'a, Option>>> { - self.parse_assoc_item(|_| true) + pub fn parse_impl_item( + &mut self, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + self.parse_assoc_item(|_| true, force_collect) } - pub fn parse_trait_item(&mut self) -> PResult<'a, Option>>> { - self.parse_assoc_item(|edition| edition >= Edition::Edition2018) + pub fn parse_trait_item( + &mut self, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + self.parse_assoc_item(|edition| edition >= Edition::Edition2018, force_collect) } /// Parses associated items. - fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { - Ok(self.parse_item_(req_name, ForceCollect::No)?.map( + fn parse_assoc_item( + &mut self, + req_name: ReqName, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + Ok(self.parse_item_(req_name, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, @@ -918,14 +919,17 @@ impl<'a> Parser<'a> { unsafety: Unsafe, ) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - let items = self.parse_item_list(attrs, |p| p.parse_foreign_item())?; + let items = self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?; let module = ast::ForeignMod { unsafety, abi, items }; Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } /// Parses a foreign item (one in an `extern { ... }` block). - pub fn parse_foreign_item(&mut self) -> PResult<'a, Option>>> { - Ok(self.parse_item_(|_| true, ForceCollect::No)?.map( + pub fn parse_foreign_item( + &mut self, + force_collect: ForceCollect, + ) -> PResult<'a, Option>>> { + Ok(self.parse_item_(|_| true, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, @@ -1444,7 +1448,7 @@ impl<'a> Parser<'a> { Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) } - /// Is this unambiguously the start of a `macro_rules! foo` item defnition? + /// Is this unambiguously the start of a `macro_rules! foo` item definition? fn is_macro_rules_item(&mut self) -> bool { self.check_keyword(kw::MacroRules) && self.look_ahead(1, |t| *t == token::Not) @@ -1474,7 +1478,15 @@ impl<'a> Parser<'a> { let vstr = pprust::vis_to_string(vis); let vstr = vstr.trim_end(); if macro_rules { - self.sess.gated_spans.gate(sym::pub_macro_rules, vis.span); + let msg = format!("can't qualify macro_rules invocation with `{}`", vstr); + self.struct_span_err(vis.span, &msg) + .span_suggestion( + vis.span, + "try exporting the macro", + "#[macro_export]".to_owned(), + Applicability::MaybeIncorrect, // speculative + ) + .emit(); } else { self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`") .span_suggestion( diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4cc2224d27..a55eb3cf75 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -14,18 +14,21 @@ use crate::lexer::UnmatchedBrace; pub use attr_wrapper::AttrWrapper; pub use diagnostics::AttemptLocalParseRecovery; use diagnostics::Error; -pub use pat::{GateOr, RecoverComma}; +pub use pat::RecoverComma; pub use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{self, DelimToken, Token, TokenKind}; +use rustc_ast::tokenstream::AttributesData; use rustc_ast::tokenstream::{self, DelimSpan, Spacing}; -use rustc_ast::tokenstream::{TokenStream, TokenTree, TreeAndSpacing}; +use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::AttrId; use rustc_ast::DUMMY_NODE_ID; use rustc_ast::{self as ast, AnonConst, AstLike, AttrStyle, AttrVec, Const, CrateSugar, Extern}; use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacDelimiter, Mutability, StrLit, Unsafe}; use rustc_ast::{Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError}; @@ -34,6 +37,7 @@ use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use tracing::debug; +use std::ops::Range; use std::{cmp, mem, slice}; bitflags::bitflags! { @@ -64,6 +68,7 @@ pub enum ForceCollect { No, } +#[derive(Debug, Eq, PartialEq)] pub enum TrailingToken { None, Semi, @@ -111,6 +116,7 @@ pub struct Parser<'a> { pub token_spacing: Spacing, /// The previous token. pub prev_token: Token, + pub capture_cfg: bool, restrictions: Restrictions, expected_tokens: Vec, // Important: This must only be advanced from `next_tok` @@ -134,6 +140,44 @@ pub struct Parser<'a> { pub last_type_ascription: Option<(Span, bool /* likely path typo */)>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. subparser_name: Option<&'static str>, + capture_state: CaptureState, +} + +/// Indicates a range of tokens that should be replaced by +/// the tokens in the provided vector. This is used in two +/// places during token collection: +/// +/// 1. During the parsing of an AST node that may have a `#[derive]` +/// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]` +/// In this case, we use a `ReplaceRange` to replace the entire inner AST node +/// with `FlatToken::AttrTarget`, allowing us to perform eager cfg-expansion +/// on a `AttrAnnotatedTokenStream` +/// +/// 2. When we parse an inner attribute while collecting tokens. We +/// remove inner attributes from the token stream entirely, and +/// instead track them through the `attrs` field on the AST node. +/// This allows us to easily manipulate them (for example, removing +/// the first macro inner attribute to invoke a proc-macro). +/// When create a `TokenStream`, the inner attributes get inserted +/// into the proper place in the token stream. +pub type ReplaceRange = (Range, Vec<(FlatToken, Spacing)>); + +/// Controls how we capture tokens. Capturing can be expensive, +/// so we try to avoid performing capturing in cases where +/// we will never need a `AttrAnnotatedTokenStream` +#[derive(Copy, Clone)] +pub enum Capturing { + /// We aren't performing any capturing - this is the default mode. + No, + /// We are capturing tokens + Yes, +} + +#[derive(Clone)] +struct CaptureState { + capturing: Capturing, + replace_ranges: Vec, + inner_attr_ranges: FxHashMap, } impl<'a> Drop for Parser<'a> { @@ -167,11 +211,11 @@ struct TokenCursor { // want to capture just the first 'unglued' token. // For example, capturing the `Vec` // in `Option>` requires us to unglue - // the trailing `>>` token. The `append_unglued_token` + // the trailing `>>` token. The `break_last_token` // field is used to track this token - it gets // appended to the captured stream when // we evaluate a `LazyTokenStream` - append_unglued_token: Option, + break_last_token: bool, } #[derive(Clone)] @@ -188,9 +232,9 @@ impl TokenCursorFrame { TokenCursorFrame { delim, span, - open_delim: delim == token::NoDelim, + open_delim: false, tree_cursor: tts.into_trees(), - close_delim: delim == token::NoDelim, + close_delim: false, } } } @@ -364,19 +408,24 @@ impl<'a> Parser<'a> { desugar_doc_comments: bool, subparser_name: Option<&'static str>, ) -> Self { + let mut start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens); + start_frame.open_delim = true; + start_frame.close_delim = true; + let mut parser = Parser { sess, token: Token::dummy(), token_spacing: Spacing::Alone, prev_token: Token::dummy(), + capture_cfg: false, restrictions: Restrictions::empty(), expected_tokens: Vec::new(), token_cursor: TokenCursor { - frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens), + frame: start_frame, stack: Vec::new(), num_next_calls: 0, desugar_doc_comments, - append_unglued_token: None, + break_last_token: false, }, desugar_doc_comments, unmatched_angle_bracket_count: 0, @@ -385,6 +434,11 @@ impl<'a> Parser<'a> { last_unexpected_token_span: None, last_type_ascription: None, subparser_name, + capture_state: CaptureState { + capturing: Capturing::No, + replace_ranges: Vec::new(), + inner_attr_ranges: Default::default(), + }, }; // Make parser point to the first token. @@ -394,21 +448,29 @@ impl<'a> Parser<'a> { } fn next_tok(&mut self, fallback_span: Span) -> (Token, Spacing) { - let (mut next, spacing) = if self.desugar_doc_comments { - self.token_cursor.next_desugared() - } else { - self.token_cursor.next() - }; - self.token_cursor.num_next_calls += 1; - // We've retrieved an token from the underlying - // cursor, so we no longer need to worry about - // an unglued token. See `break_and_eat` for more details - self.token_cursor.append_unglued_token = None; - if next.span.is_dummy() { - // Tweak the location for better diagnostics, but keep syntactic context intact. - next.span = fallback_span.with_ctxt(next.span.ctxt()); + loop { + let (mut next, spacing) = if self.desugar_doc_comments { + self.token_cursor.next_desugared() + } else { + self.token_cursor.next() + }; + self.token_cursor.num_next_calls += 1; + // We've retrieved an token from the underlying + // cursor, so we no longer need to worry about + // an unglued token. See `break_and_eat` for more details + self.token_cursor.break_last_token = false; + if next.span.is_dummy() { + // Tweak the location for better diagnostics, but keep syntactic context intact. + next.span = fallback_span.with_ctxt(next.span.ctxt()); + } + if matches!( + next.kind, + token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) + ) { + continue; + } + return (next, spacing); } - (next, spacing) } pub fn unexpected(&mut self) -> PResult<'a, T> { @@ -606,8 +668,7 @@ impl<'a> Parser<'a> { // If we consume any additional tokens, then this token // is not needed (we'll capture the entire 'glued' token), // and `next_tok` will set this field to `None` - self.token_cursor.append_unglued_token = - Some((TokenTree::Token(self.token.clone()), Spacing::Alone)); + self.token_cursor.break_last_token = true; // Use the spacing of the glued token as the spacing // of the unglued second token. self.bump_with((Token::new(second, second_span), self.token_spacing)); @@ -688,6 +749,8 @@ impl<'a> Parser<'a> { let mut recovered = false; let mut trailing = false; let mut v = vec![]; + let unclosed_delims = !self.unclosed_delims.is_empty(); + while !self.expect_any_with_type(kets, expect) { if let token::CloseDelim(..) | token::Eof = self.token.kind { break; @@ -708,7 +771,7 @@ impl<'a> Parser<'a> { // Attempt to keep parsing if it was a similar separator. if let Some(ref tokens) = t.similar_tokens() { - if tokens.contains(&self.token.kind) { + if tokens.contains(&self.token.kind) && !unclosed_delims { self.bump(); } } @@ -867,15 +930,38 @@ impl<'a> Parser<'a> { } let frame = &self.token_cursor.frame; - match frame.tree_cursor.look_ahead(dist - 1) { - Some(tree) => match tree { - TokenTree::Token(token) => looker(token), - TokenTree::Delimited(dspan, delim, _) => { - looker(&Token::new(token::OpenDelim(*delim), dspan.open)) - } - }, - None => looker(&Token::new(token::CloseDelim(frame.delim), frame.span.close)), + if frame.delim != DelimToken::NoDelim { + let all_normal = (0..dist).all(|i| { + let token = frame.tree_cursor.look_ahead(i); + !matches!(token, Some(TokenTree::Delimited(_, DelimToken::NoDelim, _))) + }); + if all_normal { + return match frame.tree_cursor.look_ahead(dist - 1) { + Some(tree) => match tree { + TokenTree::Token(token) => looker(token), + TokenTree::Delimited(dspan, delim, _) => { + looker(&Token::new(token::OpenDelim(*delim), dspan.open)) + } + }, + None => looker(&Token::new(token::CloseDelim(frame.delim), frame.span.close)), + }; + } } + + let mut cursor = self.token_cursor.clone(); + let mut i = 0; + let mut token = Token::dummy(); + while i < dist { + token = cursor.next().0; + if matches!( + token.kind, + token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) + ) { + continue; + } + i += 1; + } + return looker(&token); } /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. @@ -987,12 +1073,15 @@ impl<'a> Parser<'a> { } // Collect tokens because they are used during lowering to HIR. - let expr = self.collect_tokens_no_attrs(|this| this.parse_expr())?; + let expr = self.parse_expr_force_collect()?; let span = expr.span; match &expr.kind { - // Not gated to supporte things like `doc = $expr` that work on stable. - _ if is_interpolated_expr => {} + // Not gated to support things like `doc = $expr` that work on stable. + // Do not gate in `capture_cfg` mode, since we flatten all nontemrinals + // before parsing. `capture_cfg` mode is only used to reparse existing + // tokens, so the gating will be performed by the initial parse + _ if is_interpolated_expr || self.capture_cfg => {} ExprKind::Lit(lit) if lit.kind.is_unsuffixed() => {} _ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span), } @@ -1287,3 +1376,24 @@ pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, sess: &Pa } } } + +/// A helper struct used when building a `AttrAnnotatedTokenStream` from +/// a `LazyTokenStream`. Both delimiter and non-delimited tokens +/// are stored as `FlatToken::Token`. A vector of `FlatToken`s +/// is then 'parsed' to build up a `AttrAnnotatedTokenStream` with nested +/// `AttrAnnotatedTokenTree::Delimited` tokens +#[derive(Debug, Clone)] +pub enum FlatToken { + /// A token - this holds both delimiter (e.g. '{' and '}') + /// and non-delimiter tokens + Token(Token), + /// Holds the `AttributesData` for an AST node. The + /// `AttributesData` is inserted directly into the + /// constructed `AttrAnnotatedTokenStream` as + /// a `AttrAnnotatedTokenTree::Attributes` + AttrTarget(AttributesData), + /// A special 'empty' token that is ignored during the conversion + /// to a `AttrAnnotatedTokenStream`. This is used to simplify the + /// handling of replace ranges. + Empty, +} diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index a84ae51514..0c43e304f1 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -4,7 +4,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; -use crate::parser::pat::{GateOr, RecoverComma}; +use crate::parser::pat::RecoverComma; use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle}; impl<'a> Parser<'a> { @@ -61,7 +61,8 @@ impl<'a> Parser<'a> { }, _ => false, }, - NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => match token.kind { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { + match token.kind { token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) token::OpenDelim(token::Paren) | // tuple pattern token::OpenDelim(token::Bracket) | // slice pattern @@ -75,10 +76,11 @@ impl<'a> Parser<'a> { token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(kind, NonterminalKind::Pat2021 {..}), + token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr {..}), token::Interpolated(ref nt) => may_be_ident(nt), _ => false, - }, + } + } NonterminalKind::Lifetime => match token.kind { token::Lifetime(_) => true, token::Interpolated(ref nt) => { @@ -118,32 +120,17 @@ impl<'a> Parser<'a> { return Err(self.struct_span_err(self.token.span, "expected a statement")); } }, - NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { token::NtPat(self.collect_tokens_no_attrs(|this| match kind { - NonterminalKind::Pat2018 { .. } => this.parse_pat_no_top_alt(None), - NonterminalKind::Pat2021 { .. } => { - this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No) + NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None), + NonterminalKind::PatWithOr { .. } => { + this.parse_pat_allow_top_alt(None, RecoverComma::No) } _ => unreachable!(), })?) } - // If there are attributes present, then `parse_expr` will end up collecting tokens, - // turning the outer `collect_tokens_no_attrs` into a no-op due to the already present - // tokens. If there are *not* attributes present, then the outer - // `collect_tokens_no_attrs` will ensure that we will end up collecting tokens for the - // expressions. - // - // This is less efficient than it could be, since the outer `collect_tokens_no_attrs` - // still needs to snapshot the `TokenCursor` before calling `parse_expr`, even when - // `parse_expr` will end up collecting tokens. Ideally, this would work more like - // `parse_item`, and take in a `ForceCollect` parameter. However, this would require - // adding a `ForceCollect` parameter in a bunch of places in expression parsing - // for little gain. If the perf impact from this turns out to be noticeable, we should - // revisit this apporach. - NonterminalKind::Expr => { - token::NtExpr(self.collect_tokens_no_attrs(|this| this.parse_expr())?) - } + NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes token::NtLiteral( @@ -168,9 +155,7 @@ impl<'a> Parser<'a> { NonterminalKind::Path => token::NtPath( self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?, ), - NonterminalKind::Meta => { - token::NtMeta(P(self.collect_tokens_no_attrs(|this| this.parse_attr_item(false))?)) - } + NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), NonterminalKind::TT => token::NtTT(self.parse_token_tree()), NonterminalKind::Vis => token::NtVis( self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 51c01f5a77..0abefbd6a1 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -17,13 +17,6 @@ pub(super) const PARAM_EXPECTED: Expected = Some("parameter name"); const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here"; -/// Whether or not an or-pattern should be gated when occurring in the current context. -#[derive(PartialEq, Clone, Copy)] -pub enum GateOr { - Yes, - No, -} - /// Whether or not to recover a `,` when parsing or-patterns. #[derive(PartialEq, Copy, Clone)] pub enum RecoverComma { @@ -64,10 +57,9 @@ impl<'a> Parser<'a> { pub fn parse_pat_allow_top_alt( &mut self, expected: Expected, - gate_or: GateOr, rc: RecoverComma, ) -> PResult<'a, P> { - self.parse_pat_allow_top_alt_inner(expected, gate_or, rc).map(|(pat, _)| pat) + self.parse_pat_allow_top_alt_inner(expected, rc).map(|(pat, _)| pat) } /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true = @@ -75,7 +67,6 @@ impl<'a> Parser<'a> { fn parse_pat_allow_top_alt_inner( &mut self, expected: Expected, - gate_or: GateOr, rc: RecoverComma, ) -> PResult<'a, (P, bool)> { // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated @@ -90,7 +81,7 @@ impl<'a> Parser<'a> { // Parse the first pattern (`p_0`). let first_pat = self.parse_pat_no_top_alt(expected)?; - self.maybe_recover_unexpected_comma(first_pat.span, rc, gate_or)?; + self.maybe_recover_unexpected_comma(first_pat.span, rc)?; // If the next token is not a `|`, // this is not an or-pattern and we should exit here. @@ -99,10 +90,6 @@ impl<'a> Parser<'a> { // then we should really gate the leading `|`. // This complicated procedure is done purely for diagnostics UX. if let Some(leading_vert_span) = leading_vert_span { - if gate_or == GateOr::Yes && self.sess.gated_spans.is_ungated(sym::or_patterns) { - self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span); - } - // If there was a leading vert, treat this as an or-pattern. This improves // diagnostics. let span = leading_vert_span.to(self.prev_token.span); @@ -128,16 +115,11 @@ impl<'a> Parser<'a> { err.span_label(lo, WHILE_PARSING_OR_MSG); err })?; - self.maybe_recover_unexpected_comma(pat.span, rc, gate_or)?; + self.maybe_recover_unexpected_comma(pat.span, rc)?; pats.push(pat); } let or_pattern_span = lo.to(self.prev_token.span); - // Feature gate the or-pattern if instructed: - if gate_or == GateOr::Yes { - self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span); - } - Ok((self.mk_pat(or_pattern_span, PatKind::Or(pats)), trailing_vert)) } @@ -152,14 +134,13 @@ impl<'a> Parser<'a> { pub(super) fn parse_pat_before_ty( &mut self, expected: Expected, - gate_or: GateOr, rc: RecoverComma, syntax_loc: &str, ) -> PResult<'a, (P, bool)> { // 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, gate_or, rc)?; + let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, rc)?; let colon = self.eat(&token::Colon); if let PatKind::Or(pats) = &pat.kind { @@ -213,12 +194,7 @@ impl<'a> Parser<'a> { self.bump(); } - self.parse_pat_before_ty( - PARAM_EXPECTED, - GateOr::No, - RecoverComma::No, - "function parameters", - ) + self.parse_pat_before_ty(PARAM_EXPECTED, RecoverComma::No, "function parameters") } /// Eat the or-pattern `|` separator. @@ -287,12 +263,7 @@ impl<'a> Parser<'a> { /// Some special error handling for the "top-level" patterns in a match arm, /// `for` loop, `let`, &c. (in contrast to subpatterns within such). - fn maybe_recover_unexpected_comma( - &mut self, - lo: Span, - rc: RecoverComma, - gate_or: GateOr, - ) -> PResult<'a, ()> { + fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> { if rc == RecoverComma::No || self.token != token::Comma { return Ok(()); } @@ -313,22 +284,18 @@ impl<'a> Parser<'a> { if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { const MSG: &str = "try adding parentheses to match on a tuple..."; - let or_suggestion = - gate_or == GateOr::No || !self.sess.gated_spans.is_ungated(sym::or_patterns); err.span_suggestion( seq_span, - if or_suggestion { MSG } else { MSG.trim_end_matches('.') }, + MSG, format!("({})", seq_snippet), Applicability::MachineApplicable, ); - if or_suggestion { - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(",", " |"), - Applicability::MachineApplicable, - ); - } + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(",", " |"), + Applicability::MachineApplicable, + ); } Err(err) } @@ -383,7 +350,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, GateOr::Yes, RecoverComma::No) + p.parse_pat_allow_top_alt(None, RecoverComma::No) })?; PatKind::Slice(pats) } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) { @@ -596,9 +563,8 @@ 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, GateOr::Yes, RecoverComma::No) - })?; + let (fields, trailing_comma) = + self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?; // Here, `(pat,)` is a tuple pattern. // For backward compatibility, `(..)` is a tuple pattern as well. @@ -911,9 +877,8 @@ impl<'a> Parser<'a> { if qself.is_some() { return self.error_qpath_before_pat(&path, "("); } - let (fields, _) = self.parse_paren_comma_seq(|p| { - p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No) - })?; + let (fields, _) = + self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?; Ok(PatKind::TupleStruct(path, fields)) } @@ -1079,7 +1044,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, GateOr::Yes, RecoverComma::No)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No)?; hi = pat.span; (pat, fieldname, false) } else { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 92e67e7929..592f64f4a3 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1,7 +1,7 @@ use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN; use super::diagnostics::{AttemptLocalParseRecovery, Error}; use super::expr::LhsExpr; -use super::pat::{GateOr, RecoverComma}; +use super::pat::RecoverComma; use super::path::PathStyle; use super::TrailingToken; use super::{AttrWrapper, BlockMode, ForceCollect, Parser, Restrictions, SemiColonMode}; @@ -48,39 +48,26 @@ impl<'a> Parser<'a> { if let token::Interpolated(nt) = &self.token.kind { if let token::NtStmt(stmt) = &**nt { let mut stmt = stmt.clone(); - return self.collect_tokens_trailing_token( - attrs, - force_collect, - |this, mut attrs| { - stmt.visit_attrs(|stmt_attrs| { - mem::swap(stmt_attrs, &mut attrs); - stmt_attrs.extend(attrs); - }); - // Make sure we capture the token::Interpolated - this.bump(); - Ok((Some(stmt), TrailingToken::None)) - }, - ); + self.bump(); + stmt.visit_attrs(|stmt_attrs| { + attrs.prepend_to_nt_inner(stmt_attrs); + }); + return Ok(Some(stmt)); } } Ok(Some(if self.token.is_keyword(kw::Let) { self.parse_local_mk(lo, attrs, capture_semi, force_collect)? } else if self.is_kw_followed_by_ident(kw::Mut) { - self.recover_stmt_local( - lo, - attrs.take_for_recovery().into(), - "missing keyword", - "let mut", - )? + self.recover_stmt_local(lo, attrs, "missing keyword", "let mut")? } else if self.is_kw_followed_by_ident(kw::Auto) { self.bump(); // `auto` let msg = "write `let` instead of `auto` to introduce a new variable"; - self.recover_stmt_local(lo, attrs.take_for_recovery().into(), msg, "let")? + self.recover_stmt_local(lo, attrs, msg, "let")? } else if self.is_kw_followed_by_ident(sym::var) { self.bump(); // `var` let msg = "write `let` instead of `var` to introduce a new variable"; - self.recover_stmt_local(lo, attrs.take_for_recovery().into(), msg, "let")? + self.recover_stmt_local(lo, attrs, msg, "let")? } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something @@ -112,7 +99,7 @@ impl<'a> Parser<'a> { attrs: AttrWrapper, force_collect: ForceCollect, ) -> PResult<'a, Stmt> { - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + let stmt = self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { let path = this.parse_path(PathStyle::Expr)?; if this.eat(&token::Not) { @@ -132,14 +119,22 @@ impl<'a> Parser<'a> { }; let expr = this.with_res(Restrictions::STMT_EXPR, |this| { - let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs)?; + this.parse_dot_or_call_expr_with(expr, lo, attrs) + })?; + // `DUMMY_SP` will get overwritten later in this function + Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), TrailingToken::None)) + })?; + + if let StmtKind::Expr(expr) = stmt.kind { + // Perform this outside of the `collect_tokens_trailing_token` closure, + // since our outer attributes do not apply to this part of the expression + let expr = self.with_res(Restrictions::STMT_EXPR, |this| { this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr)) })?; - Ok(( - this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Expr(expr)), - TrailingToken::None, - )) - }) + Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) + } else { + Ok(stmt) + } } /// Parses a statement macro `mac!(args)` provided a `path` representing `mac`. @@ -183,7 +178,7 @@ impl<'a> Parser<'a> { fn recover_stmt_local( &mut self, lo: Span, - attrs: AttrVec, + attrs: AttrWrapper, msg: &str, sugg: &str, ) -> PResult<'a, Stmt> { @@ -213,16 +208,21 @@ impl<'a> Parser<'a> { }) } - fn recover_local_after_let(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> { - let local = self.parse_local(attrs)?; - Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Local(local))) + fn recover_local_after_let(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> { + self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + let local = this.parse_local(attrs.into())?; + // FIXME - maybe capture semicolon in recovery? + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), + TrailingToken::None, + )) + }) } /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; - let (pat, colon) = - self.parse_pat_before_ty(None, GateOr::Yes, RecoverComma::Yes, "`let` bindings")?; + let (pat, colon) = self.parse_pat_before_ty(None, RecoverComma::Yes, "`let` bindings")?; let (err, ty) = if colon { // Save the state of the parser before parsing type normally, in case there is a `:` diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 92d974690b..50db69f420 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -10,7 +10,7 @@ test(attr(deny(warnings))) )] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(bool_to_option)] pub use Alignment::*; @@ -213,11 +213,13 @@ impl<'a> Iterator for Parser<'a> { Some(String(self.string(pos + 1))) } else { let arg = self.argument(); - if let Some(end) = self.must_consume('}') { - let start = self.to_span_index(pos); - let end = self.to_span_index(end + 1); + if let Some(rbrace_byte_idx) = self.must_consume('}') { + let lbrace_inner_offset = self.to_span_index(pos); + let rbrace_inner_offset = self.to_span_index(rbrace_byte_idx); if self.is_literal { - self.arg_places.push(start.to(end)); + self.arg_places.push( + lbrace_inner_offset.to(InnerOffset(rbrace_inner_offset.0 + 1)), + ); } } Some(NextArgument(arg)) @@ -735,25 +737,24 @@ fn find_skips_from_snippet( }; fn find_skips(snippet: &str, is_raw: bool) -> Vec { - let mut eat_ws = false; let mut s = snippet.char_indices().peekable(); let mut skips = vec![]; while let Some((pos, c)) = s.next() { match (c, s.peek()) { // skip whitespace and empty lines ending in '\\' ('\\', Some((next_pos, '\n'))) if !is_raw => { - eat_ws = true; skips.push(pos); skips.push(*next_pos); let _ = s.next(); - } - ('\\', Some((next_pos, '\n' | 'n' | 't'))) if eat_ws => { - skips.push(pos); - skips.push(*next_pos); - let _ = s.next(); - } - (' ' | '\n' | '\t', _) if eat_ws => { - skips.push(pos); + + while let Some((pos, c)) = s.peek() { + if matches!(c, ' ' | '\n' | '\t') { + skips.push(*pos); + let _ = s.next(); + } else { + break; + } + } } ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { skips.push(*next_pos); @@ -804,10 +805,6 @@ fn find_skips_from_snippet( } } } - _ if eat_ws => { - // `take_while(|c| c.is_whitespace())` - eat_ws = false; - } _ => {} } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d91d0e1765..3ffe488cae 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_ast::{Attribute, Lit, LitKind, NestedMetaItem}; -use rustc_errors::{pluralize, struct_span_err}; +use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -69,49 +69,48 @@ impl CheckAttrVisitor<'tcx> { let mut is_valid = true; let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { - is_valid &= if self.tcx.sess.check_name(attr, sym::inline) { - self.check_inline(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::non_exhaustive) { - self.check_non_exhaustive(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::marker) { - self.check_marker(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::target_feature) { - self.check_target_feature(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::track_caller) { - self.check_track_caller(hir_id, &attr.span, attrs, span, target) - } else if self.tcx.sess.check_name(attr, sym::doc) { - self.check_doc_attrs(attr, hir_id, target) - } else if self.tcx.sess.check_name(attr, sym::no_link) { - self.check_no_link(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::export_name) { - self.check_export_name(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_args_required_const) { - self.check_rustc_args_required_const(&attr, span, target, item) - } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_start) { - self.check_rustc_layout_scalar_valid_range(&attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_end) { - self.check_rustc_layout_scalar_valid_range(&attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) { - self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs) - } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) { - self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::naked) { - self.check_naked(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_legacy_const_generics) { - self.check_rustc_legacy_const_generics(&attr, span, target, item) - } else { - // lint-only checks - if self.tcx.sess.check_name(attr, sym::cold) { - self.check_cold(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::link_name) { - self.check_link_name(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::link_section) { - self.check_link_section(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::no_mangle) { - self.check_no_mangle(hir_id, attr, span, target); + is_valid &= match attr.name_or_empty() { + sym::inline => self.check_inline(hir_id, attr, span, target), + sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), + sym::marker => self.check_marker(hir_id, attr, span, target), + sym::target_feature => self.check_target_feature(hir_id, attr, span, target), + sym::track_caller => { + self.check_track_caller(hir_id, &attr.span, attrs, span, target) } - true + sym::doc => self.check_doc_attrs(attr, hir_id, target), + sym::no_link => self.check_no_link(hir_id, &attr, span, target), + sym::export_name => self.check_export_name(hir_id, &attr, span, target), + sym::rustc_args_required_const => { + self.check_rustc_args_required_const(&attr, span, target, item) + } + sym::rustc_layout_scalar_valid_range_start + | sym::rustc_layout_scalar_valid_range_end => { + self.check_rustc_layout_scalar_valid_range(&attr, span, target) + } + sym::allow_internal_unstable => { + self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs) + } + sym::rustc_allow_const_fn_unstable => { + self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) + } + sym::naked => self.check_naked(hir_id, attr, span, target), + sym::rustc_legacy_const_generics => { + self.check_rustc_legacy_const_generics(&attr, span, target, item) + } + sym::rustc_clean + | sym::rustc_dirty + | sym::rustc_if_this_changed + | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), + _ => true, }; + // lint-only checks + match attr.name_or_empty() { + sym::cold => self.check_cold(hir_id, attr, span, target), + sym::link_name => self.check_link_name(hir_id, attr, span, target), + sym::link_section => self.check_link_section(hir_id, attr, span, target), + sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target), + _ => {} + } } if !is_valid { @@ -642,10 +641,10 @@ impl CheckAttrVisitor<'tcx> { | sym::masked | sym::no_default_passes | sym::no_inline + | sym::notable_trait | sym::passes | sym::plugins | sym::primitive - | sym::spotlight | sym::test => {} _ => { @@ -654,11 +653,23 @@ impl CheckAttrVisitor<'tcx> { hir_id, i_meta.span, |lint| { - let msg = format!( + let mut diag = lint.build(&format!( "unknown `doc` attribute `{}`", rustc_ast_pretty::pprust::path_to_string(&i_meta.path), - ); - lint.build(&msg).emit(); + )); + if i_meta.has_name(sym::spotlight) { + diag.note( + "`doc(spotlight)` was renamed to `doc(notable_trait)`", + ); + diag.span_suggestion_short( + i_meta.span, + "use `notable_trait` instead", + String::from("notable_trait"), + Applicability::MachineApplicable, + ); + diag.note("`doc(spotlight)` is now a no-op"); + } + diag.emit(); }, ); is_valid = false; @@ -1012,6 +1023,20 @@ impl CheckAttrVisitor<'tcx> { } } + /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph + /// option is passed to the compiler. + fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool { + if self.tcx.sess.opts.debugging_opts.query_dep_graph { + true + } else { + self.tcx + .sess + .struct_span_err(attr.span, "attribute requires -Z query-dep-graph to be enabled") + .emit(); + false + } + } + /// Checks if `#[link_section]` is applied to a function or static. fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) { match target { @@ -1084,7 +1109,7 @@ impl CheckAttrVisitor<'tcx> { // ``` let hints: Vec<_> = attrs .iter() - .filter(|attr| self.tcx.sess.check_name(attr, sym::repr)) + .filter(|attr| attr.has_name(sym::repr)) .filter_map(|attr| attr.meta_item_list()) .flatten() .collect(); @@ -1221,7 +1246,7 @@ impl CheckAttrVisitor<'tcx> { fn check_used(&self, attrs: &'hir [Attribute], target: Target) { for attr in attrs { - if self.tcx.sess.check_name(attr, sym::used) && target != Target::Static { + if attr.has_name(sym::used) && target != Target::Static { self.tcx .sess .span_err(attr.span, "attribute must be applied to a `static` variable"); @@ -1423,7 +1448,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::path, sym::automatically_derived, sym::start, - sym::main, + sym::rustc_main, ]; for attr in attrs { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9d70bc4a82..c671035bb7 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -451,7 +451,9 @@ fn create_and_seed_worklist<'tcx>( ) .chain( // Seed entry point - tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().local_def_id_to_hir_id(def_id)), + tcx.entry_fn(LOCAL_CRATE).and_then(|(def_id, _)| { + def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) + }), ) .collect::>(); diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 57848208f9..65cfe986ad 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,12 +1,13 @@ use rustc_ast::entry::EntryPointType; use rustc_errors::struct_span_err; -use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, 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_middle::hir::map::Map; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::config::{CrateType, EntryFnType}; +use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -16,9 +17,6 @@ struct EntryContext<'a, 'tcx> { map: Map<'tcx>, - /// The top-level function called `main`. - main_fn: Option<(HirId, Span)>, - /// The function that has attribute named `main`. attr_main_fn: Option<(HirId, Span)>, @@ -50,7 +48,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { } } -fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> { +fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { assert_eq!(cnum, LOCAL_CRATE); let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable); @@ -67,7 +65,6 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType) let mut ctxt = EntryContext { session: tcx.sess, map: tcx.hir(), - main_fn: None, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new(), @@ -84,7 +81,7 @@ fn entry_point_type(ctxt: &EntryContext<'_, '_>, item: &Item<'_>, at_root: bool) let attrs = ctxt.map.attrs(item.hir_id()); if ctxt.session.contains_name(attrs, sym::start) { EntryPointType::Start - } else if ctxt.session.contains_name(attrs, sym::main) { + } else if ctxt.session.contains_name(attrs, sym::rustc_main) { EntryPointType::MainAttr } else if item.ident.name == sym::main { if at_root { @@ -111,18 +108,11 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) { throw_attr_err(&ctxt.session, attr.span, "start"); } - if let Some(attr) = ctxt.session.find_by_name(attrs, sym::main) { - throw_attr_err(&ctxt.session, attr.span, "main"); - } - } - EntryPointType::MainNamed => { - if ctxt.main_fn.is_none() { - ctxt.main_fn = Some((item.hir_id(), item.span)); - } else { - struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions") - .emit(); + if let Some(attr) = ctxt.session.find_by_name(attrs, sym::rustc_main) { + throw_attr_err(&ctxt.session, attr.span, "rustc_main"); } } + EntryPointType::MainNamed => (), EntryPointType::OtherMain => { ctxt.non_main_fns.push((item.hir_id(), item.span)); } @@ -154,16 +144,23 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { } } -fn configure_main( - tcx: TyCtxt<'_>, - visitor: &EntryContext<'_, '_>, -) -> Option<(LocalDefId, EntryFnType)> { +fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(DefId, EntryFnType)> { if let Some((hir_id, _)) = visitor.start_fn { - Some((tcx.hir().local_def_id(hir_id), EntryFnType::Start)) + 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), EntryFnType::Main)) - } else if let Some((hir_id, _)) = visitor.main_fn { - Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main)) + 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 { no_main_err(tcx, visitor); None @@ -171,7 +168,7 @@ fn configure_main( } fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { - let sp = tcx.hir().krate().item.span; + let sp = tcx.hir().krate().item.inner; if *tcx.sess.parse_sess.reached_eof.borrow() { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. @@ -193,10 +190,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { err.span_note(span, "here is a function named `main`"); } err.note("you have one or more functions named `main` not defined at the crate level"); - err.help( - "either move the `main` function definitions or attach the `#[main]` attribute \ - to one of them", - ); + err.help("consider moving the `main` function definitions"); // There were some functions named `main` though. Try to give the user a hint. format!( "the main function must be defined at the crate level{}", @@ -216,6 +210,14 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { } else { err.note(¬e); } + + if let Some(main_def) = tcx.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")); + } + } + if tcx.sess.teach(&err.get_code().unwrap()) { err.note( "If you don't know the basics of Rust, you can go look to the Rust Book \ @@ -225,7 +227,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { err.emit(); } -pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(LocalDefId, EntryFnType)> { +pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> { tcx.entry_fn(LOCAL_CRATE) } diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 79e3b5952a..944a3097a6 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -172,17 +172,4 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { // we are currently in. So for those it's correct that they have a // different owner. } - - fn visit_generic_param(&mut self, param: &'hir hir::GenericParam<'hir>) { - if let hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } = param.kind - { - // Synthetic impl trait parameters are owned by the node of the desugared type. - // This means it is correct for them to have a different owner. - } else { - intravisit::walk_generic_param(self, param); - } - } } diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 0f4bb635ee..3f095d0e82 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -347,7 +347,7 @@ impl ExprVisitor<'tcx> { } fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { - for (idx, (op, _op_sp)) in asm.operands.iter().enumerate() { + for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { match *op { hir::InlineAsmOperand::In { reg, ref expr } => { self.check_asm_operand_type(idx, reg, expr, asm.template, None); @@ -372,14 +372,15 @@ impl ExprVisitor<'tcx> { ); } } - hir::InlineAsmOperand::Const { ref expr } => { - let ty = self.typeck_results.expr_ty_adjusted(expr); - match ty.kind() { + hir::InlineAsmOperand::Const { ref anon_const } => { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + match value.ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Float(_) => {} _ => { let msg = "asm `const` arguments must be integer or floating-point values"; - self.tcx.sess.span_err(expr.span, msg); + self.tcx.sess.span_err(*op_sp, msg); } } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 9759a500e0..0be7ef7e12 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -5,12 +5,12 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(const_fn)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 9aef49df7b..fa930471c2 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -103,6 +103,7 @@ use rustc_span::Span; use std::collections::VecDeque; use std::io; use std::io::prelude::*; +use std::iter; use std::rc::Rc; mod rwu_table; @@ -1066,7 +1067,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { expr, .. } - | hir::InlineAsmOperand::Const { expr, .. } | hir::InlineAsmOperand::Sym { expr, .. } => { succ = self.propagate_through_expr(expr, succ) } @@ -1084,6 +1084,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } succ = self.propagate_through_expr(in_expr, succ); } + hir::InlineAsmOperand::Const { .. } => {} } } succ @@ -1093,7 +1094,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let ia = &asm.inner; let outputs = asm.outputs_exprs; let inputs = asm.inputs_exprs; - let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| { + let succ = iter::zip(&ia.outputs, outputs).rev().fold(succ, |succ, (o, output)| { // see comment on places // in propagate_through_place_components() if o.is_indirect { @@ -1344,7 +1345,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { } // Output operands must be places - for (o, output) in asm.inner.outputs.iter().zip(asm.outputs_exprs) { + for (o, output) in iter::zip(&asm.inner.outputs, asm.outputs_exprs) { if !o.is_indirect { this.check_place(output); } @@ -1475,7 +1476,7 @@ impl<'tcx> Liveness<'_, 'tcx> { for p in body.params { self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| { if !self.live_on_entry(ln, var) { - self.report_unsed_assign(hir_id, spans, var, |name| { + self.report_unused_assign(hir_id, spans, var, |name| { format!("value passed to `{}` is never read", name) }); } @@ -1614,13 +1615,13 @@ impl<'tcx> Liveness<'_, 'tcx> { fn warn_about_dead_assign(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { if !self.live_on_exit(ln, var) { - self.report_unsed_assign(hir_id, spans, var, |name| { + self.report_unused_assign(hir_id, spans, var, |name| { format!("value assigned to `{}` is never read", name) }); } } - fn report_unsed_assign( + fn report_unused_assign( &self, hir_id: HirId, spans: Vec, diff --git a/compiler/rustc_passes/src/liveness/rwu_table.rs b/compiler/rustc_passes/src/liveness/rwu_table.rs index a1a6f27398..6d5983f53d 100644 --- a/compiler/rustc_passes/src/liveness/rwu_table.rs +++ b/compiler/rustc_passes/src/liveness/rwu_table.rs @@ -1,4 +1,5 @@ use crate::liveness::{LiveNode, Variable}; +use std::iter; #[derive(Clone, Copy)] pub(super) struct RWU { @@ -91,7 +92,7 @@ impl RWUTable { let mut changed = false; let (dst_row, src_row) = self.pick2_rows_mut(dst, src); - for (dst_word, src_word) in dst_row.iter_mut().zip(src_row.iter()) { + for (dst_word, src_word) in iter::zip(dst_row, &*src_row) { let old = *dst_word; let new = *dst_word | src_word; *dst_word = new; diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index b532021bed..14a373c594 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -23,14 +23,6 @@ use std::mem; #[derive(Debug, Copy, Clone)] pub struct Context { - /// The root of the current region tree. This is typically the id - /// of the innermost fn body. Each fn forms its own disjoint tree - /// in the region hierarchy. These fn bodies are themselves - /// arranged into a tree. See the "Modeling closures" section of - /// the README in `rustc_trait_selection::infer::region_constraints` - /// for more details. - root_id: Option, - /// The scope that contains any new variables declared, plus its depth in /// the scope tree. var_parent: Option<(Scope, ScopeDepth)>, @@ -743,11 +735,6 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); self.terminating_scopes.insert(body.value.hir_id.local_id); - if let Some(root_id) = self.cx.root_id { - self.scope_tree.record_closure_parent(body.value.hir_id.local_id, root_id); - } - self.cx.root_id = Some(body.value.hir_id.local_id); - self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite }); self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments }); @@ -824,7 +811,7 @@ fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { tcx, scope_tree: ScopeTree::default(), expr_and_pat_count: 0, - cx: Context { root_id: None, parent: None, var_parent: None }, + cx: Context { parent: None, var_parent: None }, terminating_scopes: Default::default(), pessimistic_yield: false, fixup_scopes: vec![], diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index dd9cb51c85..9c4f9b1198 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -22,6 +22,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use std::cmp::Ordering; +use std::iter; use std::mem::replace; use std::num::NonZeroU32; @@ -214,7 +215,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { { // Explicit version of iter::order::lt to handle parse errors properly for (dep_v, stab_v) in - dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) + iter::zip(dep_since.as_str().split('.'), stab_since.as_str().split('.')) { match stab_v.parse::() { Err(_) => { @@ -507,10 +508,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { let kind = match &p.kind { - // FIXME(const_generics_defaults) - hir::GenericParamKind::Type { default, .. } if default.is_some() => { - AnnotationKind::Container - } + // Allow stability attributes on default generic arguments. + hir::GenericParamKind::Type { default: Some(_), .. } + | hir::GenericParamKind::Const { default: Some(_), .. } => AnnotationKind::Container, _ => AnnotationKind::Prohibited, }; @@ -686,7 +686,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { annotator.annotate( hir::CRATE_HIR_ID, - krate.item.span, + krate.item.inner, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -885,7 +885,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { if tcx.stability().staged_api[&LOCAL_CRATE] { let krate = tcx.hir().krate(); let mut missing = MissingStabilityAnnotations { tcx, access_levels }; - missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span); + missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.inner); intravisit::walk_crate(&mut missing, krate); krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 84240f86b5..d37a5be2fe 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,7 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(control_flow_enum)] #![feature(try_blocks)] #![feature(associated_type_defaults)] @@ -928,8 +928,11 @@ impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { self.visit(self.ev.tcx.type_of(param.def_id)); } } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { has_default, .. } => { self.visit(self.ev.tcx.type_of(param.def_id)); + if has_default { + self.visit(self.ev.tcx.const_param_default(param.def_id)); + } } } } @@ -1111,7 +1114,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { //////////////////////////////////////////////////////////////////////////////////////////// /// Type privacy visitor, checks types for privacy and reports violations. -/// Both explicitly written types and inferred types of expressions and patters are checked. +/// Both explicitly written types and inferred types of expressions and patterns are checked. /// Checks are performed on "semantic" types regardless of names and their hygiene. //////////////////////////////////////////////////////////////////////////////////////////// @@ -1741,7 +1744,8 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { self.visit(self.tcx.type_of(param.def_id)); } } - GenericParamDefKind::Const => { + // FIXME(const_evaluatable_checked): May want to look inside const here + GenericParamDefKind::Const { .. } => { self.visit(self.tcx.type_of(param.def_id)); } } diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index e467f41986..1fdb37398f 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -255,6 +255,15 @@ impl<'tcx> Key for GenericArg<'tcx> { } } +impl<'tcx> Key for mir::ConstantKind<'tcx> { + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for &'tcx ty::Const<'tcx> { fn query_crate(&self) -> CrateNum { LOCAL_CRATE diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index e9314797fb..00d886000f 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -19,8 +19,7 @@ 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::CrateNum; -use rustc_index::vec::IndexVec; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::dep_graph; use rustc_middle::ich::StableHashingContext; use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values}; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 37a176de94..ee914fa1ba 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -390,13 +390,12 @@ macro_rules! define_queries { #[inline] fn compute(tcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { - let provider = tcx.queries.providers.get(key.query_crate()) - // HACK(eddyb) it's possible crates may be loaded after - // the query engine is created, and because crate loading - // is not yet integrated with the query engine, such crates - // would be missing appropriate entries in `providers`. - .unwrap_or(&tcx.queries.fallback_extern_providers) - .$name; + let is_local = key.query_crate() == LOCAL_CRATE; + let provider = if is_local { + tcx.queries.local_providers.$name + } else { + tcx.queries.extern_providers.$name + }; provider(*tcx, key) } @@ -439,6 +438,11 @@ macro_rules! define_queries { try_load_from_on_disk_cache: |_, _| {}, }; + pub const CompileMonoItem: QueryStruct = QueryStruct { + force_from_dep_node: |_, _| false, + try_load_from_on_disk_cache: |_, _| {}, + }; + $(pub const $name: QueryStruct = { const is_anon: bool = is_anon!([$($modifiers)*]); @@ -478,10 +482,7 @@ macro_rules! define_queries { return } - debug_assert!(tcx.dep_graph - .node_color(dep_node) - .map(|c| c.is_green()) - .unwrap_or(false)); + debug_assert!(tcx.dep_graph.is_green(dep_node)); let key = recover(*tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)); if queries::$name::cache_on_disk(tcx, &key, None) { @@ -507,8 +508,8 @@ macro_rules! define_queries_struct { (tcx: $tcx:tt, input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => { pub struct Queries<$tcx> { - providers: IndexVec, - fallback_extern_providers: Box, + local_providers: Box, + extern_providers: Box, $($(#[$attr])* $name: QueryState< crate::dep_graph::DepKind, @@ -518,12 +519,12 @@ macro_rules! define_queries_struct { impl<$tcx> Queries<$tcx> { pub fn new( - providers: IndexVec, - fallback_extern_providers: Providers, + local_providers: Providers, + extern_providers: Providers, ) -> Self { Queries { - providers, - fallback_extern_providers: Box::new(fallback_extern_providers), + local_providers: Box::new(local_providers), + extern_providers: Box::new(extern_providers), $($name: Default::default()),* } } diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 2448588973..2517793ece 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -250,8 +250,8 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( // need to invoke queries itself, we cannot keep the query caches // locked while doing so. Instead we copy out the // `(query_key, dep_node_index)` pairs and release the lock again. - let query_keys_and_indices: Vec<_> = query_cache - .iter_results(|results| results.map(|(k, _, i)| (k.clone(), i)).collect()); + let mut query_keys_and_indices = Vec::new(); + query_cache.iter_results(&mut |k, _, i| query_keys_and_indices.push((k.clone(), i))); // Now actually allocate the strings. If allocating the strings // generates new entries in the query cache, we'll miss them but @@ -275,14 +275,15 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( let query_name = profiler.get_or_alloc_cached_string(query_name); let event_id = event_id_builder.from_label(query_name).to_string_id(); - query_cache.iter_results(|results| { - let query_invocation_ids: Vec<_> = results.map(|v| v.2.into()).collect(); - - profiler.bulk_map_query_invocation_id_to_single_string( - query_invocation_ids.into_iter(), - event_id, - ); + let mut query_invocation_ids = Vec::new(); + query_cache.iter_results(&mut |_, _, i| { + query_invocation_ids.push(i.into()); }); + + profiler.bulk_map_query_invocation_id_to_single_string( + query_invocation_ids.into_iter(), + event_id, + ); } }); } diff --git a/compiler/rustc_query_impl/src/stats.rs b/compiler/rustc_query_impl/src/stats.rs index 4d52483c3b..e877034bd7 100644 --- a/compiler/rustc_query_impl/src/stats.rs +++ b/compiler/rustc_query_impl/src/stats.rs @@ -50,13 +50,12 @@ where key_type: type_name::(), value_size: mem::size_of::(), value_type: type_name::(), - entry_count: map.iter_results(|results| results.count()), + entry_count: 0, local_def_id_keys: None, }; - map.iter_results(|results| { - for (key, _, _) in results { - key.key_stats(&mut stats) - } + map.iter_results(&mut |key, _, _| { + stats.entry_count += 1; + key.key_stats(&mut stats) }); stats } diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs index c6dc7b4fe2..d592812f79 100644 --- a/compiler/rustc_query_system/src/cache.rs +++ b/compiler/rustc_query_system/src/cache.rs @@ -3,7 +3,6 @@ use crate::dep_graph::{DepContext, DepNodeIndex}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::HashMapExt; use rustc_data_structures::sync::Lock; use std::hash::Hash; @@ -34,13 +33,6 @@ impl Cache { pub fn insert(&self, key: Key, dep_node: DepNodeIndex, value: Value) { self.hashmap.borrow_mut().insert(key, WithDepNode::new(dep_node, value)); } - - pub fn insert_same(&self, key: Key, dep_node: DepNodeIndex, value: Value) - where - Value: Eq, - { - self.hashmap.borrow_mut().insert_same(key, WithDepNode::new(dep_node, value)); - } } #[derive(Clone, Eq, PartialEq)] diff --git a/compiler/rustc_query_system/src/dep_graph/debug.rs b/compiler/rustc_query_system/src/dep_graph/debug.rs index 718a2f1039..a544ac2c34 100644 --- a/compiler/rustc_query_system/src/dep_graph/debug.rs +++ b/compiler/rustc_query_system/src/dep_graph/debug.rs @@ -1,6 +1,8 @@ //! Code for debugging the dep-graph. -use super::{DepKind, DepNode}; +use super::{DepKind, DepNode, DepNodeIndex}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Lock; use std::error::Error; /// A dep-node filter goes from a user-defined string to a query over @@ -34,13 +36,14 @@ impl DepNodeFilter { /// A filter like `F -> G` where `F` and `G` are valid dep-node /// filters. This can be used to test the source/target independently. -pub struct EdgeFilter { +pub struct EdgeFilter { pub source: DepNodeFilter, pub target: DepNodeFilter, + pub index_to_node: Lock>>, } -impl EdgeFilter { - pub fn new(test: &str) -> Result> { +impl EdgeFilter { + pub fn new(test: &str) -> Result, Box> { let parts: Vec<_> = test.split("->").collect(); if parts.len() != 2 { Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into()) @@ -48,11 +51,13 @@ impl EdgeFilter { Ok(EdgeFilter { source: DepNodeFilter::new(parts[0]), target: DepNodeFilter::new(parts[1]), + index_to_node: Lock::new(FxHashMap::default()), }) } } - pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { + #[cfg(debug_assertions)] + pub fn test(&self, source: &DepNode, target: &DepNode) -> bool { self.source.test(source) && self.target.test(target) } } diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index f55e2f777a..59ef6052a6 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -26,7 +26,7 @@ //! could not be instantiated because the current compilation session //! contained no `DefId` for thing that had been removed. //! -//! `DepNode` definition happens in `librustc_middle` with the `define_dep_nodes!()` macro. +//! `DepNode` definition happens in `rustc_middle` with the `define_dep_nodes!()` macro. //! This macro defines the `DepKind` enum and a corresponding `DepConstructor` enum. The //! `DepConstructor` enum links a `DepKind` to the parameters that are needed at runtime in order //! to construct a valid `DepNode` fingerprint. diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 0f25572170..7a0fc32066 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1,31 +1,33 @@ 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::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, LockGuard, Lrc, Ordering}; +use rustc_data_structures::steal::Steal; +use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; use rustc_data_structures::unlikely; use rustc_errors::Diagnostic; -use rustc_index::vec::{Idx, IndexVec}; -use rustc_serialize::{Encodable, Encoder}; +use rustc_index::vec::IndexVec; +use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use parking_lot::{Condvar, Mutex}; use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; -use std::env; use std::hash::Hash; use std::marker::PhantomData; use std::mem; -use std::ops::Range; use std::sync::atomic::Ordering::Relaxed; -use super::debug::EdgeFilter; use super::prev::PreviousDepGraph; use super::query::DepGraphQuery; -use super::serialized::SerializedDepNodeIndex; +use super::serialized::{GraphEncoder, SerializedDepNodeIndex}; use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; use crate::query::QueryContext; +#[cfg(debug_assertions)] +use {super::debug::EdgeFilter, std::env}; + #[derive(Clone)] pub struct DepGraph { data: Option>>, @@ -109,6 +111,9 @@ impl DepGraph { pub fn new( prev_graph: PreviousDepGraph, prev_work_products: FxHashMap, + encoder: FileEncoder, + record_graph: bool, + record_stats: bool, ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); @@ -116,7 +121,12 @@ impl DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, dep_node_debug: Default::default(), - current: CurrentDepGraph::new(prev_graph_node_count), + current: CurrentDepGraph::new( + prev_graph_node_count, + encoder, + record_graph, + record_stats, + ), emitting_diagnostics: Default::default(), emitting_diagnostics_cond_var: Condvar::new(), previous: prev_graph, @@ -136,62 +146,10 @@ impl DepGraph { self.data.is_some() } - pub fn query(&self) -> DepGraphQuery { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - - // Note locking order: `prev_index_to_index`, then `data`. - let prev_index_to_index = data.current.prev_index_to_index.lock(); - let data = data.current.data.lock(); - let node_count = data.hybrid_indices.len(); - let edge_count = self.edge_count(&data); - - let mut nodes = Vec::with_capacity(node_count); - let mut edge_list_indices = Vec::with_capacity(node_count); - let mut edge_list_data = Vec::with_capacity(edge_count); - - // See `DepGraph`'s `Encodable` implementation for notes on the approach used here. - - edge_list_data.extend(data.unshared_edges.iter().map(|i| i.index())); - - for &hybrid_index in data.hybrid_indices.iter() { - match hybrid_index.into() { - HybridIndex::New(new_index) => { - nodes.push(data.new.nodes[new_index]); - let edges = &data.new.edges[new_index]; - edge_list_indices.push((edges.start.index(), edges.end.index())); - } - HybridIndex::Red(red_index) => { - nodes.push(previous.index_to_node(data.red.node_indices[red_index])); - let edges = &data.red.edges[red_index]; - edge_list_indices.push((edges.start.index(), edges.end.index())); - } - HybridIndex::LightGreen(lg_index) => { - nodes.push(previous.index_to_node(data.light_green.node_indices[lg_index])); - let edges = &data.light_green.edges[lg_index]; - edge_list_indices.push((edges.start.index(), edges.end.index())); - } - HybridIndex::DarkGreen(prev_index) => { - nodes.push(previous.index_to_node(prev_index)); - - let edges_iter = previous - .edge_targets_from(prev_index) - .iter() - .map(|&dst| prev_index_to_index[dst].unwrap().index()); - - let start = edge_list_data.len(); - edge_list_data.extend(edges_iter); - let end = edge_list_data.len(); - edge_list_indices.push((start, end)); - } - } + pub fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + if let Some(data) = &self.data { + data.current.encoder.borrow().with_query(f) } - - debug_assert_eq!(nodes.len(), node_count); - debug_assert_eq!(edge_list_indices.len(), node_count); - debug_assert_eq!(edge_list_data.len(), edge_count); - - DepGraphQuery::new(&nodes[..], &edge_list_indices[..], &edge_list_data[..]) } pub fn assert_ignored(&self) { @@ -283,56 +241,16 @@ impl DepGraph { let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; // Intern the new `DepNode`. - let dep_node_index = if let Some(prev_index) = data.previous.node_to_index_opt(&key) { - // Determine the color and index of the new `DepNode`. - let (color, dep_node_index) = if let Some(current_fingerprint) = current_fingerprint - { - if current_fingerprint == data.previous.fingerprint_by_index(prev_index) { - if print_status { - eprintln!("[task::green] {:?}", key); - } - - // This is a light green node: it existed in the previous compilation, - // its query was re-executed, and it has the same result as before. - let dep_node_index = - data.current.intern_light_green_node(&data.previous, prev_index, edges); - - (DepNodeColor::Green(dep_node_index), dep_node_index) - } else { - if print_status { - eprintln!("[task::red] {:?}", key); - } - - // This is a red node: it existed in the previous compilation, its query - // was re-executed, but it has a different result from before. - let dep_node_index = data.current.intern_red_node( - &data.previous, - prev_index, - edges, - current_fingerprint, - ); - - (DepNodeColor::Red, dep_node_index) - } - } else { - if print_status { - eprintln!("[task::unknown] {:?}", key); - } - - // This is a red node, effectively: it existed in the previous compilation - // session, its query was re-executed, but it doesn't compute a result hash - // (i.e. it represents a `no_hash` query), so we have no way of determining - // whether or not the result was the same as before. - let dep_node_index = data.current.intern_red_node( - &data.previous, - prev_index, - edges, - Fingerprint::ZERO, - ); - - (DepNodeColor::Red, dep_node_index) - }; + let (dep_node_index, prev_and_color) = data.current.intern_node( + dcx.profiler(), + &data.previous, + key, + edges, + current_fingerprint, + print_status, + ); + if let Some((prev_index, color)) = prev_and_color { debug_assert!( data.colors.get(prev_index).is_none(), "DepGraph::with_task() - Duplicate DepNodeColor \ @@ -341,20 +259,7 @@ impl DepGraph { ); data.colors.insert(prev_index, color); - dep_node_index - } else { - if print_status { - eprintln!("[task::new] {:?}", key); - } - - // This is a new node: it didn't exist in the previous compilation session. - data.current.intern_new_node( - &data.previous, - key, - edges, - current_fingerprint.unwrap_or(Fingerprint::ZERO), - ) - }; + } (result, dep_node_index) } else { @@ -368,7 +273,12 @@ impl DepGraph { /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. - pub fn with_anon_task(&self, dep_kind: K, op: OP) -> (R, DepNodeIndex) + pub fn with_anon_task, OP, R>( + &self, + cx: Ctxt, + dep_kind: K, + op: OP, + ) -> (R, DepNodeIndex) where OP: FnOnce() -> R, { @@ -396,7 +306,7 @@ impl DepGraph { }; let dep_node_index = data.current.intern_new_node( - &data.previous, + cx.profiler(), target_dep_node, task_deps.reads, Fingerprint::ZERO, @@ -451,7 +361,7 @@ impl DepGraph { { if let Some(target) = task_deps.node { if let Some(ref forbidden_edge) = data.current.forbidden_edge { - let src = self.dep_node_of(dep_node_index); + let src = forbidden_edge.index_to_node.lock()[&dep_node_index]; if forbidden_edge.test(&src, &target) { panic!("forbidden edge {:?} -> {:?} created", src, target) } @@ -488,38 +398,6 @@ impl DepGraph { self.data.is_some() && self.dep_node_index_of_opt(dep_node).is_some() } - #[inline] - pub fn dep_node_of(&self, dep_node_index: DepNodeIndex) -> DepNode { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - let data = data.current.data.lock(); - - match data.hybrid_indices[dep_node_index].into() { - HybridIndex::New(new_index) => data.new.nodes[new_index], - HybridIndex::Red(red_index) => previous.index_to_node(data.red.node_indices[red_index]), - HybridIndex::LightGreen(light_green_index) => { - previous.index_to_node(data.light_green.node_indices[light_green_index]) - } - HybridIndex::DarkGreen(prev_index) => previous.index_to_node(prev_index), - } - } - - #[inline] - pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - let data = data.current.data.lock(); - - match data.hybrid_indices[dep_node_index].into() { - HybridIndex::New(new_index) => data.new.fingerprints[new_index], - HybridIndex::Red(red_index) => data.red.fingerprints[red_index], - HybridIndex::LightGreen(light_green_index) => { - previous.fingerprint_by_index(data.light_green.node_indices[light_green_index]) - } - HybridIndex::DarkGreen(prev_index) => previous.fingerprint_by_index(prev_index), - } - } - pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { self.data.as_ref().unwrap().previous.fingerprint_of(dep_node) } @@ -554,29 +432,13 @@ impl DepGraph { self.data.as_ref()?.dep_node_debug.borrow().get(&dep_node).cloned() } - fn edge_count(&self, node_data: &LockGuard<'_, DepNodeData>) -> usize { - let data = self.data.as_ref().unwrap(); - let previous = &data.previous; - - let mut edge_count = node_data.unshared_edges.len(); - - for &hybrid_index in node_data.hybrid_indices.iter() { - if let HybridIndex::DarkGreen(prev_index) = hybrid_index.into() { - edge_count += previous.edge_targets_from(prev_index).len() - } - } - - edge_count - } - - pub fn node_color(&self, dep_node: &DepNode) -> Option { + fn node_color(&self, dep_node: &DepNode) -> Option { if let Some(ref data) = self.data { if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) { return data.colors.get(prev_index); } else { - // This is a node that did not exist in the previous compilation - // session, so we consider it to be red. - return Some(DepNodeColor::Red); + // This is a node that did not exist in the previous compilation session. + return None; } } @@ -775,11 +637,13 @@ impl DepGraph { // There may be multiple threads trying to mark the same dep node green concurrently - let dep_node_index = { - // We allocating an entry for the node in the current dependency graph and - // adding all the appropriate edges imported from the previous graph - data.current.intern_dark_green_node(&data.previous, prev_dep_node_index) - }; + // We allocating an entry for the node in the current dependency graph and + // adding all the appropriate edges imported from the previous graph + let dep_node_index = data.current.promote_node_and_deps_to_current( + tcx.dep_context().profiler(), + &data.previous, + prev_dep_node_index, + ); // ... emitting any stored diagnostic ... @@ -862,6 +726,12 @@ impl DepGraph { } } + // Returns true if the given node has been marked as red during the + // current compilation session. Used in various assertions + pub fn is_red(&self, dep_node: &DepNode) -> bool { + self.node_color(dep_node) == Some(DepNodeColor::Red) + } + // Returns true if the given node has been marked as green during the // current compilation session. Used in various assertions pub fn is_green(&self, dep_node: &DepNode) -> bool { @@ -911,106 +781,20 @@ impl DepGraph { } pub fn print_incremental_info(&self) { - #[derive(Clone)] - struct Stat { - kind: Kind, - node_counter: u64, - edge_counter: u64, + if let Some(data) = &self.data { + data.current.encoder.borrow().print_incremental_info( + data.current.total_read_count.load(Relaxed), + data.current.total_duplicate_read_count.load(Relaxed), + ) } + } - let data = self.data.as_ref().unwrap(); - let prev = &data.previous; - let current = &data.current; - let data = current.data.lock(); - - let mut stats: FxHashMap<_, Stat> = FxHashMap::with_hasher(Default::default()); - - for &hybrid_index in data.hybrid_indices.iter() { - let (kind, edge_count) = match hybrid_index.into() { - HybridIndex::New(new_index) => { - let kind = data.new.nodes[new_index].kind; - let edge_range = &data.new.edges[new_index]; - (kind, edge_range.end.as_usize() - edge_range.start.as_usize()) - } - HybridIndex::Red(red_index) => { - let kind = prev.index_to_node(data.red.node_indices[red_index]).kind; - let edge_range = &data.red.edges[red_index]; - (kind, edge_range.end.as_usize() - edge_range.start.as_usize()) - } - HybridIndex::LightGreen(lg_index) => { - let kind = prev.index_to_node(data.light_green.node_indices[lg_index]).kind; - let edge_range = &data.light_green.edges[lg_index]; - (kind, edge_range.end.as_usize() - edge_range.start.as_usize()) - } - HybridIndex::DarkGreen(prev_index) => { - let kind = prev.index_to_node(prev_index).kind; - let edge_count = prev.edge_targets_from(prev_index).len(); - (kind, edge_count) - } - }; - - let stat = stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 }); - stat.node_counter += 1; - stat.edge_counter += edge_count as u64; - } - - let total_node_count = data.hybrid_indices.len(); - let total_edge_count = self.edge_count(&data); - - // Drop the lock guard. - std::mem::drop(data); - - let mut stats: Vec<_> = stats.values().cloned().collect(); - stats.sort_by_key(|s| -(s.node_counter as i64)); - - const SEPARATOR: &str = "[incremental] --------------------------------\ - ----------------------------------------------\ - ------------"; - - eprintln!("[incremental]"); - eprintln!("[incremental] DepGraph Statistics"); - eprintln!("{}", SEPARATOR); - eprintln!("[incremental]"); - eprintln!("[incremental] Total Node Count: {}", total_node_count); - eprintln!("[incremental] Total Edge Count: {}", total_edge_count); - - if cfg!(debug_assertions) { - let total_edge_reads = current.total_read_count.load(Relaxed); - let total_duplicate_edge_reads = current.total_duplicate_read_count.load(Relaxed); - - eprintln!("[incremental] Total Edge Reads: {}", total_edge_reads); - eprintln!("[incremental] Total Duplicate Edge Reads: {}", total_duplicate_edge_reads); - } - - eprintln!("[incremental]"); - - eprintln!( - "[incremental] {:<36}| {:<17}| {:<12}| {:<17}|", - "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count" - ); - - eprintln!( - "[incremental] -------------------------------------\ - |------------------\ - |-------------\ - |------------------|" - ); - - for stat in stats { - let node_kind_ratio = (100.0 * (stat.node_counter as f64)) / (total_node_count as f64); - let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64); - - eprintln!( - "[incremental] {:<36}|{:>16.1}% |{:>12} |{:>17.1} |", - format!("{:?}", stat.kind), - node_kind_ratio, - stat.node_counter, - node_kind_avg_edges, - ); + pub fn encode(&self, profiler: &SelfProfilerRef) -> FileEncodeResult { + if let Some(data) = &self.data { + data.current.encoder.steal().finish(profiler) + } else { + Ok(()) } - - eprintln!("{}", SEPARATOR); - eprintln!("[incremental]"); } fn next_virtual_depnode_index(&self) -> DepNodeIndex { @@ -1019,142 +803,6 @@ impl DepGraph { } } -impl> Encodable for DepGraph { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - // We used to serialize the dep graph by creating and serializing a `SerializedDepGraph` - // using data copied from the `DepGraph`. But copying created a large memory spike, so we - // now serialize directly from the `DepGraph` as if it's a `SerializedDepGraph`. Because we - // deserialize that data into a `SerializedDepGraph` in the next compilation session, we - // need `DepGraph`'s `Encodable` and `SerializedDepGraph`'s `Decodable` implementations to - // be in sync. If you update this encoding, be sure to update the decoding, and vice-versa. - - let data = self.data.as_ref().unwrap(); - let prev = &data.previous; - - // Note locking order: `prev_index_to_index`, then `data`. - let prev_index_to_index = data.current.prev_index_to_index.lock(); - let data = data.current.data.lock(); - let new = &data.new; - let red = &data.red; - let lg = &data.light_green; - - let node_count = data.hybrid_indices.len(); - let edge_count = self.edge_count(&data); - - // `rustc_middle::ty::query::OnDiskCache` expects nodes to be encoded in `DepNodeIndex` - // order. The edges in `edge_list_data` don't need to be in a particular order, as long as - // each node references its edges as a contiguous range within it. Therefore, we can encode - // `edge_list_data` directly from `unshared_edges`. It meets the above requirements, as - // each non-dark-green node already knows the range of edges to reference within it, which - // they'll encode in `edge_list_indices`. Dark green nodes, however, don't have their edges - // in `unshared_edges`, so need to add them to `edge_list_data`. - - use HybridIndex::*; - - // Encoded values (nodes, etc.) are explicitly typed below to avoid inadvertently - // serializing data in the wrong format (i.e. one incompatible with `SerializedDepGraph`). - e.emit_struct("SerializedDepGraph", 4, |e| { - e.emit_struct_field("nodes", 0, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of `DepNode`s. - e.emit_seq(node_count, |e| { - for (seq_index, &hybrid_index) in data.hybrid_indices.iter().enumerate() { - let node: DepNode = match hybrid_index.into() { - New(i) => new.nodes[i], - Red(i) => prev.index_to_node(red.node_indices[i]), - LightGreen(i) => prev.index_to_node(lg.node_indices[i]), - DarkGreen(prev_index) => prev.index_to_node(prev_index), - }; - - e.emit_seq_elt(seq_index, |e| node.encode(e))?; - } - - Ok(()) - }) - })?; - - e.emit_struct_field("fingerprints", 1, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of `Fingerprints`s. - e.emit_seq(node_count, |e| { - for (seq_index, &hybrid_index) in data.hybrid_indices.iter().enumerate() { - let fingerprint: Fingerprint = match hybrid_index.into() { - New(i) => new.fingerprints[i], - Red(i) => red.fingerprints[i], - LightGreen(i) => prev.fingerprint_by_index(lg.node_indices[i]), - DarkGreen(prev_index) => prev.fingerprint_by_index(prev_index), - }; - - e.emit_seq_elt(seq_index, |e| fingerprint.encode(e))?; - } - - Ok(()) - }) - })?; - - e.emit_struct_field("edge_list_indices", 2, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of `(u32, u32)`s. - e.emit_seq(node_count, |e| { - // Dark green node edges start after the unshared (all other nodes') edges. - let mut dark_green_edge_index = data.unshared_edges.len(); - - for (seq_index, &hybrid_index) in data.hybrid_indices.iter().enumerate() { - let edge_indices: (u32, u32) = match hybrid_index.into() { - New(i) => (new.edges[i].start.as_u32(), new.edges[i].end.as_u32()), - Red(i) => (red.edges[i].start.as_u32(), red.edges[i].end.as_u32()), - LightGreen(i) => (lg.edges[i].start.as_u32(), lg.edges[i].end.as_u32()), - DarkGreen(prev_index) => { - let edge_count = prev.edge_targets_from(prev_index).len(); - let start = dark_green_edge_index as u32; - dark_green_edge_index += edge_count; - let end = dark_green_edge_index as u32; - (start, end) - } - }; - - e.emit_seq_elt(seq_index, |e| edge_indices.encode(e))?; - } - - assert_eq!(dark_green_edge_index, edge_count); - - Ok(()) - }) - })?; - - e.emit_struct_field("edge_list_data", 3, |e| { - // `SerializedDepGraph` expects this to be encoded as a sequence of - // `SerializedDepNodeIndex`. - e.emit_seq(edge_count, |e| { - for (seq_index, &edge) in data.unshared_edges.iter().enumerate() { - let serialized_edge = SerializedDepNodeIndex::new(edge.index()); - e.emit_seq_elt(seq_index, |e| serialized_edge.encode(e))?; - } - - let mut seq_index = data.unshared_edges.len(); - - for &hybrid_index in data.hybrid_indices.iter() { - if let DarkGreen(prev_index) = hybrid_index.into() { - for &edge in prev.edge_targets_from(prev_index) { - // Dark green node edges are stored in the previous graph - // and must be converted to edges in the current graph, - // and then serialized as `SerializedDepNodeIndex`. - let serialized_edge = SerializedDepNodeIndex::new( - prev_index_to_index[edge].as_ref().unwrap().index(), - ); - - e.emit_seq_elt(seq_index, |e| serialized_edge.encode(e))?; - seq_index += 1; - } - } - } - - assert_eq!(seq_index, edge_count); - - Ok(()) - }) - }) - }) - } -} - /// A "work product" is an intermediate result that we save into the /// incremental directory for later re-use. The primary example are /// the object files that we save for each partition at code @@ -1193,216 +841,20 @@ pub struct WorkProduct { pub saved_file: Option, } -// The maximum value of the follow index types leaves the upper two bits unused -// so that we can store multiple index types in `CompressedHybridIndex`, and use -// those bits to encode which index type it contains. - -// Index type for `NewDepNodeData`. -rustc_index::newtype_index! { - struct NewDepNodeIndex { - MAX = 0x7FFF_FFFF - } -} - -// Index type for `RedDepNodeData`. -rustc_index::newtype_index! { - struct RedDepNodeIndex { - MAX = 0x7FFF_FFFF - } -} - -// Index type for `LightGreenDepNodeData`. -rustc_index::newtype_index! { - struct LightGreenDepNodeIndex { - MAX = 0x7FFF_FFFF - } -} - -/// Compressed representation of `HybridIndex` enum. Bits unused by the -/// contained index types are used to encode which index type it contains. -#[derive(Copy, Clone)] -struct CompressedHybridIndex(u32); - -impl CompressedHybridIndex { - const NEW_TAG: u32 = 0b0000_0000_0000_0000_0000_0000_0000_0000; - const RED_TAG: u32 = 0b0100_0000_0000_0000_0000_0000_0000_0000; - const LIGHT_GREEN_TAG: u32 = 0b1000_0000_0000_0000_0000_0000_0000_0000; - const DARK_GREEN_TAG: u32 = 0b1100_0000_0000_0000_0000_0000_0000_0000; - - const TAG_MASK: u32 = 0b1100_0000_0000_0000_0000_0000_0000_0000; - const INDEX_MASK: u32 = !Self::TAG_MASK; -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: NewDepNodeIndex) -> Self { - CompressedHybridIndex(Self::NEW_TAG | index.as_u32()) - } -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: RedDepNodeIndex) -> Self { - CompressedHybridIndex(Self::RED_TAG | index.as_u32()) - } -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: LightGreenDepNodeIndex) -> Self { - CompressedHybridIndex(Self::LIGHT_GREEN_TAG | index.as_u32()) - } -} - -impl From for CompressedHybridIndex { - #[inline] - fn from(index: SerializedDepNodeIndex) -> Self { - CompressedHybridIndex(Self::DARK_GREEN_TAG | index.as_u32()) - } -} - -/// Contains an index into one of several node data collections. Elsewhere, we -/// store `CompressedHyridIndex` instead of this to save space, but convert to -/// this type during processing to take advantage of the enum match ergonomics. -enum HybridIndex { - New(NewDepNodeIndex), - Red(RedDepNodeIndex), - LightGreen(LightGreenDepNodeIndex), - DarkGreen(SerializedDepNodeIndex), -} - -impl From for HybridIndex { - #[inline] - fn from(hybrid_index: CompressedHybridIndex) -> Self { - let index = hybrid_index.0 & CompressedHybridIndex::INDEX_MASK; - - match hybrid_index.0 & CompressedHybridIndex::TAG_MASK { - CompressedHybridIndex::NEW_TAG => HybridIndex::New(NewDepNodeIndex::from_u32(index)), - CompressedHybridIndex::RED_TAG => HybridIndex::Red(RedDepNodeIndex::from_u32(index)), - CompressedHybridIndex::LIGHT_GREEN_TAG => { - HybridIndex::LightGreen(LightGreenDepNodeIndex::from_u32(index)) - } - CompressedHybridIndex::DARK_GREEN_TAG => { - HybridIndex::DarkGreen(SerializedDepNodeIndex::from_u32(index)) - } - _ => unreachable!(), - } - } -} - // Index type for `DepNodeData`'s edges. rustc_index::newtype_index! { struct EdgeIndex { .. } } -/// Data for nodes in the current graph, divided into different collections -/// based on their presence in the previous graph, and if present, their color. -/// We divide nodes this way because different types of nodes are able to share -/// more or less data with the previous graph. -/// -/// To enable more sharing, we distinguish between two kinds of green nodes. -/// Light green nodes are nodes in the previous graph that have been marked -/// green because we re-executed their queries and the results were the same as -/// in the previous session. Dark green nodes are nodes in the previous graph -/// that have been marked green because we were able to mark all of their -/// dependencies green. -/// -/// Both light and dark green nodes can share the dep node and fingerprint with -/// the previous graph, but for light green nodes, we can't be sure that the -/// edges may be shared without comparing them against the previous edges, so we -/// store them directly (an approach in which we compare edges with the previous -/// edges to see if they can be shared was evaluated, but was not found to be -/// very profitable). -/// -/// For dark green nodes, we can share everything with the previous graph, which -/// is why the `HybridIndex::DarkGreen` enum variant contains the index of the -/// node in the previous graph, and why we don't have a separate collection for -/// dark green node data--the collection is the `PreviousDepGraph` itself. -/// -/// (Note that for dark green nodes, the edges in the previous graph -/// (`SerializedDepNodeIndex`s) must be converted to edges in the current graph -/// (`DepNodeIndex`s). `CurrentDepGraph` contains `prev_index_to_index`, which -/// can perform this conversion. It should always be possible, as by definition, -/// a dark green node is one whose dependencies from the previous session have -/// all been marked green--which means `prev_index_to_index` contains them.) -/// -/// Node data is stored in parallel vectors to eliminate the padding between -/// elements that would be needed to satisfy alignment requirements of the -/// structure that would contain all of a node's data. We could group tightly -/// packing subsets of node data together and use fewer vectors, but for -/// consistency's sake, we use separate vectors for each piece of data. -struct DepNodeData { - /// Data for nodes not in previous graph. - new: NewDepNodeData, - - /// Data for nodes in previous graph that have been marked red. - red: RedDepNodeData, - - /// Data for nodes in previous graph that have been marked light green. - light_green: LightGreenDepNodeData, - - // Edges for all nodes other than dark-green ones. Edges for each node - // occupy a contiguous region of this collection, which a node can reference - // using two indices. Storing edges this way rather than using an `EdgesVec` - // for each node reduces memory consumption by a not insignificant amount - // when compiling large crates. The downside is that we have to copy into - // this collection the edges from the `EdgesVec`s that are built up during - // query execution. But this is mostly balanced out by the more efficient - // implementation of `DepGraph::serialize` enabled by this representation. - unshared_edges: IndexVec, - - /// Mapping from `DepNodeIndex` to an index into a collection above. - /// Indicates which of the above collections contains a node's data. - /// - /// This collection is wasteful in time and space during incr-full builds, - /// because for those, all nodes are new. However, the waste is relatively - /// small, and the maintenance cost of avoiding using this for incr-full - /// builds is somewhat high and prone to bugginess. It does not seem worth - /// it at the time of this writing, but we may want to revisit the idea. - hybrid_indices: IndexVec, -} - -/// Data for nodes not in previous graph. Since we cannot share any data with -/// the previous graph, so we must store all of such a node's data here. -struct NewDepNodeData { - nodes: IndexVec>, - edges: IndexVec>, - fingerprints: IndexVec, -} - -/// Data for nodes in previous graph that have been marked red. We can share the -/// dep node with the previous graph, but the edges may be different, and the -/// fingerprint is known to be different, so we store the latter two directly. -struct RedDepNodeData { - node_indices: IndexVec, - edges: IndexVec>, - fingerprints: IndexVec, -} - -/// Data for nodes in previous graph that have been marked green because we -/// re-executed their queries and the results were the same as in the previous -/// session. We can share the dep node and the fingerprint with the previous -/// graph, but the edges may be different, so we store them directly. -struct LightGreenDepNodeData { - node_indices: IndexVec, - edges: IndexVec>, -} - /// `CurrentDepGraph` stores the dependency graph for the current session. It /// will be populated as we run queries or tasks. We never remove nodes from the /// graph: they are only added. /// -/// The nodes in it are identified by a `DepNodeIndex`. Internally, this maps to -/// a `HybridIndex`, which identifies which collection in the `data` field -/// contains a node's data. Which collection is used for a node depends on -/// whether the node was present in the `PreviousDepGraph`, and if so, the color -/// of the node. Each type of node can share more or less data with the previous -/// graph. When possible, we can store just the index of the node in the -/// previous graph, rather than duplicating its data in our own collections. -/// This is important, because these graph structures are some of the largest in -/// the compiler. +/// The nodes in it are identified by a `DepNodeIndex`. We avoid keeping the nodes +/// in memory. This is important, because these graph structures are some of the +/// largest in the compiler. /// -/// For the same reason, we also avoid storing `DepNode`s more than once as map +/// For this reason, we avoid storing `DepNode`s more than once as map /// keys. The `new_node_to_index` map only contains nodes not in the previous /// graph, and we map nodes in the previous graph to indices via a two-step /// mapping. `PreviousDepGraph` maps from `DepNode` to `SerializedDepNodeIndex`, @@ -1417,15 +869,15 @@ struct LightGreenDepNodeData { /// `new_node_to_index` and `data`, or `prev_index_to_index` and `data`. When /// manipulating both, we acquire `new_node_to_index` or `prev_index_to_index` /// first, and `data` second. -pub(super) struct CurrentDepGraph { - data: Lock>, +pub(super) struct CurrentDepGraph { + encoder: Steal>, new_node_to_index: Sharded, DepNodeIndex>>, prev_index_to_index: Lock>>, /// Used to trap when a specific edge is added to the graph. /// This is used for debug purposes and is only active with `debug_assertions`. - #[allow(dead_code)] - forbidden_edge: Option, + #[cfg(debug_assertions)] + forbidden_edge: Option>, /// Anonymous `DepNode`s are nodes whose IDs we compute from the list of /// their edges. This has the beneficial side-effect that multiple anonymous @@ -1447,7 +899,12 @@ pub(super) struct CurrentDepGraph { } impl CurrentDepGraph { - fn new(prev_graph_node_count: usize) -> CurrentDepGraph { + fn new( + prev_graph_node_count: usize, + encoder: FileEncoder, + record_graph: bool, + record_stats: bool, + ) -> CurrentDepGraph { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); @@ -1455,70 +912,29 @@ impl CurrentDepGraph { let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); - let forbidden_edge = if cfg!(debug_assertions) { - match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { - Ok(s) => match EdgeFilter::new(&s) { - Ok(f) => Some(f), - Err(err) => panic!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), - }, - Err(_) => None, - } - } else { - None + #[cfg(debug_assertions)] + let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { + Ok(s) => match EdgeFilter::new(&s) { + Ok(f) => Some(f), + Err(err) => panic!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), + }, + Err(_) => None, }; - // Pre-allocate the dep node structures. We over-allocate a little so - // that we hopefully don't have to re-allocate during this compilation - // session. The over-allocation for new nodes is 2% plus a small - // constant to account for the fact that in very small crates 2% might - // not be enough. The allocation for red and green node data doesn't - // include a constant, as we don't want to allocate anything for these - // structures during full incremental builds, where they aren't used. - // - // These estimates are based on the distribution of node and edge counts - // seen in rustc-perf benchmarks, adjusted somewhat to account for the - // fact that these benchmarks aren't perfectly representative. - // - // FIXME Use a collection type that doesn't copy node and edge data and - // grow multiplicatively on reallocation. Without such a collection or - // solution having the same effect, there is a performance hazard here - // in both time and space, as growing these collections means copying a - // large amount of data and doubling already large buffer capacities. A - // solution for this will also mean that it's less important to get - // these estimates right. - let new_node_count_estimate = (prev_graph_node_count * 2) / 100 + 200; - let red_node_count_estimate = (prev_graph_node_count * 3) / 100; - let light_green_node_count_estimate = (prev_graph_node_count * 25) / 100; - let total_node_count_estimate = prev_graph_node_count + new_node_count_estimate; - - let average_edges_per_node_estimate = 6; - let unshared_edge_count_estimate = average_edges_per_node_estimate - * (new_node_count_estimate + red_node_count_estimate + light_green_node_count_estimate); - // We store a large collection of these in `prev_index_to_index` during // non-full incremental builds, and want to ensure that the element size // doesn't inadvertently increase. static_assert_size!(Option, 4); + let new_node_count_estimate = 102 * prev_graph_node_count / 100 + 200; + CurrentDepGraph { - data: Lock::new(DepNodeData { - new: NewDepNodeData { - nodes: IndexVec::with_capacity(new_node_count_estimate), - edges: IndexVec::with_capacity(new_node_count_estimate), - fingerprints: IndexVec::with_capacity(new_node_count_estimate), - }, - red: RedDepNodeData { - node_indices: IndexVec::with_capacity(red_node_count_estimate), - edges: IndexVec::with_capacity(red_node_count_estimate), - fingerprints: IndexVec::with_capacity(red_node_count_estimate), - }, - light_green: LightGreenDepNodeData { - node_indices: IndexVec::with_capacity(light_green_node_count_estimate), - edges: IndexVec::with_capacity(light_green_node_count_estimate), - }, - unshared_edges: IndexVec::with_capacity(unshared_edge_count_estimate), - hybrid_indices: IndexVec::with_capacity(total_node_count_estimate), - }), + encoder: Steal::new(GraphEncoder::new( + encoder, + prev_graph_node_count, + record_graph, + record_stats, + )), new_node_to_index: Sharded::new(|| { FxHashMap::with_capacity_and_hasher( new_node_count_estimate / sharded::SHARDS, @@ -1527,89 +943,143 @@ impl CurrentDepGraph { }), prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)), anon_id_seed: stable_hasher.finish(), + #[cfg(debug_assertions)] forbidden_edge, total_read_count: AtomicU64::new(0), total_duplicate_read_count: AtomicU64::new(0), } } + #[cfg(debug_assertions)] + fn record_edge(&self, dep_node_index: DepNodeIndex, key: DepNode) { + if let Some(forbidden_edge) = &self.forbidden_edge { + forbidden_edge.index_to_node.lock().insert(dep_node_index, key); + } + } + + /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it. + /// Assumes that this is a node that has no equivalent in the previous dep-graph. fn intern_new_node( &self, - prev_graph: &PreviousDepGraph, - dep_node: DepNode, + profiler: &SelfProfilerRef, + key: DepNode, edges: EdgesVec, - fingerprint: Fingerprint, + current_fingerprint: Fingerprint, ) -> DepNodeIndex { - debug_assert!( - prev_graph.node_to_index_opt(&dep_node).is_none(), - "node in previous graph should be interned using one \ - of `intern_red_node`, `intern_light_green_node`, etc." - ); - - match self.new_node_to_index.get_shard_by_value(&dep_node).lock().entry(dep_node) { + match self.new_node_to_index.get_shard_by_value(&key).lock().entry(key) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { - let data = &mut *self.data.lock(); - let new_index = data.new.nodes.push(dep_node); - add_edges(&mut data.unshared_edges, &mut data.new.edges, edges); - data.new.fingerprints.push(fingerprint); - let dep_node_index = data.hybrid_indices.push(new_index.into()); + let dep_node_index = + self.encoder.borrow().send(profiler, key, current_fingerprint, edges); entry.insert(dep_node_index); + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); dep_node_index } } } - fn intern_red_node( + fn intern_node( &self, + profiler: &SelfProfilerRef, prev_graph: &PreviousDepGraph, - prev_index: SerializedDepNodeIndex, + key: DepNode, edges: EdgesVec, - fingerprint: Fingerprint, - ) -> DepNodeIndex { - self.debug_assert_not_in_new_nodes(prev_graph, prev_index); + fingerprint: Option, + print_status: bool, + ) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>) { + let print_status = cfg!(debug_assertions) && print_status; + + if let Some(prev_index) = prev_graph.node_to_index_opt(&key) { + // Determine the color and index of the new `DepNode`. + if let Some(fingerprint) = fingerprint { + if fingerprint == prev_graph.fingerprint_by_index(prev_index) { + if print_status { + eprintln!("[task::green] {:?}", key); + } - let mut prev_index_to_index = self.prev_index_to_index.lock(); + // This is a green node: it existed in the previous compilation, + // its query was re-executed, and it has the same result as before. + let mut prev_index_to_index = self.prev_index_to_index.lock(); + + let dep_node_index = match prev_index_to_index[prev_index] { + Some(dep_node_index) => dep_node_index, + None => { + let dep_node_index = + self.encoder.borrow().send(profiler, key, fingerprint, edges); + prev_index_to_index[prev_index] = Some(dep_node_index); + dep_node_index + } + }; - match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let data = &mut *self.data.lock(); - let red_index = data.red.node_indices.push(prev_index); - add_edges(&mut data.unshared_edges, &mut data.red.edges, edges); - data.red.fingerprints.push(fingerprint); - let dep_node_index = data.hybrid_indices.push(red_index.into()); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index - } - } - } + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); + (dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index)))) + } else { + if print_status { + eprintln!("[task::red] {:?}", key); + } - fn intern_light_green_node( - &self, - prev_graph: &PreviousDepGraph, - prev_index: SerializedDepNodeIndex, - edges: EdgesVec, - ) -> DepNodeIndex { - self.debug_assert_not_in_new_nodes(prev_graph, prev_index); + // This is a red node: it existed in the previous compilation, its query + // was re-executed, but it has a different result from before. + let mut prev_index_to_index = self.prev_index_to_index.lock(); + + let dep_node_index = match prev_index_to_index[prev_index] { + Some(dep_node_index) => dep_node_index, + None => { + let dep_node_index = + self.encoder.borrow().send(profiler, key, fingerprint, edges); + prev_index_to_index[prev_index] = Some(dep_node_index); + dep_node_index + } + }; - let mut prev_index_to_index = self.prev_index_to_index.lock(); + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); + (dep_node_index, Some((prev_index, DepNodeColor::Red))) + } + } else { + if print_status { + eprintln!("[task::unknown] {:?}", key); + } - match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let data = &mut *self.data.lock(); - let light_green_index = data.light_green.node_indices.push(prev_index); - add_edges(&mut data.unshared_edges, &mut data.light_green.edges, edges); - let dep_node_index = data.hybrid_indices.push(light_green_index.into()); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index + // This is a red node, effectively: it existed in the previous compilation + // session, its query was re-executed, but it doesn't compute a result hash + // (i.e. it represents a `no_hash` query), so we have no way of determining + // whether or not the result was the same as before. + let mut prev_index_to_index = self.prev_index_to_index.lock(); + + let dep_node_index = match prev_index_to_index[prev_index] { + Some(dep_node_index) => dep_node_index, + None => { + let dep_node_index = + self.encoder.borrow().send(profiler, key, Fingerprint::ZERO, edges); + prev_index_to_index[prev_index] = Some(dep_node_index); + dep_node_index + } + }; + + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); + (dep_node_index, Some((prev_index, DepNodeColor::Red))) + } + } else { + if print_status { + eprintln!("[task::new] {:?}", key); } + + let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO); + + // This is a new node: it didn't exist in the previous compilation session. + let dep_node_index = self.intern_new_node(profiler, key, edges, fingerprint); + + (dep_node_index, None) } } - fn intern_dark_green_node( + fn promote_node_and_deps_to_current( &self, + profiler: &SelfProfilerRef, prev_graph: &PreviousDepGraph, prev_index: SerializedDepNodeIndex, ) -> DepNodeIndex { @@ -1620,9 +1090,20 @@ impl CurrentDepGraph { match prev_index_to_index[prev_index] { Some(dep_node_index) => dep_node_index, None => { - let mut data = self.data.lock(); - let dep_node_index = data.hybrid_indices.push(prev_index.into()); + let key = prev_graph.index_to_node(prev_index); + let dep_node_index = self.encoder.borrow().send( + profiler, + key, + prev_graph.fingerprint_by_index(prev_index), + prev_graph + .edge_targets_from(prev_index) + .iter() + .map(|i| prev_index_to_index[*i].unwrap()) + .collect(), + ); prev_index_to_index[prev_index] = Some(dep_node_index); + #[cfg(debug_assertions)] + self.record_edge(dep_node_index, key); dep_node_index } } @@ -1642,18 +1123,6 @@ impl CurrentDepGraph { } } -#[inline] -fn add_edges( - edges: &mut IndexVec, - edge_indices: &mut IndexVec>, - new_edges: EdgesVec, -) { - let start = edges.next_index(); - edges.extend(new_edges); - let end = edges.next_index(); - edge_indices.push(start..end); -} - /// The capacity of the `reads` field `SmallVec` const TASK_DEPS_READS_CAP: usize = 8; type EdgesVec = SmallVec<[DepNodeIndex; TASK_DEPS_READS_CAP]>; diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index e8fb71be3e..1b6ecf3e63 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -13,6 +13,7 @@ pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; +use rustc_serialize::{opaque::FileEncoder, Encodable}; use rustc_session::Session; use std::fmt; @@ -59,7 +60,7 @@ impl HasDepContext for T { } /// Describe the different families of dependency nodes. -pub trait DepKind: Copy + fmt::Debug + Eq + Hash { +pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { const NULL: Self; /// Return whether this kind always require evaluation. diff --git a/compiler/rustc_query_system/src/dep_graph/prev.rs b/compiler/rustc_query_system/src/dep_graph/prev.rs index c3d0f79525..6303bbf53b 100644 --- a/compiler/rustc_query_system/src/dep_graph/prev.rs +++ b/compiler/rustc_query_system/src/dep_graph/prev.rs @@ -35,11 +35,6 @@ impl PreviousDepGraph { self.data.nodes[dep_node_index] } - #[inline] - pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex { - self.index[dep_node] - } - #[inline] pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option { self.index.get(dep_node).cloned() diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_query_system/src/dep_graph/query.rs index cc25d08cb5..27b3b5e136 100644 --- a/compiler/rustc_query_system/src/dep_graph/query.rs +++ b/compiler/rustc_query_system/src/dep_graph/query.rs @@ -1,38 +1,43 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::implementation::{Direction, Graph, NodeIndex, INCOMING}; +use rustc_index::vec::IndexVec; -use super::{DepKind, DepNode}; +use super::{DepKind, DepNode, DepNodeIndex}; pub struct DepGraphQuery { pub graph: Graph, ()>, pub indices: FxHashMap, NodeIndex>, + pub dep_index_to_index: IndexVec>, } impl DepGraphQuery { - pub fn new( - nodes: &[DepNode], - edge_list_indices: &[(usize, usize)], - edge_list_data: &[usize], - ) -> DepGraphQuery { - let mut graph = Graph::with_capacity(nodes.len(), edge_list_data.len()); - let mut indices = FxHashMap::default(); - for node in nodes { - indices.insert(*node, graph.add_node(*node)); - } + pub fn new(prev_node_count: usize) -> DepGraphQuery { + let node_count = prev_node_count + prev_node_count / 4; + let edge_count = 6 * node_count; - for (source, &(start, end)) in edge_list_indices.iter().enumerate() { - for &target in &edge_list_data[start..end] { - let source = indices[&nodes[source]]; - let target = indices[&nodes[target]]; - graph.add_edge(source, target, ()); - } - } + let graph = Graph::with_capacity(node_count, edge_count); + let indices = FxHashMap::default(); + let dep_index_to_index = IndexVec::new(); - DepGraphQuery { graph, indices } + DepGraphQuery { graph, indices, dep_index_to_index } } - pub fn contains_node(&self, node: &DepNode) -> bool { - self.indices.contains_key(&node) + pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) { + let source = self.graph.add_node(node); + if index.index() >= self.dep_index_to_index.len() { + self.dep_index_to_index.resize(index.index() + 1, None); + } + self.dep_index_to_index[index] = Some(source); + self.indices.insert(node, source); + + for &target in edges.iter() { + let target = self.dep_index_to_index[target]; + // We may miss the edges that are pushed while the `DepGraphQuery` is being accessed. + // Skip them to issues. + if let Some(target) = target { + self.graph.add_edge(source, target, ()); + } + } } pub fn nodes(&self) -> Vec<&DepNode> { diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 9bb922b0a9..6f3d1fb719 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -1,9 +1,28 @@ //! The data that we will serialize and deserialize. +//! +//! The dep-graph is serialized as a sequence of NodeInfo, with the dependencies +//! specified inline. The total number of nodes and edges are stored as the last +//! 16 bytes of the file, so we can find them easily at decoding time. +//! +//! The serialisation is performed on-demand when each node is emitted. Using this +//! scheme, we do not need to keep the current graph in memory. +//! +//! The deserisalisation is performed manually, in order to convert from the stored +//! sequence of NodeInfos to the different arrays in SerializedDepGraph. Since the +//! node and edge count are stored at the end of the file, all the arrays can be +//! pre-allocated with the right length. -use super::{DepKind, DepNode}; +use super::query::DepGraphQuery; +use super::{DepKind, DepNode, DepNodeIndex}; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_index::vec::IndexVec; -use rustc_serialize::{Decodable, Decoder}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::sync::Lock; +use rustc_index::vec::{Idx, IndexVec}; +use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}; +use rustc_serialize::{Decodable, Decoder, Encodable}; +use smallvec::SmallVec; +use std::convert::TryInto; // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits // unused so that we can store multiple index types in `CompressedHybridIndex`, @@ -50,78 +69,239 @@ impl SerializedDepGraph { } } -impl> Decodable for SerializedDepGraph { - fn decode(d: &mut D) -> Result, D::Error> { - // We used to serialize the dep graph by creating and serializing a `SerializedDepGraph` - // using data copied from the `DepGraph`. But copying created a large memory spike, so we - // now serialize directly from the `DepGraph` as if it's a `SerializedDepGraph`. Because we - // deserialize that data into a `SerializedDepGraph` in the next compilation session, we - // need `DepGraph`'s `Encodable` and `SerializedDepGraph`'s `Decodable` implementations to - // be in sync. If you update this decoding, be sure to update the encoding, and vice-versa. - // - // We mimic the sequence of `Encode` and `Encodable` method calls used by the `DepGraph`'s - // `Encodable` implementation with the corresponding sequence of `Decode` and `Decodable` - // method calls. E.g. `Decode::read_struct` pairs with `Encode::emit_struct`, `DepNode`'s - // `decode` pairs with `DepNode`'s `encode`, and so on. Any decoding methods not associated - // with corresponding encoding methods called in `DepGraph`'s `Encodable` implementation - // are off limits, because we'd be relying on their implementation details. - // - // For example, because we know it happens to do the right thing, its tempting to just use - // `IndexVec`'s `Decodable` implementation to decode into some of the collections below, - // even though `DepGraph` doesn't use its `Encodable` implementation. But the `IndexVec` - // implementation could change, and we'd have a bug. - // - // Variables below are explicitly typed so that anyone who changes the `SerializedDepGraph` - // representation without updating this function will encounter a compilation error, and - // know to update this and possibly the `DepGraph` `Encodable` implementation accordingly - // (the latter should serialize data in a format compatible with our representation). - - d.read_struct("SerializedDepGraph", 4, |d| { - let nodes: IndexVec> = - d.read_struct_field("nodes", 0, |d| { - d.read_seq(|d, len| { - let mut v = IndexVec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); - } - Ok(v) - }) - })?; +impl<'a, K: DepKind + Decodable>> Decodable> + for SerializedDepGraph +{ + #[instrument(skip(d))] + fn decode(d: &mut opaque::Decoder<'a>) -> Result, String> { + let start_position = d.position(); - let fingerprints: IndexVec = - d.read_struct_field("fingerprints", 1, |d| { - d.read_seq(|d, len| { - let mut v = IndexVec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); - } - Ok(v) - }) - })?; + // The last 16 bytes are the node count and edge count. + debug!("position: {:?}", d.position()); + d.set_position(d.data.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE); + debug!("position: {:?}", d.position()); - let edge_list_indices: IndexVec = d - .read_struct_field("edge_list_indices", 2, |d| { - d.read_seq(|d, len| { - let mut v = IndexVec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); - } - Ok(v) - }) - })?; + let node_count = IntEncodedWithFixedSize::decode(d)?.0 as usize; + let edge_count = IntEncodedWithFixedSize::decode(d)?.0 as usize; + debug!(?node_count, ?edge_count); + + debug!("position: {:?}", d.position()); + d.set_position(start_position); + debug!("position: {:?}", d.position()); + + let mut nodes = IndexVec::with_capacity(node_count); + let mut fingerprints = IndexVec::with_capacity(node_count); + let mut edge_list_indices = IndexVec::with_capacity(node_count); + let mut edge_list_data = Vec::with_capacity(edge_count); + + for _index in 0..node_count { + d.read_struct("NodeInfo", 3, |d| { + let dep_node: DepNode = d.read_struct_field("node", 0, Decodable::decode)?; + let _i: SerializedDepNodeIndex = nodes.push(dep_node); + debug_assert_eq!(_i.index(), _index); - let edge_list_data: Vec = - d.read_struct_field("edge_list_data", 3, |d| { + let fingerprint: Fingerprint = + d.read_struct_field("fingerprint", 1, Decodable::decode)?; + let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint); + debug_assert_eq!(_i.index(), _index); + + d.read_struct_field("edges", 2, |d| { d.read_seq(|d, len| { - let mut v = Vec::with_capacity(len); - for i in 0..len { - v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?); + let start = edge_list_data.len().try_into().unwrap(); + for e in 0..len { + let edge = d.read_seq_elt(e, Decodable::decode)?; + edge_list_data.push(edge); } - Ok(v) + let end = edge_list_data.len().try_into().unwrap(); + let _i: SerializedDepNodeIndex = edge_list_indices.push((start, end)); + debug_assert_eq!(_i.index(), _index); + Ok(()) }) - })?; + }) + })?; + } + + Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data }) + } +} + +#[derive(Debug, Encodable, Decodable)] +pub struct NodeInfo { + node: DepNode, + fingerprint: Fingerprint, + edges: SmallVec<[DepNodeIndex; 8]>, +} + +struct Stat { + kind: K, + node_counter: u64, + edge_counter: u64, +} + +struct EncoderState { + encoder: FileEncoder, + total_node_count: usize, + total_edge_count: usize, + result: FileEncodeResult, + stats: Option>>, +} + +impl EncoderState { + fn new(encoder: FileEncoder, record_stats: bool) -> Self { + Self { + encoder, + total_edge_count: 0, + total_node_count: 0, + result: Ok(()), + stats: if record_stats { Some(FxHashMap::default()) } else { None }, + } + } + + #[instrument(skip(self, record_graph))] + fn encode_node( + &mut self, + node: &NodeInfo, + record_graph: &Option>>, + ) -> DepNodeIndex { + let index = DepNodeIndex::new(self.total_node_count); + self.total_node_count += 1; + + let edge_count = node.edges.len(); + self.total_edge_count += edge_count; + + if let Some(record_graph) = &record_graph { + // Do not ICE when a query is called from within `with_query`. + if let Some(record_graph) = &mut record_graph.try_lock() { + record_graph.push(index, node.node, &node.edges); + } + } + + if let Some(stats) = &mut self.stats { + let kind = node.node.kind; + + let stat = stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 }); + stat.node_counter += 1; + stat.edge_counter += edge_count as u64; + } + + debug!(?index, ?node); + let encoder = &mut self.encoder; + if self.result.is_ok() { + self.result = node.encode(encoder); + } + index + } + + fn finish(self) -> FileEncodeResult { + let Self { mut encoder, total_node_count, total_edge_count, result, stats: _ } = self; + let () = result?; + + let node_count = total_node_count.try_into().unwrap(); + let edge_count = total_edge_count.try_into().unwrap(); + + debug!(?node_count, ?edge_count); + debug!("position: {:?}", encoder.position()); + IntEncodedWithFixedSize(node_count).encode(&mut encoder)?; + IntEncodedWithFixedSize(edge_count).encode(&mut encoder)?; + debug!("position: {:?}", encoder.position()); + // Drop the encoder so that nothing is written after the counts. + encoder.flush() + } +} + +pub struct GraphEncoder { + status: Lock>, + record_graph: Option>>, +} + +impl> GraphEncoder { + pub fn new( + encoder: FileEncoder, + prev_node_count: usize, + record_graph: bool, + record_stats: bool, + ) -> Self { + let record_graph = + if record_graph { Some(Lock::new(DepGraphQuery::new(prev_node_count))) } else { None }; + let status = Lock::new(EncoderState::new(encoder, record_stats)); + GraphEncoder { status, record_graph } + } + + pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) { + if let Some(record_graph) = &self.record_graph { + f(&record_graph.lock()) + } + } + + pub(crate) fn print_incremental_info( + &self, + total_read_count: u64, + total_duplicate_read_count: u64, + ) { + let status = self.status.lock(); + if let Some(record_stats) = &status.stats { + let mut stats: Vec<_> = record_stats.values().collect(); + stats.sort_by_key(|s| -(s.node_counter as i64)); + + const SEPARATOR: &str = "[incremental] --------------------------------\ + ----------------------------------------------\ + ------------"; + + eprintln!("[incremental]"); + eprintln!("[incremental] DepGraph Statistics"); + eprintln!("{}", SEPARATOR); + eprintln!("[incremental]"); + eprintln!("[incremental] Total Node Count: {}", status.total_node_count); + eprintln!("[incremental] Total Edge Count: {}", status.total_edge_count); + + if cfg!(debug_assertions) { + eprintln!("[incremental] Total Edge Reads: {}", total_read_count); + eprintln!( + "[incremental] Total Duplicate Edge Reads: {}", + total_duplicate_read_count + ); + } + + eprintln!("[incremental]"); + eprintln!( + "[incremental] {:<36}| {:<17}| {:<12}| {:<17}|", + "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count" + ); + eprintln!("{}", SEPARATOR); + + for stat in stats { + let node_kind_ratio = + (100.0 * (stat.node_counter as f64)) / (status.total_node_count as f64); + let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64); + + eprintln!( + "[incremental] {:<36}|{:>16.1}% |{:>12} |{:>17.1} |", + format!("{:?}", stat.kind), + node_kind_ratio, + stat.node_counter, + node_kind_avg_edges, + ); + } + + eprintln!("{}", SEPARATOR); + eprintln!("[incremental]"); + } + } + + pub(crate) fn send( + &self, + profiler: &SelfProfilerRef, + node: DepNode, + fingerprint: Fingerprint, + edges: SmallVec<[DepNodeIndex; 8]>, + ) -> DepNodeIndex { + let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph"); + let node = NodeInfo { node, fingerprint, edges }; + self.status.lock().encode_node(&node, &self.record_graph) + } - Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data }) - }) + pub fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { + let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph"); + self.status.into_inner().finish() } } diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 26b76a9c00..be72baefb9 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,8 +1,9 @@ #![feature(bool_to_option)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(core_intrinsics)] +#![feature(drain_filter)] #![feature(hash_raw_entry)] +#![feature(iter_zip)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 001bf3b216..2e4c8d0565 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -49,13 +49,11 @@ pub trait QueryCache: QueryStorage { index: DepNodeIndex, ) -> Self::Stored; - fn iter( + fn iter( &self, shards: &Sharded, - f: impl for<'a> FnOnce( - &'a mut dyn Iterator, - ) -> R, - ) -> R; + f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex), + ); } pub struct DefaultCacheSelector; @@ -124,14 +122,17 @@ where value } - fn iter( + fn iter( &self, shards: &Sharded, - f: impl for<'a> FnOnce(&'a mut dyn Iterator) -> R, - ) -> R { + f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex), + ) { let shards = shards.lock_shards(); - let mut results = shards.iter().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1)); - f(&mut results) + for shard in shards.iter() { + for (k, v) in shard.iter() { + f(k, &v.0, v.1); + } + } } } @@ -207,13 +208,16 @@ where &value.0 } - fn iter( + fn iter( &self, shards: &Sharded, - f: impl for<'a> FnOnce(&'a mut dyn Iterator) -> R, - ) -> R { + f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex), + ) { let shards = shards.lock_shards(); - let mut results = shards.iter().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1)); - f(&mut results) + for shard in shards.iter() { + for (k, v) in shard.iter() { + f(k, &v.0, v.1); + } + } } } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 35a2ac865f..21f580db04 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -22,7 +22,7 @@ use { rustc_data_structures::{jobserver, OnDrop}, rustc_rayon_core as rayon_core, rustc_span::DUMMY_SP, - std::iter::FromIterator, + std::iter::{self, FromIterator}, std::{mem, process}, }; @@ -463,7 +463,7 @@ fn remove_cycle( spans.rotate_right(1); // Zip them back together - let mut stack: Vec<_> = spans.into_iter().zip(queries).collect(); + let mut stack: Vec<_> = iter::zip(spans, queries).collect(); // Remove the queries in our cycle from the list of jobs to look at for r in &stack { diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index da37209160..06a364691d 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -73,12 +73,7 @@ impl QueryCacheStore { (QueryLookup { key_hash, shard }, lock) } - pub fn iter_results( - &self, - f: impl for<'a> FnOnce( - &'a mut dyn Iterator, - ) -> R, - ) -> R { + pub fn iter_results(&self, f: &mut dyn FnMut(&C::Key, &C::Value, DepNodeIndex)) { self.cache.iter(&self.shards, f) } } @@ -449,9 +444,11 @@ where let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { tcx.start_query(job.id, diagnostics, || { - tcx.dep_context() - .dep_graph() - .with_anon_task(query.dep_kind, || query.compute(tcx, key)) + tcx.dep_context().dep_graph().with_anon_task( + *tcx.dep_context(), + query.dep_kind, + || query.compute(tcx, key), + ) }) }); @@ -537,7 +534,7 @@ where // If `-Zincremental-verify-ich` is specified, re-hash results from // the cache and make sure that they have the expected fingerprint. if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) { - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, dep_node_index, query); + incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); } result @@ -560,7 +557,7 @@ where // // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, dep_node_index, query); + incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); result } @@ -570,14 +567,12 @@ fn incremental_verify_ich( tcx: CTX::DepContext, result: &V, dep_node: &DepNode, - dep_node_index: DepNodeIndex, query: &QueryVtable, ) where CTX: QueryContext, { assert!( - Some(tcx.dep_graph().fingerprint_of(dep_node_index)) - == tcx.dep_graph().prev_fingerprint_of(dep_node), + tcx.dep_graph().is_green(dep_node), "fingerprint for green query instance not loaded from cache: {:?}", dep_node, ); @@ -588,9 +583,9 @@ fn incremental_verify_ich( let new_hash = query.hash_result(&mut hcx, result).unwrap_or(Fingerprint::ZERO); debug!("END verify_ich({:?})", dep_node); - let old_hash = tcx.dep_graph().fingerprint_of(dep_node_index); + let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); - if new_hash != old_hash { + if Some(new_hash) != old_hash { let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name { format!("`cargo clean -p {}` or `cargo clean`", crate_name) } else { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index d77022a65e..b5c95cfcb2 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1230,13 +1230,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }; let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id.to_def_id()); - let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export); self.r.macro_map.insert(def_id.to_def_id(), ext); self.r.local_macro_def_scopes.insert(def_id, parent_scope.module); - if macro_rules && matches!(item.vis.kind, ast::VisibilityKind::Inherited) { + if macro_rules { let ident = ident.normalize_to_macros_2_0(); self.r.macro_names.insert(ident); + let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export); let vis = if is_macro_export { ty::Visibility::Public } else { @@ -1261,11 +1261,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }), )) } else { - if is_macro_export { - let what = if macro_rules { "`macro_rules` with `pub`" } else { "`macro` items" }; - let msg = format!("`#[macro_export]` cannot be used on {what}"); - self.r.session.span_err(item.span, &msg); - } let module = parent_scope.module; let vis = match item.kind { // Visibilities must not be resolved non-speculatively twice diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7493fd6850..6ea46f5c52 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -450,12 +450,12 @@ impl<'a> Resolver<'a> { self.session, span, E0128, - "type parameters with a default cannot use \ + "generic parameters with a default cannot use \ forward declared identifiers" ); err.span_label( span, - "defaulted type parameters cannot be forward declared".to_string(), + "defaulted generic parameters cannot be forward declared".to_string(), ); err } @@ -472,17 +472,6 @@ impl<'a> Resolver<'a> { ); err } - ResolutionError::ParamInAnonConstInTyDefault(name) => { - let mut err = self.session.struct_span_err( - span, - "constant values inside of type parameter defaults must not depend on generic parameters", - ); - err.span_label( - span, - format!("the anonymous constant must not depend on the parameter `{}`", name), - ); - err - } ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { let mut err = self.session.struct_span_err( span, @@ -498,7 +487,13 @@ impl<'a> Resolver<'a> { name )); } - err.help("use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions"); + + if self.session.is_nightly_build() { + err.help( + "use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` \ + to allow generic const expressions" + ); + } err } @@ -606,7 +601,7 @@ impl<'a> Resolver<'a> { /// Lookup typo candidate in scope for a macro or import. fn early_lookup_typo_candidate( &mut self, - scope_set: ScopeSet, + scope_set: ScopeSet<'a>, parent_scope: &ParentScope<'a>, ident: Ident, filter_fn: &impl Fn(Res) -> bool, @@ -662,7 +657,7 @@ impl<'a> Resolver<'a> { let root_module = this.resolve_crate_root(root_ident); this.add_module_candidates(root_module, &mut suggestions, filter_fn); } - Scope::Module(module) => { + Scope::Module(module, _) => { this.add_module_candidates(module, &mut suggestions, filter_fn); } Scope::RegisteredAttrs => { @@ -758,17 +753,14 @@ impl<'a> Resolver<'a> { { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); - let not_local_module = crate_name.name != kw::Crate; - let mut worklist = - vec![(start_module, Vec::::new(), true, not_local_module)]; + let mut worklist = vec![(start_module, Vec::::new(), true)]; let mut worklist_via_import = vec![]; - while let Some((in_module, path_segments, accessible, in_module_is_extern)) = - match worklist.pop() { - None => worklist_via_import.pop(), - Some(x) => Some(x), - } - { + while let Some((in_module, path_segments, accessible)) = match worklist.pop() { + None => worklist_via_import.pop(), + Some(x) => Some(x), + } { + let in_module_is_extern = !in_module.def_id().unwrap().is_local(); // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). in_module.for_each_child(self, |this, ident, ns, name_binding| { @@ -850,11 +842,10 @@ impl<'a> Resolver<'a> { name_binding.is_extern_crate() && lookup_ident.span.rust_2018(); if !is_extern_crate_that_also_appears_in_prelude { - let is_extern = in_module_is_extern || name_binding.is_extern_crate(); // add the module to the lookup if seen_modules.insert(module.def_id().unwrap()) { if via_import { &mut worklist_via_import } else { &mut worklist } - .push((module, path_segments, child_accessible, is_extern)); + .push((module, path_segments, child_accessible)); } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 61f4c00a4c..26858915f4 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -955,14 +955,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } return None; } - PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => { + PathResult::NonModule(_) => { if no_ambiguity { assert!(import.imported_module.get().is_none()); } // The error was already reported earlier. return None; } - PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), + PathResult::Indeterminate => unreachable!(), }; let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index af241ef8af..92f21191de 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -132,10 +132,10 @@ crate enum RibKind<'a> { /// We passed through a `macro_rules!` statement MacroDefinition(DefId), - /// All bindings in this rib are type parameters that can't be used - /// from the default of a type parameter because they're not declared - /// before said type parameter. Also see the `visit_generics` override. - ForwardTyParamBanRibKind, + /// All bindings in this rib are generic parameters that can't be used + /// from the default of a generic parameter because they're not declared + /// before said generic parameter. Also see the `visit_generics` override. + ForwardGenericParamBanRibKind, /// We are inside of the type of a const parameter. Can't refer to any /// parameters. @@ -154,7 +154,7 @@ impl RibKind<'_> { | ModuleRibKind(_) | MacroDefinition(_) | ConstParamTyRibKind => false, - AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true, + AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true, } } } @@ -555,17 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); - let mut found_default = false; - default_ban_rib.bindings.extend(generics.params.iter().filter_map( - |param| match param.kind { - GenericParamKind::Const { .. } | GenericParamKind::Lifetime { .. } => None, - GenericParamKind::Type { ref default, .. } => { - found_default |= default.is_some(); - found_default.then_some((Ident::with_dummy_span(param.ident.name), Res::Err)) + let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + for param in generics.params.iter() { + match param.kind { + GenericParamKind::Type { .. } => { + forward_ty_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } - }, - )); + GenericParamKind::Const { .. } => { + forward_const_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + } + GenericParamKind::Lifetime => {} + } + } // rust-lang/rust#61631: The type `Self` is essentially // another type parameter. For ADTs, we consider it @@ -578,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // such as in the case of `trait Add`.) if self.diagnostic_metadata.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); + forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } for param in &generics.params { @@ -590,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } if let Some(ref ty) = default { - self.ribs[TypeNS].push(default_ban_rib); - self.with_rib(ValueNS, ForwardTyParamBanRibKind, |this| { - // HACK: We use an empty `ForwardTyParamBanRibKind` here which - // is only used to forbid the use of const parameters inside of - // type defaults. - // - // While the rib name doesn't really fit here, it does allow us to use the same - // code for both const and type parameters. - this.visit_ty(ty); - }); - default_ban_rib = self.ribs[TypeNS].pop().unwrap(); + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_ty(ty); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); + forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } - GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { - // FIXME(const_generics_defaults): handle `default` value here - for bound in ¶m.bounds { - self.visit_param_bound(bound); - } + GenericParamKind::Const { ref ty, kw_span: _, ref default } => { + // Const parameters can't have param bounds. + assert!(param.bounds.is_empty()); + self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); + + if let Some(ref expr) = default { + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_anon_const(expr); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); + } + + // Allow all following defaults to refer to this const parameter. + forward_const_ban_rib + .bindings + .remove(&Ident::with_dummy_span(param.ident.name)); } } } @@ -865,7 +877,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { | ItemRibKind(..) | ConstantItemRibKind(..) | ModuleRibKind(..) - | ForwardTyParamBanRibKind + | ForwardGenericParamBanRibKind | ConstParamTyRibKind => { return false; } @@ -1030,7 +1042,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => { - debug!("resolve_item ItemKind::Const"); self.with_item_rib(HasGenericParams::No, |this| { this.visit_ty(ty); if let Some(expr) = expr { @@ -1596,6 +1607,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); self.r.record_partial_res(pat.id, PartialRes::new(res)); + self.r.record_pat_span(pat.id, pat.span); } PatKind::TupleStruct(ref path, ref sub_patterns) => { self.smart_resolve_path( @@ -2326,7 +2338,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ExprKind::Call(ref callee, ref arguments) => { self.resolve_expr(callee, Some(expr)); - let const_args = self.r.legacy_const_generic_args(callee).unwrap_or(Vec::new()); + let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default(); for (idx, argument) in arguments.iter().enumerate() { // Constant arguments need to be treated as AnonConst since // that is how they will be later lowered to HIR. diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e85d78db22..e33c374f56 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -22,6 +22,8 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; +use std::iter; + use tracing::debug; type Res = def::Res; @@ -184,7 +186,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(), _ => None, } - .map_or(String::new(), |res| format!("{} ", res.descr())); + .map_or_else(String::new, |res| format!("{} ", res.descr())); (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) }; ( @@ -454,12 +456,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } + let is_macro = base_span.from_expansion() && base_span.desugaring_kind().is_none(); if !self.type_ascription_suggestion(&mut err, base_span) { let mut fallback = false; if let ( PathSource::Trait(AliasPossibility::Maybe), Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)), - ) = (source, res) + false, + ) = (source, res, is_macro) { if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object { fallback = true; @@ -926,7 +930,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \ `type` alias"; if let Some(span) = self.def_span(def_id) { - err.span_help(span, msg); + if let Ok(snip) = self.r.session.source_map().span_to_snippet(span) { + // The span contains a type alias so we should be able to + // replace `type` with `trait`. + let snip = snip.replacen("type", "trait", 1); + err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect); + } else { + err.span_help(span, msg); + } } else { err.help(msg); } @@ -1004,9 +1015,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if let Some(spans) = field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len()) { - let non_visible_spans: Vec = fields - .iter() - .zip(spans.iter()) + let non_visible_spans: Vec = iter::zip(&fields, &spans) .filter(|(vis, _)| { !self.r.is_accessible_from(**vis, self.parent_scope.module) }) @@ -1042,10 +1051,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if let Some(span) = self.def_span(def_id) { err.span_label(span, &format!("`{}` defined here", path_str)); } - let fields = - self.r.field_names.get(&def_id).map_or("/* fields */".to_string(), |fields| { - vec!["_"; fields.len()].join(", ") - }); + let fields = self.r.field_names.get(&def_id).map_or_else( + || "/* fields */".to_string(), + |fields| vec!["_"; fields.len()].join(", "), + ); err.span_suggestion( span, "use the tuple variant pattern syntax instead", diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 2c61c0963a..174df09cbd 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength //! Name resolution for lifetimes. //! //! Name resolution for lifetimes follows *much* simpler rules than the @@ -11,7 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefIdMap, LOCAL_CRATE}; +use rustc_hir::def_id::DefIdMap; use rustc_hir::hir_id::ItemLocalId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}; @@ -26,9 +27,10 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::borrow::Cow; use std::cell::Cell; +use std::fmt; use std::mem::take; -use tracing::debug; +use tracing::{debug, span, Level}; // This counts the no of times a lifetime is used #[derive(Clone, Copy, Debug)] @@ -40,9 +42,9 @@ pub enum LifetimeUseSet<'tcx> { trait RegionExt { fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (ParamName, Region); - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); + fn late(index: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); - fn late_anon(index: &Cell) -> Region; + fn late_anon(named_late_bound_vars: u32, index: &Cell) -> Region; fn id(&self) -> Option; @@ -65,29 +67,32 @@ impl RegionExt for Region { (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id.to_def_id(), origin)) } - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { + fn late(idx: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { let depth = ty::INNERMOST; let def_id = hir_map.local_def_id(param.hir_id); let origin = LifetimeDefOrigin::from_param(param); debug!( - "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}", - param, depth, def_id, origin, + "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?} origin={:?}", + idx, param, depth, def_id, origin, ); - (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id.to_def_id(), origin)) + ( + param.name.normalize_to_macros_2_0(), + Region::LateBound(depth, idx, def_id.to_def_id(), origin), + ) } - fn late_anon(index: &Cell) -> Region { + fn late_anon(named_late_bound_vars: u32, index: &Cell) -> Region { let i = index.get(); index.set(i + 1); let depth = ty::INNERMOST; - Region::LateBoundAnon(depth, i) + Region::LateBoundAnon(depth, named_late_bound_vars + i, i) } fn id(&self) -> Option { match *self { Region::Static | Region::LateBoundAnon(..) => None, - Region::EarlyBound(_, id, _) | Region::LateBound(_, id, _) | Region::Free(_, id) => { + Region::EarlyBound(_, id, _) | Region::LateBound(_, _, id, _) | Region::Free(_, id) => { Some(id) } } @@ -95,11 +100,11 @@ impl RegionExt for Region { fn shifted(self, amount: u32) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_in(amount), id, origin) + Region::LateBound(debruijn, idx, id, origin) => { + Region::LateBound(debruijn.shifted_in(amount), idx, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_in(amount), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_in(amount), index, anon_index) } _ => self, } @@ -107,11 +112,11 @@ impl RegionExt for Region { fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_out_to_binder(binder), id, origin) + Region::LateBound(debruijn, index, id, origin) => { + Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index, anon_index) } _ => self, } @@ -135,7 +140,7 @@ impl RegionExt for Region { /// FIXME. This struct gets converted to a `ResolveLifetimes` for /// actual use. It has the same data, but indexed by `LocalDefId`. This /// is silly. -#[derive(Default)] +#[derive(Debug, Default)] struct NamedRegionMap { // maps from every use of a named (not anonymous) lifetime to a // `Region` describing how that region is bound @@ -146,9 +151,13 @@ struct NamedRegionMap { // (b) it DOES appear in the arguments. late_bound: HirIdSet, - // For each type and trait definition, maps type parameters - // to the trait object lifetime defaults computed from them. - object_lifetime_defaults: HirIdMap>, + // Maps relevant hir items to the bound vars on them. These include: + // - function defs + // - function pointers + // - closures + // - trait refs + // - bound types (like `T` in `for<'a> T<'a>: Foo`) + late_bound_vars: HirIdMap>, } crate struct LifetimeContext<'a, 'tcx> { @@ -156,26 +165,16 @@ crate struct LifetimeContext<'a, 'tcx> { map: &'a mut NamedRegionMap, scope: ScopeRef<'a>, - /// This is slightly complicated. Our representation for poly-trait-refs contains a single - /// binder and thus we only allow a single level of quantification. However, - /// the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>` - /// and `for <'a, 'b> &'b T: Foo<'a>`. In order to get the De Bruijn indices - /// correct when representing these constraints, we should only introduce one - /// scope. However, we want to support both locations for the quantifier and - /// during lifetime resolution we want precise information (so we can't - /// desugar in an earlier phase). - /// - /// So, if we encounter a quantifier at the outer scope, we set - /// `trait_ref_hack` to `true` (and introduce a scope), and then if we encounter - /// a quantifier at the inner scope, we error. If `trait_ref_hack` is `false`, - /// then we introduce the scope at the inner quantifier. - trait_ref_hack: bool, - /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax. is_in_fn_syntax: bool, is_in_const_generic: bool, + /// Indicates that we only care about the definition of a trait. This should + /// be false if the `Item` we are resolving lifetimes for is not a trait or + /// we eventually need lifetimes resolve for trait items. + trait_definition_only: bool, + /// List of labels in the function/method currently under analysis. labels_in_fn: Vec, @@ -222,6 +221,14 @@ enum Scope<'a> { /// of the resulting opaque type. opaque_type_parent: bool, + scope_type: BinderScopeType, + + /// The late bound vars for a given item are stored by `HirId` to be + /// queried later. However, if we enter an elision scope, we have to + /// later append the elided bound vars to the list and need to know what + /// to append to. + hir_id: hir::HirId, + s: ScopeRef<'a>, }, @@ -249,14 +256,90 @@ enum Scope<'a> { s: ScopeRef<'a>, }, + /// When we have nested trait refs, we concanetate late bound vars for inner + /// trait refs from outer ones. But we also need to include any HRTB + /// lifetimes encountered when identifying the trait that an associated type + /// is declared on. + Supertrait { + lifetimes: Vec, + s: ScopeRef<'a>, + }, + + TraitRefBoundary { + s: ScopeRef<'a>, + }, + Root, } +#[derive(Copy, Clone, Debug)] +enum BinderScopeType { + /// Any non-concatenating binder scopes. + Normal, + /// Within a syntactic trait ref, there may be multiple poly trait refs that + /// are nested (under the `associcated_type_bounds` feature). The binders of + /// the innner poly trait refs are extended from the outer poly trait refs + /// and don't increase the late bound depth. If you had + /// `T: for<'a> Foo Baz<'a, 'b>>`, then the `for<'b>` scope + /// would be `Concatenating`. This also used in trait refs in where clauses + /// where we have two binders `for<> T: for<> Foo` (I've intentionally left + /// out any lifetimes because they aren't needed to show the two scopes). + /// The inner `for<>` has a scope of `Concatenating`. + Concatenating, +} + +// A helper struct for debugging scopes without printing parent scopes +struct TruncatedScopeDebug<'a>(&'a Scope<'a>); + +impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 { + Scope::Binder { + lifetimes, + next_early_index, + track_lifetime_uses, + opaque_type_parent, + scope_type, + hir_id, + s: _, + } => f + .debug_struct("Binder") + .field("lifetimes", lifetimes) + .field("next_early_index", next_early_index) + .field("track_lifetime_uses", track_lifetime_uses) + .field("opaque_type_parent", opaque_type_parent) + .field("scope_type", scope_type) + .field("hir_id", hir_id) + .field("s", &"..") + .finish(), + Scope::Body { id, s: _ } => { + f.debug_struct("Body").field("id", id).field("s", &"..").finish() + } + Scope::Elision { elide, s: _ } => { + f.debug_struct("Elision").field("elide", elide).field("s", &"..").finish() + } + Scope::ObjectLifetimeDefault { lifetime, s: _ } => f + .debug_struct("ObjectLifetimeDefault") + .field("lifetime", lifetime) + .field("s", &"..") + .finish(), + Scope::Supertrait { lifetimes, s: _ } => f + .debug_struct("Supertrait") + .field("lifetimes", lifetimes) + .field("s", &"..") + .finish(), + Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), + Scope::Root => f.debug_struct("Root").finish(), + } + } +} + #[derive(Clone, Debug)] enum Elide { /// Use a fresh anonymous late-bound lifetime each time, by - /// incrementing the counter to generate sequential indices. - FreshLateAnon(Cell), + /// incrementing the counter to generate sequential indices. All + /// anonymous lifetimes must start *after* named bound vars. + FreshLateAnon(u32, Cell), /// Always use this one lifetime. Exact(Region), /// Less or more than one lifetime were found, error on unspecified. @@ -283,26 +366,94 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root; pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { + resolve_lifetimes_trait_definition, resolve_lifetimes, - named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id), + named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id), is_late_bound_map, object_lifetime_defaults_map: |tcx, id| { - tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id) + let hir_id = tcx.hir().local_def_id_to_hir_id(id); + match tcx.hir().find(hir_id) { + Some(Node::Item(item)) => compute_object_lifetime_defaults(tcx, item), + _ => None, + } }, + late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), ..*providers }; } -/// Computes the `ResolveLifetimes` map that contains data for the -/// entire crate. You should not read the result of this query -/// directly, but rather use `named_region_map`, `is_late_bound_map`, -/// etc. -fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> ResolveLifetimes { - assert_eq!(for_krate, LOCAL_CRATE); +/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items. +/// Also does not generate any diagnostics. +/// +/// This is ultimately a subset of the `resolve_lifetimes` work. It effectively +/// resolves lifetimes only within the trait "header" -- that is, the trait +/// and supertrait list. In contrast, `resolve_lifetimes` resolves all the +/// lifetimes within the trait and its items. There is room to refactor this, +/// for example to resolve lifetimes for each trait item in separate queries, +/// but it's convenient to do the entire trait at once because the lifetimes +/// from the trait definition are in scope within the trait items as well. +/// +/// The reason for this separate call is to resolve what would otherwise +/// be a cycle. Consider this example: +/// +/// ```rust +/// trait Base<'a> { +/// type BaseItem; +/// } +/// trait Sub<'b>: for<'a> Base<'a> { +/// type SubItem: Sub; +/// } +/// ``` +/// +/// When we resolve `Sub` and all its items, we also have to resolve `Sub`. +/// To figure out the index of `'b`, we have to know about the supertraits +/// of `Sub` so that we can determine that the `for<'a>` will be in scope. +/// (This is because we -- currently at least -- flatten all the late-bound +/// lifetimes into a single binder.) This requires us to resolve the +/// *trait definition* of `Sub`; basically just enough lifetime information +/// to look at the supertraits. +#[tracing::instrument(level = "debug", skip(tcx))] +fn resolve_lifetimes_trait_definition( + tcx: TyCtxt<'_>, + local_def_id: LocalDefId, +) -> ResolveLifetimes { + do_resolve(tcx, local_def_id, true) +} - let named_region_map = krate(tcx); +/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`. +/// You should not read the result of this query directly, but rather use +/// `named_region_map`, `is_late_bound_map`, etc. +#[tracing::instrument(level = "debug", skip(tcx))] +fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes { + do_resolve(tcx, local_def_id, false) +} + +fn do_resolve( + tcx: TyCtxt<'_>, + local_def_id: LocalDefId, + trait_definition_only: bool, +) -> ResolveLifetimes { + let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id)); + let mut named_region_map = NamedRegionMap { + defs: Default::default(), + late_bound: Default::default(), + late_bound_vars: Default::default(), + }; + let mut visitor = LifetimeContext { + tcx, + map: &mut named_region_map, + scope: ROOT_SCOPE, + is_in_fn_syntax: false, + is_in_const_generic: false, + trait_definition_only, + labels_in_fn: vec![], + xcrate_object_lifetime_defaults: Default::default(), + lifetime_uses: &mut Default::default(), + missing_named_lifetime_spots: vec![], + }; + visitor.visit_item(item); let mut rl = ResolveLifetimes::default(); @@ -314,14 +465,62 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> ResolveLifetimes { let map = rl.late_bound.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id); } - for (hir_id, v) in named_region_map.object_lifetime_defaults { - let map = rl.object_lifetime_defaults.entry(hir_id.owner).or_default(); + for (hir_id, v) in named_region_map.late_bound_vars { + let map = rl.late_bound_vars.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } + debug!(?rl.defs); rl } +/// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution. +/// There are two important things this does. +/// First, we have to resolve lifetimes for +/// the entire *`Item`* that contains this owner, because that's the largest "scope" +/// where we can have relevant lifetimes. +/// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition` +/// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics. +/// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner +/// other than the trait itself (like the trait methods or associated types), then we just use the regular +/// `resolve_lifetimes`. +fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes { + let item_id = item_for(tcx, def_id); + if item_id == def_id { + let item = tcx.hir().item(hir::ItemId { def_id: item_id }); + match item.kind { + hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id), + _ => tcx.resolve_lifetimes(item_id), + } + } else { + tcx.resolve_lifetimes(item_id) + } +} + +/// Finds the `Item` that contains the given `LocalDefId` +fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { + let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id); + match tcx.hir().find(hir_id) { + Some(Node::Item(item)) => { + return item.def_id; + } + _ => {} + } + let item = { + let hir = tcx.hir(); + let mut parent_iter = hir.parent_iter(hir_id); + loop { + let node = parent_iter.next().map(|n| n.1); + match node { + Some(hir::Node::Item(item)) => break item.def_id, + Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."), + _ => {} + } + } + }; + item +} + fn is_late_bound_map<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -344,37 +543,10 @@ fn is_late_bound_map<'tcx>( tcx.is_late_bound_map(def_id.expect_local()) } - _ => tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&def_id).map(|lt| (def_id, lt)), + _ => resolve_lifetimes_for(tcx, def_id).late_bound.get(&def_id).map(|lt| (def_id, lt)), } } -fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { - let krate = tcx.hir().krate(); - let mut map = NamedRegionMap { - defs: Default::default(), - late_bound: Default::default(), - object_lifetime_defaults: compute_object_lifetime_defaults(tcx), - }; - { - let mut visitor = LifetimeContext { - tcx, - map: &mut map, - scope: ROOT_SCOPE, - trait_ref_hack: false, - is_in_fn_syntax: false, - is_in_const_generic: false, - labels_in_fn: vec![], - xcrate_object_lifetime_defaults: Default::default(), - lifetime_uses: &mut Default::default(), - missing_named_lifetime_spots: vec![], - }; - for item in krate.items.values() { - visitor.visit_item(item); - } - } - map -} - /// In traits, there is an implicit `Self` type parameter which comes before the generics. /// We have to account for this when computing the index of the other generic parameters. /// This function returns whether there is such an implicit parameter defined on the given item. @@ -382,6 +554,56 @@ fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool { matches!(*node, hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..)) } +fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind { + match region { + Region::LateBound(_, _, def_id, _) => { + let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); + ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) + } + Region::LateBoundAnon(_, _, anon_idx) => { + ty::BoundVariableKind::Region(ty::BrAnon(*anon_idx)) + } + _ => bug!("{:?} is not a late region", region), + } +} + +impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { + /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref. + fn poly_trait_ref_binder_info(&mut self) -> (Vec, BinderScopeType) { + let mut scope = self.scope; + let mut supertrait_lifetimes = vec![]; + loop { + match scope { + Scope::Body { .. } | Scope::Root => { + break (vec![], BinderScopeType::Normal); + } + + Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + scope = s; + } + + Scope::Supertrait { s, lifetimes } => { + supertrait_lifetimes = lifetimes.clone(); + scope = s; + } + + Scope::TraitRefBoundary { .. } => { + // We should only see super trait lifetimes if there is a `Binder` above + assert!(supertrait_lifetimes.is_empty()); + break (vec![], BinderScopeType::Normal); + } + + Scope::Binder { hir_id, .. } => { + // Nested poly trait refs have the binders concatenated + let mut full_binders = + self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + full_binders.extend(supertrait_lifetimes.into_iter()); + break (full_binders, BinderScopeType::Concatenating); + } + } + } + } +} impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; @@ -392,6 +614,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // We want to nest trait/impl items in their parent, but nothing else. fn visit_nested_item(&mut self, _: hir::ItemId) {} + fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) { + if !self.trait_definition_only { + intravisit::walk_trait_item_ref(self, ii) + } + } + fn visit_nested_body(&mut self, body: hir::BodyId) { // Each body has their own set of labels, save labels. let saved = take(&mut self.labels_in_fn); @@ -403,11 +631,58 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.labels_in_fn = saved; } + fn visit_fn( + &mut self, + fk: intravisit::FnKind<'tcx>, + fd: &'tcx hir::FnDecl<'tcx>, + b: hir::BodyId, + s: rustc_span::Span, + hir_id: hir::HirId, + ) { + let name = match fk { + intravisit::FnKind::ItemFn(id, _, _, _) => id.as_str(), + intravisit::FnKind::Method(id, _, _) => id.as_str(), + intravisit::FnKind::Closure => Symbol::intern("closure").as_str(), + }; + let name: &str = &name; + let span = span!(Level::DEBUG, "visit_fn", name); + let _enter = span.enter(); + match fk { + // Any `Binders` are handled elsewhere + intravisit::FnKind::ItemFn(..) | intravisit::FnKind::Method(..) => { + intravisit::walk_fn(self, fk, fd, b, s, hir_id) + } + intravisit::FnKind::Closure => { + self.map.late_bound_vars.insert(hir_id, vec![]); + let scope = Scope::Binder { + hir_id, + lifetimes: FxHashMap::default(), + next_early_index: self.next_early_index(), + s: self.scope, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type: BinderScopeType::Normal, + }; + self.with(scope, move |_old_scope, this| { + intravisit::walk_fn(this, fk, fd, b, s, hir_id) + }); + } + } + } + fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + match &item.kind { + hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { + if let Some(of_trait) = of_trait { + self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default()); + } + } + _ => {} + } match item.kind { hir::ItemKind::Fn(ref sig, ref generics, _) => { self.missing_named_lifetime_spots.push(generics.into()); - self.visit_early_late(None, &sig.decl, generics, |this| { + self.visit_early_late(None, item.hir_id(), &sig.decl, generics, |this| { intravisit::walk_item(this, item); }); self.missing_named_lifetime_spots.pop(); @@ -430,6 +705,47 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // Opaque types are visited when we visit the // `TyKind::OpaqueDef`, so that they have the lifetimes from // their parent opaque_ty in scope. + // + // The core idea here is that since OpaqueTys are generated with the impl Trait as + // their owner, we can keep going until we find the Item that owns that. We then + // conservatively add all resolved lifetimes. Otherwise we run into problems in + // cases like `type Foo<'a> = impl Bar`. + for (_hir_id, node) in + self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id)) + { + match node { + hir::Node::Item(parent_item) => { + let resolved_lifetimes: &ResolveLifetimes = + self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id)); + // We need to add *all* deps, since opaque tys may want them from *us* + for (&owner, defs) in resolved_lifetimes.defs.iter() { + defs.iter().for_each(|(&local_id, region)| { + self.map + .defs + .insert(hir::HirId { owner, local_id }, region.clone()); + }); + } + for (&owner, late_bound) in resolved_lifetimes.late_bound.iter() { + late_bound.iter().for_each(|&local_id| { + self.map.late_bound.insert(hir::HirId { owner, local_id }); + }); + } + for (&owner, late_bound_vars) in + resolved_lifetimes.late_bound_vars.iter() + { + late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { + self.map.late_bound_vars.insert( + hir::HirId { owner, local_id }, + late_bound_vars.clone(), + ); + }); + } + break; + } + hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"), + _ => {} + } + } } hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Enum(_, ref generics) @@ -463,16 +779,22 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }) .collect(); + self.map.late_bound_vars.insert(item.hir_id(), vec![]); let scope = Scope::Binder { + hir_id: item.hir_id(), lifetimes, next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, + scope_type: BinderScopeType::Normal, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); - intravisit::walk_item(this, item); + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + intravisit::walk_item(this, item); + }); }); self.missing_named_lifetime_spots.pop(); } @@ -482,7 +804,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { hir::ForeignItemKind::Fn(ref decl, _, ref generics) => { - self.visit_early_late(None, decl, generics, |this| { + self.visit_early_late(None, item.hir_id(), decl, generics, |this| { intravisit::walk_foreign_item(this, item); }) } @@ -495,9 +817,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - debug!("visit_ty: id={:?} ty={:?}", ty.hir_id, ty); - debug!("visit_ty: ty.kind={:?}", ty.kind); match ty.kind { hir::TyKind::BareFn(ref c) => { let next_early_index = self.next_early_index(); @@ -515,21 +836,29 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.missing_named_lifetime_spots .push(MissingLifetimeSpot::HigherRanked { span, span_type }); + let (lifetimes, binders): (FxHashMap, Vec<_>) = c + .generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param); + let r = late_region_as_bound_region(self.tcx, &pair.1); + (pair, r) + }) + .unzip(); + self.map.late_bound_vars.insert(ty.hir_id, binders); let scope = Scope::Binder { - lifetimes: c - .generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(), + hir_id: ty.hir_id, + lifetimes, s: self.scope, next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -541,10 +870,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.is_in_fn_syntax = was_in_fn_syntax; } hir::TyKind::TraitObject(bounds, ref lifetime, _) => { - debug!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds, lifetime); - for bound in bounds { - self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); - } + debug!(?bounds, ?lifetime, "TraitObject"); + let scope = Scope::TraitRefBoundary { s: self.scope }; + self.with(scope, |_, this| { + for bound in bounds { + this.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); + } + }); match lifetime.name { LifetimeName::Implicit => { // For types like `dyn Foo`, we should @@ -564,7 +896,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 - self.resolve_elided_lifetimes(vec![lifetime]) + self.resolve_elided_lifetimes(&[lifetime]) } LifetimeName::Param(_) | LifetimeName::Static => { // If the user wrote an explicit name, use that. @@ -596,9 +928,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // Elided lifetimes are not allowed in non-return // position impl Trait - let scope = Scope::Elision { elide: Elide::Forbid, s: self.scope }; + let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |_, this| { - intravisit::walk_item(this, opaque_ty); + let scope = Scope::Elision { elide: Elide::Forbid, s: this.scope }; + this.with(scope, |_, this| { + intravisit::walk_item(this, opaque_ty); + }) }); return; @@ -627,7 +962,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.hir_id).cloned(); - if let Some(Region::LateBound(_, def_id, _)) = def { + if let Some(Region::LateBound(_, _, def_id, _)) = def { if let Some(def_id) = def_id.as_local() { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB @@ -652,14 +987,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; if !parent_is_item { - struct_span_err!( - self.tcx.sess, - lifetime.span, - E0657, - "`impl Trait` can only capture lifetimes \ - bound at the fn or impl level" - ) - .emit(); + if !self.trait_definition_only { + struct_span_err!( + self.tcx.sess, + lifetime.span, + E0657, + "`impl Trait` can only capture lifetimes \ + bound at the fn or impl level" + ) + .emit(); + } self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } } @@ -670,7 +1007,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // We want to start our early-bound indices at the end of the parent scope, // not including any parent `impl Trait`s. let mut index = self.next_early_index_for_opaque_type(); - debug!("visit_ty: index = {}", index); + debug!(?index); let mut elision = None; let mut lifetimes = FxHashMap::default(); @@ -704,38 +1041,49 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } let next_early_index = index + non_lifetime_count; + self.map.late_bound_vars.insert(ty.hir_id, vec![]); if let Some(elision_region) = elision { let scope = Scope::Elision { elide: Elide::Exact(elision_region), s: self.scope }; self.with(scope, |_old_scope, this| { let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index, s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + for bound in bounds { + this.visit_param_bound(bound); + } + }) }); }); } else { let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index, s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; self.with(scope, |_old_scope, this| { - this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + this.visit_generics(generics); + for bound in bounds { + this.visit_param_bound(bound); + } + }) }); } } @@ -751,6 +1099,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(trait_item.hir_id())), + trait_item.hir_id(), &sig.decl, &trait_item.generics, |this| intravisit::walk_trait_item(this, trait_item), @@ -776,22 +1125,28 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }) .collect(); + self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]); let scope = Scope::Binder { + hir_id: trait_item.hir_id(), lifetimes, next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); - this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } - if let Some(ty) = ty { - this.visit_ty(ty); - } + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + this.visit_generics(generics); + for bound in bounds { + this.visit_param_bound(bound); + } + if let Some(ty) = ty { + this.visit_ty(ty); + } + }) }); self.missing_named_lifetime_spots.pop(); } @@ -813,6 +1168,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(impl_item.hir_id())), + impl_item.hir_id(), &sig.decl, &impl_item.generics, |this| intravisit::walk_impl_item(this, impl_item), @@ -825,7 +1181,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let mut index = self.next_early_index(); let mut non_lifetime_count = 0; debug!("visit_ty: index = {}", index); - let lifetimes = generics + let lifetimes: FxHashMap = generics .params .iter() .filter_map(|param| match param.kind { @@ -838,17 +1194,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }) .collect(); + self.map.late_bound_vars.insert(ty.hir_id, vec![]); let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + scope_type: BinderScopeType::Normal, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); - this.visit_generics(generics); - this.visit_ty(ty); + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |_, this| { + this.visit_generics(generics); + this.visit_ty(ty); + }) }); self.missing_named_lifetime_spots.pop(); } @@ -862,10 +1224,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref); if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(vec![lifetime_ref]); + self.resolve_elided_lifetimes(&[lifetime_ref]); return; } if lifetime_ref.is_static() { @@ -897,93 +1259,113 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { - check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params); - for param in generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => { - walk_list!(self, visit_param_bound, param.bounds); - if let Some(ref ty) = default { - self.visit_ty(&ty); + if !self.trait_definition_only { + check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params); + } + let scope = Scope::TraitRefBoundary { s: self.scope }; + self.with(scope, |_, this| { + for param in generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { ref default, .. } => { + walk_list!(this, visit_param_bound, param.bounds); + if let Some(ref ty) = default { + this.visit_ty(&ty); + } + } + GenericParamKind::Const { ref ty, .. } => { + let was_in_const_generic = this.is_in_const_generic; + this.is_in_const_generic = true; + walk_list!(this, visit_param_bound, param.bounds); + this.visit_ty(&ty); + this.is_in_const_generic = was_in_const_generic; } } - GenericParamKind::Const { ref ty, .. } => { - let was_in_const_generic = self.is_in_const_generic; - self.is_in_const_generic = true; - walk_list!(self, visit_param_bound, param.bounds); - self.visit_ty(&ty); - self.is_in_const_generic = was_in_const_generic; - } - } - } - for predicate in generics.where_clause.predicates { - match predicate { - &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - ref bounded_ty, - bounds, - ref bound_generic_params, - .. - }) => { - let lifetimes: FxHashMap<_, _> = bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(); - if !lifetimes.is_empty() { - let next_early_index = self.next_early_index(); + } + for predicate in generics.where_clause.predicates { + match predicate { + &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + ref bounded_ty, + bounds, + ref bound_generic_params, + .. + }) => { + let (lifetimes, binders): (FxHashMap, Vec<_>) = + bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = + Region::late(late_bound_idx as u32, &this.tcx.hir(), param); + let r = late_region_as_bound_region(this.tcx, &pair.1); + (pair, r) + }) + .unzip(); + this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); + let next_early_index = this.next_early_index(); + // Even if there are no lifetimes defined here, we still wrap it in a binder + // scope. If there happens to be a nested poly trait ref (an error), that + // will be `Concatenating` anyways, so we don't have to worry about the depth + // being wrong. let scope = Scope::Binder { + hir_id: bounded_ty.hir_id, lifetimes, - s: self.scope, + s: this.scope, next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + scope_type: BinderScopeType::Normal, }; - let result = self.with(scope, |old_scope, this| { + this.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); - this.trait_ref_hack = true; walk_list!(this, visit_param_bound, bounds); - this.trait_ref_hack = false; - }); - result - } else { - self.visit_ty(&bounded_ty); - walk_list!(self, visit_param_bound, bounds); + }) + } + &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + ref lifetime, + bounds, + .. + }) => { + this.visit_lifetime(lifetime); + walk_list!(this, visit_param_bound, bounds); + } + &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { + ref lhs_ty, + ref rhs_ty, + .. + }) => { + this.visit_ty(lhs_ty); + this.visit_ty(rhs_ty); } - } - &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - ref lifetime, - bounds, - .. - }) => { - self.visit_lifetime(lifetime); - walk_list!(self, visit_param_bound, bounds); - } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - self.visit_ty(lhs_ty); - self.visit_ty(rhs_ty); } } - } + }) } fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { match bound { - hir::GenericBound::LangItemTrait { .. } if !self.trait_ref_hack => { + hir::GenericBound::LangItemTrait(_, _, hir_id, _) => { + // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go + // through the regular poly trait ref code, so we don't get another + // chance to introduce a binder. For now, I'm keeping the existing logic + // of "if there isn't a Binder scope above us, add one", but I + // imagine there's a better way to go about this. + let (binders, scope_type) = self.poly_trait_ref_binder_info(); + + self.map.late_bound_vars.insert(*hir_id, binders); let scope = Scope::Binder { + hir_id: *hir_id, lifetimes: FxHashMap::default(), s: self.scope, next_early_index: self.next_early_index(), track_lifetime_uses: true, opaque_type_parent: false, + scope_type, }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); @@ -1002,48 +1384,53 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); - let trait_ref_hack = take(&mut self.trait_ref_hack); - if !trait_ref_hack - || trait_ref - .bound_generic_params - .iter() - .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) - { - if trait_ref_hack { - struct_span_err!( - self.tcx.sess, - trait_ref.span, - E0316, - "nested quantification of lifetimes" - ) - .emit(); - } - let next_early_index = self.next_early_index(); - let scope = Scope::Binder { - lifetimes: trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(), - s: self.scope, - next_early_index, - track_lifetime_uses: true, - opaque_type_parent: false, - }; - self.with(scope, |old_scope, this| { - this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); - walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); - this.visit_trait_ref(&trait_ref.trait_ref); + let next_early_index = self.next_early_index(); + let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); + + let initial_bound_vars = binders.len() as u32; + let mut lifetimes: FxHashMap = FxHashMap::default(); + let binders_iter = trait_ref + .bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late( + initial_bound_vars + late_bound_idx as u32, + &self.tcx.hir(), + param, + ); + let r = late_region_as_bound_region(self.tcx, &pair.1); + lifetimes.insert(pair.0, pair.1); + r }); - } else { - self.visit_trait_ref(&trait_ref.trait_ref); - } - self.trait_ref_hack = trait_ref_hack; + binders.extend(binders_iter); + + debug!(?binders); + self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); + + // Always introduce a scope here, even if this is in a where clause and + // we introduced the binders around the bounded Ty. In that case, we + // just reuse the concatenation functionality also present in nested trait + // refs. + let scope = Scope::Binder { + hir_id: trait_ref.trait_ref.hir_ref_id, + lifetimes, + s: self.scope, + next_early_index, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type, + }; + self.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); + walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); + this.visit_trait_ref(&trait_ref.trait_ref); + }); + if should_pop_missing_lt { self.missing_named_lifetime_spots.pop(); } @@ -1193,7 +1580,9 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { match *scope { Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } @@ -1224,56 +1613,53 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { } } -fn compute_object_lifetime_defaults(tcx: TyCtxt<'_>) -> HirIdMap> { - let mut map = HirIdMap::default(); - for item in tcx.hir().krate().items.values() { - match item.kind { - hir::ItemKind::Struct(_, ref generics) - | hir::ItemKind::Union(_, ref generics) - | hir::ItemKind::Enum(_, ref generics) - | hir::ItemKind::OpaqueTy(hir::OpaqueTy { - ref generics, impl_trait_fn: None, .. - }) - | hir::ItemKind::TyAlias(_, ref generics) - | hir::ItemKind::Trait(_, _, ref generics, ..) => { - let result = object_lifetime_defaults_for_item(tcx, generics); - - // Debugging aid. - let attrs = tcx.hir().attrs(item.hir_id()); - if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) { - let object_lifetime_default_reprs: String = result - .iter() - .map(|set| match *set { - Set1::Empty => "BaseDefault".into(), - Set1::One(Region::Static) => "'static".into(), - Set1::One(Region::EarlyBound(mut i, _, _)) => generics - .params - .iter() - .find_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - if i == 0 { - return Some(param.name.ident().to_string().into()); - } - i -= 1; - None +fn compute_object_lifetime_defaults( + tcx: TyCtxt<'_>, + item: &hir::Item<'_>, +) -> Option> { + match item.kind { + hir::ItemKind::Struct(_, ref generics) + | hir::ItemKind::Union(_, ref generics) + | hir::ItemKind::Enum(_, ref generics) + | hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | hir::ItemKind::TyAlias(_, ref generics) + | hir::ItemKind::Trait(_, _, ref generics, ..) => { + let result = object_lifetime_defaults_for_item(tcx, generics); + + // Debugging aid. + let attrs = tcx.hir().attrs(item.hir_id()); + if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) { + let object_lifetime_default_reprs: String = result + .iter() + .map(|set| match *set { + Set1::Empty => "BaseDefault".into(), + Set1::One(Region::Static) => "'static".into(), + Set1::One(Region::EarlyBound(mut i, _, _)) => generics + .params + .iter() + .find_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + if i == 0 { + return Some(param.name.ident().to_string().into()); } - _ => None, - }) - .unwrap(), - Set1::One(_) => bug!(), - Set1::Many => "Ambiguous".into(), - }) - .collect::>>() - .join(","); - tcx.sess.span_err(item.span, &object_lifetime_default_reprs); - } - - map.insert(item.hir_id(), result); + i -= 1; + None + } + _ => None, + }) + .unwrap(), + Set1::One(_) => bug!(), + Set1::Many => "Ambiguous".into(), + }) + .collect::>>() + .join(","); + tcx.sess.span_err(item.span, &object_lifetime_default_reprs); } - _ => {} + + Some(result) } + _ => None, } - map } /// Scan the bounds and where-clauses on parameters to extract bounds @@ -1389,18 +1775,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { tcx: *tcx, map, scope: &wrap_scope, - trait_ref_hack: self.trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, is_in_const_generic: self.is_in_const_generic, + trait_definition_only: self.trait_definition_only, labels_in_fn, xcrate_object_lifetime_defaults, lifetime_uses, missing_named_lifetime_spots, }; - debug!("entering scope {:?}", this.scope); - f(self.scope, &mut this); - this.check_uses_for_lifetimes_defined_by_scope(); - debug!("exiting scope {:?}", this.scope); + let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); + { + let _enter = span.enter(); + f(self.scope, &mut this); + if !self.trait_definition_only { + this.check_uses_for_lifetimes_defined_by_scope(); + } + } self.labels_in_fn = this.labels_in_fn; self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; self.missing_named_lifetime_spots = this.missing_named_lifetime_spots; @@ -1552,7 +1942,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .values() .flat_map(|region| match region { Region::EarlyBound(_, def_id, _) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::Free(_, def_id) => Some(*def_id), Region::LateBoundAnon(..) | Region::Static => None, @@ -1698,6 +2088,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn visit_early_late( &mut self, parent_id: Option, + hir_id: hir::HirId, decl: &'tcx hir::FnDecl<'tcx>, generics: &'tcx hir::Generics<'tcx>, walk: F, @@ -1707,31 +2098,34 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { insert_late_bound_lifetimes(self.map, decl, generics); // Find the start of nested early scopes, e.g., in methods. - let mut index = 0; + let mut next_early_index = 0; if let Some(parent_id) = parent_id { let parent = self.tcx.hir().expect_item(parent_id); if sub_items_have_self_param(&parent.kind) { - index += 1; // Self comes before lifetimes + next_early_index += 1; // Self comes before lifetimes } match parent.kind { hir::ItemKind::Trait(_, _, ref generics, ..) | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => { - index += generics.params.len() as u32; + next_early_index += generics.params.len() as u32; } _ => {} } } let mut non_lifetime_count = 0; - let lifetimes = generics + let mut named_late_bound_vars = 0; + let lifetimes: FxHashMap = generics .params .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { if self.map.late_bound.contains(¶m.hir_id) { - Some(Region::late(&self.tcx.hir(), param)) + let late_bound_idx = named_late_bound_vars; + named_late_bound_vars += 1; + Some(Region::late(late_bound_idx, &self.tcx.hir(), param)) } else { - Some(Region::early(&self.tcx.hir(), &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut next_early_index, param)) } } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { @@ -1740,14 +2134,35 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } }) .collect(); - let next_early_index = index + non_lifetime_count; + let next_early_index = next_early_index + non_lifetime_count; + let binders: Vec<_> = generics + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } + if self.map.late_bound.contains(¶m.hir_id) => + { + Some(param) + } + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param); + let r = late_region_as_bound_region(self.tcx, &pair.1); + r + }) + .collect(); + self.map.late_bound_vars.insert(hir_id, binders); let scope = Scope::Binder { + hir_id, lifetimes, next_early_index, s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, + scope_type: BinderScopeType::Normal, }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1770,7 +2185,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { s, .. } | Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => scope = s, + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => scope = s, } } } @@ -1819,7 +2236,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break None; } - Scope::Binder { ref lifetimes, s, .. } => { + Scope::Binder { ref lifetimes, scope_type, s, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) @@ -1829,12 +2246,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } _ => bug!("expected LifetimeName::Param"), } - - late_depth += 1; + match scope_type { + BinderScopeType::Normal => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } - Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -1859,10 +2281,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } // Check for fn-syntax conflicts with in-band lifetime definitions - if self.is_in_fn_syntax { + if !self.trait_definition_only && self.is_in_fn_syntax { match def { Region::EarlyBound(_, _, LifetimeDefOrigin::InBand) - | Region::LateBound(_, _, LifetimeDefOrigin::InBand) => { + | Region::LateBound(_, _, _, LifetimeDefOrigin::InBand) => { struct_span_err!( self.tcx.sess, lifetime_ref.span, @@ -1881,6 +2303,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error, ) | Region::LateBound( + _, _, _, LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error, @@ -1916,7 +2339,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } let mut elide_lifetimes = true; - let lifetimes = generic_args + let lifetimes: Vec<_> = generic_args .args .iter() .filter_map(|arg| match arg { @@ -1929,8 +2352,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, }) .collect(); + // We short-circuit here if all are elided in order to pluralize + // possible errors if elide_lifetimes { - self.resolve_elided_lifetimes(lifetimes); + self.resolve_elided_lifetimes(&lifetimes); } else { lifetimes.iter().for_each(|lt| self.visit_lifetime(lt)); } @@ -1983,7 +2408,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -1991,45 +2418,47 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; let map = &self.map; - let unsubst = if let Some(def_id) = def_id.as_local() { + let set_to_region = |set: &ObjectLifetimeDefault| match *set { + Set1::Empty => { + if in_body { + None + } else { + Some(Region::Static) + } + } + Set1::One(r) => { + let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { + GenericArg::Lifetime(lt) => Some(lt), + _ => None, + }); + r.subst(lifetimes, map) + } + Set1::Many => None, + }; + if let Some(def_id) = def_id.as_local() { let id = self.tcx.hir().local_def_id_to_hir_id(def_id); - &map.object_lifetime_defaults[&id] + self.tcx.object_lifetime_defaults(id).unwrap().iter().map(set_to_region).collect() } else { let tcx = self.tcx; - self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| { - tcx.generics_of(def_id) - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamDefKind::Type { object_lifetime_default, .. } => { - Some(object_lifetime_default) - } - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, - }) - .collect() - }) - }; - debug!("visit_segment_args: unsubst={:?}", unsubst); - unsubst - .iter() - .map(|set| match *set { - Set1::Empty => { - if in_body { - None - } else { - Some(Region::Static) - } - } - Set1::One(r) => { - let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { - GenericArg::Lifetime(lt) => Some(lt), - _ => None, - }); - r.subst(lifetimes, map) - } - Set1::Many => None, - }) - .collect() + self.xcrate_object_lifetime_defaults + .entry(def_id) + .or_insert_with(|| { + tcx.generics_of(def_id) + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamDefKind::Type { object_lifetime_default, .. } => { + Some(object_lifetime_default) + } + GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { .. } => None, + }) + .collect() + }) + .iter() + .map(set_to_region) + .collect() + } }); debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); @@ -2080,23 +2509,139 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let has_lifetime_parameter = generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); - // Resolve lifetimes found in the type `XX` from `Item = XX` bindings. - for b in generic_args.bindings { + // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or + // in the trait ref `YY<...>` in `Item: YY<...>`. + for binding in generic_args.bindings { let scope = Scope::ObjectLifetimeDefault { lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) }, s: self.scope, }; - self.with(scope, |_, this| this.visit_assoc_type_binding(b)); + if let Some(type_def_id) = type_def_id { + let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes( + self.tcx, + type_def_id, + binding.ident, + ); + self.with(scope, |_, this| { + let scope = + Scope::Supertrait { lifetimes: lifetimes.unwrap_or(vec![]), s: this.scope }; + this.with(scope, |_, this| this.visit_assoc_type_binding(binding)); + }); + } else { + self.with(scope, |_, this| this.visit_assoc_type_binding(binding)); + } + } + } + + /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the + /// associated type name and starting trait. + /// For example, imagine we have + /// ```rust + /// trait Foo<'a, 'b> { + /// type As; + /// } + /// trait Bar<'b>: for<'a> Foo<'a, 'b> {} + /// trait Bar: for<'b> Bar<'b> {} + /// ``` + /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on + /// the starting trait `Bar`, we would return `Some(['b, 'a])`. + fn supertrait_hrtb_lifetimes( + tcx: TyCtxt<'tcx>, + def_id: DefId, + assoc_name: Ident, + ) -> Option> { + let trait_defines_associated_type_named = |trait_def_id: DefId| { + tcx.associated_items(trait_def_id) + .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id) + .is_some() + }; + + use smallvec::{smallvec, SmallVec}; + let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> = + smallvec![(def_id, smallvec![])]; + let mut visited: FxHashSet = FxHashSet::default(); + loop { + let (def_id, bound_vars) = match stack.pop() { + Some(next) => next, + None => break None, + }; + // See issue #83753. If someone writes an associated type on a non-trait, just treat it as + // there being no supertrait HRTBs. + match tcx.def_kind(def_id) { + DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {} + _ => break None, + } + + if trait_defines_associated_type_named(def_id) { + break Some(bound_vars.into_iter().collect()); + } + let predicates = + tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name))); + let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { + let bound_predicate = pred.kind(); + match bound_predicate.skip_binder() { + ty::PredicateKind::Trait(data, _) => { + // The order here needs to match what we would get from `subst_supertrait` + let pred_bound_vars = bound_predicate.bound_vars(); + let mut all_bound_vars = bound_vars.clone(); + all_bound_vars.extend(pred_bound_vars.iter()); + let super_def_id = data.trait_ref.def_id; + Some((super_def_id, all_bound_vars)) + } + _ => None, + } + }); + + let obligations = obligations.filter(|o| visited.insert(o.0)); + stack.extend(obligations); } } + #[tracing::instrument(level = "debug", skip(self))] fn visit_fn_like_elision( &mut self, inputs: &'tcx [hir::Ty<'tcx>], output: Option<&'tcx hir::Ty<'tcx>>, ) { debug!("visit_fn_like_elision: enter"); - let arg_scope = Scope::Elision { elide: Elide::FreshLateAnon(Cell::new(0)), s: self.scope }; + let mut scope = &*self.scope; + let hir_id = loop { + match scope { + Scope::Binder { hir_id, .. } => { + break *hir_id; + } + Scope::Body { id, .. } => break id.hir_id, + Scope::ObjectLifetimeDefault { ref s, .. } + | Scope::Elision { ref s, .. } + | Scope::Supertrait { ref s, .. } + | Scope::TraitRefBoundary { ref s, .. } => { + scope = *s; + } + Scope::Root => { + // See issue #83907. Just bail out from looking inside. + self.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + "In fn_like_elision without appropriate scope above", + ); + return; + } + } + }; + // While not strictly necessary, we gather anon lifetimes *before* actually + // visiting the argument types. + let mut gather = GatherAnonLifetimes { anon_count: 0 }; + for input in inputs { + gather.visit_ty(input); + } + let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default(); + let named_late_bound_vars = late_bound_vars.len() as u32; + late_bound_vars.extend( + (0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))), + ); + let arg_scope = Scope::Elision { + elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)), + s: self.scope, + }; self.with(arg_scope, |_, this| { for input in inputs { this.visit_ty(input); @@ -2108,7 +2653,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { None => return, }; - debug!("visit_fn_like_elision: determine output"); + debug!("determine output"); // Figure out if there's a body we can get argument names from, // and whether there's a `self` argument (treated specially). @@ -2274,11 +2819,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Elide::Error(arg_lifetimes) }; - debug!("visit_fn_like_elision: elide={:?}", elide); + debug!(?elide); let scope = Scope::Elision { elide, s: self.scope }; self.with(scope, |_, this| this.visit_ty(output)); - debug!("visit_fn_like_elision: exit"); struct GatherLifetimes<'a> { map: &'a NamedRegionMap, @@ -2352,21 +2896,60 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) { match lifetime { - Region::LateBound(debruijn, _, _) | Region::LateBoundAnon(debruijn, _) + Region::LateBound(debruijn, _, _, _) + | Region::LateBoundAnon(debruijn, _, _) if debruijn < self.outer_index => { self.have_bound_regions = true; } _ => { + // FIXME(jackh726): nested trait refs? self.lifetimes.insert(lifetime.shifted_out_to_binder(self.outer_index)); } } } } } + + struct GatherAnonLifetimes { + anon_count: u32, + } + impl<'v> Visitor<'v> for GatherAnonLifetimes { + type Map = intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + // If we enter a `BareFn`, then we enter a *new* binding scope + if let hir::TyKind::BareFn(_) = ty.kind { + return; + } + intravisit::walk_ty(self, ty); + } + + fn visit_generic_args( + &mut self, + path_span: Span, + generic_args: &'v hir::GenericArgs<'v>, + ) { + // parenthesized args enter a new elison scope + if generic_args.parenthesized { + return; + } + intravisit::walk_generic_args(self, path_span, generic_args) + } + + fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { + if lifetime_ref.is_elided() { + self.anon_count += 1; + } + } + } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) { + fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) { debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs); if lifetime_refs.is_empty() { @@ -2385,7 +2968,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Root => break None, - Scope::Binder { s, ref lifetimes, .. } => { + Scope::Binder { s, ref lifetimes, scope_type, .. } => { // collect named lifetimes for suggestions for name in lifetimes.keys() { if let hir::ParamName::Plain(name) = name { @@ -2393,15 +2976,20 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { lifetime_spans.push(name.span); } } - late_depth += 1; + match scope_type { + BinderScopeType::Normal => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } Scope::Elision { ref elide, ref s, .. } => { let lifetime = match *elide { - Elide::FreshLateAnon(ref counter) => { + Elide::FreshLateAnon(named_late_bound_vars, ref counter) => { for lifetime_ref in lifetime_refs { - let lifetime = Region::late_anon(counter).shifted(late_depth); + let lifetime = Region::late_anon(named_late_bound_vars, counter) + .shifted(late_depth); + self.insert_lifetime(lifetime_ref, lifetime); } return; @@ -2422,7 +3010,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope = s; } Scope::ObjectLifetimeDefault { ref s, .. } - | Scope::Elision { ref s, .. } => { + | Scope::Elision { ref s, .. } + | Scope::TraitRefBoundary { ref s, .. } => { scope = s; } _ => break, @@ -2438,7 +3027,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { return; } - Scope::ObjectLifetimeDefault { s, .. } => { + Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { scope = s; } } @@ -2547,8 +3138,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let mut scope = self.scope; let lifetime = loop { match *scope { - Scope::Binder { s, .. } => { - late_depth += 1; + Scope::Binder { s, scope_type, .. } => { + match scope_type { + BinderScopeType::Normal => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } @@ -2557,6 +3151,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return, Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l, + + Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { + scope = s; + } } }; self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth)); @@ -2680,7 +3278,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { match *old_scope { Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { old_scope = s; } @@ -2726,7 +3326,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // A lifetime only used in a fn argument could as well // be replaced with `'_`, as that would generate a // fresh name, too. - Scope::Elision { elide: Elide::FreshLateAnon(_), .. } => break true, + Scope::Elision { elide: Elide::FreshLateAnon(..), .. } => break true, // In the return type or other such place, `'_` is not // going to make a fresh name, so we cannot @@ -2736,17 +3336,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { elide: Elide::Exact(_) | Elide::Error(_) | Elide::Forbid, .. } => break false, - Scope::ObjectLifetimeDefault { s, .. } => scope = s, + Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => scope = s, } } } + #[tracing::instrument(level = "debug", skip(self))] fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) { debug!( - "insert_lifetime: {} resolved to {:?} span={:?}", - self.tcx.hir().node_to_string(lifetime_ref.hir_id), - def, - self.tcx.sess.source_map().span_to_string(lifetime_ref.span) + node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id), + span = ?self.tcx.sess.source_map().span_to_string(lifetime_ref.span) ); self.map.defs.insert(lifetime_ref.hir_id, def); @@ -2756,16 +3357,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Region::Free(_, def_id) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::EarlyBound(_, def_id, _) => { // A lifetime declared by the user. let track_lifetime_uses = self.track_lifetime_uses(); - debug!("insert_lifetime: track_lifetime_uses={}", track_lifetime_uses); + debug!(?track_lifetime_uses); if track_lifetime_uses && !self.lifetime_uses.contains_key(&def_id) { - debug!("insert_lifetime: first use of {:?}", def_id); + debug!("first use of {:?}", def_id); self.lifetime_uses.insert(def_id, LifetimeUseSet::One(lifetime_ref)); } else { - debug!("insert_lifetime: many uses of {:?}", def_id); + debug!("many uses of {:?}", def_id); self.lifetime_uses.insert(def_id, LifetimeUseSet::Many); } } @@ -2791,13 +3392,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// "Constrained" basically means that it appears in any type but /// not amongst the inputs to a projection. In other words, `<&'a /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`. +#[tracing::instrument(level = "debug", skip(map))] fn insert_late_bound_lifetimes( map: &mut NamedRegionMap, decl: &hir::FnDecl<'_>, generics: &hir::Generics<'_>, ) { - debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl, generics); - let mut constrained_by_input = ConstrainedCollector::default(); for arg_ty in decl.inputs { constrained_by_input.visit_ty(arg_ty); @@ -2806,7 +3406,7 @@ fn insert_late_bound_lifetimes( let mut appears_in_output = AllCollector::default(); intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output); - debug!("insert_late_bound_lifetimes: constrained_by_input={:?}", constrained_by_input.regions); + debug!(?constrained_by_input.regions); // Walk the lifetimes that appear in where clauses. // @@ -2826,10 +3426,7 @@ fn insert_late_bound_lifetimes( } } - debug!( - "insert_late_bound_lifetimes: appears_in_where_clause={:?}", - appears_in_where_clause.regions - ); + debug!(?appears_in_where_clause.regions); // Late bound regions are those that: // - appear in the inputs @@ -2856,11 +3453,7 @@ fn insert_late_bound_lifetimes( continue; } - debug!( - "insert_late_bound_lifetimes: lifetime {:?} with id {:?} is late-bound", - param.name.ident(), - param.hir_id - ); + debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id); let inserted = map.late_bound.insert(param.hir_id); assert!(inserted, "visited lifetime {:?} twice", param.hir_id); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ccfb5ff3aa..9197f4059c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -6,7 +6,7 @@ //! Paths in macros, imports, expressions, types, patterns are resolved here. //! Label and lifetime names are resolved here as well. //! -//! Type-relative name resolution (methods, fields, associated items) happens in `librustc_typeck`. +//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_typeck`. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] @@ -14,9 +14,11 @@ #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] +#![allow(rustdoc::private_intra_doc_links)] pub use rustc_hir::def::{Namespace, PerNS}; @@ -25,7 +27,6 @@ use Determinacy::*; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; -use rustc_ast::unwrap_or; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; use rustc_ast::{Crate, CRATE_NODE_ID}; @@ -37,19 +38,19 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; -use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; +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::definitions::{DefKey, DefPathData, Definitions}; -use rustc_hir::{PrimTy, TraitCandidate}; +use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::hir::exports::ExportMap; use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, DefIdTree, ResolverOutputs}; +use rustc_middle::ty::{self, DefIdTree, MainDefinition, ResolverOutputs}; use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; @@ -108,7 +109,9 @@ enum Scope<'a> { DeriveHelpersCompat, MacroRules(MacroRulesScopeRef<'a>), CrateRoot, - Module(Module<'a>), + // The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` + // lint if it should be reported. + Module(Module<'a>, Option), RegisteredAttrs, MacroUsePrelude, BuiltinAttrs, @@ -122,13 +125,17 @@ enum Scope<'a> { /// with different restrictions when looking up the resolution. /// This enum is currently used only for early resolution (imports and macros), /// but not for late resolution yet. -enum ScopeSet { +#[derive(Clone, Copy)] +enum ScopeSet<'a> { /// All scopes with the given namespace. All(Namespace, /*is_import*/ bool), /// Crate root, then extern prelude (used for mixed 2015-2018 mode in macros). AbsolutePath(Namespace), /// All scopes with macro namespace and the given macro kind restriction. Macro(MacroKind), + /// All scopes with the given namespace, used for partially performing late resolution. + /// The node id enables lints and is used for reporting them. + Late(Namespace, Module<'a>, Option), } /// Everything you need to know about a name's location to resolve it. @@ -228,17 +235,15 @@ enum ResolutionError<'a> { ), /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>), - /// Error E0128: type parameters with a default cannot use forward-declared identifiers. + /// Error E0128: generic parameters with a default cannot use forward-declared identifiers. ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), - /// constant values inside of type parameter defaults must not depend on generic parameters. - ParamInAnonConstInTyDefault(Symbol), /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { name: Symbol, is_type: bool }, - /// Error E0735: type parameters with a default cannot use `Self` + /// Error E0735: generic parameters with a default cannot use `Self` SelfInTyParamDefault, /// Error E0767: use of unreachable label UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option }, @@ -845,6 +850,12 @@ enum BuiltinMacroState { AlreadySeen(Span), } +struct DeriveData { + resolutions: DeriveResolutions, + helper_attrs: Vec<(usize, Ident)>, + has_derive_copy: bool, +} + /// The main resolver class. /// /// This is the visitor that walks the whole crate. @@ -878,6 +889,10 @@ pub struct Resolver<'a> { /// "self-confirming" import resolutions during import validation. unusable_binding: Option<&'a NameBinding<'a>>, + // Spans for local variables found during pattern resolution. + // Used for suggestions during error reporting. + pat_span_map: NodeMap, + /// Resolutions for nodes that have a single resolution. partial_res_map: NodeMap, /// Resolutions for import nodes, which have multiple resolutions in different namespaces. @@ -967,8 +982,9 @@ pub struct Resolver<'a> { output_macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. helper_attrs: FxHashMap>, - /// Resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`. - derive_resolutions: FxHashMap, ast::Path)>>, + /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute + /// with the given `ExpnId`. + derive_data: FxHashMap, /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, @@ -1005,6 +1021,8 @@ pub struct Resolver<'a> { trait_impl_items: FxHashSet, legacy_const_generic_args: FxHashMap>>, + + main_def: Option, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1256,6 +1274,7 @@ impl<'a> Resolver<'a> { last_import_segment: false, unusable_binding: None, + pat_span_map: Default::default(), partial_res_map: Default::default(), import_res_map: Default::default(), label_res_map: Default::default(), @@ -1304,7 +1323,7 @@ impl<'a> Resolver<'a> { invocation_parent_scopes: Default::default(), output_macro_rules_scopes: Default::default(), helper_attrs: Default::default(), - derive_resolutions: Default::default(), + derive_data: Default::default(), local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), potentially_unused_imports: Vec::new(), @@ -1331,6 +1350,7 @@ impl<'a> Resolver<'a> { next_disambiguator: Default::default(), trait_impl_items: Default::default(), legacy_const_generic_args: Default::default(), + main_def: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1365,6 +1385,7 @@ impl<'a> Resolver<'a> { let maybe_unused_trait_imports = self.maybe_unused_trait_imports; let maybe_unused_extern_crates = self.maybe_unused_extern_crates; let glob_map = self.glob_map; + let main_def = self.main_def; ResolverOutputs { definitions, cstore: Box::new(self.crate_loader.into_cstore()), @@ -1379,6 +1400,7 @@ impl<'a> Resolver<'a> { .iter() .map(|(ident, entry)| (ident.name, entry.introduced_by_item)) .collect(), + main_def, } } @@ -1397,6 +1419,7 @@ impl<'a> Resolver<'a> { .iter() .map(|(ident, entry)| (ident.name, entry.introduced_by_item)) .collect(), + main_def: self.main_def.clone(), } } @@ -1442,6 +1465,7 @@ impl<'a> Resolver<'a> { self.session.time("finalize_imports", || ImportResolver { r: self }.finalize_imports()); self.session.time("finalize_macro_resolutions", || self.finalize_macro_resolutions()); self.session.time("late_resolve_crate", || self.late_resolve_crate(krate)); + self.session.time("resolve_main", || self.resolve_main()); self.session.time("resolve_check_unused", || self.check_unused(krate)); self.session.time("resolve_report_errors", || self.report_errors(krate)); self.session.time("resolve_postprocess", || self.crate_loader.postprocess(krate)); @@ -1466,7 +1490,7 @@ impl<'a> Resolver<'a> { self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| { match scope { - Scope::Module(module) => { + Scope::Module(module, _) => { this.traits_in_module(module, assoc_item, &mut found_traits); } Scope::StdLibPrelude => { @@ -1630,7 +1654,7 @@ impl<'a> Resolver<'a> { /// If the callback returns `Some` result, we stop visiting scopes and return it. fn visit_scopes( &mut self, - scope_set: ScopeSet, + scope_set: ScopeSet<'a>, parent_scope: &ParentScope<'a>, ctxt: SyntaxContext, mut visitor: impl FnMut( @@ -1686,12 +1710,17 @@ impl<'a> Resolver<'a> { ScopeSet::All(ns, _) => (ns, None, false), ScopeSet::AbsolutePath(ns) => (ns, None, true), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), + ScopeSet::Late(ns, ..) => (ns, None, false), + }; + let module = match scope_set { + // Start with the specified module. + ScopeSet::Late(_, module, _) => module, + // Jump out of trait or enum modules, they do not act as scopes. + _ => parent_scope.module.nearest_item_scope(), }; - // Jump out of trait or enum modules, they do not act as scopes. - let module = parent_scope.module.nearest_item_scope(); let mut scope = match ns { _ if is_absolute_path => Scope::CrateRoot, - TypeNS | ValueNS => Scope::Module(module), + TypeNS | ValueNS => Scope::Module(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; let mut ctxt = ctxt.normalize_to_macros_2_0(); @@ -1756,7 +1785,7 @@ impl<'a> Resolver<'a> { MacroRulesScope::Invocation(invoc_id) => { Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules) } - MacroRulesScope::Empty => Scope::Module(module), + MacroRulesScope::Empty => Scope::Module(module, None), }, Scope::CrateRoot => match ns { TypeNS => { @@ -1765,10 +1794,16 @@ impl<'a> Resolver<'a> { } ValueNS | MacroNS => break, }, - Scope::Module(module) => { + Scope::Module(module, prev_lint_id) => { use_prelude = !module.no_implicit_prelude; - match self.hygienic_lexical_parent(module, &mut ctxt) { - Some(parent_module) => Scope::Module(parent_module), + let derive_fallback_lint_id = match scope_set { + ScopeSet::Late(.., lint_id) => lint_id, + _ => None, + }; + match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) { + Some((parent_module, lint_id)) => { + Scope::Module(parent_module, lint_id.or(prev_lint_id)) + } None => { ctxt.adjust(ExpnId::root()); match ns { @@ -1824,6 +1859,7 @@ impl<'a> Resolver<'a> { ribs: &[Rib<'a>], ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); + let orig_ident = ident; if ident.name == kw::Empty { return Some(LexicalScopeBinding::Res(Res::Err)); } @@ -1873,135 +1909,48 @@ impl<'a> Resolver<'a> { _ => continue, }; - let item = self.resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), - ident, - ns, - parent_scope, - record_used, - path_span, - ); - if let Ok(binding) = item { - // The ident resolves to an item. - return Some(LexicalScopeBinding::Item(binding)); - } - match module.kind { ModuleKind::Block(..) => {} // We can see through blocks _ => break, } - } - ident = normalized_ident; - let mut poisoned = None; - loop { - let mut span_data = ident.span.data(); - let opt_module = if let Some(node_id) = record_used_id { - self.hygienic_lexical_parent_with_compatibility_fallback( - module, - &mut span_data.ctxt, - node_id, - &mut poisoned, - ) - } else { - self.hygienic_lexical_parent(module, &mut span_data.ctxt) - }; - ident.span = span_data.span(); - module = unwrap_or!(opt_module, break); - let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; - let result = self.resolve_ident_in_module_unadjusted( + let item = self.resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(module), ident, ns, - adjusted_parent_scope, + parent_scope, record_used, path_span, ); - - match result { - Ok(binding) => { - if let Some(node_id) = poisoned { - self.lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, - node_id, - ident.span, - &format!("cannot find {} `{}` in this scope", ns.descr(), ident), - BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(ident.span), - ); - } - return Some(LexicalScopeBinding::Item(binding)); - } - Err(Determined) => continue, - Err(Undetermined) => { - span_bug!(ident.span, "undetermined resolution during main resolution pass") - } - } - } - - if !module.no_implicit_prelude { - ident.span.adjust(ExpnId::root()); - if ns == TypeNS { - if let Some(binding) = self.extern_prelude_get(ident, !record_used) { - return Some(LexicalScopeBinding::Item(binding)); - } - if let Some(ident) = self.registered_tools.get(&ident) { - let binding = - (Res::ToolMod, ty::Visibility::Public, ident.span, ExpnId::root()) - .to_name_binding(self.arenas); - return Some(LexicalScopeBinding::Item(binding)); - } - } - if let Some(prelude) = self.prelude { - if let Ok(binding) = self.resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(prelude), - ident, - ns, - parent_scope, - false, - path_span, - ) { - return Some(LexicalScopeBinding::Item(binding)); - } - } - } - - if ns == TypeNS { - if let Some(prim_ty) = PrimTy::from_name(ident.name) { - let binding = - (Res::PrimTy(prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root()) - .to_name_binding(self.arenas); + if let Ok(binding) = item { + // The ident resolves to an item. return Some(LexicalScopeBinding::Item(binding)); } } - - None + self.early_resolve_ident_in_lexical_scope( + orig_ident, + ScopeSet::Late(ns, module, record_used_id), + parent_scope, + record_used, + record_used, + path_span, + ) + .ok() + .map(LexicalScopeBinding::Item) } fn hygienic_lexical_parent( &mut self, module: Module<'a>, ctxt: &mut SyntaxContext, - ) -> Option> { + derive_fallback_lint_id: Option, + ) -> Option<(Module<'a>, Option)> { if !module.expansion.outer_expn_is_descendant_of(*ctxt) { - return Some(self.macro_def_scope(ctxt.remove_mark())); + return Some((self.macro_def_scope(ctxt.remove_mark()), None)); } if let ModuleKind::Block(..) = module.kind { - return Some(module.parent.unwrap().nearest_item_scope()); - } - - None - } - - fn hygienic_lexical_parent_with_compatibility_fallback( - &mut self, - module: Module<'a>, - ctxt: &mut SyntaxContext, - node_id: NodeId, - poisoned: &mut Option, - ) -> Option> { - if let module @ Some(..) = self.hygienic_lexical_parent(module, ctxt) { - return module; + return Some((module.parent.unwrap().nearest_item_scope(), None)); } // We need to support the next case under a deprecation warning @@ -2015,20 +1964,21 @@ impl<'a> Resolver<'a> { // ---- end // ``` // So we have to fall back to the module's parent during lexical resolution in this case. - if let Some(parent) = module.parent { - // Inner module is inside the macro, parent module is outside of the macro. - if module.expansion != parent.expansion - && module.expansion.is_descendant_of(parent.expansion) - { - // The macro is a proc macro derive - if let Some(def_id) = module.expansion.expn_data().macro_def_id { - let ext = self.get_macro_by_def_id(def_id); - if ext.builtin_name.is_none() - && ext.macro_kind() == MacroKind::Derive - && parent.expansion.outer_expn_is_descendant_of(*ctxt) - { - *poisoned = Some(node_id); - return module.parent; + if derive_fallback_lint_id.is_some() { + if let Some(parent) = module.parent { + // Inner module is inside the macro, parent module is outside of the macro. + if module.expansion != parent.expansion + && module.expansion.is_descendant_of(parent.expansion) + { + // The macro is a proc macro derive + if let Some(def_id) = module.expansion.expn_data().macro_def_id { + let ext = self.get_macro_by_def_id(def_id); + if ext.builtin_name.is_none() + && ext.macro_kind() == MacroKind::Derive + && parent.expansion.outer_expn_is_descendant_of(*ctxt) + { + return Some((parent, derive_fallback_lint_id)); + } } } } @@ -2453,7 +2403,59 @@ impl<'a> Resolver<'a> { .next() .map_or(false, |c| c.is_ascii_uppercase()) { - (format!("use of undeclared type `{}`", ident), None) + // Check whether the name refers to an item in the value namespace. + let suggestion = if ribs.is_some() { + let match_span = match self.resolve_ident_in_lexical_scope( + ident, + ValueNS, + parent_scope, + None, + path_span, + &ribs.unwrap()[ValueNS], + ) { + // Name matches a local variable. For example: + // ``` + // fn f() { + // let Foo: &str = ""; + // println!("{}", Foo::Bar); // Name refers to local + // // variable `Foo`. + // } + // ``` + Some(LexicalScopeBinding::Res(Res::Local(id))) => { + Some(*self.pat_span_map.get(&id).unwrap()) + } + + // Name matches item from a local name binding + // created by `use` declaration. For example: + // ``` + // pub Foo: &str = ""; + // + // mod submod { + // use super::Foo; + // println!("{}", Foo::Bar); // Name refers to local + // // binding `Foo`. + // } + // ``` + Some(LexicalScopeBinding::Item(name_binding)) => { + Some(name_binding.span) + } + _ => None, + }; + + if let Some(span) = match_span { + Some(( + vec![(span, String::from(""))], + format!("`{}` is defined here, but is not a type", ident), + Applicability::MaybeIncorrect, + )) + } else { + None + } + } else { + None + }; + + (format!("use of undeclared type `{}`", ident), suggestion) } else { (format!("use of undeclared crate or module `{}`", ident), None) } @@ -2592,8 +2594,8 @@ impl<'a> Resolver<'a> { debug!("validate_res_from_ribs({:?})", res); let ribs = &all_ribs[rib_index + 1..]; - // An invalid forward use of a type parameter from a previous default. - if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind { + // An invalid forward use of a generic parameter from a previous default. + if let ForwardGenericParamBanRibKind = all_ribs[rib_index].kind { if record_used { let res_error = if rib_ident.name == kw::SelfUpper { ResolutionError::SelfInTyParamDefault @@ -2617,7 +2619,7 @@ impl<'a> Resolver<'a> { | ClosureOrAsyncRibKind | ModuleRibKind(..) | MacroDefinition(..) - | ForwardTyParamBanRibKind => { + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. } ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { @@ -2675,24 +2677,18 @@ impl<'a> Resolver<'a> { } } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { - let mut in_ty_param_default = false; for rib in ribs { - let has_generic_params = match rib.kind { + let has_generic_params: HasGenericParams = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => { + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. continue; } - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardTyParamBanRibKind => { - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2721,19 +2717,7 @@ impl<'a> Resolver<'a> { } } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } // This was an attempt to use a type parameter outside its scope. @@ -2771,21 +2755,15 @@ impl<'a> Resolver<'a> { ribs.next(); } - let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => continue, + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => continue, - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardTyParamBanRibKind => { - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2807,19 +2785,7 @@ impl<'a> Resolver<'a> { return Res::Err; } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } ItemRibKind(has_generic_params) => has_generic_params, @@ -2860,6 +2826,11 @@ impl<'a> Resolver<'a> { } } + fn record_pat_span(&mut self, node: NodeId, span: Span) { + debug!("(recording pat) recording {:?} for {:?}", node, span); + self.pat_span_map.insert(node, span); + } + fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool { vis.is_accessible_from(module.nearest_parent_mod, self) } @@ -3386,6 +3357,32 @@ impl<'a> Resolver<'a> { } None } + + fn resolve_main(&mut self) { + let module = self.graph_root; + let ident = Ident::with_dummy_span(sym::main); + let parent_scope = &ParentScope::module(module, self); + + let name_binding = match self.resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + ident, + ValueNS, + parent_scope, + false, + DUMMY_SP, + ) { + Ok(name_binding) => name_binding, + _ => return, + }; + + let res = name_binding.res(); + let is_import = name_binding.is_import(); + let span = name_binding.span; + if let Res::Def(DefKind::Fn, _) = res { + self.record_use(ident, ValueNS, name_binding, false); + } + self.main_def = Some(MainDefinition { res, is_import, span }); + } } fn names_to_string(names: &[Symbol]) -> String { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 2e47d4cece..10e27f33c2 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -4,7 +4,7 @@ use crate::imports::ImportResolver; use crate::Namespace::*; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BuiltinMacroState, Determinacy}; -use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak}; +use crate::{CrateLint, DeriveData, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc_ast::{self as ast, Inline, ItemKind, ModKind, NodeId}; use rustc_ast_lowering::ResolverAstLowering; @@ -14,17 +14,18 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; -use rustc_expand::base::Annotatable; -use rustc_expand::base::{Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; +use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; +use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; -use rustc_expand::expand::{AstFragment, Invocation, InvocationKind}; +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; use rustc_hir::PrimTy; use rustc_middle::middle::stability; use rustc_middle::ty; -use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNUSED_MACROS}; +use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK}; +use rustc_session::lint::builtin::{SOFT_UNSTABLE, UNUSED_MACROS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::feature_err; use rustc_session::Session; @@ -278,12 +279,12 @@ 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 require_inert = !invoc.fragment_kind.supports_macro_expansion(); + let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion(); let node_id = self.lint_node_id(eager_expansion_root); let (ext, res) = self.smart_resolve_macro_path( path, kind, - require_inert, + supports_macro_expansion, inner_attr, parent_scope, node_id, @@ -358,8 +359,8 @@ impl<'a> ResolverExpand for Resolver<'a> { fn resolve_derives( &mut self, expn_id: ExpnId, - derives: Vec, force: bool, + derive_paths: &dyn Fn() -> DeriveResolutions, ) -> Result<(), Indeterminate> { // Block expansion of the container until we resolve all derives in it. // This is required for two reasons: @@ -367,49 +368,63 @@ impl<'a> ResolverExpand for Resolver<'a> { // is applied, so they have to be produced by the container's expansion rather // than by individual derives. // - Derives in the container need to know whether one of them is a built-in `Copy`. - // FIXME: Try to cache intermediate results to avoid resolving same derives multiple times. + // Temporarily take the data to avoid borrow checker conflicts. + let mut derive_data = mem::take(&mut self.derive_data); + let entry = derive_data.entry(expn_id).or_insert_with(|| DeriveData { + resolutions: derive_paths(), + helper_attrs: Vec::new(), + has_derive_copy: false, + }); let parent_scope = self.invocation_parent_scopes[&expn_id]; - let mut exts = Vec::new(); - let mut helper_attrs = Vec::new(); - let mut has_derive_copy = false; - for path in derives { - exts.push(( - match self.resolve_macro_path( - &path, - Some(MacroKind::Derive), - &parent_scope, - true, - force, - ) { - Ok((Some(ext), _)) => { - let span = - path.segments.last().unwrap().ident.span.normalize_to_macros_2_0(); - helper_attrs - .extend(ext.helper_attrs.iter().map(|name| Ident::new(*name, span))); - has_derive_copy |= ext.builtin_name == Some(sym::Copy); - ext - } - Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), - Err(Determinacy::Undetermined) => return Err(Indeterminate), - }, - path, - )) + for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() { + if opt_ext.is_none() { + *opt_ext = Some( + match self.resolve_macro_path( + &path, + Some(MacroKind::Derive), + &parent_scope, + true, + force, + ) { + Ok((Some(ext), _)) => { + if !ext.helper_attrs.is_empty() { + let last_seg = path.segments.last().unwrap(); + let span = last_seg.ident.span.normalize_to_macros_2_0(); + entry.helper_attrs.extend( + ext.helper_attrs + .iter() + .map(|name| (i, Ident::new(*name, span))), + ); + } + entry.has_derive_copy |= ext.builtin_name == Some(sym::Copy); + ext + } + Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), + Err(Determinacy::Undetermined) => { + assert!(self.derive_data.is_empty()); + self.derive_data = derive_data; + return Err(Indeterminate); + } + }, + ); + } } - self.derive_resolutions.insert(expn_id, exts); - self.helper_attrs.insert(expn_id, helper_attrs); + // Sort helpers in a stable way independent from the derive resolution order. + entry.helper_attrs.sort_by_key(|(i, _)| *i); + self.helper_attrs + .insert(expn_id, entry.helper_attrs.iter().map(|(_, ident)| *ident).collect()); // Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive // has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`. - if has_derive_copy || self.has_derive_copy(parent_scope.expansion) { + if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) { self.containers_deriving_copy.insert(expn_id); } + assert!(self.derive_data.is_empty()); + self.derive_data = derive_data; Ok(()) } - fn take_derive_resolutions( - &mut self, - expn_id: ExpnId, - ) -> Option, ast::Path)>> { - self.derive_resolutions.remove(&expn_id) + fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option { + self.derive_data.remove(&expn_id).map(|data| data.resolutions) } // The function that implements the resolution logic of `#[cfg_accessible(path)]`. @@ -457,7 +472,7 @@ impl<'a> Resolver<'a> { &mut self, path: &ast::Path, kind: MacroKind, - require_inert: bool, + supports_macro_expansion: SupportsMacroExpansion, inner_attr: bool, parent_scope: &ParentScope<'a>, node_id: NodeId, @@ -505,8 +520,17 @@ impl<'a> Resolver<'a> { let unexpected_res = if ext.macro_kind() != kind { Some((kind.article(), kind.descr_expected())) - } else if require_inert && matches!(res, Res::Def(..)) { - Some(("a", "non-macro attribute")) + } else if matches!(res, Res::Def(..)) { + match supports_macro_expansion { + SupportsMacroExpansion::No => Some(("a", "non-macro attribute")), + SupportsMacroExpansion::Yes { supports_inner_attrs } => { + if inner_attr && !supports_inner_attrs { + Some(("a", "non-macro inner attribute")) + } else { + None + } + } + } } else { None }; @@ -633,7 +657,7 @@ impl<'a> Resolver<'a> { crate fn early_resolve_ident_in_lexical_scope( &mut self, orig_ident: Ident, - scope_set: ScopeSet, + scope_set: ScopeSet<'a>, parent_scope: &ParentScope<'a>, record_used: bool, force: bool, @@ -660,6 +684,7 @@ impl<'a> Resolver<'a> { ScopeSet::All(ns, is_import) => (ns, None, is_import), ScopeSet::AbsolutePath(ns) => (ns, None, false), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), + ScopeSet::Late(ns, ..) => (ns, None, false), }; // This is *the* result, resolution from the scope closest to the resolved identifier. @@ -768,19 +793,34 @@ impl<'a> Resolver<'a> { Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), } } - Scope::Module(module) => { + Scope::Module(module, derive_fallback_lint_id) => { let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; let binding = this.resolve_ident_in_module_unadjusted_ext( ModuleOrUniformRoot::Module(module), ident, ns, adjusted_parent_scope, - true, + !matches!(scope_set, ScopeSet::Late(..)), record_used, path_span, ); match binding { Ok(binding) => { + if let Some(lint_id) = derive_fallback_lint_id { + this.lint_buffer.buffer_lint_with_diagnostic( + PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, + lint_id, + orig_ident.span, + &format!( + "cannot find {} `{}` in this scope", + ns.descr(), + ident + ), + BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback( + orig_ident.span, + ), + ); + } let misc_flags = if ptr::eq(module, this.graph_root) { Flags::MISC_SUGGEST_CRATE } else if module.is_normal() { @@ -864,7 +904,7 @@ impl<'a> Resolver<'a> { Ok((binding, flags)) if sub_namespace_match(binding.macro_kind(), macro_kind) => { - if !record_used { + if !record_used || matches!(scope_set, ScopeSet::Late(..)) { return Some(Ok(binding)); } diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 15435df32b..12c77e0c8a 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -151,7 +151,7 @@ impl<'tcx> DumpVisitor<'tcx> { }, crate_root: crate_root.unwrap_or_else(|| "".to_owned()), external_crates: self.save_ctxt.get_external_crates(), - span: self.span_from_span(krate.item.span), + span: self.span_from_span(krate.item.inner), }; self.dumper.crate_prelude(data); @@ -320,15 +320,6 @@ impl<'tcx> DumpVisitor<'tcx> { for param in generics.params { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} - hir::GenericParamKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } => { - return self - .nest_typeck_results(self.tcx.hir().local_def_id(param.hir_id), |this| { - this.visit_generics(generics) - }); - } hir::GenericParamKind::Type { .. } => { let param_ss = param.name.ident().span; let name = escape(self.span.snippet(param_ss)); @@ -1106,16 +1097,11 @@ impl<'tcx> DumpVisitor<'tcx> { format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id())); let sm = self.tcx.sess.source_map(); - let filename = sm.span_to_filename(krate.item.span); + let filename = sm.span_to_filename(krate.item.inner); let data_id = id_from_hir_id(id, &self.save_ctxt); - let children = krate - .item - .module - .item_ids - .iter() - .map(|i| id_from_def_id(i.def_id.to_def_id())) - .collect(); - let span = self.span_from_span(krate.item.span); + let children = + krate.item.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect(); + let span = self.span_from_span(krate.item.inner); let attrs = self.tcx.hir().attrs(id); self.dumper.dump_def( diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 2acae29cc2..c19c16b88a 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -1,6 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] mod dump_visitor; @@ -516,19 +516,6 @@ impl<'tcx> SaveContext<'tcx> { }) } - pub fn get_trait_ref_data(&self, trait_ref: &hir::TraitRef<'_>) -> Option { - self.lookup_def_id(trait_ref.hir_ref_id).and_then(|def_id| { - let span = trait_ref.path.span; - if generated_code(span) { - return None; - } - let sub_span = trait_ref.path.segments.last().unwrap().ident.span; - filter!(self.span_utils, sub_span); - let span = self.span_from_span(sub_span); - Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }) - }) - } - pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option { let ty = self.typeck_results().expr_ty_adjusted_opt(expr)?; if matches!(ty.kind(), ty::Error(_)) { @@ -784,7 +771,10 @@ impl<'tcx> SaveContext<'tcx> { /// For a given piece of AST defined by the supplied Span and NodeId, /// returns `None` if the node is not macro-generated or the span is malformed, /// else uses the expansion callsite and callee to return some MacroRef. - pub fn get_macro_use_data(&self, span: Span) -> Option { + /// + /// FIXME: [`DumpVisitor::process_macro_use`] should actually dump this data + #[allow(dead_code)] + fn get_macro_use_data(&self, span: Span) -> Option { if !generated_code(span) { return None; } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 53150a9266..c3bc1c191f 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -614,11 +614,12 @@ impl<'hir> Sig for hir::Generics<'hir> { start: offset + text.len(), end: offset + text.len() + param_text.as_str().len(), }); - if let hir::GenericParamKind::Const { ref ty, ref default } = param.kind { + if let hir::GenericParamKind::Const { ref ty, default } = param.kind { param_text.push_str(": "); param_text.push_str(&ty_to_string(&ty)); - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): push the `default` value here + if let Some(default) = default { + param_text.push_str(" = "); + param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id)); } } if !param.bounds.is_empty() { diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index bbbe568f17..78a102c5c2 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -553,6 +553,12 @@ impl<'a> crate::Encoder for Encoder<'a> { fn emit_str(&mut self, v: &str) -> EncodeResult { escape_str(self.writer, v) } + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> { + for &c in s.iter() { + self.emit_u8(c)?; + } + Ok(()) + } fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult where @@ -879,6 +885,12 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> { fn emit_str(&mut self, v: &str) -> EncodeResult { escape_str(self.writer, v) } + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> { + for &c in s.iter() { + self.emit_u8(c)?; + } + Ok(()) + } fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult where @@ -2354,6 +2366,13 @@ impl crate::Decoder for Decoder { expect!(self.pop(), String).map(Cow::Owned) } + fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error> { + for c in s.iter_mut() { + *c = self.read_u8()?; + } + Ok(()) + } + fn read_enum(&mut self, _name: &str, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index e439ddcdaa..cf5a911827 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -16,7 +16,8 @@ Core encoding and decoding interfaces. #![feature(min_specialization)] #![feature(vec_spare_capacity)] #![feature(core_intrinsics)] -#![feature(int_bits_const)] +#![feature(maybe_uninit_array_assume_init)] +#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_slice)] #![feature(new_uninit)] #![cfg_attr(test, feature(test))] diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 3e37fc87ce..6e36184aff 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -1,6 +1,7 @@ use crate::leb128::{self, max_leb128_len}; -use crate::serialize; +use crate::serialize::{self, Encoder as _}; use std::borrow::Cow; +use std::convert::TryInto; use std::fs::File; use std::io::{self, Write}; use std::mem::MaybeUninit; @@ -30,11 +31,6 @@ impl Encoder { pub fn position(&self) -> usize { self.data.len() } - - #[inline] - pub fn emit_raw_bytes(&mut self, s: &[u8]) { - self.data.extend_from_slice(s); - } } macro_rules! write_leb128 { @@ -154,7 +150,12 @@ impl serialize::Encoder for Encoder { #[inline] fn emit_str(&mut self, v: &str) -> EncodeResult { self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes()); + self.emit_raw_bytes(v.as_bytes()) + } + + #[inline] + fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult { + self.data.extend_from_slice(s); Ok(()) } } @@ -208,11 +209,6 @@ impl FileEncoder { self.flushed + self.buffered } - #[inline] - pub fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { - self.write_all(s) - } - pub fn flush(&mut self) -> FileEncodeResult { // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever // offers a raw buffer access API, we can use it, and remove this. @@ -508,6 +504,11 @@ impl serialize::Encoder for FileEncoder { self.emit_usize(v.len())?; self.emit_raw_bytes(v.as_bytes()) } + + #[inline] + fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { + self.write_all(s) + } } // ----------------------------------------------------------------------------- @@ -541,23 +542,10 @@ impl<'a> Decoder<'a> { } #[inline] - pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit]) -> Result<(), String> { + pub fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] { let start = self.position; - let end = start + s.len(); - assert!(end <= self.data.len()); - - // SAFETY: Both `src` and `dst` point to at least `s.len()` elements: - // `src` points to at least `s.len()` elements by above assert, and - // `dst` points to `s.len()` elements by derivation from `s`. - unsafe { - let src = self.data.as_ptr().add(start); - let dst = s.as_mut_ptr() as *mut u8; - ptr::copy_nonoverlapping(src, dst, s.len()); - } - - self.position = end; - - Ok(()) + self.position += bytes; + &self.data[start..self.position] } } @@ -677,6 +665,14 @@ impl<'a> serialize::Decoder for Decoder<'a> { fn error(&mut self, err: &str) -> Self::Error { err.to_string() } + + #[inline] + fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), String> { + let start = self.position; + self.position += s.len(); + s.copy_from_slice(&self.data[start..self.position]); + Ok(()) + } } // Specializations for contiguous byte sequences follow. The default implementations for slices @@ -689,8 +685,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { impl serialize::Encodable for [u8] { fn encode(&self, e: &mut Encoder) -> EncodeResult { serialize::Encoder::emit_usize(e, self.len())?; - e.emit_raw_bytes(self); - Ok(()) + e.emit_raw_bytes(self) } } @@ -706,15 +701,48 @@ impl serialize::Encodable for [u8] { impl<'a> serialize::Decodable> for Vec { fn decode(d: &mut Decoder<'a>) -> Result { let len = serialize::Decoder::read_usize(d)?; + Ok(d.read_raw_bytes(len).to_owned()) + } +} - let mut v = Vec::with_capacity(len); - let buf = &mut v.spare_capacity_mut()[..len]; - d.read_raw_bytes(buf)?; +// An integer that will always encode to 8 bytes. +pub struct IntEncodedWithFixedSize(pub u64); - unsafe { - v.set_len(len); - } +impl IntEncodedWithFixedSize { + pub const ENCODED_SIZE: usize = 8; +} + +impl serialize::Encodable for IntEncodedWithFixedSize { + #[inline] + fn encode(&self, e: &mut Encoder) -> EncodeResult { + let _start_pos = e.position(); + e.emit_raw_bytes(&self.0.to_le_bytes())?; + let _end_pos = e.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + Ok(()) + } +} + +impl serialize::Encodable for IntEncodedWithFixedSize { + #[inline] + fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult { + let _start_pos = e.position(); + e.emit_raw_bytes(&self.0.to_le_bytes())?; + let _end_pos = e.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + Ok(()) + } +} + +impl<'a> serialize::Decodable> for IntEncodedWithFixedSize { + #[inline] + fn decode(decoder: &mut Decoder<'a>) -> Result { + let _start_pos = decoder.position(); + let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE); + let _end_pos = decoder.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - Ok(v) + let value = u64::from_le_bytes(bytes.try_into().unwrap()); + Ok(IntEncodedWithFixedSize(value)) } } diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 47aad5b88c..d3e5f30697 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -33,6 +33,7 @@ pub trait Encoder { fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>; fn emit_char(&mut self, v: char) -> Result<(), Self::Error>; fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error>; // Compound types: #[inline] @@ -224,6 +225,7 @@ pub trait Decoder { fn read_f32(&mut self) -> Result; fn read_char(&mut self) -> Result; fn read_str(&mut self) -> Result, Self::Error>; + fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error>; // Compound types: #[inline] diff --git a/compiler/rustc_serialize/tests/leb128.rs b/compiler/rustc_serialize/tests/leb128.rs index a2bcf2c251..3e2aab5125 100644 --- a/compiler/rustc_serialize/tests/leb128.rs +++ b/compiler/rustc_serialize/tests/leb128.rs @@ -1,4 +1,3 @@ -#![feature(int_bits_const)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 85448b7fe7..ad2b36691b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -10,7 +10,6 @@ use crate::{early_error, early_warn, Session}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::impl_stable_hash_via_hash; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_target::abi::{Align, TargetDataLayout}; use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple}; @@ -19,7 +18,7 @@ use rustc_serialize::json; use crate::parse::CrateConfig; use rustc_feature::UnstableFeatures; -use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST}; +use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; use rustc_span::source_map::{FileName, FilePathMapping}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::SourceFileHashAlgorithm; @@ -36,66 +35,6 @@ use std::iter::{self, FromIterator}; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; -bitflags! { - #[derive(Default, Encodable, Decodable)] - pub struct SanitizerSet: u8 { - const ADDRESS = 1 << 0; - const LEAK = 1 << 1; - const MEMORY = 1 << 2; - const THREAD = 1 << 3; - const HWADDRESS = 1 << 4; - } -} - -/// Formats a sanitizer set as a comma separated list of sanitizers' names. -impl fmt::Display for SanitizerSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut first = true; - for s in *self { - let name = match s { - SanitizerSet::ADDRESS => "address", - SanitizerSet::LEAK => "leak", - SanitizerSet::MEMORY => "memory", - SanitizerSet::THREAD => "thread", - SanitizerSet::HWADDRESS => "hwaddress", - _ => panic!("unrecognized sanitizer {:?}", s), - }; - if !first { - f.write_str(",")?; - } - f.write_str(name)?; - first = false; - } - Ok(()) - } -} - -impl IntoIterator for SanitizerSet { - type Item = SanitizerSet; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - [ - SanitizerSet::ADDRESS, - SanitizerSet::LEAK, - SanitizerSet::MEMORY, - SanitizerSet::THREAD, - SanitizerSet::HWADDRESS, - ] - .iter() - .copied() - .filter(|&s| self.contains(s)) - .collect::>() - .into_iter() - } -} - -impl HashStable for SanitizerSet { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.bits().hash_stable(ctx, hasher); - } -} - /// The different settings that the `-Z strip` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Strip { @@ -136,19 +75,21 @@ impl_stable_hash_via_hash!(OptLevel); /// This is what the `LtoCli` values get mapped to after resolving defaults and /// and taking other command line options into account. +/// +/// Note that linker plugin-based LTO is a different mechanism entirely. #[derive(Clone, PartialEq)] pub enum Lto { - /// Don't do any LTO whatsoever + /// Don't do any LTO whatsoever. No, - /// Do a full crate graph LTO with ThinLTO + /// Do a full-crate-graph (inter-crate) LTO with ThinLTO. Thin, - /// Do a local graph LTO with ThinLTO (only relevant for multiple codegen - /// units). + /// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is + /// only relevant if multiple CGUs are used. ThinLocal, - /// Do a full crate graph LTO with "fat" LTO + /// Do a full-crate-graph (inter-crate) LTO with "fat" LTO. Fat, } @@ -184,7 +125,38 @@ pub enum MirSpanview { Block, } -#[derive(Clone, PartialEq, Hash)] +/// The different settings that the `-Z instrument-coverage` flag can have. +/// +/// Coverage instrumentation now supports combining `-Z instrument-coverage` +/// with compiler and linker optimization (enabled with `-O` or `-C opt-level=1` +/// and higher). Nevertheless, there are many variables, depending on options +/// selected, code structure, and enabled attributes. If errors are encountered, +/// either while compiling or when generating `llvm-cov show` reports, consider +/// lowering the optimization level, including or excluding `-C link-dead-code`, +/// or using `-Z instrument-coverage=except-unused-functions` or `-Z +/// instrument-coverage=except-unused-generics`. +/// +/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the +/// coverage map, it will not attempt to generate synthetic functions for unused +/// (and not code-generated) functions (whether they are generic or not). As a +/// result, non-codegenned functions will not be included in the coverage map, +/// and will not appear, as covered or uncovered, in coverage reports. +/// +/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map, +/// unless the function has type parameters. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum InstrumentCoverage { + /// Default `-Z instrument-coverage` or `-Z instrument-coverage=statement` + All, + /// `-Z instrument-coverage=except-unused-generics` + ExceptUnusedGenerics, + /// `-Z instrument-coverage=except-unused-functions` + ExceptUnusedFunctions, + /// `-Z instrument-coverage=off` (or `no`, etc.) + Off, +} + +#[derive(Clone, PartialEq, Hash, Debug)] pub enum LinkerPluginLto { LinkerPlugin(PathBuf), LinkerPluginAuto, @@ -200,7 +172,7 @@ impl LinkerPluginLto { } } -#[derive(Clone, PartialEq, Hash)] +#[derive(Clone, PartialEq, Hash, Debug)] pub enum SwitchWithOptPath { Enabled(Option), Disabled, @@ -474,6 +446,7 @@ impl<'a> From<&'a ExternDepSpec> for rustc_lint_defs::ExternDepSpec { } impl Externs { + /// Used for testing. pub fn new(data: BTreeMap) -> Externs { Externs(data) } @@ -485,6 +458,10 @@ impl Externs { pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> { self.0.iter() } + + pub fn len(&self) -> usize { + self.0.len() + } } impl ExternEntry { @@ -573,13 +550,6 @@ impl Input { } } - pub fn get_input(&mut self) -> Option<&mut String> { - match *self { - Input::File(_) => None, - Input::Str { ref mut input, .. } => Some(input), - } - } - pub fn source_name(&self) -> FileName { match *self { Input::File(ref ifile) => ifile.clone().into(), @@ -732,8 +702,10 @@ impl Default for Options { cli_forced_codegen_units: None, cli_forced_thinlto_off: false, remap_path_prefix: Vec::new(), + real_rust_source_base_dir: None, edition: DEFAULT_EDITION, json_artifact_notifications: false, + json_unused_externs: false, pretty: None, } } @@ -747,12 +719,6 @@ impl Options { || self.debugging_opts.query_dep_graph } - #[inline(always)] - pub fn enable_dep_node_debug_strs(&self) -> bool { - cfg!(debug_assertions) - && (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info) - } - pub fn file_path_mapping(&self) -> FilePathMapping { FilePathMapping::new(self.remap_path_prefix.clone()) } @@ -813,7 +779,7 @@ pub enum CrateType { impl_stable_hash_via_hash!(CrateType); -#[derive(Clone, Hash)] +#[derive(Clone, Hash, Debug, PartialEq, Eq)] pub enum Passes { Some(Vec), All, @@ -832,7 +798,7 @@ pub const fn default_lib_output() -> CrateType { CrateType::Rlib } -pub fn default_configuration(sess: &Session) -> CrateConfig { +fn default_configuration(sess: &Session) -> CrateConfig { let end = &sess.target.endian; let arch = &sess.target.arch; let wordsz = sess.target.pointer_width.to_string(); @@ -927,14 +893,14 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo user_cfg } -pub fn build_target_config(opts: &Options, target_override: Option) -> Target { +pub(super) fn build_target_config(opts: &Options, target_override: Option) -> Target { let target_result = target_override.map_or_else(|| Target::search(&opts.target_triple), Ok); let target = target_result.unwrap_or_else(|e| { early_error( opts.error_format, &format!( "Error loading target specification: {}. \ - Use `--print target-list` for a list of built-in targets", + Run `rustc --print target-list` for a list of built-in targets", e ), ) @@ -1029,9 +995,6 @@ mod opt { pub fn flag_s(a: S, b: S, c: S) -> R { stable(longer(a, b), move |opts| opts.optflag(a, b, c)) } - pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R { - stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) - } pub fn flagmulti_s(a: S, b: S, c: S) -> R { stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) } @@ -1042,15 +1005,6 @@ mod opt { pub fn multi(a: S, b: S, c: S, d: S) -> R { unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) } - pub fn flag(a: S, b: S, c: S) -> R { - unstable(longer(a, b), move |opts| opts.optflag(a, b, c)) - } - pub fn flagopt(a: S, b: S, c: S, d: S) -> R { - unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d)) - } - pub fn flagmulti(a: S, b: S, c: S) -> R { - unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) - } } /// Returns the "short" subset of the rustc command line options, @@ -1250,15 +1204,23 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { } } +/// Possible json config files +pub struct JsonConfig { + pub json_rendered: HumanReadableErrorType, + pub json_artifact_notifications: bool, + pub json_unused_externs: bool, +} + /// Parse the `--json` flag. /// /// The first value returned is how to render JSON diagnostics, and the second /// is whether or not artifact notifications are enabled. -pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) { +pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType = HumanReadableErrorType::Default; let mut json_color = ColorConfig::Never; let mut json_artifact_notifications = false; + let mut json_unused_externs = false; for option in matches.opt_strs("json") { // For now conservatively forbid `--color` with `--json` since `--json` // won't actually be emitting any colors and anything colorized is @@ -1275,6 +1237,7 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) "diagnostic-short" => json_rendered = HumanReadableErrorType::Short, "diagnostic-rendered-ansi" => json_color = ColorConfig::Always, "artifacts" => json_artifact_notifications = true, + "unused-externs" => json_unused_externs = true, s => early_error( ErrorOutputType::default(), &format!("unknown `--json` option `{}`", s), @@ -1282,7 +1245,12 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) } } } - (json_rendered(json_color), json_artifact_notifications) + + JsonConfig { + json_rendered: json_rendered(json_color), + json_artifact_notifications, + json_unused_externs, + } } /// Parses the `--error-format` flag. @@ -1355,13 +1323,16 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition { }; if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { - early_error( - ErrorOutputType::default(), - &format!( - "edition {} is unstable and only available with -Z unstable-options.", - edition, - ), - ) + let is_nightly = nightly_options::match_is_nightly_build(matches); + let msg = if !is_nightly { + format!( + "the crate requires edition {}, but the latest edition supported by this Rust version is {}", + edition, LATEST_STABLE_EDITION + ) + } else { + format!("edition {} is unstable and only available with -Z unstable-options", edition) + }; + early_error(ErrorOutputType::default(), &msg) } edition @@ -1860,7 +1831,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let edition = parse_crate_edition(matches); - let (json_rendered, json_artifact_notifications) = parse_json(matches); + let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs } = + parse_json(matches); let error_format = parse_error_format(matches, color, json_rendered); @@ -1873,6 +1845,14 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let mut debugging_opts = build_debugging_options(matches, error_format); check_debug_option_stability(&debugging_opts, error_format, json_rendered); + if !debugging_opts.unstable_options && json_unused_externs { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to enable \ + the flag `--json=unused-externs`", + ); + } + let output_types = parse_output_types(&debugging_opts, matches, error_format); let mut cg = build_codegen_options(matches, error_format); @@ -1916,7 +1896,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } - if debugging_opts.instrument_coverage { + if debugging_opts.instrument_coverage.is_some() + && debugging_opts.instrument_coverage != Some(InstrumentCoverage::Off) + { if cg.profile_generate.enabled() || cg.profile_use.is_some() { early_error( error_format, @@ -2004,6 +1986,34 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } + // Try to find a directory containing the Rust `src`, for more details see + // the doc comment on the `real_rust_source_base_dir` field. + let tmp_buf; + let sysroot = match &sysroot_opt { + Some(s) => s, + None => { + tmp_buf = crate::filesearch::get_or_default_sysroot(); + &tmp_buf + } + }; + let real_rust_source_base_dir = { + // This is the location used by the `rust-src` `rustup` component. + let mut candidate = sysroot.join("lib/rustlib/src/rust"); + if let Ok(metadata) = candidate.symlink_metadata() { + // Replace the symlink rustbuild creates, with its destination. + // We could try to use `fs::canonicalize` instead, but that might + // produce unnecessarily verbose path. + if metadata.file_type().is_symlink() { + if let Ok(symlink_dest) = std::fs::read_link(&candidate) { + candidate = symlink_dest; + } + } + } + + // Only use this directory if it has a file we can expect to always find. + if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None } + }; + Options { crate_types, optimize: opt_level, @@ -2034,8 +2044,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { cli_forced_codegen_units: codegen_units, cli_forced_thinlto_off: disable_thinlto, remap_path_prefix, + real_rust_source_base_dir, edition, json_artifact_notifications, + json_unused_externs, pretty, } } @@ -2279,7 +2291,7 @@ impl PpMode { pub fn needs_analysis(&self) -> bool { use PpMode::*; - matches!(*self, Mir | MirCFG) + matches!(*self, Mir | MirCFG | ThirTree) } } @@ -2303,8 +2315,8 @@ impl PpMode { /// how the hash should be calculated when adding a new command-line argument. crate mod dep_tracking { use super::{ - CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel, - OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath, + CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto, + LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, }; use crate::lint; @@ -2313,7 +2325,7 @@ crate mod dep_tracking { use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; - use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; + use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel}; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::hash::Hash; @@ -2357,6 +2369,7 @@ crate mod dep_tracking { impl_dep_tracking_hash_via_hash!(PathBuf); impl_dep_tracking_hash_via_hash!(lint::Level); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); @@ -2369,6 +2382,7 @@ crate mod dep_tracking { impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(CrateType); @@ -2395,6 +2409,7 @@ crate mod dep_tracking { impl_dep_tracking_hash_for_sortable_vec_of!(String); impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); + impl_dep_tracking_hash_for_sortable_vec_of!((PathBuf, PathBuf)); impl_dep_tracking_hash_for_sortable_vec_of!(CrateType); impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level)); impl_dep_tracking_hash_for_sortable_vec_of!((String, Option, NativeLibKind)); @@ -2430,7 +2445,7 @@ crate mod dep_tracking { } // This is a stable hash because BTreeMap is a sorted container - pub fn stable_hash( + crate fn stable_hash( sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>, hasher: &mut DefaultHasher, error_format: ErrorOutputType, diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 7eaeae504e..7971f7ef9e 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,10 +1,8 @@ #![feature(crate_visibility_modifier)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] -#[macro_use] -extern crate bitflags; #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d9e5a18607..1c2a7f7716 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -5,7 +5,7 @@ use crate::lint; use crate::search_paths::SearchPath; use crate::utils::NativeLibKind; -use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; +use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel}; use rustc_feature::UnstableFeatures; @@ -20,73 +20,112 @@ use std::num::NonZeroUsize; use std::path::PathBuf; use std::str; -macro_rules! hash_option { - ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => {{}}; - ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => {{ +macro_rules! insert { + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => { if $sub_hashes .insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash) .is_some() { panic!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) } + }; +} + +macro_rules! hash_opt { + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [UNTRACKED]) => {{}}; + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [TRACKED]) => {{ insert!($opt_name, $opt_expr, $sub_hashes) }}; + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $for_crate_hash: ident, [TRACKED_NO_CRATE_HASH]) => {{ + if !$for_crate_hash { + insert!($opt_name, $opt_expr, $sub_hashes) + } }}; + ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [SUBSTRUCT]) => {{}}; +} + +macro_rules! hash_substruct { + ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [UNTRACKED]) => {{}}; + ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED]) => {{}}; + ($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); + }; } macro_rules! top_level_options { - (pub struct Options { $( - $opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*], + ( $( #[$top_level_attr:meta] )* pub struct Options { $( + $( #[$attr:meta] )* + $opt:ident : $t:ty [$dep_tracking_marker:ident], )* } ) => ( #[derive(Clone)] + $( #[$top_level_attr] )* pub struct Options { - $(pub $opt: $t),* + $( + $( #[$attr] )* + pub $opt: $t + ),* } impl Options { - pub fn dep_tracking_hash(&self) -> u64 { + pub fn dep_tracking_hash(&self, for_crate_hash: bool) -> u64 { let mut sub_hashes = BTreeMap::new(); $({ - hash_option!($opt, - &self.$opt, - &mut sub_hashes, - [$dep_tracking_marker $($warn_val, - $warn_text, - self.error_format)*]); + hash_opt!($opt, + &self.$opt, + &mut sub_hashes, + for_crate_hash, + [$dep_tracking_marker]); })* let mut hasher = DefaultHasher::new(); dep_tracking::stable_hash(sub_hashes, &mut hasher, self.error_format); + $({ + hash_substruct!($opt, + &self.$opt, + self.error_format, + for_crate_hash, + &mut hasher, + [$dep_tracking_marker]); + })* hasher.finish() } } ); } -// The top-level command-line options struct. -// -// For each option, one has to specify how it behaves with regard to the -// dependency tracking system of incremental compilation. This is done via the -// square-bracketed directive after the field type. The options are: -// -// [TRACKED] -// A change in the given field will cause the compiler to completely clear the -// incremental compilation cache before proceeding. -// -// [UNTRACKED] -// Incremental compilation is not influenced by this option. -// -// If you add a new option to this struct or one of the sub-structs like -// `CodegenOptions`, think about how it influences incremental compilation. If in -// doubt, specify [TRACKED], which is always "correct" but might lead to -// unnecessary re-compilation. top_level_options!( + /// The top-level command-line options struct. + /// + /// For each option, one has to specify how it behaves with regard to the + /// dependency tracking system of incremental compilation. This is done via the + /// square-bracketed directive after the field type. The options are: + /// + /// - `[TRACKED]` + /// A change in the given field will cause the compiler to completely clear the + /// incremental compilation cache before proceeding. + /// + /// - `[TRACKED_NO_CRATE_HASH]` + /// Same as `[TRACKED]`, but will not affect the crate hash. This is useful for options that only + /// affect the incremental cache. + /// + /// - `[UNTRACKED]` + /// Incremental compilation is not influenced by this option. + /// + /// - `[SUBSTRUCT]` + /// Second-level sub-structs containing more options. + /// + /// If you add a new option to this struct or one of the sub-structs like + /// `CodegenOptions`, think about how it influences incremental compilation. If in + /// doubt, specify `[TRACKED]`, which is always "correct" but might lead to + /// unnecessary re-compilation. pub struct Options { - // The crate config requested for the session, which may be combined - // with additional crate configurations during the compile process. + /// The crate config requested for the session, which may be combined + /// with additional crate configurations during the compile process. crate_types: Vec [TRACKED], optimize: OptLevel [TRACKED], - // Include the `debug_assertions` flag in dependency tracking, since it - // can influence whether overflow checks are done or not. + /// Include the `debug_assertions` flag in dependency tracking, since it + /// can influence whether overflow checks are done or not. debug_assertions: bool [TRACKED], debuginfo: DebugInfo [TRACKED], lint_opts: Vec<(String, lint::Level)> [TRACKED], @@ -102,51 +141,62 @@ top_level_options!( test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], - // If `Some`, enable incremental compilation, using the given - // directory to store intermediate results. + /// If `Some`, enable incremental compilation, using the given + /// directory to store intermediate results. incremental: Option [UNTRACKED], - debugging_opts: DebuggingOptions [TRACKED], + debugging_opts: DebuggingOptions [SUBSTRUCT], prints: Vec [UNTRACKED], - // Determines which borrow checker(s) to run. This is the parsed, sanitized - // version of `debugging_opts.borrowck`, which is just a plain string. + /// Determines which borrow checker(s) to run. This is the parsed, sanitized + /// version of `debugging_opts.borrowck`, which is just a plain string. borrowck_mode: BorrowckMode [UNTRACKED], - cg: CodegenOptions [TRACKED], + cg: CodegenOptions [SUBSTRUCT], externs: Externs [UNTRACKED], extern_dep_specs: ExternDepSpecs [UNTRACKED], crate_name: Option [TRACKED], - // An optional name to use as the crate for std during std injection, - // written `extern crate name as std`. Defaults to `std`. Used by - // out-of-tree drivers. + /// An optional name to use as the crate for std during std injection, + /// written `extern crate name as std`. Defaults to `std`. Used by + /// out-of-tree drivers. alt_std_name: Option [TRACKED], - // Indicates how the compiler should treat unstable features. + /// Indicates how the compiler should treat unstable features. unstable_features: UnstableFeatures [TRACKED], - // Indicates whether this run of the compiler is actually rustdoc. This - // is currently just a hack and will be removed eventually, so please - // try to not rely on this too much. + /// Indicates whether this run of the compiler is actually rustdoc. This + /// is currently just a hack and will be removed eventually, so please + /// try to not rely on this too much. actually_rustdoc: bool [TRACKED], - // Control path trimming. + /// Control path trimming. trimmed_def_paths: TrimmedDefPaths [TRACKED], - // Specifications of codegen units / ThinLTO which are forced as a - // result of parsing command line options. These are not necessarily - // what rustc was invoked with, but massaged a bit to agree with - // commands like `--emit llvm-ir` which they're often incompatible with - // if we otherwise use the defaults of rustc. + /// Specifications of codegen units / ThinLTO which are forced as a + /// result of parsing command line options. These are not necessarily + /// what rustc was invoked with, but massaged a bit to agree with + /// commands like `--emit llvm-ir` which they're often incompatible with + /// if we otherwise use the defaults of rustc. cli_forced_codegen_units: Option [UNTRACKED], cli_forced_thinlto_off: bool [UNTRACKED], - // Remap source path prefixes in all output (messages, object files, debug, etc.). - remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED], + /// Remap source path prefixes in all output (messages, object files, debug, etc.). + remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH], + /// Base directory containing the `src/` for the Rust standard library, and + /// potentially `rustc` as well, if we can can find it. Right now it's always + /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component). + /// + /// This directory is what the virtual `/rustc/$hash` is translated back to, + /// if Rust was built with path remapping to `/rustc/$hash` enabled + /// (the `rust.remap-debuginfo` option in `config.toml`). + real_rust_source_base_dir: Option [TRACKED_NO_CRATE_HASH], edition: Edition [TRACKED], - // `true` if we're emitting JSON blobs about each artifact produced - // by the compiler. + /// `true` if we're emitting JSON blobs about each artifact produced + /// by the compiler. json_artifact_notifications: bool [TRACKED], + /// `true` if we're emitting a JSON blob containing the unused externs + json_unused_externs: bool [UNTRACKED], + pretty: Option [UNTRACKED], } ); @@ -163,10 +213,10 @@ macro_rules! options { ($struct_name:ident, $setter_name:ident, $defaultfn:ident, $buildfn:ident, $prefix:expr, $outputname:expr, $stat:ident, $mod_desc:ident, $mod_set:ident, - $($opt:ident : $t:ty = ( + $($( #[$attr:meta] )* $opt:ident : $t:ty = ( $init:expr, $parse:ident, - [$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*], + [$dep_tracking_marker:ident], $desc:expr) ),* ,) => ( @@ -174,7 +224,7 @@ macro_rules! options { pub struct $struct_name { $(pub $opt: $t),* } pub fn $defaultfn() -> $struct_name { - $struct_name { $($opt: $init),* } + $struct_name { $( $( #[$attr] )* $opt: $init),* } } pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name @@ -216,18 +266,21 @@ macro_rules! options { return op; } - impl dep_tracking::DepTrackingHash for $struct_name { - fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { + impl $struct_name { + fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 { let mut sub_hashes = BTreeMap::new(); $({ - hash_option!($opt, - &self.$opt, - &mut sub_hashes, - [$dep_tracking_marker $($dep_warn_val, - $dep_warn_text, - error_format)*]); + hash_opt!($opt, + &self.$opt, + &mut sub_hashes, + _for_crate_hash, + [$dep_tracking_marker]); })* - dep_tracking::stable_hash(sub_hashes, hasher, error_format); + let mut hasher = DefaultHasher::new(); + dep_tracking::stable_hash(sub_hashes, + &mut hasher, + error_format); + hasher.finish() } } @@ -248,9 +301,9 @@ macro_rules! options { pub const parse_list: &str = "a space-separated list of strings"; pub const parse_opt_list: &str = parse_list; pub const parse_opt_comma_list: &str = "a comma-separated list of strings"; - pub const parse_uint: &str = "a number"; - pub const parse_opt_uint: &str = parse_uint; - pub const parse_threads: &str = parse_uint; + pub const parse_number: &str = "a number"; + pub const parse_opt_number: &str = parse_number; + pub const parse_threads: &str = parse_number; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; @@ -262,6 +315,7 @@ macro_rules! options { pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; + pub const parse_instrument_coverage: &str = "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0"; pub const parse_lto: &str = @@ -413,16 +467,16 @@ macro_rules! options { } } - /// Use this for any uint option that has a static default. - fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool { + /// Use this for any numeric option that has a static default. + fn parse_number(slot: &mut T, v: Option<&str>) -> bool { match v.and_then(|s| s.parse().ok()) { Some(i) => { *slot = i; true }, None => false } } - /// Use this for any uint option that lacks a static default. - fn parse_opt_uint(slot: &mut Option, v: Option<&str>) -> bool { + /// Use this for any numeric option that lacks a static default. + fn parse_opt_number(slot: &mut Option, v: Option<&str>) -> bool { match v { Some(s) => { *slot = s.parse().ok(); slot.is_some() } None => false @@ -592,6 +646,41 @@ macro_rules! options { true } + fn parse_instrument_coverage(slot: &mut Option, v: Option<&str>) -> bool { + if v.is_some() { + let mut bool_arg = None; + if parse_opt_bool(&mut bool_arg, v) { + *slot = if bool_arg.unwrap() { + Some(InstrumentCoverage::All) + } else { + None + }; + return true + } + } + + let v = match v { + None => { + *slot = Some(InstrumentCoverage::All); + return true; + } + Some(v) => v, + }; + + *slot = Some(match v { + "all" => InstrumentCoverage::All, + "except-unused-generics" | "except_unused_generics" => { + InstrumentCoverage::ExceptUnusedGenerics + } + "except-unused-functions" | "except_unused_functions" => { + InstrumentCoverage::ExceptUnusedFunctions + } + "off" | "no" | "n" | "false" | "0" => InstrumentCoverage::Off, + _ => return false, + }); + true + } + fn parse_treat_err_as_bug(slot: &mut Option, v: Option<&str>) -> bool { match v { Some(s) => { *slot = s.parse().ok(); slot.is_some() } @@ -748,13 +837,13 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "this option is deprecated and does nothing"), code_model: Option = (None, parse_code_model, [TRACKED], "choose the code model to use (`rustc --print code-models` for details)"), - codegen_units: Option = (None, parse_opt_uint, [UNTRACKED], + codegen_units: Option = (None, parse_opt_number, [UNTRACKED], "divide crate into N units to optimize in parallel"), control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED], "use Windows Control Flow Guard (default: no)"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(debug_assertions)` directive"), - debuginfo: usize = (0, parse_uint, [TRACKED], + debuginfo: usize = (0, parse_number, [TRACKED], "debug info emission level (0 = no debug info, 1 = line tables only, \ 2 = full debug info with variable and type information; default: 0)"), default_linker_libraries: bool = (false, parse_bool, [UNTRACKED], @@ -769,13 +858,13 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "force use of unwind tables"), incremental: Option = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation"), - inline_threshold: Option = (None, parse_opt_uint, [TRACKED], + inline_threshold: Option = (None, parse_opt_number, [TRACKED], "set the threshold for inlining a function"), link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED], "a single extra argument to append to the linker invocation (can be used several times)"), link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], "extra arguments to append to the linker invocation (space separated)"), - link_dead_code: Option = (None, parse_opt_bool, [UNTRACKED], + link_dead_code: Option = (None, parse_opt_bool, [TRACKED], "keep dead code at link time (useful for code coverage) (default: no)"), link_self_contained: Option = (None, parse_opt_bool, [UNTRACKED], "control whether to link Rust provided C objects/libraries or rely @@ -870,8 +959,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (default: no)"), borrowck: String = ("migrate".to_string(), parse_string, [UNTRACKED], "select which borrowck is used (`mir` or `migrate`) (default: `migrate`)"), - borrowck_stats: bool = (false, parse_bool, [UNTRACKED], - "gather borrowck statistics (default: no)"), cgu_partitioning_strategy: Option = (None, parse_opt_string, [TRACKED], "the codegen unit partitioning strategy to use"), chalk: bool = (false, parse_bool, [TRACKED], @@ -959,20 +1046,22 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "verify incr. comp. hashes of green query instances (default: no)"), inline_mir: Option = (None, parse_opt_bool, [TRACKED], "enable MIR inlining (default: no)"), - inline_mir_threshold: Option = (None, parse_opt_uint, [TRACKED], + inline_mir_threshold: Option = (None, parse_opt_number, [TRACKED], "a default MIR inlining threshold (default: 50)"), - inline_mir_hint_threshold: Option = (None, parse_opt_uint, [TRACKED], + inline_mir_hint_threshold: Option = (None, parse_opt_number, [TRACKED], "inlining threshold for functions with inline hint (default: 100)"), inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], "control whether `#[inline]` functions are in all CGUs"), input_stats: bool = (false, parse_bool, [UNTRACKED], "gather statistics about the input (default: no)"), - instrument_coverage: bool = (false, parse_bool, [TRACKED], + instrument_coverage: Option = (None, parse_instrument_coverage, [TRACKED], "instrument the generated code to support LLVM source-based code coverage \ reports (note, the compiler build config must include `profiler = true`, \ and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \ implies `-Z symbol-mangling-version=v0`; disables/overrides some Rust \ - optimizations (default: no)"), + optimizations. Optional values are: `=all` (default coverage), \ + `=except-unused-generics`, `=except-unused-functions`, or `=off` \ + (default: instrument-coverage=off)"), instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], @@ -995,10 +1084,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), - mir_opt_level: Option = (None, parse_opt_uint, [TRACKED], + mir_opt_level: Option = (None, parse_opt_number, [TRACKED], "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), - mutable_noalias: bool = (false, parse_bool, [TRACKED], - "emit noalias metadata for mutable references (default: no)"), + mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], + "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"), new_llvm_pass_manager: bool = (false, parse_bool, [TRACKED], "use new LLVM pass manager (default: no)"), nll_facts: bool = (false, parse_bool, [UNTRACKED], @@ -1089,7 +1178,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled, parse_switch_with_opt_path, [UNTRACKED], "run the self profiler and output the raw event data"), - // keep this in sync with the event filter names in librustc_data_structures/profiling.rs + /// keep this in sync with the event filter names in librustc_data_structures/profiling.rs self_profile_events: Option> = (None, parse_opt_comma_list, [UNTRACKED], "specify the events recorded by the self profiler; for example: `-Z self-profile-events=default,query-keys` @@ -1101,7 +1190,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "show spans for compiler debugging (expr|pat|ty)"), span_debug: bool = (false, parse_bool, [UNTRACKED], "forward proc_macro::Span's `Debug` impl to `Span`"), - // o/w tests have closure@path + /// o/w tests have closure@path span_free_formats: bool = (false, parse_bool, [UNTRACKED], "exclude spans when debug-printing compiler state (default: no)"), src_hash_algorithm: Option = (None, parse_src_file_hash, [TRACKED], @@ -1116,16 +1205,16 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "which mangling version to use for symbol names ('legacy' (default) or 'v0')"), teach: bool = (false, parse_bool, [TRACKED], "show extended diagnostic help (default: no)"), - terminal_width: Option = (None, parse_opt_uint, [UNTRACKED], + terminal_width: Option = (None, parse_opt_number, [UNTRACKED], "set the current terminal width"), tune_cpu: Option = (None, parse_opt_string, [TRACKED], "select processor to schedule for (`rustc --print target-cpus` for details)"), thinlto: Option = (None, parse_opt_bool, [TRACKED], "enable ThinLTO when possible"), - // We default to 1 here since we want to behave like - // a sequential compiler for now. This'll likely be adjusted - // in the future. Note that -Zthreads=0 is the way to get - // the num_cpus behavior. + /// We default to 1 here since we want to behave like + /// a sequential compiler for now. This'll likely be adjusted + /// in the future. Note that -Zthreads=0 is the way to get + /// the num_cpus behavior. threads: usize = (1, parse_threads, [UNTRACKED], "use a thread pool with N threads"), time: bool = (false, parse_bool, [UNTRACKED], @@ -1181,7 +1270,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, // - compiler/rustc_interface/src/tests.rs } -#[derive(Clone, Hash)] +#[derive(Clone, Hash, PartialEq, Eq, Debug)] pub enum WasiExecModel { Command, Reactor, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 592773bfe1..65d5d96aba 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -140,6 +140,7 @@ pub struct ParseSess { } impl ParseSess { + /// Used for testing. pub fn new(file_path_mapping: FilePathMapping) -> Self { let sm = Lrc::new(SourceMap::new(file_path_mapping)); let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(sm.clone())); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index fc57b6b8ac..e7dfc4b8c4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -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, SanitizerSet, SwitchWithOptPath}; +use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath}; use crate::filesearch; use crate::lint::{self, LintId}; use crate::parse::ParseSess; @@ -20,7 +20,7 @@ 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::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported}; +use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported}; use rustc_lint_defs::FutureBreakage; pub use rustc_span::crate_disambiguator::CrateDisambiguator; use rustc_span::edition::Edition; @@ -28,7 +28,7 @@ use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, S use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; -use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel}; +use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel}; use std::cell::{self, RefCell}; use std::env; @@ -83,6 +83,12 @@ impl Limit { } } +impl From for Limit { + fn from(value: usize) -> Self { + Self::new(value) + } +} + impl fmt::Display for Limit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) @@ -143,6 +149,10 @@ pub struct Session { /// operations such as auto-dereference and monomorphization. pub recursion_limit: OnceCell, + /// The size at which the `large_assignments` lint starts + /// being emitted. + pub move_size_limit: OnceCell, + /// The maximum length of types during monomorphization. pub type_length_limit: OnceCell, @@ -204,15 +214,6 @@ pub struct Session { /// drown everything else in noise. miri_unleashed_features: Lock)>>, - /// Base directory containing the `src/` for the Rust standard library, and - /// potentially `rustc` as well, if we can can find it. Right now it's always - /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component). - /// - /// This directory is what the virtual `/rustc/$hash` is translated back to, - /// if Rust was built with path remapping to `/rustc/$hash` enabled - /// (the `rust.remap-debuginfo` option in `config.toml`). - pub real_rust_source_base_dir: Option, - /// Architecture to use for interpreting asm!. pub asm_arch: Option, @@ -241,8 +242,7 @@ pub struct PerfStats { enum DiagnosticBuilderMethod { Note, SpanNote, - SpanSuggestion(String), // suggestion - // Add more variants as needed to support one-time diagnostics. + // Add more variants as needed to support one-time diagnostics. } /// Trait implemented by error types. This should not be implemented manually. Instead, use @@ -353,6 +353,11 @@ impl Session { 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() @@ -551,15 +556,6 @@ impl Session { let span = span_maybe.expect("`span_note` needs a span"); diag_builder.span_note(span, message); } - DiagnosticBuilderMethod::SpanSuggestion(suggestion) => { - let span = span_maybe.expect("`span_suggestion_*` needs a span"); - diag_builder.span_suggestion( - span, - message, - suggestion, - Applicability::Unspecified, - ); - } } } } @@ -589,23 +585,6 @@ impl Session { self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, msg_id, message, None); } - pub fn diag_span_suggestion_once<'a, 'b>( - &'a self, - diag_builder: &'b mut DiagnosticBuilder<'a>, - msg_id: DiagnosticMessageId, - span: Span, - message: &str, - suggestion: String, - ) { - self.diag_once( - diag_builder, - DiagnosticBuilderMethod::SpanSuggestion(suggestion), - msg_id, - message, - Some(span), - ); - } - #[inline] pub fn source_map(&self) -> &SourceMap { self.parse_sess.source_map() @@ -631,9 +610,6 @@ impl Session { pub fn verify_llvm_ir(&self) -> bool { self.opts.debugging_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some() } - pub fn borrowck_stats(&self) -> bool { - self.opts.debugging_opts.borrowck_stats - } pub fn print_llvm_passes(&self) -> bool { self.opts.debugging_opts.print_llvm_passes } @@ -793,13 +769,6 @@ impl Session { } } - pub fn inline_asm_dialect(&self) -> rustc_ast::LlvmAsmDialect { - match self.asm_arch { - Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) => rustc_ast::LlvmAsmDialect::Intel, - _ => rustc_ast::LlvmAsmDialect::Att, - } - } - pub fn relocation_model(&self) -> RelocModel { self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model) } @@ -844,8 +813,11 @@ impl Session { // This is used to control the emission of the `uwtable` attribute on // LLVM functions. // - // At the very least, unwind tables are needed when compiling with - // `-C panic=unwind`. + // Unwind tables are needed when compiling with `-C panic=unwind`, but + // LLVM won't omit unwind tables unless the function is also marked as + // `nounwind`, so users are allowed to disable `uwtable` emission. + // Historically rustc always emits `uwtable` attributes by default, so + // even they can be disabled, they're still emitted by default. // // On some targets (including windows), however, exceptions include // other events such as illegal instructions, segfaults, etc. This means @@ -858,13 +830,10 @@ impl Session { // If a target requires unwind tables, then they must be emitted. // Otherwise, we can defer to the `-C force-unwind-tables=` // value, if it is provided, or disable them, if not. - if self.panic_strategy() == PanicStrategy::Unwind { - true - } else if self.target.requires_uwtable { - true - } else { - self.opts.cg.force_unwind_tables.unwrap_or(false) - } + self.target.requires_uwtable + || self.opts.cg.force_unwind_tables.unwrap_or( + self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable, + ) } /// Returns the symbol name for the registrar function, @@ -897,22 +866,6 @@ impl Session { ) } - pub fn set_incr_session_load_dep_graph(&self, load: bool) { - let mut incr_comp_session = self.incr_comp_session.borrow_mut(); - - if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session { - *load_dep_graph = load; - } - } - - pub fn incr_session_load_dep_graph(&self) -> bool { - let incr_comp_session = self.incr_comp_session.borrow(); - match *incr_comp_session { - IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph, - _ => false, - } - } - pub fn init_incr_comp_session( &self, session_dir: PathBuf, @@ -1150,6 +1103,21 @@ impl Session { self.opts.cg.link_dead_code.unwrap_or(false) } + pub fn instrument_coverage(&self) -> bool { + self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) + != config::InstrumentCoverage::Off + } + + pub fn instrument_coverage_except_unused_generics(&self) -> bool { + self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) + == config::InstrumentCoverage::ExceptUnusedGenerics + } + + pub fn instrument_coverage_except_unused_functions(&self) -> bool { + self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) + == config::InstrumentCoverage::ExceptUnusedFunctions + } + pub fn mark_attr_known(&self, attr: &Attribute) { self.known_attrs.lock().mark(attr) } @@ -1413,26 +1381,6 @@ pub fn build_session( _ => CtfeBacktrace::Disabled, }); - // Try to find a directory containing the Rust `src`, for more details see - // the doc comment on the `real_rust_source_base_dir` field. - let real_rust_source_base_dir = { - // This is the location used by the `rust-src` `rustup` component. - let mut candidate = sysroot.join("lib/rustlib/src/rust"); - if let Ok(metadata) = candidate.symlink_metadata() { - // Replace the symlink rustbuild creates, with its destination. - // We could try to use `fs::canonicalize` instead, but that might - // produce unnecessarily verbose path. - if metadata.file_type().is_symlink() { - if let Ok(symlink_dest) = std::fs::read_link(&candidate) { - candidate = symlink_dest; - } - } - } - - // Only use this directory if it has a file we can expect to always find. - if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None } - }; - let asm_arch = if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None }; @@ -1452,6 +1400,7 @@ pub fn build_session( 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)), @@ -1475,7 +1424,6 @@ pub fn build_session( system_library_path: OneThread::new(RefCell::new(Default::default())), ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), - real_rust_source_base_dir, asm_arch, target_features: FxHashSet::default(), known_attrs: Lock::new(MarkedAttrs::new()), @@ -1521,13 +1469,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Unwind tables cannot be disabled if the target requires them. if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables { - if sess.panic_strategy() == PanicStrategy::Unwind && !include_uwtables { - sess.err( - "panic=unwind requires unwind tables, they cannot be disabled \ - with `-C force-unwind-tables=no`.", - ); - } - if sess.target.requires_uwtable && !include_uwtables { sess.err( "target requires unwind tables, they cannot be disabled with \ @@ -1555,59 +1496,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) { ); } - const ASAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-fuchsia", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-fuchsia", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - ]; - const LSAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-unknown-linux-gnu", - ]; - const MSAN_SUPPORTED_TARGETS: &[&str] = - &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"]; - const TSAN_SUPPORTED_TARGETS: &[&str] = &[ - "aarch64-apple-darwin", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-unknown-freebsd", - "x86_64-unknown-linux-gnu", - ]; - const HWASAN_SUPPORTED_TARGETS: &[&str] = - &["aarch64-linux-android", "aarch64-unknown-linux-gnu"]; - - // Sanitizers can only be used on some tested platforms. - for s in sess.opts.debugging_opts.sanitizer { - let supported_targets = match s { - SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS, - SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS, - SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS, - SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS, - SanitizerSet::HWADDRESS => HWASAN_SUPPORTED_TARGETS, - _ => panic!("unrecognized sanitizer {}", s), - }; - if !supported_targets.contains(&&*sess.opts.target_triple.triple()) { - sess.err(&format!( - "`-Zsanitizer={}` only works with targets: {}", - s, - supported_targets.join(", ") - )); - } - let conflicting = sess.opts.debugging_opts.sanitizer - s; - if !conflicting.is_empty() { - sess.err(&format!( - "`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", - s, conflicting, - )); - // Don't report additional errors. - break; - } + // 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; + match unsupported_sanitizers.into_iter().count() { + 0 => {} + 1 => sess + .err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)), + _ => sess.err(&format!( + "{} sanitizers are not supported for this target", + unsupported_sanitizers + )), + } + // Cannot mix and match sanitizers. + let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter(); + if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) { + sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second)); } } diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index f3d3330912..e9d597d1ba 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -1,7 +1,13 @@ +use crate::parse::ParseSess; use crate::session::Session; +use rustc_ast::token::{self, DelimToken, Nonterminal, Token}; +use rustc_ast::tokenstream::CanSynthesizeMissingTokens; +use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_data_structures::profiling::VerboseTimingGuard; use std::path::{Path, PathBuf}; +pub type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream; + impl Session { pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> { self.prof.verbose_generic_activity(what) @@ -53,3 +59,52 @@ impl CanonicalizedPath { &self.original } } + +// FIXME: Find a better spot for this - it needs to be accessible from `rustc_ast_lowering`, +// and needs to access `ParseSess +pub struct FlattenNonterminals<'a> { + pub parse_sess: &'a ParseSess, + pub synthesize_tokens: CanSynthesizeMissingTokens, + pub nt_to_tokenstream: NtToTokenstream, +} + +impl<'a> FlattenNonterminals<'a> { + pub fn process_token_stream(&mut self, tokens: TokenStream) -> TokenStream { + fn can_skip(stream: &TokenStream) -> bool { + stream.trees().all(|tree| match tree { + TokenTree::Token(token) => !matches!(token.kind, token::Interpolated(_)), + TokenTree::Delimited(_, _, inner) => can_skip(&inner), + }) + } + + if can_skip(&tokens) { + return tokens; + } + + tokens.into_trees().flat_map(|tree| self.process_token_tree(tree).into_trees()).collect() + } + + pub fn process_token_tree(&mut self, tree: TokenTree) -> TokenStream { + match tree { + TokenTree::Token(token) => self.process_token(token), + TokenTree::Delimited(span, delim, tts) => { + TokenTree::Delimited(span, delim, self.process_token_stream(tts)).into() + } + } + } + + pub fn process_token(&mut self, token: Token) -> TokenStream { + match token.kind { + token::Interpolated(nt) => { + let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens); + TokenTree::Delimited( + DelimSpan::from_single(token.span), + DelimToken::NoDelim, + self.process_token_stream(tts), + ) + .into() + } + _ => TokenTree::Token(token).into(), + } + } +} diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 885f30ebb4..95bb0ad7ba 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -160,6 +160,8 @@ impl DefPathHash { } /// Returns the crate-local part of the [DefPathHash]. + /// + /// Used for tests. #[inline] pub fn local_hash(&self) -> u64 { self.0.as_value().1 diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index eb5b7c4a74..f75fe22767 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -413,7 +413,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb let names: Vec<_> = range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect(); HygieneData::with(|data| { - range_to_update.zip(names.into_iter()).for_each(|(idx, name)| { + range_to_update.zip(names).for_each(|(idx, name)| { data.syntax_context_data[idx].dollar_crate_name = name; }) }) @@ -748,7 +748,7 @@ pub struct ExpnData { /// 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 constract of `HashStable` + /// 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). @@ -1176,11 +1176,7 @@ pub fn decode_syntax_context< Ok(new_ctxt) } -pub fn num_syntax_ctxts() -> usize { - HygieneData::with(|data| data.syntax_context_data.len()) -} - -pub fn for_all_ctxts_in Result<(), E>>( +fn for_all_ctxts_in Result<(), E>>( ctxts: impl Iterator, mut f: F, ) -> Result<(), E> { @@ -1193,7 +1189,7 @@ pub fn for_all_ctxts_in Ok(()) } -pub fn for_all_expns_in Result<(), E>>( +fn for_all_expns_in Result<(), E>>( expns: impl Iterator, mut f: F, ) -> Result<(), E> { @@ -1206,16 +1202,6 @@ pub fn for_all_expns_in Result<(), E>>( Ok(()) } -pub fn for_all_data Result<(), E>>( - mut f: F, -) -> Result<(), E> { - let all_data = HygieneData::with(|data| data.syntax_context_data.clone()); - for (i, data) in all_data.into_iter().enumerate() { - f((i as u32, SyntaxContext(i as u32), &data))?; - } - Ok(()) -} - impl Encodable for ExpnId { default fn encode(&self, _: &mut E) -> Result<(), E::Error> { panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::()); @@ -1228,14 +1214,6 @@ impl Decodable for ExpnId { } } -pub fn for_all_expn_data Result<(), E>>(mut f: F) -> Result<(), E> { - let all_data = HygieneData::with(|data| data.expn_data.clone()); - for (i, data) in all_data.into_iter().enumerate() { - f(i as u32, &data.unwrap_or_else(|| panic!("Missing ExpnData!")))?; - } - Ok(()) -} - pub fn raw_encode_syntax_context( ctxt: SyntaxContext, context: &HygieneEncodeContext, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index d2790335b5..d30236ec3e 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -16,7 +16,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(crate_visibility_modifier)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(negative_impls)] #![feature(nll)] @@ -1037,10 +1036,6 @@ pub enum ExternalSourceKind { } impl ExternalSource { - pub fn is_absent(&self) -> bool { - !matches!(self, ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. }) - } - pub fn get_source(&self) -> Option<&Lrc> { match self { ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), @@ -1433,9 +1428,6 @@ impl SourceFile { self.src.is_none() } - pub fn byte_length(&self) -> u32 { - self.end_pos.0 - self.start_pos.0 - } pub fn count_lines(&self) -> usize { self.lines.len() } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cd3dabb679..c4007f74bd 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -382,8 +382,11 @@ symbols! { const_fn, const_fn_floating_point_arithmetic, const_fn_fn_ptr_basics, + const_fn_trait_bound, const_fn_transmute, const_fn_union, + const_fn_unsize, + const_generic_defaults, const_generics, const_generics_defaults, const_if_match, @@ -476,6 +479,7 @@ symbols! { doc_cfg, doc_keyword, doc_masked, + doc_notable_trait, doc_spotlight, doctest, document_private_items, @@ -629,6 +633,7 @@ symbols! { impl_macros, impl_trait_in_bindings, import_shadowing, + imported_main, in_band_lifetimes, include, include_bytes, @@ -666,6 +671,7 @@ symbols! { label_break_value, lang, lang_items, + large_assignments, lateout, lazy_normalization_consts, le, @@ -746,6 +752,7 @@ symbols! { more_struct_aliases, movbe_target_feature, move_ref_pattern, + move_size_limit, mul, mul_assign, mul_with_overflow, @@ -774,6 +781,7 @@ symbols! { no, no_builtins, no_core, + no_coverage, no_crate_inject, no_debug, no_default_passes, @@ -793,13 +801,13 @@ symbols! { non_modrs_mods, none_error, nontemporal_store, - nontrapping_dash_fptoint: "nontrapping-fptoint", noop_method_borrow, noop_method_clone, noop_method_deref, noreturn, nostack, not, + notable_trait, note, object_safe_for_dispatch, of, @@ -845,8 +853,7 @@ symbols! { partial_ord, passes, pat, - pat2018, - pat2021, + pat_param, path, pattern_parentheses, phantom_data, @@ -896,6 +903,8 @@ symbols! { profiler_runtime, ptr_guaranteed_eq, ptr_guaranteed_ne, + ptr_null, + ptr_null_mut, ptr_offset_from, pub_macro_rules, pub_restricted, @@ -1002,6 +1011,7 @@ symbols! { rustc_layout_scalar_valid_range_start, rustc_legacy_const_generics, rustc_macro_transparency, + rustc_main, rustc_mir, rustc_nonnull_optimization_guaranteed, rustc_object_lifetime_default, @@ -1023,6 +1033,7 @@ symbols! { rustc_regions, rustc_reservation_impl, rustc_serialize, + rustc_skip_array_during_method_dispatch, rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, @@ -1097,6 +1108,7 @@ symbols! { simd_reduce_or, simd_reduce_xor, simd_rem, + simd_round, simd_saturating_add, simd_saturating_sub, simd_scatter, @@ -1105,6 +1117,7 @@ symbols! { simd_shl, simd_shr, simd_sub, + simd_trunc, simd_xor, since, sinf32, @@ -1291,6 +1304,7 @@ symbols! { vreg, vreg_low16, warn, + wasm_abi, wasm_import_module, wasm_target_feature, while_let, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index b0d5f34090..7d186c330b 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -230,7 +230,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { let mut first = true; for p in predicates { diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 7f8cded0ac..c050bbc9b9 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -90,7 +90,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(never_type)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(in_band_lifetimes)] #![recursion_limit = "256"] @@ -198,7 +198,7 @@ fn compute_symbol_name( // // [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 if is_foreign - && (tcx.sess.target.arch != "wasm32" + && (!tcx.sess.target.is_like_wasm || !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id)) { if let Some(name) = attrs.link_name { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 12c0a14799..37a834043f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -181,7 +181,7 @@ impl SymbolMangler<'tcx> { fn in_binder( mut self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, print_value: impl FnOnce(Self, &T) -> Result, ) -> Result where @@ -318,7 +318,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i) }) => { + ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + i; @@ -483,7 +483,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { for predicate in predicates { self = self.in_binder(&predicate, |mut cx, predicate| { diff --git a/compiler/rustc_target/README.md b/compiler/rustc_target/README.md index ac1e03385d..ca72a89da5 100644 --- a/compiler/rustc_target/README.md +++ b/compiler/rustc_target/README.md @@ -1,4 +1,4 @@ -`librustc_target` contains some very low-level details that are +`rustc_target` contains some very low-level details that are specific to different compilation targets and so forth. For more information about how rustc works, see the [rustc dev guide]. diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 0deb1186b0..0cf2441d84 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -18,8 +18,7 @@ mod riscv; mod s390x; mod sparc; mod sparc64; -mod wasm32; -mod wasm32_bindgen_compat; +mod wasm; mod x86; mod x86_64; mod x86_win64; @@ -65,14 +64,17 @@ mod attr_impl { const NoCapture = 1 << 2; const NonNull = 1 << 3; const ReadOnly = 1 << 4; - const InReg = 1 << 8; + const InReg = 1 << 5; + // NoAlias on &mut arguments can only be used with LLVM >= 12 due to miscompiles + // in earlier versions. FIXME: Remove this distinction once possible. + const NoAliasMutRef = 1 << 6; } } } /// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum -/// defines if this extension should be zero-extension or sign-extension when necssary. When it is -/// not necesary to extend the argument, this enum is ignored. +/// defines if this extension should be zero-extension or sign-extension when necessary. When it is +/// not necessary to extend the argument, this enum is ignored. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ArgExtension { None, @@ -644,11 +646,14 @@ impl<'a, Ty> FnAbi<'a, Ty> { "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), - "wasm32" => match cx.target_spec().os.as_str() { - "emscripten" | "wasi" => wasm32::compute_abi_info(cx, self), - _ => wasm32_bindgen_compat::compute_abi_info(self), - }, - "asmjs" => wasm32::compute_abi_info(cx, self), + "wasm32" | "wasm64" => { + if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm { + wasm::compute_wasm_abi_info(self) + } else { + wasm::compute_c_abi_info(cx, self) + } + } + "asmjs" => wasm::compute_c_abi_info(cx, self), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), } diff --git a/compiler/rustc_target/src/abi/call/wasm32.rs b/compiler/rustc_target/src/abi/call/wasm.rs similarity index 66% rename from compiler/rustc_target/src/abi/call/wasm32.rs rename to compiler/rustc_target/src/abi/call/wasm.rs index ff2c0e9bb6..bf2c08bb16 100644 --- a/compiler/rustc_target/src/abi/call/wasm32.rs +++ b/compiler/rustc_target/src/abi/call/wasm.rs @@ -40,7 +40,8 @@ where } } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +/// The purpose of this ABI is to match the C ABI (aka clang) exactly. +pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAndLayoutMethods<'a, C> + Copy, C: LayoutOf> + HasDataLayout, @@ -56,3 +57,27 @@ where classify_arg(cx, arg); } } + +/// The purpose of this ABI is for matching the WebAssembly standard. This +/// intentionally diverges from the C ABI and is specifically crafted to take +/// advantage of LLVM's support of multiple returns in WebAssembly. +pub fn compute_wasm_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in &mut fn_abi.args { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } + + fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { + ret.extend_integer_width_to(32); + } + + fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { + arg.extend_integer_width_to(32); + } +} diff --git a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs b/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs deleted file mode 100644 index 59571fd9d4..0000000000 --- a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs +++ /dev/null @@ -1,29 +0,0 @@ -// This is not and has never been a correct C ABI for WebAssembly, but -// for a long time this was the C ABI that Rust used. wasm-bindgen -// depends on ABI details for this ABI and is incompatible with the -// correct C ABI, so this ABI is being kept around until wasm-bindgen -// can be fixed to work with the correct ABI. See #63649 for further -// discussion. - -use crate::abi::call::{ArgAbi, FnAbi}; - -fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { - ret.extend_integer_width_to(32); -} - -fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { - arg.extend_integer_width_to(32); -} - -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { - if !fn_abi.ret.is_ignore() { - classify_ret(&mut fn_abi.ret); - } - - for arg in &mut fn_abi.args { - if arg.is_ignore() { - continue; - } - classify_arg(arg); - } -} diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index b14b1ef00d..e2618da749 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1112,7 +1112,7 @@ pub enum PointerKind { /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`. Frozen, - /// `&mut T`, when we know `noalias` is safe for LLVM. + /// `&mut T` which is `noalias` but not `readonly`. UniqueBorrowed, /// `Box`, unlike `UniqueBorrowed`, it also has `noalias` on returns. diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 28000916e0..a7a708fe7d 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -68,7 +68,6 @@ fn frame_pointer_r11( _arch: InlineAsmArch, has_feature: impl FnMut(&str) -> bool, target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { if !frame_pointer_is_r7(has_feature, target) { Err("the frame pointer (r11) cannot be used as an operand for inline asm") @@ -81,7 +80,6 @@ fn frame_pointer_r7( _arch: InlineAsmArch, has_feature: impl FnMut(&str) -> bool, target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { if frame_pointer_is_r7(has_feature, target) { Err("the frame pointer (r7) cannot be used as an operand for inline asm") diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index a09c87b3ec..e2268a61a4 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -90,7 +90,7 @@ macro_rules! def_regs { match name { $( $($alias)|* | $reg_name => { - $($filter(_arch, &mut _has_feature, _target, false)?;)? + $($filter(_arch, &mut _has_feature, _target)?;)? Ok(Self::$reg) } )* @@ -114,7 +114,7 @@ macro_rules! def_regs { #[allow(unused_imports)] use super::{InlineAsmReg, InlineAsmRegClass}; $( - if $($filter(_arch, &mut _has_feature, _target, true).is_ok() &&)? true { + if $($filter(_arch, &mut _has_feature, _target).is_ok() &&)? true { if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) { set.insert(InlineAsmReg::$arch($arch_reg::$reg)); } diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index ced7483b00..185d6ac824 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -52,7 +52,6 @@ fn not_e( _arch: InlineAsmArch, mut has_feature: impl FnMut(&str) -> bool, _target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { if has_feature("e") { Err("register can't be used with the `e` target feature") diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 0f62c19e1a..90660dad4c 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -133,7 +133,6 @@ fn x86_64_only( arch: InlineAsmArch, _has_feature: impl FnMut(&str) -> bool, _target: &Target, - _allocating: bool, ) -> Result<(), &'static str> { match arch { InlineAsmArch::X86 => Err("register is only available on x86_64"), @@ -146,13 +145,9 @@ fn high_byte( arch: InlineAsmArch, _has_feature: impl FnMut(&str) -> bool, _target: &Target, - allocating: bool, ) -> Result<(), &'static str> { match arch { - InlineAsmArch::X86_64 if allocating => { - // The error message isn't actually used... - Err("high byte registers are not allocated by reg_byte") - } + InlineAsmArch::X86_64 => Err("high byte registers cannot be used as an operand on x86_64"), _ => Ok(()), } } diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index fb747dfcbd..6702538874 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -9,7 +9,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] -#![feature(const_fn)] #![feature(const_panic)] #![feature(nll)] #![feature(never_type)] @@ -28,5 +27,5 @@ pub mod spec; /// 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 librustc_middle. +/// instead of implementing everything in `rustc_middle`. pub trait HashStableContext {} diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 7de809f762..feadd4e891 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,11 +1,12 @@ -use crate::spec::{LinkerFlavor, Target, TargetOptions}; +use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); base.cpu = "apple-a12".to_string(); base.max_atomic_width = Some(128); - base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]); + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]); base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); // Clang automatically chooses a more specific target based on diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs index 1252741f97..c9cb21f1eb 100644 --- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs @@ -1,8 +1,9 @@ -use crate::spec::{Target, TargetOptions}; +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(), diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs index fa6108df20..eaf3a2dbcf 100644 --- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a // for target ABI requirements. @@ -9,6 +9,7 @@ pub fn target() -> Target { // 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, diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs index 58c72af4e7..a07cd7db88 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs @@ -1,8 +1,13 @@ -use crate::spec::{Target, TargetOptions}; +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(), diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index 17eb33b8f2..a026a623f7 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -34,6 +34,7 @@ pub enum Abi { AvrInterrupt, AvrNonBlockingInterrupt, CCmseNonSecureCall, + Wasm, // Multiplatform / generic ABIs System { unwind: bool }, @@ -83,6 +84,7 @@ const AbiDatas: &[AbiData] = &[ 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 }, @@ -131,13 +133,14 @@ impl Abi { AvrInterrupt => 18, AvrNonBlockingInterrupt => 19, CCmseNonSecureCall => 20, + Wasm => 21, // Cross-platform ABIs - System { unwind: false } => 21, - System { unwind: true } => 22, - RustIntrinsic => 23, - RustCall => 24, - PlatformIntrinsic => 25, - Unadjusted => 26, + System { unwind: false } => 22, + System { unwind: true } => 23, + RustIntrinsic => 24, + RustCall => 25, + PlatformIntrinsic => 26, + Unadjusted => 27, }; debug_assert!( AbiDatas diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index f6fbe7cd5f..aaf81648c5 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -6,13 +6,16 @@ pub fn opts() -> TargetOptions { // Many of the symbols defined in compiler-rt are also defined in libgcc. // Android's linker doesn't like that by default. base.pre_link_args - .get_mut(&LinkerFlavor::Gcc) - .unwrap() + .entry(LinkerFlavor::Gcc) + .or_default() .push("-Wl,--allow-multiple-definition".to_string()); base.dwarf_version = Some(2); base.position_independent_executables = true; base.has_elf_tls = false; - base.requires_uwtable = true; + // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867 + // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution + // was to always emit `uwtable`). + base.default_uwtable = true; base.crt_static_respected = false; base } diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 23f1357af1..6fa0b34545 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -1,6 +1,6 @@ use std::env; -use crate::spec::{LinkArgs, SplitDebuginfo, TargetOptions}; +use crate::spec::{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,10 +27,8 @@ pub fn opts(os: &str) -> TargetOptions { is_like_osx: true, dwarf_version: Some(2), has_rpath: true, - dll_prefix: "lib".to_string(), dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), - pre_link_args: LinkArgs::new(), has_elf_tls: version >= (10, 7), abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs index 9aa378a801..02a1191463 100644 --- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs @@ -12,7 +12,7 @@ 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.get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string()); Target { llvm_target: "armv7-none-linux-android".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs index ae6b8286f0..f6fe88de37 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs @@ -13,7 +13,6 @@ pub fn target() -> Target { options: TargetOptions { features: "+v7,+thumb2,+soft-float,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs index 48c16b620f..5f0f47dd39 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs @@ -14,7 +14,6 @@ pub fn target() -> Target { options: TargetOptions { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs index 9f9f1bd79b..c888fc2d4a 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs @@ -18,7 +18,6 @@ pub fn target() -> Target { options: TargetOptions { features: "+v7,+thumb2,+soft-float,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs index 59deee30ef..2432ea519a 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs @@ -17,7 +17,6 @@ pub fn target() -> Target { // target. options: TargetOptions { features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs index 660525704c..4fae3a8d0b 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs @@ -11,7 +11,6 @@ pub fn target() -> Target { options: TargetOptions { env: "eabihf".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "__mcount".to_string(), diff --git a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs index 6a43054067..9fe7098a85 100644 --- a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs @@ -10,7 +10,6 @@ pub fn target() -> Target { options: TargetOptions { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), ..base diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs index 67a7684da2..69ccce875a 100644 --- a/compiler/rustc_target/src/spec/avr_gnu_base.rs +++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs @@ -15,28 +15,12 @@ pub fn target(target_cpu: String) -> Target { exe_suffix: ".elf".to_string(), linker: Some("avr-gcc".to_owned()), - dynamic_linking: false, executables: true, linker_is_gnu: true, - has_rpath: false, - position_independent_executables: false, eh_frame_header: false, - pre_link_args: vec![( - LinkerFlavor::Gcc, - vec![ - format!("-mmcu={}", target_cpu), - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - ], - )] - .into_iter() - .collect(), + pre_link_args: vec![(LinkerFlavor::Gcc, vec![format!("-mmcu={}", target_cpu)])] + .into_iter() + .collect(), late_link_args: vec![(LinkerFlavor::Gcc, vec!["-lgcc".to_owned()])] .into_iter() .collect(), diff --git a/compiler/rustc_target/src/spec/dragonfly_base.rs b/compiler/rustc_target/src/spec/dragonfly_base.rs index b96de7ab1e..dd01709878 100644 --- a/compiler/rustc_target/src/spec/dragonfly_base.rs +++ b/compiler/rustc_target/src/spec/dragonfly_base.rs @@ -1,20 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "dragonfly".to_string(), dynamic_linking: true, @@ -22,7 +8,6 @@ pub fn opts() -> TargetOptions { os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, dwarf_version: Some(2), diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs index c70c492716..ad3383cc5f 100644 --- a/compiler/rustc_target/src/spec/freebsd_base.rs +++ b/compiler/rustc_target/src/spec/freebsd_base.rs @@ -1,20 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "freebsd".to_string(), dynamic_linking: true, @@ -22,7 +8,6 @@ pub fn opts() -> TargetOptions { os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, eliminate_frame_pointer: false, // FIXME 43575 relro_level: RelroLevel::Full, diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs index 5c39773cbe..2b925f8b94 100644 --- a/compiler/rustc_target/src/spec/fuchsia_base.rs +++ b/compiler/rustc_target/src/spec/fuchsia_base.rs @@ -23,13 +23,11 @@ pub fn opts() -> TargetOptions { os: "fuchsia".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), - lld_flavor: LldFlavor::Ld, dynamic_linking: true, executables: true, os_family: Some("unix".to_string()), is_like_fuchsia: true, linker_is_gnu: true, - has_rpath: false, pre_link_args, pre_link_objects: crt_objects::new(&[ (LinkOutputKind::DynamicNoPicExe, &["Scrt1.o"]), diff --git a/compiler/rustc_target/src/spec/haiku_base.rs b/compiler/rustc_target/src/spec/haiku_base.rs index ec87645c4f..956e4ed4bf 100644 --- a/compiler/rustc_target/src/spec/haiku_base.rs +++ b/compiler/rustc_target/src/spec/haiku_base.rs @@ -5,7 +5,6 @@ pub fn opts() -> TargetOptions { os: "haiku".to_string(), dynamic_linking: true, executables: true, - has_rpath: false, os_family: Some("unix".to_string()), relro_level: RelroLevel::Full, linker_is_gnu: true, diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs index a75158a0ea..ad013047e6 100644 --- a/compiler/rustc_target/src/spec/hermit_base.rs +++ b/compiler/rustc_target/src/spec/hermit_base.rs @@ -1,5 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy}; -use crate::spec::{RelocModel, TargetOptions, TlsModel}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -19,8 +18,6 @@ pub fn opts() -> TargetOptions { panic_strategy: PanicStrategy::Abort, position_independent_executables: true, static_position_independent_executables: true, - relocation_model: RelocModel::Pic, - os_family: None, tls_model: TlsModel::InitialExec, ..Default::default() } diff --git a/compiler/rustc_target/src/spec/hermit_kernel_base.rs b/compiler/rustc_target/src/spec/hermit_kernel_base.rs index 622f0d9a47..6d18a14d6a 100644 --- a/compiler/rustc_target/src/spec/hermit_kernel_base.rs +++ b/compiler/rustc_target/src/spec/hermit_kernel_base.rs @@ -1,5 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy}; -use crate::spec::{RelocModel, TargetOptions, TlsModel}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel}; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); @@ -20,8 +19,6 @@ pub fn opts() -> TargetOptions { panic_strategy: PanicStrategy::Abort, position_independent_executables: true, static_position_independent_executables: true, - relocation_model: RelocModel::Pic, - os_family: None, tls_model: TlsModel::InitialExec, ..Default::default() } diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs index 73d5e2057f..e0097ee220 100644 --- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, Target}; +use crate::spec::Target; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); @@ -8,15 +8,11 @@ pub fn target() -> Target { base.features = "-small-data,+hvx-length128b".to_string(); base.crt_static_default = false; - base.atomic_cas = true; base.has_rpath = true; base.linker_is_gnu = false; base.dynamic_linking = true; base.executables = true; - base.pre_link_args = LinkArgs::new(); - base.post_link_args = LinkArgs::new(); - Target { llvm_target: "hexagon-unknown-linux-musl".to_string(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs index 4979a5b3bc..7002d88c51 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. base.pre_link_args - .get_mut(&LinkerFlavor::Gcc) - .unwrap() + .entry(LinkerFlavor::Gcc) + .or_default() .push("-Wl,--large-address-aware".to_string()); Target { diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs index e7a5643eaa..74074cfb5d 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs @@ -14,10 +14,10 @@ pub fn target() -> Target { // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers "/SAFESEH".to_string(), ]; - base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); + base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); base.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .extend(pre_link_args_msvc); Target { diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs index 75c3ea6a9a..d8e37e7237 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - let pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); pre_link_args.push("-m32".to_string()); pre_link_args.push("-Wl,-znotext".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs index 9daf1d37dd..165505ee73 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs index 5fd54007ed..228976779f 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs @@ -4,8 +4,8 @@ pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-melf_i386".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-Wl,-melf_i386".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs index 716bb9e246..989e3fb1ad 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs index e53462c099..7ff7996137 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs @@ -4,8 +4,8 @@ pub fn target() -> Target { let mut base = super::openbsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-fuse-ld=lld".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-fuse-ld=lld".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs index a3de93efb7..426df59882 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. base.pre_link_args - .get_mut(&LinkerFlavor::Gcc) - .unwrap() + .entry(LinkerFlavor::Gcc) + .or_default() .push("-Wl,--large-address-aware".to_string()); Target { diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs index 2f8702d464..c7963dbde7 100644 --- a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/l4re_base.rs index 660fae5f5c..db6b74eff6 100644 --- a/compiler/rustc_target/src/spec/l4re_base.rs +++ b/compiler/rustc_target/src/spec/l4re_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions}; +use crate::spec::{LinkerFlavor, PanicStrategy, TargetOptions}; //use std::process::Command; // Use GCC to locate code for crt* libraries from the host, not from L4Re. Note @@ -13,18 +13,13 @@ use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions}; //} pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert(LinkerFlavor::Gcc, vec![]); - TargetOptions { os: "l4re".to_string(), env: "uclibc".to_string(), linker_flavor: LinkerFlavor::Ld, executables: true, - has_elf_tls: false, panic_strategy: PanicStrategy::Abort, linker: Some("ld".to_string()), - pre_link_args: args, os_family: Some("unix".to_string()), ..Default::default() } diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/linux_base.rs index 0631644ad6..eeefd056e4 100644 --- a/compiler/rustc_target/src/spec/linux_base.rs +++ b/compiler/rustc_target/src/spec/linux_base.rs @@ -1,23 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "linux".to_string(), dynamic_linking: true, @@ -25,7 +8,6 @@ pub fn opts() -> TargetOptions { os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, has_elf_tls: true, diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs index 738ff38b09..64f47b4aa9 100644 --- a/compiler/rustc_target/src/spec/linux_kernel_base.rs +++ b/compiler/rustc_target/src/spec/linux_kernel_base.rs @@ -1,14 +1,6 @@ -use crate::spec::{ - LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions, -}; +use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions}; pub fn opts() -> TargetOptions { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert( - LinkerFlavor::Gcc, - vec!["-Wl,--as-needed".to_string(), "-Wl,-z,noexecstack".to_string()], - ); - TargetOptions { env: "gnu".to_string(), disable_redzone: true, @@ -21,7 +13,6 @@ pub fn opts() -> TargetOptions { needs_plt: true, relro_level: RelroLevel::Full, relocation_model: RelocModel::Static, - pre_link_args, ..Default::default() } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c9fffd213d..2af4669344 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -37,6 +37,7 @@ use crate::abi::Endian; use crate::spec::abi::{lookup as lookup_abi, Abi}; use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_serialize::json::{Json, ToJson}; use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeMap; @@ -78,7 +79,7 @@ mod solaris_base; mod thumb_base; mod uefi_msvc_base; mod vxworks_base; -mod wasm32_base; +mod wasm_base; mod windows_gnu_base; mod windows_msvc_base; mod windows_uwp_gnu_base; @@ -511,38 +512,6 @@ impl fmt::Display for SplitDebuginfo { } } -macro_rules! supported_targets { - ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { - $(mod $module;)+ - - /// List of supported targets - pub const TARGETS: &[&str] = &[$($($triple),+),+]; - - fn load_builtin(target: &str) -> Option { - let mut t = match target { - $( $($triple)|+ => $module::target(), )+ - _ => return None, - }; - t.is_builtin = true; - debug!("got builtin target: {:?}", t); - Some(t) - } - - #[cfg(test)] - mod tests { - mod tests_impl; - - // Cannot put this into a separate file without duplication, make an exception. - $( - #[test] // `#[test]` - fn $module() { - tests_impl::test_target(super::$module::target()); - } - )+ - } - }; -} - #[derive(Clone, Debug, PartialEq, Eq)] pub enum StackProbeType { /// Don't emit any stack probes. @@ -620,6 +589,117 @@ impl ToJson for StackProbeType { } } +bitflags::bitflags! { + #[derive(Default, Encodable, Decodable)] + pub struct SanitizerSet: u8 { + const ADDRESS = 1 << 0; + const LEAK = 1 << 1; + const MEMORY = 1 << 2; + const THREAD = 1 << 3; + const HWADDRESS = 1 << 4; + } +} + +impl SanitizerSet { + /// Return sanitizer's name + /// + /// Returns none if the flags is a set of sanitizers numbering not exactly one. + fn as_str(self) -> Option<&'static str> { + Some(match self { + SanitizerSet::ADDRESS => "address", + SanitizerSet::LEAK => "leak", + SanitizerSet::MEMORY => "memory", + SanitizerSet::THREAD => "thread", + SanitizerSet::HWADDRESS => "hwaddress", + _ => return None, + }) + } +} + +/// Formats a sanitizer set as a comma separated list of sanitizers' names. +impl fmt::Display for SanitizerSet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut first = true; + for s in *self { + let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {:?}", s)); + if !first { + f.write_str(", ")?; + } + f.write_str(name)?; + first = false; + } + Ok(()) + } +} + +impl IntoIterator for SanitizerSet { + type Item = SanitizerSet; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + [ + SanitizerSet::ADDRESS, + SanitizerSet::LEAK, + SanitizerSet::MEMORY, + SanitizerSet::THREAD, + SanitizerSet::HWADDRESS, + ] + .iter() + .copied() + .filter(|&s| self.contains(s)) + .collect::>() + .into_iter() + } +} + +impl HashStable for SanitizerSet { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.bits().hash_stable(ctx, hasher); + } +} + +impl ToJson for SanitizerSet { + fn to_json(&self) -> Json { + self.into_iter() + .map(|v| Some(v.as_str()?.to_json())) + .collect::>>() + .unwrap_or(Vec::new()) + .to_json() + } +} + +macro_rules! supported_targets { + ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { + $(mod $module;)+ + + /// List of supported targets + pub const TARGETS: &[&str] = &[$($($triple),+),+]; + + fn load_builtin(target: &str) -> Option { + let mut t = match target { + $( $($triple)|+ => $module::target(), )+ + _ => return None, + }; + t.is_builtin = true; + debug!("got builtin target: {:?}", t); + Some(t) + } + + #[cfg(test)] + mod tests { + mod tests_impl; + + // Cannot put this into a separate file without duplication, make an exception. + $( + #[test] // `#[test]` + fn $module() { + tests_impl::test_target(super::$module::target()); + } + )+ + } + }; +} + supported_targets! { ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu), ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32), @@ -762,6 +842,7 @@ supported_targets! { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), + ("wasm64-unknown-unknown", wasm64_unknown_unknown), ("thumbv6m-none-eabi", thumbv6m_none_eabi), ("thumbv7m-none-eabi", thumbv7m_none_eabi), @@ -996,6 +1077,8 @@ pub struct TargetOptions { pub is_like_emscripten: bool, /// Whether the target toolchain is like Fuchsia's. pub is_like_fuchsia: bool, + /// Whether a target toolchain is like WASM. + pub is_like_wasm: bool, /// Version of DWARF to use if not using the default. /// Useful because some platforms (osx, bsd) only want up to DWARF2. pub dwarf_version: Option, @@ -1111,6 +1194,10 @@ pub struct TargetOptions { /// unwinders. pub requires_uwtable: bool, + /// Whether or not to emit `uwtable` attributes on functions if `-C force-unwind-tables` + /// is not specified and `uwtable` is not required on this target. + pub default_uwtable: bool, + /// Whether or not SIMD types are passed by reference in the Rust ABI, /// typically required if a target can be compiled with a mixed set of /// target features. This is `true` by default, and `false` for targets like @@ -1160,6 +1247,16 @@ pub struct TargetOptions { /// How to handle split debug information, if at all. Specifying `None` has /// target-specific meaning. pub split_debuginfo: SplitDebuginfo, + + /// The sanitizers supported by this target + /// + /// Note that the support here is at a codegen level. If the machine code with sanitizer + /// enabled can generated on this target, but the necessary supporting libraries are not + /// distributed with the target, the sanitizer should still appear in this list for the target. + pub supported_sanitizers: SanitizerSet, + + /// If present it's a default value to use for adjusting the C ABI. + pub default_adjusted_cabi: Option, } impl Default for TargetOptions { @@ -1204,6 +1301,7 @@ impl Default for TargetOptions { is_like_emscripten: false, is_like_msvc: false, is_like_fuchsia: false, + is_like_wasm: false, dwarf_version: None, linker_is_gnu: false, allows_weak_linkage: true, @@ -1248,6 +1346,7 @@ impl Default for TargetOptions { default_hidden_visibility: false, emit_debug_gdb_scripts: true, requires_uwtable: false, + default_uwtable: false, simd_types_indirect: true, limit_rdylib_exports: true, override_export_symbols: None, @@ -1260,6 +1359,8 @@ impl Default for TargetOptions { eh_frame_header: true, has_thumb_interworking: false, split_debuginfo: SplitDebuginfo::Off, + supported_sanitizers: SanitizerSet::empty(), + default_adjusted_cabi: None, } } } @@ -1311,6 +1412,9 @@ impl Target { Abi::C { unwind: false } } } + + Abi::C { unwind } => self.default_adjusted_cabi.unwrap_or(Abi::C { unwind }), + abi => abi, } } @@ -1342,8 +1446,8 @@ impl Target { let get_req_field = |name: &str| { obj.find(name) - .map(|s| s.as_string()) - .and_then(|os| os.map(|s| s.to_string())) + .and_then(Json::as_string) + .map(str::to_string) .ok_or_else(|| format!("Field {} in target specification is required", name)) }; @@ -1546,6 +1650,24 @@ impl Target { )), }).unwrap_or(Ok(())) } ); + ($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))), + }; + } + Some(Ok(())) + }).unwrap_or(Ok(())) + } ); + ($key_name:ident, crt_objects_fallback) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { @@ -1627,6 +1749,16 @@ impl Target { } } } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&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))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); } if let Some(s) = obj.find("target-endian").and_then(Json::as_string) { @@ -1678,6 +1810,7 @@ impl Target { key!(is_like_msvc, bool); key!(is_like_emscripten, bool); key!(is_like_fuchsia, bool); + key!(is_like_wasm, bool); key!(dwarf_version, Option); key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); @@ -1711,6 +1844,7 @@ impl Target { key!(default_hidden_visibility, bool); key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); + key!(default_uwtable, bool); key!(simd_types_indirect, bool); key!(limit_rdylib_exports, bool); key!(override_export_symbols, opt_list); @@ -1723,6 +1857,8 @@ impl Target { key!(eh_frame_header, bool); key!(has_thumb_interworking, bool); key!(split_debuginfo, SplitDebuginfo)?; + key!(supported_sanitizers, SanitizerSet)?; + key!(default_adjusted_cabi, Option)?; // NB: The old name is deprecated, but support for it is retained for // compatibility. @@ -1914,6 +2050,7 @@ impl ToJson for Target { target_option_val!(is_like_msvc); target_option_val!(is_like_emscripten); target_option_val!(is_like_fuchsia); + target_option_val!(is_like_wasm); target_option_val!(dwarf_version); target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); @@ -1947,6 +2084,7 @@ impl ToJson for Target { target_option_val!(default_hidden_visibility); target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); + target_option_val!(default_uwtable); target_option_val!(simd_types_indirect); target_option_val!(limit_rdylib_exports); target_option_val!(override_export_symbols); @@ -1959,6 +2097,11 @@ impl ToJson for Target { target_option_val!(eh_frame_header); target_option_val!(has_thumb_interworking); target_option_val!(split_debuginfo); + target_option_val!(supported_sanitizers); + + if let Some(abi) = self.default_adjusted_cabi { + d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); + } if default.unsupported_abis != self.unsupported_abis { d.insert( diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/msvc_base.rs index 39c0d5f0bb..4ed7685ca0 100644 --- a/compiler/rustc_target/src/spec/msvc_base.rs +++ b/compiler/rustc_target/src/spec/msvc_base.rs @@ -5,13 +5,6 @@ pub fn opts() -> TargetOptions { // Suppress the verbose logo and authorship debugging output, which would needlessly // clog any log files. "/NOLOGO".to_string(), - // Tell the compiler that non-code sections can be marked as non-executable, - // including stack pages. - // UEFI is fully compatible to non-executable data pages. - // In fact, firmware might enforce this, so we better let the linker know about this, - // so it will fail if the compiler ever tries placing code on the stack - // (e.g., trampoline constructs and alike). - "/NXCOMPAT".to_string(), ]; let mut pre_link_args = LinkArgs::new(); pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone()); diff --git a/compiler/rustc_target/src/spec/netbsd_base.rs b/compiler/rustc_target/src/spec/netbsd_base.rs index a77d60bd9d..680cd60788 100644 --- a/compiler/rustc_target/src/spec/netbsd_base.rs +++ b/compiler/rustc_target/src/spec/netbsd_base.rs @@ -1,18 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - ], - ); - TargetOptions { os: "netbsd".to_string(), dynamic_linking: true, @@ -21,7 +9,6 @@ pub fn opts() -> TargetOptions { linker_is_gnu: true, no_default_libraries: false, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, use_ctors_section: true, diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/openbsd_base.rs index 2b40a1ed94..a6fd01ab11 100644 --- a/compiler/rustc_target/src/spec/openbsd_base.rs +++ b/compiler/rustc_target/src/spec/openbsd_base.rs @@ -1,20 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "openbsd".to_string(), dynamic_linking: true, @@ -23,7 +9,6 @@ pub fn opts() -> TargetOptions { linker_is_gnu: true, has_rpath: true, abi_return_struct_as_int: true, - pre_link_args: args, position_independent_executables: true, eliminate_frame_pointer: false, // FIXME 43575 relro_level: RelroLevel::Full, diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs index 3dddeb1129..b3d6b7c610 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs index 9db880b0e5..559a1a4086 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); // ld.so in at least RHEL6 on ppc64 has a bug related to BIND_NOW, so only enable partial RELRO diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs index 8767f86b00..f1190b159a 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs index 2f28a85624..3ebc5469e0 100644 --- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs index 4cbd997650..76f70e474f 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "ppc64le".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs index efdc9ad751..42c49103b3 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "ppc64le".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs index 70dd0b2aee..21ffdd2d16 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs index 66118b7495..8d8f746f97 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".to_string()); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs index 679a3a2f6a..9633705db6 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs index 1245098329..4cc5224fae 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::netbsd_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs index bb943a8825..2f0a6ca44a 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs @@ -3,8 +3,8 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::vxworks_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("--secure-plt".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".to_string()); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs index 4b4f118ba4..215f1a3622 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs @@ -3,8 +3,8 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::vxworks_base::opts(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string()); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("--secure-plt".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".to_string()); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/redox_base.rs b/compiler/rustc_target/src/spec/redox_base.rs index 5ef705878a..0afb4a72ac 100644 --- a/compiler/rustc_target/src/spec/redox_base.rs +++ b/compiler/rustc_target/src/spec/redox_base.rs @@ -1,23 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions}; +use crate::spec::{RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], - ); - TargetOptions { os: "redox".to_string(), env: "relibc".to_string(), @@ -26,7 +9,6 @@ pub fn opts() -> TargetOptions { os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, has_elf_tls: true, diff --git a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs index a31a08a8cf..88a22f25ff 100644 --- a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs @@ -14,7 +14,6 @@ pub fn target() -> Target { cpu: "generic-rv32".to_string(), max_atomic_width: Some(0), atomic_cas: false, - features: String::new(), executables: true, panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs index 2ee53fdc40..b406eec1e7 100644 --- a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs @@ -13,7 +13,6 @@ pub fn target() -> Target { linker: Some("rust-lld".to_string()), cpu: "generic-rv32".to_string(), max_atomic_width: Some(32), - atomic_cas: true, features: "+m,+a,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs index aa823b13fd..481bce05a0 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs @@ -14,7 +14,6 @@ pub fn target() -> Target { llvm_abiname: "lp64d".to_string(), cpu: "generic-rv64".to_string(), max_atomic_width: Some(64), - atomic_cas: true, features: "+m,+a,+f,+d,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs index 908367ee20..3e4afd446d 100644 --- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs @@ -13,7 +13,6 @@ pub fn target() -> Target { linker: Some("rust-lld".to_string()), cpu: "generic-rv64".to_string(), max_atomic_width: Some(64), - atomic_cas: true, features: "+m,+a,+c".to_string(), executables: true, panic_strategy: PanicStrategy::Abort, diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs index 7d685c8310..b4286dfd88 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs @@ -4,7 +4,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "v9".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs index 63b13fad4f..9732983161 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs @@ -5,7 +5,7 @@ pub fn target() -> Target { let mut base = super::openbsd_base::opts(); base.endian = Endian::Big; base.cpu = "v9".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs index 9e8fbff81c..1fd4cadfff 100644 --- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs @@ -6,7 +6,7 @@ pub fn target() -> Target { base.endian = Endian::Big; base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mv8plus".to_string()); Target { llvm_target: "sparc-unknown-linux-gnu".to_string(), diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 9ec8467e0a..f4de8bc0a5 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -50,6 +50,7 @@ impl Target { // and you certainly want "unknown" for the OS name. fn can_use_os_unknown(&self) -> bool { self.llvm_target == "wasm32-unknown-unknown" + || self.llvm_target == "wasm64-unknown-unknown" || (self.env == "sgx" && self.vendor == "fortanix") } } diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs index d87c06d49c..ef58824f38 100644 --- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs @@ -45,9 +45,6 @@ pub fn target() -> Target { main_needs_argc_argv: false, - // No thread-local storage (just use a static Cell) - has_elf_tls: false, - // don't have atomic compare-and-swap atomic_cas: false, has_thumb_interworking: true, diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs index 8131a6e2ea..1232daa577 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs @@ -11,10 +11,10 @@ pub fn target() -> Target { // where necessary, but this is not the observed behavior. // Disabling the LBR optimization works around the issue. let pre_link_args_msvc = "/OPT:NOLBR".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push(pre_link_args_msvc.clone()); + base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().push(pre_link_args_msvc.clone()); base.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .push(pre_link_args_msvc); // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is @@ -29,7 +29,6 @@ pub fn target() -> Target { options: TargetOptions { features: "+vfp3,+neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), ..base diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs index a2c1b6bb90..e6a59f015c 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs @@ -16,7 +16,6 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { features: "+vfp3,+neon".to_string(), - cpu: "generic".to_string(), unsupported_abis: super::arm_base::unsupported_abis(), ..base }, diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs index 41fdbc2f0a..58b0a9d220 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs @@ -12,7 +12,7 @@ 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.get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string()); Target { llvm_target: "armv7-none-linux-android".to_string(), diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs index 352d246874..12d816d095 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs @@ -17,7 +17,6 @@ pub fn target() -> Target { options: TargetOptions { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), ..base diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs index a788167aed..020de87147 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs @@ -21,7 +21,6 @@ pub fn target() -> Target { // target. options: TargetOptions { features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), - cpu: "generic".to_string(), max_atomic_width: Some(64), unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs index b9ff16bd19..6b6b601860 100644 --- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs +++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs @@ -30,10 +30,10 @@ pub fn opts() -> TargetOptions { // exit (default for applications). "/subsystem:efi_application".to_string(), ]; - base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); + base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); base.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .extend(pre_link_args_msvc); TargetOptions { diff --git a/compiler/rustc_target/src/spec/vxworks_base.rs b/compiler/rustc_target/src/spec/vxworks_base.rs index 70bc9ce3e0..41c4d7625a 100644 --- a/compiler/rustc_target/src/spec/vxworks_base.rs +++ b/compiler/rustc_target/src/spec/vxworks_base.rs @@ -1,21 +1,6 @@ -use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - ], - ); - TargetOptions { os: "vxworks".to_string(), env: "gnu".to_string(), @@ -27,8 +12,6 @@ pub fn opts() -> TargetOptions { os_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: args, - position_independent_executables: false, has_elf_tls: true, crt_static_default: true, crt_static_respected: true, diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index 9f69ce16c2..e028dbaa32 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -1,10 +1,10 @@ -use super::wasm32_base; +use super::wasm_base; use super::{LinkArgs, LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { - let mut options = wasm32_base::options(); + let mut options = wasm_base::options(); - let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); // Rust really needs a way for users to specify exports and imports in // the source code. --export-dynamic isn't the right tool for this job, diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 5e89ba2520..834c4dbfc0 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -10,14 +10,26 @@ //! This target is more or less managed by the Rust and WebAssembly Working //! Group nowadays at . -use super::wasm32_base; +use super::wasm_base; use super::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::abi::Abi; pub fn target() -> Target { - let mut options = wasm32_base::options(); + let mut options = wasm_base::options(); options.os = "unknown".to_string(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); - let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + + // This is a default for backwards-compatibility with the original + // definition of this target oh-so-long-ago. Once the "wasm" ABI is + // stable and the wasm-bindgen project has switched to using it then there's + // no need for this and it can be removed. + // + // Currently this is the reason that this target's ABI is mismatched with + // clang's ABI. This means that, in the limit, you can't merge C and Rust + // code on this target due to this ABI mismatch. + options.default_adjusted_cabi = Some(Abi::Wasm); + + let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); // Make sure clang uses LLD as its linker and is configured appropriately // otherwise @@ -35,7 +47,7 @@ pub fn target() -> Target { clang_args.push("-Wl,--export-dynamic".to_string()); // Add the flags to wasm-ld's args too. - let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap(); + let lld_args = options.pre_link_args.entry(LinkerFlavor::Lld(LldFlavor::Wasm)).or_default(); lld_args.push("--no-entry".to_string()); lld_args.push("--export-dynamic".to_string()); diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 3f44acdc36..a6b12d2ee8 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -72,11 +72,11 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::wasm32_base; +use super::wasm_base; use super::{crt_objects, LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { - let mut options = wasm32_base::options(); + let mut options = wasm_base::options(); options.os = "wasi".to_string(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs new file mode 100644 index 0000000000..8bfb229d77 --- /dev/null +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -0,0 +1,39 @@ +//! A "bare wasm" target representing a WebAssembly output that makes zero +//! assumptions about its environment. +//! +//! The `wasm64-unknown-unknown` target is intended to encapsulate use cases +//! that do not rely on any imported functionality. The binaries generated are +//! entirely self-contained by default when using the standard library. Although +//! the standard library is available, most of it returns an error immediately +//! (e.g. trying to create a TCP stream or something like that). + +use super::wasm_base; +use super::{LinkerFlavor, LldFlavor, Target}; + +pub fn target() -> Target { + let mut options = wasm_base::options(); + options.os = "unknown".to_string(); + options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); + let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + + // Make sure clang uses LLD as its linker and is configured appropriately + // otherwise + clang_args.push("--target=wasm64-unknown-unknown".to_string()); + + // For now this target just never has an entry symbol no matter the output + // type, so unconditionally pass this. + clang_args.push("-Wl,--no-entry".to_string()); + options + .pre_link_args + .get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)) + .unwrap() + .push("--no-entry".to_string()); + + Target { + llvm_target: "wasm64-unknown-unknown".to_string(), + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128".to_string(), + arch: "wasm64".to_string(), + options, + } +} diff --git a/compiler/rustc_target/src/spec/wasm32_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs similarity index 99% rename from compiler/rustc_target/src/spec/wasm32_base.rs rename to compiler/rustc_target/src/spec/wasm_base.rs index bfef3d3722..b208eb92f8 100644 --- a/compiler/rustc_target/src/spec/wasm32_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -60,6 +60,8 @@ pub fn options() -> TargetOptions { pre_link_args.insert(LinkerFlavor::Gcc, clang_args); TargetOptions { + is_like_wasm: true, + // we allow dynamic linking, but only cdylibs. Basically we allow a // final library artifact that exports some symbols (a wasm module) but // we don't allow intermediate `dylib` crate types @@ -73,7 +75,6 @@ pub fn options() -> TargetOptions { exe_suffix: ".wasm".to_string(), dll_prefix: String::new(), dll_suffix: ".wasm".to_string(), - linker_is_gnu: false, eh_frame_header: false, max_atomic_width: Some(64), diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs index f556a13a51..478c567a93 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs @@ -9,8 +9,6 @@ pub fn opts() -> TargetOptions { // Tell GCC to avoid linker plugins, because we are not bundling // them with Windows installer, and Rust does its own LTO anyways. "-fno-use-linker-plugin".to_string(), - // Always enable DEP (NX bit) when it is available - "-Wl,--nxcompat".to_string(), // Enable ASLR "-Wl,--dynamicbase".to_string(), // ASLR will rebase it anyway so leaving that option enabled only leads to confusion @@ -73,8 +71,6 @@ pub fn opts() -> TargetOptions { dll_prefix: String::new(), dll_suffix: ".dll".to_string(), exe_suffix: ".exe".to_string(), - staticlib_prefix: "lib".to_string(), - staticlib_suffix: ".a".to_string(), os_family: Some("windows".to_string()), is_like_windows: true, allows_weak_linkage: false, diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs index 700ee5ec64..b3fa5c22f9 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs +++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs @@ -5,10 +5,10 @@ pub fn opts() -> TargetOptions { opts.vendor = "uwp".to_string(); let pre_link_args_msvc = vec!["/APPCONTAINER".to_string(), "mincore.lib".to_string()]; - opts.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); + opts.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); opts.pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) - .unwrap() + .entry(LinkerFlavor::Lld(LldFlavor::Link)) + .or_default() .extend(pre_link_args_msvc); opts diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index 570cf7974f..dc7597fe7b 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); @@ -12,6 +12,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.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs index 74fb6f0a83..90705c526f 100644 --- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs @@ -1,12 +1,9 @@ use std::iter; -use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions}; +use super::{LinkerFlavor, LldFlavor, Target, TargetOptions}; pub fn target() -> Target { const PRE_LINK_ARGS: &[&str] = &[ - "--as-needed", - "-z", - "noexecstack", "-e", "elf_entry", "-Bstatic", @@ -59,12 +56,10 @@ pub fn target() -> Target { env: "sgx".into(), vendor: "fortanix".into(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), - dynamic_linking: false, executables: true, linker_is_gnu: true, linker: Some("rust-lld".to_owned()), max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Unwind, cpu: "x86-64".into(), features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(), llvm_args: vec!["--x86-experimental-lvi-inline-asm-hardening".into()], diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs index 7774308b4c..aa65ebe1f9 100644 --- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs @@ -1,4 +1,4 @@ -use crate::spec::{StackProbeType, Target}; +use crate::spec::{SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::fuchsia_base::opts(); @@ -6,6 +6,7 @@ pub fn target() -> Target { base.max_atomic_width = Some(64); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; + base.supported_sanitizers = SanitizerSet::ADDRESS; Target { llvm_target: "x86_64-fuchsia".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs index 19bf27c457..9065283b73 100644 --- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs @@ -6,7 +6,7 @@ pub fn target() -> Target { // https://developer.android.com/ndk/guides/abis.html#86-64 base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs index 36726ab4ae..26a81a484b 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); base.cpu = "x86-64".to_string(); - let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); gcc_pre_link_args.push("-m64".to_string()); // Use high-entropy 64 bit address space for ASLR gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string()); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs index d551ce6d37..d69830f0a3 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::dragonfly_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs index e51f6c1a75..b5fc15f5e0 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs @@ -1,12 +1,13 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-freebsd".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs index 04499bc5bb..085079e06e 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs @@ -1,12 +1,14 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-linux-gnu".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs index 5bf9a19575..7b77ad668c 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string()); + 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 base.stack_probes = StackProbeType::Call; base.has_elf_tls = false; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs index 658dc977c1..5ad243aa40 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs @@ -1,13 +1,15 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.static_position_independent_executables = true; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "x86_64-unknown-linux-musl".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs index 4718ad2be4..0269c7afe5 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs index 68d80205e1..fa6f255d4d 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float" .to_string(); base.code_model = Some(CodeModel::Kernel); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); Target { // FIXME: Some dispute, the linux-on-clang folks think this should use diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs index 2c5ac43f24..4eb3f34a03 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::openbsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs index b5aa37d032..b8269ecae2 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::redox_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs index 57913ba0da..a5425e1c12 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs @@ -3,7 +3,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); base.cpu = "x86-64".to_string(); - let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); gcc_pre_link_args.push("-m64".to_string()); // Use high-entropy 64 bit address space for ASLR gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string()); diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs index 6c59817259..f9f775084f 100644 --- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; base.disable_redzone = true; diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index aea3d8eef6..4097e1577e 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -15,9 +15,10 @@ #![feature(box_patterns)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(crate_visibility_modifier)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(control_flow_enum)] #![recursion_limit = "512"] // For rustdoc diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index d6a585e626..fb4a8ce687 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -697,7 +697,7 @@ where { fn visit_binder>( &mut self, - t: &ty::Binder, + t: &ty::Binder<'tcx, T>, ) -> ControlFlow { t.as_ref().skip_binder().visit_with(self); ControlFlow::CONTINUE @@ -1171,7 +1171,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // This also instantiates nested instances of `impl Trait`. let predicate = self.instantiate_opaque_types_in_map(predicate); - let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation); + let cause = traits::ObligationCause::new(span, self.body_id, traits::OpaqueType); // Require that the predicate holds for the concrete type. debug!("instantiate_opaque_types: predicate={:?}", predicate); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 6510c9464e..f54eb0914a 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -12,6 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry; use std::collections::VecDeque; +use std::iter; // FIXME(twk): this is obviously not nice to duplicate like that #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)] @@ -83,7 +84,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) }; - let trait_pred = ty::Binder::bind(trait_ref); + let trait_pred = ty::Binder::dummy(trait_ref); let bail_out = tcx.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::with_negative(&infcx, true); @@ -279,7 +280,7 @@ impl AutoTraitFinder<'tcx> { let mut already_visited = FxHashSet::default(); let mut predicates = VecDeque::new(); - predicates.push_back(ty::Binder::bind(ty::TraitPredicate { + predicates.push_back(ty::Binder::dummy(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: trait_did, substs: infcx.tcx.mk_substs_trait(ty, &[]), @@ -428,7 +429,9 @@ impl AutoTraitFinder<'tcx> { return true; } - for (new_region, old_region) in new_substs.regions().zip(old_substs.regions()) { + for (new_region, old_region) in + iter::zip(new_substs.regions(), old_substs.regions()) + { match (new_region, old_region) { // If both predicates have an `ReLateBound` (a HRTB) in the // same spot, we do nothing. @@ -803,12 +806,10 @@ impl AutoTraitFinder<'tcx> { } ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: &'tcx ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { match select.infcx().const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) { Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty)), diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e8ae1f44a3..9bb4af16a8 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -74,23 +74,22 @@ where let impl2_ref = tcx.impl_trait_ref(impl2_def_id); // Check if any of the input types definitely do not unify. - if impl1_ref - .iter() - .flat_map(|tref| tref.substs.types()) - .zip(impl2_ref.iter().flat_map(|tref| tref.substs.types())) - .any(|(ty1, ty2)| { - let t1 = fast_reject::simplify_type(tcx, ty1, false); - let t2 = fast_reject::simplify_type(tcx, ty2, false); - if let (Some(t1), Some(t2)) = (t1, t2) { - // Simplified successfully - // Types cannot unify if they differ in their reference mutability or simplify to different types - t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability() - } else { - // Types might unify - false - } - }) - { + if iter::zip( + impl1_ref.iter().flat_map(|tref| tref.substs.types()), + impl2_ref.iter().flat_map(|tref| tref.substs.types()), + ) + .any(|(ty1, ty2)| { + let t1 = fast_reject::simplify_type(tcx, ty1, false); + let t2 = fast_reject::simplify_type(tcx, ty2, false); + if let (Some(t1), Some(t2)) = (t1, t2) { + // Simplified successfully + // Types cannot unify if they differ in their reference mutability or simplify to different types + t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability() + } else { + // Types might unify + false + } + }) { // Some types involved are definitely different, so the impls couldn't possibly overlap. debug!("overlapping_impls: fast_reject early-exit"); return no_overlap(); @@ -587,6 +586,11 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { false } + ty::Closure(..) => { + // Similar to the `Opaque` case (#83613). + false + } + ty::Dynamic(ref tt, ..) => { if let Some(principal) = tt.principal() { def_id_is_local(principal.def_id(), in_crate) @@ -597,7 +601,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { ty::Error(_) => true, - ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { + ty::Generator(..) | ty::GeneratorWitness(..) => { bug!("ty_is_local invoked on unexpected type: {:?}", ty) } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 670527fb3f..8961cdaebf 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -13,7 +13,7 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; -use rustc_middle::mir::abstract_const::{Node, NodeId}; +use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::subst::{Subst, SubstsRef}; @@ -23,6 +23,7 @@ use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; use std::cmp; +use std::iter; use std::ops::ControlFlow; /// Check if a given constant can be evaluated. @@ -32,7 +33,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( substs: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, -) -> Result<(), ErrorHandled> { +) -> Result<(), NotConstEvaluatable> { debug!("is_const_evaluatable({:?}, {:?})", def, substs); if infcx.tcx.features().const_evaluatable_checked { let tcx = infcx.tcx; @@ -103,29 +104,10 @@ pub fn is_const_evaluatable<'cx, 'tcx>( match failure_kind { FailureKind::MentionsInfer => { - return Err(ErrorHandled::TooGeneric); + return Err(NotConstEvaluatable::MentionsInfer); } FailureKind::MentionsParam => { - // FIXME(const_evaluatable_checked): Better error message. - let mut err = - infcx.tcx.sess.struct_span_err(span, "unconstrained generic constant"); - let const_span = tcx.def_span(def.did); - // FIXME(const_evaluatable_checked): Update this suggestion once - // explicit const evaluatable bounds are implemented. - if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(const_span) - { - err.span_help( - tcx.def_span(def.did), - &format!("try adding a `where` bound using this expression: `where [u8; {}]: Sized`", snippet), - ); - } else { - err.span_help( - const_span, - "consider adding a `where` bound for this expression", - ); - } - err.emit(); - return Err(ErrorHandled::Reported(ErrorReported)); + return Err(NotConstEvaluatable::MentionsParam); } FailureKind::Concrete => { // Dealt with below by the same code which handles this @@ -163,7 +145,11 @@ pub fn is_const_evaluatable<'cx, 'tcx>( // and hopefully soon change this to an error. // // See #74595 for more details about this. - let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span)); + let concrete = infcx.const_eval_resolve( + param_env, + ty::Unevaluated { def, substs, promoted: None }, + Some(span), + ); if concrete.is_ok() && substs.has_param_types_or_consts() { match infcx.tcx.def_kind(def.did) { @@ -180,34 +166,16 @@ pub fn is_const_evaluatable<'cx, 'tcx>( debug!(?concrete, "is_const_evaluatable"); match concrete { - Err(ErrorHandled::TooGeneric) if !substs.has_infer_types_or_consts() => { - // FIXME(const_evaluatable_checked): We really should move - // emitting this error message to fulfill instead. For - // now this is easier. - // - // This is not a problem without `const_evaluatable_checked` as - // all `ConstEvaluatable` predicates have to be fulfilled for compilation - // to succeed. - // - // @lcnr: We already emit an error for things like - // `fn test() -> [0 - N]` eagerly here, - // so until we fix this I don't really care. - - let mut err = infcx - .tcx - .sess - .struct_span_err(span, "constant expression depends on a generic parameter"); - // FIXME(const_generics): we should suggest to the user how they can resolve this - // issue. However, this is currently not actually possible - // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). - // - // Note that with `feature(const_evaluatable_checked)` this case should not - // be reachable. - err.note("this may fail depending on what value the parameter takes"); - err.emit(); - Err(ErrorHandled::Reported(ErrorReported)) + Err(ErrorHandled::TooGeneric) => Err(match substs.has_infer_types_or_consts() { + true => NotConstEvaluatable::MentionsInfer, + false => NotConstEvaluatable::MentionsParam, + }), + Err(ErrorHandled::Linted) => { + infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); + Err(NotConstEvaluatable::Error(ErrorReported)) } - c => c.map(drop), + Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), + Ok(_) => Ok(()), } } @@ -239,7 +207,9 @@ impl AbstractConst<'tcx> { ct: &ty::Const<'tcx>, ) -> Result>, ErrorReported> { match ct.val { - ty::ConstKind::Unevaluated(def, substs, None) => AbstractConst::new(tcx, def, substs), + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => { + AbstractConst::new(tcx, def, substs) + } ty::ConstKind::Error(_) => Err(ErrorReported), _ => Ok(None), } @@ -532,22 +502,25 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { if let Some(next) = self.build_terminator(block.terminator())? { block = &self.body.basic_blocks()[next]; } else { - assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); + break; + } + } + + assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); + for n in self.nodes.iter() { + if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node { // `AbstractConst`s should not contain any promoteds as they require references which // are not allowed. - assert!(!self.nodes.iter().any(|n| matches!( - n.node, - Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(_, _, Some(_)), ty: _ }) - ))); - - self.nodes[self.locals[mir::RETURN_PLACE]].used = true; - if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { - self.error(Some(unused.span), "dead code")?; - } - - return Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))); + assert_eq!(ct.promoted, None); } } + + self.nodes[self.locals[mir::RETURN_PLACE]].used = true; + if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { + self.error(Some(unused.span), "dead code")?; + } + + Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))) } } @@ -673,10 +646,16 @@ pub(super) fn try_unify<'tcx>( // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This // means that we only allow inference variables if they are equal. (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val, - ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) => a_def == b_def && a_substs == b_substs, + // We expand generic anonymous constants at the start of this function, so this + // branch should only be taking when dealing with associated constants, at + // which point directly comparing them seems like the desired behavior. + // + // FIXME(const_evaluatable_checked): This isn't actually the case. + // We also take this branch for concrete anonymous constants and + // expand generic anonymous constants with concrete substs. + (ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => { + a_uv == b_uv + } // FIXME(const_evaluatable_checked): We may want to either actually try // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like // this, for now we just return false here. @@ -694,9 +673,7 @@ pub(super) fn try_unify<'tcx>( if a_args.len() == b_args.len() => { try_unify(tcx, a.subtree(a_f), b.subtree(b_f)) - && a_args - .iter() - .zip(b_args) + && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } _ => false, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index a3faf4cb7d..da5a1af7f7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2,10 +2,10 @@ pub mod on_unimplemented; pub mod suggestions; use super::{ - ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, - OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, + EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, + OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation, + SelectionContext, SelectionError, TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; @@ -17,7 +17,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; -use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ @@ -28,6 +28,7 @@ use rustc_session::DiagnosticMessageId; use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; use std::fmt; +use std::iter; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::AtExt as _; @@ -161,7 +162,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } - for (error, suppressed) in errors.iter().zip(is_suppressed) { + for (error, suppressed) in iter::zip(errors, is_suppressed) { if !suppressed { self.report_fulfillment_error(error, body_id, fallback_has_occurred); } @@ -502,14 +503,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let unit_obligation = obligation.with(predicate.without_const().to_predicate(tcx)); if self.predicate_may_hold(&unit_obligation) { + err.note("this trait is implemented for `()`."); err.note( - "the trait is implemented for `()`. \ - Possibly this error has been caused by changes to \ - Rust's type-inference algorithm (see issue #48950 \ - \ - for more information). Consider whether you meant to use \ - the type `()` here instead.", + "this error might have been caused by changes to \ + Rust's type-inference algorithm (see issue #48950 \ + \ + for more information).", ); + err.help("did you intend to use the type `()` here instead?"); } } @@ -738,24 +739,59 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) } - ConstEvalFailure(ErrorHandled::TooGeneric) => { - bug!("too generic should have been handled in `is_const_evaluatable`"); + + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { + bug!( + "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`" + ) + } + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { + if !self.tcx.features().const_evaluatable_checked { + let mut err = self.tcx.sess.struct_span_err( + span, + "constant expression depends on a generic parameter", + ); + // FIXME(const_generics): we should suggest to the user how they can resolve this + // issue. However, this is currently not actually possible + // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). + // + // Note that with `feature(const_evaluatable_checked)` this case should not + // be reachable. + err.note("this may fail depending on what value the parameter takes"); + err.emit(); + return; + } + + match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::ConstEvaluatable(def, _) => { + let mut err = + self.tcx.sess.struct_span_err(span, "unconstrained generic constant"); + let const_span = self.tcx.def_span(def.did); + match self.tcx.sess.source_map().span_to_snippet(const_span) { + Ok(snippet) => err.help(&format!( + "try adding a `where` bound using this expression: `where [(); {}]:`", + snippet + )), + _ => err.help("consider adding a `where` bound using this expression"), + }; + err + } + _ => { + span_bug!( + span, + "unexpected non-ConstEvaluatable predicate, this should not be reachable" + ) + } + } } + // Already reported in the query. - ConstEvalFailure(ErrorHandled::Reported(ErrorReported)) => { + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorReported)) => { // FIXME(eddyb) remove this once `ErrorReported` becomes a proof token. self.tcx.sess.delay_span_bug(span, "`ErrorReported` without an error"); return; } - // Already reported in the query, but only as a lint. - // This shouldn't actually happen for constants used in types, modulo - // bugs. The `delay_span_bug` here ensures it won't be ignored. - ConstEvalFailure(ErrorHandled::Linted) => { - self.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); - return; - } - Overflow => { bug!("overflow should be handled before the `report_selection_error` path"); } @@ -1190,10 +1226,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ); let is_normalized_ty_expected = !matches!( - obligation.cause.code, + obligation.cause.code.peel_derives(), ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ObjectCastObligation(_) + | ObligationCauseCode::OpaqueType ); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( @@ -1917,7 +1954,7 @@ pub enum ArgKind { Arg(String, String), /// An argument of tuple type. For a "found" argument, the span is - /// the locationo in the source of the pattern. For a "expected" + /// the location in the source of the pattern. For a "expected" /// argument, it will be None. The vector is a list of (name, ty) /// strings for the components of the tuple. Tuple(Option, Vec<(String, String)>), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index e6a1cf58fe..1ea34e5814 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, GenericParamDefKind}; use rustc_span::symbol::sym; +use std::iter; use super::InferCtxtPrivExt; @@ -51,12 +52,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) { self_match_impls.push(def_id); - if trait_ref - .substs - .types() - .skip(1) - .zip(impl_trait_ref.substs.types().skip(1)) - .all(|(u, v)| self.fuzzy_match_tys(u, v)) + if iter::zip( + trait_ref.substs.types().skip(1), + impl_trait_ref.substs.types().skip(1), + ) + .all(|(u, v)| self.fuzzy_match_tys(u, v)) { fuzzy_match_impls.push(def_id); } @@ -163,61 +163,65 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { flags.push((sym::from_desugaring, None)); flags.push((sym::from_desugaring, Some(format!("{:?}", k)))); } - let generics = self.tcx.generics_of(def_id); - let self_ty = trait_ref.self_ty(); - // This is also included through the generics list as `Self`, - // but the parser won't allow you to use it - flags.push((sym::_Self, Some(self_ty.to_string()))); - if let Some(def) = self_ty.ty_adt_def() { - // We also want to be able to select self's original - // signature with no type arguments resolved - flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); - } - for param in generics.params.iter() { - let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { - trait_ref.substs[param.index as usize].to_string() - } - GenericParamDefKind::Lifetime => continue, - }; - let name = param.name; - flags.push((name, Some(value))); - } + // Add all types without trimmed paths. + ty::print::with_no_trimmed_paths(|| { + let generics = self.tcx.generics_of(def_id); + let self_ty = trait_ref.self_ty(); + // This is also included through the generics list as `Self`, + // but the parser won't allow you to use it + flags.push((sym::_Self, Some(self_ty.to_string()))); + if let Some(def) = self_ty.ty_adt_def() { + // We also want to be able to select self's original + // signature with no type arguments resolved + flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); + } - if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { - flags.push((sym::crate_local, None)); - } + for param in generics.params.iter() { + let value = match param.kind { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + trait_ref.substs[param.index as usize].to_string() + } + GenericParamDefKind::Lifetime => continue, + }; + let name = param.name; + flags.push((name, Some(value))); + } - // Allow targeting all integers using `{integral}`, even if the exact type was resolved - if self_ty.is_integral() { - flags.push((sym::_Self, Some("{integral}".to_owned()))); - } + if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { + flags.push((sym::crate_local, None)); + } - if let ty::Array(aty, len) = self_ty.kind() { - flags.push((sym::_Self, Some("[]".to_owned()))); - flags.push((sym::_Self, Some(format!("[{}]", aty)))); - if let Some(def) = aty.ty_adt_def() { - // We also want to be able to select the array's type's original - // signature with no type arguments resolved - let type_string = self.tcx.type_of(def.did).to_string(); - flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + // Allow targeting all integers using `{integral}`, even if the exact type was resolved + if self_ty.is_integral() { + flags.push((sym::_Self, Some("{integral}".to_owned()))); + } - let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); - let string = match len { - Some(n) => format!("[{}; {}]", type_string, n), - None => format!("[{}; _]", type_string), - }; - flags.push((sym::_Self, Some(string))); + if let ty::Array(aty, len) = self_ty.kind() { + flags.push((sym::_Self, Some("[]".to_owned()))); + flags.push((sym::_Self, Some(format!("[{}]", aty)))); + if let Some(def) = aty.ty_adt_def() { + // We also want to be able to select the array's type's original + // signature with no type arguments resolved + let type_string = self.tcx.type_of(def.did).to_string(); + flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + + let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); + let string = match len { + Some(n) => format!("[{}; {}]", type_string, n), + None => format!("[{}; _]", type_string), + }; + flags.push((sym::_Self, Some(string))); + } } - } - if let ty::Dynamic(traits, _) = self_ty.kind() { - for t in traits.iter() { - if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { - flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + if let ty::Dynamic(traits, _) = self_ty.kind() { + for t in traits.iter() { + if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { + flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + } } } - } + }); if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c1b105f1d8..6a4d41ffc1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -28,6 +28,7 @@ use std::fmt; use super::InferCtxtPrivExt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_middle::ty::print::with_no_trimmed_paths; #[derive(Debug)] pub enum GeneratorInteriorOrUpvar { @@ -65,7 +66,7 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ); @@ -73,7 +74,7 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder>, + trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, has_custom_message: bool, ) -> bool; @@ -82,14 +83,14 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ); @@ -98,7 +99,7 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option; @@ -108,7 +109,7 @@ pub trait InferCtxtExt<'tcx> { err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool; fn point_at_returns_when_relevant( @@ -170,7 +171,7 @@ pub trait InferCtxtExt<'tcx> { &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, span: Span, ); } @@ -440,7 +441,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { { // Missing generic type parameter bound. let param_name = self_ty.to_string(); - let constraint = trait_ref.print_only_trait_path().to_string(); + let constraint = + with_no_trimmed_paths(|| trait_ref.print_only_trait_path().to_string()); if suggest_constraining_type_param( self.tcx, generics, @@ -583,7 +585,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ) { let self_ty = match trait_ref.self_ty().no_bound_vars() { @@ -676,7 +678,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder>, + trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, has_custom_message: bool, ) -> bool { @@ -761,7 +763,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let span = obligation.cause.span; @@ -824,7 +826,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ) { let span = obligation.cause.span; @@ -896,10 +898,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let is_empty_tuple = - |ty: ty::Binder>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); + |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); @@ -948,7 +950,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool { match obligation.cause.code.peel_derives() { // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`. @@ -1840,6 +1842,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::UnifyReceiver(..) + | ObligationCauseCode::OpaqueType | ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); @@ -2067,7 +2070,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Don't print the tuple of capture types if !is_upvar_tys_infer_tuple { - err.note(&format!("required because it appears within the type `{}`", ty)); + let msg = format!("required because it appears within the type `{}`", ty); + match ty.kind() { + ty::Adt(def, _) => match self.tcx.opt_item_name(def.did) { + Some(ident) => err.span_note(ident.span, &msg), + None => err.note(&msg), + }, + _ => err.note(&msg), + }; } obligated_types.push(ty); @@ -2089,11 +2099,36 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::ImplDerivedObligation(ref data) => { let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); let parent_def_id = parent_trait_ref.def_id(); - err.note(&format!( + let msg = format!( "required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref.print_only_trait_path(), parent_trait_ref.skip_binder().self_ty() - )); + ); + let mut candidates = vec![]; + self.tcx.for_each_relevant_impl( + parent_def_id, + parent_trait_ref.self_ty().skip_binder(), + |impl_def_id| { + candidates.push(impl_def_id); + }, + ); + match &candidates[..] { + [def_id] => match self.tcx.hir().get_if_local(*def_id) { + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), + .. + })) => { + let mut spans = Vec::with_capacity(2); + if let Some(trait_ref) = of_trait { + spans.push(trait_ref.path.span); + } + spans.push(self_ty.span); + err.span_note(spans, &msg) + } + _ => err.note(&msg), + }, + _ => err.note(&msg), + }; let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); let mut data = data; @@ -2144,19 +2179,60 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) }); } - ObligationCauseCode::CompareImplMethodObligation { .. } => { - err.note(&format!( - "the requirement `{}` appears on the impl method but not on the corresponding \ - trait method", - predicate - )); + ObligationCauseCode::CompareImplMethodObligation { + item_name, + trait_item_def_id, + .. + } => { + let msg = format!( + "the requirement `{}` appears on the impl method `{}` but not on the \ + corresponding trait method", + predicate, item_name, + ); + let sp = self + .tcx + .opt_item_name(trait_item_def_id) + .map(|i| i.span) + .unwrap_or_else(|| self.tcx.def_span(trait_item_def_id)); + let mut assoc_span: MultiSpan = sp.into(); + assoc_span.push_span_label( + sp, + format!("this trait method doesn't have the requirement `{}`", predicate), + ); + if let Some(ident) = self + .tcx + .opt_associated_item(trait_item_def_id) + .and_then(|i| self.tcx.opt_item_name(i.container.id())) + { + assoc_span.push_span_label(ident.span, "in this trait".into()); + } + err.span_note(assoc_span, &msg); } - ObligationCauseCode::CompareImplTypeObligation { .. } => { - err.note(&format!( - "the requirement `{}` appears on the associated impl type but not on the \ + ObligationCauseCode::CompareImplTypeObligation { + item_name, trait_item_def_id, .. + } => { + let msg = format!( + "the requirement `{}` appears on the associated impl type `{}` but not on the \ corresponding associated trait type", - predicate - )); + predicate, item_name, + ); + let sp = self.tcx.def_span(trait_item_def_id); + let mut assoc_span: MultiSpan = sp.into(); + assoc_span.push_span_label( + sp, + format!( + "this trait associated type doesn't have the requirement `{}`", + predicate, + ), + ); + if let Some(ident) = self + .tcx + .opt_associated_item(trait_item_def_id) + .and_then(|i| self.tcx.opt_item_name(i.container.id())) + { + assoc_span.push_span_label(ident.span, "in this trait".into()); + } + err.span_note(assoc_span, &msg); } ObligationCauseCode::CompareImplConstObligation => { err.note(&format!( @@ -2190,7 +2266,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, span: Span, ) { debug!( diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 7d451fc234..fc9739f70d 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -3,7 +3,8 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; -use rustc_infer::traits::{TraitEngine, TraitEngineExt as _, TraitObligation}; +use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::subst::SubstsRef; @@ -18,7 +19,7 @@ use super::wf; use super::CodeAmbiguity; use super::CodeProjectionError; use super::CodeSelectionError; -use super::{ConstEvalFailure, Unimplemented}; +use super::Unimplemented; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; @@ -498,14 +499,19 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { obligation.cause.span, ) { Ok(()) => ProcessResult::Changed(vec![]), - Err(ErrorHandled::TooGeneric) => { + Err(NotConstEvaluatable::MentionsInfer) => { pending_obligation.stalled_on.clear(); pending_obligation.stalled_on.extend( substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); ProcessResult::Unchanged } - Err(e) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))), + Err( + e @ NotConstEvaluatable::MentionsParam + | e @ NotConstEvaluatable::Error(_), + ) => ProcessResult::Error(CodeSelectionError( + SelectionError::NotConstEvaluatable(e), + )), } } @@ -516,15 +522,13 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { // if the constants depend on generic parameters. // // Let's just see where this breaks :shrug: - if let ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) = (c1.val, c2.val) + if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = + (c1.val, c2.val) { if self .selcx .tcx() - .try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) + .try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs))) { return ProcessResult::Changed(vec![]); } @@ -534,18 +538,17 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let stalled_on = &mut pending_obligation.stalled_on; let mut evaluate = |c: &'tcx Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { match self.selcx.infcx().const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) { Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty)), Err(ErrorHandled::TooGeneric) => { stalled_on.extend( - substs + unevaluated + .substs .iter() .filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); @@ -576,11 +579,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } } (Err(ErrorHandled::Reported(ErrorReported)), _) - | (_, Err(ErrorHandled::Reported(ErrorReported))) => { - ProcessResult::Error(CodeSelectionError(ConstEvalFailure( - ErrorHandled::Reported(ErrorReported), - ))) - } + | (_, Err(ErrorHandled::Reported(ErrorReported))) => ProcessResult::Error( + CodeSelectionError(SelectionError::NotConstEvaluatable( + NotConstEvaluatable::Error(ErrorReported), + )), + ), (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { span_bug!( obligation.cause.span(self.selcx.tcx()), @@ -681,7 +684,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { /// Returns the set of inference variables contained in `substs`. fn substs_infer_vars<'a, 'tcx>( selcx: &mut SelectionContext<'a, 'tcx>, - substs: ty::Binder>, + substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> impl Iterator> { selcx .infcx() diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5a8c53a0c4..f26eb15910 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -483,7 +483,7 @@ fn vtable_methods<'tcx>( 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 => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize] } }) diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 7de20e477f..d5e1bd3f9e 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -132,6 +132,14 @@ fn object_safety_violations_for_trait( .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)), ); + violations.extend( + tcx.associated_items(trait_def_id) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| !tcx.generics_of(item.def_id).params.is_empty()) + .map(|item| ObjectSafetyViolation::GAT(item.ident.name, item.ident.span)), + ); + debug!( "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", trait_def_id, violations @@ -439,8 +447,7 @@ fn virtual_call_violation_for_method<'tcx>( return Some(MethodViolationCode::WhereClauseReferencesSelf); } - let receiver_ty = - tcx.liberate_late_bound_regions(method.def_id, sig.map_bound(|sig| sig.inputs()[0])); + let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0)); // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. // However, this is already considered object-safe. We allow it as a special case here. @@ -757,7 +764,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( struct IllegalSelfTypeVisitor<'tcx> { tcx: TyCtxt<'tcx>, trait_def_id: DefId, - supertraits: Option>>, + supertraits: Option>, } impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> { @@ -778,8 +785,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // Compute supertraits of current trait lazily. if self.supertraits.is_none() { let trait_ref = - ty::Binder::bind(ty::TraitRef::identity(self.tcx, self.trait_def_id)); - self.supertraits = Some(traits::supertraits(self.tcx, trait_ref).collect()); + ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)); + self.supertraits = Some( + traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(), + ); } // Determine whether the trait reference `Foo as @@ -790,9 +799,11 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // direct equality here because all of these types // are part of the formal parameter listing, and // hence there should be no inference variables. - let projection_trait_ref = ty::Binder::bind(data.trait_ref(self.tcx)); - let is_supertrait_of_current_trait = - self.supertraits.as_ref().unwrap().contains(&projection_trait_ref); + let is_supertrait_of_current_trait = self + .supertraits + .as_ref() + .unwrap() + .contains(&data.trait_ref(self.tcx).def_id); if is_supertrait_of_current_trait { ControlFlow::CONTINUE // do not walk contained types, do not report error, do collect $200 diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 75822eadb2..209fd83b3a 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -337,7 +337,7 @@ impl<'tcx> OnUnimplementedFormatString { .iter() .filter_map(|param| { let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize].to_string() } GenericParamDefKind::Lifetime => return None, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0af6d64591..b3e5df4da0 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1275,6 +1275,9 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); + // We get here from `poly_project_and_unify_type` which replaces bound vars + // with placeholders + debug_assert!(!self_ty.has_escaping_bound_vars()); let substs = tcx.mk_substs([self_ty.into()].iter()); let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None); @@ -1306,7 +1309,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( ty: self_ty.ptr_metadata_ty(tcx), }; - confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false) + confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/query/mod.rs b/compiler/rustc_trait_selection/src/traits/query/mod.rs index 01f4f09e23..f6f42814d3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/mod.rs @@ -3,7 +3,7 @@ //! which makes a canonical query by replacing unbound inference //! variables and regions, so that results can be reused more broadly. //! The providers for the queries defined here can be found in -//! `librustc_traits`. +//! `rustc_traits`. pub mod dropck_outlives; pub mod evaluate_obligation; diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index c908e1418c..eb7ea8715c 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -10,6 +10,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::Normalized; +use rustc_middle::mir; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -214,4 +215,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { let constant = constant.super_fold_with(self); constant.eval(self.infcx.tcx, self.param_env) } + + fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + constant.super_fold_with(self) + } } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index cf7f0a553c..b351af44e9 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -8,12 +8,6 @@ pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, } -impl<'tcx> ImpliedOutlivesBounds<'tcx> { - pub fn new(ty: Ty<'tcx>) -> Self { - ImpliedOutlivesBounds { ty } - } -} - impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> { type QueryResponse = Vec>; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 272930f6bb..e338a21b60 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -272,7 +272,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, trait_def_id: DefId, - nested: ty::Binder>>, + nested: ty::Binder<'tcx, Vec>>, ) -> ImplSourceAutoImplData> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { @@ -462,12 +462,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for assoc_type in assoc_types { if !tcx.generics_of(assoc_type).params.is_empty() { - // FIXME(generic_associated_types) generate placeholders to - // extend the trait substs. - tcx.sess.span_fatal( + tcx.sess.delay_span_bug( obligation.cause.span, - "generic associated types in trait objects are not supported yet", + "GATs in trait object shouldn't have been considered", ); + return Err(SelectionError::Unimplemented); } // This maybe belongs in wf, but that can't (doesn't) handle // higher-ranked things. @@ -748,7 +747,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause, obligation.recursion_depth + 1, obligation.param_env, - ty::Binder::bind(outlives).to_predicate(tcx), + obligation.predicate.rebind(outlives).to_predicate(tcx), )); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 45b5aff40a..727285e492 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -34,6 +34,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::Constness; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -203,7 +204,7 @@ struct EvaluatedCandidate<'tcx> { /// When does the builtin impl for `T: Trait` apply? enum BuiltinImplConditions<'tcx> { /// The impl is conditional on `T1, T2, ...: Trait`. - Where(ty::Binder>>), + Where(ty::Binder<'tcx, Vec>>), /// There is no built-in impl. There may be some other /// candidate (a where-clause or user-defined impl). None, @@ -547,7 +548,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.span, ) { Ok(()) => Ok(EvaluatedToOk), - Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig), + Err(NotConstEvaluatable::MentionsInfer) => Ok(EvaluatedToAmbig), + Err(NotConstEvaluatable::MentionsParam) => Ok(EvaluatedToErr), Err(_) => Ok(EvaluatedToErr), } } @@ -556,13 +558,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts"); let evaluate = |c: &'tcx ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { self.infcx .const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) .map(|val| ty::Const::from_value(self.tcx(), val, c.ty)) @@ -863,7 +863,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>, candidate: &SelectionCandidate<'tcx>, ) -> Result { - let result = self.evaluation_probe(|this| { + let mut result = self.evaluation_probe(|this| { let candidate = (*candidate).clone(); match this.confirm_candidate(stack.obligation, candidate) { Ok(selection) => { @@ -876,6 +876,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(..) => Ok(EvaluatedToErr), } })?; + + // If we erased any lifetimes, then we want to use + // `EvaluatedToOkModuloRegions` instead of `EvaluatedToOk` + // as your final result. The result will be cached using + // the freshened trait predicate as a key, so we need + // our result to be correct by *any* choice of original lifetimes, + // not just the lifetime choice for this particular (non-erased) + // predicate. + // See issue #80691 + if stack.fresh_trait_ref.has_erased_regions() { + result = result.max(EvaluatedToOkModuloRegions); + } + debug!(?result); Ok(result) } @@ -931,7 +944,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// subobligations without taking in a 'parent' depth, causing the /// generated subobligations to have a `recursion_depth` of `0`. /// - /// To ensure that obligation_depth never decreasees, we force all subobligations + /// To ensure that obligation_depth never decreases, we force all subobligations /// to have at least the depth of the original obligation. fn add_depth>>( &self, @@ -968,7 +981,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { OP: FnOnce(&mut Self) -> R, { let (result, dep_node) = - self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self)); + self.tcx().dep_graph.with_anon_task(self.tcx(), DepKind::TraitSelect, || op(self)); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) } @@ -1348,7 +1361,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => false, (ParamCandidate(other), ParamCandidate(victim)) => { - if other.value == victim.value && victim.constness == Constness::NotConst { + let value_same_except_bound_vars = other.value.skip_binder() + == victim.value.skip_binder() + && !other.value.skip_binder().has_escaping_bound_vars(); + if value_same_except_bound_vars { + // See issue #84398. In short, we can generate multiple ParamCandidates which are + // the same except for unused bound vars. Just pick the one with the fewest bound vars + // or the current one if tied (they should both evaluate to the same answer). This is + // probably best characterized as a "hack", since we might prefer to just do our + // best to *not* create essentially duplicate candidates in the first place. + other.value.bound_vars().len() <= victim.value.bound_vars().len() + } else if other.value == victim.value && victim.constness == Constness::NotConst { // Drop otherwise equivalent non-const candidates in favor of const candidates. true } else { @@ -1660,7 +1683,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Bar where struct Bar { x: T, y: u32 } -> [i32, u32] /// Zed where enum Zed { A(T), B(u32) } -> [i32, u32] /// ``` - fn constituent_types_for_ty(&self, t: ty::Binder>) -> ty::Binder>> { + fn constituent_types_for_ty( + &self, + t: ty::Binder<'tcx, Ty<'tcx>>, + ) -> ty::Binder<'tcx, Vec>> { match *t.skip_binder().kind() { ty::Uint(_) | ty::Int(_) @@ -1733,7 +1759,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause: ObligationCause<'tcx>, recursion_depth: usize, trait_def_id: DefId, - types: ty::Binder>>, + types: ty::Binder<'tcx, Vec>>, ) -> Vec> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound @@ -1754,7 +1780,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .skip_binder() // binder moved -\ .iter() .flat_map(|ty| { - let ty: ty::Binder> = types.rebind(ty); // <----/ + let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(ty); // <----/ self.infcx.commit_unconditionally(|_| { let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(ty); @@ -1874,7 +1900,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // substitution if we find that any of the input types, when // simplified, do not match. - obligation.predicate.skip_binder().trait_ref.substs.iter().zip(impl_trait_ref.substs).any( + iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs).any( |(obligation_arg, impl_arg)| { match (obligation_arg.unpack(), impl_arg.unpack()) { (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 264cc4f248..4b563a87a1 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -395,14 +395,14 @@ fn report_conflicting_impls( // that's passed in. let decorate = |err: LintDiagnosticBuilder<'_>| { let msg = format!( - "conflicting implementations of trait `{}`{}:{}", + "conflicting implementations of trait `{}`{}{}", overlap.trait_desc, overlap .self_desc .clone() .map_or_else(String::new, |ty| { format!(" for type `{}`", ty) }), match used_to_be_allowed { - Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", + Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)", _ => "", } ); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 8888ea2c84..fd94f9f799 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -328,7 +328,7 @@ pub fn closure_trait_ref_and_return_type( self_ty: Ty<'tcx>, sig: ty::PolyFnSig<'tcx>, tuple_arguments: TupleArgumentsFlag, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> { +) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> { let arguments_tuple = match tuple_arguments { TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()), @@ -346,7 +346,7 @@ pub fn generator_trait_ref_and_outputs( fn_trait_def_id: DefId, self_ty: Ty<'tcx>, sig: ty::PolyGenSig<'tcx>, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { +) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { debug_assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e6ef9b137d..f592cf1cd2 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { GenericArgKind::Const(constant) => { match constant.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { assert!(promoted.is_none()); let obligations = self.nominal_obligations(def.did, substs); @@ -692,11 +692,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let predicates = predicates.instantiate(self.infcx.tcx, substs); debug_assert_eq!(predicates.predicates.len(), origins.len()); - predicates - .predicates - .into_iter() - .zip(predicates.spans.into_iter()) - .zip(origins.into_iter().rev()) + iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev()) .map(|((pred, span), origin_def_id)| { let cause = self.cause(traits::BindingObligation(origin_def_id, span)); traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) @@ -708,7 +704,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { fn from_object_ty( &mut self, ty: Ty<'tcx>, - data: &'tcx ty::List>>, + data: &'tcx ty::List>>, region: ty::Region<'tcx>, ) { // Imagine a type like this: @@ -771,7 +767,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// `infer::required_region_bounds`, see that for more information. pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>>, ) -> Vec> { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 916186f420..8c97e606c5 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -735,11 +735,14 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { .into(), ty::GenericParamDefKind::Lifetime => { - let br = ty::BoundRegion { kind: ty::BrAnon(substs.len() as u32) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(substs.len()), + kind: ty::BrAnon(substs.len() as u32), + }; tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into() } - ty::GenericParamDefKind::Const => tcx + ty::GenericParamDefKind::Const { .. } => tcx .mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), ty: tcx.type_of(param.def_id), diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index fdf5f697e6..39890fd5b0 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -434,17 +434,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t ReEarlyBound(_) => { panic!("Should have already been substituted."); } - ReLateBound(db, br) => match br.kind { - ty::BoundRegionKind::BrAnon(var) => { - chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( - chalk_ir::DebruijnIndex::new(db.as_u32()), - var as usize, - )) - .intern(interner) - } - ty::BoundRegionKind::BrNamed(_def_id, _name) => unimplemented!(), - ty::BrEnv => unimplemented!(), - }, + ReLateBound(db, br) => chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( + chalk_ir::DebruijnIndex::new(db.as_u32()), + br.var.as_usize(), + )) + .intern(interner), ReFree(_) => unimplemented!(), ReStatic => chalk_ir::LifetimeData::Static.intern(interner), ReVar(_) => unimplemented!(), @@ -467,7 +461,10 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime ty::RegionKind::ReLateBound( ty::DebruijnIndex::from_u32(var.debruijn.depth()), - ty::BoundRegion { kind: ty::BrAnon(var.index as u32) }, + ty::BoundRegion { + var: ty::BoundVar::from_usize(var.index), + kind: ty::BrAnon(var.index as u32), + }, ), chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(), chalk_ir::LifetimeData::Placeholder(p) => { @@ -606,7 +603,7 @@ impl<'tcx> LowerInto<'tcx, Option LowerInto<'tcx, chalk_ir::Binders>>> - for &'tcx ty::List>> + for &'tcx ty::List>> { fn lower_into( self, @@ -677,7 +674,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders LowerInto<'tcx, chalk_ir::FnSig>> for ty::Binder> { +impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig>> + for ty::Binder<'tcx, ty::FnSig<'tcx>> +{ fn lower_into(self, _interner: &RustInterner<'_>) -> FnSig> { chalk_ir::FnSig { abi: self.abi(), @@ -801,7 +800,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>( interner: &RustInterner<'tcx>, tcx: TyCtxt<'tcx>, - ty: Binder, + ty: Binder<'tcx, T>, ) -> (T, chalk_ir::VariableKinds>, BTreeMap) { let mut bound_vars_collector = BoundVarsCollector::new(); ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector); @@ -849,7 +848,10 @@ impl<'tcx> BoundVarsCollector<'tcx> { } impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); @@ -895,7 +897,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { }, }, - ty::BrEnv => unimplemented!(), + ty::BoundRegionKind::BrEnv => unimplemented!(), }, ty::ReEarlyBound(_re) => { @@ -931,7 +933,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: Binder) -> Binder { + fn fold_binder>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); @@ -943,7 +945,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> { ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { Some(idx) => { - let new_br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; + let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) }; return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br)); } None => panic!("Missing `BrNamed`."), @@ -987,7 +989,7 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { self.tcx } - fn fold_binder>(&mut self, t: Binder) -> Binder { + fn fold_binder>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); @@ -1026,12 +1028,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { // This covers any region variables in a goal, right? ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) { Some(idx) => { - let br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(*idx), + kind: ty::BrAnon(*idx), + }; self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) } None => { let idx = self.named_regions.len() as u32; - let br = ty::BoundRegion { kind: ty::BrAnon(idx) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) }; self.named_regions.insert(_re.def_id, idx); self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) } diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 1213e55390..5ad0684fe6 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -1,24 +1,35 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::GenericArg; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable}; use rustc_trait_selection::traits::query::normalize::AtExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers) { - *p = Providers { normalize_generic_arg_after_erasing_regions, ..*p }; + *p = Providers { + normalize_generic_arg_after_erasing_regions: |tcx, goal| { + debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); + + tcx.sess + .perf_stats + .normalize_generic_arg_after_erasing_regions + .fetch_add(1, Ordering::Relaxed); + normalize_after_erasing_regions(tcx, goal) + }, + normalize_mir_const_after_erasing_regions: |tcx, goal| { + normalize_after_erasing_regions(tcx, goal) + }, + ..*p + }; } -fn normalize_generic_arg_after_erasing_regions<'tcx>( +#[instrument(level = "debug", skip(tcx))] +fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>( tcx: TyCtxt<'tcx>, - goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>, -) -> GenericArg<'tcx> { - debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); - + goal: ParamEnvAnd<'tcx, T>, +) -> T { let ParamEnvAnd { param_env, value } = goal; - tcx.sess.perf_stats.normalize_generic_arg_after_erasing_regions.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).normalize(value) { diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index 24ba071786..cedc84d97c 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -18,6 +18,10 @@ fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>> is_item_raw(tcx, query, LangItem::Freeze) } +fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + is_item_raw(tcx, query, LangItem::Unpin) +} + fn is_item_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, @@ -37,5 +41,11 @@ fn is_item_raw<'tcx>( } pub(crate) fn provide(providers: &mut ty::query::Providers) { - *providers = ty::query::Providers { is_copy_raw, is_sized_raw, is_freeze_raw, ..*providers }; + *providers = ty::query::Providers { + is_copy_raw, + is_sized_raw, + is_freeze_raw, + is_unpin_raw, + ..*providers + }; } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 6b9d46ee0a..874289d029 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -115,7 +115,7 @@ 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)))?; + let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?; // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index aa5d338840..67a692ecea 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -20,6 +20,7 @@ use rustc_middle::ty::query::Providers; mod common_traits; pub mod instance; mod needs_drop; +pub mod representability; mod ty; pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs new file mode 100644 index 0000000000..ca001635a3 --- /dev/null +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -0,0 +1,186 @@ +//! Check whether a type is representable. +use rustc_data_structures::stable_map::FxHashMap; +use rustc_hir as hir; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; +use std::cmp; + +/// Describes whether a type is representable. For types that are not +/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to +/// distinguish between types that are recursive with themselves and types that +/// contain a different recursive type. These cases can therefore be treated +/// differently when reporting errors. +/// +/// The ordering of the cases is significant. They are sorted so that cmp::max +/// will keep the "more erroneous" of two values. +#[derive(Clone, PartialOrd, Ord, Eq, PartialEq, Debug)] +pub enum Representability { + Representable, + ContainsRecursive, + SelfRecursive(Vec), +} + +/// Check whether a type is representable. This means it cannot contain unboxed +/// structural recursion. This check is needed for structs and enums. +pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> Representability { + debug!("is_type_representable: {:?}", ty); + // To avoid a stack overflow when checking an enum variant or struct that + // contains a different, structurally recursive type, maintain a stack + // of seen types and check recursion for each of them (issues #3008, #3779). + let mut seen: Vec> = Vec::new(); + let mut representable_cache = FxHashMap::default(); + let r = is_type_structurally_recursive(tcx, sp, &mut seen, &mut representable_cache, ty); + debug!("is_type_representable: {:?} is {:?}", ty, r); + r +} + +// Iterate until something non-representable is found +fn fold_repr>(iter: It) -> Representability { + iter.fold(Representability::Representable, |r1, r2| match (r1, r2) { + (Representability::SelfRecursive(v1), Representability::SelfRecursive(v2)) => { + Representability::SelfRecursive(v1.into_iter().chain(v2).collect()) + } + (r1, r2) => cmp::max(r1, r2), + }) +} + +fn are_inner_types_recursive<'tcx>( + tcx: TyCtxt<'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>, +) -> Representability { + match ty.kind() { + ty::Tuple(..) => { + // Find non representable + fold_repr( + ty.tuple_fields().map(|ty| { + is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) + }), + ) + } + // Fixed-length vectors. + // FIXME(#11924) Behavior undecided for zero-length vectors. + ty::Array(ty, _) => is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty), + ty::Adt(def, substs) => { + // Find non representable fields with their spans + fold_repr(def.all_fields().map(|field| { + let ty = field.ty(tcx, substs); + let span = match field + .did + .as_local() + .map(|id| tcx.hir().local_def_id_to_hir_id(id)) + .and_then(|id| tcx.hir().find(id)) + { + Some(hir::Node::Field(field)) => field.ty.span, + _ => sp, + }; + match is_type_structurally_recursive(tcx, span, seen, representable_cache, ty) { + Representability::SelfRecursive(_) => { + Representability::SelfRecursive(vec![span]) + } + x => x, + } + })) + } + ty::Closure(..) => { + // this check is run on type definitions, so we don't expect + // to see closure types + bug!("requires check invoked on inapplicable type: {:?}", ty) + } + _ => Representability::Representable, + } +} + +fn same_adt<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool { + match *ty.kind() { + ty::Adt(ty_def, _) => ty_def == def, + _ => false, + } +} + +// Does the type `ty` directly (without indirection through a pointer) +// contain any types on stack `seen`? +fn is_type_structurally_recursive<'tcx>( + tcx: TyCtxt<'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>, +) -> Representability { + debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp); + if let Some(representability) = representable_cache.get(ty) { + debug!( + "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}", + ty, sp, representability + ); + return representability.clone(); + } + + let representability = + is_type_structurally_recursive_inner(tcx, sp, seen, representable_cache, ty); + + representable_cache.insert(ty, representability.clone()); + representability +} + +fn is_type_structurally_recursive_inner<'tcx>( + tcx: TyCtxt<'tcx>, + sp: Span, + seen: &mut Vec>, + representable_cache: &mut FxHashMap, Representability>, + ty: Ty<'tcx>, +) -> Representability { + match ty.kind() { + ty::Adt(def, _) => { + { + // Iterate through stack of previously seen types. + let mut iter = seen.iter(); + + // The first item in `seen` is the type we are actually curious about. + // We want to return SelfRecursive if this type contains itself. + // It is important that we DON'T take generic parameters into account + // for this check, so that Bar in this example counts as SelfRecursive: + // + // struct Foo; + // struct Bar { x: Bar } + + if let Some(&seen_adt) = iter.next() { + if same_adt(seen_adt, *def) { + debug!("SelfRecursive: {:?} contains {:?}", seen_adt, ty); + return Representability::SelfRecursive(vec![sp]); + } + } + + // We also need to know whether the first item contains other types + // that are structurally recursive. If we don't catch this case, we + // will recurse infinitely for some inputs. + // + // It is important that we DO take generic parameters into account + // here, so that code like this is considered SelfRecursive, not + // ContainsRecursive: + // + // struct Foo { Option> } + + for &seen_adt in iter { + if ty::TyS::same_type(ty, seen_adt) { + debug!("ContainsRecursive: {:?} contains {:?}", seen_adt, ty); + return Representability::ContainsRecursive; + } + } + } + + // For structs and enums, track all previously seen types by pushing them + // onto the 'seen' stack. + seen.push(ty); + let out = are_inner_types_recursive(tcx, sp, seen, representable_cache, ty); + seen.pop(); + out + } + _ => { + // No need to push in other cases. + are_inner_types_recursive(tcx, sp, seen, representable_cache, ty) + } + } +} diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 29f1761b84..38e5ce6fd8 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -210,9 +210,9 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { } } -fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssociatedItems<'_> { +fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> { let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); - ty::AssociatedItems::new(items) + ty::AssocItems::new(items) } fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index fccd8b795e..8fcdf813b4 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,7 +1,3 @@ -#![feature(never_type)] -#![feature(const_panic)] -#![feature(control_flow_enum)] - #[macro_use] extern crate bitflags; #[macro_use] diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_typeck/Cargo.toml index d92d317e34..eb55a8a23a 100644 --- a/compiler/rustc_typeck/Cargo.toml +++ b/compiler/rustc_typeck/Cargo.toml @@ -26,3 +26,4 @@ rustc_span = { path = "../rustc_span" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_ty_utils = { path = "../rustc_ty_utils" } diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index b5404c3a15..695132281c 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -10,6 +10,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use std::collections::BTreeSet; +use std::iter; impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// On missing type parameters, emit an E0393 error and provide a structured suggestion using @@ -309,7 +310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // that the user forgot to give the associtated type's name. The canonical // example would be trying to use `Iterator` instead of // `Iterator`. - for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) { + for (potential, item) in iter::zip(&potential_assoc_types, assoc_items) { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) { suggestions.push((*potential, format!("{} = {}", item.ident, snippet))); } diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 0ea0ccacea..a3804e468d 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -64,7 +64,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)), .. }), - GenericParamDefKind::Const, + GenericParamDefKind::Const { .. }, ) => match path.res { Res::Err => { add_braces_suggestion(arg, &mut err); @@ -82,7 +82,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if param_type.is_suggestable() { err.span_suggestion( tcx.def_span(src_def_id), - "consider changing this type paramater to a `const`-generic", + "consider changing this type parameter to be a `const` generic", format!("const {}: {}", param_name, param_type), Applicability::MaybeIncorrect, ); @@ -93,7 +93,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }, ( GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }), - GenericParamDefKind::Const, + GenericParamDefKind::Const { .. }, ) => add_braces_suggestion(arg, &mut err), ( GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), @@ -109,6 +109,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); } } + (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { + let body = tcx.hir().body(cnst.value.body); + if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = + body.value.kind + { + if let Res::Def(DefKind::Fn { .. }, id) = path.res { + err.help(&format!( + "`{}` is a function item, not a type", + tcx.item_name(id) + )); + err.help("function item types cannot be named directly"); + } + } + } _ => {} } @@ -166,7 +180,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs: &[subst::GenericArg<'tcx>], has_self: bool, self_ty: Option>, - arg_count: GenericArgCountResult, + arg_count: &GenericArgCountResult, ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, ) -> SubstsRef<'tcx> { // Collect the segments of the path; we need to substitute arguments @@ -236,7 +250,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match (arg, ¶m.kind, arg_count.explicit_late_bound) { (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _) - | (GenericArg::Const(_), GenericParamDefKind::Const, _) => { + | (GenericArg::Const(_), GenericParamDefKind::Const { .. }, _) => { substs.push(ctx.provided_kind(param, arg)); args.next(); params.next(); @@ -282,11 +296,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericParamDefKind::Type { .. } => { ParamKindOrd::Type } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { ParamKindOrd::Const { unordered: tcx .features() - .const_generics, + .unordered_const_ty_params(), } } }, @@ -309,7 +323,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, GenericArg::Const(_) => ParamKindOrd::Const { - unordered: tcx.features().const_generics, + unordered: tcx + .features() + .unordered_const_ty_params(), }, }), Some(&format!( @@ -499,7 +515,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let expected_min = if infer_args { 0 } else { - param_counts.consts + named_type_param_count - default_counts.types + param_counts.consts + named_type_param_count + - default_counts.types + - default_counts.consts }; check_generics( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 7c5398003f..2f2e90e4bd 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -198,6 +198,7 @@ pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> { } impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { + #[tracing::instrument(level = "debug", skip(self))] pub fn ast_region_to_region( &self, lifetime: &hir::Lifetime, @@ -209,14 +210,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let r = match tcx.named_region(lifetime.hir_id) { Some(rl::Region::Static) => tcx.lifetimes.re_static, - Some(rl::Region::LateBound(debruijn, id, _)) => { - let name = lifetime_name(id.expect_local()); - let br = ty::BoundRegion { kind: ty::BrNamed(id, name) }; + Some(rl::Region::LateBound(debruijn, index, def_id, _)) => { + let name = lifetime_name(def_id.expect_local()); + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(index), + kind: ty::BrNamed(def_id, name), + }; tcx.mk_region(ty::ReLateBound(debruijn, br)) } - Some(rl::Region::LateBoundAnon(debruijn, index)) => { - let br = ty::BoundRegion { kind: ty::BrAnon(index) }; + Some(rl::Region::LateBoundAnon(debruijn, index, anon_index)) => { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(index), + kind: ty::BrAnon(anon_index), + }; tcx.mk_region(ty::ReLateBound(debruijn, br)) } @@ -237,6 +244,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { None => { self.re_infer(def, lifetime.span).unwrap_or_else(|| { + debug!(?lifetime, "unelided lifetime in signature"); + // This indicates an illegal lifetime // elision. `resolve_lifetime` should have // reported an error in this case -- but if @@ -263,7 +272,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id: DefId, item_segment: &hir::PathSegment<'_>, ) -> SubstsRef<'tcx> { - let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, def_id, &[], @@ -272,6 +281,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.infer_args, None, ); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args()); if let Some(b) = assoc_bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -311,6 +321,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// `[Vec, u8]` and `generic_args` are the arguments for the associated /// type itself: `['a]`. The returned `SubstsRef` concatenates these two /// lists: `[Vec, u8, 'a]`. + #[tracing::instrument(level = "debug", skip(self, span))] fn create_substs_for_ast_path<'a>( &self, span: Span, @@ -320,15 +331,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, - ) -> (SubstsRef<'tcx>, Vec>, GenericArgCountResult) { + ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - debug!( - "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ - generic_args={:?})", - def_id, self_ty, generic_args - ); let tcx = self.tcx(); let generics = tcx.generics_of(def_id); @@ -364,7 +370,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // here and so associated type bindings will be handled regardless of whether there are any // non-`Self` generic parameters. if generics.params.len() == 0 { - return (tcx.intern_substs(&[]), vec![], arg_count); + return (tcx.intern_substs(&[]), arg_count); } let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self); @@ -443,7 +449,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.astconv.ast_ty_to_ty(&ty).into() } } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { ty::Const::from_opt_const_arg_anon_const( tcx, ty::WithOptConstParam { @@ -504,15 +510,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.ty_error().into() } } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); - // FIXME(const_generics_defaults) - if infer_args { - // No const parameters were provided, we can infer all. - self.astconv.ct_infer(ty, Some(param), self.span).into() + if !infer_args && has_default { + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { - // We've already errored above about the mismatch. - tcx.const_error(ty).into() + if infer_args { + self.astconv.ct_infer(ty, Some(param), self.span).into() + } else { + // We've already errored above about the mismatch. + tcx.const_error(ty).into() + } } } } @@ -535,7 +545,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs, self_ty.is_some(), self_ty, - arg_count.clone(), + &arg_count, &mut substs_ctx, ); @@ -546,6 +556,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args.args.is_empty(), ); + debug!( + "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", + generics, self_ty, substs + ); + + (substs, arg_count) + } + + fn create_assoc_bindings_for_generic_args<'a>( + &self, + generic_args: &'a hir::GenericArgs<'_>, + ) -> Vec> { // Convert associated-type bindings or constraints into a separate vector. // Example: Given this: // @@ -576,12 +598,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) .collect(); - debug!( - "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", - generics, self_ty, substs - ); - - (substs, assoc_bindings, arg_count) + assoc_bindings } crate fn create_substs_for_associated_item( @@ -631,8 +648,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) } - /// The given trait-ref must actually be a trait. - pub(super) fn instantiate_poly_trait_ref_inner( + /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct + /// a full trait reference. The resulting trait reference is returned. This may also generate + /// auxiliary bounds, which are added to `bounds`. + /// + /// Example: + /// + /// ``` + /// poly_trait_ref = Iterator + /// self_ty = Foo + /// ``` + /// + /// this would return `Foo: Iterator` and add `::Item = u32` into `bounds`. + /// + /// **A note on binders:** against our usual convention, there is an implied bounder around + /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. + /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` + /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be + /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, + /// however. + #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))] + pub fn instantiate_poly_trait_ref( &self, trait_ref: &hir::TraitRef<'_>, span: Span, @@ -643,18 +679,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); - debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); - self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); - let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref( + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); + debug!(?bound_vars); + + let (substs, arg_count) = self.create_substs_for_ast_trait_ref( trait_ref.path.span, trait_def_id, self_ty, trait_ref.path.segments.last().unwrap(), ); - let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + let assoc_bindings = self + .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args()); + + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); + debug!(?poly_trait_ref, ?assoc_bindings); bounds.trait_bounds.push((poly_trait_ref, span, constness)); let mut dup_bindings = FxHashMap::default(); @@ -672,50 +715,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Okay to ignore `Err` because of `ErrorReported` (see above). } - debug!( - "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}", - trait_ref, bounds, poly_trait_ref - ); - arg_count } - /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct - /// a full trait reference. The resulting trait reference is returned. This may also generate - /// auxiliary bounds, which are added to `bounds`. - /// - /// Example: - /// - /// ``` - /// poly_trait_ref = Iterator - /// self_ty = Foo - /// ``` - /// - /// this would return `Foo: Iterator` and add `::Item = u32` into `bounds`. - /// - /// **A note on binders:** against our usual convention, there is an implied bounder around - /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. - /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` - /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be - /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, - /// however. - pub fn instantiate_poly_trait_ref( - &self, - poly_trait_ref: &hir::PolyTraitRef<'_>, - constness: Constness, - self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx>, - ) -> GenericArgCountResult { - self.instantiate_poly_trait_ref_inner( - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - self_ty, - bounds, - false, - ) - } - pub fn instantiate_lang_item_trait_ref( &self, lang_item: hir::LangItem, @@ -727,7 +729,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) { let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); - let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, trait_def_id, &[], @@ -736,7 +738,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { false, Some(self_ty), ); - let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst)); let mut dup_bindings = FxHashMap::default(); @@ -760,23 +766,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, ) -> ty::TraitRef<'tcx> { - let (substs, assoc_bindings, _) = + let (substs, _) = self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args()); if let Some(b) = assoc_bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); } ty::TraitRef::new(trait_def_id, substs) } + #[tracing::instrument(level = "debug", skip(self, span))] fn create_substs_for_ast_trait_ref<'a>( &self, span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, - ) -> (SubstsRef<'tcx>, Vec>, GenericArgCountResult) { - debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); - + ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); self.create_substs_for_ast_path( @@ -798,7 +804,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Returns `true` if a bounds list includes `?Sized`. - pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool { + pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool { let tcx = self.tcx(); // Try to find an unbound in bounds. @@ -853,29 +859,46 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// **A note on binders:** there is an implied binder around /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. + #[tracing::instrument(level = "debug", skip(self, bounds))] fn add_bounds( &self, param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'_>], bounds: &mut Bounds<'tcx>, + bound_vars: &'tcx ty::List, ) { let constness = self.default_constness_for_trait_bounds(); for ast_bound in ast_bounds { match *ast_bound { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { - self.instantiate_poly_trait_ref(b, constness, param_ty, bounds); + self.instantiate_poly_trait_ref( + &b.trait_ref, + b.span, + constness, + param_ty, + bounds, + false, + ); } hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => { - self.instantiate_poly_trait_ref(b, Constness::NotConst, param_ty, bounds); + self.instantiate_poly_trait_ref( + &b.trait_ref, + b.span, + Constness::NotConst, + param_ty, + bounds, + false, + ); } hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self .instantiate_lang_item_trait_ref( - *lang_item, *span, *hir_id, args, param_ty, bounds, + lang_item, span, hir_id, args, param_ty, bounds, ), - hir::GenericBound::Outlives(ref l) => bounds - .region_bounds - .push((ty::Binder::bind(self.ast_region_to_region(l, None)), l.span)), + hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push(( + ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars), + l.span, + )), } } } @@ -903,7 +926,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { sized_by_default: SizedByDefault, span: Span, ) -> Bounds<'tcx> { - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span) } @@ -923,7 +945,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(trait_ref) = ast_bound.trait_ref() { if let Some(trait_did) = trait_ref.trait_def_id() { if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) { - result.push(ast_bound); + result.push(ast_bound.clone()); } } } @@ -935,13 +957,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn compute_bounds_inner( &self, param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'_>], sized_by_default: SizedByDefault, span: Span, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - self.add_bounds(param_ty, ast_bounds, &mut bounds); + self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty()); bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { if !self.is_unsized(ast_bounds, span) { Some(span) } else { None } @@ -958,6 +980,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// **A note on binders:** given something like `T: for<'a> Iterator`, the /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* /// the binder (e.g., `&'a u32`) and hence may reference bound regions. + #[tracing::instrument( + level = "debug", + skip(self, bounds, speculative, dup_bindings, path_span) + )] fn add_predicates_for_ast_type_binding( &self, hir_ref_id: hir::HirId, @@ -984,7 +1010,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // We want to produce `>::T == foo`. - debug!(?hir_ref_id, ?trait_ref, ?binding, ?bounds, "add_predicates_for_ast_type_binding",); let tcx = self.tcx(); let candidate = @@ -1085,7 +1110,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&projection_ty); let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty)); + tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); debug!("late_bound_in_ty = {:?}", late_bound_in_ty); @@ -1134,10 +1159,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. - let param_ty = - tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs); - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); - self.add_bounds(param_ty, &ast_bounds, bounds); + let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder())); + self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars()); } } Ok(()) @@ -1171,10 +1194,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), .. } = self.instantiate_poly_trait_ref( - trait_bound, + &trait_bound.trait_ref, + trait_bound.span, Constness::NotConst, dummy_self, &mut bounds, + false, ) { potential_assoc_types.extend(cur_potential_assoc_types); } @@ -1659,7 +1684,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; self.one_bound_for_assoc_type( - || traits::supertraits(tcx, ty::Binder::bind(trait_ref)), + || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)), || "Self".to_string(), assoc_ident, span, @@ -2171,9 +2196,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. + #[tracing::instrument(level = "debug", skip(self))] fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> { - debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind); - let tcx = self.tcx(); let result_ty = match ast_ty.kind { @@ -2183,7 +2207,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); - debug!("ast_ty_to_ty: r={:?}", r); + debug!(?r); let t = self.ast_ty_to_ty_inner(&mt.ty, true); tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } @@ -2195,6 +2219,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); tcx.mk_fn_ptr(self.ty_of_fn( + ast_ty.hir_id, bf.unsafety, bf.abi, &bf.decl, @@ -2207,7 +2232,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed) } hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => { - debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); + debug!(?maybe_qself, ?path); let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself)); self.res_to_ty(opt_self_ty, path, false) } @@ -2223,7 +2248,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { - debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment); + debug!(?qself, ?segment); let ty = self.ast_ty_to_ty(qself); let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind { @@ -2237,7 +2262,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); - let (substs, _, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, def_id, &[], @@ -2254,9 +2279,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } - hir::TyKind::Typeof(ref _e) => { + hir::TyKind::Typeof(ref e) => { tcx.sess.emit_err(TypeofReservedKeywordUsed { span: ast_ty.span }); - tcx.ty_error() + tcx.type_of(tcx.hir().local_def_id(e.hir_id)) } hir::TyKind::Infer => { // Infer also appears as the type of arguments or return @@ -2268,13 +2293,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Err => tcx.ty_error(), }; - debug!("ast_ty_to_ty: result_ty={:?}", result_ty); + debug!(?result_ty); self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span); result_ty } - pub fn impl_trait_ty_to_ty( + fn impl_trait_ty_to_ty( &self, def_id: DefId, lifetimes: &[hir::GenericArg<'_>], @@ -2335,6 +2360,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn ty_of_fn( &self, + hir_id: hir::HirId, unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl<'_>, @@ -2345,6 +2371,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("ty_of_fn"); let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + debug!(?bound_vars); // We proactively collect all the inferred type params to emit a single error per fn def. let mut visitor = PlaceholderHirTyCollector::default(); @@ -2364,8 +2392,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("ty_of_fn: output_ty={:?}", output_ty); - let bare_fn_ty = - ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi)); + let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi); + let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); if !self.allow_ty_infer() { // We always collect the spans for placeholder types when evaluating `fn`s, but we @@ -2446,7 +2474,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn compute_object_lifetime_bound( &self, span: Span, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>>, ) -> Option> // if None, use the default { let tcx = self.tcx(); diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 7ba90ad881..5d20064072 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -26,7 +26,7 @@ pub struct Bounds<'tcx> { /// A list of region bounds on the (implicit) self type. So if you /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but /// the `T` is not explicitly included). - pub region_bounds: Vec<(ty::Binder>, Span)>, + pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>, /// A list of trait bounds. So if you had `T: Debug` this would be /// `T: Debug`. Note that the self-type is explicit here. @@ -57,7 +57,7 @@ impl<'tcx> Bounds<'tcx> { // If it could be sized, and is, add the `Sized` predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { tcx.lang_items().sized_trait().map(|sized| { - let trait_ref = ty::Binder::bind(ty::TraitRef { + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id: sized, substs: tcx.mk_substs_trait(param_ty, &[]), }); diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index a29f551800..b48102e0fc 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -17,6 +17,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; use rustc_trait_selection::autoderef::Autoderef; +use std::iter; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -539,7 +540,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { debug!("attempt_resolution: method_callee={:?}", method_callee); for (method_arg_ty, self_arg_ty) in - method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) + iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs()) { fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty); } diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 16c344e8e2..b760a54f08 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -359,6 +359,21 @@ impl<'a, 'tcx> CastCheck<'tcx> { { sugg = Some(format!("&{}", mutbl.prefix_str())); } + } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() { + if fcx + .try_coerce( + self.expr, + fcx.tcx.mk_ref( + &ty::RegionKind::ReErased, + TypeAndMut { ty: self.expr_ty, mutbl }, + ), + self.cast_ty, + AllowTwoPhase::No, + ) + .is_ok() + { + sugg = Some(format!("&{}", mutbl.prefix_str())); + } } if let Some(sugg) = sugg { err.span_label(self.span, "invalid cast"); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index e2fc1da5c7..92d7ea2600 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -6,7 +6,7 @@ use super::*; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorReported}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; @@ -15,17 +15,18 @@ use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::layout::MAX_SIMD_LANES; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::util::{Discr, IntTypeExt, Representability}; -use rustc_middle::ty::{self, ParamEnv, RegionKind, ToPredicate, Ty, TyCtxt}; -use rustc_session::config::EntryFnType; +use rustc_middle::ty::util::{Discr, IntTypeExt}; +use rustc_middle::ty::{self, ParamEnv, RegionKind, Ty, TyCtxt}; use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::opaque_types::InferCtxtExt as _; +use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCauseCode}; +use rustc_ty_utils::representability::{self, Representability}; +use std::iter; use std::ops::ControlFlow; pub fn check_wf_new(tcx: TyCtxt<'_>) { @@ -324,29 +325,6 @@ pub(super) fn check_fn<'a, 'tcx>( } fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty); - // Check that the main return type implements the termination trait. - if let Some(term_id) = tcx.lang_items().termination() { - if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) { - let main_id = hir.local_def_id_to_hir_id(def_id); - if main_id == fn_id { - let substs = tcx.mk_substs_trait(declared_ret_ty, &[]); - let trait_ref = ty::TraitRef::new(term_id, substs); - let return_ty_span = decl.output.span(); - let cause = traits::ObligationCause::new( - return_ty_span, - fn_id, - ObligationCauseCode::MainFunctionType, - ); - - inherited.register_predicate(traits::Obligation::new( - cause, - param_env, - trait_ref.without_const().to_predicate(tcx), - )); - } - } - } - // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` if let Some(panic_impl_did) = tcx.lang_items().panic_impl() { if panic_impl_did == hir.local_def_id(fn_id).to_def_id() { @@ -1187,7 +1165,7 @@ pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalD // recursive type. It is only necessary to throw an error on those that // contain themselves. For case 2, there must be an inner type that will be // caught by case 1. - match rty.is_representable(tcx, sp) { + match representability::ty_is_representable(tcx, rty, sp) { Representability::SelfRecursive(spans) => { recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans); return false; @@ -1472,7 +1450,7 @@ fn check_enum<'tcx>( } let mut disr_vals: Vec> = Vec::with_capacity(vs.len()); - for ((_, discr), v) in def.discriminants(tcx).zip(vs) { + for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) { // Check for duplicate discriminant values if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { let variant_did = def.variants[VariantIdx::new(i)].def_id; diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 431e6d70ff..22d3dc6bdc 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id); let ClosureSignatures { bound_sig, liberated_sig } = - self.sig_of_closure(expr_def_id.to_def_id(), decl, body, expected_sig); + self.sig_of_closure(expr.hir_id, expr_def_id.to_def_id(), decl, body, expected_sig); debug!("check_closure: ty_of_closure returns {:?}", liberated_sig); @@ -288,15 +288,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, expected_sig: Option>, ) -> ClosureSignatures<'tcx> { if let Some(e) = expected_sig { - self.sig_of_closure_with_expectation(expr_def_id, decl, body, e) + self.sig_of_closure_with_expectation(hir_id, expr_def_id, decl, body, e) } else { - self.sig_of_closure_no_expectation(expr_def_id, decl, body) + self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body) } } @@ -304,13 +305,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// types that the user gave into a signature. fn sig_of_closure_no_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, ) -> ClosureSignatures<'tcx> { debug!("sig_of_closure_no_expectation()"); - let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let bound_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); self.closure_sigs(expr_def_id, body, bound_sig) } @@ -364,6 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// regions with depth 1, which are bound then by the closure. fn sig_of_closure_with_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -375,7 +378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // expectation if things don't see to match up with what we // expect. if expected_sig.sig.c_variadic() != decl.c_variadic { - return self.sig_of_closure_no_expectation(expr_def_id, decl, body); + return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body); } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { return self.sig_of_closure_with_mismatched_number_of_arguments( expr_def_id, @@ -411,9 +414,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Along the way, it also writes out entries for types that the user // wrote into our typeck results, which are then later used by the privacy // check. - match self.check_supplied_sig_against_expectation(expr_def_id, decl, body, &closure_sigs) { + match self.check_supplied_sig_against_expectation( + hir_id, + expr_def_id, + decl, + body, + &closure_sigs, + ) { Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), - Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body), + Err(_) => return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body), } closure_sigs @@ -460,6 +469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// strategy. fn check_supplied_sig_against_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -469,7 +479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // (See comment on `sig_of_closure_with_expectation` for the // meaning of these letters.) - let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let supplied_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); debug!("check_supplied_sig_against_expectation: supplied_sig={:?}", supplied_sig); @@ -492,13 +502,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The liberated version of this signature should be a subtype // of the liberated form of the expectation. - for ((hir_ty, &supplied_ty), expected_ty) in decl - .inputs - .iter() - .zip(supplied_sig.inputs().skip_binder()) // binder moved to (*) below - .zip(expected_sigs.liberated_sig.inputs()) - // `liberated_sig` is E'. - { + for ((hir_ty, &supplied_ty), expected_ty) in iter::zip( + iter::zip( + decl.inputs, + supplied_sig.inputs().skip_binder(), // binder moved to (*) below + ), + expected_sigs.liberated_sig.inputs(), // `liberated_sig` is E'. + ) { // Instantiate (this part of..) S to S', i.e., with fresh variables. let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars( hir_ty.span, @@ -534,6 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Also, record this closure signature for later. fn supplied_sig_of_closure( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -545,6 +556,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl, body.generator_kind, ); + let bound_vars = self.tcx.late_bound_vars(hir_id); + // First, convert the types that the user supplied (if any). let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_return = match decl.output { @@ -571,13 +584,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, }; - let result = ty::Binder::bind(self.tcx.mk_fn_sig( - supplied_arguments, - supplied_return, - decl.c_variadic, - hir::Unsafety::Normal, - Abi::RustCall, - )); + let result = ty::Binder::bind_with_vars( + self.tcx.mk_fn_sig( + supplied_arguments, + supplied_return, + decl.c_variadic, + hir::Unsafety::Normal, + Abi::RustCall, + ), + bound_vars, + ); debug!("supplied_sig_of_closure: result={:?}", result); diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 94aee87364..236fec94bd 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -973,6 +973,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) { + // Intrinsics are not coercible to function pointers. + if a_sig.abi() == Abi::RustIntrinsic + || a_sig.abi() == Abi::PlatformIntrinsic + || b_sig.abi() == Abi::RustIntrinsic + || b_sig.abi() == Abi::PlatformIntrinsic + { + return Err(TypeError::IntrinsicCast); + } // The signature must match. let a_sig = self.normalize_associated_types_in(new.span, a_sig); let b_sig = self.normalize_associated_types_in(new.span, b_sig); @@ -1440,9 +1448,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // as prior return coercions would not be relevant (#57664). let parent_id = fcx.tcx.hir().get_parent_node(id); let fn_decl = if let Some((expr, blk_id)) = expression { - pointing_at_return_type = fcx.suggest_mismatched_types_on_tail( - &mut err, expr, expected, found, cause.span, blk_id, - ); + pointing_at_return_type = + fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id); let parent = fcx.tcx.hir().get(parent_id); if let (Some(cond_expr), true, false) = ( fcx.tcx.hir().get_if_cause(expr.hir_id), @@ -1487,34 +1494,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if let (Some((expr, _)), Some((fn_decl, _, _))) = (expression, fcx.get_node_fn_decl(parent_item)) { - fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found); + fcx.suggest_missing_break_or_return_expr( + &mut err, expr, fn_decl, expected, found, id, parent_id, + ); } if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) { self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output); } - - if let Some(sp) = fcx.ret_coercion_span.get() { - // If the closure has an explicit return type annotation, - // then a type error may occur at the first return expression we - // see in the closure (if it conflicts with the declared - // return type). Skip adding a note in this case, since it - // would be incorrect. - if !err.span.primary_spans().iter().any(|&span| span == sp) { - let hir = fcx.tcx.hir(); - let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id)); - if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) { - err.span_note( - sp, - &format!( - "return type inferred to be `{}` here", - fcx.resolve_vars_if_possible(expected) - ), - ); - } - } - } - err } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index a30a810793..60ca562f99 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; +use std::iter; use super::{potentially_plural_count, FnCtxt, Inherited}; @@ -224,7 +225,7 @@ fn compare_predicate_entailment<'tcx>( 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), + ty::Binder::bind(impl_m_own_bounds.predicates, tcx), ); for predicate in impl_m_own_bounds { let traits::Normalized { value: predicate, obligations } = @@ -257,14 +258,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)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx)); 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)); + let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -277,9 +278,8 @@ fn compare_predicate_entailment<'tcx>( if let Err(terr) = sub_result { debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); - let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting( - &infcx, param_env, &terr, &cause, impl_m, impl_sig, trait_m, trait_sig, - ); + let (impl_err_span, trait_err_span) = + extract_spans_for_error_reporting(&infcx, &terr, &cause, impl_m, trait_m); cause.make_mut().span = impl_err_span; @@ -290,18 +290,79 @@ fn compare_predicate_entailment<'tcx>( "method `{}` has an incompatible type for trait", trait_m.ident ); - if let TypeError::Mutability = terr { - if let Some(trait_err_span) = trait_err_span { - if let Ok(trait_err_str) = tcx.sess.source_map().span_to_snippet(trait_err_span) + match &terr { + TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) + if trait_m.fn_has_self_parameter => + { + let ty = trait_sig.inputs()[0]; + let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) { + ExplicitSelf::ByValue => "self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Mut) => { + "&mut self".to_owned() + } + _ => format!("self: {}", ty), + }; + + // When the `impl` receiver is an arbitrary self type, like `self: Box`, the + // span points only at the type `Box, but we want to cover the whole + // argument pattern and type. + let impl_m_hir_id = + tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); + let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + ImplItemKind::Fn(ref sig, body) => tcx + .hir() + .body_param_names(body) + .zip(sig.decl.inputs.iter()) + .map(|(param, ty)| param.span.to(ty.span)) + .next() + .unwrap_or(impl_err_span), + _ => bug!("{:?} is not a method", impl_m), + }; + + diag.span_suggestion( + span, + "change the self-receiver type to match the trait", + sugg, + Applicability::MachineApplicable, + ); + } + TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => { + if trait_sig.inputs().len() == *i { + // Suggestion to change output type. We do not suggest in `async` functions + // to avoid complex logic or incorrect output. + let impl_m_hir_id = + tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); + match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + ImplItemKind::Fn(ref sig, _) + if sig.header.asyncness == hir::IsAsync::NotAsync => + { + let msg = "change the output type to match the trait"; + let ap = Applicability::MachineApplicable; + match sig.decl.output { + hir::FnRetTy::DefaultReturn(sp) => { + let sugg = format!("-> {} ", trait_sig.output()); + diag.span_suggestion_verbose(sp, msg, sugg, ap); + } + hir::FnRetTy::Return(hir_ty) => { + let sugg = trait_sig.output().to_string(); + diag.span_suggestion(hir_ty.span, msg, sugg, ap); + } + }; + } + _ => {} + }; + } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { diag.span_suggestion( impl_err_span, - "consider changing the mutability to match the trait", - trait_err_str, + "change the parameter type to match the trait", + trait_ty.to_string(), Applicability::MachineApplicable, ); } } + _ => {} } infcx.note_type_err( @@ -384,90 +445,35 @@ fn check_region_bounds_on_impl_item<'tcx>( fn extract_spans_for_error_reporting<'a, 'tcx>( infcx: &infer::InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, terr: &TypeError<'_>, cause: &ObligationCause<'tcx>, impl_m: &ty::AssocItem, - impl_sig: ty::FnSig<'tcx>, trait_m: &ty::AssocItem, - trait_sig: ty::FnSig<'tcx>, ) -> (Span, Option) { let tcx = infcx.tcx; let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { - ImplItemKind::Fn(ref impl_m_sig, _) => { - (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter()) + let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + ImplItemKind::Fn(ref sig, _) => { + sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) } _ => bug!("{:?} is not a method", impl_m), }; - - match *terr { - TypeError::Mutability => { - if let Some(def_id) = trait_m.def_id.as_local() { - let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind { - TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(), - _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), - }; - - impl_m_iter - .zip(trait_m_iter) - .find(|&(ref impl_arg, ref trait_arg)| { - match (&impl_arg.kind, &trait_arg.kind) { - ( - &hir::TyKind::Rptr(_, ref impl_mt), - &hir::TyKind::Rptr(_, ref trait_mt), - ) - | (&hir::TyKind::Ptr(ref impl_mt), &hir::TyKind::Ptr(ref trait_mt)) => { - impl_mt.mutbl != trait_mt.mutbl - } - _ => false, - } - }) - .map(|(ref impl_arg, ref trait_arg)| (impl_arg.span, Some(trait_arg.span))) - .unwrap_or_else(|| (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id))) - } else { - (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)) + let trait_args = trait_m.def_id.as_local().map(|def_id| { + let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + match tcx.hir().expect_trait_item(trait_m_hir_id).kind { + TraitItemKind::Fn(ref sig, _) => { + sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) } + _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), } - TypeError::Sorts(ExpectedFound { .. }) => { - if let Some(def_id) = trait_m.def_id.as_local() { - let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let (trait_m_output, trait_m_iter) = - match tcx.hir().expect_trait_item(trait_m_hir_id).kind { - TraitItemKind::Fn(ref trait_m_sig, _) => { - (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter()) - } - _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), - }; + }); - let impl_iter = impl_sig.inputs().iter(); - let trait_iter = trait_sig.inputs().iter(); - impl_iter - .zip(trait_iter) - .zip(impl_m_iter) - .zip(trait_m_iter) - .find_map(|(((&impl_arg_ty, &trait_arg_ty), impl_arg), trait_arg)| match infcx - .at(&cause, param_env) - .sub(trait_arg_ty, impl_arg_ty) - { - Ok(_) => None, - Err(_) => Some((impl_arg.span, Some(trait_arg.span))), - }) - .unwrap_or_else(|| { - if infcx - .at(&cause, param_env) - .sup(trait_sig.output(), impl_sig.output()) - .is_err() - { - (impl_m_output.span(), Some(trait_m_output.span())) - } else { - (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)) - } - }) - } else { - (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)) - } + match *terr { + TypeError::ArgumentMutability(i) => { + (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i))) + } + TypeError::ArgumentSorts(ExpectedFound { .. }, i) => { + (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i))) } _ => (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)), } @@ -517,8 +523,7 @@ fn compare_self_type<'tcx>( tcx.sess, impl_m_span, E0185, - "method `{}` has a `{}` declaration in the impl, but \ - not in the trait", + "method `{}` has a `{}` declaration in the impl, but not in the trait", trait_m.ident, self_descr ); @@ -538,8 +543,7 @@ fn compare_self_type<'tcx>( tcx.sess, impl_m_span, E0186, - "method `{}` has a `{}` declaration in the trait, but \ - not in the impl", + "method `{}` has a `{}` declaration in the trait, but not in the impl", trait_m.ident, self_descr ); @@ -792,14 +796,14 @@ fn compare_synthetic_generics<'tcx>( let trait_m_generics = tcx.generics_of(trait_m.def_id); let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, }); let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, }); for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in - impl_m_type_params.zip(trait_m_type_params) + iter::zip(impl_m_type_params, trait_m_type_params) { if impl_synthetic != trait_synthetic { let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id.expect_local()); @@ -996,8 +1000,7 @@ crate fn compare_const_impl<'tcx>( tcx.sess, cause.span, E0326, - "implemented const `{}` has an incompatible type for \ - trait", + "implemented const `{}` has an incompatible type for trait", trait_c.ident ); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index f9f67769e9..e5fcdcfa74 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -37,6 +37,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_missing_parentheses(err, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); + self.report_closure_infered_return_type(err, expected) } // Requires that the two types unify, and prints an error message if @@ -366,6 +367,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + /// If the given `HirId` corresponds to a block with a trailing expression, return that expression + crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> { + match self.tcx.hir().find(hir_id)? { + Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr, + _ => None, + } + } + + /// Returns whether the given expression is an `else if`. + crate fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool { + if let hir::ExprKind::If(..) = expr.kind { + let parent_id = self.tcx.hir().get_parent_node(expr.hir_id); + if let Some(Node::Expr(hir::Expr { + kind: hir::ExprKind::If(_, _, Some(else_expr)), + .. + })) = self.tcx.hir().find(parent_id) + { + return else_expr.hir_id == expr.hir_id; + } + } + false + } + /// This function is used to determine potential "simple" improvements or users' errors and /// provide them useful help. For example: /// @@ -652,6 +676,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let suggestion = if is_struct_pat_shorthand_field { format!("{}: *{}", code, code) + } else if self.is_else_if_block(expr) { + // Don't suggest nonsense like `else *if` + return None; + } else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) { + format!("*{}", sm.span_to_snippet(expr.span).unwrap_or(code)) } else { format!("*{}", code) }; @@ -1033,4 +1062,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => false, } } + + // Report the type inferred by the return statement. + fn report_closure_infered_return_type( + &self, + err: &mut DiagnosticBuilder<'_>, + expected: Ty<'tcx>, + ) { + if let Some(sp) = self.ret_coercion_span.get() { + // If the closure has an explicit return type annotation, + // then a type error may occur at the first return expression we + // see in the closure (if it conflicts with the declared + // return type). Skip adding a note in this case, since it + // would be incorrect. + if !err.span.primary_spans().iter().any(|&span| span == sp) { + let hir = self.tcx.hir(); + let body_owner = hir.body_owned_by(hir.enclosing_body_owner(self.body_id)); + if self.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) { + err.span_note( + sp, + &format!( + "return type inferred to be `{}` here", + self.resolve_vars_if_possible(expected) + ), + ); + } + } + } + } } diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 4d74962d28..de6336b254 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -354,9 +354,9 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_typeck/src/check/expectation.rs b/compiler/rustc_typeck/src/check/expectation.rs index 22be10a731..e9e8103447 100644 --- a/compiler/rustc_typeck/src/check/expectation.rs +++ b/compiler/rustc_typeck/src/check/expectation.rs @@ -104,8 +104,8 @@ impl<'a, 'tcx> Expectation<'tcx> { /// for the program to type-check). `only_has_type` will return /// such a constraint, if it exists. pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { - match self.resolve(fcx) { - ExpectHasType(ty) => Some(ty), + match self { + ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)), NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => { None } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 8951c08bd3..991c2ba693 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -6,7 +6,7 @@ use crate::astconv::AstConv as _; use crate::check::cast; use crate::check::coercion::CoerceMany; use crate::check::fatally_break_rust; -use crate::check::method::{probe, MethodError, SelfSource}; +use crate::check::method::SelfSource; use crate::check::report_unexpected_variant_res; use crate::check::BreakableCtxt; use crate::check::Diverges; @@ -30,7 +30,6 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -162,7 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - debug!(">> type-checking: expr={:?} expected={:?}", expr, expected); + debug!(">> type-checking: expected={:?}, expr={:?} ", expected, expr); // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block // without the final expr (e.g. `try { return; }`). We don't want to generate an @@ -225,7 +224,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - debug!("check_expr_kind(expr={:?}, expected={:?})", expr, expected); + debug!("check_expr_kind(expected={:?}, expr={:?})", expected, expr); let tcx = self.tcx; match expr.kind { @@ -461,7 +460,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 } - fn check_expr_path(&self, qpath: &hir::QPath<'_>, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> { + fn check_expr_path( + &self, + qpath: &'tcx hir::QPath<'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 ty = match res { @@ -600,7 +603,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &cause, &mut |mut err| { self.suggest_mismatched_types_on_tail( - &mut err, expr, ty, e_ty, cause.span, target_id, + &mut err, expr, ty, e_ty, target_id, ); if let Some(val) = ty_kind_suggestion(ty) { let label = destination @@ -947,7 +950,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Err(error) => { if segment.ident.name != kw::Empty { - self.report_extended_method_error(segment, span, args, rcvr_t, error); + if let Some(mut err) = self.report_method_error( + span, + rcvr_t, + segment.ident, + SelfSource::MethodCall(&args[0]), + error, + Some(args), + ) { + err.emit(); + } } Err(()) } @@ -964,59 +976,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - fn report_extended_method_error( - &self, - segment: &hir::PathSegment<'_>, - span: Span, - args: &'tcx [hir::Expr<'tcx>], - rcvr_t: Ty<'tcx>, - error: MethodError<'tcx>, - ) { - let rcvr = &args[0]; - let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| { - if let Some(new_rcvr_t) = new_rcvr_t { - if let Ok(pick) = self.lookup_probe( - span, - segment.ident, - new_rcvr_t, - rcvr, - probe::ProbeScope::AllTraits, - ) { - debug!("try_alt_rcvr: pick candidate {:?}", pick); - // Make sure the method is defined for the *actual* receiver: - // we don't want to treat `Box` as a receiver if - // it only works because of an autoderef to `&self` - if pick.autoderefs == 0 { - err.span_label( - pick.item.ident.span, - &format!("the method is available for `{}` here", new_rcvr_t), - ); - } - } - } - }; - - if let Some(mut err) = self.report_method_error( - span, - rcvr_t, - segment.ident, - SelfSource::MethodCall(rcvr), - error, - Some(args), - ) { - if let ty::Adt(..) = rcvr_t.kind() { - // Try alternative arbitrary self types that could fulfill this call. - // FIXME: probe for all types that *could* be arbitrary self-types, not - // just this list. - try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox)); - try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::Pin)); - try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc)); - try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc)); - } - err.emit(); - } - } - fn check_expr_cast( &self, e: &'tcx hir::Expr<'tcx>, @@ -2128,7 +2087,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { for (op, _op_sp) in asm.operands { match op { - hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::Const { expr } => { + hir::InlineAsmOperand::In { expr, .. } => { self.check_expr_asm_operand(expr, true); } hir::InlineAsmOperand::Out { expr, .. } => { @@ -2145,6 +2104,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_asm_operand(out_expr, false); } } + hir::InlineAsmOperand::Const { anon_const } => { + self.to_const(anon_const); + } hir::InlineAsmOperand::Sym { expr } => { self.check_expr(expr); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index dc8a804bfe..a50f8e1c65 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -42,6 +42,7 @@ use rustc_trait_selection::traits::{ }; use std::collections::hash_map::Entry; +use std::iter; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -904,12 +905,12 @@ 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<'b>( + pub fn resolve_ty_and_res_ufcs( &self, - qpath: &'b QPath<'b>, + qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, - ) -> (Res, Option>, &'b [hir::PathSegment<'b>]) { + ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span); let (ty, qself, item_segment) = match *qpath { QPath::Resolved(ref opt_qself, ref path) => { @@ -1146,7 +1147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ( hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }), hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }), - ) if last_bounds.iter().zip(exp_bounds.iter()).all(|(left, right)| { + ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| { match (left, right) { ( hir::GenericBound::Trait(tl, ml), @@ -1405,7 +1406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.fcx.to_ty(ty).into() } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.fcx.const_arg_to_const(&ct.value, param.def_id).into() } _ => unreachable!(), @@ -1443,10 +1444,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.var_for_def(self.span, param) } } - GenericParamDefKind::Const => { - // FIXME(const_generics_defaults) - // No const parameters were provided, we have to infer them. - self.fcx.var_for_def(self.span, param) + GenericParamDefKind::Const { has_default, .. } => { + if !infer_args && has_default { + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() + } else { + self.fcx.var_for_def(self.span, param) + } } } } @@ -1459,7 +1464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[][..], has_self, self_ty, - arg_count, + &arg_count, &mut CreateCtorSubstsContext { fcx: self, span, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index c92c7f7ad0..80b5a9d4e6 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -23,6 +23,7 @@ use rustc_span::{self, MultiSpan, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; use crate::structured_errors::StructuredDiagnostic; +use std::iter; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -108,7 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // All the input types from the fn signature must outlive the call // so as to validate implied bounds. - for (&fn_input_ty, arg_expr) in fn_inputs.iter().zip(args.iter()) { + for (&fn_input_ty, arg_expr) in iter::zip(fn_inputs, args) { self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index f90159efb5..d6b1e56316 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -8,7 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, ItemKind, Node}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node, Stmt, StmtKind}; use rustc_infer::infer; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; @@ -41,21 +41,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, - cause_span: Span, blk_id: hir::HirId, ) -> bool { let expr = expr.peel_drop_temps(); // If the expression is from an external macro, then do not suggest // adding a semicolon, because there's nowhere to put it. // See issue #81943. - if expr.can_have_side_effects() && !in_external_macro(self.tcx.sess, cause_span) { - self.suggest_missing_semicolon(err, expr, expected, cause_span); + if expr.can_have_side_effects() && !in_external_macro(self.tcx.sess, expr.span) { + self.suggest_missing_semicolon(err, expr, expected); } 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); - self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found); + let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); + self.suggest_missing_break_or_return_expr( + err, expr, &fn_decl, expected, found, blk_id, fn_id, + ); } pointing_at_return_type } @@ -204,6 +206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) { + let expr = expr.peel_blocks(); if let Some((sp, msg, suggestion, applicability)) = self.check_ref(expr, found, expected) { err.span_suggestion(sp, msg, suggestion, applicability); } else if let (ty::FnDef(def_id, ..), true) = @@ -218,8 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span); let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id); if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { - let mut suggestions = iter::repeat(&expr_text) - .zip(methods.iter()) + let mut suggestions = iter::zip(iter::repeat(&expr_text), &methods) .filter_map(|(receiver, method)| { let method_call = format!(".{}()", method.ident); if receiver.ends_with(&method_call) { @@ -388,7 +390,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, expression: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, - cause_span: Span, ) { if expected.is_unit() { // `BlockTailExpression` only relevant if the tail expr would be @@ -403,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if expression.can_have_side_effects() => { err.span_suggestion( - cause_span.shrink_to_hi(), + expression.span.shrink_to_hi(), "consider using a semicolon here", ";".to_string(), Applicability::MachineApplicable, @@ -473,21 +474,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(in super::super) fn suggest_missing_return_expr( + pub(in super::super) fn suggest_missing_break_or_return_expr( &self, err: &mut DiagnosticBuilder<'_>, expr: &'tcx hir::Expr<'tcx>, fn_decl: &hir::FnDecl<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, + id: hir::HirId, + fn_id: hir::HirId, ) { if !expected.is_unit() { return; } let found = self.resolve_vars_with_obligations(found); + + let in_loop = self.is_loop(id) + || self.tcx.hir().parent_iter(id).any(|(parent_id, _)| self.is_loop(parent_id)); + + let in_local_statement = self.is_local_statement(id) + || self + .tcx + .hir() + .parent_iter(id) + .any(|(parent_id, _)| self.is_local_statement(parent_id)); + + if in_loop && in_local_statement { + err.multipart_suggestion( + "you might have meant to break the loop with this value", + vec![ + (expr.span.shrink_to_lo(), "break ".to_string()), + (expr.span.shrink_to_hi(), ";".to_string()), + ], + Applicability::MaybeIncorrect, + ); + return; + } + if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = >::ast_ty_to_ty(self, ty); - let ty = self.tcx.erase_late_bound_regions(Binder::bind(ty)); + 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(expr.span, ty); if self.can_coerce(found, ty) { err.multipart_suggestion( @@ -513,4 +540,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None); } } + + fn is_loop(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. })) + } + + fn is_local_statement(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) + } } diff --git a/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_typeck/src/check/gather_locals.rs index 4c5d16d0b7..2683e886ee 100644 --- a/compiler/rustc_typeck/src/check/gather_locals.rs +++ b/compiler/rustc_typeck/src/check/gather_locals.rs @@ -6,7 +6,6 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_middle::ty::Ty; use rustc_span::{sym, Span}; use rustc_trait_selection::traits; -use std::mem; pub(super) struct GatherLocalsVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -14,12 +13,12 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> { // 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. - outermost_fn_param_pat: bool, + outermost_fn_param_pat: Option, } 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: false } + Self { fcx, parent_id, outermost_fn_param_pat: None } } fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option>) -> Ty<'tcx> { @@ -92,7 +91,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, true); + let old_outermost_fn_param_pat = self.outermost_fn_param_pat.replace(param.ty_span); intravisit::walk_param(self, param); self.outermost_fn_param_pat = old_outermost_fn_param_pat; } @@ -102,12 +101,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { if let PatKind::Binding(_, _, ident, _) = p.kind { let var_ty = self.assign(p.span, p.hir_id, None); - if self.outermost_fn_param_pat { + if let Some(ty_span) = self.outermost_fn_param_pat { if !self.fcx.tcx.features().unsized_fn_params { self.fcx.require_type_is_sized( var_ty, p.span, - traits::SizedArgumentType(Some(p.span)), + traits::SizedArgumentType(Some(ty_span)), ); } } else { @@ -123,7 +122,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { var_ty ); } - let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, false); + let old_outermost_fn_param_pat = self.outermost_fn_param_pat.take(); intravisit::walk_pat(self, p); self.outermost_fn_param_pat = old_outermost_fn_param_pat; } diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 91708465b3..e40aa91485 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -186,7 +186,10 @@ pub fn resolve_interior<'a, 'tcx>( // which means that none of the regions inside relate to any other, even if // typeck had previously found constraints that would cause them to be related. let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| { - let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon(counter), + }; let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); counter += 1; r @@ -202,11 +205,15 @@ pub fn resolve_interior<'a, 'tcx>( // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); - let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list)); + let bound_vars = fcx.tcx.mk_bound_variable_kinds( + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + ); + let witness = + fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone())); // Store the generator types and spans into the typeck results for this generator. visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types = - ty::Binder::bind(type_causes); + ty::Binder::bind_with_vars(type_causes, bound_vars); debug!( "types in generator after region replacement {:?}, span = {:?}", diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 990ed5abdb..5741b6824b 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -101,12 +101,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let intrinsic_name = tcx.item_name(it.def_id.to_def_id()); let name_str = intrinsic_name.as_str(); + let bound_vars = tcx.mk_bound_variable_kinds( + [ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)] + .iter() + .copied(), + ); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { - let region = tcx - .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrAnon(0) })); - let env_region = - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv })); + let region = tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }, + )); + let env_region = tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, + )); let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) }) @@ -305,7 +314,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; - let br = ty::BoundRegion { kind: ty::BrAnon(0) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; ( 1, vec![ @@ -366,7 +375,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (n_tps, inputs, output, unsafety) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); - let sig = ty::Binder::bind(sig); + let sig = ty::Binder::bind_with_vars(sig, bound_vars); equate_intrinsic_type(tcx, it, n_tps, sig) } @@ -398,8 +407,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_fpow | sym::simd_saturating_add | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), - sym::simd_neg => (1, vec![param(0)], param(0)), - sym::simd_fsqrt + sym::simd_neg + | sym::simd_fsqrt | sym::simd_fsin | sym::simd_fcos | sym::simd_fexp @@ -408,8 +417,10 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_flog10 | sym::simd_flog | sym::simd_fabs + | sym::simd_ceil | sym::simd_floor - | sym::simd_ceil => (1, vec![param(0)], param(0)), + | sym::simd_round + | sym::simd_trunc => (1, vec![param(0)], param(0)), sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)), sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)), sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)), diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 4a2dd6faf0..f546a0d896 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, Ty}; use rustc_span::Span; use rustc_trait_selection::traits; +use std::iter; use std::ops::Deref; struct ConfirmContext<'a, 'tcx> { @@ -118,7 +119,7 @@ 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)); + let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx)); self.add_obligations(method_ty, all_substs, method_predicates); } @@ -358,7 +359,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.cfcx.to_ty(ty).into() } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.cfcx.const_arg_to_const(&ct.value, param.def_id).into() } _ => unreachable!(), @@ -380,7 +381,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { parent_substs, false, None, - arg_count_correct, + &arg_count_correct, &mut MethodSubstsCtxt { cfcx: self, pick, seg }, ) } @@ -496,10 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We don't care about regions here. .filter_map(|obligation| match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => { - let span = predicates - .predicates - .iter() - .zip(predicates.spans.iter()) + let span = iter::zip(&predicates.predicates, &predicates.spans) .find_map( |(p, span)| { if *p == obligation.predicate { Some(*span) } else { None } @@ -552,7 +550,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { upcast_trait_refs.into_iter().next().unwrap() } - fn replace_bound_vars_with_fresh_vars(&self, value: ty::Binder) -> T + fn replace_bound_vars_with_fresh_vars(&self, value: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 9a3d1e42b7..bd7ffd057b 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -45,6 +45,7 @@ pub struct MethodCallee<'tcx> { pub sig: ty::FnSig<'tcx>, } +#[derive(Debug)] pub enum MethodError<'tcx> { // Did not find an applicable method, but we did find various near-misses that may work. NoMatch(NoMatchData<'tcx>), @@ -66,6 +67,7 @@ pub enum MethodError<'tcx> { // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which // could lead to matches if satisfied, and a list of not-in-scope traits which may work. +#[derive(Debug)] pub struct NoMatchData<'tcx> { pub static_candidates: Vec, pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, @@ -308,7 +310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct a trait-reference `self_ty : Trait` let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => {} + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} GenericParamDefKind::Type { .. } => { if param.index == 0 { return self_ty.into(); @@ -397,7 +399,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)); + let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx)); debug!( "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 3006cabc63..c79743f2d7 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -83,6 +83,8 @@ struct ProbeContext<'a, 'tcx> { unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, is_suggestion: IsSuggestion, + + scope_expr_id: hir::HirId, } impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { @@ -156,7 +158,7 @@ enum ProbeResult { /// When adjusting a receiver we often want to do one of /// -/// - Add a `&` (or `&mut`), converting the recevier from `T` to `&T` (or `&mut T`) +/// - Add a `&` (or `&mut`), converting the receiver from `T` to `&T` (or `&mut T`) /// - If the receiver has type `*mut T`, convert it to `*const T` /// /// This type tells us which one to do. @@ -448,6 +450,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { orig_values, steps.steps, is_suggestion, + scope_expr_id, ); probe_cx.assemble_inherent_candidates(); @@ -547,6 +550,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { orig_steps_var_values: OriginalQueryValues<'tcx>, steps: Lrc>>, is_suggestion: IsSuggestion, + scope_expr_id: hir::HirId, ) -> ProbeContext<'a, 'tcx> { ProbeContext { fcx, @@ -564,6 +568,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { private_candidate: None, unsatisfied_predicates: Vec::new(), is_suggestion, + scope_expr_id, } } @@ -1312,7 +1317,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ) { self.tcx.struct_span_lint_hir( lint::builtin::UNSTABLE_NAME_COLLISIONS, - self.fcx.body_id, + self.scope_expr_id, self.span, |lint| { let def_kind = stable_pick.item.kind.as_def_kind(); @@ -1456,6 +1461,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } TraitCandidate(trait_ref) => { + if let Some(method_name) = self.method_name { + // Some trait methods are excluded for arrays before 2021. + // (`array.into_iter()` wants a slice iterator for compatibility.) + if self_ty.is_array() && !method_name.span.rust_2021() { + let trait_def = self.tcx.trait_def(trait_ref.def_id); + if trait_def.skip_array_during_method_dispatch { + return ProbeResult::NoMatch; + } + } + } let predicate = trait_ref.without_const().to_predicate(self.tcx); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { @@ -1594,6 +1609,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.orig_steps_var_values.clone(), steps, IsSuggestion(true), + self.scope_expr_id, ); pcx.allow_similar_names = true; pcx.assemble_inherent_candidates(); @@ -1700,7 +1716,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // In general, during probe we erase regions. self.tcx.lifetimes.re_erased.into() } - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { self.var_for_def(self.span, param) } } @@ -1753,7 +1769,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// region got replaced with the same variable, which requires a bit more coordination /// and/or tracking the substitution and /// so forth. - fn erase_late_bound_regions(&self, value: ty::Binder) -> T + fn erase_late_bound_regions(&self, value: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { @@ -1762,7 +1778,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// Finds the method with the appropriate name (or return type, as the case may be). If /// `allow_similar_names` is set, find methods with close-matching names. - fn impl_or_trait_item(&self, def_id: DefId) -> Vec { + // The length of the returned iterator is nearly always 0 or 1 and this + // method is fairly hot. + fn impl_or_trait_item(&self, def_id: DefId) -> SmallVec<[ty::AssocItem; 1]> { if let Some(name) = self.method_name { if self.allow_similar_names { let max_dist = max(name.as_str().len(), 3) / 3; @@ -1778,7 +1796,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { self.fcx .associated_item(def_id, name, Namespace::ValueNS) - .map_or_else(Vec::new, |x| vec![x]) + .map_or_else(SmallVec::new, |x| SmallVec::from_buf([x])) } } else { self.tcx.associated_items(def_id).in_definition_order().copied().collect() diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 13757ac413..b2e4e7a981 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -68,12 +68,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn report_method_error<'b>( + pub fn report_method_error( &self, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, - source: SelfSource<'b>, + source: SelfSource<'tcx>, error: MethodError<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> Option> { @@ -323,8 +323,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( lit.span, &format!( - "you must specify a concrete type for \ - this numeric value, like `{}`", + "you must specify a concrete type for this numeric value, \ + like `{}`", concrete_type ), format!("{}_{}", snippet, concrete_type), @@ -579,6 +579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut restrict_type_params = false; + let mut unsatisfied_bounds = false; if !unsatisfied_predicates.is_empty() { let def_span = |def_id| { self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)) @@ -739,6 +740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(&format!( "the following trait bounds were not satisfied:\n{bound_list}" )); + unsatisfied_bounds = true; } } @@ -752,6 +754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, out_of_scope_traits, &unsatisfied_predicates, + unsatisfied_bounds, ); } @@ -975,16 +978,100 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn suggest_traits_to_import<'b>( + fn suggest_traits_to_import( &self, err: &mut DiagnosticBuilder<'_>, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, - source: SelfSource<'b>, + source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec, unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option>)], + unsatisfied_bounds: bool, ) { + let mut alt_rcvr_sugg = false; + if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) { + debug!(?span, ?item_name, ?rcvr_ty, ?rcvr); + let skippable = [ + self.tcx.lang_items().clone_trait(), + self.tcx.lang_items().deref_trait(), + self.tcx.lang_items().deref_mut_trait(), + self.tcx.lang_items().drop_trait(), + ]; + // Try alternative arbitrary self types that could fulfill this call. + // FIXME: probe for all types that *could* be arbitrary self-types, not + // just this list. + for (rcvr_ty, post) in &[ + (rcvr_ty, ""), + (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "), + (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"), + ] { + if let Ok(pick) = self.lookup_probe( + span, + item_name, + rcvr_ty, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + // If the method is defined for the receiver we have, it likely wasn't `use`d. + // We point at the method, but we just skip the rest of the check for arbitrary + // self types and rely on the suggestion to `use` the trait from + // `suggest_valid_traits`. + let did = Some(pick.item.container.id()); + let skip = skippable.contains(&did); + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", rcvr_ty), + ); + } + break; + } + for (rcvr_ty, pre) in &[ + (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"), + (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"), + (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"), + (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"), + ] { + if let Some(new_rcvr_t) = *rcvr_ty { + if let Ok(pick) = self.lookup_probe( + span, + item_name, + new_rcvr_t, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + debug!("try_alt_rcvr: pick candidate {:?}", pick); + let did = Some(pick.item.container.id()); + // We don't want to suggest a container type when the missing + // method is `.clone()` or `.deref()` otherwise we'd suggest + // `Arc::new(foo).clone()`, which is far from what the user wants. + let skip = skippable.contains(&did); + // Make sure the method is defined for the *actual* receiver: we don't + // want to treat `Box` as a receiver if it only works because of + // an autoderef to `&self` + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + err.multipart_suggestion( + "consider wrapping the receiver expression with the \ + appropriate type", + vec![ + (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)), + (rcvr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + // We don't care about the other suggestions. + alt_rcvr_sugg = true; + } + } + } + } + } + } if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } @@ -1075,6 +1162,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the method might not be found because of this arbitrary self type", ); } + if alt_rcvr_sugg { + return; + } if !candidates.is_empty() { // Sort from most relevant to least relevant. @@ -1284,7 +1374,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks whether there is a local type somewhere in the chain of /// autoderefs of `rcvr_ty`. - fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool { + fn type_derefs_to_local( + &self, + span: Span, + rcvr_ty: Ty<'tcx>, + source: SelfSource<'tcx>, + ) -> bool { fn is_local(ty: Ty<'_>) -> bool { match ty.kind() { ty::Adt(def, _) => def.did.is_local(), @@ -1310,7 +1405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum SelfSource<'a> { QPath(&'a hir::Ty<'a>), MethodCall(&'a hir::Expr<'a> /* rcvr */), diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index ad9bb70377..cb7589318d 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -116,7 +116,6 @@ 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::WithConstness; use rustc_middle::ty::{self, RegionKind, Ty, TyCtxt, UserType}; use rustc_session::config; use rustc_session::parse::feature_err; @@ -497,6 +496,7 @@ fn typeck_with_fallback<'tcx>( let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); >::ty_of_fn( &fcx, + id, header.unsafety, header.abi, decl, @@ -539,6 +539,25 @@ fn typeck_with_fallback<'tcx>( kind: TypeVariableOriginKind::TypeInference, span, }), + Node::Ty(&hir::Ty { + kind: hir::TyKind::Typeof(ref anon_const), .. + }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span, + }), + Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(ia), .. }) + if ia.operands.iter().any(|(op, _op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } => { + anon_const.hir_id == id + } + _ => false, + }) => + { + fcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + }) + } _ => fallback(), }, _ => fallback(), diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 79c544bd38..53593b9bab 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -861,7 +861,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_tuple_struct( &self, pat: &'tcx Pat<'tcx>, - qpath: &hir::QPath<'_>, + qpath: &'tcx hir::QPath<'tcx>, subpats: &'tcx [&'tcx Pat<'tcx>], ddpos: Option, expected: Ty<'tcx>, diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 8a4c69b5ac..751eebb9f9 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -30,11 +30,11 @@ //! then mean that all later passes would have to check for these figments //! and report an error, and it just seems like more mess in the end.) -use super::writeback::Resolver; use super::FnCtxt; use crate::expr_use_visitor as euv; use rustc_data_structures::fx::FxIndexMap; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; @@ -42,7 +42,6 @@ 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::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt, TypeckResults, UpvarSubsts}; use rustc_session::lint; use rustc_span::sym; @@ -51,6 +50,8 @@ use rustc_span::{MultiSpan, Span, Symbol}; use rustc_index::vec::Idx; use rustc_target::abi::VariantIdx; +use std::iter; + /// Describe the relationship between the paths of two places /// eg: /// - `foo` is ancestor of `foo.bar.baz` @@ -91,7 +92,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.kind { let body = self.fcx.tcx.hir().body(body_id); self.visit_body(body); - self.fcx.analyze_closure(expr.hir_id, expr.span, body, cc); + self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc); } intravisit::walk_expr(self, expr); @@ -104,6 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, closure_hir_id: hir::HirId, span: Span, + body_id: hir::BodyId, body: &'tcx hir::Body<'tcx>, capture_clause: hir::CaptureBy, ) { @@ -167,7 +169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); if should_do_migration_analysis(self.tcx, closure_hir_id) { - self.perform_2229_migration_anaysis(closure_def_id, capture_clause, span, body); + self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span); } // We now fake capture information for all variables that are mentioned within the closure @@ -465,20 +467,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn perform_2229_migration_anaysis( &self, closure_def_id: DefId, + body_id: hir::BodyId, capture_clause: hir::CaptureBy, span: Span, - body: &'tcx hir::Body<'tcx>, ) { let need_migrations = self.compute_2229_migrations( closure_def_id, span, capture_clause, - body, self.typeck_results.borrow().closure_min_captures.get(&closure_def_id), ); if !need_migrations.is_empty() { - let migrations_text = migration_suggestion_for_2229(self.tcx, &need_migrations); + let (migration_string, migrated_variables_concat) = + migration_suggestion_for_2229(self.tcx, &need_migrations); 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); @@ -490,7 +492,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut diagnostics_builder = lint.build( "drop order affected for closure because of `capture_disjoint_fields`", ); - diagnostics_builder.note(&migrations_text); + 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) { + Ok(s) => { + let trimmed = s.trim_start(); + + // If the closure contains a block then replace the opening brace + // with "{ let _ = (..); " + let sugg = if let Some('{') = trimmed.chars().next() { + format!("{{ {}; {}", migration_string, &trimmed[1..]) + } else { + format!("{{ {}; {} }}", migration_string, s) + }; + (sugg, Applicability::MachineApplicable) + } + Err(_) => (migration_string.clone(), Applicability::HasPlaceholders), + }; + + let diagnostic_msg = format!( + "add a dummy let to cause {} to be fully captured", + migrated_variables_concat + ); + + diagnostics_builder.span_suggestion( + closure_body_span, + &diagnostic_msg, + sugg, + app, + ); diagnostics_builder.emit(); }, ); @@ -511,19 +541,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_def_id: DefId, closure_span: Span, closure_clause: hir::CaptureBy, - body: &'tcx hir::Body<'tcx>, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, ) -> Vec { - fn resolve_ty>( - fcx: &FnCtxt<'_, 'tcx>, - span: Span, - body: &'tcx hir::Body<'tcx>, - ty: T, - ) -> T { - let mut resolver = Resolver::new(fcx, &span, body); - ty.fold_with(&mut resolver) - } - let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { upvars } else { @@ -533,7 +552,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut need_migrations = Vec::new(); for (&var_hir_id, _) in upvars.iter() { - let ty = resolve_ty(self, closure_span, body, self.node_ty(var_hir_id)); + let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); if !ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { continue; @@ -634,7 +653,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// `w[c]`. /// Notation: /// - Ty(place): Type of place - /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_projs` + /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_by_move_projs` /// respectively. /// ``` /// (Ty(w), [ &[p, x], &[c] ]) @@ -695,7 +714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_def_id: DefId, closure_span: Span, base_path_ty: Ty<'tcx>, - captured_projs: Vec<&[Projection<'tcx>]>, + captured_by_move_projs: Vec<&[Projection<'tcx>]>, ) -> bool { let needs_drop = |ty: Ty<'tcx>| { ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) @@ -720,9 +739,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // eg. If `a.b` is captured and we are processing `a.b`, then we can't have the closure also // capture `a.b.c`, because that voilates min capture. - let is_completely_captured = captured_projs.iter().any(|projs| projs.is_empty()); + let is_completely_captured = captured_by_move_projs.iter().any(|projs| projs.is_empty()); - assert!(!is_completely_captured || (captured_projs.len() == 1)); + assert!(!is_completely_captured || (captured_by_move_projs.len() == 1)); if is_completely_captured { // The place is captured entirely, so doesn't matter if needs dtor, it will be drop @@ -730,23 +749,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } + if captured_by_move_projs.is_empty() { + return needs_drop(base_path_ty); + } + if is_drop_defined_for_ty { // If drop is implemented for this type then we need it to be fully captured, - // which we know it is not because of the previous check. Therefore we need to - // do migrate. - return true; - } + // and we know it is not completely captured because of the previous checks. - if captured_projs.is_empty() { - return needs_drop(base_path_ty); + // Note that this is a bug in the user code that will be reported by the + // borrow checker, since we can't move out of drop types. + + // The bug exists in the user's code pre-migration, and we don't migrate here. + return false; } match base_path_ty.kind() { // Observations: - // - `captured_projs` is not empty. Therefore we can call - // `captured_projs.first().unwrap()` safely. - // - All entries in `captured_projs` have atleast one projection. - // Therefore we can call `captured_projs.first().unwrap().first().unwrap()` safely. + // - `captured_by_move_projs` is not empty. Therefore we can call + // `captured_by_move_projs.first().unwrap()` safely. + // - All entries in `captured_by_move_projs` have atleast one projection. + // Therefore we can call `captured_by_move_projs.first().unwrap().first().unwrap()` safely. // We don't capture derefs in case of move captures, which would have be applied to // access any further paths. @@ -756,19 +779,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(def, substs) => { // Multi-varaint enums are captured in entirety, - // which would've been handled in the case of single empty slice in `captured_projs`. + // which would've been handled in the case of single empty slice in `captured_by_move_projs`. assert_eq!(def.variants.len(), 1); // Only Field projections can be applied to a non-box Adt. assert!( - captured_projs.iter().all(|projs| matches!( + captured_by_move_projs.iter().all(|projs| matches!( projs.first().unwrap().kind, ProjectionKind::Field(..) )) ); def.variants.get(VariantIdx::new(0)).unwrap().fields.iter().enumerate().any( |(i, field)| { - let paths_using_field = captured_projs + let paths_using_field = captured_by_move_projs .iter() .filter_map(|projs| { if let ProjectionKind::Field(field_idx, _) = @@ -795,14 +818,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Tuple(..) => { // Only Field projections can be applied to a tuple. assert!( - captured_projs.iter().all(|projs| matches!( + captured_by_move_projs.iter().all(|projs| matches!( projs.first().unwrap().kind, ProjectionKind::Field(..) )) ); base_path_ty.tuple_fields().enumerate().any(|(i, element_ty)| { - let paths_using_field = captured_projs + let paths_using_field = captured_by_move_projs .iter() .filter_map(|projs| { if let ProjectionKind::Field(field_idx, _) = projs.first().unwrap().kind @@ -1528,12 +1551,29 @@ fn should_do_migration_analysis(tcx: TyCtxt<'_>, closure_id: hir::HirId) -> bool !matches!(level, lint::Level::Allow) } -fn migration_suggestion_for_2229(tcx: TyCtxt<'_>, need_migrations: &Vec) -> String { - let need_migrations_strings = - need_migrations.iter().map(|v| format!("{}", var_name(tcx, *v))).collect::>(); - let migrations_list_concat = need_migrations_strings.join(", "); +/// Return a two string tuple (s1, s2) +/// - s1: Line of code that is needed for the migration: eg: `let _ = (&x, ...)`. +/// - s2: Comma separated names of the variables being migrated. +fn migration_suggestion_for_2229( + tcx: TyCtxt<'_>, + need_migrations: &Vec, +) -> (String, String) { + let need_migrations_variables = + need_migrations.iter().map(|v| var_name(tcx, *v)).collect::>(); + + let migration_ref_concat = + need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::>().join(", "); + + let migration_string = if 1 == need_migrations.len() { + format!("let _ = {}", migration_ref_concat) + } else { + format!("let _ = ({})", migration_ref_concat) + }; + + let migrated_variables_concat = + need_migrations_variables.iter().map(|v| format!("`{}`", v)).collect::>().join(", "); - format!("drop(&({}));", migrations_list_concat) + (migration_string, migrated_variables_concat) } /// Helper function to determine if we need to escalate CaptureKind from @@ -1548,7 +1588,7 @@ fn migration_suggestion_for_2229(tcx: TyCtxt<'_>, need_migrations: &Vec, param: &hir::GenericParam<'_>) { ), ) } else { - tcx.sess - .struct_span_err( - hir_ty.span, - &format!( - "{} is forbidden as the type of a const generic parameter", - unsupported_type - ), - ) - .note("the only supported types are integers, `bool` and `char`") - .help("more complex types are supported with `#![feature(const_generics)]`") - .emit() + let mut err = tcx.sess.struct_span_err( + hir_ty.span, + &format!( + "{} is forbidden as the type of a const generic parameter", + unsupported_type + ), + ); + err.note("the only supported types are integers, `bool` and `char`"); + if tcx.sess.is_nightly_build() { + err.help( + "more complex types are supported with `#![feature(const_generics)]`", + ); + } + err.emit() } }; @@ -713,10 +717,11 @@ fn check_where_clauses<'tcx, 'fcx>( let generics = tcx.generics_of(def_id); let is_our_default = |def: &ty::GenericParamDef| match def.kind { - GenericParamDefKind::Type { has_default, .. } => { + GenericParamDefKind::Type { has_default, .. } + | GenericParamDefKind::Const { has_default } => { has_default && def.index >= generics.parent_count as u32 } - _ => unreachable!(), + GenericParamDefKind::Lifetime => unreachable!(), }; // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. @@ -726,20 +731,36 @@ fn check_where_clauses<'tcx, 'fcx>( // // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. for param in &generics.params { - if let GenericParamDefKind::Type { .. } = param.kind { - if is_our_default(¶m) { - let ty = fcx.tcx.type_of(param.def_id); - // Ignore dependent defaults -- that is, where the default of one type - // parameter includes another (e.g., ``). In those cases, we can't - // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { + match param.kind { + GenericParamDefKind::Type { .. } => { + if is_our_default(¶m) { + let ty = fcx.tcx.type_of(param.def_id); + // Ignore dependent defaults -- that is, where the default of one type + // parameter includes another (e.g., ``). In those cases, we can't + // be sure if it will error or not as user might always specify the other. + if !ty.needs_subst() { + fcx.register_wf_obligation( + ty.into(), + fcx.tcx.def_span(param.def_id), + ObligationCauseCode::MiscObligation, + ); + } + } + } + GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): Figure out if this + // is the behavior we want, see the comment further below. + if is_our_default(¶m) { + let default_ct = tcx.const_param_default(param.def_id); fcx.register_wf_obligation( - ty.into(), + default_ct.into(), fcx.tcx.def_span(param.def_id), ObligationCauseCode::MiscObligation, ); } } + // Doesn't have defaults. + GenericParamDefKind::Lifetime => {} } } @@ -771,9 +792,25 @@ fn check_where_clauses<'tcx, 'fcx>( 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); + // ... and it's not a dependent default, ... + if !default_ct.needs_subst() { + // ... then substitute it with the default. + return default_ct.into(); + } + } - GenericParamDefKind::Const => { - // FIXME(const_generics_defaults) fcx.tcx.mk_param_from_def(param) } } @@ -857,7 +894,7 @@ fn check_where_clauses<'tcx, 'fcx>( debug!("check_where_clauses: predicates={:?}", predicates.predicates); assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = - predicates.predicates.iter().zip(predicates.spans.iter()).flat_map(|(&p, &sp)| { + iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| { traits::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, sp) }); @@ -879,8 +916,8 @@ fn check_fn_or_method<'fcx, 'tcx>( let sig = fcx.normalize_associated_types_in(span, sig); let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - for (&input_ty, span) in sig.inputs().iter().zip(hir_decl.inputs.iter().map(|t| t.span)) { - fcx.register_wf_obligation(input_ty.into(), span, ObligationCauseCode::MiscObligation); + for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) { + fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::MiscObligation); } implied_bounds.extend(sig.inputs()); @@ -1060,13 +1097,14 @@ fn check_method_receiver<'fcx, 'tcx>( 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)); + 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.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) { diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 9a183ed9e6..e472add6e8 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -675,7 +675,7 @@ impl Locatable for hir::HirId { /// The Resolver. This is the type folding engine that detects /// unresolved types and so forth. -crate struct Resolver<'cx, 'tcx> { +struct Resolver<'cx, 'tcx> { tcx: TyCtxt<'tcx>, infcx: &'cx InferCtxt<'cx, 'tcx>, span: &'cx dyn Locatable, @@ -686,7 +686,7 @@ crate struct Resolver<'cx, 'tcx> { } impl<'cx, 'tcx> Resolver<'cx, 'tcx> { - crate fn new( + fn new( fcx: &'cx FnCtxt<'cx, 'tcx>, span: &'cx dyn Locatable, body: &'tcx hir::Body<'tcx>, diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs index 2965409999..c69389e7b4 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs @@ -24,8 +24,8 @@ impl InherentOverlapChecker<'tcx> { /// namespace. fn impls_have_common_items( &self, - impl_items1: &ty::AssociatedItems<'_>, - impl_items2: &ty::AssociatedItems<'_>, + impl_items1: &ty::AssocItems<'_>, + impl_items2: &ty::AssocItems<'_>, ) -> bool { let mut impl_items1 = &impl_items1; let mut impl_items2 = &impl_items2; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e5136355ca..d073262cad 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -43,13 +43,13 @@ use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; -use rustc_session::config::SanitizerSet; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::spec::abi; +use rustc_target::spec::{abi, SanitizerSet}; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +use std::iter; mod item_bounds; mod type_of; @@ -254,10 +254,15 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { self.tcx.ensure().type_of(def_id); } hir::GenericParamKind::Type { .. } => {} - hir::GenericParamKind::Const { .. } => { + hir::GenericParamKind::Const { default, .. } => { let def_id = self.tcx.hir().local_def_id(param.hir_id); self.tcx.ensure().type_of(def_id); - // FIXME(const_generics_defaults) + if let Some(default) = default { + let default_def_id = self.tcx.hir().local_def_id(default.hir_id); + // need to store default and type of default + self.tcx.ensure().type_of(default_def_id); + self.tcx.ensure().const_param_default(def_id); + } } } } @@ -729,8 +734,14 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().generics_of(item.def_id); tcx.ensure().type_of(item.def_id); tcx.ensure().predicates_of(item.def_id); - if let hir::ForeignItemKind::Fn(..) = item.kind { - tcx.ensure().fn_sig(item.def_id); + match item.kind { + hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id), + hir::ForeignItemKind::Static(..) => { + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_foreign_item(item); + placeholder_type_error(tcx, None, &[], visitor.0, false, None); + } + _ => (), } } } @@ -1178,6 +1189,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { } let is_marker = tcx.has_attr(def_id, sym::marker); + let skip_array_during_method_dispatch = + tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch); let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) { ty::trait_def::TraitSpecializationKind::Marker } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) { @@ -1186,7 +1199,16 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { ty::trait_def::TraitSpecializationKind::None }; let def_path_hash = tcx.def_path_hash(def_id); - ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, spec_kind, def_path_hash) + ty::TraitDef::new( + def_id, + unsafety, + paren_sugar, + is_auto, + is_marker, + skip_array_during_method_dispatch, + spec_kind, + def_path_hash, + ) } fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option { @@ -1238,7 +1260,8 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option {} Some( - rl::Region::LateBound(debruijn, _, _) | rl::Region::LateBoundAnon(debruijn, _), + rl::Region::LateBound(debruijn, _, _, _) + | rl::Region::LateBoundAnon(debruijn, _, _), ) if debruijn < self.outer_index => {} Some( rl::Region::LateBound(..) @@ -1302,13 +1325,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option Visitor<'v> for AnonConstInParamListDetector { +impl<'v> Visitor<'v> for AnonConstInParamTyDetector { type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1316,15 +1339,17 @@ impl<'v> Visitor<'v> for AnonConstInParamListDetector { } fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - let prev = self.in_param_list; - self.in_param_list = true; - intravisit::walk_generic_param(self, p); - self.in_param_list = prev; + if let GenericParamKind::Const { ref ty, default: _ } = p.kind { + let prev = self.in_param_ty; + self.in_param_ty = true; + self.visit_ty(ty); + self.in_param_ty = prev; + } } fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { - if self.in_param_list && self.ct == c.hir_id { - self.found_anon_const_in_list = true; + if self.in_param_ty && self.ct == c.hir_id { + self.found_anon_const_in_param_ty = true; } else { intravisit::walk_anon_const(self, c) } @@ -1352,27 +1377,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); let parent_def_id = tcx.hir().local_def_id(parent_id); - let mut in_param_list = false; + let mut in_param_ty = false; for (_parent, node) in tcx.hir().parent_iter(hir_id) { if let Some(generics) = node.generics() { - let mut visitor = AnonConstInParamListDetector { - in_param_list: false, - found_anon_const_in_list: false, + let mut visitor = AnonConstInParamTyDetector { + in_param_ty: false, + found_anon_const_in_param_ty: false, ct: hir_id, }; visitor.visit_generics(generics); - in_param_list = visitor.found_anon_const_in_list; + in_param_ty = visitor.found_anon_const_in_param_ty; break; } } - if in_param_list { + if in_param_ty { // We do not allow generic parameters in anon consts if we are inside - // of a param list. - // - // This affects both default type bindings, e.g. `struct()]>(T, U)`, - // and the types of const parameters, e.g. `struct V();`. + // of a const parameter type, e.g. `struct Foo` is not allowed. None } else if tcx.lazy_normalization() { // HACK(eddyb) this provides the correct generics when @@ -1523,7 +1545,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { |lint| { lint.build( "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions.", + `struct`, `enum`, `type`, or `trait` definitions", ) .emit(); }, @@ -1549,13 +1571,21 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { i += 1; Some(param_def) } - GenericParamKind::Const { .. } => { + GenericParamKind::Const { default, .. } => { + if !allow_defaults && default.is_some() { + tcx.sess.span_err( + param.span, + "defaults for const parameters are only allowed in \ + `struct`, `enum`, `type`, or `trait` definitions", + ); + } + let param_def = ty::GenericParamDef { index: type_start + i as u32, name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), pure_wrt_drop: param.pure_wrt_drop, - kind: ty::GenericParamDefKind::Const, + kind: ty::GenericParamDefKind::Const { has_default: default.is_some() }, }; i += 1; Some(param_def) @@ -1693,10 +1723,11 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } diag.emit(); - ty::Binder::bind(fn_sig) + ty::Binder::bind(fn_sig, tcx) } None => >::ty_of_fn( &icx, + hir_id, sig.header.unsafety, sig.header.abi, &sig.decl, @@ -1714,6 +1745,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { .. }) => >::ty_of_fn( &icx, + hir_id, header.unsafety, header.abi, decl, @@ -1735,13 +1767,10 @@ 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, - )) + ty::Binder::bind( + tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust), + tcx, + ) } Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { @@ -2025,7 +2054,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 = >::ast_region_to_region(&icx, <, None); - let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound)); + let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx); predicates.insert((outlives.to_predicate(tcx), lt.span)); } _ => bug!(), @@ -2070,6 +2099,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { let ty = icx.to_ty(&bound_pred.bounded_ty); + let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` @@ -2085,9 +2115,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } else { let span = bound_pred.bounded_ty.span; let re_root_empty = tcx.lifetimes.re_root_empty; - let predicate = ty::Binder::bind(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(ty, re_root_empty), - )); + let predicate = ty::Binder::bind_with_vars( + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, + re_root_empty, + )), + bound_vars, + ); predicates.insert((predicate.to_predicate(tcx), span)); } } @@ -2104,10 +2138,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let mut bounds = Bounds::default(); let _ = >::instantiate_poly_trait_ref( &icx, - &poly_trait_ref, + &poly_trait_ref.trait_ref, + poly_trait_ref.span, constness, ty, &mut bounds, + false, ); predicates.extend(bounds.predicates(tcx, ty)); } @@ -2130,9 +2166,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let region = >::ast_region_to_region(&icx, lifetime, None); predicates.insert(( - ty::Binder::bind(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(ty, region), - )) + ty::Binder::bind_with_vars( + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, region, + )), + bound_vars, + ) .to_predicate(tcx), lifetime.span, )); @@ -2212,10 +2251,11 @@ fn const_evaluatable_predicates_of<'tcx>( fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { let def_id = self.tcx.hir().local_def_id(c.hir_id); let ct = ty::Const::from_anon_const(self.tcx, def_id); - if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val { + if let ty::ConstKind::Unevaluated(uv) = ct.val { + assert_eq!(uv.promoted, None); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( - ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx), + ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs).to_predicate(self.tcx), span, )); } @@ -2353,7 +2393,14 @@ fn predicates_from_bound<'tcx>( }; let mut bounds = Bounds::default(); - let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds); + let _ = astconv.instantiate_poly_trait_ref( + &tr.trait_ref, + tr.span, + constness, + param_ty, + &mut bounds, + false, + ); bounds.predicates(astconv.tcx(), param_ty) } hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { @@ -2389,8 +2436,10 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } else { hir::Unsafety::Unsafe }; + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let fty = >::ty_of_fn( &ItemCtxt::new(tcx, def_id), + hir_id, unsafety, abi, decl, @@ -2425,7 +2474,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( .emit(); } }; - for (input, ty) in decl.inputs.iter().zip(fty.inputs().skip_binder()) { + for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { check(&input, ty) } if let hir::FnRetTy::Return(ref ty) = decl.output { @@ -2673,6 +2722,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED; } else if tcx.sess.check_name(attr, sym::no_mangle) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; + } else if tcx.sess.check_name(attr, sym::no_coverage) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE; } else if tcx.sess.check_name(attr, sym::rustc_std_internal_symbol) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } else if tcx.sess.check_name(attr, sym::used) { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 3f2f244e44..97b6f5cf41 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -83,7 +83,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< return generics .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(arg_index) .map(|param| param.def_id); } @@ -121,7 +121,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< tcx.generics_of(type_dependent_def) .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(idx) .map(|param| param.def_id) } @@ -191,7 +191,25 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< Res::Def(DefKind::Ctor(..), def_id) => { tcx.generics_of(tcx.parent(def_id).unwrap()) } - Res::Def(_, def_id) => tcx.generics_of(def_id), + // Other `DefKind`s don't have generics and would ICE when calling + // `generics_of`. + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::OpaqueTy + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Impl, + def_id, + ) => tcx.generics_of(def_id), Res::Err => { tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err"); return None; @@ -211,7 +229,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< generics .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(arg_index) .map(|param| param.def_id) } @@ -417,12 +435,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); match parent_node { Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) - | Node::Ty(&Ty { kind: TyKind::Typeof(ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) if constant.hir_id == hir_id => { tcx.types.usize } + Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => { + tcx.typeck(def_id).node_type(e.hir_id) + } Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. }) if anon_const.hir_id == hir_id => @@ -430,12 +450,27 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { tcx.typeck(def_id).node_type(anon_const.hir_id) } + Node::Expr(&Expr { kind: ExprKind::InlineAsm(ia), .. }) + if ia.operands.iter().any(|(op, _op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id, + _ => false, + }) => + { + tcx.typeck(def_id).node_type(hir_id) + } + Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx .adt_def(tcx.hir().get_parent_did(hir_id).to_def_id()) .repr .discr_type() .to_ty(tcx), + Node::GenericParam(&GenericParam { + hir_id: param_hir_id, + kind: GenericParamKind::Const { default: Some(ct), .. }, + .. + }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)), + x => tcx.ty_error_with_message( DUMMY_SP, &format!("unexpected const parent in type_of_def_id(): {:?}", x), diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index b172cb9c44..532ee00daf 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -18,6 +18,7 @@ use rustc_middle::hir::place::ProjectionKind; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, adjustment, TyCtxt}; use rustc_target::abi::VariantIdx; +use std::iter; use crate::mem_categorization as mc; @@ -279,9 +280,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { if needs_to_be_read { self.borrow_expr(&discr, ty::ImmBorrow); } else { + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + _ => None, + }; + self.delegate.fake_read( discr_place.place.clone(), - FakeReadCause::ForMatchedPlace, + FakeReadCause::ForMatchedPlace(closure_def_id), discr_place.hir_id, ); @@ -312,7 +318,6 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } - | hir::InlineAsmOperand::Const { expr, .. } | hir::InlineAsmOperand::Sym { expr, .. } => self.consume_expr(expr), hir::InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -328,12 +333,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.mutate_expr(out_expr); } } + hir::InlineAsmOperand::Const { .. } => {} } } } hir::ExprKind::LlvmInlineAsm(ref ia) => { - for (o, output) in ia.inner.outputs.iter().zip(ia.outputs_exprs) { + for (o, output) in iter::zip(&ia.inner.outputs, ia.outputs_exprs) { if o.is_indirect { self.consume_expr(output); } else { @@ -577,9 +583,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) { + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + _ => None, + }; + self.delegate.fake_read( discr_place.place.clone(), - FakeReadCause::ForMatchedPlace, + FakeReadCause::ForMatchedPlace(closure_def_id), discr_place.hir_id, ); self.walk_pat(discr_place, &arm.pat); @@ -594,9 +605,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or /// let binding, and *not* a match arm or nested pat.) fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), + _ => None, + }; + self.delegate.fake_read( discr_place.place.clone(), - FakeReadCause::ForLet, + FakeReadCause::ForLet(closure_def_id), discr_place.hir_id, ); self.walk_pat(discr_place, pat); @@ -655,7 +671,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// In the following example the closures `c` only captures `p.x`` even though `incr` /// is a capture of the nested closure /// - /// ```rust,ignore(cannot-test-this-because-pseduo-code) + /// ```rust,ignore(cannot-test-this-because-pseudo-code) /// let p = ..; /// let c = || { /// let incr = 10; @@ -699,7 +715,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // The only places we want to fake read before creating the parent closure are the ones that // are not local to it/ defined by it. // - // ```rust,ignore(cannot-test-this-because-pseduo-code) + // ```rust,ignore(cannot-test-this-because-pseudo-code) // let v1 = (0, 1); // let c = || { // fake reads: v1 // let v2 = (0, 1); diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 7713381e62..1240946860 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -173,7 +173,7 @@ fn enforce_impl_params_are_constrained( ); } } - ty::GenericParamDefKind::Const => { + ty::GenericParamDefKind::Const { .. } => { let param_ct = ty::ParamConst::for_def(param); if !input_parameters.contains(&cgp::Parameter::from(param_ct)) { report_unused_parameter( diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 88b47bf5b9..4e07e52347 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -63,8 +63,9 @@ This API is completely unstable and subject to change. #![feature(format_args_capture)] #![feature(in_band_lifetimes)] #![feature(is_sorted)] +#![feature(iter_zip)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(try_blocks)] #![feature(never_type)] #![feature(slice_partition_dedup)] @@ -96,8 +97,8 @@ mod variance; use rustc_errors::{struct_span_err, ErrorReported}; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; -use rustc_hir::Node; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::{Node, CRATE_HIR_ID}; use rustc_infer::infer::{InferOk, TyCtxtInferExt}; use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::middle; @@ -109,7 +110,7 @@ use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ - ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, + self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, }; use std::iter; @@ -163,106 +164,203 @@ fn require_same_types<'tcx>( }) } -fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) { - let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id); +fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { + let main_fnsig = tcx.fn_sig(main_def_id); let main_span = tcx.def_span(main_def_id); - let main_t = tcx.type_of(main_def_id); - match main_t.kind() { - ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.hir().find(main_id) { - if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind { - let mut error = false; - if !generics.params.is_empty() { - let msg = "`main` function is not allowed to have generic \ - parameters" - .to_owned(); - let label = "`main` cannot have generic parameters".to_string(); - struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg) - .span_label(generics.span, label) - .emit(); - error = true; - } - if let Some(sp) = generics.where_clause.span() { - struct_span_err!( - tcx.sess, - sp, - E0646, - "`main` function is not allowed to have a `where` clause" - ) - .span_label(sp, "`main` cannot have a `where` clause") - .emit(); - error = true; - } - if let hir::IsAsync::Async = sig.header.asyncness { - let span = tcx.sess.source_map().guess_head_span(it.span); - struct_span_err!( - tcx.sess, - span, - E0752, - "`main` function is not allowed to be `async`" - ) - .span_label(span, "`main` function is not allowed to be `async`") - .emit(); - error = true; - } - let attrs = tcx.hir().attrs(main_id); - for attr in attrs { - if tcx.sess.check_name(attr, sym::track_caller) { - tcx.sess - .struct_span_err( - attr.span, - "`main` function is not allowed to be `#[track_caller]`", - ) - .span_label( - main_span, - "`main` function is not allowed to be `#[track_caller]`", - ) - .emit(); - error = true; - } - } + fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId { + if let Some(local_def_id) = def_id.as_local() { + let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id); + let hir_type = tcx.type_of(local_def_id); + if !matches!(hir_type.kind(), ty::FnDef(..)) { + span_bug!(sp, "main has a non-function type: found `{}`", hir_type); + } + hir_id + } else { + CRATE_HIR_ID + } + } - if error { - return; - } - } + fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; + } + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { + let generics_param_span = + if !generics.params.is_empty() { Some(generics.span) } else { None }; + generics_param_span + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); } + } + } - let actual = tcx.fn_sig(main_def_id); - let expected_return_type = if tcx.lang_items().termination().is_some() { - // we take the return type of the given main function, the real check is done - // in `check_fn` - actual.output() - } else { - // standard () main return type - ty::Binder::dummy(tcx.mk_unit()) - }; - - let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { - tcx.mk_fn_sig( - iter::empty(), - expected_return_type, - false, - hir::Unsafety::Normal, - Abi::Rust, - ) - })); + fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; + } + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { + generics.where_clause.span() + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); + } + } + } - require_same_types( - tcx, - &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), - se_ty, - tcx.mk_fn_ptr(actual), - ); + fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; } - _ => { - span_bug!(main_span, "main has a non-function type: found `{}`", main_t); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { span: item_span, .. })) => { + Some(tcx.sess.source_map().guess_head_span(*item_span)) + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); + } } } -} -fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) { + fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if !def_id.is_local() { + return None; + } + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().find(hir_id) { + Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(ref fn_sig, _, _), .. })) => { + Some(fn_sig.decl.output.span()) + } + _ => { + span_bug!(tcx.def_span(def_id), "main has a non-function type"); + } + } + } + + let mut error = false; + let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span); + let main_fn_generics = tcx.generics_of(main_def_id); + let main_fn_predicates = tcx.predicates_of(main_def_id); + if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() { + let generics_param_span = main_fn_generics_params_span(tcx, main_def_id); + let msg = "`main` function is not allowed to have generic \ + parameters"; + let mut diag = + struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg); + if let Some(generics_param_span) = generics_param_span { + let label = "`main` cannot have generic parameters".to_string(); + diag.span_label(generics_param_span, label); + } + diag.emit(); + error = true; + } else if !main_fn_predicates.predicates.is_empty() { + // generics may bring in implicit predicates, so we skip this check if generics is present. + let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id); + let mut diag = struct_span_err!( + tcx.sess, + generics_where_clauses_span.unwrap_or(main_span), + E0646, + "`main` function is not allowed to have a `where` clause" + ); + if let Some(generics_where_clauses_span) = generics_where_clauses_span { + diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause"); + } + diag.emit(); + error = true; + } + + let main_asyncness = tcx.asyncness(main_def_id); + if let hir::IsAsync::Async = main_asyncness { + let mut diag = struct_span_err!( + tcx.sess, + main_span, + E0752, + "`main` function is not allowed to be `async`" + ); + let asyncness_span = main_fn_asyncness_span(tcx, main_def_id); + if let Some(asyncness_span) = asyncness_span { + diag.span_label(asyncness_span, "`main` function is not allowed to be `async`"); + } + diag.emit(); + error = true; + } + + for attr in tcx.get_attrs(main_def_id) { + if tcx.sess.check_name(attr, sym::track_caller) { + tcx.sess + .struct_span_err( + attr.span, + "`main` function is not allowed to be `#[track_caller]`", + ) + .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`") + .emit(); + error = true; + } + } + + if error { + return; + } + + let expected_return_type; + if let Some(term_id) = tcx.lang_items().termination() { + let return_ty = main_fnsig.output(); + let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span); + if !return_ty.bound_vars().is_empty() { + let msg = "`main` function return type is not allowed to have generic \ + parameters" + .to_owned(); + struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit(); + error = true; + } + let return_ty = return_ty.skip_binder(); + tcx.infer_ctxt().enter(|infcx| { + let cause = traits::ObligationCause::new( + return_ty_span, + main_diagnostics_hir_id, + ObligationCauseCode::MainFunctionType, + ); + let mut fulfillment_cx = traits::FulfillmentContext::new(); + fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), return_ty, term_id, cause); + if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(&err, None, false); + error = true; + } + }); + // now we can take the return type of the given main function + expected_return_type = main_fnsig.output(); + } else { + // standard () main return type + expected_return_type = ty::Binder::dummy(tcx.mk_unit()); + } + + if error { + return; + } + + let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { + tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust) + })); + + require_same_types( + tcx, + &ObligationCause::new( + main_span, + main_diagnostics_hir_id, + ObligationCauseCode::MainFunctionType, + ), + se_ty, + tcx.mk_fn_ptr(main_fnsig), + ); +} +fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { + let start_def_id = start_def_id.expect_local(); let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id); let start_span = tcx.def_span(start_def_id); let start_t = tcx.type_of(start_def_id); @@ -429,7 +527,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id); let env_def_id = tcx.hir().local_def_id(env_node_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); - item_cx.to_ty(hir_ty) + >::ast_ty_to_ty(&item_cx, hir_ty) } pub fn hir_trait_to_predicates<'tcx>( @@ -444,7 +542,7 @@ pub fn hir_trait_to_predicates<'tcx>( let env_def_id = tcx.hir().local_def_id(env_hir_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); let mut bounds = Bounds::default(); - let _ = >::instantiate_poly_trait_ref_inner( + let _ = >::instantiate_poly_trait_ref( &item_cx, hir_trait, DUMMY_SP, diff --git a/compiler/rustc_typeck/src/variance/solve.rs b/compiler/rustc_typeck/src/variance/solve.rs index 2d3369cba7..1a4d88ced0 100644 --- a/compiler/rustc_typeck/src/variance/solve.rs +++ b/compiler/rustc_typeck/src/variance/solve.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { // Make all const parameters invariant. for param in generics.params.iter() { - if let ty::GenericParamDefKind::Const = param.kind { + if let ty::GenericParamDefKind::Const { .. } = param.kind { variances[param.index as usize] = ty::Invariant; } } diff --git a/config.toml.example b/config.toml.example index ee06e1bd0b..6e5584797b 100644 --- a/config.toml.example +++ b/config.toml.example @@ -112,6 +112,7 @@ changelog-seen = 2 # When invoking `llvm-config` this configures whether the `--shared` argument is # passed to prefer linking to shared libraries. +# NOTE: `thin-lto = true` requires this to be `true` and will give an error otherwise. #link-shared = false # When building llvm, this configures what is being appended to the version. @@ -120,22 +121,23 @@ changelog-seen = 2 #version-suffix = "-rust-dev" # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass -# with clang-cl, so this is special in that it only compiles LLVM with clang-cl -#clang-cl = '/path/to/clang-cl.exe' +# with clang-cl, so this is special in that it only compiles LLVM with clang-cl. +# Note that this takes a /path/to/clang-cl, not a boolean. +#clang-cl = cc # Pass extra compiler and linker flags to the LLVM CMake build. -#cflags = "-fextra-flag" -#cxxflags = "-fextra-flag" -#ldflags = "-Wl,extra-flag" +#cflags = "" +#cxxflags = "" +#ldflags = "" # Use libc++ when building LLVM instead of libstdc++. This is the default on # platforms already use libc++ as the default C++ library, but this option # allows you to use libc++ even on platforms when it's not. You need to ensure # that your host compiler ships with libc++. -#use-libcxx = true +#use-libcxx = false # The value specified here will be passed as `-DLLVM_USE_LINKER` to CMake. -#use-linker = "lld" +#use-linker = (path) # Whether or not to specify `-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=YES` #allow-old-toolchain = false @@ -147,6 +149,9 @@ changelog-seen = 2 # General build configuration options # ============================================================================= [build] +# The default stage to use for the `check` subcommand +#check-stage = 0 + # The default stage to use for the `doc` subcommand #doc-stage = 0 @@ -170,14 +175,14 @@ changelog-seen = 2 # binaries of this build triple and the nightly will be used to bootstrap the # first compiler. # -# Defaults to host platform -#build = "x86_64-unknown-linux-gnu" +# Defaults to platform where `x.py` is run. +#build = "x86_64-unknown-linux-gnu" (as an example) # Which triples to produce a compiler toolchain for. Each of these triples will # be bootstrapped from the build triple themselves. # -# Defaults to just the build triple -#host = ["x86_64-unknown-linux-gnu"] +# Defaults to just the build triple. +#host = ["x86_64-unknown-linux-gnu"] (as an example) # Which triples to build libraries (core/alloc/std/test/proc_macro) for. Each of # these triples will be bootstrapped from the build triple themselves. @@ -185,7 +190,7 @@ changelog-seen = 2 # Defaults to `host`. If you set this explicitly, you likely want to add all # host triples to this list as well in order for those host toolchains to be # able to compile programs for their native target. -#target = ["x86_64-unknown-linux-gnu"] +#target = ["x86_64-unknown-linux-gnu"] (as an example) # Use this directory to store build artifacts. # You can use "$ROOT" to indicate the root of the git repository. @@ -193,15 +198,15 @@ changelog-seen = 2 # Instead of downloading the src/stage0.txt version of Cargo specified, use # this Cargo binary instead to build all Rust code -#cargo = "/path/to/bin/cargo" +#cargo = "/path/to/cargo" # Instead of downloading the src/stage0.txt version of the compiler # specified, use this rustc binary instead as the stage0 snapshot compiler. -#rustc = "/path/to/bin/rustc" +#rustc = "/path/to/rustc" # Instead of download the src/stage0.txt version of rustfmt specified, # use this rustfmt binary instead as the stage0 snapshot rustfmt. -#rustfmt = "/path/to/bin/rustfmt" +#rustfmt = "/path/to/rustfmt" # Flag to specify whether any documentation is built. If false, rustdoc and # friends will still be compiled but they will not be used to generate any @@ -259,10 +264,11 @@ changelog-seen = 2 # be built if `extended = true`. #extended = false -# Installs chosen set of extended tools if `extended = true`. By default builds all. -# If chosen tool failed to build the installation fails. If `extended = false`, this -# option is ignored. -#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] +# Installs chosen set of extended tools if `extended = true`. By default builds +# all extended tools except `rust-demangler`, unless the target is also being +# built with `profiler = true`. If chosen tool failed to build the installation +# fails. If `extended = false`, this option is ignored. +#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] # + "rust-demangler" if `profiler` # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose #verbose = 0 @@ -325,16 +331,9 @@ changelog-seen = 2 # Where to install man pages in `prefix` above #mandir = "share/man" -# Where to install data in `prefix` above (currently unused) +# Where to install data in `prefix` above #datadir = "share" -# Where to install additional info in `prefix` above (currently unused) -#infodir = "share/info" - -# Where to install local state (currently unused) -# If this is a relative path, it will get installed in `prefix` above -#localstatedir = "/var/lib" - # ============================================================================= # Options for compiling Rust code itself # ============================================================================= @@ -372,7 +371,9 @@ changelog-seen = 2 # Whether to download the stage 1 and 2 compilers from CI. # This is mostly useful for tools; if you have changes to `compiler/` they will be ignored. # -# FIXME: currently, this also uses the downloaded compiler for stage0, but that causes unnecessary rebuilds. +# You can set this to "if-unchanged" to only download if `compiler/` has not been modified. +# +# FIXME(#82739): currently, this also uses the downloaded compiler for stage0, but that causes unnecessary rebuilds. #download-rustc = false # Number of codegen units to use for each compiler invocation. A value of 0 @@ -384,7 +385,9 @@ changelog-seen = 2 # Sets the number of codegen units to build the standard library with, # regardless of what the codegen-unit setting for the rest of the compiler is. -#codegen-units-std = 1 +# NOTE: building with anything other than 1 is known to occasionally have bugs. +# See https://github.com/rust-lang/rust/issues/83600. +#codegen-units-std = codegen-units # Whether or not debug assertions are enabled for the compiler and standard # library. Debug assertions control the maximum log level used by rustc. When @@ -427,19 +430,13 @@ changelog-seen = 2 #debuginfo-level = 0 # Debuginfo level for the compiler. -# -# Defaults to rust.debuginfo-level value -#debuginfo-level-rustc = 0 +#debuginfo-level-rustc = debuginfo-level # Debuginfo level for the standard library. -# -# Defaults to rust.debuginfo-level value -#debuginfo-level-std = 0 +#debuginfo-level-std = debuginfo-level # Debuginfo level for the tools. -# -# Defaults to rust.debuginfo-level value -#debuginfo-level-tools = 0 +#debuginfo-level-tools = debuginfo-level # Debuginfo level for the test suites run with compiletest. # FIXME(#61117): Some tests fail when this option is enabled. @@ -466,7 +463,9 @@ changelog-seen = 2 # The default linker that will be hard-coded into the generated compiler for # targets that don't specify linker explicitly in their target specifications. # Note that this is not the linker used to link said compiler. -#default-linker = "cc" +# +# See https://doc.rust-lang.org/rustc/codegen-options/index.html#linker for more information. +#default-linker = (path) # The "channel" for the Rust build to produce. The stable/beta channels only # allow using stable features, whereas the nightly and dev channels allow using @@ -476,10 +475,15 @@ changelog-seen = 2 # A descriptive string to be appended to `rustc --version` output, which is # also used in places like debuginfo `DW_AT_producer`. This may be useful for # supplementary build information, like distro-specific package versions. -#description = "" +#description = (string) -# The root location of the musl installation directory. -#musl-root = "..." +# The root location of the musl installation directory. The library directory +# will also need to contain libunwind.a for an unwinding implementation. Note +# that this option only makes sense for musl targets that produce statically +# linked binaries. +# +# Defaults to /usr on musl hosts. Has no default otherwise. +#musl-root = (path) # By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix # platforms to ensure that the compiler is usable by default from the build @@ -502,14 +506,14 @@ changelog-seen = 2 # Having the git information can cause a lot of rebuilds during development. # Note: If this attribute is not explicitly set (e.g. if left commented out) it # will default to true if channel = "dev", but will default to false otherwise. -#ignore-git = true +#ignore-git = if channel == "dev" { true } else { false } # When creating source tarballs whether or not to create a source tarball. -#dist-src = false +#dist-src = true # After building or testing extended tools (e.g. clippy and rustfmt), append the # result (broken, compiling, testing) into this JSON file. -#save-toolstates = "/path/to/toolstates.json" +#save-toolstates = (path) # This is an array of the codegen backends that will be compiled for the rustc # that's being compiled. The default is to only build the LLVM codegen backend, @@ -545,9 +549,7 @@ changelog-seen = 2 # Compile the compiler with a non-default ThinLTO import limit. This import # limit controls the maximum size of functions imported by ThinLTO. Decreasing # will make code compile faster at the expense of lower runtime performance. -# If `incremental` is set to true above, the import limit will default to 10 -# instead of LLVM's default of 100. -#thin-lto-import-instr-limit = 100 +#thin-lto-import-instr-limit = if incremental { 10 } else { LLVM default (currently 100) } # Map debuginfo paths to `/rust/$sha/...`, generally only set for releases #remap-debuginfo = false @@ -581,63 +583,66 @@ changelog-seen = 2 # ============================================================================= [target.x86_64-unknown-linux-gnu] -# C compiler to be used to compiler C code. Note that the +# C compiler to be used to compile C code. Note that the # default value is platform specific, and if not specified it may also depend on # what platform is crossing to what platform. -#cc = "cc" +# See `src/bootstrap/cc_detect.rs` for details. +#cc = "cc" (path) -# C++ compiler to be used to compiler C++ code (e.g. LLVM and our LLVM shims). +# C++ compiler to be used to compile C++ code (e.g. LLVM and our LLVM shims). # This is only used for host targets. -#cxx = "c++" +# See `src/bootstrap/cc_detect.rs` for details. +#cxx = "c++" (path) # Archiver to be used to assemble static libraries compiled from C/C++ code. # Note: an absolute path should be used, otherwise LLVM build will break. -#ar = "ar" +#ar = "ar" (path) # Ranlib to be used to assemble static libraries compiled from C/C++ code. # Note: an absolute path should be used, otherwise LLVM build will break. -#ranlib = "ranlib" +#ranlib = "ranlib" (path) -# Linker to be used to link Rust code. Note that the +# Linker to be used to bootstrap Rust code. Note that the # default value is platform specific, and if not specified it may also depend on # what platform is crossing to what platform. # Setting this will override the `use-lld` option for Rust code when targeting MSVC. -#linker = "cc" +#linker = "cc" (path) # Path to the `llvm-config` binary of the installation of a custom LLVM to link # against. Note that if this is specified we don't compile LLVM at all for this # target. -#llvm-config = "../path/to/llvm/root/bin/llvm-config" +#llvm-config = (path) # Normally the build system can find LLVM's FileCheck utility, but if # not, you can specify an explicit file name for it. -#llvm-filecheck = "/path/to/FileCheck" +#llvm-filecheck = "/path/to/llvm-version/bin/FileCheck" # If this target is for Android, this option will be required to specify where # the NDK for the target lives. This is used to find the C compiler to link and # build native code. -#android-ndk = "/path/to/ndk" +# See `src/bootstrap/cc_detect.rs` for details. +#android-ndk = (path) # Build the sanitizer runtimes for this target. # This option will override the same option under [build] section. -#sanitizers = false +#sanitizers = build.sanitizers (bool) # Build the profiler runtime for this target(required when compiling with options that depend # on this runtime, such as `-C profile-generate` or `-Z instrument-coverage`). # This option will override the same option under [build] section. -#profiler = false +#profiler = build.profiler (bool) # Force static or dynamic linkage of the standard library for this target. If # this target is a host for rustc, this will also affect the linkage of the # compiler itself. This is useful for building rustc on targets that normally # only use static libraries. If unset, the target's default linkage is used. -#crt-static = false +#crt-static = (bool) # The root location of the musl installation directory. The library directory # will also need to contain libunwind.a for an unwinding implementation. Note # that this option only makes sense for musl targets that produce statically -# linked binaries -#musl-root = "..." +# linked binaries. +#musl-root = build.musl-root (path) # The full path to the musl libdir. #musl-libdir = musl-root/lib @@ -645,11 +650,11 @@ changelog-seen = 2 # The root location of the `wasm32-wasi` sysroot. Only used for the # `wasm32-wasi` target. If you are building wasm32-wasi target, make sure to # create a `[target.wasm32-wasi]` section and move this field there. -#wasi-root = "..." +#wasi-root = (path) # Used in testing for configuring where the QEMU images are located, you # probably don't want to use this. -#qemu-rootfs = "..." +#qemu-rootfs = (path) # ============================================================================= # Distribution options @@ -666,12 +671,7 @@ changelog-seen = 2 # # This folder should be populated ahead of time before the build system is # invoked. -#sign-folder = "path/to/folder/to/sign" - -# This is a file which contains the password of the default gpg key. This will -# be passed to `gpg` down the road when signing all files in `sign-folder` -# above. This should be stored in plaintext. -#gpg-password-file = "path/to/gpg/password" +#sign-folder = (path) # The remote address that all artifacts will eventually be uploaded to. The # build system generates manifests which will point to these urls, and for the @@ -679,18 +679,19 @@ changelog-seen = 2 # # Note that this address should not contain a trailing slash as file names will # be appended to it. -#upload-addr = "https://example.com/folder" +#upload-addr = (URL) # Whether to build a plain source tarball to upload # We disable that on Windows not to override the one already uploaded on S3 # as the one built on Windows will contain backslashes in paths causing problems # on linux #src-tarball = true -# # Whether to allow failures when building tools #missing-tools = false # List of compression formats to use when generating dist tarballs. The list of # formats is provided to rust-installer, which must support all of them. +# +# This list must be non-empty. #compression-formats = ["gz", "xz"] diff --git a/git-commit-hash b/git-commit-hash index 7b5c989351..a1526191f7 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -9bc8c42bb2f19e745a63f3445f1ac248fb015e53 \ No newline at end of file +53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b \ No newline at end of file diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index d95b5b7f17..4f97c95bcb 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "alloc" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "The Rust core allocation and collections library" autotests = false autobenches = false edition = "2018" diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 73eb353f6e..c9bdcaa78f 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -4,23 +4,13 @@ use test::{black_box, Bencher}; #[bench] fn bench_new(b: &mut Bencher) { - b.iter(|| { - let v: Vec = Vec::new(); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), 0); - v - }) + b.iter(|| Vec::::new()) } fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { b.bytes = src_len as u64; - b.iter(|| { - let v: Vec = Vec::with_capacity(src_len); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), src_len); - v - }) + b.iter(|| Vec::::with_capacity(src_len)) } #[bench] @@ -46,12 +36,7 @@ fn bench_with_capacity_1000(b: &mut Bencher) { fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { b.bytes = src_len as u64; - b.iter(|| { - let dst = (0..src_len).collect::>(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - dst - }) + b.iter(|| (0..src_len).collect::>()) } #[bench] @@ -77,12 +62,7 @@ fn bench_from_fn_1000(b: &mut Bencher) { fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { b.bytes = src_len as u64; - b.iter(|| { - let dst: Vec = repeat(5).take(src_len).collect(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().all(|x| *x == 5)); - dst - }) + b.iter(|| repeat(5).take(src_len).collect::>()) } #[bench] @@ -110,12 +90,7 @@ fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { b.bytes = src_len as u64; - b.iter(|| { - let dst = src.clone()[..].to_vec(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - dst - }); + b.iter(|| src.as_slice().to_vec()); } #[bench] @@ -144,9 +119,7 @@ fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { b.bytes = src_len as u64; b.iter(|| { - let dst: Vec<_> = FromIterator::from_iter(src.clone()); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + let dst: Vec<_> = FromIterator::from_iter(src.iter().cloned()); dst }); } @@ -180,8 +153,6 @@ fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { b.iter(|| { let mut dst = dst.clone(); dst.extend(src.clone()); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); dst }); } @@ -230,8 +201,6 @@ fn do_bench_extend_from_slice(b: &mut Bencher, dst_len: usize, src_len: usize) { b.iter(|| { let mut dst = dst.clone(); dst.extend_from_slice(&src); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); dst }); } @@ -290,12 +259,7 @@ fn do_bench_clone(b: &mut Bencher, src_len: usize) { b.bytes = src_len as u64; - b.iter(|| { - let dst = src.clone(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - dst - }); + b.iter(|| src.clone()); } #[bench] @@ -329,8 +293,7 @@ fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: u for _ in 0..times { dst.clone_from(&src); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); + dst = black_box(dst); } dst }); @@ -463,11 +426,10 @@ macro_rules! bench_in_place { fn $fname(b: &mut Bencher) { b.iter(|| { let src: Vec<$type> = black_box(vec![$init; $count]); - let mut sink = src.into_iter() + src.into_iter() .enumerate() .map(|(idx, e)| idx as $type ^ e) - .collect::>(); - black_box(sink.as_mut_ptr()) + .collect::>() }); } )+ @@ -506,7 +468,6 @@ fn bench_in_place_recycle(b: &mut Bencher) { .enumerate() .map(|(idx, e)| idx.wrapping_add(e)) .fuse() - .peekable() .collect::>(), ); }); @@ -527,7 +488,6 @@ fn bench_in_place_zip_recycle(b: &mut Bencher) { .enumerate() .map(|(i, (d, s))| d.wrapping_add(i as u8) ^ s) .collect::>(); - assert_eq!(mangled.len(), 1000); data = black_box(mangled); }); } @@ -548,6 +508,22 @@ fn bench_in_place_zip_iter_mut(b: &mut Bencher) { black_box(data); } +pub fn vec_cast(input: Vec) -> Vec { + input.into_iter().map(|e| unsafe { std::mem::transmute_copy(&e) }).collect() +} + +#[bench] +fn bench_transmute(b: &mut Bencher) { + let mut vec = vec![10u32; 100]; + b.bytes = 800; // 2 casts x 4 bytes x 100 + b.iter(|| { + let v = std::mem::take(&mut vec); + let v = black_box(vec_cast::(v)); + let v = black_box(vec_cast::(v)); + vec = v; + }); +} + #[derive(Clone)] struct Droppable(usize); @@ -598,23 +574,6 @@ fn bench_nest_chain_chain_collect(b: &mut Bencher) { }); } -pub fn example_plain_slow(l: &[u32]) -> Vec { - let mut result = Vec::with_capacity(l.len()); - result.extend(l.iter().rev()); - result -} - -pub fn map_fast(l: &[(u32, u32)]) -> Vec { - let mut result = Vec::with_capacity(l.len()); - for i in 0..l.len() { - unsafe { - *result.get_unchecked_mut(i) = l[i].0; - result.set_len(i); - } - } - result -} - #[bench] fn bench_range_map_collect(b: &mut Bencher) { b.iter(|| (0..LEN).map(|_| u32::default()).collect::>()); @@ -653,7 +612,11 @@ fn bench_rev_1(b: &mut Bencher) { #[bench] fn bench_rev_2(b: &mut Bencher) { let data = black_box([0; LEN]); - b.iter(|| example_plain_slow(&data)); + b.iter(|| { + let mut v = Vec::::with_capacity(data.len()); + v.extend(data.iter().rev()); + v + }); } #[bench] @@ -669,7 +632,16 @@ fn bench_map_regular(b: &mut Bencher) { #[bench] fn bench_map_fast(b: &mut Bencher) { let data = black_box([(0, 0); LEN]); - b.iter(|| map_fast(&data)); + b.iter(|| { + let mut result = Vec::with_capacity(data.len()); + for i in 0..data.len() { + unsafe { + *result.get_unchecked_mut(i) = data[i].0; + result.set_len(i); + } + } + result + }); } fn random_sorted_fill(mut seed: u32, buf: &mut [u32]) { diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 0403390572..ef37fef045 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -793,7 +793,7 @@ impl Box { /// use std::alloc::{Allocator, Layout, System}; /// /// unsafe { - /// let ptr = System.allocate(Layout::new::())?.as_mut_ptr(); + /// let ptr = System.allocate(Layout::new::())?.as_mut_ptr() as *mut i32; /// // In general .write is required to avoid attempting to destruct /// // the (uninitialized) previous contents of `ptr`, though for this /// // simple example `*ptr = 5` would have worked as well. diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index b5e66d37ab..a201af0103 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -652,6 +652,43 @@ impl BinaryHeap { unsafe { self.sift_up(start, pos) }; } + /// Rebuild assuming data[0..start] is still a proper heap. + fn rebuild_tail(&mut self, start: usize) { + if start == self.len() { + return; + } + + let tail_len = self.len() - start; + + #[inline(always)] + fn log2_fast(x: usize) -> usize { + (usize::BITS - x.leading_zeros() - 1) as usize + } + + // `rebuild` takes O(self.len()) operations + // and about 2 * self.len() comparisons in the worst case + // while repeating `sift_up` takes O(tail_len * log(start)) operations + // and about 1 * tail_len * log_2(start) comparisons in the worst case, + // assuming start >= tail_len. For larger heaps, the crossover point + // no longer follows this reasoning and was determined empirically. + let better_to_rebuild = if start < tail_len { + true + } else if self.len() <= 2048 { + 2 * self.len() < tail_len * log2_fast(start) + } else { + 2 * self.len() < tail_len * 11 + }; + + if better_to_rebuild { + self.rebuild(); + } else { + for i in start..self.len() { + // SAFETY: The index `i` is always less than self.len(). + unsafe { self.sift_up(0, i) }; + } + } + } + fn rebuild(&mut self) { let mut n = self.len() / 2; while n > 0 { @@ -689,37 +726,11 @@ impl BinaryHeap { swap(self, other); } - if other.is_empty() { - return; - } + let start = self.data.len(); - #[inline(always)] - fn log2_fast(x: usize) -> usize { - (usize::BITS - x.leading_zeros() - 1) as usize - } - - // `rebuild` takes O(len1 + len2) operations - // and about 2 * (len1 + len2) comparisons in the worst case - // while `extend` takes O(len2 * log(len1)) operations - // and about 1 * len2 * log_2(len1) comparisons in the worst case, - // assuming len1 >= len2. For larger heaps, the crossover point - // no longer follows this reasoning and was determined empirically. - #[inline] - fn better_to_rebuild(len1: usize, len2: usize) -> bool { - let tot_len = len1 + len2; - if tot_len <= 2048 { - 2 * tot_len < len2 * log2_fast(len1) - } else { - 2 * tot_len < len2 * 11 - } - } + self.data.append(&mut other.data); - if better_to_rebuild(self.len(), other.len()) { - self.data.append(&mut other.data); - self.rebuild(); - } else { - self.extend(other.drain()); - } + self.rebuild_tail(start); } /// Returns an iterator which retrieves elements in heap order. @@ -770,12 +781,22 @@ impl BinaryHeap { /// assert_eq!(heap.into_sorted_vec(), [-10, 2, 4]) /// ``` #[unstable(feature = "binary_heap_retain", issue = "71503")] - pub fn retain(&mut self, f: F) + pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, { - self.data.retain(f); - self.rebuild(); + let mut first_removed = self.len(); + let mut i = 0; + self.data.retain(|e| { + let keep = f(e); + if !keep && i < first_removed { + first_removed = i; + } + i += 1; + keep + }); + // data[0..first_removed] is untouched, so we only need to rebuild the tail: + self.rebuild_tail(first_removed); } } @@ -958,6 +979,27 @@ impl BinaryHeap { self.data.shrink_to(min_capacity) } + /// Returns a slice of all values in the underlying vector, in arbitrary + /// order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_as_slice)] + /// use std::collections::BinaryHeap; + /// use std::io::{self, Write}; + /// + /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5, 6, 7]); + /// + /// io::sink().write(heap.as_slice()).unwrap(); + /// ``` + #[unstable(feature = "binary_heap_as_slice", issue = "83659")] + pub fn as_slice(&self) -> &[T] { + self.data.as_slice() + } + /// Consumes the `BinaryHeap` and returns the underlying vector /// in arbitrary order. /// diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index a0dbb28925..971244718b 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -940,7 +940,6 @@ impl BTreeMap { /// # Examples /// /// ``` - /// #![feature(btree_retain)] /// use std::collections::BTreeMap; /// /// let mut map: BTreeMap = (0..8).map(|x| (x, x*10)).collect(); @@ -949,7 +948,7 @@ impl BTreeMap { /// assert!(map.into_iter().eq(vec![(0, 0), (2, 20), (4, 40), (6, 60)])); /// ``` #[inline] - #[unstable(feature = "btree_retain", issue = "79025")] + #[stable(feature = "btree_retain", since = "1.53.0")] pub fn retain(&mut self, mut f: F) where K: Ord, diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index e636e490e1..3a74b6a6fa 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -776,7 +776,6 @@ fn test_range_backwards_4() { } #[test] -#[should_panic] fn test_range_finding_ill_order_in_map() { let mut map = BTreeMap::new(); map.insert(Cyclic3::B, ()); @@ -789,7 +788,6 @@ fn test_range_finding_ill_order_in_map() { } #[test] -#[should_panic] fn test_range_finding_ill_order_in_range_ord() { // Has proper order the first time asked, then flips around. struct EvilTwin(i32); diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index c2c99a9360..4399feaccc 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -29,11 +29,18 @@ impl LeafRange { impl NodeRef { /// Finds the distinct leaf edges delimiting a specified range in a tree. - /// Returns either a pair of different handles into the same tree or a pair - /// of empty options. + /// + /// If such distinct edges exist, returns them in ascending order, meaning + /// that a non-zero number of calls to `next_unchecked` on the `front` of + /// the result and/or calls to `next_back_unchecked` on the `back` of the + /// 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. + /// /// # Safety - /// Unless `BorrowType` is `Immut`, do not use the duplicate handles to - /// visit the same KV twice. + /// Unless `BorrowType` is `Immut`, do not use the handles to visit the same + /// KV twice. unsafe fn find_leaf_edges_spanning_range( self, range: R, diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 9a7119470f..af403496e3 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -89,7 +89,7 @@ impl LeafNode { /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden /// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an -/// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the +/// `InternalNode` can be directly cast to a pointer to the underlying `LeafNode` portion of the /// node, allowing code to act on leaf and internal nodes generically without having to even check /// which of the two a pointer is pointing at. This property is enabled by the use of `repr(C)`. #[repr(C)] @@ -128,106 +128,6 @@ impl InternalNode { /// is not a separate type and has no destructor. type BoxedNode = NonNull>; -/// The root node of an owned tree. -/// -/// Note that this does not have a destructor, and must be cleaned up manually. -pub type Root = NodeRef; - -impl Root { - /// Returns a new owned tree, with its own root node that is initially empty. - pub fn new() -> Self { - NodeRef::new_leaf().forget_type() - } -} - -impl NodeRef { - fn new_leaf() -> Self { - Self::from_new_leaf(LeafNode::new()) - } - - fn from_new_leaf(leaf: Box>) -> Self { - NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } - } -} - -impl NodeRef { - fn new_internal(child: Root) -> Self { - let mut new_node = unsafe { InternalNode::new() }; - new_node.edges[0].write(child.node); - unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } - } - - /// # Safety - /// `height` must not be zero. - unsafe fn from_new_internal(internal: Box>, height: usize) -> Self { - debug_assert!(height > 0); - let node = NonNull::from(Box::leak(internal)).cast(); - let mut this = NodeRef { height, node, _marker: PhantomData }; - this.borrow_mut().correct_all_childrens_parent_links(); - this - } -} - -impl NodeRef { - /// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe - /// because the return value cannot be used to destroy the root, and there - /// cannot be other references to the tree. - pub fn borrow_mut(&mut self) -> NodeRef, K, V, Type> { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Slightly mutably borrows the owned root node. - pub fn borrow_valmut(&mut self) -> NodeRef, K, V, Type> { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Irreversibly transitions to a reference that permits traversal and offers - /// destructive methods and little else. - pub fn into_dying(self) -> NodeRef { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - -impl NodeRef { - /// Adds a new internal node with a single edge pointing to the previous root node, - /// make that new node the root node, and return it. This increases the height by 1 - /// and is the opposite of `pop_internal_level`. - pub fn push_internal_level(&mut self) -> NodeRef, K, V, marker::Internal> { - super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root).forget_type()); - - // `self.borrow_mut()`, except that we just forgot we're internal now: - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Removes the internal root node, using its first child as the new root node. - /// As it is intended only to be called when the root node has only one child, - /// no cleanup is done on any of the keys, values and other children. - /// This decreases the height by 1 and is the opposite of `push_internal_level`. - /// - /// Requires exclusive access to the `Root` object but not to the root node; - /// it will not invalidate other handles or references to the root node. - /// - /// Panics if there is no internal level, i.e., if the root node is a leaf. - pub fn pop_internal_level(&mut self) { - assert!(self.height > 0); - - let top = self.node; - - // SAFETY: we asserted to be internal. - let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; - // SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. - let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) }; - // SAFETY: the first edge is always initialized. - self.node = unsafe { internal_node.edges[0].assume_init_read() }; - self.height -= 1; - self.clear_parent_link(); - - unsafe { - Global.deallocate(top.cast(), Layout::new::>()); - } - } -} - // N.B. `NodeRef` is always covariant in `K` and `V`, even when the `BorrowType` // is `Mut`. This is technically wrong, but cannot result in any unsafety due to // internal use of `NodeRef` because we stay completely generic over `K` and `V`. @@ -292,6 +192,11 @@ pub struct NodeRef { _marker: PhantomData<(BorrowType, Type)>, } +/// The root node of an owned tree. +/// +/// Note that this does not have a destructor, and must be cleaned up manually. +pub type Root = NodeRef; + impl<'a, K: 'a, V: 'a, Type> Copy for NodeRef, K, V, Type> {} impl<'a, K: 'a, V: 'a, Type> Clone for NodeRef, K, V, Type> { fn clone(&self) -> Self { @@ -307,6 +212,34 @@ unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef Send for NodeRef {} unsafe impl Send for NodeRef {} +impl NodeRef { + fn new_leaf() -> Self { + Self::from_new_leaf(LeafNode::new()) + } + + fn from_new_leaf(leaf: Box>) -> Self { + NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } + } +} + +impl NodeRef { + fn new_internal(child: Root) -> Self { + let mut new_node = unsafe { InternalNode::new() }; + new_node.edges[0].write(child.node); + unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } + } + + /// # Safety + /// `height` must not be zero. + unsafe fn from_new_internal(internal: Box>, height: usize) -> Self { + debug_assert!(height > 0); + let node = NonNull::from(Box::leak(internal)).cast(); + let mut this = NodeRef { height, node, _marker: PhantomData }; + this.borrow_mut().correct_all_childrens_parent_links(); + this + } +} + impl NodeRef { /// Unpack a node reference that was packed as `NodeRef::parent`. fn from_internal(node: NonNull>, height: usize) -> Self { @@ -420,6 +353,19 @@ impl NodeRef } } +impl NodeRef { + /// Could be a public implementation of PartialEq, but only used in this module. + fn eq(&self, other: &Self) -> bool { + let Self { node, height, _marker } = self; + if node.eq(&other.node) { + debug_assert_eq!(*height, other.height); + true + } else { + false + } + } +} + impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// Exposes the leaf portion of any leaf or internal node in an immutable tree. fn into_leaf(self) -> &'a LeafNode { @@ -461,22 +407,8 @@ impl NodeRef { } } -impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { - /// Unsafely asserts to the compiler the static information that this node is a `Leaf`. - unsafe fn cast_to_leaf_unchecked(self) -> NodeRef, K, V, marker::Leaf> { - debug_assert!(self.height == 0); - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Unsafely asserts to the compiler the static information that this node is an `Internal`. - unsafe fn cast_to_internal_unchecked(self) -> NodeRef, K, V, marker::Internal> { - debug_assert!(self.height > 0); - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - impl<'a, K, V, Type> NodeRef, K, V, Type> { - /// Temporarily takes out another, mutable reference to the same node. Beware, as + /// Temporarily takes out another mutable reference to the same node. Beware, as /// this method is very dangerous, doubly so since it may not immediately appear /// dangerous. /// @@ -577,6 +509,22 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { } } +impl<'a, K, V> NodeRef, K, V, marker::Internal> { + /// # Safety + /// Every item returned by `range` is a valid edge index for the node. + unsafe fn correct_childrens_parent_links>(&mut self, range: R) { + for i in range { + debug_assert!(i <= self.len()); + unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); + } + } + + fn correct_all_childrens_parent_links(&mut self) { + let len = self.len(); + unsafe { self.correct_childrens_parent_links(0..=len) }; + } +} + impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { /// Sets the node's link to its parent edge, /// without invalidating other references to the node. @@ -596,6 +544,71 @@ impl NodeRef { } } +impl NodeRef { + /// Returns a new owned tree, with its own root node that is initially empty. + pub fn new() -> Self { + NodeRef::new_leaf().forget_type() + } + + /// Adds a new internal node with a single edge pointing to the previous root node, + /// make that new node the root node, and return it. This increases the height by 1 + /// and is the opposite of `pop_internal_level`. + pub fn push_internal_level(&mut self) -> NodeRef, K, V, marker::Internal> { + super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root).forget_type()); + + // `self.borrow_mut()`, except that we just forgot we're internal now: + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Removes the internal root node, using its first child as the new root node. + /// As it is intended only to be called when the root node has only one child, + /// no cleanup is done on any of the keys, values and other children. + /// This decreases the height by 1 and is the opposite of `push_internal_level`. + /// + /// Requires exclusive access to the `Root` object but not to the root node; + /// it will not invalidate other handles or references to the root node. + /// + /// Panics if there is no internal level, i.e., if the root node is a leaf. + pub fn pop_internal_level(&mut self) { + assert!(self.height > 0); + + let top = self.node; + + // SAFETY: we asserted to be internal. + let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; + // SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. + let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) }; + // SAFETY: the first edge is always initialized. + self.node = unsafe { internal_node.edges[0].assume_init_read() }; + self.height -= 1; + self.clear_parent_link(); + + unsafe { + Global.deallocate(top.cast(), Layout::new::>()); + } + } +} + +impl NodeRef { + /// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe + /// because the return value cannot be used to destroy the root, and there + /// cannot be other references to the tree. + pub fn borrow_mut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Slightly mutably borrows the owned root node. + pub fn borrow_valmut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Irreversibly transitions to a reference that permits traversal and offers + /// destructive methods and little else. + pub fn into_dying(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { /// Adds a key-value pair to the end of the node. pub fn push(&mut self, key: K, val: V) { @@ -610,22 +623,6 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { } } -impl<'a, K, V> NodeRef, K, V, marker::Internal> { - /// # Safety - /// Every item returned by `range` is a valid edge index for the node. - unsafe fn correct_childrens_parent_links>(&mut self, range: R) { - for i in range { - debug_assert!(i <= self.len()); - unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); - } - } - - fn correct_all_childrens_parent_links(&mut self) { - let len = self.len(); - unsafe { self.correct_childrens_parent_links(0..=len) }; - } -} - impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { /// Adds a key-value pair, and an edge to go to the right of that pair, /// to the end of the node. @@ -645,6 +642,20 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { } } +impl NodeRef { + /// Removes any static information asserting that this node is a `Leaf` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Removes any static information asserting that this node is an `Internal` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + impl NodeRef { /// Checks whether a node is an `Internal` node or a `Leaf` node. pub fn force( @@ -669,6 +680,20 @@ impl NodeRef { } } +impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { + /// Unsafely asserts to the compiler the static information that this node is a `Leaf`. + unsafe fn cast_to_leaf_unchecked(self) -> NodeRef, K, V, marker::Leaf> { + debug_assert!(self.height == 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Unsafely asserts to the compiler the static information that this node is an `Internal`. + unsafe fn cast_to_internal_unchecked(self) -> NodeRef, K, V, marker::Internal> { + debug_assert!(self.height > 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + /// A reference to a specific key-value pair or edge within a node. The `Node` parameter /// must be a `NodeRef`, while the `Type` can either be `KV` (signifying a handle on a key-value /// pair) or `Edge` (signifying a handle on an edge). @@ -722,19 +747,6 @@ impl Handle, mar } } -impl NodeRef { - /// Could be a public implementation of PartialEq, but only used in this module. - fn eq(&self, other: &Self) -> bool { - let Self { node, height, _marker } = self; - if node.eq(&other.node) { - debug_assert_eq!(*height, other.height); - true - } else { - false - } - } -} - impl PartialEq for Handle, HandleType> { @@ -747,25 +759,15 @@ impl PartialEq impl Handle, HandleType> { - /// Temporarily takes out another, immutable handle on the same location. + /// Temporarily takes out another immutable handle on the same location. pub fn reborrow(&self) -> Handle, K, V, NodeType>, HandleType> { // We can't use Handle::new_kv or Handle::new_edge because we don't know our type Handle { node: self.node.reborrow(), idx: self.idx, _marker: PhantomData } } } -impl<'a, K, V, Type> Handle, K, V, marker::LeafOrInternal>, Type> { - /// Unsafely asserts to the compiler the static information that the handle's node is a `Leaf`. - pub unsafe fn cast_to_leaf_unchecked( - self, - ) -> Handle, K, V, marker::Leaf>, Type> { - let node = unsafe { self.node.cast_to_leaf_unchecked() }; - Handle { node, idx: self.idx, _marker: PhantomData } - } -} - impl<'a, K, V, NodeType, HandleType> Handle, K, V, NodeType>, HandleType> { - /// Temporarily takes out another, mutable handle on the same location. Beware, as + /// Temporarily takes out another mutable handle on the same location. Beware, as /// this method is very dangerous, doubly so since it may not immediately appear /// dangerous. /// @@ -1466,20 +1468,6 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { } } -impl NodeRef { - /// Removes any static information asserting that this node is a `Leaf` node. - pub fn forget_type(self) -> NodeRef { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - -impl NodeRef { - /// Removes any static information asserting that this node is an `Internal` node. - pub fn forget_type(self) -> NodeRef { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - impl Handle, marker::Edge> { pub fn forget_node_type( self, @@ -1531,6 +1519,16 @@ impl Handle Handle, K, V, marker::LeafOrInternal>, Type> { + /// Unsafely asserts to the compiler the static information that the handle's node is a `Leaf`. + pub unsafe fn cast_to_leaf_unchecked( + self, + ) -> Handle, K, V, marker::Leaf>, Type> { + let node = unsafe { self.node.cast_to_leaf_unchecked() }; + Handle { node, idx: self.idx, _marker: PhantomData } + } +} + impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { /// Move the suffix after `self` from one node to another one. `right` must be empty. /// The first edge of `right` remains unchanged. diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs index 5dc62d4ec7..5651a03c47 100644 --- a/library/alloc/src/collections/btree/search.rs +++ b/library/alloc/src/collections/btree/search.rs @@ -68,13 +68,16 @@ impl NodeRef( mut self, @@ -112,10 +115,8 @@ impl NodeRef upper_edge_idx { - panic!("Ord is ill-defined in BTreeMap range") - } + let (upper_edge_idx, upper_child_bound) = + unsafe { self.find_upper_bound_index(upper_bound, lower_edge_idx) }; if lower_edge_idx < upper_edge_idx { return Ok(( self, @@ -125,6 +126,7 @@ impl NodeRef return Err(common_edge), @@ -164,7 +166,7 @@ impl NodeRef, { - let (edge_idx, bound) = self.find_upper_bound_index(bound); + let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) }; let edge = unsafe { Handle::new_edge(self, edge_idx) }; (edge, bound) } @@ -183,29 +185,33 @@ impl NodeRef { Q: Ord, K: Borrow, { - match self.find_key_index(key) { + match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }), IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }), } } /// Returns either the KV index in the node at which the key (or an equivalent) - /// exists, or the edge index where the key belongs. + /// exists, or the edge index where the key belongs, starting from a particular index. /// /// The result is meaningful only if the tree is ordered by key, like the tree /// in a `BTreeMap` is. - fn find_key_index(&self, key: &Q) -> IndexResult + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_key_index(&self, key: &Q, start_index: usize) -> IndexResult where Q: Ord, K: Borrow, { let node = self.reborrow(); let keys = node.keys(); - for (i, k) in keys.iter().enumerate() { + debug_assert!(start_index <= keys.len()); + for (offset, k) in unsafe { keys.get_unchecked(start_index..) }.iter().enumerate() { match key.cmp(k.borrow()) { Ordering::Greater => {} - Ordering::Equal => return IndexResult::KV(i), - Ordering::Less => return IndexResult::Edge(i), + Ordering::Equal => return IndexResult::KV(start_index + offset), + Ordering::Less => return IndexResult::Edge(start_index + offset), } } IndexResult::Edge(keys.len()) @@ -225,11 +231,11 @@ impl NodeRef { K: Borrow, { match bound { - Included(key) => match self.find_key_index(key) { + Included(key) => match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => (idx, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, - Excluded(key) => match self.find_key_index(key) { + Excluded(key) => match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => (idx + 1, AllIncluded), IndexResult::Edge(idx) => (idx, bound), }, @@ -238,26 +244,31 @@ impl NodeRef { } } - /// Clone of `find_lower_bound_index` for the upper bound. - fn find_upper_bound_index<'r, Q>( + /// Mirror image of `find_lower_bound_index` for the upper bound, + /// with an additional parameter to skip part of the key array. + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_upper_bound_index<'r, Q>( &self, bound: SearchBound<&'r Q>, + start_index: usize, ) -> (usize, SearchBound<&'r Q>) where Q: ?Sized + Ord, K: Borrow, { match bound { - Included(key) => match self.find_key_index(key) { + Included(key) => match unsafe { self.find_key_index(key, start_index) } { IndexResult::KV(idx) => (idx + 1, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, - Excluded(key) => match self.find_key_index(key) { + Excluded(key) => match unsafe { self.find_key_index(key, start_index) } { IndexResult::KV(idx) => (idx, AllIncluded), IndexResult::Edge(idx) => (idx, bound), }, AllIncluded => (self.len(), AllIncluded), - AllExcluded => (0, AllExcluded), + AllExcluded => (start_index, AllExcluded), } } } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index a331b8d8e4..737932d931 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -851,7 +851,6 @@ impl BTreeSet { /// # Examples /// /// ``` - /// #![feature(btree_retain)] /// use std::collections::BTreeSet; /// /// let xs = [1, 2, 3, 4, 5, 6]; @@ -860,7 +859,7 @@ impl BTreeSet { /// set.retain(|&k| k % 2 == 0); /// assert!(set.iter().eq([2, 4, 6].iter())); /// ``` - #[unstable(feature = "btree_retain", issue = "79025")] + #[stable(feature = "btree_retain", since = "1.53.0")] pub fn retain(&mut self, mut f: F) where T: Ord, diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 465b058cd9..612f7e6eb4 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -1,5 +1,5 @@ use core::fmt; -use core::iter::FusedIterator; +use core::iter::{FusedIterator, TrustedLen}; use super::VecDeque; @@ -55,3 +55,6 @@ impl ExactSizeIterator for IntoIter { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index ad31b991cb..e4cfb3acdf 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -1,5 +1,5 @@ use core::fmt; -use core::iter::FusedIterator; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; use core::ops::Try; use super::{count, wrap_index, RingSlices}; @@ -101,6 +101,19 @@ impl<'a, T> Iterator for Iter<'a, T> { fn last(mut self) -> Option<&'a T> { self.next_back() } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len()); + self.ring.get_unchecked(idx) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -157,3 +170,12 @@ impl ExactSizeIterator for Iter<'_, T> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Iter<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Iter<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Iter<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 3d0c3094e2..9493676e66 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -1,5 +1,5 @@ use core::fmt; -use core::iter::FusedIterator; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; use core::marker::PhantomData; use super::{count, wrap_index, RingSlices}; @@ -87,6 +87,19 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn last(mut self) -> Option<&'a mut T> { self.next_back() } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len()); + &mut *self.ring.get_unchecked_mut(idx) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -126,3 +139,12 @@ impl ExactSizeIterator for IterMut<'_, T> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IterMut<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for IterMut<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 7a0de74eb2..7d6fbf1c43 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -58,7 +58,7 @@ mod tests; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 const MINIMUM_CAPACITY: usize = 1; // 2 - 1 -const MAXIMUM_ZST_CAPACITY: usize = 1 << (core::mem::size_of::() * 8 - 1); // Largest possible power of two +const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two /// A double-ended queue implemented with a growable ring buffer. /// @@ -2403,6 +2403,12 @@ impl VecDeque { /// [`Result::Err`] is returned, containing the index where a matching /// element could be inserted while maintaining sorted order. /// + /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// [`partition_point`]: VecDeque::partition_point + /// /// # Examples /// /// Looks up a series of four elements. The first is found, with a @@ -2457,6 +2463,12 @@ impl VecDeque { /// [`Result::Err`] is returned, containing the index where a matching /// element could be inserted while maintaining sorted order. /// + /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// [`partition_point`]: VecDeque::partition_point + /// /// # Examples /// /// Looks up a series of four elements. The first is found, with a @@ -2481,8 +2493,11 @@ impl VecDeque { F: FnMut(&'a T) -> Ordering, { let (front, back) = self.as_slices(); + let cmp_back = back.first().map(|elem| f(elem)); - if let Some(Ordering::Less | Ordering::Equal) = back.first().map(|elem| f(elem)) { + if let Some(Ordering::Equal) = cmp_back { + Ok(front.len()) + } else if let Some(Ordering::Less) = cmp_back { back.binary_search_by(f).map(|idx| idx + front.len()).map_err(|idx| idx + front.len()) } else { front.binary_search_by(f) @@ -2492,8 +2507,7 @@ impl VecDeque { /// Binary searches this sorted `VecDeque` with a key extraction function. /// /// Assumes that the `VecDeque` is sorted by the key, for instance with - /// [`make_contiguous().sort_by_key()`](#method.make_contiguous) using the same - /// key extraction function. + /// [`make_contiguous().sort_by_key()`] using the same key extraction function. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2501,6 +2515,13 @@ impl VecDeque { /// [`Result::Err`] is returned, containing the index where a matching /// element could be inserted while maintaining sorted order. /// + /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`]. + /// + /// [`make_contiguous().sort_by_key()`]: VecDeque::make_contiguous + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`partition_point`]: VecDeque::partition_point + /// /// # Examples /// /// Looks up a series of four elements in a slice of pairs sorted by @@ -2531,6 +2552,51 @@ impl VecDeque { { self.binary_search_by(|k| f(k).cmp(b)) } + + /// Returns the index of the partition point according to the given predicate + /// (the index of the first element of the second partition). + /// + /// The deque is assumed to be partitioned according to the given predicate. + /// This means that all elements for which the predicate returns true are at the start of the deque + /// and all elements for which the predicate returns false are at the end. + /// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0 + /// (all odd numbers are at the start, all even at the end). + /// + /// If this deque is not partitioned, the returned result is unspecified and meaningless, + /// as this method performs a kind of binary search. + /// + /// See also [`binary_search`], [`binary_search_by`], and [`binary_search_by_key`]. + /// + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_binary_search)] + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = vec![1, 2, 3, 3, 5, 6, 7].into(); + /// let i = deque.partition_point(|&x| x < 5); + /// + /// assert_eq!(i, 4); + /// assert!(deque.iter().take(i).all(|&x| x < 5)); + /// assert!(deque.iter().skip(i).all(|&x| !(x < 5))); + /// ``` + #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + pub fn partition_point

`] ensures that the pointee of any pointer type +//! At a high level, a [Pin]\

ensures that the pointee of any pointer type //! `P` has a stable location in memory, meaning it cannot be moved elsewhere //! and its memory cannot be deallocated until it gets dropped. We say that the //! pointee is "pinned". Things get more subtle when discussing types that @@ -14,13 +14,15 @@ //! for more details. //! //! By default, all types in Rust are movable. Rust allows passing all types by-value, -//! and common smart-pointer types such as [`Box`] and `&mut T` allow replacing and -//! moving the values they contain: you can move out of a [`Box`], or you can use [`mem::swap`]. -//! [`Pin

`] wraps a pointer type `P`, so [`Pin`]`<`[`Box`]`>` functions much like a regular -//! [`Box`]: when a [`Pin`]`<`[`Box`]`>` gets dropped, so do its contents, and the memory gets -//! deallocated. Similarly, [`Pin`]`<&mut T>` is a lot like `&mut T`. However, [`Pin

`] does -//! not let clients actually obtain a [`Box`] or `&mut T` to pinned data, which implies that you -//! cannot use operations such as [`mem::swap`]: +//! and common smart-pointer types such as [Box]\ and [&mut] T allow +//! replacing and moving the values they contain: you can move out of a [Box]\, +//! or you can use [`mem::swap`]. [Pin]\

wraps a pointer type `P`, so +//! [Pin]<[Box]\> functions much like a regular [Box]\: +//! when a [Pin]<[Box]\> gets dropped, so do its contents, and the memory gets +//! deallocated. Similarly, [Pin]<[&mut] T> is a lot like [&mut] T. +//! However, [Pin]\

does not let clients actually obtain a [Box]\ +//! or [&mut] T to pinned data, which implies that you cannot use operations such +//! as [`mem::swap`]: //! //! ``` //! use std::pin::Pin; @@ -32,18 +34,18 @@ //! } //! ``` //! -//! It is worth reiterating that [`Pin

`] does *not* change the fact that a Rust compiler -//! considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, [`Pin

`] -//! prevents certain *values* (pointed to by pointers wrapped in [`Pin

`]) from being -//! moved by making it impossible to call methods that require `&mut T` on them -//! (like [`mem::swap`]). -//! -//! [`Pin

`] can be used to wrap any pointer type `P`, and as such it interacts with -//! [`Deref`] and [`DerefMut`]. A [`Pin

`] where `P: Deref` should be considered -//! as a "`P`-style pointer" to a pinned `P::Target` -- so, a [`Pin`]`<`[`Box`]`>` is -//! an owned pointer to a pinned `T`, and a [`Pin`]`<`[`Rc`]`>` is a reference-counted -//! pointer to a pinned `T`. -//! For correctness, [`Pin

`] relies on the implementations of [`Deref`] and +//! It is worth reiterating that [Pin]\

does *not* change the fact that a Rust +//! compiler considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, +//! [Pin]\

prevents certain *values* (pointed to by pointers wrapped in +//! [Pin]\

) from being moved by making it impossible to call methods that require +//! [&mut] T on them (like [`mem::swap`]). +//! +//! [Pin]\

can be used to wrap any pointer type `P`, and as such it interacts with +//! [`Deref`] and [`DerefMut`]. A [Pin]\

where P: [Deref] should be +//! considered as a "`P`-style pointer" to a pinned P::[Target] – so, a +//! [Pin]<[Box]\> is an owned pointer to a pinned `T`, and a +//! [Pin]<[Rc]\> is a reference-counted pointer to a pinned `T`. +//! For correctness, [Pin]\

relies on the implementations of [`Deref`] and //! [`DerefMut`] not to move out of their `self` parameter, and only ever to //! return a pointer to pinned data when they are called on a pinned pointer. //! @@ -53,19 +55,19 @@ //! rely on having a stable address. This includes all the basic types (like //! [`bool`], [`i32`], and references) as well as types consisting solely of these //! types. Types that do not care about pinning implement the [`Unpin`] -//! auto-trait, which cancels the effect of [`Pin

`]. For `T: Unpin`, -//! [`Pin`]`<`[`Box`]`>` and [`Box`] function identically, as do [`Pin`]`<&mut T>` and -//! `&mut T`. +//! auto-trait, which cancels the effect of [Pin]\

. For T: [Unpin], +//! [Pin]<[Box]\> and [Box]\ function identically, as do +//! [Pin]<[&mut] T> and [&mut] T. //! -//! Note that pinning and [`Unpin`] only affect the pointed-to type `P::Target`, not the pointer -//! type `P` itself that got wrapped in [`Pin

`]. For example, whether or not [`Box`] is -//! [`Unpin`] has no effect on the behavior of [`Pin`]`<`[`Box`]`>` (here, `T` is the -//! pointed-to type). +//! Note that pinning and [`Unpin`] only affect the pointed-to type P::[Target], +//! not the pointer type `P` itself that got wrapped in [Pin]\

. For example, +//! whether or not [Box]\ is [`Unpin`] has no effect on the behavior of +//! [Pin]<[Box]\> (here, `T` is the pointed-to type). //! //! # Example: self-referential struct //! //! Before we go into more details to explain the guarantees and choices -//! associated with `Pin`, we discuss some examples for how it might be used. +//! associated with [Pin]\

, we discuss some examples for how it might be used. //! Feel free to [skip to where the theoretical discussion continues](#drop-guarantee). //! //! ```rust @@ -129,7 +131,7 @@ //! //! To make this work, every element has pointers to its predecessor and successor in //! the list. Elements can only be added when they are pinned, because moving the elements -//! around would invalidate the pointers. Moreover, the [`Drop`] implementation of a linked +//! around would invalidate the pointers. Moreover, the [`Drop`][Drop] implementation of a linked //! list element will patch the pointers of its predecessor and successor to remove itself //! from the list. //! @@ -149,8 +151,8 @@ //! when [`drop`] is called*. Only once [`drop`] returns or panics, the memory may be reused. //! //! Memory can be "invalidated" by deallocation, but also by -//! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements -//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without +//! replacing a [Some]\(v) by [`None`], or calling [`Vec::set_len`] to "kill" some +//! elements off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without //! calling the destructor first. None of this is allowed for pinned data without calling [`drop`]. //! //! This is exactly the kind of guarantee that the intrusive linked list from the previous @@ -158,25 +160,25 @@ //! //! Notice that this guarantee does *not* mean that memory does not leak! It is still //! completely okay not ever to call [`drop`] on a pinned element (e.g., you can still -//! call [`mem::forget`] on a [`Pin`]`<`[`Box`]`>`). In the example of the doubly-linked +//! call [`mem::forget`] on a [Pin]<[Box]\>). In the example of the doubly-linked //! list, that element would just stay in the list. However you may not free or reuse the storage //! *without calling [`drop`]*. //! //! # `Drop` implementation //! //! If your type uses pinning (such as the two examples above), you have to be careful -//! when implementing [`Drop`]. The [`drop`] function takes `&mut self`, but this +//! when implementing [`Drop`][Drop]. The [`drop`] function takes [&mut] self, but this //! is called *even if your type was previously pinned*! It is as if the //! compiler automatically called [`Pin::get_unchecked_mut`]. //! //! This can never cause a problem in safe code because implementing a type that //! relies on pinning requires unsafe code, but be aware that deciding to make //! use of pinning in your type (for example by implementing some operation on -//! [`Pin`]`<&Self>` or [`Pin`]`<&mut Self>`) has consequences for your [`Drop`] -//! implementation as well: if an element of your type could have been pinned, -//! you must treat [`Drop`] as implicitly taking [`Pin`]`<&mut Self>`. +//! [Pin]<[&]Self> or [Pin]<[&mut] Self>) has consequences for your +//! [`Drop`][Drop]implementation as well: if an element of your type could have been pinned, +//! you must treat [`Drop`][Drop] as implicitly taking [Pin]<[&mut] Self>. //! -//! For example, you could implement `Drop` as follows: +//! For example, you could implement [`Drop`][Drop] as follows: //! //! ```rust,no_run //! # use std::pin::Pin; @@ -204,18 +206,18 @@ //! # Projections and Structural Pinning //! //! When working with pinned structs, the question arises how one can access the -//! fields of that struct in a method that takes just [`Pin`]`<&mut Struct>`. +//! fields of that struct in a method that takes just [Pin]<[&mut] Struct>. //! The usual approach is to write helper methods (so called *projections*) -//! that turn [`Pin`]`<&mut Struct>` into a reference to the field, but what -//! type should that reference have? Is it [`Pin`]`<&mut Field>` or `&mut Field`? +//! that turn [Pin]<[&mut] Struct> into a reference to the field, but what type should +//! that reference have? Is it [Pin]<[&mut] Field> or [&mut] Field? //! The same question arises with the fields of an `enum`, and also when considering -//! container/wrapper types such as [`Vec`], [`Box`], or [`RefCell`]. -//! (This question applies to both mutable and shared references, we just -//! use the more common case of mutable references here for illustration.) +//! container/wrapper types such as [Vec]\, [Box]\, +//! or [RefCell]\. (This question applies to both mutable and shared references, +//! we just use the more common case of mutable references here for illustration.) //! -//! It turns out that it is actually up to the author of the data structure -//! to decide whether the pinned projection for a particular field turns -//! [`Pin`]`<&mut Struct>` into [`Pin`]`<&mut Field>` or `&mut Field`. There are some +//! It turns out that it is actually up to the author of the data structure to decide whether +//! the pinned projection for a particular field turns [Pin]<[&mut] Struct> +//! into [Pin]<[&mut] Field> or [&mut] Field. There are some //! constraints though, and the most important constraint is *consistency*: //! every field can be *either* projected to a pinned reference, *or* have //! pinning removed as part of the projection. If both are done for the same field, @@ -230,12 +232,12 @@ //! ## Pinning *is not* structural for `field` //! //! It may seem counter-intuitive that the field of a pinned struct might not be pinned, -//! but that is actually the easiest choice: if a [`Pin`]`<&mut Field>` is never created, +//! but that is actually the easiest choice: if a [Pin]<[&mut] Field> is never created, //! nothing can go wrong! So, if you decide that some field does not have structural pinning, //! all you have to ensure is that you never create a pinned reference to that field. //! //! Fields without structural pinning may have a projection method that turns -//! [`Pin`]`<&mut Struct>` into `&mut Field`: +//! [Pin]<[&mut] Struct> into [&mut] Field: //! //! ```rust,no_run //! # use std::pin::Pin; @@ -249,16 +251,16 @@ //! } //! ``` //! -//! You may also `impl Unpin for Struct` *even if* the type of `field` +//! You may also impl [Unpin] for Struct *even if* the type of `field` //! is not [`Unpin`]. What that type thinks about pinning is not relevant -//! when no [`Pin`]`<&mut Field>` is ever created. +//! when no [Pin]<[&mut] Field> is ever created. //! //! ## Pinning *is* structural for `field` //! //! The other option is to decide that pinning is "structural" for `field`, //! meaning that if the struct is pinned then so is the field. //! -//! This allows writing a projection that creates a [`Pin`]`<&mut Field>`, thus +//! This allows writing a projection that creates a [Pin]<[&mut] Field>, thus //! witnessing that the field is pinned: //! //! ```rust,no_run @@ -278,34 +280,36 @@ //! 1. The struct must only be [`Unpin`] if all the structural fields are //! [`Unpin`]. This is the default, but [`Unpin`] is a safe trait, so as the author of //! the struct it is your responsibility *not* to add something like -//! `impl Unpin for Struct`. (Notice that adding a projection operation +//! impl\ [Unpin] for Struct\. (Notice that adding a projection operation //! requires unsafe code, so the fact that [`Unpin`] is a safe trait does not break -//! the principle that you only have to worry about any of this if you use `unsafe`.) +//! the principle that you only have to worry about any of this if you use [`unsafe`].) //! 2. The destructor of the struct must not move structural fields out of its argument. This -//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes -//! `&mut self`, but the struct (and hence its fields) might have been pinned before. -//! You have to guarantee that you do not move a field inside your [`Drop`] implementation. -//! In particular, as explained previously, this means that your struct must *not* -//! be `#[repr(packed)]`. +//! is the exact point that was raised in the [previous section][drop-impl]: [`drop`] takes +//! [&mut] self, but the struct (and hence its fields) might have been pinned +//! before. You have to guarantee that you do not move a field inside your [`Drop`][Drop] +//! implementation. In particular, as explained previously, this means that your struct +//! must *not* be `#[repr(packed)]`. //! See that section for how to write [`drop`] in a way that the compiler can help you //! not accidentally break pinning. //! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]: //! once your struct is pinned, the memory that contains the //! content is not overwritten or deallocated without calling the content's destructors. -//! This can be tricky, as witnessed by [`VecDeque`]: the destructor of [`VecDeque`] -//! can fail to call [`drop`] on all elements if one of the destructors panics. This violates -//! the [`Drop`] guarantee, because it can lead to elements being deallocated without -//! their destructor being called. ([`VecDeque`] has no pinning projections, so this +//! This can be tricky, as witnessed by [VecDeque]\: the destructor of +//! [VecDeque]\ can fail to call [`drop`] on all elements if one of the +//! destructors panics. This violates the [`Drop`][Drop] guarantee, because it can lead to +//! elements being deallocated without their destructor being called. +//! ([VecDeque]\ has no pinning projections, so this //! does not cause unsoundness.) //! 4. You must not offer any other operations that could lead to data being moved out of //! the structural fields when your type is pinned. For example, if the struct contains an -//! [`Option`] and there is a `take`-like operation with type -//! `fn(Pin<&mut Struct>) -> Option`, -//! that operation can be used to move a `T` out of a pinned `Struct` -- which means +//! [Option]\ and there is a [`take`][Option::take]-like operation with type +//! fn([Pin]<[&mut] Struct\>) -> [Option]\, +//! that operation can be used to move a `T` out of a pinned `Struct` – which means //! pinning cannot be structural for the field holding this data. //! -//! For a more complex example of moving data out of a pinned type, imagine if [`RefCell`] -//! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`. +//! For a more complex example of moving data out of a pinned type, +//! imagine if [RefCell]\ had a method +//! fn get_pin_mut(self: [Pin]<[&mut] Self>) -> [Pin]<[&mut] T>. //! Then we could do the following: //! ```compile_fail //! fn exploit_ref_cell(rc: Pin<&mut RefCell>) { @@ -315,60 +319,65 @@ //! let content = &mut *b; // And here we have `&mut T` to the same data. //! } //! ``` -//! This is catastrophic, it means we can first pin the content of the [`RefCell`] -//! (using `RefCell::get_pin_mut`) and then move that content using the mutable -//! reference we got later. +//! This is catastrophic, it means we can first pin the content of the +//! [RefCell]\ (using [RefCell]::get_pin_mut) and then move that +//! content using the mutable reference we got later. //! //! ## Examples //! -//! For a type like [`Vec`], both possibilities (structural pinning or not) make sense. -//! A [`Vec`] with structural pinning could have `get_pin`/`get_pin_mut` methods to get -//! pinned references to elements. However, it could *not* allow calling -//! [`pop`][Vec::pop] on a pinned [`Vec`] because that would move the (structurally pinned) -//! contents! Nor could it allow [`push`][Vec::push], which might reallocate and thus also move the -//! contents. +//! For a type like [Vec]\, both possibilities (structural pinning or not) make +//! sense. A [Vec]\ with structural pinning could have `get_pin`/`get_pin_mut` +//! methods to get pinned references to elements. However, it could *not* allow calling +//! [`pop`][Vec::pop] on a pinned [Vec]\ because that would move the (structurally +//! pinned) contents! Nor could it allow [`push`][Vec::push], which might reallocate and thus also +//! move the contents. //! -//! A [`Vec`] without structural pinning could `impl Unpin for Vec`, because the contents -//! are never pinned and the [`Vec`] itself is fine with being moved as well. +//! A [Vec]\ without structural pinning could +//! impl\ [Unpin] for [Vec]\, because the contents are never pinned +//! and the [Vec]\ itself is fine with being moved as well. //! At that point pinning just has no effect on the vector at all. //! //! In the standard library, pointer types generally do not have structural pinning, -//! and thus they do not offer pinning projections. This is why `Box: Unpin` holds for all `T`. -//! It makes sense to do this for pointer types, because moving the `Box` -//! does not actually move the `T`: the [`Box`] can be freely movable (aka `Unpin`) even if -//! the `T` is not. In fact, even [`Pin`]`<`[`Box`]`>` and [`Pin`]`<&mut T>` are always -//! [`Unpin`] themselves, for the same reason: their contents (the `T`) are pinned, but the -//! pointers themselves can be moved without moving the pinned data. For both [`Box`] and -//! [`Pin`]`<`[`Box`]`>`, whether the content is pinned is entirely independent of whether the +//! and thus they do not offer pinning projections. This is why [Box]\: [Unpin] +//! holds for all `T`. It makes sense to do this for pointer types, because moving the +//! [Box]\ does not actually move the `T`: the [Box]\ can be freely +//! movable (aka [`Unpin`]) even if the `T` is not. In fact, even [Pin]<[Box]\> and +//! [Pin]<[&mut] T> are always [`Unpin`] themselves, for the same reason: +//! their contents (the `T`) are pinned, but the pointers themselves can be moved without moving +//! the pinned data. For both [Box]\ and [Pin]<[Box]\>, +//! whether the content is pinned is entirely independent of whether the //! pointer is pinned, meaning pinning is *not* structural. //! //! When implementing a [`Future`] combinator, you will usually need structural pinning //! for the nested futures, as you need to get pinned references to them to call [`poll`]. //! But if your combinator contains any other data that does not need to be pinned, //! you can make those fields not structural and hence freely access them with a -//! mutable reference even when you just have [`Pin`]`<&mut Self>` (such as in your own +//! mutable reference even when you just have [Pin]<[&mut] Self> (such as in your own //! [`poll`] implementation). //! -//! [`Deref`]: crate::ops::Deref -//! [`DerefMut`]: crate::ops::DerefMut -//! [`mem::swap`]: crate::mem::swap -//! [`mem::forget`]: crate::mem::forget -//! [`Box`]: ../../std/boxed/struct.Box.html -//! [`Vec`]: ../../std/vec/struct.Vec.html -//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len -//! [`Box`]: ../../std/boxed/struct.Box.html -//! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop -//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push -//! [`Rc`]: ../../std/rc/struct.Rc.html -//! [`RefCell`]: crate::cell::RefCell -//! [`drop`]: Drop::drop -//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html -//! [`Some(v)`]: Some -//! [`ptr::write`]: crate::ptr::write -//! [`Future`]: crate::future::Future +//! [Deref]: crate::ops::Deref "ops::Deref" +//! [`Deref`]: crate::ops::Deref "ops::Deref" +//! [Target]: crate::ops::Deref::Target "ops::Deref::Target" +//! [`DerefMut`]: crate::ops::DerefMut "ops::DerefMut" +//! [`mem::swap`]: crate::mem::swap "mem::swap" +//! [`mem::forget`]: crate::mem::forget "mem::forget" +//! [Vec]: ../../std/vec/struct.Vec.html "Vec" +//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len "Vec::set_len" +//! [Box]: ../../std/boxed/struct.Box.html "Box" +//! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop "Vec::pop" +//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push "Vec::push" +//! [Rc]: ../../std/rc/struct.Rc.html "rc::Rc" +//! [RefCell]: crate::cell::RefCell "cell::RefCell" +//! [`drop`]: Drop::drop "Drop::drop" +//! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque" +//! [`ptr::write`]: crate::ptr::write "ptr::write" +//! [`Future`]: crate::future::Future "future::Future" //! [drop-impl]: #drop-implementation //! [drop-guarantee]: #drop-guarantee -//! [`poll`]: crate::future::Future::poll +//! [`poll`]: crate::future::Future::poll "future::Future::poll" +//! [&]: ../../std/primitive.reference.html "shared reference" +//! [&mut]: ../../std/primitive.reference.html "mutable reference" +//! [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" #![stable(feature = "pin", since = "1.33.0")] diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 7d33ca8bb6..c89fe57cb0 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -67,7 +67,6 @@ pub use crate::macros::builtin::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::macros::builtin::derive; @@ -80,7 +79,6 @@ pub use crate::macros::builtin::derive; #[doc(no_inline)] pub use crate::macros::builtin::cfg_accessible; -#[cfg(not(bootstrap))] #[unstable( feature = "cfg_eval", issue = "82679", diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index b511466acd..b9b2ba9ae6 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -51,7 +51,6 @@ impl *const T { /// Decompose a (possibly wide) pointer into is address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts`]. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] @@ -184,8 +183,7 @@ impl *const T { /// Behavior: /// /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * The computed offset, **in bytes**, cannot overflow an `isize`. /// @@ -210,6 +208,7 @@ impl *const T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_offset`]: #method.wrapping_offset + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -227,7 +226,7 @@ impl *const T { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const unsafe fn offset(self, count: isize) -> *const T where T: Sized, @@ -245,9 +244,8 @@ impl *const T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer remains attached to the same allocated object that `self` points to. - /// It may *not* be used to access a different allocated object. Note that in Rust, every - /// (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not + /// be used to read or write other allocated objects. /// /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still @@ -265,10 +263,8 @@ impl *const T { /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other /// words, leaving the allocated object and then re-entering it later is permitted. /// - /// If you need to cross object boundaries, cast the pointer to an integer and - /// do the arithmetic there. - /// /// [`offset`]: #method.offset + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -292,7 +288,7 @@ impl *const T { #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const fn wrapping_offset(self, count: isize) -> *const T where T: Sized, @@ -314,8 +310,7 @@ impl *const T { /// Behavior: /// /// * Both the starting and other pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. /// (See below for an example.) @@ -345,6 +340,7 @@ impl *const T { /// such large allocations either.) /// /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object /// /// # Panics /// @@ -468,8 +464,7 @@ impl *const T { /// Behavior: /// /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * The computed offset, **in bytes**, cannot overflow an `isize`. /// @@ -494,6 +489,7 @@ impl *const T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_add`]: #method.wrapping_add + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -511,7 +507,7 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const unsafe fn add(self, count: usize) -> Self where T: Sized, @@ -532,8 +528,7 @@ impl *const T { /// Behavior: /// /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * The computed offset cannot exceed `isize::MAX` **bytes**. /// @@ -558,6 +553,7 @@ impl *const T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_sub`]: #method.wrapping_sub + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -594,9 +590,8 @@ impl *const T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer remains attached to the same allocated object that `self` points to. - /// It may *not* be used to access a different allocated object. Note that in Rust, every - /// (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not + /// be used to read or write other allocated objects. /// /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still @@ -614,10 +609,8 @@ impl *const T { /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the /// allocated object and then re-entering it later is permitted. /// - /// If you need to cross object boundaries, cast the pointer to an integer and - /// do the arithmetic there. - /// /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -641,7 +634,7 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const fn wrapping_add(self, count: usize) -> Self where T: Sized, @@ -659,9 +652,8 @@ impl *const T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer remains attached to the same allocated object that `self` points to. - /// It may *not* be used to access a different allocated object. Note that in Rust, every - /// (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not + /// be used to read or write other allocated objects. /// /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still @@ -679,10 +671,8 @@ impl *const T { /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the /// allocated object and then re-entering it later is permitted. /// - /// If you need to cross object boundaries, cast the pointer to an integer and - /// do the arithmetic there. - /// /// [`sub`]: #method.sub + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -734,7 +724,7 @@ impl *const T { /// #![feature(set_ptr_value)] /// # use core::fmt::Debug; /// let arr: [i32; 3] = [1, 2, 3]; - /// let mut ptr = &arr[0] as *const dyn Debug; + /// let mut ptr = arr.as_ptr() as *const dyn Debug; /// let thin = ptr as *const u8; /// unsafe { /// ptr = ptr.set_ptr_value(thin.add(8)); @@ -924,13 +914,6 @@ impl *const [T] { #[unstable(feature = "slice_ptr_len", issue = "71146")] #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { - #[cfg(bootstrap)] - { - // SAFETY: this is safe because `*const [T]` and `FatPtr` have the same layout. - // Only `std` can make this guarantee. - unsafe { Repr { rust: self }.raw }.len - } - #[cfg(not(bootstrap))] metadata(self) } @@ -997,7 +980,7 @@ impl *const [T] { /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single allocated object! + /// * The entire memory range of this slice must be contained within a single [allocated object]! /// Slices can never span across multiple allocated objects. /// /// * The pointer must be aligned even for zero-length slices. One @@ -1019,6 +1002,7 @@ impl *const [T] { /// See also [`slice::from_raw_parts`][]. /// /// [valid]: crate::ptr#safety + /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index fd24469bd3..28044e0651 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -55,6 +55,14 @@ //! has size 0, i.e., even if memory is not actually touched. Consider using //! [`NonNull::dangling`] in such cases. //! +//! ## Allocated object +//! +//! For several operations, such as [`offset`] or field projections (`expr.field`), the notion of an +//! "allocated object" becomes relevant. An allocated object is a contiguous region of memory. +//! Common examples of allocated objects include stack-allocated variables (each variable is a +//! separate allocated object), heap allocations (each allocation created by the global allocator is +//! a separate allocated object), and `static` variables. +//! //! [aliasing]: ../../nomicon/aliasing.html //! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer //! [ub]: ../../reference/behavior-considered-undefined.html @@ -82,11 +90,8 @@ pub use crate::intrinsics::copy; #[doc(inline)] pub use crate::intrinsics::write_bytes; -#[cfg(not(bootstrap))] mod metadata; -#[cfg(not(bootstrap))] pub(crate) use metadata::PtrRepr; -#[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin}; @@ -205,7 +210,8 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_ptr_null", since = "1.32.0")] +#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] +#[rustc_diagnostic_item = "ptr_null"] pub const fn null() -> *const T { 0 as *const T } @@ -223,38 +229,12 @@ pub const fn null() -> *const T { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_ptr_null", since = "1.32.0")] +#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] +#[rustc_diagnostic_item = "ptr_null_mut"] pub const fn null_mut() -> *mut T { 0 as *mut T } -#[cfg(bootstrap)] -#[repr(C)] -pub(crate) union Repr { - pub(crate) rust: *const [T], - rust_mut: *mut [T], - pub(crate) raw: FatPtr, -} - -#[cfg(bootstrap)] -#[repr(C)] -pub(crate) struct FatPtr { - data: *const T, - pub(crate) len: usize, -} - -#[cfg(bootstrap)] -// Manual impl needed to avoid `T: Clone` bound. -impl Clone for FatPtr { - fn clone(&self) -> Self { - *self - } -} - -#[cfg(bootstrap)] -// Manual impl needed to avoid `T: Copy` bound. -impl Copy for FatPtr {} - /// Forms a raw slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes. @@ -279,14 +259,6 @@ impl Copy for FatPtr {} #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { - #[cfg(bootstrap)] - { - // SAFETY: Accessing the value from the `Repr` union is safe since *const [T] - // and FatPtr have the same memory layouts. Only std can make this - // guarantee. - unsafe { Repr { raw: FatPtr { data, len } }.rust } - } - #[cfg(not(bootstrap))] from_raw_parts(data.cast(), len) } @@ -319,13 +291,6 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { - #[cfg(bootstrap)] - { - // SAFETY: Accessing the value from the `Repr` union is safe since *mut [T] - // and FatPtr have the same memory layouts - unsafe { Repr { raw: FatPtr { data, len } }.rust_mut } - } - #[cfg(not(bootstrap))] from_raw_parts_mut(data.cast(), len) } @@ -464,19 +429,32 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { #[inline] pub(crate) unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { - // For types smaller than the block optimization below, - // just swap directly to avoid pessimizing codegen. - if mem::size_of::() < 32 { - // SAFETY: the caller must guarantee that `x` and `y` are valid - // for writes, properly aligned, and non-overlapping. - unsafe { - let z = read(x); - copy_nonoverlapping(y, x, 1); - write(y, z); + // 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 + // into the (unoptimized) direct swapping implementation, so we disable it. + // FIXME(eddyb) the block optimization also prevents MIR optimizations from + // understanding `mem::replace`, `Option::take`, etc. - a better overall + // solution might be to make `swap_nonoverlapping` into an intrinsic, which + // a backend can choose to implement using the block optimization, or not. + #[cfg(not(target_arch = "spirv"))] + { + // Only apply the block optimization in `swap_nonoverlapping_bytes` for types + // at least as large as the block size, to avoid pessimizing codegen. + if mem::size_of::() >= 32 { + // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`. + unsafe { swap_nonoverlapping(x, y, 1) }; + return; } - } else { - // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`. - unsafe { swap_nonoverlapping(x, y, 1) }; + } + + // Direct swapping, for the cases not going through the block optimization. + // SAFETY: the caller must guarantee that `x` and `y` are valid + // for writes, properly aligned, and non-overlapping. + unsafe { + let z = read(x); + copy_nonoverlapping(y, x, 1); + write(y, z); } } @@ -765,6 +743,7 @@ pub const unsafe fn read(src: *const T) -> T { /// unaligned: 0x01020304, /// }; /// +/// #[allow(unaligned_references)] /// let v = unsafe { /// // Here we attempt to take the address of a 32-bit integer which is not aligned. /// let unaligned = @@ -962,6 +941,7 @@ pub unsafe fn write(dst: *mut T, src: T) { /// let v = 0x01020304; /// let mut packed: Packed = unsafe { std::mem::zeroed() }; /// +/// #[allow(unaligned_references)] /// let v = unsafe { /// // Here we attempt to take the address of a 32-bit integer which is not aligned. /// let unaligned = @@ -1516,6 +1496,10 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// +/// Note, however, that the `expr` in `addr_of!(expr)` is still subject to all +/// the usual rules. In particular, `addr_of!(*ptr::null())` is Undefined +/// Behavior because it dereferences a NULL pointer. +/// /// # Example /// /// ``` @@ -1532,6 +1516,10 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } /// let raw_f2 = ptr::addr_of!(packed.f2); /// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); /// ``` +/// +/// See [`addr_of_mut`] for how to create a pointer to unininitialized data. +/// Doing that with `addr_of` would not make much sense since one could only +/// read the data, and that would be Undefined Behavior. #[stable(feature = "raw_ref_macros", since = "1.51.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(raw_ref_op)] @@ -1548,7 +1536,13 @@ pub macro addr_of($place:expr) { /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// -/// # Example +/// Note, however, that the `expr` in `addr_of_mut!(expr)` is still subject to all +/// the usual rules. In particular, `addr_of_mut!(*ptr::null_mut())` is Undefined +/// Behavior because it dereferences a NULL pointer. +/// +/// # Examples +/// +/// **Creating a pointer to unaligned data:** /// /// ``` /// use std::ptr; @@ -1565,6 +1559,23 @@ pub macro addr_of($place:expr) { /// unsafe { raw_f2.write_unaligned(42); } /// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference. /// ``` +/// +/// **Creating a pointer to uninitialized data:** +/// +/// ```rust +/// use std::{ptr, mem::MaybeUninit}; +/// +/// struct Demo { +/// field: bool, +/// } +/// +/// let mut uninit = MaybeUninit::::uninit(); +/// // `&uninit.as_mut().field` would create a reference to an uninitialized `bool`, +/// // and thus be Undefined Behavior! +/// let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) }; +/// unsafe { f1_ptr.write(true); } +/// let init = unsafe { uninit.assume_init() }; +/// ``` #[stable(feature = "raw_ref_macros", since = "1.51.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(raw_ref_op)] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index a9de2333bc..16f6efc374 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -50,7 +50,6 @@ impl *mut T { /// Decompose a (possibly wide) pointer into is address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts_mut`]. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] @@ -189,8 +188,7 @@ impl *mut T { /// Behavior: /// /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * The computed offset, **in bytes**, cannot overflow an `isize`. /// @@ -215,6 +213,7 @@ impl *mut T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_offset`]: #method.wrapping_offset + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -232,7 +231,7 @@ impl *mut T { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const unsafe fn offset(self, count: isize) -> *mut T where T: Sized, @@ -251,9 +250,8 @@ impl *mut T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer remains attached to the same allocated object that `self` points to. - /// It may *not* be used to access a different allocated object. Note that in Rust, every - /// (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not + /// be used to read or write other allocated objects. /// /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still @@ -271,10 +269,8 @@ impl *mut T { /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other /// words, leaving the allocated object and then re-entering it later is permitted. /// - /// If you need to cross object boundaries, cast the pointer to an integer and - /// do the arithmetic there. - /// /// [`offset`]: #method.offset + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -298,7 +294,7 @@ impl *mut T { #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const fn wrapping_offset(self, count: isize) -> *mut T where T: Sized, @@ -485,8 +481,7 @@ impl *mut T { /// Behavior: /// /// * Both the starting and other pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. /// (See below for an example.) @@ -516,6 +511,7 @@ impl *mut T { /// such large allocations either.) /// /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object /// /// # Panics /// @@ -575,8 +571,7 @@ impl *mut T { /// Behavior: /// /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * The computed offset, **in bytes**, cannot overflow an `isize`. /// @@ -618,7 +613,7 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const unsafe fn add(self, count: usize) -> Self where T: Sized, @@ -639,8 +634,7 @@ impl *mut T { /// Behavior: /// /// * Both the starting and resulting pointer must be either in bounds or one - /// byte past the end of the same allocated object. Note that in Rust, - /// every (stack-allocated) variable is considered a separate allocated object. + /// byte past the end of the same [allocated object]. /// /// * The computed offset cannot exceed `isize::MAX` **bytes**. /// @@ -665,6 +659,7 @@ impl *mut T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_sub`]: #method.wrapping_sub + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -701,9 +696,8 @@ impl *mut T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer remains attached to the same allocated object that `self` points to. - /// It may *not* be used to access a different allocated object. Note that in Rust, every - /// (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not + /// be used to read or write other allocated objects. /// /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still @@ -721,10 +715,8 @@ impl *mut T { /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the /// allocated object and then re-entering it later is permitted. /// - /// If you need to cross object boundaries, cast the pointer to an integer and - /// do the arithmetic there. - /// /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -748,7 +740,7 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")] - #[inline] + #[inline(always)] pub const fn wrapping_add(self, count: usize) -> Self where T: Sized, @@ -766,9 +758,8 @@ impl *mut T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer remains attached to the same allocated object that `self` points to. - /// It may *not* be used to access a different allocated object. Note that in Rust, every - /// (stack-allocated) variable is considered a separate allocated object. + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not + /// be used to read or write other allocated objects. /// /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still @@ -786,10 +777,8 @@ impl *mut T { /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the /// allocated object and then re-entering it later is permitted. /// - /// If you need to cross object boundaries, cast the pointer to an integer and - /// do the arithmetic there. - /// /// [`sub`]: #method.sub + /// [allocated object]: crate::ptr#allocated-object /// /// # Examples /// @@ -841,7 +830,7 @@ impl *mut T { /// #![feature(set_ptr_value)] /// # use core::fmt::Debug; /// let mut arr: [i32; 3] = [1, 2, 3]; - /// let mut ptr = &mut arr[0] as *mut dyn Debug; + /// let mut ptr = arr.as_mut_ptr() as *mut dyn Debug; /// let thin = ptr as *mut u8; /// unsafe { /// ptr = ptr.set_ptr_value(thin.add(8)); @@ -1184,13 +1173,6 @@ impl *mut [T] { #[unstable(feature = "slice_ptr_len", issue = "71146")] #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { - #[cfg(bootstrap)] - { - // SAFETY: this is safe because `*const [T]` and `FatPtr` have the same layout. - // Only `std` can make this guarantee. - unsafe { Repr { rust_mut: self }.raw }.len - } - #[cfg(not(bootstrap))] metadata(self) } @@ -1260,7 +1242,7 @@ impl *mut [T] { /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single allocated object! + /// * The entire memory range of this slice must be contained within a single [allocated object]! /// Slices can never span across multiple allocated objects. /// /// * The pointer must be aligned even for zero-length slices. One @@ -1282,6 +1264,7 @@ impl *mut [T] { /// See also [`slice::from_raw_parts`][]. /// /// [valid]: crate::ptr#safety + /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { @@ -1310,7 +1293,7 @@ impl *mut [T] { /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::()` /// many bytes, and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single allocated object! + /// * The entire memory range of this slice must be contained within a single [allocated object]! /// Slices can never span across multiple allocated objects. /// /// * The pointer must be aligned even for zero-length slices. One @@ -1332,6 +1315,7 @@ impl *mut [T] { /// See also [`slice::from_raw_parts_mut`][]. /// /// [valid]: crate::ptr#safety + /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 8d533cd6be..e525f61604 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -72,7 +72,7 @@ impl NonNull { /// sentinel value. Types that lazily allocate must track initialization by /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] - #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.32.0")] + #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.36.0")] #[inline] pub const fn dangling() -> Self { // SAFETY: mem::align_of() returns a non-zero usize which is then casted @@ -110,7 +110,7 @@ impl NonNull { /// [the module documentation]: crate::ptr#safety #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_ref(&self) -> &MaybeUninit { + pub unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.cast().as_ptr() } @@ -142,7 +142,7 @@ impl NonNull { /// [the module documentation]: crate::ptr#safety #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_mut(&mut self) -> &mut MaybeUninit { + pub unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &mut *self.cast().as_ptr() } @@ -156,7 +156,7 @@ impl NonNull { /// /// `ptr` must be non-null. #[stable(feature = "nonnull", since = "1.25.0")] - #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.32.0")] + #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.25.0")] #[inline] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. @@ -181,7 +181,6 @@ impl NonNull { /// See the documentation of [`std::ptr::from_raw_parts`] for more details. /// /// [`std::ptr::from_raw_parts`]: crate::ptr::from_raw_parts - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] @@ -198,7 +197,6 @@ impl NonNull { /// Decompose a (possibly wide) pointer into is address and metadata components. /// /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`]. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] @@ -244,7 +242,7 @@ impl NonNull { /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - pub unsafe fn as_ref(&self) -> &T { + pub unsafe fn as_ref<'a>(&self) -> &'a T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.as_ptr() } @@ -280,7 +278,7 @@ impl NonNull { /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { + pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a mutable reference. unsafe { &mut *self.as_ptr() } @@ -288,7 +286,7 @@ impl NonNull { /// Casts to a pointer of another type. #[stable(feature = "nonnull_cast", since = "1.27.0")] - #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.32.0")] + #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.36.0")] #[inline] pub const fn cast(self) -> NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null @@ -427,7 +425,7 @@ impl NonNull<[T]> { /// [valid]: crate::ptr#safety #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice(&self) -> &[MaybeUninit] { + pub unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) } } @@ -488,7 +486,7 @@ impl NonNull<[T]> { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice_mut(&self) -> &mut [MaybeUninit] { + pub unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) } } diff --git a/library/core/src/raw.rs b/library/core/src/raw.rs index 1227d9b01f..6d1e28f4cd 100644 --- a/library/core/src/raw.rs +++ b/library/core/src/raw.rs @@ -1,5 +1,9 @@ #![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. //! diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 2ce8a703c1..e0071f806a 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -228,7 +228,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; -use crate::ops::{self, Deref, DerefMut}; +use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). @@ -506,8 +506,8 @@ impl Result { } } - /// Applies a function to the contained value (if [`Ok`]), - /// or returns the provided default (if [`Err`]). + /// Returns the provided default (if [`Err`]), or + /// applies a function to the contained value (if [`Ok`]), /// /// Arguments passed to `map_or` are eagerly evaluated; if you are passing /// the result of a function call, it is recommended to use [`map_or_else`], @@ -533,9 +533,9 @@ impl Result { } } - /// Maps a `Result` to `U` by applying a function to a - /// contained [`Ok`] value, or a fallback function to a - /// contained [`Err`] value. + /// Maps a `Result` to `U` by applying a fallback function to a + /// contained [`Err`] value, or a default function to a + /// contained [`Ok`] value. /// /// This function can be used to unpack a successful result /// while handling an error. @@ -1167,6 +1167,42 @@ impl> Result { } } +#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] +impl, E> Result { + /// Returns the contained [`Err`] value, but never panics. + /// + /// Unlike [`unwrap_err`], this method is known to never panic on the + /// result types it is implemented for. Therefore, it can be used + /// instead of `unwrap_err` as a maintainability safeguard that will fail + /// to compile if the ok type of the `Result` is later changed + /// to a type that can actually occur. + /// + /// [`unwrap_err`]: Result::unwrap_err + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(never_type)] + /// # #![feature(unwrap_infallible)] + /// + /// fn only_bad_news() -> Result { + /// Err("Oops, it failed".into()) + /// } + /// + /// let error: String = only_bad_news().into_err(); + /// println!("{}", error); + /// ``` + #[inline] + pub fn into_err(self) -> E { + match self { + Ok(x) => x.into(), + Err(e) => e, + } + } +} + impl Result { /// Converts from `Result` (or `&Result`) to `Result<&::Target, &E>`. /// @@ -1610,3 +1646,32 @@ impl ops::Try for Result { Err(v) } } + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::TryV2 for Result { + type Output = T; + type Residual = Result; + + #[inline] + fn from_output(output: Self::Output) -> Self { + Ok(output) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Ok(v) => ControlFlow::Continue(v), + Err(e) => ControlFlow::Break(Err(e)), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl> ops::FromResidual> for Result { + #[inline] + fn from_residual(residual: Result) -> Self { + match residual { + Err(e) => Err(From::from(e)), + } + } +} diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 42032bc903..906dcb1e8b 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -1,6 +1,10 @@ //! Operations on ASCII `[u8]`. +use crate::ascii; +use crate::fmt::{self, Write}; +use crate::iter; use crate::mem; +use crate::ops; #[lang = "slice_u8"] #[cfg(not(test))] @@ -19,7 +23,7 @@ impl [u8] { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { - self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq_ignore_ascii_case(b)) + self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) } /// Converts this slice to its ASCII upper case equivalent in-place. @@ -55,6 +59,95 @@ impl [u8] { byte.make_ascii_lowercase(); } } + + /// Returns an iterator that produces an escaped version of this slice, + /// treating it as an ASCII string. + /// + /// # Examples + /// + /// ``` + /// #![feature(inherent_ascii_escape)] + /// + /// let s = b"0\t\r\n'\"\\\x9d"; + /// let escaped = s.escape_ascii().to_string(); + /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d"); + /// ``` + #[unstable(feature = "inherent_ascii_escape", issue = "77174")] + pub fn escape_ascii(&self) -> EscapeAscii<'_> { + EscapeAscii { inner: self.iter().flat_map(EscapeByte) } + } +} + +impl_fn_for_zst! { + #[derive(Clone)] + struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault { + ascii::escape_default(*byte) + }; +} + +/// An iterator over the escaped version of a byte slice. +/// +/// This `struct` is created by the [`slice::escape_ascii`] method. See its +/// documentation for more information. +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +#[derive(Clone)] +pub struct EscapeAscii<'a> { + inner: iter::FlatMap, ascii::EscapeDefault, EscapeByte>, +} + +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::Iterator for EscapeAscii<'a> { + type Item = u8; + #[inline] + fn next(&mut self) -> Option { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Fold: FnMut(Acc, Self::Item) -> R, + R: ops::Try, + { + self.inner.try_fold(init, fold) + } + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.fold(init, fold) + } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> { + fn next_back(&mut self) -> Option { + self.inner.next_back() + } +} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::ExactSizeIterator for EscapeAscii<'a> {} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::FusedIterator for EscapeAscii<'a> {} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> fmt::Display for EscapeAscii<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.clone().try_for_each(|b| f.write_char(b as char)) + } +} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> fmt::Debug for EscapeAscii<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EscapeAscii").finish_non_exhaustive() + } } /// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index c92b37b14b..f722430354 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -81,6 +81,8 @@ mod private_slice_index { impl Sealed for ops::RangeInclusive {} #[stable(feature = "slice_get_slice", since = "1.28.0")] impl Sealed for ops::RangeToInclusive {} + #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] + impl Sealed for (ops::Bound, ops::Bound) {} } /// A helper trait used for indexing operations. @@ -546,3 +548,113 @@ where ops::Range { start, end } } + +/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking +fn into_range_unchecked( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> ops::Range { + use ops::Bound; + let start = match start { + Bound::Included(i) => i, + Bound::Excluded(i) => i + 1, + Bound::Unbounded => 0, + }; + let end = match end { + Bound::Included(i) => i + 1, + Bound::Excluded(i) => i, + Bound::Unbounded => len, + }; + start..end +} + +/// Convert pair of `ops::Bound`s into `ops::Range`. +/// Returns `None` on overflowing indices. +fn into_range( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> Option> { + use ops::Bound; + let start = match start { + Bound::Included(start) => start, + Bound::Excluded(start) => start.checked_add(1)?, + Bound::Unbounded => 0, + }; + + let end = match end { + Bound::Included(end) => end.checked_add(1)?, + Bound::Excluded(end) => end, + Bound::Unbounded => len, + }; + + // Don't bother with checking `start < end` and `end <= len` + // since these checks are handled by `Range` impls + + Some(start..end) +} + +/// Convert pair of `ops::Bound`s into `ops::Range`. +/// Panics on overflowing indices. +fn into_slice_range( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> ops::Range { + use ops::Bound; + let start = match start { + Bound::Included(start) => start, + Bound::Excluded(start) => { + start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) + } + Bound::Unbounded => 0, + }; + + let end = match end { + Bound::Included(end) => { + end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) + } + Bound::Excluded(end) => end, + Bound::Unbounded => len, + }; + + // Don't bother with checking `start < end` and `end <= len` + // since these checks are handled by `Range` impls + + start..end +} + +#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] +unsafe impl SliceIndex<[T]> for (ops::Bound, ops::Bound) { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&Self::Output> { + into_range(slice.len(), self)?.get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + into_range(slice.len(), self)?.get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &Self::Output { + into_slice_range(slice.len(), self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + into_slice_range(slice.len(), self).index_mut(slice) + } +} diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index c82b76df6f..1ee662c6c8 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -286,7 +286,6 @@ impl<'a, T> IterMut<'a, T> { /// Basic usage: /// /// ``` - /// # #![feature(slice_iter_mut_as_slice)] /// let mut slice: &mut [usize] = &mut [1, 2, 3]; /// /// // First, we get the iterator: @@ -299,12 +298,19 @@ impl<'a, T> IterMut<'a, T> { /// // Now `as_slice` returns "[2, 3]": /// assert_eq!(iter.as_slice(), &[2, 3]); /// ``` - #[unstable(feature = "slice_iter_mut_as_slice", reason = "recently added", issue = "58957")] + #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] pub fn as_slice(&self) -> &[T] { self.make_slice() } } +#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] +impl AsRef<[T]> for IterMut<'_, T> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}} /// An internal abstraction over the splitting iterators, so that diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 417a106b99..ec28cdd1ba 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -81,6 +81,9 @@ pub use index::SliceIndex; #[unstable(feature = "slice_range", issue = "76393")] pub use index::range; +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +pub use ascii::EscapeAscii; + #[lang = "slice"] #[cfg(not(test))] impl [T] { @@ -94,28 +97,19 @@ impl [T] { /// ``` #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")] + #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) #[rustc_allow_const_fn_unstable(const_fn_union)] pub const fn len(&self) -> usize { - #[cfg(bootstrap)] - { - // SAFETY: this is safe because `&[T]` and `FatPtr` have the same layout. - // Only `std` can make this guarantee. - unsafe { crate::ptr::Repr { rust: self }.raw.len } - } - #[cfg(not(bootstrap))] - { - // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable. - // As of this writing this causes a "Const-stable functions can only call other - // const-stable functions" error. - - // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T - // and PtrComponents have the same memory layouts. Only std can make this - // guarantee. - unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata } - } + // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable. + // As of this writing this causes a "Const-stable functions can only call other + // const-stable functions" error. + + // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T + // and PtrComponents have the same memory layouts. Only std can make this + // guarantee. + unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata } } /// Returns `true` if the slice has a length of 0. @@ -127,7 +121,7 @@ impl [T] { /// assert!(!a.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.32.0")] + #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.39.0")] #[inline] pub const fn is_empty(&self) -> bool { self.len() == 0 @@ -145,8 +139,9 @@ impl [T] { /// assert_eq!(None, w.first()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn first(&self) -> Option<&T> { + pub const fn first(&self) -> Option<&T> { if let [first, ..] = self { Some(first) } else { None } } @@ -163,8 +158,9 @@ impl [T] { /// assert_eq!(x, &[5, 1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn first_mut(&mut self) -> Option<&mut T> { + pub const fn first_mut(&mut self) -> Option<&mut T> { if let [first, ..] = self { Some(first) } else { None } } @@ -181,8 +177,9 @@ impl [T] { /// } /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn split_first(&self) -> Option<(&T, &[T])> { + pub const fn split_first(&self) -> Option<(&T, &[T])> { if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } @@ -201,8 +198,9 @@ impl [T] { /// assert_eq!(x, &[3, 4, 5]); /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { + pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } @@ -219,8 +217,9 @@ impl [T] { /// } /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn split_last(&self) -> Option<(&T, &[T])> { + pub const fn split_last(&self) -> Option<(&T, &[T])> { if let [init @ .., last] = self { Some((last, init)) } else { None } } @@ -239,8 +238,9 @@ impl [T] { /// assert_eq!(x, &[4, 5, 3]); /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { + pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { if let [init @ .., last] = self { Some((last, init)) } else { None } } @@ -256,8 +256,9 @@ impl [T] { /// assert_eq!(None, w.last()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn last(&self) -> Option<&T> { + pub const fn last(&self) -> Option<&T> { if let [.., last] = self { Some(last) } else { None } } @@ -274,8 +275,9 @@ impl [T] { /// assert_eq!(x, &[0, 1, 10]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")] #[inline] - pub fn last_mut(&mut self) -> Option<&mut T> { + pub const fn last_mut(&mut self) -> Option<&mut T> { if let [.., last] = self { Some(last) } else { None } } @@ -2204,6 +2206,8 @@ impl [T] { } else if cmp == Greater { right = mid; } else { + // SAFETY: same as the `get_unchecked` above + unsafe { crate::intrinsics::assume(mid < self.len()) }; return Ok(mid); } @@ -2252,8 +2256,7 @@ impl [T] { // in crate `alloc`, and as such doesn't exists yet when building `core`. // links to downstream crate: #74481. Since primitives are only documented in // libstd (#73423), this never leads to broken links in practice. - #[cfg_attr(not(bootstrap), allow(rustdoc::broken_intra_doc_links))] - #[cfg_attr(bootstrap, allow(broken_intra_doc_links))] + #[allow(rustdoc::broken_intra_doc_links)] #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] #[inline] pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result diff --git a/library/core/src/slice/specialize.rs b/library/core/src/slice/specialize.rs index 16a9588989..425cf71626 100644 --- a/library/core/src/slice/specialize.rs +++ b/library/core/src/slice/specialize.rs @@ -1,3 +1,4 @@ +use crate::mem::{size_of, transmute_copy}; use crate::ptr::write_bytes; pub(super) trait SpecFill { @@ -17,42 +18,18 @@ impl SpecFill for [T] { } impl SpecFill for [T] { - default fn spec_fill(&mut self, value: T) { - for item in self.iter_mut() { - *item = value; - } - } -} - -impl SpecFill for [u8] { - fn spec_fill(&mut self, value: u8) { - // SAFETY: this is slice of u8 - unsafe { - let ptr = self.as_mut_ptr(); - let len = self.len(); - write_bytes(ptr, value, len); - } - } -} - -impl SpecFill for [i8] { - fn spec_fill(&mut self, value: i8) { - // SAFETY: this is slice of i8 - unsafe { - let ptr = self.as_mut_ptr(); - let len = self.len(); - write_bytes(ptr, value as u8, len); - } - } -} - -impl SpecFill for [bool] { - fn spec_fill(&mut self, value: bool) { - // SAFETY: this is slice of bool - unsafe { - let ptr = self.as_mut_ptr(); - let len = self.len(); - write_bytes(ptr, value as u8, len); + fn spec_fill(&mut self, value: T) { + if size_of::() == 1 { + // SAFETY: The size_of check above ensures that values are 1 byte wide, as required + // for the transmute and write_bytes + unsafe { + let value: u8 = transmute_copy(&value); + write_bytes(self.as_mut_ptr(), value, self.len()); + } + } else { + for item in self.iter_mut() { + *item = value; + } } } } diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 4eac017f91..724137aba9 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -189,6 +189,30 @@ impl<'a> CharIndices<'a> { pub fn as_str(&self) -> &'a str { self.iter.as_str() } + + /// Returns the byte position of the next character, or the length + /// of the underlying string if there are no more characters. + /// + /// # Examples + /// + /// ``` + /// #![feature(char_indices_offset)] + /// let mut chars = "a楽".char_indices(); + /// + /// assert_eq!(chars.offset(), 0); + /// assert_eq!(chars.next(), Some((0, 'a'))); + /// + /// assert_eq!(chars.offset(), 1); + /// assert_eq!(chars.next(), Some((1, '楽'))); + /// + /// assert_eq!(chars.offset(), 4); + /// assert_eq!(chars.next(), None); + /// ``` + #[inline] + #[unstable(feature = "char_indices_offset", issue = "83871")] + pub fn offset(&self) -> usize { + self.front_offset + } } /// An iterator over the bytes of a string slice. @@ -1359,7 +1383,7 @@ pub struct EncodeUtf16<'a> { #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for EncodeUtf16<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("EncodeUtf16 { .. }") + f.debug_struct("EncodeUtf16").finish_non_exhaustive() } } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 67c074b394..95dd54976b 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -15,7 +15,7 @@ mod validations; use self::pattern::Pattern; use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher}; -use crate::char; +use crate::char::{self, EscapeDebugExtArgs}; use crate::mem; use crate::slice::{self, SliceIndex}; @@ -140,7 +140,7 @@ impl str { /// ``` #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_str_len", since = "1.32.0")] + #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")] #[inline] pub const fn len(&self) -> usize { self.as_bytes().len() @@ -161,7 +161,7 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_str_is_empty", since = "1.32.0")] + #[rustc_const_stable(feature = "const_str_is_empty", since = "1.39.0")] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -217,7 +217,7 @@ impl str { /// assert_eq!(b"bors", bytes); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")] #[inline(always)] #[allow(unused_attributes)] #[rustc_allow_const_fn_unstable(const_fn_transmute)] @@ -2342,7 +2342,7 @@ impl str { EscapeDebug { inner: chars .next() - .map(|first| first.escape_debug_ext(true)) + .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)) .into_iter() .flatten() .chain(chars.flat_map(CharEscapeDebugContinue)), @@ -2460,7 +2460,11 @@ impl_fn_for_zst! { #[derive(Clone)] struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug { - c.escape_debug_ext(false) + c.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: false, + escape_single_quote: true, + escape_double_quote: true + }) }; #[derive(Clone)] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index ca39224602..f1a115563f 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -78,7 +78,7 @@ //! ``` //! use std::sync::Arc; //! use std::sync::atomic::{AtomicUsize, Ordering}; -//! use std::thread; +//! use std::{hint, thread}; //! //! fn main() { //! let spinlock = Arc::new(AtomicUsize::new(1)); @@ -89,7 +89,9 @@ //! }); //! //! // Wait for the other thread to release the lock -//! while spinlock.load(Ordering::SeqCst) != 0 {} +//! while spinlock.load(Ordering::SeqCst) != 0 { +//! hint::spin_loop(); +//! } //! //! if let Err(panic) = thread.join() { //! println!("Thread had an error: {:?}", panic); @@ -283,7 +285,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_atomic_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] pub const fn new(v: bool) -> AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } @@ -837,7 +839,6 @@ impl AtomicBool { /// # Examples /// /// ```rust - /// #![feature(atomic_fetch_update)] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let x = AtomicBool::new(false); @@ -847,7 +848,7 @@ impl AtomicBool { /// assert_eq!(x.load(Ordering::SeqCst), false); /// ``` #[inline] - #[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")] + #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "8")] pub fn fetch_update( &self, @@ -883,7 +884,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_atomic_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] pub const fn new(p: *mut T) -> AtomicPtr { AtomicPtr { p: UnsafeCell::new(p) } } @@ -898,8 +899,10 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let mut atomic_ptr = AtomicPtr::new(&mut 10); - /// *atomic_ptr.get_mut() = &mut 5; + /// let mut data = 10; + /// let mut atomic_ptr = AtomicPtr::new(&mut data); + /// let mut other_data = 5; + /// *atomic_ptr.get_mut() = &mut other_data; /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5); /// ``` #[inline] @@ -916,9 +919,11 @@ impl AtomicPtr { /// #![feature(atomic_from_mut)] /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let mut some_ptr = &mut 123 as *mut i32; + /// let mut data = 123; + /// let mut some_ptr = &mut data as *mut i32; /// let a = AtomicPtr::from_mut(&mut some_ptr); - /// a.store(&mut 456, Ordering::Relaxed); + /// let mut other_data = 456; + /// a.store(&mut other_data, Ordering::Relaxed); /// assert_eq!(unsafe { *some_ptr }, 456); /// ``` #[inline] @@ -944,7 +949,8 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::AtomicPtr; /// - /// let atomic_ptr = AtomicPtr::new(&mut 5); + /// let mut data = 5; + /// let atomic_ptr = AtomicPtr::new(&mut data); /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5); /// ``` #[inline] @@ -1220,7 +1226,6 @@ impl AtomicPtr { /// # Examples /// /// ```rust - /// #![feature(atomic_fetch_update)] /// use std::sync::atomic::{AtomicPtr, Ordering}; /// /// let ptr: *mut _ = &mut 5; @@ -1239,7 +1244,7 @@ impl AtomicPtr { /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); /// ``` #[inline] - #[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")] + #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "ptr")] pub fn fetch_update( &self, @@ -2276,7 +2281,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), - rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"), stable(feature = "rust1", since = "1.0.0"), "isize", "", @@ -2296,7 +2301,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), - rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"), stable(feature = "rust1", since = "1.0.0"), "usize", "", diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 42c9d9f0cc..2765c21a46 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -1,6 +1,7 @@ #![stable(feature = "futures_api", since = "1.36.0")] -use crate::ops::Try; +use crate::convert; +use crate::ops::{self, ControlFlow, Try}; use crate::result::Result; /// Indicates whether a value is available or if the current task has been @@ -152,6 +153,36 @@ impl Try for Poll> { } } +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::TryV2 for Poll> { + type Output = Poll; + type Residual = Result; + + #[inline] + fn from_output(c: Self::Output) -> Self { + c.map(Ok) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)), + Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)), + Poll::Pending => ControlFlow::Continue(Poll::Pending), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl> ops::FromResidual> for Poll> { + #[inline] + fn from_residual(x: Result) -> Self { + match x { + Err(e) => Poll::Ready(Err(From::from(e))), + } + } +} + #[stable(feature = "futures_api", since = "1.36.0")] impl Try for Poll>> { type Ok = Poll>; @@ -177,3 +208,36 @@ impl Try for Poll>> { x.map(|x| x.map(Ok)) } } + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::TryV2 for Poll>> { + type Output = Poll>; + type Residual = Result; + + #[inline] + fn from_output(c: Self::Output) -> Self { + c.map(|x| x.map(Ok)) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))), + Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)), + Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)), + Poll::Pending => ControlFlow::Continue(Poll::Pending), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl> ops::FromResidual> + for Poll>> +{ + #[inline] + fn from_residual(x: Result) -> Self { + match x { + Err(e) => Poll::Ready(Some(Err(From::from(e)))), + } + } +} diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 8c0848c64a..bfea39e321 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -124,29 +124,32 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_zero)] /// use std::time::Duration; /// /// let duration = Duration::ZERO; /// assert!(duration.is_zero()); /// assert_eq!(duration.as_nanos(), 0); /// ``` - #[unstable(feature = "duration_zero", issue = "73544")] + #[stable(feature = "duration_zero", since = "1.53.0")] pub const ZERO: Duration = Duration::from_nanos(0); /// The maximum duration. /// - /// It is roughly equal to a duration of 584,942,417,355 years. + /// May vary by platform as necessary. Must be able to contain the difference between + /// two instances of [`Instant`] or two instances of [`SystemTime`]. + /// This constraint gives it a value of about 584,942,417,355 years in practice, + /// which is currently used on all platforms. /// /// # Examples /// /// ``` - /// #![feature(duration_constants)] /// use std::time::Duration; /// /// assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1)); /// ``` - #[unstable(feature = "duration_constants", issue = "57391")] + /// [`Instant`]: ../../std/time/struct.Instant.html + /// [`SystemTime`]: ../../std/time/struct.SystemTime.html + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] pub const MAX: Duration = Duration::new(u64::MAX, NANOS_PER_SEC - 1); /// Creates a new `Duration` from the specified number of whole seconds and @@ -269,7 +272,6 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_zero)] /// use std::time::Duration; /// /// assert!(Duration::ZERO.is_zero()); @@ -281,7 +283,8 @@ impl Duration { /// assert!(!Duration::from_nanos(1).is_zero()); /// assert!(!Duration::from_secs(1).is_zero()); /// ``` - #[unstable(feature = "duration_zero", issue = "73544")] + #[stable(feature = "duration_zero", since = "1.53.0")] + #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] #[inline] pub const fn is_zero(&self) -> bool { self.secs == 0 && self.nanos == 0 @@ -479,14 +482,13 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_saturating_ops)] /// #![feature(duration_constants)] /// use std::time::Duration; /// /// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1)); /// assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX); /// ``` - #[unstable(feature = "duration_saturating_ops", issue = "76416")] + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn saturating_add(self, rhs: Duration) -> Duration { @@ -537,14 +539,12 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_saturating_ops)] - /// #![feature(duration_zero)] /// use std::time::Duration; /// /// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1)); /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO); /// ``` - #[unstable(feature = "duration_saturating_ops", issue = "76416")] + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn saturating_sub(self, rhs: Duration) -> Duration { @@ -590,14 +590,13 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_saturating_ops)] /// #![feature(duration_constants)] /// use std::time::Duration; /// /// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2)); /// assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX); /// ``` - #[unstable(feature = "duration_saturating_ops", issue = "76416")] + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn saturating_mul(self, rhs: u32) -> Duration { diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 89c2a969c2..ce7480ce2e 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -1,24 +1,6 @@ -use core::array::{self, FixedSizeArray, IntoIter}; +use core::array::{self, IntoIter}; use core::convert::TryFrom; -#[test] -fn fixed_size_array() { - let mut array = [0; 64]; - let mut zero_sized = [(); 64]; - let mut empty_array = [0; 0]; - let mut empty_zero_sized = [(); 0]; - - assert_eq!(FixedSizeArray::as_slice(&array).len(), 64); - assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64); - assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0); - assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0); - - assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64); - assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64); - assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0); - assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0); -} - #[test] fn array_from_ref() { let value: String = "Hello World!".into(); diff --git a/library/core/tests/const_ptr.rs b/library/core/tests/const_ptr.rs index 4158a4dece..4acd059ab0 100644 --- a/library/core/tests/const_ptr.rs +++ b/library/core/tests/const_ptr.rs @@ -49,53 +49,3 @@ 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])]); -//} diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs index 129c121e8c..7580010a28 100644 --- a/library/core/tests/fmt/builders.rs +++ b/library/core/tests/fmt/builders.rs @@ -105,12 +105,7 @@ mod debug_struct { } assert_eq!("Foo { .. }", format!("{:?}", Foo)); - assert_eq!( - "Foo { - .. -}", - format!("{:#?}", Foo) - ); + assert_eq!("Foo { .. }", format!("{:#?}", Foo)); } #[test] diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs index ca5ae12ae2..4cd79687b5 100644 --- a/library/core/tests/iter/adapters/chain.rs +++ b/library/core/tests/iter/adapters/chain.rs @@ -174,14 +174,14 @@ fn test_iterator_chain_size_hint() { fn test_iterator_chain_unfused() { // Chain shouldn't be fused in its second iterator, depending on direction let mut iter = NonFused::new(empty()).chain(Toggle { is_empty: true }); - iter.next().unwrap_none(); - iter.next().unwrap(); - iter.next().unwrap_none(); + assert!(iter.next().is_none()); + assert!(iter.next().is_some()); + assert!(iter.next().is_none()); let mut iter = Toggle { is_empty: true }.chain(NonFused::new(empty())); - iter.next_back().unwrap_none(); - iter.next_back().unwrap(); - iter.next_back().unwrap_none(); + assert!(iter.next_back().is_none()); + assert!(iter.next_back().is_some()); + assert!(iter.next_back().is_none()); } #[test] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index b7fcc74036..35e4d213dd 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,6 +1,5 @@ #![feature(alloc_layout_extra)] #![feature(array_chunks)] -#![feature(array_from_ref)] #![feature(array_methods)] #![feature(array_map)] #![feature(array_windows)] @@ -20,16 +19,12 @@ #![feature(core_intrinsics)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] -#![feature(debug_non_exhaustive)] #![feature(dec2flt)] #![feature(div_duration)] #![feature(duration_consts_2)] #![feature(duration_constants)] -#![feature(duration_saturating_ops)] -#![feature(duration_zero)] #![feature(exact_size_is_empty)] #![feature(extern_types)] -#![feature(fixed_size_array)] #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(hashmap_internals)] @@ -58,7 +53,6 @@ #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] -#![feature(cmp_min_max_by)] #![feature(iter_map_while)] #![feature(const_mut_refs)] #![feature(const_pin)] @@ -68,19 +62,14 @@ #![feature(unwrap_infallible)] #![feature(option_result_unwrap_unchecked)] #![feature(result_into_ok_or_err)] -#![feature(option_unwrap_none)] -#![feature(peekable_peek_mut)] -#![cfg_attr(not(bootstrap), feature(ptr_metadata))] +#![feature(ptr_metadata)] #![feature(once_cell)] #![feature(unsized_tuple_coercion)] -#![feature(int_bits_const)] -#![feature(nonzero_leading_trailing_zeros)] #![feature(const_option)] #![feature(integer_atomics)] #![feature(slice_group_by)] #![feature(trusted_random_access)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] -#![cfg_attr(not(bootstrap), feature(unsize))] +#![feature(unsize)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index c0b75036f4..dfdbc9305d 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -97,6 +97,9 @@ 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 { diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs index 8e95249a79..960a7ca5ff 100644 --- a/library/core/tests/num/flt2dec/mod.rs +++ b/library/core/tests/num/flt2dec/mod.rs @@ -514,51 +514,38 @@ where let f = &mut f_; assert_eq!(to_string(f, 0.0, Minus, 0), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 0), "0"); + assert_eq!(to_string(f, 0.0, Minus, 0), "0"); assert_eq!(to_string(f, 0.0, MinusPlus, 0), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0), "+0"); - assert_eq!(to_string(f, -0.0, Minus, 0), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 0), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 0), "+0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0), "-0"); + assert_eq!(to_string(f, -0.0, Minus, 0), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 0), "-0"); + assert_eq!(to_string(f, 0.0, Minus, 1), "0.0"); assert_eq!(to_string(f, 0.0, Minus, 1), "0.0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1), "0.0"); assert_eq!(to_string(f, 0.0, MinusPlus, 1), "+0.0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1), "+0.0"); - assert_eq!(to_string(f, -0.0, Minus, 8), "0.00000000"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8), "-0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8), "+0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8), "-0.00000000"); + assert_eq!(to_string(f, -0.0, Minus, 8), "-0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8), "-0.00000000"); assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 0), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0), "inf"); assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 0), "+inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 0), "+inf"); assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 1), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 64), "NaN"); assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 1), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 64), "-inf"); assert_eq!(to_string(f, 3.14, Minus, 0), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, 0), "3.14"); + assert_eq!(to_string(f, 3.14, Minus, 0), "3.14"); assert_eq!(to_string(f, 3.14, MinusPlus, 0), "+3.14"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0), "+3.14"); assert_eq!(to_string(f, -3.14, Minus, 0), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusRaw, 0), "-3.14"); + assert_eq!(to_string(f, -3.14, Minus, 0), "-3.14"); assert_eq!(to_string(f, -3.14, MinusPlus, 0), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0), "-3.14"); assert_eq!(to_string(f, 3.14, Minus, 1), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, 2), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3), "+3.140"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4), "+3.1400"); + assert_eq!(to_string(f, 3.14, Minus, 2), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 4), "+3.1400"); + assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusRaw, 8), "-3.14000000"); assert_eq!(to_string(f, -3.14, MinusPlus, 8), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8), "-3.14000000"); assert_eq!(to_string(f, 7.5e-11, Minus, 0), "0.000000000075"); assert_eq!(to_string(f, 7.5e-11, Minus, 3), "0.000000000075"); @@ -615,68 +602,48 @@ where let f = &mut f_; assert_eq!(to_string(f, 0.0, Minus, (-4, 16), false), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, (-4, 16), false), "0"); + assert_eq!(to_string(f, 0.0, Minus, (-4, 16), false), "0"); assert_eq!(to_string(f, 0.0, MinusPlus, (-4, 16), false), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, (-4, 16), false), "+0"); - assert_eq!(to_string(f, -0.0, Minus, (-4, 16), false), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, (-4, 16), false), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, (-4, 16), false), "+0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, (-4, 16), false), "-0"); + assert_eq!(to_string(f, -0.0, Minus, (-4, 16), false), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, (-4, 16), false), "-0"); assert_eq!(to_string(f, 0.0, Minus, (0, 0), true), "0E0"); - assert_eq!(to_string(f, 0.0, MinusRaw, (0, 0), false), "0e0"); - assert_eq!(to_string(f, 0.0, MinusPlus, (-9, -5), true), "+0E0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, (5, 9), false), "+0e0"); - assert_eq!(to_string(f, -0.0, Minus, (0, 0), true), "0E0"); - assert_eq!(to_string(f, -0.0, MinusRaw, (0, 0), false), "-0e0"); - assert_eq!(to_string(f, -0.0, MinusPlus, (-9, -5), true), "+0E0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, (5, 9), false), "-0e0"); + assert_eq!(to_string(f, 0.0, Minus, (0, 0), false), "0e0"); + assert_eq!(to_string(f, 0.0, MinusPlus, (5, 9), false), "+0e0"); + assert_eq!(to_string(f, -0.0, Minus, (0, 0), true), "-0E0"); + assert_eq!(to_string(f, -0.0, MinusPlus, (5, 9), false), "-0e0"); assert_eq!(to_string(f, 1.0 / 0.0, Minus, (-4, 16), false), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, (-4, 16), true), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, (-4, 16), false), "+inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, (-4, 16), true), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, Minus, (-4, 16), true), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, (-4, 16), true), "+inf"); assert_eq!(to_string(f, 0.0 / 0.0, Minus, (0, 0), false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, (0, 0), true), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, (-9, -5), false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, (5, 9), true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, (0, 0), true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, (5, 9), true), "NaN"); assert_eq!(to_string(f, -1.0 / 0.0, Minus, (0, 0), false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, (0, 0), true), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, (-9, -5), false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, (5, 9), true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, (0, 0), true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, (5, 9), true), "-inf"); assert_eq!(to_string(f, 3.14, Minus, (-4, 16), false), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, (-4, 16), false), "3.14"); assert_eq!(to_string(f, 3.14, MinusPlus, (-4, 16), false), "+3.14"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, (-4, 16), false), "+3.14"); assert_eq!(to_string(f, -3.14, Minus, (-4, 16), false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusRaw, (-4, 16), false), "-3.14"); assert_eq!(to_string(f, -3.14, MinusPlus, (-4, 16), false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, (-4, 16), false), "-3.14"); assert_eq!(to_string(f, 3.14, Minus, (0, 0), true), "3.14E0"); - assert_eq!(to_string(f, 3.14, MinusRaw, (0, 0), false), "3.14e0"); - assert_eq!(to_string(f, 3.14, MinusPlus, (-9, -5), true), "+3.14E0"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, (5, 9), false), "+3.14e0"); + assert_eq!(to_string(f, 3.14, Minus, (0, 0), false), "3.14e0"); + assert_eq!(to_string(f, 3.14, MinusPlus, (5, 9), false), "+3.14e0"); assert_eq!(to_string(f, -3.14, Minus, (0, 0), true), "-3.14E0"); - assert_eq!(to_string(f, -3.14, MinusRaw, (0, 0), false), "-3.14e0"); - assert_eq!(to_string(f, -3.14, MinusPlus, (-9, -5), true), "-3.14E0"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, (5, 9), false), "-3.14e0"); + assert_eq!(to_string(f, -3.14, Minus, (0, 0), false), "-3.14e0"); + assert_eq!(to_string(f, -3.14, MinusPlus, (5, 9), false), "-3.14e0"); assert_eq!(to_string(f, 0.1, Minus, (-4, 16), false), "0.1"); - assert_eq!(to_string(f, 0.1, MinusRaw, (-4, 16), false), "0.1"); + assert_eq!(to_string(f, 0.1, Minus, (-4, 16), false), "0.1"); assert_eq!(to_string(f, 0.1, MinusPlus, (-4, 16), false), "+0.1"); - assert_eq!(to_string(f, 0.1, MinusPlusRaw, (-4, 16), false), "+0.1"); assert_eq!(to_string(f, -0.1, Minus, (-4, 16), false), "-0.1"); - assert_eq!(to_string(f, -0.1, MinusRaw, (-4, 16), false), "-0.1"); assert_eq!(to_string(f, -0.1, MinusPlus, (-4, 16), false), "-0.1"); - assert_eq!(to_string(f, -0.1, MinusPlusRaw, (-4, 16), false), "-0.1"); assert_eq!(to_string(f, 0.1, Minus, (0, 0), true), "1E-1"); - assert_eq!(to_string(f, 0.1, MinusRaw, (0, 0), false), "1e-1"); - assert_eq!(to_string(f, 0.1, MinusPlus, (-9, -5), true), "+1E-1"); - assert_eq!(to_string(f, 0.1, MinusPlusRaw, (5, 9), false), "+1e-1"); + assert_eq!(to_string(f, 0.1, Minus, (0, 0), false), "1e-1"); + assert_eq!(to_string(f, 0.1, MinusPlus, (5, 9), false), "+1e-1"); assert_eq!(to_string(f, -0.1, Minus, (0, 0), true), "-1E-1"); - assert_eq!(to_string(f, -0.1, MinusRaw, (0, 0), false), "-1e-1"); - assert_eq!(to_string(f, -0.1, MinusPlus, (-9, -5), true), "-1E-1"); - assert_eq!(to_string(f, -0.1, MinusPlusRaw, (5, 9), false), "-1e-1"); + assert_eq!(to_string(f, -0.1, Minus, (0, 0), false), "-1e-1"); + assert_eq!(to_string(f, -0.1, MinusPlus, (5, 9), false), "-1e-1"); assert_eq!(to_string(f, 7.5e-11, Minus, (-4, 16), false), "7.5e-11"); assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), "0.000000000075"); @@ -734,68 +701,51 @@ where let f = &mut f_; assert_eq!(to_string(f, 0.0, Minus, 1, true), "0E0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1, false), "0e0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0E0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, false), "+0e0"); - assert_eq!(to_string(f, -0.0, Minus, 1, true), "0E0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 1, false), "-0e0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 1, true), "+0E0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 1, false), "-0e0"); + assert_eq!(to_string(f, 0.0, Minus, 1, false), "0e0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 1, false), "+0e0"); + assert_eq!(to_string(f, -0.0, Minus, 1, true), "-0E0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 1, false), "-0e0"); assert_eq!(to_string(f, 0.0, Minus, 2, true), "0.0E0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 2, false), "0.0e0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 2, true), "+0.0E0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 2, false), "+0.0e0"); - assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.0000000E0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8, false), "-0.0000000e0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.0000000E0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, false), "-0.0000000e0"); + assert_eq!(to_string(f, 0.0, Minus, 2, false), "0.0e0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 2, false), "+0.0e0"); + assert_eq!(to_string(f, -0.0, Minus, 8, false), "-0.0000000e0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8, false), "-0.0000000e0"); assert_eq!(to_string(f, 1.0 / 0.0, Minus, 1, false), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1, true), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 1, false), "+inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 1, true), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 1, true), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 1, true), "+inf"); assert_eq!(to_string(f, 0.0 / 0.0, Minus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 8, true), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 8, true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 8, true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, true), "NaN"); assert_eq!(to_string(f, -1.0 / 0.0, Minus, 64, false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 64, true), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 64, false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64, true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 64, true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 64, true), "-inf"); assert_eq!(to_string(f, 3.14, Minus, 1, true), "3E0"); - assert_eq!(to_string(f, 3.14, MinusRaw, 1, false), "3e0"); - assert_eq!(to_string(f, 3.14, MinusPlus, 1, true), "+3E0"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 1, false), "+3e0"); + assert_eq!(to_string(f, 3.14, Minus, 1, false), "3e0"); + assert_eq!(to_string(f, 3.14, MinusPlus, 1, false), "+3e0"); assert_eq!(to_string(f, -3.14, Minus, 2, true), "-3.1E0"); - assert_eq!(to_string(f, -3.14, MinusRaw, 2, false), "-3.1e0"); - assert_eq!(to_string(f, -3.14, MinusPlus, 2, true), "-3.1E0"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 2, false), "-3.1e0"); + assert_eq!(to_string(f, -3.14, Minus, 2, false), "-3.1e0"); + assert_eq!(to_string(f, -3.14, MinusPlus, 2, false), "-3.1e0"); assert_eq!(to_string(f, 3.14, Minus, 3, true), "3.14E0"); - assert_eq!(to_string(f, 3.14, MinusRaw, 3, false), "3.14e0"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.14E0"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 3, false), "+3.14e0"); + assert_eq!(to_string(f, 3.14, Minus, 3, false), "3.14e0"); + assert_eq!(to_string(f, 3.14, MinusPlus, 3, false), "+3.14e0"); assert_eq!(to_string(f, -3.14, Minus, 4, true), "-3.140E0"); - assert_eq!(to_string(f, -3.14, MinusRaw, 4, false), "-3.140e0"); - assert_eq!(to_string(f, -3.14, MinusPlus, 4, true), "-3.140E0"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 4, false), "-3.140e0"); + assert_eq!(to_string(f, -3.14, Minus, 4, false), "-3.140e0"); + assert_eq!(to_string(f, -3.14, MinusPlus, 4, false), "-3.140e0"); assert_eq!(to_string(f, 0.195, Minus, 1, false), "2e-1"); - assert_eq!(to_string(f, 0.195, MinusRaw, 1, true), "2E-1"); - assert_eq!(to_string(f, 0.195, MinusPlus, 1, false), "+2e-1"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 1, true), "+2E-1"); + assert_eq!(to_string(f, 0.195, Minus, 1, true), "2E-1"); + assert_eq!(to_string(f, 0.195, MinusPlus, 1, true), "+2E-1"); assert_eq!(to_string(f, -0.195, Minus, 2, false), "-2.0e-1"); - assert_eq!(to_string(f, -0.195, MinusRaw, 2, true), "-2.0E-1"); - assert_eq!(to_string(f, -0.195, MinusPlus, 2, false), "-2.0e-1"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2, true), "-2.0E-1"); + assert_eq!(to_string(f, -0.195, Minus, 2, true), "-2.0E-1"); + assert_eq!(to_string(f, -0.195, MinusPlus, 2, true), "-2.0E-1"); assert_eq!(to_string(f, 0.195, Minus, 3, false), "1.95e-1"); - assert_eq!(to_string(f, 0.195, MinusRaw, 3, true), "1.95E-1"); - assert_eq!(to_string(f, 0.195, MinusPlus, 3, false), "+1.95e-1"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 3, true), "+1.95E-1"); + assert_eq!(to_string(f, 0.195, Minus, 3, true), "1.95E-1"); + assert_eq!(to_string(f, 0.195, MinusPlus, 3, true), "+1.95E-1"); assert_eq!(to_string(f, -0.195, Minus, 4, false), "-1.950e-1"); - assert_eq!(to_string(f, -0.195, MinusRaw, 4, true), "-1.950E-1"); - assert_eq!(to_string(f, -0.195, MinusPlus, 4, false), "-1.950e-1"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4, true), "-1.950E-1"); + assert_eq!(to_string(f, -0.195, Minus, 4, true), "-1.950E-1"); + assert_eq!(to_string(f, -0.195, MinusPlus, 4, true), "-1.950E-1"); assert_eq!(to_string(f, 9.5, Minus, 1, false), "1e1"); assert_eq!(to_string(f, 9.5, Minus, 2, false), "9.5e0"); @@ -1007,68 +957,48 @@ where let f = &mut f_; assert_eq!(to_string(f, 0.0, Minus, 0), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 0), "0"); assert_eq!(to_string(f, 0.0, MinusPlus, 0), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0), "+0"); - assert_eq!(to_string(f, -0.0, Minus, 0), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 0), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 0), "+0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0), "-0"); + assert_eq!(to_string(f, -0.0, Minus, 0), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 0), "-0"); assert_eq!(to_string(f, 0.0, Minus, 1), "0.0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1), "0.0"); assert_eq!(to_string(f, 0.0, MinusPlus, 1), "+0.0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1), "+0.0"); - assert_eq!(to_string(f, -0.0, Minus, 8), "0.00000000"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8), "-0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8), "+0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8), "-0.00000000"); + assert_eq!(to_string(f, -0.0, Minus, 8), "-0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8), "-0.00000000"); assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 8), "+inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 64), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 1), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 64), "+inf"); assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 1), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 64), "NaN"); assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 1), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 64), "-inf"); assert_eq!(to_string(f, 3.14, Minus, 0), "3"); - assert_eq!(to_string(f, 3.14, MinusRaw, 0), "3"); + assert_eq!(to_string(f, 3.14, Minus, 0), "3"); assert_eq!(to_string(f, 3.14, MinusPlus, 0), "+3"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0), "+3"); assert_eq!(to_string(f, -3.14, Minus, 0), "-3"); - assert_eq!(to_string(f, -3.14, MinusRaw, 0), "-3"); + assert_eq!(to_string(f, -3.14, Minus, 0), "-3"); assert_eq!(to_string(f, -3.14, MinusPlus, 0), "-3"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0), "-3"); assert_eq!(to_string(f, 3.14, Minus, 1), "3.1"); - assert_eq!(to_string(f, 3.14, MinusRaw, 2), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3), "+3.140"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4), "+3.1400"); + assert_eq!(to_string(f, 3.14, Minus, 2), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 4), "+3.1400"); + assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusRaw, 8), "-3.14000000"); assert_eq!(to_string(f, -3.14, MinusPlus, 8), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8), "-3.14000000"); assert_eq!(to_string(f, 0.195, Minus, 0), "0"); - assert_eq!(to_string(f, 0.195, MinusRaw, 0), "0"); assert_eq!(to_string(f, 0.195, MinusPlus, 0), "+0"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0), "+0"); assert_eq!(to_string(f, -0.195, Minus, 0), "-0"); - assert_eq!(to_string(f, -0.195, MinusRaw, 0), "-0"); + assert_eq!(to_string(f, -0.195, Minus, 0), "-0"); assert_eq!(to_string(f, -0.195, MinusPlus, 0), "-0"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0), "-0"); assert_eq!(to_string(f, 0.195, Minus, 1), "0.2"); - assert_eq!(to_string(f, 0.195, MinusRaw, 2), "0.20"); - assert_eq!(to_string(f, 0.195, MinusPlus, 3), "+0.195"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4), "+0.1950"); + assert_eq!(to_string(f, 0.195, Minus, 2), "0.20"); + assert_eq!(to_string(f, 0.195, MinusPlus, 4), "+0.1950"); assert_eq!(to_string(f, -0.195, Minus, 5), "-0.19500"); - assert_eq!(to_string(f, -0.195, MinusRaw, 6), "-0.195000"); - assert_eq!(to_string(f, -0.195, MinusPlus, 7), "-0.1950000"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8), "-0.19500000"); + assert_eq!(to_string(f, -0.195, Minus, 6), "-0.195000"); + assert_eq!(to_string(f, -0.195, MinusPlus, 8), "-0.19500000"); assert_eq!(to_string(f, 999.5, Minus, 0), "1000"); assert_eq!(to_string(f, 999.5, Minus, 1), "999.5"); diff --git a/library/core/tests/num/ieee754.rs b/library/core/tests/num/ieee754.rs new file mode 100644 index 0000000000..f6e5dfc98c --- /dev/null +++ b/library/core/tests/num/ieee754.rs @@ -0,0 +1,158 @@ +//! IEEE 754 floating point compliance tests +//! +//! To understand IEEE 754's requirements on a programming language, one must understand that the +//! requirements of IEEE 754 rest on the total programming environment, and not entirely on any +//! one component. That means the hardware, language, and even libraries are considered part of +//! conforming floating point support in a programming environment. +//! +//! A programming language's duty, accordingly, is: +//! 1. offer access to the hardware where the hardware offers support +//! 2. provide operations that fulfill the remaining requirements of the standard +//! 3. provide the ability to write additional software that can fulfill those requirements +//! +//! This may be fulfilled in any combination that the language sees fit. However, to claim that +//! a language supports IEEE 754 is to suggest that it has fulfilled requirements 1 and 2, without +//! deferring minimum requirements to libraries. This is because support for IEEE 754 is defined +//! as complete support for at least one specified floating point type as an "arithmetic" and +//! "interchange" format, plus specified type conversions to "external character sequences" and +//! integer types. +//! +//! For our purposes, +//! "interchange format" => f32, f64 +//! "arithmetic format" => f32, f64, and any "soft floats" +//! "external character sequence" => str from any float +//! "integer format" => {i,u}{8,16,32,64,128} +//! +//! None of these tests are against Rust's own implementation. They are only tests against the +//! standard. That is why they accept wildly diverse inputs or may seem to duplicate other tests. +//! Please consider this carefully when adding, removing, or reorganizing these tests. They are +//! here so that it is clear what tests are required by the standard and what can be changed. +use ::core::str::FromStr; + +// IEEE 754 for many tests is applied to specific bit patterns. +// These generally are not applicable to NaN, however. +macro_rules! assert_biteq { + ($lhs:expr, $rhs:expr) => { + assert_eq!($lhs.to_bits(), $rhs.to_bits()) + }; +} + +// ToString uses the default fmt::Display impl without special concerns, and bypasses other parts +// of the formatting infrastructure, which makes it ideal for testing here. +#[allow(unused_macros)] +macro_rules! roundtrip { + ($f:expr => $t:ty) => { + ($f).to_string().parse::<$t>().unwrap() + }; +} + +macro_rules! assert_floats_roundtrip { + ($f:ident) => { + assert_biteq!(f32::$f, roundtrip!(f32::$f => f32)); + assert_biteq!(f64::$f, roundtrip!(f64::$f => f64)); + }; + ($f:expr) => { + assert_biteq!($f as f32, roundtrip!($f => f32)); + assert_biteq!($f as f64, roundtrip!($f => f64)); + } +} + +macro_rules! assert_floats_bitne { + ($lhs:ident, $rhs:ident) => { + assert_ne!(f32::$lhs.to_bits(), f32::$rhs.to_bits()); + assert_ne!(f64::$lhs.to_bits(), f64::$rhs.to_bits()); + }; + ($lhs:expr, $rhs:expr) => { + assert_ne!(f32::to_bits($lhs), f32::to_bits($rhs)); + assert_ne!(f64::to_bits($lhs), f64::to_bits($rhs)); + }; +} + +// We must preserve signs on all numbers. That includes zero. +// -0 and 0 are == normally, so test bit equality. +#[test] +fn preserve_signed_zero() { + assert_floats_roundtrip!(-0.0); + assert_floats_roundtrip!(0.0); + assert_floats_bitne!(0.0, -0.0); +} + +#[test] +fn preserve_signed_infinity() { + assert_floats_roundtrip!(INFINITY); + assert_floats_roundtrip!(NEG_INFINITY); + assert_floats_bitne!(INFINITY, NEG_INFINITY); +} + +#[test] +fn infinity_to_str() { + assert!(match f32::INFINITY.to_string().to_lowercase().as_str() { + "+infinity" | "infinity" => true, + "+inf" | "inf" => true, + _ => false, + }); + assert!( + match f64::INFINITY.to_string().to_lowercase().as_str() { + "+infinity" | "infinity" => true, + "+inf" | "inf" => true, + _ => false, + }, + "Infinity must write to a string as some casing of inf or infinity, with an optional +." + ); +} + +#[test] +fn neg_infinity_to_str() { + assert!(match f32::NEG_INFINITY.to_string().to_lowercase().as_str() { + "-infinity" | "-inf" => true, + _ => false, + }); + assert!( + match f64::NEG_INFINITY.to_string().to_lowercase().as_str() { + "-infinity" | "-inf" => true, + _ => false, + }, + "Negative Infinity must write to a string as some casing of -inf or -infinity" + ) +} + +#[test] +fn nan_to_str() { + assert!( + match f32::NAN.to_string().to_lowercase().as_str() { + "nan" | "+nan" | "-nan" => true, + _ => false, + }, + "NaNs must write to a string as some casing of nan." + ) +} + +// "+"?("inf"|"infinity") in any case => Infinity +#[test] +fn infinity_from_str() { + assert_biteq!(f32::INFINITY, f32::from_str("infinity").unwrap()); + assert_biteq!(f32::INFINITY, f32::from_str("inf").unwrap()); + assert_biteq!(f32::INFINITY, f32::from_str("+infinity").unwrap()); + assert_biteq!(f32::INFINITY, f32::from_str("+inf").unwrap()); + // yes! this means you are weLcOmE tO mY iNfInItElY tWiStEd MiNd + assert_biteq!(f32::INFINITY, f32::from_str("+iNfInItY").unwrap()); +} + +// "-inf"|"-infinity" in any case => Negative Infinity +#[test] +fn neg_infinity_from_str() { + assert_biteq!(f32::NEG_INFINITY, f32::from_str("-infinity").unwrap()); + assert_biteq!(f32::NEG_INFINITY, f32::from_str("-inf").unwrap()); + assert_biteq!(f32::NEG_INFINITY, f32::from_str("-INF").unwrap()); + assert_biteq!(f32::NEG_INFINITY, f32::from_str("-INFinity").unwrap()); +} + +// ("+"|"-"")?"s"?"nan" in any case => qNaN +#[test] +fn qnan_from_str() { + assert!("nan".parse::().unwrap().is_nan()); + assert!("-nan".parse::().unwrap().is_nan()); + assert!("+nan".parse::().unwrap().is_nan()); + assert!("+NAN".parse::().unwrap().is_nan()); + assert!("-NaN".parse::().unwrap().is_nan()); +} diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index e66a73ac12..bbb67667df 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -32,6 +32,7 @@ mod flt2dec; mod ops; mod wrapping; +mod ieee754; mod nan; /// Adds the attribute to all items in the block. diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 224a58e3cc..11af8090c3 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1,8 +1,6 @@ use core::cell::RefCell; -#[cfg(not(bootstrap))] use core::ptr; use core::ptr::*; -#[cfg(not(bootstrap))] use std::fmt::{Debug, Display}; #[test] @@ -419,7 +417,6 @@ fn offset_from() { } #[test] -#[cfg(not(bootstrap))] fn ptr_metadata() { struct Unit; struct Pair(A, B); @@ -478,7 +475,6 @@ fn ptr_metadata() { } #[test] -#[cfg(not(bootstrap))] fn ptr_metadata_bounds() { fn metadata_eq_method_address() -> usize { // The `Metadata` associated type has an `Ord` bound, so this is valid: @@ -510,7 +506,6 @@ fn ptr_metadata_bounds() { } #[test] -#[cfg(not(bootstrap))] fn dyn_metadata() { #[derive(Debug)] #[repr(align(32))] @@ -530,7 +525,6 @@ fn dyn_metadata() { } #[test] -#[cfg(not(bootstrap))] fn from_raw_parts() { let mut value = 5_u32; let address = &mut value as *mut _ as *mut (); @@ -557,7 +551,6 @@ fn from_raw_parts() { } #[test] -#[cfg(not(bootstrap))] fn thin_box() { let foo = ThinBox::::new(4); assert_eq!(foo.to_string(), "4"); diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index 5fcd7b4d3a..c461ab380a 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -225,6 +225,28 @@ pub fn test_into_ok() { assert_eq!(infallible_op2().into_ok(), 667); } +#[test] +pub fn test_into_err() { + fn until_error_op() -> Result { + Err(666) + } + + assert_eq!(until_error_op().into_err(), 666); + + enum MyNeverToken {} + impl From for ! { + fn from(never: MyNeverToken) -> ! { + match never {} + } + } + + fn until_error_op2() -> Result { + Err(667) + } + + assert_eq!(until_error_op2().into_err(), 667); +} + #[test] fn test_try() { fn try_result_some() -> Option { diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 7e198631cc..3a98cd9d2e 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1280,6 +1280,9 @@ mod slice_index { } )*) => {$( mod $case_name { + #[allow(unused_imports)] + use core::ops::Bound; + #[test] fn pass() { let mut v = $data; @@ -1376,6 +1379,24 @@ mod slice_index { bad: data[7..=6]; message: "out of range"; } + + in mod boundpair_len { + data: [0, 1, 2, 3, 4, 5]; + + good: data[(Bound::Included(6), Bound::Unbounded)] == []; + good: data[(Bound::Unbounded, Bound::Included(5))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Unbounded, Bound::Excluded(6))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Included(0), Bound::Included(5))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Included(0), Bound::Excluded(6))] == [0, 1, 2, 3, 4, 5]; + good: data[(Bound::Included(2), Bound::Excluded(4))] == [2, 3]; + good: data[(Bound::Excluded(1), Bound::Included(4))] == [2, 3, 4]; + good: data[(Bound::Excluded(5), Bound::Excluded(6))] == []; + good: data[(Bound::Included(6), Bound::Excluded(6))] == []; + good: data[(Bound::Excluded(5), Bound::Included(5))] == []; + good: data[(Bound::Included(6), Bound::Included(5))] == []; + bad: data[(Bound::Unbounded, Bound::Included(6))]; + message: "out of range"; + } } panic_cases! { @@ -1416,6 +1437,14 @@ mod slice_index { bad: data[4..=2]; message: "but ends at"; } + + in mod boundpair_neg_width { + data: [0, 1, 2, 3, 4, 5]; + + good: data[(Bound::Included(4), Bound::Excluded(4))] == []; + bad: data[(Bound::Included(4), Bound::Excluded(3))]; + message: "but ends at"; + } } panic_cases! { @@ -1434,6 +1463,20 @@ mod slice_index { bad: data[..= usize::MAX]; message: "maximum usize"; } + + in mod boundpair_overflow_end { + data: [0; 1]; + + bad: data[(Bound::Unbounded, Bound::Included(usize::MAX))]; + message: "maximum usize"; + } + + in mod boundpair_overflow_start { + data: [0; 1]; + + bad: data[(Bound::Excluded(usize::MAX), Bound::Unbounded)]; + message: "maximum usize"; + } } // panic_cases! } diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml index b15919fad7..bdab664cd6 100644 --- a/library/panic_abort/Cargo.toml +++ b/library/panic_abort/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "panic_abort" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "Implementation of Rust panics via process aborts" edition = "2018" [lib] @@ -10,6 +13,7 @@ bench = false doc = false [dependencies] +alloc = { path = "../alloc" } cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } core = { path = "../core" } libc = { version = "0.2", default-features = false } diff --git a/library/panic_abort/src/android.rs b/library/panic_abort/src/android.rs new file mode 100644 index 0000000000..34d77502ea --- /dev/null +++ b/library/panic_abort/src/android.rs @@ -0,0 +1,49 @@ +use alloc::string::String; +use core::mem::transmute; +use core::panic::BoxMeUp; +use core::ptr::copy_nonoverlapping; + +const ANDROID_SET_ABORT_MESSAGE: &[u8] = b"android_set_abort_message\0"; +type SetAbortMessageType = unsafe extern "C" fn(*const libc::c_char) -> (); + +// Forward the abort message to libc's android_set_abort_message. We try our best to populate the +// message but as this function may already be called as part of a failed allocation, it may not be +// possible to do so. +// +// Some methods of core are on purpose avoided (such as try_reserve) as these rely on the correct +// resolution of rust_eh_personality which is loosely defined in panic_abort. +// +// Weakly resolve the symbol for android_set_abort_message. This function is only available +// for API >= 21. +pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) { + let func_addr = + libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char) + as usize; + if func_addr == 0 { + return; + } + + let payload = (*payload).get(); + let msg = match payload.downcast_ref::<&'static str>() { + Some(msg) => msg.as_bytes(), + None => match payload.downcast_ref::() { + Some(msg) => msg.as_bytes(), + None => &[], + }, + }; + if msg.is_empty() { + return; + } + + // Allocate a new buffer to append the null byte. + let size = msg.len() + 1usize; + let buf = libc::malloc(size) as *mut libc::c_char; + if buf.is_null() { + return; // allocation failure + } + copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len()); + buf.offset(msg.len() as isize).write(0); + + let func = transmute::(func_addr); + func(buf); +} diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index eb2277d8ba..5dcd1e6af3 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -19,6 +19,9 @@ #![feature(rustc_attrs)] #![feature(asm)] +#[cfg(target_os = "android")] +mod android; + use core::any::Any; use core::panic::BoxMeUp; @@ -31,6 +34,10 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen // "Leak" the payload and shim to the relevant abort on the platform in question. #[rustc_std_internal_symbol] pub unsafe extern "C" fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { + // Android has the ability to attach a message as part of the abort. + #[cfg(target_os = "android")] + android::android_set_abort_message(_payload); + abort(); cfg_if::cfg_if! { diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index d27ba98764..533f059a85 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "panic_unwind" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "Implementation of Rust panics via stack unwinding" edition = "2018" [lib] diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 9ce9c477ec..99a0c67fc1 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -18,7 +18,6 @@ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/" )] #![feature(core_intrinsics)] -#![feature(int_bits_const)] #![feature(lang_items)] #![feature(nll)] #![feature(panic_unwind)] diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 5f1f7d8cac..c7f58f3615 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -21,7 +21,8 @@ #![feature(rustc_allow_const_fn_unstable)] #![feature(nll)] #![feature(staged_api)] -#![feature(const_fn)] +#![cfg_attr(bootstrap, feature(const_fn))] +#![cfg_attr(not(bootstrap), feature(const_fn_trait_bound))] #![feature(const_fn_fn_ptr_basics)] #![feature(allow_internal_unstable)] #![feature(decl_macro)] diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index 2de6db762b..1b1f11798d 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -24,13 +24,11 @@ fn main() { "InstrProfilingPlatformLinux.c", "InstrProfilingPlatformOther.c", "InstrProfilingPlatformWindows.c", + "InstrProfilingRuntime.cpp", "InstrProfilingUtil.c", "InstrProfilingValue.c", "InstrProfilingVersionVar.c", "InstrProfilingWriter.c", - // This file was renamed in LLVM 10. - "InstrProfilingRuntime.cc", - "InstrProfilingRuntime.cpp", // These files were added in LLVM 11. "InstrProfilingInternal.c", "InstrProfilingBiasVar.c", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 22ca7ed09b..ab7b142ef3 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -16,11 +16,12 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.88", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.93", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.39" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] } +std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] } # Dependencies of the `backtrace` crate addr2line = { version = "0.14.0", optional = true, default-features = false } @@ -70,8 +71,8 @@ panic_immediate_abort = ["core/panic_immediate_abort"] # Enable std_detect default features for stdarch/crates/std_detect: # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml -std_detect_file_io = [] -std_detect_dlsym_getauxval = [] +std_detect_file_io = ["std_detect/std_detect_file_io"] +std_detect_dlsym_getauxval = ["std_detect/std_detect_dlsym_getauxval"] [package.metadata.fortanix-sgx] # Maximum possible number of threads when testing diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index ed32668456..bdf559847c 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1793,7 +1793,7 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { #[unstable(feature = "hash_raw_entry", issue = "56167")] impl Debug for RawEntryBuilderMut<'_, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish() + f.debug_struct("RawEntryBuilder").finish_non_exhaustive() } } @@ -1813,21 +1813,21 @@ impl Debug for RawOccupiedEntryMut<'_, K, V, S> { f.debug_struct("RawOccupiedEntryMut") .field("key", self.key()) .field("value", self.get()) - .finish() + .finish_non_exhaustive() } } #[unstable(feature = "hash_raw_entry", issue = "56167")] impl Debug for RawVacantEntryMut<'_, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawVacantEntryMut").finish() + f.debug_struct("RawVacantEntryMut").finish_non_exhaustive() } } #[unstable(feature = "hash_raw_entry", issue = "56167")] impl Debug for RawEntryBuilder<'_, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish() + f.debug_struct("RawEntryBuilder").finish_non_exhaustive() } } @@ -1867,7 +1867,10 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> { #[stable(feature = "debug_hash_map", since = "1.12.0")] impl Debug for OccupiedEntry<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedEntry").field("key", self.key()).field("value", self.get()).finish() + f.debug_struct("OccupiedEntry") + .field("key", self.key()) + .field("value", self.get()) + .finish_non_exhaustive() } } @@ -1903,7 +1906,7 @@ impl Debug for OccupiedError<'_, K, V> { .field("key", self.entry.key()) .field("old_value", self.entry.get()) .field("new_value", &self.value) - .finish() + .finish_non_exhaustive() } } @@ -2254,7 +2257,7 @@ where F: FnMut(&K, &mut V) -> bool, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("DrainFilter { .. }") + f.debug_struct("DrainFilter").finish_non_exhaustive() } } @@ -2954,7 +2957,7 @@ impl Default for RandomState { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for RandomState { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("RandomState { .. }") + f.debug_struct("RandomState").finish_non_exhaustive() } } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 8c801b9f12..5220c8ad70 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -1533,7 +1533,7 @@ where F: FnMut(&K) -> bool, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("DrainFilter { .. }") + f.debug_struct("DrainFilter").finish_non_exhaustive() } } diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 9763a2da34..821e7d4cfe 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -124,6 +124,10 @@ pub fn vars() -> Vars { /// variables at the time of this invocation. Modifications to environment /// variables afterwards will not be reflected in the returned iterator. /// +/// Note that the returned iterator will not check if the environment variables +/// are valid Unicode. If you want to panic on invalid UTF-8, +/// use the [`vars`] function instead. +/// /// # Examples /// /// ``` @@ -154,7 +158,7 @@ impl Iterator for Vars { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Vars { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Vars { .. }") + f.debug_struct("Vars").finish_non_exhaustive() } } @@ -172,7 +176,7 @@ impl Iterator for VarsOs { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for VarsOs { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("VarsOs { .. }") + f.debug_struct("VarOs").finish_non_exhaustive() } } @@ -180,8 +184,9 @@ impl fmt::Debug for VarsOs { /// /// # Errors /// -/// * Environment variable is not present -/// * Environment variable is not valid unicode +/// Errors if the environment variable is not present. +/// Errors if the environment variable is not valid Unicode. If this is not desired, consider using +/// [`var_os`]. /// /// # Panics /// @@ -221,6 +226,10 @@ fn _var(key: &OsStr) -> Result { /// `'='` or the NUL character `'\0'`, or when the value contains the NUL /// character. /// +/// Note that the method will not check if the environment variable +/// is valid Unicode. If you want to have an error on invalid UTF-8, +/// use the [`var`] function instead. +/// /// # Examples /// /// ``` @@ -419,7 +428,7 @@ impl<'a> Iterator for SplitPaths<'a> { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for SplitPaths<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("SplitPaths { .. }") + f.debug_struct("SplitPaths").finish_non_exhaustive() } } @@ -710,14 +719,14 @@ pub struct ArgsOs { /// passed as-is. /// /// On glibc Linux systems, arguments are retrieved by placing a function in `.init_array`. -/// Glibc passes `argc`, `argv`, and `envp` to functions in `.init_array`, as a non-standard +/// glibc passes `argc`, `argv`, and `envp` to functions in `.init_array`, as a non-standard /// extension. This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it /// does on macOS and Windows. /// /// # Panics /// /// The returned iterator will panic during iteration if any argument to the -/// process is not valid unicode. If this is not desired, +/// process is not valid Unicode. If this is not desired, /// use the [`args_os`] function instead. /// /// # Examples @@ -735,17 +744,25 @@ pub fn args() -> Args { Args { inner: args_os() } } -/// Returns the arguments which this program was started with (normally passed +/// Returns the arguments that this program was started with (normally passed /// via the command line). /// /// The first element is traditionally the path of the executable, but it can be -/// set to arbitrary text, and it may not even exist, so this property should +/// set to arbitrary text, and may not even exist. This means this property should /// not be relied upon for security purposes. /// -/// On glibc Linux systems, arguments are retrieved by placing a function in ".init_array". -/// Glibc passes argc, argv, and envp to functions in ".init_array", as a non-standard extension. -/// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS -/// and Windows. +/// On Unix systems the shell usually expands unquoted arguments with glob patterns +/// (such as `*` and `?`). On Windows this is not done, and such arguments are +/// passed as-is. +/// +/// On glibc Linux systems, arguments are retrieved by placing a function in `.init_array`. +/// glibc passes `argc`, `argv`, and `envp` to functions in `.init_array`, as a non-standard +/// extension. This allows `std::env::args_os` to work even in a `cdylib` or `staticlib`, as it +/// does on macOS and Windows. +/// +/// Note that the returned iterator will not check if the arguments to the +/// process are valid Unicode. If you want to panic on invalid UTF-8, +/// use the [`args`] function instead. /// /// # Examples /// @@ -799,7 +816,7 @@ impl DoubleEndedIterator for Args { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Args").field("inner", &self.inner.inner.inner_debug()).finish() + f.debug_struct("Args").field("inner", &self.inner.inner).finish() } } @@ -840,7 +857,7 @@ impl DoubleEndedIterator for ArgsOs { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ArgsOs { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ArgsOs").field("inner", &self.inner.inner_debug()).finish() + f.debug_struct("ArgsOs").field("inner", &self.inner).finish() } } diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 80c35307d5..14c2f961d3 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -33,15 +33,22 @@ use crate::string; use crate::sync::Arc; /// `Error` is a trait representing the basic expectations for error values, -/// i.e., values of type `E` in [`Result`]. Errors must describe -/// themselves through the [`Display`] and [`Debug`] traits, and may provide -/// cause chain information: +/// i.e., values of type `E` in [`Result`]. /// -/// [`Error::source()`] is generally used when errors cross -/// "abstraction boundaries". If one module must report an error that is caused -/// by an error from a lower-level module, it can allow accessing that error -/// via [`Error::source()`]. This makes it possible for the high-level -/// module to provide its own errors while also revealing some of the +/// Errors must describe themselves through the [`Display`] and [`Debug`] +/// traits. Error messages are typically concise lowercase sentences without +/// trailing punctuation: +/// +/// ``` +/// let err = "NaN".parse::().unwrap_err(); +/// assert_eq!(err.to_string(), "invalid digit found in string"); +/// ``` +/// +/// Errors may provide cause chain information. [`Error::source()`] is generally +/// used when errors cross "abstraction boundaries". If one module must report +/// an error that is caused by an error from a lower-level module, it can allow +/// accessing that error via [`Error::source()`]. This makes it possible for the +/// high-level module to provide its own errors while also revealing some of the /// implementation for debugging via `source` chains. #[stable(feature = "rust1", since = "1.0.0")] pub trait Error: Debug + Display { diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 945bfda1b7..ed4950c57a 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -613,7 +613,8 @@ impl CString { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { - &self.inner[..self.inner.len() - 1] + // SAFETY: CString has a length at least 1 + unsafe { self.inner.get_unchecked(..self.inner.len() - 1) } } /// Equivalent to [`CString::as_bytes()`] except that the @@ -1036,7 +1037,7 @@ impl fmt::Display for NulError { impl From for io::Error { /// Converts a [`NulError`] into a [`io::Error`]. fn from(_: NulError) -> io::Error { - io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte") + io::Error::new_const(io::ErrorKind::InvalidInput, &"data provided contains a nul byte") } } @@ -1322,7 +1323,8 @@ impl CStr { #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); - &bytes[..bytes.len() - 1] + // SAFETY: to_bytes_with_nul returns slice with length at least 1 + unsafe { bytes.get_unchecked(..bytes.len() - 1) } } /// Converts this C string to a byte slice containing the trailing 0 byte. diff --git a/library/std/src/ffi/c_str/tests.rs b/library/std/src/ffi/c_str/tests.rs index 4dff3df63a..4f7ba9ad43 100644 --- a/library/std/src/ffi/c_str/tests.rs +++ b/library/std/src/ffi/c_str/tests.rs @@ -193,3 +193,19 @@ fn cstr_index_from_empty() { let cstr = CStr::from_bytes_with_nul(original).unwrap(); let _ = &cstr[original.len()..]; } + +#[test] +fn c_string_from_empty_string() { + let original = ""; + let cstring = CString::new(original).unwrap(); + assert_eq!(original.as_bytes(), cstring.as_bytes()); + assert_eq!([b'\0'], cstring.as_bytes_with_nul()); +} + +#[test] +fn c_str_from_empty_string() { + let original = b"\0"; + let cstr = CStr::from_bytes_with_nul(original).unwrap(); + assert_eq!([] as [u8; 0], cstr.to_bytes()); + assert_eq!([b'\0'], cstr.to_bytes_with_nul()); +} diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index ce52ffc024..ea4b286601 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -71,7 +71,6 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// [`&str`]: str /// [`CStr`]: crate::ffi::CStr /// [conversions]: super#conversions -#[derive(Clone)] #[cfg_attr(not(test), rustc_diagnostic_item = "OsString")] #[stable(feature = "rust1", since = "1.0.0")] pub struct OsString { @@ -361,7 +360,7 @@ impl OsString { impl From for OsString { /// Converts a [`String`] into a [`OsString`]. /// - /// The conversion copies the data, and includes an allocation on the heap. + /// This conversion does not allocate or copy memory. #[inline] fn from(s: String) -> OsString { OsString { inner: Buf::from_string(s) } @@ -420,6 +419,19 @@ impl Default for OsString { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for OsString { + #[inline] + fn clone(&self) -> Self { + OsString { inner: self.inner.clone() } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for OsString { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -716,7 +728,6 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤"); @@ -725,7 +736,7 @@ impl OsStr { /// /// assert_eq!("grÜße, jÜrgen ❤", s); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] #[inline] pub fn make_ascii_lowercase(&mut self) { self.inner.make_ascii_lowercase() @@ -742,7 +753,6 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// let mut s = OsString::from("Grüße, Jürgen ❤"); @@ -751,7 +761,7 @@ impl OsStr { /// /// assert_eq!("GRüßE, JüRGEN ❤", s); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] #[inline] pub fn make_ascii_uppercase(&mut self) { self.inner.make_ascii_uppercase() @@ -768,13 +778,12 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// let s = OsString::from("Grüße, Jürgen ❤"); /// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_lowercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_lowercase()) } @@ -790,13 +799,12 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// let s = OsString::from("Grüße, Jürgen ❤"); /// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_uppercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_uppercase()) } @@ -806,7 +814,6 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// let ascii = OsString::from("hello!\n"); @@ -815,7 +822,7 @@ impl OsStr { /// assert!(ascii.is_ascii()); /// assert!(!non_ascii.is_ascii()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] #[inline] pub fn is_ascii(&self) -> bool { self.inner.is_ascii() @@ -829,14 +836,13 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS")); /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS")); /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS")); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn eq_ignore_ascii_case>(&self, other: S) -> bool { self.inner.eq_ignore_ascii_case(&other.as_ref().inner) } @@ -864,7 +870,7 @@ impl From> for Box { #[stable(feature = "os_string_from_box", since = "1.18.0")] impl From> for OsString { - /// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or + /// Converts a [`Box`]`<`[`OsStr`]`>` into an [`OsString`] without copying or /// allocating. #[inline] fn from(boxed: Box) -> OsString { diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 43119c36cf..e6120b8ee3 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -265,8 +265,9 @@ pub fn read>(path: P) -> io::Result> { /// ```no_run /// use std::fs; /// use std::net::SocketAddr; +/// use std::error::Error; /// -/// fn main() -> Result<(), Box> { +/// fn main() -> Result<(), Box> { /// let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?; /// Ok(()) /// } @@ -1154,7 +1155,7 @@ impl fmt::Debug for Metadata { .field("modified", &self.modified()) .field("accessed", &self.accessed()) .field("created", &self.created()) - .finish() + .finish_non_exhaustive() } } @@ -1677,9 +1678,9 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// This function will return an error in the following situations, but is not /// limited to just these cases: /// -/// * The `from` path is not a file. -/// * The `from` file does not exist. -/// * The current process does not have the permission rights to access +/// * `from` is neither a regular file nor a symlink to a regular file. +/// * `from` does not exist. +/// * The current process does not have the permission rights to read /// `from` or write `to`. /// /// # Examples @@ -2188,7 +2189,10 @@ impl DirBuilder { match path.parent() { Some(p) => self.create_dir_all(p)?, None => { - return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree")); + return Err(io::Error::new_const( + io::ErrorKind::Other, + &"failed to create whole tree", + )); } } match self.inner.mkdir(path) { diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 5c96974159..ce8d3a56f7 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1329,7 +1329,9 @@ 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::Other && e2.kind() == ErrorKind::Other + || e1.kind() == ErrorKind::Unsupported + && e2.kind() == ErrorKind::Unsupported => {} (a, b) => { panic!("creation time must be always supported or not supported: {:?} {:?}", a, b,) } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 02b0fc0c57..d8021d3e99 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -234,7 +234,7 @@ impl BufReader { /// the buffer will not be flushed, allowing for more efficient seeks. /// This method does not return the location of the underlying reader, so the caller /// must track this information themselves if it is required. - #[unstable(feature = "bufreader_seek_relative", issue = "31100")] + #[stable(feature = "bufreader_seek_relative", since = "1.53.0")] pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> { let pos = self.pos as u64; if offset < 0 { diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 65bc2fcf00..80f98bbbad 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -164,9 +164,9 @@ impl BufWriter { match r { Ok(0) => { - return Err(Error::new( + return Err(Error::new_const( ErrorKind::WriteZero, - "failed to write the buffered data", + &"failed to write the buffered data", )); } Ok(n) => guard.consume(n), diff --git a/library/std/src/io/buffered/linewriter.rs b/library/std/src/io/buffered/linewriter.rs index 502c6e3c6c..d7b620d6f9 100644 --- a/library/std/src/io/buffered/linewriter.rs +++ b/library/std/src/io/buffered/linewriter.rs @@ -227,6 +227,6 @@ where "buffer", &format_args!("{}/{}", self.inner.buffer().len(), self.inner.capacity()), ) - .finish() + .finish_non_exhaustive() } } diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index bbee2cc984..9021b47006 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -229,9 +229,9 @@ where self.pos = n; Ok(self.pos) } - None => Err(Error::new( + None => Err(Error::new_const( ErrorKind::InvalidInput, - "invalid seek to a negative or overflowing position", + &"invalid seek to a negative or overflowing position", )), } } @@ -328,9 +328,9 @@ fn slice_write_vectored( // Resizing write implementation fn vec_write(pos_mut: &mut u64, vec: &mut Vec, buf: &[u8]) -> io::Result { let pos: usize = (*pos_mut).try_into().map_err(|_| { - Error::new( + Error::new_const( ErrorKind::InvalidInput, - "cursor position exceeds maximum possible vector length", + &"cursor position exceeds maximum possible vector length", ) })?; // Make sure the internal buffer is as least as big as where we diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index ba0f0a0cd7..9bed12bf2a 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -69,6 +69,8 @@ impl fmt::Debug for Error { enum Repr { Os(i32), Simple(ErrorKind), + // &str is a fat pointer, but &&str is a thin pointer. + SimpleMessage(ErrorKind, &'static &'static str), Custom(Box), } @@ -178,6 +180,12 @@ pub enum ErrorKind { /// read. #[stable(feature = "read_exact", since = "1.6.0")] UnexpectedEof, + + /// This operation is unsupported on this platform. + /// + /// This means that the operation can never succeed. + #[stable(feature = "unsupported_error", since = "1.53.0")] + Unsupported, } impl ErrorKind { @@ -201,6 +209,7 @@ impl ErrorKind { ErrorKind::Interrupted => "operation interrupted", ErrorKind::Other => "other os error", ErrorKind::UnexpectedEof => "unexpected end of file", + ErrorKind::Unsupported => "unsupported", } } } @@ -259,6 +268,19 @@ impl Error { Error { repr: Repr::Custom(Box::new(Custom { kind, error })) } } + /// Creates a new I/O error from a known kind of error as well as a + /// constant message. + /// + /// This function does not allocate. + /// + /// This function should maybe change to + /// `new_const(kind: ErrorKind)` + /// in the future, when const generics allow that. + #[inline] + pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error { + Self { repr: Repr::SimpleMessage(kind, message) } + } + /// Returns an error representing the last OS error which occurred. /// /// This function reads the value of `errno` for the target platform (e.g. @@ -273,6 +295,7 @@ impl Error { /// println!("last OS error: {:?}", Error::last_os_error()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn last_os_error() -> Error { Error::from_raw_os_error(sys::os::errno() as i32) } @@ -303,6 +326,7 @@ impl Error { /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn from_raw_os_error(code: i32) -> Error { Error { repr: Repr::Os(code) } } @@ -337,11 +361,13 @@ impl Error { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn raw_os_error(&self) -> Option { match self.repr { Repr::Os(i) => Some(i), Repr::Custom(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, } } @@ -373,10 +399,12 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[inline] pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref c) => Some(&*c.error), } } @@ -444,10 +472,12 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[inline] pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref mut c) => Some(&mut *c.error), } } @@ -480,10 +510,12 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[inline] pub fn into_inner(self) -> Option> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(c) => Some(c.error), } } @@ -507,11 +539,13 @@ impl Error { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn kind(&self) -> ErrorKind { match self.repr { Repr::Os(code) => sys::decode_error_kind(code), Repr::Custom(ref c) => c.kind, Repr::Simple(kind) => kind, + Repr::SimpleMessage(kind, _) => kind, } } } @@ -527,6 +561,9 @@ impl fmt::Debug for Repr { .finish(), Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt), Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), + Repr::SimpleMessage(kind, &message) => { + fmt.debug_struct("Error").field("kind", &kind).field("message", &message).finish() + } } } } @@ -541,6 +578,7 @@ impl fmt::Display for Error { } Repr::Custom(ref c) => c.error.fmt(fmt), Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()), + Repr::SimpleMessage(_, &msg) => msg.fmt(fmt), } } } @@ -551,6 +589,7 @@ impl error::Error for Error { fn description(&self) -> &str { match self.repr { Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(), + Repr::SimpleMessage(_, &msg) => msg, Repr::Custom(ref c) => c.error.description(), } } @@ -560,6 +599,7 @@ impl error::Error for Error { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref c) => c.error.cause(), } } @@ -568,6 +608,7 @@ impl error::Error for Error { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref c) => c.error.source(), } } diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index 0cce9368c8..5098a46313 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -1,9 +1,15 @@ use super::{Custom, Error, ErrorKind, Repr}; use crate::error; use crate::fmt; +use crate::mem::size_of; use crate::sys::decode_error_kind; use crate::sys::os::error_string; +#[test] +fn test_size() { + assert!(size_of::() <= size_of::<[usize; 2]>()); +} + #[test] fn test_debug_error() { let code = 6; @@ -51,3 +57,13 @@ fn test_downcasting() { let extracted = err.into_inner().unwrap(); extracted.downcast::().unwrap(); } + +#[test] +fn test_const() { + const E: Error = Error::new_const(ErrorKind::NotFound, &"hello"); + + assert_eq!(E.kind(), ErrorKind::NotFound); + assert_eq!(E.to_string(), "hello"); + assert!(format!("{:?}", E).contains("\"hello\"")); + assert!(format!("{:?}", E).contains("NotFound")); +} diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 9870cfc4c9..6891bd8a66 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -263,7 +263,7 @@ impl Read for &[u8] { #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { if buf.len() > self.len() { - return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")); + return Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer")); } let (a, b) = self.split_at(buf.len()); @@ -345,7 +345,7 @@ impl Write for &mut [u8] { if self.write(data)? == data.len() { Ok(()) } else { - Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) + Err(Error::new_const(ErrorKind::WriteZero, &"failed to write whole buffer")) } } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 6abb300054..94c70c4f26 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -293,6 +293,10 @@ mod util; const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; +pub(crate) fn cleanup() { + stdio::cleanup() +} + struct Guard<'a> { buf: &'a mut Vec, len: usize, @@ -333,7 +337,7 @@ where let ret = f(g.buf); if str::from_utf8(&g.buf[g.len..]).is_err() { ret.and_then(|_| { - Err(Error::new(ErrorKind::InvalidData, "stream did not contain valid UTF-8")) + Err(Error::new_const(ErrorKind::InvalidData, &"stream did not contain valid UTF-8")) }) } else { g.len = g.buf.len(); @@ -429,7 +433,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } if !buf.is_empty() { - Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")) + Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) } else { Ok(()) } @@ -505,7 +509,8 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ /// [`std::io`]: self /// [`File`]: crate::fs::File #[stable(feature = "rust1", since = "1.0.0")] -#[doc(spotlight)] +#[cfg_attr(bootstrap, doc(spotlight))] +#[cfg_attr(not(bootstrap), doc(notable_trait))] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -1296,7 +1301,8 @@ impl Initializer { /// /// [`write_all`]: Write::write_all #[stable(feature = "rust1", since = "1.0.0")] -#[doc(spotlight)] +#[cfg_attr(bootstrap, doc(spotlight))] +#[cfg_attr(not(bootstrap), doc(notable_trait))] pub trait Write { /// Write a buffer into this writer, returning how many bytes were written. /// @@ -1437,7 +1443,10 @@ pub trait Write { while !buf.is_empty() { match self.write(buf) { Ok(0) => { - return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")); + return Err(Error::new_const( + ErrorKind::WriteZero, + &"failed to write whole buffer", + )); } Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} @@ -1502,7 +1511,10 @@ pub trait Write { while !bufs.is_empty() { match self.write_vectored(bufs) { Ok(0) => { - return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")); + return Err(Error::new_const( + ErrorKind::WriteZero, + &"failed to write whole buffer", + )); } Ok(n) => bufs = IoSlice::advance(bufs, n), Err(ref e) if e.kind() == ErrorKind::Interrupted => {} @@ -1576,7 +1588,7 @@ pub trait Write { if output.error.is_err() { output.error } else { - Err(Error::new(ErrorKind::Other, "formatter error")) + Err(Error::new_const(ErrorKind::Other, &"formatter error")) } } } @@ -2108,6 +2120,7 @@ pub trait BufRead: Read { /// /// [`chain`]: Read::chain #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Chain { first: T, second: U, @@ -2189,13 +2202,6 @@ impl Chain { } } -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for Chain { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Chain").field("t", &self.first).field("u", &self.second).finish() - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 1e72c9e061..2b0d2b7e0b 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -13,7 +13,6 @@ use crate::pin::Pin; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::{Arc, Mutex, MutexGuard}; use crate::sys::stdio; -use crate::sys_common; use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; type LocalStream = Arc>>; @@ -373,7 +372,7 @@ impl Stdin { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Stdin { .. }") + f.debug_struct("Stdin").finish_non_exhaustive() } } @@ -467,7 +466,7 @@ impl BufRead for StdinLock<'_> { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for StdinLock<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("StdinLock { .. }") + f.debug_struct("StdinLock").finish_non_exhaustive() } } @@ -508,6 +507,8 @@ pub struct StdoutLock<'a> { inner: ReentrantMutexGuard<'a, RefCell>>, } +static STDOUT: SyncOnceCell>>> = SyncOnceCell::new(); + /// Constructs a new handle to the standard output of the current process. /// /// Each handle returned is a reference to a shared global buffer whose access @@ -549,34 +550,28 @@ pub struct StdoutLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { - static INSTANCE: SyncOnceCell>>> = - SyncOnceCell::new(); - - fn cleanup() { - if let Some(instance) = INSTANCE.get() { - // Flush the data and disable buffering during shutdown - // by replacing the line writer by one with zero - // buffering capacity. - // We use try_lock() instead of lock(), because someone - // might have leaked a StdoutLock, which would - // otherwise cause a deadlock here. - if let Some(lock) = Pin::static_ref(instance).try_lock() { - *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw()); - } - } - } - Stdout { - inner: Pin::static_ref(&INSTANCE).get_or_init_pin( - || unsafe { - let _ = sys_common::at_exit(cleanup); - ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) - }, + inner: Pin::static_ref(&STDOUT).get_or_init_pin( + || unsafe { ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) }, |mutex| unsafe { mutex.init() }, ), } } +pub fn cleanup() { + if let Some(instance) = STDOUT.get() { + // Flush the data and disable buffering during shutdown + // by replacing the line writer by one with zero + // buffering capacity. + // We use try_lock() instead of lock(), because someone + // might have leaked a StdoutLock, which would + // otherwise cause a deadlock here. + if let Some(lock) = Pin::static_ref(instance).try_lock() { + *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw()); + } + } +} + impl Stdout { /// Locks this handle to the standard output stream, returning a writable /// guard. @@ -607,7 +602,7 @@ impl Stdout { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdout { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Stdout { .. }") + f.debug_struct("Stdout").finish_non_exhaustive() } } @@ -689,7 +684,7 @@ impl Write for StdoutLock<'_> { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for StdoutLock<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("StdoutLock { .. }") + f.debug_struct("StdoutLock").finish_non_exhaustive() } } @@ -804,7 +799,7 @@ impl Stderr { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stderr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Stderr { .. }") + f.debug_struct("Stderr").finish_non_exhaustive() } } @@ -886,7 +881,7 @@ impl Write for StderrLock<'_> { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for StderrLock<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("StderrLock { .. }") + f.debug_struct("StderrLock").finish_non_exhaustive() } } diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index a85dd0d982..2b14e16150 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -152,12 +152,12 @@ fn take_eof() { impl Read for R { fn read(&mut self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(io::ErrorKind::Other, "")) + Err(io::Error::new_const(io::ErrorKind::Other, &"")) } } impl BufRead for R { fn fill_buf(&mut self) -> io::Result<&[u8]> { - Err(io::Error::new(io::ErrorKind::Other, "")) + Err(io::Error::new_const(io::ErrorKind::Other, &"")) } fn consume(&mut self, _amt: usize) {} } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index f472361f91..73f2f3eb3f 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -78,7 +78,7 @@ impl Seek for Empty { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Empty { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Empty { .. }") + f.debug_struct("Empty").finish_non_exhaustive() } } @@ -150,7 +150,7 @@ impl Read for Repeat { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Repeat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Repeat { .. }") + f.debug_struct("Repeat").finish_non_exhaustive() } } @@ -236,6 +236,6 @@ impl Write for &Sink { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Sink { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Sink { .. }") + f.debug_struct("Sink").finish_non_exhaustive() } } diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 46bfd834f8..39ed62425c 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -547,15 +547,18 @@ mod fn_keyword {} /// # fn code() { } /// # let iterator = 0..2; /// { -/// let mut _iter = std::iter::IntoIterator::into_iter(iterator); -/// loop { -/// match _iter.next() { -/// Some(loop_variable) => { -/// code() -/// }, -/// None => break, -/// } -/// } +/// let result = match IntoIterator::into_iter(iterator) { +/// mut iter => loop { +/// let next; +/// match iter.next() { +/// Some(val) => next = val, +/// None => break, +/// }; +/// let loop_variable = next; +/// let () = { code(); }; +/// }, +/// }; +/// result /// } /// ``` /// @@ -1031,8 +1034,8 @@ mod mod_keyword {} /// }; /// ``` /// -/// For more information on the `move` keyword, see the [closure]'s section -/// of the Rust book or the [threads] section +/// For more information on the `move` keyword, see the [closures][closure] section +/// of the Rust book or the [threads] section. /// /// [closure]: ../book/ch13-01-closures.html /// [threads]: ../book/ch16-01-threads.html#using-move-closures-with-threads @@ -1765,6 +1768,7 @@ mod super_keyword {} /// In the 2015 edition the parameters pattern was not needed for traits: /// /// ```rust,edition2015 +/// # #![allow(anonymous_parameters)] /// trait Tr { /// fn f(i32); /// } diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index 974851a8bd..ca86e569bc 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -515,7 +515,7 @@ pub struct SyncLazy T> { #[unstable(feature = "once_cell", issue = "74465")] impl fmt::Debug for SyncLazy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() + f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive() } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 1f53a4c783..1b764d5a69 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -208,13 +208,15 @@ // std may use features in a platform-specific way #![allow(unused_features)] #![feature(rustc_allow_const_fn_unstable)] -#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))] +#![cfg_attr( + test, + feature(internal_output_capture, print_internals, update_panic_count, thread_local_const_init) +)] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] #![deny(rustc::existing_doc_keyword)] -#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))] // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. @@ -230,10 +232,11 @@ #![feature(asm)] #![feature(associated_type_bounds)] #![feature(atomic_mut_ptr)] +#![feature(bench_black_box)] #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_accessible)] -#![cfg_attr(not(bootstrap), feature(cfg_eval))] +#![feature(cfg_eval)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] @@ -248,6 +251,7 @@ #![feature(const_ip)] #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] +#![feature(const_socketaddr)] #![feature(const_ipv4)] #![feature(container_error_extra)] #![feature(core_intrinsics)] @@ -256,10 +260,10 @@ #![feature(doc_cfg)] #![feature(doc_keyword)] #![feature(doc_masked)] -#![feature(doc_spotlight)] +#![cfg_attr(bootstrap, feature(doc_spotlight))] +#![cfg_attr(not(bootstrap), feature(doc_notable_trait))] #![feature(dropck_eyepatch)] #![feature(duration_constants)] -#![feature(duration_zero)] #![feature(edition_panic)] #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] @@ -277,8 +281,8 @@ #![feature(integer_atomics)] #![feature(into_future)] #![feature(intra_doc_pointers)] +#![feature(iter_zip)] #![feature(lang_items)] -#![feature(link_args)] #![feature(linkage)] #![feature(llvm_asm)] #![feature(log_syntax)] @@ -296,7 +300,7 @@ #![feature(nonnull_slice_from_raw_parts)] #![feature(once_cell)] #![feature(auto_traits)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(panic_info_message)] #![feature(panic_internals)] #![feature(panic_unwind)] @@ -327,7 +331,6 @@ #![feature(try_blocks)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] #![feature(unsafe_cell_raw_get)] #![feature(unwind_attributes)] #![feature(vec_into_raw_parts)] @@ -456,6 +459,7 @@ 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; @@ -537,22 +541,16 @@ pub mod rt; #[allow(dead_code, unused_attributes)] mod backtrace_rs; -// Pull in the `std_detect` crate directly into libstd. The contents of -// `std_detect` are in a different repository: rust-lang/stdarch. -// -// `std_detect` depends on libstd, but the contents of this module are -// set up in such a way that directly pulling it here works such that the -// crate uses the this crate as its libstd. -#[path = "../../stdarch/crates/std_detect/src/mod.rs"] -#[allow(missing_debug_implementations, missing_docs, dead_code)] -#[unstable(feature = "stdsimd", issue = "48556")] -#[cfg(not(test))] -mod std_detect; - +#[stable(feature = "simd_x86", since = "1.27.0")] +pub use std_detect::is_x86_feature_detected; #[doc(hidden)] #[unstable(feature = "stdsimd", issue = "48556")] -#[cfg(not(test))] -pub use std_detect::detect; +pub use std_detect::*; +#[unstable(feature = "stdsimd", issue = "48556")] +pub use std_detect::{ + is_aarch64_feature_detected, is_arm_feature_detected, is_mips64_feature_detected, + is_mips_feature_detected, is_powerpc64_feature_detected, is_powerpc_feature_detected, +}; // Re-export macros defined in libcore. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 63de871283..70376d5e06 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -57,7 +57,8 @@ pub enum SocketAddr { /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. /// /// The size of a `SocketAddrV4` struct may vary depending on the target operating -/// system. +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. /// /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 /// [`IPv4` address]: Ipv4Addr @@ -76,6 +77,8 @@ pub enum SocketAddr { #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV4 { + // Do not assume that this struct is implemented as the underlying system representation. + // The memory layout is not part of the stable interface that std exposes. inner: c::sockaddr_in, } @@ -88,7 +91,8 @@ pub struct SocketAddrV4 { /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. /// /// The size of a `SocketAddrV6` struct may vary depending on the target operating -/// system. +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. /// /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 /// [`IPv6` address]: Ipv6Addr @@ -107,6 +111,8 @@ pub struct SocketAddrV4 { #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV6 { + // Do not assume that this struct is implemented as the underlying system representation. + // The memory layout is not part of the stable interface that std exposes. inner: c::sockaddr_in6, } @@ -143,7 +149,8 @@ impl SocketAddr { /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] - pub fn ip(&self) -> IpAddr { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn ip(&self) -> IpAddr { match *self { SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), @@ -182,7 +189,8 @@ impl SocketAddr { /// assert_eq!(socket.port(), 8080); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn port(&self) -> u16 { match *self { SocketAddr::V4(ref a) => a.port(), SocketAddr::V6(ref a) => a.port(), @@ -224,7 +232,8 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv6(), false); /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] - pub fn is_ipv4(&self) -> bool { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn is_ipv4(&self) -> bool { matches!(*self, SocketAddr::V4(_)) } @@ -244,7 +253,8 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv6(), true); /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] - pub fn is_ipv6(&self) -> bool { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn is_ipv6(&self) -> bool { matches!(*self, SocketAddr::V6(_)) } } @@ -284,7 +294,8 @@ impl SocketAddrV4 { /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn ip(&self) -> &Ipv4Addr { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn ip(&self) -> &Ipv4Addr { // SAFETY: `Ipv4Addr` is `#[repr(C)] struct { _: in_addr; }`. // It is safe to cast from `&in_addr` to `&Ipv4Addr`. unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) } @@ -317,7 +328,8 @@ impl SocketAddrV4 { /// assert_eq!(socket.port(), 8080); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn port(&self) -> u16 { ntohs(self.inner.sin_port) } @@ -380,7 +392,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn ip(&self) -> &Ipv6Addr { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn ip(&self) -> &Ipv6Addr { unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) } } @@ -411,7 +424,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.port(), 8080); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn port(&self) -> u16 { ntohs(self.inner.sin6_port) } @@ -452,7 +466,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.flowinfo(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn flowinfo(&self) -> u32 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn flowinfo(&self) -> u32 { self.inner.sin6_flowinfo } @@ -490,7 +505,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.scope_id(), 78); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn scope_id(&self) -> u32 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn scope_id(&self) -> u32 { self.inner.sin6_scope_id } diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 2aa305d7f8..9b629e19be 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -67,7 +67,9 @@ pub enum IpAddr { /// /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal /// notation, divided by `.` (this is called "dot-decimal notation"). +/// Notably, octal numbers and hexadecimal numbers are not allowed per [IETF RFC 6943]. /// +/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1 /// [`FromStr`]: crate::str::FromStr /// /// # Examples @@ -332,6 +334,8 @@ impl Ipv4Addr { /// An IPv4 address representing an unspecified address: 0.0.0.0 /// + /// This corresponds to the constant `INADDR_ANY` in other languages. + /// /// # Examples /// /// ``` @@ -340,6 +344,7 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::UNSPECIFIED; /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); /// ``` + #[doc(alias = "INADDR_ANY")] #[stable(feature = "ip_constructors", since = "1.30.0")] pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); @@ -991,6 +996,7 @@ impl Ord for Ipv4Addr { } impl IntoInner for Ipv4Addr { + #[inline] fn into_inner(self) -> c::in_addr { self.inner } @@ -1798,11 +1804,13 @@ impl Ord for Ipv6Addr { } impl AsInner for Ipv6Addr { + #[inline] fn as_inner(&self) -> &c::in6_addr { &self.inner } } impl FromInner for Ipv6Addr { + #[inline] fn from_inner(addr: c::in6_addr) -> Ipv6Addr { Ipv6Addr { inner: addr } } diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index d4b1552fec..d814e9b25b 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -88,6 +88,6 @@ where } } Err(last_err.unwrap_or_else(|| { - Error::new(ErrorKind::InvalidInput, "could not resolve to any addresses") + Error::new_const(ErrorKind::InvalidInput, &"could not resolve to any addresses") })) } diff --git a/library/std/src/net/parser.rs b/library/std/src/net/parser.rs index 7064ed3ed2..88a8cb76be 100644 --- a/library/std/src/net/parser.rs +++ b/library/std/src/net/parser.rs @@ -67,6 +67,11 @@ impl<'a> Parser<'a> { if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(())) } + /// Peek the next character from the input + fn peek_char(&self) -> Option { + self.state.first().map(|&b| char::from(b)) + } + /// Read the next character from the input fn read_char(&mut self) -> Option { self.state.split_first().map(|(&b, tail)| { @@ -132,7 +137,14 @@ impl<'a> Parser<'a> { let mut groups = [0; 4]; for (i, slot) in groups.iter_mut().enumerate() { - *slot = p.read_separator('.', i, |p| p.read_number(10, None))?; + *slot = p.read_separator('.', i, |p| { + // Disallow octal number in IP string. + // https://tools.ietf.org/html/rfc6943#section-3.1.1 + match (p.peek_char(), p.read_number(10, None)) { + (Some('0'), Some(number)) if number != 0 => None, + (_, number) => number, + } + })?; } Some(groups.into()) diff --git a/library/std/src/net/parser/tests.rs b/library/std/src/net/parser/tests.rs index 8d8889cd19..6d2d48ecad 100644 --- a/library/std/src/net/parser/tests.rs +++ b/library/std/src/net/parser/tests.rs @@ -8,11 +8,15 @@ const SCOPE_ID: u32 = 1337; const IPV4: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1); const IPV4_STR: &str = "192.168.0.1"; const IPV4_STR_PORT: &str = "192.168.0.1:8080"; +const IPV4_STR_WITH_OCTAL: &str = "0127.0.0.1"; +const IPV4_STR_WITH_HEX: &str = "0x10.0.0.1"; const IPV6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc0a8, 0x1); const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1"; const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1"; const IPV6_STR_V4: &str = "2001:db8::192.168.0.1"; +const IPV6_STR_V4_WITH_OCTAL: &str = "2001:db8::0127.0.0.1"; +const IPV6_STR_V4_WITH_HEX: &str = "2001:db8::0x10.0.0.1"; const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080"; const IPV6_STR_PORT_SCOPE_ID: &str = "[2001:db8::c0a8:1%1337]:8080"; @@ -22,6 +26,8 @@ fn parse_ipv4() { assert_eq!(result, IPV4); assert!(Ipv4Addr::from_str(IPV4_STR_PORT).is_err()); + assert!(Ipv4Addr::from_str(IPV4_STR_WITH_OCTAL).is_err()); + assert!(Ipv4Addr::from_str(IPV4_STR_WITH_HEX).is_err()); assert!(Ipv4Addr::from_str(IPV6_STR_FULL).is_err()); assert!(Ipv4Addr::from_str(IPV6_STR_COMPRESS).is_err()); assert!(Ipv4Addr::from_str(IPV6_STR_V4).is_err()); @@ -39,6 +45,8 @@ fn parse_ipv6() { let result: Ipv6Addr = IPV6_STR_V4.parse().unwrap(); assert_eq!(result, IPV6); + assert!(Ipv6Addr::from_str(IPV6_STR_V4_WITH_OCTAL).is_err()); + assert!(Ipv6Addr::from_str(IPV6_STR_V4_WITH_HEX).is_err()); assert!(Ipv6Addr::from_str(IPV4_STR).is_err()); assert!(Ipv6Addr::from_str(IPV4_STR_PORT).is_err()); assert!(Ipv6Addr::from_str(IPV6_STR_PORT).is_err()); diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 2377a76a33..b9af5992df 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -173,7 +173,7 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], addr: A) -> io::Result { match addr.to_socket_addrs()?.next() { Some(addr) => self.0.send_to(buf, &addr), - None => Err(Error::new(ErrorKind::InvalidInput, "no addresses to send data to")), + None => Err(Error::new_const(ErrorKind::InvalidInput, &"no addresses to send data to")), } } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 57c892f32b..ed0987064e 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1065,7 +1065,6 @@ impl FusedIterator for Ancestors<'_> {} /// ``` /// /// Which method works best depends on what kind of situation you're in. -#[derive(Clone)] #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")] #[stable(feature = "rust1", since = "1.0.0")] // FIXME: @@ -1406,6 +1405,19 @@ impl PathBuf { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for PathBuf { + #[inline] + fn clone(&self) -> Self { + PathBuf { inner: self.inner.clone() } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner) + } +} + #[stable(feature = "box_from_path", since = "1.17.0")] impl From<&Path> for Box { fn from(path: &Path) -> Box { @@ -1467,7 +1479,7 @@ impl> From<&T> for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { - /// Converts a `OsString` into a `PathBuf` + /// Converts an [`OsString`] into a [`PathBuf`] /// /// This conversion does not allocate or copy memory. #[inline] @@ -1478,7 +1490,7 @@ impl From for PathBuf { #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")] impl From for OsString { - /// Converts a `PathBuf` into a `OsString` + /// Converts a [`PathBuf`] into an [`OsString`] /// /// This conversion does not allocate or copy memory. #[inline] @@ -1489,7 +1501,7 @@ impl From for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { - /// Converts a `String` into a `PathBuf` + /// Converts a [`String`] into a [`PathBuf`] /// /// This conversion does not allocate or copy memory. #[inline] @@ -1595,7 +1607,7 @@ impl<'a> From> for PathBuf { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer. + /// Converts a [`PathBuf`] into an [`Arc`] by moving the [`PathBuf`] data into a new [`Arc`] buffer. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1605,7 +1617,7 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&Path> for Arc { - /// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer. + /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer. #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); @@ -1615,7 +1627,7 @@ impl From<&Path> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer. + /// Converts a [`PathBuf`] into an [`Rc`] by moving the [`PathBuf`] data into a new `Rc` buffer. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); @@ -1625,7 +1637,7 @@ impl From for Rc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&Path> for Rc { - /// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer. + /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new `Rc` buffer. #[inline] fn from(s: &Path) -> Rc { let rc: Rc = Rc::from(s.as_os_str()); diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index 505b5f3013..1b4facdd04 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -28,53 +28,53 @@ //! The current version of the prelude (version 1) lives in //! [`std::prelude::v1`], and re-exports the following: //! -//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}: +//! * [std::marker]::{[Copy], [Send], [Sized], [Sync], [Unpin]}, //! marker traits that indicate fundamental properties of types. -//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}: various +//! * [std::ops]::{[Drop], [Fn], [FnMut], [FnOnce]}, various //! operations for both destructors and overloading `()`. -//! * [`std::mem`]::[`drop`][`mem::drop`]: a convenience function for explicitly +//! * [std::mem]::[drop][mem::drop], a convenience function for explicitly //! dropping a value. -//! * [`std::boxed`]::[`Box`]: a way to allocate values on the heap. -//! * [`std::borrow`]::[`ToOwned`]: the conversion trait that defines +//! * [std::boxed]::[Box], a way to allocate values on the heap. +//! * [std::borrow]::[ToOwned], the conversion trait that defines //! [`to_owned`], the generic method for creating an owned type from a //! borrowed type. -//! * [`std::clone`]::[`Clone`]: the ubiquitous trait that defines -//! [`clone`][`Clone::clone`], the method for producing a copy of a value. -//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`]}: the +//! * [std::clone]::[Clone], the ubiquitous trait that defines +//! [`clone`][Clone::clone], the method for producing a copy of a value. +//! * [std::cmp]::{[PartialEq], [PartialOrd], [Eq], [Ord]}, the //! comparison traits, which implement the comparison operators and are often //! seen in trait bounds. -//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}: generic +//! * [std::convert]::{[AsRef], [AsMut], [Into], [From]}, generic //! conversions, used by savvy API authors to create overloaded methods. -//! * [`std::default`]::[`Default`], types that have default values. -//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`], -//! [`DoubleEndedIterator`], [`ExactSizeIterator`]}: iterators of various +//! * [std::default]::[Default], types that have default values. +//! * [std::iter]::{[Iterator], [Extend], [IntoIterator], [DoubleEndedIterator], [ExactSizeIterator]}, +//! iterators of various //! kinds. -//! * [`std::option`]::[`Option`]::{[`self`][`Option`], [`Some`], [`None`]}, a +//! * [std::option]::[Option]::{[self][Option], [Some], [None]}, a //! type which expresses the presence or absence of a value. This type is so //! commonly used, its variants are also exported. -//! * [`std::result`]::[`Result`]::{[`self`][`Result`], [`Ok`], [`Err`]}: a type +//! * [std::result]::[Result]::{[self][Result], [Ok], [Err]}, a type //! for functions that may succeed or fail. Like [`Option`], its variants are //! exported as well. -//! * [`std::string`]::{[`String`], [`ToString`]}: heap-allocated strings. -//! * [`std::vec`]::[`Vec`]: a growable, heap-allocated vector. +//! * [std::string]::{[String], [ToString]}, heap-allocated strings. +//! * [std::vec]::[Vec], a growable, heap-allocated vector. //! -//! [`mem::drop`]: crate::mem::drop -//! [`std::borrow`]: crate::borrow -//! [`std::boxed`]: crate::boxed -//! [`std::clone`]: crate::clone -//! [`std::cmp`]: crate::cmp -//! [`std::convert`]: crate::convert -//! [`std::default`]: crate::default -//! [`std::iter`]: crate::iter -//! [`std::marker`]: crate::marker -//! [`std::mem`]: crate::mem -//! [`std::ops`]: crate::ops -//! [`std::option`]: crate::option +//! [mem::drop]: crate::mem::drop +//! [std::borrow]: crate::borrow +//! [std::boxed]: crate::boxed +//! [std::clone]: crate::clone +//! [std::cmp]: crate::cmp +//! [std::convert]: crate::convert +//! [std::default]: crate::default +//! [std::iter]: crate::iter +//! [std::marker]: crate::marker +//! [std::mem]: crate::mem +//! [std::ops]: crate::ops +//! [std::option]: crate::option //! [`std::prelude::v1`]: v1 -//! [`std::result`]: crate::result -//! [`std::slice`]: crate::slice -//! [`std::string`]: crate::string -//! [`std::vec`]: mod@crate::vec +//! [std::result]: crate::result +//! [std::slice]: crate::slice +//! [std::string]: crate::string +//! [std::vec]: mod@crate::vec //! [`to_owned`]: crate::borrow::ToOwned::to_owned //! [book-closures]: ../../book/ch13-01-closures.html //! [book-dtor]: ../../book/ch15-03-drop.html diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index c5b871edbf..4a3c3ba163 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -54,7 +54,6 @@ pub use core::prelude::v1::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(hidden)] pub use core::prelude::v1::derive; @@ -67,7 +66,6 @@ pub use core::prelude::v1::derive; #[doc(hidden)] pub use core::prelude::v1::cfg_accessible; -#[cfg(not(bootstrap))] #[unstable( feature = "cfg_eval", issue = "82679", diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index d4bb2083d0..cd6b0b2d7e 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -498,7 +498,7 @@ mod prim_pointer {} /// - [`Copy`] /// - [`Clone`] /// - [`Debug`] -/// - [`IntoIterator`] (implemented for `&[T; N]` and `&mut [T; N]`) +/// - [`IntoIterator`] (implemented for `[T; N]`, `&[T; N]` and `&mut [T; N]`) /// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] /// - [`Hash`] /// - [`AsRef`], [`AsMut`] @@ -517,7 +517,8 @@ mod prim_pointer {} /// /// # Examples /// -/// ``` +#[cfg_attr(bootstrap, doc = "```ignore")] +#[cfg_attr(not(bootstrap), doc = "```")] /// let mut array: [i32; 3] = [0; 3]; /// /// array[1] = 1; @@ -526,42 +527,123 @@ mod prim_pointer {} /// assert_eq!([1, 2], &array[1..]); /// /// // This loop prints: 0 1 2 -/// for x in &array { +/// for x in array { /// print!("{} ", x); /// } /// ``` /// -/// An array itself is not iterable: +/// You can also iterate over reference to the array's elements: /// -/// ```compile_fail,E0277 +/// ``` /// let array: [i32; 3] = [0; 3]; /// -/// for x in array { } -/// // error: the trait bound `[i32; 3]: std::iter::Iterator` is not satisfied +/// for x in &array { } /// ``` /// -/// The solution is to coerce the array to a slice by calling a slice method: +/// You can use a [slice pattern] to move elements out of an array: /// /// ``` -/// # let array: [i32; 3] = [0; 3]; -/// for x in array.iter() { } +/// fn move_away(_: String) { /* Do interesting things. */ } +/// +/// let [john, roa] = ["John".to_string(), "Roa".to_string()]; +/// move_away(john); +/// move_away(roa); /// ``` /// -/// You can also use the array reference's [`IntoIterator`] implementation: +/// # Editions /// -/// ``` -/// # let array: [i32; 3] = [0; 3]; -/// for x in &array { } +/// Prior to Rust 1.53, arrays did not implement `IntoIterator` by value, so the method call +/// `array.into_iter()` auto-referenced into a slice iterator. Right now, the old behavior +/// is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring +/// `IntoIterator` by value. In the future, the behavior on the 2015 and 2018 edition +/// might be made consistent to the behavior of later editions. +/// +#[cfg_attr(bootstrap, doc = "```rust,edition2018,ignore")] +#[cfg_attr(not(bootstrap), doc = "```rust,edition2018")] +/// # #![allow(array_into_iter)] // override our `deny(warnings)` +/// let array: [i32; 3] = [0; 3]; +/// +/// // This creates a slice iterator, producing references to each value. +/// for item in array.into_iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// +/// // The `array_into_iter` lint suggests this change for future compatibility: +/// for item in array.iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// +/// // You can explicitly iterate an array by value using +/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`: +/// for item in IntoIterator::into_iter(array).enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{}] = {}", i, x); +/// } /// ``` /// -/// You can use a [slice pattern] to move elements out of an array: +/// Starting in the 2021 edition, `array.into_iter()` will use `IntoIterator` normally to iterate +/// by value, and `iter()` should be used to iterate by reference like previous editions. /// +/// ```rust,edition2021,ignore +/// # // FIXME: ignored because 2021 testing is still unstable +/// let array: [i32; 3] = [0; 3]; +/// +/// // This iterates by reference: +/// for item in array.iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// +/// // This iterates by value: +/// for item in array.into_iter().enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{}] = {}", i, x); +/// } /// ``` -/// fn move_away(_: String) { /* Do interesting things. */ } /// -/// let [john, roa] = ["John".to_string(), "Roa".to_string()]; -/// move_away(john); -/// move_away(roa); +/// Future language versions might start treating the `array.into_iter()` +/// syntax on editions 2015 and 2018 the same as on edition 2021. So code using +/// those older editions should still be written with this change in mind, to +/// prevent breakage in the future. The safest way to accomplish this is to +/// avoid the `into_iter` syntax on those editions. If an edition update is not +/// viable/desired, there are multiple alternatives: +/// * use `iter`, equivalent to the old behavior, creating references +/// * use [`array::IntoIter`], equivalent to the post-2021 behavior (Rust 1.51+) +/// * replace `for ... in array.into_iter() {` with `for ... in array {`, +/// equivalent to the post-2021 behavior (Rust 1.53+) +/// +#[cfg_attr(bootstrap, doc = "```rust,edition2018,ignore")] +#[cfg_attr(not(bootstrap), doc = "```rust,edition2018")] +/// use std::array::IntoIter; +/// +/// let array: [i32; 3] = [0; 3]; +/// +/// // This iterates by reference: +/// for item in array.iter() { +/// let x: &i32 = item; +/// println!("{}", x); +/// } +/// +/// // This iterates by value: +/// for item in IntoIter::new(array) { +/// let x: i32 = item; +/// println!("{}", x); +/// } +/// +/// // This iterates by value: +/// for item in array { +/// let x: i32 = item; +/// println!("{}", x); +/// } +/// +/// // IntoIter can also start a chain. +/// // This iterates by value: +/// for item in IntoIter::new(array).enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{}] = {}", i, x); +/// } /// ``` /// /// [slice]: prim@slice @@ -805,10 +887,12 @@ mod prim_tuple {} /// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will /// print `0.2`. /// -/// Additionally, `f32` can represent a couple of special values: +/// Additionally, `f32` can represent some special values: /// -/// - `-0`: this is just due to how floats are encoded. It is semantically -/// equivalent to `0` and `-0.0 == 0.0` results in `true`. +/// - −0.0: IEEE 754 floating point numbers have a bit that indicates their sign, so −0.0 is a +/// possible value. For comparison −0.0 = +0.0, but floating point operations can carry +/// the sign bit through arithmetic operations. This means −0.0 × +0.0 produces −0.0 and +/// a negative number rounded to a value smaller than a float can represent also produces −0.0. /// - [∞](#associatedconstant.INFINITY) and /// [−∞](#associatedconstant.NEG_INFINITY): these result from calculations /// like `1.0 / 0.0`. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index f9cfd11e90..b45c620fd0 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -234,7 +234,7 @@ impl fmt::Debug for Child { .field("stdin", &self.stdin) .field("stdout", &self.stdout) .field("stderr", &self.stderr) - .finish() + .finish_non_exhaustive() } } @@ -312,7 +312,7 @@ impl FromInner for ChildStdin { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("ChildStdin { .. }") + f.debug_struct("ChildStdin").finish_non_exhaustive() } } @@ -373,7 +373,7 @@ impl FromInner for ChildStdout { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdout { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("ChildStdout { .. }") + f.debug_struct("ChildStdout").finish_non_exhaustive() } } @@ -434,7 +434,7 @@ impl FromInner for ChildStderr { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStderr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("ChildStderr { .. }") + f.debug_struct("ChildStderr").finish_non_exhaustive() } } @@ -1257,7 +1257,7 @@ impl FromInner for Stdio { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdio { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Stdio { .. }") + f.debug_struct("Stdio").finish_non_exhaustive() } } @@ -1749,7 +1749,7 @@ impl Child { /// [platform-specific behavior]: #platform-specific-behavior #[stable(feature = "rust1", since = "1.0.0")] pub fn exit(code: i32) -> ! { - crate::sys_common::cleanup(); + crate::sys_common::rt::cleanup(); crate::sys::os::exit(code) } diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 45af9f68a0..1e19aff51f 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -26,33 +26,16 @@ fn lang_start_internal( argv: *const *const u8, ) -> isize { use crate::panic; - use crate::sys; use crate::sys_common; - use crate::sys_common::thread_info; - use crate::thread::Thread; - sys::init(); + // SAFETY: Only called once during runtime initialization. + unsafe { sys_common::rt::init(argc, argv) }; - unsafe { - let main_guard = sys::thread::guard::init(); - sys::stack_overflow::init(); + let exit_code = panic::catch_unwind(main); - // Next, set up the current Thread with the guard information we just - // created. Note that this isn't necessary in general for new threads, - // but we just do this to name the main thread and to give it correct - // info about the stack bounds. - let thread = Thread::new(Some("main".to_owned())); - thread_info::set(main_guard, thread); + sys_common::rt::cleanup(); - // Store our args if necessary in a squirreled away location - sys::args::init(argc, argv); - - // Let's run some code! - let exit_code = panic::catch_unwind(main); - - sys_common::cleanup(); - exit_code.unwrap_or(101) as isize - } + exit_code.unwrap_or(101) as isize } #[cfg(not(test))] diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index eab26b6c71..a17b82f82e 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -60,7 +60,7 @@ pub struct BarrierWaitResult(bool); #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Barrier { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Barrier { .. }") + f.debug_struct("Barrier").finish_non_exhaustive() } } diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index ffc1e57f4e..2f0b32c90d 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -2,9 +2,8 @@ mod tests; use crate::fmt; -use crate::sync::{mutex, MutexGuard, PoisonError}; +use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError}; use crate::sys_common::condvar as sys; -use crate::sys_common::poison::{self, LockResult}; use crate::time::{Duration, Instant}; /// A type indicating whether a timed wait on a condition variable returned @@ -548,7 +547,7 @@ impl Condvar { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Condvar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Condvar { .. }") + f.debug_struct("Condvar").finish_non_exhaustive() } } diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index b6699910b0..ee35598bab 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -166,9 +166,9 @@ pub use self::mutex::{Mutex, MutexGuard}; #[allow(deprecated)] pub use self::once::{Once, OnceState, ONCE_INIT}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; +pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult}; #[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::poison::{LockResult, PoisonError, TryLockError, TryLockResult}; +pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; pub mod mpsc; @@ -176,4 +176,5 @@ mod barrier; mod condvar; mod mutex; mod once; +mod poison; mod rwlock; diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index b12e7eeb13..ea1d598d26 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -864,7 +864,7 @@ impl Drop for Sender { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for Sender { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Sender").finish() + f.debug_struct("Sender").finish_non_exhaustive() } } @@ -991,7 +991,7 @@ impl Drop for SyncSender { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for SyncSender { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("SyncSender").finish() + f.debug_struct("SyncSender").finish_non_exhaustive() } } @@ -1470,14 +1470,14 @@ impl Drop for Receiver { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for Receiver { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Receiver").finish() + f.debug_struct("Receiver").finish_non_exhaustive() } } #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for SendError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "SendError(..)".fmt(f) + f.debug_struct("SendError").finish_non_exhaustive() } } diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index ab61618dc7..773ab18b2c 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -3,11 +3,9 @@ mod tests; use crate::cell::UnsafeCell; use crate::fmt; -use crate::mem; use crate::ops::{Deref, DerefMut}; -use crate::ptr; +use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; use crate::sys_common::mutex as sys; -use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; /// A mutual exclusion primitive useful for protecting shared data /// @@ -376,23 +374,8 @@ impl Mutex { where T: Sized, { - // We know statically that there are no outstanding references to - // `self` so there's no need to lock the inner mutex. - // - // To get the inner value, we'd like to call `data.into_inner()`, - // but because `Mutex` impl-s `Drop`, we can't move out of it, so - // we'll have to destructure it manually instead. - unsafe { - // Like `let Mutex { inner, poison, data } = self`. - let (inner, poison, data) = { - let Mutex { ref inner, ref poison, ref data } = self; - (ptr::read(inner), ptr::read(poison), ptr::read(data)) - }; - mem::forget(self); - drop(inner); - - poison::map_result(poison.borrow(), |_| data.into_inner()) - } + let data = self.data.into_inner(); + poison::map_result(self.poison.borrow(), |_| data) } /// Returns a mutable reference to the underlying data. @@ -441,10 +424,13 @@ impl Default for Mutex { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Mutex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_struct("Mutex"); match self.try_lock() { - Ok(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), + Ok(guard) => { + d.field("data", &&*guard); + } Err(TryLockError::Poisoned(err)) => { - f.debug_struct("Mutex").field("data", &&**err.get_ref()).finish() + d.field("data", &&**err.get_ref()); } Err(TryLockError::WouldBlock) => { struct LockedPlaceholder; @@ -453,10 +439,11 @@ impl fmt::Debug for Mutex { f.write_str("") } } - - f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish() + d.field("data", &LockedPlaceholder); } } + d.field("poisoned", &self.poison.get()); + d.finish_non_exhaustive() } } diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 2e5f843fc4..6da6c18e47 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -471,7 +471,7 @@ fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) { // If the managing thread happens to signal and unpark us before we // can park ourselves, the result could be this thread never gets // unparked. Luckily `park` comes with the guarantee that if it got - // an `unpark` just before on an unparked thread is does not park. + // an `unpark` just before on an unparked thread it does not park. thread::park(); } break; @@ -481,7 +481,7 @@ fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Once { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Once { .. }") + f.debug_struct("Once").finish_non_exhaustive() } } diff --git a/library/std/src/sys_common/poison.rs b/library/std/src/sync/poison.rs similarity index 94% rename from library/std/src/sys_common/poison.rs rename to library/std/src/sync/poison.rs index 2ab2c700a1..05e1833c3e 100644 --- a/library/std/src/sys_common/poison.rs +++ b/library/std/src/sync/poison.rs @@ -3,9 +3,6 @@ use crate::fmt; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::thread; -#[allow(unused_imports)] // for intra-doc links -use crate::sync::{Mutex, RwLock}; - pub struct Flag { failed: AtomicBool, } @@ -80,6 +77,8 @@ pub struct Guard { /// } /// }; /// ``` +/// [`Mutex`]: crate::sync::Mutex +/// [`RwLock`]: crate::sync::RwLock #[stable(feature = "rust1", since = "1.0.0")] pub struct PoisonError { guard: T, @@ -89,9 +88,11 @@ pub struct PoisonError { /// can occur while trying to acquire a lock, from the [`try_lock`] method on a /// [`Mutex`] or the [`try_read`] and [`try_write`] methods on an [`RwLock`]. /// -/// [`try_lock`]: Mutex::try_lock -/// [`try_read`]: RwLock::try_read -/// [`try_write`]: RwLock::try_write +/// [`try_lock`]: crate::sync::Mutex::try_lock +/// [`try_read`]: crate::sync::RwLock::try_read +/// [`try_write`]: crate::sync::RwLock::try_write +/// [`Mutex`]: crate::sync::Mutex +/// [`RwLock`]: crate::sync::RwLock #[stable(feature = "rust1", since = "1.0.0")] pub enum TryLockError { /// The lock could not be acquired because another thread failed while holding @@ -127,7 +128,7 @@ pub type TryLockResult = Result>; #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for PoisonError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "PoisonError { inner: .. }".fmt(f) + f.debug_struct("PoisonError").finish_non_exhaustive() } } @@ -149,7 +150,8 @@ impl Error for PoisonError { impl PoisonError { /// Creates a `PoisonError`. /// - /// This is generally created by methods like [`Mutex::lock`] or [`RwLock::read`]. + /// This is generally created by methods like [`Mutex::lock`](crate::sync::Mutex::lock) + /// or [`RwLock::read`](crate::sync::RwLock::read). #[stable(feature = "sync_poison", since = "1.2.0")] pub fn new(guard: T) -> PoisonError { PoisonError { guard } diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 0298f59228..b01bcec136 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -6,7 +6,7 @@ use crate::fmt; use crate::mem; use crate::ops::{Deref, DerefMut}; use crate::ptr; -use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; +use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; use crate::sys_common::rwlock as sys; /// A reader-writer lock @@ -422,10 +422,13 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for RwLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_struct("RwLock"); match self.try_read() { - Ok(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(), + Ok(guard) => { + d.field("data", &&*guard); + } Err(TryLockError::Poisoned(err)) => { - f.debug_struct("RwLock").field("data", &&**err.get_ref()).finish() + d.field("data", &&**err.get_ref()); } Err(TryLockError::WouldBlock) => { struct LockedPlaceholder; @@ -434,10 +437,11 @@ impl fmt::Debug for RwLock { f.write_str("") } } - - f.debug_struct("RwLock").field("data", &LockedPlaceholder).finish() + d.field("data", &LockedPlaceholder); } } + d.field("poisoned", &self.poison.get()); + d.finish_non_exhaustive() } } @@ -473,7 +477,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for RwLockReadGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RwLockReadGuard").field("lock", &self.lock).finish() + (**self).fmt(f) } } @@ -487,7 +491,7 @@ impl fmt::Display for RwLockReadGuard<'_, T> { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for RwLockWriteGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RwLockWriteGuard").field("lock", &self.lock).finish() + (**self).fmt(f) } } diff --git a/library/std/src/sys_common/alloc.rs b/library/std/src/sys/common/alloc.rs similarity index 98% rename from library/std/src/sys_common/alloc.rs rename to library/std/src/sys/common/alloc.rs index 6c1bc0d839..2a54e99020 100644 --- a/library/std/src/sys_common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - use crate::alloc::{GlobalAlloc, Layout, System}; use crate::cmp; use crate::ptr; diff --git a/library/std/src/sys/common/mod.rs b/library/std/src/sys/common/mod.rs new file mode 100644 index 0000000000..ff64d2aa82 --- /dev/null +++ b/library/std/src/sys/common/mod.rs @@ -0,0 +1,13 @@ +// This module contains code that is shared between all platforms, mostly utility or fallback code. +// This explicitly does not include code that is shared between only a few platforms, +// such as when reusing an implementation from `unix` or `unsupported`. +// In those cases the desired code should be included directly using the #[path] attribute, +// not moved to this module. +// +// Currently `sys_common` contains a lot of code that should live in this module, +// ideally `sys_common` would only contain platform-independent abstractions on top of `sys`. +// Progress on this is tracked in #84187. + +#![allow(dead_code)] + +pub mod alloc; diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs index 7727293927..4eb0d8437b 100644 --- a/library/std/src/sys/hermit/args.rs +++ b/library/std/src/sys/hermit/args.rs @@ -1,5 +1,5 @@ use crate::ffi::OsString; -use crate::marker::PhantomData; +use crate::fmt; use crate::vec; /// One-time global initialization. @@ -19,15 +19,17 @@ pub fn args() -> Args { pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } -impl Args { - pub fn inner_debug(&self) -> &[OsString] { - self.iter.as_slice() +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) } } +impl !Send for Args {} +impl !Sync for Args {} + impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { @@ -53,7 +55,6 @@ impl DoubleEndedIterator for Args { mod imp { use super::Args; use crate::ffi::{CStr, OsString}; - use crate::marker::PhantomData; use crate::ptr; use crate::sys_common::os_str_bytes::*; @@ -76,7 +77,7 @@ mod imp { } pub fn args() -> Args { - Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: clone().into_iter() } } fn clone() -> Vec { diff --git a/library/std/src/sys/hermit/cmath.rs b/library/std/src/sys/hermit/cmath.rs deleted file mode 100644 index 304cf906b2..0000000000 --- a/library/std/src/sys/hermit/cmath.rs +++ /dev/null @@ -1,29 +0,0 @@ -// These symbols are all defined in `compiler-builtins` -extern "C" { - pub fn acos(n: f64) -> f64; - pub fn acosf(n: f32) -> f32; - pub fn asin(n: f64) -> f64; - pub fn asinf(n: f32) -> f32; - pub fn atan(n: f64) -> f64; - pub fn atan2(a: f64, b: f64) -> f64; - pub fn atan2f(a: f32, b: f32) -> f32; - pub fn atanf(n: f32) -> f32; - pub fn cbrt(n: f64) -> f64; - pub fn cbrtf(n: f32) -> f32; - pub fn cosh(n: f64) -> f64; - pub fn coshf(n: f32) -> f32; - pub fn expm1(n: f64) -> f64; - pub fn expm1f(n: f32) -> f32; - pub fn fdim(a: f64, b: f64) -> f64; - pub fn fdimf(a: f32, b: f32) -> f32; - pub fn hypot(x: f64, y: f64) -> f64; - pub fn hypotf(x: f32, y: f32) -> f32; - pub fn log1p(n: f64) -> f64; - pub fn log1pf(n: f32) -> f32; - pub fn sinh(n: f64) -> f64; - pub fn sinhf(n: f32) -> f32; - pub fn tan(n: f64) -> f64; - pub fn tanf(n: f32) -> f32; - pub fn tanh(n: f64) -> f64; - pub fn tanhf(n: f32) -> f32; -} diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs index 97d1a38b41..c400f5f2c2 100644 --- a/library/std/src/sys/hermit/fd.rs +++ b/library/std/src/sys/hermit/fd.rs @@ -1,9 +1,10 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -use crate::io::{self, ErrorKind, Read}; +use crate::io::{self, Read}; use crate::mem; use crate::sys::cvt; use crate::sys::hermit::abi; +use crate::sys::unsupported; use crate::sys_common::AsInner; #[derive(Debug)] @@ -46,7 +47,7 @@ impl FileDesc { self.duplicate_path(&[]) } pub fn duplicate_path(&self, _path: &[u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "duplicate isn't supported")) + unsupported() } pub fn nonblocking(&self) -> io::Result { @@ -54,11 +55,11 @@ impl FileDesc { } pub fn set_cloexec(&self) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "cloexec isn't supported")) + unsupported() } pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "nonblocking isn't supported")) + unsupported() } } diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index 1807655e97..5b3f2fa4e8 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -9,7 +9,7 @@ use crate::sys::hermit::abi; use crate::sys::hermit::abi::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}; use crate::sys::hermit::fd::FileDesc; use crate::sys::time::SystemTime; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::sys_common::os_str_bytes::OsStrExt; pub use crate::sys_common::fs::copy; @@ -22,11 +22,11 @@ fn cstr(path: &Path) -> io::Result { #[derive(Debug)] pub struct File(FileDesc); -pub struct FileAttr(Void); +pub struct FileAttr(!); -pub struct ReadDir(Void); +pub struct ReadDir(!); -pub struct DirEntry(Void); +pub struct DirEntry(!); #[derive(Clone, Debug)] pub struct OpenOptions { @@ -41,64 +41,64 @@ pub struct OpenOptions { mode: i32, } -pub struct FilePermissions(Void); +pub struct FilePermissions(!); -pub struct FileType(Void); +pub struct FileType(!); #[derive(Debug)] pub struct DirBuilder {} impl FileAttr { pub fn size(&self) -> u64 { - match self.0 {} + self.0 } pub fn perm(&self) -> FilePermissions { - match self.0 {} + self.0 } pub fn file_type(&self) -> FileType { - match self.0 {} + self.0 } pub fn modified(&self) -> io::Result { - match self.0 {} + self.0 } pub fn accessed(&self) -> io::Result { - match self.0 {} + self.0 } pub fn created(&self) -> io::Result { - match self.0 {} + self.0 } } impl Clone for FileAttr { fn clone(&self) -> FileAttr { - match self.0 {} + self.0 } } impl FilePermissions { pub fn readonly(&self) -> bool { - match self.0 {} + self.0 } pub fn set_readonly(&mut self, _readonly: bool) { - match self.0 {} + self.0 } } impl Clone for FilePermissions { fn clone(&self) -> FilePermissions { - match self.0 {} + self.0 } } impl PartialEq for FilePermissions { fn eq(&self, _other: &FilePermissions) -> bool { - match self.0 {} + self.0 } } @@ -106,27 +106,27 @@ impl Eq for FilePermissions {} impl fmt::Debug for FilePermissions { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } impl FileType { pub fn is_dir(&self) -> bool { - match self.0 {} + self.0 } pub fn is_file(&self) -> bool { - match self.0 {} + self.0 } pub fn is_symlink(&self) -> bool { - match self.0 {} + self.0 } } impl Clone for FileType { fn clone(&self) -> FileType { - match self.0 {} + self.0 } } @@ -134,7 +134,7 @@ impl Copy for FileType {} impl PartialEq for FileType { fn eq(&self, _other: &FileType) -> bool { - match self.0 {} + self.0 } } @@ -142,19 +142,19 @@ impl Eq for FileType {} impl Hash for FileType { fn hash(&self, _h: &mut H) { - match self.0 {} + self.0 } } impl fmt::Debug for FileType { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } impl fmt::Debug for ReadDir { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } @@ -162,25 +162,25 @@ impl Iterator for ReadDir { type Item = io::Result; fn next(&mut self) -> Option> { - match self.0 {} + self.0 } } impl DirEntry { pub fn path(&self) -> PathBuf { - match self.0 {} + self.0 } pub fn file_name(&self) -> OsString { - match self.0 {} + self.0 } pub fn metadata(&self) -> io::Result { - match self.0 {} + self.0 } pub fn file_type(&self) -> io::Result { - match self.0 {} + self.0 } } @@ -226,7 +226,7 @@ impl OpenOptions { (false, _, true) => Ok(O_WRONLY | O_APPEND), (true, _, true) => Ok(O_RDWR | O_APPEND), (false, false, false) => { - Err(io::Error::new(ErrorKind::InvalidInput, "invalid access mode")) + Err(io::Error::new_const(ErrorKind::InvalidInput, &"invalid access mode")) } } } @@ -236,12 +236,18 @@ impl OpenOptions { (true, false) => {} (false, false) => { if self.truncate || self.create || self.create_new { - return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"invalid creation mode", + )); } } (_, true) => { if self.truncate && !self.create_new { - return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"invalid creation mode", + )); } } } diff --git a/library/std/src/sys/hermit/io.rs b/library/std/src/sys/hermit/io.rs deleted file mode 100644 index d5f475b431..0000000000 --- a/library/std/src/sys/hermit/io.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::mem; - -#[derive(Copy, Clone)] -pub struct IoSlice<'a>(&'a [u8]); - -impl<'a> IoSlice<'a> { - #[inline] - pub fn new(buf: &'a [u8]) -> IoSlice<'a> { - IoSlice(buf) - } - - #[inline] - pub fn advance(&mut self, n: usize) { - self.0 = &self.0[n..] - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - self.0 - } -} - -pub struct IoSliceMut<'a>(&'a mut [u8]); - -impl<'a> IoSliceMut<'a> { - #[inline] - pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { - IoSliceMut(buf) - } - - #[inline] - pub fn advance(&mut self, n: usize) { - let slice = mem::replace(&mut self.0, &mut []); - let (_, remaining) = slice.split_at_mut(n); - self.0 = remaining; - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - self.0 - } - - #[inline] - pub fn as_mut_slice(&mut self) -> &mut [u8] { - self.0 - } -} diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index 17a51abeb0..0c49a6fb6d 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -20,27 +20,30 @@ use crate::os::raw::c_char; pub mod alloc; pub mod args; +#[path = "../unix/cmath.rs"] pub mod cmath; pub mod condvar; pub mod env; pub mod ext; pub mod fd; pub mod fs; +#[path = "../unsupported/io.rs"] pub mod io; pub mod memchr; pub mod mutex; pub mod net; pub mod os; +#[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] pub mod process; pub mod rwlock; -pub mod stack_overflow; pub mod stdio; pub mod thread; pub mod thread_local_dtor; +#[path = "../unsupported/thread_local_key.rs"] pub mod thread_local_key; pub mod time; @@ -55,14 +58,12 @@ pub fn unsupported() -> crate::io::Result { } pub fn unsupported_err() -> crate::io::Error { - crate::io::Error::new(crate::io::ErrorKind::Other, "operation not supported on HermitCore yet") + crate::io::Error::new_const( + crate::io::ErrorKind::Unsupported, + &"operation not supported on HermitCore yet", + ) } -// This enum is used as the storage for a bunch of types which can't actually -// exist. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub enum Void {} - pub unsafe fn strlen(start: *const c_char) -> usize { let mut str = start; @@ -98,9 +99,17 @@ pub extern "C" fn __rust_abort() { abort_internal(); } -#[cfg(not(test))] -pub fn init() { +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +pub unsafe fn init(argc: isize, argv: *const *const u8) { let _ = net::init(); + args::init(argc, argv); +} + +// 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(); } #[cfg(not(test))] diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index 8a788a9265..5f8839157e 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -6,7 +6,7 @@ use crate::str; use crate::sync::Arc; use crate::sys::hermit::abi; use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6}; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::sys_common::AsInner; use crate::time::Duration; @@ -14,7 +14,10 @@ use crate::time::Duration; /// if not, starts it. pub fn init() -> io::Result<()> { if abi::network_init() < 0 { - return Err(io::Error::new(ErrorKind::Other, "Unable to initialize network interface")); + return Err(io::Error::new_const( + ErrorKind::Other, + &"Unable to initialize network interface", + )); } Ok(()) @@ -47,9 +50,10 @@ 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(ErrorKind::Other, "Unable to initiate a connection on a socket")) - } + _ => Err(io::Error::new_const( + ErrorKind::Other, + &"Unable to initiate a connection on a socket", + )), } } @@ -60,15 +64,16 @@ impl TcpStream { Some(duration.as_millis() as u64), ) { Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), - _ => { - Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) - } + _ => Err(io::Error::new_const( + ErrorKind::Other, + &"Unable to initiate a connection on a socket", + )), } } pub fn set_read_timeout(&self, duration: Option) -> io::Result<()> { abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64)) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) } pub fn set_write_timeout(&self, duration: Option) -> io::Result<()> { @@ -76,26 +81,28 @@ impl TcpStream { *self.0.as_inner(), duration.map(|d| d.as_millis() as u64), ) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) } pub fn read_timeout(&self) -> io::Result> { - let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; + let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| { + io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + })?; Ok(duration.map(|d| Duration::from_millis(d))) } pub fn write_timeout(&self) -> io::Result> { - let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; + let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| { + io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + })?; Ok(duration.map(|d| Duration::from_millis(d))) } pub fn peek(&self, buf: &mut [u8]) -> io::Result { abi::tcpstream::peek(*self.0.as_inner(), buf) - .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) } pub fn read(&self, buffer: &mut [u8]) -> io::Result { @@ -107,7 +114,7 @@ impl TcpStream { for i in ioslice.iter_mut() { let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?; if ret != 0 { size += ret; @@ -130,8 +137,9 @@ impl TcpStream { let mut size: usize = 0; for i in ioslice.iter() { - size += abi::tcpstream::write(*self.0.as_inner(), i) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?; + size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| { + io::Error::new_const(ErrorKind::Other, &"Unable to write on socket") + })?; } Ok(size) @@ -144,13 +152,13 @@ impl TcpStream { pub fn peer_addr(&self) -> io::Result { let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"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(ErrorKind::Other, "peer_addr failed")); + return Err(io::Error::new_const(ErrorKind::Other, &"peer_addr failed")); } }; @@ -158,12 +166,12 @@ impl TcpStream { } pub fn socket_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "socket_addr isn't supported")) + unsupported() } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { abi::tcpstream::shutdown(*self.0.as_inner(), how as i32) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket")) } pub fn duplicate(&self) -> io::Result { @@ -172,31 +180,31 @@ 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(ErrorKind::Other, "set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) } pub fn nodelay(&self) -> io::Result { abi::tcpstream::nodelay(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"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(ErrorKind::Other, "unable to set TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set TTL")) } pub fn ttl(&self) -> io::Result { abi::tcpstream::get_tll(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to get TTL")) } pub fn take_error(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "take_error isn't supported")) + unsupported() } pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode")) } } @@ -222,12 +230,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(ErrorKind::Other, "accept failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"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(ErrorKind::Other, "accept failed")); + return Err(io::Error::new_const(ErrorKind::Other, &"accept failed")); } }; @@ -239,27 +247,27 @@ impl TcpListener { } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn ttl(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn only_v6(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn take_error(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } } @@ -273,127 +281,127 @@ pub struct UdpSocket(abi::Handle); impl UdpSocket { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn peer_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn socket_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn duplicate(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn read_timeout(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn write_timeout(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn broadcast(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn multicast_loop_v4(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn multicast_ttl_v4(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn multicast_loop_v6(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn ttl(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn take_error(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn recv(&self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn peek(&self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn send(&self, _: &[u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + unsupported() } } @@ -403,18 +411,18 @@ impl fmt::Debug for UdpSocket { } } -pub struct LookupHost(Void); +pub struct LookupHost(!); impl LookupHost { pub fn port(&self) -> u16 { - match self.0 {} + self.0 } } impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index 78eabf8f81..81cd68a74e 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -9,7 +9,7 @@ use crate::path::{self, PathBuf}; use crate::str; use crate::sync::Mutex; use crate::sys::hermit::abi; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::sys_common::os_str_bytes::*; use crate::vec; @@ -29,7 +29,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> { unsupported() } -pub struct SplitPaths<'a>(&'a Void); +pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { panic!("unsupported") @@ -38,7 +38,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { impl<'a> Iterator for SplitPaths<'a> { type Item = PathBuf; fn next(&mut self) -> Option { - match *self.0 {} + self.0 } } @@ -110,9 +110,11 @@ pub fn init_environment(env: *const *const i8) { pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Env {} +impl !Sync for Env {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -134,7 +136,7 @@ pub fn env() -> Env { result.push((key.clone(), value.clone())); } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } } diff --git a/library/std/src/sys/hermit/path.rs b/library/std/src/sys/hermit/path.rs deleted file mode 100644 index 840a7ae042..0000000000 --- a/library/std/src/sys/hermit/path.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::ffi::OsStr; -use crate::path::Prefix; - -#[inline] -pub fn is_sep_byte(b: u8) -> bool { - b == b'/' -} - -#[inline] -pub fn is_verbatim_sep(b: u8) -> bool { - b == b'/' -} - -pub fn parse_prefix(_: &OsStr) -> Option> { - None -} - -pub const MAIN_SEP_STR: &str = "/"; -pub const MAIN_SEP: char = '/'; diff --git a/library/std/src/sys/hermit/stack_overflow.rs b/library/std/src/sys/hermit/stack_overflow.rs deleted file mode 100644 index 121fe42011..0000000000 --- a/library/std/src/sys/hermit/stack_overflow.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[inline] -pub unsafe fn init() {} - -#[inline] -pub unsafe fn cleanup() {} diff --git a/library/std/src/sys/hermit/stdio.rs b/library/std/src/sys/hermit/stdio.rs index 82304dd6dc..6bff13ca92 100644 --- a/library/std/src/sys/hermit/stdio.rs +++ b/library/std/src/sys/hermit/stdio.rs @@ -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(io::ErrorKind::Other, "Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"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(io::ErrorKind::Other, "Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"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(io::ErrorKind::Other, "Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"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(io::ErrorKind::Other, "Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) } else { Ok(len as usize) } diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index 7bd71e120d..f35a3a8a80 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -37,7 +37,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(io::ErrorKind::Other, "Unable to create thread!")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Unable to create thread!")) } else { Ok(Thread { tid: tid }) }; diff --git a/library/std/src/sys/hermit/thread_local_key.rs b/library/std/src/sys/hermit/thread_local_key.rs deleted file mode 100644 index bf1b49eb83..0000000000 --- a/library/std/src/sys/hermit/thread_local_key.rs +++ /dev/null @@ -1,26 +0,0 @@ -pub type Key = usize; - -#[inline] -pub unsafe fn create(_dtor: Option) -> Key { - panic!("should not be used on the hermit target"); -} - -#[inline] -pub unsafe fn set(_key: Key, _value: *mut u8) { - panic!("should not be used on the hermit target"); -} - -#[inline] -pub unsafe fn get(_key: Key) -> *mut u8 { - panic!("should not be used on the hermit target"); -} - -#[inline] -pub unsafe fn destroy(_key: Key) { - panic!("should not be used on the hermit target"); -} - -#[inline] -pub fn requires_synchronized_create() -> bool { - panic!("should not be used on the hermit target"); -} diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 1e79a5c3f9..2450a7aac5 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -22,11 +22,10 @@ #![allow(missing_debug_implementations)] +mod common; + cfg_if::cfg_if! { - if #[cfg(target_os = "vxworks")] { - mod vxworks; - pub use self::vxworks::*; - } else if #[cfg(unix)] { + if #[cfg(unix)] { mod unix; pub use self::unix::*; } else if #[cfg(windows)] { @@ -70,8 +69,6 @@ cfg_if::cfg_if! { #[allow(missing_docs)] pub mod unix_ext {} } else { - // On other platforms like Windows document the bare bones of unix - use crate::os::linux as platform; #[path = "unix/ext/mod.rs"] pub mod unix_ext; } diff --git a/library/std/src/sys/sgx/abi/mem.rs b/library/std/src/sys/sgx/abi/mem.rs index 3753fdd353..1e743894a9 100644 --- a/library/std/src/sys/sgx/abi/mem.rs +++ b/library/std/src/sys/sgx/abi/mem.rs @@ -36,10 +36,9 @@ pub fn image_base() -> u64 { let base: u64; unsafe { asm!( - "lea IMAGE_BASE(%rip), {}", + "lea {}, qword ptr [rip + IMAGE_BASE]", lateout(reg) base, - // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9. - options(att_syntax, nostack, preserves_flags, nomem, pure), + options(nostack, preserves_flags, nomem, pure), ) }; base diff --git a/library/std/src/sys/sgx/abi/mod.rs b/library/std/src/sys/sgx/abi/mod.rs index a5e4530347..f9536c4203 100644 --- a/library/std/src/sys/sgx/abi/mod.rs +++ b/library/std/src/sys/sgx/abi/mod.rs @@ -62,10 +62,12 @@ unsafe extern "C" fn tcs_init(secondary: bool) { extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> EntryReturn { // FIXME: how to support TLS in library mode? let tls = Box::new(tls::Tls::new()); - let _tls_guard = unsafe { tls.activate() }; + let tls_guard = unsafe { tls.activate() }; if secondary { - super::thread::Thread::entry(); + let join_notifier = super::thread::Thread::entry(); + drop(tls_guard); + drop(join_notifier); EntryReturn(0, 0) } else { diff --git a/library/std/src/sys/sgx/args.rs b/library/std/src/sys/sgx/args.rs index 2d2e692ec7..ef4176c4ac 100644 --- a/library/std/src/sys/sgx/args.rs +++ b/library/std/src/sys/sgx/args.rs @@ -1,5 +1,6 @@ use super::abi::usercalls::{alloc, raw::ByteBuffer}; use crate::ffi::OsString; +use crate::fmt; use crate::slice; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys::os_str::Buf; @@ -22,8 +23,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { } } -pub unsafe fn cleanup() {} - pub fn args() -> Args { let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() }; if let Some(args) = args { Args(args.iter()) } else { Args([].iter()) } @@ -31,9 +30,9 @@ pub fn args() -> Args { pub struct Args(slice::Iter<'static, OsString>); -impl Args { - pub fn inner_debug(&self) -> &[OsString] { - self.0.as_slice() +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.as_slice().fmt(f) } } diff --git a/library/std/src/sys/sgx/cmath.rs b/library/std/src/sys/sgx/cmath.rs deleted file mode 100644 index b89238f1da..0000000000 --- a/library/std/src/sys/sgx/cmath.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![cfg(not(test))] - -// These symbols are all defined in `compiler-builtins` -extern "C" { - pub fn acos(n: f64) -> f64; - pub fn acosf(n: f32) -> f32; - pub fn asin(n: f64) -> f64; - pub fn asinf(n: f32) -> f32; - pub fn atan(n: f64) -> f64; - pub fn atan2(a: f64, b: f64) -> f64; - pub fn atan2f(a: f32, b: f32) -> f32; - pub fn atanf(n: f32) -> f32; - pub fn cbrt(n: f64) -> f64; - pub fn cbrtf(n: f32) -> f32; - pub fn cosh(n: f64) -> f64; - pub fn coshf(n: f32) -> f32; - pub fn expm1(n: f64) -> f64; - pub fn expm1f(n: f32) -> f32; - pub fn fdim(a: f64, b: f64) -> f64; - pub fn fdimf(a: f32, b: f32) -> f32; - pub fn hypot(x: f64, y: f64) -> f64; - pub fn hypotf(x: f32, y: f32) -> f32; - pub fn log1p(n: f64) -> f64; - pub fn log1pf(n: f32) -> f32; - pub fn sinh(n: f64) -> f64; - pub fn sinhf(n: f32) -> f32; - pub fn tan(n: f64) -> f64; - pub fn tanf(n: f32) -> f32; - pub fn tanh(n: f64) -> f64; - pub fn tanhf(n: f32) -> f32; -} diff --git a/library/std/src/sys/sgx/ext/arch.rs b/library/std/src/sys/sgx/ext/arch.rs index 7488e7e5dc..730db34e73 100644 --- a/library/std/src/sys/sgx/ext/arch.rs +++ b/library/std/src/sys/sgx/ext/arch.rs @@ -36,8 +36,7 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result, u32> inlateout("eax") ENCLU_EGETKEY => error, in("rbx") request, in("rcx") out.as_mut_ptr(), - // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9. - options(att_syntax, nostack), + options(nostack), ); match error { @@ -66,8 +65,7 @@ pub fn ereport( in("rbx") targetinfo, in("rcx") reportdata, in("rdx") report.as_mut_ptr(), - // NOTE(#76738): ATT syntax is used to support LLVM 8 and 9. - options(att_syntax, preserves_flags, nostack), + options(preserves_flags, nostack), ); report.assume_init() diff --git a/library/std/src/sys/sgx/ext/io.rs b/library/std/src/sys/sgx/ext/io.rs index 795a4d190c..7223ade681 100644 --- a/library/std/src/sys/sgx/ext/io.rs +++ b/library/std/src/sys/sgx/ext/io.rs @@ -63,12 +63,14 @@ pub trait TryIntoRawFd: Sized { } impl AsRawFd for net::TcpStream { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() } } impl AsRawFd for net::TcpListener { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() } @@ -87,6 +89,7 @@ pub struct TcpStreamMetadata { impl FromRawFd for net::TcpStream { type Metadata = TcpStreamMetadata; + #[inline] unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpStream { let fd = sys::fd::FileDesc::from_inner(fd); let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); @@ -105,6 +108,7 @@ pub struct TcpListenerMetadata { impl FromRawFd for net::TcpListener { type Metadata = TcpListenerMetadata; + #[inline] unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpListener { let fd = sys::fd::FileDesc::from_inner(fd); let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); @@ -113,6 +117,7 @@ impl FromRawFd for net::TcpListener { } impl TryIntoRawFd for net::TcpStream { + #[inline] fn try_into_raw_fd(self) -> Result { let (socket, peer_addr) = self.into_inner().into_inner(); match socket.try_into_inner() { @@ -126,6 +131,7 @@ impl TryIntoRawFd for net::TcpStream { } impl TryIntoRawFd for net::TcpListener { + #[inline] fn try_into_raw_fd(self) -> Result { match self.into_inner().into_inner().try_into_inner() { Ok(fd) => Ok(fd.into_inner()), diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index b10bed621d..bf3bd57e98 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -13,6 +13,7 @@ mod waitqueue; pub mod alloc; pub mod args; +#[path = "../unix/cmath.rs"] pub mod cmath; pub mod condvar; pub mod env; @@ -32,7 +33,6 @@ pub mod pipe; #[path = "../unsupported/process.rs"] pub mod process; pub mod rwlock; -pub mod stack_overflow; pub mod stdio; pub mod thread; pub mod thread_local_key; @@ -40,8 +40,17 @@ pub mod time; pub use crate::sys_common::os_str_bytes as os_str; -#[cfg(not(test))] -pub fn init() {} +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +pub unsafe fn init(argc: isize, argv: *const *const u8) { + unsafe { + args::init(argc, argv); + } +} + +// 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() {} /// This function is used to implement functionality that simply doesn't exist. /// Programs relying on this functionality will need to deal with the error. @@ -50,7 +59,7 @@ pub fn unsupported() -> crate::io::Result { } pub fn unsupported_err() -> crate::io::Error { - crate::io::Error::new(ErrorKind::Other, "operation not supported on SGX yet") + crate::io::Error::new_const(ErrorKind::Unsupported, &"operation not supported on SGX yet") } /// This function is used to implement various functions that doesn't exist, @@ -61,9 +70,9 @@ pub fn unsupported_err() -> crate::io::Error { pub fn sgx_ineffective(v: T) -> crate::io::Result { static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false); if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) { - Err(crate::io::Error::new( + Err(crate::io::Error::new_const( ErrorKind::Other, - "operation can't be trusted to have any effect on SGX", + &"operation can't be trusted to have any effect on SGX", )) } else { Ok(v) @@ -115,11 +124,6 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { } } -// This enum is used as the storage for a bunch of types which can't actually -// exist. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub enum Void {} - pub unsafe fn strlen(mut s: *const c_char) -> usize { let mut n = 0; while unsafe { *s } != 0 { diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs index 3dd8267921..5ccedece0f 100644 --- a/library/std/src/sys/sgx/net.rs +++ b/library/std/src/sys/sgx/net.rs @@ -5,7 +5,7 @@ use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::sync::Arc; use crate::sys::fd::FileDesc; -use crate::sys::{sgx_ineffective, unsupported, AsInner, FromInner, IntoInner, TryIntoInner, Void}; +use crate::sys::{sgx_ineffective, unsupported, AsInner, FromInner, IntoInner, TryIntoInner}; use crate::time::Duration; use super::abi::usercalls; @@ -97,9 +97,9 @@ impl TcpStream { pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result { if dur == Duration::default() { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } Self::connect(Ok(addr)) // FIXME: ignoring timeout @@ -108,9 +108,9 @@ impl TcpStream { pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { match dur { Some(dur) if dur == Duration::default() => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } _ => sgx_ineffective(()), @@ -120,9 +120,9 @@ impl TcpStream { pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { match dur { Some(dur) if dur == Duration::default() => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } _ => sgx_ineffective(()), @@ -310,7 +310,7 @@ impl FromInner for TcpListener { } } -pub struct UdpSocket(Void); +pub struct UdpSocket(!); impl UdpSocket { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { @@ -318,129 +318,129 @@ impl UdpSocket { } pub fn peer_addr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + self.0 } pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + self.0 } pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { - match self.0 {} + self.0 } pub fn duplicate(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + self.0 } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + self.0 } pub fn read_timeout(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn write_timeout(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn broadcast(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn multicast_loop_v4(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn multicast_ttl_v4(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn multicast_loop_v6(&self) -> io::Result { - match self.0 {} + self.0 } pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + self.0 } pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + self.0 } pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn ttl(&self) -> io::Result { - match self.0 {} + self.0 } pub fn take_error(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn recv(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn peek(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn send(&self, _: &[u8]) -> io::Result { - match self.0 {} + self.0 } pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - match self.0 {} + self.0 } } impl fmt::Debug for UdpSocket { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } @@ -462,7 +462,7 @@ impl fmt::Display for NonIpSockAddr { } } -pub struct LookupHost(Void); +pub struct LookupHost(!); impl LookupHost { fn new(host: String) -> io::Result { @@ -470,14 +470,14 @@ impl LookupHost { } pub fn port(&self) -> u16 { - match self.0 {} + self.0 } } impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/sgx/os.rs b/library/std/src/sys/sgx/os.rs index 56fc84b4a3..144248d60c 100644 --- a/library/std/src/sys/sgx/os.rs +++ b/library/std/src/sys/sgx/os.rs @@ -5,12 +5,13 @@ use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::fmt; use crate::io; +use crate::marker::PhantomData; use crate::path::{self, PathBuf}; use crate::str; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::Mutex; use crate::sync::Once; -use crate::sys::{decode_error_kind, sgx_ineffective, unsupported, Void}; +use crate::sys::{decode_error_kind, sgx_ineffective, unsupported}; use crate::vec; pub fn errno() -> i32 { @@ -35,7 +36,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> { sgx_ineffective(()) } -pub struct SplitPaths<'a>(&'a Void); +pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { panic!("unsupported") @@ -44,7 +45,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { impl<'a> Iterator for SplitPaths<'a> { type Item = PathBuf; fn next(&mut self) -> Option { - match *self.0 {} + self.0 } } diff --git a/library/std/src/sys/sgx/stack_overflow.rs b/library/std/src/sys/sgx/stack_overflow.rs deleted file mode 100644 index b96652a833..0000000000 --- a/library/std/src/sys/sgx/stack_overflow.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[cfg_attr(test, allow(dead_code))] -pub unsafe fn init() {} - -pub unsafe fn cleanup() {} diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index 55ef460cc9..67e2e8b59d 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -9,26 +9,37 @@ pub struct Thread(task_queue::JoinHandle); pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; +pub use self::task_queue::JoinNotifier; + mod task_queue { - use crate::sync::mpsc; + use super::wait_notify; use crate::sync::{Mutex, MutexGuard, Once}; - pub type JoinHandle = mpsc::Receiver<()>; + pub type JoinHandle = wait_notify::Waiter; + + pub struct JoinNotifier(Option); + + impl Drop for JoinNotifier { + fn drop(&mut self) { + self.0.take().unwrap().notify(); + } + } pub(super) struct Task { p: Box, - done: mpsc::Sender<()>, + done: JoinNotifier, } impl Task { pub(super) fn new(p: Box) -> (Task, JoinHandle) { - let (done, recv) = mpsc::channel(); + let (done, recv) = wait_notify::new(); + let done = JoinNotifier(Some(done)); (Task { p, done }, recv) } - pub(super) fn run(self) { + pub(super) fn run(self) -> JoinNotifier { (self.p)(); - let _ = self.done.send(()); + self.done } } @@ -47,6 +58,48 @@ mod task_queue { } } +/// This module provides a synchronization primitive that does not use thread +/// local variables. This is needed for signaling that a thread has finished +/// execution. The signal is sent once all TLS destructors have finished at +/// which point no new thread locals should be created. +pub mod wait_notify { + use super::super::waitqueue::{SpinMutex, WaitQueue, WaitVariable}; + use crate::sync::Arc; + + pub struct Notifier(Arc>>); + + impl Notifier { + /// Notify the waiter. The waiter is either notified right away (if + /// currently blocked in `Waiter::wait()`) or later when it calls the + /// `Waiter::wait()` method. + pub fn notify(self) { + let mut guard = self.0.lock(); + *guard.lock_var_mut() = true; + let _ = WaitQueue::notify_one(guard); + } + } + + pub struct Waiter(Arc>>); + + impl Waiter { + /// Wait for a notification. If `Notifier::notify()` has already been + /// called, this will return immediately, otherwise the current thread + /// is blocked until notified. + pub fn wait(self) { + let guard = self.0.lock(); + if *guard.lock_var() { + return; + } + WaitQueue::wait(guard, || {}); + } + } + + pub fn new() -> (Notifier, Waiter) { + let inner = Arc::new(SpinMutex::new(WaitVariable::new(false))); + (Notifier(inner.clone()), Waiter(inner)) + } +} + impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(_stack: usize, p: Box) -> io::Result { @@ -57,7 +110,7 @@ impl Thread { Ok(Thread(handle)) } - pub(super) fn entry() { + pub(super) fn entry() -> JoinNotifier { let mut pending_tasks = task_queue::lock(); let task = rtunwrap!(Some, pending_tasks.pop()); drop(pending_tasks); // make sure to not hold the task queue lock longer than necessary @@ -78,7 +131,7 @@ impl Thread { } pub fn join(self) { - let _ = self.0.recv(); + self.0.wait(); } } diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs index 964abe8b8c..1b71905aa0 100644 --- a/library/std/src/sys/unix/alloc.rs +++ b/library/std/src/sys/unix/alloc.rs @@ -1,6 +1,6 @@ use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; -use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN}; +use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/unix/android.rs b/library/std/src/sys/unix/android.rs index ea05ee3d7c..cf6aa31b7c 100644 --- a/library/std/src/sys/unix/android.rs +++ b/library/std/src/sys/unix/android.rs @@ -96,7 +96,7 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> { Some(f) => cvt_r(|| f(fd, size as i64)).map(drop), None => { if size > i32::MAX as u64 { - Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot truncate >2GB")) + Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot truncate >2GB")) } else { cvt_r(|| ftruncate(fd, size as i32)).map(drop) } @@ -123,7 +123,7 @@ pub unsafe fn cvt_pread64( if let Ok(o) = offset.try_into() { cvt(pread(fd, buf, count, o)) } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot pread >2GB")) + Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pread >2GB")) } }) } @@ -141,7 +141,7 @@ pub unsafe fn cvt_pwrite64( if let Ok(o) = offset.try_into() { cvt(pwrite(fd, buf, count, o)) } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot pwrite >2GB")) + Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pwrite >2GB")) } }) } diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index 6967647249..fc423e393d 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -6,7 +6,7 @@ #![allow(dead_code)] // runtime init functions not used during testing use crate::ffi::OsString; -use crate::marker::PhantomData; +use crate::fmt; use crate::vec; /// One-time global initialization. @@ -26,12 +26,14 @@ pub fn args() -> Args { pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } -impl Args { - pub fn inner_debug(&self) -> &[OsString] { - self.iter.as_slice() +impl !Send for Args {} +impl !Sync for Args {} + +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) } } @@ -76,7 +78,6 @@ impl DoubleEndedIterator for Args { mod imp { use super::Args; use crate::ffi::{CStr, OsString}; - use crate::marker::PhantomData; use crate::os::unix::prelude::*; use crate::ptr; use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering}; @@ -133,7 +134,7 @@ mod imp { } pub fn args() -> Args { - Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: clone().into_iter() } } fn clone() -> Vec { @@ -155,7 +156,6 @@ mod imp { mod imp { use super::Args; use crate::ffi::CStr; - use crate::marker::PhantomData; pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} @@ -180,7 +180,7 @@ mod imp { }) .collect::>() }; - Args { iter: vec.into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: vec.into_iter() } } // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs @@ -247,6 +247,6 @@ mod imp { } } - Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: res.into_iter() } } } diff --git a/library/std/src/sys/unix/cmath.rs b/library/std/src/sys/unix/cmath.rs index f327b69fc7..2bf80d7a4c 100644 --- a/library/std/src/sys/unix/cmath.rs +++ b/library/std/src/sys/unix/cmath.rs @@ -1,32 +1,33 @@ #![cfg(not(test))] -use libc::{c_double, c_float}; +// These symbols are all defined by `libm`, +// or by `compiler-builtins` on unsupported platforms. extern "C" { - pub fn acos(n: c_double) -> c_double; - pub fn acosf(n: c_float) -> c_float; - pub fn asin(n: c_double) -> c_double; - pub fn asinf(n: c_float) -> c_float; - pub fn atan(n: c_double) -> c_double; - pub fn atan2(a: c_double, b: c_double) -> c_double; - pub fn atan2f(a: c_float, b: c_float) -> c_float; - pub fn atanf(n: c_float) -> c_float; - pub fn cbrt(n: c_double) -> c_double; - pub fn cbrtf(n: c_float) -> c_float; - pub fn cosh(n: c_double) -> c_double; - pub fn coshf(n: c_float) -> c_float; - pub fn expm1(n: c_double) -> c_double; - pub fn expm1f(n: c_float) -> c_float; - pub fn fdim(a: c_double, b: c_double) -> c_double; - pub fn fdimf(a: c_float, b: c_float) -> c_float; - pub fn hypot(x: c_double, y: c_double) -> c_double; - pub fn hypotf(x: c_float, y: c_float) -> c_float; - pub fn log1p(n: c_double) -> c_double; - pub fn log1pf(n: c_float) -> c_float; - pub fn sinh(n: c_double) -> c_double; - pub fn sinhf(n: c_float) -> c_float; - pub fn tan(n: c_double) -> c_double; - pub fn tanf(n: c_float) -> c_float; - pub fn tanh(n: c_double) -> c_double; - pub fn tanhf(n: c_float) -> c_float; + pub fn acos(n: f64) -> f64; + pub fn acosf(n: f32) -> f32; + pub fn asin(n: f64) -> f64; + pub fn asinf(n: f32) -> f32; + pub fn atan(n: f64) -> f64; + pub fn atan2(a: f64, b: f64) -> f64; + pub fn atan2f(a: f32, b: f32) -> f32; + pub fn atanf(n: f32) -> f32; + pub fn cbrt(n: f64) -> f64; + pub fn cbrtf(n: f32) -> f32; + pub fn cosh(n: f64) -> f64; + pub fn coshf(n: f32) -> f32; + pub fn expm1(n: f64) -> f64; + pub fn expm1f(n: f32) -> f32; + pub fn fdim(a: f64, b: f64) -> f64; + pub fn fdimf(a: f32, b: f32) -> f32; + pub fn hypot(x: f64, y: f64) -> f64; + pub fn hypotf(x: f32, y: f32) -> f32; + pub fn log1p(n: f64) -> f64; + pub fn log1pf(n: f32) -> f32; + pub fn sinh(n: f64) -> f64; + pub fn sinhf(n: f32) -> f32; + pub fn tan(n: f64) -> f64; + pub fn tanf(n: f32) -> f32; + pub fn tanh(n: f64) -> f64; + pub fn tanhf(n: f32) -> f32; } diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index 7f5e9b04db..3a88dc083b 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -173,3 +173,14 @@ pub mod os { pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } + +#[cfg(target_os = "vxworks")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "vxworks"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs index ba75b9bac8..9cf51be283 100644 --- a/library/std/src/sys/unix/ext/fs.rs +++ b/library/std/src/sys/unix/ext/fs.rs @@ -2,11 +2,11 @@ #![stable(feature = "rust1", since = "1.0.0")] +use super::platform::fs::MetadataExt as _; use crate::fs::{self, OpenOptions, Permissions}; use crate::io; use crate::path::Path; use crate::sys; -use crate::sys::platform::fs::MetadataExt as UnixMetadataExt; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; // Used for `File::read` on intra-doc links #[allow(unused_imports)] @@ -109,7 +109,7 @@ pub trait FileExt { } } if !buf.is_empty() { - Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer")) + Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) } else { Ok(()) } @@ -191,9 +191,9 @@ pub trait FileExt { while !buf.is_empty() { match self.write_at(buf, offset) { Ok(0) => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::WriteZero, - "failed to write whole buffer", + &"failed to write whole buffer", )); } Ok(n) => { @@ -884,3 +884,29 @@ impl DirBuilderExt for fs::DirBuilder { self } } + +/// Change the root directory of the current process to the specified path. +/// +/// This typically requires privileges, such as root or a specific capability. +/// +/// This does not change the current working directory; you should call +/// [`std::env::set_current_dir`][`crate::env::set_current_dir`] afterwards. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chroot)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::chroot("/sandbox")?; +/// std::env::set_current_dir("/")?; +/// // continue working in sandbox +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chroot", issue = "84715")] +#[cfg(not(target_os = "fuchsia"))] +pub fn chroot>(dir: P) -> io::Result<()> { + sys::fs::chroot(dir.as_ref()) +} diff --git a/library/std/src/sys/unix/ext/io.rs b/library/std/src/sys/unix/ext/io.rs index ef3c689bd3..07c30bfa9e 100644 --- a/library/std/src/sys/unix/ext/io.rs +++ b/library/std/src/sys/unix/ext/io.rs @@ -104,18 +104,21 @@ pub trait IntoRawFd { #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl AsRawFd for RawFd { + #[inline] fn as_raw_fd(&self) -> RawFd { *self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl IntoRawFd for RawFd { + #[inline] fn into_raw_fd(self) -> RawFd { self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl FromRawFd for RawFd { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> RawFd { fd } @@ -123,18 +126,21 @@ impl FromRawFd for RawFd { #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for fs::File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for fs::File { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> fs::File { fs::File::from_inner(sys::fs::File::from_inner(fd)) } } #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for fs::File { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } @@ -142,6 +148,7 @@ impl IntoRawFd for fs::File { #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawFd for io::Stdin { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO } @@ -149,6 +156,7 @@ impl AsRawFd for io::Stdin { #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawFd for io::Stdout { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO } @@ -156,6 +164,7 @@ impl AsRawFd for io::Stdout { #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawFd for io::Stderr { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } @@ -163,6 +172,7 @@ impl AsRawFd for io::Stderr { #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawFd for io::StdinLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO } @@ -170,6 +180,7 @@ impl<'a> AsRawFd for io::StdinLock<'a> { #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawFd for io::StdoutLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO } @@ -177,6 +188,7 @@ impl<'a> AsRawFd for io::StdoutLock<'a> { #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawFd for io::StderrLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } diff --git a/library/std/src/sys/unix/ext/mod.rs b/library/std/src/sys/unix/ext/mod.rs index f435468809..735bf35a3c 100644 --- a/library/std/src/sys/unix/ext/mod.rs +++ b/library/std/src/sys/unix/ext/mod.rs @@ -29,6 +29,44 @@ #![doc(cfg(unix))] #![allow(missing_docs)] +cfg_if::cfg_if! { + if #[cfg(doc)] { + // Use linux as the default platform when documenting on other platforms like Windows + use crate::os::linux as platform; + } else { + #[cfg(target_os = "android")] + use crate::os::android as platform; + #[cfg(target_os = "dragonfly")] + use crate::os::dragonfly as platform; + #[cfg(target_os = "emscripten")] + use crate::os::emscripten as platform; + #[cfg(target_os = "freebsd")] + use crate::os::freebsd as platform; + #[cfg(target_os = "fuchsia")] + use crate::os::fuchsia as platform; + #[cfg(target_os = "haiku")] + use crate::os::haiku as platform; + #[cfg(target_os = "illumos")] + use crate::os::illumos as platform; + #[cfg(target_os = "ios")] + use crate::os::ios as platform; + #[cfg(any(target_os = "linux", target_os = "l4re"))] + use crate::os::linux as platform; + #[cfg(target_os = "macos")] + use crate::os::macos as platform; + #[cfg(target_os = "netbsd")] + use crate::os::netbsd as platform; + #[cfg(target_os = "openbsd")] + use crate::os::openbsd as platform; + #[cfg(target_os = "redox")] + use crate::os::redox as platform; + #[cfg(target_os = "solaris")] + use crate::os::solaris as platform; + #[cfg(target_os = "vxworks")] + use crate::os::vxworks as platform; + } +} + pub mod ffi; pub mod fs; pub mod io; diff --git a/library/std/src/sys/unix/ext/net/addr.rs b/library/std/src/sys/unix/ext/net/addr.rs index 1f9036242e..459f3590e6 100644 --- a/library/std/src/sys/unix/ext/net/addr.rs +++ b/library/std/src/sys/unix/ext/net/addr.rs @@ -2,7 +2,7 @@ use crate::ffi::OsStr; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; use crate::sys::cvt; -use crate::{ascii, fmt, io, mem}; +use crate::{ascii, fmt, io, iter, mem}; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? #[cfg(not(unix))] @@ -29,19 +29,19 @@ pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, let bytes = path.as_os_str().as_bytes(); if bytes.contains(&0) { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "paths may not contain interior null bytes", + &"paths may not contain interior null bytes", )); } if bytes.len() >= addr.sun_path.len() { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "path must be shorter than SUN_LEN", + &"path must be shorter than SUN_LEN", )); } - for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) { + for (dst, src) in iter::zip(&mut addr.sun_path, bytes) { *dst = *src as libc::c_char; } // null byte for pathname addresses is already there because we zeroed the @@ -118,9 +118,9 @@ impl SocketAddr { // linux returns zero bytes of address len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "file descriptor did not correspond to a Unix socket", + &"file descriptor did not correspond to a Unix socket", )); } diff --git a/library/std/src/sys/unix/ext/net/ancillary.rs b/library/std/src/sys/unix/ext/net/ancillary.rs index 33d6a39af0..011ae643f8 100644 --- a/library/std/src/sys/unix/ext/net/ancillary.rs +++ b/library/std/src/sys/unix/ext/net/ancillary.rs @@ -5,9 +5,7 @@ use crate::marker::PhantomData; use crate::mem::{size_of, zeroed}; use crate::os::unix::io::RawFd; use crate::path::Path; -#[cfg(target_os = "android")] -use crate::ptr::eq; -use crate::ptr::read_unaligned; +use crate::ptr::{eq, read_unaligned}; use crate::slice::from_raw_parts; use crate::sys::net::Socket; @@ -30,12 +28,10 @@ pub(super) fn recv_vectored_with_ancillary_from( ) -> io::Result<(usize, bool, io::Result)> { unsafe { let mut msg_name: libc::sockaddr_un = zeroed(); - let mut msg: libc::msghdr = zeroed(); msg.msg_name = &mut msg_name as *mut _ as *mut _; msg.msg_namelen = size_of::() as libc::socklen_t; msg.msg_iov = bufs.as_mut_ptr().cast(); - msg.msg_control = ancillary.buffer.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; @@ -45,6 +41,7 @@ pub(super) fn recv_vectored_with_ancillary_from( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -52,6 +49,10 @@ pub(super) fn recv_vectored_with_ancillary_from( msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t; } } + // 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(); + } let count = socket.recv_msg(&mut msg)?; @@ -79,7 +80,6 @@ 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 _; - msg.msg_control = ancillary.buffer.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; @@ -89,6 +89,7 @@ pub(super) fn send_vectored_with_ancillary_to( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -96,6 +97,10 @@ pub(super) fn send_vectored_with_ancillary_to( msg.msg_controllen = ancillary.length as libc::socklen_t; } } + // 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(); + } ancillary.truncated = false; @@ -147,6 +152,7 @@ fn add_to_ancillary_data( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -159,14 +165,12 @@ fn add_to_ancillary_data( while !cmsg.is_null() { previous_cmsg = cmsg; cmsg = libc::CMSG_NXTHDR(&msg, cmsg); - cfg_if::cfg_if! { - // Android return the same pointer if it is the last cmsg. - // Therefore, check it if the previous pointer is the same as the current one. - if #[cfg(target_os = "android")] { - if cmsg == previous_cmsg { - break; - } - } + + // Most operating systems, but not Linux or emscripten, return the previous pointer + // when its length is zero. Therefore, check if the previous pointer is the same as + // the current one. + if eq(cmsg, previous_cmsg) { + break; } } @@ -184,6 +188,7 @@ fn add_to_ancillary_data( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -371,6 +376,7 @@ impl<'a> AncillaryData<'a> { target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -421,6 +427,7 @@ impl<'a> Iterator for Messages<'a> { target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -435,15 +442,13 @@ impl<'a> Iterator for Messages<'a> { }; let cmsg = cmsg.as_ref()?; - cfg_if::cfg_if! { - // Android return the same pointer if it is the last cmsg. - // Therefore, check it if the previous pointer is the same as the current one. - if #[cfg(target_os = "android")] { - if let Some(current) = self.current { - if eq(current, cmsg) { - return None; - } - } + + // Most operating systems, but not Linux or emscripten, return the previous pointer + // when its length is zero. Therefore, check if the previous pointer is the same as + // the current one. + if let Some(current) = self.current { + if eq(current, cmsg) { + return None; } } @@ -514,6 +519,12 @@ impl<'a> SocketAncillary<'a> { self.buffer.len() } + /// Returns `true` if the ancillary data is empty. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn is_empty(&self) -> bool { + self.length == 0 + } + /// Returns the number of used bytes. #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn len(&self) -> usize { diff --git a/library/std/src/sys/unix/ext/net/datagram.rs b/library/std/src/sys/unix/ext/net/datagram.rs index a8c13fbb87..9e39f70f68 100644 --- a/library/std/src/sys/unix/ext/net/datagram.rs +++ b/library/std/src/sys/unix/ext/net/datagram.rs @@ -879,6 +879,7 @@ impl UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixDatagram { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } @@ -886,6 +887,7 @@ impl AsRawFd for UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixDatagram { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { UnixDatagram(Socket::from_inner(fd)) } @@ -893,6 +895,7 @@ impl FromRawFd for UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixDatagram { + #[inline] fn into_raw_fd(self) -> RawFd { self.0.into_inner() } diff --git a/library/std/src/sys/unix/ext/net/listener.rs b/library/std/src/sys/unix/ext/net/listener.rs index 9803c6e274..bdd08fe838 100644 --- a/library/std/src/sys/unix/ext/net/listener.rs +++ b/library/std/src/sys/unix/ext/net/listener.rs @@ -240,6 +240,7 @@ impl UnixListener { #[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixListener { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } @@ -247,6 +248,7 @@ impl AsRawFd for UnixListener { #[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixListener { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener(Socket::from_inner(fd)) } @@ -254,6 +256,7 @@ impl FromRawFd for UnixListener { #[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixListener { + #[inline] fn into_raw_fd(self) -> RawFd { self.0.into_inner() } diff --git a/library/std/src/sys/unix/ext/net/raw_fd.rs b/library/std/src/sys/unix/ext/net/raw_fd.rs index c42fee4c73..b3f1284410 100644 --- a/library/std/src/sys/unix/ext/net/raw_fd.rs +++ b/library/std/src/sys/unix/ext/net/raw_fd.rs @@ -6,6 +6,7 @@ macro_rules! impl_as_raw_fd { ($($t:ident)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::$t { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } @@ -18,6 +19,7 @@ macro_rules! impl_from_raw_fd { ($($t:ident)*) => {$( #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::$t { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::$t { let socket = sys::net::Socket::from_inner(fd); net::$t::from_inner(sys_common::net::$t::from_inner(socket)) @@ -31,6 +33,7 @@ macro_rules! impl_into_raw_fd { ($($t:ident)*) => {$( #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for net::$t { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_socket().into_inner() } diff --git a/library/std/src/sys/unix/ext/net/stream.rs b/library/std/src/sys/unix/ext/net/stream.rs index fc08edacb8..a6f6e09130 100644 --- a/library/std/src/sys/unix/ext/net/stream.rs +++ b/library/std/src/sys/unix/ext/net/stream.rs @@ -654,6 +654,7 @@ impl<'a> io::Write for &'a UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixStream { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } @@ -661,6 +662,7 @@ impl AsRawFd for UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixStream { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream(Socket::from_inner(fd)) } @@ -668,6 +670,7 @@ impl FromRawFd for UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixStream { + #[inline] fn into_raw_fd(self) -> RawFd { self.0.into_inner() } diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 1276edc6af..355855bcd1 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -227,14 +227,14 @@ pub trait ExitStatusExt: Sealed { /// If the process was stopped by a signal, returns that signal. /// /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`. This is only possible if the status came from - /// a `wait` system call which was passed `WUNTRACED`, was then converted into an `ExitStatus`. + /// a `wait` system call which was passed `WUNTRACED`, and was then converted into an `ExitStatus`. #[unstable(feature = "unix_process_wait_more", issue = "80695")] fn stopped_signal(&self) -> Option; /// Whether the process was continued from a stopped status. /// /// Ie, `WIFCONTINUED`. This is only possible if the status came from a `wait` system call - /// which was passed `WCONTINUED`, was then converted into an `ExitStatus`. + /// which was passed `WCONTINUED`, and was then converted into an `ExitStatus`. #[unstable(feature = "unix_process_wait_more", issue = "80695")] fn continued(&self) -> bool; @@ -274,6 +274,7 @@ impl ExitStatusExt for process::ExitStatus { #[stable(feature = "process_extensions", since = "1.2.0")] impl FromRawFd for process::Stdio { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio { let fd = sys::fd::FileDesc::new(fd); let io = sys::process::Stdio::Fd(fd); @@ -283,6 +284,7 @@ impl FromRawFd for process::Stdio { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawFd for process::ChildStdin { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } @@ -290,6 +292,7 @@ impl AsRawFd for process::ChildStdin { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawFd for process::ChildStdout { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } @@ -297,6 +300,7 @@ impl AsRawFd for process::ChildStdout { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawFd for process::ChildStderr { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } @@ -304,6 +308,7 @@ impl AsRawFd for process::ChildStderr { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for process::ChildStdin { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } @@ -311,6 +316,7 @@ impl IntoRawFd for process::ChildStdin { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for process::ChildStdout { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } @@ -318,6 +324,7 @@ impl IntoRawFd for process::ChildStdout { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for process::ChildStderr { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } diff --git a/library/std/src/sys/unix/ext/raw.rs b/library/std/src/sys/unix/ext/raw.rs index 3199a0bff0..c292955cb4 100644 --- a/library/std/src/sys/unix/ext/raw.rs +++ b/library/std/src/sys/unix/ext/raw.rs @@ -24,10 +24,10 @@ pub type pid_t = i32; #[doc(inline)] #[stable(feature = "pthread_t", since = "1.8.0")] -pub use crate::sys::platform::raw::pthread_t; +pub use super::platform::raw::pthread_t; #[doc(inline)] #[stable(feature = "raw_ext", since = "1.1.0")] -pub use crate::sys::platform::raw::{blkcnt_t, time_t}; +pub use super::platform::raw::{blkcnt_t, time_t}; #[doc(inline)] #[stable(feature = "raw_ext", since = "1.1.0")] -pub use crate::sys::platform::raw::{blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t}; +pub use super::platform::raw::{blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t}; diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index d1b0ad9e5f..45bae25a0c 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::path::{Path, PathBuf}; use crate::ptr; @@ -357,17 +357,17 @@ impl FileAttr { tv_nsec: ext.stx_btime.tv_nsec as _, })) } else { - Err(io::Error::new( + Err(io::Error::new_const( io::ErrorKind::Other, - "creation time is not available for the filesystem", + &"creation time is not available for the filesystem", )) }; } } - Err(io::Error::new( - io::ErrorKind::Other, - "creation time is not available on this platform \ + Err(io::Error::new_const( + io::ErrorKind::Unsupported, + &"creation time is not available on this platform \ currently", )) } @@ -1152,14 +1152,12 @@ pub fn canonicalize(p: &Path) -> io::Result { fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::fs::File; + use crate::sys_common::fs::NOT_FILE_ERROR; let reader = File::open(from)?; let metadata = reader.metadata()?; if !metadata.is_file() { - return Err(Error::new( - ErrorKind::InvalidInput, - "the source path is not an existing regular file", - )); + return Err(NOT_FILE_ERROR); } Ok((reader, metadata)) } @@ -1330,3 +1328,10 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { })?; Ok(bytes_copied as u64) } + +#[cfg(not(target_os = "fuchsia"))] +pub fn chroot(dir: &Path) -> io::Result<()> { + let dir = cstr(dir)?; + cvt(unsafe { libc::chroot(dir.as_ptr()) })?; + Ok(()) +} diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs index a291238710..3cf637c822 100644 --- a/library/std/src/sys/unix/l4re.rs +++ b/library/std/src/sys/unix/l4re.rs @@ -1,6 +1,9 @@ macro_rules! unimpl { () => { - return Err(io::Error::new(io::ErrorKind::Other, "No networking available on L4Re.")); + return Err(io::Error::new_const( + io::ErrorKind::Unsupported, + &"No networking available on L4Re.", + )); }; } diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index f8a5ee8996..6c4fbaf273 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -2,38 +2,6 @@ use crate::io::ErrorKind; -#[cfg(any(doc, target_os = "linux"))] -pub use crate::os::linux as platform; - -#[cfg(all(not(doc), target_os = "android"))] -pub use crate::os::android as platform; -#[cfg(all(not(doc), target_os = "dragonfly"))] -pub use crate::os::dragonfly as platform; -#[cfg(all(not(doc), target_os = "emscripten"))] -pub use crate::os::emscripten as platform; -#[cfg(all(not(doc), target_os = "freebsd"))] -pub use crate::os::freebsd as platform; -#[cfg(all(not(doc), target_os = "fuchsia"))] -pub use crate::os::fuchsia as platform; -#[cfg(all(not(doc), target_os = "haiku"))] -pub use crate::os::haiku as platform; -#[cfg(all(not(doc), target_os = "illumos"))] -pub use crate::os::illumos as platform; -#[cfg(all(not(doc), target_os = "ios"))] -pub use crate::os::ios as platform; -#[cfg(all(not(doc), target_os = "l4re"))] -pub use crate::os::linux as platform; -#[cfg(all(not(doc), target_os = "macos"))] -pub use crate::os::macos as platform; -#[cfg(all(not(doc), target_os = "netbsd"))] -pub use crate::os::netbsd as platform; -#[cfg(all(not(doc), target_os = "openbsd"))] -pub use crate::os::openbsd as platform; -#[cfg(all(not(doc), target_os = "redox"))] -pub use crate::os::redox as platform; -#[cfg(all(not(doc), target_os = "solaris"))] -pub use crate::os::solaris as platform; - pub use self::rand::hashmap_random_keys; pub use libc::strlen; @@ -43,6 +11,7 @@ pub mod weak; pub mod alloc; pub mod android; pub mod args; +#[path = "../unix/cmath.rs"] pub mod cmath; pub mod condvar; pub mod env; @@ -76,14 +45,13 @@ pub mod time; pub use crate::sys_common::os_str_bytes as os_str; -#[cfg(not(test))] -pub fn init() { +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +pub unsafe fn init(argc: isize, argv: *const *const u8) { // The standard streams might be closed on application startup. To prevent // std::io::{stdin, stdout,stderr} objects from using other unrelated file // resources opened later, we reopen standards streams when they are closed. - unsafe { - sanitize_standard_fds(); - } + sanitize_standard_fds(); // By default, some platforms will send a *signal* when an EPIPE error // would otherwise be delivered. This runtime doesn't install a SIGPIPE @@ -92,25 +60,24 @@ pub fn init() { // // Hence, we set SIGPIPE to ignore when the program starts up in order // to prevent this problem. - unsafe { - reset_sigpipe(); - } + reset_sigpipe(); - cfg_if::cfg_if! { - if #[cfg(miri)] { - // The standard fds are always available in Miri. - unsafe fn sanitize_standard_fds() {} - } else if #[cfg(not(any( - target_os = "emscripten", - target_os = "fuchsia", - // The poll on Darwin doesn't set POLLNVAL for closed fds. - target_os = "macos", - target_os = "ios", - target_os = "redox", - )))] { - // In the case when all file descriptors are open, the poll has been - // observed to perform better than fcntl (on GNU/Linux). - unsafe fn sanitize_standard_fds() { + stack_overflow::init(); + args::init(argc, argv); + + unsafe fn sanitize_standard_fds() { + #[cfg(not(miri))] + // The standard fds are always available in Miri. + cfg_if::cfg_if! { + if #[cfg(not(any( + target_os = "emscripten", + target_os = "fuchsia", + target_os = "vxworks", + // The poll on Darwin doesn't set POLLNVAL for closed fds. + target_os = "macos", + target_os = "ios", + target_os = "redox", + )))] { use crate::sys::os::errno; let pfds: &mut [_] = &mut [ libc::pollfd { fd: 0, events: 0, revents: 0 }, @@ -135,9 +102,7 @@ pub fn init() { libc::abort(); } } - } - } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] { - unsafe fn sanitize_standard_fds() { + } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] { use crate::sys::os::errno; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { @@ -147,17 +112,20 @@ pub fn init() { } } } - } else { - unsafe fn sanitize_standard_fds() {} } } - #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))] unsafe fn reset_sigpipe() { + #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))] assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); } - #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))] - unsafe fn reset_sigpipe() {} +} + +// 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(); } #[cfg(target_os = "android")] @@ -180,6 +148,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::EINVAL => ErrorKind::InvalidInput, libc::ETIMEDOUT => ErrorKind::TimedOut, libc::EEXIST => ErrorKind::AlreadyExists, + libc::ENOSYS => ErrorKind::Unsupported, // These two constants can have the same value on some systems, // but different values on others, so we can't use a match diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 587ffe1598..e6b61062d1 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -139,9 +139,9 @@ impl Socket { let mut pollfd = libc::pollfd { fd: self.0.raw(), events: libc::POLLOUT, revents: 0 }; if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } @@ -150,7 +150,7 @@ impl Socket { loop { let elapsed = start.elapsed(); if elapsed >= timeout { - return Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")); + return Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")); } let timeout = timeout - elapsed; @@ -177,7 +177,10 @@ impl Socket { // for POLLHUP rather than read readiness if pollfd.revents & libc::POLLHUP != 0 { let e = self.take_error()?.unwrap_or_else(|| { - io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP") + io::Error::new_const( + io::ErrorKind::Other, + &"no error set after POLLHUP", + ) }); return Err(e); } @@ -318,9 +321,9 @@ impl Socket { let timeout = match dur { Some(dur) => { if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 1d1118aa69..984c08c2ad 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -12,7 +12,6 @@ use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; use crate::io; use crate::iter; -use crate::marker::PhantomData; use crate::mem; use crate::memchr; use crate::path::{self, PathBuf}; @@ -21,8 +20,8 @@ use crate::slice; use crate::str; use crate::sys::cvt; use crate::sys::fd; +use crate::sys::rwlock::{RWLockReadGuard, StaticRWLock}; use crate::sys_common::mutex::{StaticMutex, StaticMutexGuard}; -use crate::sys_common::rwlock::{RWLockReadGuard, StaticRWLock}; use crate::vec; use libc::{c_char, c_int, c_void}; @@ -85,11 +84,6 @@ pub fn errno() -> i32 { unsafe { libc::errnoGet() } } -#[cfg(target_os = "vxworks")] -pub fn set_errno(e: i32) { - unsafe { libc::errnoSet(e as c_int) }; -} - #[cfg(target_os = "dragonfly")] pub fn errno() -> i32 { extern "C" { @@ -223,7 +217,7 @@ where impl fmt::Display for JoinPathsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "path segment contains separator `{}`", PATH_SEPARATOR) + write!(f, "path segment contains separator `{}`", char::from(PATH_SEPARATOR)) } } @@ -287,9 +281,9 @@ pub fn current_exe() -> io::Result { 0, ))?; if path_len <= 1 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::Other, - "KERN_PROC_PATHNAME sysctl returned zero-length string", + &"KERN_PROC_PATHNAME sysctl returned zero-length string", )); } let mut path: Vec = Vec::with_capacity(path_len); @@ -310,9 +304,9 @@ pub fn current_exe() -> io::Result { if curproc_exe.is_file() { return crate::fs::read_link(curproc_exe); } - Err(io::Error::new( + Err(io::Error::new_const( io::ErrorKind::Other, - "/proc/curproc/exe doesn't point to regular file.", + &"/proc/curproc/exe doesn't point to regular file.", )) } sysctl().or_else(|_| procfs()) @@ -329,7 +323,7 @@ pub fn current_exe() -> io::Result { 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(io::ErrorKind::Other, "no current exe available")); + return Err(io::Error::new_const(io::ErrorKind::Other, &"no current exe available")); } let argv0 = CStr::from_ptr(argv[0]).to_bytes(); if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') { @@ -343,9 +337,9 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] pub fn current_exe() -> io::Result { match crate::fs::read_link("/proc/self/exe") { - Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new( + Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const( io::ErrorKind::Other, - "no /proc/self/exe available. Is /proc mounted?", + &"no /proc/self/exe available. Is /proc mounted?", )), other => other, } @@ -431,7 +425,7 @@ pub fn current_exe() -> io::Result { _get_next_image_info(0, &mut cookie, &mut info, mem::size_of::() as i32); if result != 0 { use crate::io::ErrorKind; - Err(io::Error::new(ErrorKind::Other, "Error getting executable path")) + Err(io::Error::new_const(ErrorKind::Other, &"Error getting executable path")) } else { let name = CStr::from_ptr(info.name.as_ptr()).to_bytes(); Ok(PathBuf::from(OsStr::from_bytes(name))) @@ -447,7 +441,7 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "fuchsia", target_os = "l4re"))] pub fn current_exe() -> io::Result { use crate::io::ErrorKind; - Err(io::Error::new(ErrorKind::Other, "Not yet implemented!")) + Err(io::Error::new_const(ErrorKind::Unsupported, &"Not yet implemented!")) } #[cfg(target_os = "vxworks")] @@ -465,9 +459,11 @@ pub fn current_exe() -> io::Result { pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Env {} +impl !Sync for Env {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -515,7 +511,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { @@ -642,7 +638,7 @@ pub fn getppid() -> u32 { unsafe { libc::getppid() as u32 } } -#[cfg(target_env = "gnu")] +#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] pub fn glibc_version() -> Option<(usize, usize)> { if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { parse_glibc_version(version_str) @@ -651,7 +647,7 @@ pub fn glibc_version() -> Option<(usize, usize)> { } } -#[cfg(target_env = "gnu")] +#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] fn glibc_version_cstr() -> Option<&'static CStr> { weak! { fn gnu_get_libc_version() -> *const libc::c_char @@ -665,7 +661,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> { // Returns Some((major, minor)) if the string is a valid "x.y" version, // ignoring any extra dot-separated parts. Otherwise return None. -#[cfg(target_env = "gnu")] +#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { let mut parsed_ints = version.split('.').map(str::parse::).fuse(); match (parsed_ints.next(), parsed_ints.next()) { diff --git a/library/std/src/sys/unix/process/mod.rs b/library/std/src/sys/unix/process/mod.rs index 1b7b93f9d4..f67c70c017 100644 --- a/library/std/src/sys/unix/process/mod.rs +++ b/library/std/src/sys/unix/process/mod.rs @@ -4,11 +4,17 @@ pub use crate::ffi::OsString as EnvKey; pub use crate::sys_common::process::CommandEnvs; mod process_common; -#[cfg(not(target_os = "fuchsia"))] -#[path = "process_unix.rs"] -mod process_inner; -#[cfg(target_os = "fuchsia")] -#[path = "process_fuchsia.rs"] -mod process_inner; -#[cfg(target_os = "fuchsia")] -mod zircon; + +cfg_if::cfg_if! { + if #[cfg(target_os = "fuchsia")] { + #[path = "process_fuchsia.rs"] + mod process_inner; + mod zircon; + } else if #[cfg(target_os = "vxworks")] { + #[path = "process_vxworks.rs"] + mod process_inner; + } else { + #[path = "process_unix.rs"] + mod process_inner; + } +} diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index 0d4703d7f5..b19ad4ccdc 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -22,9 +22,9 @@ impl Command { let envp = self.capture_env(); if self.saw_nul() { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "nul byte found in provided data", + &"nul byte found in provided data", )); } @@ -37,7 +37,10 @@ impl Command { pub fn exec(&mut self, default: Stdio) -> io::Error { if self.saw_nul() { - return io::Error::new(io::ErrorKind::InvalidInput, "nul byte found in provided data"); + return io::Error::new_const( + io::ErrorKind::InvalidInput, + &"nul byte found in provided data", + ); } match self.setup_io(default, true) { @@ -182,9 +185,9 @@ impl Process { ))?; } if actual != 1 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Failed to get exit status of process", + &"Failed to get exit status of process", )); } Ok(ExitStatus(proc_info.return_code)) @@ -220,9 +223,9 @@ impl Process { ))?; } if actual != 1 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Failed to get exit status of process", + &"Failed to get exit status of process", )); } Ok(Some(ExitStatus(proc_info.return_code))) diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 47aaca82af..ed9044382a 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -28,7 +28,10 @@ impl Command { let envp = self.capture_env(); if self.saw_nul() { - return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"nul byte found in provided data", + )); } let (ours, theirs) = self.setup_io(default, needs_stdin)?; @@ -48,41 +51,35 @@ impl Command { // a lock any more because the parent won't do anything and the child is // in its own process. Thus the parent drops the lock guard while the child // forgets it to avoid unlocking it on a new thread, which would be invalid. - let (env_lock, result) = unsafe { (sys::os::env_read_lock(), cvt(libc::fork())?) }; - - let pid = unsafe { - match result { - 0 => { - mem::forget(env_lock); - drop(input); - let Err(err) = self.do_exec(theirs, envp.as_ref()); - let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; - let errno = errno.to_be_bytes(); - let bytes = [ - errno[0], - errno[1], - errno[2], - errno[3], - CLOEXEC_MSG_FOOTER[0], - CLOEXEC_MSG_FOOTER[1], - CLOEXEC_MSG_FOOTER[2], - CLOEXEC_MSG_FOOTER[3], - ]; - // pipe I/O up to PIPE_BUF bytes should be atomic, and then - // we want to be sure we *don't* run at_exit destructors as - // we're being torn down regardless - rtassert!(output.write(&bytes).is_ok()); - libc::_exit(1) - } - n => { - drop(env_lock); - n - } - } - }; + let (env_lock, pid) = unsafe { (sys::os::env_read_lock(), cvt(libc::fork())?) }; - let mut p = Process { pid, status: None }; + if pid == 0 { + mem::forget(env_lock); + drop(input); + let Err(err) = unsafe { self.do_exec(theirs, envp.as_ref()) }; + let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; + let errno = errno.to_be_bytes(); + let bytes = [ + errno[0], + errno[1], + errno[2], + errno[3], + CLOEXEC_MSG_FOOTER[0], + CLOEXEC_MSG_FOOTER[1], + CLOEXEC_MSG_FOOTER[2], + CLOEXEC_MSG_FOOTER[3], + ]; + // pipe I/O up to PIPE_BUF bytes should be atomic, and then + // we want to be sure we *don't* run at_exit destructors as + // we're being torn down regardless + rtassert!(output.write(&bytes).is_ok()); + unsafe { libc::_exit(1) } + } + + drop(env_lock); drop(output); + + let mut p = Process { pid, status: None }; let mut bytes = [0; 8]; // loop to handle EINTR @@ -118,7 +115,10 @@ impl Command { let envp = self.capture_env(); if self.saw_nul() { - return io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data"); + return io::Error::new_const( + ErrorKind::InvalidInput, + &"nul byte found in provided data", + ); } match self.setup_io(default, true) { @@ -442,9 +442,9 @@ impl Process { // and used for another process, and we probably shouldn't be killing // random processes, so just return an error. if self.status.is_some() { - Err(Error::new( + Err(Error::new_const( ErrorKind::InvalidInput, - "invalid argument: can't kill an exited process", + &"invalid argument: can't kill an exited process", )) } else { cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) @@ -529,7 +529,7 @@ impl From for ExitStatus { impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(code) = self.code() { - write!(f, "exit code: {}", code) + write!(f, "exit status: {}", code) } else if let Some(signal) = self.signal() { if self.core_dumped() { write!(f, "signal: {} (core dumped)", signal) diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs index 5819d2c2a5..02c469fbcd 100644 --- a/library/std/src/sys/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/unix/process/process_unix/tests.rs @@ -9,8 +9,8 @@ fn exitstatus_display_tests() { t(0x0000f, "signal: 15"); t(0x0008b, "signal: 11 (core dumped)"); - t(0x00000, "exit code: 0"); - t(0x0ff00, "exit code: 255"); + t(0x00000, "exit status: 0"); + t(0x0ff00, "exit status: 255"); // On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED. Probably *BSD is similar. // https://github.com/rust-lang/rust/pull/82749#issuecomment-790525956 diff --git a/library/std/src/sys/vxworks/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs similarity index 88% rename from library/std/src/sys/vxworks/process/process_vxworks.rs rename to library/std/src/sys/unix/process/process_vxworks.rs index 69adbcdddc..eecdb624b9 100644 --- a/library/std/src/sys/vxworks/process/process_vxworks.rs +++ b/library/std/src/sys/unix/process/process_vxworks.rs @@ -18,11 +18,13 @@ impl Command { needs_stdin: bool, ) -> io::Result<(Process, StdioPipes)> { use crate::sys::cvt_r; - const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; let envp = self.capture_env(); if self.saw_nul() { - return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"nul byte found in provided data", + )); } let (ours, theirs) = self.setup_io(default, needs_stdin)?; let mut p = Process { pid: 0, status: None }; @@ -58,6 +60,9 @@ impl Command { t!(cvt(libc::chdir(cwd.as_ptr()))); } + // pre_exec closures are ignored on VxWorks + let _ = self.get_closures(); + let c_envp = envp .as_ref() .map(|c| c.as_ptr()) @@ -65,7 +70,7 @@ impl Command { let stack_size = thread::min_stack(); // ensure that access to the environment is synchronized - let _lock = sys::os::env_lock(); + let _lock = sys::os::env_read_lock(); let ret = libc::rtpSpawn( self.get_program_cstr().as_ptr(), @@ -134,9 +139,9 @@ impl Process { // and used for another process, and we probably shouldn't be killing // random processes, so just return an error. if self.status.is_some() { - Err(Error::new( + Err(Error::new_const( ErrorKind::InvalidInput, - "invalid argument: can't kill an exited process", + &"invalid argument: can't kill an exited process", )) } else { cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) @@ -193,6 +198,24 @@ impl ExitStatus { pub fn signal(&self) -> Option { if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None } } + + pub fn core_dumped(&self) -> bool { + // This method is not yet properly implemented on VxWorks + false + } + + pub fn stopped_signal(&self) -> Option { + if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None } + } + + pub fn continued(&self) -> bool { + // This method is not yet properly implemented on VxWorks + false + } + + pub fn into_raw(&self) -> c_int { + self.0 + } } /// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying. diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index 38ddb41700..44f9eabc31 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -18,7 +18,8 @@ pub fn hashmap_random_keys() -> (u64, u64) { not(target_os = "freebsd"), not(target_os = "netbsd"), not(target_os = "fuchsia"), - not(target_os = "redox") + not(target_os = "redox"), + not(target_os = "vxworks") ))] mod imp { use crate::fs::File; @@ -237,3 +238,29 @@ mod imp { file.read_exact(v).expect("failed to read rand:") } } + +#[cfg(target_os = "vxworks")] +mod imp { + use crate::io; + use core::sync::atomic::{AtomicBool, Ordering::Relaxed}; + + pub fn fill_bytes(v: &mut [u8]) { + static RNG_INIT: AtomicBool = AtomicBool::new(false); + while !RNG_INIT.load(Relaxed) { + let ret = unsafe { libc::randSecure() }; + if ret < 0 { + panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); + } else if ret > 0 { + RNG_INIT.store(true, Relaxed); + break; + } + unsafe { libc::usleep(10) }; + } + let ret = unsafe { + libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int) + }; + if ret < 0 { + panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); + } + } +} diff --git a/library/std/src/sys/unix/rwlock.rs b/library/std/src/sys/unix/rwlock.rs index 2b5067a34f..d97d9d712f 100644 --- a/library/std/src/sys/unix/rwlock.rs +++ b/library/std/src/sys/unix/rwlock.rs @@ -139,3 +139,55 @@ impl RWLock { } } } + +pub struct StaticRWLock(RWLock); + +impl StaticRWLock { + pub const fn new() -> StaticRWLock { + StaticRWLock(RWLock::new()) + } + + /// Acquires shared access to the underlying lock, blocking the current + /// thread to do so. + /// + /// The lock is automatically unlocked when the returned guard is dropped. + #[inline] + pub fn read_with_guard(&'static self) -> RWLockReadGuard { + // SAFETY: All methods require static references, therefore self + // cannot be moved between invocations. + unsafe { + self.0.read(); + } + RWLockReadGuard(&self.0) + } + + /// Acquires write access to the underlying lock, blocking the current thread + /// to do so. + /// + /// The lock is automatically unlocked when the returned guard is dropped. + #[inline] + pub fn write_with_guard(&'static self) -> RWLockWriteGuard { + // SAFETY: All methods require static references, therefore self + // cannot be moved between invocations. + unsafe { + self.0.write(); + } + RWLockWriteGuard(&self.0) + } +} + +pub struct RWLockReadGuard(&'static RWLock); + +impl Drop for RWLockReadGuard { + fn drop(&mut self) { + unsafe { self.0.read_unlock() } + } +} + +pub struct RWLockWriteGuard(&'static RWLock); + +impl Drop for RWLockWriteGuard { + fn drop(&mut self) { + unsafe { self.0.write_unlock() } + } +} diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 01a12dcf5a..b8f43caec3 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -343,6 +343,20 @@ pub mod guard { // it can eventually grow to. It cannot be used to determine // the position of kernel's stack guard. None + } else if cfg!(target_os = "freebsd") { + // FreeBSD's stack autogrows, and optionally includes a guard page + // at the bottom. If we try to remap the bottom of the stack + // ourselves, FreeBSD's guard page moves upwards. So we'll just use + // the builtin guard page. + let stackaddr = get_stack_start_aligned()?; + let guardaddr = stackaddr as usize; + // Technically the number of guard pages is tunable and controlled + // by the security.bsd.stack_guard_page sysctl, but there are + // few reasons to change it from the default. The default value has + // been 1 ever since FreeBSD 11.1 and 10.4. + const GUARD_PAGES: usize = 1; + let guard = guardaddr..guardaddr + GUARD_PAGES * page_size; + Some(guard) } else { // Reallocate the last page of the stack. // This ensures SIGBUS will be raised on @@ -371,9 +385,8 @@ pub mod guard { } let guardaddr = stackaddr as usize; - let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 }; - Some(guardaddr..guardaddr + offset * page_size) + Some(guardaddr..guardaddr + page_size) } } @@ -417,11 +430,7 @@ pub mod guard { assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0); let stackaddr = stackaddr as usize; - ret = if cfg!(target_os = "freebsd") { - // FIXME does freebsd really fault *below* the guard addr? - let guardaddr = stackaddr - guardsize; - Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr) - } else if cfg!(target_os = "netbsd") { + ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd")) { Some(stackaddr - guardsize..stackaddr) } else if cfg!(all(target_os = "linux", target_env = "musl")) { Some(stackaddr - guardsize..stackaddr) diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index c3275eb6f0..c3f410353b 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -92,3 +92,9 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { } } } + +#[cfg(target_os = "vxworks")] +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + use crate::sys_common::thread_local_dtor::register_dtor_fallback; + register_dtor_fallback(t, dtor); +} diff --git a/library/std/src/sys/unsupported/args.rs b/library/std/src/sys/unsupported/args.rs index 71d0c5fa13..c924a7d8a2 100644 --- a/library/std/src/sys/unsupported/args.rs +++ b/library/std/src/sys/unsupported/args.rs @@ -1,17 +1,14 @@ use crate::ffi::OsString; -pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} -pub unsafe fn cleanup() {} - pub struct Args {} pub fn args() -> Args { Args {} } -impl Args { - pub fn inner_debug(&self) -> &[OsString] { - &[] +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().finish() } } diff --git a/library/std/src/sys/unsupported/cmath.rs b/library/std/src/sys/unsupported/cmath.rs deleted file mode 100644 index 304cf906b2..0000000000 --- a/library/std/src/sys/unsupported/cmath.rs +++ /dev/null @@ -1,29 +0,0 @@ -// These symbols are all defined in `compiler-builtins` -extern "C" { - pub fn acos(n: f64) -> f64; - pub fn acosf(n: f32) -> f32; - pub fn asin(n: f64) -> f64; - pub fn asinf(n: f32) -> f32; - pub fn atan(n: f64) -> f64; - pub fn atan2(a: f64, b: f64) -> f64; - pub fn atan2f(a: f32, b: f32) -> f32; - pub fn atanf(n: f32) -> f32; - pub fn cbrt(n: f64) -> f64; - pub fn cbrtf(n: f32) -> f32; - pub fn cosh(n: f64) -> f64; - pub fn coshf(n: f32) -> f32; - pub fn expm1(n: f64) -> f64; - pub fn expm1f(n: f32) -> f32; - pub fn fdim(a: f64, b: f64) -> f64; - pub fn fdimf(a: f32, b: f32) -> f32; - pub fn hypot(x: f64, y: f64) -> f64; - pub fn hypotf(x: f32, y: f32) -> f32; - pub fn log1p(n: f64) -> f64; - pub fn log1pf(n: f32) -> f32; - pub fn sinh(n: f64) -> f64; - pub fn sinhf(n: f32) -> f32; - pub fn tan(n: f64) -> f64; - pub fn tanf(n: f32) -> f32; - pub fn tanh(n: f64) -> f64; - pub fn tanhf(n: f32) -> f32; -} diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs index 2cdd9c4d19..6e72a7c632 100644 --- a/library/std/src/sys/unsupported/common.rs +++ b/library/std/src/sys/unsupported/common.rs @@ -10,15 +10,23 @@ pub use crate::sys_common::os_str_bytes as os_str; // spec definition? use crate::os::raw::c_char; -#[cfg(not(test))] -pub fn init() {} +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +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() {} pub fn unsupported() -> std_io::Result { Err(unsupported_err()) } pub fn unsupported_err() -> std_io::Error { - std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform") + std_io::Error::new_const( + std_io::ErrorKind::Unsupported, + &"operation not supported on this platform", + ) } pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { @@ -33,11 +41,6 @@ pub fn hashmap_random_keys() -> (u64, u64) { (1, 2) } -// This enum is used as the storage for a bunch of types which can't actually -// exist. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub enum Void {} - pub unsafe fn strlen(mut s: *const c_char) -> usize { // SAFETY: The caller must guarantee `s` points to a valid 0-terminated string. unsafe { diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index 4271d9b334..cd533761e3 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -4,77 +4,77 @@ use crate::hash::{Hash, Hasher}; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; -pub struct File(Void); +pub struct File(!); -pub struct FileAttr(Void); +pub struct FileAttr(!); -pub struct ReadDir(Void); +pub struct ReadDir(!); -pub struct DirEntry(Void); +pub struct DirEntry(!); #[derive(Clone, Debug)] pub struct OpenOptions {} -pub struct FilePermissions(Void); +pub struct FilePermissions(!); -pub struct FileType(Void); +pub struct FileType(!); #[derive(Debug)] pub struct DirBuilder {} impl FileAttr { pub fn size(&self) -> u64 { - match self.0 {} + self.0 } pub fn perm(&self) -> FilePermissions { - match self.0 {} + self.0 } pub fn file_type(&self) -> FileType { - match self.0 {} + self.0 } pub fn modified(&self) -> io::Result { - match self.0 {} + self.0 } pub fn accessed(&self) -> io::Result { - match self.0 {} + self.0 } pub fn created(&self) -> io::Result { - match self.0 {} + self.0 } } impl Clone for FileAttr { fn clone(&self) -> FileAttr { - match self.0 {} + self.0 } } impl FilePermissions { pub fn readonly(&self) -> bool { - match self.0 {} + self.0 } pub fn set_readonly(&mut self, _readonly: bool) { - match self.0 {} + self.0 } } impl Clone for FilePermissions { fn clone(&self) -> FilePermissions { - match self.0 {} + self.0 } } impl PartialEq for FilePermissions { fn eq(&self, _other: &FilePermissions) -> bool { - match self.0 {} + self.0 } } @@ -82,27 +82,27 @@ impl Eq for FilePermissions {} impl fmt::Debug for FilePermissions { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } impl FileType { pub fn is_dir(&self) -> bool { - match self.0 {} + self.0 } pub fn is_file(&self) -> bool { - match self.0 {} + self.0 } pub fn is_symlink(&self) -> bool { - match self.0 {} + self.0 } } impl Clone for FileType { fn clone(&self) -> FileType { - match self.0 {} + self.0 } } @@ -110,7 +110,7 @@ impl Copy for FileType {} impl PartialEq for FileType { fn eq(&self, _other: &FileType) -> bool { - match self.0 {} + self.0 } } @@ -118,19 +118,19 @@ impl Eq for FileType {} impl Hash for FileType { fn hash(&self, _h: &mut H) { - match self.0 {} + self.0 } } impl fmt::Debug for FileType { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } impl fmt::Debug for ReadDir { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } @@ -138,25 +138,25 @@ impl Iterator for ReadDir { type Item = io::Result; fn next(&mut self) -> Option> { - match self.0 {} + self.0 } } impl DirEntry { pub fn path(&self) -> PathBuf { - match self.0 {} + self.0 } pub fn file_name(&self) -> OsString { - match self.0 {} + self.0 } pub fn metadata(&self) -> io::Result { - match self.0 {} + self.0 } pub fn file_type(&self) -> io::Result { - match self.0 {} + self.0 } } @@ -179,59 +179,59 @@ impl File { } pub fn file_attr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn fsync(&self) -> io::Result<()> { - match self.0 {} + self.0 } pub fn datasync(&self) -> io::Result<()> { - match self.0 {} + self.0 } pub fn truncate(&self, _size: u64) -> io::Result<()> { - match self.0 {} + self.0 } pub fn read(&self, _buf: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result { - match self.0 {} + self.0 } pub fn is_read_vectored(&self) -> bool { - match self.0 {} + self.0 } pub fn write(&self, _buf: &[u8]) -> io::Result { - match self.0 {} + self.0 } pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result { - match self.0 {} + self.0 } pub fn is_write_vectored(&self) -> bool { - match self.0 {} + self.0 } pub fn flush(&self) -> io::Result<()> { - match self.0 {} + self.0 } pub fn seek(&self, _pos: SeekFrom) -> io::Result { - match self.0 {} + self.0 } pub fn duplicate(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { - match self.0 {} + self.0 } } @@ -247,7 +247,7 @@ impl DirBuilder { impl fmt::Debug for File { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/unsupported/mod.rs b/library/std/src/sys/unsupported/mod.rs index d9efdec33d..3ef4c6b8a8 100644 --- a/library/std/src/sys/unsupported/mod.rs +++ b/library/std/src/sys/unsupported/mod.rs @@ -2,6 +2,7 @@ pub mod alloc; pub mod args; +#[path = "../unix/cmath.rs"] pub mod cmath; pub mod condvar; pub mod env; @@ -15,7 +16,6 @@ pub mod path; pub mod pipe; pub mod process; pub mod rwlock; -pub mod stack_overflow; pub mod stdio; pub mod thread; #[cfg(target_thread_local)] diff --git a/library/std/src/sys/unsupported/net.rs b/library/std/src/sys/unsupported/net.rs index 5c9f1098f9..96203c74b5 100644 --- a/library/std/src/sys/unsupported/net.rs +++ b/library/std/src/sys/unsupported/net.rs @@ -2,10 +2,10 @@ use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::time::Duration; -pub struct TcpStream(Void); +pub struct TcpStream(!); impl TcpStream { pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { @@ -17,97 +17,97 @@ impl TcpStream { } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + self.0 } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + self.0 } pub fn read_timeout(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn write_timeout(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn peek(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn read(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result { - match self.0 {} + self.0 } pub fn is_read_vectored(&self) -> bool { - match self.0 {} + self.0 } pub fn write(&self, _: &[u8]) -> io::Result { - match self.0 {} + self.0 } pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { - match self.0 {} + self.0 } pub fn is_write_vectored(&self) -> bool { - match self.0 {} + self.0 } pub fn peer_addr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - match self.0 {} + self.0 } pub fn duplicate(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn nodelay(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn ttl(&self) -> io::Result { - match self.0 {} + self.0 } pub fn take_error(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } } impl fmt::Debug for TcpStream { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } -pub struct TcpListener(Void); +pub struct TcpListener(!); impl TcpListener { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { @@ -115,49 +115,49 @@ impl TcpListener { } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - match self.0 {} + self.0 } pub fn duplicate(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn ttl(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn only_v6(&self) -> io::Result { - match self.0 {} + self.0 } pub fn take_error(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } } impl fmt::Debug for TcpListener { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } -pub struct UdpSocket(Void); +pub struct UdpSocket(!); impl UdpSocket { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { @@ -165,144 +165,144 @@ impl UdpSocket { } pub fn peer_addr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + self.0 } pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + self.0 } pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + self.0 } pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { - match self.0 {} + self.0 } pub fn duplicate(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + self.0 } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + self.0 } pub fn read_timeout(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn write_timeout(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn broadcast(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn multicast_loop_v4(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn multicast_ttl_v4(&self) -> io::Result { - match self.0 {} + self.0 } pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn multicast_loop_v6(&self) -> io::Result { - match self.0 {} + self.0 } pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + self.0 } pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + self.0 } pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + self.0 } pub fn ttl(&self) -> io::Result { - match self.0 {} + self.0 } pub fn take_error(&self) -> io::Result> { - match self.0 {} + self.0 } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + self.0 } pub fn recv(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn peek(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn send(&self, _: &[u8]) -> io::Result { - match self.0 {} + self.0 } pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - match self.0 {} + self.0 } } impl fmt::Debug for UdpSocket { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } -pub struct LookupHost(Void); +pub struct LookupHost(!); impl LookupHost { pub fn port(&self) -> u16 { - match self.0 {} + self.0 } } impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/unsupported/os.rs b/library/std/src/sys/unsupported/os.rs index 0615780c24..e30395a0b1 100644 --- a/library/std/src/sys/unsupported/os.rs +++ b/library/std/src/sys/unsupported/os.rs @@ -1,8 +1,9 @@ -use super::{unsupported, Void}; +use super::unsupported; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::fmt; use crate::io; +use crate::marker::PhantomData; use crate::path::{self, PathBuf}; pub fn errno() -> i32 { @@ -21,7 +22,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> { unsupported() } -pub struct SplitPaths<'a>(&'a Void); +pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { panic!("unsupported") @@ -30,7 +31,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { impl<'a> Iterator for SplitPaths<'a> { type Item = PathBuf; fn next(&mut self) -> Option { - match *self.0 {} + self.0 } } @@ -62,12 +63,12 @@ pub fn current_exe() -> io::Result { unsupported() } -pub struct Env(Void); +pub struct Env(!); impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { - match self.0 {} + self.0 } } @@ -80,11 +81,11 @@ pub fn getenv(_: &OsStr) -> io::Result> { } pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on this platform")) + Err(io::Error::new_const(io::ErrorKind::Unsupported, &"cannot set env vars on this platform")) } pub fn unsetenv(_: &OsStr) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on this platform")) + Err(io::Error::new_const(io::ErrorKind::Unsupported, &"cannot unset env vars on this platform")) } pub fn temp_dir() -> PathBuf { diff --git a/library/std/src/sys/unsupported/pipe.rs b/library/std/src/sys/unsupported/pipe.rs index 10d0925823..25514c2322 100644 --- a/library/std/src/sys/unsupported/pipe.rs +++ b/library/std/src/sys/unsupported/pipe.rs @@ -1,35 +1,34 @@ use crate::io::{self, IoSlice, IoSliceMut}; -use crate::sys::Void; -pub struct AnonPipe(Void); +pub struct AnonPipe(!); impl AnonPipe { pub fn read(&self, _buf: &mut [u8]) -> io::Result { - match self.0 {} + self.0 } pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result { - match self.0 {} + self.0 } pub fn is_read_vectored(&self) -> bool { - match self.0 {} + self.0 } pub fn write(&self, _buf: &[u8]) -> io::Result { - match self.0 {} + self.0 } pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result { - match self.0 {} + self.0 } pub fn is_write_vectored(&self) -> bool { - match self.0 {} + self.0 } pub fn diverge(&self) -> ! { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs index 3ede2291d5..38ac0a1ddd 100644 --- a/library/std/src/sys/unsupported/process.rs +++ b/library/std/src/sys/unsupported/process.rs @@ -5,7 +5,7 @@ use crate::marker::PhantomData; use crate::path::Path; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::sys_common::process::{CommandEnv, CommandEnvs}; pub use crate::ffi::OsString as EnvKey; @@ -94,21 +94,21 @@ impl fmt::Debug for Command { } } -pub struct ExitStatus(Void); +pub struct ExitStatus(!); impl ExitStatus { pub fn success(&self) -> bool { - match self.0 {} + self.0 } pub fn code(&self) -> Option { - match self.0 {} + self.0 } } impl Clone for ExitStatus { fn clone(&self) -> ExitStatus { - match self.0 {} + self.0 } } @@ -116,7 +116,7 @@ impl Copy for ExitStatus {} impl PartialEq for ExitStatus { fn eq(&self, _other: &ExitStatus) -> bool { - match self.0 {} + self.0 } } @@ -124,13 +124,13 @@ impl Eq for ExitStatus {} impl fmt::Debug for ExitStatus { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } impl fmt::Display for ExitStatus { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + self.0 } } @@ -146,23 +146,23 @@ impl ExitCode { } } -pub struct Process(Void); +pub struct Process(!); impl Process { pub fn id(&self) -> u32 { - match self.0 {} + self.0 } pub fn kill(&mut self) -> io::Result<()> { - match self.0 {} + self.0 } pub fn wait(&mut self) -> io::Result { - match self.0 {} + self.0 } pub fn try_wait(&mut self) -> io::Result> { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/unsupported/stack_overflow.rs b/library/std/src/sys/unsupported/stack_overflow.rs deleted file mode 100644 index 32555394cd..0000000000 --- a/library/std/src/sys/unsupported/stack_overflow.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub unsafe fn init() {} - -pub unsafe fn cleanup() {} diff --git a/library/std/src/sys/unsupported/thread.rs b/library/std/src/sys/unsupported/thread.rs index 20ae309db3..cda8510e1b 100644 --- a/library/std/src/sys/unsupported/thread.rs +++ b/library/std/src/sys/unsupported/thread.rs @@ -1,9 +1,9 @@ -use super::{unsupported, Void}; +use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::time::Duration; -pub struct Thread(Void); +pub struct Thread(!); pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; @@ -26,7 +26,7 @@ impl Thread { } pub fn join(self) { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/vxworks/env.rs b/library/std/src/sys/vxworks/env.rs deleted file mode 100644 index fe1aedd585..0000000000 --- a/library/std/src/sys/vxworks/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = "vxworks"; - pub const OS: &str = "vxworks"; - pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".so"; - pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; -} diff --git a/library/std/src/sys/vxworks/mod.rs b/library/std/src/sys/vxworks/mod.rs deleted file mode 100644 index c20edaa1a4..0000000000 --- a/library/std/src/sys/vxworks/mod.rs +++ /dev/null @@ -1,137 +0,0 @@ -#![allow(dead_code)] -#![allow(missing_docs, nonstandard_style)] - -use crate::io::ErrorKind; - -pub use self::rand::hashmap_random_keys; -pub use crate::os::vxworks as platform; -pub use libc::strlen; - -#[macro_use] -#[path = "../unix/weak.rs"] -pub mod weak; - -#[path = "../unix/alloc.rs"] -pub mod alloc; -#[path = "../unix/args.rs"] -pub mod args; -#[path = "../unix/cmath.rs"] -pub mod cmath; -#[path = "../unix/condvar.rs"] -pub mod condvar; -pub mod env; -#[path = "../unix/ext/mod.rs"] -pub mod ext; -#[path = "../unix/fd.rs"] -pub mod fd; -#[path = "../unix/fs.rs"] -pub mod fs; -#[path = "../unix/io.rs"] -pub mod io; -#[path = "../unix/memchr.rs"] -pub mod memchr; -#[path = "../unix/mutex.rs"] -pub mod mutex; -#[path = "../unix/net.rs"] -pub mod net; -#[path = "../unix/os.rs"] -pub mod os; -#[path = "../unix/path.rs"] -pub mod path; -#[path = "../unix/pipe.rs"] -pub mod pipe; -pub mod process; -pub mod rand; -#[path = "../unix/rwlock.rs"] -pub mod rwlock; -#[path = "../unix/stack_overflow.rs"] -pub mod stack_overflow; -#[path = "../unix/stdio.rs"] -pub mod stdio; -#[path = "../unix/thread.rs"] -pub mod thread; -pub mod thread_local_dtor; -#[path = "../unix/thread_local_key.rs"] -pub mod thread_local_key; -#[path = "../unix/time.rs"] -pub mod time; - -pub use crate::sys_common::os_str_bytes as os_str; - -#[cfg(not(test))] -pub fn init() { - // ignore SIGPIPE - unsafe { - assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); - } -} - -pub use libc::signal; - -pub fn decode_error_kind(errno: i32) -> 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, - - // 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, - - _ => ErrorKind::Other, - } -} - -#[doc(hidden)] -pub trait IsMinusOne { - fn is_minus_one(&self) -> bool; -} - -macro_rules! impl_is_minus_one { - ($($t:ident)*) => ($(impl IsMinusOne for $t { - fn is_minus_one(&self) -> bool { - *self == -1 - } - })*) -} - -impl_is_minus_one! { i8 i16 i32 i64 isize } - -pub fn cvt(t: T) -> crate::io::Result { - if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) } -} - -pub fn cvt_r(mut f: F) -> crate::io::Result -where - T: IsMinusOne, - F: FnMut() -> T, -{ - loop { - match cvt(f()) { - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} - other => return other, - } - } -} - -// 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. -pub fn abort_internal() -> ! { - unsafe { libc::abort() } -} diff --git a/library/std/src/sys/vxworks/process/mod.rs b/library/std/src/sys/vxworks/process/mod.rs deleted file mode 100644 index dc6130eaa2..0000000000 --- a/library/std/src/sys/vxworks/process/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub use self::process_common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes}; -pub use self::process_inner::{ExitStatus, Process}; -pub use crate::ffi::OsString as EnvKey; -pub use crate::sys_common::process::CommandEnvs; - -#[path = "../../unix/process/process_common.rs"] -mod process_common; -#[path = "process_vxworks.rs"] -mod process_inner; diff --git a/library/std/src/sys/vxworks/rand.rs b/library/std/src/sys/vxworks/rand.rs deleted file mode 100644 index 3a1ff5fd3b..0000000000 --- a/library/std/src/sys/vxworks/rand.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::mem; -use crate::slice; - -pub fn hashmap_random_keys() -> (u64, u64) { - let mut v = (0, 0); - unsafe { - let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8, mem::size_of_val(&v)); - imp::fill_bytes(view); - } - return v; -} - -mod imp { - use crate::io; - use core::sync::atomic::{AtomicBool, Ordering::Relaxed}; - - pub fn fill_bytes(v: &mut [u8]) { - static RNG_INIT: AtomicBool = AtomicBool::new(false); - while !RNG_INIT.load(Relaxed) { - let ret = unsafe { libc::randSecure() }; - if ret < 0 { - panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); - } else if ret > 0 { - RNG_INIT.store(true, Relaxed); - break; - } - unsafe { libc::usleep(10) }; - } - let ret = unsafe { - libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int) - }; - if ret < 0 { - panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); - } - } -} diff --git a/library/std/src/sys/vxworks/thread_local_dtor.rs b/library/std/src/sys/vxworks/thread_local_dtor.rs deleted file mode 100644 index 5391ed83eb..0000000000 --- a/library/std/src/sys/vxworks/thread_local_dtor.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![cfg(target_thread_local)] -#![unstable(feature = "thread_local_internals", issue = "none")] - -pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - use crate::sys_common::thread_local_dtor::register_dtor_fallback; - register_dtor_fallback(t, dtor); -} diff --git a/library/std/src/sys/wasi/args.rs b/library/std/src/sys/wasi/args.rs index 9a27218e1f..c42c310e3a 100644 --- a/library/std/src/sys/wasi/args.rs +++ b/library/std/src/sys/wasi/args.rs @@ -1,25 +1,20 @@ #![deny(unsafe_op_in_unsafe_fn)] use crate::ffi::{CStr, OsStr, OsString}; -use crate::marker::PhantomData; +use crate::fmt; use crate::os::wasi::ffi::OsStrExt; use crate::vec; -pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} - -pub unsafe fn cleanup() {} - pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + /// Returns the command line arguments pub fn args() -> Args { - Args { - iter: maybe_args().unwrap_or(Vec::new()).into_iter(), - _dont_send_or_sync_me: PhantomData, - } + Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() } } fn maybe_args() -> Option> { @@ -38,9 +33,9 @@ fn maybe_args() -> Option> { } } -impl Args { - pub fn inner_debug(&self) -> &[OsString] { - self.iter.as_slice() +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) } } diff --git a/library/std/src/sys/wasi/ext/fs.rs b/library/std/src/sys/wasi/ext/fs.rs index 6472642f03..ba4057bd34 100644 --- a/library/std/src/sys/wasi/ext/fs.rs +++ b/library/std/src/sys/wasi/ext/fs.rs @@ -85,7 +85,7 @@ pub trait FileExt { } } if !buf.is_empty() { - Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer")) + Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) } else { Ok(()) } @@ -151,9 +151,9 @@ pub trait FileExt { while !buf.is_empty() { match self.write_at(buf, offset) { Ok(0) => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::WriteZero, - "failed to write whole buffer", + &"failed to write whole buffer", )); } Ok(n) => { @@ -532,5 +532,5 @@ pub fn symlink_path, U: AsRef>(old_path: P, new_path: U) -> } fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8")) + f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) } diff --git a/library/std/src/sys/wasi/ext/io.rs b/library/std/src/sys/wasi/ext/io.rs index 3c480aa8e1..b2e79cc1b4 100644 --- a/library/std/src/sys/wasi/ext/io.rs +++ b/library/std/src/sys/wasi/ext/io.rs @@ -54,126 +54,147 @@ pub trait IntoRawFd { #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl AsRawFd for RawFd { + #[inline] fn as_raw_fd(&self) -> RawFd { *self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl IntoRawFd for RawFd { + #[inline] fn into_raw_fd(self) -> RawFd { self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl FromRawFd for RawFd { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> RawFd { fd } } impl AsRawFd for net::TcpStream { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for net::TcpStream { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { net::TcpStream::from_inner(sys::net::TcpStream::from_inner(fd)) } } impl IntoRawFd for net::TcpStream { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for net::TcpListener { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for net::TcpListener { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { net::TcpListener::from_inner(sys::net::TcpListener::from_inner(fd)) } } impl IntoRawFd for net::TcpListener { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for net::UdpSocket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for net::UdpSocket { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { net::UdpSocket::from_inner(sys::net::UdpSocket::from_inner(fd)) } } impl IntoRawFd for net::UdpSocket { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for fs::File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for fs::File { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> fs::File { fs::File::from_inner(sys::fs::File::from_inner(fd)) } } impl IntoRawFd for fs::File { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for io::Stdin { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO as RawFd } } impl AsRawFd for io::Stdout { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO as RawFd } } impl AsRawFd for io::Stderr { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO as RawFd } } impl<'a> AsRawFd for io::StdinLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO as RawFd } } impl<'a> AsRawFd for io::StdoutLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO as RawFd } } impl<'a> AsRawFd for io::StderrLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO as RawFd } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 63c2213627..ed0f03e4b7 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -130,7 +130,7 @@ impl FileType { impl fmt::Debug for ReadDir { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ReadDir").finish() + f.debug_struct("ReadDir").finish_non_exhaustive() } } @@ -670,7 +670,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { } pub fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8")) + f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) } pub fn copy(from: &Path, to: &Path) -> io::Result { diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index a0a37ef831..37f74fcc05 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -20,7 +20,7 @@ use crate::mem; #[path = "../unix/alloc.rs"] pub mod alloc; pub mod args; -#[path = "../unsupported/cmath.rs"] +#[path = "../unix/cmath.rs"] pub mod cmath; #[path = "../unsupported/condvar.rs"] pub mod condvar; @@ -42,8 +42,6 @@ pub mod pipe; pub mod process; #[path = "../unsupported/rwlock.rs"] pub mod rwlock; -#[path = "../unsupported/stack_overflow.rs"] -pub mod stack_overflow; pub mod stdio; pub mod thread; #[path = "../unsupported/thread_local_dtor.rs"] @@ -78,6 +76,7 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { wasi::ERRNO_TIMEDOUT => TimedOut, wasi::ERRNO_EXIST => AlreadyExists, wasi::ERRNO_AGAIN => WouldBlock, + wasi::ERRNO_NOSYS => Unsupported, _ => Other, } } diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 3f294e7df4..06860673d9 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -5,7 +5,7 @@ use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::sys_common::FromInner; use crate::time::Duration; @@ -343,18 +343,18 @@ impl fmt::Debug for UdpSocket { } } -pub struct LookupHost(Void); +pub struct LookupHost(!); impl LookupHost { pub fn port(&self) -> u16 { - match self.0 {} + self.0 } } impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs index 185d6109cb..f129ee55a8 100644 --- a/library/std/src/sys/wasi/os.rs +++ b/library/std/src/sys/wasi/os.rs @@ -10,7 +10,7 @@ use crate::os::wasi::prelude::*; use crate::path::{self, PathBuf}; use crate::str; use crate::sys::memchr; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::vec; // Add a few symbols not in upstream `libc` just yet. @@ -87,7 +87,7 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { } } -pub struct SplitPaths<'a>(&'a Void); +pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { panic!("unsupported") @@ -96,7 +96,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { impl<'a> Iterator for SplitPaths<'a> { type Item = PathBuf; fn next(&mut self) -> Option { - match *self.0 {} + self.0 } } @@ -129,9 +129,11 @@ pub fn current_exe() -> io::Result { } pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Env {} +impl !Sync for Env {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -155,7 +157,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } // See src/libstd/sys/unix/os.rs, same as that diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index 8eaa5f09cb..74515553a8 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -3,10 +3,10 @@ use crate::ffi::CStr; use crate::io; use crate::mem; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::time::Duration; -pub struct Thread(Void); +pub struct Thread(!); pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; @@ -59,7 +59,7 @@ impl Thread { } pub fn join(self) { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/wasm/args.rs b/library/std/src/sys/wasm/args.rs index 3b6557ae32..fde1ab79e1 100644 --- a/library/std/src/sys/wasm/args.rs +++ b/library/std/src/sys/wasm/args.rs @@ -1,25 +1,21 @@ use crate::ffi::OsString; -use crate::marker::PhantomData; +use crate::fmt; use crate::vec; -pub unsafe fn init(_argc: isize, _argv: *const *const u8) { - // On wasm these should always be null, so there's nothing for us to do here -} - -pub unsafe fn cleanup() {} - pub fn args() -> Args { - Args { iter: Vec::new().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: Vec::new().into_iter() } } pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } -impl Args { - pub fn inner_debug(&self) -> &[OsString] { - self.iter.as_slice() +impl !Send for Args {} +impl !Sync for Args {} + +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) } } diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs index 82683c0f62..afcc5ca928 100644 --- a/library/std/src/sys/wasm/mod.rs +++ b/library/std/src/sys/wasm/mod.rs @@ -18,7 +18,7 @@ pub mod alloc; pub mod args; -#[path = "../unsupported/cmath.rs"] +#[path = "../unix/cmath.rs"] pub mod cmath; pub mod env; #[path = "../unsupported/fs.rs"] @@ -35,8 +35,6 @@ pub mod path; pub mod pipe; #[path = "../unsupported/process.rs"] pub mod process; -#[path = "../unsupported/stack_overflow.rs"] -pub mod stack_overflow; #[path = "../unsupported/stdio.rs"] pub mod stdio; pub mod thread; diff --git a/library/std/src/sys/wasm/thread.rs b/library/std/src/sys/wasm/thread.rs index 5eafb77da1..b7bf95c89b 100644 --- a/library/std/src/sys/wasm/thread.rs +++ b/library/std/src/sys/wasm/thread.rs @@ -1,9 +1,9 @@ use crate::ffi::CStr; use crate::io; -use crate::sys::{unsupported, Void}; +use crate::sys::unsupported; use crate::time::Duration; -pub struct Thread(Void); +pub struct Thread(!); pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; @@ -47,7 +47,7 @@ impl Thread { } pub fn join(self) { - match self.0 {} + self.0 } } diff --git a/library/std/src/sys/windows/alloc.rs b/library/std/src/sys/windows/alloc.rs index 99b4d6c72a..2fe71f9f28 100644 --- a/library/std/src/sys/windows/alloc.rs +++ b/library/std/src/sys/windows/alloc.rs @@ -1,61 +1,246 @@ +#![deny(unsafe_op_in_unsafe_fn)] + use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::ffi::c_void; +use crate::ptr; +use crate::sync::atomic::{AtomicPtr, Ordering}; use crate::sys::c; -use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN}; +use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; -#[repr(C)] -struct Header(*mut u8); +#[cfg(test)] +mod tests; + +// Heap memory management on Windows is done by using the system Heap API (heapapi.h) +// See https://docs.microsoft.com/windows/win32/api/heapapi/ + +// Flag to indicate that the memory returned by `HeapAlloc` should be zeroed. +const HEAP_ZERO_MEMORY: c::DWORD = 0x00000008; -unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { - &mut *(ptr as *mut Header).offset(-1) +extern "system" { + // Get a handle to the default heap of the current process, or null if the operation fails. + // + // SAFETY: Successful calls to this function within the same process are assumed to + // always return the same handle, which remains valid for the entire lifetime of the process. + // + // See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-getprocessheap + fn GetProcessHeap() -> c::HANDLE; + + // Allocate a block of `dwBytes` bytes of memory from a given heap `hHeap`. + // The allocated memory may be uninitialized, or zeroed if `dwFlags` is + // set to `HEAP_ZERO_MEMORY`. + // + // Returns a pointer to the newly-allocated memory or null if the operation fails. + // The returned pointer will be aligned to at least `MIN_ALIGN`. + // + // SAFETY: + // - `hHeap` must be a non-null handle returned by `GetProcessHeap`. + // - `dwFlags` must be set to either zero or `HEAP_ZERO_MEMORY`. + // + // Note that `dwBytes` is allowed to be zero, contrary to some other allocators. + // + // See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heapalloc + fn HeapAlloc(hHeap: c::HANDLE, dwFlags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID; + + // Reallocate a block of memory behind a given pointer `lpMem` from a given heap `hHeap`, + // to a block of at least `dwBytes` bytes, either shrinking the block in place, + // or allocating at a new location, copying memory, and freeing the original location. + // + // Returns a pointer to the reallocated memory or null if the operation fails. + // The returned pointer will be aligned to at least `MIN_ALIGN`. + // If the operation fails the given block will never have been freed. + // + // SAFETY: + // - `hHeap` must be a non-null handle returned by `GetProcessHeap`. + // - `dwFlags` must be set to zero. + // - `lpMem` must be a non-null pointer to an allocated block returned by `HeapAlloc` or + // `HeapReAlloc`, that has not already been freed. + // If the block was successfully reallocated at a new location, pointers pointing to + // the freed memory, such as `lpMem`, must not be dereferenced ever again. + // + // Note that `dwBytes` is allowed to be zero, contrary to some other allocators. + // + // See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heaprealloc + fn HeapReAlloc( + hHeap: c::HANDLE, + dwFlags: c::DWORD, + lpMem: c::LPVOID, + dwBytes: c::SIZE_T, + ) -> c::LPVOID; + + // Free a block of memory behind a given pointer `lpMem` from a given heap `hHeap`. + // Returns a nonzero value if the operation is successful, and zero if the operation fails. + // + // SAFETY: + // - `hHeap` must be a non-null handle returned by `GetProcessHeap`. + // - `dwFlags` must be set to zero. + // - `lpMem` must be a pointer to an allocated block returned by `HeapAlloc` or `HeapReAlloc`, + // that has not already been freed. + // If the block was successfully freed, pointers pointing to the freed memory, such as `lpMem`, + // must not be dereferenced ever again. + // + // Note that `lpMem` is allowed to be null, which will not cause the operation to fail. + // + // See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heapfree + fn HeapFree(hHeap: c::HANDLE, dwFlags: c::DWORD, lpMem: c::LPVOID) -> c::BOOL; } -unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { - let aligned = ptr.add(align - (ptr as usize & (align - 1))); - *get_header(aligned) = Header(ptr); - aligned +// Cached handle to the default heap of the current process. +// Either a non-null handle returned by `GetProcessHeap`, or null when not yet initialized or `GetProcessHeap` failed. +static HEAP: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + +// Get a handle to the default heap of the current process, or null if the operation fails. +// If this operation is successful, `HEAP` will be successfully initialized and contain +// a non-null handle returned by `GetProcessHeap`. +#[inline] +fn init_or_get_process_heap() -> c::HANDLE { + let heap = HEAP.load(Ordering::Relaxed); + if heap.is_null() { + // `HEAP` has not yet been successfully initialized + let heap = unsafe { GetProcessHeap() }; + if !heap.is_null() { + // SAFETY: No locking is needed because within the same process, + // successful calls to `GetProcessHeap` will always return the same value, even on different threads. + HEAP.store(heap, Ordering::Release); + + // SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap` + heap + } else { + // Could not get the current process heap. + ptr::null_mut() + } + } else { + // SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap` + heap + } } +// Get a non-null handle to the default heap of the current process. +// SAFETY: `HEAP` must have been successfully initialized. #[inline] -unsafe fn allocate_with_flags(layout: Layout, flags: c::DWORD) -> *mut u8 { - if layout.align() <= MIN_ALIGN { - return c::HeapAlloc(c::GetProcessHeap(), flags, layout.size()) as *mut u8; +unsafe fn get_process_heap() -> c::HANDLE { + HEAP.load(Ordering::Acquire) +} + +// Header containing a pointer to the start of an allocated block. +// SAFETY: Size and alignment must be <= `MIN_ALIGN`. +#[repr(C)] +struct Header(*mut u8); + +// Allocate a block of optionally zeroed memory for a given `layout`. +// SAFETY: Returns a pointer satisfying the guarantees of `System` about allocated pointers, +// or null if the operation fails. If this returns non-null `HEAP` will have been successfully +// initialized. +#[inline] +unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 { + let heap = init_or_get_process_heap(); + if heap.is_null() { + // Allocation has failed, could not get the current process heap. + return ptr::null_mut(); } - let size = layout.size() + layout.align(); - let ptr = c::HeapAlloc(c::GetProcessHeap(), flags, size); - if ptr.is_null() { ptr as *mut u8 } else { align_ptr(ptr as *mut u8, layout.align()) } + // Allocated memory will be either zeroed or uninitialized. + let flags = if zeroed { HEAP_ZERO_MEMORY } else { 0 }; + + if layout.align() <= MIN_ALIGN { + // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. + // The returned pointer points to the start of an allocated block. + unsafe { HeapAlloc(heap, flags, layout.size()) as *mut u8 } + } else { + // Allocate extra padding in order to be able to satisfy the alignment. + let total = layout.align() + layout.size(); + + // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. + let ptr = unsafe { HeapAlloc(heap, flags, total) as *mut u8 }; + if ptr.is_null() { + // Allocation has failed. + return ptr::null_mut(); + } + + // Create a correctly aligned pointer offset from the start of the allocated block, + // and write a header before it. + + let offset = layout.align() - (ptr as usize & (layout.align() - 1)); + // SAFETY: `MIN_ALIGN` <= `offset` <= `layout.align()` and the size of the allocated + // block is `layout.align() + layout.size()`. `aligned` will thus be a correctly aligned + // pointer inside the allocated block with at least `layout.size()` bytes after it and at + // least `MIN_ALIGN` bytes of padding before it. + let aligned = unsafe { ptr.add(offset) }; + // SAFETY: Because the size and alignment of a header is <= `MIN_ALIGN` and `aligned` + // is aligned to at least `MIN_ALIGN` and has at least `MIN_ALIGN` bytes of padding before + // it, it is safe to write a header directly before it. + unsafe { ptr::write((aligned as *mut Header).offset(-1), Header(ptr)) }; + + // SAFETY: The returned pointer does not point to the to the start of an allocated block, + // but there is a header readable directly before it containing the location of the start + // of the block. + aligned + } } +// All pointers returned by this allocator have, in addition to the guarantees of `GlobalAlloc`, the +// following properties: +// +// If the pointer was allocated or reallocated with a `layout` specifying an alignment <= `MIN_ALIGN` +// the pointer will be aligned to at least `MIN_ALIGN` and point to the start of the allocated block. +// +// If the pointer was allocated or reallocated with a `layout` specifying an alignment > `MIN_ALIGN` +// the pointer will be aligned to the specified alignment and not point to the start of the allocated block. +// Instead there will be a header readable directly before the returned pointer, containing the actual +// location of the start of the block. #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - allocate_with_flags(layout, 0) + // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System` + let zeroed = false; + unsafe { allocate(layout, zeroed) } } #[inline] unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - allocate_with_flags(layout, c::HEAP_ZERO_MEMORY) + // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System` + let zeroed = true; + unsafe { allocate(layout, zeroed) } } #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - if layout.align() <= MIN_ALIGN { - let err = c::HeapFree(c::GetProcessHeap(), 0, ptr as c::LPVOID); - debug_assert!(err != 0, "Failed to free heap memory: {}", c::GetLastError()); - } else { - let header = get_header(ptr); - let err = c::HeapFree(c::GetProcessHeap(), 0, header.0 as c::LPVOID); - debug_assert!(err != 0, "Failed to free heap memory: {}", c::GetLastError()); - } + let block = { + if layout.align() <= MIN_ALIGN { + ptr + } else { + // The location of the start of the block is stored in the padding before `ptr`. + + // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null + // and have a header readable directly before it. + unsafe { ptr::read((ptr as *mut Header).offset(-1)).0 } + } + }; + + // SAFETY: because `ptr` has been successfully allocated with this allocator, + // `HEAP` must have been successfully initialized. + let heap = unsafe { get_process_heap() }; + + // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, + // `block` is a pointer to the start of an allocated block. + unsafe { HeapFree(heap, 0, block as c::LPVOID) }; } #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { if layout.align() <= MIN_ALIGN { - c::HeapReAlloc(c::GetProcessHeap(), 0, ptr as c::LPVOID, new_size) as *mut u8 + // SAFETY: because `ptr` has been successfully allocated with this allocator, + // `HEAP` must have been successfully initialized. + let heap = unsafe { get_process_heap() }; + + // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, + // `ptr` is a pointer to the start of an allocated block. + // The returned pointer points to the start of an allocated block. + unsafe { HeapReAlloc(heap, 0, ptr as c::LPVOID, new_size) as *mut u8 } } else { - realloc_fallback(self, ptr, layout, new_size) + // SAFETY: `realloc_fallback` is implemented using `dealloc` and `alloc`, which will + // correctly handle `ptr` and return a pointer satisfying the guarantees of `System` + unsafe { realloc_fallback(self, ptr, layout, new_size) } } } } diff --git a/library/std/src/sys/windows/alloc/tests.rs b/library/std/src/sys/windows/alloc/tests.rs new file mode 100644 index 0000000000..674a3e1d92 --- /dev/null +++ b/library/std/src/sys/windows/alloc/tests.rs @@ -0,0 +1,9 @@ +use super::{Header, MIN_ALIGN}; +use crate::mem; + +#[test] +fn alloc_header() { + // Header must fit in the padding before an aligned pointer + assert!(mem::size_of::

() <= MIN_ALIGN); + assert!(mem::align_of::
() <= MIN_ALIGN); +} diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs index bcc2ea9ae0..f1264130fa 100644 --- a/library/std/src/sys/windows/args.rs +++ b/library/std/src/sys/windows/args.rs @@ -14,10 +14,6 @@ use crate::vec; use core::iter; -pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} - -pub unsafe fn cleanup() {} - pub fn args() -> Args { unsafe { let lp_cmd_line = c::GetCommandLineW(); @@ -164,19 +160,9 @@ pub struct Args { parsed_args_list: vec::IntoIter, } -pub struct ArgsInnerDebug<'a> { - args: &'a Args, -} - -impl<'a> fmt::Debug for ArgsInnerDebug<'a> { +impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.args.parsed_args_list.as_slice().fmt(f) - } -} - -impl Args { - pub fn inner_debug(&self) -> ArgsInnerDebug<'_> { - ArgsInnerDebug { args: self } + self.parsed_args_list.as_slice().fmt(f) } } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 9789ed085e..3e4176ef7f 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -285,8 +285,6 @@ pub const FD_SETSIZE: usize = 64; pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000; -pub const HEAP_ZERO_MEMORY: DWORD = 0x00000008; - pub const STATUS_SUCCESS: NTSTATUS = 0x00000000; #[repr(C)] @@ -1017,11 +1015,6 @@ extern "system" { timeout: *const timeval, ) -> c_int; - pub fn GetProcessHeap() -> HANDLE; - pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; - pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; - pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; - // >= Vista / Server 2008 // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw pub fn CreateSymbolicLinkW( diff --git a/library/std/src/sys/windows/ext/io.rs b/library/std/src/sys/windows/ext/io.rs index e75f9a4bfd..31b5d015ed 100644 --- a/library/std/src/sys/windows/ext/io.rs +++ b/library/std/src/sys/windows/ext/io.rs @@ -59,6 +59,7 @@ pub trait IntoRawHandle { #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for fs::File { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as RawHandle } @@ -108,6 +109,7 @@ impl<'a> AsRawHandle for io::StderrLock<'a> { #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawHandle for fs::File { + #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { let handle = handle as c::HANDLE; fs::File::from_inner(sys::fs::File::from_inner(handle)) @@ -116,6 +118,7 @@ impl FromRawHandle for fs::File { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawHandle for fs::File { + #[inline] fn into_raw_handle(self) -> RawHandle { self.into_inner().into_handle().into_raw() as *mut _ } @@ -161,18 +164,21 @@ pub trait IntoRawSocket { #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpStream { + #[inline] fn as_raw_socket(&self) -> RawSocket { *self.as_inner().socket().as_inner() } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpListener { + #[inline] fn as_raw_socket(&self) -> RawSocket { *self.as_inner().socket().as_inner() } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::UdpSocket { + #[inline] fn as_raw_socket(&self) -> RawSocket { *self.as_inner().socket().as_inner() } @@ -180,6 +186,7 @@ impl AsRawSocket for net::UdpSocket { #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::TcpStream { + #[inline] unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream { let sock = sys::net::Socket::from_inner(sock); net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock)) @@ -187,6 +194,7 @@ impl FromRawSocket for net::TcpStream { } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::TcpListener { + #[inline] unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener { let sock = sys::net::Socket::from_inner(sock); net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock)) @@ -194,6 +202,7 @@ impl FromRawSocket for net::TcpListener { } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::UdpSocket { + #[inline] unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { let sock = sys::net::Socket::from_inner(sock); net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock)) @@ -202,6 +211,7 @@ impl FromRawSocket for net::UdpSocket { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawSocket for net::TcpStream { + #[inline] fn into_raw_socket(self) -> RawSocket { self.into_inner().into_socket().into_inner() } @@ -209,6 +219,7 @@ impl IntoRawSocket for net::TcpStream { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawSocket for net::TcpListener { + #[inline] fn into_raw_socket(self) -> RawSocket { self.into_inner().into_socket().into_inner() } @@ -216,6 +227,7 @@ impl IntoRawSocket for net::TcpListener { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawSocket for net::UdpSocket { + #[inline] fn into_raw_socket(self) -> RawSocket { self.into_inner().into_socket().into_inner() } diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs index 67412e1677..67756b1553 100644 --- a/library/std/src/sys/windows/ext/process.rs +++ b/library/std/src/sys/windows/ext/process.rs @@ -19,6 +19,7 @@ impl FromRawHandle for process::Stdio { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::Child { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -33,6 +34,7 @@ impl IntoRawHandle for process::Child { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::ChildStdin { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -40,6 +42,7 @@ impl AsRawHandle for process::ChildStdin { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::ChildStdout { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -47,6 +50,7 @@ impl AsRawHandle for process::ChildStdout { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::ChildStderr { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } diff --git a/library/std/src/sys/windows/ext/thread.rs b/library/std/src/sys/windows/ext/thread.rs index 41c29f5b95..6bd02054f7 100644 --- a/library/std/src/sys/windows/ext/thread.rs +++ b/library/std/src/sys/windows/ext/thread.rs @@ -8,6 +8,7 @@ use crate::thread; #[stable(feature = "thread_extensions", since = "1.9.0")] impl AsRawHandle for thread::JoinHandle { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -15,6 +16,7 @@ impl AsRawHandle for thread::JoinHandle { #[stable(feature = "thread_extensions", since = "1.9.0")] impl IntoRawHandle for thread::JoinHandle { + #[inline] fn into_raw_handle(self) -> RawHandle { self.into_inner().into_handle().into_raw() as *mut _ } diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 307a47678c..8e6bd76f85 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -513,9 +513,9 @@ impl File { ) } _ => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::Other, - "Unsupported reparse point type", + &"Unsupported reparse point type", )); } }; @@ -802,7 +802,10 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { #[cfg(target_vendor = "uwp")] pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { - return Err(io::Error::new(io::ErrorKind::Other, "hard link are not supported on UWP")); + return Err(io::Error::new_const( + io::ErrorKind::Unsupported, + &"hard link are not supported on UWP", + )); } pub fn stat(path: &Path) -> io::Result { diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index fcbff59dec..ddb6ac5f55 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -49,8 +49,17 @@ cfg_if::cfg_if! { } } -#[cfg(not(test))] -pub fn init() {} +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +pub unsafe fn init(_argc: isize, _argv: *const *const u8) { + stack_overflow::init(); +} + +// 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() { + net::cleanup(); +} pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno as c::DWORD { @@ -78,6 +87,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { | 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, _ => {} } @@ -130,9 +140,9 @@ pub fn to_u16s>(s: S) -> crate::io::Result> { fn inner(s: &OsStr) -> crate::io::Result> { let mut maybe_result: Vec = s.encode_wide().collect(); if unrolled_find_u16s(0, &maybe_result).is_some() { - return Err(crate::io::Error::new( + return Err(crate::io::Error::new_const( ErrorKind::InvalidInput, - "strings passed to WinAPI cannot contain NULs", + &"strings passed to WinAPI cannot contain NULs", )); } maybe_result.push(0); diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 9e74454bc2..1ad13254c0 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -9,7 +9,7 @@ use crate::sync::Once; use crate::sys; use crate::sys::c; use crate::sys_common::net; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; use libc::{c_int, c_long, c_ulong, c_void}; @@ -26,23 +26,28 @@ pub mod netc { pub struct Socket(c::SOCKET); +static INIT: Once = Once::new(); + /// Checks whether the Windows socket interface has been started already, and /// if not, starts it. pub fn init() { - static START: Once = Once::new(); - - START.call_once(|| unsafe { + INIT.call_once(|| unsafe { let mut data: c::WSADATA = mem::zeroed(); let ret = c::WSAStartup( 0x202, // version 2.2 &mut data, ); assert_eq!(ret, 0); + }); +} - let _ = sys_common::at_exit(|| { +pub fn cleanup() { + if INIT.is_completed() { + // only close the socket interface if it has actually been started + unsafe { c::WSACleanup(); - }); - }); + } + } } /// Returns the last error from the Windows socket interface. @@ -136,9 +141,9 @@ impl Socket { } if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } @@ -164,7 +169,7 @@ impl Socket { unsafe { cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? }; match n { - 0 => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")), + 0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")), _ => { if writefds.fd_count != 1 { if let Some(e) = self.take_error()? { @@ -339,9 +344,9 @@ impl Socket { Some(dur) => { let timeout = sys::dur2timeout(dur); if timeout == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } timeout @@ -370,7 +375,7 @@ impl Socket { #[cfg(target_vendor = "uwp")] fn set_no_inherit(&self) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "Unavailable on UWP")) + Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Unavailable on UWP")) } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 83d37795ee..a579960614 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -19,9 +19,9 @@ use crate::sys::c; use crate::sys::cvt; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; -use crate::sys::mutex::Mutex; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; +use crate::sys_common::mutex::StaticMutex; use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::sys_common::AsInner; @@ -62,7 +62,7 @@ impl AsRef for EnvKey { fn ensure_no_nuls>(str: T) -> io::Result { if str.as_ref().encode_wide().any(|b| b == 0) { - Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")) + Err(io::Error::new_const(ErrorKind::InvalidInput, &"nul byte found in provided data")) } else { Ok(str) } @@ -94,10 +94,6 @@ pub struct StdioPipes { pub stderr: Option, } -struct DropGuard<'a> { - lock: &'a Mutex, -} - impl Command { pub fn new(program: &OsStr) -> Command { Command { @@ -209,8 +205,9 @@ impl Command { // // For more information, msdn also has an article about this race: // http://support.microsoft.com/kb/315939 - static CREATE_PROCESS_LOCK: Mutex = Mutex::new(); - let _guard = DropGuard::new(&CREATE_PROCESS_LOCK); + static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new(); + + let _guard = unsafe { CREATE_PROCESS_LOCK.lock() }; let mut pipes = StdioPipes { stdin: None, stdout: None, stderr: None }; let null = Stdio::Null; @@ -259,23 +256,6 @@ impl fmt::Debug for Command { } } -impl<'a> DropGuard<'a> { - fn new(lock: &'a Mutex) -> DropGuard<'a> { - unsafe { - lock.lock(); - DropGuard { lock } - } - } -} - -impl<'a> Drop for DropGuard<'a> { - fn drop(&mut self) { - unsafe { - self.lock.unlock(); - } - } -} - impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option) -> io::Result { match *self { diff --git a/library/std/src/sys/windows/stack_overflow.rs b/library/std/src/sys/windows/stack_overflow.rs index 187ad4e66c..39efb77820 100644 --- a/library/std/src/sys/windows/stack_overflow.rs +++ b/library/std/src/sys/windows/stack_overflow.rs @@ -37,5 +37,3 @@ pub unsafe fn init() { // Set the thread stack guarantee for the main thread. let _h = Handler::new(); } - -pub unsafe fn cleanup() {} diff --git a/library/std/src/sys/windows/stack_overflow_uwp.rs b/library/std/src/sys/windows/stack_overflow_uwp.rs index e7236cf359..afdf7f566a 100644 --- a/library/std/src/sys/windows/stack_overflow_uwp.rs +++ b/library/std/src/sys/windows/stack_overflow_uwp.rs @@ -9,5 +9,3 @@ impl Handler { } pub unsafe fn init() {} - -pub unsafe fn cleanup() {} diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs index ff21449716..be3141e46a 100644 --- a/library/std/src/sys/windows/stdio.rs +++ b/library/std/src/sys/windows/stdio.rs @@ -68,9 +68,9 @@ fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result { let utf8 = match str::from_utf8(&data[..len]) { Ok(s) => s, Err(ref e) if e.valid_up_to() == 0 => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Windows stdio in console mode does not support writing non-UTF-8 byte sequences", + &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences", )); } Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(), @@ -149,9 +149,9 @@ impl io::Read for Stdin { if buf.len() == 0 { return Ok(0); } else if buf.len() < 4 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "Windows stdin in console mode does not support a buffer too small to \ + &"Windows stdin in console mode does not support a buffer too small to \ guarantee holding one arbitrary UTF-8 character (4 bytes)", )); } @@ -243,9 +243,9 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result { } Err(_) => { // We can't really do any better than forget all data and return an error. - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Windows stdin in console mode does not support non-UTF-16 input; \ + &"Windows stdin in console mode does not support non-UTF-16 input; \ encountered unpaired surrogate", )); } diff --git a/library/std/src/sys_common/at_exit_imp.rs b/library/std/src/sys_common/at_exit_imp.rs deleted file mode 100644 index 90d5d3a789..0000000000 --- a/library/std/src/sys_common/at_exit_imp.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Implementation of running at_exit routines -//! -//! Documentation can be found on the `rt::at_exit` function. - -use crate::mem; -use crate::ptr; -use crate::sys_common::mutex::StaticMutex; - -type Queue = Vec>; - -// NB these are specifically not types from `std::sync` as they currently rely -// on poisoning and this module needs to operate at a lower level than requiring -// the thread infrastructure to be in place (useful on the borders of -// initialization/destruction). -// It is UB to attempt to acquire this mutex reentrantly! -static LOCK: StaticMutex = StaticMutex::new(); -static mut QUEUE: *mut Queue = ptr::null_mut(); - -const DONE: *mut Queue = 1_usize as *mut _; - -// The maximum number of times the cleanup routines will be run. While running -// the at_exit closures new ones may be registered, and this count is the number -// of times the new closures will be allowed to register successfully. After -// this number of iterations all new registrations will return `false`. -const ITERS: usize = 10; - -unsafe fn init() -> bool { - if QUEUE.is_null() { - let state: Box = box Vec::new(); - QUEUE = Box::into_raw(state); - } else if QUEUE == DONE { - // can't re-init after a cleanup - return false; - } - - true -} - -pub fn cleanup() { - for i in 1..=ITERS { - unsafe { - let queue = { - let _guard = LOCK.lock(); - mem::replace(&mut QUEUE, if i == ITERS { DONE } else { ptr::null_mut() }) - }; - - // make sure we're not recursively cleaning up - assert!(queue != DONE); - - // If we never called init, not need to cleanup! - if !queue.is_null() { - let queue: Box = Box::from_raw(queue); - for to_run in *queue { - // We are not holding any lock, so reentrancy is fine. - to_run(); - } - } - } - } -} - -pub fn push(f: Box) -> bool { - unsafe { - let _guard = LOCK.lock(); - if init() { - // We are just moving `f` around, not calling it. - // There is no possibility of reentrancy here. - (*QUEUE).push(f); - true - } else { - false - } - } -} diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs index 6bdb26cd07..30908824dd 100644 --- a/library/std/src/sys_common/fs.rs +++ b/library/std/src/sys_common/fs.rs @@ -4,15 +4,17 @@ use crate::fs; use crate::io::{self, Error, ErrorKind}; use crate::path::Path; +pub(crate) const NOT_FILE_ERROR: Error = Error::new_const( + ErrorKind::InvalidInput, + &"the source path is neither a regular file nor a symlink to a regular file", +); + pub fn copy(from: &Path, to: &Path) -> io::Result { let mut reader = fs::File::open(from)?; let metadata = reader.metadata()?; if !metadata.is_file() { - return Err(Error::new( - ErrorKind::InvalidInput, - "the source path is not an existing regular file", - )); + return Err(NOT_FILE_ERROR); } let mut writer = fs::File::create(to)?; diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 660f0e0df9..7fa6977f2a 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -8,9 +8,11 @@ //! rest of `std` is complex, with dependencies going in all //! directions: `std` depending on `sys_common`, `sys_common` //! depending on `sys`, and `sys` depending on `sys_common` and `std`. -//! Ideally `sys_common` would be split into two and the dependencies -//! between them all would form a dag, facilitating the extraction of -//! `std::sys` from the standard library. +//! This is because `sys_common` not only contains platform-independent code, +//! but also code that is shared between the different platforms in `sys`. +//! Ideally all that shared code should be moved to `sys::common`, +//! and the dependencies between `std`, `sys_common` and `sys` all would form a dag. +//! Progress on this is tracked in #84187. #![allow(missing_docs)] #![allow(missing_debug_implementations)] @@ -18,36 +20,6 @@ #[cfg(test)] mod tests; -use crate::sync::Once; -use crate::sys; - -macro_rules! rtabort { - ($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*))) -} - -macro_rules! rtassert { - ($e:expr) => { - if !$e { - rtabort!(concat!("assertion failed: ", stringify!($e))); - } - }; -} - -#[allow(unused_macros)] // not used on all platforms -macro_rules! rtunwrap { - ($ok:ident, $e:expr) => { - match $e { - $ok(v) => v, - ref err => { - let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug - rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) - } - } - }; -} - -pub mod alloc; -pub mod at_exit_imp; pub mod backtrace; pub mod bytestring; pub mod condvar; @@ -58,9 +30,10 @@ pub mod mutex; // when generating documentation. #[cfg(any(doc, not(windows)))] pub mod os_str_bytes; -pub mod poison; pub mod process; pub mod remutex; +#[macro_use] +pub mod rt; pub mod rwlock; pub mod thread; pub mod thread_info; @@ -108,30 +81,6 @@ pub trait FromInner { fn from_inner(inner: Inner) -> Self; } -/// Enqueues a procedure to run when the main thread exits. -/// -/// Currently these closures are only run once the main *Rust* thread exits. -/// Once the `at_exit` handlers begin running, more may be enqueued, but not -/// infinitely so. Eventually a handler registration will be forced to fail. -/// -/// Returns `Ok` if the handler was successfully registered, meaning that the -/// closure will be run once the main thread exits. Returns `Err` to indicate -/// that the closure could not be registered, meaning that it is not scheduled -/// to be run. -pub fn at_exit(f: F) -> Result<(), ()> { - if at_exit_imp::push(Box::new(f)) { Ok(()) } else { Err(()) } -} - -/// One-time runtime cleanup. -pub fn cleanup() { - static CLEANUP: Once = Once::new(); - CLEANUP.call_once(|| unsafe { - sys::args::cleanup(); - sys::stack_overflow::cleanup(); - at_exit_imp::cleanup(); - }); -} - // Computes (value*numer)/denom without overflow, as long as both // (numer*denom) and the overall result fit into i64 (which is the case // for our time conversions). diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 38ba0d2fbd..d5f29c4a43 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -108,7 +108,7 @@ pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result *(storage as *const _ as *const c::sockaddr_in6) }))) } - _ => Err(Error::new(ErrorKind::InvalidInput, "invalid argument")), + _ => Err(Error::new_const(ErrorKind::InvalidInput, &"invalid argument")), } } @@ -171,7 +171,7 @@ impl TryFrom<&str> for LookupHost { ($e:expr, $msg:expr) => { match $e { Some(r) => r, - None => return Err(io::Error::new(io::ErrorKind::InvalidInput, $msg)), + None => return Err(io::Error::new_const(io::ErrorKind::InvalidInput, &$msg)), } }; } diff --git a/library/std/src/sys_common/os_str_bytes.rs b/library/std/src/sys_common/os_str_bytes.rs index 302c519740..32705c432f 100644 --- a/library/std/src/sys_common/os_str_bytes.rs +++ b/library/std/src/sys_common/os_str_bytes.rs @@ -14,7 +14,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; use core::str::lossy::Utf8Lossy; -#[derive(Clone, Hash)] +#[derive(Hash)] pub(crate) struct Buf { pub inner: Vec, } @@ -53,6 +53,18 @@ impl fmt::Display for Buf { } } +impl Clone for Buf { + #[inline] + fn clone(&self) -> Self { + Buf { inner: self.inner.clone() } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner) + } +} + impl IntoInner> for Buf { fn into_inner(self) -> Vec { self.inner diff --git a/library/std/src/sys_common/rt.rs b/library/std/src/sys_common/rt.rs new file mode 100644 index 0000000000..c70f2ecc04 --- /dev/null +++ b/library/std/src/sys_common/rt.rs @@ -0,0 +1,64 @@ +#![deny(unsafe_op_in_unsafe_fn)] + +use crate::sync::Once; +use crate::sys; +use crate::sys_common::thread_info; +use crate::thread::Thread; + +// One-time runtime initialization. +// Runs before `main`. +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +#[cfg_attr(test, allow(dead_code))] +pub unsafe fn init(argc: isize, argv: *const *const u8) { + unsafe { + sys::init(argc, argv); + + let main_guard = sys::thread::guard::init(); + // Next, set up the current Thread with the guard information we just + // created. Note that this isn't necessary in general for new threads, + // but we just do this to name the main thread and to give it correct + // info about the stack bounds. + let thread = Thread::new(Some("main".to_owned())); + thread_info::set(main_guard, thread); + } +} + +// One-time runtime cleanup. +// Runs after `main` or at program exit. +// NOTE: this is not guaranteed to run, for example when the program aborts. +#[cfg_attr(test, allow(dead_code))] +pub fn cleanup() { + static CLEANUP: Once = Once::new(); + CLEANUP.call_once(|| unsafe { + // Flush stdout and disable buffering. + crate::io::cleanup(); + // SAFETY: Only called once during runtime cleanup. + sys::cleanup(); + }); +} + +macro_rules! rtabort { + ($($t:tt)*) => (crate::sys_common::util::abort(format_args!($($t)*))) +} + +macro_rules! rtassert { + ($e:expr) => { + if !$e { + rtabort!(concat!("assertion failed: ", stringify!($e))); + } + }; +} + +#[allow(unused_macros)] // not used on all platforms +macro_rules! rtunwrap { + ($ok:ident, $e:expr) => { + match $e { + $ok(v) => v, + ref err => { + let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug + rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) + } + } + }; +} diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs index 70b31b19f8..3705d641a1 100644 --- a/library/std/src/sys_common/rwlock.rs +++ b/library/std/src/sys_common/rwlock.rs @@ -86,62 +86,3 @@ impl RWLock { self.0.destroy() } } - -// the cfg annotations only exist due to dead code warnings. the code itself is portable -#[cfg(unix)] -pub struct StaticRWLock(RWLock); - -#[cfg(unix)] -impl StaticRWLock { - pub const fn new() -> StaticRWLock { - StaticRWLock(RWLock::new()) - } - - /// Acquires shared access to the underlying lock, blocking the current - /// thread to do so. - /// - /// The lock is automatically unlocked when the returned guard is dropped. - #[inline] - pub fn read_with_guard(&'static self) -> RWLockReadGuard { - // SAFETY: All methods require static references, therefore self - // cannot be moved between invocations. - unsafe { - self.0.read(); - } - RWLockReadGuard(&self.0) - } - - /// Acquires write access to the underlying lock, blocking the current thread - /// to do so. - /// - /// The lock is automatically unlocked when the returned guard is dropped. - #[inline] - pub fn write_with_guard(&'static self) -> RWLockWriteGuard { - // SAFETY: All methods require static references, therefore self - // cannot be moved between invocations. - unsafe { - self.0.write(); - } - RWLockWriteGuard(&self.0) - } -} - -#[cfg(unix)] -pub struct RWLockReadGuard(&'static RWLock); - -#[cfg(unix)] -impl Drop for RWLockReadGuard { - fn drop(&mut self) { - unsafe { self.0.read_unlock() } - } -} - -#[cfg(unix)] -pub struct RWLockWriteGuard(&'static RWLock); - -#[cfg(unix)] -impl Drop for RWLockWriteGuard { - fn drop(&mut self) { - unsafe { self.0.write_unlock() } - } -} diff --git a/library/std/src/thread/available_concurrency.rs b/library/std/src/thread/available_concurrency.rs index 64a5f89890..e8cdde8801 100644 --- a/library/std/src/thread/available_concurrency.rs +++ b/library/std/src/thread/available_concurrency.rs @@ -64,7 +64,7 @@ cfg_if::cfg_if! { sysinfo.dwNumberOfProcessors as usize }; match res { - 0 => Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")), + 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) }), } } @@ -81,7 +81,7 @@ cfg_if::cfg_if! { fn available_concurrency_internal() -> io::Result { match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { -1 => Err(io::Error::last_os_error()), - 0 => Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")), + 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) }), } } @@ -114,7 +114,7 @@ cfg_if::cfg_if! { if res == -1 { return Err(io::Error::last_os_error()); } else if cpus == 0 { - return Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")); + 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) }) @@ -142,7 +142,7 @@ cfg_if::cfg_if! { if res == -1 { return Err(io::Error::last_os_error()); } else if cpus == 0 { - return Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")); + 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) }) @@ -150,7 +150,7 @@ cfg_if::cfg_if! { } else { // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re fn available_concurrency_internal() -> io::Result { - Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")) + Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")) } } } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index dd438858c3..abd5b77848 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -100,7 +100,7 @@ pub struct LocalKey { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for LocalKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("LocalKey { .. }") + f.debug_struct("LocalKey").finish_non_exhaustive() } } @@ -133,6 +133,15 @@ macro_rules! thread_local { // empty (base case for the recursion) () => {}; + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => ( + $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); + $crate::thread_local!($($rest)*); + ); + + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => ( + $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); + ); + // process multiple declarations ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init); @@ -151,6 +160,101 @@ macro_rules! thread_local { #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)] #[allow_internal_unsafe] macro_rules! __thread_local_inner { + // used to generate the `LocalKey` value for const-initialized thread locals + (@key $t:ty, const $init:expr) => {{ + unsafe fn __getit() -> $crate::option::Option<&'static $t> { + const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local(); + + // wasm without atomics maps directly to `static mut`, and dtors + // aren't implemented because thread dtors aren't really a thing + // on wasm right now + // + // FIXME(#84224) this should come after the `target_thread_local` + // block. + #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] + { + static mut VAL: $t = $init; + Some(&VAL) + } + + // If the platform has support for `#[thread_local]`, use it. + #[cfg(all( + target_thread_local, + not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + ))] + { + // If a dtor isn't needed we can do something "very raw" and + // just get going. + if !$crate::mem::needs_drop::<$t>() { + #[thread_local] + static mut VAL: $t = $init; + unsafe { + return Some(&VAL) + } + } + + #[thread_local] + static mut VAL: $t = $init; + // 0 == dtor not registered + // 1 == dtor registered, dtor not run + // 2 == dtor registered and is running or has run + #[thread_local] + static mut STATE: u8 = 0; + + unsafe extern "C" fn destroy(ptr: *mut u8) { + let ptr = ptr as *mut $t; + + unsafe { + debug_assert_eq!(STATE, 1); + STATE = 2; + $crate::ptr::drop_in_place(ptr); + } + } + + unsafe { + match STATE { + // 0 == we haven't registered a destructor, so do + // so now. + 0 => { + $crate::thread::__FastLocalKeyInner::<$t>::register_dtor( + $crate::ptr::addr_of_mut!(VAL) as *mut u8, + destroy, + ); + STATE = 1; + Some(&VAL) + } + // 1 == the destructor is registered and the value + // is valid, so return the pointer. + 1 => Some(&VAL), + // otherwise the destructor has already run, so we + // can't give access. + _ => None, + } + } + } + + // On platforms without `#[thread_local]` we fall back to the + // same implementation as below for os thread locals. + #[cfg(all( + not(target_thread_local), + not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + ))] + { + #[inline] + const fn __init() -> $t { $init } + static __KEY: $crate::thread::__OsLocalKeyInner<$t> = + $crate::thread::__OsLocalKeyInner::new(); + #[allow(unused_unsafe)] + unsafe { __KEY.get(__init) } + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + }}; + + // used to generate the `LocalKey` value for `thread_local!` (@key $t:ty, $init:expr) => { { #[inline] @@ -188,9 +292,9 @@ macro_rules! __thread_local_inner { } } }; - ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => { + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = - $crate::__thread_local_inner!(@key $t, $init); + $crate::__thread_local_inner!(@key $t, $($init)*); } } @@ -368,7 +472,7 @@ pub mod statik { impl fmt::Debug for Key { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Key { .. }") + f.debug_struct("Key").finish_non_exhaustive() } } @@ -433,7 +537,7 @@ pub mod fast { impl fmt::Debug for Key { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Key { .. }") + f.debug_struct("Key").finish_non_exhaustive() } } @@ -442,6 +546,15 @@ pub mod fast { Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } } + // note that this is just a publically-callable function only for the + // const-initialized form of thread locals, basically a way to call the + // free `register_dtor` function defined elsewhere in libstd. + pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + unsafe { + register_dtor(a, dtor); + } + } + pub unsafe fn get T>(&self, init: F) -> Option<&'static T> { // SAFETY: See the definitions of `LazyKeyInner::get` and // `try_initialize` for more informations. @@ -538,7 +651,7 @@ pub mod os { impl fmt::Debug for Key { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Key { .. }") + f.debug_struct("Key").finish_non_exhaustive() } } diff --git a/library/std/src/thread/local/tests.rs b/library/std/src/thread/local/tests.rs index 4fb0a08908..f33d612961 100644 --- a/library/std/src/thread/local/tests.rs +++ b/library/std/src/thread/local/tests.rs @@ -1,6 +1,7 @@ use crate::cell::{Cell, UnsafeCell}; +use crate::sync::atomic::{AtomicU8, Ordering}; use crate::sync::mpsc::{channel, Sender}; -use crate::thread; +use crate::thread::{self, LocalKey}; use crate::thread_local; struct Foo(Sender<()>); @@ -15,74 +16,90 @@ impl Drop for Foo { #[test] fn smoke_no_dtor() { thread_local!(static FOO: Cell = Cell::new(1)); + run(&FOO); + thread_local!(static FOO2: Cell = const { Cell::new(1) }); + run(&FOO2); - FOO.with(|f| { - assert_eq!(f.get(), 1); - f.set(2); - }); - let (tx, rx) = channel(); - let _t = thread::spawn(move || { - FOO.with(|f| { + fn run(key: &'static LocalKey>) { + key.with(|f| { assert_eq!(f.get(), 1); + f.set(2); }); - tx.send(()).unwrap(); - }); - rx.recv().unwrap(); + let t = thread::spawn(move || { + key.with(|f| { + assert_eq!(f.get(), 1); + }); + }); + t.join().unwrap(); - FOO.with(|f| { - assert_eq!(f.get(), 2); - }); + key.with(|f| { + assert_eq!(f.get(), 2); + }); + } } #[test] fn states() { - struct Foo; + struct Foo(&'static LocalKey); impl Drop for Foo { fn drop(&mut self) { - assert!(FOO.try_with(|_| ()).is_err()); + assert!(self.0.try_with(|_| ()).is_err()); } } - thread_local!(static FOO: Foo = Foo); - thread::spawn(|| { - assert!(FOO.try_with(|_| ()).is_ok()); - }) - .join() - .ok() - .expect("thread panicked"); + thread_local!(static FOO: Foo = Foo(&FOO)); + run(&FOO); + thread_local!(static FOO2: Foo = const { Foo(&FOO2) }); + run(&FOO2); + + fn run(foo: &'static LocalKey) { + thread::spawn(move || { + assert!(foo.try_with(|_| ()).is_ok()); + }) + .join() + .unwrap(); + } } #[test] fn smoke_dtor() { thread_local!(static FOO: UnsafeCell> = UnsafeCell::new(None)); + run(&FOO); + thread_local!(static FOO2: UnsafeCell> = const { UnsafeCell::new(None) }); + run(&FOO2); - let (tx, rx) = channel(); - let _t = thread::spawn(move || unsafe { - let mut tx = Some(tx); - FOO.with(|f| { - *f.get() = Some(Foo(tx.take().unwrap())); + fn run(key: &'static LocalKey>>) { + let (tx, rx) = channel(); + let t = thread::spawn(move || unsafe { + let mut tx = Some(tx); + key.with(|f| { + *f.get() = Some(Foo(tx.take().unwrap())); + }); }); - }); - rx.recv().unwrap(); + rx.recv().unwrap(); + t.join().unwrap(); + } } #[test] fn circular() { - struct S1; - struct S2; + struct S1(&'static LocalKey>>, &'static LocalKey>>); + struct S2(&'static LocalKey>>, &'static LocalKey>>); thread_local!(static K1: UnsafeCell> = UnsafeCell::new(None)); thread_local!(static K2: UnsafeCell> = UnsafeCell::new(None)); - static mut HITS: u32 = 0; + thread_local!(static K3: UnsafeCell> = const { UnsafeCell::new(None) }); + thread_local!(static K4: UnsafeCell> = const { UnsafeCell::new(None) }); + static mut HITS: usize = 0; impl Drop for S1 { fn drop(&mut self) { unsafe { HITS += 1; - if K2.try_with(|_| ()).is_err() { + if self.1.try_with(|_| ()).is_err() { assert_eq!(HITS, 3); } else { if HITS == 1 { - K2.with(|s| *s.get() = Some(S2)); + self.1.with(|s| *s.get() = Some(S2(self.0, self.1))); } else { assert_eq!(HITS, 3); } @@ -94,38 +111,54 @@ fn circular() { fn drop(&mut self) { unsafe { HITS += 1; - assert!(K1.try_with(|_| ()).is_ok()); + assert!(self.0.try_with(|_| ()).is_ok()); assert_eq!(HITS, 2); - K1.with(|s| *s.get() = Some(S1)); + self.0.with(|s| *s.get() = Some(S1(self.0, self.1))); } } } thread::spawn(move || { - drop(S1); + drop(S1(&K1, &K2)); }) .join() - .ok() - .expect("thread panicked"); + .unwrap(); + + unsafe { + HITS = 0; + } + + thread::spawn(move || { + drop(S1(&K3, &K4)); + }) + .join() + .unwrap(); } #[test] fn self_referential() { - struct S1; + struct S1(&'static LocalKey>>); + thread_local!(static K1: UnsafeCell> = UnsafeCell::new(None)); + thread_local!(static K2: UnsafeCell> = const { UnsafeCell::new(None) }); impl Drop for S1 { fn drop(&mut self) { - assert!(K1.try_with(|_| ()).is_err()); + assert!(self.0.try_with(|_| ()).is_err()); } } thread::spawn(move || unsafe { - K1.with(|s| *s.get() = Some(S1)); + K1.with(|s| *s.get() = Some(S1(&K1))); + }) + .join() + .unwrap(); + + thread::spawn(move || unsafe { + K2.with(|s| *s.get() = Some(S1(&K2))); }) .join() - .ok() - .expect("thread panicked"); + .unwrap(); } // Note that this test will deadlock if TLS destructors aren't run (this @@ -152,3 +185,133 @@ fn dtors_in_dtors_in_dtors() { }); rx.recv().unwrap(); } + +#[test] +fn dtors_in_dtors_in_dtors_const_init() { + struct S1(Sender<()>); + thread_local!(static K1: UnsafeCell> = const { UnsafeCell::new(None) }); + thread_local!(static K2: UnsafeCell> = const { UnsafeCell::new(None) }); + + impl Drop for S1 { + fn drop(&mut self) { + let S1(ref tx) = *self; + unsafe { + let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone()))); + } + } + } + + let (tx, rx) = channel(); + let _t = thread::spawn(move || unsafe { + let mut tx = Some(tx); + K1.with(|s| *s.get() = Some(S1(tx.take().unwrap()))); + }); + rx.recv().unwrap(); +} + +// This test tests that TLS destructors have run before the thread joins. The +// test has no false positives (meaning: if the test fails, there's actually +// an ordering problem). It may have false negatives, where the test passes but +// join is not guaranteed to be after the TLS destructors. However, false +// negatives should be exceedingly rare due to judicious use of +// thread::yield_now and running the test several times. +#[test] +fn join_orders_after_tls_destructors() { + // We emulate a synchronous MPSC rendezvous channel using only atomics and + // thread::yield_now. We can't use std::mpsc as the implementation itself + // may rely on thread locals. + // + // The basic state machine for an SPSC rendezvous channel is: + // FRESH -> THREAD1_WAITING -> MAIN_THREAD_RENDEZVOUS + // where the first transition is done by the “receiving” thread and the 2nd + // transition is done by the “sending” thread. + // + // We add an additional state `THREAD2_LAUNCHED` between `FRESH` and + // `THREAD1_WAITING` to block until all threads are actually running. + // + // A thread that joins on the “receiving” thread completion should never + // observe the channel in the `THREAD1_WAITING` state. If this does occur, + // we switch to the “poison” state `THREAD2_JOINED` and panic all around. + // (This is equivalent to “sending” from an alternate producer thread.) + const FRESH: u8 = 0; + const THREAD2_LAUNCHED: u8 = 1; + const THREAD1_WAITING: u8 = 2; + const MAIN_THREAD_RENDEZVOUS: u8 = 3; + const THREAD2_JOINED: u8 = 4; + static SYNC_STATE: AtomicU8 = AtomicU8::new(FRESH); + + for _ in 0..10 { + SYNC_STATE.store(FRESH, Ordering::SeqCst); + + let jh = thread::Builder::new() + .name("thread1".into()) + .spawn(move || { + struct TlDrop; + + impl Drop for TlDrop { + fn drop(&mut self) { + let mut sync_state = SYNC_STATE.swap(THREAD1_WAITING, Ordering::SeqCst); + loop { + match sync_state { + THREAD2_LAUNCHED | THREAD1_WAITING => thread::yield_now(), + MAIN_THREAD_RENDEZVOUS => break, + THREAD2_JOINED => panic!( + "Thread 1 still running after thread 2 joined on thread 1" + ), + v => unreachable!("sync state: {}", v), + } + sync_state = SYNC_STATE.load(Ordering::SeqCst); + } + } + } + + thread_local! { + static TL_DROP: TlDrop = TlDrop; + } + + TL_DROP.with(|_| {}); + + loop { + match SYNC_STATE.load(Ordering::SeqCst) { + FRESH => thread::yield_now(), + THREAD2_LAUNCHED => break, + v => unreachable!("sync state: {}", v), + } + } + }) + .unwrap(); + + let jh2 = thread::Builder::new() + .name("thread2".into()) + .spawn(move || { + assert_eq!(SYNC_STATE.swap(THREAD2_LAUNCHED, Ordering::SeqCst), FRESH); + jh.join().unwrap(); + match SYNC_STATE.swap(THREAD2_JOINED, Ordering::SeqCst) { + MAIN_THREAD_RENDEZVOUS => return, + THREAD2_LAUNCHED | THREAD1_WAITING => { + panic!("Thread 2 running after thread 1 join before main thread rendezvous") + } + v => unreachable!("sync state: {:?}", v), + } + }) + .unwrap(); + + loop { + match SYNC_STATE.compare_exchange_weak( + THREAD1_WAITING, + MAIN_THREAD_RENDEZVOUS, + Ordering::SeqCst, + Ordering::SeqCst, + ) { + Ok(_) => break, + Err(FRESH) => thread::yield_now(), + Err(THREAD2_LAUNCHED) => thread::yield_now(), + Err(THREAD2_JOINED) => { + panic!("Main thread rendezvous after thread 2 joined thread 1") + } + v => unreachable!("sync state: {:?}", v), + } + } + jh2.join().unwrap(); + } +} diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 0ef848ff0c..30d8c2a1b6 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -204,6 +204,13 @@ pub use self::local::os::Key as __OsLocalKeyInner; #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; +// This is only used to make thread locals with `const { .. }` initialization +// expressions unstable. If and/or when that syntax is stabilized with thread +// locals this will simply be removed. +#[doc(hidden)] +#[unstable(feature = "thread_local_const_init", issue = "84223")] +pub const fn require_unstable_const_init_thread_local() {} + //////////////////////////////////////////////////////////////////////////////// // Builder //////////////////////////////////////////////////////////////////////////////// @@ -1176,7 +1183,10 @@ impl Thread { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Thread { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Thread").field("id", &self.id()).field("name", &self.name()).finish() + f.debug_struct("Thread") + .field("id", &self.id()) + .field("name", &self.name()) + .finish_non_exhaustive() } } @@ -1403,7 +1413,7 @@ impl IntoInner for JoinHandle { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for JoinHandle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("JoinHandle { .. }") + f.debug_struct("JoinHandle").finish_non_exhaustive() } } diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index fdae25c903..c7cec5a858 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -90,7 +90,8 @@ jobs: - thumbv7em-none-eabihf # macOS targets - - x86_64-apple-darwin + #- x86_64-apple-darwin + - aarch64-apple-darwin # FIXME: gh-actions build environment doesn't have linker support # - i686-apple-darwin @@ -132,10 +133,14 @@ jobs: os: ubuntu-latest - target: wasm32-wasi os: ubuntu-latest + - target: aarch64-apple-darwin + os: macos-latest + norun: true - target: aarch64-unknown-linux-gnu os: ubuntu-latest - - target: x86_64-apple-darwin - os: macos-latest + # Temporarily disabled because otool crashes with "Out of memory", seems Github CI issue + #- target: x86_64-apple-darwin + # os: macos-latest - target: x86_64-pc-windows-msvc os: windows-latest - target: i686-pc-windows-msvc @@ -183,6 +188,12 @@ jobs: rustup default nightly rustup target add ${{ matrix.target }} if: "!endsWith(matrix.target, 'emulated')" + - name: Setup (aarch64-apple-darwin) + run: | + sudo xcode-select -s /Applications/Xcode_12.2.app/ + echo "SDKROOT=$(xcrun -sdk macosx11.0 --show-sdk-path)" >> $GITHUB_ENV + echo "MACOS_DEPLOYMENT_TARGET=$(xcrun -sdk macosx11.0 --show-sdk-platform-version)" >> $GITHUB_ENV + if: matrix.target == 'aarch64-apple-darwin' - run: cargo generate-lockfile # Configure some env vars based on matrix configuration diff --git a/library/stdarch/ci/docker/i586-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/i586-unknown-linux-gnu/Dockerfile index 01093698f6..0e4d1c6eb4 100644 --- a/library/stdarch/ci/docker/i586-unknown-linux-gnu/Dockerfile +++ b/library/stdarch/ci/docker/i586-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-multilib \ libc6-dev \ diff --git a/library/stdarch/ci/docker/i686-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/i686-unknown-linux-gnu/Dockerfile index 01093698f6..0e4d1c6eb4 100644 --- a/library/stdarch/ci/docker/i686-unknown-linux-gnu/Dockerfile +++ b/library/stdarch/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-multilib \ libc6-dev \ diff --git a/library/stdarch/ci/docker/wasm32-wasi/Dockerfile b/library/stdarch/ci/docker/wasm32-wasi/Dockerfile index 9bb4dc6f1d..eca3f61c70 100644 --- a/library/stdarch/ci/docker/wasm32-wasi/Dockerfile +++ b/library/stdarch/ci/docker/wasm32-wasi/Dockerfile @@ -7,8 +7,8 @@ RUN apt-get update -y && apt-get install -y --no-install-recommends \ xz-utils \ clang -RUN curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v0.19.0/wasmtime-v0.19.0-x86_64-linux.tar.xz | tar xJf - -ENV PATH=$PATH:/wasmtime-v0.19.0-x86_64-linux +RUN curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v0.22.1/wasmtime-v0.22.1-x86_64-linux.tar.xz | tar xJf - +ENV PATH=$PATH:/wasmtime-v0.22.1-x86_64-linux ENV CARGO_TARGET_WASM32_WASI_RUNNER="wasmtime \ --enable-simd \ diff --git a/library/stdarch/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile b/library/stdarch/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile index 40dbebdcc9..b7fc930523 100644 --- a/library/stdarch/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile +++ b/library/stdarch/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libc6-dev \ @@ -10,4 +10,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ RUN wget https://github.com/gnzlbg/intel_sde/raw/master/sde-external-8.35.0-2019-03-11-lin.tar.bz2 RUN tar -xjf sde-external-8.35.0-2019-03-11-lin.tar.bz2 +ENV SKIP_TESTS="avx512bf16" ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="/sde-external-8.35.0-2019-03-11-lin/sde64 -rtm_mode full --" diff --git a/library/stdarch/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/x86_64-unknown-linux-gnu/Dockerfile index db64f7f915..dc4c4e5989 100644 --- a/library/stdarch/ci/docker/x86_64-unknown-linux-gnu/Dockerfile +++ b/library/stdarch/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libc6-dev \ diff --git a/library/stdarch/ci/run.sh b/library/stdarch/ci/run.sh index 4f4eaa1cfc..699c89cecb 100755 --- a/library/stdarch/ci/run.sh +++ b/library/stdarch/ci/run.sh @@ -56,6 +56,9 @@ cargo_test() { ;; esac + if [ "$SKIP_TESTS" != "" ]; then + cmd="$cmd --skip "$SKIP_TESTS + fi $cmd } diff --git a/library/stdarch/crates/assert-instr-macro/src/lib.rs b/library/stdarch/crates/assert-instr-macro/src/lib.rs index 7f2c9902e2..0b3d5b725d 100644 --- a/library/stdarch/crates/assert-instr-macro/src/lib.rs +++ b/library/stdarch/crates/assert-instr-macro/src/lib.rs @@ -7,6 +7,7 @@ //! The procedural macro here is relatively simple, it simply appends a //! `#[test]` function to the original token stream which asserts that the //! function itself contains the relevant instruction. +#![deny(rust_2018_idioms)] extern crate proc_macro; extern crate proc_macro2; @@ -162,7 +163,7 @@ struct Invoc { } impl syn::parse::Parse for Invoc { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { use syn::{ext::IdentExt, Token}; let mut instr = String::new(); diff --git a/library/stdarch/crates/core_arch/avx512bw.md b/library/stdarch/crates/core_arch/avx512bw.md index a9ce7d43e1..fa50c66e6c 100644 --- a/library/stdarch/crates/core_arch/avx512bw.md +++ b/library/stdarch/crates/core_arch/avx512bw.md @@ -1,5 +1,35 @@ ["AVX512BW"]

+ * [x] [`_mm512_loadu_epi16`] + * [_] [`_mm512_mask_loadu_epi16`] //need i1 + * [_] [`_mm512_maskz_loadu_epi16`] //need i1 + * [x] [`_mm_loadu_epi16`] + * [_] [`_mm_mask_loadu_epi16`] //need i1 + * [_] [`_mm_maskz_loadu_epi16`] //need i1 + * [x] [`_mm256_loadu_epi16`] + * [_] [`_mm256_mask_loadu_epi16`] //need i1 + * [_] [`_mm256_maskz_loadu_epi16`] //need i1 + * [x] [`_mm512_loadu_epi8`] + * [_] [`_mm512_mask_loadu_epi8`] //need i1 + * [_] [`_mm512_maskz_loadu_epi8`] //need i1 + * [x] [`_mm_loadu_epi8`] + * [_] [`_mm_mask_loadu_epi8`] //need i1 + * [_] [`_mm_maskz_loadu_epi8`] //need i1 + * [x] [`_mm256_loadu_epi8`] + * [_] [`_mm256_mask_loadu_epi8`] //need i1 + * [_] [`_mm256_maskz_loadu_epi8`] //need i1 + * [_] [`_mm512_mask_storeu_epi16`] + * [x] [`_mm512_storeu_epi16`] + * [_] [`_mm_mask_storeu_epi16`] //need i1 + * [x] [`_mm_storeu_epi16`] + * [_] [`_mm256_mask_storeu_epi16`] //need i1 + * [x] [`_mm256_storeu_epi16`] + * [_] [`_mm512_mask_storeu_epi8`] //need i1 + * [x] [`_mm512_storeu_epi8`] + * [_] [`_mm_mask_storeu_epi8`] //need i1 + * [x] [`_mm_storeu_epi8`] + * [_] [`_mm256_mask_storeu_epi8`] //need i1 + * [x] [`_mm256_storeu_epi8`] * [x] [`_mm512_abs_epi16`] * [x] [`_mm512_mask_abs_epi16`] * [x] [`_mm512_maskz_abs_epi16`] @@ -59,6 +89,10 @@ * [x] [`_mm512_alignr_epi8`] * [x] [`_mm512_mask_alignr_epi8`] * [x] [`_mm512_maskz_alignr_epi8`] + * [x] [`_mm_mask_alignr_epi8`] + * [x] [`_mm_maskz_alignr_epi8`] + * [x] [`_mm256_mask_alignr_epi8`] + * [x] [`_mm256_maskz_alignr_epi8`] * [x] [`_mm512_avg_epu16`] * [x] [`_mm512_mask_avg_epu16`] * [x] [`_mm512_maskz_avg_epu16`] @@ -97,85 +131,231 @@ * [x] [`_mm512_bsrli_epi128`] * [x] [`_mm512_cmp_epi16_mask`] * [x] [`_mm512_mask_cmp_epi16_mask`] + * [x] [`_mm_cmp_epi16_mask`] + * [x] [`_mm_mask_cmp_epi16_mask`] + * [x] [`_mm256_cmp_epi16_mask`] + * [x] [`_mm256_mask_cmp_epi16_mask`] * [x] [`_mm512_cmp_epi8_mask`] * [x] [`_mm512_mask_cmp_epi8_mask`] + * [x] [`_mm_cmp_epi8_mask`] + * [x] [`_mm_mask_cmp_epi8_mask`] + * [x] [`_mm256_cmp_epi8_mask`] + * [x] [`_mm256_mask_cmp_epi8_mask`] * [x] [`_mm512_cmp_epu16_mask`] * [x] [`_mm512_mask_cmp_epu16_mask`] + * [x] [`_mm_cmp_epu16_mask`] + * [x] [`_mm_mask_cmp_epu16_mask`] + * [x] [`_mm256_cmp_epu16_mask`] + * [x] [`_mm256_mask_cmp_epu16_mask`] * [x] [`_mm512_cmp_epu8_mask`] * [x] [`_mm512_mask_cmp_epu8_mask`] + * [x] [`_mm_cmp_epu8_mask`] + * [x] [`_mm_mask_cmp_epu8_mask`] + * [x] [`_mm256_cmp_epu8_mask`] + * [x] [`_mm256_mask_cmp_epu8_mask`] * [x] [`_mm512_cmpeq_epi16_mask`] * [x] [`_mm512_mask_cmpeq_epi16_mask`] + * [x] [`_mm_cmpeq_epi16_mask`] + * [x] [`_mm_mask_cmpeq_epi16_mask`] + * [x] [`_mm256_cmpeq_epi16_mask`] + * [x] [`_mm256_mask_cmpeq_epi16_mask`] * [x] [`_mm512_cmpeq_epi8_mask`] * [x] [`_mm512_mask_cmpeq_epi8_mask`] + * [x] [`_mm_cmpeq_epi8_mask`] + * [x] [`_mm_mask_cmpeq_epi8_mask`] + * [x] [`_mm256_cmpeq_epi8_mask`] + * [x] [`_mm256_mask_cmpeq_epi8_mask`] * [x] [`_mm512_cmpeq_epu16_mask`] * [x] [`_mm512_mask_cmpeq_epu16_mask`] + * [x] [`_mm_cmpeq_epu16_mask`] + * [x] [`_mm_mask_cmpeq_epu16_mask`] + * [x] [`_mm256_cmpeq_epu16_mask`] + * [x] [`_mm256_mask_cmpeq_epu16_mask`] * [x] [`_mm512_cmpeq_epu8_mask`] * [x] [`_mm512_mask_cmpeq_epu8_mask`] + * [x] [`_mm_cmpeq_epu8_mask`] + * [x] [`_mm_mask_cmpeq_epu8_mask`] + * [x] [`_mm256_cmpeq_epu8_mask`] + * [x] [`_mm256_mask_cmpeq_epu8_mask`] * [x] [`_mm512_cmpge_epi16_mask`] * [x] [`_mm512_mask_cmpge_epi16_mask`] + * [x] [`_mm_cmpge_epi16_mask`] + * [x] [`_mm_mask_cmpge_epi16_mask`] + * [x] [`_mm256_cmpge_epi16_mask`] + * [x] [`_mm256_mask_cmpge_epi16_mask`] * [x] [`_mm512_cmpge_epi8_mask`] * [x] [`_mm512_mask_cmpge_epi8_mask`] + * [x] [`_mm_cmpge_epi8_mask`] + * [x] [`_mm_mask_cmpge_epi8_mask`] + * [x] [`_mm256_cmpge_epi8_mask`] + * [x] [`_mm256_mask_cmpge_epi8_mask`] * [x] [`_mm512_cmpge_epu16_mask`] * [x] [`_mm512_mask_cmpge_epu16_mask`] + * [x] [`_mm_cmpge_epu16_mask`] + * [x] [`_mm_mask_cmpge_epu16_mask`] + * [x] [`_mm256_cmpge_epu16_mask`] + * [x] [`_mm256_mask_cmpge_epu16_mask`] * [x] [`_mm512_cmpge_epu8_mask`] * [x] [`_mm512_mask_cmpge_epu8_mask`] + * [x] [`_mm_cmpge_epu8_mask`] + * [x] [`_mm_mask_cmpge_epu8_mask`] + * [x] [`_mm256_cmpge_epu8_mask`] + * [x] [`_mm256_mask_cmpge_epu8_mask`] * [x] [`_mm512_cmpgt_epi16_mask`] * [x] [`_mm512_mask_cmpgt_epi16_mask`] * [x] [`_mm512_cmpgt_epi8_mask`] * [x] [`_mm512_mask_cmpgt_epi8_mask`] + * [x] [`_mm_cmpgt_epi8_mask`] + * [x] [`_mm_mask_cmpgt_epi8_mask`] + * [x] [`_mm256_cmpgt_epi8_mask`] + * [x] [`_mm256_mask_cmpgt_epi8_mask`] * [x] [`_mm512_cmpgt_epu16_mask`] * [x] [`_mm512_mask_cmpgt_epu16_mask`] + * [x] [`_mm_cmpgt_epu16_mask`] + * [x] [`_mm_mask_cmpgt_epu16_mask`] + * [x] [`_mm256_cmpgt_epu16_mask`] + * [x] [`_mm256_mask_cmpgt_epu16_mask`] * [x] [`_mm512_cmpgt_epu8_mask`] * [x] [`_mm512_mask_cmpgt_epu8_mask`] + * [x] [`_mm_cmpgt_epu8_mask`] + * [x] [`_mm_mask_cmpgt_epu8_mask`] + * [x] [`_mm256_cmpgt_epu8_mask`] + * [x] [`_mm256_mask_cmpgt_epu8_mask`] * [x] [`_mm512_cmple_epi16_mask`] * [x] [`_mm512_mask_cmple_epi16_mask`] + * [x] [`_mm_cmpgt_epi16_mask`] + * [x] [`_mm_mask_cmpgt_epi16_mask`] + * [x] [`_mm256_cmpgt_epi16_mask`] + * [x] [`_mm256_mask_cmpgt_epi16_mask`] * [x] [`_mm512_cmple_epi8_mask`] * [x] [`_mm512_mask_cmple_epi8_mask`] + * [x] [`_mm_cmple_epi8_mask`] + * [x] [`_mm_mask_cmple_epi8_mask`] + * [x] [`_mm256_cmple_epi8_mask`] + * [x] [`_mm256_mask_cmple_epi8_mask`] * [x] [`_mm512_cmple_epu16_mask`] * [x] [`_mm512_mask_cmple_epu16_mask`] + * [x] [`_mm_cmple_epu16_mask`] + * [x] [`_mm_mask_cmple_epu16_mask`] + * [x] [`_mm256_cmple_epu16_mask`] + * [x] [`_mm256_mask_cmple_epu16_mask`] * [x] [`_mm512_cmple_epu8_mask`] * [x] [`_mm512_mask_cmple_epu8_mask`] + * [x] [`_mm_cmple_epu8_mask`] + * [x] [`_mm_mask_cmple_epu8_mask`] + * [x] [`_mm256_cmple_epu8_mask`] + * [x] [`_mm256_mask_cmple_epu8_mask`] * [x] [`_mm512_cmplt_epi16_mask`] * [x] [`_mm512_mask_cmplt_epi16_mask`] + * [x] [`_mm_cmple_epi16_mask`] + * [x] [`_mm_mask_cmple_epi16_mask`] + * [x] [`_mm256_cmple_epi16_mask`] + * [x] [`_mm256_mask_cmple_epi16_mask`] * [x] [`_mm512_cmplt_epi8_mask`] * [x] [`_mm512_mask_cmplt_epi8_mask`] + * [x] [`_mm_cmplt_epi8_mask`] + * [x] [`_mm_mask_cmplt_epi8_mask`] + * [x] [`_mm256_cmplt_epi8_mask`] + * [x] [`_mm256_mask_cmplt_epi8_mask`] * [x] [`_mm512_cmplt_epu16_mask`] * [x] [`_mm512_mask_cmplt_epu16_mask`] + * [x] [`_mm_cmplt_epu16_mask`] + * [x] [`_mm_mask_cmplt_epu16_mask`] + * [x] [`_mm256_cmplt_epu16_mask`] + * [x] [`_mm256_mask_cmplt_epu16_mask`] * [x] [`_mm512_cmplt_epu8_mask`] * [x] [`_mm512_mask_cmplt_epu8_mask`] + * [x] [`_mm_cmplt_epu8_mask`] + * [x] [`_mm_mask_cmplt_epu8_mask`] + * [x] [`_mm256_cmplt_epu8_mask`] + * [x] [`_mm256_mask_cmplt_epu8_mask`] * [x] [`_mm512_cmpneq_epi16_mask`] * [x] [`_mm512_mask_cmpneq_epi16_mask`] + * [x] [`_mm_cmpneq_epi16_mask`] + * [x] [`_mm_mask_cmpneq_epi16_mask`] + * [x] [`_mm256_cmpneq_epi16_mask`] + * [x] [`_mm256_mask_cmpneq_epi16_mask`] * [x] [`_mm512_cmpneq_epi8_mask`] * [x] [`_mm512_mask_cmpneq_epi8_mask`] + * [x] [`_mm_cmpneq_epi8_mask`] + * [x] [`_mm_mask_cmpneq_epi8_mask`] + * [x] [`_mm256_cmpneq_epi8_mask`] + * [x] [`_mm256_mask_cmpneq_epi8_mask`] * [x] [`_mm512_cmpneq_epu16_mask`] * [x] [`_mm512_mask_cmpneq_epu16_mask`] + * [x] [`_mm_cmpneq_epu16_mask`] + * [x] [`_mm_mask_cmpneq_epu16_mask`] + * [x] [`_mm256_cmpneq_epu16_mask`] + * [x] [`_mm256_mask_cmpneq_epu16_mask`] * [x] [`_mm512_cmpneq_epu8_mask`] * [x] [`_mm512_mask_cmpneq_epu8_mask`] + * [x] [`_mm_cmpneq_epu8_mask`] + * [x] [`_mm_mask_cmpneq_epu8_mask`] + * [x] [`_mm256_cmpneq_epu8_mask`] + * [x] [`_mm256_mask_cmpneq_epu8_mask`] * [x] [`_mm512_cvtepi16_epi8`] * [x] [`_mm512_mask_cvtepi16_epi8`] * [x] [`_mm512_maskz_cvtepi16_epi8`] - * [_] [`_mm512_mask_cvtepi16_storeu_epi8`] + * [x] [`_mm512_mask_cvtepi16_storeu_epi8`] + * [x] [`_mm_mask_cvtepi16_storeu_epi8`] + * [x] [`_mm256_mask_cvtepi16_storeu_epi8`] + * [x] [`_mm_cvtepi16_epi8`] + * [x] [`_mm_mask_cvtepi16_epi8`] + * [x] [`_mm_maskz_cvtepi16_epi8`] + * [x] [`_mm256_cvtepi16_epi8`] + * [x] [`_mm256_mask_cvtepi16_epi8`] + * [x] [`_mm256_maskz_cvtepi16_epi8`] * [x] [`_mm512_cvtepi8_epi16`] * [x] [`_mm512_mask_cvtepi8_epi16`] * [x] [`_mm512_maskz_cvtepi8_epi16`] + * [x] [`_mm_mask_cvtepi8_epi16`] + * [x] [`_mm_maskz_cvtepi8_epi16`] + * [x] [`_mm256_mask_cvtepi8_epi16`] + * [x] [`_mm256_maskz_cvtepi8_epi16`] + * [x] [`_mm512_cvtsepi16_epi8`] + * [x] [`_mm512_mask_cvtsepi16_epi8`] + * [x] [`_mm512_maskz_cvtsepi16_epi8`] + * [x] [`_mm_cvtsepi16_epi8`] + * [x] [`_mm_mask_cvtsepi16_epi8`] + * [x] [`_mm_maskz_cvtsepi16_epi8`] + * [x] [`_mm256_cvtsepi16_epi8`] + * [x] [`_mm256_mask_cvtsepi16_epi8`] + * [x] [`_mm256_maskz_cvtsepi16_epi8`] + * [x] [`_mm512_mask_cvtsepi16_storeu_epi8`] + * [x] [`_mm_mask_cvtsepi16_storeu_epi8`] + * [x] [`_mm256_mask_cvtsepi16_storeu_epi8`] * [x] [`_mm512_cvtepu8_epi16`] * [x] [`_mm512_mask_cvtepu8_epi16`] * [x] [`_mm512_maskz_cvtepu8_epi16`] + * [x] [`_mm_mask_cvtepu8_epi16`] + * [x] [`_mm_maskz_cvtepu8_epi16`] + * [x] [`_mm256_mask_cvtepu8_epi16`] + * [x] [`_mm256_maskz_cvtepu8_epi16`] * [_] [`_cvtmask32_u32`] * [_] [`_cvtmask64_u64`] - * [x] [`_mm512_cvtsepi16_epi8`] - * [x] [`_mm512_mask_cvtsepi16_epi8`] - * [x] [`_mm512_maskz_cvtsepi16_epi8`] - * [_] [`_mm512_mask_cvtsepi16_storeu_epi8`] * [_] [`_cvtu32_mask32`] * [_] [`_cvtu64_mask64`] * [x] [`_mm512_cvtusepi16_epi8`] * [x] [`_mm512_mask_cvtusepi16_epi8`] * [x] [`_mm512_maskz_cvtusepi16_epi8`] - * [_] [`_mm512_mask_cvtusepi16_storeu_epi8`] + * [x] [`_mm_cvtusepi16_epi8`] + * [x] [`_mm_mask_cvtusepi16_epi8`] + * [x] [`_mm_maskz_cvtusepi16_epi8`] + * [x] [`_mm256_cvtusepi16_epi8`] + * [x] [`_mm256_mask_cvtusepi16_epi8`] + * [x] [`_mm256_maskz_cvtusepi16_epi8`] + * [x] [`_mm512_mask_cvtusepi16_storeu_epi8`] + * [x] [`_mm_mask_cvtusepi16_storeu_epi8`] + * [x] [`_mm256_mask_cvtusepi16_storeu_epi8`] * [x] [`_mm512_dbsad_epu8`] * [x] [`_mm512_mask_dbsad_epu8`] * [x] [`_mm512_maskz_dbsad_epu8`] + * [x] [`_mm_dbsad_epu8`] + * [x] [`_mm_mask_dbsad_epu8`] + * [x] [`_mm_maskz_dbsad_epu8`] + * [x] [`_mm256_dbsad_epu8`] + * [x] [`_mm256_mask_dbsad_epu8`] + * [x] [`_mm256_maskz_dbsad_epu8`] * [x] [`_kadd_mask32`] * [x] [`_kadd_mask64`] * [x] [`_kand_mask32`] @@ -210,12 +390,6 @@ * [x] [`_kxor_mask64`] * [x] [`_load_mask32`] * [x] [`_load_mask64`] - * [x] [`_mm512_loadu_epi16`] - * [_] [`_mm512_mask_loadu_epi16`] - * [_] [`_mm512_maskz_loadu_epi16`] - * [x] [`_mm512_loadu_epi8`] - * [_] [`_mm512_mask_loadu_epi8`] - * [_] [`_mm512_maskz_loadu_epi8`] * [x] [`_mm512_madd_epi16`] * [x] [`_mm512_mask_madd_epi16`] * [x] [`_mm512_maskz_madd_epi16`] @@ -299,9 +473,17 @@ * [x] [`_mm256_mask_mov_epi8`] * [x] [`_mm256_maskz_mov_epi8`] * [x] [`_mm512_movepi16_mask`] + * [x] [`_mm_movepi16_mask`] + * [x] [`_mm256_movepi16_mask`] * [x] [`_mm512_movepi8_mask`] + * [x] [`_mm_movepi8_mask`] + * [x] [`_mm256_movepi8_mask`] * [x] [`_mm512_movm_epi16`] + * [x] [`_mm_movm_epi16`] + * [x] [`_mm256_movm_epi16`] * [x] [`_mm512_movm_epi8`] + * [x] [`_mm_movm_epi8`] + * [x] [`_mm256_movm_epi8`] * [x] [`_mm512_mask_mulhi_epi16`] * [x] [`_mm512_maskz_mulhi_epi16`] * [x] [`_mm512_mulhi_epi16`] @@ -395,12 +577,24 @@ * [x] [`_mm512_mask_shuffle_epi8`] * [x] [`_mm512_maskz_shuffle_epi8`] * [x] [`_mm512_shuffle_epi8`] + * [x] [`_mm_mask_shuffle_epi8`] + * [x] [`_mm_maskz_shuffle_epi8`] + * [x] [`_mm256_mask_shuffle_epi8`] + * [x] [`_mm256_maskz_shuffle_epi8`] * [x] [`_mm512_mask_shufflehi_epi16`] * [x] [`_mm512_maskz_shufflehi_epi16`] * [x] [`_mm512_shufflehi_epi16`] + * [x] [`_mm_mask_shufflehi_epi16`] + * [x] [`_mm_maskz_shufflehi_epi16`] + * [x] [`_mm256_mask_shufflehi_epi16`] + * [x] [`_mm256_maskz_shufflehi_epi16`] * [x] [`_mm512_mask_shufflelo_epi16`] * [x] [`_mm512_maskz_shufflelo_epi16`] * [x] [`_mm512_shufflelo_epi16`] + * [x] [`_mm_mask_shufflelo_epi16`] + * [x] [`_mm_maskz_shufflelo_epi16`] + * [x] [`_mm256_mask_shufflelo_epi16`] + * [x] [`_mm256_maskz_shufflelo_epi16`] * [x] [`_mm512_mask_sll_epi16`] * [x] [`_mm512_maskz_sll_epi16`] * [x] [`_mm512_sll_epi16`] @@ -441,12 +635,12 @@ * [x] [`_mm512_mask_srav_epi16`] * [x] [`_mm512_maskz_srav_epi16`] * [x] [`_mm512_srav_epi16`] - * [_] [`_mm_mask_srav_epi16`] - * [_] [`_mm_maskz_srav_epi16`] - * [_] [`_mm_srav_epi16`] - * [_] [`_mm256_mask_srav_epi16`] - * [_] [`_mm256_maskz_srav_epi16`] - * [_] [`_mm256_srav_epi16`] + * [x] [`_mm_mask_srav_epi16`] + * [x] [`_mm_maskz_srav_epi16`] + * [x] [`_mm_srav_epi16`] + * [x] [`_mm256_mask_srav_epi16`] + * [x] [`_mm256_maskz_srav_epi16`] + * [x] [`_mm256_srav_epi16`] * [x] [`_mm512_mask_srl_epi16`] * [x] [`_mm512_maskz_srl_epi16`] * [x] [`_mm512_srl_epi16`] @@ -472,10 +666,6 @@ * [x] [`_mm256_srlv_epi16`] * [x] [`_store_mask32`] * [x] [`_store_mask64`] - * [_] [`_mm512_mask_storeu_epi16`] - * [x] [`_mm512_storeu_epi16`] - * [_] [`_mm512_mask_storeu_epi8`] - * [x] [`_mm512_storeu_epi8`] * [x] [`_mm512_mask_sub_epi16`] * [x] [`_mm512_maskz_sub_epi16`] * [x] [`_mm512_sub_epi16`] @@ -520,12 +710,28 @@ * [x] [`_mm256_maskz_subs_epu8`] * [x] [`_mm512_mask_test_epi16_mask`] * [x] [`_mm512_test_epi16_mask`] + * [x] [`_mm_mask_test_epi16_mask`] + * [x] [`_mm_test_epi16_mask`] + * [x] [`_mm256_mask_test_epi16_mask`] + * [x] [`_mm256_test_epi16_mask`] * [x] [`_mm512_mask_test_epi8_mask`] * [x] [`_mm512_test_epi8_mask`] + * [x] [`_mm_mask_test_epi8_mask`] + * [x] [`_mm_test_epi8_mask`] + * [x] [`_mm256_mask_test_epi8_mask`] + * [x] [`_mm256_test_epi8_mask`] * [x] [`_mm512_mask_testn_epi16_mask`] * [x] [`_mm512_testn_epi16_mask`] + * [x] [`_mm_mask_testn_epi16_mask`] + * [x] [`_mm_testn_epi16_mask`] + * [x] [`_mm256_mask_testn_epi16_mask`] + * [x] [`_mm256_testn_epi16_mask`] * [x] [`_mm512_mask_testn_epi8_mask`] * [x] [`_mm512_testn_epi8_mask`] + * [x] [`_mm_mask_testn_epi8_mask`] + * [x] [`_mm_testn_epi8_mask`] + * [x] [`_mm256_mask_testn_epi8_mask`] + * [x] [`_mm256_testn_epi8_mask`] * [x] [`_mm512_mask_unpackhi_epi16`] * [x] [`_mm512_maskz_unpackhi_epi16`] * [x] [`_mm512_unpackhi_epi16`] diff --git a/library/stdarch/crates/core_arch/avx512f.md b/library/stdarch/crates/core_arch/avx512f.md index 6dd08b67f6..1ad80147cf 100644 --- a/library/stdarch/crates/core_arch/avx512f.md +++ b/library/stdarch/crates/core_arch/avx512f.md @@ -1,1422 +1,2633 @@

["AVX512F"]

- - * [x] [`_mm512_abs_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_epi32&expand=5236) - * [x] [`_mm512_abs_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_epi64&expand=5236) - * [x] [`_mm512_abs_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_pd&expand=5236) - * [x] [`_mm512_abs_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_ps&expand=5236) - * [x] [`_mm512_add_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_epi32&expand=5236) - * [x] [`_mm512_add_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_epi64&expand=5236) - * [x] [`_mm512_add_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_pd&expand=5236) - * [x] [`_mm512_add_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_ps&expand=5236) - * [x] [`_mm512_add_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_round_pd&expand=5236) - * [x] [`_mm512_add_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_round_ps&expand=5236) - * [x] [`_mm512_alignr_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_alignr_epi32&expand=5236) - * [x] [`_mm512_alignr_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_alignr_epi64&expand=5236) - * [x] [`_mm512_and_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_and_epi32&expand=5236) - * [x] [`_mm512_and_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_and_epi64&expand=5236) - * [x] [`_mm512_and_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_and_si512&expand=5236) - * [x] [`_mm512_andnot_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_andnot_epi32&expand=5236) - * [x] [`_mm512_andnot_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_andnot_epi64&expand=5236) - * [x] [`_mm512_andnot_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_andnot_si512&expand=5236) - * [x] [`_mm512_broadcast_f32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcast_f32x4&expand=5236) - * [x] [`_mm512_broadcast_f64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcast_f64x4&expand=5236) - * [x] [`_mm512_broadcast_i32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcast_i32x4&expand=5236) - * [x] [`_mm512_broadcast_i64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcast_i64x4&expand=5236) - * [x] [`_mm512_broadcastd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastd_epi32&expand=5236) - * [x] [`_mm512_broadcastq_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastq_epi64&expand=5236) - * [x] [`_mm512_broadcastsd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastsd_pd&expand=5236) - * [x] [`_mm512_broadcastss_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastss_ps&expand=5236) - * [x] [`_mm512_castpd128_pd512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd128_pd512&expand=5236) - * [x] [`_mm512_castpd256_pd512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd256_pd512&expand=5236) - * [x] [`_mm512_castpd512_pd128`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd512_pd128&expand=5236) - * [x] [`_mm512_castpd512_pd256`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd512_pd256&expand=5236) - * [x] [`_mm512_castpd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd_ps&expand=5236) - * [x] [`_mm512_castpd_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd_si512&expand=5236) - * [x] [`_mm512_castps128_ps512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps128_ps512&expand=5236) - * [x] [`_mm512_castps256_ps512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps256_ps512&expand=5236) - * [x] [`_mm512_castps512_ps128`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps512_ps128&expand=5236) - * [x] [`_mm512_castps512_ps256`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps512_ps256&expand=5236) - * [x] [`_mm512_castps_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps_pd&expand=5236) - * [x] [`_mm512_castps_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps_si512&expand=5236) - * [x] [`_mm512_castsi128_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi128_si512&expand=5236) - * [x] [`_mm512_castsi256_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi256_si512&expand=5236) - * [x] [`_mm512_castsi512_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi512_pd&expand=5236) - * [x] [`_mm512_castsi512_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi512_ps&expand=5236) - * [x] [`_mm512_castsi512_si128`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi512_si128&expand=5236) - * [x] [`_mm512_castsi512_si256`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi512_si256&expand=5236) - * [x] [`_mm512_cmp_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi32_mask&expand=5236) - * [x] [`_mm512_cmp_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi64_mask&expand=5236) - * [x] [`_mm512_cmp_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu32_mask&expand=5236) - * [x] [`_mm512_cmp_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu64_mask&expand=5236) - * [x] [`_mm512_cmp_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_pd_mask&expand=5236) - * [x] [`_mm512_cmp_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_ps_mask&expand=5236) - * [x] [`_mm512_cmp_round_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_round_pd_mask&expand=5236) - * [x] [`_mm512_cmp_round_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_round_ps_mask&expand=5236) - * [x] [`_mm512_cmpeq_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi32_mask&expand=5236) - * [x] [`_mm512_cmpeq_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi64_mask&expand=5236) - * [x] [`_mm512_cmpeq_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu32_mask&expand=5236) - * [x] [`_mm512_cmpeq_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu64_mask&expand=5236) - * [x] [`_mm512_cmpeq_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_pd_mask&expand=5236) - * [x] [`_mm512_cmpeq_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_ps_mask&expand=5236) - * [x] [`_mm512_cmpge_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi32_mask&expand=5236) - * [x] [`_mm512_cmpge_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi64_mask&expand=5236) - * [x] [`_mm512_cmpge_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu32_mask&expand=5236) - * [x] [`_mm512_cmpge_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu64_mask&expand=5236) - * [x] [`_mm512_cmpgt_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi32_mask&expand=5236) - * [x] [`_mm512_cmpgt_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi64_mask&expand=5236) - * [x] [`_mm512_cmpgt_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu32_mask&expand=5236) - * [x] [`_mm512_cmpgt_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu64_mask&expand=5236) - * [x] [`_mm512_cmple_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi32_mask&expand=5236) - * [x] [`_mm512_cmple_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi64_mask&expand=5236) - * [x] [`_mm512_cmple_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu32_mask&expand=5236) - * [x] [`_mm512_cmple_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu64_mask&expand=5236) - * [x] [`_mm512_cmple_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_pd_mask&expand=5236) - * [x] [`_mm512_cmple_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_ps_mask&expand=5236) - * [x] [`_mm512_cmplt_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi32_mask&expand=5236) - * [x] [`_mm512_cmplt_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi64_mask&expand=5236) - * [x] [`_mm512_cmplt_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epu32_mask&expand=5236) - * [x] [`_mm512_cmplt_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epu64_mask&expand=5236) - * [x] [`_mm512_cmplt_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_pd_mask&expand=5236) - * [x] [`_mm512_cmplt_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_ps_mask&expand=5236) - * [x] [`_mm512_cmpneq_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi32_mask&expand=5236) - * [x] [`_mm512_cmpneq_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi64_mask&expand=5236) - * [x] [`_mm512_cmpneq_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu32_mask&expand=5236) - * [x] [`_mm512_cmpneq_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu64_mask&expand=5236) - * [x] [`_mm512_cmpneq_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_pd_mask&expand=5236) - * [x] [`_mm512_cmpneq_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_ps_mask&expand=5236) - * [x] [`_mm512_cmpnle_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnle_pd_mask&expand=5236) - * [x] [`_mm512_cmpnle_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnle_ps_mask&expand=5236) - * [x] [`_mm512_cmpnlt_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnlt_pd_mask&expand=5236) - * [x] [`_mm512_cmpnlt_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnlt_ps_mask&expand=5236) - * [x] [`_mm512_cmpord_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpord_pd_mask&expand=5236) - * [x] [`_mm512_cmpord_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpord_ps_mask&expand=5236) - * [x] [`_mm512_cmpunord_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpunord_pd_mask&expand=5236) - * [x] [`_mm512_cmpunord_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpunord_ps_mask&expand=5236) - * [x] [`_mm512_cvt_roundepi32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundepi32_ps&expand=5236) - * [x] [`_mm512_cvt_roundepu32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundepu32_ps&expand=5236) - * [x] [`_mm512_cvt_roundpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundpd_epi32&expand=5236) - * [x] [`_mm512_cvt_roundpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundpd_epu32&expand=5236) - * [x] [`_mm512_cvt_roundpd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundpd_ps&expand=5236) - * [x] [`_mm512_cvt_roundph_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundph_ps&expand=5236) - * [x] [`_mm512_cvt_roundps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_epi32&expand=5236) - * [x] [`_mm512_cvt_roundps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_epu32&expand=5236) - * [x] [`_mm512_cvt_roundps_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_pd&expand=5236) - * [x] [`_mm512_cvt_roundps_ph`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_ph&expand=5236) - * [x] [`_mm512_cvtepi16_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi16_epi32&expand=5236) - * [x] [`_mm512_cvtepi16_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi16_epi64&expand=5236) - * [x] [`_mm512_cvtepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_epi16&expand=5236) - * [x] [`_mm512_cvtepi32_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_epi64&expand=5236) - * [x] [`_mm512_cvtepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_epi8&expand=5236) - * [x] [`_mm512_cvtepi32_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_pd&expand=5236) - * [x] [`_mm512_cvtepi32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_ps&expand=5236) - * [x] [`_mm512_cvtepi32lo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32lo_pd&expand=5236) - * [x] [`_mm512_cvtepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi64_epi16&expand=5236) - * [x] [`_mm512_cvtepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi64_epi32&expand=5236) - * [x] [`_mm512_cvtepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi64_epi8&expand=5236) - * [x] [`_mm512_cvtepi8_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi8_epi32&expand=5236) - * [x] [`_mm512_cvtepi8_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi8_epi64&expand=5236) - * [x] [`_mm512_cvtepu16_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu16_epi32&expand=5236) - * [x] [`_mm512_cvtepu16_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu16_epi64&expand=5236) - * [x] [`_mm512_cvtepu32_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32_epi64&expand=5236) - * [x] [`_mm512_cvtepu32_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32_pd&expand=5236) - * [x] [`_mm512_cvtepu32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32_ps&expand=5236) - * [x] [`_mm512_cvtepu32lo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32lo_pd&expand=5236) - * [x] [`_mm512_cvtepu8_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu8_epi32&expand=5236) - * [x] [`_mm512_cvtepu8_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu8_epi64&expand=5236) - * [x] [`_mm512_cvtpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_epi32&expand=5236) - * [x] [`_mm512_cvtpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_epu32&expand=5236) - * [x] [`_mm512_cvtpd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_ps&expand=5236) - * [x] [`_mm512_cvtpd_pslo`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_pslo&expand=5236) - * [x] [`_mm512_cvtph_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtph_ps&expand=5236) - * [x] [`_mm512_cvtps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_epi32&expand=5236) - * [x] [`_mm512_cvtps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_epu32&expand=5236) - * [x] [`_mm512_cvtps_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_pd&expand=5236) - * [x] [`_mm512_cvtps_ph`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_ph&expand=5236) - * [x] [`_mm512_cvtpslo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpslo_pd&expand=5236) - * [x] [`_mm512_cvtsepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi32_epi16&expand=5236) - * [x] [`_mm512_cvtsepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi32_epi8&expand=5236) - * [x] [`_mm512_cvtsepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi64_epi16&expand=5236) - * [x] [`_mm512_cvtsepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi64_epi32&expand=5236) - * [x] [`_mm512_cvtsepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi64_epi8&expand=5236) - * [x] [`_mm512_cvtt_roundpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundpd_epi32&expand=5236) - * [x] [`_mm512_cvtt_roundpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundpd_epu32&expand=5236) - * [x] [`_mm512_cvtt_roundps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundps_epi32&expand=5236) - * [x] [`_mm512_cvtt_roundps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundps_epu32&expand=5236) - * [x] [`_mm512_cvttpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttpd_epi32&expand=5236) - * [x] [`_mm512_cvttpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttpd_epu32&expand=5236) - * [x] [`_mm512_cvttps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttps_epi32&expand=5236) - * [x] [`_mm512_cvttps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttps_epu32&expand=5236) - * [x] [`_mm512_cvtusepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi32_epi16&expand=5236) - * [x] [`_mm512_cvtusepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi32_epi8&expand=5236) - * [x] [`_mm512_cvtusepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi64_epi16&expand=5236) - * [x] [`_mm512_cvtusepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi64_epi32&expand=5236) - * [x] [`_mm512_cvtusepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi64_epi8&expand=5236) - * [x] [`_mm512_div_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_div_pd&expand=5236) - * [x] [`_mm512_div_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_div_ps&expand=5236) - * [x] [`_mm512_div_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_div_round_pd&expand=5236) - * [x] [`_mm512_div_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_div_round_ps&expand=5236) - * [x] [`_mm512_extractf32x4_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extractf32x4_ps&expand=5236) - * [x] [`_mm512_extractf64x4_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extractf64x4_pd&expand=5236) - * [x] [`_mm512_extracti32x4_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extracti32x4_epi32&expand=5236) - * [x] [`_mm512_extracti64x4_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extracti64x4_epi64&expand=5236) - * [x] [`_mm512_fixupimm_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_pd&expand=5236) - * [x] [`_mm512_fixupimm_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_ps&expand=5236) - * [x] [`_mm512_fixupimm_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_round_pd&expand=5236) - * [x] [`_mm512_fixupimm_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_round_ps&expand=5236) - * [x] [`_mm512_fmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_pd&expand=5236) - * [x] [`_mm512_fmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_ps&expand=5236) - * [x] [`_mm512_fmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_round_pd&expand=5236) - * [x] [`_mm512_fmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_round_ps&expand=5236) - * [x] [`_mm512_fmaddsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_pd&expand=5236) - * [x] [`_mm512_fmaddsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_ps&expand=5236) - * [x] [`_mm512_fmaddsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_round_pd&expand=5236) - * [x] [`_mm512_fmaddsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_round_ps&expand=5236) - * [x] [`_mm512_fmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_pd&expand=5236) - * [x] [`_mm512_fmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_ps&expand=5236) - * [x] [`_mm512_fmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_round_pd&expand=5236) - * [x] [`_mm512_fmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_round_ps&expand=5236) - * [x] [`_mm512_fmsubadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_pd&expand=5236) - * [x] [`_mm512_fmsubadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_ps&expand=5236) - * [x] [`_mm512_fmsubadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_round_pd&expand=5236) - * [x] [`_mm512_fmsubadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_round_ps&expand=5236) - * [x] [`_mm512_fnmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_pd&expand=5236) - * [x] [`_mm512_fnmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_ps&expand=5236) - * [x] [`_mm512_fnmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_round_pd&expand=5236) - * [x] [`_mm512_fnmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_round_ps&expand=5236) - * [x] [`_mm512_fnmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_pd&expand=5236) - * [x] [`_mm512_fnmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_ps&expand=5236) - * [x] [`_mm512_fnmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_round_pd&expand=5236) - * [x] [`_mm512_fnmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_round_ps&expand=5236) - * [x] [`_mm512_getexp_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_pd&expand=5236) - * [x] [`_mm512_getexp_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_ps&expand=5236) - * [x] [`_mm512_getexp_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_round_pd&expand=5236) - * [x] [`_mm512_getexp_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_round_ps&expand=5236) - * [x] [`_mm512_getmant_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_pd&expand=5236) - * [x] [`_mm512_getmant_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_ps&expand=5236) - * [x] [`_mm512_getmant_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_round_pd&expand=5236) - * [x] [`_mm512_getmant_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_round_ps&expand=5236) - * [ ] [`_mm512_i32extgather_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32extgather_epi32&expand=5236) - * [ ] [`_mm512_i32extgather_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32extgather_ps&expand=5236) - * [ ] [`_mm512_i32extscatter_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32extscatter_epi32&expand=5236) - * [ ] [`_mm512_i32extscatter_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32extscatter_ps&expand=5236) - * [x] [`_mm512_i32gather_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_epi32&expand=5236) - * [x] [`_mm512_i32gather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_epi64&expand=5236) - * [x] [`_mm512_i32gather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_pd&expand=5236) - * [x] [`_mm512_i32gather_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_ps&expand=5236) - * [ ] [`_mm512_i32loextgather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32loextgather_epi64&expand=5236) - * [ ] [`_mm512_i32loextgather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32loextgather_pd&expand=5236) - * [ ] [`_mm512_i32loextscatter_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32loextscatter_epi64&expand=5236) - * [ ] [`_mm512_i32loextscatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32loextscatter_pd&expand=5236) - * [ ] [`_mm512_i32logather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32logather_epi64&expand=5236) - * [ ] [`_mm512_i32logather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32logather_pd&expand=5236) - * [ ] [`_mm512_i32loscatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32loscatter_pd&expand=5236) - * [x] [`_mm512_i32scatter_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_epi32&expand=5236) - * [x] [`_mm512_i32scatter_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_epi64&expand=5236) - * [x] [`_mm512_i32scatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_pd&expand=5236) - * [x] [`_mm512_i32scatter_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_ps&expand=5236) - * [x] [`_mm512_i64gather_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_epi32&expand=5236) - * [x] [`_mm512_i64gather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_epi64&expand=5236) - * [x] [`_mm512_i64gather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_pd&expand=5236) - * [x] [`_mm512_i64gather_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_ps&expand=5236) - * [x] [`_mm512_i64scatter_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_epi32&expand=5236) - * [x] [`_mm512_i64scatter_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_epi64&expand=5236) - * [x] [`_mm512_i64scatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_pd&expand=5236) - * [x] [`_mm512_i64scatter_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_ps&expand=5236) - * [x] [`_mm512_insertf32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_insertf32x4&expand=5236) - * [x] [`_mm512_insertf64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_insertf64x4&expand=5236) - * [x] [`_mm512_inserti32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_inserti32x4&expand=5236) - * [x] [`_mm512_inserti64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_inserti64x4&expand=5236) - * [x] [`_mm512_int2mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_int2mask&expand=5236) - * [x] [`_mm512_kand`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kand&expand=5236) - * [x] [`_mm512_kandn`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kandn&expand=5236) - * [x] [`_mm512_kmov`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kmov&expand=5236) - * [x] [`_mm512_knot`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_knot&expand=5236) - * [x] [`_mm512_kor`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kor&expand=5236) - * [x] [`_mm512_kortestc`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kortestc&expand=5236) - * [ ] [`_mm512_kortestz`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kortestz&expand=5236) - * [x] [`_mm512_kunpackb`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kunpackb&expand=5236) - * [x] [`_mm512_kxnor`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kxnor&expand=5236) - * [x] [`_mm512_kxor`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_kxor&expand=5236) - * [x] [`_mm512_load_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_epi32&expand=5236) - * [x] [`_mm512_load_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_epi64&expand=5236) - * [x] [`_mm512_load_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_pd&expand=5236) - * [x] [`_mm512_load_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_ps&expand=5236) - * [x] [`_mm512_load_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_si512&expand=5236) - * [x] [`_mm512_loadu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_pd&expand=5236) - * [x] [`_mm512_loadu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_ps&expand=5236) + + * [x] [`_mm512_abs_epi32`] + * [x] [`_mm512_mask_abs_epi32`] + * [x] [`_mm512_maskz_abs_epi32`] + * [x] [`_mm_mask_abs_epi32`] + * [x] [`_mm_maskz_abs_epi32`] + * [x] [`_mm256_mask_abs_epi32`] + * [x] [`_mm256_maskz_abs_epi32`] + * [x] [`_mm512_abs_epi64`] + * [x] [`_mm512_mask_abs_epi64`] + * [x] [`_mm512_maskz_abs_epi64`] + * [x] [`_mm_abs_epi64`] + * [x] [`_mm_mask_abs_epi64`] + * [x] [`_mm_maskz_abs_epi64`] + * [x] [`_mm256_abs_epi64`] + * [x] [`_mm256_mask_abs_epi64`] + * [x] [`_mm256_maskz_abs_epi64`] + * [x] [`_mm512_abs_pd`] + * [x] [`_mm512_mask_abs_pd`] + * [x] [`_mm512_abs_ps`] + * [x] [`_mm512_mask_abs_ps`] + * [x] [`_mm512_add_epi32`] + * [x] [`_mm512_mask_add_epi32`] + * [x] [`_mm512_maskz_add_epi32`] + * [x] [`_mm_mask_add_epi32`] + * [x] [`_mm_maskz_add_epi32`] + * [x] [`_mm256_mask_add_epi32`] + * [x] [`_mm256_maskz_add_epi32`] + * [x] [`_mm512_add_epi64`] + * [x] [`_mm512_mask_add_epi64`] + * [x] [`_mm512_maskz_add_epi64`] + * [x] [`_mm_mask_add_epi64`] + * [x] [`_mm_maskz_add_epi64`] + * [x] [`_mm256_mask_add_epi64`] + * [x] [`_mm256_maskz_add_epi64`] + * [x] [`_mm512_add_ps`] + * [x] [`_mm512_mask_add_ps`] + * [x] [`_mm512_maskz_add_ps`] + * [x] [`_mm_mask_add_ps`] + * [x] [`_mm_maskz_add_ps`] + * [x] [`_mm256_mask_add_ps`] + * [x] [`_mm256_maskz_add_ps`] + * [x] [`_mm512_add_pd`] + * [x] [`_mm512_mask_add_pd`] + * [x] [`_mm512_maskz_add_pd`] + * [x] [`_mm_mask_add_pd`] + * [x] [`_mm_maskz_add_pd`] + * [x] [`_mm256_mask_add_pd`] + * [x] [`_mm256_maskz_add_pd`] + * [x] [`_mm512_add_round_ps`] + * [x] [`_mm512_mask_add_round_ps`] + * [x] [`_mm512_maskz_add_round_ps`] + * [x] [`_mm512_add_round_pd`] + * [x] [`_mm512_mask_add_round_pd`] + * [x] [`_mm512_maskz_add_round_pd`] + * [x] [`_mm512_sub_epi32`] + * [x] [`_mm512_mask_sub_epi32`] + * [x] [`_mm512_maskz_sub_epi32`] + * [x] [`_mm_mask_sub_epi32`] + * [x] [`_mm_maskz_sub_epi32`] + * [x] [`_mm256_mask_sub_epi32`] + * [x] [`_mm256_maskz_sub_epi32`] + * [x] [`_mm512_sub_epi64`] + * [x] [`_mm512_mask_sub_epi64`] + * [x] [`_mm512_maskz_sub_epi64`] + * [x] [`_mm_mask_sub_epi64`] + * [x] [`_mm_maskz_sub_epi64`] + * [x] [`_mm256_mask_sub_epi64`] + * [x] [`_mm256_maskz_sub_epi64`] + * [x] [`_mm512_sub_ps`] + * [x] [`_mm512_mask_sub_ps`] + * [x] [`_mm512_maskz_sub_ps`] + * [x] [`_mm_mask_sub_ps`] + * [x] [`_mm_maskz_sub_ps`] + * [x] [`_mm256_mask_sub_ps`] + * [x] [`_mm256_maskz_sub_ps`] + * [x] [`_mm512_sub_pd`] + * [x] [`_mm512_mask_sub_pd`] + * [x] [`_mm512_maskz_sub_pd`] + * [x] [`_mm_mask_sub_pd`] + * [x] [`_mm_maskz_sub_pd`] + * [x] [`_mm256_mask_sub_pd`] + * [x] [`_mm256_maskz_sub_pd`] + * [x] [`_mm512_sub_round_ps`] + * [x] [`_mm512_mask_sub_round_ps`] + * [x] [`_mm512_maskz_sub_round_ps`] + * [x] [`_mm512_sub_round_pd`] + * [x] [`_mm512_mask_sub_round_pd`] + * [x] [`_mm512_maskz_sub_round_pd`] + * [x] [`_mm512_mul_epi32`] + * [x] [`_mm512_mask_mul_epi32`] + * [x] [`_mm512_maskz_mul_epi32`] + * [x] [`_mm_mask_mul_epi32`] + * [x] [`_mm_maskz_mul_epi32`] + * [x] [`_mm256_mask_mul_epi32`] + * [x] [`_mm256_maskz_mul_epi32`] + * [x] [`_mm512_mul_epu32`] + * [x] [`_mm512_mask_mul_epu32`] + * [x] [`_mm512_maskz_mul_epu32`] + * [x] [`_mm_mask_mul_epu32`] + * [x] [`_mm_maskz_mul_epu32`] + * [x] [`_mm256_mask_mul_epu32`] + * [x] [`_mm256_maskz_mul_epu32`] + * [x] [`_mm512_mul_ps`] + * [x] [`_mm512_mask_mul_ps`] + * [x] [`_mm512_maskz_mul_ps`] + * [x] [`_mm_mask_mul_ps`] + * [x] [`_mm_maskz_mul_ps`] + * [x] [`_mm256_mask_mul_ps`] + * [x] [`_mm256_maskz_mul_ps`] + * [x] [`_mm512_mul_pd`] + * [x] [`_mm512_mask_mul_pd`] + * [x] [`_mm512_maskz_mul_pd`] + * [x] [`_mm_mask_mul_pd`] + * [x] [`_mm_maskz_mul_pd`] + * [x] [`_mm256_mask_mul_pd`] + * [x] [`_mm256_maskz_mul_pd`] + * [x] [`_mm512_mul_round_ps`] + * [x] [`_mm512_mask_mul_round_ps`] + * [x] [`_mm512_maskz_mul_round_ps`] + * [x] [`_mm512_mul_round_pd`] + * [x] [`_mm512_mask_mul_round_pd`] + * [x] [`_mm512_maskz_mul_round_pd`] + * [x] [`_mm512_mullo_epi32`] + * [x] [`_mm512_mask_mullo_epi32`] + * [x] [`_mm512_maskz_mullo_epi32`] + * [x] [`_mm_mask_mullo_epi32`] + * [x] [`_mm_maskz_mullo_epi32`] + * [x] [`_mm256_mask_mullo_epi32`] + * [x] [`_mm256_maskz_mullo_epi32`] + * [x] [`_mm512_mullox_epi64`] + * [x] [`_mm512_mask_mullox_epi64`] + * [x] [`_mm512_div_ps`] + * [x] [`_mm512_mask_div_ps`] + * [x] [`_mm512_maskz_div_ps`] + * [x] [`_mm_mask_div_ps`] + * [x] [`_mm_maskz_div_ps`] + * [x] [`_mm256_mask_div_ps`] + * [x] [`_mm256_maskz_div_ps`] + * [x] [`_mm512_div_pd`] + * [x] [`_mm512_mask_div_pd`] + * [x] [`_mm512_maskz_div_pd`] + * [x] [`_mm_mask_div_pd`] + * [x] [`_mm_maskz_div_pd`] + * [x] [`_mm256_mask_div_pd`] + * [x] [`_mm256_maskz_div_pd`] + * [x] [`_mm512_div_round_ps`] + * [x] [`_mm512_mask_div_round_ps`] + * [x] [`_mm512_maskz_div_round_ps`] + * [x] [`_mm512_div_round_pd`] + * [x] [`_mm512_mask_div_round_pd`] + * [x] [`_mm512_maskz_div_round_pd`] + * [x] [`_mm512_max_epi32`] + * [x] [`_mm512_mask_max_epi32`] + * [x] [`_mm512_maskz_max_epi32`] + * [x] [`_mm_mask_max_epi32`] + * [x] [`_mm_maskz_max_epi32`] + * [x] [`_mm256_mask_max_epi32`] + * [x] [`_mm256_maskz_max_epi32`] + * [x] [`_mm512_max_epu32`] + * [x] [`_mm512_mask_max_epu32`] + * [x] [`_mm512_maskz_max_epu32`] + * [x] [`_mm_mask_max_epu32`] + * [x] [`_mm_maskz_max_epu32`] + * [x] [`_mm256_mask_max_epu32`] + * [x] [`_mm256_maskz_max_epu32`] + * [x] [`_mm512_max_epi64`] + * [x] [`_mm512_mask_max_epi64`] + * [x] [`_mm512_maskz_max_epi64`] + * [x] [`_mm_mask_max_epi64`] + * [x] [`_mm_maskz_max_epi64`] + * [x] [`_mm_max_epi64`] + * [x] [`_mm256_mask_max_epi64`] + * [x] [`_mm256_maskz_max_epi64`] + * [x] [`_mm256_max_epi64`] + * [x] [`_mm512_max_epu64`] + * [x] [`_mm512_mask_max_epu64`] + * [x] [`_mm512_maskz_max_epu64`] + * [x] [`_mm_mask_max_epu64`] + * [x] [`_mm_maskz_max_epu64`] + * [x] [`_mm_max_epu64`] + * [x] [`_mm256_mask_max_epu64`] + * [x] [`_mm256_maskz_max_epu64`] + * [x] [`_mm256_max_epu64`] + * [x] [`_mm512_max_ps`] + * [x] [`_mm512_mask_max_ps`] + * [x] [`_mm512_maskz_max_ps`] + * [x] [`_mm_mask_max_ps`] + * [x] [`_mm_maskz_max_ps`] + * [x] [`_mm256_mask_max_ps`] + * [x] [`_mm256_maskz_max_ps`] + * [x] [`_mm512_max_pd`] + * [x] [`_mm512_mask_max_pd`] + * [x] [`_mm512_maskz_max_pd`] + * [x] [`_mm_mask_max_pd`] + * [x] [`_mm_maskz_max_pd`] + * [x] [`_mm256_mask_max_pd`] + * [x] [`_mm256_maskz_max_pd`] + * [x] [`_mm512_max_round_ps`] + * [x] [`_mm512_mask_max_round_ps`] + * [x] [`_mm512_maskz_max_round_ps`] + * [x] [`_mm512_max_round_pd`] + * [x] [`_mm512_mask_max_round_pd`] + * [x] [`_mm512_maskz_max_round_pd`] + * [x] [`_mm512_min_epi32`] + * [x] [`_mm512_mask_min_epi32`] + * [x] [`_mm512_maskz_min_epi32`] + * [x] [`_mm_mask_min_epi32`] + * [x] [`_mm_maskz_min_epi32`] + * [x] [`_mm256_mask_min_epi32`] + * [x] [`_mm256_maskz_min_epi32`] + * [x] [`_mm512_min_epi64`] + * [x] [`_mm512_mask_min_epi64`] + * [x] [`_mm512_maskz_min_epi64`] + * [x] [`_mm_mask_min_epi64`] + * [x] [`_mm_maskz_min_epi64`] + * [x] [`_mm_min_epi64`] + * [x] [`_mm256_mask_min_epi64`] + * [x] [`_mm256_maskz_min_epi64`] + * [x] [`_mm256_min_epi64`] + * [x] [`_mm512_min_epu32`] + * [x] [`_mm512_mask_min_epu32`] + * [x] [`_mm512_maskz_min_epu32`] + * [x] [`_mm_mask_min_epu32`] + * [x] [`_mm_maskz_min_epu32`] + * [x] [`_mm256_mask_min_epu32`] + * [x] [`_mm256_maskz_min_epu32`] + * [x] [`_mm512_min_epu64`] + * [x] [`_mm512_mask_min_epu64`] + * [x] [`_mm512_maskz_min_epu64`] + * [x] [`_mm_mask_min_epu64`] + * [x] [`_mm_maskz_min_epu64`] + * [x] [`_mm_min_epu64`] + * [x] [`_mm256_mask_min_epu64`] + * [x] [`_mm256_maskz_min_epu64`] + * [x] [`_mm256_min_epu64`] + * [x] [`_mm512_min_ps`] + * [x] [`_mm512_mask_min_ps`] + * [x] [`_mm512_maskz_min_ps`] + * [x] [`_mm_mask_min_ps`] + * [x] [`_mm_maskz_min_ps`] + * [x] [`_mm256_mask_min_ps`] + * [x] [`_mm256_maskz_min_ps`] + * [x] [`_mm512_min_pd`] + * [x] [`_mm512_mask_min_pd`] + * [x] [`_mm512_maskz_min_pd`] + * [x] [`_mm_mask_min_pd`] + * [x] [`_mm_maskz_min_pd`] + * [x] [`_mm256_mask_min_pd`] + * [x] [`_mm256_maskz_min_pd`] + * [x] [`_mm512_min_round_ps`] + * [x] [`_mm512_mask_min_round_ps`] + * [x] [`_mm512_maskz_min_round_ps`] + * [x] [`_mm512_min_round_pd`] + * [x] [`_mm512_mask_min_round_pd`] + * [x] [`_mm512_maskz_min_round_pd`] + * [x] [`_mm512_sqrt_ps`] + * [x] [`_mm512_mask_sqrt_ps`] + * [x] [`_mm512_maskz_sqrt_ps`] + * [x] [`_mm_mask_sqrt_ps`] + * [x] [`_mm_maskz_sqrt_ps`] + * [x] [`_mm256_mask_sqrt_ps`] + * [x] [`_mm256_maskz_sqrt_ps`] + * [x] [`_mm512_sqrt_pd`] + * [x] [`_mm512_mask_sqrt_pd`] + * [x] [`_mm512_maskz_sqrt_pd`] + * [x] [`_mm_mask_sqrt_pd`] + * [x] [`_mm_maskz_sqrt_pd`] + * [x] [`_mm256_mask_sqrt_pd`] + * [x] [`_mm256_maskz_sqrt_pd`] + * [x] [`_mm512_sqrt_round_ps`] + * [x] [`_mm512_mask_sqrt_round_ps`] + * [x] [`_mm512_maskz_sqrt_round_ps`] + * [x] [`_mm512_sqrt_round_pd`] + * [x] [`_mm512_mask_sqrt_round_pd`] + * [x] [`_mm512_maskz_sqrt_round_pd`] + * [x] [`_mm512_rsqrt14_ps`] + * [x] [`_mm512_mask_rsqrt14_ps`] + * [x] [`_mm512_maskz_rsqrt14_ps`] + * [x] [`_mm_mask_rsqrt14_ps`] + * [x] [`_mm_maskz_rsqrt14_ps`] + * [x] [`_mm256_mask_rsqrt14_ps`] + * [x] [`_mm256_maskz_rsqrt14_ps`] + * [x] [`_mm512_rsqrt14_pd`] + * [x] [`_mm512_mask_rsqrt14_pd`] + * [x] [`_mm512_maskz_rsqrt14_pd`] + * [x] [`_mm_mask_rsqrt14_pd`] + * [x] [`_mm_maskz_rsqrt14_pd`] + * [x] [`_mm256_mask_rsqrt14_pd`] + * [x] [`_mm256_maskz_rsqrt14_pd`] + * [x] [`_mm512_rcp14_ps`] + * [x] [`_mm512_mask_rcp14_ps`] + * [x] [`_mm512_maskz_rcp14_ps`] + * [x] [`_mm_mask_rcp14_ps`] + * [x] [`_mm_maskz_rcp14_ps`] + * [x] [`_mm_rcp14_ps`] + * [x] [`_mm256_mask_rcp14_ps`] + * [x] [`_mm256_maskz_rcp14_ps`] + * [x] [`_mm256_rcp14_ps`] + * [x] [`_mm512_rcp14_pd`] + * [x] [`_mm512_mask_rcp14_pd`] + * [x] [`_mm512_maskz_rcp14_pd`] + * [x] [`_mm_mask_rcp14_pd`] + * [x] [`_mm_maskz_rcp14_pd`] + * [x] [`_mm_rcp14_pd`] + * [x] [`_mm256_mask_rcp14_pd`] + * [x] [`_mm256_maskz_rcp14_pd`] + * [x] [`_mm256_rcp14_pd`] + * [x] [`_mm512_getexp_ps`] + * [x] [`_mm512_mask_getexp_ps`] + * [x] [`_mm512_maskz_getexp_ps`] + * [x] [`_mm_getexp_ps`] + * [x] [`_mm_mask_getexp_ps`] + * [x] [`_mm_maskz_getexp_ps`] + * [x] [`_mm256_getexp_ps`] + * [x] [`_mm256_mask_getexp_ps`] + * [x] [`_mm256_maskz_getexp_ps`] + * [x] [`_mm512_getexp_pd`] + * [x] [`_mm512_mask_getexp_pd`] + * [x] [`_mm512_maskz_getexp_pd`] + * [x] [`_mm_getexp_pd`] + * [x] [`_mm_mask_getexp_pd`] + * [x] [`_mm_maskz_getexp_pd`] + * [x] [`_mm256_getexp_pd`] + * [x] [`_mm256_mask_getexp_pd`] + * [x] [`_mm256_maskz_getexp_pd`] + * [x] [`_mm512_getexp_round_ps`] + * [x] [`_mm512_mask_getexp_round_ps`] + * [x] [`_mm512_maskz_getexp_round_ps`] + * [x] [`_mm512_getexp_round_pd`] + * [x] [`_mm512_mask_getexp_round_pd`] + * [x] [`_mm512_maskz_getexp_round_pd`] + * [x] [`_mm512_getmant_ps`] + * [x] [`_mm512_mask_getmant_ps`] + * [x] [`_mm512_maskz_getmant_ps`] + * [x] [`_mm_getmant_ps`] + * [x] [`_mm_mask_getmant_ps`] + * [x] [`_mm_maskz_getmant_ps`] + * [x] [`_mm256_getmant_ps`] + * [x] [`_mm256_mask_getmant_ps`] + * [x] [`_mm256_maskz_getmant_ps`] + * [x] [`_mm512_getmant_pd`] + * [x] [`_mm512_mask_getmant_pd`] + * [x] [`_mm512_maskz_getmant_pd`] + * [x] [`_mm_getmant_pd`] + * [x] [`_mm_mask_getmant_pd`] + * [x] [`_mm_maskz_getmant_pd`] + * [x] [`_mm256_getmant_pd`] + * [x] [`_mm256_mask_getmant_pd`] + * [x] [`_mm256_maskz_getmant_pd`] + * [x] [`_mm512_getmant_round_ps`] + * [x] [`_mm512_mask_getmant_round_ps`] + * [x] [`_mm512_maskz_getmant_round_ps`] + * [x] [`_mm512_getmant_round_pd`] + * [x] [`_mm512_mask_getmant_round_pd`] + * [x] [`_mm512_maskz_getmant_round_pd`] + * [x] [`_mm512_roundscale_ps`] + * [x] [`_mm512_mask_roundscale_ps`] + * [x] [`_mm512_maskz_roundscale_ps`] + * [x] [`_mm_mask_roundscale_ps`] + * [x] [`_mm_maskz_roundscale_ps`] + * [x] [`_mm_roundscale_ps`] + * [x] [`_mm256_mask_roundscale_ps`] + * [x] [`_mm256_maskz_roundscale_ps`] + * [x] [`_mm256_roundscale_ps`] + * [x] [`_mm512_roundscale_pd`] + * [x] [`_mm512_mask_roundscale_pd`] + * [x] [`_mm512_maskz_roundscale_pd`] + * [x] [`_mm_mask_roundscale_pd`] + * [x] [`_mm_maskz_roundscale_pd`] + * [x] [`_mm_roundscale_pd`] + * [x] [`_mm256_mask_roundscale_pd`] + * [x] [`_mm256_maskz_roundscale_pd`] + * [x] [`_mm256_roundscale_pd`] + * [x] [`_mm512_roundscale_round_ps`] + * [x] [`_mm512_mask_roundscale_round_ps`] + * [x] [`_mm512_maskz_roundscale_round_ps`] + * [x] [`_mm512_roundscale_round_pd`] + * [x] [`_mm512_mask_roundscale_round_pd`] + * [x] [`_mm512_maskz_roundscale_round_pd`] + * [x] [`_mm512_scalef_ps`] + * [x] [`_mm512_mask_scalef_ps`] + * [x] [`_mm512_maskz_scalef_ps`] + * [x] [`_mm_mask_scalef_ps`] + * [x] [`_mm_maskz_scalef_ps`] + * [x] [`_mm_scalef_ps`] + * [x] [`_mm256_mask_scalef_ps`] + * [x] [`_mm256_maskz_scalef_ps`] + * [x] [`_mm256_scalef_ps`] + * [x] [`_mm512_scalef_pd`] + * [x] [`_mm512_mask_scalef_pd`] + * [x] [`_mm512_maskz_scalef_pd`] + * [x] [`_mm_mask_scalef_pd`] + * [x] [`_mm_maskz_scalef_pd`] + * [x] [`_mm_scalef_pd`] + * [x] [`_mm256_mask_scalef_pd`] + * [x] [`_mm256_maskz_scalef_pd`] + * [x] [`_mm256_scalef_pd`] + * [x] [`_mm512_scalef_round_ps`] + * [x] [`_mm512_mask_scalef_round_ps`] + * [x] [`_mm512_maskz_scalef_round_ps`] + * [x] [`_mm512_scalef_round_pd`] + * [x] [`_mm512_mask_scalef_round_pd`] + * [x] [`_mm512_maskz_scalef_round_pd`] + * [x] [`_mm512_fixupimm_ps`] + * [x] [`_mm512_mask_fixupimm_ps`] + * [x] [`_mm512_maskz_fixupimm_ps`] + * [x] [`_mm_fixupimm_ps`] + * [x] [`_mm_mask_fixupimm_ps`] + * [x] [`_mm_maskz_fixupimm_ps`] + * [x] [`_mm256_fixupimm_ps`] + * [x] [`_mm256_mask_fixupimm_ps`] + * [x] [`_mm256_maskz_fixupimm_ps`] + * [x] [`_mm512_fixupimm_pd`] + * [x] [`_mm512_mask_fixupimm_pd`] + * [x] [`_mm512_maskz_fixupimm_pd`] + * [x] [`_mm_fixupimm_pd`] + * [x] [`_mm_mask_fixupimm_pd`] + * [x] [`_mm_maskz_fixupimm_pd`] + * [x] [`_mm256_fixupimm_pd`] + * [x] [`_mm256_mask_fixupimm_pd`] + * [x] [`_mm256_maskz_fixupimm_pd`] + * [x] [`_mm512_fixupimm_round_ps`] + * [x] [`_mm512_mask_fixupimm_round_ps`] + * [x] [`_mm512_maskz_fixupimm_round_ps`] + * [x] [`_mm512_fixupimm_round_pd`] + * [x] [`_mm512_mask_fixupimm_round_pd`] + * [x] [`_mm512_maskz_fixupimm_round_pd`] + * [x] [`_mm512_fmadd_ps`] + * [x] [`_mm512_mask_fmadd_ps`] + * [x] [`_mm512_maskz_fmadd_ps`] + * [x] [`_mm512_mask3_fmadd_ps`] + * [x] [`_mm_mask_fmadd_ps`] + * [x] [`_mm_mask3_fmadd_ps`] + * [x] [`_mm_maskz_fmadd_ps`] + * [x] [`_mm256_mask_fmadd_ps`] + * [x] [`_mm256_mask3_fmadd_ps`] + * [x] [`_mm256_maskz_fmadd_ps`] + * [x] [`_mm512_fmadd_pd`] + * [x] [`_mm512_mask_fmadd_pd`] + * [x] [`_mm512_maskz_fmadd_pd`] + * [x] [`_mm512_mask3_fmadd_pd`] + * [x] [`_mm_mask_fmadd_pd`] + * [x] [`_mm_mask3_fmadd_pd`] + * [x] [`_mm_maskz_fmadd_pd`] + * [x] [`_mm256_mask_fmadd_pd`] + * [x] [`_mm256_mask3_fmadd_pd`] + * [x] [`_mm256_maskz_fmadd_pd`] + * [x] [`_mm512_fmadd_round_ps`] + * [x] [`_mm512_mask_fmadd_round_ps`] + * [x] [`_mm512_maskz_fmadd_round_ps`] + * [x] [`_mm512_mask3_fmadd_round_ps`] + * [x] [`_mm512_fmadd_round_pd`] + * [x] [`_mm512_mask_fmadd_round_pd`] + * [x] [`_mm512_maskz_fmadd_round_pd`] + * [x] [`_mm512_mask3_fmadd_round_pd`] + * [x] [`_mm512_fmsub_ps`] + * [x] [`_mm512_mask_fmsub_ps`] + * [x] [`_mm512_maskz_fmsub_ps`] + * [x] [`_mm512_mask3_fmsub_ps`] + * [x] [`_mm_mask_fmsub_ps`] + * [x] [`_mm_mask3_fmsub_ps`] + * [x] [`_mm_maskz_fmsub_ps`] + * [x] [`_mm256_mask_fmsub_ps`] + * [x] [`_mm256_mask3_fmsub_ps`] + * [x] [`_mm256_maskz_fmsub_ps`] + * [x] [`_mm512_fmsub_pd`] + * [x] [`_mm512_mask_fmsub_pd`] + * [x] [`_mm512_maskz_fmsub_pd`] + * [x] [`_mm512_mask3_fmsub_pd`] + * [x] [`_mm_mask_fmsub_pd`] + * [x] [`_mm_mask3_fmsub_pd`] + * [x] [`_mm_maskz_fmsub_pd`] + * [x] [`_mm256_mask_fmsub_pd`] + * [x] [`_mm256_mask3_fmsub_pd`] + * [x] [`_mm256_maskz_fmsub_pd`] + * [x] [`_mm512_fmsub_round_ps`] + * [x] [`_mm512_mask_fmsub_round_ps`] + * [x] [`_mm512_maskz_fmsub_round_ps`] + * [x] [`_mm512_mask3_fmsub_round_ps`] + * [x] [`_mm512_fmsub_round_pd`] + * [x] [`_mm512_mask_fmsub_round_pd`] + * [x] [`_mm512_maskz_fmsub_round_pd`] + * [x] [`_mm512_mask3_fmsub_round_pd`] + * [x] [`_mm512_fmaddsub_ps`] + * [x] [`_mm512_mask_fmaddsub_ps`] + * [x] [`_mm512_maskz_fmaddsub_ps`] + * [x] [`_mm512_mask3_fmaddsub_ps`] + * [x] [`_mm_mask_fmaddsub_ps`] + * [x] [`_mm_mask3_fmaddsub_ps`] + * [x] [`_mm_maskz_fmaddsub_ps`] + * [x] [`_mm256_mask_fmaddsub_ps`] + * [x] [`_mm256_mask3_fmaddsub_ps`] + * [x] [`_mm256_maskz_fmaddsub_ps`] + * [x] [`_mm512_fmaddsub_pd`] + * [x] [`_mm512_mask_fmaddsub_pd`] + * [x] [`_mm512_maskz_fmaddsub_pd`] + * [x] [`_mm512_mask3_fmaddsub_pd`] + * [x] [`_mm_mask_fmaddsub_pd`] + * [x] [`_mm_mask3_fmaddsub_pd`] + * [x] [`_mm_maskz_fmaddsub_pd`] + * [x] [`_mm256_mask_fmaddsub_pd`] + * [x] [`_mm256_mask3_fmaddsub_pd`] + * [x] [`_mm256_maskz_fmaddsub_pd`] + * [x] [`_mm512_fmaddsub_round_ps`] + * [x] [`_mm512_mask_fmaddsub_round_ps`] + * [x] [`_mm512_maskz_fmaddsub_round_ps`] + * [x] [`_mm512_mask3_fmaddsub_round_ps`] + * [x] [`_mm512_fmaddsub_round_pd`] + * [x] [`_mm512_mask_fmaddsub_round_pd`] + * [x] [`_mm512_maskz_fmaddsub_round_pd`] + * [x] [`_mm512_mask3_fmaddsub_round_pd`] + * [x] [`_mm512_fmsubadd_ps`] + * [x] [`_mm512_mask_fmsubadd_ps`] + * [x] [`_mm512_maskz_fmsubadd_ps`] + * [x] [`_mm512_mask3_fmsubadd_ps`] + * [x] [`_mm_mask_fmsubadd_ps`] + * [x] [`_mm_mask3_fmsubadd_ps`] + * [x] [`_mm_maskz_fmsubadd_ps`] + * [x] [`_mm256_mask_fmsubadd_ps`] + * [x] [`_mm256_mask3_fmsubadd_ps`] + * [x] [`_mm256_maskz_fmsubadd_ps`] + * [x] [`_mm512_fmsubadd_pd`] + * [x] [`_mm512_mask_fmsubadd_pd`] + * [x] [`_mm512_maskz_fmsubadd_pd`] + * [x] [`_mm512_mask3_fmsubadd_pd`] + * [x] [`_mm_mask_fmsubadd_pd`] + * [x] [`_mm_mask3_fmsubadd_pd`] + * [x] [`_mm_maskz_fmsubadd_pd`] + * [x] [`_mm256_mask_fmsubadd_pd`] + * [x] [`_mm256_mask3_fmsubadd_pd`] + * [x] [`_mm256_maskz_fmsubadd_pd`] + * [x] [`_mm512_fmsubadd_round_ps`] + * [x] [`_mm512_mask_fmsubadd_round_ps`] + * [x] [`_mm512_maskz_fmsubadd_round_ps`] + * [x] [`_mm512_mask3_fmsubadd_round_ps`] + * [x] [`_mm512_fmsubadd_round_pd`] + * [x] [`_mm512_mask_fmsubadd_round_pd`] + * [x] [`_mm512_maskz_fmsubadd_round_pd`] + * [x] [`_mm512_mask3_fmsubadd_round_pd`] + * [x] [`_mm512_fnmadd_ps`] + * [x] [`_mm512_mask_fnmadd_ps`] + * [x] [`_mm512_maskz_fnmadd_ps`] + * [x] [`_mm512_mask3_fnmadd_ps`] + * [x] [`_mm_mask_fnmadd_ps`] + * [x] [`_mm_mask3_fnmadd_ps`] + * [x] [`_mm_maskz_fnmadd_ps`] + * [x] [`_mm256_mask_fnmadd_ps`] + * [x] [`_mm256_mask3_fnmadd_ps`] + * [x] [`_mm256_maskz_fnmadd_ps`] + * [x] [`_mm512_fnmadd_pd`] + * [x] [`_mm512_mask_fnmadd_pd`] + * [x] [`_mm512_maskz_fnmadd_pd`] + * [x] [`_mm512_mask3_fnmadd_pd`] + * [x] [`_mm_mask_fnmadd_pd`] + * [x] [`_mm_mask3_fnmadd_pd`] + * [x] [`_mm_maskz_fnmadd_pd`] + * [x] [`_mm256_mask_fnmadd_pd`] + * [x] [`_mm256_mask3_fnmadd_pd`] + * [x] [`_mm256_maskz_fnmadd_pd`] + * [x] [`_mm512_fnmadd_round_ps`] + * [x] [`_mm512_mask_fnmadd_round_ps`] + * [x] [`_mm512_maskz_fnmadd_round_ps`] + * [x] [`_mm512_mask3_fnmadd_round_ps`] + * [x] [`_mm512_fnmadd_round_pd`] + * [x] [`_mm512_mask_fnmadd_round_pd`] + * [x] [`_mm512_maskz_fnmadd_round_pd`] + * [x] [`_mm512_mask3_fnmadd_round_pd`] + * [x] [`_mm512_fnmsub_ps`] + * [x] [`_mm512_mask_fnmsub_ps`] + * [x] [`_mm512_maskz_fnmsub_ps`] + * [x] [`_mm512_mask3_fnmsub_ps`] + * [x] [`_mm_mask_fnmsub_ps`] + * [x] [`_mm_mask3_fnmsub_ps`] + * [x] [`_mm_maskz_fnmsub_ps`] + * [x] [`_mm256_mask_fnmsub_ps`] + * [x] [`_mm256_mask3_fnmsub_ps`] + * [x] [`_mm256_maskz_fnmsub_ps`] + * [x] [`_mm512_fnmsub_pd`] + * [x] [`_mm512_mask_fnmsub_pd`] + * [x] [`_mm512_maskz_fnmsub_pd`] + * [x] [`_mm512_mask3_fnmsub_pd`] + * [x] [`_mm_mask_fnmsub_pd`] + * [x] [`_mm_mask3_fnmsub_pd`] + * [x] [`_mm_maskz_fnmsub_pd`] + * [x] [`_mm256_mask_fnmsub_pd`] + * [x] [`_mm256_mask3_fnmsub_pd`] + * [x] [`_mm256_maskz_fnmsub_pd`] + * [x] [`_mm512_fnmsub_round_ps`] + * [x] [`_mm512_mask_fnmsub_round_ps`] + * [x] [`_mm512_maskz_fnmsub_round_ps`] + * [x] [`_mm512_mask3_fnmsub_round_ps`] + * [x] [`_mm512_fnmsub_round_pd`] + * [x] [`_mm512_mask_fnmsub_round_pd`] + * [x] [`_mm512_maskz_fnmsub_round_pd`] + * [x] [`_mm512_mask3_fnmsub_round_pd`] + * [x] [`_mm512_cmp_epi32_mask`] + * [x] [`_mm512_mask_cmp_epi32_mask`] + * [x] [`_mm_cmp_epi32_mask`] + * [x] [`_mm_mask_cmp_epi32_mask`] + * [x] [`_mm256_cmp_epi32_mask`] + * [x] [`_mm256_mask_cmp_epi32_mask`] + * [x] [`_mm512_cmp_epi64_mask`] + * [x] [`_mm512_mask_cmp_epi64_mask`] + * [x] [`_mm_cmp_epi64_mask`] + * [x] [`_mm_mask_cmp_epi64_mask`] + * [x] [`_mm256_cmp_epi64_mask`] + * [x] [`_mm256_mask_cmp_epi64_mask`] + * [x] [`_mm512_cmp_epu32_mask`] + * [x] [`_mm512_mask_cmp_epu32_mask`] + * [x] [`_mm_cmp_epu32_mask`] + * [x] [`_mm_mask_cmp_epu32_mask`] + * [x] [`_mm256_cmp_epu32_mask`] + * [x] [`_mm256_mask_cmp_epu32_mask`] + * [x] [`_mm512_cmp_epu64_mask`] + * [x] [`_mm512_mask_cmp_epu64_mask`] + * [x] [`_mm_cmp_epu64_mask`] + * [x] [`_mm_mask_cmp_epu64_mask`] + * [x] [`_mm256_cmp_epu64_mask`] + * [x] [`_mm256_mask_cmp_epu64_mask`] + * [x] [`_mm512_cmp_ps_mask`] + * [x] [`_mm512_mask_cmp_ps_mask`] + * [x] [`_mm_cmp_ps_mask`] + * [x] [`_mm_mask_cmp_ps_mask`] + * [x] [`_mm256_cmp_ps_mask`] + * [x] [`_mm256_mask_cmp_ps_mask`] + * [x] [`_mm512_cmp_round_ps_mask`] + * [x] [`_mm512_mask_cmp_round_ps_mask`] + * [x] [`_mm512_cmp_pd_mask`] + * [x] [`_mm512_mask_cmp_pd_mask`] + * [x] [`_mm_cmp_pd_mask`] + * [x] [`_mm_mask_cmp_pd_mask`] + * [x] [`_mm256_cmp_pd_mask`] + * [x] [`_mm256_mask_cmp_pd_mask`] + * [x] [`_mm512_cmp_round_pd_mask`] + * [x] [`_mm512_mask_cmp_round_pd_mask`] + * [x] [`_mm512_cmpeq_epi32_mask`] + * [x] [`_mm512_mask_cmpeq_epi32_mask`] + * [x] [`_mm_cmpeq_epi32_mask`] + * [x] [`_mm_mask_cmpeq_epi32_mask`] + * [x] [`_mm256_cmpeq_epi32_mask`] + * [x] [`_mm256_mask_cmpeq_epi32_mask`] + * [x] [`_mm512_cmpeq_epi64_mask`] + * [x] [`_mm512_mask_cmpeq_epi64_mask`] + * [x] [`_mm_cmpeq_epi64_mask`] + * [x] [`_mm_mask_cmpeq_epi64_mask`] + * [x] [`_mm256_cmpeq_epi64_mask`] + * [x] [`_mm256_mask_cmpeq_epi64_mask`] + * [x] [`_mm512_cmpeq_epu32_mask`] + * [x] [`_mm512_mask_cmpeq_epu32_mask`] + * [x] [`_mm_cmpeq_epu32_mask`] + * [x] [`_mm_mask_cmpeq_epu32_mask`] + * [x] [`_mm256_cmpeq_epu32_mask`] + * [x] [`_mm256_mask_cmpeq_epu32_mask`] + * [x] [`_mm512_cmpeq_epu64_mask`] + * [x] [`_mm512_mask_cmpeq_epu64_mask`] + * [x] [`_mm_cmpeq_epu64_mask`] + * [x] [`_mm_mask_cmpeq_epu64_mask`] + * [x] [`_mm256_cmpeq_epu64_mask`] + * [x] [`_mm256_mask_cmpeq_epu64_mask`] + * [x] [`_mm512_cmpneq_epi32_mask`] + * [x] [`_mm512_mask_cmpneq_epi32_mask`] + * [x] [`_mm_cmpneq_epi32_mask`] + * [x] [`_mm_mask_cmpneq_epi32_mask`] + * [x] [`_mm256_cmpneq_epi32_mask`] + * [x] [`_mm256_mask_cmpneq_epi32_mask`] + * [x] [`_mm512_cmpneq_epi64_mask`] + * [x] [`_mm512_mask_cmpneq_epi64_mask`] + * [x] [`_mm_cmpneq_epi64_mask`] + * [x] [`_mm_mask_cmpneq_epi64_mask`] + * [x] [`_mm256_cmpneq_epi64_mask`] + * [x] [`_mm256_mask_cmpneq_epi64_mask`] + * [x] [`_mm512_cmpneq_epu32_mask`] + * [x] [`_mm512_mask_cmpneq_epu32_mask`] + * [x] [`_mm_cmpneq_epu32_mask`] + * [x] [`_mm_mask_cmpneq_epu32_mask`] + * [x] [`_mm256_cmpneq_epu32_mask`] + * [x] [`_mm256_mask_cmpneq_epu32_mask`] + * [x] [`_mm512_cmpneq_epu64_mask`] + * [x] [`_mm512_mask_cmpneq_epu64_mask`] + * [x] [`_mm_cmpneq_epu64_mask`] + * [x] [`_mm_mask_cmpneq_epu64_mask`] + * [x] [`_mm256_cmpneq_epu64_mask`] + * [x] [`_mm256_mask_cmpneq_epu64_mask`] + * [x] [`_mm512_cmpge_epi32_mask`] + * [x] [`_mm512_mask_cmpge_epi32_mask`] + * [x] [`_mm_cmpge_epi32_mask`] + * [x] [`_mm_mask_cmpge_epi32_mask`] + * [x] [`_mm256_cmpge_epi32_mask`] + * [x] [`_mm256_mask_cmpge_epi32_mask`] + * [x] [`_mm512_cmpge_epi64_mask`] + * [x] [`_mm512_mask_cmpge_epi64_mask`] + * [x] [`_mm_cmpge_epi64_mask`] + * [x] [`_mm_mask_cmpge_epi64_mask`] + * [x] [`_mm256_cmpge_epi64_mask`] + * [x] [`_mm256_mask_cmpge_epi64_mask`] + * [x] [`_mm512_cmpge_epu32_mask`] + * [x] [`_mm512_mask_cmpge_epu32_mask`] + * [x] [`_mm_cmpge_epu32_mask`] + * [x] [`_mm_mask_cmpge_epu32_mask`] + * [x] [`_mm256_cmpge_epu32_mask`] + * [x] [`_mm256_mask_cmpge_epu32_mask`] + * [x] [`_mm512_cmpge_epu64_mask`] + * [x] [`_mm512_mask_cmpge_epu64_mask`] + * [x] [`_mm_cmpge_epu64_mask`] + * [x] [`_mm_mask_cmpge_epu64_mask`] + * [x] [`_mm256_cmpge_epu64_mask`] + * [x] [`_mm256_mask_cmpge_epu64_mask`] + * [x] [`_mm512_cmpgt_epi32_mask`] + * [x] [`_mm512_mask_cmpgt_epi32_mask`] + * [x] [`_mm_cmpgt_epi32_mask`] + * [x] [`_mm_mask_cmpgt_epi32_mask`] + * [x] [`_mm256_cmpgt_epi32_mask`] + * [x] [`_mm256_mask_cmpgt_epi32_mask`] + * [x] [`_mm512_cmpgt_epi64_mask`] + * [x] [`_mm512_mask_cmpgt_epi64_mask`] + * [x] [`_mm_cmpgt_epi64_mask`] + * [x] [`_mm_mask_cmpgt_epi64_mask`] + * [x] [`_mm256_cmpgt_epi64_mask`] + * [x] [`_mm256_mask_cmpgt_epi64_mask`] + * [x] [`_mm512_cmpgt_epu32_mask`] + * [x] [`_mm512_mask_cmpgt_epu32_mask`] + * [x] [`_mm_cmpgt_epu32_mask`] + * [x] [`_mm_mask_cmpgt_epu32_mask`] + * [x] [`_mm256_cmpgt_epu32_mask`] + * [x] [`_mm256_mask_cmpgt_epu32_mask`] + * [x] [`_mm512_cmpgt_epu64_mask`] + * [x] [`_mm512_mask_cmpgt_epu64_mask`] + * [x] [`_mm_cmpgt_epu64_mask`] + * [x] [`_mm_mask_cmpgt_epu64_mask`] + * [x] [`_mm256_cmpgt_epu64_mask`] + * [x] [`_mm256_mask_cmpgt_epu64_mask`] + * [x] [`_mm512_cmple_epi32_mask`] + * [x] [`_mm512_mask_cmple_epi32_mask`] + * [x] [`_mm_cmple_epi32_mask`] + * [x] [`_mm_mask_cmple_epi32_mask`] + * [x] [`_mm256_cmple_epi32_mask`] + * [x] [`_mm256_mask_cmple_epi32_mask`] + * [x] [`_mm512_cmple_epi64_mask`] + * [x] [`_mm512_mask_cmple_epi64_mask`] + * [x] [`_mm_cmple_epi64_mask`] + * [x] [`_mm_mask_cmple_epi64_mask`] + * [x] [`_mm256_cmple_epi64_mask`] + * [x] [`_mm256_mask_cmple_epi64_mask`] + * [x] [`_mm512_cmple_epu32_mask`] + * [x] [`_mm512_mask_cmple_epu32_mask`] + * [x] [`_mm_cmple_epu32_mask`] + * [x] [`_mm_mask_cmple_epu32_mask`] + * [x] [`_mm256_cmple_epu32_mask`] + * [x] [`_mm256_mask_cmple_epu32_mask`] + * [x] [`_mm512_cmple_epu64_mask`] + * [x] [`_mm512_mask_cmple_epu64_mask`] + * [x] [`_mm_cmple_epu64_mask`] + * [x] [`_mm_mask_cmple_epu64_mask`] + * [x] [`_mm256_cmple_epu64_mask`] + * [x] [`_mm256_mask_cmple_epu64_mask`] + * [x] [`_mm512_cmplt_epi32_mask`] + * [x] [`_mm512_mask_cmplt_epi32_mask`] + * [x] [`_mm_cmplt_epi32_mask`] + * [x] [`_mm_mask_cmplt_epi32_mask`] + * [x] [`_mm256_cmplt_epi32_mask`] + * [x] [`_mm256_mask_cmplt_epi32_mask`] + * [x] [`_mm512_cmplt_epi64_mask`] + * [x] [`_mm512_mask_cmplt_epi64_mask`] + * [x] [`_mm_cmplt_epi64_mask`] + * [x] [`_mm_mask_cmplt_epi64_mask`] + * [x] [`_mm256_cmplt_epi64_mask`] + * [x] [`_mm256_mask_cmplt_epi64_mask`] + * [x] [`_mm512_cmplt_epu32_mask`] + * [x] [`_mm512_mask_cmplt_epu32_mask`] + * [x] [`_mm_cmplt_epu32_mask`] + * [x] [`_mm_mask_cmplt_epu32_mask`] + * [x] [`_mm256_cmplt_epu32_mask`] + * [x] [`_mm256_mask_cmplt_epu32_mask`] + * [x] [`_mm512_cmplt_epu64_mask`] + * [x] [`_mm512_mask_cmplt_epu64_mask`] + * [x] [`_mm_cmplt_epu64_mask`] + * [x] [`_mm_mask_cmplt_epu64_mask`] + * [x] [`_mm256_cmplt_epu64_mask`] + * [x] [`_mm256_mask_cmplt_epu64_mask`] + * [x] [`_mm512_cmpeq_ps_mask`] + * [x] [`_mm512_mask_cmpeq_ps_mask`] + * [x] [`_mm512_cmpeq_pd_mask`] + * [x] [`_mm512_mask_cmpeq_pd_mask`] + * [x] [`_mm512_cmpneq_ps_mask`] + * [x] [`_mm512_mask_cmpneq_ps_mask`] + * [x] [`_mm512_cmpneq_pd_mask`] + * [x] [`_mm512_mask_cmpneq_pd_mask`] + * [x] [`_mm512_cmple_ps_mask`] + * [x] [`_mm512_mask_cmple_ps_mask`] + * [x] [`_mm512_cmple_pd_mask`] + * [x] [`_mm512_mask_cmple_pd_mask`] + * [x] [`_mm512_cmplt_ps_mask`] + * [x] [`_mm512_mask_cmplt_ps_mask`] + * [x] [`_mm512_cmplt_pd_mask`] + * [x] [`_mm512_mask_cmplt_pd_mask`] + * [x] [`_mm512_cmpnle_ps_mask`] + * [x] [`_mm512_mask_cmpnle_ps_mask`] + * [x] [`_mm512_cmpnle_pd_mask`] + * [x] [`_mm512_mask_cmpnle_pd_mask`] + * [x] [`_mm512_cmpnlt_ps_mask`] + * [x] [`_mm512_mask_cmpnlt_ps_mask`] + * [x] [`_mm512_cmpnlt_pd_mask`] + * [x] [`_mm512_mask_cmpnlt_pd_mask`] + * [x] [`_mm512_cmpord_ps_mask`] + * [x] [`_mm512_mask_cmpord_ps_mask`] + * [x] [`_mm512_cmpord_pd_mask`] + * [x] [`_mm512_mask_cmpord_pd_mask`] + * [x] [`_mm512_cmpunord_ps_mask`] + * [x] [`_mm512_mask_cmpunord_ps_mask`] + * [x] [`_mm512_cmpunord_pd_mask`] + * [x] [`_mm512_mask_cmpunord_pd_mask`] + * [x] [`_mm512_reduce_add_epi32`] + * [x] [`_mm512_mask_reduce_add_epi32`] + * [x] [`_mm512_reduce_add_epi64`] + * [x] [`_mm512_mask_reduce_add_epi64`] + * [x] [`_mm512_reduce_add_ps`] + * [x] [`_mm512_mask_reduce_add_ps`] + * [x] [`_mm512_reduce_add_pd`] + * [x] [`_mm512_mask_reduce_add_pd`] + * [x] [`_mm512_reduce_and_epi32`] + * [x] [`_mm512_mask_reduce_and_epi32`] + * [x] [`_mm512_reduce_and_epi64`] + * [x] [`_mm512_mask_reduce_and_epi64`] + * [x] [`_mm512_reduce_max_epi32`] + * [x] [`_mm512_mask_reduce_max_epi32`] + * [x] [`_mm512_reduce_max_epi64`] + * [x] [`_mm512_mask_reduce_max_epi64`] + * [x] [`_mm512_reduce_max_epu32`] + * [x] [`_mm512_mask_reduce_max_epu32`] + * [x] [`_mm512_reduce_max_epu64`] + * [x] [`_mm512_mask_reduce_max_epu64`] + * [x] [`_mm512_reduce_max_ps`] + * [x] [`_mm512_mask_reduce_max_ps`] + * [x] [`_mm512_reduce_max_pd`] + * [x] [`_mm512_mask_reduce_max_pd`] + * [x] [`_mm512_reduce_min_epi32`] + * [x] [`_mm512_mask_reduce_min_epi32`] + * [x] [`_mm512_reduce_min_epi64`] + * [x] [`_mm512_mask_reduce_min_epi64`] + * [x] [`_mm512_reduce_min_epu32`] + * [x] [`_mm512_mask_reduce_min_epu32`] + * [x] [`_mm512_reduce_min_epu64`] + * [x] [`_mm512_mask_reduce_min_epu64`] + * [x] [`_mm512_reduce_min_ps`] + * [x] [`_mm512_mask_reduce_min_ps`] + * [x] [`_mm512_reduce_min_pd`] + * [x] [`_mm512_mask_reduce_min_pd`] + * [x] [`_mm512_reduce_mul_epi32`] + * [x] [`_mm512_mask_reduce_mul_epi32`] + * [x] [`_mm512_reduce_mul_epi64`] + * [x] [`_mm512_mask_reduce_mul_epi64`] + * [x] [`_mm512_reduce_mul_ps`] + * [x] [`_mm512_mask_reduce_mul_ps`] + * [x] [`_mm512_reduce_mul_pd`] + * [x] [`_mm512_mask_reduce_mul_pd`] + * [x] [`_mm512_reduce_or_epi32`] + * [x] [`_mm512_mask_reduce_or_epi32`] + * [x] [`_mm512_reduce_or_epi64`] + * [x] [`_mm512_mask_reduce_or_epi64`] + * [x] [`_mm512_rol_epi32`] + * [x] [`_mm512_mask_rol_epi32`] + * [x] [`_mm512_maskz_rol_epi32`] + * [x] [`_mm_mask_rol_epi32`] + * [x] [`_mm_maskz_rol_epi32`] + * [x] [`_mm_rol_epi32`] + * [x] [`_mm256_mask_rol_epi32`] + * [x] [`_mm256_maskz_rol_epi32`] + * [x] [`_mm256_rol_epi32`] + * [x] [`_mm512_rol_epi64`] + * [x] [`_mm512_mask_rol_epi64`] + * [x] [`_mm512_maskz_rol_epi64`] + * [x] [`_mm_mask_rol_epi64`] + * [x] [`_mm_maskz_rol_epi64`] + * [x] [`_mm_rol_epi64`] + * [x] [`_mm256_mask_rol_epi64`] + * [x] [`_mm256_maskz_rol_epi64`] + * [x] [`_mm256_rol_epi64`] + * [x] [`_mm512_rolv_epi32`] + * [x] [`_mm512_mask_rolv_epi32`] + * [x] [`_mm512_maskz_rolv_epi32`] + * [x] [`_mm_mask_rolv_epi32`] + * [x] [`_mm_maskz_rolv_epi32`] + * [x] [`_mm_rolv_epi32`] + * [x] [`_mm256_mask_rolv_epi32`] + * [x] [`_mm256_maskz_rolv_epi32`] + * [x] [`_mm256_rolv_epi32`] + * [x] [`_mm512_rolv_epi64`] + * [x] [`_mm512_mask_rolv_epi64`] + * [x] [`_mm512_maskz_rolv_epi64`] + * [x] [`_mm_mask_rolv_epi64`] + * [x] [`_mm_maskz_rolv_epi64`] + * [x] [`_mm_rolv_epi64`] + * [x] [`_mm256_mask_rolv_epi64`] + * [x] [`_mm256_maskz_rolv_epi64`] + * [x] [`_mm256_rolv_epi64`] + * [x] [`_mm512_ror_epi32`] + * [x] [`_mm512_mask_ror_epi32`] + * [x] [`_mm512_maskz_ror_epi32`] + * [x] [`_mm_mask_ror_epi32`] + * [x] [`_mm_maskz_ror_epi32`] + * [x] [`_mm_ror_epi32`] + * [x] [`_mm256_mask_ror_epi32`] + * [x] [`_mm256_maskz_ror_epi32`] + * [x] [`_mm256_ror_epi32`] + * [x] [`_mm512_ror_epi64`] + * [x] [`_mm512_mask_ror_epi64`] + * [x] [`_mm512_maskz_ror_epi64`] + * [x] [`_mm_mask_ror_epi64`] + * [x] [`_mm_maskz_ror_epi64`] + * [x] [`_mm_ror_epi64`] + * [x] [`_mm256_mask_ror_epi64`] + * [x] [`_mm256_maskz_ror_epi64`] + * [x] [`_mm256_ror_epi64`] + * [x] [`_mm512_rorv_epi32`] + * [x] [`_mm512_mask_rorv_epi32`] + * [x] [`_mm512_maskz_rorv_epi32`] + * [x] [`_mm_mask_rorv_epi32`] + * [x] [`_mm_maskz_rorv_epi32`] + * [x] [`_mm_rorv_epi32`] + * [x] [`_mm256_mask_rorv_epi32`] + * [x] [`_mm256_maskz_rorv_epi32`] + * [x] [`_mm256_rorv_epi32`] + * [x] [`_mm512_rorv_epi64`] + * [x] [`_mm512_mask_rorv_epi64`] + * [x] [`_mm512_maskz_rorv_epi64`] + * [x] [`_mm_mask_rorv_epi64`] + * [x] [`_mm_maskz_rorv_epi64`] + * [x] [`_mm_rorv_epi64`] + * [x] [`_mm256_mask_rorv_epi64`] + * [x] [`_mm256_maskz_rorv_epi64`] + * [x] [`_mm256_rorv_epi64`] + * [x] [`_mm512_sll_epi32`] + * [x] [`_mm512_mask_sll_epi32`] + * [x] [`_mm512_maskz_sll_epi32`] + * [x] [`_mm_mask_sll_epi32`] + * [x] [`_mm_maskz_sll_epi32`] + * [x] [`_mm256_mask_sll_epi32`] + * [x] [`_mm256_maskz_sll_epi32`] + * [x] [`_mm512_sll_epi64`] + * [x] [`_mm512_mask_sll_epi64`] + * [x] [`_mm512_maskz_sll_epi64`] + * [x] [`_mm_mask_sll_epi64`] + * [x] [`_mm_maskz_sll_epi64`] + * [x] [`_mm256_mask_sll_epi64`] + * [x] [`_mm256_maskz_sll_epi64`] + * [x] [`_mm512_slli_epi32`] + * [x] [`_mm512_mask_slli_epi32`] + * [x] [`_mm512_maskz_slli_epi32`] + * [x] [`_mm_mask_slli_epi32`] + * [x] [`_mm_maskz_slli_epi32`] + * [x] [`_mm256_mask_slli_epi32`] + * [x] [`_mm256_maskz_slli_epi32`] + * [x] [`_mm512_slli_epi64`] + * [x] [`_mm512_mask_slli_epi64`] + * [x] [`_mm512_maskz_slli_epi64`] + * [x] [`_mm_mask_slli_epi64`] + * [x] [`_mm_maskz_slli_epi64`] + * [x] [`_mm256_mask_slli_epi64`] + * [x] [`_mm256_maskz_slli_epi64`] + * [x] [`_mm512_sllv_epi32`] + * [x] [`_mm512_mask_sllv_epi32`] + * [x] [`_mm512_maskz_sllv_epi32`] + * [x] [`_mm_mask_sllv_epi32`] + * [x] [`_mm_maskz_sllv_epi32`] + * [x] [`_mm256_mask_sllv_epi32`] + * [x] [`_mm256_maskz_sllv_epi32`] + * [x] [`_mm512_sllv_epi64`] + * [x] [`_mm512_mask_sllv_epi64`] + * [x] [`_mm512_maskz_sllv_epi64`] + * [x] [`_mm_mask_sllv_epi64`] + * [x] [`_mm_maskz_sllv_epi64`] + * [x] [`_mm256_mask_sllv_epi64`] + * [x] [`_mm256_maskz_sllv_epi64`] + * [x] [`_mm512_sra_epi32`] + * [x] [`_mm512_mask_sra_epi32`] + * [x] [`_mm512_maskz_sra_epi32`] + * [x] [`_mm_mask_sra_epi32`] + * [x] [`_mm_maskz_sra_epi32`] + * [x] [`_mm256_mask_sra_epi32`] + * [x] [`_mm256_maskz_sra_epi32`] + * [x] [`_mm512_sra_epi64`] + * [x] [`_mm512_mask_sra_epi64`] + * [x] [`_mm512_maskz_sra_epi64`] + * [x] [`_mm_mask_sra_epi64`] + * [x] [`_mm_maskz_sra_epi64`] + * [x] [`_mm_sra_epi64`] + * [x] [`_mm256_mask_sra_epi64`] + * [x] [`_mm256_maskz_sra_epi64`] + * [x] [`_mm256_sra_epi64`] + * [x] [`_mm512_srai_epi32`] + * [x] [`_mm512_mask_srai_epi32`] + * [x] [`_mm512_maskz_srai_epi32`] + * [x] [`_mm_mask_srai_epi32`] + * [x] [`_mm_maskz_srai_epi32`] + * [x] [`_mm256_mask_srai_epi32`] + * [x] [`_mm256_maskz_srai_epi32`] + * [x] [`_mm512_srai_epi64`] + * [x] [`_mm512_mask_srai_epi64`] + * [x] [`_mm512_maskz_srai_epi64`] + * [x] [`_mm_mask_srai_epi64`] + * [x] [`_mm_maskz_srai_epi64`] + * [x] [`_mm_srai_epi64`] + * [x] [`_mm256_mask_srai_epi64`] + * [x] [`_mm256_maskz_srai_epi64`] + * [x] [`_mm256_srai_epi64`] + * [x] [`_mm512_srav_epi32`] + * [x] [`_mm512_mask_srav_epi32`] + * [x] [`_mm512_maskz_srav_epi32`] + * [x] [`_mm_mask_srav_epi32`] + * [x] [`_mm_maskz_srav_epi32`] + * [x] [`_mm256_mask_srav_epi32`] + * [x] [`_mm256_maskz_srav_epi32`] + * [x] [`_mm512_srav_epi64`] + * [x] [`_mm512_mask_srav_epi64`] + * [x] [`_mm512_maskz_srav_epi64`] + * [x] [`_mm_mask_srav_epi64`] + * [x] [`_mm_maskz_srav_epi64`] + * [x] [`_mm_srav_epi64`] + * [x] [`_mm256_mask_srav_epi64`] + * [x] [`_mm256_maskz_srav_epi64`] + * [x] [`_mm256_srav_epi64`] + * [x] [`_mm512_srl_epi32`] + * [x] [`_mm512_mask_srl_epi32`] + * [x] [`_mm512_maskz_srl_epi32`] + * [x] [`_mm_mask_srl_epi32`] + * [x] [`_mm_maskz_srl_epi32`] + * [x] [`_mm256_mask_srl_epi32`] + * [x] [`_mm256_maskz_srl_epi32`] + * [x] [`_mm512_srl_epi64`] + * [x] [`_mm512_mask_srl_epi64`] + * [x] [`_mm512_maskz_srl_epi64`] + * [x] [`_mm_mask_srl_epi64`] + * [x] [`_mm_maskz_srl_epi64`] + * [x] [`_mm256_mask_srl_epi64`] + * [x] [`_mm256_maskz_srl_epi64`] + * [x] [`_mm512_srli_epi32`] + * [x] [`_mm512_mask_srli_epi32`] + * [x] [`_mm512_maskz_srli_epi32`] + * [x] [`_mm_mask_srli_epi32`] + * [x] [`_mm_maskz_srli_epi32`] + * [x] [`_mm256_mask_srli_epi32`] + * [x] [`_mm256_maskz_srli_epi32`] + * [x] [`_mm512_srli_epi64`] + * [x] [`_mm512_mask_srli_epi64`] + * [x] [`_mm512_maskz_srli_epi64`] + * [x] [`_mm_mask_srli_epi64`] + * [x] [`_mm_maskz_srli_epi64`] + * [x] [`_mm256_mask_srli_epi64`] + * [x] [`_mm256_maskz_srli_epi64`] + * [x] [`_mm512_srlv_epi32`] + * [x] [`_mm512_mask_srlv_epi32`] + * [x] [`_mm512_maskz_srlv_epi32`] + * [x] [`_mm_mask_srlv_epi32`] + * [x] [`_mm_maskz_srlv_epi32`] + * [x] [`_mm256_mask_srlv_epi32`] + * [x] [`_mm256_maskz_srlv_epi32`] + * [x] [`_mm512_srlv_epi64`] + * [x] [`_mm512_mask_srlv_epi64`] + * [x] [`_mm512_maskz_srlv_epi64`] + * [x] [`_mm_mask_srlv_epi64`] + * [x] [`_mm_maskz_srlv_epi64`] + * [x] [`_mm256_mask_srlv_epi64`] + * [x] [`_mm256_maskz_srlv_epi64`] + * [x] [`_mm512_mask_mov_epi32`] + * [x] [`_mm512_maskz_mov_epi32`] + * [x] [`_mm_mask_mov_epi32`] + * [x] [`_mm_maskz_mov_epi32`] + * [x] [`_mm256_mask_mov_epi32`] + * [x] [`_mm256_maskz_mov_epi32`] + * [x] [`_mm512_mask_mov_epi64`] + * [x] [`_mm512_maskz_mov_epi64`] + * [x] [`_mm_mask_mov_epi64`] + * [x] [`_mm_maskz_mov_epi64`] + * [x] [`_mm256_mask_mov_epi64`] + * [x] [`_mm256_maskz_mov_epi64`] + * [x] [`_mm512_mask_mov_ps`] + * [x] [`_mm512_maskz_mov_ps`] + * [x] [`_mm_mask_mov_ps`] + * [x] [`_mm_maskz_mov_ps`] + * [x] [`_mm256_mask_mov_ps`] + * [x] [`_mm256_maskz_mov_ps`] + * [x] [`_mm512_mask_mov_pd`] + * [x] [`_mm512_maskz_mov_pd`] + * [x] [`_mm_mask_mov_pd`] + * [x] [`_mm_maskz_mov_pd`] + * [x] [`_mm256_mask_mov_pd`] + * [x] [`_mm256_maskz_mov_pd`] + * [x] [`_mm512_movehdup_ps`] + * [x] [`_mm512_mask_movehdup_ps`] + * [x] [`_mm512_maskz_movehdup_ps`] + * [x] [`_mm_mask_movehdup_ps`] + * [x] [`_mm_maskz_movehdup_ps`] + * [x] [`_mm256_mask_movehdup_ps`] + * [x] [`_mm256_maskz_movehdup_ps`] + * [x] [`_mm512_moveldup_ps`] + * [x] [`_mm512_mask_moveldup_ps`] + * [x] [`_mm512_maskz_moveldup_ps`] + * [x] [`_mm_mask_moveldup_ps`] + * [x] [`_mm_maskz_moveldup_ps`] + * [x] [`_mm256_mask_moveldup_ps`] + * [x] [`_mm256_maskz_moveldup_ps`] + * [x] [`_mm512_movedup_pd`] + * [x] [`_mm512_mask_movedup_pd`] + * [x] [`_mm512_maskz_movedup_pd`] + * [x] [`_mm_mask_movedup_pd`] + * [x] [`_mm_maskz_movedup_pd`] + * [x] [`_mm256_mask_movedup_pd`] + * [x] [`_mm256_maskz_movedup_pd`] + * [x] [`_mm512_or_epi32`] + * [x] [`_mm512_mask_or_epi32`] + * [x] [`_mm512_maskz_or_epi32`] + * [x] [`_mm_mask_or_epi32`] + * [x] [`_mm_maskz_or_epi32`] + * [x] [`_mm_or_epi32`] + * [x] [`_mm256_mask_or_epi32`] + * [x] [`_mm256_maskz_or_epi32`] + * [x] [`_mm256_or_epi32`] + * [x] [`_mm512_or_epi64`] + * [x] [`_mm512_mask_or_epi64`] + * [x] [`_mm512_maskz_or_epi64`] + * [x] [`_mm_mask_or_epi64`] + * [x] [`_mm_maskz_or_epi64`] + * [x] [`_mm_or_epi64`] + * [x] [`_mm256_mask_or_epi64`] + * [x] [`_mm256_maskz_or_epi64`] + * [x] [`_mm256_or_epi64`] + * [x] [`_mm512_or_si512`] + * [x] [`_mm512_and_epi32`] + * [x] [`_mm512_mask_and_epi32`] + * [x] [`_mm512_maskz_and_epi32`] + * [x] [`_mm_mask_and_epi32`] + * [x] [`_mm_maskz_and_epi32`] + * [x] [`_mm256_mask_and_epi32`] + * [x] [`_mm256_maskz_and_epi32`] + * [x] [`_mm512_and_epi64`] + * [x] [`_mm512_mask_and_epi64`] + * [x] [`_mm512_maskz_and_epi64`] + * [x] [`_mm_mask_and_epi64`] + * [x] [`_mm_maskz_and_epi64`] + * [x] [`_mm256_mask_and_epi64`] + * [x] [`_mm256_maskz_and_epi64`] + * [x] [`_mm512_and_si512`] + * [x] [`_mm512_xor_epi32`] + * [x] [`_mm512_mask_xor_epi32`] + * [x] [`_mm512_maskz_xor_epi32`] + * [x] [`_mm_mask_xor_epi32`] + * [x] [`_mm_maskz_xor_epi32`] + * [x] [`_mm_xor_epi32`] + * [x] [`_mm256_mask_xor_epi32`] + * [x] [`_mm256_maskz_xor_epi32`] + * [x] [`_mm256_xor_epi32`] + * [x] [`_mm512_xor_epi64`] + * [x] [`_mm512_mask_xor_epi64`] + * [x] [`_mm512_maskz_xor_epi64`] + * [x] [`_mm_mask_xor_epi64`] + * [x] [`_mm_maskz_xor_epi64`] + * [x] [`_mm_xor_epi64`] + * [x] [`_mm256_mask_xor_epi64`] + * [x] [`_mm256_maskz_xor_epi64`] + * [x] [`_mm256_xor_epi64`] + * [x] [`_mm512_xor_si512`] + * [x] [`_mm512_andnot_epi32`] + * [x] [`_mm512_mask_andnot_epi32`] + * [x] [`_mm512_maskz_andnot_epi32`] + * [x] [`_mm_mask_andnot_epi32`] + * [x] [`_mm_maskz_andnot_epi32`] + * [x] [`_mm256_mask_andnot_epi32`] + * [x] [`_mm256_maskz_andnot_epi32`] + * [x] [`_mm512_andnot_epi64`] + * [x] [`_mm512_mask_andnot_epi64`] + * [x] [`_mm512_maskz_andnot_epi64`] + * [x] [`_mm_mask_andnot_epi64`] + * [x] [`_mm_maskz_andnot_epi64`] + * [x] [`_mm256_mask_andnot_epi64`] + * [x] [`_mm256_maskz_andnot_epi64`] + * [x] [`_mm512_andnot_si512`] + * [x] [`_mm512_unpackhi_epi32`] + * [x] [`_mm512_mask_unpackhi_epi32`] + * [x] [`_mm512_maskz_unpackhi_epi32`] + * [x] [`_mm_mask_unpackhi_epi32`] + * [x] [`_mm_maskz_unpackhi_epi32`] + * [x] [`_mm256_mask_unpackhi_epi32`] + * [x] [`_mm256_maskz_unpackhi_epi32`] + * [x] [`_mm512_unpackhi_epi64`] + * [x] [`_mm512_mask_unpackhi_epi64`] + * [x] [`_mm512_maskz_unpackhi_epi64`] + * [x] [`_mm_mask_unpackhi_epi64`] + * [x] [`_mm_maskz_unpackhi_epi64`] + * [x] [`_mm256_mask_unpackhi_epi64`] + * [x] [`_mm256_maskz_unpackhi_epi64`] + * [x] [`_mm512_unpackhi_ps`] + * [x] [`_mm512_mask_unpackhi_ps`] + * [x] [`_mm512_maskz_unpackhi_ps`] + * [x] [`_mm_mask_unpackhi_ps`] + * [x] [`_mm_maskz_unpackhi_ps`] + * [x] [`_mm256_mask_unpackhi_ps`] + * [x] [`_mm256_maskz_unpackhi_ps`] + * [x] [`_mm512_unpackhi_pd`] + * [x] [`_mm512_mask_unpackhi_pd`] + * [x] [`_mm512_maskz_unpackhi_pd`] + * [x] [`_mm_mask_unpackhi_pd`] + * [x] [`_mm_maskz_unpackhi_pd`] + * [x] [`_mm256_mask_unpackhi_pd`] + * [x] [`_mm256_maskz_unpackhi_pd`] + * [x] [`_mm512_unpacklo_epi32`] + * [x] [`_mm512_mask_unpacklo_epi32`] + * [x] [`_mm512_maskz_unpacklo_epi32`] + * [x] [`_mm_mask_unpacklo_epi32`] + * [x] [`_mm_maskz_unpacklo_epi32`] + * [x] [`_mm256_mask_unpacklo_epi32`] + * [x] [`_mm256_maskz_unpacklo_epi32`] + * [x] [`_mm512_unpacklo_epi64`] + * [x] [`_mm512_mask_unpacklo_epi64`] + * [x] [`_mm512_maskz_unpacklo_epi64`] + * [x] [`_mm_mask_unpacklo_epi64`] + * [x] [`_mm_maskz_unpacklo_epi64`] + * [x] [`_mm256_mask_unpacklo_epi64`] + * [x] [`_mm256_maskz_unpacklo_epi64`] + * [x] [`_mm512_unpacklo_ps`] + * [x] [`_mm512_mask_unpacklo_ps`] + * [x] [`_mm512_maskz_unpacklo_ps`] + * [x] [`_mm_mask_unpacklo_ps`] + * [x] [`_mm_maskz_unpacklo_ps`] + * [x] [`_mm256_mask_unpacklo_ps`] + * [x] [`_mm256_maskz_unpacklo_ps`] + * [x] [`_mm512_unpacklo_pd`] + * [x] [`_mm512_mask_unpacklo_pd`] + * [x] [`_mm512_maskz_unpacklo_pd`] + * [x] [`_mm_mask_unpacklo_pd`] + * [x] [`_mm_maskz_unpacklo_pd`] + * [x] [`_mm256_mask_unpacklo_pd`] + * [x] [`_mm256_maskz_unpacklo_pd`] + * [x] [`_mm512_mask_blend_epi32`] + * [x] [`_mm_mask_blend_epi32`] + * [x] [`_mm256_mask_blend_epi32`] + * [x] [`_mm512_mask_blend_epi64`] + * [x] [`_mm_mask_blend_epi64`] + * [x] [`_mm256_mask_blend_epi64`] + * [x] [`_mm512_mask_blend_ps`] + * [x] [`_mm_mask_blend_ps`] + * [x] [`_mm256_mask_blend_ps`] + * [x] [`_mm512_mask_blend_pd`] + * [x] [`_mm_mask_blend_pd`] + * [x] [`_mm256_mask_blend_pd`] + * [x] [`_mm512_broadcast_f32x4`] + * [x] [`_mm512_mask_broadcast_f32x4`] + * [x] [`_mm512_maskz_broadcast_f32x4`] + * [x] [`_mm256_broadcast_f32x4`] + * [x] [`_mm256_mask_broadcast_f32x4`] + * [x] [`_mm256_maskz_broadcast_f32x4`] + * [x] [`_mm512_broadcast_f64x4`] + * [x] [`_mm512_mask_broadcast_f64x4`] + * [x] [`_mm512_maskz_broadcast_f64x4`] + * [x] [`_mm512_broadcast_i32x4`] + * [x] [`_mm512_mask_broadcast_i32x4`] + * [x] [`_mm512_maskz_broadcast_i32x4`] + * [x] [`_mm256_broadcast_i32x4`] + * [x] [`_mm256_mask_broadcast_i32x4`] + * [x] [`_mm256_maskz_broadcast_i32x4`] + * [x] [`_mm512_broadcast_i64x4`] + * [x] [`_mm512_mask_broadcast_i64x4`] + * [x] [`_mm512_maskz_broadcast_i64x4`] + * [x] [`_mm512_broadcastd_epi32`] + * [x] [`_mm512_mask_broadcastd_epi32`] + * [x] [`_mm512_maskz_broadcastd_epi32`] + * [x] [`_mm_mask_broadcastd_epi32`] + * [x] [`_mm_maskz_broadcastd_epi32`] + * [x] [`_mm256_mask_broadcastd_epi32`] + * [x] [`_mm256_maskz_broadcastd_epi32`] + * [x] [`_mm512_broadcastq_epi64`] + * [x] [`_mm512_mask_broadcastq_epi64`] + * [x] [`_mm512_maskz_broadcastq_epi64`] + * [x] [`_mm_mask_broadcastq_epi64`] + * [x] [`_mm_maskz_broadcastq_epi64`] + * [x] [`_mm256_mask_broadcastq_epi64`] + * [x] [`_mm256_maskz_broadcastq_epi64`] + * [x] [`_mm512_broadcastss_ps`] + * [x] [`_mm512_mask_broadcastss_ps`] + * [x] [`_mm512_maskz_broadcastss_ps`] + * [x] [`_mm_mask_broadcastss_ps`] + * [x] [`_mm_maskz_broadcastss_ps`] + * [x] [`_mm256_mask_broadcastss_ps`] + * [x] [`_mm256_maskz_broadcastss_ps`] + * [x] [`_mm512_broadcastsd_pd`] + * [x] [`_mm512_mask_broadcastsd_pd`] + * [x] [`_mm512_maskz_broadcastsd_pd`] + * [x] [`_mm256_mask_broadcastsd_pd`] + * [x] [`_mm256_maskz_broadcastsd_pd`] + * [x] [`_mm512_shuffle_epi32`] + * [x] [`_mm512_mask_shuffle_epi32`] + * [x] [`_mm512_maskz_shuffle_epi32`] + * [x] [`_mm_mask_shuffle_epi32`] + * [x] [`_mm_maskz_shuffle_epi32`] + * [x] [`_mm256_mask_shuffle_epi32`] + * [x] [`_mm256_maskz_shuffle_epi32`] + * [x] [`_mm512_shuffle_ps`] + * [x] [`_mm512_mask_shuffle_ps`] + * [x] [`_mm512_maskz_shuffle_ps`] + * [x] [`_mm_mask_shuffle_ps`] + * [x] [`_mm_maskz_shuffle_ps`] + * [x] [`_mm256_mask_shuffle_ps`] + * [x] [`_mm256_maskz_shuffle_ps`] + * [x] [`_mm512_shuffle_pd`] + * [x] [`_mm512_mask_shuffle_pd`] + * [x] [`_mm512_maskz_shuffle_pd`] + * [x] [`_mm_mask_shuffle_pd`] + * [x] [`_mm_maskz_shuffle_pd`] + * [x] [`_mm256_mask_shuffle_pd`] + * [x] [`_mm256_maskz_shuffle_pd`] + * [x] [`_mm512_shuffle_i32x4`] + * [x] [`_mm512_mask_shuffle_i32x4`] + * [x] [`_mm512_maskz_shuffle_i32x4`] + * [x] [`_mm256_mask_shuffle_i32x4`] + * [x] [`_mm256_maskz_shuffle_i32x4`] + * [x] [`_mm256_shuffle_i32x4`] + * [x] [`_mm512_shuffle_i64x2`] + * [x] [`_mm512_mask_shuffle_i64x2`] + * [x] [`_mm512_maskz_shuffle_i64x2`] + * [x] [`_mm256_mask_shuffle_i64x2`] + * [x] [`_mm256_maskz_shuffle_i64x2`] + * [x] [`_mm256_shuffle_i64x2`] + * [x] [`_mm512_shuffle_f32x4`] + * [x] [`_mm512_mask_shuffle_f32x4`] + * [x] [`_mm512_maskz_shuffle_f32x4`] + * [x] [`_mm256_mask_shuffle_f32x4`] + * [x] [`_mm256_maskz_shuffle_f32x4`] + * [x] [`_mm256_shuffle_f32x4`] + * [x] [`_mm512_shuffle_f64x2`] + * [x] [`_mm512_mask_shuffle_f64x2`] + * [x] [`_mm512_maskz_shuffle_f64x2`] + * [x] [`_mm256_mask_shuffle_f64x2`] + * [x] [`_mm256_maskz_shuffle_f64x2`] + * [x] [`_mm256_shuffle_f64x2`] + * [x] [`_mm512_alignr_epi32`] + * [x] [`_mm512_mask_alignr_epi32`] + * [x] [`_mm512_maskz_alignr_epi32`] + * [x] [`_mm_alignr_epi32`] + * [x] [`_mm_mask_alignr_epi32`] + * [x] [`_mm_maskz_alignr_epi32`] + * [x] [`_mm256_alignr_epi32`] + * [x] [`_mm256_mask_alignr_epi32`] + * [x] [`_mm256_maskz_alignr_epi32`] + * [x] [`_mm512_alignr_epi64`] + * [x] [`_mm512_mask_alignr_epi64`] + * [x] [`_mm512_maskz_alignr_epi64`] + * [x] [`_mm_alignr_epi64`] + * [x] [`_mm_mask_alignr_epi64`] + * [x] [`_mm_maskz_alignr_epi64`] + * [x] [`_mm256_alignr_epi64`] + * [x] [`_mm256_mask_alignr_epi64`] + * [x] [`_mm256_maskz_alignr_epi64`] + * [x] [`_mm512_permute_ps`] + * [x] [`_mm512_mask_permute_ps`] + * [x] [`_mm512_maskz_permute_ps`] + * [x] [`_mm_mask_permute_ps`] + * [x] [`_mm_maskz_permute_ps`] + * [x] [`_mm256_mask_permute_ps`] + * [x] [`_mm256_maskz_permute_ps`] + * [x] [`_mm512_permute_pd`] + * [x] [`_mm512_mask_permute_pd`] + * [x] [`_mm512_maskz_permute_pd`] + * [x] [`_mm_mask_permute_pd`] + * [x] [`_mm_maskz_permute_pd`] + * [x] [`_mm256_mask_permute_pd`] + * [x] [`_mm256_maskz_permute_pd`] + * [x] [`_mm512_permutevar_epi32`] + * [x] [`_mm512_mask_permutevar_epi32`] + * [x] [`_mm512_permutevar_ps`] + * [x] [`_mm512_mask_permutevar_ps`] + * [x] [`_mm512_maskz_permutevar_ps`] + * [x] [`_mm_mask_permutevar_ps`] + * [x] [`_mm_maskz_permutevar_ps`] + * [x] [`_mm256_mask_permutevar_ps`] + * [x] [`_mm256_maskz_permutevar_ps`] + * [x] [`_mm512_permutevar_pd`] + * [x] [`_mm512_mask_permutevar_pd`] + * [x] [`_mm512_maskz_permutevar_pd`] + * [x] [`_mm_mask_permutevar_pd`] + * [x] [`_mm_maskz_permutevar_pd`] + * [x] [`_mm256_mask_permutevar_pd`] + * [x] [`_mm256_maskz_permutevar_pd`] + * [x] [`_mm512_permutex2var_epi32`] + * [x] [`_mm512_mask_permutex2var_epi32`] + * [x] [`_mm512_maskz_permutex2var_epi32`] + * [x] [`_mm512_mask2_permutex2var_epi32`] + * [x] [`_mm_mask_permutex2var_epi32`] + * [x] [`_mm_mask2_permutex2var_epi32`] + * [x] [`_mm_maskz_permutex2var_epi32`] + * [x] [`_mm_permutex2var_epi32`] + * [x] [`_mm256_mask_permutex2var_epi32`] + * [x] [`_mm256_mask2_permutex2var_epi32`] + * [x] [`_mm256_maskz_permutex2var_epi32`] + * [x] [`_mm256_permutex2var_epi32`] + * [x] [`_mm512_permutex2var_epi64`] + * [x] [`_mm512_mask_permutex2var_epi64`] + * [x] [`_mm512_maskz_permutex2var_epi64`] + * [x] [`_mm512_mask2_permutex2var_epi64`] + * [x] [`_mm_mask_permutex2var_epi64`] + * [x] [`_mm_mask2_permutex2var_epi64`] + * [x] [`_mm_maskz_permutex2var_epi64`] + * [x] [`_mm_permutex2var_epi64`] + * [x] [`_mm256_mask_permutex2var_epi64`] + * [x] [`_mm256_mask2_permutex2var_epi64`] + * [x] [`_mm256_maskz_permutex2var_epi64`] + * [x] [`_mm256_permutex2var_epi64`] + * [x] [`_mm512_permutex2var_ps`] + * [x] [`_mm512_mask_permutex2var_ps`] + * [x] [`_mm512_maskz_permutex2var_ps`] + * [x] [`_mm512_mask2_permutex2var_ps`] + * [x] [`_mm_mask_permutex2var_ps`] + * [x] [`_mm_mask2_permutex2var_ps`] + * [x] [`_mm_maskz_permutex2var_ps`] + * [x] [`_mm_permutex2var_ps`] + * [x] [`_mm256_mask_permutex2var_ps`] + * [x] [`_mm256_mask2_permutex2var_ps`] + * [x] [`_mm256_maskz_permutex2var_ps`] + * [x] [`_mm256_permutex2var_ps`] + * [x] [`_mm512_permutex2var_pd`] + * [x] [`_mm512_mask_permutex2var_pd`] + * [x] [`_mm512_maskz_permutex2var_pd`] + * [x] [`_mm512_mask2_permutex2var_pd`] + * [x] [`_mm_mask_permutex2var_pd`] + * [x] [`_mm_mask2_permutex2var_pd`] + * [x] [`_mm_maskz_permutex2var_pd`] + * [x] [`_mm_permutex2var_pd`] + * [x] [`_mm256_mask_permutex2var_pd`] + * [x] [`_mm256_mask2_permutex2var_pd`] + * [x] [`_mm256_maskz_permutex2var_pd`] + * [x] [`_mm256_permutex2var_pd`] + * [x] [`_mm512_permutex_epi64`] + * [x] [`_mm512_mask_permutex_epi64`] + * [x] [`_mm512_maskz_permutex_epi64`] + * [x] [`_mm256_mask_permutex_epi64`] + * [x] [`_mm256_maskz_permutex_epi64`] + * [x] [`_mm256_permutex_epi64`] + * [x] [`_mm512_permutex_pd`] + * [x] [`_mm512_mask_permutex_pd`] + * [x] [`_mm512_maskz_permutex_pd`] + * [x] [`_mm256_mask_permutex_pd`] + * [x] [`_mm256_maskz_permutex_pd`] + * [x] [`_mm256_permutex_pd`] + * [x] [`_mm512_permutexvar_epi32`] + * [x] [`_mm512_mask_permutexvar_epi32`] + * [x] [`_mm512_maskz_permutexvar_epi32`] + * [x] [`_mm256_mask_permutexvar_epi32`] + * [x] [`_mm256_maskz_permutexvar_epi32`] + * [x] [`_mm256_permutexvar_epi32`] + * [x] [`_mm512_permutexvar_epi64`] + * [x] [`_mm512_mask_permutexvar_epi64`] + * [x] [`_mm512_maskz_permutexvar_epi64`] + * [x] [`_mm256_mask_permutexvar_epi64`] + * [x] [`_mm256_maskz_permutexvar_epi64`] + * [x] [`_mm256_permutexvar_epi64`] + * [x] [`_mm512_permutexvar_ps`] + * [x] [`_mm512_mask_permutexvar_ps`] + * [x] [`_mm512_maskz_permutexvar_ps`] + * [x] [`_mm256_mask_permutexvar_ps`] + * [x] [`_mm256_maskz_permutexvar_ps`] + * [x] [`_mm256_permutexvar_ps`] + * [x] [`_mm512_permutexvar_pd`] + * [x] [`_mm512_mask_permutexvar_pd`] + * [x] [`_mm512_maskz_permutexvar_pd`] + * [x] [`_mm256_mask_permutexvar_pd`] + * [x] [`_mm256_maskz_permutexvar_pd`] + * [x] [`_mm256_permutexvar_pd`] + * [x] [`_mm512_i32gather_epi32`] + * [x] [`_mm512_mask_i32gather_epi32`] + * [_] [`_mm_mmask_i32gather_epi32`] //need i1 + * [_] [`_mm256_mmask_i32gather_epi32`] //need i1 + * [x] [`_mm512_i32gather_epi64`] + * [x] [`_mm512_mask_i32gather_epi64`] + * [_] [`_mm_mmask_i32gather_epi64`] //need i1 + * [_] [`_mm256_mmask_i32gather_epi64`] //need i1 + * [x] [`_mm512_i32gather_ps`] + * [x] [`_mm512_mask_i32gather_ps`] + * [_] [`_mm_mmask_i32gather_ps`] //need i1 + * [_] [`_mm256_mmask_i32gather_ps`] //need i1 + * [x] [`_mm512_i32gather_pd`] + * [x] [`_mm512_mask_i32gather_pd`] + * [_] [`_mm_mmask_i32gather_pd`] //need i1 + * [_] [`_mm256_mmask_i32gather_pd`] //need i1 + * [x] [`_mm512_i64gather_epi32`] + * [x] [`_mm512_mask_i64gather_epi32`] + * [_] [`_mm_mmask_i64gather_epi32`] //need i1 + * [_] [`_mm256_mmask_i64gather_epi32`] //need i1 + * [x] [`_mm512_i64gather_epi64`] + * [x] [`_mm512_mask_i64gather_epi64`] + * [_] [`_mm_mmask_i64gather_epi64`] //need i1 + * [_] [`_mm256_mmask_i64gather_epi64`] //need i1 + * [x] [`_mm512_i64gather_ps`] + * [x] [`_mm512_mask_i64gather_ps`] + * [_] [`_mm_mmask_i64gather_ps`] //need i1 + * [_] [`_mm256_mmask_i64gather_ps`] //need i1 + * [x] [`_mm512_i64gather_pd`] + * [x] [`_mm512_mask_i64gather_pd`] + * [_] [`_mm_mmask_i64gather_pd`] //need i1 + * [_] [`_mm256_mmask_i64gather_pd`] //need i1 + * [ ] [`_mm512_i32extgather_epi32`] //not in llvm + * [ ] [`_mm512_mask_i32extgather_epi32`] //not in llvm + * [ ] [`_mm512_i32extgather_ps`] // not in llvm + * [ ] [`_mm512_mask_i32extgather_ps`] //not in llvm + * [ ] [`_mm512_i32loextgather_epi64`] //not in llvm + * [ ] [`_mm512_mask_i32loextgather_epi64`] //not in llvm + * [ ] [`_mm512_i32loextgather_pd`] //not in llvm + * [ ] [`_mm512_mask_i32loextgather_pd`] //not in llvm + * [ ] [`_mm512_i32logather_epi64`] //not in llvm + * [ ] [`_mm512_mask_i32logather_epi64`] //not in llvm + * [ ] [`_mm512_i32logather_pd`] //not in llvm + * [ ] [`_mm512_mask_i32logather_pd`] //not in llvm + * [x] [`_mm512_i32scatter_epi32`] + * [x] [`_mm512_mask_i32scatter_epi32`] + * [_] [`_mm_i32scatter_epi32`] //need i1 + * [_] [`_mm_mask_i32scatter_epi32`] // need i1 + * [_] [`_mm256_i32scatter_epi32`] //need i1 + * [_] [`_mm256_mask_i32scatter_epi32`] //need i1 + * [x] [`_mm512_i32scatter_epi64`] + * [x] [`_mm512_mask_i32scatter_epi64`] + * [_] [`_mm_i32scatter_epi64`]//need i1 + * [_] [`_mm_mask_i32scatter_epi64`] //need i1 + * [_] [`_mm256_i32scatter_epi64`] //need i1 + * [_] [`_mm256_mask_i32scatter_epi64`] //need i1 + * [x] [`_mm512_i32scatter_ps`] + * [x] [`_mm512_mask_i32scatter_ps`] + * [_] [`_mm_i32scatter_ps`] //need i1 + * [_] [`_mm_mask_i32scatter_ps`] //need i1 + * [_] [`_mm256_i32scatter_ps`] //need i1 + * [_] [`_mm256_mask_i32scatter_ps`] //need i1 + * [x] [`_mm512_i32scatter_pd`] + * [x] [`_mm512_mask_i32scatter_pd`] + * [_] [`_mm_i32scatter_pd`] //need i1 + * [_] [`_mm_mask_i32scatter_pd`] //need i1 + * [_] [`_mm256_i32scatter_pd`] //need i1 + * [_] [`_mm256_mask_i32scatter_pd`] //need i1 + * [x] [`_mm512_i64scatter_epi32`] + * [x] [`_mm512_mask_i64scatter_epi32`] + * [_] [`_mm_i64scatter_epi32`] //need i1 + * [_] [`_mm_mask_i64scatter_epi32`] //need i1 + * [_] [`_mm256_i64scatter_epi32`] //need i1 + * [_] [`_mm256_mask_i64scatter_epi32`] //need i1 + * [x] [`_mm512_mask_i64scatter_epi64`] + * [x] [`_mm512_i64scatter_epi64`] + * [_] [`_mm_i64scatter_epi64`] //need i1 + * [_] [`_mm_mask_i64scatter_epi64`] //need i1 + * [_] [`_mm256_i64scatter_epi64`] //need i1 + * [_] [`_mm256_mask_i64scatter_epi64`] //need i1 + * [x] [`_mm512_i64scatter_ps`] + * [x] [`_mm512_mask_i64scatter_ps`] + * [_] [`_mm_i64scatter_ps`] //need i1 + * [_] [`_mm_mask_i64scatter_ps`] //need i1 + * [_] [`_mm256_i64scatter_ps`] //need i1 + * [_] [`_mm256_mask_i64scatter_ps`] //need i1 + * [x] [`_mm512_i64scatter_pd`] + * [x] [`_mm512_mask_i64scatter_pd`] + * [_] [`_mm_i64scatter_pd`] //need i1 + * [_] [`_mm_mask_i64scatter_pd`] //need i1 + * [_] [`_mm256_i64scatter_pd`] //need i1 + * [_] [`_mm256_mask_i64scatter_pd`] //need i1 + * [ ] [`_mm512_i32extscatter_epi32`] //not in llvm + * [ ] [`_mm512_mask_i32extscatter_epi32`] //not in llvm + * [ ] [`_mm512_i32extscatter_ps`] //not in llvm + * [ ] [`_mm512_mask_i32extscatter_ps`] //not in llvm + * [ ] [`_mm512_i32loextscatter_epi64`] //not in llvm + * [ ] [`_mm512_mask_i32loextscatter_epi64`] //not in llvm + * [ ] [`_mm512_i32loextscatter_pd`] //not in llvm + * [ ] [`_mm512_mask_i32loextscatter_pd`] //not in llvm + * [ ] [`_mm512_i32loscatter_epi64`] //not in llvm + * [ ] [`_mm512_mask_i32loscatter_epi64`] //not in llvm + * [ ] [`_mm512_i32loscatter_pd`] //not in llvm + * [ ] [`_mm512_mask_i32loscatter_pd`] //not in llvm + * [x] [`_mm512_inserti32x4`] + * [x] [`_mm512_mask_inserti32x4`] + * [x] [`_mm512_maskz_inserti32x4`] + * [x] [`_mm256_inserti32x4`] + * [x] [`_mm256_mask_inserti32x4`] + * [x] [`_mm256_maskz_inserti32x4`] + * [x] [`_mm512_inserti64x4`] + * [x] [`_mm512_mask_inserti64x4`] + * [x] [`_mm512_maskz_inserti64x4`] + * [x] [`_mm512_insertf32x4`] + * [x] [`_mm512_mask_insertf32x4`] + * [x] [`_mm512_maskz_insertf32x4`] + * [x] [`_mm256_insertf32x4`] + * [x] [`_mm256_mask_insertf32x4`] + * [x] [`_mm256_maskz_insertf32x4`] + * [x] [`_mm512_insertf64x4`] + * [x] [`_mm512_mask_insertf64x4`] + * [x] [`_mm512_maskz_insertf64x4`] + * [x] [`_mm512_extracti32x4_epi32`] + * [x] [`_mm512_mask_extracti32x4_epi32`] + * [x] [`_mm512_maskz_extracti32x4_epi32`] + * [x] [`_mm256_extracti32x4_epi32`] + * [x] [`_mm256_mask_extracti32x4_epi32`] + * [x] [`_mm256_maskz_extracti32x4_epi32`] + * [x] [`_mm512_extracti64x4_epi64`] + * [x] [`_mm512_mask_extracti64x4_epi64`] + * [x] [`_mm512_maskz_extracti64x4_epi64`] + * [x] [`_mm512_extractf32x4_ps`] + * [x] [`_mm512_mask_extractf32x4_ps`] + * [x] [`_mm512_maskz_extractf32x4_ps`] + * [x] [`_mm256_extractf32x4_ps`] + * [x] [`_mm256_mask_extractf32x4_ps`] + * [x] [`_mm256_maskz_extractf32x4_ps`] + * [x] [`_mm512_extractf64x4_pd`] + * [x] [`_mm512_mask_extractf64x4_pd`] + * [x] [`_mm512_maskz_extractf64x4_pd`] + * [x] [`_mm512_maskz_compress_epi32`] + * [x] [`_mm512_mask_compress_epi32`] + * [x] [`_mm_mask_compress_epi32`] + * [x] [`_mm_maskz_compress_epi32`] + * [x] [`_mm256_mask_compress_epi32`] + * [x] [`_mm256_maskz_compress_epi32`] + * [x] [`_mm512_mask_compress_epi64`] + * [x] [`_mm512_maskz_compress_epi64`] + * [x] [`_mm_mask_compress_epi64`] + * [x] [`_mm_maskz_compress_epi64`] + * [x] [`_mm256_mask_compress_epi64`] + * [x] [`_mm256_maskz_compress_epi64`] + * [x] [`_mm512_mask_compress_ps`] + * [x] [`_mm512_maskz_compress_ps`] + * [x] [`_mm_mask_compress_ps`] + * [x] [`_mm_maskz_compress_ps`] + * [x] [`_mm256_mask_compress_ps`] + * [x] [`_mm256_maskz_compress_ps`] + * [x] [`_mm512_mask_compress_pd`] + * [x] [`_mm512_maskz_compress_pd`] + * [x] [`_mm_mask_compress_pd`] + * [x] [`_mm_maskz_compress_pd`] + * [x] [`_mm256_mask_compress_pd`] + * [x] [`_mm256_maskz_compress_pd`] + * [ ] [`_mm512_mask_compressstoreu_epi32`] //need i1 + * [_] [`_mm_mask_compressstoreu_epi32`] //need i1 + * [_] [`_mm256_mask_compressstoreu_epi32`] //need i1 + * [ ] [`_mm512_mask_compressstoreu_epi64`] //need i1 + * [_] [`_mm_mask_compressstoreu_epi64`] //need i1 + * [_] [`_mm256_mask_compressstoreu_epi64`] //need i1 + * [ ] [`_mm512_mask_compressstoreu_ps`] //need i1 + * [_] [`_mm_mask_compressstoreu_ps`] //need i1 + * [_] [`_mm256_mask_compressstoreu_ps`] //need i1 + * [ ] [`_mm512_mask_compressstoreu_pd`] //need i1 + * [_] [`_mm_mask_compressstoreu_pd`] //need i1 + * [_] [`_mm256_mask_compressstoreu_pd`] //need i1 + * [x] [`_mm512_mask_expand_epi32`] + * [x] [`_mm512_maskz_expand_epi32`] + * [x] [`_mm_mask_expand_epi32`] + * [x] [`_mm_maskz_expand_epi32`] + * [x] [`_mm256_mask_expand_epi32`] + * [x] [`_mm256_maskz_expand_epi32`] + * [x] [`_mm512_mask_expand_epi64`] + * [x] [`_mm512_maskz_expand_epi64`] + * [x] [`_mm_mask_expand_epi64`] + * [x] [`_mm_maskz_expand_epi64`] + * [x] [`_mm256_mask_expand_epi64`] + * [x] [`_mm256_maskz_expand_epi64`] + * [x] [`_mm512_mask_expand_ps`] + * [x] [`_mm512_maskz_expand_ps`] + * [x] [`_mm_mask_expand_ps`] + * [x] [`_mm_maskz_expand_ps`] + * [x] [`_mm256_mask_expand_ps`] + * [x] [`_mm256_maskz_expand_ps`] + * [x] [`_mm512_mask_expand_pd`] + * [x] [`_mm512_maskz_expand_pd`] + * [x] [`_mm_mask_expand_pd`] + * [x] [`_mm_maskz_expand_pd`] + * [x] [`_mm256_mask_expand_pd`] + * [x] [`_mm256_maskz_expand_pd`] + * [ ] [`_mm512_mask_expandloadu_epi32`] //need i1 + * [ ] [`_mm512_maskz_expandloadu_epi32`] //need i1 + * [_] [`_mm_mask_expandloadu_epi32`] //need i1 + * [_] [`_mm_maskz_expandloadu_epi32`] //need i1 + * [_] [`_mm256_mask_expandloadu_epi32`] //need i1 + * [_] [`_mm256_maskz_expandloadu_epi32`] //need i1 + * [ ] [`_mm512_mask_expandloadu_epi64`] //need i1 + * [ ] [`_mm512_maskz_expandloadu_epi64`] //need i1 + * [_] [`_mm_mask_expandloadu_epi64`] //need i1 + * [_] [`_mm_maskz_expandloadu_epi64`] //need i1 + * [_] [`_mm256_mask_expandloadu_epi64`] //need i1 + * [_] [`_mm256_maskz_expandloadu_epi64`] //need i1 + * [ ] [`_mm512_mask_expandloadu_ps`] //need i1 + * [ ] [`_mm512_maskz_expandloadu_ps`] //need i1 + * [_] [`_mm_mask_expandloadu_ps`] //need i1 + * [_] [`_mm_maskz_expandloadu_ps`] //need i1 + * [_] [`_mm256_mask_expandloadu_ps`] //need i1 + * [_] [`_mm256_maskz_expandloadu_ps`] //need i1 + * [ ] [`_mm512_mask_expandloadu_pd`] //need i1 + * [ ] [`_mm512_maskz_expandloadu_pd`] //need i1 + * [_] [`_mm_mask_expandloadu_pd`] //need i1 + * [_] [`_mm_maskz_expandloadu_pd`] //need i1 + * [_] [`_mm256_mask_expandloadu_pd`] //need i1 + * [_] [`_mm256_maskz_expandloadu_pd`] //need i1 + * [x] [`_mm512_zextpd128_pd512`] + * [x] [`_mm512_zextpd256_pd512`] + * [x] [`_mm512_zextps128_ps512`] + * [x] [`_mm512_zextps256_ps512`] + * [x] [`_mm512_zextsi128_si512`] + * [x] [`_mm512_zextsi256_si512`] + * [x] [`_mm512_undefined_epi32`] + * [x] [`_mm512_undefined_pd`] + * [x] [`_mm512_undefined_ps`] + * [x] [`_mm512_undefined`] + * [ ] [`_mm512_svml_round_pd`] //not in llvm + * [x] [`_mm512_ternarylogic_epi32`] + * [x] [`_mm512_mask_ternarylogic_epi32`] + * [x] [`_mm512_maskz_ternarylogic_epi32`] + * [x] [`_mm_mask_ternarylogic_epi32`] + * [x] [`_mm_maskz_ternarylogic_epi32`] + * [x] [`_mm_ternarylogic_epi32`] + * [x] [`_mm256_mask_ternarylogic_epi32`] + * [x] [`_mm256_maskz_ternarylogic_epi32`] + * [x] [`_mm256_ternarylogic_epi32`] + * [x] [`_mm512_ternarylogic_epi64`] + * [x] [`_mm512_mask_ternarylogic_epi64`] + * [x] [`_mm512_maskz_ternarylogic_epi64`] + * [x] [`_mm_mask_ternarylogic_epi64`] + * [x] [`_mm_maskz_ternarylogic_epi64`] + * [x] [`_mm_ternarylogic_epi64`] + * [x] [`_mm256_mask_ternarylogic_epi64`] + * [x] [`_mm256_maskz_ternarylogic_epi64`] + * [x] [`_mm256_ternarylogic_epi64`] + * [x] [`_mm512_test_epi32_mask`] + * [x] [`_mm512_mask_test_epi32_mask`] + * [x] [`_mm_mask_test_epi32_mask`] + * [x] [`_mm_test_epi32_mask`] + * [x] [`_mm256_mask_test_epi32_mask`] + * [x] [`_mm256_test_epi32_mask`] + * [x] [`_mm512_test_epi64_mask`] + * [x] [`_mm512_mask_test_epi64_mask`] + * [x] [`_mm_mask_test_epi64_mask`] + * [x] [`_mm_test_epi64_mask`] + * [x] [`_mm256_mask_test_epi64_mask`] + * [x] [`_mm256_test_epi64_mask`] + * [x] [`_mm512_testn_epi32_mask`] + * [x] [`_mm512_mask_testn_epi32_mask`] + * [x] [`_mm_mask_testn_epi32_mask`] + * [x] [`_mm_testn_epi32_mask`] + * [x] [`_mm256_mask_testn_epi32_mask`] + * [x] [`_mm256_testn_epi32_mask`] + * [x] [`_mm512_testn_epi64_mask`] + * [x] [`_mm512_mask_testn_epi64_mask`] + * [x] [`_mm_mask_testn_epi64_mask`] + * [x] [`_mm_testn_epi64_mask`] + * [x] [`_mm256_mask_testn_epi64_mask`] + * [x] [`_mm256_testn_epi64_mask`] + * [x] [`_mm512_set1_epi8`] + * [x] [`_mm512_set1_epi16`] + * [x] [`_mm512_set1_epi32`] + * [x] [`_mm512_mask_set1_epi32`] + * [x] [`_mm512_maskz_set1_epi32`] + * [x] [`_mm_mask_set1_epi32`] + * [x] [`_mm_maskz_set1_epi32`] + * [x] [`_mm256_mask_set1_epi32`] + * [x] [`_mm256_maskz_set1_epi32`] + * [x] [`_mm512_set1_epi64`] + * [x] [`_mm512_mask_set1_epi64`] + * [x] [`_mm512_maskz_set1_epi64`] + * [x] [`_mm_mask_set1_epi64`] + * [x] [`_mm_maskz_set1_epi64`] + * [x] [`_mm256_mask_set1_epi64`] + * [x] [`_mm256_maskz_set1_epi64`] + * [x] [`_mm512_set1_ps`] + * [x] [`_mm512_set1_pd`] + * [x] [`_mm512_set4_epi32`] + * [x] [`_mm512_set4_epi64`] + * [x] [`_mm512_set4_pd`] + * [x] [`_mm512_set4_ps`] + * [x] [`_mm512_set_epi16`] + * [x] [`_mm512_set_epi32`] + * [x] [`_mm512_set_epi64`] + * [x] [`_mm512_set_epi8`] + * [x] [`_mm512_set_pd`] + * [x] [`_mm512_set_ps`] + * [x] [`_mm512_setr4_epi32`] + * [x] [`_mm512_setr4_epi64`] + * [x] [`_mm512_setr4_pd`] + * [x] [`_mm512_setr4_ps`] + * [x] [`_mm512_setr_epi32`] + * [x] [`_mm512_setr_epi64`] + * [x] [`_mm512_setr_pd`] + * [x] [`_mm512_setr_ps`] + * [x] [`_mm512_setzero_epi32`] + * [x] [`_mm512_setzero_pd`] + * [x] [`_mm512_setzero_ps`] + * [x] [`_mm512_setzero_si512`] + * [x] [`_mm512_setzero`] + * [x] [`_mm512_load_epi32`] + * [ ] [`_mm512_mask_load_epi32`] //need i1 + * [ ] [`_mm512_maskz_load_epi32`] //need i1 + * [x] [`_mm_load_epi32`] + * [_] [`_mm_mask_load_epi32`] //need i1 + * [_] [`_mm_maskz_load_epi32`] //need i1 + * [x] [`_mm256_load_epi32`] + * [_] [`_mm256_mask_load_epi32`] //need i1 + * [_] [`_mm256_maskz_load_epi32`] //need i1 + * [x] [`_mm512_load_epi64`] + * [ ] [`_mm512_mask_load_epi64`] //need i1 + * [ ] [`_mm512_maskz_load_epi64`] //need i1 + * [x] [`_mm_load_epi64`] //need i1 + * [_] [`_mm_mask_load_epi64`] //need i1 + * [_] [`_mm_maskz_load_epi64`] //need i1 + * [x] [`_mm256_load_epi64`] //need i1 + * [_] [`_mm256_mask_load_epi64`] //need i1 + * [_] [`_mm256_maskz_load_epi64`] //need i1 + * [x] [`_mm512_load_ps`] + * [ ] [`_mm512_mask_load_ps`] //need i1 + * [ ] [`_mm512_maskz_load_ps`] //need i1 + * [_] [`_mm_maskz_load_ps`] //need i + * [_] [`_mm_mask_load_ps`] //need i1 + * [_] [`_mm_maskz_load_ps`] //need i1 + * [_] [`_mm256_mask_load_ps`] //need i1 + * [_] [`_mm256_maskz_load_ps`] //need i1 + * [x] [`_mm512_load_pd`] + * [ ] [`_mm512_mask_load_pd`] //need i1 + * [ ] [`_mm512_maskz_load_pd`] //need i1 + * [_] [`_mm_mask_load_pd`] //need i1 + * [_] [`_mm_maskz_load_pd`] //need i1 + * [_] [`_mm256_mask_load_pd`] //need i1 + * [_] [`_mm256_maskz_load_pd`] //need i1 + * [x] [`_mm512_load_si512`] * [x] [`_mm512_loadu_epi32`] + * [ ] [`_mm512_mask_loadu_epi32`] //need i1 + * [x] [`_mm_loadu_epi32`] + * [_] [`_mm_mask_loadu_epi32`] //need i1 + * [_] [`_mm_maskz_loadu_epi32`] //need i1 + * [ ] [`_mm512_maskz_loadu_epi32`] //need i1 + * [x] [`_mm256_loadu_epi32`] + * [_] [`_mm256_mask_loadu_epi32`] //need i1 + * [_] [`_mm256_maskz_loadu_epi32`] //need i1 * [x] [`_mm512_loadu_epi64`] - * [x] [`_mm512_loadu_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_si512&expand=5236) - * [x] [`_mm512_mask2_permutex2var_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_epi32&expand=5236) - * [x] [`_mm512_mask2_permutex2var_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_epi64&expand=5236) - * [x] [`_mm512_mask2_permutex2var_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_pd&expand=5236) - * [x] [`_mm512_mask2_permutex2var_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_ps&expand=5236) - * [x] [`_mm512_mask2int`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2int&expand=5236) - * [x] [`_mm512_mask3_fmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_pd&expand=5236) - * [x] [`_mm512_mask3_fmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_ps&expand=5236) - * [x] [`_mm512_mask3_fmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_round_pd&expand=5236) - * [x] [`_mm512_mask3_fmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_round_ps&expand=5236) - * [x] [`_mm512_mask3_fmaddsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_pd&expand=5236) - * [x] [`_mm512_mask3_fmaddsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_ps&expand=5236) - * [x] [`_mm512_mask3_fmaddsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_round_pd&expand=5236) - * [x] [`_mm512_mask3_fmaddsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_round_ps&expand=5236) - * [x] [`_mm512_mask3_fmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_pd&expand=5236) - * [x] [`_mm512_mask3_fmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_ps&expand=5236) - * [x] [`_mm512_mask3_fmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_round_pd&expand=5236) - * [x] [`_mm512_mask3_fmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_round_ps&expand=5236) - * [x] [`_mm512_mask3_fmsubadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_pd&expand=5236) - * [x] [`_mm512_mask3_fmsubadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_ps&expand=5236) - * [x] [`_mm512_mask3_fmsubadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_round_pd&expand=5236) - * [x] [`_mm512_mask3_fmsubadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_round_ps&expand=5236) - * [x] [`_mm512_mask3_fnmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_pd&expand=5236) - * [x] [`_mm512_mask3_fnmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_ps&expand=5236) - * [x] [`_mm512_mask3_fnmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_round_pd&expand=5236) - * [x] [`_mm512_mask3_fnmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_round_ps&expand=5236) - * [x] [`_mm512_mask3_fnmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_pd&expand=5236) - * [x] [`_mm512_mask3_fnmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_ps&expand=5236) - * [x] [`_mm512_mask3_fnmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_round_pd&expand=5236) - * [x] [`_mm512_mask3_fnmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_round_ps&expand=5236) - * [x] [`_mm512_mask_abs_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_epi32&expand=5236) - * [x] [`_mm512_mask_abs_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_epi64&expand=5236) - * [x] [`_mm512_mask_abs_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_pd&expand=5236) - * [x] [`_mm512_mask_abs_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_ps&expand=5236) - * [x] [`_mm512_mask_add_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_epi32&expand=5236) - * [x] [`_mm512_mask_add_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_epi64&expand=5236) - * [x] [`_mm512_mask_add_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_pd&expand=5236) - * [x] [`_mm512_mask_add_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_ps&expand=5236) - * [x] [`_mm512_mask_add_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_round_pd&expand=5236) - * [x] [`_mm512_mask_add_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_round_ps&expand=5236) - * [x] [`_mm512_mask_alignr_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_alignr_epi32&expand=5236) - * [x] [`_mm512_mask_alignr_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_alignr_epi64&expand=5236) - * [x] [`_mm512_mask_and_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_and_epi32&expand=5236) - * [x] [`_mm512_mask_and_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_and_epi64&expand=5236) - * [x] [`_mm512_mask_andnot_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_andnot_epi32&expand=5236) - * [x] [`_mm512_mask_andnot_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_andnot_epi64&expand=5236) - * [x] [`_mm512_mask_blend_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_epi32&expand=5236) - * [x] [`_mm512_mask_blend_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_epi64&expand=5236) - * [x] [`_mm512_mask_blend_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_pd&expand=5236) - * [x] [`_mm512_mask_blend_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_ps&expand=5236) - * [x] [`_mm512_mask_broadcast_f32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcast_f32x4&expand=5236) - * [x] [`_mm512_mask_broadcast_f64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcast_f64x4&expand=5236) - * [x] [`_mm512_mask_broadcast_i32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcast_i32x4&expand=5236) - * [x] [`_mm512_mask_broadcast_i64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcast_i64x4&expand=5236) - * [x] [`_mm512_mask_broadcastd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastd_epi32&expand=5236) - * [x] [`_mm512_mask_broadcastq_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastq_epi64&expand=5236) - * [x] [`_mm512_mask_broadcastsd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastsd_pd&expand=5236) - * [x] [`_mm512_mask_broadcastss_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastss_ps&expand=5236) - * [x] [`_mm512_mask_cmp_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epi32_mask&expand=5236) - * [x] [`_mm512_mask_cmp_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epi64_mask&expand=5236) - * [x] [`_mm512_mask_cmp_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epu32_mask&expand=5236) - * [x] [`_mm512_mask_cmp_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epu64_mask&expand=5236) - * [x] [`_mm512_mask_cmp_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmp_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmp_round_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_round_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmp_round_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_round_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmpeq_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi32_mask&expand=5236) - * [x] [`_mm512_mask_cmpeq_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi64_mask&expand=5236) - * [x] [`_mm512_mask_cmpeq_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu32_mask&expand=5236) - * [x] [`_mm512_mask_cmpeq_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu64_mask&expand=5236) - * [x] [`_mm512_mask_cmpeq_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmpeq_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmpge_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi32_mask&expand=5236) - * [x] [`_mm512_mask_cmpge_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi64_mask&expand=5236) - * [x] [`_mm512_mask_cmpge_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu32_mask&expand=5236) - * [x] [`_mm512_mask_cmpge_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu64_mask&expand=5236) - * [x] [`_mm512_mask_cmpgt_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi32_mask&expand=5236) - * [x] [`_mm512_mask_cmpgt_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi64_mask&expand=5236) - * [x] [`_mm512_mask_cmpgt_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu32_mask&expand=5236) - * [x] [`_mm512_mask_cmpgt_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu64_mask&expand=5236) - * [x] [`_mm512_mask_cmple_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi32_mask&expand=5236) - * [x] [`_mm512_mask_cmple_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi64_mask&expand=5236) - * [x] [`_mm512_mask_cmple_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu32_mask&expand=5236) - * [x] [`_mm512_mask_cmple_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu64_mask&expand=5236) - * [x] [`_mm512_mask_cmple_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmple_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmplt_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi32_mask&expand=5236) - * [x] [`_mm512_mask_cmplt_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi64_mask&expand=5236) - * [x] [`_mm512_mask_cmplt_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epu32_mask&expand=5236) - * [x] [`_mm512_mask_cmplt_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epu64_mask&expand=5236) - * [x] [`_mm512_mask_cmplt_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmplt_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmpneq_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi32_mask&expand=5236) - * [x] [`_mm512_mask_cmpneq_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi64_mask&expand=5236) - * [x] [`_mm512_mask_cmpneq_epu32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu32_mask&expand=5236) - * [x] [`_mm512_mask_cmpneq_epu64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu64_mask&expand=5236) - * [x] [`_mm512_mask_cmpneq_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmpneq_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmpnle_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnle_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmpnle_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnle_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmpnlt_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnlt_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmpnlt_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnlt_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmpord_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpord_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmpord_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpord_ps_mask&expand=5236) - * [x] [`_mm512_mask_cmpunord_pd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpunord_pd_mask&expand=5236) - * [x] [`_mm512_mask_cmpunord_ps_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpunord_ps_mask&expand=5236) - * [x] [`_mm512_mask_compress_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_epi32&expand=5236) - * [x] [`_mm512_mask_compress_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_epi64&expand=5236) - * [x] [`_mm512_mask_compress_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_pd&expand=5236) - * [x] [`_mm512_mask_compress_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_ps&expand=5236) - * [ ] [`_mm512_mask_compressstoreu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compressstoreu_epi32&expand=5236) - * [ ] [`_mm512_mask_compressstoreu_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compressstoreu_epi64&expand=5236) - * [ ] [`_mm512_mask_compressstoreu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compressstoreu_pd&expand=5236) - * [ ] [`_mm512_mask_compressstoreu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compressstoreu_ps&expand=5236) - * [x] [`_mm512_mask_cvt_roundepi32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundepi32_ps&expand=5236) - * [x] [`_mm512_mask_cvt_roundepu32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundepu32_ps&expand=5236) - * [x] [`_mm512_mask_cvt_roundpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundpd_epi32&expand=5236) - * [x] [`_mm512_mask_cvt_roundpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundpd_epu32&expand=5236) - * [x] [`_mm512_mask_cvt_roundpd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundpd_ps&expand=5236) - * [x] [`_mm512_mask_cvt_roundph_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundph_ps&expand=5236) - * [x] [`_mm512_mask_cvt_roundps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_epi32&expand=5236) - * [x] [`_mm512_mask_cvt_roundps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_epu32&expand=5236) - * [x] [`_mm512_mask_cvt_roundps_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_pd&expand=5236) - * [x] [`_mm512_mask_cvt_roundps_ph`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_ph&expand=5236) - * [x] [`_mm512_mask_cvtepi16_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi16_epi32&expand=5236) - * [x] [`_mm512_mask_cvtepi16_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi16_epi64&expand=5236) - * [x] [`_mm512_mask_cvtepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_epi16&expand=5236) - * [x] [`_mm512_mask_cvtepi32_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_epi64&expand=5236) - * [x] [`_mm512_mask_cvtepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_epi8&expand=5236) - * [x] [`_mm512_mask_cvtepi32_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_pd&expand=5236) - * [x] [`_mm512_mask_cvtepi32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_ps&expand=5236) - * [ ] [`_mm512_mask_cvtepi32_storeu_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_storeu_epi16&expand=5236) - * [ ] [`_mm512_mask_cvtepi32_storeu_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_storeu_epi8&expand=5236) - * [x] [`_mm512_mask_cvtepi32lo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32lo_pd&expand=5236) - * [x] [`_mm512_mask_cvtepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_epi16&expand=5236) - * [x] [`_mm512_mask_cvtepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_epi32&expand=5236) - * [x] [`_mm512_mask_cvtepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_epi8&expand=5236) - * [ ] [`_mm512_mask_cvtepi64_storeu_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_storeu_epi16&expand=5236) - * [ ] [`_mm512_mask_cvtepi64_storeu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_storeu_epi32&expand=5236) - * [ ] [`_mm512_mask_cvtepi64_storeu_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_storeu_epi8&expand=5236) - * [x] [`_mm512_mask_cvtepi8_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi8_epi32&expand=5236) - * [x] [`_mm512_mask_cvtepi8_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi8_epi64&expand=5236) - * [x] [`_mm512_mask_cvtepu16_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu16_epi32&expand=5236) - * [x] [`_mm512_mask_cvtepu16_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu16_epi64&expand=5236) - * [x] [`_mm512_mask_cvtepu32_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32_epi64&expand=5236) - * [x] [`_mm512_mask_cvtepu32_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32_pd&expand=5236) - * [x] [`_mm512_mask_cvtepu32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32_ps&expand=5236) - * [x] [`_mm512_mask_cvtepu32lo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32lo_pd&expand=5236) - * [x] [`_mm512_mask_cvtepu8_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu8_epi32&expand=5236) - * [x] [`_mm512_mask_cvtepu8_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu8_epi64&expand=5236) - * [x] [`_mm512_mask_cvtpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_epi32&expand=5236) - * [x] [`_mm512_mask_cvtpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_epu32&expand=5236) - * [x] [`_mm512_mask_cvtpd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_ps&expand=5236) - * [x] [`_mm512_mask_cvtpd_pslo`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_pslo&expand=5236) - * [x] [`_mm512_mask_cvtph_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtph_ps&expand=5236) - * [x] [`_mm512_mask_cvtps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_epi32&expand=5236) - * [x] [`_mm512_mask_cvtps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_epu32&expand=5236) - * [x] [`_mm512_mask_cvtps_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_pd&expand=5236) - * [x] [`_mm512_mask_cvtps_ph`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_ph&expand=5236) - * [x] [`_mm512_mask_cvtpslo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpslo_pd&expand=5236) - * [x] [`_mm512_mask_cvtsepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_epi16&expand=5236) - * [x] [`_mm512_mask_cvtsepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_epi8&expand=5236) - * [ ] [`_mm512_mask_cvtsepi32_storeu_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_storeu_epi16&expand=5236) - * [ ] [`_mm512_mask_cvtsepi32_storeu_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_storeu_epi8&expand=5236) - * [x] [`_mm512_mask_cvtsepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_epi16&expand=5236) - * [x] [`_mm512_mask_cvtsepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_epi32&expand=5236) - * [x] [`_mm512_mask_cvtsepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_epi8&expand=5236) - * [ ] [`_mm512_mask_cvtsepi64_storeu_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_storeu_epi16&expand=5236) - * [ ] [`_mm512_mask_cvtsepi64_storeu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_storeu_epi32&expand=5236) - * [ ] [`_mm512_mask_cvtsepi64_storeu_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_storeu_epi8&expand=5236) - * [x] [`_mm512_mask_cvtt_roundpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundpd_epi32&expand=5236) - * [x] [`_mm512_mask_cvtt_roundpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundpd_epu32&expand=5236) - * [x] [`_mm512_mask_cvtt_roundps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundps_epi32&expand=5236) - * [x] [`_mm512_mask_cvtt_roundps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundps_epu32&expand=5236) - * [x] [`_mm512_mask_cvttpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttpd_epi32&expand=5236) - * [x] [`_mm512_mask_cvttpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttpd_epu32&expand=5236) - * [x] [`_mm512_mask_cvttps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttps_epi32&expand=5236) - * [x] [`_mm512_mask_cvttps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttps_epu32&expand=5236) - * [x] [`_mm512_mask_cvtusepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_epi16&expand=5236) - * [x] [`_mm512_mask_cvtusepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_epi8&expand=5236) - * [ ] [`_mm512_mask_cvtusepi32_storeu_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_storeu_epi16&expand=5236) - * [ ] [`_mm512_mask_cvtusepi32_storeu_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_storeu_epi8&expand=5236) - * [x] [`_mm512_mask_cvtusepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_epi16&expand=5236) - * [x] [`_mm512_mask_cvtusepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_epi32&expand=5236) - * [x] [`_mm512_mask_cvtusepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_epi8&expand=5236) - * [ ] [`_mm512_mask_cvtusepi64_storeu_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_storeu_epi16&expand=5236) - * [ ] [`_mm512_mask_cvtusepi64_storeu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_storeu_epi32&expand=5236) - * [ ] [`_mm512_mask_cvtusepi64_storeu_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_storeu_epi8&expand=5236) - * [x] [`_mm512_mask_div_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_pd&expand=5236) - * [x] [`_mm512_mask_div_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_ps&expand=5236) - * [x] [`_mm512_mask_div_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_round_pd&expand=5236) - * [x] [`_mm512_mask_div_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_round_ps&expand=5236) - * [x] [`_mm512_mask_expand_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_epi32&expand=5236) - * [x] [`_mm512_mask_expand_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_epi64&expand=5236) - * [x] [`_mm512_mask_expand_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_pd&expand=5236) - * [x] [`_mm512_mask_expand_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_ps&expand=5236) - * [ ] [`_mm512_mask_expandloadu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expandloadu_epi32&expand=5236) - * [ ] [`_mm512_mask_expandloadu_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expandloadu_epi64&expand=5236) - * [ ] [`_mm512_mask_expandloadu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expandloadu_pd&expand=5236) - * [ ] [`_mm512_mask_expandloadu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expandloadu_ps&expand=5236) - * [x] [`_mm512_mask_extractf32x4_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extractf32x4_ps&expand=5236) - * [x] [`_mm512_mask_extractf64x4_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extractf64x4_pd&expand=5236) - * [x] [`_mm512_mask_extracti32x4_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extracti32x4_epi32&expand=5236) - * [x] [`_mm512_mask_extracti64x4_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extracti64x4_epi64&expand=5236) - * [x] [`_mm512_mask_fixupimm_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_pd&expand=5236) - * [x] [`_mm512_mask_fixupimm_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_ps&expand=5236) - * [x] [`_mm512_mask_fixupimm_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_round_pd&expand=5236) - * [x] [`_mm512_mask_fixupimm_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_round_ps&expand=5236) - * [x] [`_mm512_mask_fmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_pd&expand=5236) - * [x] [`_mm512_mask_fmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_ps&expand=5236) - * [x] [`_mm512_mask_fmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_round_pd&expand=5236) - * [x] [`_mm512_mask_fmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_round_ps&expand=5236) - * [x] [`_mm512_mask_fmaddsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_pd&expand=5236) - * [x] [`_mm512_mask_fmaddsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_ps&expand=5236) - * [x] [`_mm512_mask_fmaddsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_round_pd&expand=5236) - * [x] [`_mm512_mask_fmaddsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_round_ps&expand=5236) - * [x] [`_mm512_mask_fmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_pd&expand=5236) - * [x] [`_mm512_mask_fmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_ps&expand=5236) - * [x] [`_mm512_mask_fmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_round_pd&expand=5236) - * [x] [`_mm512_mask_fmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_round_ps&expand=5236) - * [x] [`_mm512_mask_fmsubadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_pd&expand=5236) - * [x] [`_mm512_mask_fmsubadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_ps&expand=5236) - * [x] [`_mm512_mask_fmsubadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_round_pd&expand=5236) - * [x] [`_mm512_mask_fmsubadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_round_ps&expand=5236) - * [x] [`_mm512_mask_fnmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_pd&expand=5236) - * [x] [`_mm512_mask_fnmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_ps&expand=5236) - * [x] [`_mm512_mask_fnmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_round_pd&expand=5236) - * [x] [`_mm512_mask_fnmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_round_ps&expand=5236) - * [x] [`_mm512_mask_fnmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_pd&expand=5236) - * [x] [`_mm512_mask_fnmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_ps&expand=5236) - * [x] [`_mm512_mask_fnmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_round_pd&expand=5236) - * [x] [`_mm512_mask_fnmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_round_ps&expand=5236) - * [x] [`_mm512_mask_getexp_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_pd&expand=5236) - * [x] [`_mm512_mask_getexp_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_ps&expand=5236) - * [x] [`_mm512_mask_getexp_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_round_pd&expand=5236) - * [x] [`_mm512_mask_getexp_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_round_ps&expand=5236) - * [x] [`_mm512_mask_getmant_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_pd&expand=5236) - * [x] [`_mm512_mask_getmant_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_ps&expand=5236) - * [x] [`_mm512_mask_getmant_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_round_pd&expand=5236) - * [x] [`_mm512_mask_getmant_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_round_ps&expand=5236) - * [ ] [`_mm512_mask_i32extgather_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32extgather_epi32&expand=5236) - * [ ] [`_mm512_mask_i32extgather_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32extgather_ps&expand=5236) - * [ ] [`_mm512_mask_i32extscatter_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32extscatter_epi32&expand=5236) - * [ ] [`_mm512_mask_i32extscatter_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32extscatter_ps&expand=5236) - * [x] [`_mm512_mask_i32gather_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_epi32&expand=5236) - * [x] [`_mm512_mask_i32gather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_epi64&expand=5236) - * [x] [`_mm512_mask_i32gather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_pd&expand=5236) - * [x] [`_mm512_mask_i32gather_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_ps&expand=5236) - * [ ] [`_mm512_mask_i32loextgather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32loextgather_epi64&expand=5236) - * [ ] [`_mm512_mask_i32loextgather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32loextgather_pd&expand=5236) - * [ ] [`_mm512_mask_i32loextscatter_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32loextscatter_epi64&expand=5236) - * [ ] [`_mm512_mask_i32loextscatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32loextscatter_pd&expand=5236) - * [ ] [`_mm512_mask_i32logather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32logather_epi64&expand=5236) - * [ ] [`_mm512_mask_i32logather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32logather_pd&expand=5236) - * [ ] [`_mm512_mask_i32loscatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32loscatter_pd&expand=5236) - * [x] [`_mm512_mask_i32scatter_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_epi32&expand=5236) - * [x] [`_mm512_mask_i32scatter_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_epi64&expand=5236) - * [x] [`_mm512_mask_i32scatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_pd&expand=5236) - * [x] [`_mm512_mask_i32scatter_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_ps&expand=5236) - * [x] [`_mm512_mask_i64gather_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_epi32&expand=5236) - * [x] [`_mm512_mask_i64gather_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_epi64&expand=5236) - * [x] [`_mm512_mask_i64gather_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_pd&expand=5236) - * [x] [`_mm512_mask_i64gather_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_ps&expand=5236) - * [x] [`_mm512_mask_i64scatter_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_epi32&expand=5236) - * [x] [`_mm512_mask_i64scatter_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_epi64&expand=5236) - * [x] [`_mm512_mask_i64scatter_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_pd&expand=5236) - * [x] [`_mm512_mask_i64scatter_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_ps&expand=5236) - * [x] [`_mm512_mask_insertf32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_insertf32x4&expand=5236) - * [x] [`_mm512_mask_insertf64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_insertf64x4&expand=5236) - * [x] [`_mm512_mask_inserti32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_inserti32x4&expand=5236) - * [x] [`_mm512_mask_inserti64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_inserti64x4&expand=5236) - * [ ] [`_mm512_mask_load_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_epi32&expand=5236) - * [ ] [`_mm512_mask_load_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_epi64&expand=5236) - * [ ] [`_mm512_mask_load_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_pd&expand=5236) - * [ ] [`_mm512_mask_load_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_ps&expand=5236) - * [ ] [`_mm512_mask_loadu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_epi32&expand=5236) - * [ ] [`_mm512_mask_loadu_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_epi64&expand=5236) - * [ ] [`_mm512_mask_loadu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_pd&expand=5236) - * [ ] [`_mm512_mask_loadu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_ps&expand=5236) - * [x] [`_mm512_mask_max_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epi32&expand=5236) - * [x] [`_mm512_mask_max_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epi64&expand=5236) - * [x] [`_mm512_mask_max_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epu32&expand=5236) - * [x] [`_mm512_mask_max_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epu64&expand=5236) - * [x] [`_mm512_mask_max_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_pd&expand=5236) - * [x] [`_mm512_mask_max_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_ps&expand=5236) - * [x] [`_mm512_mask_max_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_round_pd&expand=5236) - * [x] [`_mm512_mask_max_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_round_ps&expand=5236) - * [x] [`_mm512_mask_min_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epi32&expand=5236) - * [x] [`_mm512_mask_min_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epi64&expand=5236) - * [x] [`_mm512_mask_min_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epu32&expand=5236) - * [x] [`_mm512_mask_min_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epu64&expand=5236) - * [x] [`_mm512_mask_min_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_pd&expand=5236) - * [x] [`_mm512_mask_min_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_ps&expand=5236) - * [x] [`_mm512_mask_min_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_round_pd&expand=5236) - * [x] [`_mm512_mask_min_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_round_ps&expand=5236) - * [x] [`_mm512_mask_mov_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_epi32&expand=5236) - * [x] [`_mm512_mask_mov_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_epi64&expand=5236) - * [x] [`_mm512_mask_mov_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_pd&expand=5236) - * [x] [`_mm512_mask_mov_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_ps&expand=5236) - * [x] [`_mm512_mask_movedup_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_movedup_pd&expand=5236) - * [x] [`_mm512_mask_movehdup_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_movehdup_ps&expand=5236) - * [x] [`_mm512_mask_moveldup_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_moveldup_ps&expand=5236) - * [x] [`_mm512_mask_mul_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_epi32&expand=5236) - * [x] [`_mm512_mask_mul_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_epu32&expand=5236) - * [x] [`_mm512_mask_mul_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_pd&expand=5236) - * [x] [`_mm512_mask_mul_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_ps&expand=5236) - * [x] [`_mm512_mask_mul_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_round_pd&expand=5236) - * [x] [`_mm512_mask_mul_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_round_ps&expand=5236) - * [x] [`_mm512_mask_mullo_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mullo_epi32&expand=5236) - * [x] [`_mm512_mask_mullox_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mullox_epi64&expand=5236) - * [x] [`_mm512_mask_or_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_or_epi32&expand=5236) - * [x] [`_mm512_mask_or_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_or_epi64&expand=5236) - * [x] [`_mm512_mask_permute_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permute_pd&expand=5236) - * [x] [`_mm512_mask_permute_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permute_ps&expand=5236) - * [x] [`_mm512_mask_permutevar_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutevar_epi32&expand=5236) - * [x] [`_mm512_mask_permutevar_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutevar_pd&expand=5236) - * [x] [`_mm512_mask_permutevar_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutevar_ps&expand=5236) - * [x] [`_mm512_mask_permutex2var_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_epi32&expand=5236) - * [x] [`_mm512_mask_permutex2var_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_epi64&expand=5236) - * [x] [`_mm512_mask_permutex2var_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_pd&expand=5236) - * [x] [`_mm512_mask_permutex2var_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_ps&expand=5236) - * [x] [`_mm512_mask_permutex_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex_epi64&expand=5236) - * [x] [`_mm512_mask_permutex_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex_pd&expand=5236) - * [x] [`_mm512_mask_permutexvar_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_epi32&expand=5236) - * [x] [`_mm512_mask_permutexvar_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_epi64&expand=5236) - * [x] [`_mm512_mask_permutexvar_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_pd&expand=5236) - * [x] [`_mm512_mask_permutexvar_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_ps&expand=5236) - * [x] [`_mm512_mask_rcp14_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rcp14_pd&expand=5236) - * [x] [`_mm512_mask_rcp14_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rcp14_ps&expand=5236) - * [x] [`_mm512_mask_reduce_add_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_epi32&expand=5236) - * [x] [`_mm512_mask_reduce_add_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_epi64&expand=5236) - * [x] [`_mm512_mask_reduce_add_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_pd&expand=5236) - * [x] [`_mm512_mask_reduce_add_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_ps&expand=5236) - * [x] [`_mm512_mask_reduce_and_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_and_epi32&expand=5236) - * [x] [`_mm512_mask_reduce_and_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_and_epi64&expand=5236) - * [x] [`_mm512_mask_reduce_max_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epi32&expand=5236) - * [x] [`_mm512_mask_reduce_max_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epi64&expand=5236) - * [x] [`_mm512_mask_reduce_max_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epu32&expand=5236) - * [x] [`_mm512_mask_reduce_max_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epu64&expand=5236) - * [x] [`_mm512_mask_reduce_max_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_pd&expand=5236) - * [x] [`_mm512_mask_reduce_max_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_ps&expand=5236) - * [x] [`_mm512_mask_reduce_min_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epi32&expand=5236) - * [x] [`_mm512_mask_reduce_min_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epi64&expand=5236) - * [x] [`_mm512_mask_reduce_min_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epu32&expand=5236) - * [x] [`_mm512_mask_reduce_min_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epu64&expand=5236) - * [x] [`_mm512_mask_reduce_min_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_pd&expand=5236) - * [x] [`_mm512_mask_reduce_min_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_ps&expand=5236) - * [x] [`_mm512_mask_reduce_mul_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_epi32&expand=5236) - * [x] [`_mm512_mask_reduce_mul_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_epi64&expand=5236) - * [x] [`_mm512_mask_reduce_mul_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_pd&expand=5236) - * [x] [`_mm512_mask_reduce_mul_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_ps&expand=5236) - * [x] [`_mm512_mask_reduce_or_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_or_epi32&expand=5236) - * [x] [`_mm512_mask_reduce_or_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_or_epi64&expand=5236) - * [x] [`_mm512_mask_rol_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rol_epi32&expand=5236) - * [x] [`_mm512_mask_rol_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rol_epi64&expand=5236) - * [x] [`_mm512_mask_rolv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rolv_epi32&expand=5236) - * [x] [`_mm512_mask_rolv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rolv_epi64&expand=5236) - * [x] [`_mm512_mask_ror_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ror_epi32&expand=5236) - * [x] [`_mm512_mask_ror_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ror_epi64&expand=5236) - * [x] [`_mm512_mask_rorv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rorv_epi32&expand=5236) - * [x] [`_mm512_mask_rorv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rorv_epi64&expand=5236) - * [x] [`_mm512_mask_roundscale_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_pd&expand=5236) - * [x] [`_mm512_mask_roundscale_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_ps&expand=5236) - * [x] [`_mm512_mask_roundscale_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_round_pd&expand=5236) - * [x] [`_mm512_mask_roundscale_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_round_ps&expand=5236) - * [x] [`_mm512_mask_rsqrt14_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rsqrt14_pd&expand=5236) - * [x] [`_mm512_mask_rsqrt14_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rsqrt14_ps&expand=5236) - * [x] [`_mm512_mask_scalef_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_pd&expand=5236) - * [x] [`_mm512_mask_scalef_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_ps&expand=5236) - * [x] [`_mm512_mask_scalef_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_round_pd&expand=5236) - * [x] [`_mm512_mask_scalef_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_round_ps&expand=5236) - * [x] [`_mm512_mask_set1_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_set1_epi32&expand=5236) - * [x] [`_mm512_mask_set1_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_set1_epi64&expand=5236) - * [x] [`_mm512_mask_shuffle_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_epi32&expand=5236) - * [x] [`_mm512_mask_shuffle_f32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_f32x4&expand=5236) - * [x] [`_mm512_mask_shuffle_f64x2`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_f64x2&expand=5236) - * [x] [`_mm512_mask_shuffle_i32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_i32x4&expand=5236) - * [x] [`_mm512_mask_shuffle_i64x2`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_i64x2&expand=5236) - * [x] [`_mm512_mask_shuffle_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_pd&expand=5236) - * [x] [`_mm512_mask_shuffle_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_ps&expand=5236) - * [x] [`_mm512_mask_sll_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sll_epi32&expand=5236) - * [x] [`_mm512_mask_sll_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sll_epi64&expand=5236) - * [x] [`_mm512_mask_slli_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_slli_epi32&expand=5236) - * [x] [`_mm512_mask_slli_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_slli_epi64&expand=5236) - * [x] [`_mm512_mask_sllv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sllv_epi32&expand=5236) - * [x] [`_mm512_mask_sllv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sllv_epi64&expand=5236) - * [x] [`_mm512_mask_sqrt_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_pd&expand=5236) - * [x] [`_mm512_mask_sqrt_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_ps&expand=5236) - * [x] [`_mm512_mask_sqrt_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_round_pd&expand=5236) - * [x] [`_mm512_mask_sqrt_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_round_ps&expand=5236) - * [x] [`_mm512_mask_sra_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sra_epi32&expand=5236) - * [x] [`_mm512_mask_sra_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sra_epi64&expand=5236) - * [x] [`_mm512_mask_srai_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srai_epi32&expand=5236) - * [x] [`_mm512_mask_srai_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srai_epi64&expand=5236) - * [x] [`_mm512_mask_srav_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srav_epi32&expand=5236) - * [x] [`_mm512_mask_srav_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srav_epi64&expand=5236) - * [x] [`_mm512_mask_srl_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srl_epi32&expand=5236) - * [x] [`_mm512_mask_srl_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srl_epi64&expand=5236) - * [x] [`_mm512_mask_srli_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srli_epi32&expand=5236) - * [x] [`_mm512_mask_srli_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srli_epi64&expand=5236) - * [x] [`_mm512_mask_srlv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srlv_epi32&expand=5236) - * [x] [`_mm512_mask_srlv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srlv_epi64&expand=5236) - * [ ] [`_mm512_mask_store_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_epi32&expand=5236) - * [ ] [`_mm512_mask_store_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_epi64&expand=5236) - * [ ] [`_mm512_mask_store_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_pd&expand=5236) - * [ ] [`_mm512_mask_store_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_ps&expand=5236) - * [ ] [`_mm512_mask_storeu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_epi32&expand=5236) - * [ ] [`_mm512_mask_storeu_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_epi64&expand=5236) - * [ ] [`_mm512_mask_storeu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_pd&expand=5236) - * [ ] [`_mm512_mask_storeu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_ps&expand=5236) - * [x] [`_mm512_mask_sub_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_epi32&expand=5236) - * [x] [`_mm512_mask_sub_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_epi64&expand=5236) - * [x] [`_mm512_mask_sub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_pd&expand=5236) - * [x] [`_mm512_mask_sub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_ps&expand=5236) - * [x] [`_mm512_mask_sub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_round_pd&expand=5236) - * [x] [`_mm512_mask_sub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_round_ps&expand=5236) - * [x] [`_mm512_mask_ternarylogic_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ternarylogic_epi32&expand=5236) - * [x] [`_mm512_mask_ternarylogic_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ternarylogic_epi64&expand=5236) - * [x] [`_mm512_mask_test_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_test_epi32_mask&expand=5236) - * [x] [`_mm512_mask_test_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_test_epi64_mask&expand=5236) - * [x] [`_mm512_mask_testn_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_testn_epi32_mask&expand=5236) - * [x] [`_mm512_mask_testn_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_testn_epi64_mask&expand=5236) - * [x] [`_mm512_mask_unpackhi_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_epi32&expand=5236) - * [x] [`_mm512_mask_unpackhi_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_epi64&expand=5236) - * [x] [`_mm512_mask_unpackhi_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_pd&expand=5236) - * [x] [`_mm512_mask_unpackhi_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_ps&expand=5236) - * [x] [`_mm512_mask_unpacklo_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_epi32&expand=5236) - * [x] [`_mm512_mask_unpacklo_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_epi64&expand=5236) - * [x] [`_mm512_mask_unpacklo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_pd&expand=5236) - * [x] [`_mm512_mask_unpacklo_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_ps&expand=5236) - * [x] [`_mm512_mask_xor_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_xor_epi32&expand=5236) - * [x] [`_mm512_mask_xor_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_xor_epi64&expand=5236) - * [x] [`_mm512_maskz_abs_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_abs_epi32&expand=5236) - * [x] [`_mm512_maskz_abs_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_abs_epi64&expand=5236) - * [x] [`_mm512_maskz_add_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_epi32&expand=5236) - * [x] [`_mm512_maskz_add_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_epi64&expand=5236) - * [x] [`_mm512_maskz_add_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_pd&expand=5236) - * [x] [`_mm512_maskz_add_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_ps&expand=5236) - * [x] [`_mm512_maskz_add_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_round_pd&expand=5236) - * [x] [`_mm512_maskz_add_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_round_ps&expand=5236) - * [x] [`_mm512_maskz_alignr_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_alignr_epi32&expand=5236) - * [x] [`_mm512_maskz_alignr_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_alignr_epi64&expand=5236) - * [x] [`_mm512_maskz_and_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_and_epi32&expand=5236) - * [x] [`_mm512_maskz_and_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_and_epi64&expand=5236) - * [x] [`_mm512_maskz_andnot_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_andnot_epi32&expand=5236) - * [x] [`_mm512_maskz_andnot_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_andnot_epi64&expand=5236) - * [x] [`_mm512_maskz_broadcast_f32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcast_f32x4&expand=5236) - * [x] [`_mm512_maskz_broadcast_f64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcast_f64x4&expand=5236) - * [x] [`_mm512_maskz_broadcast_i32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcast_i32x4&expand=5236) - * [x] [`_mm512_maskz_broadcast_i64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcast_i64x4&expand=5236) - * [x] [`_mm512_maskz_broadcastd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastd_epi32&expand=5236) - * [x] [`_mm512_maskz_broadcastq_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastq_epi64&expand=5236) - * [x] [`_mm512_maskz_broadcastsd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastsd_pd&expand=5236) - * [x] [`_mm512_maskz_broadcastss_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastss_ps&expand=5236) - * [x] [`_mm512_maskz_compress_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_epi32&expand=5236) - * [x] [`_mm512_maskz_compress_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_epi64&expand=5236) - * [x] [`_mm512_maskz_compress_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_pd&expand=5236) - * [x] [`_mm512_maskz_compress_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_ps&expand=5236) - * [x] [`_mm512_maskz_cvt_roundepi32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundepi32_ps&expand=5236) - * [x] [`_mm512_maskz_cvt_roundepu32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundepu32_ps&expand=5236) - * [x] [`_mm512_maskz_cvt_roundpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundpd_epi32&expand=5236) - * [x] [`_mm512_maskz_cvt_roundpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundpd_epu32&expand=5236) - * [x] [`_mm512_maskz_cvt_roundpd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundpd_ps&expand=5236) - * [x] [`_mm512_maskz_cvt_roundph_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundph_ps&expand=5236) - * [x] [`_mm512_maskz_cvt_roundps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_epi32&expand=5236) - * [x] [`_mm512_maskz_cvt_roundps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_epu32&expand=5236) - * [x] [`_mm512_maskz_cvt_roundps_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_pd&expand=5236) - * [x] [`_mm512_maskz_cvt_roundps_ph`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_ph&expand=5236) - * [x] [`_mm512_maskz_cvtepi16_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi16_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtepi16_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi16_epi64&expand=5236) - * [x] [`_mm512_maskz_cvtepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_epi16&expand=5236) - * [x] [`_mm512_maskz_cvtepi32_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_epi64&expand=5236) - * [x] [`_mm512_maskz_cvtepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_epi8&expand=5236) - * [x] [`_mm512_maskz_cvtepi32_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_pd&expand=5236) - * [x] [`_mm512_maskz_cvtepi32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_ps&expand=5236) - * [x] [`_mm512_maskz_cvtepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi64_epi16&expand=5236) - * [x] [`_mm512_maskz_cvtepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi64_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi64_epi8&expand=5236) - * [x] [`_mm512_maskz_cvtepi8_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi8_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtepi8_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi8_epi64&expand=5236) - * [x] [`_mm512_maskz_cvtepu16_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu16_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtepu16_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu16_epi64&expand=5236) - * [x] [`_mm512_maskz_cvtepu32_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu32_epi64&expand=5236) - * [x] [`_mm512_maskz_cvtepu32_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu32_pd&expand=5236) - * [x] [`_mm512_maskz_cvtepu32_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu32_ps&expand=5236) - * [x] [`_mm512_maskz_cvtepu8_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu8_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtepu8_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu8_epi64&expand=5236) - * [x] [`_mm512_maskz_cvtpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtpd_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtpd_epu32&expand=5236) - * [x] [`_mm512_maskz_cvtpd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtpd_ps&expand=5236) - * [x] [`_mm512_maskz_cvtph_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtph_ps&expand=5236) - * [x] [`_mm512_maskz_cvtps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtps_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtps_epu32&expand=5236) - * [x] [`_mm512_maskz_cvtps_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtps_pd&expand=5236) - * [x] [`_mm512_maskz_cvtps_ph`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtps_ph&expand=5236) - * [x] [`_mm512_maskz_cvtsepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi32_epi16&expand=5236) - * [x] [`_mm512_maskz_cvtsepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi32_epi8&expand=5236) - * [x] [`_mm512_maskz_cvtsepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi64_epi16&expand=5236) - * [x] [`_mm512_maskz_cvtsepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi64_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtsepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi64_epi8&expand=5236) - * [x] [`_mm512_maskz_cvtt_roundpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundpd_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtt_roundpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundpd_epu32&expand=5236) - * [x] [`_mm512_maskz_cvtt_roundps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundps_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtt_roundps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundps_epu32&expand=5236) - * [x] [`_mm512_maskz_cvttpd_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttpd_epi32&expand=5236) - * [x] [`_mm512_maskz_cvttpd_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttpd_epu32&expand=5236) - * [x] [`_mm512_maskz_cvttps_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttps_epi32&expand=5236) - * [x] [`_mm512_maskz_cvttps_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttps_epu32&expand=5236) - * [x] [`_mm512_maskz_cvtusepi32_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi32_epi16&expand=5236) - * [x] [`_mm512_maskz_cvtusepi32_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi32_epi8&expand=5236) - * [x] [`_mm512_maskz_cvtusepi64_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi64_epi16&expand=5236) - * [x] [`_mm512_maskz_cvtusepi64_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi64_epi32&expand=5236) - * [x] [`_mm512_maskz_cvtusepi64_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi64_epi8&expand=5236) - * [x] [`_mm512_maskz_div_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_pd&expand=5236) - * [x] [`_mm512_maskz_div_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_ps&expand=5236) - * [x] [`_mm512_maskz_div_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_round_pd&expand=5236) - * [x] [`_mm512_maskz_div_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_round_ps&expand=5236) - * [x] [`_mm512_maskz_expand_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_epi32&expand=5236) - * [x] [`_mm512_maskz_expand_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_epi64&expand=5236) - * [x] [`_mm512_maskz_expand_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_pd&expand=5236) - * [x] [`_mm512_maskz_expand_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_ps&expand=5236) - * [ ] [`_mm512_maskz_expandloadu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expandloadu_epi32&expand=5236) - * [ ] [`_mm512_maskz_expandloadu_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expandloadu_epi64&expand=5236) - * [ ] [`_mm512_maskz_expandloadu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expandloadu_pd&expand=5236) - * [ ] [`_mm512_maskz_expandloadu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expandloadu_ps&expand=5236) - * [x] [`_mm512_maskz_extractf32x4_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extractf32x4_ps&expand=5236) - * [x] [`_mm512_maskz_extractf64x4_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extractf64x4_pd&expand=5236) - * [x] [`_mm512_maskz_extracti32x4_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extracti32x4_epi32&expand=5236) - * [x] [`_mm512_maskz_extracti64x4_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extracti64x4_epi64&expand=5236) - * [x] [`_mm512_maskz_fixupimm_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_pd&expand=5236) - * [x] [`_mm512_maskz_fixupimm_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_ps&expand=5236) - * [x] [`_mm512_maskz_fixupimm_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_round_pd&expand=5236) - * [x] [`_mm512_maskz_fixupimm_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_round_ps&expand=5236) - * [x] [`_mm512_maskz_fmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_pd&expand=5236) - * [x] [`_mm512_maskz_fmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_ps&expand=5236) - * [x] [`_mm512_maskz_fmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_round_pd&expand=5236) - * [x] [`_mm512_maskz_fmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_round_ps&expand=5236) - * [x] [`_mm512_maskz_fmaddsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_pd&expand=5236) - * [x] [`_mm512_maskz_fmaddsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_ps&expand=5236) - * [x] [`_mm512_maskz_fmaddsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_round_pd&expand=5236) - * [x] [`_mm512_maskz_fmaddsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_round_ps&expand=5236) - * [x] [`_mm512_maskz_fmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_pd&expand=5236) - * [x] [`_mm512_maskz_fmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_ps&expand=5236) - * [x] [`_mm512_maskz_fmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_round_pd&expand=5236) - * [x] [`_mm512_maskz_fmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_round_ps&expand=5236) - * [x] [`_mm512_maskz_fmsubadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_pd&expand=5236) - * [x] [`_mm512_maskz_fmsubadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_ps&expand=5236) - * [x] [`_mm512_maskz_fmsubadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_round_pd&expand=5236) - * [x] [`_mm512_maskz_fmsubadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_round_ps&expand=5236) - * [x] [`_mm512_maskz_fnmadd_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_pd&expand=5236) - * [x] [`_mm512_maskz_fnmadd_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_ps&expand=5236) - * [x] [`_mm512_maskz_fnmadd_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_round_pd&expand=5236) - * [x] [`_mm512_maskz_fnmadd_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_round_ps&expand=5236) - * [x] [`_mm512_maskz_fnmsub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_pd&expand=5236) - * [x] [`_mm512_maskz_fnmsub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_ps&expand=5236) - * [x] [`_mm512_maskz_fnmsub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_round_pd&expand=5236) - * [x] [`_mm512_maskz_fnmsub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_round_ps&expand=5236) - * [x] [`_mm512_maskz_getexp_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_pd&expand=5236) - * [x] [`_mm512_maskz_getexp_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_ps&expand=5236) - * [x] [`_mm512_maskz_getexp_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_round_pd&expand=5236) - * [x] [`_mm512_maskz_getexp_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_round_ps&expand=5236) - * [x] [`_mm512_maskz_getmant_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getmant_pd&expand=5236) - * [x] [`_mm512_maskz_getmant_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getmant_ps&expand=5236) - * [x] [`_mm512_maskz_getmant_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getmant_round_pd&expand=5236) - * [x] [`_mm512_maskz_getmant_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getmant_round_ps&expand=5236) - * [x] [`_mm512_maskz_insertf32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_insertf32x4&expand=5236) - * [x] [`_mm512_maskz_insertf64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_insertf64x4&expand=5236) - * [x] [`_mm512_maskz_inserti32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_inserti32x4&expand=5236) - * [x] [`_mm512_maskz_inserti64x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_inserti64x4&expand=5236) - * [ ] [`_mm512_maskz_load_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_epi32&expand=5236) - * [ ] [`_mm512_maskz_load_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_epi64&expand=5236) - * [ ] [`_mm512_maskz_load_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_pd&expand=5236) - * [ ] [`_mm512_maskz_load_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_ps&expand=5236) - * [ ] [`_mm512_maskz_loadu_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_epi32&expand=5236) - * [ ] [`_mm512_maskz_loadu_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_epi64&expand=5236) - * [ ] [`_mm512_maskz_loadu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_pd&expand=5236) - * [ ] [`_mm512_maskz_loadu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_ps&expand=5236) - * [x] [`_mm512_maskz_max_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epi32&expand=5236) - * [x] [`_mm512_maskz_max_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epi64&expand=5236) - * [x] [`_mm512_maskz_max_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epu32&expand=5236) - * [x] [`_mm512_maskz_max_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epu64&expand=5236) - * [x] [`_mm512_maskz_max_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_pd&expand=5236) - * [x] [`_mm512_maskz_max_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_ps&expand=5236) - * [x] [`_mm512_maskz_max_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_round_pd&expand=5236) - * [x] [`_mm512_maskz_max_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_round_ps&expand=5236) - * [x] [`_mm512_maskz_min_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_epi32&expand=5236) - * [x] [`_mm512_maskz_min_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_epi64&expand=5236) - * [x] [`_mm512_maskz_min_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_epu32&expand=5236) - * [x] [`_mm512_maskz_min_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_epu64&expand=5236) - * [x] [`_mm512_maskz_min_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_pd&expand=5236) - * [x] [`_mm512_maskz_min_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_ps&expand=5236) - * [x] [`_mm512_maskz_min_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_round_pd&expand=5236) - * [x] [`_mm512_maskz_min_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_round_ps&expand=5236) - * [x] [`_mm512_maskz_mov_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_epi32&expand=5236) - * [x] [`_mm512_maskz_mov_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_epi64&expand=5236) - * [x] [`_mm512_maskz_mov_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_pd&expand=5236) - * [x] [`_mm512_maskz_mov_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_ps&expand=5236) - * [x] [`_mm512_maskz_movedup_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_movedup_pd&expand=5236) - * [x] [`_mm512_maskz_movehdup_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_movehdup_ps&expand=5236) - * [x] [`_mm512_maskz_moveldup_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_moveldup_ps&expand=5236) - * [x] [`_mm512_maskz_mul_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_epi32&expand=5236) - * [x] [`_mm512_maskz_mul_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_epu32&expand=5236) - * [x] [`_mm512_maskz_mul_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_pd&expand=5236) - * [x] [`_mm512_maskz_mul_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_ps&expand=5236) - * [x] [`_mm512_maskz_mul_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_round_pd&expand=5236) - * [x] [`_mm512_maskz_mul_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_round_ps&expand=5236) - * [x] [`_mm512_maskz_mullo_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mullo_epi32&expand=5236) - * [x] [`_mm512_maskz_or_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_or_epi32&expand=5236) - * [x] [`_mm512_maskz_or_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_or_epi64&expand=5236) - * [x] [`_mm512_maskz_permute_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permute_pd&expand=5236) - * [x] [`_mm512_maskz_permute_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permute_ps&expand=5236) - * [x] [`_mm512_maskz_permutevar_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutevar_pd&expand=5236) - * [x] [`_mm512_maskz_permutevar_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutevar_ps&expand=5236) - * [x] [`_mm512_maskz_permutex2var_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_epi32&expand=5236) - * [x] [`_mm512_maskz_permutex2var_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_epi64&expand=5236) - * [x] [`_mm512_maskz_permutex2var_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_pd&expand=5236) - * [x] [`_mm512_maskz_permutex2var_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_ps&expand=5236) - * [x] [`_mm512_maskz_permutex_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex_epi64&expand=5236) - * [x] [`_mm512_maskz_permutex_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex_pd&expand=5236) - * [x] [`_mm512_maskz_permutexvar_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_epi32&expand=5236) - * [x] [`_mm512_maskz_permutexvar_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_epi64&expand=5236) - * [x] [`_mm512_maskz_permutexvar_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_pd&expand=5236) - * [x] [`_mm512_maskz_permutexvar_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_ps&expand=5236) - * [x] [`_mm512_maskz_rcp14_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rcp14_pd&expand=5236) - * [x] [`_mm512_maskz_rcp14_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rcp14_ps&expand=5236) - * [x] [`_mm512_maskz_rol_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rol_epi32&expand=5236) - * [x] [`_mm512_maskz_rol_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rol_epi64&expand=5236) - * [x] [`_mm512_maskz_rolv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rolv_epi32&expand=5236) - * [x] [`_mm512_maskz_rolv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rolv_epi64&expand=5236) - * [x] [`_mm512_maskz_ror_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ror_epi32&expand=5236) - * [x] [`_mm512_maskz_ror_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ror_epi64&expand=5236) - * [x] [`_mm512_maskz_rorv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rorv_epi32&expand=5236) - * [x] [`_mm512_maskz_rorv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rorv_epi64&expand=5236) - * [x] [`_mm512_maskz_roundscale_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_pd&expand=5236) - * [x] [`_mm512_maskz_roundscale_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_ps&expand=5236) - * [x] [`_mm512_maskz_roundscale_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_round_pd&expand=5236) - * [x] [`_mm512_maskz_roundscale_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_round_ps&expand=5236) - * [x] [`_mm512_maskz_rsqrt14_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rsqrt14_pd&expand=5236) - * [x] [`_mm512_maskz_rsqrt14_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rsqrt14_ps&expand=5236) - * [x] [`_mm512_maskz_scalef_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_pd&expand=5236) - * [x] [`_mm512_maskz_scalef_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_ps&expand=5236) - * [x] [`_mm512_maskz_scalef_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_round_pd&expand=5236) - * [x] [`_mm512_maskz_scalef_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_round_ps&expand=5236) - * [x] [`_mm512_maskz_set1_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_set1_epi32&expand=5236) - * [x] [`_mm512_maskz_set1_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_set1_epi64&expand=5236) - * [x] [`_mm512_maskz_shuffle_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_epi32&expand=5236) - * [x] [`_mm512_maskz_shuffle_f32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_f32x4&expand=5236) - * [x] [`_mm512_maskz_shuffle_f64x2`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_f64x2&expand=5236) - * [x] [`_mm512_maskz_shuffle_i32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_i32x4&expand=5236) - * [x] [`_mm512_maskz_shuffle_i64x2`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_i64x2&expand=5236) - * [x] [`_mm512_maskz_shuffle_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_pd&expand=5236) - * [x] [`_mm512_maskz_shuffle_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_ps&expand=5236) - * [x] [`_mm512_maskz_sll_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sll_epi32&expand=5236) - * [x] [`_mm512_maskz_sll_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sll_epi64&expand=5236) - * [x] [`_mm512_maskz_slli_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_slli_epi32&expand=5236) - * [x] [`_mm512_maskz_slli_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_slli_epi64&expand=5236) - * [x] [`_mm512_maskz_sllv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sllv_epi32&expand=5236) - * [x] [`_mm512_maskz_sllv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sllv_epi64&expand=5236) - * [x] [`_mm512_maskz_sqrt_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_pd&expand=5236) - * [x] [`_mm512_maskz_sqrt_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_ps&expand=5236) - * [x] [`_mm512_maskz_sqrt_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_round_pd&expand=5236) - * [x] [`_mm512_maskz_sqrt_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_round_ps&expand=5236) - * [x] [`_mm512_maskz_sra_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sra_epi32&expand=5236) - * [x] [`_mm512_maskz_sra_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sra_epi64&expand=5236) - * [x] [`_mm512_maskz_srai_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srai_epi32&expand=5236) - * [x] [`_mm512_maskz_srai_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srai_epi64&expand=5236) - * [x] [`_mm512_maskz_srav_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srav_epi32&expand=5236) - * [x] [`_mm512_maskz_srav_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srav_epi64&expand=5236) - * [x] [`_mm512_maskz_srl_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srl_epi32&expand=5236) - * [x] [`_mm512_maskz_srl_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srl_epi64&expand=5236) - * [x] [`_mm512_maskz_srli_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srli_epi32&expand=5236) - * [x] [`_mm512_maskz_srli_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srli_epi64&expand=5236) - * [x] [`_mm512_maskz_srlv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srlv_epi32&expand=5236) - * [x] [`_mm512_maskz_srlv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srlv_epi64&expand=5236) - * [x] [`_mm512_maskz_sub_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_epi32&expand=5236) - * [x] [`_mm512_maskz_sub_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_epi64&expand=5236) - * [x] [`_mm512_maskz_sub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_pd&expand=5236) - * [x] [`_mm512_maskz_sub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_ps&expand=5236) - * [x] [`_mm512_maskz_sub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_round_pd&expand=5236) - * [x] [`_mm512_maskz_sub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_round_ps&expand=5236) - * [x] [`_mm512_maskz_ternarylogic_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ternarylogic_epi32&expand=5236) - * [x] [`_mm512_maskz_ternarylogic_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ternarylogic_epi64&expand=5236) - * [x] [`_mm512_maskz_unpackhi_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_epi32&expand=5236) - * [x] [`_mm512_maskz_unpackhi_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_epi64&expand=5236) - * [x] [`_mm512_maskz_unpackhi_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_pd&expand=5236) - * [x] [`_mm512_maskz_unpackhi_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_ps&expand=5236) - * [x] [`_mm512_maskz_unpacklo_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_epi32&expand=5236) - * [x] [`_mm512_maskz_unpacklo_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_epi64&expand=5236) - * [x] [`_mm512_maskz_unpacklo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_pd&expand=5236) - * [x] [`_mm512_maskz_unpacklo_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_ps&expand=5236) - * [x] [`_mm512_maskz_xor_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_xor_epi32&expand=5236) - * [x] [`_mm512_maskz_xor_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_xor_epi64&expand=5236) - * [x] [`_mm512_max_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epi32&expand=5236) - * [x] [`_mm512_max_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epi64&expand=5236) - * [x] [`_mm512_max_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epu32&expand=5236) - * [x] [`_mm512_max_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epu64&expand=5236) - * [x] [`_mm512_max_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_pd&expand=5236) - * [x] [`_mm512_max_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_ps&expand=5236) - * [x] [`_mm512_max_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_round_pd&expand=5236) - * [x] [`_mm512_max_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_round_ps&expand=5236) - * [x] [`_mm512_min_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epi32&expand=5236) - * [x] [`_mm512_min_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epi64&expand=5236) - * [x] [`_mm512_min_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epu32&expand=5236) - * [x] [`_mm512_min_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epu64&expand=5236) - * [x] [`_mm512_min_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_pd&expand=5236) - * [x] [`_mm512_min_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_ps&expand=5236) - * [x] [`_mm512_min_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_round_pd&expand=5236) - * [x] [`_mm512_min_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_round_ps&expand=5236) - * [x] [`_mm512_movedup_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movedup_pd&expand=5236) - * [x] [`_mm512_movehdup_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movehdup_ps&expand=5236) - * [x] [`_mm512_moveldup_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_moveldup_ps&expand=5236) - * [x] [`_mm512_mul_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_epi32&expand=5236) - * [x] [`_mm512_mul_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_epu32&expand=5236) - * [x] [`_mm512_mul_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_pd&expand=5236) - * [x] [`_mm512_mul_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_ps&expand=5236) - * [x] [`_mm512_mul_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_round_pd&expand=5236) - * [x] [`_mm512_mul_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_round_ps&expand=5236) - * [x] [`_mm512_mullo_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mullo_epi32&expand=5236) - * [x] [`_mm512_mullox_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mullox_epi64&expand=5236) - * [x] [`_mm512_or_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_or_epi32&expand=5236) - * [x] [`_mm512_or_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_or_epi64&expand=5236) - * [x] [`_mm512_or_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_or_si512&expand=5236) - * [x] [`_mm512_permute_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permute_pd&expand=5236) - * [x] [`_mm512_permute_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permute_ps&expand=5236) - * [x] [`_mm512_permutevar_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutevar_epi32&expand=5236) - * [x] [`_mm512_permutevar_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutevar_pd&expand=5236) - * [x] [`_mm512_permutevar_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutevar_ps&expand=5236) - * [x] [`_mm512_permutex2var_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_epi32&expand=5236) - * [x] [`_mm512_permutex2var_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_epi64&expand=5236) - * [x] [`_mm512_permutex2var_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_pd&expand=5236) - * [x] [`_mm512_permutex2var_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_ps&expand=5236) - * [x] [`_mm512_permutex_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex_epi64&expand=5236) - * [x] [`_mm512_permutex_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex_pd&expand=5236) - * [x] [`_mm512_permutexvar_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_epi32&expand=5236) - * [x] [`_mm512_permutexvar_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_epi64&expand=5236) - * [x] [`_mm512_permutexvar_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_pd&expand=5236) - * [x] [`_mm512_permutexvar_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_ps&expand=5236) - * [x] [`_mm512_rcp14_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rcp14_pd&expand=5236) - * [x] [`_mm512_rcp14_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rcp14_ps&expand=5236) - * [x] [`_mm512_reduce_add_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_epi32&expand=5236) - * [x] [`_mm512_reduce_add_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_epi64&expand=5236) - * [x] [`_mm512_reduce_add_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_pd&expand=5236) - * [x] [`_mm512_reduce_add_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_ps&expand=5236) - * [x] [`_mm512_reduce_and_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_and_epi32&expand=5236) - * [x] [`_mm512_reduce_and_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_and_epi64&expand=5236) - * [x] [`_mm512_reduce_max_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epi32&expand=5236) - * [x] [`_mm512_reduce_max_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epi64&expand=5236) - * [x] [`_mm512_reduce_max_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epu32&expand=5236) - * [x] [`_mm512_reduce_max_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epu64&expand=5236) - * [x] [`_mm512_reduce_max_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_pd&expand=5236) - * [x] [`_mm512_reduce_max_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_ps&expand=5236) - * [x] [`_mm512_reduce_min_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epi32&expand=5236) - * [x] [`_mm512_reduce_min_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epi64&expand=5236) - * [x] [`_mm512_reduce_min_epu32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epu32&expand=5236) - * [x] [`_mm512_reduce_min_epu64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epu64&expand=5236) - * [x] [`_mm512_reduce_min_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_pd&expand=5236) - * [x] [`_mm512_reduce_min_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_ps&expand=5236) - * [x] [`_mm512_reduce_mul_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_epi32&expand=5236) - * [x] [`_mm512_reduce_mul_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_epi64&expand=5236) - * [x] [`_mm512_reduce_mul_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_pd&expand=5236) - * [x] [`_mm512_reduce_mul_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_ps&expand=5236) - * [x] [`_mm512_reduce_or_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_or_epi32&expand=5236) - * [x] [`_mm512_reduce_or_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_or_epi64&expand=5236) - * [x] [`_mm512_rol_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rol_epi32&expand=5236) - * [x] [`_mm512_rol_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rol_epi64&expand=5236) - * [x] [`_mm512_rolv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rolv_epi32&expand=5236) - * [x] [`_mm512_rolv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rolv_epi64&expand=5236) - * [x] [`_mm512_ror_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ror_epi32&expand=5236) - * [x] [`_mm512_ror_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ror_epi64&expand=5236) - * [x] [`_mm512_rorv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rorv_epi32&expand=5236) - * [x] [`_mm512_rorv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rorv_epi64&expand=5236) - * [x] [`_mm512_roundscale_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_pd&expand=5236) - * [x] [`_mm512_roundscale_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_ps&expand=5236) - * [x] [`_mm512_roundscale_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_round_pd&expand=5236) - * [x] [`_mm512_roundscale_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_round_ps&expand=5236) - * [x] [`_mm512_rsqrt14_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rsqrt14_pd&expand=5236) - * [x] [`_mm512_rsqrt14_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rsqrt14_ps&expand=5236) - * [x] [`_mm512_scalef_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_pd&expand=5236) - * [x] [`_mm512_scalef_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_ps&expand=5236) - * [x] [`_mm512_scalef_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_round_pd&expand=5236) - * [x] [`_mm512_scalef_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_round_ps&expand=5236) - * [x] [`_mm512_set1_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi16&expand=5236) - * [x] [`_mm512_set1_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi32&expand=5236) - * [x] [`_mm512_set1_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi64&expand=5236) - * [x] [`_mm512_set1_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi8&expand=5236) - * [x] [`_mm512_set1_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_pd&expand=5236) - * [x] [`_mm512_set1_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_ps&expand=5236) - * [x] [`_mm512_set4_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_epi32&expand=5236) - * [x] [`_mm512_set4_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_epi64&expand=5236) - * [x] [`_mm512_set4_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_pd&expand=5236) - * [x] [`_mm512_set4_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_ps&expand=5236) - * [x] [`_mm512_set_epi16`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi16&expand=5236) - * [x] [`_mm512_set_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi32&expand=5236) - * [x] [`_mm512_set_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi64&expand=5236) - * [x] [`_mm512_set_epi8`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi8&expand=5236) - * [x] [`_mm512_set_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_pd&expand=5236) - * [x] [`_mm512_set_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_ps&expand=5236) - * [x] [`_mm512_setr4_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_epi32&expand=5236) - * [x] [`_mm512_setr4_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_epi64&expand=5236) - * [x] [`_mm512_setr4_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_pd&expand=5236) - * [x] [`_mm512_setr4_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_ps&expand=5236) - * [x] [`_mm512_setr_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_epi32&expand=5236) - * [x] [`_mm512_setr_epi64`](https:/software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_epi64&expand=5236) - * [x] [`_mm512_setr_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_pd&expand=5236) - * [x] [`_mm512_setr_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_ps&expand=5236) - * [x] [`_mm512_setzero_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_epi32&expand=5236) - * [x] [`_mm512_setzero_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_pd&expand=5236) - * [x] [`_mm512_setzero_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_ps&expand=5236) - * [x] [`_mm512_setzero_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_si512&expand=5236) - * [x] [`_mm512_setzero`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero&expand=5236) - * [x] [`_mm512_shuffle_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_epi32&expand=5236) - * [x] [`_mm512_shuffle_f32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_f32x4&expand=5236) - * [x] [`_mm512_shuffle_f64x2`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_f64x2&expand=5236) - * [x] [`_mm512_shuffle_i32x4`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_i32x4&expand=5236) - * [x] [`_mm512_shuffle_i64x2`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_i64x2&expand=5236) - * [x] [`_mm512_shuffle_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_pd&expand=5236) - * [x] [`_mm512_shuffle_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_ps&expand=5236) - * [x] [`_mm512_sll_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sll_epi32&expand=5236) - * [x] [`_mm512_sll_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sll_epi64&expand=5236) - * [x] [`_mm512_slli_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_slli_epi32&expand=5236) - * [x] [`_mm512_slli_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_slli_epi64&expand=5236) - * [x] [`_mm512_sllv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sllv_epi32&expand=5236) - * [x] [`_mm512_sllv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sllv_epi64&expand=5236) - * [x] [`_mm512_sqrt_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_pd&expand=5236) - * [x] [`_mm512_sqrt_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_ps&expand=5236) - * [x] [`_mm512_sqrt_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_round_pd&expand=5236) - * [x] [`_mm512_sqrt_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_round_ps&expand=5236) - * [x] [`_mm512_sra_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sra_epi32&expand=5236) - * [x] [`_mm512_sra_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sra_epi64&expand=5236) - * [x] [`_mm512_srai_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srai_epi32&expand=5236) - * [x] [`_mm512_srai_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srai_epi64&expand=5236) - * [x] [`_mm512_srav_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srav_epi32&expand=5236) - * [x] [`_mm512_srav_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srav_epi64&expand=5236) - * [x] [`_mm512_srl_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srl_epi32&expand=5236) - * [x] [`_mm512_srl_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srl_epi64&expand=5236) - * [x] [`_mm512_srli_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srli_epi32&expand=5236) - * [x] [`_mm512_srli_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srli_epi64&expand=5236) - * [x] [`_mm512_srlv_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srlv_epi32&expand=5236) - * [x] [`_mm512_srlv_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srlv_epi64&expand=5236) - * [x] [`_mm512_store_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_epi32&expand=5236) - * [x] [`_mm512_store_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_epi64&expand=5236) - * [x] [`_mm512_store_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_pd&expand=5236) - * [x] [`_mm512_store_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_ps&expand=5236) - * [x] [`_mm512_store_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_si512&expand=5236) - * [x] [`_mm512_storeu_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_pd&expand=5236) - * [x] [`_mm512_storeu_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_ps&expand=5236) + * [ ] [`_mm512_mask_loadu_epi64`] //need i1 + * [ ] [`_mm512_maskz_loadu_epi64`] //need i1 + * [x] [`_mm_loadu_epi64`] + * [_] [`_mm_mask_loadu_epi64`] //need i1 + * [_] [`_mm_maskz_loadu_epi64`] //need i1 + * [x] [`_mm256_loadu_epi64`] + * [_] [`_mm256_mask_loadu_epi64`] //need i1 + * [_] [`_mm256_maskz_loadu_epi64`] //need i1 + * [x] [`_mm512_loadu_ps`] + * [ ] [`_mm512_mask_loadu_ps`] //need i1 + * [ ] [`_mm512_maskz_loadu_ps`] //need i1 + * [_] [`_mm_mask_loadu_ps`] //need i1 + * [_] [`_mm_maskz_loadu_ps`] //need i1 + * [_] [`_mm256_mask_loadu_ps`] //need i1 + * [_] [`_mm256_maskz_loadu_ps`] //need i1 + * [x] [`_mm512_loadu_pd`] + * [ ] [`_mm512_mask_loadu_pd`] //need i1 + * [ ] [`_mm512_maskz_loadu_pd`] //need i1 + * [_] [`_mm_mask_loadu_pd`] //need i1 + * [_] [`_mm_maskz_loadu_pd`] //need i1 + * [_] [`_mm256_mask_loadu_pd`] //need i1 + * [_] [`_mm256_maskz_loadu_pd`] //need i1 + * [x] [`_mm512_loadu_si512`] + * [x] [`_mm512_store_epi32`] + * [ ] [`_mm512_mask_store_epi32`] //need i1 + * [_] [`_mm_mask_store_epi32`] //need i1 + * [x] [`_mm_store_epi32`] + * [_] [`_mm256_mask_store_epi32`] //need i1 + * [x] [`_mm256_store_epi32`] + * [x] [`_mm512_store_epi64`] + * [ ] [`_mm512_mask_store_epi64`] //need i1 + * [_] [`_mm_mask_store_epi64`] //need i1 + * [x] [`_mm_store_epi64`] + * [_] [`_mm256_mask_store_epi64`] //need i1 + * [x] [`_mm256_store_epi64`] + * [x] [`_mm512_store_ps`] + * [ ] [`_mm512_mask_store_ps`] //need i1 + * [_] [`_mm_mask_store_ps`] //need i1 + * [_] [`_mm256_mask_store_ps`] //need i1 + * [x] [`_mm512_store_pd`] + * [ ] [`_mm512_mask_store_pd`] //need i1 + * [_] [`_mm_mask_store_pd`] //need i1 + * [_] [`_mm256_mask_store_pd`] //need i1 + * [x] [`_mm512_store_si512`] * [x] [`_mm512_storeu_epi32`] + * [ ] [`_mm512_mask_storeu_epi32`] //need i1 + * [_] [`_mm_mask_storeu_epi32`] //need i1 + * [x] [`_mm_storeu_epi32`] + * [_] [`_mm256_mask_storeu_epi32`] //need i1 + * [x] [`_mm256_storeu_epi32`] * [x] [`_mm512_storeu_epi64`] - * [x] [`_mm512_storeu_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_si512&expand=5236) - * [ ] [`_mm512_stream_load_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_stream_load_si512&expand=5236) - * [x] [`_mm512_stream_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_stream_pd&expand=5236) - * [x] [`_mm512_stream_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_stream_ps&expand=5236) - * [x] [`_mm512_stream_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_stream_si512&expand=5236) - * [x] [`_mm512_sub_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_epi32&expand=5236) - * [x] [`_mm512_sub_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_epi64&expand=5236) - * [x] [`_mm512_sub_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_pd&expand=5236) - * [x] [`_mm512_sub_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_ps&expand=5236) - * [x] [`_mm512_sub_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_round_pd&expand=5236) - * [x] [`_mm512_sub_round_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_round_ps&expand=5236) - * [ ] [`_mm512_svml_round_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_svml_round_pd&expand=5236) - * [x] [`_mm512_ternarylogic_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ternarylogic_epi32&expand=5236) - * [x] [`_mm512_ternarylogic_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ternarylogic_epi64&expand=5236) - * [x] [`_mm512_test_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_test_epi32_mask&expand=5236) - * [x] [`_mm512_test_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_test_epi64_mask&expand=5236) - * [x] [`_mm512_testn_epi32_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_testn_epi32_mask&expand=5236) - * [x] [`_mm512_testn_epi64_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_testn_epi64_mask&expand=5236) - * [x] [`_mm512_undefined_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined_epi32&expand=5236) - * [x] [`_mm512_undefined_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined_pd&expand=5236) - * [x] [`_mm512_undefined_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined_ps&expand=5236) - * [x] [`_mm512_undefined`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined&expand=5236) - * [x] [`_mm512_unpackhi_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_epi32&expand=5236) - * [x] [`_mm512_unpackhi_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_epi64&expand=5236) - * [x] [`_mm512_unpackhi_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_pd&expand=5236) - * [x] [`_mm512_unpackhi_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_ps&expand=5236) - * [x] [`_mm512_unpacklo_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_epi32&expand=5236) - * [x] [`_mm512_unpacklo_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_epi64&expand=5236) - * [x] [`_mm512_unpacklo_pd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_pd&expand=5236) - * [x] [`_mm512_unpacklo_ps`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_ps&expand=5236) - * [x] [`_mm512_xor_epi32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_xor_epi32&expand=5236) - * [x] [`_mm512_xor_epi64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_xor_epi64&expand=5236) - * [x] [`_mm512_xor_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_xor_si512&expand=5236) - * [x] [`_mm512_zextpd128_pd512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextpd128_pd512&expand=5236) - * [x] [`_mm512_zextpd256_pd512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextpd256_pd512&expand=5236) - * [x] [`_mm512_zextps128_ps512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextps128_ps512&expand=5236) - * [x] [`_mm512_zextps256_ps512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextps256_ps512&expand=5236) - * [x] [`_mm512_zextsi128_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextsi128_si512&expand=5236) - * [x] [`_mm512_zextsi256_si512`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextsi256_si512&expand=5236) - * [x] [`_mm_add_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_round_sd&expand=5236) - * [x] [`_mm_add_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_round_ss&expand=5236) - * [x] [`_mm_cmp_round_sd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_round_sd_mask&expand=5236) - * [x] [`_mm_cmp_round_ss_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_round_ss_mask&expand=5236) - * [x] [`_mm_cmp_sd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_sd_mask&expand=5236) - * [x] [`_mm_cmp_ss_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_ss_mask&expand=5236) - * [x] [`_mm_comi_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comi_round_sd&expand=5236) - * [x] [`_mm_comi_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comi_round_ss&expand=5236) - * [x] [`_mm_cvt_roundi32_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundi32_ss&expand=5236) - * [ ] [`_mm_cvt_roundi64_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundi64_sd&expand=5236) - * [ ] [`_mm_cvt_roundi64_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundi64_ss&expand=5236) - * [x] [`_mm_cvt_roundsd_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_i32&expand=5236) - * [ ] [`_mm_cvt_roundsd_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_i64&expand=5236) - * [x] [`_mm_cvt_roundsd_si32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_si32&expand=5236) - * [ ] [`_mm_cvt_roundsd_si64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_si64&expand=5236) - * [x] [`_mm_cvt_roundsd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_ss&expand=5236) - * [x] [`_mm_cvt_roundsd_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_u32&expand=5236) - * [ ] [`_mm_cvt_roundsd_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_u64&expand=5236) - * [x] [`_mm_cvt_roundsi32_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsi32_ss&expand=5236) - * [ ] [`_mm_cvt_roundsi64_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsi64_sd&expand=5236) - * [ ] [`_mm_cvt_roundsi64_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsi64_ss&expand=5236) - * [x] [`_mm_cvt_roundss_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_i32&expand=5236) - * [ ] [`_mm_cvt_roundss_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_i64&expand=5236) - * [x] [`_mm_cvt_roundss_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_sd&expand=5236) - * [x] [`_mm_cvt_roundss_si32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_si32&expand=5236) - * [ ] [`_mm_cvt_roundss_si64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_si64&expand=5236) - * [x] [`_mm_cvt_roundss_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_u32&expand=5236) - * [ ] [`_mm_cvt_roundss_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_u64&expand=5236) - * [x] [`_mm_cvt_roundu32_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundu32_ss&expand=5236) - * [ ] [`_mm_cvt_roundu64_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundu64_sd&expand=5236) - * [ ] [`_mm_cvt_roundu64_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundu64_ss&expand=5236) - * [x] [`_mm_cvti32_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvti32_sd&expand=5236) - * [x] [`_mm_cvti32_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvti32_ss&expand=5236) - * [ ] [`_mm_cvti64_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvti64_sd&expand=5236) - * [ ] [`_mm_cvti64_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvti64_ss&expand=5236) - * [x] [`_mm_cvtsd_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_i32&expand=5236) - * [ ] [`_mm_cvtsd_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_i64&expand=5236) - * [x] [`_mm_cvtsd_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_u32&expand=5236) - * [ ] [`_mm_cvtsd_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_u64&expand=5236) - * [x] [`_mm_cvtss_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_i32&expand=5236) - * [ ] [`_mm_cvtss_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_i64&expand=5236) - * [x] [`_mm_cvtss_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_u32&expand=5236) - * [ ] [`_mm_cvtss_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_u64&expand=5236) - * [x] [`_mm_cvtt_roundsd_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_i32&expand=5236) - * [x] [`_mm_cvtt_roundsd_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_i64&expand=5236) - * [x] [`_mm_cvtt_roundsd_si32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_si32&expand=5236) - * [ ] [`_mm_cvtt_roundsd_si64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_si64&expand=5236) - * [x] [`_mm_cvtt_roundsd_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_u32&expand=5236) - * [ ] [`_mm_cvtt_roundsd_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_u64&expand=5236) - * [x] [`_mm_cvtt_roundss_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_i32&expand=5236) - * [ ] [`_mm_cvtt_roundss_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_i64&expand=5236) - * [x] [`_mm_cvtt_roundss_si32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_si32&expand=5236) - * [ ] [`_mm_cvtt_roundss_si64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_si64&expand=5236) - * [x] [`_mm_cvtt_roundss_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_u32&expand=5236) - * [ ] [`_mm_cvtt_roundss_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_u64&expand=5236) - * [x] [`_mm_cvttsd_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_i32&expand=5236) - * [ ] [`_mm_cvttsd_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_i64&expand=5236) - * [x] [`_mm_cvttsd_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_u32&expand=5236) - * [ ] [`_mm_cvttsd_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_u64&expand=5236) - * [x] [`_mm_cvttss_i32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_i32&expand=5236) - * [ ] [`_mm_cvttss_i64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_i64&expand=5236) - * [x] [`_mm_cvttss_u32`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_u32&expand=5236) - * [ ] [`_mm_cvttss_u64`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_u64&expand=5236) - * [x] [`_mm_cvtu32_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu32_sd&expand=5236) - * [x] [`_mm_cvtu32_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu32_ss&expand=5236) - * [x] [`_mm_cvtu64_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu64_sd&expand=5236) - * [x] [`_mm_cvtu64_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu64_ss&expand=5236) - * [x] [`_mm_div_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_div_round_sd&expand=5236) - * [x] [`_mm_div_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_div_round_ss&expand=5236) - * [x] [`_mm_fixupimm_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fixupimm_round_sd&expand=5236) - * [x] [`_mm_fixupimm_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fixupimm_round_ss&expand=5236) - * [x] [`_mm_fixupimm_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fixupimm_sd&expand=5236) - * [x] [`_mm_fixupimm_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fixupimm_ss&expand=5236) - * [x] [`_mm_fmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fmadd_round_sd&expand=5236) - * [x] [`_mm_fmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fmadd_round_ss&expand=5236) - * [x] [`_mm_fmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fmsub_round_sd&expand=5236) - * [x] [`_mm_fmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fmsub_round_ss&expand=5236) - * [x] [`_mm_fnmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fnmadd_round_sd&expand=5236) - * [x] [`_mm_fnmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fnmadd_round_ss&expand=5236) - * [x] [`_mm_fnmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fnmsub_round_sd&expand=5236) - * [x] [`_mm_fnmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fnmsub_round_ss&expand=5236) - * [x] [`_mm_getexp_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getexp_round_sd&expand=5236) - * [x] [`_mm_getexp_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getexp_round_ss&expand=5236) - * [x] [`_mm_getexp_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getexp_sd&expand=5236) - * [x] [`_mm_getexp_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getexp_ss&expand=5236) - * [x] [`_mm_getmant_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getmant_round_sd&expand=5236) - * [x] [`_mm_getmant_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getmant_round_ss&expand=5236) - * [x] [`_mm_getmant_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getmant_sd&expand=5236) - * [x] [`_mm_getmant_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getmant_ss&expand=5236) - * [x] [`_mm_mask3_fmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmadd_round_sd&expand=5236) - * [x] [`_mm_mask3_fmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmadd_round_ss&expand=5236) - * [x] [`_mm_mask3_fmadd_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmadd_sd&expand=5236) - * [x] [`_mm_mask3_fmadd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmadd_ss&expand=5236) - * [x] [`_mm_mask3_fmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsub_round_sd&expand=5236) - * [x] [`_mm_mask3_fmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsub_round_ss&expand=5236) - * [x] [`_mm_mask3_fmsub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsub_sd&expand=5236) - * [x] [`_mm_mask3_fmsub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsub_ss&expand=5236) - * [x] [`_mm_mask3_fnmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmadd_round_sd&expand=5236) - * [x] [`_mm_mask3_fnmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmadd_round_ss&expand=5236) - * [x] [`_mm_mask3_fnmadd_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmadd_sd&expand=5236) - * [x] [`_mm_mask3_fnmadd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmadd_ss&expand=5236) - * [x] [`_mm_mask3_fnmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmsub_round_sd&expand=5236) - * [x] [`_mm_mask3_fnmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmsub_round_ss&expand=5236) - * [x] [`_mm_mask3_fnmsub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmsub_sd&expand=5236) - * [x] [`_mm_mask3_fnmsub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmsub_ss&expand=5236) - * [x] [`_mm_mask_add_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_round_sd&expand=5236) - * [x] [`_mm_mask_add_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_round_ss&expand=5236) - * [x] [`_mm_mask_add_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_sd&expand=5236) - * [x] [`_mm_mask_add_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_ss&expand=5236) - * [x] [`_mm_mask_cmp_round_sd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_round_sd_mask&expand=5236) - * [x] [`_mm_mask_cmp_round_ss_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_round_ss_mask&expand=5236) - * [x] [`_mm_mask_cmp_sd_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_sd_mask&expand=5236) - * [x] [`_mm_mask_cmp_ss_mask`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_ss_mask&expand=5236) - * [x] [`_mm_mask_cvt_roundsd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvt_roundsd_ss&expand=5236) - * [x] [`_mm_mask_cvt_roundss_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvt_roundss_sd&expand=5236) - * [x] [`_mm_mask_cvtsd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsd_ss&expand=5236) - * [x] [`_mm_mask_cvtss_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtss_sd&expand=5236) - * [x] [`_mm_mask_div_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_div_round_sd&expand=5236) - * [x] [`_mm_mask_div_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_div_round_ss&expand=5236) - * [x] [`_mm_mask_div_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_div_sd&expand=5236) - * [x] [`_mm_mask_div_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_div_ss&expand=5236) - * [x] [`_mm_mask_fixupimm_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fixupimm_round_sd&expand=5236) - * [x] [`_mm_mask_fixupimm_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fixupimm_round_ss&expand=5236) - * [x] [`_mm_mask_fixupimm_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fixupimm_sd&expand=5236) - * [x] [`_mm_mask_fixupimm_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fixupimm_ss&expand=5236) - * [x] [`_mm_mask_fmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmadd_round_sd&expand=5236) - * [x] [`_mm_mask_fmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmadd_round_ss&expand=5236) - * [x] [`_mm_mask_fmadd_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmadd_sd&expand=5236) - * [x] [`_mm_mask_fmadd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmadd_ss&expand=5236) - * [x] [`_mm_mask_fmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsub_round_sd&expand=5236) - * [x] [`_mm_mask_fmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsub_round_ss&expand=5236) - * [x] [`_mm_mask_fmsub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsub_sd&expand=5236) - * [x] [`_mm_mask_fmsub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsub_ss&expand=5236) - * [x] [`_mm_mask_fnmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmadd_round_sd&expand=5236) - * [x] [`_mm_mask_fnmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmadd_round_ss&expand=5236) - * [x] [`_mm_mask_fnmadd_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmadd_sd&expand=5236) - * [x] [`_mm_mask_fnmadd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmadd_ss&expand=5236) - * [x] [`_mm_mask_fnmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmsub_round_sd&expand=5236) - * [x] [`_mm_mask_fnmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmsub_round_ss&expand=5236) - * [x] [`_mm_mask_fnmsub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmsub_sd&expand=5236) - * [x] [`_mm_mask_fnmsub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmsub_ss&expand=5236) - * [x] [`_mm_mask_getexp_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getexp_round_sd&expand=5236) - * [x] [`_mm_mask_getexp_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getexp_round_ss&expand=5236) - * [x] [`_mm_mask_getexp_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getexp_sd&expand=5236) - * [x] [`_mm_mask_getexp_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getexp_ss&expand=5236) - * [x] [`_mm_mask_getmant_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getmant_round_sd&expand=5236) - * [x] [`_mm_mask_getmant_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getmant_round_ss&expand=5236) - * [x] [`_mm_mask_getmant_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getmant_sd&expand=5236) - * [x] [`_mm_mask_getmant_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getmant_ss&expand=5236) - * [ ] [`_mm_mask_load_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_load_sd&expand=5236) - * [ ] [`_mm_mask_load_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_load_ss&expand=5236) - * [x] [`_mm_mask_max_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_round_sd&expand=5236) - * [x] [`_mm_mask_max_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_round_ss&expand=5236) - * [x] [`_mm_mask_max_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_sd&expand=5236) - * [x] [`_mm_mask_max_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_ss&expand=5236) - * [x] [`_mm_mask_min_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_round_sd&expand=5236) - * [x] [`_mm_mask_min_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_round_ss&expand=5236) - * [x] [`_mm_mask_min_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_sd&expand=5236) - * [x] [`_mm_mask_min_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_ss&expand=5236) - * [x] [`_mm_mask_move_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_move_sd&expand=5236) - * [x] [`_mm_mask_move_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_move_ss&expand=5236) - * [x] [`_mm_mask_mul_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_round_sd&expand=5236) - * [x] [`_mm_mask_mul_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_round_ss&expand=5236) - * [x] [`_mm_mask_mul_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_sd&expand=5236) - * [x] [`_mm_mask_mul_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_ss&expand=5236) - * [x] [`_mm_mask_rcp14_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rcp14_sd&expand=5236) - * [x] [`_mm_mask_rcp14_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rcp14_ss&expand=5236) - * [x] [`_mm_mask_roundscale_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_roundscale_round_sd&expand=5236) - * [x] [`_mm_mask_roundscale_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_roundscale_round_ss&expand=5236) - * [x] [`_mm_mask_roundscale_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_roundscale_sd&expand=5236) - * [x] [`_mm_mask_roundscale_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_roundscale_ss&expand=5236) - * [x] [`_mm_mask_rsqrt14_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rsqrt14_sd&expand=5236) - * [x] [`_mm_mask_rsqrt14_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rsqrt14_ss&expand=5236) - * [x] [`_mm_mask_scalef_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_scalef_round_sd&expand=5236) - * [x] [`_mm_mask_scalef_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_scalef_round_ss&expand=5236) - * [x] [`_mm_mask_scalef_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_scalef_sd&expand=5236) - * [x] [`_mm_mask_scalef_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_scalef_ss&expand=5236) - * [x] [`_mm_mask_sqrt_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sqrt_round_sd&expand=5236) - * [x] [`_mm_mask_sqrt_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sqrt_round_ss&expand=5236) - * [x] [`_mm_mask_sqrt_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sqrt_sd&expand=5236) - * [x] [`_mm_mask_sqrt_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sqrt_ss&expand=5236) - * [ ] [`_mm_mask_store_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_store_sd&expand=5236) - * [ ] [`_mm_mask_store_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_store_ss&expand=5236) - * [x] [`_mm_mask_sub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_round_sd&expand=5236) - * [x] [`_mm_mask_sub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_round_ss&expand=5236) - * [x] [`_mm_mask_sub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_sd&expand=5236) - * [x] [`_mm_mask_sub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_ss&expand=5236) - * [x] [`_mm_maskz_add_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_round_sd&expand=5236) - * [x] [`_mm_maskz_add_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_round_ss&expand=5236) - * [x] [`_mm_maskz_add_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_sd&expand=5236) - * [x] [`_mm_maskz_add_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_ss&expand=5236) - * [x] [`_mm_maskz_cvt_roundsd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvt_roundsd_ss&expand=5236) - * [x] [`_mm_maskz_cvt_roundss_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvt_roundss_sd&expand=5236) - * [x] [`_mm_maskz_cvtsd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtsd_ss&expand=5236) - * [x] [`_mm_maskz_cvtss_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtss_sd&expand=5236) - * [x] [`_mm_maskz_div_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_div_round_sd&expand=5236) - * [x] [`_mm_maskz_div_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_div_round_ss&expand=5236) - * [x] [`_mm_maskz_div_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_div_sd&expand=5236) - * [x] [`_mm_maskz_div_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_div_ss&expand=5236) - * [x] [`_mm_maskz_fixupimm_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fixupimm_round_sd&expand=5236) - * [x] [`_mm_maskz_fixupimm_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fixupimm_round_ss&expand=5236) - * [x] [`_mm_maskz_fixupimm_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fixupimm_sd&expand=5236) - * [x] [`_mm_maskz_fixupimm_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fixupimm_ss&expand=5236) - * [x] [`_mm_maskz_fmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmadd_round_sd&expand=5236) - * [x] [`_mm_maskz_fmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmadd_round_ss&expand=5236) - * [x] [`_mm_maskz_fmadd_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmadd_sd&expand=5236) - * [x] [`_mm_maskz_fmadd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmadd_ss&expand=5236) - * [x] [`_mm_maskz_fmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsub_round_sd&expand=5236) - * [x] [`_mm_maskz_fmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsub_round_ss&expand=5236) - * [x] [`_mm_maskz_fmsub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsub_sd&expand=5236) - * [x] [`_mm_maskz_fmsub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsub_ss&expand=5236) - * [x] [`_mm_maskz_fnmadd_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmadd_round_sd&expand=5236) - * [x] [`_mm_maskz_fnmadd_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmadd_round_ss&expand=5236) - * [x] [`_mm_maskz_fnmadd_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmadd_sd&expand=5236) - * [x] [`_mm_maskz_fnmadd_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmadd_ss&expand=5236) - * [x] [`_mm_maskz_fnmsub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmsub_round_sd&expand=5236) - * [x] [`_mm_maskz_fnmsub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmsub_round_ss&expand=5236) - * [x] [`_mm_maskz_fnmsub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmsub_sd&expand=5236) - * [x] [`_mm_maskz_fnmsub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmsub_ss&expand=5236) - * [x] [`_mm_maskz_getexp_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getexp_round_sd&expand=5236) - * [x] [`_mm_maskz_getexp_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getexp_round_ss&expand=5236) - * [x] [`_mm_maskz_getexp_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getexp_sd&expand=5236) - * [x] [`_mm_maskz_getexp_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getexp_ss&expand=5236) - * [x] [`_mm_maskz_getmant_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getmant_round_sd&expand=5236) - * [x] [`_mm_maskz_getmant_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getmant_round_ss&expand=5236) - * [x] [`_mm_maskz_getmant_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getmant_sd&expand=5236) - * [x] [`_mm_maskz_getmant_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getmant_ss&expand=5236) - * [ ] [`_mm_maskz_load_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_load_sd&expand=5236) - * [ ] [`_mm_maskz_load_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_load_ss&expand=5236) - * [x] [`_mm_maskz_max_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_round_sd&expand=5236) - * [x] [`_mm_maskz_max_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_round_ss&expand=5236) - * [x] [`_mm_maskz_max_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_sd&expand=5236) - * [x] [`_mm_maskz_max_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_ss&expand=5236) - * [x] [`_mm_maskz_min_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_round_sd&expand=5236) - * [x] [`_mm_maskz_min_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_round_ss&expand=5236) - * [x] [`_mm_maskz_min_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_sd&expand=5236) - * [x] [`_mm_maskz_min_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_ss&expand=5236) - * [x] [`_mm_maskz_move_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_move_sd&expand=5236) - * [x] [`_mm_maskz_move_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_move_ss&expand=5236) - * [x] [`_mm_maskz_mul_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_round_sd&expand=5236) - * [x] [`_mm_maskz_mul_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_round_ss&expand=5236) - * [x] [`_mm_maskz_mul_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_sd&expand=5236) - * [x] [`_mm_maskz_mul_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_ss&expand=5236) - * [x] [`_mm_maskz_rcp14_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rcp14_sd&expand=5236) - * [x] [`_mm_maskz_rcp14_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rcp14_ss&expand=5236) - * [x] [`_mm_maskz_roundscale_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_roundscale_round_sd&expand=5236) - * [x] [`_mm_maskz_roundscale_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_roundscale_round_ss&expand=5236) - * [x] [`_mm_maskz_roundscale_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_roundscale_sd&expand=5236) - * [x] [`_mm_maskz_roundscale_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_roundscale_ss&expand=5236) - * [x] [`_mm_maskz_rsqrt14_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rsqrt14_sd&expand=5236) - * [x] [`_mm_maskz_rsqrt14_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rsqrt14_ss&expand=5236) - * [x] [`_mm_maskz_scalef_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_scalef_round_sd&expand=5236) - * [x] [`_mm_maskz_scalef_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_scalef_round_ss&expand=5236) - * [x] [`_mm_maskz_scalef_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_scalef_sd&expand=5236) - * [x] [`_mm_maskz_scalef_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_scalef_ss&expand=5236) - * [x] [`_mm_maskz_sqrt_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sqrt_round_sd&expand=5236) - * [x] [`_mm_maskz_sqrt_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sqrt_round_ss&expand=5236) - * [x] [`_mm_maskz_sqrt_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sqrt_sd&expand=5236) - * [x] [`_mm_maskz_sqrt_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sqrt_ss&expand=5236) - * [x] [`_mm_maskz_sub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_round_sd&expand=5236) - * [x] [`_mm_maskz_sub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_round_ss&expand=5236) - * [x] [`_mm_maskz_sub_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_sd&expand=5236) - * [x] [`_mm_maskz_sub_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_ss&expand=5236) - * [x] [`_mm_max_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_round_sd&expand=5236) - * [x] [`_mm_max_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_round_ss&expand=5236) - * [x] [`_mm_min_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_round_sd&expand=5236) - * [x] [`_mm_min_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_round_ss&expand=5236) - * [x] [`_mm_mul_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_round_sd&expand=5236) - * [x] [`_mm_mul_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_round_ss&expand=5236) - * [x] [`_mm_rcp14_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp14_sd&expand=5236) - * [x] [`_mm_rcp14_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp14_ss&expand=5236) - * [x] [`_mm_roundscale_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_roundscale_round_sd&expand=5236) - * [x] [`_mm_roundscale_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_roundscale_round_ss&expand=5236) - * [x] [`_mm_roundscale_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_roundscale_sd&expand=5236) - * [x] [`_mm_roundscale_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_roundscale_ss&expand=5236) - * [x] [`_mm_rsqrt14_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rsqrt14_sd&expand=5236) - * [x] [`_mm_rsqrt14_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rsqrt14_ss&expand=5236) - * [x] [`_mm_scalef_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_scalef_round_sd&expand=5236) - * [x] [`_mm_scalef_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_scalef_round_ss&expand=5236) - * [x] [`_mm_scalef_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_scalef_sd&expand=5236) - * [x] [`_mm_scalef_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_scalef_ss&expand=5236) - * [x] [`_mm_sqrt_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_round_sd&expand=5236) - * [x] [`_mm_sqrt_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_round_ss&expand=5236) - * [x] [`_mm_sub_round_sd`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_round_sd&expand=5236) - * [x] [`_mm_sub_round_ss`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_round_ss&expand=5236) - + * [ ] [`_mm512_mask_storeu_epi64`] //need i1 + * [_] [`_mm_mask_storeu_epi64`] //need i1 + * [x] [`_mm_storeu_epi64`] + * [_] [`_mm256_mask_storeu_epi64`] //need i1 + * [x] [`_mm256_storeu_epi64`] + * [x] [`_mm512_storeu_ps`] + * [ ] [`_mm512_mask_storeu_ps`] //need i1 + * [_] [`_mm_mask_storeu_ps`] //need i1 + * [_] [`_mm256_mask_storeu_ps`] //need i1 + * [x] [`_mm512_storeu_pd`] + * [ ] [`_mm512_mask_storeu_pd`] //need i1 + * [_] [`_mm_mask_storeu_pd`] //need i1 + * [_] [`_mm256_mask_storeu_pd`] //need i1 + * [x] [`_mm512_storeu_si512`] + * [ ] [`_mm512_stream_load_si512`] //stream_load_si256, ... not implment yet + * [x] [`_mm512_stream_pd`] + * [x] [`_mm512_stream_ps`] + * [x] [`_mm512_stream_si512`] + * [x] [`_mm512_castpd128_pd512`] + * [x] [`_mm512_castpd256_pd512`] + * [x] [`_mm512_castpd512_pd128`] + * [x] [`_mm512_castpd512_pd256`] + * [x] [`_mm512_castpd_ps`] + * [x] [`_mm512_castpd_si512`] + * [x] [`_mm512_castps128_ps512`] + * [x] [`_mm512_castps256_ps512`] + * [x] [`_mm512_castps512_ps128`] + * [x] [`_mm512_castps512_ps256`] + * [x] [`_mm512_castps_pd`] + * [x] [`_mm512_castps_si512`] + * [x] [`_mm512_castsi128_si512`] + * [x] [`_mm512_castsi256_si512`] + * [x] [`_mm512_castsi512_pd`] + * [x] [`_mm512_castsi512_ps`] + * [x] [`_mm512_castsi512_si128`] + * [x] [`_mm512_castsi512_si256`] + * [x] [`_mm512_cvt_roundps_ph`] + * [x] [`_mm512_mask_cvt_roundps_ph`] + * [x] [`_mm512_maskz_cvt_roundps_ph`] + * [x] [`_mm_mask_cvt_roundps_ph`] + * [x] [`_mm_maskz_cvt_roundps_ph`] + * [x] [`_mm256_mask_cvt_roundps_ph`] + * [x] [`_mm256_maskz_cvt_roundps_ph`] + * [x] [`_mm512_cvtepi16_epi32`] + * [x] [`_mm512_mask_cvtepi16_epi32`] + * [x] [`_mm512_maskz_cvtepi16_epi32`] + * [x] [`_mm_mask_cvtepi16_epi32`] + * [x] [`_mm_maskz_cvtepi16_epi32`] + * [x] [`_mm256_mask_cvtepi16_epi32`] + * [x] [`_mm256_maskz_cvtepi16_epi32`] + * [x] [`_mm512_cvtepi16_epi64`] + * [x] [`_mm512_mask_cvtepi16_epi64`] + * [x] [`_mm512_maskz_cvtepi16_epi64`] + * [x] [`_mm_mask_cvtepi16_epi64`] + * [x] [`_mm_maskz_cvtepi16_epi64`] + * [x] [`_mm256_mask_cvtepi16_epi64`] + * [x] [`_mm256_maskz_cvtepi16_epi64`] + * [x] [`_mm512_cvtepi32_epi16`] + * [x] [`_mm512_mask_cvtepi32_epi16`] + * [x] [`_mm512_maskz_cvtepi32_epi16`] + * [x] [`_mm512_mask_cvtepi32_storeu_epi16`] + * [x] [`_mm_mask_cvtepi32_storeu_epi16`] + * [x] [`_mm256_mask_cvtepi32_storeu_epi16`] + * [x] [`_mm_cvtepi32_epi16`] + * [x] [`_mm_mask_cvtepi32_epi16`] + * [x] [`_mm_maskz_cvtepi32_epi16`] + * [x] [`_mm256_cvtepi32_epi16`] + * [x] [`_mm256_mask_cvtepi32_epi16`] + * [x] [`_mm256_maskz_cvtepi32_epi16`] + * [x] [`_mm512_cvtepi32_epi64`] + * [x] [`_mm512_mask_cvtepi32_epi64`] + * [x] [`_mm512_maskz_cvtepi32_epi64`] + * [x] [`_mm_mask_cvtepi32_epi64`] + * [x] [`_mm_maskz_cvtepi32_epi64`] + * [x] [`_mm256_mask_cvtepi32_epi64`] + * [x] [`_mm256_maskz_cvtepi32_epi64`] + * [x] [`_mm512_cvtepi32_epi8`] + * [x] [`_mm512_mask_cvtepi32_epi8`] + * [x] [`_mm512_maskz_cvtepi32_epi8`] + * [x] [`_mm512_mask_cvtepi32_storeu_epi8`] + * [x] [`_mm_mask_cvtepi32_storeu_epi8`] + * [x] [`_mm256_mask_cvtepi32_storeu_epi8`] + * [x] [`_mm_cvtepi32_epi8`] + * [x] [`_mm_mask_cvtepi32_epi8`] + * [x] [`_mm_maskz_cvtepi32_epi8`] + * [x] [`_mm256_cvtepi32_epi8`] + * [x] [`_mm256_mask_cvtepi32_epi8`] + * [x] [`_mm256_maskz_cvtepi32_epi8`] + * [x] [`_mm512_cvtepi32_ps`] + * [x] [`_mm512_mask_cvtepi32_ps`] + * [x] [`_mm512_maskz_cvtepi32_ps`] + * [x] [`_mm_mask_cvtepi32_ps`] + * [x] [`_mm_maskz_cvtepi32_ps`] + * [x] [`_mm256_mask_cvtepi32_ps`] + * [x] [`_mm256_maskz_cvtepi32_ps`] + * [x] [`_mm512_cvtepi32_pd`] + * [x] [`_mm512_mask_cvtepi32_pd`] + * [x] [`_mm512_maskz_cvtepi32_pd`] + * [x] [`_mm_mask_cvtepi32_pd`] + * [x] [`_mm_maskz_cvtepi32_pd`] + * [x] [`_mm256_mask_cvtepi32_pd`] + * [x] [`_mm256_maskz_cvtepi32_pd`] + * [x] [`_mm512_cvtepi32lo_pd`] + * [x] [`_mm512_mask_cvtepi32lo_pd`] + * [x] [`_mm512_cvtepi64_epi16`] + * [x] [`_mm512_mask_cvtepi64_epi16`] + * [x] [`_mm512_maskz_cvtepi64_epi16`] + * [x] [`_mm_cvtepi64_epi16`] + * [x] [`_mm_mask_cvtepi64_epi16`] + * [x] [`_mm_maskz_cvtepi64_epi16`] + * [x] [`_mm256_cvtepi64_epi16`] + * [x] [`_mm256_mask_cvtepi64_epi16`] + * [x] [`_mm256_maskz_cvtepi64_epi16`] + * [x] [`_mm512_mask_cvtepi64_storeu_epi16`] + * [x] [`_mm_mask_cvtepi64_storeu_epi16`] + * [x] [`_mm256_mask_cvtepi64_storeu_epi16`] + * [x] [`_mm512_cvtepi64_epi8`] + * [x] [`_mm512_mask_cvtepi64_epi8`] + * [x] [`_mm512_maskz_cvtepi64_epi8`] + * [x] [`_mm_cvtepi64_epi8`] + * [x] [`_mm_mask_cvtepi64_epi8`] + * [x] [`_mm_maskz_cvtepi64_epi8`] + * [x] [`_mm256_cvtepi64_epi8`] + * [x] [`_mm256_mask_cvtepi64_epi8`] + * [x] [`_mm256_maskz_cvtepi64_epi8`] + * [x] [`_mm512_mask_cvtepi64_storeu_epi8`] + * [x] [`_mm_mask_cvtepi64_storeu_epi8`] + * [x] [`_mm256_mask_cvtepi64_storeu_epi8`] + * [x] [`_mm512_cvtepi64_epi32`] + * [x] [`_mm512_mask_cvtepi64_epi32`] + * [x] [`_mm512_maskz_cvtepi64_epi32`] + * [x] [`_mm_cvtepi64_epi32`] + * [x] [`_mm_mask_cvtepi64_epi32`] + * [x] [`_mm_maskz_cvtepi64_epi32`] + * [x] [`_mm256_cvtepi64_epi32`] + * [x] [`_mm256_mask_cvtepi64_epi32`] + * [x] [`_mm256_maskz_cvtepi64_epi32`] + * [x] [`_mm512_mask_cvtepi64_storeu_epi32`] + * [x] [`_mm_mask_cvtepi64_storeu_epi32`] + * [x] [`_mm256_mask_cvtepi64_storeu_epi32`] + * [x] [`_mm512_cvtepi8_epi32`] + * [x] [`_mm512_mask_cvtepi8_epi32`] + * [x] [`_mm512_maskz_cvtepi8_epi32`] + * [x] [`_mm_mask_cvtepi8_epi32`] + * [x] [`_mm_maskz_cvtepi8_epi32`] + * [x] [`_mm256_mask_cvtepi8_epi32`] + * [x] [`_mm256_maskz_cvtepi8_epi32`] + * [x] [`_mm512_cvtepi8_epi64`] + * [x] [`_mm512_mask_cvtepi8_epi64`] + * [x] [`_mm512_maskz_cvtepi8_epi64`] + * [x] [`_mm_mask_cvtepi8_epi64`] + * [x] [`_mm_maskz_cvtepi8_epi64`] + * [x] [`_mm256_mask_cvtepi8_epi64`] + * [x] [`_mm256_maskz_cvtepi8_epi64`] + * [x] [`_mm512_cvtepu16_epi32`] + * [x] [`_mm512_mask_cvtepu16_epi32`] + * [x] [`_mm512_maskz_cvtepu16_epi32`] + * [x] [`_mm_mask_cvtepu16_epi32`] + * [x] [`_mm_maskz_cvtepu16_epi32`] + * [x] [`_mm256_mask_cvtepu16_epi32`] + * [x] [`_mm256_maskz_cvtepu16_epi32`] + * [x] [`_mm512_cvtepu16_epi64`] + * [x] [`_mm512_mask_cvtepu16_epi64`] + * [x] [`_mm512_maskz_cvtepu16_epi64`] + * [x] [`_mm_mask_cvtepu16_epi64`] + * [x] [`_mm_maskz_cvtepu16_epi64`] + * [x] [`_mm256_mask_cvtepu16_epi64`] + * [x] [`_mm256_maskz_cvtepu16_epi64`] + * [x] [`_mm512_cvtepu32_epi64`] + * [x] [`_mm512_mask_cvtepu32_epi64`] + * [x] [`_mm512_maskz_cvtepu32_epi64`] + * [x] [`_mm_mask_cvtepu32_epi64`] + * [x] [`_mm_maskz_cvtepu32_epi64`] + * [x] [`_mm256_mask_cvtepu32_epi64`] + * [x] [`_mm256_maskz_cvtepu32_epi64`] + * [x] [`_mm512_cvtepu32_ps`] + * [x] [`_mm512_mask_cvtepu32_ps`] + * [x] [`_mm512_maskz_cvtepu32_ps`] + * [x] [`_mm512_cvtepu32_pd`] + * [x] [`_mm512_mask_cvtepu32_pd`] + * [x] [`_mm512_maskz_cvtepu32_pd`] + * [x] [`_mm_cvtepu32_pd`] + * [x] [`_mm_mask_cvtepu32_pd`] + * [x] [`_mm_maskz_cvtepu32_pd`] + * [x] [`_mm256_cvtepu32_pd`] + * [x] [`_mm256_mask_cvtepu32_pd`] + * [x] [`_mm256_maskz_cvtepu32_pd`] + * [x] [`_mm512_cvtepu32lo_pd`] + * [x] [`_mm512_mask_cvtepu32lo_pd`] + * [x] [`_mm512_cvtepu8_epi32`] + * [x] [`_mm512_mask_cvtepu8_epi32`] + * [x] [`_mm512_maskz_cvtepu8_epi32`] + * [x] [`_mm_mask_cvtepu8_epi32`] + * [x] [`_mm_maskz_cvtepu8_epi32`] + * [x] [`_mm256_mask_cvtepu8_epi32`] + * [x] [`_mm256_maskz_cvtepu8_epi32`] + * [x] [`_mm512_cvtepu8_epi64`] + * [x] [`_mm512_mask_cvtepu8_epi64`] + * [x] [`_mm512_maskz_cvtepu8_epi64`] + * [x] [`_mm_mask_cvtepu8_epi64`] + * [x] [`_mm_maskz_cvtepu8_epi64`] + * [x] [`_mm256_mask_cvtepu8_epi64`] + * [x] [`_mm256_maskz_cvtepu8_epi64`] + * [x] [`_mm512_cvtpd_epi32`] + * [x] [`_mm512_mask_cvtpd_epi32`] + * [x] [`_mm512_maskz_cvtpd_epi32`] + * [x] [`_mm_mask_cvtpd_epi32`] + * [x] [`_mm_maskz_cvtpd_epi32`] + * [x] [`_mm256_mask_cvtpd_epi32`] + * [x] [`_mm256_maskz_cvtpd_epi32`] + * [x] [`_mm512_cvtpd_epu32`] + * [x] [`_mm512_mask_cvtpd_epu32`] + * [x] [`_mm512_maskz_cvtpd_epu32`] + * [x] [`_mm_cvtpd_epu32`] + * [x] [`_mm_mask_cvtpd_epu32`] + * [x] [`_mm_maskz_cvtpd_epu32`] + * [x] [`_mm256_cvtpd_epu32`] + * [x] [`_mm256_mask_cvtpd_epu32`] + * [x] [`_mm256_maskz_cvtpd_epu32`] + * [x] [`_mm512_cvtpd_ps`] + * [x] [`_mm512_mask_cvtpd_ps`] + * [x] [`_mm512_maskz_cvtpd_ps`] + * [x] [`_mm_mask_cvtpd_ps`] + * [x] [`_mm_maskz_cvtpd_ps`] + * [x] [`_mm256_mask_cvtpd_ps`] + * [x] [`_mm256_maskz_cvtpd_ps`] + * [x] [`_mm512_cvtpd_pslo`] + * [x] [`_mm512_mask_cvtpd_pslo`] + * [x] [`_mm512_cvtph_ps`] + * [x] [`_mm512_mask_cvtph_ps`] + * [x] [`_mm512_maskz_cvtph_ps`] + * [x] [`_mm_mask_cvtph_ps`] + * [x] [`_mm_maskz_cvtph_ps`] + * [x] [`_mm256_mask_cvtph_ps`] + * [x] [`_mm256_maskz_cvtph_ps`] + * [x] [`_mm512_cvtps_epi32`] + * [x] [`_mm512_mask_cvtps_epi32`] + * [x] [`_mm512_maskz_cvtps_epi32`] + * [x] [`_mm_mask_cvtps_epi32`] + * [x] [`_mm_maskz_cvtps_epi32`] + * [x] [`_mm256_mask_cvtps_epi32`] + * [x] [`_mm256_maskz_cvtps_epi32`] + * [x] [`_mm512_cvtps_epu32`] + * [x] [`_mm512_mask_cvtps_epu32`] + * [x] [`_mm512_maskz_cvtps_epu32`] + * [x] [`_mm_cvtps_epu32`] + * [x] [`_mm_mask_cvtps_epu32`] + * [x] [`_mm_maskz_cvtps_epu32`] + * [x] [`_mm256_cvtps_epu32`] + * [x] [`_mm256_mask_cvtps_epu32`] + * [x] [`_mm256_maskz_cvtps_epu32`] + * [x] [`_mm512_cvtps_pd`] + * [x] [`_mm512_mask_cvtps_pd`] + * [x] [`_mm512_maskz_cvtps_pd`] + * [x] [`_mm512_cvtps_ph`] + * [x] [`_mm512_mask_cvtps_ph`] + * [x] [`_mm512_maskz_cvtps_ph`] + * [x] [`_mm_mask_cvtps_ph`] + * [x] [`_mm_maskz_cvtps_ph`] + * [x] [`_mm256_mask_cvtps_ph`] + * [x] [`_mm256_maskz_cvtps_ph`] + * [x] [`_mm512_cvtpslo_pd`] + * [x] [`_mm512_mask_cvtpslo_pd`] + * [x] [`_mm512_cvtsepi32_epi16`] + * [x] [`_mm512_mask_cvtsepi32_epi16`] + * [x] [`_mm512_maskz_cvtsepi32_epi16`] + * [x] [`_mm_cvtsepi32_epi16`] + * [x] [`_mm_mask_cvtsepi32_epi16`] + * [x] [`_mm_maskz_cvtsepi32_epi16`] + * [x] [`_mm256_cvtsepi32_epi16`] + * [x] [`_mm256_mask_cvtsepi32_epi16`] + * [x] [`_mm256_maskz_cvtsepi32_epi16`] + * [x] [`_mm512_cvtsepi32_epi8`] + * [x] [`_mm512_mask_cvtsepi32_epi8`] + * [x] [`_mm512_maskz_cvtsepi32_epi8`] + * [x] [`_mm_cvtsepi32_epi8`] + * [x] [`_mm_mask_cvtsepi32_epi8`] + * [x] [`_mm_maskz_cvtsepi32_epi8`] + * [x] [`_mm256_cvtsepi32_epi8`] + * [x] [`_mm256_mask_cvtsepi32_epi8`] + * [x] [`_mm256_maskz_cvtsepi32_epi8`] + * [x] [`_mm512_mask_cvtsepi32_storeu_epi16`] + * [x] [`_mm_mask_cvtsepi32_storeu_epi16`] + * [x] [`_mm256_mask_cvtsepi32_storeu_epi16`] + * [x] [`_mm512_mask_cvtsepi32_storeu_epi8`] + * [x] [`_mm_mask_cvtsepi32_storeu_epi8`] + * [x] [`_mm256_mask_cvtsepi32_storeu_epi8`] + * [x] [`_mm512_cvtsepi64_epi16`] + * [x] [`_mm512_mask_cvtsepi64_epi16`] + * [x] [`_mm512_maskz_cvtsepi64_epi16`] + * [x] [`_mm_cvtsepi64_epi16`] + * [x] [`_mm_mask_cvtsepi64_epi16`] + * [x] [`_mm_maskz_cvtsepi64_epi16`] + * [x] [`_mm256_cvtsepi64_epi16`] + * [x] [`_mm256_mask_cvtsepi64_epi16`] + * [x] [`_mm256_maskz_cvtsepi64_epi16`] + * [x] [`_mm512_cvtsepi64_epi32`] + * [x] [`_mm512_mask_cvtsepi64_epi32`] + * [x] [`_mm512_maskz_cvtsepi64_epi32`] + * [x] [`_mm_cvtsepi64_epi32`] + * [x] [`_mm_mask_cvtsepi64_epi32`] + * [x] [`_mm_maskz_cvtsepi64_epi32`] + * [x] [`_mm256_cvtsepi64_epi32`] + * [x] [`_mm256_mask_cvtsepi64_epi32`] + * [x] [`_mm256_maskz_cvtsepi64_epi32`] + * [x] [`_mm512_cvtsepi64_epi8`] + * [x] [`_mm512_mask_cvtsepi64_epi8`] + * [x] [`_mm512_maskz_cvtsepi64_epi8`] + * [x] [`_mm_cvtsepi64_epi8`] + * [x] [`_mm_mask_cvtsepi64_epi8`] + * [x] [`_mm_maskz_cvtsepi64_epi8`] + * [x] [`_mm256_cvtsepi64_epi8`] + * [x] [`_mm256_mask_cvtsepi64_epi8`] + * [x] [`_mm256_maskz_cvtsepi64_epi8`] + * [x] [`_mm512_mask_cvtsepi64_storeu_epi16`] + * [x] [`_mm_mask_cvtsepi64_storeu_epi16`] + * [x] [`_mm256_mask_cvtsepi64_storeu_epi16`] + * [x] [`_mm512_mask_cvtsepi64_storeu_epi32`] + * [x] [`_mm_mask_cvtsepi64_storeu_epi32`] + * [x] [`_mm256_mask_cvtsepi64_storeu_epi32`] + * [x] [`_mm512_mask_cvtsepi64_storeu_epi8`] + * [x] [`_mm_mask_cvtsepi64_storeu_epi8`] + * [x] [`_mm256_mask_cvtsepi64_storeu_epi8`] + * [x] [`_mm512_cvtusepi32_epi16`] + * [x] [`_mm512_mask_cvtusepi32_epi16`] + * [x] [`_mm512_maskz_cvtusepi32_epi16`] + * [x] [`_mm_cvtusepi32_epi16`] + * [x] [`_mm_mask_cvtusepi32_epi16`] + * [x] [`_mm_maskz_cvtusepi32_epi16`] + * [x] [`_mm256_cvtusepi32_epi16`] + * [x] [`_mm256_mask_cvtusepi32_epi16`] + * [x] [`_mm256_maskz_cvtusepi32_epi16`] + * [x] [`_mm512_cvtusepi32_epi8`] + * [x] [`_mm512_mask_cvtusepi32_epi8`] + * [x] [`_mm512_maskz_cvtusepi32_epi8`] + * [x] [`_mm_cvtusepi32_epi8`] + * [x] [`_mm_mask_cvtusepi32_epi8`] + * [x] [`_mm_maskz_cvtusepi32_epi8`] + * [x] [`_mm256_cvtusepi32_epi8`] + * [x] [`_mm256_mask_cvtusepi32_epi8`] + * [x] [`_mm256_maskz_cvtusepi32_epi8`] + * [x] [`_mm512_mask_cvtusepi32_storeu_epi16`] + * [x] [`_mm_mask_cvtusepi32_storeu_epi16`] + * [x] [`_mm256_mask_cvtusepi32_storeu_epi16`] + * [x] [`_mm512_mask_cvtusepi32_storeu_epi8`] + * [x] [`_mm_mask_cvtusepi32_storeu_epi8`] + * [x] [`_mm256_mask_cvtusepi32_storeu_epi8`] + * [x] [`_mm512_cvtusepi64_epi16`] + * [x] [`_mm512_mask_cvtusepi64_epi16`] + * [x] [`_mm512_maskz_cvtusepi64_epi16`] + * [x] [`_mm_cvtusepi64_epi16`] + * [x] [`_mm_mask_cvtusepi64_epi16`] + * [x] [`_mm_maskz_cvtusepi64_epi16`] + * [x] [`_mm256_cvtusepi64_epi16`] + * [x] [`_mm256_mask_cvtusepi64_epi16`] + * [x] [`_mm256_maskz_cvtusepi64_epi16`] + * [x] [`_mm512_cvtusepi64_epi32`] + * [x] [`_mm512_mask_cvtusepi64_epi32`] + * [x] [`_mm512_maskz_cvtusepi64_epi32`] + * [x] [`_mm_cvtusepi64_epi32`] + * [x] [`_mm_mask_cvtusepi64_epi32`] + * [x] [`_mm_maskz_cvtusepi64_epi32`] + * [x] [`_mm256_cvtusepi64_epi32`] + * [x] [`_mm256_mask_cvtusepi64_epi32`] + * [x] [`_mm256_maskz_cvtusepi64_epi32`] + * [x] [`_mm512_cvtusepi64_epi8`] + * [x] [`_mm512_mask_cvtusepi64_epi8`] + * [x] [`_mm512_maskz_cvtusepi64_epi8`] + * [x] [`_mm_cvtusepi64_epi8`] + * [x] [`_mm_mask_cvtusepi64_epi8`] + * [x] [`_mm_maskz_cvtusepi64_epi8`] + * [x] [`_mm256_cvtusepi64_epi8`] + * [x] [`_mm256_mask_cvtusepi64_epi8`] + * [x] [`_mm256_maskz_cvtusepi64_epi8`] + * [x] [`_mm512_mask_cvtusepi64_storeu_epi16`] + * [x] [`_mm_mask_cvtusepi64_storeu_epi16`] + * [x] [`_mm256_mask_cvtusepi64_storeu_epi16`] + * [x] [`_mm512_mask_cvtusepi64_storeu_epi32`] + * [x] [`_mm_mask_cvtusepi64_storeu_epi32`] + * [x] [`_mm256_mask_cvtusepi64_storeu_epi32`] + * [x] [`_mm512_mask_cvtusepi64_storeu_epi8`] + * [x] [`_mm_mask_cvtusepi64_storeu_epi8`] + * [x] [`_mm256_mask_cvtusepi64_storeu_epi8`] + * [x] [`_mm512_cvtsi512_si32`] + * [x] [`_mm512_cvttpd_epi32`] + * [x] [`_mm512_mask_cvttpd_epi32`] + * [x] [`_mm512_maskz_cvttpd_epi32`] + * [x] [`_mm_mask_cvttpd_epi32`] + * [x] [`_mm_maskz_cvttpd_epi32`] + * [x] [`_mm256_mask_cvttpd_epi32`] + * [x] [`_mm256_maskz_cvttpd_epi32`] + * [x] [`_mm512_cvttpd_epu32`] + * [x] [`_mm512_mask_cvttpd_epu32`] + * [x] [`_mm512_maskz_cvttpd_epu32`] + * [x] [`_mm_cvttpd_epu32`] + * [x] [`_mm_mask_cvttpd_epu32`] + * [x] [`_mm_maskz_cvttpd_epu32`] + * [x] [`_mm256_cvttpd_epu32`] + * [x] [`_mm256_mask_cvttpd_epu32`] + * [x] [`_mm256_maskz_cvttpd_epu32`] + * [x] [`_mm512_cvttps_epi32`] + * [x] [`_mm512_mask_cvttps_epi32`] + * [x] [`_mm512_maskz_cvttps_epi32`] + * [x] [`_mm_mask_cvttps_epi32`] + * [x] [`_mm_maskz_cvttps_epi32`] + * [x] [`_mm256_mask_cvttps_epi32`] + * [x] [`_mm256_maskz_cvttps_epi32`] + * [x] [`_mm512_cvttps_epu32`] + * [x] [`_mm512_mask_cvttps_epu32`] + * [x] [`_mm512_maskz_cvttps_epu32`] + * [x] [`_mm_cvttps_epu32`] + * [x] [`_mm_mask_cvttps_epu32`] + * [x] [`_mm_maskz_cvttps_epu32`] + * [x] [`_mm256_cvttps_epu32`] + * [x] [`_mm256_mask_cvttps_epu32`] + * [x] [`_mm256_maskz_cvttps_epu32`] + * [x] [`_mm512_cvt_roundepi32_ps`] + * [x] [`_mm512_mask_cvt_roundepi32_ps`] + * [x] [`_mm512_maskz_cvt_roundepi32_ps`] + * [x] [`_mm512_cvt_roundepu32_ps`] + * [x] [`_mm512_mask_cvt_roundepu32_ps`] + * [x] [`_mm512_maskz_cvt_roundepu32_ps`] + * [x] [`_mm512_cvt_roundpd_epi32`] + * [x] [`_mm512_mask_cvt_roundpd_epi32`] + * [x] [`_mm512_maskz_cvt_roundpd_epi32`] + * [x] [`_mm512_cvt_roundpd_epu32`] + * [x] [`_mm512_mask_cvt_roundpd_epu32`] + * [x] [`_mm512_maskz_cvt_roundpd_epu32`] + * [x] [`_mm512_cvt_roundpd_ps`] + * [x] [`_mm512_mask_cvt_roundpd_ps`] + * [x] [`_mm512_maskz_cvt_roundpd_ps`] + * [x] [`_mm512_cvt_roundph_ps`] + * [x] [`_mm512_mask_cvt_roundph_ps`] + * [x] [`_mm512_maskz_cvt_roundph_ps`] + * [x] [`_mm512_cvt_roundps_epi32`] + * [x] [`_mm512_mask_cvt_roundps_epi32`] + * [x] [`_mm512_maskz_cvt_roundps_epi32`] + * [x] [`_mm512_cvt_roundps_epu32`] + * [x] [`_mm512_mask_cvt_roundps_epu32`] + * [x] [`_mm512_maskz_cvt_roundps_epu32`] + * [x] [`_mm512_cvt_roundps_pd`] + * [x] [`_mm512_mask_cvt_roundps_pd`] + * [x] [`_mm512_maskz_cvt_roundps_pd`] + * [x] [`_mm512_cvtt_roundpd_epi32`] + * [x] [`_mm512_mask_cvtt_roundpd_epi32`] + * [x] [`_mm512_maskz_cvtt_roundpd_epi32`] + * [x] [`_mm512_cvtt_roundpd_epu32`] + * [x] [`_mm512_mask_cvtt_roundpd_epu32`] + * [x] [`_mm512_maskz_cvtt_roundpd_epu32`] + * [x] [`_mm512_cvtt_roundps_epi32`] + * [x] [`_mm512_mask_cvtt_roundps_epi32`] + * [x] [`_mm512_maskz_cvtt_roundps_epi32`] + * [x] [`_mm512_cvtt_roundps_epu32`] + * [x] [`_mm512_mask_cvtt_roundps_epu32`] + * [x] [`_mm512_maskz_cvtt_roundps_epu32`] + * [x] [`_mm_add_round_sd`] + * [x] [`_mm_add_round_ss`] + * [x] [`_mm_cmp_round_sd_mask`] + * [x] [`_mm_cmp_round_ss_mask`] + * [x] [`_mm_cmp_sd_mask`] + * [x] [`_mm_cmp_ss_mask`] + * [x] [`_mm_comi_round_sd`] + * [x] [`_mm_comi_round_ss`] + * [x] [`_mm_cvt_roundi32_ss`] + * [x] [`_mm_cvt_roundi64_sd`] + * [x] [`_mm_cvt_roundi64_ss`] + * [x] [`_mm_cvt_roundsd_i32`] + * [x] [`_mm_cvt_roundsd_i64`] + * [x] [`_mm_cvt_roundsd_si32`] + * [x] [`_mm_cvt_roundsd_si64`] + * [x] [`_mm_cvt_roundsd_ss`] + * [x] [`_mm_cvt_roundsd_u32`] + * [x] [`_mm_cvt_roundsd_u64`] + * [x] [`_mm_cvt_roundsi32_ss`] + * [x] [`_mm_cvt_roundsi64_sd`] + * [x] [`_mm_cvt_roundsi64_ss`] + * [x] [`_mm_cvt_roundss_i32`] + * [x] [`_mm_cvt_roundss_i64`] + * [x] [`_mm_cvt_roundss_sd`] + * [x] [`_mm_cvt_roundss_si32`] + * [x] [`_mm_cvt_roundss_si64`] + * [x] [`_mm_cvt_roundss_u32`] + * [x] [`_mm_cvt_roundss_u64`] + * [x] [`_mm_cvt_roundu32_ss`] + * [x] [`_mm_cvt_roundu64_sd`] + * [x] [`_mm_cvt_roundu64_ss`] + * [x] [`_mm_cvti32_sd`] + * [x] [`_mm_cvti32_ss`] + * [x] [`_mm_cvti64_sd`] + * [x] [`_mm_cvti64_ss`] + * [x] [`_mm_cvtsd_i32`] + * [x] [`_mm_cvtsd_i64`] + * [x] [`_mm_cvtsd_u32`] + * [x] [`_mm_cvtsd_u64`] + * [x] [`_mm_cvtss_i32`] + * [x] [`_mm_cvtss_i64`] + * [x] [`_mm_cvtss_u32`] + * [x] [`_mm_cvtss_u64`] + * [x] [`_mm_cvtt_roundsd_i32`] + * [x] [`_mm_cvtt_roundsd_i64`] + * [x] [`_mm_cvtt_roundsd_si32`] + * [x] [`_mm_cvtt_roundsd_si64`] + * [x] [`_mm_cvtt_roundsd_u32`] + * [x] [`_mm_cvtt_roundsd_u64`] + * [x] [`_mm_cvtt_roundss_i32`] + * [x] [`_mm_cvtt_roundss_i64`] + * [x] [`_mm_cvtt_roundss_si32`] + * [x] [`_mm_cvtt_roundss_si64`] + * [x] [`_mm_cvtt_roundss_u32`] + * [x] [`_mm_cvtt_roundss_u64`] + * [x] [`_mm_cvttsd_i32`] + * [x] [`_mm_cvttsd_i64`] + * [x] [`_mm_cvttsd_u32`] + * [x] [`_mm_cvttsd_u64`] + * [x] [`_mm_cvttss_i32`] + * [x] [`_mm_cvttss_i64`] + * [x] [`_mm_cvttss_u32`] + * [x] [`_mm_cvttss_u64`] + * [x] [`_mm_cvtu32_sd`] + * [x] [`_mm_cvtu32_ss`] + * [x] [`_mm_cvtu64_sd`] + * [x] [`_mm_cvtu64_ss`] + * [x] [`_mm_div_round_sd`] + * [x] [`_mm_div_round_ss`] + * [x] [`_mm_fixupimm_round_sd`] + * [x] [`_mm_fixupimm_round_ss`] + * [x] [`_mm_fixupimm_sd`] + * [x] [`_mm_fixupimm_ss`] + * [x] [`_mm_fmadd_round_sd`] + * [x] [`_mm_fmadd_round_ss`] + * [x] [`_mm_fmsub_round_sd`] + * [x] [`_mm_fmsub_round_ss`] + * [x] [`_mm_fnmadd_round_sd`] + * [x] [`_mm_fnmadd_round_ss`] + * [x] [`_mm_fnmsub_round_sd`] + * [x] [`_mm_fnmsub_round_ss`] + * [x] [`_mm_getexp_round_sd`] + * [x] [`_mm_getexp_round_ss`] + * [x] [`_mm_getexp_sd`] + * [x] [`_mm_getexp_ss`] + * [x] [`_mm_getmant_round_sd`] + * [x] [`_mm_getmant_round_ss`] + * [x] [`_mm_getmant_sd`] + * [x] [`_mm_getmant_ss`] + * [x] [`_mm_mask3_fmadd_round_sd`] + * [x] [`_mm_mask3_fmadd_round_ss`] + * [x] [`_mm_mask3_fmadd_sd`] + * [x] [`_mm_mask3_fmadd_ss`] + * [x] [`_mm_mask3_fmsub_round_sd`] + * [x] [`_mm_mask3_fmsub_round_ss`] + * [x] [`_mm_mask3_fmsub_sd`] + * [x] [`_mm_mask3_fmsub_ss`] + * [x] [`_mm_mask3_fnmadd_round_sd`] + * [x] [`_mm_mask3_fnmadd_round_ss`] + * [x] [`_mm_mask3_fnmadd_sd`] + * [x] [`_mm_mask3_fnmadd_ss`] + * [x] [`_mm_mask3_fnmsub_round_sd`] + * [x] [`_mm_mask3_fnmsub_round_ss`] + * [x] [`_mm_mask3_fnmsub_sd`] + * [x] [`_mm_mask3_fnmsub_ss`] + * [x] [`_mm_mask_add_round_sd`] + * [x] [`_mm_mask_add_round_ss`] + * [x] [`_mm_mask_add_sd`] + * [x] [`_mm_mask_add_ss`] + * [x] [`_mm_mask_cmp_round_sd_mask`] + * [x] [`_mm_mask_cmp_round_ss_mask`] + * [x] [`_mm_mask_cmp_sd_mask`] + * [x] [`_mm_mask_cmp_ss_mask`] + * [x] [`_mm_mask_cvt_roundsd_ss`] + * [x] [`_mm_mask_cvt_roundss_sd`] + * [x] [`_mm_mask_cvtsd_ss`] + * [x] [`_mm_mask_cvtss_sd`] + * [x] [`_mm_mask_div_round_sd`] + * [x] [`_mm_mask_div_round_ss`] + * [x] [`_mm_mask_div_sd`] + * [x] [`_mm_mask_div_ss`] + * [x] [`_mm_mask_fixupimm_round_sd`] + * [x] [`_mm_mask_fixupimm_round_ss`] + * [x] [`_mm_mask_fixupimm_sd`] + * [x] [`_mm_mask_fixupimm_ss`] + * [x] [`_mm_mask_fmadd_round_sd`] + * [x] [`_mm_mask_fmadd_round_ss`] + * [x] [`_mm_mask_fmadd_sd`] + * [x] [`_mm_mask_fmadd_ss`] + * [x] [`_mm_mask_fmsub_round_sd`] + * [x] [`_mm_mask_fmsub_round_ss`] + * [x] [`_mm_mask_fmsub_sd`] + * [x] [`_mm_mask_fmsub_ss`] + * [x] [`_mm_mask_fnmadd_round_sd`] + * [x] [`_mm_mask_fnmadd_round_ss`] + * [x] [`_mm_mask_fnmadd_sd`] + * [x] [`_mm_mask_fnmadd_ss`] + * [x] [`_mm_mask_fnmsub_round_sd`] + * [x] [`_mm_mask_fnmsub_round_ss`] + * [x] [`_mm_mask_fnmsub_sd`] + * [x] [`_mm_mask_fnmsub_ss`] + * [x] [`_mm_mask_getexp_round_sd`] + * [x] [`_mm_mask_getexp_round_ss`] + * [x] [`_mm_mask_getexp_sd`] + * [x] [`_mm_mask_getexp_ss`] + * [x] [`_mm_mask_getmant_round_sd`] + * [x] [`_mm_mask_getmant_round_ss`] + * [x] [`_mm_mask_getmant_sd`] + * [x] [`_mm_mask_getmant_ss`] + * [ ] [`_mm_mask_load_sd`] //need i1 + * [ ] [`_mm_mask_load_ss`] //need i1 + * [x] [`_mm_mask_max_round_sd`] + * [x] [`_mm_mask_max_round_ss`] + * [x] [`_mm_mask_max_sd`] + * [x] [`_mm_mask_max_ss`] + * [x] [`_mm_mask_min_round_sd`] + * [x] [`_mm_mask_min_round_ss`] + * [x] [`_mm_mask_min_sd`] + * [x] [`_mm_mask_min_ss`] + * [x] [`_mm_mask_move_sd`] + * [x] [`_mm_mask_move_ss`] + * [x] [`_mm_mask_mul_round_sd`] + * [x] [`_mm_mask_mul_round_ss`] + * [x] [`_mm_mask_mul_sd`] + * [x] [`_mm_mask_mul_ss`] + * [x] [`_mm_mask_rcp14_sd`] + * [x] [`_mm_mask_rcp14_ss`] + * [x] [`_mm_mask_roundscale_round_sd`] + * [x] [`_mm_mask_roundscale_round_ss`] + * [x] [`_mm_mask_roundscale_sd`] + * [x] [`_mm_mask_roundscale_ss`] + * [x] [`_mm_mask_rsqrt14_sd`] + * [x] [`_mm_mask_rsqrt14_ss`] + * [x] [`_mm_mask_scalef_round_sd`] + * [x] [`_mm_mask_scalef_round_ss`] + * [x] [`_mm_mask_scalef_sd`] + * [x] [`_mm_mask_scalef_ss`] + * [x] [`_mm_mask_sqrt_round_sd`] + * [x] [`_mm_mask_sqrt_round_ss`] + * [x] [`_mm_mask_sqrt_sd`] + * [x] [`_mm_mask_sqrt_ss`] + * [ ] [`_mm_mask_store_sd`] //need i1 + * [ ] [`_mm_mask_store_ss`] //need i1 + * [x] [`_mm_mask_sub_round_sd`] + * [x] [`_mm_mask_sub_round_ss`] + * [x] [`_mm_mask_sub_sd`] + * [x] [`_mm_mask_sub_ss`] + * [x] [`_mm_maskz_add_round_sd`] + * [x] [`_mm_maskz_add_round_ss`] + * [x] [`_mm_maskz_add_sd`] + * [x] [`_mm_maskz_add_ss`] + * [x] [`_mm_maskz_cvt_roundsd_ss`] + * [x] [`_mm_maskz_cvt_roundss_sd`] + * [x] [`_mm_maskz_cvtsd_ss`] + * [x] [`_mm_maskz_cvtss_sd`] + * [x] [`_mm_maskz_div_round_sd`] + * [x] [`_mm_maskz_div_round_ss`] + * [x] [`_mm_maskz_div_sd`] + * [x] [`_mm_maskz_div_ss`] + * [x] [`_mm_maskz_fixupimm_round_sd`] + * [x] [`_mm_maskz_fixupimm_round_ss`] + * [x] [`_mm_maskz_fixupimm_sd`] + * [x] [`_mm_maskz_fixupimm_ss`] + * [x] [`_mm_maskz_fmadd_round_sd`] + * [x] [`_mm_maskz_fmadd_round_ss`] + * [x] [`_mm_maskz_fmadd_sd`] + * [x] [`_mm_maskz_fmadd_ss`] + * [x] [`_mm_maskz_fmsub_round_sd`] + * [x] [`_mm_maskz_fmsub_round_ss`] + * [x] [`_mm_maskz_fmsub_sd`] + * [x] [`_mm_maskz_fmsub_ss`] + * [x] [`_mm_maskz_fnmadd_round_sd`] + * [x] [`_mm_maskz_fnmadd_round_ss`] + * [x] [`_mm_maskz_fnmadd_sd`] + * [x] [`_mm_maskz_fnmadd_ss`] + * [x] [`_mm_maskz_fnmsub_round_sd`] + * [x] [`_mm_maskz_fnmsub_round_ss`] + * [x] [`_mm_maskz_fnmsub_sd`] + * [x] [`_mm_maskz_fnmsub_ss`] + * [x] [`_mm_maskz_getexp_round_sd`] + * [x] [`_mm_maskz_getexp_round_ss`] + * [x] [`_mm_maskz_getexp_sd`] + * [x] [`_mm_maskz_getexp_ss`] + * [x] [`_mm_maskz_getmant_round_sd`] + * [x] [`_mm_maskz_getmant_round_ss`] + * [x] [`_mm_maskz_getmant_sd`] + * [x] [`_mm_maskz_getmant_ss`] + * [ ] [`_mm_maskz_load_sd`] //need i1 + * [ ] [`_mm_maskz_load_ss`] //need i1 + * [x] [`_mm_maskz_max_round_sd`] + * [x] [`_mm_maskz_max_round_ss`] + * [x] [`_mm_maskz_max_sd`] + * [x] [`_mm_maskz_max_ss`] + * [x] [`_mm_maskz_min_round_sd`] + * [x] [`_mm_maskz_min_round_ss`] + * [x] [`_mm_maskz_min_sd`] + * [x] [`_mm_maskz_min_ss`] + * [x] [`_mm_maskz_move_sd`] + * [x] [`_mm_maskz_move_ss`] + * [x] [`_mm_maskz_mul_round_sd`] + * [x] [`_mm_maskz_mul_round_ss`] + * [x] [`_mm_maskz_mul_sd`] + * [x] [`_mm_maskz_mul_ss`] + * [x] [`_mm_maskz_rcp14_sd`] + * [x] [`_mm_maskz_rcp14_ss`] + * [x] [`_mm_maskz_roundscale_round_sd`] + * [x] [`_mm_maskz_roundscale_round_ss`] + * [x] [`_mm_maskz_roundscale_sd`] + * [x] [`_mm_maskz_roundscale_ss`] + * [x] [`_mm_maskz_rsqrt14_sd`] + * [x] [`_mm_maskz_rsqrt14_ss`] + * [x] [`_mm_maskz_scalef_round_sd`] + * [x] [`_mm_maskz_scalef_round_ss`] + * [x] [`_mm_maskz_scalef_sd`] + * [x] [`_mm_maskz_scalef_ss`] + * [x] [`_mm_maskz_sqrt_round_sd`] + * [x] [`_mm_maskz_sqrt_round_ss`] + * [x] [`_mm_maskz_sqrt_sd`] + * [x] [`_mm_maskz_sqrt_ss`] + * [x] [`_mm_maskz_sub_round_sd`] + * [x] [`_mm_maskz_sub_round_ss`] + * [x] [`_mm_maskz_sub_sd`] + * [x] [`_mm_maskz_sub_ss`] + * [x] [`_mm_max_round_sd`] + * [x] [`_mm_max_round_ss`] + * [x] [`_mm_min_round_sd`] + * [x] [`_mm_min_round_ss`] + * [x] [`_mm_mul_round_sd`] + * [x] [`_mm_mul_round_ss`] + * [x] [`_mm_rcp14_sd`] + * [x] [`_mm_rcp14_ss`] + * [x] [`_mm_roundscale_round_sd`] + * [x] [`_mm_roundscale_round_ss`] + * [x] [`_mm_roundscale_sd`] + * [x] [`_mm_roundscale_ss`] + * [x] [`_mm_rsqrt14_sd`] + * [x] [`_mm_rsqrt14_ss`] + * [x] [`_mm_scalef_round_sd`] + * [x] [`_mm_scalef_round_ss`] + * [x] [`_mm_scalef_sd`] + * [x] [`_mm_scalef_ss`] + * [x] [`_mm_sqrt_round_sd`] + * [x] [`_mm_sqrt_round_ss`] + * [x] [`_mm_sub_round_sd`] + * [x] [`_mm_sub_round_ss`] + * [x] [`_mm512_int2mask`] + * [x] [`_mm512_kand`] + * [x] [`_mm512_kandn`] + * [x] [`_mm512_kmov`] + * [x] [`_mm512_knot`] + * [x] [`_mm512_kor`] + * [x] [`_mm512_kortestc`] + * [ ] [`_mm512_kortestz`] //not sure + * [x] [`_mm512_kunpackb`] + * [x] [`_mm512_kxnor`] + * [x] [`_mm512_kxor`] + * [x] [`_mm512_mask2int`]

diff --git a/library/stdarch/crates/core_arch/avx512vbmi2.md b/library/stdarch/crates/core_arch/avx512vbmi2.md new file mode 100644 index 0000000000..693af9d930 --- /dev/null +++ b/library/stdarch/crates/core_arch/avx512vbmi2.md @@ -0,0 +1,153 @@ +["AVX512_VBMI2"]

+ + * [x] [`_mm_mask_compress_epi16`] + * [x] [`_mm_maskz_compress_epi16`] + * [x] [`_mm256_mask_compress_epi16`] + * [x] [`_mm256_maskz_compress_epi16`] + * [x] [`_mm512_mask_compress_epi16`] + * [x] [`_mm512_maskz_compress_epi16`] + * [x] [`_mm_mask_compress_epi8`] + * [x] [`_mm_maskz_compress_epi8`] + * [x] [`_mm256_mask_compress_epi8`] + * [x] [`_mm256_maskz_compress_epi8`] + * [x] [`_mm512_mask_compress_epi8`] + * [x] [`_mm512_maskz_compress_epi8`] + * [_] [`_mm_mask_compressstoreu_epi16`] //need i1 + * [_] [`_mm256_mask_compressstoreu_epi16`] //need i1 + * [_] [`_mm512_mask_compressstoreu_epi16`] //need i1 + * [_] [`_mm_mask_compressstoreu_epi8`] //need i1 + * [_] [`_mm256_mask_compressstoreu_epi8`] //need i1 + * [_] [`_mm512_mask_compressstoreu_epi8`] //need i1 + * [x] [`_mm_mask_expand_epi16`] + * [x] [`_mm_maskz_expand_epi16`] + * [x] [`_mm256_mask_expand_epi16`] + * [x] [`_mm256_maskz_expand_epi16`] + * [x] [`_mm512_mask_expand_epi16`] + * [x] [`_mm512_maskz_expand_epi16`] + * [x] [`_mm_mask_expand_epi8`] + * [x] [`_mm_maskz_expand_epi8`] + * [x] [`_mm256_mask_expand_epi8`] + * [x] [`_mm256_maskz_expand_epi8`] + * [x] [`_mm512_mask_expand_epi8`] + * [x] [`_mm512_maskz_expand_epi8`] + * [_] [`_mm_mask_expandloadu_epi16`] //need i1 + * [_] [`_mm_maskz_expandloadu_epi16`] //need i1 + * [_] [`_mm256_mask_expandloadu_epi16`] //need i1 + * [_] [`_mm256_maskz_expandloadu_epi16`] //need i1 + * [_] [`_mm512_mask_expandloadu_epi16`] //need i1 + * [_] [`_mm512_maskz_expandloadu_epi16`] //need i1 + * [_] [`_mm_mask_expandloadu_epi8`] //need i1 + * [_] [`_mm_maskz_expandloadu_epi8`] //need i1 + * [_] [`_mm256_mask_expandloadu_epi8`] //need i1 + * [_] [`_mm256_maskz_expandloadu_epi8`] //need i1 + * [_] [`_mm512_mask_expandloadu_epi8`] //need i1 + * [_] [`_mm512_maskz_expandloadu_epi8`] //need i1 + * [x] [`_mm_mask_shldi_epi16`] + * [x] [`_mm_maskz_shldi_epi16`] + * [x] [`_mm_shldi_epi16`] + * [x] [`_mm256_mask_shldi_epi16`] + * [x] [`_mm256_maskz_shldi_epi16`] + * [x] [`_mm256_shldi_epi16`] + * [x] [`_mm512_mask_shldi_epi16`] + * [x] [`_mm512_maskz_shldi_epi16`] + * [x] [`_mm512_shldi_epi16`] + * [x] [`_mm_mask_shldi_epi32`] + * [x] [`_mm_maskz_shldi_epi32`] + * [x] [`_mm_shldi_epi32`] + * [x] [`_mm256_mask_shldi_epi32`] + * [x] [`_mm256_maskz_shldi_epi32`] + * [x] [`_mm256_shldi_epi32`] + * [x] [`_mm512_mask_shldi_epi32`] + * [x] [`_mm512_maskz_shldi_epi32`] + * [x] [`_mm512_shldi_epi32`] + * [x] [`_mm_mask_shldi_epi64`] + * [x] [`_mm_maskz_shldi_epi64`] + * [x] [`_mm_shldi_epi64`] + * [x] [`_mm256_mask_shldi_epi64`] + * [x] [`_mm256_maskz_shldi_epi64`] + * [x] [`_mm256_shldi_epi64`] + * [x] [`_mm512_mask_shldi_epi64`] + * [x] [`_mm512_maskz_shldi_epi64`] + * [x] [`_mm512_shldi_epi64`] + * [x] [`_mm_mask_shldv_epi16`] + * [x] [`_mm_maskz_shldv_epi16`] + * [x] [`_mm_shldv_epi16`] + * [x] [`_mm256_mask_shldv_epi16`] + * [x] [`_mm256_maskz_shldv_epi16`] + * [x] [`_mm256_shldv_epi16`] + * [x] [`_mm512_mask_shldv_epi16`] + * [x] [`_mm512_maskz_shldv_epi16`] + * [x] [`_mm512_shldv_epi16`] + * [x] [`_mm_mask_shldv_epi32`] + * [x] [`_mm_maskz_shldv_epi32`] + * [x] [`_mm_shldv_epi32`] + * [x] [`_mm256_mask_shldv_epi32`] + * [x] [`_mm256_maskz_shldv_epi32`] + * [x] [`_mm256_shldv_epi32`] + * [x] [`_mm512_mask_shldv_epi32`] + * [x] [`_mm512_maskz_shldv_epi32`] + * [x] [`_mm512_shldv_epi32`] + * [x] [`_mm_mask_shldv_epi64`] + * [x] [`_mm_maskz_shldv_epi64`] + * [x] [`_mm_shldv_epi64`] + * [x] [`_mm256_mask_shldv_epi64`] + * [x] [`_mm256_maskz_shldv_epi64`] + * [x] [`_mm256_shldv_epi64`] + * [x] [`_mm512_mask_shldv_epi64`] + * [x] [`_mm512_maskz_shldv_epi64`] + * [x] [`_mm512_shldv_epi64`] + * [x] [`_mm_mask_shrdi_epi16`] + * [x] [`_mm_maskz_shrdi_epi16`] + * [x] [`_mm_shrdi_epi16`] + * [x] [`_mm256_mask_shrdi_epi16`] + * [x] [`_mm256_maskz_shrdi_epi16`] + * [x] [`_mm256_shrdi_epi16`] + * [x] [`_mm512_mask_shrdi_epi16`] + * [x] [`_mm512_maskz_shrdi_epi16`] + * [x] [`_mm512_shrdi_epi16`] + * [x] [`_mm_mask_shrdi_epi32`] + * [x] [`_mm_maskz_shrdi_epi32`] + * [x] [`_mm_shrdi_epi32`] + * [x] [`_mm256_mask_shrdi_epi32`] + * [x] [`_mm256_maskz_shrdi_epi32`] + * [x] [`_mm256_shrdi_epi32`] + * [x] [`_mm512_mask_shrdi_epi32`] + * [x] [`_mm512_maskz_shrdi_epi32`] + * [x] [`_mm512_shrdi_epi32`] + * [x] [`_mm_mask_shrdi_epi64`] + * [x] [`_mm_maskz_shrdi_epi64`] + * [x] [`_mm_shrdi_epi64`] + * [x] [`_mm256_mask_shrdi_epi64`] + * [x] [`_mm256_maskz_shrdi_epi64`] + * [x] [`_mm256_shrdi_epi64`] + * [x] [`_mm512_mask_shrdi_epi64`] + * [x] [`_mm512_maskz_shrdi_epi64`] + * [x] [`_mm512_shrdi_epi64`] + * [x] [`_mm_mask_shrdv_epi16`] + * [x] [`_mm_maskz_shrdv_epi16`] + * [x] [`_mm_shrdv_epi16`] + * [x] [`_mm256_mask_shrdv_epi16`] + * [x] [`_mm256_maskz_shrdv_epi16`] + * [x] [`_mm256_shrdv_epi16`] + * [x] [`_mm512_mask_shrdv_epi16`] + * [x] [`_mm512_maskz_shrdv_epi16`] + * [x] [`_mm512_shrdv_epi16`] + * [x] [`_mm_mask_shrdv_epi32`] + * [x] [`_mm_maskz_shrdv_epi32`] + * [x] [`_mm_shrdv_epi32`] + * [x] [`_mm256_mask_shrdv_epi32`] + * [x] [`_mm256_maskz_shrdv_epi32`] + * [x] [`_mm256_shrdv_epi32`] + * [x] [`_mm512_mask_shrdv_epi32`] + * [x] [`_mm512_maskz_shrdv_epi32`] + * [x] [`_mm512_shrdv_epi32`] + * [x] [`_mm_mask_shrdv_epi64`] + * [x] [`_mm_maskz_shrdv_epi64`] + * [x] [`_mm_shrdv_epi64`] + * [x] [`_mm256_mask_shrdv_epi64`] + * [x] [`_mm256_maskz_shrdv_epi64`] + * [x] [`_mm256_shrdv_epi64`] + * [x] [`_mm512_mask_shrdv_epi64`] + * [x] [`_mm512_maskz_shrdv_epi64`] + * [x] [`_mm512_shrdv_epi64`] +

diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 2c744c2ffb..a8f1875781 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -1,13 +1,13 @@ -#![doc(include = "core_arch_docs.md")] +#![doc = include_str!("core_arch_docs.md")] #![allow(improper_ctypes_definitions)] #![allow(dead_code)] #![allow(unused_features)] -#![allow(incomplete_features)] +#![deny(rust_2018_idioms)] #![feature( + asm, const_fn, const_fn_union, const_fn_transmute, - const_generics, custom_inner_attributes, link_llvm_intrinsics, platform_intrinsics, @@ -37,7 +37,8 @@ f16c_target_feature, external_doc, allow_internal_unstable, - decl_macro + decl_macro, + extended_key_value_attributes )] #![cfg_attr(test, feature(test, abi_vectorcall))] #![cfg_attr(all(test, target_arch = "wasm32"), feature(wasm_simd))] @@ -69,9 +70,6 @@ extern crate std; #[cfg(test)] #[macro_use] extern crate std_detect; -#[cfg(test)] -extern crate stdarch_test; - #[path = "mod.rs"] mod core_arch; diff --git a/library/stdarch/crates/core_arch/src/mod.rs b/library/stdarch/crates/core_arch/src/mod.rs index e9e9fcff5b..a5b0e30cad 100644 --- a/library/stdarch/crates/core_arch/src/mod.rs +++ b/library/stdarch/crates/core_arch/src/mod.rs @@ -9,7 +9,7 @@ mod acle; mod simd; -#[doc(include = "core_arch_docs.md")] +#[doc = include_str!("core_arch_docs.md")] #[stable(feature = "simd_arch", since = "1.27.0")] pub mod arch { /// Platform-specific intrinsics for the `x86` platform. diff --git a/library/stdarch/crates/core_arch/src/simd.rs b/library/stdarch/crates/core_arch/src/simd.rs index 6108bc40de..a2e393ab32 100644 --- a/library/stdarch/crates/core_arch/src/simd.rs +++ b/library/stdarch/crates/core_arch/src/simd.rs @@ -245,6 +245,7 @@ simd_ty!(i64x2[i64]: i64, i64 | x0, x1); simd_ty!(f32x4[f32]: f32, f32, f32, f32 | x0, x1, x2, x3); simd_ty!(f64x2[f64]: f64, f64 | x0, x1); +simd_ty!(f64x4[f64]: f64, f64, f64, f64 | x0, x1, x2, x3); simd_m_ty!( m8x16[i8]: i8, diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 5fe898922f..358ce15081 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -2587,14 +2587,13 @@ pub unsafe fn _mm256_sad_epu8(a: __m256i, b: __m256i) -> __m256i { /// Shuffles bytes from `a` according to the content of `b`. /// -/// The last 4 bits of each byte of `b` are used as addresses into the 32 bytes -/// of `a`. +/// For each of the 128-bit low and high halves of the vectors, the last +/// 4 bits of each byte of `b` are used as addresses into the respective +/// low or high 16 bytes of `a`. That is, the halves are shuffled separately. /// /// In addition, if the highest significant bit of a byte of `b` is set, the /// respective destination byte is set to 0. /// -/// The low and high halves of the vectors are shuffled separately. -/// /// Picturing `a` and `b` as `[u8; 32]`, `_mm256_shuffle_epi8` is logically /// equivalent to: /// diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs b/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs new file mode 100644 index 0000000000..e9977e0188 --- /dev/null +++ b/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs @@ -0,0 +1,1573 @@ +//! [AVX512BF16 intrinsics]. +//! +//! [AVX512BF16 intrinsics]: https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769&avx512techs=AVX512_BF16 + +use crate::{ + core_arch::{simd::*, simd_llvm::*, x86::*}, + mem::transmute, +}; + +#[cfg(test)] +use stdarch_test::assert_instr; + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.x86.avx512bf16.cvtne2ps2bf16.128"] + fn cvtne2ps2bf16(a: f32x4, b: f32x4) -> i16x8; + #[link_name = "llvm.x86.avx512bf16.cvtne2ps2bf16.256"] + fn cvtne2ps2bf16_256(a: f32x8, b: f32x8) -> i16x16; + #[link_name = "llvm.x86.avx512bf16.cvtne2ps2bf16.512"] + fn cvtne2ps2bf16_512(a: f32x16, b: f32x16) -> i16x32; + #[link_name = "llvm.x86.avx512bf16.cvtneps2bf16.256"] + fn cvtneps2bf16_256(a: f32x8) -> i16x8; + #[link_name = "llvm.x86.avx512bf16.cvtneps2bf16.512"] + fn cvtneps2bf16_512(a: f32x16) -> i16x16; + #[link_name = "llvm.x86.avx512bf16.dpbf16ps.128"] + fn dpbf16ps(a: f32x4, b: i32x4, c: i32x4) -> f32x4; + #[link_name = "llvm.x86.avx512bf16.dpbf16ps.256"] + fn dpbf16ps_256(a: f32x8, b: i32x8, c: i32x8) -> f32x8; + #[link_name = "llvm.x86.avx512bf16.dpbf16ps.512"] + fn dpbf16ps_512(a: f32x16, b: i32x16, c: i32x16) -> f32x16; +} + +/// Convert packed single-precision (32-bit) floating-point elements in two 128-bit vectors +/// a and b to packed BF16 (16-bit) floating-point elements, and store the results in a +/// 128-bit wide vector. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651&avx512techs=AVX512_BF16&text=_mm_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm_cvtne2ps_pbh(a: __m128, b: __m128) -> __m128bh { + transmute(cvtne2ps2bf16(a.as_f32x4(), b.as_f32x4())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two vectors +/// a and b to packed BF16 (16-bit) floating-point elements, and store the results +/// in single vector dst using writemask k (elements are copied from src when the +/// corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651&avx512techs=AVX512_BF16&text=_mm_mask_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm_mask_cvtne2ps_pbh(src: __m128bh, k: __mmask8, a: __m128, b: __m128) -> __m128bh { + let cvt = _mm_cvtne2ps_pbh(a, b).as_u16x8(); + transmute(simd_select_bitmask(k, cvt, src.as_u16x8())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two vectors +/// a and b to packed BF16 (16-bit) floating-point elements, and store the results +/// in single vector dst using zeromask k (elements are zeroed out when the corresponding +/// mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651&avx512techs=AVX512_BF16&text=_mm_maskz_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm_maskz_cvtne2ps_pbh(k: __mmask8, a: __m128, b: __m128) -> __m128bh { + let cvt = _mm_cvtne2ps_pbh(a, b).as_u16x8(); + let zero = _mm_setzero_si128().as_u16x8(); + transmute(simd_select_bitmask(k, cvt, zero)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two 256-bit vectors +/// a and b to packed BF16 (16-bit) floating-point elements, and store the results in a +/// 256-bit wide vector. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654&avx512techs=AVX512_BF16&text=_mm256_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm256_cvtne2ps_pbh(a: __m256, b: __m256) -> __m256bh { + transmute(cvtne2ps2bf16_256(a.as_f32x8(), b.as_f32x8())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two vectors a and b +/// to packed BF16 (16-bit) floating-point elements and and store the results in single vector +/// dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654&avx512techs=AVX512_BF16&text=_mm256_mask_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm256_mask_cvtne2ps_pbh( + src: __m256bh, + k: __mmask16, + a: __m256, + b: __m256, +) -> __m256bh { + let cvt = _mm256_cvtne2ps_pbh(a, b).as_u16x16(); + transmute(simd_select_bitmask(k, cvt, src.as_u16x16())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two vectors a and b +/// to packed BF16 (16-bit) floating-point elements, and store the results in single vector +/// dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654&avx512techs=AVX512_BF16&text=_mm256_maskz_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm256_maskz_cvtne2ps_pbh(k: __mmask16, a: __m256, b: __m256) -> __m256bh { + let cvt = _mm256_cvtne2ps_pbh(a, b).as_u16x16(); + let zero = _mm256_setzero_si256().as_u16x16(); + transmute(simd_select_bitmask(k, cvt, zero)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two 512-bit vectors +/// a and b to packed BF16 (16-bit) floating-point elements, and store the results in a +/// 512-bit wide vector. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657&avx512techs=AVX512_BF16&text=_mm512_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm512_cvtne2ps_pbh(a: __m512, b: __m512) -> __m512bh { + transmute(cvtne2ps2bf16_512(a.as_f32x16(), b.as_f32x16())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two vectors +/// a and b to packed BF16 (16-bit) floating-point elements, and store the results +/// in single vector dst using writemask k (elements are copied from src when the +/// corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657&avx512techs=AVX512_BF16&text=_mm512_mask_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm512_mask_cvtne2ps_pbh( + src: __m512bh, + k: __mmask32, + a: __m512, + b: __m512, +) -> __m512bh { + let cvt = _mm512_cvtne2ps_pbh(a, b).as_u16x32(); + transmute(simd_select_bitmask(k, cvt, src.as_u16x32())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in two vectors +/// a and b to packed BF16 (16-bit) floating-point elements, and store the results +/// in single vector dst using zeromask k (elements are zeroed out when the corresponding +/// mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657&avx512techs=AVX512_BF16&text=_mm512_maskz_cvtne2ps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vcvtne2ps2bf16"))] +pub unsafe fn _mm512_maskz_cvtne2ps_pbh(k: __mmask32, a: __m512, b: __m512) -> __m512bh { + let cvt = _mm512_cvtne2ps_pbh(a, b).as_u16x32(); + let zero = _mm512_setzero_si512().as_u16x32(); + transmute(simd_select_bitmask(k, cvt, zero)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed BF16 (16-bit) +/// floating-point elements, and store the results in dst. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm256_cvtneps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtneps2bf16"))] +pub unsafe fn _mm256_cvtneps_pbh(a: __m256) -> __m128bh { + transmute(cvtneps2bf16_256(a.as_f32x8())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed BF16 (16-bit) +/// floating-point elements, and store the results in dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm256_mask_cvtneps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtneps2bf16"))] +pub unsafe fn _mm256_mask_cvtneps_pbh(src: __m128bh, k: __mmask8, a: __m256) -> __m128bh { + let cvt = _mm256_cvtneps_pbh(a).as_u16x8(); + transmute(simd_select_bitmask(k, cvt, src.as_u16x8())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed BF16 (16-bit) +/// floating-point elements, and store the results in dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm256_maskz_cvtneps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vcvtneps2bf16"))] +pub unsafe fn _mm256_maskz_cvtneps_pbh(k: __mmask8, a: __m256) -> __m128bh { + let cvt = _mm256_cvtneps_pbh(a).as_u16x8(); + let zero = _mm_setzero_si128().as_u16x8(); + transmute(simd_select_bitmask(k, cvt, zero)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed BF16 (16-bit) +/// floating-point elements, and store the results in dst. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm512_cvtneps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vcvtneps2bf16"))] +pub unsafe fn _mm512_cvtneps_pbh(a: __m512) -> __m256bh { + transmute(cvtneps2bf16_512(a.as_f32x16())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed BF16 (16-bit) +/// floating-point elements, and store the results in dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm512_mask_cvtneps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vcvtneps2bf16"))] +pub unsafe fn _mm512_mask_cvtneps_pbh(src: __m256bh, k: __mmask16, a: __m512) -> __m256bh { + let cvt = _mm512_cvtneps_pbh(a).as_u16x16(); + transmute(simd_select_bitmask(k, cvt, src.as_u16x16())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed BF16 (16-bit) +/// floating-point elements, and store the results in dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm512_maskz_cvtneps_pbh) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vcvtneps2bf16"))] +pub unsafe fn _mm512_maskz_cvtneps_pbh(k: __mmask16, a: __m512) -> __m256bh { + let cvt = _mm512_cvtneps_pbh(a).as_u16x16(); + let zero = _mm256_setzero_si256().as_u16x16(); + transmute(simd_select_bitmask(k, cvt, zero)) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm_dpbf16_ps(src: __m128, a: __m128bh, b: __m128bh) -> __m128 { + transmute(dpbf16ps(src.as_f32x4(), a.as_i32x4(), b.as_i32x4())) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm_mask_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm_mask_dpbf16_ps(src: __m128, k: __mmask8, a: __m128bh, b: __m128bh) -> __m128 { + let rst = _mm_dpbf16_ps(src, a, b).as_f32x4(); + transmute(simd_select_bitmask(k, rst, src.as_f32x4())) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm_maskz_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm_maskz_dpbf16_ps(k: __mmask8, src: __m128, a: __m128bh, b: __m128bh) -> __m128 { + let rst = _mm_dpbf16_ps(src, a, b).as_f32x4(); + let zero = _mm_set1_ps(0.0_f32).as_f32x4(); + transmute(simd_select_bitmask(k, rst, zero)) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm256_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm256_dpbf16_ps(src: __m256, a: __m256bh, b: __m256bh) -> __m256 { + transmute(dpbf16ps_256(src.as_f32x8(), a.as_i32x8(), b.as_i32x8())) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm256_mask_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm256_mask_dpbf16_ps(src: __m256, k: __mmask8, a: __m256bh, b: __m256bh) -> __m256 { + let rst = _mm256_dpbf16_ps(src, a, b).as_f32x8(); + transmute(simd_select_bitmask(k, rst, src.as_f32x8())) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm256_maskz_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512vl")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm256_maskz_dpbf16_ps(k: __mmask8, src: __m256, a: __m256bh, b: __m256bh) -> __m256 { + let rst = _mm256_dpbf16_ps(src, a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, rst, zero)) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst.Compute dot-product of BF16 (16-bit) +/// floating-point pairs in a and b, accumulating the intermediate single-precision (32-bit) +/// floating-point elements with elements in src, and store the results in dst. +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm512_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm512_dpbf16_ps(src: __m512, a: __m512bh, b: __m512bh) -> __m512 { + transmute(dpbf16ps_512(src.as_f32x16(), a.as_i32x16(), b.as_i32x16())) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm512_mask_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm512_mask_dpbf16_ps(src: __m512, k: __mmask16, a: __m512bh, b: __m512bh) -> __m512 { + let rst = _mm512_dpbf16_ps(src, a, b).as_f32x16(); + transmute(simd_select_bitmask(k, rst, src.as_f32x16())) +} + +/// Compute dot-product of BF16 (16-bit) floating-point pairs in a and b, +/// accumulating the intermediate single-precision (32-bit) floating-point elements +/// with elements in src, and store the results in dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654,1657,1660&avx512techs=AVX512_BF16&text=_mm512_maskz_dpbf16_ps) +#[inline] +#[target_feature(enable = "avx512bf16,avx512f")] +#[cfg_attr(test, assert_instr("vdpbf16ps"))] +pub unsafe fn _mm512_maskz_dpbf16_ps( + k: __mmask16, + src: __m512, + a: __m512bh, + b: __m512bh, +) -> __m512 { + let rst = _mm512_dpbf16_ps(src, a, b).as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); + transmute(simd_select_bitmask(k, rst, zero)) +} + +#[cfg(test)] +mod tests { + use crate::{core_arch::x86::*, mem::transmute}; + use stdarch_test::simd_test; + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm_cvtne2ps_pbh() { + let a_array = [178.125_f32, 10.5_f32, 3.75_f32, 50.25_f32]; + let b_array = [-178.125_f32, -10.5_f32, -3.75_f32, -50.25_f32]; + let a: __m128 = transmute(a_array); + let b: __m128 = transmute(b_array); + let c: __m128bh = _mm_cvtne2ps_pbh(a, b); + let result: [u16; 8] = transmute(c.as_u16x8()); + #[rustfmt::skip] + let expected_result: [u16; 8] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm_mask_cvtne2ps_pbh() { + let a_array = [178.125_f32, 10.5_f32, 3.75_f32, 50.25_f32]; + let b_array = [-178.125_f32, -10.5_f32, -3.75_f32, -50.25_f32]; + #[rustfmt::skip] + let src_array: [u16; 8] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + ]; + let src: __m128bh = transmute(src_array); + let a: __m128 = transmute(a_array); + let b: __m128 = transmute(b_array); + let k: __mmask8 = 0b1111_1111; + let c: __m128bh = _mm_mask_cvtne2ps_pbh(src, k, a, b); + let result: [u16; 8] = transmute(c.as_u16x8()); + #[rustfmt::skip] + let expected_result: [u16; 8] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + ]; + assert_eq!(result, expected_result); + let k = 0b0000_0000; + let c = _mm_mask_cvtne2ps_pbh(src, k, a, b); + let result: [u16; 8] = transmute(c.as_u16x8()); + let expected_result = src_array; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm_maskz_cvtne2ps_pbh() { + let a_array = [178.125_f32, 10.5_f32, 3.75_f32, 50.25_f32]; + let b_array = [-178.125_f32, -10.5_f32, -3.75_f32, -50.25_f32]; + let a: __m128 = transmute(a_array); + let b: __m128 = transmute(b_array); + let k: __mmask8 = 0b1111_1111; + let c: __m128bh = _mm_maskz_cvtne2ps_pbh(k, a, b); + let result: [u16; 8] = transmute(c.as_u16x8()); + #[rustfmt::skip] + let expected_result: [u16; 8] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + ]; + assert_eq!(result, expected_result); + let k = 0b0011_1100; + let c = _mm_maskz_cvtne2ps_pbh(k, a, b); + let result: [u16; 8] = transmute(c.as_u16x8()); + #[rustfmt::skip] + let expected_result: [u16; 8] = [ + 0, + 0, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0, + 0, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_cvtne2ps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let b_array = [ + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + ]; + let a: __m256 = transmute(a_array); + let b: __m256 = transmute(b_array); + let c: __m256bh = _mm256_cvtne2ps_pbh(a, b); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_mask_cvtne2ps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let b_array = [ + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + ]; + let src_array: [u16; 16] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + ]; + let src: __m256bh = transmute(src_array); + let a: __m256 = transmute(a_array); + let b: __m256 = transmute(b_array); + let k: __mmask16 = 0xffff; + let c: __m256bh = _mm256_mask_cvtne2ps_pbh(src, k, a, b); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0; + let c: __m256bh = _mm256_mask_cvtne2ps_pbh(src, k, a, b); + let result: [u16; 16] = transmute(c.as_u16x16()); + let expected_result = src_array; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_maskz_cvtne2ps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let b_array = [ + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + ]; + let a: __m256 = transmute(a_array); + let b: __m256 = transmute(b_array); + let k: __mmask16 = 0xffff; + let c: __m256bh = _mm256_maskz_cvtne2ps_pbh(k, a, b); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0b0110_1100_0011_0110; + let c: __m256bh = _mm256_maskz_cvtne2ps_pbh(k, a, b); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0, + 0, + 0, + 0, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_cvtne2ps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let b_array = [ + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + ]; + let a: __m512 = transmute(a_array); + let b: __m512 = transmute(b_array); + let c: __m512bh = _mm512_cvtne2ps_pbh(a, b); + let result: [u16; 32] = transmute(c.as_u16x32()); + #[rustfmt::skip] + let expected_result: [u16; 32] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_mask_cvtne2ps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let b_array = [ + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + ]; + let src_array: [u16; 32] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + ]; + let src: __m512bh = transmute(src_array); + let a: __m512 = transmute(a_array); + let b: __m512 = transmute(b_array); + let k: __mmask32 = 0xffffffff; + let c: __m512bh = _mm512_mask_cvtne2ps_pbh(src, k, a, b); + let result: [u16; 32] = transmute(c.as_u16x32()); + #[rustfmt::skip] + let expected_result: [u16; 32] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask32 = 0; + let c: __m512bh = _mm512_mask_cvtne2ps_pbh(src, k, a, b); + let result: [u16; 32] = transmute(c.as_u16x32()); + let expected_result = src_array; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_maskz_cvtne2ps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let b_array = [ + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + -178.125_f32, + -10.5_f32, + -3.75_f32, + -50.25_f32, + -16.5_f32, + -255.11_f32, + -1000.158_f32, + -575.575_f32, + ]; + let a: __m512 = transmute(a_array); + let b: __m512 = transmute(b_array); + let k: __mmask32 = 0xffffffff; + let c: __m512bh = _mm512_maskz_cvtne2ps_pbh(k, a, b); + let result: [u16; 32] = transmute(c.as_u16x32()); + #[rustfmt::skip] + let expected_result: [u16; 32] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask32 = 0b1100_1010_1001_0110_1010_0011_0101_0110; + let c: __m512bh = _mm512_maskz_cvtne2ps_pbh(k, a, b); + let result: [u16; 32] = transmute(c.as_u16x32()); + #[rustfmt::skip] + let expected_result: [u16; 32] = [ + 0, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0, + 0b1_10000011_0000100, + 0, + 0b1_10001000_1111010, + 0, + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0, + 0, + 0, + 0b1_10000110_1111111, + 0, + 0b1_10001000_0010000, + 0, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0, + 0b0_10000011_0000100, + 0, + 0, + 0b0_10001000_0010000, + 0, + 0b0_10000010_0101000, + 0, + 0b0_10000100_1001001, + 0, + 0, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_cvtneps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let a: __m256 = transmute(a_array); + let c: __m128bh = _mm256_cvtneps_pbh(a); + let result: [u16; 8] = transmute(c.as_u16x8()); + #[rustfmt::skip] + let expected_result: [u16; 8] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_mask_cvtneps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let src_array: [u16; 8] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + ]; + let src: __m128bh = transmute(src_array); + let a: __m256 = transmute(a_array); + let k: __mmask8 = 0xff; + let b = _mm256_mask_cvtneps_pbh(src, k, a); + let result: [u16; 8] = transmute(b.as_u16x8()); + #[rustfmt::skip] + let expected_result: [u16; 8] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0x0; + let b: __m128bh = _mm256_mask_cvtneps_pbh(src, k, a); + let result: [u16; 8] = transmute(b.as_u16x8()); + let expected_result: [u16; 8] = src_array; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_maskz_cvtneps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let a: __m256 = transmute(a_array); + let k: __mmask8 = 0xff; + let b = _mm256_maskz_cvtneps_pbh(k, a); + let result: [u16; 8] = transmute(b.as_u16x8()); + #[rustfmt::skip] + let expected_result: [u16; 8] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0x6; + let b: __m128bh = _mm256_maskz_cvtneps_pbh(k, a); + let result: [u16; 8] = transmute(b.as_u16x8()); + let expected_result: [u16; 8] = + [0, 0b0_10000010_0101000, 0b0_10000000_1110000, 0, 0, 0, 0, 0]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_cvtneps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let a: __m512 = transmute(a_array); + let c: __m256bh = _mm512_cvtneps_pbh(a); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_mask_cvtneps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let src_array: [u16; 16] = [ + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + 0b1_10000110_0110010, + 0b1_10000010_0101000, + 0b1_10000000_1110000, + 0b1_10000100_1001001, + 0b1_10000011_0000100, + 0b1_10000110_1111111, + 0b1_10001000_1111010, + 0b1_10001000_0010000, + ]; + let src: __m256bh = transmute(src_array); + let a: __m512 = transmute(a_array); + let k: __mmask16 = 0xffff; + let c: __m256bh = _mm512_mask_cvtneps_pbh(src, k, a); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0; + let c: __m256bh = _mm512_mask_cvtneps_pbh(src, k, a); + let result: [u16; 16] = transmute(c.as_u16x16()); + let expected_result = src_array; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_maskz_cvtneps_pbh() { + #[rustfmt::skip] + let a_array = [ + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + 178.125_f32, + 10.5_f32, + 3.75_f32, + 50.25_f32, + 16.5_f32, + 255.11_f32, + 1000.158_f32, + 575.575_f32, + ]; + let a: __m512 = transmute(a_array); + let k: __mmask16 = 0xffff; + let c: __m256bh = _mm512_maskz_cvtneps_pbh(k, a); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + 0b0_10000110_0110010, + 0b0_10000010_0101000, + 0b0_10000000_1110000, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0b0_10001000_0010000, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0x653a; + let c: __m256bh = _mm512_maskz_cvtneps_pbh(k, a); + let result: [u16; 16] = transmute(c.as_u16x16()); + #[rustfmt::skip] + let expected_result: [u16; 16] = [ + 0, + 0b0_10000010_0101000, + 0, + 0b0_10000100_1001001, + 0b0_10000011_0000100, + 0b0_10000110_1111111, + 0, + 0, + 0b0_10000110_0110010, + 0, + 0b0_10000000_1110000, + 0, + 0, + 0b0_10000110_1111111, + 0b0_10001000_1111010, + 0, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm_dpbf16_ps() { + let a_array = [8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32]; + let b_array = [-1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32]; + let a1: __m128 = transmute(a_array); + let b1: __m128 = transmute(b_array); + let src: __m128 = transmute([1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32]); + let a: __m128bh = _mm_cvtne2ps_pbh(a1, a1); + let b: __m128bh = _mm_cvtne2ps_pbh(b1, b1); + let c: __m128 = _mm_dpbf16_ps(src, a, b); + let result: [f32; 4] = transmute(c.as_f32x4()); + let expected_result: [f32; 4] = [-18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm_mask_dpbf16_ps() { + let a_array = [8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32]; + let b_array = [-1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32]; + let a1: __m128 = transmute(a_array); + let b1: __m128 = transmute(b_array); + let k: __mmask8 = 0xf3; + let src: __m128 = transmute([1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32]); + let a: __m128bh = _mm_cvtne2ps_pbh(a1, a1); + let b: __m128bh = _mm_cvtne2ps_pbh(b1, b1); + let c: __m128 = _mm_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 4] = transmute(c.as_f32x4()); + let expected_result: [f32; 4] = [-18.0_f32, -52.0_f32, 3.0_f32, 4.0_f32]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0xff; + let c: __m128 = _mm_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 4] = transmute(c.as_f32x4()); + let expected_result: [f32; 4] = [-18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0; + let c: __m128 = _mm_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 4] = transmute(c.as_f32x4()); + let expected_result: [f32; 4] = [1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm_maskz_dpbf16_ps() { + let a_array = [8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32]; + let b_array = [-1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32]; + let a1: __m128 = transmute(a_array); + let b1: __m128 = transmute(b_array); + let k: __mmask8 = 0xf3; + let src: __m128 = transmute([1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32]); + let a: __m128bh = _mm_cvtne2ps_pbh(a1, a1); + let b: __m128bh = _mm_cvtne2ps_pbh(b1, b1); + let c: __m128 = _mm_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 4] = transmute(c.as_f32x4()); + let expected_result: [f32; 4] = [-18.0_f32, -52.0_f32, 0.0, 0.0]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0xff; + let c: __m128 = _mm_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 4] = transmute(c.as_f32x4()); + let expected_result: [f32; 4] = [-18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0; + let c: __m128 = _mm_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 4] = transmute(c.as_f32x4()); + let expected_result: [f32; 4] = [0.0, 0.0, 0.0, 0.0]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_dpbf16_ps() { + #[rustfmt::skip] + let a_array = [ + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + ]; + let b_array = [ + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + ]; + let a1: __m256 = transmute(a_array); + let b1: __m256 = transmute(b_array); + #[rustfmt::skip] + let src: __m256 = transmute([ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]); + let a: __m256bh = _mm256_cvtne2ps_pbh(a1, a1); + let b: __m256bh = _mm256_cvtne2ps_pbh(b1, b1); + let c: __m256 = _mm256_dpbf16_ps(src, a, b); + let result: [f32; 8] = transmute(c.as_f32x8()); + #[rustfmt::skip] + let expected_result: [f32; 8] = [ + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_mask_dpbf16_ps() { + #[rustfmt::skip] + let a_array = [ + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + ]; + let b_array = [ + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + ]; + let a1: __m256 = transmute(a_array); + let b1: __m256 = transmute(b_array); + let k: __mmask8 = 0x33; + #[rustfmt::skip] + let src: __m256 = transmute([ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]); + let a: __m256bh = _mm256_cvtne2ps_pbh(a1, a1); + let b: __m256bh = _mm256_cvtne2ps_pbh(b1, b1); + let c: __m256 = _mm256_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 8] = transmute(c.as_f32x8()); + #[rustfmt::skip] + let expected_result: [f32; 8] = [ + -18.0_f32, -52.0_f32, 3.0_f32, 4.0_f32, -18.0_f32, -52.0_f32, 3.0_f32, 4.0_f32, + ]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0xff; + let c: __m256 = _mm256_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 8] = transmute(c.as_f32x8()); + #[rustfmt::skip] + let expected_result: [f32; 8] = [ + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + ]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0; + let c: __m256 = _mm256_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 8] = transmute(c.as_f32x8()); + #[rustfmt::skip] + let expected_result: [f32; 8] = [ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512vl")] + unsafe fn test_mm256_maskz_dpbf16_ps() { + #[rustfmt::skip] + let a_array = [ + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + ]; + let b_array = [ + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + ]; + let a1: __m256 = transmute(a_array); + let b1: __m256 = transmute(b_array); + let k: __mmask8 = 0x33; + #[rustfmt::skip] + let src: __m256 = transmute([ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]); + let a: __m256bh = _mm256_cvtne2ps_pbh(a1, a1); + let b: __m256bh = _mm256_cvtne2ps_pbh(b1, b1); + let c: __m256 = _mm256_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 8] = transmute(c.as_f32x8()); + #[rustfmt::skip] + let expected_result: [f32; 8] = [ + -18.0_f32, -52.0_f32, 0.0, 0.0, -18.0_f32, -52.0_f32, 0.0, 0.0, + ]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0xff; + let c: __m256 = _mm256_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 8] = transmute(c.as_f32x8()); + #[rustfmt::skip] + let expected_result: [f32; 8] = [ + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + ]; + assert_eq!(result, expected_result); + let k: __mmask8 = 0; + let c: __m256 = _mm256_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 8] = transmute(c.as_f32x8()); + let expected_result: [f32; 8] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_dpbf16_ps() { + #[rustfmt::skip] + let a_array = [ + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + ]; + let b_array = [ + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + ]; + let a1: __m512 = transmute(a_array); + let b1: __m512 = transmute(b_array); + let src: __m512 = transmute([ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, + 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]); + let a: __m512bh = _mm512_cvtne2ps_pbh(a1, a1); + let b: __m512bh = _mm512_cvtne2ps_pbh(b1, b1); + let c: __m512 = _mm512_dpbf16_ps(src, a, b); + let result: [f32; 16] = transmute(c.as_f32x16()); + #[rustfmt::skip] + let expected_result: [f32; 16] = [ + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_mask_dpbf16_ps() { + #[rustfmt::skip] + let a_array = [ + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + ]; + let b_array = [ + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + ]; + let a1: __m512 = transmute(a_array); + let b1: __m512 = transmute(b_array); + let k: __mmask16 = 0x3333; + #[rustfmt::skip] + let src: __m512 = transmute([ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, + 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]); + let a: __m512bh = _mm512_cvtne2ps_pbh(a1, a1); + let b: __m512bh = _mm512_cvtne2ps_pbh(b1, b1); + let c: __m512 = _mm512_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 16] = transmute(c.as_f32x16()); + #[rustfmt::skip] + let expected_result: [f32; 16] = [ + -18.0_f32, -52.0_f32, 3.0_f32, 4.0_f32, -18.0_f32, -52.0_f32, 3.0_f32, 4.0_f32, + -18.0_f32, -52.0_f32, 3.0_f32, 4.0_f32, -18.0_f32, -52.0_f32, 3.0_f32, 4.0_f32, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0xffff; + let c: __m512 = _mm512_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 16] = transmute(c.as_f32x16()); + #[rustfmt::skip] + let expected_result: [f32; 16] = [ + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0; + let c: __m512 = _mm512_mask_dpbf16_ps(src, k, a, b); + let result: [f32; 16] = transmute(c.as_f32x16()); + #[rustfmt::skip] + let expected_result: [f32; 16] = [ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, + 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]; + assert_eq!(result, expected_result); + } + + #[simd_test(enable = "avx512bf16,avx512f")] + unsafe fn test_mm512_maskz_dpbf16_ps() { + #[rustfmt::skip] + let a_array = [ + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, 8.5_f32, 10.5_f32, 3.75_f32, 50.25_f32, + ]; + let b_array = [ + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, -1.0_f32, + ]; + let a1: __m512 = transmute(a_array); + let b1: __m512 = transmute(b_array); + let k: __mmask16 = 0x3333; + #[rustfmt::skip] + let src: __m512 = transmute([ + 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, + 2.0_f32, 3.0_f32, 4.0_f32, 1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32, + ]); + let a: __m512bh = _mm512_cvtne2ps_pbh(a1, a1); + let b: __m512bh = _mm512_cvtne2ps_pbh(b1, b1); + let c: __m512 = _mm512_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 16] = transmute(c.as_f32x16()); + #[rustfmt::skip] + let expected_result: [f32; 16] = [ + -18.0_f32, -52.0_f32, 0.0, 0.0, -18.0_f32, -52.0_f32, 0.0, 0.0, -18.0_f32, -52.0_f32, + 0.0, 0.0, -18.0_f32, -52.0_f32, 0.0, 0.0, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0xffff; + let c: __m512 = _mm512_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 16] = transmute(c.as_f32x16()); + #[rustfmt::skip] + let expected_result: [f32; 16] = [ + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, -18.0_f32, -52.0_f32, -16.0_f32, -50.0_f32, + ]; + assert_eq!(result, expected_result); + let k: __mmask16 = 0; + let c: __m512 = _mm512_maskz_dpbf16_ps(k, src, a, b); + let result: [f32; 16] = transmute(c.as_f32x16()); + #[rustfmt::skip] + let expected_result: [f32; 16] = [ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + ]; + assert_eq!(result, expected_result); + } +} diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 8530fc7cbe..f4dc00bd87 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -2269,6 +2269,46 @@ pub unsafe fn _mm512_mask_cmplt_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i _mm512_cmplt_epu16_mask(a, b) & k1 } +/// Compare packed unsigned 16-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmplt_epu16_mask&expand=1050) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmplt_epu16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_lt(a.as_u16x16(), b.as_u16x16())) +} + +/// Compare packed unsigned 16-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epu16_mask&expand=1049) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmplt_epu16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmplt_epu16_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epi16_mask&expand=1018) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmplt_epu16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_lt(a.as_u16x8(), b.as_u16x8())) +} + +/// Compare packed unsigned 16-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epi16_mask&expand=1019) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmplt_epu16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmplt_epu16_mask(a, b) & k1 +} + /// Compare packed unsigned 8-bit integers in a and b for less-than, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm512_cmplt_epu8_mask&expand=1068) @@ -2289,898 +2329,2232 @@ pub unsafe fn _mm512_mask_cmplt_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) _mm512_cmplt_epu8_mask(a, b) & k1 } -/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi16_mask&expand=1022) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmplt_epu8_mask&expand=1066) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmplt_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_lt(a.as_i16x32(), b.as_i16x32())) +pub unsafe fn _mm256_cmplt_epu8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_lt(a.as_u8x32(), b.as_u8x32())) } -/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi16_mask&expand=1023) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epu8_mask&expand=1067) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmplt_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmplt_epi16_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmplt_epu8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmplt_epu8_mask(a, b) & k1 } -/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi8_mask&expand=1044) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epu8_mask&expand=1064) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmplt_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_lt(a.as_i8x64(), b.as_i8x64())) +pub unsafe fn _mm_cmplt_epu8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_lt(a.as_u8x16(), b.as_u8x16())) } -/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi8_mask&expand=1045) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epu8_mask&expand=1065) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmplt_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmplt_epi8_mask(a, b) & k1 +pub unsafe fn _mm_mask_cmplt_epu8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmplt_epu8_mask(a, b) & k1 } -/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k. +/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu16_mask&expand=927) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi16_mask&expand=1022) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpgt_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_gt(a.as_u16x32(), b.as_u16x32())) +pub unsafe fn _mm512_cmplt_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_lt(a.as_i16x32(), b.as_i16x32())) } -/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu16_mask&expand=928) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi16_mask&expand=1023) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpgt_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpgt_epu16_mask(a, b) & k1 +pub unsafe fn _mm512_mask_cmplt_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmplt_epi16_mask(a, b) & k1 } -/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k. +/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu8_mask&expand=945) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmplt_epi16_mask&expand=1020) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpgt_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_gt(a.as_u8x64(), b.as_u8x64())) +pub unsafe fn _mm256_cmplt_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_lt(a.as_i16x16(), b.as_i16x16())) } -/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu8_mask&expand=946) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epi16_mask&expand=1021) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpgt_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpgt_epu8_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmplt_epi16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmplt_epi16_mask(a, b) & k1 } -/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k. +/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi16_mask&expand=897) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epi16_mask&expand=1018) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpgt_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_gt(a.as_i16x32(), b.as_i16x32())) +pub unsafe fn _mm_cmplt_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_lt(a.as_i16x8(), b.as_i16x8())) } -/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 16-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi16_mask&expand=898) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epi16_mask&expand=1019) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpgt_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpgt_epi16_mask(a, b) & k1 +pub unsafe fn _mm_mask_cmplt_epi16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmplt_epi16_mask(a, b) & k1 } -/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k. +/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi8_mask&expand=921) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi8_mask&expand=1044) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpgt_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_gt(a.as_i8x64(), b.as_i8x64())) +pub unsafe fn _mm512_cmplt_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_lt(a.as_i8x64(), b.as_i8x64())) } -/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi8_mask&expand=922) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi8_mask&expand=1045) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpgt_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpgt_epi8_mask(a, b) & k1 +pub unsafe fn _mm512_mask_cmplt_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmplt_epi8_mask(a, b) & k1 } -/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu16_mask&expand=989) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmplt_epi8_mask&expand=1042) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmple_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_le(a.as_u16x32(), b.as_u16x32())) +pub unsafe fn _mm256_cmplt_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_lt(a.as_i8x32(), b.as_i8x32())) } -/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu16_mask&expand=990) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epi8_mask&expand=1043) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmple_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmple_epu16_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmplt_epi8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmplt_epi8_mask(a, b) & k1 } -/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu8_mask&expand=1007) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epi8_mask&expand=1040) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmple_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_le(a.as_u8x64(), b.as_u8x64())) +pub unsafe fn _mm_cmplt_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_lt(a.as_i8x16(), b.as_i8x16())) } -/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu8_mask&expand=1008) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epi8_mask&expand=1041) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmple_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmple_epu8_mask(a, b) & k1 +pub unsafe fn _mm_mask_cmplt_epi8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmplt_epi8_mask(a, b) & k1 } -/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi16_mask&expand=965) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu16_mask&expand=927) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmple_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_le(a.as_i16x32(), b.as_i16x32())) +pub unsafe fn _mm512_cmpgt_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_gt(a.as_u16x32(), b.as_u16x32())) } -/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi16_mask&expand=966) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu16_mask&expand=928) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmple_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmple_epi16_mask(a, b) & k1 +pub unsafe fn _mm512_mask_cmpgt_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpgt_epu16_mask(a, b) & k1 } -/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi8_mask&expand=983) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epu16_mask&expand=925) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmple_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_le(a.as_i8x64(), b.as_i8x64())) +pub unsafe fn _mm256_cmpgt_epu16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_gt(a.as_u16x16(), b.as_u16x16())) } -/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi8_mask&expand=984) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epu16_mask&expand=926) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmple_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmple_epi8_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmpgt_epu16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpgt_epu16_mask(a, b) & k1 } -/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu16_mask&expand=867) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epu16_mask&expand=923) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpge_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_ge(a.as_u16x32(), b.as_u16x32())) +pub unsafe fn _mm_cmpgt_epu16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_gt(a.as_u16x8(), b.as_u16x8())) } -/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu16_mask&expand=868) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epu16_mask&expand=924) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpge_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpge_epu16_mask(a, b) & k1 +pub unsafe fn _mm_mask_cmpgt_epu16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpgt_epu16_mask(a, b) & k1 } -/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu8_mask&expand=885) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu8_mask&expand=945) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpge_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_ge(a.as_u8x64(), b.as_u8x64())) +pub unsafe fn _mm512_cmpgt_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_gt(a.as_u8x64(), b.as_u8x64())) } -/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu8_mask&expand=886) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu8_mask&expand=946) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpge_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpge_epu8_mask(a, b) & k1 +pub unsafe fn _mm512_mask_cmpgt_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpgt_epu8_mask(a, b) & k1 } -/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi16_mask&expand=843) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epu8_mask&expand=943) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpge_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_ge(a.as_i16x32(), b.as_i16x32())) +pub unsafe fn _mm256_cmpgt_epu8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_gt(a.as_u8x32(), b.as_u8x32())) } -/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi16_mask&expand=844) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epu8_mask&expand=944) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpge_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpge_epi16_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmpgt_epu8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpgt_epu8_mask(a, b) & k1 } -/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi8_mask&expand=861) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epu8_mask&expand=941) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpge_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_ge(a.as_i8x64(), b.as_i8x64())) +pub unsafe fn _mm_cmpgt_epu8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_gt(a.as_u8x16(), b.as_u8x16())) } -/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi8_mask&expand=862) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epu8_mask&expand=942) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpge_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpge_epi8_mask(a, b) & k1 +pub unsafe fn _mm_mask_cmpgt_epu8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpgt_epu8_mask(a, b) & k1 } -/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k. +/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu16_mask&expand=801) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi16_mask&expand=897) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpeq_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_eq(a.as_u16x32(), b.as_u16x32())) +pub unsafe fn _mm512_cmpgt_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_gt(a.as_i16x32(), b.as_i16x32())) } -/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu16_mask&expand=802) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi16_mask&expand=898) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpeq_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpeq_epu16_mask(a, b) & k1 +pub unsafe fn _mm512_mask_cmpgt_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpgt_epi16_mask(a, b) & k1 } -/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k. +/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu8_mask&expand=819) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epi16_mask&expand=895) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpeq_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_eq(a.as_u8x64(), b.as_u8x64())) +pub unsafe fn _mm256_cmpgt_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_gt(a.as_i16x16(), b.as_i16x16())) } -/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu8_mask&expand=820) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epi16_mask&expand=896) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpeq_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpeq_epu8_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmpgt_epi16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpgt_epi16_mask(a, b) & k1 } -/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k. +/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi16_mask&expand=771) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epi16_mask&expand=893) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpeq_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_eq(a.as_i16x32(), b.as_i16x32())) +pub unsafe fn _mm_cmpgt_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_gt(a.as_i16x8(), b.as_i16x8())) } -/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 16-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi16_mask&expand=772) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epi16_mask&expand=894) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpeq_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpeq_epi16_mask(a, b) & k1 +pub unsafe fn _mm_mask_cmpgt_epi16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpgt_epi16_mask(a, b) & k1 } -/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k. +/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi8_mask&expand=795) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi8_mask&expand=921) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpeq_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_eq(a.as_i8x64(), b.as_i8x64())) +pub unsafe fn _mm512_cmpgt_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_gt(a.as_i8x64(), b.as_i8x64())) } -/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi8_mask&expand=796) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi8_mask&expand=922) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpeq_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpeq_epi8_mask(a, b) & k1 +pub unsafe fn _mm512_mask_cmpgt_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpgt_epi8_mask(a, b) & k1 } -/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu16_mask&expand=1106) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epi8_mask&expand=919) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpneq_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_ne(a.as_u16x32(), b.as_u16x32())) +pub unsafe fn _mm256_cmpgt_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_gt(a.as_i8x32(), b.as_i8x32())) } -/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu16_mask&expand=1107) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epi8_mask&expand=920) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpneq_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpneq_epu16_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmpgt_epi8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpgt_epi8_mask(a, b) & k1 } -/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu8_mask&expand=1124) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epi8_mask&expand=917) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpneq_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_ne(a.as_u8x64(), b.as_u8x64())) +pub unsafe fn _mm_cmpgt_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_gt(a.as_i8x16(), b.as_i8x16())) } -/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu8_mask&expand=1125) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epi8_mask&expand=918) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpneq_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpneq_epu8_mask(a, b) & k1 +pub unsafe fn _mm_mask_cmpgt_epi8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpgt_epi8_mask(a, b) & k1 } -/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi16_mask&expand=1082) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu16_mask&expand=989) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpneq_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { - simd_bitmask::(simd_ne(a.as_i16x32(), b.as_i16x32())) +pub unsafe fn _mm512_cmple_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_le(a.as_u16x32(), b.as_u16x32())) } -/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi16_mask&expand=1083) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu16_mask&expand=990) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpneq_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { - _mm512_cmpneq_epi16_mask(a, b) & k1 +pub unsafe fn _mm512_mask_cmple_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmple_epu16_mask(a, b) & k1 } -/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi8_mask&expand=1100) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epu16_mask&expand=987) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmpneq_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { - simd_bitmask::(simd_ne(a.as_i8x64(), b.as_i8x64())) +pub unsafe fn _mm256_cmple_epu16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_le(a.as_u16x16(), b.as_u16x16())) } -/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi8_mask&expand=1101) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epu16_mask&expand=988) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmpneq_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { - _mm512_cmpneq_epi8_mask(a, b) & k1 +pub unsafe fn _mm256_mask_cmple_epu16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmple_epu16_mask(a, b) & k1 } -/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu16_mask&expand=715) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epu16_mask&expand=985) #[inline] -#[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(2)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_cmp_epu16_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask32 { - let a = a.as_u16x32(); - let b = b.as_u16x32(); - macro_rules! call { - ($imm3:expr) => { - vpcmpuw(a, b, $imm3, 0b11111111_11111111_11111111_11111111) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmple_epu16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_le(a.as_u16x8(), b.as_u16x8())) } -/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epu16_mask&expand=716) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epu16_mask&expand=986) #[inline] -#[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(3)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_mask_cmp_epu16_mask( - k1: __mmask32, - a: __m512i, - b: __m512i, - imm8: i32, -) -> __mmask32 { - let a = a.as_u16x32(); - let b = b.as_u16x32(); - macro_rules! call { - ($imm3:expr) => { - vpcmpuw(a, b, $imm3, k1) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmple_epu16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmple_epu16_mask(a, b) & k1 } -/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu8_mask&expand=733) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu8_mask&expand=1007) #[inline] #[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(2)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_cmp_epu8_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask64 { - let a = a.as_u8x64(); - let b = b.as_u8x64(); - macro_rules! call { - ($imm3:expr) => { - vpcmpub( - a, - b, - $imm3, - 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, - ) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmple_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_le(a.as_u8x64(), b.as_u8x64())) } -/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epu8_mask&expand=734) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu8_mask&expand=1008) #[inline] #[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(3)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_mask_cmp_epu8_mask( - k1: __mmask64, - a: __m512i, - b: __m512i, - imm8: i32, -) -> __mmask64 { - let a = a.as_u8x64(); - let b = b.as_u8x64(); - macro_rules! call { - ($imm3:expr) => { - vpcmpub(a, b, $imm3, k1) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmple_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmple_epu8_mask(a, b) & k1 } -/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi16_mask&expand=691) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epu8_mask&expand=1005) #[inline] -#[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(2)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_cmp_epi16_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask32 { - let a = a.as_i16x32(); - let b = b.as_i16x32(); - macro_rules! call { - ($imm3:expr) => { - vpcmpw(a, b, $imm3, 0b11111111_11111111_11111111_11111111) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmple_epu8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_le(a.as_u8x32(), b.as_u8x32())) } -/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epi16_mask&expand=692) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epu8_mask&expand=1006) #[inline] -#[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(3)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_mask_cmp_epi16_mask( - k1: __mmask32, - a: __m512i, - b: __m512i, - imm8: i32, -) -> __mmask32 { - let a = a.as_i16x32(); - let b = b.as_i16x32(); - macro_rules! call { - ($imm3:expr) => { - vpcmpw(a, b, $imm3, k1) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmple_epu8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmple_epu8_mask(a, b) & k1 } -/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi8_mask&expand=709) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epu8_mask&expand=1003) #[inline] -#[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(2)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_cmp_epi8_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask64 { - let a = a.as_i8x64(); - let b = b.as_i8x64(); - macro_rules! call { - ($imm3:expr) => { - vpcmpb( - a, - b, - $imm3, - 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, - ) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmple_epu8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_le(a.as_u8x16(), b.as_u8x16())) } -/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epi8_mask&expand=710) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epu8_mask&expand=1004) #[inline] -#[target_feature(enable = "avx512bw")] -#[rustc_args_required_const(3)] -#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] -pub unsafe fn _mm512_mask_cmp_epi8_mask( - k1: __mmask64, - a: __m512i, - b: __m512i, - imm8: i32, -) -> __mmask64 { - let a = a.as_i8x64(); - let b = b.as_i8x64(); - macro_rules! call { - ($imm3:expr) => { - vpcmpb(a, b, $imm3, k1) - }; - } - let r = constify_imm3!(imm8, call); - transmute(r) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmple_epu8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmple_epu8_mask(a, b) & k1 } -/// Load 512-bits (composed of 32 packed 16-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_epi16&expand=3368) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi16_mask&expand=965) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu16 -pub unsafe fn _mm512_loadu_epi16(mem_addr: *const i16) -> __m512i { - ptr::read_unaligned(mem_addr as *const __m512i) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmple_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_le(a.as_i16x32(), b.as_i16x32())) } -/// Load 512-bits (composed of 64 packed 8-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_epi8&expand=3395) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi16_mask&expand=966) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 -pub unsafe fn _mm512_loadu_epi8(mem_addr: *const i8) -> __m512i { - ptr::read_unaligned(mem_addr as *const __m512i) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmple_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmple_epi16_mask(a, b) & k1 } -/// Store 512-bits (composed of 32 packed 16-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_epi16&expand=5622) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epi16_mask&expand=963) #[inline] -#[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 -pub unsafe fn _mm512_storeu_epi16(mem_addr: *mut i16, a: __m512i) { - ptr::write_unaligned(mem_addr as *mut __m512i, a); +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmple_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_le(a.as_i16x16(), b.as_i16x16())) } -/// Store 512-bits (composed of 64 packed 8-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_epi8&expand=5640) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epi16_mask&expand=964) #[inline] -#[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 -pub unsafe fn _mm512_storeu_epi8(mem_addr: *mut i8, a: __m512i) { - ptr::write_unaligned(mem_addr as *mut __m512i, a); +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmple_epi16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmple_epi16_mask(a, b) & k1 } -/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst. +/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_madd_epi16&expand=3511) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epi16_mask&expand=961) #[inline] -#[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpmaddwd))] -pub unsafe fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { - transmute(vpmaddwd(a.as_i16x32(), b.as_i16x32())) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmple_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_le(a.as_i16x8(), b.as_i16x8())) } -/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed signed 16-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_madd_epi16&expand=3512) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epi16_mask&expand=962) #[inline] -#[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpmaddwd))] -pub unsafe fn _mm512_mask_madd_epi16( - src: __m512i, - k: __mmask16, - a: __m512i, - b: __m512i, -) -> __m512i { - let madd = _mm512_madd_epi16(a, b).as_i32x16(); - transmute(simd_select_bitmask(k, madd, src.as_i32x16())) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmple_epi16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmple_epi16_mask(a, b) & k1 } -/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_madd_epi16&expand=3513) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi8_mask&expand=983) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpmaddwd))] -pub unsafe fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { - let madd = _mm512_madd_epi16(a, b).as_i32x16(); - let zero = _mm512_setzero_si512().as_i32x16(); - transmute(simd_select_bitmask(k, madd, zero)) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmple_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_le(a.as_i8x64(), b.as_i8x64())) } -/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_madd_epi16&expand=3509) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi8_mask&expand=984) #[inline] -#[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddwd))] -pub unsafe fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { - let madd = _mm256_madd_epi16(a, b).as_i32x8(); - transmute(simd_select_bitmask(k, madd, src.as_i32x8())) +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmple_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmple_epi8_mask(a, b) & k1 } -/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_madd_epi16&expand=3510) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epi8_mask&expand=981) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddwd))] -pub unsafe fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { - let madd = _mm256_madd_epi16(a, b).as_i32x8(); - let zero = _mm256_setzero_si256().as_i32x8(); - transmute(simd_select_bitmask(k, madd, zero)) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmple_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_le(a.as_i8x32(), b.as_i8x32())) } -/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_madd_epi16&expand=3506) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epi8_mask&expand=982) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddwd))] -pub unsafe fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { - let madd = _mm_madd_epi16(a, b).as_i32x4(); - transmute(simd_select_bitmask(k, madd, src.as_i32x4())) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmple_epi8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmple_epi8_mask(a, b) & k1 } -/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_madd_epi16&expand=3507) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epi8_mask&expand=979) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddwd))] -pub unsafe fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { - let madd = _mm_madd_epi16(a, b).as_i32x4(); - let zero = _mm_setzero_si128().as_i32x4(); - transmute(simd_select_bitmask(k, madd, zero)) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmple_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_le(a.as_i8x16(), b.as_i8x16())) } -/// Vertically multiply each unsigned 8-bit integer from a with the corresponding signed 8-bit integer from b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst. +/// Compare packed signed 8-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maddubs_epi16&expand=3539) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epi8_mask&expand=980) #[inline] -#[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpmaddubsw))] -pub unsafe fn _mm512_maddubs_epi16(a: __m512i, b: __m512i) -> __m512i { - transmute(vpmaddubsw(a.as_i8x64(), b.as_i8x64())) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmple_epi8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmple_epi8_mask(a, b) & k1 } -/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_maddubs_epi16&expand=3540) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu16_mask&expand=867) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpmaddubsw))] -pub unsafe fn _mm512_mask_maddubs_epi16( - src: __m512i, - k: __mmask32, - a: __m512i, - b: __m512i, -) -> __m512i { - let madd = _mm512_maddubs_epi16(a, b).as_i16x32(); - transmute(simd_select_bitmask(k, madd, src.as_i16x32())) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpge_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_ge(a.as_u16x32(), b.as_u16x32())) } -/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_maddubs_epi16&expand=3541) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu16_mask&expand=868) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpmaddubsw))] -pub unsafe fn _mm512_maskz_maddubs_epi16(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { - let madd = _mm512_maddubs_epi16(a, b).as_i16x32(); - let zero = _mm512_setzero_si512().as_i16x32(); - transmute(simd_select_bitmask(k, madd, zero)) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpge_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpge_epu16_mask(a, b) & k1 } -/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_maddubs_epi16&expand=3537) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epu16_mask&expand=865) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddubsw))] -pub unsafe fn _mm256_mask_maddubs_epi16( - src: __m256i, - k: __mmask16, - a: __m256i, - b: __m256i, -) -> __m256i { - let madd = _mm256_maddubs_epi16(a, b).as_i16x16(); - transmute(simd_select_bitmask(k, madd, src.as_i16x16())) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpge_epu16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_ge(a.as_u16x16(), b.as_u16x16())) } -/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_maddubs_epi16&expand=3538) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epu16_mask&expand=866) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddubsw))] -pub unsafe fn _mm256_maskz_maddubs_epi16(k: __mmask16, a: __m256i, b: __m256i) -> __m256i { - let madd = _mm256_maddubs_epi16(a, b).as_i16x16(); - let zero = _mm256_setzero_si256().as_i16x16(); - transmute(simd_select_bitmask(k, madd, zero)) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpge_epu16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpge_epu16_mask(a, b) & k1 } -/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_maddubs_epi16&expand=3534) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epu16_mask&expand=863) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddubsw))] -pub unsafe fn _mm_mask_maddubs_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { - let madd = _mm_maddubs_epi16(a, b).as_i16x8(); - transmute(simd_select_bitmask(k, madd, src.as_i16x8())) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpge_epu16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ge(a.as_u16x8(), b.as_u16x8())) } -/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_maddubs_epi16&expand=3535) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epu16_mask&expand=864) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpmaddubsw))] -pub unsafe fn _mm_maskz_maddubs_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { - let madd = _mm_maddubs_epi16(a, b).as_i16x8(); - let zero = _mm_setzero_si128().as_i16x8(); - transmute(simd_select_bitmask(k, madd, zero)) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpge_epu16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpge_epu16_mask(a, b) & k1 } -/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst. +/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_packs_epi32&expand=4091) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu8_mask&expand=885) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpackssdw))] -pub unsafe fn _mm512_packs_epi32(a: __m512i, b: __m512i) -> __m512i { - transmute(vpackssdw(a.as_i32x16(), b.as_i32x16())) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpge_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_ge(a.as_u8x64(), b.as_u8x64())) } -/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_packs_epi32&expand=4089) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu8_mask&expand=886) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpackssdw))] -pub unsafe fn _mm512_mask_packs_epi32( - src: __m512i, - k: __mmask32, - a: __m512i, - b: __m512i, -) -> __m512i { - let pack = _mm512_packs_epi32(a, b).as_i16x32(); - transmute(simd_select_bitmask(k, pack, src.as_i16x32())) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpge_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpge_epu8_mask(a, b) & k1 } -/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_packs_epi32&expand=4090) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epu8_mask&expand=883) #[inline] -#[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpackssdw))] -pub unsafe fn _mm512_maskz_packs_epi32(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { - let pack = _mm512_packs_epi32(a, b).as_i16x32(); - let zero = _mm512_setzero_si512().as_i16x32(); - transmute(simd_select_bitmask(k, pack, zero)) +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpge_epu8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_ge(a.as_u8x32(), b.as_u8x32())) } -/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_packs_epi32&expand=4086) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epu8_mask&expand=884) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(vpackssdw))] -pub unsafe fn _mm256_mask_packs_epi32( - src: __m256i, - k: __mmask16, - a: __m256i, - b: __m256i, -) -> __m256i { - let pack = _mm256_packs_epi32(a, b).as_i16x16(); - transmute(simd_select_bitmask(k, pack, src.as_i16x16())) +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpge_epu8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpge_epu8_mask(a, b) & k1 } -/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_packs_epi32&expand=4087) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epu8_mask&expand=881) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpge_epu8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_ge(a.as_u8x16(), b.as_u8x16())) +} + +/// Compare packed unsigned 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epu8_mask&expand=882) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpge_epu8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpge_epu8_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi16_mask&expand=843) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpge_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_ge(a.as_i16x32(), b.as_i16x32())) +} + +/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi16_mask&expand=844) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpge_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpge_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epi16_mask&expand=841) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpge_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_ge(a.as_i16x16(), b.as_i16x16())) +} + +/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epi16_mask&expand=842) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpge_epi16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpge_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epi16_mask&expand=839) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpge_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ge(a.as_i16x8(), b.as_i16x8())) +} + +/// Compare packed signed 16-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epi16_mask&expand=840) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpge_epi16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpge_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi8_mask&expand=861) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpge_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_ge(a.as_i8x64(), b.as_i8x64())) +} + +/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi8_mask&expand=862) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpge_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpge_epi8_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epi8_mask&expand=859) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpge_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_ge(a.as_i8x32(), b.as_i8x32())) +} + +/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epi8_mask&expand=860) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpge_epi8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpge_epi8_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epi8_mask&expand=857) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpge_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_ge(a.as_i8x16(), b.as_i8x16())) +} + +/// Compare packed signed 8-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epi8_mask&expand=858) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpge_epi8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpge_epi8_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu16_mask&expand=801) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpeq_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_eq(a.as_u16x32(), b.as_u16x32())) +} + +/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu16_mask&expand=802) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpeq_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpeq_epu16_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epu16_mask&expand=799) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpeq_epu16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_eq(a.as_u16x16(), b.as_u16x16())) +} + +/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epu16_mask&expand=800) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpeq_epu16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpeq_epu16_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epu16_mask&expand=797) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpeq_epu16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_eq(a.as_u16x8(), b.as_u16x8())) +} + +/// Compare packed unsigned 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epu16_mask&expand=798) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpeq_epu16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpeq_epu16_mask(a, b) & k1 +} + +/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu8_mask&expand=819) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpeq_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_eq(a.as_u8x64(), b.as_u8x64())) +} + +/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu8_mask&expand=820) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpeq_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpeq_epu8_mask(a, b) & k1 +} + +/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epu8_mask&expand=817) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpeq_epu8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_eq(a.as_u8x32(), b.as_u8x32())) +} + +/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epu8_mask&expand=818) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpeq_epu8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpeq_epu8_mask(a, b) & k1 +} + +/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epu8_mask&expand=815) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpeq_epu8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_eq(a.as_u8x16(), b.as_u8x16())) +} + +/// Compare packed unsigned 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epu8_mask&expand=816) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpeq_epu8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpeq_epu8_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi16_mask&expand=771) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpeq_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_eq(a.as_i16x32(), b.as_i16x32())) +} + +/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi16_mask&expand=772) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpeq_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpeq_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epi16_mask&expand=769) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpeq_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_eq(a.as_i16x16(), b.as_i16x16())) +} + +/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epi16_mask&expand=770) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpeq_epi16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpeq_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epi16_mask&expand=767) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpeq_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_eq(a.as_i16x8(), b.as_i16x8())) +} + +/// Compare packed signed 16-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epi16_mask&expand=768) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpeq_epi16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpeq_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi8_mask&expand=795) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpeq_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_eq(a.as_i8x64(), b.as_i8x64())) +} + +/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi8_mask&expand=796) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpeq_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpeq_epi8_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epi8_mask&expand=793) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpeq_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_eq(a.as_i8x32(), b.as_i8x32())) +} + +/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epi8_mask&expand=794) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpeq_epi8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpeq_epi8_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epi8_mask&expand=791) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpeq_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_eq(a.as_i8x16(), b.as_i8x16())) +} + +/// Compare packed signed 8-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epi8_mask&expand=792) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpeq_epi8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpeq_epi8_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu16_mask&expand=1106) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpneq_epu16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_ne(a.as_u16x32(), b.as_u16x32())) +} + +/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu16_mask&expand=1107) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpneq_epu16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpneq_epu16_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epu16_mask&expand=1104) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpneq_epu16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_ne(a.as_u16x16(), b.as_u16x16())) +} + +/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epu16_mask&expand=1105) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpneq_epu16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpneq_epu16_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epu16_mask&expand=1102) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpneq_epu16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ne(a.as_u16x8(), b.as_u16x8())) +} + +/// Compare packed unsigned 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epu16_mask&expand=1103) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpneq_epu16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpneq_epu16_mask(a, b) & k1 +} + +/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu8_mask&expand=1124) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpneq_epu8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_ne(a.as_u8x64(), b.as_u8x64())) +} + +/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu8_mask&expand=1125) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpneq_epu8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpneq_epu8_mask(a, b) & k1 +} + +/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epu8_mask&expand=1122) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpneq_epu8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_ne(a.as_u8x32(), b.as_u8x32())) +} + +/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epu8_mask&expand=1123) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpneq_epu8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpneq_epu8_mask(a, b) & k1 +} + +/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epu8_mask&expand=1120) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpneq_epu8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_ne(a.as_u8x16(), b.as_u8x16())) +} + +/// Compare packed unsigned 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epu8_mask&expand=1121) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpneq_epu8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpneq_epu8_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi16_mask&expand=1082) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpneq_epi16_mask(a: __m512i, b: __m512i) -> __mmask32 { + simd_bitmask::(simd_ne(a.as_i16x32(), b.as_i16x32())) +} + +/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi16_mask&expand=1083) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpneq_epi16_mask(k1: __mmask32, a: __m512i, b: __m512i) -> __mmask32 { + _mm512_cmpneq_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epi16_mask&expand=1080) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpneq_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + simd_bitmask::(simd_ne(a.as_i16x16(), b.as_i16x16())) +} + +/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epi16_mask&expand=1081) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpneq_epi16_mask(k1: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + _mm256_cmpneq_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epi16_mask&expand=1078) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpneq_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ne(a.as_i16x8(), b.as_i16x8())) +} + +/// Compare packed signed 16-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epi16_mask&expand=1079) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpneq_epi16_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpneq_epi16_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi8_mask&expand=1100) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_cmpneq_epi8_mask(a: __m512i, b: __m512i) -> __mmask64 { + simd_bitmask::(simd_ne(a.as_i8x64(), b.as_i8x64())) +} + +/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi8_mask&expand=1101) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm512_mask_cmpneq_epi8_mask(k1: __mmask64, a: __m512i, b: __m512i) -> __mmask64 { + _mm512_cmpneq_epi8_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epi8_mask&expand=1098) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_cmpneq_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + simd_bitmask::(simd_ne(a.as_i8x32(), b.as_i8x32())) +} + +/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epi8_mask&expand=1099) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm256_mask_cmpneq_epi8_mask(k1: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + _mm256_cmpneq_epi8_mask(a, b) & k1 +} + +/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epi8_mask&expand=1096) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_cmpneq_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + simd_bitmask::(simd_ne(a.as_i8x16(), b.as_i8x16())) +} + +/// Compare packed signed 8-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epi8_mask&expand=1097) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] +pub unsafe fn _mm_mask_cmpneq_epi8_mask(k1: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + _mm_cmpneq_epi8_mask(a, b) & k1 +} + +/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu16_mask&expand=715) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_cmp_epu16_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask32 { + let a = a.as_u16x32(); + let b = b.as_u16x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuw(a, b, $imm3, 0b11111111_11111111_11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epu16_mask&expand=716) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_mask_cmp_epu16_mask( + k1: __mmask32, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __mmask32 { + let a = a.as_u16x32(); + let b = b.as_u16x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuw(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_epu16_mask&expand=713) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epu16_mask(a: __m256i, b: __m256i, imm8: i32) -> __mmask16 { + let a = a.as_u16x16(); + let b = b.as_u16x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuw256(a, b, $imm3, 0b11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epu16_mask&expand=714) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epu16_mask( + k1: __mmask16, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __mmask16 { + let a = a.as_u16x16(); + let b = b.as_u16x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuw256(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epu16_mask&expand=711) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epu16_mask(a: __m128i, b: __m128i, imm8: i32) -> __mmask8 { + let a = a.as_u16x8(); + let b = b.as_u16x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuw128(a, b, $imm3, 0b11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epu16_mask&expand=712) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epu16_mask(k1: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __mmask8 { + let a = a.as_u16x8(); + let b = b.as_u16x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuw128(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu8_mask&expand=733) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_cmp_epu8_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask64 { + let a = a.as_u8x64(); + let b = b.as_u8x64(); + macro_rules! call { + ($imm3:expr) => { + vpcmpub( + a, + b, + $imm3, + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + ) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epu8_mask&expand=734) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_mask_cmp_epu8_mask( + k1: __mmask64, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __mmask64 { + let a = a.as_u8x64(); + let b = b.as_u8x64(); + macro_rules! call { + ($imm3:expr) => { + vpcmpub(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_epu8_mask&expand=731) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epu8_mask(a: __m256i, b: __m256i, imm8: i32) -> __mmask32 { + let a = a.as_u8x32(); + let b = b.as_u8x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpub256(a, b, $imm3, 0b11111111_11111111_11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epu8_mask&expand=732) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epu8_mask( + k1: __mmask32, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __mmask32 { + let a = a.as_u8x32(); + let b = b.as_u8x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpub256(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epu8_mask&expand=729) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epu8_mask(a: __m128i, b: __m128i, imm8: i32) -> __mmask16 { + let a = a.as_u8x16(); + let b = b.as_u8x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpub128(a, b, $imm3, 0b11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epu8_mask&expand=730) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epu8_mask( + k1: __mmask16, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __mmask16 { + let a = a.as_u8x16(); + let b = b.as_u8x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpub128(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi16_mask&expand=691) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_cmp_epi16_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask32 { + let a = a.as_i16x32(); + let b = b.as_i16x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpw(a, b, $imm3, 0b11111111_11111111_11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epi16_mask&expand=692) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_mask_cmp_epi16_mask( + k1: __mmask32, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __mmask32 { + let a = a.as_i16x32(); + let b = b.as_i16x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpw(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_epi16_mask&expand=689) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epi16_mask(a: __m256i, b: __m256i, imm8: i32) -> __mmask16 { + let a = a.as_i16x16(); + let b = b.as_i16x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpw256(a, b, $imm3, 0b11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epi16_mask&expand=690) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epi16_mask( + k1: __mmask16, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __mmask16 { + let a = a.as_i16x16(); + let b = b.as_i16x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpw256(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epi16_mask&expand=687) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epi16_mask(a: __m128i, b: __m128i, imm8: i32) -> __mmask8 { + let a = a.as_i16x8(); + let b = b.as_i16x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpw128(a, b, $imm3, 0b11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 16-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epi16_mask&expand=688) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epi16_mask(k1: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __mmask8 { + let a = a.as_i16x8(); + let b = b.as_i16x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpw128(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi8_mask&expand=709) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_cmp_epi8_mask(a: __m512i, b: __m512i, imm8: i32) -> __mmask64 { + let a = a.as_i8x64(); + let b = b.as_i8x64(); + macro_rules! call { + ($imm3:expr) => { + vpcmpb( + a, + b, + $imm3, + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + ) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_epi8_mask&expand=710) +#[inline] +#[target_feature(enable = "avx512bw")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm512_mask_cmp_epi8_mask( + k1: __mmask64, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __mmask64 { + let a = a.as_i8x64(); + let b = b.as_i8x64(); + macro_rules! call { + ($imm3:expr) => { + vpcmpb(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_epi8_mask&expand=707) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epi8_mask(a: __m256i, b: __m256i, imm8: i32) -> __mmask32 { + let a = a.as_i8x32(); + let b = b.as_i8x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpb256(a, b, $imm3, 0b11111111_11111111_11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epi8_mask&expand=708) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epi8_mask( + k1: __mmask32, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __mmask32 { + let a = a.as_i8x32(); + let b = b.as_i8x32(); + macro_rules! call { + ($imm3:expr) => { + vpcmpb256(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epi8_mask&expand=705) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epi8_mask(a: __m128i, b: __m128i, imm8: i32) -> __mmask16 { + let a = a.as_i8x16(); + let b = b.as_i8x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpb128(a, b, $imm3, 0b11111111_11111111) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 8-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epi8_mask&expand=706) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epi8_mask( + k1: __mmask16, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __mmask16 { + let a = a.as_i8x16(); + let b = b.as_i8x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpb128(a, b, $imm3, k1) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Load 512-bits (composed of 32 packed 16-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_epi16&expand=3368) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu16 +pub unsafe fn _mm512_loadu_epi16(mem_addr: *const i16) -> __m512i { + ptr::read_unaligned(mem_addr as *const __m512i) +} + +/// Load 256-bits (composed of 16 packed 16-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_loadu_epi16&expand=3365) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu16 +pub unsafe fn _mm256_loadu_epi16(mem_addr: *const i16) -> __m256i { + ptr::read_unaligned(mem_addr as *const __m256i) +} + +/// Load 128-bits (composed of 8 packed 16-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_epi16&expand=3362) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu16 +pub unsafe fn _mm_loadu_epi16(mem_addr: *const i16) -> __m128i { + ptr::read_unaligned(mem_addr as *const __m128i) +} + +/// Load 512-bits (composed of 64 packed 8-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_epi8&expand=3395) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 +pub unsafe fn _mm512_loadu_epi8(mem_addr: *const i8) -> __m512i { + ptr::read_unaligned(mem_addr as *const __m512i) +} + +/// Load 256-bits (composed of 32 packed 8-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_loadu_epi8&expand=3392) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 +pub unsafe fn _mm256_loadu_epi8(mem_addr: *const i8) -> __m256i { + ptr::read_unaligned(mem_addr as *const __m256i) +} + +/// Load 128-bits (composed of 16 packed 8-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_epi8&expand=3389) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 +pub unsafe fn _mm_loadu_epi8(mem_addr: *const i8) -> __m128i { + ptr::read_unaligned(mem_addr as *const __m128i) +} + +/// Store 512-bits (composed of 32 packed 16-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_epi16&expand=5622) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu16 +pub unsafe fn _mm512_storeu_epi16(mem_addr: *mut i16, a: __m512i) { + ptr::write_unaligned(mem_addr as *mut __m512i, a); +} + +/// Store 256-bits (composed of 16 packed 16-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_storeu_epi16&expand=5620) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu16 +pub unsafe fn _mm256_storeu_epi16(mem_addr: *mut i16, a: __m256i) { + ptr::write_unaligned(mem_addr as *mut __m256i, a); +} + +/// Store 128-bits (composed of 8 packed 16-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_epi16&expand=5618) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu16 +pub unsafe fn _mm_storeu_epi16(mem_addr: *mut i16, a: __m128i) { + ptr::write_unaligned(mem_addr as *mut __m128i, a); +} + +/// Store 512-bits (composed of 64 packed 8-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_epi8&expand=5640) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 +pub unsafe fn _mm512_storeu_epi8(mem_addr: *mut i8, a: __m512i) { + ptr::write_unaligned(mem_addr as *mut __m512i, a); +} + +/// Store 256-bits (composed of 32 packed 8-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_storeu_epi8&expand=5638) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 +pub unsafe fn _mm256_storeu_epi8(mem_addr: *mut i8, a: __m256i) { + ptr::write_unaligned(mem_addr as *mut __m256i, a); +} + +/// Store 128-bits (composed of 16 packed 8-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_epi8&expand=5636) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu8 +pub unsafe fn _mm_storeu_epi8(mem_addr: *mut i8, a: __m128i) { + ptr::write_unaligned(mem_addr as *mut __m128i, a); +} + +/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_madd_epi16&expand=3511) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmaddwd))] +pub unsafe fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { + transmute(vpmaddwd(a.as_i16x32(), b.as_i16x32())) +} + +/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_madd_epi16&expand=3512) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmaddwd))] +pub unsafe fn _mm512_mask_madd_epi16( + src: __m512i, + k: __mmask16, + a: __m512i, + b: __m512i, +) -> __m512i { + let madd = _mm512_madd_epi16(a, b).as_i32x16(); + transmute(simd_select_bitmask(k, madd, src.as_i32x16())) +} + +/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_madd_epi16&expand=3513) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmaddwd))] +pub unsafe fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { + let madd = _mm512_madd_epi16(a, b).as_i32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, madd, zero)) +} + +/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_madd_epi16&expand=3509) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddwd))] +pub unsafe fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let madd = _mm256_madd_epi16(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, madd, src.as_i32x8())) +} + +/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_madd_epi16&expand=3510) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddwd))] +pub unsafe fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let madd = _mm256_madd_epi16(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, madd, zero)) +} + +/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_madd_epi16&expand=3506) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddwd))] +pub unsafe fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let madd = _mm_madd_epi16(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, madd, src.as_i32x4())) +} + +/// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_madd_epi16&expand=3507) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddwd))] +pub unsafe fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let madd = _mm_madd_epi16(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, madd, zero)) +} + +/// Vertically multiply each unsigned 8-bit integer from a with the corresponding signed 8-bit integer from b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maddubs_epi16&expand=3539) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmaddubsw))] +pub unsafe fn _mm512_maddubs_epi16(a: __m512i, b: __m512i) -> __m512i { + transmute(vpmaddubsw(a.as_i8x64(), b.as_i8x64())) +} + +/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_maddubs_epi16&expand=3540) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmaddubsw))] +pub unsafe fn _mm512_mask_maddubs_epi16( + src: __m512i, + k: __mmask32, + a: __m512i, + b: __m512i, +) -> __m512i { + let madd = _mm512_maddubs_epi16(a, b).as_i16x32(); + transmute(simd_select_bitmask(k, madd, src.as_i16x32())) +} + +/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_maddubs_epi16&expand=3541) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmaddubsw))] +pub unsafe fn _mm512_maskz_maddubs_epi16(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { + let madd = _mm512_maddubs_epi16(a, b).as_i16x32(); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, madd, zero)) +} + +/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_maddubs_epi16&expand=3537) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddubsw))] +pub unsafe fn _mm256_mask_maddubs_epi16( + src: __m256i, + k: __mmask16, + a: __m256i, + b: __m256i, +) -> __m256i { + let madd = _mm256_maddubs_epi16(a, b).as_i16x16(); + transmute(simd_select_bitmask(k, madd, src.as_i16x16())) +} + +/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_maddubs_epi16&expand=3538) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddubsw))] +pub unsafe fn _mm256_maskz_maddubs_epi16(k: __mmask16, a: __m256i, b: __m256i) -> __m256i { + let madd = _mm256_maddubs_epi16(a, b).as_i16x16(); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, madd, zero)) +} + +/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_maddubs_epi16&expand=3534) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddubsw))] +pub unsafe fn _mm_mask_maddubs_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let madd = _mm_maddubs_epi16(a, b).as_i16x8(); + transmute(simd_select_bitmask(k, madd, src.as_i16x8())) +} + +/// Multiply packed unsigned 8-bit integers in a by packed signed 8-bit integers in b, producing intermediate signed 16-bit integers. Horizontally add adjacent pairs of intermediate signed 16-bit integers, and pack the saturated results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_maddubs_epi16&expand=3535) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaddubsw))] +pub unsafe fn _mm_maskz_maddubs_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let madd = _mm_maddubs_epi16(a, b).as_i16x8(); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, madd, zero)) +} + +/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_packs_epi32&expand=4091) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpackssdw))] +pub unsafe fn _mm512_packs_epi32(a: __m512i, b: __m512i) -> __m512i { + transmute(vpackssdw(a.as_i32x16(), b.as_i32x16())) +} + +/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_packs_epi32&expand=4089) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpackssdw))] +pub unsafe fn _mm512_mask_packs_epi32( + src: __m512i, + k: __mmask32, + a: __m512i, + b: __m512i, +) -> __m512i { + let pack = _mm512_packs_epi32(a, b).as_i16x32(); + transmute(simd_select_bitmask(k, pack, src.as_i16x32())) +} + +/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_packs_epi32&expand=4090) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpackssdw))] +pub unsafe fn _mm512_maskz_packs_epi32(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { + let pack = _mm512_packs_epi32(a, b).as_i16x32(); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, pack, zero)) +} + +/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_packs_epi32&expand=4086) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpackssdw))] +pub unsafe fn _mm256_mask_packs_epi32( + src: __m256i, + k: __mmask16, + a: __m256i, + b: __m256i, +) -> __m256i { + let pack = _mm256_packs_epi32(a, b).as_i16x16(); + transmute(simd_select_bitmask(k, pack, src.as_i16x16())) +} + +/// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_packs_epi32&expand=4087) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpackssdw))] @@ -3792,11 +5166,11 @@ pub unsafe fn _mm512_maskz_slli_epi16(k: __mmask32, a: __m512i, imm8: u32) -> __ pub unsafe fn _mm256_mask_slli_epi16(src: __m256i, k: __mmask16, a: __m256i, imm8: u32) -> __m256i { macro_rules! call { ($imm8:expr) => { - _mm256_slli_epi16(a, $imm8).as_i16x16() + _mm256_slli_epi16(a, $imm8) }; } let shf = constify_imm8_sae!(imm8, call); - transmute(simd_select_bitmask(k, shf, src.as_i16x16())) + transmute(simd_select_bitmask(k, shf.as_i16x16(), src.as_i16x16())) } /// Shift packed 16-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -3812,9 +5186,9 @@ pub unsafe fn _mm256_maskz_slli_epi16(k: __mmask16, a: __m256i, imm8: u32) -> __ _mm256_slli_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x16(); + let shf = constify_imm8_sae!(imm8, call); let zero = _mm256_setzero_si256().as_i16x16(); - transmute(simd_select_bitmask(k, shf, zero)) + transmute(simd_select_bitmask(k, shf.as_i16x16(), zero)) } /// Shift packed 16-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -3830,8 +5204,8 @@ pub unsafe fn _mm_mask_slli_epi16(src: __m128i, k: __mmask8, a: __m128i, imm8: u _mm_slli_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x8(); - transmute(simd_select_bitmask(k, shf, src.as_i16x8())) + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i16x8(), src.as_i16x8())) } /// Shift packed 16-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -3847,9 +5221,9 @@ pub unsafe fn _mm_maskz_slli_epi16(k: __mmask8, a: __m128i, imm8: u32) -> __m128 _mm_slli_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x8(); + let shf = constify_imm8_sae!(imm8, call); let zero = _mm_setzero_si128().as_i16x8(); - transmute(simd_select_bitmask(k, shf, zero)) + transmute(simd_select_bitmask(k, shf.as_i16x8(), zero)) } /// Shift packed 16-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst. @@ -4124,8 +5498,8 @@ pub unsafe fn _mm256_mask_srli_epi16(src: __m256i, k: __mmask16, a: __m256i, imm _mm256_srli_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x16(); - transmute(simd_select_bitmask(k, shf, src.as_i16x16())) + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i16x16(), src.as_i16x16())) } /// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -4141,9 +5515,9 @@ pub unsafe fn _mm256_maskz_srli_epi16(k: __mmask16, a: __m256i, imm8: i32) -> __ _mm256_srli_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x16(); + let shf = constify_imm8_sae!(imm8, call); let zero = _mm256_setzero_si256().as_i16x16(); - transmute(simd_select_bitmask(k, shf, zero)) + transmute(simd_select_bitmask(k, shf.as_i16x16(), zero)) } /// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -4159,8 +5533,8 @@ pub unsafe fn _mm_mask_srli_epi16(src: __m128i, k: __mmask8, a: __m128i, imm8: i _mm_srli_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x8(); - transmute(simd_select_bitmask(k, shf, src.as_i16x8())) + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i16x8(), src.as_i16x8())) } /// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -4176,9 +5550,9 @@ pub unsafe fn _mm_maskz_srli_epi16(k: __mmask8, a: __m128i, imm8: i32) -> __m128 _mm_srli_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x8(); + let shf = constify_imm8_sae!(imm8, call); let zero = _mm_setzero_si128().as_i16x8(); - transmute(simd_select_bitmask(k, shf, zero)) + transmute(simd_select_bitmask(k, shf.as_i16x8(), zero)) } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst. @@ -4452,8 +5826,8 @@ pub unsafe fn _mm256_mask_srai_epi16(src: __m256i, k: __mmask16, a: __m256i, imm _mm256_srai_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x16(); - transmute(simd_select_bitmask(k, shf, src.as_i16x16())) + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i16x16(), src.as_i16x16())) } /// Shift packed 16-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -4469,9 +5843,9 @@ pub unsafe fn _mm256_maskz_srai_epi16(k: __mmask16, a: __m256i, imm8: u32) -> __ _mm256_srai_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x16(); + let shf = constify_imm8_sae!(imm8, call); let zero = _mm256_setzero_si256().as_i16x16(); - transmute(simd_select_bitmask(k, shf, zero)) + transmute(simd_select_bitmask(k, shf.as_i16x16(), zero)) } /// Shift packed 16-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -4487,8 +5861,8 @@ pub unsafe fn _mm_mask_srai_epi16(src: __m128i, k: __mmask8, a: __m128i, imm8: u _mm_srai_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x8(); - transmute(simd_select_bitmask(k, shf, src.as_i16x8())) + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i16x8(), src.as_i16x8())) } /// Shift packed 16-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -4504,9 +5878,9 @@ pub unsafe fn _mm_maskz_srai_epi16(k: __mmask8, a: __m128i, imm8: u32) -> __m128 _mm_srai_epi16(a, $imm8) }; } - let shf = constify_imm8_sae!(imm8, call).as_i16x8(); + let shf = constify_imm8_sae!(imm8, call); let zero = _mm_setzero_si128().as_i16x8(); - transmute(simd_select_bitmask(k, shf, zero)) + transmute(simd_select_bitmask(k, shf.as_i16x8(), zero)) } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst. @@ -5958,54 +7332,13 @@ pub unsafe fn _mm512_mask_shufflelo_epi16( a: __m512i, imm8: i32, ) -> __m512i { - let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i16x32(); - macro_rules! shuffle_done { - ($x01: expr, $x23: expr, $x45: expr, $x67: expr) => { - #[rustfmt::skip] - simd_shuffle32(a, a, [ - 0+$x01, 0+$x23, 0+$x45, 0+$x67, 4, 5, 6, 7, 8+$x01, 8+$x23, 8+$x45, 8+$x67, 12, 13, 14, 15, - 16+$x01, 16+$x23, 16+$x45, 16+$x67, 20, 21, 22, 23, 24+$x01, 24+$x23, 24+$x45, 24+$x67, 28, 29, 30, 31, - ]) - }; - } - macro_rules! shuffle_x67 { - ($x01:expr, $x23:expr, $x45:expr) => { - match (imm8 >> 6) & 0b11 { - 0b00 => shuffle_done!($x01, $x23, $x45, 0), - 0b01 => shuffle_done!($x01, $x23, $x45, 1), - 0b10 => shuffle_done!($x01, $x23, $x45, 2), - _ => shuffle_done!($x01, $x23, $x45, 3), - } - }; - } - macro_rules! shuffle_x45 { - ($x01:expr, $x23:expr) => { - match (imm8 >> 4) & 0b11 { - 0b00 => shuffle_x67!($x01, $x23, 0), - 0b01 => shuffle_x67!($x01, $x23, 1), - 0b10 => shuffle_x67!($x01, $x23, 2), - _ => shuffle_x67!($x01, $x23, 3), - } - }; - } - macro_rules! shuffle_x23 { - ($x01:expr) => { - match (imm8 >> 2) & 0b11 { - 0b00 => shuffle_x45!($x01, 0), - 0b01 => shuffle_x45!($x01, 1), - 0b10 => shuffle_x45!($x01, 2), - _ => shuffle_x45!($x01, 3), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shufflelo_epi16(a, $imm8) }; } - let r: i16x32 = match imm8 & 0b11 { - 0b00 => shuffle_x23!(0), - 0b01 => shuffle_x23!(1), - 0b10 => shuffle_x23!(2), - _ => shuffle_x23!(3), - }; - transmute(simd_select_bitmask(k, r, src.as_i16x32())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i16x32(), src.as_i16x32())) } /// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -6016,58 +7349,94 @@ pub unsafe fn _mm512_mask_shufflelo_epi16( #[cfg_attr(test, assert_instr(vpshuflw, imm8 = 0))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_shufflelo_epi16(k: __mmask32, a: __m512i, imm8: i32) -> __m512i { - let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i16x32(); - macro_rules! shuffle_done { - ($x01: expr, $x23: expr, $x45: expr, $x67: expr) => { - #[rustfmt::skip] - simd_shuffle32(a, a, [ - 0+$x01, 0+$x23, 0+$x45, 0+$x67, 4, 5, 6, 7, 8+$x01, 8+$x23, 8+$x45, 8+$x67, 12, 13, 14, 15, - 16+$x01, 16+$x23, 16+$x45, 16+$x67, 20, 21, 22, 23, 24+$x01, 24+$x23, 24+$x45, 24+$x67, 28, 29, 30, 31, - ]) + macro_rules! call { + ($imm8:expr) => { + _mm512_shufflelo_epi16(a, $imm8) }; } - macro_rules! shuffle_x67 { - ($x01:expr, $x23:expr, $x45:expr) => { - match (imm8 >> 6) & 0b11 { - 0b00 => shuffle_done!($x01, $x23, $x45, 0), - 0b01 => shuffle_done!($x01, $x23, $x45, 1), - 0b10 => shuffle_done!($x01, $x23, $x45, 2), - _ => shuffle_done!($x01, $x23, $x45, 3), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, r.as_i16x32(), zero)) +} + +/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shufflelo_epi16&expand=5216) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshuflw, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_shufflelo_epi16( + src: __m256i, + k: __mmask16, + a: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shufflelo_epi16(a, $imm8) + }; + } + let shuffle = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shuffle.as_i16x16(), src.as_i16x16())) +} + +/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shufflelo_epi16&expand=5217) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshuflw, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_shufflelo_epi16(k: __mmask16, a: __m256i, imm8: i32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shufflelo_epi16(a, $imm8) }; } - macro_rules! shuffle_x45 { - ($x01:expr, $x23:expr) => { - match (imm8 >> 4) & 0b11 { - 0b00 => shuffle_x67!($x01, $x23, 0), - 0b01 => shuffle_x67!($x01, $x23, 1), - 0b10 => shuffle_x67!($x01, $x23, 2), - _ => shuffle_x67!($x01, $x23, 3), - } + let shuffle = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, shuffle.as_i16x16(), zero)) +} + +/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shufflelo_epi16&expand=5213) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshuflw, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_shufflelo_epi16( + src: __m128i, + k: __mmask8, + a: __m128i, + imm8: i32, +) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_shufflelo_epi16(a, $imm8) }; } - macro_rules! shuffle_x23 { - ($x01:expr) => { - match (imm8 >> 2) & 0b11 { - 0b00 => shuffle_x45!($x01, 0), - 0b01 => shuffle_x45!($x01, 1), - 0b10 => shuffle_x45!($x01, 2), - _ => shuffle_x45!($x01, 3), - } + let shuffle = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shuffle.as_i16x8(), src.as_i16x8())) +} + +/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shufflelo_epi16&expand=5214) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshuflw, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_shufflelo_epi16(k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_shufflelo_epi16(a, $imm8) }; } - let r: i16x32 = match imm8 & 0b11 { - 0b00 => shuffle_x23!(0), - 0b01 => shuffle_x23!(1), - 0b10 => shuffle_x23!(2), - _ => shuffle_x23!(3), - }; - transmute(simd_select_bitmask( - k, - r, - _mm512_setzero_si512().as_i16x32(), - )) + let shuffle = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, shuffle.as_i16x8(), zero)) } /// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst. @@ -6141,54 +7510,13 @@ pub unsafe fn _mm512_mask_shufflehi_epi16( a: __m512i, imm8: i32, ) -> __m512i { - let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i16x32(); - macro_rules! shuffle_done { - ($x01: expr, $x23: expr, $x45: expr, $x67: expr) => { - #[rustfmt::skip] - simd_shuffle32(a, a, [ - 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67, - 16, 17, 18, 19, 20+$x01, 20+$x23, 20+$x45, 20+$x67, 24, 25, 26, 27, 28+$x01, 28+$x23, 28+$x45, 28+$x67, - ]) - }; - } - macro_rules! shuffle_x67 { - ($x01:expr, $x23:expr, $x45:expr) => { - match (imm8 >> 6) & 0b11 { - 0b00 => shuffle_done!($x01, $x23, $x45, 0), - 0b01 => shuffle_done!($x01, $x23, $x45, 1), - 0b10 => shuffle_done!($x01, $x23, $x45, 2), - _ => shuffle_done!($x01, $x23, $x45, 3), - } - }; - } - macro_rules! shuffle_x45 { - ($x01:expr, $x23:expr) => { - match (imm8 >> 4) & 0b11 { - 0b00 => shuffle_x67!($x01, $x23, 0), - 0b01 => shuffle_x67!($x01, $x23, 1), - 0b10 => shuffle_x67!($x01, $x23, 2), - _ => shuffle_x67!($x01, $x23, 3), - } - }; - } - macro_rules! shuffle_x23 { - ($x01:expr) => { - match (imm8 >> 2) & 0b11 { - 0b00 => shuffle_x45!($x01, 0), - 0b01 => shuffle_x45!($x01, 1), - 0b10 => shuffle_x45!($x01, 2), - _ => shuffle_x45!($x01, 3), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shufflehi_epi16(a, $imm8) }; } - let r: i16x32 = match imm8 & 0b11 { - 0b00 => shuffle_x23!(0), - 0b01 => shuffle_x23!(1), - 0b10 => shuffle_x23!(2), - _ => shuffle_x23!(3), - }; - transmute(simd_select_bitmask(k, r, src.as_i16x32())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i16x32(), src.as_i16x32())) } /// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -6199,95 +7527,182 @@ pub unsafe fn _mm512_mask_shufflehi_epi16( #[cfg_attr(test, assert_instr(vpshufhw, imm8 = 0))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_shufflehi_epi16(k: __mmask32, a: __m512i, imm8: i32) -> __m512i { - let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i16x32(); - macro_rules! shuffle_done { - ($x01: expr, $x23: expr, $x45: expr, $x67: expr) => { - #[rustfmt::skip] - simd_shuffle32(a, a, [ - 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67, - 16, 17, 18, 19, 20+$x01, 20+$x23, 20+$x45, 20+$x67, 24, 25, 26, 27, 28+$x01, 28+$x23, 28+$x45, 28+$x67, - ]) + macro_rules! call { + ($imm8:expr) => { + _mm512_shufflehi_epi16(a, $imm8) }; } - macro_rules! shuffle_x67 { - ($x01:expr, $x23:expr, $x45:expr) => { - match (imm8 >> 6) & 0b11 { - 0b00 => shuffle_done!($x01, $x23, $x45, 0), - 0b01 => shuffle_done!($x01, $x23, $x45, 1), - 0b10 => shuffle_done!($x01, $x23, $x45, 2), - _ => shuffle_done!($x01, $x23, $x45, 3), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, r.as_i16x32(), zero)) +} + +/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shufflehi_epi16&expand=5207) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufhw, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_shufflehi_epi16( + src: __m256i, + k: __mmask16, + a: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shufflehi_epi16(a, $imm8) }; } - macro_rules! shuffle_x45 { - ($x01:expr, $x23:expr) => { - match (imm8 >> 4) & 0b11 { - 0b00 => shuffle_x67!($x01, $x23, 0), - 0b01 => shuffle_x67!($x01, $x23, 1), - 0b10 => shuffle_x67!($x01, $x23, 2), - _ => shuffle_x67!($x01, $x23, 3), - } + let shuffle = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shuffle.as_i16x16(), src.as_i16x16())) +} + +/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shufflehi_epi16&expand=5208) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufhw, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_shufflehi_epi16(k: __mmask16, a: __m256i, imm8: i32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shufflehi_epi16(a, $imm8) }; } - macro_rules! shuffle_x23 { - ($x01:expr) => { - match (imm8 >> 2) & 0b11 { - 0b00 => shuffle_x45!($x01, 0), - 0b01 => shuffle_x45!($x01, 1), - 0b10 => shuffle_x45!($x01, 2), - _ => shuffle_x45!($x01, 3), - } + let shuffle = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, shuffle.as_i16x16(), zero)) +} + +/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shufflehi_epi16&expand=5204) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufhw, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_shufflehi_epi16( + src: __m128i, + k: __mmask8, + a: __m128i, + imm8: i32, +) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_shufflehi_epi16(a, $imm8) }; } - let r: i16x32 = match imm8 & 0b11 { - 0b00 => shuffle_x23!(0), - 0b01 => shuffle_x23!(1), - 0b10 => shuffle_x23!(2), - _ => shuffle_x23!(3), - }; - transmute(simd_select_bitmask( - k, - r, - _mm512_setzero_si512().as_i16x32(), - )) + let shuffle = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shuffle.as_i16x8(), src.as_i16x8())) +} + +/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shufflehi_epi16&expand=5205) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufhw, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_shufflehi_epi16(k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_shufflehi_epi16(a, $imm8) + }; + } + let shuffle = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, shuffle.as_i16x8(), zero)) +} + +/// Shuffle packed 8-bit integers in a according to shuffle control mask in the corresponding 8-bit element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_epi8&expand=5159) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpshufb))] +pub unsafe fn _mm512_shuffle_epi8(a: __m512i, b: __m512i) -> __m512i { + transmute(vpshufb(a.as_i8x64(), b.as_i8x64())) +} + +/// Shuffle 8-bit integers in a within 128-bit lanes using the control in the corresponding 8-bit element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_epi8&expand=5157) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpshufb))] +pub unsafe fn _mm512_mask_shuffle_epi8( + src: __m512i, + k: __mmask64, + a: __m512i, + b: __m512i, +) -> __m512i { + let shuffle = _mm512_shuffle_epi8(a, b).as_i8x64(); + transmute(simd_select_bitmask(k, shuffle, src.as_i8x64())) +} + +/// Shuffle packed 8-bit integers in a according to shuffle control mask in the corresponding 8-bit element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_epi8&expand=5158) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpshufb))] +pub unsafe fn _mm512_maskz_shuffle_epi8(k: __mmask64, a: __m512i, b: __m512i) -> __m512i { + let shuffle = _mm512_shuffle_epi8(a, b).as_i8x64(); + let zero = _mm512_setzero_si512().as_i8x64(); + transmute(simd_select_bitmask(k, shuffle, zero)) +} + +/// Shuffle 8-bit integers in a within 128-bit lanes using the control in the corresponding 8-bit element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_epi8&expand=5154) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufb))] +pub unsafe fn _mm256_mask_shuffle_epi8( + src: __m256i, + k: __mmask32, + a: __m256i, + b: __m256i, +) -> __m256i { + let shuffle = _mm256_shuffle_epi8(a, b).as_i8x32(); + transmute(simd_select_bitmask(k, shuffle, src.as_i8x32())) } -/// Shuffle packed 8-bit integers in a according to shuffle control mask in the corresponding 8-bit element of b, and store the results in dst. +/// Shuffle packed 8-bit integers in a according to shuffle control mask in the corresponding 8-bit element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_epi8&expand=5159) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_epi8&expand=5155) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpshufb))] -pub unsafe fn _mm512_shuffle_epi8(a: __m512i, b: __m512i) -> __m512i { - transmute(vpshufb(a.as_i8x64(), b.as_i8x64())) +pub unsafe fn _mm256_maskz_shuffle_epi8(k: __mmask32, a: __m256i, b: __m256i) -> __m256i { + let shuffle = _mm256_shuffle_epi8(a, b).as_i8x32(); + let zero = _mm256_setzero_si256().as_i8x32(); + transmute(simd_select_bitmask(k, shuffle, zero)) } /// Shuffle 8-bit integers in a within 128-bit lanes using the control in the corresponding 8-bit element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_epi8&expand=5157) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shuffle_epi8&expand=5151) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpshufb))] -pub unsafe fn _mm512_mask_shuffle_epi8( - src: __m512i, - k: __mmask64, - a: __m512i, - b: __m512i, -) -> __m512i { - let shuffle = _mm512_shuffle_epi8(a, b).as_i8x64(); - transmute(simd_select_bitmask(k, shuffle, src.as_i8x64())) +pub unsafe fn _mm_mask_shuffle_epi8(src: __m128i, k: __mmask16, a: __m128i, b: __m128i) -> __m128i { + let shuffle = _mm_shuffle_epi8(a, b).as_i8x16(); + transmute(simd_select_bitmask(k, shuffle, src.as_i8x16())) } /// Shuffle packed 8-bit integers in a according to shuffle control mask in the corresponding 8-bit element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_epi8&expand=5158) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shuffle_epi8&expand=5152) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpshufb))] -pub unsafe fn _mm512_maskz_shuffle_epi8(k: __mmask64, a: __m512i, b: __m512i) -> __m512i { - let shuffle = _mm512_shuffle_epi8(a, b).as_i8x64(); - let zero = _mm512_setzero_si512().as_i8x64(); +pub unsafe fn _mm_maskz_shuffle_epi8(k: __mmask16, a: __m128i, b: __m128i) -> __m128i { + let shuffle = _mm_shuffle_epi8(a, b).as_i8x16(); + let zero = _mm_setzero_si128().as_i8x16(); transmute(simd_select_bitmask(k, shuffle, zero)) } @@ -6315,6 +7730,54 @@ pub unsafe fn _mm512_mask_test_epi16_mask(k: __mmask32, a: __m512i, b: __m512i) _mm512_mask_cmpneq_epi16_mask(k, and, zero) } +/// Compute the bitwise AND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_test_epi16_mask&expand=5882) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmw))] +pub unsafe fn _mm256_test_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpneq_epi16_mask(and, zero) +} + +/// Compute the bitwise AND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_test_epi16_mask&expand=5881) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmw))] +pub unsafe fn _mm256_mask_test_epi16_mask(k: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpneq_epi16_mask(k, and, zero) +} + +/// Compute the bitwise AND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_epi16_mask&expand=5880) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmw))] +pub unsafe fn _mm_test_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpneq_epi16_mask(and, zero) +} + +/// Compute the bitwise AND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_test_epi16_mask&expand=5879) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmw))] +pub unsafe fn _mm_mask_test_epi16_mask(k: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpneq_epi16_mask(k, and, zero) +} + /// Compute the bitwise AND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_test_epi8_mask&expand=5902) @@ -6339,6 +7802,54 @@ pub unsafe fn _mm512_mask_test_epi8_mask(k: __mmask64, a: __m512i, b: __m512i) - _mm512_mask_cmpneq_epi8_mask(k, and, zero) } +/// Compute the bitwise AND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_test_epi8_mask&expand=5900) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmb))] +pub unsafe fn _mm256_test_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpneq_epi8_mask(and, zero) +} + +/// Compute the bitwise AND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_test_epi8_mask&expand=5899) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmb))] +pub unsafe fn _mm256_mask_test_epi8_mask(k: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpneq_epi8_mask(k, and, zero) +} + +/// Compute the bitwise AND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_epi8_mask&expand=5898) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmb))] +pub unsafe fn _mm_test_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpneq_epi8_mask(and, zero) +} + +/// Compute the bitwise AND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_test_epi8_mask&expand=5897) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmb))] +pub unsafe fn _mm_mask_test_epi8_mask(k: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpneq_epi8_mask(k, and, zero) +} + /// Compute the bitwise NAND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_testn_epi16_mask&expand=5915) @@ -6363,6 +7874,54 @@ pub unsafe fn _mm512_mask_testn_epi16_mask(k: __mmask32, a: __m512i, b: __m512i) _mm512_mask_cmpeq_epi16_mask(k, and, zero) } +/// Compute the bitwise NAND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_testn_epi16_mask&expand=5913) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmw))] +pub unsafe fn _mm256_testn_epi16_mask(a: __m256i, b: __m256i) -> __mmask16 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpeq_epi16_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_testn_epi16_mask&expand=5912) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmw))] +pub unsafe fn _mm256_mask_testn_epi16_mask(k: __mmask16, a: __m256i, b: __m256i) -> __mmask16 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpeq_epi16_mask(k, and, zero) +} + +/// Compute the bitwise NAND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testn_epi16_mask&expand=5911) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmw))] +pub unsafe fn _mm_testn_epi16_mask(a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpeq_epi16_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 16-bit integers in a and b, producing intermediate 16-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_testn_epi16_mask&expand=5910) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmw))] +pub unsafe fn _mm_mask_testn_epi16_mask(k: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpeq_epi16_mask(k, and, zero) +} + /// Compute the bitwise NAND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_testn_epi8_mask&expand=5933) @@ -6387,6 +7946,54 @@ pub unsafe fn _mm512_mask_testn_epi8_mask(k: __mmask64, a: __m512i, b: __m512i) _mm512_mask_cmpeq_epi8_mask(k, and, zero) } +/// Compute the bitwise NAND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_testn_epi8_mask&expand=5931) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmb))] +pub unsafe fn _mm256_testn_epi8_mask(a: __m256i, b: __m256i) -> __mmask32 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpeq_epi8_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_testn_epi8_mask&expand=5930) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmb))] +pub unsafe fn _mm256_mask_testn_epi8_mask(k: __mmask32, a: __m256i, b: __m256i) -> __mmask32 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpeq_epi8_mask(k, and, zero) +} + +/// Compute the bitwise NAND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testn_epi8_mask&expand=5929) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmb))] +pub unsafe fn _mm_testn_epi8_mask(a: __m128i, b: __m128i) -> __mmask16 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpeq_epi8_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 8-bit integers in a and b, producing intermediate 8-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_testn_epi8_mask&expand=5928) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmb))] +pub unsafe fn _mm_mask_testn_epi8_mask(k: __mmask16, a: __m128i, b: __m128i) -> __mmask16 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpeq_epi8_mask(k, and, zero) +} + /// Store 64-bit mask from a into memory. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_store_mask64&expand=5578) @@ -6504,16 +8111,170 @@ pub unsafe fn _mm512_maskz_dbsad_epu8(k: __mmask32, a: __m512i, b: __m512i, imm8 )) } +/// Compute the sum of absolute differences (SADs) of quadruplets of unsigned 8-bit integers in a compared to those in b, and store the 16-bit results in dst. Four SADs are performed on four 8-bit quadruplets for each 64-bit lane. The first two SADs use the lower 8-bit quadruplet of the lane from a, and the last two SADs use the uppper 8-bit quadruplet of the lane from a. Quadruplets from b are selected from within 128-bit lanes according to the control in imm8, and each SAD in each 64-bit lane uses the selected quadruplet at 8-bit offsets. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_dbsad_epu8&expand=2111) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vdbpsadbw, imm8 = 0))] +pub unsafe fn _mm256_dbsad_epu8(a: __m256i, b: __m256i, imm8: i32) -> __m256i { + let a = a.as_u8x32(); + let b = b.as_u8x32(); + macro_rules! call { + ($imm8:expr) => { + vdbpsadbw256(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Compute the sum of absolute differences (SADs) of quadruplets of unsigned 8-bit integers in a compared to those in b, and store the 16-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). Four SADs are performed on four 8-bit quadruplets for each 64-bit lane. The first two SADs use the lower 8-bit quadruplet of the lane from a, and the last two SADs use the uppper 8-bit quadruplet of the lane from a. Quadruplets from b are selected from within 128-bit lanes according to the control in imm8, and each SAD in each 64-bit lane uses the selected quadruplet at 8-bit offsets. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_dbsad_epu8&expand=2112) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(4)] +#[cfg_attr(test, assert_instr(vdbpsadbw, imm8 = 0))] +pub unsafe fn _mm256_mask_dbsad_epu8( + src: __m256i, + k: __mmask16, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + let a = a.as_u8x32(); + let b = b.as_u8x32(); + macro_rules! call { + ($imm8:expr) => { + vdbpsadbw256(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r, src.as_u16x16())) +} + +/// Compute the sum of absolute differences (SADs) of quadruplets of unsigned 8-bit integers in a compared to those in b, and store the 16-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). Four SADs are performed on four 8-bit quadruplets for each 64-bit lane. The first two SADs use the lower 8-bit quadruplet of the lane from a, and the last two SADs use the uppper 8-bit quadruplet of the lane from a. Quadruplets from b are selected from within 128-bit lanes according to the control in imm8, and each SAD in each 64-bit lane uses the selected quadruplet at 8-bit offsets. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_dbsad_epu8&expand=2113) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vdbpsadbw, imm8 = 0))] +pub unsafe fn _mm256_maskz_dbsad_epu8(k: __mmask16, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + let a = a.as_u8x32(); + let b = b.as_u8x32(); + macro_rules! call { + ($imm8:expr) => { + vdbpsadbw256(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask( + k, + r, + _mm256_setzero_si256().as_u16x16(), + )) +} + +/// Compute the sum of absolute differences (SADs) of quadruplets of unsigned 8-bit integers in a compared to those in b, and store the 16-bit results in dst. Four SADs are performed on four 8-bit quadruplets for each 64-bit lane. The first two SADs use the lower 8-bit quadruplet of the lane from a, and the last two SADs use the uppper 8-bit quadruplet of the lane from a. Quadruplets from b are selected from within 128-bit lanes according to the control in imm8, and each SAD in each 64-bit lane uses the selected quadruplet at 8-bit offsets. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dbsad_epu8&expand=2108) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vdbpsadbw, imm8 = 0))] +pub unsafe fn _mm_dbsad_epu8(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + let a = a.as_u8x16(); + let b = b.as_u8x16(); + macro_rules! call { + ($imm8:expr) => { + vdbpsadbw128(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Compute the sum of absolute differences (SADs) of quadruplets of unsigned 8-bit integers in a compared to those in b, and store the 16-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). Four SADs are performed on four 8-bit quadruplets for each 64-bit lane. The first two SADs use the lower 8-bit quadruplet of the lane from a, and the last two SADs use the uppper 8-bit quadruplet of the lane from a. Quadruplets from b are selected from within 128-bit lanes according to the control in imm8, and each SAD in each 64-bit lane uses the selected quadruplet at 8-bit offsets. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_dbsad_epu8&expand=2109) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(4)] +#[cfg_attr(test, assert_instr(vdbpsadbw, imm8 = 0))] +pub unsafe fn _mm_mask_dbsad_epu8( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + let a = a.as_u8x16(); + let b = b.as_u8x16(); + macro_rules! call { + ($imm8:expr) => { + vdbpsadbw128(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r, src.as_u16x8())) +} + +/// Compute the sum of absolute differences (SADs) of quadruplets of unsigned 8-bit integers in a compared to those in b, and store the 16-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). Four SADs are performed on four 8-bit quadruplets for each 64-bit lane. The first two SADs use the lower 8-bit quadruplet of the lane from a, and the last two SADs use the uppper 8-bit quadruplet of the lane from a. Quadruplets from b are selected from within 128-bit lanes according to the control in imm8, and each SAD in each 64-bit lane uses the selected quadruplet at 8-bit offsets. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_dbsad_epu8&expand=2110) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vdbpsadbw, imm8 = 0))] +pub unsafe fn _mm_maskz_dbsad_epu8(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + let a = a.as_u8x16(); + let b = b.as_u8x16(); + macro_rules! call { + ($imm8:expr) => { + vdbpsadbw128(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r, _mm_setzero_si128().as_u16x8())) +} + /// Set each bit of mask register k based on the most significant bit of the corresponding packed 16-bit integer in a. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movepi16_mask&expand=3873) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(mov))] // should be vpmovw2m but msvc does not generate it -pub unsafe fn _mm512_movepi16_mask(a: __m512i) -> __mmask32 { - let filter = _mm512_set1_epi16(1 << 15); - let a = _mm512_and_si512(a, filter); - _mm512_cmpeq_epi16_mask(a, filter) +pub unsafe fn _mm512_movepi16_mask(a: __m512i) -> __mmask32 { + let filter = _mm512_set1_epi16(1 << 15); + let a = _mm512_and_si512(a, filter); + _mm512_cmpeq_epi16_mask(a, filter) +} + +/// Set each bit of mask register k based on the most significant bit of the corresponding packed 16-bit integer in a. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_movepi16_mask&expand=3872) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(mov))] // should be vpmovw2m but msvc does not generate it +pub unsafe fn _mm256_movepi16_mask(a: __m256i) -> __mmask16 { + let filter = _mm256_set1_epi16(1 << 15); + let a = _mm256_and_si256(a, filter); + _mm256_cmpeq_epi16_mask(a, filter) +} + +/// Set each bit of mask register k based on the most significant bit of the corresponding packed 16-bit integer in a. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi16_mask&expand=3871) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(mov))] // should be vpmovw2m but msvc does not generate it +pub unsafe fn _mm_movepi16_mask(a: __m128i) -> __mmask8 { + let filter = _mm_set1_epi16(1 << 15); + let a = _mm_and_si128(a, filter); + _mm_cmpeq_epi16_mask(a, filter) } /// Set each bit of mask register k based on the most significant bit of the corresponding packed 8-bit integer in a. @@ -6528,6 +8289,30 @@ pub unsafe fn _mm512_movepi8_mask(a: __m512i) -> __mmask64 { _mm512_cmpeq_epi8_mask(a, filter) } +/// Set each bit of mask register k based on the most significant bit of the corresponding packed 8-bit integer in a. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_movepi8_mask&expand=3882) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(mov))] // should be vpmovb2m but msvc does not generate it +pub unsafe fn _mm256_movepi8_mask(a: __m256i) -> __mmask32 { + let filter = _mm256_set1_epi8(1 << 7); + let a = _mm256_and_si256(a, filter); + _mm256_cmpeq_epi8_mask(a, filter) +} + +/// Set each bit of mask register k based on the most significant bit of the corresponding packed 8-bit integer in a. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi8_mask&expand=3881) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(mov))] // should be vpmovb2m but msvc does not generate it +pub unsafe fn _mm_movepi8_mask(a: __m128i) -> __mmask16 { + let filter = _mm_set1_epi8(1 << 7); + let a = _mm_and_si128(a, filter); + _mm_cmpeq_epi8_mask(a, filter) +} + /// Set each packed 16-bit integer in dst to all ones or all zeros based on the value of the corresponding bit in k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movm_epi16&expand=3886) @@ -6558,6 +8343,66 @@ pub unsafe fn _mm512_movm_epi16(k: __mmask32) -> __m512i { transmute(simd_select_bitmask(k, one, zero)) } +/// Set each packed 16-bit integer in dst to all ones or all zeros based on the value of the corresponding bit in k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_movm_epi16&expand=3885) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovm2w))] +pub unsafe fn _mm256_movm_epi16(k: __mmask16) -> __m256i { + let one = _mm256_set1_epi16( + 1 << 15 + | 1 << 14 + | 1 << 13 + | 1 << 12 + | 1 << 11 + | 1 << 10 + | 1 << 9 + | 1 << 8 + | 1 << 7 + | 1 << 6 + | 1 << 5 + | 1 << 4 + | 1 << 3 + | 1 << 2 + | 1 << 1 + | 1 << 0, + ) + .as_i16x16(); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, one, zero)) +} + +/// Set each packed 16-bit integer in dst to all ones or all zeros based on the value of the corresponding bit in k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movm_epi16&expand=3884) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovm2w))] +pub unsafe fn _mm_movm_epi16(k: __mmask8) -> __m128i { + let one = _mm_set1_epi16( + 1 << 15 + | 1 << 14 + | 1 << 13 + | 1 << 12 + | 1 << 11 + | 1 << 10 + | 1 << 9 + | 1 << 8 + | 1 << 7 + | 1 << 6 + | 1 << 5 + | 1 << 4 + | 1 << 3 + | 1 << 2 + | 1 << 1 + | 1 << 0, + ) + .as_i16x8(); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, one, zero)) +} + /// Set each packed 8-bit integer in dst to all ones or all zeros based on the value of the corresponding bit in k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movm_epi8&expand=3895) @@ -6572,12 +8417,40 @@ pub unsafe fn _mm512_movm_epi8(k: __mmask64) -> __m512i { transmute(simd_select_bitmask(k, one, zero)) } +/// Set each packed 8-bit integer in dst to all ones or all zeros based on the value of the corresponding bit in k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_movm_epi8&expand=3894) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovm2b))] +pub unsafe fn _mm256_movm_epi8(k: __mmask32) -> __m256i { + let one = + _mm256_set1_epi8(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0) + .as_i8x32(); + let zero = _mm256_setzero_si256().as_i8x32(); + transmute(simd_select_bitmask(k, one, zero)) +} + +/// Set each packed 8-bit integer in dst to all ones or all zeros based on the value of the corresponding bit in k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movm_epi8&expand=3893) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovm2b))] +pub unsafe fn _mm_movm_epi8(k: __mmask16) -> __m128i { + let one = _mm_set1_epi8(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0) + .as_i8x16(); + let zero = _mm_setzero_si128().as_i8x16(); + transmute(simd_select_bitmask(k, one, zero)) +} + /// Add 32-bit masks in a and b, and store the result in k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_kadd_mask32&expand=3207) #[inline] #[target_feature(enable = "avx512bw")] #[cfg_attr(test, assert_instr(mov))] // generate normal and code instead of kaddd + //llvm.x86.avx512.kadd.d pub unsafe fn _kadd_mask32(a: __mmask32, b: __mmask32) -> __mmask32 { transmute(a + b) } @@ -6747,6 +8620,81 @@ pub unsafe fn _mm512_maskz_cvtepi16_epi8(k: __mmask32, a: __m512i) -> __m256i { )) } +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtepi16_epi8&expand=1404) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm256_cvtepi16_epi8(a: __m256i) -> __m128i { + let a = a.as_i16x16(); + transmute::(simd_cast(a)) +} + +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi16_epi8&expand=1405) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm256_mask_cvtepi16_epi8(src: __m128i, k: __mmask16, a: __m256i) -> __m128i { + let convert = _mm256_cvtepi16_epi8(a).as_i8x16(); + transmute(simd_select_bitmask(k, convert, src.as_i8x16())) +} + +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi16_epi8&expand=1406) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm256_maskz_cvtepi16_epi8(k: __mmask16, a: __m256i) -> __m128i { + let convert = _mm256_cvtepi16_epi8(a).as_i8x16(); + transmute(simd_select_bitmask( + k, + convert, + _mm_setzero_si128().as_i8x16(), + )) +} + +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi16_epi8&expand=1401) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm_cvtepi16_epi8(a: __m128i) -> __m128i { + let a = a.as_i16x8(); + let zero = _mm_setzero_si128().as_i16x8(); + let v256: i16x16 = simd_shuffle16(a, zero, [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8]); + transmute::(simd_cast(v256)) +} + +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi16_epi8&expand=1402) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm_mask_cvtepi16_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi16_epi8(a).as_i8x16(); + let k: __mmask16 = 0b11111111_11111111 & k as __mmask16; + transmute(simd_select_bitmask(k, convert, src.as_i8x16())) +} + +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi16_epi8&expand=1403) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm_maskz_cvtepi16_epi8(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi16_epi8(a).as_i8x16(); + let k: __mmask16 = 0b11111111_11111111 & k as __mmask16; + let zero = _mm_setzero_si128().as_i8x16(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi16_epi8&expand=1807) @@ -6785,40 +8733,188 @@ pub unsafe fn _mm512_maskz_cvtsepi16_epi8(k: __mmask32, a: __m512i) -> __m256i { )) } +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtsepi16_epi8&expand=1804) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm256_cvtsepi16_epi8(a: __m256i) -> __m128i { + transmute(vpmovswb256( + a.as_i16x16(), + _mm_setzero_si128().as_i8x16(), + 0b11111111_11111111, + )) +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi16_epi8&expand=1805) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm256_mask_cvtsepi16_epi8(src: __m128i, k: __mmask16, a: __m256i) -> __m128i { + transmute(vpmovswb256(a.as_i16x16(), src.as_i8x16(), k)) +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtsepi16_epi8&expand=1806) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm256_maskz_cvtsepi16_epi8(k: __mmask16, a: __m256i) -> __m128i { + transmute(vpmovswb256( + a.as_i16x16(), + _mm_setzero_si128().as_i8x16(), + k, + )) +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsepi16_epi8&expand=1801) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm_cvtsepi16_epi8(a: __m128i) -> __m128i { + transmute(vpmovswb128( + a.as_i16x8(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi16_epi8&expand=1802) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm_mask_cvtsepi16_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovswb128(a.as_i16x8(), src.as_i8x16(), k)) +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtsepi16_epi8&expand=1803) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm_maskz_cvtsepi16_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovswb128(a.as_i16x8(), _mm_setzero_si128().as_i8x16(), k)) +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi16_epi8&expand=2042) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm512_cvtusepi16_epi8(a: __m512i) -> __m256i { + transmute(vpmovuswb( + a.as_u16x32(), + _mm256_setzero_si256().as_u8x32(), + 0b11111111_11111111_11111111_11111111, + )) +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi16_epi8&expand=2043) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm512_mask_cvtusepi16_epi8(src: __m256i, k: __mmask32, a: __m512i) -> __m256i { + transmute(vpmovuswb(a.as_u16x32(), src.as_u8x32(), k)) +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi16_epi8&expand=2044) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm512_maskz_cvtusepi16_epi8(k: __mmask32, a: __m512i) -> __m256i { + transmute(vpmovuswb( + a.as_u16x32(), + _mm256_setzero_si256().as_u8x32(), + k, + )) +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtusepi16_epi8&expand=2039) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm256_cvtusepi16_epi8(a: __m256i) -> __m128i { + transmute(vpmovuswb256( + a.as_u16x16(), + _mm_setzero_si128().as_u8x16(), + 0b11111111_11111111, + )) +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi16_epi8&expand=2040) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm256_mask_cvtusepi16_epi8(src: __m128i, k: __mmask16, a: __m256i) -> __m128i { + transmute(vpmovuswb256(a.as_u16x16(), src.as_u8x16(), k)) +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtusepi16_epi8&expand=2041) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm256_maskz_cvtusepi16_epi8(k: __mmask16, a: __m256i) -> __m128i { + transmute(vpmovuswb256( + a.as_u16x16(), + _mm_setzero_si128().as_u8x16(), + k, + )) +} + /// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi16_epi8&expand=2042) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtusepi16_epi8&expand=2036) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpmovuswb))] -pub unsafe fn _mm512_cvtusepi16_epi8(a: __m512i) -> __m256i { - transmute(vpmovuswb( - a.as_u16x32(), - _mm256_setzero_si256().as_u8x32(), - 0b11111111_11111111_11111111_11111111, +pub unsafe fn _mm_cvtusepi16_epi8(a: __m128i) -> __m128i { + transmute(vpmovuswb128( + a.as_u16x8(), + _mm_setzero_si128().as_u8x16(), + 0b11111111, )) } /// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi16_epi8&expand=2043) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi16_epi8&expand=2037) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpmovuswb))] -pub unsafe fn _mm512_mask_cvtusepi16_epi8(src: __m256i, k: __mmask32, a: __m512i) -> __m256i { - transmute(vpmovuswb(a.as_u16x32(), src.as_u8x32(), k)) +pub unsafe fn _mm_mask_cvtusepi16_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovuswb128(a.as_u16x8(), src.as_u8x16(), k)) } /// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi16_epi8&expand=2044) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtusepi16_epi8&expand=2038) #[inline] -#[target_feature(enable = "avx512bw")] +#[target_feature(enable = "avx512bw,avx512vl")] #[cfg_attr(test, assert_instr(vpmovuswb))] -pub unsafe fn _mm512_maskz_cvtusepi16_epi8(k: __mmask32, a: __m512i) -> __m256i { - transmute(vpmovuswb( - a.as_u16x32(), - _mm256_setzero_si256().as_u8x32(), +pub unsafe fn _mm_maskz_cvtusepi16_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovuswb128( + a.as_u16x8(), + _mm_setzero_si128().as_u8x16(), k, )) } @@ -6860,6 +8956,58 @@ pub unsafe fn _mm512_maskz_cvtepi8_epi16(k: __mmask32, a: __m256i) -> __m512i { )) } +/// Sign extend packed 8-bit integers in a to packed 16-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi8_epi16&expand=1524) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbw))] +pub unsafe fn _mm256_mask_cvtepi8_epi16(src: __m256i, k: __mmask16, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi8_epi16(a).as_i16x16(); + transmute(simd_select_bitmask(k, convert, src.as_i16x16())) +} + +/// Sign extend packed 8-bit integers in a to packed 16-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi8_epi16&expand=1525) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbw))] +pub unsafe fn _mm256_maskz_cvtepi8_epi16(k: __mmask16, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi8_epi16(a).as_i16x16(); + transmute(simd_select_bitmask( + k, + convert, + _mm256_setzero_si256().as_i16x16(), + )) +} + +/// Sign extend packed 8-bit integers in a to packed 16-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi8_epi16&expand=1521) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbw))] +pub unsafe fn _mm_mask_cvtepi8_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi8_epi16(a).as_i16x8(); + transmute(simd_select_bitmask(k, convert, src.as_i16x8())) +} + +/// Sign extend packed 8-bit integers in a to packed 16-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi8_epi16&expand=1522) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbw))] +pub unsafe fn _mm_maskz_cvtepi8_epi16(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi8_epi16(a).as_i16x8(); + transmute(simd_select_bitmask( + k, + convert, + _mm_setzero_si128().as_i16x8(), + )) +} + /// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers, and store the results in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu8_epi16&expand=1612) @@ -6897,6 +9045,58 @@ pub unsafe fn _mm512_maskz_cvtepu8_epi16(k: __mmask32, a: __m256i) -> __m512i { )) } +/// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepu8_epi16&expand=1610) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbw))] +pub unsafe fn _mm256_mask_cvtepu8_epi16(src: __m256i, k: __mmask16, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu8_epi16(a).as_i16x16(); + transmute(simd_select_bitmask(k, convert, src.as_i16x16())) +} + +/// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepu8_epi16&expand=1611) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbw))] +pub unsafe fn _mm256_maskz_cvtepu8_epi16(k: __mmask16, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu8_epi16(a).as_i16x16(); + transmute(simd_select_bitmask( + k, + convert, + _mm256_setzero_si256().as_i16x16(), + )) +} + +/// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepu8_epi16&expand=1607) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbw))] +pub unsafe fn _mm_mask_cvtepu8_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu8_epi16(a).as_i16x8(); + transmute(simd_select_bitmask(k, convert, src.as_i16x8())) +} + +/// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepu8_epi16&expand=1608) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbw))] +pub unsafe fn _mm_maskz_cvtepu8_epi16(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu8_epi16(a).as_i16x8(); + transmute(simd_select_bitmask( + k, + convert, + _mm_setzero_si128().as_i16x8(), + )) +} + /// Shift 128-bit lanes in a left by imm8 bytes while shifting in zeros, and store the results in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_bslli_epi128&expand=591) @@ -7076,122 +9276,206 @@ pub unsafe fn _mm512_mask_alignr_epi8( b: __m512i, imm8: i32, ) -> __m512i { - // If palignr is shifting the pair of vectors more than the size of two - // lanes, emit zero. - if imm8 > 32 { - return _mm512_set1_epi8(0); + macro_rules! call { + ($imm8:expr) => { + _mm512_alignr_epi8(a, b, $imm8) + }; } - // If palignr is shifting the pair of input vectors more than one lane, - // but less than two lanes, convert to shifting in zeroes. - let (a, b, imm8) = if imm8 > 16 { - (_mm512_set1_epi8(0), a, imm8 - 16) - } else { - (a, b, imm8) - }; - let a = a.as_i8x64(); - let b = b.as_i8x64(); - #[rustfmt::skip] - macro_rules! shuffle { + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i8x64(), src.as_i8x64())) +} + +/// Concatenate pairs of 16-byte blocks in a and b into a 32-byte temporary result, shift the result right by imm8 bytes, and store the low 16 bytes in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_alignr_epi8&expand=265) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpalignr, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_maskz_alignr_epi8(k: __mmask64, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + macro_rules! call { ($imm8:expr) => { - simd_shuffle64( - b, - a, - [ - 0 + ($imm8+48), 1 + ($imm8+48), 2 + ($imm8+48), 3 + ($imm8+48), 4 + ($imm8+48), 5 + ($imm8+48), 6 + ($imm8+48), 7 + ($imm8+48), - 8 + ($imm8+48), 9 + ($imm8+48), 10 + ($imm8+48), 11 + ($imm8+48), 12 + ($imm8+48), 13 + ($imm8+48), 14 + ($imm8+48), 15 + ($imm8+48), - 16 + ($imm8+32), 17 + ($imm8+32), 18 + ($imm8+32), 19 + ($imm8+32), 20 + ($imm8+32), 21 + ($imm8+32), 22 + ($imm8+32), 23 + ($imm8+32), - 24 + ($imm8+32), 25 + ($imm8+32), 26 + ($imm8+32), 27 + ($imm8+32), 28 + ($imm8+32), 29 + ($imm8+32), 30 + ($imm8+32), 31 + ($imm8+32), - 32 + ($imm8+16), 33 + ($imm8+16), 34 + ($imm8+16), 35 + ($imm8+16), 36 + ($imm8+16), 37 + ($imm8+16), 38 + ($imm8+16), 39 + ($imm8+16), - 40 + ($imm8+16), 41 + ($imm8+16), 42 + ($imm8+16), 43 + ($imm8+16), 44 + ($imm8+16), 45 + ($imm8+16), 46 + ($imm8+16), 47 + ($imm8+16), - 48 + $imm8, 49 + $imm8, 50 + $imm8, 51 + $imm8, 52 + $imm8, 53 + $imm8, 54 + $imm8, 55 + $imm8, - 56 + $imm8, 57 + $imm8, 58 + $imm8, 59 + $imm8, 60 + $imm8, 61 + $imm8, 62 + $imm8, 63 + $imm8, - ], - ) + _mm512_alignr_epi8(a, b, $imm8) }; } - let r: i8x64 = match imm8 { - 0 => shuffle!(0), - 1 => shuffle!(1), - 2 => shuffle!(2), - 3 => shuffle!(3), - 4 => shuffle!(4), - 5 => shuffle!(5), - 6 => shuffle!(6), - 7 => shuffle!(7), - 8 => shuffle!(8), - 9 => shuffle!(9), - 10 => shuffle!(10), - 11 => shuffle!(11), - 12 => shuffle!(12), - 13 => shuffle!(13), - 14 => shuffle!(14), - 15 => shuffle!(15), - _ => shuffle!(16), - }; - transmute(simd_select_bitmask(k, r, src.as_i8x64())) + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i8x64(); + transmute(simd_select_bitmask(k, r.as_i8x64(), zero)) +} + +/// Concatenate pairs of 16-byte blocks in a and b into a 32-byte temporary result, shift the result right by imm8 bytes, and store the low 16 bytes in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_alignr_epi8&expand=261) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(4)] +#[cfg_attr(test, assert_instr(vpalignr, imm8 = 5))] +pub unsafe fn _mm256_mask_alignr_epi8( + src: __m256i, + k: __mmask32, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_alignr_epi8(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i8x32(), src.as_i8x32())) +} + +/// Concatenate pairs of 16-byte blocks in a and b into a 32-byte temporary result, shift the result right by imm8 bytes, and store the low 16 bytes in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_alignr_epi8&expand=262) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpalignr, imm8 = 5))] +pub unsafe fn _mm256_maskz_alignr_epi8(k: __mmask32, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_alignr_epi8(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask( + k, + r.as_i8x32(), + _mm256_setzero_si256().as_i8x32(), + )) +} + +/// Concatenate pairs of 16-byte blocks in a and b into a 32-byte temporary result, shift the result right by imm8 bytes, and store the low 16 bytes in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_alignr_epi8&expand=258) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(4)] +#[cfg_attr(test, assert_instr(vpalignr, imm8 = 5))] +pub unsafe fn _mm_mask_alignr_epi8( + src: __m128i, + k: __mmask16, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_alignr_epi8(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i8x16(), src.as_i8x16())) +} + +/// Concatenate pairs of 16-byte blocks in a and b into a 32-byte temporary result, shift the result right by imm8 bytes, and store the low 16 bytes in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_alignr_epi8&expand=259) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpalignr, imm8 = 5))] +pub unsafe fn _mm_maskz_alignr_epi8(k: __mmask16, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_alignr_epi8(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i8x16(); + transmute(simd_select_bitmask(k, r.as_i8x16(), zero)) +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi16_storeu_epi8&expand=1812) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm512_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask32, a: __m512i) { + vpmovswbmem(mem_addr as *mut i8, a.as_i16x32(), k); +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi16_storeu_epi8&expand=1811) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm256_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m256i) { + vpmovswbmem256(mem_addr as *mut i8, a.as_i16x16(), k); +} + +/// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi16_storeu_epi8&expand=1810) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovswb))] +pub unsafe fn _mm_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovswbmem128(mem_addr as *mut i8, a.as_i16x8(), k); +} + +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi16_storeu_epi8&expand=1412) +#[inline] +#[target_feature(enable = "avx512bw")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm512_mask_cvtepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask32, a: __m512i) { + vpmovwbmem(mem_addr as *mut i8, a.as_i16x32(), k); } -/// Concatenate pairs of 16-byte blocks in a and b into a 32-byte temporary result, shift the result right by imm8 bytes, and store the low 16 bytes in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_alignr_epi8&expand=265) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi16_storeu_epi8&expand=1411) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm256_mask_cvtepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m256i) { + vpmovwbmem256(mem_addr as *mut i8, a.as_i16x16(), k); +} + +/// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi16_storeu_epi8&expand=1410) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovwb))] +pub unsafe fn _mm_mask_cvtepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovwbmem128(mem_addr as *mut i8, a.as_i16x8(), k); +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi16_storeu_epi8&expand=2047) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(vpalignr, imm8 = 1))] -#[rustc_args_required_const(3)] -pub unsafe fn _mm512_maskz_alignr_epi8(k: __mmask64, a: __m512i, b: __m512i, imm8: i32) -> __m512i { - // If palignr is shifting the pair of vectors more than the size of two - // lanes, emit zero. - if imm8 > 32 { - return _mm512_set1_epi8(0); - } - // If palignr is shifting the pair of input vectors more than one lane, - // but less than two lanes, convert to shifting in zeroes. - let (a, b, imm8) = if imm8 > 16 { - (_mm512_set1_epi8(0), a, imm8 - 16) - } else { - (a, b, imm8) - }; - let a = a.as_i8x64(); - let b = b.as_i8x64(); - #[rustfmt::skip] - macro_rules! shuffle { - ($imm8:expr) => { - simd_shuffle64( - b, - a, - [ - 0 + ($imm8+48), 1 + ($imm8+48), 2 + ($imm8+48), 3 + ($imm8+48), 4 + ($imm8+48), 5 + ($imm8+48), 6 + ($imm8+48), 7 + ($imm8+48), - 8 + ($imm8+48), 9 + ($imm8+48), 10 + ($imm8+48), 11 + ($imm8+48), 12 + ($imm8+48), 13 + ($imm8+48), 14 + ($imm8+48), 15 + ($imm8+48), - 16 + ($imm8+32), 17 + ($imm8+32), 18 + ($imm8+32), 19 + ($imm8+32), 20 + ($imm8+32), 21 + ($imm8+32), 22 + ($imm8+32), 23 + ($imm8+32), - 24 + ($imm8+32), 25 + ($imm8+32), 26 + ($imm8+32), 27 + ($imm8+32), 28 + ($imm8+32), 29 + ($imm8+32), 30 + ($imm8+32), 31 + ($imm8+32), - 32 + ($imm8+16), 33 + ($imm8+16), 34 + ($imm8+16), 35 + ($imm8+16), 36 + ($imm8+16), 37 + ($imm8+16), 38 + ($imm8+16), 39 + ($imm8+16), - 40 + ($imm8+16), 41 + ($imm8+16), 42 + ($imm8+16), 43 + ($imm8+16), 44 + ($imm8+16), 45 + ($imm8+16), 46 + ($imm8+16), 47 + ($imm8+16), - 48 + $imm8, 49 + $imm8, 50 + $imm8, 51 + $imm8, 52 + $imm8, 53 + $imm8, 54 + $imm8, 55 + $imm8, - 56 + $imm8, 57 + $imm8, 58 + $imm8, 59 + $imm8, 60 + $imm8, 61 + $imm8, 62 + $imm8, 63 + $imm8, - ], - ) - }; - } - let r: i8x64 = match imm8 { - 0 => shuffle!(0), - 1 => shuffle!(1), - 2 => shuffle!(2), - 3 => shuffle!(3), - 4 => shuffle!(4), - 5 => shuffle!(5), - 6 => shuffle!(6), - 7 => shuffle!(7), - 8 => shuffle!(8), - 9 => shuffle!(9), - 10 => shuffle!(10), - 11 => shuffle!(11), - 12 => shuffle!(12), - 13 => shuffle!(13), - 14 => shuffle!(14), - 15 => shuffle!(15), - _ => shuffle!(16), - }; - transmute(simd_select_bitmask(k, r, _mm512_setzero_si512().as_i8x64())) +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm512_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask32, a: __m512i) { + vpmovuswbmem(mem_addr as *mut i8, a.as_i16x32(), k); +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi16_storeu_epi8&expand=2046) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm256_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m256i) { + vpmovuswbmem256(mem_addr as *mut i8, a.as_i16x16(), k); +} + +/// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi16_storeu_epi8&expand=2045) +#[inline] +#[target_feature(enable = "avx512bw,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovuswb))] +pub unsafe fn _mm_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovuswbmem128(mem_addr as *mut i8, a.as_i16x8(), k); } #[allow(improper_ctypes)] @@ -7261,12 +9545,31 @@ extern "C" { #[link_name = "llvm.x86.avx512.mask.ucmp.w.512"] fn vpcmpuw(a: u16x32, b: u16x32, op: i32, mask: u32) -> u32; + #[link_name = "llvm.x86.avx512.mask.ucmp.w.256"] + fn vpcmpuw256(a: u16x16, b: u16x16, op: i32, mask: u16) -> u16; + #[link_name = "llvm.x86.avx512.mask.ucmp.w.128"] + fn vpcmpuw128(a: u16x8, b: u16x8, op: i32, mask: u8) -> u8; + #[link_name = "llvm.x86.avx512.mask.ucmp.b.512"] fn vpcmpub(a: u8x64, b: u8x64, op: i32, mask: u64) -> u64; + #[link_name = "llvm.x86.avx512.mask.ucmp.b.256"] + fn vpcmpub256(a: u8x32, b: u8x32, op: i32, mask: u32) -> u32; + #[link_name = "llvm.x86.avx512.mask.ucmp.b.128"] + fn vpcmpub128(a: u8x16, b: u8x16, op: i32, mask: u16) -> u16; + #[link_name = "llvm.x86.avx512.mask.cmp.w.512"] fn vpcmpw(a: i16x32, b: i16x32, op: i32, mask: u32) -> u32; + #[link_name = "llvm.x86.avx512.mask.cmp.w.256"] + fn vpcmpw256(a: i16x16, b: i16x16, op: i32, mask: u16) -> u16; + #[link_name = "llvm.x86.avx512.mask.cmp.w.128"] + fn vpcmpw128(a: i16x8, b: i16x8, op: i32, mask: u8) -> u8; + #[link_name = "llvm.x86.avx512.mask.cmp.b.512"] fn vpcmpb(a: i8x64, b: i8x64, op: i32, mask: u64) -> u64; + #[link_name = "llvm.x86.avx512.mask.cmp.b.256"] + fn vpcmpb256(a: i8x32, b: i8x32, op: i32, mask: u32) -> u32; + #[link_name = "llvm.x86.avx512.mask.cmp.b.128"] + fn vpcmpb128(a: i8x16, b: i8x16, op: i32, mask: u16) -> u16; #[link_name = "llvm.x86.avx512.mask.pmaxu.w.512"] fn vpmaxuw(a: u16x32, b: u16x32) -> u16x32; @@ -7360,13 +9663,48 @@ extern "C" { #[link_name = "llvm.x86.avx512.psad.bw.512"] fn vpsadbw(a: u8x64, b: u8x64) -> u64x8; + #[link_name = "llvm.x86.avx512.dbpsadbw.512"] fn vdbpsadbw(a: u8x64, b: u8x64, imm8: i32) -> u16x32; + #[link_name = "llvm.x86.avx512.dbpsadbw.256"] + fn vdbpsadbw256(a: u8x32, b: u8x32, imm8: i32) -> u16x16; + #[link_name = "llvm.x86.avx512.dbpsadbw.128"] + fn vdbpsadbw128(a: u8x16, b: u8x16, imm8: i32) -> u16x8; #[link_name = "llvm.x86.avx512.mask.pmovs.wb.512"] fn vpmovswb(a: i16x32, src: i8x32, mask: u32) -> i8x32; + #[link_name = "llvm.x86.avx512.mask.pmovs.wb.256"] + fn vpmovswb256(a: i16x16, src: i8x16, mask: u16) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.wb.128"] + fn vpmovswb128(a: i16x8, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.wb.512"] fn vpmovuswb(a: u16x32, src: u8x32, mask: u32) -> u8x32; + #[link_name = "llvm.x86.avx512.mask.pmovus.wb.256"] + fn vpmovuswb256(a: u16x16, src: u8x16, mask: u16) -> u8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.wb.128"] + fn vpmovuswb128(a: u16x8, src: u8x16, mask: u8) -> u8x16; + + #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.512"] + fn vpmovswbmem(mem_addr: *mut i8, a: i16x32, mask: u32); + #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.256"] + fn vpmovswbmem256(mem_addr: *mut i8, a: i16x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.128"] + fn vpmovswbmem128(mem_addr: *mut i8, a: i16x8, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmov.wb.mem.512"] + fn vpmovwbmem(mem_addr: *mut i8, a: i16x32, mask: u32); + #[link_name = "llvm.x86.avx512.mask.pmov.wb.mem.256"] + fn vpmovwbmem256(mem_addr: *mut i8, a: i16x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmov.wb.mem.128"] + fn vpmovwbmem128(mem_addr: *mut i8, a: i16x8, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.512"] + fn vpmovuswbmem(mem_addr: *mut i8, a: i16x32, mask: u32); + #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.256"] + fn vpmovuswbmem256(mem_addr: *mut i8, a: i16x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.128"] + fn vpmovuswbmem128(mem_addr: *mut i8, a: i16x8, mask: u8); } #[cfg(test)] @@ -9835,6 +12173,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmplt_epu16_mask() { + let a = _mm256_set1_epi16(-2); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmplt_epu16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epu16_mask() { + let a = _mm256_set1_epi16(-2); + let b = _mm256_set1_epi16(-1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmplt_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmplt_epu16_mask() { + let a = _mm_set1_epi16(-2); + let b = _mm_set1_epi16(-1); + let m = _mm_cmplt_epu16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmplt_epu16_mask() { + let a = _mm_set1_epi16(-2); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmplt_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmplt_epu8_mask() { let a = _mm512_set1_epi8(-2); @@ -9858,6 +12230,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmplt_epu8_mask() { + let a = _mm256_set1_epi8(-2); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmplt_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epu8_mask() { + let a = _mm256_set1_epi8(-2); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmplt_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmplt_epu8_mask() { + let a = _mm_set1_epi8(-2); + let b = _mm_set1_epi8(-1); + let m = _mm_cmplt_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmplt_epu8_mask() { + let a = _mm_set1_epi8(-2); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmplt_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmplt_epi16_mask() { let a = _mm512_set1_epi16(-2); @@ -9875,6 +12281,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmplt_epi16_mask() { + let a = _mm256_set1_epi16(-2); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmplt_epi16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epi16_mask() { + let a = _mm256_set1_epi16(-2); + let b = _mm256_set1_epi16(-1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmplt_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmplt_epi16_mask() { + let a = _mm_set1_epi16(-2); + let b = _mm_set1_epi16(-1); + let m = _mm_cmplt_epi16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmplt_epi16_mask() { + let a = _mm_set1_epi16(-2); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmplt_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmplt_epi8_mask() { let a = _mm512_set1_epi8(-2); @@ -9898,6 +12338,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmplt_epi8_mask() { + let a = _mm256_set1_epi8(-2); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmplt_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epi8_mask() { + let a = _mm256_set1_epi8(-2); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmplt_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmplt_epi8_mask() { + let a = _mm_set1_epi8(-2); + let b = _mm_set1_epi8(-1); + let m = _mm_cmplt_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmplt_epi8_mask() { + let a = _mm_set1_epi8(-2); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmplt_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpgt_epu16_mask() { let a = _mm512_set1_epi16(2); @@ -9915,6 +12389,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpgt_epu16_mask() { + let a = _mm256_set1_epi16(2); + let b = _mm256_set1_epi16(1); + let m = _mm256_cmpgt_epu16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epu16_mask() { + let a = _mm256_set1_epi16(2); + let b = _mm256_set1_epi16(1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmpgt_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpgt_epu16_mask() { + let a = _mm_set1_epi16(2); + let b = _mm_set1_epi16(1); + let m = _mm_cmpgt_epu16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epu16_mask() { + let a = _mm_set1_epi16(2); + let b = _mm_set1_epi16(1); + let mask = 0b01010101; + let r = _mm_mask_cmpgt_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpgt_epu8_mask() { let a = _mm512_set1_epi8(2); @@ -9938,6 +12446,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpgt_epu8_mask() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(1); + let m = _mm256_cmpgt_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epu8_mask() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpgt_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpgt_epu8_mask() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(1); + let m = _mm_cmpgt_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epu8_mask() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpgt_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpgt_epi16_mask() { let a = _mm512_set1_epi16(2); @@ -9955,6 +12497,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpgt_epi16_mask() { + let a = _mm256_set1_epi16(2); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmpgt_epi16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epi16_mask() { + let a = _mm256_set1_epi16(2); + let b = _mm256_set1_epi16(-1); + let mask = 0b001010101_01010101; + let r = _mm256_mask_cmpgt_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpgt_epi16_mask() { + let a = _mm_set1_epi16(2); + let b = _mm_set1_epi16(-1); + let m = _mm_cmpgt_epi16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epi16_mask() { + let a = _mm_set1_epi16(2); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmpgt_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpgt_epi8_mask() { let a = _mm512_set1_epi8(2); @@ -9978,6 +12554,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpgt_epi8_mask() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmpgt_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epi8_mask() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpgt_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpgt_epi8_mask() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(-1); + let m = _mm_cmpgt_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epi8_mask() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpgt_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmple_epu16_mask() { let a = _mm512_set1_epi16(-1); @@ -9995,6 +12605,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmple_epu16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmple_epu16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmple_epu16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmple_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmple_epu16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let m = _mm_cmple_epu16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmple_epu16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmple_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmple_epu8_mask() { let a = _mm512_set1_epi8(-1); @@ -10006,16 +12650,50 @@ mod tests { ); } - #[simd_test(enable = "avx512bw")] - unsafe fn test_mm512_mask_cmple_epu8_mask() { - let a = _mm512_set1_epi8(-1); - let b = _mm512_set1_epi8(-1); - let mask = 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101; - let r = _mm512_mask_cmple_epu8_mask(mask, a, b); - assert_eq!( - r, - 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101 - ); + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_mask_cmple_epu8_mask() { + let a = _mm512_set1_epi8(-1); + let b = _mm512_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101; + let r = _mm512_mask_cmple_epu8_mask(mask, a, b); + assert_eq!( + r, + 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101 + ); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmple_epu8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmple_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmple_epu8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmple_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmple_epu8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let m = _mm_cmple_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmple_epu8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmple_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); } #[simd_test(enable = "avx512bw")] @@ -10035,6 +12713,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmple_epi16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmple_epi16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmple_epi16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmple_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmple_epi16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let m = _mm_cmple_epi16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmple_epi16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmple_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmple_epi8_mask() { let a = _mm512_set1_epi8(-1); @@ -10058,6 +12770,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmple_epi8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmple_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmple_epi8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmple_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmple_epi8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let m = _mm_cmple_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmple_epi8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmple_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpge_epu16_mask() { let a = _mm512_set1_epi16(1); @@ -10075,6 +12821,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpge_epu16_mask() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1); + let m = _mm256_cmpge_epu16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epu16_mask() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmpge_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpge_epu16_mask() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1); + let m = _mm_cmpge_epu16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpge_epu16_mask() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1); + let mask = 0b01010101; + let r = _mm_mask_cmpge_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpge_epu8_mask() { let a = _mm512_set1_epi8(1); @@ -10098,6 +12878,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpge_epu8_mask() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(1); + let m = _mm256_cmpge_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epu8_mask() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpge_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpge_epu8_mask() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(1); + let m = _mm_cmpge_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpge_epu8_mask() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpge_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpge_epi16_mask() { let a = _mm512_set1_epi16(-1); @@ -10115,6 +12929,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpge_epi16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmpge_epi16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epi16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmpge_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpge_epi16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let m = _mm_cmpge_epi16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpge_epi16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmpge_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpge_epi8_mask() { let a = _mm512_set1_epi8(-1); @@ -10138,6 +12986,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpge_epi8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmpge_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epi8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpge_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpge_epi8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let m = _mm_cmpge_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpge_epi8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpge_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpeq_epu16_mask() { let a = _mm512_set1_epi16(1); @@ -10155,6 +13037,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpeq_epu16_mask() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1); + let m = _mm256_cmpeq_epu16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epu16_mask() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmpeq_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpeq_epu16_mask() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1); + let m = _mm_cmpeq_epu16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epu16_mask() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1); + let mask = 0b01010101; + let r = _mm_mask_cmpeq_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpeq_epu8_mask() { let a = _mm512_set1_epi8(1); @@ -10178,6 +13094,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpeq_epu8_mask() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(1); + let m = _mm256_cmpeq_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epu8_mask() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpeq_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpeq_epu8_mask() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(1); + let m = _mm_cmpeq_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epu8_mask() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpeq_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpeq_epi16_mask() { let a = _mm512_set1_epi16(-1); @@ -10195,6 +13145,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpeq_epi16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmpeq_epi16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epi16_mask() { + let a = _mm256_set1_epi16(-1); + let b = _mm256_set1_epi16(-1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmpeq_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpeq_epi16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let m = _mm_cmpeq_epi16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epi16_mask() { + let a = _mm_set1_epi16(-1); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmpeq_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpeq_epi8_mask() { let a = _mm512_set1_epi8(-1); @@ -10218,6 +13202,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpeq_epi8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmpeq_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epi8_mask() { + let a = _mm256_set1_epi8(-1); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpeq_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpeq_epi8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let m = _mm_cmpeq_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epi8_mask() { + let a = _mm_set1_epi8(-1); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpeq_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpneq_epu16_mask() { let a = _mm512_set1_epi16(2); @@ -10235,6 +13253,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpneq_epu16_mask() { + let a = _mm256_set1_epi16(2); + let b = _mm256_set1_epi16(1); + let m = _mm256_cmpneq_epu16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epu16_mask() { + let a = _mm256_set1_epi16(2); + let b = _mm256_set1_epi16(1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmpneq_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpneq_epu16_mask() { + let a = _mm_set1_epi16(2); + let b = _mm_set1_epi16(1); + let m = _mm_cmpneq_epu16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epu16_mask() { + let a = _mm_set1_epi16(2); + let b = _mm_set1_epi16(1); + let mask = 0b01010101; + let r = _mm_mask_cmpneq_epu16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpneq_epu8_mask() { let a = _mm512_set1_epi8(2); @@ -10246,16 +13298,50 @@ mod tests { ); } - #[simd_test(enable = "avx512bw")] - unsafe fn test_mm512_mask_cmpneq_epu8_mask() { - let a = _mm512_set1_epi8(2); - let b = _mm512_set1_epi8(1); - let mask = 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101; - let r = _mm512_mask_cmpneq_epu8_mask(mask, a, b); - assert_eq!( - r, - 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101 - ); + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_mask_cmpneq_epu8_mask() { + let a = _mm512_set1_epi8(2); + let b = _mm512_set1_epi8(1); + let mask = 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101; + let r = _mm512_mask_cmpneq_epu8_mask(mask, a, b); + assert_eq!( + r, + 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101 + ); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpneq_epu8_mask() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(1); + let m = _mm256_cmpneq_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epu8_mask() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpneq_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpneq_epu8_mask() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(1); + let m = _mm_cmpneq_epu8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epu8_mask() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpneq_epu8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); } #[simd_test(enable = "avx512bw")] @@ -10275,6 +13361,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpneq_epi16_mask() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(-1); + let m = _mm256_cmpneq_epi16_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epi16_mask() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(-1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmpneq_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpneq_epi16_mask() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(-1); + let m = _mm_cmpneq_epi16_mask(a, b); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epi16_mask() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(-1); + let mask = 0b01010101; + let r = _mm_mask_cmpneq_epi16_mask(mask, a, b); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmpneq_epi8_mask() { let a = _mm512_set1_epi8(1); @@ -10298,6 +13418,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmpneq_epi8_mask() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(-1); + let m = _mm256_cmpneq_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epi8_mask() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(-1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmpneq_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmpneq_epi8_mask() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(-1); + let m = _mm_cmpneq_epi8_mask(a, b); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epi8_mask() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(-1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmpneq_epi8_mask(mask, a, b); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmp_epu16_mask() { let a = _mm512_set1_epi16(0); @@ -10315,6 +13469,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmp_epu16_mask() { + let a = _mm256_set1_epi16(0); + let b = _mm256_set1_epi16(1); + let m = _mm256_cmp_epu16_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmp_epu16_mask() { + let a = _mm256_set1_epi16(0); + let b = _mm256_set1_epi16(1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmp_epu16_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmp_epu16_mask() { + let a = _mm_set1_epi16(0); + let b = _mm_set1_epi16(1); + let m = _mm_cmp_epu16_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmp_epu16_mask() { + let a = _mm_set1_epi16(0); + let b = _mm_set1_epi16(1); + let mask = 0b01010101; + let r = _mm_mask_cmp_epu16_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmp_epu8_mask() { let a = _mm512_set1_epi8(0); @@ -10338,6 +13526,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmp_epu8_mask() { + let a = _mm256_set1_epi8(0); + let b = _mm256_set1_epi8(1); + let m = _mm256_cmp_epu8_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmp_epu8_mask() { + let a = _mm256_set1_epi8(0); + let b = _mm256_set1_epi8(1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmp_epu8_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmp_epu8_mask() { + let a = _mm_set1_epi8(0); + let b = _mm_set1_epi8(1); + let m = _mm_cmp_epu8_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmp_epu8_mask() { + let a = _mm_set1_epi8(0); + let b = _mm_set1_epi8(1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmp_epu8_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmp_epi16_mask() { let a = _mm512_set1_epi16(0); @@ -10355,6 +13577,40 @@ mod tests { assert_eq!(r, 0b01010101_01010101_01010101_01010101); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmp_epi16_mask() { + let a = _mm256_set1_epi16(0); + let b = _mm256_set1_epi16(1); + let m = _mm256_cmp_epi16_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmp_epi16_mask() { + let a = _mm256_set1_epi16(0); + let b = _mm256_set1_epi16(1); + let mask = 0b01010101_01010101; + let r = _mm256_mask_cmp_epi16_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmp_epi16_mask() { + let a = _mm_set1_epi16(0); + let b = _mm_set1_epi16(1); + let m = _mm_cmp_epi16_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmp_epi16_mask() { + let a = _mm_set1_epi16(0); + let b = _mm_set1_epi16(1); + let mask = 0b01010101; + let r = _mm_mask_cmp_epi16_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cmp_epi8_mask() { let a = _mm512_set1_epi8(0); @@ -10378,6 +13634,40 @@ mod tests { ); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cmp_epi8_mask() { + let a = _mm256_set1_epi8(0); + let b = _mm256_set1_epi8(1); + let m = _mm256_cmp_epi8_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111_11111111_11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cmp_epi8_mask() { + let a = _mm256_set1_epi8(0); + let b = _mm256_set1_epi8(1); + let mask = 0b01010101_01010101_01010101_01010101; + let r = _mm256_mask_cmp_epi8_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101_01010101_01010101_01010101); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cmp_epi8_mask() { + let a = _mm_set1_epi8(0); + let b = _mm_set1_epi8(1); + let m = _mm_cmp_epi8_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11111111_11111111); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cmp_epi8_mask() { + let a = _mm_set1_epi8(0); + let b = _mm_set1_epi8(1); + let mask = 0b01010101_01010101; + let r = _mm_mask_cmp_epi8_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b01010101_01010101); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_loadu_epi16() { #[rustfmt::skip] @@ -10388,6 +13678,22 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_loadu_epi16() { + let a: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let r = _mm256_loadu_epi16(&a[0]); + let e = _mm256_set_epi16(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_loadu_epi16() { + let a: [i16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; + let r = _mm_loadu_epi16(&a[0]); + let e = _mm_set_epi16(8, 7, 6, 5, 4, 3, 2, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_loadu_epi8() { #[rustfmt::skip] @@ -10400,6 +13706,24 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_loadu_epi8() { + #[rustfmt::skip] + let a: [i8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; + let r = _mm256_loadu_epi8(&a[0]); + #[rustfmt::skip] + let e = _mm256_set_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_loadu_epi8() { + let a: [i8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let r = _mm_loadu_epi8(&a[0]); + let e = _mm_set_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_storeu_epi16() { let a = _mm512_set1_epi16(9); @@ -10408,6 +13732,22 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_storeu_epi16() { + let a = _mm256_set1_epi16(9); + let mut r = _mm256_set1_epi32(0); + _mm256_storeu_epi16(&mut r as *mut _ as *mut i16, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_storeu_epi16() { + let a = _mm_set1_epi16(9); + let mut r = _mm_set1_epi32(0); + _mm_storeu_epi16(&mut r as *mut _ as *mut i16, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_storeu_epi8() { let a = _mm512_set1_epi8(9); @@ -10416,6 +13756,22 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_storeu_epi8() { + let a = _mm256_set1_epi8(9); + let mut r = _mm256_set1_epi32(0); + _mm256_storeu_epi8(&mut r as *mut _ as *mut i8, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_storeu_epi8() { + let a = _mm_set1_epi8(9); + let mut r = _mm_set1_epi32(0); + _mm_storeu_epi8(&mut r as *mut _ as *mut i8, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_madd_epi16() { let a = _mm512_set1_epi16(1); @@ -13137,6 +16493,46 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_shufflelo_epi16() { + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_mask_shufflelo_epi16(a, 0, a, 0b00_01_01_11); + assert_eq_m256i(r, a); + let r = _mm256_mask_shufflelo_epi16(a, 0b11111111_11111111, a, 0b00_01_01_11); + let e = _mm256_set_epi16(0, 1, 2, 3, 7, 6, 6, 4, 8, 9, 10, 11, 15, 14, 14, 12); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_shufflelo_epi16() { + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_shufflelo_epi16(0, a, 0b00_01_01_11); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shufflelo_epi16(0b11111111_11111111, a, 0b00_01_01_11); + let e = _mm256_set_epi16(0, 1, 2, 3, 7, 6, 6, 4, 8, 9, 10, 11, 15, 14, 14, 12); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_shufflelo_epi16() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_mask_shufflelo_epi16(a, 0, a, 0b00_01_01_11); + assert_eq_m128i(r, a); + let r = _mm_mask_shufflelo_epi16(a, 0b11111111, a, 0b00_01_01_11); + let e = _mm_set_epi16(0, 1, 2, 3, 7, 6, 6, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_shufflelo_epi16() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_maskz_shufflelo_epi16(0, a, 0b00_01_01_11); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shufflelo_epi16(0b11111111, a, 0b00_01_01_11); + let e = _mm_set_epi16(0, 1, 2, 3, 7, 6, 6, 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_shufflehi_epi16() { #[rustfmt::skip] @@ -13191,6 +16587,46 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_shufflehi_epi16() { + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_mask_shufflehi_epi16(a, 0, a, 0b00_01_01_11); + assert_eq_m256i(r, a); + let r = _mm256_mask_shufflehi_epi16(a, 0b11111111_11111111, a, 0b00_01_01_11); + let e = _mm256_set_epi16(3, 2, 2, 0, 4, 5, 6, 7, 11, 10, 10, 8, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_shufflehi_epi16() { + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_shufflehi_epi16(0, a, 0b00_01_01_11); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shufflehi_epi16(0b11111111_11111111, a, 0b00_01_01_11); + let e = _mm256_set_epi16(3, 2, 2, 0, 4, 5, 6, 7, 11, 10, 10, 8, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_shufflehi_epi16() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_mask_shufflehi_epi16(a, 0, a, 0b00_01_01_11); + assert_eq_m128i(r, a); + let r = _mm_mask_shufflehi_epi16(a, 0b11111111, a, 0b00_01_01_11); + let e = _mm_set_epi16(3, 2, 2, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_shufflehi_epi16() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_maskz_shufflehi_epi16(0, a, 0b00_01_01_11); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shufflehi_epi16(0b11111111, a, 0b00_01_01_11); + let e = _mm_set_epi16(3, 2, 2, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_shuffle_epi8() { #[rustfmt::skip] @@ -13224,35 +16660,92 @@ mod tests { a, b, ); - #[rustfmt::skip] - let e = _mm512_set_epi8(14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62); - assert_eq_m512i(r, e); + #[rustfmt::skip] + let e = _mm512_set_epi8(14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_maskz_shuffle_epi8() { + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let b = _mm512_set1_epi8(1); + let r = _mm512_maskz_shuffle_epi8(0, a, b); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shuffle_epi8( + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + a, + b, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8(14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_shuffle_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let b = _mm256_set1_epi8(1); + let r = _mm256_mask_shuffle_epi8(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_shuffle_epi8(a, 0b11111111_11111111_11111111_11111111, a, b); + #[rustfmt::skip] + let e = _mm256_set_epi8(14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let b = _mm256_set1_epi8(1); + let r = _mm256_maskz_shuffle_epi8(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shuffle_epi8(0b11111111_11111111_11111111_11111111, a, b); + #[rustfmt::skip] + let e = _mm256_set_epi8(14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_shuffle_epi8() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b = _mm_set1_epi8(1); + let r = _mm_mask_shuffle_epi8(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_shuffle_epi8(a, 0b11111111_11111111, a, b); + let e = _mm_set_epi8( + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + ); + assert_eq_m128i(r, e); } - #[simd_test(enable = "avx512bw")] - unsafe fn test_mm512_maskz_shuffle_epi8() { + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_shuffle_epi8() { #[rustfmt::skip] - let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); - let b = _mm512_set1_epi8(1); - let r = _mm512_maskz_shuffle_epi8(0, a, b); - assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_shuffle_epi8( - 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, - a, - b, + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let b = _mm_set1_epi8(1); + let r = _mm_maskz_shuffle_epi8(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shuffle_epi8(0b11111111_11111111, a, b); + let e = _mm_set_epi8( + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, ); - #[rustfmt::skip] - let e = _mm512_set_epi8(14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62); - assert_eq_m512i(r, e); + assert_eq_m128i(r, e); } #[simd_test(enable = "avx512bw")] @@ -13275,6 +16768,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_test_epi16_mask() { + let a = _mm256_set1_epi16(1 << 0); + let b = _mm256_set1_epi16(1 << 0 | 1 << 1); + let r = _mm256_test_epi16_mask(a, b); + let e: __mmask16 = 0b11111111_11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_test_epi16_mask() { + let a = _mm256_set1_epi16(1 << 0); + let b = _mm256_set1_epi16(1 << 0 | 1 << 1); + let r = _mm256_mask_test_epi16_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_test_epi16_mask(0b11111111_11111111, a, b); + let e: __mmask16 = 0b11111111_11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_test_epi16_mask() { + let a = _mm_set1_epi16(1 << 0); + let b = _mm_set1_epi16(1 << 0 | 1 << 1); + let r = _mm_test_epi16_mask(a, b); + let e: __mmask8 = 0b11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_test_epi16_mask() { + let a = _mm_set1_epi16(1 << 0); + let b = _mm_set1_epi16(1 << 0 | 1 << 1); + let r = _mm_mask_test_epi16_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_test_epi16_mask(0b11111111, a, b); + let e: __mmask8 = 0b11111111; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_test_epi8_mask() { let a = _mm512_set1_epi8(1 << 0); @@ -13301,6 +16834,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_test_epi8_mask() { + let a = _mm256_set1_epi8(1 << 0); + let b = _mm256_set1_epi8(1 << 0 | 1 << 1); + let r = _mm256_test_epi8_mask(a, b); + let e: __mmask32 = 0b11111111_11111111_11111111_11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_test_epi8_mask() { + let a = _mm256_set1_epi8(1 << 0); + let b = _mm256_set1_epi8(1 << 0 | 1 << 1); + let r = _mm256_mask_test_epi8_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_test_epi8_mask(0b11111111_11111111_11111111_11111111, a, b); + let e: __mmask32 = 0b11111111_11111111_11111111_11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_test_epi8_mask() { + let a = _mm_set1_epi8(1 << 0); + let b = _mm_set1_epi8(1 << 0 | 1 << 1); + let r = _mm_test_epi8_mask(a, b); + let e: __mmask16 = 0b11111111_11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_test_epi8_mask() { + let a = _mm_set1_epi8(1 << 0); + let b = _mm_set1_epi8(1 << 0 | 1 << 1); + let r = _mm_mask_test_epi8_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_test_epi8_mask(0b11111111_11111111, a, b); + let e: __mmask16 = 0b11111111_11111111; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_testn_epi16_mask() { let a = _mm512_set1_epi16(1 << 0); @@ -13321,6 +16894,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_testn_epi16_mask() { + let a = _mm256_set1_epi16(1 << 0); + let b = _mm256_set1_epi16(1 << 0 | 1 << 1); + let r = _mm256_testn_epi16_mask(a, b); + let e: __mmask16 = 0b00000000_00000000; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_testn_epi16_mask() { + let a = _mm256_set1_epi16(1 << 0); + let b = _mm256_set1_epi16(1 << 0 | 1 << 1); + let r = _mm256_mask_testn_epi16_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_testn_epi16_mask(0b11111111_11111111, a, b); + let e: __mmask16 = 0b00000000_00000000; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_testn_epi16_mask() { + let a = _mm_set1_epi16(1 << 0); + let b = _mm_set1_epi16(1 << 0 | 1 << 1); + let r = _mm_testn_epi16_mask(a, b); + let e: __mmask8 = 0b00000000; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_testn_epi16_mask() { + let a = _mm_set1_epi16(1 << 0); + let b = _mm_set1_epi16(1 << 0 | 1 << 1); + let r = _mm_mask_testn_epi16_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_testn_epi16_mask(0b11111111, a, b); + let e: __mmask8 = 0b00000000; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_testn_epi8_mask() { let a = _mm512_set1_epi8(1 << 0); @@ -13347,6 +16960,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_testn_epi8_mask() { + let a = _mm256_set1_epi8(1 << 0); + let b = _mm256_set1_epi8(1 << 0 | 1 << 1); + let r = _mm256_testn_epi8_mask(a, b); + let e: __mmask32 = 0b00000000_00000000_00000000_00000000; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_testn_epi8_mask() { + let a = _mm256_set1_epi8(1 << 0); + let b = _mm256_set1_epi8(1 << 0 | 1 << 1); + let r = _mm256_mask_testn_epi8_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_testn_epi8_mask(0b11111111_11111111_11111111_11111111, a, b); + let e: __mmask32 = 0b00000000_00000000_00000000_00000000; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_testn_epi8_mask() { + let a = _mm_set1_epi8(1 << 0); + let b = _mm_set1_epi8(1 << 0 | 1 << 1); + let r = _mm_testn_epi8_mask(a, b); + let e: __mmask16 = 0b00000000_00000000; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_testn_epi8_mask() { + let a = _mm_set1_epi8(1 << 0); + let b = _mm_set1_epi8(1 << 0 | 1 << 1); + let r = _mm_mask_testn_epi8_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_testn_epi8_mask(0b11111111_11111111, a, b); + let e: __mmask16 = 0b00000000_00000000; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_store_mask64() { let a: __mmask64 = @@ -13423,6 +17076,70 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_dbsad_epu8() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(4); + let r = _mm256_dbsad_epu8(a, b, 0); + let e = _mm256_set1_epi16(8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_dbsad_epu8() { + let src = _mm256_set1_epi16(1); + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(4); + let r = _mm256_mask_dbsad_epu8(src, 0, a, b, 0); + assert_eq_m256i(r, src); + let r = _mm256_mask_dbsad_epu8(src, 0b11111111_11111111, a, b, 0); + let e = _mm256_set1_epi16(8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_dbsad_epu8() { + let a = _mm256_set1_epi8(2); + let b = _mm256_set1_epi8(4); + let r = _mm256_maskz_dbsad_epu8(0, a, b, 0); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_dbsad_epu8(0b11111111_11111111, a, b, 0); + let e = _mm256_set1_epi16(8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_dbsad_epu8() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(4); + let r = _mm_dbsad_epu8(a, b, 0); + let e = _mm_set1_epi16(8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_dbsad_epu8() { + let src = _mm_set1_epi16(1); + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(4); + let r = _mm_mask_dbsad_epu8(src, 0, a, b, 0); + assert_eq_m128i(r, src); + let r = _mm_mask_dbsad_epu8(src, 0b11111111, a, b, 0); + let e = _mm_set1_epi16(8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_dbsad_epu8() { + let a = _mm_set1_epi8(2); + let b = _mm_set1_epi8(4); + let r = _mm_maskz_dbsad_epu8(0, a, b, 0); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_dbsad_epu8(0b11111111, a, b, 0); + let e = _mm_set1_epi16(8); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_movepi16_mask() { let a = _mm512_set1_epi16(1 << 15); @@ -13431,6 +17148,22 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_movepi16_mask() { + let a = _mm256_set1_epi16(1 << 15); + let r = _mm256_movepi16_mask(a); + let e: __mmask16 = 0b11111111_11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_movepi16_mask() { + let a = _mm_set1_epi16(1 << 15); + let r = _mm_movepi16_mask(a); + let e: __mmask8 = 0b11111111; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_movepi8_mask() { let a = _mm512_set1_epi8(1 << 7); @@ -13440,6 +17173,22 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_movepi8_mask() { + let a = _mm256_set1_epi8(1 << 7); + let r = _mm256_movepi8_mask(a); + let e: __mmask32 = 0b11111111_11111111_11111111_11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_movepi8_mask() { + let a = _mm_set1_epi8(1 << 7); + let r = _mm_movepi8_mask(a); + let e: __mmask16 = 0b11111111_11111111; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_movm_epi16() { let a: __mmask32 = 0b11111111_11111111_11111111_11111111; @@ -13465,6 +17214,56 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_movm_epi16() { + let a: __mmask16 = 0b11111111_11111111; + let r = _mm256_movm_epi16(a); + let e = _mm256_set1_epi16( + 1 << 15 + | 1 << 14 + | 1 << 13 + | 1 << 12 + | 1 << 11 + | 1 << 10 + | 1 << 9 + | 1 << 8 + | 1 << 7 + | 1 << 6 + | 1 << 5 + | 1 << 4 + | 1 << 3 + | 1 << 2 + | 1 << 1 + | 1 << 0, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_movm_epi16() { + let a: __mmask8 = 0b11111111; + let r = _mm_movm_epi16(a); + let e = _mm_set1_epi16( + 1 << 15 + | 1 << 14 + | 1 << 13 + | 1 << 12 + | 1 << 11 + | 1 << 10 + | 1 << 9 + | 1 << 8 + | 1 << 7 + | 1 << 6 + | 1 << 5 + | 1 << 4 + | 1 << 3 + | 1 << 2 + | 1 << 1 + | 1 << 0, + ); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_movm_epi8() { let a: __mmask64 = @@ -13475,6 +17274,24 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_movm_epi8() { + let a: __mmask32 = 0b11111111_11111111_11111111_11111111; + let r = _mm256_movm_epi8(a); + let e = + _mm256_set1_epi8(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_movm_epi8() { + let a: __mmask16 = 0b11111111_11111111; + let r = _mm_movm_epi8(a); + let e = + _mm_set1_epi8(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_kadd_mask32() { let a: __mmask32 = 11; @@ -13624,25 +17441,83 @@ mod tests { assert_eq_m256i(r, e); } - #[simd_test(enable = "avx512bw")] - unsafe fn test_mm512_mask_cvtepi16_epi8() { - let src = _mm256_set1_epi8(1); - let a = _mm512_set1_epi16(2); - let r = _mm512_mask_cvtepi16_epi8(src, 0, a); - assert_eq_m256i(r, src); - let r = _mm512_mask_cvtepi16_epi8(src, 0b11111111_11111111_11111111_11111111, a); - let e = _mm256_set1_epi8(2); - assert_eq_m256i(r, e); + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_mask_cvtepi16_epi8() { + let src = _mm256_set1_epi8(1); + let a = _mm512_set1_epi16(2); + let r = _mm512_mask_cvtepi16_epi8(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm512_mask_cvtepi16_epi8(src, 0b11111111_11111111_11111111_11111111, a); + let e = _mm256_set1_epi8(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_maskz_cvtepi16_epi8() { + let a = _mm512_set1_epi16(2); + let r = _mm512_maskz_cvtepi16_epi8(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm512_maskz_cvtepi16_epi8(0b11111111_11111111_11111111_11111111, a); + let e = _mm256_set1_epi8(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cvtepi16_epi8() { + let a = _mm256_set1_epi16(2); + let r = _mm256_cvtepi16_epi8(a); + let e = _mm_set1_epi8(2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtepi16_epi8() { + let src = _mm_set1_epi8(1); + let a = _mm256_set1_epi16(2); + let r = _mm256_mask_cvtepi16_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtepi16_epi8(src, 0b11111111_11111111, a); + let e = _mm_set1_epi8(2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi16_epi8() { + let a = _mm256_set1_epi16(2); + let r = _mm256_maskz_cvtepi16_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtepi16_epi8(0b11111111_11111111, a); + let e = _mm_set1_epi8(2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cvtepi16_epi8() { + let a = _mm_set1_epi16(2); + let r = _mm_cvtepi16_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtepi16_epi8() { + let src = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm_set1_epi16(2); + let r = _mm_mask_cvtepi16_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi16_epi8(src, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m128i(r, e); } - #[simd_test(enable = "avx512bw")] - unsafe fn test_mm512_maskz_cvtepi16_epi8() { - let a = _mm512_set1_epi16(2); - let r = _mm512_maskz_cvtepi16_epi8(0, a); - assert_eq_m256i(r, _mm256_setzero_si256()); - let r = _mm512_maskz_cvtepi16_epi8(0b11111111_11111111_11111111_11111111, a); - let e = _mm256_set1_epi8(2); - assert_eq_m256i(r, e); + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_cvtepi16_epi8() { + let a = _mm_set1_epi16(2); + let r = _mm_maskz_cvtepi16_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi16_epi8(0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m128i(r, e); } #[simd_test(enable = "avx512bw")] @@ -13664,6 +17539,67 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cvtsepi16_epi8() { + let a = _mm256_set1_epi16(i16::MAX); + let r = _mm256_cvtsepi16_epi8(a); + let e = _mm_set1_epi8(i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi16_epi8() { + let src = _mm_set1_epi8(1); + let a = _mm256_set1_epi16(i16::MAX); + let r = _mm256_mask_cvtsepi16_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtsepi16_epi8(src, 0b11111111_11111111, a); + let e = _mm_set1_epi8(i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_cvtsepi16_epi8() { + let a = _mm256_set1_epi16(i16::MAX); + let r = _mm256_maskz_cvtsepi16_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtsepi16_epi8(0b11111111_11111111, a); + let e = _mm_set1_epi8(i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cvtsepi16_epi8() { + let a = _mm_set1_epi16(i16::MAX); + let r = _mm_cvtsepi16_epi8(a); + #[rustfmt::skip] + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtsepi16_epi8() { + let src = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm_set1_epi16(i16::MAX); + let r = _mm_mask_cvtsepi16_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtsepi16_epi8(src, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_cvtsepi16_epi8() { + let a = _mm_set1_epi16(i16::MAX); + let r = _mm_maskz_cvtsepi16_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtsepi16_epi8(0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_maskz_cvtsepi16_epi8() { let a = _mm512_set1_epi16(i16::MAX); @@ -13703,6 +17639,64 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_cvtusepi16_epi8() { + let a = _mm256_set1_epi16(i16::MIN); + let r = _mm256_cvtusepi16_epi8(a); + let e = _mm_set1_epi8(-1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi16_epi8() { + let src = _mm_set1_epi8(1); + let a = _mm256_set1_epi16(i16::MIN); + let r = _mm256_mask_cvtusepi16_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtusepi16_epi8(src, 0b11111111_11111111, a); + let e = _mm_set1_epi8(-1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_cvtusepi16_epi8() { + let a = _mm256_set1_epi16(i16::MIN); + let r = _mm256_maskz_cvtusepi16_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtusepi16_epi8(0b11111111_11111111, a); + let e = _mm_set1_epi8(-1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_cvtusepi16_epi8() { + let a = _mm_set1_epi16(i16::MIN); + let r = _mm_cvtusepi16_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtusepi16_epi8() { + let src = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm_set1_epi16(i16::MIN); + let r = _mm_mask_cvtusepi16_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtusepi16_epi8(src, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_cvtusepi16_epi8() { + let a = _mm_set1_epi16(i16::MIN); + let r = _mm_maskz_cvtusepi16_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtusepi16_epi8(0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cvtepi8_epi16() { let a = _mm256_set1_epi8(2); @@ -13732,6 +17726,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtepi8_epi16() { + let src = _mm256_set1_epi16(1); + let a = _mm_set1_epi8(2); + let r = _mm256_mask_cvtepi8_epi16(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepi8_epi16(src, 0b11111111_11111111, a); + let e = _mm256_set1_epi16(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi8_epi16() { + let a = _mm_set1_epi8(2); + let r = _mm256_maskz_cvtepi8_epi16(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepi8_epi16(0b11111111_11111111, a); + let e = _mm256_set1_epi16(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtepi8_epi16() { + let src = _mm_set1_epi16(1); + let a = _mm_set1_epi8(2); + let r = _mm_mask_cvtepi8_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi8_epi16(src, 0b11111111, a); + let e = _mm_set1_epi16(2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_cvtepi8_epi16() { + let a = _mm_set1_epi8(2); + let r = _mm_maskz_cvtepi8_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi8_epi16(0b11111111, a); + let e = _mm_set1_epi16(2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_cvtepu8_epi16() { let a = _mm256_set1_epi8(2); @@ -13761,6 +17797,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtepu8_epi16() { + let src = _mm256_set1_epi16(1); + let a = _mm_set1_epi8(2); + let r = _mm256_mask_cvtepu8_epi16(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepu8_epi16(src, 0b11111111_11111111, a); + let e = _mm256_set1_epi16(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_cvtepu8_epi16() { + let a = _mm_set1_epi8(2); + let r = _mm256_maskz_cvtepu8_epi16(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepu8_epi16(0b11111111_11111111, a); + let e = _mm256_set1_epi16(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtepu8_epi16() { + let src = _mm_set1_epi16(1); + let a = _mm_set1_epi8(2); + let r = _mm_mask_cvtepu8_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepu8_epi16(src, 0b11111111, a); + let e = _mm_set1_epi16(2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_cvtepu8_epi16() { + let a = _mm_set1_epi8(2); + let r = _mm_maskz_cvtepu8_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepu8_epi16(0b11111111, a); + let e = _mm_set1_epi16(2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_bslli_epi128() { #[rustfmt::skip] @@ -13878,4 +17956,167 @@ mod tests { ); assert_eq_m512i(r, e); } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_alignr_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8( + 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + ); + let b = _mm256_set1_epi8(1); + let r = _mm256_mask_alignr_epi8(a, 0, a, b, 14); + assert_eq_m256i(r, a); + let r = _mm256_mask_alignr_epi8(a, 0b11111111_11111111_11111111_11111111, a, b, 14); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_alignr_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8( + 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + ); + let b = _mm256_set1_epi8(1); + let r = _mm256_maskz_alignr_epi8(0, a, b, 14); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_alignr_epi8(0b11111111_11111111_11111111_11111111, a, b, 14); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_alignr_epi8() { + let a = _mm_set_epi8(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); + let b = _mm_set1_epi8(1); + let r = _mm_mask_alignr_epi8(a, 0, a, b, 14); + assert_eq_m128i(r, a); + let r = _mm_mask_alignr_epi8(a, 0b11111111_11111111, a, b, 14); + let e = _mm_set_epi8(0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_maskz_alignr_epi8() { + let a = _mm_set_epi8(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); + let b = _mm_set1_epi8(1); + let r = _mm_maskz_alignr_epi8(0, a, b, 14); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_alignr_epi8(0b11111111_11111111, a, b, 14); + let e = _mm_set_epi8(0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_mask_cvtsepi16_storeu_epi8() { + let a = _mm512_set1_epi16(i16::MAX); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtsepi16_storeu_epi8( + &mut r as *mut _ as *mut i8, + 0b11111111_11111111_11111111_11111111, + a, + ); + let e = _mm256_set1_epi8(i8::MAX); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi16_storeu_epi8() { + let a = _mm256_set1_epi16(i16::MAX); + let mut r = _mm_undefined_si128(); + _mm256_mask_cvtsepi16_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm_set1_epi8(i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtsepi16_storeu_epi8() { + let a = _mm_set1_epi16(i16::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtsepi16_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, 0, 0, 0, 0, + i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, i8::MAX, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_mask_cvtepi16_storeu_epi8() { + let a = _mm512_set1_epi16(8); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtepi16_storeu_epi8( + &mut r as *mut _ as *mut i8, + 0b11111111_11111111_11111111_11111111, + a, + ); + let e = _mm256_set1_epi8(8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtepi16_storeu_epi8() { + let a = _mm256_set1_epi16(8); + let mut r = _mm_undefined_si128(); + _mm256_mask_cvtepi16_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm_set1_epi8(8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtepi16_storeu_epi8() { + let a = _mm_set1_epi16(8); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtepi16_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw")] + unsafe fn test_mm512_mask_cvtusepi16_storeu_epi8() { + let a = _mm512_set1_epi16(i16::MAX); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtusepi16_storeu_epi8( + &mut r as *mut _ as *mut i8, + 0b11111111_11111111_11111111_11111111, + a, + ); + let e = _mm256_set1_epi8(u8::MAX as i8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi16_storeu_epi8() { + let a = _mm256_set1_epi16(i16::MAX); + let mut r = _mm_undefined_si128(); + _mm256_mask_cvtusepi16_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm_set1_epi8(u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512bw,avx512vl")] + unsafe fn test_mm_mask_cvtusepi16_storeu_epi8() { + let a = _mm_set1_epi16(i16::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtusepi16_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + ); + assert_eq_m128i(r, e); + } } diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 6a0426bd0b..f72f56a355 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -9,7 +9,7 @@ use stdarch_test::assert_instr; /// Computes the absolute values of packed 32-bit integers in `a`. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_epi32&expand=39) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpabsd))] @@ -26,7 +26,7 @@ pub unsafe fn _mm512_abs_epi32(a: __m512i) -> __m512i { /// unsigned results in `dst` using writemask `k` (elements are copied from /// `src` when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_epi32&expand=40) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpabsd))] @@ -39,7 +39,7 @@ pub unsafe fn _mm512_mask_abs_epi32(src: __m512i, k: __mmask16, a: __m512i) -> _ /// unsigned results in `dst` using zeromask `k` (elements are zeroed out when /// the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33,34,35,35&text=_mm512_maskz_abs_epi32) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_abs_epi32&expand=41) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpabsd))] @@ -49,9 +49,55 @@ pub unsafe fn _mm512_maskz_abs_epi32(k: __mmask16, a: __m512i) -> __m512i { transmute(simd_select_bitmask(k, abs, zero)) } +/// Compute the absolute value of packed signed 32-bit integers in a, and store the unsigned results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_abs_epi32&expand=37) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpabsd))] +pub unsafe fn _mm256_mask_abs_epi32(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + let abs = _mm256_abs_epi32(a).as_i32x8(); + transmute(simd_select_bitmask(k, abs, src.as_i32x8())) +} + +/// Compute the absolute value of packed signed 32-bit integers in a, and store the unsigned results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_abs_epi32&expand=38) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpabsd))] +pub unsafe fn _mm256_maskz_abs_epi32(k: __mmask8, a: __m256i) -> __m256i { + let abs = _mm256_abs_epi32(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, abs, zero)) +} + +/// Compute the absolute value of packed signed 32-bit integers in a, and store the unsigned results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_abs_epi32&expand=34) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpabsd))] +pub unsafe fn _mm_mask_abs_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let abs = _mm_abs_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, abs, src.as_i32x4())) +} + +/// Compute the absolute value of packed signed 32-bit integers in a, and store the unsigned results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_abs_epi32&expand=35) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpabsd))] +pub unsafe fn _mm_maskz_abs_epi32(k: __mmask8, a: __m128i) -> __m128i { + let abs = _mm_abs_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, abs, zero)) +} + /// Compute the absolute value of packed signed 64-bit integers in a, and store the unsigned results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_abs_epi64&expand=48) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_epi64&expand=48) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpabsq))] @@ -66,7 +112,7 @@ pub unsafe fn _mm512_abs_epi64(a: __m512i) -> __m512i { /// Compute the absolute value of packed signed 64-bit integers in a, and store the unsigned results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_abs_epi64&expand=49) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_epi64&expand=49) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpabsq))] @@ -77,7 +123,7 @@ pub unsafe fn _mm512_mask_abs_epi64(src: __m512i, k: __mmask8, a: __m512i) -> __ /// Compute the absolute value of packed signed 64-bit integers in a, and store the unsigned results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_abs_epi64&expand=50) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_abs_epi64&expand=50) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpabsq))] @@ -87,9 +133,47 @@ pub unsafe fn _mm512_maskz_abs_epi64(k: __mmask8, a: __m512i) -> __m512i { transmute(simd_select_bitmask(k, abs, zero)) } +/// Compute the absolute value of packed signed 64-bit integers in a, and store the unsigned results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_abs_epi64&expand=45) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpabsq))] +pub unsafe fn _mm256_abs_epi64(a: __m256i) -> __m256i { + let a = a.as_i64x4(); + // all-0 is a properly initialized i64x4 + let zero: i64x4 = mem::zeroed(); + let sub = simd_sub(zero, a); + let cmp: i64x4 = simd_gt(a, zero); + transmute(simd_select(cmp, a, sub)) +} + +/// Compute the absolute value of packed signed 64-bit integers in a, and store the unsigned results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_abs_epi64&expand=46) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpabsq))] +pub unsafe fn _mm256_mask_abs_epi64(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + let abs = _mm256_abs_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, abs, src.as_i64x4())) +} + +/// Compute the absolute value of packed signed 64-bit integers in a, and store the unsigned results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_abs_epi64&expand=45) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpabsq))] +pub unsafe fn _mm256_maskz_abs_epi64(k: __mmask8, a: __m256i) -> __m256i { + let abs = _mm256_abs_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, abs, zero)) +} + /// Finds the absolute value of each packed single-precision (32-bit) floating-point element in v2, storing the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_abs_ps&expand=65) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_ps&expand=65) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] @@ -102,7 +186,7 @@ pub unsafe fn _mm512_abs_ps(v2: __m512) -> __m512 { /// Finds the absolute value of each packed single-precision (32-bit) floating-point element in v2, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_abs_ps&expand=66) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_ps&expand=66) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandd))] @@ -113,7 +197,7 @@ pub unsafe fn _mm512_mask_abs_ps(src: __m512, k: __mmask16, v2: __m512) -> __m51 /// Finds the absolute value of each packed double-precision (64-bit) floating-point element in v2, storing the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_abs_pd&expand=60) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_pd&expand=60) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] @@ -126,7 +210,7 @@ pub unsafe fn _mm512_abs_pd(v2: __m512d) -> __m512d { /// Finds the absolute value of each packed double-precision (64-bit) floating-point element in v2, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_abs_pd&expand=61) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_abs_pd&expand=61) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] @@ -137,7 +221,7 @@ pub unsafe fn _mm512_mask_abs_pd(src: __m512d, k: __mmask8, v2: __m512d) -> __m5 /// Move packed 32-bit integers from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mov_epi32&expand=3801) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_epi32&expand=3801) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovdqa32))] @@ -148,7 +232,7 @@ pub unsafe fn _mm512_mask_mov_epi32(src: __m512i, k: __mmask16, a: __m512i) -> _ /// Move packed 32-bit integers from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mov_epi32&expand=3802) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_epi32&expand=3802) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovdqa32))] @@ -158,9 +242,55 @@ pub unsafe fn _mm512_maskz_mov_epi32(k: __mmask16, a: __m512i) -> __m512i { transmute(simd_select_bitmask(k, mov, zero)) } +/// Move packed 32-bit integers from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mov_epi32&expand=3799) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa32))] +pub unsafe fn _mm256_mask_mov_epi32(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + let mov = a.as_i32x8(); + transmute(simd_select_bitmask(k, mov, src.as_i32x8())) +} + +/// Move packed 32-bit integers from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mov_epi32&expand=3800) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa32))] +pub unsafe fn _mm256_maskz_mov_epi32(k: __mmask8, a: __m256i) -> __m256i { + let mov = a.as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, mov, zero)) +} + +/// Move packed 32-bit integers from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mov_epi32&expand=3797) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa32))] +pub unsafe fn _mm_mask_mov_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let mov = a.as_i32x4(); + transmute(simd_select_bitmask(k, mov, src.as_i32x4())) +} + +/// Move packed 32-bit integers from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mov_epi32&expand=3798) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa32))] +pub unsafe fn _mm_maskz_mov_epi32(k: __mmask8, a: __m128i) -> __m128i { + let mov = a.as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, mov, zero)) +} + /// Move packed 64-bit integers from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mov_epi64&expand=3807) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_epi64&expand=3807) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovdqa64))] @@ -171,7 +301,7 @@ pub unsafe fn _mm512_mask_mov_epi64(src: __m512i, k: __mmask8, a: __m512i) -> __ /// Move packed 64-bit integers from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mov_epi64&expand=3808) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_epi64&expand=3808) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovdqa64))] @@ -181,9 +311,55 @@ pub unsafe fn _mm512_maskz_mov_epi64(k: __mmask8, a: __m512i) -> __m512i { transmute(simd_select_bitmask(k, mov, zero)) } +/// Move packed 64-bit integers from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mov_epi64&expand=3805) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa64))] +pub unsafe fn _mm256_mask_mov_epi64(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + let mov = a.as_i64x4(); + transmute(simd_select_bitmask(k, mov, src.as_i64x4())) +} + +/// Move packed 64-bit integers from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mov_epi64&expand=3806) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa64))] +pub unsafe fn _mm256_maskz_mov_epi64(k: __mmask8, a: __m256i) -> __m256i { + let mov = a.as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, mov, zero)) +} + +/// Move packed 64-bit integers from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mov_epi64&expand=3803) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa64))] +pub unsafe fn _mm_mask_mov_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let mov = a.as_i64x2(); + transmute(simd_select_bitmask(k, mov, src.as_i64x2())) +} + +/// Move packed 64-bit integers from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mov_epi64&expand=3804) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa64))] +pub unsafe fn _mm_maskz_mov_epi64(k: __mmask8, a: __m128i) -> __m128i { + let mov = a.as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, mov, zero)) +} + /// Move packed single-precision (32-bit) floating-point elements from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mov_ps&expand=3825) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_ps&expand=3825) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] @@ -194,7 +370,7 @@ pub unsafe fn _mm512_mask_mov_ps(src: __m512, k: __mmask16, a: __m512) -> __m512 /// Move packed single-precision (32-bit) floating-point elements from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mov_ps&expand=3826) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_ps&expand=3826) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] @@ -204,9 +380,55 @@ pub unsafe fn _mm512_maskz_mov_ps(k: __mmask16, a: __m512) -> __m512 { transmute(simd_select_bitmask(k, mov, zero)) } +/// Move packed single-precision (32-bit) floating-point elements from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mov_ps&expand=3823) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] +pub unsafe fn _mm256_mask_mov_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + let mov = a.as_f32x8(); + transmute(simd_select_bitmask(k, mov, src.as_f32x8())) +} + +/// Move packed single-precision (32-bit) floating-point elements from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mov_ps&expand=3824) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] +pub unsafe fn _mm256_maskz_mov_ps(k: __mmask8, a: __m256) -> __m256 { + let mov = a.as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, mov, zero)) +} + +/// Move packed single-precision (32-bit) floating-point elements from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mov_ps&expand=3821) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] +pub unsafe fn _mm_mask_mov_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + let mov = a.as_f32x4(); + transmute(simd_select_bitmask(k, mov, src.as_f32x4())) +} + +/// Move packed single-precision (32-bit) floating-point elements from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mov_ps&expand=3822) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] +pub unsafe fn _mm_maskz_mov_ps(k: __mmask8, a: __m128) -> __m128 { + let mov = a.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, mov, zero)) +} + /// Move packed double-precision (64-bit) floating-point elements from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mov_pd&expand=3819) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mov_pd&expand=3819) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovapd))] @@ -217,7 +439,7 @@ pub unsafe fn _mm512_mask_mov_pd(src: __m512d, k: __mmask8, a: __m512d) -> __m51 /// Move packed double-precision (64-bit) floating-point elements from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mov_pd&expand=3820) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mov_pd&expand=3820) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovapd))] @@ -227,9 +449,55 @@ pub unsafe fn _mm512_maskz_mov_pd(k: __mmask8, a: __m512d) -> __m512d { transmute(simd_select_bitmask(k, mov, zero)) } +/// Move packed double-precision (64-bit) floating-point elements from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mov_pd&expand=3817) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovapd))] +pub unsafe fn _mm256_mask_mov_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + let mov = a.as_f64x4(); + transmute(simd_select_bitmask(k, mov, src.as_f64x4())) +} + +/// Move packed double-precision (64-bit) floating-point elements from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mov_pd&expand=3818) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovapd))] +pub unsafe fn _mm256_maskz_mov_pd(k: __mmask8, a: __m256d) -> __m256d { + let mov = a.as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, mov, zero)) +} + +/// Move packed double-precision (64-bit) floating-point elements from a to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mov_pd&expand=3815) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovapd))] +pub unsafe fn _mm_mask_mov_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + let mov = a.as_f64x2(); + transmute(simd_select_bitmask(k, mov, src.as_f64x2())) +} + +/// Move packed double-precision (64-bit) floating-point elements from a into dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mov_pd&expand=3816) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovapd))] +pub unsafe fn _mm_maskz_mov_pd(k: __mmask8, a: __m128d) -> __m128d { + let mov = a.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, mov, zero)) +} + /// Add packed 32-bit integers in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_add_epi32&expand=100) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_epi32&expand=100) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpaddd))] @@ -239,7 +507,7 @@ pub unsafe fn _mm512_add_epi32(a: __m512i, b: __m512i) -> __m512i { /// Add packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_add_epi32&expand=101) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_epi32&expand=101) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpaddd))] @@ -250,7 +518,7 @@ pub unsafe fn _mm512_mask_add_epi32(src: __m512i, k: __mmask16, a: __m512i, b: _ /// Add packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_add_epi32&expand=102) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_epi32&expand=102) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpaddd))] @@ -260,9 +528,55 @@ pub unsafe fn _mm512_maskz_add_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, add, zero)) } +/// Add packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_add_epi32&expand=98) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddd))] +pub unsafe fn _mm256_mask_add_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let add = _mm256_add_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, add, src.as_i32x8())) +} + +/// Add packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_add_epi32&expand=99) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddd))] +pub unsafe fn _mm256_maskz_add_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let add = _mm256_add_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, add, zero)) +} + +/// Add packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_epi32&expand=95) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddd))] +pub unsafe fn _mm_mask_add_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let add = _mm_add_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, add, src.as_i32x4())) +} + +/// Add packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_epi32&expand=96) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddd))] +pub unsafe fn _mm_maskz_add_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let add = _mm_add_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, add, zero)) +} + /// Add packed 64-bit integers in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_add_epi64&expand=109) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_epi64&expand=109) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpaddq))] @@ -272,7 +586,7 @@ pub unsafe fn _mm512_add_epi64(a: __m512i, b: __m512i) -> __m512i { /// Add packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_add_epi64&expand=110) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_epi64&expand=110) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpaddq))] @@ -283,7 +597,7 @@ pub unsafe fn _mm512_mask_add_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __ /// Add packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_add_epi64&expand=111) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_epi64&expand=111) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpaddq))] @@ -293,9 +607,55 @@ pub unsafe fn _mm512_maskz_add_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, add, zero)) } +/// Add packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_add_epi64&expand=107) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddq))] +pub unsafe fn _mm256_mask_add_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let add = _mm256_add_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, add, src.as_i64x4())) +} + +/// Add packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_add_epi64&expand=108) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddq))] +pub unsafe fn _mm256_maskz_add_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let add = _mm256_add_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, add, zero)) +} + +/// Add packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_epi64&expand=104) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddq))] +pub unsafe fn _mm_mask_add_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let add = _mm_add_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, add, src.as_i64x2())) +} + +/// Add packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_epi64&expand=105) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpaddq))] +pub unsafe fn _mm_maskz_add_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let add = _mm_add_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, add, zero)) +} + /// Add packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_add_ps&expand=139) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_ps&expand=139) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddps))] @@ -305,7 +665,7 @@ pub unsafe fn _mm512_add_ps(a: __m512, b: __m512) -> __m512 { /// Add packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_add_ps&expand=140) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_ps&expand=140) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddps))] @@ -316,7 +676,7 @@ pub unsafe fn _mm512_mask_add_ps(src: __m512, k: __mmask16, a: __m512, b: __m512 /// Add packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_add_ps&expand=141) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_ps&expand=141) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddps))] @@ -326,9 +686,55 @@ pub unsafe fn _mm512_maskz_add_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 transmute(simd_select_bitmask(k, add, zero)) } +/// Add packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_add_ps&expand=137) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddps))] +pub unsafe fn _mm256_mask_add_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let add = _mm256_add_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, add, src.as_f32x8())) +} + +/// Add packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_add_ps&expand=138) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddps))] +pub unsafe fn _mm256_maskz_add_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let add = _mm256_add_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, add, zero)) +} + +/// Add packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_ps&expand=134) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddps))] +pub unsafe fn _mm_mask_add_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let add = _mm_add_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, add, src.as_f32x4())) +} + +/// Add packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_ps&expand=135) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddps))] +pub unsafe fn _mm_maskz_add_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let add = _mm_add_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, add, zero)) +} + /// Add packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_add_pd&expand=127) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_pd&expand=127) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddpd))] @@ -338,7 +744,7 @@ pub unsafe fn _mm512_add_pd(a: __m512d, b: __m512d) -> __m512d { /// Add packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_add_pd&expand=128) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_pd&expand=128) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddpd))] @@ -349,7 +755,7 @@ pub unsafe fn _mm512_mask_add_pd(src: __m512d, k: __mmask8, a: __m512d, b: __m51 /// Add packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_add_pd&expand=129) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_pd&expand=129) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddpd))] @@ -359,9 +765,55 @@ pub unsafe fn _mm512_maskz_add_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m512 transmute(simd_select_bitmask(k, add, zero)) } +/// Add packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_add_pd&expand=125) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddpd))] +pub unsafe fn _mm256_mask_add_pd(src: __m256d, k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let add = _mm256_add_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, add, src.as_f64x4())) +} + +/// Add packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_add_pd&expand=126) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddpd))] +pub unsafe fn _mm256_maskz_add_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let add = _mm256_add_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, add, zero)) +} + +/// Add packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_add_pd&expand=122) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddpd))] +pub unsafe fn _mm_mask_add_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let add = _mm_add_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, add, src.as_f64x2())) +} + +/// Add packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_add_pd&expand=123) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vaddpd))] +pub unsafe fn _mm_maskz_add_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let add = _mm_add_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, add, zero)) +} + /// Subtract packed 32-bit integers in b from packed 32-bit integers in a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sub_epi32&expand=5694) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_epi32&expand=5694) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsubd))] @@ -371,7 +823,7 @@ pub unsafe fn _mm512_sub_epi32(a: __m512i, b: __m512i) -> __m512i { /// Subtract packed 32-bit integers in b from packed 32-bit integers in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sub_epi32&expand=5692) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_epi32&expand=5692) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsubd))] @@ -382,7 +834,7 @@ pub unsafe fn _mm512_mask_sub_epi32(src: __m512i, k: __mmask16, a: __m512i, b: _ /// Subtract packed 32-bit integers in b from packed 32-bit integers in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sub_epi32&expand=5693) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_epi32&expand=5693) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsubd))] @@ -392,9 +844,55 @@ pub unsafe fn _mm512_maskz_sub_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, sub, zero)) } +/// Subtract packed 32-bit integers in b from packed 32-bit integers in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sub_epi32&expand=5689) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubd))] +pub unsafe fn _mm256_mask_sub_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let sub = _mm256_sub_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, sub, src.as_i32x8())) +} + +/// Subtract packed 32-bit integers in b from packed 32-bit integers in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sub_epi32&expand=5690) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubd))] +pub unsafe fn _mm256_maskz_sub_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let sub = _mm256_sub_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, sub, zero)) +} + +/// Subtract packed 32-bit integers in b from packed 32-bit integers in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_epi32&expand=5686) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubd))] +pub unsafe fn _mm_mask_sub_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let sub = _mm_sub_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, sub, src.as_i32x4())) +} + +/// Subtract packed 32-bit integers in b from packed 32-bit integers in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_epi32&expand=5687) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubd))] +pub unsafe fn _mm_maskz_sub_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let sub = _mm_sub_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, sub, zero)) +} + /// Subtract packed 64-bit integers in b from packed 64-bit integers in a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sub_epi64&expand=5703) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_epi64&expand=5703) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsubq))] @@ -404,7 +902,7 @@ pub unsafe fn _mm512_sub_epi64(a: __m512i, b: __m512i) -> __m512i { /// Subtract packed 64-bit integers in b from packed 64-bit integers in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sub_epi64&expand=5701) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_epi64&expand=5701) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsubq))] @@ -415,19 +913,65 @@ pub unsafe fn _mm512_mask_sub_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __ /// Subtract packed 64-bit integers in b from packed 64-bit integers in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sub_epi64&expand=5702) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_epi64&expand=5702) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsubq))] pub unsafe fn _mm512_maskz_sub_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m512i { - let add = _mm512_sub_epi64(a, b).as_i64x8(); + let sub = _mm512_sub_epi64(a, b).as_i64x8(); let zero = _mm512_setzero_si512().as_i64x8(); - transmute(simd_select_bitmask(k, add, zero)) + transmute(simd_select_bitmask(k, sub, zero)) +} + +/// Subtract packed 64-bit integers in b from packed 64-bit integers in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sub_epi64&expand=5698) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubq))] +pub unsafe fn _mm256_mask_sub_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let sub = _mm256_sub_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, sub, src.as_i64x4())) +} + +/// Subtract packed 64-bit integers in b from packed 64-bit integers in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sub_epi64&expand=5699) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubq))] +pub unsafe fn _mm256_maskz_sub_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let sub = _mm256_sub_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, sub, zero)) +} + +/// Subtract packed 64-bit integers in b from packed 64-bit integers in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_epi64&expand=5695) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubq))] +pub unsafe fn _mm_mask_sub_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let sub = _mm_sub_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, sub, src.as_i64x2())) +} + +/// Subtract packed 64-bit integers in b from packed 64-bit integers in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_epi64&expand=5696) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsubq))] +pub unsafe fn _mm_maskz_sub_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let sub = _mm_sub_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, sub, zero)) } /// Subtract packed single-precision (32-bit) floating-point elements in b from packed single-precision (32-bit) floating-point elements in a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sub_ps&expand=5733) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_ps&expand=5733) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubps))] @@ -437,7 +981,7 @@ pub unsafe fn _mm512_sub_ps(a: __m512, b: __m512) -> __m512 { /// Subtract packed single-precision (32-bit) floating-point elements in b from packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sub_ps&expand=5731) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_ps&expand=5731) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubps))] @@ -448,7 +992,7 @@ pub unsafe fn _mm512_mask_sub_ps(src: __m512, k: __mmask16, a: __m512, b: __m512 /// Subtract packed single-precision (32-bit) floating-point elements in b from packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sub_ps&expand=5732) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_ps&expand=5732) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubps))] @@ -458,9 +1002,55 @@ pub unsafe fn _mm512_maskz_sub_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 transmute(simd_select_bitmask(k, sub, zero)) } +/// Subtract packed single-precision (32-bit) floating-point elements in b from packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sub_ps&expand=5728) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubps))] +pub unsafe fn _mm256_mask_sub_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let sub = _mm256_sub_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, sub, src.as_f32x8())) +} + +/// Subtract packed single-precision (32-bit) floating-point elements in b from packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sub_ps&expand=5729) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubps))] +pub unsafe fn _mm256_maskz_sub_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let sub = _mm256_sub_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, sub, zero)) +} + +/// Subtract packed single-precision (32-bit) floating-point elements in b from packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_ps&expand=5725) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubps))] +pub unsafe fn _mm_mask_sub_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let sub = _mm_sub_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, sub, src.as_f32x4())) +} + +/// Subtract packed single-precision (32-bit) floating-point elements in b from packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_ps&expand=5726) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubps))] +pub unsafe fn _mm_maskz_sub_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let sub = _mm_sub_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, sub, zero)) +} + /// Subtract packed double-precision (64-bit) floating-point elements in b from packed double-precision (64-bit) floating-point elements in a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sub_pd&expand=5721) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_pd&expand=5721) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubpd))] @@ -470,7 +1060,7 @@ pub unsafe fn _mm512_sub_pd(a: __m512d, b: __m512d) -> __m512d { /// Subtract packed double-precision (64-bit) floating-point elements in b from packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sub_pd&expand=5719) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_pd&expand=5719) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubpd))] @@ -481,7 +1071,7 @@ pub unsafe fn _mm512_mask_sub_pd(src: __m512d, k: __mmask8, a: __m512d, b: __m51 /// Subtract packed double-precision (64-bit) floating-point elements in b from packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sub_pd&expand=5720) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_pd&expand=5720) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubpd))] @@ -491,9 +1081,55 @@ pub unsafe fn _mm512_maskz_sub_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m512 transmute(simd_select_bitmask(k, sub, zero)) } +/// Subtract packed double-precision (64-bit) floating-point elements in b from packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sub_pd&expand=5716) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubpd))] +pub unsafe fn _mm256_mask_sub_pd(src: __m256d, k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let sub = _mm256_sub_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, sub, src.as_f64x4())) +} + +/// Subtract packed double-precision (64-bit) floating-point elements in b from packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sub_pd&expand=5717) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubpd))] +pub unsafe fn _mm256_maskz_sub_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let sub = _mm256_sub_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, sub, zero)) +} + +/// Subtract packed double-precision (64-bit) floating-point elements in b from packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sub_pd&expand=5713) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubpd))] +pub unsafe fn _mm_mask_sub_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let sub = _mm_sub_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, sub, src.as_f64x2())) +} + +/// Subtract packed double-precision (64-bit) floating-point elements in b from packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sub_pd&expand=5714) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsubpd))] +pub unsafe fn _mm_maskz_sub_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let sub = _mm_sub_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, sub, zero)) +} + /// Multiply the low signed 32-bit integers from each packed 64-bit element in a and b, and store the signed 64-bit results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mul_epi32&expand=3907) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_epi32&expand=3907) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmuldq))] @@ -503,7 +1139,7 @@ pub unsafe fn _mm512_mul_epi32(a: __m512i, b: __m512i) -> __m512i { /// Multiply the low signed 32-bit integers from each packed 64-bit element in a and b, and store the signed 64-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mul_epi32&expand=3905) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_epi32&expand=3905) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmuldq))] @@ -514,7 +1150,7 @@ pub unsafe fn _mm512_mask_mul_epi32(src: __m512i, k: __mmask8, a: __m512i, b: __ /// Multiply the low signed 32-bit integers from each packed 64-bit element in a and b, and store the signed 64-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mul_epi32&expand=3906) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_epi32&expand=3906) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmuldq))] @@ -524,9 +1160,55 @@ pub unsafe fn _mm512_maskz_mul_epi32(k: __mmask8, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, mul, zero)) } +/// Multiply the low signed 32-bit integers from each packed 64-bit element in a and b, and store the signed 64-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mul_epi32&expand=3902) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuldq))] +pub unsafe fn _mm256_mask_mul_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let mul = _mm256_mul_epi32(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, mul, src.as_i64x4())) +} + +/// Multiply the low signed 32-bit integers from each packed 64-bit element in a and b, and store the signed 64-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mul_epi32&expand=3903) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuldq))] +pub unsafe fn _mm256_maskz_mul_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let mul = _mm256_mul_epi32(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, mul, zero)) +} + +/// Multiply the low signed 32-bit integers from each packed 64-bit element in a and b, and store the signed 64-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_epi32&expand=3899) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuldq))] +pub unsafe fn _mm_mask_mul_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let mul = _mm_mul_epi32(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, mul, src.as_i64x2())) +} + +/// Multiply the low signed 32-bit integers from each packed 64-bit element in a and b, and store the signed 64-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_epi32&expand=3900) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuldq))] +pub unsafe fn _mm_maskz_mul_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let mul = _mm_mul_epi32(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, mul, zero)) +} + /// Multiply the packed 32-bit integers in a and b, producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mullo_epi&expand=4005) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mullo_epi&expand=4005) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmulld))] @@ -536,7 +1218,7 @@ pub unsafe fn _mm512_mullo_epi32(a: __m512i, b: __m512i) -> __m512i { /// Multiply the packed 32-bit integers in a and b, producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mullo_epi32&expand=4003) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mullo_epi32&expand=4003) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmulld))] @@ -552,7 +1234,7 @@ pub unsafe fn _mm512_mask_mullo_epi32( /// Multiply the packed 32-bit integers in a and b, producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mullo_epi32&expand=4004) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mullo_epi32&expand=4004) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmulld))] @@ -562,6 +1244,57 @@ pub unsafe fn _mm512_maskz_mullo_epi32(k: __mmask16, a: __m512i, b: __m512i) -> transmute(simd_select_bitmask(k, mul, zero)) } +/// Multiply the packed 32-bit integers in a and b, producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mullo_epi32&expand=4000) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmulld))] +pub unsafe fn _mm256_mask_mullo_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let mul = _mm256_mullo_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, mul, src.as_i32x8())) +} + +/// Multiply the packed 32-bit integers in a and b, producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mullo_epi32&expand=4001) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmulld))] +pub unsafe fn _mm256_maskz_mullo_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let mul = _mm256_mullo_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, mul, zero)) +} + +/// Multiply the packed 32-bit integers in a and b, producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mullo_epi32&expand=3997) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmulld))] +pub unsafe fn _mm_mask_mullo_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let mul = _mm_mullo_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, mul, src.as_i32x4())) +} + +/// Multiply the packed 32-bit integers in a and b, producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mullo_epi32&expand=3998) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmulld))] +pub unsafe fn _mm_maskz_mullo_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let mul = _mm_mullo_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, mul, zero)) +} + /// Multiplies elements in packed 64-bit integer vectors a and b together, storing the lower 64 bits of the result in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mullox_epi64&expand=4017) @@ -623,9 +1356,55 @@ pub unsafe fn _mm512_maskz_mul_epu32(k: __mmask8, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, mul, zero)) } +/// Multiply the low unsigned 32-bit integers from each packed 64-bit element in a and b, and store the unsigned 64-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mul_epu32&expand=3911) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuludq))] +pub unsafe fn _mm256_mask_mul_epu32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let mul = _mm256_mul_epu32(a, b).as_u64x4(); + transmute(simd_select_bitmask(k, mul, src.as_u64x4())) +} + +/// Multiply the low unsigned 32-bit integers from each packed 64-bit element in a and b, and store the unsigned 64-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mul_epu32&expand=3912) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuludq))] +pub unsafe fn _mm256_maskz_mul_epu32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let mul = _mm256_mul_epu32(a, b).as_u64x4(); + let zero = _mm256_setzero_si256().as_u64x4(); + transmute(simd_select_bitmask(k, mul, zero)) +} + +/// Multiply the low unsigned 32-bit integers from each packed 64-bit element in a and b, and store the unsigned 64-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_epu32&expand=3908) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuludq))] +pub unsafe fn _mm_mask_mul_epu32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let mul = _mm_mul_epu32(a, b).as_u64x2(); + transmute(simd_select_bitmask(k, mul, src.as_u64x2())) +} + +/// Multiply the low unsigned 32-bit integers from each packed 64-bit element in a and b, and store the unsigned 64-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_epu32&expand=3909) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmuludq))] +pub unsafe fn _mm_maskz_mul_epu32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let mul = _mm_mul_epu32(a, b).as_u64x2(); + let zero = _mm_setzero_si128().as_u64x2(); + transmute(simd_select_bitmask(k, mul, zero)) +} + /// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm512_mul_ps&expand=3934) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_ps&expand=3934) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulps))] @@ -633,9 +1412,9 @@ pub unsafe fn _mm512_mul_ps(a: __m512, b: __m512) -> __m512 { transmute(simd_mul(a.as_f32x16(), b.as_f32x16())) } -/// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). RM. +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mul_ps&expand=3932) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_ps&expand=3932) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulps))] @@ -646,7 +1425,7 @@ pub unsafe fn _mm512_mask_mul_ps(src: __m512, k: __mmask16, a: __m512, b: __m512 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mul_ps&expand=3933) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_ps&expand=3933) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulps))] @@ -656,9 +1435,55 @@ pub unsafe fn _mm512_maskz_mul_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 transmute(simd_select_bitmask(k, mul, zero)) } +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mul_ps&expand=3929) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulps))] +pub unsafe fn _mm256_mask_mul_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let mul = _mm256_mul_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, mul, src.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mul_ps&expand=3930) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulps))] +pub unsafe fn _mm256_maskz_mul_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let mul = _mm256_mul_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, mul, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_ps&expand=3926) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulps))] +pub unsafe fn _mm_mask_mul_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let mul = _mm_mul_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, mul, src.as_f32x4())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_ps&expand=3927) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulps))] +pub unsafe fn _mm_maskz_mul_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let mul = _mm_mul_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, mul, zero)) +} + /// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mul_pd&expand=3925) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_pd&expand=3925) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulpd))] @@ -666,9 +1491,9 @@ pub unsafe fn _mm512_mul_pd(a: __m512d, b: __m512d) -> __m512d { transmute(simd_mul(a.as_f64x8(), b.as_f64x8())) } -/// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). RM. +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mul_pd&expand=3923) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_pd&expand=3923) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulpd))] @@ -679,7 +1504,7 @@ pub unsafe fn _mm512_mask_mul_pd(src: __m512d, k: __mmask8, a: __m512d, b: __m51 /// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mul_pd&expand=3924) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_pd&expand=3924) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulpd))] @@ -689,36 +1514,128 @@ pub unsafe fn _mm512_maskz_mul_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m512 transmute(simd_select_bitmask(k, mul, zero)) } -/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst. +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_div_ps&expand=2162) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_mul_pd&expand=3920) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vdivps))] -pub unsafe fn _mm512_div_ps(a: __m512, b: __m512) -> __m512 { - transmute(simd_div(a.as_f32x16(), b.as_f32x16())) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulpd))] +pub unsafe fn _mm256_mask_mul_pd(src: __m256d, k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let mul = _mm256_mul_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, mul, src.as_f64x4())) } -/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_div_ps&expand=2163) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_mul_pd&expand=3921) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vdivps))] -pub unsafe fn _mm512_mask_div_ps(src: __m512, k: __mmask16, a: __m512, b: __m512) -> __m512 { - let div = _mm512_div_ps(a, b).as_f32x16(); - transmute(simd_select_bitmask(k, div, src.as_f32x16())) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulpd))] +pub unsafe fn _mm256_maskz_mul_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let mul = _mm256_mul_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, mul, zero)) } -/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_div_ps&expand=2164) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_mul_pd&expand=3917) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vdivps))] -pub unsafe fn _mm512_maskz_div_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 { - let div = _mm512_div_ps(a, b).as_f32x16(); - let zero = _mm512_setzero_ps().as_f32x16(); +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulpd))] +pub unsafe fn _mm_mask_mul_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let mul = _mm_mul_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, mul, src.as_f64x2())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_mul_pd&expand=3918) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmulpd))] +pub unsafe fn _mm_maskz_mul_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let mul = _mm_mul_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, mul, zero)) +} + +/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_div_ps&expand=2162) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vdivps))] +pub unsafe fn _mm512_div_ps(a: __m512, b: __m512) -> __m512 { + transmute(simd_div(a.as_f32x16(), b.as_f32x16())) +} + +/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_ps&expand=2163) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vdivps))] +pub unsafe fn _mm512_mask_div_ps(src: __m512, k: __mmask16, a: __m512, b: __m512) -> __m512 { + let div = _mm512_div_ps(a, b).as_f32x16(); + transmute(simd_select_bitmask(k, div, src.as_f32x16())) +} + +/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_ps&expand=2164) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vdivps))] +pub unsafe fn _mm512_maskz_div_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 { + let div = _mm512_div_ps(a, b).as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); + transmute(simd_select_bitmask(k, div, zero)) +} + +/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_div_ps&expand=2160) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivps))] +pub unsafe fn _mm256_mask_div_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let div = _mm256_div_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, div, src.as_f32x8())) +} + +/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_div_ps&expand=2161) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivps))] +pub unsafe fn _mm256_maskz_div_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let div = _mm256_div_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, div, zero)) +} + +/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_div_ps&expand=2157) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivps))] +pub unsafe fn _mm_mask_div_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let div = _mm_div_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, div, src.as_f32x4())) +} + +/// Divide packed single-precision (32-bit) floating-point elements in a by packed elements in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_div_ps&expand=2158) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivps))] +pub unsafe fn _mm_maskz_div_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let div = _mm_div_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); transmute(simd_select_bitmask(k, div, zero)) } @@ -734,7 +1651,7 @@ pub unsafe fn _mm512_div_pd(a: __m512d, b: __m512d) -> __m512d { /// Divide packed double-precision (64-bit) floating-point elements in a by packed elements in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_div_pd&expand=2154) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_pd&expand=2154) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivpd))] @@ -745,7 +1662,7 @@ pub unsafe fn _mm512_mask_div_pd(src: __m512d, k: __mmask8, a: __m512d, b: __m51 /// Divide packed double-precision (64-bit) floating-point elements in a by packed elements in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_div_pd&expand=2155) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_pd&expand=2155) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivpd))] @@ -755,9 +1672,55 @@ pub unsafe fn _mm512_maskz_div_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m512 transmute(simd_select_bitmask(k, div, zero)) } +/// Divide packed double-precision (64-bit) floating-point elements in a by packed elements in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_div_pd&expand=2151) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivpd))] +pub unsafe fn _mm256_mask_div_pd(src: __m256d, k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let div = _mm256_div_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, div, src.as_f64x4())) +} + +/// Divide packed double-precision (64-bit) floating-point elements in a by packed elements in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_div_pd&expand=2152) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivpd))] +pub unsafe fn _mm256_maskz_div_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let div = _mm256_div_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, div, zero)) +} + +/// Divide packed double-precision (64-bit) floating-point elements in a by packed elements in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_div_pd&expand=2148) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivpd))] +pub unsafe fn _mm_mask_div_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let div = _mm_div_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, div, src.as_f64x2())) +} + +/// Divide packed double-precision (64-bit) floating-point elements in a by packed elements in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_div_pd&expand=2149) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vdivpd))] +pub unsafe fn _mm_maskz_div_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let div = _mm_div_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, div, zero)) +} + /// Compare packed signed 32-bit integers in a and b, and store packed maximum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_max_epi32&expand=3582) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epi32&expand=3582) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxsd))] @@ -767,7 +1730,7 @@ pub unsafe fn _mm512_max_epi32(a: __m512i, b: __m512i) -> __m512i { /// Compare packed signed 32-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_epi32&expand=3580) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epi32&expand=3580) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxsd))] @@ -778,7 +1741,7 @@ pub unsafe fn _mm512_mask_max_epi32(src: __m512i, k: __mmask16, a: __m512i, b: _ /// Compare packed signed 32-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_epi32&expand=3581) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epi32&expand=3581) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxsd))] @@ -788,9 +1751,55 @@ pub unsafe fn _mm512_maskz_max_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, max, zero)) } +/// Compare packed signed 32-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_max_epi32&expand=3577) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsd))] +pub unsafe fn _mm256_mask_max_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, max, src.as_i32x8())) +} + +/// Compare packed signed 32-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_max_epi32&expand=3578) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsd))] +pub unsafe fn _mm256_maskz_max_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, max, zero)) +} + +/// Compare packed signed 32-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_epi32&expand=3574) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsd))] +pub unsafe fn _mm_mask_max_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, max, src.as_i32x4())) +} + +/// Compare packed signed 32-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_epi32&expand=3575) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsd))] +pub unsafe fn _mm_maskz_max_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, max, zero)) +} + /// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_max_epi64&expand=3591) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epi64&expand=3591) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxsq))] @@ -800,7 +1809,7 @@ pub unsafe fn _mm512_max_epi64(a: __m512i, b: __m512i) -> __m512i { /// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_epi64&expand=3589) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epi64&expand=3589) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxsq))] @@ -811,7 +1820,7 @@ pub unsafe fn _mm512_mask_max_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __ /// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_epi64&expand=3590) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epi64&expand=3590) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxsq))] @@ -821,9 +1830,75 @@ pub unsafe fn _mm512_maskz_max_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, max, zero)) } +/// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_max_epi64&expand=3588) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsq))] +pub unsafe fn _mm256_max_epi64(a: __m256i, b: __m256i) -> __m256i { + transmute(vpmaxsq256(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_max_epi64&expand=3586) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsq))] +pub unsafe fn _mm256_mask_max_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, max, src.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_max_epi64&expand=3587) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsq))] +pub unsafe fn _mm256_maskz_max_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, max, zero)) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epi64&expand=3585) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsq))] +pub unsafe fn _mm_max_epi64(a: __m128i, b: __m128i) -> __m128i { + transmute(vpmaxsq128(a.as_i64x2(), b.as_i64x2())) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_epi64&expand=3583) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsq))] +pub unsafe fn _mm_mask_max_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, max, src.as_i64x2())) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_epi64&expand=3584) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxsq))] +pub unsafe fn _mm_maskz_max_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, max, zero)) +} + /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_max_ps&expand=3655) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_ps&expand=3655) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxps))] @@ -837,7 +1912,7 @@ pub unsafe fn _mm512_max_ps(a: __m512, b: __m512) -> __m512 { /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_ps&expand=3653) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_ps&expand=3653) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxps))] @@ -848,7 +1923,7 @@ pub unsafe fn _mm512_mask_max_ps(src: __m512, k: __mmask16, a: __m512, b: __m512 /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_ps&expand=3654) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_ps&expand=3654) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxps))] @@ -858,9 +1933,55 @@ pub unsafe fn _mm512_maskz_max_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 transmute(simd_select_bitmask(k, max, zero)) } +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_max_ps&expand=3650) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxps))] +pub unsafe fn _mm256_mask_max_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let max = _mm256_max_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, max, src.as_f32x8())) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_max_ps&expand=3651) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxps))] +pub unsafe fn _mm256_maskz_max_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let max = _mm256_max_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, max, zero)) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_ps&expand=3647) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxps))] +pub unsafe fn _mm_mask_max_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let max = _mm_max_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, max, src.as_f32x4())) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_ps&expand=3648) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxps))] +pub unsafe fn _mm_maskz_max_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let max = _mm_max_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, max, zero)) +} + /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_max_pd&expand=3645) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_pd&expand=3645) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxpd))] @@ -870,7 +1991,7 @@ pub unsafe fn _mm512_max_pd(a: __m512d, b: __m512d) -> __m512d { /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_pd&expand=3643) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_pd&expand=3643) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxpd))] @@ -881,7 +2002,7 @@ pub unsafe fn _mm512_mask_max_pd(src: __m512d, k: __mmask8, a: __m512d, b: __m51 /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_pd&expand=3644) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_pd&expand=3644) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxpd))] @@ -891,9 +2012,55 @@ pub unsafe fn _mm512_maskz_max_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m512 transmute(simd_select_bitmask(k, max, zero)) } +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_max_pd&expand=3640) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxpd))] +pub unsafe fn _mm256_mask_max_pd(src: __m256d, k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let max = _mm256_max_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, max, src.as_f64x4())) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_max_pd&expand=3641) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxpd))] +pub unsafe fn _mm256_maskz_max_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let max = _mm256_max_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, max, zero)) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_pd&expand=3637) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxpd))] +pub unsafe fn _mm_mask_max_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let max = _mm_max_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, max, src.as_f64x2())) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_pd&expand=3638) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmaxpd))] +pub unsafe fn _mm_maskz_max_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let max = _mm_max_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, max, zero)) +} + /// Compare packed unsigned 32-bit integers in a and b, and store packed maximum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_max_epu32&expand=3618) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epu32&expand=3618) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxud))] @@ -903,7 +2070,7 @@ pub unsafe fn _mm512_max_epu32(a: __m512i, b: __m512i) -> __m512i { /// Compare packed unsigned 32-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_epu32&expand=3616) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epu32&expand=3616) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxud))] @@ -914,7 +2081,7 @@ pub unsafe fn _mm512_mask_max_epu32(src: __m512i, k: __mmask16, a: __m512i, b: _ /// Compare packed unsigned 32-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_epu32&expand=3617) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epu32&expand=3617) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxud))] @@ -924,9 +2091,55 @@ pub unsafe fn _mm512_maskz_max_epu32(k: __mmask16, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, max, zero)) } +/// Compare packed unsigned 32-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_max_epu32&expand=3613) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxud))] +pub unsafe fn _mm256_mask_max_epu32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epu32(a, b).as_u32x8(); + transmute(simd_select_bitmask(k, max, src.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_max_epu32&expand=3614) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxud))] +pub unsafe fn _mm256_maskz_max_epu32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epu32(a, b).as_u32x8(); + let zero = _mm256_setzero_si256().as_u32x8(); + transmute(simd_select_bitmask(k, max, zero)) +} + +/// Compare packed unsigned 32-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_epu32&expand=3610) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxud))] +pub unsafe fn _mm_mask_max_epu32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epu32(a, b).as_u32x4(); + transmute(simd_select_bitmask(k, max, src.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_epu32&expand=3611) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxud))] +pub unsafe fn _mm_maskz_max_epu32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epu32(a, b).as_u32x4(); + let zero = _mm_setzero_si128().as_u32x4(); + transmute(simd_select_bitmask(k, max, zero)) +} + /// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=max_epu64&expand=3627) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_epu64&expand=3627) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxuq))] @@ -936,7 +2149,7 @@ pub unsafe fn _mm512_max_epu64(a: __m512i, b: __m512i) -> __m512i { /// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_epu64&expand=3625) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_epu64&expand=3625) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxuq))] @@ -947,7 +2160,7 @@ pub unsafe fn _mm512_mask_max_epu64(src: __m512i, k: __mmask8, a: __m512i, b: __ /// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_epu&expand=3626) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_epu&expand=3626) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmaxuq))] @@ -957,9 +2170,75 @@ pub unsafe fn _mm512_maskz_max_epu64(k: __mmask8, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, max, zero)) } +/// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_max_epu64&expand=3624) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxuq))] +pub unsafe fn _mm256_max_epu64(a: __m256i, b: __m256i) -> __m256i { + transmute(vpmaxuq256(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_max_epu64&expand=3622) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxuq))] +pub unsafe fn _mm256_mask_max_epu64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epu64(a, b).as_u64x4(); + transmute(simd_select_bitmask(k, max, src.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_max_epu64&expand=3623) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxuq))] +pub unsafe fn _mm256_maskz_max_epu64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let max = _mm256_max_epu64(a, b).as_u64x4(); + let zero = _mm256_setzero_si256().as_u64x4(); + transmute(simd_select_bitmask(k, max, zero)) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu64&expand=3621) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxuq))] +pub unsafe fn _mm_max_epu64(a: __m128i, b: __m128i) -> __m128i { + transmute(vpmaxuq128(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_max_epu64&expand=3619) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxuq))] +pub unsafe fn _mm_mask_max_epu64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epu64(a, b).as_u64x2(); + transmute(simd_select_bitmask(k, max, src.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_max_epu64&expand=3620) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmaxuq))] +pub unsafe fn _mm_maskz_max_epu64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let max = _mm_max_epu64(a, b).as_u64x2(); + let zero = _mm_setzero_si128().as_u64x2(); + transmute(simd_select_bitmask(k, max, zero)) +} + /// Compare packed signed 32-bit integers in a and b, and store packed minimum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_epi32&expand=3696) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epi32&expand=3696) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminsd))] @@ -969,30 +2248,76 @@ pub unsafe fn _mm512_min_epi32(a: __m512i, b: __m512i) -> __m512i { /// Compare packed signed 32-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_min_epi32&expand=3694) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epi32&expand=3694) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminsd))] pub unsafe fn _mm512_mask_min_epi32(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epi32(a, b).as_i32x16(); - transmute(simd_select_bitmask(k, max, src.as_i32x16())) + let min = _mm512_min_epi32(a, b).as_i32x16(); + transmute(simd_select_bitmask(k, min, src.as_i32x16())) } /// Compare packed signed 32-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_min_epi32&expand=3695) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_epi32&expand=3695) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminsd))] pub unsafe fn _mm512_maskz_min_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epi32(a, b).as_i32x16(); + let min = _mm512_min_epi32(a, b).as_i32x16(); let zero = _mm512_setzero_si512().as_i32x16(); - transmute(simd_select_bitmask(k, max, zero)) + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed signed 32-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_min_epi32&expand=3691) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminsd))] +pub unsafe fn _mm256_mask_min_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, min, src.as_i32x8())) +} + +/// Compare packed signed 32-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_min_epi32&expand=3692) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminsd))] +pub unsafe fn _mm256_maskz_min_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed signed 32-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_epi32&expand=3688) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminsd))] +pub unsafe fn _mm_mask_min_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let min = _mm_min_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, min, src.as_i32x4())) +} + +/// Compare packed signed 32-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_epi32&expand=3689) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminsd))] +pub unsafe fn _mm_maskz_min_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let min = _mm_min_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, min, zero)) } /// Compare packed signed 64-bit integers in a and b, and store packed minimum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_epi64&expand=3705) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epi64&expand=3705) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminsq))] @@ -1002,13 +2327,13 @@ pub unsafe fn _mm512_min_epi64(a: __m512i, b: __m512i) -> __m512i { /// Compare packed signed 64-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_min_epi64&expand=3703) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epi64&expand=3703) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminsq))] pub unsafe fn _mm512_mask_min_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epi64(a, b).as_i64x8(); - transmute(simd_select_bitmask(k, max, src.as_i64x8())) + let min = _mm512_min_epi64(a, b).as_i64x8(); + transmute(simd_select_bitmask(k, min, src.as_i64x8())) } /// Compare packed signed 64-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -1018,14 +2343,47 @@ pub unsafe fn _mm512_mask_min_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __ #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminsq))] pub unsafe fn _mm512_maskz_min_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epi64(a, b).as_i64x8(); + let min = _mm512_min_epi64(a, b).as_i64x8(); let zero = _mm512_setzero_si512().as_i64x8(); - transmute(simd_select_bitmask(k, max, zero)) + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed minimum values in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_min_epi64&expand=3702) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminsq))] +pub unsafe fn _mm256_min_epi64(a: __m256i, b: __m256i) -> __m256i { + transmute(vpminsq256(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_min_epi64&expand=3700) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminsq))] +pub unsafe fn _mm256_mask_min_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, min, src.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_min_epi64&expand=3701) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminsq))] +pub unsafe fn _mm256_maskz_min_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, min, zero)) } /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_ps&expand=3769) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_ps&expand=3769) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminps))] @@ -1039,27 +2397,75 @@ pub unsafe fn _mm512_min_ps(a: __m512, b: __m512) -> __m512 { /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_min_ps&expand=3767) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_ps&expand=3767) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminps))] pub unsafe fn _mm512_mask_min_ps(src: __m512, k: __mmask16, a: __m512, b: __m512) -> __m512 { - let max = _mm512_min_ps(a, b).as_f32x16(); - transmute(simd_select_bitmask(k, max, src.as_f32x16())) + let min = _mm512_min_ps(a, b).as_f32x16(); + transmute(simd_select_bitmask(k, min, src.as_f32x16())) } /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_min_ps&expand=3768) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_ps&expand=3768) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminps))] pub unsafe fn _mm512_maskz_min_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 { - let max = _mm512_min_ps(a, b).as_f32x16(); + let min = _mm512_min_ps(a, b).as_f32x16(); let zero = _mm512_setzero_ps().as_f32x16(); - transmute(simd_select_bitmask(k, max, zero)) + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_min_ps&expand=3764) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminps))] +pub unsafe fn _mm256_mask_min_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let min = _mm256_min_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, min, src.as_f32x8())) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_min_ps&expand=3765) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminps))] +pub unsafe fn _mm256_maskz_min_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let min = _mm256_min_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_ps&expand=3761) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminps))] +pub unsafe fn _mm_mask_min_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let min = _mm_min_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, min, src.as_f32x4())) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_ps&expand=3762) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminps))] +pub unsafe fn _mm_maskz_min_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let min = _mm_min_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, min, zero)) } +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst. + /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_pd&expand=3759) @@ -1077,8 +2483,8 @@ pub unsafe fn _mm512_min_pd(a: __m512d, b: __m512d) -> __m512d { #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminpd))] pub unsafe fn _mm512_mask_min_pd(src: __m512d, k: __mmask8, a: __m512d, b: __m512d) -> __m512d { - let max = _mm512_min_pd(a, b).as_f64x8(); - transmute(simd_select_bitmask(k, max, src.as_f64x8())) + let min = _mm512_min_pd(a, b).as_f64x8(); + transmute(simd_select_bitmask(k, min, src.as_f64x8())) } /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -1088,14 +2494,60 @@ pub unsafe fn _mm512_mask_min_pd(src: __m512d, k: __mmask8, a: __m512d, b: __m51 #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminpd))] pub unsafe fn _mm512_maskz_min_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m512d { - let max = _mm512_min_pd(a, b).as_f64x8(); + let min = _mm512_min_pd(a, b).as_f64x8(); let zero = _mm512_setzero_pd().as_f64x8(); - transmute(simd_select_bitmask(k, max, zero)) + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_min_pd&expand=3754) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminpd))] +pub unsafe fn _mm256_mask_min_pd(src: __m256d, k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let min = _mm256_min_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, min, src.as_f64x4())) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_min_pd&expand=3755) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminpd))] +pub unsafe fn _mm256_maskz_min_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let min = _mm256_min_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_pd&expand=3751) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminpd))] +pub unsafe fn _mm_mask_min_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let min = _mm_min_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, min, src.as_f64x2())) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_pd&expand=3752) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vminpd))] +pub unsafe fn _mm_maskz_min_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let min = _mm_min_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, min, zero)) } /// Compare packed unsigned 32-bit integers in a and b, and store packed minimum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_epu32&expand=3732) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epu32&expand=3732) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminud))] @@ -1105,30 +2557,76 @@ pub unsafe fn _mm512_min_epu32(a: __m512i, b: __m512i) -> __m512i { /// Compare packed unsigned 32-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_min_epu32&expand=3730) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epu32&expand=3730) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminud))] pub unsafe fn _mm512_mask_min_epu32(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epu32(a, b).as_u32x16(); - transmute(simd_select_bitmask(k, max, src.as_u32x16())) + let min = _mm512_min_epu32(a, b).as_u32x16(); + transmute(simd_select_bitmask(k, min, src.as_u32x16())) } /// Compare packed unsigned 32-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_min_epu32&expand=3731) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_epu32&expand=3731) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminud))] pub unsafe fn _mm512_maskz_min_epu32(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epu32(a, b).as_u32x16(); + let min = _mm512_min_epu32(a, b).as_u32x16(); let zero = _mm512_setzero_si512().as_u32x16(); - transmute(simd_select_bitmask(k, max, zero)) + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed unsigned 32-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_min_epu32&expand=3727) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminud))] +pub unsafe fn _mm256_mask_min_epu32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epu32(a, b).as_u32x8(); + transmute(simd_select_bitmask(k, min, src.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_min_epu32&expand=3728) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminud))] +pub unsafe fn _mm256_maskz_min_epu32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epu32(a, b).as_u32x8(); + let zero = _mm256_setzero_si256().as_u32x8(); + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed unsigned 32-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_epu32&expand=3724) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminud))] +pub unsafe fn _mm_mask_min_epu32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let min = _mm_min_epu32(a, b).as_u32x4(); + transmute(simd_select_bitmask(k, min, src.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_epu32&expand=3725) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminud))] +pub unsafe fn _mm_maskz_min_epu32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let min = _mm_min_epu32(a, b).as_u32x4(); + let zero = _mm_setzero_si128().as_u32x4(); + transmute(simd_select_bitmask(k, min, zero)) } /// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_epu64&expand=3741) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_epu64&expand=3741) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminuq))] @@ -1138,30 +2636,96 @@ pub unsafe fn _mm512_min_epu64(a: __m512i, b: __m512i) -> __m512i { /// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_min_epu64&expand=3739) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_epu64&expand=3739) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminuq))] pub unsafe fn _mm512_mask_min_epu64(src: __m512i, k: __mmask8, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epu64(a, b).as_u64x8(); - transmute(simd_select_bitmask(k, max, src.as_u64x8())) + let min = _mm512_min_epu64(a, b).as_u64x8(); + transmute(simd_select_bitmask(k, min, src.as_u64x8())) } /// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_min_epu64&expand=3740) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_epu64&expand=3740) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpminuq))] pub unsafe fn _mm512_maskz_min_epu64(k: __mmask8, a: __m512i, b: __m512i) -> __m512i { - let max = _mm512_min_epu64(a, b).as_u64x8(); + let min = _mm512_min_epu64(a, b).as_u64x8(); let zero = _mm512_setzero_si512().as_u64x8(); - transmute(simd_select_bitmask(k, max, zero)) + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_min_epu64&expand=3738) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminuq))] +pub unsafe fn _mm256_min_epu64(a: __m256i, b: __m256i) -> __m256i { + transmute(vpminuq256(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_min_epu64&expand=3736) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminuq))] +pub unsafe fn _mm256_mask_min_epu64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epu64(a, b).as_u64x4(); + transmute(simd_select_bitmask(k, min, src.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_min_epu64&expand=3737) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminuq))] +pub unsafe fn _mm256_maskz_min_epu64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let min = _mm256_min_epu64(a, b).as_u64x4(); + let zero = _mm256_setzero_si256().as_u64x4(); + transmute(simd_select_bitmask(k, min, zero)) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epu64&expand=3735) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminuq))] +pub unsafe fn _mm_min_epu64(a: __m128i, b: __m128i) -> __m128i { + transmute(vpminuq128(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_min_epu64&expand=3733) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminuq))] +pub unsafe fn _mm_mask_min_epu64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let min = _mm_min_epu64(a, b).as_u64x2(); + transmute(simd_select_bitmask(k, min, src.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_min_epu64&expand=3734) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpminuq))] +pub unsafe fn _mm_maskz_min_epu64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let min = _mm_min_epu64(a, b).as_u64x2(); + let zero = _mm_setzero_si128().as_u64x2(); + transmute(simd_select_bitmask(k, min, zero)) } /// Compute the square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sqrt_ps&expand=5371) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_ps&expand=5371) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtps))] @@ -1171,7 +2735,7 @@ pub unsafe fn _mm512_sqrt_ps(a: __m512) -> __m512 { /// Compute the square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sqrt_ps&expand=5369) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_ps&expand=5369) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtps))] @@ -1182,7 +2746,7 @@ pub unsafe fn _mm512_mask_sqrt_ps(src: __m512, k: __mmask16, a: __m512) -> __m51 /// Compute the square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sqrt_ps&expand=5370) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_ps&expand=5370) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtps))] @@ -1192,9 +2756,55 @@ pub unsafe fn _mm512_maskz_sqrt_ps(k: __mmask16, a: __m512) -> __m512 { transmute(simd_select_bitmask(k, sqrt, zero)) } +/// Compute the square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sqrt_ps&expand=5366) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtps))] +pub unsafe fn _mm256_mask_sqrt_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + let sqrt = _mm256_sqrt_ps(a).as_f32x8(); + transmute(simd_select_bitmask(k, sqrt, src.as_f32x8())) +} + +/// Compute the square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sqrt_ps&expand=5367) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtps))] +pub unsafe fn _mm256_maskz_sqrt_ps(k: __mmask8, a: __m256) -> __m256 { + let sqrt = _mm256_sqrt_ps(a).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, sqrt, zero)) +} + +/// Compute the square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sqrt_ps&expand=5363) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtps))] +pub unsafe fn _mm_mask_sqrt_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + let sqrt = _mm_sqrt_ps(a).as_f32x4(); + transmute(simd_select_bitmask(k, sqrt, src.as_f32x4())) +} + +/// Compute the square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sqrt_ps&expand=5364) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtps))] +pub unsafe fn _mm_maskz_sqrt_ps(k: __mmask8, a: __m128) -> __m128 { + let sqrt = _mm_sqrt_ps(a).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, sqrt, zero)) +} + /// Compute the square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sqrt_pd&expand=5362) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_pd&expand=5362) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtpd))] @@ -1204,7 +2814,7 @@ pub unsafe fn _mm512_sqrt_pd(a: __m512d) -> __m512d { /// Compute the square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sqrt_pd&expand=5360) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_pd&expand=5360) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtpd))] @@ -1215,7 +2825,7 @@ pub unsafe fn _mm512_mask_sqrt_pd(src: __m512d, k: __mmask8, a: __m512d) -> __m5 /// Compute the square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sqrt_pd&expand=5361) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_pd&expand=5361) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtpd))] @@ -1225,24 +2835,65 @@ pub unsafe fn _mm512_maskz_sqrt_pd(k: __mmask8, a: __m512d) -> __m512d { transmute(simd_select_bitmask(k, sqrt, zero)) } +/// Compute the square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sqrt_pd&expand=5357) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtpd))] +pub unsafe fn _mm256_mask_sqrt_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + let sqrt = _mm256_sqrt_pd(a).as_f64x4(); + transmute(simd_select_bitmask(k, sqrt, src.as_f64x4())) +} + +/// Compute the square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sqrt_pd&expand=5358) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtpd))] +pub unsafe fn _mm256_maskz_sqrt_pd(k: __mmask8, a: __m256d) -> __m256d { + let sqrt = _mm256_sqrt_pd(a).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, sqrt, zero)) +} + +/// Compute the square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sqrt_pd&expand=5354) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtpd))] +pub unsafe fn _mm_mask_sqrt_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + let sqrt = _mm_sqrt_pd(a).as_f64x2(); + transmute(simd_select_bitmask(k, sqrt, src.as_f64x2())) +} + +/// Compute the square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sqrt_pd&expand=5355) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vsqrtpd))] +pub unsafe fn _mm_maskz_sqrt_pd(k: __mmask8, a: __m128d) -> __m128d { + let sqrt = _mm_sqrt_pd(a).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, sqrt, zero)) +} + /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=fmadd_ps&expand=2557) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_ps&expand=2557) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps pub unsafe fn _mm512_fmadd_ps(a: __m512, b: __m512, c: __m512) -> __m512 { - transmute(vfmadd132ps( - a.as_f32x16(), - b.as_f32x16(), - c.as_f32x16(), - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16())) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmadd_ps&expand=2558) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_ps&expand=2558) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps @@ -1253,7 +2904,7 @@ pub unsafe fn _mm512_mask_fmadd_ps(a: __m512, k: __mmask16, b: __m512, c: __m512 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmadd_ps&expand=2560) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_ps&expand=2560) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps @@ -1265,7 +2916,7 @@ pub unsafe fn _mm512_maskz_fmadd_ps(k: __mmask16, a: __m512, b: __m512, c: __m51 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmadd_ps&expand=2559) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_ps&expand=2559) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps @@ -1274,24 +2925,87 @@ pub unsafe fn _mm512_mask3_fmadd_ps(a: __m512, b: __m512, c: __m512, k: __mmask1 transmute(simd_select_bitmask(k, fmadd, c.as_f32x16())) } -/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst. +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmadd_pd&expand=2545) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmadd_ps&expand=2554) #[inline] -#[target_feature(enable = "avx512f")] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps +pub unsafe fn _mm256_mask_fmadd_ps(a: __m256, k: __mmask8, b: __m256, c: __m256) -> __m256 { + let fmadd = _mm256_fmadd_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmadd, a.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmadd_ps&expand=2556) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps +pub unsafe fn _mm256_maskz_fmadd_ps(k: __mmask8, a: __m256, b: __m256, c: __m256) -> __m256 { + let fmadd = _mm256_fmadd_ps(a, b, c).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, fmadd, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmadd_ps&expand=2555) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps +pub unsafe fn _mm256_mask3_fmadd_ps(a: __m256, b: __m256, c: __m256, k: __mmask8) -> __m256 { + let fmadd = _mm256_fmadd_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmadd, c.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmadd_ps&expand=2550) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps +pub unsafe fn _mm_mask_fmadd_ps(a: __m128, k: __mmask8, b: __m128, c: __m128) -> __m128 { + let fmadd = _mm_fmadd_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmadd, a.as_f32x4())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmadd_ps&expand=2552) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps +pub unsafe fn _mm_maskz_fmadd_ps(k: __mmask8, a: __m128, b: __m128, c: __m128) -> __m128 { + let fmadd = _mm_fmadd_ps(a, b, c).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, fmadd, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmadd_ps&expand=2551) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132ps or vfmadd213ps or vfmadd231ps +pub unsafe fn _mm_mask3_fmadd_ps(a: __m128, b: __m128, c: __m128, k: __mmask8) -> __m128 { + let fmadd = _mm_fmadd_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmadd, c.as_f32x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_pd&expand=2545) +#[inline] +#[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd pub unsafe fn _mm512_fmadd_pd(a: __m512d, b: __m512d, c: __m512d) -> __m512d { - transmute(vfmadd132pd( - a.as_f64x8(), - b.as_f64x8(), - c.as_f64x8(), - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8())) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmadd_pd&expand=2546) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_pd&expand=2546) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd @@ -1302,7 +3016,7 @@ pub unsafe fn _mm512_mask_fmadd_pd(a: __m512d, k: __mmask8, b: __m512d, c: __m51 /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmadd_pd&expand=2548) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_pd&expand=2548) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd @@ -1314,7 +3028,7 @@ pub unsafe fn _mm512_maskz_fmadd_pd(k: __mmask8, a: __m512d, b: __m512d, c: __m5 /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmadd_pd&expand=2547) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_pd&expand=2547) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd @@ -1323,26 +3037,89 @@ pub unsafe fn _mm512_mask3_fmadd_pd(a: __m512d, b: __m512d, c: __m512d, k: __mma transmute(simd_select_bitmask(k, fmadd, c.as_f64x8())) } +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmadd_pd&expand=2542) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd +pub unsafe fn _mm256_mask_fmadd_pd(a: __m256d, k: __mmask8, b: __m256d, c: __m256d) -> __m256d { + let fmadd = _mm256_fmadd_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmadd, a.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmadd_pd&expand=2544) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd +pub unsafe fn _mm256_maskz_fmadd_pd(k: __mmask8, a: __m256d, b: __m256d, c: __m256d) -> __m256d { + let fmadd = _mm256_fmadd_pd(a, b, c).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, fmadd, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmadd_pd&expand=2543) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd +pub unsafe fn _mm256_mask3_fmadd_pd(a: __m256d, b: __m256d, c: __m256d, k: __mmask8) -> __m256d { + let fmadd = _mm256_fmadd_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmadd, c.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmadd_pd&expand=2538) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd +pub unsafe fn _mm_mask_fmadd_pd(a: __m128d, k: __mmask8, b: __m128d, c: __m128d) -> __m128d { + let fmadd = _mm_fmadd_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmadd, a.as_f64x2())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmadd_pd&expand=2540) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd +pub unsafe fn _mm_maskz_fmadd_pd(k: __mmask8, a: __m128d, b: __m128d, c: __m128d) -> __m128d { + let fmadd = _mm_fmadd_pd(a, b, c).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, fmadd, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmadd_pd&expand=2539) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmadd))] //vfmadd132pd or vfmadd213pd or vfmadd231pd +pub unsafe fn _mm_mask3_fmadd_pd(a: __m128d, b: __m128d, c: __m128d, k: __mmask8) -> __m128d { + let fmadd = _mm_fmadd_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmadd, c.as_f64x2())) +} + /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsub_ps&expand=2643) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_ps&expand=2643) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub pub unsafe fn _mm512_fmsub_ps(a: __m512, b: __m512, c: __m512) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, c.as_f32x16()); - transmute(vfmadd132ps( - a.as_f32x16(), - b.as_f32x16(), - sub, - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132ps(a.as_f32x16(), b.as_f32x16(), sub)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsub_ps&expand=2644) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_ps&expand=2644) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub @@ -1353,7 +3130,7 @@ pub unsafe fn _mm512_mask_fmsub_ps(a: __m512, k: __mmask16, b: __m512, c: __m512 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsub_ps&expand=2646) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_ps&expand=2646) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub @@ -1365,7 +3142,7 @@ pub unsafe fn _mm512_maskz_fmsub_ps(k: __mmask16, a: __m512, b: __m512, c: __m51 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsub_ps&expand=2645) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_ps&expand=2645) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub @@ -1374,26 +3151,89 @@ pub unsafe fn _mm512_mask3_fmsub_ps(a: __m512, b: __m512, c: __m512, k: __mmask1 transmute(simd_select_bitmask(k, fmsub, c.as_f32x16())) } +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmsub_ps&expand=2640) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub +pub unsafe fn _mm256_mask_fmsub_ps(a: __m256, k: __mmask8, b: __m256, c: __m256) -> __m256 { + let fmsub = _mm256_fmsub_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmsub, a.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmsub_ps&expand=2642) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub +pub unsafe fn _mm256_maskz_fmsub_ps(k: __mmask8, a: __m256, b: __m256, c: __m256) -> __m256 { + let fmsub = _mm256_fmsub_ps(a, b, c).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, fmsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmsub_ps&expand=2641) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub +pub unsafe fn _mm256_mask3_fmsub_ps(a: __m256, b: __m256, c: __m256, k: __mmask8) -> __m256 { + let fmsub = _mm256_fmsub_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmsub, c.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsub_ps&expand=2636) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub +pub unsafe fn _mm_mask_fmsub_ps(a: __m128, k: __mmask8, b: __m128, c: __m128) -> __m128 { + let fmsub = _mm_fmsub_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmsub, a.as_f32x4())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsub_ps&expand=2638) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub +pub unsafe fn _mm_maskz_fmsub_ps(k: __mmask8, a: __m128, b: __m128, c: __m128) -> __m128 { + let fmsub = _mm_fmsub_ps(a, b, c).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, fmsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsub_ps&expand=2637) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generate vfmadd, gcc generate vfmsub +pub unsafe fn _mm_mask3_fmsub_ps(a: __m128, b: __m128, c: __m128, k: __mmask8) -> __m128 { + let fmsub = _mm_fmsub_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmsub, c.as_f32x4())) +} + /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsub_pd&expand=2631) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_pd&expand=2631) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub pub unsafe fn _mm512_fmsub_pd(a: __m512d, b: __m512d, c: __m512d) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, c.as_f64x8()); - transmute(vfmadd132pd( - a.as_f64x8(), - b.as_f64x8(), - sub, - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132pd(a.as_f64x8(), b.as_f64x8(), sub)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsub_pd&expand=2632) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_pd&expand=2632) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub @@ -1404,7 +3244,7 @@ pub unsafe fn _mm512_mask_fmsub_pd(a: __m512d, k: __mmask8, b: __m512d, c: __m51 /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsub_pd&expand=2634) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_pd&expand=2634) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub @@ -1416,7 +3256,7 @@ pub unsafe fn _mm512_maskz_fmsub_pd(k: __mmask8, a: __m512d, b: __m512d, c: __m5 /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsub_pd&expand=2633) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_pd&expand=2633) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub @@ -1425,9 +3265,77 @@ pub unsafe fn _mm512_mask3_fmsub_pd(a: __m512d, b: __m512d, c: __m512d, k: __mma transmute(simd_select_bitmask(k, fmsub, c.as_f64x8())) } +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmsub_pd&expand=2628) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub +pub unsafe fn _mm256_mask_fmsub_pd(a: __m256d, k: __mmask8, b: __m256d, c: __m256d) -> __m256d { + let fmsub = _mm256_fmsub_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmsub, a.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmsub_pd&expand=2630) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub +pub unsafe fn _mm256_maskz_fmsub_pd(k: __mmask8, a: __m256d, b: __m256d, c: __m256d) -> __m256d { + let fmsub = _mm256_fmsub_pd(a, b, c).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, fmsub, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmsub_pd&expand=2629) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub +pub unsafe fn _mm256_mask3_fmsub_pd(a: __m256d, b: __m256d, c: __m256d, k: __mmask8) -> __m256d { + let fmsub = _mm256_fmsub_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmsub, c.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsub_pd&expand=2624) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub +pub unsafe fn _mm_mask_fmsub_pd(a: __m128d, k: __mmask8, b: __m128d, c: __m128d) -> __m128d { + let fmsub = _mm_fmsub_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmsub, a.as_f64x2())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsub_pd&expand=2626) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub +pub unsafe fn _mm_maskz_fmsub_pd(k: __mmask8, a: __m128d, b: __m128d, c: __m128d) -> __m128d { + let fmsub = _mm_fmsub_pd(a, b, c).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, fmsub, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsub_pd&expand=2625) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsub))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang fmadd, gcc fmsub +pub unsafe fn _mm_mask3_fmsub_pd(a: __m128d, b: __m128d, c: __m128d, k: __mmask8) -> __m128d { + let fmsub = _mm_fmsub_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmsub, c.as_f64x2())) +} + /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmaddsub_ps&expand=2611) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_ps&expand=2611) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps @@ -1442,7 +3350,7 @@ pub unsafe fn _mm512_fmaddsub_ps(a: __m512, b: __m512, c: __m512) -> __m512 { /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmaddsub_ps&expand=2612) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_ps&expand=2612) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps @@ -1453,7 +3361,7 @@ pub unsafe fn _mm512_mask_fmaddsub_ps(a: __m512, k: __mmask16, b: __m512, c: __m /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmaddsub_ps&expand=2614) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_ps&expand=2614) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps @@ -1465,7 +3373,7 @@ pub unsafe fn _mm512_maskz_fmaddsub_ps(k: __mmask16, a: __m512, b: __m512, c: __ /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmaddsub_ps&expand=2613) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_ps&expand=2613) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps @@ -1474,9 +3382,77 @@ pub unsafe fn _mm512_mask3_fmaddsub_ps(a: __m512, b: __m512, c: __m512, k: __mma transmute(simd_select_bitmask(k, fmaddsub, c.as_f32x16())) } +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmaddsub_ps&expand=2608) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps +pub unsafe fn _mm256_mask_fmaddsub_ps(a: __m256, k: __mmask8, b: __m256, c: __m256) -> __m256 { + let fmaddsub = _mm256_fmaddsub_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmaddsub, a.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmaddsub_ps&expand=2610) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps +pub unsafe fn _mm256_maskz_fmaddsub_ps(k: __mmask8, a: __m256, b: __m256, c: __m256) -> __m256 { + let fmaddsub = _mm256_fmaddsub_ps(a, b, c).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, fmaddsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmaddsub_ps&expand=2609) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps +pub unsafe fn _mm256_mask3_fmaddsub_ps(a: __m256, b: __m256, c: __m256, k: __mmask8) -> __m256 { + let fmaddsub = _mm256_fmaddsub_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmaddsub, c.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmaddsub_ps&expand=2604) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps +pub unsafe fn _mm_mask_fmaddsub_ps(a: __m128, k: __mmask8, b: __m128, c: __m128) -> __m128 { + let fmaddsub = _mm_fmaddsub_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmaddsub, a.as_f32x4())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=_mm_maskz_fmaddsub_ps&expand=2606) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps +pub unsafe fn _mm_maskz_fmaddsub_ps(k: __mmask8, a: __m128, b: __m128, c: __m128) -> __m128 { + let fmaddsub = _mm_fmaddsub_ps(a, b, c).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, fmaddsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmaddsub_ps&expand=2605) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps +pub unsafe fn _mm_mask3_fmaddsub_ps(a: __m128, b: __m128, c: __m128, k: __mmask8) -> __m128 { + let fmaddsub = _mm_fmaddsub_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmaddsub, c.as_f32x4())) +} + /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmaddsub_pd&expand=2599) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_pd&expand=2599) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -1491,7 +3467,7 @@ pub unsafe fn _mm512_fmaddsub_pd(a: __m512d, b: __m512d, c: __m512d) -> __m512d /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmaddsub_pd&expand=2600) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_pd&expand=2600) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -1502,7 +3478,7 @@ pub unsafe fn _mm512_mask_fmaddsub_pd(a: __m512d, k: __mmask8, b: __m512d, c: __ /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmaddsub_pd&expand=2602) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_pd&expand=2602) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -1514,7 +3490,7 @@ pub unsafe fn _mm512_maskz_fmaddsub_pd(k: __mmask8, a: __m512d, b: __m512d, c: _ /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmaddsub_ps&expand=2613) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_ps&expand=2613) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -1523,9 +3499,77 @@ pub unsafe fn _mm512_mask3_fmaddsub_pd(a: __m512d, b: __m512d, c: __m512d, k: __ transmute(simd_select_bitmask(k, fmaddsub, c.as_f64x8())) } +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmaddsub_pd&expand=2596) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd +pub unsafe fn _mm256_mask_fmaddsub_pd(a: __m256d, k: __mmask8, b: __m256d, c: __m256d) -> __m256d { + let fmaddsub = _mm256_fmaddsub_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmaddsub, a.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmaddsub_pd&expand=2598) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd +pub unsafe fn _mm256_maskz_fmaddsub_pd(k: __mmask8, a: __m256d, b: __m256d, c: __m256d) -> __m256d { + let fmaddsub = _mm256_fmaddsub_pd(a, b, c).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, fmaddsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmaddsub_pd&expand=2597) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd +pub unsafe fn _mm256_mask3_fmaddsub_pd(a: __m256d, b: __m256d, c: __m256d, k: __mmask8) -> __m256d { + let fmaddsub = _mm256_fmaddsub_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmaddsub, c.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmaddsub_pd&expand=2592) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd +pub unsafe fn _mm_mask_fmaddsub_pd(a: __m128d, k: __mmask8, b: __m128d, c: __m128d) -> __m128d { + let fmaddsub = _mm_fmaddsub_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmaddsub, a.as_f64x2())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmaddsub_pd&expand=2594) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd +pub unsafe fn _mm_maskz_fmaddsub_pd(k: __mmask8, a: __m128d, b: __m128d, c: __m128d) -> __m128d { + let fmaddsub = _mm_fmaddsub_pd(a, b, c).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, fmaddsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmaddsub_pd&expand=2593) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmaddsub))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd +pub unsafe fn _mm_mask3_fmaddsub_pd(a: __m128d, b: __m128d, c: __m128d, k: __mmask8) -> __m128d { + let fmaddsub = _mm_fmaddsub_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmaddsub, c.as_f64x2())) +} + /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsubadd_ps&expand=2691) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_ps&expand=2691) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -1542,7 +3586,7 @@ pub unsafe fn _mm512_fmsubadd_ps(a: __m512, b: __m512, c: __m512) -> __m512 { /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsubadd_ps&expand=2692) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_ps&expand=2692) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -1553,7 +3597,7 @@ pub unsafe fn _mm512_mask_fmsubadd_ps(a: __m512, k: __mmask16, b: __m512, c: __m /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsubadd_ps&expand=2694) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_ps&expand=2694) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -1565,7 +3609,7 @@ pub unsafe fn _mm512_maskz_fmsubadd_ps(k: __mmask16, a: __m512, b: __m512, c: __ /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsubadd_ps&expand=2693) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_ps&expand=2693) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -1574,9 +3618,77 @@ pub unsafe fn _mm512_mask3_fmsubadd_ps(a: __m512, b: __m512, c: __m512, k: __mma transmute(simd_select_bitmask(k, fmsubadd, c.as_f32x16())) } +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmsubadd_ps&expand=2688) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps +pub unsafe fn _mm256_mask_fmsubadd_ps(a: __m256, k: __mmask8, b: __m256, c: __m256) -> __m256 { + let fmsubadd = _mm256_fmsubadd_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmsubadd, a.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmsubadd_ps&expand=2690) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps +pub unsafe fn _mm256_maskz_fmsubadd_ps(k: __mmask8, a: __m256, b: __m256, c: __m256) -> __m256 { + let fmsubadd = _mm256_fmsubadd_ps(a, b, c).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, fmsubadd, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmsubadd_ps&expand=2689) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps +pub unsafe fn _mm256_mask3_fmsubadd_ps(a: __m256, b: __m256, c: __m256, k: __mmask8) -> __m256 { + let fmsubadd = _mm256_fmsubadd_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fmsubadd, c.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsubadd_ps&expand=2684) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps +pub unsafe fn _mm_mask_fmsubadd_ps(a: __m128, k: __mmask8, b: __m128, c: __m128) -> __m128 { + let fmsubadd = _mm_fmsubadd_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmsubadd, a.as_f32x4())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsubadd_ps&expand=2686) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps +pub unsafe fn _mm_maskz_fmsubadd_ps(k: __mmask8, a: __m128, b: __m128, c: __m128) -> __m128 { + let fmsubadd = _mm_fmsubadd_ps(a, b, c).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, fmsubadd, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsubadd_ps&expand=2685) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps +pub unsafe fn _mm_mask3_fmsubadd_ps(a: __m128, b: __m128, c: __m128, k: __mmask8) -> __m128 { + let fmsubadd = _mm_fmsubadd_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fmsubadd, c.as_f32x4())) +} + /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsubadd_pd&expand=2679) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_pd&expand=2679) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -1593,7 +3705,7 @@ pub unsafe fn _mm512_fmsubadd_pd(a: __m512d, b: __m512d, c: __m512d) -> __m512d /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsubadd_pd&expand=2680) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_pd&expand=2680) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -1604,7 +3716,7 @@ pub unsafe fn _mm512_mask_fmsubadd_pd(a: __m512d, k: __mmask8, b: __m512d, c: __ /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsubadd_pd&expand=2682) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_pd&expand=2682) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -1616,7 +3728,7 @@ pub unsafe fn _mm512_maskz_fmsubadd_pd(k: __mmask8, a: __m512d, b: __m512d, c: _ /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsubadd_pd&expand=2681) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_pd&expand=2681) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -1625,26 +3737,89 @@ pub unsafe fn _mm512_mask3_fmsubadd_pd(a: __m512d, b: __m512d, c: __m512d, k: __ transmute(simd_select_bitmask(k, fmsubadd, c.as_f64x8())) } +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fmsubadd_pd&expand=2676) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd +pub unsafe fn _mm256_mask_fmsubadd_pd(a: __m256d, k: __mmask8, b: __m256d, c: __m256d) -> __m256d { + let fmsubadd = _mm256_fmsubadd_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmsubadd, a.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fmsubadd_pd&expand=2678) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd +pub unsafe fn _mm256_maskz_fmsubadd_pd(k: __mmask8, a: __m256d, b: __m256d, c: __m256d) -> __m256d { + let fmsubadd = _mm256_fmsubadd_pd(a, b, c).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, fmsubadd, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fmsubadd_pd&expand=2677) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd +pub unsafe fn _mm256_mask3_fmsubadd_pd(a: __m256d, b: __m256d, c: __m256d, k: __mmask8) -> __m256d { + let fmsubadd = _mm256_fmsubadd_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fmsubadd, c.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fmsubadd_pd&expand=2672) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd +pub unsafe fn _mm_mask_fmsubadd_pd(a: __m128d, k: __mmask8, b: __m128d, c: __m128d) -> __m128d { + let fmsubadd = _mm_fmsubadd_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmsubadd, a.as_f64x2())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fmsubadd_pd&expand=2674) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd +pub unsafe fn _mm_maskz_fmsubadd_pd(k: __mmask8, a: __m128d, b: __m128d, c: __m128d) -> __m128d { + let fmsubadd = _mm_fmsubadd_pd(a, b, c).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, fmsubadd, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fmsubadd_pd&expand=2673) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfmsubadd))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd +pub unsafe fn _mm_mask3_fmsubadd_pd(a: __m128d, b: __m128d, c: __m128d, k: __mmask8) -> __m128d { + let fmsubadd = _mm_fmsubadd_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fmsubadd, c.as_f64x2())) +} + /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmadd_ps&expand=2723) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_ps&expand=2723) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps pub unsafe fn _mm512_fnmadd_ps(a: __m512, b: __m512, c: __m512) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, a.as_f32x16()); - transmute(vfmadd132ps( - sub, - b.as_f32x16(), - c.as_f32x16(), - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132ps(sub, b.as_f32x16(), c.as_f32x16())) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmadd_ps&expand=2724) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_ps&expand=2724) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps @@ -1655,7 +3830,7 @@ pub unsafe fn _mm512_mask_fnmadd_ps(a: __m512, k: __mmask16, b: __m512, c: __m51 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmadd_ps&expand=2726) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_ps&expand=2726) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps @@ -1667,7 +3842,7 @@ pub unsafe fn _mm512_maskz_fnmadd_ps(k: __mmask16, a: __m512, b: __m512, c: __m5 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmadd_ps&expand=2725) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_ps&expand=2725) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps @@ -1676,26 +3851,89 @@ pub unsafe fn _mm512_mask3_fnmadd_ps(a: __m512, b: __m512, c: __m512, k: __mmask transmute(simd_select_bitmask(k, fnmadd, c.as_f32x16())) } +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fnmadd_ps&expand=2720) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps +pub unsafe fn _mm256_mask_fnmadd_ps(a: __m256, k: __mmask8, b: __m256, c: __m256) -> __m256 { + let fnmadd = _mm256_fnmadd_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fnmadd, a.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fnmadd_ps&expand=2722) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps +pub unsafe fn _mm256_maskz_fnmadd_ps(k: __mmask8, a: __m256, b: __m256, c: __m256) -> __m256 { + let fnmadd = _mm256_fnmadd_ps(a, b, c).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, fnmadd, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fnmadd_ps&expand=2721) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps +pub unsafe fn _mm256_mask3_fnmadd_ps(a: __m256, b: __m256, c: __m256, k: __mmask8) -> __m256 { + let fnmadd = _mm256_fnmadd_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fnmadd, c.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmadd_ps&expand=2716) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps +pub unsafe fn _mm_mask_fnmadd_ps(a: __m128, k: __mmask8, b: __m128, c: __m128) -> __m128 { + let fnmadd = _mm_fnmadd_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fnmadd, a.as_f32x4())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmadd_ps&expand=2718) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps +pub unsafe fn _mm_maskz_fnmadd_ps(k: __mmask8, a: __m128, b: __m128, c: __m128) -> __m128 { + let fnmadd = _mm_fnmadd_ps(a, b, c).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, fnmadd, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmadd_ps&expand=2717) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps +pub unsafe fn _mm_mask3_fnmadd_ps(a: __m128, b: __m128, c: __m128, k: __mmask8) -> __m128 { + let fnmadd = _mm_fnmadd_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fnmadd, c.as_f32x4())) +} + /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmadd_pd&expand=2711) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_pd&expand=2711) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd pub unsafe fn _mm512_fnmadd_pd(a: __m512d, b: __m512d, c: __m512d) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, a.as_f64x8()); - transmute(vfmadd132pd( - sub, - b.as_f64x8(), - c.as_f64x8(), - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132pd(sub, b.as_f64x8(), c.as_f64x8())) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmadd_pd&expand=2712) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_pd&expand=2712) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd @@ -1706,7 +3944,7 @@ pub unsafe fn _mm512_mask_fnmadd_pd(a: __m512d, k: __mmask8, b: __m512d, c: __m5 /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmadd_pd&expand=2714) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_pd&expand=2714) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd @@ -1718,7 +3956,7 @@ pub unsafe fn _mm512_maskz_fnmadd_pd(k: __mmask8, a: __m512d, b: __m512d, c: __m /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmadd_pd&expand=2713) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_pd&expand=2713) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd @@ -1727,9 +3965,77 @@ pub unsafe fn _mm512_mask3_fnmadd_pd(a: __m512d, b: __m512d, c: __m512d, k: __mm transmute(simd_select_bitmask(k, fnmadd, c.as_f64x8())) } +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fnmadd_pd&expand=2708) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd +pub unsafe fn _mm256_mask_fnmadd_pd(a: __m256d, k: __mmask8, b: __m256d, c: __m256d) -> __m256d { + let fnmadd = _mm256_fnmadd_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fnmadd, a.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fnmadd_pd&expand=2710) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd +pub unsafe fn _mm256_maskz_fnmadd_pd(k: __mmask8, a: __m256d, b: __m256d, c: __m256d) -> __m256d { + let fnmadd = _mm256_fnmadd_pd(a, b, c).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, fnmadd, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fnmadd_pd&expand=2709) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd +pub unsafe fn _mm256_mask3_fnmadd_pd(a: __m256d, b: __m256d, c: __m256d, k: __mmask8) -> __m256d { + let fnmadd = _mm256_fnmadd_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fnmadd, c.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmadd_pd&expand=2704) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd +pub unsafe fn _mm_mask_fnmadd_pd(a: __m128d, k: __mmask8, b: __m128d, c: __m128d) -> __m128d { + let fnmadd = _mm_fnmadd_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fnmadd, a.as_f64x2())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmadd_pd&expand=2706) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd +pub unsafe fn _mm_maskz_fnmadd_pd(k: __mmask8, a: __m128d, b: __m128d, c: __m128d) -> __m128d { + let fnmadd = _mm_fnmadd_pd(a, b, c).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, fnmadd, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmadd_pd&expand=2705) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmadd))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd +pub unsafe fn _mm_mask3_fnmadd_pd(a: __m128d, b: __m128d, c: __m128d, k: __mmask8) -> __m128d { + let fnmadd = _mm_fnmadd_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fnmadd, c.as_f64x2())) +} + /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmsub_ps&expand=2771) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_ps&expand=2771) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -1737,17 +4043,12 @@ pub unsafe fn _mm512_fnmsub_ps(a: __m512, b: __m512, c: __m512) -> __m512 { let zero: f32x16 = mem::zeroed(); let suba = simd_sub(zero, a.as_f32x16()); let subc = simd_sub(zero, c.as_f32x16()); - transmute(vfmadd132ps( - suba, - b.as_f32x16(), - subc, - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132ps(suba, b.as_f32x16(), subc)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmsub_ps&expand=2772) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_ps&expand=2772) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -1758,7 +4059,7 @@ pub unsafe fn _mm512_mask_fnmsub_ps(a: __m512, k: __mmask16, b: __m512, c: __m51 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmsub_ps&expand=2774) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_ps&expand=2774) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -1770,7 +4071,7 @@ pub unsafe fn _mm512_maskz_fnmsub_ps(k: __mmask16, a: __m512, b: __m512, c: __m5 /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmsub_ps&expand=2773) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_ps&expand=2773) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -1779,9 +4080,77 @@ pub unsafe fn _mm512_mask3_fnmsub_ps(a: __m512, b: __m512, c: __m512, k: __mmask transmute(simd_select_bitmask(k, fnmsub, c.as_f32x16())) } +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fnmsub_ps&expand=2768) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps +pub unsafe fn _mm256_mask_fnmsub_ps(a: __m256, k: __mmask8, b: __m256, c: __m256) -> __m256 { + let fnmsub = _mm256_fnmsub_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fnmsub, a.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fnmsub_ps&expand=2770) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps +pub unsafe fn _mm256_maskz_fnmsub_ps(k: __mmask8, a: __m256, b: __m256, c: __m256) -> __m256 { + let fnmsub = _mm256_fnmsub_ps(a, b, c).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, fnmsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fnmsub_ps&expand=2769) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps +pub unsafe fn _mm256_mask3_fnmsub_ps(a: __m256, b: __m256, c: __m256, k: __mmask8) -> __m256 { + let fnmsub = _mm256_fnmsub_ps(a, b, c).as_f32x8(); + transmute(simd_select_bitmask(k, fnmsub, c.as_f32x8())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmsub_ps&expand=2764) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps +pub unsafe fn _mm_mask_fnmsub_ps(a: __m128, k: __mmask8, b: __m128, c: __m128) -> __m128 { + let fnmsub = _mm_fnmsub_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fnmsub, a.as_f32x4())) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmsub_ps&expand=2766) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps +pub unsafe fn _mm_maskz_fnmsub_ps(k: __mmask8, a: __m128, b: __m128, c: __m128) -> __m128 { + let fnmsub = _mm_fnmsub_ps(a, b, c).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, fnmsub, zero)) +} + +/// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmsub_ps&expand=2765) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps +pub unsafe fn _mm_mask3_fnmsub_ps(a: __m128, b: __m128, c: __m128, k: __mmask8) -> __m128 { + let fnmsub = _mm_fnmsub_ps(a, b, c).as_f32x4(); + transmute(simd_select_bitmask(k, fnmsub, c.as_f32x4())) +} + /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmsub_pd&expand=2759) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_pd&expand=2759) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -1789,17 +4158,12 @@ pub unsafe fn _mm512_fnmsub_pd(a: __m512d, b: __m512d, c: __m512d) -> __m512d { let zero: f64x8 = mem::zeroed(); let suba = simd_sub(zero, a.as_f64x8()); let subc = simd_sub(zero, c.as_f64x8()); - transmute(vfmadd132pd( - suba, - b.as_f64x8(), - subc, - _MM_FROUND_CUR_DIRECTION, - )) + transmute(vfmadd132pd(suba, b.as_f64x8(), subc)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmsub_pd&expand=2760) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_pd&expand=2760) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -1810,7 +4174,7 @@ pub unsafe fn _mm512_mask_fnmsub_pd(a: __m512d, k: __mmask8, b: __m512d, c: __m5 /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmsub_pd&expand=2762) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_pd&expand=2762) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -1822,7 +4186,7 @@ pub unsafe fn _mm512_maskz_fnmsub_pd(k: __mmask8, a: __m512d, b: __m512d, c: __m /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmsub_pd&expand=2761) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_pd&expand=2761) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -1831,9 +4195,77 @@ pub unsafe fn _mm512_mask3_fnmsub_pd(a: __m512d, b: __m512d, c: __m512d, k: __mm transmute(simd_select_bitmask(k, fnmsub, c.as_f64x8())) } +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fnmsub_pd&expand=2756) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd +pub unsafe fn _mm256_mask_fnmsub_pd(a: __m256d, k: __mmask8, b: __m256d, c: __m256d) -> __m256d { + let fnmsub = _mm256_fnmsub_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fnmsub, a.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fnmsub_pd&expand=2758) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd +pub unsafe fn _mm256_maskz_fnmsub_pd(k: __mmask8, a: __m256d, b: __m256d, c: __m256d) -> __m256d { + let fnmsub = _mm256_fnmsub_pd(a, b, c).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, fnmsub, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask3_fnmsub_pd&expand=2757) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd +pub unsafe fn _mm256_mask3_fnmsub_pd(a: __m256d, b: __m256d, c: __m256d, k: __mmask8) -> __m256d { + let fnmsub = _mm256_fnmsub_pd(a, b, c).as_f64x4(); + transmute(simd_select_bitmask(k, fnmsub, c.as_f64x4())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fnmsub_pd&expand=2752) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd +pub unsafe fn _mm_mask_fnmsub_pd(a: __m128d, k: __mmask8, b: __m128d, c: __m128d) -> __m128d { + let fnmsub = _mm_fnmsub_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fnmsub, a.as_f64x2())) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fnmsub_pd&expand=2754) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd +pub unsafe fn _mm_maskz_fnmsub_pd(k: __mmask8, a: __m128d, b: __m128d, c: __m128d) -> __m128d { + let fnmsub = _mm_fnmsub_pd(a, b, c).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, fnmsub, zero)) +} + +/// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using writemask k (elements are copied from c when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask3_fnmsub_pd&expand=2753) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfnmsub))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd +pub unsafe fn _mm_mask3_fnmsub_pd(a: __m128d, b: __m128d, c: __m128d, k: __mmask8) -> __m128d { + let fnmsub = _mm_fnmsub_pd(a, b, c).as_f64x2(); + transmute(simd_select_bitmask(k, fnmsub, c.as_f64x2())) +} + /// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rcp14_ps&expand=4502) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rcp14_ps&expand=4502) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrcp14ps))] @@ -1847,7 +4279,7 @@ pub unsafe fn _mm512_rcp14_ps(a: __m512) -> __m512 { /// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rcp14_ps&expand=4500) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rcp14_ps&expand=4500) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrcp14ps))] @@ -1857,7 +4289,7 @@ pub unsafe fn _mm512_mask_rcp14_ps(src: __m512, k: __mmask16, a: __m512) -> __m5 /// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rcp14_ps&expand=4501) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rcp14_ps&expand=4501) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrcp14ps))] @@ -1865,9 +4297,77 @@ pub unsafe fn _mm512_maskz_rcp14_ps(k: __mmask16, a: __m512) -> __m512 { transmute(vrcp14ps(a.as_f32x16(), _mm512_setzero_ps().as_f32x16(), k)) } +/// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rcp14_ps&expand=4499) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14ps))] +pub unsafe fn _mm256_rcp14_ps(a: __m256) -> __m256 { + transmute(vrcp14ps256( + a.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + 0b11111111, + )) +} + +/// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rcp14_ps&expand=4497) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14ps))] +pub unsafe fn _mm256_mask_rcp14_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + transmute(vrcp14ps256(a.as_f32x8(), src.as_f32x8(), k)) +} + +/// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rcp14_ps&expand=4498) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14ps))] +pub unsafe fn _mm256_maskz_rcp14_ps(k: __mmask8, a: __m256) -> __m256 { + transmute(vrcp14ps256(a.as_f32x8(), _mm256_setzero_ps().as_f32x8(), k)) +} + +/// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp14_ps&expand=4496) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14ps))] +pub unsafe fn _mm_rcp14_ps(a: __m128) -> __m128 { + transmute(vrcp14ps128( + a.as_f32x4(), + _mm_setzero_ps().as_f32x4(), + 0b00001111, + )) +} + +/// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rcp14_ps&expand=4494) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14ps))] +pub unsafe fn _mm_mask_rcp14_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + transmute(vrcp14ps128(a.as_f32x4(), src.as_f32x4(), k)) +} + +/// Compute the approximate reciprocal of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rcp14_ps&expand=4495) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14ps))] +pub unsafe fn _mm_maskz_rcp14_ps(k: __mmask8, a: __m128) -> __m128 { + transmute(vrcp14ps128(a.as_f32x4(), _mm_setzero_ps().as_f32x4(), k)) +} + /// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rcp14_pd&expand=4493) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rcp14_pd&expand=4493) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrcp14pd))] @@ -1881,7 +4381,7 @@ pub unsafe fn _mm512_rcp14_pd(a: __m512d) -> __m512d { /// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rcp14_pd&expand=4491) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rcp14_pd&expand=4491) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrcp14pd))] @@ -1891,7 +4391,7 @@ pub unsafe fn _mm512_mask_rcp14_pd(src: __m512d, k: __mmask8, a: __m512d) -> __m /// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rcp14_pd&expand=4492) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rcp14_pd&expand=4492) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrcp14pd))] @@ -1899,23 +4399,91 @@ pub unsafe fn _mm512_maskz_rcp14_pd(k: __mmask8, a: __m512d) -> __m512d { transmute(vrcp14pd(a.as_f64x8(), _mm512_setzero_pd().as_f64x8(), k)) } -/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. +/// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rsqrt14_ps&expand=4819) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rcp14_pd&expand=4490) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vrsqrt14ps))] -pub unsafe fn _mm512_rsqrt14_ps(a: __m512) -> __m512 { - transmute(vrsqrt14ps( - a.as_f32x16(), - _mm512_setzero_ps().as_f32x16(), - 0b11111111_11111111, +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14pd))] +pub unsafe fn _mm256_rcp14_pd(a: __m256d) -> __m256d { + transmute(vrcp14pd256( + a.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + 0b00001111, )) } -/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rcp14_pd&expand=4488) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14pd))] +pub unsafe fn _mm256_mask_rcp14_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + transmute(vrcp14pd256(a.as_f64x4(), src.as_f64x4(), k)) +} + +/// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rcp14_pd&expand=4489) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14pd))] +pub unsafe fn _mm256_maskz_rcp14_pd(k: __mmask8, a: __m256d) -> __m256d { + transmute(vrcp14pd256(a.as_f64x4(), _mm256_setzero_pd().as_f64x4(), k)) +} + +/// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp14_pd&expand=4487) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14pd))] +pub unsafe fn _mm_rcp14_pd(a: __m128d) -> __m128d { + transmute(vrcp14pd128( + a.as_f64x2(), + _mm_setzero_pd().as_f64x2(), + 0b00000011, + )) +} + +/// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rcp14_pd&expand=4485) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14pd))] +pub unsafe fn _mm_mask_rcp14_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + transmute(vrcp14pd128(a.as_f64x2(), src.as_f64x2(), k)) +} + +/// Compute the approximate reciprocal of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rcp14_pd&expand=4486) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrcp14pd))] +pub unsafe fn _mm_maskz_rcp14_pd(k: __mmask8, a: __m128d) -> __m128d { + transmute(vrcp14pd128(a.as_f64x2(), _mm_setzero_pd().as_f64x2(), k)) +} + +/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rsqrt14_ps&expand=4819) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vrsqrt14ps))] +pub unsafe fn _mm512_rsqrt14_ps(a: __m512) -> __m512 { + transmute(vrsqrt14ps( + a.as_f32x16(), + _mm512_setzero_ps().as_f32x16(), + 0b11111111_11111111, + )) +} + +/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rsqrt14_ps&expand=4817) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rsqrt14_ps&expand=4817) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrsqrt14ps))] @@ -1925,7 +4493,7 @@ pub unsafe fn _mm512_mask_rsqrt14_ps(src: __m512, k: __mmask16, a: __m512) -> __ /// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rsqrt14_ps&expand=4818) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rsqrt14_ps&expand=4818) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrsqrt14ps))] @@ -1937,9 +4505,53 @@ pub unsafe fn _mm512_maskz_rsqrt14_ps(k: __mmask16, a: __m512) -> __m512 { )) } +/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rsqrt14_ps&expand=4815) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14ps))] +pub unsafe fn _mm256_mask_rsqrt14_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + transmute(vrsqrt14ps256(a.as_f32x8(), src.as_f32x8(), k)) +} + +/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rsqrt14_ps&expand=4816) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14ps))] +pub unsafe fn _mm256_maskz_rsqrt14_ps(k: __mmask8, a: __m256) -> __m256 { + transmute(vrsqrt14ps256( + a.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + k, + )) +} + +/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rsqrt14_ps&expand=4813) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14ps))] +pub unsafe fn _mm_mask_rsqrt14_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + transmute(vrsqrt14ps128(a.as_f32x4(), src.as_f32x4(), k)) +} + +/// Compute the approximate reciprocal square root of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rsqrt14_ps&expand=4814) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14ps))] +pub unsafe fn _mm_maskz_rsqrt14_ps(k: __mmask8, a: __m128) -> __m128 { + transmute(vrsqrt14ps128(a.as_f32x4(), _mm_setzero_ps().as_f32x4(), k)) +} + /// Compute the approximate reciprocal square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rsqrt14_pd&expand=4812) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rsqrt14_pd&expand=4812) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrsqrt14pd))] @@ -1953,7 +4565,7 @@ pub unsafe fn _mm512_rsqrt14_pd(a: __m512d) -> __m512d { /// Compute the approximate reciprocal square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rsqrt14_pd&expand=4810) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rsqrt14_pd&expand=4810) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrsqrt14pd))] @@ -1963,7 +4575,7 @@ pub unsafe fn _mm512_mask_rsqrt14_pd(src: __m512d, k: __mmask8, a: __m512d) -> _ /// Compute the approximate reciprocal square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rsqrt14_pd&expand=4811) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rsqrt14_pd&expand=4811) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrsqrt14pd))] @@ -1971,9 +4583,53 @@ pub unsafe fn _mm512_maskz_rsqrt14_pd(k: __mmask8, a: __m512d) -> __m512d { transmute(vrsqrt14pd(a.as_f64x8(), _mm512_setzero_pd().as_f64x8(), k)) } +/// Compute the approximate reciprocal square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rsqrt14_pd&expand=4808) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14pd))] +pub unsafe fn _mm256_mask_rsqrt14_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + transmute(vrsqrt14pd256(a.as_f64x4(), src.as_f64x4(), k)) +} + +/// Compute the approximate reciprocal square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rsqrt14_pd&expand=4809) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14pd))] +pub unsafe fn _mm256_maskz_rsqrt14_pd(k: __mmask8, a: __m256d) -> __m256d { + transmute(vrsqrt14pd256( + a.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + k, + )) +} + +/// Compute the approximate reciprocal square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rsqrt14_pd&expand=4806) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14pd))] +pub unsafe fn _mm_mask_rsqrt14_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + transmute(vrsqrt14pd128(a.as_f64x2(), src.as_f64x2(), k)) +} + +/// Compute the approximate reciprocal square root of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). The maximum relative error for this approximation is less than 2^-14. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rsqrt14_pd&expand=4807) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrsqrt14pd))] +pub unsafe fn _mm_maskz_rsqrt14_pd(k: __mmask8, a: __m128d) -> __m128d { + transmute(vrsqrt14pd128(a.as_f64x2(), _mm_setzero_pd().as_f64x2(), k)) +} + /// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getexp_ps&expand=2844) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_ps&expand=2844) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexpps))] @@ -1988,7 +4644,7 @@ pub unsafe fn _mm512_getexp_ps(a: __m512) -> __m512 { /// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getexp_ps&expand=2845) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_ps&expand=2845) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexpps))] @@ -2003,7 +4659,7 @@ pub unsafe fn _mm512_mask_getexp_ps(src: __m512, k: __mmask16, a: __m512) -> __m /// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getexp_ps&expand=2846) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_ps&expand=2846) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexpps))] @@ -2016,9 +4672,81 @@ pub unsafe fn _mm512_maskz_getexp_ps(k: __mmask16, a: __m512) -> __m512 { )) } +/// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_getexp_ps&expand=2841) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexpps))] +pub unsafe fn _mm256_getexp_ps(a: __m256) -> __m256 { + transmute(vgetexpps256( + a.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + 0b11111111, + )) +} + +/// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_getexp_ps&expand=2842) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexpps))] +pub unsafe fn _mm256_mask_getexp_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + transmute(vgetexpps256(a.as_f32x8(), src.as_f32x8(), k)) +} + +/// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_getexp_ps&expand=2843) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexpps))] +pub unsafe fn _mm256_maskz_getexp_ps(k: __mmask8, a: __m256) -> __m256 { + transmute(vgetexpps256( + a.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + k, + )) +} + +/// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getexp_ps&expand=2838) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexpps))] +pub unsafe fn _mm_getexp_ps(a: __m128) -> __m128 { + transmute(vgetexpps128( + a.as_f32x4(), + _mm_setzero_ps().as_f32x4(), + 0b00001111, + )) +} + +/// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getexp_ps&expand=2839) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexpps))] +pub unsafe fn _mm_mask_getexp_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + transmute(vgetexpps128(a.as_f32x4(), src.as_f32x4(), k)) +} + +/// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getexp_ps&expand=2840) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexpps))] +pub unsafe fn _mm_maskz_getexp_ps(k: __mmask8, a: __m128) -> __m128 { + transmute(vgetexpps128(a.as_f32x4(), _mm_setzero_ps().as_f32x4(), k)) +} + /// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getexp_pd&expand=2835) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_pd&expand=2835) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexppd))] @@ -2033,7 +4761,7 @@ pub unsafe fn _mm512_getexp_pd(a: __m512d) -> __m512d { /// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getexp_pd&expand=2836) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_pd&expand=2836) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexppd))] @@ -2048,7 +4776,7 @@ pub unsafe fn _mm512_mask_getexp_pd(src: __m512d, k: __mmask8, a: __m512d) -> __ /// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getexp_pd&expand=2837) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_pd&expand=2837) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexppd))] @@ -2061,6 +4789,78 @@ pub unsafe fn _mm512_maskz_getexp_pd(k: __mmask8, a: __m512d) -> __m512d { )) } +/// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_getexp_pd&expand=2832) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexppd))] +pub unsafe fn _mm256_getexp_pd(a: __m256d) -> __m256d { + transmute(vgetexppd256( + a.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + 0b00001111, + )) +} + +/// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_getexp_pd&expand=2833) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexppd))] +pub unsafe fn _mm256_mask_getexp_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + transmute(vgetexppd256(a.as_f64x4(), src.as_f64x4(), k)) +} + +/// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_getexp_pd&expand=2834) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexppd))] +pub unsafe fn _mm256_maskz_getexp_pd(k: __mmask8, a: __m256d) -> __m256d { + transmute(vgetexppd256( + a.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + k, + )) +} + +/// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getexp_pd&expand=2829) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexppd))] +pub unsafe fn _mm_getexp_pd(a: __m128d) -> __m128d { + transmute(vgetexppd128( + a.as_f64x2(), + _mm_setzero_pd().as_f64x2(), + 0b00000011, + )) +} + +/// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getexp_pd&expand=2830) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexppd))] +pub unsafe fn _mm_mask_getexp_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + transmute(vgetexppd128(a.as_f64x2(), src.as_f64x2(), k)) +} + +/// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getexp_pd&expand=2831) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetexppd))] +pub unsafe fn _mm_maskz_getexp_pd(k: __mmask8, a: __m128d) -> __m128d { + transmute(vgetexppd128(a.as_f64x2(), _mm_setzero_pd().as_f64x2(), k)) +} + /// Round packed single-precision (32-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst.\ /// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ /// _MM_FROUND_TO_NEAREST_INT // round to nearest\ @@ -2069,7 +4869,7 @@ pub unsafe fn _mm512_maskz_getexp_pd(k: __mmask8, a: __m512d) -> __m512d { /// _MM_FROUND_TO_ZERO // truncate\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_roundscale_ps&expand=4784) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_ps&expand=4784) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0))] @@ -2100,7 +4900,7 @@ pub unsafe fn _mm512_roundscale_ps(a: __m512, imm8: i32) -> __m512 { /// _MM_FROUND_TO_ZERO // truncate\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_roundscale_ps&expand=4782) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_ps&expand=4782) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0))] @@ -2125,7 +4925,7 @@ pub unsafe fn _mm512_mask_roundscale_ps(src: __m512, k: __mmask16, a: __m512, im /// _MM_FROUND_TO_ZERO // truncate\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_roundscale_ps&expand=4783) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_ps&expand=4783) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0))] @@ -2142,6 +4942,156 @@ pub unsafe fn _mm512_maskz_roundscale_ps(k: __mmask16, a: __m512, imm8: i32) -> transmute(r) } +/// Round packed single-precision (32-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst.\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_roundscale_ps&expand=4781) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 250))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_roundscale_ps(a: __m256, imm8: i32) -> __m256 { + let a = a.as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + macro_rules! call { + ($imm8:expr) => { + vrndscaleps256(a, $imm8, zero, 0b11111111) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed single-precision (32-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_roundscale_ps&expand=4779) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_roundscale_ps(src: __m256, k: __mmask8, a: __m256, imm8: i32) -> __m256 { + let a = a.as_f32x8(); + let src = src.as_f32x8(); + macro_rules! call { + ($imm8:expr) => { + vrndscaleps256(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed single-precision (32-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_roundscale_ps&expand=4780) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_roundscale_ps(k: __mmask8, a: __m256, imm8: i32) -> __m256 { + let a = a.as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + macro_rules! call { + ($imm8:expr) => { + vrndscaleps256(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed single-precision (32-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst.\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_roundscale_ps&expand=4778) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 250))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_roundscale_ps(a: __m128, imm8: i32) -> __m128 { + let a = a.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + macro_rules! call { + ($imm8:expr) => { + vrndscaleps128(a, $imm8, zero, 0b00001111) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed single-precision (32-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_roundscale_ps&expand=4776) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_roundscale_ps(src: __m128, k: __mmask8, a: __m128, imm8: i32) -> __m128 { + let a = a.as_f32x4(); + let src = src.as_f32x4(); + macro_rules! call { + ($imm8:expr) => { + vrndscaleps128(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed single-precision (32-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_roundscale_ps&expand=4777) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_roundscale_ps(k: __mmask8, a: __m128, imm8: i32) -> __m128 { + let a = a.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + macro_rules! call { + ($imm8:expr) => { + vrndscaleps128(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + /// Round packed double-precision (64-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst.\ /// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ /// _MM_FROUND_TO_NEAREST_INT // round to nearest\ @@ -2150,7 +5100,7 @@ pub unsafe fn _mm512_maskz_roundscale_ps(k: __mmask16, a: __m512, imm8: i32) -> /// _MM_FROUND_TO_ZERO // truncate\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_roundscale_pd&expand=4775) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_pd&expand=4775) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] @@ -2175,7 +5125,7 @@ pub unsafe fn _mm512_roundscale_pd(a: __m512d, imm8: i32) -> __m512d { /// _MM_FROUND_TO_ZERO // truncate\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_roundscale_pd&expand=4773) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_pd&expand=4773) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] @@ -2205,7 +5155,7 @@ pub unsafe fn _mm512_mask_roundscale_pd( /// _MM_FROUND_TO_ZERO // truncate\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_roundscale_pd&expand=4774) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_pd&expand=4774) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] @@ -2222,9 +5172,164 @@ pub unsafe fn _mm512_maskz_roundscale_pd(k: __mmask8, a: __m512d, imm8: i32) -> transmute(r) } +/// Round packed double-precision (64-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst.\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_roundscale_pd&expand=4772) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_roundscale_pd(a: __m256d, imm8: i32) -> __m256d { + let a = a.as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + macro_rules! call { + ($imm8:expr) => { + vrndscalepd256(a, $imm8, zero, 0b00001111) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed double-precision (64-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_roundscale_pd&expand=4770) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_roundscale_pd( + src: __m256d, + k: __mmask8, + a: __m256d, + imm8: i32, +) -> __m256d { + let a = a.as_f64x4(); + let src = src.as_f64x4(); + macro_rules! call { + ($imm8:expr) => { + vrndscalepd256(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed double-precision (64-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_roundscale_pd&expand=4771) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_roundscale_pd(k: __mmask8, a: __m256d, imm8: i32) -> __m256d { + let a = a.as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + macro_rules! call { + ($imm8:expr) => { + vrndscalepd256(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed double-precision (64-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst.\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_roundscale_pd&expand=4769) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_roundscale_pd(a: __m128d, imm8: i32) -> __m128d { + let a = a.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + macro_rules! call { + ($imm8:expr) => { + vrndscalepd128(a, $imm8, zero, 0b00000011) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed double-precision (64-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_roundscale_pd&expand=4767) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_roundscale_pd(src: __m128d, k: __mmask8, a: __m128d, imm8: i32) -> __m128d { + let a = a.as_f64x2(); + let src = src.as_f64x2(); + macro_rules! call { + ($imm8:expr) => { + vrndscalepd128(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Round packed double-precision (64-bit) floating-point elements in a to the number of fraction bits specified by imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_roundscale_pd&expand=4768) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_roundscale_pd(k: __mmask8, a: __m128d, imm8: i32) -> __m128d { + let a = a.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + macro_rules! call { + ($imm8:expr) => { + vrndscalepd128(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + /// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_scalef_ps&expand=4883) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_ps&expand=4883) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefps))] @@ -2240,7 +5345,7 @@ pub unsafe fn _mm512_scalef_ps(a: __m512, b: __m512) -> __m512 { /// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_scalef_ps&expand=4881) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_ps&expand=4881) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefps))] @@ -2256,7 +5361,7 @@ pub unsafe fn _mm512_mask_scalef_ps(src: __m512, k: __mmask16, a: __m512, b: __m /// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_scalef_ps&expand=4882) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_ps&expand=4882) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefps))] @@ -2270,9 +5375,89 @@ pub unsafe fn _mm512_maskz_scalef_ps(k: __mmask16, a: __m512, b: __m512) -> __m5 )) } +/// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_scalef_ps&expand=4880) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefps))] +pub unsafe fn _mm256_scalef_ps(a: __m256, b: __m256) -> __m256 { + transmute(vscalefps256( + a.as_f32x8(), + b.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + 0b11111111, + )) +} + +/// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_scalef_ps&expand=4878) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefps))] +pub unsafe fn _mm256_mask_scalef_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + transmute(vscalefps256(a.as_f32x8(), b.as_f32x8(), src.as_f32x8(), k)) +} + +/// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_scalef_ps&expand=4879) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefps))] +pub unsafe fn _mm256_maskz_scalef_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + transmute(vscalefps256( + a.as_f32x8(), + b.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + k, + )) +} + +/// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_scalef_ps&expand=4877) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefps))] +pub unsafe fn _mm_scalef_ps(a: __m128, b: __m128) -> __m128 { + transmute(vscalefps128( + a.as_f32x4(), + b.as_f32x4(), + _mm_setzero_ps().as_f32x4(), + 0b00001111, + )) +} + +/// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_scalef_ps&expand=4875) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefps))] +pub unsafe fn _mm_mask_scalef_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + transmute(vscalefps128(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k)) +} + +/// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_scalef_ps&expand=4876) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefps))] +pub unsafe fn _mm_maskz_scalef_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + transmute(vscalefps128( + a.as_f32x4(), + b.as_f32x4(), + _mm_setzero_ps().as_f32x4(), + k, + )) +} + /// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_scalef_pd&expand=4874) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_pd&expand=4874) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefpd))] @@ -2288,7 +5473,7 @@ pub unsafe fn _mm512_scalef_pd(a: __m512d, b: __m512d) -> __m512d { /// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_scalef_pd&expand=4872) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_pd&expand=4872) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefpd))] @@ -2304,7 +5489,7 @@ pub unsafe fn _mm512_mask_scalef_pd(src: __m512d, k: __mmask8, a: __m512d, b: __ /// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_scalef_pd&expand=4873) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_pd&expand=4873) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefpd))] @@ -2318,36 +5503,116 @@ pub unsafe fn _mm512_maskz_scalef_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m )) } -/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting. +/// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fixupimm_ps&expand=2499) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_scalef_pd&expand=4871) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] -#[rustc_args_required_const(3)] -pub unsafe fn _mm512_fixupimm_ps(a: __m512, b: __m512, c: __m512i, imm8: i32) -> __m512 { - let a = a.as_f32x16(); - let b = b.as_f32x16(); - let c = c.as_i32x16(); - macro_rules! call { - ($imm8:expr) => { - vfixupimmps( - a, - b, - c, - $imm8, - 0b11111111_11111111, - _MM_FROUND_CUR_DIRECTION, - ) - }; - } - let r = constify_imm8_sae!(imm8, call); - transmute(r) -} +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefpd))] +pub unsafe fn _mm256_scalef_pd(a: __m256d, b: __m256d) -> __m256d { + transmute(vscalefpd256( + a.as_f64x4(), + b.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + 0b00001111, + )) +} + +/// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_scalef_pd&expand=4869) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefpd))] +pub unsafe fn _mm256_mask_scalef_pd(src: __m256d, k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + transmute(vscalefpd256(a.as_f64x4(), b.as_f64x4(), src.as_f64x4(), k)) +} + +/// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_scalef_pd&expand=4870) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefpd))] +pub unsafe fn _mm256_maskz_scalef_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + transmute(vscalefpd256( + a.as_f64x4(), + b.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + k, + )) +} + +/// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_scalef_pd&expand=4868) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefpd))] +pub unsafe fn _mm_scalef_pd(a: __m128d, b: __m128d) -> __m128d { + transmute(vscalefpd128( + a.as_f64x2(), + b.as_f64x2(), + _mm_setzero_pd().as_f64x2(), + 0b00000011, + )) +} + +/// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_scalef_pd&expand=4866) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefpd))] +pub unsafe fn _mm_mask_scalef_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + transmute(vscalefpd128(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k)) +} + +/// Scale the packed double-precision (64-bit) floating-point elements in a using values from b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_scalef_pd&expand=4867) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vscalefpd))] +pub unsafe fn _mm_maskz_scalef_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + transmute(vscalefpd128( + a.as_f64x2(), + b.as_f64x2(), + _mm_setzero_pd().as_f64x2(), + k, + )) +} + +/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_ps&expand=2499) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_fixupimm_ps(a: __m512, b: __m512, c: __m512i, imm8: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_i32x16(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmps( + a, + b, + c, + $imm8, + 0b11111111_11111111, + _MM_FROUND_CUR_DIRECTION, + ) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} /// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fixupimm_ps&expand=2500) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_ps&expand=2500) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] @@ -2373,7 +5638,7 @@ pub unsafe fn _mm512_mask_fixupimm_ps( /// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fixupimm_ps&expand=2501) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_ps&expand=2501) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] @@ -2397,9 +5662,153 @@ pub unsafe fn _mm512_maskz_fixupimm_ps( transmute(r) } +/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_fixupimm_ps&expand=2496) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_fixupimm_ps(a: __m256, b: __m256, c: __m256i, imm8: i32) -> __m256 { + let a = a.as_f32x8(); + let b = b.as_f32x8(); + let c = c.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmps256(a, b, c, $imm8, 0b11111111) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fixupimm_ps&expand=2497) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_fixupimm_ps( + a: __m256, + k: __mmask8, + b: __m256, + c: __m256i, + imm8: i32, +) -> __m256 { + let a = a.as_f32x8(); + let b = b.as_f32x8(); + let c = c.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmps256(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fixupimm_ps&expand=2498) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_maskz_fixupimm_ps( + k: __mmask8, + a: __m256, + b: __m256, + c: __m256i, + imm8: i32, +) -> __m256 { + let a = a.as_f32x8(); + let b = b.as_f32x8(); + let c = c.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpsz256(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fixupimm_ps&expand=2493) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_fixupimm_ps(a: __m128, b: __m128, c: __m128i, imm8: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let c = c.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmps128(a, b, c, $imm8, 0b00001111) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fixupimm_ps&expand=2494) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_fixupimm_ps( + a: __m128, + k: __mmask8, + b: __m128, + c: __m128i, + imm8: i32, +) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let c = c.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmps128(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fixupimm_ps&expand=2495) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_maskz_fixupimm_ps( + k: __mmask8, + a: __m128, + b: __m128, + c: __m128i, + imm8: i32, +) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let c = c.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpsz128(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + /// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fixupimm_pd&expand=2490) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_pd&expand=2490) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] @@ -2419,7 +5828,7 @@ pub unsafe fn _mm512_fixupimm_pd(a: __m512d, b: __m512d, c: __m512i, imm8: i32) /// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fixupimm_pd&expand=2491) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_pd&expand=2491) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] @@ -2445,7 +5854,7 @@ pub unsafe fn _mm512_mask_fixupimm_pd( /// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fixupimm_pd&expand=2492) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_pd&expand=2492) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] @@ -2469,9 +5878,153 @@ pub unsafe fn _mm512_maskz_fixupimm_pd( transmute(r) } +/// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_fixupimm_pd&expand=2487) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_fixupimm_pd(a: __m256d, b: __m256d, c: __m256i, imm8: i32) -> __m256d { + let a = a.as_f64x4(); + let b = b.as_f64x4(); + let c = c.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpd256(a, b, c, $imm8, 0b00001111) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_fixupimm_pd&expand=2488) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_fixupimm_pd( + a: __m256d, + k: __mmask8, + b: __m256d, + c: __m256i, + imm8: i32, +) -> __m256d { + let a = a.as_f64x4(); + let b = b.as_f64x4(); + let c = c.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpd256(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_fixupimm_pd&expand=2489) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_maskz_fixupimm_pd( + k: __mmask8, + a: __m256d, + b: __m256d, + c: __m256i, + imm8: i32, +) -> __m256d { + let a = a.as_f64x4(); + let b = b.as_f64x4(); + let c = c.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpdz256(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fixupimm_pd&expand=2484) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_fixupimm_pd(a: __m128d, b: __m128d, c: __m128i, imm8: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let c = c.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpd128(a, b, c, $imm8, 0b00000011) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_fixupimm_pd&expand=2485) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_fixupimm_pd( + a: __m128d, + k: __mmask8, + b: __m128d, + c: __m128i, + imm8: i32, +) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let c = c.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpd128(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_fixupimm_pd&expand=2486) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_maskz_fixupimm_pd( + k: __mmask8, + a: __m128d, + b: __m128d, + c: __m128i, + imm8: i32, +) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let c = c.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vfixupimmpdz128(a, b, c, $imm8, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + /// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_ternarylogic_epi32&expand=5867) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ternarylogic_epi32&expand=5867) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] @@ -2491,7 +6044,7 @@ pub unsafe fn _mm512_ternarylogic_epi32(a: __m512i, b: __m512i, c: __m512i, imm8 /// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from src, a, and b are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using writemask k at 32-bit granularity (32-bit elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_ternarylogic_epi32&expand=5865) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ternarylogic_epi32&expand=5865) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] @@ -2517,7 +6070,7 @@ pub unsafe fn _mm512_mask_ternarylogic_epi32( /// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using zeromask k at 32-bit granularity (32-bit elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_ternarylogic_epi32&expand=5866) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ternarylogic_epi32&expand=5866) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] @@ -2542,9 +6095,155 @@ pub unsafe fn _mm512_maskz_ternarylogic_epi32( transmute(simd_select_bitmask(k, ternarylogic, zero)) } +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_ternarylogic_epi32&expand=5864) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_ternarylogic_epi32(a: __m256i, b: __m256i, c: __m256i, imm8: i32) -> __m256i { + let a = a.as_i32x8(); + let b = b.as_i32x8(); + let c = c.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vpternlogd256(a, b, c, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from src, a, and b are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using writemask k at 32-bit granularity (32-bit elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_ternarylogic_epi32&expand=5862) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_ternarylogic_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + let src = src.as_i32x8(); + let a = a.as_i32x8(); + let b = b.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vpternlogd256(src, a, b, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ternarylogic, src)) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using zeromask k at 32-bit granularity (32-bit elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_ternarylogic_epi32&expand=5863) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_maskz_ternarylogic_epi32( + k: __mmask8, + a: __m256i, + b: __m256i, + c: __m256i, + imm8: i32, +) -> __m256i { + let a = a.as_i32x8(); + let b = b.as_i32x8(); + let c = c.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vpternlogd256(a, b, c, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, ternarylogic, zero)) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ternarylogic_epi32&expand=5861) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_ternarylogic_epi32(a: __m128i, b: __m128i, c: __m128i, imm8: i32) -> __m128i { + let a = a.as_i32x4(); + let b = b.as_i32x4(); + let c = c.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vpternlogd128(a, b, c, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from src, a, and b are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using writemask k at 32-bit granularity (32-bit elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_ternarylogic_epi32&expand=5859) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_ternarylogic_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + let src = src.as_i32x4(); + let a = a.as_i32x4(); + let b = b.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vpternlogd128(src, a, b, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ternarylogic, src)) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 32-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using zeromask k at 32-bit granularity (32-bit elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_ternarylogic_epi32&expand=5860) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogd, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_maskz_ternarylogic_epi32( + k: __mmask8, + a: __m128i, + b: __m128i, + c: __m128i, + imm8: i32, +) -> __m128i { + let a = a.as_i32x4(); + let b = b.as_i32x4(); + let c = c.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vpternlogd128(a, b, c, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, ternarylogic, zero)) +} + /// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_ternarylogic_epi64&expand=5876) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ternarylogic_epi64&expand=5876) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] @@ -2564,7 +6263,7 @@ pub unsafe fn _mm512_ternarylogic_epi64(a: __m512i, b: __m512i, c: __m512i, imm8 /// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from src, a, and b are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using writemask k at 64-bit granularity (64-bit elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_ternarylogic_epi64&expand=5874) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ternarylogic_epi64&expand=5874) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] @@ -2590,7 +6289,7 @@ pub unsafe fn _mm512_mask_ternarylogic_epi64( /// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using zeromask k at 64-bit granularity (64-bit elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_ternarylogic_epi64&expand=5875) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ternarylogic_epi64&expand=5875) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] @@ -2615,6 +6314,152 @@ pub unsafe fn _mm512_maskz_ternarylogic_epi64( transmute(simd_select_bitmask(k, ternarylogic, zero)) } +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_ternarylogic_epi64&expand=5873) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_ternarylogic_epi64(a: __m256i, b: __m256i, c: __m256i, imm8: i32) -> __m256i { + let a = a.as_i64x4(); + let b = b.as_i64x4(); + let c = c.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vpternlogq256(a, b, c, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from src, a, and b are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using writemask k at 64-bit granularity (64-bit elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_ternarylogic_epi64&expand=5871) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_ternarylogic_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + let src = src.as_i64x4(); + let a = a.as_i64x4(); + let b = b.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vpternlogq256(src, a, b, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ternarylogic, src)) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using zeromask k at 64-bit granularity (64-bit elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_ternarylogic_epi64&expand=5872) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_maskz_ternarylogic_epi64( + k: __mmask8, + a: __m256i, + b: __m256i, + c: __m256i, + imm8: i32, +) -> __m256i { + let a = a.as_i64x4(); + let b = b.as_i64x4(); + let c = c.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vpternlogq256(a, b, c, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, ternarylogic, zero)) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ternarylogic_epi64&expand=5870) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_ternarylogic_epi64(a: __m128i, b: __m128i, c: __m128i, imm8: i32) -> __m128i { + let a = a.as_i64x2(); + let b = b.as_i64x2(); + let c = c.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vpternlogq128(a, b, c, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from src, a, and b are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using writemask k at 64-bit granularity (64-bit elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_ternarylogic_epi64&expand=5868) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_ternarylogic_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + let src = src.as_i64x2(); + let a = a.as_i64x2(); + let b = b.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vpternlogq128(src, a, b, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ternarylogic, src)) +} + +/// Bitwise ternary logic that provides the capability to implement any three-operand binary function; the specific binary function is specified by value in imm8. For each bit in each packed 64-bit integer, the corresponding bit from a, b, and c are used to form a 3 bit index into imm8, and the value at that bit in imm8 is written to the corresponding bit in dst using zeromask k at 64-bit granularity (64-bit elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_ternarylogic_epi64&expand=5869) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpternlogq, imm8 = 114))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_maskz_ternarylogic_epi64( + k: __mmask8, + a: __m128i, + b: __m128i, + c: __m128i, + imm8: i32, +) -> __m128i { + let a = a.as_i64x2(); + let b = b.as_i64x2(); + let c = c.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vpternlogq128(a, b, c, $imm8) + }; + } + let ternarylogic = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, ternarylogic, zero)) +} + /// Normalize the mantissas of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign. /// The mantissa is normalized to the interval specified by interv, which can take the following values: /// _MM_MANT_NORM_1_2 // interval [1, 2) @@ -2626,7 +6471,7 @@ pub unsafe fn _mm512_maskz_ternarylogic_epi64( /// _MM_MANT_SIGN_zero // sign = 0 /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getmant_ps&expand=2880) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_ps&expand=2880) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] @@ -2636,12 +6481,14 @@ pub unsafe fn _mm512_getmant_ps( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m512 { + let a = a.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr, $imm2:expr) => { vgetmantps( - a.as_f32x16(), + a, $imm2 << 2 | $imm4, - _mm512_setzero_ps().as_f32x16(), + zero, 0b11111111_11111111, _MM_FROUND_CUR_DIRECTION, ) @@ -2662,7 +6509,7 @@ pub unsafe fn _mm512_getmant_ps( /// _MM_MANT_SIGN_zero // sign = 0\ /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getmant_ps&expand=2881) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_ps&expand=2881) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] @@ -2674,15 +6521,11 @@ pub unsafe fn _mm512_mask_getmant_ps( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m512 { + let a = a.as_f32x16(); + let src = src.as_f32x16(); macro_rules! call { ($imm4:expr, $imm2:expr) => { - vgetmantps( - a.as_f32x16(), - $imm2 << 2 | $imm4, - src.as_f32x16(), - k, - _MM_FROUND_CUR_DIRECTION, - ) + vgetmantps(a, $imm2 << 2 | $imm4, src, k, _MM_FROUND_CUR_DIRECTION) }; } let r = constify_imm4_mantissas!(norm, sign, call); @@ -2700,7 +6543,7 @@ pub unsafe fn _mm512_mask_getmant_ps( /// _MM_MANT_SIGN_zero // sign = 0\ /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getmant_ps&expand=2882) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getmant_ps&expand=2882) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] @@ -2711,22 +6554,149 @@ pub unsafe fn _mm512_maskz_getmant_ps( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m512 { + let a = a.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr, $imm2:expr) => { - vgetmantps( - a.as_f32x16(), - $imm2 << 2 | $imm4, - _mm512_setzero_ps().as_f32x16(), - k, - _MM_FROUND_CUR_DIRECTION, - ) + vgetmantps(a, $imm2 << 2 | $imm4, zero, k, _MM_FROUND_CUR_DIRECTION) }; } let r = constify_imm4_mantissas!(norm, sign, call); transmute(r) } -/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// Normalize the mantissas of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign. +/// The mantissa is normalized to the interval specified by interv, which can take the following values: +/// _MM_MANT_NORM_1_2 // interval [1, 2) +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2) +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1) +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5) +/// The sign is determined by sc which can take the following values: +/// _MM_MANT_SIGN_src // sign = sign(src) +/// _MM_MANT_SIGN_zero // sign = 0 +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_getmant_ps&expand=2877) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] +#[rustc_args_required_const(1, 2)] +pub unsafe fn _mm256_getmant_ps( + a: __m256, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m256 { + let a = a.as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantps256(a, $imm2 << 2 | $imm4, zero, 0b11111111) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_getmant_ps&expand=2878) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] +#[rustc_args_required_const(3, 4)] +pub unsafe fn _mm256_mask_getmant_ps( + src: __m256, + k: __mmask8, + a: __m256, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m256 { + let a = a.as_f32x8(); + let src = src.as_f32x8(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantps256(a, $imm2 << 2 | $imm4, src, k) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_getmant_ps&expand=2879) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] +#[rustc_args_required_const(2, 3)] +pub unsafe fn _mm256_maskz_getmant_ps( + k: __mmask8, + a: __m256, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m256 { + let a = a.as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantps256(a, $imm2 << 2 | $imm4, zero, k) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed single-precision (32-bit) floating-point elements in a, and store the results in dst. This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign. +/// The mantissa is normalized to the interval specified by interv, which can take the following values: +/// _MM_MANT_NORM_1_2 // interval [1, 2) +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2) +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1) +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5) +/// The sign is determined by sc which can take the following values: +/// _MM_MANT_SIGN_src // sign = sign(src) +/// _MM_MANT_SIGN_zero // sign = 0 +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getmant_ps&expand=2874) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] +#[rustc_args_required_const(1, 2)] +pub unsafe fn _mm_getmant_ps( + a: __m128, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m128 { + let a = a.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantps128(a, $imm2 << 2 | $imm4, zero, 0b00001111) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ /// The mantissa is normalized to the interval specified by interv, which can take the following values:\ /// _MM_MANT_NORM_1_2 // interval [1, 2)\ /// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ @@ -2737,7 +6707,74 @@ pub unsafe fn _mm512_maskz_getmant_ps( /// _MM_MANT_SIGN_zero // sign = 0\ /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getmant_pd&expand=2871) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getmant_ps&expand=2875) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] +#[rustc_args_required_const(3, 4)] +pub unsafe fn _mm_mask_getmant_ps( + src: __m128, + k: __mmask8, + a: __m128, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m128 { + let a = a.as_f32x4(); + let src = src.as_f32x4(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantps128(a, $imm2 << 2 | $imm4, src, k) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed single-precision (32-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getmant_ps&expand=2876) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0))] +#[rustc_args_required_const(2, 3)] +pub unsafe fn _mm_maskz_getmant_ps( + k: __mmask8, + a: __m128, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m128 { + let a = a.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantps128(a, $imm2 << 2 | $imm4, zero, k) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_pd&expand=2871) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] @@ -2747,12 +6784,14 @@ pub unsafe fn _mm512_getmant_pd( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m512d { + let a = a.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr, $imm2:expr) => { vgetmantpd( - a.as_f64x8(), + a, $imm2 << 2 | $imm4, - _mm512_setzero_pd().as_f64x8(), + zero, 0b11111111, _MM_FROUND_CUR_DIRECTION, ) @@ -2773,7 +6812,7 @@ pub unsafe fn _mm512_getmant_pd( /// _MM_MANT_SIGN_zero // sign = 0\ /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getmant_pd&expand=2872) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_pd&expand=2872) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] @@ -2785,15 +6824,11 @@ pub unsafe fn _mm512_mask_getmant_pd( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m512d { + let a = a.as_f64x8(); + let src = src.as_f64x8(); macro_rules! call { ($imm4:expr, $imm2:expr) => { - vgetmantpd( - a.as_f64x8(), - $imm2 << 2 | $imm4, - src.as_f64x8(), - k, - _MM_FROUND_CUR_DIRECTION, - ) + vgetmantpd(a, $imm2 << 2 | $imm4, src, k, _MM_FROUND_CUR_DIRECTION) }; } let r = constify_imm4_mantissas!(norm, sign, call); @@ -2811,7 +6846,7 @@ pub unsafe fn _mm512_mask_getmant_pd( /// _MM_MANT_SIGN_zero // sign = 0\ /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getmant_pd&expand=2873) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getmant_pd&expand=2873) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] @@ -2822,15 +6857,209 @@ pub unsafe fn _mm512_maskz_getmant_pd( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m512d { + let a = a.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr, $imm2:expr) => { - vgetmantpd( - a.as_f64x8(), - $imm2 << 2 | $imm4, - _mm512_setzero_pd().as_f64x8(), - k, - _MM_FROUND_CUR_DIRECTION, - ) + vgetmantpd(a, $imm2 << 2 | $imm4, zero, k, _MM_FROUND_CUR_DIRECTION) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_getmant_pd&expand=2868) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] +#[rustc_args_required_const(1, 2)] +pub unsafe fn _mm256_getmant_pd( + a: __m256d, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m256d { + let a = a.as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantpd256(a, $imm2 << 2 | $imm4, zero, 0b00001111) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_getmant_pd&expand=2869) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] +#[rustc_args_required_const(3, 4)] +pub unsafe fn _mm256_mask_getmant_pd( + src: __m256d, + k: __mmask8, + a: __m256d, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m256d { + let a = a.as_f64x4(); + let src = src.as_f64x4(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantpd256(a, $imm2 << 2 | $imm4, src, k) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_getmant_pd&expand=2870) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] +#[rustc_args_required_const(2, 3)] +pub unsafe fn _mm256_maskz_getmant_pd( + k: __mmask8, + a: __m256d, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m256d { + let a = a.as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantpd256(a, $imm2 << 2 | $imm4, zero, k) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst. This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getmant_pd&expand=2865) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] +#[rustc_args_required_const(1, 2)] +pub unsafe fn _mm_getmant_pd( + a: __m128d, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m128d { + let a = a.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantpd128(a, $imm2 << 2 | $imm4, zero, 0b00000011) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_getmant_pd&expand=2866) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] +#[rustc_args_required_const(3, 4)] +pub unsafe fn _mm_mask_getmant_pd( + src: __m128d, + k: __mmask8, + a: __m128d, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m128d { + let a = a.as_f64x2(); + let src = src.as_f64x2(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantpd128(a, $imm2 << 2 | $imm4, src, k) + }; + } + let r = constify_imm4_mantissas!(norm, sign, call); + transmute(r) +} + +/// Normalize the mantissas of packed double-precision (64-bit) floating-point elements in a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates ±(2^k)*|x.significand|, where k depends on the interval range defined by interv and the sign depends on sc and the source sign.\ +/// The mantissa is normalized to the interval specified by interv, which can take the following values:\ +/// _MM_MANT_NORM_1_2 // interval [1, 2)\ +/// _MM_MANT_NORM_p5_2 // interval [0.5, 2)\ +/// _MM_MANT_NORM_p5_1 // interval [0.5, 1)\ +/// _MM_MANT_NORM_p75_1p5 // interval [0.75, 1.5)\ +/// The sign is determined by sc which can take the following values:\ +/// _MM_MANT_SIGN_src // sign = sign(src)\ +/// _MM_MANT_SIGN_zero // sign = 0\ +/// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1 +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_getmant_pd&expand=2867) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0))] +#[rustc_args_required_const(2, 3)] +pub unsafe fn _mm_maskz_getmant_pd( + k: __mmask8, + a: __m128d, + norm: _MM_MANTISSA_NORM_ENUM, + sign: _MM_MANTISSA_SIGN_ENUM, +) -> __m128d { + let a = a.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + macro_rules! call { + ($imm4:expr, $imm2:expr) => { + vgetmantpd128(a, $imm2 << 2 | $imm4, zero, k) }; } let r = constify_imm4_mantissas!(norm, sign, call); @@ -2846,7 +7075,7 @@ pub unsafe fn _mm512_maskz_getmant_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_add_round_ps&expand=145) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_round_ps&expand=145) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddps, rounding = 8))] @@ -2872,7 +7101,7 @@ pub unsafe fn _mm512_add_round_ps(a: __m512, b: __m512, rounding: i32) -> __m512 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_add_round_ps&expand=146) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_round_ps&expand=146) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddps, rounding = 8))] @@ -2904,7 +7133,7 @@ pub unsafe fn _mm512_mask_add_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_add_round_ps&expand=147) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_round_ps&expand=147) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddps, rounding = 8))] @@ -2936,7 +7165,7 @@ pub unsafe fn _mm512_maskz_add_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_add_round_pd&expand=142) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_add_round_pd&expand=142) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddpd, rounding = 8))] @@ -2962,7 +7191,7 @@ pub unsafe fn _mm512_add_round_pd(a: __m512d, b: __m512d, rounding: i32) -> __m5 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_add_round_pd&expand=143) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_add_round_pd&expand=143) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddpd, rounding = 8))] @@ -2994,7 +7223,7 @@ pub unsafe fn _mm512_mask_add_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_add_round_pd&expand=144) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_add_round_pd&expand=144) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vaddpd, rounding = 8))] @@ -3026,7 +7255,7 @@ pub unsafe fn _mm512_maskz_add_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sub_round_ps&expand=5739) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_round_ps&expand=5739) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubps, rounding = 8))] @@ -3052,7 +7281,7 @@ pub unsafe fn _mm512_sub_round_ps(a: __m512, b: __m512, rounding: i32) -> __m512 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sub_round_ps&expand=5737) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_round_ps&expand=5737) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubps, rounding = 8))] @@ -3084,7 +7313,7 @@ pub unsafe fn _mm512_mask_sub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sub_round_ps&expand=5738) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_round_ps&expand=5738) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubps, rounding = 8))] @@ -3116,7 +7345,7 @@ pub unsafe fn _mm512_maskz_sub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sub_round_pd&expand=5736) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sub_round_pd&expand=5736) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubpd, rounding = 8))] @@ -3142,7 +7371,7 @@ pub unsafe fn _mm512_sub_round_pd(a: __m512d, b: __m512d, rounding: i32) -> __m5 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sub_round_pd&expand=5734) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sub_round_pd&expand=5734) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubpd, rounding = 8))] @@ -3174,7 +7403,7 @@ pub unsafe fn _mm512_mask_sub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sub_round_pd&expand=5735) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sub_round_pd&expand=5735) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsubpd, rounding = 8))] @@ -3206,7 +7435,7 @@ pub unsafe fn _mm512_maskz_sub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mul_round_ps&expand=3940) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_round_ps&expand=3940) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulps, rounding = 8))] @@ -3232,7 +7461,7 @@ pub unsafe fn _mm512_mul_round_ps(a: __m512, b: __m512, rounding: i32) -> __m512 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mul_round_ps&expand=3938) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_round_ps&expand=3938) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulps, rounding = 8))] @@ -3264,7 +7493,7 @@ pub unsafe fn _mm512_mask_mul_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mul_round_ps&expand=3939) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_round_ps&expand=3939) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulps, rounding = 8))] @@ -3296,7 +7525,7 @@ pub unsafe fn _mm512_maskz_mul_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mul_round_pd&expand=3937) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mul_round_pd&expand=3937) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulpd, rounding = 8))] @@ -3322,7 +7551,7 @@ pub unsafe fn _mm512_mul_round_pd(a: __m512d, b: __m512d, rounding: i32) -> __m5 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_mul_round_pd&expand=3935) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_mul_round_pd&expand=3935) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulpd, rounding = 8))] @@ -3354,7 +7583,7 @@ pub unsafe fn _mm512_mask_mul_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_mul_round_ps&expand=3939) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_mul_round_ps&expand=3939) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmulpd, rounding = 8))] @@ -3386,7 +7615,7 @@ pub unsafe fn _mm512_maskz_mul_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_div_round_ps&expand=2168) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_div_round_ps&expand=2168) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivps, rounding = 8))] @@ -3412,7 +7641,7 @@ pub unsafe fn _mm512_div_round_ps(a: __m512, b: __m512, rounding: i32) -> __m512 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_div_round_ps&expand=2169) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_round_ps&expand=2169) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivps, rounding = 8))] @@ -3444,7 +7673,7 @@ pub unsafe fn _mm512_mask_div_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_div_round_ps&expand=2170) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_round_ps&expand=2170) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivps, rounding = 8))] @@ -3476,7 +7705,7 @@ pub unsafe fn _mm512_maskz_div_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_div_round_pd&expand=2165) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_div_round_pd&expand=2165) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivpd, rounding = 8))] @@ -3502,7 +7731,7 @@ pub unsafe fn _mm512_div_round_pd(a: __m512d, b: __m512d, rounding: i32) -> __m5 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_div_round_pd&expand=2166) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_div_round_pd&expand=2166) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivpd, rounding = 8))] @@ -3534,7 +7763,7 @@ pub unsafe fn _mm512_mask_div_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_div_round_pd&expand=2167) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_div_round_pd&expand=2167) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vdivpd, rounding = 8))] @@ -3566,7 +7795,7 @@ pub unsafe fn _mm512_maskz_div_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sqrt_round_ps&expand=5377) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_round_ps&expand=5377) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtps, rounding = 8))] @@ -3591,7 +7820,7 @@ pub unsafe fn _mm512_sqrt_round_ps(a: __m512, rounding: i32) -> __m512 { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sqrt_round_ps&expand=5375) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_round_ps&expand=5375) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtps, rounding = 8))] @@ -3621,7 +7850,7 @@ pub unsafe fn _mm512_mask_sqrt_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sqrt_round_ps&expand=5376) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_round_ps&expand=5376) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtps, rounding = 8))] @@ -3647,7 +7876,7 @@ pub unsafe fn _mm512_maskz_sqrt_round_ps(k: __mmask16, a: __m512, rounding: i32) /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sqrt_round_pd&expand=5374) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sqrt_round_pd&expand=5374) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtpd, rounding = 8))] @@ -3672,7 +7901,7 @@ pub unsafe fn _mm512_sqrt_round_pd(a: __m512d, rounding: i32) -> __m512d { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sqrt_round_pd&expand=5372) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sqrt_round_pd&expand=5372) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtpd, rounding = 8))] @@ -3683,9 +7912,10 @@ pub unsafe fn _mm512_mask_sqrt_round_pd( a: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vsqrtpd(a.as_f64x8(), $imm4) + vsqrtpd(a, $imm4) }; } let sqrtround = constify_imm4_round!(rounding, call); @@ -3701,15 +7931,16 @@ pub unsafe fn _mm512_mask_sqrt_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sqrt_round_pd&expand=5373) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sqrt_round_pd&expand=5373) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vsqrtpd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_sqrt_round_pd(k: __mmask8, a: __m512d, rounding: i32) -> __m512d { + let a = a.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vsqrtpd(a.as_f64x8(), $imm4) + vsqrtpd(a, $imm4) }; } let sqrtround = constify_imm4_round!(rounding, call); @@ -3726,15 +7957,18 @@ pub unsafe fn _mm512_maskz_sqrt_round_pd(k: __mmask8, a: __m512d, rounding: i32) /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmadd_round_ps&expand=2565) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_round_ps&expand=2565) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132ps or vfmadd213ps or vfmadd231ps #[rustc_args_required_const(3)] pub unsafe fn _mm512_fmadd_round_ps(a: __m512, b: __m512, c: __m512, rounding: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(a, b, c, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -3750,7 +7984,7 @@ pub unsafe fn _mm512_fmadd_round_ps(a: __m512, b: __m512, c: __m512, rounding: i /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmadd_round_ps&expand=2566) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_round_ps&expand=2566) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132ps or vfmadd213ps or vfmadd231ps @@ -3762,13 +7996,16 @@ pub unsafe fn _mm512_mask_fmadd_round_ps( c: __m512, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(a, b, c, $imm4) }; } let fmadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmadd, a.as_f32x16())) + transmute(simd_select_bitmask(k, fmadd, a)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in a using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -3780,7 +8017,7 @@ pub unsafe fn _mm512_mask_fmadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmadd_round_ps&expand=2568) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_round_ps&expand=2568) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132ps or vfmadd213ps or vfmadd231ps @@ -3792,9 +8029,12 @@ pub unsafe fn _mm512_maskz_fmadd_round_ps( c: __m512, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(a, b, c, $imm4) }; } let fmadd = constify_imm4_round!(rounding, call); @@ -3811,7 +8051,7 @@ pub unsafe fn _mm512_maskz_fmadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmadd_round_ps&expand=2567) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_round_ps&expand=2567) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132ps or vfmadd213ps or vfmadd231ps @@ -3823,13 +8063,16 @@ pub unsafe fn _mm512_mask3_fmadd_round_ps( k: __mmask16, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(a, b, c, $imm4) }; } let fmadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmadd, c.as_f32x16())) + transmute(simd_select_bitmask(k, fmadd, c)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst.\ @@ -3841,15 +8084,18 @@ pub unsafe fn _mm512_mask3_fmadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmadd_round_pd&expand=2561) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmadd_round_pd&expand=2561) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132pd or vfmadd213pd or vfmadd231pd #[rustc_args_required_const(3)] pub unsafe fn _mm512_fmadd_round_pd(a: __m512d, b: __m512d, c: __m512d, rounding: i32) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(a, b, c, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -3865,7 +8111,7 @@ pub unsafe fn _mm512_fmadd_round_pd(a: __m512d, b: __m512d, c: __m512d, rounding /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmadd_round_pd&expand=2562) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmadd_round_pd&expand=2562) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132pd or vfmadd213pd or vfmadd231pd @@ -3877,13 +8123,16 @@ pub unsafe fn _mm512_mask_fmadd_round_pd( c: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(a, b, c, $imm4) }; } let fmadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmadd, a.as_f64x8())) + transmute(simd_select_bitmask(k, fmadd, a)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -3895,7 +8144,7 @@ pub unsafe fn _mm512_mask_fmadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmadd_round_pd&expand=2564) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmadd_round_pd&expand=2564) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132pd or vfmadd213pd or vfmadd231pd @@ -3907,9 +8156,12 @@ pub unsafe fn _mm512_maskz_fmadd_round_pd( c: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(a, b, c, $imm4) }; } let fmadd = constify_imm4_round!(rounding, call); @@ -3926,7 +8178,7 @@ pub unsafe fn _mm512_maskz_fmadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmadd_round_pd&expand=2563) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmadd_round_pd&expand=2563) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmadd132pd or vfmadd213pd or vfmadd231pd @@ -3938,13 +8190,16 @@ pub unsafe fn _mm512_mask3_fmadd_round_pd( k: __mmask8, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(a, b, c, $imm4) }; } let fmadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmadd, c.as_f64x8())) + transmute(simd_select_bitmask(k, fmadd, c)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst.\ @@ -3956,7 +8211,7 @@ pub unsafe fn _mm512_mask3_fmadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsub_round_ps&expand=2651) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_round_ps&expand=2651) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generates vfmadd, gcc generates vfmsub @@ -3964,9 +8219,11 @@ pub unsafe fn _mm512_mask3_fmadd_round_pd( pub unsafe fn _mm512_fmsub_round_ps(a: __m512, b: __m512, c: __m512, rounding: i32) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, c.as_f32x16()); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmadd132psround(a, b, sub, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -3982,7 +8239,7 @@ pub unsafe fn _mm512_fmsub_round_ps(a: __m512, b: __m512, c: __m512, rounding: i /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsub_round_ps&expand=2652) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_round_ps&expand=2652) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generates vfmadd, gcc generates vfmsub @@ -3996,13 +8253,15 @@ pub unsafe fn _mm512_mask_fmsub_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, c.as_f32x16()); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmadd132psround(a, b, sub, $imm4) }; } let fmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsub, a.as_f32x16())) + transmute(simd_select_bitmask(k, fmsub, a)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4014,7 +8273,7 @@ pub unsafe fn _mm512_mask_fmsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsub_round_ps&expand=2654) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_round_ps&expand=2654) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generates vfmadd, gcc generates vfmsub @@ -4028,9 +8287,11 @@ pub unsafe fn _mm512_maskz_fmsub_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, c.as_f32x16()); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmadd132psround(a, b, sub, $imm4) }; } let fmsub = constify_imm4_round!(rounding, call); @@ -4046,7 +8307,7 @@ pub unsafe fn _mm512_maskz_fmsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsub_round_ps&expand=2653) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_round_ps&expand=2653) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132ps or vfmsub213ps or vfmsub231ps, clang generates vfmadd, gcc generates vfmsub @@ -4059,14 +8320,17 @@ pub unsafe fn _mm512_mask3_fmsub_round_ps( rounding: i32, ) -> __m512 { let zero: f32x16 = mem::zeroed(); - let sub = simd_sub(zero, c.as_f32x16()); + let c = c.as_f32x16(); + let sub = simd_sub(zero, c); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmadd132psround(a, b, sub, $imm4) }; } let fmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsub, c.as_f32x16())) + transmute(simd_select_bitmask(k, fmsub, c)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst.\ @@ -4078,7 +8342,7 @@ pub unsafe fn _mm512_mask3_fmsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsub_round_pd&expand=2647) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsub_round_pd&expand=2647) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang generates fmadd, gcc generates fmsub @@ -4086,9 +8350,11 @@ pub unsafe fn _mm512_mask3_fmsub_round_ps( pub unsafe fn _mm512_fmsub_round_pd(a: __m512d, b: __m512d, c: __m512d, rounding: i32) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, c.as_f64x8()); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmadd132pdround(a, b, sub, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4104,7 +8370,7 @@ pub unsafe fn _mm512_fmsub_round_pd(a: __m512d, b: __m512d, c: __m512d, rounding /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsub_round_pd&expand=2648) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsub_round_pd&expand=2648) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang generates fmadd, gcc generates fmsub @@ -4118,13 +8384,15 @@ pub unsafe fn _mm512_mask_fmsub_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, c.as_f64x8()); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmadd132pdround(a, b, sub, $imm4) }; } let fmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsub, a.as_f64x8())) + transmute(simd_select_bitmask(k, fmsub, a)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4136,7 +8404,7 @@ pub unsafe fn _mm512_mask_fmsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsub_round_pd&expand=2650) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsub_round_pd&expand=2650) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang generates fmadd, gcc generates fmsub @@ -4150,9 +8418,11 @@ pub unsafe fn _mm512_maskz_fmsub_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, c.as_f64x8()); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmadd132pdround(a, b, sub, $imm4) }; } let fmsub = constify_imm4_round!(rounding, call); @@ -4168,7 +8438,7 @@ pub unsafe fn _mm512_maskz_fmsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsub_round_pd&expand=2649) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsub_round_pd&expand=2649) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfmsub132pd or vfmsub213pd or vfmsub231pd. clang generates fmadd, gcc generates fmsub @@ -4181,14 +8451,17 @@ pub unsafe fn _mm512_mask3_fmsub_round_pd( rounding: i32, ) -> __m512d { let zero: f64x8 = mem::zeroed(); - let sub = simd_sub(zero, c.as_f64x8()); + let c = c.as_f64x8(); + let sub = simd_sub(zero, c); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmadd132pdround(a, b, sub, $imm4) }; } let fmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsub, c.as_f64x8())) + transmute(simd_select_bitmask(k, fmsub, c)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst.\ @@ -4200,15 +8473,18 @@ pub unsafe fn _mm512_mask3_fmsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmaddsub_round_ps&expand=2619) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_round_ps&expand=2619) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps #[rustc_args_required_const(3)] pub unsafe fn _mm512_fmaddsub_round_ps(a: __m512, b: __m512, c: __m512, rounding: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmaddsub213ps(a, b, c, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4224,7 +8500,7 @@ pub unsafe fn _mm512_fmaddsub_round_ps(a: __m512, b: __m512, c: __m512, rounding /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmaddsub_round_ps&expand=2620) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_round_ps&expand=2620) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps @@ -4236,13 +8512,16 @@ pub unsafe fn _mm512_mask_fmaddsub_round_ps( c: __m512, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmaddsub213ps(a, b, c, $imm4) }; } let fmaddsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmaddsub, a.as_f32x16())) + transmute(simd_select_bitmask(k, fmaddsub, a)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4254,7 +8533,7 @@ pub unsafe fn _mm512_mask_fmaddsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmaddsub_round_ps&expand=2622) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_round_ps&expand=2622) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps @@ -4266,9 +8545,12 @@ pub unsafe fn _mm512_maskz_fmaddsub_round_ps( c: __m512, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmaddsub213ps(a, b, c, $imm4) }; } let fmaddsub = constify_imm4_round!(rounding, call); @@ -4285,7 +8567,7 @@ pub unsafe fn _mm512_maskz_fmaddsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmaddsub_round_ps&expand=2621) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_round_ps&expand=2621) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132ps or vfmaddsub213ps or vfmaddsub231ps @@ -4297,13 +8579,16 @@ pub unsafe fn _mm512_mask3_fmaddsub_round_ps( k: __mmask16, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), c.as_f32x16(), $imm4) + vfmaddsub213ps(a, b, c, $imm4) }; } let fmaddsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmaddsub, c.as_f32x16())) + transmute(simd_select_bitmask(k, fmaddsub, c)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst.\ @@ -4315,7 +8600,7 @@ pub unsafe fn _mm512_mask3_fmaddsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmaddsub_round_pd&expand=2615) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmaddsub_round_pd&expand=2615) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -4326,9 +8611,12 @@ pub unsafe fn _mm512_fmaddsub_round_pd( c: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmaddsub213pd(a, b, c, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4344,7 +8632,7 @@ pub unsafe fn _mm512_fmaddsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmaddsub_round_pd&expand=2616) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmaddsub_round_pd&expand=2616) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -4356,13 +8644,16 @@ pub unsafe fn _mm512_mask_fmaddsub_round_pd( c: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmaddsub213pd(a, b, c, $imm4) }; } let fmaddsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmaddsub, a.as_f64x8())) + transmute(simd_select_bitmask(k, fmaddsub, a)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4374,7 +8665,7 @@ pub unsafe fn _mm512_mask_fmaddsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmaddsub_round_pd&expand=2618) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmaddsub_round_pd&expand=2618) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -4386,9 +8677,12 @@ pub unsafe fn _mm512_maskz_fmaddsub_round_pd( c: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmaddsub213pd(a, b, c, $imm4) }; } let fmaddsub = constify_imm4_round!(rounding, call); @@ -4405,7 +8699,7 @@ pub unsafe fn _mm512_maskz_fmaddsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmaddsub_round_pd&expand=2617) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmaddsub_round_pd&expand=2617) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmaddsub132pd or vfmaddsub213pd or vfmaddsub231pd @@ -4417,13 +8711,16 @@ pub unsafe fn _mm512_mask3_fmaddsub_round_pd( k: __mmask8, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), c.as_f64x8(), $imm4) + vfmaddsub213pd(a, b, c, $imm4) }; } let fmaddsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmaddsub, c.as_f64x8())) + transmute(simd_select_bitmask(k, fmaddsub, c)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst.\ @@ -4435,7 +8732,7 @@ pub unsafe fn _mm512_mask3_fmaddsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsubadd_round_ps&expand=2699) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_round_ps&expand=2699) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -4443,9 +8740,11 @@ pub unsafe fn _mm512_mask3_fmaddsub_round_pd( pub unsafe fn _mm512_fmsubadd_round_ps(a: __m512, b: __m512, c: __m512, rounding: i32) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, c.as_f32x16()); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmaddsub213ps(a, b, sub, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4461,7 +8760,7 @@ pub unsafe fn _mm512_fmsubadd_round_ps(a: __m512, b: __m512, c: __m512, rounding /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsubadd_round_ps&expand=2700) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_round_ps&expand=2700) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -4475,13 +8774,15 @@ pub unsafe fn _mm512_mask_fmsubadd_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, c.as_f32x16()); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmaddsub213ps(a, b, sub, $imm4) }; } let fmsubadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsubadd, a.as_f32x16())) + transmute(simd_select_bitmask(k, fmsubadd, a)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4493,7 +8794,7 @@ pub unsafe fn _mm512_mask_fmsubadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsubadd_round_ps&expand=2702) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_round_ps&expand=2702) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -4507,9 +8808,11 @@ pub unsafe fn _mm512_maskz_fmsubadd_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, c.as_f32x16()); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmaddsub213ps(a, b, sub, $imm4) }; } let fmsubadd = constify_imm4_round!(rounding, call); @@ -4525,7 +8828,7 @@ pub unsafe fn _mm512_maskz_fmsubadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsubadd_round_ps&expand=2701) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_round_ps&expand=2701) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132ps or vfmsubadd213ps or vfmsubadd231ps @@ -4538,14 +8841,17 @@ pub unsafe fn _mm512_mask3_fmsubadd_round_ps( rounding: i32, ) -> __m512 { let zero: f32x16 = mem::zeroed(); - let sub = simd_sub(zero, c.as_f32x16()); + let c = c.as_f32x16(); + let sub = simd_sub(zero, c); + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213ps(a.as_f32x16(), b.as_f32x16(), sub, $imm4) + vfmaddsub213ps(a, b, sub, $imm4) }; } let fmsubadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsubadd, c.as_f32x16())) + transmute(simd_select_bitmask(k, fmsubadd, c)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively subtract and add packed elements in c from/to the intermediate result, and store the results in dst.\ @@ -4557,7 +8863,7 @@ pub unsafe fn _mm512_mask3_fmsubadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fmsubadd_round_pd&expand=2695) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fmsubadd_round_pd&expand=2695) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -4570,9 +8876,11 @@ pub unsafe fn _mm512_fmsubadd_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, c.as_f64x8()); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmaddsub213pd(a, b, sub, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4588,7 +8896,7 @@ pub unsafe fn _mm512_fmsubadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fmsubadd_round_pd&expand=2696) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fmsubadd_round_pd&expand=2696) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -4602,13 +8910,15 @@ pub unsafe fn _mm512_mask_fmsubadd_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, c.as_f64x8()); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmaddsub213pd(a, b, sub, $imm4) }; } let fmsubadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsubadd, a.as_f64x8())) + transmute(simd_select_bitmask(k, fmsubadd, a)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, alternatively add and subtract packed elements in c to/from the intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4620,7 +8930,7 @@ pub unsafe fn _mm512_mask_fmsubadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fmsubadd_round_pd&expand=2698) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fmsubadd_round_pd&expand=2698) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -4634,9 +8944,11 @@ pub unsafe fn _mm512_maskz_fmsubadd_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, c.as_f64x8()); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmaddsub213pd(a, b, sub, $imm4) }; } let fmsubadd = constify_imm4_round!(rounding, call); @@ -4652,7 +8964,7 @@ pub unsafe fn _mm512_maskz_fmsubadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fmsubadd_round_pd&expand=2697) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fmsubadd_round_pd&expand=2697) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmaddsub, rounding = 8))] //vfmsubadd132pd or vfmsubadd213pd or vfmsubadd231pd @@ -4665,14 +8977,17 @@ pub unsafe fn _mm512_mask3_fmsubadd_round_pd( rounding: i32, ) -> __m512d { let zero: f64x8 = mem::zeroed(); - let sub = simd_sub(zero, c.as_f64x8()); + let c = c.as_f64x8(); + let sub = simd_sub(zero, c); + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmaddsub213pd(a.as_f64x8(), b.as_f64x8(), sub, $imm4) + vfmaddsub213pd(a, b, sub, $imm4) }; } let fmsubadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fmsubadd, c.as_f64x8())) + transmute(simd_select_bitmask(k, fmsubadd, c)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst.\ @@ -4684,7 +8999,7 @@ pub unsafe fn _mm512_mask3_fmsubadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmadd_round_ps&expand=2731) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_round_ps&expand=2731) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps @@ -4692,9 +9007,11 @@ pub unsafe fn _mm512_mask3_fmsubadd_round_pd( pub unsafe fn _mm512_fnmadd_round_ps(a: __m512, b: __m512, c: __m512, rounding: i32) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, a.as_f32x16()); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(sub, b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(sub, b, c, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4710,7 +9027,7 @@ pub unsafe fn _mm512_fnmadd_round_ps(a: __m512, b: __m512, c: __m512, rounding: /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmadd_round_ps&expand=2732) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_round_ps&expand=2732) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps @@ -4724,9 +9041,11 @@ pub unsafe fn _mm512_mask_fnmadd_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, a.as_f32x16()); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(sub, b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(sub, b, c, $imm4) }; } let fnmadd = constify_imm4_round!(rounding, call); @@ -4742,7 +9061,7 @@ pub unsafe fn _mm512_mask_fnmadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmadd_round_ps&expand=2734) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_round_ps&expand=2734) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps @@ -4756,9 +9075,11 @@ pub unsafe fn _mm512_maskz_fnmadd_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, a.as_f32x16()); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(sub, b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(sub, b, c, $imm4) }; } let fnmadd = constify_imm4_round!(rounding, call); @@ -4774,7 +9095,7 @@ pub unsafe fn _mm512_maskz_fnmadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmadd_round_ps&expand=2733) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_round_ps&expand=2733) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132ps or vfnmadd213ps or vfnmadd231ps @@ -4788,13 +9109,15 @@ pub unsafe fn _mm512_mask3_fnmadd_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let sub = simd_sub(zero, a.as_f32x16()); + let b = b.as_f32x16(); + let c = c.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(sub, b.as_f32x16(), c.as_f32x16(), $imm4) + vfmadd132psround(sub, b, c, $imm4) }; } let fnmadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fnmadd, c.as_f32x16())) + transmute(simd_select_bitmask(k, fnmadd, c)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst.\ @@ -4806,7 +9129,7 @@ pub unsafe fn _mm512_mask3_fnmadd_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmadd_pd&expand=2711) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmadd_pd&expand=2711) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd @@ -4814,9 +9137,11 @@ pub unsafe fn _mm512_mask3_fnmadd_round_ps( pub unsafe fn _mm512_fnmadd_round_pd(a: __m512d, b: __m512d, c: __m512d, rounding: i32) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, a.as_f64x8()); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(sub, b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(sub, b, c, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4832,7 +9157,7 @@ pub unsafe fn _mm512_fnmadd_round_pd(a: __m512d, b: __m512d, c: __m512d, roundin /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmadd_round_pd&expand=2728) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmadd_round_pd&expand=2728) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd @@ -4845,14 +9170,17 @@ pub unsafe fn _mm512_mask_fnmadd_round_pd( rounding: i32, ) -> __m512d { let zero: f64x8 = mem::zeroed(); - let sub = simd_sub(zero, a.as_f64x8()); + let a = a.as_f64x8(); + let sub = simd_sub(zero, a); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(sub, b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(sub, b, c, $imm4) }; } let fnmadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fnmadd, a.as_f64x8())) + transmute(simd_select_bitmask(k, fnmadd, a)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, add the negated intermediate result to packed elements in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4864,7 +9192,7 @@ pub unsafe fn _mm512_mask_fnmadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmadd_round_pd&expand=2730) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmadd_round_pd&expand=2730) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd @@ -4878,9 +9206,11 @@ pub unsafe fn _mm512_maskz_fnmadd_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, a.as_f64x8()); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(sub, b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(sub, b, c, $imm4) }; } let fnmadd = constify_imm4_round!(rounding, call); @@ -4896,7 +9226,7 @@ pub unsafe fn _mm512_maskz_fnmadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmadd_round_pd&expand=2729) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmadd_round_pd&expand=2729) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmadd132pd or vfnmadd213pd or vfnmadd231pd @@ -4910,13 +9240,15 @@ pub unsafe fn _mm512_mask3_fnmadd_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let sub = simd_sub(zero, a.as_f64x8()); + let b = b.as_f64x8(); + let c = c.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(sub, b.as_f64x8(), c.as_f64x8(), $imm4) + vfmadd132pdround(sub, b, c, $imm4) }; } let fnmadd = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fnmadd, c.as_f64x8())) + transmute(simd_select_bitmask(k, fnmadd, c)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst.\ @@ -4928,7 +9260,7 @@ pub unsafe fn _mm512_mask3_fnmadd_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmsub_round_ps&expand=2779) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_round_ps&expand=2779) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -4937,9 +9269,10 @@ pub unsafe fn _mm512_fnmsub_round_ps(a: __m512, b: __m512, c: __m512, rounding: let zero: f32x16 = mem::zeroed(); let suba = simd_sub(zero, a.as_f32x16()); let subc = simd_sub(zero, c.as_f32x16()); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(suba, b.as_f32x16(), subc, $imm4) + vfmadd132psround(suba, b, subc, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -4955,7 +9288,7 @@ pub unsafe fn _mm512_fnmsub_round_ps(a: __m512, b: __m512, c: __m512, rounding: /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmsub_round_ps&expand=2780) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_round_ps&expand=2780) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -4968,15 +9301,17 @@ pub unsafe fn _mm512_mask_fnmsub_round_ps( rounding: i32, ) -> __m512 { let zero: f32x16 = mem::zeroed(); - let suba = simd_sub(zero, a.as_f32x16()); + let a = a.as_f32x16(); + let suba = simd_sub(zero, a); let subc = simd_sub(zero, c.as_f32x16()); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(suba, b.as_f32x16(), subc, $imm4) + vfmadd132psround(suba, b, subc, $imm4) }; } let fnmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fnmsub, a.as_f32x16())) + transmute(simd_select_bitmask(k, fnmsub, a)) } /// Multiply packed single-precision (32-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -4988,7 +9323,7 @@ pub unsafe fn _mm512_mask_fnmsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmsub_round_ps&expand=2782) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_round_ps&expand=2782) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -5003,9 +9338,10 @@ pub unsafe fn _mm512_maskz_fnmsub_round_ps( let zero: f32x16 = mem::zeroed(); let suba = simd_sub(zero, a.as_f32x16()); let subc = simd_sub(zero, c.as_f32x16()); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(suba, b.as_f32x16(), subc, $imm4) + vfmadd132psround(suba, b, subc, $imm4) }; } let fnmsub = constify_imm4_round!(rounding, call); @@ -5021,7 +9357,7 @@ pub unsafe fn _mm512_maskz_fnmsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmsub_round_ps&expand=2781) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_round_ps&expand=2781) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132ps or vfnmsub213ps or vfnmsub231ps @@ -5035,14 +9371,16 @@ pub unsafe fn _mm512_mask3_fnmsub_round_ps( ) -> __m512 { let zero: f32x16 = mem::zeroed(); let suba = simd_sub(zero, a.as_f32x16()); - let subc = simd_sub(zero, c.as_f32x16()); + let c = c.as_f32x16(); + let subc = simd_sub(zero, c); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vfmadd132ps(suba, b.as_f32x16(), subc, $imm4) + vfmadd132psround(suba, b, subc, $imm4) }; } let fnmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fnmsub, c.as_f32x16())) + transmute(simd_select_bitmask(k, fnmsub, c)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst.\ @@ -5054,7 +9392,7 @@ pub unsafe fn _mm512_mask3_fnmsub_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fnmsub_round_pd&expand=2775) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fnmsub_round_pd&expand=2775) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -5063,9 +9401,10 @@ pub unsafe fn _mm512_fnmsub_round_pd(a: __m512d, b: __m512d, c: __m512d, roundin let zero: f64x8 = mem::zeroed(); let suba = simd_sub(zero, a.as_f64x8()); let subc = simd_sub(zero, c.as_f64x8()); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(suba, b.as_f64x8(), subc, $imm4) + vfmadd132pdround(suba, b, subc, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -5081,7 +9420,7 @@ pub unsafe fn _mm512_fnmsub_round_pd(a: __m512d, b: __m512d, c: __m512d, roundin /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fnmsub_round_pd&expand=2776) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fnmsub_round_pd&expand=2776) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -5094,15 +9433,17 @@ pub unsafe fn _mm512_mask_fnmsub_round_pd( rounding: i32, ) -> __m512d { let zero: f64x8 = mem::zeroed(); - let suba = simd_sub(zero, a.as_f64x8()); + let a = a.as_f64x8(); + let suba = simd_sub(zero, a); let subc = simd_sub(zero, c.as_f64x8()); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(suba, b.as_f64x8(), subc, $imm4) + vfmadd132pdround(suba, b, subc, $imm4) }; } let fnmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fnmsub, a.as_f64x8())) + transmute(simd_select_bitmask(k, fnmsub, a)) } /// Multiply packed double-precision (64-bit) floating-point elements in a and b, subtract packed elements in c from the negated intermediate result, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ @@ -5114,7 +9455,7 @@ pub unsafe fn _mm512_mask_fnmsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fnmsub_round_pd&expand=2778) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fnmsub_round_pd&expand=2778) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -5129,9 +9470,10 @@ pub unsafe fn _mm512_maskz_fnmsub_round_pd( let zero: f64x8 = mem::zeroed(); let suba = simd_sub(zero, a.as_f64x8()); let subc = simd_sub(zero, c.as_f64x8()); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(suba, b.as_f64x8(), subc, $imm4) + vfmadd132pdround(suba, b, subc, $imm4) }; } let fnmsub = constify_imm4_round!(rounding, call); @@ -5147,7 +9489,7 @@ pub unsafe fn _mm512_maskz_fnmsub_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask3_fnmsub_round_pd&expand=2777) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask3_fnmsub_round_pd&expand=2777) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfmadd, rounding = 8))] //vfnmsub132pd or vfnmsub213pd or vfnmsub231pd @@ -5161,28 +9503,32 @@ pub unsafe fn _mm512_mask3_fnmsub_round_pd( ) -> __m512d { let zero: f64x8 = mem::zeroed(); let suba = simd_sub(zero, a.as_f64x8()); - let subc = simd_sub(zero, c.as_f64x8()); + let c = c.as_f64x8(); + let subc = simd_sub(zero, c); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vfmadd132pd(suba, b.as_f64x8(), subc, $imm4) + vfmadd132pdround(suba, b, subc, $imm4) }; } let fnmsub = constify_imm4_round!(rounding, call); - transmute(simd_select_bitmask(k, fnmsub, c.as_f64x8())) + transmute(simd_select_bitmask(k, fnmsub, c)) } /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=max_round_ps&expand=3662) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_round_ps&expand=3662) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxps, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_max_round_ps(a: __m512, b: __m512, sae: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vmaxps(a.as_f32x16(), b.as_f32x16(), $imm4) + vmaxps(a, b, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5192,7 +9538,7 @@ pub unsafe fn _mm512_max_round_ps(a: __m512, b: __m512, sae: i32) -> __m512 { /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_round_ps&expand=3660) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_round_ps&expand=3660) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxps, sae = 8))] @@ -5204,9 +9550,11 @@ pub unsafe fn _mm512_mask_max_round_ps( b: __m512, sae: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vmaxps(a.as_f32x16(), b.as_f32x16(), $imm4) + vmaxps(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5216,15 +9564,17 @@ pub unsafe fn _mm512_mask_max_round_ps( /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_round_ps&expand=3661) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_round_ps&expand=3661) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxps, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_max_round_ps(k: __mmask16, a: __m512, b: __m512, sae: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vmaxps(a.as_f32x16(), b.as_f32x16(), $imm4) + vmaxps(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5235,15 +9585,17 @@ pub unsafe fn _mm512_maskz_max_round_ps(k: __mmask16, a: __m512, b: __m512, sae: /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_max_round_pd&expand=3659) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_max_round_pd&expand=3659) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxpd, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_max_round_pd(a: __m512d, b: __m512d, sae: i32) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vmaxpd(a.as_f64x8(), b.as_f64x8(), $imm4) + vmaxpd(a, b, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5253,7 +9605,7 @@ pub unsafe fn _mm512_max_round_pd(a: __m512d, b: __m512d, sae: i32) -> __m512d { /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_max_round_pd&expand=3657) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_max_round_pd&expand=3657) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxpd, sae = 8))] @@ -5265,9 +9617,11 @@ pub unsafe fn _mm512_mask_max_round_pd( b: __m512d, sae: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vmaxpd(a.as_f64x8(), b.as_f64x8(), $imm4) + vmaxpd(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5277,15 +9631,17 @@ pub unsafe fn _mm512_mask_max_round_pd( /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed maximum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_max_round_pd&expand=3658) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_max_round_pd&expand=3658) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmaxpd, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_max_round_pd(k: __mmask8, a: __m512d, b: __m512d, sae: i32) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vmaxpd(a.as_f64x8(), b.as_f64x8(), $imm4) + vmaxpd(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5296,15 +9652,17 @@ pub unsafe fn _mm512_maskz_max_round_pd(k: __mmask8, a: __m512d, b: __m512d, sae /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_round_ps&expand=3776) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_round_ps&expand=3776) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminps, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_min_round_ps(a: __m512, b: __m512, sae: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vminps(a.as_f32x16(), b.as_f32x16(), $imm4) + vminps(a, b, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5314,7 +9672,7 @@ pub unsafe fn _mm512_min_round_ps(a: __m512, b: __m512, sae: i32) -> __m512 { /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_min_round_ps&expand=3774) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_round_ps&expand=3774) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminps, sae = 8))] @@ -5326,9 +9684,11 @@ pub unsafe fn _mm512_mask_min_round_ps( b: __m512, sae: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vminps(a.as_f32x16(), b.as_f32x16(), $imm4) + vminps(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5338,15 +9698,17 @@ pub unsafe fn _mm512_mask_min_round_ps( /// Compare packed single-precision (32-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_min_round_ps&expand=3775) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_round_ps&expand=3775) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminps, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_min_round_ps(k: __mmask16, a: __m512, b: __m512, sae: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vminps(a.as_f32x16(), b.as_f32x16(), $imm4) + vminps(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5357,15 +9719,17 @@ pub unsafe fn _mm512_maskz_min_round_ps(k: __mmask16, a: __m512, b: __m512, sae: /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_min_round_pd&expand=3773) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_min_round_pd&expand=3773) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminpd, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_min_round_pd(a: __m512d, b: __m512d, sae: i32) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vminpd(a.as_f64x8(), b.as_f64x8(), $imm4) + vminpd(a, b, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5375,7 +9739,7 @@ pub unsafe fn _mm512_min_round_pd(a: __m512d, b: __m512d, sae: i32) -> __m512d { /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_min_round_pd&expand=3771) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_min_round_pd&expand=3771) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminpd, sae = 8))] @@ -5387,9 +9751,11 @@ pub unsafe fn _mm512_mask_min_round_pd( b: __m512d, sae: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vminpd(a.as_f64x8(), b.as_f64x8(), $imm4) + vminpd(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5399,15 +9765,17 @@ pub unsafe fn _mm512_mask_min_round_pd( /// Compare packed double-precision (64-bit) floating-point elements in a and b, and store packed minimum values in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_min_round_pd&expand=3772) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_min_round_pd&expand=3772) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vminpd, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_min_round_pd(k: __mmask8, a: __m512d, b: __m512d, sae: i32) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vminpd(a.as_f64x8(), b.as_f64x8(), $imm4) + vminpd(a, b, $imm4) }; } let max = constify_imm4_sae!(sae, call); @@ -5418,20 +9786,17 @@ pub unsafe fn _mm512_maskz_min_round_pd(k: __mmask8, a: __m512d, b: __m512d, sae /// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getexp_round_ps&expand=2850) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_round_ps&expand=2850) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexpps, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_getexp_round_ps(a: __m512, sae: i32) -> __m512 { + let a = a.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr) => { - vgetexpps( - a.as_f32x16(), - _mm512_setzero_ps().as_f32x16(), - 0b11111111_11111111, - $imm4, - ) + vgetexpps(a, zero, 0b11111111_11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5441,7 +9806,7 @@ pub unsafe fn _mm512_getexp_round_ps(a: __m512, sae: i32) -> __m512 { /// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getexp_round_ps&expand=2851) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_round_ps&expand=2851) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexpps, sae = 8))] @@ -5452,9 +9817,11 @@ pub unsafe fn _mm512_mask_getexp_round_ps( a: __m512, sae: i32, ) -> __m512 { + let a = a.as_f32x16(); + let src = src.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vgetexpps(a.as_f32x16(), src.as_f32x16(), k, $imm4) + vgetexpps(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5464,15 +9831,17 @@ pub unsafe fn _mm512_mask_getexp_round_ps( /// Convert the exponent of each packed single-precision (32-bit) floating-point element in a to a single-precision (32-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getexp_round_ps&expand=2852) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_round_ps&expand=2852) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexpps, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_getexp_round_ps(k: __mmask16, a: __m512, sae: i32) -> __m512 { + let a = a.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr) => { - vgetexpps(a.as_f32x16(), _mm512_setzero_ps().as_f32x16(), k, $imm4) + vgetexpps(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5482,20 +9851,17 @@ pub unsafe fn _mm512_maskz_getexp_round_ps(k: __mmask16, a: __m512, sae: i32) -> /// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst. This intrinsic essentially calculates floor(log2(x)) for each element.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getexp_round_pd&expand=2847) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getexp_round_pd&expand=2847) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexppd, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_getexp_round_pd(a: __m512d, sae: i32) -> __m512d { + let a = a.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr) => { - vgetexppd( - a.as_f64x8(), - _mm512_setzero_pd().as_f64x8(), - 0b11111111, - $imm4, - ) + vgetexppd(a, zero, 0b11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5505,7 +9871,7 @@ pub unsafe fn _mm512_getexp_round_pd(a: __m512d, sae: i32) -> __m512d { /// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getexp_round_pd&expand=2848) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getexp_round_pd&expand=2848) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexppd, sae = 8))] @@ -5516,9 +9882,11 @@ pub unsafe fn _mm512_mask_getexp_round_pd( a: __m512d, sae: i32, ) -> __m512d { + let a = a.as_f64x8(); + let src = src.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vgetexppd(a.as_f64x8(), src.as_f64x8(), k, $imm4) + vgetexppd(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5528,15 +9896,17 @@ pub unsafe fn _mm512_mask_getexp_round_pd( /// Convert the exponent of each packed double-precision (64-bit) floating-point element in a to a double-precision (64-bit) floating-point number representing the integer exponent, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). This intrinsic essentially calculates floor(log2(x)) for each element.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getexp_round_pd&expand=2849) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getexp_round_pd&expand=2849) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetexppd, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_getexp_round_pd(k: __mmask8, a: __m512d, sae: i32) -> __m512d { + let a = a.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr) => { - vgetexppd(a.as_f64x8(), _mm512_setzero_pd().as_f64x8(), k, $imm4) + vgetexppd(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -5552,7 +9922,7 @@ pub unsafe fn _mm512_maskz_getexp_round_pd(k: __mmask8, a: __m512d, sae: i32) -> /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_roundscale_round_ps&expand=4790) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_round_ps&expand=4790) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0, sae = 8))] @@ -5578,7 +9948,7 @@ pub unsafe fn _mm512_roundscale_round_ps(a: __m512, imm8: i32, sae: i32) -> __m5 /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_roundscale_round_ps&expand=4788) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_round_ps&expand=4788) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0, sae = 8))] @@ -5610,7 +9980,7 @@ pub unsafe fn _mm512_mask_roundscale_round_ps( /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_roundscale_round_ps&expand=4789) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_round_ps&expand=4789) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscaleps, imm8 = 0, sae = 8))] @@ -5641,7 +10011,7 @@ pub unsafe fn _mm512_maskz_roundscale_round_ps( /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_roundscale_round_pd&expand=4787) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_roundscale_round_pd&expand=4787) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0, sae = 8))] @@ -5667,7 +10037,7 @@ pub unsafe fn _mm512_roundscale_round_pd(a: __m512d, imm8: i32, sae: i32) -> __m /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_roundscale_round_pd&expand=4785) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_roundscale_round_pd&expand=4785) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0, sae = 8))] @@ -5699,7 +10069,7 @@ pub unsafe fn _mm512_mask_roundscale_round_pd( /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_roundscale_round_pd&expand=4786) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_roundscale_round_pd&expand=4786) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vrndscalepd, imm8 = 0, sae = 8))] @@ -5730,21 +10100,18 @@ pub unsafe fn _mm512_maskz_roundscale_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_scalef_round_ps&expand=4889) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_round_ps&expand=4889) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefps, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_scalef_round_ps(a: __m512, b: __m512, rounding: i32) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr) => { - vscalefps( - a.as_f32x16(), - b.as_f32x16(), - _mm512_setzero_ps().as_f32x16(), - 0b11111111_11111111, - $imm4, - ) + vscalefps(a, b, zero, 0b11111111_11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -5760,7 +10127,7 @@ pub unsafe fn _mm512_scalef_round_ps(a: __m512, b: __m512, rounding: i32) -> __m /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_scalef_round_ps&expand=4887) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_round_ps&expand=4887) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefps, rounding = 8))] @@ -5772,9 +10139,12 @@ pub unsafe fn _mm512_mask_scalef_round_ps( b: __m512, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let src = src.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vscalefps(a.as_f32x16(), b.as_f32x16(), src.as_f32x16(), k, $imm4) + vscalefps(a, b, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -5790,7 +10160,7 @@ pub unsafe fn _mm512_mask_scalef_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_scalef_round_ps&expand=4888) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_round_ps&expand=4888) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefps, rounding = 8))] @@ -5801,15 +10171,12 @@ pub unsafe fn _mm512_maskz_scalef_round_ps( b: __m512, rounding: i32, ) -> __m512 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr) => { - vscalefps( - a.as_f32x16(), - b.as_f32x16(), - _mm512_setzero_ps().as_f32x16(), - k, - $imm4, - ) + vscalefps(a, b, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -5825,21 +10192,18 @@ pub unsafe fn _mm512_maskz_scalef_round_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_scalef_round_pd&expand=4886) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_scalef_round_pd&expand=4886) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefpd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_scalef_round_pd(a: __m512d, b: __m512d, rounding: i32) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr) => { - vscalefpd( - a.as_f64x8(), - b.as_f64x8(), - _mm512_setzero_pd().as_f64x8(), - 0b11111111, - $imm4, - ) + vscalefpd(a, b, zero, 0b11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -5855,7 +10219,7 @@ pub unsafe fn _mm512_scalef_round_pd(a: __m512d, b: __m512d, rounding: i32) -> _ /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_scalef_round_pd&expand=4884) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_scalef_round_pd&expand=4884) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefpd, rounding = 8))] @@ -5867,9 +10231,12 @@ pub unsafe fn _mm512_mask_scalef_round_pd( b: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let src = src.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vscalefpd(a.as_f64x8(), b.as_f64x8(), src.as_f64x8(), k, $imm4) + vscalefpd(a, b, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -5885,7 +10252,7 @@ pub unsafe fn _mm512_mask_scalef_round_pd( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_scalef_round_pd&expand=4885) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_scalef_round_pd&expand=4885) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefpd, rounding = 8))] @@ -5896,15 +10263,12 @@ pub unsafe fn _mm512_maskz_scalef_round_pd( b: __m512d, rounding: i32, ) -> __m512d { + let a = a.as_f64x8(); + let b = b.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr) => { - vscalefpd( - a.as_f64x8(), - b.as_f64x8(), - _mm512_setzero_pd().as_f64x8(), - k, - $imm4, - ) + vscalefpd(a, b, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -5914,7 +10278,7 @@ pub unsafe fn _mm512_maskz_scalef_round_pd( /// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting.\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fixupimm_round_ps&expand=2505) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_round_ps&expand=2505) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0, sae = 8))] @@ -5941,7 +10305,7 @@ pub unsafe fn _mm512_fixupimm_round_ps( /// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting.\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fixupimm_round_ps&expand=2506) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_round_ps&expand=2506) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0, sae = 8))] @@ -5969,7 +10333,7 @@ pub unsafe fn _mm512_mask_fixupimm_round_ps( /// Fix up packed single-precision (32-bit) floating-point elements in a and b using packed 32-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting.\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fixupimm_round_ps&expand=2507) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_round_ps&expand=2507) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmps, imm8 = 0, sae = 8))] @@ -5997,7 +10361,7 @@ pub unsafe fn _mm512_maskz_fixupimm_round_ps( /// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst. imm8 is used to set the required flags reporting.\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_fixupimm_round_pd&expand=2502) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_fixupimm_round_pd&expand=2502) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0, sae = 8))] @@ -6024,7 +10388,7 @@ pub unsafe fn _mm512_fixupimm_round_pd( /// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). imm8 is used to set the required flags reporting.\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_fixupimm_round_pd&expand=2503) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_fixupimm_round_pd&expand=2503) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0, sae = 8))] @@ -6052,7 +10416,7 @@ pub unsafe fn _mm512_mask_fixupimm_round_pd( /// Fix up packed double-precision (64-bit) floating-point elements in a and b using packed 64-bit integers in c, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). imm8 is used to set the required flags reporting.\ /// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_fixupimm_round_pd&expand=2504) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_fixupimm_round_pd&expand=2504) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vfixupimmpd, imm8 = 0, sae = 8))] @@ -6089,7 +10453,7 @@ pub unsafe fn _mm512_maskz_fixupimm_round_pd( /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getmant_round_ps&expand=2886) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_round_ps&expand=2886) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0, sae = 4))] @@ -6100,15 +10464,11 @@ pub unsafe fn _mm512_getmant_round_ps( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m512 { + let a = a.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantps( - a.as_f32x16(), - $imm2 << 2 | $imm4_1, - _mm512_setzero_ps().as_f32x16(), - 0b11111111_11111111, - $imm4_2, - ) + vgetmantps(a, $imm2 << 2 | $imm4_1, zero, 0b11111111_11111111, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -6127,7 +10487,7 @@ pub unsafe fn _mm512_getmant_round_ps( /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getmant_round_ps&expand=2887) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_round_ps&expand=2887) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0, sae = 4))] @@ -6140,15 +10500,11 @@ pub unsafe fn _mm512_mask_getmant_round_ps( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m512 { + let a = a.as_f32x16(); + let src = src.as_f32x16(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantps( - a.as_f32x16(), - $imm2 << 2 | $imm4_1, - src.as_f32x16(), - k, - $imm4_2, - ) + vgetmantps(a, $imm2 << 2 | $imm4_1, src, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -6167,7 +10523,7 @@ pub unsafe fn _mm512_mask_getmant_round_ps( /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getmant_round_ps&expand=2888) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_getmant_round_ps&expand=2888) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantps, norm = 0, sign = 0, sae = 4))] @@ -6179,15 +10535,11 @@ pub unsafe fn _mm512_maskz_getmant_round_ps( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m512 { + let a = a.as_f32x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantps( - a.as_f32x16(), - $imm2 << 2 | $imm4_1, - _mm512_setzero_ps().as_f32x16(), - k, - $imm4_2, - ) + vgetmantps(a, $imm2 << 2 | $imm4_1, zero, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -6206,7 +10558,7 @@ pub unsafe fn _mm512_maskz_getmant_round_ps( /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_getmant_round_pd&expand=2883) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_getmant_round_pd&expand=2883) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0, sae = 4))] @@ -6217,15 +10569,11 @@ pub unsafe fn _mm512_getmant_round_pd( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m512d { + let a = a.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantpd( - a.as_f64x8(), - $imm2 << 2 | $imm4_1, - _mm512_setzero_pd().as_f64x8(), - 0b11111111, - $imm4_2, - ) + vgetmantpd(a, $imm2 << 2 | $imm4_1, zero, 0b11111111, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -6244,7 +10592,7 @@ pub unsafe fn _mm512_getmant_round_pd( /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_getmant_round_pd&expand=2884) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_getmant_round_pd&expand=2884) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0, sae = 4))] @@ -6257,15 +10605,11 @@ pub unsafe fn _mm512_mask_getmant_round_pd( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m512d { + let a = a.as_f64x8(); + let src = src.as_f64x8(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantpd( - a.as_f64x8(), - $imm2 << 2 | $imm4_1, - src.as_f64x8(), - k, - $imm4_2, - ) + vgetmantpd(a, $imm2 << 2 | $imm4_1, src, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -6284,7 +10628,7 @@ pub unsafe fn _mm512_mask_getmant_round_pd( /// _MM_MANT_SIGN_nan // dst = NaN if sign(src) = 1\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_getmant_round_pd&expand=2885) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_512_maskz_getmant_round_pd&expand=2885) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgetmantpd, norm = 0, sign = 0, sae = 4))] @@ -6296,15 +10640,11 @@ pub unsafe fn _mm512_maskz_getmant_round_pd( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m512d { + let a = a.as_f64x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantpd( - a.as_f64x8(), - $imm2 << 2 | $imm4_1, - _mm512_setzero_pd().as_f64x8(), - k, - $imm4_2, - ) + vgetmantpd(a, $imm2 << 2 | $imm4_1, zero, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -6313,7 +10653,7 @@ pub unsafe fn _mm512_maskz_getmant_round_pd( /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=cvtps_epi32&expand=1737) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_epi32&expand=1737) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2dq))] @@ -6328,7 +10668,7 @@ pub unsafe fn _mm512_cvtps_epi32(a: __m512) -> __m512i { /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtps_epi32&expand=1738) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_epi32&expand=1738) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2dq))] @@ -6343,7 +10683,7 @@ pub unsafe fn _mm512_mask_cvtps_epi32(src: __m512i, k: __mmask16, a: __m512) -> /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtps_epi32&expand=1739) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtps_epi32&expand=1739) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2dq))] @@ -6356,9 +10696,55 @@ pub unsafe fn _mm512_maskz_cvtps_epi32(k: __mmask16, a: __m512) -> __m512i { )) } +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtps_epi32&expand=1735) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2dq))] +pub unsafe fn _mm256_mask_cvtps_epi32(src: __m256i, k: __mmask8, a: __m256) -> __m256i { + let convert = _mm256_cvtps_epi32(a); + transmute(simd_select_bitmask(k, convert.as_i32x8(), src.as_i32x8())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtps_epi32&expand=1736) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2dq))] +pub unsafe fn _mm256_maskz_cvtps_epi32(k: __mmask8, a: __m256) -> __m256i { + let convert = _mm256_cvtps_epi32(a); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, convert.as_i32x8(), zero)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtps_epi32&expand=1732) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2dq))] +pub unsafe fn _mm_mask_cvtps_epi32(src: __m128i, k: __mmask8, a: __m128) -> __m128i { + let convert = _mm_cvtps_epi32(a); + transmute(simd_select_bitmask(k, convert.as_i32x4(), src.as_i32x4())) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtps_epi32&expand=1733) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2dq))] +pub unsafe fn _mm_maskz_cvtps_epi32(k: __mmask8, a: __m128) -> __m128i { + let convert = _mm_cvtps_epi32(a); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, convert.as_i32x4(), zero)) +} + /// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtps_epu32&expand=1755) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_epu32&expand=1755) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2udq))] @@ -6373,7 +10759,7 @@ pub unsafe fn _mm512_cvtps_epu32(a: __m512) -> __m512i { /// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtps_epu32&expand=1756) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_epu32&expand=1756) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2udq))] @@ -6388,7 +10774,7 @@ pub unsafe fn _mm512_mask_cvtps_epu32(src: __m512i, k: __mmask16, a: __m512) -> /// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=maskz_cvt_roundps_epu32&expand=1343) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_epu32&expand=1343) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2udq))] @@ -6401,9 +10787,85 @@ pub unsafe fn _mm512_maskz_cvtps_epu32(k: __mmask16, a: __m512) -> __m512i { )) } +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtps_epu32&expand=1752) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2udq))] +pub unsafe fn _mm256_cvtps_epu32(a: __m256) -> __m256i { + transmute(vcvtps2udq256( + a.as_f32x8(), + _mm256_setzero_si256().as_u32x8(), + 0b11111111, + )) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtps_epu32&expand=1753) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2udq))] +pub unsafe fn _mm256_mask_cvtps_epu32(src: __m256i, k: __mmask8, a: __m256) -> __m256i { + transmute(vcvtps2udq256(a.as_f32x8(), src.as_u32x8(), k)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtps_epu32&expand=1754) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2udq))] +pub unsafe fn _mm256_maskz_cvtps_epu32(k: __mmask8, a: __m256) -> __m256i { + transmute(vcvtps2udq256( + a.as_f32x8(), + _mm256_setzero_si256().as_u32x8(), + k, + )) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_epu32&expand=1749) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2udq))] +pub unsafe fn _mm_cvtps_epu32(a: __m128) -> __m128i { + transmute(vcvtps2udq128( + a.as_f32x4(), + _mm_setzero_si128().as_u32x4(), + 0b11111111, + )) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtps_epu32&expand=1750) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2udq))] +pub unsafe fn _mm_mask_cvtps_epu32(src: __m128i, k: __mmask8, a: __m128) -> __m128i { + transmute(vcvtps2udq128(a.as_f32x4(), src.as_u32x4(), k)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtps_epu32&expand=1751) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2udq))] +pub unsafe fn _mm_maskz_cvtps_epu32(k: __mmask8, a: __m128) -> __m128i { + transmute(vcvtps2udq128( + a.as_f32x4(), + _mm_setzero_si128().as_u32x4(), + k, + )) +} + /// Convert packed single-precision (32-bit) floating-point elements in a to packed double-precision (64-bit) floating-point elements, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtps_pd&expand=1769) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_pd&expand=1769) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd))] @@ -6418,7 +10880,7 @@ pub unsafe fn _mm512_cvtps_pd(a: __m256) -> __m512d { /// Convert packed single-precision (32-bit) floating-point elements in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtps_pd&expand=1770) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_pd&expand=1770) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd))] @@ -6433,7 +10895,7 @@ pub unsafe fn _mm512_mask_cvtps_pd(src: __m512d, k: __mmask8, a: __m256) -> __m5 /// Convert packed single-precision (32-bit) floating-point elements in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtps_pd&expand=1771) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtps_pd&expand=1771) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd))] @@ -6448,7 +10910,7 @@ pub unsafe fn _mm512_maskz_cvtps_pd(k: __mmask8, a: __m256) -> __m512d { /// Performs element-by-element conversion of the lower half of packed single-precision (32-bit) floating-point elements in v2 to packed double-precision (64-bit) floating-point elements, storing the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtpslo_pd&expand=1784) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpslo_pd&expand=1784) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd))] @@ -6463,7 +10925,7 @@ pub unsafe fn _mm512_cvtpslo_pd(v2: __m512) -> __m512d { /// Performs element-by-element conversion of the lower half of packed single-precision (32-bit) floating-point elements in v2 to packed double-precision (64-bit) floating-point elements, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtpslo_pd&expand=1785) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpslo_pd&expand=1785) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd))] @@ -6478,7 +10940,7 @@ pub unsafe fn _mm512_mask_cvtpslo_pd(src: __m512d, k: __mmask8, v2: __m512) -> _ /// Convert packed double-precision (64-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtpd_ps&expand=1712) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_ps&expand=1712) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps))] @@ -6493,7 +10955,7 @@ pub unsafe fn _mm512_cvtpd_ps(a: __m512d) -> __m256 { /// Convert packed double-precision (64-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtpd_ps&expand=1713) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_ps&expand=1713) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps))] @@ -6508,7 +10970,7 @@ pub unsafe fn _mm512_mask_cvtpd_ps(src: __m256, k: __mmask8, a: __m512d) -> __m2 /// Convert packed double-precision (64-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtpd_ps&expand=1714) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtpd_ps&expand=1714) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps))] @@ -6521,9 +10983,273 @@ pub unsafe fn _mm512_maskz_cvtpd_ps(k: __mmask8, a: __m512d) -> __m256 { )) } +/// Convert packed double-precision (64-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtpd_ps&expand=1710) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2ps))] +pub unsafe fn _mm256_mask_cvtpd_ps(src: __m128, k: __mmask8, a: __m256d) -> __m128 { + let convert = _mm256_cvtpd_ps(a); + transmute(simd_select_bitmask(k, convert.as_f32x4(), src.as_f32x4())) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtpd_ps&expand=1711) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2ps))] +pub unsafe fn _mm256_maskz_cvtpd_ps(k: __mmask8, a: __m256d) -> __m128 { + let convert = _mm256_cvtpd_ps(a); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, convert.as_f32x4(), zero)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtpd_ps&expand=1707) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2ps))] +pub unsafe fn _mm_mask_cvtpd_ps(src: __m128, k: __mmask8, a: __m128d) -> __m128 { + let convert = _mm_cvtpd_ps(a); + transmute(simd_select_bitmask(k, convert.as_f32x4(), src.as_f32x4())) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtpd_ps&expand=1708) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2ps))] +pub unsafe fn _mm_maskz_cvtpd_ps(k: __mmask8, a: __m128d) -> __m128 { + let convert = _mm_cvtpd_ps(a); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, convert.as_f32x4(), zero)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_epi32&expand=1675) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtpd2dq))] +pub unsafe fn _mm512_cvtpd_epi32(a: __m512d) -> __m256i { + transmute(vcvtpd2dq( + a.as_f64x8(), + _mm256_setzero_si256().as_i32x8(), + 0b11111111, + _MM_FROUND_CUR_DIRECTION, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_epi32&expand=1676) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtpd2dq))] +pub unsafe fn _mm512_mask_cvtpd_epi32(src: __m256i, k: __mmask8, a: __m512d) -> __m256i { + transmute(vcvtpd2dq( + a.as_f64x8(), + src.as_i32x8(), + k, + _MM_FROUND_CUR_DIRECTION, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtpd_epi32&expand=1677) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtpd2dq))] +pub unsafe fn _mm512_maskz_cvtpd_epi32(k: __mmask8, a: __m512d) -> __m256i { + transmute(vcvtpd2dq( + a.as_f64x8(), + _mm256_setzero_si256().as_i32x8(), + k, + _MM_FROUND_CUR_DIRECTION, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtpd_epi32&expand=1673) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2dq))] +pub unsafe fn _mm256_mask_cvtpd_epi32(src: __m128i, k: __mmask8, a: __m256d) -> __m128i { + let convert = _mm256_cvtpd_epi32(a); + transmute(simd_select_bitmask(k, convert.as_i32x4(), src.as_i32x4())) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtpd_epi32&expand=1674) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2dq))] +pub unsafe fn _mm256_maskz_cvtpd_epi32(k: __mmask8, a: __m256d) -> __m128i { + let convert = _mm256_cvtpd_epi32(a); + transmute(simd_select_bitmask( + k, + convert.as_i32x4(), + _mm_setzero_si128().as_i32x4(), + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtpd_epi32&expand=1670) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2dq))] +pub unsafe fn _mm_mask_cvtpd_epi32(src: __m128i, k: __mmask8, a: __m128d) -> __m128i { + let convert = _mm_cvtpd_epi32(a); + transmute(simd_select_bitmask(k, convert.as_i32x4(), src.as_i32x4())) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtpd_epi32&expand=1671) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2dq))] +pub unsafe fn _mm_maskz_cvtpd_epi32(k: __mmask8, a: __m128d) -> __m128i { + let convert = _mm_cvtpd_epi32(a); + transmute(simd_select_bitmask( + k, + convert.as_i32x4(), + _mm_setzero_si128().as_i32x4(), + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_epu32&expand=1693) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm512_cvtpd_epu32(a: __m512d) -> __m256i { + transmute(vcvtpd2udq( + a.as_f64x8(), + _mm256_setzero_si256().as_u32x8(), + 0b11111111, + _MM_FROUND_CUR_DIRECTION, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_epu32&expand=1694) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm512_mask_cvtpd_epu32(src: __m256i, k: __mmask8, a: __m512d) -> __m256i { + transmute(vcvtpd2udq( + a.as_f64x8(), + src.as_u32x8(), + k, + _MM_FROUND_CUR_DIRECTION, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtpd_epu32&expand=1695) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm512_maskz_cvtpd_epu32(k: __mmask8, a: __m512d) -> __m256i { + transmute(vcvtpd2udq( + a.as_f64x8(), + _mm256_setzero_si256().as_u32x8(), + k, + _MM_FROUND_CUR_DIRECTION, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtpd_epu32&expand=1690) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm256_cvtpd_epu32(a: __m256d) -> __m128i { + transmute(vcvtpd2udq256( + a.as_f64x4(), + _mm_setzero_si128().as_u32x4(), + 0b11111111, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtpd_epu32&expand=1691) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm256_mask_cvtpd_epu32(src: __m128i, k: __mmask8, a: __m256d) -> __m128i { + transmute(vcvtpd2udq256(a.as_f64x4(), src.as_u32x4(), k)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtpd_epu32&expand=1692) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm256_maskz_cvtpd_epu32(k: __mmask8, a: __m256d) -> __m128i { + transmute(vcvtpd2udq256( + a.as_f64x4(), + _mm_setzero_si128().as_u32x4(), + k, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_epu32&expand=1687) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm_cvtpd_epu32(a: __m128d) -> __m128i { + transmute(vcvtpd2udq128( + a.as_f64x2(), + _mm_setzero_si128().as_u32x4(), + 0b11111111, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtpd_epu32&expand=1688) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm_mask_cvtpd_epu32(src: __m128i, k: __mmask8, a: __m128d) -> __m128i { + transmute(vcvtpd2udq128(a.as_f64x2(), src.as_u32x4(), k)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtpd_epu32&expand=1689) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtpd2udq))] +pub unsafe fn _mm_maskz_cvtpd_epu32(k: __mmask8, a: __m128d) -> __m128i { + transmute(vcvtpd2udq128( + a.as_f64x2(), + _mm_setzero_si128().as_u32x4(), + k, + )) +} + /// Performs an element-by-element conversion of packed double-precision (64-bit) floating-point elements in v2 to single-precision (32-bit) floating-point elements and stores them in dst. The elements are stored in the lower half of the results vector, while the remaining upper half locations are set to 0. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtpd_pslo&expand=1715) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtpd_pslo&expand=1715) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps))] @@ -6543,7 +11269,7 @@ pub unsafe fn _mm512_cvtpd_pslo(v2: __m512d) -> __m512 { /// Performs an element-by-element conversion of packed double-precision (64-bit) floating-point elements in v2 to single-precision (32-bit) floating-point elements and stores them in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). The elements are stored in the lower half of the results vector, while the remaining upper half locations are set to 0. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtpd_pslo&expand=1716) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtpd_pslo&expand=1716) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps))] @@ -6563,7 +11289,7 @@ pub unsafe fn _mm512_mask_cvtpd_pslo(src: __m512, k: __mmask8, v2: __m512d) -> _ /// Sign extend packed 8-bit integers in a to packed 32-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi8_epi32&expand=1535) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi8_epi32&expand=1535) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxbd))] @@ -6574,7 +11300,7 @@ pub unsafe fn _mm512_cvtepi8_epi32(a: __m128i) -> __m512i { /// Sign extend packed 8-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi8_epi32&expand=1536) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi8_epi32&expand=1536) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxbd))] @@ -6585,7 +11311,7 @@ pub unsafe fn _mm512_mask_cvtepi8_epi32(src: __m512i, k: __mmask16, a: __m128i) /// Sign extend packed 8-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi8_epi32&expand=1537) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi8_epi32&expand=1537) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxbd))] @@ -6595,9 +11321,55 @@ pub unsafe fn _mm512_maskz_cvtepi8_epi32(k: __mmask16, a: __m128i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Sign extend packed 8-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi8_epi32&expand=1533) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbd))] +pub unsafe fn _mm256_mask_cvtepi8_epi32(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi8_epi32(a).as_i32x8(); + transmute(simd_select_bitmask(k, convert, src.as_i32x8())) +} + +/// Sign extend packed 8-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi8_epi32&expand=1534) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbd))] +pub unsafe fn _mm256_maskz_cvtepi8_epi32(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi8_epi32(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Sign extend packed 8-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi8_epi32&expand=1530) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbd))] +pub unsafe fn _mm_mask_cvtepi8_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi8_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, convert, src.as_i32x4())) +} + +/// Sign extend packed 8-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi8_epi32&expand=1531) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbd))] +pub unsafe fn _mm_maskz_cvtepi8_epi32(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi8_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Sign extend packed 8-bit integers in the low 8 bytes of a to packed 64-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi8_epi64&expand=1544) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi8_epi64&expand=1544) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxbq))] @@ -6609,7 +11381,7 @@ pub unsafe fn _mm512_cvtepi8_epi64(a: __m128i) -> __m512i { /// Sign extend packed 8-bit integers in the low 8 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi8_epi64&expand=1545) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi8_epi64&expand=1545) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxbq))] @@ -6620,7 +11392,7 @@ pub unsafe fn _mm512_mask_cvtepi8_epi64(src: __m512i, k: __mmask8, a: __m128i) - /// Sign extend packed 8-bit integers in the low 8 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi8_epi64&expand=1546) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi8_epi64&expand=1546) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxbq))] @@ -6630,9 +11402,55 @@ pub unsafe fn _mm512_maskz_cvtepi8_epi64(k: __mmask8, a: __m128i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Sign extend packed 8-bit integers in the low 4 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi8_epi64&expand=1542) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbq))] +pub unsafe fn _mm256_mask_cvtepi8_epi64(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi8_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, convert, src.as_i64x4())) +} + +/// Sign extend packed 8-bit integers in the low 4 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi8_epi64&expand=1543) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbq))] +pub unsafe fn _mm256_maskz_cvtepi8_epi64(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi8_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Sign extend packed 8-bit integers in the low 2 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi8_epi64&expand=1539) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbq))] +pub unsafe fn _mm_mask_cvtepi8_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi8_epi64(a).as_i64x2(); + transmute(simd_select_bitmask(k, convert, src.as_i64x2())) +} + +/// Sign extend packed 8-bit integers in the low 2 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi8_epi64&expand=1540) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxbq))] +pub unsafe fn _mm_maskz_cvtepi8_epi64(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi8_epi64(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Zero extend packed unsigned 8-bit integers in a to packed 32-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu8_epi32&expand=1621) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu8_epi32&expand=1621) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxbd))] @@ -6643,7 +11461,7 @@ pub unsafe fn _mm512_cvtepu8_epi32(a: __m128i) -> __m512i { /// Zero extend packed unsigned 8-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu8_epi32&expand=1622) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu8_epi32&expand=1622) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxbd))] @@ -6654,7 +11472,7 @@ pub unsafe fn _mm512_mask_cvtepu8_epi32(src: __m512i, k: __mmask16, a: __m128i) /// Zero extend packed unsigned 8-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepu8_epi32&expand=1623) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu8_epi32&expand=1623) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxbd))] @@ -6664,9 +11482,55 @@ pub unsafe fn _mm512_maskz_cvtepu8_epi32(k: __mmask16, a: __m128i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Zero extend packed unsigned 8-bit integers in the low 8 bytes of a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepu8_epi32&expand=1619) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbd))] +pub unsafe fn _mm256_mask_cvtepu8_epi32(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu8_epi32(a).as_i32x8(); + transmute(simd_select_bitmask(k, convert, src.as_i32x8())) +} + +/// Zero extend packed unsigned 8-bit integers in the low 8 bytes of a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=_mm256_maskz_cvtepu8_epi32&expand=1620) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbd))] +pub unsafe fn _mm256_maskz_cvtepu8_epi32(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu8_epi32(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Zero extend packed unsigned 8-bit integers in the low 4 bytes of a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepu8_epi32&expand=1616) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbd))] +pub unsafe fn _mm_mask_cvtepu8_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu8_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, convert, src.as_i32x4())) +} + +/// Zero extend packed unsigned 8-bit integers in th elow 4 bytes of a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=_mm_maskz_cvtepu8_epi32&expand=1617) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbd))] +pub unsafe fn _mm_maskz_cvtepu8_epi32(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu8_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Zero extend packed unsigned 8-bit integers in the low 8 byte sof a to packed 64-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu8_epi64&expand=1630) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu8_epi64&expand=1630) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxbq))] @@ -6678,7 +11542,7 @@ pub unsafe fn _mm512_cvtepu8_epi64(a: __m128i) -> __m512i { /// Zero extend packed unsigned 8-bit integers in the low 8 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu8_epi64&expand=1631) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu8_epi64&expand=1631) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxbq))] @@ -6689,7 +11553,7 @@ pub unsafe fn _mm512_mask_cvtepu8_epi64(src: __m512i, k: __mmask8, a: __m128i) - /// Zero extend packed unsigned 8-bit integers in the low 8 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepu8_epi64&expand=1632) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu8_epi64&expand=1632) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxbq))] @@ -6699,9 +11563,55 @@ pub unsafe fn _mm512_maskz_cvtepu8_epi64(k: __mmask8, a: __m128i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Zero extend packed unsigned 8-bit integers in the low 4 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepu8_epi64&expand=1628) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbq))] +pub unsafe fn _mm256_mask_cvtepu8_epi64(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu8_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, convert, src.as_i64x4())) +} + +/// Zero extend packed unsigned 8-bit integers in the low 4 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepu8_epi64&expand=1629) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbq))] +pub unsafe fn _mm256_maskz_cvtepu8_epi64(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu8_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Zero extend packed unsigned 8-bit integers in the low 2 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepu8_epi64&expand=1625) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbq))] +pub unsafe fn _mm_mask_cvtepu8_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu8_epi64(a).as_i64x2(); + transmute(simd_select_bitmask(k, convert, src.as_i64x2())) +} + +/// Zero extend packed unsigned 8-bit integers in the low 2 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepu8_epi64&expand=1626) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxbq))] +pub unsafe fn _mm_maskz_cvtepu8_epi64(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu8_epi64(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Sign extend packed 16-bit integers in a to packed 32-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi16_epi32&expand=1389) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi16_epi32&expand=1389) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxwd))] @@ -6712,7 +11622,7 @@ pub unsafe fn _mm512_cvtepi16_epi32(a: __m256i) -> __m512i { /// Sign extend packed 16-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi16_epi32&expand=1390) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi16_epi32&expand=1390) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxwd))] @@ -6723,7 +11633,7 @@ pub unsafe fn _mm512_mask_cvtepi16_epi32(src: __m512i, k: __mmask16, a: __m256i) /// Sign extend packed 16-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi16_epi32&expand=1391) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi16_epi32&expand=1391) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxwd))] @@ -6733,9 +11643,55 @@ pub unsafe fn _mm512_maskz_cvtepi16_epi32(k: __mmask16, a: __m256i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Sign extend packed 16-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi16_epi32&expand=1387) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwd))] +pub unsafe fn _mm256_mask_cvtepi16_epi32(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi16_epi32(a).as_i32x8(); + transmute(simd_select_bitmask(k, convert, src.as_i32x8())) +} + +/// Sign extend packed 16-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi16_epi32&expand=1388) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwd))] +pub unsafe fn _mm256_maskz_cvtepi16_epi32(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi16_epi32(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Sign extend packed 16-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi16_epi32&expand=1384) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwd))] +pub unsafe fn _mm_mask_cvtepi16_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi16_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, convert, src.as_i32x4())) +} + +/// Sign extend packed 16-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi16_epi32&expand=1385) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwd))] +pub unsafe fn _mm_maskz_cvtepi16_epi32(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi16_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Sign extend packed 16-bit integers in a to packed 64-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi16_epi64&expand=1398) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi16_epi64&expand=1398) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxwq))] @@ -6746,7 +11702,7 @@ pub unsafe fn _mm512_cvtepi16_epi64(a: __m128i) -> __m512i { /// Sign extend packed 16-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi16_epi64&expand=1399) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi16_epi64&expand=1399) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxwq))] @@ -6757,7 +11713,7 @@ pub unsafe fn _mm512_mask_cvtepi16_epi64(src: __m512i, k: __mmask8, a: __m128i) /// Sign extend packed 16-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi16_epi64&expand=1400) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi16_epi64&expand=1400) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxwq))] @@ -6767,9 +11723,55 @@ pub unsafe fn _mm512_maskz_cvtepi16_epi64(k: __mmask8, a: __m128i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Sign extend packed 16-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi16_epi64&expand=1396) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwq))] +pub unsafe fn _mm256_mask_cvtepi16_epi64(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi16_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, convert, src.as_i64x4())) +} + +/// Sign extend packed 16-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi16_epi64&expand=1397) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwq))] +pub unsafe fn _mm256_maskz_cvtepi16_epi64(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi16_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Sign extend packed 16-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi16_epi64&expand=1393) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwq))] +pub unsafe fn _mm_mask_cvtepi16_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi16_epi64(a).as_i64x2(); + transmute(simd_select_bitmask(k, convert, src.as_i64x2())) +} + +/// Sign extend packed 16-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi16_epi64&expand=1394) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxwq))] +pub unsafe fn _mm_maskz_cvtepi16_epi64(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi16_epi64(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Zero extend packed unsigned 16-bit integers in a to packed 32-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu16_epi32&expand=1553) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu16_epi32&expand=1553) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxwd))] @@ -6780,7 +11782,7 @@ pub unsafe fn _mm512_cvtepu16_epi32(a: __m256i) -> __m512i { /// Zero extend packed unsigned 16-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu16_epi32&expand=1554) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu16_epi32&expand=1554) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxwd))] @@ -6791,7 +11793,7 @@ pub unsafe fn _mm512_mask_cvtepu16_epi32(src: __m512i, k: __mmask16, a: __m256i) /// Zero extend packed unsigned 16-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepu16_epi32&expand=1555) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu16_epi32&expand=1555) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxwd))] @@ -6801,9 +11803,55 @@ pub unsafe fn _mm512_maskz_cvtepu16_epi32(k: __mmask16, a: __m256i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Zero extend packed unsigned 16-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepu16_epi32&expand=1551) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwd))] +pub unsafe fn _mm256_mask_cvtepu16_epi32(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu16_epi32(a).as_i32x8(); + transmute(simd_select_bitmask(k, convert, src.as_i32x8())) +} + +/// Zero extend packed unsigned 16-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepu16_epi32&expand=1552) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwd))] +pub unsafe fn _mm256_maskz_cvtepu16_epi32(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu16_epi32(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Zero extend packed unsigned 16-bit integers in a to packed 32-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepu16_epi32&expand=1548) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwd))] +pub unsafe fn _mm_mask_cvtepu16_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu16_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, convert, src.as_i32x4())) +} + +/// Zero extend packed unsigned 16-bit integers in a to packed 32-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepu16_epi32&expand=1549) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwd))] +pub unsafe fn _mm_maskz_cvtepu16_epi32(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu16_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Zero extend packed unsigned 16-bit integers in a to packed 64-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu16_epi64&expand=1562) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu16_epi64&expand=1562) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxwq))] @@ -6814,7 +11862,7 @@ pub unsafe fn _mm512_cvtepu16_epi64(a: __m128i) -> __m512i { /// Zero extend packed unsigned 16-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu16_epi64&expand=1563) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu16_epi64&expand=1563) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxwq))] @@ -6825,7 +11873,7 @@ pub unsafe fn _mm512_mask_cvtepu16_epi64(src: __m512i, k: __mmask8, a: __m128i) /// Zero extend packed unsigned 16-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepu16_epi64&expand=1564) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu16_epi64&expand=1564) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxwq))] @@ -6835,9 +11883,55 @@ pub unsafe fn _mm512_maskz_cvtepu16_epi64(k: __mmask8, a: __m128i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Zero extend packed unsigned 16-bit integers in the low 8 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepu16_epi64&expand=1560) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwq))] +pub unsafe fn _mm256_mask_cvtepu16_epi64(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu16_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, convert, src.as_i64x4())) +} + +/// Zero extend packed unsigned 16-bit integers in the low 8 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepu16_epi64&expand=1561) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwq))] +pub unsafe fn _mm256_maskz_cvtepu16_epi64(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu16_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Zero extend packed unsigned 16-bit integers in the low 4 bytes of a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepu16_epi64&expand=1557) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwq))] +pub unsafe fn _mm_mask_cvtepu16_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu16_epi64(a).as_i64x2(); + transmute(simd_select_bitmask(k, convert, src.as_i64x2())) +} + +/// Zero extend packed unsigned 16-bit integers in the low 4 bytes of a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepu16_epi64&expand=1558) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxwq))] +pub unsafe fn _mm_maskz_cvtepu16_epi64(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu16_epi64(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi32_epi64&expand=1428) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_epi64&expand=1428) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxdq))] @@ -6848,7 +11942,7 @@ pub unsafe fn _mm512_cvtepi32_epi64(a: __m256i) -> __m512i { /// Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi32_epi64&expand=1429) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_epi64&expand=1429) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxdq))] @@ -6859,7 +11953,7 @@ pub unsafe fn _mm512_mask_cvtepi32_epi64(src: __m512i, k: __mmask8, a: __m256i) /// Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi32_epi64&expand=1430) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_epi64&expand=1430) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsxdq))] @@ -6869,9 +11963,55 @@ pub unsafe fn _mm512_maskz_cvtepi32_epi64(k: __mmask8, a: __m256i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi32_epi64&expand=1426) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxdq))] +pub unsafe fn _mm256_mask_cvtepi32_epi64(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi32_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, convert, src.as_i64x4())) +} + +/// Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi32_epi64&expand=1427) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxdq))] +pub unsafe fn _mm256_maskz_cvtepi32_epi64(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepi32_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi32_epi64&expand=1423) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxdq))] +pub unsafe fn _mm_mask_cvtepi32_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi32_epi64(a).as_i64x2(); + transmute(simd_select_bitmask(k, convert, src.as_i64x2())) +} + +/// Sign extend packed 32-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi32_epi64&expand=1424) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsxdq))] +pub unsafe fn _mm_maskz_cvtepi32_epi64(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepi32_epi64(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu32_epi64&expand=1571) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32_epi64&expand=1571) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxdq))] @@ -6882,7 +12022,7 @@ pub unsafe fn _mm512_cvtepu32_epi64(a: __m256i) -> __m512i { /// Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu32_epi64&expand=1572) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32_epi64&expand=1572) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxdq))] @@ -6893,7 +12033,7 @@ pub unsafe fn _mm512_mask_cvtepu32_epi64(src: __m512i, k: __mmask8, a: __m256i) /// Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepu32_epi64&expand=1573) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu32_epi64&expand=1573) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovzxdq))] @@ -6903,9 +12043,55 @@ pub unsafe fn _mm512_maskz_cvtepu32_epi64(k: __mmask8, a: __m256i) -> __m512i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepu32_epi64&expand=1569) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxdq))] +pub unsafe fn _mm256_mask_cvtepu32_epi64(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu32_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, convert, src.as_i64x4())) +} + +/// Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepu32_epi64&expand=1570) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxdq))] +pub unsafe fn _mm256_maskz_cvtepu32_epi64(k: __mmask8, a: __m128i) -> __m256i { + let convert = _mm256_cvtepu32_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepu32_epi64&expand=1566) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxdq))] +pub unsafe fn _mm_mask_cvtepu32_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu32_epi64(a).as_i64x2(); + transmute(simd_select_bitmask(k, convert, src.as_i64x2())) +} + +/// Zero extend packed unsigned 32-bit integers in a to packed 64-bit integers, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepu32_epi64&expand=1567) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovzxdq))] +pub unsafe fn _mm_maskz_cvtepu32_epi64(k: __mmask8, a: __m128i) -> __m128i { + let convert = _mm_cvtepu32_epi64(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Convert packed signed 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi32_ps&expand=1455) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_ps&expand=1455) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2ps))] @@ -6916,7 +12102,7 @@ pub unsafe fn _mm512_cvtepi32_ps(a: __m512i) -> __m512 { /// Convert packed signed 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi32_ps&expand=1456) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_ps&expand=1456) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2ps))] @@ -6927,7 +12113,7 @@ pub unsafe fn _mm512_mask_cvtepi32_ps(src: __m512, k: __mmask16, a: __m512i) -> /// Convert packed signed 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi32_ps&expand=1457) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_ps&expand=1457) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2ps))] @@ -6937,9 +12123,55 @@ pub unsafe fn _mm512_maskz_cvtepi32_ps(k: __mmask16, a: __m512i) -> __m512 { transmute(simd_select_bitmask(k, convert, zero)) } +/// Convert packed signed 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi32_ps&expand=1453) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2ps))] +pub unsafe fn _mm256_mask_cvtepi32_ps(src: __m256, k: __mmask8, a: __m256i) -> __m256 { + let convert = _mm256_cvtepi32_ps(a).as_f32x8(); + transmute(simd_select_bitmask(k, convert, src.as_f32x8())) +} + +/// Convert packed signed 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi32_ps&expand=1454) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2ps))] +pub unsafe fn _mm256_maskz_cvtepi32_ps(k: __mmask8, a: __m256i) -> __m256 { + let convert = _mm256_cvtepi32_ps(a).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Convert packed signed 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi32_ps&expand=1450) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2ps))] +pub unsafe fn _mm_mask_cvtepi32_ps(src: __m128, k: __mmask8, a: __m128i) -> __m128 { + let convert = _mm_cvtepi32_ps(a).as_f32x4(); + transmute(simd_select_bitmask(k, convert, src.as_f32x4())) +} + +/// Convert packed signed 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi32_ps&expand=1451) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2ps))] +pub unsafe fn _mm_maskz_cvtepi32_ps(k: __mmask8, a: __m128i) -> __m128 { + let convert = _mm_cvtepi32_ps(a).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Convert packed signed 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi32_pd&expand=1446) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_pd&expand=1446) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2pd))] @@ -6950,7 +12182,7 @@ pub unsafe fn _mm512_cvtepi32_pd(a: __m256i) -> __m512d { /// Convert packed signed 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi32_pd&expand=1447) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_pd&expand=1447) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2pd))] @@ -6961,7 +12193,7 @@ pub unsafe fn _mm512_mask_cvtepi32_pd(src: __m512d, k: __mmask8, a: __m256i) -> /// Convert packed signed 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi32_pd&expand=1448) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_pd&expand=1448) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2pd))] @@ -6971,9 +12203,55 @@ pub unsafe fn _mm512_maskz_cvtepi32_pd(k: __mmask8, a: __m256i) -> __m512d { transmute(simd_select_bitmask(k, convert, zero)) } +/// Convert packed signed 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi32_pd&expand=1444) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2pd))] +pub unsafe fn _mm256_mask_cvtepi32_pd(src: __m256d, k: __mmask8, a: __m128i) -> __m256d { + let convert = _mm256_cvtepi32_pd(a).as_f64x4(); + transmute(simd_select_bitmask(k, convert, src.as_f64x4())) +} + +/// Convert packed signed 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi32_pd&expand=1445) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2pd))] +pub unsafe fn _mm256_maskz_cvtepi32_pd(k: __mmask8, a: __m128i) -> __m256d { + let convert = _mm256_cvtepi32_pd(a).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Convert packed signed 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi32_pd&expand=1441) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2pd))] +pub unsafe fn _mm_mask_cvtepi32_pd(src: __m128d, k: __mmask8, a: __m128i) -> __m128d { + let convert = _mm_cvtepi32_pd(a).as_f64x2(); + transmute(simd_select_bitmask(k, convert, src.as_f64x2())) +} + +/// Convert packed signed 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi32_pd&expand=1442) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtdq2pd))] +pub unsafe fn _mm_maskz_cvtepi32_pd(k: __mmask8, a: __m128i) -> __m128d { + let convert = _mm_cvtepi32_pd(a).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu32_ps&expand=1583) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32_ps&expand=1583) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] @@ -6984,7 +12262,7 @@ pub unsafe fn _mm512_cvtepu32_ps(a: __m512i) -> __m512 { /// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu32_ps&expand=1584) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32_ps&expand=1584) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] @@ -6995,7 +12273,7 @@ pub unsafe fn _mm512_mask_cvtepu32_ps(src: __m512, k: __mmask16, a: __m512i) -> /// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepu32_ps&expand=1585) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu32_ps&expand=1585) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] @@ -7007,7 +12285,7 @@ pub unsafe fn _mm512_maskz_cvtepu32_ps(k: __mmask16, a: __m512i) -> __m512 { /// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu32_pd&expand=1580) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32_pd&expand=1580) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2pd))] @@ -7018,7 +12296,7 @@ pub unsafe fn _mm512_cvtepu32_pd(a: __m256i) -> __m512d { /// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu32_pd&expand=1581) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32_pd&expand=1581) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2pd))] @@ -7029,7 +12307,7 @@ pub unsafe fn _mm512_mask_cvtepu32_pd(src: __m512d, k: __mmask8, a: __m256i) -> /// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepu32_pd&expand=1582) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepu32_pd&expand=1582) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2pd))] @@ -7039,9 +12317,78 @@ pub unsafe fn _mm512_maskz_cvtepu32_pd(k: __mmask8, a: __m256i) -> __m512d { transmute(simd_select_bitmask(k, convert, zero)) } +/// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtepu32_pd&expand=1577) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtudq2pd))] +pub unsafe fn _mm256_cvtepu32_pd(a: __m128i) -> __m256d { + let a = a.as_u32x4(); + transmute::(simd_cast(a)) +} + +/// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepu32_pd&expand=1578) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtudq2pd))] +pub unsafe fn _mm256_mask_cvtepu32_pd(src: __m256d, k: __mmask8, a: __m128i) -> __m256d { + let convert = _mm256_cvtepu32_pd(a).as_f64x4(); + transmute(simd_select_bitmask(k, convert, src.as_f64x4())) +} + +/// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepu32_pd&expand=1579) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtudq2pd))] +pub unsafe fn _mm256_maskz_cvtepu32_pd(k: __mmask8, a: __m128i) -> __m256d { + let convert = _mm256_cvtepu32_pd(a).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepu32_pd&expand=1574) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtudq2pd))] +pub unsafe fn _mm_cvtepu32_pd(a: __m128i) -> __m128d { + let a = a.as_u32x4(); + let u64: u32x2 = simd_shuffle2(a, a, [0, 1]); + transmute::(simd_cast(u64)) +} + +/// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepu32_pd&expand=1575) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtudq2pd))] +pub unsafe fn _mm_mask_cvtepu32_pd(src: __m128d, k: __mmask8, a: __m128i) -> __m128d { + let convert = _mm_cvtepu32_pd(a).as_f64x2(); + transmute(simd_select_bitmask(k, convert, src.as_f64x2())) +} + +/// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepu32_pd&expand=1576) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtudq2pd))] +pub unsafe fn _mm_maskz_cvtepu32_pd(k: __mmask8, a: __m128i) -> __m128d { + let convert = _mm_cvtepu32_pd(a).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, convert, zero)) +} + /// Performs element-by-element conversion of the lower half of packed 32-bit integer elements in v2 to packed double-precision (64-bit) floating-point elements, storing the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi32lo_pd&expand=1464) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32lo_pd&expand=1464) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2pd))] @@ -7053,7 +12400,7 @@ pub unsafe fn _mm512_cvtepi32lo_pd(v2: __m512i) -> __m512d { /// Performs element-by-element conversion of the lower half of packed 32-bit integer elements in v2 to packed double-precision (64-bit) floating-point elements, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi32lo_pd&expand=1465) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32lo_pd&expand=1465) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2pd))] @@ -7064,7 +12411,7 @@ pub unsafe fn _mm512_mask_cvtepi32lo_pd(src: __m512d, k: __mmask8, v2: __m512i) /// Performs element-by-element conversion of the lower half of packed 32-bit unsigned integer elements in v2 to packed double-precision (64-bit) floating-point elements, storing the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepu32lo_pd&expand=1586) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepu32lo_pd&expand=1586) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2pd))] @@ -7076,7 +12423,7 @@ pub unsafe fn _mm512_cvtepu32lo_pd(v2: __m512i) -> __m512d { /// Performs element-by-element conversion of the lower half of 32-bit unsigned integer elements in v2 to packed double-precision (64-bit) floating-point elements, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepu32lo_pd&expand=1587) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepu32lo_pd&expand=1587) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2pd))] @@ -7087,7 +12434,7 @@ pub unsafe fn _mm512_mask_cvtepu32lo_pd(src: __m512d, k: __mmask8, v2: __m512i) /// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi32_epi16&expand=1419) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_epi16&expand=1419) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovdw))] @@ -7098,7 +12445,7 @@ pub unsafe fn _mm512_cvtepi32_epi16(a: __m512i) -> __m256i { /// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi32_epi16&expand=1420) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_epi16&expand=1420) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovdw))] @@ -7109,7 +12456,7 @@ pub unsafe fn _mm512_mask_cvtepi32_epi16(src: __m256i, k: __mmask16, a: __m512i) /// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi32_epi16&expand=1421) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_epi16&expand=1421) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovdw))] @@ -7119,31 +12466,99 @@ pub unsafe fn _mm512_maskz_cvtepi32_epi16(k: __mmask16, a: __m512i) -> __m256i { transmute(simd_select_bitmask(k, convert, zero)) } -/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi32_epi8&expand=1437) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtepi32_epi16&expand=1416) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpmovdb))] -pub unsafe fn _mm512_cvtepi32_epi8(a: __m512i) -> __m128i { - let a = a.as_i32x16(); - transmute::(simd_cast(a)) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm256_cvtepi32_epi16(a: __m256i) -> __m128i { + let a = a.as_i32x8(); + transmute::(simd_cast(a)) } -/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi32_epi8&expand=1438) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi32_epi16&expand=1417) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpmovdb))] -pub unsafe fn _mm512_mask_cvtepi32_epi8(src: __m128i, k: __mmask16, a: __m512i) -> __m128i { - let convert = _mm512_cvtepi32_epi8(a).as_i8x16(); - transmute(simd_select_bitmask(k, convert, src.as_i8x16())) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm256_mask_cvtepi32_epi16(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + let convert = _mm256_cvtepi32_epi16(a).as_i16x8(); + transmute(simd_select_bitmask(k, convert, src.as_i16x8())) +} + +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi32_epi16&expand=1418) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm256_maskz_cvtepi32_epi16(k: __mmask8, a: __m256i) -> __m128i { + let convert = _mm256_cvtepi32_epi16(a).as_i16x8(); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi32_epi16&expand=1413) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm_cvtepi32_epi16(a: __m128i) -> __m128i { + transmute(vpmovdw128( + a.as_i32x4(), + _mm_setzero_si128().as_i16x8(), + 0b11111111, + )) +} + +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi32_epi16&expand=1414) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm_mask_cvtepi32_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovdw128(a.as_i32x4(), src.as_i16x8(), k)) +} + +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi32_epi16&expand=1415) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm_maskz_cvtepi32_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovdw128(a.as_i32x4(), _mm_setzero_si128().as_i16x8(), k)) +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi32_epi8&expand=1437) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm512_cvtepi32_epi8(a: __m512i) -> __m128i { + let a = a.as_i32x16(); + transmute::(simd_cast(a)) +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_epi8&expand=1438) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm512_mask_cvtepi32_epi8(src: __m128i, k: __mmask16, a: __m512i) -> __m128i { + let convert = _mm512_cvtepi32_epi8(a).as_i8x16(); + transmute(simd_select_bitmask(k, convert, src.as_i8x16())) } /// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi32_epi8&expand=1439) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi32_epi8&expand=1439) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovdb))] @@ -7153,9 +12568,77 @@ pub unsafe fn _mm512_maskz_cvtepi32_epi8(k: __mmask16, a: __m512i) -> __m128i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtepi32_epi8&expand=1434) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm256_cvtepi32_epi8(a: __m256i) -> __m128i { + transmute(vpmovdb256( + a.as_i32x8(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi32_epi8&expand=1435) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm256_mask_cvtepi32_epi8(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovdb256(a.as_i32x8(), src.as_i8x16(), k)) +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi32_epi8&expand=1436) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm256_maskz_cvtepi32_epi8(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovdb256(a.as_i32x8(), _mm_setzero_si128().as_i8x16(), k)) +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi32_epi8&expand=1431) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm_cvtepi32_epi8(a: __m128i) -> __m128i { + transmute(vpmovdb128( + a.as_i32x4(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi32_epi8&expand=1432) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm_mask_cvtepi32_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovdb128(a.as_i32x4(), src.as_i8x16(), k)) +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi32_epi8&expand=1433) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm_maskz_cvtepi32_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovdb128(a.as_i32x4(), _mm_setzero_si128().as_i8x16(), k)) +} + /// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi64_epi32&expand=1481) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi64_epi32&expand=1481) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqd))] @@ -7166,7 +12649,7 @@ pub unsafe fn _mm512_cvtepi64_epi32(a: __m512i) -> __m256i { /// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi64_epi32&expand=1482) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_epi32&expand=1482) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqd))] @@ -7177,7 +12660,7 @@ pub unsafe fn _mm512_mask_cvtepi64_epi32(src: __m256i, k: __mmask8, a: __m512i) /// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi64_epi32&expand=1483) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi64_epi32&expand=1483) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqd))] @@ -7187,9 +12670,77 @@ pub unsafe fn _mm512_maskz_cvtepi64_epi32(k: __mmask8, a: __m512i) -> __m256i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtepi64_epi32&expand=1478) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm256_cvtepi64_epi32(a: __m256i) -> __m128i { + let a = a.as_i64x4(); + transmute::(simd_cast(a)) +} + +/// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi64_epi32&expand=1479) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm256_mask_cvtepi64_epi32(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + let convert = _mm256_cvtepi64_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, convert, src.as_i32x4())) +} + +/// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi64_epi32&expand=1480) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm256_maskz_cvtepi64_epi32(k: __mmask8, a: __m256i) -> __m128i { + let convert = _mm256_cvtepi64_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, convert, zero)) +} + +/// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi64_epi32&expand=1475) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm_cvtepi64_epi32(a: __m128i) -> __m128i { + transmute(vpmovqd128( + a.as_i64x2(), + _mm_setzero_si128().as_i32x4(), + 0b11111111, + )) +} + +/// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi64_epi32&expand=1476) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm_mask_cvtepi64_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovqd128(a.as_i64x2(), src.as_i32x4(), k)) +} + +/// Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi64_epi32&expand=1477) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm_maskz_cvtepi64_epi32(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovqd128(a.as_i64x2(), _mm_setzero_si128().as_i32x4(), k)) +} + /// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi64_epi16&expand=1472) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi64_epi16&expand=1472) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqw))] @@ -7200,7 +12751,7 @@ pub unsafe fn _mm512_cvtepi64_epi16(a: __m512i) -> __m128i { /// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi64_epi16&expand=1473) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_epi16&expand=1473) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqw))] @@ -7211,7 +12762,7 @@ pub unsafe fn _mm512_mask_cvtepi64_epi16(src: __m128i, k: __mmask8, a: __m512i) /// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi64_epi16&expand=1474) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi64_epi16&expand=1474) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqw))] @@ -7221,9 +12772,77 @@ pub unsafe fn _mm512_maskz_cvtepi64_epi16(k: __mmask8, a: __m512i) -> __m128i { transmute(simd_select_bitmask(k, convert, zero)) } +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtepi64_epi16&expand=1469) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm256_cvtepi64_epi16(a: __m256i) -> __m128i { + transmute(vpmovqw256( + a.as_i64x4(), + _mm_setzero_si128().as_i16x8(), + 0b11111111, + )) +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi64_epi16&expand=1470) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm256_mask_cvtepi64_epi16(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovqw256(a.as_i64x4(), src.as_i16x8(), k)) +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi64_epi16&expand=1471) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm256_maskz_cvtepi64_epi16(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovqw256(a.as_i64x4(), _mm_setzero_si128().as_i16x8(), k)) +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi64_epi16&expand=1466) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm_cvtepi64_epi16(a: __m128i) -> __m128i { + transmute(vpmovqw128( + a.as_i64x2(), + _mm_setzero_si128().as_i16x8(), + 0b11111111, + )) +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi64_epi16&expand=1467) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm_mask_cvtepi64_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovqw128(a.as_i64x2(), src.as_i16x8(), k)) +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi64_epi16&expand=1468) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm_maskz_cvtepi64_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovqw128(a.as_i64x2(), _mm_setzero_si128().as_i16x8(), k)) +} + /// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtepi64_epi8&expand=1490) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtepi64_epi8&expand=1490) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqb))] @@ -7237,7 +12856,7 @@ pub unsafe fn _mm512_cvtepi64_epi8(a: __m512i) -> __m128i { /// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtepi64_epi8&expand=1491) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_epi8&expand=1491) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqb))] @@ -7247,7 +12866,7 @@ pub unsafe fn _mm512_mask_cvtepi64_epi8(src: __m128i, k: __mmask8, a: __m512i) - /// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtepi64_epi8&expand=1492) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtepi64_epi8&expand=1492) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovqb))] @@ -7255,9 +12874,77 @@ pub unsafe fn _mm512_maskz_cvtepi64_epi8(k: __mmask8, a: __m512i) -> __m128i { transmute(vpmovqb(a.as_i64x8(), _mm_setzero_si128().as_i8x16(), k)) } +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtepi64_epi8&expand=1487) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm256_cvtepi64_epi8(a: __m256i) -> __m128i { + transmute(vpmovqb256( + a.as_i64x4(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi64_epi8&expand=1488) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm256_mask_cvtepi64_epi8(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovqb256(a.as_i64x4(), src.as_i8x16(), k)) +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtepi64_epi8&expand=1489) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm256_maskz_cvtepi64_epi8(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovqb256(a.as_i64x4(), _mm_setzero_si128().as_i8x16(), k)) +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtepi64_epi8&expand=1484) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm_cvtepi64_epi8(a: __m128i) -> __m128i { + transmute(vpmovqb128( + a.as_i64x2(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi64_epi8&expand=1485) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm_mask_cvtepi64_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovqb128(a.as_i64x2(), src.as_i8x16(), k)) +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtepi64_epi8&expand=1486) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm_maskz_cvtepi64_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovqb128(a.as_i64x2(), _mm_setzero_si128().as_i8x16(), k)) +} + /// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtsepi32_epi16&expand=1819) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi32_epi16&expand=1819) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsdw))] @@ -7271,7 +12958,7 @@ pub unsafe fn _mm512_cvtsepi32_epi16(a: __m512i) -> __m256i { /// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtsepi32_epi16&expand=1820) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_epi16&expand=1820) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsdw))] @@ -7281,7 +12968,7 @@ pub unsafe fn _mm512_mask_cvtsepi32_epi16(src: __m256i, k: __mmask16, a: __m512i /// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtsepi32_epi16&expand=1819) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi32_epi16&expand=1819) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsdw))] @@ -7293,9 +12980,77 @@ pub unsafe fn _mm512_maskz_cvtsepi32_epi16(k: __mmask16, a: __m512i) -> __m256i )) } +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtsepi32_epi16&expand=1816) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm256_cvtsepi32_epi16(a: __m256i) -> __m128i { + transmute(vpmovsdw256( + a.as_i32x8(), + _mm_setzero_si128().as_i16x8(), + 0b11111111, + )) +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi32_epi16&expand=1817) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm256_mask_cvtsepi32_epi16(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsdw256(a.as_i32x8(), src.as_i16x8(), k)) +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtsepi32_epi16&expand=1818) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm256_maskz_cvtsepi32_epi16(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsdw256(a.as_i32x8(), _mm_setzero_si128().as_i16x8(), k)) +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsepi32_epi16&expand=1813) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm_cvtsepi32_epi16(a: __m128i) -> __m128i { + transmute(vpmovsdw128( + a.as_i32x4(), + _mm_setzero_si128().as_i16x8(), + 0b11111111, + )) +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi32_epi16&expand=1814) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm_mask_cvtsepi32_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsdw128(a.as_i32x4(), src.as_i16x8(), k)) +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtsepi32_epi16&expand=1815) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm_maskz_cvtsepi32_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsdw128(a.as_i32x4(), _mm_setzero_si128().as_i16x8(), k)) +} + /// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtsepi32_epi8&expand=1828) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi32_epi8&expand=1828) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsdb))] @@ -7309,7 +13064,7 @@ pub unsafe fn _mm512_cvtsepi32_epi8(a: __m512i) -> __m128i { /// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtsepi32_epi8&expand=1829) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_epi8&expand=1829) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsdb))] @@ -7319,7 +13074,7 @@ pub unsafe fn _mm512_mask_cvtsepi32_epi8(src: __m128i, k: __mmask16, a: __m512i) /// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtsepi32_epi8&expand=1830) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi32_epi8&expand=1830) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsdb))] @@ -7327,9 +13082,77 @@ pub unsafe fn _mm512_maskz_cvtsepi32_epi8(k: __mmask16, a: __m512i) -> __m128i { transmute(vpmovsdb(a.as_i32x16(), _mm_setzero_si128().as_i8x16(), k)) } +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtsepi32_epi8&expand=1825) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm256_cvtsepi32_epi8(a: __m256i) -> __m128i { + transmute(vpmovsdb256( + a.as_i32x8(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi32_epi8&expand=1826) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm256_mask_cvtsepi32_epi8(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsdb256(a.as_i32x8(), src.as_i8x16(), k)) +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtsepi32_epi8&expand=1827) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm256_maskz_cvtsepi32_epi8(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsdb256(a.as_i32x8(), _mm_setzero_si128().as_i8x16(), k)) +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsepi32_epi8&expand=1822) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm_cvtsepi32_epi8(a: __m128i) -> __m128i { + transmute(vpmovsdb128( + a.as_i32x4(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi32_epi8&expand=1823) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm_mask_cvtsepi32_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsdb128(a.as_i32x4(), src.as_i8x16(), k)) +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtsepi32_epi8&expand=1824) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm_maskz_cvtsepi32_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsdb128(a.as_i32x4(), _mm_setzero_si128().as_i8x16(), k)) +} + /// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtsepi64_epi32&expand=1852) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi64_epi32&expand=1852) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqd))] @@ -7343,7 +13166,7 @@ pub unsafe fn _mm512_cvtsepi64_epi32(a: __m512i) -> __m256i { /// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtsepi64_epi32&expand=1853) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_epi32&expand=1853) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqd))] @@ -7353,7 +13176,7 @@ pub unsafe fn _mm512_mask_cvtsepi64_epi32(src: __m256i, k: __mmask8, a: __m512i) /// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtsepi64_epi32&expand=1854) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi64_epi32&expand=1854) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqd))] @@ -7361,9 +13184,77 @@ pub unsafe fn _mm512_maskz_cvtsepi64_epi32(k: __mmask8, a: __m512i) -> __m256i { transmute(vpmovsqd(a.as_i64x8(), _mm256_setzero_si256().as_i32x8(), k)) } +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtsepi64_epi32&expand=1849) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm256_cvtsepi64_epi32(a: __m256i) -> __m128i { + transmute(vpmovsqd256( + a.as_i64x4(), + _mm_setzero_si128().as_i32x4(), + 0b11111111, + )) +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi64_epi32&expand=1850) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm256_mask_cvtsepi64_epi32(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsqd256(a.as_i64x4(), src.as_i32x4(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtsepi64_epi32&expand=1851) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm256_maskz_cvtsepi64_epi32(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsqd256(a.as_i64x4(), _mm_setzero_si128().as_i32x4(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsepi64_epi32&expand=1846) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm_cvtsepi64_epi32(a: __m128i) -> __m128i { + transmute(vpmovsqd128( + a.as_i64x2(), + _mm_setzero_si128().as_i32x4(), + 0b11111111, + )) +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi64_epi32&expand=1847) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm_mask_cvtsepi64_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsqd128(a.as_i64x2(), src.as_i32x4(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtsepi64_epi32&expand=1848) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm_maskz_cvtsepi64_epi32(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsqd128(a.as_i64x2(), _mm_setzero_si128().as_i32x4(), k)) +} + /// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtsepi64_epi16&expand=1843) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi64_epi16&expand=1843) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqw))] @@ -7377,7 +13268,7 @@ pub unsafe fn _mm512_cvtsepi64_epi16(a: __m512i) -> __m128i { /// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtsepi64_epi16&expand=1844) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_epi16&expand=1844) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqw))] @@ -7387,7 +13278,7 @@ pub unsafe fn _mm512_mask_cvtsepi64_epi16(src: __m128i, k: __mmask8, a: __m512i) /// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtsepi64_epi16&expand=1845) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi64_epi16&expand=1845) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqw))] @@ -7395,9 +13286,77 @@ pub unsafe fn _mm512_maskz_cvtsepi64_epi16(k: __mmask8, a: __m512i) -> __m128i { transmute(vpmovsqw(a.as_i64x8(), _mm_setzero_si128().as_i16x8(), k)) } +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtsepi64_epi16&expand=1840) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm256_cvtsepi64_epi16(a: __m256i) -> __m128i { + transmute(vpmovsqw256( + a.as_i64x4(), + _mm_setzero_si128().as_i16x8(), + 0b11111111, + )) +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi64_epi16&expand=1841) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm256_mask_cvtsepi64_epi16(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsqw256(a.as_i64x4(), src.as_i16x8(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtsepi64_epi16&expand=1842) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm256_maskz_cvtsepi64_epi16(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsqw256(a.as_i64x4(), _mm_setzero_si128().as_i16x8(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsepi64_epi16&expand=1837) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm_cvtsepi64_epi16(a: __m128i) -> __m128i { + transmute(vpmovsqw128( + a.as_i64x2(), + _mm_setzero_si128().as_i16x8(), + 0b11111111, + )) +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi64_epi16&expand=1838) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm_mask_cvtsepi64_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsqw128(a.as_i64x2(), src.as_i16x8(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtsepi64_epi16&expand=1839) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm_maskz_cvtsepi64_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsqw128(a.as_i64x2(), _mm_setzero_si128().as_i16x8(), k)) +} + /// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtsepi64_epi8&expand=1861) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsepi64_epi8&expand=1861) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqb))] @@ -7411,7 +13370,7 @@ pub unsafe fn _mm512_cvtsepi64_epi8(a: __m512i) -> __m128i { /// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtsepi64_epi8&expand=1862) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_epi8&expand=1862) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqb))] @@ -7421,7 +13380,7 @@ pub unsafe fn _mm512_mask_cvtsepi64_epi8(src: __m128i, k: __mmask8, a: __m512i) /// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtsepi64_epi8&expand=1863) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtsepi64_epi8&expand=1863) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovsqb))] @@ -7429,9 +13388,77 @@ pub unsafe fn _mm512_maskz_cvtsepi64_epi8(k: __mmask8, a: __m512i) -> __m128i { transmute(vpmovsqb(a.as_i64x8(), _mm_setzero_si128().as_i8x16(), k)) } +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtsepi64_epi8&expand=1858) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm256_cvtsepi64_epi8(a: __m256i) -> __m128i { + transmute(vpmovsqb256( + a.as_i64x4(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi64_epi8&expand=1859) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm256_mask_cvtsepi64_epi8(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsqb256(a.as_i64x4(), src.as_i8x16(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtsepi64_epi8&expand=1860) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm256_maskz_cvtsepi64_epi8(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovsqb256(a.as_i64x4(), _mm_setzero_si128().as_i8x16(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsepi64_epi8&expand=1855) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm_cvtsepi64_epi8(a: __m128i) -> __m128i { + transmute(vpmovsqb128( + a.as_i64x2(), + _mm_setzero_si128().as_i8x16(), + 0b11111111, + )) +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi64_epi8&expand=1856) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm_mask_cvtsepi64_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsqb128(a.as_i64x2(), src.as_i8x16(), k)) +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtsepi64_epi8&expand=1857) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm_maskz_cvtsepi64_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovsqb128(a.as_i64x2(), _mm_setzero_si128().as_i8x16(), k)) +} + /// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtusepi32_epi16&expand=2054) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi32_epi16&expand=2054) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusdw))] @@ -7445,7 +13472,7 @@ pub unsafe fn _mm512_cvtusepi32_epi16(a: __m512i) -> __m256i { /// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtusepi32_epi16&expand=2055) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_epi16&expand=2055) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusdw))] @@ -7455,7 +13482,7 @@ pub unsafe fn _mm512_mask_cvtusepi32_epi16(src: __m256i, k: __mmask16, a: __m512 /// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtusepi32_epi16&expand=2056) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi32_epi16&expand=2056) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusdw))] @@ -7467,9 +13494,85 @@ pub unsafe fn _mm512_maskz_cvtusepi32_epi16(k: __mmask16, a: __m512i) -> __m256i )) } +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtusepi32_epi16&expand=2051) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm256_cvtusepi32_epi16(a: __m256i) -> __m128i { + transmute(vpmovusdw256( + a.as_u32x8(), + _mm_setzero_si128().as_u16x8(), + 0b11111111, + )) +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi32_epi16&expand=2052) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm256_mask_cvtusepi32_epi16(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusdw256(a.as_u32x8(), src.as_u16x8(), k)) +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtusepi32_epi16&expand=2053) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm256_maskz_cvtusepi32_epi16(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusdw256( + a.as_u32x8(), + _mm_setzero_si128().as_u16x8(), + k, + )) +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtusepi32_epi16&expand=2048) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm_cvtusepi32_epi16(a: __m128i) -> __m128i { + transmute(vpmovusdw128( + a.as_u32x4(), + _mm_setzero_si128().as_u16x8(), + 0b11111111, + )) +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi32_epi16&expand=2049) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm_mask_cvtusepi32_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusdw128(a.as_u32x4(), src.as_u16x8(), k)) +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtusepi32_epi16&expand=2050) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm_maskz_cvtusepi32_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusdw128( + a.as_u32x4(), + _mm_setzero_si128().as_u16x8(), + k, + )) +} + /// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtusepi32_epi8&expand=2063) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi32_epi8&expand=2063) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusdb))] @@ -7483,7 +13586,7 @@ pub unsafe fn _mm512_cvtusepi32_epi8(a: __m512i) -> __m128i { /// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtusepi32_epi8&expand=2064) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_epi8&expand=2064) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusdb))] @@ -7493,7 +13596,7 @@ pub unsafe fn _mm512_mask_cvtusepi32_epi8(src: __m128i, k: __mmask16, a: __m512i /// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtusepi32_epi8&expand=2065) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi32_epi8&expand=2065) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusdb))] @@ -7501,61 +13604,213 @@ pub unsafe fn _mm512_maskz_cvtusepi32_epi8(k: __mmask16, a: __m512i) -> __m128i transmute(vpmovusdb(a.as_u32x16(), _mm_setzero_si128().as_u8x16(), k)) } -/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst. +/// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtusepi64_epi32&expand=2087) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtusepi32_epi8&expand=2060) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpmovusqd))] -pub unsafe fn _mm512_cvtusepi64_epi32(a: __m512i) -> __m256i { - transmute(vpmovusqd( - a.as_u64x8(), - _mm256_setzero_si256().as_u32x8(), +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm256_cvtusepi32_epi8(a: __m256i) -> __m128i { + transmute(vpmovusdb256( + a.as_u32x8(), + _mm_setzero_si128().as_u8x16(), 0b11111111, )) } -/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtusepi64_epi32&expand=2088) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi32_epi8&expand=2061) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpmovusqd))] -pub unsafe fn _mm512_mask_cvtusepi64_epi32(src: __m256i, k: __mmask8, a: __m512i) -> __m256i { - transmute(vpmovusqd(a.as_u64x8(), src.as_u32x8(), k)) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm256_mask_cvtusepi32_epi8(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusdb256(a.as_u32x8(), src.as_u8x16(), k)) } -/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtusepi64_epi32&expand=2089) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtusepi32_epi8&expand=2062) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpmovusqd))] -pub unsafe fn _mm512_maskz_cvtusepi64_epi32(k: __mmask8, a: __m512i) -> __m256i { - transmute(vpmovusqd( - a.as_u64x8(), - _mm256_setzero_si256().as_u32x8(), +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm256_maskz_cvtusepi32_epi8(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusdb256( + a.as_u32x8(), + _mm_setzero_si128().as_u8x16(), k, )) } -/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst. +/// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtusepi64_epi16&expand=2078) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtusepi32_epi8&expand=2057) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpmovusqw))] -pub unsafe fn _mm512_cvtusepi64_epi16(a: __m512i) -> __m128i { - transmute(vpmovusqw( - a.as_u64x8(), - _mm_setzero_si128().as_u16x8(), +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm_cvtusepi32_epi8(a: __m128i) -> __m128i { + transmute(vpmovusdb128( + a.as_u32x4(), + _mm_setzero_si128().as_u8x16(), 0b11111111, )) } -/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtusepi64_epi16&expand=2079) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi32_epi8&expand=2058) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm_mask_cvtusepi32_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusdb128(a.as_u32x4(), src.as_u8x16(), k)) +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtusepi32_epi8&expand=2059) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm_maskz_cvtusepi32_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusdb128( + a.as_u32x4(), + _mm_setzero_si128().as_u8x16(), + k, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi64_epi32&expand=2087) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm512_cvtusepi64_epi32(a: __m512i) -> __m256i { + transmute(vpmovusqd( + a.as_u64x8(), + _mm256_setzero_si256().as_u32x8(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_epi32&expand=2088) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm512_mask_cvtusepi64_epi32(src: __m256i, k: __mmask8, a: __m512i) -> __m256i { + transmute(vpmovusqd(a.as_u64x8(), src.as_u32x8(), k)) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi64_epi32&expand=2089) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm512_maskz_cvtusepi64_epi32(k: __mmask8, a: __m512i) -> __m256i { + transmute(vpmovusqd( + a.as_u64x8(), + _mm256_setzero_si256().as_u32x8(), + k, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtusepi64_epi32&expand=2084) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm256_cvtusepi64_epi32(a: __m256i) -> __m128i { + transmute(vpmovusqd256( + a.as_u64x4(), + _mm_setzero_si128().as_u32x4(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi64_epi32&expand=2085) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm256_mask_cvtusepi64_epi32(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusqd256(a.as_u64x4(), src.as_u32x4(), k)) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtusepi64_epi32&expand=2086) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm256_maskz_cvtusepi64_epi32(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusqd256( + a.as_u64x4(), + _mm_setzero_si128().as_u32x4(), + k, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtusepi64_epi32&expand=2081) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm_cvtusepi64_epi32(a: __m128i) -> __m128i { + transmute(vpmovusqd128( + a.as_u64x2(), + _mm_setzero_si128().as_u32x4(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi64_epi32&expand=2082) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm_mask_cvtusepi64_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusqd128(a.as_u64x2(), src.as_u32x4(), k)) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 32-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtusepi64_epi32&expand=2083) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm_maskz_cvtusepi64_epi32(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusqd128( + a.as_u64x2(), + _mm_setzero_si128().as_u32x4(), + k, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi64_epi16&expand=2078) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm512_cvtusepi64_epi16(a: __m512i) -> __m128i { + transmute(vpmovusqw( + a.as_u64x8(), + _mm_setzero_si128().as_u16x8(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_epi16&expand=2079) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusqw))] @@ -7565,7 +13820,7 @@ pub unsafe fn _mm512_mask_cvtusepi64_epi16(src: __m128i, k: __mmask8, a: __m512i /// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtusepi64_epi16&expand=2080) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi64_epi16&expand=2080) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusqw))] @@ -7573,9 +13828,85 @@ pub unsafe fn _mm512_maskz_cvtusepi64_epi16(k: __mmask8, a: __m512i) -> __m128i transmute(vpmovusqw(a.as_u64x8(), _mm_setzero_si128().as_u16x8(), k)) } +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtusepi64_epi16&expand=2075) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm256_cvtusepi64_epi16(a: __m256i) -> __m128i { + transmute(vpmovusqw256( + a.as_u64x4(), + _mm_setzero_si128().as_u16x8(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi64_epi16&expand=2076) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm256_mask_cvtusepi64_epi16(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusqw256(a.as_u64x4(), src.as_u16x8(), k)) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtusepi64_epi16&expand=2077) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm256_maskz_cvtusepi64_epi16(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusqw256( + a.as_u64x4(), + _mm_setzero_si128().as_u16x8(), + k, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtusepi64_epi16&expand=2072) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm_cvtusepi64_epi16(a: __m128i) -> __m128i { + transmute(vpmovusqw128( + a.as_u64x2(), + _mm_setzero_si128().as_u16x8(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi64_epi16&expand=2073) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm_mask_cvtusepi64_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusqw128(a.as_u64x2(), src.as_u16x8(), k)) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtusepi64_epi16&expand=2074) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm_maskz_cvtusepi64_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusqw128( + a.as_u64x2(), + _mm_setzero_si128().as_u16x8(), + k, + )) +} + /// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtusepi64_epi8&expand=2096) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtusepi64_epi8&expand=2096) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusqb))] @@ -7589,7 +13920,7 @@ pub unsafe fn _mm512_cvtusepi64_epi8(a: __m512i) -> __m128i { /// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtusepi64_epi8&expand=2097) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_epi8&expand=2097) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusqb))] @@ -7599,7 +13930,7 @@ pub unsafe fn _mm512_mask_cvtusepi64_epi8(src: __m128i, k: __mmask8, a: __m512i) /// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtusepi64_epi8&expand=2098) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtusepi64_epi8&expand=2098) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpmovusqb))] @@ -7607,6 +13938,82 @@ pub unsafe fn _mm512_maskz_cvtusepi64_epi8(k: __mmask8, a: __m512i) -> __m128i { transmute(vpmovusqb(a.as_u64x8(), _mm_setzero_si128().as_u8x16(), k)) } +/// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvtusepi64_epi8&expand=2093) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm256_cvtusepi64_epi8(a: __m256i) -> __m128i { + transmute(vpmovusqb256( + a.as_u64x4(), + _mm_setzero_si128().as_u8x16(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi64_epi8&expand=2094) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm256_mask_cvtusepi64_epi8(src: __m128i, k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusqb256(a.as_u64x4(), src.as_u8x16(), k)) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtusepi64_epi8&expand=2095) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm256_maskz_cvtusepi64_epi8(k: __mmask8, a: __m256i) -> __m128i { + transmute(vpmovusqb256( + a.as_u64x4(), + _mm_setzero_si128().as_u8x16(), + k, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtusepi64_epi8&expand=2090) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm_cvtusepi64_epi8(a: __m128i) -> __m128i { + transmute(vpmovusqb128( + a.as_u64x2(), + _mm_setzero_si128().as_u8x16(), + 0b11111111, + )) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi64_epi8&expand=2091) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm_mask_cvtusepi64_epi8(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusqb128(a.as_u64x2(), src.as_u8x16(), k)) +} + +/// Convert packed unsigned 64-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtusepi64_epi8&expand=2092) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm_maskz_cvtusepi64_epi8(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpmovusqb128( + a.as_u64x2(), + _mm_setzero_si128().as_u8x16(), + k, + )) +} + /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers, and store the results in dst. /// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of: @@ -7616,20 +14023,17 @@ pub unsafe fn _mm512_maskz_cvtusepi64_epi8(k: __mmask8, a: __m512i) -> __m128i { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundps_epi32&expand=1335) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_epi32&expand=1335) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2dq, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundps_epi32(a: __m512, rounding: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2dq( - a.as_f32x16(), - _mm512_setzero_si512().as_i32x16(), - 0b11111111_11111111, - $imm4, - ) + vcvtps2dq(a, zero, 0b11111111_11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7645,7 +14049,7 @@ pub unsafe fn _mm512_cvt_roundps_epi32(a: __m512, rounding: i32) -> __m512i { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundps_epi32&expand=1336) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_epi32&expand=1336) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2dq, rounding = 8))] @@ -7656,9 +14060,11 @@ pub unsafe fn _mm512_mask_cvt_roundps_epi32( a: __m512, rounding: i32, ) -> __m512i { + let a = a.as_f32x16(); + let src = src.as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2dq(a.as_f32x16(), src.as_i32x16(), k, $imm4) + vcvtps2dq(a, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7674,15 +14080,17 @@ pub unsafe fn _mm512_mask_cvt_roundps_epi32( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvt_roundps_epi32&expand=1337) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_epi32&expand=1337) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2dq, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundps_epi32(k: __mmask16, a: __m512, rounding: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2dq(a.as_f32x16(), _mm512_setzero_si512().as_i32x16(), k, $imm4) + vcvtps2dq(a, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7698,20 +14106,17 @@ pub unsafe fn _mm512_maskz_cvt_roundps_epi32(k: __mmask16, a: __m512, rounding: /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundps_epu32&expand=1341) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_epu32&expand=1341) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2udq, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundps_epu32(a: __m512, rounding: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2udq( - a.as_f32x16(), - _mm512_setzero_si512().as_u32x16(), - 0b11111111_11111111, - $imm4, - ) + vcvtps2udq(a, zero, 0b11111111_11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7727,7 +14132,7 @@ pub unsafe fn _mm512_cvt_roundps_epu32(a: __m512, rounding: i32) -> __m512i { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundps_epu32&expand=1342) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_epu32&expand=1342) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2udq, rounding = 8))] @@ -7738,9 +14143,11 @@ pub unsafe fn _mm512_mask_cvt_roundps_epu32( a: __m512, rounding: i32, ) -> __m512i { + let a = a.as_f32x16(); + let src = src.as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2udq(a.as_f32x16(), src.as_u32x16(), k, $imm4) + vcvtps2udq(a, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7756,15 +14163,17 @@ pub unsafe fn _mm512_mask_cvt_roundps_epu32( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=maskz_cvt_roundps_epu32&expand=1343) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_epu32&expand=1343) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2udq, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundps_epu32(k: __mmask16, a: __m512, rounding: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2udq(a.as_f32x16(), _mm512_setzero_si512().as_u32x16(), k, $imm4) + vcvtps2udq(a, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7774,20 +14183,17 @@ pub unsafe fn _mm512_maskz_cvt_roundps_epu32(k: __mmask16, a: __m512, rounding: /// Convert packed single-precision (32-bit) floating-point elements in a to packed double-precision (64-bit) floating-point elements, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=cvt_roundps_pd&expand=1347) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_pd&expand=1347) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundps_pd(a: __m256, sae: i32) -> __m512d { + let a = a.as_f32x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr) => { - vcvtps2pd( - a.as_f32x8(), - _mm512_setzero_pd().as_f64x8(), - 0b11111111, - $imm4, - ) + vcvtps2pd(a, zero, 0b11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -7797,7 +14203,7 @@ pub unsafe fn _mm512_cvt_roundps_pd(a: __m256, sae: i32) -> __m512d { /// Convert packed single-precision (32-bit) floating-point elements in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundps_epi32&expand=1336) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_epi32&expand=1336) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd, sae = 8))] @@ -7808,9 +14214,11 @@ pub unsafe fn _mm512_mask_cvt_roundps_pd( a: __m256, sae: i32, ) -> __m512d { + let a = a.as_f32x8(); + let src = src.as_f64x8(); macro_rules! call { ($imm4:expr) => { - vcvtps2pd(a.as_f32x8(), src.as_f64x8(), k, $imm4) + vcvtps2pd(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -7820,15 +14228,17 @@ pub unsafe fn _mm512_mask_cvt_roundps_pd( /// Convert packed single-precision (32-bit) floating-point elements in a to packed double-precision (64-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvt_roundps_epi32&expand=1337) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_epi32&expand=1337) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2pd, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundps_pd(k: __mmask8, a: __m256, sae: i32) -> __m512d { + let a = a.as_f32x8(); + let zero = _mm512_setzero_pd().as_f64x8(); macro_rules! call { ($imm4:expr) => { - vcvtps2pd(a.as_f32x8(), _mm512_setzero_pd().as_f64x8(), k, $imm4) + vcvtps2pd(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -7844,20 +14254,17 @@ pub unsafe fn _mm512_maskz_cvt_roundps_pd(k: __mmask8, a: __m256, sae: i32) -> _ /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundpd_epi32&expand=1315) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundpd_epi32&expand=1315) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2dq, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundpd_epi32(a: __m512d, rounding: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2dq( - a.as_f64x8(), - _mm256_setzero_si256().as_i32x8(), - 0b11111111, - $imm4, - ) + vcvtpd2dq(a, zero, 0b11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7873,7 +14280,7 @@ pub unsafe fn _mm512_cvt_roundpd_epi32(a: __m512d, rounding: i32) -> __m256i { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundpd_epi32&expand=1316) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundpd_epi32&expand=1316) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2dq, rounding = 8))] @@ -7884,9 +14291,11 @@ pub unsafe fn _mm512_mask_cvt_roundpd_epi32( a: __m512d, rounding: i32, ) -> __m256i { + let a = a.as_f64x8(); + let src = src.as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2dq(a.as_f64x8(), src.as_i32x8(), k, $imm4) + vcvtpd2dq(a, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7902,15 +14311,17 @@ pub unsafe fn _mm512_mask_cvt_roundpd_epi32( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=512_maskz_cvt_roundpd_epi32&expand=1317) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundpd_epi32&expand=1317) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2dq, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundpd_epi32(k: __mmask8, a: __m512d, rounding: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2dq(a.as_f64x8(), _mm256_setzero_si256().as_i32x8(), k, $imm4) + vcvtpd2dq(a, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7926,20 +14337,17 @@ pub unsafe fn _mm512_maskz_cvt_roundpd_epi32(k: __mmask8, a: __m512d, rounding: /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundpd_epu32&expand=1321) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundpd_epu32&expand=1321) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2udq, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundpd_epu32(a: __m512d, rounding: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_u32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2udq( - a.as_f64x8(), - _mm256_setzero_si256().as_u32x8(), - 0b11111111, - $imm4, - ) + vcvtpd2udq(a, zero, 0b11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7955,7 +14363,7 @@ pub unsafe fn _mm512_cvt_roundpd_epu32(a: __m512d, rounding: i32) -> __m256i { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundpd_epu32&expand=1322) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundpd_epu32&expand=1322) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2udq, rounding = 8))] @@ -7966,9 +14374,11 @@ pub unsafe fn _mm512_mask_cvt_roundpd_epu32( a: __m512d, rounding: i32, ) -> __m256i { + let a = a.as_f64x8(); + let src = src.as_u32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2udq(a.as_f64x8(), src.as_u32x8(), k, $imm4) + vcvtpd2udq(a, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -7984,15 +14394,17 @@ pub unsafe fn _mm512_mask_cvt_roundpd_epu32( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=512_maskz_cvt_roundpd_epu32&expand=1323) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundpd_epu32&expand=1323) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2udq, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundpd_epu32(k: __mmask8, a: __m512d, rounding: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_u32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2udq(a.as_f64x8(), _mm256_setzero_si256().as_u32x8(), k, $imm4) + vcvtpd2udq(a, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8008,20 +14420,17 @@ pub unsafe fn _mm512_maskz_cvt_roundpd_epu32(k: __mmask8, a: __m512d, rounding: /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundpd_ps&expand=1327) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundpd_ps&expand=1327) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundpd_ps(a: __m512d, rounding: i32) -> __m256 { + let a = a.as_f64x8(); + let zero = _mm256_setzero_ps().as_f32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2ps( - a.as_f64x8(), - _mm256_setzero_ps().as_f32x8(), - 0b11111111, - $imm4, - ) + vcvtpd2ps(a, zero, 0b11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8037,7 +14446,7 @@ pub unsafe fn _mm512_cvt_roundpd_ps(a: __m512d, rounding: i32) -> __m256 { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundpd_ps&expand=1328) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundpd_ps&expand=1328) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps, rounding = 8))] @@ -8048,9 +14457,11 @@ pub unsafe fn _mm512_mask_cvt_roundpd_ps( a: __m512d, rounding: i32, ) -> __m256 { + let a = a.as_f64x8(); + let src = src.as_f32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2ps(a.as_f64x8(), src.as_f32x8(), k, $imm4) + vcvtpd2ps(a, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8066,15 +14477,17 @@ pub unsafe fn _mm512_mask_cvt_roundpd_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvt_roundpd_ps&expand=1329) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundpd_ps&expand=1329) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtpd2ps, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundpd_ps(k: __mmask8, a: __m512d, rounding: i32) -> __m256 { + let a = a.as_f64x8(); + let zero = _mm256_setzero_ps().as_f32x8(); macro_rules! call { ($imm4:expr) => { - vcvtpd2ps(a.as_f64x8(), _mm256_setzero_ps().as_f32x8(), k, $imm4) + vcvtpd2ps(a, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8090,15 +14503,16 @@ pub unsafe fn _mm512_maskz_cvt_roundpd_ps(k: __mmask8, a: __m512d, rounding: i32 /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundepi32_ps&expand=1294) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundepi32_ps&expand=1294) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2ps, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundepi32_ps(a: __m512i, rounding: i32) -> __m512 { + let a = a.as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvtdq2ps(a.as_i32x16(), $imm4) + vcvtdq2ps(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8114,7 +14528,7 @@ pub unsafe fn _mm512_cvt_roundepi32_ps(a: __m512i, rounding: i32) -> __m512 { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundepi32_ps&expand=1295) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundepi32_ps&expand=1295) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2ps, rounding = 8))] @@ -8125,9 +14539,10 @@ pub unsafe fn _mm512_mask_cvt_roundepi32_ps( a: __m512i, rounding: i32, ) -> __m512 { + let a = a.as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvtdq2ps(a.as_i32x16(), $imm4) + vcvtdq2ps(a, $imm4) }; } let r: f32x16 = constify_imm4_round!(rounding, call); @@ -8143,15 +14558,16 @@ pub unsafe fn _mm512_mask_cvt_roundepi32_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvt_roundepi32_ps&expand=1296) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundepi32_ps&expand=1296) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtdq2ps, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundepi32_ps(k: __mmask16, a: __m512i, rounding: i32) -> __m512 { + let a = a.as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvtdq2ps(a.as_i32x16(), $imm4) + vcvtdq2ps(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8168,15 +14584,16 @@ pub unsafe fn _mm512_maskz_cvt_roundepi32_ps(k: __mmask16, a: __m512i, rounding: /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundepu32_ps&expand=1303) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundepu32_ps&expand=1303) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2ps, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundepu32_ps(a: __m512i, rounding: i32) -> __m512 { + let a = a.as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvtudq2ps(a.as_u32x16(), $imm4) + vcvtudq2ps(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8192,7 +14609,7 @@ pub unsafe fn _mm512_cvt_roundepu32_ps(a: __m512i, rounding: i32) -> __m512 { /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundepu32_ps&expand=1304) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundepu32_ps&expand=1304) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2ps, rounding = 8))] @@ -8203,9 +14620,10 @@ pub unsafe fn _mm512_mask_cvt_roundepu32_ps( a: __m512i, rounding: i32, ) -> __m512 { + let a = a.as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvtudq2ps(a.as_u32x16(), $imm4) + vcvtudq2ps(a, $imm4) }; } let r: f32x16 = constify_imm4_round!(rounding, call); @@ -8221,15 +14639,16 @@ pub unsafe fn _mm512_mask_cvt_roundepu32_ps( /// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvt_roundepu32_ps&expand=1305) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundepu32_ps&expand=1305) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtudq2ps, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundepu32_ps(k: __mmask16, a: __m512i, rounding: i32) -> __m512 { + let a = a.as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvtudq2ps(a.as_u32x16(), $imm4) + vcvtudq2ps(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -8240,20 +14659,17 @@ pub unsafe fn _mm512_maskz_cvt_roundepu32_ps(k: __mmask16, a: __m512i, rounding: /// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundps_ph&expand=1354) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundps_ph&expand=1354) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2ph, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundps_ph(a: __m512, sae: i32) -> __m256i { + let a = a.as_f32x16(); + let zero = _mm256_setzero_si256().as_i16x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2ph( - a.as_f32x16(), - $imm4, - _mm256_setzero_si256().as_i16x16(), - 0b11111111_11111111, - ) + vcvtps2ph(a, $imm4, zero, 0b11111111_11111111) }; } let r = constify_imm4_sae!(sae, call); @@ -8263,7 +14679,7 @@ pub unsafe fn _mm512_cvt_roundps_ph(a: __m512, sae: i32) -> __m256i { /// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundps_ph&expand=1355) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundps_ph&expand=1355) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2ph, sae = 8))] @@ -8274,9 +14690,11 @@ pub unsafe fn _mm512_mask_cvt_roundps_ph( a: __m512, sae: i32, ) -> __m256i { + let a = a.as_f32x16(); + let src = src.as_i16x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2ph(a.as_f32x16(), $imm4, src.as_i16x16(), k) + vcvtps2ph(a, $imm4, src, k) }; } let r = constify_imm4_sae!(sae, call); @@ -8286,38 +14704,142 @@ pub unsafe fn _mm512_mask_cvt_roundps_ph( /// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvt_roundps_ph&expand=1356) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundps_ph&expand=1356) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2ph, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundps_ph(k: __mmask16, a: __m512, sae: i32) -> __m256i { + let a = a.as_f32x16(); + let zero = _mm256_setzero_si256().as_i16x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2ph(a.as_f32x16(), $imm4, _mm256_setzero_si256().as_i16x16(), k) + vcvtps2ph(a, $imm4, zero, k) }; } let r = constify_imm4_sae!(sae, call); transmute(r) } +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of: +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvt_roundps_ph&expand=1352) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_cvt_roundps_ph( + src: __m128i, + k: __mmask8, + a: __m256, + imm8: i32, +) -> __m128i { + let a = a.as_f32x8(); + let src = src.as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph256(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvt_roundps_ph&expand=1353) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_cvt_roundps_ph(k: __mmask8, a: __m256, imm8: i32) -> __m128i { + let a = a.as_f32x8(); + let zero = _mm_setzero_si128().as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph256(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvt_roundps_ph&expand=1350) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_cvt_roundps_ph(src: __m128i, k: __mmask8, a: __m128, imm8: i32) -> __m128i { + let a = a.as_f32x4(); + let src = src.as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph128(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvt_roundps_ph&expand=1351) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_cvt_roundps_ph(k: __mmask8, a: __m128, imm8: i32) -> __m128i { + let a = a.as_f32x4(); + let zero = _mm_setzero_si128().as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph128(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + /// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtps_ph&expand=1778) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtps_ph&expand=1778) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2ph, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvtps_ph(a: __m512, sae: i32) -> __m256i { + let a = a.as_f32x16(); + let zero = _mm256_setzero_si256().as_i16x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2ph( - a.as_f32x16(), - $imm4, - _mm256_setzero_si256().as_i16x16(), - 0b11111111_11111111, - ) + vcvtps2ph(a, $imm4, zero, 0b11111111_11111111) }; } let r = constify_imm4_sae!(sae, call); @@ -8327,15 +14849,17 @@ pub unsafe fn _mm512_cvtps_ph(a: __m512, sae: i32) -> __m256i { /// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtps_ph&expand=1779) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtps_ph&expand=1779) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2ph, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_mask_cvtps_ph(src: __m256i, k: __mmask16, a: __m512, sae: i32) -> __m256i { + let a = a.as_f32x16(); + let src = src.as_i16x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2ph(a.as_f32x16(), $imm4, src.as_i16x16(), k) + vcvtps2ph(a, $imm4, src, k) }; } let r = constify_imm4_sae!(sae, call); @@ -8345,38 +14869,137 @@ pub unsafe fn _mm512_mask_cvtps_ph(src: __m256i, k: __mmask16, a: __m512, sae: i /// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtps_ph&expand=1780) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtps_ph&expand=1780) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtps2ph, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvtps_ph(k: __mmask16, a: __m512, sae: i32) -> __m256i { + let a = a.as_f32x16(); + let zero = _mm256_setzero_si256().as_i16x16(); macro_rules! call { ($imm4:expr) => { - vcvtps2ph(a.as_f32x16(), $imm4, _mm256_setzero_si256().as_i16x16(), k) + vcvtps2ph(a, $imm4, zero, k) }; } let r = constify_imm4_sae!(sae, call); transmute(r) } +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtps_ph&expand=1776) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_cvtps_ph(src: __m128i, k: __mmask8, a: __m256, imm8: i32) -> __m128i { + let a = a.as_f32x8(); + let src = src.as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph256(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtps_ph&expand=1777) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_cvtps_ph(k: __mmask8, a: __m256, imm8: i32) -> __m128i { + let a = a.as_f32x8(); + let zero = _mm_setzero_si128().as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph256(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtps_ph&expand=1773) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_cvtps_ph(src: __m128i, k: __mmask8, a: __m128, imm8: i32) -> __m128i { + let a = a.as_f32x4(); + let src = src.as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph128(a, $imm8, src, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed half-precision (16-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ +/// Rounding is done according to the imm8\[2:0\] parameter, which can be one of:\ +/// _MM_FROUND_TO_NEAREST_INT // round to nearest\ +/// _MM_FROUND_TO_NEG_INF // round down\ +/// _MM_FROUND_TO_POS_INF // round up\ +/// _MM_FROUND_TO_ZERO // truncate\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtps_ph&expand=1774) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtps2ph, imm8 = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_cvtps_ph(k: __mmask8, a: __m128, imm8: i32) -> __m128i { + let a = a.as_f32x4(); + let zero = _mm_setzero_si128().as_i16x8(); + macro_rules! call { + ($imm8:expr) => { + vcvtps2ph128(a, $imm8, zero, k) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + /// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvt_roundph_ps&expand=1332) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvt_roundph_ps&expand=1332) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtph2ps, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvt_roundph_ps(a: __m256i, sae: i32) -> __m512 { + let a = a.as_i16x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr) => { - vcvtph2ps( - a.as_i16x16(), - _mm512_setzero_ps().as_f32x16(), - 0b11111111_11111111, - $imm4, - ) + vcvtph2ps(a, zero, 0b11111111_11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8386,7 +15009,7 @@ pub unsafe fn _mm512_cvt_roundph_ps(a: __m256i, sae: i32) -> __m512 { /// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvt_roundph_ps&expand=1333) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvt_roundph_ps&expand=1333) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtph2ps, sae = 8))] @@ -8397,9 +15020,11 @@ pub unsafe fn _mm512_mask_cvt_roundph_ps( a: __m256i, sae: i32, ) -> __m512 { + let a = a.as_i16x16(); + let src = src.as_f32x16(); macro_rules! call { ($imm4:expr) => { - vcvtph2ps(a.as_i16x16(), src.as_f32x16(), k, $imm4) + vcvtph2ps(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8409,15 +15034,17 @@ pub unsafe fn _mm512_mask_cvt_roundph_ps( /// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvt_roundph_ps&expand=1334) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvt_roundph_ps&expand=1334) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtph2ps, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvt_roundph_ps(k: __mmask16, a: __m256i, sae: i32) -> __m512 { + let a = a.as_i16x16(); + let zero = _mm512_setzero_ps().as_f32x16(); macro_rules! call { ($imm4:expr) => { - vcvtph2ps(a.as_i16x16(), _mm512_setzero_ps().as_f32x16(), k, $imm4) + vcvtph2ps(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8426,7 +15053,7 @@ pub unsafe fn _mm512_maskz_cvt_roundph_ps(k: __mmask16, a: __m256i, sae: i32) -> /// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtph_ps&expand=1723) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtph_ps&expand=1723) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtph2ps))] @@ -8441,7 +15068,7 @@ pub unsafe fn _mm512_cvtph_ps(a: __m256i) -> __m512 { /// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtph_ps&expand=1724) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtph_ps&expand=1724) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtph2ps))] @@ -8456,7 +15083,7 @@ pub unsafe fn _mm512_mask_cvtph_ps(src: __m512, k: __mmask16, a: __m256i) -> __m /// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtph_ps&expand=1725) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtph_ps&expand=1725) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtph2ps))] @@ -8469,23 +15096,66 @@ pub unsafe fn _mm512_maskz_cvtph_ps(k: __mmask16, a: __m256i) -> __m512 { )) } +/// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtph_ps&expand=1721) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtph2ps))] +pub unsafe fn _mm256_mask_cvtph_ps(src: __m256, k: __mmask8, a: __m128i) -> __m256 { + let convert = _mm256_cvtph_ps(a); + transmute(simd_select_bitmask(k, convert.as_f32x8(), src.as_f32x8())) +} + +/// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvtph_ps&expand=1722) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtph2ps))] +pub unsafe fn _mm256_maskz_cvtph_ps(k: __mmask8, a: __m128i) -> __m256 { + let convert = _mm256_cvtph_ps(a); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, convert.as_f32x8(), zero)) +} + +/// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtph_ps&expand=1718) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtph2ps))] +pub unsafe fn _mm_mask_cvtph_ps(src: __m128, k: __mmask8, a: __m128i) -> __m128 { + let convert = _mm_cvtph_ps(a); + transmute(simd_select_bitmask(k, convert.as_f32x4(), src.as_f32x4())) +} + +/// Convert packed half-precision (16-bit) floating-point elements in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvtph_ps&expand=1719) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvtph2ps))] +pub unsafe fn _mm_maskz_cvtph_ps(k: __mmask8, a: __m128i) -> __m128 { + let convert = _mm_cvtph_ps(a); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, convert.as_f32x4(), zero)) +} + /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtt_roundps_epi32&expand=1916) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundps_epi32&expand=1916) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2dq, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvtt_roundps_epi32(a: __m512, sae: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvttps2dq( - a.as_f32x16(), - _mm512_setzero_si512().as_i32x16(), - 0b11111111_11111111, - $imm4, - ) + vcvttps2dq(a, zero, 0b11111111_11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8495,7 +15165,7 @@ pub unsafe fn _mm512_cvtt_roundps_epi32(a: __m512, sae: i32) -> __m512i { /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtt_roundps_epi32&expand=1917) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundps_epi32&expand=1917) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2dq, sae = 8))] @@ -8506,9 +15176,11 @@ pub unsafe fn _mm512_mask_cvtt_roundps_epi32( a: __m512, sae: i32, ) -> __m512i { + let a = a.as_f32x16(); + let src = src.as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvttps2dq(a.as_f32x16(), src.as_i32x16(), k, $imm4) + vcvttps2dq(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8518,15 +15190,17 @@ pub unsafe fn _mm512_mask_cvtt_roundps_epi32( /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtt_roundps_epi32&expand=1918) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundps_epi32&expand=1918) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2dq, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvtt_roundps_epi32(k: __mmask16, a: __m512, sae: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); macro_rules! call { ($imm4:expr) => { - vcvttps2dq(a.as_f32x16(), _mm512_setzero_si512().as_i32x16(), k, $imm4) + vcvttps2dq(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8536,20 +15210,17 @@ pub unsafe fn _mm512_maskz_cvtt_roundps_epi32(k: __mmask16, a: __m512, sae: i32) /// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtt_roundps_epu32&expand=1922) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundps_epu32&expand=1922) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2udq, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvtt_roundps_epu32(a: __m512, sae: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvttps2udq( - a.as_f32x16(), - _mm512_setzero_si512().as_i32x16(), - 0b11111111_11111111, - $imm4, - ) + vcvttps2udq(a, zero, 0b11111111_11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8559,7 +15230,7 @@ pub unsafe fn _mm512_cvtt_roundps_epu32(a: __m512, sae: i32) -> __m512i { /// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtt_roundps_epu32&expand=1923) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundps_epu32&expand=1923) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2udq, sae = 8))] @@ -8570,9 +15241,11 @@ pub unsafe fn _mm512_mask_cvtt_roundps_epu32( a: __m512, sae: i32, ) -> __m512i { + let a = a.as_f32x16(); + let src = src.as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvttps2udq(a.as_f32x16(), src.as_i32x16(), k, $imm4) + vcvttps2udq(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8582,15 +15255,17 @@ pub unsafe fn _mm512_mask_cvtt_roundps_epu32( /// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtt_roundps_epu32&expand=1924) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundps_epu32&expand=1924) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2udq, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvtt_roundps_epu32(k: __mmask16, a: __m512, sae: i32) -> __m512i { + let a = a.as_f32x16(); + let zero = _mm512_setzero_si512().as_u32x16(); macro_rules! call { ($imm4:expr) => { - vcvttps2udq(a.as_f32x16(), _mm512_setzero_si512().as_i32x16(), k, $imm4) + vcvttps2udq(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8600,20 +15275,17 @@ pub unsafe fn _mm512_maskz_cvtt_roundps_epu32(k: __mmask16, a: __m512, sae: i32) /// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtt_roundpd_epi32&expand=1904) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundpd_epi32&expand=1904) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2dq, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvtt_roundpd_epi32(a: __m512d, sae: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvttpd2dq( - a.as_f64x8(), - _mm256_setzero_si256().as_i32x8(), - 0b11111111, - $imm4, - ) + vcvttpd2dq(a, zero, 0b11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8623,7 +15295,7 @@ pub unsafe fn _mm512_cvtt_roundpd_epi32(a: __m512d, sae: i32) -> __m256i { /// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtt_roundpd_epi32&expand=1905) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundpd_epi32&expand=1905) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2dq, sae = 8))] @@ -8634,9 +15306,11 @@ pub unsafe fn _mm512_mask_cvtt_roundpd_epi32( a: __m512d, sae: i32, ) -> __m256i { + let a = a.as_f64x8(); + let src = src.as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvttpd2dq(a.as_f64x8(), src.as_i32x8(), k, $imm4) + vcvttpd2dq(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8646,15 +15320,17 @@ pub unsafe fn _mm512_mask_cvtt_roundpd_epi32( /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtt_roundps_epi32&expand=1918) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundps_epi32&expand=1918) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2dq, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvtt_roundpd_epi32(k: __mmask8, a: __m512d, sae: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvttpd2dq(a.as_f64x8(), _mm256_setzero_si256().as_i32x8(), k, $imm4) + vcvttpd2dq(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8664,20 +15340,17 @@ pub unsafe fn _mm512_maskz_cvtt_roundpd_epi32(k: __mmask8, a: __m512d, sae: i32) /// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvtt_roundpd_epu32&expand=1910) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtt_roundpd_epu32&expand=1910) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2udq, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_cvtt_roundpd_epu32(a: __m512d, sae: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvttpd2udq( - a.as_f64x8(), - _mm256_setzero_si256().as_i32x8(), - 0b11111111, - $imm4, - ) + vcvttpd2udq(a, zero, 0b11111111, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8687,7 +15360,7 @@ pub unsafe fn _mm512_cvtt_roundpd_epu32(a: __m512d, sae: i32) -> __m256i { /// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvtt_roundpd_epu32&expand=1911) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtt_roundpd_epu32&expand=1911) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2udq, sae = 8))] @@ -8698,9 +15371,11 @@ pub unsafe fn _mm512_mask_cvtt_roundpd_epu32( a: __m512d, sae: i32, ) -> __m256i { + let a = a.as_f64x8(); + let src = src.as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvttpd2udq(a.as_f64x8(), src.as_i32x8(), k, $imm4) + vcvttpd2udq(a, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8709,7 +15384,7 @@ pub unsafe fn _mm512_mask_cvtt_roundpd_epu32( /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvttps_epi32&expand=1984) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttps_epi32&expand=1984) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2dq))] @@ -8724,7 +15399,7 @@ pub unsafe fn _mm512_cvttps_epi32(a: __m512) -> __m512i { /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvttps_epi32&expand=1985) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttps_epi32&expand=1985) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2dq))] @@ -8739,7 +15414,7 @@ pub unsafe fn _mm512_mask_cvttps_epi32(src: __m512i, k: __mmask16, a: __m512) -> /// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvttps_epi32&expand=1986) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttps_epi32&expand=1986) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2dq))] @@ -8752,16 +15427,64 @@ pub unsafe fn _mm512_maskz_cvttps_epi32(k: __mmask16, a: __m512) -> __m512i { )) } +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvttps_epi32&expand=1982) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2dq))] +pub unsafe fn _mm256_mask_cvttps_epi32(src: __m256i, k: __mmask8, a: __m256) -> __m256i { + transmute(vcvttps2dq256(a.as_f32x8(), src.as_i32x8(), k)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvttps_epi32&expand=1983) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2dq))] +pub unsafe fn _mm256_maskz_cvttps_epi32(k: __mmask8, a: __m256) -> __m256i { + transmute(vcvttps2dq256( + a.as_f32x8(), + _mm256_setzero_si256().as_i32x8(), + k, + )) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvttps_epi32&expand=1979) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2dq))] +pub unsafe fn _mm_mask_cvttps_epi32(src: __m128i, k: __mmask8, a: __m128) -> __m128i { + transmute(vcvttps2dq128(a.as_f32x4(), src.as_i32x4(), k)) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvttps_epi32&expand=1980) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2dq))] +pub unsafe fn _mm_maskz_cvttps_epi32(k: __mmask8, a: __m128) -> __m128i { + transmute(vcvttps2dq128( + a.as_f32x4(), + _mm_setzero_si128().as_i32x4(), + k, + )) +} + /// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvttps_epu32&expand=2002) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttps_epu32&expand=2002) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2udq))] pub unsafe fn _mm512_cvttps_epu32(a: __m512) -> __m512i { transmute(vcvttps2udq( a.as_f32x16(), - _mm512_setzero_si512().as_i32x16(), + _mm512_setzero_si512().as_u32x16(), 0b11111111_11111111, _MM_FROUND_CUR_DIRECTION, )) @@ -8769,14 +15492,14 @@ pub unsafe fn _mm512_cvttps_epu32(a: __m512) -> __m512i { /// Convert packed double-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvttps_epu32&expand=2003) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttps_epu32&expand=2003) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2udq))] pub unsafe fn _mm512_mask_cvttps_epu32(src: __m512i, k: __mmask16, a: __m512) -> __m512i { transmute(vcvttps2udq( a.as_f32x16(), - src.as_i32x16(), + src.as_u32x16(), k, _MM_FROUND_CUR_DIRECTION, )) @@ -8784,31 +15507,109 @@ pub unsafe fn _mm512_mask_cvttps_epu32(src: __m512i, k: __mmask16, a: __m512) -> /// Convert packed double-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvttps_epu32&expand=2004) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttps_epu32&expand=2004) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttps2udq))] pub unsafe fn _mm512_maskz_cvttps_epu32(k: __mmask16, a: __m512) -> __m512i { transmute(vcvttps2udq( a.as_f32x16(), - _mm512_setzero_si512().as_i32x16(), + _mm512_setzero_si512().as_u32x16(), k, _MM_FROUND_CUR_DIRECTION, )) } +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvttps_epu32&expand=1999) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2udq))] +pub unsafe fn _mm256_cvttps_epu32(a: __m256) -> __m256i { + transmute(vcvttps2udq256( + a.as_f32x8(), + _mm256_setzero_si256().as_u32x8(), + 0b11111111, + )) +} + +/// Convert packed double-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvttps_epu32&expand=2000) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2udq))] +pub unsafe fn _mm256_mask_cvttps_epu32(src: __m256i, k: __mmask8, a: __m256) -> __m256i { + transmute(vcvttps2udq256(a.as_f32x8(), src.as_u32x8(), k)) +} + +/// Convert packed double-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvttps_epu32&expand=2001) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2udq))] +pub unsafe fn _mm256_maskz_cvttps_epu32(k: __mmask8, a: __m256) -> __m256i { + transmute(vcvttps2udq256( + a.as_f32x8(), + _mm256_setzero_si256().as_u32x8(), + k, + )) +} + +/// Convert packed single-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttps_epu32&expand=1996) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2udq))] +pub unsafe fn _mm_cvttps_epu32(a: __m128) -> __m128i { + transmute(vcvttps2udq128( + a.as_f32x4(), + _mm_setzero_si128().as_u32x4(), + 0b11111111, + )) +} + +/// Convert packed double-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvttps_epu32&expand=1997) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2udq))] +pub unsafe fn _mm_mask_cvttps_epu32(src: __m128i, k: __mmask8, a: __m128) -> __m128i { + transmute(vcvttps2udq128(a.as_f32x4(), src.as_u32x4(), k)) +} + +/// Convert packed double-precision (32-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvttps_epu32&expand=1998) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttps2udq))] +pub unsafe fn _mm_maskz_cvttps_epu32(k: __mmask8, a: __m128) -> __m128i { + transmute(vcvttps2udq128( + a.as_f32x4(), + _mm_setzero_si128().as_u32x4(), + k, + )) +} + /// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvtt_roundpd_epu32&expand=1912) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvtt_roundpd_epu32&expand=1912) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2udq, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_cvtt_roundpd_epu32(k: __mmask8, a: __m512d, sae: i32) -> __m256i { + let a = a.as_f64x8(); + let zero = _mm256_setzero_si256().as_i32x8(); macro_rules! call { ($imm4:expr) => { - vcvttpd2udq(a.as_f64x8(), _mm256_setzero_si256().as_i32x8(), k, $imm4) + vcvttpd2udq(a, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -8817,7 +15618,7 @@ pub unsafe fn _mm512_maskz_cvtt_roundpd_epu32(k: __mmask8, a: __m512d, sae: i32) /// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvttpd_epi32&expand=1947) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttpd_epi32&expand=1947) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2dq))] @@ -8832,7 +15633,7 @@ pub unsafe fn _mm512_cvttpd_epi32(a: __m512d) -> __m256i { /// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvttpd_epi32&expand=1948) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttpd_epi32&expand=1948) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2dq))] @@ -8847,7 +15648,7 @@ pub unsafe fn _mm512_mask_cvttpd_epi32(src: __m256i, k: __mmask8, a: __m512d) -> /// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvttpd_epi32&expand=1949) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttpd_epi32&expand=1949) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2dq))] @@ -8860,9 +15661,57 @@ pub unsafe fn _mm512_maskz_cvttpd_epi32(k: __mmask8, a: __m512d) -> __m256i { )) } +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvttpd_epi32&expand=1945) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2dq))] +pub unsafe fn _mm256_mask_cvttpd_epi32(src: __m128i, k: __mmask8, a: __m256d) -> __m128i { + transmute(vcvttpd2dq256(a.as_f64x4(), src.as_i32x4(), k)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvttpd_epi32&expand=1946) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2dq))] +pub unsafe fn _mm256_maskz_cvttpd_epi32(k: __mmask8, a: __m256d) -> __m128i { + transmute(vcvttpd2dq256( + a.as_f64x4(), + _mm_setzero_si128().as_i32x4(), + k, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvttpd_epi32&expand=1942) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2dq))] +pub unsafe fn _mm_mask_cvttpd_epi32(src: __m128i, k: __mmask8, a: __m128d) -> __m128i { + transmute(vcvttpd2dq128(a.as_f64x2(), src.as_i32x4(), k)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvttpd_epi32&expand=1943) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2dq))] +pub unsafe fn _mm_maskz_cvttpd_epi32(k: __mmask8, a: __m128d) -> __m128i { + transmute(vcvttpd2dq128( + a.as_f64x2(), + _mm_setzero_si128().as_i32x4(), + k, + )) +} + /// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cvttpd_epu32&expand=1965) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvttpd_epu32&expand=1965) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2udq))] @@ -8877,7 +15726,7 @@ pub unsafe fn _mm512_cvttpd_epu32(a: __m512d) -> __m256i { /// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cvttpd_epu32&expand=1966) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvttpd_epu32&expand=1966) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2udq))] @@ -8892,7 +15741,7 @@ pub unsafe fn _mm512_mask_cvttpd_epu32(src: __m256i, k: __mmask8, a: __m512d) -> /// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_cvttpd_epu32&expand=1967) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_cvttpd_epu32&expand=1967) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvttpd2udq))] @@ -8905,9 +15754,85 @@ pub unsafe fn _mm512_maskz_cvttpd_epu32(k: __mmask8, a: __m512d) -> __m256i { )) } +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cvttpd_epu32&expand=1962) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2udq))] +pub unsafe fn _mm256_cvttpd_epu32(a: __m256d) -> __m128i { + transmute(vcvttpd2udq256( + a.as_f64x4(), + _mm_setzero_si128().as_i32x4(), + 0b11111111, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvttpd_epu32&expand=1963) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2udq))] +pub unsafe fn _mm256_mask_cvttpd_epu32(src: __m128i, k: __mmask8, a: __m256d) -> __m128i { + transmute(vcvttpd2udq256(a.as_f64x4(), src.as_i32x4(), k)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_cvttpd_epu32&expand=1964) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2udq))] +pub unsafe fn _mm256_maskz_cvttpd_epu32(k: __mmask8, a: __m256d) -> __m128i { + transmute(vcvttpd2udq256( + a.as_f64x4(), + _mm_setzero_si128().as_i32x4(), + k, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttpd_epu32&expand=1959) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2udq))] +pub unsafe fn _mm_cvttpd_epu32(a: __m128d) -> __m128i { + transmute(vcvttpd2udq128( + a.as_f64x2(), + _mm_setzero_si128().as_i32x4(), + 0b11111111, + )) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvttpd_epu32&expand=1960) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2udq))] +pub unsafe fn _mm_mask_cvttpd_epu32(src: __m128i, k: __mmask8, a: __m128d) -> __m128i { + transmute(vcvttpd2udq128(a.as_f64x2(), src.as_i32x4(), k)) +} + +/// Convert packed double-precision (64-bit) floating-point elements in a to packed unsigned 32-bit integers with truncation, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_cvttpd_epu32&expand=1961) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcvttpd2udq))] +pub unsafe fn _mm_maskz_cvttpd_epu32(k: __mmask8, a: __m128d) -> __m128i { + transmute(vcvttpd2udq128( + a.as_f64x2(), + _mm_setzero_si128().as_i32x4(), + k, + )) +} + /// Returns vector of type `__m512d` with all elements set to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990&text=_mm512_setzero_pd) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_pd&expand=5018) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vxorps))] @@ -8918,7 +15843,7 @@ pub unsafe fn _mm512_setzero_pd() -> __m512d { /// Returns vector of type `__m512d` with all elements set to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990&text=_mm512_setzero_pd) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_ps&expand=5021) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vxorps))] @@ -8929,7 +15854,7 @@ pub unsafe fn _mm512_setzero_ps() -> __m512 { /// Return vector of type __m512 with all elements set to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_setzero&expand=5014) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero&expand=5014) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vxorps))] @@ -8940,7 +15865,7 @@ pub unsafe fn _mm512_setzero() -> __m512 { /// Returns vector of type `__m512i` with all elements set to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990&text=_mm512_setzero_si512) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_si512&expand=5024) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vxorps))] @@ -8951,7 +15876,7 @@ pub unsafe fn _mm512_setzero_si512() -> __m512i { /// Return vector of type __m512i with all elements set to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_setzero_epi32&expand=5015) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_epi32&expand=5015) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vxorps))] @@ -8962,6 +15887,8 @@ pub unsafe fn _mm512_setzero_epi32() -> __m512i { /// Sets packed 32-bit integers in `dst` with the supplied values in reverse /// order. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_epi32&expand=4991) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_setr_epi32( @@ -8990,7 +15917,7 @@ pub unsafe fn _mm512_setr_epi32( /// Set packed 8-bit integers in dst with the supplied values. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set_epi8&expand=4915) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi8&expand=4915) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set_epi8( @@ -9070,7 +15997,7 @@ pub unsafe fn _mm512_set_epi8( /// Set packed 16-bit integers in dst with the supplied values. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set_epi16&expand=4905) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi16&expand=4905) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set_epi16( @@ -9116,7 +16043,7 @@ pub unsafe fn _mm512_set_epi16( /// Set packed 32-bit integers in dst with the repeated 4 element sequence. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set4_epi32&expand=4982) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_epi32&expand=4982) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set4_epi32(d: i32, c: i32, b: i32, a: i32) -> __m512i { @@ -9125,7 +16052,7 @@ pub unsafe fn _mm512_set4_epi32(d: i32, c: i32, b: i32, a: i32) -> __m512i { /// Set packed single-precision (32-bit) floating-point elements in dst with the repeated 4 element sequence. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set4_ps&expand=4985) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_ps&expand=4985) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set4_ps(d: f32, c: f32, b: f32, a: f32) -> __m512 { @@ -9134,7 +16061,7 @@ pub unsafe fn _mm512_set4_ps(d: f32, c: f32, b: f32, a: f32) -> __m512 { /// Set packed double-precision (64-bit) floating-point elements in dst with the repeated 4 element sequence. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set4_pd&expand=4984) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_pd&expand=4984) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set4_pd(d: f64, c: f64, b: f64, a: f64) -> __m512d { @@ -9143,7 +16070,7 @@ pub unsafe fn _mm512_set4_pd(d: f64, c: f64, b: f64, a: f64) -> __m512d { /// Set packed 32-bit integers in dst with the repeated 4 element sequence in reverse order. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_setr4_epi32&expand=5009) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_epi32&expand=5009) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_setr4_epi32(d: i32, c: i32, b: i32, a: i32) -> __m512i { @@ -9152,7 +16079,7 @@ pub unsafe fn _mm512_setr4_epi32(d: i32, c: i32, b: i32, a: i32) -> __m512i { /// Set packed single-precision (32-bit) floating-point elements in dst with the repeated 4 element sequence in reverse order. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_setr4_ps&expand=5012) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_ps&expand=5012) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_setr4_ps(d: f32, c: f32, b: f32, a: f32) -> __m512 { @@ -9161,7 +16088,7 @@ pub unsafe fn _mm512_setr4_ps(d: f32, c: f32, b: f32, a: f32) -> __m512 { /// Set packed double-precision (64-bit) floating-point elements in dst with the repeated 4 element sequence in reverse order. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_setr4_pd&expand=5011) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_pd&expand=5011) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_setr4_pd(d: f64, c: f64, b: f64, a: f64) -> __m512d { @@ -9170,7 +16097,7 @@ pub unsafe fn _mm512_setr4_pd(d: f64, c: f64, b: f64, a: f64) -> __m512d { /// Set packed 64-bit integers in dst with the supplied values. /// -/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set_epi64&expand=4910) +/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi64&expand=4910) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set_epi64( @@ -9188,7 +16115,7 @@ pub unsafe fn _mm512_set_epi64( /// Set packed 64-bit integers in dst with the supplied values in reverse order. /// -/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_setr_epi64&expand=4993) +/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_epi64&expand=4993) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_setr_epi64( @@ -9207,7 +16134,7 @@ pub unsafe fn _mm512_setr_epi64( /// Gather double-precision (64-bit) floating-point elements from memory using 32-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32gather_pd&expand=3002) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_pd&expand=3002) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherdpd, scale = 1))] @@ -9228,7 +16155,7 @@ pub unsafe fn _mm512_i32gather_pd(offsets: __m256i, slice: *const u8, scale: i32 /// Gather double-precision (64-bit) floating-point elements from memory using 32-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32gather_pd&expand=3003) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_pd&expand=3003) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherdpd, scale = 1))] @@ -9254,7 +16181,7 @@ pub unsafe fn _mm512_mask_i32gather_pd( /// Gather double-precision (64-bit) floating-point elements from memory using 64-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64gather_pd&expand=3092) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_pd&expand=3092) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherqpd, scale = 1))] @@ -9275,7 +16202,7 @@ pub unsafe fn _mm512_i64gather_pd(offsets: __m512i, slice: *const u8, scale: i32 /// Gather double-precision (64-bit) floating-point elements from memory using 64-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64gather_pd&expand=3093) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_pd&expand=3093) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherqpd, scale = 1))] @@ -9301,7 +16228,7 @@ pub unsafe fn _mm512_mask_i64gather_pd( /// Gather single-precision (32-bit) floating-point elements from memory using 64-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64gather_ps&expand=3100) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_ps&expand=3100) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherqps, scale = 1))] @@ -9322,7 +16249,7 @@ pub unsafe fn _mm512_i64gather_ps(offsets: __m512i, slice: *const u8, scale: i32 /// Gather single-precision (32-bit) floating-point elements from memory using 64-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64gather_ps&expand=3101) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_ps&expand=3101) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherqps, scale = 1))] @@ -9348,7 +16275,7 @@ pub unsafe fn _mm512_mask_i64gather_ps( /// Gather single-precision (32-bit) floating-point elements from memory using 32-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32gather_ps&expand=3010) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_ps&expand=3010) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherdps, scale = 1))] @@ -9369,7 +16296,7 @@ pub unsafe fn _mm512_i32gather_ps(offsets: __m512i, slice: *const u8, scale: i32 /// Gather single-precision (32-bit) floating-point elements from memory using 32-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32gather_ps&expand=3011) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_ps&expand=3011) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vgatherdps, scale = 1))] @@ -9395,7 +16322,7 @@ pub unsafe fn _mm512_mask_i32gather_ps( /// Gather 32-bit integers from memory using 32-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32gather_epi32&expand=2986) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_epi32&expand=2986) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherdd, scale = 1))] @@ -9416,7 +16343,7 @@ pub unsafe fn _mm512_i32gather_epi32(offsets: __m512i, slice: *const u8, scale: /// Gather 32-bit integers from memory using 32-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32gather_epi32&expand=2987) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_epi32&expand=2987) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherdd, scale = 1))] @@ -9443,7 +16370,7 @@ pub unsafe fn _mm512_mask_i32gather_epi32( /// Gather 64-bit integers from memory using 32-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32gather_epi64&expand=2994) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32gather_epi64&expand=2994) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherdq, scale = 1))] @@ -9464,7 +16391,7 @@ pub unsafe fn _mm512_i32gather_epi64(offsets: __m256i, slice: *const u8, scale: /// Gather 64-bit integers from memory using 32-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32gather_epi64&expand=2995) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32gather_epi64&expand=2995) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherdq, scale = 1))] @@ -9491,7 +16418,7 @@ pub unsafe fn _mm512_mask_i32gather_epi64( /// Gather 64-bit integers from memory using 64-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64gather_epi64&expand=3084) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_epi64&expand=3084) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherqq, scale = 1))] @@ -9512,7 +16439,7 @@ pub unsafe fn _mm512_i64gather_epi64(offsets: __m512i, slice: *const u8, scale: /// Gather 64-bit integers from memory using 64-bit indices. 64-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64gather_epi64&expand=3085) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_epi64&expand=3085) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherqq, scale = 1))] @@ -9539,7 +16466,7 @@ pub unsafe fn _mm512_mask_i64gather_epi64( /// Gather 32-bit integers from memory using 64-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64gather_epi32&expand=3074) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64gather_epi32&expand=3074) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherqd, scale = 1))] @@ -9560,7 +16487,7 @@ pub unsafe fn _mm512_i64gather_epi32(offsets: __m512i, slice: *const u8, scale: /// Gather 32-bit integers from memory using 64-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst using writemask k (elements are copied from src when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64gather_epi32&expand=3075) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64gather_epi32&expand=3075) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpgatherqd, scale = 1))] @@ -9587,7 +16514,7 @@ pub unsafe fn _mm512_mask_i64gather_epi32( /// Scatter double-precision (64-bit) floating-point elements from a into memory using 32-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32scatter_pd&expand=3044) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_pd&expand=3044) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterdpd, scale = 1))] @@ -9607,7 +16534,7 @@ pub unsafe fn _mm512_i32scatter_pd(slice: *mut u8, offsets: __m256i, src: __m512 /// Scatter double-precision (64-bit) floating-point elements from a into memory using 32-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32scatter_pd&expand=3045) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_pd&expand=3045) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterdpd, scale = 1))] @@ -9632,7 +16559,7 @@ pub unsafe fn _mm512_mask_i32scatter_pd( /// Scatter double-precision (64-bit) floating-point elements from a into memory using 64-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64scatter_pd&expand=3122) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_pd&expand=3122) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterqpd, scale = 1))] @@ -9652,7 +16579,7 @@ pub unsafe fn _mm512_i64scatter_pd(slice: *mut u8, offsets: __m512i, src: __m512 /// Scatter double-precision (64-bit) floating-point elements from a into memory using 64-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64scatter_pd&expand=3123) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_pd&expand=3123) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterqpd, scale = 1))] @@ -9677,7 +16604,7 @@ pub unsafe fn _mm512_mask_i64scatter_pd( /// Scatter single-precision (32-bit) floating-point elements from a into memory using 32-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32scatter_ps&expand=3050) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_ps&expand=3050) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterdps, scale = 1))] @@ -9697,7 +16624,7 @@ pub unsafe fn _mm512_i32scatter_ps(slice: *mut u8, offsets: __m512i, src: __m512 /// Scatter single-precision (32-bit) floating-point elements from a into memory using 32-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32scatter_ps&expand=3051) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_ps&expand=3051) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterdps, scale = 1))] @@ -9722,7 +16649,7 @@ pub unsafe fn _mm512_mask_i32scatter_ps( /// Scatter single-precision (32-bit) floating-point elements from a into memory using 64-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64scatter_ps&expand=3128) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_ps&expand=3128) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterqps, scale = 1))] @@ -9742,7 +16669,7 @@ pub unsafe fn _mm512_i64scatter_ps(slice: *mut u8, offsets: __m512i, src: __m256 /// Scatter single-precision (32-bit) floating-point elements from a into memory using 64-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64scatter_ps&expand=3129) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_ps&expand=3129) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscatterqps, scale = 1))] @@ -9767,7 +16694,7 @@ pub unsafe fn _mm512_mask_i64scatter_ps( /// Scatter 64-bit integers from a into memory using 32-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32scatter_epi64&expand=3038) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_epi64&expand=3038) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterdq, scale = 1))] @@ -9787,7 +16714,7 @@ pub unsafe fn _mm512_i32scatter_epi64(slice: *mut u8, offsets: __m256i, src: __m /// Scatter 64-bit integers from a into memory using 32-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32scatter_epi64&expand=3039) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_epi64&expand=3039) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterdq, scale = 1))] @@ -9813,7 +16740,7 @@ pub unsafe fn _mm512_mask_i32scatter_epi64( /// Scatter 64-bit integers from a into memory using 64-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64scatter_epi64&expand=3116) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_epi64&expand=3116) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterqq, scale = 1))] @@ -9833,7 +16760,7 @@ pub unsafe fn _mm512_i64scatter_epi64(slice: *mut u8, offsets: __m512i, src: __m /// Scatter 64-bit integers from a into memory using 64-bit indices. 64-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64scatter_epi64&expand=3117) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_epi64&expand=3117) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterqq, scale = 1))] @@ -9859,7 +16786,7 @@ pub unsafe fn _mm512_mask_i64scatter_epi64( /// Scatter 32-bit integers from a into memory using 32-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i32scatter_epi32&expand=3032) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i32scatter_epi32&expand=3032) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterdd, scale = 1))] @@ -9879,7 +16806,7 @@ pub unsafe fn _mm512_i32scatter_epi32(slice: *mut u8, offsets: __m512i, src: __m /// Scatter 32-bit integers from a into memory using 32-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i32scatter_epi32&expand=3033) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i32scatter_epi32&expand=3033) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterdd, scale = 1))] @@ -9905,7 +16832,7 @@ pub unsafe fn _mm512_mask_i32scatter_epi32( /// Scatter 32-bit integers from a into memory using 64-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_i64scatter_epi32&expand=3108) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_i64scatter_epi32&expand=3108) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterqd, scale = 1))] @@ -9925,7 +16852,7 @@ pub unsafe fn _mm512_i64scatter_epi32(slice: *mut u8, offsets: __m512i, src: __m /// Scatter 32-bit integers from a into memory using 64-bit indices. 32-bit elements are stored at addresses starting at base_addr and offset by each 64-bit element in vindex (each index is scaled by the factor in scale) subject to mask k (elements are not stored when the corresponding mask bit is not set). scale should be 1, 2, 4 or 8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_i64scatter_epi32&expand=3109) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_i64scatter_epi32&expand=3109) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpscatterqd, scale = 1))] @@ -9951,7 +16878,7 @@ pub unsafe fn _mm512_mask_i64scatter_epi32( /// Contiguously store the active 32-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_compress_epi32&expand=1198) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_epi32&expand=1198) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpcompressd))] @@ -9961,7 +16888,7 @@ pub unsafe fn _mm512_mask_compress_epi32(src: __m512i, k: __mmask16, a: __m512i) /// Contiguously store the active 32-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_compress_epi32&expand=1199) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_epi32&expand=1199) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpcompressd))] @@ -9973,9 +16900,57 @@ pub unsafe fn _mm512_maskz_compress_epi32(k: __mmask16, a: __m512i) -> __m512i { )) } +/// Contiguously store the active 32-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_compress_epi32&expand=1196) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressd))] +pub unsafe fn _mm256_mask_compress_epi32(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + transmute(vpcompressd256(a.as_i32x8(), src.as_i32x8(), k)) +} + +/// Contiguously store the active 32-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_compress_epi32&expand=1197) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressd))] +pub unsafe fn _mm256_maskz_compress_epi32(k: __mmask8, a: __m256i) -> __m256i { + transmute(vpcompressd256( + a.as_i32x8(), + _mm256_setzero_si256().as_i32x8(), + k, + )) +} + +/// Contiguously store the active 32-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_compress_epi32&expand=1194) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressd))] +pub unsafe fn _mm_mask_compress_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpcompressd128(a.as_i32x4(), src.as_i32x4(), k)) +} + +/// Contiguously store the active 32-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_compress_epi32&expand=1195) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressd))] +pub unsafe fn _mm_maskz_compress_epi32(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpcompressd128( + a.as_i32x4(), + _mm_setzero_si128().as_i32x4(), + k, + )) +} + /// Contiguously store the active 64-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_compress_epi64&expand=1204) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_epi64&expand=1204) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpcompressq))] @@ -9985,7 +16960,7 @@ pub unsafe fn _mm512_mask_compress_epi64(src: __m512i, k: __mmask8, a: __m512i) /// Contiguously store the active 64-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_compress_epi64&expand=1205) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_epi64&expand=1205) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpcompressq))] @@ -9997,9 +16972,57 @@ pub unsafe fn _mm512_maskz_compress_epi64(k: __mmask8, a: __m512i) -> __m512i { )) } +/// Contiguously store the active 64-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_compress_epi64&expand=1202) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressq))] +pub unsafe fn _mm256_mask_compress_epi64(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + transmute(vpcompressq256(a.as_i64x4(), src.as_i64x4(), k)) +} + +/// Contiguously store the active 64-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_compress_epi64&expand=1203) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressq))] +pub unsafe fn _mm256_maskz_compress_epi64(k: __mmask8, a: __m256i) -> __m256i { + transmute(vpcompressq256( + a.as_i64x4(), + _mm256_setzero_si256().as_i64x4(), + k, + )) +} + +/// Contiguously store the active 64-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_compress_epi64&expand=1200) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressq))] +pub unsafe fn _mm_mask_compress_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpcompressq128(a.as_i64x2(), src.as_i64x2(), k)) +} + +/// Contiguously store the active 64-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_compress_epi64&expand=1201) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressq))] +pub unsafe fn _mm_maskz_compress_epi64(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpcompressq128( + a.as_i64x2(), + _mm_setzero_si128().as_i64x2(), + k, + )) +} + /// Contiguously store the active single-precision (32-bit) floating-point elements in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_compress_ps&expand=1222) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_ps&expand=1222) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcompressps))] @@ -10009,7 +17032,7 @@ pub unsafe fn _mm512_mask_compress_ps(src: __m512, k: __mmask16, a: __m512) -> _ /// Contiguously store the active single-precision (32-bit) floating-point elements in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_compress_ps&expand=1223) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_ps&expand=1223) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcompressps))] @@ -10021,9 +17044,53 @@ pub unsafe fn _mm512_maskz_compress_ps(k: __mmask16, a: __m512) -> __m512 { )) } +/// Contiguously store the active single-precision (32-bit) floating-point elements in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_compress_ps&expand=1220) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompressps))] +pub unsafe fn _mm256_mask_compress_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + transmute(vcompressps256(a.as_f32x8(), src.as_f32x8(), k)) +} + +/// Contiguously store the active single-precision (32-bit) floating-point elements in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_compress_ps&expand=1221) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompressps))] +pub unsafe fn _mm256_maskz_compress_ps(k: __mmask8, a: __m256) -> __m256 { + transmute(vcompressps256( + a.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + k, + )) +} + +/// Contiguously store the active single-precision (32-bit) floating-point elements in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_compress_ps&expand=1218) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompressps))] +pub unsafe fn _mm_mask_compress_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + transmute(vcompressps128(a.as_f32x4(), src.as_f32x4(), k)) +} + +/// Contiguously store the active single-precision (32-bit) floating-point elements in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_compress_ps&expand=1219) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompressps))] +pub unsafe fn _mm_maskz_compress_ps(k: __mmask8, a: __m128) -> __m128 { + transmute(vcompressps128(a.as_f32x4(), _mm_setzero_ps().as_f32x4(), k)) +} + /// Contiguously store the active double-precision (64-bit) floating-point elements in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_compress_pd&expand=1216) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_pd&expand=1216) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcompresspd))] @@ -10033,7 +17100,7 @@ pub unsafe fn _mm512_mask_compress_pd(src: __m512d, k: __mmask8, a: __m512d) -> /// Contiguously store the active double-precision (64-bit) floating-point elements in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_compress_pd&expand=1217) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_pd&expand=1217) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcompresspd))] @@ -10041,9 +17108,53 @@ pub unsafe fn _mm512_maskz_compress_pd(k: __mmask8, a: __m512d) -> __m512d { transmute(vcompresspd(a.as_f64x8(), _mm512_setzero_pd().as_f64x8(), k)) } +/// Contiguously store the active double-precision (64-bit) floating-point elements in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_compress_pd&expand=1214) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompresspd))] +pub unsafe fn _mm256_mask_compress_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + transmute(vcompresspd256(a.as_f64x4(), src.as_f64x4(), k)) +} + +/// Contiguously store the active double-precision (64-bit) floating-point elements in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_compress_pd&expand=1215) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompresspd))] +pub unsafe fn _mm256_maskz_compress_pd(k: __mmask8, a: __m256d) -> __m256d { + transmute(vcompresspd256( + a.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + k, + )) +} + +/// Contiguously store the active double-precision (64-bit) floating-point elements in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_compress_pd&expand=1212) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompresspd))] +pub unsafe fn _mm_mask_compress_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + transmute(vcompresspd128(a.as_f64x2(), src.as_f64x2(), k)) +} + +/// Contiguously store the active double-precision (64-bit) floating-point elements in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_compress_pd&expand=1213) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vcompresspd))] +pub unsafe fn _mm_maskz_compress_pd(k: __mmask8, a: __m128d) -> __m128d { + transmute(vcompresspd128(a.as_f64x2(), _mm_setzero_pd().as_f64x2(), k)) +} + /// Load contiguous active 32-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_expand_epi32&expand=2316) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_epi32&expand=2316) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpexpandd))] @@ -10053,7 +17164,7 @@ pub unsafe fn _mm512_mask_expand_epi32(src: __m512i, k: __mmask16, a: __m512i) - /// Load contiguous active 32-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_expand_epi32&expand=2317) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_epi32&expand=2317) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpexpandd))] @@ -10065,9 +17176,57 @@ pub unsafe fn _mm512_maskz_expand_epi32(k: __mmask16, a: __m512i) -> __m512i { )) } +/// Load contiguous active 32-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_expand_epi32&expand=2314) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandd))] +pub unsafe fn _mm256_mask_expand_epi32(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + transmute(vpexpandd256(a.as_i32x8(), src.as_i32x8(), k)) +} + +/// Load contiguous active 32-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_expand_epi32&expand=2315) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandd))] +pub unsafe fn _mm256_maskz_expand_epi32(k: __mmask8, a: __m256i) -> __m256i { + transmute(vpexpandd256( + a.as_i32x8(), + _mm256_setzero_si256().as_i32x8(), + k, + )) +} + +/// Load contiguous active 32-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_expand_epi32&expand=2312) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandd))] +pub unsafe fn _mm_mask_expand_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpexpandd128(a.as_i32x4(), src.as_i32x4(), k)) +} + +/// Load contiguous active 32-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_expand_epi32&expand=2313) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandd))] +pub unsafe fn _mm_maskz_expand_epi32(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpexpandd128( + a.as_i32x4(), + _mm_setzero_si128().as_i32x4(), + k, + )) +} + /// Load contiguous active 64-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_expand_epi64&expand=2322) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_epi64&expand=2322) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpexpandq))] @@ -10077,7 +17236,7 @@ pub unsafe fn _mm512_mask_expand_epi64(src: __m512i, k: __mmask8, a: __m512i) -> /// Load contiguous active 64-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_expand_epi64&expand=2323) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_epi64&expand=2323) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpexpandq))] @@ -10089,9 +17248,57 @@ pub unsafe fn _mm512_maskz_expand_epi64(k: __mmask8, a: __m512i) -> __m512i { )) } +/// Load contiguous active 64-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_expand_epi64&expand=2320) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandq))] +pub unsafe fn _mm256_mask_expand_epi64(src: __m256i, k: __mmask8, a: __m256i) -> __m256i { + transmute(vpexpandq256(a.as_i64x4(), src.as_i64x4(), k)) +} + +/// Load contiguous active 64-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_expand_epi64&expand=2321) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandq))] +pub unsafe fn _mm256_maskz_expand_epi64(k: __mmask8, a: __m256i) -> __m256i { + transmute(vpexpandq256( + a.as_i64x4(), + _mm256_setzero_si256().as_i64x4(), + k, + )) +} + +/// Load contiguous active 64-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_expand_epi64&expand=2318) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandq))] +pub unsafe fn _mm_mask_expand_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpexpandq128(a.as_i64x2(), src.as_i64x2(), k)) +} + +/// Load contiguous active 64-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_expand_epi64&expand=2319) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandq))] +pub unsafe fn _mm_maskz_expand_epi64(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpexpandq128( + a.as_i64x2(), + _mm_setzero_si128().as_i64x2(), + k, + )) +} + /// Load contiguous active single-precision (32-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_expand_ps&expand=2340) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_ps&expand=2340) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vexpandps))] @@ -10101,7 +17308,7 @@ pub unsafe fn _mm512_mask_expand_ps(src: __m512, k: __mmask16, a: __m512) -> __m /// Load contiguous active single-precision (32-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_expand_ps&expand=2341) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_ps&expand=2341) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vexpandps))] @@ -10109,9 +17316,53 @@ pub unsafe fn _mm512_maskz_expand_ps(k: __mmask16, a: __m512) -> __m512 { transmute(vexpandps(a.as_f32x16(), _mm512_setzero_ps().as_f32x16(), k)) } +/// Load contiguous active single-precision (32-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_expand_ps&expand=2338) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandps))] +pub unsafe fn _mm256_mask_expand_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + transmute(vexpandps256(a.as_f32x8(), src.as_f32x8(), k)) +} + +/// Load contiguous active single-precision (32-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_expand_ps&expand=2339) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandps))] +pub unsafe fn _mm256_maskz_expand_ps(k: __mmask8, a: __m256) -> __m256 { + transmute(vexpandps256( + a.as_f32x8(), + _mm256_setzero_ps().as_f32x8(), + k, + )) +} + +/// Load contiguous active single-precision (32-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_expand_ps&expand=2336) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandps))] +pub unsafe fn _mm_mask_expand_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + transmute(vexpandps128(a.as_f32x4(), src.as_f32x4(), k)) +} + +/// Load contiguous active single-precision (32-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_expand_ps&expand=2337) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandps))] +pub unsafe fn _mm_maskz_expand_ps(k: __mmask8, a: __m128) -> __m128 { + transmute(vexpandps128(a.as_f32x4(), _mm_setzero_ps().as_f32x4(), k)) +} + /// Load contiguous active double-precision (64-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_expand_pd&expand=2334) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_pd&expand=2334) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vexpandpd))] @@ -10121,7 +17372,7 @@ pub unsafe fn _mm512_mask_expand_pd(src: __m512d, k: __mmask8, a: __m512d) -> __ /// Load contiguous active double-precision (64-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_expand_pd&expand=2335) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_pd&expand=2335) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vexpandpd))] @@ -10129,9 +17380,53 @@ pub unsafe fn _mm512_maskz_expand_pd(k: __mmask8, a: __m512d) -> __m512d { transmute(vexpandpd(a.as_f64x8(), _mm512_setzero_pd().as_f64x8(), k)) } +/// Load contiguous active double-precision (64-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_expand_pd&expand=2332) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandpd))] +pub unsafe fn _mm256_mask_expand_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + transmute(vexpandpd256(a.as_f64x4(), src.as_f64x4(), k)) +} + +/// Load contiguous active double-precision (64-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_expand_pd&expand=2333) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandpd))] +pub unsafe fn _mm256_maskz_expand_pd(k: __mmask8, a: __m256d) -> __m256d { + transmute(vexpandpd256( + a.as_f64x4(), + _mm256_setzero_pd().as_f64x4(), + k, + )) +} + +/// Load contiguous active double-precision (64-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_expand_pd&expand=2330) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandpd))] +pub unsafe fn _mm_mask_expand_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + transmute(vexpandpd128(a.as_f64x2(), src.as_f64x2(), k)) +} + +/// Load contiguous active double-precision (64-bit) floating-point elements from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_expand_pd&expand=2331) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vexpandpd))] +pub unsafe fn _mm_maskz_expand_pd(k: __mmask8, a: __m128d) -> __m128d { + transmute(vexpandpd128(a.as_f64x2(), _mm_setzero_pd().as_f64x2(), k)) +} + /// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rol_epi32&expand=4685) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rol_epi32&expand=4685) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprold, imm8 = 1))] @@ -10149,7 +17444,7 @@ pub unsafe fn _mm512_rol_epi32(a: __m512i, imm8: i32) -> __m512i { /// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rol_epi32&expand=4683) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rol_epi32&expand=4683) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprold, imm8 = 1))] @@ -10167,7 +17462,7 @@ pub unsafe fn _mm512_mask_rol_epi32(src: __m512i, k: __mmask16, a: __m512i, imm8 /// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rol_epi32&expand=4684) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rol_epi32&expand=4684) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprold, imm8 = 1))] @@ -10184,9 +17479,119 @@ pub unsafe fn _mm512_maskz_rol_epi32(k: __mmask16, a: __m512i, imm8: i32) -> __m transmute(simd_select_bitmask(k, rol, zero)) } +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rol_epi32&expand=4682) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_rol_epi32(a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vprold256(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rol_epi32&expand=4680) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_rol_epi32(src: __m256i, k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vprold256(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, rol, src.as_i32x8())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rol_epi32&expand=4681) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_rol_epi32(k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vprold256(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, rol, zero)) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rol_epi32&expand=4679) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_rol_epi32(a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vprold128(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rol_epi32&expand=4677) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_rol_epi32(src: __m128i, k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vprold128(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, rol, src.as_i32x4())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rol_epi32&expand=4678) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_rol_epi32(k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vprold128(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, rol, zero)) +} + /// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_ror_epi32&expand=4721) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ror_epi32&expand=4721) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprold, imm8 = 1))] @@ -10204,7 +17609,7 @@ pub unsafe fn _mm512_ror_epi32(a: __m512i, imm8: i32) -> __m512i { /// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_ror_epi32&expand=4719) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ror_epi32&expand=4719) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprold, imm8 = 123))] @@ -10222,7 +17627,7 @@ pub unsafe fn _mm512_mask_ror_epi32(src: __m512i, k: __mmask16, a: __m512i, imm8 /// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_ror_epi32&expand=4720) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ror_epi32&expand=4720) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprold, imm8 = 123))] @@ -10239,9 +17644,119 @@ pub unsafe fn _mm512_maskz_ror_epi32(k: __mmask16, a: __m512i, imm8: i32) -> __m transmute(simd_select_bitmask(k, ror, zero)) } +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_ror_epi32&expand=4718) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_ror_epi32(a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vprord256(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_ror_epi32&expand=4716) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 123))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_ror_epi32(src: __m256i, k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vprord256(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ror, src.as_i32x8())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_ror_epi32&expand=4717) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 123))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_ror_epi32(k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i32x8(); + macro_rules! call { + ($imm8:expr) => { + vprord256(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, ror, zero)) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ror_epi32&expand=4715) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_ror_epi32(a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vprord128(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_ror_epi32&expand=4713) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 123))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_ror_epi32(src: __m128i, k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vprord128(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ror, src.as_i32x4())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_ror_epi32&expand=4714) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprold, imm8 = 123))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_ror_epi32(k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i32x4(); + macro_rules! call { + ($imm8:expr) => { + vprord128(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, ror, zero)) +} + /// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rol_epi64&expand=4694) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rol_epi64&expand=4694) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] @@ -10259,7 +17774,7 @@ pub unsafe fn _mm512_rol_epi64(a: __m512i, imm8: i32) -> __m512i { /// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rol_epi64&expand=4692) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rol_epi64&expand=4692) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] @@ -10277,7 +17792,7 @@ pub unsafe fn _mm512_mask_rol_epi64(src: __m512i, k: __mmask8, a: __m512i, imm8: /// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rol_epi64&expand=4693) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rol_epi64&expand=4693) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] @@ -10294,9 +17809,119 @@ pub unsafe fn _mm512_maskz_rol_epi64(k: __mmask8, a: __m512i, imm8: i32) -> __m5 transmute(simd_select_bitmask(k, rol, zero)) } +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rol_epi64&expand=4691) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_rol_epi64(a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vprolq256(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rol_epi64&expand=4689) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_rol_epi64(src: __m256i, k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vprolq256(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, rol, src.as_i64x4())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rol_epi64&expand=4690) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_rol_epi64(k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vprolq256(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, rol, zero)) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rol_epi64&expand=4688) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_rol_epi64(a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vprolq128(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rol_epi64&expand=4686) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_rol_epi64(src: __m128i, k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vprolq128(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, rol, src.as_i64x2())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rol_epi64&expand=4687) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_rol_epi64(k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vprolq128(a, $imm8) + }; + } + let rol = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, rol, zero)) +} + /// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_ror_epi64&expand=4730) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_ror_epi64&expand=4730) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] @@ -10314,7 +17939,7 @@ pub unsafe fn _mm512_ror_epi64(a: __m512i, imm8: i32) -> __m512i { /// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_ror_epi64&expand=4728) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_ror_epi64&expand=4728) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] @@ -10332,7 +17957,7 @@ pub unsafe fn _mm512_mask_ror_epi64(src: __m512i, k: __mmask8, a: __m512i, imm8: /// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_ror_epi64&expand=4729) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_ror_epi64&expand=4729) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] @@ -10349,9 +17974,119 @@ pub unsafe fn _mm512_maskz_ror_epi64(k: __mmask8, a: __m512i, imm8: i32) -> __m5 transmute(simd_select_bitmask(k, ror, zero)) } +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_ror_epi64&expand=4727) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_ror_epi64(a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vprorq256(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_ror_epi64&expand=4725) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_ror_epi64(src: __m256i, k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vprorq256(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ror, src.as_i64x4())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_ror_epi64&expand=4726) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_ror_epi64(k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vprorq256(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, ror, zero)) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ror_epi64&expand=4724) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_ror_epi64(a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vprorq128(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_ror_epi64&expand=4722) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_ror_epi64(src: __m128i, k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vprorq128(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, ror, src.as_i64x2())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_ror_epi64&expand=4723) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolq, imm8 = 15))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_ror_epi64(k: __mmask8, a: __m128i, imm8: i32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vprorq128(a, $imm8) + }; + } + let ror = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, ror, zero)) +} + /// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_slli_epi32&expand=5310) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_slli_epi32&expand=5310) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpslld, imm8 = 5))] @@ -10369,7 +18104,7 @@ pub unsafe fn _mm512_slli_epi32(a: __m512i, imm8: u32) -> __m512i { /// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_slli_epi32&expand=5308) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_slli_epi32&expand=5308) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpslld, imm8 = 5))] @@ -10387,7 +18122,7 @@ pub unsafe fn _mm512_mask_slli_epi32(src: __m512i, k: __mmask16, a: __m512i, imm /// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_slli_epi32&expand=5309) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_slli_epi32&expand=5309) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpslld, imm8 = 5))] @@ -10404,9 +18139,79 @@ pub unsafe fn _mm512_maskz_slli_epi32(k: __mmask16, a: __m512i, imm8: u32) -> __ transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_slli_epi32&expand=5305) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_slli_epi32(src: __m256i, k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_slli_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i32x8(), src.as_i32x8())) +} + +/// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_slli_epi32&expand=5306) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_slli_epi32(k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_slli_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf.as_i32x8(), zero)) +} + +/// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_slli_epi32&expand=5302) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_slli_epi32(src: __m128i, k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_slli_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i32x4(), src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_slli_epi32&expand=5303) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_slli_epi32(k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_slli_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf.as_i32x4(), zero)) +} + /// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srli_epi32&expand=5522) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srli_epi32&expand=5522) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrld, imm8 = 1))] @@ -10424,7 +18229,7 @@ pub unsafe fn _mm512_srli_epi32(a: __m512i, imm8: u32) -> __m512i { /// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srli_epi32&expand=5520) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srli_epi32&expand=5520) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrld, imm8 = 1))] @@ -10442,7 +18247,7 @@ pub unsafe fn _mm512_mask_srli_epi32(src: __m512i, k: __mmask16, a: __m512i, imm /// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srli_epi32&expand=5521) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srli_epi32&expand=5521) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrld, imm8 = 1))] @@ -10459,54 +18264,124 @@ pub unsafe fn _mm512_maskz_srli_epi32(k: __mmask16, a: __m512i, imm8: u32) -> __ transmute(simd_select_bitmask(k, shf, zero)) } -/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst. +/// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_slli_epi64&expand=5319) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srli_epi32&expand=5517) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] -#[rustc_args_required_const(1)] -pub unsafe fn _mm512_slli_epi64(a: __m512i, imm8: u32) -> __m512i { - let a = a.as_i64x8(); +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_srli_epi32(src: __m256i, k: __mmask8, a: __m256i, imm8: u32) -> __m256i { macro_rules! call { ($imm8:expr) => { - vpslliq(a, $imm8) + _mm256_srli_epi32(a, $imm8) }; } - let r = constify_imm8_sae!(imm8, call); - transmute(r) + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i32x8(), src.as_i32x8())) } -/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_slli_epi64&expand=5317) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srli_epi32&expand=5518) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] -#[rustc_args_required_const(3)] -pub unsafe fn _mm512_mask_slli_epi64(src: __m512i, k: __mmask8, a: __m512i, imm8: u32) -> __m512i { - let a = a.as_i64x8(); +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_srli_epi32(k: __mmask8, a: __m256i, imm8: u32) -> __m256i { macro_rules! call { ($imm8:expr) => { - vpslliq(a, $imm8) + _mm256_srli_epi32(a, $imm8) }; } let shf = constify_imm8_sae!(imm8, call); - transmute(simd_select_bitmask(k, shf, src.as_i64x8())) + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf.as_i32x8(), zero)) } -/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_slli_epi64&expand=5318) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srli_epi32&expand=5514) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] -#[rustc_args_required_const(2)] -pub unsafe fn _mm512_maskz_slli_epi64(k: __mmask8, a: __m512i, imm8: u32) -> __m512i { - let a = a.as_i64x8(); +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_srli_epi32(src: __m128i, k: __mmask8, a: __m128i, imm8: u32) -> __m128i { macro_rules! call { ($imm8:expr) => { - vpslliq(a, $imm8) + _mm_srli_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i32x4(), src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srli_epi32&expand=5515) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_srli_epi32(k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_srli_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf.as_i32x4(), zero)) +} + +/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_slli_epi64&expand=5319) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm512_slli_epi64(a: __m512i, imm8: u32) -> __m512i { + let a = a.as_i64x8(); + macro_rules! call { + ($imm8:expr) => { + vpslliq(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_slli_epi64&expand=5317) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_mask_slli_epi64(src: __m512i, k: __mmask8, a: __m512i, imm8: u32) -> __m512i { + let a = a.as_i64x8(); + macro_rules! call { + ($imm8:expr) => { + vpslliq(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf, src.as_i64x8())) +} + +/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_slli_epi64&expand=5318) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_maskz_slli_epi64(k: __mmask8, a: __m512i, imm8: u32) -> __m512i { + let a = a.as_i64x8(); + macro_rules! call { + ($imm8:expr) => { + vpslliq(a, $imm8) }; } let shf = constify_imm8_sae!(imm8, call); @@ -10514,9 +18389,79 @@ pub unsafe fn _mm512_maskz_slli_epi64(k: __mmask8, a: __m512i, imm8: u32) -> __m transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_slli_epi64&expand=5314) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_slli_epi64(src: __m256i, k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_slli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i64x4(), src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_slli_epi64&expand=5315) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_slli_epi64(k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_slli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf.as_i64x4(), zero)) +} + +/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_slli_epi64&expand=5311) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_slli_epi64(src: __m128i, k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_slli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i64x2(), src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_slli_epi64&expand=5312) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_slli_epi64(k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_slli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf.as_i64x2(), zero)) +} + /// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srli_epi64&expand=5531) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srli_epi64&expand=5531) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlq, imm8 = 1))] @@ -10534,7 +18479,7 @@ pub unsafe fn _mm512_srli_epi64(a: __m512i, imm8: u32) -> __m512i { /// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srli_epi64&expand=5529) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srli_epi64&expand=5529) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlq, imm8 = 1))] @@ -10552,7 +18497,7 @@ pub unsafe fn _mm512_mask_srli_epi64(src: __m512i, k: __mmask8, a: __m512i, imm8 /// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srli_epi64&expand=5530) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srli_epi64&expand=5530) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlq, imm8 = 1))] @@ -10569,9 +18514,79 @@ pub unsafe fn _mm512_maskz_srli_epi64(k: __mmask8, a: __m512i, imm8: u32) -> __m transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srli_epi64&expand=5526) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_srli_epi64(src: __m256i, k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_srli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i64x4(), src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srli_epi64&expand=5527) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_srli_epi64(k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_srli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf.as_i64x4(), zero)) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srli_epi64&expand=5523) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_srli_epi64(src: __m128i, k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_srli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i64x2(), src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srli_epi64&expand=5524) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_srli_epi64(k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_srli_epi64(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf.as_i64x2(), zero)) +} + /// Shift packed 32-bit integers in a left by count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sll_epi32&expand=5280) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sll_epi32&expand=5280) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpslld))] @@ -10581,7 +18596,7 @@ pub unsafe fn _mm512_sll_epi32(a: __m512i, count: __m128i) -> __m512i { /// Shift packed 32-bit integers in a left by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sll_epi32&expand=5278) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sll_epi32&expand=5278) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpslld))] @@ -10597,7 +18612,7 @@ pub unsafe fn _mm512_mask_sll_epi32( /// Shift packed 32-bit integers in a left by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sll_epi32&expand=5279) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sll_epi32&expand=5279) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpslld))] @@ -10607,9 +18622,60 @@ pub unsafe fn _mm512_maskz_sll_epi32(k: __mmask16, a: __m512i, count: __m128i) - transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 32-bit integers in a left by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sll_epi32&expand=5275) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld))] +pub unsafe fn _mm256_mask_sll_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m128i, +) -> __m256i { + let shf = _mm256_sll_epi32(a, count).as_i32x8(); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) +} + +/// Shift packed 32-bit integers in a left by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sll_epi32&expand=5276) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld))] +pub unsafe fn _mm256_maskz_sll_epi32(k: __mmask8, a: __m256i, count: __m128i) -> __m256i { + let shf = _mm256_sll_epi32(a, count).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 32-bit integers in a left by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sll_epi32&expand=5272) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld))] +pub unsafe fn _mm_mask_sll_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sll_epi32(a, count).as_i32x4(); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a left by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sll_epi32&expand=5273) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpslld))] +pub unsafe fn _mm_maskz_sll_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sll_epi32(a, count).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 32-bit integers in a right by count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srl_epi32&expand=5492) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srl_epi32&expand=5492) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrld))] @@ -10619,7 +18685,7 @@ pub unsafe fn _mm512_srl_epi32(a: __m512i, count: __m128i) -> __m512i { /// Shift packed 32-bit integers in a right by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srl_epi32&expand=5490) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srl_epi32&expand=5490) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrld))] @@ -10635,7 +18701,7 @@ pub unsafe fn _mm512_mask_srl_epi32( /// Shift packed 32-bit integers in a right by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srl_epi32&expand=5491) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srl_epi32&expand=5491) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrld))] @@ -10645,9 +18711,60 @@ pub unsafe fn _mm512_maskz_srl_epi32(k: __mmask16, a: __m512i, count: __m128i) - transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 32-bit integers in a right by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srl_epi32&expand=5487) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld))] +pub unsafe fn _mm256_mask_srl_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m128i, +) -> __m256i { + let shf = _mm256_srl_epi32(a, count).as_i32x8(); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) +} + +/// Shift packed 32-bit integers in a right by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srl_epi32&expand=5488) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld))] +pub unsafe fn _mm256_maskz_srl_epi32(k: __mmask8, a: __m256i, count: __m128i) -> __m256i { + let shf = _mm256_srl_epi32(a, count).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 32-bit integers in a right by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srl_epi32&expand=5484) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld))] +pub unsafe fn _mm_mask_srl_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srl_epi32(a, count).as_i32x4(); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a right by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srl_epi32&expand=5485) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrld))] +pub unsafe fn _mm_maskz_srl_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srl_epi32(a, count).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sll_epi64&expand=5289) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sll_epi64&expand=5289) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllq))] @@ -10657,7 +18774,7 @@ pub unsafe fn _mm512_sll_epi64(a: __m512i, count: __m128i) -> __m512i { /// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sll_epi64&expand=5287) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sll_epi64&expand=5287) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllq))] @@ -10673,7 +18790,7 @@ pub unsafe fn _mm512_mask_sll_epi64( /// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sll_epi64&expand=5288) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sll_epi64&expand=5288) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllq))] @@ -10683,9 +18800,60 @@ pub unsafe fn _mm512_maskz_sll_epi64(k: __mmask8, a: __m512i, count: __m128i) -> transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sll_epi64&expand=5284) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq))] +pub unsafe fn _mm256_mask_sll_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m128i, +) -> __m256i { + let shf = _mm256_sll_epi64(a, count).as_i64x4(); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sll_epi64&expand=5285) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq))] +pub unsafe fn _mm256_maskz_sll_epi64(k: __mmask8, a: __m256i, count: __m128i) -> __m256i { + let shf = _mm256_sll_epi64(a, count).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sll_epi64&expand=5281) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq))] +pub unsafe fn _mm_mask_sll_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sll_epi64(a, count).as_i64x2(); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sll_epi64&expand=5282) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllq))] +pub unsafe fn _mm_maskz_sll_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sll_epi64(a, count).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 64-bit integers in a right by count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srl_epi64&expand=5501) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srl_epi64&expand=5501) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlq))] @@ -10695,7 +18863,7 @@ pub unsafe fn _mm512_srl_epi64(a: __m512i, count: __m128i) -> __m512i { /// Shift packed 64-bit integers in a right by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srl_epi64&expand=5499) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srl_epi64&expand=5499) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlq))] @@ -10709,9 +18877,9 @@ pub unsafe fn _mm512_mask_srl_epi64( transmute(simd_select_bitmask(k, shf, src.as_i64x8())) } -/// Shift packed 64-bit integers in a left by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Shift packed 64-bit integers in a right by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sll_epi64&expand=5288) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srl_epi64&expand=5500) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlq))] @@ -10721,9 +18889,60 @@ pub unsafe fn _mm512_maskz_srl_epi64(k: __mmask8, a: __m512i, count: __m128i) -> transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a right by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srl_epi64&expand=5496) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq))] +pub unsafe fn _mm256_mask_srl_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m128i, +) -> __m256i { + let shf = _mm256_srl_epi64(a, count).as_i64x4(); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a right by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srl_epi64&expand=5497) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq))] +pub unsafe fn _mm256_maskz_srl_epi64(k: __mmask8, a: __m256i, count: __m128i) -> __m256i { + let shf = _mm256_srl_epi64(a, count).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a right by count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srl_epi64&expand=5493) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq))] +pub unsafe fn _mm_mask_srl_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srl_epi64(a, count).as_i64x2(); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srl_epi64&expand=5494) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlq))] +pub unsafe fn _mm_maskz_srl_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srl_epi64(a, count).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 32-bit integers in a right by count while shifting in sign bits, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sra_epi32&expand=5407) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sra_epi32&expand=5407) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrad))] @@ -10733,7 +18952,7 @@ pub unsafe fn _mm512_sra_epi32(a: __m512i, count: __m128i) -> __m512i { /// Shift packed 32-bit integers in a right by count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sra_epi32&expand=5405) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sra_epi32&expand=5405) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrad))] @@ -10749,7 +18968,7 @@ pub unsafe fn _mm512_mask_sra_epi32( /// Shift packed 32-bit integers in a right by count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sra_epi32&expand=5406) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sra_epi32&expand=5406) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrad))] @@ -10759,9 +18978,60 @@ pub unsafe fn _mm512_maskz_sra_epi32(k: __mmask16, a: __m512i, count: __m128i) - transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 32-bit integers in a right by count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sra_epi32&expand=5402) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad))] +pub unsafe fn _mm256_mask_sra_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m128i, +) -> __m256i { + let shf = _mm256_sra_epi32(a, count).as_i32x8(); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) +} + +/// Shift packed 32-bit integers in a right by count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sra_epi32&expand=5403) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad))] +pub unsafe fn _mm256_maskz_sra_epi32(k: __mmask8, a: __m256i, count: __m128i) -> __m256i { + let shf = _mm256_sra_epi32(a, count).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 32-bit integers in a right by count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sra_epi32&expand=5399) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad))] +pub unsafe fn _mm_mask_sra_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sra_epi32(a, count).as_i32x4(); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a right by count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sra_epi32&expand=5400) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad))] +pub unsafe fn _mm_maskz_sra_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sra_epi32(a, count).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sra_epi64&expand=5416) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sra_epi64&expand=5416) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsraq))] @@ -10771,7 +19041,7 @@ pub unsafe fn _mm512_sra_epi64(a: __m512i, count: __m128i) -> __m512i { /// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sra_epi64&expand=5414) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sra_epi64&expand=5414) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsraq))] @@ -10787,7 +19057,7 @@ pub unsafe fn _mm512_mask_sra_epi64( /// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sra_epi64&expand=5415) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sra_epi64&expand=5415) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsraq))] @@ -10797,9 +19067,80 @@ pub unsafe fn _mm512_maskz_sra_epi64(k: __mmask8, a: __m512i, count: __m128i) -> transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_sra_epi64&expand=5413) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq))] +pub unsafe fn _mm256_sra_epi64(a: __m256i, count: __m128i) -> __m256i { + transmute(vpsraq256(a.as_i64x4(), count.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sra_epi64&expand=5411) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq))] +pub unsafe fn _mm256_mask_sra_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m128i, +) -> __m256i { + let shf = _mm256_sra_epi64(a, count).as_i64x4(); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sra_epi64&expand=5412) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq))] +pub unsafe fn _mm256_maskz_sra_epi64(k: __mmask8, a: __m256i, count: __m128i) -> __m256i { + let shf = _mm256_sra_epi64(a, count).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sra_epi64&expand=5410) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq))] +pub unsafe fn _mm_sra_epi64(a: __m128i, count: __m128i) -> __m128i { + transmute(vpsraq128(a.as_i64x2(), count.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sra_epi64&expand=5408) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq))] +pub unsafe fn _mm_mask_sra_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sra_epi64(a, count).as_i64x2(); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sra_epi64&expand=5409) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq))] +pub unsafe fn _mm_maskz_sra_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sra_epi64(a, count).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srai_epi32&expand=5436) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srai_epi32&expand=5436) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrad, imm8 = 1))] @@ -10817,7 +19158,7 @@ pub unsafe fn _mm512_srai_epi32(a: __m512i, imm8: u32) -> __m512i { /// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srai_epi32&expand=5434) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srai_epi32&expand=5434) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrad, imm8 = 1))] @@ -10835,7 +19176,7 @@ pub unsafe fn _mm512_mask_srai_epi32(src: __m512i, k: __mmask16, a: __m512i, imm /// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srai_epi32&expand=5435) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srai_epi32&expand=5435) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrad, imm8 = 1))] @@ -10852,9 +19193,79 @@ pub unsafe fn _mm512_maskz_srai_epi32(k: __mmask16, a: __m512i, imm8: u32) -> __ transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srai_epi32&expand=5431) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_srai_epi32(src: __m256i, k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_srai_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i32x8(), src.as_i32x8())) +} + +/// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srai_epi32&expand=5432) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_srai_epi32(k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_srai_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf.as_i32x8(), zero)) +} + +/// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srai_epi32&expand=5428) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_srai_epi32(src: __m128i, k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_srai_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf.as_i32x4(), src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srai_epi32&expand=5429) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrad, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_srai_epi32(k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_srai_epi32(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf.as_i32x4(), zero)) +} + /// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srai_epi64&expand=5445) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srai_epi64&expand=5445) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] @@ -10872,7 +19283,7 @@ pub unsafe fn _mm512_srai_epi64(a: __m512i, imm8: u32) -> __m512i { /// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srai_epi64&expand=5443) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srai_epi64&expand=5443) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] @@ -10890,7 +19301,7 @@ pub unsafe fn _mm512_mask_srai_epi64(src: __m512i, k: __mmask8, a: __m512i, imm8 /// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srai_epi64&expand=5444) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srai_epi64&expand=5444) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] @@ -10907,9 +19318,119 @@ pub unsafe fn _mm512_maskz_srai_epi64(k: __mmask8, a: __m512i, imm8: u32) -> __m transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_srai_epi64&expand=5442) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_srai_epi64(a: __m256i, imm8: u32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vpsraiq256(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srai_epi64&expand=5440) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_srai_epi64(src: __m256i, k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vpsraiq256(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srai_epi64&expand=5441) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_srai_epi64(k: __mmask8, a: __m256i, imm8: u32) -> __m256i { + let a = a.as_i64x4(); + macro_rules! call { + ($imm8:expr) => { + vpsraiq256(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi64&expand=5439) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_srai_epi64(a: __m128i, imm8: u32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vpsraiq128(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(r) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srai_epi64&expand=5437) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_srai_epi64(src: __m128i, k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vpsraiq128(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by imm8 while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srai_epi64&expand=5438) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsraq, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_srai_epi64(k: __mmask8, a: __m128i, imm8: u32) -> __m128i { + let a = a.as_i64x2(); + macro_rules! call { + ($imm8:expr) => { + vpsraiq128(a, $imm8) + }; + } + let shf = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srav_epi32&expand=5465) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srav_epi32&expand=5465) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsravd))] @@ -10919,7 +19440,7 @@ pub unsafe fn _mm512_srav_epi32(a: __m512i, count: __m512i) -> __m512i { /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srav_epi32&expand=5463) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srav_epi32&expand=5463) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsravd))] @@ -10935,7 +19456,7 @@ pub unsafe fn _mm512_mask_srav_epi32( /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srav_epi32&expand=5464) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srav_epi32&expand=5464) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsravd))] @@ -10945,25 +19466,81 @@ pub unsafe fn _mm512_maskz_srav_epi32(k: __mmask16, a: __m512i, count: __m512i) transmute(simd_select_bitmask(k, shf, zero)) } -/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst. +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srav_epi64&expand=5474) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srav_epi32&expand=5460) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpsravq))] -pub unsafe fn _mm512_srav_epi64(a: __m512i, count: __m512i) -> __m512i { - transmute(vpsravq(a.as_i64x8(), count.as_i64x8())) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravd))] +pub unsafe fn _mm256_mask_srav_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m256i, +) -> __m256i { + let shf = _mm256_srav_epi32(a, count).as_i32x8(); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) } -/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srav_epi64&expand=5472) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srav_epi32&expand=5461) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpsravq))] -pub unsafe fn _mm512_mask_srav_epi64( - src: __m512i, - k: __mmask8, +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravd))] +pub unsafe fn _mm256_maskz_srav_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { + let shf = _mm256_srav_epi32(a, count).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srav_epi32&expand=5457) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravd))] +pub unsafe fn _mm_mask_srav_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + count: __m128i, +) -> __m128i { + let shf = _mm_srav_epi32(a, count).as_i32x4(); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srav_epi32&expand=5458) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravd))] +pub unsafe fn _mm_maskz_srav_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srav_epi32(a, count).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srav_epi64&expand=5474) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm512_srav_epi64(a: __m512i, count: __m512i) -> __m512i { + transmute(vpsravq(a.as_i64x8(), count.as_i64x8())) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srav_epi64&expand=5472) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm512_mask_srav_epi64( + src: __m512i, + k: __mmask8, a: __m512i, count: __m512i, ) -> __m512i { @@ -10973,7 +19550,7 @@ pub unsafe fn _mm512_mask_srav_epi64( /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srav_epi64&expand=5473) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srav_epi64&expand=5473) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsravq))] @@ -10983,9 +19560,85 @@ pub unsafe fn _mm512_maskz_srav_epi64(k: __mmask8, a: __m512i, count: __m512i) - transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_srav_epi64&expand=5471) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm256_srav_epi64(a: __m256i, count: __m256i) -> __m256i { + transmute(vpsravq256(a.as_i64x4(), count.as_i64x4())) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srav_epi64&expand=5469) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm256_mask_srav_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m256i, +) -> __m256i { + let shf = _mm256_srav_epi64(a, count).as_i64x4(); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srav_epi64&expand=5470) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm256_maskz_srav_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { + let shf = _mm256_srav_epi64(a, count).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srav_epi64&expand=5468) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm_srav_epi64(a: __m128i, count: __m128i) -> __m128i { + transmute(vpsravq128(a.as_i64x2(), count.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srav_epi64&expand=5466) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm_mask_srav_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + count: __m128i, +) -> __m128i { + let shf = _mm_srav_epi64(a, count).as_i64x2(); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srav_epi64&expand=5467) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsravq))] +pub unsafe fn _mm_maskz_srav_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srav_epi64(a, count).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rolv_epi32&expand=4703) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rolv_epi32&expand=4703) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolvd))] @@ -10995,7 +19648,7 @@ pub unsafe fn _mm512_rolv_epi32(a: __m512i, b: __m512i) -> __m512i { /// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rolv_epi32&expand=4701) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rolv_epi32&expand=4701) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolvd))] @@ -11011,7 +19664,7 @@ pub unsafe fn _mm512_mask_rolv_epi32( /// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rolv_epi32&expand=4702) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rolv_epi32&expand=4702) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolvd))] @@ -11021,9 +19674,75 @@ pub unsafe fn _mm512_maskz_rolv_epi32(k: __mmask16, a: __m512i, b: __m512i) -> _ transmute(simd_select_bitmask(k, rol, zero)) } +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rolv_epi32&expand=4700) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvd))] +pub unsafe fn _mm256_rolv_epi32(a: __m256i, b: __m256i) -> __m256i { + transmute(vprolvd256(a.as_i32x8(), b.as_i32x8())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rolv_epi3&expand=4698) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvd))] +pub unsafe fn _mm256_mask_rolv_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let rol = _mm256_rolv_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, rol, src.as_i32x8())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rolv_epi32&expand=4699) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvd))] +pub unsafe fn _mm256_maskz_rolv_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let rol = _mm256_rolv_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, rol, zero)) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rolv_epi32&expand=4697) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvd))] +pub unsafe fn _mm_rolv_epi32(a: __m128i, b: __m128i) -> __m128i { + transmute(vprolvd128(a.as_i32x4(), b.as_i32x4())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rolv_epi32&expand=4695) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvd))] +pub unsafe fn _mm_mask_rolv_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let rol = _mm_rolv_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, rol, src.as_i32x4())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rolv_epi32&expand=4696) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvd))] +pub unsafe fn _mm_maskz_rolv_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let rol = _mm_rolv_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, rol, zero)) +} + /// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rorv_epi32&expand=4739) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rorv_epi32&expand=4739) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprorvd))] @@ -11033,7 +19752,7 @@ pub unsafe fn _mm512_rorv_epi32(a: __m512i, b: __m512i) -> __m512i { /// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rorv_epi32&expand=4737) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rorv_epi32&expand=4737) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprorvd))] @@ -11049,7 +19768,7 @@ pub unsafe fn _mm512_mask_rorv_epi32( /// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rorv_epi32&expand=4738) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rorv_epi32&expand=4738) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprorvd))] @@ -11059,9 +19778,75 @@ pub unsafe fn _mm512_maskz_rorv_epi32(k: __mmask16, a: __m512i, b: __m512i) -> _ transmute(simd_select_bitmask(k, ror, zero)) } +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rorv_epi32&expand=4736) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvd))] +pub unsafe fn _mm256_rorv_epi32(a: __m256i, b: __m256i) -> __m256i { + transmute(vprorvd256(a.as_i32x8(), b.as_i32x8())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rorv_epi32&expand=4734) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvd))] +pub unsafe fn _mm256_mask_rorv_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let ror = _mm256_rorv_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, ror, src.as_i32x8())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rorv_epi32&expand=4735) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvd))] +pub unsafe fn _mm256_maskz_rorv_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let ror = _mm256_rorv_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, ror, zero)) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rorv_epi32&expand=4733) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvd))] +pub unsafe fn _mm_rorv_epi32(a: __m128i, b: __m128i) -> __m128i { + transmute(vprorvd128(a.as_i32x4(), b.as_i32x4())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rorv_epi32&expand=4731) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvd))] +pub unsafe fn _mm_mask_rorv_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let ror = _mm_rorv_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, ror, src.as_i32x4())) +} + +/// Rotate the bits in each packed 32-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rorv_epi32&expand=4732) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvd))] +pub unsafe fn _mm_maskz_rorv_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let ror = _mm_rorv_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, ror, zero)) +} + /// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rolv_epi64&expand=4712) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rolv_epi64&expand=4712) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolvq))] @@ -11071,7 +19856,7 @@ pub unsafe fn _mm512_rolv_epi64(a: __m512i, b: __m512i) -> __m512i { /// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rolv_epi64&expand=4710) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rolv_epi64&expand=4710) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolvq))] @@ -11082,7 +19867,7 @@ pub unsafe fn _mm512_mask_rolv_epi64(src: __m512i, k: __mmask8, a: __m512i, b: _ /// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rolv_epi64&expand=4711) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rolv_epi64&expand=4711) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprolvq))] @@ -11092,9 +19877,75 @@ pub unsafe fn _mm512_maskz_rolv_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, rol, zero)) } +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rolv_epi64&expand=4709) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvq))] +pub unsafe fn _mm256_rolv_epi64(a: __m256i, b: __m256i) -> __m256i { + transmute(vprolvq256(a.as_i64x4(), b.as_i64x4())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rolv_epi64&expand=4707) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvq))] +pub unsafe fn _mm256_mask_rolv_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let rol = _mm256_rolv_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, rol, src.as_i64x4())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rolv_epi64&expand=4708) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvq))] +pub unsafe fn _mm256_maskz_rolv_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let rol = _mm256_rolv_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, rol, zero)) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rolv_epi64&expand=4706) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvq))] +pub unsafe fn _mm_rolv_epi64(a: __m128i, b: __m128i) -> __m128i { + transmute(vprolvq128(a.as_i64x2(), b.as_i64x2())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rolv_epi64&expand=4704) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvq))] +pub unsafe fn _mm_mask_rolv_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let rol = _mm_rolv_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, rol, src.as_i64x2())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the left by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rolv_epi64&expand=4705) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprolvq))] +pub unsafe fn _mm_maskz_rolv_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let rol = _mm_rolv_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, rol, zero)) +} + /// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_rorv_epi64&expand=4748) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_rorv_epi64&expand=4748) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprorvq))] @@ -11104,7 +19955,7 @@ pub unsafe fn _mm512_rorv_epi64(a: __m512i, b: __m512i) -> __m512i { /// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_rorv_epi64&expand=4746) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_rorv_epi64&expand=4746) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprorvq))] @@ -11115,7 +19966,7 @@ pub unsafe fn _mm512_mask_rorv_epi64(src: __m512i, k: __mmask8, a: __m512i, b: _ /// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_rorv_epi64&expand=4747) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_rorv_epi64&expand=4747) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vprorvq))] @@ -11125,9 +19976,75 @@ pub unsafe fn _mm512_maskz_rorv_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, ror, zero)) } +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_rorv_epi64&expand=4745) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvq))] +pub unsafe fn _mm256_rorv_epi64(a: __m256i, b: __m256i) -> __m256i { + transmute(vprorvq256(a.as_i64x4(), b.as_i64x4())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_rorv_epi64&expand=4743) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvq))] +pub unsafe fn _mm256_mask_rorv_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let ror = _mm256_rorv_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, ror, src.as_i64x4())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_rorv_epi64&expand=4744) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvq))] +pub unsafe fn _mm256_maskz_rorv_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let ror = _mm256_rorv_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, ror, zero)) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rorv_epi64&expand=4742) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvq))] +pub unsafe fn _mm_rorv_epi64(a: __m128i, b: __m128i) -> __m128i { + transmute(vprorvq128(a.as_i64x2(), b.as_i64x2())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_rorv_epi64&expand=4740) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvq))] +pub unsafe fn _mm_mask_rorv_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let ror = _mm_rorv_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, ror, src.as_i64x2())) +} + +/// Rotate the bits in each packed 64-bit integer in a to the right by the number of bits specified in the corresponding element of b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_rorv_epi64&expand=4741) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vprorvq))] +pub unsafe fn _mm_maskz_rorv_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let ror = _mm_rorv_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, ror, zero)) +} + /// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sllv_epi32&expand=5342) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sllv_epi32&expand=5342) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllvd))] @@ -11137,7 +20054,7 @@ pub unsafe fn _mm512_sllv_epi32(a: __m512i, count: __m512i) -> __m512i { /// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sllv_epi32&expand=5340) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sllv_epi32&expand=5340) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllvd))] @@ -11153,7 +20070,7 @@ pub unsafe fn _mm512_mask_sllv_epi32( /// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sllv_epi32&expand=5341) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sllv_epi32&expand=5341) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllvd))] @@ -11163,9 +20080,65 @@ pub unsafe fn _mm512_maskz_sllv_epi32(k: __mmask16, a: __m512i, count: __m512i) transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sllv_epi32&expand=5337) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvd))] +pub unsafe fn _mm256_mask_sllv_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m256i, +) -> __m256i { + let shf = _mm256_sllv_epi32(a, count).as_i32x8(); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) +} + +/// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sllv_epi32&expand=5338) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvd))] +pub unsafe fn _mm256_maskz_sllv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { + let shf = _mm256_sllv_epi32(a, count).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sllv_epi32&expand=5334) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvd))] +pub unsafe fn _mm_mask_sllv_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + count: __m128i, +) -> __m128i { + let shf = _mm_sllv_epi32(a, count).as_i32x4(); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sllv_epi32&expand=5335) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvd))] +pub unsafe fn _mm_maskz_sllv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sllv_epi32(a, count).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srlv_epi32&expand=5554) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srlv_epi32&expand=5554) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlvd))] @@ -11175,7 +20148,7 @@ pub unsafe fn _mm512_srlv_epi32(a: __m512i, count: __m512i) -> __m512i { /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_srlv_epi32&expand=5552) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srlv_epi32&expand=5552) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlvd))] @@ -11191,7 +20164,7 @@ pub unsafe fn _mm512_mask_srlv_epi32( /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srlv_epi32&expand=5553) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srlv_epi32&expand=5553) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlvd))] @@ -11201,9 +20174,65 @@ pub unsafe fn _mm512_maskz_srlv_epi32(k: __mmask16, a: __m512i, count: __m512i) transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srlv_epi32&expand=5549) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvd))] +pub unsafe fn _mm256_mask_srlv_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m256i, +) -> __m256i { + let shf = _mm256_srlv_epi32(a, count).as_i32x8(); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) +} + +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srlv_epi32&expand=5550) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvd))] +pub unsafe fn _mm256_maskz_srlv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { + let shf = _mm256_srlv_epi32(a, count).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srlv_epi32&expand=5546) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvd))] +pub unsafe fn _mm_mask_srlv_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + count: __m128i, +) -> __m128i { + let shf = _mm_srlv_epi32(a, count).as_i32x4(); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srlv_epi32&expand=5547) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvd))] +pub unsafe fn _mm_maskz_srlv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srlv_epi32(a, count).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_sllv_epi64&expand=5351) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_sllv_epi64&expand=5351) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllvq))] @@ -11213,7 +20242,7 @@ pub unsafe fn _mm512_sllv_epi64(a: __m512i, count: __m512i) -> __m512i { /// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_sllv_epi64&expand=5349) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_sllv_epi64&expand=5349) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllvq))] @@ -11229,7 +20258,7 @@ pub unsafe fn _mm512_mask_sllv_epi64( /// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_sllv_epi64&expand=5350) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_sllv_epi64&expand=5350) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsllvq))] @@ -11239,9 +20268,65 @@ pub unsafe fn _mm512_maskz_sllv_epi64(k: __mmask8, a: __m512i, count: __m512i) - transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_sllv_epi64&expand=5346) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvq))] +pub unsafe fn _mm256_mask_sllv_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m256i, +) -> __m256i { + let shf = _mm256_sllv_epi64(a, count).as_i64x4(); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_sllv_epi64&expand=5347) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvq))] +pub unsafe fn _mm256_maskz_sllv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { + let shf = _mm256_sllv_epi64(a, count).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_sllv_epi64&expand=5343) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvq))] +pub unsafe fn _mm_mask_sllv_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + count: __m128i, +) -> __m128i { + let shf = _mm_sllv_epi64(a, count).as_i64x2(); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_sllv_epi64&expand=5344) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsllvq))] +pub unsafe fn _mm_maskz_sllv_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_sllv_epi64(a, count).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_srlv_epi64&expand=5563) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_srlv_epi64&expand=5563) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlvq))] @@ -11251,7 +20336,7 @@ pub unsafe fn _mm512_srlv_epi64(a: __m512i, count: __m512i) -> __m512i { /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mask_srlv_epi64&expand=5561) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_srlv_epi64&expand=5561) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlvq))] @@ -11267,7 +20352,7 @@ pub unsafe fn _mm512_mask_srlv_epi64( /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_srlv_epi64&expand=5562) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_srlv_epi64&expand=5562) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpsrlvq))] @@ -11277,245 +20362,778 @@ pub unsafe fn _mm512_maskz_srlv_epi64(k: __mmask8, a: __m512i, count: __m512i) - transmute(simd_select_bitmask(k, shf, zero)) } +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_srlv_epi64&expand=5558) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvq))] +pub unsafe fn _mm256_mask_srlv_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + count: __m256i, +) -> __m256i { + let shf = _mm256_srlv_epi64(a, count).as_i64x4(); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_srlv_epi64&expand=5559) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvq))] +pub unsafe fn _mm256_maskz_srlv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { + let shf = _mm256_srlv_epi64(a, count).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_srlv_epi64&expand=5555) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvq))] +pub unsafe fn _mm_mask_srlv_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + count: __m128i, +) -> __m128i { + let shf = _mm_srlv_epi64(a, count).as_i64x2(); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_srlv_epi64&expand=5556) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpsrlvq))] +pub unsafe fn _mm_maskz_srlv_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { + let shf = _mm_srlv_epi64(a, count).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permute_ps&expand=4170) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permute_ps&expand=4170) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilps, imm8 = 1))] #[rustc_args_required_const(1)] pub unsafe fn _mm512_permute_ps(a: __m512, imm8: i32) -> __m512 { - let a = a.as_f32x16(); - macro_rules! call { - ($imm8:expr) => { - vpermilps(a, _mm512_set1_epi32($imm8).as_i32x16()) + let imm8 = (imm8 & 0xFF) as u8; + let undefined = _mm512_undefined_ps(); + macro_rules! shuffle4 { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + simd_shuffle16( + a, + undefined, + [ + $a, + $b, + $c, + $d, + $a + 4, + $b + 4, + $c + 4, + $d + 4, + $a + 8, + $b + 8, + $c + 8, + $d + 8, + $a + 12, + $b + 12, + $c + 12, + $d + 12, + ], + ) }; } - let r = constify_imm8_sae!(imm8, call); - transmute(r) + macro_rules! shuffle3 { + ($a:expr, $b:expr, $c:expr) => { + match (imm8 >> 6) & 0b11 { + 0b00 => shuffle4!($a, $b, $c, 0), + 0b01 => shuffle4!($a, $b, $c, 1), + 0b10 => shuffle4!($a, $b, $c, 2), + _ => shuffle4!($a, $b, $c, 3), + } + }; + } + macro_rules! shuffle2 { + ($a:expr, $b:expr) => { + match (imm8 >> 4) & 0b11 { + 0b00 => shuffle3!($a, $b, 0), + 0b01 => shuffle3!($a, $b, 1), + 0b10 => shuffle3!($a, $b, 2), + _ => shuffle3!($a, $b, 3), + } + }; + } + macro_rules! shuffle1 { + ($a:expr) => { + match (imm8 >> 2) & 0b11 { + 0b00 => shuffle2!($a, 0), + 0b01 => shuffle2!($a, 1), + 0b10 => shuffle2!($a, 2), + _ => shuffle2!($a, 3), + } + }; + } + match imm8 & 0b11 { + 0b00 => shuffle1!(0), + 0b01 => shuffle1!(1), + 0b10 => shuffle1!(2), + _ => shuffle1!(3), + } } /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permute_ps&expand=4168) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permute_ps&expand=4168) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilps, imm8 = 1))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_mask_permute_ps(src: __m512, k: __mmask16, a: __m512, imm8: i32) -> __m512 { - let a = a.as_f32x16(); macro_rules! call { ($imm8:expr) => { - vpermilps(a, _mm512_set1_epi32($imm8).as_i32x16()) + _mm512_permute_ps(a, $imm8) }; } - let permute = constify_imm8_sae!(imm8, call); - transmute(simd_select_bitmask(k, permute, src.as_f32x16())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x16(), src.as_f32x16())) } /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permute_ps&expand=4169) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permute_ps&expand=4169) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilps, imm8 = 1))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_permute_ps(k: __mmask16, a: __m512, imm8: i32) -> __m512 { - let a = a.as_f32x16(); - macro_rules! call { - ($imm8:expr) => { - vpermilps(a, _mm512_set1_epi32($imm8).as_i32x16()) - }; - } - let permute = constify_imm8_sae!(imm8, call); - let zero = _mm512_setzero_ps().as_f32x16(); - transmute(simd_select_bitmask(k, permute, zero)) -} - -/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst. -/// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permute_pd&expand=4161) -#[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] -#[rustc_args_required_const(1)] -pub unsafe fn _mm512_permute_pd(a: __m512d, imm8: i32) -> __m512d { - let a = a.as_f64x8(); macro_rules! call { ($imm8:expr) => { - vpermilpd(a, _mm512_set1_epi64($imm8).as_i64x8()) + _mm512_permute_ps(a, $imm8) }; } let r = constify_imm8_sae!(imm8, call); - transmute(r) + let zero = _mm512_setzero_ps().as_f32x16(); + transmute(simd_select_bitmask(k, r.as_f32x16(), zero)) } -/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permute_pd&expand=4159) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permute_ps&expand=4165) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps, imm8 = 1))] #[rustc_args_required_const(3)] -pub unsafe fn _mm512_mask_permute_pd(src: __m512d, k: __mmask8, a: __m512d, imm8: i32) -> __m512d { - let a = a.as_f64x8(); +pub unsafe fn _mm256_mask_permute_ps(src: __m256, k: __mmask8, a: __m256, imm8: i32) -> __m256 { macro_rules! call { ($imm8:expr) => { - vpermilpd(a, _mm512_set1_epi64($imm8).as_i64x8()) + _mm256_permute_ps(a, $imm8) }; } - let permute = constify_imm8_sae!(imm8, call); - transmute(simd_select_bitmask(k, permute, src.as_f64x8())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x8(), src.as_f32x8())) } -/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permute_pd&expand=4160) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permute_ps&expand=4166) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps, imm8 = 1))] #[rustc_args_required_const(2)] -pub unsafe fn _mm512_maskz_permute_pd(k: __mmask8, a: __m512d, imm8: i32) -> __m512d { - let a = a.as_f64x8(); - macro_rules! call { - ($imm8:expr) => { - vpermilpd(a, _mm512_set1_epi64($imm8).as_i64x8()) - }; - } - let permute = constify_imm8_sae!(imm8, call); - let zero = _mm512_setzero_pd().as_f64x8(); - transmute(simd_select_bitmask(k, permute, zero)) -} - -/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst. -/// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutex_epi64&expand=4208) -#[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vbroadcast, imm8 = 0b11111111))] -//shoud be vpermq, but generate vpermpd. It generates vpermq with mask. change to vbroadcast becaise CI Windows -#[rustc_args_required_const(1)] -pub unsafe fn _mm512_permutex_epi64(a: __m512i, imm8: i32) -> __m512i { - let a = a.as_i64x8(); +pub unsafe fn _mm256_maskz_permute_ps(k: __mmask8, a: __m256, imm8: i32) -> __m256 { macro_rules! call { ($imm8:expr) => { - vpermq(a, _mm512_set1_epi64($imm8).as_i64x8()) + _mm256_permute_ps(a, $imm8) }; } let r = constify_imm8_sae!(imm8, call); - transmute(r) + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, r.as_f32x8(), zero)) } -/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutex_epi64&expand=4206) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permute_ps&expand=4162) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpbroadcast, imm8 = 0b11111111))] //shoud be vpermq. change to vpbroadcast becaise CI Windows +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps, imm8 = 1))] #[rustc_args_required_const(3)] -pub unsafe fn _mm512_mask_permutex_epi64( - src: __m512i, - k: __mmask8, - a: __m512i, - imm8: i32, -) -> __m512i { - let a = a.as_i64x8(); +pub unsafe fn _mm_mask_permute_ps(src: __m128, k: __mmask8, a: __m128, imm8: i32) -> __m128 { macro_rules! call { ($imm8:expr) => { - vpermq(a, _mm512_set1_epi64($imm8).as_i64x8()) + _mm_permute_ps(a, $imm8) }; } - let permute = constify_imm8_sae!(imm8, call); - transmute(simd_select_bitmask(k, permute, src.as_i64x8())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x4(), src.as_f32x4())) } -/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutex_epi64&expand=4207) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permute_ps&expand=4163) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpbroadcast, imm8 = 0b11111111))] //shoud be vpermq. change to vpbroadcast becaise CI Windows +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps, imm8 = 1))] #[rustc_args_required_const(2)] -pub unsafe fn _mm512_maskz_permutex_epi64(k: __mmask8, a: __m512i, imm8: i32) -> __m512i { - let a = a.as_i64x8(); +pub unsafe fn _mm_maskz_permute_ps(k: __mmask8, a: __m128, imm8: i32) -> __m128 { macro_rules! call { ($imm8:expr) => { - vpermq(a, _mm512_set1_epi64($imm8).as_i64x8()) + _mm_permute_ps(a, $imm8) }; } - let permute = constify_imm8_sae!(imm8, call); - let zero = _mm512_setzero_si512().as_i64x8(); - transmute(simd_select_bitmask(k, permute, zero)) + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, r.as_f32x4(), zero)) } -/// Shuffle double-precision (64-bit) floating-point elements in a within 256-bit lanes using the control in imm8, and store the results in dst. +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutex_pd&expand=4214) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permute_pd&expand=4161) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vbroadcast, imm8 = 0b11111111))] //shoud be vpermpd. change to vbroadcast becaise CI Windows +#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] #[rustc_args_required_const(1)] -pub unsafe fn _mm512_permutex_pd(a: __m512d, imm8: i32) -> __m512d { - let a = a.as_f64x8(); - macro_rules! call { - ($imm8:expr) => { - vpermpd(a, _mm512_set1_epi64($imm8).as_i64x8()) +pub unsafe fn _mm512_permute_pd(a: __m512d, imm8: i32) -> __m512d { + let imm8 = (imm8 & 0xFF) as u8; + let undefined = _mm512_undefined_pd(); + macro_rules! shuffle4 { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + simd_shuffle8( + a, + undefined, + [$a, $b, $c, $d, $a + 4, $b + 4, $c + 4, $d + 4], + ) }; } - let r = constify_imm8_sae!(imm8, call); - transmute(r) -} + macro_rules! shuffle3 { + ($a:expr, $b:expr, $c:expr) => { + match (imm8 >> 3) & 0x1 { + 0 => shuffle4!($a, $b, $c, 2), + _ => shuffle4!($a, $b, $c, 3), + } + }; + } + macro_rules! shuffle2 { + ($a:expr, $b:expr) => { + match (imm8 >> 2) & 0x1 { + 0 => shuffle3!($a, $b, 2), + _ => shuffle3!($a, $b, 3), + } + }; + } + macro_rules! shuffle1 { + ($a:expr) => { + match (imm8 >> 1) & 0x1 { + 0 => shuffle2!($a, 0), + _ => shuffle2!($a, 1), + } + }; + } + match imm8 & 0x1 { + 0 => shuffle1!(0), + _ => shuffle1!(1), + } +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permute_pd&expand=4159) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_mask_permute_pd(src: __m512d, k: __mmask8, a: __m512d, imm8: i32) -> __m512d { + macro_rules! call { + ($imm8:expr) => { + _mm512_permute_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x8(), src.as_f64x8())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permute_pd&expand=4160) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_maskz_permute_pd(k: __mmask8, a: __m512d, imm8: i32) -> __m512d { + macro_rules! call { + ($imm8:expr) => { + _mm512_permute_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_pd().as_f64x8(); + transmute(simd_select_bitmask(k, r.as_f64x8(), zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permute_pd&expand=4156) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_permute_pd(src: __m256d, k: __mmask8, a: __m256d, imm8: i32) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_permute_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x4(), src.as_f64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permute_pd&expand=4157) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 2))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_permute_pd(k: __mmask8, a: __m256d, imm8: i32) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_permute_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, r.as_f64x4(), zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permute_pd&expand=4153) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 0b01))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_permute_pd(src: __m128d, k: __mmask8, a: __m128d, imm8: i32) -> __m128d { + macro_rules! call { + ($imm8:expr) => { + _mm_permute_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x2(), src.as_f64x2())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permute_pd&expand=4154) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd, imm8 = 0b01))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_permute_pd(k: __mmask8, a: __m128d, imm8: i32) -> __m128d { + macro_rules! call { + ($imm8:expr) => { + _mm_permute_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, r.as_f64x2(), zero)) +} + +/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex_epi64&expand=4208) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b10011011))] //shoud be vpermq +#[rustc_args_required_const(1)] +pub unsafe fn _mm512_permutex_epi64(a: __m512i, imm8: i32) -> __m512i { + let imm8 = (imm8 & 0xFF) as u8; + let undefined = _mm512_set1_epi64(0); + macro_rules! shuffle4 { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + simd_shuffle8( + a, + undefined, + [$a, $b, $c, $d, $a + 4, $b + 4, $c + 4, $d + 4], + ) + }; + } + macro_rules! shuffle3 { + ($a:expr, $b:expr, $c:expr) => { + match (imm8 >> 6) & 0b11 { + 0b00 => shuffle4!($a, $b, $c, 0), + 0b01 => shuffle4!($a, $b, $c, 1), + 0b10 => shuffle4!($a, $b, $c, 2), + _ => shuffle4!($a, $b, $c, 3), + } + }; + } + macro_rules! shuffle2 { + ($a:expr, $b:expr) => { + match (imm8 >> 4) & 0b11 { + 0b00 => shuffle3!($a, $b, 0), + 0b01 => shuffle3!($a, $b, 1), + 0b10 => shuffle3!($a, $b, 2), + _ => shuffle3!($a, $b, 3), + } + }; + } + macro_rules! shuffle1 { + ($a:expr) => { + match (imm8 >> 2) & 0b11 { + 0b00 => shuffle2!($a, 0), + 0b01 => shuffle2!($a, 1), + 0b10 => shuffle2!($a, 2), + _ => shuffle2!($a, 3), + } + }; + } + match imm8 & 0b11 { + 0b00 => shuffle1!(0), + 0b01 => shuffle1!(1), + 0b10 => shuffle1!(2), + _ => shuffle1!(3), + } +} + +/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex_epi64&expand=4206) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b11111111))] //should be vpermq +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_mask_permutex_epi64( + src: __m512i, + k: __mmask8, + a: __m512i, + imm8: i32, +) -> __m512i { + macro_rules! call { + ($imm8:expr) => { + _mm512_permutex_epi64(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x8(), src.as_i64x8())) +} + +/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex_epi64&expand=4207) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b11111111))] //should be vpermq +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_maskz_permutex_epi64(k: __mmask8, a: __m512i, imm8: i32) -> __m512i { + macro_rules! call { + ($imm8:expr) => { + _mm512_permutex_epi64(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i64x8(); + transmute(simd_select_bitmask(k, r.as_i64x8(), zero)) +} + +/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex_epi64&expand=4205) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b10011011))] //shoud be vpermq +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_permutex_epi64(a: __m256i, imm8: i32) -> __m256i { + let imm8 = (imm8 & 0xFF) as u8; + let undefined = _mm256_set1_epi64x(0); + macro_rules! shuffle4 { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + simd_shuffle4(a, undefined, [$a, $b, $c, $d]) + }; + } + macro_rules! shuffle3 { + ($a:expr, $b:expr, $c:expr) => { + match (imm8 >> 6) & 0b11 { + 0b00 => shuffle4!($a, $b, $c, 0), + 0b01 => shuffle4!($a, $b, $c, 1), + 0b10 => shuffle4!($a, $b, $c, 2), + _ => shuffle4!($a, $b, $c, 3), + } + }; + } + macro_rules! shuffle2 { + ($a:expr, $b:expr) => { + match (imm8 >> 4) & 0b11 { + 0b00 => shuffle3!($a, $b, 0), + 0b01 => shuffle3!($a, $b, 1), + 0b10 => shuffle3!($a, $b, 2), + _ => shuffle3!($a, $b, 3), + } + }; + } + macro_rules! shuffle1 { + ($a:expr) => { + match (imm8 >> 2) & 0b11 { + 0b00 => shuffle2!($a, 0), + 0b01 => shuffle2!($a, 1), + 0b10 => shuffle2!($a, 2), + _ => shuffle2!($a, 3), + } + }; + } + match imm8 & 0b11 { + 0b00 => shuffle1!(0), + 0b01 => shuffle1!(1), + 0b10 => shuffle1!(2), + _ => shuffle1!(3), + } +} + +/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex_epi6&expand=4203) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b10011011))] //should be vpermq +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_permutex_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_permutex_epi64(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x4(), src.as_i64x4())) +} + +/// Shuffle 64-bit integers in a within 256-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex_epi64&expand=4204) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b10011011))] //should be vpermq +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_permutex_epi64(k: __mmask8, a: __m256i, imm8: i32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_permutex_epi64(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, r.as_i64x4(), zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 256-bit lanes using the control in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex_pd&expand=4214) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b11111111))] //shoud be vpermpd +#[rustc_args_required_const(1)] +pub unsafe fn _mm512_permutex_pd(a: __m512d, imm8: i32) -> __m512d { + let imm8 = (imm8 & 0xFF) as u8; + let undefined = _mm512_undefined_pd(); + macro_rules! shuffle4 { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + simd_shuffle8( + a, + undefined, + [$a, $b, $c, $d, $a + 4, $b + 4, $c + 4, $d + 4], + ) + }; + } + macro_rules! shuffle3 { + ($a:expr, $b:expr, $c:expr) => { + match (imm8 >> 6) & 0b11 { + 0b00 => shuffle4!($a, $b, $c, 0), + 0b01 => shuffle4!($a, $b, $c, 1), + 0b10 => shuffle4!($a, $b, $c, 2), + _ => shuffle4!($a, $b, $c, 3), + } + }; + } + macro_rules! shuffle2 { + ($a:expr, $b:expr) => { + match (imm8 >> 4) & 0b11 { + 0b00 => shuffle3!($a, $b, 0), + 0b01 => shuffle3!($a, $b, 1), + 0b10 => shuffle3!($a, $b, 2), + _ => shuffle3!($a, $b, 3), + } + }; + } + macro_rules! shuffle1 { + ($a:expr) => { + match (imm8 >> 2) & 0b11 { + 0b00 => shuffle2!($a, 0), + 0b01 => shuffle2!($a, 1), + 0b10 => shuffle2!($a, 2), + _ => shuffle2!($a, 3), + } + }; + } + match imm8 & 0b11 { + 0b00 => shuffle1!(0), + 0b01 => shuffle1!(1), + 0b10 => shuffle1!(2), + _ => shuffle1!(3), + } +} /// Shuffle double-precision (64-bit) floating-point elements in a within 256-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutex_pd&expand=4212) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex_pd&expand=4212) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vbroadcast, imm8 = 0b11111111))] //shoud be vpermpd. change to vbroadcast becaise CI Windows +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b11111111))] //shoud be vpermpd #[rustc_args_required_const(3)] pub unsafe fn _mm512_mask_permutex_pd(src: __m512d, k: __mmask8, a: __m512d, imm8: i32) -> __m512d { - let a = a.as_f64x8(); macro_rules! call { ($imm8:expr) => { - vpermpd(a, _mm512_set1_epi64($imm8).as_i64x8()) + _mm512_permutex_pd(a, $imm8) }; } - let permute = constify_imm8_sae!(imm8, call); - transmute(simd_select_bitmask(k, permute, src.as_f64x8())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x8(), src.as_f64x8())) } /// Shuffle double-precision (64-bit) floating-point elements in a within 256-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutex_pd&expand=4213) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex_pd&expand=4213) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vbroadcast, imm8 = 0b11111111))] //shoud be vpermpd. change to vbroadcast becaise CI Windows +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b11111111))] //shoud be vpermpd #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_permutex_pd(k: __mmask8, a: __m512d, imm8: i32) -> __m512d { - let a = a.as_f64x8(); macro_rules! call { ($imm8:expr) => { - vpermpd(a, _mm512_set1_epi64($imm8).as_i64x8()) + _mm512_permutex_pd(a, $imm8) }; } - let permute = constify_imm8_sae!(imm8, call); + let r = constify_imm8_sae!(imm8, call); let zero = _mm512_setzero_pd().as_f64x8(); - transmute(simd_select_bitmask(k, permute, zero)) + transmute(simd_select_bitmask(k, r.as_f64x8(), zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 256-bit lanes using the control in imm8, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex_pd&expand=4211) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b10011011))] //shoud be vpermpd +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_permutex_pd(a: __m256d, imm8: i32) -> __m256d { + let imm8 = (imm8 & 0xFF) as u8; + let undefined = _mm256_undefined_pd(); + macro_rules! shuffle4 { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + simd_shuffle4(a, undefined, [$a, $b, $c, $d]) + }; + } + macro_rules! shuffle3 { + ($a:expr, $b:expr, $c:expr) => { + match (imm8 >> 6) & 0b11 { + 0b00 => shuffle4!($a, $b, $c, 0), + 0b01 => shuffle4!($a, $b, $c, 1), + 0b10 => shuffle4!($a, $b, $c, 2), + _ => shuffle4!($a, $b, $c, 3), + } + }; + } + macro_rules! shuffle2 { + ($a:expr, $b:expr) => { + match (imm8 >> 4) & 0b11 { + 0b00 => shuffle3!($a, $b, 0), + 0b01 => shuffle3!($a, $b, 1), + 0b10 => shuffle3!($a, $b, 2), + _ => shuffle3!($a, $b, 3), + } + }; + } + macro_rules! shuffle1 { + ($a:expr) => { + match (imm8 >> 2) & 0b11 { + 0b00 => shuffle2!($a, 0), + 0b01 => shuffle2!($a, 1), + 0b10 => shuffle2!($a, 2), + _ => shuffle2!($a, 3), + } + }; + } + match imm8 & 0b11 { + 0b00 => shuffle1!(0), + 0b01 => shuffle1!(1), + 0b10 => shuffle1!(2), + _ => shuffle1!(3), + } +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 256-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex_pd&expand=4209) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b10011011))] //shoud be vpermpd +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_permutex_pd(src: __m256d, k: __mmask8, a: __m256d, imm8: i32) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_permutex_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x4(), src.as_f64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 256-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex_pd&expand=4210) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b10011011))] //shoud be vpermpd +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_permutex_pd(k: __mmask8, a: __m256d, imm8: i32) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_permutex_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, r.as_f64x4(), zero)) } /// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. Note that this intrinsic shuffles across 128-bit lanes, unlike past intrinsics that use the permutevar name. This intrinsic is identical to _mm512_permutexvar_epi32, and it is recommended that you use that intrinsic name. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutevar_epi32&expand=4182) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutevar_epi32&expand=4182) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm))] //should be vpermd, but generate vpermps. It generates vpermd with mask +#[cfg_attr(test, assert_instr(vperm))] //should be vpermd pub unsafe fn _mm512_permutevar_epi32(idx: __m512i, a: __m512i) -> __m512i { transmute(vpermd(a.as_i32x16(), idx.as_i32x16())) } /// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). Note that this intrinsic shuffles across 128-bit lanes, unlike past intrinsics that use the permutevar name. This intrinsic is identical to _mm512_mask_permutexvar_epi32, and it is recommended that you use that intrinsic name. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutevar_epi32&expand=4181) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutevar_epi32&expand=4181) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermd))] @@ -11531,7 +21149,7 @@ pub unsafe fn _mm512_mask_permutevar_epi32( /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutevar_ps&expand=4200) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutevar_ps&expand=4200) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilps))] @@ -11541,7 +21159,7 @@ pub unsafe fn _mm512_permutevar_ps(a: __m512, b: __m512i) -> __m512 { /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutevar_ps&expand=4198) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutevar_ps&expand=4198) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilps))] @@ -11557,7 +21175,7 @@ pub unsafe fn _mm512_mask_permutevar_ps( /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutevar_ps&expand=4199) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutevar_ps&expand=4199) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilps))] @@ -11567,9 +21185,55 @@ pub unsafe fn _mm512_maskz_permutevar_ps(k: __mmask16, a: __m512, b: __m512i) -> transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm256_mask_permutevar_ps&expand=4195) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps))] +pub unsafe fn _mm256_mask_permutevar_ps(src: __m256, k: __mmask8, a: __m256, b: __m256i) -> __m256 { + let permute = _mm256_permutevar_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, permute, src.as_f32x8())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutevar_ps&expand=4196) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps))] +pub unsafe fn _mm256_maskz_permutevar_ps(k: __mmask8, a: __m256, b: __m256i) -> __m256 { + let permute = _mm256_permutevar_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutevar_ps&expand=4192) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps))] +pub unsafe fn _mm_mask_permutevar_ps(src: __m128, k: __mmask8, a: __m128, b: __m128i) -> __m128 { + let permute = _mm_permutevar_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, permute, src.as_f32x4())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutevar_ps&expand=4193) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilps))] +pub unsafe fn _mm_maskz_permutevar_ps(k: __mmask8, a: __m128, b: __m128i) -> __m128 { + let permute = _mm_permutevar_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + /// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutevar_pd&expand=4191) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutevar_pd&expand=4191) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilpd))] @@ -11579,7 +21243,7 @@ pub unsafe fn _mm512_permutevar_pd(a: __m512d, b: __m512i) -> __m512d { /// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutevar_pd&expand=4189) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutevar_pd&expand=4189) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilpd))] @@ -11595,7 +21259,7 @@ pub unsafe fn _mm512_mask_permutevar_pd( /// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutevar_pd&expand=4190) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutevar_pd&expand=4190) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermilpd))] @@ -11605,19 +21269,70 @@ pub unsafe fn _mm512_maskz_permutevar_pd(k: __mmask8, a: __m512d, b: __m512i) -> transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutevar_pd&expand=4186) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd))] +pub unsafe fn _mm256_mask_permutevar_pd( + src: __m256d, + k: __mmask8, + a: __m256d, + b: __m256i, +) -> __m256d { + let permute = _mm256_permutevar_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, permute, src.as_f64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutevar_pd&expand=4187) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd))] +pub unsafe fn _mm256_maskz_permutevar_pd(k: __mmask8, a: __m256d, b: __m256i) -> __m256d { + let permute = _mm256_permutevar_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutevar_pd&expand=4183) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd))] +pub unsafe fn _mm_mask_permutevar_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128i) -> __m128d { + let permute = _mm_permutevar_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, permute, src.as_f64x2())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutevar_pd&expand=4184) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermilpd))] +pub unsafe fn _mm_maskz_permutevar_pd(k: __mmask8, a: __m128d, b: __m128i) -> __m128d { + let permute = _mm_permutevar_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, permute, zero)) +} + /// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutexvar_epi32&expand=4301) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_epi32&expand=4301) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm))] //should be vpermd, but generate vpermps. It generates vpermd with mask +#[cfg_attr(test, assert_instr(vperm))] //should be vpermd pub unsafe fn _mm512_permutexvar_epi32(idx: __m512i, a: __m512i) -> __m512i { transmute(vpermd(a.as_i32x16(), idx.as_i32x16())) } /// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutexvar_epi32&expand=4299) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_epi32&expand=4299) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermd))] @@ -11633,7 +21348,7 @@ pub unsafe fn _mm512_mask_permutexvar_epi32( /// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutexvar_epi32&expand=4300) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_epi32&expand=4300) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermd))] @@ -11643,19 +21358,57 @@ pub unsafe fn _mm512_maskz_permutexvar_epi32(k: __mmask16, idx: __m512i, a: __m5 transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutexvar_epi32&expand=4298) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermd +pub unsafe fn _mm256_permutexvar_epi32(idx: __m256i, a: __m256i) -> __m256i { + transmute(_mm256_permutevar8x32_epi32(a, idx)) // llvm use llvm.x86.avx2.permd +} + +/// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutexvar_epi32&expand=4296) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermd))] +pub unsafe fn _mm256_mask_permutexvar_epi32( + src: __m256i, + k: __mmask8, + idx: __m256i, + a: __m256i, +) -> __m256i { + let permute = _mm256_permutexvar_epi32(idx, a).as_i32x8(); + transmute(simd_select_bitmask(k, permute, src.as_i32x8())) +} + +/// Shuffle 32-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutexvar_epi32&expand=4297) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermd))] +pub unsafe fn _mm256_maskz_permutexvar_epi32(k: __mmask8, idx: __m256i, a: __m256i) -> __m256i { + let permute = _mm256_permutexvar_epi32(idx, a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, permute, zero)) +} + /// Shuffle 64-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutexvar_epi64&expand=4307) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_epi64&expand=4307) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm))] //should be vpermq, but generate vpermpd. It generates vpermd with mask +#[cfg_attr(test, assert_instr(vperm))] //should be vpermq pub unsafe fn _mm512_permutexvar_epi64(idx: __m512i, a: __m512i) -> __m512i { transmute(vpermq(a.as_i64x8(), idx.as_i64x8())) } /// Shuffle 64-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutexvar_epi64&expand=4305) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_epi64&expand=4305) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermq))] @@ -11671,7 +21424,7 @@ pub unsafe fn _mm512_mask_permutexvar_epi64( /// Shuffle 64-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutexvar_epi64&expand=4306) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_epi64&expand=4306) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermq))] @@ -11681,9 +21434,47 @@ pub unsafe fn _mm512_maskz_permutexvar_epi64(k: __mmask8, idx: __m512i, a: __m51 transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle 64-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutexvar_epi64&expand=4304) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermq +pub unsafe fn _mm256_permutexvar_epi64(idx: __m256i, a: __m256i) -> __m256i { + transmute(vpermq256(a.as_i64x4(), idx.as_i64x4())) +} + +/// Shuffle 64-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutexvar_epi64&expand=4302) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermq))] +pub unsafe fn _mm256_mask_permutexvar_epi64( + src: __m256i, + k: __mmask8, + idx: __m256i, + a: __m256i, +) -> __m256i { + let permute = _mm256_permutexvar_epi64(idx, a).as_i64x4(); + transmute(simd_select_bitmask(k, permute, src.as_i64x4())) +} + +/// Shuffle 64-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutexvar_epi64&expand=4303) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermq))] +pub unsafe fn _mm256_maskz_permutexvar_epi64(k: __mmask8, idx: __m256i, a: __m256i) -> __m256i { + let permute = _mm256_permutexvar_epi64(idx, a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + /// Shuffle single-precision (32-bit) floating-point elements in a across lanes using the corresponding index in idx. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutevar_ps&expand=4200) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutevar_ps&expand=4200) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermps))] @@ -11693,7 +21484,7 @@ pub unsafe fn _mm512_permutexvar_ps(idx: __m512i, a: __m512) -> __m512 { /// Shuffle single-precision (32-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutexvar_ps&expand=4326) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_ps&expand=4326) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermps))] @@ -11709,7 +21500,7 @@ pub unsafe fn _mm512_mask_permutexvar_ps( /// Shuffle single-precision (32-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutexvar_ps&expand=4327) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_ps&expand=4327) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermps))] @@ -11719,9 +21510,47 @@ pub unsafe fn _mm512_maskz_permutexvar_ps(k: __mmask16, idx: __m512i, a: __m512) transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle single-precision (32-bit) floating-point elements in a across lanes using the corresponding index in idx. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutexvar_ps&expand=4325) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermps))] +pub unsafe fn _mm256_permutexvar_ps(idx: __m256i, a: __m256) -> __m256 { + transmute(_mm256_permutevar8x32_ps(a, idx)) //llvm.x86.avx2.permps +} + +/// Shuffle single-precision (32-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutexvar_ps&expand=4323) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermps))] +pub unsafe fn _mm256_mask_permutexvar_ps( + src: __m256, + k: __mmask8, + idx: __m256i, + a: __m256, +) -> __m256 { + let permute = _mm256_permutexvar_ps(idx, a).as_f32x8(); + transmute(simd_select_bitmask(k, permute, src.as_f32x8())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutexvar_ps&expand=4324) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermps))] +pub unsafe fn _mm256_maskz_permutexvar_ps(k: __mmask8, idx: __m256i, a: __m256) -> __m256 { + let permute = _mm256_permutexvar_ps(idx, a).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, permute, zero)) +} + /// Shuffle double-precision (64-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutexvar_pd&expand=4322) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_pd&expand=4322) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermpd))] @@ -11731,7 +21560,7 @@ pub unsafe fn _mm512_permutexvar_pd(idx: __m512i, a: __m512d) -> __m512d { /// Shuffle double-precision (64-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutexvar_pd&expand=4320) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_pd&expand=4320) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermpd))] @@ -11747,7 +21576,7 @@ pub unsafe fn _mm512_mask_permutexvar_pd( /// Shuffle double-precision (64-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutexvar_pd&expand=4321) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_pd&expand=4321) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermpd))] @@ -11757,9 +21586,47 @@ pub unsafe fn _mm512_maskz_permutexvar_pd(k: __mmask8, idx: __m512i, a: __m512d) transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle double-precision (64-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutexvar_pd&expand=4319) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermpd))] +pub unsafe fn _mm256_permutexvar_pd(idx: __m256i, a: __m256d) -> __m256d { + transmute(vpermpd256(a.as_f64x4(), idx.as_i64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutexvar_pd&expand=4317) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermpd))] +pub unsafe fn _mm256_mask_permutexvar_pd( + src: __m256d, + k: __mmask8, + idx: __m256i, + a: __m256d, +) -> __m256d { + let permute = _mm256_permutexvar_pd(idx, a).as_f64x4(); + transmute(simd_select_bitmask(k, permute, src.as_f64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutexvar_pd&expand=4318) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermpd))] +pub unsafe fn _mm256_maskz_permutexvar_pd(k: __mmask8, idx: __m256i, a: __m256d) -> __m256d { + let permute = _mm256_permutexvar_pd(idx, a).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + /// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutex2var_epi32&expand=4238) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_epi32&expand=4238) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //vpermi2d or vpermt2d @@ -11769,7 +21636,7 @@ pub unsafe fn _mm512_permutex2var_epi32(a: __m512i, idx: __m512i, b: __m512i) -> /// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutex2var_epi32&expand=4235) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_epi32&expand=4235) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermt2d))] @@ -11785,7 +21652,7 @@ pub unsafe fn _mm512_mask_permutex2var_epi32( /// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutex2var_epi32&expand=4237) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_epi32&expand=4237) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //vpermi2d or vpermt2d @@ -11802,7 +21669,7 @@ pub unsafe fn _mm512_maskz_permutex2var_epi32( /// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask2_permutex2var_epi32&expand=4236) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_epi32&expand=4236) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermi2d))] @@ -11816,68 +21683,304 @@ pub unsafe fn _mm512_mask2_permutex2var_epi32( transmute(simd_select_bitmask(k, permute, idx.as_i32x16())) } -/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutex2var_epi64&expand=4250) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex2var_epi32&expand=4234) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q -pub unsafe fn _mm512_permutex2var_epi64(a: __m512i, idx: __m512i, b: __m512i) -> __m512i { - transmute(vpermi2q(a.as_i64x8(), idx.as_i64x8(), b.as_i64x8())) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2d or vpermt2d +pub unsafe fn _mm256_permutex2var_epi32(a: __m256i, idx: __m256i, b: __m256i) -> __m256i { + transmute(vpermi2d256(a.as_i32x8(), idx.as_i32x8(), b.as_i32x8())) } -/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutex2var_epi64&expand=4247) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex2var_epi32&expand=4231) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpermt2q))] -pub unsafe fn _mm512_mask_permutex2var_epi64( - a: __m512i, +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2d))] +pub unsafe fn _mm256_mask_permutex2var_epi32( + a: __m256i, k: __mmask8, - idx: __m512i, - b: __m512i, -) -> __m512i { - let permute = _mm512_permutex2var_epi64(a, idx, b).as_i64x8(); - transmute(simd_select_bitmask(k, permute, a.as_i64x8())) + idx: __m256i, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi32(a, idx, b).as_i32x8(); + transmute(simd_select_bitmask(k, permute, a.as_i32x8())) } -/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutex2var_epi64&expand=4249) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex2var_epi32&expand=4233) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q -pub unsafe fn _mm512_maskz_permutex2var_epi64( +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2d or vpermt2d +pub unsafe fn _mm256_maskz_permutex2var_epi32( k: __mmask8, - a: __m512i, - idx: __m512i, - b: __m512i, -) -> __m512i { - let permute = _mm512_permutex2var_epi64(a, idx, b).as_i64x8(); - let zero = _mm512_setzero_si512().as_i64x8(); + a: __m256i, + idx: __m256i, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi32(a, idx, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); transmute(simd_select_bitmask(k, permute, zero)) } -/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask2_permutex2var_epi64&expand=4248) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask2_permutex2var_epi32&expand=4232) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpermi2q))] -pub unsafe fn _mm512_mask2_permutex2var_epi64( - a: __m512i, - idx: __m512i, +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermi2d))] +pub unsafe fn _mm256_mask2_permutex2var_epi32( + a: __m256i, + idx: __m256i, k: __mmask8, - b: __m512i, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi32(a, idx, b).as_i32x8(); + transmute(simd_select_bitmask(k, permute, idx.as_i32x8())) +} + +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutex2var_epi32&expand=4230) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2d or vpermt2d +pub unsafe fn _mm_permutex2var_epi32(a: __m128i, idx: __m128i, b: __m128i) -> __m128i { + transmute(vpermi2d128(a.as_i32x4(), idx.as_i32x4(), b.as_i32x4())) +} + +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutex2var_epi32&expand=4227) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2d))] +pub unsafe fn _mm_mask_permutex2var_epi32( + a: __m128i, + k: __mmask8, + idx: __m128i, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi32(a, idx, b).as_i32x4(); + transmute(simd_select_bitmask(k, permute, a.as_i32x4())) +} + +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutex2var_epi32&expand=4229) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2d or vpermt2d +pub unsafe fn _mm_maskz_permutex2var_epi32( + k: __mmask8, + a: __m128i, + idx: __m128i, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi32(a, idx, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 32-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask2_permutex2var_epi32&expand=4228) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermi2d))] +pub unsafe fn _mm_mask2_permutex2var_epi32( + a: __m128i, + idx: __m128i, + k: __mmask8, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi32(a, idx, b).as_i32x4(); + transmute(simd_select_bitmask(k, permute, idx.as_i32x4())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_epi64&expand=4250) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q +pub unsafe fn _mm512_permutex2var_epi64(a: __m512i, idx: __m512i, b: __m512i) -> __m512i { + transmute(vpermi2q(a.as_i64x8(), idx.as_i64x8(), b.as_i64x8())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_epi64&expand=4247) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpermt2q))] +pub unsafe fn _mm512_mask_permutex2var_epi64( + a: __m512i, + k: __mmask8, + idx: __m512i, + b: __m512i, +) -> __m512i { + let permute = _mm512_permutex2var_epi64(a, idx, b).as_i64x8(); + transmute(simd_select_bitmask(k, permute, a.as_i64x8())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_epi64&expand=4249) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q +pub unsafe fn _mm512_maskz_permutex2var_epi64( + k: __mmask8, + a: __m512i, + idx: __m512i, + b: __m512i, +) -> __m512i { + let permute = _mm512_permutex2var_epi64(a, idx, b).as_i64x8(); + let zero = _mm512_setzero_si512().as_i64x8(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_epi64&expand=4248) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpermi2q))] +pub unsafe fn _mm512_mask2_permutex2var_epi64( + a: __m512i, + idx: __m512i, + k: __mmask8, + b: __m512i, ) -> __m512i { let permute = _mm512_permutex2var_epi64(a, idx, b).as_i64x8(); transmute(simd_select_bitmask(k, permute, idx.as_i64x8())) } +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex2var_epi64&expand=4246) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q +pub unsafe fn _mm256_permutex2var_epi64(a: __m256i, idx: __m256i, b: __m256i) -> __m256i { + transmute(vpermi2q256(a.as_i64x4(), idx.as_i64x4(), b.as_i64x4())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex2var_epi64&expand=4243) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2q))] +pub unsafe fn _mm256_mask_permutex2var_epi64( + a: __m256i, + k: __mmask8, + idx: __m256i, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi64(a, idx, b).as_i64x4(); + transmute(simd_select_bitmask(k, permute, a.as_i64x4())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex2var_epi64&expand=4245) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q +pub unsafe fn _mm256_maskz_permutex2var_epi64( + k: __mmask8, + a: __m256i, + idx: __m256i, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi64(a, idx, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask2_permutex2var_epi64&expand=4244) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermi2q))] +pub unsafe fn _mm256_mask2_permutex2var_epi64( + a: __m256i, + idx: __m256i, + k: __mmask8, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi64(a, idx, b).as_i64x4(); + transmute(simd_select_bitmask(k, permute, idx.as_i64x4())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutex2var_epi64&expand=4242) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q +pub unsafe fn _mm_permutex2var_epi64(a: __m128i, idx: __m128i, b: __m128i) -> __m128i { + transmute(vpermi2q128(a.as_i64x2(), idx.as_i64x2(), b.as_i64x2())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutex2var_epi64&expand=4239) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2q))] +pub unsafe fn _mm_mask_permutex2var_epi64( + a: __m128i, + k: __mmask8, + idx: __m128i, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi64(a, idx, b).as_i64x2(); + transmute(simd_select_bitmask(k, permute, a.as_i64x2())) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutex2var_epi64&expand=4241) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2q or vpermt2q +pub unsafe fn _mm_maskz_permutex2var_epi64( + k: __mmask8, + a: __m128i, + idx: __m128i, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi64(a, idx, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 64-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask2_permutex2var_epi64&expand=4240) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermi2q))] +pub unsafe fn _mm_mask2_permutex2var_epi64( + a: __m128i, + idx: __m128i, + k: __mmask8, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi64(a, idx, b).as_i64x2(); + transmute(simd_select_bitmask(k, permute, idx.as_i64x2())) +} + /// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutex2var_ps&expand=4286) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_ps&expand=4286) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //vpermi2ps or vpermt2ps @@ -11887,7 +21990,7 @@ pub unsafe fn _mm512_permutex2var_ps(a: __m512, idx: __m512i, b: __m512) -> __m5 /// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutex2var_ps&expand=4283) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_ps&expand=4283) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermt2ps))] @@ -11903,7 +22006,7 @@ pub unsafe fn _mm512_mask_permutex2var_ps( /// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutex2var_ps&expand=4285) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_ps&expand=4285) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //vpermi2ps or vpermt2ps @@ -11920,7 +22023,7 @@ pub unsafe fn _mm512_maskz_permutex2var_ps( /// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask2_permutex2var_ps&expand=4284) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_ps&expand=4284) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //should be vpermi2ps, but it shows vpermt2ps @@ -11931,13 +22034,118 @@ pub unsafe fn _mm512_mask2_permutex2var_ps( b: __m512, ) -> __m512 { let permute = _mm512_permutex2var_ps(a, idx, b).as_f32x16(); - let zero = _mm512_setzero_ps().as_f32x16(); + let idx = _mm512_castsi512_ps(idx).as_f32x16(); + transmute(simd_select_bitmask(k, permute, idx)) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex2var_ps&expand=4282) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2ps or vpermt2ps +pub unsafe fn _mm256_permutex2var_ps(a: __m256, idx: __m256i, b: __m256) -> __m256 { + transmute(vpermi2ps256(a.as_f32x8(), idx.as_i32x8(), b.as_f32x8())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex2var_ps&expand=4279) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2ps))] +pub unsafe fn _mm256_mask_permutex2var_ps( + a: __m256, + k: __mmask8, + idx: __m256i, + b: __m256, +) -> __m256 { + let permute = _mm256_permutex2var_ps(a, idx, b).as_f32x8(); + transmute(simd_select_bitmask(k, permute, a.as_f32x8())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex2var_ps&expand=4281) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2ps or vpermt2ps +pub unsafe fn _mm256_maskz_permutex2var_ps( + k: __mmask8, + a: __m256, + idx: __m256i, + b: __m256, +) -> __m256 { + let permute = _mm256_permutex2var_ps(a, idx, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask2_permutex2var_ps&expand=4280) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2ps, but it shows vpermt2ps +pub unsafe fn _mm256_mask2_permutex2var_ps( + a: __m256, + idx: __m256i, + k: __mmask8, + b: __m256, +) -> __m256 { + let permute = _mm256_permutex2var_ps(a, idx, b).as_f32x8(); + let idx = _mm256_castsi256_ps(idx).as_f32x8(); + transmute(simd_select_bitmask(k, permute, idx)) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutex2var_ps&expand=4278) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2ps or vpermt2ps +pub unsafe fn _mm_permutex2var_ps(a: __m128, idx: __m128i, b: __m128) -> __m128 { + transmute(vpermi2ps128(a.as_f32x4(), idx.as_i32x4(), b.as_f32x4())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutex2var_ps&expand=4275) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2ps))] +pub unsafe fn _mm_mask_permutex2var_ps(a: __m128, k: __mmask8, idx: __m128i, b: __m128) -> __m128 { + let permute = _mm_permutex2var_ps(a, idx, b).as_f32x4(); + transmute(simd_select_bitmask(k, permute, a.as_f32x4())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutex2var_ps&expand=4277) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2ps or vpermt2ps +pub unsafe fn _mm_maskz_permutex2var_ps(k: __mmask8, a: __m128, idx: __m128i, b: __m128) -> __m128 { + let permute = _mm_permutex2var_ps(a, idx, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask2_permutex2var_ps&expand=4276) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2ps, but it shows vpermt2ps +pub unsafe fn _mm_mask2_permutex2var_ps(a: __m128, idx: __m128i, k: __mmask8, b: __m128) -> __m128 { + let permute = _mm_permutex2var_ps(a, idx, b).as_f32x4(); + let idx = _mm_castsi128_ps(idx).as_f32x4(); + transmute(simd_select_bitmask(k, permute, idx)) +} + /// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_permutex2var_pd&expand=4274) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_pd&expand=4274) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //vpermi2pd or vpermt2pd @@ -11947,7 +22155,7 @@ pub unsafe fn _mm512_permutex2var_pd(a: __m512d, idx: __m512i, b: __m512d) -> __ /// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_permutex2var_pd&expand=4271) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_pd&expand=4271) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpermt2pd))] @@ -11963,7 +22171,7 @@ pub unsafe fn _mm512_mask_permutex2var_pd( /// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_permutex2var_pd&expand=4273) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_pd&expand=4273) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //vpermi2pd or vpermt2pd @@ -11980,7 +22188,7 @@ pub unsafe fn _mm512_maskz_permutex2var_pd( /// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set) /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask2_permutex2var_pd&expand=4272) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_pd&expand=4272) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vperm))] //should be vpermi2pd, but it shows vpermt2pd @@ -11991,10 +22199,130 @@ pub unsafe fn _mm512_mask2_permutex2var_pd( b: __m512d, ) -> __m512d { let permute = _mm512_permutex2var_pd(a, idx, b).as_f64x8(); - let zero = _mm512_setzero_pd().as_f64x8(); + let idx = _mm512_castsi512_pd(idx).as_f64x8(); + transmute(simd_select_bitmask(k, permute, idx)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex2var_pd&expand=4270) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2pd or vpermt2pd +pub unsafe fn _mm256_permutex2var_pd(a: __m256d, idx: __m256i, b: __m256d) -> __m256d { + transmute(vpermi2pd256(a.as_f64x4(), idx.as_i64x4(), b.as_f64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex2var_pd&expand=4267) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2pd))] +pub unsafe fn _mm256_mask_permutex2var_pd( + a: __m256d, + k: __mmask8, + idx: __m256i, + b: __m256d, +) -> __m256d { + let permute = _mm256_permutex2var_pd(a, idx, b).as_f64x4(); + transmute(simd_select_bitmask(k, permute, a.as_f64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex2var_pd&expand=4269) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2pd or vpermt2pd +pub unsafe fn _mm256_maskz_permutex2var_pd( + k: __mmask8, + a: __m256d, + idx: __m256i, + b: __m256d, +) -> __m256d { + let permute = _mm256_permutex2var_pd(a, idx, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set) +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask2_permutex2var_pd&expand=4268) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2pd, but it shows vpermt2pd +pub unsafe fn _mm256_mask2_permutex2var_pd( + a: __m256d, + idx: __m256i, + k: __mmask8, + b: __m256d, +) -> __m256d { + let permute = _mm256_permutex2var_pd(a, idx, b).as_f64x4(); + let idx = _mm256_castsi256_pd(idx).as_f64x4(); + transmute(simd_select_bitmask(k, permute, idx)) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutex2var_pd&expand=4266) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2pd or vpermt2pd +pub unsafe fn _mm_permutex2var_pd(a: __m128d, idx: __m128i, b: __m128d) -> __m128d { + transmute(vpermi2pd128(a.as_f64x2(), idx.as_i64x2(), b.as_f64x2())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutex2var_pd&expand=4263) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2pd))] +pub unsafe fn _mm_mask_permutex2var_pd( + a: __m128d, + k: __mmask8, + idx: __m128i, + b: __m128d, +) -> __m128d { + let permute = _mm_permutex2var_pd(a, idx, b).as_f64x2(); + transmute(simd_select_bitmask(k, permute, a.as_f64x2())) +} + +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutex2var_pd&expand=4265) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //vpermi2pd or vpermt2pd +pub unsafe fn _mm_maskz_permutex2var_pd( + k: __mmask8, + a: __m128d, + idx: __m128i, + b: __m128d, +) -> __m128d { + let permute = _mm_permutex2var_pd(a, idx, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); transmute(simd_select_bitmask(k, permute, zero)) } +/// Shuffle double-precision (64-bit) floating-point elements in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from idx when the corresponding mask bit is not set) +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask2_permutex2var_pd&expand=4264) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2pd, but it shows vpermt2pd +pub unsafe fn _mm_mask2_permutex2var_pd( + a: __m128d, + idx: __m128i, + k: __mmask8, + b: __m128d, +) -> __m128d { + let permute = _mm_permutex2var_pd(a, idx, b).as_f64x2(); + let idx = _mm_castsi128_pd(idx).as_f64x2(); + transmute(simd_select_bitmask(k, permute, idx)) +} + /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_shuffle_epi32&expand=5150) @@ -12004,7 +22332,6 @@ pub unsafe fn _mm512_mask2_permutex2var_pd( #[rustc_args_required_const(1)] pub unsafe fn _mm512_shuffle_epi32(a: __m512i, imm8: _MM_PERM_ENUM) -> __m512i { let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i32x16(); macro_rules! shuffle4 { ( @@ -12075,10 +22402,10 @@ pub unsafe fn _mm512_shuffle_epi32(a: __m512i, imm8: _MM_PERM_ENUM) -> __m512i { /// Shuffle 32-bit integers in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_shuffle_epi32&expand=5148) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_epi32&expand=5148) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] //should be vpshufd, but generate vpermilps +#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_mask_shuffle_epi32( src: __m512i, @@ -12086,158 +22413,116 @@ pub unsafe fn _mm512_mask_shuffle_epi32( a: __m512i, imm8: _MM_PERM_ENUM, ) -> __m512i { - let imm8 = (imm8 & 0xFF) as u8; - - let a = a.as_i32x16(); - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr - ) => { - simd_shuffle16( - a, - a, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, 16, $e, $f, $g, 20, $i, $j, $k, 24, $m, $n, $o, 28), - 1 => shuffle4!($a, $b, $c, 17, $e, $f, $g, 21, $i, $j, $k, 25, $m, $n, $o, 29), - 2 => shuffle4!($a, $b, $c, 18, $e, $f, $g, 22, $i, $j, $k, 26, $m, $n, $o, 30), - _ => shuffle4!($a, $b, $c, 19, $e, $f, $g, 23, $i, $j, $k, 27, $m, $n, $o, 31), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, 16, $e, $f, 20, $i, $j, 24, $m, $n, 28), - 1 => shuffle3!($a, $b, 17, $e, $f, 21, $i, $j, 25, $m, $n, 29), - 2 => shuffle3!($a, $b, 18, $e, $f, 22, $i, $j, 26, $m, $n, 30), - _ => shuffle3!($a, $b, 19, $e, $f, 23, $i, $j, 27, $m, $n, 31), - } - }; - } - macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, 0, $e, 4, $i, 8, $m, 12), - 1 => shuffle2!($a, 1, $e, 5, $i, 9, $m, 13), - 2 => shuffle2!($a, 2, $e, 6, $i, 10, $m, 14), - _ => shuffle2!($a, 3, $e, 7, $i, 11, $m, 15), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_epi32(a, $imm8) }; } - let shuffle: i32x16 = match imm8 & 0x3 { - 0 => shuffle1!(0, 4, 8, 12), - 1 => shuffle1!(1, 5, 9, 13), - 2 => shuffle1!(2, 6, 10, 14), - _ => shuffle1!(3, 7, 11, 15), - }; - transmute(simd_select_bitmask(k, shuffle, src.as_i32x16())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x16(), src.as_i32x16())) } /// Shuffle 32-bit integers in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_shuffle_epi32&expand=5149) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_epi32&expand=5149) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] //should be vpshufd, but generate vpermilps +#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_shuffle_epi32(k: __mmask16, a: __m512i, imm8: _MM_PERM_ENUM) -> __m512i { - let imm8 = (imm8 & 0xFF) as u8; + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_epi32(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, r.as_i32x16(), zero)) +} - let a = a.as_i32x16(); - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr - ) => { - simd_shuffle16( - a, - a, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) +/// Shuffle 32-bit integers in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_epi32&expand=5145) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_shuffle_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + imm8: _MM_PERM_ENUM, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_epi32(a, $imm8) }; } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, 16, $e, $f, $g, 20, $i, $j, $k, 24, $m, $n, $o, 28), - 1 => shuffle4!($a, $b, $c, 17, $e, $f, $g, 21, $i, $j, $k, 25, $m, $n, $o, 29), - 2 => shuffle4!($a, $b, $c, 18, $e, $f, $g, 22, $i, $j, $k, 26, $m, $n, $o, 30), - _ => shuffle4!($a, $b, $c, 19, $e, $f, $g, 23, $i, $j, $k, 27, $m, $n, $o, 31), - } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x8(), src.as_i32x8())) +} + +/// Shuffle 32-bit integers in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_epi32&expand=5146) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_shuffle_epi32(k: __mmask8, a: __m256i, imm8: _MM_PERM_ENUM) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_epi32(a, $imm8) }; } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, 16, $e, $f, 20, $i, $j, 24, $m, $n, 28), - 1 => shuffle3!($a, $b, 17, $e, $f, 21, $i, $j, 25, $m, $n, 29), - 2 => shuffle3!($a, $b, 18, $e, $f, 22, $i, $j, 26, $m, $n, 30), - _ => shuffle3!($a, $b, 19, $e, $f, 23, $i, $j, 27, $m, $n, 31), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r.as_i32x8(), zero)) +} + +/// Shuffle 32-bit integers in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shuffle_epi32&expand=5142) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_mask_shuffle_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + imm8: _MM_PERM_ENUM, +) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_shuffle_epi32(a, $imm8) }; } - macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, 0, $e, 4, $i, 8, $m, 12), - 1 => shuffle2!($a, 1, $e, 5, $i, 9, $m, 13), - 2 => shuffle2!($a, 2, $e, 6, $i, 10, $m, 14), - _ => shuffle2!($a, 3, $e, 7, $i, 11, $m, 15), - } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x4(), src.as_i32x4())) +} + +/// Shuffle 32-bit integers in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shuffle_epi32&expand=5143) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpshufd, imm8 = 9))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_maskz_shuffle_epi32(k: __mmask8, a: __m128i, imm8: _MM_PERM_ENUM) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_shuffle_epi32(a, $imm8) }; } - let shuffle: i32x16 = match imm8 & 0x3 { - 0 => shuffle1!(0, 4, 8, 12), - 1 => shuffle1!(1, 5, 9, 13), - 2 => shuffle1!(2, 6, 10, 14), - _ => shuffle1!(3, 7, 11, 15), - }; - let zero = _mm512_setzero_si512().as_i32x16(); - transmute(simd_select_bitmask(k, shuffle, zero)) + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r.as_i32x4(), zero)) } /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_shuffle_ps&expand=5203) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_ps&expand=5203) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufps, imm8 = 0))] @@ -12313,7 +22598,7 @@ pub unsafe fn _mm512_shuffle_ps(a: __m512, b: __m512, imm8: i32) -> __m512 { /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_shuffle_ps&expand=5201) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_ps&expand=5201) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufps, imm8 = 0))] @@ -12325,246 +22610,123 @@ pub unsafe fn _mm512_mask_shuffle_ps( b: __m512, imm8: i32, ) -> __m512 { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr - ) => { - simd_shuffle16( - a, - b, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, 16, $e, $f, $g, 20, $i, $j, $k, 24, $m, $n, $o, 28), - 1 => shuffle4!($a, $b, $c, 17, $e, $f, $g, 21, $i, $j, $k, 25, $m, $n, $o, 29), - 2 => shuffle4!($a, $b, $c, 18, $e, $f, $g, 22, $i, $j, $k, 26, $m, $n, $o, 30), - _ => shuffle4!($a, $b, $c, 19, $e, $f, $g, 23, $i, $j, $k, 27, $m, $n, $o, 31), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, 16, $e, $f, 20, $i, $j, 24, $m, $n, 28), - 1 => shuffle3!($a, $b, 17, $e, $f, 21, $i, $j, 25, $m, $n, 29), - 2 => shuffle3!($a, $b, 18, $e, $f, 22, $i, $j, 26, $m, $n, 30), - _ => shuffle3!($a, $b, 19, $e, $f, 23, $i, $j, 27, $m, $n, 31), - } - }; - } - macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, 0, $e, 4, $i, 8, $m, 12), - 1 => shuffle2!($a, 1, $e, 5, $i, 9, $m, 13), - 2 => shuffle2!($a, 2, $e, 6, $i, 10, $m, 14), - _ => shuffle2!($a, 3, $e, 7, $i, 11, $m, 15), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_ps(a, b, $imm8) }; } - let shuffle = match imm8 & 0x3 { - 0 => shuffle1!(0, 4, 8, 12), - 1 => shuffle1!(1, 5, 9, 13), - 2 => shuffle1!(2, 6, 10, 14), - _ => shuffle1!(3, 7, 11, 15), - }; - - transmute(simd_select_bitmask(k, shuffle, src.as_f32x16())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x16(), src.as_f32x16())) } /// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_shuffle_ps&expand=5202) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_ps&expand=5202) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufps, imm8 = 0))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_shuffle_ps(k: __mmask16, a: __m512, b: __m512, imm8: i32) -> __m512 { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr - ) => { - simd_shuffle16( - a, - b, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, 16, $e, $f, $g, 20, $i, $j, $k, 24, $m, $n, $o, 28), - 1 => shuffle4!($a, $b, $c, 17, $e, $f, $g, 21, $i, $j, $k, 25, $m, $n, $o, 29), - 2 => shuffle4!($a, $b, $c, 18, $e, $f, $g, 22, $i, $j, $k, 26, $m, $n, $o, 30), - _ => shuffle4!($a, $b, $c, 19, $e, $f, $g, 23, $i, $j, $k, 27, $m, $n, $o, 31), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, 16, $e, $f, 20, $i, $j, 24, $m, $n, 28), - 1 => shuffle3!($a, $b, 17, $e, $f, 21, $i, $j, 25, $m, $n, 29), - 2 => shuffle3!($a, $b, 18, $e, $f, 22, $i, $j, 26, $m, $n, 30), - _ => shuffle3!($a, $b, 19, $e, $f, 23, $i, $j, 27, $m, $n, 31), - } - }; - } - macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, 0, $e, 4, $i, 8, $m, 12), - 1 => shuffle2!($a, 1, $e, 5, $i, 9, $m, 13), - 2 => shuffle2!($a, 2, $e, 6, $i, 10, $m, 14), - _ => shuffle2!($a, 3, $e, 7, $i, 11, $m, 15), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_ps(a, b, $imm8) }; } - let shuffle = match imm8 & 0x3 { - 0 => shuffle1!(0, 4, 8, 12), - 1 => shuffle1!(1, 5, 9, 13), - 2 => shuffle1!(2, 6, 10, 14), - _ => shuffle1!(3, 7, 11, 15), - }; - + let r = constify_imm8_sae!(imm8, call); let zero = _mm512_setzero_ps().as_f32x16(); - transmute(simd_select_bitmask(k, shuffle, zero)) + transmute(simd_select_bitmask(k, r.as_f32x16(), zero)) } -/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst. +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_shuffle_pd&expand=5192) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_ps&expand=5198) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vshufpd, imm8 = 3))] -#[rustc_args_required_const(2)] -pub unsafe fn _mm512_shuffle_pd(a: __m512d, b: __m512d, imm8: i32) -> __m512d { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle8 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr) => { - simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) - }; - } - macro_rules! shuffle7 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr) => { - match (imm8 >> 7) & 0x1 { - 0 => shuffle8!($a, $b, $c, $d, $e, $f, $g, 14), - _ => shuffle8!($a, $b, $c, $d, $e, $f, $g, 15), - } - }; - } - macro_rules! shuffle6 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr) => { - match (imm8 >> 6) & 0x1 { - 0 => shuffle7!($a, $b, $c, $d, $e, $f, 6), - _ => shuffle7!($a, $b, $c, $d, $e, $f, 7), - } - }; - } - macro_rules! shuffle5 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr) => { - match (imm8 >> 5) & 0x1 { - 0 => shuffle6!($a, $b, $c, $d, $e, 12), - _ => shuffle6!($a, $b, $c, $d, $e, 13), - } - }; - } - macro_rules! shuffle4 { - ($a:expr, $b:expr, $c:expr, $d:expr) => { - match (imm8 >> 4) & 0x1 { - 0 => shuffle5!($a, $b, $c, $d, 4), - _ => shuffle5!($a, $b, $c, $d, 5), - } +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufps, imm8 = 9))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shuffle_ps( + src: __m256, + k: __mmask8, + a: __m256, + b: __m256, + imm8: i32, +) -> __m256 { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_ps(a, b, $imm8) }; } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr) => { - match (imm8 >> 3) & 0x1 { - 0 => shuffle4!($a, $b, $c, 10), - _ => shuffle4!($a, $b, $c, 11), - } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x8(), src.as_f32x8())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_ps&expand=5199) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufps, imm8 = 9))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shuffle_ps(k: __mmask8, a: __m256, b: __m256, imm8: i32) -> __m256 { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_ps(a, b, $imm8) }; } - macro_rules! shuffle2 { - ($a:expr, $b:expr) => { - match (imm8 >> 2) & 0x1 { - 0 => shuffle3!($a, $b, 2), - _ => shuffle3!($a, $b, 3), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, r.as_f32x8(), zero)) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shuffle_ps&expand=5195) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufps, imm8 = 9))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shuffle_ps( + src: __m128, + k: __mmask8, + a: __m128, + b: __m128, + imm8: i32, +) -> __m128 { + macro_rules! call { + ($imm8:expr) => { + _mm_shuffle_ps(a, b, $imm8) }; } - macro_rules! shuffle1 { - ($a:expr) => { - match (imm8 >> 1) & 0x1 { - 0 => shuffle2!($a, 8), - _ => shuffle2!($a, 9), - } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x4(), src.as_f32x4())) +} + +/// Shuffle single-precision (32-bit) floating-point elements in a using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shuffle_ps&expand=5196) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufps, imm8 = 9))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shuffle_ps(k: __mmask8, a: __m128, b: __m128, imm8: i32) -> __m128 { + macro_rules! call { + ($imm8:expr) => { + _mm_shuffle_ps(a, b, $imm8) }; } - match imm8 & 0x1 { - 0 => shuffle1!(0), - _ => shuffle1!(1), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, r.as_f32x4(), zero)) } -/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_shuffle_pd&expand=5190) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_pd&expand=5192) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufpd, imm8 = 3))] -#[rustc_args_required_const(4)] -pub unsafe fn _mm512_mask_shuffle_pd( - src: __m512d, - k: __mmask8, - a: __m512d, - b: __m512d, - imm8: i32, -) -> __m512d { +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shuffle_pd(a: __m512d, b: __m512d, imm8: i32) -> __m512d { assert!(imm8 >= 0 && imm8 <= 255); let imm8 = (imm8 & 0xFF) as u8; macro_rules! shuffle8 { @@ -12628,100 +22790,141 @@ pub unsafe fn _mm512_mask_shuffle_pd( } }; } - let shuffle = match imm8 & 0x1 { + match imm8 & 0x1 { 0 => shuffle1!(0), _ => shuffle1!(1), - }; + } +} - transmute(simd_select_bitmask(k, shuffle, src.as_f64x8())) +/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_pd&expand=5190) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vshufpd, imm8 = 3))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shuffle_pd( + src: __m512d, + k: __mmask8, + a: __m512d, + b: __m512d, + imm8: i32, +) -> __m512d { + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_pd(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x8(), src.as_f64x8())) } /// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_shuffle_pd&expand=5191) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_pd&expand=5191) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufpd, imm8 = 3))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_shuffle_pd(k: __mmask8, a: __m512d, b: __m512d, imm8: i32) -> __m512d { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle8 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr) => { - simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) - }; - } - macro_rules! shuffle7 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr) => { - match (imm8 >> 7) & 0x1 { - 0 => shuffle8!($a, $b, $c, $d, $e, $f, $g, 14), - _ => shuffle8!($a, $b, $c, $d, $e, $f, $g, 15), - } - }; - } - macro_rules! shuffle6 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr) => { - match (imm8 >> 6) & 0x1 { - 0 => shuffle7!($a, $b, $c, $d, $e, $f, 6), - _ => shuffle7!($a, $b, $c, $d, $e, $f, 7), - } - }; - } - macro_rules! shuffle5 { - ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr) => { - match (imm8 >> 5) & 0x1 { - 0 => shuffle6!($a, $b, $c, $d, $e, 12), - _ => shuffle6!($a, $b, $c, $d, $e, 13), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_pd(a, b, $imm8) }; } - macro_rules! shuffle4 { - ($a:expr, $b:expr, $c:expr, $d:expr) => { - match (imm8 >> 4) & 0x1 { - 0 => shuffle5!($a, $b, $c, $d, 4), - _ => shuffle5!($a, $b, $c, $d, 5), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_pd().as_f64x8(); + transmute(simd_select_bitmask(k, r.as_f64x8(), zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_pd&expand=5187) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufpd, imm8 = 9))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shuffle_pd( + src: __m256d, + k: __mmask8, + a: __m256d, + b: __m256d, + imm8: i32, +) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_pd(a, b, $imm8) }; } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr) => { - match (imm8 >> 3) & 0x1 { - 0 => shuffle4!($a, $b, $c, 10), - _ => shuffle4!($a, $b, $c, 11), - } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x4(), src.as_f64x4())) +} + +/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_pd&expand=5188) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufpd, imm8 = 9))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shuffle_pd(k: __mmask8, a: __m256d, b: __m256d, imm8: i32) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_pd(a, b, $imm8) }; } - macro_rules! shuffle2 { - ($a:expr, $b:expr) => { - match (imm8 >> 2) & 0x1 { - 0 => shuffle3!($a, $b, 2), - _ => shuffle3!($a, $b, 3), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, r.as_f64x4(), zero)) +} + +/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shuffle_pd&expand=5184) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufpd, imm8 = 9))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shuffle_pd( + src: __m128d, + k: __mmask8, + a: __m128d, + b: __m128d, + imm8: i32, +) -> __m128d { + macro_rules! call { + ($imm8:expr) => { + _mm_shuffle_pd(a, b, $imm8) }; } - macro_rules! shuffle1 { - ($a:expr) => { - match (imm8 >> 1) & 0x1 { - 0 => shuffle2!($a, 8), - _ => shuffle2!($a, 9), - } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x2(), src.as_f64x2())) +} + +/// Shuffle double-precision (64-bit) floating-point elements within 128-bit lanes using the control in imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shuffle_pd&expand=5185) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufpd, imm8 = 9))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shuffle_pd(k: __mmask8, a: __m128d, b: __m128d, imm8: i32) -> __m128d { + macro_rules! call { + ($imm8:expr) => { + _mm_shuffle_pd(a, b, $imm8) }; } - let shuffle = match imm8 & 0x1 { - 0 => shuffle1!(0), - _ => shuffle1!(1), - }; - - let zero = _mm512_setzero_pd().as_f64x8(); - transmute(simd_select_bitmask(k, shuffle, zero)) + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, r.as_f64x2(), zero)) } /// Shuffle 128-bits (composed of 4 32-bit integers) selected by imm8 from a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_shuffle_i32&expand=5177) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_i32&expand=5177) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vshufi64x2, imm8 = 0b10111111))] //should be vshufi32x4, but generate vshufi64x2 +#[cfg_attr(test, assert_instr(vshufi64x2, imm8 = 0b10010101))] //should be vshufi32x4 #[rustc_args_required_const(2)] pub unsafe fn _mm512_shuffle_i32x4(a: __m512i, b: __m512i, imm8: i32) -> __m512i { assert!(imm8 >= 0 && imm8 <= 255); @@ -12798,10 +23001,10 @@ pub unsafe fn _mm512_shuffle_i32x4(a: __m512i, b: __m512i, imm8: i32) -> __m512i /// Shuffle 128-bits (composed of 4 32-bit integers) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_shuffle_i32x&expand=5175) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_i32x&expand=5175) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vshufi32x4, imm8 = 0b10111111))] +#[cfg_attr(test, assert_instr(vshufi32x4, imm8 = 0b10110101))] #[rustc_args_required_const(4)] pub unsafe fn _mm512_mask_shuffle_i32x4( src: __m512i, @@ -12810,84 +23013,21 @@ pub unsafe fn _mm512_mask_shuffle_i32x4( b: __m512i, imm8: i32, ) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i32x16(); - let b = b.as_i32x16(); - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr - ) => { - simd_shuffle16( - a, - b, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 16, 17, 18, 19), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 20, 21, 22, 23), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 24, 25, 26, 27), - _ => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 28, 29, 30, 31), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 16, 17, 18, 19), - 1 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 20, 21, 22, 23), - 2 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 24, 25, 26, 27), - _ => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 28, 29, 30, 31), - } - }; - } - macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, $i, $m, 0, 1, 2, 3), - 1 => shuffle2!($a, $e, $i, $m, 4, 5, 6, 7), - 2 => shuffle2!($a, $e, $i, $m, 8, 9, 10, 11), - _ => shuffle2!($a, $e, $i, $m, 12, 13, 14, 15), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_i32x4(a, b, $imm8) }; } - let shuffle = match imm8 & 0x3 { - 0 => shuffle1!(0, 1, 2, 3), - 1 => shuffle1!(4, 5, 6, 7), - 2 => shuffle1!(8, 9, 10, 11), - _ => shuffle1!(12, 13, 14, 15), - }; - - transmute(simd_select_bitmask(k, shuffle, src.as_i32x16())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x16(), src.as_i32x16())) } /// Shuffle 128-bits (composed of 4 32-bit integers) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_shuffle_i32&expand=5176) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_i32&expand=5176) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vshufi32x4, imm8 = 0b10111111))] +#[cfg_attr(test, assert_instr(vshufi32x4, imm8 = 0b10110101))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_shuffle_i32x4( k: __mmask16, @@ -12895,11 +23035,29 @@ pub unsafe fn _mm512_maskz_shuffle_i32x4( b: __m512i, imm8: i32, ) -> __m512i { + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_i32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, r.as_i32x16(), zero)) +} + +/// Shuffle 128-bits (composed of 4 32-bit integers) selected by imm8 from a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shuffle_i32x4&expand=5174) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b01))] //should be vshufi32x4 +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shuffle_i32x4(a: __m256i, b: __m256i, imm8: i32) -> __m256i { assert!(imm8 >= 0 && imm8 <= 255); let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i32x16(); - let b = b.as_i32x16(); - macro_rules! shuffle4 { + let a = a.as_i32x8(); + let b = b.as_i32x8(); + macro_rules! shuffle2 { ( $a:expr, $b:expr, @@ -12908,69 +23066,75 @@ pub unsafe fn _mm512_maskz_shuffle_i32x4( $e:expr, $f:expr, $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr + $h:expr ) => { - simd_shuffle16( - a, - b, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 16, 17, 18, 19), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 20, 21, 22, 23), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 24, 25, 26, 27), - _ => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 28, 29, 30, 31), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 16, 17, 18, 19), - 1 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 20, 21, 22, 23), - 2 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 24, 25, 26, 27), - _ => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 28, 29, 30, 31), - } + simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) }; } macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, $i, $m, 0, 1, 2, 3), - 1 => shuffle2!($a, $e, $i, $m, 4, 5, 6, 7), - 2 => shuffle2!($a, $e, $i, $m, 8, 9, 10, 11), - _ => shuffle2!($a, $e, $i, $m, 12, 13, 14, 15), + ($a:expr, $b:expr, $c: expr, $d: expr) => { + match (imm8 >> 1) & 0x1 { + 0 => shuffle2!($a, $b, $c, $d, 8, 9, 10, 11), + _ => shuffle2!($a, $b, $c, $d, 12, 13, 14, 15), } }; } - let shuffle = match imm8 & 0x3 { + let r: i32x8 = match imm8 & 0x1 { 0 => shuffle1!(0, 1, 2, 3), - 1 => shuffle1!(4, 5, 6, 7), - 2 => shuffle1!(8, 9, 10, 11), - _ => shuffle1!(12, 13, 14, 15), + _ => shuffle1!(4, 5, 6, 7), }; + transmute(r) +} - let zero = _mm512_setzero_si512().as_i32x16(); - transmute(simd_select_bitmask(k, shuffle, zero)) +/// Shuffle 128-bits (composed of 4 32-bit integers) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_i32x4&expand=5172) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufi32x4, imm8 = 0b11))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shuffle_i32x4( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_i32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x8(), src.as_i32x8())) +} + +/// Shuffle 128-bits (composed of 4 32-bit integers) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_i32x4&expand=5173) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufi32x4, imm8 = 0b11))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shuffle_i32x4( + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_i32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r.as_i32x8(), zero)) } /// Shuffle 128-bits (composed of 2 64-bit integers) selected by imm8 from a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_shuffle_i64x2&expand=5183) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_i64x2&expand=5183) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufi64x2, imm8 = 0b10111111))] @@ -13032,7 +23196,7 @@ pub unsafe fn _mm512_shuffle_i64x2(a: __m512i, b: __m512i, imm8: i32) -> __m512i /// Shuffle 128-bits (composed of 2 64-bit integers) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_shuffle_i64x&expand=5181) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_i64x&expand=5181) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufi64x2, imm8 = 0b10111111))] @@ -13044,65 +23208,18 @@ pub unsafe fn _mm512_mask_shuffle_i64x2( b: __m512i, imm8: i32, ) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr - ) => { - simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, 8, 9), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, 10, 11), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, 12, 13), - _ => shuffle4!($a, $b, $c, $e, $f, $g, 14, 15), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, 8, 9), - 1 => shuffle3!($a, $b, $e, $f, 10, 11), - 2 => shuffle3!($a, $b, $e, $f, 12, 13), - _ => shuffle3!($a, $b, $e, $f, 14, 15), - } - }; - } - macro_rules! shuffle1 { - ($a:expr, $e:expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, 0, 1), - 1 => shuffle2!($a, $e, 2, 3), - 2 => shuffle2!($a, $e, 4, 5), - _ => shuffle2!($a, $e, 6, 7), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_i64x2(a, b, $imm8) }; } - let shuffle = match imm8 & 0x3 { - 0 => shuffle1!(0, 1), - 1 => shuffle1!(2, 3), - 2 => shuffle1!(4, 5), - _ => shuffle1!(6, 7), - }; - - transmute(simd_select_bitmask(k, shuffle, src.as_i64x8())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x8(), src.as_i64x8())) } /// Shuffle 128-bits (composed of 2 64-bit integers) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_shuffle_i64&expand=5182) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_i64&expand=5182) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshufi64x2, imm8 = 0b10111111))] @@ -13113,153 +23230,107 @@ pub unsafe fn _mm512_maskz_shuffle_i64x2( b: __m512i, imm8: i32, ) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr - ) => { - simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, 8, 9), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, 10, 11), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, 12, 13), - _ => shuffle4!($a, $b, $c, $e, $f, $g, 14, 15), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, 8, 9), - 1 => shuffle3!($a, $b, $e, $f, 10, 11), - 2 => shuffle3!($a, $b, $e, $f, 12, 13), - _ => shuffle3!($a, $b, $e, $f, 14, 15), - } - }; - } - macro_rules! shuffle1 { - ($a:expr, $e:expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, 0, 1), - 1 => shuffle2!($a, $e, 2, 3), - 2 => shuffle2!($a, $e, 4, 5), - _ => shuffle2!($a, $e, 6, 7), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_i64x2(a, b, $imm8) }; } - let shuffle = match imm8 & 0x3 { - 0 => shuffle1!(0, 1), - 1 => shuffle1!(2, 3), - 2 => shuffle1!(4, 5), - _ => shuffle1!(6, 7), - }; - + let r = constify_imm8_sae!(imm8, call); let zero = _mm512_setzero_si512().as_i64x8(); - transmute(simd_select_bitmask(k, shuffle, zero)) + transmute(simd_select_bitmask(k, r.as_i64x8(), zero)) } -/// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst. +/// Shuffle 128-bits (composed of 2 64-bit integers) selected by imm8 from a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_shuffle_f32x4&expand=5165) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shuffle_i64x2&expand=5180) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vshuff64x2, imm8 = 0b10111111))] //should be vshuff32x4, but generate vshuff64x2 +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b01))] //should be vshufi64x2 #[rustc_args_required_const(2)] -pub unsafe fn _mm512_shuffle_f32x4(a: __m512, b: __m512, imm8: i32) -> __m512 { +pub unsafe fn _mm256_shuffle_i64x2(a: __m256i, b: __m256i, imm8: i32) -> __m256i { assert!(imm8 >= 0 && imm8 <= 255); let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { + let a = a.as_i64x4(); + let b = b.as_i64x4(); + macro_rules! shuffle2 { ( $a:expr, $b:expr, $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr + $d:expr ) => { - simd_shuffle16( - a, - b, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) + simd_shuffle4(a, b, [$a, $b, $c, $d]) }; } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 16, 17, 18, 19), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 20, 21, 22, 23), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 24, 25, 26, 27), - _ => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 28, 29, 30, 31), + macro_rules! shuffle1 { + ($a:expr, $b:expr) => { + match (imm8 >> 1) & 0x1 { + 0 => shuffle2!($a, $b, 4, 5), + _ => shuffle2!($a, $b, 6, 7), } }; } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 16, 17, 18, 19), - 1 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 20, 21, 22, 23), - 2 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 24, 25, 26, 27), - _ => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 28, 29, 30, 31), - } + let r: i64x4 = match imm8 & 0x1 { + 0 => shuffle1!(0, 1), + _ => shuffle1!(2, 3), + }; + transmute(r) +} + +/// Shuffle 128-bits (composed of 2 64-bit integers) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_i64x2&expand=5178) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufi64x2, imm8 = 0b11))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shuffle_i64x2( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_i64x2(a, b, $imm8) }; } - macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, $i, $m, 0, 1, 2, 3), - 1 => shuffle2!($a, $e, $i, $m, 4, 5, 6, 7), - 2 => shuffle2!($a, $e, $i, $m, 8, 9, 10, 11), - _ => shuffle2!($a, $e, $i, $m, 12, 13, 14, 15), - } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x4(), src.as_i64x4())) +} + +/// Shuffle 128-bits (composed of 2 64-bit integers) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_i64x2&expand=5179) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshufi64x2, imm8 = 0b11))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shuffle_i64x2( + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_i64x2(a, b, $imm8) }; } - match imm8 & 0x3 { - 0 => shuffle1!(0, 1, 2, 3), - 1 => shuffle1!(4, 5, 6, 7), - 2 => shuffle1!(8, 9, 10, 11), - _ => shuffle1!(12, 13, 14, 15), - } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, r.as_i64x4(), zero)) } -/// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_shuffle_f32&expand=5163) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_f32x4&expand=5165) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vshuff32x4, imm8 = 0b10111111))] -#[rustc_args_required_const(4)] -pub unsafe fn _mm512_mask_shuffle_f32x4( - src: __m512, - k: __mmask16, - a: __m512, - b: __m512, - imm8: i32, -) -> __m512 { +#[cfg_attr(test, assert_instr(vshuff64x2, imm8 = 0b10111111))] //should be vshuff32x4, but generate vshuff64x2 +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shuffle_f32x4(a: __m512, b: __m512, imm8: i32) -> __m512 { assert!(imm8 >= 0 && imm8 <= 255); let imm8 = (imm8 & 0xFF) as u8; macro_rules! shuffle4 { @@ -13320,27 +23391,68 @@ pub unsafe fn _mm512_mask_shuffle_f32x4( } }; } - let shuffle = match imm8 & 0x3 { + match imm8 & 0x3 { 0 => shuffle1!(0, 1, 2, 3), 1 => shuffle1!(4, 5, 6, 7), 2 => shuffle1!(8, 9, 10, 11), _ => shuffle1!(12, 13, 14, 15), - }; + } +} - transmute(simd_select_bitmask(k, shuffle, src.as_f32x16())) +/// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_f32&expand=5163) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vshuff32x4, imm8 = 0b10111111))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shuffle_f32x4( + src: __m512, + k: __mmask16, + a: __m512, + b: __m512, + imm8: i32, +) -> __m512 { + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_f32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x16(), src.as_f32x16())) } /// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_shuffle_f32&expand=5164) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_f32&expand=5164) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshuff32x4, imm8 = 0b10111111))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_shuffle_f32x4(k: __mmask16, a: __m512, b: __m512, imm8: i32) -> __m512 { + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_f32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_ps().as_f32x16(); + transmute(simd_select_bitmask(k, r.as_f32x16(), zero)) +} + +/// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shuffle_f32x4&expand=5162) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b01))] //should be vshuff32x4 +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shuffle_f32x4(a: __m256, b: __m256, imm8: i32) -> __m256 { assert!(imm8 >= 0 && imm8 <= 255); let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { + let a = a.as_f32x8(); + let b = b.as_f32x8(); + macro_rules! shuffle2 { ( $a:expr, $b:expr, @@ -13349,69 +23461,71 @@ pub unsafe fn _mm512_maskz_shuffle_f32x4(k: __mmask16, a: __m512, b: __m512, imm $e:expr, $f:expr, $g:expr, - $h:expr, - $i:expr, - $j:expr, - $k:expr, - $l:expr, - $m:expr, - $n:expr, - $o:expr, - $p:expr + $h:expr ) => { - simd_shuffle16( - a, - b, - [ - $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, - ], - ) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr, $i:expr, $j:expr, $k:expr, $m:expr, $n:expr, $o:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 16, 17, 18, 19), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 20, 21, 22, 23), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 24, 25, 26, 27), - _ => shuffle4!($a, $b, $c, $e, $f, $g, $i, $j, $k, $m, $n, $o, 28, 29, 30, 31), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr, $i:expr, $j:expr, $m:expr, $n:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 16, 17, 18, 19), - 1 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 20, 21, 22, 23), - 2 => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 24, 25, 26, 27), - _ => shuffle3!($a, $b, $e, $f, $i, $j, $m, $n, 28, 29, 30, 31), - } + simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) }; } macro_rules! shuffle1 { - ($a:expr, $e:expr, $i: expr, $m: expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, $i, $m, 0, 1, 2, 3), - 1 => shuffle2!($a, $e, $i, $m, 4, 5, 6, 7), - 2 => shuffle2!($a, $e, $i, $m, 8, 9, 10, 11), - _ => shuffle2!($a, $e, $i, $m, 12, 13, 14, 15), + ($a:expr, $b:expr, $c: expr, $d: expr) => { + match (imm8 >> 1) & 0x1 { + 0 => shuffle2!($a, $b, $c, $d, 8, 9, 10, 11), + _ => shuffle2!($a, $b, $c, $d, 12, 13, 14, 15), } }; } - let shuffle = match imm8 & 0x3 { + let r: f32x8 = match imm8 & 0x1 { 0 => shuffle1!(0, 1, 2, 3), - 1 => shuffle1!(4, 5, 6, 7), - 2 => shuffle1!(8, 9, 10, 11), - _ => shuffle1!(12, 13, 14, 15), + _ => shuffle1!(4, 5, 6, 7), }; - let zero = _mm512_setzero_ps().as_f32x16(); - transmute(simd_select_bitmask(k, shuffle, zero)) + transmute(r) +} + +/// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_f32x4&expand=5160) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshuff32x4, imm8 = 0b11))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shuffle_f32x4( + src: __m256, + k: __mmask8, + a: __m256, + b: __m256, + imm8: i32, +) -> __m256 { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_f32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x8(), src.as_f32x8())) +} + +/// Shuffle 128-bits (composed of 4 single-precision (32-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_f32x4&expand=5161) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshuff32x4, imm8 = 0b11))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shuffle_f32x4(k: __mmask8, a: __m256, b: __m256, imm8: i32) -> __m256 { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_f32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, r.as_f32x8(), zero)) } /// Shuffle 128-bits (composed of 2 double-precision (64-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_shuffle_f64x2&expand=5171) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shuffle_f64x2&expand=5171) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshuff64x2, imm8 = 0b10111111))] @@ -13473,7 +23587,7 @@ pub unsafe fn _mm512_shuffle_f64x2(a: __m512d, b: __m512d, imm8: i32) -> __m512d /// Shuffle 128-bits (composed of 2 double-precision (64-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_shuffle_f64x2&expand=5169) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shuffle_f64x2&expand=5169) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshuff64x2, imm8 = 0b10111111))] @@ -13485,65 +23599,18 @@ pub unsafe fn _mm512_mask_shuffle_f64x2( b: __m512d, imm8: i32, ) -> __m512d { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { - ( - $a:expr, - $b:expr, - $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr - ) => { - simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, 8, 9), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, 10, 11), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, 12, 13), - _ => shuffle4!($a, $b, $c, $e, $f, $g, 14, 15), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, 8, 9), - 1 => shuffle3!($a, $b, $e, $f, 10, 11), - 2 => shuffle3!($a, $b, $e, $f, 12, 13), - _ => shuffle3!($a, $b, $e, $f, 14, 15), - } - }; - } - macro_rules! shuffle1 { - ($a:expr, $e:expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, 0, 1), - 1 => shuffle2!($a, $e, 2, 3), - 2 => shuffle2!($a, $e, 4, 5), - _ => shuffle2!($a, $e, 6, 7), - } + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_f64x2(a, b, $imm8) }; } - let shuffle = match imm8 & 0x3 { - 0 => shuffle1!(0, 1), - 1 => shuffle1!(2, 3), - 2 => shuffle1!(4, 5), - _ => shuffle1!(6, 7), - }; - - transmute(simd_select_bitmask(k, shuffle, src.as_f64x8())) + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x8(), src.as_f64x8())) } /// Shuffle 128-bits (composed of 2 double-precision (64-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_shuffle_f64x2&expand=5170) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shuffle_f64x2&expand=5170) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vshuff64x2, imm8 = 0b10111111))] @@ -13554,66 +23621,102 @@ pub unsafe fn _mm512_maskz_shuffle_f64x2( b: __m512d, imm8: i32, ) -> __m512d { + macro_rules! call { + ($imm8:expr) => { + _mm512_shuffle_f64x2(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_pd().as_f64x8(); + transmute(simd_select_bitmask(k, r.as_f64x8(), zero)) +} + +/// Shuffle 128-bits (composed of 2 double-precision (64-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shuffle_f64x2&expand=5168) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vperm, imm8 = 0b01))] //should be vshuff64x2 +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shuffle_f64x2(a: __m256d, b: __m256d, imm8: i32) -> __m256d { assert!(imm8 >= 0 && imm8 <= 255); let imm8 = (imm8 & 0xFF) as u8; - macro_rules! shuffle4 { + let a = a.as_f64x4(); + let b = b.as_f64x4(); + macro_rules! shuffle2 { ( $a:expr, $b:expr, $c:expr, - $d:expr, - $e:expr, - $f:expr, - $g:expr, - $h:expr + $d:expr ) => { - simd_shuffle8(a, b, [$a, $b, $c, $d, $e, $f, $g, $h]) - }; - } - macro_rules! shuffle3 { - ($a:expr, $b:expr, $c:expr, $e:expr, $f:expr, $g:expr) => { - match (imm8 >> 6) & 0x3 { - 0 => shuffle4!($a, $b, $c, $e, $f, $g, 8, 9), - 1 => shuffle4!($a, $b, $c, $e, $f, $g, 10, 11), - 2 => shuffle4!($a, $b, $c, $e, $f, $g, 12, 13), - _ => shuffle4!($a, $b, $c, $e, $f, $g, 14, 15), - } - }; - } - macro_rules! shuffle2 { - ($a:expr, $b:expr, $e:expr, $f:expr) => { - match (imm8 >> 4) & 0x3 { - 0 => shuffle3!($a, $b, $e, $f, 8, 9), - 1 => shuffle3!($a, $b, $e, $f, 10, 11), - 2 => shuffle3!($a, $b, $e, $f, 12, 13), - _ => shuffle3!($a, $b, $e, $f, 14, 15), - } + simd_shuffle4(a, b, [$a, $b, $c, $d]) }; } macro_rules! shuffle1 { - ($a:expr, $e:expr) => { - match (imm8 >> 2) & 0x3 { - 0 => shuffle2!($a, $e, 0, 1), - 1 => shuffle2!($a, $e, 2, 3), - 2 => shuffle2!($a, $e, 4, 5), - _ => shuffle2!($a, $e, 6, 7), + ($a:expr, $b:expr) => { + match (imm8 >> 1) & 0x1 { + 0 => shuffle2!($a, $b, 4, 5), + _ => shuffle2!($a, $b, 6, 7), } }; } - let shuffle = match imm8 & 0x3 { + let r: f64x4 = match imm8 & 0x1 { 0 => shuffle1!(0, 1), - 1 => shuffle1!(2, 3), - 2 => shuffle1!(4, 5), - _ => shuffle1!(6, 7), + _ => shuffle1!(2, 3), }; + transmute(r) +} - let zero = _mm512_setzero_pd().as_f64x8(); - transmute(simd_select_bitmask(k, shuffle, zero)) +/// Shuffle 128-bits (composed of 2 double-precision (64-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shuffle_f64x2&expand=5166) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshuff64x2, imm8 = 0b11))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shuffle_f64x2( + src: __m256d, + k: __mmask8, + a: __m256d, + b: __m256d, + imm8: i32, +) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_f64x2(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x4(), src.as_f64x4())) +} + +/// Shuffle 128-bits (composed of 2 double-precision (64-bit) floating-point elements) selected by imm8 from a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shuffle_f64x2&expand=5167) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vshuff64x2, imm8 = 0b11))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shuffle_f64x2( + k: __mmask8, + a: __m256d, + b: __m256d, + imm8: i32, +) -> __m256d { + macro_rules! call { + ($imm8:expr) => { + _mm256_shuffle_f64x2(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, r.as_f64x4(), zero)) } /// Extract 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from a, selected with imm8, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_extractf32x4_ps&expand=2442) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extractf32x4_ps&expand=2442) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13633,7 +23736,7 @@ pub unsafe fn _mm512_extractf32x4_ps(a: __m512, imm8: i32) -> __m128 { /// Extract 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from a, selected with imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_extractf32x4_ps&expand=2443) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extractf32x4_ps&expand=2443) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13647,19 +23750,18 @@ pub unsafe fn _mm512_mask_extractf32x4_ps( a: __m512, imm8: i32, ) -> __m128 { - assert!(imm8 >= 0 && imm8 <= 3); - let extract: __m128 = match imm8 & 0x3 { - 0 => simd_shuffle4(a, _mm512_undefined_ps(), [0, 1, 2, 3]), - 1 => simd_shuffle4(a, _mm512_undefined_ps(), [4, 5, 6, 7]), - 2 => simd_shuffle4(a, _mm512_undefined_ps(), [8, 9, 10, 11]), - _ => simd_shuffle4(a, _mm512_undefined_ps(), [12, 13, 14, 15]), - }; - transmute(simd_select_bitmask(k, extract.as_f32x4(), src.as_f32x4())) + macro_rules! call { + ($imm8:expr) => { + _mm512_extractf32x4_ps(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x4(), src.as_f32x4())) } /// Extract 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from a, selected with imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_extractf32x4_ps&expand=2444) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extractf32x4_ps&expand=2444) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13668,20 +23770,83 @@ pub unsafe fn _mm512_mask_extractf32x4_ps( )] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_extractf32x4_ps(k: __mmask8, a: __m512, imm8: i32) -> __m128 { - assert!(imm8 >= 0 && imm8 <= 3); - let extract: __m128 = match imm8 & 0x3 { - 0 => simd_shuffle4(a, _mm512_undefined_ps(), [0, 1, 2, 3]), - 1 => simd_shuffle4(a, _mm512_undefined_ps(), [4, 5, 6, 7]), - 2 => simd_shuffle4(a, _mm512_undefined_ps(), [8, 9, 10, 11]), - _ => simd_shuffle4(a, _mm512_undefined_ps(), [12, 13, 14, 15]), - }; + macro_rules! call { + ($imm8:expr) => { + _mm512_extractf32x4_ps(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, r.as_f32x4(), zero)) +} + +/// Extract 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from a, selected with imm8, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_extractf32x4_ps&expand=2439) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vextract, imm8 = 1) //should be vextractf32x4 +)] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_extractf32x4_ps(a: __m256, imm8: i32) -> __m128 { + assert!(imm8 >= 0 && imm8 <= 1); + match imm8 & 0x1 { + 0 => simd_shuffle4(a, _mm256_undefined_ps(), [0, 1, 2, 3]), + _ => simd_shuffle4(a, _mm256_undefined_ps(), [4, 5, 6, 7]), + } +} + +/// Extract 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from a, selected with imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_extractf32x4_ps&expand=2440) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vextractf32x4, imm8 = 1) +)] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_extractf32x4_ps( + src: __m128, + k: __mmask8, + a: __m256, + imm8: i32, +) -> __m128 { + macro_rules! call { + ($imm8:expr) => { + _mm256_extractf32x4_ps(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x4(), src.as_f32x4())) +} + +/// Extract 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from a, selected with imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_extractf32x4_ps&expand=2441) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vextractf32x4, imm8 = 1) +)] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_extractf32x4_ps(k: __mmask8, a: __m256, imm8: i32) -> __m128 { + macro_rules! call { + ($imm8:expr) => { + _mm256_extractf32x4_ps(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); let zero = _mm_setzero_ps().as_f32x4(); - transmute(simd_select_bitmask(k, extract.as_f32x4(), zero)) + transmute(simd_select_bitmask(k, r.as_f32x4(), zero)) } /// Extract 256 bits (composed of 4 packed 64-bit integers) from a, selected with imm8, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_extracti64x4_epi64&expand=2473) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extracti64x4_epi64&expand=2473) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13699,7 +23864,7 @@ pub unsafe fn _mm512_extracti64x4_epi64(a: __m512i, imm8: i32) -> __m256i { /// Extract 256 bits (composed of 4 packed 64-bit integers) from a, selected with imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_extracti64x4_epi64&expand=2474) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extracti64x4_epi64&expand=2474) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13713,17 +23878,18 @@ pub unsafe fn _mm512_mask_extracti64x4_epi64( a: __m512i, imm8: i32, ) -> __m256i { - assert!(imm8 >= 0 && imm8 <= 1); - let extract = match imm8 & 0x1 { - 0 => simd_shuffle4(a, _mm512_set1_epi64(0), [0, 1, 2, 3]), - _ => simd_shuffle4(a, _mm512_set1_epi64(0), [4, 5, 6, 7]), - }; - transmute(simd_select_bitmask(k, extract, src.as_i64x4())) + macro_rules! call { + ($imm8:expr) => { + _mm512_extracti64x4_epi64(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x4(), src.as_i64x4())) } /// Extract 256 bits (composed of 4 packed 64-bit integers) from a, selected with imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_extracti64x4_epi64&expand=2475) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extracti64x4_epi64&expand=2475) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13732,18 +23898,19 @@ pub unsafe fn _mm512_mask_extracti64x4_epi64( )] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_extracti64x4_epi64(k: __mmask8, a: __m512i, imm8: i32) -> __m256i { - assert!(imm8 >= 0 && imm8 <= 1); - let extract: __m256i = match imm8 & 0x1 { - 0 => simd_shuffle4(a, _mm512_set1_epi64(0), [0, 1, 2, 3]), - _ => simd_shuffle4(a, _mm512_set1_epi64(0), [4, 5, 6, 7]), - }; + macro_rules! call { + ($imm8:expr) => { + _mm512_extracti64x4_epi64(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); let zero = _mm256_setzero_si256().as_i64x4(); - transmute(simd_select_bitmask(k, extract.as_i64x4(), zero)) + transmute(simd_select_bitmask(k, r.as_i64x4(), zero)) } /// Extract 256 bits (composed of 4 packed double-precision (64-bit) floating-point elements) from a, selected with imm8, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_extractf64x4_pd&expand=2454) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extractf64x4_pd&expand=2454) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13761,7 +23928,7 @@ pub unsafe fn _mm512_extractf64x4_pd(a: __m512d, imm8: i32) -> __m256d { /// Extract 256 bits (composed of 4 packed double-precision (64-bit) floating-point elements) from a, selected with imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_extractf64x4_pd&expand=2455) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extractf64x4_pd&expand=2455) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13775,17 +23942,18 @@ pub unsafe fn _mm512_mask_extractf64x4_pd( a: __m512d, imm8: i32, ) -> __m256d { - assert!(imm8 >= 0 && imm8 <= 1); - let extract = match imm8 & 0x1 { - 0 => simd_shuffle4(a, _mm512_undefined_pd(), [0, 1, 2, 3]), - _ => simd_shuffle4(a, _mm512_undefined_pd(), [4, 5, 6, 7]), - }; - transmute(simd_select_bitmask(k, extract, src)) + macro_rules! call { + ($imm8:expr) => { + _mm512_extractf64x4_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x4(), src.as_f64x4())) } /// Extract 256 bits (composed of 4 packed double-precision (64-bit) floating-point elements) from a, selected with imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_extractf64x4_pd&expand=2456) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extractf64x4_pd&expand=2456) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13794,18 +23962,19 @@ pub unsafe fn _mm512_mask_extractf64x4_pd( )] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_extractf64x4_pd(k: __mmask8, a: __m512d, imm8: i32) -> __m256d { - assert!(imm8 >= 0 && imm8 <= 1); - let extract = match imm8 & 0x1 { - 0 => simd_shuffle4(a, _mm512_undefined_pd(), [0, 1, 2, 3]), - _ => simd_shuffle4(a, _mm512_undefined_pd(), [4, 5, 6, 7]), - }; - let zero = _mm256_setzero_pd(); - transmute(simd_select_bitmask(k, extract, zero)) + macro_rules! call { + ($imm8:expr) => { + _mm512_extractf64x4_pd(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, r.as_f64x4(), zero)) } /// Extract 128 bits (composed of 4 packed 32-bit integers) from a, selected with imm8, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_extracti32x4_epi32&expand=2461) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_extracti32x4_epi32&expand=2461) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13828,7 +23997,7 @@ pub unsafe fn _mm512_extracti32x4_epi32(a: __m512i, imm8: i32) -> __m128i { /// Extract 128 bits (composed of 4 packed 32-bit integers) from a, selected with imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_extracti32x4_epi32&expand=2462) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_extracti32x4_epi32&expand=2462) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13842,21 +24011,18 @@ pub unsafe fn _mm512_mask_extracti32x4_epi32( a: __m512i, imm8: i32, ) -> __m128i { - assert!(imm8 >= 0 && imm8 <= 3); - let a = a.as_i32x16(); - let undefined = _mm512_undefined_epi32().as_i32x16(); - let extract: i32x4 = match imm8 & 0x3 { - 0 => simd_shuffle4(a, undefined, [0, 1, 2, 3]), - 1 => simd_shuffle4(a, undefined, [4, 5, 6, 7]), - 2 => simd_shuffle4(a, undefined, [8, 9, 10, 11]), - _ => simd_shuffle4(a, undefined, [12, 13, 14, 15]), - }; - transmute(simd_select_bitmask(k, extract, src.as_i32x4())) + macro_rules! call { + ($imm8:expr) => { + _mm512_extracti32x4_epi32(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x4(), src.as_i32x4())) } /// Extract 128 bits (composed of 4 packed 32-bit integers) from a, selected with imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_extracti32x4_epi32&expand=2463) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_extracti32x4_epi32&expand=2463) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr( @@ -13865,22 +24031,86 @@ pub unsafe fn _mm512_mask_extracti32x4_epi32( )] #[rustc_args_required_const(2)] pub unsafe fn _mm512_maskz_extracti32x4_epi32(k: __mmask8, a: __m512i, imm8: i32) -> __m128i { - assert!(imm8 >= 0 && imm8 <= 3); - let a = a.as_i32x16(); - let undefined = _mm512_undefined_epi32().as_i32x16(); - let extract: i32x4 = match imm8 & 0x3 { + macro_rules! call { + ($imm8:expr) => { + _mm512_extracti32x4_epi32(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r.as_i32x4(), zero)) +} + +/// Extract 128 bits (composed of 4 packed 32-bit integers) from a, selected with imm8, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_extracti32x4_epi32&expand=2458) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vextract, imm8 = 1) //should be vextracti32x4 +)] +#[rustc_args_required_const(1)] +pub unsafe fn _mm256_extracti32x4_epi32(a: __m256i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 1); + let a = a.as_i32x8(); + let undefined = _mm256_undefined_si256().as_i32x8(); + let extract: i32x4 = match imm8 & 0x1 { 0 => simd_shuffle4(a, undefined, [0, 1, 2, 3]), - 1 => simd_shuffle4(a, undefined, [4, 5, 6, 7]), - 2 => simd_shuffle4(a, undefined, [8, 9, 10, 11]), - _ => simd_shuffle4(a, undefined, [12, 13, 14, 15]), + _ => simd_shuffle4(a, undefined, [4, 5, 6, 7]), }; + transmute(extract) +} + +/// Extract 128 bits (composed of 4 packed 32-bit integers) from a, selected with imm8, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_extracti32x4_epi32&expand=2459) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vextracti32x4, imm8 = 1) +)] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_mask_extracti32x4_epi32( + src: __m128i, + k: __mmask8, + a: __m256i, + imm8: i32, +) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm256_extracti32x4_epi32(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x4(), src.as_i32x4())) +} + +/// Extract 128 bits (composed of 4 packed 32-bit integers) from a, selected with imm8, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_extracti32x4_epi32&expand=2460) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vextracti32x4, imm8 = 1) +)] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_maskz_extracti32x4_epi32(k: __mmask8, a: __m256i, imm8: i32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm256_extracti32x4_epi32(a, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); let zero = _mm_setzero_si128().as_i32x4(); - transmute(simd_select_bitmask(k, extract, zero)) + transmute(simd_select_bitmask(k, r.as_i32x4(), zero)) } /// Duplicate even-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_moveldup_ps&expand=3862) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_moveldup_ps&expand=3862) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovsldup))] @@ -13891,7 +24121,7 @@ pub unsafe fn _mm512_moveldup_ps(a: __m512) -> __m512 { /// Duplicate even-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_moveldup_ps&expand=3860) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_moveldup_ps&expand=3860) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovsldup))] @@ -13902,7 +24132,7 @@ pub unsafe fn _mm512_mask_moveldup_ps(src: __m512, k: __mmask16, a: __m512) -> _ /// Duplicate even-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_moveldup_ps&expand=3861) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_moveldup_ps&expand=3861) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovsldup))] @@ -13912,6 +24142,52 @@ pub unsafe fn _mm512_maskz_moveldup_ps(k: __mmask16, a: __m512) -> __m512 { transmute(simd_select_bitmask(k, mov, zero)) } +/// Duplicate even-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_moveldup_ps&expand=3857) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovsldup))] +pub unsafe fn _mm256_mask_moveldup_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + let mov = _mm256_moveldup_ps(a); + transmute(simd_select_bitmask(k, mov.as_f32x8(), src.as_f32x8())) +} + +/// Duplicate even-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_moveldup_ps&expand=3858) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovsldup))] +pub unsafe fn _mm256_maskz_moveldup_ps(k: __mmask8, a: __m256) -> __m256 { + let mov = _mm256_moveldup_ps(a); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, mov.as_f32x8(), zero)) +} + +/// Duplicate even-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_moveldup_ps&expand=3854) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovsldup))] +pub unsafe fn _mm_mask_moveldup_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + let mov = _mm_moveldup_ps(a); + transmute(simd_select_bitmask(k, mov.as_f32x4(), src.as_f32x4())) +} + +/// Duplicate even-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_moveldup_ps&expand=3855) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovsldup))] +pub unsafe fn _mm_maskz_moveldup_ps(k: __mmask8, a: __m128) -> __m128 { + let mov = _mm_moveldup_ps(a); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, mov.as_f32x4(), zero)) +} + /// Duplicate odd-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_movehdup_ps&expand=3852) @@ -13925,7 +24201,7 @@ pub unsafe fn _mm512_movehdup_ps(a: __m512) -> __m512 { /// Duplicate odd-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_movehdup&expand=3850) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_movehdup&expand=3850) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovshdup))] @@ -13936,7 +24212,7 @@ pub unsafe fn _mm512_mask_movehdup_ps(src: __m512, k: __mmask16, a: __m512) -> _ /// Duplicate odd-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_moveh&expand=3851) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_moveh&expand=3851) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovshdup))] @@ -13946,9 +24222,55 @@ pub unsafe fn _mm512_maskz_movehdup_ps(k: __mmask16, a: __m512) -> __m512 { transmute(simd_select_bitmask(k, mov, zero)) } +/// Duplicate odd-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_movehdup_ps&expand=3847) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovshdup))] +pub unsafe fn _mm256_mask_movehdup_ps(src: __m256, k: __mmask8, a: __m256) -> __m256 { + let mov = _mm256_movehdup_ps(a); + transmute(simd_select_bitmask(k, mov.as_f32x8(), src.as_f32x8())) +} + +/// Duplicate odd-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_movehdup_ps&expand=3848) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovshdup))] +pub unsafe fn _mm256_maskz_movehdup_ps(k: __mmask8, a: __m256) -> __m256 { + let mov = _mm256_movehdup_ps(a); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, mov.as_f32x8(), zero)) +} + +/// Duplicate odd-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_movehdup_ps&expand=3844) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovshdup))] +pub unsafe fn _mm_mask_movehdup_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + let mov = _mm_movehdup_ps(a); + transmute(simd_select_bitmask(k, mov.as_f32x4(), src.as_f32x4())) +} + +/// Duplicate odd-indexed single-precision (32-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_movehdup_ps&expand=3845) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovshdup))] +pub unsafe fn _mm_maskz_movehdup_ps(k: __mmask8, a: __m128) -> __m128 { + let mov = _mm_movehdup_ps(a); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, mov.as_f32x4(), zero)) +} + /// Duplicate even-indexed double-precision (64-bit) floating-point elements from a, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_movedup_pd&expand=3843) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movedup_pd&expand=3843) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovddup))] @@ -13959,7 +24281,7 @@ pub unsafe fn _mm512_movedup_pd(a: __m512d) -> __m512d { /// Duplicate even-indexed double-precision (64-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_movedup_pd&expand=3841) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_movedup_pd&expand=3841) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovddup))] @@ -13970,7 +24292,7 @@ pub unsafe fn _mm512_mask_movedup_pd(src: __m512d, k: __mmask8, a: __m512d) -> _ /// Duplicate even-indexed double-precision (64-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_movedup_pd&expand=3842) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_movedup_pd&expand=3842) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovddup))] @@ -13980,9 +24302,55 @@ pub unsafe fn _mm512_maskz_movedup_pd(k: __mmask8, a: __m512d) -> __m512d { transmute(simd_select_bitmask(k, mov, zero)) } +/// Duplicate even-indexed double-precision (64-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_movedup_pd&expand=3838) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovddup))] +pub unsafe fn _mm256_mask_movedup_pd(src: __m256d, k: __mmask8, a: __m256d) -> __m256d { + let mov = _mm256_movedup_pd(a); + transmute(simd_select_bitmask(k, mov.as_f64x4(), src.as_f64x4())) +} + +/// Duplicate even-indexed double-precision (64-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_movedup_pd&expand=3839) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovddup))] +pub unsafe fn _mm256_maskz_movedup_pd(k: __mmask8, a: __m256d) -> __m256d { + let mov = _mm256_movedup_pd(a); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, mov.as_f64x4(), zero)) +} + +/// Duplicate even-indexed double-precision (64-bit) floating-point elements from a, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_movedup_pd&expand=3835) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovddup))] +pub unsafe fn _mm_mask_movedup_pd(src: __m128d, k: __mmask8, a: __m128d) -> __m128d { + let mov = _mm_movedup_pd(a); + transmute(simd_select_bitmask(k, mov.as_f64x2(), src.as_f64x2())) +} + +/// Duplicate even-indexed double-precision (64-bit) floating-point elements from a, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_movedup_pd&expand=3836) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovddup))] +pub unsafe fn _mm_maskz_movedup_pd(k: __mmask8, a: __m128d) -> __m128d { + let mov = _mm_movedup_pd(a); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, mov.as_f64x2(), zero)) +} + /// Copy a to dst, then insert 128 bits (composed of 4 packed 32-bit integers) from b into dst at the location specified by imm8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_inserti32x4&expand=3174) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_inserti32x4&expand=3174) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf32x4, imm8 = 2))] //should be vinserti32x4 @@ -14014,7 +24382,7 @@ pub unsafe fn _mm512_inserti32x4(a: __m512i, b: __m128i, imm8: i32) -> __m512i { /// Copy a to tmp, then insert 128 bits (composed of 4 packed 32-bit integers) from b into tmp at the location specified by imm8. Store tmp to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_inserti32x4&expand=3175) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_inserti32x4&expand=3175) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinserti32x4, imm8 = 2))] @@ -14026,66 +24394,104 @@ pub unsafe fn _mm512_mask_inserti32x4( b: __m128i, imm8: i32, ) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 3); - let a = a.as_i32x16(); - let b = _mm512_castsi128_si512(b).as_i32x16(); - let insert: i32x16 = match imm8 & 0b11 { - 0 => simd_shuffle16( - a, - b, - [16, 17, 18, 19, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 1 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 2 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 12, 13, 14, 15], - ), - _ => simd_shuffle16(a, b, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19]), - }; - transmute(simd_select_bitmask(k, insert, src.as_i32x16())) + macro_rules! call { + ($imm8:expr) => { + _mm512_inserti32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x16(), src.as_i32x16())) } /// Copy a to tmp, then insert 128 bits (composed of 4 packed 32-bit integers) from b into tmp at the location specified by imm8. Store tmp to dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_inserti32x4&expand=3176) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_inserti32x4&expand=3176) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinserti32x4, imm8 = 2))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_inserti32x4(k: __mmask16, a: __m512i, b: __m128i, imm8: i32) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 3); - let a = a.as_i32x16(); - let b = _mm512_castsi128_si512(b).as_i32x16(); - let insert = match imm8 & 0b11 { - 0 => simd_shuffle16( - a, - b, - [16, 17, 18, 19, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 1 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 2 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 12, 13, 14, 15], - ), - _ => simd_shuffle16(a, b, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19]), - }; + macro_rules! call { + ($imm8:expr) => { + _mm512_inserti32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); let zero = _mm512_setzero_si512().as_i32x16(); - transmute(simd_select_bitmask(k, insert, zero)) + transmute(simd_select_bitmask(k, r.as_i32x16(), zero)) +} + +/// Copy a to dst, then insert 128 bits (composed of 4 packed 32-bit integers) from b into dst at the location specified by imm8. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_inserti32x4&expand=3171) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vinsert, imm8 = 1) //should be vinserti32x4 +)] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_inserti32x4(a: __m256i, b: __m128i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 1); + let a = a.as_i32x8(); + let b = _mm256_castsi128_si256(b).as_i32x8(); + let ret: i32x8 = match imm8 & 0b1 { + 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 4, 5, 6, 7]), + _ => simd_shuffle8(a, b, [0, 1, 2, 3, 8, 9, 10, 11]), + }; + transmute(ret) +} + +/// Copy a to tmp, then insert 128 bits (composed of 4 packed 32-bit integers) from b into tmp at the location specified by imm8. Store tmp to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_inserti32x4&expand=3172) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vinserti32x4, imm8 = 1) +)] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_inserti32x4( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m128i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_inserti32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x8(), src.as_i32x8())) +} + +/// Copy a to tmp, then insert 128 bits (composed of 4 packed 32-bit integers) from b into tmp at the location specified by imm8. Store tmp to dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_inserti32x4&expand=3173) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vinserti32x4, imm8 = 1) +)] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_inserti32x4(k: __mmask8, a: __m256i, b: __m128i, imm8: i32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_inserti32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r.as_i32x8(), zero)) } /// Copy a to dst, then insert 256 bits (composed of 4 packed 64-bit integers) from b into dst at the location specified by imm8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_inserti64x4&expand=3186) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_inserti64x4&expand=3186) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf64x4, imm8 = 1))] //should be vinserti64x4 @@ -14101,7 +24507,7 @@ pub unsafe fn _mm512_inserti64x4(a: __m512i, b: __m256i, imm8: i32) -> __m512i { /// Copy a to tmp, then insert 256 bits (composed of 4 packed 64-bit integers) from b into tmp at the location specified by imm8. Store tmp to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_inserti64x4&expand=3187) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_inserti64x4&expand=3187) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinserti64x4, imm8 = 1))] @@ -14113,36 +24519,36 @@ pub unsafe fn _mm512_mask_inserti64x4( b: __m256i, imm8: i32, ) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 1); - let b = _mm512_castsi256_si512(b); - let insert = match imm8 & 0b1 { - 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 4, 5, 6, 7]), - _ => simd_shuffle8(a, b, [0, 1, 2, 3, 8, 9, 10, 11]), - }; - transmute(simd_select_bitmask(k, insert, src.as_i64x8())) + macro_rules! call { + ($imm8:expr) => { + _mm512_inserti64x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x8(), src.as_i64x8())) } /// Copy a to tmp, then insert 256 bits (composed of 4 packed 64-bit integers) from b into tmp at the location specified by imm8. Store tmp to dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_inserti64x4&expand=3188) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_inserti64x4&expand=3188) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinserti64x4, imm8 = 1))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_inserti64x4(k: __mmask8, a: __m512i, b: __m256i, imm8: i32) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 1); - let b = _mm512_castsi256_si512(b); - let insert = match imm8 & 0b1 { - 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 4, 5, 6, 7]), - _ => simd_shuffle8(a, b, [0, 1, 2, 3, 8, 9, 10, 11]), - }; + macro_rules! call { + ($imm8:expr) => { + _mm512_inserti64x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); let zero = _mm512_setzero_si512().as_i64x8(); - transmute(simd_select_bitmask(k, insert, zero)) + transmute(simd_select_bitmask(k, r.as_i64x8(), zero)) } /// Copy a to dst, then insert 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from b into dst at the location specified by imm8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_insertf32x4&expand=3155) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_insertf32x4&expand=3155) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf32x4, imm8 = 2))] @@ -14172,7 +24578,7 @@ pub unsafe fn _mm512_insertf32x4(a: __m512, b: __m128, imm8: i32) -> __m512 { /// Copy a to tmp, then insert 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from b into tmp at the location specified by imm8. Store tmp to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_insertf32x4&expand=3156) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_insertf32x4&expand=3156) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf32x4, imm8 = 2))] @@ -14184,64 +24590,102 @@ pub unsafe fn _mm512_mask_insertf32x4( b: __m128, imm8: i32, ) -> __m512 { - assert!(imm8 >= 0 && imm8 <= 3); - let b = _mm512_castps128_ps512(b); - let insert = match imm8 & 0b11 { - 0 => simd_shuffle16( - a, - b, - [16, 17, 18, 19, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 1 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 2 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 12, 13, 14, 15], - ), - _ => simd_shuffle16(a, b, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19]), - }; - transmute(simd_select_bitmask(k, insert, src.as_f32x16())) + macro_rules! call { + ($imm8:expr) => { + _mm512_insertf32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x16(), src.as_f32x16())) } /// Copy a to tmp, then insert 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from b into tmp at the location specified by imm8. Store tmp to dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_insertf32x4&expand=3157) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_insertf32x4&expand=3157) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf32x4, imm8 = 2))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_insertf32x4(k: __mmask16, a: __m512, b: __m128, imm8: i32) -> __m512 { - assert!(imm8 >= 0 && imm8 <= 3); - let b = _mm512_castps128_ps512(b); - let insert = match imm8 & 0b11 { - 0 => simd_shuffle16( - a, - b, - [16, 17, 18, 19, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 1 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 12, 13, 14, 15], - ), - 2 => simd_shuffle16( - a, - b, - [0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 12, 13, 14, 15], - ), - _ => simd_shuffle16(a, b, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19]), - }; + macro_rules! call { + ($imm8:expr) => { + _mm512_insertf32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); let zero = _mm512_setzero_ps().as_f32x16(); - transmute(simd_select_bitmask(k, insert, zero)) + transmute(simd_select_bitmask(k, r.as_f32x16(), zero)) +} + +/// Copy a to dst, then insert 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from b into dst at the location specified by imm8. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_insertf32x4&expand=3152) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vinsert, imm8 = 1) //should be vinsertf32x4 +)] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_insertf32x4(a: __m256, b: __m128, imm8: i32) -> __m256 { + assert!(imm8 >= 0 && imm8 <= 1); + let b = _mm256_castps128_ps256(b); + match imm8 & 0b1 { + 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 4, 5, 6, 7]), + _ => simd_shuffle8(a, b, [0, 1, 2, 3, 8, 9, 10, 11]), + } +} + +/// Copy a to tmp, then insert 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from b into tmp at the location specified by imm8. Store tmp to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_insertf32x4&expand=3153) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vinsertf32x4, imm8 = 1) +)] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_insertf32x4( + src: __m256, + k: __mmask8, + a: __m256, + b: __m128, + imm8: i32, +) -> __m256 { + macro_rules! call { + ($imm8:expr) => { + _mm256_insertf32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f32x8(), src.as_f32x8())) +} + +/// Copy a to tmp, then insert 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from b into tmp at the location specified by imm8. Store tmp to dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_insertf32x4&expand=3154) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr( + all(test, not(target_os = "windows")), + assert_instr(vinsertf32x4, imm8 = 1) +)] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_insertf32x4(k: __mmask8, a: __m256, b: __m128, imm8: i32) -> __m256 { + macro_rules! call { + ($imm8:expr) => { + _mm256_insertf32x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, r.as_f32x8(), zero)) } /// Copy a to dst, then insert 256 bits (composed of 4 packed double-precision (64-bit) floating-point elements) from b into dst at the location specified by imm8. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_insertf64x4&expand=3167) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_insertf64x4&expand=3167) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf64x4, imm8 = 1))] @@ -14257,7 +24701,7 @@ pub unsafe fn _mm512_insertf64x4(a: __m512d, b: __m256d, imm8: i32) -> __m512d { /// Copy a to tmp, then insert 256 bits (composed of 4 packed double-precision (64-bit) floating-point elements) from b into tmp at the location specified by imm8. Store tmp to dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_insertf64x4&expand=3168) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_insertf64x4&expand=3168) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf64x4, imm8 = 1))] @@ -14269,70 +24713,56 @@ pub unsafe fn _mm512_mask_insertf64x4( b: __m256d, imm8: i32, ) -> __m512d { - assert!(imm8 >= 0 && imm8 <= 1); - let b = _mm512_castpd256_pd512(b); - let insert = match imm8 & 0b1 { - 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 4, 5, 6, 7]), - _ => simd_shuffle8(a, b, [0, 1, 2, 3, 8, 9, 10, 11]), - }; - transmute(simd_select_bitmask(k, insert, src.as_f64x8())) + macro_rules! call { + ($imm8:expr) => { + _mm512_insertf64x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_f64x8(), src.as_f64x8())) } /// Copy a to tmp, then insert 256 bits (composed of 4 packed double-precision (64-bit) floating-point elements) from b into tmp at the location specified by imm8. Store tmp to dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_insertf64x4&expand=3169) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_insertf64x4&expand=3169) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vinsertf64x4, imm8 = 1))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_insertf64x4(k: __mmask8, a: __m512d, b: __m256d, imm8: i32) -> __m512d { - assert!(imm8 >= 0 && imm8 <= 1); - let b = _mm512_castpd256_pd512(b); - let insert = match imm8 & 0b1 { - 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 4, 5, 6, 7]), - _ => simd_shuffle8(a, b, [0, 1, 2, 3, 8, 9, 10, 11]), - }; + macro_rules! call { + ($imm8:expr) => { + _mm512_insertf64x4(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); let zero = _mm512_setzero_pd().as_f64x8(); - transmute(simd_select_bitmask(k, insert, zero)) + transmute(simd_select_bitmask(k, r.as_f64x8(), zero)) } /// Unpack and interleave 32-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpackhi_epi32&expand=6021) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_epi32&expand=6021) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhps))] //should be vpunpckhdq pub unsafe fn _mm512_unpackhi_epi32(a: __m512i, b: __m512i) -> __m512i { let a = a.as_i32x16(); let b = b.as_i32x16(); + #[rustfmt::skip] let r: i32x16 = simd_shuffle16( - a, - b, - [ - 2, - 18, - 3, - 19, - 2 + 4, - 18 + 4, - 3 + 4, - 19 + 4, - 2 + 8, - 18 + 8, - 3 + 8, - 19 + 8, - 2 + 12, - 18 + 12, - 3 + 12, - 19 + 12, - ], + a, b, + [ 2, 18, 3, 19, + 2 + 4, 18 + 4, 3 + 4, 19 + 4, + 2 + 8, 18 + 8, 3 + 8, 19 + 8, + 2 + 12, 18 + 12, 3 + 12, 19 + 12], ); transmute(r) } /// Unpack and interleave 32-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpackhi_epi32&expand=6019) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_epi32&expand=6019) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpckhdq))] @@ -14348,7 +24778,7 @@ pub unsafe fn _mm512_mask_unpackhi_epi32( /// Unpack and interleave 32-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpackhi_epi32&expand=6020) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_epi32&expand=6020) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpckhdq))] @@ -14358,10 +24788,65 @@ pub unsafe fn _mm512_maskz_unpackhi_epi32(k: __mmask16, a: __m512i, b: __m512i) transmute(simd_select_bitmask(k, unpackhi, zero)) } -/// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and -/// store the results in dst. +/// Unpack and interleave 32-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpackhi_epi32&expand=6016) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhdq))] +pub unsafe fn _mm256_mask_unpackhi_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let unpackhi = _mm256_unpackhi_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, unpackhi, src.as_i32x8())) +} + +/// Unpack and interleave 32-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpackhi_epi32&expand=6017) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhdq))] +pub unsafe fn _mm256_maskz_unpackhi_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let unpackhi = _mm256_unpackhi_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + +/// Unpack and interleave 32-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpackhi_epi32&expand=6013) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhdq))] +pub unsafe fn _mm_mask_unpackhi_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, +) -> __m128i { + let unpackhi = _mm_unpackhi_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, unpackhi, src.as_i32x4())) +} + +/// Unpack and interleave 32-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpackhi_epi32&expand=6014) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhdq))] +pub unsafe fn _mm_maskz_unpackhi_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let unpackhi = _mm_unpackhi_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + +/// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpackhi_epi64&expand=6030) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_epi64&expand=6030) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhpd))] //should be vpunpckhqdq @@ -14371,7 +24856,7 @@ pub unsafe fn _mm512_unpackhi_epi64(a: __m512i, b: __m512i) -> __m512i { /// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpackhi_epi64&expand=6028) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_epi64&expand=6028) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpckhqdq))] @@ -14387,7 +24872,7 @@ pub unsafe fn _mm512_mask_unpackhi_epi64( /// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpackhi_epi64&expand=6029) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_epi64&expand=6029) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpckhqdq))] @@ -14397,40 +24882,82 @@ pub unsafe fn _mm512_maskz_unpackhi_epi64(k: __mmask8, a: __m512i, b: __m512i) - transmute(simd_select_bitmask(k, unpackhi, zero)) } +/// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpackhi_epi64&expand=6025) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhqdq))] +pub unsafe fn _mm256_mask_unpackhi_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let unpackhi = _mm256_unpackhi_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, unpackhi, src.as_i64x4())) +} + +/// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpackhi_epi64&expand=6026) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhqdq))] +pub unsafe fn _mm256_maskz_unpackhi_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let unpackhi = _mm256_unpackhi_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + +/// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpackhi_epi64&expand=6022) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhqdq))] +pub unsafe fn _mm_mask_unpackhi_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, +) -> __m128i { + let unpackhi = _mm_unpackhi_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, unpackhi, src.as_i64x2())) +} + +/// Unpack and interleave 64-bit integers from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpackhi_epi64&expand=6023) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckhqdq))] +pub unsafe fn _mm_maskz_unpackhi_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let unpackhi = _mm_unpackhi_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + /// Unpack and interleave single-precision (32-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpackhi_ps&expand=6060) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_ps&expand=6060) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhps))] pub unsafe fn _mm512_unpackhi_ps(a: __m512, b: __m512) -> __m512 { + #[rustfmt::skip] simd_shuffle16( - a, - b, - [ - 2, - 18, - 3, - 19, - 2 + 4, - 18 + 4, - 3 + 4, - 19 + 4, - 2 + 8, - 18 + 8, - 3 + 8, - 19 + 8, - 2 + 12, - 18 + 12, - 3 + 12, - 19 + 12, - ], + a, b, + [ 2, 18, 3, 19, + 2 + 4, 18 + 4, 3 + 4, 19 + 4, + 2 + 8, 18 + 8, 3 + 8, 19 + 8, + 2 + 12, 18 + 12, 3 + 12, 19 + 12], ) } /// Unpack and interleave single-precision (32-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpackhi_ps&expand=6058) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_ps&expand=6058) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhps))] @@ -14441,7 +24968,7 @@ pub unsafe fn _mm512_mask_unpackhi_ps(src: __m512, k: __mmask16, a: __m512, b: _ /// Unpack and interleave single-precision (32-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpackhi_ps&expand=6059) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_ps&expand=6059) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhps))] @@ -14451,9 +24978,55 @@ pub unsafe fn _mm512_maskz_unpackhi_ps(k: __mmask16, a: __m512, b: __m512) -> __ transmute(simd_select_bitmask(k, unpackhi, zero)) } +/// Unpack and interleave single-precision (32-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpackhi_ps&expand=6055) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhps))] +pub unsafe fn _mm256_mask_unpackhi_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let unpackhi = _mm256_unpackhi_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, unpackhi, src.as_f32x8())) +} + +/// Unpack and interleave single-precision (32-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpackhi_ps&expand=6056) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhps))] +pub unsafe fn _mm256_maskz_unpackhi_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let unpackhi = _mm256_unpackhi_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + +/// Unpack and interleave single-precision (32-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpackhi_ps&expand=6052) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhps))] +pub unsafe fn _mm_mask_unpackhi_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let unpackhi = _mm_unpackhi_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, unpackhi, src.as_f32x4())) +} + +/// Unpack and interleave single-precision (32-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpackhi_ps&expand=6053) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhps))] +pub unsafe fn _mm_maskz_unpackhi_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let unpackhi = _mm_unpackhi_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + /// Unpack and interleave double-precision (64-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpackhi_pd&expand=6048) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpackhi_pd&expand=6048) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhpd))] @@ -14463,7 +25036,7 @@ pub unsafe fn _mm512_unpackhi_pd(a: __m512d, b: __m512d) -> __m512d { /// Unpack and interleave double-precision (64-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpackhi_pd&expand=6046) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpackhi_pd&expand=6046) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhpd))] @@ -14479,7 +25052,7 @@ pub unsafe fn _mm512_mask_unpackhi_pd( /// Unpack and interleave double-precision (64-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpackhi_pd&expand=6047) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpackhi_pd&expand=6047) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpckhpd))] @@ -14489,43 +25062,80 @@ pub unsafe fn _mm512_maskz_unpackhi_pd(k: __mmask8, a: __m512d, b: __m512d) -> _ transmute(simd_select_bitmask(k, unpackhi, zero)) } +/// Unpack and interleave double-precision (64-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpackhi_pd&expand=6043) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhpd))] +pub unsafe fn _mm256_mask_unpackhi_pd( + src: __m256d, + k: __mmask8, + a: __m256d, + b: __m256d, +) -> __m256d { + let unpackhi = _mm256_unpackhi_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, unpackhi, src.as_f64x4())) +} + +/// Unpack and interleave double-precision (64-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpackhi_pd&expand=6044) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhpd))] +pub unsafe fn _mm256_maskz_unpackhi_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let unpackhi = _mm256_unpackhi_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + +/// Unpack and interleave double-precision (64-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpackhi_pd&expand=6040) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhpd))] +pub unsafe fn _mm_mask_unpackhi_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let unpackhi = _mm_unpackhi_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, unpackhi, src.as_f64x2())) +} + +/// Unpack and interleave double-precision (64-bit) floating-point elements from the high half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpackhi_pd&expand=6041) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpckhpd))] +pub unsafe fn _mm_maskz_unpackhi_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let unpackhi = _mm_unpackhi_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, unpackhi, zero)) +} + /// Unpack and interleave 32-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpacklo_epi32&expand=6078) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_epi32&expand=6078) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklps))] //should be vpunpckldq pub unsafe fn _mm512_unpacklo_epi32(a: __m512i, b: __m512i) -> __m512i { let a = a.as_i32x16(); let b = b.as_i32x16(); + #[rustfmt::skip] let r: i32x16 = simd_shuffle16( - a, - b, - [ - 0, - 16, - 1, - 17, - 0 + 4, - 16 + 4, - 1 + 4, - 17 + 4, - 0 + 8, - 16 + 8, - 1 + 8, - 17 + 8, - 0 + 12, - 16 + 12, - 1 + 12, - 17 + 12, - ], + a, b, + [ 0, 16, 1, 17, + 0 + 4, 16 + 4, 1 + 4, 17 + 4, + 0 + 8, 16 + 8, 1 + 8, 17 + 8, + 0 + 12, 16 + 12, 1 + 12, 17 + 12], ); transmute(r) } /// Unpack and interleave 32-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpacklo_epi32&expand=6076) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_epi32&expand=6076) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpckldq))] @@ -14535,25 +25145,81 @@ pub unsafe fn _mm512_mask_unpacklo_epi32( a: __m512i, b: __m512i, ) -> __m512i { - let unpackhi = _mm512_unpacklo_epi32(a, b).as_i32x16(); - transmute(simd_select_bitmask(k, unpackhi, src.as_i32x16())) + let unpacklo = _mm512_unpacklo_epi32(a, b).as_i32x16(); + transmute(simd_select_bitmask(k, unpacklo, src.as_i32x16())) } /// Unpack and interleave 32-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpacklo_epi32&expand=6077) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_epi32&expand=6077) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpckldq))] pub unsafe fn _mm512_maskz_unpacklo_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { - let unpackhi = _mm512_unpacklo_epi32(a, b).as_i32x16(); + let unpacklo = _mm512_unpacklo_epi32(a, b).as_i32x16(); let zero = _mm512_setzero_si512().as_i32x16(); - transmute(simd_select_bitmask(k, unpackhi, zero)) + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave 32-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpacklo_epi32&expand=6073) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckldq))] +pub unsafe fn _mm256_mask_unpacklo_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let unpacklo = _mm256_unpacklo_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, unpacklo, src.as_i32x8())) +} + +/// Unpack and interleave 32-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpacklo_epi32&expand=6074) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckldq))] +pub unsafe fn _mm256_maskz_unpacklo_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let unpacklo = _mm256_unpacklo_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave 32-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpacklo_epi32&expand=6070) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckldq))] +pub unsafe fn _mm_mask_unpacklo_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, +) -> __m128i { + let unpacklo = _mm_unpacklo_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, unpacklo, src.as_i32x4())) +} + +/// Unpack and interleave 32-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpacklo_epi32&expand=6071) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpckldq))] +pub unsafe fn _mm_maskz_unpacklo_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let unpacklo = _mm_unpacklo_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, unpacklo, zero)) } /// Unpack and interleave 64-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpacklo_epi64&expand=6087) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_epi64&expand=6087) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklpd))] //should be vpunpcklqdq @@ -14563,7 +25229,7 @@ pub unsafe fn _mm512_unpacklo_epi64(a: __m512i, b: __m512i) -> __m512i { /// Unpack and interleave 64-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpacklo_epi64&expand=6085) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_epi64&expand=6085) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpcklqdq))] @@ -14573,79 +25239,166 @@ pub unsafe fn _mm512_mask_unpacklo_epi64( a: __m512i, b: __m512i, ) -> __m512i { - let unpackhi = _mm512_unpacklo_epi64(a, b).as_i64x8(); - transmute(simd_select_bitmask(k, unpackhi, src.as_i64x8())) + let unpacklo = _mm512_unpacklo_epi64(a, b).as_i64x8(); + transmute(simd_select_bitmask(k, unpacklo, src.as_i64x8())) } /// Unpack and interleave 64-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpacklo_epi64&expand=6086) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_epi64&expand=6086) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpunpcklqdq))] pub unsafe fn _mm512_maskz_unpacklo_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m512i { - let unpackhi = _mm512_unpacklo_epi64(a, b).as_i64x8(); + let unpacklo = _mm512_unpacklo_epi64(a, b).as_i64x8(); let zero = _mm512_setzero_si512().as_i64x8(); - transmute(simd_select_bitmask(k, unpackhi, zero)) + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave 64-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpacklo_epi64&expand=6082) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpcklqdq))] +pub unsafe fn _mm256_mask_unpacklo_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let unpacklo = _mm256_unpacklo_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, unpacklo, src.as_i64x4())) +} + +/// Unpack and interleave 64-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpacklo_epi64&expand=6083) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpcklqdq))] +pub unsafe fn _mm256_maskz_unpacklo_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let unpacklo = _mm256_unpacklo_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave 64-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpacklo_epi64&expand=6079) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpcklqdq))] +pub unsafe fn _mm_mask_unpacklo_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, +) -> __m128i { + let unpacklo = _mm_unpacklo_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, unpacklo, src.as_i64x2())) +} + +/// Unpack and interleave 64-bit integers from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpacklo_epi64&expand=6080) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpunpcklqdq))] +pub unsafe fn _mm_maskz_unpacklo_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let unpacklo = _mm_unpacklo_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, unpacklo, zero)) } /// Unpack and interleave single-precision (32-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpacklo_ps&expand=6117) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_ps&expand=6117) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklps))] pub unsafe fn _mm512_unpacklo_ps(a: __m512, b: __m512) -> __m512 { - simd_shuffle16( - a, - b, - [ - 0, - 16, - 1, - 17, - 0 + 4, - 16 + 4, - 1 + 4, - 17 + 4, - 0 + 8, - 16 + 8, - 1 + 8, - 17 + 8, - 0 + 12, - 16 + 12, - 1 + 12, - 17 + 12, - ], + #[rustfmt::skip] + simd_shuffle16(a, b, + [ 0, 16, 1, 17, + 0 + 4, 16 + 4, 1 + 4, 17 + 4, + 0 + 8, 16 + 8, 1 + 8, 17 + 8, + 0 + 12, 16 + 12, 1 + 12, 17 + 12], ) } /// Unpack and interleave single-precision (32-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpacklo_ps&expand=6115) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_ps&expand=6115) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklps))] pub unsafe fn _mm512_mask_unpacklo_ps(src: __m512, k: __mmask16, a: __m512, b: __m512) -> __m512 { - let unpackhi = _mm512_unpacklo_ps(a, b).as_f32x16(); - transmute(simd_select_bitmask(k, unpackhi, src.as_f32x16())) + let unpacklo = _mm512_unpacklo_ps(a, b).as_f32x16(); + transmute(simd_select_bitmask(k, unpacklo, src.as_f32x16())) } /// Unpack and interleave single-precision (32-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpacklo_ps&expand=6116) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_ps&expand=6116) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklps))] pub unsafe fn _mm512_maskz_unpacklo_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 { - let unpackhi = _mm512_unpacklo_ps(a, b).as_f32x16(); + let unpacklo = _mm512_unpacklo_ps(a, b).as_f32x16(); let zero = _mm512_setzero_ps().as_f32x16(); - transmute(simd_select_bitmask(k, unpackhi, zero)) + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave single-precision (32-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpacklo_ps&expand=6112) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklps))] +pub unsafe fn _mm256_mask_unpacklo_ps(src: __m256, k: __mmask8, a: __m256, b: __m256) -> __m256 { + let unpacklo = _mm256_unpacklo_ps(a, b).as_f32x8(); + transmute(simd_select_bitmask(k, unpacklo, src.as_f32x8())) +} + +/// Unpack and interleave single-precision (32-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpacklo_ps&expand=6113) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklps))] +pub unsafe fn _mm256_maskz_unpacklo_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + let unpacklo = _mm256_unpacklo_ps(a, b).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave single-precision (32-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpacklo_ps&expand=6109) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklps))] +pub unsafe fn _mm_mask_unpacklo_ps(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { + let unpacklo = _mm_unpacklo_ps(a, b).as_f32x4(); + transmute(simd_select_bitmask(k, unpacklo, src.as_f32x4())) +} + +/// Unpack and interleave single-precision (32-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpacklo_ps&expand=6110) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklps))] +pub unsafe fn _mm_maskz_unpacklo_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + let unpacklo = _mm_unpacklo_ps(a, b).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, unpacklo, zero)) } /// Unpack and interleave double-precision (64-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_unpacklo_pd&expand=6105) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_unpacklo_pd&expand=6105) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklpd))] @@ -14655,7 +25408,7 @@ pub unsafe fn _mm512_unpacklo_pd(a: __m512d, b: __m512d) -> __m512d { /// Unpack and interleave double-precision (64-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_unpacklo_pd&expand=6103) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_unpacklo_pd&expand=6103) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklpd))] @@ -14665,20 +25418,71 @@ pub unsafe fn _mm512_mask_unpacklo_pd( a: __m512d, b: __m512d, ) -> __m512d { - let unpackhi = _mm512_unpacklo_pd(a, b).as_f64x8(); - transmute(simd_select_bitmask(k, unpackhi, src.as_f64x8())) + let unpacklo = _mm512_unpacklo_pd(a, b).as_f64x8(); + transmute(simd_select_bitmask(k, unpacklo, src.as_f64x8())) } /// Unpack and interleave double-precision (64-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_unpacklo_pd&expand=6104) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_unpacklo_pd&expand=6104) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vunpcklpd))] pub unsafe fn _mm512_maskz_unpacklo_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m512d { - let unpackhi = _mm512_unpacklo_pd(a, b).as_f64x8(); + let unpacklo = _mm512_unpacklo_pd(a, b).as_f64x8(); let zero = _mm512_setzero_pd().as_f64x8(); - transmute(simd_select_bitmask(k, unpackhi, zero)) + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave double-precision (64-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_unpacklo_pd&expand=6100) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklpd))] +pub unsafe fn _mm256_mask_unpacklo_pd( + src: __m256d, + k: __mmask8, + a: __m256d, + b: __m256d, +) -> __m256d { + let unpacklo = _mm256_unpacklo_pd(a, b).as_f64x4(); + transmute(simd_select_bitmask(k, unpacklo, src.as_f64x4())) +} + +/// Unpack and interleave double-precision (64-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_unpacklo_pd&expand=6101) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklpd))] +pub unsafe fn _mm256_maskz_unpacklo_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + let unpacklo = _mm256_unpacklo_pd(a, b).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, unpacklo, zero)) +} + +/// Unpack and interleave double-precision (64-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_unpacklo_pd&expand=6097) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklpd))] +pub unsafe fn _mm_mask_unpacklo_pd(src: __m128d, k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let unpacklo = _mm_unpacklo_pd(a, b).as_f64x2(); + transmute(simd_select_bitmask(k, unpacklo, src.as_f64x2())) +} + +/// Unpack and interleave double-precision (64-bit) floating-point elements from the low half of each 128-bit lane in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_unpacklo_pd&expand=6098) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vunpcklpd))] +pub unsafe fn _mm_maskz_unpacklo_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + let unpacklo = _mm_unpacklo_pd(a, b).as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); + transmute(simd_select_bitmask(k, unpacklo, zero)) } /// Cast vector of type __m128 to type __m512; the upper 384 bits of the result are undefined. This intrinsic is only used for compilation and does not generate any instructions, thus it has zero latency. @@ -14913,9 +25717,20 @@ pub unsafe fn _mm512_castsi512_pd(a: __m512i) -> __m512d { transmute(a) } +/// Copy the lower 32-bit integer in a to dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cvtsi512_si32&expand=1882) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(all(test, not(target_os = "windows")), assert_instr(vmovd))] +pub unsafe fn _mm512_cvtsi512_si32(a: __m512i) -> i32 { + let extract: i32 = simd_extract(a.as_i32x16(), 0); + transmute(extract) +} + /// Broadcast the low packed 32-bit integer from a to all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcastd_epi32&expand=545) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastd_epi32&expand=545) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcast))] //should be vpbroadcastd @@ -14927,7 +25742,7 @@ pub unsafe fn _mm512_broadcastd_epi32(a: __m128i) -> __m512i { /// Broadcast the low packed 32-bit integer from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_broadcastd_epi32&expand=546) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastd_epi32&expand=546) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastd @@ -14938,7 +25753,7 @@ pub unsafe fn _mm512_mask_broadcastd_epi32(src: __m512i, k: __mmask16, a: __m128 /// Broadcast the low packed 32-bit integer from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_broadcastd_epi32&expand=547) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastd_epi32&expand=547) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastd @@ -14948,9 +25763,55 @@ pub unsafe fn _mm512_maskz_broadcastd_epi32(k: __mmask16, a: __m128i) -> __m512i transmute(simd_select_bitmask(k, broadcast, zero)) } +/// Broadcast the low packed 32-bit integer from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_broadcastd_epi32&expand=543) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastd +pub unsafe fn _mm256_mask_broadcastd_epi32(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let broadcast = _mm256_broadcastd_epi32(a).as_i32x8(); + transmute(simd_select_bitmask(k, broadcast, src.as_i32x8())) +} + +/// Broadcast the low packed 32-bit integer from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_broadcastd_epi32&expand=544) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastd +pub unsafe fn _mm256_maskz_broadcastd_epi32(k: __mmask8, a: __m128i) -> __m256i { + let broadcast = _mm256_broadcastd_epi32(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + +/// Broadcast the low packed 32-bit integer from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_broadcastd_epi32&expand=540) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastd +pub unsafe fn _mm_mask_broadcastd_epi32(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let broadcast = _mm_broadcastd_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, broadcast, src.as_i32x4())) +} + +/// Broadcast the low packed 32-bit integer from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_broadcastd_epi32&expand=541) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastd +pub unsafe fn _mm_maskz_broadcastd_epi32(k: __mmask8, a: __m128i) -> __m128i { + let broadcast = _mm_broadcastd_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + /// Broadcast the low packed 64-bit integer from a to all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcastq_epi64&expand=560) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastq_epi64&expand=560) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcas))] //should be vpbroadcastq @@ -14960,7 +25821,7 @@ pub unsafe fn _mm512_broadcastq_epi64(a: __m128i) -> __m512i { /// Broadcast the low packed 64-bit integer from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_broadcastq_epi64&expand=561) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastq_epi64&expand=561) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastq @@ -14971,7 +25832,7 @@ pub unsafe fn _mm512_mask_broadcastq_epi64(src: __m512i, k: __mmask8, a: __m128i /// Broadcast the low packed 64-bit integer from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_broadcastq_epi64&expand=562) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastq_epi64&expand=562) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastq @@ -14981,9 +25842,55 @@ pub unsafe fn _mm512_maskz_broadcastq_epi64(k: __mmask8, a: __m128i) -> __m512i transmute(simd_select_bitmask(k, broadcast, zero)) } +/// Broadcast the low packed 64-bit integer from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_broadcastq_epi64&expand=558) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastq +pub unsafe fn _mm256_mask_broadcastq_epi64(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let broadcast = _mm256_broadcastq_epi64(a).as_i64x4(); + transmute(simd_select_bitmask(k, broadcast, src.as_i64x4())) +} + +/// Broadcast the low packed 64-bit integer from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_broadcastq_epi64&expand=559) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastq +pub unsafe fn _mm256_maskz_broadcastq_epi64(k: __mmask8, a: __m128i) -> __m256i { + let broadcast = _mm256_broadcastq_epi64(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + +/// Broadcast the low packed 64-bit integer from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_broadcastq_epi64&expand=555) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastq +pub unsafe fn _mm_mask_broadcastq_epi64(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + let broadcast = _mm_broadcastq_epi64(a).as_i64x2(); + transmute(simd_select_bitmask(k, broadcast, src.as_i64x2())) +} + +/// Broadcast the low packed 64-bit integer from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_broadcastq_epi64&expand=556) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcast))] //should be vpbroadcastq +pub unsafe fn _mm_maskz_broadcastq_epi64(k: __mmask8, a: __m128i) -> __m128i { + let broadcast = _mm_broadcastq_epi64(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + /// Broadcast the low single-precision (32-bit) floating-point element from a to all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcastss_ps&expand=578) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastss_ps&expand=578) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcastss))] @@ -14993,7 +25900,7 @@ pub unsafe fn _mm512_broadcastss_ps(a: __m128) -> __m512 { /// Broadcast the low single-precision (32-bit) floating-point element from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_broadcastss_ps&expand=579) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastss_ps&expand=579) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcastss))] @@ -15004,7 +25911,7 @@ pub unsafe fn _mm512_mask_broadcastss_ps(src: __m512, k: __mmask16, a: __m128) - /// Broadcast the low single-precision (32-bit) floating-point element from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_broadcastss_ps&expand=580) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastss_ps&expand=580) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcastss))] @@ -15014,19 +25921,65 @@ pub unsafe fn _mm512_maskz_broadcastss_ps(k: __mmask16, a: __m128) -> __m512 { transmute(simd_select_bitmask(k, broadcast, zero)) } +/// Broadcast the low single-precision (32-bit) floating-point element from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_broadcastss_ps&expand=576) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vbroadcastss))] +pub unsafe fn _mm256_mask_broadcastss_ps(src: __m256, k: __mmask8, a: __m128) -> __m256 { + let broadcast = _mm256_broadcastss_ps(a).as_f32x8(); + transmute(simd_select_bitmask(k, broadcast, src.as_f32x8())) +} + +/// Broadcast the low single-precision (32-bit) floating-point element from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_broadcastss_ps&expand=577) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vbroadcastss))] +pub unsafe fn _mm256_maskz_broadcastss_ps(k: __mmask8, a: __m128) -> __m256 { + let broadcast = _mm256_broadcastss_ps(a).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + +/// Broadcast the low single-precision (32-bit) floating-point element from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_broadcastss_ps&expand=573) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vbroadcastss))] +pub unsafe fn _mm_mask_broadcastss_ps(src: __m128, k: __mmask8, a: __m128) -> __m128 { + let broadcast = _mm_broadcastss_ps(a).as_f32x4(); + transmute(simd_select_bitmask(k, broadcast, src.as_f32x4())) +} + +/// Broadcast the low single-precision (32-bit) floating-point element from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_broadcastss_ps&expand=574) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vbroadcastss))] +pub unsafe fn _mm_maskz_broadcastss_ps(k: __mmask8, a: __m128) -> __m128 { + let broadcast = _mm_broadcastss_ps(a).as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + /// Broadcast the low double-precision (64-bit) floating-point element from a to all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcastsd_pd&expand=567) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcastsd_pd&expand=567) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcastsd))] pub unsafe fn _mm512_broadcastsd_pd(a: __m128d) -> __m512d { - simd_shuffle8(a, a, [1, 1, 1, 1, 1, 1, 1, 1]) + simd_shuffle8(a, a, [0, 0, 0, 0, 0, 0, 0, 0]) } /// Broadcast the low double-precision (64-bit) floating-point element from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_broadcastsd_pd&expand=568) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcastsd_pd&expand=568) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcastsd))] @@ -15037,7 +25990,7 @@ pub unsafe fn _mm512_mask_broadcastsd_pd(src: __m512d, k: __mmask8, a: __m128d) /// Broadcast the low double-precision (64-bit) floating-point element from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_broadcastsd_pd&expand=569) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcastsd_pd&expand=569) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vbroadcastsd))] @@ -15047,20 +26000,43 @@ pub unsafe fn _mm512_maskz_broadcastsd_pd(k: __mmask8, a: __m128d) -> __m512d { transmute(simd_select_bitmask(k, broadcast, zero)) } +/// Broadcast the low double-precision (64-bit) floating-point element from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_broadcastsd_pd&expand=565) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vbroadcastsd))] +pub unsafe fn _mm256_mask_broadcastsd_pd(src: __m256d, k: __mmask8, a: __m128d) -> __m256d { + let broadcast = _mm256_broadcastsd_pd(a).as_f64x4(); + transmute(simd_select_bitmask(k, broadcast, src.as_f64x4())) +} + +/// Broadcast the low double-precision (64-bit) floating-point element from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_broadcastsd_pd&expand=566) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vbroadcastsd))] +pub unsafe fn _mm256_maskz_broadcastsd_pd(k: __mmask8, a: __m128d) -> __m256d { + let broadcast = _mm256_broadcastsd_pd(a).as_f64x4(); + let zero = _mm256_setzero_pd().as_f64x4(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + /// Broadcast the 4 packed 32-bit integers from a to all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcast_i32x4&expand=510) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcast_i32x4&expand=510) #[inline] #[target_feature(enable = "avx512f")] //msvc: vbroadcasti32x4, linux: vshuf pub unsafe fn _mm512_broadcast_i32x4(a: __m128i) -> __m512i { - let a = _mm512_castsi128_si512(a).as_i32x16(); + let a = a.as_i32x4(); let ret: i32x16 = simd_shuffle16(a, a, [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]); transmute(ret) } /// Broadcast the 4 packed 32-bit integers from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_broadcast_i32x4&expand=511) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcast_i32x4&expand=511) #[inline] #[target_feature(enable = "avx512f")] //msvc: vbroadcasti32x4, linux: vshuf pub unsafe fn _mm512_mask_broadcast_i32x4(src: __m512i, k: __mmask16, a: __m128i) -> __m512i { @@ -15070,7 +26046,7 @@ pub unsafe fn _mm512_mask_broadcast_i32x4(src: __m512i, k: __mmask16, a: __m128i /// Broadcast the 4 packed 32-bit integers from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_broadcast_i32x4&expand=512) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcast_i32x4&expand=512) #[inline] #[target_feature(enable = "avx512f")] //msvc: vbroadcasti32x4, linux: vshuf pub unsafe fn _mm512_maskz_broadcast_i32x4(k: __mmask16, a: __m128i) -> __m512i { @@ -15079,6 +26055,38 @@ pub unsafe fn _mm512_maskz_broadcast_i32x4(k: __mmask16, a: __m128i) -> __m512i transmute(simd_select_bitmask(k, broadcast, zero)) } +/// Broadcast the 4 packed 32-bit integers from a to all elements of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_broadcast_i32x4&expand=507) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] //msvc: vbroadcasti32x4, linux: vshuf +pub unsafe fn _mm256_broadcast_i32x4(a: __m128i) -> __m256i { + let a = a.as_i32x4(); + let ret: i32x8 = simd_shuffle8(a, a, [0, 1, 2, 3, 0, 1, 2, 3]); + transmute(ret) +} + +/// Broadcast the 4 packed 32-bit integers from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_broadcast_i32x4&expand=508) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] //msvc: vbroadcasti32x4, linux: vshuf +pub unsafe fn _mm256_mask_broadcast_i32x4(src: __m256i, k: __mmask8, a: __m128i) -> __m256i { + let broadcast = _mm256_broadcast_i32x4(a).as_i32x8(); + transmute(simd_select_bitmask(k, broadcast, src.as_i32x8())) +} + +/// Broadcast the 4 packed 32-bit integers from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_broadcast_i32x4&expand=509) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] //msvc: vbroadcasti32x4, linux: vshuf +pub unsafe fn _mm256_maskz_broadcast_i32x4(k: __mmask8, a: __m128i) -> __m256i { + let broadcast = _mm256_broadcast_i32x4(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + /// Broadcast the 4 packed 64-bit integers from a to all elements of dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcast_i64x4&expand=522) @@ -15111,7 +26119,7 @@ pub unsafe fn _mm512_maskz_broadcast_i64x4(k: __mmask8, a: __m256i) -> __m512i { /// Broadcast the 4 packed single-precision (32-bit) floating-point elements from a to all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcast_f32x4&expand=483) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_broadcast_f32x4&expand=483) #[inline] #[target_feature(enable = "avx512f")] //msvc: vbroadcastf32x4, linux: vshuf pub unsafe fn _mm512_broadcast_f32x4(a: __m128) -> __m512 { @@ -15120,7 +26128,7 @@ pub unsafe fn _mm512_broadcast_f32x4(a: __m128) -> __m512 { /// Broadcast the 4 packed single-precision (32-bit) floating-point elements from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_broadcast_f32x4&expand=484) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_broadcast_f32x4&expand=484) #[inline] #[target_feature(enable = "avx512f")] //msvc: vbroadcastf32x4, linux: vshu pub unsafe fn _mm512_mask_broadcast_f32x4(src: __m512, k: __mmask16, a: __m128) -> __m512 { @@ -15130,7 +26138,7 @@ pub unsafe fn _mm512_mask_broadcast_f32x4(src: __m512, k: __mmask16, a: __m128) /// Broadcast the 4 packed single-precision (32-bit) floating-point elements from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_broadcast_f32x4&expand=485) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_broadcast_f32x4&expand=485) #[inline] #[target_feature(enable = "avx512f")] //msvc: vbroadcastf32x4, linux: vshu pub unsafe fn _mm512_maskz_broadcast_f32x4(k: __mmask16, a: __m128) -> __m512 { @@ -15139,6 +26147,36 @@ pub unsafe fn _mm512_maskz_broadcast_f32x4(k: __mmask16, a: __m128) -> __m512 { transmute(simd_select_bitmask(k, broadcast, zero)) } +/// Broadcast the 4 packed single-precision (32-bit) floating-point elements from a to all elements of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_broadcast_f32x4&expand=480) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] //msvc: vbroadcastf32x4, linux: vshuf +pub unsafe fn _mm256_broadcast_f32x4(a: __m128) -> __m256 { + simd_shuffle8(a, a, [0, 1, 2, 3, 0, 1, 2, 3]) +} + +/// Broadcast the 4 packed single-precision (32-bit) floating-point elements from a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_broadcast_f32x4&expand=481) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] //msvc: vbroadcastf32x4, linux: vshu +pub unsafe fn _mm256_mask_broadcast_f32x4(src: __m256, k: __mmask8, a: __m128) -> __m256 { + let broadcast = _mm256_broadcast_f32x4(a).as_f32x8(); + transmute(simd_select_bitmask(k, broadcast, src.as_f32x8())) +} + +/// Broadcast the 4 packed single-precision (32-bit) floating-point elements from a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_broadcast_f32x4&expand=482) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] //msvc: vbroadcastf32x4, linux: vshu +pub unsafe fn _mm256_maskz_broadcast_f32x4(k: __mmask8, a: __m128) -> __m256 { + let broadcast = _mm256_broadcast_f32x4(a).as_f32x8(); + let zero = _mm256_setzero_ps().as_f32x8(); + transmute(simd_select_bitmask(k, broadcast, zero)) +} + /// Broadcast the 4 packed double-precision (64-bit) floating-point elements from a to all elements of dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_broadcast_f64x4&expand=495) @@ -15171,7 +26209,7 @@ pub unsafe fn _mm512_maskz_broadcast_f64x4(k: __mmask8, a: __m256d) -> __m512d { /// Blend packed 32-bit integers from a and b using control mask k, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_blend_epi32&expand=435) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_epi32&expand=435) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovdqa32))] //should be vpblendmd @@ -15179,9 +26217,29 @@ pub unsafe fn _mm512_mask_blend_epi32(k: __mmask16, a: __m512i, b: __m512i) -> _ transmute(simd_select_bitmask(k, b.as_i32x16(), a.as_i32x16())) } +/// Blend packed 32-bit integers from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_blend_epi32&expand=434) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa32))] //should be vpblendmd +pub unsafe fn _mm256_mask_blend_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + transmute(simd_select_bitmask(k, b.as_i32x8(), a.as_i32x8())) +} + +/// Blend packed 32-bit integers from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_blend_epi32&expand=432) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa32))] //should be vpblendmd +pub unsafe fn _mm_mask_blend_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + transmute(simd_select_bitmask(k, b.as_i32x4(), a.as_i32x4())) +} + /// Blend packed 64-bit integers from a and b using control mask k, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_blend_epi64&expand=438) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_epi64&expand=438) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovdqa64))] //should be vpblendmq @@ -15189,9 +26247,29 @@ pub unsafe fn _mm512_mask_blend_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, b.as_i64x8(), a.as_i64x8())) } +/// Blend packed 64-bit integers from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_blend_epi64&expand=437) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa64))] //should be vpblendmq +pub unsafe fn _mm256_mask_blend_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + transmute(simd_select_bitmask(k, b.as_i64x4(), a.as_i64x4())) +} + +/// Blend packed 64-bit integers from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_blend_epi64&expand=436) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovdqa64))] //should be vpblendmq +pub unsafe fn _mm_mask_blend_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + transmute(simd_select_bitmask(k, b.as_i64x2(), a.as_i64x2())) +} + /// Blend packed single-precision (32-bit) floating-point elements from a and b using control mask k, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_blend_ps&expand=451) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_ps&expand=451) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] //should be vpblendmps @@ -15199,9 +26277,29 @@ pub unsafe fn _mm512_mask_blend_ps(k: __mmask16, a: __m512, b: __m512) -> __m512 transmute(simd_select_bitmask(k, b.as_f32x16(), a.as_f32x16())) } +/// Blend packed single-precision (32-bit) floating-point elements from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_blend_ps&expand=450) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vpblendmps +pub unsafe fn _mm256_mask_blend_ps(k: __mmask8, a: __m256, b: __m256) -> __m256 { + transmute(simd_select_bitmask(k, b.as_f32x8(), a.as_f32x8())) +} + +/// Blend packed single-precision (32-bit) floating-point elements from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_blend_ps&expand=448) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vpblendmps +pub unsafe fn _mm_mask_blend_ps(k: __mmask8, a: __m128, b: __m128) -> __m128 { + transmute(simd_select_bitmask(k, b.as_f32x4(), a.as_f32x4())) +} + /// Blend packed double-precision (64-bit) floating-point elements from a and b using control mask k, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_blend_pd&expand=446) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_pd&expand=446) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovapd))] //should be vpblendmpd @@ -15209,6 +26307,26 @@ pub unsafe fn _mm512_mask_blend_pd(k: __mmask8, a: __m512d, b: __m512d) -> __m51 transmute(simd_select_bitmask(k, b.as_f64x8(), a.as_f64x8())) } +/// Blend packed double-precision (64-bit) floating-point elements from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_blend_pd&expand=445) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovapd))] //should be vpblendmpd +pub unsafe fn _mm256_mask_blend_pd(k: __mmask8, a: __m256d, b: __m256d) -> __m256d { + transmute(simd_select_bitmask(k, b.as_f64x4(), a.as_f64x4())) +} + +/// Blend packed double-precision (64-bit) floating-point elements from a and b using control mask k, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_blend_pd&expand=443) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovapd))] //should be vpblendmpd +pub unsafe fn _mm_mask_blend_pd(k: __mmask8, a: __m128d, b: __m128d) -> __m128d { + transmute(simd_select_bitmask(k, b.as_f64x2(), a.as_f64x2())) +} + /// Concatenate a and b into a 128-byte immediate result, shift the result right by imm8 32-bit elements, and store the low 64 bytes (16 elements) in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_alignr_epi32&expand=245) @@ -15300,73 +26418,13 @@ pub unsafe fn _mm512_mask_alignr_epi32( b: __m512i, imm8: i32, ) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 255); - let a = a.as_i32x16(); - let b = b.as_i32x16(); - let imm8: i32 = imm8 % 16; - let r: i32x16 = match imm8 { - 0 => simd_shuffle16( - a, - b, - [ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - ], - ), - 1 => simd_shuffle16( - a, - b, - [ - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, - ], - ), - 2 => simd_shuffle16( - a, - b, - [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1], - ), - 3 => simd_shuffle16( - a, - b, - [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2], - ), - 4 => simd_shuffle16( - a, - b, - [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3], - ), - 5 => simd_shuffle16( - a, - b, - [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4], - ), - 6 => simd_shuffle16( - a, - b, - [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5], - ), - 7 => simd_shuffle16( - a, - b, - [23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6], - ), - 8 => simd_shuffle16( - a, - b, - [24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7], - ), - 9 => simd_shuffle16( - a, - b, - [25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8], - ), - 10 => simd_shuffle16(a, b, [26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), - 11 => simd_shuffle16(a, b, [27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), - 12 => simd_shuffle16(a, b, [28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]), - 13 => simd_shuffle16(a, b, [29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]), - 14 => simd_shuffle16(a, b, [30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]), - _ => simd_shuffle16(a, b, [31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]), - }; - transmute(simd_select_bitmask(k, r, src.as_i32x16())) + macro_rules! call { + ($imm8:expr) => { + _mm512_alignr_epi32(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x16(), src.as_i32x16())) } /// Concatenate a and b into a 128-byte immediate result, shift the result right by imm8 32-bit elements, and stores the low 64 bytes (16 elements) in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -15382,74 +26440,154 @@ pub unsafe fn _mm512_maskz_alignr_epi32( b: __m512i, imm8: i32, ) -> __m512i { + macro_rules! call { + ($imm8:expr) => { + _mm512_alignr_epi32(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, r.as_i32x16(), zero)) +} + +/// Concatenate a and b into a 64-byte immediate result, shift the result right by imm8 32-bit elements, and store the low 32 bytes (8 elements) in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_alignr_epi32&expand=242) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignd, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_alignr_epi32(a: __m256i, b: __m256i, imm8: i32) -> __m256i { assert!(imm8 >= 0 && imm8 <= 255); - let a = a.as_i32x16(); - let b = b.as_i32x16(); + let a = a.as_i32x8(); + let b = b.as_i32x8(); let imm8: i32 = imm8 % 16; - let r: i32x16 = match imm8 { - 0 => simd_shuffle16( - a, - b, - [ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - ], - ), - 1 => simd_shuffle16( - a, - b, - [ - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, - ], - ), - 2 => simd_shuffle16( - a, - b, - [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1], - ), - 3 => simd_shuffle16( - a, - b, - [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2], - ), - 4 => simd_shuffle16( - a, - b, - [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3], - ), - 5 => simd_shuffle16( - a, - b, - [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4], - ), - 6 => simd_shuffle16( - a, - b, - [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5], - ), - 7 => simd_shuffle16( - a, - b, - [23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6], - ), - 8 => simd_shuffle16( - a, - b, - [24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7], - ), - 9 => simd_shuffle16( - a, - b, - [25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8], - ), - 10 => simd_shuffle16(a, b, [26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), - 11 => simd_shuffle16(a, b, [27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), - 12 => simd_shuffle16(a, b, [28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]), - 13 => simd_shuffle16(a, b, [29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]), - 14 => simd_shuffle16(a, b, [30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]), - _ => simd_shuffle16(a, b, [31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]), + let r: i32x8 = match imm8 { + 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 12, 13, 14, 15]), + 1 => simd_shuffle8(a, b, [9, 10, 11, 12, 13, 14, 15, 0]), + 2 => simd_shuffle8(a, b, [10, 11, 12, 13, 14, 15, 0, 1]), + 3 => simd_shuffle8(a, b, [11, 12, 13, 14, 15, 0, 1, 2]), + 4 => simd_shuffle8(a, b, [12, 13, 14, 15, 0, 1, 2, 3]), + 5 => simd_shuffle8(a, b, [13, 14, 15, 0, 1, 2, 3, 4]), + 6 => simd_shuffle8(a, b, [14, 15, 0, 1, 2, 3, 4, 5]), + 7 => simd_shuffle8(a, b, [15, 0, 1, 2, 3, 4, 5, 6]), + 8 => simd_shuffle8(a, b, [0, 1, 2, 3, 4, 5, 6, 7]), + 9 => simd_shuffle8(a, b, [1, 2, 3, 4, 5, 6, 7, 8]), + 10 => simd_shuffle8(a, b, [2, 3, 4, 5, 6, 7, 8, 9]), + 11 => simd_shuffle8(a, b, [3, 4, 5, 6, 7, 8, 9, 10]), + 12 => simd_shuffle8(a, b, [4, 5, 6, 7, 8, 9, 10, 11]), + 13 => simd_shuffle8(a, b, [5, 6, 7, 8, 9, 10, 11, 12]), + 14 => simd_shuffle8(a, b, [6, 7, 8, 9, 10, 11, 12, 13]), + _ => simd_shuffle8(a, b, [7, 8, 9, 10, 11, 12, 13, 14]), + }; + transmute(r) +} + +/// Concatenate a and b into a 64-byte immediate result, shift the result right by imm8 32-bit elements, and store the low 32 bytes (8 elements) in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_alignr_epi32&expand=243) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignd, imm8 = 1))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_alignr_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_alignr_epi32(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x8(), src.as_i32x8())) +} + +/// Concatenate a and b into a 64-byte immediate result, shift the result right by imm8 32-bit elements, and store the low 32 bytes (8 elements) in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_alignr_epi32&expand=244) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignd, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_alignr_epi32(k: __mmask8, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_alignr_epi32(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r.as_i32x8(), zero)) +} + +/// Concatenate a and b into a 32-byte immediate result, shift the result right by imm8 32-bit elements, and store the low 16 bytes (4 elements) in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_epi32&expand=239) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpalignr, imm8 = 1))] //should be valignd +#[rustc_args_required_const(2)] +pub unsafe fn _mm_alignr_epi32(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let a = a.as_i32x4(); + let b = b.as_i32x4(); + let imm8: i32 = imm8 % 8; + let r: i32x4 = match imm8 { + 0 => simd_shuffle4(a, b, [4, 5, 6, 7]), + 1 => simd_shuffle4(a, b, [5, 6, 7, 0]), + 2 => simd_shuffle4(a, b, [6, 7, 0, 1]), + 3 => simd_shuffle4(a, b, [7, 0, 1, 2]), + 4 => simd_shuffle4(a, b, [0, 1, 2, 3]), + 5 => simd_shuffle4(a, b, [1, 2, 3, 0]), + 6 => simd_shuffle4(a, b, [2, 3, 0, 1]), + _ => simd_shuffle4(a, b, [3, 0, 1, 2]), }; - let zero = _mm512_setzero_si512().as_i32x16(); - transmute(simd_select_bitmask(k, r, zero)) + transmute(r) +} + +/// Concatenate a and b into a 32-byte immediate result, shift the result right by imm8 32-bit elements, and store the low 16 bytes (4 elements) in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_alignr_epi32&expand=240) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignd, imm8 = 1))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_alignr_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_alignr_epi32(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i32x4(), src.as_i32x4())) +} + +/// Concatenate a and b into a 32-byte immediate result, shift the result right by imm8 32-bit elements, and store the low 16 bytes (4 elements) in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_alignr_epi32&expand=241) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignd, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_alignr_epi32(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_alignr_epi32(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r.as_i32x4(), zero)) } /// Concatenate a and b into a 128-byte immediate result, shift the result right by imm8 64-bit elements, and store the low 64 bytes (8 elements) in dst. @@ -15489,19 +26627,13 @@ pub unsafe fn _mm512_mask_alignr_epi64( b: __m512i, imm8: i32, ) -> __m512i { - assert!(imm8 >= 0 && imm8 <= 255); - let imm8: i32 = imm8 % 8; - let r: i64x8 = match imm8 { - 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 12, 13, 14, 15]), - 1 => simd_shuffle8(a, b, [9, 10, 11, 12, 13, 14, 15, 0]), - 2 => simd_shuffle8(a, b, [10, 11, 12, 13, 14, 15, 0, 1]), - 3 => simd_shuffle8(a, b, [11, 12, 13, 14, 15, 0, 1, 2]), - 4 => simd_shuffle8(a, b, [12, 13, 14, 15, 0, 1, 2, 3]), - 5 => simd_shuffle8(a, b, [13, 14, 15, 0, 1, 2, 3, 4]), - 6 => simd_shuffle8(a, b, [14, 15, 0, 1, 2, 3, 4, 5]), - _ => simd_shuffle8(a, b, [15, 0, 1, 2, 3, 4, 5, 6]), - }; - transmute(simd_select_bitmask(k, r, src.as_i64x8())) + macro_rules! call { + ($imm8:expr) => { + _mm512_alignr_epi64(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x8(), src.as_i64x8())) } /// Concatenate a and b into a 128-byte immediate result, shift the result right by imm8 64-bit elements, and stores the low 64 bytes (8 elements) in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). @@ -15512,25 +26644,143 @@ pub unsafe fn _mm512_mask_alignr_epi64( #[cfg_attr(test, assert_instr(valignq, imm8 = 1))] #[rustc_args_required_const(3)] pub unsafe fn _mm512_maskz_alignr_epi64(k: __mmask8, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + macro_rules! call { + ($imm8:expr) => { + _mm512_alignr_epi64(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm512_setzero_si512().as_i64x8(); + transmute(simd_select_bitmask(k, r.as_i64x8(), zero)) +} + +/// Concatenate a and b into a 64-byte immediate result, shift the result right by imm8 64-bit elements, and store the low 32 bytes (4 elements) in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_alignr_epi64&expand=251) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignq, imm8 = 1))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_alignr_epi64(a: __m256i, b: __m256i, imm8: i32) -> __m256i { assert!(imm8 >= 0 && imm8 <= 255); let imm8: i32 = imm8 % 8; - let r: i64x8 = match imm8 { - 0 => simd_shuffle8(a, b, [8, 9, 10, 11, 12, 13, 14, 15]), - 1 => simd_shuffle8(a, b, [9, 10, 11, 12, 13, 14, 15, 0]), - 2 => simd_shuffle8(a, b, [10, 11, 12, 13, 14, 15, 0, 1]), - 3 => simd_shuffle8(a, b, [11, 12, 13, 14, 15, 0, 1, 2]), - 4 => simd_shuffle8(a, b, [12, 13, 14, 15, 0, 1, 2, 3]), - 5 => simd_shuffle8(a, b, [13, 14, 15, 0, 1, 2, 3, 4]), - 6 => simd_shuffle8(a, b, [14, 15, 0, 1, 2, 3, 4, 5]), - _ => simd_shuffle8(a, b, [15, 0, 1, 2, 3, 4, 5, 6]), + let r: i64x4 = match imm8 { + 0 => simd_shuffle4(a, b, [4, 5, 6, 7]), + 1 => simd_shuffle4(a, b, [5, 6, 7, 0]), + 2 => simd_shuffle4(a, b, [6, 7, 0, 1]), + 3 => simd_shuffle4(a, b, [7, 0, 1, 2]), + 4 => simd_shuffle4(a, b, [0, 1, 2, 3]), + 5 => simd_shuffle4(a, b, [1, 2, 3, 4]), + 6 => simd_shuffle4(a, b, [2, 3, 4, 5]), + _ => simd_shuffle4(a, b, [3, 4, 5, 6]), }; - let zero = _mm512_setzero_si512().as_i64x8(); - transmute(simd_select_bitmask(k, r, zero)) + transmute(r) +} + +/// Concatenate a and b into a 64-byte immediate result, shift the result right by imm8 64-bit elements, and store the low 32 bytes (4 elements) in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_alignr_epi64&expand=252) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignq, imm8 = 1))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_alignr_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_alignr_epi64(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x4(), src.as_i64x4())) +} + +/// Concatenate a and b into a 64-byte immediate result, shift the result right by imm8 64-bit elements, and store the low 32 bytes (4 elements) in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_alignr_epi64&expand=253) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_alignr_epi64(k: __mmask8, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + macro_rules! call { + ($imm8:expr) => { + _mm256_alignr_epi64(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, r.as_i64x4(), zero)) +} + +/// Concatenate a and b into a 32-byte immediate result, shift the result right by imm8 64-bit elements, and store the low 16 bytes (2 elements) in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_alignr_epi64&expand=248) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpalignr, imm8 = 1))] //should be valignq +#[rustc_args_required_const(2)] +pub unsafe fn _mm_alignr_epi64(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let imm8: i32 = imm8 % 4; + let r: i64x2 = match imm8 { + 0 => simd_shuffle2(a, b, [2, 3]), + 1 => simd_shuffle2(a, b, [3, 0]), + 2 => simd_shuffle2(a, b, [0, 1]), + _ => simd_shuffle2(a, b, [1, 2]), + }; + transmute(r) +} + +/// Concatenate a and b into a 32-byte immediate result, shift the result right by imm8 64-bit elements, and store the low 16 bytes (2 elements) in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_alignr_epi64&expand=249) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignq, imm8 = 1))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_alignr_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_alignr_epi64(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + transmute(simd_select_bitmask(k, r.as_i64x2(), src.as_i64x2())) +} + +/// Concatenate a and b into a 32-byte immediate result, shift the result right by imm8 64-bit elements, and store the low 16 bytes (2 elements) in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_alignr_epi64&expand=250) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(valignq, imm8 = 1))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_alignr_epi64(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + macro_rules! call { + ($imm8:expr) => { + _mm_alignr_epi64(a, b, $imm8) + }; + } + let r = constify_imm8_sae!(imm8, call); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, r.as_i64x2(), zero)) } /// Compute the bitwise AND of packed 32-bit integers in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_and_epi32&expand=272) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_and_epi32&expand=272) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] //should be vpandd, but generate vpandq @@ -15538,9 +26788,9 @@ pub unsafe fn _mm512_and_epi32(a: __m512i, b: __m512i) -> __m512i { transmute(simd_and(a.as_i32x16(), b.as_i32x16())) } -/// Performs element-by-element bitwise AND between packed 32-bit integer elements of v2 and v3, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Performs element-by-element bitwise AND between packed 32-bit integer elements of a and b, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_and_epi32&expand=273) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_and_epi32&expand=273) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandd))] @@ -15551,7 +26801,7 @@ pub unsafe fn _mm512_mask_and_epi32(src: __m512i, k: __mmask16, a: __m512i, b: _ /// Compute the bitwise AND of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_and_epi32&expand=274) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_and_epi32&expand=274) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandd))] @@ -15561,9 +26811,55 @@ pub unsafe fn _mm512_maskz_and_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, and, zero)) } +/// Performs element-by-element bitwise AND between packed 32-bit integer elements of a and b, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_and_epi32&expand=270) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandd))] +pub unsafe fn _mm256_mask_and_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let and = simd_and(a.as_i32x8(), b.as_i32x8()); + transmute(simd_select_bitmask(k, and, src.as_i32x8())) +} + +/// Compute the bitwise AND of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_and_epi32&expand=271) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandd))] +pub unsafe fn _mm256_maskz_and_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let and = simd_and(a.as_i32x8(), b.as_i32x8()); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, and, zero)) +} + +/// Performs element-by-element bitwise AND between packed 32-bit integer elements of a and b, storing the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_and_epi32&expand=268) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandd))] +pub unsafe fn _mm_mask_and_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let and = simd_and(a.as_i32x4(), b.as_i32x4()); + transmute(simd_select_bitmask(k, and, src.as_i32x4())) +} + +/// Compute the bitwise AND of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_and_epi32&expand=269) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandd))] +pub unsafe fn _mm_maskz_and_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let and = simd_and(a.as_i32x4(), b.as_i32x4()); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, and, zero)) +} + /// Compute the bitwise AND of 512 bits (composed of packed 64-bit integers) in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_and_epi64&expand=279) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_and_epi64&expand=279) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] @@ -15573,7 +26869,7 @@ pub unsafe fn _mm512_and_epi64(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise AND of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_and_epi64&expand=280) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_and_epi64&expand=280) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] @@ -15582,9 +26878,9 @@ pub unsafe fn _mm512_mask_and_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __ transmute(simd_select_bitmask(k, and, src.as_i64x8())) } -/// Compute the bitwise AND of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Compute the bitwise AND of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_and_Epi32&expand=274) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_and_epi64&expand=281) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] @@ -15594,9 +26890,55 @@ pub unsafe fn _mm512_maskz_and_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, and, zero)) } +/// Compute the bitwise AND of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_and_epi64&expand=277) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandq))] +pub unsafe fn _mm256_mask_and_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let and = simd_and(a.as_i64x4(), b.as_i64x4()); + transmute(simd_select_bitmask(k, and, src.as_i64x4())) +} + +/// Compute the bitwise AND of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_and_epi64&expand=278) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandq))] +pub unsafe fn _mm256_maskz_and_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let and = simd_and(a.as_i64x4(), b.as_i64x4()); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, and, zero)) +} + +/// Compute the bitwise AND of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_and_epi64&expand=275) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandq))] +pub unsafe fn _mm_mask_and_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let and = simd_and(a.as_i64x2(), b.as_i64x2()); + transmute(simd_select_bitmask(k, and, src.as_i64x2())) +} + +/// Compute the bitwise AND of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_and_epi64&expand=276) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandq))] +pub unsafe fn _mm_maskz_and_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let and = simd_and(a.as_i64x2(), b.as_i64x2()); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, and, zero)) +} + /// Compute the bitwise AND of 512 bits (representing integer data) in a and b, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_and_si512&expand=302) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_and_si512&expand=302) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandq))] @@ -15606,7 +26948,7 @@ pub unsafe fn _mm512_and_si512(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_or_epi32&expand=4042) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_or_epi32&expand=4042) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vporq))] @@ -15616,7 +26958,7 @@ pub unsafe fn _mm512_or_epi32(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_or_epi32&expand=4040) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_or_epi32&expand=4040) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpord))] @@ -15627,7 +26969,7 @@ pub unsafe fn _mm512_mask_or_epi32(src: __m512i, k: __mmask16, a: __m512i, b: __ /// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_or_epi32&expand=4041) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_or_epi32&expand=4041) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpord))] @@ -15637,9 +26979,75 @@ pub unsafe fn _mm512_maskz_or_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, or, zero)) } +/// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_or_epi32&expand=4039) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vor))] //should be vpord +pub unsafe fn _mm256_or_epi32(a: __m256i, b: __m256i) -> __m256i { + transmute(simd_or(a.as_i32x8(), b.as_i32x8())) +} + +/// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_or_epi32&expand=4037) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpord))] +pub unsafe fn _mm256_mask_or_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let or = _mm256_or_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, or, src.as_i32x8())) +} + +/// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_or_epi32&expand=4038) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpord))] +pub unsafe fn _mm256_maskz_or_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let or = _mm256_or_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, or, zero)) +} + +/// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_or_epi32&expand=4036) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vor))] //should be vpord +pub unsafe fn _mm_or_epi32(a: __m128i, b: __m128i) -> __m128i { + transmute(simd_or(a.as_i32x4(), b.as_i32x4())) +} + +/// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_or_epi32&expand=4034) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpord))] +pub unsafe fn _mm_mask_or_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let or = _mm_or_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, or, src.as_i32x4())) +} + +/// Compute the bitwise OR of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_or_epi32&expand=4035) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpord))] +pub unsafe fn _mm_maskz_or_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let or = _mm_or_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, or, zero)) +} + /// Compute the bitwise OR of packed 64-bit integers in a and b, and store the resut in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_or_epi64&expand=4051) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_or_epi64&expand=4051) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vporq))] @@ -15649,7 +27057,7 @@ pub unsafe fn _mm512_or_epi64(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise OR of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_or_epi64&expand=4049) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_or_epi64&expand=4049) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vporq))] @@ -15660,7 +27068,7 @@ pub unsafe fn _mm512_mask_or_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __m /// Compute the bitwise OR of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_or_epi64&expand=4050) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_or_epi64&expand=4050) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vporq))] @@ -15670,9 +27078,75 @@ pub unsafe fn _mm512_maskz_or_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m5 transmute(simd_select_bitmask(k, or, zero)) } +/// Compute the bitwise OR of packed 64-bit integers in a and b, and store the resut in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_or_epi64&expand=4048) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vor))] //should be vporq +pub unsafe fn _mm256_or_epi64(a: __m256i, b: __m256i) -> __m256i { + transmute(simd_or(a.as_i64x4(), b.as_i64x4())) +} + +/// Compute the bitwise OR of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_or_epi64&expand=4046) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vporq))] +pub unsafe fn _mm256_mask_or_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let or = _mm256_or_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, or, src.as_i64x4())) +} + +/// Compute the bitwise OR of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_or_epi64&expand=4047) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vporq))] +pub unsafe fn _mm256_maskz_or_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let or = _mm256_or_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, or, zero)) +} + +/// Compute the bitwise OR of packed 64-bit integers in a and b, and store the resut in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_or_epi64&expand=4045) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vor))] //should be vporq +pub unsafe fn _mm_or_epi64(a: __m128i, b: __m128i) -> __m128i { + transmute(simd_or(a.as_i64x2(), b.as_i64x2())) +} + +/// Compute the bitwise OR of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_or_epi64&expand=4043) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vporq))] +pub unsafe fn _mm_mask_or_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let or = _mm_or_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, or, src.as_i64x2())) +} + +/// Compute the bitwise OR of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_or_epi64&expand=4044) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vporq))] +pub unsafe fn _mm_maskz_or_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let or = _mm_or_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, or, zero)) +} + /// Compute the bitwise OR of 512 bits (representing integer data) in a and b, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_or_si512&expand=4072) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_or_si512&expand=4072) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vporq))] @@ -15682,17 +27156,17 @@ pub unsafe fn _mm512_or_si512(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_xor_epi32&expand=6142) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_xor_epi32&expand=6142) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpxorq))] +#[cfg_attr(test, assert_instr(vpxorq))] //should be vpxord pub unsafe fn _mm512_xor_epi32(a: __m512i, b: __m512i) -> __m512i { transmute(simd_xor(a.as_i32x16(), b.as_i32x16())) } /// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_xor_epi32&expand=6140) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_xor_epi32&expand=6140) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpxord))] @@ -15703,7 +27177,7 @@ pub unsafe fn _mm512_mask_xor_epi32(src: __m512i, k: __mmask16, a: __m512i, b: _ /// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_xor_epi32&expand=6141) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_xor_epi32&expand=6141) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpxord))] @@ -15713,9 +27187,75 @@ pub unsafe fn _mm512_maskz_xor_epi32(k: __mmask16, a: __m512i, b: __m512i) -> __ transmute(simd_select_bitmask(k, xor, zero)) } +/// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_xor_epi32&expand=6139) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vxor))] //should be vpxord +pub unsafe fn _mm256_xor_epi32(a: __m256i, b: __m256i) -> __m256i { + transmute(simd_xor(a.as_i32x8(), b.as_i32x8())) +} + +/// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_xor_epi32&expand=6137) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxord))] +pub unsafe fn _mm256_mask_xor_epi32(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let xor = _mm256_xor_epi32(a, b).as_i32x8(); + transmute(simd_select_bitmask(k, xor, src.as_i32x8())) +} + +/// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_xor_epi32&expand=6138) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxord))] +pub unsafe fn _mm256_maskz_xor_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let xor = _mm256_xor_epi32(a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, xor, zero)) +} + +/// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_xor_epi32&expand=6136) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vxor))] //should be vpxord +pub unsafe fn _mm_xor_epi32(a: __m128i, b: __m128i) -> __m128i { + transmute(simd_xor(a.as_i32x4(), b.as_i32x4())) +} + +/// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_xor_epi32&expand=6134) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxord))] +pub unsafe fn _mm_mask_xor_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let xor = _mm_xor_epi32(a, b).as_i32x4(); + transmute(simd_select_bitmask(k, xor, src.as_i32x4())) +} + +/// Compute the bitwise XOR of packed 32-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_xor_epi32&expand=6135) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxord))] +pub unsafe fn _mm_maskz_xor_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let xor = _mm_xor_epi32(a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, xor, zero)) +} + /// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_xor_epi64&expand=6151) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_xor_epi64&expand=6151) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpxorq))] @@ -15725,7 +27265,7 @@ pub unsafe fn _mm512_xor_epi64(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_xor_epi64&expand=6149) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_xor_epi64&expand=6149) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpxorq))] @@ -15736,7 +27276,7 @@ pub unsafe fn _mm512_mask_xor_epi64(src: __m512i, k: __mmask8, a: __m512i, b: __ /// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_xor_epi64&expand=6150) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_xor_epi64&expand=6150) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpxorq))] @@ -15746,9 +27286,75 @@ pub unsafe fn _mm512_maskz_xor_epi64(k: __mmask8, a: __m512i, b: __m512i) -> __m transmute(simd_select_bitmask(k, xor, zero)) } +/// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_xor_epi64&expand=6148) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vxor))] //should be vpxorq +pub unsafe fn _mm256_xor_epi64(a: __m256i, b: __m256i) -> __m256i { + transmute(simd_xor(a.as_i64x4(), b.as_i64x4())) +} + +/// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_xor_epi64&expand=6146) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxorq))] +pub unsafe fn _mm256_mask_xor_epi64(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let xor = _mm256_xor_epi64(a, b).as_i64x4(); + transmute(simd_select_bitmask(k, xor, src.as_i64x4())) +} + +/// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_xor_epi64&expand=6147) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxorq))] +pub unsafe fn _mm256_maskz_xor_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let xor = _mm256_xor_epi64(a, b).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, xor, zero)) +} + +/// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_xor_epi64&expand=6145) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vxor))] //should be vpxorq +pub unsafe fn _mm_xor_epi64(a: __m128i, b: __m128i) -> __m128i { + transmute(simd_xor(a.as_i64x2(), b.as_i64x2())) +} + +/// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_xor_epi64&expand=6143) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxorq))] +pub unsafe fn _mm_mask_xor_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let xor = _mm_xor_epi64(a, b).as_i64x2(); + transmute(simd_select_bitmask(k, xor, src.as_i64x2())) +} + +/// Compute the bitwise XOR of packed 64-bit integers in a and b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_xor_epi64&expand=6144) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpxorq))] +pub unsafe fn _mm_maskz_xor_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let xor = _mm_xor_epi64(a, b).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, xor, zero)) +} + /// Compute the bitwise XOR of 512 bits (representing integer data) in a and b, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_xor_si512&expand=6172) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_xor_si512&expand=6172) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpxorq))] @@ -15758,7 +27364,7 @@ pub unsafe fn _mm512_xor_si512(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise NOT of packed 32-bit integers in a and then AND with b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_andnot_epi32&expand=310) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_andnot_epi32&expand=310) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandnq))] //should be vpandnd @@ -15768,7 +27374,7 @@ pub unsafe fn _mm512_andnot_epi32(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise NOT of packed 32-bit integers in a and then AND with b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_andnot_epi32&expand=311) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_andnot_epi32&expand=311) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandnd))] @@ -15784,7 +27390,7 @@ pub unsafe fn _mm512_mask_andnot_epi32( /// Compute the bitwise NOT of packed 32-bit integers in a and then AND with b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_andnot_epi32&expand=312) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_andnot_epi32&expand=312) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandnd))] @@ -15794,9 +27400,64 @@ pub unsafe fn _mm512_maskz_andnot_epi32(k: __mmask16, a: __m512i, b: __m512i) -> transmute(simd_select_bitmask(k, andnot, zero)) } +/// Compute the bitwise NOT of packed 32-bit integers in a and then AND with b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_andnot_epi32&expand=308) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnd))] +pub unsafe fn _mm256_mask_andnot_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let not = _mm256_xor_epi32(a, _mm256_set1_epi32(u32::MAX as i32)); + let andnot = simd_and(not.as_i32x8(), b.as_i32x8()); + transmute(simd_select_bitmask(k, andnot, src.as_i32x8())) +} + +/// Compute the bitwise NOT of packed 32-bit integers in a and then AND with b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_andnot_epi32&expand=309) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnd))] +pub unsafe fn _mm256_maskz_andnot_epi32(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let not = _mm256_xor_epi32(a, _mm256_set1_epi32(u32::MAX as i32)); + let andnot = simd_and(not.as_i32x8(), b.as_i32x8()); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, andnot, zero)) +} + +/// Compute the bitwise NOT of packed 32-bit integers in a and then AND with b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_andnot_epi32&expand=306) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnd))] +pub unsafe fn _mm_mask_andnot_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let not = _mm_xor_epi32(a, _mm_set1_epi32(u32::MAX as i32)); + let andnot = simd_and(not.as_i32x4(), b.as_i32x4()); + transmute(simd_select_bitmask(k, andnot, src.as_i32x4())) +} + +/// Compute the bitwise NOT of packed 32-bit integers in a and then AND with b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_andnot_epi32&expand=307) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnd))] +pub unsafe fn _mm_maskz_andnot_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let not = _mm_xor_epi32(a, _mm_set1_epi32(u32::MAX as i32)); + let andnot = simd_and(not.as_i32x4(), b.as_i32x4()); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, andnot, zero)) +} + /// Compute the bitwise NOT of 512 bits (composed of packed 64-bit integers) in a and then AND with b, and store the results in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_andnot_epi64&expand=317) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_andnot_epi64&expand=317) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandnq))] //should be vpandnd @@ -15806,7 +27467,7 @@ pub unsafe fn _mm512_andnot_epi64(a: __m512i, b: __m512i) -> __m512i { /// Compute the bitwise NOT of packed 64-bit integers in a and then AND with b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_andnot_epi64&expand=318) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_andnot_epi64&expand=318) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandnq))] @@ -15822,7 +27483,7 @@ pub unsafe fn _mm512_mask_andnot_epi64( /// Compute the bitwise NOT of packed 64-bit integers in a and then AND with b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_andnot_epi64&expand=319) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_andnot_epi64&expand=319) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandnq))] @@ -15832,9 +27493,64 @@ pub unsafe fn _mm512_maskz_andnot_epi64(k: __mmask8, a: __m512i, b: __m512i) -> transmute(simd_select_bitmask(k, andnot, zero)) } +/// Compute the bitwise NOT of packed 64-bit integers in a and then AND with b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_andnot_epi64&expand=315) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnq))] +pub unsafe fn _mm256_mask_andnot_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let not = _mm256_xor_epi64(a, _mm256_set1_epi64x(u64::MAX as i64)); + let andnot = simd_and(not.as_i64x4(), b.as_i64x4()); + transmute(simd_select_bitmask(k, andnot, src.as_i64x4())) +} + +/// Compute the bitwise NOT of packed 64-bit integers in a and then AND with b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_andnot_epi64&expand=316) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnq))] +pub unsafe fn _mm256_maskz_andnot_epi64(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { + let not = _mm256_xor_epi64(a, _mm256_set1_epi64x(u64::MAX as i64)); + let andnot = simd_and(not.as_i64x4(), b.as_i64x4()); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, andnot, zero)) +} + +/// Compute the bitwise NOT of packed 64-bit integers in a and then AND with b, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_andnot_epi64&expand=313) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnq))] +pub unsafe fn _mm_mask_andnot_epi64(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let not = _mm_xor_epi64(a, _mm_set1_epi64x(u64::MAX as i64)); + let andnot = simd_and(not.as_i64x2(), b.as_i64x2()); + transmute(simd_select_bitmask(k, andnot, src.as_i64x2())) +} + +/// Compute the bitwise NOT of packed 64-bit integers in a and then AND with b, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_andnot_epi64&expand=314) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpandnq))] +pub unsafe fn _mm_maskz_andnot_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let not = _mm_xor_epi64(a, _mm_set1_epi64x(u64::MAX as i64)); + let andnot = simd_and(not.as_i64x2(), b.as_i64x2()); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, andnot, zero)) +} + /// Compute the bitwise NOT of 512 bits (representing integer data) in a and then AND with b, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_andnot_si512&expand=340) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_andnot_si512&expand=340) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpandnq))] @@ -16021,7 +27737,7 @@ pub unsafe fn _mm512_kortestc(a: __mmask16, b: __mmask16) -> i32 { /// Compute the bitwise AND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_test_epi32_mask&expand=5890) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_test_epi32_mask&expand=5890) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestmd))] @@ -16033,7 +27749,7 @@ pub unsafe fn _mm512_test_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// Compute the bitwise AND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_test_epi32_mask&expand=5889) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_test_epi32_mask&expand=5889) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestmd))] @@ -16043,9 +27759,57 @@ pub unsafe fn _mm512_mask_test_epi32_mask(k: __mmask16, a: __m512i, b: __m512i) _mm512_mask_cmpneq_epi32_mask(k, and, zero) } +/// Compute the bitwise AND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_test_epi32_mask&expand=5888) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmd))] +pub unsafe fn _mm256_test_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpneq_epi32_mask(and, zero) +} + +/// Compute the bitwise AND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_test_epi32_mask&expand=5887) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmd))] +pub unsafe fn _mm256_mask_test_epi32_mask(k: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpneq_epi32_mask(k, and, zero) +} + +/// Compute the bitwise AND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_epi32_mask&expand=5886) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmd))] +pub unsafe fn _mm_test_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpneq_epi32_mask(and, zero) +} + +/// Compute the bitwise AND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_test_epi32_mask&expand=5885) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmd))] +pub unsafe fn _mm_mask_test_epi32_mask(k: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpneq_epi32_mask(k, and, zero) +} + /// Compute the bitwise AND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_test_epi64_mask&expand=5896) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_test_epi64_mask&expand=5896) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestmq))] @@ -16057,7 +27821,7 @@ pub unsafe fn _mm512_test_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// Compute the bitwise AND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_test_epi64_mask&expand=5895) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_test_epi64_mask&expand=5895) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestmq))] @@ -16067,9 +27831,57 @@ pub unsafe fn _mm512_mask_test_epi64_mask(k: __mmask8, a: __m512i, b: __m512i) - _mm512_mask_cmpneq_epi64_mask(k, and, zero) } +/// Compute the bitwise AND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_test_epi64_mask&expand=5894) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmq))] +pub unsafe fn _mm256_test_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpneq_epi64_mask(and, zero) +} + +/// Compute the bitwise AND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_test_epi64_mask&expand=5893) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmq))] +pub unsafe fn _mm256_mask_test_epi64_mask(k: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpneq_epi64_mask(k, and, zero) +} + +/// Compute the bitwise AND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_epi64_mask&expand=5892) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmq))] +pub unsafe fn _mm_test_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpneq_epi64_mask(and, zero) +} + +/// Compute the bitwise AND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is non-zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_test_epi64_mask&expand=5891) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestmq))] +pub unsafe fn _mm_mask_test_epi64_mask(k: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpneq_epi64_mask(k, and, zero) +} + /// Compute the bitwise NAND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_testn_epi32_mask&expand=5921) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_testn_epi32_mask&expand=5921) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestnmd))] @@ -16081,7 +27893,7 @@ pub unsafe fn _mm512_testn_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// Compute the bitwise NAND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_testn_epi32_mask&expand=5920) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_testn_epi32_mask&expand=5920) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestnmd))] @@ -16091,9 +27903,57 @@ pub unsafe fn _mm512_mask_testn_epi32_mask(k: __mmask16, a: __m512i, b: __m512i) _mm512_mask_cmpeq_epi32_mask(k, and, zero) } +/// Compute the bitwise NAND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_testn_epi32_mask&expand=5919) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmd))] +pub unsafe fn _mm256_testn_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpeq_epi32_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_testn_epi32_mask&expand=5918) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmd))] +pub unsafe fn _mm256_mask_testn_epi32_mask(k: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpeq_epi32_mask(k, and, zero) +} + +/// Compute the bitwise NAND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testn_epi32_mask&expand=5917) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmd))] +pub unsafe fn _mm_testn_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpeq_epi32_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 32-bit integers in a and b, producing intermediate 32-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_testn_epi32_mask&expand=5916) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmd))] +pub unsafe fn _mm_mask_testn_epi32_mask(k: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpeq_epi32_mask(k, and, zero) +} + /// Compute the bitwise NAND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_testn_epi64_mask&expand=5927) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_testn_epi64_mask&expand=5927) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestnmq))] @@ -16105,7 +27965,7 @@ pub unsafe fn _mm512_testn_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// Compute the bitwise NAND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_testn_epi64_mask&expand=5926) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_testn_epi64_mask&expand=5926) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vptestnmq))] @@ -16115,9 +27975,57 @@ pub unsafe fn _mm512_mask_testn_epi64_mask(k: __mmask8, a: __m512i, b: __m512i) _mm512_mask_cmpeq_epi64_mask(k, and, zero) } +/// Compute the bitwise NAND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_testn_epi64_mask&expand=5925) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmq))] +pub unsafe fn _mm256_testn_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_cmpeq_epi64_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_testn_epi64_mask&expand=5924) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmq))] +pub unsafe fn _mm256_mask_testn_epi64_mask(k: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + let and = _mm256_and_si256(a, b); + let zero = _mm256_setzero_si256(); + _mm256_mask_cmpeq_epi64_mask(k, and, zero) +} + +/// Compute the bitwise NAND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testn_epi64_mask&expand=5923) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmq))] +pub unsafe fn _mm_testn_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_cmpeq_epi64_mask(and, zero) +} + +/// Compute the bitwise NAND of packed 64-bit integers in a and b, producing intermediate 64-bit values, and set the corresponding bit in result mask k (subject to writemask k) if the intermediate value is zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_testn_epi64_mask&expand=5922) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vptestnmq))] +pub unsafe fn _mm_mask_testn_epi64_mask(k: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + let and = _mm_and_si128(a, b); + let zero = _mm_setzero_si128(); + _mm_mask_cmpeq_epi64_mask(k, and, zero) +} + /// Store 512-bits (composed of 16 packed single-precision (32-bit) floating-point elements) from a into memory using a non-temporal memory hint. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_stream_ps&expand=5671) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_stream_ps&expand=5671) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovntps))] @@ -16128,7 +28036,7 @@ pub unsafe fn _mm512_stream_ps(mem_addr: *mut f32, a: __m512) { /// Store 512-bits (composed of 8 packed double-precision (64-bit) floating-point elements) from a into memory using a non-temporal memory hint. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_stream_pd&expand=5667) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_stream_pd&expand=5667) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovntps))] //should be vmovntpd @@ -16139,7 +28047,7 @@ pub unsafe fn _mm512_stream_pd(mem_addr: *mut f64, a: __m512d) { /// Store 512-bits of integer data from a into memory using a non-temporal memory hint. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_stream_si512&expand=5675) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_stream_si512&expand=5675) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovntps))] //should be vmovntdq @@ -16150,7 +28058,7 @@ pub unsafe fn _mm512_stream_si512(mem_addr: *mut i64, a: __m512i) { /// Sets packed 32-bit integers in `dst` with the supplied values. /// -/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=727,1063,4909,1062,1062,4909&text=_mm512_set_ps) +/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_ps&expand=4931) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set_ps( @@ -16179,7 +28087,7 @@ pub unsafe fn _mm512_set_ps( /// Sets packed 32-bit integers in `dst` with the supplied values in /// reverse order. /// -/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=727,1063,4909,1062,1062,4909&text=_mm512_set_ps) +/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_ps&expand=5008) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_setr_ps( @@ -16207,6 +28115,8 @@ pub unsafe fn _mm512_setr_ps( } /// Broadcast 64-bit float `a` to all elements of `dst`. +/// +/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_pd&expand=4975) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set1_pd(a: f64) -> __m512d { @@ -16214,6 +28124,8 @@ pub unsafe fn _mm512_set1_pd(a: f64) -> __m512d { } /// Broadcast 32-bit float `a` to all elements of `dst`. +/// +/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_ps&expand=4981) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set1_ps(a: f32) -> __m512 { @@ -16221,6 +28133,8 @@ pub unsafe fn _mm512_set1_ps(a: f32) -> __m512 { } /// Sets packed 32-bit integers in `dst` with the supplied values. +/// +/// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set_epi32&expand=4908) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set_epi32( @@ -16248,7 +28162,7 @@ pub unsafe fn _mm512_set_epi32( /// Broadcast 8-bit integer a to all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set1_epi8&expand=4972) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi8&expand=4972) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set1_epi8(a: i8) -> __m512i { @@ -16257,7 +28171,7 @@ pub unsafe fn _mm512_set1_epi8(a: i8) -> __m512i { /// Broadcast the low packed 16-bit integer from a to all all elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set1_epi16&expand=4944) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi16&expand=4944) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set1_epi16(a: i16) -> __m512i { @@ -16273,7 +28187,7 @@ pub unsafe fn _mm512_set1_epi32(a: i32) -> __m512i { /// Broadcast 32-bit integer a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_set1_epi32&expand=4951) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_set1_epi32&expand=4951) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcastd))] @@ -16284,7 +28198,7 @@ pub unsafe fn _mm512_mask_set1_epi32(src: __m512i, k: __mmask16, a: i32) -> __m5 /// Broadcast 32-bit integer a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_set1_epi32&expand=4952) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_set1_epi32&expand=4952) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcastd))] @@ -16294,7 +28208,55 @@ pub unsafe fn _mm512_maskz_set1_epi32(k: __mmask16, a: i32) -> __m512i { transmute(simd_select_bitmask(k, r, zero)) } +/// Broadcast 32-bit integer a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_set1_epi32&expand=4948) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastd))] +pub unsafe fn _mm256_mask_set1_epi32(src: __m256i, k: __mmask8, a: i32) -> __m256i { + let r = _mm256_set1_epi32(a).as_i32x8(); + transmute(simd_select_bitmask(k, r, src.as_i32x8())) +} + +/// Broadcast 32-bit integer a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_set1_epi32&expand=4949) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastd))] +pub unsafe fn _mm256_maskz_set1_epi32(k: __mmask8, a: i32) -> __m256i { + let r = _mm256_set1_epi32(a).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Broadcast 32-bit integer a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_set1_epi32&expand=4945) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastd))] +pub unsafe fn _mm_mask_set1_epi32(src: __m128i, k: __mmask8, a: i32) -> __m128i { + let r = _mm_set1_epi32(a).as_i32x4(); + transmute(simd_select_bitmask(k, r, src.as_i32x4())) +} + +/// Broadcast 32-bit integer a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_set1_epi32&expand=4946) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastd))] +pub unsafe fn _mm_maskz_set1_epi32(k: __mmask8, a: i32) -> __m128i { + let r = _mm_set1_epi32(a).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r, zero)) +} + /// Broadcast 64-bit integer `a` to all elements of `dst`. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi64&expand=4961) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set1_epi64(a: i64) -> __m512i { @@ -16303,7 +28265,7 @@ pub unsafe fn _mm512_set1_epi64(a: i64) -> __m512i { /// Broadcast 64-bit integer a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_set1_epi64&expand=4959) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_set1_epi64&expand=4959) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcastq))] @@ -16314,7 +28276,7 @@ pub unsafe fn _mm512_mask_set1_epi64(src: __m512i, k: __mmask8, a: i64) -> __m51 /// Broadcast 64-bit integer a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_maskz_set1_epi64&expand=4960) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_set1_epi64&expand=4960) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vpbroadcastq))] @@ -16324,9 +28286,55 @@ pub unsafe fn _mm512_maskz_set1_epi64(k: __mmask8, a: i64) -> __m512i { transmute(simd_select_bitmask(k, r, zero)) } +/// Broadcast 64-bit integer a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_set1_epi64&expand=4957) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastq))] +pub unsafe fn _mm256_mask_set1_epi64(src: __m256i, k: __mmask8, a: i64) -> __m256i { + let r = _mm256_set1_epi64x(a).as_i64x4(); + transmute(simd_select_bitmask(k, r, src.as_i64x4())) +} + +/// Broadcast 64-bit integer a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_set1_epi64&expand=4958) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastq))] +pub unsafe fn _mm256_maskz_set1_epi64(k: __mmask8, a: i64) -> __m256i { + let r = _mm256_set1_epi64x(a).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Broadcast 64-bit integer a to all elements of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_set1_epi64&expand=4954) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastq))] +pub unsafe fn _mm_mask_set1_epi64(src: __m128i, k: __mmask8, a: i64) -> __m128i { + let r = _mm_set1_epi64x(a).as_i64x2(); + transmute(simd_select_bitmask(k, r, src.as_i64x2())) +} + +/// Broadcast 64-bit integer a to all elements of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_set1_epi64&expand=4955) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpbroadcastq))] +pub unsafe fn _mm_maskz_set1_epi64(k: __mmask8, a: i64) -> __m128i { + let r = _mm_set1_epi64x(a).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, r, zero)) +} + /// Set packed 64-bit integers in dst with the repeated 4 element sequence. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_set4_epi64&expand=4983) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set4_epi64&expand=4983) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_set4_epi64(d: i64, c: i64, b: i64, a: i64) -> __m512i { @@ -16336,7 +28344,7 @@ pub unsafe fn _mm512_set4_epi64(d: i64, c: i64, b: i64, a: i64) -> __m512i { /// Set packed 64-bit integers in dst with the repeated 4 element sequence in reverse order. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_setr4_epi64&expand=5010) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr4_epi64&expand=5010) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_setr4_epi64(d: i64, c: i64, b: i64, a: i64) -> __m512i { @@ -16346,142 +28354,138 @@ pub unsafe fn _mm512_setr4_epi64(d: i64, c: i64, b: i64, a: i64) -> __m512i { /// Compare packed single-precision (32-bit) floating-point elements in a and b for less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmplt_ps_mask&expand=1074) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_ps_mask&expand=1074) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_cmplt_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_LT_OS) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmplt_ps_mask&expand=1075) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_ps_mask&expand=1075) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmplt_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_LT_OS) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for not-less-than, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmpnlt_ps_mask&expand=1154) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnlt_ps_mask&expand=1154) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_cmpnlt_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_NLT_US) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for not-less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmpnlt_ps_mask&expand=1155) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnlt_ps_mask&expand=1155) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmpnlt_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_NLT_US) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmple_ps_mask&expand=1013) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_ps_mask&expand=1013) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_cmple_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_LE_OS) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmple_ps_mask&expand=1014) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_ps_mask&expand=1014) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmple_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_LE_OS) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for not-less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmpnle_ps_mask&expand=1146) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnle_ps_mask&expand=1146) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_cmpnle_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_NLE_US) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for not-less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmpnle_ps_mask&expand=1147) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnle_ps_mask&expand=1147) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmpnle_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_NLE_US) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for equality, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmpeq_ps_mask&expand=828) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_ps_mask&expand=828) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_cmpeq_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_EQ_OQ) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmpeq_ps_mask&expand=829) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_ps_mask&expand=829) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmpeq_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_EQ_OQ) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for not-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmpneq_ps_mask&expand=1130) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_ps_mask&expand=1130) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_cmpneq_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_NEQ_UQ) } /// Compare packed single-precision (32-bit) floating-point elements in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmpneq_ps_mask&expand=1131) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_ps_mask&expand=1131) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmpneq_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_NEQ_UQ) } /// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmp_ps_mask&expand=749) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_ps_mask&expand=749) #[inline] #[target_feature(enable = "avx512f")] #[rustc_args_required_const(2)] #[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] pub unsafe fn _mm512_cmp_ps_mask(a: __m512, b: __m512, imm8: i32) -> __mmask16 { let neg_one = -1; + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm5:expr) => { - vcmpps( - a.as_f32x16(), - b.as_f32x16(), - $imm5, - neg_one, - _MM_FROUND_CUR_DIRECTION, - ) + vcmpps(a, b, $imm5, neg_one, _MM_FROUND_CUR_DIRECTION) }; } let r = constify_imm5!(imm8, call); @@ -16490,21 +28494,95 @@ pub unsafe fn _mm512_cmp_ps_mask(a: __m512, b: __m512, imm8: i32) -> __mmask16 { /// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmp_ps_mask&expand=750) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_ps_mask&expand=750) #[inline] #[target_feature(enable = "avx512f")] #[rustc_args_required_const(3)] #[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] pub unsafe fn _mm512_mask_cmp_ps_mask(k1: __mmask16, a: __m512, b: __m512, imm8: i32) -> __mmask16 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm5:expr) => { - vcmpps( - a.as_f32x16(), - b.as_f32x16(), - $imm5, - k1 as i16, - _MM_FROUND_CUR_DIRECTION, - ) + vcmpps(a, b, $imm5, k1 as i16, _MM_FROUND_CUR_DIRECTION) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_ps_mask&expand=747) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_ps_mask(a: __m256, b: __m256, imm8: i32) -> __mmask8 { + let neg_one = -1; + let a = a.as_f32x8(); + let b = b.as_f32x8(); + macro_rules! call { + ($imm5:expr) => { + vcmpps256(a, b, $imm5, neg_one) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_ps_mask&expand=748) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_ps_mask(k1: __mmask8, a: __m256, b: __m256, imm8: i32) -> __mmask8 { + let a = a.as_f32x8(); + let b = b.as_f32x8(); + macro_rules! call { + ($imm5:expr) => { + vcmpps256(a, b, $imm5, k1 as i8) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_ps_mask&expand=745) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_ps_mask(a: __m128, b: __m128, imm8: i32) -> __mmask8 { + let neg_one = -1; + let a = a.as_f32x4(); + let b = b.as_f32x4(); + macro_rules! call { + ($imm5:expr) => { + vcmpps128(a, b, $imm5, neg_one) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_ps_mask&expand=746) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_ps_mask(k1: __mmask8, a: __m128, b: __m128, imm8: i32) -> __mmask8 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + macro_rules! call { + ($imm5:expr) => { + vcmpps128(a, b, $imm5, k1 as i8) }; } let r = constify_imm5!(imm8, call); @@ -16514,16 +28592,18 @@ pub unsafe fn _mm512_mask_cmp_ps_mask(k1: __mmask16, a: __m512, b: __m512, imm8: /// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_cmp_round_ps_mask&expand=753) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_round_ps_mask&expand=753) #[inline] #[target_feature(enable = "avx512f")] #[rustc_args_required_const(2, 3)] #[cfg_attr(test, assert_instr(vcmp, imm8 = 0, sae = 4))] pub unsafe fn _mm512_cmp_round_ps_mask(a: __m512, b: __m512, imm8: i32, sae: i32) -> __mmask16 { let neg_one = -1; + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm5:expr, $imm4:expr) => { - vcmpps(a.as_f32x16(), b.as_f32x16(), $imm5, neg_one, $imm4) + vcmpps(a, b, $imm5, neg_one, $imm4) }; } let r = constify_imm5_sae!(imm8, sae, call); @@ -16533,7 +28613,7 @@ pub unsafe fn _mm512_cmp_round_ps_mask(a: __m512, b: __m512, imm8: i32, sae: i32 /// Compare packed single-precision (32-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_cmp_round_ps_mask&expand=754) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmp_round_ps_mask&expand=754) #[inline] #[target_feature(enable = "avx512f")] #[rustc_args_required_const(3, 4)] @@ -16545,9 +28625,11 @@ pub unsafe fn _mm512_mask_cmp_round_ps_mask( imm8: i32, sae: i32, ) -> __mmask16 { + let a = a.as_f32x16(); + let b = b.as_f32x16(); macro_rules! call { ($imm5:expr, $imm4:expr) => { - vcmpps(a.as_f32x16(), b.as_f32x16(), $imm5, m as i16, $imm4) + vcmpps(a, b, $imm5, m as i16, $imm4) }; } let r = constify_imm5_sae!(imm8, sae, call); @@ -16559,7 +28641,7 @@ pub unsafe fn _mm512_mask_cmp_round_ps_mask( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpord_ps_mask&expand=1162) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmps pub unsafe fn _mm512_cmpord_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_ORD_Q) } @@ -16569,7 +28651,7 @@ pub unsafe fn _mm512_cmpord_ps_mask(a: __m512, b: __m512) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpord_ps_mask&expand=1163) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmpord_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_ORD_Q) } @@ -16579,7 +28661,7 @@ pub unsafe fn _mm512_mask_cmpord_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpunord_ps_mask&expand=1170) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_cmpunord_ps_mask(a: __m512, b: __m512) -> __mmask16 { _mm512_cmp_ps_mask(a, b, _CMP_UNORD_Q) } @@ -16589,7 +28671,7 @@ pub unsafe fn _mm512_cmpunord_ps_mask(a: __m512, b: __m512) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpunord_ps_mask&expand=1171) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmpps pub unsafe fn _mm512_mask_cmpunord_ps_mask(k1: __mmask16, a: __m512, b: __m512) -> __mmask16 { _mm512_mask_cmp_ps_mask(k1, a, b, _CMP_UNORD_Q) } @@ -16599,7 +28681,7 @@ pub unsafe fn _mm512_mask_cmpunord_ps_mask(k1: __mmask16, a: __m512, b: __m512) /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_pd_mask&expand=1071) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmplt_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_LT_OS) } @@ -16609,7 +28691,7 @@ pub unsafe fn _mm512_cmplt_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_pd_mask&expand=1072) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmplt_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(k1, a, b, _CMP_LT_OS) } @@ -16619,7 +28701,7 @@ pub unsafe fn _mm512_mask_cmplt_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnlt_pd_mask&expand=1151) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmpnlt_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_NLT_US) } @@ -16629,7 +28711,7 @@ pub unsafe fn _mm512_cmpnlt_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnlt_pd_mask&expand=1152) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmpnlt_pd_mask(m: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLT_US) } @@ -16639,7 +28721,7 @@ pub unsafe fn _mm512_mask_cmpnlt_pd_mask(m: __mmask8, a: __m512d, b: __m512d) -> /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_pd_mask&expand=1010) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmple_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_LE_OS) } @@ -16649,7 +28731,7 @@ pub unsafe fn _mm512_cmple_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_pd_mask&expand=1011) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmple_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(k1, a, b, _CMP_LE_OS) } @@ -16659,7 +28741,7 @@ pub unsafe fn _mm512_mask_cmple_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpnle_pd_mask&expand=1143) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmpnle_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_NLE_US) } @@ -16669,7 +28751,7 @@ pub unsafe fn _mm512_cmpnle_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpnle_pd_mask&expand=1144) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmpnle_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(k1, a, b, _CMP_NLE_US) } @@ -16679,7 +28761,7 @@ pub unsafe fn _mm512_mask_cmpnle_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) - /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_pd_mask&expand=822) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmpeq_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_EQ_OQ) } @@ -16689,7 +28771,7 @@ pub unsafe fn _mm512_cmpeq_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_pd_mask&expand=823) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmpeq_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(k1, a, b, _CMP_EQ_OQ) } @@ -16699,7 +28781,7 @@ pub unsafe fn _mm512_mask_cmpeq_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_pd_mask&expand=1127) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmpneq_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_NEQ_UQ) } @@ -16709,7 +28791,7 @@ pub unsafe fn _mm512_cmpneq_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_pd_mask&expand=1128) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmpneq_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(k1, a, b, _CMP_NEQ_UQ) } @@ -16723,15 +28805,11 @@ pub unsafe fn _mm512_mask_cmpneq_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) - #[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] pub unsafe fn _mm512_cmp_pd_mask(a: __m512d, b: __m512d, imm8: i32) -> __mmask8 { let neg_one = -1; + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm5:expr) => { - vcmppd( - a.as_f64x8(), - b.as_f64x8(), - $imm5, - neg_one, - _MM_FROUND_CUR_DIRECTION, - ) + vcmppd(a, b, $imm5, neg_one, _MM_FROUND_CUR_DIRECTION) }; } let r = constify_imm5!(imm8, call); @@ -16746,15 +28824,89 @@ pub unsafe fn _mm512_cmp_pd_mask(a: __m512d, b: __m512d, imm8: i32) -> __mmask8 #[rustc_args_required_const(3)] #[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] pub unsafe fn _mm512_mask_cmp_pd_mask(k1: __mmask8, a: __m512d, b: __m512d, imm8: i32) -> __mmask8 { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm5:expr) => { - vcmppd( - a.as_f64x8(), - b.as_f64x8(), - $imm5, - k1 as i8, - _MM_FROUND_CUR_DIRECTION, - ) + vcmppd(a, b, $imm5, k1 as i8, _MM_FROUND_CUR_DIRECTION) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_pd_mask&expand=739) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_pd_mask(a: __m256d, b: __m256d, imm8: i32) -> __mmask8 { + let neg_one = -1; + let a = a.as_f64x4(); + let b = b.as_f64x4(); + macro_rules! call { + ($imm5:expr) => { + vcmppd256(a, b, $imm5, neg_one) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_pd_mask&expand=740) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_pd_mask(k1: __mmask8, a: __m256d, b: __m256d, imm8: i32) -> __mmask8 { + let a = a.as_f64x4(); + let b = b.as_f64x4(); + macro_rules! call { + ($imm5:expr) => { + vcmppd256(a, b, $imm5, k1 as i8) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_pd_mask&expand=737) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_pd_mask(a: __m128d, b: __m128d, imm8: i32) -> __mmask8 { + let neg_one = -1; + let a = a.as_f64x2(); + let b = b.as_f64x2(); + macro_rules! call { + ($imm5:expr) => { + vcmppd128(a, b, $imm5, neg_one) + }; + } + let r = constify_imm5!(imm8, call); + transmute(r) +} + +/// Compare packed double-precision (64-bit) floating-point elements in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_pd_mask&expand=738) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_pd_mask(k1: __mmask8, a: __m128d, b: __m128d, imm8: i32) -> __mmask8 { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + macro_rules! call { + ($imm5:expr) => { + vcmppd128(a, b, $imm5, k1 as i8) }; } let r = constify_imm5!(imm8, call); @@ -16771,9 +28923,11 @@ pub unsafe fn _mm512_mask_cmp_pd_mask(k1: __mmask8, a: __m512d, b: __m512d, imm8 #[cfg_attr(test, assert_instr(vcmp, imm8 = 0, sae = 4))] pub unsafe fn _mm512_cmp_round_pd_mask(a: __m512d, b: __m512d, imm8: i32, sae: i32) -> __mmask8 { let neg_one = -1; + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm5:expr, $imm4:expr) => { - vcmppd(a.as_f64x8(), b.as_f64x8(), $imm5, neg_one, $imm4) + vcmppd(a, b, $imm5, neg_one, $imm4) }; } let r = constify_imm5_sae!(imm8, sae, call); @@ -16795,9 +28949,11 @@ pub unsafe fn _mm512_mask_cmp_round_pd_mask( imm8: i32, sae: i32, ) -> __mmask8 { + let a = a.as_f64x8(); + let b = b.as_f64x8(); macro_rules! call { ($imm5:expr, $imm4:expr) => { - vcmppd(a.as_f64x8(), b.as_f64x8(), $imm5, k1 as i8, $imm4) + vcmppd(a, b, $imm5, k1 as i8, $imm4) }; } let r = constify_imm5_sae!(imm8, sae, call); @@ -16809,7 +28965,7 @@ pub unsafe fn _mm512_mask_cmp_round_pd_mask( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpord_pd_mask&expand=1159) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmpord_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_ORD_Q) } @@ -16819,7 +28975,7 @@ pub unsafe fn _mm512_cmpord_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpord_pd_mask&expand=1160) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmpord_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(k1, a, b, _CMP_ORD_Q) } @@ -16829,7 +28985,7 @@ pub unsafe fn _mm512_mask_cmpord_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) - /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpunord_pd_mask&expand=1167) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_cmpunord_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { _mm512_cmp_pd_mask(a, b, _CMP_UNORD_Q) } @@ -16839,7 +28995,7 @@ pub unsafe fn _mm512_cmpunord_pd_mask(a: __m512d, b: __m512d) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpunord_pd_mask&expand=1168) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vcmp))] +#[cfg_attr(test, assert_instr(vcmp))] //should be vcmppd pub unsafe fn _mm512_mask_cmpunord_pd_mask(k1: __mmask8, a: __m512d, b: __m512d) -> __mmask8 { _mm512_mask_cmp_pd_mask(k1, a, b, _CMP_UNORD_Q) } @@ -17005,7 +29161,7 @@ pub unsafe fn _mm_mask_cmp_round_sd_mask( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epu32_mask&expand=1056) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_cmplt_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_lt(a.as_u32x16(), b.as_u32x16())) } @@ -17015,17 +29171,57 @@ pub unsafe fn _mm512_cmplt_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epu32_mask&expand=1057) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_mask_cmplt_epu32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmplt_epu32_mask(a, b) & k1 } +/// Compare packed unsigned 32-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmplt_epu32_mask&expand=1054) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_cmplt_epu32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_lt(a.as_u32x8(), b.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epu32_mask&expand=1055) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_mask_cmplt_epu32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmplt_epu32_mask(a, b) & k1 +} + +/// Compare packed unsigned 32-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epu32_mask&expand=1052) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_cmplt_epu32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_lt(a.as_u32x4(), b.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epu32_mask&expand=1053) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_mask_cmplt_epu32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmplt_epu32_mask(a, b) & k1 +} + /// Compare packed unsigned 32-bit integers in a and b for greater-than, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu32_mask&expand=933) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_cmpgt_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_gt(a.as_u32x16(), b.as_u32x16())) } @@ -17035,17 +29231,57 @@ pub unsafe fn _mm512_cmpgt_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu32_mask&expand=934) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_mask_cmpgt_epu32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpgt_epu32_mask(a, b) & k1 } +/// Compare packed unsigned 32-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epu32_mask&expand=931) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_cmpgt_epu32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_gt(a.as_u32x8(), b.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epu32_mask&expand=932) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_mask_cmpgt_epu32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpgt_epu32_mask(a, b) & k1 +} + +/// Compare packed unsigned 32-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epu32_mask&expand=929) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_cmpgt_epu32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_gt(a.as_u32x4(), b.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epu32_mask&expand=930) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_mask_cmpgt_epu32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpgt_epu32_mask(a, b) & k1 +} + /// Compare packed unsigned 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu32_mask&expand=995) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_cmple_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_le(a.as_u32x16(), b.as_u32x16())) } @@ -17055,17 +29291,57 @@ pub unsafe fn _mm512_cmple_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu32_mask&expand=996) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_mask_cmple_epu32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmple_epu32_mask(a, b) & k1 } +/// Compare packed unsigned 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epu32_mask&expand=993) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_cmple_epu32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_le(a.as_u32x8(), b.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epu32_mask&expand=994) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_mask_cmple_epu32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmple_epu32_mask(a, b) & k1 +} + +/// Compare packed unsigned 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epu32_mask&expand=991) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_cmple_epu32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_le(a.as_u32x4(), b.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epu32_mask&expand=992) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_mask_cmple_epu32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmple_epu32_mask(a, b) & k1 +} + /// Compare packed unsigned 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu32_mask&expand=873) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_cmpge_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_ge(a.as_u32x16(), b.as_u32x16())) } @@ -17075,17 +29351,57 @@ pub unsafe fn _mm512_cmpge_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu32_mask&expand=874) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_mask_cmpge_epu32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpge_epu32_mask(a, b) & k1 } +/// Compare packed unsigned 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epu32_mask&expand=871) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_cmpge_epu32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_ge(a.as_u32x8(), b.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epu32_mask&expand=872) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_mask_cmpge_epu32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpge_epu32_mask(a, b) & k1 +} + +/// Compare packed unsigned 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epu32_mask&expand=869) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_cmpge_epu32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ge(a.as_u32x4(), b.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epu32_mask&expand=870) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_mask_cmpge_epu32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpge_epu32_mask(a, b) & k1 +} + /// Compare packed unsigned 32-bit integers in a and b for equality, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu32_mask&expand=807) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_cmpeq_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_eq(a.as_u32x16(), b.as_u32x16())) } @@ -17095,17 +29411,57 @@ pub unsafe fn _mm512_cmpeq_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu32_mask&expand=808) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_mask_cmpeq_epu32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpeq_epu32_mask(a, b) & k1 } +/// Compare packed unsigned 32-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epu32_mask&expand=805) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_cmpeq_epu32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_eq(a.as_u32x8(), b.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epu32_mask&expand=806) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_mask_cmpeq_epu32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpeq_epu32_mask(a, b) & k1 +} + +/// Compare packed unsigned 32-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epu32_mask&expand=803) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_cmpeq_epu32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_eq(a.as_u32x4(), b.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epu32_mask&expand=804) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_mask_cmpeq_epu32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpeq_epu32_mask(a, b) & k1 +} + /// Compare packed unsigned 32-bit integers in a and b for not-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu32_mask&expand=1112) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_cmpneq_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_ne(a.as_u32x16(), b.as_u32x16())) } @@ -17115,11 +29471,51 @@ pub unsafe fn _mm512_cmpneq_epu32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu32_mask&expand=1113) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud pub unsafe fn _mm512_mask_cmpneq_epu32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpneq_epu32_mask(a, b) & k1 } +/// Compare packed unsigned 32-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epu32_mask&expand=1110) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_cmpneq_epu32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_ne(a.as_u32x8(), b.as_u32x8())) +} + +/// Compare packed unsigned 32-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epu32_mask&expand=1111) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm256_mask_cmpneq_epu32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpneq_epu32_mask(a, b) & k1 +} + +/// Compare packed unsigned 32-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epu32_mask&expand=1108) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_cmpneq_epu32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ne(a.as_u32x4(), b.as_u32x4())) +} + +/// Compare packed unsigned 32-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epu32_mask&expand=1109) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpud +pub unsafe fn _mm_mask_cmpneq_epu32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpneq_epu32_mask(a, b) & k1 +} + /// Compare packed unsigned 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu32_mask&expand=721) @@ -17129,9 +29525,11 @@ pub unsafe fn _mm512_mask_cmpneq_epu32_mask(k1: __mmask16, a: __m512i, b: __m512 #[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] pub unsafe fn _mm512_cmp_epu32_mask(a: __m512i, b: __m512i, imm8: _MM_CMPINT_ENUM) -> __mmask16 { let neg_one = -1; + let a = a.as_i32x16(); + let b = b.as_i32x16(); macro_rules! call { ($imm3:expr) => { - vpcmpud(a.as_i32x16(), b.as_i32x16(), $imm3, neg_one) + vpcmpud(a, b, $imm3, neg_one) }; } let r = constify_imm3!(imm8, call); @@ -17151,9 +29549,99 @@ pub unsafe fn _mm512_mask_cmp_epu32_mask( b: __m512i, imm8: _MM_CMPINT_ENUM, ) -> __mmask16 { + let a = a.as_i32x16(); + let b = b.as_i32x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpud(a, b, $imm3, k1 as i16) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_epu32_mask&expand=719) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epu32_mask(a: __m256i, b: __m256i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i32x8(); + let b = b.as_i32x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpud256(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epu32_mask&expand=720) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epu32_mask( + k1: __mmask8, + a: __m256i, + b: __m256i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i32x8(); + let b = b.as_i32x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpud256(a, b, $imm3, k1 as i8) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epu32_mask&expand=717) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epu32_mask(a: __m128i, b: __m128i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i32x4(); + let b = b.as_i32x4(); macro_rules! call { ($imm3:expr) => { - vpcmpud(a.as_i32x16(), b.as_i32x16(), $imm3, k1 as i16) + vpcmpud128(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epu32_mask&expand=718) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epu32_mask( + k1: __mmask8, + a: __m128i, + b: __m128i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i32x4(); + let b = b.as_i32x4(); + macro_rules! call { + ($imm3:expr) => { + vpcmpud128(a, b, $imm3, k1 as i8) }; } let r = constify_imm3!(imm8, call); @@ -17165,7 +29653,7 @@ pub unsafe fn _mm512_mask_cmp_epu32_mask( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi32_mask&expand=1029) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_cmplt_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_lt(a.as_i32x16(), b.as_i32x16())) } @@ -17175,17 +29663,57 @@ pub unsafe fn _mm512_cmplt_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi32_mask&expand=1031) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_mask_cmplt_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmplt_epi32_mask(a, b) & k1 } +/// Compare packed signed 32-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmplt_epi32_mask&expand=1027) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_cmplt_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_lt(a.as_i32x8(), b.as_i32x8())) +} + +/// Compare packed signed 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epi32_mask&expand=1028) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_mask_cmplt_epi32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmplt_epi32_mask(a, b) & k1 +} + +/// Compare packed signed 32-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epi32_mask&expand=1025) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_cmplt_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_lt(a.as_i32x4(), b.as_i32x4())) +} + +/// Compare packed signed 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epi32_mask&expand=1026) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_mask_cmplt_epi32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmplt_epi32_mask(a, b) & k1 +} + /// Compare packed signed 32-bit integers in a and b for greater-than, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi32_mask&expand=905) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_cmpgt_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_gt(a.as_i32x16(), b.as_i32x16())) } @@ -17195,29 +29723,109 @@ pub unsafe fn _mm512_cmpgt_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi32_mask&expand=906) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_mask_cmpgt_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpgt_epi32_mask(a, b) & k1 } +/// Compare packed signed 32-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epi32_mask&expand=903) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_cmpgt_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_gt(a.as_i32x8(), b.as_i32x8())) +} + +/// Compare packed signed 32-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epi32_mask&expand=904) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_mask_cmpgt_epi32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpgt_epi32_mask(a, b) & k1 +} + +/// Compare packed signed 32-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epi32_mask&expand=901) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_cmpgt_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_gt(a.as_i32x4(), b.as_i32x4())) +} + +/// Compare packed signed 32-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epi32_mask&expand=902) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_mask_cmpgt_epi32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpgt_epi32_mask(a, b) & k1 +} + +/// Compare packed signed 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi32_mask&expand=971) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm512_cmple_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { + simd_bitmask::(simd_le(a.as_i32x16(), b.as_i32x16())) +} + +/// Compare packed signed 32-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi32_mask&expand=972) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm512_mask_cmple_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { + _mm512_cmple_epi32_mask(a, b) & k1 +} + +/// Compare packed signed 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epi32_mask&expand=969) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_cmple_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_le(a.as_i32x8(), b.as_i32x8())) +} + +/// Compare packed signed 32-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epi32_mask&expand=970) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_mask_cmple_epi32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmple_epi32_mask(a, b) & k1 +} + /// Compare packed signed 32-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi32_mask&expand=971) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epi32_mask&expand=967) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_cmple_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { - simd_bitmask::(simd_le(a.as_i32x16(), b.as_i32x16())) +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_cmple_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_le(a.as_i32x4(), b.as_i32x4())) } /// Compare packed signed 32-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi32_mask&expand=972) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epi32_mask&expand=968) #[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] -pub unsafe fn _mm512_mask_cmple_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { - _mm512_cmple_epi32_mask(a, b) & k1 +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_mask_cmple_epi32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmple_epi32_mask(a, b) & k1 } /// Compare packed signed 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. @@ -17225,7 +29833,7 @@ pub unsafe fn _mm512_mask_cmple_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi32_mask&expand=849) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_cmpge_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_ge(a.as_i32x16(), b.as_i32x16())) } @@ -17235,17 +29843,57 @@ pub unsafe fn _mm512_cmpge_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi32_mask&expand=850) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_mask_cmpge_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpge_epi32_mask(a, b) & k1 } +/// Compare packed signed 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epi32_mask&expand=847) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_cmpge_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_ge(a.as_i32x8(), b.as_i32x8())) +} + +/// Compare packed signed 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epi32_mask&expand=848) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_mask_cmpge_epi32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpge_epi32_mask(a, b) & k1 +} + +/// Compare packed signed 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epi32_mask&expand=845) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_cmpge_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ge(a.as_i32x4(), b.as_i32x4())) +} + +/// Compare packed signed 32-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epi32_mask&expand=846) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_mask_cmpge_epi32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpge_epi32_mask(a, b) & k1 +} + /// Compare packed 32-bit integers in a and b for equality, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi32_mask&expand=779) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_cmpeq_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_eq(a.as_i32x16(), b.as_i32x16())) } @@ -17255,17 +29903,57 @@ pub unsafe fn _mm512_cmpeq_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi32_mask&expand=780) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_mask_cmpeq_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpeq_epi32_mask(a, b) & k1 } +/// Compare packed 32-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epi32_mask&expand=777) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_cmpeq_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_eq(a.as_i32x8(), b.as_i32x8())) +} + +/// Compare packed 32-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epi32_mask&expand=778) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_mask_cmpeq_epi32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpeq_epi32_mask(a, b) & k1 +} + +/// Compare packed 32-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epi32_mask&expand=775) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_cmpeq_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_eq(a.as_i32x4(), b.as_i32x4())) +} + +/// Compare packed 32-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epi32_mask&expand=776) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_mask_cmpeq_epi32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpeq_epi32_mask(a, b) & k1 +} + /// Compare packed 32-bit integers in a and b for not-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi32_mask&expand=1088) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_cmpneq_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { simd_bitmask::(simd_ne(a.as_i32x16(), b.as_i32x16())) } @@ -17275,11 +29963,51 @@ pub unsafe fn _mm512_cmpneq_epi32_mask(a: __m512i, b: __m512i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi32_mask&expand=1089) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd pub unsafe fn _mm512_mask_cmpneq_epi32_mask(k1: __mmask16, a: __m512i, b: __m512i) -> __mmask16 { _mm512_cmpneq_epi32_mask(a, b) & k1 } +/// Compare packed 32-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epi32_mask&expand=1086) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_cmpneq_epi32_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::(simd_ne(a.as_i32x8(), b.as_i32x8())) +} + +/// Compare packed 32-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epi32_mask&expand=1087) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm256_mask_cmpneq_epi32_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpneq_epi32_mask(a, b) & k1 +} + +/// Compare packed 32-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epi32_mask&expand=1084) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_cmpneq_epi32_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::(simd_ne(a.as_i32x4(), b.as_i32x4())) +} + +/// Compare packed 32-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epi32_mask&expand=1085) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpd +pub unsafe fn _mm_mask_cmpneq_epi32_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpneq_epi32_mask(a, b) & k1 +} + /// Compare packed signed 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi32_mask&expand=697) @@ -17289,9 +30017,11 @@ pub unsafe fn _mm512_mask_cmpneq_epi32_mask(k1: __mmask16, a: __m512i, b: __m512 #[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] pub unsafe fn _mm512_cmp_epi32_mask(a: __m512i, b: __m512i, imm8: _MM_CMPINT_ENUM) -> __mmask16 { let neg_one = -1; + let a = a.as_i32x16(); + let b = b.as_i32x16(); macro_rules! call { ($imm3:expr) => { - vpcmpd(a.as_i32x16(), b.as_i32x16(), $imm3, neg_one) + vpcmpd(a, b, $imm3, neg_one) }; } let r = constify_imm3!(imm8, call); @@ -17311,9 +30041,99 @@ pub unsafe fn _mm512_mask_cmp_epi32_mask( b: __m512i, imm8: _MM_CMPINT_ENUM, ) -> __mmask16 { + let a = a.as_i32x16(); + let b = b.as_i32x16(); + macro_rules! call { + ($imm3:expr) => { + vpcmpd(a, b, $imm3, k1 as i16) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=#text=_mm256_cmp_epi32_mask&expand=695) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epi32_mask(a: __m256i, b: __m256i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i32x8(); + let b = b.as_i32x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpd256(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epi32_mask&expand=696) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epi32_mask( + k1: __mmask8, + a: __m256i, + b: __m256i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i32x8(); + let b = b.as_i32x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpd256(a, b, $imm3, k1 as i8) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epi32_mask&expand=693) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epi32_mask(a: __m128i, b: __m128i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i32x4(); + let b = b.as_i32x4(); + macro_rules! call { + ($imm3:expr) => { + vpcmpd128(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 32-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epi32_mask&expand=694) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epi32_mask( + k1: __mmask8, + a: __m128i, + b: __m128i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i32x4(); + let b = b.as_i32x4(); macro_rules! call { ($imm3:expr) => { - vpcmpd(a.as_i32x16(), b.as_i32x16(), $imm3, k1 as i16) + vpcmpd128(a, b, $imm3, k1 as i8) }; } let r = constify_imm3!(imm8, call); @@ -17325,7 +30145,7 @@ pub unsafe fn _mm512_mask_cmp_epi32_mask( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epu64_mask&expand=1062) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_cmplt_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_lt(a.as_u64x8(), b.as_u64x8())) } @@ -17335,17 +30155,57 @@ pub unsafe fn _mm512_cmplt_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epu64_mask&expand=1063) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_mask_cmplt_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmplt_epu64_mask(a, b) & k1 } +/// Compare packed unsigned 64-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmplt_epu64_mask&expand=1060) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_cmplt_epu64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_lt(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epu64_mask&expand=1061) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_mask_cmplt_epu64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmplt_epu64_mask(a, b) & k1 +} + +/// Compare packed unsigned 64-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epu64_mask&expand=1058) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_cmplt_epu64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_lt(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epu64_mask&expand=1059) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_mask_cmplt_epu64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmplt_epu64_mask(a, b) & k1 +} + /// Compare packed unsigned 64-bit integers in a and b for greater-than, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epu64_mask&expand=939) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_cmpgt_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_gt(a.as_u64x8(), b.as_u64x8())) } @@ -17355,17 +30215,57 @@ pub unsafe fn _mm512_cmpgt_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epu64_mask&expand=940) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_mask_cmpgt_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmpgt_epu64_mask(a, b) & k1 } +/// Compare packed unsigned 64-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epu64_mask&expand=937) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_cmpgt_epu64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_gt(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epu64_mask&expand=938) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_mask_cmpgt_epu64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpgt_epu64_mask(a, b) & k1 +} + +/// Compare packed unsigned 64-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epu64_mask&expand=935) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_cmpgt_epu64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_gt(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epu64_mask&expand=936) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_mask_cmpgt_epu64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpgt_epu64_mask(a, b) & k1 +} + /// Compare packed unsigned 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epu64_mask&expand=1001) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_cmple_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_le(a.as_u64x8(), b.as_u64x8())) } @@ -17375,17 +30275,57 @@ pub unsafe fn _mm512_cmple_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epu64_mask&expand=1002) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_mask_cmple_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmple_epu64_mask(a, b) & k1 } +/// Compare packed unsigned 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epu64_mask&expand=999) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_cmple_epu64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_le(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epu64_mask&expand=1000) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_mask_cmple_epu64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmple_epu64_mask(a, b) & k1 +} + +/// Compare packed unsigned 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epu64_mask&expand=997) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_cmple_epu64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_le(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epu64_mask&expand=998) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_mask_cmple_epu64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmple_epu64_mask(a, b) & k1 +} + /// Compare packed unsigned 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epu64_mask&expand=879) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_cmpge_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_ge(a.as_u64x8(), b.as_u64x8())) } @@ -17395,9 +30335,49 @@ pub unsafe fn _mm512_cmpge_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epu64_mask&expand=880) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_mask_cmpge_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { - _mm512_cmpge_epu64_mask(b, a) & k1 + _mm512_cmpge_epu64_mask(a, b) & k1 +} + +/// Compare packed unsigned 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epu64_mask&expand=877) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_cmpge_epu64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_ge(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epu64_mask&expand=878) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_mask_cmpge_epu64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpge_epu64_mask(a, b) & k1 +} + +/// Compare packed unsigned 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epu64_mask&expand=875) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_cmpge_epu64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_ge(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epu64_mask&expand=876) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_mask_cmpge_epu64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpge_epu64_mask(a, b) & k1 } /// Compare packed unsigned 64-bit integers in a and b for equality, and store the results in mask vector k. @@ -17405,7 +30385,7 @@ pub unsafe fn _mm512_mask_cmpge_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i) /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epu64_mask&expand=813) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_cmpeq_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_eq(a.as_u64x8(), b.as_u64x8())) } @@ -17415,17 +30395,57 @@ pub unsafe fn _mm512_cmpeq_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epu64_mask&expand=814) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_mask_cmpeq_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmpeq_epu64_mask(a, b) & k1 } +/// Compare packed unsigned 64-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epu64_mask&expand=811) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_cmpeq_epu64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_eq(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epu64_mask&expand=812) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_mask_cmpeq_epu64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpeq_epu64_mask(a, b) & k1 +} + +/// Compare packed unsigned 64-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epu64_mask&expand=809) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_cmpeq_epu64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_eq(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epu64_mask&expand=810) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_mask_cmpeq_epu64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpeq_epu64_mask(a, b) & k1 +} + /// Compare packed unsigned 64-bit integers in a and b for not-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epu64_mask&expand=1118) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_cmpneq_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_ne(a.as_u64x8(), b.as_u64x8())) } @@ -17435,11 +30455,51 @@ pub unsafe fn _mm512_cmpneq_epu64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epu64_mask&expand=1119) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq pub unsafe fn _mm512_mask_cmpneq_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmpneq_epu64_mask(a, b) & k1 } +/// Compare packed unsigned 64-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epu64_mask&expand=1116) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_cmpneq_epu64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_ne(a.as_u64x4(), b.as_u64x4())) +} + +/// Compare packed unsigned 64-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epu64_mask&expand=1117) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm256_mask_cmpneq_epu64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpneq_epu64_mask(a, b) & k1 +} + +/// Compare packed unsigned 64-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epu64_mask&expand=1114) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_cmpneq_epu64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_ne(a.as_u64x2(), b.as_u64x2())) +} + +/// Compare packed unsigned 64-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epu64_mask&expand=1115) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpuq +pub unsafe fn _mm_mask_cmpneq_epu64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpneq_epu64_mask(a, b) & k1 +} + /// Compare packed unsigned 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epu64_mask&expand=727) @@ -17449,9 +30509,11 @@ pub unsafe fn _mm512_mask_cmpneq_epu64_mask(k1: __mmask8, a: __m512i, b: __m512i #[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] pub unsafe fn _mm512_cmp_epu64_mask(a: __m512i, b: __m512i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { let neg_one = -1; + let a = a.as_i64x8(); + let b = b.as_i64x8(); macro_rules! call { ($imm3:expr) => { - vpcmpuq(a.as_i64x8(), b.as_i64x8(), $imm3, neg_one) + vpcmpuq(a, b, $imm3, neg_one) }; } let r = constify_imm3!(imm8, call); @@ -17471,9 +30533,99 @@ pub unsafe fn _mm512_mask_cmp_epu64_mask( b: __m512i, imm8: _MM_CMPINT_ENUM, ) -> __mmask8 { + let a = a.as_i64x8(); + let b = b.as_i64x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuq(a, b, $imm3, k1 as i8) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_epu64_mask&expand=725) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epu64_mask(a: __m256i, b: __m256i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i64x4(); + let b = b.as_i64x4(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuq256(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epu64_mask&expand=726) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epu64_mask( + k1: __mmask8, + a: __m256i, + b: __m256i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i64x4(); + let b = b.as_i64x4(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuq256(a, b, $imm3, k1 as i8) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epu64_mask&expand=723) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epu64_mask(a: __m128i, b: __m128i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i64x2(); + let b = b.as_i64x2(); + macro_rules! call { + ($imm3:expr) => { + vpcmpuq128(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed unsigned 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epu64_mask&expand=724) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epu64_mask( + k1: __mmask8, + a: __m128i, + b: __m128i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i64x2(); + let b = b.as_i64x2(); macro_rules! call { ($imm3:expr) => { - vpcmpuq(a.as_i64x8(), b.as_i64x8(), $imm3, k1 as i8) + vpcmpuq128(a, b, $imm3, k1 as i8) }; } let r = constify_imm3!(imm8, call); @@ -17485,7 +30637,7 @@ pub unsafe fn _mm512_mask_cmp_epu64_mask( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmplt_epi64_mask&expand=1037) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_cmplt_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_lt(a.as_i64x8(), b.as_i64x8())) } @@ -17495,17 +30647,57 @@ pub unsafe fn _mm512_cmplt_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmplt_epi64_mask&expand=1038) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_mask_cmplt_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmplt_epi64_mask(a, b) & k1 } +/// Compare packed signed 64-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmplt_epi64_mask&expand=1035) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_cmplt_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_lt(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmplt_epi64_mask&expand=1036) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_mask_cmplt_epi64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmplt_epi64_mask(a, b) & k1 +} + +/// Compare packed signed 64-bit integers in a and b for less-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epi64_mask&expand=1033) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_cmplt_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_lt(a.as_i64x2(), b.as_i64x2())) +} + +/// Compare packed signed 64-bit integers in a and b for less-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmplt_epi64_mask&expand=1034) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_mask_cmplt_epi64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmplt_epi64_mask(a, b) & k1 +} + /// Compare packed signed 64-bit integers in a and b for greater-than, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpgt_epi64_mask&expand=913) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_cmpgt_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_gt(a.as_i64x8(), b.as_i64x8())) } @@ -17515,17 +30707,57 @@ pub unsafe fn _mm512_cmpgt_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpgt_epi64_mask&expand=914) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_mask_cmpgt_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmpgt_epi64_mask(a, b) & k1 } +/// Compare packed signed 64-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpgt_epi64_mask&expand=911) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_cmpgt_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_gt(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpgt_epi64_mask&expand=912) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_mask_cmpgt_epi64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpgt_epi64_mask(a, b) & k1 +} + +/// Compare packed signed 64-bit integers in a and b for greater-than, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_epi64_mask&expand=909) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_cmpgt_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_gt(a.as_i64x2(), b.as_i64x2())) +} + +/// Compare packed signed 64-bit integers in a and b for greater-than, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpgt_epi64_mask&expand=910) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_mask_cmpgt_epi64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpgt_epi64_mask(a, b) & k1 +} + /// Compare packed signed 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmple_epi64_mask&expand=977) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_cmple_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_le(a.as_i64x8(), b.as_i64x8())) } @@ -17535,17 +30767,57 @@ pub unsafe fn _mm512_cmple_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmple_epi64_mask&expand=978) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_mask_cmple_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmple_epi64_mask(a, b) & k1 } +/// Compare packed signed 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmple_epi64_mask&expand=975) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_cmple_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_le(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmple_epi64_mask&expand=976) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_mask_cmple_epi64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmple_epi64_mask(a, b) & k1 +} + +/// Compare packed signed 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_epi64_mask&expand=973) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_cmple_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_le(a.as_i64x2(), b.as_i64x2())) +} + +/// Compare packed signed 64-bit integers in a and b for less-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmple_epi64_mask&expand=974) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_mask_cmple_epi64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmple_epi64_mask(a, b) & k1 +} + /// Compare packed signed 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpge_epi64_mask&expand=855) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_cmpge_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_ge(a.as_i64x8(), b.as_i64x8())) } @@ -17555,9 +30827,49 @@ pub unsafe fn _mm512_cmpge_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpge_epi64_mask&expand=856) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_mask_cmpge_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { - _mm512_cmpge_epi64_mask(b, a) & k1 + _mm512_cmpge_epi64_mask(a, b) & k1 +} + +/// Compare packed signed 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpge_epi64_mask&expand=853) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_cmpge_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_ge(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpge_epi64_mask&expand=854) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_mask_cmpge_epi64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpge_epi64_mask(a, b) & k1 +} + +/// Compare packed signed 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_epi64_mask&expand=851) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_cmpge_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_ge(a.as_i64x2(), b.as_i64x2())) +} + +/// Compare packed signed 64-bit integers in a and b for greater-than-or-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpge_epi64_mask&expand=852) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_mask_cmpge_epi64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpge_epi64_mask(a, b) & k1 } /// Compare packed 64-bit integers in a and b for equality, and store the results in mask vector k. @@ -17565,7 +30877,7 @@ pub unsafe fn _mm512_mask_cmpge_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i) /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpeq_epi64_mask&expand=787) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_cmpeq_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_eq(a.as_i64x8(), b.as_i64x8())) } @@ -17575,17 +30887,57 @@ pub unsafe fn _mm512_cmpeq_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpeq_epi64_mask&expand=788) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_mask_cmpeq_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmpeq_epi64_mask(a, b) & k1 } +/// Compare packed 64-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpeq_epi64_mask&expand=785) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_cmpeq_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_eq(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed 64-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpeq_epi64_mask&expand=786) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_mask_cmpeq_epi64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpeq_epi64_mask(a, b) & k1 +} + +/// Compare packed 64-bit integers in a and b for equality, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epi64_mask&expand=783) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_cmpeq_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_eq(a.as_i64x2(), b.as_i64x2())) +} + +/// Compare packed 64-bit integers in a and b for equality, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpeq_epi64_mask&expand=784) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_mask_cmpeq_epi64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpeq_epi64_mask(a, b) & k1 +} + /// Compare packed signed 64-bit integers in a and b for not-equal, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmpneq_epi64_mask&expand=1094) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_cmpneq_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { simd_bitmask::<__m512i, _>(simd_ne(a.as_i64x8(), b.as_i64x8())) } @@ -17595,11 +30947,51 @@ pub unsafe fn _mm512_cmpneq_epi64_mask(a: __m512i, b: __m512i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cmpneq_epi64_mask&expand=1095) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vpcmp))] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq pub unsafe fn _mm512_mask_cmpneq_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i) -> __mmask8 { _mm512_cmpneq_epi64_mask(a, b) & k1 } +/// Compare packed signed 64-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmpneq_epi64_mask&expand=1092) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_cmpneq_epi64_mask(a: __m256i, b: __m256i) -> __mmask8 { + simd_bitmask::<__m256i, _>(simd_ne(a.as_i64x4(), b.as_i64x4())) +} + +/// Compare packed signed 64-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmpneq_epi64_mask&expand=1093) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm256_mask_cmpneq_epi64_mask(k1: __mmask8, a: __m256i, b: __m256i) -> __mmask8 { + _mm256_cmpneq_epi64_mask(a, b) & k1 +} + +/// Compare packed signed 64-bit integers in a and b for not-equal, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_epi64_mask&expand=1090) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_cmpneq_epi64_mask(a: __m128i, b: __m128i) -> __mmask8 { + simd_bitmask::<__m128i, _>(simd_ne(a.as_i64x2(), b.as_i64x2())) +} + +/// Compare packed signed 64-bit integers in a and b for not-equal, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmpneq_epi64_mask&expand=1091) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpcmp))] //should be vpcmpq +pub unsafe fn _mm_mask_cmpneq_epi64_mask(k1: __mmask8, a: __m128i, b: __m128i) -> __mmask8 { + _mm_cmpneq_epi64_mask(a, b) & k1 +} + /// Compare packed signed 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_cmp_epi64_mask&expand=703) @@ -17609,9 +31001,11 @@ pub unsafe fn _mm512_mask_cmpneq_epi64_mask(k1: __mmask8, a: __m512i, b: __m512i #[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] pub unsafe fn _mm512_cmp_epi64_mask(a: __m512i, b: __m512i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { let neg_one = -1; + let a = a.as_i64x8(); + let b = b.as_i64x8(); macro_rules! call { ($imm3:expr) => { - vpcmpq(a.as_i64x8(), b.as_i64x8(), $imm3, neg_one) + vpcmpq(a, b, $imm3, neg_one) }; } let r = constify_imm3!(imm8, call); @@ -17631,9 +31025,99 @@ pub unsafe fn _mm512_mask_cmp_epi64_mask( b: __m512i, imm8: _MM_CMPINT_ENUM, ) -> __mmask8 { + let a = a.as_i64x8(); + let b = b.as_i64x8(); + macro_rules! call { + ($imm3:expr) => { + vpcmpq(a, b, $imm3, k1 as i8) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_cmp_epi64_mask&expand=701) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_cmp_epi64_mask(a: __m256i, b: __m256i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i64x4(); + let b = b.as_i64x4(); + macro_rules! call { + ($imm3:expr) => { + vpcmpq256(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cmp_epi64_mask&expand=702) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm256_mask_cmp_epi64_mask( + k1: __mmask8, + a: __m256i, + b: __m256i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i64x4(); + let b = b.as_i64x4(); macro_rules! call { ($imm3:expr) => { - vpcmpq(a.as_i64x8(), b.as_i64x8(), $imm3, k1 as i8) + vpcmpq256(a, b, $imm3, k1 as i8) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmp_epi64_mask&expand=699) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(2)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_cmp_epi64_mask(a: __m128i, b: __m128i, imm8: _MM_CMPINT_ENUM) -> __mmask8 { + let neg_one = -1; + let a = a.as_i64x2(); + let b = b.as_i64x2(); + macro_rules! call { + ($imm3:expr) => { + vpcmpq128(a, b, $imm3, neg_one) + }; + } + let r = constify_imm3!(imm8, call); + transmute(r) +} + +/// Compare packed signed 64-bit integers in a and b based on the comparison operand specified by imm8, and store the results in mask vector k using zeromask k1 (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cmp_epi64_mask&expand=700) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[rustc_args_required_const(3)] +#[cfg_attr(test, assert_instr(vpcmp, imm8 = 0))] +pub unsafe fn _mm_mask_cmp_epi64_mask( + k1: __mmask8, + a: __m128i, + b: __m128i, + imm8: _MM_CMPINT_ENUM, +) -> __mmask8 { + let a = a.as_i64x2(); + let b = b.as_i64x2(); + macro_rules! call { + ($imm3:expr) => { + vpcmpq128(a, b, $imm3, k1 as i8) }; } let r = constify_imm3!(imm8, call); @@ -17642,7 +31126,7 @@ pub unsafe fn _mm512_mask_cmp_epi64_mask( /// Reduce the packed 32-bit integers in a by addition. Returns the sum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_add_epi32&expand=4556) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_epi32&expand=4556) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_add_epi32(a: __m512i) -> i32 { @@ -17651,7 +31135,7 @@ pub unsafe fn _mm512_reduce_add_epi32(a: __m512i) -> i32 { /// Reduce the packed 32-bit integers in a by addition using mask k. Returns the sum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_add_epi32&expand=4555) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_epi32&expand=4555) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_add_epi32(k: __mmask16, a: __m512i) -> i32 { @@ -17664,7 +31148,7 @@ pub unsafe fn _mm512_mask_reduce_add_epi32(k: __mmask16, a: __m512i) -> i32 { /// Reduce the packed 64-bit integers in a by addition. Returns the sum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_add_epi64&expand=4558) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_epi64&expand=4558) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_add_epi64(a: __m512i) -> i64 { @@ -17673,7 +31157,7 @@ pub unsafe fn _mm512_reduce_add_epi64(a: __m512i) -> i64 { /// Reduce the packed 64-bit integers in a by addition using mask k. Returns the sum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_add_epi64&expand=4557) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_epi64&expand=4557) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_add_epi64(k: __mmask8, a: __m512i) -> i64 { @@ -17686,7 +31170,7 @@ pub unsafe fn _mm512_mask_reduce_add_epi64(k: __mmask8, a: __m512i) -> i64 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by addition. Returns the sum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_add_ps&expand=4562) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_ps&expand=4562) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_add_ps(a: __m512) -> f32 { @@ -17695,7 +31179,7 @@ pub unsafe fn _mm512_reduce_add_ps(a: __m512) -> f32 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by addition using mask k. Returns the sum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_add_ps&expand=4561) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_ps&expand=4561) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_add_ps(k: __mmask16, a: __m512) -> f32 { @@ -17708,7 +31192,7 @@ pub unsafe fn _mm512_mask_reduce_add_ps(k: __mmask16, a: __m512) -> f32 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by addition. Returns the sum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_add_pd&expand=4560) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_add_pd&expand=4560) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_add_pd(a: __m512d) -> f64 { @@ -17717,7 +31201,7 @@ pub unsafe fn _mm512_reduce_add_pd(a: __m512d) -> f64 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by addition using mask k. Returns the sum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_add_pd&expand=4559) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_pd&expand=4559) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_add_pd(k: __mmask8, a: __m512d) -> f64 { @@ -17730,7 +31214,7 @@ pub unsafe fn _mm512_mask_reduce_add_pd(k: __mmask8, a: __m512d) -> f64 { /// Reduce the packed 32-bit integers in a by multiplication. Returns the product of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_mul_epi32&expand=4600) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_epi32&expand=4600) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_mul_epi32(a: __m512i) -> i32 { @@ -17739,7 +31223,7 @@ pub unsafe fn _mm512_reduce_mul_epi32(a: __m512i) -> i32 { /// Reduce the packed 32-bit integers in a by multiplication using mask k. Returns the product of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_mul_epi32&expand=4599) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_epi32&expand=4599) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_mul_epi32(k: __mmask16, a: __m512i) -> i32 { @@ -17752,7 +31236,7 @@ pub unsafe fn _mm512_mask_reduce_mul_epi32(k: __mmask16, a: __m512i) -> i32 { /// Reduce the packed 64-bit integers in a by multiplication. Returns the product of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_mul_epi64&expand=4602) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_epi64&expand=4602) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_mul_epi64(a: __m512i) -> i64 { @@ -17761,7 +31245,7 @@ pub unsafe fn _mm512_reduce_mul_epi64(a: __m512i) -> i64 { /// Reduce the packed 64-bit integers in a by multiplication using mask k. Returns the product of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_mul_epi64&expand=4601) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_epi64&expand=4601) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_mul_epi64(k: __mmask8, a: __m512i) -> i64 { @@ -17774,7 +31258,7 @@ pub unsafe fn _mm512_mask_reduce_mul_epi64(k: __mmask8, a: __m512i) -> i64 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by multiplication. Returns the product of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_mul_ps&expand=4606) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_ps&expand=4606) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_mul_ps(a: __m512) -> f32 { @@ -17783,7 +31267,7 @@ pub unsafe fn _mm512_reduce_mul_ps(a: __m512) -> f32 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by multiplication using mask k. Returns the product of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_mul_ps&expand=4605) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_ps&expand=4605) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_mul_ps(k: __mmask16, a: __m512) -> f32 { @@ -17796,7 +31280,7 @@ pub unsafe fn _mm512_mask_reduce_mul_ps(k: __mmask16, a: __m512) -> f32 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by multiplication. Returns the product of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_mul_pd&expand=4604) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_mul_pd&expand=4604) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_mul_pd(a: __m512d) -> f64 { @@ -17805,7 +31289,7 @@ pub unsafe fn _mm512_reduce_mul_pd(a: __m512d) -> f64 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by multiplication using mask k. Returns the product of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_mul_pd&expand=4603) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_mul_pd&expand=4603) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_mul_pd(k: __mmask8, a: __m512d) -> f64 { @@ -17818,7 +31302,7 @@ pub unsafe fn _mm512_mask_reduce_mul_pd(k: __mmask8, a: __m512d) -> f64 { /// Reduce the packed signed 32-bit integers in a by maximum. Returns the maximum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_max_epi32&expand=4576) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epi32&expand=4576) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_max_epi32(a: __m512i) -> i32 { @@ -17827,7 +31311,7 @@ pub unsafe fn _mm512_reduce_max_epi32(a: __m512i) -> i32 { /// Reduce the packed signed 32-bit integers in a by maximum using mask k. Returns the maximum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_max_epi32&expand=4575) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epi32&expand=4575) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_max_epi32(k: __mmask16, a: __m512i) -> i32 { @@ -17840,7 +31324,7 @@ pub unsafe fn _mm512_mask_reduce_max_epi32(k: __mmask16, a: __m512i) -> i32 { /// Reduce the packed signed 64-bit integers in a by maximum. Returns the maximum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_max_epi64&expand=4578) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epi64&expand=4578) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_max_epi64(a: __m512i) -> i64 { @@ -17849,7 +31333,7 @@ pub unsafe fn _mm512_reduce_max_epi64(a: __m512i) -> i64 { /// Reduce the packed signed 64-bit integers in a by maximum using mask k. Returns the maximum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_max_epi64&expand=4577) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epi64&expand=4577) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_max_epi64(k: __mmask8, a: __m512i) -> i64 { @@ -17862,7 +31346,7 @@ pub unsafe fn _mm512_mask_reduce_max_epi64(k: __mmask8, a: __m512i) -> i64 { /// Reduce the packed unsigned 32-bit integers in a by maximum. Returns the maximum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_max_epu32&expand=4580) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epu32&expand=4580) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_max_epu32(a: __m512i) -> u32 { @@ -17871,7 +31355,7 @@ pub unsafe fn _mm512_reduce_max_epu32(a: __m512i) -> u32 { /// Reduce the packed unsigned 32-bit integers in a by maximum using mask k. Returns the maximum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_max_epu32&expand=4579) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epu32&expand=4579) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_max_epu32(k: __mmask16, a: __m512i) -> u32 { @@ -17884,7 +31368,7 @@ pub unsafe fn _mm512_mask_reduce_max_epu32(k: __mmask16, a: __m512i) -> u32 { /// Reduce the packed unsigned 64-bit integers in a by maximum. Returns the maximum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_max_epu64&expand=4582) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_epu64&expand=4582) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_max_epu64(a: __m512i) -> u64 { @@ -17893,7 +31377,7 @@ pub unsafe fn _mm512_reduce_max_epu64(a: __m512i) -> u64 { /// Reduce the packed unsigned 64-bit integers in a by maximum using mask k. Returns the maximum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_max_epu64&expand=4581) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_epu64&expand=4581) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_max_epu64(k: __mmask8, a: __m512i) -> u64 { @@ -17906,7 +31390,7 @@ pub unsafe fn _mm512_mask_reduce_max_epu64(k: __mmask8, a: __m512i) -> u64 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by maximum. Returns the maximum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_max_ps&expand=4586) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_ps&expand=4586) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_max_ps(a: __m512) -> f32 { @@ -17915,7 +31399,7 @@ pub unsafe fn _mm512_reduce_max_ps(a: __m512) -> f32 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by maximum using mask k. Returns the maximum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_max_ps&expand=4585) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_ps&expand=4585) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_max_ps(k: __mmask16, a: __m512) -> f32 { @@ -17928,7 +31412,7 @@ pub unsafe fn _mm512_mask_reduce_max_ps(k: __mmask16, a: __m512) -> f32 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by maximum. Returns the maximum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_max_pd&expand=4584) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_max_pd&expand=4584) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_max_pd(a: __m512d) -> f64 { @@ -17937,7 +31421,7 @@ pub unsafe fn _mm512_reduce_max_pd(a: __m512d) -> f64 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by maximum using mask k. Returns the maximum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_max_pd&expand=4583) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_max_pd&expand=4583) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_max_pd(k: __mmask8, a: __m512d) -> f64 { @@ -17950,7 +31434,7 @@ pub unsafe fn _mm512_mask_reduce_max_pd(k: __mmask8, a: __m512d) -> f64 { /// Reduce the packed signed 32-bit integers in a by minimum. Returns the minimum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_min_epi32&expand=4588) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epi32&expand=4588) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_min_epi32(a: __m512i) -> i32 { @@ -17959,7 +31443,7 @@ pub unsafe fn _mm512_reduce_min_epi32(a: __m512i) -> i32 { /// Reduce the packed signed 32-bit integers in a by maximum using mask k. Returns the minimum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_min_epi32&expand=4587) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epi32&expand=4587) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_min_epi32(k: __mmask16, a: __m512i) -> i32 { @@ -17972,7 +31456,7 @@ pub unsafe fn _mm512_mask_reduce_min_epi32(k: __mmask16, a: __m512i) -> i32 { /// Reduce the packed signed 64-bit integers in a by minimum. Returns the minimum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_min_epi64&expand=4590) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epi64&expand=4590) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_min_epi64(a: __m512i) -> i64 { @@ -17981,7 +31465,7 @@ pub unsafe fn _mm512_reduce_min_epi64(a: __m512i) -> i64 { /// Reduce the packed signed 64-bit integers in a by maximum using mask k. Returns the minimum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_min_epi64&expand=4589) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epi64&expand=4589) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_min_epi64(k: __mmask8, a: __m512i) -> i64 { @@ -17994,7 +31478,7 @@ pub unsafe fn _mm512_mask_reduce_min_epi64(k: __mmask8, a: __m512i) -> i64 { /// Reduce the packed unsigned 32-bit integers in a by minimum. Returns the minimum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_min_epu32&expand=4592) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epu32&expand=4592) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_min_epu32(a: __m512i) -> u32 { @@ -18003,7 +31487,7 @@ pub unsafe fn _mm512_reduce_min_epu32(a: __m512i) -> u32 { /// Reduce the packed unsigned 32-bit integers in a by maximum using mask k. Returns the minimum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_min_epu32&expand=4591) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epu32&expand=4591) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_min_epu32(k: __mmask16, a: __m512i) -> u32 { @@ -18016,7 +31500,7 @@ pub unsafe fn _mm512_mask_reduce_min_epu32(k: __mmask16, a: __m512i) -> u32 { /// Reduce the packed unsigned 64-bit integers in a by minimum. Returns the minimum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_min_epu64&expand=4594) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_epu64&expand=4594) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_min_epu64(a: __m512i) -> u64 { @@ -18025,7 +31509,7 @@ pub unsafe fn _mm512_reduce_min_epu64(a: __m512i) -> u64 { /// Reduce the packed signed 64-bit integers in a by maximum using mask k. Returns the minimum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_min_epi64&expand=4589) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_epi64&expand=4589) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_min_epu64(k: __mmask8, a: __m512i) -> u64 { @@ -18038,7 +31522,7 @@ pub unsafe fn _mm512_mask_reduce_min_epu64(k: __mmask8, a: __m512i) -> u64 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by minimum. Returns the minimum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_min_ps&expand=4598) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_ps&expand=4598) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_min_ps(a: __m512) -> f32 { @@ -18047,7 +31531,7 @@ pub unsafe fn _mm512_reduce_min_ps(a: __m512) -> f32 { /// Reduce the packed single-precision (32-bit) floating-point elements in a by maximum using mask k. Returns the minimum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_min_ps&expand=4597) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_ps&expand=4597) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_min_ps(k: __mmask16, a: __m512) -> f32 { @@ -18060,7 +31544,7 @@ pub unsafe fn _mm512_mask_reduce_min_ps(k: __mmask16, a: __m512) -> f32 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by minimum. Returns the minimum of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_min_pd&expand=4596) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_min_pd&expand=4596) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_min_pd(a: __m512d) -> f64 { @@ -18069,7 +31553,7 @@ pub unsafe fn _mm512_reduce_min_pd(a: __m512d) -> f64 { /// Reduce the packed double-precision (64-bit) floating-point elements in a by maximum using mask k. Returns the minimum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_min_pd&expand=4595) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_min_pd&expand=4595) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_min_pd(k: __mmask8, a: __m512d) -> f64 { @@ -18082,7 +31566,7 @@ pub unsafe fn _mm512_mask_reduce_min_pd(k: __mmask8, a: __m512d) -> f64 { /// Reduce the packed 32-bit integers in a by bitwise AND. Returns the bitwise AND of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_and_epi32&expand=4564) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_and_epi32&expand=4564) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_and_epi32(a: __m512i) -> i32 { @@ -18091,38 +31575,20 @@ pub unsafe fn _mm512_reduce_and_epi32(a: __m512i) -> i32 { /// Reduce the packed 32-bit integers in a by bitwise AND using mask k. Returns the bitwise AND of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_and_epi32&expand=4563) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_and_epi32&expand=4563) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_and_epi32(k: __mmask16, a: __m512i) -> i32 { simd_reduce_and(simd_select_bitmask( k, a.as_i32x16(), - _mm512_set1_epi32( - 1 << 0 - | 1 << 1 - | 1 << 2 - | 1 << 3 - | 1 << 4 - | 1 << 5 - | 1 << 6 - | 1 << 7 - | 1 << 8 - | 1 << 9 - | 1 << 10 - | 1 << 11 - | 1 << 12 - | 1 << 13 - | 1 << 14 - | 1 << 15, - ) - .as_i32x16(), + _mm512_set1_epi32(0xFF).as_i32x16(), )) } /// Reduce the packed 64-bit integers in a by bitwise AND. Returns the bitwise AND of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_and_epi64&expand=4566) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_and_epi64&expand=4566) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_and_epi64(a: __m512i) -> i64 { @@ -18131,7 +31597,7 @@ pub unsafe fn _mm512_reduce_and_epi64(a: __m512i) -> i64 { /// Reduce the packed 64-bit integers in a by addition using mask k. Returns the sum of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_add_epi64&expand=4557) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_add_epi64&expand=4557) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_and_epi64(k: __mmask8, a: __m512i) -> i64 { @@ -18145,7 +31611,7 @@ pub unsafe fn _mm512_mask_reduce_and_epi64(k: __mmask8, a: __m512i) -> i64 { /// Reduce the packed 32-bit integers in a by bitwise OR. Returns the bitwise OR of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_or_epi32&expand=4608) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_or_epi32&expand=4608) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_or_epi32(a: __m512i) -> i32 { @@ -18154,7 +31620,7 @@ pub unsafe fn _mm512_reduce_or_epi32(a: __m512i) -> i32 { /// Reduce the packed 32-bit integers in a by bitwise OR using mask k. Returns the bitwise OR of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_or_epi32&expand=4607) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_or_epi32&expand=4607) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_or_epi32(k: __mmask16, a: __m512i) -> i32 { @@ -18167,7 +31633,7 @@ pub unsafe fn _mm512_mask_reduce_or_epi32(k: __mmask16, a: __m512i) -> i32 { /// Reduce the packed 64-bit integers in a by bitwise OR. Returns the bitwise OR of all elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_reduce_or_epi64&expand=4610) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_reduce_or_epi64&expand=4610) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_reduce_or_epi64(a: __m512i) -> i64 { @@ -18176,7 +31642,7 @@ pub unsafe fn _mm512_reduce_or_epi64(a: __m512i) -> i64 { /// Reduce the packed 64-bit integers in a by bitwise OR using mask k. Returns the bitwise OR of all active elements in a. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_mask_reduce_or_epi64&expand=4609) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_reduce_or_epi64&expand=4609) #[inline] #[target_feature(enable = "avx512f")] pub unsafe fn _mm512_mask_reduce_or_epi64(k: __mmask8, a: __m512i) -> i64 { @@ -18209,7 +31675,7 @@ pub unsafe fn _mm512_undefined_ps() -> __m512 { /// Return vector of type __m512i with undefined elements. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_undefined_epi32&expand=5995) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined_epi32&expand=5995) #[inline] #[target_feature(enable = "avx512f")] // This intrinsic has no corresponding instruction. @@ -18219,7 +31685,7 @@ pub unsafe fn _mm512_undefined_epi32() -> __m512i { /// Return vector of type __m512 with undefined elements. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_undefined&expand=5994) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined&expand=5994) #[inline] #[target_feature(enable = "avx512f")] // This intrinsic has no corresponding instruction. @@ -18229,7 +31695,7 @@ pub unsafe fn _mm512_undefined() -> __m512 { /// Load 512-bits (composed of 16 packed 32-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_loadu_epi32&expand=3377) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_epi32&expand=3377) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 @@ -18237,9 +31703,479 @@ pub unsafe fn _mm512_loadu_epi32(mem_addr: *const i32) -> __m512i { ptr::read_unaligned(mem_addr as *const __m512i) } +/// Load 256-bits (composed of 8 packed 32-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_loadu_epi32&expand=3374) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 +pub unsafe fn _mm256_loadu_epi32(mem_addr: *const i32) -> __m256i { + ptr::read_unaligned(mem_addr as *const __m256i) +} + +/// Load 128-bits (composed of 4 packed 32-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_epi32&expand=3371) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 +pub unsafe fn _mm_loadu_epi32(mem_addr: *const i32) -> __m128i { + ptr::read_unaligned(mem_addr as *const __m128i) +} + +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_storeu_epi16&expand=1460) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm512_mask_cvtepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask16, a: __m512i) { + vpmovdwmem(mem_addr as *mut i8, a.as_i32x16(), k); +} + +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi32_storeu_epi8&expand=1462) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm256_mask_cvtepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovdwmem256(mem_addr as *mut i8, a.as_i32x8(), k); +} + +/// Convert packed 32-bit integers in a to packed 16-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi32_storeu_epi8&expand=1461) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdw))] +pub unsafe fn _mm_mask_cvtepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovdwmem128(mem_addr as *mut i8, a.as_i32x4(), k); +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_storeu_epi16&expand=1833) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm512_mask_cvtsepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask16, a: __m512i) { + vpmovsdwmem(mem_addr as *mut i8, a.as_i32x16(), k); +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi32_storeu_epi16&expand=1832) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm256_mask_cvtsepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovsdwmem256(mem_addr as *mut i8, a.as_i32x8(), k); +} + +/// Convert packed signed 32-bit integers in a to packed 16-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi32_storeu_epi16&expand=1831) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdw))] +pub unsafe fn _mm_mask_cvtsepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovsdwmem128(mem_addr as *mut i8, a.as_i32x4(), k); +} + +/// Convert packed unsigned 32-bit integers in a to packed 16-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_storeu_epi16&expand=2068) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm512_mask_cvtusepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask16, a: __m512i) { + vpmovusdwmem(mem_addr as *mut i8, a.as_i32x16(), k); +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi32_storeu_epi16&expand=2067) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm256_mask_cvtusepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovusdwmem256(mem_addr as *mut i8, a.as_i32x8(), k); +} + +/// Convert packed unsigned 32-bit integers in a to packed unsigned 16-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi32_storeu_epi16&expand=2066) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdw))] +pub unsafe fn _mm_mask_cvtusepi32_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovusdwmem128(mem_addr as *mut i8, a.as_i32x4(), k); +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi32_storeu_epi8&expand=1463) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm512_mask_cvtepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m512i) { + vpmovdbmem(mem_addr as *mut i8, a.as_i32x16(), k); +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi32_storeu_epi8&expand=1462) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm256_mask_cvtepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovdbmem256(mem_addr as *mut i8, a.as_i32x8(), k); +} + +/// Convert packed 32-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi32_storeu_epi8&expand=1461) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovdb))] +pub unsafe fn _mm_mask_cvtepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovdbmem128(mem_addr as *mut i8, a.as_i32x4(), k); +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi32_storeu_epi8&expand=1836) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm512_mask_cvtsepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m512i) { + vpmovsdbmem(mem_addr as *mut i8, a.as_i32x16(), k); +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi32_storeu_epi8&expand=1835) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm256_mask_cvtsepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovsdbmem256(mem_addr as *mut i8, a.as_i32x8(), k); +} + +/// Convert packed signed 32-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi32_storeu_epi8&expand=1834) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsdb))] +pub unsafe fn _mm_mask_cvtsepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovsdbmem128(mem_addr as *mut i8, a.as_i32x4(), k); +} + +/// Convert packed unsigned 32-bit integers in a to packed 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi32_storeu_epi8&expand=2071) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm512_mask_cvtusepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m512i) { + vpmovusdbmem(mem_addr as *mut i8, a.as_i32x16(), k); +} + +/// Convert packed unsigned 32-bit integers in a to packed 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi32_storeu_epi8&expand=2070) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm256_mask_cvtusepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovusdbmem256(mem_addr as *mut i8, a.as_i32x8(), k); +} + +/// Convert packed unsigned 32-bit integers in a to packed 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi32_storeu_epi8&expand=2069) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusdb))] +pub unsafe fn _mm_mask_cvtusepi32_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovusdbmem128(mem_addr as *mut i8, a.as_i32x4(), k); +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_storeu_epi16&expand=1513) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm512_mask_cvtepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovqwmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi64_storeu_epi16&expand=1512) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm256_mask_cvtepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovqwmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed 64-bit integers in a to packed 16-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi64_storeu_epi16&expand=1511) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqw))] +pub unsafe fn _mm_mask_cvtepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovqwmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_storeu_epi16&expand=1866) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm512_mask_cvtsepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovsqwmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi64_storeu_epi16&expand=1865) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm256_mask_cvtsepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovsqwmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 16-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi64_storeu_epi16&expand=1864) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqw))] +pub unsafe fn _mm_mask_cvtsepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovsqwmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 16-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_storeu_epi16&expand=2101) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm512_mask_cvtusepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovusqwmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 16-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi64_storeu_epi16&expand=2100) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm256_mask_cvtusepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovusqwmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 16-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi64_storeu_epi16&expand=2099) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqw))] +pub unsafe fn _mm_mask_cvtusepi64_storeu_epi16(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovusqwmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_storeu_epi8&expand=1519) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm512_mask_cvtepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovqbmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi64_storeu_epi8&expand=1518) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm256_mask_cvtepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovqbmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed 64-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi64_storeu_epi8&expand=1517) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqb))] +pub unsafe fn _mm_mask_cvtepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovqbmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_storeu_epi8&expand=1872) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm512_mask_cvtsepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovsqbmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi64_storeu_epi8&expand=1871) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm256_mask_cvtsepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovsqbmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi64_storeu_epi8&expand=1870) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqb))] +pub unsafe fn _mm_mask_cvtsepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovsqbmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_storeu_epi8&expand=2107) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm512_mask_cvtusepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovusqbmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi64_storeu_epi8&expand=2106) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm256_mask_cvtusepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovusqbmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi64_storeu_epi8&expand=2105) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqb))] +pub unsafe fn _mm_mask_cvtusepi64_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovusqbmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +///Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtepi64_storeu_epi32&expand=1516) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm512_mask_cvtepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovqdmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +///Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtepi64_storeu_epi32&expand=1515) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm256_mask_cvtepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovqdmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +///Convert packed 64-bit integers in a to packed 32-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtepi64_storeu_epi32&expand=1514) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovqd))] +pub unsafe fn _mm_mask_cvtepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovqdmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtsepi64_storeu_epi32&expand=1869) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm512_mask_cvtsepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovsqdmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtsepi64_storeu_epi32&expand=1868) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm256_mask_cvtsepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovsqdmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed signed 64-bit integers in a to packed 32-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtsepi64_storeu_epi32&expand=1867) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovsqd))] +pub unsafe fn _mm_mask_cvtsepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovsqdmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 32-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_cvtusepi64_storeu_epi32&expand=2104) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm512_mask_cvtusepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m512i) { + vpmovusqdmem(mem_addr as *mut i8, a.as_i64x8(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 32-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_cvtusepi64_storeu_epi32&expand=2103) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm256_mask_cvtusepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m256i) { + vpmovusqdmem256(mem_addr as *mut i8, a.as_i64x4(), k); +} + +/// Convert packed unsigned 64-bit integers in a to packed 32-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_cvtusepi64_storeu_epi32&expand=2102) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vpmovusqd))] +pub unsafe fn _mm_mask_cvtusepi64_storeu_epi32(mem_addr: *mut i8, k: __mmask8, a: __m128i) { + vpmovusqdmem128(mem_addr as *mut i8, a.as_i64x2(), k); +} + /// Store 512-bits (composed of 16 packed 32-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_storeu_epi32&expand=5628) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_epi32&expand=5628) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 @@ -18247,9 +32183,29 @@ pub unsafe fn _mm512_storeu_epi32(mem_addr: *mut i32, a: __m512i) { ptr::write_unaligned(mem_addr as *mut __m512i, a); } +/// Store 256-bits (composed of 8 packed 32-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_storeu_epi32&expand=5626) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 +pub unsafe fn _mm256_storeu_epi32(mem_addr: *mut i32, a: __m256i) { + ptr::write_unaligned(mem_addr as *mut __m256i, a); +} + +/// Store 128-bits (composed of 4 packed 32-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_epi32&expand=5624) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 +pub unsafe fn _mm_storeu_epi32(mem_addr: *mut i32, a: __m128i) { + ptr::write_unaligned(mem_addr as *mut __m128i, a); +} + /// Load 512-bits (composed of 8 packed 64-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_loadu_epi64&expand=3386) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_epi64&expand=3386) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu64 @@ -18257,9 +32213,29 @@ pub unsafe fn _mm512_loadu_epi64(mem_addr: *const i64) -> __m512i { ptr::read_unaligned(mem_addr as *const __m512i) } +/// Load 256-bits (composed of 4 packed 64-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_loadu_epi64&expand=3383) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu64 +pub unsafe fn _mm256_loadu_epi64(mem_addr: *const i64) -> __m256i { + ptr::read_unaligned(mem_addr as *const __m256i) +} + +/// Load 128-bits (composed of 2 packed 64-bit integers) from memory into dst. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_epi64&expand=3380) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu64 +pub unsafe fn _mm_loadu_epi64(mem_addr: *const i64) -> __m128i { + ptr::read_unaligned(mem_addr as *const __m128i) +} + /// Store 512-bits (composed of 8 packed 64-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_storeu_epi64&expand=5634) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_epi64&expand=5634) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu64 @@ -18267,9 +32243,29 @@ pub unsafe fn _mm512_storeu_epi64(mem_addr: *mut i64, a: __m512i) { ptr::write_unaligned(mem_addr as *mut __m512i, a); } +/// Store 256-bits (composed of 4 packed 64-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_storeu_epi64&expand=5632) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu64 +pub unsafe fn _mm256_storeu_epi64(mem_addr: *mut i64, a: __m256i) { + ptr::write_unaligned(mem_addr as *mut __m256i, a); +} + +/// Store 128-bits (composed of 2 packed 64-bit integers) from a into memory. mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_epi64&expand=5630) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu64 +pub unsafe fn _mm_storeu_epi64(mem_addr: *mut i64, a: __m128i) { + ptr::write_unaligned(mem_addr as *mut __m128i, a); +} + /// Load 512-bits of integer data from memory into dst. mem_addr does not need to be aligned on any particular boundary. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_loadu_si512&expand=3420) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_loadu_si512&expand=3420) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 @@ -18279,7 +32275,7 @@ pub unsafe fn _mm512_loadu_si512(mem_addr: *const i32) -> __m512i { /// Store 512-bits of integer data from a into memory. mem_addr does not need to be aligned on any particular boundary. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_storeu_si512&expand=5657) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_storeu_si512&expand=5657) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovups))] //should be vmovdqu32 @@ -18358,7 +32354,7 @@ pub unsafe fn _mm512_store_si512(mem_addr: *mut i32, a: __m512i) { /// Load 512-bits (composed of 16 packed 32-bit integers) from memory into dst. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_load_epi32&expand=3304) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_epi32&expand=3304) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa32 @@ -18366,6 +32362,26 @@ pub unsafe fn _mm512_load_epi32(mem_addr: *const i32) -> __m512i { ptr::read(mem_addr as *const __m512i) } +/// Load 256-bits (composed of 8 packed 32-bit integers) from memory into dst. mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_load_epi32&expand=3301) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa32 +pub unsafe fn _mm256_load_epi32(mem_addr: *const i32) -> __m256i { + ptr::read(mem_addr as *const __m256i) +} + +/// Load 128-bits (composed of 4 packed 32-bit integers) from memory into dst. mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_epi32&expand=3298) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa32 +pub unsafe fn _mm_load_epi32(mem_addr: *const i32) -> __m128i { + ptr::read(mem_addr as *const __m128i) +} + /// Store 512-bits (composed of 16 packed 32-bit integers) from a into memory. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_store_epi32&expand=5569) @@ -18376,9 +32392,29 @@ pub unsafe fn _mm512_store_epi32(mem_addr: *mut i32, a: __m512i) { ptr::write(mem_addr as *mut __m512i, a); } +/// Store 256-bits (composed of 8 packed 32-bit integers) from a into memory. mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_store_epi32&expand=5567) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa32 +pub unsafe fn _mm256_store_epi32(mem_addr: *mut i32, a: __m256i) { + ptr::write(mem_addr as *mut __m256i, a); +} + +/// Store 128-bits (composed of 4 packed 32-bit integers) from a into memory. mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_epi32&expand=5565) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa32 +pub unsafe fn _mm_store_epi32(mem_addr: *mut i32, a: __m128i) { + ptr::write(mem_addr as *mut __m128i, a); +} + /// Load 512-bits (composed of 8 packed 64-bit integers) from memory into dst. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_load_epi64&expand=3313) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_epi64&expand=3313) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa64 @@ -18386,9 +32422,29 @@ pub unsafe fn _mm512_load_epi64(mem_addr: *const i64) -> __m512i { ptr::read(mem_addr as *const __m512i) } +/// Load 256-bits (composed of 4 packed 64-bit integers) from memory into dst. mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_load_epi64&expand=3310) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa64 +pub unsafe fn _mm256_load_epi64(mem_addr: *const i64) -> __m256i { + ptr::read(mem_addr as *const __m256i) +} + +/// Load 128-bits (composed of 2 packed 64-bit integers) from memory into dst. mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_epi64&expand=3307) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa64 +pub unsafe fn _mm_load_epi64(mem_addr: *const i64) -> __m128i { + ptr::read(mem_addr as *const __m128i) +} + /// Store 512-bits (composed of 8 packed 64-bit integers) from a into memory. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_store_epi64&expand=5575) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_epi64&expand=5575) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa64 @@ -18396,9 +32452,29 @@ pub unsafe fn _mm512_store_epi64(mem_addr: *mut i64, a: __m512i) { ptr::write(mem_addr as *mut __m512i, a); } +/// Store 256-bits (composed of 4 packed 64-bit integers) from a into memory. mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_store_epi64&expand=5573) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa64 +pub unsafe fn _mm256_store_epi64(mem_addr: *mut i64, a: __m256i) { + ptr::write(mem_addr as *mut __m256i, a); +} + +/// Store 128-bits (composed of 2 packed 64-bit integers) from a into memory. mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_epi64&expand=5571) +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[cfg_attr(test, assert_instr(vmovaps))] //should be vmovdqa64 +pub unsafe fn _mm_store_epi64(mem_addr: *mut i64, a: __m128i) { + ptr::write(mem_addr as *mut __m128i, a); +} + /// Load 512-bits (composed of 16 packed single-precision (32-bit) floating-point elements) from memory into dst. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_load_ps&expand=3336) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_ps&expand=3336) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] @@ -18408,7 +32484,7 @@ pub unsafe fn _mm512_load_ps(mem_addr: *const f32) -> __m512 { /// Store 512-bits of integer data from a into memory. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_store_ps&expand=5592) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_ps&expand=5592) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] @@ -18418,7 +32494,7 @@ pub unsafe fn _mm512_store_ps(mem_addr: *mut f32, a: __m512) { /// Load 512-bits (composed of 8 packed double-precision (64-bit) floating-point elements) from memory into dst. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_load_pd&expand=3326) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_load_pd&expand=3326) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] //should be vmovapd @@ -18428,7 +32504,7 @@ pub unsafe fn _mm512_load_pd(mem_addr: *const f64) -> __m512d { /// Store 512-bits (composed of 8 packed double-precision (64-bit) floating-point elements) from a into memory. mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=512_store_pd&expand=5585) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_store_pd&expand=5585) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vmovaps))] //should be vmovapd @@ -19286,13 +33362,16 @@ pub unsafe fn _mm_getmant_ss( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4_1:expr, $imm2:expr) => { vgetmantss( - a.as_f32x4(), - b.as_f32x4(), + a, + b, $imm2 << 2 | $imm4_1, - _mm_setzero_ps().as_f32x4(), + zero, 0b1, _MM_FROUND_CUR_DIRECTION, ) @@ -19327,16 +33406,12 @@ pub unsafe fn _mm_mask_getmant_ss( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4_1:expr, $imm2:expr) => { - vgetmantss( - a.as_f32x4(), - b.as_f32x4(), - $imm2 << 2 | $imm4_1, - src.as_f32x4(), - k, - _MM_FROUND_CUR_DIRECTION, - ) + vgetmantss(a, b, $imm2 << 2 | $imm4_1, src, k, _MM_FROUND_CUR_DIRECTION) }; } let r = constify_imm4_mantissas!(norm, sign, call); @@ -19367,13 +33442,16 @@ pub unsafe fn _mm_maskz_getmant_ss( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4_1:expr, $imm2:expr) => { vgetmantss( - a.as_f32x4(), - b.as_f32x4(), + a, + b, $imm2 << 2 | $imm4_1, - _mm_setzero_ps().as_f32x4(), + zero, k, _MM_FROUND_CUR_DIRECTION, ) @@ -19406,13 +33484,16 @@ pub unsafe fn _mm_getmant_sd( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4_1:expr, $imm2:expr) => { vgetmantsd( - a.as_f64x2(), - b.as_f64x2(), + a, + b, $imm2 << 2 | $imm4_1, - _mm_setzero_pd().as_f64x2(), + zero, 0b1, _MM_FROUND_CUR_DIRECTION, ) @@ -19447,16 +33528,12 @@ pub unsafe fn _mm_mask_getmant_sd( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4_1:expr, $imm2:expr) => { - vgetmantsd( - a.as_f64x2(), - b.as_f64x2(), - $imm2 << 2 | $imm4_1, - src.as_f64x2(), - k, - _MM_FROUND_CUR_DIRECTION, - ) + vgetmantsd(a, b, $imm2 << 2 | $imm4_1, src, k, _MM_FROUND_CUR_DIRECTION) }; } let r = constify_imm4_mantissas!(norm, sign, call); @@ -19487,13 +33564,16 @@ pub unsafe fn _mm_maskz_getmant_sd( norm: _MM_MANTISSA_NORM_ENUM, sign: _MM_MANTISSA_SIGN_ENUM, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4_1:expr, $imm2:expr) => { vgetmantsd( - a.as_f64x2(), - b.as_f64x2(), + a, + b, $imm2 << 2 | $imm4_1, - _mm_setzero_pd().as_f64x2(), + zero, k, _MM_FROUND_CUR_DIRECTION, ) @@ -19678,13 +33758,10 @@ pub unsafe fn _mm_maskz_roundscale_sd(k: __mmask8, a: __m128d, b: __m128d, imm8: #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefss))] pub unsafe fn _mm_scalef_ss(a: __m128, b: __m128) -> __m128 { - transmute(vscalefss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b11111111, - _MM_FROUND_CUR_DIRECTION, - )) + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); + transmute(vscalefss(a, b, zero, 0b11111111, _MM_FROUND_CUR_DIRECTION)) } /// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, store the result in the lower element of dst using writemask k (the element is copied from src when mask bit 0 is not set), and copy the upper 3 packed elements from a to the upper elements of dst. @@ -19694,13 +33771,10 @@ pub unsafe fn _mm_scalef_ss(a: __m128, b: __m128) -> __m128 { #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vscalefss))] pub unsafe fn _mm_mask_scalef_ss(src: __m128, k: __mmask8, a: __m128, b: __m128) -> __m128 { - transmute(vscalefss( - a.as_f32x4(), - b.as_f32x4(), - src.as_f32x4(), - k, - _MM_FROUND_CUR_DIRECTION, - )) + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); + transmute(vscalefss(a, b, src, k, _MM_FROUND_CUR_DIRECTION)) } /// Scale the packed single-precision (32-bit) floating-point elements in a using values from b, store the result in the lower element of dst using zeromask k (the element is zeroed out when mask bit 0 is not set), and copy the upper 3 packed elements from a to the upper elements of dst. @@ -20222,15 +34296,12 @@ pub unsafe fn _mm_mask3_fnmsub_sd(a: __m128d, b: __m128d, c: __m128d, k: __mmask #[cfg_attr(test, assert_instr(vaddss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_add_round_ss(a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vaddss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vaddss(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20257,9 +34328,12 @@ pub unsafe fn _mm_mask_add_round_ss( b: __m128, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vaddss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vaddss(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20280,15 +34354,12 @@ pub unsafe fn _mm_mask_add_round_ss( #[cfg_attr(test, assert_instr(vaddss, rounding = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_add_round_ss(k: __mmask8, a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vaddss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vaddss(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20309,15 +34380,12 @@ pub unsafe fn _mm_maskz_add_round_ss(k: __mmask8, a: __m128, b: __m128, rounding #[cfg_attr(test, assert_instr(vaddsd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_add_round_sd(a: __m128d, b: __m128d, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vaddsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vaddsd(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20344,9 +34412,12 @@ pub unsafe fn _mm_mask_add_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vaddsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vaddsd(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20372,15 +34443,12 @@ pub unsafe fn _mm_maskz_add_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vaddsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vaddsd(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20401,15 +34469,12 @@ pub unsafe fn _mm_maskz_add_round_sd( #[cfg_attr(test, assert_instr(vsubss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_sub_round_ss(a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vsubss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vsubss(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20436,9 +34501,12 @@ pub unsafe fn _mm_mask_sub_round_ss( b: __m128, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vsubss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vsubss(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20459,15 +34527,12 @@ pub unsafe fn _mm_mask_sub_round_ss( #[cfg_attr(test, assert_instr(vsubss, rounding = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_sub_round_ss(k: __mmask8, a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vsubss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vsubss(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20488,15 +34553,12 @@ pub unsafe fn _mm_maskz_sub_round_ss(k: __mmask8, a: __m128, b: __m128, rounding #[cfg_attr(test, assert_instr(vsubsd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_sub_round_sd(a: __m128d, b: __m128d, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vsubsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vsubsd(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20523,9 +34585,12 @@ pub unsafe fn _mm_mask_sub_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vsubsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vsubsd(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20551,15 +34616,12 @@ pub unsafe fn _mm_maskz_sub_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vsubsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vsubsd(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20580,15 +34642,12 @@ pub unsafe fn _mm_maskz_sub_round_sd( #[cfg_attr(test, assert_instr(vmulss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_mul_round_ss(a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vmulss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vmulss(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20615,9 +34674,12 @@ pub unsafe fn _mm_mask_mul_round_ss( b: __m128, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vmulss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vmulss(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20638,15 +34700,12 @@ pub unsafe fn _mm_mask_mul_round_ss( #[cfg_attr(test, assert_instr(vmulss, rounding = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_mul_round_ss(k: __mmask8, a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vmulss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vmulss(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20667,15 +34726,12 @@ pub unsafe fn _mm_maskz_mul_round_ss(k: __mmask8, a: __m128, b: __m128, rounding #[cfg_attr(test, assert_instr(vmulsd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_mul_round_sd(a: __m128d, b: __m128d, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vmulsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vmulsd(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20702,9 +34758,12 @@ pub unsafe fn _mm_mask_mul_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vmulsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vmulsd(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20730,15 +34789,12 @@ pub unsafe fn _mm_maskz_mul_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vmulsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vmulsd(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20759,15 +34815,12 @@ pub unsafe fn _mm_maskz_mul_round_sd( #[cfg_attr(test, assert_instr(vdivss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_div_round_ss(a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vdivss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vdivss(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20794,9 +34847,12 @@ pub unsafe fn _mm_mask_div_round_ss( b: __m128, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vdivss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vdivss(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20817,15 +34873,12 @@ pub unsafe fn _mm_mask_div_round_ss( #[cfg_attr(test, assert_instr(vdivss, rounding = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_div_round_ss(k: __mmask8, a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vdivss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vdivss(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20846,15 +34899,12 @@ pub unsafe fn _mm_maskz_div_round_ss(k: __mmask8, a: __m128, b: __m128, rounding #[cfg_attr(test, assert_instr(vdivsd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_div_round_sd(a: __m128d, b: __m128d, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vdivsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vdivsd(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20881,9 +34931,12 @@ pub unsafe fn _mm_mask_div_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vdivsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vdivsd(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20909,15 +34962,12 @@ pub unsafe fn _mm_maskz_div_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vdivsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vdivsd(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -20932,15 +34982,12 @@ pub unsafe fn _mm_maskz_div_round_sd( #[cfg_attr(test, assert_instr(vmaxss, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_max_round_ss(a: __m128, b: __m128, sae: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vmaxss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vmaxss(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -20961,9 +35008,12 @@ pub unsafe fn _mm_mask_max_round_ss( b: __m128, sae: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vmaxss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vmaxss(a, b, src, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -20978,15 +35028,12 @@ pub unsafe fn _mm_mask_max_round_ss( #[cfg_attr(test, assert_instr(vmaxss, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_max_round_ss(k: __mmask8, a: __m128, b: __m128, sae: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vmaxss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vmaxss(a, b, zero, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21001,15 +35048,12 @@ pub unsafe fn _mm_maskz_max_round_ss(k: __mmask8, a: __m128, b: __m128, sae: i32 #[cfg_attr(test, assert_instr(vmaxsd, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_max_round_sd(a: __m128d, b: __m128d, sae: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vmaxsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vmaxsd(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21030,9 +35074,12 @@ pub unsafe fn _mm_mask_max_round_sd( b: __m128d, sae: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vmaxsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vmaxsd(a, b, src, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21047,15 +35094,12 @@ pub unsafe fn _mm_mask_max_round_sd( #[cfg_attr(test, assert_instr(vmaxsd, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_max_round_sd(k: __mmask8, a: __m128d, b: __m128d, sae: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vmaxsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vmaxsd(a, b, zero, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21070,15 +35114,12 @@ pub unsafe fn _mm_maskz_max_round_sd(k: __mmask8, a: __m128d, b: __m128d, sae: i #[cfg_attr(test, assert_instr(vminss, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_min_round_ss(a: __m128, b: __m128, sae: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vminss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vminss(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21099,9 +35140,12 @@ pub unsafe fn _mm_mask_min_round_ss( b: __m128, sae: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vminss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vminss(a, b, src, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21116,15 +35160,12 @@ pub unsafe fn _mm_mask_min_round_ss( #[cfg_attr(test, assert_instr(vminss, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_min_round_ss(k: __mmask8, a: __m128, b: __m128, sae: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vminss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vminss(a, b, zero, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21139,15 +35180,12 @@ pub unsafe fn _mm_maskz_min_round_ss(k: __mmask8, a: __m128, b: __m128, sae: i32 #[cfg_attr(test, assert_instr(vminsd, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_min_round_sd(a: __m128d, b: __m128d, sae: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vminsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vminsd(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21168,9 +35206,12 @@ pub unsafe fn _mm_mask_min_round_sd( b: __m128d, sae: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vminsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vminsd(a, b, src, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21185,15 +35226,12 @@ pub unsafe fn _mm_mask_min_round_sd( #[cfg_attr(test, assert_instr(vminsd, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_min_round_sd(k: __mmask8, a: __m128d, b: __m128d, sae: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vminsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vminsd(a, b, zero, k, $imm4) }; } transmute(constify_imm4_sae!(sae, call)) @@ -21214,15 +35252,12 @@ pub unsafe fn _mm_maskz_min_round_sd(k: __mmask8, a: __m128d, b: __m128d, sae: i #[cfg_attr(test, assert_instr(vsqrtss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_sqrt_round_ss(a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vsqrtss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vsqrtss(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -21249,9 +35284,12 @@ pub unsafe fn _mm_mask_sqrt_round_ss( b: __m128, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vsqrtss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vsqrtss(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -21272,15 +35310,12 @@ pub unsafe fn _mm_mask_sqrt_round_ss( #[cfg_attr(test, assert_instr(vsqrtss, rounding = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_sqrt_round_ss(k: __mmask8, a: __m128, b: __m128, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vsqrtss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vsqrtss(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -21301,15 +35336,12 @@ pub unsafe fn _mm_maskz_sqrt_round_ss(k: __mmask8, a: __m128, b: __m128, roundin #[cfg_attr(test, assert_instr(vsqrtsd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_sqrt_round_sd(a: __m128d, b: __m128d, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vsqrtsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vsqrtsd(a, b, zero, 0b1, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -21336,9 +35368,12 @@ pub unsafe fn _mm_mask_sqrt_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vsqrtsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vsqrtsd(a, b, src, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -21364,15 +35399,12 @@ pub unsafe fn _mm_maskz_sqrt_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vsqrtsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vsqrtsd(a, b, zero, k, $imm4) }; } transmute(constify_imm4_round!(rounding, call)) @@ -21387,15 +35419,12 @@ pub unsafe fn _mm_maskz_sqrt_round_sd( #[cfg_attr(test, assert_instr(vgetexpss, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_getexp_round_ss(a: __m128, b: __m128, sae: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vgetexpss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4, - ) + vgetexpss(a, b, zero, 0b1, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -21417,9 +35446,12 @@ pub unsafe fn _mm_mask_getexp_round_ss( b: __m128, sae: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vgetexpss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vgetexpss(a, b, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -21435,15 +35467,12 @@ pub unsafe fn _mm_mask_getexp_round_ss( #[cfg_attr(test, assert_instr(vgetexpss, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_getexp_round_ss(k: __mmask8, a: __m128, b: __m128, sae: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vgetexpss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vgetexpss(a, b, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -21459,15 +35488,12 @@ pub unsafe fn _mm_maskz_getexp_round_ss(k: __mmask8, a: __m128, b: __m128, sae: #[cfg_attr(test, assert_instr(vgetexpsd, sae = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_getexp_round_sd(a: __m128d, b: __m128d, sae: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vgetexpsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4, - ) + vgetexpsd(a, b, zero, 0b1, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -21489,9 +35515,12 @@ pub unsafe fn _mm_mask_getexp_round_sd( b: __m128d, sae: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vgetexpsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vgetexpsd(a, b, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -21507,15 +35536,12 @@ pub unsafe fn _mm_mask_getexp_round_sd( #[cfg_attr(test, assert_instr(vgetexpsd, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_getexp_round_sd(k: __mmask8, a: __m128d, b: __m128d, sae: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vgetexpsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vgetexpsd(a, b, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -21546,16 +35572,12 @@ pub unsafe fn _mm_getmant_round_ss( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantss( - a.as_f32x4(), - b.as_f32x4(), - $imm2 << 2 | $imm4_1, - _mm_setzero_ps().as_f32x4(), - 0b1, - $imm4_2, - ) + vgetmantss(a, b, $imm2 << 2 | $imm4_1, zero, 0b1, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -21588,16 +35610,12 @@ pub unsafe fn _mm_mask_getmant_round_ss( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantss( - a.as_f32x4(), - b.as_f32x4(), - $imm2 << 2 | $imm4_1, - src.as_f32x4(), - k, - $imm4_2, - ) + vgetmantss(a, b, $imm2 << 2 | $imm4_1, src, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -21629,16 +35647,12 @@ pub unsafe fn _mm_maskz_getmant_round_ss( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantss( - a.as_f32x4(), - b.as_f32x4(), - $imm2 << 2 | $imm4_1, - _mm_setzero_ps().as_f32x4(), - k, - $imm4_2, - ) + vgetmantss(a, b, $imm2 << 2 | $imm4_1, zero, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -21669,16 +35683,12 @@ pub unsafe fn _mm_getmant_round_sd( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantsd( - a.as_f64x2(), - b.as_f64x2(), - $imm2 << 2 | $imm4_1, - _mm_setzero_pd().as_f64x2(), - 0b1, - $imm4_2, - ) + vgetmantsd(a, b, $imm2 << 2 | $imm4_1, zero, 0b1, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -21711,16 +35721,12 @@ pub unsafe fn _mm_mask_getmant_round_sd( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantsd( - a.as_f64x2(), - b.as_f64x2(), - $imm2 << 2 | $imm4_1, - src.as_f64x2(), - k, - $imm4_2, - ) + vgetmantsd(a, b, $imm2 << 2 | $imm4_1, src, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -21752,16 +35758,12 @@ pub unsafe fn _mm_maskz_getmant_round_sd( sign: _MM_MANTISSA_SIGN_ENUM, sae: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4_1:expr, $imm2:expr, $imm4_2:expr) => { - vgetmantsd( - a.as_f64x2(), - b.as_f64x2(), - $imm2 << 2 | $imm4_1, - _mm_setzero_pd().as_f64x2(), - k, - $imm4_2, - ) + vgetmantsd(a, b, $imm2 << 2 | $imm4_1, zero, k, $imm4_2) }; } let r = constify_imm4_mantissas_sae!(norm, sign, sae, call); @@ -22004,9 +36006,12 @@ pub unsafe fn _mm_mask_scalef_round_ss( b: __m128, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vscalefss(a.as_f32x4(), b.as_f32x4(), src.as_f32x4(), k, $imm4) + vscalefss(a, b, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -22033,15 +36038,12 @@ pub unsafe fn _mm_maskz_scalef_round_ss( b: __m128, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vscalefss( - a.as_f32x4(), - b.as_f32x4(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vscalefss(a, b, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -22063,15 +36065,12 @@ pub unsafe fn _mm_maskz_scalef_round_ss( #[cfg_attr(test, assert_instr(vscalefsd, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_scalef_round_sd(a: __m128d, b: __m128d, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vscalefsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - 0b11111111, - $imm4, - ) + vscalefsd(a, b, zero, 0b11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -22099,9 +36098,12 @@ pub unsafe fn _mm_mask_scalef_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vscalefsd(a.as_f64x2(), b.as_f64x2(), src.as_f64x2(), k, $imm4) + vscalefsd(a, b, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -22128,15 +36130,12 @@ pub unsafe fn _mm_maskz_scalef_round_sd( b: __m128d, rounding: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f64x2(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vscalefsd( - a.as_f64x2(), - b.as_f64x2(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vscalefsd(a, b, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23428,8 +37427,8 @@ pub unsafe fn _mm_maskz_fixupimm_sd( } /// Fix up the lower single-precision (32-bit) floating-point elements in a and b using the lower 32-bit integer in c, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. imm8 is used to set the required flags reporting.\ -/// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_fixupimm_round_ss&expand=2511) #[inline] #[target_feature(enable = "avx512f")] @@ -23457,8 +37456,8 @@ pub unsafe fn _mm_fixupimm_round_ss( } /// Fix up the lower single-precision (32-bit) floating-point elements in a and b using the lower 32-bit integer in c, store the result in the lower element of dst using writemask k (the element is copied from a when mask bit 0 is not set), and copy the upper 3 packed elements from a to the upper elements of dst. imm8 is used to set the required flags reporting.\ -/// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_mask_fixupimm_round_ss&expand=2512) #[inline] #[target_feature(enable = "avx512f")] @@ -23487,8 +37486,8 @@ pub unsafe fn _mm_mask_fixupimm_round_ss( } /// Fix up the lower single-precision (32-bit) floating-point elements in a and b using the lower 32-bit integer in c, store the result in the lower element of dst using zeromask k (the element is zeroed out when mask bit 0 is not set), and copy the upper 3 packed elements from a to the upper elements of dst. imm8 is used to set the required flags reporting.\ -/// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_maskz_fixupimm_round_ss&expand=2513) #[inline] #[target_feature(enable = "avx512f")] @@ -23517,8 +37516,8 @@ pub unsafe fn _mm_maskz_fixupimm_round_ss( } /// Fix up the lower double-precision (64-bit) floating-point elements in a and b using the lower 64-bit integer in c, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst. imm8 is used to set the required flags reporting.\ -/// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_fixupimm_round_sd&expand=2508) #[inline] #[target_feature(enable = "avx512f")] @@ -23546,8 +37545,8 @@ pub unsafe fn _mm_fixupimm_round_sd( } /// Fix up the lower double-precision (64-bit) floating-point elements in a and b using the lower 64-bit integer in c, store the result in the lower element of dst using writemask k (the element is copied from a when mask bit 0 is not set), and copy the upper element from a to the upper element of dst. imm8 is used to set the required flags reporting.\ -/// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_mask_fixupimm_round_sd&expand=2509) #[inline] #[target_feature(enable = "avx512f")] @@ -23576,8 +37575,8 @@ pub unsafe fn _mm_mask_fixupimm_round_sd( } /// Fix up the lower double-precision (64-bit) floating-point elements in a and b using the lower 64-bit integer in c, store the result in the lower element of dst using zeromask k (the element is zeroed out when mask bit 0 is not set), and copy the upper element from a to the upper element of dst. imm8 is used to set the required flags reporting.\ -/// /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_maskz_fixupimm_round_sd&expand=2510) #[inline] #[target_feature(enable = "avx512f")] @@ -23708,9 +37707,12 @@ pub unsafe fn _mm_mask_cvt_roundss_sd( b: __m128, sae: i32, ) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f32x4(); + let src = src.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtss2sd(a.as_f64x2(), b.as_f32x4(), src.as_f64x2(), k, $imm4) + vcvtss2sd(a, b, src, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -23726,28 +37728,24 @@ pub unsafe fn _mm_mask_cvt_roundss_sd( #[cfg_attr(test, assert_instr(vcvtss2sd, sae = 8))] #[rustc_args_required_const(3)] pub unsafe fn _mm_maskz_cvt_roundss_sd(k: __mmask8, a: __m128d, b: __m128, sae: i32) -> __m128d { + let a = a.as_f64x2(); + let b = b.as_f32x4(); + let zero = _mm_setzero_pd().as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtss2sd( - a.as_f64x2(), - b.as_f32x4(), - _mm_setzero_pd().as_f64x2(), - k, - $imm4, - ) + vcvtss2sd(a, b, zero, k, $imm4) }; } let r = constify_imm4_sae!(sae, call); transmute(r) } -/// Convert the lower double-precision (64-bit) floating-point element in b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. -/// -/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of: -/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions -/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions -/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions -/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions +/// Convert the lower double-precision (64-bit) floating-point element in b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvt_roundsd_ss&expand=1361) @@ -23756,28 +37754,24 @@ pub unsafe fn _mm_maskz_cvt_roundss_sd(k: __mmask8, a: __m128d, b: __m128, sae: #[cfg_attr(test, assert_instr(vcvtsd2ss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_cvt_roundsd_ss(a: __m128, b: __m128d, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f64x2(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtsd2ss( - a.as_f32x4(), - b.as_f64x2(), - _mm_setzero_ps().as_f32x4(), - 0b11111111, - $imm4, - ) + vcvtsd2ss(a, b, zero, 0b11111111, $imm4) }; } let r = constify_imm4_round!(rounding, call); transmute(r) } -/// Convert the lower double-precision (64-bit) floating-point element in b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst using writemask k (the element is copied from src when mask bit 0 is not set), and copy the upper 3 packed elements from a to the upper elements of dst. -/// -/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of: -/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions -/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions -/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions -/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions +/// Convert the lower double-precision (64-bit) floating-point element in b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst using writemask k (the element is copied from src when mask bit 0 is not set), and copy the upper 3 packed elements from a to the upper elements of dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ /// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_mask_cvt_roundsd_ss&expand=1362) @@ -23792,9 +37786,12 @@ pub unsafe fn _mm_mask_cvt_roundsd_ss( b: __m128d, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f64x2(); + let src = src.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtsd2ss(a.as_f32x4(), b.as_f64x2(), src.as_f32x4(), k, $imm4) + vcvtsd2ss(a, b, src, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23802,7 +37799,6 @@ pub unsafe fn _mm_mask_cvt_roundsd_ss( } /// Convert the lower double-precision (64-bit) floating-point element in b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst using zeromask k (the element is zeroed out when mask bit 0 is not set), and copy the upper 3 packed elements from a to the upper elements of dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -23821,15 +37817,12 @@ pub unsafe fn _mm_maskz_cvt_roundsd_ss( b: __m128d, rounding: i32, ) -> __m128 { + let a = a.as_f32x4(); + let b = b.as_f64x2(); + let zero = _mm_setzero_ps().as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtsd2ss( - a.as_f32x4(), - b.as_f64x2(), - _mm_setzero_ps().as_f32x4(), - k, - $imm4, - ) + vcvtsd2ss(a, b, zero, k, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23837,7 +37830,6 @@ pub unsafe fn _mm_maskz_cvt_roundsd_ss( } /// Convert the lower single-precision (32-bit) floating-point element in a to a 32-bit integer, and store the result in dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -23851,9 +37843,10 @@ pub unsafe fn _mm_maskz_cvt_roundsd_ss( #[cfg_attr(test, assert_instr(vcvtss2si, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvt_roundss_si32(a: __m128, rounding: i32) -> i32 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtss2si(a.as_f32x4(), $imm4) + vcvtss2si(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23861,7 +37854,6 @@ pub unsafe fn _mm_cvt_roundss_si32(a: __m128, rounding: i32) -> i32 { } /// Convert the lower single-precision (32-bit) floating-point element in a to a 32-bit integer, and store the result in dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -23875,9 +37867,10 @@ pub unsafe fn _mm_cvt_roundss_si32(a: __m128, rounding: i32) -> i32 { #[cfg_attr(test, assert_instr(vcvtss2si, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvt_roundss_i32(a: __m128, rounding: i32) -> i32 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtss2si(a.as_f32x4(), $imm4) + vcvtss2si(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23885,7 +37878,6 @@ pub unsafe fn _mm_cvt_roundss_i32(a: __m128, rounding: i32) -> i32 { } /// Convert the lower single-precision (32-bit) floating-point element in a to an unsigned 32-bit integer, and store the result in dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -23899,9 +37891,10 @@ pub unsafe fn _mm_cvt_roundss_i32(a: __m128, rounding: i32) -> i32 { #[cfg_attr(test, assert_instr(vcvtss2usi, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvt_roundss_u32(a: __m128, rounding: i32) -> u32 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtss2usi(a.as_f32x4(), $imm4) + vcvtss2usi(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23929,7 +37922,6 @@ pub unsafe fn _mm_cvtss_u32(a: __m128) -> u32 { } /// Convert the lower double-precision (64-bit) floating-point element in a to a 32-bit integer, and store the result in dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -23943,9 +37935,10 @@ pub unsafe fn _mm_cvtss_u32(a: __m128) -> u32 { #[cfg_attr(test, assert_instr(vcvtsd2si, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvt_roundsd_si32(a: __m128d, rounding: i32) -> i32 { + let a = a.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtsd2si(a.as_f64x2(), $imm4) + vcvtsd2si(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23953,7 +37946,6 @@ pub unsafe fn _mm_cvt_roundsd_si32(a: __m128d, rounding: i32) -> i32 { } /// Convert the lower single-precision (32-bit) floating-point element in a to a 32-bit integer, and store the result in dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -23967,9 +37959,10 @@ pub unsafe fn _mm_cvt_roundsd_si32(a: __m128d, rounding: i32) -> i32 { #[cfg_attr(test, assert_instr(vcvtsd2si, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvt_roundsd_i32(a: __m128d, rounding: i32) -> i32 { + let a = a.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtsd2si(a.as_f64x2(), $imm4) + vcvtsd2si(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -23977,7 +37970,6 @@ pub unsafe fn _mm_cvt_roundsd_i32(a: __m128d, rounding: i32) -> i32 { } /// Convert the lower double-precision (64-bit) floating-point element in a to an unsigned 32-bit integer, and store the result in dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -23991,9 +37983,10 @@ pub unsafe fn _mm_cvt_roundsd_i32(a: __m128d, rounding: i32) -> i32 { #[cfg_attr(test, assert_instr(vcvtsd2usi, rounding = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvt_roundsd_u32(a: __m128d, rounding: i32) -> u32 { + let a = a.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtsd2usi(a.as_f64x2(), $imm4) + vcvtsd2usi(a, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -24035,9 +38028,10 @@ pub unsafe fn _mm_cvtsd_u32(a: __m128d) -> u32 { #[cfg_attr(test, assert_instr(vcvtsi2ss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_cvt_roundi32_ss(a: __m128, b: i32, rounding: i32) -> __m128 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtsi2ss(a.as_f32x4(), b, $imm4) + vcvtsi2ss(a, b, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -24059,9 +38053,10 @@ pub unsafe fn _mm_cvt_roundi32_ss(a: __m128, b: i32, rounding: i32) -> __m128 { #[cfg_attr(test, assert_instr(vcvtsi2ss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_cvt_roundsi32_ss(a: __m128, b: i32, rounding: i32) -> __m128 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtsi2ss(a.as_f32x4(), b, $imm4) + vcvtsi2ss(a, b, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -24069,7 +38064,6 @@ pub unsafe fn _mm_cvt_roundsi32_ss(a: __m128, b: i32, rounding: i32) -> __m128 { } /// Convert the unsigned 32-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst.\ -/// /// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ /// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ /// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ @@ -24083,9 +38077,10 @@ pub unsafe fn _mm_cvt_roundsi32_ss(a: __m128, b: i32, rounding: i32) -> __m128 { #[cfg_attr(test, assert_instr(vcvtusi2ss, rounding = 8))] #[rustc_args_required_const(2)] pub unsafe fn _mm_cvt_roundu32_ss(a: __m128, b: u32, rounding: i32) -> __m128 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtusi2ss(a.as_f32x4(), b, $imm4) + vcvtusi2ss(a, b, $imm4) }; } let r = constify_imm4_round!(rounding, call); @@ -24125,9 +38120,10 @@ pub unsafe fn _mm_cvti32_sd(a: __m128d, b: i32) -> __m128d { #[cfg_attr(test, assert_instr(vcvtss2si, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvtt_roundss_si32(a: __m128, sae: i32) -> i32 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtss2si(a.as_f32x4(), $imm4) + vcvtss2si(a, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -24143,9 +38139,10 @@ pub unsafe fn _mm_cvtt_roundss_si32(a: __m128, sae: i32) -> i32 { #[cfg_attr(test, assert_instr(vcvtss2si, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvtt_roundss_i32(a: __m128, sae: i32) -> i32 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtss2si(a.as_f32x4(), $imm4) + vcvtss2si(a, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -24161,9 +38158,10 @@ pub unsafe fn _mm_cvtt_roundss_i32(a: __m128, sae: i32) -> i32 { #[cfg_attr(test, assert_instr(vcvtss2usi, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvtt_roundss_u32(a: __m128, sae: i32) -> u32 { + let a = a.as_f32x4(); macro_rules! call { ($imm4:expr) => { - vcvtss2usi(a.as_f32x4(), $imm4) + vcvtss2usi(a, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -24172,7 +38170,7 @@ pub unsafe fn _mm_cvtt_roundss_u32(a: __m128, sae: i32) -> u32 { /// Convert the lower single-precision (32-bit) floating-point element in a to a 32-bit integer with truncation, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvttss_i32&expand=2022) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_i32&expand=2022) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtss2si))] @@ -24182,7 +38180,7 @@ pub unsafe fn _mm_cvttss_i32(a: __m128) -> i32 { /// Convert the lower single-precision (32-bit) floating-point element in a to an unsigned 32-bit integer with truncation, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvttss_u32&expand=2026) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_u32&expand=2026) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtss2usi))] @@ -24193,15 +38191,16 @@ pub unsafe fn _mm_cvttss_u32(a: __m128) -> u32 { /// Convert the lower double-precision (64-bit) floating-point element in a to a 32-bit integer with truncation, and store the result in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvtt_roundsd_si32&expand=1930) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_si32&expand=1930) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtsd2si, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvtt_roundsd_si32(a: __m128d, sae: i32) -> i32 { + let a = a.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtsd2si(a.as_f64x2(), $imm4) + vcvtsd2si(a, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -24211,15 +38210,16 @@ pub unsafe fn _mm_cvtt_roundsd_si32(a: __m128d, sae: i32) -> i32 { /// Convert the lower double-precision (64-bit) floating-point element in a to a 32-bit integer with truncation, and store the result in dst.\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvtt_roundsd_i32&expand=1928) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_i32&expand=1928) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtsd2si, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvtt_roundsd_i32(a: __m128d, sae: i32) -> i32 { + let a = a.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtsd2si(a.as_f64x2(), $imm4) + vcvtsd2si(a, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -24235,9 +38235,10 @@ pub unsafe fn _mm_cvtt_roundsd_i32(a: __m128d, sae: i32) -> i32 { #[cfg_attr(test, assert_instr(vcvtsd2usi, sae = 8))] #[rustc_args_required_const(1)] pub unsafe fn _mm_cvtt_roundsd_u32(a: __m128d, sae: i32) -> u32 { + let a = a.as_f64x2(); macro_rules! call { ($imm4:expr) => { - vcvtsd2usi(a.as_f64x2(), $imm4) + vcvtsd2usi(a, $imm4) }; } let r = constify_imm4_sae!(sae, call); @@ -24246,7 +38247,7 @@ pub unsafe fn _mm_cvtt_roundsd_u32(a: __m128d, sae: i32) -> u32 { /// Convert the lower double-precision (64-bit) floating-point element in a to a 32-bit integer with truncation, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvttsd_i32&expand=2015) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_i32&expand=2015) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtsd2si))] @@ -24256,7 +38257,7 @@ pub unsafe fn _mm_cvttsd_i32(a: __m128d) -> i32 { /// Convert the lower double-precision (64-bit) floating-point element in a to an unsigned 32-bit integer with truncation, and store the result in dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvttsd_u32&expand=2020) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_u32&expand=2020) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtsd2usi))] @@ -24266,7 +38267,7 @@ pub unsafe fn _mm_cvttsd_u32(a: __m128d) -> u32 { /// Convert the unsigned 32-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvtu32_ss&expand=2032) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu32_ss&expand=2032) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtusi2ss))] @@ -24278,7 +38279,7 @@ pub unsafe fn _mm_cvtu32_ss(a: __m128, b: u32) -> __m128 { /// Convert the unsigned 32-bit integer b to a double-precision (64-bit) floating-point element, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvtu32_sd&expand=2031) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu32_sd&expand=2031) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcvtusi2sd))] @@ -24288,42 +38289,20 @@ pub unsafe fn _mm_cvtu32_sd(a: __m128d, b: u32) -> __m128d { transmute(r) } -/// Convert the unsigned 64-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. -/// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvtu64_ss&expand=2035) -#[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(mov))] // should be vcvtusi2ss -pub unsafe fn _mm_cvtu64_ss(a: __m128, b: u64) -> __m128 { - let b = b as f32; - let r = simd_insert(a, 0, b); - transmute(r) -} - -/// Convert the unsigned 64-bit integer b to a double-precision (64-bit) floating-point element, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst. -/// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvtu64_sd&expand=2034) -#[inline] -#[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(mov))] // should be vcvtusi2sd -pub unsafe fn _mm_cvtu64_sd(a: __m128d, b: u64) -> __m128d { - let b = b as f64; - let r = simd_insert(a, 0, b); - transmute(r) -} - /// Compare the lower single-precision (32-bit) floating-point element in a and b based on the comparison operand specified by imm8, and return the boolean result (0 or 1).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_comi_round_ss&expand=1175) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comi_round_ss&expand=1175) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcmp, imm8 = 5, sae = 4))] //should be vcomiss #[rustc_args_required_const(2, 3)] pub unsafe fn _mm_comi_round_ss(a: __m128, b: __m128, imm8: i32, sae: i32) -> i32 { + let a = a.as_f32x4(); + let b = b.as_f32x4(); macro_rules! call { ($imm8:expr, $imm4:expr) => { - vcomiss(a.as_f32x4(), b.as_f32x4(), $imm8, $imm4) + vcomiss(a, b, $imm8, $imm4) }; } let r = constify_imm5_sae!(imm8, sae, call); @@ -24333,15 +38312,17 @@ pub unsafe fn _mm_comi_round_ss(a: __m128, b: __m128, imm8: i32, sae: i32) -> i3 /// Compare the lower double-precision (64-bit) floating-point element in a and b based on the comparison operand specified by imm8, and return the boolean result (0 or 1).\ /// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. /// -/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_comi_round_sd&expand=1174) +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comi_round_sd&expand=1174) #[inline] #[target_feature(enable = "avx512f")] #[cfg_attr(test, assert_instr(vcmp, imm8 = 5, sae = 4))] //should be vcomisd #[rustc_args_required_const(2, 3)] pub unsafe fn _mm_comi_round_sd(a: __m128d, b: __m128d, imm8: i32, sae: i32) -> i32 { + let a = a.as_f64x2(); + let b = b.as_f64x2(); macro_rules! call { ($imm8:expr, $imm4:expr) => { - vcomisd(a.as_f64x2(), b.as_f64x2(), $imm8, $imm4) + vcomisd(a, b, $imm8, $imm4) }; } let r = constify_imm5_sae!(imm8, sae, call); @@ -24647,31 +38628,58 @@ extern "C" { #[link_name = "llvm.x86.avx512.mask.pmaxs.d.512"] fn vpmaxsd(a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.pmaxs.q.512"] fn vpmaxsq(a: i64x8, b: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.pmaxs.q.256"] + fn vpmaxsq256(a: i64x4, b: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.pmaxs.q.128"] + fn vpmaxsq128(a: i64x2, b: i64x2) -> i64x2; + #[link_name = "llvm.x86.avx512.mask.pmins.d.512"] fn vpminsd(a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.pmins.q.512"] fn vpminsq(a: i64x8, b: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.pmins.q.256"] + fn vpminsq256(a: i64x4, b: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.pmins.q.128"] + fn vpminsq128(a: i64x2, b: i64x2) -> i64x2; #[link_name = "llvm.x86.avx512.mask.pmaxu.d.512"] fn vpmaxud(a: u32x16, b: u32x16) -> u32x16; + #[link_name = "llvm.x86.avx512.mask.pmaxu.q.512"] - fn vpmaxuq(a: u64x8, b: u64x8) -> i64x8; + fn vpmaxuq(a: u64x8, b: u64x8) -> u64x8; + #[link_name = "llvm.x86.avx512.mask.pmaxu.q.256"] + fn vpmaxuq256(a: u64x4, b: u64x4) -> u64x4; + #[link_name = "llvm.x86.avx512.mask.pmaxu.q.128"] + fn vpmaxuq128(a: u64x2, b: u64x2) -> u64x2; + #[link_name = "llvm.x86.avx512.mask.pminu.d.512"] fn vpminud(a: u32x16, b: u32x16) -> u32x16; + #[link_name = "llvm.x86.avx512.mask.pminu.q.512"] - fn vpminuq(a: u64x8, b: u64x8) -> i64x8; + fn vpminuq(a: u64x8, b: u64x8) -> u64x8; + #[link_name = "llvm.x86.avx512.mask.pminu.q.256"] + fn vpminuq256(a: u64x4, b: u64x4) -> u64x4; + #[link_name = "llvm.x86.avx512.mask.pminu.q.128"] + fn vpminuq128(a: u64x2, b: u64x2) -> u64x2; #[link_name = "llvm.x86.avx512.sqrt.ps.512"] fn vsqrtps(a: f32x16, rounding: i32) -> f32x16; #[link_name = "llvm.x86.avx512.sqrt.pd.512"] fn vsqrtpd(a: f64x8, rounding: i32) -> f64x8; + #[link_name = "llvm.fma.v16f32"] + fn vfmadd132ps(a: f32x16, b: f32x16, c: f32x16) -> f32x16; + #[link_name = "llvm.fma.v8f64"] + fn vfmadd132pd(a: f64x8, b: f64x8, c: f64x8) -> f64x8; + #[link_name = "llvm.x86.avx512.vfmadd.ps.512"] - fn vfmadd132ps(a: f32x16, b: f32x16, c: f32x16, rounding: i32) -> f32x16; + fn vfmadd132psround(a: f32x16, b: f32x16, c: f32x16, rounding: i32) -> f32x16; #[link_name = "llvm.x86.avx512.vfmadd.pd.512"] - fn vfmadd132pd(a: f64x8, b: f64x8, c: f64x8, rounding: i32) -> f64x8; + fn vfmadd132pdround(a: f64x8, b: f64x8, c: f64x8, rounding: i32) -> f64x8; #[link_name = "llvm.x86.avx512.vfmaddsub.ps.512"] fn vfmaddsub213ps(a: f32x16, b: f32x16, c: f32x16, d: i32) -> f32x16; //from clang @@ -24706,58 +38714,156 @@ extern "C" { #[link_name = "llvm.x86.avx512.mask.getexp.ps.512"] fn vgetexpps(a: f32x16, src: f32x16, m: u16, sae: i32) -> f32x16; + + #[link_name = "llvm.x86.avx512.mask.getexp.ps.256"] + fn vgetexpps256(a: f32x8, src: f32x8, m: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.getexp.ps.128"] + fn vgetexpps128(a: f32x4, src: f32x4, m: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.mask.getexp.pd.512"] fn vgetexppd(a: f64x8, src: f64x8, m: u8, sae: i32) -> f64x8; + #[link_name = "llvm.x86.avx512.mask.getexp.pd.256"] + fn vgetexppd256(a: f64x4, src: f64x4, m: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.mask.getexp.pd.128"] + fn vgetexppd128(a: f64x2, src: f64x2, m: u8) -> f64x2; #[link_name = "llvm.x86.avx512.mask.rndscale.ps.512"] fn vrndscaleps(a: f32x16, imm8: i32, src: f32x16, mask: u16, sae: i32) -> f32x16; + #[link_name = "llvm.x86.avx512.mask.rndscale.ps.256"] + fn vrndscaleps256(a: f32x8, imm8: i32, src: f32x8, mask: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.rndscale.ps.128"] + fn vrndscaleps128(a: f32x4, imm8: i32, src: f32x4, mask: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.mask.rndscale.pd.512"] fn vrndscalepd(a: f64x8, imm8: i32, src: f64x8, mask: u8, sae: i32) -> f64x8; + #[link_name = "llvm.x86.avx512.mask.rndscale.pd.256"] + fn vrndscalepd256(a: f64x4, imm8: i32, src: f64x4, mask: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.mask.rndscale.pd.128"] + fn vrndscalepd128(a: f64x2, imm8: i32, src: f64x2, mask: u8) -> f64x2; + #[link_name = "llvm.x86.avx512.mask.scalef.ps.512"] fn vscalefps(a: f32x16, b: f32x16, src: f32x16, mask: u16, rounding: i32) -> f32x16; + #[link_name = "llvm.x86.avx512.mask.scalef.ps.256"] + fn vscalefps256(a: f32x8, b: f32x8, src: f32x8, mask: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.scalef.ps.128"] + fn vscalefps128(a: f32x4, b: f32x4, src: f32x4, mask: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.mask.scalef.pd.512"] fn vscalefpd(a: f64x8, b: f64x8, src: f64x8, mask: u8, rounding: i32) -> f64x8; + #[link_name = "llvm.x86.avx512.mask.scalef.pd.256"] + fn vscalefpd256(a: f64x4, b: f64x4, src: f64x4, mask: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.mask.scalef.pd.128"] + fn vscalefpd128(a: f64x2, b: f64x2, src: f64x2, mask: u8) -> f64x2; #[link_name = "llvm.x86.avx512.mask.fixupimm.ps.512"] fn vfixupimmps(a: f32x16, b: f32x16, c: i32x16, imm8: i32, mask: u16, sae: i32) -> f32x16; + #[link_name = "llvm.x86.avx512.mask.fixupimm.ps.256"] + fn vfixupimmps256(a: f32x8, b: f32x8, c: i32x8, imm8: i32, mask: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.fixupimm.ps.128"] + fn vfixupimmps128(a: f32x4, b: f32x4, c: i32x4, imm8: i32, mask: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.mask.fixupimm.pd.512"] fn vfixupimmpd(a: f64x8, b: f64x8, c: i64x8, imm8: i32, mask: u8, sae: i32) -> f64x8; + #[link_name = "llvm.x86.avx512.mask.fixupimm.pd.256"] + fn vfixupimmpd256(a: f64x4, b: f64x4, c: i64x4, imm8: i32, mask: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.mask.fixupimm.pd.128"] + fn vfixupimmpd128(a: f64x2, b: f64x2, c: i64x2, imm8: i32, mask: u8) -> f64x2; + #[link_name = "llvm.x86.avx512.maskz.fixupimm.ps.512"] fn vfixupimmpsz(a: f32x16, b: f32x16, c: i32x16, imm8: i32, mask: u16, sae: i32) -> f32x16; + #[link_name = "llvm.x86.avx512.maskz.fixupimm.ps.256"] + fn vfixupimmpsz256(a: f32x8, b: f32x8, c: i32x8, imm8: i32, mask: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.maskz.fixupimm.ps.128"] + fn vfixupimmpsz128(a: f32x4, b: f32x4, c: i32x4, imm8: i32, mask: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.maskz.fixupimm.pd.512"] fn vfixupimmpdz(a: f64x8, b: f64x8, c: i64x8, imm8: i32, mask: u8, sae: i32) -> f64x8; + #[link_name = "llvm.x86.avx512.maskz.fixupimm.pd.256"] + fn vfixupimmpdz256(a: f64x4, b: f64x4, c: i64x4, imm8: i32, mask: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.maskz.fixupimm.pd.128"] + fn vfixupimmpdz128(a: f64x2, b: f64x2, c: i64x2, imm8: i32, mask: u8) -> f64x2; #[link_name = "llvm.x86.avx512.pternlog.d.512"] - fn vpternlogd(a: i32x16, b: i32x16, c: i32x16, sae: i32) -> i32x16; + fn vpternlogd(a: i32x16, b: i32x16, c: i32x16, imm8: i32) -> i32x16; + #[link_name = "llvm.x86.avx512.pternlog.d.256"] + fn vpternlogd256(a: i32x8, b: i32x8, c: i32x8, imm8: i32) -> i32x8; + #[link_name = "llvm.x86.avx512.pternlog.d.128"] + fn vpternlogd128(a: i32x4, b: i32x4, c: i32x4, imm8: i32) -> i32x4; + #[link_name = "llvm.x86.avx512.pternlog.q.512"] - fn vpternlogq(a: i64x8, b: i64x8, c: i64x8, sae: i32) -> i64x8; + fn vpternlogq(a: i64x8, b: i64x8, c: i64x8, imm8: i32) -> i64x8; + #[link_name = "llvm.x86.avx512.pternlog.q.256"] + fn vpternlogq256(a: i64x4, b: i64x4, c: i64x4, imm8: i32) -> i64x4; + #[link_name = "llvm.x86.avx512.pternlog.q.128"] + fn vpternlogq128(a: i64x2, b: i64x2, c: i64x2, imm8: i32) -> i64x2; #[link_name = "llvm.x86.avx512.mask.getmant.ps.512"] fn vgetmantps(a: f32x16, mantissas: i32, src: f32x16, m: u16, sae: i32) -> f32x16; + #[link_name = "llvm.x86.avx512.mask.getmant.ps.256"] + fn vgetmantps256(a: f32x8, mantissas: i32, src: f32x8, m: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.getmant.ps.128"] + fn vgetmantps128(a: f32x4, mantissas: i32, src: f32x4, m: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.mask.getmant.pd.512"] fn vgetmantpd(a: f64x8, mantissas: i32, src: f64x8, m: u8, sae: i32) -> f64x8; + #[link_name = "llvm.x86.avx512.mask.getmant.pd.256"] + fn vgetmantpd256(a: f64x4, mantissas: i32, src: f64x4, m: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.mask.getmant.pd.128"] + fn vgetmantpd128(a: f64x2, mantissas: i32, src: f64x2, m: u8) -> f64x2; #[link_name = "llvm.x86.avx512.rcp14.ps.512"] fn vrcp14ps(a: f32x16, src: f32x16, m: u16) -> f32x16; + #[link_name = "llvm.x86.avx512.rcp14.ps.256"] + fn vrcp14ps256(a: f32x8, src: f32x8, m: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.rcp14.ps.128"] + fn vrcp14ps128(a: f32x4, src: f32x4, m: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.rcp14.pd.512"] fn vrcp14pd(a: f64x8, src: f64x8, m: u8) -> f64x8; + #[link_name = "llvm.x86.avx512.rcp14.pd.256"] + fn vrcp14pd256(a: f64x4, src: f64x4, m: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.rcp14.pd.128"] + fn vrcp14pd128(a: f64x2, src: f64x2, m: u8) -> f64x2; + #[link_name = "llvm.x86.avx512.rsqrt14.ps.512"] fn vrsqrt14ps(a: f32x16, src: f32x16, m: u16) -> f32x16; + #[link_name = "llvm.x86.avx512.rsqrt14.ps.256"] + fn vrsqrt14ps256(a: f32x8, src: f32x8, m: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.rsqrt14.ps.128"] + fn vrsqrt14ps128(a: f32x4, src: f32x4, m: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.rsqrt14.pd.512"] fn vrsqrt14pd(a: f64x8, src: f64x8, m: u8) -> f64x8; + #[link_name = "llvm.x86.avx512.rsqrt14.pd.256"] + fn vrsqrt14pd256(a: f64x4, src: f64x4, m: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.rsqrt14.pd.128"] + fn vrsqrt14pd128(a: f64x2, src: f64x2, m: u8) -> f64x2; #[link_name = "llvm.x86.avx512.mask.cvtps2dq.512"] fn vcvtps2dq(a: f32x16, src: i32x16, mask: u16, rounding: i32) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.cvtps2udq.512"] fn vcvtps2udq(a: f32x16, src: u32x16, mask: u16, rounding: i32) -> u32x16; + #[link_name = "llvm.x86.avx512.mask.cvtps2udq.256"] + fn vcvtps2udq256(a: f32x8, src: u32x8, mask: u8) -> u32x8; + #[link_name = "llvm.x86.avx512.mask.cvtps2udq.128"] + fn vcvtps2udq128(a: f32x4, src: u32x4, mask: u8) -> u32x4; + #[link_name = "llvm.x86.avx512.mask.cvtps2pd.512"] fn vcvtps2pd(a: f32x8, src: f64x8, mask: u8, sae: i32) -> f64x8; #[link_name = "llvm.x86.avx512.mask.cvtpd2ps.512"] fn vcvtpd2ps(a: f64x8, src: f32x8, mask: u8, rounding: i32) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.cvtpd2dq.512"] fn vcvtpd2dq(a: f64x8, src: i32x8, mask: u8, rounding: i32) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.cvtpd2udq.512"] fn vcvtpd2udq(a: f64x8, src: u32x8, mask: u8, rounding: i32) -> u32x8; + #[link_name = "llvm.x86.avx512.mask.cvtpd2udq.256"] + fn vcvtpd2udq256(a: f64x4, src: u32x4, mask: u8) -> u32x4; + #[link_name = "llvm.x86.avx512.mask.cvtpd2udq.128"] + fn vcvtpd2udq128(a: f64x2, src: u32x4, mask: u8) -> u32x4; + #[link_name = "llvm.x86.avx512.sitofp.round.v16f32.v16i32"] fn vcvtdq2ps(a: i32x16, rounding: i32) -> f32x16; #[link_name = "llvm.x86.avx512.uitofp.round.v16f32.v16i32"] @@ -24765,40 +38871,237 @@ extern "C" { #[link_name = "llvm.x86.avx512.mask.vcvtps2ph.512"] fn vcvtps2ph(a: f32x16, sae: i32, src: i16x16, mask: u16) -> i16x16; + #[link_name = "llvm.x86.avx512.mask.vcvtps2ph.256"] + fn vcvtps2ph256(a: f32x8, sae: i32, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.vcvtps2ph.128"] + fn vcvtps2ph128(a: f32x4, sae: i32, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.vcvtph2ps.512"] fn vcvtph2ps(a: i16x16, src: f32x16, mask: u16, sae: i32) -> f32x16; #[link_name = "llvm.x86.avx512.mask.cvttps2dq.512"] fn vcvttps2dq(a: f32x16, src: i32x16, mask: u16, rounding: i32) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.cvttps2dq.256"] + fn vcvttps2dq256(a: f32x8, src: i32x8, mask: u8) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.cvttps2dq.128"] + fn vcvttps2dq128(a: f32x4, src: i32x4, mask: u8) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.cvttps2udq.512"] - fn vcvttps2udq(a: f32x16, src: i32x16, mask: u16, rounding: i32) -> u32x16; + fn vcvttps2udq(a: f32x16, src: u32x16, mask: u16, rounding: i32) -> u32x16; + #[link_name = "llvm.x86.avx512.mask.cvttps2udq.256"] + fn vcvttps2udq256(a: f32x8, src: u32x8, mask: u8) -> u32x8; + #[link_name = "llvm.x86.avx512.mask.cvttps2udq.128"] + fn vcvttps2udq128(a: f32x4, src: u32x4, mask: u8) -> u32x4; + #[link_name = "llvm.x86.avx512.mask.cvttpd2dq.512"] fn vcvttpd2dq(a: f64x8, src: i32x8, mask: u8, rounding: i32) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.cvttpd2dq.256"] + fn vcvttpd2dq256(a: f64x4, src: i32x4, mask: u8) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.cvttpd2dq.128"] + fn vcvttpd2dq128(a: f64x2, src: i32x4, mask: u8) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.cvttpd2udq.512"] fn vcvttpd2udq(a: f64x8, src: i32x8, mask: u8, rounding: i32) -> u32x8; + #[link_name = "llvm.x86.avx512.mask.cvttpd2udq.256"] + fn vcvttpd2udq256(a: f64x4, src: i32x4, mask: u8) -> u32x4; + #[link_name = "llvm.x86.avx512.mask.cvttpd2udq.128"] + fn vcvttpd2udq128(a: f64x2, src: i32x4, mask: u8) -> u32x4; + + #[link_name = "llvm.x86.avx512.mask.pmov.dw.128"] + fn vpmovdw128(a: i32x4, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmov.db.256"] + fn vpmovdb256(a: i32x8, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmov.db.128"] + fn vpmovdb128(a: i32x4, src: i8x16, mask: u8) -> i8x16; + + #[link_name = "llvm.x86.avx512.mask.pmov.qw.256"] + fn vpmovqw256(a: i64x4, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmov.qw.128"] + fn vpmovqw128(a: i64x2, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmov.qb.256"] + fn vpmovqb256(a: i64x4, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmov.qb.128"] + fn vpmovqb128(a: i64x2, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmov.qd.128"] + fn vpmovqd128(a: i64x2, src: i32x4, mask: u8) -> i32x4; + + #[link_name = "llvm.x86.avx512.mask.pmov.dw.mem.512"] + fn vpmovdwmem(mem_addr: *mut i8, a: i32x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmov.dw.mem.256"] + fn vpmovdwmem256(mem_addr: *mut i8, a: i32x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.dw.mem.128"] + fn vpmovdwmem128(mem_addr: *mut i8, a: i32x4, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovs.dw.mem.512"] + fn vpmovsdwmem(mem_addr: *mut i8, a: i32x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmovs.dw.mem.256"] + fn vpmovsdwmem256(mem_addr: *mut i8, a: i32x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.dw.mem.128"] + fn vpmovsdwmem128(mem_addr: *mut i8, a: i32x4, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovus.dw.mem.512"] + fn vpmovusdwmem(mem_addr: *mut i8, a: i32x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmovus.dw.mem.256"] + fn vpmovusdwmem256(mem_addr: *mut i8, a: i32x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.dw.mem.128"] + fn vpmovusdwmem128(mem_addr: *mut i8, a: i32x4, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmov.db.mem.512"] + fn vpmovdbmem(mem_addr: *mut i8, a: i32x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmov.db.mem.256"] + fn vpmovdbmem256(mem_addr: *mut i8, a: i32x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.db.mem.128"] + fn vpmovdbmem128(mem_addr: *mut i8, a: i32x4, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovs.db.mem.512"] + fn vpmovsdbmem(mem_addr: *mut i8, a: i32x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmovs.db.mem.256"] + fn vpmovsdbmem256(mem_addr: *mut i8, a: i32x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.db.mem.128"] + fn vpmovsdbmem128(mem_addr: *mut i8, a: i32x4, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovus.db.mem.512"] + fn vpmovusdbmem(mem_addr: *mut i8, a: i32x16, mask: u16); + #[link_name = "llvm.x86.avx512.mask.pmovus.db.mem.256"] + fn vpmovusdbmem256(mem_addr: *mut i8, a: i32x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.db.mem.128"] + fn vpmovusdbmem128(mem_addr: *mut i8, a: i32x4, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmov.qw.mem.512"] + fn vpmovqwmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.qw.mem.256"] + fn vpmovqwmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.qw.mem.128"] + fn vpmovqwmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovs.qw.mem.512"] + fn vpmovsqwmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.qw.mem.256"] + fn vpmovsqwmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.qw.mem.128"] + fn vpmovsqwmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovus.qw.mem.512"] + fn vpmovusqwmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.qw.mem.256"] + fn vpmovusqwmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.qw.mem.128"] + fn vpmovusqwmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmov.qb.mem.512"] + fn vpmovqbmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.qb.mem.256"] + fn vpmovqbmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.qb.mem.128"] + fn vpmovqbmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovs.qb.mem.512"] + fn vpmovsqbmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.qb.mem.256"] + fn vpmovsqbmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.qb.mem.128"] + fn vpmovsqbmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovus.qb.mem.512"] + fn vpmovusqbmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.qb.mem.256"] + fn vpmovusqbmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.qb.mem.128"] + fn vpmovusqbmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmov.qd.mem.512"] + fn vpmovqdmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.qd.mem.256"] + fn vpmovqdmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmov.qd.mem.128"] + fn vpmovqdmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovs.qd.mem.512"] + fn vpmovsqdmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.qd.mem.256"] + fn vpmovsqdmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovs.qd.mem.128"] + fn vpmovsqdmem128(mem_addr: *mut i8, a: i64x2, mask: u8); + + #[link_name = "llvm.x86.avx512.mask.pmovus.qd.mem.512"] + fn vpmovusqdmem(mem_addr: *mut i8, a: i64x8, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.qd.mem.256"] + fn vpmovusqdmem256(mem_addr: *mut i8, a: i64x4, mask: u8); + #[link_name = "llvm.x86.avx512.mask.pmovus.qd.mem.128"] + fn vpmovusqdmem128(mem_addr: *mut i8, a: i64x2, mask: u8); #[link_name = "llvm.x86.avx512.mask.pmov.qb.512"] fn vpmovqb(a: i64x8, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.dw.512"] fn vpmovsdw(a: i32x16, src: i16x16, mask: u16) -> i16x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.dw.256"] + fn vpmovsdw256(a: i32x8, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmovs.dw.128"] + fn vpmovsdw128(a: i32x4, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmovs.db.512"] fn vpmovsdb(a: i32x16, src: i8x16, mask: u16) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.db.256"] + fn vpmovsdb256(a: i32x8, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.db.128"] + fn vpmovsdb128(a: i32x4, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.qd.512"] fn vpmovsqd(a: i64x8, src: i32x8, mask: u8) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.pmovs.qd.256"] + fn vpmovsqd256(a: i64x4, src: i32x4, mask: u8) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.pmovs.qd.128"] + fn vpmovsqd128(a: i64x2, src: i32x4, mask: u8) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.pmovs.qw.512"] fn vpmovsqw(a: i64x8, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmovs.qw.256"] + fn vpmovsqw256(a: i64x4, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmovs.qw.128"] + fn vpmovsqw128(a: i64x2, src: i16x8, mask: u8) -> i16x8; + #[link_name = "llvm.x86.avx512.mask.pmovs.qb.512"] fn vpmovsqb(a: i64x8, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.qb.256"] + fn vpmovsqb256(a: i64x4, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovs.qb.128"] + fn vpmovsqb128(a: i64x2, src: i8x16, mask: u8) -> i8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.dw.512"] fn vpmovusdw(a: u32x16, src: u16x16, mask: u16) -> u16x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.dw.256"] + fn vpmovusdw256(a: u32x8, src: u16x8, mask: u8) -> u16x8; + #[link_name = "llvm.x86.avx512.mask.pmovus.dw.128"] + fn vpmovusdw128(a: u32x4, src: u16x8, mask: u8) -> u16x8; + #[link_name = "llvm.x86.avx512.mask.pmovus.db.512"] fn vpmovusdb(a: u32x16, src: u8x16, mask: u16) -> u8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.db.256"] + fn vpmovusdb256(a: u32x8, src: u8x16, mask: u8) -> u8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.db.128"] + fn vpmovusdb128(a: u32x4, src: u8x16, mask: u8) -> u8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.qd.512"] fn vpmovusqd(a: u64x8, src: u32x8, mask: u8) -> u32x8; + #[link_name = "llvm.x86.avx512.mask.pmovus.qd.256"] + fn vpmovusqd256(a: u64x4, src: u32x4, mask: u8) -> u32x4; + #[link_name = "llvm.x86.avx512.mask.pmovus.qd.128"] + fn vpmovusqd128(a: u64x2, src: u32x4, mask: u8) -> u32x4; + #[link_name = "llvm.x86.avx512.mask.pmovus.qw.512"] fn vpmovusqw(a: u64x8, src: u16x8, mask: u8) -> u16x8; + #[link_name = "llvm.x86.avx512.mask.pmovus.qw.256"] + fn vpmovusqw256(a: u64x4, src: u16x8, mask: u8) -> u16x8; + #[link_name = "llvm.x86.avx512.mask.pmovus.qw.128"] + fn vpmovusqw128(a: u64x2, src: u16x8, mask: u8) -> u16x8; + #[link_name = "llvm.x86.avx512.mask.pmovus.qb.512"] fn vpmovusqb(a: u64x8, src: u8x16, mask: u8) -> u8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.qb.256"] + fn vpmovusqb256(a: u64x4, src: u8x16, mask: u8) -> u8x16; + #[link_name = "llvm.x86.avx512.mask.pmovus.qb.128"] + fn vpmovusqb128(a: u64x2, src: u8x16, mask: u8) -> u8x16; #[link_name = "llvm.x86.avx512.gather.dpd.512"] fn vgatherdpd(src: f64x8, slice: *const i8, offsets: i32x8, mask: i8, scale: i32) -> f64x8; @@ -24827,6 +39130,7 @@ extern "C" { fn vscatterqps(slice: *mut i8, mask: i8, offsets: i64x8, src: f32x8, scale: i32); #[link_name = "llvm.x86.avx512.scatter.dpq.512"] fn vpscatterdq(slice: *mut i8, mask: i8, offsets: i32x8, src: i64x8, scale: i32); + #[link_name = "llvm.x86.avx512.scatter.dpi.512"] fn vpscatterdd(slice: *mut i8, mask: i16, offsets: i32x16, src: i32x16, scale: i32); #[link_name = "llvm.x86.avx512.scatter.qpq.512"] @@ -24838,36 +39142,104 @@ extern "C" { fn vcmpss(a: __m128, b: __m128, op: i32, m: i8, sae: i32) -> i8; #[link_name = "llvm.x86.avx512.mask.cmp.sd"] fn vcmpsd(a: __m128d, b: __m128d, op: i32, m: i8, sae: i32) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.ps.512"] fn vcmpps(a: f32x16, b: f32x16, op: i32, m: i16, sae: i32) -> i16; + #[link_name = "llvm.x86.avx512.mask.cmp.ps.256"] + fn vcmpps256(a: f32x8, b: f32x8, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.ps.128"] + fn vcmpps128(a: f32x4, b: f32x4, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.pd.512"] fn vcmppd(a: f64x8, b: f64x8, op: i32, m: i8, sae: i32) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.pd.256"] + fn vcmppd256(a: f64x4, b: f64x4, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.pd.128"] + fn vcmppd128(a: f64x2, b: f64x2, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.ucmp.q.512"] fn vpcmpuq(a: i64x8, b: i64x8, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.ucmp.q.256"] + fn vpcmpuq256(a: i64x4, b: i64x4, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.ucmp.q.128"] + fn vpcmpuq128(a: i64x2, b: i64x2, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.q.512"] fn vpcmpq(a: i64x8, b: i64x8, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.q.256"] + fn vpcmpq256(a: i64x4, b: i64x4, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.q.128"] + fn vpcmpq128(a: i64x2, b: i64x2, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.ucmp.d.512"] fn vpcmpud(a: i32x16, b: i32x16, op: i32, m: i16) -> i16; + #[link_name = "llvm.x86.avx512.mask.ucmp.d.256"] + fn vpcmpud256(a: i32x8, b: i32x8, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.ucmp.d.128"] + fn vpcmpud128(a: i32x4, b: i32x4, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.d.512"] fn vpcmpd(a: i32x16, b: i32x16, op: i32, m: i16) -> i16; + #[link_name = "llvm.x86.avx512.mask.cmp.d.256"] + fn vpcmpd256(a: i32x8, b: i32x8, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.mask.cmp.d.128"] + fn vpcmpd128(a: i32x4, b: i32x4, op: i32, m: i8) -> i8; #[link_name = "llvm.x86.avx512.mask.prol.d.512"] fn vprold(a: i32x16, i8: i32) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.prol.d.256"] + fn vprold256(a: i32x8, i8: i32) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.prol.d.128"] + fn vprold128(a: i32x4, i8: i32) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.pror.d.512"] fn vprord(a: i32x16, i8: i32) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.pror.d.256"] + fn vprord256(a: i32x8, i8: i32) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.pror.d.128"] + fn vprord128(a: i32x4, i8: i32) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.prol.q.512"] fn vprolq(a: i64x8, i8: i32) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.prol.q.256"] + fn vprolq256(a: i64x4, i8: i32) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.prol.q.128"] + fn vprolq128(a: i64x2, i8: i32) -> i64x2; + #[link_name = "llvm.x86.avx512.mask.pror.q.512"] fn vprorq(a: i64x8, i8: i32) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.pror.q.256"] + fn vprorq256(a: i64x4, i8: i32) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.pror.q.128"] + fn vprorq128(a: i64x2, i8: i32) -> i64x2; #[link_name = "llvm.x86.avx512.mask.prolv.d.512"] fn vprolvd(a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.prolv.d.256"] + fn vprolvd256(a: i32x8, b: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.prolv.d.128"] + fn vprolvd128(a: i32x4, b: i32x4) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.prorv.d.512"] fn vprorvd(a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.prorv.d.256"] + fn vprorvd256(a: i32x8, b: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.prorv.d.128"] + fn vprorvd128(a: i32x4, b: i32x4) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.prolv.q.512"] fn vprolvq(a: i64x8, b: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.prolv.q.256"] + fn vprolvq256(a: i64x4, b: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.prolv.q.128"] + fn vprolvq128(a: i64x2, b: i64x2) -> i64x2; + #[link_name = "llvm.x86.avx512.mask.prorv.q.512"] fn vprorvq(a: i64x8, b: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.prorv.q.256"] + fn vprorvq256(a: i64x4, b: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.prorv.q.128"] + fn vprorvq128(a: i64x2, b: i64x2) -> i64x2; #[link_name = "llvm.x86.avx512.psllv.d.512"] fn vpsllvd(a: i32x16, b: i32x16) -> i32x16; @@ -24898,18 +39270,33 @@ extern "C" { #[link_name = "llvm.x86.avx512.psra.d.512"] fn vpsrad(a: i32x16, count: i32x4) -> i32x16; + #[link_name = "llvm.x86.avx512.psra.q.512"] fn vpsraq(a: i64x8, count: i64x2) -> i64x8; + #[link_name = "llvm.x86.avx512.psra.q.256"] + fn vpsraq256(a: i64x4, count: i64x2) -> i64x4; + #[link_name = "llvm.x86.avx512.psra.q.128"] + fn vpsraq128(a: i64x2, count: i64x2) -> i64x2; #[link_name = "llvm.x86.avx512.psrai.d.512"] fn vpsraid(a: i32x16, imm8: u32) -> i32x16; + #[link_name = "llvm.x86.avx512.psrai.q.512"] fn vpsraiq(a: i64x8, imm8: u32) -> i64x8; + #[link_name = "llvm.x86.avx512.psrai.q.256"] + fn vpsraiq256(a: i64x4, imm8: u32) -> i64x4; + #[link_name = "llvm.x86.avx512.psrai.q.128"] + fn vpsraiq128(a: i64x2, imm8: u32) -> i64x2; #[link_name = "llvm.x86.avx512.psrav.d.512"] fn vpsravd(a: i32x16, count: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.psrav.q.512"] fn vpsravq(a: i64x8, count: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.psrav.q.256"] + fn vpsravq256(a: i64x4, count: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.psrav.q.128"] + fn vpsravq128(a: i64x2, count: i64x2) -> i64x2; #[link_name = "llvm.x86.avx512.vpermilvar.ps.512"] fn vpermilps(a: f32x16, b: i32x16) -> f32x16; @@ -24918,38 +39305,103 @@ extern "C" { #[link_name = "llvm.x86.avx512.permvar.si.512"] fn vpermd(a: i32x16, idx: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.permvar.di.512"] fn vpermq(a: i64x8, idx: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.permvar.di.256"] + fn vpermq256(a: i64x4, idx: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.permvar.sf.512"] fn vpermps(a: f32x16, idx: i32x16) -> f32x16; + #[link_name = "llvm.x86.avx512.permvar.df.512"] fn vpermpd(a: f64x8, idx: i64x8) -> f64x8; + #[link_name = "llvm.x86.avx512.permvar.df.256"] + fn vpermpd256(a: f64x4, idx: i64x4) -> f64x4; #[link_name = "llvm.x86.avx512.vpermi2var.d.512"] fn vpermi2d(a: i32x16, idx: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.vpermi2var.d.256"] + fn vpermi2d256(a: i32x8, idx: i32x8, b: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx512.vpermi2var.d.128"] + fn vpermi2d128(a: i32x4, idx: i32x4, b: i32x4) -> i32x4; + #[link_name = "llvm.x86.avx512.vpermi2var.q.512"] fn vpermi2q(a: i64x8, idx: i64x8, b: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.vpermi2var.q.256"] + fn vpermi2q256(a: i64x4, idx: i64x4, b: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.vpermi2var.q.128"] + fn vpermi2q128(a: i64x2, idx: i64x2, b: i64x2) -> i64x2; + #[link_name = "llvm.x86.avx512.vpermi2var.ps.512"] fn vpermi2ps(a: f32x16, idx: i32x16, b: f32x16) -> f32x16; + #[link_name = "llvm.x86.avx512.vpermi2var.ps.256"] + fn vpermi2ps256(a: f32x8, idx: i32x8, b: f32x8) -> f32x8; + #[link_name = "llvm.x86.avx512.vpermi2var.ps.128"] + fn vpermi2ps128(a: f32x4, idx: i32x4, b: f32x4) -> f32x4; + #[link_name = "llvm.x86.avx512.vpermi2var.pd.512"] fn vpermi2pd(a: f64x8, idx: i64x8, b: f64x8) -> f64x8; + #[link_name = "llvm.x86.avx512.vpermi2var.pd.256"] + fn vpermi2pd256(a: f64x4, idx: i64x4, b: f64x4) -> f64x4; + #[link_name = "llvm.x86.avx512.vpermi2var.pd.128"] + fn vpermi2pd128(a: f64x2, idx: i64x2, b: f64x2) -> f64x2; #[link_name = "llvm.x86.avx512.mask.compress.d.512"] fn vpcompressd(a: i32x16, src: i32x16, mask: u16) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.compress.d.256"] + fn vpcompressd256(a: i32x8, src: i32x8, mask: u8) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.compress.d.128"] + fn vpcompressd128(a: i32x4, src: i32x4, mask: u8) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.compress.q.512"] fn vpcompressq(a: i64x8, src: i64x8, mask: u8) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.compress.q.256"] + fn vpcompressq256(a: i64x4, src: i64x4, mask: u8) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.compress.q.128"] + fn vpcompressq128(a: i64x2, src: i64x2, mask: u8) -> i64x2; + #[link_name = "llvm.x86.avx512.mask.compress.ps.512"] fn vcompressps(a: f32x16, src: f32x16, mask: u16) -> f32x16; + #[link_name = "llvm.x86.avx512.mask.compress.ps.256"] + fn vcompressps256(a: f32x8, src: f32x8, mask: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.compress.ps.128"] + fn vcompressps128(a: f32x4, src: f32x4, mask: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.mask.compress.pd.512"] fn vcompresspd(a: f64x8, src: f64x8, mask: u8) -> f64x8; + #[link_name = "llvm.x86.avx512.mask.compress.pd.256"] + fn vcompresspd256(a: f64x4, src: f64x4, mask: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.mask.compress.pd.128"] + fn vcompresspd128(a: f64x2, src: f64x2, mask: u8) -> f64x2; + #[link_name = "llvm.x86.avx512.mask.expand.d.512"] fn vpexpandd(a: i32x16, src: i32x16, mask: u16) -> i32x16; + #[link_name = "llvm.x86.avx512.mask.expand.d.256"] + fn vpexpandd256(a: i32x8, src: i32x8, mask: u8) -> i32x8; + #[link_name = "llvm.x86.avx512.mask.expand.d.128"] + fn vpexpandd128(a: i32x4, src: i32x4, mask: u8) -> i32x4; + #[link_name = "llvm.x86.avx512.mask.expand.q.512"] fn vpexpandq(a: i64x8, src: i64x8, mask: u8) -> i64x8; + #[link_name = "llvm.x86.avx512.mask.expand.q.256"] + fn vpexpandq256(a: i64x4, src: i64x4, mask: u8) -> i64x4; + #[link_name = "llvm.x86.avx512.mask.expand.q.128"] + fn vpexpandq128(a: i64x2, src: i64x2, mask: u8) -> i64x2; + #[link_name = "llvm.x86.avx512.mask.expand.ps.512"] fn vexpandps(a: f32x16, src: f32x16, mask: u16) -> f32x16; + #[link_name = "llvm.x86.avx512.mask.expand.ps.256"] + fn vexpandps256(a: f32x8, src: f32x8, mask: u8) -> f32x8; + #[link_name = "llvm.x86.avx512.mask.expand.ps.128"] + fn vexpandps128(a: f32x4, src: f32x4, mask: u8) -> f32x4; + #[link_name = "llvm.x86.avx512.mask.expand.pd.512"] fn vexpandpd(a: f64x8, src: f64x8, mask: u8) -> f64x8; + #[link_name = "llvm.x86.avx512.mask.expand.pd.256"] + fn vexpandpd256(a: f64x4, src: f64x4, mask: u8) -> f64x4; + #[link_name = "llvm.x86.avx512.mask.expand.pd.128"] + fn vexpandpd128(a: f64x2, src: f64x2, mask: u8) -> f64x2; #[link_name = "llvm.x86.avx512.mask.add.ss.round"] fn vaddss(a: f32x4, b: f32x4, src: f32x4, mask: u8, rounding: i32) -> f32x4; @@ -25027,31 +39479,21 @@ extern "C" { #[link_name = "llvm.x86.avx512.vcvtss2si32"] fn vcvtss2si(a: f32x4, rounding: i32) -> i32; - #[link_name = "llvm.x86.avx512.vcvtss2si64"] - fn vcvtss2si64(a: f32x4, rounding: i32) -> i64; #[link_name = "llvm.x86.avx512.vcvtss2usi32"] fn vcvtss2usi(a: f32x4, rounding: i32) -> u32; - #[link_name = "llvm.x86.avx512.vcvtss2usi64"] - fn vcvtss2usi64(a: f32x4, rounding: i32) -> u64; + #[link_name = "llvm.x86.avx512.vcvtsd2si32"] fn vcvtsd2si(a: f64x2, rounding: i32) -> i32; - #[link_name = "llvm.x86.avx512.vcvtsd2si64"] - fn vcvtsd2si64(a: f64x2, rounding: i32) -> i64; #[link_name = "llvm.x86.avx512.vcvtsd2usi32"] fn vcvtsd2usi(a: f64x2, rounding: i32) -> u32; - #[link_name = "llvm.x86.avx512.vcvtsd2usi64"] - fn vcvtsd2usi64(a: f64x2, rounding: i32) -> u64; #[link_name = "llvm.x86.avx512.cvtsi2ss32"] fn vcvtsi2ss(a: f32x4, b: i32, rounding: i32) -> f32x4; - #[link_name = "llvm.x86.avx512.cvtsi2ss64"] - fn vcvtsi2ss64(a: f32x4, b: i64, rounding: i32) -> f32x4; #[link_name = "llvm.x86.avx512.cvtsi2sd64"] fn vcvtsi2sd(a: f64x2, b: i64, rounding: i32) -> f64x2; + #[link_name = "llvm.x86.avx512.cvtusi2ss"] fn vcvtusi2ss(a: f32x4, b: u32, rounding: i32) -> f32x4; - #[link_name = "llvm.x86.avx512.cvtusi642ss"] - fn vcvtusi2ss64(a: f32x4, b: u64, rounding: i32) -> f32x4; #[link_name = "llvm.x86.avx512.cvtusi642sd"] fn vcvtusi2sd(a: f64x2, b: u64, rounding: i32) -> f64x2; @@ -25080,23 +39522,12 @@ mod tests { i32::MIN, 100, -100, -32, ); let r = _mm512_abs_epi32(a); + #[rustfmt::skip] let e = _mm512_setr_epi32( - 0, - 1, - 1, - i32::MAX, - i32::MAX.wrapping_add(1), - 100, - 100, - 32, - 0, - 1, - 1, - i32::MAX, - i32::MAX.wrapping_add(1), - 100, - 100, - 32, + 0, 1, 1, i32::MAX, + i32::MAX.wrapping_add(1), 100, 100, 32, + 0, 1, 1, i32::MAX, + i32::MAX.wrapping_add(1), 100, 100, 32, ); assert_eq_m512i(r, e); } @@ -25113,23 +39544,12 @@ mod tests { let r = _mm512_mask_abs_epi32(a, 0, a); assert_eq_m512i(r, a); let r = _mm512_mask_abs_epi32(a, 0b00000000_11111111, a); + #[rustfmt::skip] let e = _mm512_setr_epi32( - 0, - 1, - 1, - i32::MAX, - i32::MAX.wrapping_add(1), - 100, - 100, - 32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, 1, i32::MAX, + i32::MAX.wrapping_add(1), 100, 100, 32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); assert_eq_m512i(r, e); } @@ -25146,27 +39566,72 @@ mod tests { let r = _mm512_maskz_abs_epi32(0, a); assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_abs_epi32(0b00000000_11111111, a); + #[rustfmt::skip] let e = _mm512_setr_epi32( - 0, - 1, - 1, - i32::MAX, - i32::MAX.wrapping_add(1), - 100, - 100, - 32, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 0, 1, 1, i32::MAX, + i32::MAX.wrapping_add(1), 100, 100, 32, + 0, 0, 0, 0, + 0, 0, 0, 0, ); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_abs_epi32() { + #[rustfmt::skip] + let a = _mm256_setr_epi32( + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + ); + let r = _mm256_mask_abs_epi32(a, 0, a); + assert_eq_m256i(r, a); + let r = _mm256_mask_abs_epi32(a, 0b00001111, a); + #[rustfmt::skip] + let e = _mm256_setr_epi32( + 0, 1, 1, i32::MAX, + i32::MAX.wrapping_add(1), 100, -100, -32, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_abs_epi32() { + #[rustfmt::skip] + let a = _mm256_setr_epi32( + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + ); + let r = _mm256_maskz_abs_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_abs_epi32(0b00001111, a); + #[rustfmt::skip] + let e = _mm256_setr_epi32( + 0, 1, 1, i32::MAX, + 0, 0, 0, 0, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_abs_epi32() { + let a = _mm_setr_epi32(i32::MIN, 100, -100, -32); + let r = _mm_mask_abs_epi32(a, 0, a); + assert_eq_m128i(r, a); + let r = _mm_mask_abs_epi32(a, 0b00001111, a); + let e = _mm_setr_epi32(i32::MAX.wrapping_add(1), 100, 100, 32); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_abs_epi32() { + let a = _mm_setr_epi32(i32::MIN, 100, -100, -32); + let r = _mm_maskz_abs_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_abs_epi32(0b00001111, a); + let e = _mm_setr_epi32(i32::MAX.wrapping_add(1), 100, 100, 32); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_abs_ps() { #[rustfmt::skip] @@ -25177,67 +39642,34 @@ mod tests { f32::MIN, 100., -100., -32., ); let r = _mm512_abs_ps(a); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 1., - 1., - f32::MAX, - f32::MAX, - 100., - 100., - 32., - 0., - 1., - 1., - f32::MAX, - f32::MAX, - 100., - 100., - 32., + 0., 1., 1., f32::MAX, + f32::MAX, 100., 100., 32., + 0., 1., 1., f32::MAX, + f32::MAX, 100., 100., 32., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_abs_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let r = _mm512_mask_abs_ps(a, 0, a); assert_eq_m512(r, a); let r = _mm512_mask_abs_ps(a, 0b00000000_11111111, a); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 1., - 1., - f32::MAX, - f32::MAX, - 100., - 100., - 32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., 1., f32::MAX, + f32::MAX, 100., 100., 32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); assert_eq_m512(r, e); } @@ -25261,6 +39693,44 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mov_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(2); + let r = _mm256_mask_mov_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_mov_epi32(src, 0b11111111, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mov_epi32() { + let a = _mm256_set1_epi32(2); + let r = _mm256_maskz_mov_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_mov_epi32(0b11111111, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mov_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(2); + let r = _mm_mask_mov_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_mov_epi32(src, 0b00001111, a); + assert_eq_m128i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mov_epi32() { + let a = _mm_set1_epi32(2); + let r = _mm_maskz_mov_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_mov_epi32(0b00001111, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mov_ps() { let src = _mm512_set1_ps(1.); @@ -25280,45 +39750,61 @@ mod tests { assert_eq_m512(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mov_ps() { + let src = _mm256_set1_ps(1.); + let a = _mm256_set1_ps(2.); + let r = _mm256_mask_mov_ps(src, 0, a); + assert_eq_m256(r, src); + let r = _mm256_mask_mov_ps(src, 0b11111111, a); + assert_eq_m256(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mov_ps() { + let a = _mm256_set1_ps(2.); + let r = _mm256_maskz_mov_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_mov_ps(0b11111111, a); + assert_eq_m256(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mov_ps() { + let src = _mm_set1_ps(1.); + let a = _mm_set1_ps(2.); + let r = _mm_mask_mov_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm_mask_mov_ps(src, 0b00001111, a); + assert_eq_m128(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mov_ps() { + let a = _mm_set1_ps(2.); + let r = _mm_maskz_mov_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_mov_ps(0b00001111, a); + assert_eq_m128(r, a); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_add_epi32() { + #[rustfmt::skip] let a = _mm512_setr_epi32( - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); let b = _mm512_set1_epi32(1); let r = _mm512_add_epi32(a, b); + #[rustfmt::skip] let e = _mm512_setr_epi32( - 1, - 2, - 0, - i32::MIN, - i32::MIN + 1, - 101, - -99, - -31, - 1, - 2, - 0, - i32::MIN, - i32::MIN + 1, - 101, - -99, - -31, + 1, 2, 0, i32::MIN, + i32::MIN + 1, 101, -99, -31, + 1, 2, 0, i32::MIN, + i32::MIN + 1, 101, -99, -31, ); assert_eq_m512i(r, e); } @@ -25336,23 +39822,12 @@ mod tests { let r = _mm512_mask_add_epi32(a, 0, a, b); assert_eq_m512i(r, a); let r = _mm512_mask_add_epi32(a, 0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_epi32( - 1, - 2, - 0, - i32::MIN, - i32::MIN + 1, - 101, - -99, - -31, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 1, 2, 0, i32::MIN, + i32::MIN + 1, 101, -99, -31, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); assert_eq_m512i(r, e); } @@ -25370,445 +39845,401 @@ mod tests { let r = _mm512_maskz_add_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_add_epi32(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_epi32( - 1, - 2, - 0, - i32::MIN, - i32::MIN + 1, - 101, - -99, - -31, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 1, 2, 0, i32::MIN, + i32::MIN + 1, 101, -99, -31, + 0, 0, 0, 0, + 0, 0, 0, 0, ); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_add_epi32() { + let a = _mm256_set_epi32(0, 1, -1, i32::MAX, i32::MIN, 100, -100, -32); + let b = _mm256_set1_epi32(1); + let r = _mm256_mask_add_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_add_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(1, 2, 0, i32::MIN, i32::MIN + 1, 101, -99, -31); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_add_epi32() { + let a = _mm256_setr_epi32(0, 1, -1, i32::MAX, i32::MIN, 100, -100, -32); + let b = _mm256_set1_epi32(1); + let r = _mm256_maskz_add_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_add_epi32(0b11111111, a, b); + let e = _mm256_setr_epi32(1, 2, 0, i32::MIN, i32::MIN + 1, 101, -99, -31); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_add_epi32() { + let a = _mm_set_epi32(1, -1, i32::MAX, i32::MIN); + let b = _mm_set1_epi32(1); + let r = _mm_mask_add_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_add_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(2, 0, i32::MIN, i32::MIN + 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_add_epi32() { + let a = _mm_setr_epi32(1, -1, i32::MAX, i32::MIN); + let b = _mm_set1_epi32(1); + let r = _mm_maskz_add_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_add_epi32(0b00001111, a, b); + let e = _mm_setr_epi32(2, 0, i32::MIN, i32::MIN + 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_add_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(1.); let r = _mm512_add_ps(a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 1., - 2., - 0., - f32::MAX, - f32::MIN + 1., - 101., - -99., - -31., - 1., - 2., - 0., - f32::MAX, - f32::MIN + 1., - 101., - -99., - -31., + 1., 2., 0., f32::MAX, + f32::MIN + 1., 101., -99., -31., + 1., 2., 0., f32::MAX, + f32::MIN + 1., 101., -99., -31., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_add_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(1.); let r = _mm512_mask_add_ps(a, 0, a, b); assert_eq_m512(r, a); let r = _mm512_mask_add_ps(a, 0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 1., - 2., - 0., - f32::MAX, - f32::MIN + 1., - 101., - -99., - -31., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 1., 2., 0., f32::MAX, + f32::MIN + 1., 101., -99., -31., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_add_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(1.); let r = _mm512_maskz_add_ps(0, a, b); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_add_ps(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 1., - 2., - 0., - f32::MAX, - f32::MIN + 1., - 101., - -99., - -31., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + 1., 2., 0., f32::MAX, + f32::MIN + 1., 101., -99., -31., + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_add_ps() { + let a = _mm256_set_ps(0., 1., -1., f32::MAX, f32::MIN, 100., -100., -32.); + let b = _mm256_set1_ps(1.); + let r = _mm256_mask_add_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_add_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(1., 2., 0., f32::MAX, f32::MIN + 1., 101., -99., -31.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_add_ps() { + let a = _mm256_set_ps(0., 1., -1., f32::MAX, f32::MIN, 100., -100., -32.); + let b = _mm256_set1_ps(1.); + let r = _mm256_maskz_add_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_add_ps(0b11111111, a, b); + let e = _mm256_set_ps(1., 2., 0., f32::MAX, f32::MIN + 1., 101., -99., -31.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_add_ps() { + let a = _mm_set_ps(1., -1., f32::MAX, f32::MIN); + let b = _mm_set1_ps(1.); + let r = _mm_mask_add_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_add_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(2., 0., f32::MAX, f32::MIN + 1.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_add_ps() { + let a = _mm_set_ps(1., -1., f32::MAX, f32::MIN); + let b = _mm_set1_ps(1.); + let r = _mm_maskz_add_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_add_ps(0b00001111, a, b); + let e = _mm_set_ps(2., 0., f32::MAX, f32::MIN + 1.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sub_epi32() { + #[rustfmt::skip] let a = _mm512_setr_epi32( - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); let b = _mm512_set1_epi32(1); let r = _mm512_sub_epi32(a, b); + #[rustfmt::skip] let e = _mm512_setr_epi32( - -1, - 0, - -2, - i32::MAX - 1, - i32::MAX, - 99, - -101, - -33, - -1, - 0, - -2, - i32::MAX - 1, - i32::MAX, - 99, - -101, - -33, + -1, 0, -2, i32::MAX - 1, + i32::MAX, 99, -101, -33, + -1, 0, -2, i32::MAX - 1, + i32::MAX, 99, -101, -33, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_sub_epi32() { + #[rustfmt::skip] let a = _mm512_setr_epi32( - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); let b = _mm512_set1_epi32(1); let r = _mm512_mask_sub_epi32(a, 0, a, b); assert_eq_m512i(r, a); let r = _mm512_mask_sub_epi32(a, 0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_epi32( - -1, - 0, - -2, - i32::MAX - 1, - i32::MAX, - 99, - -101, - -33, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + -1, 0, -2, i32::MAX - 1, + i32::MAX, 99, -101, -33, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_sub_epi32() { + #[rustfmt::skip] let a = _mm512_setr_epi32( - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); let b = _mm512_set1_epi32(1); let r = _mm512_maskz_sub_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_sub_epi32(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_epi32( - -1, - 0, - -2, - i32::MAX - 1, - i32::MAX, - 99, - -101, - -33, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + -1, 0, -2, i32::MAX - 1, + i32::MAX, 99, -101, -33, + 0, 0, 0, 0, + 0, 0, 0, 0, ); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sub_epi32() { + let a = _mm256_set_epi32(0, 1, -1, i32::MAX, i32::MIN, 100, -100, -32); + let b = _mm256_set1_epi32(1); + let r = _mm256_mask_sub_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_sub_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(-1, 0, -2, i32::MAX - 1, i32::MAX, 99, -101, -33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sub_epi32() { + let a = _mm256_set_epi32(0, 1, -1, i32::MAX, i32::MIN, 100, -100, -32); + let b = _mm256_set1_epi32(1); + let r = _mm256_maskz_sub_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sub_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(-1, 0, -2, i32::MAX - 1, i32::MAX, 99, -101, -33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sub_epi32() { + let a = _mm_set_epi32(1, -1, i32::MAX, i32::MIN); + let b = _mm_set1_epi32(1); + let r = _mm_mask_sub_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_sub_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(0, -2, i32::MAX - 1, i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sub_epi32() { + let a = _mm_set_epi32(1, -1, i32::MAX, i32::MIN); + let b = _mm_set1_epi32(1); + let r = _mm_maskz_sub_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sub_epi32(0b00001111, a, b); + let e = _mm_set_epi32(0, -2, i32::MAX - 1, i32::MAX); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sub_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(1.); let r = _mm512_sub_ps(a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - -1., - 0., - -2., - f32::MAX - 1., - f32::MIN, - 99., - -101., - -33., - -1., - 0., - -2., - f32::MAX - 1., - f32::MIN, - 99., - -101., - -33., + -1., 0., -2., f32::MAX - 1., + f32::MIN, 99., -101., -33., + -1., 0., -2., f32::MAX - 1., + f32::MIN, 99., -101., -33., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_sub_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(1.); let r = _mm512_mask_sub_ps(a, 0, a, b); assert_eq_m512(r, a); let r = _mm512_mask_sub_ps(a, 0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - -1., - 0., - -2., - f32::MAX - 1., - f32::MIN, - 99., - -101., - -33., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + -1., 0., -2., f32::MAX - 1., + f32::MIN, 99., -101., -33., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_sub_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(1.); let r = _mm512_maskz_sub_ps(0, a, b); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_sub_ps(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - -1., - 0., - -2., - f32::MAX - 1., - f32::MIN, - 99., - -101., - -33., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + -1., 0., -2., f32::MAX - 1., + f32::MIN, 99., -101., -33., + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sub_ps() { + let a = _mm256_set_ps(0., 1., -1., f32::MAX, f32::MIN, 100., -100., -32.); + let b = _mm256_set1_ps(1.); + let r = _mm256_mask_sub_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_sub_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(-1., 0., -2., f32::MAX - 1., f32::MIN, 99., -101., -33.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sub_ps() { + let a = _mm256_set_ps(0., 1., -1., f32::MAX, f32::MIN, 100., -100., -32.); + let b = _mm256_set1_ps(1.); + let r = _mm256_maskz_sub_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_sub_ps(0b11111111, a, b); + let e = _mm256_set_ps(-1., 0., -2., f32::MAX - 1., f32::MIN, 99., -101., -33.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sub_ps() { + let a = _mm_set_ps(1., -1., f32::MAX, f32::MIN); + let b = _mm_set1_ps(1.); + let r = _mm_mask_sub_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_sub_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(0., -2., f32::MAX - 1., f32::MIN); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sub_ps() { + let a = _mm_set_ps(1., -1., f32::MAX, f32::MIN); + let b = _mm_set1_ps(1.); + let r = _mm_maskz_sub_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_sub_ps(0b00001111, a, b); + let e = _mm_set_ps(0., -2., f32::MAX - 1., f32::MIN); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mullo_epi32() { + #[rustfmt::skip] let a = _mm512_setr_epi32( - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); let b = _mm512_set1_epi32(2); let r = _mm512_mullo_epi32(a, b); @@ -25820,68 +40251,35 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mullo_epi32() { + #[rustfmt::skip] let a = _mm512_setr_epi32( - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); let b = _mm512_set1_epi32(2); let r = _mm512_mask_mullo_epi32(a, 0, a, b); assert_eq_m512i(r, a); let r = _mm512_mask_mullo_epi32(a, 0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_epi32( - 0, - 2, - -2, - -2, - 0, - 200, - -200, - -64, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 2, -2, -2, + 0, 200, -200, -64, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_mullo_epi32() { + #[rustfmt::skip] let a = _mm512_setr_epi32( - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, - 0, - 1, - -1, - i32::MAX, - i32::MIN, - 100, - -100, - -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, + 0, 1, -1, i32::MAX, + i32::MIN, 100, -100, -32, ); let b = _mm512_set1_epi32(2); let r = _mm512_maskz_mullo_epi32(0, a, b); @@ -25891,44 +40289,67 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mullo_epi32() { + let a = _mm256_set_epi32(0, 1, -1, i32::MAX, i32::MIN, 100, -100, -32); + let b = _mm256_set1_epi32(2); + let r = _mm256_mask_mullo_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_mullo_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(0, 2, -2, -2, 0, 200, -200, -64); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mullo_epi32() { + let a = _mm256_set_epi32(0, 1, -1, i32::MAX, i32::MIN, 100, -100, -32); + let b = _mm256_set1_epi32(2); + let r = _mm256_maskz_mullo_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_mullo_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(0, 2, -2, -2, 0, 200, -200, -64); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mullo_epi32() { + let a = _mm_set_epi32(1, -1, i32::MAX, i32::MIN); + let b = _mm_set1_epi32(2); + let r = _mm_mask_mullo_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_mullo_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(2, -2, -2, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mullo_epi32() { + let a = _mm_set_epi32(1, -1, i32::MAX, i32::MIN); + let b = _mm_set1_epi32(2); + let r = _mm_maskz_mullo_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_mullo_epi32(0b00001111, a, b); + let e = _mm_set_epi32(2, -2, -2, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mul_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(2.); let r = _mm512_mul_ps(a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 2., - -2., - f32::INFINITY, - f32::NEG_INFINITY, - 200., - -200., - -64., - 0., - 2., - -2., - f32::INFINITY, - f32::NEG_INFINITY, - 200., - -200., + 0., 2., -2., f32::INFINITY, + f32::NEG_INFINITY, 200., -200., -64., + 0., 2., -2., f32::INFINITY, + f32::NEG_INFINITY, 200., -200., -64., ); assert_eq_m512(r, e); @@ -25936,94 +40357,102 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mul_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(2.); let r = _mm512_mask_mul_ps(a, 0, a, b); assert_eq_m512(r, a); let r = _mm512_mask_mul_ps(a, 0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 2., - -2., - f32::INFINITY, - f32::NEG_INFINITY, - 200., - -200., - -64., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 2., -2., f32::INFINITY, + f32::NEG_INFINITY, 200., -200., -64., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_mul_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., - 0., - 1., - -1., - f32::MAX, - f32::MIN, - 100., - -100., - -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., + 0., 1., -1., f32::MAX, + f32::MIN, 100., -100., -32., ); let b = _mm512_set1_ps(2.); let r = _mm512_maskz_mul_ps(0, a, b); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_mul_ps(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 2., - -2., - f32::INFINITY, - f32::NEG_INFINITY, - 200., - -200., - -64., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + 0., 2., -2., f32::INFINITY, + f32::NEG_INFINITY, 200., -200., -64., + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mul_ps() { + let a = _mm256_set_ps(0., 1., -1., f32::MAX, f32::MIN, 100., -100., -32.); + let b = _mm256_set1_ps(2.); + let r = _mm256_mask_mul_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_mul_ps(a, 0b11111111, a, b); + #[rustfmt::skip] + let e = _mm256_set_ps( + 0., 2., -2., f32::INFINITY, + f32::NEG_INFINITY, 200., -200., -64., + ); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mul_ps() { + let a = _mm256_set_ps(0., 1., -1., f32::MAX, f32::MIN, 100., -100., -32.); + let b = _mm256_set1_ps(2.); + let r = _mm256_maskz_mul_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_mul_ps(0b11111111, a, b); + #[rustfmt::skip] + let e = _mm256_set_ps( + 0., 2., -2., f32::INFINITY, + f32::NEG_INFINITY, 200., -200., -64., + ); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mul_ps() { + let a = _mm_set_ps(1., -1., f32::MAX, f32::MIN); + let b = _mm_set1_ps(2.); + let r = _mm_mask_mul_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_mul_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(2., -2., f32::INFINITY, f32::NEG_INFINITY); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mul_ps() { + let a = _mm_set_ps(1., -1., f32::MAX, f32::MIN); + let b = _mm_set1_ps(2.); + let r = _mm_maskz_mul_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_mul_ps(0b00001111, a, b); + let e = _mm_set_ps(2., -2., f32::INFINITY, f32::NEG_INFINITY); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_div_ps() { let a = _mm512_setr_ps( @@ -26033,23 +40462,12 @@ mod tests { 2., 2., 2., 2., 2., 0., 2., 2., 2., 2., 2., 2., 0., 2., 2., 2., ); let r = _mm512_div_ps(a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0.5, - -0.5, - -1., - 50., - f32::INFINITY, - -50., - -16., - 0., - 0.5, - -0.5, - 500., - f32::NEG_INFINITY, - 50., - -50., - -16., + 0., 0.5, -0.5, -1., + 50., f32::INFINITY, -50., -16., + 0., 0.5, -0.5, 500., + f32::NEG_INFINITY, 50., -50., -16., ); assert_eq_m512(r, e); // 0/0 = NAN } @@ -26065,23 +40483,12 @@ mod tests { let r = _mm512_mask_div_ps(a, 0, a, b); assert_eq_m512(r, a); let r = _mm512_mask_div_ps(a, 0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0.5, - -0.5, - -1., - 50., - f32::INFINITY, - -50., - -16., - 0., - 1., - -1., - 1000., - -131., - 100., - -100., - -32., + 0., 0.5, -0.5, -1., + 50., f32::INFINITY, -50., -16., + 0., 1., -1., 1000., + -131., 100., -100., -32., ); assert_eq_m512(r, e); } @@ -26097,27 +40504,60 @@ mod tests { let r = _mm512_maskz_div_ps(0, a, b); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_div_ps(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0.5, - -0.5, - -1., - 50., - f32::INFINITY, - -50., - -16., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + 0., 0.5, -0.5, -1., + 50., f32::INFINITY, -50., -16., + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_div_ps() { + let a = _mm256_set_ps(0., 1., -1., -2., 100., 100., -100., -32.); + let b = _mm256_set_ps(2., 2., 2., 2., 2., 0., 2., 2.); + let r = _mm256_mask_div_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_div_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(0., 0.5, -0.5, -1., 50., f32::INFINITY, -50., -16.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_div_ps() { + let a = _mm256_set_ps(0., 1., -1., -2., 100., 100., -100., -32.); + let b = _mm256_set_ps(2., 2., 2., 2., 2., 0., 2., 2.); + let r = _mm256_maskz_div_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_div_ps(0b11111111, a, b); + let e = _mm256_set_ps(0., 0.5, -0.5, -1., 50., f32::INFINITY, -50., -16.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_div_ps() { + let a = _mm_set_ps(100., 100., -100., -32.); + let b = _mm_set_ps(2., 0., 2., 2.); + let r = _mm_mask_div_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_div_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(50., f32::INFINITY, -50., -16.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_div_ps() { + let a = _mm_set_ps(100., 100., -100., -32.); + let b = _mm_set_ps(2., 0., 2., 2.); + let r = _mm_maskz_div_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_div_ps(0b00001111, a, b); + let e = _mm_set_ps(50., f32::INFINITY, -50., -16.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_max_epi32() { let a = _mm512_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -26149,6 +40589,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_max_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_mask_max_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_max_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(7, 6, 5, 4, 4, 5, 6, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_max_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_maskz_max_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_max_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(7, 6, 5, 4, 4, 5, 6, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_max_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_mask_max_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_max_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(3, 2, 2, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_max_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_maskz_max_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_max_epi32(0b00001111, a, b); + let e = _mm_set_epi32(3, 2, 2, 3); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_max_ps() { let a = _mm512_setr_ps( @@ -26198,6 +40682,50 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_max_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let b = _mm256_set_ps(7., 6., 5., 4., 3., 2., 1., 0.); + let r = _mm256_mask_max_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_max_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(7., 6., 5., 4., 4., 5., 6., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_max_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let b = _mm256_set_ps(7., 6., 5., 4., 3., 2., 1., 0.); + let r = _mm256_maskz_max_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_max_ps(0b11111111, a, b); + let e = _mm256_set_ps(7., 6., 5., 4., 4., 5., 6., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_max_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let b = _mm_set_ps(3., 2., 1., 0.); + let r = _mm_mask_max_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_max_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(3., 2., 2., 3.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_max_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let b = _mm_set_ps(3., 2., 1., 0.); + let r = _mm_maskz_max_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_mask_max_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(3., 2., 2., 3.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_max_epu32() { let a = _mm512_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -26229,6 +40757,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_max_epu32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_mask_max_epu32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_max_epu32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(7, 6, 5, 4, 4, 5, 6, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_max_epu32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_maskz_max_epu32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_max_epu32(0b11111111, a, b); + let e = _mm256_set_epi32(7, 6, 5, 4, 4, 5, 6, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_max_epu32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_mask_max_epu32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_max_epu32(a, 0b00001111, a, b); + let e = _mm_set_epi32(3, 2, 2, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_max_epu32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_maskz_max_epu32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_max_epu32(0b00001111, a, b); + let e = _mm_set_epi32(3, 2, 2, 3); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_min_epi32() { let a = _mm512_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -26260,6 +40832,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_min_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_mask_min_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_min_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(0, 1, 2, 3, 3, 2, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_min_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_maskz_min_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_min_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(0, 1, 2, 3, 3, 2, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_min_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_mask_min_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_min_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(0, 1, 1, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_min_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_maskz_min_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_min_epi32(0b00001111, a, b); + let e = _mm_set_epi32(0, 1, 1, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_min_ps() { let a = _mm512_setr_ps( @@ -26309,6 +40925,50 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_min_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let b = _mm256_set_ps(7., 6., 5., 4., 3., 2., 1., 0.); + let r = _mm256_mask_min_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_min_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(0., 1., 2., 3., 3., 2., 1., 0.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_min_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let b = _mm256_set_ps(7., 6., 5., 4., 3., 2., 1., 0.); + let r = _mm256_maskz_min_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_min_ps(0b11111111, a, b); + let e = _mm256_set_ps(0., 1., 2., 3., 3., 2., 1., 0.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_min_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let b = _mm_set_ps(3., 2., 1., 0.); + let r = _mm_mask_min_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_min_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(0., 1., 1., 0.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_min_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let b = _mm_set_ps(3., 2., 1., 0.); + let r = _mm_maskz_min_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_min_ps(0b00001111, a, b); + let e = _mm_set_ps(0., 1., 1., 0.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_min_epu32() { let a = _mm512_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -26340,6 +41000,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_min_epu32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_mask_min_epu32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_min_epu32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(0, 1, 2, 3, 3, 2, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_min_epu32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let b = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); + let r = _mm256_maskz_min_epu32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_min_epu32(0b11111111, a, b); + let e = _mm256_set_epi32(0, 1, 2, 3, 3, 2, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_min_epu32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_mask_min_epu32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_min_epu32(a, 0b00001111, a, b); + let e = _mm_set_epi32(0, 1, 1, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_min_epu32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let b = _mm_set_epi32(3, 2, 1, 0); + let r = _mm_maskz_min_epu32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_min_epu32(0b00001111, a, b); + let e = _mm_set_epi32(0, 1, 1, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sqrt_ps() { let a = _mm512_setr_ps( @@ -26380,17 +41084,53 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sqrt_ps() { + let a = _mm256_set_ps(0., 1., 4., 9., 16., 25., 36., 49.); + let r = _mm256_mask_sqrt_ps(a, 0, a); + assert_eq_m256(r, a); + let r = _mm256_mask_sqrt_ps(a, 0b11111111, a); + let e = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sqrt_ps() { + let a = _mm256_set_ps(0., 1., 4., 9., 16., 25., 36., 49.); + let r = _mm256_maskz_sqrt_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_sqrt_ps(0b11111111, a); + let e = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sqrt_ps() { + let a = _mm_set_ps(0., 1., 4., 9.); + let r = _mm_mask_sqrt_ps(a, 0, a); + assert_eq_m128(r, a); + let r = _mm_mask_sqrt_ps(a, 0b00001111, a); + let e = _mm_set_ps(0., 1., 2., 3.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sqrt_ps() { + let a = _mm_set_ps(0., 1., 4., 9.); + let r = _mm_maskz_sqrt_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_sqrt_ps(0b00001111, a); + let e = _mm_set_ps(0., 1., 2., 3.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_fmadd_ps(a, b, c); let e = _mm512_setr_ps( 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., @@ -26400,15 +41140,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_mask_fmadd_ps(a, 0, b, c); assert_eq_m512(r, a); let r = _mm512_mask_fmadd_ps(a, 0b00000000_11111111, b, c); @@ -26420,15 +41156,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_maskz_fmadd_ps(0, a, b, c); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_fmadd_ps(0b00000000_11111111, a, b, c); @@ -26440,24 +41172,92 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 2., 2., - ); + let c = _mm512_set1_ps(2.); let r = _mm512_mask3_fmadd_ps(a, b, c, 0); assert_eq_m512(r, c); let r = _mm512_mask3_fmadd_ps(a, b, c, 0b00000000_11111111); let e = _mm512_setr_ps( - 1., 2., 3., 4., 5., 6., 7., 8., 2., 2., 2., 2., 2., 2., 2., 2., + 2., 3., 4., 5., 6., 7., 8., 9., 2., 2., 2., 2., 2., 2., 2., 2., ); assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask_fmadd_ps(a, 0, b, c); + assert_eq_m256(r, a); + let r = _mm256_mask_fmadd_ps(a, 0b11111111, b, c); + let e = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_maskz_fmadd_ps(0, a, b, c); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_fmadd_ps(0b11111111, a, b, c); + let e = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask3_fmadd_ps(a, b, c, 0); + assert_eq_m256(r, c); + let r = _mm256_mask3_fmadd_ps(a, b, c, 0b11111111); + let e = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask_fmadd_ps(a, 0, b, c); + assert_eq_m128(r, a); + let r = _mm_mask_fmadd_ps(a, 0b00001111, b, c); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_maskz_fmadd_ps(0, a, b, c); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_fmadd_ps(0b00001111, a, b, c); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask3_fmadd_ps(a, b, c, 0); + assert_eq_m128(r, c); + let r = _mm_mask3_fmadd_ps(a, b, c, 0b00001111); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmsub_ps() { let a = _mm512_setr_ps( @@ -26478,15 +41278,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fmsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_mask_fmsub_ps(a, 0, b, c); assert_eq_m512(r, a); let r = _mm512_mask_fmsub_ps(a, 0b00000000_11111111, b, c); @@ -26498,15 +41294,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fmsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_maskz_fmsub_ps(0, a, b, c); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_fmsub_ps(0b00000000_11111111, a, b, c); @@ -26518,9 +41310,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fmsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); @@ -26536,17 +41326,85 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask_fmsub_ps(a, 0, b, c); + assert_eq_m256(r, a); + let r = _mm256_mask_fmsub_ps(a, 0b11111111, b, c); + let e = _mm256_set_ps(-1., 0., 1., 2., 3., 4., 5., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_maskz_fmsub_ps(0, a, b, c); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_fmsub_ps(0b11111111, a, b, c); + let e = _mm256_set_ps(-1., 0., 1., 2., 3., 4., 5., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask3_fmsub_ps(a, b, c, 0); + assert_eq_m256(r, c); + let r = _mm256_mask3_fmsub_ps(a, b, c, 0b11111111); + let e = _mm256_set_ps(-1., 0., 1., 2., 3., 4., 5., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask_fmsub_ps(a, 0, b, c); + assert_eq_m128(r, a); + let r = _mm_mask_fmsub_ps(a, 0b00001111, b, c); + let e = _mm_set_ps(-1., 0., 1., 2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_maskz_fmsub_ps(0, a, b, c); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_fmsub_ps(0b00001111, a, b, c); + let e = _mm_set_ps(-1., 0., 1., 2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask3_fmsub_ps(a, b, c, 0); + assert_eq_m128(r, c); + let r = _mm_mask3_fmsub_ps(a, b, c, 0b00001111); + let e = _mm_set_ps(-1., 0., 1., 2.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmaddsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_fmaddsub_ps(a, b, c); let e = _mm512_setr_ps( -1., 2., 1., 4., 3., 6., 5., 8., 7., 10., 9., 12., 11., 14., 13., 16., @@ -26556,15 +41414,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fmaddsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_mask_fmaddsub_ps(a, 0, b, c); assert_eq_m512(r, a); let r = _mm512_mask_fmaddsub_ps(a, 0b00000000_11111111, b, c); @@ -26576,15 +41430,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fmaddsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_maskz_fmaddsub_ps(0, a, b, c); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_fmaddsub_ps(0b00000000_11111111, a, b, c); @@ -26596,9 +41446,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fmaddsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); @@ -26614,6 +41462,78 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmaddsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask_fmaddsub_ps(a, 0, b, c); + assert_eq_m256(r, a); + let r = _mm256_mask_fmaddsub_ps(a, 0b11111111, b, c); + let e = _mm256_set_ps(1., 0., 3., 2., 5., 4., 7., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmaddsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_maskz_fmaddsub_ps(0, a, b, c); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_fmaddsub_ps(0b11111111, a, b, c); + let e = _mm256_set_ps(1., 0., 3., 2., 5., 4., 7., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmaddsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask3_fmaddsub_ps(a, b, c, 0); + assert_eq_m256(r, c); + let r = _mm256_mask3_fmaddsub_ps(a, b, c, 0b11111111); + let e = _mm256_set_ps(1., 0., 3., 2., 5., 4., 7., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmaddsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask_fmaddsub_ps(a, 0, b, c); + assert_eq_m128(r, a); + let r = _mm_mask_fmaddsub_ps(a, 0b00001111, b, c); + let e = _mm_set_ps(1., 0., 3., 2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmaddsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_maskz_fmaddsub_ps(0, a, b, c); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_fmaddsub_ps(0b00001111, a, b, c); + let e = _mm_set_ps(1., 0., 3., 2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmaddsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask3_fmaddsub_ps(a, b, c, 0); + assert_eq_m128(r, c); + let r = _mm_mask3_fmaddsub_ps(a, b, c, 0b00001111); + let e = _mm_set_ps(1., 0., 3., 2.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmsubadd_ps() { let a = _mm512_setr_ps( @@ -26634,15 +41554,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fmsubadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_mask_fmsubadd_ps(a, 0, b, c); assert_eq_m512(r, a); let r = _mm512_mask_fmsubadd_ps(a, 0b00000000_11111111, b, c); @@ -26654,15 +41570,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fmsubadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_maskz_fmsubadd_ps(0, a, b, c); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_fmsubadd_ps(0b00000000_11111111, a, b, c); @@ -26674,9 +41586,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fmsubadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); @@ -26692,17 +41602,85 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmsubadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask_fmsubadd_ps(a, 0, b, c); + assert_eq_m256(r, a); + let r = _mm256_mask_fmsubadd_ps(a, 0b11111111, b, c); + let e = _mm256_set_ps(-1., 2., 1., 4., 3., 6., 5., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmsubadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_maskz_fmsubadd_ps(0, a, b, c); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_fmsubadd_ps(0b11111111, a, b, c); + let e = _mm256_set_ps(-1., 2., 1., 4., 3., 6., 5., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmsubadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask3_fmsubadd_ps(a, b, c, 0); + assert_eq_m256(r, c); + let r = _mm256_mask3_fmsubadd_ps(a, b, c, 0b11111111); + let e = _mm256_set_ps(-1., 2., 1., 4., 3., 6., 5., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmsubadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask_fmsubadd_ps(a, 0, b, c); + assert_eq_m128(r, a); + let r = _mm_mask_fmsubadd_ps(a, 0b00001111, b, c); + let e = _mm_set_ps(-1., 2., 1., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmsubadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_maskz_fmsubadd_ps(0, a, b, c); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_fmsubadd_ps(0b00001111, a, b, c); + let e = _mm_set_ps(-1., 2., 1., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmsubadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask3_fmsubadd_ps(a, b, c, 0); + assert_eq_m128(r, c); + let r = _mm_mask3_fmsubadd_ps(a, b, c, 0b00001111); + let e = _mm_set_ps(-1., 2., 1., 4.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fnmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_fnmadd_ps(a, b, c); let e = _mm512_setr_ps( 1., 0., -1., -2., -3., -4., -5., -6., -7., -8., -9., -10., -11., -12., -13., -14., @@ -26712,15 +41690,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fnmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_mask_fnmadd_ps(a, 0, b, c); assert_eq_m512(r, a); let r = _mm512_mask_fnmadd_ps(a, 0b00000000_11111111, b, c); @@ -26732,15 +41706,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fnmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_maskz_fnmadd_ps(0, a, b, c); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_fnmadd_ps(0b00000000_11111111, a, b, c); @@ -26752,9 +41722,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fnmadd_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); @@ -26770,17 +41738,85 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fnmadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask_fnmadd_ps(a, 0, b, c); + assert_eq_m256(r, a); + let r = _mm256_mask_fnmadd_ps(a, 0b11111111, b, c); + let e = _mm256_set_ps(1., 0., -1., -2., -3., -4., -5., -6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fnmadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_maskz_fnmadd_ps(0, a, b, c); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_fnmadd_ps(0b11111111, a, b, c); + let e = _mm256_set_ps(1., 0., -1., -2., -3., -4., -5., -6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fnmadd_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask3_fnmadd_ps(a, b, c, 0); + assert_eq_m256(r, c); + let r = _mm256_mask3_fnmadd_ps(a, b, c, 0b11111111); + let e = _mm256_set_ps(1., 0., -1., -2., -3., -4., -5., -6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fnmadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask_fnmadd_ps(a, 0, b, c); + assert_eq_m128(r, a); + let r = _mm_mask_fnmadd_ps(a, 0b00001111, b, c); + let e = _mm_set_ps(1., 0., -1., -2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fnmadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_maskz_fnmadd_ps(0, a, b, c); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_fnmadd_ps(0b00001111, a, b, c); + let e = _mm_set_ps(1., 0., -1., -2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fnmadd_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask3_fnmadd_ps(a, b, c, 0); + assert_eq_m128(r, c); + let r = _mm_mask3_fnmadd_ps(a, b, c, 0b00001111); + let e = _mm_set_ps(1., 0., -1., -2.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fnmsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_fnmsub_ps(a, b, c); let e = _mm512_setr_ps( -1., -2., -3., -4., -5., -6., -7., -8., -9., -10., -11., -12., -13., -14., -15., -16., @@ -26790,15 +41826,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fnmsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_mask_fnmsub_ps(a, 0, b, c); assert_eq_m512(r, a); let r = _mm512_mask_fnmsub_ps(a, 0b00000000_11111111, b, c); @@ -26810,15 +41842,11 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fnmsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let c = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let c = _mm512_set1_ps(1.); let r = _mm512_maskz_fnmsub_ps(0, a, b, c); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_fnmsub_ps(0b00000000_11111111, a, b, c); @@ -26830,9 +41858,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fnmsub_ps() { - let a = _mm512_setr_ps( - 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., - ); + let a = _mm512_set1_ps(1.); let b = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); @@ -26848,6 +41874,78 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fnmsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask_fnmsub_ps(a, 0, b, c); + assert_eq_m256(r, a); + let r = _mm256_mask_fnmsub_ps(a, 0b11111111, b, c); + let e = _mm256_set_ps(-1., -2., -3., -4., -5., -6., -7., -8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fnmsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_maskz_fnmsub_ps(0, a, b, c); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_fnmsub_ps(0b11111111, a, b, c); + let e = _mm256_set_ps(-1., -2., -3., -4., -5., -6., -7., -8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fnmsub_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm256_set1_ps(1.); + let r = _mm256_mask3_fnmsub_ps(a, b, c, 0); + assert_eq_m256(r, c); + let r = _mm256_mask3_fnmsub_ps(a, b, c, 0b11111111); + let e = _mm256_set_ps(-1., -2., -3., -4., -5., -6., -7., -8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fnmsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask_fnmsub_ps(a, 0, b, c); + assert_eq_m128(r, a); + let r = _mm_mask_fnmsub_ps(a, 0b00001111, b, c); + let e = _mm_set_ps(-1., -2., -3., -4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fnmsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_maskz_fnmsub_ps(0, a, b, c); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_fnmsub_ps(0b00001111, a, b, c); + let e = _mm_set_ps(-1., -2., -3., -4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fnmsub_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set_ps(0., 1., 2., 3.); + let c = _mm_set1_ps(1.); + let r = _mm_mask3_fnmsub_ps(a, b, c, 0); + assert_eq_m128(r, c); + let r = _mm_mask3_fnmsub_ps(a, b, c, 0b00001111); + let e = _mm_set_ps(-1., -2., -3., -4.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rcp14_ps() { let a = _mm512_set1_ps(3.); @@ -26882,6 +41980,62 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rcp14_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_rcp14_ps(a); + let e = _mm256_set1_ps(0.33333206); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rcp14_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_mask_rcp14_ps(a, 0, a); + assert_eq_m256(r, a); + let r = _mm256_mask_rcp14_ps(a, 0b11111111, a); + let e = _mm256_set1_ps(0.33333206); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rcp14_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_maskz_rcp14_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_rcp14_ps(0b11111111, a); + let e = _mm256_set1_ps(0.33333206); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rcp14_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_rcp14_ps(a); + let e = _mm_set1_ps(0.33333206); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rcp14_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_mask_rcp14_ps(a, 0, a); + assert_eq_m128(r, a); + let r = _mm_mask_rcp14_ps(a, 0b00001111, a); + let e = _mm_set1_ps(0.33333206); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rcp14_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_maskz_rcp14_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_rcp14_ps(0b00001111, a); + let e = _mm_set1_ps(0.33333206); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rsqrt14_ps() { let a = _mm512_set1_ps(3.); @@ -26916,6 +42070,46 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rsqrt14_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_mask_rsqrt14_ps(a, 0, a); + assert_eq_m256(r, a); + let r = _mm256_mask_rsqrt14_ps(a, 0b11111111, a); + let e = _mm256_set1_ps(0.5773392); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rsqrt14_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_maskz_rsqrt14_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_rsqrt14_ps(0b11111111, a); + let e = _mm256_set1_ps(0.5773392); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rsqrt14_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_mask_rsqrt14_ps(a, 0, a); + assert_eq_m128(r, a); + let r = _mm_mask_rsqrt14_ps(a, 0b00001111, a); + let e = _mm_set1_ps(0.5773392); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rsqrt14_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_maskz_rsqrt14_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_rsqrt14_ps(0b00001111, a); + let e = _mm_set1_ps(0.5773392); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_getexp_ps() { let a = _mm512_set1_ps(3.); @@ -26948,6 +42142,62 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_getexp_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_getexp_ps(a); + let e = _mm256_set1_ps(1.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_getexp_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_mask_getexp_ps(a, 0, a); + assert_eq_m256(r, a); + let r = _mm256_mask_getexp_ps(a, 0b11111111, a); + let e = _mm256_set1_ps(1.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_getexp_ps() { + let a = _mm256_set1_ps(3.); + let r = _mm256_maskz_getexp_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_getexp_ps(0b11111111, a); + let e = _mm256_set1_ps(1.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_getexp_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_getexp_ps(a); + let e = _mm_set1_ps(1.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_getexp_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_mask_getexp_ps(a, 0, a); + assert_eq_m128(r, a); + let r = _mm_mask_getexp_ps(a, 0b00001111, a); + let e = _mm_set1_ps(1.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_getexp_ps() { + let a = _mm_set1_ps(3.); + let r = _mm_maskz_getexp_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_getexp_ps(0b00001111, a); + let e = _mm_set1_ps(1.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_roundscale_ps() { let a = _mm512_set1_ps(1.1); @@ -26977,6 +42227,64 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_roundscale_ps() { + let a = _mm256_set1_ps(1.1); + let r = _mm256_roundscale_ps(a, 0); + let e = _mm256_set1_ps(1.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_roundscale_ps() { + let a = _mm256_set1_ps(1.1); + let r = _mm256_mask_roundscale_ps(a, 0, a, 0); + let e = _mm256_set1_ps(1.1); + assert_eq_m256(r, e); + let r = _mm256_mask_roundscale_ps(a, 0b11111111, a, 0); + let e = _mm256_set1_ps(1.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_roundscale_ps() { + let a = _mm256_set1_ps(1.1); + let r = _mm256_maskz_roundscale_ps(0, a, 0); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_roundscale_ps(0b11111111, a, 0); + let e = _mm256_set1_ps(1.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_roundscale_ps() { + let a = _mm_set1_ps(1.1); + let r = _mm_roundscale_ps(a, 0); + let e = _mm_set1_ps(1.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_roundscale_ps() { + let a = _mm_set1_ps(1.1); + let r = _mm_mask_roundscale_ps(a, 0, a, 0); + let e = _mm_set1_ps(1.1); + assert_eq_m128(r, e); + let r = _mm_mask_roundscale_ps(a, 0b00001111, a, 0); + let e = _mm_set1_ps(1.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_roundscale_ps() { + let a = _mm_set1_ps(1.1); + let r = _mm_maskz_roundscale_ps(0, a, 0); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_roundscale_ps(0b00001111, a, 0); + let e = _mm_set1_ps(1.0); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_scalef_ps() { let a = _mm512_set1_ps(1.); @@ -27012,6 +42320,68 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_scalef_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set1_ps(3.); + let r = _mm256_scalef_ps(a, b); + let e = _mm256_set1_ps(8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_scalef_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set1_ps(3.); + let r = _mm256_mask_scalef_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_scalef_ps(a, 0b11111111, a, b); + let e = _mm256_set1_ps(8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_scalef_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set1_ps(3.); + let r = _mm256_maskz_scalef_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_scalef_ps(0b11111111, a, b); + let e = _mm256_set1_ps(8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_scalef_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set1_ps(3.); + let r = _mm_scalef_ps(a, b); + let e = _mm_set1_ps(8.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_scalef_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set1_ps(3.); + let r = _mm_mask_scalef_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_scalef_ps(a, 0b00001111, a, b); + let e = _mm_set1_ps(8.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_scalef_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set1_ps(3.); + let r = _mm_maskz_scalef_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_scalef_ps(0b00001111, a, b); + let e = _mm_set1_ps(8.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fixupimm_ps() { let a = _mm512_set1_ps(f32::NAN); @@ -27024,23 +42394,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fixupimm_ps() { + #[rustfmt::skip] let a = _mm512_set_ps( - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - 1., - 1., - 1., - 1., - 1., - 1., - 1., - 1., + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + 1., 1., 1., 1., + 1., 1., 1., 1., ); let b = _mm512_set1_ps(f32::MAX); let c = _mm512_set1_epi32(i32::MAX); @@ -27053,23 +42412,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fixupimm_ps() { + #[rustfmt::skip] let a = _mm512_set_ps( - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - 1., - 1., - 1., - 1., - 1., - 1., - 1., - 1., + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + 1., 1., 1., 1., + 1., 1., 1., 1., ); let b = _mm512_set1_ps(f32::MAX); let c = _mm512_set1_epi32(i32::MAX); @@ -27080,6 +42428,66 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_fixupimm_ps() { + let a = _mm256_set1_ps(f32::NAN); + let b = _mm256_set1_ps(f32::MAX); + let c = _mm256_set1_epi32(i32::MAX); + let r = _mm256_fixupimm_ps(a, b, c, 5); + let e = _mm256_set1_ps(0.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fixupimm_ps() { + let a = _mm256_set1_ps(f32::NAN); + let b = _mm256_set1_ps(f32::MAX); + let c = _mm256_set1_epi32(i32::MAX); + let r = _mm256_mask_fixupimm_ps(a, 0b11111111, b, c, 5); + let e = _mm256_set1_ps(0.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fixupimm_ps() { + let a = _mm256_set1_ps(f32::NAN); + let b = _mm256_set1_ps(f32::MAX); + let c = _mm256_set1_epi32(i32::MAX); + let r = _mm256_maskz_fixupimm_ps(0b11111111, a, b, c, 5); + let e = _mm256_set1_ps(0.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_fixupimm_ps() { + let a = _mm_set1_ps(f32::NAN); + let b = _mm_set1_ps(f32::MAX); + let c = _mm_set1_epi32(i32::MAX); + let r = _mm_fixupimm_ps(a, b, c, 5); + let e = _mm_set1_ps(0.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fixupimm_ps() { + let a = _mm_set1_ps(f32::NAN); + let b = _mm_set1_ps(f32::MAX); + let c = _mm_set1_epi32(i32::MAX); + let r = _mm_mask_fixupimm_ps(a, 0b00001111, b, c, 5); + let e = _mm_set1_ps(0.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fixupimm_ps() { + let a = _mm_set1_ps(f32::NAN); + let b = _mm_set1_ps(f32::MAX); + let c = _mm_set1_epi32(i32::MAX); + let r = _mm_maskz_fixupimm_ps(0b00001111, a, b, c, 5); + let e = _mm_set1_ps(0.0); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_ternarylogic_epi32() { let a = _mm512_set1_epi32(1 << 2); @@ -27114,6 +42522,74 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_ternarylogic_epi32() { + let a = _mm256_set1_epi32(1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let c = _mm256_set1_epi32(1 << 0); + let r = _mm256_ternarylogic_epi32(a, b, c, 8); + let e = _mm256_set1_epi32(0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_ternarylogic_epi32() { + let src = _mm256_set1_epi32(1 << 2); + let a = _mm256_set1_epi32(1 << 1); + let b = _mm256_set1_epi32(1 << 0); + let r = _mm256_mask_ternarylogic_epi32(src, 0, a, b, 8); + assert_eq_m256i(r, src); + let r = _mm256_mask_ternarylogic_epi32(src, 0b11111111, a, b, 8); + let e = _mm256_set1_epi32(0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_ternarylogic_epi32() { + let a = _mm256_set1_epi32(1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let c = _mm256_set1_epi32(1 << 0); + let r = _mm256_maskz_ternarylogic_epi32(0, a, b, c, 9); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_ternarylogic_epi32(0b11111111, a, b, c, 8); + let e = _mm256_set1_epi32(0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_ternarylogic_epi32() { + let a = _mm_set1_epi32(1 << 2); + let b = _mm_set1_epi32(1 << 1); + let c = _mm_set1_epi32(1 << 0); + let r = _mm_ternarylogic_epi32(a, b, c, 8); + let e = _mm_set1_epi32(0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_ternarylogic_epi32() { + let src = _mm_set1_epi32(1 << 2); + let a = _mm_set1_epi32(1 << 1); + let b = _mm_set1_epi32(1 << 0); + let r = _mm_mask_ternarylogic_epi32(src, 0, a, b, 8); + assert_eq_m128i(r, src); + let r = _mm_mask_ternarylogic_epi32(src, 0b00001111, a, b, 8); + let e = _mm_set1_epi32(0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_ternarylogic_epi32() { + let a = _mm_set1_epi32(1 << 2); + let b = _mm_set1_epi32(1 << 1); + let c = _mm_set1_epi32(1 << 0); + let r = _mm_maskz_ternarylogic_epi32(0, a, b, c, 9); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_ternarylogic_epi32(0b00001111, a, b, c, 8); + let e = _mm_set1_epi32(0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_getmant_ps() { let a = _mm512_set1_ps(10.); @@ -27153,6 +42629,62 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_getmant_ps() { + let a = _mm256_set1_ps(10.); + let r = _mm256_getmant_ps(a, _MM_MANT_NORM_P75_1P5, _MM_MANT_SIGN_NAN); + let e = _mm256_set1_ps(1.25); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_getmant_ps() { + let a = _mm256_set1_ps(10.); + let r = _mm256_mask_getmant_ps(a, 0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m256(r, a); + let r = _mm256_mask_getmant_ps(a, 0b11111111, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm256_set1_ps(1.25); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_getmant_ps() { + let a = _mm256_set1_ps(10.); + let r = _mm256_maskz_getmant_ps(0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_getmant_ps(0b11111111, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm256_set1_ps(1.25); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_getmant_ps() { + let a = _mm_set1_ps(10.); + let r = _mm_getmant_ps(a, _MM_MANT_NORM_P75_1P5, _MM_MANT_SIGN_NAN); + let e = _mm_set1_ps(1.25); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_getmant_ps() { + let a = _mm_set1_ps(10.); + let r = _mm_mask_getmant_ps(a, 0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m128(r, a); + let r = _mm_mask_getmant_ps(a, 0b00001111, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm_set1_ps(1.25); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_getmant_ps() { + let a = _mm_set1_ps(10.); + let r = _mm_maskz_getmant_ps(0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_getmant_ps(0b00001111, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm_set1_ps(1.25); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_add_round_ps() { let a = _mm512_setr_ps( @@ -27160,23 +42692,12 @@ mod tests { ); let b = _mm512_set1_ps(-1.); let r = _mm512_add_round_ps(a, b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + #[rustfmt::skip] let e = _mm512_setr_ps( - -1., - 0.5, - 1., - 2.5, - 3., - 4.5, - 5., - 6.5, - 7., - 8.5, - 9., - 10.5, - 11., - 12.5, - 13., - -0.99999994, + -1., 0.5, 1., 2.5, + 3., 4.5, 5., 6.5, + 7., 8.5, 9., 10.5, + 11., 12.5, 13., -0.99999994, ); assert_eq_m512(r, e); let r = _mm512_add_round_ps(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); @@ -27201,23 +42722,12 @@ mod tests { b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 1.5, - 2., - 3.5, - 4., - 5.5, - 6., - 7.5, - 7., - 8.5, - 9., - 10.5, - 11., - 12.5, - 13., - -0.99999994, + 0., 1.5, 2., 3.5, + 4., 5.5, 6., 7.5, + 7., 8.5, 9., 10.5, + 11., 12.5, 13., -0.99999994, ); assert_eq_m512(r, e); } @@ -27236,23 +42746,12 @@ mod tests { b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 7., - 8.5, - 9., - 10.5, - 11., - 12.5, - 13., - -0.99999994, + 0., 0., 0., 0., + 0., 0., 0., 0., + 7., 8.5, 9., 10.5, + 11., 12.5, 13., -0.99999994, ); assert_eq_m512(r, e); } @@ -27264,23 +42763,12 @@ mod tests { ); let b = _mm512_set1_ps(1.); let r = _mm512_sub_round_ps(a, b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + #[rustfmt::skip] let e = _mm512_setr_ps( - -1., - 0.5, - 1., - 2.5, - 3., - 4.5, - 5., - 6.5, - 7., - 8.5, - 9., - 10.5, - 11., - 12.5, - 13., - -0.99999994, + -1., 0.5, 1., 2.5, + 3., 4.5, 5., 6.5, + 7., 8.5, 9., 10.5, + 11., 12.5, 13., -0.99999994, ); assert_eq_m512(r, e); let r = _mm512_sub_round_ps(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); @@ -27305,23 +42793,12 @@ mod tests { b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 1.5, - 2., - 3.5, - 4., - 5.5, - 6., - 7.5, - 7., - 8.5, - 9., - 10.5, - 11., - 12.5, - 13., - -0.99999994, + 0., 1.5, 2., 3.5, + 4., 5.5, 6., 7.5, + 7., 8.5, 9., 10.5, + 11., 12.5, 13., -0.99999994, ); assert_eq_m512(r, e); } @@ -27340,109 +42817,54 @@ mod tests { b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 7., - 8.5, - 9., - 10.5, - 11., - 12.5, - 13., - -0.99999994, + 0., 0., 0., 0., + 0., 0., 0., 0., + 7., 8.5, 9., 10.5, + 11., 12.5, 13., -0.99999994, ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mul_round_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1.5, - 2., - 3.5, - 4., - 5.5, - 6., - 7.5, - 8., - 9.5, - 10., - 11.5, - 12., - 13.5, - 14., - 0.00000000000000000000007, + 0., 1.5, 2., 3.5, + 4., 5.5, 6., 7.5, + 8., 9.5, 10., 11.5, + 12., 13.5, 14., 0.00000000000000000000007, ); let b = _mm512_set1_ps(0.1); let r = _mm512_mul_round_ps(a, b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0.15, - 0.2, - 0.35, - 0.4, - 0.55, - 0.6, - 0.75, - 0.8, - 0.95, - 1.0, - 1.15, - 1.2, - 1.35, - 1.4, - 0.000000000000000000000007000001, + 0., 0.15, 0.2, 0.35, + 0.4, 0.55, 0.6, 0.75, + 0.8, 0.95, 1.0, 1.15, + 1.2, 1.35, 1.4, 0.000000000000000000000007000001, ); assert_eq_m512(r, e); let r = _mm512_mul_round_ps(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0.14999999, - 0.2, - 0.35, - 0.4, - 0.54999995, - 0.59999996, - 0.75, - 0.8, - 0.95, - 1.0, - 1.15, - 1.1999999, - 1.3499999, - 1.4, - 0.000000000000000000000007, + 0., 0.14999999, 0.2, 0.35, + 0.4, 0.54999995, 0.59999996, 0.75, + 0.8, 0.95, 1.0, 1.15, + 1.1999999, 1.3499999, 1.4, 0.000000000000000000000007, ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mul_round_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1.5, - 2., - 3.5, - 4., - 5.5, - 6., - 7.5, - 8., - 9.5, - 10., - 11.5, - 12., - 13.5, - 14., - 0.00000000000000000000007, + 0., 1.5, 2., 3.5, + 4., 5.5, 6., 7.5, + 8., 9.5, 10., 11.5, + 12., 13.5, 14., 0.00000000000000000000007, ); let b = _mm512_set1_ps(0.1); let r = _mm512_mask_mul_round_ps(a, 0, a, b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); @@ -27454,46 +42876,24 @@ mod tests { b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 1.5, - 2., - 3.5, - 4., - 5.5, - 6., - 7.5, - 0.8, - 0.95, - 1.0, - 1.15, - 1.2, - 1.35, - 1.4, - 0.000000000000000000000007000001, + 0., 1.5, 2., 3.5, + 4., 5.5, 6., 7.5, + 0.8, 0.95, 1.0, 1.15, + 1.2, 1.35, 1.4, 0.000000000000000000000007000001, ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_mul_round_ps() { + #[rustfmt::skip] let a = _mm512_setr_ps( - 0., - 1.5, - 2., - 3.5, - 4., - 5.5, - 6., - 7.5, - 8., - 9.5, - 10., - 11.5, - 12., - 13.5, - 14., - 0.00000000000000000000007, + 0., 1.5, 2., 3.5, + 4., 5.5, 6., 7.5, + 8., 9.5, 10., 11.5, + 12., 13.5, 14., 0.00000000000000000000007, ); let b = _mm512_set1_ps(0.1); let r = _mm512_maskz_mul_round_ps(0, a, b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); @@ -27504,23 +42904,12 @@ mod tests { b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0.8, - 0.95, - 1.0, - 1.15, - 1.2, - 1.35, - 1.4, - 0.000000000000000000000007000001, + 0., 0., 0., 0., + 0., 0., 0., 0., + 0.8, 0.95, 1.0, 1.15, + 1.2, 1.35, 1.4, 0.000000000000000000000007000001, ); assert_eq_m512(r, e); } @@ -27650,23 +43039,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, ); assert_eq_m512(r, e); } @@ -27679,6 +43057,7 @@ mod tests { let r = _mm512_maskz_fmadd_round_ps(0, a, b, c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); assert_eq_m512(r, _mm512_setzero_ps()); + #[rustfmt::skip] let r = _mm512_maskz_fmadd_round_ps( 0b00000000_11111111, a, @@ -27686,23 +43065,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } @@ -27722,23 +43090,12 @@ mod tests { 0b00000000_11111111, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -1., - -1., - -1., - -1., - -1., - -1., - -1., - -1., + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + -1., -1., -1., -1., + -1., -1., -1., -1., ); assert_eq_m512(r, e); } @@ -27771,23 +43128,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, ); assert_eq_m512(r, e); } @@ -27807,23 +43153,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } @@ -27843,23 +43178,12 @@ mod tests { 0b00000000_11111111, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - -0.99999994, - 1., - 1., - 1., - 1., - 1., - 1., - 1., - 1., + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + -0.99999994, -0.99999994, -0.99999994, -0.99999994, + 1., 1., 1., 1., + 1., 1., 1., 1., ); assert_eq_m512(r, e); } @@ -27870,23 +43194,12 @@ mod tests { let b = _mm512_set1_ps(1.); let c = _mm512_set1_ps(-1.); let r = _mm512_fmaddsub_round_ps(a, b, c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + #[rustfmt::skip] let e = _mm512_setr_ps( - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, ); assert_eq_m512(r, e); let r = _mm512_fmaddsub_round_ps(a, b, c, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); @@ -27917,23 +43230,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, ); assert_eq_m512(r, e); } @@ -27958,23 +43260,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } @@ -27999,23 +43290,12 @@ mod tests { 0b00000000_11111111, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - -1., - -1., - -1., - -1., - -1., - -1., - -1., - -1., + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + 1.0000001, -0.99999994, 1.0000001, -0.99999994, + -1., -1., -1., -1., + -1., -1., -1., -1., ); assert_eq_m512(r, e); } @@ -28026,23 +43306,12 @@ mod tests { let b = _mm512_set1_ps(1.); let c = _mm512_set1_ps(-1.); let r = _mm512_fmsubadd_round_ps(a, b, c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, ); assert_eq_m512(r, e); let r = _mm512_fmsubadd_round_ps(a, b, c, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); @@ -28073,23 +43342,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, - 0.00000007, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, + 0.00000007, 0.00000007, 0.00000007, 0.00000007, ); assert_eq_m512(r, e); } @@ -28114,23 +43372,12 @@ mod tests { c, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } @@ -28155,23 +43402,12 @@ mod tests { 0b00000000_11111111, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -0.99999994, - 1.0000001, - -1., - -1., - -1., - -1., - -1., - -1., - -1., - -1., + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + -0.99999994, 1.0000001, -0.99999994, 1.0000001, + -1., -1., -1., -1., + -1., -1., -1., -1., ); assert_eq_m512(r, e); } @@ -28560,23 +43796,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fixupimm_round_ps() { + #[rustfmt::skip] let a = _mm512_set_ps( - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - 1., - 1., - 1., - 1., - 1., - 1., - 1., - 1., + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + 1., 1., 1., 1., + 1., 1., 1., 1., ); let b = _mm512_set1_ps(f32::MAX); let c = _mm512_set1_epi32(i32::MAX); @@ -28596,23 +43821,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fixupimm_round_ps() { + #[rustfmt::skip] let a = _mm512_set_ps( - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - f32::NAN, - 1., - 1., - 1., - 1., - 1., - 1., - 1., - 1., + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + f32::NAN, f32::NAN, f32::NAN, f32::NAN, + 1., 1., 1., 1., + 1., 1., 1., 1., ); let b = _mm512_set1_ps(f32::MAX); let c = _mm512_set1_epi32(i32::MAX); @@ -28728,6 +43942,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtps_epi32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let src = _mm256_set1_epi32(0); + let r = _mm256_mask_cvtps_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtps_epi32(src, 0b11111111, a); + let e = _mm256_set_epi32(8, 10, 10, 12, 12, 14, 14, 16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtps_epi32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let r = _mm256_maskz_cvtps_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtps_epi32(0b11111111, a); + let e = _mm256_set_epi32(8, 10, 10, 12, 12, 14, 14, 16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtps_epi32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvtps_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtps_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(12, 14, 14, 16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtps_epi32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let r = _mm_maskz_cvtps_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtps_epi32(0b00001111, a); + let e = _mm_set_epi32(12, 14, 14, 16); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtps_epu32() { let a = _mm512_setr_ps( @@ -28763,6 +44019,64 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtps_epu32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let r = _mm256_cvtps_epu32(a); + let e = _mm256_set_epi32(8, 10, 10, 12, 12, 14, 14, 16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtps_epu32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let src = _mm256_set1_epi32(0); + let r = _mm256_mask_cvtps_epu32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtps_epu32(src, 0b11111111, a); + let e = _mm256_set_epi32(8, 10, 10, 12, 12, 14, 14, 16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtps_epu32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let r = _mm256_maskz_cvtps_epu32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtps_epu32(0b11111111, a); + let e = _mm256_set_epi32(8, 10, 10, 12, 12, 14, 14, 16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtps_epu32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let r = _mm_cvtps_epu32(a); + let e = _mm_set_epi32(12, 14, 14, 16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtps_epu32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvtps_epu32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtps_epu32(src, 0b00001111, a); + let e = _mm_set_epi32(12, 14, 14, 16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtps_epu32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let r = _mm_maskz_cvtps_epu32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtps_epu32(0b00001111, a); + let e = _mm_set_epi32(12, 14, 14, 16); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi8_epi32() { let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -28792,6 +44106,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm256_set1_epi32(-1); + let r = _mm256_mask_cvtepi8_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepi8_epi32(src, 0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_cvtepi8_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepi8_epi32(0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm_set1_epi32(-1); + let r = _mm_mask_cvtepi8_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi8_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_cvtepi8_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi8_epi32(0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepu8_epi32() { let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -28821,6 +44177,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepu8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm256_set1_epi32(-1); + let r = _mm256_mask_cvtepu8_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepu8_epi32(src, 0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepu8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_cvtepu8_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepu8_epi32(0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepu8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm_set1_epi32(-1); + let r = _mm_mask_cvtepu8_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepu8_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepu8_epi32() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_cvtepu8_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepu8_epi32(0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi16_epi32() { let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -28850,6 +44248,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi16_epi32() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let src = _mm256_set1_epi32(-1); + let r = _mm256_mask_cvtepi16_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepi16_epi32(src, 0b11111111, a); + let e = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi16_epi32() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_maskz_cvtepi16_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepi16_epi32(0b11111111, a); + let e = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi16_epi32() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let src = _mm_set1_epi32(-1); + let r = _mm_mask_cvtepi16_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi16_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi16_epi32() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_maskz_cvtepi16_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi16_epi32(0b00001111, a); + let e = _mm_set_epi32(4, 5, 6, 7); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepu16_epi32() { let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -28879,6 +44319,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepu16_epi32() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm256_set1_epi32(-1); + let r = _mm256_mask_cvtepu16_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepu16_epi32(src, 0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepu16_epi32() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_cvtepu16_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepu16_epi32(0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepu16_epi32() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm_set1_epi32(-1); + let r = _mm_mask_cvtepu16_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepu16_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepu16_epi32() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_cvtepu16_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepu16_epi32(0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi32_ps() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -28914,6 +44396,48 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi32_ps() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let src = _mm256_set1_ps(-1.); + let r = _mm256_mask_cvtepi32_ps(src, 0, a); + assert_eq_m256(r, src); + let r = _mm256_mask_cvtepi32_ps(src, 0b11111111, a); + let e = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi32_ps() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_maskz_cvtepi32_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_cvtepi32_ps(0b11111111, a); + let e = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi32_ps() { + let a = _mm_set_epi32(1, 2, 3, 4); + let src = _mm_set1_ps(-1.); + let r = _mm_mask_cvtepi32_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm_mask_cvtepi32_ps(src, 0b00001111, a); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi32_ps() { + let a = _mm_set_epi32(1, 2, 3, 4); + let r = _mm_maskz_cvtepi32_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_cvtepi32_ps(0b00001111, a); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepu32_ps() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -28978,6 +44502,64 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtepi32_epi16() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_cvtepi32_epi16(a); + let e = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi32_epi16() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let src = _mm_set1_epi16(-1); + let r = _mm256_mask_cvtepi32_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtepi32_epi16(src, 0b11111111, a); + let e = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi32_epi16() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_maskz_cvtepi32_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtepi32_epi16(0b11111111, a); + let e = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtepi32_epi16() { + let a = _mm_set_epi32(4, 5, 6, 7); + let r = _mm_cvtepi32_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi32_epi16() { + let a = _mm_set_epi32(4, 5, 6, 7); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvtepi32_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi32_epi16(src, 0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi32_epi16() { + let a = _mm_set_epi32(4, 5, 6, 7); + let r = _mm_maskz_cvtepi32_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi32_epi16(0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi32_epi8() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -29007,287 +44589,354 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtepi32_epi8() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_cvtepi32_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi32_epi8() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let src = _mm_set1_epi8(0); + let r = _mm256_mask_cvtepi32_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtepi32_epi8(src, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi32_epi8() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_maskz_cvtepi32_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtepi32_epi8(0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtepi32_epi8() { + let a = _mm_set_epi32(4, 5, 6, 7); + let r = _mm_cvtepi32_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi32_epi8() { + let a = _mm_set_epi32(4, 5, 6, 7); + let src = _mm_set1_epi8(0); + let r = _mm_mask_cvtepi32_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi32_epi8(src, 0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi32_epi8() { + let a = _mm_set_epi32(4, 5, 6, 7); + let r = _mm_maskz_cvtepi32_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi32_epi8(0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtsepi32_epi16() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MAX, ); let r = _mm512_cvtsepi32_epi16(a); + #[rustfmt::skip] let e = _mm256_set_epi16( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i16::MIN, - i16::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i16::MIN, i16::MAX, ); assert_eq_m256i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_cvtsepi32_epi16() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MAX, ); let src = _mm256_set1_epi16(-1); let r = _mm512_mask_cvtsepi32_epi16(src, 0, a); assert_eq_m256i(r, src); let r = _mm512_mask_cvtsepi32_epi16(src, 0b00000000_11111111, a); + #[rustfmt::skip] let e = _mm256_set_epi16( - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - 8, - 9, - 10, - 11, - 12, - 13, - i16::MIN, - i16::MAX, + -1, -1, -1, -1, + -1, -1, -1, -1, + 8, 9, 10, 11, + 12, 13, i16::MIN, i16::MAX, ); assert_eq_m256i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_cvtsepi32_epi16() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MAX, ); let r = _mm512_maskz_cvtsepi32_epi16(0, a); assert_eq_m256i(r, _mm256_setzero_si256()); let r = _mm512_maskz_cvtsepi32_epi16(0b00000000_11111111, a); + #[rustfmt::skip] let e = _mm256_set_epi16( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8, - 9, - 10, - 11, - 12, - 13, - i16::MIN, - i16::MAX, + 0, 0, 0, 0, + 0, 0, 0, 0, + 8, 9, 10, 11, + 12, 13, i16::MIN, i16::MAX, ); assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtsepi32_epi16() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_cvtsepi32_epi16(a); + let e = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi32_epi16() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let src = _mm_set1_epi16(-1); + let r = _mm256_mask_cvtsepi32_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtsepi32_epi16(src, 0b11111111, a); + let e = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtsepi32_epi16() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_maskz_cvtsepi32_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtsepi32_epi16(0b11111111, a); + let e = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtsepi32_epi16() { + let a = _mm_set_epi32(4, 5, 6, 7); + let r = _mm_cvtsepi32_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi32_epi16() { + let a = _mm_set_epi32(4, 5, 6, 7); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvtsepi32_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtsepi32_epi16(src, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtsepi32_epi16() { + let a = _mm_set_epi32(4, 5, 6, 7); + let r = _mm_maskz_cvtsepi32_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtsepi32_epi16(0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, 7); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtsepi32_epi8() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MAX, ); let r = _mm512_cvtsepi32_epi8(a); + #[rustfmt::skip] let e = _mm_set_epi8( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i8::MIN, - i8::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i8::MIN, i8::MAX, ); assert_eq_m128i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_cvtsepi32_epi8() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MAX, ); let src = _mm_set1_epi8(-1); let r = _mm512_mask_cvtsepi32_epi8(src, 0, a); assert_eq_m128i(r, src); let r = _mm512_mask_cvtsepi32_epi8(src, 0b00000000_11111111, a); + #[rustfmt::skip] let e = _mm_set_epi8( - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - 8, - 9, - 10, - 11, - 12, - 13, - i8::MIN, - i8::MAX, + -1, -1, -1, -1, + -1, -1, -1, -1, + 8, 9, 10, 11, + 12, 13, i8::MIN, i8::MAX, ); assert_eq_m128i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_cvtsepi32_epi8() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MAX, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MAX, ); let r = _mm512_maskz_cvtsepi32_epi8(0, a); assert_eq_m128i(r, _mm_setzero_si128()); let r = _mm512_maskz_cvtsepi32_epi8(0b00000000_11111111, a); + #[rustfmt::skip] let e = _mm_set_epi8( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8, - 9, - 10, - 11, - 12, - 13, - i8::MIN, - i8::MAX, + 0, 0, 0, 0, + 0, 0, 0, 0, + 8, 9, 10, 11, + 12, 13, i8::MIN, i8::MAX, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtsepi32_epi8() { + let a = _mm256_set_epi32(9, 10, 11, 12, 13, 14, 15, 16); + let r = _mm256_cvtsepi32_epi8(a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 9, 10, 11, 12, + 13, 14, 15, 16, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi32_epi8() { + let a = _mm256_set_epi32(9, 10, 11, 12, 13, 14, 15, 16); + let src = _mm_set1_epi8(0); + let r = _mm256_mask_cvtsepi32_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtsepi32_epi8(src, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 9, 10, 11, 12, + 13, 14, 15, 16, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtsepi32_epi8() { + let a = _mm256_set_epi32(9, 10, 11, 12, 13, 14, 15, 16); + let r = _mm256_maskz_cvtsepi32_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtsepi32_epi8(0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 9, 10, 11, 12, + 13, 14, 15, 16, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtsepi32_epi8() { + let a = _mm_set_epi32(13, 14, 15, 16); + let r = _mm_cvtsepi32_epi8(a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 13, 14, 15, 16, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi32_epi8() { + let a = _mm_set_epi32(13, 14, 15, 16); + let src = _mm_set1_epi8(0); + let r = _mm_mask_cvtsepi32_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtsepi32_epi8(src, 0b00001111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 13, 14, 15, 16, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtsepi32_epi8() { + let a = _mm_set_epi32(13, 14, 15, 16); + let r = _mm_maskz_cvtsepi32_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtsepi32_epi8(0b00001111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 13, 14, 15, 16, ); assert_eq_m128i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtusepi32_epi16() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MIN, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MIN, ); let r = _mm512_cvtusepi32_epi16(a); let e = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, -1); @@ -29296,23 +44945,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_cvtusepi32_epi16() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MIN, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MIN, ); let src = _mm256_set1_epi16(-1); let r = _mm512_mask_cvtusepi32_epi16(src, 0, a); @@ -29324,23 +44962,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_cvtusepi32_epi16() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MIN, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MIN, ); let r = _mm512_maskz_cvtusepi32_epi16(0, a); assert_eq_m256i(r, _mm256_setzero_si256()); @@ -29349,25 +44976,72 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtusepi32_epi16() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_cvtusepi32_epi16(a); + let e = _mm_set_epi16(1, 2, 3, 4, 5, 6, 7, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi32_epi16() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let src = _mm_set1_epi16(0); + let r = _mm256_mask_cvtusepi32_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtusepi32_epi16(src, 0b11111111, a); + let e = _mm_set_epi16(1, 2, 3, 4, 5, 6, 7, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtusepi32_epi16() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_maskz_cvtusepi32_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtusepi32_epi16(0b11111111, a); + let e = _mm_set_epi16(1, 2, 3, 4, 5, 6, 7, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtusepi32_epi16() { + let a = _mm_set_epi32(5, 6, 7, 8); + let r = _mm_cvtusepi32_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 5, 6, 7, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi32_epi16() { + let a = _mm_set_epi32(5, 6, 7, 8); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvtusepi32_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtusepi32_epi16(src, 0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 5, 6, 7, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtusepi32_epi16() { + let a = _mm_set_epi32(5, 6, 7, 8); + let r = _mm_maskz_cvtusepi32_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtusepi32_epi16(0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 5, 6, 7, 8); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtusepi32_epi8() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MIN, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MIN, ); let r = _mm512_cvtusepi32_epi8(a); let e = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, -1); @@ -29376,23 +45050,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_cvtusepi32_epi8() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MIN, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MIN, ); let src = _mm_set1_epi8(-1); let r = _mm512_mask_cvtusepi32_epi8(src, 0, a); @@ -29404,23 +45067,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_cvtusepi32_epi8() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - i32::MIN, - i32::MIN, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, i32::MIN, i32::MIN, ); let r = _mm512_maskz_cvtusepi32_epi8(0, a); assert_eq_m128i(r, _mm_setzero_si128()); @@ -29429,6 +45081,64 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtusepi32_epi8() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, i32::MAX); + let r = _mm256_cvtusepi32_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi32_epi8() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, i32::MAX); + let src = _mm_set1_epi8(0); + let r = _mm256_mask_cvtusepi32_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtusepi32_epi8(src, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtusepi32_epi8() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, i32::MAX); + let r = _mm256_maskz_cvtusepi32_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtusepi32_epi8(0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtusepi32_epi8() { + let a = _mm_set_epi32(5, 6, 7, i32::MAX); + let r = _mm_cvtusepi32_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi32_epi8() { + let a = _mm_set_epi32(5, 6, 7, i32::MAX); + let src = _mm_set1_epi8(0); + let r = _mm_mask_cvtusepi32_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtusepi32_epi8(src, 0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtusepi32_epi8() { + let a = _mm_set_epi32(5, 6, 7, i32::MAX); + let r = _mm_maskz_cvtusepi32_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtusepi32_epi8(0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, u8::MAX as i8); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvt_roundps_epi32() { let a = _mm512_setr_ps( @@ -29574,23 +45284,12 @@ mod tests { unsafe fn test_mm512_cvt_roundepu32_ps() { let a = _mm512_setr_epi32(0, -2, 2, -4, 4, -6, 6, -8, 8, 10, 10, 12, 12, 14, 14, 16); let r = _mm512_cvt_roundepu32_ps(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 4294967300., - 2., - 4294967300., - 4., - 4294967300., - 6., - 4294967300., - 8., - 10., - 10., - 12., - 12., - 14., - 14., - 16., + 0., 4294967300., 2., 4294967300., + 4., 4294967300., 6., 4294967300., + 8., 10., 10., 12., + 12., 14., 14., 16., ); assert_eq_m512(r, e); } @@ -29608,23 +45307,12 @@ mod tests { a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 4294967300., - 2., - 4294967300., - 4., - 4294967300., - 6., - 4294967300., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + 0., 4294967300., 2., 4294967300., + 4., 4294967300., 6., 4294967300., + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } @@ -29639,23 +45327,12 @@ mod tests { a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC, ); + #[rustfmt::skip] let e = _mm512_setr_ps( - 0., - 4294967300., - 2., - 4294967300., - 4., - 4294967300., - 6., - 4294967300., - 0., - 0., - 0., - 0., - 0., - 0., - 0., - 0., + 0., 4294967300., 2., 4294967300., + 4., 4294967300., 6., 4294967300., + 0., 0., 0., 0., + 0., 0., 0., 0., ); assert_eq_m512(r, e); } @@ -29694,6 +45371,48 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvt_roundps_ph() { + let a = _mm256_set1_ps(1.); + let src = _mm_set1_epi16(0); + let r = _mm256_mask_cvt_roundps_ph(src, 0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvt_roundps_ph(src, 0b11111111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvt_roundps_ph() { + let a = _mm256_set1_ps(1.); + let r = _mm256_maskz_cvt_roundps_ph(0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvt_roundps_ph(0b11111111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvt_roundps_ph() { + let a = _mm_set1_ps(1.); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvt_roundps_ph(src, 0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, src); + let r = _mm_mask_cvt_roundps_ph(src, 0b00001111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvt_roundps_ph() { + let a = _mm_set1_ps(1.); + let r = _mm_maskz_cvt_roundps_ph(0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvt_roundps_ph(0b00001111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtps_ph() { let a = _mm512_set1_ps(1.); @@ -29728,6 +45447,48 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtps_ph() { + let a = _mm256_set1_ps(1.); + let src = _mm_set1_epi16(0); + let r = _mm256_mask_cvtps_ph(src, 0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtps_ph(src, 0b11111111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtps_ph() { + let a = _mm256_set1_ps(1.); + let r = _mm256_maskz_cvtps_ph(0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtps_ph(0b11111111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtps_ph() { + let a = _mm_set1_ps(1.); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvtps_ph(src, 0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtps_ph(src, 0b00001111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtps_ph() { + let a = _mm_set1_ps(1.); + let r = _mm_maskz_cvtps_ph(0, a, _MM_FROUND_NO_EXC); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtps_ph(0b00001111, a, _MM_FROUND_NO_EXC); + let e = _mm_setr_epi64x(4323521613979991040, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvt_roundph_ps() { let a = _mm256_setr_epi64x( @@ -29824,6 +45585,48 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtph_ps() { + let a = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + let src = _mm256_set1_ps(0.); + let r = _mm256_mask_cvtph_ps(src, 0, a); + assert_eq_m256(r, src); + let r = _mm256_mask_cvtph_ps(src, 0b11111111, a); + let e = _mm256_setr_ps(1., 1., 1., 1., 1., 1., 1., 1.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtph_ps() { + let a = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + let r = _mm256_maskz_cvtph_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_cvtph_ps(0b11111111, a); + let e = _mm256_setr_ps(1., 1., 1., 1., 1., 1., 1., 1.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtph_ps() { + let a = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + let src = _mm_set1_ps(0.); + let r = _mm_mask_cvtph_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm_mask_cvtph_ps(src, 0b00001111, a); + let e = _mm_setr_ps(1., 1., 1., 1.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtph_ps() { + let a = _mm_setr_epi64x(4323521613979991040, 4323521613979991040); + let r = _mm_maskz_cvtph_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_cvtph_ps(0b00001111, a); + let e = _mm_setr_ps(1., 1., 1., 1.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtt_roundps_epi32() { let a = _mm512_setr_ps( @@ -29929,6 +45732,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvttps_epi32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let src = _mm256_set1_epi32(0); + let r = _mm256_mask_cvttps_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvttps_epi32(src, 0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvttps_epi32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let r = _mm256_maskz_cvttps_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvttps_epi32(0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvttps_epi32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvttps_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvttps_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvttps_epi32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let r = _mm_maskz_cvttps_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvttps_epi32(0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvttps_epu32() { let a = _mm512_setr_ps( @@ -29964,6 +45809,64 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvttps_epu32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let r = _mm256_cvttps_epu32(a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvttps_epu32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let src = _mm256_set1_epi32(0); + let r = _mm256_mask_cvttps_epu32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvttps_epu32(src, 0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvttps_epu32() { + let a = _mm256_set_ps(8., 9.5, 10., 11.5, 12., 13.5, 14., 15.5); + let r = _mm256_maskz_cvttps_epu32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvttps_epu32(0b11111111, a); + let e = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvttps_epu32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let r = _mm_cvttps_epu32(a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvttps_epu32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvttps_epu32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvttps_epu32(src, 0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvttps_epu32() { + let a = _mm_set_ps(12., 13.5, 14., 15.5); + let r = _mm_maskz_cvttps_epu32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvttps_epu32(0b00001111, a); + let e = _mm_set_epi32(12, 13, 14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_i32gather_ps() { let mut arr = [0f32; 256]; @@ -30022,14 +45925,15 @@ mod tests { } let src = _mm512_set1_epi32(2); let mask = 0b10101010_10101010; - #[rustfmt::skip] - let index = _mm512_setr_epi32(0, 16, 32, 48, 64, 80, 96, 112, - 128, 144, 160, 176, 192, 208, 224, 240); + let index = _mm512_setr_epi32( + 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, + ); // A multiplier of 4 is word-addressing let r = _mm512_mask_i32gather_epi32(src, mask, index, arr.as_ptr() as *const u8, 4); - #[rustfmt::skip] - assert_eq_m512i(r, _mm512_setr_epi32(2, 16, 2, 48, 2, 80, 2, 112, - 2, 144, 2, 176, 2, 208, 2, 240)); + assert_eq_m512i( + r, + _mm512_setr_epi32(2, 16, 2, 48, 2, 80, 2, 112, 2, 144, 2, 176, 2, 208, 2, 240), + ); } #[simd_test(enable = "avx512f")] @@ -30254,6 +46158,40 @@ mod tests { assert_eq!(r, 0b00000100_00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmp_ps_mask() { + let a = _mm256_set_ps(0., 1., -1., 13., f32::MAX, f32::MIN, 100., -100.); + let b = _mm256_set1_ps(-1.); + let m = _mm256_cmp_ps_mask(a, b, _CMP_LT_OQ); + assert_eq!(m, 0b00000101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmp_ps_mask() { + let a = _mm256_set_ps(0., 1., -1., 13., f32::MAX, f32::MIN, 100., -100.); + let b = _mm256_set1_ps(-1.); + let mask = 0b01100110; + let r = _mm256_mask_cmp_ps_mask(mask, a, b, _CMP_LT_OQ); + assert_eq!(r, 0b00000100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmp_ps_mask() { + let a = _mm_set_ps(0., 1., -1., 13.); + let b = _mm_set1_ps(1.); + let m = _mm_cmp_ps_mask(a, b, _CMP_LT_OQ); + assert_eq!(m, 0b00001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmp_ps_mask() { + let a = _mm_set_ps(0., 1., -1., 13.); + let b = _mm_set1_ps(1.); + let mask = 0b11111111; + let r = _mm_mask_cmp_ps_mask(mask, a, b, _CMP_LT_OQ); + assert_eq!(r, 0b00001010); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmp_round_ps_mask() { #[rustfmt::skip] @@ -30419,6 +46357,40 @@ mod tests { assert_eq!(r, 0b01001010_01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmplt_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 101, 100, 99); + let b = _mm256_set1_epi32(1); + let r = _mm256_cmplt_epu32_mask(a, b); + assert_eq!(r, 0b10000000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 101, 100, 99); + let b = _mm256_set1_epi32(1); + let mask = 0b11111111; + let r = _mm256_mask_cmplt_epu32_mask(mask, a, b); + assert_eq!(r, 0b10000000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmplt_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let r = _mm_cmplt_epu32_mask(a, b); + assert_eq!(r, 0b00001000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmplt_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let mask = 0b11111111; + let r = _mm_mask_cmplt_epu32_mask(mask, a, b); + assert_eq!(r, 0b00001000); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpgt_epu32_mask() { #[rustfmt::skip] @@ -30440,6 +46412,40 @@ mod tests { assert_eq!(r, 0b01001010_01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpgt_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 99, 100, 101); + let b = _mm256_set1_epi32(1); + let r = _mm256_cmpgt_epu32_mask(a, b); + assert_eq!(r, 0b00111111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 99, 100, 101); + let b = _mm256_set1_epi32(1); + let mask = 0b11111111; + let r = _mm256_mask_cmpgt_epu32_mask(mask, a, b); + assert_eq!(r, 0b00111111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpgt_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let r = _mm_cmpgt_epu32_mask(a, b); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let mask = 0b11111111; + let r = _mm_mask_cmpgt_epu32_mask(mask, a, b); + assert_eq!(r, 0b00000011); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmple_epu32_mask() { #[rustfmt::skip] @@ -30465,6 +46471,40 @@ mod tests { ); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmple_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 200, 100, 101); + let b = _mm256_set1_epi32(1); + let r = _mm256_cmple_epu32_mask(a, b); + assert_eq!(r, 0b11000000) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmple_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 200, 100, 101); + let b = _mm256_set1_epi32(1); + let mask = 0b11111111; + let r = _mm256_mask_cmple_epu32_mask(mask, a, b); + assert_eq!(r, 0b11000000) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmple_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let r = _mm_cmple_epu32_mask(a, b); + assert_eq!(r, 0b00001100) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmple_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let mask = 0b11111111; + let r = _mm_mask_cmple_epu32_mask(mask, a, b); + assert_eq!(r, 0b00001100) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpge_epu32_mask() { #[rustfmt::skip] @@ -30487,6 +46527,40 @@ mod tests { assert_eq!(_mm512_mask_cmpge_epu32_mask(mask, a, b), 0b01100000_0110000); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpge_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 300, 100, 200); + let b = _mm256_set1_epi32(1); + let r = _mm256_cmpge_epu32_mask(a, b); + assert_eq!(r, 0b01111111) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epu32_mask() { + let a = _mm256_set_epi32(0, 1, 2, u32::MAX as i32, i32::MAX, 300, 100, 200); + let b = _mm256_set1_epi32(1); + let mask = 0b11111111; + let r = _mm256_mask_cmpge_epu32_mask(mask, a, b); + assert_eq!(r, 0b01111111) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpge_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let r = _mm_cmpge_epu32_mask(a, b); + assert_eq!(r, 0b00000111) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpge_epu32_mask() { + let a = _mm_set_epi32(0, 1, 2, u32::MAX as i32); + let b = _mm_set1_epi32(1); + let mask = 0b11111111; + let r = _mm_mask_cmpge_epu32_mask(mask, a, b); + assert_eq!(r, 0b00000111) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpeq_epu32_mask() { #[rustfmt::skip] @@ -30512,6 +46586,40 @@ mod tests { assert_eq!(r, 0b01001010_01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpeq_epu32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, 100, -100); + let m = _mm256_cmpeq_epu32_mask(b, a); + assert_eq!(m, 0b11001111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epu32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, 100, -100); + let mask = 0b01111010; + let r = _mm256_mask_cmpeq_epu32_mask(mask, b, a); + assert_eq!(r, 0b01001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpeq_epu32_mask() { + let a = _mm_set_epi32(0, 1, -1, u32::MAX as i32); + let b = _mm_set_epi32(0, 1, 13, 42); + let m = _mm_cmpeq_epu32_mask(b, a); + assert_eq!(m, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epu32_mask() { + let a = _mm_set_epi32(0, 1, -1, u32::MAX as i32); + let b = _mm_set_epi32(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm_mask_cmpeq_epu32_mask(mask, b, a); + assert_eq!(r, 0b00001100); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpneq_epu32_mask() { #[rustfmt::skip] @@ -30537,6 +46645,40 @@ mod tests { assert_eq!(r, 0b00110010_00110010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpneq_epu32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, -100, 100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, -100, 100); + let r = _mm256_cmpneq_epu32_mask(b, a); + assert_eq!(r, 0b00110000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epu32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, -100, 100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, -100, 100); + let mask = 0b11111111; + let r = _mm256_mask_cmpneq_epu32_mask(mask, b, a); + assert_eq!(r, 0b00110000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpneq_epu32_mask() { + let a = _mm_set_epi32(0, 1, -1, u32::MAX as i32); + let b = _mm_set_epi32(0, 1, 13, 42); + let r = _mm_cmpneq_epu32_mask(b, a); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epu32_mask() { + let a = _mm_set_epi32(0, 1, -1, u32::MAX as i32); + let b = _mm_set_epi32(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm_mask_cmpneq_epu32_mask(mask, b, a); + assert_eq!(r, 0b00000011); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmp_epu32_mask() { #[rustfmt::skip] @@ -30558,6 +46700,40 @@ mod tests { assert_eq!(r, 0b01001010_01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmp_epu32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let m = _mm256_cmp_epu32_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b11001111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmp_epu32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b11001111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmp_epu32_mask() { + let a = _mm_set_epi32(0, 1, -1, i32::MAX); + let b = _mm_set1_epi32(1); + let m = _mm_cmp_epu32_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b00001000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmp_epu32_mask() { + let a = _mm_set_epi32(0, 1, -1, i32::MAX); + let b = _mm_set1_epi32(1); + let mask = 0b11111111; + let r = _mm_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b00001000); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmplt_epi32_mask() { #[rustfmt::skip] @@ -30579,6 +46755,40 @@ mod tests { assert_eq!(r, 0b00000100_00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmplt_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 101, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let r = _mm256_cmplt_epi32_mask(a, b); + assert_eq!(r, 0b00000101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 101, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmplt_epi32_mask(mask, a, b); + assert_eq!(r, 0b00000101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmplt_epi32_mask() { + let a = _mm_set_epi32(i32::MAX, i32::MIN, 100, -100); + let b = _mm_set1_epi32(-1); + let r = _mm_cmplt_epi32_mask(a, b); + assert_eq!(r, 0b00000101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmplt_epi32_mask() { + let a = _mm_set_epi32(i32::MAX, i32::MIN, 100, -100); + let b = _mm_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm_mask_cmplt_epi32_mask(mask, a, b); + assert_eq!(r, 0b00000101); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpgt_epi32_mask() { #[rustfmt::skip] @@ -30600,6 +46810,40 @@ mod tests { assert_eq!(r, 0b00000100_00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpgt_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let r = _mm256_cmpgt_epi32_mask(a, b); + assert_eq!(r, 0b11011010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmpgt_epi32_mask(mask, a, b); + assert_eq!(r, 0b11011010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpgt_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set1_epi32(-1); + let r = _mm_cmpgt_epi32_mask(a, b); + assert_eq!(r, 0b00001101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm_mask_cmpgt_epi32_mask(mask, a, b); + assert_eq!(r, 0b00001101); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmple_epi32_mask() { #[rustfmt::skip] @@ -30622,6 +46866,40 @@ mod tests { assert_eq!(_mm512_mask_cmple_epi32_mask(mask, a, b), 0b01100000_0110000); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmple_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 200, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let r = _mm256_cmple_epi32_mask(a, b); + assert_eq!(r, 0b00100101) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmple_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 200, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmple_epi32_mask(mask, a, b); + assert_eq!(r, 0b00100101) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmple_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 200); + let b = _mm_set1_epi32(-1); + let r = _mm_cmple_epi32_mask(a, b); + assert_eq!(r, 0b00000010) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmple_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 200); + let b = _mm_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm_mask_cmple_epi32_mask(mask, a, b); + assert_eq!(r, 0b00000010) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpge_epi32_mask() { #[rustfmt::skip] @@ -30647,6 +46925,40 @@ mod tests { ); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpge_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let r = _mm256_cmpge_epi32_mask(a, b); + assert_eq!(r, 0b11111010) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, u32::MAX as i32, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmpge_epi32_mask(mask, a, b); + assert_eq!(r, 0b11111010) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpge_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, u32::MAX as i32); + let b = _mm_set1_epi32(-1); + let r = _mm_cmpge_epi32_mask(a, b); + assert_eq!(r, 0b00001111) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpge_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, u32::MAX as i32); + let b = _mm_set1_epi32(-1); + let mask = 0b11111111; + let r = _mm_mask_cmpge_epi32_mask(mask, a, b); + assert_eq!(r, 0b00001111) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpeq_epi32_mask() { #[rustfmt::skip] @@ -30672,6 +46984,40 @@ mod tests { assert_eq!(r, 0b01001010_01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpeq_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, 100, -100); + let m = _mm256_cmpeq_epi32_mask(b, a); + assert_eq!(m, 0b11001111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, 100, -100); + let mask = 0b01111010; + let r = _mm256_mask_cmpeq_epi32_mask(mask, b, a); + assert_eq!(r, 0b01001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpeq_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set_epi32(0, 1, 13, 42); + let m = _mm_cmpeq_epi32_mask(b, a); + assert_eq!(m, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set_epi32(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm_mask_cmpeq_epi32_mask(mask, b, a); + assert_eq!(r, 0b00001100); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpneq_epi32_mask() { #[rustfmt::skip] @@ -30697,6 +47043,40 @@ mod tests { assert_eq!(r, 0b00110010_00110010) } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpneq_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, 100, -100); + let m = _mm256_cmpneq_epi32_mask(b, a); + assert_eq!(m, !_mm256_cmpeq_epi32_mask(b, a)); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, -100, 100); + let b = _mm256_set_epi32(0, 1, 13, 42, i32::MAX, i32::MIN, 100, -100); + let mask = 0b11111111; + let r = _mm256_mask_cmpneq_epi32_mask(mask, b, a); + assert_eq!(r, 0b00110011) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpneq_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set_epi32(0, 1, 13, 42); + let r = _mm_cmpneq_epi32_mask(b, a); + assert_eq!(r, 0b00000011) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set_epi32(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm_mask_cmpneq_epi32_mask(mask, b, a); + assert_eq!(r, 0b00000011) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmp_epi32_mask() { #[rustfmt::skip] @@ -30718,6 +47098,40 @@ mod tests { assert_eq!(r, 0b00000100_00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmp_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let m = _mm256_cmp_epi32_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b00000101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmp_epi32_mask() { + let a = _mm256_set_epi32(0, 1, -1, 13, i32::MAX, i32::MIN, 100, -100); + let b = _mm256_set1_epi32(-1); + let mask = 0b01100110; + let r = _mm256_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b00000100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmp_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set1_epi32(1); + let m = _mm_cmp_epi32_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b00001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmp_epi32_mask() { + let a = _mm_set_epi32(0, 1, -1, 13); + let b = _mm_set1_epi32(1); + let mask = 0b11111111; + let r = _mm_mask_cmp_epi32_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b00001010); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_set_epi8() { let r = _mm512_set1_epi8(2); @@ -30931,7 +47345,6 @@ mod tests { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); let r = _mm512_mask_rol_epi32(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_rol_epi32(a, 0b11111111_11111111, a, 1); let e = _mm512_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); assert_eq_m512i(r, e); @@ -30942,12 +47355,67 @@ mod tests { let a = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 << 31); let r = _mm512_maskz_rol_epi32(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_rol_epi32(0b00000000_11111111, a, 1); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 1 << 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rol_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let r = _mm256_rol_epi32(a, 1); + let e = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rol_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let r = _mm256_mask_rol_epi32(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_rol_epi32(a, 0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rol_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let r = _mm256_maskz_rol_epi32(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_rol_epi32(0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rol_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let r = _mm_rol_epi32(a, 1); + let e = _mm_set_epi32(1 << 0, 2, 2, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rol_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let r = _mm_mask_rol_epi32(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_rol_epi32(a, 0b00001111, a, 1); + let e = _mm_set_epi32(1 << 0, 2, 2, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rol_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let r = _mm_maskz_rol_epi32(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_rol_epi32(0b00001111, a, 1); + let e = _mm_set_epi32(1 << 0, 2, 2, 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_ror_epi32() { let a = _mm512_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); @@ -30961,7 +47429,6 @@ mod tests { let a = _mm512_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); let r = _mm512_mask_ror_epi32(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_ror_epi32(a, 0b11111111_11111111, a, 1); let e = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); assert_eq_m512i(r, e); @@ -30972,12 +47439,67 @@ mod tests { let a = _mm512_set_epi32(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 << 0); let r = _mm512_maskz_ror_epi32(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_ror_epi32(0b00000000_11111111, a, 1); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 << 31); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_ror_epi32() { + let a = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + let r = _mm256_ror_epi32(a, 1); + let e = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_ror_epi32() { + let a = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + let r = _mm256_mask_ror_epi32(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_ror_epi32(a, 0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_ror_epi32() { + let a = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + let r = _mm256_maskz_ror_epi32(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_ror_epi32(0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_ror_epi32() { + let a = _mm_set_epi32(1 << 0, 2, 2, 2); + let r = _mm_ror_epi32(a, 1); + let e = _mm_set_epi32(1 << 31, 1, 1, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_ror_epi32() { + let a = _mm_set_epi32(1 << 0, 2, 2, 2); + let r = _mm_mask_ror_epi32(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_ror_epi32(a, 0b00001111, a, 1); + let e = _mm_set_epi32(1 << 31, 1, 1, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_ror_epi32() { + let a = _mm_set_epi32(1 << 0, 2, 2, 2); + let r = _mm_maskz_ror_epi32(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_ror_epi32(0b00001111, a, 1); + let e = _mm_set_epi32(1 << 31, 1, 1, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_slli_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); @@ -30991,7 +47513,6 @@ mod tests { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); let r = _mm512_mask_slli_epi32(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_slli_epi32(a, 0b11111111_11111111, a, 1); let e = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); assert_eq_m512i(r, e); @@ -31002,12 +47523,51 @@ mod tests { let a = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 << 31); let r = _mm512_maskz_slli_epi32(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_slli_epi32(0b00000000_11111111, a, 1); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_slli_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let r = _mm256_mask_slli_epi32(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_slli_epi32(a, 0b11111111, a, 1); + let e = _mm256_set_epi32(0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_slli_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let r = _mm256_maskz_slli_epi32(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_slli_epi32(0b11111111, a, 1); + let e = _mm256_set_epi32(0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_slli_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let r = _mm_mask_slli_epi32(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_slli_epi32(a, 0b00001111, a, 1); + let e = _mm_set_epi32(0, 2, 2, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_slli_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let r = _mm_maskz_slli_epi32(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_slli_epi32(0b00001111, a, 1); + let e = _mm_set_epi32(0, 2, 2, 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srli_epi32() { let a = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); @@ -31021,7 +47581,6 @@ mod tests { let a = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); let r = _mm512_mask_srli_epi32(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_srli_epi32(a, 0b11111111_11111111, a, 1); let e = _mm512_set_epi32(0 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); assert_eq_m512i(r, e); @@ -31032,19 +47591,56 @@ mod tests { let a = _mm512_set_epi32(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0); let r = _mm512_maskz_srli_epi32(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srli_epi32(0b00000000_11111111, a, 1); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0 << 31); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srli_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let r = _mm256_mask_srli_epi32(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_srli_epi32(a, 0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srli_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let r = _mm256_maskz_srli_epi32(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srli_epi32(0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srli_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let r = _mm_mask_srli_epi32(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_srli_epi32(a, 0b00001111, a, 1); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srli_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let r = _mm_maskz_srli_epi32(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srli_epi32(0b00001111, a, 1); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rolv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let b = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let b = _mm512_set1_epi32(1); let r = _mm512_rolv_epi32(a, b); - let e = _mm512_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); assert_eq_m512i(r, e); } @@ -31052,13 +47648,10 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_rolv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let b = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let b = _mm512_set1_epi32(1); let r = _mm512_mask_rolv_epi32(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_rolv_epi32(a, 0b11111111_11111111, a, b); - let e = _mm512_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); assert_eq_m512i(r, e); } @@ -31066,24 +47659,81 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_rolv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 << 31); - let b = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let b = _mm512_set1_epi32(1); let r = _mm512_maskz_rolv_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_rolv_epi32(0b00000000_11111111, a, b); - let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 1 << 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rolv_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let b = _mm256_set1_epi32(1); + let r = _mm256_rolv_epi32(a, b); + let e = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rolv_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let b = _mm256_set1_epi32(1); + let r = _mm256_mask_rolv_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_rolv_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rolv_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let b = _mm256_set1_epi32(1); + let r = _mm256_maskz_rolv_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_rolv_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rolv_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let b = _mm_set1_epi32(1); + let r = _mm_rolv_epi32(a, b); + let e = _mm_set_epi32(1 << 0, 2, 2, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rolv_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let b = _mm_set1_epi32(1); + let r = _mm_mask_rolv_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_rolv_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(1 << 0, 2, 2, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rolv_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let b = _mm_set1_epi32(1); + let r = _mm_maskz_rolv_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_rolv_epi32(0b00001111, a, b); + let e = _mm_set_epi32(1 << 0, 2, 2, 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rorv_epi32() { let a = _mm512_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let b = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let b = _mm512_set1_epi32(1); let r = _mm512_rorv_epi32(a, b); - let e = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); assert_eq_m512i(r, e); } @@ -31091,13 +47741,10 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_rorv_epi32() { let a = _mm512_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let b = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let b = _mm512_set1_epi32(1); let r = _mm512_mask_rorv_epi32(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_rorv_epi32(a, 0b11111111_11111111, a, b); - let e = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); assert_eq_m512i(r, e); } @@ -31105,24 +47752,81 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_rorv_epi32() { let a = _mm512_set_epi32(3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 << 0); - let b = _mm512_set_epi32(2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let b = _mm512_set1_epi32(1); let r = _mm512_maskz_rorv_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_rorv_epi32(0b00000000_11111111, a, b); - let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 << 31); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rorv_epi32() { + let a = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + let b = _mm256_set1_epi32(1); + let r = _mm256_rorv_epi32(a, b); + let e = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rorv_epi32() { + let a = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + let b = _mm256_set1_epi32(1); + let r = _mm256_mask_rorv_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_rorv_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rorv_epi32() { + let a = _mm256_set_epi32(1 << 0, 2, 2, 2, 2, 2, 2, 2); + let b = _mm256_set1_epi32(1); + let r = _mm256_maskz_rorv_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_rorv_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rorv_epi32() { + let a = _mm_set_epi32(1 << 0, 2, 2, 2); + let b = _mm_set1_epi32(1); + let r = _mm_rorv_epi32(a, b); + let e = _mm_set_epi32(1 << 31, 1, 1, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rorv_epi32() { + let a = _mm_set_epi32(1 << 0, 2, 2, 2); + let b = _mm_set1_epi32(1); + let r = _mm_mask_rorv_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_rorv_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(1 << 31, 1, 1, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rorv_epi32() { + let a = _mm_set_epi32(1 << 0, 2, 2, 2); + let b = _mm_set1_epi32(1); + let r = _mm_maskz_rorv_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_rorv_epi32(0b00001111, a, b); + let e = _mm_set_epi32(1 << 31, 1, 1, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sllv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let count = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let count = _mm512_set1_epi32(1); let r = _mm512_sllv_epi32(a, count); - let e = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); assert_eq_m512i(r, e); } @@ -31130,13 +47834,10 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_sllv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let count = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let count = _mm512_set1_epi32(1); let r = _mm512_mask_sllv_epi32(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_sllv_epi32(a, 0b11111111_11111111, a, count); - let e = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); assert_eq_m512i(r, e); } @@ -31145,23 +47846,62 @@ mod tests { unsafe fn test_mm512_maskz_sllv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 << 31); let count = _mm512_set_epi32(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r = _mm512_maskz_sllv_epi32(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_sllv_epi32(0b00000000_11111111, a, count); - let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sllv_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let count = _mm256_set1_epi32(1); + let r = _mm256_mask_sllv_epi32(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_sllv_epi32(a, 0b11111111, a, count); + let e = _mm256_set_epi32(0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sllv_epi32() { + let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); + let count = _mm256_set1_epi32(1); + let r = _mm256_maskz_sllv_epi32(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sllv_epi32(0b11111111, a, count); + let e = _mm256_set_epi32(0, 2, 2, 2, 2, 2, 2, 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sllv_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let count = _mm_set1_epi32(1); + let r = _mm_mask_sllv_epi32(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_sllv_epi32(a, 0b00001111, a, count); + let e = _mm_set_epi32(0, 2, 2, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sllv_epi32() { + let a = _mm_set_epi32(1 << 31, 1, 1, 1); + let count = _mm_set1_epi32(1); + let r = _mm_maskz_sllv_epi32(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sllv_epi32(0b00001111, a, count); + let e = _mm_set_epi32(0, 2, 2, 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srlv_epi32() { let a = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let count = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let count = _mm512_set1_epi32(1); let r = _mm512_srlv_epi32(a, count); - let e = _mm512_set_epi32(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); assert_eq_m512i(r, e); } @@ -31169,13 +47909,10 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_srlv_epi32() { let a = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - let count = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - + let count = _mm512_set1_epi32(1); let r = _mm512_mask_srlv_epi32(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_srlv_epi32(a, 0b11111111_11111111, a, count); - let e = _mm512_set_epi32(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); assert_eq_m512i(r, e); } @@ -31184,153 +47921,170 @@ mod tests { unsafe fn test_mm512_maskz_srlv_epi32() { let a = _mm512_set_epi32(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0); let count = _mm512_set_epi32(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); - let r = _mm512_maskz_srlv_epi32(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srlv_epi32(0b00000000_11111111, a, count); - let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srlv_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm256_set1_epi32(1); + let r = _mm256_mask_srlv_epi32(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_srlv_epi32(a, 0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srlv_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm256_set1_epi32(1); + let r = _mm256_maskz_srlv_epi32(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srlv_epi32(0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srlv_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set1_epi32(1); + let r = _mm_mask_srlv_epi32(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_srlv_epi32(a, 0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srlv_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set1_epi32(1); + let r = _mm_maskz_srlv_epi32(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srlv_epi32(0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sll_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 31, - 1 << 0, - 1 << 1, - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 1 << 31, 1 << 0, 1 << 1, 1 << 2, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, ); let count = _mm_set_epi32(0, 0, 0, 2); let r = _mm512_sll_epi32(a, count); + #[rustfmt::skip] let e = _mm512_set_epi32( - 0, - 1 << 2, - 1 << 3, - 1 << 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 0, 1 << 2, 1 << 3, 1 << 4, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_sll_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 31, - 1 << 0, - 1 << 1, - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 1 << 31, 1 << 0, 1 << 1, 1 << 2, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, ); let count = _mm_set_epi32(0, 0, 0, 2); let r = _mm512_mask_sll_epi32(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_sll_epi32(a, 0b11111111_11111111, a, count); + #[rustfmt::skip] let e = _mm512_set_epi32( - 0, - 1 << 2, - 1 << 3, - 1 << 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 0, 1 << 2, 1 << 3, 1 << 4, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_sll_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 31, - 1 << 0, - 1 << 1, - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 31, + 1 << 31, 1 << 0, 1 << 1, 1 << 2, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 31, ); let count = _mm_set_epi32(2, 0, 0, 2); let r = _mm512_maskz_sll_epi32(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_sll_epi32(0b00000000_11111111, a, count); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sll_epi32() { + let a = _mm256_set_epi32(1 << 13, 0, 0, 0, 0, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm256_mask_sll_epi32(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_sll_epi32(a, 0b11111111, a, count); + let e = _mm256_set_epi32(1 << 14, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sll_epi32() { + let a = _mm256_set_epi32(1 << 13, 0, 0, 0, 0, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm256_maskz_sll_epi32(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sll_epi32(0b11111111, a, count); + let e = _mm256_set_epi32(1 << 14, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sll_epi32() { + let a = _mm_set_epi32(1 << 13, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm_mask_sll_epi32(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_sll_epi32(a, 0b00001111, a, count); + let e = _mm_set_epi32(1 << 14, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sll_epi32() { + let a = _mm_set_epi32(1 << 13, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm_maskz_sll_epi32(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sll_epi32(0b00001111, a, count); + let e = _mm_set_epi32(1 << 14, 0, 0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srl_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 31, - 1 << 0, - 1 << 1, - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 1 << 31, 1 << 0, 1 << 1, 1 << 2, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, ); let count = _mm_set_epi32(0, 0, 0, 2); let r = _mm512_srl_epi32(a, count); @@ -31340,28 +48094,16 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_srl_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 31, - 1 << 0, - 1 << 1, - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 1 << 31, 1 << 0, 1 << 1, 1 << 2, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, ); let count = _mm_set_epi32(0, 0, 0, 2); let r = _mm512_mask_srl_epi32(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_srl_epi32(a, 0b11111111_11111111, a, count); let e = _mm512_set_epi32(1 << 29, 0, 0, 1 << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); assert_eq_m512i(r, e); @@ -31369,33 +48111,65 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_srl_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 31, - 1 << 0, - 1 << 1, - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 31, + 1 << 31, 1 << 0, 1 << 1, 1 << 2, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 31, ); let count = _mm_set_epi32(2, 0, 0, 2); let r = _mm512_maskz_srl_epi32(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srl_epi32(0b00000000_11111111, a, count); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 << 29); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srl_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm256_mask_srl_epi32(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_srl_epi32(a, 0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srl_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm256_maskz_srl_epi32(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srl_epi32(0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srl_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm_mask_srl_epi32(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_srl_epi32(a, 0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srl_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm_maskz_srl_epi32(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srl_epi32(0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sra_epi32() { let a = _mm512_set_epi32(8, -8, 16, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); @@ -31411,7 +48185,6 @@ mod tests { let count = _mm_set_epi32(0, 0, 0, 2); let r = _mm512_mask_sra_epi32(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_sra_epi32(a, 0b11111111_11111111, a, count); let e = _mm512_set_epi32(2, -2, 4, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4); assert_eq_m512i(r, e); @@ -31423,12 +48196,55 @@ mod tests { let count = _mm_set_epi32(2, 0, 0, 2); let r = _mm512_maskz_sra_epi32(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_sra_epi32(0b00000000_11111111, a, count); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -4); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sra_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm256_mask_sra_epi32(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_sra_epi32(a, 0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sra_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm256_maskz_sra_epi32(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sra_epi32(0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sra_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm_mask_sra_epi32(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_sra_epi32(a, 0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sra_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set_epi32(0, 0, 0, 1); + let r = _mm_maskz_sra_epi32(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sra_epi32(0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srav_epi32() { let a = _mm512_set_epi32(8, -8, 16, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); @@ -31444,7 +48260,6 @@ mod tests { let count = _mm512_set_epi32(2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); let r = _mm512_mask_srav_epi32(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_srav_epi32(a, 0b11111111_11111111, a, count); let e = _mm512_set_epi32(2, -2, 4, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8); assert_eq_m512i(r, e); @@ -31456,12 +48271,55 @@ mod tests { let count = _mm512_set_epi32(2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2); let r = _mm512_maskz_srav_epi32(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srav_epi32(0b00000000_11111111, a, count); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -4); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srav_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm256_set1_epi32(1); + let r = _mm256_mask_srav_epi32(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_srav_epi32(a, 0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srav_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let count = _mm256_set1_epi32(1); + let r = _mm256_maskz_srav_epi32(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srav_epi32(0b11111111, a, count); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srav_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set1_epi32(1); + let r = _mm_mask_srav_epi32(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_srav_epi32(a, 0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srav_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let count = _mm_set1_epi32(1); + let r = _mm_maskz_srav_epi32(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srav_epi32(0b00001111, a, count); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srai_epi32() { let a = _mm512_set_epi32(8, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, -15); @@ -31475,7 +48333,6 @@ mod tests { let a = _mm512_set_epi32(8, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, -15); let r = _mm512_mask_srai_epi32(a, 0, a, 2); assert_eq_m512i(r, a); - let r = _mm512_mask_srai_epi32(a, 0b11111111_11111111, a, 2); let e = _mm512_set_epi32(2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -4); assert_eq_m512i(r, e); @@ -31486,52 +48343,131 @@ mod tests { let a = _mm512_set_epi32(8, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, -15); let r = _mm512_maskz_srai_epi32(0, a, 2); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srai_epi32(0b00000000_11111111, a, 2); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -4); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srai_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let r = _mm256_mask_srai_epi32(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_srai_epi32(a, 0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srai_epi32() { + let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); + let r = _mm256_maskz_srai_epi32(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srai_epi32(0b11111111, a, 1); + let e = _mm256_set_epi32(1 << 4, 0, 0, 0, 0, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srai_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let r = _mm_mask_srai_epi32(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_srai_epi32(a, 0b00001111, a, 1); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srai_epi32() { + let a = _mm_set_epi32(1 << 5, 0, 0, 0); + let r = _mm_maskz_srai_epi32(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srai_epi32(0b00001111, a, 1); + let e = _mm_set_epi32(1 << 4, 0, 0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permute_ps() { - let a = _mm512_set_ps( + let a = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let r = _mm512_permute_ps(a, 1); - let e = _mm512_set_ps( - 2., 2., 2., 2., 6., 6., 6., 6., 10., 10., 10., 10., 14., 14., 14., 14., + let r = _mm512_permute_ps(a, 0b11111111); + let e = _mm512_setr_ps( + 3., 3., 3., 3., 7., 7., 7., 7., 11., 11., 11., 11., 15., 15., 15., 15., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_permute_ps() { - let a = _mm512_set_ps( + let a = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let r = _mm512_mask_permute_ps(a, 0b00000000_00000000, a, 1); + let r = _mm512_mask_permute_ps(a, 0, a, 0b11111111); assert_eq_m512(r, a); - let r = _mm512_mask_permute_ps(a, 0b11111111_11111111, a, 1); - let e = _mm512_set_ps( - 2., 2., 2., 2., 6., 6., 6., 6., 10., 10., 10., 10., 14., 14., 14., 14., + let r = _mm512_mask_permute_ps(a, 0b11111111_11111111, a, 0b111111111); + let e = _mm512_setr_ps( + 3., 3., 3., 3., 7., 7., 7., 7., 11., 11., 11., 11., 15., 15., 15., 15., ); assert_eq_m512(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_permute_ps() { - let a = _mm512_set_ps( + let a = _mm512_setr_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let r = _mm512_maskz_permute_ps(0, a, 1); + let r = _mm512_maskz_permute_ps(0, a, 0b11111111); assert_eq_m512(r, _mm512_setzero_ps()); - let r = _mm512_maskz_permute_ps(0b00000000_11111111, a, 1); - let e = _mm512_set_ps( - 0., 0., 0., 0., 0., 0., 0., 0., 10., 10., 10., 10., 14., 14., 14., 14., + let r = _mm512_maskz_permute_ps(0b11111111_11111111, a, 0b11111111); + let e = _mm512_setr_ps( + 3., 3., 3., 3., 7., 7., 7., 7., 11., 11., 11., 11., 15., 15., 15., 15., ); assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permute_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_mask_permute_ps(a, 0, a, 0b11111111); + assert_eq_m256(r, a); + let r = _mm256_mask_permute_ps(a, 0b11111111, a, 0b11111111); + let e = _mm256_set_ps(0., 0., 0., 0., 4., 4., 4., 4.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permute_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_maskz_permute_ps(0, a, 0b11111111); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_permute_ps(0b11111111, a, 0b11111111); + let e = _mm256_set_ps(0., 0., 0., 0., 4., 4., 4., 4.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permute_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let r = _mm_mask_permute_ps(a, 0, a, 0b11111111); + assert_eq_m128(r, a); + let r = _mm_mask_permute_ps(a, 0b00001111, a, 0b11111111); + let e = _mm_set_ps(0., 0., 0., 0.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permute_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let r = _mm_maskz_permute_ps(0, a, 0b11111111); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_permute_ps(0b00001111, a, 0b11111111); + let e = _mm_set_ps(0., 0., 0., 0.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutevar_epi32() { let idx = _mm512_set1_epi32(1); @@ -31557,7 +48493,7 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let b = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(0b01); let r = _mm512_permutevar_ps(a, b); let e = _mm512_set_ps( 2., 2., 2., 2., 6., 6., 6., 6., 10., 10., 10., 10., 14., 14., 14., 14., @@ -31570,7 +48506,7 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let b = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(0b01); let r = _mm512_mask_permutevar_ps(a, 0, a, b); assert_eq_m512(r, a); let r = _mm512_mask_permutevar_ps(a, 0b11111111_11111111, a, b); @@ -31585,7 +48521,7 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); - let b = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(0b01); let r = _mm512_maskz_permutevar_ps(0, a, b); assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_permutevar_ps(0b00000000_11111111, a, b); @@ -31595,6 +48531,50 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutevar_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let b = _mm256_set1_epi32(0b01); + let r = _mm256_mask_permutevar_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_permutevar_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(2., 2., 2., 2., 6., 6., 6., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutevar_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let b = _mm256_set1_epi32(0b01); + let r = _mm256_maskz_permutevar_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_permutevar_ps(0b11111111, a, b); + let e = _mm256_set_ps(2., 2., 2., 2., 6., 6., 6., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permutevar_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let b = _mm_set1_epi32(0b01); + let r = _mm_mask_permutevar_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_permutevar_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(2., 2., 2., 2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permutevar_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let b = _mm_set1_epi32(0b01); + let r = _mm_maskz_permutevar_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_permutevar_ps(0b00001111, a, b); + let e = _mm_set_ps(2., 2., 2., 2.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutexvar_epi32() { let idx = _mm512_set1_epi32(1); @@ -31626,6 +48606,37 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutexvar_epi32() { + let idx = _mm256_set1_epi32(1); + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_permutexvar_epi32(idx, a); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutexvar_epi32() { + let idx = _mm256_set1_epi32(1); + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_mask_permutexvar_epi32(a, 0, idx, a); + assert_eq_m256i(r, a); + let r = _mm256_mask_permutexvar_epi32(a, 0b11111111, idx, a); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutexvar_epi32() { + let idx = _mm256_set1_epi32(1); + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_maskz_permutexvar_epi32(0, idx, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_permutexvar_epi32(0b11111111, idx, a); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutexvar_ps() { let idx = _mm512_set1_epi32(1); @@ -31665,26 +48676,46 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutexvar_ps() { + let idx = _mm256_set1_epi32(1); + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_permutexvar_ps(idx, a); + let e = _mm256_set1_ps(6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutexvar_ps() { + let idx = _mm256_set1_epi32(1); + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_mask_permutexvar_ps(a, 0, idx, a); + assert_eq_m256(r, a); + let r = _mm256_mask_permutexvar_ps(a, 0b11111111, idx, a); + let e = _mm256_set1_ps(6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutexvar_ps() { + let idx = _mm256_set1_epi32(1); + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_maskz_permutexvar_ps(0, idx, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_permutexvar_ps(0b11111111, idx, a); + let e = _mm256_set1_ps(6.); + assert_eq_m256(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutex2var_epi32() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1, - 1 << 4, - 2, - 1 << 4, - 3, - 1 << 4, - 4, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1, 1 << 4, 2, 1 << 4, + 3, 1 << 4, 4, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_epi32(100); let r = _mm512_permutex2var_epi32(a, idx, b); @@ -31697,23 +48728,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_permutex2var_epi32() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1, - 1 << 4, - 2, - 1 << 4, - 3, - 1 << 4, - 4, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1, 1 << 4, 2, 1 << 4, + 3, 1 << 4, 4, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_epi32(100); let r = _mm512_mask_permutex2var_epi32(a, 0, idx, b); @@ -31728,23 +48748,12 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_permutex2var_epi32() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1, - 1 << 4, - 2, - 1 << 4, - 3, - 1 << 4, - 4, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1, 1 << 4, 2, 1 << 4, + 3, 1 << 4, 4, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_epi32(100); let r = _mm512_maskz_permutex2var_epi32(0, a, idx, b); @@ -31757,71 +48766,130 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask2_permutex2var_epi32() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1000, - 1 << 4, - 2000, - 1 << 4, - 3000, - 1 << 4, - 4000, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1000, 1 << 4, 2000, 1 << 4, + 3000, 1 << 4, 4000, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_epi32(100); let r = _mm512_mask2_permutex2var_epi32(a, idx, 0, b); assert_eq_m512i(r, idx); let r = _mm512_mask2_permutex2var_epi32(a, idx, 0b00000000_11111111, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1000, - 1 << 4, - 2000, - 1 << 4, - 3000, - 1 << 4, - 4000, - 1 << 4, - 10, - 100, - 9, - 100, - 8, - 100, - 7, - 100, + 1000, 1 << 4, 2000, 1 << 4, + 3000, 1 << 4, 4000, 1 << 4, + 10, 100, 9, 100, + 8, 100, 7, 100, ); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutex2var_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_epi32(100); + let r = _mm256_permutex2var_epi32(a, idx, b); + let e = _mm256_set_epi32(6, 100, 5, 100, 4, 100, 3, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutex2var_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_epi32(100); + let r = _mm256_mask_permutex2var_epi32(a, 0, idx, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_permutex2var_epi32(a, 0b11111111, idx, b); + let e = _mm256_set_epi32(6, 100, 5, 100, 4, 100, 3, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutex2var_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_epi32(100); + let r = _mm256_maskz_permutex2var_epi32(0, a, idx, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_permutex2var_epi32(0b11111111, a, idx, b); + let e = _mm256_set_epi32(6, 100, 5, 100, 4, 100, 3, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask2_permutex2var_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_epi32(100); + let r = _mm256_mask2_permutex2var_epi32(a, idx, 0, b); + assert_eq_m256i(r, idx); + let r = _mm256_mask2_permutex2var_epi32(a, idx, 0b11111111, b); + let e = _mm256_set_epi32(6, 100, 5, 100, 4, 100, 3, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_permutex2var_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_epi32(100); + let r = _mm_permutex2var_epi32(a, idx, b); + let e = _mm_set_epi32(2, 100, 1, 100); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permutex2var_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_epi32(100); + let r = _mm_mask_permutex2var_epi32(a, 0, idx, b); + assert_eq_m128i(r, a); + let r = _mm_mask_permutex2var_epi32(a, 0b00001111, idx, b); + let e = _mm_set_epi32(2, 100, 1, 100); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permutex2var_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_epi32(100); + let r = _mm_maskz_permutex2var_epi32(0, a, idx, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_permutex2var_epi32(0b00001111, a, idx, b); + let e = _mm_set_epi32(2, 100, 1, 100); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask2_permutex2var_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_epi32(100); + let r = _mm_mask2_permutex2var_epi32(a, idx, 0, b); + assert_eq_m128i(r, idx); + let r = _mm_mask2_permutex2var_epi32(a, idx, 0b00001111, b); + let e = _mm_set_epi32(2, 100, 1, 100); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutex2var_ps() { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1, - 1 << 4, - 2, - 1 << 4, - 3, - 1 << 4, - 4, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1, 1 << 4, 2, 1 << 4, + 3, 1 << 4, 4, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_ps(100.); let r = _mm512_permutex2var_ps(a, idx, b); @@ -31836,23 +48904,12 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1, - 1 << 4, - 2, - 1 << 4, - 3, - 1 << 4, - 4, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1, 1 << 4, 2, 1 << 4, + 3, 1 << 4, 4, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_ps(100.); let r = _mm512_mask_permutex2var_ps(a, 0, idx, b); @@ -31869,23 +48926,12 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1, - 1 << 4, - 2, - 1 << 4, - 3, - 1 << 4, - 4, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1, 1 << 4, 2, 1 << 4, + 3, 1 << 4, 4, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_ps(100.); let r = _mm512_maskz_permutex2var_ps(0, a, idx, b); @@ -31902,34 +48948,115 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + #[rustfmt::skip] let idx = _mm512_set_epi32( - 1, - 1 << 4, - 2, - 1 << 4, - 3, - 1 << 4, - 4, - 1 << 4, - 5, - 1 << 4, - 6, - 1 << 4, - 7, - 1 << 4, - 8, - 1 << 4, + 1, 1 << 4, 2, 1 << 4, + 3, 1 << 4, 4, 1 << 4, + 5, 1 << 4, 6, 1 << 4, + 7, 1 << 4, 8, 1 << 4, ); let b = _mm512_set1_ps(100.); let r = _mm512_mask2_permutex2var_ps(a, idx, 0, b); - assert_eq_m512(r, _mm512_setzero_ps()); - let r = _mm512_mask2_permutex2var_ps(a, idx, 0b00000000_11111111, b); + assert_eq_m512(r, _mm512_castsi512_ps(idx)); + let r = _mm512_mask2_permutex2var_ps(a, idx, 0b11111111_11111111, b); let e = _mm512_set_ps( - 0., 0., 0., 0., 0., 0., 0., 0., 10., 100., 9., 100., 8., 100., 7., 100., + 14., 100., 13., 100., 12., 100., 11., 100., 10., 100., 9., 100., 8., 100., 7., 100., ); assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutex2var_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_ps(100.); + let r = _mm256_permutex2var_ps(a, idx, b); + let e = _mm256_set_ps(6., 100., 5., 100., 4., 100., 3., 100.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutex2var_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_ps(100.); + let r = _mm256_mask_permutex2var_ps(a, 0, idx, b); + assert_eq_m256(r, a); + let r = _mm256_mask_permutex2var_ps(a, 0b11111111, idx, b); + let e = _mm256_set_ps(6., 100., 5., 100., 4., 100., 3., 100.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutex2var_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_ps(100.); + let r = _mm256_maskz_permutex2var_ps(0, a, idx, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_permutex2var_ps(0b11111111, a, idx, b); + let e = _mm256_set_ps(6., 100., 5., 100., 4., 100., 3., 100.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask2_permutex2var_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let idx = _mm256_set_epi32(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); + let b = _mm256_set1_ps(100.); + let r = _mm256_mask2_permutex2var_ps(a, idx, 0, b); + assert_eq_m256(r, _mm256_castsi256_ps(idx)); + let r = _mm256_mask2_permutex2var_ps(a, idx, 0b11111111, b); + let e = _mm256_set_ps(6., 100., 5., 100., 4., 100., 3., 100.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_permutex2var_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_ps(100.); + let r = _mm_permutex2var_ps(a, idx, b); + let e = _mm_set_ps(2., 100., 1., 100.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permutex2var_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_ps(100.); + let r = _mm_mask_permutex2var_ps(a, 0, idx, b); + assert_eq_m128(r, a); + let r = _mm_mask_permutex2var_ps(a, 0b00001111, idx, b); + let e = _mm_set_ps(2., 100., 1., 100.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permutex2var_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_ps(100.); + let r = _mm_maskz_permutex2var_ps(0, a, idx, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_permutex2var_ps(0b00001111, a, idx, b); + let e = _mm_set_ps(2., 100., 1., 100.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask2_permutex2var_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let idx = _mm_set_epi32(1, 1 << 2, 2, 1 << 2); + let b = _mm_set1_ps(100.); + let r = _mm_mask2_permutex2var_ps(a, idx, 0, b); + assert_eq_m128(r, _mm_castsi128_ps(idx)); + let r = _mm_mask2_permutex2var_ps(a, idx, 0b00001111, b); + let e = _mm_set_ps(2., 100., 1., 100.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_shuffle_epi32() { let a = _mm512_setr_epi32(1, 4, 5, 8, 9, 12, 13, 16, 1, 4, 5, 8, 9, 12, 13, 16); @@ -31958,6 +49085,46 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_shuffle_epi32() { + let a = _mm256_set_epi32(1, 4, 5, 8, 9, 12, 13, 16); + let r = _mm256_mask_shuffle_epi32(a, 0, a, _MM_PERM_AADD); + assert_eq_m256i(r, a); + let r = _mm256_mask_shuffle_epi32(a, 0b11111111, a, _MM_PERM_AADD); + let e = _mm256_set_epi32(8, 8, 1, 1, 16, 16, 9, 9); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_epi32() { + let a = _mm256_set_epi32(1, 4, 5, 8, 9, 12, 13, 16); + let r = _mm256_maskz_shuffle_epi32(0, a, _MM_PERM_AADD); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shuffle_epi32(0b11111111, a, _MM_PERM_AADD); + let e = _mm256_set_epi32(8, 8, 1, 1, 16, 16, 9, 9); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_shuffle_epi32() { + let a = _mm_set_epi32(1, 4, 5, 8); + let r = _mm_mask_shuffle_epi32(a, 0, a, _MM_PERM_AADD); + assert_eq_m128i(r, a); + let r = _mm_mask_shuffle_epi32(a, 0b00001111, a, _MM_PERM_AADD); + let e = _mm_set_epi32(8, 8, 1, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_shuffle_epi32() { + let a = _mm_set_epi32(1, 4, 5, 8); + let r = _mm_maskz_shuffle_epi32(0, a, _MM_PERM_AADD); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shuffle_epi32(0b00001111, a, _MM_PERM_AADD); + let e = _mm_set_epi32(8, 8, 1, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_shuffle_ps() { let a = _mm512_setr_ps( @@ -32007,11 +49174,55 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_shuffle_ps() { + let a = _mm256_set_ps(1., 4., 5., 8., 9., 12., 13., 16.); + let b = _mm256_set_ps(2., 3., 6., 7., 10., 11., 14., 15.); + let r = _mm256_mask_shuffle_ps(a, 0, a, b, 0x0F); + assert_eq_m256(r, a); + let r = _mm256_mask_shuffle_ps(a, 0b11111111, a, b, 0x0F); + let e = _mm256_set_ps(7., 7., 1., 1., 15., 15., 9., 9.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_ps() { + let a = _mm256_set_ps(1., 4., 5., 8., 9., 12., 13., 16.); + let b = _mm256_set_ps(2., 3., 6., 7., 10., 11., 14., 15.); + let r = _mm256_maskz_shuffle_ps(0, a, b, 0x0F); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_shuffle_ps(0b11111111, a, b, 0x0F); + let e = _mm256_set_ps(7., 7., 1., 1., 15., 15., 9., 9.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_shuffle_ps() { + let a = _mm_set_ps(1., 4., 5., 8.); + let b = _mm_set_ps(2., 3., 6., 7.); + let r = _mm_mask_shuffle_ps(a, 0, a, b, 0x0F); + assert_eq_m128(r, a); + let r = _mm_mask_shuffle_ps(a, 0b00001111, a, b, 0x0F); + let e = _mm_set_ps(7., 7., 1., 1.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_shuffle_ps() { + let a = _mm_set_ps(1., 4., 5., 8.); + let b = _mm_set_ps(2., 3., 6., 7.); + let r = _mm_maskz_shuffle_ps(0, a, b, 0x0F); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_shuffle_ps(0b00001111, a, b, 0x0F); + let e = _mm_set_ps(7., 7., 1., 1.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_shuffle_i32x4() { let a = _mm512_setr_epi32(1, 4, 5, 8, 9, 12, 13, 16, 1, 4, 5, 8, 9, 12, 13, 16); let b = _mm512_setr_epi32(2, 3, 6, 7, 10, 11, 14, 15, 2, 3, 6, 7, 10, 11, 14, 15); - let r = _mm512_shuffle_i32x4(a, b, 0b00000000); + let r = _mm512_shuffle_i32x4(a, b, 0b0000); let e = _mm512_setr_epi32(1, 4, 5, 8, 1, 4, 5, 8, 2, 3, 6, 7, 2, 3, 6, 7); assert_eq_m512i(r, e); } @@ -32020,9 +49231,9 @@ mod tests { unsafe fn test_mm512_mask_shuffle_i32x4() { let a = _mm512_setr_epi32(1, 4, 5, 8, 9, 12, 13, 16, 1, 4, 5, 8, 9, 12, 13, 16); let b = _mm512_setr_epi32(2, 3, 6, 7, 10, 11, 14, 15, 2, 3, 6, 7, 10, 11, 14, 15); - let r = _mm512_mask_shuffle_i32x4(a, 0, a, b, 0b00000000); + let r = _mm512_mask_shuffle_i32x4(a, 0, a, b, 0b0000); assert_eq_m512i(r, a); - let r = _mm512_mask_shuffle_i32x4(a, 0b11111111_11111111, a, b, 0b00000000); + let r = _mm512_mask_shuffle_i32x4(a, 0b11111111_11111111, a, b, 0b0000); let e = _mm512_setr_epi32(1, 4, 5, 8, 1, 4, 5, 8, 2, 3, 6, 7, 2, 3, 6, 7); assert_eq_m512i(r, e); } @@ -32031,13 +49242,44 @@ mod tests { unsafe fn test_mm512_maskz_shuffle_i32x4() { let a = _mm512_setr_epi32(1, 4, 5, 8, 9, 12, 13, 16, 1, 4, 5, 8, 9, 12, 13, 16); let b = _mm512_setr_epi32(2, 3, 6, 7, 10, 11, 14, 15, 2, 3, 6, 7, 10, 11, 14, 15); - let r = _mm512_maskz_shuffle_i32x4(0, a, b, 0b00000000); + let r = _mm512_maskz_shuffle_i32x4(0, a, b, 0b0000); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_shuffle_i32x4(0b00000000_11111111, a, b, 0b00000000); + let r = _mm512_maskz_shuffle_i32x4(0b00000000_11111111, a, b, 0b0000); let e = _mm512_setr_epi32(1, 4, 5, 8, 1, 4, 5, 8, 0, 0, 0, 0, 0, 0, 0, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_shuffle_i32x4() { + let a = _mm256_set_epi32(1, 4, 5, 8, 9, 12, 13, 16); + let b = _mm256_set_epi32(2, 3, 6, 7, 10, 11, 14, 15); + let r = _mm256_shuffle_i32x4(a, b, 0b00); + let e = _mm256_set_epi32(10, 11, 14, 15, 9, 12, 13, 16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_shuffle_i32x4() { + let a = _mm256_set_epi32(1, 4, 5, 8, 9, 12, 13, 16); + let b = _mm256_set_epi32(2, 3, 6, 7, 10, 11, 14, 15); + let r = _mm256_mask_shuffle_i32x4(a, 0, a, b, 0b00); + assert_eq_m256i(r, a); + let r = _mm256_mask_shuffle_i32x4(a, 0b11111111, a, b, 0b00); + let e = _mm256_set_epi32(10, 11, 14, 15, 9, 12, 13, 16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_i32x4() { + let a = _mm256_set_epi32(1, 4, 5, 8, 9, 12, 13, 16); + let b = _mm256_set_epi32(2, 3, 6, 7, 10, 11, 14, 15); + let r = _mm256_maskz_shuffle_i32x4(0, a, b, 0b00); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shuffle_i32x4(0b11111111, a, b, 0b00); + let e = _mm256_set_epi32(10, 11, 14, 15, 9, 12, 13, 16); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_shuffle_f32x4() { let a = _mm512_setr_ps( @@ -32087,12 +49329,43 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_shuffle_f32x4() { + let a = _mm256_set_ps(1., 4., 5., 8., 9., 12., 13., 16.); + let b = _mm256_set_ps(2., 3., 6., 7., 10., 11., 14., 15.); + let r = _mm256_shuffle_f32x4(a, b, 0b00); + let e = _mm256_set_ps(10., 11., 14., 15., 9., 12., 13., 16.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_shuffle_f32x4() { + let a = _mm256_set_ps(1., 4., 5., 8., 9., 12., 13., 16.); + let b = _mm256_set_ps(2., 3., 6., 7., 10., 11., 14., 15.); + let r = _mm256_mask_shuffle_f32x4(a, 0, a, b, 0b00); + assert_eq_m256(r, a); + let r = _mm256_mask_shuffle_f32x4(a, 0b11111111, a, b, 0b00); + let e = _mm256_set_ps(10., 11., 14., 15., 9., 12., 13., 16.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_f32x4() { + let a = _mm256_set_ps(1., 4., 5., 8., 9., 12., 13., 16.); + let b = _mm256_set_ps(2., 3., 6., 7., 10., 11., 14., 15.); + let r = _mm256_maskz_shuffle_f32x4(0, a, b, 0b00); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_shuffle_f32x4(0b11111111, a, b, 0b00); + let e = _mm256_set_ps(10., 11., 14., 15., 9., 12., 13., 16.); + assert_eq_m256(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_extractf32x4_ps() { let a = _mm512_setr_ps( 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., ); - let r = _mm512_extractf32x4_ps(a, 0x1); + let r = _mm512_extractf32x4_ps(a, 0b1); let e = _mm_setr_ps(5., 6., 7., 8.); assert_eq_m128(r, e); } @@ -32103,9 +49376,9 @@ mod tests { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., ); let src = _mm_set1_ps(100.); - let r = _mm512_mask_extractf32x4_ps(src, 0, a, 0x1); + let r = _mm512_mask_extractf32x4_ps(src, 0, a, 0b1); assert_eq_m128(r, src); - let r = _mm512_mask_extractf32x4_ps(src, 0b11111111, a, 0x1); + let r = _mm512_mask_extractf32x4_ps(src, 0b11111111, a, 0b1); let e = _mm_setr_ps(5., 6., 7., 8.); assert_eq_m128(r, e); } @@ -32115,17 +49388,46 @@ mod tests { let a = _mm512_setr_ps( 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., ); - let r = _mm512_maskz_extractf32x4_ps(0, a, 0x1); + let r = _mm512_maskz_extractf32x4_ps(0, a, 0b1); assert_eq_m128(r, _mm_setzero_ps()); - let r = _mm512_maskz_extractf32x4_ps(0b00000001, a, 0x1); + let r = _mm512_maskz_extractf32x4_ps(0b00000001, a, 0b1); let e = _mm_setr_ps(5., 0., 0., 0.); assert_eq_m128(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_extractf32x4_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let r = _mm256_extractf32x4_ps(a, 0b1); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_extractf32x4_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let src = _mm_set1_ps(100.); + let r = _mm256_mask_extractf32x4_ps(src, 0, a, 0b1); + assert_eq_m128(r, src); + let r = _mm256_mask_extractf32x4_ps(src, 0b00001111, a, 0b1); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_extractf32x4_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let r = _mm256_maskz_extractf32x4_ps(0, a, 0b1); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm256_maskz_extractf32x4_ps(0b00001111, a, 0b1); + let e = _mm_set_ps(1., 2., 3., 4.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_extracti32x4_epi32() { let a = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r = _mm512_extracti32x4_epi32(a, 0x1); + let r = _mm512_extracti32x4_epi32(a, 0b1); let e = _mm_setr_epi32(5, 6, 7, 8); assert_eq_m128i(r, e); } @@ -32136,18 +49438,47 @@ mod tests { let src = _mm_set1_epi32(100); let r = _mm512_mask_extracti32x4_epi32(src, 0, a, 0x1); assert_eq_m128i(r, src); - let r = _mm512_mask_extracti32x4_epi32(src, 0b11111111, a, 0x1); - let e = _mm_setr_epi32(5, 6, 7, 8); + let r = _mm512_mask_extracti32x4_epi32(src, 0b11111111, a, 0b1); + let e = _mm_setr_epi32(5, 6, 7, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm512_maskz_extracti32x4_epi32() { + let a = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r = _mm512_maskz_extracti32x4_epi32(0, a, 0b1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm512_maskz_extracti32x4_epi32(0b00000001, a, 0x1); + let e = _mm_setr_epi32(5, 0, 0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_extracti32x4_epi32() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_extracti32x4_epi32(a, 0b1); + let e = _mm_set_epi32(1, 2, 3, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_extracti32x4_epi32() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let src = _mm_set1_epi32(100); + let r = _mm256_mask_extracti32x4_epi32(src, 0, a, 0b1); + assert_eq_m128i(r, src); + let r = _mm256_mask_extracti32x4_epi32(src, 0b00001111, a, 0b1); + let e = _mm_set_epi32(1, 2, 3, 4); assert_eq_m128i(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_maskz_extracti32x4_epi32() { - let a = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); - let r = _mm512_maskz_extracti32x4_epi32(0, a, 0x1); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_extracti32x4_epi32() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_maskz_extracti32x4_epi32(0, a, 0b1); assert_eq_m128i(r, _mm_setzero_si128()); - let r = _mm512_maskz_extracti32x4_epi32(0b00000001, a, 0x1); - let e = _mm_setr_epi32(5, 0, 0, 0); + let r = _mm256_maskz_extracti32x4_epi32(0b00001111, a, 0b1); + let e = _mm_set_epi32(1, 2, 3, 4); assert_eq_m128i(r, e); } @@ -32191,6 +49522,46 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_moveldup_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let r = _mm256_mask_moveldup_ps(a, 0, a); + assert_eq_m256(r, a); + let r = _mm256_mask_moveldup_ps(a, 0b11111111, a); + let e = _mm256_set_ps(2., 2., 4., 4., 6., 6., 8., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_moveldup_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let r = _mm256_maskz_moveldup_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_moveldup_ps(0b11111111, a); + let e = _mm256_set_ps(2., 2., 4., 4., 6., 6., 8., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_moveldup_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let r = _mm_mask_moveldup_ps(a, 0, a); + assert_eq_m128(r, a); + let r = _mm_mask_moveldup_ps(a, 0b00001111, a); + let e = _mm_set_ps(2., 2., 4., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_moveldup_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let r = _mm_maskz_moveldup_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_moveldup_ps(0b00001111, a); + let e = _mm_set_ps(2., 2., 4., 4.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_movehdup_ps() { let a = _mm512_setr_ps( @@ -32231,6 +49602,46 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_movehdup_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let r = _mm256_mask_movehdup_ps(a, 0, a); + assert_eq_m256(r, a); + let r = _mm256_mask_movehdup_ps(a, 0b11111111, a); + let e = _mm256_set_ps(1., 1., 3., 3., 5., 5., 7., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_movehdup_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let r = _mm256_maskz_movehdup_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_movehdup_ps(0b11111111, a); + let e = _mm256_set_ps(1., 1., 3., 3., 5., 5., 7., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_movehdup_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let r = _mm_mask_movehdup_ps(a, 0, a); + assert_eq_m128(r, a); + let r = _mm_mask_movehdup_ps(a, 0b00001111, a); + let e = _mm_set_ps(1., 1., 3., 3.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_movehdup_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let r = _mm_maskz_movehdup_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_movehdup_ps(0b00001111, a); + let e = _mm_set_ps(1., 1., 3., 3.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_inserti32x4() { let a = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); @@ -32262,6 +49673,37 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_inserti32x4() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_inserti32x4(a, b, 1); + let e = _mm256_set_epi32(17, 18, 19, 20, 5, 6, 7, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_inserti32x4() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_mask_inserti32x4(a, 0, a, b, 0); + assert_eq_m256i(r, a); + let r = _mm256_mask_inserti32x4(a, 0b11111111, a, b, 1); + let e = _mm256_set_epi32(17, 18, 19, 20, 5, 6, 7, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_inserti32x4() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_maskz_inserti32x4(0, a, b, 0); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_inserti32x4(0b11111111, a, b, 1); + let e = _mm256_set_epi32(17, 18, 19, 20, 5, 6, 7, 8); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_insertf32x4() { let a = _mm512_setr_ps( @@ -32305,6 +49747,37 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_insertf32x4() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let b = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_insertf32x4(a, b, 1); + let e = _mm256_set_ps(17., 18., 19., 20., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_insertf32x4() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let b = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_mask_insertf32x4(a, 0, a, b, 0); + assert_eq_m256(r, a); + let r = _mm256_mask_insertf32x4(a, 0b11111111, a, b, 1); + let e = _mm256_set_ps(17., 18., 19., 20., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_insertf32x4() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let b = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_maskz_insertf32x4(0, a, b, 0); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_insertf32x4(0b11111111, a, b, 1); + let e = _mm256_set_ps(17., 18., 19., 20., 5., 6., 7., 8.); + assert_eq_m256(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_castps128_ps512() { let a = _mm_setr_ps(17., 18., 19., 20.); @@ -32410,6 +49883,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_broadcastd_epi32() { + let src = _mm256_set1_epi32(20); + let a = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_mask_broadcastd_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_broadcastd_epi32(src, 0b11111111, a); + let e = _mm256_set1_epi32(20); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_broadcastd_epi32() { + let a = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_maskz_broadcastd_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_broadcastd_epi32(0b11111111, a); + let e = _mm256_set1_epi32(20); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_broadcastd_epi32() { + let src = _mm_set1_epi32(20); + let a = _mm_set_epi32(17, 18, 19, 20); + let r = _mm_mask_broadcastd_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_broadcastd_epi32(src, 0b00001111, a); + let e = _mm_set1_epi32(20); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_broadcastd_epi32() { + let a = _mm_set_epi32(17, 18, 19, 20); + let r = _mm_maskz_broadcastd_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_broadcastd_epi32(0b00001111, a); + let e = _mm_set1_epi32(20); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_broadcastss_ps() { let a = _mm_set_ps(17., 18., 19., 20.); @@ -32441,6 +49956,48 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_broadcastss_ps() { + let src = _mm256_set1_ps(20.); + let a = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_mask_broadcastss_ps(src, 0, a); + assert_eq_m256(r, src); + let r = _mm256_mask_broadcastss_ps(src, 0b11111111, a); + let e = _mm256_set1_ps(20.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_broadcastss_ps() { + let a = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_maskz_broadcastss_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_broadcastss_ps(0b11111111, a); + let e = _mm256_set1_ps(20.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_broadcastss_ps() { + let src = _mm_set1_ps(20.); + let a = _mm_set_ps(17., 18., 19., 20.); + let r = _mm_mask_broadcastss_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm_mask_broadcastss_ps(src, 0b00001111, a); + let e = _mm_set1_ps(20.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_broadcastss_ps() { + let a = _mm_set_ps(17., 18., 19., 20.); + let r = _mm_maskz_broadcastss_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_broadcastss_ps(0b00001111, a); + let e = _mm_set1_ps(20.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_broadcast_i32x4() { let a = _mm_set_epi32(17, 18, 19, 20); @@ -32474,6 +50031,35 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_broadcast_i32x4() { + let a = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_broadcast_i32x4(a); + let e = _mm256_set_epi32(17, 18, 19, 20, 17, 18, 19, 20); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_broadcast_i32x4() { + let src = _mm256_set1_epi32(20); + let a = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_mask_broadcast_i32x4(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_broadcast_i32x4(src, 0b11111111, a); + let e = _mm256_set_epi32(17, 18, 19, 20, 17, 18, 19, 20); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_broadcast_i32x4() { + let a = _mm_set_epi32(17, 18, 19, 20); + let r = _mm256_maskz_broadcast_i32x4(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_broadcast_i32x4(0b11111111, a); + let e = _mm256_set_epi32(17, 18, 19, 20, 17, 18, 19, 20); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_broadcast_f32x4() { let a = _mm_set_ps(17., 18., 19., 20.); @@ -32509,6 +50095,35 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_broadcast_f32x4() { + let a = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_broadcast_f32x4(a); + let e = _mm256_set_ps(17., 18., 19., 20., 17., 18., 19., 20.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_broadcast_f32x4() { + let src = _mm256_set1_ps(20.); + let a = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_mask_broadcast_f32x4(src, 0, a); + assert_eq_m256(r, src); + let r = _mm256_mask_broadcast_f32x4(src, 0b11111111, a); + let e = _mm256_set_ps(17., 18., 19., 20., 17., 18., 19., 20.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_broadcast_f32x4() { + let a = _mm_set_ps(17., 18., 19., 20.); + let r = _mm256_maskz_broadcast_f32x4(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_broadcast_f32x4(0b11111111, a); + let e = _mm256_set_ps(17., 18., 19., 20., 17., 18., 19., 20.); + assert_eq_m256(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_blend_epi32() { let a = _mm512_set1_epi32(1); @@ -32518,6 +50133,24 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_blend_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set1_epi32(2); + let r = _mm256_mask_blend_epi32(0b11111111, a, b); + let e = _mm256_set1_epi32(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_blend_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set1_epi32(2); + let r = _mm_mask_blend_epi32(0b00001111, a, b); + let e = _mm_set1_epi32(2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_blend_ps() { let a = _mm512_set1_ps(1.); @@ -32529,6 +50162,24 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_blend_ps() { + let a = _mm256_set1_ps(1.); + let b = _mm256_set1_ps(2.); + let r = _mm256_mask_blend_ps(0b11111111, a, b); + let e = _mm256_set1_ps(2.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_blend_ps() { + let a = _mm_set1_ps(1.); + let b = _mm_set1_ps(2.); + let r = _mm_mask_blend_ps(0b00001111, a, b); + let e = _mm_set1_ps(2.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpackhi_epi32() { let a = _mm512_set_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); @@ -32566,6 +50217,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpackhi_epi32() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm256_set_epi32(17, 18, 19, 20, 21, 22, 23, 24); + let r = _mm256_mask_unpackhi_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_unpackhi_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(17, 1, 18, 2, 21, 5, 22, 6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpackhi_epi32() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm256_set_epi32(17, 18, 19, 20, 21, 22, 23, 24); + let r = _mm256_maskz_unpackhi_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_unpackhi_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(17, 1, 18, 2, 21, 5, 22, 6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpackhi_epi32() { + let a = _mm_set_epi32(1, 2, 3, 4); + let b = _mm_set_epi32(17, 18, 19, 20); + let r = _mm_mask_unpackhi_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_unpackhi_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(17, 1, 18, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpackhi_epi32() { + let a = _mm_set_epi32(1, 2, 3, 4); + let b = _mm_set_epi32(17, 18, 19, 20); + let r = _mm_maskz_unpackhi_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_unpackhi_epi32(0b00001111, a, b); + let e = _mm_set_epi32(17, 1, 18, 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpackhi_ps() { let a = _mm512_set_ps( @@ -32615,6 +50310,50 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpackhi_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let b = _mm256_set_ps(17., 18., 19., 20., 21., 22., 23., 24.); + let r = _mm256_mask_unpackhi_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_unpackhi_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(17., 1., 18., 2., 21., 5., 22., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpackhi_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let b = _mm256_set_ps(17., 18., 19., 20., 21., 22., 23., 24.); + let r = _mm256_maskz_unpackhi_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_unpackhi_ps(0b11111111, a, b); + let e = _mm256_set_ps(17., 1., 18., 2., 21., 5., 22., 6.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpackhi_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let b = _mm_set_ps(17., 18., 19., 20.); + let r = _mm_mask_unpackhi_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_unpackhi_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(17., 1., 18., 2.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpackhi_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let b = _mm_set_ps(17., 18., 19., 20.); + let r = _mm_maskz_unpackhi_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_unpackhi_ps(0b00001111, a, b); + let e = _mm_set_ps(17., 1., 18., 2.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpacklo_epi32() { let a = _mm512_set_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); @@ -32652,6 +50391,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpacklo_epi32() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm256_set_epi32(17, 18, 19, 20, 21, 22, 23, 24); + let r = _mm256_mask_unpacklo_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_unpacklo_epi32(a, 0b11111111, a, b); + let e = _mm256_set_epi32(19, 3, 20, 4, 23, 7, 24, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpacklo_epi32() { + let a = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let b = _mm256_set_epi32(17, 18, 19, 20, 21, 22, 23, 24); + let r = _mm256_maskz_unpacklo_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_unpacklo_epi32(0b11111111, a, b); + let e = _mm256_set_epi32(19, 3, 20, 4, 23, 7, 24, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpacklo_epi32() { + let a = _mm_set_epi32(1, 2, 3, 4); + let b = _mm_set_epi32(17, 18, 19, 20); + let r = _mm_mask_unpacklo_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_unpacklo_epi32(a, 0b00001111, a, b); + let e = _mm_set_epi32(19, 3, 20, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpacklo_epi32() { + let a = _mm_set_epi32(1, 2, 3, 4); + let b = _mm_set_epi32(17, 18, 19, 20); + let r = _mm_maskz_unpacklo_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_unpacklo_epi32(0b00001111, a, b); + let e = _mm_set_epi32(19, 3, 20, 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpacklo_ps() { let a = _mm512_set_ps( @@ -32701,6 +50484,50 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpacklo_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let b = _mm256_set_ps(17., 18., 19., 20., 21., 22., 23., 24.); + let r = _mm256_mask_unpacklo_ps(a, 0, a, b); + assert_eq_m256(r, a); + let r = _mm256_mask_unpacklo_ps(a, 0b11111111, a, b); + let e = _mm256_set_ps(19., 3., 20., 4., 23., 7., 24., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpacklo_ps() { + let a = _mm256_set_ps(1., 2., 3., 4., 5., 6., 7., 8.); + let b = _mm256_set_ps(17., 18., 19., 20., 21., 22., 23., 24.); + let r = _mm256_maskz_unpacklo_ps(0, a, b); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_unpacklo_ps(0b11111111, a, b); + let e = _mm256_set_ps(19., 3., 20., 4., 23., 7., 24., 8.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpacklo_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let b = _mm_set_ps(17., 18., 19., 20.); + let r = _mm_mask_unpacklo_ps(a, 0, a, b); + assert_eq_m128(r, a); + let r = _mm_mask_unpacklo_ps(a, 0b00001111, a, b); + let e = _mm_set_ps(19., 3., 20., 4.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpacklo_ps() { + let a = _mm_set_ps(1., 2., 3., 4.); + let b = _mm_set_ps(17., 18., 19., 20.); + let r = _mm_maskz_unpacklo_ps(0, a, b); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_unpacklo_ps(0b00001111, a, b); + let e = _mm_set_ps(19., 3., 20., 4.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_alignr_epi32() { let a = _mm512_set_epi32(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); @@ -32746,43 +50573,87 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_alignr_epi32() { + let a = _mm256_set_epi32(8, 7, 6, 5, 4, 3, 2, 1); + let b = _mm256_set_epi32(16, 15, 14, 13, 12, 11, 10, 9); + let r = _mm256_alignr_epi32(a, b, 0); + assert_eq_m256i(r, b); + let r = _mm256_alignr_epi32(a, b, 1); + let e = _mm256_set_epi32(1, 16, 15, 14, 13, 12, 11, 10); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_alignr_epi32() { + let a = _mm256_set_epi32(8, 7, 6, 5, 4, 3, 2, 1); + let b = _mm256_set_epi32(16, 15, 14, 13, 12, 11, 10, 9); + let r = _mm256_mask_alignr_epi32(a, 0, a, b, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_alignr_epi32(a, 0b11111111, a, b, 1); + let e = _mm256_set_epi32(1, 16, 15, 14, 13, 12, 11, 10); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_alignr_epi32() { + let a = _mm256_set_epi32(8, 7, 6, 5, 4, 3, 2, 1); + let b = _mm256_set_epi32(16, 15, 14, 13, 12, 11, 10, 9); + let r = _mm256_maskz_alignr_epi32(0, a, b, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_alignr_epi32(0b11111111, a, b, 1); + let e = _mm256_set_epi32(1, 16, 15, 14, 13, 12, 11, 10); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_alignr_epi32() { + let a = _mm_set_epi32(4, 3, 2, 1); + let b = _mm_set_epi32(8, 7, 6, 5); + let r = _mm_alignr_epi32(a, b, 0); + assert_eq_m128i(r, b); + let r = _mm_alignr_epi32(a, b, 1); + let e = _mm_set_epi32(1, 8, 7, 6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_alignr_epi32() { + let a = _mm_set_epi32(4, 3, 2, 1); + let b = _mm_set_epi32(8, 7, 6, 5); + let r = _mm_mask_alignr_epi32(a, 0, a, b, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_alignr_epi32(a, 0b00001111, a, b, 1); + let e = _mm_set_epi32(1, 8, 7, 6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_alignr_epi32() { + let a = _mm_set_epi32(4, 3, 2, 1); + let b = _mm_set_epi32(8, 7, 6, 5); + let r = _mm_maskz_alignr_epi32(0, a, b, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_alignr_epi32(0b00001111, a, b, 1); + let e = _mm_set_epi32(1, 8, 7, 6); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_and_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_and_epi32(a, b); let e = _mm512_set_epi32(1 << 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 << 3); @@ -32791,150 +50662,115 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_and_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_mask_and_epi32(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_and_epi32(a, 0b01111111_11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_and_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_maskz_and_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_and_epi32(0b00000000_11111111, a, b); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 << 3); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_and_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_mask_and_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_and_epi32(a, 0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_and_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_maskz_and_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_and_epi32(0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_and_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_mask_and_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_and_epi32(a, 0b00001111, a, b); + let e = _mm_set1_epi32(1 << 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_and_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_maskz_and_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_and_epi32(0b00001111, a, b); + let e = _mm_set1_epi32(1 << 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_and_si512() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_and_epi32(a, b); let e = _mm512_set_epi32(1 << 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 << 3); @@ -32943,475 +50779,342 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_or_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_or_epi32(a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3 | 1 << 4, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3 | 1 << 4, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_or_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_mask_or_epi32(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_or_epi32(a, 0b11111111_11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3 | 1 << 4, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3 | 1 << 4, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_or_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_maskz_or_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_or_epi32(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3 | 1 << 4, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3 | 1 << 4, ); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_or_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_or_epi32(a, b); + let e = _mm256_set1_epi32(1 << 1 | 1 << 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_or_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_mask_or_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_or_epi32(a, 0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 1 | 1 << 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_or_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_maskz_or_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_or_epi32(0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 1 | 1 << 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_or_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_or_epi32(a, b); + let e = _mm_set1_epi32(1 << 1 | 1 << 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_or_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_mask_or_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_or_epi32(a, 0b00001111, a, b); + let e = _mm_set1_epi32(1 << 1 | 1 << 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_or_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_maskz_or_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_or_epi32(0b00001111, a, b); + let e = _mm_set1_epi32(1 << 1 | 1 << 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_or_si512() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_or_epi32(a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3 | 1 << 4, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3 | 1 << 4, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_xor_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_xor_epi32(a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 4, + 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 4, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_xor_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_mask_xor_epi32(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_xor_epi32(a, 0b01111111_11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 4, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 4, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_xor_epi32() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_maskz_xor_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_xor_epi32(0b00000000_11111111, a, b); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 4); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_xor_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_xor_epi32(a, b); + let e = _mm256_set1_epi32(1 << 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_xor_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_mask_xor_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_xor_epi32(a, 0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_xor_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_maskz_xor_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_xor_epi32(0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_xor_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_xor_epi32(a, b); + let e = _mm_set1_epi32(1 << 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_xor_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_mask_xor_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_xor_epi32(a, 0b00001111, a, b); + let e = _mm_set1_epi32(1 << 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_xor_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_maskz_xor_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_xor_epi32(0b00001111, a, b); + let e = _mm_set1_epi32(1 << 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_xor_si512() { + #[rustfmt::skip] let a = _mm512_set_epi32( - 1 << 1 | 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 3, + 1 << 1 | 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 3, ); + #[rustfmt::skip] let b = _mm512_set_epi32( - 1 << 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, + 1 << 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 3 | 1 << 4, ); let r = _mm512_xor_epi32(a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 1 << 2, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 4, + 1 << 2, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 4, ); assert_eq_m512i(r, e); } @@ -33431,7 +51134,6 @@ mod tests { let b = _mm512_set1_epi32(1 << 3 | 1 << 4); let r = _mm512_mask_andnot_epi32(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_andnot_epi32(a, 0b11111111_11111111, a, b); let e = _mm512_set1_epi32(1 << 3 | 1 << 4); assert_eq_m512i(r, e); @@ -33443,29 +51145,61 @@ mod tests { let b = _mm512_set1_epi32(1 << 3 | 1 << 4); let r = _mm512_maskz_andnot_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_andnot_epi32(0b00000000_11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi32( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, + 0, 0, 0, 0, + 0, 0, 0, 0, + 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, + 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, ); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_andnot_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 3 | 1 << 4); + let r = _mm256_mask_andnot_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_andnot_epi32(a, 0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 3 | 1 << 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_andnot_epi32() { + let a = _mm256_set1_epi32(1 << 1 | 1 << 2); + let b = _mm256_set1_epi32(1 << 3 | 1 << 4); + let r = _mm256_maskz_andnot_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_andnot_epi32(0b11111111, a, b); + let e = _mm256_set1_epi32(1 << 3 | 1 << 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_andnot_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 3 | 1 << 4); + let r = _mm_mask_andnot_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_andnot_epi32(a, 0b00001111, a, b); + let e = _mm_set1_epi32(1 << 3 | 1 << 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_andnot_epi32() { + let a = _mm_set1_epi32(1 << 1 | 1 << 2); + let b = _mm_set1_epi32(1 << 3 | 1 << 4); + let r = _mm_maskz_andnot_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_andnot_epi32(0b00001111, a, b); + let e = _mm_set1_epi32(1 << 3 | 1 << 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_kand() { let a: u16 = 0b11001100_00110011; @@ -33636,6 +51370,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_test_epi32_mask() { + let a = _mm256_set1_epi32(1 << 0); + let b = _mm256_set1_epi32(1 << 0 | 1 << 1); + let r = _mm256_test_epi32_mask(a, b); + let e: __mmask8 = 0b11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_test_epi32_mask() { + let a = _mm256_set1_epi32(1 << 0); + let b = _mm256_set1_epi32(1 << 0 | 1 << 1); + let r = _mm256_mask_test_epi32_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_test_epi32_mask(0b11111111, a, b); + let e: __mmask8 = 0b11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_test_epi32_mask() { + let a = _mm_set1_epi32(1 << 0); + let b = _mm_set1_epi32(1 << 0 | 1 << 1); + let r = _mm_test_epi32_mask(a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_test_epi32_mask() { + let a = _mm_set1_epi32(1 << 0); + let b = _mm_set1_epi32(1 << 0 | 1 << 1); + let r = _mm_mask_test_epi32_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_test_epi32_mask(0b11111111, a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_testn_epi32_mask() { let a = _mm512_set1_epi32(1 << 0); @@ -33656,6 +51430,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_testn_epi32_mask() { + let a = _mm256_set1_epi32(1 << 0); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_testn_epi32_mask(a, b); + let e: __mmask8 = 0b11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_testn_epi32_mask() { + let a = _mm256_set1_epi32(1 << 0); + let b = _mm256_set1_epi32(1 << 1); + let r = _mm256_mask_test_epi32_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_testn_epi32_mask(0b11111111, a, b); + let e: __mmask8 = 0b11111111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_testn_epi32_mask() { + let a = _mm_set1_epi32(1 << 0); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_testn_epi32_mask(a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_testn_epi32_mask() { + let a = _mm_set1_epi32(1 << 0); + let b = _mm_set1_epi32(1 << 1); + let r = _mm_mask_test_epi32_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_testn_epi32_mask(0b11111111, a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_stream_ps() { #[repr(align(32))] @@ -33843,7 +51657,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_reduce_or_epi32() { let a = _mm512_set_epi32(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2); - let e: i32 = _mm512_mask_reduce_or_epi32(0b11111111_00000000, a); + let e: i32 = _mm512_mask_reduce_and_epi32(0b11111111_00000000, a); assert_eq!(1, e); } @@ -33851,6 +51665,8 @@ mod tests { unsafe fn test_mm512_mask_compress_epi32() { let src = _mm512_set1_epi32(200); let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm512_mask_compress_epi32(src, 0, a); + assert_eq_m512i(r, src); let r = _mm512_mask_compress_epi32(src, 0b01010101_01010101, a); let e = _mm512_set_epi32( 200, 200, 200, 200, 200, 200, 200, 200, 1, 3, 5, 7, 9, 11, 13, 15, @@ -33861,17 +51677,63 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_compress_epi32() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm512_maskz_compress_epi32(0, a); + assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_compress_epi32(0b01010101_01010101, a); let e = _mm512_set_epi32(0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 9, 11, 13, 15); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_compress_epi32() { + let src = _mm256_set1_epi32(200); + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_mask_compress_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_compress_epi32(src, 0b01010101, a); + let e = _mm256_set_epi32(200, 200, 200, 200, 1, 3, 5, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_compress_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_maskz_compress_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_compress_epi32(0b01010101, a); + let e = _mm256_set_epi32(0, 0, 0, 0, 1, 3, 5, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_compress_epi32() { + let src = _mm_set1_epi32(200); + let a = _mm_set_epi32(0, 1, 2, 3); + let r = _mm_mask_compress_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_compress_epi32(src, 0b00000101, a); + let e = _mm_set_epi32(200, 200, 1, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_compress_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let r = _mm_maskz_compress_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_compress_epi32(0b00000101, a); + let e = _mm_set_epi32(0, 0, 1, 3); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_compress_ps() { let src = _mm512_set1_ps(200.); let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + let r = _mm512_mask_compress_ps(src, 0, a); + assert_eq_m512(r, src); let r = _mm512_mask_compress_ps(src, 0b01010101_01010101, a); let e = _mm512_set_ps( 200., 200., 200., 200., 200., 200., 200., 200., 1., 3., 5., 7., 9., 11., 13., 15., @@ -33884,6 +51746,8 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + let r = _mm512_maskz_compress_ps(0, a); + assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_compress_ps(0b01010101_01010101, a); let e = _mm512_set_ps( 0., 0., 0., 0., 0., 0., 0., 0., 1., 3., 5., 7., 9., 11., 13., 15., @@ -33891,10 +51755,54 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_compress_ps() { + let src = _mm256_set1_ps(200.); + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_mask_compress_ps(src, 0, a); + assert_eq_m256(r, src); + let r = _mm256_mask_compress_ps(src, 0b01010101, a); + let e = _mm256_set_ps(200., 200., 200., 200., 1., 3., 5., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_compress_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_maskz_compress_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_compress_ps(0b01010101, a); + let e = _mm256_set_ps(0., 0., 0., 0., 1., 3., 5., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_compress_ps() { + let src = _mm_set1_ps(200.); + let a = _mm_set_ps(0., 1., 2., 3.); + let r = _mm_mask_compress_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm_mask_compress_ps(src, 0b00000101, a); + let e = _mm_set_ps(200., 200., 1., 3.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_compress_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let r = _mm_maskz_compress_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_compress_ps(0b00000101, a); + let e = _mm_set_ps(0., 0., 1., 3.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_expand_epi32() { let src = _mm512_set1_epi32(200); let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm512_mask_expand_epi32(src, 0, a); + assert_eq_m512i(r, src); let r = _mm512_mask_expand_epi32(src, 0b01010101_01010101, a); let e = _mm512_set_epi32( 200, 8, 200, 9, 200, 10, 200, 11, 200, 12, 200, 13, 200, 14, 200, 15, @@ -33905,17 +51813,63 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_expand_epi32() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm512_maskz_expand_epi32(0, a); + assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_expand_epi32(0b01010101_01010101, a); let e = _mm512_set_epi32(0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_expand_epi32() { + let src = _mm256_set1_epi32(200); + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_mask_expand_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_expand_epi32(src, 0b01010101, a); + let e = _mm256_set_epi32(200, 4, 200, 5, 200, 6, 200, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_expand_epi32() { + let a = _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm256_maskz_expand_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_expand_epi32(0b01010101, a); + let e = _mm256_set_epi32(0, 4, 0, 5, 0, 6, 0, 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_expand_epi32() { + let src = _mm_set1_epi32(200); + let a = _mm_set_epi32(0, 1, 2, 3); + let r = _mm_mask_expand_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_expand_epi32(src, 0b00000101, a); + let e = _mm_set_epi32(200, 2, 200, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_expand_epi32() { + let a = _mm_set_epi32(0, 1, 2, 3); + let r = _mm_maskz_expand_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_expand_epi32(0b00000101, a); + let e = _mm_set_epi32(0, 2, 0, 3); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_expand_ps() { let src = _mm512_set1_ps(200.); let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + let r = _mm512_mask_expand_ps(src, 0, a); + assert_eq_m512(r, src); let r = _mm512_mask_expand_ps(src, 0b01010101_01010101, a); let e = _mm512_set_ps( 200., 8., 200., 9., 200., 10., 200., 11., 200., 12., 200., 13., 200., 14., 200., 15., @@ -33928,6 +51882,8 @@ mod tests { let a = _mm512_set_ps( 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., ); + let r = _mm512_maskz_expand_ps(0, a); + assert_eq_m512(r, _mm512_setzero_ps()); let r = _mm512_maskz_expand_ps(0b01010101_01010101, a); let e = _mm512_set_ps( 0., 8., 0., 9., 0., 10., 0., 11., 0., 12., 0., 13., 0., 14., 0., 15., @@ -33935,6 +51891,48 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_expand_ps() { + let src = _mm256_set1_ps(200.); + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_mask_expand_ps(src, 0, a); + assert_eq_m256(r, src); + let r = _mm256_mask_expand_ps(src, 0b01010101, a); + let e = _mm256_set_ps(200., 4., 200., 5., 200., 6., 200., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_expand_ps() { + let a = _mm256_set_ps(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm256_maskz_expand_ps(0, a); + assert_eq_m256(r, _mm256_setzero_ps()); + let r = _mm256_maskz_expand_ps(0b01010101, a); + let e = _mm256_set_ps(0., 4., 0., 5., 0., 6., 0., 7.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_expand_ps() { + let src = _mm_set1_ps(200.); + let a = _mm_set_ps(0., 1., 2., 3.); + let r = _mm_mask_expand_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm_mask_expand_ps(src, 0b00000101, a); + let e = _mm_set_ps(200., 2., 200., 3.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_expand_ps() { + let a = _mm_set_ps(0., 1., 2., 3.); + let r = _mm_maskz_expand_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_expand_ps(0b00000101, a); + let e = _mm_set_ps(0., 2., 0., 3.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_loadu_epi32() { let a = &[4, 3, 2, 5, 8, 9, 64, 50, -4, -3, -2, -5, -8, -9, -64, -50]; @@ -33944,6 +51942,219 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_loadu_epi32() { + let a = &[4, 3, 2, 5, 8, 9, 64, 50]; + let p = a.as_ptr(); + let r = _mm256_loadu_epi32(black_box(p)); + let e = _mm256_setr_epi32(4, 3, 2, 5, 8, 9, 64, 50); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_loadu_epi32() { + let a = &[4, 3, 2, 5]; + let p = a.as_ptr(); + let r = _mm_loadu_epi32(black_box(p)); + let e = _mm_setr_epi32(4, 3, 2, 5); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtepi32_storeu_epi16() { + let a = _mm512_set1_epi32(9); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm256_set1_epi16(9); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi32_storeu_epi16() { + let a = _mm256_set1_epi32(9); + let mut r = _mm_undefined_si128(); + _mm256_mask_cvtepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set1_epi16(9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi32_storeu_epi16() { + let a = _mm_set1_epi32(9); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 9, 9, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtsepi32_storeu_epi16() { + let a = _mm512_set1_epi32(i32::MAX); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtsepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm256_set1_epi16(i16::MAX); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi32_storeu_epi16() { + let a = _mm256_set1_epi32(i32::MAX); + let mut r = _mm_undefined_si128(); + _mm256_mask_cvtsepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set1_epi16(i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi32_storeu_epi16() { + let a = _mm_set1_epi32(i32::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtsepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, i16::MAX, i16::MAX, i16::MAX, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtusepi32_storeu_epi16() { + let a = _mm512_set1_epi32(i32::MAX); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtusepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm256_set1_epi16(u16::MAX as i16); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi32_storeu_epi16() { + let a = _mm256_set1_epi32(i32::MAX); + let mut r = _mm_undefined_si128(); + _mm256_mask_cvtusepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set1_epi16(u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi32_storeu_epi16() { + let a = _mm_set1_epi32(i32::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtusepi32_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16( + 0, + 0, + 0, + 0, + u16::MAX as i16, + u16::MAX as i16, + u16::MAX as i16, + u16::MAX as i16, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtepi32_storeu_epi8() { + let a = _mm512_set1_epi32(9); + let mut r = _mm_undefined_si128(); + _mm512_mask_cvtepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm_set1_epi8(9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi32_storeu_epi8() { + let a = _mm256_set1_epi32(9); + let mut r = _mm_set1_epi8(0); + _mm256_mask_cvtepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi32_storeu_epi8() { + let a = _mm_set1_epi32(9); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtsepi32_storeu_epi8() { + let a = _mm512_set1_epi32(i32::MAX); + let mut r = _mm_undefined_si128(); + _mm512_mask_cvtsepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm_set1_epi8(i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi32_storeu_epi8() { + let a = _mm256_set1_epi32(i32::MAX); + let mut r = _mm_set1_epi8(0); + _mm256_mask_cvtsepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + i8::MAX, i8::MAX, i8::MAX, i8::MAX, + i8::MAX, i8::MAX, i8::MAX, i8::MAX, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi32_storeu_epi8() { + let a = _mm_set1_epi32(i32::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtsepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + i8::MAX, i8::MAX, i8::MAX, i8::MAX, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtusepi32_storeu_epi8() { + let a = _mm512_set1_epi32(i32::MAX); + let mut r = _mm_undefined_si128(); + _mm512_mask_cvtusepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111_11111111, a); + let e = _mm_set1_epi8(u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi32_storeu_epi8() { + let a = _mm256_set1_epi32(i32::MAX); + let mut r = _mm_set1_epi8(0); + _mm256_mask_cvtusepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi32_storeu_epi8() { + let a = _mm_set1_epi32(i32::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtusepi32_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + ); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_storeu_epi32() { let a = _mm512_set1_epi32(9); @@ -33952,6 +52163,22 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_storeu_epi32() { + let a = _mm256_set1_epi32(9); + let mut r = _mm256_undefined_si256(); + _mm256_storeu_epi32(&mut r as *mut _ as *mut i32, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_storeu_epi32() { + let a = _mm_set1_epi32(9); + let mut r = _mm_undefined_si128(); + _mm_storeu_epi32(&mut r as *mut _ as *mut i32, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_loadu_si512() { let a = &[4, 3, 2, 5, 8, 9, 64, 50, -4, -3, -2, -5, -8, -9, -64, -50]; @@ -34007,6 +52234,34 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_load_epi32() { + #[repr(align(64))] + struct Align { + data: [i32; 8], + } + let a = Align { + data: [4, 3, 2, 5, 8, 9, 64, 50], + }; + let p = (a.data).as_ptr(); + let r = _mm256_load_epi32(black_box(p)); + let e = _mm256_setr_epi32(4, 3, 2, 5, 8, 9, 64, 50); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_load_epi32() { + #[repr(align(64))] + struct Align { + data: [i32; 4], + } + let a = Align { data: [4, 3, 2, 5] }; + let p = (a.data).as_ptr(); + let r = _mm_load_epi32(black_box(p)); + let e = _mm_setr_epi32(4, 3, 2, 5); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_store_epi32() { let a = _mm512_set1_epi32(9); @@ -34015,6 +52270,22 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_store_epi32() { + let a = _mm256_set1_epi32(9); + let mut r = _mm256_undefined_si256(); + _mm256_store_epi32(&mut r as *mut _ as *mut i32, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_store_epi32() { + let a = _mm_set1_epi32(9); + let mut r = _mm_undefined_si128(); + _mm_store_epi32(&mut r as *mut _ as *mut i32, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_load_ps() { #[repr(align(64))] @@ -34063,6 +52334,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_set1_epi32() { + let src = _mm256_set1_epi32(2); + let a: i32 = 11; + let r = _mm256_mask_set1_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_set1_epi32(src, 0b11111111, a); + let e = _mm256_set1_epi32(11); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm256_maskz_set1_epi32() { + let a: i32 = 11; + let r = _mm256_maskz_set1_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_set1_epi32(0b11111111, a); + let e = _mm256_set1_epi32(11); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_set1_epi32() { + let src = _mm_set1_epi32(2); + let a: i32 = 11; + let r = _mm_mask_set1_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_set1_epi32(src, 0b00001111, a); + let e = _mm_set1_epi32(11); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_maskz_set1_epi32() { + let a: i32 = 11; + let r = _mm_maskz_set1_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_set1_epi32(0b00001111, a); + let e = _mm_set1_epi32(11); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm_mask_move_ss() { let src = _mm_set_ps(10., 11., 100., 110.); @@ -37039,24 +55352,6 @@ mod tests { assert_eq_m128d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm_cvtu64_ss() { - let a = _mm_set_ps(0., -0.5, 1., -1.5); - let b: u64 = 9; - let r = _mm_cvtu64_ss(a, b); - let e = _mm_set_ps(0., -0.5, 1., 9.); - assert_eq_m128(r, e); - } - - #[simd_test(enable = "avx512f")] - unsafe fn test_mm_cvtu64_sd() { - let a = _mm_set_pd(1., -1.5); - let b: u64 = 9; - let r = _mm_cvtu64_sd(a, b); - let e = _mm_set_pd(1., 9.); - assert_eq_m128d(r, e); - } - #[simd_test(enable = "avx512f")] unsafe fn test_mm_comi_round_ss() { let a = _mm_set1_ps(2.2); @@ -37074,4 +55369,12 @@ mod tests { let e: i32 = 0; assert_eq!(r, e); } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_cvtsi512_si32() { + let a = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let r = _mm512_cvtsi512_si32(a); + let e: i32 = 1; + assert_eq!(r, e); + } } diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs b/library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs new file mode 100644 index 0000000000..f0ff75162f --- /dev/null +++ b/library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs @@ -0,0 +1,916 @@ +use crate::core_arch::{simd::*, simd_llvm::*, x86::*}; + +#[cfg(test)] +use stdarch_test::assert_instr; + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_epi8&expand=4262) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2b +pub unsafe fn _mm512_permutex2var_epi8(a: __m512i, idx: __m512i, b: __m512i) -> __m512i { + transmute(vpermi2b(a.as_i8x64(), idx.as_i8x64(), b.as_i8x64())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex2var_epi8&expand=4259) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpermt2b))] +pub unsafe fn _mm512_mask_permutex2var_epi8( + a: __m512i, + k: __mmask64, + idx: __m512i, + b: __m512i, +) -> __m512i { + let permute = _mm512_permutex2var_epi8(a, idx, b).as_i8x64(); + transmute(simd_select_bitmask(k, permute, a.as_i8x64())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex2var_epi8&expand=4261) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2b +pub unsafe fn _mm512_maskz_permutex2var_epi8( + k: __mmask64, + a: __m512i, + idx: __m512i, + b: __m512i, +) -> __m512i { + let permute = _mm512_permutex2var_epi8(a, idx, b).as_i8x64(); + let zero = _mm512_setzero_si512().as_i8x64(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask2_permutex2var_epi8&expand=4260) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpermi2b))] +pub unsafe fn _mm512_mask2_permutex2var_epi8( + a: __m512i, + idx: __m512i, + k: __mmask64, + b: __m512i, +) -> __m512i { + let permute = _mm512_permutex2var_epi8(a, idx, b).as_i8x64(); + transmute(simd_select_bitmask(k, permute, idx.as_i8x64())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex2var_epi8&expand=4258) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2b +pub unsafe fn _mm256_permutex2var_epi8(a: __m256i, idx: __m256i, b: __m256i) -> __m256i { + transmute(vpermi2b256(a.as_i8x32(), idx.as_i8x32(), b.as_i8x32())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex2var_epi8&expand=4255) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2b))] +pub unsafe fn _mm256_mask_permutex2var_epi8( + a: __m256i, + k: __mmask32, + idx: __m256i, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi8(a, idx, b).as_i8x32(); + transmute(simd_select_bitmask(k, permute, a.as_i8x32())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex2var_epi8&expand=4257) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2b +pub unsafe fn _mm256_maskz_permutex2var_epi8( + k: __mmask32, + a: __m256i, + idx: __m256i, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi8(a, idx, b).as_i8x32(); + let zero = _mm256_setzero_si256().as_i8x32(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask2_permutex2var_epi8&expand=4256) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermi2b))] +pub unsafe fn _mm256_mask2_permutex2var_epi8( + a: __m256i, + idx: __m256i, + k: __mmask32, + b: __m256i, +) -> __m256i { + let permute = _mm256_permutex2var_epi8(a, idx, b).as_i8x32(); + transmute(simd_select_bitmask(k, permute, idx.as_i8x32())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutex2var_epi8&expand=4254) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2b +pub unsafe fn _mm_permutex2var_epi8(a: __m128i, idx: __m128i, b: __m128i) -> __m128i { + transmute(vpermi2b128(a.as_i8x16(), idx.as_i8x16(), b.as_i8x16())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutex2var_epi8&expand=4251) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermt2b))] +pub unsafe fn _mm_mask_permutex2var_epi8( + a: __m128i, + k: __mmask16, + idx: __m128i, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi8(a, idx, b).as_i8x16(); + transmute(simd_select_bitmask(k, permute, a.as_i8x16())) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutex2var_epi8&expand=4253) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vperm))] //should be vpermi2b +pub unsafe fn _mm_maskz_permutex2var_epi8( + k: __mmask16, + a: __m128i, + idx: __m128i, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi8(a, idx, b).as_i8x16(); + let zero = _mm_setzero_si128().as_i8x16(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 8-bit integers in a and b across lanes using the corresponding selector and index in idx, and store the results in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask2_permutex2var_epi8&expand=4252) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermi2b))] +pub unsafe fn _mm_mask2_permutex2var_epi8( + a: __m128i, + idx: __m128i, + k: __mmask16, + b: __m128i, +) -> __m128i { + let permute = _mm_permutex2var_epi8(a, idx, b).as_i8x16(); + transmute(simd_select_bitmask(k, permute, idx.as_i8x16())) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_epi8&expand=4316) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm512_permutexvar_epi8(idx: __m512i, a: __m512i) -> __m512i { + transmute(vpermb(a.as_i8x64(), idx.as_i8x64())) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutexvar_epi8&expand=4314) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm512_mask_permutexvar_epi8( + src: __m512i, + k: __mmask64, + idx: __m512i, + a: __m512i, +) -> __m512i { + let permute = _mm512_permutexvar_epi8(idx, a).as_i8x64(); + transmute(simd_select_bitmask(k, permute, src.as_i8x64())) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutexvar_epi8&expand=4315) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm512_maskz_permutexvar_epi8(k: __mmask64, idx: __m512i, a: __m512i) -> __m512i { + let permute = _mm512_permutexvar_epi8(idx, a).as_i8x64(); + let zero = _mm512_setzero_si512().as_i8x64(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutexvar_epi8&expand=4313) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm256_permutexvar_epi8(idx: __m256i, a: __m256i) -> __m256i { + transmute(vpermb256(a.as_i8x32(), idx.as_i8x32())) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutexvar_epi8&expand=4311) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm256_mask_permutexvar_epi8( + src: __m256i, + k: __mmask32, + idx: __m256i, + a: __m256i, +) -> __m256i { + let permute = _mm256_permutexvar_epi8(idx, a).as_i8x32(); + transmute(simd_select_bitmask(k, permute, src.as_i8x32())) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutexvar_epi8&expand=4312) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm256_maskz_permutexvar_epi8(k: __mmask32, idx: __m256i, a: __m256i) -> __m256i { + let permute = _mm256_permutexvar_epi8(idx, a).as_i8x32(); + let zero = _mm256_setzero_si256().as_i8x32(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutexvar_epi8&expand=4310) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm_permutexvar_epi8(idx: __m128i, a: __m128i) -> __m128i { + transmute(vpermb128(a.as_i8x16(), idx.as_i8x16())) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_permutexvar_epi8&expand=4308) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm_mask_permutexvar_epi8( + src: __m128i, + k: __mmask16, + idx: __m128i, + a: __m128i, +) -> __m128i { + let permute = _mm_permutexvar_epi8(idx, a).as_i8x16(); + transmute(simd_select_bitmask(k, permute, src.as_i8x16())) +} + +/// Shuffle 8-bit integers in a across lanes using the corresponding index in idx, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_permutexvar_epi8&expand=4309) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpermb))] +pub unsafe fn _mm_maskz_permutexvar_epi8(k: __mmask16, idx: __m128i, a: __m128i) -> __m128i { + let permute = _mm_permutexvar_epi8(idx, a).as_i8x16(); + let zero = _mm_setzero_si128().as_i8x16(); + transmute(simd_select_bitmask(k, permute, zero)) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_multishift_epi64_epi8&expand=4026) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm512_multishift_epi64_epi8(a: __m512i, b: __m512i) -> __m512i { + transmute(vpmultishiftqb(a.as_i8x64(), b.as_i8x64())) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_multishift_epi64_epi8&expand=4024) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm512_mask_multishift_epi64_epi8( + src: __m512i, + k: __mmask64, + a: __m512i, + b: __m512i, +) -> __m512i { + let multishift = _mm512_multishift_epi64_epi8(a, b).as_i8x64(); + transmute(simd_select_bitmask(k, multishift, src.as_i8x64())) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_multishift_epi64_epi8&expand=4025) +#[inline] +#[target_feature(enable = "avx512vbmi")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm512_maskz_multishift_epi64_epi8(k: __mmask64, a: __m512i, b: __m512i) -> __m512i { + let multishift = _mm512_multishift_epi64_epi8(a, b).as_i8x64(); + let zero = _mm512_setzero_si512().as_i8x64(); + transmute(simd_select_bitmask(k, multishift, zero)) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_multishift_epi64_epi8&expand=4023) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm256_multishift_epi64_epi8(a: __m256i, b: __m256i) -> __m256i { + transmute(vpmultishiftqb256(a.as_i8x32(), b.as_i8x32())) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_multishift_epi64_epi8&expand=4021) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm256_mask_multishift_epi64_epi8( + src: __m256i, + k: __mmask32, + a: __m256i, + b: __m256i, +) -> __m256i { + let multishift = _mm256_multishift_epi64_epi8(a, b).as_i8x32(); + transmute(simd_select_bitmask(k, multishift, src.as_i8x32())) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_multishift_epi64_epi8&expand=4022) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm256_maskz_multishift_epi64_epi8(k: __mmask32, a: __m256i, b: __m256i) -> __m256i { + let multishift = _mm256_multishift_epi64_epi8(a, b).as_i8x32(); + let zero = _mm256_setzero_si256().as_i8x32(); + transmute(simd_select_bitmask(k, multishift, zero)) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/IntrinsicsGuide/#text=_mm_multishift_epi64_epi8&expand=4020) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm_multishift_epi64_epi8(a: __m128i, b: __m128i) -> __m128i { + transmute(vpmultishiftqb128(a.as_i8x16(), b.as_i8x16())) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_multishift_epi64_epi8&expand=4018) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm_mask_multishift_epi64_epi8( + src: __m128i, + k: __mmask16, + a: __m128i, + b: __m128i, +) -> __m128i { + let multishift = _mm_multishift_epi64_epi8(a, b).as_i8x16(); + transmute(simd_select_bitmask(k, multishift, src.as_i8x16())) +} + +/// For each 64-bit element in b, select 8 unaligned bytes using a byte-granular shift control within the corresponding 64-bit element of a, and store the 8 assembled bytes to the corresponding 64-bit element of dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_multishift_epi64_epi8&expand=4019) +#[inline] +#[target_feature(enable = "avx512vbmi,avx512vl")] +#[cfg_attr(test, assert_instr(vpmultishiftqb))] +pub unsafe fn _mm_maskz_multishift_epi64_epi8(k: __mmask16, a: __m128i, b: __m128i) -> __m128i { + let multishift = _mm_multishift_epi64_epi8(a, b).as_i8x16(); + let zero = _mm_setzero_si128().as_i8x16(); + transmute(simd_select_bitmask(k, multishift, zero)) +} + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.x86.avx512.vpermi2var.qi.512"] + fn vpermi2b(a: i8x64, idx: i8x64, b: i8x64) -> i8x64; + #[link_name = "llvm.x86.avx512.vpermi2var.qi.256"] + fn vpermi2b256(a: i8x32, idx: i8x32, b: i8x32) -> i8x32; + #[link_name = "llvm.x86.avx512.vpermi2var.qi.128"] + fn vpermi2b128(a: i8x16, idx: i8x16, b: i8x16) -> i8x16; + + #[link_name = "llvm.x86.avx512.permvar.qi.512"] + fn vpermb(a: i8x64, idx: i8x64) -> i8x64; + #[link_name = "llvm.x86.avx512.permvar.qi.256"] + fn vpermb256(a: i8x32, idx: i8x32) -> i8x32; + #[link_name = "llvm.x86.avx512.permvar.qi.128"] + fn vpermb128(a: i8x16, idx: i8x16) -> i8x16; + + #[link_name = "llvm.x86.avx512.pmultishift.qb.512"] + fn vpmultishiftqb(a: i8x64, b: i8x64) -> i8x64; + #[link_name = "llvm.x86.avx512.pmultishift.qb.256"] + fn vpmultishiftqb256(a: i8x32, b: i8x32) -> i8x32; + #[link_name = "llvm.x86.avx512.pmultishift.qb.128"] + fn vpmultishiftqb128(a: i8x16, b: i8x16) -> i8x16; +} + +#[cfg(test)] +mod tests { + + use stdarch_test::simd_test; + + use crate::core_arch::x86::*; + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + #[rustfmt::skip] + let idx = _mm512_set_epi8(1, 1<<6, 2, 1<<6, 3, 1<<6, 4, 1<<6, 5, 1<<6, 6, 1<<6, 7, 1<<6, 8, 1<<6, + 9, 1<<6, 10, 1<<6, 11, 1<<6, 12, 1<<6, 13, 1<<6, 14, 1<<6, 15, 1<<6, 16, 1<<6, + 17, 1<<6, 18, 1<<6, 19, 1<<6, 20, 1<<6, 21, 1<<6, 22, 1<<6, 23, 1<<6, 24, 1<<6, + 25, 1<<6, 26, 1<<6, 27, 1<<6, 28, 1<<6, 29, 1<<6, 30, 1<<6, 31, 1<<6, 32, 1<<6); + let b = _mm512_set1_epi8(100); + let r = _mm512_permutex2var_epi8(a, idx, b); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 62, 100, 61, 100, 60, 100, 59, 100, 58, 100, 57, 100, 56, 100, 55, 100, + 54, 100, 53, 100, 52, 100, 51, 100, 50, 100, 49, 100, 48, 100, 47, 100, + 46, 100, 45, 100, 44, 100, 43, 100, 42, 100, 41, 100, 40, 100, 39, 100, + 38, 100, 37, 100, 36, 100, 35, 100, 34, 100, 33, 100, 32, 100, 31, 100, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_mask_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + #[rustfmt::skip] + let idx = _mm512_set_epi8(1, 1<<6, 2, 1<<6, 3, 1<<6, 4, 1<<6, 5, 1<<6, 6, 1<<6, 7, 1<<6, 8, 1<<6, + 9, 1<<6, 10, 1<<6, 11, 1<<6, 12, 1<<6, 13, 1<<6, 14, 1<<6, 15, 1<<6, 16, 1<<6, + 17, 1<<6, 18, 1<<6, 19, 1<<6, 20, 1<<6, 21, 1<<6, 22, 1<<6, 23, 1<<6, 24, 1<<6, + 25, 1<<6, 26, 1<<6, 27, 1<<6, 28, 1<<6, 29, 1<<6, 30, 1<<6, 31, 1<<6, 32, 1<<6); + let b = _mm512_set1_epi8(100); + let r = _mm512_mask_permutex2var_epi8(a, 0, idx, b); + assert_eq_m512i(r, a); + let r = _mm512_mask_permutex2var_epi8( + a, + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + idx, + b, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 62, 100, 61, 100, 60, 100, 59, 100, 58, 100, 57, 100, 56, 100, 55, 100, + 54, 100, 53, 100, 52, 100, 51, 100, 50, 100, 49, 100, 48, 100, 47, 100, + 46, 100, 45, 100, 44, 100, 43, 100, 42, 100, 41, 100, 40, 100, 39, 100, + 38, 100, 37, 100, 36, 100, 35, 100, 34, 100, 33, 100, 32, 100, 31, 100, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_maskz_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + #[rustfmt::skip] + let idx = _mm512_set_epi8(1, 1<<6, 2, 1<<6, 3, 1<<6, 4, 1<<6, 5, 1<<6, 6, 1<<6, 7, 1<<6, 8, 1<<6, + 9, 1<<6, 10, 1<<6, 11, 1<<6, 12, 1<<6, 13, 1<<6, 14, 1<<6, 15, 1<<6, 16, 1<<6, + 17, 1<<6, 18, 1<<6, 19, 1<<6, 20, 1<<6, 21, 1<<6, 22, 1<<6, 23, 1<<6, 24, 1<<6, + 25, 1<<6, 26, 1<<6, 27, 1<<6, 28, 1<<6, 29, 1<<6, 30, 1<<6, 31, 1<<6, 32, 1<<6); + let b = _mm512_set1_epi8(100); + let r = _mm512_maskz_permutex2var_epi8(0, a, idx, b); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_permutex2var_epi8( + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + a, + idx, + b, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 62, 100, 61, 100, 60, 100, 59, 100, 58, 100, 57, 100, 56, 100, 55, 100, + 54, 100, 53, 100, 52, 100, 51, 100, 50, 100, 49, 100, 48, 100, 47, 100, + 46, 100, 45, 100, 44, 100, 43, 100, 42, 100, 41, 100, 40, 100, 39, 100, + 38, 100, 37, 100, 36, 100, 35, 100, 34, 100, 33, 100, 32, 100, 31, 100, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_mask2_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + #[rustfmt::skip] + let idx = _mm512_set_epi8(1, 1<<6, 2, 1<<6, 3, 1<<6, 4, 1<<6, 5, 1<<6, 6, 1<<6, 7, 1<<6, 8, 1<<6, + 9, 1<<6, 10, 1<<6, 11, 1<<6, 12, 1<<6, 13, 1<<6, 14, 1<<6, 15, 1<<6, 16, 1<<6, + 17, 1<<6, 18, 1<<6, 19, 1<<6, 20, 1<<6, 21, 1<<6, 22, 1<<6, 23, 1<<6, 24, 1<<6, + 25, 1<<6, 26, 1<<6, 27, 1<<6, 28, 1<<6, 29, 1<<6, 30, 1<<6, 31, 1<<6, 32, 1<<6); + let b = _mm512_set1_epi8(100); + let r = _mm512_mask2_permutex2var_epi8(a, idx, 0, b); + assert_eq_m512i(r, idx); + let r = _mm512_mask2_permutex2var_epi8( + a, + idx, + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + b, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 62, 100, 61, 100, 60, 100, 59, 100, 58, 100, 57, 100, 56, 100, 55, 100, + 54, 100, 53, 100, 52, 100, 51, 100, 50, 100, 49, 100, 48, 100, 47, 100, + 46, 100, 45, 100, 44, 100, 43, 100, 42, 100, 41, 100, 40, 100, 39, 100, + 38, 100, 37, 100, 36, 100, 35, 100, 34, 100, 33, 100, 32, 100, 31, 100, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + #[rustfmt::skip] + let idx = _mm256_set_epi8(1, 1<<5, 2, 1<<5, 3, 1<<5, 4, 1<<5, 5, 1<<5, 6, 1<<5, 7, 1<<5, 8, 1<<5, + 9, 1<<5, 10, 1<<5, 11, 1<<5, 12, 1<<5, 13, 1<<5, 14, 1<<5, 15, 1<<5, 16, 1<<5); + let b = _mm256_set1_epi8(100); + let r = _mm256_permutex2var_epi8(a, idx, b); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 30, 100, 29, 100, 28, 100, 27, 100, 26, 100, 25, 100, 24, 100, 23, 100, + 22, 100, 21, 100, 20, 100, 19, 100, 18, 100, 17, 100, 16, 100, 15, 100, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_mask_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + #[rustfmt::skip] + let idx = _mm256_set_epi8(1, 1<<5, 2, 1<<5, 3, 1<<5, 4, 1<<5, 5, 1<<5, 6, 1<<5, 7, 1<<5, 8, 1<<5, + 9, 1<<5, 10, 1<<5, 11, 1<<5, 12, 1<<5, 13, 1<<5, 14, 1<<5, 15, 1<<5, 16, 1<<5); + let b = _mm256_set1_epi8(100); + let r = _mm256_mask_permutex2var_epi8(a, 0, idx, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_permutex2var_epi8(a, 0b11111111_11111111_11111111_11111111, idx, b); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 30, 100, 29, 100, 28, 100, 27, 100, 26, 100, 25, 100, 24, 100, 23, 100, + 22, 100, 21, 100, 20, 100, 19, 100, 18, 100, 17, 100, 16, 100, 15, 100, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_maskz_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + #[rustfmt::skip] + let idx = _mm256_set_epi8(1, 1<<5, 2, 1<<5, 3, 1<<5, 4, 1<<5, 5, 1<<5, 6, 1<<5, 7, 1<<5, 8, 1<<5, + 9, 1<<5, 10, 1<<5, 11, 1<<5, 12, 1<<5, 13, 1<<5, 14, 1<<5, 15, 1<<5, 16, 1<<5); + let b = _mm256_set1_epi8(100); + let r = _mm256_maskz_permutex2var_epi8(0, a, idx, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_permutex2var_epi8(0b11111111_11111111_11111111_11111111, a, idx, b); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 30, 100, 29, 100, 28, 100, 27, 100, 26, 100, 25, 100, 24, 100, 23, 100, + 22, 100, 21, 100, 20, 100, 19, 100, 18, 100, 17, 100, 16, 100, 15, 100, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_mask2_permutex2var_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + #[rustfmt::skip] + let idx = _mm256_set_epi8(1, 1<<5, 2, 1<<5, 3, 1<<5, 4, 1<<5, 5, 1<<5, 6, 1<<5, 7, 1<<5, 8, 1<<5, + 9, 1<<5, 10, 1<<5, 11, 1<<5, 12, 1<<5, 13, 1<<5, 14, 1<<5, 15, 1<<5, 16, 1<<5); + let b = _mm256_set1_epi8(100); + let r = _mm256_mask2_permutex2var_epi8(a, idx, 0, b); + assert_eq_m256i(r, idx); + let r = _mm256_mask2_permutex2var_epi8(a, idx, 0b11111111_11111111_11111111_11111111, b); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 30, 100, 29, 100, 28, 100, 27, 100, 26, 100, 25, 100, 24, 100, 23, 100, + 22, 100, 21, 100, 20, 100, 19, 100, 18, 100, 17, 100, 16, 100, 15, 100, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_permutex2var_epi8() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] + let idx = _mm_set_epi8(1, 1 << 4, 2, 1 << 4, 3, 1 << 4, 4, 1 << 4, 5, 1 << 4, 6, 1 << 4, 7, 1 << 4, 8, 1 << 4); + let b = _mm_set1_epi8(100); + let r = _mm_permutex2var_epi8(a, idx, b); + let e = _mm_set_epi8( + 14, 100, 13, 100, 12, 100, 11, 100, 10, 100, 9, 100, 8, 100, 7, 100, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_mask_permutex2var_epi8() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] + let idx = _mm_set_epi8(1, 1 << 4, 2, 1 << 4, 3, 1 << 4, 4, 1 << 4, 5, 1 << 4, 6, 1 << 4, 7, 1 << 4, 8, 1 << 4); + let b = _mm_set1_epi8(100); + let r = _mm_mask_permutex2var_epi8(a, 0, idx, b); + assert_eq_m128i(r, a); + let r = _mm_mask_permutex2var_epi8(a, 0b11111111_11111111, idx, b); + let e = _mm_set_epi8( + 14, 100, 13, 100, 12, 100, 11, 100, 10, 100, 9, 100, 8, 100, 7, 100, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_maskz_permutex2var_epi8() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] + let idx = _mm_set_epi8(1, 1 << 4, 2, 1 << 4, 3, 1 << 4, 4, 1 << 4, 5, 1 << 4, 6, 1 << 4, 7, 1 << 4, 8, 1 << 4); + let b = _mm_set1_epi8(100); + let r = _mm_maskz_permutex2var_epi8(0, a, idx, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_permutex2var_epi8(0b11111111_11111111, a, idx, b); + let e = _mm_set_epi8( + 14, 100, 13, 100, 12, 100, 11, 100, 10, 100, 9, 100, 8, 100, 7, 100, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_mask2_permutex2var_epi8() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] + let idx = _mm_set_epi8(1, 1 << 4, 2, 1 << 4, 3, 1 << 4, 4, 1 << 4, 5, 1 << 4, 6, 1 << 4, 7, 1 << 4, 8, 1 << 4); + let b = _mm_set1_epi8(100); + let r = _mm_mask2_permutex2var_epi8(a, idx, 0, b); + assert_eq_m128i(r, idx); + let r = _mm_mask2_permutex2var_epi8(a, idx, 0b11111111_11111111, b); + let e = _mm_set_epi8( + 14, 100, 13, 100, 12, 100, 11, 100, 10, 100, 9, 100, 8, 100, 7, 100, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_permutexvar_epi8() { + let idx = _mm512_set1_epi8(1); + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let r = _mm512_permutexvar_epi8(idx, a); + let e = _mm512_set1_epi8(62); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_mask_permutexvar_epi8() { + let idx = _mm512_set1_epi8(1); + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let r = _mm512_mask_permutexvar_epi8(a, 0, idx, a); + assert_eq_m512i(r, a); + let r = _mm512_mask_permutexvar_epi8( + a, + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + idx, + a, + ); + let e = _mm512_set1_epi8(62); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_maskz_permutexvar_epi8() { + let idx = _mm512_set1_epi8(1); + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let r = _mm512_maskz_permutexvar_epi8(0, idx, a); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_permutexvar_epi8( + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + idx, + a, + ); + let e = _mm512_set1_epi8(62); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_permutexvar_epi8() { + let idx = _mm256_set1_epi8(1); + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm256_permutexvar_epi8(idx, a); + let e = _mm256_set1_epi8(30); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_mask_permutexvar_epi8() { + let idx = _mm256_set1_epi8(1); + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm256_mask_permutexvar_epi8(a, 0, idx, a); + assert_eq_m256i(r, a); + let r = _mm256_mask_permutexvar_epi8(a, 0b11111111_11111111_11111111_11111111, idx, a); + let e = _mm256_set1_epi8(30); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_maskz_permutexvar_epi8() { + let idx = _mm256_set1_epi8(1); + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm256_maskz_permutexvar_epi8(0, idx, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_permutexvar_epi8(0b11111111_11111111_11111111_11111111, idx, a); + let e = _mm256_set1_epi8(30); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_permutexvar_epi8() { + let idx = _mm_set1_epi8(1); + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_permutexvar_epi8(idx, a); + let e = _mm_set1_epi8(14); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_mask_permutexvar_epi8() { + let idx = _mm_set1_epi8(1); + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_mask_permutexvar_epi8(a, 0, idx, a); + assert_eq_m128i(r, a); + let r = _mm_mask_permutexvar_epi8(a, 0b11111111_11111111, idx, a); + let e = _mm_set1_epi8(14); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_maskz_permutexvar_epi8() { + let idx = _mm_set1_epi8(1); + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_permutexvar_epi8(0, idx, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_permutexvar_epi8(0b11111111_11111111, idx, a); + let e = _mm_set1_epi8(14); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_multishift_epi64_epi8() { + let a = _mm512_set1_epi8(1); + let b = _mm512_set1_epi8(1); + let r = _mm512_multishift_epi64_epi8(a, b); + let e = _mm512_set1_epi8(1 << 7); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_mask_multishift_epi64_epi8() { + let a = _mm512_set1_epi8(1); + let b = _mm512_set1_epi8(1); + let r = _mm512_mask_multishift_epi64_epi8(a, 0, a, b); + assert_eq_m512i(r, a); + let r = _mm512_mask_multishift_epi64_epi8( + a, + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + a, + b, + ); + let e = _mm512_set1_epi8(1 << 7); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi")] + unsafe fn test_mm512_maskz_multishift_epi64_epi8() { + let a = _mm512_set1_epi8(1); + let b = _mm512_set1_epi8(1); + let r = _mm512_maskz_multishift_epi64_epi8(0, a, b); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_multishift_epi64_epi8( + 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111, + a, + b, + ); + let e = _mm512_set1_epi8(1 << 7); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_multishift_epi64_epi8() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(1); + let r = _mm256_multishift_epi64_epi8(a, b); + let e = _mm256_set1_epi8(1 << 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_mask_multishift_epi64_epi8() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(1); + let r = _mm256_mask_multishift_epi64_epi8(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_multishift_epi64_epi8(a, 0b11111111_11111111_11111111_11111111, a, b); + let e = _mm256_set1_epi8(1 << 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm256_maskz_multishift_epi64_epi8() { + let a = _mm256_set1_epi8(1); + let b = _mm256_set1_epi8(1); + let r = _mm256_maskz_multishift_epi64_epi8(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_multishift_epi64_epi8(0b11111111_11111111_11111111_11111111, a, b); + let e = _mm256_set1_epi8(1 << 7); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_multishift_epi64_epi8() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(1); + let r = _mm_multishift_epi64_epi8(a, b); + let e = _mm_set1_epi8(1 << 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_mask_multishift_epi64_epi8() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(1); + let r = _mm_mask_multishift_epi64_epi8(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_multishift_epi64_epi8(a, 0b11111111_11111111, a, b); + let e = _mm_set1_epi8(1 << 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi,avx512vl")] + unsafe fn test_mm_maskz_multishift_epi64_epi8() { + let a = _mm_set1_epi8(1); + let b = _mm_set1_epi8(1); + let r = _mm_maskz_multishift_epi64_epi8(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_multishift_epi64_epi8(0b11111111_11111111, a, b); + let e = _mm_set1_epi8(1 << 7); + assert_eq_m128i(r, e); + } +} diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs b/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs new file mode 100644 index 0000000000..032bce9176 --- /dev/null +++ b/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs @@ -0,0 +1,3477 @@ +use crate::core_arch::{simd::*, simd_llvm::*, x86::*}; + +#[cfg(test)] +use stdarch_test::assert_instr; + +/// Contiguously store the active 16-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_epi16&expand=1192) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpcompressw))] +pub unsafe fn _mm512_mask_compress_epi16(src: __m512i, k: __mmask32, a: __m512i) -> __m512i { + transmute(vpcompressw(a.as_i16x32(), src.as_i16x32(), k)) +} + +/// Contiguously store the active 16-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_epi16&expand=1193) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpcompressw))] +pub unsafe fn _mm512_maskz_compress_epi16(k: __mmask32, a: __m512i) -> __m512i { + transmute(vpcompressw( + a.as_i16x32(), + _mm512_setzero_si512().as_i16x32(), + k, + )) +} + +/// Contiguously store the active 16-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_compress_epi16&expand=1190) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressw))] +pub unsafe fn _mm256_mask_compress_epi16(src: __m256i, k: __mmask16, a: __m256i) -> __m256i { + transmute(vpcompressw256(a.as_i16x16(), src.as_i16x16(), k)) +} + +/// Contiguously store the active 16-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_compress_epi16&expand=1191) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressw))] +pub unsafe fn _mm256_maskz_compress_epi16(k: __mmask16, a: __m256i) -> __m256i { + transmute(vpcompressw256( + a.as_i16x16(), + _mm256_setzero_si256().as_i16x16(), + k, + )) +} + +/// Contiguously store the active 16-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_compress_epi16&expand=1188) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressw))] +pub unsafe fn _mm_mask_compress_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpcompressw128(a.as_i16x8(), src.as_i16x8(), k)) +} + +/// Contiguously store the active 16-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_compress_epi16&expand=1189) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressw))] +pub unsafe fn _mm_maskz_compress_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpcompressw128( + a.as_i16x8(), + _mm_setzero_si128().as_i16x8(), + k, + )) +} + +/// Contiguously store the active 8-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_compress_epi8&expand=1210) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpcompressb))] +pub unsafe fn _mm512_mask_compress_epi8(src: __m512i, k: __mmask64, a: __m512i) -> __m512i { + transmute(vpcompressb(a.as_i8x64(), src.as_i8x64(), k)) +} + +/// Contiguously store the active 8-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_compress_epi8&expand=1211) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpcompressb))] +pub unsafe fn _mm512_maskz_compress_epi8(k: __mmask64, a: __m512i) -> __m512i { + transmute(vpcompressb( + a.as_i8x64(), + _mm512_setzero_si512().as_i8x64(), + k, + )) +} + +/// Contiguously store the active 8-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_compress_epi8&expand=1208) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressb))] +pub unsafe fn _mm256_mask_compress_epi8(src: __m256i, k: __mmask32, a: __m256i) -> __m256i { + transmute(vpcompressb256(a.as_i8x32(), src.as_i8x32(), k)) +} + +/// Contiguously store the active 8-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_compress_epi8&expand=1209) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressb))] +pub unsafe fn _mm256_maskz_compress_epi8(k: __mmask32, a: __m256i) -> __m256i { + transmute(vpcompressb256( + a.as_i8x32(), + _mm256_setzero_si256().as_i8x32(), + k, + )) +} + +/// Contiguously store the active 8-bit integers in a (those with their respective bit set in writemask k) to dst, and pass through the remaining elements from src. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_compress_epi8&expand=1206) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressb))] +pub unsafe fn _mm_mask_compress_epi8(src: __m128i, k: __mmask16, a: __m128i) -> __m128i { + transmute(vpcompressb128(a.as_i8x16(), src.as_i8x16(), k)) +} + +/// Contiguously store the active 8-bit integers in a (those with their respective bit set in zeromask k) to dst, and set the remaining elements to zero. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_compress_epi8&expand=1207) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpcompressb))] +pub unsafe fn _mm_maskz_compress_epi8(k: __mmask16, a: __m128i) -> __m128i { + transmute(vpcompressb128( + a.as_i8x16(), + _mm_setzero_si128().as_i8x16(), + k, + )) +} + +/// Load contiguous active 16-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_epi16&expand=2310) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpexpandw))] +pub unsafe fn _mm512_mask_expand_epi16(src: __m512i, k: __mmask32, a: __m512i) -> __m512i { + transmute(vpexpandw(a.as_i16x32(), src.as_i16x32(), k)) +} + +/// Load contiguous active 16-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_epi16&expand=2311) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpexpandw))] +pub unsafe fn _mm512_maskz_expand_epi16(k: __mmask32, a: __m512i) -> __m512i { + transmute(vpexpandw( + a.as_i16x32(), + _mm512_setzero_si512().as_i16x32(), + k, + )) +} + +/// Load contiguous active 16-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_expand_epi16&expand=2308) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandw))] +pub unsafe fn _mm256_mask_expand_epi16(src: __m256i, k: __mmask16, a: __m256i) -> __m256i { + transmute(vpexpandw256(a.as_i16x16(), src.as_i16x16(), k)) +} + +/// Load contiguous active 16-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_expand_epi16&expand=2309) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandw))] +pub unsafe fn _mm256_maskz_expand_epi16(k: __mmask16, a: __m256i) -> __m256i { + transmute(vpexpandw256( + a.as_i16x16(), + _mm256_setzero_si256().as_i16x16(), + k, + )) +} + +/// Load contiguous active 16-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_expand_epi16&expand=2306) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandw))] +pub unsafe fn _mm_mask_expand_epi16(src: __m128i, k: __mmask8, a: __m128i) -> __m128i { + transmute(vpexpandw128(a.as_i16x8(), src.as_i16x8(), k)) +} + +/// Load contiguous active 16-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_expand_epi16&expand=2307) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandw))] +pub unsafe fn _mm_maskz_expand_epi16(k: __mmask8, a: __m128i) -> __m128i { + transmute(vpexpandw128( + a.as_i16x8(), + _mm_setzero_si128().as_i16x8(), + k, + )) +} + +/// Load contiguous active 8-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_expand_epi8&expand=2328) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpexpandb))] +pub unsafe fn _mm512_mask_expand_epi8(src: __m512i, k: __mmask64, a: __m512i) -> __m512i { + transmute(vpexpandb(a.as_i8x64(), src.as_i8x64(), k)) +} + +/// Load contiguous active 8-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_expand_epi8&expand=2329) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpexpandb))] +pub unsafe fn _mm512_maskz_expand_epi8(k: __mmask64, a: __m512i) -> __m512i { + transmute(vpexpandb( + a.as_i8x64(), + _mm512_setzero_si512().as_i8x64(), + k, + )) +} + +/// Load contiguous active 8-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_expand_epi8&expand=2326) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandb))] +pub unsafe fn _mm256_mask_expand_epi8(src: __m256i, k: __mmask32, a: __m256i) -> __m256i { + transmute(vpexpandb256(a.as_i8x32(), src.as_i8x32(), k)) +} + +/// Load contiguous active 8-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_expand_epi8&expand=2327) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandb))] +pub unsafe fn _mm256_maskz_expand_epi8(k: __mmask32, a: __m256i) -> __m256i { + transmute(vpexpandb256( + a.as_i8x32(), + _mm256_setzero_si256().as_i8x32(), + k, + )) +} + +/// Load contiguous active 8-bit integers from a (those with their respective bit set in mask k), and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_expand_epi8&expand=2324) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandb))] +pub unsafe fn _mm_mask_expand_epi8(src: __m128i, k: __mmask16, a: __m128i) -> __m128i { + transmute(vpexpandb128(a.as_i8x16(), src.as_i8x16(), k)) +} + +/// Load contiguous active 8-bit integers from a (those with their respective bit set in mask k), and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_expand_epi8&expand=2325) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpexpandb))] +pub unsafe fn _mm_maskz_expand_epi8(k: __mmask16, a: __m128i) -> __m128i { + transmute(vpexpandb128( + a.as_i8x16(), + _mm_setzero_si128().as_i8x16(), + k, + )) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shldv_epi64&expand=5087) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm512_shldv_epi64(a: __m512i, b: __m512i, c: __m512i) -> __m512i { + transmute(vpshldvq(a.as_i64x8(), b.as_i64x8(), c.as_i64x8())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shldv_epi64&expand=5085) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm512_mask_shldv_epi64(a: __m512i, k: __mmask8, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shldv_epi64(a, b, c).as_i64x8(); + transmute(simd_select_bitmask(k, shf, a.as_i64x8())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shldv_epi64&expand=5086) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm512_maskz_shldv_epi64(k: __mmask8, a: __m512i, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shldv_epi64(a, b, c).as_i64x8(); + let zero = _mm512_setzero_si512().as_i64x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shldv_epi64&expand=5084) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm256_shldv_epi64(a: __m256i, b: __m256i, c: __m256i) -> __m256i { + transmute(vpshldvq256(a.as_i64x4(), b.as_i64x4(), c.as_i64x4())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shldv_epi64&expand=5082) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm256_mask_shldv_epi64(a: __m256i, k: __mmask8, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shldv_epi64(a, b, c).as_i64x4(); + transmute(simd_select_bitmask(k, shf, a.as_i64x4())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shldv_epi64&expand=5083) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm256_maskz_shldv_epi64(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shldv_epi64(a, b, c).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shldv_epi64&expand=5081) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm_shldv_epi64(a: __m128i, b: __m128i, c: __m128i) -> __m128i { + transmute(vpshldvq128(a.as_i64x2(), b.as_i64x2(), c.as_i64x2())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shldv_epi64&expand=5079) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm_mask_shldv_epi64(a: __m128i, k: __mmask8, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shldv_epi64(a, b, c).as_i64x2(); + transmute(simd_select_bitmask(k, shf, a.as_i64x2())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shldv_epi64&expand=5080) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvq))] +pub unsafe fn _mm_maskz_shldv_epi64(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shldv_epi64(a, b, c).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shldv_epi32&expand=5078) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm512_shldv_epi32(a: __m512i, b: __m512i, c: __m512i) -> __m512i { + transmute(vpshldvd(a.as_i32x16(), b.as_i32x16(), c.as_i32x16())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shldv_epi32&expand=5076) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm512_mask_shldv_epi32(a: __m512i, k: __mmask16, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shldv_epi32(a, b, c).as_i32x16(); + transmute(simd_select_bitmask(k, shf, a.as_i32x16())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shldv_epi32&expand=5077) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm512_maskz_shldv_epi32( + k: __mmask16, + a: __m512i, + b: __m512i, + c: __m512i, +) -> __m512i { + let shf = _mm512_shldv_epi32(a, b, c).as_i32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shldv_epi32&expand=5075) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm256_shldv_epi32(a: __m256i, b: __m256i, c: __m256i) -> __m256i { + transmute(vpshldvd256(a.as_i32x8(), b.as_i32x8(), c.as_i32x8())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shldv_epi32&expand=5073) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm256_mask_shldv_epi32(a: __m256i, k: __mmask8, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shldv_epi32(a, b, c).as_i32x8(); + transmute(simd_select_bitmask(k, shf, a.as_i32x8())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shldv_epi32&expand=5074) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm256_maskz_shldv_epi32(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shldv_epi32(a, b, c).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shldv_epi32&expand=5072) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm_shldv_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { + transmute(vpshldvd128(a.as_i32x4(), b.as_i32x4(), c.as_i32x4())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shldv_epi32&expand=5070) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm_mask_shldv_epi32(a: __m128i, k: __mmask8, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shldv_epi32(a, b, c).as_i32x4(); + transmute(simd_select_bitmask(k, shf, a.as_i32x4())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shldv_epi32&expand=5071) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvd))] +pub unsafe fn _mm_maskz_shldv_epi32(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shldv_epi32(a, b, c).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shldv_epi16&expand=5069) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm512_shldv_epi16(a: __m512i, b: __m512i, c: __m512i) -> __m512i { + transmute(vpshldvw(a.as_i16x32(), b.as_i16x32(), c.as_i16x32())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shldv_epi16&expand=5067) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm512_mask_shldv_epi16(a: __m512i, k: __mmask32, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shldv_epi16(a, b, c).as_i16x32(); + transmute(simd_select_bitmask(k, shf, a.as_i16x32())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shldv_epi16&expand=5068) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm512_maskz_shldv_epi16( + k: __mmask32, + a: __m512i, + b: __m512i, + c: __m512i, +) -> __m512i { + let shf = _mm512_shldv_epi16(a, b, c).as_i16x32(); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shldv_epi16&expand=5066) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm256_shldv_epi16(a: __m256i, b: __m256i, c: __m256i) -> __m256i { + transmute(vpshldvw256(a.as_i16x16(), b.as_i16x16(), c.as_i16x16())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shldv_epi16&expand=5064) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm256_mask_shldv_epi16(a: __m256i, k: __mmask16, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shldv_epi16(a, b, c).as_i16x16(); + transmute(simd_select_bitmask(k, shf, a.as_i16x16())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shldv_epi16&expand=5065) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm256_maskz_shldv_epi16( + k: __mmask16, + a: __m256i, + b: __m256i, + c: __m256i, +) -> __m256i { + let shf = _mm256_shldv_epi16(a, b, c).as_i16x16(); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shldv_epi16&expand=5063) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm_shldv_epi16(a: __m128i, b: __m128i, c: __m128i) -> __m128i { + transmute(vpshldvw128(a.as_i16x8(), b.as_i16x8(), c.as_i16x8())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shldv_epi16&expand=5061) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm_mask_shldv_epi16(a: __m128i, k: __mmask8, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shldv_epi16(a, b, c).as_i16x8(); + transmute(simd_select_bitmask(k, shf, a.as_i16x8())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shldv_epi16&expand=5062) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldvw))] +pub unsafe fn _mm_maskz_shldv_epi16(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shldv_epi16(a, b, c).as_i16x8(); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shrdv_epi64&expand=5141) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm512_shrdv_epi64(a: __m512i, b: __m512i, c: __m512i) -> __m512i { + transmute(vpshrdvq(a.as_i64x8(), b.as_i64x8(), c.as_i64x8())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shrdv_epi64&expand=5139) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm512_mask_shrdv_epi64(a: __m512i, k: __mmask8, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shrdv_epi64(a, b, c).as_i64x8(); + transmute(simd_select_bitmask(k, shf, a.as_i64x8())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shrdv_epi64&expand=5140) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm512_maskz_shrdv_epi64(k: __mmask8, a: __m512i, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shrdv_epi64(a, b, c).as_i64x8(); + let zero = _mm512_setzero_si512().as_i64x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shrdv_epi64&expand=5138) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm256_shrdv_epi64(a: __m256i, b: __m256i, c: __m256i) -> __m256i { + transmute(vpshrdvq256(a.as_i64x4(), b.as_i64x4(), c.as_i64x4())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shrdv_epi64&expand=5136) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm256_mask_shrdv_epi64(a: __m256i, k: __mmask8, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shrdv_epi64(a, b, c).as_i64x4(); + transmute(simd_select_bitmask(k, shf, a.as_i64x4())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shrdv_epi64&expand=5137) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm256_maskz_shrdv_epi64(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shrdv_epi64(a, b, c).as_i64x4(); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shrdv_epi64&expand=5135) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm_shrdv_epi64(a: __m128i, b: __m128i, c: __m128i) -> __m128i { + transmute(vpshrdvq128(a.as_i64x2(), b.as_i64x2(), c.as_i64x2())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shrdv_epi64&expand=5133) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm_mask_shrdv_epi64(a: __m128i, k: __mmask8, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shrdv_epi64(a, b, c).as_i64x2(); + transmute(simd_select_bitmask(k, shf, a.as_i64x2())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shrdv_epi64&expand=5134) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvq))] +pub unsafe fn _mm_maskz_shrdv_epi64(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shrdv_epi64(a, b, c).as_i64x2(); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shrdv_epi32&expand=5132) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm512_shrdv_epi32(a: __m512i, b: __m512i, c: __m512i) -> __m512i { + transmute(vpshrdvd(a.as_i32x16(), b.as_i32x16(), c.as_i32x16())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shrdv_epi32&expand=5130) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm512_mask_shrdv_epi32(a: __m512i, k: __mmask16, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shrdv_epi32(a, b, c).as_i32x16(); + transmute(simd_select_bitmask(k, shf, a.as_i32x16())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shrdv_epi32&expand=5131) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm512_maskz_shrdv_epi32( + k: __mmask16, + a: __m512i, + b: __m512i, + c: __m512i, +) -> __m512i { + let shf = _mm512_shrdv_epi32(a, b, c).as_i32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shrdv_epi32&expand=5129) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm256_shrdv_epi32(a: __m256i, b: __m256i, c: __m256i) -> __m256i { + transmute(vpshrdvd256(a.as_i32x8(), b.as_i32x8(), c.as_i32x8())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shrdv_epi32&expand=5127) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm256_mask_shrdv_epi32(a: __m256i, k: __mmask8, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shrdv_epi32(a, b, c).as_i32x8(); + transmute(simd_select_bitmask(k, shf, a.as_i32x8())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shrdv_epi32&expand=5128) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm256_maskz_shrdv_epi32(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shrdv_epi32(a, b, c).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shrdv_epi32&expand=5126) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm_shrdv_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { + transmute(vpshrdvd128(a.as_i32x4(), b.as_i32x4(), c.as_i32x4())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shrdv_epi32&expand=5124) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm_mask_shrdv_epi32(a: __m128i, k: __mmask8, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shrdv_epi32(a, b, c).as_i32x4(); + transmute(simd_select_bitmask(k, shf, a.as_i32x4())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shrdv_epi32&expand=5125) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvd))] +pub unsafe fn _mm_maskz_shrdv_epi32(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shrdv_epi32(a, b, c).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shrdv_epi16&expand=5123) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm512_shrdv_epi16(a: __m512i, b: __m512i, c: __m512i) -> __m512i { + transmute(vpshrdvw(a.as_i16x32(), b.as_i16x32(), c.as_i16x32())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shrdv_epi16&expand=5121) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm512_mask_shrdv_epi16(a: __m512i, k: __mmask32, b: __m512i, c: __m512i) -> __m512i { + let shf = _mm512_shrdv_epi16(a, b, c).as_i16x32(); + transmute(simd_select_bitmask(k, shf, a.as_i16x32())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shrdv_epi16&expand=5122) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm512_maskz_shrdv_epi16( + k: __mmask32, + a: __m512i, + b: __m512i, + c: __m512i, +) -> __m512i { + let shf = _mm512_shrdv_epi16(a, b, c).as_i16x32(); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shrdv_epi16&expand=5120) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm256_shrdv_epi16(a: __m256i, b: __m256i, c: __m256i) -> __m256i { + transmute(vpshrdvw256(a.as_i16x16(), b.as_i16x16(), c.as_i16x16())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shrdv_epi16&expand=5118) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm256_mask_shrdv_epi16(a: __m256i, k: __mmask16, b: __m256i, c: __m256i) -> __m256i { + let shf = _mm256_shrdv_epi16(a, b, c).as_i16x16(); + transmute(simd_select_bitmask(k, shf, a.as_i16x16())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shrdv_epi16&expand=5119) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm256_maskz_shrdv_epi16( + k: __mmask16, + a: __m256i, + b: __m256i, + c: __m256i, +) -> __m256i { + let shf = _mm256_shrdv_epi16(a, b, c).as_i16x16(); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shrdv_epi16&expand=5117) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm_shrdv_epi16(a: __m128i, b: __m128i, c: __m128i) -> __m128i { + transmute(vpshrdvw128(a.as_i16x8(), b.as_i16x8(), c.as_i16x8())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shrdv_epi16&expand=5115) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm_mask_shrdv_epi16(a: __m128i, k: __mmask8, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shrdv_epi16(a, b, c).as_i16x8(); + transmute(simd_select_bitmask(k, shf, a.as_i16x8())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shrdv_epi16&expand=5116) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshrdvw))] +pub unsafe fn _mm_maskz_shrdv_epi16(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> __m128i { + let shf = _mm_shrdv_epi16(a, b, c).as_i16x8(); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shldi_epi64&expand=5060) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shldi_epi64(a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvq( + a.as_i64x8(), + b.as_i64x8(), + _mm512_set1_epi64(imm8 as i64).as_i64x8(), + )) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shldi_epi64&expand=5058) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shldi_epi64( + src: __m512i, + k: __mmask8, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x8 = vpshldvq( + a.as_i64x8(), + b.as_i64x8(), + _mm512_set1_epi64(imm8 as i64).as_i64x8(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i64x8())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shldi_epi64&expand=5059) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_maskz_shldi_epi64(k: __mmask8, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x8 = vpshldvq( + a.as_i64x8(), + b.as_i64x8(), + _mm512_set1_epi64(imm8 as i64).as_i64x8(), + ); + let zero = _mm512_setzero_si512().as_i64x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shldi_epi64&expand=5057) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shldi_epi64(a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvq256( + a.as_i64x4(), + b.as_i64x4(), + _mm256_set1_epi64x(imm8 as i64).as_i64x4(), + )) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shldi_epi64&expand=5055) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shldi_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x4 = vpshldvq256( + a.as_i64x4(), + b.as_i64x4(), + _mm256_set1_epi64x(imm8 as i64).as_i64x4(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shldi_epi64&expand=5056) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shldi_epi64(k: __mmask8, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x4 = vpshldvq256( + a.as_i64x4(), + b.as_i64x4(), + _mm256_set1_epi64x(imm8 as i64).as_i64x4(), + ); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shldi_epi64&expand=5054) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_shldi_epi64(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvq128( + a.as_i64x2(), + b.as_i64x2(), + _mm_set1_epi64x(imm8 as i64).as_i64x2(), + )) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shldi_epi64&expand=5052) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shldi_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x2 = vpshldvq128( + a.as_i64x2(), + b.as_i64x2(), + _mm_set1_epi64x(imm8 as i64).as_i64x2(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by imm8 bits, and store the upper 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shldi_epi64&expand=5053) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shldi_epi64(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x2 = vpshldvq128( + a.as_i64x2(), + b.as_i64x2(), + _mm_set1_epi64x(imm8 as i64).as_i64x2(), + ); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shldi_epi32&expand=5051) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shldi_epi32(a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvd( + a.as_i32x16(), + b.as_i32x16(), + _mm512_set1_epi32(imm8).as_i32x16(), + )) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shldi_epi32&expand=5049) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shldi_epi32( + src: __m512i, + k: __mmask16, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x16 = vpshldvd( + a.as_i32x16(), + b.as_i32x16(), + _mm512_set1_epi32(imm8).as_i32x16(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i32x16())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shldi_epi32&expand=5050) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_maskz_shldi_epi32(k: __mmask16, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x16 = vpshldvd( + a.as_i32x16(), + b.as_i32x16(), + _mm512_set1_epi32(imm8).as_i32x16(), + ); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shldi_epi32&expand=5048) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shldi_epi32(a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvd256( + a.as_i32x8(), + b.as_i32x8(), + _mm256_set1_epi32(imm8).as_i32x8(), + )) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shldi_epi32&expand=5046) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shldi_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x8 = vpshldvd256( + a.as_i32x8(), + b.as_i32x8(), + _mm256_set1_epi32(imm8).as_i32x8(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shldi_epi32&expand=5047) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shldi_epi32(k: __mmask8, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x8 = vpshldvd256( + a.as_i32x8(), + b.as_i32x8(), + _mm256_set1_epi32(imm8).as_i32x8(), + ); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shldi_epi32&expand=5045) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_shldi_epi32(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvd128( + a.as_i32x4(), + b.as_i32x4(), + _mm_set1_epi32(imm8).as_i32x4(), + )) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shldi_epi32&expand=5043) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shldi_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x4 = vpshldvd128(a.as_i32x4(), b.as_i32x4(), _mm_set1_epi32(imm8).as_i32x4()); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by imm8 bits, and store the upper 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shldi_epi32&expand=5044) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shldi_epi32(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x4 = vpshldvd128(a.as_i32x4(), b.as_i32x4(), _mm_set1_epi32(imm8).as_i32x4()); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shldi_epi16&expand=5042) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shldi_epi16(a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvw( + a.as_i16x32(), + b.as_i16x32(), + _mm512_set1_epi16(imm8 as i16).as_i16x32(), + )) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shldi_epi16&expand=5040) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shldi_epi16( + src: __m512i, + k: __mmask32, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i16x32 = vpshldvw( + a.as_i16x32(), + b.as_i16x32(), + _mm512_set1_epi16(imm8 as i16).as_i16x32(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i16x32())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shldi_epi16&expand=5041) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_maskz_shldi_epi16(k: __mmask32, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i16x32 = vpshldvw( + a.as_i16x32(), + b.as_i16x32(), + _mm512_set1_epi16(imm8 as i16).as_i16x32(), + ); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shldi_epi16&expand=5039) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shldi_epi16(a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshldvw256( + a.as_i16x16(), + b.as_i16x16(), + _mm256_set1_epi16(imm8 as i16).as_i16x16(), + )) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shldi_epi16&expand=5037) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shldi_epi16( + src: __m256i, + k: __mmask16, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i16x16 = vpshldvw256( + a.as_i16x16(), + b.as_i16x16(), + _mm256_set1_epi16(imm8 as i16).as_i16x16(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i16x16())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shldi_epi16&expand=5038) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shldi_epi16(k: __mmask16, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + let shf: i16x16 = vpshldvw256( + a.as_i16x16(), + b.as_i16x16(), + _mm256_set1_epi16(imm8 as i16).as_i16x16(), + ); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shldi_epi16&expand=5036) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_shldi_epi16(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + transmute(vpshldvw128( + a.as_i16x8(), + b.as_i16x8(), + _mm_set1_epi16(imm8 as i16).as_i16x8(), + )) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shldi_epi16&expand=5034) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shldi_epi16( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + let shf: i16x8 = vpshldvw128( + a.as_i16x8(), + b.as_i16x8(), + _mm_set1_epi16(imm8 as i16).as_i16x8(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i16x8())) +} + +/// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by imm8 bits, and store the upper 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shldi_epi16&expand=5035) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shldi_epi16(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + let shf: i16x8 = vpshldvw128( + a.as_i16x8(), + b.as_i16x8(), + _mm_set1_epi16(imm8 as i16).as_i16x8(), + ); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shrdi_epi64&expand=5114) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shrdi_epi64(a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvq( + a.as_i64x8(), + b.as_i64x8(), + _mm512_set1_epi64(imm8 as i64).as_i64x8(), + )) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst using writemask k (elements are copied from src" when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shrdi_epi64&expand=5112) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shrdi_epi64( + src: __m512i, + k: __mmask8, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x8 = vpshrdvq( + a.as_i64x8(), + b.as_i64x8(), + _mm512_set1_epi64(imm8 as i64).as_i64x8(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i64x8())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shrdi_epi64&expand=5113) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 255))] //should be vpshrdq +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_maskz_shrdi_epi64(k: __mmask8, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x8 = vpshrdvq( + a.as_i64x8(), + b.as_i64x8(), + _mm512_set1_epi64(imm8 as i64).as_i64x8(), + ); + let zero = _mm512_setzero_si512().as_i64x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shrdi_epi64&expand=5111) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shrdi_epi64(a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvq256( + a.as_i64x4(), + b.as_i64x4(), + _mm256_set1_epi64x(imm8 as i64).as_i64x4(), + )) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst using writemask k (elements are copied from src" when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shrdi_epi64&expand=5109) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shrdi_epi64( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x4 = vpshrdvq256( + a.as_i64x4(), + b.as_i64x4(), + _mm256_set1_epi64x(imm8 as i64).as_i64x4(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i64x4())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shrdi_epi64&expand=5110) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shrdi_epi64(k: __mmask8, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x4 = vpshrdvq256( + a.as_i64x4(), + b.as_i64x4(), + _mm256_set1_epi64x(imm8 as i64).as_i64x4(), + ); + let zero = _mm256_setzero_si256().as_i64x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shrdi_epi64&expand=5108) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(2)] +pub unsafe fn _mm_shrdi_epi64(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvq128( + a.as_i64x2(), + b.as_i64x2(), + _mm_set1_epi64x(imm8 as i64).as_i64x2(), + )) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst using writemask k (elements are copied from src" when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shrdi_epi64&expand=5106) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shrdi_epi64( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x2 = vpshrdvq128( + a.as_i64x2(), + b.as_i64x2(), + _mm_set1_epi64x(imm8 as i64).as_i64x2(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i64x2())) +} + +/// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by imm8 bits, and store the lower 64-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shrdi_epi64&expand=5107) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldq, imm8 = 5))] //should be vpshrdq +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shrdi_epi64(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i64x2 = vpshrdvq128( + a.as_i64x2(), + b.as_i64x2(), + _mm_set1_epi64x(imm8 as i64).as_i64x2(), + ); + let zero = _mm_setzero_si128().as_i64x2(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shrdi_epi32&expand=5105) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shrdi_epi32(a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvd( + a.as_i32x16(), + b.as_i32x16(), + _mm512_set1_epi32(imm8).as_i32x16(), + )) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shrdi_epi32&expand=5103) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shrdi_epi32( + src: __m512i, + k: __mmask16, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x16 = vpshrdvd( + a.as_i32x16(), + b.as_i32x16(), + _mm512_set1_epi32(imm8).as_i32x16(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i32x16())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shrdi_epi32&expand=5104) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_maskz_shrdi_epi32(k: __mmask16, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x16 = vpshrdvd( + a.as_i32x16(), + b.as_i32x16(), + _mm512_set1_epi32(imm8).as_i32x16(), + ); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shrdi_epi32&expand=5102) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shrdi_epi32(a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvd256( + a.as_i32x8(), + b.as_i32x8(), + _mm256_set1_epi32(imm8).as_i32x8(), + )) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shrdi_epi32&expand=5100) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shrdi_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x8 = vpshrdvd256( + a.as_i32x8(), + b.as_i32x8(), + _mm256_set1_epi32(imm8).as_i32x8(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i32x8())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shrdi_epi32&expand=5101) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shrdi_epi32(k: __mmask8, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x8 = vpshrdvd256( + a.as_i32x8(), + b.as_i32x8(), + _mm256_set1_epi32(imm8).as_i32x8(), + ); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shrdi_epi32&expand=5099) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(2)] +pub unsafe fn _mm_shrdi_epi32(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvd128( + a.as_i32x4(), + b.as_i32x4(), + _mm_set1_epi32(imm8).as_i32x4(), + )) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shrdi_epi32&expand=5097) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shrdi_epi32( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x4 = vpshrdvd128(a.as_i32x4(), b.as_i32x4(), _mm_set1_epi32(imm8).as_i32x4()); + transmute(simd_select_bitmask(k, shf, src.as_i32x4())) +} + +/// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by imm8 bits, and store the lower 32-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shrdi_epi32&expand=5098) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldd, imm8 = 5))] //should be vpshldd +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shrdi_epi32(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i32x4 = vpshrdvd128(a.as_i32x4(), b.as_i32x4(), _mm_set1_epi32(imm8).as_i32x4()); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shrdi_epi16&expand=5096) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(2)] +pub unsafe fn _mm512_shrdi_epi16(a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvw( + a.as_i16x32(), + b.as_i16x32(), + _mm512_set1_epi16(imm8 as i16).as_i16x32(), + )) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shrdi_epi16&expand=5094) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(4)] +pub unsafe fn _mm512_mask_shrdi_epi16( + src: __m512i, + k: __mmask32, + a: __m512i, + b: __m512i, + imm8: i32, +) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i16x32 = vpshrdvw( + a.as_i16x32(), + b.as_i16x32(), + _mm512_set1_epi16(imm8 as i16).as_i16x32(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i16x32())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shrdi_epi16&expand=5095) +#[inline] +#[target_feature(enable = "avx512vbmi2")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(3)] +pub unsafe fn _mm512_maskz_shrdi_epi16(k: __mmask32, a: __m512i, b: __m512i, imm8: i32) -> __m512i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i16x32 = vpshrdvw( + a.as_i16x32(), + b.as_i16x32(), + _mm512_set1_epi16(imm8 as i16).as_i16x32(), + ); + let zero = _mm512_setzero_si512().as_i16x32(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_shrdi_epi16&expand=5093) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(2)] +pub unsafe fn _mm256_shrdi_epi16(a: __m256i, b: __m256i, imm8: i32) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + transmute(vpshrdvw256( + a.as_i16x16(), + b.as_i16x16(), + _mm256_set1_epi16(imm8 as i16).as_i16x16(), + )) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shrdi_epi16&expand=5091) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(4)] +pub unsafe fn _mm256_mask_shrdi_epi16( + src: __m256i, + k: __mmask16, + a: __m256i, + b: __m256i, + imm8: i32, +) -> __m256i { + assert!(imm8 >= 0 && imm8 <= 255); + let shf: i16x16 = vpshrdvw256( + a.as_i16x16(), + b.as_i16x16(), + _mm256_set1_epi16(imm8 as i16).as_i16x16(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i16x16())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shrdi_epi16&expand=5092) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(3)] +pub unsafe fn _mm256_maskz_shrdi_epi16(k: __mmask16, a: __m256i, b: __m256i, imm8: i32) -> __m256i { + let shf: i16x16 = vpshrdvw256( + a.as_i16x16(), + b.as_i16x16(), + _mm256_set1_epi16(imm8 as i16).as_i16x16(), + ); + let zero = _mm256_setzero_si256().as_i16x16(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shrdi_epi16&expand=5090) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(2)] +pub unsafe fn _mm_shrdi_epi16(a: __m128i, b: __m128i, imm8: i32) -> __m128i { + transmute(vpshrdvw128( + a.as_i16x8(), + b.as_i16x8(), + _mm_set1_epi16(imm8 as i16).as_i16x8(), + )) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shrdi_epi16&expand=5088) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(4)] +pub unsafe fn _mm_mask_shrdi_epi16( + src: __m128i, + k: __mmask8, + a: __m128i, + b: __m128i, + imm8: i32, +) -> __m128i { + let shf: i16x8 = vpshrdvw128( + a.as_i16x8(), + b.as_i16x8(), + _mm_set1_epi16(imm8 as i16).as_i16x8(), + ); + transmute(simd_select_bitmask(k, shf, src.as_i16x8())) +} + +/// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by imm8 bits, and store the lower 16-bits in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shrdi_epi16&expand=5089) +#[inline] +#[target_feature(enable = "avx512vbmi2,avx512vl")] +#[cfg_attr(test, assert_instr(vpshldw, imm8 = 5))] //should be vpshrdw +#[rustc_args_required_const(3)] +pub unsafe fn _mm_maskz_shrdi_epi16(k: __mmask8, a: __m128i, b: __m128i, imm8: i32) -> __m128i { + let shf: i16x8 = vpshrdvw128( + a.as_i16x8(), + b.as_i16x8(), + _mm_set1_epi16(imm8 as i16).as_i16x8(), + ); + let zero = _mm_setzero_si128().as_i16x8(); + transmute(simd_select_bitmask(k, shf, zero)) +} + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.x86.avx512.mask.compress.w.512"] + fn vpcompressw(a: i16x32, src: i16x32, mask: u32) -> i16x32; + #[link_name = "llvm.x86.avx512.mask.compress.w.256"] + fn vpcompressw256(a: i16x16, src: i16x16, mask: u16) -> i16x16; + #[link_name = "llvm.x86.avx512.mask.compress.w.128"] + fn vpcompressw128(a: i16x8, src: i16x8, mask: u8) -> i16x8; + + #[link_name = "llvm.x86.avx512.mask.compress.b.512"] + fn vpcompressb(a: i8x64, src: i8x64, mask: u64) -> i8x64; + #[link_name = "llvm.x86.avx512.mask.compress.b.256"] + fn vpcompressb256(a: i8x32, src: i8x32, mask: u32) -> i8x32; + #[link_name = "llvm.x86.avx512.mask.compress.b.128"] + fn vpcompressb128(a: i8x16, src: i8x16, mask: u16) -> i8x16; + + #[link_name = "llvm.x86.avx512.mask.expand.w.512"] + fn vpexpandw(a: i16x32, src: i16x32, mask: u32) -> i16x32; + #[link_name = "llvm.x86.avx512.mask.expand.w.256"] + fn vpexpandw256(a: i16x16, src: i16x16, mask: u16) -> i16x16; + #[link_name = "llvm.x86.avx512.mask.expand.w.128"] + fn vpexpandw128(a: i16x8, src: i16x8, mask: u8) -> i16x8; + + #[link_name = "llvm.x86.avx512.mask.expand.b.512"] + fn vpexpandb(a: i8x64, src: i8x64, mask: u64) -> i8x64; + #[link_name = "llvm.x86.avx512.mask.expand.b.256"] + fn vpexpandb256(a: i8x32, src: i8x32, mask: u32) -> i8x32; + #[link_name = "llvm.x86.avx512.mask.expand.b.128"] + fn vpexpandb128(a: i8x16, src: i8x16, mask: u16) -> i8x16; + + #[link_name = "llvm.fshl.v8i64"] + fn vpshldvq(a: i64x8, b: i64x8, c: i64x8) -> i64x8; + #[link_name = "llvm.fshl.v4i64"] + fn vpshldvq256(a: i64x4, b: i64x4, c: i64x4) -> i64x4; + #[link_name = "llvm.fshl.v2i64"] + fn vpshldvq128(a: i64x2, b: i64x2, c: i64x2) -> i64x2; + #[link_name = "llvm.fshl.v16i32"] + fn vpshldvd(a: i32x16, b: i32x16, c: i32x16) -> i32x16; + #[link_name = "llvm.fshl.v8i32"] + fn vpshldvd256(a: i32x8, b: i32x8, c: i32x8) -> i32x8; + #[link_name = "llvm.fshl.v4i32"] + fn vpshldvd128(a: i32x4, b: i32x4, c: i32x4) -> i32x4; + #[link_name = "llvm.fshl.v32i16"] + fn vpshldvw(a: i16x32, b: i16x32, c: i16x32) -> i16x32; + #[link_name = "llvm.fshl.v16i16"] + fn vpshldvw256(a: i16x16, b: i16x16, c: i16x16) -> i16x16; + #[link_name = "llvm.fshl.v8i16"] + fn vpshldvw128(a: i16x8, b: i16x8, c: i16x8) -> i16x8; + + #[link_name = "llvm.fshr.v8i64"] + fn vpshrdvq(a: i64x8, b: i64x8, c: i64x8) -> i64x8; + #[link_name = "llvm.fshr.v4i64"] + fn vpshrdvq256(a: i64x4, b: i64x4, c: i64x4) -> i64x4; + #[link_name = "llvm.fshr.v2i64"] + fn vpshrdvq128(a: i64x2, b: i64x2, c: i64x2) -> i64x2; + #[link_name = "llvm.fshr.v16i32"] + fn vpshrdvd(a: i32x16, b: i32x16, c: i32x16) -> i32x16; + #[link_name = "llvm.fshr.v8i32"] + fn vpshrdvd256(a: i32x8, b: i32x8, c: i32x8) -> i32x8; + #[link_name = "llvm.fshr.v4i32"] + fn vpshrdvd128(a: i32x4, b: i32x4, c: i32x4) -> i32x4; + #[link_name = "llvm.fshr.v32i16"] + fn vpshrdvw(a: i16x32, b: i16x32, c: i16x32) -> i16x32; + #[link_name = "llvm.fshr.v16i16"] + fn vpshrdvw256(a: i16x16, b: i16x16, c: i16x16) -> i16x16; + #[link_name = "llvm.fshr.v8i16"] + fn vpshrdvw128(a: i16x8, b: i16x8, c: i16x8) -> i16x8; +} + +#[cfg(test)] +mod tests { + + use stdarch_test::simd_test; + + use crate::core_arch::x86::*; + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_compress_epi16() { + let src = _mm512_set1_epi16(200); + #[rustfmt::skip] + let a = _mm512_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm512_mask_compress_epi16(src, 0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm512_set_epi16( + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_compress_epi16() { + #[rustfmt::skip] + let a = _mm512_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm512_maskz_compress_epi16(0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm512_set_epi16( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_compress_epi16() { + let src = _mm256_set1_epi16(200); + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_mask_compress_epi16(src, 0b01010101_01010101, a); + let e = _mm256_set_epi16( + 200, 200, 200, 200, 200, 200, 200, 200, 1, 3, 5, 7, 9, 11, 13, 15, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_compress_epi16() { + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_compress_epi16(0b01010101_01010101, a); + let e = _mm256_set_epi16(0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 9, 11, 13, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_compress_epi16() { + let src = _mm_set1_epi16(200); + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_mask_compress_epi16(src, 0b01010101, a); + let e = _mm_set_epi16(200, 200, 200, 200, 1, 3, 5, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_compress_epi16() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_maskz_compress_epi16(0b01010101, a); + let e = _mm_set_epi16(0, 0, 0, 0, 1, 3, 5, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_compress_epi8() { + let src = _mm512_set1_epi8(100); + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let r = _mm512_mask_compress_epi8( + src, + 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101, + a, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_compress_epi8() { + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let r = _mm512_maskz_compress_epi8( + 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101, + a, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_compress_epi8() { + let src = _mm256_set1_epi8(100); + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm256_mask_compress_epi8(src, 0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_compress_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm256_maskz_compress_epi8(0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_compress_epi8() { + let src = _mm_set1_epi8(100); + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_mask_compress_epi8(src, 0b01010101_01010101, a); + let e = _mm_set_epi8( + 100, 100, 100, 100, 100, 100, 100, 100, 1, 3, 5, 7, 9, 11, 13, 15, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_compress_epi8() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_compress_epi8(0b01010101_01010101, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 9, 11, 13, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_expand_epi16() { + let src = _mm512_set1_epi16(200); + #[rustfmt::skip] + let a = _mm512_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm512_mask_expand_epi16(src, 0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm512_set_epi16( + 200, 16, 200, 17, 200, 18, 200, 19, 200, 20, 200, 21, 200, 22, 200, 23, + 200, 24, 200, 25, 200, 26, 200, 27, 200, 28, 200, 29, 200, 30, 200, 31, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_expand_epi16() { + #[rustfmt::skip] + let a = _mm512_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm512_maskz_expand_epi16(0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm512_set_epi16(0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, + 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_expand_epi16() { + let src = _mm256_set1_epi16(200); + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_mask_expand_epi16(src, 0b01010101_01010101, a); + let e = _mm256_set_epi16( + 200, 8, 200, 9, 200, 10, 200, 11, 200, 12, 200, 13, 200, 14, 200, 15, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_expand_epi16() { + let a = _mm256_set_epi16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_expand_epi16(0b01010101_01010101, a); + let e = _mm256_set_epi16(0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_expand_epi16() { + let src = _mm_set1_epi16(200); + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_mask_expand_epi16(src, 0b01010101, a); + let e = _mm_set_epi16(200, 4, 200, 5, 200, 6, 200, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_expand_epi16() { + let a = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm_maskz_expand_epi16(0b01010101, a); + let e = _mm_set_epi16(0, 4, 0, 5, 0, 6, 0, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_expand_epi8() { + let src = _mm512_set1_epi8(100); + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let r = _mm512_mask_expand_epi8( + src, + 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101, + a, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 100, 32, 100, 33, 100, 34, 100, 35, 100, 36, 100, 37, 100, 38, 100, 39, + 100, 40, 100, 41, 100, 42, 100, 43, 100, 44, 100, 45, 100, 46, 100, 47, + 100, 48, 100, 49, 100, 50, 100, 51, 100, 52, 100, 53, 100, 54, 100, 55, + 100, 56, 100, 57, 100, 58, 100, 59, 100, 60, 100, 61, 100, 62, 100, 63, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_expand_epi8() { + #[rustfmt::skip] + let a = _mm512_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63); + let r = _mm512_maskz_expand_epi8( + 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101, + a, + ); + #[rustfmt::skip] + let e = _mm512_set_epi8( + 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, + 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, + 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, + 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, + ); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_expand_epi8() { + let src = _mm256_set1_epi8(100); + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm256_mask_expand_epi8(src, 0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 100, 16, 100, 17, 100, 18, 100, 19, 100, 20, 100, 21, 100, 22, 100, 23, + 100, 24, 100, 25, 100, 26, 100, 27, 100, 28, 100, 29, 100, 30, 100, 31, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_expand_epi8() { + #[rustfmt::skip] + let a = _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + let r = _mm256_maskz_expand_epi8(0b01010101_01010101_01010101_01010101, a); + #[rustfmt::skip] + let e = _mm256_set_epi8( + 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, + 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, + ); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_expand_epi8() { + let src = _mm_set1_epi8(100); + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_mask_expand_epi8(src, 0b01010101_01010101, a); + let e = _mm_set_epi8( + 100, 8, 100, 9, 100, 10, 100, 11, 100, 12, 100, 13, 100, 14, 100, 15, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_expand_epi8() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_expand_epi8(0b01010101_01010101, a); + let e = _mm_set_epi8(0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shldv_epi64() { + let a = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(1 << 63); + let c = _mm512_set1_epi64(2); + let r = _mm512_shldv_epi64(a, b, c); + let e = _mm512_set1_epi64(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shldv_epi64() { + let a = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(1 << 63); + let c = _mm512_set1_epi64(2); + let r = _mm512_mask_shldv_epi64(a, 0, b, c); + assert_eq_m512i(r, a); + let r = _mm512_mask_shldv_epi64(a, 0b11111111, b, c); + let e = _mm512_set1_epi64(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shldv_epi64() { + let a = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(1 << 63); + let c = _mm512_set1_epi64(2); + let r = _mm512_maskz_shldv_epi64(0, a, b, c); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shldv_epi64(0b11111111, a, b, c); + let e = _mm512_set1_epi64(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shldv_epi64() { + let a = _mm256_set1_epi64x(1); + let b = _mm256_set1_epi64x(1 << 63); + let c = _mm256_set1_epi64x(2); + let r = _mm256_shldv_epi64(a, b, c); + let e = _mm256_set1_epi64x(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shldv_epi64() { + let a = _mm256_set1_epi64x(1); + let b = _mm256_set1_epi64x(1 << 63); + let c = _mm256_set1_epi64x(2); + let r = _mm256_mask_shldv_epi64(a, 0, b, c); + assert_eq_m256i(r, a); + let r = _mm256_mask_shldv_epi64(a, 0b00001111, b, c); + let e = _mm256_set1_epi64x(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shldv_epi64() { + let a = _mm256_set1_epi64x(1); + let b = _mm256_set1_epi64x(1 << 63); + let c = _mm256_set1_epi64x(2); + let r = _mm256_maskz_shldv_epi64(0, a, b, c); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shldv_epi64(0b00001111, a, b, c); + let e = _mm256_set1_epi64x(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shldv_epi64() { + let a = _mm_set1_epi64x(1); + let b = _mm_set1_epi64x(1 << 63); + let c = _mm_set1_epi64x(2); + let r = _mm_shldv_epi64(a, b, c); + let e = _mm_set1_epi64x(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shldv_epi64() { + let a = _mm_set1_epi64x(1); + let b = _mm_set1_epi64x(1 << 63); + let c = _mm_set1_epi64x(2); + let r = _mm_mask_shldv_epi64(a, 0, b, c); + assert_eq_m128i(r, a); + let r = _mm_mask_shldv_epi64(a, 0b00000011, b, c); + let e = _mm_set1_epi64x(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shldv_epi64() { + let a = _mm_set1_epi64x(1); + let b = _mm_set1_epi64x(1 << 63); + let c = _mm_set1_epi64x(2); + let r = _mm_maskz_shldv_epi64(0, a, b, c); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shldv_epi64(0b00000011, a, b, c); + let e = _mm_set1_epi64x(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shldv_epi32() { + let a = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(1 << 31); + let c = _mm512_set1_epi32(2); + let r = _mm512_shldv_epi32(a, b, c); + let e = _mm512_set1_epi32(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shldv_epi32() { + let a = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(1 << 31); + let c = _mm512_set1_epi32(2); + let r = _mm512_mask_shldv_epi32(a, 0, b, c); + assert_eq_m512i(r, a); + let r = _mm512_mask_shldv_epi32(a, 0b11111111_11111111, b, c); + let e = _mm512_set1_epi32(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shldv_epi32() { + let a = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(1 << 31); + let c = _mm512_set1_epi32(2); + let r = _mm512_maskz_shldv_epi32(0, a, b, c); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shldv_epi32(0b11111111_11111111, a, b, c); + let e = _mm512_set1_epi32(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shldv_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set1_epi32(1 << 31); + let c = _mm256_set1_epi32(2); + let r = _mm256_shldv_epi32(a, b, c); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shldv_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set1_epi32(1 << 31); + let c = _mm256_set1_epi32(2); + let r = _mm256_mask_shldv_epi32(a, 0, b, c); + assert_eq_m256i(r, a); + let r = _mm256_mask_shldv_epi32(a, 0b11111111, b, c); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shldv_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set1_epi32(1 << 31); + let c = _mm256_set1_epi32(2); + let r = _mm256_maskz_shldv_epi32(0, a, b, c); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shldv_epi32(0b11111111, a, b, c); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shldv_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set1_epi32(1 << 31); + let c = _mm_set1_epi32(2); + let r = _mm_shldv_epi32(a, b, c); + let e = _mm_set1_epi32(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shldv_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set1_epi32(1 << 31); + let c = _mm_set1_epi32(2); + let r = _mm_mask_shldv_epi32(a, 0, b, c); + assert_eq_m128i(r, a); + let r = _mm_mask_shldv_epi32(a, 0b00001111, b, c); + let e = _mm_set1_epi32(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shldv_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set1_epi32(1 << 31); + let c = _mm_set1_epi32(2); + let r = _mm_maskz_shldv_epi32(0, a, b, c); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shldv_epi32(0b00001111, a, b, c); + let e = _mm_set1_epi32(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shldv_epi16() { + let a = _mm512_set1_epi16(1); + let b = _mm512_set1_epi16(1 << 15); + let c = _mm512_set1_epi16(2); + let r = _mm512_shldv_epi16(a, b, c); + let e = _mm512_set1_epi16(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shldv_epi16() { + let a = _mm512_set1_epi16(1); + let b = _mm512_set1_epi16(1 << 15); + let c = _mm512_set1_epi16(2); + let r = _mm512_mask_shldv_epi16(a, 0, b, c); + assert_eq_m512i(r, a); + let r = _mm512_mask_shldv_epi16(a, 0b11111111_11111111_11111111_11111111, b, c); + let e = _mm512_set1_epi16(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shldv_epi16() { + let a = _mm512_set1_epi16(1); + let b = _mm512_set1_epi16(1 << 15); + let c = _mm512_set1_epi16(2); + let r = _mm512_maskz_shldv_epi16(0, a, b, c); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shldv_epi16(0b11111111_11111111_11111111_11111111, a, b, c); + let e = _mm512_set1_epi16(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shldv_epi16() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1 << 15); + let c = _mm256_set1_epi16(2); + let r = _mm256_shldv_epi16(a, b, c); + let e = _mm256_set1_epi16(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shldv_epi16() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1 << 15); + let c = _mm256_set1_epi16(2); + let r = _mm256_mask_shldv_epi16(a, 0, b, c); + assert_eq_m256i(r, a); + let r = _mm256_mask_shldv_epi16(a, 0b11111111_11111111, b, c); + let e = _mm256_set1_epi16(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shldv_epi16() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1 << 15); + let c = _mm256_set1_epi16(2); + let r = _mm256_maskz_shldv_epi16(0, a, b, c); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shldv_epi16(0b11111111_11111111, a, b, c); + let e = _mm256_set1_epi16(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shldv_epi16() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1 << 15); + let c = _mm_set1_epi16(2); + let r = _mm_shldv_epi16(a, b, c); + let e = _mm_set1_epi16(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shldv_epi16() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1 << 15); + let c = _mm_set1_epi16(2); + let r = _mm_mask_shldv_epi16(a, 0, b, c); + assert_eq_m128i(r, a); + let r = _mm_mask_shldv_epi16(a, 0b11111111, b, c); + let e = _mm_set1_epi16(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shldv_epi16() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1 << 15); + let c = _mm_set1_epi16(2); + let r = _mm_maskz_shldv_epi16(0, a, b, c); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shldv_epi16(0b11111111, a, b, c); + let e = _mm_set1_epi16(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shrdv_epi64() { + let a = _mm512_set1_epi64(8); + let b = _mm512_set1_epi64(2); + let c = _mm512_set1_epi64(1); + let r = _mm512_shrdv_epi64(a, b, c); + let e = _mm512_set1_epi64(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shrdv_epi64() { + let a = _mm512_set1_epi64(8); + let b = _mm512_set1_epi64(2); + let c = _mm512_set1_epi64(1); + let r = _mm512_mask_shrdv_epi64(a, 0, b, c); + assert_eq_m512i(r, a); + let r = _mm512_mask_shrdv_epi64(a, 0b11111111, b, c); + let e = _mm512_set1_epi64(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shrdv_epi64() { + let a = _mm512_set1_epi64(8); + let b = _mm512_set1_epi64(2); + let c = _mm512_set1_epi64(1); + let r = _mm512_maskz_shrdv_epi64(0, a, b, c); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shrdv_epi64(0b11111111, a, b, c); + let e = _mm512_set1_epi64(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shrdv_epi64() { + let a = _mm256_set1_epi64x(8); + let b = _mm256_set1_epi64x(2); + let c = _mm256_set1_epi64x(1); + let r = _mm256_shrdv_epi64(a, b, c); + let e = _mm256_set1_epi64x(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shrdv_epi64() { + let a = _mm256_set1_epi64x(8); + let b = _mm256_set1_epi64x(2); + let c = _mm256_set1_epi64x(1); + let r = _mm256_mask_shrdv_epi64(a, 0, b, c); + assert_eq_m256i(r, a); + let r = _mm256_mask_shrdv_epi64(a, 0b00001111, b, c); + let e = _mm256_set1_epi64x(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shrdv_epi64() { + let a = _mm256_set1_epi64x(8); + let b = _mm256_set1_epi64x(2); + let c = _mm256_set1_epi64x(1); + let r = _mm256_maskz_shrdv_epi64(0, a, b, c); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shrdv_epi64(0b00001111, a, b, c); + let e = _mm256_set1_epi64x(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shrdv_epi64() { + let a = _mm_set1_epi64x(8); + let b = _mm_set1_epi64x(2); + let c = _mm_set1_epi64x(1); + let r = _mm_shrdv_epi64(a, b, c); + let e = _mm_set1_epi64x(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shrdv_epi64() { + let a = _mm_set1_epi64x(8); + let b = _mm_set1_epi64x(2); + let c = _mm_set1_epi64x(1); + let r = _mm_mask_shrdv_epi64(a, 0, b, c); + assert_eq_m128i(r, a); + let r = _mm_mask_shrdv_epi64(a, 0b00000011, b, c); + let e = _mm_set1_epi64x(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shrdv_epi64() { + let a = _mm_set1_epi64x(8); + let b = _mm_set1_epi64x(2); + let c = _mm_set1_epi64x(1); + let r = _mm_maskz_shrdv_epi64(0, a, b, c); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shrdv_epi64(0b00000011, a, b, c); + let e = _mm_set1_epi64x(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shrdv_epi32() { + let a = _mm512_set1_epi32(8); + let b = _mm512_set1_epi32(2); + let c = _mm512_set1_epi32(1); + let r = _mm512_shrdv_epi32(a, b, c); + let e = _mm512_set1_epi32(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shrdv_epi32() { + let a = _mm512_set1_epi32(8); + let b = _mm512_set1_epi32(2); + let c = _mm512_set1_epi32(1); + let r = _mm512_mask_shrdv_epi32(a, 0, b, c); + assert_eq_m512i(r, a); + let r = _mm512_mask_shrdv_epi32(a, 0b11111111_11111111, b, c); + let e = _mm512_set1_epi32(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shrdv_epi32() { + let a = _mm512_set1_epi32(8); + let b = _mm512_set1_epi32(2); + let c = _mm512_set1_epi32(1); + let r = _mm512_maskz_shrdv_epi32(0, a, b, c); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shrdv_epi32(0b11111111_11111111, a, b, c); + let e = _mm512_set1_epi32(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shrdv_epi32() { + let a = _mm256_set1_epi32(8); + let b = _mm256_set1_epi32(2); + let c = _mm256_set1_epi32(1); + let r = _mm256_shrdv_epi32(a, b, c); + let e = _mm256_set1_epi32(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shrdv_epi32() { + let a = _mm256_set1_epi32(8); + let b = _mm256_set1_epi32(2); + let c = _mm256_set1_epi32(1); + let r = _mm256_mask_shrdv_epi32(a, 0, b, c); + assert_eq_m256i(r, a); + let r = _mm256_mask_shrdv_epi32(a, 0b11111111, b, c); + let e = _mm256_set1_epi32(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shrdv_epi32() { + let a = _mm256_set1_epi32(8); + let b = _mm256_set1_epi32(2); + let c = _mm256_set1_epi32(1); + let r = _mm256_maskz_shrdv_epi32(0, a, b, c); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shrdv_epi32(0b11111111, a, b, c); + let e = _mm256_set1_epi32(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shrdv_epi32() { + let a = _mm_set1_epi32(8); + let b = _mm_set1_epi32(2); + let c = _mm_set1_epi32(1); + let r = _mm_shrdv_epi32(a, b, c); + let e = _mm_set1_epi32(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shrdv_epi32() { + let a = _mm_set1_epi32(8); + let b = _mm_set1_epi32(2); + let c = _mm_set1_epi32(1); + let r = _mm_mask_shrdv_epi32(a, 0, b, c); + assert_eq_m128i(r, a); + let r = _mm_mask_shrdv_epi32(a, 0b00001111, b, c); + let e = _mm_set1_epi32(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shrdv_epi32() { + let a = _mm_set1_epi32(8); + let b = _mm_set1_epi32(2); + let c = _mm_set1_epi32(1); + let r = _mm_maskz_shrdv_epi32(0, a, b, c); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shrdv_epi32(0b00001111, a, b, c); + let e = _mm_set1_epi32(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shrdv_epi16() { + let a = _mm512_set1_epi16(8); + let b = _mm512_set1_epi16(2); + let c = _mm512_set1_epi16(1); + let r = _mm512_shrdv_epi16(a, b, c); + let e = _mm512_set1_epi16(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shrdv_epi16() { + let a = _mm512_set1_epi16(8); + let b = _mm512_set1_epi16(2); + let c = _mm512_set1_epi16(1); + let r = _mm512_mask_shrdv_epi16(a, 0, b, c); + assert_eq_m512i(r, a); + let r = _mm512_mask_shrdv_epi16(a, 0b11111111_11111111_11111111_11111111, b, c); + let e = _mm512_set1_epi16(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shrdv_epi16() { + let a = _mm512_set1_epi16(8); + let b = _mm512_set1_epi16(2); + let c = _mm512_set1_epi16(1); + let r = _mm512_maskz_shrdv_epi16(0, a, b, c); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shrdv_epi16(0b11111111_11111111_11111111_11111111, a, b, c); + let e = _mm512_set1_epi16(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shrdv_epi16() { + let a = _mm256_set1_epi16(8); + let b = _mm256_set1_epi16(2); + let c = _mm256_set1_epi16(1); + let r = _mm256_shrdv_epi16(a, b, c); + let e = _mm256_set1_epi16(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shrdv_epi16() { + let a = _mm256_set1_epi16(8); + let b = _mm256_set1_epi16(2); + let c = _mm256_set1_epi16(1); + let r = _mm256_mask_shrdv_epi16(a, 0, b, c); + assert_eq_m256i(r, a); + let r = _mm256_mask_shrdv_epi16(a, 0b11111111_11111111, b, c); + let e = _mm256_set1_epi16(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shrdv_epi16() { + let a = _mm256_set1_epi16(8); + let b = _mm256_set1_epi16(2); + let c = _mm256_set1_epi16(1); + let r = _mm256_maskz_shrdv_epi16(0, a, b, c); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shrdv_epi16(0b11111111_11111111, a, b, c); + let e = _mm256_set1_epi16(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shrdv_epi16() { + let a = _mm_set1_epi16(8); + let b = _mm_set1_epi16(2); + let c = _mm_set1_epi16(1); + let r = _mm_shrdv_epi16(a, b, c); + let e = _mm_set1_epi16(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shrdv_epi16() { + let a = _mm_set1_epi16(8); + let b = _mm_set1_epi16(2); + let c = _mm_set1_epi16(1); + let r = _mm_mask_shrdv_epi16(a, 0, b, c); + assert_eq_m128i(r, a); + let r = _mm_mask_shrdv_epi16(a, 0b11111111, b, c); + let e = _mm_set1_epi16(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shrdv_epi16() { + let a = _mm_set1_epi16(8); + let b = _mm_set1_epi16(2); + let c = _mm_set1_epi16(1); + let r = _mm_maskz_shrdv_epi16(0, a, b, c); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shrdv_epi16(0b11111111, a, b, c); + let e = _mm_set1_epi16(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shldi_epi64() { + let a = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(1 << 63); + let r = _mm512_shldi_epi64(a, b, 2); + let e = _mm512_set1_epi64(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shldi_epi64() { + let a = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(1 << 63); + let r = _mm512_mask_shldi_epi64(a, 0, a, b, 2); + assert_eq_m512i(r, a); + let r = _mm512_mask_shldi_epi64(a, 0b11111111, a, b, 2); + let e = _mm512_set1_epi64(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shldi_epi64() { + let a = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(1 << 63); + let r = _mm512_maskz_shldi_epi64(0, a, b, 2); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shldi_epi64(0b11111111, a, b, 2); + let e = _mm512_set1_epi64(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shldi_epi64() { + let a = _mm256_set1_epi64x(1); + let b = _mm256_set1_epi64x(1 << 63); + let r = _mm256_shldi_epi64(a, b, 2); + let e = _mm256_set1_epi64x(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shldi_epi64() { + let a = _mm256_set1_epi64x(1); + let b = _mm256_set1_epi64x(1 << 63); + let r = _mm256_mask_shldi_epi64(a, 0, a, b, 2); + assert_eq_m256i(r, a); + let r = _mm256_mask_shldi_epi64(a, 0b00001111, a, b, 2); + let e = _mm256_set1_epi64x(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shldi_epi64() { + let a = _mm256_set1_epi64x(1); + let b = _mm256_set1_epi64x(1 << 63); + let r = _mm256_maskz_shldi_epi64(0, a, b, 2); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shldi_epi64(0b00001111, a, b, 2); + let e = _mm256_set1_epi64x(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shldi_epi64() { + let a = _mm_set1_epi64x(1); + let b = _mm_set1_epi64x(1 << 63); + let r = _mm_shldi_epi64(a, b, 2); + let e = _mm_set1_epi64x(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shldi_epi64() { + let a = _mm_set1_epi64x(1); + let b = _mm_set1_epi64x(1 << 63); + let r = _mm_mask_shldi_epi64(a, 0, a, b, 2); + assert_eq_m128i(r, a); + let r = _mm_mask_shldi_epi64(a, 0b00000011, a, b, 2); + let e = _mm_set1_epi64x(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shldi_epi64() { + let a = _mm_set1_epi64x(1); + let b = _mm_set1_epi64x(1 << 63); + let r = _mm_maskz_shldi_epi64(0, a, b, 2); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shldi_epi64(0b00000011, a, b, 2); + let e = _mm_set1_epi64x(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shldi_epi32() { + let a = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(1 << 31); + let r = _mm512_shldi_epi32(a, b, 2); + let e = _mm512_set1_epi32(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shldi_epi32() { + let a = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(1 << 31); + let r = _mm512_mask_shldi_epi32(a, 0, a, b, 2); + assert_eq_m512i(r, a); + let r = _mm512_mask_shldi_epi32(a, 0b11111111_11111111, a, b, 2); + let e = _mm512_set1_epi32(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shldi_epi32() { + let a = _mm512_set1_epi32(1); + let b = _mm512_set1_epi32(1 << 31); + let r = _mm512_maskz_shldi_epi32(0, a, b, 2); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shldi_epi32(0b11111111_11111111, a, b, 2); + let e = _mm512_set1_epi32(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shldi_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set1_epi32(1 << 31); + let r = _mm256_shldi_epi32(a, b, 2); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shldi_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set1_epi32(1 << 31); + let r = _mm256_mask_shldi_epi32(a, 0, a, b, 2); + assert_eq_m256i(r, a); + let r = _mm256_mask_shldi_epi32(a, 0b11111111, a, b, 2); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shldi_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set1_epi32(1 << 31); + let r = _mm256_maskz_shldi_epi32(0, a, b, 2); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shldi_epi32(0b11111111, a, b, 2); + let e = _mm256_set1_epi32(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shldi_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set1_epi32(1 << 31); + let r = _mm_shldi_epi32(a, b, 2); + let e = _mm_set1_epi32(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shldi_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set1_epi32(1 << 31); + let r = _mm_mask_shldi_epi32(a, 0, a, b, 2); + assert_eq_m128i(r, a); + let r = _mm_mask_shldi_epi32(a, 0b00001111, a, b, 2); + let e = _mm_set1_epi32(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shldi_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set1_epi32(1 << 31); + let r = _mm_maskz_shldi_epi32(0, a, b, 2); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shldi_epi32(0b00001111, a, b, 2); + let e = _mm_set1_epi32(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shldi_epi16() { + let a = _mm512_set1_epi16(1); + let b = _mm512_set1_epi16(1 << 15); + let r = _mm512_shldi_epi16(a, b, 2); + let e = _mm512_set1_epi16(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shldi_epi16() { + let a = _mm512_set1_epi16(1); + let b = _mm512_set1_epi16(1 << 15); + let r = _mm512_mask_shldi_epi16(a, 0, a, b, 2); + assert_eq_m512i(r, a); + let r = _mm512_mask_shldi_epi16(a, 0b11111111_11111111_11111111_11111111, a, b, 2); + let e = _mm512_set1_epi16(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shldi_epi16() { + let a = _mm512_set1_epi16(1); + let b = _mm512_set1_epi16(1 << 15); + let r = _mm512_maskz_shldi_epi16(0, a, b, 2); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shldi_epi16(0b11111111_11111111_11111111_11111111, a, b, 2); + let e = _mm512_set1_epi16(6); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shldi_epi16() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1 << 15); + let r = _mm256_shldi_epi16(a, b, 2); + let e = _mm256_set1_epi16(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shldi_epi16() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1 << 15); + let r = _mm256_mask_shldi_epi16(a, 0, a, b, 2); + assert_eq_m256i(r, a); + let r = _mm256_mask_shldi_epi16(a, 0b11111111_11111111, a, b, 2); + let e = _mm256_set1_epi16(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shldi_epi16() { + let a = _mm256_set1_epi16(1); + let b = _mm256_set1_epi16(1 << 15); + let r = _mm256_maskz_shldi_epi16(0, a, b, 2); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shldi_epi16(0b11111111_11111111, a, b, 2); + let e = _mm256_set1_epi16(6); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shldi_epi16() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1 << 15); + let r = _mm_shldi_epi16(a, b, 2); + let e = _mm_set1_epi16(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shldi_epi16() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1 << 15); + let r = _mm_mask_shldi_epi16(a, 0, a, b, 2); + assert_eq_m128i(r, a); + let r = _mm_mask_shldi_epi16(a, 0b11111111, a, b, 2); + let e = _mm_set1_epi16(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shldi_epi16() { + let a = _mm_set1_epi16(1); + let b = _mm_set1_epi16(1 << 15); + let r = _mm_maskz_shldi_epi16(0, a, b, 2); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shldi_epi16(0b11111111, a, b, 2); + let e = _mm_set1_epi16(6); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shrdi_epi64() { + let a = _mm512_set1_epi64(8); + let b = _mm512_set1_epi64(2); + let r = _mm512_shrdi_epi64(a, b, 1); + let e = _mm512_set1_epi64(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shrdi_epi64() { + let a = _mm512_set1_epi64(8); + let b = _mm512_set1_epi64(2); + let r = _mm512_mask_shrdi_epi64(a, 0, a, b, 1); + assert_eq_m512i(r, a); + let r = _mm512_mask_shrdi_epi64(a, 0b11111111, a, b, 1); + let e = _mm512_set1_epi64(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shrdi_epi64() { + let a = _mm512_set1_epi64(8); + let b = _mm512_set1_epi64(2); + let r = _mm512_maskz_shrdi_epi64(0, a, b, 1); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shrdi_epi64(0b11111111, a, b, 1); + let e = _mm512_set1_epi64(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shrdi_epi64() { + let a = _mm256_set1_epi64x(8); + let b = _mm256_set1_epi64x(2); + let r = _mm256_shrdi_epi64(a, b, 1); + let e = _mm256_set1_epi64x(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shrdi_epi64() { + let a = _mm256_set1_epi64x(8); + let b = _mm256_set1_epi64x(2); + let r = _mm256_mask_shrdi_epi64(a, 0, a, b, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_shrdi_epi64(a, 0b00001111, a, b, 1); + let e = _mm256_set1_epi64x(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shrdi_epi64() { + let a = _mm256_set1_epi64x(8); + let b = _mm256_set1_epi64x(2); + let r = _mm256_maskz_shrdi_epi64(0, a, b, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shrdi_epi64(0b00001111, a, b, 1); + let e = _mm256_set1_epi64x(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shrdi_epi64() { + let a = _mm_set1_epi64x(8); + let b = _mm_set1_epi64x(2); + let r = _mm_shrdi_epi64(a, b, 1); + let e = _mm_set1_epi64x(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shrdi_epi64() { + let a = _mm_set1_epi64x(8); + let b = _mm_set1_epi64x(2); + let r = _mm_mask_shrdi_epi64(a, 0, a, b, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_shrdi_epi64(a, 0b00000011, a, b, 1); + let e = _mm_set1_epi64x(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shrdi_epi64() { + let a = _mm_set1_epi64x(8); + let b = _mm_set1_epi64x(2); + let r = _mm_maskz_shrdi_epi64(0, a, b, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shrdi_epi64(0b00000011, a, b, 1); + let e = _mm_set1_epi64x(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shrdi_epi32() { + let a = _mm512_set1_epi32(8); + let b = _mm512_set1_epi32(2); + let r = _mm512_shrdi_epi32(a, b, 1); + let e = _mm512_set1_epi32(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shrdi_epi32() { + let a = _mm512_set1_epi32(8); + let b = _mm512_set1_epi32(2); + let r = _mm512_mask_shrdi_epi32(a, 0, a, b, 1); + assert_eq_m512i(r, a); + let r = _mm512_mask_shrdi_epi32(a, 0b11111111_11111111, a, b, 1); + let e = _mm512_set1_epi32(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shrdi_epi32() { + let a = _mm512_set1_epi32(8); + let b = _mm512_set1_epi32(2); + let r = _mm512_maskz_shrdi_epi32(0, a, b, 1); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shrdi_epi32(0b11111111_11111111, a, b, 1); + let e = _mm512_set1_epi32(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shrdi_epi32() { + let a = _mm256_set1_epi32(8); + let b = _mm256_set1_epi32(2); + let r = _mm256_shrdi_epi32(a, b, 1); + let e = _mm256_set1_epi32(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shrdi_epi32() { + let a = _mm256_set1_epi32(8); + let b = _mm256_set1_epi32(2); + let r = _mm256_mask_shrdi_epi32(a, 0, a, b, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_shrdi_epi32(a, 0b11111111, a, b, 1); + let e = _mm256_set1_epi32(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shrdi_epi32() { + let a = _mm256_set1_epi32(8); + let b = _mm256_set1_epi32(2); + let r = _mm256_maskz_shrdi_epi32(0, a, b, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shrdi_epi32(0b11111111, a, b, 1); + let e = _mm256_set1_epi32(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shrdi_epi32() { + let a = _mm_set1_epi32(8); + let b = _mm_set1_epi32(2); + let r = _mm_shrdi_epi32(a, b, 1); + let e = _mm_set1_epi32(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shrdi_epi32() { + let a = _mm_set1_epi32(8); + let b = _mm_set1_epi32(2); + let r = _mm_mask_shrdi_epi32(a, 0, a, b, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_shrdi_epi32(a, 0b00001111, a, b, 1); + let e = _mm_set1_epi32(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shrdi_epi32() { + let a = _mm_set1_epi32(8); + let b = _mm_set1_epi32(2); + let r = _mm_maskz_shrdi_epi32(0, a, b, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shrdi_epi32(0b00001111, a, b, 1); + let e = _mm_set1_epi32(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_shrdi_epi16() { + let a = _mm512_set1_epi16(8); + let b = _mm512_set1_epi16(2); + let r = _mm512_shrdi_epi16(a, b, 1); + let e = _mm512_set1_epi16(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_mask_shrdi_epi16() { + let a = _mm512_set1_epi16(8); + let b = _mm512_set1_epi16(2); + let r = _mm512_mask_shrdi_epi16(a, 0, a, b, 1); + assert_eq_m512i(r, a); + let r = _mm512_mask_shrdi_epi16(a, 0b11111111_11111111_11111111_11111111, a, b, 1); + let e = _mm512_set1_epi16(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2")] + unsafe fn test_mm512_maskz_shrdi_epi16() { + let a = _mm512_set1_epi16(8); + let b = _mm512_set1_epi16(2); + let r = _mm512_maskz_shrdi_epi16(0, a, b, 1); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_shrdi_epi16(0b11111111_11111111_11111111_11111111, a, b, 1); + let e = _mm512_set1_epi16(1); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_shrdi_epi16() { + let a = _mm256_set1_epi16(8); + let b = _mm256_set1_epi16(2); + let r = _mm256_shrdi_epi16(a, b, 1); + let e = _mm256_set1_epi16(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_mask_shrdi_epi16() { + let a = _mm256_set1_epi16(8); + let b = _mm256_set1_epi16(2); + let r = _mm256_mask_shrdi_epi16(a, 0, a, b, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_shrdi_epi16(a, 0b11111111_11111111, a, b, 1); + let e = _mm256_set1_epi16(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm256_maskz_shrdi_epi16() { + let a = _mm256_set1_epi16(8); + let b = _mm256_set1_epi16(2); + let r = _mm256_maskz_shrdi_epi16(0, a, b, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shrdi_epi16(0b11111111_11111111, a, b, 1); + let e = _mm256_set1_epi16(1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_shrdi_epi16() { + let a = _mm_set1_epi16(8); + let b = _mm_set1_epi16(2); + let r = _mm_shrdi_epi16(a, b, 1); + let e = _mm_set1_epi16(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_mask_shrdi_epi16() { + let a = _mm_set1_epi16(8); + let b = _mm_set1_epi16(2); + let r = _mm_mask_shrdi_epi16(a, 0, a, b, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_shrdi_epi16(a, 0b11111111, a, b, 1); + let e = _mm_set1_epi16(1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vbmi2,avx512vl")] + unsafe fn test_mm_maskz_shrdi_epi16() { + let a = _mm_set1_epi16(8); + let b = _mm_set1_epi16(2); + let r = _mm_maskz_shrdi_epi16(0, a, b, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_shrdi_epi16(0b11111111, a, b, 1); + let e = _mm_set1_epi16(1); + assert_eq_m128i(r, e); + } +} diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vnni.rs b/library/stdarch/crates/core_arch/src/x86/avx512vnni.rs new file mode 100644 index 0000000000..ff2c773ec8 --- /dev/null +++ b/library/stdarch/crates/core_arch/src/x86/avx512vnni.rs @@ -0,0 +1,939 @@ +use crate::{ + core_arch::{simd::*, simd_llvm::*, x86::*}, + mem::transmute, +}; + +#[cfg(test)] +use stdarch_test::assert_instr; + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_dpwssd_epi32&expand=2219) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm512_dpwssd_epi32(src: __m512i, a: __m512i, b: __m512i) -> __m512i { + transmute(vpdpwssd(src.as_i32x16(), a.as_i32x16(), b.as_i32x16())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_dpwssd_epi32&expand=2220) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm512_mask_dpwssd_epi32( + src: __m512i, + k: __mmask16, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpwssd_epi32(src, a, b).as_i32x16(); + transmute(simd_select_bitmask(k, r, src.as_i32x16())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_dpwssd_epi32&expand=2221) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm512_maskz_dpwssd_epi32( + k: __mmask16, + src: __m512i, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpwssd_epi32(src, a, b).as_i32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_dpwssd_epi32&expand=2216) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm256_dpwssd_epi32(src: __m256i, a: __m256i, b: __m256i) -> __m256i { + transmute(vpdpwssd256(src.as_i32x8(), a.as_i32x8(), b.as_i32x8())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_dpwssd_epi32&expand=2217) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm256_mask_dpwssd_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpwssd_epi32(src, a, b).as_i32x8(); + transmute(simd_select_bitmask(k, r, src.as_i32x8())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_dpwssd_epi32&expand=2218) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm256_maskz_dpwssd_epi32( + k: __mmask8, + src: __m256i, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpwssd_epi32(src, a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dpwssd_epi32&expand=2213) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm_dpwssd_epi32(src: __m128i, a: __m128i, b: __m128i) -> __m128i { + transmute(vpdpwssd128(src.as_i32x4(), a.as_i32x4(), b.as_i32x4())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_dpwssd_epi32&expand=2214) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm_mask_dpwssd_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let r = _mm_dpwssd_epi32(src, a, b).as_i32x4(); + transmute(simd_select_bitmask(k, r, src.as_i32x4())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_dpwssd_epi32&expand=2215) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssd))] +pub unsafe fn _mm_maskz_dpwssd_epi32(k: __mmask8, src: __m128i, a: __m128i, b: __m128i) -> __m128i { + let r = _mm_dpwssd_epi32(src, a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_dpwssds_epi32&expand=2228) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm512_dpwssds_epi32(src: __m512i, a: __m512i, b: __m512i) -> __m512i { + transmute(vpdpwssds(src.as_i32x16(), a.as_i32x16(), b.as_i32x16())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_dpwssds_epi32&expand=2229) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm512_mask_dpwssds_epi32( + src: __m512i, + k: __mmask16, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpwssds_epi32(src, a, b).as_i32x16(); + transmute(simd_select_bitmask(k, r, src.as_i32x16())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_dpwssds_epi32&expand=2230) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm512_maskz_dpwssds_epi32( + k: __mmask16, + src: __m512i, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpwssds_epi32(src, a, b).as_i32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_dpwssds_epi32&expand=2225) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm256_dpwssds_epi32(src: __m256i, a: __m256i, b: __m256i) -> __m256i { + transmute(vpdpwssds256(src.as_i32x8(), a.as_i32x8(), b.as_i32x8())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_dpwssds_epi32&expand=2226) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm256_mask_dpwssds_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpwssds_epi32(src, a, b).as_i32x8(); + transmute(simd_select_bitmask(k, r, src.as_i32x8())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_dpwssds_epi32&expand=2227) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm256_maskz_dpwssds_epi32( + k: __mmask8, + src: __m256i, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpwssds_epi32(src, a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dpwssds_epi32&expand=2222) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm_dpwssds_epi32(src: __m128i, a: __m128i, b: __m128i) -> __m128i { + transmute(vpdpwssds128(src.as_i32x4(), a.as_i32x4(), b.as_i32x4())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_dpwssds_epi32&expand=2223) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm_mask_dpwssds_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let r = _mm_dpwssds_epi32(src, a, b).as_i32x4(); + transmute(simd_select_bitmask(k, r, src.as_i32x4())) +} + +/// Multiply groups of 2 adjacent pairs of signed 16-bit integers in a with corresponding 16-bit integers in b, producing 2 intermediate signed 32-bit results. Sum these 2 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_dpwssds_epi32&expand=2224) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpwssds))] +pub unsafe fn _mm_maskz_dpwssds_epi32( + k: __mmask8, + src: __m128i, + a: __m128i, + b: __m128i, +) -> __m128i { + let r = _mm_dpwssds_epi32(src, a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_dpbusd_epi32&expand=2201) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm512_dpbusd_epi32(src: __m512i, a: __m512i, b: __m512i) -> __m512i { + transmute(vpdpbusd(src.as_i32x16(), a.as_i32x16(), b.as_i32x16())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_dpbusd_epi32&expand=2202) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm512_mask_dpbusd_epi32( + src: __m512i, + k: __mmask16, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpbusd_epi32(src, a, b).as_i32x16(); + transmute(simd_select_bitmask(k, r, src.as_i32x16())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_dpbusd_epi32&expand=2203) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm512_maskz_dpbusd_epi32( + k: __mmask16, + src: __m512i, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpbusd_epi32(src, a, b).as_i32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_dpbusd_epi32&expand=2198) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm256_dpbusd_epi32(src: __m256i, a: __m256i, b: __m256i) -> __m256i { + transmute(vpdpbusd256(src.as_i32x8(), a.as_i32x8(), b.as_i32x8())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_dpbusd_epi32&expand=2199) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm256_mask_dpbusd_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpbusd_epi32(src, a, b).as_i32x8(); + transmute(simd_select_bitmask(k, r, src.as_i32x8())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_dpbusd_epi32&expand=2200) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm256_maskz_dpbusd_epi32( + k: __mmask8, + src: __m256i, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpbusd_epi32(src, a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dpbusd_epi32&expand=2195) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm_dpbusd_epi32(src: __m128i, a: __m128i, b: __m128i) -> __m128i { + transmute(vpdpbusd128(src.as_i32x4(), a.as_i32x4(), b.as_i32x4())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_dpbusd_epi32&expand=2196) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm_mask_dpbusd_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let r = _mm_dpbusd_epi32(src, a, b).as_i32x4(); + transmute(simd_select_bitmask(k, r, src.as_i32x4())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_dpbusd_epi32&expand=2197) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusd))] +pub unsafe fn _mm_maskz_dpbusd_epi32(k: __mmask8, src: __m128i, a: __m128i, b: __m128i) -> __m128i { + let r = _mm_dpbusd_epi32(src, a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_dpbusds_epi32&expand=2210) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm512_dpbusds_epi32(src: __m512i, a: __m512i, b: __m512i) -> __m512i { + transmute(vpdpbusds(src.as_i32x16(), a.as_i32x16(), b.as_i32x16())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_dpbusds_epi32&expand=2211) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm512_mask_dpbusds_epi32( + src: __m512i, + k: __mmask16, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpbusds_epi32(src, a, b).as_i32x16(); + transmute(simd_select_bitmask(k, r, src.as_i32x16())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_dpbusds_epi32&expand=2212) +#[inline] +#[target_feature(enable = "avx512vnni")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm512_maskz_dpbusds_epi32( + k: __mmask16, + src: __m512i, + a: __m512i, + b: __m512i, +) -> __m512i { + let r = _mm512_dpbusds_epi32(src, a, b).as_i32x16(); + let zero = _mm512_setzero_si512().as_i32x16(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_dpbusds_epi32&expand=2207) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm256_dpbusds_epi32(src: __m256i, a: __m256i, b: __m256i) -> __m256i { + transmute(vpdpbusds256(src.as_i32x8(), a.as_i32x8(), b.as_i32x8())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_dpbusds_epi32&expand=2208) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm256_mask_dpbusds_epi32( + src: __m256i, + k: __mmask8, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpbusds_epi32(src, a, b).as_i32x8(); + transmute(simd_select_bitmask(k, r, src.as_i32x8())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_dpbusds_epi32&expand=2209) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm256_maskz_dpbusds_epi32( + k: __mmask8, + src: __m256i, + a: __m256i, + b: __m256i, +) -> __m256i { + let r = _mm256_dpbusds_epi32(src, a, b).as_i32x8(); + let zero = _mm256_setzero_si256().as_i32x8(); + transmute(simd_select_bitmask(k, r, zero)) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dpbusds_epi32&expand=2204) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm_dpbusds_epi32(src: __m128i, a: __m128i, b: __m128i) -> __m128i { + transmute(vpdpbusds128(src.as_i32x4(), a.as_i32x4(), b.as_i32x4())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_dpbusds_epi32&expand=2205) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm_mask_dpbusds_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { + let r = _mm_dpbusds_epi32(src, a, b).as_i32x4(); + transmute(simd_select_bitmask(k, r, src.as_i32x4())) +} + +/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding signed 8-bit integers in b, producing 4 intermediate signed 16-bit results. Sum these 4 results with the corresponding 32-bit integer in src using signed saturation, and store the packed 32-bit results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_dpbusds_epi32&expand=2206) +#[inline] +#[target_feature(enable = "avx512vnni,avx512vl")] +#[cfg_attr(test, assert_instr(vpdpbusds))] +pub unsafe fn _mm_maskz_dpbusds_epi32( + k: __mmask8, + src: __m128i, + a: __m128i, + b: __m128i, +) -> __m128i { + let r = _mm_dpbusds_epi32(src, a, b).as_i32x4(); + let zero = _mm_setzero_si128().as_i32x4(); + transmute(simd_select_bitmask(k, r, zero)) +} + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.x86.avx512.vpdpwssd.512"] + fn vpdpwssd(src: i32x16, a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.vpdpwssd.256"] + fn vpdpwssd256(src: i32x8, a: i32x8, b: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx512.vpdpwssd.128"] + fn vpdpwssd128(src: i32x4, a: i32x4, b: i32x4) -> i32x4; + + #[link_name = "llvm.x86.avx512.vpdpwssds.512"] + fn vpdpwssds(src: i32x16, a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.vpdpwssds.256"] + fn vpdpwssds256(src: i32x8, a: i32x8, b: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx512.vpdpwssds.128"] + fn vpdpwssds128(src: i32x4, a: i32x4, b: i32x4) -> i32x4; + + #[link_name = "llvm.x86.avx512.vpdpbusd.512"] + fn vpdpbusd(src: i32x16, a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.vpdpbusd.256"] + fn vpdpbusd256(src: i32x8, a: i32x8, b: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx512.vpdpbusd.128"] + fn vpdpbusd128(src: i32x4, a: i32x4, b: i32x4) -> i32x4; + + #[link_name = "llvm.x86.avx512.vpdpbusds.512"] + fn vpdpbusds(src: i32x16, a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.vpdpbusds.256"] + fn vpdpbusds256(src: i32x8, a: i32x8, b: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx512.vpdpbusds.128"] + fn vpdpbusds128(src: i32x4, a: i32x4, b: i32x4) -> i32x4; +} + +#[cfg(test)] +mod tests { + + use crate::core_arch::x86::*; + use stdarch_test::simd_test; + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_dpwssd_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 16 | 1 << 0); + let b = _mm512_set1_epi32(1 << 16 | 1 << 0); + let r = _mm512_dpwssd_epi32(src, a, b); + let e = _mm512_set1_epi32(3); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_mask_dpwssd_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 16 | 1 << 0); + let b = _mm512_set1_epi32(1 << 16 | 1 << 0); + let r = _mm512_mask_dpwssd_epi32(src, 0b00000000_00000000, a, b); + assert_eq_m512i(r, src); + let r = _mm512_mask_dpwssd_epi32(src, 0b11111111_11111111, a, b); + let e = _mm512_set1_epi32(3); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_maskz_dpwssd_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 16 | 1 << 0); + let b = _mm512_set1_epi32(1 << 16 | 1 << 0); + let r = _mm512_maskz_dpwssd_epi32(0b00000000_00000000, src, a, b); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_dpwssd_epi32(0b11111111_11111111, src, a, b); + let e = _mm512_set1_epi32(3); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_dpwssd_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 16 | 1 << 0); + let b = _mm256_set1_epi32(1 << 16 | 1 << 0); + let r = _mm256_dpwssd_epi32(src, a, b); + let e = _mm256_set1_epi32(3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_mask_dpwssd_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 16 | 1 << 0); + let b = _mm256_set1_epi32(1 << 16 | 1 << 0); + let r = _mm256_mask_dpwssd_epi32(src, 0b00000000, a, b); + assert_eq_m256i(r, src); + let r = _mm256_mask_dpwssd_epi32(src, 0b11111111, a, b); + let e = _mm256_set1_epi32(3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_maskz_dpwssd_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 16 | 1 << 0); + let b = _mm256_set1_epi32(1 << 16 | 1 << 0); + let r = _mm256_maskz_dpwssd_epi32(0b00000000, src, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_dpwssd_epi32(0b11111111, src, a, b); + let e = _mm256_set1_epi32(3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_dpwssd_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 16 | 1 << 0); + let b = _mm_set1_epi32(1 << 16 | 1 << 0); + let r = _mm_dpwssd_epi32(src, a, b); + let e = _mm_set1_epi32(3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_mask_dpwssd_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 16 | 1 << 0); + let b = _mm_set1_epi32(1 << 16 | 1 << 0); + let r = _mm_mask_dpwssd_epi32(src, 0b00000000, a, b); + assert_eq_m128i(r, src); + let r = _mm_mask_dpwssd_epi32(src, 0b00001111, a, b); + let e = _mm_set1_epi32(3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_maskz_dpwssd_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 16 | 1 << 0); + let b = _mm_set1_epi32(1 << 16 | 1 << 0); + let r = _mm_maskz_dpwssd_epi32(0b00000000, src, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_dpwssd_epi32(0b00001111, src, a, b); + let e = _mm_set1_epi32(3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_dpwssds_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 16 | 1 << 0); + let b = _mm512_set1_epi32(1 << 16 | 1 << 0); + let r = _mm512_dpwssds_epi32(src, a, b); + let e = _mm512_set1_epi32(3); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_mask_dpwssds_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 16 | 1 << 0); + let b = _mm512_set1_epi32(1 << 16 | 1 << 0); + let r = _mm512_mask_dpwssds_epi32(src, 0b00000000_00000000, a, b); + assert_eq_m512i(r, src); + let r = _mm512_mask_dpwssds_epi32(src, 0b11111111_11111111, a, b); + let e = _mm512_set1_epi32(3); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_maskz_dpwssds_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 16 | 1 << 0); + let b = _mm512_set1_epi32(1 << 16 | 1 << 0); + let r = _mm512_maskz_dpwssds_epi32(0b00000000_00000000, src, a, b); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_dpwssds_epi32(0b11111111_11111111, src, a, b); + let e = _mm512_set1_epi32(3); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_dpwssds_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 16 | 1 << 0); + let b = _mm256_set1_epi32(1 << 16 | 1 << 0); + let r = _mm256_dpwssds_epi32(src, a, b); + let e = _mm256_set1_epi32(3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_mask_dpwssds_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 16 | 1 << 0); + let b = _mm256_set1_epi32(1 << 16 | 1 << 0); + let r = _mm256_mask_dpwssds_epi32(src, 0b00000000, a, b); + assert_eq_m256i(r, src); + let r = _mm256_mask_dpwssds_epi32(src, 0b11111111, a, b); + let e = _mm256_set1_epi32(3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_maskz_dpwssds_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 16 | 1 << 0); + let b = _mm256_set1_epi32(1 << 16 | 1 << 0); + let r = _mm256_maskz_dpwssds_epi32(0b00000000, src, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_dpwssds_epi32(0b11111111, src, a, b); + let e = _mm256_set1_epi32(3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_dpwssds_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 16 | 1 << 0); + let b = _mm_set1_epi32(1 << 16 | 1 << 0); + let r = _mm_dpwssds_epi32(src, a, b); + let e = _mm_set1_epi32(3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_mask_dpwssds_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 16 | 1 << 0); + let b = _mm_set1_epi32(1 << 16 | 1 << 0); + let r = _mm_mask_dpwssds_epi32(src, 0b00000000, a, b); + assert_eq_m128i(r, src); + let r = _mm_mask_dpwssds_epi32(src, 0b00001111, a, b); + let e = _mm_set1_epi32(3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_maskz_dpwssds_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 16 | 1 << 0); + let b = _mm_set1_epi32(1 << 16 | 1 << 0); + let r = _mm_maskz_dpwssds_epi32(0b00000000, src, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_dpwssds_epi32(0b00001111, src, a, b); + let e = _mm_set1_epi32(3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_dpbusd_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm512_dpbusd_epi32(src, a, b); + let e = _mm512_set1_epi32(5); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_mask_dpbusd_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm512_mask_dpbusd_epi32(src, 0b00000000_00000000, a, b); + assert_eq_m512i(r, src); + let r = _mm512_mask_dpbusd_epi32(src, 0b11111111_11111111, a, b); + let e = _mm512_set1_epi32(5); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_maskz_dpbusd_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm512_maskz_dpbusd_epi32(0b00000000_00000000, src, a, b); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_dpbusd_epi32(0b11111111_11111111, src, a, b); + let e = _mm512_set1_epi32(5); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_dpbusd_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm256_dpbusd_epi32(src, a, b); + let e = _mm256_set1_epi32(5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_mask_dpbusd_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm256_mask_dpbusd_epi32(src, 0b00000000, a, b); + assert_eq_m256i(r, src); + let r = _mm256_mask_dpbusd_epi32(src, 0b11111111, a, b); + let e = _mm256_set1_epi32(5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_maskz_dpbusd_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm256_maskz_dpbusd_epi32(0b00000000, src, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_dpbusd_epi32(0b11111111, src, a, b); + let e = _mm256_set1_epi32(5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_dpbusd_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm_dpbusd_epi32(src, a, b); + let e = _mm_set1_epi32(5); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_mask_dpbusd_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm_mask_dpbusd_epi32(src, 0b00000000, a, b); + assert_eq_m128i(r, src); + let r = _mm_mask_dpbusd_epi32(src, 0b00001111, a, b); + let e = _mm_set1_epi32(5); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_maskz_dpbusd_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm_maskz_dpbusd_epi32(0b00000000, src, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_dpbusd_epi32(0b00001111, src, a, b); + let e = _mm_set1_epi32(5); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_dpbusds_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm512_dpbusds_epi32(src, a, b); + let e = _mm512_set1_epi32(5); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_mask_dpbusds_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm512_mask_dpbusds_epi32(src, 0b00000000_00000000, a, b); + assert_eq_m512i(r, src); + let r = _mm512_mask_dpbusds_epi32(src, 0b11111111_11111111, a, b); + let e = _mm512_set1_epi32(5); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni")] + unsafe fn test_mm512_maskz_dpbusds_epi32() { + let src = _mm512_set1_epi32(1); + let a = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm512_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm512_maskz_dpbusds_epi32(0b00000000_00000000, src, a, b); + assert_eq_m512i(r, _mm512_setzero_si512()); + let r = _mm512_maskz_dpbusds_epi32(0b11111111_11111111, src, a, b); + let e = _mm512_set1_epi32(5); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_dpbusds_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm256_dpbusds_epi32(src, a, b); + let e = _mm256_set1_epi32(5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_mask_dpbusds_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm256_mask_dpbusds_epi32(src, 0b00000000, a, b); + assert_eq_m256i(r, src); + let r = _mm256_mask_dpbusds_epi32(src, 0b11111111, a, b); + let e = _mm256_set1_epi32(5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm256_maskz_dpbusds_epi32() { + let src = _mm256_set1_epi32(1); + let a = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm256_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm256_maskz_dpbusds_epi32(0b00000000, src, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_dpbusds_epi32(0b11111111, src, a, b); + let e = _mm256_set1_epi32(5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_dpbusds_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm_dpbusds_epi32(src, a, b); + let e = _mm_set1_epi32(5); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_mask_dpbusds_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm_mask_dpbusds_epi32(src, 0b00000000, a, b); + assert_eq_m128i(r, src); + let r = _mm_mask_dpbusds_epi32(src, 0b00001111, a, b); + let e = _mm_set1_epi32(5); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512vnni,avx512vl")] + unsafe fn test_mm_maskz_dpbusds_epi32() { + let src = _mm_set1_epi32(1); + let a = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let b = _mm_set1_epi32(1 << 24 | 1 << 16 | 1 << 8 | 1 << 0); + let r = _mm_maskz_dpbusds_epi32(0b00000000, src, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_dpbusds_epi32(0b00001111, src, a, b); + let e = _mm_set1_epi32(5); + assert_eq_m128i(r, e); + } +} diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vpclmulqdq.rs b/library/stdarch/crates/core_arch/src/x86/avx512vpclmulqdq.rs index 831ab7f642..860fea46fc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512vpclmulqdq.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512vpclmulqdq.rs @@ -9,7 +9,7 @@ use crate::core_arch::x86::__m256i; use crate::core_arch::x86::__m512i; #[cfg(test)] -use crate::stdarch_test::assert_instr; +use stdarch_test::assert_instr; #[allow(improper_ctypes)] extern "C" { diff --git a/library/stdarch/crates/core_arch/src/x86/cpuid.rs b/library/stdarch/crates/core_arch/src/x86/cpuid.rs index f292ae7b54..42cc95b4d0 100644 --- a/library/stdarch/crates/core_arch/src/x86/cpuid.rs +++ b/library/stdarch/crates/core_arch/src/x86/cpuid.rs @@ -55,26 +55,33 @@ pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult { let ebx; let ecx; let edx; + #[cfg(target_arch = "x86")] { - llvm_asm!("cpuid" - : "={eax}"(eax), "={ebx}"(ebx), "={ecx}"(ecx), "={edx}"(edx) - : "{eax}"(leaf), "{ecx}"(sub_leaf) - : :); + asm!( + "cpuid", + inlateout("eax") leaf => eax, + lateout("ebx") ebx, + inlateout("ecx") sub_leaf => ecx, + lateout("edx") edx, + options(nostack, preserves_flags), + ); } #[cfg(target_arch = "x86_64")] { - // x86-64 uses %rbx as the base register, so preserve it. + // x86-64 uses `rbx` as the base register, so preserve it. // This works around a bug in LLVM with ASAN enabled: // https://bugs.llvm.org/show_bug.cgi?id=17907 - llvm_asm!(r#" - mov %rbx, %rsi - cpuid - xchg %rbx, %rsi - "# - : "={eax}"(eax), "={esi}"(ebx), "={ecx}"(ecx), "={edx}"(edx) - : "{eax}"(leaf), "{ecx}"(sub_leaf) - : :); + asm!( + "mov rsi, rbx", + "cpuid", + "xchg rsi, rbx", + inlateout("eax") leaf => eax, + lateout("esi") ebx, + inlateout("ecx") sub_leaf => ecx, + lateout("edx") edx, + options(nostack, preserves_flags), + ); } CpuidResult { eax, ebx, ecx, edx } } diff --git a/library/stdarch/crates/core_arch/src/x86/fxsr.rs b/library/stdarch/crates/core_arch/src/x86/fxsr.rs index b1bac1a0ac..4a39bb8de9 100644 --- a/library/stdarch/crates/core_arch/src/x86/fxsr.rs +++ b/library/stdarch/crates/core_arch/src/x86/fxsr.rs @@ -87,7 +87,7 @@ mod tests { } impl fmt::Debug for FxsaveArea { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[")?; for i in 0..self.data.len() { write!(f, "{}", self.data[i])?; diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs index 271707ecef..5f3f2e97cf 100644 --- a/library/stdarch/crates/core_arch/src/x86/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86/mod.rs @@ -296,6 +296,37 @@ types! { /// suffixed with "pd" (or otherwise contain "pd"). Not to be confused with /// "ps" which is used for `__m512`. pub struct __m512d(f64, f64, f64, f64, f64, f64, f64, f64); + + /// 128-bit wide set of eight 'u16' types, x86-specific + /// + /// This type is representing a 128-bit SIMD register which internally is consisted of + /// eight packed `u16` instances. It's purpose is for bf16 related intrinsic + /// implementations. + pub struct __m128bh(u16, u16, u16, u16, u16, u16, u16, u16); + + /// 256-bit wide set of 16 'u16' types, x86-specific + /// + /// This type is the same as the `__m128bh` type defined by Intel, + /// representing a 256-bit SIMD register which internally is consisted of + /// 16 packed `u16` instances. It's purpose is for bf16 related intrinsic + /// implementations. + pub struct __m256bh( + u16, u16, u16, u16, u16, u16, u16, u16, + u16, u16, u16, u16, u16, u16, u16, u16 + ); + + /// 512-bit wide set of 32 'u16' types, x86-specific + /// + /// This type is the same as the `__m128bh` type defined by Intel, + /// representing a 512-bit SIMD register which internally is consisted of + /// 32 packed `u16` instances. It's purpose is for bf16 related intrinsic + /// implementations. + pub struct __m512bh( + u16, u16, u16, u16, u16, u16, u16, u16, + u16, u16, u16, u16, u16, u16, u16, u16, + u16, u16, u16, u16, u16, u16, u16, u16, + u16, u16, u16, u16, u16, u16, u16, u16 + ); } /// The `__mmask64` type used in AVX-512 intrinsics, a 64-bit integer @@ -495,6 +526,24 @@ impl m256Ext for __m256 { } } +#[allow(non_camel_case_types)] +#[unstable(feature = "stdsimd_internal", issue = "none")] +pub(crate) trait m256dExt: Sized { + fn as_m256d(self) -> __m256d; + + #[inline] + fn as_f64x4(self) -> crate::core_arch::simd::f64x4 { + unsafe { transmute(self.as_m256d()) } + } +} + +impl m256dExt for __m256d { + #[inline] + fn as_m256d(self) -> Self { + self + } +} + #[allow(non_camel_case_types)] #[unstable(feature = "stdsimd_internal", issue = "none")] pub(crate) trait m512iExt: Sized { @@ -584,6 +633,105 @@ impl m512dExt for __m512d { } } +#[allow(non_camel_case_types)] +#[unstable(feature = "stdsimd_internal", issue = "none")] +pub(crate) trait m128bhExt: Sized { + fn as_m128bh(self) -> __m128bh; + + #[inline] + fn as_u16x8(self) -> crate::core_arch::simd::u16x8 { + unsafe { transmute(self.as_m128bh()) } + } + + #[inline] + fn as_i16x8(self) -> crate::core_arch::simd::i16x8 { + unsafe { transmute(self.as_m128bh()) } + } + + #[inline] + fn as_u32x4(self) -> crate::core_arch::simd::u32x4 { + unsafe { transmute(self.as_m128bh()) } + } + + #[inline] + fn as_i32x4(self) -> crate::core_arch::simd::i32x4 { + unsafe { transmute(self.as_m128bh()) } + } +} + +impl m128bhExt for __m128bh { + #[inline] + fn as_m128bh(self) -> Self { + self + } +} + +#[allow(non_camel_case_types)] +#[unstable(feature = "stdsimd_internal", issue = "none")] +pub(crate) trait m256bhExt: Sized { + fn as_m256bh(self) -> __m256bh; + + #[inline] + fn as_u16x16(self) -> crate::core_arch::simd::u16x16 { + unsafe { transmute(self.as_m256bh()) } + } + + #[inline] + fn as_i16x16(self) -> crate::core_arch::simd::i16x16 { + unsafe { transmute(self.as_m256bh()) } + } + + #[inline] + fn as_u32x8(self) -> crate::core_arch::simd::u32x8 { + unsafe { transmute(self.as_m256bh()) } + } + + #[inline] + fn as_i32x8(self) -> crate::core_arch::simd::i32x8 { + unsafe { transmute(self.as_m256bh()) } + } +} + +impl m256bhExt for __m256bh { + #[inline] + fn as_m256bh(self) -> Self { + self + } +} + +#[allow(non_camel_case_types)] +#[unstable(feature = "stdsimd_internal", issue = "none")] +pub(crate) trait m512bhExt: Sized { + fn as_m512bh(self) -> __m512bh; + + #[inline] + fn as_u16x32(self) -> crate::core_arch::simd::u16x32 { + unsafe { transmute(self.as_m512bh()) } + } + + #[inline] + fn as_i16x32(self) -> crate::core_arch::simd::i16x32 { + unsafe { transmute(self.as_m512bh()) } + } + + #[inline] + fn as_u32x16(self) -> crate::core_arch::simd::u32x16 { + unsafe { transmute(self.as_m512bh()) } + } + + #[inline] + fn as_i32x16(self) -> crate::core_arch::simd::i32x16 { + unsafe { transmute(self.as_m512bh()) } + } +} + +impl m512bhExt for __m512bh { + #[inline] + fn as_m512bh(self) -> Self { + self + } +} + mod eflags; pub use self::eflags::*; @@ -675,27 +823,28 @@ pub use self::avx512cd::*; mod avx512ifma; pub use self::avx512ifma::*; -#[cfg(not(bootstrap))] +mod avx512vbmi; +pub use self::avx512vbmi::*; + +mod avx512vbmi2; +pub use self::avx512vbmi2::*; + +mod avx512vnni; +pub use self::avx512vnni::*; + mod avx512bitalg; -#[cfg(not(bootstrap))] pub use self::avx512bitalg::*; -#[cfg(not(bootstrap))] mod avx512gfni; -#[cfg(not(bootstrap))] pub use self::avx512gfni::*; mod avx512vpopcntdq; pub use self::avx512vpopcntdq::*; -#[cfg(not(bootstrap))] mod avx512vaes; -#[cfg(not(bootstrap))] pub use self::avx512vaes::*; -#[cfg(not(bootstrap))] mod avx512vpclmulqdq; -#[cfg(not(bootstrap))] pub use self::avx512vpclmulqdq::*; mod bt; @@ -706,3 +855,6 @@ pub use self::rtm::*; mod f16c; pub use self::f16c::*; + +mod avx512bf16; +pub use self::avx512bf16::*; diff --git a/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs b/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs index 0e1bebae9e..a9d5167b91 100644 --- a/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs +++ b/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs @@ -8,7 +8,7 @@ use crate::core_arch::x86::__m128i; #[cfg(test)] -use crate::stdarch_test::assert_instr; +use stdarch_test::assert_instr; #[allow(improper_ctypes)] extern "C" { diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index f52ece769d..7835cb461a 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -1243,10 +1243,9 @@ pub unsafe fn _mm_loadr_ps(p: *const f32) -> __m128 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si64) #[inline] #[target_feature(enable = "sse")] -#[cfg_attr(all(test, not(target_arch = "x86")), assert_instr(movq))] #[stable(feature = "simd_x86_mm_loadu_si64", since = "1.46.0")] pub unsafe fn _mm_loadu_si64(mem_addr: *const u8) -> __m128i { - transmute(i64x2(0, ptr::read_unaligned(mem_addr as *const i64))) + transmute(i64x2(ptr::read_unaligned(mem_addr as *const i64), 0)) } /// Stores the lowest 32 bit float of `a` into memory. @@ -3083,7 +3082,7 @@ mod tests { unsafe fn test_mm_loadu_si64() { let a = _mm_setr_epi64x(5, 6); let r = _mm_loadu_si64(&a as *const _ as *const _); - assert_eq_m128i(r, _mm_set_epi64x(5, 0)); + assert_eq_m128i(r, _mm_setr_epi64x(5, 0)); } #[simd_test(enable = "sse")] diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index 947b196f26..12e7506f02 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -4724,7 +4724,7 @@ mod tests { assert_eq!(vals[1], 2.0); } - #[simd_test(enable = "sse")] + #[simd_test(enable = "sse2")] unsafe fn test_mm_storeu_pd() { let mut mem = Memory { data: [0.0f64; 4] }; let vals = &mut mem.data; diff --git a/library/stdarch/crates/core_arch/src/x86/test.rs b/library/stdarch/crates/core_arch/src/x86/test.rs index 9014d66fd0..c1f974133c 100644 --- a/library/stdarch/crates/core_arch/src/x86/test.rs +++ b/library/stdarch/crates/core_arch/src/x86/test.rs @@ -97,7 +97,7 @@ mod x86_polyfill { union A { a: __m128i, b: [i64; 2], - }; + } let mut a = A { a }; a.b[idx as usize] = val; a.a @@ -109,7 +109,7 @@ mod x86_polyfill { union A { a: __m256i, b: [i64; 4], - }; + } let mut a = A { a }; a.b[idx as usize] = val; a.a diff --git a/library/stdarch/crates/core_arch/src/x86/xsave.rs b/library/stdarch/crates/core_arch/src/x86/xsave.rs index 5e2148840b..30f807e447 100644 --- a/library/stdarch/crates/core_arch/src/x86/xsave.rs +++ b/library/stdarch/crates/core_arch/src/x86/xsave.rs @@ -196,7 +196,7 @@ mod tests { } impl fmt::Debug for XsaveArea { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[")?; for i in 0..self.data.len() { write!(f, "{}", self.data[i])?; diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs index f216a47f49..cf1b4b6220 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs @@ -1,8 +1,561 @@ -//use crate::{ -// -// core_arch::{simd::*, simd_llvm::*, x86::*}, -// mem::transmute, -//}; +use crate::{ + core_arch::{simd::*, simd_llvm::*, x86::*, x86_64::*}, + mem::transmute, +}; + +#[cfg(test)] +use stdarch_test::assert_instr; + +/// Convert the lower double-precision (64-bit) floating-point element in a to a 64-bit integer, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_i64&expand=1792) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2si))] +pub unsafe fn _mm_cvtsd_i64(a: __m128d) -> i64 { + _mm_cvtsd_si64(a) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to a 64-bit integer, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_i64&expand=1894) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2si))] +pub unsafe fn _mm_cvtss_i64(a: __m128) -> i64 { + _mm_cvtss_si64(a) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to an unsigned 64-bit integer, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_u64&expand=1902) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2usi))] +pub unsafe fn _mm_cvtss_u64(a: __m128) -> u64 { + transmute(vcvtss2usi64(a.as_f32x4(), _MM_FROUND_CUR_DIRECTION)) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to an unsigned 64-bit integer, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_u64&expand=1800) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2usi))] +pub unsafe fn _mm_cvtsd_u64(a: __m128d) -> u64 { + transmute(vcvtsd2usi64(a.as_f64x2(), _MM_FROUND_CUR_DIRECTION)) +} + +/// Convert the signed 64-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=mm_cvti32_ss&expand=1643) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsi2ss))] +pub unsafe fn _mm_cvti64_ss(a: __m128, b: i64) -> __m128 { + let b = b as f32; + let r = simd_insert(a, 0, b); + transmute(r) +} + +/// Convert the signed 64-bit integer b to a double-precision (64-bit) floating-point element, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvti64_sd&expand=1644) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsi2sd))] +pub unsafe fn _mm_cvti64_sd(a: __m128d, b: i64) -> __m128d { + let b = b as f64; + let r = simd_insert(a, 0, b); + transmute(r) +} + +/// Convert the unsigned 64-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu64_ss&expand=2035) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(mov))] // should be vcvtusi2ss +pub unsafe fn _mm_cvtu64_ss(a: __m128, b: u64) -> __m128 { + let b = b as f32; + let r = simd_insert(a, 0, b); + transmute(r) +} + +/// Convert the unsigned 64-bit integer b to a double-precision (64-bit) floating-point element, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu64_sd&expand=2034) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(mov))] // should be vcvtusi2sd +pub unsafe fn _mm_cvtu64_sd(a: __m128d, b: u64) -> __m128d { + let b = b as f64; + let r = simd_insert(a, 0, b); + transmute(r) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to a 64-bit integer with truncation, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_i64&expand=2016) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2si))] +pub unsafe fn _mm_cvttsd_i64(a: __m128d) -> i64 { + transmute(vcvtsd2si64(a.as_f64x2(), _MM_FROUND_CUR_DIRECTION)) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to an unsigned 64-bit integer with truncation, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_u64&expand=2021) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2usi))] +pub unsafe fn _mm_cvttsd_u64(a: __m128d) -> u64 { + transmute(vcvtsd2usi64(a.as_f64x2(), _MM_FROUND_CUR_DIRECTION)) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to a 64-bit integer with truncation, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=#text=_mm_cvttss_i64&expand=2023) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2si))] +pub unsafe fn _mm_cvttss_i64(a: __m128) -> i64 { + transmute(vcvtss2si64(a.as_f32x4(), _MM_FROUND_CUR_DIRECTION)) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to an unsigned 64-bit integer with truncation, and store the result in dst. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_u64&expand=2027) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2usi))] +pub unsafe fn _mm_cvttss_u64(a: __m128) -> u64 { + transmute(vcvtss2usi64(a.as_f32x4(), _MM_FROUND_CUR_DIRECTION)) +} + +/// Convert the signed 64-bit integer b to a double-precision (64-bit) floating-point element, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst. +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundi64_sd&expand=1313) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsi2sd, rounding = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_cvt_roundi64_sd(a: __m128d, b: i64, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsi2sd64(a, b, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the signed 64-bit integer b to a double-precision (64-bit) floating-point element, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst. +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsi64_sd&expand=1367) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsi2sd, rounding = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_cvt_roundsi64_sd(a: __m128d, b: i64, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsi2sd64(a, b, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the signed 64-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundi64_ss&expand=1314) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsi2ss, rounding = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_cvt_roundi64_ss(a: __m128, b: i64, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtsi2ss64(a, b, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the unsigned 64-bit integer b to a double-precision (64-bit) floating-point element, store the result in the lower element of dst, and copy the upper element from a to the upper element of dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundu64_sd&expand=1379) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtusi2sd, rounding = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_cvt_roundu64_sd(a: __m128d, b: u64, rounding: i32) -> __m128d { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtusi2sd64(a, b, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the signed 64-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst. +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsi64_ss&expand=1368) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsi2ss, rounding = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_cvt_roundsi64_ss(a: __m128, b: i64, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtsi2ss64(a, b, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the unsigned 64-bit integer b to a single-precision (32-bit) floating-point element, store the result in the lower element of dst, and copy the upper 3 packed elements from a to the upper elements of dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundu64_ss&expand=1380) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtusi2ss, rounding = 8))] +#[rustc_args_required_const(2)] +pub unsafe fn _mm_cvt_roundu64_ss(a: __m128, b: u64, rounding: i32) -> __m128 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtusi2ss64(a, b, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to a 64-bit integer, and store the result in dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_si64&expand=1360) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2si, rounding = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvt_roundsd_si64(a: __m128d, rounding: i32) -> i64 { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsd2si64(a, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to a 64-bit integer, and store the result in dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_i64&expand=1358) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2si, rounding = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvt_roundsd_i64(a: __m128d, rounding: i32) -> i64 { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsd2si64(a, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to an unsigned 64-bit integer, and store the result in dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundsd_u64&expand=1365) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2usi, rounding = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvt_roundsd_u64(a: __m128d, rounding: i32) -> u64 { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsd2usi64(a, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to a 64-bit integer, and store the result in dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_si64&expand=1375) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2si, rounding = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvt_roundss_si64(a: __m128, rounding: i32) -> i64 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtss2si64(a, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to a 64-bit integer, and store the result in dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_i64&expand=1370) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2si, rounding = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvt_roundss_i64(a: __m128, rounding: i32) -> i64 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtss2si64(a, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to an unsigned 64-bit integer, and store the result in dst.\ +/// Rounding is done according to the rounding\[3:0\] parameter, which can be one of:\ +/// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and suppress exceptions\ +/// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and suppress exceptions\ +/// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress exceptions\ +/// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress exceptions\ +/// _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see _MM_SET_ROUNDING_MODE +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_roundss_u64&expand=1377) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2usi, rounding = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvt_roundss_u64(a: __m128, rounding: i32) -> u64 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtss2usi64(a, $imm4) + }; + } + let r = constify_imm4_round!(rounding, call); + transmute(r) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to a 64-bit integer with truncation, and store the result in dst.\ +/// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_si64&expand=1931) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2si, sae = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvtt_roundsd_si64(a: __m128d, sae: i32) -> i64 { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsd2si64(a, $imm4) + }; + } + let r = constify_imm4_sae!(sae, call); + transmute(r) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to a 64-bit integer with truncation, and store the result in dst.\ +/// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_i64&expand=1929) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2si, sae = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvtt_roundsd_i64(a: __m128d, sae: i32) -> i64 { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsd2si64(a, $imm4) + }; + } + let r = constify_imm4_sae!(sae, call); + transmute(r) +} + +/// Convert the lower double-precision (64-bit) floating-point element in a to an unsigned 64-bit integer with truncation, and store the result in dst.\ +/// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundsd_u64&expand=1933) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtsd2usi, sae = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvtt_roundsd_u64(a: __m128d, sae: i32) -> u64 { + let a = a.as_f64x2(); + macro_rules! call { + ($imm4:expr) => { + vcvtsd2usi64(a, $imm4) + }; + } + let r = constify_imm4_sae!(sae, call); + transmute(r) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to a 64-bit integer with truncation, and store the result in dst.\ +/// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_i64&expand=1935) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2si, sae = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvtt_roundss_i64(a: __m128, sae: i32) -> i64 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtss2si64(a, $imm4) + }; + } + let r = constify_imm4_sae!(sae, call); + transmute(r) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to a 64-bit integer with truncation, and store the result in dst.\ +/// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_si64&expand=1937) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2si, sae = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvtt_roundss_si64(a: __m128, sae: i32) -> i64 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtss2si64(a, $imm4) + }; + } + let r = constify_imm4_sae!(sae, call); + transmute(r) +} + +/// Convert the lower single-precision (32-bit) floating-point element in a to an unsigned 64-bit integer with truncation, and store the result in dst.\ +/// Exceptions can be suppressed by passing _MM_FROUND_NO_EXC in the sae parameter. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_roundss_u64&expand=1939) +#[inline] +#[target_feature(enable = "avx512f")] +#[cfg_attr(test, assert_instr(vcvtss2usi, sae = 8))] +#[rustc_args_required_const(1)] +pub unsafe fn _mm_cvtt_roundss_u64(a: __m128, sae: i32) -> u64 { + let a = a.as_f32x4(); + macro_rules! call { + ($imm4:expr) => { + vcvtss2usi64(a, $imm4) + }; + } + let r = constify_imm4_sae!(sae, call); + transmute(r) +} + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.x86.avx512.vcvtss2si64"] + fn vcvtss2si64(a: f32x4, rounding: i32) -> i64; + #[link_name = "llvm.x86.avx512.vcvtss2usi64"] + fn vcvtss2usi64(a: f32x4, rounding: i32) -> u64; + #[link_name = "llvm.x86.avx512.vcvtsd2si64"] + fn vcvtsd2si64(a: f64x2, rounding: i32) -> i64; + #[link_name = "llvm.x86.avx512.vcvtsd2usi64"] + fn vcvtsd2usi64(a: f64x2, rounding: i32) -> u64; + + #[link_name = "llvm.x86.avx512.cvtsi2ss64"] + fn vcvtsi2ss64(a: f32x4, b: i64, rounding: i32) -> f32x4; + #[link_name = "llvm.x86.avx512.cvtsi2sd64"] + fn vcvtsi2sd64(a: f64x2, b: i64, rounding: i32) -> f64x2; + #[link_name = "llvm.x86.avx512.cvtusi642ss"] + fn vcvtusi2ss64(a: f32x4, b: u64, rounding: i32) -> f32x4; + #[link_name = "llvm.x86.avx512.cvtusi642sd"] + fn vcvtusi2sd64(a: f64x2, b: u64, rounding: i32) -> f64x2; +} #[cfg(test)] mod tests { @@ -15,33 +568,60 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_abs_epi64() { - let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); + let a = _mm512_set_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); let r = _mm512_abs_epi64(a); - let e = _mm512_setr_epi64(0, 1, 1, i64::MAX, i64::MAX.wrapping_add(1), 100, 100, 32); + let e = _mm512_set_epi64(0, 1, 1, i64::MAX, i64::MAX.wrapping_add(1), 100, 100, 32); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_abs_epi64() { - let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); + let a = _mm512_set_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); let r = _mm512_mask_abs_epi64(a, 0, a); assert_eq_m512i(r, a); - let r = _mm512_mask_abs_epi64(a, 0b00001111, a); - let e = _mm512_setr_epi64(0, 1, 1, i64::MAX, i64::MIN, 100, -100, -32); + let r = _mm512_mask_abs_epi64(a, 0b11111111, a); + let e = _mm512_set_epi64(0, 1, 1, i64::MAX, i64::MIN, 100, 100, 32); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_abs_epi64() { - #[rustfmt::skip] - let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); + let a = _mm512_set_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); let r = _mm512_maskz_abs_epi64(0, a); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_abs_epi64(0b00001111, a); - let e = _mm512_setr_epi64(0, 1, 1, i64::MAX, 0, 0, 0, 0); + let r = _mm512_maskz_abs_epi64(0b11111111, a); + let e = _mm512_set_epi64(0, 1, 1, i64::MAX, i64::MIN, 100, 100, 32); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_abs_epi64() { + let a = _mm256_set_epi64x(i64::MAX, i64::MIN, 100, -100); + let r = _mm256_abs_epi64(a); + let e = _mm256_set_epi64x(i64::MAX, i64::MAX.wrapping_add(1), 100, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_abs_epi64() { + let a = _mm256_set_epi64x(i64::MAX, i64::MIN, 100, -100); + let r = _mm256_mask_abs_epi64(a, 0, a); + assert_eq_m256i(r, a); + let r = _mm256_mask_abs_epi64(a, 0b00001111, a); + let e = _mm256_set_epi64x(i64::MAX, i64::MAX.wrapping_add(1), 100, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_abs_epi64() { + let a = _mm256_set_epi64x(i64::MAX, i64::MIN, 100, -100); + let r = _mm256_maskz_abs_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_abs_epi64(0b00001111, a); + let e = _mm256_set_epi64x(i64::MAX, i64::MAX.wrapping_add(1), 100, 100); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_abs_pd() { let a = _mm512_setr_pd(0., 1., -1., f64::MAX, f64::MIN, 100., -100., -32.); @@ -60,15 +640,6 @@ mod tests { assert_eq_m512d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_add_epi64() { - let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); - let b = _mm512_set1_epi64(1); - let r = _mm512_add_epi64(a, b); - let e = _mm512_setr_epi64(1, 2, 0, i64::MIN, i64::MIN + 1, 101, -99, -31); - assert_eq_m512i(r, e); - } - #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mov_epi64() { let src = _mm512_set1_epi64(1); @@ -88,6 +659,44 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mov_epi64() { + let src = _mm256_set1_epi64x(1); + let a = _mm256_set1_epi64x(2); + let r = _mm256_mask_mov_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_mov_epi64(src, 0b00001111, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mov_epi64() { + let a = _mm256_set1_epi64x(2); + let r = _mm256_maskz_mov_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_mov_epi64(0b00001111, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mov_epi64() { + let src = _mm_set1_epi64x(1); + let a = _mm_set1_epi64x(2); + let r = _mm_mask_mov_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_mov_epi64(src, 0b00000011, a); + assert_eq_m128i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mov_epi64() { + let a = _mm_set1_epi64x(2); + let r = _mm_maskz_mov_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_mov_epi64(0b00000011, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mov_pd() { let src = _mm512_set1_pd(1.); @@ -107,6 +716,53 @@ mod tests { assert_eq_m512d(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mov_pd() { + let src = _mm256_set1_pd(1.); + let a = _mm256_set1_pd(2.); + let r = _mm256_mask_mov_pd(src, 0, a); + assert_eq_m256d(r, src); + let r = _mm256_mask_mov_pd(src, 0b00001111, a); + assert_eq_m256d(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mov_pd() { + let a = _mm256_set1_pd(2.); + let r = _mm256_maskz_mov_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_mov_pd(0b00001111, a); + assert_eq_m256d(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mov_pd() { + let src = _mm_set1_pd(1.); + let a = _mm_set1_pd(2.); + let r = _mm_mask_mov_pd(src, 0, a); + assert_eq_m128d(r, src); + let r = _mm_mask_mov_pd(src, 0b00000011, a); + assert_eq_m128d(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mov_pd() { + let a = _mm_set1_pd(2.); + let r = _mm_maskz_mov_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_mov_pd(0b00000011, a); + assert_eq_m128d(r, a); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_add_epi64() { + let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); + let b = _mm512_set1_epi64(1); + let r = _mm512_add_epi64(a, b); + let e = _mm512_setr_epi64(1, 2, 0, i64::MIN, i64::MIN + 1, 101, -99, -31); + assert_eq_m512i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_add_epi64() { let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); @@ -120,11 +776,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_add_epi64() { - #[rustfmt::skip] - let a = _mm512_setr_epi64( - 0, 1, -1, i64::MAX, - i64::MIN, 100, -100, -32 - ); + let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); let b = _mm512_set1_epi64(1); let r = _mm512_maskz_add_epi64(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); @@ -133,6 +785,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_add_epi64() { + let a = _mm256_set_epi64x(1, -1, i64::MAX, i64::MIN); + let b = _mm256_set1_epi64x(1); + let r = _mm256_mask_add_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_add_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(2, 0, i64::MIN, i64::MIN + 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_add_epi64() { + let a = _mm256_set_epi64x(1, -1, i64::MAX, i64::MIN); + let b = _mm256_set1_epi64x(1); + let r = _mm256_maskz_add_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_add_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(2, 0, i64::MIN, i64::MIN + 1); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_add_epi64() { + let a = _mm_set_epi64x(i64::MAX, i64::MIN); + let b = _mm_set1_epi64x(1); + let r = _mm_mask_add_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_add_epi64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(i64::MIN, i64::MIN + 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_add_epi64() { + let a = _mm_set_epi64x(i64::MAX, i64::MIN); + let b = _mm_set1_epi64x(1); + let r = _mm_maskz_add_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_add_epi64(0b00000011, a, b); + let e = _mm_set_epi64x(i64::MIN, i64::MIN + 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_add_pd() { let a = _mm512_setr_pd(0., 1., -1., f64::MAX, f64::MIN, 100., -100., -32.); @@ -164,6 +860,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_add_pd() { + let a = _mm256_set_pd(1., -1., f64::MAX, f64::MIN); + let b = _mm256_set1_pd(1.); + let r = _mm256_mask_add_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_add_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(2., 0., f64::MAX, f64::MIN + 1.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_add_pd() { + let a = _mm256_set_pd(1., -1., f64::MAX, f64::MIN); + let b = _mm256_set1_pd(1.); + let r = _mm256_maskz_add_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_add_pd(0b00001111, a, b); + let e = _mm256_set_pd(2., 0., f64::MAX, f64::MIN + 1.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_add_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set1_pd(1.); + let r = _mm_mask_add_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_add_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(f64::MAX, f64::MIN + 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_add_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set1_pd(1.); + let r = _mm_maskz_add_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_add_pd(0b00000011, a, b); + let e = _mm_set_pd(f64::MAX, f64::MIN + 1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sub_epi64() { let a = _mm512_setr_epi64(0, 1, -1, i64::MAX, i64::MIN, 100, -100, -32); @@ -195,6 +935,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sub_epi64() { + let a = _mm256_set_epi64x(1, -1, i64::MAX, i64::MIN); + let b = _mm256_set1_epi64x(1); + let r = _mm256_mask_sub_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_sub_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(0, -2, i64::MAX - 1, i64::MAX); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sub_epi64() { + let a = _mm256_set_epi64x(1, -1, i64::MAX, i64::MIN); + let b = _mm256_set1_epi64x(1); + let r = _mm256_maskz_sub_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sub_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(0, -2, i64::MAX - 1, i64::MAX); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sub_epi64() { + let a = _mm_set_epi64x(i64::MAX, i64::MIN); + let b = _mm_set1_epi64x(1); + let r = _mm_mask_sub_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_sub_epi64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(i64::MAX - 1, i64::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sub_epi64() { + let a = _mm_set_epi64x(i64::MAX, i64::MIN); + let b = _mm_set1_epi64x(1); + let r = _mm_maskz_sub_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sub_epi64(0b00000011, a, b); + let e = _mm_set_epi64x(i64::MAX - 1, i64::MAX); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sub_pd() { let a = _mm512_setr_pd(0., 1., -1., f64::MAX, f64::MIN, 100., -100., -32.); @@ -226,9 +1010,53 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sub_pd() { + let a = _mm256_set_pd(1., -1., f64::MAX, f64::MIN); + let b = _mm256_set1_pd(1.); + let r = _mm256_mask_sub_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_sub_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(0., -2., f64::MAX - 1., f64::MIN); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sub_pd() { + let a = _mm256_set_pd(1., -1., f64::MAX, f64::MIN); + let b = _mm256_set1_pd(1.); + let r = _mm256_maskz_sub_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_sub_pd(0b00001111, a, b); + let e = _mm256_set_pd(0., -2., f64::MAX - 1., f64::MIN); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sub_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set1_pd(1.); + let r = _mm_mask_sub_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_sub_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(f64::MAX - 1., f64::MIN); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sub_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set1_pd(1.); + let r = _mm_maskz_sub_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_sub_pd(0b00000011, a, b); + let e = _mm_set_pd(f64::MAX - 1., f64::MIN); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mul_epi32() { - let a = _mm512_setr_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm512_set1_epi32(1); let b = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); let r = _mm512_mul_epi32(a, b); let e = _mm512_set_epi64(15, 13, 11, 9, 7, 5, 3, 1); @@ -237,27 +1065,22 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mul_epi32() { - let a = _mm512_setr_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm512_set1_epi32(1); let b = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); let r = _mm512_mask_mul_epi32(a, 0, a, b); assert_eq_m512i(r, a); let r = _mm512_mask_mul_epi32(a, 0b00001111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 | 1 << 32, - 1 | 1 << 32, - 1 | 1 << 32, - 1 | 1 << 32, - 7, - 5, - 3, - 1, + 1 | 1 << 32, 1 | 1 << 32, 1 | 1 << 32, 1 | 1 << 32, + 7, 5, 3, 1, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_mul_epi32() { - let a = _mm512_setr_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm512_set1_epi32(1); let b = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); let r = _mm512_maskz_mul_epi32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); @@ -266,9 +1089,53 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mul_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_mask_mul_epi32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_mul_epi32(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(2, 4, 6, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mul_epi32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_maskz_mul_epi32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_mul_epi32(0b00001111, a, b); + let e = _mm256_set_epi64x(2, 4, 6, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mul_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set_epi32(1, 2, 3, 4); + let r = _mm_mask_mul_epi32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_mul_epi32(a, 0b00000011, a, b); + let e = _mm_set_epi64x(2, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mul_epi32() { + let a = _mm_set1_epi32(1); + let b = _mm_set_epi32(1, 2, 3, 4); + let r = _mm_maskz_mul_epi32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_mul_epi32(0b00000011, a, b); + let e = _mm_set_epi64x(2, 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mul_epu32() { - let a = _mm512_setr_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm512_set1_epi32(1); let b = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); let r = _mm512_mul_epu32(a, b); let e = _mm512_set_epi64(15, 13, 11, 9, 7, 5, 3, 1); @@ -277,27 +1144,22 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_mul_epu32() { - let a = _mm512_setr_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm512_set1_epi32(1); let b = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); let r = _mm512_mask_mul_epu32(a, 0, a, b); assert_eq_m512i(r, a); let r = _mm512_mask_mul_epu32(a, 0b00001111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 | 1 << 32, - 1 | 1 << 32, - 1 | 1 << 32, - 1 | 1 << 32, - 7, - 5, - 3, - 1, + 1 | 1 << 32, 1 | 1 << 32, 1 | 1 << 32, 1 | 1 << 32, + 7, 5, 3, 1, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_mul_epu32() { - let a = _mm512_setr_epi32(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + let a = _mm512_set1_epi32(1); let b = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); let r = _mm512_maskz_mul_epu32(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); @@ -306,6 +1168,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mul_epu32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_mask_mul_epu32(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_mul_epu32(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(2, 4, 6, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mul_epu32() { + let a = _mm256_set1_epi32(1); + let b = _mm256_set_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let r = _mm256_maskz_mul_epu32(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_mul_epu32(0b00001111, a, b); + let e = _mm256_set_epi64x(2, 4, 6, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mul_epu32() { + let a = _mm_set1_epi32(1); + let b = _mm_set_epi32(1, 2, 3, 4); + let r = _mm_mask_mul_epu32(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_mul_epu32(a, 0b00000011, a, b); + let e = _mm_set_epi64x(2, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mul_epu32() { + let a = _mm_set1_epi32(1); + let b = _mm_set_epi32(1, 2, 3, 4); + let r = _mm_maskz_mul_epu32(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_mul_epu32(0b00000011, a, b); + let e = _mm_set_epi64x(2, 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mullox_epi64() { let a = _mm512_setr_epi64(0, 1, i64::MAX, i64::MIN, i64::MAX, 100, -100, -32); @@ -331,15 +1237,10 @@ mod tests { let a = _mm512_setr_pd(0., 1., f64::MAX, f64::MIN, f64::MAX, f64::MIN, -100., -32.); let b = _mm512_set1_pd(2.); let r = _mm512_mul_pd(a, b); + #[rustfmt::skip] let e = _mm512_setr_pd( - 0., - 2., - f64::INFINITY, - f64::NEG_INFINITY, - f64::INFINITY, - f64::NEG_INFINITY, - -200., - -64., + 0., 2., f64::INFINITY, f64::NEG_INFINITY, + f64::INFINITY, f64::NEG_INFINITY, -200., -64., ); assert_eq_m512d(r, e); } @@ -351,15 +1252,10 @@ mod tests { let r = _mm512_mask_mul_pd(a, 0, a, b); assert_eq_m512d(r, a); let r = _mm512_mask_mul_pd(a, 0b00001111, a, b); + #[rustfmt::skip] let e = _mm512_setr_pd( - 0., - 2., - f64::INFINITY, - f64::NEG_INFINITY, - f64::MAX, - f64::MIN, - -100., - -32., + 0., 2., f64::INFINITY, f64::NEG_INFINITY, + f64::MAX, f64::MIN, -100., -32., ); assert_eq_m512d(r, e); } @@ -375,40 +1271,74 @@ mod tests { assert_eq_m512d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_div_pd() { - let a = _mm512_setr_pd(0., 1., f64::MAX, f64::MIN, f64::MAX, f64::MIN, -100., -32.); - let b = _mm512_setr_pd(2., 2., 0., 0., 0., 0., 2., 2.); - let r = _mm512_div_pd(a, b); - let e = _mm512_setr_pd( - 0., - 0.5, - f64::INFINITY, - f64::NEG_INFINITY, - f64::INFINITY, - f64::NEG_INFINITY, - -50., - -16., - ); - assert_eq_m512d(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_mul_pd() { + let a = _mm256_set_pd(0., 1., f64::MAX, f64::MIN); + let b = _mm256_set1_pd(2.); + let r = _mm256_mask_mul_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_mul_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(0., 2., f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m256d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_mask_div_pd() { + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_mul_pd() { + let a = _mm256_set_pd(0., 1., f64::MAX, f64::MIN); + let b = _mm256_set1_pd(2.); + let r = _mm256_maskz_mul_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_mul_pd(0b00001111, a, b); + let e = _mm256_set_pd(0., 2., f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_mul_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set1_pd(2.); + let r = _mm_mask_mul_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_mul_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_mul_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set1_pd(2.); + let r = _mm_maskz_mul_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_mul_pd(0b00000011, a, b); + let e = _mm_set_pd(f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_div_pd() { + let a = _mm512_setr_pd(0., 1., f64::MAX, f64::MIN, f64::MAX, f64::MIN, -100., -32.); + let b = _mm512_setr_pd(2., 2., 0., 0., 0., 0., 2., 2.); + let r = _mm512_div_pd(a, b); + #[rustfmt::skip] + let e = _mm512_setr_pd( + 0., 0.5, f64::INFINITY, f64::NEG_INFINITY, + f64::INFINITY, f64::NEG_INFINITY, -50., -16., + ); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_div_pd() { let a = _mm512_setr_pd(0., 1., f64::MAX, f64::MIN, f64::MAX, f64::MIN, -100., -32.); let b = _mm512_setr_pd(2., 2., 0., 0., 0., 0., 2., 2.); let r = _mm512_mask_div_pd(a, 0, a, b); assert_eq_m512d(r, a); let r = _mm512_mask_div_pd(a, 0b00001111, a, b); + #[rustfmt::skip] let e = _mm512_setr_pd( - 0., - 0.5, - f64::INFINITY, - f64::NEG_INFINITY, - f64::MAX, - f64::MIN, - -100., - -32., + 0., 0.5, f64::INFINITY, f64::NEG_INFINITY, + f64::MAX, f64::MIN, -100., -32., ); assert_eq_m512d(r, e); } @@ -424,6 +1354,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_div_pd() { + let a = _mm256_set_pd(0., 1., f64::MAX, f64::MIN); + let b = _mm256_set_pd(2., 2., 0., 0.); + let r = _mm256_mask_div_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_div_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(0., 0.5, f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_div_pd() { + let a = _mm256_set_pd(0., 1., f64::MAX, f64::MIN); + let b = _mm256_set_pd(2., 2., 0., 0.); + let r = _mm256_maskz_div_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_div_pd(0b00001111, a, b); + let e = _mm256_set_pd(0., 0.5, f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_div_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set_pd(0., 0.); + let r = _mm_mask_div_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_div_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_div_pd() { + let a = _mm_set_pd(f64::MAX, f64::MIN); + let b = _mm_set_pd(0., 0.); + let r = _mm_maskz_div_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_div_pd(0b00000011, a, b); + let e = _mm_set_pd(f64::INFINITY, f64::NEG_INFINITY); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_max_epi64() { let a = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); @@ -455,6 +1429,68 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_max_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_max_epi64(a, b); + let e = _mm256_set_epi64x(3, 2, 2, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_max_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_mask_max_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_max_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(3, 2, 2, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_max_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_maskz_max_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_max_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(3, 2, 2, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_max_epi64() { + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(3, 2); + let r = _mm_max_epi64(a, b); + let e = _mm_set_epi64x(3, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_max_epi64() { + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(3, 2); + let r = _mm_mask_max_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_max_epi64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(3, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_max_epi64() { + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(3, 2); + let r = _mm_maskz_max_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_max_epi64(0b00000011, a, b); + let e = _mm_set_epi64x(3, 3); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_max_pd() { let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); @@ -486,6 +1522,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_max_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let b = _mm256_set_pd(3., 2., 1., 0.); + let r = _mm256_mask_max_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_max_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(3., 2., 2., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_max_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let b = _mm256_set_pd(3., 2., 1., 0.); + let r = _mm256_maskz_max_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_max_pd(0b00001111, a, b); + let e = _mm256_set_pd(3., 2., 2., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_max_pd() { + let a = _mm_set_pd(2., 3.); + let b = _mm_set_pd(3., 2.); + let r = _mm_mask_max_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_max_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(3., 3.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_max_pd() { + let a = _mm_set_pd(2., 3.); + let b = _mm_set_pd(3., 2.); + let r = _mm_maskz_max_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_max_pd(0b00000011, a, b); + let e = _mm_set_pd(3., 3.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_max_epu64() { let a = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); @@ -517,6 +1597,68 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_max_epu64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_max_epu64(a, b); + let e = _mm256_set_epi64x(3, 2, 2, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_max_epu64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_mask_max_epu64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_max_epu64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(3, 2, 2, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_max_epu64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_maskz_max_epu64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_max_epu64(0b00001111, a, b); + let e = _mm256_set_epi64x(3, 2, 2, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_max_epu64() { + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(3, 2); + let r = _mm_max_epu64(a, b); + let e = _mm_set_epi64x(3, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_max_epu64() { + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(3, 2); + let r = _mm_mask_max_epu64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_max_epu64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(3, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_max_epu64() { + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(3, 2); + let r = _mm_maskz_max_epu64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_max_epu64(0b00000011, a, b); + let e = _mm_set_epi64x(3, 3); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_min_epi64() { let a = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); @@ -548,6 +1690,37 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_min_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_min_epi64(a, b); + let e = _mm256_set_epi64x(0, 1, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_min_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_mask_min_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_min_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(0, 1, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_min_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_maskz_min_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_min_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(0, 1, 1, 0); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_min_pd() { let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); @@ -579,6 +1752,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_min_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let b = _mm256_set_pd(3., 2., 1., 0.); + let r = _mm256_mask_min_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_min_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(0., 1., 1., 0.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_min_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let b = _mm256_set_pd(3., 2., 1., 0.); + let r = _mm256_maskz_min_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_min_pd(0b00001111, a, b); + let e = _mm256_set_pd(0., 1., 1., 0.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_min_pd() { + let a = _mm_set_pd(0., 1.); + let b = _mm_set_pd(1., 0.); + let r = _mm_mask_min_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_min_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(0., 0.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_min_pd() { + let a = _mm_set_pd(0., 1.); + let b = _mm_set_pd(1., 0.); + let r = _mm_maskz_min_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_min_pd(0b00000011, a, b); + let e = _mm_set_pd(0., 0.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_min_epu64() { let a = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); @@ -610,6 +1827,68 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_min_epu64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_min_epu64(a, b); + let e = _mm256_set_epi64x(0, 1, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_min_epu64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_mask_min_epu64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_min_epu64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(0, 1, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_min_epu64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_maskz_min_epu64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_min_epu64(0b00001111, a, b); + let e = _mm256_set_epi64x(0, 1, 1, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_min_epu64() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set_epi64x(1, 0); + let r = _mm_min_epu64(a, b); + let e = _mm_set_epi64x(0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_min_epu64() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set_epi64x(1, 0); + let r = _mm_mask_min_epu64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_min_epu64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(0, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_min_epu64() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set_epi64x(1, 0); + let r = _mm_maskz_min_epu64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_min_epu64(0b00000011, a, b); + let e = _mm_set_epi64x(0, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sqrt_pd() { let a = _mm512_setr_pd(0., 1., 4., 9., 16., 25., 36., 49.); @@ -638,6 +1917,46 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sqrt_pd() { + let a = _mm256_set_pd(0., 1., 4., 9.); + let r = _mm256_mask_sqrt_pd(a, 0, a); + assert_eq_m256d(r, a); + let r = _mm256_mask_sqrt_pd(a, 0b00001111, a); + let e = _mm256_set_pd(0., 1., 2., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sqrt_pd() { + let a = _mm256_set_pd(0., 1., 4., 9.); + let r = _mm256_maskz_sqrt_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_sqrt_pd(0b00001111, a); + let e = _mm256_set_pd(0., 1., 2., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sqrt_pd() { + let a = _mm_set_pd(0., 1.); + let r = _mm_mask_sqrt_pd(a, 0, a); + assert_eq_m128d(r, a); + let r = _mm_mask_sqrt_pd(a, 0b00000011, a); + let e = _mm_set_pd(0., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sqrt_pd() { + let a = _mm_set_pd(0., 1.); + let r = _mm_maskz_sqrt_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_sqrt_pd(0b00000011, a); + let e = _mm_set_pd(0., 1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmadd_pd() { let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); @@ -684,11 +2003,83 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask_fmadd_pd(a, 0, b, c); + assert_eq_m256d(r, a); + let r = _mm256_mask_fmadd_pd(a, 0b00001111, b, c); + let e = _mm256_set_pd(1., 2., 3., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_maskz_fmadd_pd(0, a, b, c); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_fmadd_pd(0b00001111, a, b, c); + let e = _mm256_set_pd(1., 2., 3., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask3_fmadd_pd(a, b, c, 0); + assert_eq_m256d(r, c); + let r = _mm256_mask3_fmadd_pd(a, b, c, 0b00001111); + let e = _mm256_set_pd(1., 2., 3., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask_fmadd_pd(a, 0, b, c); + assert_eq_m128d(r, a); + let r = _mm_mask_fmadd_pd(a, 0b00000011, b, c); + let e = _mm_set_pd(1., 2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_maskz_fmadd_pd(0, a, b, c); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_fmadd_pd(0b00000011, a, b, c); + let e = _mm_set_pd(1., 2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask3_fmadd_pd(a, b, c, 0); + assert_eq_m128d(r, c); + let r = _mm_mask3_fmadd_pd(a, b, c, 0b00000011); + let e = _mm_set_pd(1., 2.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_fmsub_pd(a, b, c); let e = _mm512_setr_pd(-1., 0., 1., 2., 3., 4., 5., 6.); assert_eq_m512d(r, e); @@ -696,9 +2087,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_mask_fmsub_pd(a, 0, b, c); assert_eq_m512d(r, a); let r = _mm512_mask_fmsub_pd(a, 0b00001111, b, c); @@ -708,9 +2099,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_maskz_fmsub_pd(0, a, b, c); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_fmsub_pd(0b00001111, a, b, c); @@ -720,7 +2111,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); let c = _mm512_setr_pd(1., 1., 1., 1., 2., 2., 2., 2.); let r = _mm512_mask3_fmsub_pd(a, b, c, 0); @@ -730,11 +2121,83 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask_fmsub_pd(a, 0, b, c); + assert_eq_m256d(r, a); + let r = _mm256_mask_fmsub_pd(a, 0b00001111, b, c); + let e = _mm256_set_pd(-1., 0., 1., 2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_maskz_fmsub_pd(0, a, b, c); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_fmsub_pd(0b00001111, a, b, c); + let e = _mm256_set_pd(-1., 0., 1., 2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask3_fmsub_pd(a, b, c, 0); + assert_eq_m256d(r, c); + let r = _mm256_mask3_fmsub_pd(a, b, c, 0b00001111); + let e = _mm256_set_pd(-1., 0., 1., 2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask_fmsub_pd(a, 0, b, c); + assert_eq_m128d(r, a); + let r = _mm_mask_fmsub_pd(a, 0b00000011, b, c); + let e = _mm_set_pd(-1., 0.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_maskz_fmsub_pd(0, a, b, c); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_fmsub_pd(0b00000011, a, b, c); + let e = _mm_set_pd(-1., 0.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask3_fmsub_pd(a, b, c, 0); + assert_eq_m128d(r, c); + let r = _mm_mask3_fmsub_pd(a, b, c, 0b00000011); + let e = _mm_set_pd(-1., 0.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmaddsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_fmaddsub_pd(a, b, c); let e = _mm512_setr_pd(-1., 2., 1., 4., 3., 6., 5., 8.); assert_eq_m512d(r, e); @@ -742,9 +2205,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fmaddsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_mask_fmaddsub_pd(a, 0, b, c); assert_eq_m512d(r, a); let r = _mm512_mask_fmaddsub_pd(a, 0b00001111, b, c); @@ -754,9 +2217,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fmaddsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_maskz_fmaddsub_pd(0, a, b, c); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_fmaddsub_pd(0b00001111, a, b, c); @@ -766,7 +2229,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fmaddsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); let c = _mm512_setr_pd(1., 1., 1., 1., 2., 2., 2., 2.); let r = _mm512_mask3_fmaddsub_pd(a, b, c, 0); @@ -776,11 +2239,83 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmaddsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask_fmaddsub_pd(a, 0, b, c); + assert_eq_m256d(r, a); + let r = _mm256_mask_fmaddsub_pd(a, 0b00001111, b, c); + let e = _mm256_set_pd(1., 0., 3., 2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmaddsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_maskz_fmaddsub_pd(0, a, b, c); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_fmaddsub_pd(0b00001111, a, b, c); + let e = _mm256_set_pd(1., 0., 3., 2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmaddsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask3_fmaddsub_pd(a, b, c, 0); + assert_eq_m256d(r, c); + let r = _mm256_mask3_fmaddsub_pd(a, b, c, 0b00001111); + let e = _mm256_set_pd(1., 0., 3., 2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmaddsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask_fmaddsub_pd(a, 0, b, c); + assert_eq_m128d(r, a); + let r = _mm_mask_fmaddsub_pd(a, 0b00000011, b, c); + let e = _mm_set_pd(1., 0.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmaddsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_maskz_fmaddsub_pd(0, a, b, c); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_fmaddsub_pd(0b00000011, a, b, c); + let e = _mm_set_pd(1., 0.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmaddsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask3_fmaddsub_pd(a, b, c, 0); + assert_eq_m128d(r, c); + let r = _mm_mask3_fmaddsub_pd(a, b, c, 0b00000011); + let e = _mm_set_pd(1., 0.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fmsubadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_fmsubadd_pd(a, b, c); let e = _mm512_setr_pd(1., 0., 3., 2., 5., 4., 7., 6.); assert_eq_m512d(r, e); @@ -788,9 +2323,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fmsubadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_mask_fmsubadd_pd(a, 0, b, c); assert_eq_m512d(r, a); let r = _mm512_mask_fmsubadd_pd(a, 0b00001111, b, c); @@ -800,9 +2335,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fmsubadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_maskz_fmsubadd_pd(0, a, b, c); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_fmsubadd_pd(0b00001111, a, b, c); @@ -812,7 +2347,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fmsubadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); let c = _mm512_setr_pd(1., 1., 1., 1., 2., 2., 2., 2.); let r = _mm512_mask3_fmsubadd_pd(a, b, c, 0); @@ -822,21 +2357,93 @@ mod tests { assert_eq_m512d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_fnmadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); - let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); - let r = _mm512_fnmadd_pd(a, b, c); - let e = _mm512_setr_pd(1., 0., -1., -2., -3., -4., -5., -6.); - assert_eq_m512d(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fmsubadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask_fmsubadd_pd(a, 0, b, c); + assert_eq_m256d(r, a); + let r = _mm256_mask_fmsubadd_pd(a, 0b00001111, b, c); + let e = _mm256_set_pd(-1., 2., 1., 4.); + assert_eq_m256d(r, e); } - #[simd_test(enable = "avx512f")] + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fmsubadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_maskz_fmsubadd_pd(0, a, b, c); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_fmsubadd_pd(0b00001111, a, b, c); + let e = _mm256_set_pd(-1., 2., 1., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fmsubadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask3_fmsubadd_pd(a, b, c, 0); + assert_eq_m256d(r, c); + let r = _mm256_mask3_fmsubadd_pd(a, b, c, 0b00001111); + let e = _mm256_set_pd(-1., 2., 1., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fmsubadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask_fmsubadd_pd(a, 0, b, c); + assert_eq_m128d(r, a); + let r = _mm_mask_fmsubadd_pd(a, 0b00000011, b, c); + let e = _mm_set_pd(-1., 2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fmsubadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_maskz_fmsubadd_pd(0, a, b, c); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_fmsubadd_pd(0b00000011, a, b, c); + let e = _mm_set_pd(-1., 2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fmsubadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask3_fmsubadd_pd(a, b, c, 0); + assert_eq_m128d(r, c); + let r = _mm_mask3_fmsubadd_pd(a, b, c, 0b00000011); + let e = _mm_set_pd(-1., 2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_fnmadd_pd() { + let a = _mm512_set1_pd(1.); + let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let c = _mm512_set1_pd(1.); + let r = _mm512_fnmadd_pd(a, b, c); + let e = _mm512_setr_pd(1., 0., -1., -2., -3., -4., -5., -6.); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fnmadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_mask_fnmadd_pd(a, 0, b, c); assert_eq_m512d(r, a); let r = _mm512_mask_fnmadd_pd(a, 0b00001111, b, c); @@ -846,9 +2453,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fnmadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_maskz_fnmadd_pd(0, a, b, c); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_fnmadd_pd(0b00001111, a, b, c); @@ -858,7 +2465,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fnmadd_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); let c = _mm512_setr_pd(1., 1., 1., 1., 2., 2., 2., 2.); let r = _mm512_mask3_fnmadd_pd(a, b, c, 0); @@ -868,11 +2475,83 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fnmadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask_fnmadd_pd(a, 0, b, c); + assert_eq_m256d(r, a); + let r = _mm256_mask_fnmadd_pd(a, 0b00001111, b, c); + let e = _mm256_set_pd(1., 0., -1., -2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fnmadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_maskz_fnmadd_pd(0, a, b, c); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_fnmadd_pd(0b00001111, a, b, c); + let e = _mm256_set_pd(1., 0., -1., -2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fnmadd_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask3_fnmadd_pd(a, b, c, 0); + assert_eq_m256d(r, c); + let r = _mm256_mask3_fnmadd_pd(a, b, c, 0b00001111); + let e = _mm256_set_pd(1., 0., -1., -2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fnmadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask_fnmadd_pd(a, 0, b, c); + assert_eq_m128d(r, a); + let r = _mm_mask_fnmadd_pd(a, 0b00000011, b, c); + let e = _mm_set_pd(1., 0.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fnmadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_maskz_fnmadd_pd(0, a, b, c); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_fnmadd_pd(0b00000011, a, b, c); + let e = _mm_set_pd(1., 0.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fnmadd_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask3_fnmadd_pd(a, b, c, 0); + assert_eq_m128d(r, c); + let r = _mm_mask3_fnmadd_pd(a, b, c, 0b00000011); + let e = _mm_set_pd(1., 0.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fnmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_fnmsub_pd(a, b, c); let e = _mm512_setr_pd(-1., -2., -3., -4., -5., -6., -7., -8.); assert_eq_m512d(r, e); @@ -880,9 +2559,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_fnmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_mask_fnmsub_pd(a, 0, b, c); assert_eq_m512d(r, a); let r = _mm512_mask_fnmsub_pd(a, 0b00001111, b, c); @@ -892,9 +2571,9 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_fnmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let c = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let c = _mm512_set1_pd(1.); let r = _mm512_maskz_fnmsub_pd(0, a, b, c); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_fnmsub_pd(0b00001111, a, b, c); @@ -904,7 +2583,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask3_fnmsub_pd() { - let a = _mm512_setr_pd(1., 1., 1., 1., 1., 1., 1., 1.); + let a = _mm512_set1_pd(1.); let b = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); let c = _mm512_setr_pd(1., 1., 1., 1., 2., 2., 2., 2.); let r = _mm512_mask3_fnmsub_pd(a, b, c, 0); @@ -914,6 +2593,78 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fnmsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask_fnmsub_pd(a, 0, b, c); + assert_eq_m256d(r, a); + let r = _mm256_mask_fnmsub_pd(a, 0b00001111, b, c); + let e = _mm256_set_pd(-1., -2., -3., -4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fnmsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_maskz_fnmsub_pd(0, a, b, c); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_fnmsub_pd(0b00001111, a, b, c); + let e = _mm256_set_pd(-1., -2., -3., -4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask3_fnmsub_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set_pd(0., 1., 2., 3.); + let c = _mm256_set1_pd(1.); + let r = _mm256_mask3_fnmsub_pd(a, b, c, 0); + assert_eq_m256d(r, c); + let r = _mm256_mask3_fnmsub_pd(a, b, c, 0b00001111); + let e = _mm256_set_pd(-1., -2., -3., -4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fnmsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask_fnmsub_pd(a, 0, b, c); + assert_eq_m128d(r, a); + let r = _mm_mask_fnmsub_pd(a, 0b00000011, b, c); + let e = _mm_set_pd(-1., -2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fnmsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_maskz_fnmsub_pd(0, a, b, c); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_fnmsub_pd(0b00000011, a, b, c); + let e = _mm_set_pd(-1., -2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask3_fnmsub_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set_pd(0., 1.); + let c = _mm_set1_pd(1.); + let r = _mm_mask3_fnmsub_pd(a, b, c, 0); + assert_eq_m128d(r, c); + let r = _mm_mask3_fnmsub_pd(a, b, c, 0b00000011); + let e = _mm_set_pd(-1., -2.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rcp14_pd() { let a = _mm512_set1_pd(3.); @@ -928,15 +2679,10 @@ mod tests { let r = _mm512_mask_rcp14_pd(a, 0, a); assert_eq_m512d(r, a); let r = _mm512_mask_rcp14_pd(a, 0b11110000, a); + #[rustfmt::skip] let e = _mm512_setr_pd( - 3., - 3., - 3., - 3., - 0.3333320617675781, - 0.3333320617675781, - 0.3333320617675781, - 0.3333320617675781, + 3., 3., 3., 3., + 0.3333320617675781, 0.3333320617675781, 0.3333320617675781, 0.3333320617675781, ); assert_eq_m512d(r, e); } @@ -947,19 +2693,70 @@ mod tests { let r = _mm512_maskz_rcp14_pd(0, a); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_rcp14_pd(0b11110000, a); + #[rustfmt::skip] let e = _mm512_setr_pd( - 0., - 0., - 0., - 0., - 0.3333320617675781, - 0.3333320617675781, - 0.3333320617675781, - 0.3333320617675781, + 0., 0., 0., 0., + 0.3333320617675781, 0.3333320617675781, 0.3333320617675781, 0.3333320617675781, ); assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rcp14_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_rcp14_pd(a); + let e = _mm256_set1_pd(0.3333320617675781); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rcp14_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_mask_rcp14_pd(a, 0, a); + assert_eq_m256d(r, a); + let r = _mm256_mask_rcp14_pd(a, 0b00001111, a); + let e = _mm256_set1_pd(0.3333320617675781); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rcp14_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_maskz_rcp14_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_rcp14_pd(0b00001111, a); + let e = _mm256_set1_pd(0.3333320617675781); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rcp14_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_rcp14_pd(a); + let e = _mm_set1_pd(0.3333320617675781); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rcp14_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_mask_rcp14_pd(a, 0, a); + assert_eq_m128d(r, a); + let r = _mm_mask_rcp14_pd(a, 0b00000011, a); + let e = _mm_set1_pd(0.3333320617675781); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rcp14_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_maskz_rcp14_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_rcp14_pd(0b00000011, a); + let e = _mm_set1_pd(0.3333320617675781); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rsqrt14_pd() { let a = _mm512_set1_pd(3.); @@ -974,15 +2771,10 @@ mod tests { let r = _mm512_mask_rsqrt14_pd(a, 0, a); assert_eq_m512d(r, a); let r = _mm512_mask_rsqrt14_pd(a, 0b11110000, a); + #[rustfmt::skip] let e = _mm512_setr_pd( - 3., - 3., - 3., - 3., - 0.5773391723632813, - 0.5773391723632813, - 0.5773391723632813, - 0.5773391723632813, + 3., 3., 3., 3., + 0.5773391723632813, 0.5773391723632813, 0.5773391723632813, 0.5773391723632813, ); assert_eq_m512d(r, e); } @@ -993,19 +2785,54 @@ mod tests { let r = _mm512_maskz_rsqrt14_pd(0, a); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_rsqrt14_pd(0b11110000, a); + #[rustfmt::skip] let e = _mm512_setr_pd( - 0., - 0., - 0., - 0., - 0.5773391723632813, - 0.5773391723632813, - 0.5773391723632813, - 0.5773391723632813, + 0., 0., 0., 0., + 0.5773391723632813, 0.5773391723632813, 0.5773391723632813, 0.5773391723632813, ); assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rsqrt14_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_mask_rsqrt14_pd(a, 0, a); + assert_eq_m256d(r, a); + let r = _mm256_mask_rsqrt14_pd(a, 0b00001111, a); + let e = _mm256_set1_pd(0.5773391723632813); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rsqrt14_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_maskz_rsqrt14_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_rsqrt14_pd(0b00001111, a); + let e = _mm256_set1_pd(0.5773391723632813); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rsqrt14_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_mask_rsqrt14_pd(a, 0, a); + assert_eq_m128d(r, a); + let r = _mm_mask_rsqrt14_pd(a, 0b00000011, a); + let e = _mm_set1_pd(0.5773391723632813); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rsqrt14_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_maskz_rsqrt14_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_rsqrt14_pd(0b00000011, a); + let e = _mm_set1_pd(0.5773391723632813); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_getexp_pd() { let a = _mm512_set1_pd(3.); @@ -1034,6 +2861,62 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_getexp_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_getexp_pd(a); + let e = _mm256_set1_pd(1.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_getexp_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_mask_getexp_pd(a, 0, a); + assert_eq_m256d(r, a); + let r = _mm256_mask_getexp_pd(a, 0b00001111, a); + let e = _mm256_set1_pd(1.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_getexp_pd() { + let a = _mm256_set1_pd(3.); + let r = _mm256_maskz_getexp_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_getexp_pd(0b00001111, a); + let e = _mm256_set1_pd(1.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_getexp_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_getexp_pd(a); + let e = _mm_set1_pd(1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_getexp_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_mask_getexp_pd(a, 0, a); + assert_eq_m128d(r, a); + let r = _mm_mask_getexp_pd(a, 0b00000011, a); + let e = _mm_set1_pd(1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_getexp_pd() { + let a = _mm_set1_pd(3.); + let r = _mm_maskz_getexp_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_getexp_pd(0b00000011, a); + let e = _mm_set1_pd(1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_roundscale_pd() { let a = _mm512_set1_pd(1.1); @@ -1063,6 +2946,64 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_roundscale_pd() { + let a = _mm256_set1_pd(1.1); + let r = _mm256_roundscale_pd(a, 0); + let e = _mm256_set1_pd(1.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_roundscale_pd() { + let a = _mm256_set1_pd(1.1); + let r = _mm256_mask_roundscale_pd(a, 0, a, 0); + let e = _mm256_set1_pd(1.1); + assert_eq_m256d(r, e); + let r = _mm256_mask_roundscale_pd(a, 0b00001111, a, 0); + let e = _mm256_set1_pd(1.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_roundscale_pd() { + let a = _mm256_set1_pd(1.1); + let r = _mm256_maskz_roundscale_pd(0, a, 0); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_roundscale_pd(0b00001111, a, 0); + let e = _mm256_set1_pd(1.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_roundscale_pd() { + let a = _mm_set1_pd(1.1); + let r = _mm_roundscale_pd(a, 0); + let e = _mm_set1_pd(1.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_roundscale_pd() { + let a = _mm_set1_pd(1.1); + let r = _mm_mask_roundscale_pd(a, 0, a, 0); + let e = _mm_set1_pd(1.1); + assert_eq_m128d(r, e); + let r = _mm_mask_roundscale_pd(a, 0b00000011, a, 0); + let e = _mm_set1_pd(1.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_roundscale_pd() { + let a = _mm_set1_pd(1.1); + let r = _mm_maskz_roundscale_pd(0, a, 0); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_roundscale_pd(0b00000011, a, 0); + let e = _mm_set1_pd(1.0); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_scalef_pd() { let a = _mm512_set1_pd(1.); @@ -1094,6 +3035,68 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_scalef_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set1_pd(3.); + let r = _mm256_scalef_pd(a, b); + let e = _mm256_set1_pd(8.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_scalef_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set1_pd(3.); + let r = _mm256_mask_scalef_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_scalef_pd(a, 0b00001111, a, b); + let e = _mm256_set1_pd(8.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_scalef_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set1_pd(3.); + let r = _mm256_maskz_scalef_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_scalef_pd(0b00001111, a, b); + let e = _mm256_set1_pd(8.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_scalef_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set1_pd(3.); + let r = _mm_scalef_pd(a, b); + let e = _mm_set1_pd(8.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_scalef_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set1_pd(3.); + let r = _mm_mask_scalef_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_scalef_pd(a, 0b00000011, a, b); + let e = _mm_set1_pd(8.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_scalef_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set1_pd(3.); + let r = _mm_maskz_scalef_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_scalef_pd(0b00000011, a, b); + let e = _mm_set1_pd(8.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_fixupimm_pd() { let a = _mm512_set1_pd(f64::NAN); @@ -1124,6 +3127,66 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_fixupimm_pd() { + let a = _mm256_set1_pd(f64::NAN); + let b = _mm256_set1_pd(f64::MAX); + let c = _mm256_set1_epi64x(i32::MAX as i64); + let r = _mm256_fixupimm_pd(a, b, c, 5); + let e = _mm256_set1_pd(0.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_fixupimm_pd() { + let a = _mm256_set1_pd(f64::NAN); + let b = _mm256_set1_pd(f64::MAX); + let c = _mm256_set1_epi64x(i32::MAX as i64); + let r = _mm256_mask_fixupimm_pd(a, 0b00001111, b, c, 5); + let e = _mm256_set1_pd(0.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_fixupimm_pd() { + let a = _mm256_set1_pd(f64::NAN); + let b = _mm256_set1_pd(f64::MAX); + let c = _mm256_set1_epi64x(i32::MAX as i64); + let r = _mm256_maskz_fixupimm_pd(0b00001111, a, b, c, 5); + let e = _mm256_set1_pd(0.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_fixupimm_pd() { + let a = _mm_set1_pd(f64::NAN); + let b = _mm_set1_pd(f64::MAX); + let c = _mm_set1_epi64x(i32::MAX as i64); + let r = _mm_fixupimm_pd(a, b, c, 5); + let e = _mm_set1_pd(0.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_fixupimm_pd() { + let a = _mm_set1_pd(f64::NAN); + let b = _mm_set1_pd(f64::MAX); + let c = _mm_set1_epi64x(i32::MAX as i64); + let r = _mm_mask_fixupimm_pd(a, 0b00000011, b, c, 5); + let e = _mm_set1_pd(0.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_fixupimm_pd() { + let a = _mm_set1_pd(f64::NAN); + let b = _mm_set1_pd(f64::MAX); + let c = _mm_set1_epi64x(i32::MAX as i64); + let r = _mm_maskz_fixupimm_pd(0b00000011, a, b, c, 5); + let e = _mm_set1_pd(0.0); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_ternarylogic_epi64() { let a = _mm512_set1_epi64(1 << 2); @@ -1158,6 +3221,74 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_ternarylogic_epi64() { + let a = _mm256_set1_epi64x(1 << 2); + let b = _mm256_set1_epi64x(1 << 1); + let c = _mm256_set1_epi64x(1 << 0); + let r = _mm256_ternarylogic_epi64(a, b, c, 8); + let e = _mm256_set1_epi64x(0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_ternarylogic_epi64() { + let src = _mm256_set1_epi64x(1 << 2); + let a = _mm256_set1_epi64x(1 << 1); + let b = _mm256_set1_epi64x(1 << 0); + let r = _mm256_mask_ternarylogic_epi64(src, 0, a, b, 8); + assert_eq_m256i(r, src); + let r = _mm256_mask_ternarylogic_epi64(src, 0b00001111, a, b, 8); + let e = _mm256_set1_epi64x(0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_ternarylogic_epi64() { + let a = _mm256_set1_epi64x(1 << 2); + let b = _mm256_set1_epi64x(1 << 1); + let c = _mm256_set1_epi64x(1 << 0); + let r = _mm256_maskz_ternarylogic_epi64(0, a, b, c, 9); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_ternarylogic_epi64(0b00001111, a, b, c, 8); + let e = _mm256_set1_epi64x(0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_ternarylogic_epi64() { + let a = _mm_set1_epi64x(1 << 2); + let b = _mm_set1_epi64x(1 << 1); + let c = _mm_set1_epi64x(1 << 0); + let r = _mm_ternarylogic_epi64(a, b, c, 8); + let e = _mm_set1_epi64x(0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_ternarylogic_epi64() { + let src = _mm_set1_epi64x(1 << 2); + let a = _mm_set1_epi64x(1 << 1); + let b = _mm_set1_epi64x(1 << 0); + let r = _mm_mask_ternarylogic_epi64(src, 0, a, b, 8); + assert_eq_m128i(r, src); + let r = _mm_mask_ternarylogic_epi64(src, 0b00000011, a, b, 8); + let e = _mm_set1_epi64x(0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_ternarylogic_epi64() { + let a = _mm_set1_epi64x(1 << 2); + let b = _mm_set1_epi64x(1 << 1); + let c = _mm_set1_epi64x(1 << 0); + let r = _mm_maskz_ternarylogic_epi64(0, a, b, c, 9); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_ternarylogic_epi64(0b00000011, a, b, c, 8); + let e = _mm_set1_epi64x(0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_getmant_pd() { let a = _mm512_set1_pd(10.); @@ -1186,23 +3317,79 @@ mod tests { assert_eq_m512d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_cvtps_pd() { - let a = _mm256_setr_ps(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); - let r = _mm512_cvtps_pd(a); - let e = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); - assert_eq_m512d(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_getmant_pd() { + let a = _mm256_set1_pd(10.); + let r = _mm256_getmant_pd(a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm256_set1_pd(1.25); + assert_eq_m256d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_mask_cvtps_pd() { - let a = _mm256_setr_ps(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); - let src = _mm512_set1_pd(0.); - let r = _mm512_mask_cvtps_pd(src, 0, a); - assert_eq_m512d(r, src); - let r = _mm512_mask_cvtps_pd(src, 0b00001111, a); - let e = _mm512_setr_pd(0., -1.5, 2., -3.5, 0., 0., 0., 0.); - assert_eq_m512d(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_getmant_pd() { + let a = _mm256_set1_pd(10.); + let r = _mm256_mask_getmant_pd(a, 0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m256d(r, a); + let r = _mm256_mask_getmant_pd(a, 0b00001111, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm256_set1_pd(1.25); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_getmant_pd() { + let a = _mm256_set1_pd(10.); + let r = _mm256_maskz_getmant_pd(0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_getmant_pd(0b00001111, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm256_set1_pd(1.25); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_getmant_pd() { + let a = _mm_set1_pd(10.); + let r = _mm_getmant_pd(a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm_set1_pd(1.25); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_getmant_pd() { + let a = _mm_set1_pd(10.); + let r = _mm_mask_getmant_pd(a, 0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m128d(r, a); + let r = _mm_mask_getmant_pd(a, 0b00000011, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm_set1_pd(1.25); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_getmant_pd() { + let a = _mm_set1_pd(10.); + let r = _mm_maskz_getmant_pd(0, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_getmant_pd(0b00000011, a, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_SRC); + let e = _mm_set1_pd(1.25); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_cvtps_pd() { + let a = _mm256_setr_ps(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); + let r = _mm512_cvtps_pd(a); + let e = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtps_pd() { + let a = _mm256_setr_ps(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); + let src = _mm512_set1_pd(0.); + let r = _mm512_mask_cvtps_pd(src, 0, a); + assert_eq_m512d(r, src); + let r = _mm512_mask_cvtps_pd(src, 0b00001111, a); + let e = _mm512_setr_pd(0., -1.5, 2., -3.5, 0., 0., 0., 0.); + assert_eq_m512d(r, e); } #[simd_test(enable = "avx512f")] @@ -1267,6 +3454,206 @@ mod tests { assert_eq_m256(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtpd_ps() { + let a = _mm256_set_pd(4., -5.5, 6., -7.5); + let src = _mm_set1_ps(0.); + let r = _mm256_mask_cvtpd_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm256_mask_cvtpd_ps(src, 0b00001111, a); + let e = _mm_set_ps(4., -5.5, 6., -7.5); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtpd_ps() { + let a = _mm256_set_pd(4., -5.5, 6., -7.5); + let r = _mm256_maskz_cvtpd_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm256_maskz_cvtpd_ps(0b00001111, a); + let e = _mm_set_ps(4., -5.5, 6., -7.5); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtpd_ps() { + let a = _mm_set_pd(6., -7.5); + let src = _mm_set1_ps(0.); + let r = _mm_mask_cvtpd_ps(src, 0, a); + assert_eq_m128(r, src); + let r = _mm_mask_cvtpd_ps(src, 0b00000011, a); + let e = _mm_set_ps(0., 0., 6., -7.5); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtpd_ps() { + let a = _mm_set_pd(6., -7.5); + let r = _mm_maskz_cvtpd_ps(0, a); + assert_eq_m128(r, _mm_setzero_ps()); + let r = _mm_maskz_cvtpd_ps(0b00000011, a); + let e = _mm_set_ps(0., 0., 6., -7.5); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_cvtpd_epi32() { + let a = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); + let r = _mm512_cvtpd_epi32(a); + let e = _mm256_setr_epi32(0, -2, 2, -4, 4, -6, 6, -8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtpd_epi32() { + let a = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); + let src = _mm256_set1_epi32(0); + let r = _mm512_mask_cvtpd_epi32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm512_mask_cvtpd_epi32(src, 0b11111111, a); + let e = _mm256_setr_epi32(0, -2, 2, -4, 4, -6, 6, -8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_cvtpd_epi32() { + let a = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); + let r = _mm512_maskz_cvtpd_epi32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm512_maskz_cvtpd_epi32(0b11111111, a); + let e = _mm256_setr_epi32(0, -2, 2, -4, 4, -6, 6, -8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtpd_epi32() { + let a = _mm256_set_pd(4., -5.5, 6., -7.5); + let src = _mm_set1_epi32(0); + let r = _mm256_mask_cvtpd_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtpd_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(4, -6, 6, -8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtpd_epi32() { + let a = _mm256_set_pd(4., -5.5, 6., -7.5); + let r = _mm256_maskz_cvtpd_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtpd_epi32(0b00001111, a); + let e = _mm_set_epi32(4, -6, 6, -8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtpd_epi32() { + let a = _mm_set_pd(6., -7.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvtpd_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtpd_epi32(src, 0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, -8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtpd_epi32() { + let a = _mm_set_pd(6., -7.5); + let r = _mm_maskz_cvtpd_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtpd_epi32(0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, -8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_cvtpd_epu32() { + let a = _mm512_setr_pd(0., 1.5, 2., 3.5, 4., 5.5, 6., 7.5); + let r = _mm512_cvtpd_epu32(a); + let e = _mm256_setr_epi32(0, 2, 2, 4, 4, 6, 6, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtpd_epu32() { + let a = _mm512_setr_pd(0., 1.5, 2., 3.5, 4., 5.5, 6., 7.5); + let src = _mm256_set1_epi32(0); + let r = _mm512_mask_cvtpd_epu32(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm512_mask_cvtpd_epu32(src, 0b11111111, a); + let e = _mm256_setr_epi32(0, 2, 2, 4, 4, 6, 6, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_cvtpd_epu32() { + let a = _mm512_setr_pd(0., 1.5, 2., 3.5, 4., 5.5, 6., 7.5); + let r = _mm512_maskz_cvtpd_epu32(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm512_maskz_cvtpd_epu32(0b11111111, a); + let e = _mm256_setr_epi32(0, 2, 2, 4, 4, 6, 6, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtpd_epu32() { + let a = _mm256_set_pd(4., 5.5, 6., 7.5); + let r = _mm256_cvtpd_epu32(a); + let e = _mm_set_epi32(4, 6, 6, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtpd_epu32() { + let a = _mm256_set_pd(4., 5.5, 6., 7.5); + let src = _mm_set1_epi32(0); + let r = _mm256_mask_cvtpd_epu32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtpd_epu32(src, 0b00001111, a); + let e = _mm_set_epi32(4, 6, 6, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtpd_epu32() { + let a = _mm256_set_pd(4., 5.5, 6., 7.5); + let r = _mm256_maskz_cvtpd_epu32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtpd_epu32(0b00001111, a); + let e = _mm_set_epi32(4, 6, 6, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtpd_epu32() { + let a = _mm_set_pd(6., 7.5); + let r = _mm_cvtpd_epu32(a); + let e = _mm_set_epi32(0, 0, 6, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtpd_epu32() { + let a = _mm_set_pd(6., 7.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvtpd_epu32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtpd_epu32(src, 0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, 8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtpd_epu32() { + let a = _mm_set_pd(6., 7.5); + let r = _mm_maskz_cvtpd_epu32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtpd_epu32(0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, 8); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtpd_pslo() { let v2 = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); @@ -1319,6 +3706,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm256_set1_epi64x(-1); + let r = _mm256_mask_cvtepi8_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepi8_epi64(src, 0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_cvtepi8_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepi8_epi64(0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm_set1_epi64x(-1); + let r = _mm_mask_cvtepi8_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi8_epi64(src, 0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_cvtepi8_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi8_epi64(0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepu8_epi64() { let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -1348,6 +3777,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepu8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm256_set1_epi64x(-1); + let r = _mm256_mask_cvtepu8_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepu8_epi64(src, 0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepu8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_cvtepu8_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepu8_epi64(0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepu8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm_set1_epi64x(-1); + let r = _mm_mask_cvtepu8_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepu8_epi64(src, 0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepu8_epi64() { + let a = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_cvtepu8_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepu8_epi64(0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi16_epi64() { let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); @@ -1377,6 +3848,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm256_set1_epi64x(-1); + let r = _mm256_mask_cvtepi16_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepi16_epi64(src, 0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_cvtepi16_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepi16_epi64(0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm_set1_epi64x(-1); + let r = _mm_mask_cvtepi16_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi16_epi64(src, 0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_cvtepi16_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi16_epi64(0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepu16_epi64() { let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); @@ -1406,6 +3919,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepu16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm256_set1_epi64x(-1); + let r = _mm256_mask_cvtepu16_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepu16_epi64(src, 0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepu16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm256_maskz_cvtepu16_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepu16_epi64(0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepu16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm_set1_epi64x(-1); + let r = _mm_mask_cvtepu16_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepu16_epi64(src, 0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepu16_epi64() { + let a = _mm_set_epi16(8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm_maskz_cvtepu16_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepu16_epi64(0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi32_epi64() { let a = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); @@ -1435,6 +3990,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi32_epi64() { + let a = _mm_set_epi32(8, 9, 10, 11); + let src = _mm256_set1_epi64x(-1); + let r = _mm256_mask_cvtepi32_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepi32_epi64(src, 0b00001111, a); + let e = _mm256_set_epi64x(8, 9, 10, 11); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi32_epi64() { + let a = _mm_set_epi32(8, 9, 10, 11); + let r = _mm256_maskz_cvtepi32_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepi32_epi64(0b00001111, a); + let e = _mm256_set_epi64x(8, 9, 10, 11); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi32_epi64() { + let a = _mm_set_epi32(8, 9, 10, 11); + let src = _mm_set1_epi64x(0); + let r = _mm_mask_cvtepi32_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi32_epi64(src, 0b00000011, a); + let e = _mm_set_epi64x(10, 11); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi32_epi64() { + let a = _mm_set_epi32(8, 9, 10, 11); + let r = _mm_maskz_cvtepi32_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi32_epi64(0b00000011, a); + let e = _mm_set_epi64x(10, 11); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepu32_epi64() { let a = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); @@ -1464,6 +4061,48 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepu32_epi64() { + let a = _mm_set_epi32(12, 13, 14, 15); + let src = _mm256_set1_epi64x(-1); + let r = _mm256_mask_cvtepu32_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_cvtepu32_epi64(src, 0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepu32_epi64() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm256_maskz_cvtepu32_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_cvtepu32_epi64(0b00001111, a); + let e = _mm256_set_epi64x(12, 13, 14, 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepu32_epi64() { + let a = _mm_set_epi32(12, 13, 14, 15); + let src = _mm_set1_epi64x(-1); + let r = _mm_mask_cvtepu32_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepu32_epi64(src, 0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepu32_epi64() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm_maskz_cvtepu32_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepu32_epi64(0b00000011, a); + let e = _mm_set_epi64x(14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi32_pd() { let a = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); @@ -1493,6 +4132,48 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let src = _mm256_set1_pd(-1.); + let r = _mm256_mask_cvtepi32_pd(src, 0, a); + assert_eq_m256d(r, src); + let r = _mm256_mask_cvtepi32_pd(src, 0b00001111, a); + let e = _mm256_set_pd(12., 13., 14., 15.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm256_maskz_cvtepi32_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_cvtepi32_pd(0b00001111, a); + let e = _mm256_set_pd(12., 13., 14., 15.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let src = _mm_set1_pd(-1.); + let r = _mm_mask_cvtepi32_pd(src, 0, a); + assert_eq_m128d(r, src); + let r = _mm_mask_cvtepi32_pd(src, 0b00000011, a); + let e = _mm_set_pd(14., 15.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm_maskz_cvtepi32_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_cvtepi32_pd(0b00000011, a); + let e = _mm_set_pd(14., 15.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepu32_pd() { let a = _mm256_set_epi32(8, 9, 10, 11, 12, 13, 14, 15); @@ -1522,22 +4203,80 @@ mod tests { assert_eq_m512d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_cvtepi32lo_pd() { - let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let r = _mm512_cvtepi32lo_pd(a); - let e = _mm512_set_pd(8., 9., 10., 11., 12., 13., 14., 15.); - assert_eq_m512d(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtepu32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm256_cvtepu32_pd(a); + let e = _mm256_set_pd(12., 13., 14., 15.); + assert_eq_m256d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_mask_cvtepi32lo_pd() { - let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let src = _mm512_set1_pd(-1.); - let r = _mm512_mask_cvtepi32lo_pd(src, 0, a); - assert_eq_m512d(r, src); - let r = _mm512_mask_cvtepi32lo_pd(src, 0b00001111, a); - let e = _mm512_set_pd(-1., -1., -1., -1., 12., 13., 14., 15.); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepu32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let src = _mm256_set1_pd(-1.); + let r = _mm256_mask_cvtepu32_pd(src, 0, a); + assert_eq_m256d(r, src); + let r = _mm256_mask_cvtepu32_pd(src, 0b00001111, a); + let e = _mm256_set_pd(12., 13., 14., 15.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepu32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm256_maskz_cvtepu32_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_cvtepu32_pd(0b00001111, a); + let e = _mm256_set_pd(12., 13., 14., 15.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtepu32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm_cvtepu32_pd(a); + let e = _mm_set_pd(14., 15.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepu32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let src = _mm_set1_pd(-1.); + let r = _mm_mask_cvtepu32_pd(src, 0, a); + assert_eq_m128d(r, src); + let r = _mm_mask_cvtepu32_pd(src, 0b00000011, a); + let e = _mm_set_pd(14., 15.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepu32_pd() { + let a = _mm_set_epi32(12, 13, 14, 15); + let r = _mm_maskz_cvtepu32_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_cvtepu32_pd(0b00000011, a); + let e = _mm_set_pd(14., 15.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_cvtepi32lo_pd() { + let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let r = _mm512_cvtepi32lo_pd(a); + let e = _mm512_set_pd(8., 9., 10., 11., 12., 13., 14., 15.); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtepi32lo_pd() { + let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let src = _mm512_set1_pd(-1.); + let r = _mm512_mask_cvtepi32lo_pd(src, 0, a); + assert_eq_m512d(r, src); + let r = _mm512_mask_cvtepi32lo_pd(src, 0b00001111, a); + let e = _mm512_set_pd(-1., -1., -1., -1., 12., 13., 14., 15.); assert_eq_m512d(r, e); } @@ -1589,6 +4328,64 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtepi64_epi32() { + let a = _mm256_set_epi64x(1, 2, 3, 4); + let r = _mm256_cvtepi64_epi32(a); + let e = _mm_set_epi32(1, 2, 3, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi64_epi32() { + let a = _mm256_set_epi64x(1, 2, 3, 4); + let src = _mm_set1_epi32(0); + let r = _mm256_mask_cvtepi64_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtepi64_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(1, 2, 3, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi64_epi32() { + let a = _mm256_set_epi64x(1, 2, 3, 4); + let r = _mm256_maskz_cvtepi64_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtepi64_epi32(0b00001111, a); + let e = _mm_set_epi32(1, 2, 3, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtepi64_epi32() { + let a = _mm_set_epi64x(3, 4); + let r = _mm_cvtepi64_epi32(a); + let e = _mm_set_epi32(0, 0, 3, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi64_epi32() { + let a = _mm_set_epi64x(3, 4); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvtepi64_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi64_epi32(src, 0b00000011, a); + let e = _mm_set_epi32(0, 0, 3, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi64_epi32() { + let a = _mm_set_epi64x(3, 4); + let r = _mm_maskz_cvtepi64_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi64_epi32(0b00000011, a); + let e = _mm_set_epi32(0, 0, 3, 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi64_epi16() { let a = _mm512_set_epi64(8, 9, 10, 11, 12, 13, 14, 15); @@ -1618,6 +4415,64 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtepi64_epi16() { + let a = _mm256_set_epi64x(12, 13, 14, 15); + let r = _mm256_cvtepi64_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi64_epi16() { + let a = _mm256_set_epi64x(12, 13, 14, 15); + let src = _mm_set1_epi16(0); + let r = _mm256_mask_cvtepi64_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtepi64_epi16(src, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi64_epi16() { + let a = _mm256_set_epi64x(12, 13, 14, 15); + let r = _mm256_maskz_cvtepi64_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtepi64_epi16(0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtepi64_epi16() { + let a = _mm_set_epi64x(14, 15); + let r = _mm_cvtepi64_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi64_epi16() { + let a = _mm_set_epi64x(14, 15); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvtepi64_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi64_epi16(src, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi64_epi16() { + let a = _mm_set_epi64x(14, 15); + let r = _mm_maskz_cvtepi64_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi64_epi16(0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, 14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtepi64_epi8() { let a = _mm512_set_epi64(8, 9, 10, 11, 12, 13, 14, 15); @@ -1647,6 +4502,64 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtepi64_epi8() { + let a = _mm256_set_epi64x(12, 13, 14, 15); + let r = _mm256_cvtepi64_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi64_epi8() { + let a = _mm256_set_epi64x(12, 13, 14, 15); + let src = _mm_set1_epi8(0); + let r = _mm256_mask_cvtepi64_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtepi64_epi8(src, 0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtepi64_epi8() { + let a = _mm256_set_epi64x(12, 13, 14, 15); + let r = _mm256_maskz_cvtepi64_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtepi64_epi8(0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtepi64_epi8() { + let a = _mm_set_epi64x(14, 15); + let r = _mm_cvtepi64_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi64_epi8() { + let a = _mm_set_epi64x(14, 15); + let src = _mm_set1_epi8(0); + let r = _mm_mask_cvtepi64_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtepi64_epi8(src, 0b00000011, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtepi64_epi8() { + let a = _mm_set_epi64x(14, 15); + let r = _mm_maskz_cvtepi64_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtepi64_epi8(0b00000011, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtsepi64_epi32() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, i64::MIN, i64::MAX); @@ -1676,6 +4589,64 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtsepi64_epi32() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let r = _mm256_cvtsepi64_epi32(a); + let e = _mm_set_epi32(4, 5, i32::MIN, i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi64_epi32() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let src = _mm_set1_epi32(-1); + let r = _mm256_mask_cvtsepi64_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtsepi64_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(4, 5, i32::MIN, i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtsepi64_epi32() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let r = _mm256_maskz_cvtsepi64_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtsepi64_epi32(0b00001111, a); + let e = _mm_set_epi32(4, 5, i32::MIN, i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtsepi64_epi32() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let r = _mm_cvtsepi64_epi32(a); + let e = _mm_set_epi32(0, 0, i32::MIN, i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi64_epi32() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvtsepi64_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtsepi64_epi32(src, 0b00000011, a); + let e = _mm_set_epi32(0, 0, i32::MIN, i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtsepi64_epi32() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let r = _mm_maskz_cvtsepi64_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtsepi64_epi32(0b00000011, a); + let e = _mm_set_epi32(0, 0, i32::MIN, i32::MAX); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtsepi64_epi16() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, i64::MIN, i64::MAX); @@ -1705,6 +4676,64 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtsepi64_epi16() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let r = _mm256_cvtsepi64_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, i16::MIN, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi64_epi16() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let src = _mm_set1_epi16(0); + let r = _mm256_mask_cvtsepi64_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtsepi64_epi16(src, 0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, i16::MIN, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtsepi64_epi16() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let r = _mm256_maskz_cvtsepi64_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtsepi64_epi16(0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, i16::MIN, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtsepi64_epi16() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let r = _mm_cvtsepi64_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, i16::MIN, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi64_epi16() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvtsepi64_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtsepi64_epi16(src, 0b00000011, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, i16::MIN, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtsepi64_epi16() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let r = _mm_maskz_cvtsepi64_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtsepi64_epi16(0b00000011, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, i16::MIN, i16::MAX); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtsepi64_epi8() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, i64::MIN, i64::MAX); @@ -1720,23 +4749,12 @@ mod tests { let r = _mm512_mask_cvtsepi64_epi8(src, 0, a); assert_eq_m128i(r, src); let r = _mm512_mask_cvtsepi64_epi8(src, 0b00001111, a); + #[rustfmt::skip] let e = _mm_set_epi8( - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -1, - -1, - -1, - -1, - 4, - 5, - i8::MIN, - i8::MAX, + 0, 0, 0, 0, + 0, 0, 0, 0, + -1, -1, -1, -1, + 4, 5, i8::MIN, i8::MAX, ); assert_eq_m128i(r, e); } @@ -1751,6 +4769,64 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtsepi64_epi8() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let r = _mm256_cvtsepi64_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, i8::MIN, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi64_epi8() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let src = _mm_set1_epi8(0); + let r = _mm256_mask_cvtsepi64_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtsepi64_epi8(src, 0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, i8::MIN, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtsepi64_epi8() { + let a = _mm256_set_epi64x(4, 5, i64::MIN, i64::MAX); + let r = _mm256_maskz_cvtsepi64_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtsepi64_epi8(0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, i8::MIN, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtsepi64_epi8() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let r = _mm_cvtsepi64_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, i8::MIN, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi64_epi8() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let src = _mm_set1_epi8(0); + let r = _mm_mask_cvtsepi64_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtsepi64_epi8(src, 0b00000011, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, i8::MIN, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtsepi64_epi8() { + let a = _mm_set_epi64x(i64::MIN, i64::MAX); + let r = _mm_maskz_cvtsepi64_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtsepi64_epi8(0b00000011, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, i8::MIN, i8::MAX); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtusepi64_epi32() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, i64::MIN, i64::MIN); @@ -1780,6 +4856,64 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtusepi64_epi32() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let r = _mm256_cvtusepi64_epi32(a); + let e = _mm_set_epi32(4, 5, 6, u32::MAX as i32); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi64_epi32() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let src = _mm_set1_epi32(0); + let r = _mm256_mask_cvtusepi64_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtusepi64_epi32(src, 0b00001111, a); + let e = _mm_set_epi32(4, 5, 6, u32::MAX as i32); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtusepi64_epi32() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let r = _mm256_maskz_cvtusepi64_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtusepi64_epi32(0b00001111, a); + let e = _mm_set_epi32(4, 5, 6, u32::MAX as i32); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtusepi64_epi32() { + let a = _mm_set_epi64x(6, i64::MAX); + let r = _mm_cvtusepi64_epi32(a); + let e = _mm_set_epi32(0, 0, 6, u32::MAX as i32); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi64_epi32() { + let a = _mm_set_epi64x(6, i64::MAX); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvtusepi64_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtusepi64_epi32(src, 0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, u32::MAX as i32); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtusepi64_epi32() { + let a = _mm_set_epi64x(6, i64::MAX); + let r = _mm_maskz_cvtusepi64_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtusepi64_epi32(0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, u32::MAX as i32); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtusepi64_epi16() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, i64::MIN, i64::MIN); @@ -1809,6 +4943,64 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtusepi64_epi16() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let r = _mm256_cvtusepi64_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi64_epi16() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let src = _mm_set1_epi16(0); + let r = _mm256_mask_cvtusepi64_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtusepi64_epi16(src, 0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtusepi64_epi16() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let r = _mm256_maskz_cvtusepi64_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtusepi64_epi16(0b00001111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 4, 5, 6, u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtusepi64_epi16() { + let a = _mm_set_epi64x(6, i64::MAX); + let r = _mm_cvtusepi64_epi16(a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, 6, u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi64_epi16() { + let a = _mm_set_epi64x(6, i64::MAX); + let src = _mm_set1_epi16(0); + let r = _mm_mask_cvtusepi64_epi16(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtusepi64_epi16(src, 0b00000011, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, 6, u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtusepi64_epi16() { + let a = _mm_set_epi64x(6, i64::MAX); + let r = _mm_maskz_cvtusepi64_epi16(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtusepi64_epi16(0b00000011, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, 6, u16::MAX as i16); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtusepi64_epi8() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, i64::MIN, i64::MIN); @@ -1838,6 +5030,64 @@ mod tests { assert_eq_m128i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvtusepi64_epi8() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let r = _mm256_cvtusepi64_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi64_epi8() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let src = _mm_set1_epi8(0); + let r = _mm256_mask_cvtusepi64_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvtusepi64_epi8(src, 0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvtusepi64_epi8() { + let a = _mm256_set_epi64x(4, 5, 6, i64::MAX); + let r = _mm256_maskz_cvtusepi64_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvtusepi64_epi8(0b00001111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvtusepi64_epi8() { + let a = _mm_set_epi64x(6, i64::MAX); + let r = _mm_cvtusepi64_epi8(a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi64_epi8() { + let a = _mm_set_epi64x(6, i64::MAX); + let src = _mm_set1_epi8(0); + let r = _mm_mask_cvtusepi64_epi8(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvtusepi64_epi8(src, 0b00000011, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, u8::MAX as i8); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvtusepi64_epi8() { + let a = _mm_set_epi64x(6, i64::MAX); + let r = _mm_maskz_cvtusepi64_epi8(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvtusepi64_epi8(0b00000011, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, u8::MAX as i8); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cvtt_roundpd_epi32() { let a = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); @@ -1925,10 +5175,52 @@ mod tests { assert_eq_m256i(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_cvttpd_epu32() { - let a = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); - let r = _mm512_cvttpd_epu32(a); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvttpd_epi32() { + let a = _mm256_setr_pd(4., -5.5, 6., -7.5); + let src = _mm_set1_epi32(0); + let r = _mm256_mask_cvttpd_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvttpd_epi32(src, 0b00001111, a); + let e = _mm_setr_epi32(4, -5, 6, -7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvttpd_epi32() { + let a = _mm256_setr_pd(4., -5.5, 6., -7.5); + let r = _mm256_maskz_cvttpd_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvttpd_epi32(0b00001111, a); + let e = _mm_setr_epi32(4, -5, 6, -7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvttpd_epi32() { + let a = _mm_set_pd(6., -7.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvttpd_epi32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvttpd_epi32(src, 0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, -7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvttpd_epi32() { + let a = _mm_set_pd(6., -7.5); + let r = _mm_maskz_cvttpd_epi32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvttpd_epi32(0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, -7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_cvttpd_epu32() { + let a = _mm512_setr_pd(0., -1.5, 2., -3.5, 4., -5.5, 6., -7.5); + let r = _mm512_cvttpd_epu32(a); let e = _mm256_setr_epi32(0, -1, 2, -1, 4, -1, 6, -1); assert_eq_m256i(r, e); } @@ -1954,6 +5246,64 @@ mod tests { assert_eq_m256i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cvttpd_epu32() { + let a = _mm256_set_pd(4., 5.5, 6., 7.5); + let r = _mm256_cvttpd_epu32(a); + let e = _mm_set_epi32(4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvttpd_epu32() { + let a = _mm256_set_pd(4., 5.5, 6., 7.5); + let src = _mm_set1_epi32(0); + let r = _mm256_mask_cvttpd_epu32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm256_mask_cvttpd_epu32(src, 0b00001111, a); + let e = _mm_set_epi32(4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_cvttpd_epu32() { + let a = _mm256_set_pd(4., 5.5, 6., 7.5); + let r = _mm256_maskz_cvttpd_epu32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm256_maskz_cvttpd_epu32(0b00001111, a); + let e = _mm_set_epi32(4, 5, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cvttpd_epu32() { + let a = _mm_set_pd(6., 7.5); + let r = _mm_cvttpd_epu32(a); + let e = _mm_set_epi32(0, 0, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvttpd_epu32() { + let a = _mm_set_pd(6., 7.5); + let src = _mm_set1_epi32(0); + let r = _mm_mask_cvttpd_epu32(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_cvttpd_epu32(src, 0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, 7); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_cvttpd_epu32() { + let a = _mm_set_pd(6., 7.5); + let r = _mm_maskz_cvttpd_epu32(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_cvttpd_epu32(0b00000011, a); + let e = _mm_set_epi32(0, 0, 6, 7); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_add_round_pd() { let a = _mm512_setr_pd(8., 9.5, 10., 11.5, 12., 13.5, 14., 0.000000000000000007); @@ -3239,9 +6589,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpeq_pd_mask() { - #[rustfmt::skip] let a = _mm512_set_pd(0., 1., -1., 13., f64::MAX, f64::MIN, f64::NAN, -100.); - #[rustfmt::skip] let b = _mm512_set_pd(0., 1., 13., 42., f64::MAX, f64::MIN, f64::NAN, -100.); let m = _mm512_cmpeq_pd_mask(b, a); assert_eq!(m, 0b11001101); @@ -3249,9 +6597,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_cmpeq_pd_mask() { - #[rustfmt::skip] let a = _mm512_set_pd(0., 1., -1., 13., f64::MAX, f64::MIN, f64::NAN, -100.); - #[rustfmt::skip] let b = _mm512_set_pd(0., 1., 13., 42., f64::MAX, f64::MIN, f64::NAN, -100.); let mask = 0b01111010; let r = _mm512_mask_cmpeq_pd_mask(mask, b, a); @@ -3260,9 +6606,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpneq_pd_mask() { - #[rustfmt::skip] let a = _mm512_set_pd(0., 1., -1., 13., f64::MAX, f64::MIN, f64::NAN, -100.); - #[rustfmt::skip] let b = _mm512_set_pd(0., 1., 13., 42., f64::MAX, f64::MIN, f64::NAN, -100.); let m = _mm512_cmpneq_pd_mask(b, a); assert_eq!(m, 0b00110010); @@ -3270,9 +6614,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_cmpneq_pd_mask() { - #[rustfmt::skip] let a = _mm512_set_pd(0., 1., -1., 13., f64::MAX, f64::MIN, f64::NAN, -100.); - #[rustfmt::skip] let b = _mm512_set_pd(0., 1., 13., 42., f64::MAX, f64::MIN, f64::NAN, -100.); let mask = 0b01111010; let r = _mm512_mask_cmpneq_pd_mask(mask, b, a); @@ -3281,7 +6623,6 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmp_pd_mask() { - #[rustfmt::skip] let a = _mm512_set_pd(0., 1., -1., 13., f64::MAX, f64::MIN, 100., -100.); let b = _mm512_set1_pd(-1.); let m = _mm512_cmp_pd_mask(a, b, _CMP_LT_OQ); @@ -3290,7 +6631,6 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_cmp_pd_mask() { - #[rustfmt::skip] let a = _mm512_set_pd(0., 1., -1., 13., f64::MAX, f64::MIN, 100., -100.); let b = _mm512_set1_pd(-1.); let mask = 0b01100110; @@ -3298,6 +6638,40 @@ mod tests { assert_eq!(r, 0b00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmp_pd_mask() { + let a = _mm256_set_pd(0., 1., -1., 13.); + let b = _mm256_set1_pd(1.); + let m = _mm256_cmp_pd_mask(a, b, _CMP_LT_OQ); + assert_eq!(m, 0b00001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmp_pd_mask() { + let a = _mm256_set_pd(0., 1., -1., 13.); + let b = _mm256_set1_pd(1.); + let mask = 0b11111111; + let r = _mm256_mask_cmp_pd_mask(mask, a, b, _CMP_LT_OQ); + assert_eq!(r, 0b00001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmp_pd_mask() { + let a = _mm_set_pd(0., 1.); + let b = _mm_set1_pd(1.); + let m = _mm_cmp_pd_mask(a, b, _CMP_LT_OQ); + assert_eq!(m, 0b00000010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmp_pd_mask() { + let a = _mm_set_pd(0., 1.); + let b = _mm_set1_pd(1.); + let mask = 0b11111111; + let r = _mm_mask_cmp_pd_mask(mask, a, b, _CMP_LT_OQ); + assert_eq!(r, 0b00000010); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmp_round_pd_mask() { #[rustfmt::skip] @@ -3377,6 +6751,40 @@ mod tests { assert_eq!(r, 0b01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmplt_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, 100); + let b = _mm256_set1_epi64x(2); + let r = _mm256_cmplt_epu64_mask(a, b); + assert_eq!(r, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, 100); + let b = _mm256_set1_epi64x(2); + let mask = 0b11111111; + let r = _mm256_mask_cmplt_epu64_mask(mask, a, b); + assert_eq!(r, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmplt_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(2); + let r = _mm_cmplt_epu64_mask(a, b); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmplt_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(2); + let mask = 0b11111111; + let r = _mm_mask_cmplt_epu64_mask(mask, a, b); + assert_eq!(r, 0b00000011); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpgt_epu64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); @@ -3394,6 +6802,40 @@ mod tests { assert_eq!(r, 0b01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpgt_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set1_epi64x(1); + let r = _mm256_cmpgt_epu64_mask(a, b); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let b = _mm256_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm256_mask_cmpgt_epu64_mask(mask, a, b); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpgt_epu64_mask() { + let a = _mm_set_epi64x(1, 2); + let b = _mm_set1_epi64x(1); + let r = _mm_cmpgt_epu64_mask(a, b); + assert_eq!(r, 0b00000001); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epu64_mask() { + let a = _mm_set_epi64x(1, 2); + let b = _mm_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm_mask_cmpgt_epu64_mask(mask, a, b); + assert_eq!(r, 0b00000001); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmple_epu64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); @@ -3412,6 +6854,40 @@ mod tests { assert_eq!(_mm512_mask_cmple_epu64_mask(mask, a, b), 0b01111010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmple_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, 1); + let b = _mm256_set1_epi64x(1); + let r = _mm256_cmple_epu64_mask(a, b); + assert_eq!(r, 0b00001101) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmple_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, 1); + let b = _mm256_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm256_mask_cmple_epu64_mask(mask, a, b); + assert_eq!(r, 0b00001101) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmple_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let r = _mm_cmple_epu64_mask(a, b); + assert_eq!(r, 0b00000011) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmple_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm_mask_cmple_epu64_mask(mask, a, b); + assert_eq!(r, 0b00000011) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpge_epu64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); @@ -3426,8 +6902,43 @@ mod tests { unsafe fn test_mm512_mask_cmpge_epu64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); let b = _mm512_set1_epi64(-1); - let mask = 0b01111010; - assert_eq!(_mm512_mask_cmpge_epu64_mask(mask, a, b), 0b01111010); + let mask = 0b11111111; + let r = _mm512_mask_cmpge_epu64_mask(mask, a, b); + assert_eq!(r, 0b00110000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpge_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, u64::MAX as i64); + let b = _mm256_set1_epi64x(1); + let r = _mm256_cmpge_epu64_mask(a, b); + assert_eq!(r, 0b00000111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, 2, u64::MAX as i64); + let b = _mm256_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm256_mask_cmpge_epu64_mask(mask, a, b); + assert_eq!(r, 0b00000111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpge_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let r = _mm_cmpge_epu64_mask(a, b); + assert_eq!(r, 0b00000001); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpge_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm_mask_cmpge_epu64_mask(mask, a, b); + assert_eq!(r, 0b00000001); } #[simd_test(enable = "avx512f")] @@ -3447,6 +6958,40 @@ mod tests { assert_eq!(r, 0b01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpeq_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, u64::MAX as i64); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let m = _mm256_cmpeq_epu64_mask(b, a); + assert_eq!(m, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, u64::MAX as i64); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm256_mask_cmpeq_epu64_mask(mask, b, a); + assert_eq!(r, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpeq_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set_epi64x(0, 1); + let m = _mm_cmpeq_epu64_mask(b, a); + assert_eq!(m, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set_epi64x(0, 1); + let mask = 0b11111111; + let r = _mm_mask_cmpeq_epu64_mask(mask, b, a); + assert_eq!(r, 0b00000011); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpneq_epu64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); @@ -3464,6 +7009,40 @@ mod tests { assert_eq!(r, 0b00110010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpneq_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, u64::MAX as i64); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let r = _mm256_cmpneq_epu64_mask(b, a); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, u64::MAX as i64); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm256_mask_cmpneq_epu64_mask(mask, b, a); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpneq_epu64_mask() { + let a = _mm_set_epi64x(-1, u64::MAX as i64); + let b = _mm_set_epi64x(13, 42); + let r = _mm_cmpneq_epu64_mask(b, a); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epu64_mask() { + let a = _mm_set_epi64x(-1, u64::MAX as i64); + let b = _mm_set_epi64x(13, 42); + let mask = 0b11111111; + let r = _mm_mask_cmpneq_epu64_mask(mask, b, a); + assert_eq!(r, 0b00000011); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmp_epu64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); @@ -3481,6 +7060,40 @@ mod tests { assert_eq!(r, 0b01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmp_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 100); + let b = _mm256_set1_epi64x(1); + let m = _mm256_cmp_epu64_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b00001000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmp_epu64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 100); + let b = _mm256_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm256_mask_cmp_epu64_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b00001000); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmp_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let m = _mm_cmp_epu64_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b00000010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmp_epu64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm_mask_cmp_epu64_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b00000010); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmplt_epi64_mask() { let a = _mm512_set_epi64(0, 1, -1, 13, i64::MAX, i64::MIN, 100, -100); @@ -3498,6 +7111,40 @@ mod tests { assert_eq!(r, 0b00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmplt_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, -13); + let b = _mm256_set1_epi64x(-1); + let r = _mm256_cmplt_epi64_mask(a, b); + assert_eq!(r, 0b00000001); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmplt_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, -13); + let b = _mm256_set1_epi64x(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmplt_epi64_mask(mask, a, b); + assert_eq!(r, 0b00000001); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmplt_epi64_mask() { + let a = _mm_set_epi64x(-1, -13); + let b = _mm_set1_epi64x(-1); + let r = _mm_cmplt_epi64_mask(a, b); + assert_eq!(r, 0b00000001); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmplt_epi64_mask() { + let a = _mm_set_epi64x(-1, -13); + let b = _mm_set1_epi64x(-1); + let mask = 0b11111111; + let r = _mm_mask_cmplt_epi64_mask(mask, a, b); + assert_eq!(r, 0b00000001); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpgt_epi64_mask() { let a = _mm512_set_epi64(0, 1, -1, 13, i64::MAX, i64::MIN, 100, -100); @@ -3515,6 +7162,40 @@ mod tests { assert_eq!(r, 0b00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpgt_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set1_epi64x(-1); + let r = _mm256_cmpgt_epi64_mask(a, b); + assert_eq!(r, 0b00001101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpgt_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set1_epi64x(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmpgt_epi64_mask(mask, a, b); + assert_eq!(r, 0b00001101); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpgt_epi64_mask() { + let a = _mm_set_epi64x(0, -1); + let b = _mm_set1_epi64x(-1); + let r = _mm_cmpgt_epi64_mask(a, b); + assert_eq!(r, 0b00000010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpgt_epi64_mask() { + let a = _mm_set_epi64x(0, -1); + let b = _mm_set1_epi64x(-1); + let mask = 0b11111111; + let r = _mm_mask_cmpgt_epi64_mask(mask, a, b); + assert_eq!(r, 0b00000010); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmple_epi64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); @@ -3533,6 +7214,40 @@ mod tests { assert_eq!(_mm512_mask_cmple_epi64_mask(mask, a, b), 0b00110000); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmple_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, i64::MAX); + let b = _mm256_set1_epi64x(-1); + let r = _mm256_cmple_epi64_mask(a, b); + assert_eq!(r, 0b00000010) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmple_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, i64::MAX); + let b = _mm256_set1_epi64x(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmple_epi64_mask(mask, a, b); + assert_eq!(r, 0b00000010) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmple_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let r = _mm_cmple_epi64_mask(a, b); + assert_eq!(r, 0b00000011) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmple_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm_mask_cmple_epi64_mask(mask, a, b); + assert_eq!(r, 0b00000011) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmpge_epi64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); @@ -3547,8 +7262,43 @@ mod tests { unsafe fn test_mm512_mask_cmpge_epi64_mask() { let a = _mm512_set_epi64(0, 1, -1, u64::MAX as i64, i64::MAX, i64::MIN, 100, -100); let b = _mm512_set1_epi64(-1); - let mask = 0b01111010; - assert_eq!(_mm512_mask_cmpge_epi64_mask(mask, a, b), 0b0110000); + let mask = 0b11111111; + let r = _mm512_mask_cmpge_epi64_mask(mask, a, b); + assert_eq!(r, 0b11111010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpge_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, i64::MAX); + let b = _mm256_set1_epi64x(-1); + let r = _mm256_cmpge_epi64_mask(a, b); + assert_eq!(r, 0b00001111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpge_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, i64::MAX); + let b = _mm256_set1_epi64x(-1); + let mask = 0b11111111; + let r = _mm256_mask_cmpge_epi64_mask(mask, a, b); + assert_eq!(r, 0b00001111); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpge_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(-1); + let r = _mm_cmpge_epi64_mask(a, b); + assert_eq!(r, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpge_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(-1); + let mask = 0b11111111; + let r = _mm_mask_cmpge_epi64_mask(mask, a, b); + assert_eq!(r, 0b00000011); } #[simd_test(enable = "avx512f")] @@ -3568,6 +7318,40 @@ mod tests { assert_eq!(r, 0b01001010); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpeq_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let m = _mm256_cmpeq_epi64_mask(b, a); + assert_eq!(m, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpeq_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm256_mask_cmpeq_epi64_mask(mask, b, a); + assert_eq!(r, 0b00001100); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpeq_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set_epi64x(0, 1); + let m = _mm_cmpeq_epi64_mask(b, a); + assert_eq!(m, 0b00000011); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpeq_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set_epi64x(0, 1); + let mask = 0b11111111; + let r = _mm_mask_cmpeq_epi64_mask(mask, b, a); + assert_eq!(r, 0b00000011); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_set_epi64() { let r = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); @@ -3596,6 +7380,40 @@ mod tests { assert_eq!(r, 0b00110010) } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmpneq_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let r = _mm256_cmpneq_epi64_mask(b, a); + assert_eq!(r, 0b00000011) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmpneq_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set_epi64x(0, 1, 13, 42); + let mask = 0b11111111; + let r = _mm256_mask_cmpneq_epi64_mask(mask, b, a); + assert_eq!(r, 0b00000011) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmpneq_epi64_mask() { + let a = _mm_set_epi64x(-1, 13); + let b = _mm_set_epi64x(13, 42); + let r = _mm_cmpneq_epi64_mask(b, a); + assert_eq!(r, 0b00000011) + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmpneq_epi64_mask() { + let a = _mm_set_epi64x(-1, 13); + let b = _mm_set_epi64x(13, 42); + let mask = 0b11111111; + let r = _mm_mask_cmpneq_epi64_mask(mask, b, a); + assert_eq!(r, 0b00000011) + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_cmp_epi64_mask() { let a = _mm512_set_epi64(0, 1, -1, 13, i64::MAX, i64::MIN, 100, -100); @@ -3613,6 +7431,40 @@ mod tests { assert_eq!(r, 0b00000100); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_cmp_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set1_epi64x(1); + let m = _mm256_cmp_epi64_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b00001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cmp_epi64_mask() { + let a = _mm256_set_epi64x(0, 1, -1, 13); + let b = _mm256_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm256_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b00001010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_cmp_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let m = _mm_cmp_epi64_mask(a, b, _MM_CMPINT_LT); + assert_eq!(m, 0b00000010); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cmp_epi64_mask() { + let a = _mm_set_epi64x(0, 1); + let b = _mm_set1_epi64x(1); + let mask = 0b11111111; + let r = _mm_mask_cmp_epi64_mask(mask, a, b, _MM_CMPINT_LT); + assert_eq!(r, 0b00000010); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_i32gather_pd() { let mut arr = [0f64; 128]; @@ -3620,7 +7472,6 @@ mod tests { arr[i] = i as f64; } // A multiplier of 8 is word-addressing - #[rustfmt::skip] let index = _mm256_setr_epi32(0, 16, 32, 48, 64, 80, 96, 112); let r = _mm512_i32gather_pd(index, arr.as_ptr() as *const u8, 8); assert_eq_m512d(r, _mm512_setr_pd(0., 16., 32., 48., 64., 80., 96., 112.)); @@ -3634,7 +7485,6 @@ mod tests { } let src = _mm512_set1_pd(2.); let mask = 0b10101010; - #[rustfmt::skip] let index = _mm256_setr_epi32(0, 16, 32, 48, 64, 80, 96, 112); // A multiplier of 8 is word-addressing let r = _mm512_mask_i32gather_pd(src, mask, index, arr.as_ptr() as *const u8, 8); @@ -3648,7 +7498,6 @@ mod tests { arr[i] = i as f64; } // A multiplier of 8 is word-addressing - #[rustfmt::skip] let index = _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112); let r = _mm512_i64gather_pd(index, arr.as_ptr() as *const u8, 8); assert_eq_m512d(r, _mm512_setr_pd(0., 16., 32., 48., 64., 80., 96., 112.)); @@ -3662,7 +7511,6 @@ mod tests { } let src = _mm512_set1_pd(2.); let mask = 0b10101010; - #[rustfmt::skip] let index = _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112); // A multiplier of 8 is word-addressing let r = _mm512_mask_i64gather_pd(src, mask, index, arr.as_ptr() as *const u8, 8); @@ -3704,7 +7552,6 @@ mod tests { arr[i as usize] = i; } // A multiplier of 8 is word-addressing - #[rustfmt::skip] let index = _mm256_setr_epi32(0, 16, 32, 48, 64, 80, 96, 112); let r = _mm512_i32gather_epi64(index, arr.as_ptr() as *const u8, 8); assert_eq_m512i(r, _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112)); @@ -3718,7 +7565,6 @@ mod tests { } let src = _mm512_set1_epi64(2); let mask = 0b10101010; - #[rustfmt::skip] let index = _mm256_setr_epi32(0, 16, 32, 48, 64, 80, 96, 112); // A multiplier of 8 is word-addressing let r = _mm512_mask_i32gather_epi64(src, mask, index, arr.as_ptr() as *const u8, 8); @@ -3732,7 +7578,6 @@ mod tests { arr[i as usize] = i; } // A multiplier of 8 is word-addressing - #[rustfmt::skip] let index = _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112); let r = _mm512_i64gather_epi64(index, arr.as_ptr() as *const u8, 8); assert_eq_m512i(r, _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112)); @@ -3746,7 +7591,6 @@ mod tests { } let src = _mm512_set1_epi64(2); let mask = 0b10101010; - #[rustfmt::skip] let index = _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112); // A multiplier of 8 is word-addressing let r = _mm512_mask_i64gather_epi64(src, mask, index, arr.as_ptr() as *const u8, 8); @@ -3760,7 +7604,6 @@ mod tests { arr[i as usize] = i; } // A multiplier of 8 is word-addressing - #[rustfmt::skip] let index = _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112); let r = _mm512_i64gather_epi32(index, arr.as_ptr() as *const u8, 8); assert_eq_m256i(r, _mm256_setr_epi32(0, 16, 32, 48, 64, 80, 96, 112)); @@ -3774,7 +7617,6 @@ mod tests { } let src = _mm256_set1_epi32(2); let mask = 0b10101010; - #[rustfmt::skip] let index = _mm512_setr_epi64(0, 16, 32, 48, 64, 80, 96, 112); // A multiplier of 8 is word-addressing let r = _mm512_mask_i64gather_epi32(src, mask, index, arr.as_ptr() as *const u8, 8); @@ -3957,642 +7799,819 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rol_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 63, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let r = _mm512_rol_epi64(a, 1); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 0, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, + 1 << 0, 1 << 33, 1 << 33, 1 << 33, + 1 << 33, 1 << 33, 1 << 33, 1 << 33, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_rol_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 63, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let r = _mm512_mask_rol_epi64(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_rol_epi64(a, 0b11111111, a, 1); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 0, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, + 1 << 0, 1 << 33, 1 << 33, 1 << 33, + 1 << 33, 1 << 33, 1 << 33, 1 << 33, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_rol_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 63, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 63, ); let r = _mm512_maskz_rol_epi64(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_rol_epi64(0b00001111, a, 1); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 33, 1 << 33, 1 << 33, 1 << 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rol_epi64() { + let a = _mm256_set_epi64x(1 << 63, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_rol_epi64(a, 1); + let e = _mm256_set_epi64x(1 << 0, 1 << 33, 1 << 33, 1 << 33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rol_epi64() { + let a = _mm256_set_epi64x(1 << 63, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_mask_rol_epi64(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_rol_epi64(a, 0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 0, 1 << 33, 1 << 33, 1 << 33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rol_epi64() { + let a = _mm256_set_epi64x(1 << 63, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_maskz_rol_epi64(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_rol_epi64(0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 0, 1 << 33, 1 << 33, 1 << 33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rol_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let r = _mm_rol_epi64(a, 1); + let e = _mm_set_epi64x(1 << 0, 1 << 33); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rol_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let r = _mm_mask_rol_epi64(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_rol_epi64(a, 0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 0, 1 << 33); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rol_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let r = _mm_maskz_rol_epi64(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_rol_epi64(0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 0, 1 << 33); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_ror_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 0, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let r = _mm512_ror_epi64(a, 1); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 63, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, + 1 << 63, 1 << 31, 1 << 31, 1 << 31, + 1 << 31, 1 << 31, 1 << 31, 1 << 31, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_ror_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 0, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let r = _mm512_mask_ror_epi64(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_ror_epi64(a, 0b11111111, a, 1); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 63, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, + 1 << 63, 1 << 31, 1 << 31, 1 << 31, + 1 << 31, 1 << 31, 1 << 31, 1 << 31, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_ror_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 0, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 0, ); let r = _mm512_maskz_ror_epi64(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_ror_epi64(0b00001111, a, 1); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 31, 1 << 31, 1 << 31, 1 << 63); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_ror_epi64() { + let a = _mm256_set_epi64x(1 << 0, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_ror_epi64(a, 1); + let e = _mm256_set_epi64x(1 << 63, 1 << 31, 1 << 31, 1 << 31); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_ror_epi64() { + let a = _mm256_set_epi64x(1 << 0, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_mask_ror_epi64(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_ror_epi64(a, 0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 63, 1 << 31, 1 << 31, 1 << 31); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_ror_epi64() { + let a = _mm256_set_epi64x(1 << 0, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_maskz_ror_epi64(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_ror_epi64(0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 63, 1 << 31, 1 << 31, 1 << 31); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_ror_epi64() { + let a = _mm_set_epi64x(1 << 0, 1 << 32); + let r = _mm_ror_epi64(a, 1); + let e = _mm_set_epi64x(1 << 63, 1 << 31); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_ror_epi64() { + let a = _mm_set_epi64x(1 << 0, 1 << 32); + let r = _mm_mask_ror_epi64(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_ror_epi64(a, 0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 63, 1 << 31); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_ror_epi64() { + let a = _mm_set_epi64x(1 << 0, 1 << 32); + let r = _mm_maskz_ror_epi64(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_ror_epi64(0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 63, 1 << 31); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_slli_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 63, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let r = _mm512_slli_epi64(a, 1); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, + 0, 1 << 33, 1 << 33, 1 << 33, + 1 << 33, 1 << 33, 1 << 33, 1 << 33, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_slli_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 63, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let r = _mm512_mask_slli_epi64(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_slli_epi64(a, 0b11111111, a, 1); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, + 0, 1 << 33, 1 << 33, 1 << 33, + 1 << 33, 1 << 33, 1 << 33, 1 << 33, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_slli_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 63, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 63, ); let r = _mm512_maskz_slli_epi64(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_slli_epi64(0b00001111, a, 1); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 33, 1 << 33, 1 << 33, 0); assert_eq_m512i(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_srli_epi64() { - let a = _mm512_set_epi64( - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - ); - let r = _mm512_srli_epi64(a, 1); - let e = _mm512_set_epi64( - 0, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - ); - assert_eq_m512i(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_slli_epi64() { + let a = _mm256_set_epi64x(1 << 63, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_mask_slli_epi64(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_slli_epi64(a, 0b00001111, a, 1); + let e = _mm256_set_epi64x(0, 1 << 33, 1 << 33, 1 << 33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_slli_epi64() { + let a = _mm256_set_epi64x(1 << 63, 1 << 32, 1 << 32, 1 << 32); + let r = _mm256_maskz_slli_epi64(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_slli_epi64(0b00001111, a, 1); + let e = _mm256_set_epi64x(0, 1 << 33, 1 << 33, 1 << 33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_slli_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let r = _mm_mask_slli_epi64(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_slli_epi64(a, 0b00000011, a, 1); + let e = _mm_set_epi64x(0, 1 << 33); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_slli_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let r = _mm_maskz_slli_epi64(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_slli_epi64(0b00000011, a, 1); + let e = _mm_set_epi64x(0, 1 << 33); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_srli_epi64() { + #[rustfmt::skip] + let a = _mm512_set_epi64( + 1 << 0, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + ); + let r = _mm512_srli_epi64(a, 1); + #[rustfmt::skip] + let e = _mm512_set_epi64( + 0, 1 << 31, 1 << 31, 1 << 31, + 1 << 31, 1 << 31, 1 << 31, 1 << 31, + ); + assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_srli_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 0, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let r = _mm512_mask_srli_epi64(a, 0, a, 1); assert_eq_m512i(r, a); - let r = _mm512_mask_srli_epi64(a, 0b11111111, a, 1); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, + 0, 1 << 31, 1 << 31, 1 << 31, + 1 << 31, 1 << 31, 1 << 31, 1 << 31, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_srli_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 0, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 0, ); let r = _mm512_maskz_srli_epi64(0, a, 1); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srli_epi64(0b00001111, a, 1); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 31, 1 << 31, 1 << 31, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srli_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let r = _mm256_mask_srli_epi64(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_srli_epi64(a, 0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srli_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let r = _mm256_maskz_srli_epi64(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srli_epi64(0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srli_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let r = _mm_mask_srli_epi64(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_srli_epi64(a, 0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srli_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let r = _mm_maskz_srli_epi64(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srli_epi64(0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rolv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 63, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let b = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_rolv_epi64(a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 1 << 0, - 1 << 34, - 1 << 35, - 1 << 36, - 1 << 37, - 1 << 38, - 1 << 39, + 1 << 32, 1 << 0, 1 << 34, 1 << 35, + 1 << 36, 1 << 37, 1 << 38, 1 << 39, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_rolv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 63, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let b = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_mask_rolv_epi64(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_rolv_epi64(a, 0b11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 1 << 0, - 1 << 34, - 1 << 35, - 1 << 36, - 1 << 37, - 1 << 38, - 1 << 39, + 1 << 32, 1 << 0, 1 << 34, 1 << 35, + 1 << 36, 1 << 37, 1 << 38, 1 << 39, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_rolv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 62, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 62, ); let b = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 2); let r = _mm512_maskz_rolv_epi64(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_rolv_epi64(0b00001111, a, b); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 36, 1 << 37, 1 << 38, 1 << 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rolv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 63, 1 << 32, 1 << 32); + let b = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_rolv_epi64(a, b); + let e = _mm256_set_epi64x(1 << 32, 1 << 0, 1 << 34, 1 << 35); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rolv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 63, 1 << 32, 1 << 32); + let b = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_mask_rolv_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_rolv_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(1 << 32, 1 << 0, 1 << 34, 1 << 35); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rolv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 63, 1 << 32, 1 << 32); + let b = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_maskz_rolv_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_rolv_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(1 << 32, 1 << 0, 1 << 34, 1 << 35); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rolv_epi64() { + let a = _mm_set_epi64x(1 << 32, 1 << 63); + let b = _mm_set_epi64x(0, 1); + let r = _mm_rolv_epi64(a, b); + let e = _mm_set_epi64x(1 << 32, 1 << 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rolv_epi64() { + let a = _mm_set_epi64x(1 << 32, 1 << 63); + let b = _mm_set_epi64x(0, 1); + let r = _mm_mask_rolv_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_rolv_epi64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(1 << 32, 1 << 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rolv_epi64() { + let a = _mm_set_epi64x(1 << 32, 1 << 63); + let b = _mm_set_epi64x(0, 1); + let r = _mm_maskz_rolv_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_rolv_epi64(0b00000011, a, b); + let e = _mm_set_epi64x(1 << 32, 1 << 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_rorv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 0, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let b = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_rorv_epi64(a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 1 << 63, - 1 << 30, - 1 << 29, - 1 << 28, - 1 << 27, - 1 << 26, - 1 << 25, + 1 << 32, 1 << 63, 1 << 30, 1 << 29, + 1 << 28, 1 << 27, 1 << 26, 1 << 25, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_rorv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 0, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let b = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_mask_rorv_epi64(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_rorv_epi64(a, 0b11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 1 << 63, - 1 << 30, - 1 << 29, - 1 << 28, - 1 << 27, - 1 << 26, - 1 << 25, + 1 << 32, 1 << 63, 1 << 30, 1 << 29, + 1 << 28, 1 << 27, 1 << 26, 1 << 25, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_rorv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 0, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 0, ); let b = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 2); let r = _mm512_maskz_rorv_epi64(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_rorv_epi64(0b00001111, a, b); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 28, 1 << 27, 1 << 26, 1 << 62); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_rorv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 0, 1 << 32, 1 << 32); + let b = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_rorv_epi64(a, b); + let e = _mm256_set_epi64x(1 << 32, 1 << 63, 1 << 30, 1 << 29); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_rorv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 0, 1 << 32, 1 << 32); + let b = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_mask_rorv_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_rorv_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(1 << 32, 1 << 63, 1 << 30, 1 << 29); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_rorv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 0, 1 << 32, 1 << 32); + let b = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_maskz_rorv_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_rorv_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(1 << 32, 1 << 63, 1 << 30, 1 << 29); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_rorv_epi64() { + let a = _mm_set_epi64x(1 << 32, 1 << 0); + let b = _mm_set_epi64x(0, 1); + let r = _mm_rorv_epi64(a, b); + let e = _mm_set_epi64x(1 << 32, 1 << 63); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_rorv_epi64() { + let a = _mm_set_epi64x(1 << 32, 1 << 0); + let b = _mm_set_epi64x(0, 1); + let r = _mm_mask_rorv_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_rorv_epi64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(1 << 32, 1 << 63); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_rorv_epi64() { + let a = _mm_set_epi64x(1 << 32, 1 << 0); + let b = _mm_set_epi64x(0, 1); + let r = _mm_maskz_rorv_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_rorv_epi64(0b00000011, a, b); + let e = _mm_set_epi64x(1 << 32, 1 << 63); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sllv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 63, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm512_set_epi64(0, 2, 2, 3, 4, 5, 6, 7); let r = _mm512_sllv_epi64(a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 0, - 1 << 34, - 1 << 35, - 1 << 36, - 1 << 37, - 1 << 38, - 1 << 39, + 1 << 32, 0, 1 << 34, 1 << 35, + 1 << 36, 1 << 37, 1 << 38, 1 << 39, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_sllv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 32, 1 << 63, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_mask_sllv_epi64(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_sllv_epi64(a, 0b11111111, a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 1 << 33, - 0, - 1 << 35, - 1 << 36, - 1 << 37, - 1 << 38, - 1 << 39, + 1 << 32, 1 << 33, 0, 1 << 35, + 1 << 36, 1 << 37, 1 << 38, 1 << 39, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_sllv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 63, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 63, ); let count = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 1); let r = _mm512_maskz_sllv_epi64(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_sllv_epi64(0b00001111, a, count); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 36, 1 << 37, 1 << 38, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sllv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 32, 1 << 63, 1 << 32); + let count = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_mask_sllv_epi64(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_sllv_epi64(a, 0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 32, 1 << 33, 0, 1 << 35); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sllv_epi64() { + let a = _mm256_set_epi64x(1 << 32, 1 << 32, 1 << 63, 1 << 32); + let count = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_maskz_sllv_epi64(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sllv_epi64(0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 32, 1 << 33, 0, 1 << 35); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sllv_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let count = _mm_set_epi64x(2, 3); + let r = _mm_mask_sllv_epi64(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_sllv_epi64(a, 0b00000011, a, count); + let e = _mm_set_epi64x(0, 1 << 35); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sllv_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let count = _mm_set_epi64x(2, 3); + let r = _mm_maskz_sllv_epi64(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sllv_epi64(0b00000011, a, count); + let e = _mm_set_epi64x(0, 1 << 35); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srlv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 0, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_srlv_epi64(a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 0, - 1 << 30, - 1 << 29, - 1 << 28, - 1 << 27, - 1 << 26, - 1 << 25, + 1 << 32, 0, 1 << 30, 1 << 29, + 1 << 28, 1 << 27, 1 << 26, 1 << 25, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_srlv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 32, 1 << 0, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_mask_srlv_epi64(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_srlv_epi64(a, 0b11111111, a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 32, - 0, - 1 << 30, - 1 << 29, - 1 << 28, - 1 << 27, - 1 << 26, - 1 << 25, + 1 << 32, 0, 1 << 30, 1 << 29, + 1 << 28, 1 << 27, 1 << 26, 1 << 25, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_srlv_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 0, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 0, ); let count = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); let r = _mm512_maskz_srlv_epi64(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srlv_epi64(0b00001111, a, count); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 28, 1 << 27, 1 << 26, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srlv_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm256_set1_epi64x(1); + let r = _mm256_mask_srlv_epi64(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_srlv_epi64(a, 0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srlv_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm256_set1_epi64x(1); + let r = _mm256_maskz_srlv_epi64(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srlv_epi64(0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srlv_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set1_epi64x(1); + let r = _mm_mask_srlv_epi64(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_srlv_epi64(a, 0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srlv_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set1_epi64x(1); + let r = _mm_maskz_srlv_epi64(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srlv_epi64(0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sll_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 63, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm_set_epi64x(0, 1); let r = _mm512_sll_epi64(a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, + 0, 1 << 33, 1 << 33, 1 << 33, + 1 << 33, 1 << 33, 1 << 33, 1 << 33, ); assert_eq_m512i(r, e); - let count = _mm_set_epi64x(1, 0); let r = _mm512_sll_epi64(a, count); assert_eq_m512i(r, a); @@ -4600,133 +8619,177 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_sll_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 63, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 63, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm_set_epi64x(0, 1); let r = _mm512_mask_sll_epi64(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_sll_epi64(a, 0b11111111, a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, - 1 << 33, + 0, 1 << 33, 1 << 33, 1 << 33, + 1 << 33, 1 << 33, 1 << 33, 1 << 33, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_sll_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 63, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 63, ); let count = _mm_set_epi64x(0, 1); let r = _mm512_maskz_sll_epi64(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_sll_epi64(0b00001111, a, count); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 33, 1 << 33, 1 << 33, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sll_epi64() { + let a = _mm256_set_epi64x(1 << 63, 1 << 32, 1 << 32, 1 << 32); + let count = _mm_set_epi64x(0, 1); + let r = _mm256_mask_sll_epi64(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_sll_epi64(a, 0b00001111, a, count); + let e = _mm256_set_epi64x(0, 1 << 33, 1 << 33, 1 << 33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sll_epi64() { + let a = _mm256_set_epi64x(1 << 63, 1 << 32, 1 << 32, 1 << 32); + let count = _mm_set_epi64x(0, 1); + let r = _mm256_maskz_sll_epi64(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sll_epi64(0b00001111, a, count); + let e = _mm256_set_epi64x(0, 1 << 33, 1 << 33, 1 << 33); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sll_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let count = _mm_set_epi64x(0, 1); + let r = _mm_mask_sll_epi64(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_sll_epi64(a, 0b00000011, a, count); + let e = _mm_set_epi64x(0, 1 << 33); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sll_epi64() { + let a = _mm_set_epi64x(1 << 63, 1 << 32); + let count = _mm_set_epi64x(0, 1); + let r = _mm_maskz_sll_epi64(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sll_epi64(0b00000011, a, count); + let e = _mm_set_epi64x(0, 1 << 33); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srl_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 0, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm_set_epi64x(0, 1); let r = _mm512_srl_epi64(a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, + 0, 1 << 31, 1 << 31, 1 << 31, + 1 << 31, 1 << 31, 1 << 31, 1 << 31, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_srl_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 0, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, + 1 << 0, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, ); let count = _mm_set_epi64x(0, 1); let r = _mm512_mask_srl_epi64(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_srl_epi64(a, 0b11111111, a, count); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, - 1 << 31, + 0, 1 << 31, 1 << 31, 1 << 31, + 1 << 31, 1 << 31, 1 << 31, 1 << 31, ); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_srl_epi64() { + #[rustfmt::skip] let a = _mm512_set_epi64( - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 32, - 1 << 0, + 1 << 32, 1 << 32, 1 << 32, 1 << 32, + 1 << 32, 1 << 32, 1 << 32, 1 << 0, ); let count = _mm_set_epi64x(0, 1); let r = _mm512_maskz_srl_epi64(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srl_epi64(0b00001111, a, count); let e = _mm512_set_epi64(0, 0, 0, 0, 1 << 31, 1 << 31, 1 << 31, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srl_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm256_mask_srl_epi64(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_srl_epi64(a, 0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srl_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm256_maskz_srl_epi64(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srl_epi64(0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srl_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm_mask_srl_epi64(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_srl_epi64(a, 0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srl_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm_maskz_srl_epi64(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srl_epi64(0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_sra_epi64() { let a = _mm512_set_epi64(1, -8, 0, 0, 0, 0, 15, -16); @@ -4742,7 +8805,6 @@ mod tests { let count = _mm_set_epi64x(0, 2); let r = _mm512_mask_sra_epi64(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_sra_epi64(a, 0b11111111, a, count); let e = _mm512_set_epi64(0, -2, 0, 0, 0, 0, 3, -4); assert_eq_m512i(r, e); @@ -4754,12 +8816,73 @@ mod tests { let count = _mm_set_epi64x(0, 2); let r = _mm512_maskz_sra_epi64(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_sra_epi64(0b00001111, a, count); let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 3, -4); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_sra_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm256_sra_epi64(a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_sra_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm256_mask_sra_epi64(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_sra_epi64(a, 0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_sra_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm256_maskz_sra_epi64(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_sra_epi64(0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_sra_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm_sra_epi64(a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_sra_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm_mask_sra_epi64(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_sra_epi64(a, 0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_sra_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set_epi64x(0, 1); + let r = _mm_maskz_sra_epi64(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_sra_epi64(0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srav_epi64() { let a = _mm512_set_epi64(1, -8, 0, 0, 0, 0, 15, -16); @@ -4775,7 +8898,6 @@ mod tests { let count = _mm512_set_epi64(2, 2, 0, 0, 0, 0, 2, 1); let r = _mm512_mask_srav_epi64(a, 0, a, count); assert_eq_m512i(r, a); - let r = _mm512_mask_srav_epi64(a, 0b11111111, a, count); let e = _mm512_set_epi64(0, -2, 0, 0, 0, 0, 3, -8); assert_eq_m512i(r, e); @@ -4787,12 +8909,73 @@ mod tests { let count = _mm512_set_epi64(2, 2, 0, 0, 0, 0, 2, 1); let r = _mm512_maskz_srav_epi64(0, a, count); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srav_epi64(0b00001111, a, count); let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 3, -8); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_srav_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm256_set1_epi64x(1); + let r = _mm256_srav_epi64(a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srav_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm256_set1_epi64x(1); + let r = _mm256_mask_srav_epi64(a, 0, a, count); + assert_eq_m256i(r, a); + let r = _mm256_mask_srav_epi64(a, 0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srav_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let count = _mm256_set1_epi64x(1); + let r = _mm256_maskz_srav_epi64(0, a, count); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srav_epi64(0b00001111, a, count); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_srav_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set1_epi64x(1); + let r = _mm_srav_epi64(a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srav_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set1_epi64x(1); + let r = _mm_mask_srav_epi64(a, 0, a, count); + assert_eq_m128i(r, a); + let r = _mm_mask_srav_epi64(a, 0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srav_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let count = _mm_set1_epi64x(1); + let r = _mm_maskz_srav_epi64(0, a, count); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srav_epi64(0b00000011, a, count); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_srai_epi64() { let a = _mm512_set_epi64(1, -4, 15, 0, 0, 0, 0, -16); @@ -4806,7 +8989,6 @@ mod tests { let a = _mm512_set_epi64(1, -4, 15, 0, 0, 0, 0, -16); let r = _mm512_mask_srai_epi64(a, 0, a, 2); assert_eq_m512i(r, a); - let r = _mm512_mask_srai_epi64(a, 0b11111111, a, 2); let e = _mm512_set_epi64(0, -1, 3, 0, 0, 0, 0, -4); assert_eq_m512i(r, e); @@ -4817,100 +8999,251 @@ mod tests { let a = _mm512_set_epi64(1, -4, 15, 0, 0, 0, 0, -16); let r = _mm512_maskz_srai_epi64(0, a, 2); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_srai_epi64(0b00001111, a, 2); let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, -4); assert_eq_m512i(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_permute_pd() { - let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let r = _mm512_permute_pd(a, 1); - let e = _mm512_set_pd(1., 1., 3., 3., 5., 5., 7., 7.); - assert_eq_m512d(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_srai_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let r = _mm256_srai_epi64(a, 1); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_srai_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let r = _mm256_mask_srai_epi64(a, 0, a, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_srai_epi64(a, 0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_srai_epi64() { + let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); + let r = _mm256_maskz_srai_epi64(0, a, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_srai_epi64(0b00001111, a, 1); + let e = _mm256_set_epi64x(1 << 4, 0, 0, 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_srai_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let r = _mm_srai_epi64(a, 1); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_srai_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let r = _mm_mask_srai_epi64(a, 0, a, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_srai_epi64(a, 0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_srai_epi64() { + let a = _mm_set_epi64x(1 << 5, 0); + let r = _mm_maskz_srai_epi64(0, a, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_srai_epi64(0b00000011, a, 1); + let e = _mm_set_epi64x(1 << 4, 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_permute_pd() { + let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_permute_pd(a, 0b1111); + let e = _mm512_setr_pd(1., 1., 3., 3., 5., 5., 7., 7.); + assert_eq_m512d(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_permute_pd() { - let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let r = _mm512_mask_permute_pd(a, 0, a, 1); + let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_mask_permute_pd(a, 0, a, 0b1111); assert_eq_m512d(r, a); - let r = _mm512_mask_permute_pd(a, 0b11111111, a, 1); - let e = _mm512_set_pd(1., 1., 3., 3., 5., 5., 7., 7.); + let r = _mm512_mask_permute_pd(a, 0b11111111, a, 0b1111); + let e = _mm512_setr_pd(1., 1., 3., 3., 5., 5., 7., 7.); assert_eq_m512d(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_permute_pd() { - let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let r = _mm512_maskz_permute_pd(0, a, 1); + let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_maskz_permute_pd(0, a, 0b1111); assert_eq_m512d(r, _mm512_setzero_pd()); - let r = _mm512_maskz_permute_pd(0b00001111, a, 1); - let e = _mm512_set_pd(0., 0., 0., 0., 5., 5., 7., 7.); + let r = _mm512_maskz_permute_pd(0b11111111, a, 0b1111); + let e = _mm512_setr_pd(1., 1., 3., 3., 5., 5., 7., 7.); assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permute_pd() { + let a = _mm256_set_pd(3., 2., 1., 0.); + let r = _mm256_mask_permute_pd(a, 0, a, 0b1111); + assert_eq_m256d(r, a); + let r = _mm256_mask_permute_pd(a, 0b00001111, a, 0b1111); + let e = _mm256_set_pd(3., 3., 1., 1.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permute_pd() { + let a = _mm256_set_pd(3., 2., 1., 0.); + let r = _mm256_maskz_permute_pd(0, a, 0b1111); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_permute_pd(0b00001111, a, 0b1111); + let e = _mm256_set_pd(3., 3., 1., 1.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permute_pd() { + let a = _mm_set_pd(1., 0.); + let r = _mm_mask_permute_pd(a, 0, a, 0b1111); + assert_eq_m128d(r, a); + let r = _mm_mask_permute_pd(a, 0b00000011, a, 0b1111); + let e = _mm_set_pd(1., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permute_pd() { + let a = _mm_set_pd(1., 0.); + let r = _mm_maskz_permute_pd(0, a, 0b1111); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_permute_pd(0b00000011, a, 0b1111); + let e = _mm_set_pd(1., 1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutex_epi64() { - let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); - let r = _mm512_permutex_epi64(a, 1); - let e = _mm512_set_epi64(6, 6, 6, 6, 6, 6, 6, 6); + let a = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm512_permutex_epi64(a, 0b11111111); + let e = _mm512_setr_epi64(3, 3, 3, 3, 7, 7, 7, 7); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_permutex_epi64() { - let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); - let r = _mm512_mask_permutex_epi64(a, 0, a, 1); + let a = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm512_mask_permutex_epi64(a, 0, a, 0b11111111); assert_eq_m512i(r, a); - let r = _mm512_mask_permutex_epi64(a, 0b11111111, a, 1); - let e = _mm512_set_epi64(6, 6, 6, 6, 6, 6, 6, 6); + let r = _mm512_mask_permutex_epi64(a, 0b11111111, a, 0b11111111); + let e = _mm512_setr_epi64(3, 3, 3, 3, 7, 7, 7, 7); assert_eq_m512i(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_permutex_epi64() { - let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); - let r = _mm512_maskz_permutex_epi64(0, a, 1); + let a = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm512_maskz_permutex_epi64(0, a, 0b11111111); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_permutex_epi64(0b00001111, a, 1); - let e = _mm512_set_epi64(0, 0, 0, 0, 6, 6, 6, 6); + let r = _mm512_maskz_permutex_epi64(0b11111111, a, 0b11111111); + let e = _mm512_setr_epi64(3, 3, 3, 3, 7, 7, 7, 7); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutex_epi64() { + let a = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_permutex_epi64(a, 0b11111111); + let e = _mm256_set_epi64x(3, 3, 3, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutex_epi64() { + let a = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_mask_permutex_epi64(a, 0, a, 0b11111111); + assert_eq_m256i(r, a); + let r = _mm256_mask_permutex_epi64(a, 0b00001111, a, 0b11111111); + let e = _mm256_set_epi64x(3, 3, 3, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm256_maskz_permutex_epi64() { + let a = _mm256_set_epi64x(3, 2, 1, 0); + let r = _mm256_maskz_permutex_epi64(0, a, 0b11111111); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_permutex_epi64(0b00001111, a, 0b11111111); + let e = _mm256_set_epi64x(3, 3, 3, 3); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutex_pd() { - let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let r = _mm512_permutex_pd(a, 1); - let e = _mm512_set_pd(6., 6., 6., 6., 6., 6., 6., 6.); + let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_permutex_pd(a, 0b11111111); + let e = _mm512_setr_pd(3., 3., 3., 3., 7., 7., 7., 7.); assert_eq_m512d(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_permutex_pd() { - let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let r = _mm512_mask_permutex_pd(a, 0, a, 1); + let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_mask_permutex_pd(a, 0, a, 0b11111111); assert_eq_m512d(r, a); - let r = _mm512_mask_permutex_pd(a, 0b11111111, a, 1); - let e = _mm512_set_pd(6., 6., 6., 6., 6., 6., 6., 6.); + let r = _mm512_mask_permutex_pd(a, 0b11111111, a, 0b11111111); + let e = _mm512_setr_pd(3., 3., 3., 3., 7., 7., 7., 7.); assert_eq_m512d(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_permutex_pd() { - let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let r = _mm512_maskz_permutex_pd(0, a, 1); + let a = _mm512_setr_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_maskz_permutex_pd(0, a, 0b11111111); assert_eq_m512d(r, _mm512_setzero_pd()); - let r = _mm512_maskz_permutex_pd(0b00001111, a, 1); - let e = _mm512_set_pd(0., 0., 0., 0., 6., 6., 6., 6.); + let r = _mm512_maskz_permutex_pd(0b11111111, a, 0b11111111); + let e = _mm512_setr_pd(3., 3., 3., 3., 7., 7., 7., 7.); assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutex_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_permutex_pd(a, 0b11111111); + let e = _mm256_set_pd(0., 0., 0., 0.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutex_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_mask_permutex_pd(a, 0, a, 0b11111111); + assert_eq_m256d(r, a); + let r = _mm256_mask_permutex_pd(a, 0b00001111, a, 0b11111111); + let e = _mm256_set_pd(0., 0., 0., 0.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutex_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_maskz_permutex_pd(0, a, 0b11111111); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_permutex_pd(0b00001111, a, 0b11111111); + let e = _mm256_set_pd(0., 0., 0., 0.); + assert_eq_m256d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutevar_pd() { let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let b = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(0b1); let r = _mm512_permutevar_pd(a, b); let e = _mm512_set_pd(1., 1., 3., 3., 5., 5., 7., 7.); assert_eq_m512d(r, e); @@ -4919,7 +9252,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_permutevar_pd() { let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let b = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(0b1); let r = _mm512_mask_permutevar_pd(a, 0, a, b); assert_eq_m512d(r, a); let r = _mm512_mask_permutevar_pd(a, 0b11111111, a, b); @@ -4930,7 +9263,7 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_permutevar_pd() { let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); - let b = _mm512_set1_epi64(1); + let b = _mm512_set1_epi64(0b1); let r = _mm512_maskz_permutevar_pd(0, a, b); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_permutevar_pd(0b00001111, a, b); @@ -4938,6 +9271,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutevar_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let b = _mm256_set1_epi64x(0b1); + let r = _mm256_mask_permutevar_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_permutevar_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(1., 1., 3., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutevar_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let b = _mm256_set1_epi64x(0b1); + let r = _mm256_maskz_permutevar_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_permutevar_pd(0b00001111, a, b); + let e = _mm256_set_pd(1., 1., 3., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permutevar_pd() { + let a = _mm_set_pd(0., 1.); + let b = _mm_set1_epi64x(0b1); + let r = _mm_mask_permutevar_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_permutevar_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(1., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permutevar_pd() { + let a = _mm_set_pd(0., 1.); + let b = _mm_set1_epi64x(0b1); + let r = _mm_maskz_permutevar_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_permutevar_pd(0b00000011, a, b); + let e = _mm_set_pd(1., 1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutexvar_epi64() { let idx = _mm512_set1_epi64(1); @@ -4969,6 +9346,37 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutexvar_epi64() { + let idx = _mm256_set1_epi64x(1); + let a = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_permutexvar_epi64(idx, a); + let e = _mm256_set1_epi64x(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutexvar_epi64() { + let idx = _mm256_set1_epi64x(1); + let a = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_mask_permutexvar_epi64(a, 0, idx, a); + assert_eq_m256i(r, a); + let r = _mm256_mask_permutexvar_epi64(a, 0b00001111, idx, a); + let e = _mm256_set1_epi64x(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutexvar_epi64() { + let idx = _mm256_set1_epi64x(1); + let a = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_maskz_permutexvar_epi64(0, idx, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_permutexvar_epi64(0b00001111, idx, a); + let e = _mm256_set1_epi64x(2); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutexvar_pd() { let idx = _mm512_set1_epi64(1); @@ -5000,6 +9408,37 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutexvar_pd() { + let idx = _mm256_set1_epi64x(1); + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_permutexvar_pd(idx, a); + let e = _mm256_set1_pd(2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutexvar_pd() { + let idx = _mm256_set1_epi64x(1); + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_mask_permutexvar_pd(a, 0, idx, a); + assert_eq_m256d(r, a); + let r = _mm256_mask_permutexvar_pd(a, 0b00001111, idx, a); + let e = _mm256_set1_pd(2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutexvar_pd() { + let idx = _mm256_set1_epi64x(1); + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_maskz_permutexvar_pd(0, idx, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_permutexvar_pd(0b00001111, idx, a); + let e = _mm256_set1_pd(2.); + assert_eq_m256d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutex2var_epi64() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); @@ -5046,6 +9485,98 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutex2var_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_epi64x(100); + let r = _mm256_permutex2var_epi64(a, idx, b); + let e = _mm256_set_epi64x(2, 100, 1, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutex2var_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_epi64x(100); + let r = _mm256_mask_permutex2var_epi64(a, 0, idx, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_permutex2var_epi64(a, 0b00001111, idx, b); + let e = _mm256_set_epi64x(2, 100, 1, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutex2var_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_epi64x(100); + let r = _mm256_maskz_permutex2var_epi64(0, a, idx, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_permutex2var_epi64(0b00001111, a, idx, b); + let e = _mm256_set_epi64x(2, 100, 1, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask2_permutex2var_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_epi64x(100); + let r = _mm256_mask2_permutex2var_epi64(a, idx, 0, b); + assert_eq_m256i(r, idx); + let r = _mm256_mask2_permutex2var_epi64(a, idx, 0b00001111, b); + let e = _mm256_set_epi64x(2, 100, 1, 100); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_permutex2var_epi64() { + let a = _mm_set_epi64x(0, 1); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_epi64x(100); + let r = _mm_permutex2var_epi64(a, idx, b); + let e = _mm_set_epi64x(0, 100); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permutex2var_epi64() { + let a = _mm_set_epi64x(0, 1); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_epi64x(100); + let r = _mm_mask_permutex2var_epi64(a, 0, idx, b); + assert_eq_m128i(r, a); + let r = _mm_mask_permutex2var_epi64(a, 0b00000011, idx, b); + let e = _mm_set_epi64x(0, 100); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permutex2var_epi64() { + let a = _mm_set_epi64x(0, 1); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_epi64x(100); + let r = _mm_maskz_permutex2var_epi64(0, a, idx, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_permutex2var_epi64(0b00000011, a, idx, b); + let e = _mm_set_epi64x(0, 100); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask2_permutex2var_epi64() { + let a = _mm_set_epi64x(0, 1); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_epi64x(100); + let r = _mm_mask2_permutex2var_epi64(a, idx, 0, b); + assert_eq_m128i(r, idx); + let r = _mm_mask2_permutex2var_epi64(a, idx, 0b00000011, b); + let e = _mm_set_epi64x(0, 100); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_permutex2var_pd() { let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); @@ -5086,12 +9617,104 @@ mod tests { let idx = _mm512_set_epi64(1, 1 << 3, 2, 1 << 3, 3, 1 << 3, 4, 1 << 3); let b = _mm512_set1_pd(100.); let r = _mm512_mask2_permutex2var_pd(a, idx, 0, b); - assert_eq_m512d(r, _mm512_setzero_pd()); - let r = _mm512_mask2_permutex2var_pd(a, idx, 0b00001111, b); - let e = _mm512_set_pd(0., 0., 0., 0., 4., 100., 3., 100.); + assert_eq_m512d(r, _mm512_castsi512_pd(idx)); + let r = _mm512_mask2_permutex2var_pd(a, idx, 0b11111111, b); + let e = _mm512_set_pd(6., 100., 5., 100., 4., 100., 3., 100.); assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_permutex2var_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_pd(100.); + let r = _mm256_permutex2var_pd(a, idx, b); + let e = _mm256_set_pd(2., 100., 1., 100.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_permutex2var_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_pd(100.); + let r = _mm256_mask_permutex2var_pd(a, 0, idx, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_permutex2var_pd(a, 0b00001111, idx, b); + let e = _mm256_set_pd(2., 100., 1., 100.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_permutex2var_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_pd(100.); + let r = _mm256_maskz_permutex2var_pd(0, a, idx, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_permutex2var_pd(0b00001111, a, idx, b); + let e = _mm256_set_pd(2., 100., 1., 100.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask2_permutex2var_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let idx = _mm256_set_epi64x(1, 1 << 2, 2, 1 << 2); + let b = _mm256_set1_pd(100.); + let r = _mm256_mask2_permutex2var_pd(a, idx, 0, b); + assert_eq_m256d(r, _mm256_castsi256_pd(idx)); + let r = _mm256_mask2_permutex2var_pd(a, idx, 0b00001111, b); + let e = _mm256_set_pd(2., 100., 1., 100.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_permutex2var_pd() { + let a = _mm_set_pd(0., 1.); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_pd(100.); + let r = _mm_permutex2var_pd(a, idx, b); + let e = _mm_set_pd(0., 100.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_permutex2var_pd() { + let a = _mm_set_pd(0., 1.); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_pd(100.); + let r = _mm_mask_permutex2var_pd(a, 0, idx, b); + assert_eq_m128d(r, a); + let r = _mm_mask_permutex2var_pd(a, 0b00000011, idx, b); + let e = _mm_set_pd(0., 100.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_permutex2var_pd() { + let a = _mm_set_pd(0., 1.); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_pd(100.); + let r = _mm_maskz_permutex2var_pd(0, a, idx, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_permutex2var_pd(0b00000011, a, idx, b); + let e = _mm_set_pd(0., 100.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask2_permutex2var_pd() { + let a = _mm_set_pd(0., 1.); + let idx = _mm_set_epi64x(1, 1 << 1); + let b = _mm_set1_pd(100.); + let r = _mm_mask2_permutex2var_pd(a, idx, 0, b); + assert_eq_m128d(r, _mm_castsi128_pd(idx)); + let r = _mm_mask2_permutex2var_pd(a, idx, 0b00000011, b); + let e = _mm_set_pd(0., 100.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_shuffle_pd() { let a = _mm512_setr_pd(1., 4., 5., 8., 1., 4., 5., 8.); @@ -5149,6 +9772,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_shuffle_pd() { + let a = _mm256_set_pd(1., 4., 5., 8.); + let b = _mm256_set_pd(2., 3., 6., 7.); + let r = _mm256_mask_shuffle_pd(a, 0, a, b, 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); + assert_eq_m256d(r, a); + let r = _mm256_mask_shuffle_pd(a, 0b00001111, a, b, 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); + let e = _mm256_set_pd(2., 1., 6., 5.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_pd() { + let a = _mm256_set_pd(1., 4., 5., 8.); + let b = _mm256_set_pd(2., 3., 6., 7.); + let r = _mm256_maskz_shuffle_pd(0, a, b, 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_shuffle_pd(0b00001111, a, b, 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); + let e = _mm256_set_pd(2., 1., 6., 5.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_shuffle_pd() { + let a = _mm_set_pd(1., 4.); + let b = _mm_set_pd(2., 3.); + let r = _mm_mask_shuffle_pd(a, 0, a, b, 1 << 0 | 1 << 1); + assert_eq_m128d(r, a); + let r = _mm_mask_shuffle_pd(a, 0b00000011, a, b, 1 << 0 | 1 << 1); + let e = _mm_set_pd(2., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_shuffle_pd() { + let a = _mm_set_pd(1., 4.); + let b = _mm_set_pd(2., 3.); + let r = _mm_maskz_shuffle_pd(0, a, b, 1 << 0 | 1 << 1); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_shuffle_pd(0b00000011, a, b, 1 << 0 | 1 << 1); + let e = _mm_set_pd(2., 1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_shuffle_i64x2() { let a = _mm512_setr_epi64(1, 4, 5, 8, 9, 12, 13, 16); @@ -5180,6 +9847,37 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_shuffle_i64x2() { + let a = _mm256_set_epi64x(1, 4, 5, 8); + let b = _mm256_set_epi64x(2, 3, 6, 7); + let r = _mm256_shuffle_i64x2(a, b, 0b00); + let e = _mm256_set_epi64x(6, 7, 5, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_shuffle_i64x2() { + let a = _mm256_set_epi64x(1, 4, 5, 8); + let b = _mm256_set_epi64x(2, 3, 6, 7); + let r = _mm256_mask_shuffle_i64x2(a, 0, a, b, 0b00); + assert_eq_m256i(r, a); + let r = _mm256_mask_shuffle_i64x2(a, 0b00001111, a, b, 0b00); + let e = _mm256_set_epi64x(6, 7, 5, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_i64x2() { + let a = _mm256_set_epi64x(1, 4, 5, 8); + let b = _mm256_set_epi64x(2, 3, 6, 7); + let r = _mm256_maskz_shuffle_i64x2(0, a, b, 0b00); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_shuffle_i64x2(0b00001111, a, b, 0b00); + let e = _mm256_set_epi64x(6, 7, 5, 8); + assert_eq_m256i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_shuffle_f64x2() { let a = _mm512_setr_pd(1., 4., 5., 8., 9., 12., 13., 16.); @@ -5211,6 +9909,37 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_shuffle_f64x2() { + let a = _mm256_set_pd(1., 4., 5., 8.); + let b = _mm256_set_pd(2., 3., 6., 7.); + let r = _mm256_shuffle_f64x2(a, b, 0b00); + let e = _mm256_set_pd(6., 7., 5., 8.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_shuffle_f64x2() { + let a = _mm256_set_pd(1., 4., 5., 8.); + let b = _mm256_set_pd(2., 3., 6., 7.); + let r = _mm256_mask_shuffle_f64x2(a, 0, a, b, 0b00); + assert_eq_m256d(r, a); + let r = _mm256_mask_shuffle_f64x2(a, 0b00001111, a, b, 0b00); + let e = _mm256_set_pd(6., 7., 5., 8.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_shuffle_f64x2() { + let a = _mm256_set_pd(1., 4., 5., 8.); + let b = _mm256_set_pd(2., 3., 6., 7.); + let r = _mm256_maskz_shuffle_f64x2(0, a, b, 0b00); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_shuffle_f64x2(0b00001111, a, b, 0b00); + let e = _mm256_set_pd(6., 7., 5., 8.); + assert_eq_m256d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_movedup_pd() { let a = _mm512_setr_pd(1., 2., 3., 4., 5., 6., 7., 8.); @@ -5239,6 +9968,46 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_movedup_pd() { + let a = _mm256_set_pd(1., 2., 3., 4.); + let r = _mm256_mask_movedup_pd(a, 0, a); + assert_eq_m256d(r, a); + let r = _mm256_mask_movedup_pd(a, 0b00001111, a); + let e = _mm256_set_pd(2., 2., 4., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_movedup_pd() { + let a = _mm256_set_pd(1., 2., 3., 4.); + let r = _mm256_maskz_movedup_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_movedup_pd(0b00001111, a); + let e = _mm256_set_pd(2., 2., 4., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_movedup_pd() { + let a = _mm_set_pd(1., 2.); + let r = _mm_mask_movedup_pd(a, 0, a); + assert_eq_m128d(r, a); + let r = _mm_mask_movedup_pd(a, 0b00000011, a); + let e = _mm_set_pd(2., 2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_movedup_pd() { + let a = _mm_set_pd(1., 2.); + let r = _mm_maskz_movedup_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_movedup_pd(0b00000011, a); + let e = _mm_set_pd(2., 2.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_inserti64x4() { let a = _mm512_setr_epi64(1, 2, 3, 4, 5, 6, 7, 8); @@ -5466,9 +10235,51 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_broadcastq_epi64() { + let src = _mm256_set1_epi64x(18); + let a = _mm_set_epi64x(17, 18); + let r = _mm256_mask_broadcastq_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_broadcastq_epi64(src, 0b00001111, a); + let e = _mm256_set1_epi64x(18); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_broadcastq_epi64() { + let a = _mm_set_epi64x(17, 18); + let r = _mm256_maskz_broadcastq_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_broadcastq_epi64(0b00001111, a); + let e = _mm256_set1_epi64x(18); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_broadcastq_epi64() { + let src = _mm_set1_epi64x(18); + let a = _mm_set_epi64x(17, 18); + let r = _mm_mask_broadcastq_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_broadcastq_epi64(src, 0b00000011, a); + let e = _mm_set1_epi64x(18); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_broadcastq_epi64() { + let a = _mm_set_epi64x(17, 18); + let r = _mm_maskz_broadcastq_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_broadcastq_epi64(0b00000011, a); + let e = _mm_set1_epi64x(18); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_broadcastsd_pd() { - let a = _mm_setr_pd(17., 18.); + let a = _mm_set_pd(17., 18.); let r = _mm512_broadcastsd_pd(a); let e = _mm512_set1_pd(18.); assert_eq_m512d(r, e); @@ -5477,17 +10288,17 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_broadcastsd_pd() { let src = _mm512_set1_pd(18.); - let a = _mm_setr_pd(17., 18.); + let a = _mm_set_pd(17., 18.); let r = _mm512_mask_broadcastsd_pd(src, 0, a); assert_eq_m512d(r, src); - let r = _mm512_mask_broadcastsd_pd(src, 0b01111111, a); + let r = _mm512_mask_broadcastsd_pd(src, 0b11111111, a); let e = _mm512_set1_pd(18.); assert_eq_m512d(r, e); } #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_broadcastsd_pd() { - let a = _mm_setr_pd(17., 18.); + let a = _mm_set_pd(17., 18.); let r = _mm512_maskz_broadcastsd_pd(0, a); assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_broadcastsd_pd(0b00001111, a); @@ -5495,6 +10306,27 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_broadcastsd_pd() { + let src = _mm256_set1_pd(18.); + let a = _mm_set_pd(17., 18.); + let r = _mm256_mask_broadcastsd_pd(src, 0, a); + assert_eq_m256d(r, src); + let r = _mm256_mask_broadcastsd_pd(src, 0b00001111, a); + let e = _mm256_set1_pd(18.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_broadcastsd_pd() { + let a = _mm_set_pd(17., 18.); + let r = _mm256_maskz_broadcastsd_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_broadcastsd_pd(0b00001111, a); + let e = _mm256_set1_pd(18.); + assert_eq_m256d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_broadcast_i64x4() { let a = _mm256_set_epi64x(17, 18, 19, 20); @@ -5562,6 +10394,24 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_blend_epi64() { + let a = _mm256_set1_epi64x(1); + let b = _mm256_set1_epi64x(2); + let r = _mm256_mask_blend_epi64(0b00001111, a, b); + let e = _mm256_set1_epi64x(2); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_blend_epi64() { + let a = _mm_set1_epi64x(1); + let b = _mm_set1_epi64x(2); + let r = _mm_mask_blend_epi64(0b00000011, a, b); + let e = _mm_set1_epi64x(2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_blend_pd() { let a = _mm512_set1_pd(1.); @@ -5571,6 +10421,24 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_blend_pd() { + let a = _mm256_set1_pd(1.); + let b = _mm256_set1_pd(2.); + let r = _mm256_mask_blend_pd(0b00001111, a, b); + let e = _mm256_set1_pd(2.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_blend_pd() { + let a = _mm_set1_pd(1.); + let b = _mm_set1_pd(2.); + let r = _mm_mask_blend_pd(0b00000011, a, b); + let e = _mm_set1_pd(2.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpackhi_epi64() { let a = _mm512_set_epi64(1, 2, 3, 4, 5, 6, 7, 8); @@ -5602,6 +10470,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpackhi_epi64() { + let a = _mm256_set_epi64x(1, 2, 3, 4); + let b = _mm256_set_epi64x(17, 18, 19, 20); + let r = _mm256_mask_unpackhi_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_unpackhi_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(17, 1, 19, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpackhi_epi64() { + let a = _mm256_set_epi64x(1, 2, 3, 4); + let b = _mm256_set_epi64x(17, 18, 19, 20); + let r = _mm256_maskz_unpackhi_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_unpackhi_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(17, 1, 19, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpackhi_epi64() { + let a = _mm_set_epi64x(1, 2); + let b = _mm_set_epi64x(17, 18); + let r = _mm_mask_unpackhi_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_unpackhi_epi64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(17, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpackhi_epi64() { + let a = _mm_set_epi64x(1, 2); + let b = _mm_set_epi64x(17, 18); + let r = _mm_maskz_unpackhi_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_unpackhi_epi64(0b00000011, a, b); + let e = _mm_set_epi64x(17, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpackhi_pd() { let a = _mm512_set_pd(1., 2., 3., 4., 5., 6., 7., 8.); @@ -5633,6 +10545,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpackhi_pd() { + let a = _mm256_set_pd(1., 2., 3., 4.); + let b = _mm256_set_pd(17., 18., 19., 20.); + let r = _mm256_mask_unpackhi_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_unpackhi_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(17., 1., 19., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpackhi_pd() { + let a = _mm256_set_pd(1., 2., 3., 4.); + let b = _mm256_set_pd(17., 18., 19., 20.); + let r = _mm256_maskz_unpackhi_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_unpackhi_pd(0b00001111, a, b); + let e = _mm256_set_pd(17., 1., 19., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpackhi_pd() { + let a = _mm_set_pd(1., 2.); + let b = _mm_set_pd(17., 18.); + let r = _mm_mask_unpackhi_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_unpackhi_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(17., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpackhi_pd() { + let a = _mm_set_pd(1., 2.); + let b = _mm_set_pd(17., 18.); + let r = _mm_maskz_unpackhi_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_unpackhi_pd(0b00000011, a, b); + let e = _mm_set_pd(17., 1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpacklo_epi64() { let a = _mm512_set_epi64(1, 2, 3, 4, 5, 6, 7, 8); @@ -5664,6 +10620,50 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpacklo_epi64() { + let a = _mm256_set_epi64x(1, 2, 3, 4); + let b = _mm256_set_epi64x(17, 18, 19, 20); + let r = _mm256_mask_unpacklo_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_unpacklo_epi64(a, 0b00001111, a, b); + let e = _mm256_set_epi64x(18, 2, 20, 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpacklo_epi64() { + let a = _mm256_set_epi64x(1, 2, 3, 4); + let b = _mm256_set_epi64x(17, 18, 19, 20); + let r = _mm256_maskz_unpacklo_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_unpacklo_epi64(0b00001111, a, b); + let e = _mm256_set_epi64x(18, 2, 20, 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpacklo_epi64() { + let a = _mm_set_epi64x(1, 2); + let b = _mm_set_epi64x(17, 18); + let r = _mm_mask_unpacklo_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_unpacklo_epi64(a, 0b00000011, a, b); + let e = _mm_set_epi64x(18, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpacklo_epi64() { + let a = _mm_set_epi64x(1, 2); + let b = _mm_set_epi64x(17, 18); + let r = _mm_maskz_unpacklo_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_unpacklo_epi64(0b00000011, a, b); + let e = _mm_set_epi64x(18, 2); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_unpacklo_pd() { let a = _mm512_set_pd(1., 2., 3., 4., 5., 6., 7., 8.); @@ -5695,6 +10695,50 @@ mod tests { assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_unpacklo_pd() { + let a = _mm256_set_pd(1., 2., 3., 4.); + let b = _mm256_set_pd(17., 18., 19., 20.); + let r = _mm256_mask_unpacklo_pd(a, 0, a, b); + assert_eq_m256d(r, a); + let r = _mm256_mask_unpacklo_pd(a, 0b00001111, a, b); + let e = _mm256_set_pd(18., 2., 20., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_unpacklo_pd() { + let a = _mm256_set_pd(1., 2., 3., 4.); + let b = _mm256_set_pd(17., 18., 19., 20.); + let r = _mm256_maskz_unpacklo_pd(0, a, b); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_unpacklo_pd(0b00001111, a, b); + let e = _mm256_set_pd(18., 2., 20., 4.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_unpacklo_pd() { + let a = _mm_set_pd(1., 2.); + let b = _mm_set_pd(17., 18.); + let r = _mm_mask_unpacklo_pd(a, 0, a, b); + assert_eq_m128d(r, a); + let r = _mm_mask_unpacklo_pd(a, 0b00000011, a, b); + let e = _mm_set_pd(18., 2.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_unpacklo_pd() { + let a = _mm_set_pd(1., 2.); + let b = _mm_set_pd(17., 18.); + let r = _mm_maskz_unpacklo_pd(0, a, b); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_unpacklo_pd(0b00000011, a, b); + let e = _mm_set_pd(18., 2.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_alignr_epi64() { let a = _mm512_set_epi64(8, 7, 6, 5, 4, 3, 2, 1); @@ -5730,6 +10774,71 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_alignr_epi64() { + let a = _mm256_set_epi64x(4, 3, 2, 1); + let b = _mm256_set_epi64x(8, 7, 6, 5); + let r = _mm256_alignr_epi64(a, b, 0); + let e = _mm256_set_epi64x(8, 7, 6, 5); + assert_eq_m256i(r, e); + let r = _mm256_alignr_epi64(a, b, 6); + let e = _mm256_set_epi64x(6, 5, 4, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_alignr_epi64() { + let a = _mm256_set_epi64x(4, 3, 2, 1); + let b = _mm256_set_epi64x(8, 7, 6, 5); + let r = _mm256_mask_alignr_epi64(a, 0, a, b, 1); + assert_eq_m256i(r, a); + let r = _mm256_mask_alignr_epi64(a, 0b00001111, a, b, 0); + let e = _mm256_set_epi64x(8, 7, 6, 5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_alignr_epi64() { + let a = _mm256_set_epi64x(4, 3, 2, 1); + let b = _mm256_set_epi64x(8, 7, 6, 5); + let r = _mm256_maskz_alignr_epi64(0, a, b, 1); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_alignr_epi64(0b00001111, a, b, 0); + let e = _mm256_set_epi64x(8, 7, 6, 5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_alignr_epi64() { + let a = _mm_set_epi64x(2, 1); + let b = _mm_set_epi64x(4, 3); + let r = _mm_alignr_epi64(a, b, 0); + let e = _mm_set_epi64x(4, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_alignr_epi64() { + let a = _mm_set_epi64x(2, 1); + let b = _mm_set_epi64x(4, 3); + let r = _mm_mask_alignr_epi64(a, 0, a, b, 1); + assert_eq_m128i(r, a); + let r = _mm_mask_alignr_epi64(a, 0b00000011, a, b, 0); + let e = _mm_set_epi64x(4, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_alignr_epi64() { + let a = _mm_set_epi64x(2, 1); + let b = _mm_set_epi64x(4, 3); + let r = _mm_maskz_alignr_epi64(0, a, b, 1); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_alignr_epi64(0b00000011, a, b, 0); + let e = _mm_set_epi64x(4, 3); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_and_epi64() { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); @@ -5744,9 +10853,7 @@ mod tests { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_mask_and_epi64(a, 0, a, b); - let e = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); - assert_eq_m512i(r, e); - + assert_eq_m512i(r, a); let r = _mm512_mask_and_epi64(a, 0b01111111, a, b); let e = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); assert_eq_m512i(r, e); @@ -5757,14 +10864,56 @@ mod tests { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_maskz_and_epi64(0, a, b); - let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, 0); - assert_eq_m512i(r, e); - + assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_and_epi64(0b00001111, a, b); let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_and_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 0); + let r = _mm256_mask_and_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_and_epi64(a, 0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_and_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 0); + let r = _mm256_maskz_and_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_and_epi64(0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 0); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_and_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 0); + let r = _mm_mask_and_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_and_epi64(a, 0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 0); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_and_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 0); + let r = _mm_maskz_and_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_and_epi64(0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 0); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_and_si512() { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); @@ -5779,15 +10928,10 @@ mod tests { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_or_epi64(a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 0 | 1 << 13 | 1 << 15, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 2 | 1 << 3, + 1 << 0 | 1 << 13 | 1 << 15, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3, ); assert_eq_m512i(r, e); } @@ -5797,19 +10941,12 @@ mod tests { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_mask_or_epi64(a, 0, a, b); - let e = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); - assert_eq_m512i(r, e); - + assert_eq_m512i(r, a); let r = _mm512_mask_or_epi64(a, 0b11111111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 0 | 1 << 13 | 1 << 15, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 2 | 1 << 3, + 1 << 0 | 1 << 13 | 1 << 15, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3, ); assert_eq_m512i(r, e); } @@ -5819,28 +10956,83 @@ mod tests { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_maskz_or_epi64(0, a, b); - let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, 0); - assert_eq_m512i(r, e); - + assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_or_epi64(0b00001111, a, b); let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_or_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 13); + let r = _mm256_or_epi64(a, b); + let e = _mm256_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_or_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 13); + let r = _mm256_mask_or_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_or_epi64(a, 0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_or_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 13); + let r = _mm256_maskz_or_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_or_epi64(0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_or_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 13); + let r = _mm_or_epi64(a, b); + let e = _mm_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_or_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 13); + let r = _mm_mask_or_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_or_epi64(a, 0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_or_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 13); + let r = _mm_maskz_or_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_or_epi64(0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_or_si512() { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_or_epi64(a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 1 << 0 | 1 << 13 | 1 << 15, - 0, - 0, - 0, - 0, - 0, - 0, - 1 << 1 | 1 << 2 | 1 << 3, + 1 << 0 | 1 << 13 | 1 << 15, 0, 0, 0, + 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3, ); assert_eq_m512i(r, e); } @@ -5859,9 +11051,7 @@ mod tests { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_mask_xor_epi64(a, 0, a, b); - let e = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); - assert_eq_m512i(r, e); - + assert_eq_m512i(r, a); let r = _mm512_mask_xor_epi64(a, 0b11111111, a, b); let e = _mm512_set_epi64(1 << 0 | 1 << 13 | 1 << 15, 0, 0, 0, 0, 0, 0, 0); assert_eq_m512i(r, e); @@ -5872,14 +11062,74 @@ mod tests { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let b = _mm512_set_epi64(1 << 13, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); let r = _mm512_maskz_xor_epi64(0, a, b); - let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, 0); - assert_eq_m512i(r, e); - + assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_xor_epi64(0b00001111, a, b); let e = _mm512_set_epi64(0, 0, 0, 0, 0, 0, 0, 0); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_xor_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 13); + let r = _mm256_xor_epi64(a, b); + let e = _mm256_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_xor_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 13); + let r = _mm256_mask_xor_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_xor_epi64(a, 0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_xor_epi64() { + let a = _mm256_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm256_set1_epi64x(1 << 13); + let r = _mm256_maskz_xor_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_xor_epi64(0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_xor_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 13); + let r = _mm_xor_epi64(a, b); + let e = _mm_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_xor_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 13); + let r = _mm_mask_xor_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_xor_epi64(a, 0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_xor_epi64() { + let a = _mm_set1_epi64x(1 << 0 | 1 << 15); + let b = _mm_set1_epi64x(1 << 13); + let r = _mm_maskz_xor_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_xor_epi64(0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 0 | 1 << 13 | 1 << 15); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_xor_si512() { let a = _mm512_set_epi64(1 << 0 | 1 << 15, 0, 0, 0, 0, 0, 0, 1 << 1 | 1 << 2 | 1 << 3); @@ -5904,7 +11154,6 @@ mod tests { let b = _mm512_set1_epi64(1 << 3 | 1 << 4); let r = _mm512_mask_andnot_epi64(a, 0, a, b); assert_eq_m512i(r, a); - let r = _mm512_mask_andnot_epi64(a, 0b11111111, a, b); let e = _mm512_set1_epi64(1 << 3 | 1 << 4); assert_eq_m512i(r, e); @@ -5916,21 +11165,59 @@ mod tests { let b = _mm512_set1_epi64(1 << 3 | 1 << 4); let r = _mm512_maskz_andnot_epi64(0, a, b); assert_eq_m512i(r, _mm512_setzero_si512()); - let r = _mm512_maskz_andnot_epi64(0b00001111, a, b); + #[rustfmt::skip] let e = _mm512_set_epi64( - 0, - 0, - 0, - 0, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, - 1 << 3 | 1 << 4, + 0, 0, 0, 0, + 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, 1 << 3 | 1 << 4, ); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_andnot_epi64() { + let a = _mm256_set1_epi64x(1 << 1 | 1 << 2); + let b = _mm256_set1_epi64x(1 << 3 | 1 << 4); + let r = _mm256_mask_andnot_epi64(a, 0, a, b); + assert_eq_m256i(r, a); + let r = _mm256_mask_andnot_epi64(a, 0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 3 | 1 << 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_andnot_epi64() { + let a = _mm256_set1_epi64x(1 << 1 | 1 << 2); + let b = _mm256_set1_epi64x(1 << 3 | 1 << 4); + let r = _mm256_maskz_andnot_epi64(0, a, b); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_andnot_epi64(0b00001111, a, b); + let e = _mm256_set1_epi64x(1 << 3 | 1 << 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_andnot_epi64() { + let a = _mm_set1_epi64x(1 << 1 | 1 << 2); + let b = _mm_set1_epi64x(1 << 3 | 1 << 4); + let r = _mm_mask_andnot_epi64(a, 0, a, b); + assert_eq_m128i(r, a); + let r = _mm_mask_andnot_epi64(a, 0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 3 | 1 << 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_andnot_epi64() { + let a = _mm_set1_epi64x(1 << 1 | 1 << 2); + let b = _mm_set1_epi64x(1 << 3 | 1 << 4); + let r = _mm_maskz_andnot_epi64(0, a, b); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_andnot_epi64(0b00000011, a, b); + let e = _mm_set1_epi64x(1 << 3 | 1 << 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_andnot_si512() { let a = _mm512_set1_epi64(0); @@ -6170,6 +11457,8 @@ mod tests { unsafe fn test_mm512_mask_compress_epi64() { let src = _mm512_set1_epi64(200); let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm512_mask_compress_epi64(src, 0, a); + assert_eq_m512i(r, src); let r = _mm512_mask_compress_epi64(src, 0b01010101, a); let e = _mm512_set_epi64(200, 200, 200, 200, 1, 3, 5, 7); assert_eq_m512i(r, e); @@ -6178,15 +11467,61 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_compress_epi64() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm512_maskz_compress_epi64(0, a); + assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_compress_epi64(0b01010101, a); let e = _mm512_set_epi64(0, 0, 0, 0, 1, 3, 5, 7); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_compress_epi64() { + let src = _mm256_set1_epi64x(200); + let a = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_mask_compress_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_compress_epi64(src, 0b00000101, a); + let e = _mm256_set_epi64x(200, 200, 1, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_compress_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_maskz_compress_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_compress_epi64(0b00000101, a); + let e = _mm256_set_epi64x(0, 0, 1, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_compress_epi64() { + let src = _mm_set1_epi64x(200); + let a = _mm_set_epi64x(0, 1); + let r = _mm_mask_compress_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_compress_epi64(src, 0b00000001, a); + let e = _mm_set_epi64x(200, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_compress_epi64() { + let a = _mm_set_epi64x(0, 1); + let r = _mm_maskz_compress_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_compress_epi64(0b00000001, a); + let e = _mm_set_epi64x(0, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_compress_pd() { let src = _mm512_set1_pd(200.); let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_mask_compress_pd(src, 0, a); + assert_eq_m512d(r, src); let r = _mm512_mask_compress_pd(src, 0b01010101, a); let e = _mm512_set_pd(200., 200., 200., 200., 1., 3., 5., 7.); assert_eq_m512d(r, e); @@ -6195,15 +11530,61 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_compress_pd() { let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_maskz_compress_pd(0, a); + assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_compress_pd(0b01010101, a); let e = _mm512_set_pd(0., 0., 0., 0., 1., 3., 5., 7.); assert_eq_m512d(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_compress_pd() { + let src = _mm256_set1_pd(200.); + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_mask_compress_pd(src, 0, a); + assert_eq_m256d(r, src); + let r = _mm256_mask_compress_pd(src, 0b00000101, a); + let e = _mm256_set_pd(200., 200., 1., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_compress_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_maskz_compress_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_compress_pd(0b00000101, a); + let e = _mm256_set_pd(0., 0., 1., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_compress_pd() { + let src = _mm_set1_pd(200.); + let a = _mm_set_pd(0., 1.); + let r = _mm_mask_compress_pd(src, 0, a); + assert_eq_m128d(r, src); + let r = _mm_mask_compress_pd(src, 0b00000001, a); + let e = _mm_set_pd(200., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_compress_pd() { + let a = _mm_set_pd(0., 1.); + let r = _mm_maskz_compress_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_compress_pd(0b00000001, a); + let e = _mm_set_pd(0., 1.); + assert_eq_m128d(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_expand_epi64() { let src = _mm512_set1_epi64(200); let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm512_mask_expand_epi64(src, 0, a); + assert_eq_m512i(r, src); let r = _mm512_mask_expand_epi64(src, 0b01010101, a); let e = _mm512_set_epi64(200, 4, 200, 5, 200, 6, 200, 7); assert_eq_m512i(r, e); @@ -6212,15 +11593,61 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_expand_epi64() { let a = _mm512_set_epi64(0, 1, 2, 3, 4, 5, 6, 7); + let r = _mm512_maskz_expand_epi64(0, a); + assert_eq_m512i(r, _mm512_setzero_si512()); let r = _mm512_maskz_expand_epi64(0b01010101, a); let e = _mm512_set_epi64(0, 4, 0, 5, 0, 6, 0, 7); assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_expand_epi64() { + let src = _mm256_set1_epi64x(200); + let a = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_mask_expand_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_expand_epi64(src, 0b00000101, a); + let e = _mm256_set_epi64x(200, 2, 200, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_expand_epi64() { + let a = _mm256_set_epi64x(0, 1, 2, 3); + let r = _mm256_maskz_expand_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_expand_epi64(0b00000101, a); + let e = _mm256_set_epi64x(0, 2, 0, 3); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_expand_epi64() { + let src = _mm_set1_epi64x(200); + let a = _mm_set_epi64x(0, 1); + let r = _mm_mask_expand_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_expand_epi64(src, 0b00000001, a); + let e = _mm_set_epi64x(200, 1); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_expand_epi64() { + let a = _mm_set_epi64x(0, 1); + let r = _mm_maskz_expand_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_expand_epi64(0b00000001, a); + let e = _mm_set_epi64x(0, 1); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_mask_expand_pd() { let src = _mm512_set1_pd(200.); let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_mask_expand_pd(src, 0, a); + assert_eq_m512d(r, src); let r = _mm512_mask_expand_pd(src, 0b01010101, a); let e = _mm512_set_pd(200., 4., 200., 5., 200., 6., 200., 7.); assert_eq_m512d(r, e); @@ -6229,18 +11656,362 @@ mod tests { #[simd_test(enable = "avx512f")] unsafe fn test_mm512_maskz_expand_pd() { let a = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); + let r = _mm512_maskz_expand_pd(0, a); + assert_eq_m512d(r, _mm512_setzero_pd()); let r = _mm512_maskz_expand_pd(0b01010101, a); let e = _mm512_set_pd(0., 4., 0., 5., 0., 6., 0., 7.); assert_eq_m512d(r, e); } - #[simd_test(enable = "avx512f")] - unsafe fn test_mm512_loadu_epi64() { - let a = &[4, 3, 2, 5, -8, -9, -64, -50]; - let p = a.as_ptr(); - let r = _mm512_loadu_epi64(black_box(p)); - let e = _mm512_setr_epi64(4, 3, 2, 5, -8, -9, -64, -50); - assert_eq_m512i(r, e); + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_expand_pd() { + let src = _mm256_set1_pd(200.); + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_mask_expand_pd(src, 0, a); + assert_eq_m256d(r, src); + let r = _mm256_mask_expand_pd(src, 0b00000101, a); + let e = _mm256_set_pd(200., 2., 200., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_expand_pd() { + let a = _mm256_set_pd(0., 1., 2., 3.); + let r = _mm256_maskz_expand_pd(0, a); + assert_eq_m256d(r, _mm256_setzero_pd()); + let r = _mm256_maskz_expand_pd(0b00000101, a); + let e = _mm256_set_pd(0., 2., 0., 3.); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_expand_pd() { + let src = _mm_set1_pd(200.); + let a = _mm_set_pd(0., 1.); + let r = _mm_mask_expand_pd(src, 0, a); + assert_eq_m128d(r, src); + let r = _mm_mask_expand_pd(src, 0b00000001, a); + let e = _mm_set_pd(200., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_expand_pd() { + let a = _mm_set_pd(0., 1.); + let r = _mm_maskz_expand_pd(0, a); + assert_eq_m128d(r, _mm_setzero_pd()); + let r = _mm_maskz_expand_pd(0b00000001, a); + let e = _mm_set_pd(0., 1.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_loadu_epi64() { + let a = &[4, 3, 2, 5, -8, -9, -64, -50]; + let p = a.as_ptr(); + let r = _mm512_loadu_epi64(black_box(p)); + let e = _mm512_setr_epi64(4, 3, 2, 5, -8, -9, -64, -50); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_loadu_epi64() { + let a = &[4, 3, 2, 5]; + let p = a.as_ptr(); + let r = _mm256_loadu_epi64(black_box(p)); + let e = _mm256_setr_epi64x(4, 3, 2, 5); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_loadu_epi64() { + let a = &[4, 3]; + let p = a.as_ptr(); + let r = _mm_loadu_epi64(black_box(p)); + let e = _mm_setr_epi64x(4, 3); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtepi64_storeu_epi16() { + let a = _mm512_set1_epi64(9); + let mut r = _mm_undefined_si128(); + _mm512_mask_cvtepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set1_epi16(9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi64_storeu_epi16() { + let a = _mm256_set1_epi64x(9); + let mut r = _mm_set1_epi16(0); + _mm256_mask_cvtepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 9, 9, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi64_storeu_epi16() { + let a = _mm_set1_epi64x(9); + let mut r = _mm_set1_epi16(0); + _mm_mask_cvtepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtsepi64_storeu_epi16() { + let a = _mm512_set1_epi64(i64::MAX); + let mut r = _mm_undefined_si128(); + _mm512_mask_cvtsepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set1_epi16(i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi64_storeu_epi16() { + let a = _mm256_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi16(0); + _mm256_mask_cvtsepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, i16::MAX, i16::MAX, i16::MAX, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi64_storeu_epi16() { + let a = _mm_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi16(0); + _mm_mask_cvtsepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, i16::MAX, i16::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtusepi64_storeu_epi16() { + let a = _mm512_set1_epi64(i64::MAX); + let mut r = _mm_undefined_si128(); + _mm512_mask_cvtusepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set1_epi16(u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi64_storeu_epi16() { + let a = _mm256_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi16(0); + _mm256_mask_cvtusepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16( + 0, + 0, + 0, + 0, + u16::MAX as i16, + u16::MAX as i16, + u16::MAX as i16, + u16::MAX as i16, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi64_storeu_epi16() { + let a = _mm_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi16(0); + _mm_mask_cvtusepi64_storeu_epi16(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi16(0, 0, 0, 0, 0, 0, u16::MAX as i16, u16::MAX as i16); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtepi64_storeu_epi8() { + let a = _mm512_set1_epi64(9); + let mut r = _mm_set1_epi8(0); + _mm512_mask_cvtepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi64_storeu_epi8() { + let a = _mm256_set1_epi64x(9); + let mut r = _mm_set1_epi8(0); + _mm256_mask_cvtepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi64_storeu_epi8() { + let a = _mm_set1_epi64x(9); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtsepi64_storeu_epi8() { + let a = _mm512_set1_epi64(i64::MAX); + let mut r = _mm_set1_epi8(0); + _mm512_mask_cvtsepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + i8::MAX, i8::MAX, i8::MAX, i8::MAX, + i8::MAX, i8::MAX, i8::MAX, i8::MAX, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi64_storeu_epi8() { + let a = _mm256_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi8(0); + _mm256_mask_cvtsepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + i8::MAX, i8::MAX, i8::MAX, i8::MAX, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi64_storeu_epi8() { + let a = _mm_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtsepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, i8::MAX, i8::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtusepi64_storeu_epi8() { + let a = _mm512_set1_epi64(i64::MAX); + let mut r = _mm_set1_epi8(0); + _mm512_mask_cvtusepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi64_storeu_epi8() { + let a = _mm256_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi8(0); + _mm256_mask_cvtusepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, u8::MAX as i8, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi64_storeu_epi8() { + let a = _mm_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi8(0); + _mm_mask_cvtusepi64_storeu_epi8(&mut r as *mut _ as *mut i8, 0b11111111, a); + #[rustfmt::skip] + let e = _mm_set_epi8( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, u8::MAX as i8, u8::MAX as i8, + ); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtepi64_storeu_epi32() { + let a = _mm512_set1_epi64(9); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm256_set1_epi32(9); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtepi64_storeu_epi32() { + let a = _mm256_set1_epi64x(9); + let mut r = _mm_set1_epi32(0); + _mm256_mask_cvtepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi32(9, 9, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtepi64_storeu_epi32() { + let a = _mm_set1_epi64x(9); + let mut r = _mm_set1_epi16(0); + _mm_mask_cvtepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm_set_epi32(0, 0, 9, 9); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtsepi64_storeu_epi32() { + let a = _mm512_set1_epi64(i64::MAX); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtsepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm256_set1_epi32(i32::MAX); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtsepi64_storeu_epi32() { + let a = _mm256_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi32(0); + _mm256_mask_cvtsepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b00001111, a); + let e = _mm_set1_epi32(i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtsepi64_storeu_epi32() { + let a = _mm_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi16(0); + _mm_mask_cvtsepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b00000011, a); + let e = _mm_set_epi32(0, 0, i32::MAX, i32::MAX); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_cvtusepi64_storeu_epi32() { + let a = _mm512_set1_epi64(i64::MAX); + let mut r = _mm256_undefined_si256(); + _mm512_mask_cvtusepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b11111111, a); + let e = _mm256_set1_epi32(u32::MAX as i32); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_cvtusepi64_storeu_epi32() { + let a = _mm256_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi32(0); + _mm256_mask_cvtusepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b00001111, a); + let e = _mm_set1_epi32(u32::MAX as i32); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_cvtusepi64_storeu_epi32() { + let a = _mm_set1_epi64x(i64::MAX); + let mut r = _mm_set1_epi16(0); + _mm_mask_cvtusepi64_storeu_epi32(&mut r as *mut _ as *mut i8, 0b00000011, a); + let e = _mm_set_epi32(0, 0, u32::MAX as i32, u32::MAX as i32); + assert_eq_m128i(r, e); } #[simd_test(enable = "avx512f")] @@ -6251,6 +12022,22 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_storeu_epi64() { + let a = _mm256_set1_epi64x(9); + let mut r = _mm256_set1_epi64x(0); + _mm256_storeu_epi64(&mut r as *mut _ as *mut i64, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_storeu_epi64() { + let a = _mm_set1_epi64x(9); + let mut r = _mm_set1_epi64x(0); + _mm_storeu_epi64(&mut r as *mut _ as *mut i64, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_load_epi64() { #[repr(align(64))] @@ -6266,6 +12053,32 @@ mod tests { assert_eq_m512i(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_load_epi64() { + #[repr(align(64))] + struct Align { + data: [i64; 4], + } + let a = Align { data: [4, 3, 2, 5] }; + let p = (a.data).as_ptr(); + let r = _mm256_load_epi64(black_box(p)); + let e = _mm256_set_epi64x(5, 2, 3, 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_load_epi64() { + #[repr(align(64))] + struct Align { + data: [i64; 2], + } + let a = Align { data: [4, 3] }; + let p = (a.data).as_ptr(); + let r = _mm_load_epi64(black_box(p)); + let e = _mm_set_epi64x(3, 4); + assert_eq_m128i(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_store_epi64() { let a = _mm512_set1_epi64(9); @@ -6274,6 +12087,22 @@ mod tests { assert_eq_m512i(r, a); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_store_epi64() { + let a = _mm256_set1_epi64x(9); + let mut r = _mm256_set1_epi64x(0); + _mm256_store_epi64(&mut r as *mut _ as *mut i64, a); + assert_eq_m256i(r, a); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_store_epi64() { + let a = _mm_set1_epi64x(9); + let mut r = _mm_set1_epi64x(0); + _mm_store_epi64(&mut r as *mut _ as *mut i64, a); + assert_eq_m128i(r, a); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_load_pd() { #[repr(align(64))] @@ -6317,6 +12146,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_test_epi64_mask() { + let a = _mm256_set1_epi64x(1 << 0); + let b = _mm256_set1_epi64x(1 << 0 | 1 << 1); + let r = _mm256_test_epi64_mask(a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_test_epi64_mask() { + let a = _mm256_set1_epi64x(1 << 0); + let b = _mm256_set1_epi64x(1 << 0 | 1 << 1); + let r = _mm256_mask_test_epi64_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_test_epi64_mask(0b00001111, a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_test_epi64_mask() { + let a = _mm_set1_epi64x(1 << 0); + let b = _mm_set1_epi64x(1 << 0 | 1 << 1); + let r = _mm_test_epi64_mask(a, b); + let e: __mmask8 = 0b00000011; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_test_epi64_mask() { + let a = _mm_set1_epi64x(1 << 0); + let b = _mm_set1_epi64x(1 << 0 | 1 << 1); + let r = _mm_mask_test_epi64_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_test_epi64_mask(0b00000011, a, b); + let e: __mmask8 = 0b00000011; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_testn_epi64_mask() { let a = _mm512_set1_epi64(1 << 0); @@ -6337,6 +12206,46 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_testn_epi64_mask() { + let a = _mm256_set1_epi64x(1 << 0); + let b = _mm256_set1_epi64x(1 << 1); + let r = _mm256_testn_epi64_mask(a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_testn_epi64_mask() { + let a = _mm256_set1_epi64x(1 << 0); + let b = _mm256_set1_epi64x(1 << 1); + let r = _mm256_mask_testn_epi64_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm256_mask_testn_epi64_mask(0b11111111, a, b); + let e: __mmask8 = 0b00001111; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_testn_epi64_mask() { + let a = _mm_set1_epi64x(1 << 0); + let b = _mm_set1_epi64x(1 << 1); + let r = _mm_testn_epi64_mask(a, b); + let e: __mmask8 = 0b00000011; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_testn_epi64_mask() { + let a = _mm_set1_epi64x(1 << 0); + let b = _mm_set1_epi64x(1 << 1); + let r = _mm_mask_testn_epi64_mask(0, a, b); + assert_eq!(r, 0); + let r = _mm_mask_testn_epi64_mask(0b11111111, a, b); + let e: __mmask8 = 0b00000011; + assert_eq!(r, e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_stream_pd() { #[repr(align(64))] @@ -6387,4 +12296,296 @@ mod tests { let e = _mm512_set1_epi64(11); assert_eq_m512i(r, e); } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_set1_epi64() { + let src = _mm256_set1_epi64x(2); + let a: i64 = 11; + let r = _mm256_mask_set1_epi64(src, 0, a); + assert_eq_m256i(r, src); + let r = _mm256_mask_set1_epi64(src, 0b00001111, a); + let e = _mm256_set1_epi64x(11); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_set1_epi64() { + let a: i64 = 11; + let r = _mm256_maskz_set1_epi64(0, a); + assert_eq_m256i(r, _mm256_setzero_si256()); + let r = _mm256_maskz_set1_epi64(0b00001111, a); + let e = _mm256_set1_epi64x(11); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_set1_epi64() { + let src = _mm_set1_epi64x(2); + let a: i64 = 11; + let r = _mm_mask_set1_epi64(src, 0, a); + assert_eq_m128i(r, src); + let r = _mm_mask_set1_epi64(src, 0b00000011, a); + let e = _mm_set1_epi64x(11); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_set1_epi64() { + let a: i64 = 11; + let r = _mm_maskz_set1_epi64(0, a); + assert_eq_m128i(r, _mm_setzero_si128()); + let r = _mm_maskz_set1_epi64(0b00000011, a); + let e = _mm_set1_epi64x(11); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtsd_i64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvtsd_i64(a); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtss_i64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvtss_i64(a); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundi64_ss() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let b: i64 = 9; + let r = _mm_cvt_roundi64_ss(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e = _mm_set_ps(0., -0.5, 1., 9.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundsi64_ss() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let b: i64 = 9; + let r = _mm_cvt_roundsi64_ss(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e = _mm_set_ps(0., -0.5, 1., 9.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvti64_ss() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let b: i64 = 9; + let r = _mm_cvti64_ss(a, b); + let e = _mm_set_ps(0., -0.5, 1., 9.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvti64_sd() { + let a = _mm_set_pd(1., -1.5); + let b: i64 = 9; + let r = _mm_cvti64_sd(a, b); + let e = _mm_set_pd(1., 9.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundsd_si64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvt_roundsd_si64(a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e: i64 = -1; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundsd_i64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvt_roundsd_i64(a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e: i64 = -1; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundsd_u64() { + let a = _mm_set_pd(1., f64::MAX); + let r = _mm_cvt_roundsd_u64(a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtsd_u64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvtsd_u64(a); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundss_i64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvt_roundss_i64(a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e: i64 = -1; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundss_si64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvt_roundss_si64(a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e: i64 = -1; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundss_u64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvt_roundss_u64(a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtss_u64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvtss_u64(a); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvttsd_i64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvttsd_i64(a); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtt_roundsd_i64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvtt_roundsd_i64(a, _MM_FROUND_CUR_DIRECTION); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtt_roundsd_si64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvtt_roundsd_si64(a, _MM_FROUND_CUR_DIRECTION); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtt_roundsd_u64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvtt_roundsd_u64(a, _MM_FROUND_CUR_DIRECTION); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvttsd_u64() { + let a = _mm_set_pd(1., -1.5); + let r = _mm_cvttsd_u64(a); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvttss_i64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvttss_i64(a); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtt_roundss_i64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvtt_roundss_i64(a, _MM_FROUND_CUR_DIRECTION); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtt_roundss_si64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvtt_roundss_si64(a, _MM_FROUND_CUR_DIRECTION); + let e: i64 = -2; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtt_roundss_u64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvtt_roundss_u64(a, _MM_FROUND_CUR_DIRECTION); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvttss_u64() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let r = _mm_cvttss_u64(a); + let e: u64 = u64::MAX; + assert_eq!(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtu64_ss() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let b: u64 = 9; + let r = _mm_cvtu64_ss(a, b); + let e = _mm_set_ps(0., -0.5, 1., 9.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvtu64_sd() { + let a = _mm_set_pd(1., -1.5); + let b: u64 = 9; + let r = _mm_cvtu64_sd(a, b); + let e = _mm_set_pd(1., 9.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundu64_ss() { + let a = _mm_set_ps(0., -0.5, 1., -1.5); + let b: u64 = 9; + let r = _mm_cvt_roundu64_ss(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e = _mm_set_ps(0., -0.5, 1., 9.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundu64_sd() { + let a = _mm_set_pd(1., -1.5); + let b: u64 = 9; + let r = _mm_cvt_roundu64_sd(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e = _mm_set_pd(1., 9.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundi64_sd() { + let a = _mm_set_pd(1., -1.5); + let b: i64 = 9; + let r = _mm_cvt_roundi64_sd(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e = _mm_set_pd(1., 9.); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm_cvt_roundsi64_sd() { + let a = _mm_set_pd(1., -1.5); + let b: i64 = 9; + let r = _mm_cvt_roundsi64_sd(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); + let e = _mm_set_pd(1., 9.); + assert_eq_m128d(r, e); + } } diff --git a/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs b/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs index ef7e311cfc..4274b4c476 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs @@ -87,7 +87,7 @@ mod tests { } impl fmt::Debug for FxsaveArea { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[")?; for i in 0..self.data.len() { write!(f, "{}", self.data[i])?; diff --git a/library/stdarch/crates/core_arch/src/x86_64/macros.rs b/library/stdarch/crates/core_arch/src/x86_64/macros.rs new file mode 100644 index 0000000000..e3682d40fe --- /dev/null +++ b/library/stdarch/crates/core_arch/src/x86_64/macros.rs @@ -0,0 +1,32 @@ +//! Utility macros. + +// For round instructions, the only valid values for rounding are 4, 8, 9, 10 and 11. +// This macro enforces that. +#[allow(unused)] +macro_rules! constify_imm4_round { + ($imm8:expr, $expand:ident) => { + #[allow(overflowing_literals)] + match ($imm8) & 0b1111 { + 4 => $expand!(4), + 8 => $expand!(8), + 9 => $expand!(9), + 10 => $expand!(10), + 11 => $expand!(11), + _ => panic!("Invalid round value"), + } + }; +} + +// For sae instructions, the only valid values for sae are 4 and 8. +// This macro enforces that. +#[allow(unused)] +macro_rules! constify_imm4_sae { + ($imm8:expr, $expand:ident) => { + #[allow(overflowing_literals)] + match ($imm8) & 0b1111 { + 4 => $expand!(4), + 8 => $expand!(8), + _ => panic!("Invalid sae value"), + } + }; +} diff --git a/library/stdarch/crates/core_arch/src/x86_64/mod.rs b/library/stdarch/crates/core_arch/src/x86_64/mod.rs index c9f3bd637c..461874ece0 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/mod.rs @@ -1,5 +1,8 @@ //! `x86_64` intrinsics +#[macro_use] +mod macros; + mod fxsr; pub use self::fxsr::*; diff --git a/library/stdarch/crates/core_arch/src/x86_64/xsave.rs b/library/stdarch/crates/core_arch/src/x86_64/xsave.rs index 215e5a541e..2afd3e433a 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/xsave.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/xsave.rs @@ -164,7 +164,7 @@ mod tests { } impl fmt::Debug for XsaveArea { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[")?; for i in 0..self.data.len() { write!(f, "{}", self.data[i])?; diff --git a/library/stdarch/crates/simd-test-macro/src/lib.rs b/library/stdarch/crates/simd-test-macro/src/lib.rs index 8e65c43992..4c863ae701 100644 --- a/library/stdarch/crates/simd-test-macro/src/lib.rs +++ b/library/stdarch/crates/simd-test-macro/src/lib.rs @@ -2,6 +2,7 @@ //! //! This macro expands to a `#[test]` function which tests the local machine //! for the appropriate cfg before calling the inner test function. +#![deny(rust_2018_idioms)] extern crate proc_macro; extern crate proc_macro2; diff --git a/library/stdarch/crates/std_detect/Cargo.toml b/library/stdarch/crates/std_detect/Cargo.toml index 252e42c569..4d0f93d8cf 100644 --- a/library/stdarch/crates/std_detect/Cargo.toml +++ b/library/stdarch/crates/std_detect/Cargo.toml @@ -25,12 +25,22 @@ maintenance = { status = "experimental" } libc = { version = "0.2", optional = true, default-features = false } cfg-if = "0.1.10" +# When built as part of libstd +core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +compiler_builtins = { version = "0.1.2", optional = true } +alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" } + [dev-dependencies] auxv = "0.3.3" cupid = "0.6.0" [features] default = [ "std_detect_dlsym_getauxval", "std_detect_file_io" ] -std_detect_file_io = [] +std_detect_file_io = [ "libc" ] std_detect_dlsym_getauxval = [ "libc" ] -std_detect_env_override = [] +std_detect_env_override = [ "libc" ] +rustc-dep-of-std = [ + "core", + "compiler_builtins", + "alloc", +] diff --git a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs index 08a223fa02..e21ee6c3cb 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs @@ -158,7 +158,7 @@ features! { @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vnni: "avx512vnni"; /// AVX-512 VNNI (Vector Neural Network Instructions) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bitalg: "avx512bitalg"; - /// AVX-512 BITALG (Support for VPOPCNT[B,W] and VPSHUFBITQMB) + /// AVX-512 BITALG (Support for VPOPCNT\[B,W\] and VPSHUFBITQMB) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bf16: "avx512bf16"; /// AVX-512 BF16 (BFLOAT16 instructions) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vp2intersect: "avx512vp2intersect"; diff --git a/library/stdarch/crates/std_detect/src/detect/cache.rs b/library/stdarch/crates/std_detect/src/detect/cache.rs index e79c96dafa..d01a5ea244 100644 --- a/library/stdarch/crates/std_detect/src/detect/cache.rs +++ b/library/stdarch/crates/std_detect/src/detect/cache.rs @@ -3,9 +3,9 @@ #![allow(dead_code)] // not used on all platforms -use crate::sync::atomic::Ordering; +use core::sync::atomic::Ordering; -use crate::sync::atomic::AtomicUsize; +use core::sync::atomic::AtomicUsize; /// Sets the `bit` of `x`. #[inline] @@ -125,9 +125,16 @@ cfg_if::cfg_if! { if #[cfg(feature = "std_detect_env_override")] { #[inline] fn initialize(mut value: Initializer) -> Initializer { - if let Ok(disable) = crate::env::var("RUST_STD_DETECT_UNSTABLE") { - for v in disable.split(" ") { - let _ = super::Feature::from_str(v).map(|v| value.unset(v as u32)); + let env = unsafe { + libc::getenv(b"RUST_STD_DETECT_UNSTABLE\0".as_ptr() as *const libc::c_char) + }; + if !env.is_null() { + let len = unsafe { libc::strlen(env) }; + let env = unsafe { core::slice::from_raw_parts(env as *const u8, len) }; + if let Ok(disable) = core::str::from_utf8(env) { + for v in disable.split(" ") { + let _ = super::Feature::from_str(v).map(|v| value.unset(v as u32)); + } } } do_initialize(value); diff --git a/library/stdarch/crates/std_detect/src/detect/mod.rs b/library/stdarch/crates/std_detect/src/detect/mod.rs index 7aedef47d6..1b7768ae8f 100644 --- a/library/stdarch/crates/std_detect/src/detect/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/mod.rs @@ -98,10 +98,10 @@ cfg_if! { // On x86/x86_64 no OS specific functionality is required. #[path = "os/x86.rs"] mod os; - } else if #[cfg(all(target_os = "linux", feature = "use_std"))] { + } else if #[cfg(all(target_os = "linux", feature = "libc"))] { #[path = "os/linux/mod.rs"] mod os; - } else if #[cfg(all(target_os = "freebsd", feature = "use_std"))] { + } else if #[cfg(all(target_os = "freebsd", feature = "libc"))] { #[cfg(target_arch = "aarch64")] #[path = "os/aarch64.rs"] mod aarch64; @@ -140,7 +140,7 @@ pub fn features() -> impl Iterator { target_arch = "mips64", ))] { (0_u8..Feature::_last as u8).map(|discriminant: u8| { - let f: Feature = unsafe { crate::mem::transmute(discriminant) }; + let f: Feature = unsafe { core::mem::transmute(discriminant) }; let name: &'static str = f.to_str(); let enabled: bool = check_for(f); (name, enabled) diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs index c595ec459b..832ce2252e 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs @@ -42,7 +42,7 @@ pub(crate) fn auxv() -> Result { /// Tries to read the `key` from the auxiliary vector. fn archauxv(key: usize) -> Result { - use crate::mem; + use core::mem; #[derive(Copy, Clone)] #[repr(C)] diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs index 4321bce74d..ade7fb6269 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/mod.rs @@ -5,18 +5,18 @@ mod auxvec; cfg_if::cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; - pub use self::aarch64::check_for; + pub(crate) use self::aarch64::detect_features; } else if #[cfg(target_arch = "arm")] { mod arm; - pub use self::arm::check_for; + pub(crate) use self::arm::detect_features; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc; - pub use self::powerpc::check_for; + pub(crate) use self::powerpc::detect_features; } else { - use crate::arch::detect::Feature; + use crate::detect::cache; /// Performs run-time feature detection. - pub fn check_for(_x: Feature) -> bool { - false + pub(crate) fn detect_features() -> cache::Initializer { + cache::Initializer::default() } } } diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs index b1b68f763e..80c36e9b99 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs @@ -1,6 +1,6 @@ //! Run-time feature detection for Aarch64 on Linux. -use super::{auxvec, cpuinfo}; +use super::auxvec; use crate::detect::{bit, cache, Feature}; /// Try to read the features from the auxiliary vector, and if that fails, try @@ -10,7 +10,8 @@ pub(crate) fn detect_features() -> cache::Initializer { let hwcap: AtHwcap = auxv.into(); return hwcap.cache(); } - if let Ok(c) = cpuinfo::CpuInfo::new() { + #[cfg(feature = "std_detect_file_io")] + if let Ok(c) = super::cpuinfo::CpuInfo::new() { let hwcap: AtHwcap = c.into(); return hwcap.cache(); } @@ -77,9 +78,10 @@ impl From for AtHwcap { } } -impl From for AtHwcap { +#[cfg(feature = "std_detect_file_io")] +impl From for AtHwcap { /// Reads AtHwcap from /proc/cpuinfo . - fn from(c: cpuinfo::CpuInfo) -> Self { + fn from(c: super::cpuinfo::CpuInfo) -> Self { let f = &c.field("Features"); AtHwcap { // 64-bit names. FIXME: In 32-bit compatibility mode /proc/cpuinfo will diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs index 4b0cb586bb..66cfd05e80 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs @@ -1,6 +1,6 @@ //! Run-time feature detection for ARM on Linux. -use super::{auxvec, cpuinfo}; +use super::auxvec; use crate::detect::{bit, cache, Feature}; /// Try to read the features from the auxiliary vector, and if that fails, try @@ -31,7 +31,8 @@ pub(crate) fn detect_features() -> cache::Initializer { return value; } - if let Ok(c) = cpuinfo::CpuInfo::new() { + #[cfg(feature = "std_detect_file_io")] + if let Ok(c) = super::cpuinfo::CpuInfo::new() { enable_feature( &mut value, Feature::neon, @@ -55,7 +56,8 @@ pub(crate) fn detect_features() -> cache::Initializer { /// Is the CPU known to have a broken NEON unit? /// /// See https://crbug.com/341598. -fn has_broken_neon(cpuinfo: &cpuinfo::CpuInfo) -> bool { +#[cfg(feature = "std_detect_file_io")] +fn has_broken_neon(cpuinfo: &super::cpuinfo::CpuInfo) -> bool { cpuinfo.field("CPU implementer") == "0x51" && cpuinfo.field("CPU architecture") == "7" && cpuinfo.field("CPU variant") == "0x1" diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs index 6ebae67fbf..077fc9e4c8 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs @@ -1,13 +1,16 @@ //! Parses ELF auxiliary vectors. #![cfg_attr(not(target_arch = "aarch64"), allow(dead_code))] -#[cfg(feature = "std_detect_file_io")] -use crate::{fs::File, io::Read}; +pub(crate) const AT_NULL: usize = 0; /// Key to access the CPU Hardware capabilities bitfield. pub(crate) const AT_HWCAP: usize = 16; /// Key to access the CPU Hardware capabilities 2 bitfield. -#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] +#[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" +))] pub(crate) const AT_HWCAP2: usize = 26; /// Cache HWCAP bitfields of the ELF Auxiliary Vector. @@ -17,7 +20,11 @@ pub(crate) const AT_HWCAP2: usize = 26; #[derive(Debug, Copy, Clone)] pub(crate) struct AuxVec { pub hwcap: usize, - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] pub hwcap2: usize, } @@ -64,7 +71,11 @@ pub(crate) fn auxv() -> Result { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { if let Ok(hwcap2) = getauxval(AT_HWCAP2) { if hwcap != 0 && hwcap2 != 0 { @@ -74,21 +85,11 @@ pub(crate) fn auxv() -> Result { } drop(hwcap); } - #[cfg(feature = "std_detect_file_io")] - { - // If calling getauxval fails, try to read the auxiliary vector from - // its file: - auxv_from_file("/proc/self/auxv") - } - #[cfg(not(feature = "std_detect_file_io"))] - { - Err(()) - } } #[cfg(not(feature = "std_detect_dlsym_getauxval"))] { - let hwcap = unsafe { ffi_getauxval(AT_HWCAP) }; + let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; // Targets with only AT_HWCAP: #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] @@ -99,14 +100,29 @@ pub(crate) fn auxv() -> Result { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { - let hwcap2 = unsafe { ffi_getauxval(AT_HWCAP2) }; + let hwcap2 = unsafe { libc::getauxval(AT_HWCAP2 as libc::c_ulong) as usize }; if hwcap != 0 && hwcap2 != 0 { return Ok(AuxVec { hwcap, hwcap2 }); } } } + + #[cfg(feature = "std_detect_file_io")] + { + // If calling getauxval fails, try to read the auxiliary vector from + // its file: + auxv_from_file("/proc/self/auxv") + } + #[cfg(not(feature = "std_detect_file_io"))] + { + Err(()) + } } /// Tries to read the `key` from the auxiliary vector by calling the @@ -122,7 +138,7 @@ fn getauxval(key: usize) -> Result { return Err(()); } - let ffi_getauxval: F = mem::transmute(ptr); + let ffi_getauxval: F = core::mem::transmute(ptr); Ok(ffi_getauxval(key)) } } @@ -131,7 +147,7 @@ fn getauxval(key: usize) -> Result { /// function returns `Err`. #[cfg(feature = "std_detect_file_io")] fn auxv_from_file(file: &str) -> Result { - let mut file = File::open(file).map_err(|_| ())?; + let file = super::read_file(file)?; // See . // @@ -139,10 +155,11 @@ fn auxv_from_file(file: &str) -> Result { // `AT_EXECFN = 31` to `AT_NULL = 0`. That is, a buffer of // 2*32 `usize` elements is enough to read the whole vector. let mut buf = [0_usize; 64]; - { - let raw: &mut [u8; 64 * mem::size_of::()] = unsafe { mem::transmute(&mut buf) }; - file.read(raw).map_err(|_| ())?; + let len = core::mem::size_of_val(&buf).max(file.len()); + unsafe { + core::ptr::copy_nonoverlapping(file.as_ptr(), buf.as_mut_ptr() as *mut u8, len); } + auxv_from_buf(&buf) } @@ -155,18 +172,24 @@ fn auxv_from_buf(buf: &[usize; 64]) -> Result { { for el in buf.chunks(2) { match el[0] { + AT_NULL => break, AT_HWCAP => return Ok(AuxVec { hwcap: el[1] }), _ => (), } } } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { let mut hwcap = None; let mut hwcap2 = None; for el in buf.chunks(2) { match el[0] { + AT_NULL => break, AT_HWCAP => hwcap = Some(el[1]), AT_HWCAP2 => hwcap2 = Some(el[1]), _ => (), @@ -214,7 +237,12 @@ mod tests { // FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv // does not always contain the AT_HWCAP key under qemu. - #[cfg(not(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc")))] + #[cfg(any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] #[test] fn auxv_crate() { let v = auxv(); @@ -224,7 +252,11 @@ mod tests { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { if let Some(hwcap2) = auxv_crate_getauxval(AT_HWCAP2) { let rt_hwcap2 = v.expect("failed to find hwcap2 key").hwcap2; @@ -243,7 +275,7 @@ mod tests { } #[cfg(feature = "std_detect_file_io")] - cfg_if! { + cfg_if::cfg_if! { if #[cfg(target_arch = "arm")] { #[test] fn linux_rpi3() { @@ -264,6 +296,7 @@ mod tests { // want to fall back to /proc/cpuinfo in this case, so // reading should fail. assert_eq!(v.hwcap, 126614527); // assert_eq!(v.hwcap2, 0); + let _ = v; } } else if #[cfg(target_arch = "aarch64")] { #[test] @@ -286,7 +319,14 @@ mod tests { } } + #[cfg(any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] #[test] + #[cfg(feature = "std_detect_file_io")] fn auxv_crate_procfs() { let v = auxv(); if let Some(hwcap) = auxv_crate_getprocfs(AT_HWCAP) { @@ -294,7 +334,11 @@ mod tests { } // Targets with AT_HWCAP and AT_HWCAP2: - #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + #[cfg(any( + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64" + ))] { if let Some(hwcap2) = auxv_crate_getprocfs(AT_HWCAP2) { assert_eq!(v.unwrap().hwcap2, hwcap2); diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs index f76c48a4b1..91279b9ed7 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs @@ -1,8 +1,7 @@ //! Parses /proc/cpuinfo #![cfg_attr(not(target_arch = "arm"), allow(dead_code))] -extern crate std; -use self::std::{fs::File, io, io::Read, prelude::v1::*}; +use alloc::string::String; /// cpuinfo pub(crate) struct CpuInfo { @@ -11,14 +10,14 @@ pub(crate) struct CpuInfo { impl CpuInfo { /// Reads /proc/cpuinfo into CpuInfo. - pub(crate) fn new() -> Result { - let mut file = File::open("/proc/cpuinfo")?; - let mut cpui = Self { raw: String::new() }; - file.read_to_string(&mut cpui.raw)?; - Ok(cpui) + pub(crate) fn new() -> Result { + let raw = super::read_file("/proc/cpuinfo")?; + Ok(Self { + raw: String::from_utf8(raw).map_err(|_| ())?, + }) } /// Returns the value of the cpuinfo `field`. - pub(crate) fn field(&self, field: &str) -> CpuInfoField { + pub(crate) fn field(&self, field: &str) -> CpuInfoField<'_> { for l in self.raw.lines() { if l.trim().starts_with(field) { return CpuInfoField::new(l.split(": ").nth(1)); @@ -34,7 +33,7 @@ impl CpuInfo { } #[cfg(test)] - fn from_str(other: &str) -> Result { + fn from_str(other: &str) -> Result { Ok(Self { raw: String::from(other), }) diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs index e02d5e6dcd..4b6776e982 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs @@ -1,28 +1,61 @@ //! Run-time feature detection on Linux +//! +#[cfg(feature = "std_detect_file_io")] +use alloc::vec::Vec; mod auxvec; #[cfg(feature = "std_detect_file_io")] mod cpuinfo; -cfg_if! { +#[cfg(feature = "std_detect_file_io")] +fn read_file(path: &str) -> Result, ()> { + let mut path = Vec::from(path.as_bytes()); + path.push(0); + + unsafe { + let file = libc::open(path.as_ptr() as *const libc::c_char, libc::O_RDONLY); + if file == -1 { + return Err(()); + } + + let mut data = Vec::new(); + loop { + data.reserve(4096); + let spare = data.spare_capacity_mut(); + match libc::read(file, spare.as_mut_ptr() as *mut _, spare.len()) { + -1 => { + libc::close(file); + return Err(()); + } + 0 => break, + n => data.set_len(data.len() + n as usize), + } + } + + libc::close(file); + Ok(data) + } +} + +cfg_if::cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; - pub use self::aarch64::check_for; + pub(crate) use self::aarch64::detect_features; } else if #[cfg(target_arch = "arm")] { mod arm; - pub use self::arm::check_for; + pub(crate) use self::arm::detect_features; } else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { mod mips; - pub use self::mips::check_for; + pub(crate) use self::mips::detect_features; } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { mod powerpc; - pub use self::powerpc::check_for; + pub(crate) use self::powerpc::detect_features; } else { - use crate::detect::Feature; + use crate::detect::cache; /// Performs run-time feature detection. - pub fn check_for(_x: Feature) -> bool { - false + pub(crate) fn detect_features() -> cache::Initializer { + cache::Initializer::default() } } } diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs index 97afe49fe5..c3308e8158 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs @@ -1,6 +1,6 @@ //! Run-time feature detection for PowerPC on Linux. -use super::{auxvec, cpuinfo}; +use super::auxvec; use crate::detect::{cache, Feature}; /// Try to read the features from the auxiliary vector, and if that fails, try @@ -27,7 +27,8 @@ pub(crate) fn detect_features() -> cache::Initializer { // PowerPC's /proc/cpuinfo lacks a proper Feature field, // but `altivec` support is indicated in the `cpu` field. - if let Ok(c) = cpuinfo::CpuInfo::new() { + #[cfg(feature = "std_detect_file_io")] + if let Ok(c) = super::cpuinfo::CpuInfo::new() { enable_feature(&mut value, Feature::altivec, c.field("cpu").has("altivec")); return value; } diff --git a/library/stdarch/crates/std_detect/src/detect/os/x86.rs b/library/stdarch/crates/std_detect/src/detect/os/x86.rs index 436fb00f06..388af2e304 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/x86.rs @@ -1,11 +1,11 @@ //! x86 run-time feature detection is OS independent. #[cfg(target_arch = "x86")] -use crate::arch::x86::*; +use core::arch::x86::*; #[cfg(target_arch = "x86_64")] -use crate::arch::x86_64::*; +use core::arch::x86_64::*; -use crate::mem; +use core::mem; use crate::detect::{bit, cache, Feature}; diff --git a/library/stdarch/crates/std_detect/src/lib.rs b/library/stdarch/crates/std_detect/src/lib.rs index 8cd02c9616..782833cbb6 100644 --- a/library/stdarch/crates/std_detect/src/lib.rs +++ b/library/stdarch/crates/std_detect/src/lib.rs @@ -13,32 +13,22 @@ #![unstable(feature = "stdsimd", issue = "27731")] #![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] +#![deny(rust_2018_idioms)] #![allow(clippy::shadow_reuse)] #![deny(clippy::missing_inline_in_public_items)] -#![cfg_attr(target_os = "linux", feature(linkage))] #![cfg_attr(all(target_os = "freebsd", target_arch = "aarch64"), feature(llvm_asm))] #![cfg_attr(test, allow(unused_imports))] +#![cfg_attr(feature = "std_detect_file_io", feature(vec_spare_capacity))] #![no_std] -cfg_if::cfg_if! { - if #[cfg(any(feature = "std_detect_file_io", feature = "std_detect_env_override"))] { - #[cfg_attr(test, macro_use(println))] - extern crate std; +// rust-lang/rust#83888: removing `extern crate` gives an error that `vec_spare_capacity` is unknown +#[cfg_attr(feature = "std_detect_file_io", allow(unused_extern_crates))] +#[cfg(feature = "std_detect_file_io")] +extern crate alloc; - #[allow(unused_imports)] - use std::{arch, env, fs, io, mem, sync}; - } else { - #[cfg(test)] - #[macro_use(println)] - extern crate std; - - #[allow(unused_imports)] - use core::{arch, mem, sync}; - } -} - -#[cfg(feature = "std_detect_dlsym_getauxval")] -extern crate libc; +#[cfg(test)] +#[macro_use] +extern crate std; #[doc(hidden)] #[unstable(feature = "stdsimd", issue = "27731")] diff --git a/library/stdarch/crates/std_detect/src/mod.rs b/library/stdarch/crates/std_detect/src/mod.rs deleted file mode 100644 index b630e7ff38..0000000000 --- a/library/stdarch/crates/std_detect/src/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! `std_detect` - -#[doc(hidden)] // unstable implementation detail -#[unstable(feature = "stdsimd", issue = "27731")] -pub mod detect; diff --git a/library/stdarch/crates/std_detect/tests/x86-specific.rs b/library/stdarch/crates/std_detect/tests/x86-specific.rs index d4182644bc..59e9a62fdb 100644 --- a/library/stdarch/crates/std_detect/tests/x86-specific.rs +++ b/library/stdarch/crates/std_detect/tests/x86-specific.rs @@ -30,7 +30,7 @@ fn dump() { println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq")); println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl")); println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma")); - println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); + println!("avx512vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); println!( "avx512_vpopcntdq {:?}", is_x86_feature_detected!("avx512vpopcntdq") diff --git a/library/stdarch/crates/stdarch-test/src/lib.rs b/library/stdarch/crates/stdarch-test/src/lib.rs index 88409f5dd4..25852c9479 100644 --- a/library/stdarch/crates/stdarch-test/src/lib.rs +++ b/library/stdarch/crates/stdarch-test/src/lib.rs @@ -4,13 +4,12 @@ //! output once globally and then provides the `assert` function which makes //! assertions about the disassembly of a function. #![feature(test)] // For black_box +#![deny(rust_2018_idioms)] #![allow(clippy::missing_docs_in_private_items, clippy::print_stdout)] extern crate assert_instr_macro; -extern crate cc; #[macro_use] extern crate lazy_static; -extern crate rustc_demangle; extern crate simd_test_macro; #[macro_use] extern crate cfg_if; diff --git a/library/stdarch/crates/stdarch-verify/src/lib.rs b/library/stdarch/crates/stdarch-verify/src/lib.rs index acf22d19da..44e6fdc1fd 100644 --- a/library/stdarch/crates/stdarch-verify/src/lib.rs +++ b/library/stdarch/crates/stdarch-verify/src/lib.rs @@ -1,5 +1,4 @@ -extern crate proc_macro; -extern crate proc_macro2; +#![deny(rust_2018_idioms)] #[macro_use] extern crate quote; #[macro_use] @@ -137,12 +136,15 @@ fn to_type(t: &syn::Type) -> proc_macro2::TokenStream { syn::Type::Path(ref p) => match extract_path_ident(&p.path).to_string().as_ref() { // x86 ... "__m128" => quote! { &M128 }, + "__m128bh" => quote! { &M128BH }, "__m128d" => quote! { &M128D }, "__m128i" => quote! { &M128I }, "__m256" => quote! { &M256 }, + "__m256bh" => quote! { &M256BH }, "__m256d" => quote! { &M256D }, "__m256i" => quote! { &M256I }, "__m512" => quote! { &M512 }, + "__m512bh" => quote! { &M512BH }, "__m512d" => quote! { &M512D }, "__m512i" => quote! { &M512I }, "__mmask8" => quote! { &MMASK8 }, @@ -321,7 +323,7 @@ fn find_instrs(attrs: &[syn::Attribute]) -> Vec { // TODO: should probably just reuse `Invoc` from the `assert-instr-macro` // crate. impl syn::parse::Parse for AssertInstr { - fn parse(content: syn::parse::ParseStream) -> syn::Result { + fn parse(content: syn::parse::ParseStream<'_>) -> syn::Result { let input; parenthesized!(input in content); let _ = input.parse::()?; @@ -407,7 +409,7 @@ struct RustcArgsRequiredConst { } impl syn::parse::Parse for RustcArgsRequiredConst { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let content; parenthesized!(content in input); let list = diff --git a/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs b/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs index ddc48fc83b..01a245c54c 100644 --- a/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs +++ b/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs @@ -45,12 +45,15 @@ static ORDERING: Type = Type::Ordering; static M64: Type = Type::M64; static M128: Type = Type::M128; +static M128BH: Type = Type::M128BH; static M128I: Type = Type::M128I; static M128D: Type = Type::M128D; static M256: Type = Type::M256; +static M256BH: Type = Type::M256BH; static M256I: Type = Type::M256I; static M256D: Type = Type::M256D; static M512: Type = Type::M512; +static M512BH: Type = Type::M512BH; static M512I: Type = Type::M512I; static M512D: Type = Type::M512D; static MMASK8: Type = Type::MMASK8; @@ -75,12 +78,15 @@ enum Type { ConstPtr(&'static Type), M64, M128, + M128BH, M128D, M128I, M256, + M256BH, M256D, M256I, M512, + M512BH, M512D, M512I, MMASK8, @@ -476,6 +482,15 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> { // The XML file names BITALG as "avx512_bitalg", while Rust calls // it "avx512bitalg". "avx512_bitalg" => String::from("avx512bitalg"), + // The XML file names VBMI as "avx512_vbmi", while Rust calls + // it "avx512vbmi". + "avx512_vbmi" => String::from("avx512vbmi"), + // The XML file names VBMI2 as "avx512_vbmi2", while Rust calls + // it "avx512vbmi2". + "avx512_vbmi2" => String::from("avx512vbmi2"), + // The XML file names VNNI as "avx512_vnni", while Rust calls + // it "avx512vnni". + "avx512_vnni" => String::from("avx512vnni"), // Some AVX512f intrinsics are also supported by Knight's Corner. // The XML lists them as avx512f/kncni, but we are solely gating // them behind avx512f since we don't have a KNC feature yet. @@ -484,6 +499,9 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> { // The intrinsics guide calls `f16c` `fp16c` in disagreement with // Intel's architecture manuals. "fp16c" => String::from("f16c"), + "avx512_bf16" => String::from("avx512bf16"), + // The XML file names VNNI as "avx512_bf16", while Rust calls + // it "avx512bf16". _ => cpuid, }; let fixed_cpuid = fixup_cpuid(cpuid); @@ -577,6 +595,10 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> { | "_mm256_setr_epi64x" | "_mm256_set1_epi64x" | "_mm512_set1_epi64" + | "_mm256_mask_set1_epi64" + | "_mm256_maskz_set1_epi64" + | "_mm_mask_set1_epi64" + | "_mm_maskz_set1_epi64" | "_mm512_set4_epi64" | "_mm512_setr4_epi64" | "_mm512_set_epi64" @@ -684,12 +706,15 @@ fn equate(t: &Type, intel: &str, intrinsic: &str, is_const: bool) -> Result<(), (&Type::PrimUnsigned(8), "unsigned char") => {} (&Type::M64, "__m64") => {} (&Type::M128, "__m128") => {} + (&Type::M128BH, "__m128bh") => {} (&Type::M128I, "__m128i") => {} (&Type::M128D, "__m128d") => {} (&Type::M256, "__m256") => {} + (&Type::M256BH, "__m256bh") => {} (&Type::M256I, "__m256i") => {} (&Type::M256D, "__m256d") => {} (&Type::M512, "__m512") => {} + (&Type::M512BH, "__m512bh") => {} (&Type::M512I, "__m512i") => {} (&Type::M512D, "__m512d") => {} (&Type::MMASK64, "__mmask64") => {} @@ -717,12 +742,15 @@ fn equate(t: &Type, intel: &str, intrinsic: &str, is_const: bool) -> Result<(), (&Type::MutPtr(&Type::PrimUnsigned(64)), "__mmask64*") => {} (&Type::MutPtr(&Type::M64), "__m64*") => {} (&Type::MutPtr(&Type::M128), "__m128*") => {} + (&Type::MutPtr(&Type::M128BH), "__m128bh*") => {} (&Type::MutPtr(&Type::M128I), "__m128i*") => {} (&Type::MutPtr(&Type::M128D), "__m128d*") => {} (&Type::MutPtr(&Type::M256), "__m256*") => {} + (&Type::MutPtr(&Type::M256BH), "__m256bh*") => {} (&Type::MutPtr(&Type::M256I), "__m256i*") => {} (&Type::MutPtr(&Type::M256D), "__m256d*") => {} (&Type::MutPtr(&Type::M512), "__m512*") => {} + (&Type::MutPtr(&Type::M512BH), "__m512bh*") => {} (&Type::MutPtr(&Type::M512I), "__m512i*") => {} (&Type::MutPtr(&Type::M512D), "__m512d*") => {} @@ -745,12 +773,15 @@ fn equate(t: &Type, intel: &str, intrinsic: &str, is_const: bool) -> Result<(), (&Type::ConstPtr(&Type::PrimUnsigned(32)), "void const*") => {} (&Type::ConstPtr(&Type::M64), "__m64 const*") => {} (&Type::ConstPtr(&Type::M128), "__m128 const*") => {} + (&Type::ConstPtr(&Type::M128BH), "__m128bh const*") => {} (&Type::ConstPtr(&Type::M128I), "__m128i const*") => {} (&Type::ConstPtr(&Type::M128D), "__m128d const*") => {} (&Type::ConstPtr(&Type::M256), "__m256 const*") => {} + (&Type::ConstPtr(&Type::M256BH), "__m256bh const*") => {} (&Type::ConstPtr(&Type::M256I), "__m256i const*") => {} (&Type::ConstPtr(&Type::M256D), "__m256d const*") => {} (&Type::ConstPtr(&Type::M512), "__m512 const*") => {} + (&Type::ConstPtr(&Type::M512BH), "__m512bh const*") => {} (&Type::ConstPtr(&Type::M512I), "__m512i const*") => {} (&Type::ConstPtr(&Type::M512D), "__m512d const*") => {} (&Type::ConstPtr(&Type::PrimUnsigned(32)), "__mmask32*") => {} diff --git a/library/stdarch/examples/Cargo.toml b/library/stdarch/examples/Cargo.toml index 72599b4182..e2590ed9ff 100644 --- a/library/stdarch/examples/Cargo.toml +++ b/library/stdarch/examples/Cargo.toml @@ -8,6 +8,7 @@ authors = [ ] description = "Examples of the stdarch crate." edition = "2018" +default-run = "hex" [dependencies] core_arch = { path = "../crates/core_arch" } @@ -19,6 +20,10 @@ rand = "0.7" name = "hex" path = "hex.rs" +[[bin]] +name = "connect5" +path = "connect5.rs" + [[example]] name = "wasm" crate-type = ["cdylib"] diff --git a/library/stdarch/examples/connect5.rs b/library/stdarch/examples/connect5.rs new file mode 100644 index 0000000000..1b33257852 --- /dev/null +++ b/library/stdarch/examples/connect5.rs @@ -0,0 +1,1272 @@ +//! Outer-Open Gomoku is a board game which is a enhanced version of connect5 (Gomoku).\ +//! The game is a two-player game which played on a 15x15 Go board.\ +//! Two players take turns placing a move on an empty intersection in this board.\ +//! The winner is the first player to form an unbroken chain of five moves horizontally, vertically, or diagonally.\ +//! Unlike Gomoku, the first move is required to be placed at the two outer rows or columns of this board.\ +//! This program provides an AI playing with Minimax search with alpha-beta pruning which uses +//! patterns on evaluation.\ +//! The avx512 intrinsic can do 32 pattern matching at one time.\ +//! This avx512 is tested with non-avx512 code to verify its correctness.\ +//! +//! On Intel i7-7800x using single thread with fixed AVX-512 clock at 4.0GHz, the avx512 is speed up about 9x.\ +//! The average time for each move in the avx512 is around 14.00s ± 1.31s and in the non-avx512 +//! is 129.02s ± 4.96s.\ +//! On Intel Tiger Lake i7-1165G7, the avx512 is around 11.11s ± 1.31s. +//! +//! Pattern Matching\ +//! Use 512-bit to present the board state. The location 0 is top left.\ +//! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\ +//! 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31\ +//! ...\ +//! Pattern "OOOOO" is matching through "0 1 2 3 4", "1 2 3 4 5", ...\ +//! Using avx512, "0 1 2 3 4", "16 17 18 19 20", ... can be matched simultaneously.\ +//! +//! //! You can test out this program via: +//! +//! cargo +nightly run --release --bin connect5 +//! +//! You should see a game self-playing. In the end of the game, it shows the average time for +//! each move. + +#![feature(stdsimd, avx512_target_feature)] +#![feature(stmt_expr_attributes)] + +use rand::seq::SliceRandom; +use rand::thread_rng; + +use std::cmp; +use std::time::Instant; + +#[cfg(target_arch = "x86")] +use {core_arch::arch::x86::*, std_detect::is_x86_feature_detected}; +#[cfg(target_arch = "x86_64")] +use {core_arch::arch::x86_64::*, std_detect::is_x86_feature_detected}; + +// types + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum Color { + Black = 0, + White = 1, + Empty = 2, + Border = 3, +} + +type Square = i32; +type Move = i32; +type Side = Color; + +// constants + +const FILE_SIZE: i32 = 15; +const RANK_SIZE: i32 = 15; +const SQUARE_SIZE: i32 = (FILE_SIZE + 1) * (FILE_SIZE + 4) + 16 + 4; + +const EVAL_INF: i32 = FILE_SIZE * RANK_SIZE * 100; +const MOVE_NONE: Move = -1; +const SCORE_NONE: i32 = -EVAL_INF - 1; + +/// DIRECTION 0: left to right\ +/// DIRECTION 1: top to bottom\ +/// DIRECTION 2: top left to bottom right\ +/// DIRECTION 3: top right to bottom left +#[rustfmt::skip] +const DIRECTION: [[i32; 5]; 4] = [ [1, 2, 3, 4, 5], + [1 * (FILE_SIZE + 1), 2 * (FILE_SIZE + 1), 3 * (FILE_SIZE + 1), 4 * (FILE_SIZE + 1), 5 * (FILE_SIZE + 1)], + [1 * (FILE_SIZE + 2), 2 * (FILE_SIZE + 2), 3 * (FILE_SIZE + 2), 4 * (FILE_SIZE + 2), 5 * (FILE_SIZE + 2)], + [1 * (FILE_SIZE + 0), 2 * (FILE_SIZE + 0), 3 * (FILE_SIZE + 0), 4 * (FILE_SIZE + 0), 5 * (FILE_SIZE + 0)]]; + +/// A table to encode each location to a value in bit 31-0 in the bitboard for 4 direction +#[rustfmt::skip] +const MAPMOVEVALUE: [[i32; 239]; 4] = [ [// Direction 0 + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17, 0, + 1<<31, 1<<30, 1<<29, 1<<28, 1<<27, 1<<26, 1<<25, 1<<24, 1<<23, 1<<22, 1<<21, 1<<20, 1<<19, 1<<18, 1<<17], + [// Direction 1 + 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 1<<31, 0, + 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 1<<30, 0, + 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 1<<29, 0, + 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 1<<28, 0, + 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 1<<27, 0, + 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 1<<26, 0, + 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 1<<25, 0, + 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 1<<24, 0, + 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 1<<23, 0, + 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 1<<22, 0, + 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 1<<21, 0, + 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 1<<20, 0, + 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 0, + 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 1<<18, 0, + 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17, 1<<17], + [// Direction 2 + 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 0, 0, 0, 0, 0, + 1<<15, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 0, 0, 0, 0, + 1<<15, 1<<14, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 0, 0, 0, + 1<<15, 1<<14, 1<<13, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 0, 0, + 1<<15, 1<<14, 1<<13, 1<<12, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 0, + 1<<15, 1<<14, 1<<13, 1<<12, 1<<11, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 0, + 1<<9, 1<<14, 1<<13, 1<<12, 1<<11, 1<<10, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 0, + 1<<8, 1<<8, 1<<13, 1<<12, 1<<11, 1<<10, 1<<9, 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 0, + 1<<7, 1<<7, 1<<7, 1<<12, 1<<11, 1<<10, 1<<9, 1<<8, 1<<7, 1<<7, 1<<7, 1<<7, 1<<7, 1<<7, 1<<7, 0, + 1<<6, 1<<6, 1<<6, 1<<6, 1<<11, 1<<10, 1<<9, 1<<8, 1<<7, 1<<6, 1<<6, 1<<6, 1<<6, 1<<6, 1<<6, 0, + 1<<5, 1<<5, 1<<5, 1<<5, 1<<5, 1<<10, 1<<9, 1<<8, 1<<7, 1<<6, 1<<5, 1<<5, 1<<5, 1<<5, 1<<5, 0, + 0, 1<<4, 1<<4, 1<<4, 1<<4, 1<<4, 1<<9, 1<<8, 1<<7, 1<<6, 1<<5, 1<<4, 1<<4, 1<<4, 1<<4, 0, + 0, 0, 1<<3, 1<<3, 1<<3, 1<<3, 1<<3, 1<<8, 1<<7, 1<<6, 1<<5, 1<<4, 1<<3, 1<<3, 1<<3, 0, + 0, 0, 0, 1<<2, 1<<2, 1<<2, 1<<2, 1<<2, 1<<7, 1<<6, 1<<5, 1<<4, 1<<3, 1<<2, 1<<2, 0, + 0, 0, 0, 0, 1<<1, 1<<1, 1<<1, 1<<1, 1<<1, 1<<6, 1<<5, 1<<4, 1<<3, 1<<2, 1<<1], + [// Direction 3 + 0, 0, 0, 0, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 1<<15, 0, + 0, 0, 0, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<14, 1<<15, 0, + 0, 0, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<13, 1<<14, 1<<15, 0, + 0, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<12, 1<<13, 1<<14, 1<<15, 0, + 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, 0, + 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, 0, + 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<9, 0, + 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<8, 1<<8, 0, + 1<<7, 1<<7, 1<<7, 1<<7, 1<<7, 1<<7, 1<<7, 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<7, 1<<7, 1<<7, 0, + 1<<6, 1<<6, 1<<6, 1<<6, 1<<6, 1<<6, 1<<7, 1<<8, 1<<9, 1<<10, 1<<11, 1<<6, 1<<6, 1<<6, 1<<6, 0, + 1<<5, 1<<5, 1<<5, 1<<5, 1<<5, 1<<6, 1<<7, 1<<8, 1<<9, 1<<10, 1<<5, 1<<5, 1<<5, 1<<5, 1<<5, 0, + 1<<4, 1<<4, 1<<4, 1<<4, 1<<5, 1<<6, 1<<7, 1<<8, 1<<9, 1<<4, 1<<4, 1<<4, 1<<4, 1<<4, 0, 0, + 1<<3, 1<<3, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, 1<<8, 1<<3, 1<<3, 1<<3, 1<<3, 1<<3, 0, 0, 0, + 1<<2, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, 1<<2, 1<<2, 1<<2, 1<<2, 1<<2, 0, 0, 0, 0, + 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<1, 1<<1, 1<<1, 1<<1, 1<<1, 0, 0, 0, 0] + ]; + +/// A table to encode each location to an index in the bitboard for 4 direction +#[rustfmt::skip] +const MAPMOVEIDX: [[i32; 239]; 4] = [ [// Direction 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14], + [// Direction 1 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], + [// Direction 2 + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 0, + 2, 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 0, + 3, 2, 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 0, + 4, 3, 2, 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, + 5, 4, 3, 2, 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 0, + 0, 5, 4, 3, 2, 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 0, + 0, 0, 5, 4, 3, 2, 1, 15, 14, 13, 12, 11, 10, 9, 8, 0, + 0, 0, 0, 5, 4, 3, 2, 1, 15, 14, 13, 12, 11, 10, 9, 0, + 0, 0, 0, 0, 5, 4, 3, 2, 1, 15, 14, 13, 12, 11, 10], + [// Direction 3 + 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, + 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 0, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 0, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 0, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 0, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 0, 0, + 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 0, 0, 0, + 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 0, 0, 0, 0, + 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 0, 0, 0, 0] + ]; + +// structures + +/// Use one-dimensional array to store the board state. The location 0 is top left.\ +/// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\ +/// 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31\ +/// ... \ +/// position 15, 31, ... are Borders.\ +/// position 0 is file 0, rank 0.\ +/// position 17 is file 1, rank 1.\ +/// +/// Use a three-dimensional array to store the bitboard.\ +/// The first dimension is color: Black, White and Empty.\ +/// The second and third one are 2 x 512-bit. Direction 0 and 2 use the first 512-bit. Direction 1 and +/// 3 use the second 512-bit.\ +/// Each 512-bit is a 32-bit x 16 array. Direction 0 and 1 store at bit 31-16 and Direction 2 and 3 store at bit 15-0. + +pub struct Pos { + // position + state: [Color; SQUARE_SIZE as usize], + p_turn: Side, + bitboard: [[[i32; 16]; 2]; 3], +} + +impl Pos { + pub fn init(&mut self) { + // starting position + // Set up the Border + for i in 0..SQUARE_SIZE as usize { + self.state[i] = Color::Border; + } + + // In the beginning, all is Empty + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + self.state[sq as usize] = Color::Empty; + } + } + + // first move is Black + self.p_turn = Color::Black; + + let black = Color::Black as usize; + let white = Color::White as usize; + let empty = Color::Empty as usize; + + // set up the corresponding bitboard + for i in 0..2 { + for j in 0..16 { + self.bitboard[black][i][j] = 0; + self.bitboard[white][i][j] = 0; + self.bitboard[empty][i][j] = 0; + } + } + + for i in 0..2 { + // use bit 31-16 to store direction 0 and 1 + #[rustfmt::skip] + for j in 0..FILE_SIZE as usize { + self.bitboard[empty][i][j] = (1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17); + } + } + + // use bit 15-0 to store direction 2 and 3. There are 21 for each one. We combine row1 and row16, row2 and row17, row3 and row18, row4 and row19, and row 5 and row20 + #[rustfmt::skip] + for i in 0..2 { + self.bitboard[empty][i][0] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11); //row 0 + self.bitboard[empty][i][1] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)/*row1*/|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1);//row16 + self.bitboard[empty][i][2] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)/*row2*/|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1);//row17 + self.bitboard[empty][i][3] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)/*row3*/|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1);//row18 + self.bitboard[empty][i][4] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)/*row4*/|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1);//row19 + self.bitboard[empty][i][5] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)/*row5*/|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1);//row20 + self.bitboard[empty][i][6] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5);//row6 + self.bitboard[empty][i][7] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4);//row7 + self.bitboard[empty][i][8] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3);//row8 + self.bitboard[empty][i][9] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2);//row9 + self.bitboard[empty][i][10] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1);//row10 + self.bitboard[empty][i][11] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2);//row11 + self.bitboard[empty][i][12] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3);//row12 + self.bitboard[empty][i][13] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4);//row13 + self.bitboard[empty][i][14] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5);//row14 + self.bitboard[empty][i][15] |= (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6);//row15 + } + } + + pub fn do_move(&mut self, mv: Move) { + let atk: Side = self.p_turn; + let def: Side = side_opp(atk); + + let mv = mv as usize; + let black = Color::Black as usize; + let white = Color::White as usize; + let empty = Color::Empty as usize; + + match self.p_turn { + Color::Black => { + self.state[mv as usize] = Color::Black; + // update black move and remove empty move in bitboard + self.bitboard[black][0][MAPMOVEIDX[0][mv] as usize] |= MAPMOVEVALUE[0][mv]; + self.bitboard[empty][0][MAPMOVEIDX[0][mv] as usize] ^= MAPMOVEVALUE[0][mv]; + self.bitboard[black][1][MAPMOVEIDX[1][mv] as usize] |= MAPMOVEVALUE[1][mv]; + self.bitboard[empty][1][MAPMOVEIDX[1][mv] as usize] ^= MAPMOVEVALUE[1][mv]; + self.bitboard[black][0][MAPMOVEIDX[2][mv] as usize] |= MAPMOVEVALUE[2][mv]; + self.bitboard[empty][0][MAPMOVEIDX[2][mv] as usize] ^= MAPMOVEVALUE[2][mv]; + self.bitboard[black][1][MAPMOVEIDX[3][mv] as usize] |= MAPMOVEVALUE[3][mv]; + self.bitboard[empty][1][MAPMOVEIDX[3][mv] as usize] ^= MAPMOVEVALUE[3][mv]; + } + Color::White => { + self.state[mv as usize] = Color::White; + // update white move and remove empty move in bitboard + self.bitboard[white][0][MAPMOVEIDX[0][mv] as usize] |= MAPMOVEVALUE[0][mv]; + self.bitboard[empty][0][MAPMOVEIDX[0][mv] as usize] ^= MAPMOVEVALUE[0][mv]; + self.bitboard[white][1][MAPMOVEIDX[1][mv] as usize] |= MAPMOVEVALUE[1][mv]; + self.bitboard[empty][1][MAPMOVEIDX[1][mv] as usize] ^= MAPMOVEVALUE[1][mv]; + self.bitboard[white][0][MAPMOVEIDX[2][mv] as usize] |= MAPMOVEVALUE[2][mv]; + self.bitboard[empty][0][MAPMOVEIDX[2][mv] as usize] ^= MAPMOVEVALUE[2][mv]; + self.bitboard[white][1][MAPMOVEIDX[3][mv] as usize] |= MAPMOVEVALUE[3][mv]; + self.bitboard[empty][1][MAPMOVEIDX[3][mv] as usize] ^= MAPMOVEVALUE[3][mv]; + } + _ => panic! {}, + } + + self.p_turn = def; + } + + fn turn(&self) -> Side { + self.p_turn + } + + pub fn can_play(&self, from: Square) -> bool { + if self.state[from as usize] == Color::Empty { + true + } else { + false + } + } +} + +pub struct List { + // legal move list + p_move: [Move; (FILE_SIZE * RANK_SIZE) as usize], + p_size: i32, +} + +/// Use List to store legal moves. +impl List { + pub fn clear(&mut self) { + self.p_size = 0; + } + + pub fn add(&mut self, mv: Move) { + self.p_move[self.p_size as usize] = mv; + self.p_size += 1; + } + + pub fn size(&self) -> i32 { + self.p_size + } + + pub fn shuffle(&mut self) { + let mut rng = thread_rng(); + let num = self.p_size; + let mut new_move: Vec = vec![]; + + for x in 0..(num as usize) { + new_move.push(self.p_move[x]); + } + + new_move.shuffle(&mut rng); + + for x in 0..(self.p_size as usize) { + self.p_move[x] = new_move[x]; + } + } +} + +// functions + +fn square_make(fl: i32, rk: i32) -> Square { + rk * (FILE_SIZE + 1) + fl +} + +fn side_opp(sd: Side) -> Side { + match sd { + Side::White => Side::Black, + Side::Black => Side::White, + _ => panic!(""), + } +} + +fn pos_is_winner(pos: &Pos) -> bool { + let current_side = side_opp(pos.p_turn); + check_pattern5(&pos, current_side) +} + +fn pos_is_draw(pos: &Pos) -> bool { + let mut found: bool = true; + + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + if pos.can_play(sq) { + found = false; + break; + } + + if found == false { + break; + } + } + } + + let mut out: bool = false; + if found == true && !pos_is_winner(pos) { + out = true; + } + + out +} + +#[target_feature(enable = "avx512f,avx512bw")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +unsafe fn pos_is_draw_avx512(pos: &Pos) -> bool { + let empty = Color::Empty as usize; + + let board0org = _mm512_loadu_epi32(&pos.bitboard[empty][0][0]); + + let answer = _mm512_set1_epi32(0); + + // if all empty is 0, all board is filled. + let temp_mask = _mm512_mask_cmpneq_epi32_mask(0b11111111_11111111, answer, board0org); + + if _popcnt32(temp_mask as i32) == 0 && !pos_is_winner_avx512(pos) { + return true; + } else { + return false; + } +} + +fn pos_is_end(pos: &Pos) -> bool { + if pos_is_winner(pos) || pos_is_draw(pos) { + true + } else { + false + } +} + +fn pos_disp(pos: &Pos) { + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + + match pos.state[sq as usize] { + Color::Black => print!("# "), + Color::White => print!("O "), + Color::Empty => print!("- "), + Color::Border => print!("| "), + } + } + + println!(""); + } + + match pos.turn() { + Color::Black => println!("black to play"), + Color::White => println!("white to play"), + _ => panic!(), + } +} + +fn gen_moves(list: &mut List, pos: &Pos) { + list.clear(); + + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + if pos.can_play(sq) { + list.add(sq); + } + } + } +} + +/// AI: use Minimax search with alpha-beta pruning +fn search(pos: &Pos, alpha: i32, beta: i32, depth: i32, _ply: i32) -> i32 { + assert!(-EVAL_INF <= alpha && alpha < beta && beta <= EVAL_INF); + // leaf? + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("avx512bw") { + unsafe { + if pos_is_winner_avx512(&pos) { + return -EVAL_INF + _ply; + } + + if pos_is_draw_avx512(&pos) { + return 0; + } + } + } else { + if pos_is_winner(&pos) { + return -EVAL_INF + _ply; + } + + if pos_is_draw(&pos) { + return 0; + } + } + } + + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + if pos_is_winner(&pos) { + return -EVAL_INF + _ply; + } + + if pos_is_draw(&pos) { + return 0; + } + } + + if depth == 0 { + return eval(&pos, _ply); + } + + let p_move_new: [Move; (FILE_SIZE * RANK_SIZE) as usize] = + [0; (FILE_SIZE * RANK_SIZE) as usize]; + + let mut list = List { + p_move: p_move_new, + p_size: 0, + }; + + let mut bm: Move = MOVE_NONE; + let mut bs: i32 = SCORE_NONE; + + gen_moves(&mut list, &pos); + + // move loop + + if _ply == 0 { + list.shuffle(); + } + + for i in 0..list.size() { + if bs < beta { + let mv: Move = list.p_move[i as usize]; + + let mut new_pos = Pos { + state: pos.state, + p_turn: pos.p_turn, + bitboard: pos.bitboard, + }; + + new_pos.do_move(mv); + + let sc: i32 = -search(&new_pos, -beta, -cmp::max(alpha, bs), depth - 1, _ply + 1); + + if sc > bs { + bm = mv; + bs = sc; + } + } + } + + assert!(bm != MOVE_NONE); + assert!(bs >= -EVAL_INF && bs <= EVAL_INF); + + if _ply == 0 { + bm + } else { + bs + } //best move at the root node, best score elsewhere +} + +/// Evaluation function: give different scores to different patterns after a fixed depth. +fn eval(pos: &Pos, _ply: i32) -> i32 { + let atk: Side = pos.turn(); + let def: Side = side_opp(atk); + + // check if opp has live4 which will win playing next move + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("avx512bw") { + unsafe { + if check_patternlive4_avx512(&pos, def) { + return -4096; + } + } + } else { + if check_patternlive4(&pos, def) { + return -4096; + } + } + } + + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + if check_patternlive4(&pos, def) { + return -4096; + } + } + + // check if self has live4 which will win playing next move + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("avx512bw") { + unsafe { + if check_patternlive4_avx512(&pos, atk) { + return 2560; + } + } + } else { + if check_patternlive4(&pos, atk) { + return 2560; + } + } + } + + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + if check_patternlive4(&pos, atk) { + return 2560; + } + } + + // check if self has dead4 which will win playing next move + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("avx512bw") { + unsafe { + if check_patterndead4_avx512(&pos, atk) > 0 { + return 2560; + } + } + } else { + if check_patterndead4(&pos, atk) > 0 { + return 2560; + } + } + } + + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + if check_patterndead4(&pos, atk) > 0 { + return 2560; + } + } + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("avx512bw") { + unsafe { + let n_c4: i32 = check_patterndead4_avx512(&pos, def); + let n_c3: i32 = check_patternlive3_avx512(&pos, def); + + // check if opp has 2 dead4 which will win playing next move + if n_c4 > 1 { + return -2048; + } + + // check if opp has a dead 4 and live 3 which will win playing the next two move + if n_c4 == 1 && n_c3 > 0 { + return -2048; + } + + if check_patternlive3_avx512(&pos, atk) > 1 { + return 2560; + } + + // check if opp has 2 live3 which will win playing the next two move + if n_c3 > 1 { + return -2048; + } + } + } else { + let n_c4: i32 = check_patterndead4(&pos, def); + let n_c3: i32 = check_patternlive3(&pos, def); + + // check if opp has 2 dead4 which will win playing next move + if n_c4 > 1 { + return -2048; + } + + // check if opp has a dead 4 and live 3 which will win playing the next two move + if n_c4 == 1 && n_c3 > 0 { + return -2048; + } + + // check if self has 2 live3 which will win playing the next two move + if check_patternlive3(&pos, atk) > 1 { + return 2560; + } + + // check if opp has 2 live3 which will win playing the next two move + if n_c3 > 1 { + return -2048; + } + } + } + + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + let n_c4: i32 = check_patterndead4(&pos, def); + let n_c3: i32 = check_patternlive3(&pos, def); + + // check if opp has 2 dead4 which will win playing next move + if n_c4 > 1 { + return -2048; + } + + // check if opp has a dead 4 and live 3 which will win playing the next two move + if n_c4 == 1 && n_c3 > 0 { + return -2048; + } + + // check if self has 2 live3 which will win playing the next two move + if check_patternlive3(&pos, atk) > 1 { + return 2560; + } + + // check if opp has 2 live3 which will win playing the next two move + if n_c3 > 1 { + return -2048; + } + } + + 0 +} + +/// Check OOOOO +fn check_pattern5(pos: &Pos, sd: Side) -> bool { + let mut n: i32 = 0; + + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + + for pat in 0..4 { + let idx0 = sq; + let idx1 = sq + DIRECTION[pat][0]; + let idx2 = sq + DIRECTION[pat][1]; + let idx3 = sq + DIRECTION[pat][2]; + let idx4 = sq + DIRECTION[pat][3]; + + let val0 = pos.state[idx0 as usize]; + let val1 = pos.state[idx1 as usize]; + let val2 = pos.state[idx2 as usize]; + let val3 = pos.state[idx3 as usize]; + let val4 = pos.state[idx4 as usize]; + + #[rustfmt::skip] + if val0 == sd && val1 == sd && val2 == sd && val3 == sd && val4 == sd { n += 1; } + } + } + } + + if n > 0 { + true + } else { + false + } +} + +/// Check -OOOO- +fn check_patternlive4(pos: &Pos, sd: Side) -> bool { + let mut n: i32 = 0; + + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + + for pat in 0..4 { + let idx0 = sq; + let idx1 = sq + DIRECTION[pat][0]; + let idx2 = sq + DIRECTION[pat][1]; + let idx3 = sq + DIRECTION[pat][2]; + let idx4 = sq + DIRECTION[pat][3]; + let idx5 = sq + DIRECTION[pat][4]; + + let val0 = pos.state[idx0 as usize]; + let val1 = pos.state[idx1 as usize]; + let val2 = pos.state[idx2 as usize]; + let val3 = pos.state[idx3 as usize]; + let val4 = pos.state[idx4 as usize]; + let val5 = pos.state[idx5 as usize]; + + #[rustfmt::skip] + if val0 == Color::Empty && val1 == sd && val2 == sd && val3 == sd && val4 == sd && val5 == Color::Empty { n += 1; } + } + } + } + + if n > 0 { + true + } else { + false + } +} + +/// Check OOOO-, OOO-O, OO-OO, O-OOO, -OOOO +fn check_patterndead4(pos: &Pos, sd: Side) -> i32 { + let mut n: i32 = 0; + + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + + for dir in 0..4 { + let idx0 = sq; + let idx1 = sq + DIRECTION[dir][0]; + let idx2 = sq + DIRECTION[dir][1]; + let idx3 = sq + DIRECTION[dir][2]; + let idx4 = sq + DIRECTION[dir][3]; + + let val0 = pos.state[idx0 as usize]; + let val1 = pos.state[idx1 as usize]; + let val2 = pos.state[idx2 as usize]; + let val3 = pos.state[idx3 as usize]; + let val4 = pos.state[idx4 as usize]; + + #[rustfmt::skip] + if val0 == sd && val1 == sd && val2 == sd && val3 == sd && val4 == Color::Empty { n += 1; } + #[rustfmt::skip] + if val0 == sd && val1 == sd && val2 == sd && val3 == Color::Empty && val4 == sd { n += 1; } + #[rustfmt::skip] + if val0 == sd && val1 == sd && val2 == Color::Empty && val3 == sd && val4 == sd { n += 1; } + #[rustfmt::skip] + if val0 == sd && val1 == Color::Empty && val2 == sd && val3 == sd && val4 == sd { n += 1; } + #[rustfmt::skip] + if val0 == Color::Empty && val1 == sd && val2 == sd && val3 == sd && val4 == sd { n += 1; } + } + } + } + + n +} + +/// Check -OOO-, -OO-O-, -O-OO-
+fn check_patternlive3(pos: &Pos, sd: Side) -> i32 { + let mut n: i32 = 0; + + for rk in 0..RANK_SIZE { + for fl in 0..FILE_SIZE { + let sq: Square = square_make(fl, rk); + + for dir in 0..4 { + let idx0 = sq; + let idx1 = sq + DIRECTION[dir][0]; + let idx2 = sq + DIRECTION[dir][1]; + let idx3 = sq + DIRECTION[dir][2]; + let idx4 = sq + DIRECTION[dir][3]; + let idx5 = sq + DIRECTION[dir][4]; + + let val0 = pos.state[idx0 as usize]; + let val1 = pos.state[idx1 as usize]; + let val2 = pos.state[idx2 as usize]; + let val3 = pos.state[idx3 as usize]; + let val4 = pos.state[idx4 as usize]; + let val5 = pos.state[idx5 as usize]; + + #[rustfmt::skip] + if val0 == Color::Empty && val1 == sd && val2 == sd && val3 == sd && val4 == Color::Empty { n +=1; } + #[rustfmt::skip] + if val0 == Color::Empty && val1 == sd && val2 == sd && val3 == Color::Empty && val4 == sd && val5 == Color::Empty { n += 1; } + #[rustfmt::skip] + if val0 == Color::Empty && val1 == sd && val2 == Color::Empty && val3 == sd && val4 == sd && val5 == Color::Empty { n += 1; } + } + } + } + + n +} + +#[target_feature(enable = "avx512f,avx512bw")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +unsafe fn pos_is_winner_avx512(pos: &Pos) -> bool { + let current_side = side_opp(pos.p_turn); + let coloridx = current_side as usize; + + let board0org: [__m512i; 2] = [ + _mm512_loadu_epi32(&pos.bitboard[coloridx][0][0]), + _mm512_loadu_epi32(&pos.bitboard[coloridx][1][0]), + ]; // load states from bitboard + + #[rustfmt::skip] + let answer = _mm512_set1_epi16((1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)); // an unbroken chain of five moves + + // use Mask to filter out which data is not processed. + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + // 1 x x x x _ _ _ _ _ _ _ _ _ _ _ 0 x o x o x 0 0 0 0 0 0 0 0 0 0 0 + // 2 x _ _ _ _ o _ x o _ _ _ _ _ _ 0 x o _ _ _ _ _| x x o o o x x _ _ + // . ... + // . ... + // . ... + // 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 x o x o o o o o o o 0 0 0 0 0 0 + // + // answer_mask[0]: 01_11..............: "0" is in row 16 and column 1-16. + // There is no data to match (x = black, o = white, _ = empty, 0 = no data). + // + // + // Then, shift one space left. + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + // 1 x x x _ _ _ _ _ _ _ _ _ _ _ 0 x o x o x 0 0 0 0 0 0 0 0 0 0 0 0 + // . ... + // . ... + // . ... + // 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 x o x o o o o o o o 0 0 0 0 0 0 0 + // answer_mask[1]: ................_10: "0" is in row 1 and column 17-32; + // There is no enough data to match (o x o x but we want to match o o o o o). + // + // answer_mask[2]: mix 2 data together (column 17-23 and column 24-32). Using Mask to make it match correctly. + // For example, column 23,24,25,26,27 is not a pattern and 24,25,26,27,28 is a pattern. + // That is why some mask bits are set to 0 from answer_mask[2] to answer_mask[10]. + + #[rustfmt::skip] + let answer_mask: [__mmask32; 11] = [0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_11, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_10_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_10_10_10_10_10, + 0b00_11_11_11_11_11_11_11_11_11_10_10_10_10_11_10, + 0b00_10_11_11_11_11_11_11_11_10_10_10_10_11_11_10, + 0b00_10_10_11_11_11_11_11_10_10_10_10_11_11_11_10, + 0b00_10_10_10_11_11_11_10_10_10_10_11_11_11_11_10, + 0b00_10_10_10_10_11_10_10_10_10_11_11_11_11_11_10]; + let mut count_match: i32 = 0; + + for dir in 0..2 { + // direction 0 and 1 + let mut board0 = board0org[dir]; + let boardf = _mm512_and_si512(answer, board0); + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[0], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + + for i in 1..11 { + // OOOOOOOOOOO----, the last 4 "-" cannot make an unbroken chain of five. + board0 = _mm512_slli_epi32(board0, 1); // shift one space left + let boardf = _mm512_and_si512(answer, board0); // focus on the pattern + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[i], answer, boardf); // see if it matches the pattern + count_match += _popcnt32(temp_mask as i32); + } + } + + if count_match > 0 { + return true; + } else { + return false; + } +} + +#[target_feature(enable = "avx512f,avx512bw")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +unsafe fn check_patternlive4_avx512(pos: &Pos, sd: Side) -> bool { + let coloridx = sd as usize; + let emptyidx = Color::Empty as usize; + + #[rustfmt::skip] + let answer_color = _mm512_set1_epi16( (1<<14)|(1<<13)|(1<<12)|(1<<11) ); + #[rustfmt::skip] + let answer_empty = _mm512_set1_epi16( (1<<15)| (1<<10) ); + #[rustfmt::skip] + let answer = _mm512_set1_epi16( (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10) ); + + #[rustfmt::skip] + let answer_mask: [__mmask32; 10] = [0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_10_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_10_10_10_10_10, + 0b00_11_11_11_11_11_11_11_11_11_10_10_10_10_10_10, + 0b00_10_11_11_11_11_11_11_11_10_10_10_10_10_11_10, + 0b00_10_10_11_11_11_11_11_10_10_10_10_10_11_11_10, + 0b00_10_10_10_11_11_11_10_10_10_10_10_11_11_11_10, + 0b00_10_10_10_10_11_10_10_10_10_10_11_11_11_11_10]; + let board0org: [__m512i; 2] = [ + _mm512_loadu_epi32(&pos.bitboard[coloridx][0][0]), + _mm512_loadu_epi32(&pos.bitboard[coloridx][1][0]), + ]; + let board1org: [__m512i; 2] = [ + _mm512_loadu_epi32(&pos.bitboard[emptyidx][0][0]), + _mm512_loadu_epi32(&pos.bitboard[emptyidx][1][0]), + ]; + + let mut count_match: i32 = 0; + + for dir in 0..2 { + let mut board0 = board0org[dir]; + let mut board1 = board1org[dir]; + + let boardf1 = _mm512_and_si512(answer_color, board0); + let boardf2 = _mm512_and_si512(answer_empty, board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[0], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + + for i in 1..10 { + board0 = _mm512_slli_epi32(board0, 1); + board1 = _mm512_slli_epi32(board1, 1); + + let boardf1 = _mm512_and_si512(answer_color, board0); + let boardf2 = _mm512_and_si512(answer_empty, board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[i], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + } + } + + if count_match > 0 { + return true; + } else { + return false; + } +} + +#[target_feature(enable = "avx512f,avx512bw")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +unsafe fn check_patterndead4_avx512(pos: &Pos, sd: Side) -> i32 { + let coloridx = sd as usize; + let emptyidx = Color::Empty as usize; + + #[rustfmt::skip] + let answer_color: [__m512i; 5] = [_mm512_set1_epi16( (1<<14)|(1<<13)|(1<<12)|(1<<11) ), + _mm512_set1_epi16( (1<<15)| (1<<13)|(1<<12)|(1<<11) ), + _mm512_set1_epi16( (1<<15)|(1<<14) |(1<<12)|(1<<11) ), + _mm512_set1_epi16( (1<<15)|(1<<14)|(1<<13) |(1<<11) ), + _mm512_set1_epi16( (1<<15)|(1<<14)|(1<<13)|(1<<12) )]; + #[rustfmt::skip] + let answer_empty: [__m512i; 5]= [_mm512_set1_epi16( 1<<15 ), + _mm512_set1_epi16( 1<<14 ), + _mm512_set1_epi16( 1<<13 ), + _mm512_set1_epi16( 1<<12 ), + _mm512_set1_epi16( 1<<11)]; + #[rustfmt::skip] + let answer = _mm512_set1_epi16( (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)); + + #[rustfmt::skip] + let answer_mask: [__mmask32; 11] = [0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_11, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_10_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_10_10_10_10_10, + 0b00_11_11_11_11_11_11_11_11_11_10_10_10_10_11_10, + 0b00_10_11_11_11_11_11_11_11_10_10_10_10_11_11_10, + 0b00_10_10_11_11_11_11_11_10_10_10_10_11_11_11_10, + 0b00_10_10_10_11_11_11_10_10_10_10_11_11_11_11_10, + 0b00_10_10_10_10_11_10_10_10_10_11_11_11_11_11_10]; + let board0org: [__m512i; 2] = [ + _mm512_loadu_epi32(&pos.bitboard[coloridx][0][0]), + _mm512_loadu_epi32(&pos.bitboard[coloridx][1][0]), + ]; + let board1org: [__m512i; 2] = [ + _mm512_loadu_epi32(&pos.bitboard[emptyidx][0][0]), + _mm512_loadu_epi32(&pos.bitboard[emptyidx][1][0]), + ]; + + let mut count_match: i32 = 0; + + for pattern in 0..5 { + for dir in 0..2 { + let mut board0 = board0org[dir]; + let mut board1 = board1org[dir]; + + let boardf1 = _mm512_and_si512(answer_color[pattern], board0); + let boardf2 = _mm512_and_si512(answer_empty[pattern], board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[0], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + + for i in 1..11 { + board0 = _mm512_slli_epi32(board0, 1); + board1 = _mm512_slli_epi32(board1, 1); + + let boardf1 = _mm512_and_si512(answer_color[pattern], board0); + let boardf2 = _mm512_and_si512(answer_empty[pattern], board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[i], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + } + } + } + + count_match +} + +#[target_feature(enable = "avx512f,avx512bw")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +unsafe fn check_patternlive3_avx512(pos: &Pos, sd: Side) -> i32 { + let coloridx = sd as usize; + let emptyidx = Color::Empty as usize; + + #[rustfmt::skip] + let board0org: [__m512i; 2] = [_mm512_loadu_epi32(&pos.bitboard[coloridx][0][0]), _mm512_loadu_epi32(&pos.bitboard[coloridx][1][0])]; + #[rustfmt::skip] + let board1org: [__m512i; 2] = [_mm512_loadu_epi32(&pos.bitboard[emptyidx][0][0]), _mm512_loadu_epi32(&pos.bitboard[emptyidx][1][0])]; + + #[rustfmt::skip] + let answer_color: [__m512i; 1] = [_mm512_set1_epi16( (1<<14)|(1<<13)|(1<<12) )]; + #[rustfmt::skip] + let answer_empty: [__m512i; 1] = [_mm512_set1_epi16( (1<<15)| (1<<11) )]; + #[rustfmt::skip] + let answer: __m512i = _mm512_set1_epi16( (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11) ); + + let mut count_match: i32 = 0; + + #[rustfmt::skip] + let answer_mask: [__mmask32; 11] = [0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_11, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_10_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_10_10_10_10_10, + 0b00_11_11_11_11_11_11_11_11_11_10_10_10_10_11_10, + 0b00_10_11_11_11_11_11_11_11_10_10_10_10_11_11_10, + 0b00_10_10_11_11_11_11_11_10_10_10_10_11_11_11_10, + 0b00_10_10_10_11_11_11_10_10_10_10_11_11_11_11_10, + 0b00_10_10_10_10_11_10_10_10_10_11_11_11_11_11_10]; + for pattern in 0..1 { + for dir in 0..2 { + let mut board0 = board0org[dir]; + let mut board1 = board1org[dir]; + + let boardf1 = _mm512_and_si512(answer_color[pattern], board0); + let boardf2 = _mm512_and_si512(answer_empty[pattern], board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[0], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + + for i in 1..11 { + board0 = _mm512_slli_epi32(board0, 1); + board1 = _mm512_slli_epi32(board1, 1); + + let boardf1 = _mm512_and_si512(answer_color[pattern], board0); + let boardf2 = _mm512_and_si512(answer_empty[pattern], board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[i], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + } + } + } + + #[rustfmt::skip] + let answer_color: [__m512i; 2] = [_mm512_set1_epi16( (1<<14)| (1<<12)|(1<<11) ), + _mm512_set1_epi16( (1<<14)|(1<<13) |(1<<11) )]; + #[rustfmt::skip] + let answer_empty: [__m512i; 2] = [_mm512_set1_epi16( (1<<15)| (1<<13)| (1<<10) ), + _mm512_set1_epi16( (1<<15)| (1<<12)| (1<<10) )]; + #[rustfmt::skip] + let answer: __m512i = _mm512_set1_epi16( (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10) ); + + #[rustfmt::skip] + let answer_mask: [__mmask32; 10] = [0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_11_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_11_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_11_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_11_10_10_10_10, + 0b01_11_11_11_11_11_11_11_11_11_11_10_10_10_10_10, + 0b00_11_11_11_11_11_11_11_11_11_10_10_10_10_10_10, + 0b00_10_11_11_11_11_11_11_11_10_10_10_10_10_11_10, + 0b00_10_10_11_11_11_11_11_10_10_10_10_10_11_11_10, + 0b00_10_10_10_11_11_11_10_10_10_10_10_11_11_11_10, + 0b00_10_10_10_10_11_10_10_10_10_10_11_11_11_11_10]; + for pattern in 0..2 { + for dir in 0..2 { + let mut board0 = board0org[dir]; + let mut board1 = board1org[dir]; + + let boardf1 = _mm512_and_si512(answer_color[pattern], board0); + let boardf2 = _mm512_and_si512(answer_empty[pattern], board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[0], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + + for i in 1..10 { + board0 = _mm512_slli_epi32(board0, 1); + board1 = _mm512_slli_epi32(board1, 1); + + let boardf1 = _mm512_and_si512(answer_color[pattern], board0); + let boardf2 = _mm512_and_si512(answer_empty[pattern], board1); + let boardf = _mm512_or_si512(boardf1, boardf2); + + let temp_mask = _mm512_mask_cmpeq_epi16_mask(answer_mask[i], answer, boardf); + count_match += _popcnt32(temp_mask as i32); + } + } + } + + count_match +} + +fn main() { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("avx512bw") { + println!("\n\nThe program is running with avx512f and avx512bw intrinsics\n\n"); + } else { + println!("\n\nThe program is running with NO intrinsics.\n\n"); + } + } + + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] + { + println!("\n\nThe program is running with NO intrinsics.\n\n"); + } + + loop { + let start = Instant::now(); + + println!("Hello, this is Connect5 (Outer-Open Gomoku)!"); + println!("Self-playing with search depth = 4"); + + let test_state: [Color; SQUARE_SIZE as usize] = [Color::Empty; SQUARE_SIZE as usize]; + let test_bitboard: [[[i32; 16]; 2]; 3] = [[[0; 16]; 2]; 3]; + + let mut test1 = Pos { + state: test_state, + p_turn: Color::Black, + bitboard: test_bitboard, + }; + + test1.init(); + + let mut count: i32 = 0; + + for i in 0..(FILE_SIZE * RANK_SIZE) { + let mut next_move: Move = square_make(1, 7); // set the first move is (1,7) + + if i > 0 { + next_move = search(&test1, -EVAL_INF, EVAL_INF, 4, 0); + } // search depth = 4 + + test1.do_move(next_move); + pos_disp(&test1); + + if pos_is_end(&test1) { + println!("Game over!!!!!! at Move {}", i); + count = i + 1; + break; + } + } + + let duration = start.elapsed(); + + println!( + "Average time for each move is: {:?}", + duration / count as u32 + ); + } +} diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs index d4b37284ea..7869ba2c04 100644 --- a/library/test/src/bench.rs +++ b/library/test/src/bench.rs @@ -1,8 +1,10 @@ //! Benchmarking module. -pub use std::hint::black_box; - use super::{ - event::CompletedTest, options::BenchMode, test_result::TestResult, types::TestDesc, Sender, + event::CompletedTest, + options::BenchMode, + test_result::TestResult, + types::{TestDesc, TestId}, + Sender, }; use crate::stats; @@ -12,6 +14,15 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; +/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what +/// `black_box` could do. +/// +/// See [`std::hint::black_box`] for details. +#[inline(always)] +pub fn black_box(dummy: T) -> T { + std::hint::black_box(dummy) +} + /// Manager of the benchmarking runs. /// /// This is fed into functions marked with `#[bench]` to allow for @@ -177,8 +188,13 @@ where } } -pub fn benchmark(desc: TestDesc, monitor_ch: Sender, nocapture: bool, f: F) -where +pub fn benchmark( + id: TestId, + desc: TestDesc, + monitor_ch: Sender, + nocapture: bool, + f: F, +) where F: FnMut(&mut Bencher), { let mut bs = Bencher { mode: BenchMode::Auto, summary: None, bytes: 0 }; @@ -213,7 +229,7 @@ where }; let stdout = data.lock().unwrap().to_vec(); - let message = CompletedTest::new(desc, test_result, None, stdout); + let message = CompletedTest::new(id, desc, test_result, None, stdout); monitor_ch.send(message).unwrap(); } diff --git a/library/test/src/event.rs b/library/test/src/event.rs index 2103a0d10f..206f3e10e8 100644 --- a/library/test/src/event.rs +++ b/library/test/src/event.rs @@ -3,10 +3,11 @@ use super::test_result::TestResult; use super::time::TestExecTime; -use super::types::TestDesc; +use super::types::{TestDesc, TestId}; #[derive(Debug, Clone)] pub struct CompletedTest { + pub id: TestId, pub desc: TestDesc, pub result: TestResult, pub exec_time: Option, @@ -15,12 +16,13 @@ pub struct CompletedTest { impl CompletedTest { pub fn new( + id: TestId, desc: TestDesc, result: TestResult, exec_time: Option, stdout: Vec, ) -> Self { - Self { desc, result, exec_time, stdout } + Self { id, desc, result, exec_time, stdout } } } diff --git a/library/test/src/helpers/exit_code.rs b/library/test/src/helpers/exit_code.rs index 31e234d981..50bb260762 100644 --- a/library/test/src/helpers/exit_code.rs +++ b/library/test/src/helpers/exit_code.rs @@ -4,7 +4,7 @@ use std::process::ExitStatus; #[cfg(not(unix))] pub fn get_exit_code(status: ExitStatus) -> Result { - status.code().ok_or("received no exit code from child process".into()) + status.code().ok_or_else(|| "received no exit code from child process".into()) } #[cfg(unix)] diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 3415eaa9fb..9adc099aaa 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -24,8 +24,8 @@ #![feature(rustc_private)] #![feature(nll)] #![feature(available_concurrency)] +#![feature(bench_black_box)] #![feature(internal_output_capture)] -#![feature(option_unwrap_none)] #![feature(panic_unwind)] #![feature(staged_api)] #![feature(termination_trait_lib)] @@ -55,7 +55,7 @@ pub mod test { time::{TestExecTime, TestTimeOptions}, types::{ DynTestFn, DynTestName, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, - TestDescAndFn, TestName, TestType, + TestDescAndFn, TestId, TestName, TestType, }, }; } @@ -216,9 +216,10 @@ where // Use a deterministic hasher type TestMap = - HashMap>; + HashMap>; struct TimeoutEntry { + id: TestId, desc: TestDesc, timeout: Instant, } @@ -250,7 +251,9 @@ where let (filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests .into_iter() - .partition(|e| matches!(e.testfn, StaticTestFn(_) | DynTestFn(_))); + .enumerate() + .map(|(i, e)| (TestId(i), e)) + .partition(|(_, e)| matches!(e.testfn, StaticTestFn(_) | DynTestFn(_))); let concurrency = opts.test_threads.unwrap_or_else(get_concurrency); @@ -279,7 +282,7 @@ where break; } let timeout_entry = timeout_queue.pop_front().unwrap(); - if running_tests.contains_key(&timeout_entry.desc) { + if running_tests.contains_key(&timeout_entry.id) { timed_out.push(timeout_entry.desc); } } @@ -295,11 +298,12 @@ where if concurrency == 1 { while !remaining.is_empty() { - let test = remaining.pop().unwrap(); + let (id, test) = remaining.pop().unwrap(); let event = TestEvent::TeWait(test.desc.clone()); notify_about_test_event(event)?; - run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::No) - .unwrap_none(); + let join_handle = + run_test(opts, !opts.run_tests, id, test, run_strategy, tx.clone(), Concurrent::No); + assert!(join_handle.is_none()); let completed_test = rx.recv().unwrap(); let event = TestEvent::TeResult(completed_test); @@ -308,7 +312,7 @@ where } else { while pending > 0 || !remaining.is_empty() { while pending < concurrency && !remaining.is_empty() { - let test = remaining.pop().unwrap(); + let (id, test) = remaining.pop().unwrap(); let timeout = time::get_default_test_timeout(); let desc = test.desc.clone(); @@ -317,13 +321,14 @@ where let join_handle = run_test( opts, !opts.run_tests, + id, test, run_strategy, tx.clone(), Concurrent::Yes, ); - running_tests.insert(desc.clone(), RunningTest { join_handle }); - timeout_queue.push_back(TimeoutEntry { desc, timeout }); + running_tests.insert(id, RunningTest { join_handle }); + timeout_queue.push_back(TimeoutEntry { id, desc, timeout }); pending += 1; } @@ -352,13 +357,12 @@ where } let mut completed_test = res.unwrap(); - if let Some(running_test) = running_tests.remove(&completed_test.desc) { - if let Some(join_handle) = running_test.join_handle { - if let Err(_) = join_handle.join() { - if let TrOk = completed_test.result { - completed_test.result = - TrFailedMsg("panicked after reporting success".to_string()); - } + let running_test = running_tests.remove(&completed_test.id).unwrap(); + if let Some(join_handle) = running_test.join_handle { + if let Err(_) = join_handle.join() { + if let TrOk = completed_test.result { + completed_test.result = + TrFailedMsg("panicked after reporting success".to_string()); } } } @@ -371,10 +375,10 @@ where if opts.bench_benchmarks { // All benchmarks run at the end, in serial. - for b in filtered_benchs { + for (id, b) in filtered_benchs { let event = TestEvent::TeWait(b.desc.clone()); notify_about_test_event(event)?; - run_test(opts, false, b, run_strategy, tx.clone(), Concurrent::No); + run_test(opts, false, id, b, run_strategy, tx.clone(), Concurrent::No); let completed_test = rx.recv().unwrap(); let event = TestEvent::TeResult(completed_test); @@ -448,6 +452,7 @@ pub fn convert_benchmarks_to_tests(tests: Vec) -> Vec, @@ -461,7 +466,7 @@ pub fn run_test( && !cfg!(target_os = "emscripten"); if force_ignore || desc.ignore || ignore_because_no_process_support { - let message = CompletedTest::new(desc, TrIgnored, None, Vec::new()); + let message = CompletedTest::new(id, desc, TrIgnored, None, Vec::new()); monitor_ch.send(message).unwrap(); return None; } @@ -474,6 +479,7 @@ pub fn run_test( } fn run_test_inner( + id: TestId, desc: TestDesc, monitor_ch: Sender, testfn: Box, @@ -484,6 +490,7 @@ pub fn run_test( let runtest = move || match opts.strategy { RunStrategy::InProcess => run_test_in_process( + id, desc, opts.nocapture, opts.time.is_some(), @@ -492,6 +499,7 @@ pub fn run_test( opts.time, ), RunStrategy::SpawnPrimary => spawn_test_subprocess( + id, desc, opts.nocapture, opts.time.is_some(), @@ -530,14 +538,14 @@ pub fn run_test( match testfn { DynBenchFn(bencher) => { // Benchmarks aren't expected to panic, so we run them all in-process. - crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { + crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, |harness| { bencher.run(harness) }); None } StaticBenchFn(benchfn) => { // Benchmarks aren't expected to panic, so we run them all in-process. - crate::bench::benchmark(desc, monitor_ch, opts.nocapture, benchfn); + crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, benchfn); None } DynTestFn(f) => { @@ -546,6 +554,7 @@ pub fn run_test( _ => panic!("Cannot run dynamic test fn out-of-process"), }; run_test_inner( + id, desc, monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), @@ -553,6 +562,7 @@ pub fn run_test( ) } StaticTestFn(f) => run_test_inner( + id, desc, monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), @@ -571,6 +581,7 @@ fn __rust_begin_short_backtrace(f: F) { } fn run_test_in_process( + id: TestId, desc: TestDesc, nocapture: bool, report_time: bool, @@ -599,11 +610,12 @@ fn run_test_in_process( Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time), }; let stdout = data.lock().unwrap_or_else(|e| e.into_inner()).to_vec(); - let message = CompletedTest::new(desc, test_result, exec_time, stdout); + let message = CompletedTest::new(id, desc, test_result, exec_time, stdout); monitor_ch.send(message).unwrap(); } fn spawn_test_subprocess( + id: TestId, desc: TestDesc, nocapture: bool, report_time: bool, @@ -653,7 +665,7 @@ fn spawn_test_subprocess( (result, test_output, exec_time) })(); - let message = CompletedTest::new(desc, result, exec_time, test_output); + let message = CompletedTest::new(id, desc, result, exec_time, test_output); monitor_ch.send(message).unwrap(); } diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index e3c9b38691..6a3f31b74e 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -94,7 +94,7 @@ pub fn do_not_run_ignored_tests() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let result = rx.recv().unwrap().result; assert_ne!(result, TrOk); } @@ -113,7 +113,7 @@ pub fn ignored_tests_result_in_ignored() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let result = rx.recv().unwrap().result; assert_eq!(result, TrIgnored); } @@ -136,7 +136,7 @@ fn test_should_panic() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let result = rx.recv().unwrap().result; assert_eq!(result, TrOk); } @@ -159,7 +159,7 @@ fn test_should_panic_good_message() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let result = rx.recv().unwrap().result; assert_eq!(result, TrOk); } @@ -187,7 +187,7 @@ fn test_should_panic_bad_message() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let result = rx.recv().unwrap().result; assert_eq!(result, TrFailedMsg(failed_msg.to_string())); } @@ -219,7 +219,7 @@ fn test_should_panic_non_string_message_type() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&TestOpts::new(), false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let result = rx.recv().unwrap().result; assert_eq!(result, TrFailedMsg(failed_msg)); } @@ -243,7 +243,15 @@ fn test_should_panic_but_succeeds() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test( + &TestOpts::new(), + false, + TestId(0), + desc, + RunStrategy::InProcess, + tx, + Concurrent::No, + ); let result = rx.recv().unwrap().result; assert_eq!( result, @@ -270,7 +278,7 @@ fn report_time_test_template(report_time: bool) -> Option { let test_opts = TestOpts { time_options, ..TestOpts::new() }; let (tx, rx) = channel(); - run_test(&test_opts, false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let exec_time = rx.recv().unwrap().exec_time; exec_time } @@ -305,7 +313,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { let test_opts = TestOpts { time_options: Some(time_options), ..TestOpts::new() }; let (tx, rx) = channel(); - run_test(&test_opts, false, desc, RunStrategy::InProcess, tx, Concurrent::No); + run_test(&test_opts, false, TestId(0), desc, RunStrategy::InProcess, tx, Concurrent::No); let result = rx.recv().unwrap().result; result @@ -637,7 +645,7 @@ pub fn test_bench_no_iter() { test_type: TestType::Unknown, }; - crate::bench::benchmark(desc, tx, true, f); + crate::bench::benchmark(TestId(0), desc, tx, true, f); rx.recv().unwrap(); } @@ -657,7 +665,7 @@ pub fn test_bench_iter() { test_type: TestType::Unknown, }; - crate::bench::benchmark(desc, tx, true, f); + crate::bench::benchmark(TestId(0), desc, tx, true, f); rx.recv().unwrap(); } diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 5b75d2f367..c5d91f653b 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -112,9 +112,13 @@ impl fmt::Debug for TestFn { } } +// A unique integer associated with each test. +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub struct TestId(pub usize); + // The definition of a single test. A test runner will run a list of // these. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug)] pub struct TestDesc { pub name: TestName, pub ignore: bool, diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 4f7a304a59..69128591e0 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -2,6 +2,8 @@ authors = ["The Rust Project Developers"] name = "unwind" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" edition = "2018" include = [ '/libunwind/*', diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index f899f21080..8437a10426 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Changes since the last major version] - `llvm-libunwind` now accepts `in-tree` (formerly true), `system` or `no` (formerly false) [#77703](https://github.com/rust-lang/rust/pull/77703) +- The options `infodir`, `localstatedir`, and `gpg-password-file` are no longer allowed in config.toml. Previously, they were ignored without warning. Note that `infodir` and `localstatedir` are still accepted by `./configure`, with a warning. [#82451](https://github.com/rust-lang/rust/pull/82451) ### Non-breaking changes diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 3e7d1d54f1..4111420e47 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -383,7 +383,7 @@ class RustBuild(object): self.nix_deps_dir = None self.rustc_commit = None - def download_stage0(self): + def download_toolchain(self, stage0=True, rustc_channel=None): """Fetch the build system for Rust, written in Rust This method will build a cache directory, then it will fetch the @@ -393,43 +393,47 @@ class RustBuild(object): Each downloaded tarball is extracted, after that, the script will move all the content to the right place. """ - rustc_channel = self.rustc_channel + if rustc_channel is None: + rustc_channel = self.rustc_channel rustfmt_channel = self.rustfmt_channel - - if self.rustc().startswith(self.bin_root()) and \ - (not os.path.exists(self.rustc()) or - self.program_out_of_date(self.rustc_stamp(), self.date + str(self.rustc_commit))): - if os.path.exists(self.bin_root()): - shutil.rmtree(self.bin_root()) - download_rustc = self.rustc_commit is not None + bin_root = self.bin_root(stage0) + + key = self.date + if not stage0: + key += str(self.rustc_commit) + if self.rustc(stage0).startswith(bin_root) and \ + (not os.path.exists(self.rustc(stage0)) or + self.program_out_of_date(self.rustc_stamp(stage0), key)): + if os.path.exists(bin_root): + shutil.rmtree(bin_root) tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' filename = "rust-std-{}-{}{}".format( rustc_channel, self.build, tarball_suffix) pattern = "rust-std-{}".format(self.build) - self._download_component_helper(filename, pattern, tarball_suffix, download_rustc) + self._download_component_helper(filename, pattern, tarball_suffix, stage0) filename = "rustc-{}-{}{}".format(rustc_channel, self.build, tarball_suffix) - self._download_component_helper(filename, "rustc", tarball_suffix, download_rustc) + self._download_component_helper(filename, "rustc", tarball_suffix, stage0) filename = "cargo-{}-{}{}".format(rustc_channel, self.build, tarball_suffix) self._download_component_helper(filename, "cargo", tarball_suffix) - if self.rustc_commit is not None: + if not stage0: filename = "rustc-dev-{}-{}{}".format(rustc_channel, self.build, tarball_suffix) self._download_component_helper( - filename, "rustc-dev", tarball_suffix, download_rustc + filename, "rustc-dev", tarball_suffix, stage0 ) - self.fix_bin_or_dylib("{}/bin/rustc".format(self.bin_root())) - self.fix_bin_or_dylib("{}/bin/rustdoc".format(self.bin_root())) - self.fix_bin_or_dylib("{}/bin/cargo".format(self.bin_root())) - lib_dir = "{}/lib".format(self.bin_root()) + self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root)) + self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root)) + self.fix_bin_or_dylib("{}/bin/cargo".format(bin_root)) + lib_dir = "{}/lib".format(bin_root) for lib in os.listdir(lib_dir): if lib.endswith(".so"): - self.fix_bin_or_dylib(os.path.join(lib_dir, lib), rpath_libz=True) - with output(self.rustc_stamp()) as rust_stamp: - rust_stamp.write(self.date + str(self.rustc_commit)) + self.fix_bin_or_dylib(os.path.join(lib_dir, lib)) + with output(self.rustc_stamp(stage0)) as rust_stamp: + rust_stamp.write(key) - if self.rustfmt() and self.rustfmt().startswith(self.bin_root()) and ( + if self.rustfmt() and self.rustfmt().startswith(bin_root) and ( not os.path.exists(self.rustfmt()) or self.program_out_of_date(self.rustfmt_stamp(), self.rustfmt_channel) ): @@ -440,12 +444,13 @@ class RustBuild(object): self._download_component_helper( filename, "rustfmt-preview", tarball_suffix, key=date ) - self.fix_bin_or_dylib("{}/bin/rustfmt".format(self.bin_root())) - self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(self.bin_root())) + self.fix_bin_or_dylib("{}/bin/rustfmt".format(bin_root)) + self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(bin_root)) with output(self.rustfmt_stamp()) as rustfmt_stamp: rustfmt_stamp.write(self.rustfmt_channel) - if self.downloading_llvm(): + # Avoid downloading LLVM twice (once for stage0 and once for the master rustc) + if self.downloading_llvm() and stage0: # We want the most recent LLVM submodule update to avoid downloading # LLVM more often than necessary. # @@ -463,6 +468,8 @@ class RustBuild(object): "--", "{}/src/llvm-project".format(top_level), "{}/src/bootstrap/download-ci-llvm-stamp".format(top_level), + # the LLVM shared object file is named `LLVM-12-rust-{version}-nightly` + "{}/src/version".format(top_level) ]).decode(sys.getdefaultencoding()).strip() llvm_assertions = self.get_toml('assertions', 'llvm') == 'true' llvm_root = self.llvm_root() @@ -470,10 +477,10 @@ class RustBuild(object): if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)): self._download_ci_llvm(llvm_sha, llvm_assertions) for binary in ["llvm-config", "FileCheck"]: - self.fix_bin_or_dylib(os.path.join(llvm_root, "bin", binary), rpath_libz=True) + self.fix_bin_or_dylib(os.path.join(llvm_root, "bin", binary)) for lib in os.listdir(llvm_lib): if lib.endswith(".so"): - self.fix_bin_or_dylib(os.path.join(llvm_lib, lib), rpath_libz=True) + self.fix_bin_or_dylib(os.path.join(llvm_lib, lib)) with output(self.llvm_stamp()) as llvm_stamp: llvm_stamp.write(llvm_sha + str(llvm_assertions)) @@ -496,27 +503,26 @@ class RustBuild(object): or (opt == "if-available" and self.build in supported_platforms) def _download_component_helper( - self, filename, pattern, tarball_suffix, download_rustc=False, key=None + self, filename, pattern, tarball_suffix, stage0=True, key=None ): if key is None: - if download_rustc: - key = self.rustc_commit - else: + if stage0: key = self.date + else: + key = self.rustc_commit cache_dst = os.path.join(self.build_dir, "cache") rustc_cache = os.path.join(cache_dst, key) if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) - if download_rustc: - url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(self.rustc_commit) - else: + if stage0: url = "{}/dist/{}".format(self._download_url, key) + else: + url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(self.rustc_commit) tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): - do_verify = not download_rustc - get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=do_verify) - unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose) + get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=stage0) + unpack(tarball, tarball_suffix, self.bin_root(stage0), match=pattern, verbose=self.verbose) def _download_ci_llvm(self, llvm_sha, llvm_assertions): cache_prefix = "llvm-{}-{}".format(llvm_sha, llvm_assertions) @@ -542,7 +548,7 @@ class RustBuild(object): match="rust-dev", verbose=self.verbose) - def fix_bin_or_dylib(self, fname, rpath_libz=False): + def fix_bin_or_dylib(self, fname): """Modifies the interpreter section of 'fname' to fix the dynamic linker, or the RPATH section, to fix the dynamic library search path @@ -574,59 +580,52 @@ class RustBuild(object): nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" print(nix_os_msg, fname) - # Only build `stage0/.nix-deps` once. + # Only build `.nix-deps` once. nix_deps_dir = self.nix_deps_dir if not nix_deps_dir: - nix_deps_dir = "{}/.nix-deps".format(self.bin_root()) - if not os.path.exists(nix_deps_dir): - os.makedirs(nix_deps_dir) - - nix_deps = [ - # Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`). - "stdenv.cc.bintools", - - # Needed as a system dependency of `libLLVM-*.so`. - "zlib", - - # Needed for patching ELF binaries (see doc comment above). - "patchelf", - ] - # Run `nix-build` to "build" each dependency (which will likely reuse # the existing `/nix/store` copy, or at most download a pre-built copy). - # Importantly, we don't rely on `nix-build` printing the `/nix/store` - # path on stdout, but use `-o` to symlink it into `stage0/.nix-deps/$dep`, - # ensuring garbage collection will never remove the `/nix/store` path - # (which would break our patched binaries that hardcode those paths). - for dep in nix_deps: - try: - subprocess.check_output([ - "nix-build", "", - "-A", dep, - "-o", "{}/{}".format(nix_deps_dir, dep), - ]) - except subprocess.CalledProcessError as reason: - print("warning: failed to call nix-build:", reason) - return - + # + # Importantly, we create a gc-root called `.nix-deps` in the `build/` + # directory, but still reference the actual `/nix/store` path in the rpath + # as it makes it significantly more robust against changes to the location of + # the `.nix-deps` location. + # + # bintools: Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`). + # zlib: Needed as a system dependency of `libLLVM-*.so`. + # patchelf: Needed for patching ELF binaries (see doc comment above). + nix_deps_dir = "{}/{}".format(self.build_dir, ".nix-deps") + nix_expr = ''' + with (import {}); + symlinkJoin { + name = "rust-stage0-dependencies"; + paths = [ + zlib + patchelf + stdenv.cc.bintools + ]; + } + ''' + try: + subprocess.check_output([ + "nix-build", "-E", nix_expr, "-o", nix_deps_dir, + ]) + except subprocess.CalledProcessError as reason: + print("warning: failed to call nix-build:", reason) + return self.nix_deps_dir = nix_deps_dir - patchelf = "{}/patchelf/bin/patchelf".format(nix_deps_dir) - patchelf_args = [] - - if rpath_libz: - # Patch RPATH to add `zlib` dependency that stems from LLVM - dylib_deps = ["zlib"] - rpath_entries = [ - # Relative default, all binary and dynamic libraries we ship - # appear to have this (even when `../lib` is redundant). - "$ORIGIN/../lib", - ] + ["{}/{}/lib".format(nix_deps_dir, dep) for dep in dylib_deps] - patchelf_args += ["--set-rpath", ":".join(rpath_entries)] + patchelf = "{}/bin/patchelf".format(nix_deps_dir) + rpath_entries = [ + # Relative default, all binary and dynamic libraries we ship + # appear to have this (even when `../lib` is redundant). + "$ORIGIN/../lib", + os.path.join(os.path.realpath(nix_deps_dir), "lib") + ] + patchelf_args = ["--set-rpath", ":".join(rpath_entries)] if not fname.endswith(".so"): # Finally, set the corret .interp for binaries - bintools_dir = "{}/stdenv.cc.bintools".format(nix_deps_dir) - with open("{}/nix-support/dynamic-linker".format(bintools_dir)) as dynamic_linker: + with open("{}/nix-support/dynamic-linker".format(nix_deps_dir)) as dynamic_linker: patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()] try: @@ -635,11 +634,13 @@ class RustBuild(object): print("warning: failed to call patchelf:", reason) return - # Return the stage1 compiler to download, if any. - def maybe_download_rustc(self): + # If `download-rustc` is set, download the most recent commit with CI artifacts + def maybe_download_ci_toolchain(self): # If `download-rustc` is not set, default to rebuilding. - if self.get_toml("download-rustc", section="rust") != "true": + download_rustc = self.get_toml("download-rustc", section="rust") + if download_rustc is None or download_rustc == "false": return None + assert download_rustc == "true" or download_rustc == "if-unchanged", download_rustc # Handle running from a directory other than the top level rev_parse = ["git", "rev-parse", "--show-toplevel"] @@ -654,19 +655,27 @@ class RustBuild(object): # Warn if there were changes to the compiler since the ancestor commit. status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler]) if status != 0: + if download_rustc == "if-unchanged": + return None print("warning: `download-rustc` is enabled, but there are changes to compiler/") - return commit + if self.verbose: + print("using downloaded stage1 artifacts from CI (commit {})".format(commit)) + self.rustc_commit = commit + # FIXME: support downloading artifacts from the beta channel + self.download_toolchain(False, "nightly") - def rustc_stamp(self): - """Return the path for .rustc-stamp + def rustc_stamp(self, stage0): + """Return the path for .rustc-stamp at the given stage >>> rb = RustBuild() >>> rb.build_dir = "build" - >>> rb.rustc_stamp() == os.path.join("build", "stage0", ".rustc-stamp") + >>> rb.rustc_stamp(True) == os.path.join("build", "stage0", ".rustc-stamp") + True + >>> rb.rustc_stamp(False) == os.path.join("build", "ci-rustc", ".rustc-stamp") True """ - return os.path.join(self.bin_root(), '.rustc-stamp') + return os.path.join(self.bin_root(stage0), '.rustc-stamp') def rustfmt_stamp(self): """Return the path for .rustfmt-stamp @@ -676,7 +685,7 @@ class RustBuild(object): >>> rb.rustfmt_stamp() == os.path.join("build", "stage0", ".rustfmt-stamp") True """ - return os.path.join(self.bin_root(), '.rustfmt-stamp') + return os.path.join(self.bin_root(True), '.rustfmt-stamp') def llvm_stamp(self): """Return the path for .rustfmt-stamp @@ -696,21 +705,27 @@ class RustBuild(object): with open(stamp_path, 'r') as stamp: return key != stamp.read() - def bin_root(self): - """Return the binary root directory + def bin_root(self, stage0): + """Return the binary root directory for the given stage >>> rb = RustBuild() >>> rb.build_dir = "build" - >>> rb.bin_root() == os.path.join("build", "stage0") + >>> rb.bin_root(True) == os.path.join("build", "stage0") + True + >>> rb.bin_root(False) == os.path.join("build", "ci-rustc") True When the 'build' property is given should be a nested directory: >>> rb.build = "devel" - >>> rb.bin_root() == os.path.join("build", "devel", "stage0") + >>> rb.bin_root(True) == os.path.join("build", "devel", "stage0") True """ - return os.path.join(self.build_dir, self.build, "stage0") + if stage0: + subdir = "stage0" + else: + subdir = "ci-rustc" + return os.path.join(self.build_dir, self.build, subdir) def llvm_root(self): """Return the CI LLVM root directory @@ -773,9 +788,9 @@ class RustBuild(object): """Return config path for cargo""" return self.program_config('cargo') - def rustc(self): + def rustc(self, stage0): """Return config path for rustc""" - return self.program_config('rustc') + return self.program_config('rustc', stage0) def rustfmt(self): """Return config path for rustfmt""" @@ -783,23 +798,27 @@ class RustBuild(object): return None return self.program_config('rustfmt') - def program_config(self, program): - """Return config path for the given program + def program_config(self, program, stage0=True): + """Return config path for the given program at the given stage >>> rb = RustBuild() >>> rb.config_toml = 'rustc = "rustc"\\n' >>> rb.program_config('rustc') 'rustc' >>> rb.config_toml = '' - >>> cargo_path = rb.program_config('cargo') - >>> cargo_path.rstrip(".exe") == os.path.join(rb.bin_root(), + >>> cargo_path = rb.program_config('cargo', True) + >>> cargo_path.rstrip(".exe") == os.path.join(rb.bin_root(True), + ... "bin", "cargo") + True + >>> cargo_path = rb.program_config('cargo', False) + >>> cargo_path.rstrip(".exe") == os.path.join(rb.bin_root(False), ... "bin", "cargo") True """ config = self.get_toml(program) if config: return os.path.expanduser(config) - return os.path.join(self.bin_root(), "bin", "{}{}".format( + return os.path.join(self.bin_root(stage0), "bin", "{}{}".format( program, self.exe_suffix())) @staticmethod @@ -854,14 +873,14 @@ class RustBuild(object): if "CARGO_BUILD_TARGET" in env: del env["CARGO_BUILD_TARGET"] env["CARGO_TARGET_DIR"] = build_dir - env["RUSTC"] = self.rustc() - env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ + env["RUSTC"] = self.rustc(True) + env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(True), "lib") + \ (os.pathsep + env["LD_LIBRARY_PATH"]) \ if "LD_LIBRARY_PATH" in env else "" - env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ + env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(True), "lib") + \ (os.pathsep + env["DYLD_LIBRARY_PATH"]) \ if "DYLD_LIBRARY_PATH" in env else "" - env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ + env["LIBRARY_PATH"] = os.path.join(self.bin_root(True), "lib") + \ (os.pathsep + env["LIBRARY_PATH"]) \ if "LIBRARY_PATH" in env else "" # preserve existing RUSTFLAGS @@ -884,7 +903,7 @@ class RustBuild(object): if self.get_toml("deny-warnings", "rust") != "false": env["RUSTFLAGS"] += " -Dwarnings" - env["PATH"] = os.path.join(self.bin_root(), "bin") + \ + env["PATH"] = os.path.join(self.bin_root(True), "bin") + \ os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): raise Exception("no cargo executable found at `{}`".format( @@ -1135,14 +1154,9 @@ def bootstrap(help_triggered): build.update_submodules() # Fetch/build the bootstrap - build.rustc_commit = build.maybe_download_rustc() - if build.rustc_commit is not None: - if build.verbose: - commit = build.rustc_commit - print("using downloaded stage1 artifacts from CI (commit {})".format(commit)) - # FIXME: support downloading artifacts from the beta channel - build.rustc_channel = "nightly" - build.download_stage0() + build.download_toolchain() + # Download the master compiler if `download-rustc` is set + build.maybe_download_ci_toolchain() sys.stdout.flush() build.ensure_vendored() build.build_bootstrap() @@ -1158,6 +1172,8 @@ def bootstrap(help_triggered): env["RUSTC_BOOTSTRAP"] = '1' if toml_path: env["BOOTSTRAP_CONFIG"] = toml_path + if build.rustc_commit is not None: + env["BOOTSTRAP_DOWNLOAD_RUSTC"] = '1' run(args, env=env, verbose=build.verbose) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 22a1eb6370..cff1ec843f 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -369,7 +369,8 @@ impl<'a> Builder<'a> { tool::Rustfmt, tool::Miri, tool::CargoMiri, - native::Lld + native::Lld, + native::CrtBeginEnd ), Kind::Check | Kind::Clippy { .. } | Kind::Fix | Kind::Format => describe!( check::Std, @@ -420,6 +421,7 @@ impl<'a> Builder<'a> { test::Rustfmt, test::Miri, test::Clippy, + test::RustDemangler, test::CompiletestTest, test::RustdocJSStd, test::RustdocJSNotStd, @@ -466,6 +468,7 @@ impl<'a> Builder<'a> { dist::Rls, dist::RustAnalyzer, dist::Rustfmt, + dist::RustDemangler, dist::Clippy, dist::Miri, dist::LlvmTools, @@ -481,6 +484,7 @@ impl<'a> Builder<'a> { install::Rls, install::RustAnalyzer, install::Rustfmt, + install::RustDemangler, install::Clippy, install::Miri, install::Analysis, @@ -738,12 +742,7 @@ impl<'a> Builder<'a> { .env("RUSTDOC_REAL", self.rustdoc(compiler)) .env("RUSTC_BOOTSTRAP", "1"); - // cfg(bootstrap), can be removed on the next beta bump - if compiler.stage == 0 { - cmd.arg("-Winvalid_codeblock_attributes"); - } else { - cmd.arg("-Wrustdoc::invalid_codeblock_attributes"); - } + cmd.arg("-Wrustdoc::invalid_codeblock_attributes"); if self.config.deny_warnings { cmd.arg("-Dwarnings"); @@ -1300,12 +1299,7 @@ impl<'a> Builder<'a> { // fixed via better support from Cargo. cargo.env("RUSTC_LINT_FLAGS", lint_flags.join(" ")); - // cfg(bootstrap), can be removed on the next beta bump - if compiler.stage == 0 { - rustdocflags.arg("-Winvalid_codeblock_attributes"); - } else { - rustdocflags.arg("-Wrustdoc::invalid_codeblock_attributes"); - } + rustdocflags.arg("-Wrustdoc::invalid_codeblock_attributes"); } if mode == Mode::Rustc { @@ -1634,6 +1628,11 @@ impl Cargo { pub fn add_rustc_lib_path(&mut self, builder: &Builder<'_>, compiler: Compiler) { builder.add_rustc_lib_path(compiler, &mut self.command); } + + pub fn current_dir(&mut self, dir: &Path) -> &mut Cargo { + self.command.current_dir(dir); + self + } } impl From for Command { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 6626fead77..9b76c8b9a2 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -280,7 +280,7 @@ impl Step for CodegenBackend { } macro_rules! tool_check_step { - ($name:ident, $path:expr, $source_type:expr) => { + ($name:ident, $path:literal, $($alias:literal, )* $source_type:path) => { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct $name { pub target: TargetSelection, @@ -292,7 +292,7 @@ macro_rules! tool_check_step { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path($path) + run.paths(&[ $path, $($alias),* ]) } fn make_run(run: RunConfig<'_>) { @@ -321,11 +321,9 @@ macro_rules! tool_check_step { } // Enable internal lints for clippy and rustdoc - // NOTE: this intentionally doesn't enable lints for any other tools, - // see https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 - if $path == "src/tools/rustdoc" || $path == "src/tools/clippy" { - cargo.rustflag("-Zunstable-options"); - } + // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` + // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 + cargo.rustflag("-Zunstable-options"); builder.info(&format!( "Checking stage{} {} artifacts ({} -> {})", @@ -363,7 +361,7 @@ macro_rules! tool_check_step { }; } -tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree); +tool_check_step!(Rustdoc, "src/tools/rustdoc", "src/librustdoc", SourceType::InTree); // Clippy is a hybrid. It is an external tool, but uses a git subtree instead // of a submodule. Since the SourceType only drives the deny-warnings // behavior, treat it as in-tree so that any new warnings in clippy will be diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9398f21172..ee3527b6bf 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -65,7 +65,9 @@ impl Step for Std { // These artifacts were already copied (in `impl Step for Sysroot`). // Don't recompile them. - if builder.config.download_rustc { + // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler, + // so its artifacts can't be reused. + if builder.config.download_rustc && compiler.stage != 0 { return; } @@ -197,8 +199,9 @@ fn copy_self_contained_objects( DependencyType::TargetSelfContained, ); } + let crt_path = builder.ensure(native::CrtBeginEnd { target }); for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] { - let src = compiler_file(builder, builder.cc(target), target, obj); + let src = crt_path.join(obj); let target = libdir_self_contained.join(obj); builder.copy(&src, &target); target_deps.push((target, DependencyType::TargetSelfContained)); @@ -460,11 +463,13 @@ impl Step for StartupObjects { let dst_file = &dst_dir.join(file.to_string() + ".o"); if !up_to_date(src_file, dst_file) { let mut cmd = Command::new(&builder.initial_rustc); + cmd.env("RUSTC_BOOTSTRAP", "1"); + if !builder.local_rebuild { + // a local_rebuild compiler already has stage1 features + cmd.arg("--cfg").arg("bootstrap"); + } builder.run( - cmd.env("RUSTC_BOOTSTRAP", "1") - .arg("--cfg") - .arg("bootstrap") - .arg("--target") + cmd.arg("--target") .arg(target.rustc_target_arg()) .arg("--emit=obj") .arg("-o") @@ -513,7 +518,9 @@ impl Step for Rustc { let compiler = self.compiler; let target = self.target; - if builder.config.download_rustc { + // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler, + // so its artifacts can't be reused. + if builder.config.download_rustc && compiler.stage != 0 { // Copy the existing artifacts instead of rebuilding them. // NOTE: this path is only taken for tools linking to rustc-dev. builder.ensure(Sysroot { compiler }); @@ -934,14 +941,15 @@ impl Step for Sysroot { t!(fs::create_dir_all(&sysroot)); // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0. - if builder.config.download_rustc { + if builder.config.download_rustc && compiler.stage != 0 { assert_eq!( builder.config.build, compiler.host, "Cross-compiling is not yet supported with `download-rustc`", ); // Copy the compiler into the correct sysroot. - let stage0_dir = builder.config.out.join(&*builder.config.build.triple).join("stage0"); - builder.cp_r(&stage0_dir, &sysroot); + let ci_rustc_dir = + builder.config.out.join(&*builder.config.build.triple).join("ci-rustc"); + builder.cp_r(&ci_rustc_dir, &sysroot); return INTERNER.intern_path(sysroot); } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index b9b090bb2d..483816b98d 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -67,7 +67,7 @@ pub struct Config { pub rustc_error_format: Option, pub json_output: bool, pub test_compare_mode: bool, - pub llvm_libunwind: Option, + pub llvm_libunwind: LlvmLibunwind, pub color: Color, pub on_fail: Option, @@ -101,8 +101,8 @@ pub struct Config { pub llvm_link_jobs: Option, pub llvm_version_suffix: Option, pub llvm_use_linker: Option, - pub llvm_allow_old_toolchain: Option, - pub llvm_polly: Option, + pub llvm_allow_old_toolchain: bool, + pub llvm_polly: bool, pub llvm_from_ci: bool, pub use_lld: bool, @@ -149,7 +149,6 @@ pub struct Config { // dist misc pub dist_sign_folder: Option, pub dist_upload_addr: Option, - pub dist_gpg_password_file: Option, pub dist_compression_formats: Option>, // libstd features @@ -404,10 +403,6 @@ struct Install { libdir: Option, mandir: Option, datadir: Option, - - // standard paths, currently unused - infodir: Option, - localstatedir: Option, } /// TOML representation of how the LLVM build is configured. @@ -510,7 +505,8 @@ struct Rust { new_symbol_mangling: Option, profile_generate: Option, profile_use: Option, - download_rustc: Option, + // ignored; this is set from an env var set by bootstrap.py + download_rustc: Option, } /// TOML representation of how each build target is configured. @@ -563,11 +559,10 @@ impl Config { config.rust_rpath = true; config.channel = "dev".to_string(); config.codegen_tests = true; - config.ignore_git = false; config.rust_dist_src = true; config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")]; config.deny_warnings = true; - config.missing_tools = false; + config.bindir = "bin".into(); // set by build.rs config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); @@ -597,7 +592,6 @@ impl Config { config.dry_run = flags.dry_run; config.keep_stage = flags.keep_stage; config.keep_stage_std = flags.keep_stage_std; - config.bindir = "bin".into(); // default config.color = flags.color; if let Some(value) = flags.deny_warnings { config.deny_warnings = value; @@ -687,51 +681,6 @@ impl Config { set(&mut config.print_step_timings, build.print_step_timings); set(&mut config.print_step_rusage, build.print_step_rusage); - // See https://github.com/rust-lang/compiler-team/issues/326 - config.stage = match config.cmd { - Subcommand::Check { .. } => flags.stage.or(build.check_stage).unwrap_or(0), - Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0), - Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1), - Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1), - Subcommand::Bench { .. } => flags.stage.or(build.bench_stage).unwrap_or(2), - Subcommand::Dist { .. } => flags.stage.or(build.dist_stage).unwrap_or(2), - Subcommand::Install { .. } => flags.stage.or(build.install_stage).unwrap_or(2), - // These are all bootstrap tools, which don't depend on the compiler. - // The stage we pass shouldn't matter, but use 0 just in case. - Subcommand::Clean { .. } - | Subcommand::Clippy { .. } - | Subcommand::Fix { .. } - | Subcommand::Run { .. } - | Subcommand::Setup { .. } - | Subcommand::Format { .. } => flags.stage.unwrap_or(0), - }; - - // CI should always run stage 2 builds, unless it specifically states otherwise - #[cfg(not(test))] - if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None { - match config.cmd { - Subcommand::Test { .. } - | Subcommand::Doc { .. } - | Subcommand::Build { .. } - | Subcommand::Bench { .. } - | Subcommand::Dist { .. } - | Subcommand::Install { .. } => { - assert_eq!( - config.stage, 2, - "x.py should be run with `--stage 2` on CI, but was run with `--stage {}`", - config.stage, - ); - } - Subcommand::Clean { .. } - | Subcommand::Check { .. } - | Subcommand::Clippy { .. } - | Subcommand::Fix { .. } - | Subcommand::Run { .. } - | Subcommand::Setup { .. } - | Subcommand::Format { .. } => {} - } - } - config.verbose = cmp::max(config.verbose, flags.verbose); if let Some(install) = toml.install { @@ -792,12 +741,25 @@ impl Config { config.llvm_ldflags = llvm.ldflags.clone(); set(&mut config.llvm_use_libcxx, llvm.use_libcxx); config.llvm_use_linker = llvm.use_linker.clone(); - config.llvm_allow_old_toolchain = llvm.allow_old_toolchain; - config.llvm_polly = llvm.polly; + config.llvm_allow_old_toolchain = llvm.allow_old_toolchain.unwrap_or(false); + config.llvm_polly = llvm.polly.unwrap_or(false); config.llvm_from_ci = match llvm.download_ci_llvm { Some(StringOrBool::String(s)) => { assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s); - config.build.triple == "x86_64-unknown-linux-gnu" + // This is currently all tier 1 targets (since others may not have CI artifacts) + // https://doc.rust-lang.org/rustc/platform-support.html#tier-1 + // FIXME: this is duplicated in bootstrap.py + let supported_platforms = [ + "aarch64-unknown-linux-gnu", + "i686-pc-windows-gnu", + "i686-pc-windows-msvc", + "i686-unknown-linux-gnu", + "x86_64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-gnu", + "x86_64-pc-windows-msvc", + ]; + supported_platforms.contains(&&*config.build.triple) } Some(StringOrBool::Bool(b)) => b, None => false, @@ -818,7 +780,6 @@ impl Config { check_ci_llvm!(llvm.targets); check_ci_llvm!(llvm.experimental_targets); check_ci_llvm!(llvm.link_jobs); - check_ci_llvm!(llvm.link_shared); check_ci_llvm!(llvm.clang_cl); check_ci_llvm!(llvm.version_suffix); check_ci_llvm!(llvm.cflags); @@ -839,6 +800,11 @@ impl Config { // If we're building with ThinLTO on, we want to link to LLVM // shared, to avoid re-doing ThinLTO (which happens in the link // step) with each stage. + assert_ne!( + llvm.link_shared, + Some(false), + "setting link-shared=false is incompatible with thin-lto=true" + ); config.llvm_link_shared = true; } } @@ -864,7 +830,8 @@ impl Config { set(&mut config.test_compare_mode, rust.test_compare_mode); config.llvm_libunwind = rust .llvm_libunwind - .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); + .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")) + .unwrap_or_default(); set(&mut config.backtrace, rust.backtrace); set(&mut config.channel, rust.channel); config.description = rust.description; @@ -897,7 +864,7 @@ impl Config { config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use); config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate); - config.download_rustc = rust.download_rustc.unwrap_or(false); + config.download_rustc = env::var("BOOTSTRAP_DOWNLOAD_RUSTC").as_deref() == Ok("1"); } else { config.rust_profile_use = flags.rust_profile_use; config.rust_profile_generate = flags.rust_profile_generate; @@ -952,7 +919,6 @@ impl Config { if let Some(t) = toml.dist { config.dist_sign_folder = t.sign_folder.map(PathBuf::from); - config.dist_gpg_password_file = t.gpg_password_file.map(PathBuf::from); config.dist_upload_addr = t.upload_addr; config.dist_compression_formats = t.compression_formats; set(&mut config.rust_dist_src, t.src_tarball); @@ -976,12 +942,8 @@ impl Config { // default values for all options that we haven't otherwise stored yet. config.llvm_skip_rebuild = llvm_skip_rebuild.unwrap_or(false); - - let default = false; - config.llvm_assertions = llvm_assertions.unwrap_or(default); - - let default = true; - config.rust_optimize = optimize.unwrap_or(default); + config.llvm_assertions = llvm_assertions.unwrap_or(false); + config.rust_optimize = optimize.unwrap_or(true); let default = debug == Some(true); config.rust_debug_assertions = debug_assertions.unwrap_or(default); @@ -1005,6 +967,59 @@ impl Config { let default = config.channel == "dev"; config.ignore_git = ignore_git.unwrap_or(default); + let download_rustc = config.download_rustc; + // See https://github.com/rust-lang/compiler-team/issues/326 + config.stage = match config.cmd { + Subcommand::Check { .. } => flags.stage.or(build.check_stage).unwrap_or(0), + // `download-rustc` only has a speed-up for stage2 builds. Default to stage2 unless explicitly overridden. + Subcommand::Doc { .. } => { + flags.stage.or(build.doc_stage).unwrap_or(if download_rustc { 2 } else { 0 }) + } + Subcommand::Build { .. } => { + flags.stage.or(build.build_stage).unwrap_or(if download_rustc { 2 } else { 1 }) + } + Subcommand::Test { .. } => { + flags.stage.or(build.test_stage).unwrap_or(if download_rustc { 2 } else { 1 }) + } + Subcommand::Bench { .. } => flags.stage.or(build.bench_stage).unwrap_or(2), + Subcommand::Dist { .. } => flags.stage.or(build.dist_stage).unwrap_or(2), + Subcommand::Install { .. } => flags.stage.or(build.install_stage).unwrap_or(2), + // These are all bootstrap tools, which don't depend on the compiler. + // The stage we pass shouldn't matter, but use 0 just in case. + Subcommand::Clean { .. } + | Subcommand::Clippy { .. } + | Subcommand::Fix { .. } + | Subcommand::Run { .. } + | Subcommand::Setup { .. } + | Subcommand::Format { .. } => flags.stage.unwrap_or(0), + }; + + // CI should always run stage 2 builds, unless it specifically states otherwise + #[cfg(not(test))] + if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None { + match config.cmd { + Subcommand::Test { .. } + | Subcommand::Doc { .. } + | Subcommand::Build { .. } + | Subcommand::Bench { .. } + | Subcommand::Dist { .. } + | Subcommand::Install { .. } => { + assert_eq!( + config.stage, 2, + "x.py should be run with `--stage 2` on CI, but was run with `--stage {}`", + config.stage, + ); + } + Subcommand::Clean { .. } + | Subcommand::Check { .. } + | Subcommand::Clippy { .. } + | Subcommand::Fix { .. } + | Subcommand::Run { .. } + | Subcommand::Setup { .. } + | Subcommand::Format { .. } => {} + } + } + config } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 2e6e9142af..999882a1c0 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -439,7 +439,12 @@ def configure_section(lines, config): lines[i] = "{} = {}".format(key, to_toml(value)) break if not found: - raise RuntimeError("failed to find config line for {}".format(key)) + # These are used by rpm, but aren't accepted by x.py. + # Give a warning that they're ignored, but not a hard error. + if key in ["infodir", "localstatedir"]: + print("warning: {} will be ignored".format(key)) + else: + raise RuntimeError("failed to find config line for {}".format(key)) for section_key in config: diff --git a/src/bootstrap/defaults/config.codegen.toml b/src/bootstrap/defaults/config.codegen.toml index a9505922ca..011ff6821b 100644 --- a/src/bootstrap/defaults/config.codegen.toml +++ b/src/bootstrap/defaults/config.codegen.toml @@ -11,3 +11,5 @@ assertions = true debug-logging = true # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true +# Print backtrace on internal compiler errors during bootstrap +backtrace-on-ice = true diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml index 0ca928843d..4d689d117b 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/config.compiler.toml @@ -6,8 +6,9 @@ debug-logging = true # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true +# Print backtrace on internal compiler errors during bootstrap +backtrace-on-ice = true [llvm] -# Will download LLVM from CI if available on your platform (Linux only for now) -# https://github.com/rust-lang/rust/issues/77084 tracks support for more platforms +# Will download LLVM from CI if available on your platform. download-ci-llvm = "if-available" diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml new file mode 100644 index 0000000000..182fb0fb06 --- /dev/null +++ b/src/bootstrap/defaults/config.tools.toml @@ -0,0 +1,16 @@ +# These defaults are meant for contributors to tools which build on the +# compiler, but do not modify it directly. +[rust] +# This enables `RUSTC_LOG=debug`, avoiding confusing situations +# where adding `debug!()` appears to do nothing. +# However, it makes running the compiler slightly slower. +debug-logging = true +# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. +incremental = true +# Download rustc from CI instead of building it from source. +# This cuts compile times by almost 60x, but means you can't modify the compiler. +download-rustc = "if-unchanged" + +[llvm] +# Will download LLVM from CI if available on your platform. +download-ci-llvm = "if-available" diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 78b1d90545..8224eac823 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -74,7 +74,7 @@ impl Step for Docs { let mut tarball = Tarball::new(builder, "rust-docs", &host.triple); tarball.set_product_name("Rust Documentation"); - tarball.add_dir(&builder.doc_out(host), dest); + tarball.add_bulk_dir(&builder.doc_out(host), dest); tarball.add_file(&builder.src.join("src/doc/robots.txt"), dest, 0o644); Some(tarball.generate()) } @@ -107,7 +107,7 @@ impl Step for RustcDocs { let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple); tarball.set_product_name("Rustc Documentation"); - tarball.add_dir(&builder.compiler_doc_out(host), "share/doc/rust/html/rustc"); + tarball.add_bulk_dir(&builder.compiler_doc_out(host), "share/doc/rust/html/rustc"); Some(tarball.generate()) } } @@ -1252,6 +1252,56 @@ impl Step for Rustfmt { } } +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustDemangler { + pub compiler: Compiler, + pub target: TargetSelection, +} + +impl Step for RustDemangler { + type Output = Option; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("rust-demangler") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(RustDemangler { + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), + target: run.target, + }); + } + + fn run(self, builder: &Builder<'_>) -> Option { + let compiler = self.compiler; + let target = self.target; + assert!(builder.config.extended); + + // Only build this extended tool if explicitly included in `tools`, or if `profiler = true` + let profiler = builder.config.profiler_enabled(target); + if !builder.config.tools.as_ref().map_or(profiler, |t| t.contains("rust-demangler")) { + return None; + } + + let rust_demangler = builder + .ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() }) + .expect("rust-demangler expected to build - in-tree tool"); + + // Prepare the image directory + let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple); + tarball.set_overlay(OverlayKind::RustDemangler); + tarball.is_preview(true); + tarball.add_file(&rust_demangler, "bin", 0o755); + tarball.add_legal_and_readme_to("share/doc/rust-demangler"); + Some(tarball.generate()) + } +} + #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Extended { stage: u32, @@ -1288,6 +1338,7 @@ impl Step for Extended { let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) }); let cargo_installer = builder.ensure(Cargo { compiler, target }); let rustfmt_installer = builder.ensure(Rustfmt { compiler, target }); + let rust_demangler_installer = builder.ensure(RustDemangler { compiler, target }); let rls_installer = builder.ensure(Rls { compiler, target }); let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target }); let llvm_tools_installer = builder.ensure(LlvmTools { target }); @@ -1313,9 +1364,10 @@ impl Step for Extended { let mut tarballs = Vec::new(); tarballs.push(rustc_installer); tarballs.push(cargo_installer); + tarballs.push(clippy_installer); + tarballs.extend(rust_demangler_installer.clone()); tarballs.extend(rls_installer.clone()); tarballs.extend(rust_analyzer_installer.clone()); - tarballs.push(clippy_installer); tarballs.extend(miri_installer.clone()); tarballs.extend(rustfmt_installer.clone()); tarballs.extend(llvm_tools_installer); @@ -1372,6 +1424,9 @@ impl Step for Extended { let xform = |p: &Path| { let mut contents = t!(fs::read_to_string(p)); + if rust_demangler_installer.is_none() { + contents = filter(&contents, "rust-demangler"); + } if rls_installer.is_none() { contents = filter(&contents, "rls"); } @@ -1420,7 +1475,9 @@ impl Step for Extended { prepare("rust-std"); prepare("rust-analysis"); prepare("clippy"); - + if rust_demangler_installer.is_some() { + prepare("rust-demangler"); + } if rls_installer.is_some() { prepare("rls"); } @@ -1468,6 +1525,8 @@ impl Step for Extended { "rust-analyzer-preview".to_string() } else if name == "clippy" { "clippy-preview".to_string() + } else if name == "rust-demangler" { + "rust-demangler-preview".to_string() } else if name == "miri" { "miri-preview".to_string() } else { @@ -1485,6 +1544,9 @@ impl Step for Extended { prepare("rust-docs"); prepare("rust-std"); prepare("clippy"); + if rust_demangler_installer.is_some() { + prepare("rust-demangler"); + } if rls_installer.is_some() { prepare("rls"); } @@ -1626,6 +1688,25 @@ impl Step for Extended { .arg("-t") .arg(etc.join("msi/remove-duplicates.xsl")), ); + if rust_demangler_installer.is_some() { + builder.run( + Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-demangler") + .args(&heat_flags) + .arg("-cg") + .arg("RustDemanglerGroup") + .arg("-dr") + .arg("RustDemangler") + .arg("-var") + .arg("var.RustDemanglerDir") + .arg("-out") + .arg(exe.join("RustDemanglerGroup.wxs")) + .arg("-t") + .arg(etc.join("msi/remove-duplicates.xsl")), + ); + } if miri_installer.is_some() { builder.run( Command::new(&heat) @@ -1699,6 +1780,9 @@ impl Step for Extended { .arg(&input); add_env(builder, &mut cmd, target); + if rust_demangler_installer.is_some() { + cmd.arg("-dRustDemanglerDir=rust-demangler"); + } if rls_installer.is_some() { cmd.arg("-dRlsDir=rls"); } @@ -1721,6 +1805,9 @@ impl Step for Extended { candle("CargoGroup.wxs".as_ref()); candle("StdGroup.wxs".as_ref()); candle("ClippyGroup.wxs".as_ref()); + if rust_demangler_installer.is_some() { + candle("RustDemanglerGroup.wxs".as_ref()); + } if rls_installer.is_some() { candle("RlsGroup.wxs".as_ref()); } @@ -1767,6 +1854,9 @@ impl Step for Extended { if rust_analyzer_installer.is_some() { cmd.arg("RustAnalyzerGroup.wixobj"); } + if rust_demangler_installer.is_some() { + cmd.arg("RustDemanglerGroup.wixobj"); + } if miri_installer.is_some() { cmd.arg("MiriGroup.wixobj"); } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 1168d54b55..a32b92ef1a 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -470,12 +470,16 @@ impl Step for Std { // Look for library/std, library/core etc in the `x.py doc` arguments and // open the corresponding rendered docs. for path in builder.paths.iter().map(components_simplified) { - if path.get(0) == Some(&"library") { - let requested_crate = &path[1]; - if krates.contains(&requested_crate) { - let index = out.join(requested_crate).join("index.html"); - open(builder, &index); - } + let requested_crate = if path.get(0) == Some(&"library") { + &path[1] + } else if !path.is_empty() { + &path[0] + } else { + continue; + }; + if krates.contains(&requested_crate) { + let index = out.join(requested_crate).join("index.html"); + open(builder, &index); } } } @@ -540,6 +544,8 @@ impl Step for Rustc { // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc"); cargo.rustdocflag("--document-private-items"); + // Since we always pass --document-private-items, there's no need to warn about linking to private items. + cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("-Zunstable-options"); cargo.rustdocflag("-Znormalize-docs"); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index b427420d57..13ee909afd 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -17,6 +17,11 @@ use crate::Compiler; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::config::{Config, TargetSelection}; +#[cfg(target_os = "illumos")] +const SHELL: &str = "bash"; +#[cfg(not(target_os = "illumos"))] +const SHELL: &str = "sh"; + fn install_sh( builder: &Builder<'_>, package: &str, @@ -37,7 +42,7 @@ fn install_sh( let empty_dir = builder.out.join("tmp/empty_dir"); t!(fs::create_dir_all(&empty_dir)); - let mut cmd = Command::new("sh"); + let mut cmd = Command::new(SHELL); cmd.current_dir(&empty_dir) .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh"))) .arg(format!("--prefix={}", prepare_dir(prefix))) @@ -190,6 +195,22 @@ install!((self, builder, _config), ); } }; + RustDemangler, "rust-demangler", Self::should_build(_config), only_hosts: true, { + // Note: Even though `should_build` may return true for `extended` default tools, + // dist::RustDemangler may still return None, unless the target-dependent `profiler` config + // is also true, or the `tools` array explicitly includes "rust-demangler". + if let Some(tarball) = builder.ensure(dist::RustDemangler { + compiler: self.compiler, + target: self.target + }) { + install_sh(builder, "rust-demangler", self.compiler.stage, Some(self.target), &tarball); + } else { + builder.info( + &format!("skipping Install RustDemangler stage{} ({})", + self.compiler.stage, self.target), + ); + } + }; Analysis, "analysis", Self::should_build(_config), only_hosts: false, { let tarball = builder.ensure(dist::Analysis { // Find the actual compiler (handling the full bootstrap option) which diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 5d708d3b25..24da44b933 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -547,7 +547,7 @@ impl Build { fn std_features(&self, target: TargetSelection) -> String { let mut features = "panic-unwind".to_string(); - match self.config.llvm_libunwind.unwrap_or_default() { + match self.config.llvm_libunwind { LlvmLibunwind::InTree => features.push_str(" llvm-libunwind"), LlvmLibunwind::System => features.push_str(" system-llvm-libunwind"), LlvmLibunwind::No => {} diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index fb5127bac5..156e8dd53d 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -256,7 +256,7 @@ impl Step for Llvm { enabled_llvm_projects.push("compiler-rt"); } - if let Some(true) = builder.config.llvm_polly { + if builder.config.llvm_polly { enabled_llvm_projects.push("polly"); } @@ -311,7 +311,7 @@ impl Step for Llvm { cfg.define("LLVM_USE_LINKER", linker); } - if let Some(true) = builder.config.llvm_allow_old_toolchain { + if builder.config.llvm_allow_old_toolchain { cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES"); } @@ -347,11 +347,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { let version = output(cmd.arg("--version")); let mut parts = version.split('.').take(2).filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) { - if major >= 9 { + if major >= 10 { return; } } - panic!("\n\nbad LLVM version: {}, need >=9.0\n\n", version) + panic!("\n\nbad LLVM version: {}, need >=10.0\n\n", version) } fn configure_cmake( @@ -814,6 +814,9 @@ fn supported_sanitizers( "x86_64-unknown-linux-gnu" => { common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } + "x86_64-unknown-linux-musl" => { + common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) + } _ => Vec::new(), } } @@ -855,3 +858,69 @@ impl HashStamp { fs::write(&self.path, self.hash.as_deref().unwrap_or(b"")) } } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct CrtBeginEnd { + pub target: TargetSelection, +} + +impl Step for CrtBeginEnd { + type Output = PathBuf; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/llvm-project/compiler-rt/lib/crt") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(CrtBeginEnd { target: run.target }); + } + + /// Build crtbegin.o/crtend.o for musl target. + fn run(self, builder: &Builder<'_>) -> Self::Output { + let out_dir = builder.native_dir(self.target).join("crt"); + + if builder.config.dry_run { + return out_dir; + } + + let crtbegin_src = builder.src.join("src/llvm-project/compiler-rt/lib/crt/crtbegin.c"); + let crtend_src = builder.src.join("src/llvm-project/compiler-rt/lib/crt/crtend.c"); + if up_to_date(&crtbegin_src, &out_dir.join("crtbegin.o")) + && up_to_date(&crtend_src, &out_dir.join("crtendS.o")) + { + return out_dir; + } + + builder.info("Building crtbegin.o and crtend.o"); + t!(fs::create_dir_all(&out_dir)); + + let mut cfg = cc::Build::new(); + + if let Some(ar) = builder.ar(self.target) { + cfg.archiver(ar); + } + cfg.compiler(builder.cc(self.target)); + cfg.cargo_metadata(false) + .out_dir(&out_dir) + .target(&self.target.triple) + .host(&builder.config.build.triple) + .warnings(false) + .debug(false) + .opt_level(3) + .file(crtbegin_src) + .file(crtend_src); + + // Those flags are defined in src/llvm-project/compiler-rt/lib/crt/CMakeLists.txt + // Currently only consumer of those objects is musl, which use .init_array/.fini_array + // instead of .ctors/.dtors + cfg.flag("-std=c11") + .define("CRT_HAS_INITFINI_ARRAY", None) + .define("EH_USE_FRAME_REGISTRY", None); + + cfg.compile("crt"); + + t!(fs::copy(out_dir.join("crtbegin.o"), out_dir.join("crtbeginS.o"))); + t!(fs::copy(out_dir.join("crtend.o"), out_dir.join("crtendS.o"))); + out_dir + } +} diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 725147767d..a5829dfa9d 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -13,6 +13,7 @@ pub enum Profile { Compiler, Codegen, Library, + Tools, User, } @@ -24,15 +25,16 @@ impl Profile { pub fn all() -> impl Iterator { use Profile::*; // N.B. these are ordered by how they are displayed, not alphabetically - [Library, Compiler, Codegen, User].iter().copied() + [Library, Compiler, Codegen, Tools, User].iter().copied() } pub fn purpose(&self) -> String { use Profile::*; match self { Library => "Contribute to the standard library", - Compiler => "Contribute to the compiler or rustdoc", + Compiler => "Contribute to the compiler itself", Codegen => "Contribute to the compiler, and also modify LLVM or codegen", + Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)", User => "Install Rust from source", } .to_string() @@ -53,9 +55,12 @@ impl FromStr for Profile { fn from_str(s: &str) -> Result { match s { "lib" | "library" => Ok(Profile::Library), - "compiler" | "rustdoc" => Ok(Profile::Compiler), + "compiler" => Ok(Profile::Compiler), "llvm" | "codegen" => Ok(Profile::Codegen), "maintainer" | "user" => Ok(Profile::User), + "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => { + Ok(Profile::Tools) + } _ => Err(format!("unknown profile: '{}'", s)), } } @@ -68,6 +73,7 @@ impl fmt::Display for Profile { Profile::Codegen => write!(f, "codegen"), Profile::Library => write!(f, "library"), Profile::User => write!(f, "user"), + Profile::Tools => write!(f, "tools"), } } } @@ -103,6 +109,14 @@ pub fn setup(src_path: &Path, profile: Profile) { let suggestions = match profile { Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..], + Profile::Tools => &[ + "check", + "build", + "test src/test/rustdoc*", + "test src/tools/clippy", + "test src/tools/miri", + "test src/tools/rustfmt", + ], Profile::Library => &["check", "build", "test library/std", "doc"], Profile::User => &["dist", "build"], }; diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs index 7fb03056f1..9ff5c2327e 100644 --- a/src/bootstrap/tarball.rs +++ b/src/bootstrap/tarball.rs @@ -15,6 +15,7 @@ pub(crate) enum OverlayKind { Clippy, Miri, Rustfmt, + RustDemangler, RLS, RustAnalyzer, } @@ -47,6 +48,9 @@ impl OverlayKind { "src/tools/rustfmt/LICENSE-APACHE", "src/tools/rustfmt/LICENSE-MIT", ], + OverlayKind::RustDemangler => { + &["src/tools/rust-demangler/README.md", "LICENSE-APACHE", "LICENSE-MIT"] + } OverlayKind::RLS => &[ "src/tools/rls/README.md", "src/tools/rls/LICENSE-APACHE", @@ -64,6 +68,7 @@ impl OverlayKind { match self { OverlayKind::Rust => builder.rust_version(), OverlayKind::LLVM => builder.rust_version(), + OverlayKind::RustDemangler => builder.release_num("rust-demangler"), OverlayKind::Cargo => { builder.cargo_info.version(builder, &builder.release_num("cargo")) } @@ -94,6 +99,7 @@ pub(crate) struct Tarball<'a> { temp_dir: PathBuf, image_dir: PathBuf, overlay_dir: PathBuf, + bulk_dirs: Vec, include_target_in_component_name: bool, is_preview: bool, @@ -132,6 +138,7 @@ impl<'a> Tarball<'a> { temp_dir, image_dir, overlay_dir, + bulk_dirs: Vec::new(), include_target_in_component_name: false, is_preview: false, @@ -196,6 +203,11 @@ impl<'a> Tarball<'a> { self.builder.cp_r(src.as_ref(), &dest); } + pub(crate) fn add_bulk_dir(&mut self, src: impl AsRef, dest: impl AsRef) { + self.bulk_dirs.push(dest.as_ref().to_path_buf()); + self.add_dir(src, dest); + } + pub(crate) fn generate(self) -> GeneratedTarball { let mut component_name = self.component.clone(); if self.is_preview { @@ -216,6 +228,16 @@ impl<'a> Tarball<'a> { .arg("--image-dir") .arg(&this.image_dir) .arg(format!("--component-name={}", &component_name)); + + if let Some((dir, dirs)) = this.bulk_dirs.split_first() { + let mut arg = dir.as_os_str().to_os_string(); + for dir in dirs { + arg.push(","); + arg.push(dir); + } + cmd.arg("--bulk-dirs").arg(&arg); + } + this.non_bare_args(cmd); }) } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 86d940cd73..965d116214 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -108,6 +108,19 @@ impl Step for Linkcheck { /// documentation to ensure we don't have a bunch of dead ones. fn run(self, builder: &Builder<'_>) { let host = self.host; + let hosts = &builder.hosts; + let targets = &builder.targets; + + // if we have different hosts and targets, some things may be built for + // the host (e.g. rustc) and others for the target (e.g. std). The + // documentation built for each will contain broken links to + // docs built for the other platform (e.g. rustc linking to cargo) + if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() { + panic!( + "Linkcheck currently does not support builds with different hosts and targets. +You can skip linkcheck with --exclude src/tools/linkchecker" + ); + } builder.info(&format!("Linkcheck ({})", host)); @@ -122,7 +135,8 @@ impl Step for Linkcheck { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/tools/linkchecker").default_condition(builder.config.docs) + let run = run.path("src/tools/linkchecker"); + run.default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { @@ -337,6 +351,57 @@ impl Step for Rustfmt { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct RustDemangler { + stage: u32, + host: TargetSelection, +} + +impl Step for RustDemangler { + type Output = (); + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/rust-demangler") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(RustDemangler { stage: run.builder.top_stage, host: run.target }); + } + + /// Runs `cargo test` for rust-demangler. + fn run(self, builder: &Builder<'_>) { + let stage = self.stage; + let host = self.host; + let compiler = builder.compiler(stage, host); + + let rust_demangler = builder + .ensure(tool::RustDemangler { compiler, target: self.host, extra_features: Vec::new() }) + .expect("in-tree tool"); + let mut cargo = tool::prepare_tool_cargo( + builder, + compiler, + Mode::ToolRustc, + host, + "test", + "src/tools/rust-demangler", + SourceType::InTree, + &[], + ); + + let dir = testdir(builder, compiler.host); + t!(fs::create_dir_all(&dir)); + + cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler); + + cargo.arg("--").args(builder.config.cmd.test_args()); + + cargo.add_rustc_lib_path(builder, compiler); + + builder.run(&mut cargo.into()); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Miri { stage: u32, @@ -452,7 +517,14 @@ impl Step for Miri { cargo.add_rustc_lib_path(builder, compiler); - if !try_run(builder, &mut cargo.into()) { + let mut cargo = Command::from(cargo); + if !try_run(builder, &mut cargo) { + return; + } + + // # Run `cargo test` with `-Zmir-opt-level=4`. + cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4"); + if !try_run(builder, &mut cargo) { return; } @@ -560,6 +632,26 @@ impl Step for Clippy { cargo.add_rustc_lib_path(builder, compiler); + if builder.try_run(&mut cargo.into()) { + // The tests succeeded; nothing to do. + return; + } + + if !builder.config.cmd.bless() { + std::process::exit(1); + } + + let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run"); + cargo.arg("-p").arg("clippy_dev"); + // clippy_dev gets confused if it can't find `clippy/Cargo.toml` + cargo.current_dir(&builder.src.join("src").join("tools").join("clippy")); + if builder.config.rust_optimize { + cargo.env("PROFILE", "release"); + } else { + cargo.env("PROFILE", "debug"); + } + cargo.arg("--"); + cargo.arg("bless"); builder.run(&mut cargo.into()); } } @@ -782,6 +874,7 @@ impl Step for Tidy { cmd.arg(&builder.src); cmd.arg(&builder.initial_cargo); cmd.arg(&builder.out); + cmd.arg(builder.jobs().to_string()); if builder.is_verbose() { cmd.arg("--verbose"); } @@ -1105,7 +1198,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the } if mode == "run-make" && suite.ends_with("fulldeps") { - cmd.arg("--rust-demangler-path").arg(builder.tool_exe(Tool::RustDemangler)); + let rust_demangler = builder + .ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() }) + .expect("in-tree tool"); + cmd.arg("--rust-demangler-path").arg(rust_demangler); } cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite)); @@ -1156,6 +1252,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display())); if builder.is_fuse_ld_lld(compiler.host) { hostflags.push("-Clink-args=-fuse-ld=lld".to_string()); + hostflags.push("-Clink-arg=-Wl,--threads=1".to_string()); } cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); @@ -1163,6 +1260,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display())); if builder.is_fuse_ld_lld(target) { targetflags.push("-Clink-args=-fuse-ld=lld".to_string()); + targetflags.push("-Clink-arg=-Wl,--threads=1".to_string()); } cmd.arg("--target-rustcflags").arg(targetflags.join(" ")); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 3fc3b68fd8..e85f4628fb 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -368,7 +368,6 @@ bootstrap_tool!( Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true; BuildManifest, "src/tools/build-manifest", "build-manifest"; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; - RustDemangler, "src/tools/rust-demangler", "rust-demangler"; RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; @@ -514,12 +513,30 @@ impl Step for Rustdoc { // rustc compiler it's paired with, so it must be built with the previous stage compiler. let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build); + // When using `download-rustc` and a stage0 build_compiler, copying rustc doesn't actually + // build stage0 libstd (because the libstd in sysroot has the wrong ABI). Explicitly build + // it. + builder.ensure(compile::Std { compiler: build_compiler, target: target_compiler.host }); + builder.ensure(compile::Rustc { compiler: build_compiler, target: target_compiler.host }); + // NOTE: this implies that `download-rustc` is pretty useless when compiling with the stage0 + // compiler, since you do just as much work. + if !builder.config.dry_run && builder.config.download_rustc && build_compiler.stage == 0 { + println!( + "warning: `download-rustc` does nothing when building stage1 tools; consider using `--stage 2` instead" + ); + } + // The presence of `target_compiler` ensures that the necessary libraries (codegen backends, // compiler libraries, ...) are built. Rustdoc does not require the presence of any // libraries within sysroot_libdir (i.e., rustlib), though doctests may want it (since // they'll be linked to those libraries). As such, don't explicitly `ensure` any additional // libraries here. The intuition here is that If we've built a compiler, we should be able // to build rustdoc. + // + let mut features = Vec::new(); + if builder.config.jemalloc { + features.push("jemalloc".to_string()); + } let cargo = prepare_tool_cargo( builder, @@ -529,7 +546,7 @@ impl Step for Rustdoc { "build", "src/tools/rustdoc", SourceType::InTree, - &[], + features.as_slice(), ); builder.info(&format!( @@ -719,6 +736,7 @@ tool_extended!((self, builder), }); self.extra_features.push("clippy".to_owned()); }; + RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, {}; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, {}; RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, {}; ); diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile index f3f52ed61d..4377608700 100644 --- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile @@ -98,6 +98,6 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs -ENV SCRIPT python3 ../x.py --stage 2 test --target riscv64gc-unknown-linux-gnu +ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target riscv64gc-unknown-linux-gnu ENV NO_CHANGE_USER=1 diff --git a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile index 1f8f9fc518..cd0f01faa1 100644 --- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile @@ -144,7 +144,11 @@ ENV TARGETS=$TARGETS,armv7a-none-eabi # riscv targets currently do not need a C compiler, as compiler_builtins # doesn't currently have it enabled, and the riscv gcc compiler is not # installed. -ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ +ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft" \ + CFLAGS_arm_unknown_linux_musleabi="-march=armv6 -marm" \ + CFLAGS_arm_unknown_linux_musleabihf="-march=armv6 -marm -mfpu=vfp" \ + CFLAGS_armv7_unknown_linux_musleabihf="-march=armv7-a" \ + CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ CC_mips64el_unknown_linux_muslabi64=mips64el-linux-gnuabi64-gcc \ CC_mips64_unknown_linux_muslabi64=mips64-linux-gnuabi64-gcc \ diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index de3a99f34f..b7f181adf2 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -42,6 +42,9 @@ ENV \ AR_x86_64_pc_solaris=x86_64-pc-solaris2.10-ar \ CC_x86_64_pc_solaris=x86_64-pc-solaris2.10-gcc \ CXX_x86_64_pc_solaris=x86_64-pc-solaris2.10-g++ \ + AR_x86_64_sun_solaris=x86_64-sun-solaris2.10-ar \ + CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \ + CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++ \ CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-8 \ CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-8 \ AR_x86_64_fortanix_unknown_sgx=ar \ @@ -68,8 +71,10 @@ COPY host-x86_64/dist-various-2/shared.sh /tmp/ COPY host-x86_64/dist-various-2/build-fuchsia-toolchain.sh /tmp/ RUN /tmp/build-fuchsia-toolchain.sh COPY host-x86_64/dist-various-2/build-solaris-toolchain.sh /tmp/ -RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 -RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc +RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 pc +# Build deprecated target 'x86_64-sun-solaris2.10' until removed +RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 sun +RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc sun COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh @@ -99,6 +104,7 @@ ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasi ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-pc-solaris +ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh index ee76fafb1f..4cbc2ccfe3 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh @@ -6,21 +6,11 @@ source shared.sh ARCH=$1 LIB_ARCH=$2 APT_ARCH=$3 +MANUFACTURER=$4 BINUTILS=2.28.1 GCC=6.5.0 -# Choose correct target based on the $ARCH -case "$ARCH" in -x86_64) - TARGET=x86_64-pc-solaris2.10 - ;; -sparcv9) - TARGET=sparcv9-sun-solaris2.10 - ;; -*) - printf 'ERROR: unknown architecture: %s\n' "$ARCH" - exit 1 -esac +TARGET=${ARCH}-${MANUFACTURER}-solaris2.10 # First up, build binutils mkdir binutils diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile index 08f07eb828..ea70771a57 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile @@ -38,6 +38,7 @@ ENV HOSTS=x86_64-unknown-linux-musl ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ --enable-extended \ + --enable-sanitizers \ --enable-profiler \ --enable-lld \ --set target.x86_64-unknown-linux-musl.crt-static=false \ diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index f5fe546cdc..ad0e8e9f92 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -18,7 +18,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins wget \ patch -RUN curl -sL https://nodejs.org/dist/v14.4.0/node-v14.4.0-linux-x64.tar.xz | \ +RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \ tar -xJ WORKDIR /build/ @@ -31,7 +31,7 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ - --set build.nodejs=/node-v14.4.0-linux-x64/bin/node \ + --set build.nodejs=/node-v15.14.0-linux-x64/bin/node \ --set rust.lld # Some run-make tests have assertions about code size, and enabling debug diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-9/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile similarity index 91% rename from src/ci/docker/host-x86_64/x86_64-gnu-llvm-9/Dockerfile rename to src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile index 38eac6588b..c34198708c 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-9/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-10/Dockerfile @@ -13,8 +13,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - llvm-9-tools \ - llvm-9-dev \ + llvm-10-tools \ + llvm-10-dev \ libedit-dev \ libssl-dev \ pkg-config \ @@ -28,7 +28,7 @@ RUN sh /scripts/sccache.sh # using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-9 \ + --llvm-root=/usr/lib/llvm-10 \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 @@ -46,6 +46,7 @@ ENV SCRIPT python2.7 ../x.py --stage 2 test --exclude src/tools/tidy && \ # This is intended to make sure that both `--pass=check` continues to # work. # - python2.7 ../x.py --stage 2 test src/test/ui --pass=check --target=i686-unknown-linux-gnu && \ + python2.7 ../x.py --stage 2 test src/test/ui --pass=check \ + --host='' --target=i686-unknown-linux-gnu && \ # Run tidy at the very end, after all the other tests. python2.7 ../x.py --stage 2 test src/tools/tidy diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index c0a84444a5..a59a90b86b 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -280,7 +280,7 @@ jobs: - name: mingw-check <<: *job-linux-xl - - name: x86_64-gnu-llvm-9 + - name: x86_64-gnu-llvm-10 <<: *job-linux-xl - name: x86_64-gnu-tools @@ -412,7 +412,7 @@ jobs: - name: x86_64-gnu-distcheck <<: *job-linux-xl - - name: x86_64-gnu-llvm-9 + - name: x86_64-gnu-llvm-10 env: RUST_BACKTRACE: 1 <<: *job-linux-xl diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh index 95cf1183fc..ad2a8c771d 100755 --- a/src/ci/pgo.sh +++ b/src/ci/pgo.sh @@ -12,7 +12,7 @@ RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ # Download and build a single-file stress test benchmark on perf.rust-lang.org. function pgo_perf_benchmark { - local PERF=e095f5021bf01cf3800f50b3a9f14a9683eb3e4e + local PERF=9442def56a39d742bf27ebcc3e0614cf117e1bc2 local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF local name=$1 curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index 8070e90f15..8a30acc2e4 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -9,7 +9,7 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" # Update both macOS's and Windows's tarballs when bumping the version here. -LLVM_VERSION="10.0.0" +LLVM_VERSION="12.0.0" if isMacOS; then # If the job selects a specific Xcode version, use that instead of @@ -42,23 +42,14 @@ elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then # clang has an output mode compatible with MinGW that we need. If it does we # should switch to clang for MinGW as well! # - # Note that the LLVM installer is an NSIS installer - # - # Original downloaded here came from: - # - # https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe - # - # That installer was run through `wine ./installer.exe /S /NCRC` on Linux - # and then the resulting installation directory (found in - # `$HOME/.wine/drive_c/Program Files/LLVM`) was packaged up into a tarball. - # We've had issues otherwise that the installer will randomly hang, provide - # not a lot of useful information, pollute global state, etc. In general the - # tarball is just more confined and easier to deal with when working with - # various CI environments. + # The LLVM installer is an NSIS installer, which we can extract with 7z. We + # don't want to run the installer directly; extracting it is more reliable + # in CI environments. - mkdir -p citools + mkdir -p citools/clang-rust cd citools - curl -f "${MIRRORS_BASE}/LLVM-${LLVM_VERSION}-win64.tar.gz" | tar xzf - + curl -f "${MIRRORS_BASE}/LLVM-${LLVM_VERSION}-win64.exe" -o "LLVM-${LLVM_VERSION}-win64.exe" + 7z x -oclang-rust/ "LLVM-${LLVM_VERSION}-win64.exe" ciCommandSetEnv RUST_CONFIGURE_ARGS \ "${RUST_CONFIGURE_ARGS} --set llvm.clang-cl=$(pwd)/clang-rust/bin/clang-cl.exe" fi diff --git a/src/doc/book/COPYRIGHT b/src/doc/book/COPYRIGHT index 19559fa295..dfe614df93 100644 --- a/src/doc/book/COPYRIGHT +++ b/src/doc/book/COPYRIGHT @@ -11,8 +11,8 @@ Developers. Licensed under the Apache License, Version 2.0 or the MIT -license , +https://www.apache.org/licenses/LICENSE-2.0> or the MIT +license , at your option. All files in the project carrying such notice may not be copied, modified, or distributed except according to those terms. @@ -39,7 +39,7 @@ their own copyright notices and license terms: University of Illinois at Urbana-Champaign - http://llvm.org + https://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -95,7 +95,7 @@ their own copyright notices and license terms: University of Illinois at Urbana-Champaign - http://llvm.org + https://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/src/doc/book/README.md b/src/doc/book/README.md index 485a14e4f9..54e92f6f8f 100644 --- a/src/doc/book/README.md +++ b/src/doc/book/README.md @@ -86,7 +86,8 @@ before we merge any in, but feel free to start! ## Spellchecking To scan source files for spelling errors, you can use the `spellcheck.sh` -script. It needs a dictionary of valid words, which is provided in -`dictionary.txt`. If the script produces a false positive (say, you used word -`BTreeMap` which the script considers invalid), you need to add this word to -`dictionary.txt` (keep the sorted order for consistency). +script available in the `ci` directory. It needs a dictionary of valid words, +which is provided in `ci/dictionary.txt`. If the script produces a false +positive (say, you used word `BTreeMap` which the script considers invalid), +you need to add this word to `ci/dictionary.txt` (keep the sorted order for +consistency). diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-10/src/main.rs b/src/doc/book/listings/ch15-smart-pointers/listing-15-10/src/main.rs index a97f97c9b7..cce754d081 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-10/src/main.rs +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-10/src/main.rs @@ -4,7 +4,7 @@ use std::ops::Deref; impl Deref for MyBox { type Target = T; - fn deref(&self) -> &T { + fn deref(&self) -> &Self::Target { &self.0 } } diff --git a/src/doc/book/src/ch01-03-hello-cargo.md b/src/doc/book/src/ch01-03-hello-cargo.md index 4751b6ac64..0f11be8ade 100644 --- a/src/doc/book/src/ch01-03-hello-cargo.md +++ b/src/doc/book/src/ch01-03-hello-cargo.md @@ -223,7 +223,7 @@ existing projects, you can use the following commands to check out the code using Git, change to that project’s directory, and build: ```console -$ git clone someurl.com/someproject +$ git clone example.org/someproject $ cd someproject $ cargo build ``` diff --git a/src/doc/book/src/ch02-00-guessing-game-tutorial.md b/src/doc/book/src/ch02-00-guessing-game-tutorial.md index eb80bd85a5..ba494eb944 100644 --- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md +++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md @@ -693,8 +693,9 @@ the user must press enter to satisfy newline character is added to the string. For example, if the user types 5 and presses enter, `guess` looks like this: `5\n`. The `\n` represents “newline,” the result of -pressing enter. The `trim` method eliminates -`\n`, resulting in just `5`. +pressing enter (On Windows, pressing enter 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][parse] parses a string into some kind of number. Because this method can parse a variety of number types, we diff --git a/src/doc/book/src/ch04-03-slices.md b/src/doc/book/src/ch04-03-slices.md index 2b0385278f..a6008f4b3a 100644 --- a/src/doc/book/src/ch04-03-slices.md +++ b/src/doc/book/src/ch04-03-slices.md @@ -281,6 +281,8 @@ to part of an array. We’d do so like this: let a = [1, 2, 3, 4, 5]; let slice = &a[1..3]; + +assert_eq!(slice, &[2, 3]); ``` This slice has the type `&[i32]`. It works the same way as string slices do, by diff --git a/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md b/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md index e4cf711fb9..4104e83d8e 100644 --- a/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md +++ b/src/doc/book/src/ch16-04-extensible-concurrency-sync-and-send.md @@ -33,9 +33,9 @@ we’ll discuss in Chapter 19. The `Sync` marker trait indicates that it is safe for the type implementing `Sync` to be referenced from multiple threads. In other words, any type `T` is -`Sync` if `&T` (a reference to `T`) is `Send`, meaning the reference can be -sent safely to another thread. Similar to `Send`, primitive types are `Sync`, -and types composed entirely of types that are `Sync` are also `Sync`. +`Sync` if `&T` (an immutable reference to `T`) is `Send`, meaning the reference +can be sent safely to another thread. Similar to `Send`, primitive types are +`Sync`, and types composed entirely of types that are `Sync` are also `Sync`. The smart pointer `Rc` is also not `Sync` for the same reasons that it’s not `Send`. The `RefCell` type (which we talked about in Chapter 15) and the diff --git a/src/doc/embedded-book/src/intro/install.md b/src/doc/embedded-book/src/intro/install.md index 343f762cab..53bb68851e 100644 --- a/src/doc/embedded-book/src/intro/install.md +++ b/src/doc/embedded-book/src/intro/install.md @@ -9,7 +9,7 @@ Install rustup by following the instructions at [https://rustup.rs](https://rust **NOTE** Make sure you have a compiler version equal to or newer than `1.31`. `rustc -V` should return a date newer than the one shown below. -``` console +``` text $ rustc -V rustc 1.31.1 (b6c32da9b 2018-12-18) ``` @@ -21,43 +21,43 @@ board used for the examples in this book, use the `thumbv7em-none-eabihf` target Cortex-M0, M0+, and M1 (ARMv6-M architecture): ``` console -$ rustup target add thumbv6m-none-eabi +rustup target add thumbv6m-none-eabi ``` Cortex-M3 (ARMv7-M architecture): ``` console -$ rustup target add thumbv7m-none-eabi +rustup target add thumbv7m-none-eabi ``` Cortex-M4 and M7 without hardware floating point (ARMv7E-M architecture): ``` console -$ rustup target add thumbv7em-none-eabi +rustup target add thumbv7em-none-eabi ``` Cortex-M4F and M7F with hardware floating point (ARMv7E-M architecture): ``` console -$ rustup target add thumbv7em-none-eabihf +rustup target add thumbv7em-none-eabihf ``` Cortex-M23 (ARMv8-M architecture): ``` console -$ rustup target add thumbv8m.base-none-eabi +rustup target add thumbv8m.base-none-eabi ``` Cortex-M33 and M35P (ARMv8-M architecture): ``` console -$ rustup target add thumbv8m.main-none-eabi +rustup target add thumbv8m.main-none-eabi ``` Cortex-M33F and M35PF with hardware floating point (ARMv8-M architecture): ``` console -$ rustup target add thumbv8m.main-none-eabihf +rustup target add thumbv8m.main-none-eabihf ``` ### `cargo-binutils` -``` console +``` text $ cargo install cargo-binutils $ rustup component add llvm-tools-preview @@ -68,7 +68,7 @@ $ rustup component add llvm-tools-preview We'll use this later to generate a project from a template. ``` console -$ cargo install cargo-generate +cargo install cargo-generate ``` ### OS-Specific Instructions diff --git a/src/doc/embedded-book/src/intro/install/macos.md b/src/doc/embedded-book/src/intro/install/macos.md index 2afe2b772e..9764f73e42 100644 --- a/src/doc/embedded-book/src/intro/install/macos.md +++ b/src/doc/embedded-book/src/intro/install/macos.md @@ -4,7 +4,7 @@ All the tools can be install using [Homebrew]: [Homebrew]: http://brew.sh/ -``` console +``` text $ # GDB $ brew install armmbed/formulae/arm-none-eabi-gcc diff --git a/src/doc/embedded-book/src/intro/install/verify.md b/src/doc/embedded-book/src/intro/install/verify.md index ae2722fc4e..921db8cc76 100644 --- a/src/doc/embedded-book/src/intro/install/verify.md +++ b/src/doc/embedded-book/src/intro/install/verify.md @@ -17,7 +17,7 @@ ST-LINK header is circled in red. Now run the following command: ``` console -$ openocd -f interface/stlink.cfg -f target/stm32f3x.cfg +openocd -f interface/stlink.cfg -f target/stm32f3x.cfg ``` > **NOTE**: Old versions of openocd, including the 0.10.0 release from 2017, do @@ -54,11 +54,11 @@ and move to the [next section]. If you didn't get the "breakpoints" line then try one of the following commands. ``` console -$ openocd -f interface/stlink-v2.cfg -f target/stm32f3x.cfg +openocd -f interface/stlink-v2.cfg -f target/stm32f3x.cfg ``` ``` console -$ openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg +openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg ``` If one of those commands works it means you got an old hardware revision of the diff --git a/src/doc/embedded-book/src/intro/install/windows.md b/src/doc/embedded-book/src/intro/install/windows.md index 374f379b3f..e00740352a 100644 --- a/src/doc/embedded-book/src/intro/install/windows.md +++ b/src/doc/embedded-book/src/intro/install/windows.md @@ -6,7 +6,7 @@ ARM provides `.exe` installers for Windows. Grab one from [here][gcc], and follo Just before the installation process finishes tick/select the "Add path to environment variable" option. Then verify that the tools are in your `%PATH%`: -``` console +``` text $ arm-none-eabi-gdb -v GNU gdb (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 8.1.0.20180315-git (..) @@ -26,7 +26,7 @@ if you've been using the easy install) Verify that OpenOCD is in your `%PATH%` with: -``` console +``` text $ openocd -v Open On-Chip Debugger 0.10.0 (..) diff --git a/src/doc/embedded-book/src/start/exceptions.md b/src/doc/embedded-book/src/start/exceptions.md index a88319c024..b15717da96 100644 --- a/src/doc/embedded-book/src/start/exceptions.md +++ b/src/doc/embedded-book/src/start/exceptions.md @@ -121,7 +121,7 @@ fn SysTick() { ``` ``` console -$ tail -n5 Cargo.toml +tail -n5 Cargo.toml ``` ``` toml @@ -132,7 +132,7 @@ panic-halt = "0.2.0" cortex-m-semihosting = "0.3.1" ``` -``` console +``` text $ cargo run --release Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..) 123456789 @@ -227,7 +227,7 @@ fn HardFault(ef: &ExceptionFrame) -> ! { The `HardFault` handler prints the `ExceptionFrame` value. If you run this you'll see something like this on the OpenOCD console. -``` console +``` text $ openocd (..) ExceptionFrame { @@ -248,7 +248,7 @@ and it points to the instruction that triggered the exception. If you look at the disassembly of the program: -``` console +``` text $ cargo objdump --bin app --release -- -d --no-show-raw-insn --print-imm-hex (..) ResetTrampoline: diff --git a/src/doc/embedded-book/src/start/hardware.md b/src/doc/embedded-book/src/start/hardware.md index 7d652a23f3..94221e4274 100644 --- a/src/doc/embedded-book/src/start/hardware.md +++ b/src/doc/embedded-book/src/start/hardware.md @@ -40,19 +40,19 @@ We'll start from scratch with a fresh template instance. Refer to the [previous section on QEMU]: qemu.md -``` console +``` text $ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart Project Name: app Creating project called `app`... Done! New project created /tmp/app - $ cd app +$ cd app ``` Step number one is to set a default compilation target in `.cargo/config`. ``` console -$ tail -n5 .cargo/config +tail -n5 .cargo/config ``` ``` toml @@ -68,7 +68,7 @@ We'll use `thumbv7em-none-eabihf` as that covers the Cortex-M4F core. The second step is to enter the memory region information into the `memory.x` file. -``` console +``` text $ cat memory.x /* Linker script for the STM32F303VCT6 */ MEMORY @@ -107,7 +107,7 @@ and inspect the binaries using `cargo-binutils` as you did before. The as helpfully, pretty much all Cortex-M CPUs boot in the same fashion. ``` console -$ cargo build --example hello +cargo build --example hello ``` ## Debugging @@ -131,7 +131,7 @@ Run this command from the root of the template; `openocd` will pick up the `openocd.cfg` file which indicates which interface file and target file to use. ``` console -$ cat openocd.cfg +cat openocd.cfg ``` ``` text @@ -153,7 +153,7 @@ source [find target/stm32f3x.cfg] > board during the [verify] section then you should modify the `openocd.cfg` > file at this point to use `interface/stlink-v2.cfg`. -``` console +``` text $ openocd Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 @@ -175,7 +175,7 @@ Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints On another terminal run GDB, also from the root of the template. -``` console +``` text $ -q target/thumbv7em-none-eabihf/debug/examples/hello ``` @@ -243,7 +243,7 @@ Advancing the program with `next` should produce the same results as before. At this point you should see "Hello, world!" printed on the OpenOCD console, among other stuff. -``` console +``` text $ openocd (..) Info : halted: PC: 0x08000e6c @@ -269,7 +269,7 @@ Program received signal SIGTRAP, Trace/breakpoint trap. It also causes this to be printed to the OpenOCD console: -``` console +``` text $ openocd (..) Info : halted: PC: 0x08001188 @@ -293,7 +293,7 @@ Debugging now requires a few more steps so we have packed all those steps into a single GDB script named `openocd.gdb`. The file was created during the `cargo generate` step, and should work without any modifications. Let's have a peak: ``` console -$ cat openocd.gdb +cat openocd.gdb ``` ``` text @@ -323,7 +323,7 @@ Alternatively, you can turn ` -x openocd.gdb` into a custom runner to make in `.cargo/config` but it's commented out. ``` console -$ head -n10 .cargo/config +head -n10 .cargo/config ``` ``` toml @@ -339,7 +339,7 @@ runner = "arm-none-eabi-gdb -x openocd.gdb" # runner = "gdb -x openocd.gdb" ``` -``` console +``` text $ cargo run --example hello (..) Loading section .vector_table, size 0x400 lma 0x8000000 diff --git a/src/doc/embedded-book/src/start/panicking.md b/src/doc/embedded-book/src/start/panicking.md index 584d2b25c6..10f7318bbf 100644 --- a/src/doc/embedded-book/src/start/panicking.md +++ b/src/doc/embedded-book/src/start/panicking.md @@ -97,7 +97,7 @@ fn main() -> ! { This example chose the `panic-semihosting` behavior which prints the panic message to the host console using semihosting. -``` console +``` text $ cargo run Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..) panicked at 'index out of bounds: the len is 3 but the index is 4', src/main.rs:12:13 diff --git a/src/doc/embedded-book/src/start/qemu.md b/src/doc/embedded-book/src/start/qemu.md index a8f7ece874..69866569c3 100644 --- a/src/doc/embedded-book/src/start/qemu.md +++ b/src/doc/embedded-book/src/start/qemu.md @@ -158,7 +158,7 @@ To cross compile for the Cortex-M3 architecture we have to use the Rust toolchain, it would now be a good time to add that target to the toolchain, if you haven't done it yet: ``` console -$ rustup target add thumbv7m-none-eabi +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: diff --git a/src/doc/embedded-book/src/start/semihosting.md b/src/doc/embedded-book/src/start/semihosting.md index 655e931bb4..feae1a0725 100644 --- a/src/doc/embedded-book/src/start/semihosting.md +++ b/src/doc/embedded-book/src/start/semihosting.md @@ -32,7 +32,7 @@ fn main() -> ! { If you run this program on hardware you'll see the "Hello, world!" message within the OpenOCD logs. -``` console +``` text $ openocd (..) Hello, world! @@ -51,7 +51,7 @@ 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 template. -``` console +``` text $ # this program will block the terminal $ cargo run Running `qemu-system-arm (..) @@ -86,7 +86,7 @@ fn main() -> ! { } ``` -``` console +``` text $ cargo run Running `qemu-system-arm (..) @@ -120,7 +120,7 @@ fn main() -> ! { } ``` -``` console +``` text $ cargo run Running `qemu-system-arm (..) panicked at 'assertion failed: `(left == right)` diff --git a/src/doc/embedded-book/src/unsorted/speed-vs-size.md b/src/doc/embedded-book/src/unsorted/speed-vs-size.md index a0fd9d61a4..da914e6ab9 100644 --- a/src/doc/embedded-book/src/unsorted/speed-vs-size.md +++ b/src/doc/embedded-book/src/unsorted/speed-vs-size.md @@ -58,7 +58,7 @@ opt-level = "z" # + Without the override: -``` console +``` text $ cargo size --bin app -- -A app : section size addr @@ -71,7 +71,7 @@ section size addr With the override: -``` console +``` text $ cargo size --bin app -- -A app : section size addr diff --git a/src/doc/nomicon/src/send-and-sync.md b/src/doc/nomicon/src/send-and-sync.md index 87d0d3003d..9742328274 100644 --- a/src/doc/nomicon/src/send-and-sync.md +++ b/src/doc/nomicon/src/send-and-sync.md @@ -74,7 +74,184 @@ of their pervasive use of raw pointers to manage allocations and complex ownersh Similarly, most iterators into these collections are Send and Sync because they largely behave like an `&` or `&mut` into the collection. +## Example + +[`Box`][box-doc] is implemented as it's own special intrinsic type by the +compiler for [various reasons][box-is-special], but we can implement something +with similar-ish behavior ourselves to see an example of when it is sound to +implement Send and Sync. Let's call it a `Carton`. + +We start by writing code to take a value allocated on the stack and transfer it +to the heap. + +```rust +# pub mod libc { +# pub use ::std::os::raw::{c_int, c_void}; +# #[allow(non_camel_case_types)] +# pub type size_t = usize; +# extern "C" { pub fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int; } +# } +use std::{ + mem::{align_of, size_of}, + ptr, +}; + +struct Carton(ptr::NonNull); + +impl Carton { + pub fn new(value: T) -> Self { + // Allocate enough memory on the heap to store one T. + assert_ne!(size_of::(), 0, "Zero-sized types are out of the scope of this example"); + let mut memptr = ptr::null_mut() as *mut T; + unsafe { + let ret = libc::posix_memalign( + (&mut memptr).cast(), + align_of::(), + size_of::() + ); + assert_eq!(ret, 0, "Failed to allocate or invalid alignment"); + }; + + // NonNull is just a wrapper that enforces that the pointer isn't null. + let mut ptr = unsafe { + // Safety: memptr is dereferenceable because we created it from a + // reference and have exclusive access. + ptr::NonNull::new(memptr.cast::()) + .expect("Guaranteed non-null if posix_memalign returns 0") + }; + + // Move value from the stack to the location we allocated on the heap. + unsafe { + // Safety: If non-null, posix_memalign gives us a ptr that is valid + // for writes and properly aligned. + ptr.as_ptr().write(value); + } + + Self(ptr) + } +} +``` + +This isn't very useful, because once our users give us a value they have no way +to access it. [`Box`][box-doc] implements [`Deref`][deref-doc] and +[`DerefMut`][deref-mut-doc] so that you can access the inner value. Let's do +that. + +```rust +use std::ops::{Deref, DerefMut}; + +# struct Carton(std::ptr::NonNull); +# +impl Deref for Carton { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { + // Safety: The pointer is aligned, initialized, and dereferenceable + // by the logic in [`Self::new`]. We require writers to borrow the + // Carton, and the lifetime of the return value is elided to the + // lifetime of the input. This means the borrow checker will + // enforce that no one can mutate the contents of the Carton until + // the reference returned is dropped. + self.0.as_ref() + } + } +} + +impl DerefMut for Carton { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + // Safety: The pointer is aligned, initialized, and dereferenceable + // by the logic in [`Self::new`]. We require writers to mutably + // borrow the Carton, and the lifetime of the return value is + // elided to the lifetime of the input. This means the borrow + // checker will enforce that no one else can access the contents + // of the Carton until the mutable reference returned is dropped. + self.0.as_mut() + } + } +} +``` + +Finally, let's think about whether our `Carton` is Send and Sync. Something can +safely be Send unless it shares mutable state with something else without +enforcing exclusive access to it. Each `Carton` has a unique pointer, so +we're good. + +```rust +# struct Carton(std::ptr::NonNull); +// Safety: No one besides us has the raw pointer, so we can safely transfer the +// Carton to another thread if T can be safely transferred. +unsafe impl Send for Carton where T: Send {} +``` + +What about Sync? For `Carton` to be Sync we have to enforce that you can't +write to something stored in a `&Carton` while that same something could be read +or written to from another `&Carton`. Since you need an `&mut Carton` to +write to the pointer, and the borrow checker enforces that mutable +references must be exclusive, there are no soundness issues making `Carton` +sync either. + +```rust +# struct Carton(std::ptr::NonNull); +// Safety: Since there exists a public way to go from a `&Carton` to a `&T` +// in an unsynchronized fashion (such as `Deref`), then `Carton` can't be +// `Sync` if `T` isn't. +// Conversely, `Carton` itself does not use any interior mutability whatsoever: +// all the mutations are performed through an exclusive reference (`&mut`). This +// means it suffices that `T` be `Sync` for `Carton` to be `Sync`: +unsafe impl Sync for Carton where T: Sync {} +``` + +When we assert our type is Send and Sync we usually need to enforce that every +contained type is Send and Sync. When writing custom types that behave like +standard library types we can assert that we have the same requirements. +For example, the following code asserts that a Carton is Send if the same +sort of Box would be Send, which in this case is the same as saying T is Send. + +```rust +# struct Carton(std::ptr::NonNull); +unsafe impl Send for Carton where Box: Send {} +``` + +Right now `Carton` has a memory leak, as it never frees the memory it allocates. +Once we fix that we have a new requirement we have to ensure we meet to be Send: +we need to know `free` can be called on a pointer that was yielded by an +allocation done on another thread. We can check this is true in the docs for +[`libc::free`][libc-free-docs]. + +```rust +# struct Carton(std::ptr::NonNull); +# mod libc { +# pub use ::std::os::raw::c_void; +# extern "C" { pub fn free(p: *mut c_void); } +# } +impl Drop for Carton { + fn drop(&mut self) { + unsafe { + libc::free(self.0.as_ptr().cast()); + } + } +} +``` + +A nice example where this does not happen is with a MutexGuard: notice how +[it is not Send][mutex-guard-not-send-docs-rs]. The implementation of MutexGuard +[uses libraries][mutex-guard-not-send-comment] that require you to ensure you +don't try to free a lock that you acquired in a different thread. If you were +able to Send a MutexGuard to another thread the destructor would run in the +thread you sent it to, violating the requirement. MutexGuard can still be Sync +because all you can send to another thread is an `&MutexGuard` and dropping a +reference does nothing. + TODO: better explain what can or can't be Send or Sync. Sufficient to appeal only to data races? [unsafe traits]: safe-unsafe-meaning.html +[box-doc]: https://doc.rust-lang.org/std/boxed/struct.Box.html +[box-is-special]: https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/ +[deref-doc]: https://doc.rust-lang.org/core/ops/trait.Deref.html +[deref-mut-doc]: https://doc.rust-lang.org/core/ops/trait.DerefMut.html +[mutex-guard-not-send-docs-rs]: https://doc.rust-lang.org/std/sync/struct.MutexGuard.html#impl-Send +[mutex-guard-not-send-comment]: https://github.com/rust-lang/rust/issues/23465#issuecomment-82730326 +[libc-free-docs]: https://linux.die.net/man/3/free diff --git a/src/doc/reference/STYLE.md b/src/doc/reference/STYLE.md index f265aab3b2..07621275c6 100644 --- a/src/doc/reference/STYLE.md +++ b/src/doc/reference/STYLE.md @@ -3,18 +3,15 @@ Some conventions and content guidelines are specified in the [introduction]. This document serves as a guide for editors and reviewers. -There is a [`style-check`](style-check/) tool which is run in CI to check some -of these. To use it locally, run -`cargo run --manifest-path=style-check/Cargo.toml src`. +There is a [`style-check`](style-check/) tool which is run in CI to check some of these. To use it locally, run `cargo run --manifest-path=style-check/Cargo.toml src`. ## Markdown formatting * Use ATX-style heading with sentence case. -* Wrap long lines, preferably at 80-columns. -* Use reference links, with shortcuts if appropriate. Place the sorted link - reference definitions at the bottom of the file, or at the bottom of a - section if there is an unusually large number of links that are specific to - the section. +* Use one line per sentence to make diffs nicer. + Do not wrap long lines. +* Use reference links, with shortcuts if appropriate. + Place the sorted link reference definitions at the bottom of the file, or at the bottom of a section if there is an unusually large number of links that are specific to the section. ``` Example of shortcut link: [enumerations] @@ -24,19 +21,17 @@ of these. To use it locally, run [enumerations]: types/enum.md ``` -* Links should be relative with the `.md` extension. Links to other rust-lang - books that are published with the reference or the standard library API - should also be relative so that the linkchecker can validate them. -* See the [Conventions] section for formatting callouts such as notes, edition - differences, and warnings. +* Links should be relative with the `.md` extension. + Links to other rust-lang books that are published with the reference or the standard library API should also be relative so that the linkchecker can validate them. +* See the [Conventions] section for formatting callouts such as notes, edition differences, and warnings. * Formatting to avoid: * Avoid trailing spaces. * Avoid double blank lines. ### Code examples -Code examples should use code blocks with triple backticks. The language -should always be specified (such as `rust`). +Code examples should use code blocks with triple backticks. +The language should always be specified (such as `rust`). ```rust println!("Hello!"); @@ -44,20 +39,16 @@ println!("Hello!"); See https://highlightjs.org/ for a list of supported languages. -Rust examples are tested via rustdoc, and should include the appropriate -annotations when tests are expected to fail: +Rust examples are tested via rustdoc, and should include the appropriate annotations when tests are expected to fail: * `edition2018` — If it is edition-specific. -* `no_run` — The example should compile successfully, but should not be - executed. +* `no_run` — The example should compile successfully, but should not be executed. * `should_panic` — The example should compile and run, but produce a panic. * `compile_fail` — The example is expected to fail to compile. -* `ignore` — The example shouldn't be built or tested. This should be avoided - if possible. Usually this is only necessary when the testing framework does - not support it (such as external crates or modules, or a proc-macro), or it - contains psuedo-code which is not valid Rust. An HTML comment such as - `` should be placed before the example - to explain why it is ignored. +* `ignore` — The example shouldn't be built or tested. + This should be avoided if possible. + Usually this is only necessary when the testing framework does not support it (such as external crates or modules, or a proc-macro), or it contains pseudo-code which is not valid Rust. + An HTML comment such as `` should be placed before the example to explain why it is ignored. See the [rustdoc documentation] for more detail. @@ -66,18 +57,14 @@ See the [rustdoc documentation] for more detail. * Use American English spelling. * Use Oxford commas. * Idioms and styling to avoid: - * Avoid slashes for alternatives ("program/binary"), use conjunctions or - rewrite it ("program or binary"). - * Avoid qualifying something as "in Rust", the entire reference is about - Rust. + * Avoid slashes for alternatives ("program/binary"), use conjunctions or rewrite it ("program or binary"). + * Avoid qualifying something as "in Rust", the entire reference is about Rust. ## Content -* Whenever there is a difference between editions, the differences should be - called out with an "Edition Differences" block. The main text should stick - to what is common between the editions. However, for large differences (such - as "async"), the main text may contain edition-specific content as long as - it is made clear which editions it applies to. +* Whenever there is a difference between editions, the differences should be called out with an "Edition Differences" block. + The main text should stick to what is common between the editions. + However, for large differences (such as "async"), the main text may contain edition-specific content as long as it is made clear which editions it applies to. [conventions]: src/introduction.md#conventions [introduction]: src/introduction.md diff --git a/src/doc/reference/src/attributes/diagnostics.md b/src/doc/reference/src/attributes/diagnostics.md index 6a972d3223..dd07fdb84f 100644 --- a/src/doc/reference/src/attributes/diagnostics.md +++ b/src/doc/reference/src/attributes/diagnostics.md @@ -39,6 +39,11 @@ pub mod m1 { } ``` +Lint attributes can override the level specified from a previous attribute, as +long as the level does not attempt to change a forbidden lint. Previous +attributes are those from a higher level in the syntax tree, or from a +previous attribute on the same entity as listed in left-to-right source order. + This example shows how one can use `allow` and `warn` to toggle a particular check on and off: @@ -74,13 +79,54 @@ pub mod m3 { } ``` +> Note: `rustc` allows setting lint levels on the +> [command-line][rustc-lint-cli], and also supports [setting +> caps][rustc-lint-caps] on the lints that are reported. + +### Lint groups + +Lints may be organized into named groups so that the level of related lints +can be adjusted together. Using a named group is equivalent to listing out the +lints within that group. + +```rust,compile_fail +// This allows all lints in the "unused" group. +#[allow(unused)] +// This overrides the "unused_must_use" lint from the "unused" +// group to deny. +#[deny(unused_must_use)] +fn example() { + // This does not generate a warning because the "unused_variables" + // lint is in the "unused" group. + let x = 1; + // This generates an error because the result is unused and + // "unused_must_use" is marked as "deny". + std::fs::remove_file("some_file"); // ERROR: unused `Result` that must be used +} +``` + +There is a special group named "warnings" which includes all lints at the +"warn" level. The "warnings" group ignores attribute order and applies to all +lints that would otherwise warn within the entity. + +```rust,compile_fail +# unsafe fn an_unsafe_fn() {} +// The order of these two attributes does not matter. +#[deny(warnings)] +// The unsafe_code lint is normally "allow" by default. +#[warn(unsafe_code)] +fn example_err() { + // This is an error because the `unsafe_code` warning has + // been lifted to "deny". + unsafe { an_unsafe_fn() } // ERROR: usage of `unsafe` block +} +``` + ### Tool lint attributes Tool lints allows using scoped lints, to `allow`, `warn`, `deny` or `forbid` lints of certain tools. -Currently `clippy` is the only available lint tool. - Tool lints only get checked when the associated tool is active. If a lint attribute, such as `allow`, references a nonexistent tool lint, the compiler will not warn about the nonexistent lint until you use the tool. @@ -104,6 +150,8 @@ fn foo() { } ``` +> Note: `rustc` currently recognizes the tool lints for "[clippy]" and "[rustdoc]". + ## The `deprecated` attribute The *`deprecated` attribute* marks an item as deprecated. `rustc` will issue @@ -274,6 +322,9 @@ When used on a function in a trait implementation, the attribute does nothing. [macro definition]: ../macros-by-example.md [module]: ../items/modules.md [rustc book]: ../../rustc/lints/index.html +[rustc-lint-caps]: ../../rustc/lints/levels.html#capping-lints +[rustc-lint-cli]: ../../rustc/lints/levels.html#via-compiler-flag +[rustdoc]: ../../rustdoc/lints.html [struct field]: ../items/structs.md [struct]: ../items/structs.md [trait declaration]: ../items/traits.md diff --git a/src/doc/reference/src/attributes/limits.md b/src/doc/reference/src/attributes/limits.md index 1cb80e302d..446c33093a 100644 --- a/src/doc/reference/src/attributes/limits.md +++ b/src/doc/reference/src/attributes/limits.md @@ -29,8 +29,8 @@ a!{} ```rust,compile_fail #![recursion_limit = "1"] -// This fails because it requires two recursive steps to auto-derefence. -(|_: &u8| {})(&&1); +// This fails because it requires two recursive steps to auto-dereference. +(|_: &u8| {})(&&&1); ``` ## The `type_length_limit` attribute diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index 1cc7966bfd..5af4a4bef7 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -23,7 +23,9 @@ code. * Data races. -* Dereferencing (using the `*` operator on) a dangling or unaligned raw pointer. +* Evaluating a [dereference expression] (`*expr`) on a raw pointer that is + [dangling] or unaligned, even in [place expression context] + (e.g. `addr_of!(&*expr)`). * Breaking the [pointer aliasing rules]. `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T` contains an [`UnsafeCell`]. * Mutating immutable data. All data inside a [`const`] item is immutable. Moreover, all @@ -45,7 +47,7 @@ code. * A `!` (all values are invalid for this type). * An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer obtained from [uninitialized memory][undef], or uninitialized memory in a `str`. - * A reference or `Box` that is dangling, unaligned, or points to an invalid value. + * A reference or `Box` that is [dangling], unaligned, or points to an invalid value. * Invalid metadata in a wide reference, `Box`, or raw pointer: * `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. @@ -62,6 +64,15 @@ a restricted set of valid values. In other words, the only cases in which reading uninitialized memory is permitted are inside `union`s and in "padding" (the gaps between the fields/elements of a type). +> **Note**: Undefined behavior affects the entire program. For example, calling +> a function in C that exhibits undefined behavior of C means your entire +> program contains undefined behaviour that can also affect the Rust code. And +> vice versa, undefined behavior in Rust can cause adverse affects on code +> executed by any FFI calls to other languages. + +### Dangling pointers +[dangling]: #dangling-pointers + A reference/pointer is "dangling" if it is null or not all of the bytes it points to are part of the same allocation (so in particular they all have to be part of *some* allocation). The span of bytes it points to is determined by the @@ -71,12 +82,6 @@ that slices and strings point to their entire range, so it is important that the metadata is never too large. In particular, allocations and therefore slices and strings cannot be bigger than `isize::MAX` bytes. -> **Note**: Undefined behavior affects the entire program. For example, calling -> a function in C that exhibits undefined behavior of C means your entire -> program contains undefined behaviour that can also affect the Rust code. And -> vice versa, undefined behavior in Rust can cause adverse affects on code -> executed by any FFI calls to other languages. - [`bool`]: types/boolean.md [`const`]: items/constant-items.md [noalias]: http://llvm.org/docs/LangRef.html#noalias @@ -87,3 +92,5 @@ cannot be bigger than `isize::MAX` bytes. [Rustonomicon]: ../nomicon/index.html [`NonNull`]: ../core/ptr/struct.NonNull.html [`NonZero*`]: ../core/num/index.html +[dereference expression]: expressions/operator-expr.md#the-dereference-operator +[place expression context]: expressions.md#place-expressions-and-value-expressions diff --git a/src/doc/reference/src/const_eval.md b/src/doc/reference/src/const_eval.md index 4f67165300..4874a73724 100644 --- a/src/doc/reference/src/const_eval.md +++ b/src/doc/reference/src/const_eval.md @@ -59,6 +59,7 @@ A _const context_ is one of the following: * [constants] * [statics] * [enum discriminants] +* A [const generic argument] ## Const Functions @@ -96,7 +97,8 @@ Notable features that const contexts have, but const fn haven't are: Conversely, the following are possible in a const function, but not in a const context: -* Use of generic parameters. +* Use of generic type and lifetime parameters. + * Const contexts do allow limited use of [const generic parameters]. [arithmetic]: expressions/operator-expr.md#arithmetic-and-logical-binary-operators [array expressions]: expressions/array-expr.md @@ -111,6 +113,8 @@ Conversely, the following are possible in a const function, but not in a const c [closure expressions]: expressions/closure-expr.md [comparison]: expressions/operator-expr.md#comparison-operators [const functions]: items/functions.md#const-functions +[const generic argument]: items/generics.md#const-generics +[const generic parameters]: items/generics.md#const-generics [constants]: items/constant-items.md [Const parameters]: items/generics.md [dereference operator]: expressions/operator-expr.md#the-dereference-operator diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md index 09b433365a..aaa25af037 100644 --- a/src/doc/reference/src/expressions.md +++ b/src/doc/reference/src/expressions.md @@ -55,6 +55,9 @@ In this way, the structure of expressions dictates the structure of execution. Blocks are just another kind of expression, so blocks, statements, expressions, and blocks again can recursively nest inside each other to an arbitrary depth. +> **Note**: We give names to the operands of expressions so that we may discuss +> them, but these names are not stable and may be changed. + ## Expression precedence The precedence of Rust operators and expressions is ordered as follows, going @@ -137,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, sub-expressions 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. diff --git a/src/doc/reference/src/expressions/array-expr.md b/src/doc/reference/src/expressions/array-expr.md index 2659b229e8..5f50f09cb4 100644 --- a/src/doc/reference/src/expressions/array-expr.md +++ b/src/doc/reference/src/expressions/array-expr.md @@ -10,21 +10,28 @@ >       [_Expression_] ( `,` [_Expression_] )\* `,`?\ >    | [_Expression_] `;` [_Expression_] -An _[array] expression_ can be written by enclosing zero or more comma-separated expressions of uniform type in square brackets. +*Array expressions* construct [arrays][array]. +Array expressions come in two forms. + +The first form lists out every value in the array. +The syntax for this form is a comma-separated list of expressions of uniform type enclosed in square brackets. This produces an array containing each of these values in the order they are written. -Alternatively there can be exactly two expressions inside the brackets, separated by a semicolon. -The expression after the `;` must have type `usize` and be a [constant expression], such as a [literal] or a [constant item]. -`[a; b]` creates an array containing `b` copies of the value of `a`. -If the expression after the semicolon has a value greater than 1 then this requires that the type of `a` is [`Copy`], or `a` must be a path to a constant item. +The syntax for the second form is two expressions separated by a semicolon (`;`) enclosed in square brackets. +The expression before the `;` is called the *repeat operand*. +The expression after the `;` is called the *length operand*. +It must have type `usize` and be a [constant expression], such as a [literal] or a [constant item]. +An array expression of this form creates an array with the length of the value of the legnth operand with each element a copy of the repeat operand. +That is, `[a; b]` creates an array containing `b` copies of the value of `a`. +If the length operand has a value greater than 1 then this requires that the type of the repeat operand is [`Copy`] or that it must be a [path] to a constant item. -When the repeat expression `a` is a constant item, it is evaluated `b` times. -If `b` is 0, the constant item is not evaluated at all. -For expressions that are not a constant item, it is evaluated exactly once, and then the result is copied `b` times. +When the repeat operand is a constant item, it is evaluated the length operand's value times. +If that value is `0`, then the constant item is not evaluated at all. +For expressions that are not a constant item, it is evaluated exactly once, and then the result is copied the length operand's value times.
-Warning: In the case where `b` is 0, and `a` is a non-constant item, there is currently a bug in `rustc` where the value `a` is evaluated but not dropped, thus causing a leak. +Warning: In the case where the length operand is 0, and the repeat operand is a non-constant item, there is currently a bug in `rustc` where the value `a` is evaluated but not dropped, thus causing a leak. See [issue #74836](https://github.com/rust-lang/rust/issues/74836).
@@ -49,7 +56,7 @@ const EMPTY: Vec = Vec::new(); > _IndexExpression_ :\ >    [_Expression_] `[` [_Expression_] `]` -[Array] and [slice]-typed expressions can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them. +[Array] and [slice]-typed values can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them. When the array is mutable, the resulting [memory location] can be assigned to. For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::ops::IndexMut::index_mut(&mut a, b)` in a mutable place expression context. @@ -91,4 +98,5 @@ The array index expression can be implemented for types other than arrays and sl [constant item]: ../items/constant-items.md [literal]: ../tokens.md#literals [memory location]: ../expressions.md#place-expressions-and-value-expressions +[path]: path-expr.md [slice]: ../types/slice.md diff --git a/src/doc/reference/src/expressions/await-expr.md b/src/doc/reference/src/expressions/await-expr.md index 509a70e831..e7fc45d27b 100644 --- a/src/doc/reference/src/expressions/await-expr.md +++ b/src/doc/reference/src/expressions/await-expr.md @@ -4,28 +4,18 @@ > _AwaitExpression_ :\ >    [_Expression_] `.` `await` +*Await expressions* suspend the current computation until the given future is ready to produce a value. +The syntax for an await expression is an expression with a type that implements the [Future] trait, called the *future operand*, then the token `.`, and then the `await` keyword. Await expressions are legal only within an [async context], like an [`async fn`] or an [`async` block]. -They operate on a [future]. -Their effect is to suspend the current computation until the given future is ready to produce a value. -More specifically, an `.await` expression has the following effect. +More specifically, an await expression has the following effect. -1. Evaluate `` to a [future] `tmp`; +1. Evaluate the future operand to a [future] `tmp`; 2. Pin `tmp` using [`Pin::new_unchecked`]; 3. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context); 3. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 2; 4. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself. -[`async fn`]: ../items/functions.md#async-functions -[`async` block]: block-expr.md#async-blocks -[future]: ../../std/future/trait.Future.html -[_Expression_]: ../expressions.md -[`Future::poll`]: ../../std/future/trait.Future.html#tymethod.poll -[`Context`]: ../../std/task/struct.Context.html -[`Pin::new_unchecked`]: ../../std/pin/struct.Pin.html#method.new_unchecked -[`Poll::Pending`]: ../../std/task/enum.Poll.html#variant.Pending -[`Poll::Ready`]: ../../std/task/enum.Poll.html#variant.Ready - > **Edition differences**: Await expressions are only available beginning with Rust 2018. ## Task context @@ -33,16 +23,13 @@ More specifically, an `.await` expression has the following effect. The task context refers to the [`Context`] which was supplied to the current [async context] when the async context itself was polled. Because `await` expressions are only legal in an async context, there must be some task context available. -[`Context`]: ../../std/task/struct.Context.html -[async context]: ../expressions/block-expr.md#async-context - ## Approximate desugaring -Effectively, an `.await` expression is roughly equivalent to the following (this desugaring is not normative): +Effectively, an await expression is roughly equivalent to the following non-normative desugaring: ```rust,ignore -match /* */ { +match future_operand { mut pinned => loop { let mut pin = unsafe { Pin::new_unchecked(&mut pinned) }; match Pin::future::poll(Pin::borrow(&mut pin), &mut current_context) { @@ -55,3 +42,14 @@ match /* */ { where the `yield` pseudo-code returns `Poll::Pending` and, when re-invoked, resumes execution from that point. The variable `current_context` refers to the context taken from the async environment. + +[_Expression_]: ../expressions.md +[`async fn`]: ../items/functions.md#async-functions +[`async` block]: block-expr.md#async-blocks +[`context`]: ../../std/task/struct.Context.html +[`future::poll`]: ../../std/future/trait.Future.html#tymethod.poll +[`pin::new_unchecked`]: ../../std/pin/struct.Pin.html#method.new_unchecked +[`poll::Pending`]: ../../std/task/enum.Poll.html#variant.Pending +[`poll::Ready`]: ../../std/task/enum.Poll.html#variant.Ready +[async context]: ../expressions/block-expr.md#async-context +[future]: ../../std/future/trait.Future.html diff --git a/src/doc/reference/src/expressions/block-expr.md b/src/doc/reference/src/expressions/block-expr.md index 6d418e7452..deece94caf 100644 --- a/src/doc/reference/src/expressions/block-expr.md +++ b/src/doc/reference/src/expressions/block-expr.md @@ -16,16 +16,19 @@ A *block expression*, or *block*, is a control flow expression and anonymous nam As a control flow expression, a block sequentially executes its component non-item declaration statements and then its final optional expression. As an anonymous namespace scope, item declarations are only in scope inside the block itself and variables declared by `let` statements are in scope from the next statement until the end of the block. -Blocks are written as `{`, then any [inner attributes], then [statements], then an optional expression, and finally a `}`. -Statements are usually required to be followed by a semicolon, with two exceptions. -Item declaration statements do not need to be followed by a semicolon. -Expression statements usually require a following semicolon except if its outer expression is a flow control expression. +The syntax for a block is `{`, then any [inner attributes], then any number of [statements], then an optional expression, called the final operand, and finally a `}`. + +Statements are usually required to be followed by a semicolon, with two exceptions: + +1. Item declaration statements do not need to be followed by a semicolon. +2. Expression statements usually require a following semicolon except if its outer expression is a flow control expression. + Furthermore, extra semicolons between statements are allowed, but these semicolons do not affect semantics. When evaluating a block expression, each statement, except for item declaration statements, is executed sequentially. -Then the final expression is executed, if given. +Then the final operand is executed, if given. -The type of a block is the type of the final expression, or `()` if the final expression is omitted. +The type of a block is the type of the final operand, or `()` if the final operand is omitted. ```rust # fn fn_call() {} @@ -43,28 +46,29 @@ assert_eq!(5, five); > Note: As a control flow expression, if a block expression is the outer expression of an expression statement, the expected type is `()` unless it is followed immediately by a semicolon. -Blocks are always [value expressions] and evaluate the last expression in value expression context. -This can be used to force moving a value if really needed. -For example, the following example fails on the call to `consume_self` because the struct was moved out of `s` in the block expression. - -```rust,compile_fail -struct Struct; - -impl Struct { - fn consume_self(self) {} - fn borrow_self(&self) {} -} - -fn move_by_block_expression() { - let s = Struct; - - // Move the value out of `s` in the block expression. - (&{ s }).borrow_self(); +Blocks are always [value expressions] and evaluate the last operand in value expression context. - // Fails to execute because `s` is moved out of. - s.consume_self(); -} -``` +> **Note**: This can be used to force moving a value if really needed. +> For example, the following example fails on the call to `consume_self` because the struct was moved out of `s` in the block expression. +> +> ```rust,compile_fail +> struct Struct; +> +> impl Struct { +> fn consume_self(self) {} +> fn borrow_self(&self) {} +> } +> +> fn move_by_block_expression() { +> let s = Struct; +> +> // Move the value out of `s` in the block expression. +> (&{ s }).borrow_self(); +> +> // Fails to execute because `s` is moved out of. +> s.consume_self(); +> } +> ``` ## `async` blocks @@ -72,7 +76,7 @@ fn move_by_block_expression() { > _AsyncBlockExpression_ :\ >    `async` `move`? _BlockExpression_ -An *async block* is a variant of a block expression which evaluates to a *future*. +An *async block* is a variant of a block expression which evaluates to a future. The final expression of the block, if present, determines the result value of the future. Executing an async block is similar to executing a closure expression: @@ -84,26 +88,17 @@ The actual data format for this type is unspecified. > **Edition differences**: Async blocks are only available beginning with Rust 2018. -[`std::ops::Fn`]: ../../std/ops/trait.Fn.html -[`std::future::Future`]: ../../std/future/trait.Future.html - ### Capture modes Async blocks capture variables from their environment using the same [capture modes] as closures. Like closures, when written `async { .. }` the capture mode for each variable will be inferred from the content of the block. `async move { .. }` blocks however will move all referenced variables into the resulting future. -[capture modes]: ../types/closure.md#capture-modes -[shared references]: ../types/pointer.md#shared-references- -[mutable reference]: ../types/pointer.md#mutables-references- - ### Async context Because async blocks construct a future, they define an **async context** which can in turn contain [`await` expressions]. Async contexts are established by async blocks as well as the bodies of async functions, whose semantics are defined in terms of async blocks. -[`await` expressions]: await-expr.md - ### Control-flow operators Async blocks act like a function boundary, much like closures. @@ -171,16 +166,22 @@ fn is_unix_platform() -> bool { [_ExpressionWithoutBlock_]: ../expressions.md [_InnerAttribute_]: ../attributes.md [_Statement_]: ../statements.md +[`await` expressions]: await-expr.md [`cfg`]: ../conditional-compilation.md [`for`]: loop-expr.md#iterator-loops [`loop`]: loop-expr.md#infinite-loops +[`std::ops::Fn`]: ../../std/ops/trait.Fn.html +[`std::future::Future`]: ../../std/future/trait.Future.html [`while let`]: loop-expr.md#predicate-pattern-loops [`while`]: loop-expr.md#predicate-loops [array expressions]: array-expr.md [call expressions]: call-expr.md +[capture modes]: ../types/closure.md#capture-modes [function]: ../items/functions.md [inner attributes]: ../attributes.md [method]: ../items/associated-items.md#methods +[mutable reference]: ../types/pointer.md#mutables-references- +[shared references]: ../types/pointer.md#shared-references- [statement]: ../statements.md [statements]: ../statements.md [struct]: struct-expr.md diff --git a/src/doc/reference/src/expressions/call-expr.md b/src/doc/reference/src/expressions/call-expr.md index 0992f5e9f8..577f3f4329 100644 --- a/src/doc/reference/src/expressions/call-expr.md +++ b/src/doc/reference/src/expressions/call-expr.md @@ -7,12 +7,13 @@ > _CallParams_ :\ >    [_Expression_] ( `,` [_Expression_] )\* `,`? -A _call expression_ consists of an expression followed by a parenthesized expression-list. -It invokes a function, providing zero or more input variables. +A *call expression* calls a function. +The syntax of a call expression is an expression, called the *function operand*, followed by a parenthesized comma-separated list of expression, called the *argument operands*. If the function eventually returns, then the expression completes. -For [non-function types](../types/function-item.md), the expression f(...) uses the method on one of the [`std::ops::Fn`], [`std::ops::FnMut`] or [`std::ops::FnOnce`] traits, which differ in whether they take the type by reference, mutable reference, or take ownership respectively. +For [non-function types], the expression `f(...)` uses the method on one of the [`std::ops::Fn`], [`std::ops::FnMut`] or [`std::ops::FnOnce`] traits, which differ in whether they take the type by reference, mutable reference, or take ownership respectively. An automatic borrow will be taken if needed. -Rust will also automatically dereference `f` as required. +The function operand will also be [automatically dereferenced] as required. + Some examples of call expressions: ```rust @@ -23,13 +24,12 @@ let name: &'static str = (|| "Rust")(); ## Disambiguating Function Calls -Rust treats all function calls as sugar for a more explicit, [fully-qualified syntax]. -Upon compilation, Rust will desugar all function calls into the explicit form. -Rust may sometimes require you to qualify function calls with trait, depending on the ambiguity of a call in light of in-scope items. +All function calls are sugar for a more explicit [fully-qualified syntax]. +Function calls may need to be fully qualified, depending on the ambiguity of a call in light of in-scope items. -> **Note**: In the past, the Rust community used the terms "Unambiguous Function Call Syntax", "Universal Function Call Syntax", or "UFCS", in documentation, issues, RFCs, and other community writings. -> However, the term lacks descriptive power and potentially confuses the issue at hand. -> We mention it here for searchability's sake. +> **Note**: In the past, the terms "Unambiguous Function Call Syntax", "Universal Function Call Syntax", or "UFCS", have been used in documentation, issues, RFCs, and other community writings. +> However, these terms lack descriptive power and potentially confuse the issue at hand. +> We mention them here for searchability's sake. Several situations often occur which result in ambiguities about the receiver or referent of method or associated function calls. These situations may include: @@ -92,4 +92,6 @@ Refer to [RFC 132] for further details and motivations. [`std::ops::FnMut`]: ../../std/ops/trait.FnMut.html [`std::ops::FnOnce`]: ../../std/ops/trait.FnOnce.html [`std::ops::Fn`]: ../../std/ops/trait.Fn.html +[automatically dereferenced]: field-expr.md#automatic-dereferencing [fully-qualified syntax]: ../paths.md#qualified-paths +[non-function types]: ../types/function-item.md diff --git a/src/doc/reference/src/expressions/closure-expr.md b/src/doc/reference/src/expressions/closure-expr.md index 3669846119..bdc177bb56 100644 --- a/src/doc/reference/src/expressions/closure-expr.md +++ b/src/doc/reference/src/expressions/closure-expr.md @@ -10,29 +10,30 @@ >    _ClosureParam_ (`,` _ClosureParam_)\* `,`? > > _ClosureParam_ :\ ->    [_OuterAttribute_]\* [_Pattern_] ( `:` [_Type_] )? +>    [_OuterAttribute_]\* [_PatternNoTopAlt_] ( `:` [_Type_] )? -A _closure expression_, also know as a lambda expression or a lambda, defines a closure and denotes it as a value, in a single expression. -A closure expression is a pipe-symbol-delimited (`|`) list of irrefutable [patterns] followed by an expression. -Type annotations may optionally be added for the type of the parameters or for the return type. -If there is a return type, the expression used for the body of the closure must be a normal [block]. -A closure expression also may begin with the `move` keyword before the initial `|`. +A *closure expression*, also know as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type. +The syntax for a closure expression is an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], called the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, called the *return type*, and then an expression, called the *closure body operand*. +The optional type after each pattern is a type annotation for the pattern. +If there is a return type, the closure body must be a [block]. A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters. -Just like a [`let` binding], the parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given. +Just like a [`let` binding], the closure parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given. Each closure expression has a unique, anonymous type. -Closure expressions are most useful when passing functions as arguments to other functions, as an abbreviation for defining and capturing a separate function. - Significantly, closure expressions _capture their environment_, which regular [function definitions] do not. Without the `move` keyword, the closure expression [infers how it captures each variable from its environment](../types/closure.md#capture-modes), preferring to capture by shared reference, effectively borrowing all outer variables mentioned inside the closure's body. If needed the compiler will infer that instead mutable references should be taken, or that the values should be moved or copied (depending on their type) from the environment. A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword. -This is often used to ensure that the closure's type is `'static`. +This is often used to ensure that the closure's lifetime is `'static`. + +## Closure trait implementations + +Which traits the closure type implement depends on how variables are captured and the types of the captured variables. +See the [call traits and coercions] chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`. +The closure type implements [`Send`] and [`Sync`] if the type of every captured variable also implements the trait. -The compiler will determine which of the [closure traits](../types/closure.md#call-traits-and-coercions) the closure's type will implement by how it acts on its captured variables. -The closure will also implement [`Send`](../special-types-and-traits.md#send) and/or [`Sync`](../special-types-and-traits.md#sync) if all of its captured types do. -These traits allow functions to accept closures using generics, even though the exact types can't be named. +## Example In this example, we define a function `ten_times` that takes a higher-order function argument, and we then call it with a closure expression as an argument, followed by a closure expression that moves values from its environment. @@ -55,15 +56,18 @@ ten_times(move |j| println!("{}, {}", word, j)); Attributes on closure parameters follow the same rules and restrictions as [regular function parameters]. -[block]: block-expr.md -[function definitions]: ../items/functions.md -[patterns]: ../patterns.md -[regular function parameters]: ../items/functions.md#attributes-on-function-parameters - [_Expression_]: ../expressions.md [_BlockExpression_]: block-expr.md [_TypeNoBounds_]: ../types.md#type-expressions -[_Pattern_]: ../patterns.md +[_PatternNoTopAlt_]: ../patterns.md [_Type_]: ../types.md#type-expressions [`let` binding]: ../statements.md#let-statements +[`Send`]: ../special-types-and-traits.md#send +[`Sync`]: ../special-types-and-traits.md#sync [_OuterAttribute_]: ../attributes.md +[block]: block-expr.md +[call traits and coercions]: ../types/closure.md#call-traits-and-coercions +[closure type]: ../types/closure.md +[function definitions]: ../items/functions.md +[patterns]: ../patterns.md +[regular function parameters]: ../items/functions.md#attributes-on-function-parameters diff --git a/src/doc/reference/src/expressions/field-expr.md b/src/doc/reference/src/expressions/field-expr.md index 59451d2b6f..93777b3a7b 100644 --- a/src/doc/reference/src/expressions/field-expr.md +++ b/src/doc/reference/src/expressions/field-expr.md @@ -4,28 +4,46 @@ > _FieldExpression_ :\ >    [_Expression_] `.` [IDENTIFIER] -A _field expression_ consists of an expression followed by a single dot and an [identifier], when not immediately followed by a parenthesized expression-list (the latter is always a [method call expression]). -A field expression denotes a field of a [struct] or [union]. -To call a function stored in a struct, parentheses are needed around the field expression. +A *field expression* is a [place expression] that evaluates to the location of a field of a [struct] or [union]. +When the operand is [mutable], the field expression is also mutable. + +The syntax for a field expression is an expression, called the *container operand*, then a `.`, and finally an [identifier]. +Field expressions cannot be followed by a parenthetical comma-separated list of expressions, as that is instead parsed as a [method call expression]. +That is, they cannot be the function operand of a [call expression]. + +> **Note**: Wrap the field expression in a [parenthesized expression] to use it in a call expression. +> +> ```rust +> # struct HoldsCallable { callable: F } +> let holds_callable = HoldsCallable { callable: || () }; +> +> // Invalid: Parsed as calling the method "callable" +> // holds_callable.callable(); +> +> // Valid +> (holds_callable.callable)(); +> ``` + +Examples: ```rust,ignore mystruct.myfield; foo().x; (Struct {a: 10, b: 20}).a; -mystruct.method(); // Method expression (mystruct.function_field)() // Call expression containing a field expression ``` -A field access is a [place expression] referring to the location of that field. -When the subexpression is [mutable], the field expression is also mutable. +## Automatic dereferencing + +If the type of the container operand implements [`Deref`] or [`DerefMut`][`Deref`] depending on whether the operand is [mutable], it is *automatically dereferenced* as many times as necessary to make the field access possible. +This processes is also called *autoderef* for short. -Also, if the type of the expression to the left of the dot is a pointer, it is automatically dereferenced as many times as necessary to make the field access possible. -In cases of ambiguity, we prefer fewer autoderefs to more. +## Borrowing -Finally, the fields of a struct or a reference to a struct are treated as separate entities when borrowing. -If the struct does not implement [`Drop`](../special-types-and-traits.md#drop) and is stored in a local variable, this also applies to moving out of each of its fields. -This also does not apply if automatic dereferencing is done though user defined types other than [`Box`](../special-types-and-traits.html#boxt). +The fields of a struct or a reference to a struct are treated as separate entities when borrowing. +If the struct does not implement [`Drop`] and is stored in a local variable, this also applies to moving out of each of its fields. +This also does not apply if automatic dereferencing is done though user-defined types other than [`Box`]. ```rust struct A { f1: String, f2: String, f3: String } @@ -42,9 +60,14 @@ let d: String = x.f3; // Move out of x.f3 ``` [_Expression_]: ../expressions.md +[`Box`]: ../special-types-and-traits.md#boxt +[`Deref`]: ../special-types-and-traits.md#deref-and-derefmut +[`drop`]: ../special-types-and-traits.md#drop [IDENTIFIER]: ../identifiers.md +[call expression]: call-expr.md [method call expression]: method-call-expr.md +[mutable]: ../expressions.md#mutability +[parenthesized expression]: grouped-expr.md +[place expression]: ../expressions.md#place-expressions-and-value-expressions [struct]: ../items/structs.md [union]: ../items/unions.md -[place expression]: ../expressions.md#place-expressions-and-value-expressions -[mutable]: ../expressions.md#mutability diff --git a/src/doc/reference/src/expressions/grouped-expr.md b/src/doc/reference/src/expressions/grouped-expr.md index 096b36c823..d76e9a1e07 100644 --- a/src/doc/reference/src/expressions/grouped-expr.md +++ b/src/doc/reference/src/expressions/grouped-expr.md @@ -4,8 +4,14 @@ > _GroupedExpression_ :\ >    `(` [_InnerAttribute_]\* [_Expression_] `)` -An expression enclosed in parentheses evaluates to the result of the enclosed expression. -Parentheses can be used to explicitly specify evaluation order within an 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 `)`. + +Parenthesized expressions evaluate to the value of the enclosed operand. +Unlike other expressions, parenthesized expressions are both [place expressions and value expressions][place]. +When the enclosed operand is a place expression, it is a place expression and when the enclosed operand is a value expression, it is a value expression. + +Parentheses can be used to explicitly modify the precedence order of subexpressions within an expression. An example of a parenthesized expression: @@ -41,3 +47,4 @@ assert_eq!((a.f)(), "The field f"); [_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 diff --git a/src/doc/reference/src/expressions/if-expr.md b/src/doc/reference/src/expressions/if-expr.md index c552635cc6..87b088f784 100644 --- a/src/doc/reference/src/expressions/if-expr.md +++ b/src/doc/reference/src/expressions/if-expr.md @@ -41,7 +41,7 @@ assert_eq!(y, "Bigger"); > **Syntax**\ > _IfLetExpression_ :\ ->    `if` `let` [_MatchArmPatterns_] `=` [_Expression_]_except struct or lazy boolean operator expression_ +>    `if` `let` [_Pattern_] `=` [_Expression_]_except struct or lazy boolean operator expression_ > [_BlockExpression_]\ >    (`else` ( > [_BlockExpression_] @@ -147,7 +147,7 @@ if let PAT = ( EXPR || EXPR ) { .. } [_BlockExpression_]: block-expr.md [_Expression_]: ../expressions.md [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators -[_MatchArmPatterns_]: match-expr.md +[_Pattern_]: ../patterns.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 diff --git a/src/doc/reference/src/expressions/loop-expr.md b/src/doc/reference/src/expressions/loop-expr.md index bb2a061bd9..8c9ad28024 100644 --- a/src/doc/reference/src/expressions/loop-expr.md +++ b/src/doc/reference/src/expressions/loop-expr.md @@ -62,7 +62,7 @@ while i < 10 { > **Syntax**\ > [_PredicatePatternLoopExpression_] :\ ->    `while` `let` [_MatchArmPatterns_] `=` [_Expression_]_except struct or lazy boolean operator expression_ +>    `while` `let` [_Pattern_] `=` [_Expression_]_except struct or lazy boolean operator expression_ > [_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. @@ -263,7 +263,6 @@ In the case a `loop` has an associated `break`, it is not considered diverging, [LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels [_BlockExpression_]: block-expr.md [_Expression_]: ../expressions.md -[_MatchArmPatterns_]: match-expr.md [_Pattern_]: ../patterns.md [`match` expression]: match-expr.md [boolean]: ../types/boolean.md diff --git a/src/doc/reference/src/expressions/match-expr.md b/src/doc/reference/src/expressions/match-expr.md index c6181f7fbc..53455fa9ac 100644 --- a/src/doc/reference/src/expressions/match-expr.md +++ b/src/doc/reference/src/expressions/match-expr.md @@ -15,10 +15,7 @@ >    _MatchArm_ `=>` [_Expression_] `,`? > > _MatchArm_ :\ ->    [_OuterAttribute_]\* _MatchArmPatterns_ _MatchArmGuard_? -> -> _MatchArmPatterns_ :\ ->    `|`? [_Pattern_] ( `|` [_Pattern_] )\* +>    [_OuterAttribute_]\* [_Pattern_] _MatchArmGuard_? > > _MatchArmGuard_ :\ >    `if` [_Expression_] diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md index 73284bb782..75f59636df 100644 --- a/src/doc/reference/src/expressions/operator-expr.md +++ b/src/doc/reference/src/expressions/operator-expr.md @@ -306,7 +306,9 @@ fn average(values: &[f64]) -> f64 { ``` `as` can be used to explicitly perform [coercions](../type-coercions.md), as well as the following additional casts. -Here `*T` means either `*const T` or `*mut T`. +Any cast that does not fit either a coercion rule or an entry in the table is a compiler error. +Here `*T` means either `*const T` or `*mut T`. `m` stands for optional `mut` in +reference types and `mut` or `const` in pointer types. | Type of `e` | `U` | Cast performed by `e as U` | |-----------------------|-----------------------|----------------------------------| @@ -317,17 +319,21 @@ Here `*T` means either `*const T` or `*mut T`. | `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast | | `*T` where `T: Sized` | Integer type | Pointer to address cast | | Integer type | `*V` where `V: Sized` | Address to pointer cast | -| `&[T; n]` | `*const T` | Array to pointer cast | +| `&m₁ T` | `*m₂ T` \*\* | Reference to pointer cast | +| `&m₁ [T; n]` | `*m₂ T` \*\* | Array to pointer cast | | [Function item] | [Function pointer] | Function item to function pointer cast | | [Function item] | `*V` where `V: Sized` | Function item to pointer cast | | [Function item] | Integer | Function item to address cast | | [Function pointer] | `*V` where `V: Sized` | Function pointer to pointer cast | | [Function pointer] | Integer | Function pointer to address cast | -| Closure \*\* | Function pointer | Closure to function pointer cast | +| Closure \*\*\* | Function pointer | Closure to function pointer cast | \* or `T` and `V` are compatible unsized types, e.g., both slices, both the same trait object. -\*\* only for closures that do not capture (close over) any local variables +\*\* only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference to +`const` pointer is allowed. + +\*\*\* only for closures that do not capture (close over) any local variables ### Semantics diff --git a/src/doc/reference/src/expressions/tuple-expr.md b/src/doc/reference/src/expressions/tuple-expr.md index ef05761138..e9b1654c27 100644 --- a/src/doc/reference/src/expressions/tuple-expr.md +++ b/src/doc/reference/src/expressions/tuple-expr.md @@ -9,16 +9,18 @@ > _TupleElements_ :\ >    ( [_Expression_] `,` )+ [_Expression_]? -Tuple expressions evaluate into [tuple values][tuple type] with the operands initializing the elements of the tuple. +A *tuple expression* constructs [tuple values][tuple type]. -Tuple expressions are written by listing the [operands] in a parenthesized, comma-separated list. 1-ary tuple expressions require a comma after their operand to be disambiguated with a [parenthetical expression]. +The syntax for tuple expressions is a parenthesized, comma separated list of expressions, called the *tuple initializer operands*. +1-ary tuple expressions require a comma after their tuple initializer operand to be disambiguated with a [parenthetical expression]. -The number of operands is the arity of the constructed tuple. -Tuple expressions without operands produce the unit tuple. -For other tuple expressions, the first written operand initializes the 0th element and subsequent operands initializes the next highest element. -For example, in the tuple expression `('a', 'b', 'c')`, `'a'` initializes the value of the 0th element, `'b'` the 1st, and `'c'` the 2nd. +Tuple expressions are a [value expression] that evaluate into a newly constructed value of a tuple type. +The number of tuple initializer operands is the arity of the constructed tuple. +Tuple expressions without any tuple initializer operands produce the unit tuple. +For other tuple expressions, the first written tuple initializer operand initializes the field `0` and subsequent operands initializes the next highest field. +For example, in the tuple expression `('a', 'b', 'c')`, `'a'` initializes the value of the field `0`, `'b'` field `1`, and `'c'` field `2`. -Examples of tuple expressions: +Examples of tuple expressions and their types: | Expression | Type | | -------------------- | ------------ | @@ -37,19 +39,26 @@ Examples of tuple expressions: > _TupleIndexingExpression_ :\ >    [_Expression_] `.` [TUPLE_INDEX] -Tuple indexing expressions evaluate like [field access expressions], but access elements of [tuples][tuple type] or [tuple structs]. +A *tuple indexing expression* accesses fields of [tuples][tuple type] and [tuple structs][tuple struct]. -Tuple index expressions are written as an operand, `.`, and a tuple index. -The index must be written as a [decimal literal] with no leading zeros, underscores, or suffix. -The operand must have the type of a tuple or tuple struct. -If the tuple index is not an element of the tuple or tuple struct, it is a compiler error. +The syntax for a tuple index expression is an expression, called the *tuple operand*, then a `.`, then finally a tuple index. +The syntax for the *tuple index* is a [decimal literal] with no leading zeros, underscores, or suffix. +For example `0` and `2` are valid tuple indices but not `01`, `0_`, nor `0i32`. + +The type of the tuple operand must be a [tuple type] or a [tuple struct]. +The tuple index must be a name of a field of the type of the tuple operand. + +Evaluation of tuple index expressions has no side effects beyond evaluation of its tuple operand. +As a [place expression], it evaluates to the location of the field of the tuple operand with the same name as the tuple index. Examples of tuple indexing expressions: ```rust +// Indexing a tuple let pair = ("a string", 2); assert_eq!(pair.1, 2); +// Indexing a tuple struct # struct Point(f32, f32); let point = Point(1.0, 0.0); assert_eq!(point.0, 1.0); @@ -58,15 +67,21 @@ assert_eq!(point.1, 0.0); > **Note**: Unlike field access expressions, tuple index expressions can be the function operand of a [call expression] as it cannot be confused with a method call since method names cannot be numbers. +> **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 +[inner attributes]: ../attributes.md [operands]: ../expressions.md [parenthetical expression]: grouped-expr.md +[place expression]: ../expressions.md#place-expressions-and-value-expressions +[slice pattern]: ../patterns.md#slice-patterns [tuple type]: ../types/tuple.md -[tuple structs]: ../types/struct.md +[tuple struct]: ../types/struct.md [TUPLE_INDEX]: ../tokens.md#tuple-index +[value expression]: ../expressions.md#place-expressions-and-value-expressions diff --git a/src/doc/reference/src/identifiers.md b/src/doc/reference/src/identifiers.md index 88d3f20718..e57be8407a 100644 --- a/src/doc/reference/src/identifiers.md +++ b/src/doc/reference/src/identifiers.md @@ -2,8 +2,8 @@ > **Lexer:**\ > IDENTIFIER_OR_KEYWORD :\ ->       \[`a`-`z` `A`-`Z`] \[`a`-`z` `A`-`Z` `0`-`9` `_`]\*\ ->    | `_` \[`a`-`z` `A`-`Z` `0`-`9` `_`]+ +>       XID_start XID_continue\*\ +>    | `_` XID_continue+ > > RAW_IDENTIFIER : `r#` IDENTIFIER_OR_KEYWORD *Except `crate`, `self`, `super`, `Self`* > @@ -12,18 +12,22 @@ > IDENTIFIER :\ > NON_KEYWORD_IDENTIFIER | RAW_IDENTIFIER -An identifier is any nonempty ASCII string of the following form: +An identifier is any nonempty Unicode string of the following form: Either -* The first character is a letter. -* The remaining characters are alphanumeric or `_`. +* The first character has property [`XID_start`]. +* The remaining characters have property [`XID_continue`]. Or * The first character is `_`. * The identifier is more than one character. `_` alone is not an identifier. -* The remaining characters are alphanumeric or `_`. +* The remaining characters have property [`XID_continue`]. + +> **Note**: [`XID_start`] and [`XID_continue`] as character properties cover the +> character ranges used to form the more familiar C and Java language-family +> identifiers. A raw identifier is like a normal identifier, but prefixed by `r#`. (Note that the `r#` prefix is not included as part of the actual identifier.) @@ -32,3 +36,5 @@ keyword except the ones listed above for `RAW_IDENTIFIER`. [strict]: keywords.md#strict-keywords [reserved]: keywords.md#reserved-keywords +[`XID_start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i= +[`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i= diff --git a/src/doc/reference/src/introduction.md b/src/doc/reference/src/introduction.md index d08d0b2519..d794ab876c 100644 --- a/src/doc/reference/src/introduction.md +++ b/src/doc/reference/src/introduction.md @@ -62,7 +62,7 @@ There are two main ways to read this document. The first is to answer a specific question. If you know which chapter answers that question, you can jump to that chapter in the table of contents. -Otherwise, you can press `s` or the click the magnifying glass on the top bar to search for keywords related to your question. +Otherwise, you can press `s` or click the magnifying glass on the top bar to search for keywords related to your question. For example, say you wanted to know when a temporary value created in a let statement is dropped. If you didn't already know that the [lifetime of temporaries] is defined in the [expressions chapter], you could search "temporary let" and the first search result will take you to that section. diff --git a/src/doc/reference/src/items/functions.md b/src/doc/reference/src/items/functions.md index b6bd159046..9d6ebcde34 100644 --- a/src/doc/reference/src/items/functions.md +++ b/src/doc/reference/src/items/functions.md @@ -32,7 +32,7 @@ > ) > > _FunctionParamPattern_ :\ ->    [_Pattern_] `:` ( [_Type_] | `...` ) +>    [_PatternNoTopAlt_] `:` ( [_Type_] | `...` ) > > _FunctionReturnType_ :\ >    `->` [_Type_] @@ -378,7 +378,7 @@ fn foo_oof(#[some_inert_attribute] arg: u8) { [_BlockExpression_]: ../expressions/block-expr.md [_GenericParams_]: generics.md [_Lifetime_]: ../trait-bounds.md -[_Pattern_]: ../patterns.md +[_PatternNoTopAlt_]: ../patterns.md [_Type_]: ../types.md#type-expressions [_WhereClause_]: generics.md#where-clauses [_OuterAttribute_]: ../attributes.md diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md index e11e1e8de4..e5f766f5f0 100644 --- a/src/doc/reference/src/items/traits.md +++ b/src/doc/reference/src/items/traits.md @@ -43,7 +43,7 @@ trait Example { } ``` -Trait functions are are not allowed to be [`async`] or [`const`]. +Trait functions are not allowed to be [`async`] or [`const`]. ## Trait bounds @@ -67,23 +67,23 @@ trait Seq { Object safe traits can be the base trait of a [trait object]. A trait is *object safe* if it has the following qualities (defined in [RFC 255]): -* It must not require `Self: Sized` -* All associated functions must either have a `where Self: Sized` bound, or - * Not have any type parameters (although lifetime parameters are allowed), - and - * Be a [method] that does not use `Self` except in the type of the receiver. +* All [supertraits] must also be object safe. +* `Sized` must not be a [supertrait][supertraits]. In other words, it must not require `Self: Sized`. * It must not have any associated constants. -* All supertraits must also be object safe. - -When there isn't a `Self: Sized` bound on a method, the type of a method -receiver must be one of the following types: - -* `&Self` -* `&mut Self` -* [`Box`] -* [`Rc`] -* [`Arc`] -* [`Pin

`] where `P` is one of the types above +* All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable: + * Dispatchable functions require: + * Not have any type parameters (although lifetime parameters are allowed), + * Be a [method] that does not use `Self` except in the type of the receiver. + * Have a receiver with one of the following types: + * `&Self` (i.e. `&self`) + * `&mut Self` (i.e `&mut self`) + * [`Box`] + * [`Rc`] + * [`Arc`] + * [`Pin

#![crate_type = "lib"]
 
+use std::path::{Path, PathBuf};
+
 #[cfg(target_os = "linux")]
 fn main() {
     let foo = true && false || true;
@@ -17,11 +19,19 @@
     let _ = &foo;
     let _ = &&foo;
     let _ = *foo;
-    mac!(foo, &mut bar);
-    assert!(self.length < N && index <= self.length);
+    mac!(foo, &mut bar);
+    assert!(self.length < N && index <= self.length);
+    ::std::env::var("gateau").is_ok();
+    #[rustfmt::skip]
+    let s:std::path::PathBuf = std::path::PathBuf::new();
+    let mut s = String::new();
+
+    match &s {
+        ref mut x => {}
+    }
 }
 
-macro_rules! bar {
+macro_rules! bar {
     ($foo:tt) => {};
 }
 
diff --git a/src/librustdoc/html/highlight/fixtures/sample.rs b/src/librustdoc/html/highlight/fixtures/sample.rs index 956fdbe090..b027203655 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.rs +++ b/src/librustdoc/html/highlight/fixtures/sample.rs @@ -1,5 +1,7 @@ #![crate_type = "lib"] +use std::path::{Path, PathBuf}; + #[cfg(target_os = "linux")] fn main() { let foo = true && false || true; @@ -9,6 +11,14 @@ fn main() { let _ = *foo; mac!(foo, &mut bar); assert!(self.length < N && index <= self.length); + ::std::env::var("gateau").is_ok(); + #[rustfmt::skip] + let s:std::path::PathBuf = std::path::PathBuf::new(); + let mut s = String::new(); + + match &s { + ref mut x => {} + } } macro_rules! bar { diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index a717b30456..dc29add933 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -68,7 +68,7 @@ crate fn render( \ \ \ - %u6IgD@ZpcKWq~U<+zS zX56b?8#gq|mMm#=TxaTAbH<%kHS+hy#3WAU>6J(K`{nYzx|WxBe*uCHZ}qc5af0JbWQg7Ky~{ph0N>w(m*uSWq}I{s%?aSaoZ&R&=uT%tJGRa~Xsa#2t{B8=JfyVNMWHE=G~cU*~P=O!H0} zjKITOdGShxOvFT@LEUixTBj;3V7;wI8*R$>7-?kyGz!Bx{xX*F_mTQ{OfzmeLTD)h z**b!BNZiumFbRppfDW?0Qzhn2iqVn z@A>&1Obe^{#Rp6pG959|!c=!G8}nboCKVL}fKF@W(2l8k(TvsHn`!YvBBX;r6y@5R zt9*=mB@|&K-|?4IP6%zIW_8O^rA+cPx!6h0+wV=!L2AwTb1i9F1GyqI!>d%#1kNz$ z*6Lvd3qP3{nT-)yHLFMV>(tQ?)hs~AFfa38lPq1YON9DCtHus1OWdT>y)6$tk!;4g zG;X~aCN5Xe?!a01r>FxcoY<2VuWKFXYbzW76beFWY_2Xo5MDn=ysMBKS!^BBcCEud z*`&D}fpcMg43pYjEzk1gXCmE5i%U6^1P!Lb-)*12v;S=1YD4X(V5mctK1EAkym5=x z1iNq`{;rg~!W=X4B|K7cIK*q;vp%}_L1a8}P+*~%^2K=^A5hR}3HYLoD$&tlloMBa zf+3&ydXu>vUF3Fa!>$-X#1Z$gJb}MIo=I#K8CsJoVsTc_`~*8o_?P-LM^lRy=i*|@ z!=5^4Xr6(WGy_keO0ZU-1}Md~=;uDxd%TX;4b7f!TpRD*i+u-z zA5-fMh@Q58VF*Z@kZL`dGHJBN6?yHCE_624-5&s2i*CyY*>HrLfzS?ra9dd+owiI;s!-?gL^n*lDY4(AL*eom()L-2N*wUCP`njZ3I1~`8205` z``IGsRa*V&TmZmtJ@y)hS>9D(Q-jFe7{@~B@mbmhb$IuK!_SYMD0jKX! z5R!q+5=k%M4`)-i%%o%R**e=D>^KQc-q2+B(Wpjb1S$~O^;Nx8BOu#aGLNjy4dj)_#Qe0B3Zk{|quWe-mc(PbJ(nVTMu#P2R~>0SN-Yt+JrQMJ z_J8EdVh`vyIIOmVZo=)^Ga(OiIDYp?#$ST3S@R~~*d#lTN} zLA-r~QW>~Y${mry=`7$ixVp`4-ByuWJwx}RZqHIAQ(Jd|Iz|+=-x_|5AWChj-sgQY9gWyupSh?%2(I^EQ>O5r;e(OLPYOQ8kxK0rYV2K72kr!-u%? zeSJ1KNZFcix=%rE6Y`AN$=&>ruUZZS7WnFU!-~F}^7P;=dFzPX$Z;@t*BYgJR2!ec za^!(z*URkDXi%O9O3#uu^0tK}HZLUlpv4=|+9K`&llP}wQy8iOg$rc~NV{FR^!a91 z%AFg~t`q^C>aoRzU$CAN%`22x{t*VhgxQ1q;oo_5}aM&W*E<`08MggX^k6j;I&p%3I=|Bw$)*UG3`Pz{e&2f*K z22@I}vK$dZEFak~ghm(i?N=;pBt})|8mnvQ9XLEot2i9f3=TEfSRHR1whZ2>?y6_( z$qlk7v}!VB_I6X~&kNsC>asQPA6QX&Fr$0HcX;`Ex;{aGe;B-}5spdj%v_vrdLtf_ zJvdGyIycwwYQX$NBPY^k2&^Dt;)&Q&ZfV*5MyErc#Q|*Mv2f?xU80H!wMBX z3S=%Tr@{igwLZUUy1j2ezkhY#5Pu+ekDs@zP3QsB@emoP;Xoe}+gW4$2SU>sBk3LjfT_IZ^YrF(`Hz#%q7QUuh#F z9LqWCgpLop`$2YmGj04y&bwvS%p|!uuUpnOOY~-X089j2-3yZ@{0cKWa$s_#Ig?)) z9`2rPY2r9o*gi1ZXNP{&YWO8~e&Abj9zQ_G^5b>pkvHdtvY@Em0{m64`2*GZmuu9` zlIA0LMWNy%^NVm5!Ykx2#=4C{O4S9kSLoh}=B|$BJ-HqrH^HyB)kQN3;rIurH9Vkf zdJ?&b<@X}Hc2&KNzMC22INLY(b2uw?s3D^3$dsTRGa5{u6UxtP3h_}(#x?J39n1B2 z-hZu|uW6zv>NIb72#-J>vuh0BQXuPe&|-8gV4$(7lJspWS56^nGV&@< zp_G%5)C-7b)&IhM47oaklh%DPjM$m3^D;R_u|%EJOD)`|`y4Zhcg*F;WF3 zy~cZNifO5GR2rP6@u%K>j=awsbg|U3x+FouTmTDopSPqNxd0=lZi>= zmg+FS{z@Zlhbd%(hsoYwPu7syfZBrB&=8`^|1>C?;Lt^21;Rb`=wA(g=~HqQ2f~DN zOvVWG%(d3ykEY|e4=&<^OP;Uu3HQDIo-EJ|AMJ-MM@YKAzY+ZO4Zj&H72jSK#L zU-bPZvu$OVd-#&MBCy{7$bl~Q%p`EO1thx~x-!^=Uo-Mmv9|UBRWB*XPGG(P^iOid zy$;$0@)_&e#b2b2-2;6%4At5jJRaU+3iT#qbGd06ro1$PAri7BD@NB6~N)30N5uiTplS(2MzPW9b@7 zeLc4MPE}w>lenBc9)ETKeaP6pmZX-a?Q(@>xoQdC#l?k{Fm4Uv;3JZ$K-;5DCl@QN z&wL)+T1C~%Q2JmsWpFB6o&`5X`x=incDSd=Z4=kN2tZwT+%mSEavAg5ZUo=t<}3>f z@Ctme{m47T?P1wA=gT`poyXjn+Vy+_fK2Why+4NOlhz2 zi_)j)Nu!h7hvFUdBzC*ZWBI6*SIrg5dr=dIaBkL~k9FFSLs*xbHF)$Ntw^1$>M;xm1hFBUV$nxsZxaSR$0b z+-T^_9*5wV(DUIw2Qr0zeUmpGX~O(Xtbd6{WBPMaps#O~*VctbOT7L2{he}`OM?Y2 z$*C)C9*&=-4KIpX{59mLJD;!zS0B?R&z0c*fGE&6CHXfyI7&ujcM(lKY36f5;B(Mh z^7y*XAT?3(Wm=BicYNO1e!?>f6`}NLpCF_&Bu{pEo=4QgKHJ|Ur!-RMe+xvo?{!sJ(y4P#1EHT6LcR`;zRB=v?A*d%L*3kD1@&H1*iL ztJAZtD&{{eDT_LE=N3*rXa$EmBr7R8&wVhPMXV4fq*6Aioivgv3)~_Bw28#XqJDP9 zx)i!dk1Ugm054eOFEjnE6U=zcV_buvK?@)0Ur^gCBxh~k+{t+b7%zGRjWx2X>3eg^ zP>b6)0LRw8TpXDWI>78WuWsI)dd&$_>;^x)M$eTYGfCduj{G`=!etEeP4knkg}93Zqoi7m&eutba#KIf58HD0ZuB*;Xo~ z9W#ol2ehkeS#S!=1@&s?tXN#@o7R<4E>leNx<7wU!iqS7&pue=%~;mB`gqsTZ!ob1 zq!w+=Cxj&!^AKq`9DYCYIsk~zpDSvuwYHV>+H{cub69726>2FTPN7d0M)?-Vee*`& z0Poa2S)K=fYIb2MlN52W6BN60c9DMT?TU1#UbNMND0=eV!(_W!YaaxYt>7x$4jw75 z!KmMVkU6zQAH#BdfpAn??TuPUp^o{nmeJJ6JllcWL@0Xyrsx1GXg0qymp~N&HZURXuvyWq6)uXFGSxi1EP;oWn z2kw-PzPKhop<5tW9jtbGiHj1}8}{gGoCd70h~==#D=&KK@;`#*M^*7{17y{khY>qGMhw+b0l?tg$-b~w(0W}I~ zJz_qBNzV&x#ca2uHldrQ{^s|n0yEe6%7gA=^dtRnw%HS=yd|E?@_HD;#v=S~{kYKT z*YJIzg^``>>)Y>Z?E`%{#FhZpL}-C9)w(m=t{qGbdKuN4@Qyc)Z3bzkazqJ5(-ql) z!RNHFnpJcJ4nt@Yvy^=*@tWi##M9U*2d&-Z@Db+oRJmR$8<=A=8chCFSp%nb1Q?o< zaI9;a)FvL<(zK(RInJgeO%U7;Lj_d^AdnZ(3ny|B%f5zYvB{a%j z&zsYZU!);%#mkYuUP#rY7qF{2(U^C2!hPzx*_e~$**QBSakTS=80dbpxw@)a$ zO_6QK1IVkTg7@1{aE<r}upf^S zFrX53FfjkQe0bXcpMoBG6p)MzBi@zZ9euPgic~0XQpuD1^N@-mL`n4a2gOLo#2Di#y+yxfv$OC&X&ZB zPe74<1HbdBDkMK^qyrHF1}kvfxf8ifj=$n_*aGnBnU@)Z?N?g}QwT%@Z%^-bDBa^KEjGi&CVjo;xMd@+={$U=P@r2WgxF&GQN? z(gbKyD1bd#i+n0X6zvc~Pd&Y{Y6chX(b>6)64K_#RS+#~K^3AC)(r1(V<*OQ*D`2U zQ}y61+c?GQ6-59kd1koNrJfHN#aL0PGOkvT-$K7v+KSeX9WAa64K<#IU^+Xgo%TAuwJj=Cz!DUA)ELOW$}!E@0YyqA@O z?|tzp4@Sf@86?8>2z`Nm2jv$pLg}}fP5J0Bjbk!3-;r5I-($8xf0J5Qv*&IPy2CtD z9j2BCIhF|sCPHBI>-I=()6pT?yi76UO;}^wLUpdZ zGFp@C2F7jWB7@~6f9a7^tZ6E>oN+Pj*-Y=nZ)Hqc-8Z*-03V|j-?@>AB_8Tc3F{lD zW^?{Pk(qf|z!=w`KmRBt?2ZqsGc?D9KT2%1MoHNb;9z@(+)D4_O4r;<@8(L^dN3d+ zi~Cw@&DYrQtj*+Mdp(}<6z{c@JM@V+^ELG6T|8w4_2tQBm{uPBDlFx<9i=X3sOy&^ zsc_f_nbKl7&AxlogYq&4YsSZmo!9P$91uRIg1}-|LndJew&^X!h6^Zs&Qa}lIHGLh z7)cC+c)3x1joYx-p?!={5SEzC?c1TG7)gNP6q?xI2?&*d4!KxL_(-92RmkX}I)7E_ zXFO+Fks1&eCgmaO$GR&Gq;YG@C>f#vWTG)=CIj{%uKuZNVUmX)k|xHg4ic}E1KVkVe-AUZ0xOBWr1v`00gTMzJ>MY7l~c5cNejw z35%umtAqPg8eY$ofGz#`{JD!H#k%j^)7qkOTAg*xEc)@%LiTzhR%HAR(Jmh{&eNf8 z^!x{k15j&(4owQ^8n)wQ^3;Ihe8fM$oi#U&n&}=F`G%|<%N{j~HW_QCXA zDafVib|Z&&_l0u*&B?7=L`%1pZ3TQhW`8tUMT;izQp|2s`?!h?a#~U{-LmX%-EA~8 zt>4jkycpI`S4X~R#FYQM7(#>Q2Vgy!=m=xFYU*nu#lg6V9jPAkoDdeW?%8IGml)8zS>z+;K%iEpfr69yz>z5nI|Uvbh4eKaGy* zAm(T7-&%^~G}sjrX2b+zqme1AEEJudmNJXEb-AQ*>^G}+T0Wq`qH5vht3Z^&suUwC|&cPEBP}o=#yH`3! z=k|B1N`+DU+SR2#L^WH>>PbSb0hwLeF z5U-eQ+0@VyDKHykc~@AulMRr00;GU6Dax1>QZL?Ocvs*I(+acU19#uK)6B`z;p_8Z zJ03i2cmF2bj32=amirfuhcDB&(}U~X$H>RboX_E_T;PfkCBX}5Ly_`T?!R)n+fF`d z8EEtO=etW+9S{K0w|^6JTv`+J^-Ob}HUN^AaRhuR*w4U>oF`;}XUF^`HuM>ftBD=w zw1sHVWvbitdRIs+j+f=cX2TDD?qk>P^1<#lpi)>?F=+M+>TAOX67g!{`|^wJx>soA zW~b$v*w1TaX{AtSQo#F|Pj}EgAQjJ}JxU<_bsAYv3bKR#k$2Onf|~~RI*u1kkIAvK z`svIkaEBr6X2;5$Fk}9#xQFuNj}uf+{=1@_I@%h#4@S2!5)U5#4&(!)-|#+o9LI3} zLZa=iUHco0GxWeU$$Hmt$Cl7?M^k-;!@9Xuc_YGQEwiT|iUP}G1~H=+5tiu?<4F8e zPIZHN6?Z3D3RlSm~o7Bli(%Od0T3kL4>EJ=YHS@>COU4M_TwnQpVf#^b?7oMstq z0xAc13pZT5no33+nK9O)noM-o))I1wxF)rY&AREid3m!(%u+e} zDN}jJwpAUY+jSw{W@t$&XVFxxUINv$6YAu#%0Y5$6L7_GLY+*ikE!yFZHWlBPS4!&is3 zbKF&7OkB-?67T|HCJd=ba-zw38I`k$CdSQjW%w5OsbkvRxWg+cQPhiVVOFJ6JbelD zAl;B^PS7?)#s#-RgBSkT+<}8h++Bga%)W>})OJpih1%R6*W0aJU~oeY;P%nhXc2BP zTCXbt9?{3kUor)Hd!2ju$9cMjAc4~`UHAtkR&i+qOD8g}3Qf?`8fESn^brF`x;< z`aQ!mDeGNxTki{ZI8;{doa}$Sh|%K7GK{F_au#%J{ld?Q4{moizh^w{Yp1s2W7R=&)T=5Hz5v z4^v~&+;?rctki`0q9!qek7k3PUh`0{>aK-PKEub;0DGYn+nzVRm~=T@<}va3q5hum z`J9vKx7Gj3|B3R6LOa@VQZhhG#t}N{O~n4e73T}L)WZ7Xnk))`xb7O^)*wNGx9;>? zi6yjoPMuau2TVUA-s|_TBdMnW{>~`srI+`qmEp~>Xm_YwZW)OF)!118lna3hIf{#c*3=nZQ_blo=Bdc{N}U2%j>@G@AsH6<;-(vLOZks>mV>z zRRI5Rb#6aXOANj_QH#?|_rSM%P`K7$c$zt~+rP_O$e7l~x@2-Bzv&GCpM*Vf+(fR| zmU*2{&Tm&Xx0f!*XiKrLHd~0LrL9_3X|{7`3&*Ld(=L`y&pqE6K7{R2-8K6<4|w#~ zx!To}gV`35{juwZ13NySWnv;?`YZ0)H_enmv63UTGjKahOpa0PKINV7@@nW`xv_4W z4A?qQj&6Hvy)6e3(~Vxh1^xjYfqq7!W0xYk3PS2jq|-{Nl>@@|YHc?o3HOdhTl$-^ zJT~=t4<41E0TmA}Bk|}5<6ni4?dLMAl0AaQ4(lMJNLnzWK4A@Uq9xQZ1}0PbPCL$+ ze^X!mhfOqVt;&(nnqH_0dh`f?{m#V?F>6E4R$l%_zE8|vE|;ioaV6OfL`h6f`L{Br zR?pmUAb!3iP19^{1WR104|$U!8J)fpO~?{-o#xlKJdBAic$?v0LcTT%QJhrY?W?@x z)7^R4;ZeyNsa|?FMS#3*zJoYkxTQxC_sK{;F1Q_)LL4Bz3v62px^1cL(o8Gc)WR7W#tlN)%yEXk5+W%{P2`*xb`UduBa*ecN zu)~MzQU5uXGfTMzNUdGbj+fJl0K(3<#2l9#E542dWJan<@P*l$JpmY?Jr<&`cSzy) z(VuMYAC00y%Dv&G&X^^`1~HM+cl}(5m4yW+V)HQ@TUPHrbs8+JOM+r^dr_q8*Y0?N z>*f#)X${5s89&Y8m8gHM7veL8-MEiri*8=eYRaA1{7lvnVz_s|Gf{s_z0;ycx{Q=DJJ9LBx9ocU?Ac6KZKhDDCOmo&(IWuggjfAZWybx3k1c24UJA0MV# zgNb`$2!^7=j2gwj!ob`>Jo=lJo(}vwfj_3+QVLbl#4nkC%>J3}IylZ?*fh>y=`Wq3 z1X)6E_;(`dfP5BM-X(U(?LjrhRF7ea_&D0q+SD3NHct}Gz1%8;iK_8RX^pt8=-GN| zQL2}u@xjx6&c6szxMqY}pfHl<7R2Qy=U3~ng%38mIGOs^LV>8}7tEt(R3C8cr32=* zW7MR`3nx@o4<^ZLpKHwy9%6F>q<01NZ;92pi3fDHJn^6vv=1#!fd+zRLykTQnD0WX zgj%1!0JXxzkKYhy?-$08m^pIn9lxP=?5Fsc%xg^(KTlNDS?k$w?w3S}3`-O|EczEU z)k5T@ewzA7_-`JCMy>boOmZ4Xf`p{)T7ey<3Lh{8p@gmY7^6y z!X^Rkc_TuMNX};4H-?MgxwQ%&(8846B)O z$Y^w4Fy6)p`T$n|;&(Ign~R%mzN^tsa3xHFK9KbiL%~#+a5RaTfNOgUD$SqYgh?m% zD%VK(DK^DKLisgCKTZhe$P+AFK%=z`ePH+@s~WotwMO>)b9q$l&zbkOF4sgshW+Vr z@RKm$Nv@LuQ%FfW!K`I#T#qbIM zZpTz2MNPw!yc3$3;0&OcSkdWl-zpKryB^Y--dmSCY9jx#X4H9>bC4S+BGeG1nFN_G zs#mT>3JC)krj+CEio9Bca4CGlf=a`R7~rFKeX3pnwzA`3%kR9}Z=~zaPXg&rSFX#v zMs-#vR3j!%RI{b1iy~`<)u#1_%RThln~C3z5iR91X>q-?a@?gsuXXL8!l8^6%7ycLOH941E1aFIeO}gKvYLuIb#7 zkzMuIJ|JYKmJ_v4XJeBt1qr!GGcg+3F~l&AwMRZ+hXa+~HMzMm@L|@b&lc+if~t;Q zsxKCEnuog^xx?b%+6_mZme-p>Kf$?AnauCzrq(4^ecEGfk^zxCSqonJ4ixrgfdiP%h*RCB`5k`igk$I0VfS$F+| ztYwKYkSB`}Q&9Oegyr03TG8WILH1smIdn{{nAK$Cp|9T#&l@~YB8SxX4LWBiVhIEU zC=*h z#)&b9Ibl)xAIa>lYvRj`F(Jk^NczM=pe5uE!MH(=+ z!+D|p0s5wk| zjOy#p6G*MPNr8dNu7OtY%J4FSBj)m7ncD`F6EFU6O9+4g6Vmz6yw@&u+^Yd1ORUJX zrcnKR@G)1@sO0{`o(Vi2_XJkZ&Rz;_m3Za&r&6w?c=TT}PBE3dvIE)Sb@?Tj3n)!s zUy<(G+oOc)?v8DEK*F2EHB|L2-!+hUV*RsIxy7lM>?sr-<+9Vza=i1I%3L)J?@HFP zp;phW;PKy^$H49A8xQDzzi=DUPKH2DXav*XLO&9pL+^YLO5sjaOgs=cxd^^&uKuj? z$*FJ4s_S#vx+HOlZcsP8e}q~-ufezdlu}fY8&%_Xz~AXO8YHfaT{~7u!gdp==2L2t znRJ7GZrimGc}T>Lcc@qtp22&Hc%C82yaeKwPeV?!Cz0YvV{!s>HMxA?I|L1EnbEG& zy@Vbu4s0E3?{7Dol-q+1C>`qFnQdy>$0uAyvI^>1e$k=&sMS|FC7ke+9!K(&w5qDt zl{2`js0P`pagk0jCsxvF5FY%w(%eKH&0kWWg9IR%O5+mN9?{>_KrE)wIZ;(@+p_o! z_Ew}TbBa6|t0>i-WsrL7MiosrODwfPswQnglyv}0{ua~vwFppq=4TpGr#Ci$4A%xl z`8HA=XnjnmJ4Z`4c=3AUnj!0+ZtQKOZw@?y%C`P{Gn@9-@~Mw|hI8Y-KVv|7yK}=+ z18#hj`=)1ahga`%CW;rnCjm$kxkYykjv4*0KU()G1)>50@y~fduC*Mk;T`>K?=m(j ze2RNg;{icz37=b>a5pn`D~B&}dn3IBz=6R~D1?&H9MFly;z@*3u{_|B$rvWl4rJ-Z zkxA0b12j&_74jvbIS?|MO{cRZVtF2D>c$Z!s_Oqh(A#I2b8q~u5I9ca2WlN^&b6;0 z*gM9iY#pjL+OAx$?1S(>9K*P`{@FgarJ-*gR=m4k`69Z{3gJD4i~TurkmE4)pMikK zWHVe$cR(SNxeZP0+Hbb#&SbQj?gEcW#c`Q*AkTIlPx5|9F8gz!G2<|CFUx&EgYSNh zbL~EAGof0o*=RdZO1t5DvEF#y1xx3cCPvqO5m}}CBJ+!<91<8vAL!#+pwSdtV}h;a zLbKLH%cy0mOxq0tGaEe=!!mtO6vHBUZkR$oz5Ah<9X#?kwL+zIJ4{NYa+N}rEC3=V zlf`Pzvf5$z*r!99VU8q8hHi%Cao`=|)hw3H%*Qr1Fpl4%3SX^MFV1eUg86!l5Fme$-SdXq80!r-a@%}uW@mEE*-DvC zgq#lN^SLUy9^jzYu`0p=(ciyQlJ9E^GwVJoDy+=0SWP#BC6r31(q&rPe=AB;{!>lhEsJDQ4L^hkt>8ihkdc}6L!|A%OhJgH#_*)GDT5L*i*yl-Cd8vEYa@%U%H%TtV}ceQ=Rd`?j-^6X z)=G&1le8etNtLpFR+%6c^&}RN0vI#AdyQT}wEA>X8WT*yU}RAaB&-SsnPn$wz99-#kIe&KME6l*y!+rXo&!#L_c3bS`_R^|13;kn zE^*$X-k-O^nYVGX?wb@l@8hu0vz+aT3Avahj2NX@$CR21NwwfJl_DC{a^YqwWu%^$ zDg3XyYd(P+eR*IYaG;wdlZ_Uem6;Y!`KdV=o5XqvH^D^XV(}C*olt3whJT|e*>3%uOy7qlJP22f`LZ%TeXV@bWjzp#v zt>(BzCXq~}5vgQ3WilR5q!p{>d4>5+rC2Ro!Ss(xxl*x4w1(>ui^X!jTBM5YlFRvQ zzDBI>$1&lsn5+lO84t*$Gns6Lt2yt{XfzwFhbmdm*{s(aY({GTynnqN|3~k?e&z*4 zL-XGm*=$@ru780+{U*U66bykzCsa%}XEYp&NFz{4G^SK6kw_y{O10*6{5PhSFP~sY zDw#s5R-l+-$!fV&v68QlWJ;^qY_U?HlxF+K^YN5je>UELSTqKc-C#c1g4uK`qg8({ z(S%yHMx)hWA=QT4^>WQ^cQ(O@TsDW(ZErrsirsdr{dspT$&6kX;PJe-kY>l{`~9PQ z9LE1BU*H?i_@nm!JZ3e1AYd^6-&BQw!{vA}SiyWur~SWdg2(gjVyKG!n%Dd7?sBA# z?>}OK5&lO^i?#oXxY6SApU5##TO-B3^*F0U|FA5k_xZry%O3>CHYh&;$KEeq6wNlQ zeh|&xC!8eBHl(~D%|0OAILS7meLvaSD;P!7GN?E~)7mdtRoybId0ySxCz@s5GNig; z-8vxKdC@ZRKf^bU>!892j$6OP{}Hx_R93Wq@K9SfT}O1DH=lcj;&`40m1cOJ`=#o- zo`$u4NW=TY^1Pph)ONg|2jqG_o<{V(|Fib$;qnIkBH_PDHKWxX_DRK)Ni-srE#^%| zlS#E=wLR`oDU^%VBmTGlX}X-TnlBb>M5)@WyPSN`yN+xQ9u|J^u#FTKE;cAX&38!) zsfnpUT^d7_z~?t1C9?s~L4;1z$v=|GuVYGP30S~VTtfYKsME;T(^uD$t<{Oi|ANUz zHcO+>Ud38Cx}n>}PYgz)8b9IJ+VdYb+yRVas0cNwu8+5>T&G_s9|FG9&g_4-24;7Q z)t5J-l=U79Rdg%s6MPLx|K;b(P~M)T3bAv5TGp+I)1_MK#G=I-rdhuo8Uc z$swb&;+dJw{@5@V8SJ>_W&*a#!a9&HpLL*55r;qX@w0ik)xdF?pVw-31)e!0uX)9W zcxJ(+G80gaJyMFPFS|L4`OO&|bt_DCERIoSL6>hHmZ**+z=<6Nr$;exUZ$~&-Hl4r zrF;A06+j(@uRa}~X+7J%U6stNR2Dasmv}1L!%jT%vg3I<2{KqCN89dQlh82%%nVQM zv7_lv-S@z_-ha6;n2zm5MU5}KS?1uP;C<}&eR+I?M1AHV%j)mP)(sBtOPE7Nj5j}{ znNPjx60Lo{@A1j+Gg|MNZOIX+2u2Q*;l>EHaN~=nj|YH*Zq>nu9@pIo>ReL z8pmUTWxz?o!;Ba5B{LjG9OL99D>D}NG@kt#l(HJ7K@>6#ar>=gB1?w@-+1Ia7q-l@ z!)GIx296OU5eGL)cu;CAKJ9gWaEi=fC7t$I6R>B{5zU~(7IuoTKw{>^ob-= zc42@7D@loo1bvslo~d~BLV^W+V~p9Exp`uua?}l5W+Q!bgsy|LOwreis(E3AxXhRz zLBcfV=&&$JONkQf!2g`HJ%7sy#%nq{r@zBuAU-<@wydcL9fww_wTm@{hv}r)qlGSK zJXZo(Z}ek7nfn$NlRa*c(oY#QElVd~ZzMwZ1ai7z`5kK<03?kkIB zX68sDtIRStO7{MPozc%Pv!~)!>(SOZfsay2#r6s_LpNO{4VHYSDZe9mY0FZ{T*Hn2 zu7g3^7uzpGJEF%LffuD9>9I7?pN0{7TDqHxp8kprlaQn=9IqjgC#g$55z|4&b}-{2 zo{SH~1QIOs57t}?ZE!y+qP}nc9)GV zblJ9*Wp&v`mu>S^edoM$?|t{ji;)pA*IaYO-XljwjvbMa5d#Em6niNIN$nGzD%_(q z$>TyMXd&Z7Bn?obG$Lk-BQ!AS*w+I3w8~Ao`>A9*Gh0n`6(my+p_`)h)jzrtTM8$U zx-a4IYfedMlWekzU;0d5E1FPV;baubTRcs{XJ#Sp*_I|y`uMn#cnMm(kDa7v9^K2Q zSNPUI8?2aldFbbFQtjBi2VAio^kLh5n>3r`=F$&i1iLROjEAx)PjxBXA@bXQg}956 zT)?W_WH>rK5IL9=IKB`$nv3u*yMqt+H`7)=`ZfZ`S#tbp?I=$03877ScB^<`nqU^$ zPRsM0oL*DA^yU?>AzD7=^hS-)%loRmPy_V{XDTG_sLIb#V})xpw7dEY9$|iXqfY3F z)<3DH*cW+(pCF;3(IX8COJ3*8ToWnqkVK+K?0g*}+3!e!XITUCM1Cuo0D6YO^vRkq=H8~XUH{S4kHgmo;50;=ZOa6T6$U`~{cm@n75$fH@sII$6b~EN6W%^K<)Z zxm1lo`opN=(wkL{yH1>BPG%-%x6jl}P-ed-ezX|L*>2ueRisE&x+4a}UN}yF_utm+ zV8xs}SaH3a0k1Rgi)Ol{BB_SXS&pV2^5u z%fu8~2gxzE@9gxI-M+HpS9X>hLu)TIjncU>xE0?^%ZyiMB7-#P(NRw2*}D;9xH`%h zdFE+s9MA&r`AmxgfWHeUK8vx#mRCjm=T`i?1bdjTf<6FY^(JQZy)@2e9pPnU_&wJa z|1tQ$FH5t1t#nR7z5G_iwxt~V@-N9m!yJChF^S!H4qFVDZ#Mf)(dv2ft(5JQ`pM+! z%VfsOWJ}?zTgJ$zj{7DlIX;``p>h3Yd6Injg`Ze?l6%G;iB-0{=`8cBs%J{-V{4M; zdJMJ3lnL>Z==rC3`>^b`pb-t8Q(fHGr0EGOlS{JYh0Y&sY3Hopa?}e8HrHZWDCVYG zGKGWs#e*ocX7^bYg&D@DN%@x5EEB4-&a4@0tTD71C7NzdD_H8RH{K`H<;~g)uWCun z3j=nnE!tJ*YNrKix6KQ~ZV<-LVW{g^ifcYHa-;E?!F7o54f4pWR4KDTz41@Mt#xX)NE%Q4m*9cSixwxUjN6a z1}zD>p`So47#I};2dtJO7HnE=_?Tf|ko3CT-T&Pd#Q)t^fnXFo zFGO@2gK=*p95;Mst3%Xi6s9vug=icmwOgI$-LhlUM*eWLE)IMP2d&t+#^64q@gS|; zXY}~g@`jWA_Hw)Oj*~JkeB8{F zT&}Xo@~D&Y_Apu2__tsgn-6uI~9{=lWmea$(({A}g zbo0X;{F{ceeQi%(1k4|c+~;@u3t1mwL9GP91W-UgXcrs%o&E{NpvC{!IH)GKw6HS2 zd~uB>&URRpAX1L&QTEg~BHEM&ffUny(s%c0KePXnf3hu{_WmSdMF6;nigO`B&+cZd zfAbSb_9c#j>$vRAtB-Y8M*RIQ<_~vVWUTFv)LK@J`Ljr2Fl>f^s@m|iv*{pWj9&P& zUWj=_1h0h+R<-%dX!mp7l-}-FHgt^c#MgqF^}QQ_5d)o(L$nfIL)V1N;@D}~1Qgi> zdDxOlf5!4E@|>BtCElh=zjyTdMT8TjR(tfT!1^#0n*oq^imL%aEZ4tLmp;b7KC&86 zY-NlYl6S5dxO^dEV$2hK?w8Wd!}+O$%FTww3yM=XvdS?B4I%e44W6($i2de29>=7O{0{@8sc9pb2}R~Ojmt>PvX^xox0%_D=jF1dnn*FIXIi(rs=R2jdo9?owd zWI_5CN>(#%*lBDAA>O^P$Cg{R`DVB**tc4(&C3U~-zs#Mrg!J+*<;Nb0~u#~SqIUKh#C0A9(;J~vbCwagrYku&gc1iu#Y-51L*mO%HH zE6ecv9H7O)9hvy+*dc*tY!BFtl_NItAIeph0dyx*?Ne_(;is(O@iS8qCL3<$lRPJf zr_Pm8O+4W2dT}`du$^XtX3Xhl|FlPjh0fsN^qREzghkSwn(EWhckqQ9er=R`I{Imgy z--HC$szbC~QA%*CG#x(^6Wv)Ot0O$qYK4X6Kq?AoOCxH3J>l;HJe)4buhz`-uw1Eu zK00}dM(G+V@}q0|gv~o&cD>Jp?%F2(psRNmCF!R`MIC;Qs&`;>dFyxg|9n`ud?ru! zdaNh&S$iwT@x9kp!~7U+Xfp=pXh8~C(1?B+0;zpL3)uMB!;u79?6e*PS&CxT0GhOY zJ|{zu=eh4NRN~qH95B7utNFZ%*6zb9%`g*tp+R#^H&{8IE&D#YZ8)>b zgvu&+r=3UK_@|RuD&|eFY^8H$9^t=njyft7M$Gxti=HGq6ZJB2XQ?Z zdSENud<}DFr5YIYt7{Bo0f0f5gIk$d41kD7>g#|bE&;&W3_%>}Am84GV4JwM-rLW= zvuiWdie`4XhZ(b7`5_^*)zWJzZpy1q3{ghi+Vs@KzLsI1zz{HtUSESx;II7E`+>lK z;DJCaO-${b>}~CUz(mAkRDiIIJ)LZTu*{uIt%0y?3|;Jiuz(=GwBJ!6Us13?z@OUx zY2oX4719~dqclSlv1{+{L*GN%@n+kw^zZSkTbk{fSlUgB`PxC5f643VDE{~a4XC-K zwR9!6`og+a{2GCj4ON>hQ44M}a!vf2tdqBtUH5rh+gM0C5Awl{PTJJ1=FWZ>NJqK) zAloJcx2HMIS+HY}d`~(b^3scz&Ly^E(q+8}=E8I#--&TGFjhb?3sjf|RO~DTP5~o_ z-mYUk*{%@nz@Sz%b>nQIs@9-hjclu^wnLcPHr@G9*J>1`%g?wY3cMvro)TvdLG-IX zc3;U#+`H;jcV97tqa_tsT7X|8GKXe&Kg^%fZzxk@tP9 zS!=O&2mq4k%`gM9Ij?1Og`(GJ=|tpBq0yfY7>v19V>70u0cvcnFDCfGDG>~hi5Ev; zzV#Fjd4EEz!?9&+iWW9ta`5qB=v)9Ws6pZzbDhkm(&G}03RSk zpcNo4;1Q5`h#tsoV4nr=UUs+s5mCaIJTPGf7{|&%Ih=4}PV!~=MFq`#ydR5uks=$B z@vVP$hzqNmdC^C&;ujyZ@d1Y=&slHb__wc5qJF>m`*ODB?+;(3-_blSnEclD&uYS2 zX+9oAHnK`zJ6vo1DZ%*khJXZ?I-2f3JDnUqf9X&zja50d@KD5!HQdy9QeKXg+%&zF zmS-22lgC-7gt8LRTdR0m@YBx1R4piS36h`6WYtJFX{w)iZIpN13-Id1EhOE`@aoeq zRNRYo>0T~`-AnrF0o0~+Yfjd%91qow!g&5UzpME#R$a99$G~MfE-57$&B{O~**eLN z-_0^l0Cg=Tw<;fYJU$94n}(({lHqmwU-3cf89zj(^wz z#`hf`6xNQa3v}uGvn}LX4p;Ym=uGIF)!Uy>&#NBnUUPld`A#SORyLd;J+poQ?_~(^ z{vb-SWZe+8KBnNxyeQNLapdlb%knztNVm@)JHpWtzO~@wB~;*MWS>@Lk)hqHV7|vp zbq=OUWpX#U7&~)5C?wcr@tyR9;mydJ6*~oW{NWprMLFKWoFipEUB@COZDGC|V^?&01lbsEm21Z6 zFA6z_T_&!5q|+YoQ1l3~gM5H|%)u2U=1Mofy~v&3-OHRQz^1hRR}{930f_XXypJLJ zAFqIkGl8E8UCGKBk9dx`IrQz}_y$NwH5{jO|hocuMb9}23x z5~*|_QbOrnyq^*Ys#27>X|hcGD3kKRm{RJW4K2!3(~7ec(0vC^HMtaK-AkV~mFg7i zeK&UR8Xg+an?jz;$tbC+&J#JmHQw7ioTCGBhXd#5Mc&5-Ey`IG**W+>Rc&_VnqC$% z-p4?+GgP?6#w^v!uFYzrx9tk2O`__jVjC9+VQqe0IPkz){J%!{TzEFbtdFh)*2jE) zZuCu_yC|OuEon~r>3gAU2pod#$Q_6s3I?<+K{oLVPaEseE`dp=R`jWNJBtd}``LR=oG24?<(fz41xbY`) zMI+p+(SViB3I68hGu5%qmjK;-@md%jdS)8yVi`>952Riz$lun#B#Rz9u-U9_rlqN#=-g4@SvM$S8`&dzH@&fc ztI){H;3KL3F4)H#xHDJGY<1&oS%4>crLKFB>y=5ZoDW_l9Hqg=Gm(aTJ8q?UbHM!~ zOfA5LU!%JtUUl{Y%(@Y(a(}Its|&u;pBR9bOQOCA6zeak%5;?O_UPip>J4e_U1PhZ z^)=OhskgSc+HCt;W$tEn`%yC0@Gh65uioAckRmKoS*=77oxPB2c|t?h_0R;KwqITArt@mEqsRmELOMph-M zu-;FAKdsfB{q3M@5{dh|I=%0iC)%amW02erT0%i6+FB$(k&w|5;~xaG3tx^wmC z>5o%ay1UEu=W0&9+WEMjL)#PVDl?9X&(<0gE*>}LV`9=2!#+pqCFmZq z_KKITn_im;zN_x3_Gy>mTY6iDTasI>-4BrOjQ+Bpa36hAm~Z03@=6SIl=V$6fv*l}nvdX6zd)VRsmeGo64 z7tNb=k${c8nX8%EjmK?}F)LqA_7MJ%vLt(M;P?R6A(YcN({i$8QpdchVX18oWnjX? zX&oCODiQWE&1+~voqFAP=id^U*;Ms8Owo^M`Hg$AK=1HUIuT#XP*MXkC1J_OQoKDsS_o2lDK7I4 z5!|rwESYuA9e6D9bsjfJ$pJpuv#9|pqbWpffirob%Crb9m|x`K-f6515o+TFsB>jy zaX9Y&3CI^P!AN4&Pi6PkS`C?4_yt2PrHsF^y7Puy=b!Q{hybKUctyKnqAx{d_WX{X z1GYu$=_2X)lno;z`TCrRtm&hxe0aDQfW}ag{Cozm@({-5zde?h-rjK zED54#ngo4$SY>I0hgHpnW>o} z+kpYyfgvB70pZv3@Du~e6hlrm15!0Z)Rl*h2EVa8 zuJD@Z3F3J^N6)A}#{13lR^dC#e;!Gu)5Q7c*7)M>*9|IY1KA2}K4*F>J=$K>rWh8l8+8IX7uFkl%opzSi?A&Y!wEi8!F zJdmg@IaR7sYbt6YYpTZ8=Vu$+uG`v}+;fjO8rg~vE?LFjGs=vYGw?5Q44vzL#8SMav$0V2Oc$rEFKMU&ls z>j6x^L)sawenq9%e_9&$ViAC55us)g!)6iXW)TN}6fSoZO?MP&cO*CF9seLgeo-xvg3tg z-t7-UUexIr$@^kC%UoEk!URWA*dGSer!*HW<=KD{Dc!6Ik~-QQ#B*~~RPCusbu3P* z%}=%x@ya+@8cn5B;5TYevtPSJMgHgYd1>ztxXbR);&2VCQm2glKSt*74z)Ztjhjvs+fV+|^WDCixyi+jjb}LT&y06{MuBRTjriCtD@(=g zZNP?es*8*VSyc<*o5N6jim^{6iKnUZJ)LKQtCtpW9q=qq`gr8XO($aBr6`Z-wh@+= zQ9~?n%P%cd=hC~7{~pP9_HymdawUsT6UgtYtYpMyCs4hfG&tnQz`fDgxT7-_Z_|n^ zt0Jj!n}xPWXcrd;BzE!(vzxMwP>w_hx;2|z+^Imag0h0Jf{`k%oyeR6ox^Mt%%L5> zN+A)y{5cXw@-CNPPsmQbGiNwGB+6RB(4nzaYu8_m#}jLh)pOR$KoE*>cEqOG&7IFe zho-=!s3glJ(dG&8szQgh5J7fo4oD=(;&_kv?GrMmFJ6B^Vl7ckj=n_HH8dFDI%)Rm zQ?J`de!yIN%F{J|O5FZF9bi|=ANYZOWIwIuH85zUvf#3^T7Kn4)s}gf4HSKVQI!y- zJF%c1zKErTZGj_X47x_#X`jmovhoZRT2@YKR#j|NAwilL+%3F%bXmyn@<(Zi8)J%O zSi-2HtA|6??%l543Trrsk){=UlR|w?SH-5#uQ*C=*V7AmVQdbz9^&62Evu$re&7VQ zj7vP1*t?E;!b{ut`?!+Q@Q>z#?dhp?RI^>cb(Dq!+rceq7k3+Kyzqf#k2lX3o=?Z(<l+k4Z&^HU5h7<}y9g4zhtoc=d@VTtM z0ZWwK{9q);$;iUyB+ag zDH!^ZOmN<622(4!Bm}=COoyBcu_Rccc|BAd_2dVG=AVKez*g=@==viEo&vw%z%>92 z;6_8+zZPIl?c&n!&f+B(^!Ss87e^Y|C6>Uw?Ne++luy_twf0Hn4nKC#8`6IPSHoAV zmfj@*fRs_)TP(-3ykWL|PP^1rWvfP%>71sKPNO>AHa|$=+9r49-8TT!y?2IH%gp$*-tR>=>Ab)0aV#$fVlpe-zxKZj0;;?AABB{}g zHFlAoeKFAf^Yo8K6Ko^Xio^^fKL4Td3^)^Na=BoDF(ppR@?S6Z0dCI%^lIrr_us+? zc?d`aK>o=M zh+53SLz$l)c(R5L&u~-dU7@XE6;IuDhg~B~-wIj=dk5ii7l0#lxf6lIW0lD> z&qjveZ5^lM`KX{V;AwIjc`*|cwr#gC{ixnJUQ68~7Fqc{TTmi*iZyIlbBC8Feh#b9 zsHBC+gH37xVJ1N`-V=?vT-bu0y+Nyw@53G`??0sby8~%A9ZZ5ooTw2gdfGd8;jTL6 zv~sa|FcaLKo1)~;B^iNe)wmg53*giTj`_{^hV?n*jKce`pi?alQP^KYr&b(7aj7sJ zdiIeRr=)e7tXc5CNSah*CT*4Rzw4#c#;`Q0H)e^2Z|o^YxG+<+izrU_*(gULFzdD+ zWv(DDXgi%>H7@Miy4ToqOZFyrt+Vg|4V@vEE-%iYKK7a;AwG(VW47b6dw({0;<|>s zV;;2t9nZhrQ{0=~;q`g44|Pv;&vkcQuTV|9*|)3I^_BFMw{|jy@ym0{bFO1gJAxk}@!|Q9d{~|| zuCzCu>;}0faf7>pe1k!Qf;~GtT^wv2d>o7%tQ@o)+C7**$p9nc{pPU=!BwIzlH^`V zcuTUl$6qrQU9pR;ljCi=^3zsF^8ogdF&ZrgK~`L1)LV4IZcROD{of}(z;APeik92< zQa0gB&VL_<)5V97vYWsfesy1qi`d( zuU@bHWAGxgZXpfk^Xx^dxKGdeHGeoJM{qPHMXuMRq*%AU3Tkh;O0_JjS0`sJ-Bxo- z%bWdJ_Hj4rejw?%Y*W8jv$M1Jz#Z#w?wKj9qst}cwS{^0VVO0EcpPx^&ZA_e&e~0M zl*W2|5B@^rgrRkjUU?&GjM#b3B~(n=knQ|z)4a*c5aiXS_W_j02FV|wmdKXxo(t|tyOJq%@4_#}kMvATghBQD)AhFEX-zB+os^@9~2 zky>%2WZ#Qm^O^^WAwN*WldxKAM2>Vwap+_xhQG>rdklXYiYeMKinb|DoWO`QQAIsP zl;IhZ#cB2x5@7@>sZdNy8IlVk31W9Bf0Uyll{%2*gLtbJM&==@;`}aiP|4FGjvrU>%eX$q=0?@Zw6>$dpgsX zSNxIiu?XdzA({sV*&r?4b9{0biEFG^9?iNIHE%gI%ZI+BHtf=r9{#EeXMk`Krx;e8 zBCeoy!rfh5idg8c1W}~4XW1`@G8!N8M3PYpV#-7zx!)>Ie+rYBNrE#eHTP^r$qpsp zS0$_W@~ZZv`M6OefU|@=1Kx6Z1pTD4%_^zrovYRNWSx{PV;=f&f1o6}&0;3Zii#0R ziH&iHjCrJoVx-eGObeQg*~EHDZ|+cJv)`C0 z7L=L5Y?3`itpD>O=&xv7IQd?p4v~J!*dBEsu0R_lyP_Njl7J?;9L54=0jIF!Vb(A* z-9SjZur3AX_%%xW5BGnS5iSYQGjxCIlBq*P&<}SM`$${CobsvTNYqzM^AkIUc_U$} z+pGi8b)}bJ_BN~8 z+u}}xBdcppr7sR&k|0~ZI)Mx5Xz)70jRAYw3ZWg8XDPNE-aoN;@%99Z1F^Q5Jw`iN zbDUGMc=Gm$%741LX5<~Cdz5xC?`3veo}n3|lMU-MTn!sGi{p;YBlc}A>F-0n!A=+D z9ibfV8@l419sleIdN*9ykHK_+>RuZ8VsNU;7vd`xnz-6R7YUYTwW6DTv*R?zE|MeWkbhm|vO!vVP)Qz0QBV5%v)7gofZc_TrnGzqnrY7^eCO zmDtCJoPSI;Va-C*S+gE{JpYV5$8O0Bf~S7y&BJHvOi4XMrIHI4oZ%+exmS8{8&V>&?j#tUcz|4E#S-)znk^jm)S^h$xZ zMz{K7;^VO&(<340E+Ox)rMqxEQDxrh;p@=sX=IC1@_Q023VW|<{tEN!_UyUay&qnI ztmyYd&-Hp_`ZLs}73%j?C&#Q^Vu$T|=3&@g!L01}WG6?oU9x}zcMVL2+_DI0tTbkE zwp)*WAsR4xjna@==mrKZ(JG3~Mu#86r)Y+Vcf_=btcqx|v2_^p4H{9Tsf~%1^rl4$ zTT%cmvl zNu277wppc{SQbmPxrWU&$T-L9IlW`|uTT#(fwP;0s6~)FmM%;m_&VZn@oFKjJ9$kI z>ZXVvFoyZ;;+S85@d|!QdM7gTnaU?sXsH64t<++4Hp&|Sp$h~{b?p?U_my~38ot&6 zB;JeJqEc7(uw@UOym2WHL0uw#D|%$NY;e!4-f)&f+^i;><$~?34QAtPEe9@I8b6ps z?QE+O3_FSAWUS54<4tiZLF=oM;0|esZE2{7S6(aMdJYl~*Fc6sniD6fvV3iW5z7FHHNWn*X;V@Fku^cDzKQZf zpnQWR@yfnboEs&~W>2sx_vw65ndc4Z6W47X(}%AJBw z7c$-&bT>3*--284mETJ8!`})kcxqw1G2lIFr0 zf`R7m6oe8&;Px)q7|0oz8KB|kfU|);U0UiO$B@(SPHx@zaG4E(uU<2T`rBs@m|rUN zgD8I#sHHRnJL)m`AxC2eUk~|@#xAn^==}4#Me%nshm7voI(xX-c5hEV-Rd8=gT^7i zML5f=hLpSJ?iO&IiktduG@ly&*OMw?!ZURJiFbKjV!(qKt^VQH_4N4(k`eUU6!t_J zxOM3_v>({-uX&CqtVorNd4X~L9NI%UkkFh&59XT4HISo@`Pnn!3&ft_0*&L3Wl18f z#=<73u?I`UfsIXULL3b%7trGvEDGVwd6?-u$!Rmmc_^^Fy>aV{J@$(k+|{S0_r4Bt zVd(|EbpX>FSF)=7TI0_#-h{;Y_3Qm9bLM_VjfS`doBq1M(q$%>jLE0)LebOW@xJBP zu{~q3fQnDqsSuIUPnnfT(_PH^O}_jMc3DMT;?;I}yX$;_V#)pxCEY!BYQg*+K!p6* z*iSD7j#l(!eV>D~+bbg3dw>pQXXUb-@13LOv@ufEHzG^FC%Jn&J<6j&3{@wrTZuE2^hcYdZzVL zGFSS?L|1yGm;J9beEbajicLqJ2fllRdCwr~drG9}t$Ln*)>qK`6bI7<=z^$l!p$h+g7HLChjIi;_{8=%=L=7UpPAAr2q+2qsB za$ll8PQpt$-obkDdnkU*%M1Ve5I=o?Y2L4gdEci{b_vDq@k4bB^Ufb~RUuE5_vS_k zG|+c(+%`>sQsbbF=8aTwa3-=V^$Gr;!XP}EUTa)+$LH9C)sK?l@|R0A>0VoE*GKRA zD8k}U9i##@BSqFQQDxTJl<>O7flsbgq&thOHE1=}T{28AKf23lPY_(V(P-t}iRClm zOSJaNfIZ7av$6gI;lJTYLJ34{J({PLK(Un^X{Aok>ZEOXO8nHEBs7Gr6518Mhssq<1L?DF|o@~WOB zw11Lg*M$t(Ea>uog2`!nlNSF;He45mc+4X4Sh8g|g2-$ABBvcr>hqY@;jx6zZUmFp z3L~EwNjfQ-a=za4M47l~1 z)?Mm297zb~F#lvA9gBZX&POnZIDFM8ed%1^_FiAQ5JwW+w?B(R8OogN*O#9R{oC*J zZJ!K$`+u0f@MVsMG2{NnLNKr2mLbd>4f!vr3zRv`wv1pVC8YV^!Sv$YFKCH0i87Gx zSKX6gfWs9w6UaW zMj1$Psx7iyR{E*^cQB>c_?w0KUo2g7atPJ_jwCP-C8RvejwGkYtO}1MQ#MLp5>2y^ zb{>a95snHay6WGdq#zF^`0V5ua?^j3D;~2bJe1gyf5j5f2qYWg3*jVY&0xzwc~1l) zxUTZx*Z9`>BzJ_l8S`|#(3&q(H%6w-OiDqKPkMfF)#kvjX|ACs4*0q4@OF&rI2WIZ zd2z*Ot4d7a6`G^YHb5S)1mCF;^Lqb>(<>~&`X+2dydDU6u_s^}gc8lVRtR3NvfmHT zoTG3Ad>=B_#%-N|UKz*NCb$P9fYQxoWg?LwZ*~PX=V_dFM1o~*13U#X(-ewVEb)-Y znUW)5R}u(Yo`Vk%q#*eAmM}5-Y2=betUgMgjdunj&kp3%_$lQEMyx*?pXa>Z%_nk@ z$-PY2{d?cQ9gQT?59l+xiR4H|S^PKNTpf2L-EP?@wvfon_t^Z0-*6p`q|*=Z)BGvq zevQU4c)G%mryuZV zeA39hQ6l?0Ww@t5h9ieCjlYh+k_f|Ix+|mYXPmu4LytU0P-LYSPL?*D*uLNLt1MOV zCF<~2E|9YJSNy(iKfHel(^`%_KI~SQDtEu%C3aQmD*yPW6#W7IzJ`8+xIpWdPRBez ztk!kUAFf(s8m=3(qo^N#%k?*0^}e{JT2HtHP*keEr$%>-$X>%0H;_pnCX6Gyv4AhV zCIfcyOOLN~vTUwgo&Ru_%0a2CO7wvz&e`kIUM23NYjkQf!5*J}sspZ+@4oKELuXZH z0*Mymu#9>kaOS$Q$W#+Ytw!&i-?w^7d^aOF??Q2-%$lc|3r{%*N%&Kui_ZtW<38#| za-o1vS-0KZR}NRz{wFwTEViDX_W0!I1;LCHDrJ)`=G z^p3E34O$oB($1E0!RURHhuTI(``r!geY2jMyb4-EyEV$|TR%e!x9I$wBkls+erK}t zL%JRyBYUh^uGqX0n$!0E)Qft&Fdf<`+)MB;L966{y_AOL+L%Fq$RV5&}*t}%j_ly&|#f}V| zQwqIib~ZnPXXuVv98fi>ugse`rrURQNnd6zaDXU%&%3#DOf44S!(3>o-0>p8TZSiJ zgByXZuxvKXbW^o3(|DPu?#r~Cen2M*@fX?~UWs{Y`%}q$VC)kwM*%WDL>OlZTJJYu zbSPWdmUN7;nSMF>+=YQo=J_?{d?ki$PxMD$B?LOawPvpWHCd^f+SgjEUP7Q^gN4(u zjha>aSCiQAxn3Q>lG}pYWRk5r#}ng24ECD&HB-3wI80gYC`@&V-!awWUaw)me4NcJ zO8-)q7>~#wjmWt;n|McdbiN5U8Fr0ujnMH}%RDN^BiIlLdYbmFy0xkMjrK$7S9kI@ zz3G!Q^oLUDH!S*w^;rIt{rXZ@sZ4K0VE!vX-O0Q3)>o-8Z>F>#NWJ=t|LA`|NuxgV zE25ZT!zf4ek&Jw<1P-bgG0JMlprR><46+z9PH4#dc;>GPm%%2Qllz#mZIwZ!Qw|+V z-exjwm4T*Hj{Jrdj_FJ~#bBu`L1W3gOx6zRFgj+mbjZD?QV!`0tumN&4e+UDeWuO- zn7%e)21#9s9V2l_KmR`0~a&FjgP|VOQolu%LgSKKuZfXNSs|mXbOLAIjLwP~p(#CXbwD8l!wOm0_8^zdSuumNbV6s|4DXvTDwTz8(u`gm z7qCSuU;{6mkeWBcv`PwF{iT?}Gfx)1x|hdhIB$k(g)C-!qmaSyKQ1%yZ&)c{+gCaP z^FKl|geK?$wlT#oVFS!J^emlln*T5M3;st)BmNa5i)Y1*-=rDv-#7e2A>*f2!;hw8 z5nH!BwyaWFa;paH|F*&uGB*B0Kza6wB2t~h72vKaQM;Si!a9e_WxIW-M7E@ zI|w1lvgf-IT(qQtulm0(`d^~jv={7QqmgGz94(WtGLs{f@UUbibTa;Sj>D!v(uhSa zdWd`4V&u&d2QVN1JePLBdi!;5k%ug>p0dn=Jgb$m@K@>fpE8{vd-Sc0?3O(Cc%EUk z0Bfa;@U{eNYbEk>UGig!?8cwXn72to9&%AR`hGqhTqWjdo`8?l1Xwi*yfJ|$*Q!2X zM?wKkQ((bkT8-yO&MA;B;YTATcKKi^*9cTO88JmH@`3@E_UOMdF*lqMIf&wxWTojwJdqX;-&Mn`0HJ0n!$Tzyn%AMy(2Vo7Gl?zxjTX|b!2r-d-D z81uVTOw0Wi`a3oGQg2T+{sC(Keyy5K@kd~zL%h}~ns~c=ffGWvu7`=H>{qe-SlYjd zXqp(G8jIos zDS<1>Z;)A9awas^%T4AL%o2ZBfM>=7L)tu);-I-M0ChIQXYax2!yJQA9FR;yLjL`~ zvA8CM5nMo%@7ycBARn+#c0Bg0Et>`}MKogF9w=fX{B#eY6dQ!Wc==KvUJlFSR44h; zQP5o~&>0TARpKfoOrLzEy}iiXZhA&2RB~cPcP*tG_4upc5sXjmT)o1f<{rgfNB>20 zrXf~{yO#B*RtM4YUi4SY)0bkdI3GIl@hu#;!H-{fTv%<9)weW)N^YRixfr5|>&^O~ zkuOM}tbAN=n3mfY`cv0TwO(P{vv8@qwALN1_X6rpqVDb!2AdH}O+lxU{W7!SpJVkf zt_rgx9tke3-X?s`qbvm!TD!*R4r$XnHq(;QqLyf16OWp~6cm4_L)gs*Bk#iLI61~fJ zRqH8sVW>9CV2a}U7ke=-C?jp(qW?tTMZd2YR{XB(H5aKJ z@8KIbql>RUJ-qJW*JIVv>(tJID?g30>$|vVq~kaTS&|F4_dx#IDmmFR9B2E)W$LI` z@pBFmw&R@2tK297$e*e><4BWZW6G3(sy?+|n!tSxLqau;FjO4ti`6b=re(sz*Oo z4ZKQS0aQJJHBIAfFh4ArZIQg zPh!J)d*BoGkQZ8k_i}~q5X&~LqEdaz6ZOddX247JQBPWa-cyUdODT3M&D-;Cw%}b> z^uCr~128txhhLFA^l>hww|yNu=>s2a2mVic@EQR3?OzLcB)$5EAeT|QzR;cYvEMe? z{~lu9_qy}ne(Wm%*yhr&Z%ONQ<8?U;Rt;v&nA$GfF5HSyr)6i^(BCfjC;?U3Pa zt=~boqe%Bl_I0-3f$y&GyG-g#(GoucUwl>gKcoQ%N~2a-Mx7vxNm1AzwS6Ey49J)? z0uZ_*24rMMVxSuqxsY&oiT$c#4{DrbM}uIzX}OTdcZNZDGSgwuUL(s?#Of6|_&UJ| zURQ$nd`G>IOWVO;e?YXEHLRN$j3kuNI7mX?b> zWcA_pr7~asp}<{!_$C((J^tWW&n3>=y%Ul9?~x7oaXVVALxIyw3tdtz^}zp!tgjAh ztJ%J;0i`$;C|=y%iiP6E8{FO9DPCIK-GjSBa4il6g1Z$d?rtGpc<;SG`<`dcnmudp zwR6rt$;p{HduIRUxh7iZ0<_F?UC}cj{!^xZT!0xYKc@b!yQDkvBPpndPAxdLcn3iI z#}}|#-UUFS#w#Rt58vtnM9rmk@r<0gjULHd)pLk=F~w;|Mnc)3{&B@j3~w3tX;p}U zo!MFAA;Tj&z|>|#vuf3>mN3d9%vwG3Ij^{r?u9>5W^RWUkYk|TqZv>9S{{W!AOd_n zY!t%73b$QK|73F9P&bwJD**rd7GBZjZ=u4Nb*mKt^t)FR-k->DfBh`-N=gWqp7oYd z8nbtDb=04)E&HdBC9T*s812S+{JbK{_g&m+MUHeTq}G_daSCtVWc89k zy;I~D`yi<<(jjJSVw$Ybi3)vcJXg@co)50rS(UJk>tFM>h>c#)dMWDJN@2s7GIg8@ zeJm;aR6%bP^@=q1Ax^bKjtWDKCiCNUo>yQ0h%){4#clAsTFpiF9cl8xbSC%1)-)j% zl{!Vvbc}9`RIBOI)?>Nw^c@=)NiWPnrwI7ovd(lFm@aCx;^7R^{gyD?o7Qh}_coag z@g>TpxQcv9lQgvfS&-7sodQ)LB`Q<<$NT;~k_M0O9+E#fAI#sP-=lK$@oEjfU2l|} zzub?IY&-^io;s(xcvyI9BsdQ6@=18F6Uu-4J1#GOI%}_Zj5q}xA<->Krd&1h$FLLy zV$E8Bx_0^ChhQT9^PTz5zpPvG2HhXsDW^VO7$+OtrM*Z)41w$B>!evk)0>|765?<5@QPxLj@RcSkzWlu$9A3*vqC;94hJ2X6lQ4Iu zo=lJsjU=c0I~&5E7zf+f-LgaiID&M{6z{vmm;Fqm)`SuRI`?sXSleklf^%aZg`F}W zRW(M=VXug)C$L*Lu`)@GS=$sY7Tv2|Ky0kniCtBJepyD817Ja=0_Yc{>x_r3jTY{r8fHRrx%sZvS1$nt=69j1eYLgH8~EE$8}%Ei9#jtm$~ zQP${VD;~2c8dRhLZ7M=*=T{YFOw-W|YF6IPb>853GnhRDCJZ~PD8CwWPCfUilu8)7 z;Qs1lWNt)jdfLXV^2<3ZyY_|f7WaGD&Jhb95$~%PsL}nzW?y?oid9pO1YQ> zMP-b~D)V#5N^S2B5|HraQVzJ7q(x;+#p02q7E#Kxh>H7yG2dZlUILSuOdU@Ty)r>40KV2XV+qg`R||B#6+ z!z;2tLC5>XG(3A5Gof-GOQ4%mYA;H+hEZ@T;dma$tD94K&x}Dp&NR3rf-TXokmHw% zOra86VqD34xdIag1m(M5D(?!FI1+!9B*+yQFi&e@R51br}B+ zGJyxtr^pPc1f{_Ji2n+z9a3pXm7!H$Fk=wnGEFaZaZ0fLQ7iw|6Iq5#WRI4v{Y}Bo z>EfWh2BP{qdPEW0NmaQz)OEE=HZ5Qhp?qdgB z$0KMg-b=u4pNDfnHC4(oRGXiR623|HbLJ}010y5M1?dv7XF}c;^ztygD-i$0(G66k zqlN%CiILz#fooiuP!E%lyx)RWBgWAl;@d#5YWT=zriTgK3*a~h=8)uNP;L@)Lu$JD za!KhYq9WYN$D@Q6YeWUEEeGBmh13}by17h5#bO%Iu`Xf_Y;-WUI!cN{VPD@ZO;@sA zg9W{b2%pHWTeHIbs|@)^g8SGu8!j&%&UfY>vvjF1aID=U=Or-_4P4X(D7RycYJQlp z_@rd~8u%?V8GQfeWw-4Iy%fh4f|+*zlVn^k{bP<}pBq24QM7eAG3wZ;(^Y ztQm9?Pxrl*Jon^PA)}KT&l7OyHcx@Jw_R*=- z^na;B+Qr~W(EmwdlU_iQrRfg-YM; ztJ-(v9hM{Z!uoQT}RNt?;$8B%kMYMn>VTiA5R#~i5^BXmH!_PuO z0(eKJ@>O#E-S3f+x)H^95!sh%$<*rh?%)S(DMBCBD8bdU(?ZTv)M)9Bnkv_^<{c8) z;Ey@}_51i^Hrn(DT+p{DRc~qf4jYgq&p8dZ*_}>EmN|Es21~-&W-9vJ+G0Qd>b5*! zTe_c4qd#46kh1ObkaL*xw5DXF-(A3uzg9j%eAJ`^?%%><`yE$fWwH#ti$95N8D99P z^IT&cQso&imkkCL=?|bT1)ROd;w~@d6bqWVG46gEmM}Bd4Ku1t7@=GAE;5QwW$*TZ z*o;kTEDESlWw@0<7-gFegA%31-(*qnHzk!&;cZdY;N%ZFd6$KW#`hg>Hr@1)fOOFODhK-?WhP*Hutx~o+1 zx2C?-_z}zPk)%W)Z`Qg)#;Ppl z!cr9r|MiYBVEbW~|8W9Kvv%4zwD~rD(Ug(puudQ-;1_7F@%m6{;|Hag+01+U!QvlC z6OEHvkTWK8Tz#7T+SEt2Tvpj>?mq6-VPy}{%~s#cYMabska@#TKc#Y6YrShbvD@DY z7lASiEYm@Eanb#vLZ`>^4kO18b-TVw1$~^{H?8SM`E&dyNKwa5&V>4ib)*;)8FOg8xtFL}~khRO4>fRft{Z{nFFG#`KBB z;iVKWW9nu+Xa54p@8#tg$_3IE)YkMn$o9AX6m$S%{V|qdMDRXH!Rhu_oieM9$-%4A zstkwl%`wU0X{6M>lt^7*+(5g~z~+!fW6U1C*O(ObCDD=@eWpgY#nCul-&Fgx5EMf@ z?D&B)s+3bUx%v1>h4%G8SRr`Y6VOZTvFmq+(Lp(PZr+Z!Qq>e~ttXJm6K-X#UjNm?B{_q8n9XOI!2_=WtkX$!+gng+~(;IY>JcwcY+s zgYNx&AFQ#?Ox}1>c_!*H(zol`U1VYUEW@rq{@)ZGnHvlfNfa?zHU#wY*gv(RTRv+XCb6mFLe}&%9MSgm!6rEHY}w16$AZTkra)G0XywHOAA9ojo7V z&fEL%fRChA-l{%d$guUvW`he#qj&R^W(O|W&pghC&t{YRW{KBWvrg1i^=Fd{va5C( zH!gH9?kW?nY<;wAU3Gtu+xsA_-V45m%+$a2yl?hp0kHZaKxI0Ui1F07SH`5aez!H> zc}LNV-Uyj;mr1|2wfU_I5(L>uEDc{L{kpF4$+vh|e8L_dQ>%G>^cndU+0?>}Gi@Pk zc^oJ(85Q>{sv%F}ZV17x4fGLLU_v1QUP031c$;f{DQVrDU_RBY@cj{!fb1*Z+?T== zVY(LhGOtPOsE;=jESwmf$fWk1hsU?n?sqsK^==h!E}L=poMji#-14?8UCSH@XtS3p zy5%#z+cmylv7^zmLib4av3OiT$+8%rRg2@b5Tn=n8upS-!Y{#yONRYj!EUe;swBN+ z-h1fRFt-FFYLA~h<+%uDAHJ(z4lqa>$xhtw9OEX!O;ANSg3c|sOQ>8MatX!0Mv@ozW1b_vu8Gux zBUY4NfH7t_`@st(r)bE+Q0An-LO9CIsYZE6vme?pM zrX+H_N(Cljqgc}qmKyA|fCL8^dn(gds}G16~=@r0=XZv^OLq`zP$aKKHeJuw<`X=^Q0=Ai&g z%{}tem>9XYmIxX>MJ%$r2Zt^!p!hv1yrg)IFEJ^k*eJ-P%H%aMF&XI+cI4s~rCWH| z8HGVpm*kBx+1#d1D9Fu$n9U^=yxd!b-h7<{Xoq;?gMNZch(r&If|$q1*T44qd+rL)i$loCcQE6e={Cd=oX{l_isc|V zA-GpD&U6%#KX-MH!inl9KevP+PWCM)X^Ud)8QBdp*IYFK@oG_aoD5ma@FB+d{fFHO zEF-p?-8ypWdxA@2*YQWosqjgqi)K!IF#gVzo>g5ki-8p4;h=(>iH^HDOX1LT6DPj2 zxgC-Fw$b%prE62Uv632Yh-9t#qL5J>T7G(2WM-HX*43?L|GL3LJoq~8D zYBPK1)&XMOY!bx>>kBlCHbycNfldE`ovE}m<2kok-JI}+deGrwv)j*=k3>xp_+ZB! zu%j{0vG<}1ezm*t^|8*i-ABCwl@v*uV%?A$tgIp)JhTs6Xce zqS0(hYHA58ePhY*7uG^WYnQH+9?ki_fYdPK^@J@10x3iY+9zS&U>~b~vTVS?&P;<;@ z-}F8BjS58l@h14OS3qTc_@h2&7fya#=^}AYKhpL)yp)R%T*(YScC7lti*1tXi2{jJ552KX;kU%fhTwLGmKk8{?LA8~77%$4ah-(v&m-vv-V4k?yTWSyi8zgXiW z-#QRTV*7!9FZrPDPP=S7E=w0P=YhEan#AFis>GBK)c3JPpQMW!l6C4x&J z8Lj4<;4UfJ=xBr%i(zR6HM@ALw$e4(RO9rSlkvTHrNy{c97!_aMGJXS_v)b-VI!-~ zI!D$`oDDk!9>C#{y_l9-&hv$uF&(NksrYfvCjlmQcPuP?K5orKvGM_KrK#x-1rflM zcl4x5a^wq#CO?NQzyPZR8=OJL&m~2mG3OL6a=2y)bJa zH7$uTv4iGTuL2E0-2))HI$E*YASrcv_P4MS`e6Yf}I{Wnr73o8sSZo z!%c?qLtDdcHnR1SmM3JfE+rygRtB~EY@BIHhE$51BAp)VL8G>s4Q0F(JDzfudq?>EVDUWs3pxfbDg$mbhZ^QIhWhE7r}pZ%RKj* zp`|6c7xHEE%kMAfJ&vbh6C2<~=vV+>*4^ZroxDV*i_lg6krzMP+xfDhobs!9@h1() z>_0>YHCGN8AuD#Sez^VQY0~uxWBBx zdci7I7B#P-hzb6Vy+A4(dLknK$dcgaZ>c_+6wz3|K_)mFfi(vx1goDNAh65}=$kXL z+(M|bN{yfE75`K4!R&^#+(xB}Y>`VStL4xaHK$x^Rs?!!)&0qYU-ic9lRNj-Wj!1l zE!Ab+9Q4YyTl#34F5oW6&@RPfy>ldIpifE>?m+&8+3!yDLFkbIl(M7$nB-850Ykw3e_1 zSSgG*7TX*D$~SAZY7Yu%*PnV&zI?hYS*@anO5gC)3wsv$s!PlG(L9+yD*g>8nvU@L zn^1W9knqG5DJ;LK2)uE2f!f`Km7+=rvuf3yE8_ZOB~=wLs3zjw3ylJ#!HUSEnOa%- zvpc4r5mk!3@Kw};Of@X|+ZBuEiuiq^6xOH{zU{ZNrq`Bu->{SjuINs!#2-VII*14T zWm??jP3ex)HjZ0w6saw?kki~F_ThyV2X=oW-`6}|`1ZH?%Gf@2ntP266j9!Z%Y#Vi!XESSeGSem#Yrh?#q z@naS=P2Aq6l8Bi}#V)X$xDls%+_4Kr{O0!<;8_=5anfUjrnb~`OynkPaKma`&pg}Nb>CRC zh^MyHZ*`zy`wNY2`TKXG@nN*4ezYe48Lj6tcQdY!Hm=8TB!5-j5ICdvSBtA=kw@*} zg_?B}!Ast}&>5cUMH;oGpEEqo#I`I_IAtUQR!B9A^(Zi$J;U1j>795k8tu(h6*kSt zp?>xST{$)5T7-W?lVYfHmUgLOEn$4*GvGe+{{Vodj9s(KgqueDmx=qc^w_x8@!9)h z$g0x#Rs2kf&AWJJ2iEwM@_rNRWytRmMF28fv+#(`R4# zDuZ`@H^m$cJZDDsFsf?xohldpt+Hy_Qsdj!>V+tkc# zH9EBhH7Bn1Yfyesy>lFz-Q$e5duK+YyRQ^*3ld>%4|;zIp(CWHJkYhQl)Sk)hLX|i z(oj1IrzX)3e)JnVE^;abT!`=$XP1s8v0@3F9!M|nBw-&}ZnuDJ;5TT>;F-)Vf@|Fd z*mA8TKr{X)%MQZP)#kMit5WLnK_m8}7rp0-Yt3BTXe&?E97&r1(QbXupi8oO+sj@L zfWI=^Pcp&8b_YnD}n5@6zyk;&+R382B#eV%L=bUP-@zT@CWHdY_+bkLQ5An2;*-K6h= zc(x7ID*BV^;`sHgx)+;XBr}V7rV$&ggi{xBy6=%zxU~|$S@C+ez=mnX-te8oLC7aP z3_fSFH2P0dOOO<)F%AzCPSOp)eQ1W~_}iekeDb-}_E`=;jFYu+!WU2Te3Fm_7QaK{ z&DR<%6V&~Xu8R-Mw739}G$*y>wudZiE&|&l8qWSBFz06Tb=eGyP4XgomV*6yTN@Vo?U|1;r>$U;}i zWgHBv2a;l!GvVXXT)hGy&(?e$_Zf(@AJzk5SbPLsM%P5H*^B(}ecIq`f@+EGy;w{3 zzV7Y<%Fd^?{JH#iw^-8c*DaE$l$Vn>k^zmFi*GNU#9CMIStjc|jq~BpktwLMr4}LgwDppn#gxLUcEnoRb6?>j8&W<`rOw=8274!zXQ!EyT?{7(BI5Fk^J{$*ca| z>J=nX>+YCm$F0K6z0uh(w-hv6_rP6YdPAhubL?JcwL)eg{unW3`i@Ia$JU4tg|w7? zaqsx6dy_yn$zGJ(K$G#x+3_3qT!EqX-?k1!D>UwDWw_#|{E60_mxJ4~cvtZLEq>TU zUWDwt@@t(9rdT#yTh7bk6aC+&mWDa;tR~9y$l4IZ z{yZZ1>DvE~iT14jFA?E?`{21hl!Fof9a-={t_JZSq0cmm zzHcX)6iqxVJ9`TTD(FS(r-b{SYqj+d?@!ouOC3sZ8obUlBCQv>$*uGz(ldUkXUqa$ z6LCfY2DK8KPJN4URY3- z5-5?}4jQk6U0>&!ONtm2i5gI1&YQipVL7bF+9&jHj0$X&{8PafGy68bp6{zH7gA*! zifrUBrS$A#EV_NJ!M$&TmXsrP$UKBy*1SDp&g40KY~yc9+xWg3*CF38ph9ha_?n3d zQ#y>jEqCTh;C!>z_O6z|--bg}y4EmF-eKe|@l=`gyMd7)t1fP2$oD@R+VSv32-pS+`+##WZ6XvSJEe)!pAhKW1@vc3;SK zPxfpEwGQhp>#8}pH}~7RrJIHdEP$BYTa=gSYezu)3W*0z2g?xM9l~?HMiG_9_?wp3 zl`WvQIg+h*yTk|!{|~Xd!nhW=b_@Mg?B^+m^mp$S#befjXuZQ0zT09r)J(;&&nF8N zbZ+UNF|4>vK)Q#bVp^w_E0(ro8vRVQk9_y}byrIpT9Kp^i2*s-}+QJ`K3NK&zSHTMyV;Q+D~#$*ne!EgLhuFRR= zhtNGkcREa3B_6L*HT2g+PI4yWs>XhjP@LYlT~m!0L*4^J_dElGj__TGNCRgJjxf0> zmv8Qko|I`l;;uoy!%df9yvc)?`4IdZMJa$F>B-JrY_nKpck2pxdJvp_Z*#vGK9q=` zqoblNC*j75L0>KWAnpZ)P_@rA4t5K$Vr_^G2v(j;x(gV{kHM+|irtw-{3rDdZ!WTV zPNi2tMv5&$n5`K7$4Lu$8}sTc+mJiom^Sy7$tPI2g%cEq{G^j`N%lKHP^T%p&q@-~#T6GxkKCxljsWfc3OOI;mc-4$or`hIUSgryJU?{S?slOcb zmsP`=Wm=q@ImW-7sXTJ6Ji1t1&Bf+X6Y2Vk zwOq?XiI9FU$waUB4(LX!KCC6uG(5T}?jKkJ0-?~6fsp`P=-axR?r7`Y1?35!{)WY! z=Eep`mO7^ZXw8n#G;a?4g^mU^*oFS%)8Ts~$m5e>mN@$PYxvF*tauxM*{rmTmFr3O ztX(#Yn^So+(9vhsb%EZUz<1+oPk(%VItH`4Xy1rZ6x#WTsVa0D!2H)>YYl!@Cpl?b zYv%&HRexf3Gyt(CP?Yw<27J%I{>9%7$4-fVmHB1T{TS$SznXdBVQRZrmPG?E`aJC9 z5+xoHKux8of?=1SpGbV?dPkzks6Wx5xjNB+K+;#yo77+_xCdBJxU`^+&CwPAd7a{F z20G*>8lhP*Z%EN~YHuF(*0kf)=Z+p!A2HtkE@-qU-+Jhd)bjf8cY%2lCZrWS_d?>y z%@igAE-~l&KugWKx1Pz(ySm%5l?|_krqtdbj7i9Ih;1y^jwf){igH=8TAM_h(3bLQ7104t*d)k- zrM)sMgw`nd%*qyMJj_}bSb*T3-6lKm)M0`VSoSEc$nDM+dU%quHUWdRZezG&_?bMZ z+?<+kJGX3KSk)8PFV491M`LayEpj z=?z~p1(cb!%dzg*+(t#Dx$qApf!L#cwG-b>FQ}5$J1R$|q`AW4ELdc6feGTyKaZ7Ve>9UzcRO?=GR}>V7&1N&S5X9+*b|f*ZS(J%ta|O-L zD%D9e<}zzh8rR878P*{NPE^oEu!u#M;RQ~-EOtT@Z*|35)cHA1pbJTi?MYvTzuJ-(zGwlk$^%YIIs=JTek@wNw91nxj!eqt(F$7J#fH;?jEMCUbXIw| z#gVgcHdJkXay%yH`u*s{KDod%9iE9)U6dMj$x4stfRTa$nlH8tAooW zw0`34nbAS4=oC2L)4mRydedk5eFOF925R7jiKrvZXUCw=@Z~*r6fx;GgYtM=G&p9Q zZ?vXRD~7($a*0?IW^?ysbBpD0r;eu~kEfBpjGSbvGh?ZvK`lysSw!%!7 zUZe>p|AlY^ttb_-Nb_wG0m6UU{|WdHuZdEW`mTroqlf_Y87%{*%KfL9zE9~O6lo$C zl>|>scUkVQbGbUCd47^7$uJ|$C`4CK#waTJIW^s5x&Mdj${|hq**Qw}j~_lE^uPT$ z|A;*t()d5g3uTy5WE7GrC?h>*mizIXoTmHVStcCP*d5Yp9MT;BG1zo^{XISu2c<(O z;XB=k*m$zl>`8iG%7ItQlU={nnpSy1Jho&ElUhN0kv+)+g+9#Ijlt<*ZY3R9m)6-4!n&In({%)%|m)Ud= zkM$0-_79IKvBLN?gZ;ALt1kon^n?BMtDd0Jx~uk?Q^pqDM=e(=d?nTjsTcR|0ukGr zX)NmP)!KjXWJ|O+)MT59oRJ1;uAa2a@lHCsNH)-8HIGr{@*&kvb*Fv5$69y48CHPA^#)nQS)bCc7XaXBXI|@$pX6~@6K=ot$ zt;vH?pCGJTID(V_x_TR7W3suMd+ijapq-4iJ^U^HCoY1B*_2SRUyXt_0 zeGe0wr5=9sWYu66OswMkf_x%v1Na*yqG`o{brz)!sFiea~gBbZH za@Jz1__d-1gxc#)yE*J~Um#XvXYTI&VOW#D&q?ZLQ84so-kog?(Fo0d%r%?luVO|z z&LYb<=ZqGJrSMLPE4F_k1Pi4DmiQQ_5D#!z2oHEG5yteO0d(sUg&5u~M<_ z(l2Fdy~Zs|u7vM=Vdlj7qpWYsZ0|YvgsfFch3`%R&=r4>pQ6nse^NR1NZMTj-+PKI zIX+$SZ`lg-&Iym_hCEhqAW>+INkr& zM-Ph2-7eW*s^u*{jgT3K27j^KLAlE(!4h7e9K@!+*c*yg7xMc#- zlJ0<$pf7UguB$x(nT_6rhZ*nD7-FrqjbIVX_FvaaaX_VGIji$_+E**DJ*)Tw*1l;p zE=w`5vd$wF50tyBf?&O?bbm3ws~@uF_+QtHR|sAat<^2f3+pp&BcDWmQOc-giIXX-7J#2&>Q|NOSIL{5zmQAaJpSF2KoZc)XkRt_#u@wTLc^ zG%0N5RY~SV=jkj&)(7!{F+n#IO98kOP`eR2;_=cQbx}f5AFAvZ1QB*+Rf<=k253Ot z4dt$ztmB~*k=g>z5JbFPrPu^%#EA~Mk~piOxV1!9S@Dii$6DaIv4=KcsQ(dL>nQ1h z<#j5N39sVN+}_1mg;P79#p0Hv^9adDzh6`PBAIG9z(4G;ffd~sjj^DY#4xvdBagls zgruJA@2SQ~@$n?rlJuOMXv(REyD4{e#qb)w%cOanrrV`iPkA$k#gS6Y8{7g>B4vS% zYk)oI>eS6wDI9yQGf5PC)IX8rZS370wh`?9?1j?@c6c~d;M0~DdiY9J54n{v>bsWx zWnPz119u*`~>lq5}HO+m{XX*F#AQprl36%zS8O;d}1{(XVoeVq(cse;N?&mYf_( z;gjX-4K#KKJ+|`8ZV}jZ4%)wgOur}ciJ=LbpZX^^V#^&*#Nsm;TGPr^yz(QGUI_ za+&Anl9}VuCp)i~cGjB>j>|j|OUGTd?i&q0O-JaV>iwz70b zcnJ+i1uLPG*Ew|pUl)()Y)PM=nQMPt^mukK=hUsx9nmB-5ETeTPC~Nlz;s81G6La~ zl{s|?2@N5WcwZMOWR}7w?IbO4a_XRTMg-nuu zw#3M*bEZ4uk`V}=WXY>DO>kqCX$_dPldxo@tN1yo_Eih1pdz~tU8WVS!1e3mJDG#* zI^2X=5xDz^LPlG}5+4YU&=t2NNoe>n$xmmC@EnHl9MPBqmpw=Pm&^_8znpNnS%Mp4 z0Z77f4!(;r{EEDe`t*uw=1dP=F}*5`s>J54alJ^o^~&ZC-d)2t$x<)z3x-#-u0O@B zcSzLwmZEk0w*C}&ctz!U#(sG9p8MR`beyL&2t6E)G{@$+*Y@Y&Du{j+t?Oq0Bp>#~S}~?^uF!eJX)kiaX}@&@HH6w`-q8&9 zLFV|iCphu@gPj1v<`EnGS!ZAiSjE9fmXC$`!hFS7@&OUBcn`+vdO5@d%$F6`Pgv)=bLU*(5nlCyM{_?i<%qb;vwv6G_ zQbbQ>rEM;JZSpAvH?!8hCypgOA)c<3_%@@`Y3^bzu`qQv?;Q2{Qf4I& zc#h@HCBb>pL_}^vLTer-AJA6zWXch}mSgH8RrWXPy7r?68j6iHPURrCvEMzYo|^?I z=}zSB$`iL8P_QgMs-Hl2OfyP~8(+MLwm)umrbO`&u(br#4tr zjwwkP`wNru*H5Auinv%2G6a zML(fO^+d*eNw?C@#5Q5YKKxiqkK=Mhy4?&z`8(^GXsH(rE_BU2^B%+ zsXEcUM8Ot{JWu{kIz-*pp)+KC=X!5-jkA0yb-z@wdfuA@8<#G8V@6=^#^Tf8>LS3D z*-_a#$Wn4e=IrEfHEn$o>w8ZCP}fk^$aPVZif|mKsp-oYGAQ4 zXBO((!srJ!8GpM;Qmd-G^rtdk%8rk3KZ<48T3_dYbv!D{W=uN=P{nU7S*M_O(wx!$ zEmrBd9@{DQe&s*!7x~RC@$dNE$=*a8aUPF#pY);4x;5V0-xswb>6jRc8FCC4(Rw_UlLD{8ia4HS(rXCpm==wL~FlYy=Hs* z?h$r72B-p$ws0Fj8!kqvzm(Vg{lYhpf!*o%R>>axWILVK2ozhU)Lbc~XQwZ<4{O3l+vq6a!=LC*K#lO#zuK)N#&V3m*=!L`>Wkj zf#RShCexBKStKjRb6{jx>AUKI&{Xv^#rmytP@~XZv`V{177DdjL#nGrpv&Ov#q)AGmnQ-NDcqTr1N8VeA`&?=X zl^#SKT<#o19=M+He&F4mwd1mzW?nN{&W~QTSuT%WHCoP%UM-ztf^ZKzjdJLKBT~*e zqsNjbJjek0{X0Il-UL~^XLlR`MU3FvQ+R*Uvon1A2=HF*-htjent21hk14KSh2)_l89L|saUQOk|=iTEzBYOedI)Z8%fZ(1SvF*4T#;fg&&egS5v#e zekU!r8a$ND?mbQ7bCWf)k5N;glLuju|^FZW0)xLxYEra|Zq7Eqo35L%`fFZiAM4Y&b3S zqeUvT6nEO^`~2e1MvOm4vYB^6=$l7*-yYtq0-_q-*N@oS+L7!}`j_y};HAjzN=Hr{ zGctIcBQi2gw=Ufz707zGyaqkMM5+2zJEQ2{Piz3;urb9y7n`@<_yDq=9k0_nJ8xgC zEI8HEdxHrOmV>0*(m`1g0FjgCU+3pyY6m$Q@FVR8Y%D~qf|A*vU4ldJx;vM&^_WI(ebt0FY^z0V_?{k~ih-31$tNF@d z(J97Gy_}m;$cs42QjntmMNcvUJ^G) zZF#JDA9-1rm|CJ#tZE;5R+!l8```$A^kyZ6II=!+qA;;SoM1UxbPsvr+LTY1BE5S) zyEvSD)JcPDivlRSJW;OEeuS~=HMp(7l+=>^d=}@FE@=@%I!@YH5FNZMS&#Ad4a-G) z-_*37Po?$^w@aKc*_t4Je0PVvpE+1_SjJet5CkquU6`<9wwzsr*>6AKAAPc~e7{>S z)g<-M+^+7|mo={Ml6c?xM8z<-)>=QntxoUAY$-dFHEE}9HVyyT@e9LZU6gT_ns6^Y z#NfIi>_mN%Ua|-CW~V1E9vnWXRxlOJ3|t#y&q2LDoijXiW~eO#iR*-?C_D3*(KmFU zVh?Yl257f#{MOagAoJDJ_p*!FCxTXf&2vLg#uy)YAar6OwK24RY~}I9G{a`?ae3-& zV?t+H>v;A|Y-_c-yQClxpYL@RGIQSN4Mb^Mp|N$17PT&A(NY1uq5?vB{oR^B%yp%o zy`Hw}2oE9`pa_3GEr#)zFAkh1%%g$oWAFIL-Ib=yJ*kcmE-91!zE#wDB z7ic@zWKSc0#CRzP08%59gi9So0qt41J8o8?nGXHhi9(s8-jeIiS!XqcicT%-PgOT8 zx|Bckh8oxW5TBT(Xr!!VytNN(>ZIjecRjE8mUY(6iS-+wC}VE+vt?8>oepS_b1z|& zD39Z0V^nVai7AU8(p=l8u$l8Sw9e|IWyXEnb<6@Fc>MoK`RfGaXRZq6Y_#uLg zlw2ovQ?TF8N?9Kd7U;D3=2mFuiFlG8_)U7==rykNi z1fM|7#)+ptrDq@bT7e&gN`X^;?5FZ2fH_q5%aIgTHQ-1qI*?JM@=LweJ@5Wnj#}}R zM3v*73ff5z{_&c7iaTe}_S0t22_5tBoi>K^mXjo!-$sqImIq5q=lEr6@6qOO_-61} zs+D{cx8^?fM0|*??crLmiMvdP%ux?1zGSOAZdN}%Vwu;$CIs{oc)%IlOwK@FL#|ZSk{xwCmTKw{3$Pr%b3A4N z&6;CML<^8G&+KK=&GlnA9GA`9^N;#`6e5vCcCB*Jm0YkCt>ev?P_eGgFcl*H}M}S#rs2z40@hl19rryCiry!v&Ld9kwslyCa#Q zSyR%jQA+I1Dznl!Dh@2go<#zvw4WHy+yT(M@jelJG8LtRRz6AaR5K5Av<%AM)P2gE%AnJ0GNlay11Od6k zic=7A!3Z)YZ>TxKun9y$BXY&Jb2ucw666&}V5#)eF&L9>dcXE;5Kc_VJY&S32K%aB zAdS2nJy?*%w55+et9ZFRtZk&y#hqrB2V)h5*+)KgzJ+#j-@_;_VQ>DyzFkCfa8vnsBzh2>W zy~68xrPcFnB>j4|2yb1l7JFXt|9X|w{oh{xu2(HRuUdY+YUzHZ*7Iui*Z+r~i)KaN zw1~WE;Q;tC>tr*ETQS31M7F?tE9U%cr2K5o{A}9%Z2bIe-u!Hg{A||zY=L|O2DrB^ zTc9nQv&~>d^YIt!|7+|mqv8mjy z^XPK<0r&y9GR4;KLYUIZDXv1xs}eqUf$M~^zQCBJAbnuCNU{wiMWHgDqe1Lu%a5`R zq(aFLL(dBnQAQ`1ME766MVjD!{DYLvHrlJGe?5%DWn}fy9NWxKOm>`l`6LFv;K5Q;Q;ICi`90`ngj9^nlajZZ`B-l?#VsxPtpFbh?VFZ7E zN3dZ9enSx>KoXM`$B-8Pzfg$mT_E}{kf%WWiYU$wYXbYfCjSeH`QJt^!k6saM)ECw zE>WRpv|Ch_vptUrKQh*CoTS|DosVt|SzNR38JVR$YF$_Tne*xSCu`3s!XpwV&|JE1 z?`Pph<1S8lw)wF&j`1XGkNZ0PYz|Vmqs@GMI^9{V^6{fu?qk(8!@11ASDoJT9Qpry zLI~dwNqKm2+Pa^h_IqQ3oT&W#Gap`DA~yU*E}yG@1l4`^d()Wwr5C>8&mH%?FD|Vs zE*%-Z`euwFgHAacP3ipRV|vF*q5CGDcgsrQJhm;iDil6r1g}9)nY`>rxhx26LQkpm zhLg9l`SMAs_pmcgmbZd}6~g5xXTHMq9vUG=(Nm(K2~(&_a%E~drcs(+O!Q6(h2%ez zk*uj*q+_+Ms(Cb@ca6LVLpaG}^sU`&N(=vAsV~r`cOo$<&xYE{NQP(hTlXR%Dc+HE zuh0-!Q&X{{)0@0LMByHNb1R#&-yZ}2-rLDZSuD1)x6c=y<&56+4Z+b#84Pv71?l)e z1+o<}UN|U=rOP?mD}#|R{x%DRaEfAlzzq~l+C;g)89$}BQb&4);&ig_B;3ElF@zS& zTv6kLhjl{nAQ}ij%swR~fyoXr)8T_3?PA{~6kOqafIsP}6@uCSb74Cn+S)JLT24Xs z!J}bcqJt?Dc5ibjyGxlO($bqIybKDW-3FK4RVx%^`7Gy=7BV4<0!i?AGTLot%$0pw zc44~#rAQoh{a5(iEP5}*AVmGAr8oSR1$f>tK+hZAJ@88twqQ`L0!^?CwEZdJVrGb* zH?$v|%LQZjmKH`&l`)zh9Q(hIl-~rA8}CqbfMt&3VyX@V0Y|~bAH`j0`pA`i^}i=CsV7fC7j$XStow+_&{Q6czsET(F1N{maD}#5)5fPHnRL z{qmIHKbol!06psVx83cGgXNd!IoaR{Bwfl-5 zqgg54Ixb$42Sjn5E88{P#indbWpdhqq~xXjt<(JjUV2tpsyc`I{IHmdRwH2d*nJw& zgjIj`ydhP*g}3xfhiW=pWqSR@1=mK(g(pmibjpJu<^v*A!6Xe-jSy&Ix#I%rG(GS z?$Uj{Fjf0B{x8^OYeA~gZ=%u^Fa8et5!-MxH|Y+Y>qT;-eqQn6)pl+|;Ha1EPv_7H zUd*_eTJbI~_=6r$ZwNQUZ91-Og7@^z6%qEWaNQE#qPhL+eusKD>3V%x>X0|AhF4k< zQLJi7#haQ;tiP*JI1{0iHfT%Y;?DAIPNI*PUnmzN}<{ zE~Bfee&P->mD{yYcdX?+-0yeZ*1k9>$^p}_UgCo9-a1o224k$zzCOaUU4^gHmC3=; zfz0hEb=zOGL@R>X-Ji!j^1M+xhVx&damAkT2zRHzP06S(p4ajnVs zr?Y>rxJXZh^gT!MH;+@7wk_9;=2fya0i>_jGxz)vO*ekTNpSyYDEIrr&2y9aoo$C+ zirNG}Om9pD!PJ++E|h%mp}g=fz4XJaj!6w*r?I+H{1H(`sb>`#%^9kfB%y&~#8Xv5 z>o|VV?mlg+hCGz$>Ru9Ny`U~;xV}3BrQ1`%IN;4L70j~Ev*q_ z<+195$6fsWM#Qz@18H?57^UWja~$ESgyQ)qxw6tKpP6xn*rtRiCGQ8RT4bUR$UG(Q z!w(5lWJM>u8tfhBT^4E)SJ4Id(cRSH1?2w54jaoLEvgWnfN)PhC~jPsZixY;NnNp6 z)%hG9#}!`_V7*`kT9Dkh2;E#ccRNN)p3Z-Ys*5CmGF{vZ2`Dva+lTT!0SK?^Vhk=BQj zDh86){~%QiC9Mx3Rs8Y35Ss2-tQgZPWk^4WlsSYH81Vl=fq|sJ;CBFo`7a8*>f1So z6*&4JV2v(t^ikjlUf>8#;0Rja=rC%?A9Ae;tTg`Kiz--duEHl){3lj?CsqU}Al4HQ z`iT|Yi52__i1);b;^e?~{>Un5lQ1 zz<+RXgs5Vsnvts?S#{x9TQV63jVp;HnyhUDjiUpN>jI1u#o2U4+2lSEH2#M^VnnMV zN+Too!y-xx!{+0-u@k$gK-H%r)i;qYfLDz13#+3(EJ~5MIq{z4VYoT5o|v+qB$y}MIc2aZDNe`ogn0gN_2=yd6>#*m`ZezN`VQ^ z@w>QB`yCM%sMI>SyC47}OY*qCpF7hTWUK{0ycb48m3f8a&(-1R6OL7yJ-6I69Y7y#vfEWzH zm}0hd2WknzR)zm%?C*gXf`FZn+Dt#SZSi~bnO{W0U3^3~WG6E;>0->g_{f-uNWEhM zl7h94L#VI*jmHk^qXdP()h{Bx_b@?HWV4j;^@~vT1nBkQV$A&#%;Mjo5NEpsbtQk} zset;#eNxT?4GK)~p%?r9ed9<>eEvj$i71T{h#6`e9cH|W&{a+GE+7c3fqs|S1{()| zBG~>!V1n2Wwb-{Usn!Z@c*)ncg_M`R236vLqIyYCu*L3^n9@T{_CsFq$PsCc1(`Jg z7d!`^bEcBqQhDg1x(GABKnT-rJG%&zg@pN$M${6;;8fIpV`QxP zvaX!7)5xz;fy#@t`T|gs2JOav*%(sO-_J z;+ZwioBm}}d*tTwd3xOQtO^6#Fz5JDQ(7gSaOHf=c9OpeF78Wk$N))P0GAW2!_HZX z__~l%h1MI-^Oi0r?#BX4iMF)#&;iTr5PuVL8Sr9<_E-mI^oh_=t#YQPdw5XM{s1i` zoZx$yD#-jD)mlULxO9ly{P8;eeD|M|^TR9GYL8*n_>d=NTpj*oAh%6tag!(K9aq@2 zN20J};!{thYC)W3oqF-h{&wgTemH^p#({#e%I^?=Nnf}1g?=sZeGyp);e)a&H*2C9 z?DN!7jSDYj1xhTlsLIp+EbOnxK7|fp7HAu%qPBCpLm3y3y3i5g&N5&Z5b-Cwwn^mH`Jn`9A z@zogE=6gg(e9X=4PrYm6zr2G2$o%67d}F9v+Iv<%h1RHss;GvttAy4l_j@X?Stv-O zP-US2GEwp~qOXrk2|CS2dB!OzXt*NS;|*Nrc7)wbS9B7Rby|lx4ry%6niUdorwzPh zb)OQv=oLN$&IYlQ8EJEvG4{?Xw%+}5>gR9UH*cw7aG<6x~>u$nu=9Vetq56aHVx4EX38r<8I$+vU2 z#`td-v}94oq*SEK-8e;*563kiMkKeGH}lIp0a+GobW0*C?mbBLhS$9+YOQsLv}M&DCjjoeH^qGs3dS-GXwyH06sGvxd5)FVnhYaXijd zbu*{@6%HdEE8i5jm5{Q_Td3>jc}^EMviYYfs`qV)e8bHyKHybxkq!L7Sdj_Q=}Wil zOa{vPwR|g@3rMTXPr`RZ`pv&*6O16?(dHtA` zII+(6{IY@&LHCc(ZvQK?r#9Z@>cICn<+4cEt^LM$cN-9oHVVUF#J~2zM*lM%sp~%?_Rx`j3;Ne^ZSHy!U7t&6d&pU#RiC z`{dlqXY_x6t2Nxl)8FEE_ZZ|fyzOA^TS?YaC#EZ>8$oB9o!f)wdA$y=?Gtw5AlY}t zXHcz>%0Y@^0k#VWo#<3O{?+>AU-q&E7waAxg;O?Fx=}!#(%fZ0R&xj>e|i#m#jDS? z&w#-q*@LwlR?Sn&fDU77U5z=r1MRngsWujsKuc%8CBp=!bp9ljF4#{d;%YSw36Wj5 z@%oGhq7mvJZC$Ll zzyDp_z9nSzFtpLO0Q2icmOS9n-yPlElJk1G!EU9YM$^Jt-66|&<2@}Fref%z~kw^j9jQXg!gtsl10&Or+Ek)Mrv)xcnGXVq2uE(6a^}8+B_h=?hrHlZCE6h*>cU)+oG|ND08B+ zANc6X9wh)KYa%DpPhQs~;m1<$ce!+K!#wYox%}b-BT`zzw1M{o?|+4A6a71g88Um{ zI$w4F*j#AXwsvMTr;{*C-&_-BBS1>=PZQ0FDV}?m?}f1-*3SX8_MmBS?WK4dNmXCQ zrBWL?d0+8GNI}Yl%>$ZWu+gUbLzKhk0Jzk@^Fyu?#E0Q)HLPg;aeQROTekY)BWkaN z^IH~7T?`5)WbR$<7ycerMbpetBr&vGhaN13(OO%#9*pZT=oZ#dYHUwlwEdL}Le zHbBO(*o!;~g#1j)xZc~MB(VS|j`7~dCLAqqw4e69r`kVQESzXpVeWf^E(aCty=lAz zvm-6HLp;71M)7WEd58$74;6Au6<=`wL+rd}Ml}8)U}{7Xp;o(|Z%~bqvaP!sO|2b5 zKf2A*w4hXYXx8<1@lB9Oxp(GLzm1@(_xMs1bBZ#Ls9Jhi9^r5iq$kI}u=E>8P9d^4 z&LiQ3{_DR1?Q4FUg0#9{$uTX31(rf5hUiq;%e8-bo>CZ)00%}qWnl)#CS_iW6=V%% zwYvPW#i6DAdWkq7wM!2{EcE^tNAy*s+5^)VOZ6nMrv6VxC-(8aLq1HI=lN@PL|Mk~ z%ytEK*ba<`s_5Rc8oLg3hg9wjWhKm4U6>(ku7McCFi&D@)aNPYdo;5v~NIKs?BO52qI~RxF(BZk250t(siz zI*Y7F_A7G@wRSQqcWwE=sqVZnEaQS`Otl;RDFi8z8dAr)nd!shXnajRHNv^^r17;p z0?)-enB2>7$5;cV;UB z)S?dfcdh!?&!M17-8vlE?%GL@(p;LeF`q)YoBSvGmq0(o&U}$+ql5G4)L%{tHZw~% zTrgvfoa+j_*JG-+%eGuAiXl#l^CvgNVi!>62vEIH7oGO;6_8Kg|I_viga9yhO)>RD zJTrSMs(N!LyT*E|Q_k%;6>d!Cn24vDKj$!Qq*k#uy}+>` zyP&Kfp`e!_iJ<%-?4X$-m!PN^zhL=bBnxe01V$2Gj`-QTt$z$xzyn4X)!N}fdq^q7 z2@Bzj$MT*}N?USsa^%?M>^;dXvevGAWh}{v*rV0`Xqt=NNuY^*3k4G9@hVD&ds*f| zeiGAMmLw-z6Lg!=>TYoZ$UoR6idjST=9-tDjgIi{d(_xDp42Mp1Ap^X#d0P1^!(Z7 zYjr;v|LvRV)I@0rM3>w<)dV?9S1!i)B)3PWKK{QZRNCT-1=vZR9>4-m`LB|`IPs~A zB*KzP^FeYrI_hIV))coK4=Vss{g2E}K9IX%vV;_gy&uQL77ziDmX3cC%QOnHo5Sl%B&9zMLYZT5D;ykP*b85(W3*@6^~}`V`-@Ar8!zFTU7z1@pXRm zC4ERw0P_9SuP{f+SnR`*ADzoC??=fpG&g)l^CUN6wH`PIG`IYH)cUGyz>GAVu&OKf zqyv;TbuCRGXeBU>6|$xLYJq@d8VyJ_jkRNP`q(Nxn`pVL_1~+~C5g>Gq>Gp`2|r25 zOd{}J>{Gc?r$4lu`w~$T<$Gchspxvtc2g5(_kP=C!`X`#`>|*pKMs7$(Y8B&_sY$? zSGsIlp`0z2E>5cYU#0QalfVNOIhxX0C#8LNU{Y)gD z(U00kbMlRj{W#Qt-V42_AoLrud93j$XwL9MetH>| zwjQxJ<*m|55 zvwAB(;~h40aN5%-8sQCǬo4eGH4D`T+wvKSl&vQ(IAe(SEgBDo2!Z;T6&0B*qr?tsA~aa3@8#<#a`f(q#Fbyjml24PADEw=~U zX4*M^F!1@aL3A2<>S@ln3>qbx`I-q9z$0#}XgAj2gx-OWCWn{1OTpam=XL)?t4nab zEVBQ1GQ*EQ6;ip(m!oxD_L#Nn%$6cGZ07A2>&#bT4ZQD2`CNAv#Y?-T0}-~tv9#G< zd(HTUUc2?Y>rXqi?(5H+fJA;&e4ooX-i@F|RQG=uYU!?o9OgsGR9bPSo>#bZ(W=M$ z921Cv2vqPNprDMyP;?+)@Xz;ll%JU>8E9BO(Ni;1G16B31{IX&l@?XzmK0XxmlZo0 zTbbFKT3gtgd^fiP*g$fn9PFHI9qpZg4|h+uk7*yUVbS@}prD}s2EK|2|K|tS!g9S* zBVRMi3zdlb`+S~8h8rnA@Nhm~s}njX6or`Gdb9~Cp-3Tv-DbQEE-INxuf}?;1vR6= zcBRI0p#vr?mPEkmXtWtQrBc7u>3F;y;b*p>_vO)8D|$|c&-3N6vgkKiZAo4)%cw(f$IW;2~RPJeQY(;KtTz5#H?0A1*I zT94fKc4h+#29;wGLjsj^6_F~2W0?Q|oRKGgiRSE;-Hxdrb!IHD8@9G7uOIg!wyhho z(6g-{a}zkJ8?pC3sh{veAaNZuks$$&I?-mj4u7{S$OMji;_JH(nQQ3-$AG-6t|NBe z-B*DVzUYECg8)JuWx?A~7glx1<1;T`)pjR+Mo!B^nTZx`3iyDOpvXSQH8aLG!&E!Q zz94wb{Htz~GK#r|%iT+x?a?T5ENv{pSC2iTta;OI_dG7c<@qeZnK%90pXXQJqb#dw zcVx0xq@L~Qx8vAajvU9#QuU;=uS)f(zz(Pr2m{9nu z1XOI4RO}r2Yz+DA`~Wr@0DIEd{J|{?OM@wK0|3Fz6yFVierHOq1m+swWEuwxvTRba zfd6@I7d&S7f z*E{$yr^QhleVXmBuV zj<{-5aT-^Qf(c%PkKg?9UREqsJp8-C8@z84trqlqQ##r&1N)oz&k{IAf8cUU!JWka z)VyoQUi;2g5AmO`j8>C+oEoiiQ4H!DH1Cel=5@gahmG!U=MEhHU=q?jqPrWO3R+D*7v7{?bZ$}19zTu1@6^} zxhMW_FC*-;zp~7z+>&FKqRA`bXR0($T>@zQ}8j z^7KgCe(TX*Q@&7SkGym_+wr5((Jj8%D38+gVcRaE(QYihAMzeW=?u0*>7&E(d=Voa zXDC|LxX+|cxGOu{wkZoW66=4JJh5AMm`{=$Yh>2D3_bCm3#8vpYl=>t8@rdH@=Ea{|A-IO4$RHM06qvRi}sWq4z?3wBGPnM4n zsPR}b4ScKo9W+Ynn&=rc&S5kuvxihPoGB)sCSpa63|nE|^*e?Mr!FBR=jcBSFen{VZA=0EX|(&LlXlm+twwTdH2clC*Ii4(m+bLK*Z z2f3@tXy?S@54a_zMU(jYzkF*>$~ef?ZaT>6RgpuwNH#+6EqAP(Y+~C z(F5L0H4&>RBybEMDVFf>XM>YS?Pnku(Z@5EzM1VOnYSQivJm3wRpl{JD>rlD8L)0J zlP@>1Y3S2!utegij@~y$nAn#3%(@#By<6cEpyLy+{O6bQHR=2`!0QL;O@y$CJL*}G{zMPmo%d93VGbKU+KNF{jBP)!@uiD@3Y?Jsx$cEN?VFB8{HL-8IR zg?cos)km6H_uCiXy2B5$x%_Y6Kb7Nj11X$uYAj#VIu<-C7U1n>E$pT=Cu~~XtWxf*I?;}*V-G;F zhfQ6X<^hi7-@ksUG>;LLB`ht_$LNz&(Y;yF!u9!zyUSn{!l22mp@ll9&g>Z`1)SSF zf6#Tn(0H{-YISed zRwqCtfUyZHLhvly48t|eQCM)n06qX3ZG0nVAId&}IQ%B(s0unSvFZydq7Xul*q{V* zfK#*#+VP*t34sgRdZcZJvwdi?V2M%XLgpH>FJfKvVqF#Uy}H%7Bm{gP&}#mLZb0de z04aDKsd~p&e-NDA1E@V;#dq5J!ybR2GKry$JV2lA4*VmieV`ZVvo(NJvXil?U`NxI zKOUL}O(@HiUjt~Jsdyzv1GbJClRl~K*N(eS$)j%biAI8_YX zu5LO>6hJxL=-*%7g)>4xS7e3sG54kM441-H$H;9WTVr6uwV!gVTq=!7izvqh|ygB*qMX& ab?Uk+hzxPzi}D9BiGnj^LkR`_PW}%h3&oXHg#bVVA^-r=3;;l$ z?uz$5BCpKA{KNB84xsY`1O2fKUt?QC2LJ#{0{}pl1OO;^($4|XL%|Cp&KOh8E1wyqmv^50)#(vrc5(NN2 z8*$nONITd&y8r-_rvLzg(T^O^yyfQX|Ls#yAaG-^&Q*N`o<{%($PfLeR~SKg{~I$r zF?}O{{ef%*xdi|NKz{H);YSysuwM;7ZP@#v_x;dM0ZZRQ|4aReKt(-(j15c-3>-~0 z#{0(Or~2Rzi9pQ2%>YCq*ZLFnUIH1hxWhkpmFMD=@W1y^yXaT6 zexs&bsXvG4?rk^rhI}g{CHh{b{1VGDnq+4_{tjr^p*}VdHuU?l?eN@eWgO}7+(tj{ zFQFN)2vlW&6S(4smVAS~eAhvi23OeziUDTvgEF7> z-uvFJwDH0CW3Eruh}DxeCEj9S(} zURflmr7sQ(`OGJbXRa{vK7P>qb)J>@tf{?sVVV7|7_+%@e%@r&8RB+f*RbW|>iXJh z<0~T-QA4${zKp!lL7{ScG1g z>84GlYjlZZ+~ekkH{frS3r~)3Q`c^2bsD-haqWQCF>qyljv0Nt$b>mnQATsrrNmdb z2|3;^+fkbA9p%JJ^_+xbiqXlwzVkT$f!RA}GhEDo{9LQ`ZkZXcqF5Kelz!wttK;7r z+8Bmz6maubV`>g~asYL*pK|gq@n!1zP|Fe&W&jAIj=crE*D3FQnbxV9MS;CQwsGDb z%Ab(9f53cw7%xnZ-PYEjBlWm5=Wy?k&vR7_X`Cz4myhrbZ7f*(?W|of8O|JRY6OVq;42lGIy=E)~ zBi0ypHCwxU%Z=zkD&X@yZndiJ$R|B}RifkO| zo@Lt>q@PS^1#F@9dTPi`gYw}ad-(c>XwNYUaQKHYmUIbWa_Qlrl)G(C9|hJnJ_4C8 zy~#2w0h8U>@ej)UweLvp!QqLlPBZJ4RdYPnIZ9i?CbBbdNWzRDbP9>3Q}V{WDjUTa zVlSOmH*T#_zUs9U^|cqw;%!x0^GdRuNggu7zOaGvB+tdYMQ(l(JTpckCj7Nw6;@UX z_5Hqj0y$T}1jkQi9l?S~gZiS4Hx%Ro~?1Z&BqTv61e<79q7EoeAb^e6a8-CtYr|^qB@?a`9 zWFj}hei9H~9O$vc^A*TaOMKcZu^oKBML!;H-t?vCi$rKcciv%qWZYREWMMt2^bkAd zIdj|pGKyz#uf;P%pUJEmRsL(gl|e8aaqH76)V<#}A%A|8r|dnQtp9d|ovkzQr7jyJ z>?>(on-=s@ElcdYp*QV2iT$10;sW;mZg_crbh#$I*3^W3uEunN^**)Ig2uEX`|(A0 zQioJI`F?woY=4le*h8Z%?a$QvX;Swp-QgGTCZ`@XD^|_1DCvuIB>Y8qOhUI^#~jt0 z6Dy9Dl#rR-qwY5HXxMGp@;QzDn&Cd?c&4+Ji!+grZ`Wx4*Mr$k|6R-~QKj*&FK^5q zW9{9MXTkBQx5RkNT@iO8Bl@U~I>z|5#P?ukp?)&YMz<8%(@y=y#C~5w=7`ffr!j0T ztDxqTdVGaMN&VM~{R>G&YT+J3{zD`-Lpe*<2B7tll^>zdtXXr%h$(YYJ6Kx z%4?oY%}tu$LTdc5yX~aD4E71Re_Up${hCH?ZYCL?3T8V(%B?(88^a#^_6b9xKiv)G zxR`$Fl{4OSBu;L^=Rxzkp4YUVQ1SID`ka66Qwj3tRt}p4-o-oqy_{;*s{T3L&id%! z*Ib)|{$y6m5{|F7Lr;{gg1v|~(x+i{r19aUIQ|z7=E~##x_8R+%5yS>eD$|X7kBop zFP!$+v%R-J{}rF<1WU@IQlt1k%MvLo)g$c|=o83q^n0z)jLQk(wKxRBPhT`w7ypz* zeNqm&dF;(-k~yrzFDR)qQiz{X+5;#$6~x8(3OnT4Z>J8=)#h+gvh-~Azr&<=>DAAT zw_jFw8`g%}b%&<$s@A?D?|Bwj(7zzJ~ZaY=jNdf*o z&?HpA5HZ+bP*7)3*oRaA5}6nYnFK147%PzkOox>1jBGNnszkOW;7OeG(u-IhG#U&XEY9&lJb@`XD}@Z5Ltk2Rmfy!z$dqh zZnw{Vy$`>=4|2c^f4~GJoDrcH+CW=X&s^02Ugb;(;eZGcMaE*%8XQGOZTFO{a2u|U zKZ?Q`h`mZ^ewdD%P=s7ib5yMpAGNMGEy-|Jv-B^Q?lu1TusJ(Tg0m##CH2MwLWBr) zh{wi+#xFl_=JmJytIX4cYUqKtCQZ~!rhR)V4rvjj{#}ZV5E84PA*(RS!w3LYgkQvn zJ^&JTz!BHf&XY3ksDdXc?M_E;491f#&R{;~yM!-k^^m31Sk-dELj*k5PTf_I{SfHN{=k zb;)JPamks@k?=J5#?-B1!H*P9x zwf6C0#>El!*Ye9Jz~)epDOuFHdB~yKgdW`>Enp;NvtQmLsE%~1j^{cR#7QJ}!n1>N zCrZAcKXyb08~xv}zT02@x4)!GTw?5&b-muy@eLExc}jE6%>PdLG|k(vZ%p|)uV%C6 zWz+ zHL$F?Qb@=c;j~5B9S1tNO0)q3$2UGsA7&GlEm;cl-q>UL)6` z!>HTUhV_olJF0&I4Zofwhz^aP=}=2yZ^q42&Y!n0sjMn_pdG`ogC3F|iXQQvupWq> z_a5&a?w*Z+o6eg|d;VRRr?V7=9VLAheGou6-_-<)@93I2cXgB=E-!1RtII+8hvIg* zj3QQ%j$%YW9{;=NsC?cR>t5ChU{ngQ0dxuE00@(8pG;E+q-3G1IhpsWl+08lUj)4Pw`Ic=x2CXS5W+xxtHjPM8G>vSl>AXlxyrkWY58Zk?n!cR?P5DtVnu?IHv zroSQ&@TGS7Di83i`s27r&y^Ii1bC^>7xFoUXCou#enZVAM$9JP&gEduW?0UKSk9%K z&4$@M7>Pw2(8C&`!y2l=n%PC0=tUdx9gkR`_i3R2#Y7+cg+5G*KBAKPS0;6UHPsAE z=Y*NoKz7nlmDYsrmu!TrO$?n)(3DLS-eoxNWu)$9bk1dP&}9tBWe5W&90ez+IVW)0 zFVr$lSo2@F`p)2f2B1A7{v7~5dLdSfMhLYACcb0P8+w21goqdh$6H1+3 z3!Otu7h^9ObF51<3|u1uENWxZM45yvCz4Wo{Rv}Fq5;!vnN*HDIX+62MT`33rA2Ig zVb+Aw`D8A+5o=ex61L{j<@ru6eF#h2nlj#&w5Mf0E)8!B@vGvTmMFI+yLH|7bHG*E zr)&N-$0CT>L%t%fNi;sYpw}Sig(8Z0Tt>Us=HLPfc~34Y)I&1V+yZ$)E>pxqwPf{) z3^H#WhKy2@3`6Fj*I4oF1bK;{iPG5!d5fRX{An3^ji1^4*$H{~L&_JkKBBUUhJdO_;4s+|^}3_hqQ> zW$eIZ7|CUvJtvI5BUjI!%*UvN&YqDu&Uul(L8kIihCaQ zzXo1?W}bol^7Ti{e1_8k{hjLu6Qc`DA#c*18YLUY5UB{kOpB`%(HiFuzX+lp0as#} zpb8#OJL`5kRsVNw{XZ-0ZeAA7lZlu#$zd`ViY-g``+VV-%H@vdo z+b6&0QOAc$sZus1l&Nm0WNZHHu*Tfw&Nh#O&AROB&u>UL6H>J0&FPHWmUX0Th}~1R z1s$ty<7CQr6tnVM^%ayl^;^;%8O^Vchvd5^ZwOydV+1cNU$fQ3;fIIhj)xR?C&LtX zr@)B5Q?|uTv)~`o+@R?K%#b)z>6PqQb*nc$Iz>7(Tq>MyPnnPSW{<|n@@bN-h1IEV zD0E9UfjYH3d(W_skmp*)eTy%WaYR>W+Oq8W#O%rnvy#1qIcR$6w+eN9I#oHv+o+yn z?9}PWwhDB#JC!|qPw5?GHlaJ!J?+o&G?5q_LQ6^GebBE+` zN|a|p%9$n-Ma4L>)`=uJiM6cVl2I~JUJH}typ5D+!cD|D%!FNuJ*;74!P!!83p(U5 zPBdrY_vw?PRVIKb^G4#{M55+^v54PNp$kIf2+%ZGvQg>4l$9o+bY^#j?Nq_YQuqsr zX6#Z_8B)?PGFW6NmYT}AN69ipN3vKd3XRcftgZ@@V@_IYi=t>`G?uE$2usP;`Af3C ziwcdY%d9bq(qm#;8?54ZWEYmY3#gCD)kTl8D69&NG3>0ia}r}}>#NOzEMyoK&Md%m z$(KcRvK-AyPT{TW-Lqn2e(TFF;@o5q7TyaWc*(dwT_EqGYp%5aC-LmzH&s-W6#Rm8DF;0br(9k7S9|3lWVhMdZf9cAL+DvlmQ?JV zb}2zFrKMnAX8KF13F)WZ*GvLavQ0kFxV0EaicJ|)%1W%6sveh?o~N^=>(NxfV+u!H zEsJhLzsrc&0)h4vq7BPHJxZ6zpE#E|&&cj$sMuY~?R`wSJ*?Uc`F6XW{m|FwtYdDw zjOTXSp530a2naI(er5r259M=^*Z60lTnGOm$8W-6qI9U=yX2TckTMb|cm<&3%}^vi zuh0T0VL?Qw2sw2kAty0mOvLX8a>Sfjtk2nzhhak4VE`->8PnoJKV!52RW$Pv<8bnb zhBDHD3`X>bkIA4AtvFFNqiMsuN*{H#sCD&EtMT6zp&(>va0eY(hoKhmDP$?K|602A zVJ%>(%W~*&Y&kAG^w}<;Jj*g95dQwRsV782NY@rN>ry^(b>AF#*ESnEEDUjEUxF7S zOmSpiloJ!@IKCq{l0}%F|AFUH2o*^+z9U(dX^>v}q3hBK6^k{#BWs?Cm|ph5>(T=i z0XDuPjghIKQSjmGQUVpjHohajlF6u1_5tG34HX49&M(1{>9AV(A?#8G6^A#@FXNsG zxeAebMo<7DBa+RQ;2`%pa_WhKm6q(Et;eqDAo@yis)~ZPlI)+T$1(R$;I-^j7zIy0 z**}wyjp?7vtNE!jN&v?=zw}O~fRDl#=iA%|O+UVe7*h}-^i7Yx?fv@y*z=#OTHTL{ zpIDGdq%d#fH}vO-%2pO)$y66|&O~@!qq8)Gvb9iz!n0t4%CUfg(zU>X(zVn~HhwNf zBYP-KB5lrJAZ;$iA$#D6x(m^udMkMed!T8Uf3UudvtVryW9{@X!IrM(jG@C1B1g2A zLWvYFvK;i9Z{9yEPk$^t8~U~fZ`fun@&L~it!9{_&W$)mybyPeG%xKK44vKF=d{Fc zC}6Ggu*;OU!JJ~q4O2tZ7NLn;$xj(XUl`wKvqWnkYp(R5(~`A8tD)ZxSVq*AwT|Q{ zju~X19p0z2Kxv3+uJDjvm%U`YqUQ^KLgW_ojzlQ#9+aEg-VZuMY`AwRe}SYnTRD@s zg>tF(aOM)Vfy*IJjg!Oh7B>$+Dq|ViUeGk+JhN#?bBWck<5It5%b`dOo5t`K#t1(u zff?GK7d7fQHEK|IiO?|XRJml*B~MME$MBX?4>v8M8OohgHCj8fYB+I;(LnE1yM)rE zP>ZU?_)f4xtdix3{1)MeSSrXG@-NjMtemge-FS~_#Py*Y(%z$aG12 zL2zl)VCxkB(C$>PCfTCMO~1yt5I_j0D1;a)ofqCOIWugqddDK zkq=MHrx+q%P~ImyvuvPxi1wiJQnMlErO?aH#mEw52u~}*7&4oa-bXt%ZCHDV^bqw@ zwSn&@*Nf1@$da@VPb=dXdRoxl=RLJ;0C|Y@koQu*MC_*6&f3P{79t3LEm5Nb`$G6s{Jo(6uPUQAzc-?{AOSJsGg1u6 zU%H5>Q!`x1SRy>X;V8(3HTK0fQ-yC-FiA39UYU^Wom@5!*6b_RED>RTK?m7v?$789 zFNiHU5s)o?0iJEh(zsgBZ*u-viYROu1xnfm?2znUh_e>=9@){JkfDXUggEDD{&$IKyL&99xxx$t|jeMUtvl4Sr*3Zk2ewt{a2U-j9Y{Lx{u zV{{K{djaJZG7xyTor2F}iiw%(&Naz1@z7eH*8DYX8{E z**jCZY++$xr`ku&{-QZ%P4&|ANfp8ow5)bver@lMBh)j2;6DH*2P^>K^0Vca#(u?S znOXcC^H90=|LlM3vz|;JOf*zB04o5XDgZJI{s0i}17(D$259#IIe>2hssX$HjoUA_1!Pb$fXYd*^=|QsB1osSGJyDT~QsOr3AcEFeoHZ!yrYAr1N~n14Yr8OJn*Urc6xf zn3!R`%)sLUGRop?^7-**K3mzY1?~s1&%cR{(X>tUclU9I8!S9n+iW#diOZn9kkTl3cz&&}#<6qh@(N6jwiobK5OwP$XwX&vI5H+sn{eOX7k zPkJw%JL?3e3{NZXU7rhIZO}v1ztFy%K@kA)0|Gy8@BipLhMd#%`BHlQ`2Q{J{LQ>J z%(YafDqoue*NtqupTyp!_7h->5vj!25eW_F10TqQ$9^?t+YpwGv1F#B7bA5>+7))4 z5_v`H6}Fv{yyg0t-)cIg=9-$nYI3S&wHVO1E+@`1uinjN4y})Q4XZ7e+E84wUBX@F zT;5-GT{7U3;ZEWD;%4EFcyMh8ba`;_Mb4aPzp{mcP!ZCg{+?F=I~QUh1Rw(NxP%EX zp$`nWXaiE}q1*j`v-$!j6E6oTK`L}FLM=Ay9kaKbLeRm1Y(~uJKEWS zs&?SY10cUo_Twtc9?Bs)Aw6+b=fZHubEa@zamu<@y@tu%&#gEAebUSk*cQxjj(5U) zBE9GQ9{YO#2KNpAohDG*7vC3UaF&m+gY_w4E zgB~6er;GNZ=($7xtbbAPMgi%B=;3ht0qunN;RwtTla$iZ^eLA_;uEh+6wRq&S7WfdnD{ah8h-xkn# z!0ThcfBs)sYqH(go@%w_){pMARLZKjn*NVUyT82=-k>T$*#h4LPzpK_VQhn^1?2M) z@=+~-xqjyw5MqLn2XPuu^#!7q2ZBKoLOU7Yt-`|xB<*s3Fz66mgTw`4^s#$z`+)X< z`U{K`#>8Kb;)(=Si_sVK7Rt`rojSNsSqZM>bI%E%T0TI(q0HnDgm`XM=V}{A-F4Pz075Q_T+8)^+>k;7*;t^DwZW296)j@Ad zFIr4>2BPVzNsyuHCZs3ECy1Yrr>3F=s}_!iHRNpSd?a+l{^Z^Y!5y5_H*HAdhSwFv zJFI7P(@?i+Us*vNbzXjsq#jW<#CE*ypxZvTiE2k*cIf5=@yh>VA6nCb7#*gL4^uQ(o zy8-tOHv)G8w-U1zZFgY0;Gn$uu)VoFndzRTuO+4Z)t24jR^M5jXR~E%m9^Ho@iewQ zCbwD=n+m@w$PNGN+X>!1)?LosE2l0ePd7+MZUxF6%N?z4!*|Jdg=NeI3Kt+C^u*q#5+V7#6m%y zkblT{uvIWm!OY&Aq40~!i*>Q}p-i);3PCrbHC~ZX*a6!?#-M)$bA-;mNTYD0_k8XH znetf5Sj<@WSkhQjg;<4JgG~*`Ty}rX@aG195*g8tfkUwldq*pre+IFjfk6%8U4ZzN7ADeYgre)X(; zMQ>SpO!C#Pm|P)Y;`Q@*w9};(``+Tn!2AcoAy!@USHcr>EEKGsG_)a6qkf|rdp;JQ zO%OAQPP$r5I5NbkLnRtC$Of@HlmS7>+PjSb-gcGQ$*c0U+O2lO@cx{0Yjf1b#L(d& zW3Rf|*c!pl(WkYp)q=_P;yQDB&?VpHTIZhsz3w^=fui!0@afvay&x2bw)F{`FP0xv z(coNwREb*6F+7+gs6>L%pwCvV3(qWtG-1&~!1UO}|E2(E#ApGlmWJZ#dMEL8ZE33H z@>WmYW~}`-GvtgrcKO$hY*}@RuDO^QeKO_ULR%IuCjEUk#2uS4u+aqrVIlYjh)7kt z%mX3Vq_cS#wz&P;rcZ&ay{U^Ssmq!a0V%tKmEDYP*F9eG+fz;@UN`1IKz14Qy~iP~ ziNfzn$-)m<=a;<+HL>)=UOeI#$Lm}H;vB;3{zo@Fg_0o)Wrng~OFr+`j{6Y2^*7ZR z8orJ3lEEF&18#nDzOfvHFJ(Q@-sw+4!UUmyyw)6*d$cPXdG3GOVa+GgXNK|t%+VW_ z190{5j+kw_K^DbDkclev(u!mDgNFWnN<(k(JM|^ZNe9$@nvTzPHW4cbE~bg7rlimD z0-~{{%-l3lC!vA1d)Fks>^rh$F6-m9O+`r~v&Z1U-N%)LA8oGSkKLCZl_834xbm*(;g2Z9#^K9dkk5k-2!sY`d>8 zp%sCZI-66I{TOFgybr4ux6)-LbRBr6^n74C*qqlGq}(F3*u2)PNxk3IlCVQ(F7&-T4+6@Kd7M{(qq zRc=UB>=0PAf=cUa#1aK2lWkeg<0A7oG$WnMRA-1I=7F}|Ox{qW`(uIBt@G)hY*d z?tT^B9de+BFh63=Mmr_Tsa)c>k0JhxW$*_2>I=8$#_V`!8x+BB34KIN(tso1?nDnH=-7oE0VUIfe`$UtCfZuu1<3cgy?hubc ztm0KODB&5@w8z?hKa5BpT6)4~V9Pfi zA!|rDnd(wDGJ3TAcW&^&GS$$<{Xhx5tdG@1=m5DG_2%@T3by`XuEyl5Vc0B!taV*L zSphvFf(~DHcL*i$LR#dJQy4FC$uEWn39P(`tN9V-EHSvVX38}hZ>!rg(3PSF=wY~| zGbQ!7?nZaQ?iKHevd17%dLr<`PhTNRE^F6qmq;ba6b+JG>`U~{6DRoa0vsu4#7ZO8 zKRu|VT$79vZeb3Y81_Lyt#MXg=&}UjJ2^lzzSqv`lx`5_wT`Br(3sZHPnR2vY6{mH zqk@Ucyh8NsTK9JfeF(6>C~ve27Qw@0pXO>*(KzYhW~5VlKo+ak*Fs(Ij1IQ1rW?(R zjF95$#|&%<9X%k*nJo^#-~O#ZD=~pxyrHEp*exFZ_F zaBGJvwtp}mj;A$_!7#aa7pWqN;5y*s&s2j!!-#9hj@|`zG`aVlAIh8{C1i_VJi;^A ziu}bJiLWZuI`B*8Zn(5*MQP7RPAT&Wq&Ock)aM&20EBp-K&$OVZc4bwF!wm3i+&-- z@2g$Q!!F7UCupi|l02bE5Wf&iZh&aLyE;b2q`Nk^P~&ObB`3SdehME0L~Y&*lUQIyb?4Be+xs8w zT-_A-)M1qeO^$86jq;BHUryusEveb?tty{eKIB`E%tiP2docc2PG=tK4ZYs=4i+mK z>n~uW{pTP|&Rw9G^wth6ivnRGKa-Es_d8RW=0^dul?E6MIcjj#g|4LSgP66!(^#Wg zjbGl`l;({=YI3XaJxI0k=6Kz{c5$<`4A+;uts0XhKE}phouH~n9Qjn6ouxoK!}^2y zw((caP+QV9{y}ViqDs>&8r+-D4qeVGB0&2yd`s@Y?XCW1K{G_^lIqRX3|mR#2t* z$}`cF_zvxl8|)0qX?Of8n6ET$@Fpa{J5W43lWJ^l(V#Ua$CFtdJi*&Dv@A%Le>P#| zTEAds{NuTjXz$0Pu7}Gv|6$6!lVj`)AA=4s2jWD(RHnI9Mv@aktzCbbB!VY3s(vW? z+h(jlG{D?FVYFG`6^=iJC(YrK*__#^C1nRevjhU)mMUXq5w*rk)?q;-s#lny<*o~q^BQ~6gYmSP2*O8JTq>Q6;bT#C8?w{h zyGI$zAa}L}_41ch3^0EB!tYvdX6n4Vt3So1EE}LlvDj08lsVe7UaZZwXS1f*Q&jA| zUEr7Xuy4S+j(l_n#EqGZ)VY!3J3cYbbNd(_b)V`tHA$hkqm#b1dqWjw2s_3WPV{uB=@ z<4S`{Zi0uD#uKO!Vy}W(aMxxrn0y&ZbB(_)RVvm*Y}R@yxMwU&WZmgar{0)(=$*I* z!YIK|B|AM9q>Gl>FSQIMhYRFkCD zGzXfz^Lwf&Sq=)^-hBt8%Z!UD)9SpcmPF?9KY#N!QQ;A6DPn6z#@IxKc_+a$<&eR46O~5Ne^k5*{B;jSsa|n9tc}d^Ywxwuwm}RkQw?M>Wyy|&#J4j!dOz{ z2$z1c^$%&VPApP$x`W@knZ%L~I0VX0>J!PF+%1=LGVk7j`$jkPpfZ8)!e%#GA)ALxHAP25~8S!nbSCNlCV703s5cI02xQ-*)Mq^JA^`ERKGh~1TDL98Tg*s4e zrf16s^8!sEjSJ8V1Vs5}e7ck0HSA}`-gS^r_*GoWg(d0va&&SUL4rp2W!+fnR@n#j z#xL~^rUK_Y2bHQ?HR7bc&0ux$>btE8u{v;L^%7+fEO2AJC zq#|TCpEec8%Y?Nu9kCi8+DOJna47-nPl;XZS!^dA3DOgi`T$X><^*UoB2EDLU<~Iy zgS8ilHYak&>{V~cTYx_+(`e2)tGTzzTQ6!g{T|S&Wu~Wa+UkMyooX>vy;mQ_5+X89 zbaF_Pf>t)wS_fxXY1uS<&Jiw|`{>~}TQqqp$2YSgMZ1Ml=TTD@e)3IT8$3B>LM*v58I-S(#JNISs7NUiEerwsh8vuJSESY3R7(|UC*i|S zuqpm0j@bAf08hl?fv01+I$|vm+3w&iBa0j|Wtg7%H-fQ@ql&dS1}1m&ZxXfC5$-DL z{eGIiAB+7%s7xAk!3$WL%Gas+`?qP2n+qnslwXZvQ)rEDPobmbtjlOQ z>99&6A#2t-MU0a(jF$kxf9e|EqlPioxMoEY`HGe*{hf&OoVGUoSFlrzK6fg9N(M3g z@k4(d)RZuC#y80wVv{?xA`WBGM}A>kIBjf3#}HGhx^TIYUk6WXWB;DK4!OQ3^*{=$ z5%LR{2ahxRcOR|LH-Oz!F8n39tg^TXM&3W4|(6tG> zCKmE|fSkpgBfX}14)u^X=2zC;(TV;O_Z6-+u@6+x%3_o4jX?LvestD(VoO!yWA5Ht zE}rhzmfG^@+n*joCjY|m72p!S@XweQ^S(N*g<&aV5r{Bpa8m1P+{UX7c4(aPC2gda z&OSKRxMwiZZqI5r)fR85`Vd)i5POykXPm;Z2%+jI=Fs5b$IqdwZm8W3ZRQZ&PcJSe zP5$Mi!$;N&=3hMRp!~b8qkP`;ac~Fvnr1BEUYU47>oU z=kISvCv=CHOBsNEKYYckTLqA90bMP`k=I|mlk4%@*ymG6`akz4*Z&*7I=WIAvV!Z^ z$h$U97~6VtzGcYANHZ=aqWwQbXuH`D5Jeu6)!fv<(S{U}ADYW42*14p`Op&luAIei zp9~_p7tbt-Ga>SiA(fk8z{o9yThF~Gx_%p=nW;-v72O-jEa`h^b=#R&6b+uZ1ZRu5 z6Yw0}GR=7Q+24M6{Px^za?5+}<7|~?miHa}=XaAxw*4t0%)dC>w-`W@{=hu@uU(%x z<=RoU{8^pL#;=6-`k^Zk?kj!@Um>}jCF$VpmW3xaQNg#Fk#j(IA96`F1XrdR6G(@n#uD*VH zEmTTGUh)n7(=zKJ&g93*2R@nwQ4nHS>I=1d5X{V6#8hJ?^MDFwi(+L>(LoK37|ucQ&~Wzq{GKY4~t-2MO84RDa2H z=Obg>uXr~gq9?5RM47N+xx=6KpPC?9yWLM zrBCz@-t`1emo>VIzDgj+77`xCYSd#t->&vo6o+|@9SsJ3^1vh|CJcOI^y+HA>z5D% z61NtQ^>bj!yGWd_xZG^N57%>z`;4-vrG=E~!u9viuzspyd0sehAI|t0D*Up$0%apc zZ1G@rn3KUqI}>(J4mTxX)^AkJH(p)^<62QCXon@OJs~9f-^y`Dc{4;eLcRenB{PM7 zJl5%_{E$-w;BRe(p24U3zz-anb9GovvV@)8XiJf8h2!~beyV5pBh()~ziQ3eb>#X{ zI?~r({eanmZkhb~tiXa6zIqc9AXm^OJpVoefB3dTeBq-w-9k2CPpB(8^-_L04{3~F;GE_sw6)xcoHU-qPrZ=2=WnfJrE={GgdY8kCS-b&cQ?TG7 zZCS$Y6&zSvzQMxS=CT@#F~E~Dwo@px)4jf9fF*~u(tvB&{%WvvXX}i@ngr6*86o4P zC14@tH3N6XGikS>vcrX{vFRF}^RZ;$F13Qb{q3ZfT;z)iLn}SbF%by#T_TeG?aPKR zmAt=@*~4W~Qm3?*jkVV8Vl)DZTjp-*XFOTh=`$P0R@Ar4rft6RgPHX?I z8|%xF?-kDSPi9Jjf&zvEHu-z!X&g=sA}pRy9d7Lie}@z zw(r`J7FS7$HRIZAwMPLD;2{L_ZNC#YwV*ygPTLiGjkC(5W)p%nwSiWIu1}#k@I|vM z@UVp0=NXMqm=<~5KyOeI*!fZGh7L|-vHHd-`?177uR{N=hVNpdjG}*8m#Pi;Vw2V% z7-*nblW}7K3tX8O8A-YiCy3VHa?+?fgVg0M?V^eE77#rwlsp9$7jN-LP|k6kTF%M4 zdmU2p#IojBnm8wNi6T;N2q$u*Tli@A-^buX&kln4#RiG!J7V5VGe7F$1Je`1`p8#u z#C|lP#p+nBkS0scdokpV%}TSW)m#2}ZXQ@)^=RiXU(z_(Q4k05+*(1iXEQU|J4|1H zasikED2M0R61K>Tf&d(@4D2DnlF>7oSe3;tmZir|7(BWwQc z@Al-RG2f2gDLBnc`KVjv@3GISWF?>9DE5v_@xqnQ3dJ2uz_F4`H4t~v@iS>BW0Uy zLDnlh*Y_VDW|q9N=%Ea%_+rPwAO-meEsobG@GM^Ge}(aHJ8cj@;vF_xBKJ#zE8aQ3j8Pw}jj1Ern$yCVz& z?!(=l17;tf$Sit!q%0X08upAqrc&ZEP-lHuJFMxwo99Rm`vNSk!~8JK&mrvW58npI zuA;?ihJGas7fTaacE>ZC9v$xM%!_vBXn^#nV^J)n*P-31X3UfQ^~r0gTIdRVLr9d| zkJC;4WLht}L&?nRKy^Oe7>~NL%W^(py6=-`kDKB&0X#0cwG|DT(KOXKCFO;yD=ib_ z5R5vKcmro{!V-I9Og|^+wPRfLc{g1B1|0EP$%EX%{G;sDL>#^Uk7;}HB=t`pwWfS6 z645L3?RB9@Sop7DJLZ)iKN7h{S@`QEID7}R+s0ln(r0g~P)kKMF;cq-R{)#m_NWFf zod4!2GnW2`YRXh^cNdZ^m-#~n#BTN_MImA%OF947@KYyo6}QUB#f(t`MZM`ttk-Xi zRyZy8BXfKQP&$qyA=Ek~?OiEWn(ZxQ6 zaxLTWnqS_HXPo`b#&z_st~0)RcyZ0ys?Q5qx;yHPN6%Jk6+PYHNl#{l5(X2Ivq9VErEB4jo|c_w4fv1*=TeG z)`VZx0(;QH77Xlov7+zrPGP_>F{Z0e*}*Owi`0g0Rr#GV#Hlryru>h#*T2enTz~T- zN2}EGx0?x;*H`^QzdD6iQU5;xVnCh0G)(SM8odW?DpTx%V$cD1o^~v_H>yml4c0YQ z)y-|5ztN+dbC`WnTUBRmWbxRp-io|}L-y>LcliR~U34#8P66rw=Vmw#SoQ_+D^Y+l z?um;BNIWKoebPqQ?>#sk8wDs&|C5qCa9)`l?xExgk*}iUepN0==sr5g%BqAmOE=Q> zS(xbs^)=cI%>1@Gop_BB4gkV-ON9Ci*c`Et8q~}gbxAK_>;sH-*1U*1zd71^)bGui zv}=1rvlP%Y3*)W%jJIeu1#Hx>p3S}YA4XLZW^M({acjij56tQ2z!kN*^YW5O;+BHT|)!x?y2dv>8+PZi)DllfuFBl0b=T zG(rb0kCgQ0p}A)}b-Re>PW?4qi-ZYNmPaAH?P88rjb4EEz@^iu84$IH>R;gZH%8lo*tZSt`TQLF=yW3+^LA+ykL;|wkjg=Zhp`ny z#5x#N#JYa8_mjPK{C)K-484=P1C(WxvTC$&f9eNg%0#Q#7sn*?VP-4W5-T}bCccEe zS_FERSEw=gZjpW|Z1^3cUr@cq@T*4Buc%%^c=`ZOr2!9K8X97VD^O-=2q145xoLuJ3cXlc|n&18hhpMto#r0Z3BF913KMsVC916Wm(W+DK-?%o zjQ5=={k043ccUJn0*3n)sonaMO2n{KP~fc|9tEelxHRYMnu^PFEVGp$Qy*X|=MhCw z@NxmfC< z(ez7o#@EuGr+Uxmx6^c0Ktzvv;^@}v!HF*8^ zT{zq{w4Z4!I{pA6Y&?vx0FE%wzct^+^$78dyK}Jg8T>C_dxK7H*Ik}#8!XrWN`)W2 zRMK3bYq^BFJy+5MDumM?6_N{d>0zup0(2L_=!Qx+j-DmutwX=Y39M=MCsoOJ{Sst{%CCe{TnsgZk?s-Rk&lE{juB^}P2R`!P z@?)lB^%yK;WoFPbGKre% z&WA^G9xdxJ{zsSG@D(+;{FL9R&w0qxcO=vCXd*FSMU^uo$`;-rf^@5wbAR$J6c=V6 zhQSNO5`Z7A&kox&kht$D&-c0UcQJm{p2|b=L*q|hdFE?s4}a=rz&UK8Rl-hX!@F_7* zWfpiv%BKn3C-B3H3OonA!Ozdp&G`uN1)-f$MF(CIcvOi29~IljHv^a2C&z$m(s@1& z+)X(m77uXm~1_X+%; zWCP+2fxnNeL%d2kQkaeMBjgmbQ8wS*9-I_bAlfIPC%71vgE&tfiz!&1>>o$3g|USnhk0KB}J6x&-4Vc`9mch{**OR8h6`#OwB$okq3HJ%HsK@5Y0QZ_c?%tbCLv?ml;YX&$d#yTs z_Orc-v}-6BPk8*U-Xr&c_!R&8`Nf1M;dc)Q!fBW4yI7V*sBpfTaK3!fdE9U~F(m$Z zh$j+X1CA&cOsmV(8wuYxg!dCSUT!IobeyY-syxp1c8qkvW#nLfsvKES|E*_IFPttGvY?@$<2_SWB4JLOJ!!(l;xf z;&0rK0)K+QF9`hUWCOTCIZ_yZ0lAFNg54!!ZS79&wYx%bHl_06fp~UsFgD!HV*BJs zIF@EJD*SgRqo-LJ^&^dD)a}T)OQxUT$9@ezwuw5XNM6u>?2A9>oTYR29zj0uoIQo0 zkMcVzz-+&4HHjvDifm3#mHMV)UGJy;Qqu1l8g9!qG#1X!rNXhOC!{ZOPw#2FD~d@h zx;f#fKA1T;nMitKzM%4WXWLK`ke&ebqxR zqt;_B@SfgnQ~3q39$z{-Y+WAa%w^8wFDW15PTTI*TFrH*QcD`EUi#N$bc z#gFp%L4h|NuK0k<@#iGI2Jy(@#u@681|GmAA$}dW%HyAF=ocyJB z!qCn`B_6Xl^kG?^WBe2Ed`B*iL$7wY(j$*UA>I)9ak2*SNZ{9z%YeJ2<9;4EX>sBr zHv#v^<6_`GA%0X*f#-lX>^$*aet!I|;|lQwp&g>=z)Qk$Z&qT!M}aq}e;c^eJ~;+l z6WULZM+1-IN10y+PJ0{=X*>T78qYbjFU7-k1b&S3_T#PrN0cMQ+%Qkzv-ozl7QejZ zTKqwcuY=d@#rRevKD+Afw`}6mBdgku<#1|EvV7uoh`U0 zeWpIOD2z7idulV~c~P6rp1w2qyXd5`-af|Gsrr`tH2vlJ7L<6uuF*Ed6$s(Eke3(4lVo9_j}G9o>si5}27BcXc$>zs4l-0d(9+9L66NPEL0w(nk=D&$kybl(4{ zy$j2|J%iq%aF5&ab5Ad6qlK}hYAHFH*|~QxlXQuV-ic0Msa@q!n&>Ltwk{!^>oBpTh?{4RD#x?A9Hhb~EXA3V7r z^+*C{l$z&B5l!)X@3-upnKI5uJV5VBq_B)Xtjw{Dr?<|z+bF1e{(-hJ*cMe>)jkxW zIhzeB=P-Yc6!W1Hk8#et`0P0?^Ik-zBflW=4d8~vFLSu!lKAI=6N#S&?w0sXz&(^R ze}91a`*+?&f4@9v%fS$@tJQx#E?NCUWAXHSA{d_>Y#PaI$8epH_4X& zNI4QepeK^vm@fo_zL+~6n^}SiuZ9YHq{^GXeIi#@fX5}i3;1xC_@u597;ueW3Cf>GK1e?!dtn~D+a=lbT|sG!1^jk<z~G|JC8R=cIOyLA)mLo5>n*#5vnXfVDHtdl3fk>qyh#ijQ)LUk9!NZ~ULN za{zKBi^6bjIv#W~NcT*f9>>nuHrKY_+O}<@T)U+$a|>$~*0yb>_O@Q9{cftuZysjO ze@@@~pL6=4zyS7JJ-T~^TVvW=HGmS*Yo@vW`5!TpTILWCZ`WEqZ@9R zqrn|=S%>I>PLY}M_}l8!R;LBqsp7?_V7=X$d4h-@-aoRKTs>?nCE)CMXw%yKnMNG0cJY{0pYW3l5 zUMu~Xgz-TiMFALPl443DwWyV=*~Z>q~5up~n6aW4B)s0|d# zt|NpP5SS}zV*@Fre@$@T>ZVu!J)(?w8{f^bw4`o$jXSP)`Y4z0$Wbg%Mu`}ip7CR!=*=CVm>`b~2p)1X%SZaT( z)E40h>g<2|;^(tOxA(jDi2;q8qo8KXs+#4C1$NFLfQg_2;t4#zq|lHh=%zuH?xhn( z%i}gz#2Y5-=MHQE;Jr9Iw5NtiZ*Bk%?J@hr^LRun_ybNaCjyc7K%@28)66z=gLt~n zv?gWC!QvR*Fvc157=;_9rr_R>H|*^@kiTo%>*iiSjjaEMHQ@pRX9{6)as3SAI#j>j zb?J&io!3z4!A#?#ZC~K@Xfqj|2g4~BX2X!`ob-e=A&!`rEApO=4A83b1XOB$kCc)F z*J?cg()c{Pnn*K4dWwWY{CS5P^;!3N0;25&x7X;|NGk`-MSKp7coX$5DV2nQfkcFw zu8enFvT;I`88m#T7q$3O0MbzdH-q5Mf7V-AFc|aYraO^uP-Kgtf3X6oyFt2Xu^Ma% zsqhV+=YP}uwb%~rne1pjM&o`4hl)HCSEJY;Fkg?su3bw=3hg)b^NjAGz}qUeMqhUl zDeJY`uD{iE7aW)T>-yP8G-q5^Eh8|i51~JUhPyN4j4x)0qtmYzgr~Ar2Z-RNi!hIu zBIgm&F&f{aAi7La!Oy*bnh*q6s;@ik$j?L89l^yKD>#DlHBN0Er>rBja8_BN)^{Om zZJ4t*{*bEOjT?VPA-Z?;6KV`*?@ILSp}T$KbA{d^7?Ky{jza$#!mfu|xVrW%pm!if z=K;NIF(4C2U5-v7*d5qY=EqIbjGJbM(E=-73`=Jhz7+T3JO2S+@O}{9WVeCj;;CaD zb0s2s!1({9eFvNy#r5#ctfWAX3r_z31kw}IL+@ben;q@xB-_CE{XhSFE6v-PH}Ac9@6FTHmT{#-PkT*z znVRaKP^e_FENjRlI#apTsfkV55;eG~+uR%2H}7*4cWBa^`r>N_^$|Wfn+eA>#%KVH z_R&F;nKRNc>&A3`B-ow`$0R8bnd@|}TBXry7=U&G2^j`g=6>YJQ2t#4^xf8T-rL_csl$E9mh%)iIed;5pUMWAS@|5Iy`89H%7HU+Xobuz9 z--M<^Iv>Ktp|XF0S0h}Hy-T2U6wM+04qgpq;Bi7o%d0Pezro8;`iZxeS5UnPFGKmC zlnUu~)XEb0DU|-NV?w%%ARvj~e@9!J)q4&6561u9cZ77Q`ZA*Z(Ps?#{>Xol9?k7ZFuD!rd_ERigzH zP``ZX#}lgs0w!0Z%9H+~qR$$&`36h=tm4d_LUp_M2vtP{^u6OARMqS$(?Xk(=rMNE zHY2ICPdy-iwAN-9;xnlBoxm?I6Xy2rFI)6G~AY%BJ~r&wPq0 zx5hn`)N0bR(6}_ccFy0s)P5!?=)11!Sm-I(izQQg+`;PRM%Q#lh6d*fJI4vItO-O0 zOCXrbb1cKK%NvCY=u7@&6)&6XuTm2UjXfMqbv^J<;nwgqg zJJ8kBy;I{J>$U<=8e=CX%Ux0LV6HW1=&^cC+QEsruHi+acB0g^N@x|GaQY(BEu|ne zX~9zf8B*A(K~fnSD1(*XtH71H)u*X<2RGjQk3QWuGT`%-_3hsPx7-H?1(~}LN3Wpr zffMGZ>U)1_50YAa0o&t~QzT{9n2jW$UZ1!A37o^?vZO)ZX{}!(4$bx&Gv~>(cS8A zE!exA5_0>hrH%vl?u1*e-e4M9)i)jN8b7*WZFm|DeP|g|}?b{yYh7%xJ+5OQ3=zdnPZ<5R_WxBb^Zpmv5E)? zrD$Yl%jD4wyN;S$mS5RUB$GYXQs_=5lKEcy_~PO~GL~B`4A1q?m(r~pZ!KinhUiSP zR0J=@+Wp>H)?2dWJyL0FTd*T=Dll{n^^UD=-(H?yx9#Cez+;`m z20fRw%x+AKS3>Kah;JP3-d;Mm<+QI|?8ED%g*EWdPRPL1Bq7T0%P8Gwn-sRqwEUXs zPg2jQ+QMTBq9~2^g~k5#SFZ@^Q1ue1!0&%;6w;m5SFu&15g_Ao`R6eHXR8DO zvDN+qr9aqn{rA|$*u>V>kqxo2Es02P(!xevd~e#(qS>~!|NJe*Qx^L#+E(WCYtLxw z>bIpA_I4}`3DVJ_$IMBkqmv(;K9BltO*-dNK0Ua(CLQmBARScJf*#*MW!<>!@@mlI zJqQALD2x0{nI2a>%7$pU;4`dHw=~l`pIz5+Ca~)g*T=d`{#ahF6g@>}UubwTy}8dUtc@K{DBGwV5*QpdWGlWh0N!;z6hYbefB(86i#q+w}Q zX28FBq}k@0m&ly~<7&S4_ITZHvXNzsdUaOm-d&a}Pp|RBl-E^rP`!Ee^f7HS! z_hEpqJf{K|<>n4)4)LpQ{Zr4m4`;xU%FgzO!Cm)*vcTJmh_~+}eej>iTeA-nMR{#t zAgz#E(dd|pG3dtE_Z93h+ByPS43)PMd~D59@7_x+DL-fOShM8f+P*=BoI)P#G40ZL z&-Rj_QR7G>eMlpm&}W*?)br5bKQPV##*L%B)gQhs2>j1BWhJuOdXsUJS*pG&b*|D59F%!*CMkY%gi+p^hWn|+eu|h}L9!Ypz zi%4d6)JlKFR_H&8|KjnF?`9WvTSwT_8J5ZlrBH|OJnAD41Y)Cs?wQh#?%B0_egHa) zBaD+vS;p2RXDW(d`0DKr^V*TFot0BF;9UDLb1uhrQYvBXA37E1e< zBbL9QTK@kdmX2<(A`lvkixG?HeWvEt4|R4oM=ag_(ZEPssemFDH;w$z>fW)9ChbgD zEn+dCh~-6i>w82j;mYq+;3K)k-Rj+;wYUCbQ1@5{e5*3m{uucDm%!X|#PSv@|Nj}W zObHRo3#k(#mQ8C%=V}ql!%}MJ{KP3)F=El+b`G2nvC!`su;j9?KDz?NE1d`L+lAtl zjqK3so(UAM{C4Zc=&FwKP92-9{N?bT#XBw<7vhx*rb^ppi;JCZvA=x>aoHTNoG->J zS1aK#idU{#j#vJKXj36yl=;AT<)i`2cVmS<9I&t`U>Qz^alqp2FO^!vh{c#nwwItX zH4yO4=2Pu`$G$w=)3w_fULD5~OUq!v8kucf4p}^zjK{Txz%k29;NMto9?|9-P5y+K z6#Ii#Hl!N_UV#u=nG4RWwRc?F9wQ6(A)UkgB*Zf!H)Y;x0<#V>}edJ04 zAg}j2@de^cBn5(Nyr|LQjoPj5u+nXD@?Or#3;o6O)fwV`;w*v|_Z2oASS6H!`c%trN31qi*kbiQI5@y4S+CvKP&`4>Rd*dAyc@_9;pcqNlu0&cN6^l z|C+jW|8La&{XM7)wPD#cQwNBTfG-oT!aoSN{Lo_S`3hM~#!pN})@|?rNJ>bl75>4> z&@(%-1DcjxO6#^%t3p|D11cK?FA3Iyo_7%f&Wpj{K?1G6H6onen)%{Uv6=xt>|p?$ z@7F~$dLv^%1Y6}QYIL{7OGkYQrG>To1sr=24y%YGT`Sn&4gTn1AXvcx|6`?8^3l_* zUOMJgsLTS6Y8BJ*I^OH}ia;NFeowGwjQdX*cK}s&B6i=2An@7d8o&5~1e}bb>VK-| zqm>mOh7@?Udfu^XYY?yzLtYmki1St=4cfp{!rl0_qaC<^d|B})_Q8wOU&?*Sb^jLy z>6lO+rk021gsn6D)>6+2oe6XWw?j&fG-L!FdV+y0Ef@k;00g?zXl5e zoJQ~hxE+|$3q-Y80?I(`%#s~|BK{68fr76t0s|`BMZAn?cvzsm(9}QO6w0_WRzB-a zznltrGmaGR%i3$}#Ge9p5){Hwss5t!oPeVm2e-l>2sk*QeT@aKw(;s$!;^R3!Ci4# zu5fhC!>8Q@=-sZ}uim=t-t|Jy^gUE6SSv*f3IZt}yFmV9!;^R1iArT#;SYpjmH+H^ zo&E|g1_-9Q1kQ#(#C4&0k(F}~nO%CP=3)7PC5=^ehWs-yKKYr+kftKL03YEPUm2E+^uI$%9b>oP-9z)_3$5FKo z0_936hDy4{9Xw^uw=ocOW&Iv4tqnyz^33@rtEmORkfI}F83;_x@&MZMaZ@I#&km~O zaW~UD(#P2?5|Ur*>FX_dJi9e<50T52{!b!v;O`xxl5CD%S zBncu7gpgK&kd!VrAQIBgI?RoPAWiBaHiBL>av=k6DdQ;ZL}?dJzm3xPJ=Eg#JN5Vf z#OZf&Iu0zr1lFMRF?B&q{|2Wk%V|=M(^YkW0L$rR9go9jfu*M7gViZ;7yJ*DK`G@! z`uS6oj^ngUNE7zz#oz+?JW5me{ZCLjh0}8Uz7?f!!D$74|5ubA#c3twLo&anx(R#| zepjfO0vWIiJlt97y^Y-d?u~+G?61m*&%x(~x11qk*x&Xx`S*9t!kZ1%O~i|}a-5IM zyx6v;4V5AY*ieS5l`{AYnf+~TZEu4oDjl#0z95ue1RH^{`Z|v|UXIwfm8if8ITi&Y zIHq0h?_|rt9gFPnZ#tuvCLswDtzNZ?b`Ex?igpMMDxEtKba*+H(GYSEPI!Sl!tFhCXhZ0CqQZDGQnNi@Z zF)9njL_`yGaCE;VE0sX09R9gaGowp#HJDR2wLZ@eiA%^BByp@ zRA?=h!&7kLbry*Ax*I$BURg2nz)zCP*I?KMf!=hFO5ybBR1!tDMd!6AgZ?$EgZA~K zg)W(dQ8S!GN!B*WCeak!Jm;M$I>-CjU~;m<13w>1*%Drm@v%-P6W# zM%6mb6ane5IpXj;%BjMl(v%7mrz>VwS`68vcE7YI;*1JT^QQaIdkXXpHoZITDyAuDtJbPR~6QFFJ3wlR#isEZytv)A!}@_z64)I5;71z zd>do)xXB6kSn?>na;;Jh<*Nsx8Ke#1K+nPT`Tn!Vdk${M_aB;G|H;{oU6+rn{{;HD zES;K&wQcRRCv6%OYbN{s!z~QM#q?a-+_HG#%>23C=wo{Ix!wHmRZHtWxh*$x<>qyt z*p|CCK9%p@Ue*{F$K>hR%-E1@Y`s!XNE&Fj5K+{|1Sr&xaTRw-6?_zKOY#Hw0$$l? zx(4|9ely)geT!-@t#f(orQ$X3!wz`a+mQ-%1-DQhj|}9=FK1gOD&hC#1kt<(v?CAq zJ=8bEh@v2Ix)bs>vZ;nk+JZsM0@ZxkVpFg}imW|A+B_C=wZl_1D0DVbsgdh-QjJ8e zQfSR2)iRx)D!0s}r#dIMw{I?>$C94a8#oT!p(F1ibrx$vNm-+$4g#ehb`GyNCHP^XNxaM%x1|; z#iM5F^Q8IcQM2TE0r2GS|MVTH8P(qh_Q2o4yHVubf$H~)w_`1DZ5K6j*~V)Y-btQ> zs$27ZDkL>&i+V@E)}A!C=;gdrrL%fX)}W(%^1Vm|d)S^fX;f{eEio>fQmHx%63(Qt z87yIIG$lVN(fB^cZDa|J+G>d@WMvKezqAlF>xt)|vYBR$T{%>uS#R4NW^*}~)Y!F_ za^Ck^(k11m{qCHvI5g(fTa;n_utINPJIbMseG_w6@9Vzdip02A72h7){OOsoi$AyN z)Jr=Hs}{c*4h56HlPml^Yo2V4#S5uI%cg~akVfT^SH8*H9qn5OCJ*-Zopbw!D?X*w zxLDKp$2Oh*z@@`;SIteHH6FloH20Gu@EItBylw#TYeP(j;FSa^oGeLa3O*8_gem-G zDEvqHgg>l3kKXIM_xjW({dV7yeg_(;x)=Q|>Nok;>X%Z9)V(Pny|{AlYtt7`e+m6V zA7A_0*94hvL_z;mWEYBV?Wm3><7hs1t)lO6SAu*rfroJ+-FsQqSWe> zt*Jb(vf|U{Pp+-dnqIvI97z{A#*&c569J#ArN!rxg+ojto#*+I#xS1m zK(ZbNw}1=DQf*Y1M(s#vC~;J`@CWV-is#eW9z_o~vi9;IxaEul0M+Cf0Bn9(pdD2J zK2GKcAEv!<;_OX9z*KL$Co=`0WK9|X)oiF3^wBmIoqSsJ4U5jLFSf@J^x#Z=TMQ|i4}k93V59s_3OnqF7ACE4Ree4UEg`#QuIg=*qy;p}ws zbjgcPs{twh9k@>g`pTioEd+`39RU|$ZSoNT~d^7$GRZv4#QM}dOXLmr2lcZR)o_?#tZWnvba*IT(Q69|@!=9ImqGv^K_S$oQxYTxMc`&`zb zi*6C@<`hKFC5Rq1woTLWL=7T`(onSWmjrQc0-(xq*^2W;Zn!IdGM=K zl$;K;8@eiw+FEv-OUXztKiu8BXRc z`SV@Y?$4|%Z^;OyI#DU7SgJmNB1qxkSWYZO?o90;T>1hkb=z98)R~|R){~oXJ0P_b zEcMJihh%*lyJesZ{m6$U50^8_l__H0Q=65pm)%D8b`Qjib%AuBTV+32O`nt%I=}0q6&Do6cub z$Qh&A#mZEQ;sOD2ZLh%RQEgmveT9?MZ9|`|$>v$1;qNxu;()pL)196^3nZ9^kq zKS7YF2>A(uyoDh#5%S;FB=H)C#6`$|Rb%Lkryn3lLWKOHngmMXzYwHFg#1Q;;8IBu z@?5nI7;&Cd9g-y8#(B~rkgrr8B1#z2R)Y|d>YE@5uEp}Xt1^!ukRZ_5(luB< z7*c%`iP(oBF)Zgcb zU`V0P#p}d&ViC&+L2wIxnAnCPZDO8IpaQ$#XR&<#P~C|j?SKYxc&{KI5t2cW4Hyy= zAtj&$ix?6YAz>f`o8X;-d_+ha%5w(1RgjMe=@uZkR8oYDAj}7Go>U#81RHUlvp?GkT9A(jaiNvz6%5IVkU8Qm&PN&macKbJaTwLB&m9hcq&;Bsq5?>e+e&b?^ zY(bvUA^OFprOJ(m`ur$S&d$U=ybLfZjY+{oi&2j)qBAnX;I^)E>!zZ^sxuhWPG(~+ z!aHb9Adk4(fUti9ait>S%d?k-ntWx==L0ng8nbz`+30KYn%H2Q>rpAGu?7sL4xfPo zz}e%l@WIYuze!{2AE2PNT+O5JrW61?1pL^3zzWj$gwqtQF5Su2)9&3M;{Dvw(I>Pzq^{ z&Z1PxG?a#>LVdD6)l921A(04Y>}cH%6z41h6i$v)uO&nE!8WTQmksH$kB}s zlUDCHX*;@=L9&t=wa`XkO$$(i&%?J+OLPgl;2SR;)8n4#8qc5NxulkyrgPK#fc3Zu2=nPIaT22*)2 zj}~S``cP?~HRvVfa+;%*jJmy3rPfe#15{8!r?2SodL1oVxmm;c47UHaIX!lxS*FlB zaGZD>c!InN|6V@sycB9h)0z+2-b>AOkcX*+cg&TLNn8|E*#bsWS0F%1tP+_<=^u!K zJ7wUAU^2gVhcgh>E8&twH?*YlGhL>!j0;$8)}1!H-;RC zB$7ZEd5$tElc4C^z_tbT=F<$UO>bmv;JZq@@k>%RDF3tFBveI%%Q@O)=V;m?)T9Rr zU_dpg2zzrJL-IAwBC?63v{og+co$d#r0=&ZwQG5d;Mpf$_Eg_s{-Fqn)j48`P!6lU;QyX96kGZiW0 z9!Cp4246xJ;t~5%vBxQpcx0-nqq!++NILxt6Da#$S!|PiSy~P{`|TEbvQTH4C6t?oMo-CvE`VHmZ8Fg#)saMU`Dbknhth-%zt)W_aHxVv>q zK{0xrL=L6U7c|=J{&I5IAmgkmh1Bb?*xgo0Mq9hB2BX`_>FqRwhPR9DR-fHtVjLze zi0a;n>h2;t3A4~r;%SOLs;Q5@Fxn#>^oHm;>3oQyl!z6!959$c^+^Y{X3_VE%OI$h ziDs64$j^~%!U$hu>>>tGoe+H$yW0BoL|-&Hd% zCIz7$n@1{_xLd3gv>6PPM8%qCGHyUhCD79q0QcJZ2g`bc!lN0t+6;Y@zV-th?T34U z0|^%^6{us>zF=%u4#;BVcCNGmkGz$^XTTG+b7BB5qfXppCW@;Oh`(W_6!!==-2wJe#1sPCCTbEX4>G^$+Q$@lB=;cFaqtATmc!E zS*d6BcDYJrrs;@7FN)e;+)%W5n7-JTn|2tS|Ek}A|eWzMs3ZJAk_l4mwL>_Q_Gv0gXsIIx^!eb!iD6N z$HBCgt>Fw~MLBh9jW1{8N`7-hrsB*@TZh%%9#C3V95sao_tAa!OFIW0=|U`w{|)t>AND zGhQ9aHOI}3t0e#IPo@0AUv_jfi~hjRay)7_p3nKwBG7?>QmJ3)6H~-4@NdW?TqDPg zon{->P;!F28*bDWbOD=OeF9wQJnIoTQjFWXVzDmauPqqxa*R%6rP)NOlweI(jgH~G zC@wG=#5X23UM|O3y7tCzFoEGzXJ;zi(UIz<>em{D{=(NI{JZdLz^`k%-TT3F(*GUkZpr_&hG)LE%LNsO&7oxMzp$ug0_+-Q! zjk-3}oTN#x1GIpZ8620YohB;^5j{CaE|=WUYYZBD`Xv&iSPs2IlhelYmh8rE=13x# z?CSeE6X24if&DuqJp(>lxTpd^YV?k^rDt;hr@5r^)1Njqwr-s(~CL%jbjjJWWLOI`%ZMZx2MmlQ|0c@yGJ3x5@0N+Y4Z zxhNB0(gPN4R3cT-s)<;cHrrOWY>K!i_cF~fLD=(qOieOk@jP2`7v(c0@HItc|ayfz{5Qe(^nX)6@ zwlh3U071iH5nd*YL1a3iIGrR+?X6q~TdTA74H+@8PoBoLEW3xl(Ce4|ldwS## z$p^pmQRNYdTyjKtn@ld*Eaz40)8lEtDtTU2K}%oJr@Hd*G#fOe?QxTe$G@4YH$xxd zJlC`;z2^GFTa=C)oSan4Z|;ahY8lZP6Mz1a!^zrS}Z)9Jaa4 zf=^0TKMLhY*X2Z)aOWcMQY2D?pcfQY^jsj4YtVO|Cu^QbB)=B=BK_hi+9c=@*l%I( zpq*cpC@bH|dfa_y4!ZqLxrUiV)Sy3qKlQQv0pCXI zm(;MYTiLDcQFf=29UlrVQTMBiZQnlKFmun4ax?UN^rOdq&#RtH_op9Jg#Ph0O(>-L z21>mB_Tw7<(nF#C{(ge2zKpEMgJ_fzN+N>$jDnA%5h=j{UWdS7>+$&-PMQ@J{JE)h z>IbYdwDn7p%Fh%JY~GkrB@CDB@+(b>Rq{6!v+WW}vRSnxQ_BE9SiA^iF1SD%+Bga` zV@rwcITg<C8E3nTkPs|7n|Kz{;Uc_50FRB-EEqjAE7nZ5DG<(1${ug5@Zy?|@g~mxvfqA`l>Ol3_pGfG6DJxV+J#kQ1+@ zAcdVA(#df~mpv9H9q{Q~I&XLQ z93{9zId8R4dQ~`&~&k;*r4v&+t-;>{hmtimbBLy5`Kzt{Dk3YYQ@K zo27TZ`(Mfzr84**<#P~uQ7z>`Httj*6W4X^9ZE;}^vG%DkwL+P`>9=P(sYPNh?&1I2xW1nYZJ z)c01R>jaI*F2ZCIf|!$Qe*MX1vpg!5f37sceqJ|Y(%xvRysUU&Vx4Y8*(xDZ%Chs| zykE&E=CL&Z2sWtJlN7mLwT_gL&w>C4_zCLNFJ)04JD>${8Y-im*qzXyK z;L&IFXiP??k`8i6er_>_NeJ;v0%DEKU>`1!*|H%O?_wqK|X*jtkLkxcV^&uoUx% z`lbMiTUm8QvgthNYN;MYMUgYq^uFoZyMMR>M z(mPY}(_7aU_U$xXwR!I2ySu3k>m(z+*hnPgv2TOAeSocC^VAj^=CnI*MiQQ?z7F1i zmtlV>5Q6(QpHDEG<%o*K>%=g@3Fz}J4t7qco>D$8Nu`FBV59P4k7QgmsGje0v1-?x z+}08b$ZeE~_qoB`U`sj?$z(i*bZWIu*_Qi=BB*pmKN1LN2)xex74S1ucLLj~4i@l# z>@4a71LBQ5g}S}&k^@S<)_O#J#DxA5a)Ug#DF7udy<3r**_`&oP0`)z)9795Q&l=C z+=#lQ^Jm&-mS&1Ge*hrDb3voqYHeL;cgq#eNvmS@C%s?LR+n%2Sl7I zgj#@)6eqO!!t(H6V-)FI>Amv>5a-IS-dVoy4eHU2o85hlO=`^<-_KQzJG(PnBvC5)qT{l0~9$Mo}Gpi?am20Tk z4l6q*-^cJwK&q55JX>m=>1gjdZNbcQ(hiR2fFply*HmAr8#rGcFC;sT-R;wY=y`{= z{vA8ODZ4czsq$*0eobL`gYv-s{rd?}oj|+(Ho+V5>Tn)#pYVd0JUR>fgtb~-eg|dn zPNKGV|0OaCKT8DR24PyGC zAdNVjk%-d~5mo~bKSUfIg+cf=;$}jIo?CH@u>^jIi- zO+WBJS{TJfxqe^E1sEwG2o%8YE7v%{VC9<*uq0+9AmKvqpM_>2G9(C(C+7*&aDrzm zec++WdT^Gb@^vuk$h{VSJbm|FDWOaTm3d*gOa@7S#1%+0;2}%pDhC*=e9ZyQ%H=@h zvD966rym!}pf*MFbfYr5T0MM2TY~3=%HDqBiPk5c$dw+;ef!(F$Amo=#M9tO@JE3M z)O!j2>xNHvemZ{XrLR2yyyxgqtQ#eSb%CJq{x5_O{drK^BBbcgbH01%yd&e!1LLTt z=fXS3U#k4Gq`$E1@~%ttXQ3x5-wq7mC^&*ou4ouZZ62-!7A`=Wys{QaYtE6evjG$B zleS0;Sw{x!W{iQ9ysOt{VT}GX`eGF7niBF*xJBs@Aw!=#QEh(W9`FZn1tG0z zs4s^+dK;L{{|TSgGDzG2{|es38ken~D}V_JAX=8Ug>xoMp|~-m>B4B1J=hsTuECxag!gnx~>WIWsLxq7zEHzw+q}xwL z+n~J#S66FvJe{3R4!3j{qT{Ijg4I{>Nl$7bTHiNb5SM6(M4+HCmu(ar9u7QM3a|NKxX3|X<3Cr zEr;~bJn!Ox%xZG78a}Qg&i^jww}NX@mD@?>yB{O) zp6>Hu8(v9Ha5zG9Snlg6JNcs^0~@a zF8#TnrKt3)sB}~)UC3v1ITW7rNP~oV9K14s@zmj-I;?#Ygqz?4O8@|{RQVf9RlbG4 ze<-Z#x~ThW-4}JK!nLpHPxvZA>k!oLN_;=e^MsyA3+--V#N!==TUdgEsQFraNuDtJ zdv|!MD`;h$xtQB9lISzgVaB)sNiNnk)skx+x@bX>^7_kY{Ac=S5=s)^x&Kf(;OX0Y z$t9Klr1LtLHqd7XFuhlQbbnt*Y3%O1C$cfG-tA1{^Ec2gT%?NzfhO9MMtq9~i+QKL z;xC7^6Ecj)i^WkRDQRZIyd~a#QAPpsd^tj%W=&*~>yXy83Up9xe#wq`n+Y@gM^zo(5|N z4R4|fSYSmJnC=7HUa*36q{X-ZH|4Cb`xm*$HE{`jF(MNQykFlLl`$)d1Nh z!J={jf`FGnyt_7I@E8JcGh8@!Z>>##0KW@ACcIIQ@Vk{;E4PBpAcmit5i~?x297{A zs?mmhVq;WL3$n3$T-k%O;uHVkO(eX&M8X&D<@w%lNO*>_t1_8Y+3b8KGyiJZ@5^L- z{&at2AR6tDMEaxAfk-I3CZAu(W*74LHCY0mUhqF;82%j5qCnJp3?9-@@EE8GxcS(v z;oIQWt%#Ki;5FNh-F+JYP@WhxgV%)Kry!_{M*)Ba0NJr)1@K6v2MG=~=(aML#{FN)fFoA#9SHT}^^hyOI zHK3Eadcngg0H7K`G;&M8hCK3mE~%IiBdTW>1acU+#Ix{!;CZz@p9S0!9>Xl0KXzXN zenkeyj$Hw7Kej=Lc5zN}I}F0#<0$u!#5Kf#5Xn^Eg*nn)+jAhyPz&3vAw>m);ZARt zC4b$<;EwA%BEC7WF5G+h&=Yu_MqDFk5@y+3Gvi+eO)<< z7z}vY$}rmQvpZ#6CO*a3HH=Da4(k2P*g!a2j+In!-Vx6Px;OdzT8&C`tIOZ#(K+;$ z-Lo6~!k&Zb_dyjtT+=u}k~EDR2%P~>U3dNUKmESud*9Q5eh{oYQ~4!`RxSpI!P$b$ z_ku41J^T~)1@y{v+TLM}S;zwgKg2f+KZ+qAf&0N%;WPNI=O1Cn-H76AMT(DN$X-5nTlNb`8r_I59g-wc<;LS_y3MwfU7_R*CPuEeL7yhrAJXVGI+o$0GeX&K zBhPl2+)ZdtD0|rG>U7yzRHVH9Dh#Nubu_QJv^kZCq~UwphHxgAN## z7QLQhoh2s>MCKwU&S>DQ{sBKKXNKP=UM9C-T93Pg-rRKAJpBD}H_C(RSD=@88nu=T zmE|d6=Hr1KSDJ2iZ-w5o&t|^#B_YpG;g5+5xn4YnLdbR5LGz(cXs;*NpKYF*F`td{ z+zmU47g38^2!gDIxF`8lvS@7OIfqJXrdglfOy|NVp|Q}c*8oRK117D(6%8nh12p;) z2?#ZR1O5WI$xZK%b%ZWQtuDRR%5uEHN*7~Rw^nCkS>6DDUm9Ta8aKvj(&*hatViKC z;z^`gB*H4hv6?@t;kNd6VFnStLA*_-YHvJLNCOxRe4|*bNvf0h3(`Ivwqbn3pm^$X zTe8hYdbFuTOP9%`iuJ+HXpc|Nx3z}U{=S${_80J3;vI53Zdq?*(S<^f%C0Sk!yU9! z8S8=1_O)t#v4mIcDDkLe9dIAAp68DL%{|RJy)0+z+8*jC_{1zBUMf_=NG91WQ12G5VOV~_)p_f%5yZ90LAwo@3kmz!yWR_!$GGS7L3xmze+>Y+wIL5Y<#PIx z{1$TS>ebAF145q7l{eAt;NKR`3!+ST_0WnB^PR4-yD7$Kv#a%#bkDw^U2WH?+ted&X!^jPfsqjq;9QAk>ndX>RRTiyKX)&2UQ*BR3&EtJB-+U)`j ztEzf@dW{L;5jO?qG7a|v&qNcxoK0Bb!C5V8I`Lw}?cK=yzdBNOR$hPdNz}J7RR{VV{4hj)Np;J+ze5mXwI7Z6eGWn7)tPsnMv%SL9<*cT z>j)yN&b|9HY>#2$2>d6Z7QCf694+uyl(}uenC`4B47;Q@Bgatf%9&srDp7(zAs!<4 z5}L*mLXp){yFC~-lyYtGCr+7OtJX<+q!DL8@D~IRo+TcI590l5x#REQmGQy2c)f14 zA3ST5C0zA;b0cGTS6HUHK=`WHAj)BN)4Q(_Bsq@F~l|v(1wfJHV+8I?jYJtb+{kqvPnH z8W#77beuj%Gqg@^p<6{dv>jTr&R{S)rUg2_0G}dWCqLDQr3J1a5$RZ$a_MM|iqix| zLTIajQK^k;V_uX9MJ5mq(~3lz+?Ytq7OBy>u1Jk0;tkS@@HkiaS_uvtV?&X+Qy4`m zz&SKpyD`Kt%9bGO)My+=9+CQykC?Y~C_`zjT&ZhOhmsnFQYX@?C%^fBQ-?_P1&lJy zn_U{6gN|?}Wio`mYg}|#WTI0UP6@bMRH2ku$2UKVA^s8A;8u&6C<9i5~{ zoe0Ox!;)s5TGkFb$FnMLON3YE#y8SiqDF(&f-wFPMVZHthtd+(b*GB7+(}mCW7wXaHp1QwnqSbsNt;^HSTr;uJ5u?V6L=bPHw%>?ct0}TX zi1fa5a(WxrvK~jT0((>1#!NQTTX&>&dS?;6wiD@XRNrQjhw6QDBh7p3-E-I#h}G%- z4WiqAJl)OMkE1+OLtoCeHBr8y3BO4F-^c=@K5!!SC)dJeK0a?!Bt?biSw@)%vM#Lf zja*%QqDCUVkk%hXd<9SB>*Vzw$Keg{Wd)7=UZV^x*Np8A#VbEY>aZK$3S~s??)YOU zox*8S_%)8x1vHOf5LX%Gd?a3EfT!F~k%Olk=^vxMW0Sn{l44cK%)qn44_#6D;YAmz zLm?%|Uvv@T?rns_ig4huF<$`)SLDd@ly$S_4O zpmYhRZ8%*)enE@V3Zk~I^Cfr~ukp6vG1Wqb$rLgIr4-k=2kL}VjUM+zZn8#%N6*OV z9h39J=rK67tDIhU!T8ATQhMD*Z+^L_=gZyQzua>FsoT%ldjGC1=caqlom+k5f!@Bu zbMrSG=oKXf4qf*wJyz+*8^+4r6tK}gz zJoVT$DkM6nJoc6*B;flSV)7P@PmA%tQGK11;j~WRU)XI97ZH96rENkT8Ag~R0zzx? z9`xy>eB!Axz)}XYd^u7%I{a3Tt6_;Ls6nyU;t`dAq5q4CAC?(P7be@&m$#SCosB7 z09AfeQnRXcazRCEQ%cGeo$0=~r}9+Shq_fEQJMwJtwE?=XmdD(YDctW3V_5a>7gk~ zU|FFA)V)&hb9=G!{HLxy6ZFN);Z|S*2|t<`d-JA)A37?GI293wQ!qw`5YjP}z67VO zSfAQZ`e}F<-n)>hokvo;t6sXicY#L?>mc?s^(8mhX$tv1J+Y3LYpDy)07gnnU3kX$ zhMVL-Az!P!=-e;g2BmP5AcVE53lD$gR+Ivz-Z}Y?!n0xNzD@i%FWa}aZ;m=699HGz zdsZF1Osa8ckx*1c`QEvMmrAu34IUjt6h49}wqTibAhO-?R)O-2K#9;X;IkgZO`nB& z8(|I#!pvu;b~U9;M91C0{#vNz@C;u(dOPMrW67eDb_}txb^#WRtU7lUY-kgm(WK zJGaa7i(yrW0D`B3pF(yUK~(d?vft+U4vNB7jA(7JU@9g{)0dJ1vooJqJG!T{cy<4YXHAYsc<&qrm z0Nb(uTCw5BAJK%sZ_$t;Yv8mR*68W+pc;En-G4%L+Xct2?!NFV zC#8n`3Zf<;ti}dShU^iQyKdw<=s{nk$5923ApLHz?@Z-Ufh3f8U9^Avz6ErtIOVZ{ zCK};cjh3%fVyka(3dcIn@BC;p$)W@uh-N+EuG3tn^aT2Vx<((OX)U4&_fnN-Pez7V zyU=SjS1Nk>o5@*Zb7x^M(Sy9=8~AiRm$1G-dR*Vqy!#d$PtuJ|-Aq@#`>DLpM3=6) zw@I(`L*QE{lL|S4q{0f81@H>-W#>d<>!;}xnr@5y_wvQxDNTxP^2(p(o1zCM1z9bu z{noLoP7si$@`cuYtwKZn70fD;i>mw{xUOoJlju#coPI?tQ>DRHUi^Qt^W!CU&j;Im zc78`oY2D@@4|K=3E=?o~gMHs| z%YS!D)aEjehLbZrBQ8O5pxOs@XdcUecjA)b5FW*gdPVXL^I{D<4!>JYE%eSV4J&>U zig(TaTv_fnU%q-|Y|E;?^~KE{i8;Fm9If2gzA(6|SJmRbJ(t_@?u&Ae1G_FbG+P=z z-L76g*t4xI7JjWZ^VtXf0RE2GR`Z4630pE5)J)A+2#D=PovtjCYL!H<)7TgdAGbOD zluDKx^+E}t0O_!3O%f?*3+ydhACf<~{|l22qg-zFT7u#JFD-T*?vfz>lq?nWC?raw zr9C}xQ_th#ilWz%OhV#KJ`ESTG%n}&E+1jqc-sS#o6uIjC`^P)TgoYZ&2-l)9kl3Z zyT&J>B*j);B38x?d9~D6fWODFEa?J;sa)A9@#XQ^b%Q%IYg%)Y8erpe zUZX2lEEkMgTB|Ur#uihl)JTBlPt|l3bK^?G8ou3U|YYby(QQCyyal+u#*;~#<6t~IIy!Lh#n+pny=YygAuotICzqowY& z_j@$k!m$ps#y->0a`{8&kL%JquHUl|jAl7YKHL~LS5xpk`rK#3%HOWQWKa!e7{99-J>k4?buedZJX$>>=Bu}!yM zKe{+1+$YmleT8@h@yaf@Z@v>Y9W8X3%P&!D;=0d|~g(%$s;{$MGTzd$b0iHke(>XXr>#V^CTRT8GA9 zD_Dz+K_7I;6OG~=?4A7;;0(0OdL~K5!dVB6i1LO8+gl?F_!l|yJpZh|gzd~d}2V z)rVg{@_O4T)Zx1H%DV6XcwDB zui<=rIG{5YTHAk%J>NUX^F5Dav=jXv^`3t37NA64Pv7A6D43u0LI@NqZZC4U-*e`d zrs_Vg?+a@>4s}2&%r5&pgS9t3aZev9TJrCZC8z3^%s2YIf)AN-SxwrhwHq>hv6$BNJ=zwrn}Y`X^boqiN=1)F zJ7(!IU7NozRJ~0-{YeJK4eP=DE7gu#3Sep$cCYI9E{Ue7*C-Eub6zYkm(M(KIn1w-@ zJru7c#g<>*c2@9dNosi?HExa$d#Wo5=9LExCI#u#y7l^EyC*2sxvY0;O**aIGh=pe zs$h(Z7{G`9G^ZSpY}!|LsH1v~c{t=%heyxb)U&oHXFrG>y_J%alebI?qh+rnoqPsy zt0tU?9!e1NN+(=D6b1Lb_eLV!$-z)M7VmpNy@5M>RsVXvcPq4Djp%ui{Yecxl&#WpX^;fa>?Q^R1d{+ zeBa_l89q4_;**(SUbA+7^;IbJ8q>0~xx(i0*h7>3y}QaiR3z1y&}vAk4pFL^ zlSwt^$PZ?Js61kz6>wRGJd&XeiOj?zk*(j`?rstp!t54quR#(@u4qFpTeld@0wc1J zYdQc@_MERXq%-LpDz{m1WFD{Hq;ClYhmuYv$Z{$PEN<7>N=a^DV#w^G6v%r;dDrxG zKf@=A2NprRWOi6-E*sl@=OVuAun(RCUMA$iSv-KOpWC^-#h1f$aCBq%2@WStJ9EyP z`hqgB{oWNa z23jhGE#n(n=!d9#;pz@s-%uy(!0j<%9T*$3$8!=mqEsIHx@2@;8A@TQo%NZOO3SQk z?)+785-kVO6YS@EntE zDaRbKuX9P(8K4cZkz#q*Y>S%JnVpQ*$z3oVD+G*OKIZC7SF5#O8L$F_SXF2b?i;QYHp zi7nJ6a4Tu5OW+bg0wSJc7`{VE84Abh$k$OGvM=hdkYnv8A?hQtfebPPJbZUfp};j+b8nw7}S zH~Nw>rz`Dd{4IWCEI^wrsCC{(+&zVQKx7RRO$R8RDxg2q#rF+>Ud_L9&#C`R6(+t0 z2ylhEDE*zZsBl((W)$e1sg6P!(s(P1kc0s$K2Wn~^hH=Lh9e;gxVn2)mHTC2BLFgK z<$egp9ao;F+I!cUjk|6hymMipr$^_~yNmYKy`^nengi+skDhbsOY4b-TkT}vA6UP3 zfmxhhx!>*%h`M)pD~23^5d;y}uOhnsf_3j-)&0bk#NBvBJh^iG%a!%@tVb$;Twcy9 z)bTfj@f=tYv|U^&`5~ADzadRnpZ^Ds`|{9Dd<#}iw)&879=>TgZnTK3-jA?JNfTa) z&Nt8Lb9^(hLc_bbk##Tz);{G_nUoTmHks54qyI`h=P)5CJj@vw2Wwy*W6IbXl$X`2 zYzA*%m@}B10+={{#)*JCQv*m4D)KQjqVtxMy)-q!U8m4L^M4zaWXagyK@MHZXepTvy{< z1DV5=J%;+#2N7kAU~iOgX28lYdWQ0$uK<1X;EnJySy!OHWBq__lN|iBHrlw$o0nAh zB2d}~;vg)Hgx+I{KlFU!RR&1o=GRAZ=oG2pmXm%@IQ19 ziZ{ZL>@#2eD)`Fax({VNuKROId;SYeczOl@6pWy)L+)-4zi7rg;Wjm=C8Ne)*^vnA>0r)nP?@O}1q$?9B87xA-j#7OMz5bS8T=-D){{)AW4kF$ zj$(a}rK7YEYSkIS?#H|ixin0DG(VtL<r)X~x@WcP)137qW|EgFWNNG(!t|jW=GDV*a6AxssV0?Czu# zm)@+ig+?-6Yew}_4uU2jQ)Yqu<7}!dl!gw|y=Q6@^0ic;k&mv@E}L%)D#6G;LPn2A}wg_UuEm4mIk3||Dn z*QaQ+$Ah?eH%IznH%gx<6bs2>S%O0QYR($;X$U`d)TB*7EpVkeSAA#3`OIc2rgW;A}UMQ60xJ12@mAHIeb zr!J5hIr4>pu_MFnndA1%`PP|T>`$*TvwM4cX7`(~E3*r!2}5e85H(WCraUe3UcZU` z1*FcwXE#7Y={2tm+$A)6{lTQaHgS`jKvEdka0d8sUWy_P-4``fP?$FDJR;LfwG)~PH zxnX#hdJTIP?i$LJiEUTQ0V69`1V2PX3AXF>2T1;ug}0ywRd{R|FVQKZH=LAkXEgw+ z_$d6UzeVftH@F6i{5356Jv&8kUuy=jBRu0T%y`wVMe+=}%dX9g*!#j#^yLk1dS0P) z&5nJ5QzG}wR^)^ceVOAbsTF>?qctIVG(+8VOTv| zS}8GcQ>2Ft@2<>TTPa_1r-pIfcGNI>!_(^zw1v`ll~G@4BuFZkySEeWw4&yxT>!*}l`uchAF&^y0g(twH+!6I$ro(Iomb zv==<~M2gQNNutPx5_#vnR7bQ(ZjdIevktOLm z^C)%$>Wy#SoYOo$VdiY}x+b5%=UskG;>d!#<2s*d=UT)wcxXa?@jm;=AXEo3wO#ck zazD@Lu!8EuFEK2=+8-XkrUI6THtf0W{0#_ID1JM3?wyLfxw)u2hRNGzI z+GN&Vdv{H1(-{zKtRyC?SP;!B6bew}Mn0Rs&n+y?AL;M8@V3eDTmo`-wsz%&<_T{s z8Nq)Hy7zZ6aWlu+%Nm|{8RzXsjl)OA_r7u=sV6zkCXU~uV;lW{&x4;M8*h|suAOVE zvVhNboH+vCj(%N<^Z-Ow_!80sy_@tCXop%`>njAeFkMq;LH$rCwm@Ick_RHj5U<33 zB>=Fr)wW}%MRnZYj>eiAqy>%%X#8u4`p!+%fa?73iWTuwkW^p014=^Z%{79fgOtU6LNu6hqb-<=9%v6x+MVFgpWh2Me_`i zun_!RQ@o@gQrktPx2tPDpmffX_1}?uoXU<-YuYNenATynNvpJw?y6*nFh#Y#CMnvmYt|Rm6K>gND{-Syt=>EMnPx0W{p*-?v&UA4ekHp)G z2G53nPdAb7ilTlhSWwkZDOw;fqXfN>N5sJIpZ=-2Pff7LRXw9hs5`L7p|oeWmUa)i z+jI*=)woX)^uW*UM}lsOny*0UMGvHwEdDnR7}Gm?$MuHA1x<|S?cJ{-ulJmze7)+h}G4uE; zsmW3_Yi?Zx2M!+F&c-&ZKn+=eaEldyK;~>HOKb|L3*jdI$2MinftDLzi!7(Q-xnofC+dazlKurbrfmjE0qlle;^_La^Z$mV2a=$i5G~K z$KRp21Rle8$+-)@yq9>1*!|QE(A3bmjAb^$4P-WQ?M-!3FoIa#5f`s$WJDL$^ciah1U&9Q|he)etPXHi!b z`glAv6DUsmG_D2s#oh3WqxNz{+JGj%g&fF#`!}Qle({4!xafQ5`lND3B;)NK79^vQ zO@f$hU2^?fo=@5m68`^4GSy$+1T5c@yc70xd*VWZH}acshcyyC$8o;4#u7soFK)Fj z$xY2AiLVAbHm#$ryTk+RA84lmp8CH)Le|l#k2m9IWk?f?I-0iZHsP6XOWH0tTgypZ zg+gne-zx7T?mKCO*RI&KTbLvPQRpnxhYl`VB5UxNr_gTKg_eq$FSD|ytZ~x`3Z&cZqnm=rH<;trNcX+GYSm3VN zVZ{&zUVyvEHg*j@PvUau=MX1-lkU*@-T6wjl8JX7xS=E9DtHIjK0k(o%d=G?Typx@Xnn;!+|zwD zp6|{^qoXz|=Lt>cKQ&qKlsrQkLW!$c&T=wmUILdux&qC9hUV6UniPpA&EAsltuE9u zK3k&KZE~zuGF^kCm7>=csRVTX1yxTXG1=iOz!I@kNS__f#X@5de~;74I^E`u&PI*X z@4=6;C!yDz5ZxIoYQjMl1izOq5_2j)Zx5=|J zJ-ahLb?76bx%u~8dyF>)e#xYIR5VU2)Yv+%v=1uH6BC4mrq; zP?6@$OL!FgjEgAC8Yj|dpbQlu^B@e-yk2(G2BGRHhA1|iYeFux4Q*^2c1^5@kgv-q zgR)4aS9O&!zsYX`q(NaZ1K{ZmdmL;?!&>@d@m?vus?<|ODt^$=JM7_ZLMBWKixC4Z z_}f@Epk=L9C8!KLN;ce*yD(3ZKgVl_`W#7{QR!uan&lHiospbR+c#JpHb;$E?))4{ z{ukD_zvM{R3^e>L>Xj3NU6H(3QyGFQS3};sZ=* zlu@fWGhI}s+~e`YszGaDsju4KJDQB;R@8$<9c{K%aIC)&iAQ>4?tnjJO{B}oz=(m$ zM53cfqzPZd^5{fTNT$&1Nm~to)*3DL7nyiQ@6g+stjz4z`Lc{#@3g6KrGX+zaIf5v zrH=1>99Xn8qrFR}Ncy|{Moj7?|D zihb){GP3@umK{?%T^|dM2gdeR_Qu0@&X@Zmq>$@K>k@IJFr1k&6wY?y1|+LEPiEfg zA$?|?V^pUO(e{ARjLX^KV)eQl zt*GC;^5s1=cg7Bdh+?-3*!O;I1@8Lc`Nghv4{JmxjCfZP6`gRgcvfnQM9T^PJx&>j zs(KjhWD1gpI8iFM{-acUzKggzxj&_9<2tL->|+P@74h@g05 z%Cyc2$HfC>g<%q$+aM=UyJN%HoFDd@N)9mSiCcRZr$3agrl$6#Lbl+V>{H5;qnk}v zxx#dxRcTc0B~BCb32zlF88Y@ESD5W%Y>v>!db>0f2Ih5sSNM{r%acPl9_+UNE#b(J z^=EYI^3=e|3wrFS^NJd;SN*u&48E#T)gRTx0-^OpxeKoH7jTzYwCXIf1*tPibeetV zsCSS@g|s6&^9^TeTb<*}VmMaI$}J8kF@Yd%h*}ydXnT#5m`LtOcG7mG!`Q)gM{u={ zS3ukf9B@SxTtQm6gBUHKX_3y(m~#0?A;t7==?7`8R%W&^{c(k!sM4eDQtnFa`Gh;- zoXT>nxnnY{GTQ>~*v{Bi?D;@Ai+1%z+y!YGE$pR z1|YK%VI!jLwpSB4fg3sDqPyWUTS<5*1KHevv>MuGqb-q?J0hi|(X>0#y6vn-=hp5? z?MoSj7vA@yrkw;`m--a{D#58CB>)@FYk8XeZ%=g zpfdZeVy0s{Q#Bcre^;&C^sxS<{H79NQYKxjV=;>RyMu}OJ_u)V)K%~o@I-7-_x16o zvLy=z#1uAX7ogK31kx}Sv=?&kChn=PCw;E2U@0)n5{goB*uc^Uq@SgW1M{UMB$h@d z?$evq_B%Tg+$vZbllVYiuY2vX3@1n5&GF!7Hbj0?S5783s7z)VB_(AedsLrMJPMeg#l6FA@{aeG7lH%( z=+2~$h93oo_Tf>S&=Q?}wm{IB$<6QWxoWj2_->D)l_t45m@?LWqmO{ZdArIqI}yQS zfu5Kp8%a)d6rG8&4*5K1FL&@}RX?X6InX(@93EN~cSM9?W1`oC>7l`FTGj=uy58C7 zRODg?PeMfe5_lF`xdDFW24Wjw#2x$@JvLjvAwO-QO2q?=Kh%-*d!>|)R5}=cU+C-d zqC071;_P@iy?4+a(fQZ~yP`}$L@8~u# z4kg|h3r%FSDxbXm{+L=|ExT381TR;}?Pj(=sIw3f!P~)phsgoawEI8B9*56LzV=cM z{t0^u;lfaJ@Ec+69uBgdjvW+E;N&^YE{)e!lF`@J8<l!=)%p17N-|L( zajRPEP{Vnvy3bIb!prG!uZeN4)2n;>u3XAQ+y<>lT|=83O)SV z#Rw}T1jGb_*wgUY-+aCb?Q9Sss7KF`fJMI^fYf3LfqxWIOQXu?4Y`KA{U3lEoex61(CaKqW?QDppv5JyPy*Xfg2K>p zbXaXu%fS{7sKevOqz;ogV3sDMYIr6}T0tt63fgXGoc%6?-5^&eabG&1)iGwZ&PZvr zJ_lQk7~<~qP7rPPN}uys&5S{dyQ6BSwtIDbN2ObDjc6-HV`pjUJ%g14dpompQw6*-u!4rqg&2|P0S3` zmy0WTtG&^6uYogXy^XsUn9#F4}CSIRIQ{TcF2#o90aAo*{*__ z@mZLFoY86RY8k|xu;eU8$gcg|v{PpfX|D@LdheU49Y0{V8LX_?Mwx%{{ZSclPE)QO(FekPN9^DN8f3 zS?(i(DqpvQ4{f5|RiX&ug>OLwF=b4vu{LMm&5bGQSsf5N2U6FY6k`O*YKjs22vVm6 zMIHSp>R1uy$%C&g{3ztj89r~mqqcoCGB%NSY$VWG7OTB_Y%(~IB!UT;Nk=G2iAf>N z-Di*Eq0?$Vs;vWiCID5u#r~2dUeNjEYL%wLVbMh#+$m(_j02NmJ|7NEx=S6`du%i& z4h8Ldq7mwQP^O3lhG|Vlz`zzuuI4sda{)|icJ2$iNGZu#Mo7H}>d1LWeFvhRAUOKZ zDH8c9YUR#ggvvddF>esvk=NNY4hxJ%dUW0_G?UMvuj!uZPefwe8&T2Y)0VNO57oT)bM6~Je^{BH1S zzQLp)vxa9Xk}EB*&IW^Ju`&AT>EiO&`{- z*tfpK3t|+ZDnU;yC2O@SAJZ6!74mtn`ui7u zbW~9EJ3hO!@5lg#gT{qkq>M08&TL2b14GovdPL*pD3l@!(J8~M^tn?goCHFSMBnY z3}(N@7?E3a8k<@U0kE&)@_@wY{+L9c-_Dm-QX2IqH$rD|;>o~T6e z#LBku#BIcNyZBzbLurEy?)dBK-eWWdZ-Y z-6MF@(t_A{o09xCY>t(GpRU0O@G-Jf~R=$6K~ zyQo6dnT3#!RVDP(3N>ZO+bo7c+1tKp_a@@e!XHVclMP(;6V~alq|2pry=7S4K+^z9 zOMwtAa*lUt(y-;kwB%$!1j6RgtiB%I~8lu{e zGPR5;e}z<^qK7rob4Qj{(t z>R3&_62tUdnksh-y2!~SFGNTz{_kwZqD zQcqJ>Ft9+4h85cHkHa|w#v%o(9yTsL;Td)g`wGS5cQl56^f5tFng?Mlx>vR8mv7#` zJDskcYvbC6bj)EFl?xBP``zB)LtN|*E3a^*-ED<9W_RDpj(W4&3F@!4k0FFq{#}M0 zW^%Zn@3wnCfy6~umG%N(E){r|&6)jy4U;ZExd$!vG$>34pR6}OuckDGuf;+1WquZl zEtQ5N{tkyG4>T9nS9O@-z6=cl0Bebh%uw>)EO48V&MGijst=-nXR{NCKy{V9Sy+|{ z>#cX4QG!zWf45C!hIE*rH5dcNc9Vo*;Ly34f7t8`(HgGv<52S8c)Y`ei6&fFU%%WU1fBA)c9>9L12w{yip z`u1Q+>E#5hXfNUJ^k4b^E-u~8TdZ9D=y!m*)vad3i{OL6^sovRjV|7@O#0%*!}{DY z7iJ%r4l78hDlL31+oi8UP{>jFmjUiOS&Sm_v9-H3UrB{XjK5+ejV9X&^gAl&lRiig zCfA(t^Vo(tF&Z-j5l5U0^nnN627eO(d@%ALM8Y5)Kg_ms@B%rJ4=ulM&oWY`HpWY> z+8=W~-%XBjP*Ld+qz%mLHi(L$T9R;O)4P~1kRC_y;Qmk!JlLAr*{gLb%Ai%DfA#uf zbZnU$+H?+at<&@|i+CiFe3R2!mZtvKlY(0FTu~k*s-hd2EA*W)%vR2wz|sbqH{24m z*US4WP!K)v;6WjbSG+i_mfm8qy}}4zP{=l~2uCX0O%sxZFI8IZxOO=x_D31SY3x{q zxO~*u{*tfjYVj=;d|R)6(SsQr>Sgv=hk~wRqz=^cz>gk0aRRNxVq~7H*O{wHdr}Gq ze>@6bHPl;wKx*u|uYlkDb!V&7RK-raN1)b78#R1 zw#!E$CHKZ*_z||L+wE$gfTTMK=-x{~sPISrXTKUZq2huYl^Ff*ZYh#b2Jc8A0=E0m zxb;q#a`3n=9ze*E&1UVTTs~ z4l6gf>tAj^L9&Q~vKyKd`X~E_UIuLoACSMi<2^c?{DpvIo*hqw_u=Q;9*1SAXS?;S zK66X2alS0AM$$A&tasw|shFn?M%hwh zd7y`ApQ%`gAeH~?hwal_(5Kb<2mY}HoC3CoUQmZ zP+B@Ah>Q0W0b}CVsJd)>-^uaEtkCvYr5}msEXm?7HFJtJ(HTN^cSWP{U)>BHOKYyZ4U8r{g^l%#hH@F$Qo09qv@XYZ*NvIV@1s2ch=hGAQ2JFF^$*EedR8JJDdFTtx*AEQp`pLY7&dj{a?jfAm)b`=3&jU+IgK$6FcOlXbCFFQ{_igFZdYv z9Zy%s0EheHcDsyLSlTg=XS*mEDt>T%eUr6lzbG>;oN1thqTS(>ctcLh1(CkFHrg>W zrA`kdeaT}BhHH*V6B~X~ei7;7z(kU+Ng9;)eg0G;fdbZYP3W0@mGAK-1Dhd5|~Wb zQsK~po3)-^*362xFf7(*HgbJ)&ukzI)1TjDfxq$aHY2_Y^fWeb#6zcS3%T-s)f0}a zhv?8|8eK>rda}UE;8CaIm{>gl1YuWaB!sDf zsPUVq_#K5XFXAN>urK5Yzl$}6(4Yb=t_I2H{HFcYY<(1JboldR%zQ^GtKY(00WVC$ zFIT8IfiC>}Oq|y&(EW1!rEKeu(#J@4Z#T7EosTqFGMgU^X)-K&)}@htHORE3Zr#iB zAn+zB)|9DFU53tEccm(02H@2Y@ET=VID6DFS3hGz`n~T;LeoGm54pP58ul~t@%H!0 zvzhGdhxiv|pJd+`$Tc_~?(>T+ekYa&zUex04H|kQ)B~Lo?pDTBKSDiohiQduN$!`l-*EA z;}XLLYMiBU(^cSz=>DVdob=pKr9OfXg5hdR5w(=&$n%>>2X7K!ymLHTQjfeyHECqkFIgm=#hJQ#-ohiEyv9nB3hF}! z(QyN&2^<4Lg;?Dwo^&f=9hzE0mkMk2!8VeF;rf>gUyeK9J9*zw`)IEXz9d?^!dzn6 zaZtm!xU*zi4pmD?rPAe?spwt$ro}zRDT6{99)aOKQzjD=Lmb{#;YqNDvQ5SBrE>kh zHJ(U*(50|PRbvr&mW}csT3H=^{L(~rWItQ+k;ov*!GO7yiFur8krkPX6e=C)K9puOzW9c_dF7kvvsYx+y9 zMB#P~bYT%WcN?j)OivrC2Ds%#^zmTnzuRjseM>H=qd#ACe6r0@^bWC)(tQ=K@Wc`k zzEAs<5$?b^7d6Znh5I2!hJz98ZZn2WADX~$7yWSR6t++4c)Ite43U0t1kn$lbJ02w z(hwa2LIAXuV&nDj5v6_G-Dam(dJ%6M?-O7jc*ZS&)c7wq7VInb2R!47Z(f{@$bDRp zN#J>0nEM49+b|9JYZUVkC#nqdAS=rR^RP#?L$(Kox^cLPs=7%u5pkbL7z(Lez%MGG zu{wox3~!6ah|k6Exo^(`@uwiP;Cm&~<|Z8^8L%yO?*!DziVhnm;*%P&ZtVZ-wt zTLuIk1BC>)trWb+RPtU!4LJ?jHLlARsT&W=R=MwpoFh&-S4n1w*Bb`n@SG=UyKp1eNeiNsU?y0ZD$b`)!3}Y%V7#eL$YbCgR&Rt z?7Qt6P6u>Xn+0U!s+F1zw*3cs0bBk|-=QENx7@(4&0U?=M&s4{n$xNoC;RCu-AZ|k z!q_AFuxM1O17K;TcnXdThvbl0_w2dQ%(zKI7Chg4G9^+LK z3b0C9z$A5xEx0SWQ+o)~RrvetagZ4G0& z@nvV~*X5}AO}aN3NGO1M!E(M_sYbAnd{VQ~GP38oQYTc7$^v`kiI{@0XIDi~K~h6B z)fV7+f6Spj6K6mw7LCn;j6hC`emo+=?ie2{gjR@VqEs@O#%8t|AS#_wrQT$^5hAPA ze7@Xd2J#mckICkAIam*tR;%7ECSqUwgQ?E=Ed)2$=QO44mZ z(oNHCV%iSU?fio=G_1pmQ#5RYlT|frqMH^q>;j|N6$JACOBnxOVn2%OkNICBcaV1n zD&>$zeKGwh_bol=y7G|s^1t+cUB1+Lfneu3zP5Qy|Gs(Kjg&U}OYgalgYac!nD4r5 zI&IpEZ|2-7r6CHvC{YmSRFWi!dQ6fm)0=vPcnP!nF1f~MSL;6{<$ITy`@W;r^PEk@ zNd)m7LZ9e~U4ZWSsPG2_6-4V=2;uqOd=YNL8_YN{sV&FBYoh`a(h@U?cj8Md7g6_7zdhnNDP|*!BK*>caIb+AKGkti|Yf zJ>YXX?=6QbnN8`mI-~3AbU5JhZL~dZ%_biD1#A(2`SQt(EE~j5eO^{Ixar4t*dLK$ z5#iDjQj+5%W1}>b)KnFJ%ge0HEiF!uPL6T0aIiDeGSaowH8s|jS66sAxw$%8+uOX{ zJw0BZUfzEMgr35F_NX6v)+1-*_c_>Za@+NGr_0_#ifP?W&)bXsQU;Lk+Y9PXG!zVE zbkx+iq=c0ClUFdxZK(3JiBp5)^^V^^P~N5mIB+<(4Nn8Jery?Vc~tA!0-1C8h@$DXNRT{Matd zd*q10U)d%YZ`b~wS4{sCJir^!TVIIA zW~J%Ix)OM%k#(mW zV?J%Pg2e`Xx=WL+)DIaYf@b3&T{~zQS{Z$4ILZ-9eLIWrmPHh1(n2g1WSOn)cKb~Q zB>7Dnij76n_S4fJiRIqq)x2rF5MqqPT%m^dwmewT6;M=P@ti0nw(DZ&d&MgPv8;xm z_I}sOJF$%oSZ|qKl+Ix$xibtQDDZBJNa*T2zDew zqxYd5)CMtWM(fwNt3&@{R`legCkhSFnZOOxnau7`lP>Miv*9+GuU@OGSe)li@^a!1 zk%?nA%&W# z3C&j`HO8Sa&LA^pzZ0WUp{7hPn1ekoNLfVN%&ngjP2dgYgExq3$4jZzY$-iPsZRkG z1K{9ufn@p4EA+>T?Q0D?PtzAymboXZX$F_hVVNMru)fiq=@9_oErF1I=P0D_W> zrG_g>@Y5nrv9sQ(>{4wGU*D!2$%j_YF9ld9bsTyfz%D`*n)nsqGZI+Vf3V;tMoc2a+9G|3x^*xlq*x! zDPbw=8`;GPNc}4ON3O$SJc&ZiQe+d7m^xY-sDin?@~k~MCrhr>f~{e9 z{5;5~X+s6EzS}Vzj{=$>=k|)f3r9s;tsbXhTl-4j^zLP%9oA&p8Tj_-RP3*&-W2;_ z>+$H7F`QPksYqYytDR+R)Lt$txsGqbPbsz?u2x$D3K}EEeOlJrv>7uXn?uFa0^W7o zns->eHkS^izxbBiV?JHRkgiHpmtd*Mw55?TX^QU@945frnm zGo?b(a#UQ*0TZ5FXC(Q8sz!IVS(dI(=#l!gLFb_ZU;C)6_N|>!xN;)7L5} zi(t)o)uJY%D#ohcG~AleRSWA{I!9I2)>WKUj5j??Yr)=Mo&!dNZ^C#<^nQ9^c}Ni8 z-wcu4UEI(+KWne-MUo$G zBwV`BUt@<4`hs;;N!Rhp1$*v)ywc?sIl3G%DOQofoZG#(aT%nt=+=oUK`2D`am9^y zWr~}{h-*4tG(pv1^blqI!DuEkv?tS>Bs2JCf+#b|I>F`CtIe!7!R8bgE$=2W@WMXA z1ZqZglRA{s#jqenT2#T_b!PKj+7PzqBTEprrZqcqL` zZ=XA0pen;`-n{FBx8k9oMFMx$kN8F#eo2L{q5kMywd_K(xaUG;-bvUifP5+=USyYzNSi;&hq=f;#6Pi#!O3;(I2kWa0wB&N?b_qu3kCf*ruoj z;e-$Vh4uBWr%7yheA(7A=kFWJ5f8g_9vtAPA0mV?fJtTxkA4fKdJBh-0$eA6*^Cni z0RgSnM+Tep@oIN>XQ*}uM@PlT%+yd@U*}}+czdZaIt z?lj!+YbFbb8 zqAkO#H%_ludNK`D;&SBK?Ay0t!&1&V7j&+7y;R# z9pQj=?Y)g_j}w|*Y=L6Q*-GDg>ezCuRnReQg4p1o^In`%85Ck?E-cN?@KYZr*&-@Jn5#p*rDM5MRJr|I@?gw>sSnJP4A76kx_s3^ak||6Pz8K9& zvMvTq%aDeEVo*|%mwa$~2ZMFPBD=n&dSF-IQEQ*NwDxA&ceL!vT@JkSg^ByX%fGVb+;Vju zMY^vnU4__f;e&d;x?_>vf95_>bzez)pSL`X=3Yhi1l3bUGRdcOsxwPVRwfmrsE#Tk zSecfEyVTDkh)3YP#lI0_+WSk;pBbvJlL^u9D^{kuZh%2=mpJdxlnwHS?qB8?q3rR7 zZ=kPgN+0#7>(h!UF`2MLL*ht`mh&)UCgAtAmnW=4)BlsQM9@u5O=r3`YpPG)3H!nM zB`-?=r-p_OCAW%Th_G#Zn-C7?CtG~V9A{%gc28Mpne^bY1`0f8O!0q^e~c5jLbQ{J zQLB9h(m2P4Vk}|{)lQTIk@gHum8Xdjp2JE#BXTJJv4hR%kd7%uxTLnv8$q?4C!tZt zVMbd79SG4z?!#$1yGIg}@Wha!elakIXkC+%-uf3>gowB>H%(Yey zx9`}dYMa8d@9Ux5JmPc{(Md))Vs;b#wzt(sFH7LE;#f-KY*Gze=&)XzZfZZ*?!dLM zqEFqoMbbL9UNUfcfK#>K-B7lQ6F(oZw~uOCp(l1*jUrt)YynoeiFcrG9AB&xt=%KK zVRq1L++V2bg7n>5yk-CwISvfVM^+d39hq{E@!7|4ZHudpT8BJ5(+nrtU1EW!4a-v} z&XWs<(N;|l^$mU{(Qjv59#c2>+`rvs^4sCQA>6b*q=HaCTuDL0ZuS8Xko4r^JNVcW0%R(oQC+blJo08>-?9JJ038B|V z`%o)~CUzIn9HR<;;Jwny9JMNs=Bp0TAkc@)pW01V5ea0Bzwcl#aJPaiwzT{8dHemGjApz z_4*P9kMPaPTkf)O7`X4hJ=dS=RAm|TMf-!o=$G73IwxVOW(N+(j;q$K0dF{cr|~_m zJ5ufz&6_?;`(R?4u~c`GRNMT=g5HN|7VUl+=p*>3zG(`nad*{Sq;#^0%bPsum0ctU&WJ=??Dk>+-Ok8#yDCwU#_D@^NfZ1M^yPNZ~#eRV(o-bDYz%l4c`Af9luBV@W0!0{x(#~u;EsE-fS-XkW2q7*@nPzX@8 z4raEF=4=+^qW&FDty~D*^j8>wGXvK(3*$43^gbI#&RPi7VL&z2E82?nxb4sxs&`fK zw@A9~F4-4I;x+CMq;fLxuS}ZTm*JA0T14Csf1HDKE|6Qa;FgY^hicd4I1<|^%DguR z=*rJ0-k||>re_-N@c{DEOK^9JUD|f@nRljL;+G2)_ZH{C!#fWjLB09Zdlw%i5YX+; z=Usq*QT~qQUAt$-?%qqD_pmJW;QlV6)3Ii%;t{8l?`N24IVUeL(V--<1ZtEaLje{ny6ECi&4W>Oz>Fv(W8kiU!7jC3WMQAESrbj0rXm ze}u8><`Y>E`Jjp!@b19A98W%!LFyGhoMT+%CC*6QA;`BJyvZ#T>4i;@j^o~qJAWBl zoK&&ivyVN_a6GAUX}irawTtRCWPeEXTme7t1dLr0$1G2u)@AnD#>uB_G_)Z9?zhEX zURG9T!=sCt!u;wP>3j|$!r<=j93h9nn4!~1ewb8I@Ub$nzeuD>D@aqtFQPh8U1r@I znYbC-h412yqG#6%AH_P}to;c6x_f5*#=-x<6JW9w0-C6%VX+~MVY!(16s`t{gbmI< z`&i9bG&y7UTC)cu)9=G)0gNo4De?0iZ=m;dQ67cMseWEqp1eZQPa4efT%vZW*@426 zeL`sY(qSg%(#}K5#n495=0De!*rQ7R8qJ)U*}0tRSUX*SCG#N4n%wjw>-t+XN;FAL1*Dh3blKnDKA&ha(R4cMCL9LAXrTj2K$xj-PXFfM3Ocw2poCE=j{g zx)g^CPCc>2`0}%TxE2W70YkzSf7j9zX$M$UHRc{zZG;njIxHb}c(H$!<^`$#80s*K zfe8Af%OY=+zB4x0fqU9wY`NlI0UGoA>}ik(0Ur8%>JS(KqWVlvSm{1^-e0{@ykWg@ zyrI1@{Bj|4&EBA{M2GYWz|2puPt;F1Pu!=VJTUna#uNJ!;uAe@H%#~R6U@Ggw#1jzCfUAL_6v{`>k+ z>OWNd7xZa1Tl~-S_Oh;1gUv}K1Ylji@dRdEp~KpW9?Xf#nxm&8g_^Tr)C!959FwId6F0}%heXuVXc5YrM5WENZyl}lR;Yj#PT0`lW zlI2KgVGm3B-&ExoGVG{i<1?MfV1#mPvKO^z5 zIO6*dd(Zo&d@e*cE8o@wSK%fHIgT6XI%on<&!s(OFFRy!|M)~0q;5a**RSUSm3LIA z3!}zHZ>x^}2h%H;PZ`hDNpMO}SX#yXSB)YyCOheJztja|#+8TK+F9ACE&S{Q+{JpF zt}zfs*N~hb+=`PID0E=jC79tl=hWA)s7ts@3Jo~!IJf75*Y?c@A1|q=^xvL=>_o>`O*h!f;gNW27SJkMhqD~FQD=){F zx+@WR;$)E!tqZ_+CuG57PL`Z^WYWesmM)UlBmOjes?`e{c!SWeX=mbttw1A~m^vBG z&e$}dnu{L(;@i=k^AVjQO^q7&86?ZS6U%~MG0mZ18M(+6R!DoCmV=7NE`6{v>yK=& z<f_7fwnM^YG@;%Q{l($34y;!qkpb;OGs91RG&uqjKRi!l= zykPG9j9jpd8u5O|cilY$d{;9qG036_!f|tjUhC27!gW8BcveMg0$-gO>v46A;%U&r zjB*rFr8gR9SEeG=E3l7F-Y}HflK0g44Rou;xRka!tq)!>*p47{Aak5#&^yt!OjWrB zcdTvfUPSMhJF>E65KM+`;&$#Jxdy#ly$po+&vMm`8)2!MasF3t#Z(kvGbVKj;=YV{!=}2j`x3(@AG~0yba#*#P2*Ytu$MXx+45GJK zCR|lS$)R|7Tb{#S^S%wtE!JHFAI5I3o?PrLRJDia#2+so8T81LO;TSbDux`YLE+gJhHRXzIeBZSaKj zT*43qZkk{Z@XKIRtu;IUbiD;;wpy@8{>J2NZ{bjtzb7snX%((EvmNTj+A6%e2@I~^0h_e0RV@1V*cH1LMJ(RSMB^?S2Nuony4-3J*zaMksAkPmg>4~WJw(JH#f z{8PKgb&w++qglI|J{GLvz8k&N_b$(VV$6^^?px#0dkwXenc^k5>KvjGvE#8mPn--m z`(`6_`lthHFgf|Nb1&`;Y*epOa%dKKrz#-tL<<=GRV8%E&N;NL3KJ8tgGhB|f^cKssUw;|bs3s{@Kye& zo%6D|GkC^U|1?F997|sRcx|e;nS=WLbOEkhuvybt{Gc$rY!j)K-z^gO;Ik0KsG%by z>0GV65s;&?T}@-zdxHplcvXtBR|-c=UMSP~Fcx+Fds@#1v~B&{;4lw9F!{KMr#)f} z8hdg_%aF;=dxd%b2vE92QcT1r{S&C6-t0HDi>`*tz35%`s@7>BHuL8sxx*&yGdfv* ztjuGq%{!AhqC$$g0@}u*&zj}uze~4iqs#_5=13bWv^7^|+m4EMZMKN2h6hcz^A~Wg zm+mBke+f%S!YGhYMYBXKmFg6sOK`5^fao$)e1HdY=4z9ysLP8B`%+J~7yop$%?z?v z2Y0mNl6dFBJ1D^`m*V6iHLMM+qUhU?tNa$@R`yCq7#HQei;4bYRfdto@T&qU%MUN$ zfJA(=nM@EZmsd`Jp9(9J6!~vf*ZdqGSC8LGJ47Te>!ms%jOuA^w~Rc zlgb3glaEt6K^MyAFqQmMSL(yW-@BF#<)KK2Rhl@KVKXU7r=F9I#x9Am1DG=ov!+{V zP8hKm((r`WMc)3<{%7(q-Ztgi6>bm7v0^ubIk7%|JK*lG_M>x%XTT#iR^p1uOR_#T zu!wU&64*E^7$VpH-8qvIKrY4rw&w;@|5gxjkW&*v@KWmM6z*q>=oA|V7Y!Y^t<~N7u|SYx$~Kb*o)7x8V{p z)s$N*{r5ysM@%mD6vwh%wMAj+ygf4HVo{j&zLub{c=*0mN&ZB#GzX~U3hK6R&sjJ% zz7OX!N#>g~gI_p&$&!2#(qk0VJCVjXqVXAY^r@=BF0{KtD7>%gHmU8NbAz9Cz;}BH zlH>GJq{y~W%4|5dbbCmW<66r{G~-z~woYx&I#+FJ0Gyb_z06Nr;LQAahj|~de=o|# z%Fn%LA-#|Etpk_qo%bBOfe(=0dxhT1_%(`p?o!|F-fh4XVS~g$-=&3k2e2``hqluZ zEv98gY8j1%Q$&d|9Ur_$*5LBbl-ZQuGd=%$u?x>RnPZLpWu%V!$Q5jB79#o+K>0F# z`qfSL$90&cz1w3zGm*3ZXT;+e^>9uHE>tuW4bp1kE@)^0eCo}(QUtQvZe0Ng9LZIXJMe*N!yp% zl0nFS`@zKuvjJbg7$)aPQ2HrT6|`Bi$(rw(Y>r(Wz0l2)M+KRi=Lw>-0*j#nwHm#B3EHz9u?)_2!lG%ShI@xB!(erwZ7Q0lpDv~Z~cX;+! z@m#jDfSfMhAd#kcug@mn7%X?9IS{U5PAQcuHRT~AiA&$1U^7Z2W?{*sE~u0iiTK|#z)wzx{KETrMP@(0{VO}+h_pE* zxN!W`hhX>3iRL_x)oB1wp8Jx@Pf>tgpwLD{(OzBjT$_><+oG6h)P7T`DcL;YSQ@)o zW^ovU(jyir>xEaQ*v(ipaco z!q_h+h85ls#bj!n)(g|R~=O*_bwq7hS5S&O2lZbG+N zKjqnJ5IE^RiJ^7FzLvpr_USFyF`+1n1f5Vakv)MJb$TSBsgJ-lck2K~z$KLQ= zNp6z+Pzanb{`3!BP0n$$DPGHV7XW%D$bBA_?*Q+le%Se1eQd|RrS_=44);7AZDWAb z8LT=H4Jp4*U--6md?w-G4ke%=IMGH{R(e|WuYvD2wDM~LZwqsw6A4K+GU{nSkO;?K ze5udP=n?=5?I=bFHd{%i&f^E!6m9WD`hL>sA6V)}akAw0f(U9g6(yUl5KX{u@vd83 z^Q%g+j7pBVo#U#;lLXgQ7ik#$sk5SSu8q5sG`^QcVg7e+!#F|lP%OtoWU+ORD5ghj zv-KDF22Fz)t}2%4fDp8$7}zp)HI5p3d`W7=9-`Z;deJ6kPgW$&=4KW{5Ag1`&s&iu z(+7C5QDL_$g_AmuazoI3IR;f5>0nYH2&U6534j$*8vNs&+s) zA(@lh@!9_KWDp&;(}w)PXs}-;_q|b$nvvCnzn7@YKl+vo6o$OJ*ze>pEo3)M9iuUt zp5%Y0)oiR4Qp#0z5dZj7eW4<_R5dMSRb^_l-RbM>4)wI~Mts)4r#A+#U57e0t3tB_ zGb8ao4$;5}x^dS1ZXKkjq;}o@AigO7%5eq*R#D#Z9mO=%irwJ>-ag$9wn0 zQ>&djbkzVU96BMj3JqqOZ5tE)Y{>{W2f#1WgY-v-;dPEUD% zZkpgQ^A7M8sUdq*#b+#LY~+u~fyI6H<-e(6asCc7dYX^dW#TD;`8Migh zYM#yuh{sFG9RnvPT_{H{yN0YGKP(nF<-+YiEtk@vL$`n2apr^_2}@>*>MW*FVrEL2 z_~@acZ(+)a)bKo4^NEx9+;M$;5}|Jz&wcmAPn;L;409=Jr@y_z{~xIAkwtg z18>)Qh*OJkDiQ1OM-r;u)#$i@B%ZkLTo+1r9-35Llt>qarGZ+<;C<7LX! zjpAkE^^%{~jq+JLLL}pfkgfe5RpqV63_lYfd5s(S0`K@U(7K;UYj#+7y$;e%TMRE1 zd6<5n4%gvK5U&Gym|(yG+d*3p@9|TyWxxT+!CD-T2YFa_zyZ}^T?9|<=P+Qv0m@-r z7;o+W-Ro96gkR}^Y^D7VN3Cv1r_ur6YJCvLtaiwy(gE5^dl<*cv_5Z2KDEBYJmyCQ z9$~wi9mZe!DNblbn->L@MP>~A5#d~JpB^SEgwSs|Lf_Ei zdo1=Cgg=<~7{orx<9dunK$JI_#D1c>3M6}WSkICF>G$(I$s-`n8xH^fT$#zET$oLp z&4wS;^rs&2@o+|D0IfbA;i^DBlBC28{)@^4e10Y6j{<%#GJY>Y;=JR0tjk{!Om%$>14% z9419iov-#y=sJ+ZLHUWUI%sX=}FnsBpC9)pIss6cW{5QLsZWnD0^+fyO zK0`l~Kg;dC%5_V2lRj5Z;7;%`*)iG~ZKiwR-a_A!-_lRKPPO%ZE}!n!*5s6V6wU>j zB%7iw6D`fk@ylF`SN$z!425RN`&$6Ms@x)VxK+e)BrbWo=bfZM0xP``2 zv@8Sg1_#T;UfGrS2b|+k!`|aRp)aqghD-6pb#*;F&W&F6d->F7e4fFpE=s$rU$8Mx z-pfn#%iAknWMwB`PrOVNUdcQet-zm=gijD^_8vdZN&RTKqBw%SJU!y<7v&J@0_*s~ zxoP}$gjQRmeJ{Qz>J9U7Vr1$qf!+4%;`!A!8I15rVNAlf052=dRETM-qf|&S(l1se z@;zraw1~BSW3pB-{29AGR6QXSExzjP=+I9(NnbjgDH&~lXu`JbM%o7>Iy7Tybr_wM zzAf$45vl4`_xB!FAxJ_m^DD0$4K`63X=5EWGO7utJKr7uoGZj4E|&e#NG)^J7zJ5f z<&tv)_y(vFgwoc$Ni2M`MjBo*WMIUBuXob+5Vf9QPQx@03uWmi7v5?pwPD(Gf}2~s zYYPX|qHa@Q#Iz@W{JH63$JYti>9_d6B7k8fOgOJ`s`0<0euTGzEELcrSq zS3p@!lHVksXsKP~@iD03t>)dUybYudZ{EATg?f`5Rx|Q*qw3bu6yJngnxz>`r7ok8 zPx$uxcg}n=$5FoAJKsw(^Q{Mvr~w3ZDQRGJ`~mO;Zhr0RlyfK~6Hl%Uu&I6Mtin52 zf6-Ho@hT|3i!`?}$d<^Iz8@Vf?11}-?Q5X`mmb?Vqh-|vGhaRsd1Jh^o}q*bvOuabewS5o!=tn%p7~2Kc*iUMyfneT zC6W8X6c{4|g6yKbtPH*_8muKxNqh^&yNN*xIs3I~ce)+1QVmeiP;wl$^2O1_c{0HwYhk_C zB*DxQJD;-NxT5|y7Y zc8WbidePseKiTiHMTZ!y^xUQV18}ZlU5z$=bs3_Td-as0ox_o&+pSf++P46DjV3`E zyFwW48J@oEYOzbgqPa9Zn@l6%7hs6$#QJ-CG=u=iM^;uxUB0B^UV-LzfLW^O2#-nRbp~)|WsSt9!wmV84b!8>~5hXthQNhPr zo2~HB@}dt#dK`qMQJ_KHV;xVyW% z`@w>{I~?5M=f3y5Rex1i@9gaCOxM)xRPR*x^Aws$uKUHr6BAmQ0va^ifAg=pEQDJa zPEOc(H)-OUwQERFKn`2MFSG62&Nt0bE_0tjV$$UE$(j`?96#C}D`|cAN#u&Nnt(50 zPa18Mvnr}^k&H|cJEkRgC5UHDc!XA{^*awF=jP7%3*P zO9g99Q59)4WF_LLez;v19*@Ni?67Y%Mp62H4L54S)ldRKEOsn0{&NNduoTgbch8d`8vQ&ghTG&G~()ac#^ z7Br{iL;jFNk$Yr ze+$gCRQ1%3)o80?_b8&QwaH~UstH55pqrO1fBQJ*hd3h zKi16%&9Ee=_}OWs)S)})O^9+*y1;wls!#4l_$@PvsgXh@>RT&+q!rIIDn(|ULYzF` ziEL$W>=GJT@!6ALCepiPVU~F2ojdFB92OZm8ZBNj%oko!}_(uGZI0c8^Tr zP|JX%HebYl>8~*R(}H-Q*v8DE4I!|@Cx+*NTCS?b6ciCCkht0IW7O*p4?%bumfAB?0*Cx5; z1*E`#m0{sjhm6J_XL=A>>+<#V_^PYCbMOJ-#nGjWL?p&Bo+Q_AM!JXF5e0aU(esd5}_?<`H~&@_P)CA7JDpR%Bo2qjVGsT>lsXs zXbi_%3)g4lm9n&?{R~0Yllyl80X6KgiV^$j_ISGN?1uxNEAO>`l{ax!1FlXany;H* zsn-8of?xzxlgSKp6J?Z&1oFhXTt8~K3K8_kElr3q&)Nn$*~o<=JQ&YKgN=F~_f@3Yoenl2OI-0QQ$s&4UN4(Dkibb?Ks)q*jTlqZe0Dt~{>#Y@(+yajgk; zYTCB~)=_ZJh`k0k>6os#mc4fZfc5Y@=R3Xv^zVyup6p$sUR8^Krtbc90)${L{Te^y zG#)PlxISzmgr!KWf}448)^bq_$RQ;xhV!N25$vfNPyB?Izc8ltzxTR~gN>+BPrx~s__Ow_9*e{X}t;?Nne&5g) z=xC?!XxH&-c5`)ibCm^OXl<=?^tO-pw_9xsaA+o`PQA1cS9r47njo1knr;l^Yz%+u zw;YM|9~UGrqAO5i4fsRnIIm~cLpGk!k55rKr(Ct+V*++|ws4`o2<*o=DJ|NDI~P#B z8>nz?n3NZcDJ^`4J2w3vpnkA@bKuLy7o1mGjn-Ae{R@cn6+}v3rnNO)J4e@^iB5p& z1%TP{GAP{>w_{hmf4Y+}hCe3HY%$*qEyqk7JYJ8FvKkNq6z{(nW|}fxAa?)Cc!|?- zV{LjKN4Ryjfl&QG>DI~Bf7%JFcd5pIXDv=f613Y68-2;h-Nm>4coDGMj_E6a)_=Q> zI`^QK($(C1+lgIt31s%R4L6k#RwN%V|6?y5_}%gQX{-*6x*NXE zHjiDfSv~3~DPBL)XG5HhZFg`8lPMs++yG5KgC~~9Kz(QZL@Q+=iaG3tIV{}(3~`*xzuCWM0g91$Rp0WtrM4rib$) z6v&S|^~0=>CoAGGhs}^U8@o{qC`I#LtJEZMzJiOS`I4zvEC7YuO2VXrnU6RF(@vnT zbFQfV&qTdnQLm?rlFg8osb_B5!5uMSA3|PNy+>CsU@=$PfSD<{cMUnvod)?}kU1sY zkeMmu|979Bq$jsGmp!X%vT@d*|9B;xMZ$g$ih0u^$UnXV^ zI?x@XoTk^fNwT7}A!NfHqw|K&fK5Kn^}>JBi@5WK;}%ryH^(2g@x5kEH$aa)WwcBjX(0Rk&kz83ElNIpc?|58VJZ9B<*A({d!CP@u z`pDUy(bb;ZHpT-h?Vf`JJl~OyN?e$o6VXVxR#wiOdGN)Q83yl-X<--pO(C;BbJylhq z>bhvjZN%Lo&R71AezH9g3Zk#swfqykg;k-_nZaVZF=j1t{P0o!LYcweb0c=2X6|C2`Mg41pB#YLw@CvAAIBQ5@y-zi+`;~lN^S%*Wt;Z>p7 znZelJIOXmW1Km>&5i8)!x%-9tk3s1Saj%MU&lLO9Z%qQ^CS0s&B0DW!Ol(iwd?U;K zR16+)ioSh?7N|lvfzEnP5GdZ z%ZTekNJLArzyy9K^}XH9ZTtkWo2u!5Ru-o}7duC~P1q$P(iHR@6&ShsO3|O?a|I*@ z1gNj&s||fK`bhDPo+0^_9Bq{7ReaQHKErI;Ma{raqy4O5HKOLfN-@PH{ z&}dV%SuJt5HR!RbSEV&k^kd&rEd*udxI{Ya@cKlRf{XlzQhCJ=SF{oHJ-kEZR<{om zgFJn?Hr<$|mL-evOJ=;hj)IUrNxxT*@HaCS#;;xxhzzkB)ulsZ9~L}I2(7|E40h{$ zB?n(8H>S!}P={BeUlZDL=8B#*?()K|=dA4VIu(TFYO)BV8HD9s4U~%i;k-rt767i>fO_O+1B*} zQ%j77rZwbeQ-RO^m!<-z@}^*`#MlIfz9l6@PEP7wbAEpAO6ofuNHn5trw&=KGOT79 z1j&JB2zMQyi@r;-xM6?rOKxWwcs0o9?NZT}er?EYvuW~?i+RUhJfCQ|YPT*Qn@l0S&)bk7# zu&FMBXrO4^lXucbx2{e0sGP-Of%!Pc4KBt37psAbYq#Wq zTk?pH%J7l>a!YZ$!nrHLxkG^>`@PweenPS^z9&$=Cvd(eknW$7_Pbg+;(oNiigwt@0sbJaRtHyzG z+q1?2i@@P->hPV4{O_!3-K+`z(p!0xET!jSHhH=?wp6pk_vMLtsSlk4oSk zj+ida{Az|HE4pW1oDL^^t<{hP5H!=IU$V>p4$J+2!-8i=w+hkSXwrZQGiRmdE+}pm z3@iL_z$(%7(_ZOMBgN(FyUjF<=Zuo_CuPlVG|g|M8d@QNdcmArIg{nn2XGDU*eh#( zoYf-fH|CE2V+eSb|9{Nkj)6Pul}?{t;n!M4*89Xf2SPFdVVM9(dMp1K0~B#x%x!mf zYDVl}N77596PCjDOJszi(M3>7^GgK5)0}^nQIy)?3Y>@p>!-{ZvTs=RN4$DL3_WtV zewmC=e7XoOX?~d?c)s(`GKxzZ+?f;6l7-OHu~yBTPt9C?uiRo_rW^!cCaMcB^qCXy z(lPRX4_s>IP;2J?SIgDRT^SUc`K8H0GiAal@uCzo016tQ|4(B^IuRTlvD?j9Y~@M! zigEcxWFa!PLFzb>o?-)`a5E7Yd2w}|SXz!S>}Hl{0?ccHk$=U;t;z5#nDCB?m}do< zXL$??*m{4x^!zdlh`aZX13{8yB8v0EM>e2EI-%kn)Bo2f)u6!JpujQDRpPSAQCMm? zFi{SICKFYO7rMX+>X(HOo(k2`oKCL%r3u4R?Ya7rh9@prQdIoFfo8xfISdrSn&IFZ z>fGZMa+sMuAofgc4SJ}Vkn)OnR4_VJIng17o4n}yo7w%5c}l*3TM*ns;*oM+TotPS z#~H5aW8SOtxz?Nz$v}$F<{s<5nM`=W~+<99%~~Fg~fQEof|9$|u*zHwqUg-5JY*06;18<4+VY zi@)TLqR=;T7S09v61-*h(-3XQ;B|hwID%KNpd2*!*tj`+3SDbngqQ5UV1{aON8wQ^ z9a(h$DZVoo+u)Vhj1JXh096OXa?jyqjc7usFfb%$>}lUXKCWLGN`0LT-dz_Y^o%4X z$ovrJJ94>faHgzv()hdjff$d)&CAXDe1wa9!b^lUO=!;wN*=lk-mLob%%tM5KQraHUPiC^55GSdMN_hwNoKG zV?MtACU~(Aym0f;JcdX0=+3nn5mql!#9M^ExhQIj5Y?;fGhZpff3b^gcAj+ROlRDI z;Ly5wOT0|7&%{R2EvzeT^%Hf5sDrAxw*GsrkNC?TS`)h?bP6JO+ZD2- zcZ^j@BCuG{p(QayvG|(4BXC$*9icVAXEfK5rmL-+*?SB5SduWSyea+Nx5Pnc^%lAs zn#svKQYuG9{gau%r+Tk8V1dYwOYqxFmeEL?ldwQzEHixz9F&~x?Q{*aZlr|MtSeoJH`={5R{Jr1p38HY*Lto8D+(|xD@ib2o#Wdh!6)hzVF zbnO^idY$W#7}@P-t-reh2aI$A2U}1huJ9@bI5fft-J-?MdN`K+PivrKdhfLZ&zm7v zZG+Ca0?)a|z!gi*WM^%6OV0I6&Zo7frnRRBHK&~YA*05NzyOql;kH#6Lduw^W<)~U z&%+6N&J7Ri4o&M0o+V~?`cByz!|Nr_bc6oA+GoxgaTegezOn^|CB^joO=ZvdSv>~J zYN3TLwU&kV?6Px9i*~gY#=fF7V?AGMd;k-MQSJIO7R9ky$hkKL0CUrbEjYD7Bk;UI zoGl%tiAS5I&ehzvDib!I6>Y5mWP0i-IC4ljD%-U5_ed~lTzBE{x96b9^OqYFsKX1S zU;55FNe?*k6Q;bWs!8kxvl`?QP*Wh<%=us4n65R*vS-_O^WHxo4Ka)fczC?b?Jb;zZaj+;Hwlbf_v#QS=Mzuxp=Ox5o<$y9(S=hDEv ziOoySE`h*Wx*+B>-D)==^QF@0DY^8yA=wgHxD~k-5THn79lS2jzd8zx=L05Hy3|rf zxdQ9)H~bdTk%&4a^S*W5WcUU3SwT7Q_qUF~?P6A#2L>_ZIl?Y-Nw$p5oF{@!%Q-u~ zQ`;t{>;UgQ?q_?@&7xUankyK7Ts}E{iCLkes8(ekEF}`Ke2}6SU~P}BokOKV$lwCW z)1{>HtOI$5Ihx#tsyKk?vv#mTD>__NLH&%Y;T^j6>8X4k!mB}V14CNvjmwo9oP>~gM z;jg_>$Q|+-DBS1kMYULM#HV?9h3lma;n^7PJ`Q358zxmcN=&I}eF4-{pCxXVg&5wftYw7Wh^yRqJ)W5E( zjYfh|pnMfBW@YQ5iPG))H3L(E_v($yM9KYI7Vj@KL`Gev7S;GoR%z#HdCjJ+mH1Lt zX|riNm82HfPengDDU7H?uwq&)NOm!(e(nr(IAsWB#D-!PA0wJA;{e@4IQc)f$3hf& zo+&waGr(u`^IoRAque0B8TS;v>2e>v_7dl!Vz417a*h)gdqNnXJgPe z2-CxE2hJ-4I|J-b_1ME82qq_S3rFLhgpvD%x}ap9f&sDkyHna_Ax_Nt@t`tGKpZS} z6TK`Jz1RKIPk$a)@&%q$%f9WGc5~jT=e)Ca=!agNvii8URm(o?A9wL=y8Xz;f1EW= zDk_~#R85Pw?cQ1C!b+zYEF#GsG~52+MVuX4ekJCGZj<2Cyi@*2s}o+mdukW=+>X9E z{IDJVVfy0`|Iu^EQeOF-rd)vHV=nxoH20OBM#y`=xa5_dR!HpR((9GDI~3_`v+@-I#r zZd&RfCyCuo$}}gQT|qLfg^Xt5S2)e=0J;U~pWg_ivS+c#d<9_y@ub1*aU!e*v6SM! zLeOW=PQINsZWKhVn8O0+I5G8pMdQZr2DiAFhu&EfyJ%IrSR`XNNO-nI|FKdC`lpzzGw(&5|oJ}QvUrng#9<{Z*&Qq(KxY?(~@YdAHz-)A;$%BTDewH z84DKa(cJN5(R;k*jtilDN&^6zlXyl=&1C1+)gjrkR?}$Ga`;q#0ee+ zCS6HG`HUKQ&)}Blr6k_!ZZZt9hTSR)F)T2>)eTHeVq9JkN3h62wT((WcaGs%zWt)& zU~=mY*}Disu22ZK-XE&r35hUy*Cbkv6HKb+U;{(ur#2-q!K>(vS8 zdXCS)VznlqRUOcHz5W*BNuPw|`yUhmws)d!4rc}dhhns5HTFr{NyZmr69+Sf0v+zx zyJYqODfJ_j!&Z@WNM*IN)|qwUyACd|J;Kz!vXl1k`3BBKtksi?GFq40Y|*x__N-Vu zlTTGD#p^j1<@f7*#4+x@>4Nvb9#m{5<=Q#jE!sO?^57TnH#%+0r9)S0g( zedHrbJIJ_gTKRJQrj>k75ik7P6t*w_9{LcmwlPfToQon<%x6soGEgLJoV%$y&j8s^ zKf1tUxhqB}^ST0q_bXbK;eZDx4%`<3H)@f1A`_59t<<{sEDD*qNuwcFyM53&*& z#klH4khF@$g7HKE!(!WdV3y07fc_(mfrMn-A-P$*O5}kBVqpM#D7XYTiJit^M$6)#?%gu=mQDxz~Z0D^6WrqI~1Ea3D58K(1Ihl_yLL~$Z=0jjSY-3{)nP`i2_S*K(x%>8axNV7G)sTcJn9WX4IdslO zBQV_#{-XZ_OrAAd?nX$$>B?nk(@%Jh zT4Bn^vz>EN2&z5(r@!CHE?p)?JWbR#RL+|6T~6K3Z=;w7}uE$R%vIXhIwK5Ryg zAms)=D!2i z8rW9GqSjR@%hsY?P5q2ZNbpUcF;Ec0&WN~yP6$mR~+{#wmaTl z0oCBZGO-9##ZRCtlX*+D2 zqv?tB2J8RpDw69;P_S2>G!GkH)()_23|sM|@0SK5)i#AliH-&Nj?je|sz&C|cxnue zpHuAd%m_nB0j6S=d3UQb*W-$0lf+f5X6xJ>;nxZdj1h9HCWznajyB5+aZGb z@wpL)x2QiYM7ZxKUP633>RVXCIxWZW4ETn}X5fq=nWI_pwzjJ3^i}6=QJP0H+n4J3nM_IGdb+i- zZBdl>u8P`a@lE@9{*DlVP*JwlcDKxdFFrW=dG!tR19X&qL-Lp%sL(`)U}Y9?+$+^i zv2?_L=w<8*Q{7j>ybWZOaWZo^(>60Z{CUW7NNBY*0?GhAgWA4)Xs!;S5AmVBxs%Z3 ziO=QVv+kc31Guo+v)|GfmFXf~B(H zt|7@~?gy{9*%8Kij^}NV-VFTnSa_;H^au;j_u{?Vj3h_LAB-TAR@TM6=e0y_M~MrN zw>xvp-W7k6*^P)E$jY7Va_`M6Nd5}8YsmExy?Y1kRab!@k!gmaiaeciwXXo%I1Mp54VO6${l*NF&kQ-o3?ESg zby@@4ZU-@J2bXLI{Q!ok219OcL2x~OLqPxY17i+-Vi1ach_zyXpkkQPdJy$&NRVg% zooJXQV-Qwnh+}O4ur^G_KZx|1v*k5_>ov^uDu(O9@<%b!IE@uyEZ2)RPpK@&vMgWR zGS}rKPmdtSkRV?&E!SNuPjw{+xRNi*o9oz?r|pqr=8-S|{GG~uME-lYQe^z?B5Nvr zGIouT+7PWKO1YVAMUr!k&B8F;G6JEQvh{*5@zL2z7)3~*U31f6>55sbr><$d0dkPn zFMk*}Dl8~}B=RkXR_eEl!SUisE$!j^;|jKMjhc`X`=~zm;@Aa=r-uF2f84SciAMEO z4?w5oYv62@q zMOI&Y${o^C!9GlZnj%vEJD7dZ1HoPY#+CDLtpQ4-_%_BRbMEdRZ^!ZZ=&5yWM6seL zP127=ehox-`MrXlpgm%E9a32v_;C%9$U4mdwnasTYLENVX6Uq-o%Eiwk4*kj? z2M5Xe}X1pxT zI<`1eLh0BuoWEGS#mTQeaXP0_y7CT~s<#Q{kGphD9CLBZud#mYRow|Z*GO!Xo&l~}yOy1v$8)7kpoK)1}y>+7BqQSrqX z54rzCvP$~ON_1^~p$97&(Pp*9x~&*19ygW$EzQHsX*P+;VOVZC_77rxIR_Teupi*e z$k3+lqa!*E>H3&9H8qrW&%c#=bRQ(WM}e~Ui_s2?ZbW8*QF>s{GAv^hc0r*gI9DON zKRvqPW;LSWm6V~pare5&QL@TqBu*wX)hb>GFu28fBNxoiyhzbXV23PGYUTjTcMuZ2 zO}!Ay`(iCM5VSl`@P)G`m;yQYnMnJ`%Vtcsx1k#Ro2=;n>!sOdr-^)`YGGt%Eosj( zDq|G;Od)KK5$7O_Tpe0%+Vmt0brPwgFJ0g20Pv(4H}-OQ6sitxXLE$8qqoQd^H7x+ zud~g~H32I>{RGqhe1#3bDyMI?z#|(iFYiKl_%kh=?SXf*o~hcd9xiW&x^~@-RHc(3 z=00JbSEi5M2EKPySjWWid)#6wkFCA$151RAD+u}AZb&{OZwXs5>%4CDuG3NSHkFu% z#X-w9G2fLhwnD-J5+k7l(wf$t3C}6 zyRpyt&6Mvx<(HL+=yvqKBWLj$O~j9(lAk4xjc-@X!Mb8JWGg{Fzl_7i4g4JqI@C4~ zH`fn+b+VmYIxG!l7X{TJa^%Ivi|wqk#UwxaAkM3yopMlTdwG9`o-hNd$k;W8PksRk z^PM9-QS7VF8v|Yb$*pL%o2#D}tv80=&-;85DOuQ_LsNDJSQ*&g@!$H0i#2rY-Q<6U zAVo{sww?zIrpN1v*2+zX@k&yCeo19>PHmv+R9cSD>EO0sxThGpW#dk* zRntjrQtGG3F--js93_gfmTD1N^F=PsCCXNo49=z60$Tl@s1nmFS`w$00@PPR#PwaA z(;+Lr2(2)IWs?o9P18*)a@v-3p9_%R)Emnl_0WO%&=C^X0Ug&7G5NatRi#u)xsCOo zJ~X>RDnS9g37tgim~v+3<&5sg&bU`_^)*Kqi0hGZb7$2nl#Dw*pF7Q%`|mDy7AE&h zr{mfuF_IkymE)IU2ZCZpI5P(vGtsckwg*qIY!a}j&p-@MkSI@Nzi+?if-V1O^%|s% z7x2#VkdT)|?yDr8-xv0r{!`E0$1KN7HzmNKs?XoWYm=4``96hcBSGv%2SLE1lpy9J ztsvo|r6BGifgs7ER@c`>H9-XTTTzgMAhP=&S?sXD7x#b0vBUfq75kVVHR{?gr>`BB z@79w+oRx10M5gzq=ke1vhaX4u^!IZ$1()o%bF5i^WGaNI;C9J%0<^&hdc9v|dNI64 zd+2d$1Dvf5aTgCl)-qNd%q~XX+^J&@5c#7H!K8YJJ4Q{Q(%gz5l^C>)a;$4 zrl60VVx3&_>SESED0;h+E1T^#KTg{>5voU$V@ser=m;DA&Fshz+kA2!%o8|oy`p#c z7tyYxfeYeU>oXab&%G;}3@b~H0wG8`LIdrss_AYA!w$Kpp&qu)7RsnsW7>Pqh8xG{ zD--2L{J8BtEiUSzoDT%4Jrq?WxdQ)689ELq9cUsGI{G$(JKpu|<+jT~rCyUfQPq6K zHz&#M=T+`=z~xY%j*cwUlP7y`#+BSp}bUf zDUNxI9@7TrK#o~X|YZGeUJ$uSEX zCo>CUE>C#p`5X;V4mk=0CpkfISaoVb=7nm6lk~k949iLk>(AO**qUKUn!&1?QS+LC z9GVf0niAAs0L0p%{vNOD@*5k<>ON3`UzHTk&wipcLDm3V#8F)aYpMILxHl_tpO>I; zca^Ne#;^Q51%ig{@UjNVxe2Ow$ugq9xFJuf`aLL z-Tv0XC1?(NOc;@AGl!m^^+37QB1J6q6Vo50=@3e{Fmm-e*bJ>-g)M$`k)v&~oDJ`~ zP#r?J1{BfddFrsU8C~vSVZ}hNgFtuuQX~%+DpDV?-)3T#nB2PC` z2KqBZ&n!Nn+BCGEnWUdB9CP-Yt`ccmX8V1$I$Ld72qFDiq>4k2__MWZ@ynutgS3!z z9hP)GGNA!9!yKIE->1!|zgDo_cTTy0pYOJ76c4U>K{DCF5aHffIsYWSk9lL|&PuRY zDnwx1x@9K1XVUjWvlCF(_`#-(*ti&D#O&JZp*?_!WoqSCVU^EW)BUR7CMpiaeJnX0 zcBe74I&ff~svICTr6DnPl|SY;jv(R)HaiN*;0vimVapUE)EfK+<>2x|6Ik?Xxgwcv z0Dj{wL^M(g7_-6(PqB`^07yT3gzKzTv}rOAENG8v5+vaq{blGGAl+ZD*W8-7NRi{#Z!L-D&B^ZYh~yZy6u%2^@EC~?5Hj0ihx{v>6d_g_9_l(`6- z)=u+cG^$e`()#UNjX%?~;CsLPBcS^bP3JqUCQaG=7bKUB7)$SX^_Rph%Llzb*i7Vk zWAHn3@t5|TO1lsGQ%O2eLn*;HmkFgu5Q-yd-CDi(zzRcu!LRiLAJAzrzh?gzlk`*n Ef5?p+(f|Me literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/SourceSerifPro-LICENSE.md b/src/librustdoc/html/static/SourceSerif4-LICENSE.md similarity index 98% rename from src/librustdoc/html/static/SourceSerifPro-LICENSE.md rename to src/librustdoc/html/static/SourceSerif4-LICENSE.md index 22cb755f2f..68ea189240 100644 --- a/src/librustdoc/html/static/SourceSerifPro-LICENSE.md +++ b/src/librustdoc/html/static/SourceSerif4-LICENSE.md @@ -1,4 +1,4 @@ -Copyright 2014-2018 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. +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. diff --git a/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff b/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff new file mode 100644 index 0000000000000000000000000000000000000000..45a5521ab0c77a02ebf55a3f7305faccc02e2894 GIT binary patch literal 103604 zcmZsCV{|1!)9}s4cCvA@v7KyeJK5N_ZQItywr$(?#y7V0<#}=5Ki|yMX;yW0_jGkn zRgJ5hs3-sg004j_H3AU7L(tDk0ND5a|G5MOltcg^uzKG`qW=M7V(l(rB?+-_+{*7X z)c*j8n6StLDaH!am~(9;{u_-kmbZwCOtm;nGN0ssKTzk=#gWm7A6699nx zyWY4L0AyM(_zip1%vj&(8&~ZckL^D|Aj)H5_MQ2i7x$ee{00)(4LDOXYbUpFzDT}V z7W{5|^RlaK*vi)MyB_X$KVS*I!LG{w*R-|1+jqMlwcmKS|G@_z0i4_DTN?uax8mOe zmGaG#EUT&?h@GvY69Dk=4*)>-0RY$^!tty={%cIZKp<$lz$A1LxgP+apule$fK3Ka z$NviHA56cHK6{`#LC?O^pnxC$$prx1Kn(Sa^z?RLTH^iv_s4wwzZ7vj{eDsSIdcIb zPa#zPr+jOAcCdFmZnziWfC$tC!URCY1JdROLL1xy0-}coaYees7jTV%go#95r;H_5 zF5L@v#27h=dC6cs77pM!#ZLR6!SPT8eTWDSEhleRV)(?86{UtaxH~zt2dA%>JorJ# z&I20W1prTjQ~u^@C>1oWlH)1Vcg)lJ-mb;dO83vs!{w&NMzi(*KF)7n2Y*hhJ}pd- z2CB+@m3f>K79?aH;-=4@793u+ZcEHdchoO@RGnYM;w<~6TLrZxL@#W_R*SBy_)xbb zE#wds5`8i8jo#;h0o*8*tZz+8H#N5#;Mh6bxi_B-(YGBH{p^(cpDLlc;^>#mMml&l z7*@F&e9{j-&i7U0?Fs!$-P7ynV}0+<2rLXf3QI2t!@A`fu7T~F{n+8v{U3BMJ$kq< zByA%}O?PlVpwnU_#JyD}Ga8~_y7>}N4h6M-4U!ijpXPNDgrE=E6VePbPJ;@aLq;A% zq^Wunu|7?(j;rHipx!yuLbd5c9lrC+BMzx;TS4`ej8srBj$6qu?bwcy9GHF$&IEbE zG;zGCX+J?e=)gVbK&Z!A(oPDR5NZyVQsi9+M!JHpdV^GgT#&u>UnaVh+)FS?l8)X_ zW6>l`?eQ#QZd!lTV;^h9G}t`}fa!u`T@48A)1T5f&R&H$ zpU{Ki^aXzm=%4tH%xT6P;VDt$mlVHeAue_vR)2%1q zm(l0W{m#~Oh?S^zgwng{a!2+xj~D;tx7dqjOLZV1ag4<%Iz@^@ zu1gQ7@>n0A@sNO>JD61gK@s0XRDt`aT`oT7m+9zbU*XoY-u(G}DJyU*LIZ(nGhiL6 z{y>@e073)uHK!%0vtmKEtWz0PTVQH9bHR`{L)-S(+q?5v^42awv>hh% z(~qTg)wq$q&+FVJg{IFS!Cg#O#CBrk3sn-E9Hh+DpK?0~GNVg#S<+g(!rKLPKDN=$ zE9Q+INNqf?dRJyLc2dX%LPe5sf`g&qC4%mmk#=J-z?76U&&s)NI>1U9CLUPW~TnjTH?VtmYjM)zH%{qT7u2 zH<=FxppIy3#=13N-_XO4RU1co8yfirE(;p@j6VyahD6m?mW_B+m7gb$n78$C+pns+ z;N53zFJ)QV8_Gh{Eo8oW2oG>*&YKs54z+|Q2^XsoZr z2BxsF-pzgJ9!Yo9jwT#gu)n6vyPbenDlc(k7I+D}G%ct(sIygwIAx?SND{>w=YDk@ z4Ly{W5>rGW@&w(X3Es7D;5{E<(FOZHwZ?3h0#CW#uF;5hL|YvfFK20(=ZxMP4L!B& zUw&(~H!0M5p1a<*Y-%gLD!tvY6{Y)mlO3r$cNtb!KwXw??E+3;hIW2fnnLJL)Pu{} z-ZZ>8FX9bNpC6uaXt(p-kuAF|DqhXlp6UZ$ad$g<`>t+?y2=F;W`AC7=#}VJO=&${ zhuNQKJT1R+p~ujgHafaUFU1meK-<_jANw^N5QmrtyEaw_>N?0@Ye$5c`ajqGAFODu z?(eyRyH+)C{<(=VX!f?kb!V8ophEMCvNJ|gN_p%~(_T7_bbeGcQ`Th}zfjk>K+K+V#iqg1Nt8CQ$h z#FL~w`q<0Z$O$|5ms}0`q#o~})er5b>0xU>87F6E8PbI#zvgn+a{wRitgz87k(^!` z$d*b>{{0qkF!@KuX{TcI9PY;$9Em4A8IKer&$qNcAh0SvYW#>;CnD%`rEH2{{-v#{ zuz~r~O21C{;2YJ~iRpW8I= zit-C)H64Y;d5WmS5agzfkun#?E~#9fbVbaqF?dfcuXQwxeb}g!wV5;W4ayM82J?1k zXiwxxCa7m{lr5gtokM$ST6V6nq1a!^+b%>nSp@E=Y^$L(ul(e)y$|%o zRR>?p&vNGR);JKz&bV<)8q}u+(@ThUbP4M({-}cSW*5^r&IGc5w zxjFUXXJm9Eeywq?6w%}7FXy(L!UN_pTG|uDR0Qb3cmPB4O> zc#mVb*iMgBiYg5M`|yCnjQSnvAlFWwUS(!H-C8_d+JD-ve%N~3QHs>nCjc-4C>c{_Yi`gacB-H$X^&;vom( z{z>A&i{gQeKP1SKaJ*{xIa~FJc&u7?1t5a@BN>c@$&5rXj6~Rs#1IaI=?+Bk4@7tm zFyjmJ9boy9{|Gp<46@MlGI|Bm->`NMvAabgMopLwH~f&sPpcRQ6j`j(?ty zfZ$S49x|&_R*_gt%1|D%!^ zYIzUmo6tuSBt{cPW#QMo7xKOD!<__Wz!9@U3r$xNi5^~5!&Wu4P~4?l(&#FG^gD#PCZW@aFCuJGlotr zv0xEiuqZWI#?8=tJA=x~UvNsPo`rAMmIEqxl_1{7hg8gvuyDvoEiB)&J5DJ!j9W2v zO!7L8{$*jG1if4Ivi4!=X&-N=>L~B9Xgh7iZp&y-X-nxqP=}^%Ic%!e5UEN~F|Mdu zTEMoQYCO__t&*!+agpXq!JCn_DXF8~FbrL5JMVNs?nu*~uC{t=hTI^&7<+{C4DMRj zF}1B_-_X3sdc=Rr^&aFsl0B6@Y2LzjP2&pf$nFUCtoE!E<7VW6=8@nY<1yz>A+IP& zC`m5qa&2=>bvNklBbST?xoUC zuFFu{s#I8pvy`3PchJO*wLcejq2kK2-q7JH$r_=@v3{6Q28#FZ*@$$!vGa2rvo**!b<_2pl0|lEN6J z2FS;TSfr&az-U0vy*$JHCUmRLb8dvry+FdVKAHuA(#h+(P6ZO;wOwWV2i>sbm zXjkAkS6r?HdT7c05Riook6`AjIDW|2S?=)A?U_}5?HgpX2k9LYWiV;su#nAYILdE} z0;Vkpd=iNx(~H1|C(0ag>`fM*)CRi+#yXc&rX zoQ&=qAn1lk8FKPCXm_F%FY+dY*s^8^Ns{xX5<6C(F#e)#dgJjM9qRqo>%_DR!!w4>e zE-t-3kAu9Ay)v?W_6Ysv2m{av!x9L6ln6uCvIC&g!`|Gxg3ql#k+lYG)cQhNC+#T$ zbs5vt>(W^5Lk8^q3+z*f?P7@SvkPW}%^8!6Y7?{U{JM-XCKHG1|7?$*m3G4`6xbVu zOs0}z>!Mm1$dr$<78NfyW{7BK=xk-EGoN^A=h8YgH!rHJYiyW9W>s1@cE!xkaf*(d zqT!VVI@Kb~<#9@fLT2jc$E-keO3h7B*YFwkLT%$Fwuwu8_vF`nOS@MP}Vx`k~*|1nQjpk=$OuP;1&4R|tc@t$m z$U1mgIgI{F$AvR#n~dYC6T&LQGRo&L&PCJR7en%x8`8k)V-faz`GY zULJ&A0l7vVVMYO$FPFqekn%lh{u!L~ns}X&W1ShClYvx&30Z>~dYyrCoe4{Wkuijc zD}(`u*U+2B6qH7vmc|gztH1p@>7h2MsV*V9HbbU1M5Zofsx~6pKHktS+|WLF-#!}E zJ}c2KFws64^*ZhDI?NGy`sMjA>~p_+7lMtwE$^k>J7w$C2Mr}D`c8Vg7q(#wZVDWe za=jEnI%$V-$vKlUX_glq@?NUA`!8O1s+ohlzlo8z{M`wdT6gwO`x@0^P=G?uP`yHC z02j;;J4g^>5Vy~PTkc-Jcu@s3pSzj$ChHcQywW?#wK3h~`n2A<{T{FW!sI8RDDw-k*X%z&W2xBoXEp5!!CwM{gf6H|0ydbDK01`Aub>$ z_5K@=m_S@&ozt3MOvBPu}N`0%sV;a(}D`Q$%va&`h(|SM0T&W zBNEl;oL6=?O8uUMhkCBz9+$43c}@!Dp&*s?HB6^Z`4RIT+orasn4Pq;xP|03c6*q| z#o0qQU-sT#_~S$5f1AB10sBYE$HEoss-afGB3cBv~f z@gu7DGB`K+BdGT_mJZTedNAfTZ8&Sb zZHMYjj2h}|wI|+HIBW4$$I7+8n$l~YCn!O9Qz1cz>vgyq&TE+`K~A`HZcaz+O|Y8g zYtb7(w@vP*Y1RHU8pqFe$Ybsb?$Wc)<{t71-3RSV#@AtI-?VP-9#a*mCn7qpr%mu# z+Y0w%0DU;e!0<%38tM}xQ~1lC^txu1n*~_1OneVpaUCLD|`A6w%o}1EJE$ z&t8%`XQz70m#<4C^p-UHyHbRIsMO1*eROqo5M4>}l{MaGCNh+TDhZ@;|^O}6`p@8!uKRb(4)*LSF zEGVtEK%;~9EVi`*)P**qlhe@LShBF`3WPQTSdQV(;eUux&LWJ{$-QpUf`-!H?1M|m z!$@fpzsD|>MzdCPEVrwug+7@1!&kGqw7aZctQ*#x`F&IqBXE7*F%CqYbKH|27(V5_ zD1>=OVI;e;(jK7{ln+{(v8IA8k?KfUwiW_uZaCM6NQG3xR~BsOI6Ndf{U04DXEpbt z8)K!yyHRZOKeVXeQrwvF_7n|E2Q`5VsSt*w+ma(~jcF7&Y@B0714iL33zT#`#gd(Y zvW{2`N_$yODHCCBC|CJ+T4XfCC^1*XQrad~PU^K1dtFWq6A{)ZR|Ol|Z0B)qd|M~= zhN**)K$}!hF%n+!*!I7_iEfBI<`4TR!x0x2=-BDRy@GU{-0ej63hv7%EK`n9p{IbD zC>aa%H|QOtAF_ftuYo}b_hQglz=DJW5C|j|hC z6XzNYc+5F(7Fin9Tr)(tNvG)9GBA+n#fPlmXh}YOVI!l9LOgVlUBhr zG&+CM60=38pwr7tgv*p14o%F%7%-cO+&DDGuVSpLb)sAUYEEWDx0T5Zw=S3(+L*;K z@HCUUk!?&~)mhi*WWM<266S(_CDIX&SG+akxqxi&1Qfq9cS>5d=G5?F!XtJ`jX}?m zED7hyUl=k~VDuC*jik@N8}ghtHh2TV)WJ9vtzJ1LtBJI0oFlf2R7l^+Xpu!E8$QaQOVxp@w;CgNYO6oA&#RRTvNL zPW&#S=CEzF8UfpI+Psz_%Q-FssT1v+_518qCJ)_C1aHFTG+wkC34-vd{MaF!S#kqQ zpwf-#efp}#t5zqYH&Js;H=3=WZg^F3%@EE!yFn^Y^G4x5Yt{Hw$BX5I&?VW2jyJ`J z$R*2%k~iCj)Fse|me=2h*d@`2nm68u+$GwFo;T)`@GsV%*<;iv9q$Z{F~3oR_=Y(eG~~(1bJ80=w$eK$_5|E|-H>mIJyPlibu{@Wq)eFb zd5xLD&6SxViJ`AhVx+H}(ywH7aek%9FOda_!F86dXUhzsUl(~Cq_}x)@u45ov_btQ zpP;l<$Y--mD31%brK4SR7eqwx7nJ%;7lHoga848PWX`^)fB?j0XB-)hv zc-qAJJlc@hY_rkd`})*s|7XtziB%C-U1V4EWuML?f(L&;z6Vn1Y6nmO+VjL7`fXBi zDE>NVI5jNU{0Fpzxg<2DnFaKixkvbHl1b`y(y}PtBlP;usnrr79P|uO8k!zR16>2O zg0=;6L(iOeLDQf7fUY?agtnbhgoJ)FHwu@JAC9|D8&0?m8&0vy9!{*yAxp3eCri1G zBTKc5HHp9WQ;D++ZH}{xY!=XbWNmPwCh08bsLlKU-wORWuK^#{Udqf@{sNK z^ib%B^pNPMH#sr{znx->^@+F9lM>oP5%>fF(8x|MmU zRMV)srg`ykZ?F4!_J;G(<&TsEM+M;=m?E&Erz;*()Ste4NTIw)&WT)MU-V2Ma1G$+ zf&vHJZ#46$R%~sYdjFr0Znn-*+WEGzvP0nPN3RVVHsq==Ygya0IH+}1c`v(m)bdR7 z9+B8baDHUXO`9LLTedH4eO_9)cD#)x>X6%JwM=jwY2RMD*L2#Fa7sweqecS8#3bV_ z3X#plJmU3@P}0Rz<|dsWv<2B`dG5iw`s?dNEAh^TLh2-}@HK~;>x9n#+CKNs?5AE= zJj1`U`5^j+@%82G*Zf;+n{m7`=tRlsOTB)2ZwVt-45P{SS0h;t*WQc!O>Przx~CM! zM1lPW?i2zw(6CQ63?iHmFAa&G)(j#mmmn&@ycTM?kM1`_>OcI>0NbBVmNDKri z{T8cG8~XIPA&GYQ)&16PP&2!@Y8;yw z-SEEUYUPdP)z}q}l(-PSDyS?6Z*%9$lIQE2$6O9~!=~ zgJC4$Mq#VSQSanX__>=f`2ausCGJw|OaciqEV=ugivKmoy0}_ybfu~xR}?QTo|-*0 ziE1cS1utuyb!qqE8(h`;~o=)GZ*2E*D*rE5+RFM zH$qky=>~&^G`8cvc48n(VhzeO$&1bt&Inh@2zNV5Io2!ea zB%&LUs*5bAMC*sTS?GkV94b9Kdj=TpXa>Pwa` zVak-QRUAiY{7z?Q8y z$<6pV0PBX=#kh@Po9Wu$ar_bdE|2Y{mkYBPY%+`Q(aZl6JW(HkCfKt;mHFz;#PO|nbFQj<}b3z$?muHCHogLsvA#(1&0 zUvu4aU3J`bW>&K2=G?a2*gIH!_Q!^!KqNKzUnl>@DaHLt$I;194 zC9}-KRiM2S@+kS1{4w@Q(G_A}D+SQs@tWU-thjy->TSV>$fgn z91j}?+utRlRlst!8a;G^r0ArHq=4J3@^Xvf2zfl!F4Y!=8b#A3-#i~Ah&3VzNq(k# z=vPS0kcok&-6K2G-v~SWRD^i(q@&nif^cD=yYbQAn-_`(6m4*fD0xA{9K*Q&1>;Yy z!m^q^mQa=wmQLff>)l`nvgz-aU`ZfIQpoE zXy$0xXzFMfVv|nmQ>*z5-ptT+p`($M<&+_e_4=LLjtQSB zg+7G=`)T!g^|`juF%G`Akk;YW%Ic2ll1nz5BCezEeV;w`!?knwE4(uqPrg0po8V_j z?nv8_r~R6nnZe%%*vMq~@!H}MouW;}D)QV9>6a3Sg<|vgoZ>kpH49HC$M>Elgs6tX zCOD2^RejU??vF7wel@|i?N`Y?Ej!0w_(1$xh-QdvaB7GW$m7uRV2@CQP}$JT;EiC< zV8~#x;F4g>VAbGQVF%G-QT}gnVC&?zh+bsaWEg2sVL-m0ynnGzy@#`B_AdOcny>vs z>aP@r?4xW(;^m*}KNE}3i|32Ci}uxU?EaYpRsRnqeyd)7`EM6RYFy|9{!6}>k`I;d=5r6V8;qVNECA5X{{8lN z+Wz<9hRv|C#U>(mOvZY;`O8(dgIqHQnEfvJO1yy#`>VisF2hWzk$4>v&tFymGncHA zg$++LO2JLVi@^u(OBjx97}XUzz)g;ga3nERf;>5RT&}6aLt&uw?oXJ9=t@5MtRoQp z9s_$8;gxG45Uc;(^!E|YMl#;0jUi&)@oH+uW5x%z$cAu-m?b1@pH?l(|8#>800^xv zt1h@~zpU#{@k!p+H`80S_-*#v@>ze<_^(-~ZDEv&661o?g24hUs>OWzU4~RfMTTi6 zLAtIwr&@~UFyD5Sx<}u(Ht7PCMyQX(#x8z#&B}iVOl#&Ha6zVR>xSvx$vlq4;38g#yE8Kl> zdGBkF(>~Kpy_1$V#X%~#$bFs%I$13|F&E7_+Wx|I%X#R)!vWDf>s_9W0z8Rsocl0n zFEm+?b``2QAWKi~H&RS6^RA-XPu?IDuL?Fr%yMdFt)+4dR~1*CCv(?crM`x~{kxPW zm8az=wkNvB>PMT$%g2Q7^X~U>JW!_j8u{(935(o* zkeJ8Qr8J|RE^c+5UA}EDyXKtny1J%1y1Kf0S0B5|*e1xUyU3La`%HP=MSC&Bt3*8* z{?rNHiKb*ARS7s@APyOt;&tpDp_ugg%K|ChP4FSviuPjbwp)BI(=TS*3ew}Lul??P zfE-}k73_oJ{o%|2lEUzA@ebnFjYdP_{!2DaMK{6J4BcFL5PfK1r{>Ei_4< zby~?}nfIzf5Yl9EGE`^?clRKsyM~7SDk#!o2+tr>q$XqCx7m>JgSNYV&4u4F8E-MH z2N@0=Xg1sl)wbqkbVtP-38*FmMr7Q7_ZlBUaaLIHZ2)#O?a%nzv3$V_KUJi`1IL6h zVn?h!FVyq0K167(joq{( z#t4zOhtmN?6u`i3Izm`wD$ojw1m{Y~Li}#i^wMK>!u@y2VdCh{y$$rXpYD(}dHmRz zlJ@2&;;vy@;Y@h|j*9q9AACzp)OIsvNAr*R#L?!g5?!FR*7qm@lj2FQaKZAihQ9W4b31@<73l+Bk8JU5+_F^ffdh$|uZX%-Y z;B122+ zl+4k+WV8dnm|y!ni5qK8H{OUp5cAaMj6eDx+!QJN(}365=;S|VNBp`Mnb`$qkn*2~ z{(z+}O-5_dLi`Ok-sKEfNCK(e`mLebVac8Sb3<9P!;uC#)G(jgqCunsCA^v{q4Ja| zWF$5U0YAGEMh-V*{|^fW!J3Xzmp2PO!IqA8gEvXcp>j0jPLmp-6O%NTzc1M-51X(U zA+NY>n`jrhu;;w~G?I-x1zjIeTw_VN+Aue5gIR}1GiyCTBg-tFIP)0l+W&`aVJTXL zxls7TtxN!CB{ku5@N2mEgnx4pl2dlh09S)(v9zUaF>Kjqg9}>`PM6PuA~)M6OSSbG zrOJy886`}lZy$ZUiN=q7yJg0szAA?nM&$R&IF^`Si_Ei$sF$L~Z-@x7!WPoWJi`F2 z=#*O0KM9%*n+Kj5G0hK4OY8&UIOW=wG!iAYRJ##LvR_@ere-~j)w%SmLr=4@ggSBL zD82fdQXuh3jv^|`^_7xEv@?0^!3mEz^^`)wZ_O4t{t z%uz*RKUG*-w}i_yN<2@K;r2|0Y$brF>uYh$)97FKBgWZBzFw|`gShK zpgSIMosZ)Ex>R!!vwW+D;|;>iMB3xrCoWL@f{nH5sw{rpOvgiFf^YoukvH5O|FAi2 zNI@++3$^8*$>N;F#$cIf%ao*B5+ zAxv&#d)bL`#t5zn-d&#S#!K)^z3idVi|N~)L7A+%ow3vsD@!pyL#`IWc**8eo$TaF z1$V$Eu)~1HFJTcb;yz7-OjHs)P~iUO`=K#0?>_H+vC)DLTF!=7SI0VTvMkjvyHC#f z>bsHo530IL0oF!>0=3qV8yzAwu+P=wsr@n1j;cCbFK;&^cV!+rF$XR3Xp^VGo)#@C z;U^I`%U8TjNCHd|-=r8=4v_QdKWiiocABw;H+<%{M9s_3vNIRys zw$932LX1@d!aoDhheE2hytgnCyZ=~IR-tucz?Loc(0T0-;T1YIWw?cMSV_l1kiThg*x(fx8^RD{Bmp3GAYz23!Eg7^dMWUL-T&U3X+z^wVJrco0 zAJB~%ANsG?4x;GW2$S9@g zw%PmZGhXMzKxNloj2x+FTJ+q}C4`dyWLF{H?#WFMC3mQGH!Z^WJ1f^d%#Bu3h;dDw#hMx`NHFglxpI0PB7oENvQP;BKw{Wb z3+C25^p#fx*Hd&xs+djMl`M=^dj~61Ig)LhmTh4T@%3dVMUv;?tUNV zV@M&l304;lDO@SnQ+VPGrG=t+N=8;EYotLl;#aIa`3BKBt&3akn%1-t*|Ivjp!0l6 z2SLaP6n6caK#SlESE=8Xj=wY`TgEI$4GEd`(qI{68>rIvUROz#Msj=MecF7{G;<@k zU>f+x@$LyK`W|&Hf|3`UlNDrUMDxwP?ObGv)hp3kXF|B61%hr>`;e01N0XUlmF+1h zlR&Mw(IQ15P1z<64WXpv4ck~{H7waDD>t#tB{;j-N6|@{`*8duo-3t4>1{#pklTuP z5m5871A?<38tS|hj;n&jvr8z3z9IpiR;c7>-N>*2uTRK`yZI`ithLFDt2zo;AVSJsE zWU8}ve%Z6^5?zbLDq~Dz7%XY2)A8rv+7>C|GEk=G(1(IFAezAPgwT3zK3mTya`uKrA1*JN%;RD5FaR8dXFrUu$zgnE-nUb+CF4#Toq2SlUENhNPD3$8?p!gDG(`*hGh2BAOe@LE&^zIh; zzghUKbhyhM&u~3W)2(UHZ<4MpK=1G~X1QHumQwXZV)|>VZdXe#gFwg*63>V?OJs{V z6UgX#8b9T%FE5dFbT8Ts+$`&w94#p4dtWr@qCu{);#GO{=swLKH`<+zUq&4?p^Wsl zn~qt!Z%!D4JdEDC!|3tdtu1=jrCa&Yn~1|2Q$B{kiO}C%#puq*iPk)SXy~7>z6hjF znKWZ?d8pyN)~^%HLdo&I0YXTwazJq1g-Vp8TJs`p<+Mic(8UC!r;&Z`lw1Xc3MyPN zx6Uyib*}-%aXV1dE&|6Xl2_RKFn_K!(&WJd9f%?kHo6}U;rm-uddPfg7d5Z!*R9C9 z7TQI$vL zYO;tJ2Ibs&;h>JN0*QzOnzGE8!$C&tkivnB3JOQpx@pPN*~j0ruBUC!nor%UF5so> zv}4=$RVg0^EP_92YR6>9lPu;7bLX=O0{|khZ?dDkYF9en&|usA0^x}q$->YIg97Jt zgJo~vg?V7}N`vi)YUPjTkm0Yoi_Bm2lMAV@hBH$!MeaHDi^u;G4bwTPR2l+I1`l z@072u2j0KEr&y3|h4nymzJ@aN)ZZmz3xg3`-F`b)uwY){V`E@1Wh*n7dvvZWr!GT= zfuNwleOAS}4l&SwQ56Aoo-8k5;UOe(D4$E4nG_1hOI6`zI8bEqzh*M@J*6)lb4H#; z#!06l(J@ze^vnKHGkm@}!}e@NhSJA-(0+MeL2_NY-;9&_9*!PYl3)aK5=_B>ahV zbrL<~;kkGI`6zPB)HQO>?wY8cPn_?Y*H(%ka_2eayD%qTnYvXdd0_@V$5(@Kl9Ol# zuZh#lUQ`z$~`djt0)QwlZ_4DjsXgLT^ z`OY0vQ+5telC~imQy$ECt~K5BE+GcB&^M=BbsynmyJn~6A%dT|AjmwR-VqCNtRzge zQ7$!l51+?~1x4x)0a=rNrT0WME4`Jp3>8%hq;a*_Qhs&?OUkrXstGh`0bH6kc4U^HZ2S{}n4lhfTkntrj+=>|86bF)jvkQ+Z*j&vd#|RfK^wASc9HMTgq$zTnlD$5i;r zcBFvCfc`<%Z(2vn`%ee!RzK8Mi1(i{BX2>_3_rEkXibO_Z){hH@cP7IhDr<)29BnF z9+x(JTh>BWQ;3Rd-tIYk!q*!Y$F5f4rZ&fDx}~s0mO~1KW(kU_6KCe3GP>c=E=ku= z$px_lDUMC`ZTQYSTt%kM{E^z08?k^|20EF;n$_p8HiZ{vj>l)wj~9MMc^Sf=J(dfb z+KEelsc$jeedlTpv|q$N4%pkvA0wzlSa{sgV_Zc zR6qY0C)kdi>9460K`bB~k+K$RzV75t4+h!kz!f%G&V@%Rk0y_<>;vsJ zA%mLyxAGP06IfkI(XqgQS9eF!@81^g+uB6SL*-PLXowFv%`k6JSK@hZ3lY2I(`0ub zw-k&sf_0^Qyt2(26_JO$q|aXQY-y;>+>)-Lfa8)?@@P(ckEc*Cl@4u>Tco#JYN&V) z^$|M+KM3T2!XpC%nPo#RrTF--=%#fOQ(}xoHc|%14X5~p3+%2TTC^}cC39lPL*_Fh zfEgq${YBa9%tPWJ1%aG+pEMPcm$*w0>RX#j;O=f86oSI+)=F>)TK*oDh&44jXY26$e#;*fn`)E%v+=logTsz$N; zh{U#YrGkLh$(IL+L>1?IzTRTp!_d_V;$B}_)dr}8nUo0{#r}qI6csNO>(b%UgZi*S znjuBnmPhBB3PujEw8Ir%26waP+E@jO?cW->bj2qYRVHioZUyPwn$e7`vK?LN>?F(_ zt@+lJ1*saewWWvFQ7PpkM(`50lgt*ax_UZRP+fBm& zj$=W&WZOQb)zZYTdE?n6?)(a-wr2 z1>Uy~S;(odWA(i&8RvwwpSiFA%LgB3l6RUc7a^KU|Es`->^@t?qvV+mWJXb?K4VvA zggRI>+Od1@i;Dxw%5(w3{_YI^TgxZj(bZYE42)`!945l$h}Y)|7|##3V|2Zs_oxJ z2J~vtf{5N)3mCRYTv6QfVP9TdZQqv7>?pV!^*&&)m=f_}7Pu3VyZ?==joDVES{1s( zZ#!{h3b#cMZ#v1fh_^Tx#W8(3tW3sIy)m`dJ4jIM7XL32%r|Mzym#nv|Hr3(FFE+T zp`YB{PU<#D>+^@9pD9=;<~7JzOf`nem3^a#ZX%0)!|xw&Fr5pH=9o_2q?k1)S6Amw zoHS=#R&7R9a%evEJ*{UIJjv(yE^nh4ht`@nQ1G@*h?^~%SP(bMKO3vXUotXOKFJj= zT9#A_JHvJi2x61oQ>deEEcK#>nmlnYytNch>5plly#!p%ZM9!T=R~Q_)D6C_gh1LI zh$g`ZgOa=IT$FYCzkg*y$FiEoM&TY3X3NJs8Ed$K(=LuFHf6#Tdqa~5sX5QAj&gC{ zjqaWbEXoqnc^|j&JVgDp7Aleo<(|KDF}`dU&Pxirin_%4U8kLg7j0eB$?fTm!biMb zGMcoLQ;r*H8kR;=PR%Fc0qL-?A;JU^p|h43V_&Y_Z#P51{mwHr;cXactlLi{5mRVt zQg@I_R#me2mOAdu1q-R;;P+lri@H;}J;S||GQdS{v#DxkN$z?Y94(h&X-j?HaYK8G zF1?biy6G@M{peKZiA7RzwF(^D3Ozc#%;$;S*T>m2b>60U_*YH$8_0A16 zE??NG17NFz)fUH2DF@w|#7+*+9|_V*Ibc_%VgF|?iwwu8#Qry_|A{OQ7G!rxxgjfD zV)pCWJb$u=fBKY!nTGovg9)Mp9c4L-Z0D}XSpv17@re^fI*qBSxA}fn_m$X1bE{-2C{Y_TwRxX4Jajanyg+uMt=K0DVctrs%X3^pYVd#Da1J(WE5 zi;crhOLuxqzH3NkhiC8lKZigu?7l?Pjt)4y%Dj`T3%zb!@3M{3rkB#2LZ^MPCj=)+ zF&(gPadss@mB4%C`WoS4DV_{iqG&TcajOu2ar)5sAl|g#cH=D%cIjGB)R@KKW}jd) zi%EWTKt`WV1@cOsBREVRQl2Ms?cYkZiKux4^4g=(OMptJ1k?EF6(70B()Qw4{T&ZH zr~ zD2=MrFTf%MNlfyyg%A*?DpjEt{_+hFeDRU`yN7~TWb zvEEmtuNU@}WmjSdiw0@V&C(y?HhP}OIPzPRDUZ~eAIQaCBq*X*y{E?kqjo*n^`8Ttr%Kg#9F1x3txj$#Dyg7v%ZE0>U-^ZTH$6U`s{e~PLO@Q=u zq`D51(5%E;B29ec8`Lgo@7xhWVlKITNkj`N8}gvJ<1%JBJ}KsP9!Njf(nYgW1STi?2Qvn~ zK|N=3CbZ;82Lb@E&47lLZ_c2OELZwM92`}=!~CjMH3B(rLV(D1rZ!VKPg<{iqjA<) z?p{6_8#YYrAb-sK!C@~%uuoWAwA^aU@JPRzEM8g0?D2rwPx4r~vsu|5Z2I~4^pt%T zH`|MDW)Ue`D9gL)FBqONR>e%1j-~I*zv=Yyl`GyQuKZd`y6*f-zWXm|rd3yd0VL$q zQNAm3?-@pyotMV$(&$M&QPHLmsQWYtlSOVwR<{|TFjN13o=Q}dre%U`}$rQ;)Sv}*K^6j0vzac1*jjWx(idsW}h>>7Z^ zXN~85=>C_~(H9@rodbmGufod7S)Q8S3OuYRd7d%@$aDip)O|W%w*^-wDxrA%;eB}C z%!?}Vabho-E6+_iI)@|T(FA!q{q4IVHedXgTPWMT?cu4D6sH8~ppFWz%oN%C%F66S zfSH17!+qL0q0HnJ1=Z84nbu{u?f13Ptoq?Cn&Q5K8gK;f6_%yx!?-e2~; z@u*jbL)U4)6W90sELqf@I)B1SQxEQH)ASHqrawPR>D&!;f5OtIpub#s2^uEWydMbp zB&5yAxbXR;jwjVvc(Pw?hx=*{i8|~hqIC+q)g4w;H5OOuJZL5IWaak6kwJG$E2^4{ z$+hXp1E74-q|G0(E1(uPYGZU56c3H)+ojDA`d6i*m&-JR1cggk5fY@W- zE(GvHd_)C6LwsQDGJ$^c?h+BDafA1O-jdn)=L|7^FV%fU-)2vM?$GR-1UR6*R)G+q zu5W-6AH6Am3Q*m`TCK;y?u>y8k?slxDBbOh!J+3n4_Z+>~V1-8y2q)Er}3+j6ZtPQ{tZIp&mKnG~mKhA#I&8C6lHO2?66 z3J@=>A0i+dn_um&!Y%&XRS3;KFO?%Tz0VIOTAKbVbNusA*a2gLczP(OSHM zxv6zVguqV@u9DVkH1nv}9%)Y=>7tC^gwUOpGdy`QjNvFbu=ti7)1z&E?r zspsL`U$aV!z(BiT|kD5W3NV%2n1nzt!9~ zE8jbQFZ*N=JeUafd$^YO5hG41(K#RWu9zj2^TtsK`uu#qI@&y1*!uV8BsI}kiaEox z*n`s&mhFSU^wzQAQ>_JD2+l)giMFOkx?#zsznS=;$60Y2T&Vv-@fy@8@>}RPD|#<; zHe?q7C-|SA;wV-!sm;43nR7#@A?dl zl9q9dGEXD?AXpm~5wFl%=_fwkcL=l$e5a zl3@V^i+n-riu&7$6AQD=oDI5Jvny>_jnYNpo1nQsz@nn$tXl#Ykxef+~(Iv86x%Cl|Poh(bq zz^|5Y{Lgggac~Py)*25*FU*=sn@X|T)Do=L>*J@Wa$yf##U)B1ep6{y5qwc;4loD8 zBKE?p>b!O7rH|LTf~Y?GoOP(d+fe$c^3h8VapYSvt{|kt4d!a0N^t0?H1QW+VO!L$ zfAK3*zOSa$%u>WtKaWl%r3Mqw6yba*Q6kgJcPX=8X&k|frQp6R@dL<3mpBlx99!(C zOZ>3V6GGFYt8P6GmNQ&Rt4QB8|7^AFm;P4^Bo2hBr4{bgs*g~^r`ez!1l|K7t?d~A zzB#hq3F8-QNfB|@p80XLQTY*iQ}iohuM{xCQlJ&LU&1g z_C8enX znHbZI={b;3ir>kl+O^sptzKWX1e7UJCpGxQLU?dQcng0X-6x5zVVMzWpQ0^}PuhdO zaLR3cE0`Wi^|l8tAN z-Sf@a=No|i@8it97@7HFuGJPa6Q(l9l5yq1tCfl@iBF%;q5nVyONh!DHGKfEc5qaGWAE8j+610Nbf{3V%9x>p-qZl+@oHOZ_^+1-< z@UeV-gzHdrGC$VyX6P{ekNYP$IP~^%n(1QfGnEtkp9iORx_6~-&Ti<1pHO!!Z!~Oh ztADv|xx&aaW#0Rdg(44SEvX$pzX9jR1(&XRRAS7|cA7tP92klSIV87}C_kU(F z@0Q{s0aa`=7j7`tklyu>0H6Y7yZ_RF){s_|tes2Wx3J9)=&s~1&aTGF?c$WC^X?bJ z8w!J)o?|DA+$(;q=wGnu=E40gFpR8c{prf8Fr@iO%JZ-k@i}p+qN3EoXJaGSRqs2o z&n|qqF>m8*iEi7|U7ioeQ{E2d7AKH*Nezh4LC!EXGnRI$~6^XC#PVepaza3&sP}Cm#DZDA}7O-Y#Ot zXerHiIT1GqnRA~z-hCH#J*~S&@{zRCU4Z5HU+&YjTg2g~bhHp(S}sY6>mn64tQ;^4 zeB?kSOeV3P^=xm_3=C1;AJN)*DA_EI!yYJL79S|fI1Er(xk&3AKT|FeyLYT%b4B7; zZ#{1YF?l#WUPcX3`uWG~v(YvYCJVTNY8ax_!uoPJL9+)Iy5VOC1UnawuM+j&w3rw)2GNl? z%24tECUkJ6c|Y&=1fYyZ;Jnpvzayk8botaVXdBk5=?}#8Fq;-erH^Dw{YJ&;mG`o7 zxn`ku^5Ls0z8$}}6MQ+dYW19sa##M$nY8M5LTB3pA`6^S=M+OFgnCf)Acs}jImcB) z1&ou6hmNXBe42+1bjMbBVp2Klr>zFrt*ko9E}71vz3$(PyDp!gQft0{Sh|qHs9Cic zHR(REViuNe$TUv3)hPAUk^DAe$i8~|EWn+C;y^^Exq8b>CK_4U^iMOdhfQ518>w#Y z_K*d(KebTG{ld4^XXlAU7U6fIwuQdPZ@SgK;{O#-Poi(e-mV2zy{`Ka@&@v$5}rvkFz7!l&BDp52ouUNC&~@q%<^z8Q4^clk!&c8sUXIW>I07AIeKb#2=RKVmwt+v<+M9rt?6 z&%S0Jhn;+1`=3V3U5}h)%Hp!;u!lGqcm25sHdwoukeFcDh)+*_rmS7w zqL3x5)aSc9O6-J>TQrDNU?*(wz^t z8gk2>@k4`h%NsSN<`~`EIyuk-eG9QS7td~8Y^cC3;s|**Q5A>;Y{c|FVLC0dw2j5G z8v73=jK(w7X<_+GBFIZq5{L58zo)00MLySJuCDMKTdEc^n%A5aEflwZy@D*RcrHNd zYgho1Tm>1);WY4o}J=V!`1O@OVGC6aPzM zTRy~Bzn~l8X@*^Iv>ku2v{tYlhl5A%?~t8EnNm8_!td<| zWG=pHU$vS!|LAhNXPbuHvIb4D)#@z=n9in#+zMx>(+cz2y$R=GCLVpULUywzA#4uU zKRUew>hH67rvn@Js|SEQIT;?MMF&i$`W@Rt?{q{hrF4u-UJhdSCY(sT=&e`~}K>gvTv8$7*Qr z0MAe7yt%)r)6ER)PN^ulO9MKR`D$7)2)w_&`0vpQgHqF7=^CY#Gi9d~+O^^=que;w z_lSSR5YcG>WhzE4W@#D)r(?tt#ulKOc`qO;Jq7!cZbW@EmMzwS$8OmSJ(iSt?Yo;s z8}#7(7}jYK38PC`XS=(%(qyxO>Wp%aaP6Z;su>XXjDl*VPwJ9T@Op;^Vv1?Zf61jf z_@LB$n|<(QN-o_n4XSI-rmC0ewX~cn13@WL%eVu>(4Ges{FXB$tT=7fx~w=Om%pQf ziV6A8XFgRu9k2xTbIZ2hu@@ys1ekJ3Yi%cu;v6F7PD``-N>LW#XuqSyu1%uRLg(p- z2@KbW6?I+8YQHL?BXGI10qdl_(`K-T9$lQDVuh-xvWlCGXqT(1SyQ0CR%K_{eVmYc z!(N^Va#LgE+d<38H5Z)^<+_|EHmzhXd#Sz)fNkcsb39i&0bw+{sgIS6(rTT#jY3Xo zmnU~5K-WiY?GsFsJdEm|)O3}aR5rE9Ef-$L8zC%ijx_N* zTXZJ{_jGa0l8x?06EcB{2LjPbpkJ)lvXhShC(e`U{@(f7#q-mPI()fC#@ti+b$|cn zWU%j>t<=c4M^MoRxR5(1&ebI0`}3f-{p3-`xG6MvWoLizZOyfOHH<&$#!6P?;)kZs zu`L2HF~yR1Z-ArT`9waLZXDTX|5Bq7P(v`LWl~0;d+97)!&fvKZC1+OzII-+6)ZK! z{#Ot*U%t(MCemc)tw76GX}ENq9-nO`xAX4deXZk9Utn%hDsou{ydGT&V<;K_bX086 zh?*l$l)bx(;ifRZcb>iw3x8)X4x(+gVJ9cfW{2BVDoEg}cJ-;s{EsrdoI`Hk7tqUtYXWX8s_Hu(RynWF&++!U2Ba3o~%|UT;3L6HwCM=?fFk zKbYxBKa&m~@0IEeW2XR+M{DoG3k(8h8xk3EW zdTak$6Q!zaOIzKQ`&Tef{9QdYMs*jytADL}<8qRPPmCud7%h8yrGs>KXM(OL#MW}b ze79d#eBm1M-|zb|1Glf8^skjGDX9c2-`7`)mur@Xf8TdRLoV^@8`Ru;2xJv{WD`+q z`c>MbdK93kK)a&HY`H=Ic-N7xiyqWiP0U928UZM+AE{K)bzt0^?Z1t7H91;@EA4-(L0<`*{Em=oQeh> zKY8OfnEa?jXM>yAYWWi1U#FWvjVvU;g2o5*e=T#)y_n3-89o2&{N#4$ok!q9$CSR3 zzJlMEy4&f;Z{%NPdtyGw6X!vMV6t1(mr+ONmb1LGGnu5tP?Pa;TXmw_oMJ9xfy4Y{ zN!#^u>lJ^iFdO(Ax2C7a6UMR&I~q(1tb(tBz4ap9^t!h3qNW_>lcGazbt2s<3Hey~ zO%;vK97}-mMQOGJ$1)efCD-6~+HUI-`qq*mDBrzguG0txpkj9|P@E8v%WgK|+XTPK z&%+eKR@rl(G{NX(xu!a_1QEza3a}5ZYpIQ=<`S{fgkwR0`qiouTcH{Gcl-0LuN*RwBKtf$>+`XQzGGmx(z%(u!a@EQov&O20|oYKkb zF`NdY^!^RS1Fx=^5}vf)7e2F<1mlJs=WDh!{vn%YAx0~Rk$(NG2;F_r!CpA$4JY>5 zuHCw`+-&(zje~C9wGSA>EM;27d?7rR&n6ba`Yt)Lj$MBI6yDDV$rGuFlL&ZNy!!^1*DR$| z7F@e=an0*U9s|0pM5WO8o?|mM(CRgly9sr=I6ls4Nv(mWz~#sMo&9W^+Zahuq&D8y z8{J(V;WxV3mC+liUWu+@U)7M@^=QzZ+(dWq&yr%sJgl5iZmJYw)^{KC#uXc`HB8k| zEhdfiBfq4v8NbomjX$Y2ik-mog_?REyF6%6n?J9#(Nv^fh>t%v?w)3GTJcwg$7F=I zb_Zgjo@gjzyhb~*>G+mAi^vjBA>K9u>LpWEm25&^kGx}nK0Qw)wD?b~El_1=^m_Vk zDF7-gFS4N^Q8%l>pRD|vk0V(MV$8OVqZGO(LZ+_axLNvQrB=1SQ8TQDX^QlZSS=Zq zQKj%5ZFUB$1!I{O=XL3lMkEt$s+Curu2WbfNzcfPk&a+t^bRGqRzx$lOSBbnrS(C! z6gGeK$XoK{&`Y<7nP4chnXo)ah^n5aB#NT$i1yez2Yn2g`ua9#bL9_yj;2bP(cFkR z)T@H;0I0OP3?ISnAl~4HFZNRj>z@0Ovs&q^;emW<7qV%HSBaxNg0-t?0OFg{9k_>43#r&M*pC|Q7gD0l z6Z5bWi_-?m;Y=y*VI9%V8Tp#0W>1E{E)H%cHuxY7(UXMX*b?2MB+=19cI(-bDXT$O zuHL-Y?FTN%{Y{kog)OoOAVoP1z@tm>r%2YOzrZD>=7zg3E3UNV`$ucApm4+lKOg7& z`def2xV5GSSUojafiD#OBJe{el0K^+ISKz>mGp++Y>n~3c~s#G<-)*TqMfsB01J)u zJ_4Ea^?jC+Tx#S?z-z)%*|4+gVTLfxeKeQ>>f(doP8A${D#f|AOZ?-XB;yzUVT>*^ zVnzU#dh$aAc3et3=Oi9e5=0|hhLd=WAR7ROlqP*neTr}@Gcg+GO z3NFe}_wo6UI(=AWFsY)psnjwVN9d`kE?sU_kXw=js7$`$N$JYKZ=(`Aw5H8Y1oT&lf;OHm>WtrW-1n{`X;6Af4 z`gp=c|J|8W9RC73@Jwy{LzRB_I1&qnE`0Z$fvA#T;)Om6M+l_(A(ehN$3y+&6HCmZ zo)zt&Jvfw;4m2Y$b!4Ygse%SjZ^mf~ zVMcrpT?K^6xgiS91l>}0GEFk*&|~dOxG4|BlySs^GR;}H%TRHYKSs|pBxagA<;!ER zc&XL|iIVR<;5G}GL`A-l;VrihfvF7Uq%I)DF)xiqO(&0_pvXX;GO((S&p%r(=A_ce z)UTE$LLu6t0tV1=Fk~TfEmT=$en?j?HFcfJveA(%@~ zMZzy*Bu%Qs5yS1q#EZI%74BMruLxMu=D3lHPQZjDbC}S~Q+02PVQV zn9x|pcy+7jv6xaMOB;~@mNSy)%E-u%v>R;*Im+ZxD&4yrX@3pKm25*8iqO>XNF;4kFtif{msd*#5*~ z8#k>6v9if(Y%tFvj0j&NP~geZk2k|iC}Zo#Ntp{LgSWy$Sk;dx<5gA|$65t@!?W$@ zXGSU<>Bm2((lnkvZMPy6$^)k-p9~t(`uri?o}q4SEN2s~|3_i=HQAnFe{(&Qg$sp@ zQa5FrbP1;DqooZg*(RElnp7#dG+Sm1;fk5 zK4n7GVyrV;hrZfTn;a&T5UO>%>{45_*2ur`*DU9))OS;&kBDRgN1a7`g;l`2Ec3Hv{=2)4fuX}URf9|^Nj^DS;?s)$CE~`a|HyDMC zT6*!5bv+&PuIHv{ycjFau50K>VxeZVF~9iFN>Wzo1&5m-)_6Yh4dH+KBak(M=f`yF&!5> zEWT{8JP9u!a%UAIGdB#IHz0tve ziDuZC@}s6qw1-Q$39L%jLh3y3_mBdAi7>Lce439q1c|LT*R{)eyf zmz9ue^fUZ}9qMm)M!zS?JW?72KAS?lvMuUwd%gykZ_u?@z3eQRJq11aQ7QQH4X;lP zCj*9kDm^jo<{QJi{p3fS8kks0EXS#rFD9SMm{6Fg5K%FYQo_~Ax~Gav_H*FKEIutD zv}G*>b8Nb@W(_l{Drwj(t8^olZyrlc=dA;a9<5V!80Mg=1Ea$!pI@Osu5#Y0lfgBW z%`Vqm3>k?CV-$~=bM#e6@9@Wy^NLsQA_@E2yRCUv20Dl$pHB~J%H~U)5Q-9bQ?XY& zKl^KpUQ9=A;ua+GhtAF;9|^Tte?1-Rn|lH5I>d;!@z$K)^;bMwt9G6fF!O8rOD&#S zzDre(TYCuHy$i4YC0^F$C|If z<1fOk*kQhtv^;~EB(QmrM@NUX&!n#3dAAvwXI)w2f7$TAib6M&Tt0rCYz=tFTE<;A zRc+K5xM%X(3xVaH*{wHkF#MW8h2ICL3V(my$x-z{`J<;r@A!XzYX2>q$tS7^R{r@> zs%`bvQHq7IERbVOqWolOi}zaVHroX5%OtQM%z}kBhABF5o*-bjsm|Up-Aqo5rIg=UMR$npK^O#7NlBT?4%jsKk$`w2WY5{yeor1E zd9o};2HN_ADH(wNZQcy_k5Pvu-1&0dzDzshA#YIs#-Xv_ zlg?f(u80pIoN&LIUs5_Ge5%FskD`(@rO6VTaH&6-dgN&i&oH9ZXR(=Gpbaj>3{IWL z(p6>k1iLKz@ZlaiyJ0*Zbq&ZequQK*K4ltZ8o%8HEF&3jkFGs;G`i@H)EEF4)=GOH zExR<|fp4cZ)vV$lg>6qT&sYaP{JB%8{}6mK9-1_KdTJ8zRP^eeqlDYSHUB6p6s)(D zx6-o2==IVzYSg6CDx5L%QOq7Ykv&wzv@Sg49li^+B)k3|8qS};ChgH^Zn3?gadB&` zrr9-|Mi=e7F5SAMJHid(_YW+}{oxL)T+OZBn~}$YnLVq8<|FCgoO0hLF}}<>zDzj| zPq>?s8ojM*#e?C<3%!t0u|ymhtxwd@DHs@(K)N&g`>9Dwt8p=|2<DfpNC!m#>(n#~`!2IWl{I)7!Iv$0=$aV>wKp0+h&7EI-Rz1)NRb=; zz692uS1YLf-H?JydukoJzYDBy7wb!6sOS^;k}m^oRbSQr!%LmK^7Q!fa(Ykdq;Lho zums>{^)%4ocL9<0%wJ4WmW@1F`4UiPhVZHhU|TT=lXD@!na^?GxUyK_`LWARIRR`xPXsE_ez;;I-;K3seMq
W73DCa^X50)n4{jt&}61APZ}D1#93D}Lz-fI5SE14c0|0tWI%_M3u7dc`NG&E)FMjiW0WhX2uz(ihg@NW}cRDfRvr3iKiFK=B6w1(IjSTr=XA zku(~K*s0oo0;q}kLx}FZ%g;$;Bs5!5G6D*If1K9`(_mqoeaO)y9JB+H$`c2w9I+kS zTWGQWwSgt%Xr?!uKl~|O7~a)DWHXkuJT#Sz^_;YKc6a8(Emc@Lc>Iv?Kkfe?APy6t z{8=bq<4Nyp{s~0^tc{+cjGla~$1KpWT%@Q-iJ_XG&~HBfuMNh{&%B8#OFYo9Acs*n ziMu2Q((;>u&m6D8q?Z|}ttQfu!P-AA6qEePAPuP zF6j6aOdJ+(u-J^mKMVFT6Kv3tQ!m5pB#yq|IwnXZPga;QSFZ**E5&0A>+r!hcIiQ( z71Hq&3iJ@+3~kid?FpaZKQU!Q}qbKwQ6FJxfpkgV8G3Flb@#Yx$Ed?tFsF7^H&q)XjEW-ghS^c!UgT=)=B$pSKF_Ok8smBzO~pj zzei%5H#FC?l5jWo6grDV7AI@<`d*D|EId(A<+fb9%Flf^=D3hTFIEM?c_NDBW{ttI9is0 z6t(t~pHh}a{dg|fpgK_+lI52uIm7VDz)%1e%7N~avQ1?hyJY(CDhik0(sTRhNN0;- z>Z_BjT+PQ5l;_R|6$yIodt%=n%BIdnN0FH&wowXmQxz>@TuN=JSP+n0|GkIB)hIt2 zc1yxMFB%k0Js6V%DYk1A7fwbv^Ie;t&cNl<6+2lL`NTfNi|?Ygo-I)Gp74n{Up~p| z7E{!S27{+ys&_a^8y>TvmW7n$!3-!1~;Q zq!cK_VDO@%Mr`}_py_2$&XFWLlPr6|wpTTmj(FhU!qIMJWW<#62mf*>*{M{sggvQz z(Uhv2t(k>u2HHBbEsYm(-=L-7Ua+-2vGV&YXNlgo^4-dfC4^`yY(+J;Cb4v?G4}#m zzA?9u7wk2ax%bt?)P_D}iXDF2I{z*6*`7`S!;XVm2(9?1VT1~;iqxFD?%B63Kr=bJ zoD*+_H3{7-NFYa!%&O^v>k)F3>HFU8mr7UL(ttU+e@3h++LL<^D@O*y#ul1^jD@@B z5MTX>1)U%qV-N2hK?y-{t#XsTGZ_6Vf$8&XY zE_xVBn{PvkGf+ON9Sn}^bx9MZ+eeY{}K%b%9!NKJDESCoCgp1RqH+mBcfMai#Wj zb~{==46W9Der>)lide0?1HnFF!QW?6p^l$>7aoqEp|wU{pf{y=+JH!RV^rBMOM52` zVBt_Uq44Eq46EeF;i?sLYw4Q!$fR&^s7TuWa>(%~~dI z6P#!nOT*ZR81OpP`ZdYxxxZ#*lVq$Cykkz?p5-GP`*N1=D18(rMc&A`0AyO7{WZz# znTS-9SW1pBwH1$N0A`egtGdr_nNinuOx#xlKb9U zLB2sZ(U5cAxL!wonk%}f(;&1mM(56XoyIR@y%s2^)wQpG1|sG1id(!$&zt&_Rce%9 z-}9RVYbMDU;i)AnH;ad#nh+w7AYBb(VAY8c)Mcb5)3@ek~<@ zIsS@=&}zkSmf)~fpnfZq&d}sHcmmYmDjD?AgggJ)Cau+UKsnJX? zX6vplRn_kFDq7et;^Z@FDOImWmf<5Y3Y)TO)y;Nm+OT)RC#6uUw2Us$xE0 zY*$Asl|9kSs2nR8VhCq@79T_V)hTw{k5&T4WFTSidnGd!j+uM>&M4T%0L*K3@i=_A zQ0gFhDL1y>N5rBb`@L#Gm&RYlwlTsUsiOdZy|J3J9LW9bdJZQlddh0A7?k?w!9u#o zUFK(@ZWJW5KFB~WEQ5&1r$RlVf$h9?jAZq)_`fAvqHOzW0Ta?5_$^`HFP)<1_?FEc zTAuLc5hD^2TUd?hQjtTZZmsGjd4C1rF~_3m;v@zR%6;r2N+Eye)qTbFkOpgtt!Jfh zc?6HN8z*p|V=YBy^D5x2I%(cF5`Jd=ys!X2lPFp2?F3l1MnT0z+T|iVN7)fb?yL0C zSoM$YSu*mjjZOtXx8e=UdL{Tz?w3nf6GCtSIyn$w<;XfE=-9BXV#@~g-6jX^6>#KT z76S^T)}q2m=S@AvtlZl+pM3!#LKyy3mmISKu>Pd|vvHhfA}e5m%f*ijX_#^XjS_Sm zX$18ikIN7yaFm70DW@m48WOF=r1bkUPzI#Y8T#pZL1x_9v)F^_#`*$Sc;Q3;W}pML zT}UuuNB&;ypDy<)Q%wl%jhTmiT;%+PpG)T`cvDoVNYE}y2%Zt5#K9`y#Gv(%>(FJ^CY|%_<(M@S>E2Z zW>%v%93>D>zapln+Lvqrr_j)gX1Y|^ZM1%%*M2q#d?HoTIv7|vfy-x}x{YPCm%s0f zDVIv$kA$ZqjKpLVa8x@LS?baLwq0O=B2eh{SB2^ z0z?HGUudv38CVu)qzk!Zl62t?Z&$ya+mS`7-%gcHm3c~=rox{4r>=%zcIid`Xf33@ zN3I$vwFio<8o&E^H8Fcz8P(bezZu|M>;SoL9OhLp!=bt{VN0H-DP5w6d} z!njwJgUC=VnJYD{H$U%SdhRhneRe*Npjvi5kuq4*u0?G?c4)f<#zqWMp8MYVQ*6*% zAuEzN($bu}OS&t=LEB+Za1f=~y6|yjAiB-mzDkC!Q>Km~s`fAMDO9#nJ4bv7 zH;hT2RoNYCPZ=W}dSU>nXBymScry!@tI?xVHRzm4r0Vs6o6aeLjQb1mJc-LaWOVr# z1rks6K?EDrdvCdatzSl9p!pk5IveG}?dB_vbHE!oDj>lQ5o&hyR^yR1Ee6SY`>9an zp5|{^O!BC0T3t-pv**|$w62MG3dP!te{;t_c!K*yhMij^g2r{N!iqWmY(y}i-I63( z)-1^FU-;BM$WFB#zL_q;zG7{3K}Wj~yl8%v_nZ|nvwlyW{G*)_S1p~$mNreLI_grO ztuX9==y&*1a2IXo9-&!6n4;~*c6NopU)AFlS@j&&xoMTJzuE)W>%jYs{2bMlcm%>B z01u%oM>Vcot_%%`s*k=eFO;fnuexv`f1f6PHQ(vSzZTE^77*n>XSS0%Em8M}WBu6+ zQ2nM)l>7A4`HZ8jpf(H7Dhdo(OlPTE>Spz4r-kg{R&26ig5FmM_|X?pg7ms4oMRIU z4NsOcB;C0fEmM;eUgSN4)xI^1B*ns9R3+IgSI9la$@Uc*MuBG0r@Ccp@x#N4Me3S; z+2D_E{gfRCmq<&>R(ZEK6Rb8u6@!gP>JFIBG@6|__Uy3T$xlSnV3Ia%43o4Og}`;4 zJWOJw(+3mQd`K2tR8_}c-4$HvSr_r1#bhx!t4vSh`<$dR74tlyWQkJGfwwe8NV-$X z1BeDrwVTEok9-Ptq37_5&ZTSH?#rYzr7g7`e(2q1Q2jfT=4Mg>nz-P!E|)5a@(`2O zu03JBzW9kb5!a`ydm^=-4#1SdReC7UHHD^8?No0EIJwpGBLsi=y0Rhofd#jCr#W$c zK%4%y$DuoM@#|?1^s5j*Otux&V;Ueyv;9eKNbzQ&$ci{A@(Jh1^(zGHx5FcMJbxri zP>xc=<6K8m?(oDMqR1e>!)+^46v@}F#FN10OX;UQlpnK#cuQBeb@(TLgXhLGw^r-` zz;mT%foTu2r?-Fo&d3<7yVFk304Ls$ekr1YdFCZ5!G8Os_rCC|Q@kEW*c(VO zL^OIkL+dnw6~ZNl3KZ}M3GJxt$YTm@2z(MNAH?Cg!IdE)vFgps1o0SOH$U3gxWZH} z?t1H;>5UpGA^gy1M&0#+;>(6^VL(!fe1|4aGvC!D;vx5@IFkMi9w=Yr!$W9wA;WvW zjpXmrM(q(O>K~)&9HA&W{pOPh?CgC*Buf#>E%0N|@JAiG5SG}+KwI|rI?m{HhrYio zyA@UX4DZ6PQGdPitc6S}9CiC}}s^<&&-+xwf}Ii{2qf z06h4$ri8?#-LQbehiSRxC#n6oONVP)!TxYmlN~RFe>>NfnX|9jPn^^yiHhX1R|EF* zG=Pai_cL2p0JU=D9S)~*0pfksb4gLOym@@dGZ7xmEMAnbn0n4sB!Mzk00`00e)h3JE{srl=o8YUau|M1Q0 zabU|GkiLT&XK|2pTOTV~L?W=ADU=$cFi`5GcqbbFr-b1_B#~YmnR+U!U{ZGn%2`*U zBir=IlXMUlJaGyMWS2f3v9||+!Izx-H6BN$w2*oLqY{DFXmL;w?XVVo{*RB3S~NGI zKxs{R^x_u9 zr_1xW#I?ZHro1oaeJQu=xgx75XVgXf@a2Kr#)Pyxqm}U7;>Um=BAVvG_UgVo+6Rx4 z+bd|R;1um{_+L>dw&(3jDu-{<#4xU&*r4bV6fGW3)q1&V4w$mTih)DjOxzxy2mGh+ zS<6m#q%`?M<&DEGh5IGKHR((W6^qD-%yBCsVRV*C^`7b7bG#(ZQs8`MJTCw(t&2); zg=c$&!(R}Hdy9~(J2{iHdf`;5#<(oox;q2Y;zPr)2k%;&eA~~UBl2Yhs}S60qa6rP zYj0-HI^%Qh+_zbAX!|AG<;S>|JE9slTQ5~c!Sw_DP}Al6E3Rye?Gx3_VdF#i?hNFz zG0G*fk=K3~5M|syqrfx&Gfx}6Fhy~%){n9bqjU~4%}T-XxGT@54|{GI-C`$d(7$#db&aGt=ExqYs8gc8UN55R#foBh{S>o(vPmh zu2UcOx{td*tTq&Ly02oEa55#R9avu>aK=uX(_%$QEpqSEDe!~+PgmulUU))7YcTW+ zx8twco-Wo+96$z9COv5pcwZ=+om7TLq*BNl^2v~H4P*vh7??O;c_Zf!=4ju00bj6B zxT}!-Tp`8#n~+>LX~WkO^~k8qaKkV+xd?>Cz&Y*`97d&GBNh|l1{E8sG&>~s z7GSR@D%)f<(h9)G`(^ubEh}004OZ0oNm!wf@iuG}v00AK;NTxGpU=$n*riMAvyIw% ze5@dqH1>RPlONwv1wqxmb5M=gOfZKm4B@tOCyrVI*Z@z5^2EE$nJr!(Efl=1vr-Vs zrheeW)$d$k50rbv8XN*RGK}jgm!)r^$l22+ky2?U1f)k-gz76|Lwt<#p;VG_B}3)w zvnn@o_oo3ThkSirw^FJ8^_6i6%utJWHo;FT z{H33O=&97CF+Z?;%aX!@YkG!xlN|C;Y}4wdR;^Ae^fuwr>c;P$)P?E;ZcIoW&^F@@ zvhytou6Q+ct4M=Qbp!IcnCK*S>OS>ONZlqpI|zToy4_68xZ@ghAFTf-o^*Y7^wNIc zjGjzvSKiyw^>zHo)8h|uJ@e=G-$8-?_7idQ6VLryN?$!0^--w-ytg;(sG(lr@ya6C z&i{EWVFwf7Q~%2U2U%iHc#f;3cGbOiPWZy_Q6Lg)&D;1VwO24g9Z%Q)0Z%}%zkc?; z#XQ5lB#EAQ;KASn4+I~C{}1luE&%c%_&88+H`F_dXZmI+*ZQ7u%QeH+CAI_t7Hc42 z<$iy{*4^#3+B_bc)r+oNxH?ii!8?lh+}fvr_NPf7`6TgKLIB@efa)SK4(kJ*_?^wH zm*Mk;MRcjHeg|4-L#g=7xo>|bw=@^h@%>(J9=%Y%(1zC4@35gc$o8FYzBX8a!>-i(*zAU{M=S>XTzn0DT(uPXa5cNjLjqaxU=tud&Ut_|6NISQSpZ2 z4eEpN&DN1bGW2_NC!vFczIg;27jlHi-;+wxPqHWYpHB$jcL%2N7U;(t34UX@q&o|Ys-QK+zdX!JRDk#t z`4;+5EK%v^DmAX&>k>3K8Z+Eszwo^*5X0K8c(UsCt%xRa=4sqW)wh6iM~xdqa`rKt7aeKRrE>7>L&j;gM8k9IiU@VSL_g z+x%Z)?sYvOCn5_cHE^UYE}%1+43OtLE+p%x5*}Y4OoEd(Z%<^fcdl|;WiS#Nh#Et7 zsiQxVpR4p8_)NLhbLotlPRzWuZVFD?4f4di@!616=27d)`=-u)XgjNIAD_|02-nJ|dd{U(<&KBHBAzfXkf_@vKIbU8No2P27IR z_=XFs>Bj^BC5`1lze76+_uDQJC?)e!TaC4H2F5CI{LnG;QuzF($4GxeGM zpP&@)U5{?c)bAtzMPPs8AZfyHtq@F>rttPICrz=@h|Pa^1-&S0H`jmv)UVN~xm|oo z5sjjKp8F2fzgEBRl3zgS0F?eMlnz7br9pjL?LP;1HerEvB)N`!s4?TOzXqxL_wn^5 zIHK=;Ttwd*T-FYCu$LHmX{~lC2O&r{0xR|jrEKlA7Qd2)k2b^N#vOpx^kAE7sJCm5 z`W&?1PG6H=W!Lz%=9MbiQRwq^4)5EkuX+O|qtP;k&ihc`x4+d@w)P*Y8&X-NP3i55 zoYlYQrYYaLRj2=YTQ=fgy!He>>*DX^U%{JJ)iewkkqDyL%+h*YWveHGSS+gdVjD z9j)JqB(v#rk)-~4bX28r3;)8F^Ul9b?g48m#Vd@o(2vqc=%>+csKAI!P=WDXweCx3 z>pMo2u0LaZr~VlzwF+vB;@VjK=Vi4w)JR>GJ`d2}3Fy@x;a{R`)ozWdK8vR7|6JNO z@csGzJklY5p0E8P+V&?CO4Xk={i*)xdcWpfQ~fo4{Z-SuY690)g}NBF6rE>iI!z0q zKJO~7VSpVbc<2wA^Wb}JeWOzC5&ZSImZ7wc$}`A~@(hK1Y|GdRUW1mAQw_d8gVHQt zF(;wEYNI~jJRi8|r`Z80OE+qm#f>AG%(;IRc+^UCE6do%X-wp&NPI3pTJ2Ql$xYYZvQrOrFm!Z~u&u_K|Qktqymw` zWAEkBgVuBUc{#a-6&u9N}Zvke@rYf%V*QPU+Z4Xw4TjkJr!r0dM-g#>ukiKR_$H zTh4=F)M*>pcp`$WE%)xQS}V9XkQ-^&*cEmGlZpldTB}?ql^MM%k8VWn@kYx6KDo*o zOL<-6F;90vBQ_N5o-U`-s;cju+=%=02f&}l8ghpyil#x0&}nqvjW^!-)29_rKdnGL zh^fC>e+60Um!b>Nc`WBU(A~uS$QiR;E0hV*eaJ2n+Vqx9WwnR( zYoQc69ZLCF!$}C?`$6o}`$-e=Y4R0}4VtUND>(4u^S9+~PKQ0;MqV7x`h5%&@Mqb6 zhx|8l`LzOf7W+x?qrbVC|6nZF$e)4y1=31f4E0iw-=7v%1pNZi`rYpWMN)Dl@o(}l zj_%ahS5J^p;sNrXgn&|(m!{s`)58~qaMcft7sSbLmdC{X$<>Uw(p%NfQF3*m6H+#+s zKs;PjyG;Pm6LK#8CF_q}0-VT0yOh91VarLqAeMQPy=>RX8F;d&Foek(ZO&S>Mu}FV zVLZKT*+b+{i7sk4p;%V7OXH~8Eqc95ZqX&lw~T6+N@bQSX|*l}<-P}X?uR;|+;I^b z%b~c!ELRxhI;fhg_4P6ujaFjRTC!#+_ZZZ75!AQ5Tvuy&NAj)KSdLI`C+Q+SM!tdP zSnSL&%^W;GtUKE|*^C0ZccNe&Q?S-?`Sc>_5o2T<^_G zY;uK8q*#9@d!^Kg73<0T^=7SBEi`G)RyD5(jPVD=!_@hwz*vx4WeUASHhU1R05@Eb zFPsfds8Xz#Z`L%g*nU5oEE5oEj~$s5yQ1UvpLNz*hHZn}$Up4Zp}py*MxGal4^vy0 z=b^T)TBSSZ9D>z4^8&Ep&#>oEGWbNVe2cCtFOA22VXVeR)>e4rjmX+q{^s4p83e_y zEC}=I#qi(xg*m-R?iKlR#k}4w5y}|3)#_e7-7W}tTyZc6B+sa0FrHfg&m`zzE#Sd@ z2R?gim@&CGUJh9uu7zk~zmEFi6FQ`=I=GNwfa4{wSDyJt@F)g#<`J|B>i=ME-~5hw zEAff>M@iOp5bym4AT#q-cx&-%05JpPZGb#BpM|&g9sr0DAa4M^?~_4dkbIkv0Y1(V z$+PXF#a4qaD%qbTgLZ*YttC9 zy+|A)A7Qz#&K@5HtQqTT0KI6IR2Rc~bxaUI?^W|-#Ch{K0KGb(_dSA|-$dq!BNV${ zs3%-Y$7Md>6tmWWwUu#!x^%hHNye_wE0vR5Az=U@nOhj67tFw;mX%VbjOz2;>);WWdvi&k37IdMT-^;tDQVSgGMKnN=9yH z;zP?Cv||8TqoHFP54P0QY>}92Q3EBz2!$unZWCU;%53b?UwoXFqpmfW)H>HRgZb6^ zX|~7At*o9@bFz=}7Fu#I*MPtOnamxJ@y=>>k@laQ3ab|^+wnTN{thxM*UMkPcsXhZ zFkaiq@p8K5c!K}L>7!*-BN}U;Matj)fHfRX{JUHY%jicWR|5$ijDdKKQiBfEuwxQ0 zu;yE~(Sa}H0+(jLF(oxh6?&yee_$*h}12wl% z7QkX}V(~A!e61c|6Xk7!M9}0^sh!#|Z4kynMz>Ps((3JEp!Cc$jRUj6q+BFX#$|z| zTr5!-^thhyLp|SsdK}B@S?*e1rh38JS5RHg&uu!nrUc1+Dk6`F7Za}_YJ#%oziEUtek{R;;8i^qB1k3gDY zXW=-lf#(Ir=9}avcuo*OzZDkEKS%JlzW&M#Ns?y=pZr+u(#}-vV(wu;Ed`GV@VXm8 zrpVhG>tpFGou+kOCuRD7)j!t#=(PJn0g{TixC}~psah#T6?sD8`*A3G63U?<+uirp}r!gi4fz$Kvk`Lju67#|ZnB({~a+>8<+Mj0FCq#bW zg`49G%Hu~z!ic1uL0b)Nl1pSS$zn0~tG-@@UKJHI^`n|c_w0G}&C${4R;+jqk@wxV zZ5vw~$7!fd)s&JK8&8$e|Ba_g5fGIb@}AbGN4npcbL0CtE1S~Yqi3K10l3}-2xN1 z*TjJpS8tq~+laJicH_ob^bj)6qOBLT=ML^dv-Q{K&>0uyI}Xhvv|-|m;Fv!d91Ebi zz21o+I%9lt&OaJN?5nM~>g`<4&=KUV*`pIlcq6x(b=k!*FTD#S$t=A@0Dx&ycG&rIk`jqcf*N zF+HCzHdornb;z&|p|*C5n9tY6Ln)J9&66t9n^r+L2c^-O7(c&nV;{p%RFKI=!UMA@ zflwh_=`FG9I#)-Xs8?G1_ zx@1-9tXT&=d)EQqb*uIty!@=~2Yd$ziW{$Y<5N#;En}8D_k>DQ!j{E^<`~Yuk)Ja? zwdJ1$kwLCuB(mwn5qQn8l76MrLSad>fhn(L8!+`L|gSPr_Ho_+``2X z#c!$fi|DVyqW*1!4l80Y`ArDT>x;r;{{yN<*XD`SZWLgK%F7nt&D``uH zeC_hy;Y%u#V5>@y)DE?EUf6!)@jOG{1!@`m#@|wEPr@lPN7SpBJ0~MyId9n2a;R;L zS_7l%Y#bN=@1PNX4z<&SpS3;wqFn3&S8HJLR0W`^Q=eS9dxnV|ZW zP12OdTbb1Hb_hMROp^W+=rUl6@eb`4mQc9IXnIL!(XUQ@388KEpKT-W?MAANAHLz( zl}mUduisMIkzhF!-&R7Wi{PUE6BNIpl|NW-V*Wfww9*kIvj2@y+sdY$ryjxei<@+w zYA~Z0n$$L;&X8vG259wIGtzNm{|Vi)2`10FU&lvWzNohp?cwq1et)KCSAII%zA+Q& z(eqa*C2Fybk?192S;S=ai}WM!p1yPS@WEK+WiUC&`EBO*Bgl-Hf&E6Z$#cP!TvCnH(y@toq6vs-$btr?P?1QWgWe3w0zTK z@A|ma{-TCJUnob#Xc9TjaQ~S(XkB3%z z_3k7iY#FW36H7n<%%1&XD2iUM&&g6bEOKqsB6?qi&bNL z**h9jd3VUWs;OR?tj(VvFdJx_lD49V&mTdklQaeO-h|3x3IrN4Qqt&d@-22o&0ly@ zi(}jHvwTKDLB-swZKzGE@RzsEItI>LQ~v|ng4UniVQe3oY}cEgv1cq!zrr{+5?sIU zV{_D~D!1zsJ4XHSB28Bku8ug~h2Du?hBmvQo;;nyQxjU~&*w8Od$O1c$$ry9bh%tY zrX&6lJ%2(Xr<8gLEs-i+#(5cO;Sr9%GCoX``7!n>S+} z*;F@cxM(@g;)oY!!qci%8-hjwV}dRTle^b7K z%9Ao9xM-JqCa&AD`(tYZ!(X~?*A3%N^1GQ!&prL}>aiW^OV2&yvUX_aCa6<|UMFbW zw|;8rpnoD3M${UKP{KDdQoTeZ3&}hC(UeBA`QU^r;ec_hw-el+{r^O75=Fpr9FJHJ z3cpdtMPy*pHfmv&B}Rhmu%K;X1Dv;v#Z78`$X75%nP9{uBZxX=xb7Eh-&n@LI+GY(D1ltPo$smbkFZAseQ z{cgNpR$FnZEG-C5ryX)nQhsQITy#&HKF3f2a8uM7#r~qFtodz%H zwo#pOm6RtEAf{yTm5qYc5|NaTNR3gV7mH;fTfo6Hb_cCht#R^xWI}sr$>e!!eJN+C zhQhRD%fWGX+=)A=E#IE=`~KL_ZvV#G%?EV&d@Z{%Po~>m(if~MJ0npFrT&;J%NV>8 z&})JPz2?kyI{DMLu8R4g3ql^ z42D+}B(mXB=eSlfuB@TK?o`hT5)D@pMGcH=cP-9ET>BkxKuK6n8WE7wVDFXYN}Z>d zO0&hz)1u*`Wvm=7SjOdG&Bo7cFYa0~wy!+~@un;-VM?S-@*bzOTyZ#f~cLz{{C9P>n^H`s> zn9z??j&{#b$8e!Mz`igCTSzOL3e|08d!JRc5>a0;71qJ-e!ZTtBzzwBSgaT(FI3a25RoxXLt6bxo(2auw&s&A52`deN?p=*K(OqfMLZugk8z z!PUEW1y#85Mo0G?K86Mj+Ehu{yi-o$_o^C;RWH}cK|kw*IYa!?0nr0B zQ`#=qOGV~^3;PKrWL#5*ig!uCMcRpQ9@_FX$itfYp-!%HOgZvb< z8<@cN=Y1#a0jvP%Gz|<`(gi{Wty9U)yj0ZM3w-{_dTD`dUm2qqgUCS}6;jCs7fPOx zexBU2%P}2V=nbFNG1O-snBb9P$G*l(o(``M*~C_}!n@jaCXLmSIU-km@}4zBr}*dU`Sekpgvrf;FD;m&KD}o?rvikPm26Q@O;dLZ(-#7?3CD zdROcoWZb6845+VCcjhcHKRshPxN2ZvrrqRb26vCv=5nR>YJuSN<{b@v&Ce}LWJ5zY z`UX?i)RraI>FJvawC(6F45*NaQ5n@)PsQu6dB@tB1VW!p)BHf#qlZD(^d z^Dxa=J7D;J4sK|Hf4>Pgb8sv%IR8N||2`Hz{};$VO)<^3e-hf>#Dn4c8*mm6`)0|! zpIiwZRNsHsg90f9Ib`|P>P~(86z-HByHgIe$aBTHV|z~(s#m=Z)rgDZpm~Ry| z4y|QZu zhUHDKN@<*nM)tRoFYrsJ4>jy>@6JxiZ7lD6FiP$xy9xhsqa>eaKa5a8vOH@YCTY3S z-_|u1E^f$GT@HyNKufGqSFNYt+}}CbZnffZ;#H}WYX(;AY~u?lyDcaf3`R7RKsem* zYmckxYQhN<^S661#s|wBwUU z8f;dYuJ^`qH8EGMQ?ls-mO zf-td!R)B};*ai^*my>!lFCM4f4E;%!f-B*7r1{xOrOU1uKg-iYF3l1F!Bg-JQrZKS zcS?*ECeOAmWdMKT-}#uqaIHvi9;?Q8G3hFDciCOrV7zZY~L8 zS0Tdik8gbAADIvT>c;Gjn!zgg9B#R$>FOVI<5;M2*&E~?#22WlS5)Fa-W?9Cv)pks zTai)X&IuND&cmfG%JQ|Mqf!t#&iX>D9s4jd@xz3ouEtKeInT}!j+%@jA&G}|3B~rL zs;<5=q*odgTAkBcVJfeQR_d#xRs%5yG;;vx?a&WW6$zI^Ytg0C$c;)vsIsA6nOs!F z^x;_IDxIdXF>$swhj^)&s zB@_L_)*@ilsGX!X=1kNoN?RijNxbmPG+lY`6>uJMCtRr3F{jwEom=Smo$*T*YHPVc zBG-FWqZ5@~4Q|J9H?)odI&Fi#=)~}ulJ`uxe@!ksm4!!>HTBPaIt?VtR_3qjCG$XyUg=lZd@F(+Y4802K`@=1|sWsIL}-drLLmzpbG znT)H_TpE^^Y+e`c?crn?W*buqdxc&DA1ID4y+Pap$G4$?^vC%H+vVm6Hh3zoNJp#l zV+mD`8n>=08mlyw+njQv)KF;%RMxhYC9ups9CG(u-N=n5TmywVwJemt-IYu! z&_W3WC2%#q9!i0qKeDiF#?s0t+63+gXIUYJj|z3#%8_W5ucS(+u29;bREt>)NF&9# z=Bv=UaqEu;_iuH0HA`3Z3+#9D#*t4`u;=oCcmo?mncofL>?J~lQp{QKd*seQGcE}6)s)7oJY zp!|1;k=e!X{hGq`-n+hbZ$qV4rB?-vUp-}@*d z{{R3VLFDgBv`}GLZ>C$R?Wy^iMgfkd-bSx*G)?B@ZxU0+R>+0&1CGuS&H-or#y9{I zKm`Fc_LtYWh*=B{277Cd))z~vM*7^tZi>9K$2rnaB+_w1`>0Z`fP4|+XyjSlIMkyn zv=PsOvW*mgjqf&ZB#4bbJwiRbL=eM3gg*YAAUF$I0VdHLY?h!UqM4Fz+=4XJHu6=7 zwt0n-TR-0IqO|VaTlpdLk1H=^dZe51jU2=$AZ8iGYXIppMfaUa8WdCJ%g$QZ#GnU& zy4g(=+bosYABw>T;Mf{Nx}(>pF4>%Y3yR)#I;5ht5B7GG_de{E)E-I`>X+QGHD?2!gVtS_evLa>Nbj9P&k9fg;k(r zUMF{f{{*IcO_JCF! zXs_wLYKXj@8jHW7rAh}!<_^*D@$P}E2M4dVUyw`Hf7hPAtLwQs#fiG@xAyd(I&$Px zKgw2ngV+p5#Y_3k!dO{Gip_=60y&jas{y4v(+>5C8g0lk)N|qx&@M|##$8ic8kIXj zW;bXVCAtO&d%TjHGL16T#?har)JlbtZ%TgIZ+wa z1L6mZ1aX-joPGE!SJocRi1zJF?(7n|6%MU2x38)b6Cu*YVsJtO0h8QpjFvMdHys z{cj3sh-G#qy*B)PHm4>6IL?l3V?7IUy|k323CbZisnvpDuNH7vk;Vwx@u~s0YMObH^My&t%-xJ-JK9UphgPmMiKTrK{#_a zj8R~g=0su{2oiSe<_xl1(46Uq(vm-C)c++z#=@Rgx2@l*$)9=eExa!yhp{mCK~1pX zeOQ?J=WJItEVr^x;jYV~Jdt-|m!K^NXcboo;;YyWP976@1)BmG_zYkkLt~+!y=y0) zDd<61yOuwfeO6vC&pykq=fe%@x#w2W^s)Z;S$G~%B1l3kHZhvpa0=0|G+H#tG#Wg~ z@|CbSRlFtYf|%}bSOKViVkrAhNUafw)7r;PQN!TAbo`R7**E8ioAtHgUqgVM4hr5Y z)YNRURuW*obJ9zKJ4o+D=h)4oqc@F@!+&oX>z?$2>~6v{MO@Z#Y+&G6N2Krmi!VOa zJ9z5Qq5Fs4JKA&A@bFbVa9m1Z#`G5;JtN$Qa(Qs{+ef6&zG{4t`Z$E~wU?H#MP7$j-#S<{G>&Z`_Ep@vo{6 zNtSnGNeCuTB41=1`A?7w+y7^MkxvksS_4Ca$$e#0FKfTC=LRa%fMnxy5D)!MF@rUmmT%zJ+@r?xywo z+1P`&UQb*6pr}?`R9v)fXWN4^is3+@f&1)BG;Se8QwTb>7Oi1#CGH5vq%k)1>vU-` zxCNrGbY6fySV8ZoaY?xoBJaDZLBdi19$sw+#T=)60%6Wd5BX?cHD4P1H0RL~)#`p$ zFiU!Qqdd_h`|CGW%#EfsZ9C<4LwN;oAoE4hjZ^8c>Wu@DY_0ohQb=|%Lg<~ot~)w= zSvReOmq!h)`isLbTA2V--7YGV5~#DZWD zzFz`I&QQuCPy!e7pg{`vqj6ua2Mr=v#fOH(VNGr{BolbI_&BmJxjKKI{%mE{ zc*i>uBWteNFf4R1ntcU+ZWy%G+PUuE)FrKQm2If~bCm44N1S!N;$jW$$m3d90)mcr zK^<*DaK-;d#0&5!djDgQuL-a29rn8i1#tk;97{uDyUt{`4v8Ze%`YzPZfa5d#L5YC=`LT&3U*sno*7f zo~=;byuhdCj=*+$X#|~P$2*Eh@RYEAL&8>Hsi`O9`|F2K4)tBtKe`cQA0o-XaB2HB z8}w0lBS}oIxaMxFefXdD?fvj%$0gn z(AX#_qV;cb5}#mcT>T6SUrG{~U*$YY9p?^#)ep50-{W2{kQebH;SE-dEtr5Sy>%5^ zFbRLTg57ruFsx+d-3<9fVrs`AHSemnXOic-nH4a6y3kEDD}dTp;F21Ya8TBAGH0LK?P7c-Il3`DuShuS{_gJs&~vP=wc}I= zH8nawQU7o_(^2ml>yQos(3Xycf9crZng~Vy=#aanZAsgVQ|@SqI2&b>W`9-21-@*b z_4@qPE^Kpw&p|8&&OO^1Fn(}xamaETMQ-RHh$?v0@%gJ<8|_Kkv{T`5C|pyB4#j!( z(k?;|-zXQr$0T)d0l&pAau>=*fg|!wiBa)9_0}V@BjD~X>eHAgsL$T64+*33I@yDj z>2lWwN7BC0b?5z%niKX4cJVuR-~FBbe?Ejq{~0v;7J&fSyyu8BFavEX)Ko;vHG)~) z;@gdL+cC-*i$l(Nv$g< zfCLuf3dtqmno${5l?HO^gOD>p?B8Wud2Az(W#eHHe7a)}rVScJD!Ew+?>kO~Jh5;x z7^o~ukd@P+?zz30x|$hzYpuCLpCX88%##iVTz;=)$FVYPXMEBqZ4SAb-8nmd8cK)< zpVVVZoCwq>6K zGCkgpriteu-HvrohAAbmDeto0W%r+m57+U52_Q5Z$}GAvZB2Q3jkZi@DKnUb#N?V0 zpKPgDRhdjGn@k3eeaLJolc`Eo-$KXJ&!KaCb$NOwgPkk0T#;oo$m4ctwJQlgdk%Oz z08x945=S2`jZ&f9T@gwtD|$+83Qu)xhrQf03vsiS7KnV#;i4o?>cIl%sgX;fp;4Iw ziZF#&33FxDaKwXoQ3ZBbfxG6Qkb;63HTa74TDVVWs5?H2#=(a$Q1oM0kxr!vMdTKn zR$Hdf)VTcD_Lb#0IpxAAsbypIu2e(23CrFS5Qzn8kSbg%J`X@VN!m$0lm&lB$CvKA z=Swujzw{M-KJulKHaK91m5%Jk!5o{8;-Nog4}%Z<=|QC10TVo`TcWl3I;cF$HOshvyVIQy7(4a7ps|EnGX7#N|d3_KLU&okA^^) z*vx;9`lp>uw*cR%EdsSrdW?NZNth5CNFSs70eY^?S;*i`h_0N8gcL$0HWq`Q76;A8 z(026J5cT7j8PtCCqZeapctfJ-UkvF$S|UOKeh2Bq1oZg}CGjZnD~KYAs*Tz5>pzQ` z;5?c%tXd)XWJ^+oZ<7}@XI9V69FA|ynEa~oI~7GLp8-B@s51ss0Bp{_z6k)O@AlqS zyIEePZtVrr4zr?4-PYYLzw(md0~xvGGZK5C_}1Mevg5~w4rUZ3bz8hjxC&Hn&XmaB zT3AqkD@0=WBYUl=cyZ^#wp@ly5$aPEXV~l_1|aVOY>C6WEJx1pZ*Uu!qlOc2xZY)1 z1K?S_(X;kj&S;}nxG|%xA5fS;mS5`Qcyo;A4KzI44qQol zjgBq!(=ItZxIiXvZ8OD9)T2I96>y2ga)bg!1N{(1BNqifANbmc;os4y-V@M2f8Rp= z_y+Y)^Rvun&ZNX2xlAhDg2#?bL&VLzW4C_HXguGm=Y`EPwrhq>P;-{(L3$osTb%6p zDU)WyR32teUyuZ#DbtW@Ew!k!r^R5l699j8)0lUD{tYylFE{+svC##^BtjCcA9X0I zIxHejtEXWafk3kwYth8NAo^a4bICjeInE>sKyY$p6Sw~WfONVs)he$neSn$)8n3!( z)VpQ=ue8Ryo3$M7$@8NDoeLrtkI?R4qtj5)mOOhzXmCy z+DOj)8&_R!-ffVTVWVj3>}+c8=xDCp(L!v_-wx-+ty>edJ6l_KShjCl*tKh6+x9?w z_fWz8uxm@W_Q2@KMM;QCvUCod0l%X&YB;+;whg$(0kuQuqZCL~82ZgumUqIS(WsKg zBvp2;Q_^EohRXYzCik@h(7RX*eg`+`8Ab-|qc%mQai>;QOgiL!_JCB>9ZdJVsD~0g zlMD!Qb`0?bAp&B-^7HrLvlQpl>;mt=^UJ~9{;gta{-Hn_vvG;-4Fs*naX>^LI6bKNq5JdVTIMP*&waqG}jgG}EpQ~2wKbYCo>Fc%?#Z*eW zzI9M|_NAhcmQaVqVBI7?esu0YOsiQODHadRi{eG|19p$PDF$g%G;T)vLJ)BWdb+9m zw&Ak_WwT`Aa~N^Ug`U5#BoaJ}e(!`B38aPo432w^pq^h3#T>MAHBt5oC%!-}y{!`f zw`=3{rcHljYo-87Y%*1sXfjn?prlrHTgZvJx(SYs`X6v6MO@YuB!%TfPH8Upk#=bh#g(mN8>gM?roIeta%}YCT6UDZy|eME)3pwGLPbVmOV_ z8jVn*IdjZ5WVH_4aNHw9{27iy6&fXEt00N_JC+zPlP@-n+RvhPIcP5f6z^8AXq?SClR~#%W77yNenrvOk}pqP(Uh5dD)EuXhO2n(v-7SBold0{ zmiK#P;0MJHrzHFNFMmwta7eS0*Ihz-R&J@-SCiY->ZQac9Ek@BLO|y14}nOa zqx1y;UvG7}$O{kO$Ei$*vW6}p(2Ken(mPvPcBa#CW#5@@?a7`7)&}rI-{#GI+1lhq zBclgu>7_g{vA1U&*;|68^MnS{F+hpQ$p|&AlgptK^6b}=uTEXsuCZ&(KCii=OrzAw z_K3ij(X~F``a!A(n#BsI+FWXiTC%@nd}G9{z{s(dpiln-+X#fKLdCy99~p0$+;QS_ zlu3fL)@5HCPkuvg0>`6lkK08TVV_%97xub2XY4-JvfEANv(r2%g%-eTw9hO0Uv_Ch zfnC{aR{B1@TIO+4Pz!jSW$)9qH6s1S%>{jB$m3;49tm zm<)s~d&FWx#TBh~CZe3PD)mqr*)EZ#7z)yBa_F#g^cqU zcqNX>W9ao%%P?xJW?umpA~4&*AlGXybW2H%E*5ZXA$*hpj)jHemdbH@7S6{o$5Mn0 zT(h4B*;$`n%~j)6J$Cnsz8ZADk)85}6wYFBxp}LGGisHRC?dKT(bMXt=9_ob1^Ob; zt}q&fWeT&bY1H2xaJAWV6%+DwCzd*Myh?WEc6hMbmT|huwJkz&alUoTUG6SRWazb3 z3EqZWGH~xzgG|X)tOrexCr(j$9NA$29*Vy>eA#8-5w}~O-PE+fMNLT8rdIHg5~?cw zhruS+ThXp?K^g?AkIH`ctsl6bdHWrAu-<>IuVKcCoToF5K5&9fK>|m&lv-^u1+kt< zgrGAalJt1$lSxqb&zTS2GzCZUk-nAN89vH53);m!DQW4u|j7?shm} zvafwt3fpe(tH(5C{1UV_p9hv8ezyk}pq2a{Y`sfhM|u>Bfe_EZ{otzql_&^UQ5E~2 zijidR;8o=Q+ruY>gkSfgmO>@*@93@?u73eXw~cQOQo}v?<`6*;4|_aPcyehk{7Y@* zu)^cAD&ncjrs<`?t`rqP^}4&orNs)n9b3J`i^$GSC#E?bV0+4>bkH>s1w!xy@BJRji)K@W=)JF6^H(C{9@O}S)aq((FlF0`_ zS8|}}I0}s`io^x47^LJ7NYeA^jgy`_t3;ujx}x7;5~*ax$?ooCiP+m@Zy&PPZvReq zDmAE2C%aPe_&mqXUx~F=R-%y0N=w92g~_C}bxqZ_?rr?j*!+eq z>HefKxWGP*?kSMlrO^VeS2q?*#DSkl4FQu6Gg%`5WIvOa3lco>)SX0aUebtl^vEX< zzV{<0V`Vowx3_l6YM!(nenej>kk+$Cl*BK&Sw5^24IV*qJ-G9aGVsHFoqdd9jX3jb zjH$8?)EYG>G#_3L{rm5SW5^s;qm6?@vw&Y9?a*86FoP~Z@jUWjKi%)9w)nQ znBR0`9}&;qRWs8QAP5l==$Wahfp=w*@0}+D-7^qd|I+K=JygLJ+0be&lS2qS4v1%Q zWp2@7t~_II;uMQd?H+8et*+^Coe1|ED$D;C8}v7(dpd$!e{O9Eq}u&)t^RWGaf3oS zHXdn2AtNl~<-i<@UaN#Z!0JIX^0`)^L?Y*UU z0|0d!fu#cQ7EpqT_2+Mkh2Y^8;Ug)Ov4k^DX0B%5z(Ci~Tnt%iA z7DD&1huXe9!)_tcE+AJ($fXC+O=4^>I~I;Y1}9sL9&X<(5gU~zV~NU8)ikV6ghHN{ z#?Fl2u1k=X4UyW(aBF8*cWUSPjy8?TYRiyA}hy0tB} zIgPTA;a=(l@E#vZjs*n$4EIvAAdT=PleG63#WmIRDCxCg_iC=S|A3(-vhxm!(BtXo zAUki9kZm_hJhKYkol`!%_3cuJLUPq7o8!&ErJz1$f3I*9Plp4%8z+Ex&k-spV+qFN zohL~=sj)0Y*9ZrE0=G%_Q z-VBaWQEfWvNhrV{*tHGpbZrAk;`6?5rCyu9_RbuAa%f>?b&aXQudw)6d6R&C^7H`E^&usBy7NP&B!Krz_0V=FvJ!qOvzsIzXukvfII$dwRME~N zC<``7v5A_$)EYuRlRMC}2d&5+7#II6jEh$ZTvQxck7(n&@GvNRX%};5lD=EQtx6>R zxCwxpKh$vL7AgXM%LnVPoTp;ncP`Fu*$jTRI5)rfWvE&Y$AmZRY`?gNyah$Phl+08 z)qb>xj1Ie$4sd4o9wGRs@S+`icMG#~!UJgZyuD+LXid~L*tTt(w{6?DZJW3Iwr$(C zZQHhO>+9#8`6e@y%->1Q$@x)9W!J7T~KAo)e_OOtO53!4aXOHscpFeuP_ff*bc*omuTSB9~-D6-qxdo;~xRd5h zn)iWw)$htSMupANJ&^5@tgaa_2T^eXJ%SZy;<|2ELyzH**}>d#c^#Z<&Sghgh!|*J zH6WHi67(WYG>LPbko;q$gZuh&zDO8V~oj_AYIA z<*~*?Dozz!-VPVuL|wqaq6_TyoR3)1g~wG6I|lptf9%TzJ1~)@rmpZP@H{Z85kzKp z?x@~q_XqxbqaiLTodg5{RDoB1_#tSY(gHkw*@bp>!b&(@jJ$P~j2i`KgUGJbh zfUIg8*DR)7O8vO#EA1G}aLLSB)2ybcs4s1jlzG$lX_nDedN8*-P??g6s*-iHo5g9B9`P0+Neqwl=DY<)LU3&Gd?|Bl&oT;8Xu$8*ZT5scXzCg7T$LCb~l+8-g@=6 zSK^^qHqPGJ++2IPOM^7ZZq)eL(Cfo?t@EuoJ3E8buDfW4>3es(>m?>?tHWWC{YgOP};{buWw#9XKy|t)0WeT3GPTXC$JgL7X|qX7aO?Czck2M{LtjO zo%3&m(;?k@x<6U z>@k$upTw;ESb&Ym|&~ucyR>tc8nze^S3vx%QGvdZ#1gkgy+}y zHZNrY_Or{a8X^v}j%h2{FhX+E%c?0*-o|xw1`$wjbmPX98PbcPeg7(h85fZq;7t!L z?NxkDhNCfgE!=G`yYK?9#&4Mh8RJZvR!h#5(qYbv!Ax=yk)Jtj^RzxZ=MB1BO_WC3 zU~#@9MOs^AXu@(ueR6|(RwJ%;^2)e4b%aSiC*K;_kE8Agw#B#r%XL|J4obrV(4TQ7 z%ZeK+9o%w1o4hP~Dpf+i;j$-b4q(hjBth0}$CUqTj-3+1hTOkN4U!pi|dj0AT1nd66di8x<0)WxJz1Nc+b`vGV z!BmK@9H~>YM zzncaAO$V^>vkAbvhL1~%a7)O()_^^cI1yK==<2Utr?VMz69(O#{)a!#R)CTG568cs$@Tt?%nP?=V5pvfFsc3QQnEy|9v{xK;%bkwK8Gi9B|M z6aXMUnjoxQjLs%Y7DdIM^Klt0jk4v%QP_>lUoAVKj09(&fTd6R_w z5xkl0tM!GRW(^+DzzxAPY=9Ys_tbC>G#n3&LnbU9=IO^H8@_Mg zG0*tVyXPTSKWhw(x7Pl&Yk=4t!LGp;;*V)FruWJ8gCcxBC=<%F5;eea;y9dgC{Ptm zS#O!1n^t{Js!wrA>opoe9tP0_T7X#n%7j5705=(>gPGhvSwR2eQ4mCtlNHsPo<-a( zZUh)O>o8%~7w~|u3}SyUHI1|i!d*N2l%zK7!{}-rovRKn?Y0~PyOGuzzUAwu=9o91 z1KjP+chca~B4skv++q*g6r&iRm95n@pJc3<9(;EB2DfQ&4e;&ot4JI|P|nXe0p`C;u2ok7|feoQA<2 zNPZtPC9)6Va8f&4zSXURXv!)X$BN+-`eqch#Z_G95VU=lK5>#50Uw)h0S^b7?vhm{ z62^7eRoeJN!B!9nHQ3F&9*DQ25+B(ylcDJ@9ClMmSx@bi-IqO$h*I6MyVP^edd6UJ|gs2qnxZz~fVyJ~r_LbSr*ZH*IDN;hb0|Q=cN<^gklzv;z;p ztiG+t_)n~GvR~!&O_W`47^jo6fcjSVF3<8z66ri_E#$Qyvn1XY4BjyG!5u@Vn(BZSC3R`dyN< zTneYX{If`Qd~+{0clVQ!Yvgp>8h*~AH!5!0RY11$p8YO;^gBTQ`SYQhEXpyoGIfA& zAwh9qmT+L21eI;EhgS`SycH$5?J%WYZ8w!1fCIDn7P^()?ACF{T&6YL9+Bp}VxSg& ze|uO8e4VS!UFZL^dm?Cbzam+?A)O2NSs`g{v9UOv9pc%+Z-tfiBB@q@uSFMXq|ZuH zq@K^=KA>w<8ffv`>2Db;YXRi!1D3C-0d)Rei$x3oZ;+!oyBJixtr+sET`WPOwbdhZg5zMO%zn@?=nv%_t!As!>ovZE9O*ti@$iG-*m>%MrDEM)zj=%cBQZ zr$id3-zHU6e-?>mQB+7~?pnUc>aMOaUi5P&9imFv@|qd%93ooXsLTZ_f-&~c`YWPm zK*K#!%pqRP9#Yu$h<}_Ns(XBw5ZkSp+u_GqE+KimK`5c`o?#V^FoKQU(D2t_`vvJd zrb^$AU8I~Nt2Iz5=Ix(=bFC%gfx0?yTZTQVOrE(7@hy#xToe5eB~I-Z(&9C!qDl=Ux-+%-O1BwBI!5?dCter82E3D3 z;>*`M_hFQ@7gI>bk>#+;Yk7Cl&tK6JIKm+^>C zc6>S94!Cim?3+#5M>ja2fCDwGf&eu}e!4&@jy`n|l-9^et_zN4fRFTXO(Av0M9A6& zRnC<(&Wx50rmz_y(F+!WfrT#S*oej6@z5RXb9)~QHN%CnUFompv) z|KgWb-gNv%5@Fz!E!(4Tn>z!JLn`&G+M~5! z$t(uH#85VhAW37cN49o&ftlJIP4jUhaAwDe*s~s@%>CKc|#~ayVprP_3WQ z?Bj==!wbS2oBfv(djy9>L`M~2yZVwj`nS8ot<1NxrMpgmCej&AZ*lcW4;=};64J~V zqC22u`{4VvCPgsy>Q@T0o)FTAm`4pyLuhg7HxK2Ic2}83k3?+WKYY8V9G#`lPN;an zOmc$W(=2%b@9=!_^Z>y04yA~+F@u%B}d=gUs_MtVEQx0ib=1`wa*VQ=SM1xZW(aIlbYFmg<;MPzN3cU+%Nn4On>8s@1AP z1Lhi~`z#Fn!k}eG8iIiH^)~9FB1V@+@br<&Q~IbW&oa(oJs7?D`8{Qcb8=eY2td z1R-ouY?-1D>eVj1x}*%1?@D&Yc-+#w{;F_FxHQ4;Z)QE)j%Pv>!WwboHm~ zu2;`<3F+PI7QTyG6#-wg;+u@QW=o%~f!Y^ix*(RI?)w$hRjdkS_&m>Se!W10qY3Ut z*?Mx@WRf8KQ5S<}zx7Kz`*vl+`sssCl_pYe&vaz?&k}p__)_y*DW2iQDlkpCc2jyv zIjrK9|3Lw|^8Lv3YC1DnZOD|{wHM}6+TaaefF)6|evf;jQa9Z6srBMwJvYP;))VUn z^(C+F_>$NT*Vx94WoSW=J5oNy$qjiymLb#{o4dip068<_XHLFm*ZnydBweHLIt2jB$c*+BUogh0#SoHlc@e*T0$*XO30h z-$;b)j&|k%YQ7R6ScBkcn-BW; z2;xy=8H<=`7y!58fx?;RWtiS5C^I+#OE|C=1GpuI7k|$t+_wL7FMjQ0UC#|D z3kCRU$a+p-X&iYxeoJcAP(R{{-w#^0>)MHb-k)!Lj!9GSr<6-u>p~t@k5C{8#OSw% z2bsY;5^Q-zYEzN#kYIBZww=s~Z!d72?!p=>G2e_Dwl!*F(XeSic5t=X+w^(>cEP~} zl-e*_0jp7j(G)7nO(H1=MZeZM*qE89MBxMOe@=-%QRE4|SuwE*>bFGLn0m>5N!H9( zh3P&1PNm070((W{+x?j3qbusuLQ4|#?KqZe3y=L1VyE0)_lzjALQn#{P@NMLDW~Kf zYKpu#A@tgkbE6RiWR{2Mx6;}AQJ!xDE%oA0*k)-ty7)Rbmug9uS=ZmMV2=nfCq&<`l#b%uR%M8h4dTR|Cp z73&Ot16X@gENmwnV$h3Sj2YC!3a83mkwYs#4ZU4n$6!0N6<(uR(dP5WKDuU>$pC_sxjZQjZ5!^$(XVOIF(sck z(BEM&b#X^|a=dqYj`d{LR1Ew*(pg{G`4FTNU0g}Y%_IjoGCx8(-I^83ywFyR=@9BG zxds4L#^1#t3U1xxFWFGi(XuF+1t-IGuq*EurPcVB5Q`HA5Qtk?r%^y6* zb3KGgiAW_-W#Rz8ES)3QM$Xc#h$l!?m01ad&P>vU>San#WdHCm(`0gYG(J4cCA$Kl z{d4s|2@pN@$*QzeeEf$B8kIxH+=<8@O2EJ)-q5f+6l*BBb^kSWf;U#T@7EC;FS zQTe*$WT)|jtZN{5hF_B!Mm-GK(HYJA-Kb3#rq=uDAKo!2|7r7;yS3WYNY3j z>z#EJg@h<0KCv_Qs#u#sRkJ141RZYwkw5{pOk%F(b+cNga+xiNYItOuY-mIl-tnQM zuP&s9`4{*O<@#YPbBC}-5Ac#J->H12PhG$?OJgbX%Tz{UxxqS5TWZ+ld%Ay@2l`HQ zB_bucie;}e4XuiW(3^`~2_Xa5u)x`0$JsY+*8^~iZrrLx=}KBpSN)f|d3HDbov3&! zhUEzqn*gTyw>V(gwWlE6v{$ald}0+~GHPnmxjG9R3>5?W#c7D}Z8%I#D5*OZ%A;z)?1Hpk><^8Tam4VKC{eWM9&LmuOe3Y0MA2x4ubuI4xt zxd$_TqlwJfDuO0_FQ%`a#!llud>f!#lZ9`aop>rpVS92YQWJTa3|(J{>HW_o68#sk z?cNEc{!SgRsW&<*R+4ae>a0lQcHuGK3ee}~)h-c`#f|87* z4D^cQ(UZ|vHJ`GS8#W2k1fNi{jX~E5UMHWc9BH=s)5Kk%oUx~UVH>CW^@>jmkjUHs zL#vJHfUfgCH`l>szG>1OvmN5^Atlp1eDrK%S3ejZZDXuz-E(>lJSFHao;cXmCjRN- zfc0AF_};!X)2!l@{^`59)AgcIspOm z_X=vr!ci0UFUZbVGwj)KliN3pZVqJV1Yl6E3iMZvhnn>bT#i#MepeF}>wnA+d7PaR z`b6XKUd@Q4O^cP4IfU^#Gwp~bJgu-!Ur*|P zqD{*N>o=H~#;{j1#YBdK&~p$8jvp;(hVTcCCgxMz+~W`-JI^F81#jBes5Dc6M_21F zN1>}xMp_CQ*MStM8#4TQ*UQ1yAcgu!=!q0AcxVW%!zXce53&CE38pY_Y`!bVrY{yz z_${F(!&w9{-3R#gQ#`ok-Xy&@+-D{~-Jf5c=YUSgJ|2v0AAcU=X?#6FD6n+$^4}95Hh4UJ49uZ~2r>Rt)e0Db1d47A!eT ztH`yT!>!5uO66#`bSt4_MzJ)I9cM?b_A?M(VW%=mLLk~zP$ZxPWhf~S(lTMd)NdCy z3Oc3oiY(Kd(o)4LR_Y1kB9XNbQ>Qkn6<$|tMvv|_j-=VNNU#D0YPH1jOHcc7NsGR< zGhQO7E{SPqs_YI95i|R)2l1EhVIm-H;_%1Uek0VQ8E}(?*UZrY}5MHZ(;VgbDD$q z+uelx#JvcB*{}nU(e@r^97fLb4N0%^=J$fzI4m=!&k;#?!Y#w_ne$T3i^lllpUS^< z8zAqzm!u#X{%#qG)@rM>AKmM4s0a zp%JnB( zkSzR>Fu6+LAa`g06X(O@-`hnzLFjGiP-(qRWM~M$bLDv zoL>pU6&5E5V8&9IWWXwbR}K~STorgvwprC`EU^%N<+X1Wv~<|H%i3MU@^rGZ)0?rF z-Pl?H=6#!{z*x_Kx=8~nxII|Rw!h*XMKGEuEGiqHRQsxIS9M#&;xR4M=#zc816$Nq^Lgts#QG^ZE%njbuaAK+~f?A@nM5yFRi{Ery0 z1b8F4jGz?zX>XHX&am!Z?#+~st>0sQOAwmaDCy2$zH?C+`XS}Q1N3vc6 znc~A55m=Y$YvcS8jTLoguNu+0Wl_axF-5>m9#!Hso<_F9n7QAL=DKf;rea zC1H^1CCR=&O&^3jp>1)Q?GfC4RCjg-8xGnT-5UvEYUgG22l=$88t{MdDy6+>VLhuV zCeapEGmeEB<2s7l%g1W~4xX_B)X7+5*hoeM)ihy=qiAu{SVfYiQ5HjBs$v?G!Kf2i zpAzNOo+zC*%T+BmvBU&x?7rjG=~#KTylS-B2b zeLO~IIY3)@J*=k-8q14(^J1r=c))oj0u6GifB;{TWfQT7A}vVo6wQg^QXztdk;3X? z*Hv{jubI+;j>a8Bm>mpvrlk(c3?qtR#^_U zq8824%2lG3#JU6_0_}Lv5UUy)J$bkME;v|+*WYb-A2Wqrcuo}{OB8o8n3h~jmP5Oc z8X1}xACHtJVSyxNhW*aAIIM*=z%(zdRWxt}kjsK)6G|c!ho#@JnwTzZqZd%4qqL6w z;PL?qQm**+2N6ZQbZZRii4Q?VL1ahVff+9R2RXKBVIe2|?S8~apXg)hJtm+m;)e{t zT$>NjWK;GjP^Ubp47H-!@|U$$?=b_LdhkdxOMocOf)rL}D@w9uSQ(6_MoPOntgDXW z43)|xXhjAAcTAcZFdUG>(Piw>*fI4PBs-u0JNUIS6FZs(Yke&yG7P5^rKVR%{WpRZqaH zi~y=nN$qh{_deyarcZ<~$qzqLxZcqcu7n^t2FbvAK^x-=VKTD_7v4PEF?cG9L8;*l z&n{s>`Ko@T1k7!*$S9BBuGVKzM@vtS$=fb#2VKgUGiw*osjGs-EU&k&in!$_ zFcB?97yZ+}6p^B|i}}oyRlzTw5TtcL${8)GStD<|iyW zYqxY)YY_6)8;!?m?;&OOL8@&hAY=An$EgQACI93vglyj%GI}ODjX#J_jgvC=&)!=* zC*T%bcdAv3<-sn-6ZE1icfTchweXcZmMsY7K9vAvym9N?!a$K4f*wm@!EjVV19ntg zBp?L#3%=#TlkZ2bzun9EI-H*HTs`d;g*)z#o^x!3DTDSP-_YlddHU1em%k-yE4~n4 zJ66ef00xHiMIvVoJUq_~8CDPgq4d+h0KK2f#a5c#E8aED4yD^sA^Jc#}*C9Td_0Ag-@JUnpWo(*Fpf1RFZD zXZ_461-_r$3o9!drVAcglVn>q%A5ycT(V3|;?y<`&58))>qLm?6iZvcN1U?*h2w86 zM*>&_Vx2|%pPd)w_W~EUV%w98;Tl5;Ds1f{HP%aKr1w$gl^Qwjb>?FOo2cc7A&WQsZw^ui!YQQ|5@QL%)o+OQ<|0rOW0Wbo`=(&k zgxUmz=|#-lY1JqEtbbmhfqSVtb#>*R88 zTCs$MbH^WSmnx&(r*caI;8?n#A|$u4e0<#>E@QnfZ(#-PtjufDfv8wE0Rt3`ES98* zc8!q!X_^LUJNVZo&*zu!g>a^29Td^hOqFd!zZ_XKcutj|t5{hl$rpR=#;&<=We`(U zDQlb!Eq7^Gc45&WY+DJdp_5I8qwT5kQNy*(-ly4Jb{PdP44#nRS(Y3x?>)#v*>+!T%#()Pz6oVFbt#Q$yBgjR@ujIv8h(4e$kHtdq1- z&I%ep7BFTR((DqZS?r3{pQeaUn$<1-IzXmlNvIeP&)UdB_yCTrH7R0Dn#lW4o>OK! zwvzp@CmM|}R1=K0o3lU6IaY9Jvki{bYZ{P}n)O2Y$T6*1y$JF7Uk&UZ-j<9Y6Dp;U zoy#({6iG>E2A%gsUrZm{CD;afir7DPk?-zrVv0<}tkvjY7jg%851Z3Z54Qr%$2(s# zlk;p$^7(Zn0Dev*?%O&rDEm4Lt*7&feNT`2#$AQ^8I^JMn zY^N4}^A$80XN-O|z6SEmA=!+$E-3u1Yj>TY@Zv{p^j_Wk`IzydXL_;ndl+qkcEi(* z{eH5gQF;x%hg-xFqE!&@fw|fY<&}Z|pfPv-vnC9B4PcH*P@Ya3HkUrVLJ%t)L8mPO zb66cie;(rY=leo zLM&oft`=$clxUf784SaMaHD{oIAy;oQxi5bmbIi3ae1J&vw=}xfDNFpFD@IhO(6Lz z2tpf(R7$IA+n1)(?422B?_w#j9o5cK9KimJ=Nf6p*^j`~i>Hgw(xmsrDq(b_SnyF{ zO3DTA-)6cpfL}t%=v58?g!3~?Q;NzsAAC3&K&h+U8ooNt4>juatNyiSn(r$?=vDa0 zxn?}TCoCOOw*()@*4Yg_YPajZVHkX;jw(!p>fj4rEw-W1wRS7K#zAGZfxvZDNudRB z=MQ>D{;el`1e~F&VdM7X+&THlbLJvqG%$GF4Nq9(Fp6@Jq>Ai>K?Xl zZrvrC48{q769 zRyCO?Bu|l%IowwlZnxcstGP-}g~7&_tFG)ur6R{-9vSfV2s&{6U0O>HPiUxd zR6&d{OP)q#-v!b&sUn1iwx)d*CRlZFoD$UUK zOVhZ#K;( z87V$u*SQL+X=bw-mb#2PB_gf_r+_YsvNkw?E_f`yrHtUCDO}nD6O~^X1y0Cb!gJn_ z4)jkZfq$#Kr?@r9?L}QvRkVTScft#f?HtL*x8#cQx4uXWcB!{Jt8ouC_J+ZON0+Z} zf_(r))r~|!^GADaQmT=}zDa|QZy9%E)EgbuI1N)E;kzvLx;CCf+RpSYz`J~L-F0Ba zaI!B;2a7!Q#Zsn)q}OeE{`ikEws*Z9#`JTgbuIW=G6({8fAd!H$TedtOo4J*2qxsg zPDBuKS|FNq6|Nh8hsmm>%pLY6^}G#LsYlT}A8GM>#Mc_E&GbF;3kQ)5fR zk67ipEl)GUT_OE^3BdW8))v?a70^y-E5FkKK83baba>9d^_vG0qc!E7<;jE` z1S~nM!T6e-Kxr9POZ!xH`z+!AA{Q;%SCeQ4eDw{VYyd*Eco2@&U1Beu z!Emb;0~0Bcxl$MDsIjh>Ux?GTpnz2O%*Dt8!9jpzULrmHoidMWC|R6y(fX75;NRn; z2L@{-mK~63tKNe<#v|2l#OvDd5Wj4~rW==nA*O$^t748jsM-wgPOHt^vFC}0oHCNE zeu&lBxV$aq4In|QW~I}x&D%;6yE2vn;+^g#yzg-sm*ngwm@87Z0$EyN-1?3iM*N|` z(|)8QCFd2Lk6MD1n2%EY2jF{eZy8dgZU2Fv8Pu0vy8LG8qwz}1FptOSFD?O`m16!# zpVzH!o-mmvbYDB+z@g|6Y(jADoCHGmw56FGhJ_+_l)=EW7wVCtYO`2fFG218`TH`# z-n2kpM?iYIkZO6pyiQ6Kh)`fvL-ofz-ucWCPgjZyo3lpfB|4-PJYamr`2`y(vAoc# ztBKEoN(O6|x$jNVWApH^jfJ+I338#C@sd`aoJfSDQv%3wNroOiH%H|!c9n*XfT~75 zX(GI-e!|g2-4-~vV&xYJHAT8VUrX#Y;21qM(z=vasqD0gcd(f?6sy=RuM|(x~_;EM0r> zceMh7bj$Q3=a%{%U8Jm@h~aJLTC-F8y-Le`CLh-W4SV@Y1LdSOR#?xqW^AF=r=1*m zMU%uZpnR<(e5KB%oqfRqGHi^ho;SYl+aHrXed=b%Ef~x)YrEn6${Z$q`G&tkQ1&O)4giPAg~4uBTATc{?k)=f5S z3@Q#dGzHWL5v#&}yEZSO$b-vdn*4!-oom3V{RXAp?I_%5bnxf>T;wA+RI10rO?Qb` zn=7C?wohCqR=tiJ7)fz9C84zrIg9%VGqa%kdeTXKIowkYMo&FIuQF0x$fJ{BCtT&B zEI!F6J%<$ry;1w91YXBSiB9OX9l1q*DW`HP8i2yU1gHnO)@@_9HzSi{c7{#!A&5)6OW#Iu!6Je7Q%@B%G4MiEw)w| z@JWqi`B*B&rF4A_Q;^@VYFHmstyMHxM`gbD$kuT{k#$~iy_^VF9PAX7kk ze9nERR{IQqsJ^<22z1B(ZpDZKAn_&t`wSZ4K>7lMdLdn+QB=3~U)u7LS2b$RFO5N-dZ}V)8gUbpC4OiBe8-&d?W}A>T3z}Aq~~$eT0`+n&!)h z-r9dbu1r4HICDgxvB_pC8F44VZ1n%!++|%J2!5Fy#M!9RFX?K}ts4EP?QWsSs>EBCSTYyn0(6j3=7Ds<+nAR4-R)&9%8?SbmvYBadve%epzcfsk|V6!{0k zTnMILWKqE0wVLe=qafPIOK&v*D0T!AQE@ci=^O%AiGIP3zje3L-E!ClYvnMIP;v)R zkN9Oe`(ciz;LTYchB?^l>$KF!Cyn5+~?y_%cYnWOu;CNMLJI0hFMbPPf0r z)eIK$8_ie2O;@bfRLjHL?zmci8|UyhY%hn;$GloX8`3t@ZuIH=q!WPAMR9kPy4c3pgg?fHZY_R-Vr~n=Ta2J0@CZ_Z7ebPKU%rEK|)vIvBnr9 z+%4)>A?4|G?N;Y>OuEo+vwuf6R^(U8`&LiL9@IDYyQdzSRn(JK+&{;llG-*@i%pkm zjb=hkj1Jbxh>KKzsj7aOpcH5)UBI`IR?*uH9yi^?8+kI_KBefK zBGEl-7Qk;@zC|SY{4utxym_8f$ELxYd?S4r^ZwB{1&b^{p5_qqy8Rh#E&9PX%I1sq z*p*2=rTiG?GBrj1IJR_aOZbxC)4=zt8NdFZxuj?r6VDu#^_O!T?X(er^3h>Eka^VF zDP5L}11Tl?{g<5<_JHuHvmp6f#D z7?Omc??DQ~LKeRnDyvtH?qUTVRTs*qCkZkXV{g0lJUB_5mH9=%CTEo`>2Y3L4HM4j*|UlGswD5}*uGCtC8 z6jY(NTV$eNeTc#0TG{rxPN^u{8CI7A)5!eWkxopP2(C zKLb~_&EL5v@#S_!;uH1ltVWM*nbn@aJI)$U_-=4h%^}#q{g85Jc#f&XI>%&{Oa8*n z?5XYjRr1qXz)>Bkn%>7p+zw9y0B{Gi?o;}Q3IM=A=LNpje7uHt+}ALYwo&F&*pnRF z6~G$zwZ#E*J5#fA_!_e}(n|pNFAxHmP%@GoGQLneflw-%8#Fu-!z9vyEY&zXL7HiR z#woE(zDP6+Oh&WuY_>=&#{*5>ILt&<{RjxXZH6iP*3Sx#{WNx<+M((~`v#1yeQe6s zp<<);+V$E#0RPi5glp@__N6rieeSVA=h#7x-Oz6a3>K5sa52>Z znM~#`IHhyH$)Y=*!D_k_G$I+tWzvB>(|J6>`!TVE=Rjk|Vd6oS>wpH|{Q~F4ebi<` zwNkUecA%Jc!}W5#;ieOs&M`%duI)0sLibe$fx8qO5I`T`^G2Y-6kB70wfR!B+Cbx#z-B5`h*LO!+ov5*Zk9EDn;T)GV^sa&~2p+dF`EGnJZYR)18wuVX$P+BafpuVM!|ya$E91ZK!{>S`eM5PuclndLYbbyv^M}d}H`g|$dl!Z(L?-$sn z%Zv{^_v5IM9QV_t6Md(&7-!f0I<{Tc!*)pL;~aU8&)rf>hBe&qkiqPY&$2Qrb1W9q%|HpI;;B@bmNpbcY04vIMH$*B=6Pnj zzI@XE*Btfc5s%1bayni27g4X+Znit!^c9fL=zb!Dz+bok0HA=)ysQj&`$jwJVJloM znp$rxH(?eu+iVO^I-CAcB4(B@VAceCQe|mi)>WBY=6{OQ!s9qnOle=rS7j-e7%)i* z;Fwe?*=LanU{+6H7RiG$!+X%^6-28`C8aUJBn(6nWk{4k4jJ-B!O0?Fm+FX}~dufc`u{NOlT$clkbBGYa(XWsnN*1iX zA4={o94}55q&zQ99w1#mN*1DhKU(4^7*0_fs5nkh@=vn7v^ZGvytG81h^iot3biMJfNc9|aflJl2?#mIkj1opvQy^C@8TLXskTqD z(mnxWYa6n;wpW|8ROK6@Q1#e6;DvV|CB}OQEa5)jpm!gm)_n+W={)#VJlZABS=8fs z&!2f8H|xGlvhzL(2|mx-o|uq}TEd7@igrw@Dw9+TJXa~8K`j+-qEbfed7Z-lzQ5rU zxYd^j{AD)0T{78dwpp2J=8&J7gR+UQlW-G^H!c)UBGU<$)~G)kO(NIx7ZeFk8jMgh z8CNM)F4Bxz7auh09M;xAe+)`v|OkbDxur*d^}&U>&^X* zo=7Yv+x|kz1=GoNrvD-Y^8YJDh_ZFs9j}I~xL)wSA^(AEa{&MV=+mFcnEe{~_xIgs zj-s`~wVx#n!F5<<7|F7qFXNA0m}bAoe4uMRji0D)Jx{-|Z9PlgxNg1B-L3e*bH{i+ ziyO&yKTkW+bw5j5*>=Ckdf|ONO_=F^JQM5SD=SS4D;`Gm!6IbSJK!Ft8%d_G?#R`a_s zVXzpj2Y)4M$)wX6ZH6m39?)ns>#c{%SuR+u*XwOYs(C)X-%tMYJHqd{0BC6bXGAs| z*H7!;AP^`d7=(gBkm!VpiRKK3Lt!Zd3h~C2ibWDBgi6WQ9F9k0YPs@phNO~7lxlg3 zNtP^@OJys$3JIpPnoSlfc}gj^Jf2TyZ2GgY2E?LKm}~~~i55(zQ)w;wbMYqBs#O{- z1`EkHT&`DZZo9K_M&z4r(x5$%V`mR`XKn&v^p37VFE$%@M6Va*gWV4eOQx*^bNR zk^eJ&&*$@q-p_w?uO2FI&@U2-LaG_5?yyfPo=Bn*u52-HGMY%L6|L=Y zk4m9js2=uztv^kda~AW(LX8Mjn{}7dPkPsp&B4R`Pj1$c!u-X0<>&cMX(2T+HHa%? zup-#pM#Mx`z&WtsX*&5QGWm5($qWGtXo@R{|7q$l^7Zu9wPbB^V)VOYw2{rw$hTLq z7LKg%cKIs?B~ghVhp_g-XPz89G9#9W z@tntoslZ^zEjztyt0bfy@#;kf@(h0XD;GbLmrD&4m+57#YFFTeBm9O}Y>0anR4P3V z`NSiskou~dy^!DhkE3pxiH^kysx0vG?c);FNf;=xqu}%?2F~j=cA>jbk-BtmU#tSK zqww{Y!waov>yN9FnU%`ohVl}3SzE}dM^0ueF9$&yOZaH(gKGjhW*5_+=eFq4)aUL8 zKwR%yP7KBqdr?v2OK;{mm5UbA^v#mftp|^j=c8TH zId7uSxw{(rNvmTgCdL4X>8tn6Ru}8y|DN^6t9d5}8$Vea3StIE>?XjL?5@ z67Vo%g?z~jhvCOKILJzj#XXH@e;cK&Mrq)MOoQA|luTsla9|sbo##T9nRobXpxvxbsoHcQ~kjK^cYm!`m**);W%kQc1=38Z%8dRU`$Pe5NtCJ#lHvQpsGyjsCvDdj{8!sNQ8lu$; z4lmR&-MrtgC#t_L;ar9IBUSkoYP3*|x>i@e{tFbe7wVL*Nd2oyvR#pT=s6M^8a>jG zki=cS^c|5rH%T~p*uF^9(0~I4o>hfA#^t_&!JTM>dmIICMN1G0yn;@D|Gr4RI|Zd~ zBBd@!c!=;FkwRx_vpYN7kdX~4e1OjXBI_G~D~X=8G+sVeZZQHu>#@^Vr zZQHhWW844i`@L87{`GFv`MUe-IcKWo)=bSgbGnHbHFtT)RED!LAUWzyT1QAi93G-L79tD!z_-P~{+SS|FBsV86O$ zx6xz1X%c`r=s~{0q5OtY`VIF6LF-4gjn%v}v;YuQ97AVf_7;+R z)$eik{i2aJu0W!$eU`nUo9sD&Su2JCLwcBkgIJJ}5%$F^X@4o*Y>I>??ecFTjh*-y z>%Zpk)m*-s{a14oA46-+HxAdj(YqDhPfm|fWF&<&>ef6OWLQ?Pm-e=A` z>XJ76spYy!LWa-kerQ;`SsEu>df_cn8t0m}|H~rN)p(ZaRoOi;>9ILZeLa#&ZOVxF zN%;Izv~@^&o8N#M&!HyztYhPZh0!VA{6Z^LQ_?XbL56B!!RlH>1I5%>Ln?njw{QT3 z#^gSuEI-ZgG%nY?l6gW|+L0w~jU|#Mtw`O)VFgQ-<;L@5y0lSq;Z-HBaiQOarAf2m zT;()R<+gEQ$OXdiIT&>vOMVR?B{LF}9#8`rwZ}vvNVgE$x<%Q-dWSHqKV;PPIizFy z%Fx(}z|u3?ZnAwZ9(_0BixVU0AQUwM#X(|fBqp+-9x?L$$%pjp+kp)Mbhh2bS^@Xq zcYJNpgQeE76U)cnv=6xH5v2AIG@N%B^ai~V->F#7*zI5{~JJQYIXYN##v-Q(AYD+gfT<+ICXnfsdPhlFeB%SsH#) z+FF8Fx-?_|Vc7{kpLSd|HKpX(*L;Be;JJ0yX!A+NlEe4e$?j^=*D4Nxwvs za~_wxdGxaENr}GSMW%8^hecV#BvrGh&7Xw{f@9PBR#bqmLKNrDh*K}aC_q~62WtsKn)sb_ z8ZK|3hzQdJuj{2`<4|tWfMTP5;ez}Wj=5dS(WZeVu+gw0K zbgIo~+#!y#YGt04&MIzPUe8^2_&oAA=Ot%wuIfh%bRmpiZWV^_tB3O&2pN!G`Qnv~ z8#Zd2{)l%kY*D4=EnaC(3%1P`YhRJHY`1bMGvgvq*F**N#fp{a94R3kSy zn;u+tUu=gN{~1%d+0@ps;Gh{ioF1blKyVoCsj)6CT^nzRei>Hb>Bz^Chl!oTdy17a zRFg*4JuR$A_1s(JBdfGK50DW429t49^7Eru450LDU6oPds5PKat9jT?w*d*RS&L}7 zteD_bVLE0eGNQdoT1#-I*#Zm8jzqY#C7G!8^@OjZ^Wk(scC~7roB2uw?9stpI9yv_ zo)29e5IpaA+3`LTv}YX$LtE=A{Hu=w6?N!2yw;A@>8;Pz=ksCV@|i5&a zjBb`?e{6bx&1x`LJp}me9~V8~yS8(_RP?@<)!*6lz?<|SFS_w?x)Ij{p!&B$OxG}X zS1LilzHW{Fj80In<$z`;W<3z%;o2I|(92FxO?rR!lyCpMbpc;lPI_)XM`zb&sN_v- zvJcZ{J8}a9XDcPw5?vHmpXkF4x-{vih`r2%KS3d&7d^fvpP*mu>+S~u2Z0CqW^QC` z>tJhb0|G82BBca^W$5l;1%hSjU~CEURSe3>1_TQP;_KLdy}o_*f&~Hn)cmgzzSeO` zX26b;^-)BwJ-ZIQ4r#_4t%Fnk&1YSbt=B}7ZxT({fF(XfucssU;}g_irs9^8<=CnV z>l!g@1QJ%1E!IR$xQ)nFF>BHeo)R`)=g}==fhpX`z#FaPsay5kgN|=)rK$t0n-E;? zrZ{H-_WrWnDZI!_FB)2x*!FRkwL+K+)A_t7hLxaLz5&cXg3W$J&64BfF|h0G+1HZp z3DEQpXhcxe&*m#@4CquzHw$ap1-oq1o)31chC@32j6NdATN39ka&+TIze=^)rr8*T z^zeRu^C$$A{KSk%OQL z3RB}z8cNM!U4(P4@iy~~6g0HLN;L?do<&&=(m&(Sr>%r8yZS0V?b@dez{yM&4G%Im z)S$+JF-%(i?m5W2O!v^oZ~qfMRM6fHCn|5(3%h5YOudDDaE#CF&QAM>46599e zhQ|~wS|}~ZzFnpvv3I<};{|T_!<16Rur+u%a1<&;Rx3ivKV-04>NYpWyT=1)o7o_+h8cu76kP4T|F+ zuB_~e=6yjiUSt{rEB}}|32iPaVXthgfDBh=%9{qvrw;jq(3 zeF8KFiU6Dd^*53)JBU1p7Kpd6EDyN%G8_?Z3%Q8sUH|X+TnLyNBYaKP4M$OoFY^6P@K|b^&+Ngn*!Q4o|aB=i^r%Q z8JoGT$6&2}i(VdLohp~N@$+lybjz4k_PuK_Io>vxxQ5Yz?T2XZDn5%Md&xhLjgh2E z#o0JWx8j#qXFO%+Httvgq)Q&X6>Mc1%EqM_nZ~6YD*+Zji2(I-3l)nR9;LQaa$Lj3 z6dE9sBkGoI_NIYNb)7BKV{-5~tz$QLp)wG&ZHzQ+X!)2fg>4+I?NYm~Jp(_DZsHNB z3K=zpSBbp$i^E)|FzytE(>h}kC|OiDH+Osq>ny@i#I=`BArq)*-FC>u+g4P^1LVp( ztC@cQOa@Lu6fN#}xd4qPSsFd#9D^OR>Lyn9=GRtam$@?Qm?*6(0zqyPiZ%r=gN6y{ zBsE(@qH@QM12dOJ5NaJcZ)t(SN7S5tXfry@e!w}3J5|o0Oc7%4YwWF3m93@>H@Y#J z@tX0#anOsEBV(%>vI_J$N%woi3oGexb1K<4v8@7U&hZCDH~AED`=X9{I7eX*A~0MY){lTXlOUo(!?EV>7ILx@kKP zs*0TBH|OLj?%*k};5g5j#Cjg*V}NY?q?WLvc}&o;!jDa(%)SvCbJU3$_(dyDKbHbr zb4;4Yey}@4mlt}zVJ*?%Ineq)l#w}m$9f*VXmbylPd$o?EA9cnIqA%&fM=`KG?`qA zI~`fTP^=NB!s-bG@Px2r#2u_Ut+(|0grd7A`bJCX4JDQiZVe~ixG!Ea zab8e%m*~f+H8`BY$X_U)Fh6XiPCjNFY4w-0MWC|oU2~t-{kO|7FUK$05ty6Qb{hOu zcW#dlCFv!cXO-LYxi<~}!}>gzrA|&Y$$KT5z9mkm zsw3Dm)6pr9%E^U+R)wWwG@811$Ah2XW-mBI8Al+T(eU^Eg5zaJfoE2Er)eKnT*%9p z0=9WfJlFKM>_FS(+vDRqCXL^1Gt9DYqv@iC=A3YDyAmdI`*n>5MNuxcZyPQej7ttv zd-b?ns@EsDnaxod=*P(Giv8=u?J>`ut?{p2dR_QDX@hPCRE{j)t@RsXr=U$gqACv; z$X8P{UX#h@99;0S%hFU><)j(6fOoA-u8^c>e7@2cX=&agr7Uu}zeBp}hnvx4sln)Y5 z_Df+$cdSW%1(`vSHNWcT8s|C!ZB5HO34I?oJWe{ZGWAa2?VqF?N1u`8_}$l#oT5VG|o~+#D9d%E5?YH(V5%{f=lqp z@|GJV==1dP`ZIGUq4-auLh;Y&Zx*!pgzOW~kR|aNhpQC&38tU*z8v$bEKVQZa9R zbB`W9CMy;V%D$di3Wo^&U#~~&25YQ~deVc-jd3@;+P57FoTFlxRHmreM9Ph$%I=i- ztaiT0THD|8pNKI+#Y7++VuQa<_rtjOH%X~{um^JvW`&s`m&bH4D6GMcK8&7UCiKz5 z)cTlIYJF%f)!|+^I~ZM8X6G7p7yfT%hLaGU#rynEQ4d!F9gWZpZfAK7TmC8Azf z(=j5MF2%y!4Xq`sr8CteM>T6BSQn+sLgAK4&qpcGfiu>mi`R zNW>yY@Gc`RD}NhEu|qY())H=oRSnJTRW9VSQ~phuUAi5UQ97U|=R933#KNBsw(u=> zM+sXBsDNv?BIevW6H_WLj#vx*c>W9k9f$--(mLJKHtb}?{l&UL9z^yWA zN8b+XH@H*LBe-9X+C-X#s?L|4Ip3psigq+@x@PrwPr!{e@Wwkbvg5DAUI>zG z2||$U2j8n;-$n&xu;RkHiaPUK88LHdU}#6+iSnt7ET+;Jg|A37X7K=5p2a%TFZa=( z4L{<$fcVd@AF6+dy2vR{!W(njj;J8QV-4Eb$t%OQ7@N*0(8uO(@{lOoD9b3nqQa`N zN`Pez7Imv7cqjg?&9r4yr$HX|o#k66Q-f^1cdTF&c1(*>tV|Q$j`RH~d%y~~iaKd) zTdwJ-My7KM&-u*yqH|@>watd9b5&89mU`N*vXhgx#L5orqoB4>n@-IW*0v1V3%)iJ z(2c>F{_B;Ewnmle$WaVh$G%I?HwGrA#FUhjmK=vZ3*P#_xyto4T*Z!Rhq=y_r_eT= z-d&noidrU>_aALdbxfZbDS@Xtt3KYJp09l5BCHKL&n=Nsb#MiKD)Ov{=49AoI@@cF z#iXlh6%E=R#F{he*y6e#U>;+4nZqY$a&zY}C(774&S)CaoK%<{xM%^^6I^RRBQQ5Z zH)3j9;ZwPKjf_P-b2}_Bp%r+y+biG;w~zTJ0<%ANG9((IE^MN2K{oieY0yN!1HJERP%0~sN=X@2lrEi{{hL)y z5Q68p9vB$#BEGSDp4DK>h-cs~5I%JXM_mCvdUbTm(TDFP2q2LD0cQA8UO(7jap0ps zME&!QxKdv*P7F(;^LRIDr^)29#JrH$F`p^sixjeg-keUDil@L${p!rK1ifhQ-M7El z5jOwOf~C#5RItNrPJck1SM@LJUbxZ$s}%OeJrA9aD<%s-9~qF$UYpcq3%C8eYgK<`JPE$nQ;N**NRx`O*QtJs&3(&uD7GgASu_>sCw(ed%QKC7^HK=X05~gwC zqTGFNX)rP-#{dB;}SH+ zGy*ILwm+f~tw`k?G zaK5bmEh-s=ckV;6o^?aR$-nL7^#Yh7Ui%J<{ybb!PlCJA%X!xObn}X8aBRzBTm3fa z=4Bq0=k!Bs!**FWFRN+*41;>&dSZ`b{#G3#Y1u;d^H5KZc_+;LRdzzwzvbBaT$ugj zv3I6#SPbpIVI`H@&U+uwc7NQVFxxhgXdAt;PTQ0L$u*f|m%~iA&vfxCzE6c`!_@}_ zHi|GSCtn1VoN%WIcsZUF5z$rT9*u=&Rpu2h9k+_S5YiCCtwR$EQusi=Wn77#KzX)t z<@gwb)oQX#96b)5;NP!1xa6r1#IZ7)rs=Mg>|c31lBqln>rsE~+^lpjV~-V<%TZrv z2SG-rZ(|Pqwu;yqcrqUB8Zb6vxDmDXMKDF~v*H0CG#N=oZDcSmck?pBcI}nz4>qDT z*%OT8&}lR|t73Q%s-i0@NfLsy4b(c&vcZ~d68Ia;0o0t;^QOhjjhJIWVH(9rYM{g- z8PpA`533gv`LqldKX$=O$un9cSJxb2`g?98eSE()!ob>QKCE^HThlhUf|ND5Wh%og%esju#w9@YPLa zxuDv5Tjf#D;FE)=%PAER3lz)P5emy|n*5{(s>o>CjG>F)QFlo3cNuC0sZT`Yn>`f1 z4$74Q9Gd-KS!PP00d^kh>)yzC_fl7Y_QN$xhTji_U8jiQGX!{0Q4&1yMXmI8bR8cE zBx|@Jmj0`6up}6xYQGR6_DQ^mnPjj?7`FMa`nx>{g68}D`9=r(ky;r@bJYjqx{WWy zhEgQ+Xblnd5lLdhqeWa(*SdwJqTNb<3HVpet)W-JO9A;A@AhLMa<|V-2B<4v)fl^S z2StZ`vv!MAyg5IxsMQ1Nj|@M?Ec7>sy8UP7RFaQkn##$~$mC>*g5S63VLtnYxOUW< zKIjf$DeWK@mW?qlsm5>M(tlxx)h^t1HJkKRqXd<2PKwYgRgdZ~^y8%k8zXzxC!fjN zrdO~BAzQ;r^2aCjh#pF6VBP+Fm^i9d(E3<$uHKBGbN%)vKrBFP6z_{@FxBmX$eotG zkzCICR@@?{0K=>~k$1riSM#Hqd`~e%7OcIK-ssvAg=K5wswODf7!aX1APY1B8>FTO z;*{qpwS}3mV4}}qR)_V-D8`)dK zY$w!_`t!=!&fdE<1-#lv`*gBHn?hgV-b1}Q5lX5#_e@CHoU(x@2AKCJ)nU~Aed#2< z=Lx0tEnD6*?Klg!-qNx4Pqir0`LS3V5W*9Rc=2&^GvIVO6bIpoN!e|Rks-Z}pV-rs9cakO`v z>vtZjrmko&w4fj2A=>qmv!?N+PUcxUox#WUFDn{1AC5tP=pTE`~X>lDv&qGJp^!5IJ;^%!Ro6zfOKkR09 ziJ^@lsZ)|bt}3TC7WBw*S>e$H|@8L_l|dl4>g~3zRW7J z;HRReqF2-B!<&J9g-?f137=d(b*C=Ve&pktV zneEl%DquY)Nt)P!pt<_w%=`Vzk2TUAHnr_c;2`)`jp0a)kImXxnM<S;6`OpkS>c#~H|yNX#wl;3J)NYi^|mo;oz^nG>Ds)_sb zGH2@=P?iE~0f{W5jZ3Ec$3&`Xyp7X-^|g1}luy+y<&;)xaMZ`P0$Rd00>dd6|48fe z_s+a?EX~H)iuSG*NX;TLfe|#TNHHpInp(p9V2_K%ys^>4x68;+>F0y2j`;)*&y0*X zf&?ANsD`HHxHBP7*3(M`&l(;m^;X%K{Z0QW)OQ>zzO1Vj9~L0*c*dQoNot#UV{_V` z^*ZK|gXDe`xdz1W%ctoyjxXJY0Y)b4W95Hup8B_i%KNqc3pXc>3UAW@=2I;`c?#?W z61@rK;l8tFh$6V2hyvP>Kf}n}z9BAXV;4f*BkEu`m;L0A`x}s&h|Mp37E+zci9s09 z$IQjNuF^vSMk4wfT7qyOCqJ7}zh9q302|HVT#X!69Ga+hKZNKzqOyZfk^n&v3Q|qJ zTnKTXh?cl!xB^&zQZFGWQVs=@q<*ZBMM%B^`>!}G{xnR3bCYbSSuyEY8H=zx1!SX` zRKhqEyw%0&j9PKTSZ#|a9C8>zcO{XZ%G2MX63yr?e7$!+kQhLS`-yWR0aAmMJlc_P z4lV+=if4TsfBN0EX5Z=d5-)tPUrvHw-Ll68DSSm0enwv_Rvje`2q}geLrqU3X(0Wn z%P&;bAEEh-LS4n4g^G&a zgj7mW;U{BmHqrkTESH+{!RTMTI59}j9@zjDqK9k^L9{BB764>j0#fpA0ja9qA+HTI zE8b|=0?8ZKT!{V5!EmpwtImb-)=Xcgdmq-k_nW|6Kx)piafNKSjDmlzOs=XwAD*|T zOS*_7)2r z#-_}v42Jhx2f^bf4bPw8pTT!AyK;DF&)n_7s-(H1N|9%=%7)F2f4D1$1Zkr$uLq#G z2~XS$|a&kx^!4!wH%T!Y|~ zp6UMF=z3A@zq0*+ zYj|t(NxEJ0Ax4s{23M&4B}s@XSy$f-I~FollWyUjD2k<`Cu~omGCMa~?mu5XXmL|k z7xcDT9$9bIOS%iRqFoGvt*v9xB<5)#3vfCcjvDT!J@bz^8?C%)t7~KISe9%+cqKr7 zt*vV2dku%Qi*cieEOR9fE_KBSCWH)jY<@$;DH$h^LW%~OJsYx%OtMEMG5H}ojap5L zKuzv&#{&VAqT;mM->wB{g)l9GCE6p#_N%s`uO%vlG%I&4uCXc+s}3~ccR4Es^(zlO z>USY*QluVG>atPQQ!`-NwC|e@e2Dn-jo!K6XPb|ycyw=G!r`}WDV}kpG-PI01 zCb|YbukejO4t#b$pSvbGdx>`qxeMQ*GEuU2DKb2RO#4mURh}KW$#|!3N6nUCgxx}u z;#)3*M|Z(YAK9Yd&6zk@2rUS8oyV^GLI9C`xZJ zvvP>CZaFyR+6-@WZ&^yO;kLrQG6gYSKI^>2;tym!K^;7&WXY%NJ_%2%dN2I3eJdPy z^%iCL*p|Jf`%t)X1u4d?_RSIO2BU=s_b;yO`V-WR4>6H5)(8gO>uIdqV9lq+`|nX? z@da(3IIwZ%H&nahyWz750}F)85LeB_kNO3jgl`Bzq4r)4nC<9ZsW z8Eehs9MQ7^)%HZo`{tF^>C5NBL2tq9!s|CwW>%~eB8nj3U%&-)h9n)8{(0ZImiQ%4%3bD) zD{!NOtmReqybAU)Ya`kO<6dB~N%u!HXVSgTUd9w@6r-FH@O?}_3IV|%^tOB~tTNWLaa?&~fI1f`FMb>7V=s|JL7QMX<{ zQ~%)tTzv=0625vVMKos-f1v8G%13I*K_Pb=9`eYD)+ZEH&qyD)+|4$7>sikqY^Qu4 ze_owLylt|_HZiFOXC>NmHZeON!hYklT9_9&{BWatA*tF}2b-ns-3n(dh;uk{&m^@; zQ0g_D8IJJ4GFgd0bI0=NvT+874tb(GsaZ=WF&4aK@FzV-mXn&-u} z^5w+Td>YWr%+CS}X6Hn`Uts;{oh=Y$ zFtK{_q_*gEnP*8x>OETk$K-8&w89xZV%}A6-20XIK8k>}zH1`6Ah3KDzsTf=#g$A< zfI%ZR*b0g!uy{;NOz=2NOmp1~eck+=PV9E$nC#O$pG=rZ9BekYb&uy7ROTCx=Ekn< zG}=Rq4!`yoE`(Djnw29^^!Sfoo*`-)r1F|IY)bacRuXp2pBMfL>#*wXwG$_|^fk@g|Op#+&$&VRzSHfPa1WCSB zAifl_fKsRg>wl|Z`r-^I6hTA-a{26GD0NZwQE~3WGk|?FP!p7)2!mw#b&o|4nZmD% z-Sl~g$uoB2#dId~kW5(qm^6J6g?b`j40(jfGbpFXr^qQ$IB)_{A_Ss+v3Z@t^7#8^ zKOE{|Ia2*`;Dn+)h($YM@-~O%X&jV-aTbV0ormRl9Oe-?PNH${1*2YwMZse7dWPlU z9FziZ76?S&WAZ+R<@xrD`5c%*I7<1WEMoGo_KQI|QX_C!2t?;%@(zY)bwl2|5DOk@(sxhTnT6C<;KsJ;W097~yVBtcu5QMI9`3rc`i zj*ZOvQi>BTKrM5D)NhWR9J;Ajh22_TZvaC{$&&diS{Af%q~I3GExlSa((Foll`KmV zOjxMNrxW+Hf5g8h&nr3R$;&dcrKH_4v8AOIKovmCmG+P;(?}=>D=g$GHIOUY##{W7 zU_max3RRd8Dly4b%9AfmAzu)Sx1f+UOg4UGk zt0~=EF}SOOY+v@nAR$V&fLIZa^q}TaGeEqeFQ3t_c;Ux9R=YXe?7qI#@zE@nmN{Sq_bL-%!wfIVKwJzB}k2k9s4YqoqV125p=tz>BxP$N%gW6AgK= z%m4kKyzdY2*yiWOiw}l;c9WyUQ}X>s)y8CJV#tv~#D{}EW604$#7Bb)&t(00iSzr| z&*kHp$--G58uD_m|B_@dk0U)^H+ES#{bZ2Wn7&U^B7j0dUdIfVB5kx?mPoe=qI{DY z#|Xy=>K;oVCm(y)h`@dUqPzN^7HXH*wg4ljNk(W>b-%iZUUijiYAU-#O!hJ8bYqms zS|rmHzq;~nb(6h+^omWWX0Fc9W*FnRwIkM16W5wHHCAFeG@yYU8oEBia#%nqd&H=v ze8PQkSY&>_KDp%#GCG5Lcmg|lXpiV35%DPlA|#|eVobwwaDbPU5YKE3Jj|ZmG#uoH zTC}BFb5KQP4dzlaFC9Z=6*81Fn!=Ov?y$!-d*_F9hf`2=-1D>i*0TcNb#5m%adgUy z`w&k`@DQvY0>U-UKFm(AQ6ksW?D{3JA@jcZw^Wf>K>7&JG`{YdWs_xyg z;SMsC;ykA=N;DQcK^pRAdlP1m(g>>_QHCZ>L)3ZFo_FK$8s%WL0MA?3t*}QL=RGFJ zuLqlXyO61)tG1S^PRS4z#_)-~fD6ivQ`WmbS%CE1PZ8J8zmjVEjZ-TEoR11!I!jZX zXuO&00ZcPQR{h?w$YacJQ^D;2;om)ZbVP7N$alk zMAeP6xnyR-4m_0X^T4!omx^bimWn@T4Naq&worVEb0;1T@=rh;k;?Z(uEv$g^QPr< z!<&$Y+1-v*T&aE=T%N!7C8v6kbK21DB=;tg&J)Ly?iBenpO?0bgX8f}i#u5q?eR2| z7P9OJou+1o$@`|f7LiM{TSW)u)eCj*V% zY2<0nC8IQnjZPAR&f*M|<>3lN;k^eZAtJ{HFYwD| zMv5o(pOunpbmCp(%tA|b$iH3Dr)>LDYim`L-wkn#y)?+j2#q;%sYT-tl?177ik|;Fm1J_bK=R4tdaw+H|Hw$I5T51e~HmhcQPuCB81rlVD57+niup zMOmj>ju}*yjzi9^&66Zc&y&s<|D^jiC$5&M@9CXmhGnJWz!xclzSOeMxz!>=we&pb ztkE(Fy`+A?d8uWZaN3UUL;G>#itZ%nYI8gZx6x9-b?$TsxpAD&mElwrcdD>Z_YQx|#De^$0(e&R! zgYg`G;Zo#|{)}Ygj^8L!jVaAndyC_@&m;<9~DE&kdhEeR1@nJNK6?bIu|n=Vmwrv?#K^Iig*0=hnNsY@+I*%JMW4}u8Fw2 zhyWuR#$c`mNdfx#U2de#`dm0xheWw5=4@HNM*`uOsuY?)86c5B*oaT1928H<@VUH? zAN^*iR>dg5FG4Yl{JliJ0=7iOU|}@I!dR>U=~UUEV>DaGSgZ=EE>7CzW>_XjnTi

s+F-S2kYka3i1{!Xh!dA?nCMvU7-c`nAkIz-HN?E5<_IZ^ z6s6wFFu_W?GRVA^Y>K_7WSD9pr5LH6S))^Yocc7!)XLlHO#_QME6{_o=W0=@A!$SK zWAWx9IfbFtP!UMS=pEG6YgGgpO2POGLL9ge9wpyuMo8VHnb$}1>?C`7oL6w-9l*B0 zba4BOb&w5_v^;&N>wtuQgb<_x z%wT5qa57=iAq{efRN3?~Z)^G!e(#M|3oByRJsO6;7iedPTQbB+y%}shJ$f6{4?h0x z!_$xRk*8_EoYv8_dNpRL#^0vqW@({KOlFO;iSWJ3@!haks%Yyw53+Z7oJNeL@iyT2 zSTX#3oyM2Vcg_%zzf@T$7cbhvD5{D@<>NYetsir*5R^y7O%@B6t1+-FIo_zkBe|fSbJW7yFT*g)+8qxOYraZa zv@Pw3;=l3WPZ!%16tJweG;CN6!vU(HeDWPxEi86U`c70-#xk5tI0@=a^IotX6-Jvy zs4cbbcyc;{@*ak~0l=nL(r5DMSO+Y)(w*OnC{*@PMA;i^|FV8}4md34iQ`<*v&S+& zIjBwf@IWEPKPjWR&gl0LIjtP?W-3?ZEWc@(u+6Mnk++_}$b21lxXS!^%TR#xTHa)0 z40BTZe0`fh(4a!UFWPLjs)89eY3CX9sS6(4Zl)h#3*7ohw`a;M^_wcidlGm6Jea#M z&%b??on=(1d0kjOpAPRPo1nvwncC)-zqzT<^X~a>H7tOeawmxZ}si4^w2|0j^ zth5Fo&EOZF3pB-2fn*;&bA^NPWsz%FPsG#wjV2 z#F24^6m`{lh{FO`($@l<|`)DYg)#^#qEd*6;(pUNyX)e3C_7UHjyj(6kOEC;kmGiUj;W0z=Sz+$&*kH zl5?fx;$gxVh2*0sM!)l60?D$TMj*W%`ekXKM;Q20w#m@nj6$+tZ{i%i8HZ&>o<}hF z%&+4Zyl08XRQLB2(zRmaR2^o2kwNYo{Yj6Ai9>X75SGyy8A0W6Cn1w|U=)xM86F9t zHPJ%sll>e0W)zlXMQ)%VEL9mIj>^zNM5^4sA7QM47)SNL$piYhu;lnbDM|weQl^rS z5mbf}B2v}<{IFy#M8}Gdk>iQ_|F$iKrAq(#DRxqn`uD?=6_;&O9dc%!*tzmKJ&b7zTRD4xn5@Y^zwDMe!zV`WPYN5NW!no zkaJ-fiqg0+k48bP%)qg<5(>*k90eir%;ad&I*kP~(mIL$xd@%cMH~&06ZwM|`X3nd zzfhkBgBewuCjJLtFdjzym@t&p*~9)sFekPDB`E)iFlzGZ?7y@oK|h>B<$eid{R6)r z!bB+lqbU6ni2X4jHvZ2h`A5fodFM&K$nXEL?h$in5nrVK5Fwr*<$Oa76Dk(_(kYR0 z{vsXzfl+2*H^oYidMV68Q5Kg^Kv@uz&p=T|WixFr9uK#8Nrh)ARmcOiP*Pq@r?h;5 zng!u6Mb0lZlob?pEX+He&c~82oy`w&0Y*?Hq|EyI1IKGDev3NxCY1t8Mw3pUQx!*1 zC=~fcnfg*oIa8T%r31O(?21aG3I(!8Ia8qnN{`Jbe_8yNR@{;QWO7A6joi?~8AO%Y zk7H0=c1V8CAHw^=v?1VX+!?EGs=ONCMtMFu{`D*N_6{~>{Ml&ijW;62=k-zMmr@); z>EsZaG3s7it1DA+)kadqR=z?oI(*Rtm~s&nk}VhGw+QQyj1tdVq)B}>A-oT@E%5`C zkd8n4^knskNV*(87onW|na7cxf4O?P#*Qfwl}n%V+?u-GR^>3#HLsoN1iB0GnCpC+ zLN6tezNV>Oc=y}A;-)WPh@#^WuY zDt1wp=o+CI-c?p_u^k1GekVI}Cgz%Cjh#CTv2zD2ti8%s2{ta_-cIKQyRP=l8htvw zHb$?!8lT1Eybe~5To2_>K`hGG@MUnjPB!rAL{2%Es86xWcCg&-cx3)fK;$*f{Ak+y zNdHV54$`ejUqzGTR33GY;qP|M#( z2|?nSDE&isph9GH(BlcSWu(oot{8I<+VNLi!2voyp%m0S>dsvwFn_B~LUQX+De%rm z9OY`u-zPzK5UK9Rjr6j5j%#xCKy9SQ@^K@0C7699w(M-)~Qv5&vM8j0bKI0&@d z4qxSH2=cwXaMc_%p8of{3zy2WA1XvmuS~h!H>&i0=(g%!v~oKX5}W}@1bzQJC9`OK zf3W0jcGBfADEM99Ja#=2c#Lk)#~oj9%9^#}9-F+E*2vaV)|1LL``>)1OXp_USz)Ix zl$C3-Js@A^lO7}^h7bf-Y!8%?9TMi500h{)M$=vZXlZ#-Ob??`H3}y6Z;0@i9weh` zNK9&>ukC05)R>nO3ZrUROln~Wn3x_SqiS%>Gkyq|*d7BT`ae)X^ga4g^nOsJ3_aka z$@zt?*q9Ln0b|2@;Fww>5P8FTu$bcn0hmVg0k9%5J;p}#{;;&f0rLNBlb9Y@Mzug# z6~X}L;cekzJr>3z!T{R;1#022t;5;D{|gog0`M5s0=^hMIL0HQFXMlJcsM&8c9G~m z{lAR=?)BAymXY26KSRJ12G|?XN5Bro_F#}=41xEV>ES>|?D_Vw>wSZi+WjYgKw9;K zV%v8IuhV!*p_!wU6mBF`DLwNQ>nU z*0>g~bx4)#C5gAgB5{)IHHn|*hbof)kHi)mNg0AX93D*(g{Vu`Lqk3r07swh<~XZD zKRz9Js?FaY&-3hP-u(6zqjm$7Yu9{z2=XFYi&N$Rm7Af+2k;GX)34UK$C>5P=ugF_-UML2M^x{#5XnqeoSq;`?A>=yniH^h!|6k z)soC;_cTV7K)@Dq!bw3AV;fr07g`B;G(K)xHm;90o)rQzCR7D)7Jl1|d~31xJ5RP| zOZI9c@w{vrc$~PzBpr&SHZ%~doyu?*!7Ga}nZ)TZ1%7fJelnHO+Qx~lfrFy~8zHo&%qCV@4Y&?K};Cb`%W0_tgyWkkh^Xk;H z-PzHMhSJ#(`b3q8DfY4Dv4XQI=A+k&ov0H)mDwETrczuK?<=Z=+D?Lk(tIolh z1Hw&Of76q~(mibjTYjw#tt1U{5AyRAYw~%!+uHH_3{A_^`3xgkZ+&Wwm*D9J#hKOh zt?lmjC-KTZjR+iA??dz5Fm@du2I)xPcWPOi+$GK`Aq+JDD4{Q2ZO0o_m-ZvAxh$Jc z95+VAVJd0+6UJJC97cH$n8FU*S=sU~S+qY|LuFog&9RV=r6X4)&GmA5)g>#raeKKF=T>t3;^%u>+r+cK663s@d#@v)p)sE-7B0blIY2jW(l3 ziop~qxGBB(vRK)9=Q8n`CtxpU3*tG6y~ z&oKw~{B(ddnultIv%-BP=P9OgD`TmBMl8o7hjKm8+^3wR76oA|L8i-5PQ^U2zil64 zu&!!};q3A+Th3tzYxah{aSx$rrhfac ztc9j|*8|7b=<|3!x^t@d3wS>KN?q{}Pp?#7z^aO_#rv+B50$1X*TpUIkWC+km-iMk ze?$pNA@PFxe3>KGtl1lAc^$&hGO001cNj{2e>@+k`d)UP4}bC?#QI)vuXlfq)WctY zY%rQSD>~i`j)IKuZeVio5@#Oa9?fbfu6+~Tx=?mV^{yrE71=nS1ny?Bg6VCmbIUD6z4%@mlc(&8YD) z;j{mbv9|zjb6K`Vx05)=n3K9oeMf z{aI}8*?48Ber134HX_A-RHz7vwF!)!7M7Ysiq}Vqr-7Cx56puTVSyA;fh0co8Ed*P z+(w{KjjW&oMJe4S?e<$5v`&`f5YNChfW{?_%U^USEW4OZJ_RIa%_iR&kH;R5cj6i# zgB~E8?>C+AXXDHKMdZ%APNur?uOtwWC441KFd|j`M>c#<8bwAz64cg(5`HGD3CSKh zMl1&CPHXfJ(De^|?w6+D&ckt1f#WU?&X^Wa01;EJ#3oq%x7l1o!HSrYm6&oSHX-f* z#S8skVW0m`HgFg?A^Sf8fu=ZQraWY(pULv@P+0I$Ce5$;qmjbw$WX*X#jFp0L{fGL zyk*~HvyJ0&i|~a{{*598HvIvzHn7O)vnc5#*AfWtW}E7RC_EsiQ(#e`Y?K%gI!6_? zh)p<{-xf&w*wPsHI)DrvEUy>S$*h;7{wb!Ssk^l3ruL?GxS+x*u)i+3AD!4~L984) zju!Taio~z1F4XW^JsPQF_7DFDoSt_2^!+M4;$-nKGh}0JG?Yydk?=A?9l=D%^H_o- z%2`EITs1NX^n-lFtC7k$g86>=ca-|TF=_HL_?SfZGnUM$8itIBtPLri09qPPWYWYG zbsyMpHR2FYuvATd5RgokO@5S3&OaU>h+miM1c&F-fL~)$jpgTr`kV*lSB>B|X|j#8 z|09)CR2fC0_Xh!$3?qNOeQ^FY7B-aES85p2Eg?oaas*jzDA|Lc{L+AYv@R8t%0vP! znLk4Um7NAeaNh(;B-RdMS8O;)6vP@6(KMY&sIu z_M0tA2oR+Y%w^=~>nX^lfie1S40dsd?qr8$aj5dsP&-+@l#^<+_P2R_64A4X7FAcZ zIRo#$Mr-b#&`#CHzu-5uOYX)^U0-9G`3lCeE?XC3fV{_BFI=@(%h_IPd<^J3*6k9l z8%GPHaA(c>E87!Q3%h@Lb#bbl2+|JXty>`;S|}X(&WOsa-5%o4Xx^~D^p@MPZ=q^qCOSg4b{K7qw6TpKMf zFy9Bkcb}1~(9k6BniPDBZXgQox=&_^Ck~2H%1F#@w-Z?W!@rgSTFak6O<#^bAJ&aOKE#1B(4)D*y_iNoMyoq#8*W8HR_(jvh zlzDCGmlSl#qAsz;dfqOZ)%9Ea_H7EsojioyM?iBA|HsjnU0Qr&@ZSlyt}!cSivx7H zes7Ix_d1q#jsZ#?EwosjepG%6 zVus?=TyKnAG-zvSDZ2_s9y=o8wInLA~MHb zmhY2xTpNvUeRl5UpE~4|*U;S92VTau5g$(kJ6Omw%hmg8BF<2u9uv>PL8Lx8m29Y}h!Ecla(3h8B_{y*zxh`1!1Q^E37p zigy|@n^sdpSr-*DfG)KJ2ysoLp}V6HVh`S*S2DyXjZd{}->l19S6GzrXlyUyIi^tM*Np;w5kT+eqf z$YmUL4B6)HbKcq-eff19?~Ze7V|xDfdG8RG!fGN-&w_FE!ow_s%i1Tzf7+9zmvEV_ zz+1)3c(;YP6Cz1EOZNGRt3%+%eaoMbC0AstEn2B2J6d0C5n0X5}q6 z^oIOMHY*_{DBd<#mv{EtQEi}7LD%f}6Dc+IrO@G?3gdQ~I%)0iug$|*IfK@4zmA;L zbxTZxK%kmDb@pjU&=!L#zDop6c8O^^C=1s#geDF=)z-Wv;L`1P-TG4G4yAOAkTZ-g zqTizavpUnaZb37hzhs7I(^ageLGXTi_Z4$D?;X;Vx!_I33THyN8JyF{wfw95{az&frDYLMPDsKQ;>01@e zBCD6#PwdStTD$sY9?mddAAa(3O=LZBC{T_h?@U8*DEOH1Eriw9vEZW&wk|L-eW1zd zV`&xkEEn!<kLTi3`FY;DC-OuYnx8oV~yT}74RK_RNM%<&}zI%z*N z+(cA)ng&OSZ}?)Hoi;sTR6g=xLBli;$GUd9InEX@RKs}Xe;5X+7O zG&qE5pZ?pd2VHg?qQMZTaVt!VDe_-@6F3s8%;x7i`2OEb*cNpOk6v_qltFsWvk!;?R>Z~xG>d`%W-8e&K_Lmp<4Tc!`zmiU@%_HM|B ztU3Ov9c+}WznHLTPX^I+{8O(ySkFzEp(}QXq2Da-260wU3hucY&aVl|@1T>hWj)2{ z-V9T@1Iup#vcu=gb9JcOSMqmWTVh*Yh`A*@)riU*6RjpR6feX$S(usr@7{2Bsw^;7 zUul@+?=Ez>ww#^HA8Xb=aC8$g5& zAi)MucvmXOex-;qPbm#MqporO zVWIrZG8A^%@-=Oz`|hCo&Pi+6E$10cYZqS2oSUvDKGYCmh>r49k@PeL^{x=<&Z3ir zHth9V&KpCHKRKNTTUZ@Na2j`wQ_Yaf5B|`J zGRb0^r{#%L2WdAm4IvFXK@Lv_Y4?6jW*BDqTr)iR!L^evmuZOX-MaX<@86Cpsrhg< zdLL_CjFPqA)ky9$=heM9Sxl!USSReCdd;yzbla2pFGt_sRgHeLNQ^2}rvnj&gxcu* zSg>1K&^v)uW)8E>0@GAWoWk(l!izAZ2s7ySo58>Pn$$Mpzx!eb>PaN&5rpWu<+sy+ zYf|hsQ5&S`hdD80Mh?NlIix02#_P6_QmN3Py~x_+N154C7ZBbtNR6?A!P~Xta(CjV z+zui7ut=Kl0DpHDX^Hn(%lYfVbyceO>`Kst^v2+Rs%=M$8>@UJ4|XS*Xdem2~H$^m~b$b;RusyM&ekM>OrV!L(ly*Zd%cTQ|wjV!6?7E8zn0Uyqjs#yFuDnWpurM(mV9dPdoi`+b07Xm5K6` ztB~UP@W&Q*NF2%Wg}NVxAB%>ChL^E#nL}B~C#9_B8$nMX0KcuY);)PN2Fo$5&4O%t z&T#vn6x~tY`5KZ$EZuqeD{Rbf8^(R>zD9;=zpp$15`xK^2)(}|;hKlVTm?3wIQSg# zO-A3af>;3f`H1uGz4|Q{rP!zH2PNkx&JSw8xc3%gonv>KElS(qL;U;dGKv^A-xgBt z9&fk~t6GxvyyrCSrwDO16cFJoC9@inJA#XeLGuH#O7&6(9)zbfQ_`wa*)!->1qblR-fOP3tB#V60{eHZGvCxIzx~{h}N58oajXCbS$`E~ehfw7Z z;_Ujy+dW}2Pn}F4nG$#r5pi&FEu$9mE#}j8<863;-z;M^!IIxgA_1WL8X8d=O|gk9 z%PHSuFln7SrBjumT+$EFeUV7pqgpN}yYVG{I)2=TKnKS@ne5ex`gv#YJVo}~L96Is zZQv@oqu#EJLz-->k`79rVL7~i6WXhj+5J$@MT%^3$8uku+>m|pr#ko}vYZ{QiX&`F z()#2*8<=lt95QjqM|k>xz2SuHg$L&Oof#1X7S5wgS)OT-Z;u|4FmJ;wc;9Q~Uj{l?g)j5$)$@?ra-taNL=oTmjZsaRzi8Y1q$?nbkdN(Q zGp&NDP7S8x5XNZ3dwcIQ!@RQ;#Q()&3ctrw{~NFO>Hj1|shzB#v+LXRB zLe~!0j>`!}T|hEB#xaHpZg9_{k`^wkwXhNXy*1V)PGD1fZtswSNtY63mppxF@kjDH zU|zy{u2E_cUb*HYf(uN>Ja;fi$ai#1aT&Fs5x3PH-0j9 zkQs(BbFR`b)^Ig62X>Hrv(f;SniJ0QL=dBdQ8+V~G4dy7Sl&qCFZxAB@K*accJay{ z;Jv}PdV&%DK++QZR1WXXwKb)DVJmHtQ+i%ow1RKM`!eN3d8X<5sr7*lP5cOk zJM{X2dG6yHyER|phudri`ystmR;JG#9QMpvqzThWPxTiI&uIiS!|u_Tkk`o>2hCT) zwN71aM;6l%hXz?Nuxuaty10kQgq}I|$`*qQ>>La;i61sETd<#2-%6NiTz$~Wr{}LL zCTes#rLUrK^JX^{-SY*CAa7~-eU?bO5l9ehj{{jE!wLcWR*BN1w1SsbGv7xO>C={i zlg|2&JWaj^Re#)pO>ANC2#m7`-FXtlj2cTmPd6@QAjK$$kRLKSV&t5vIck7zZ?~fJ zg51>);FtXtxeceai)w5P-@Mfsx=3@fNd>ES$x~z}R&X)wv>ijif2dqZ+UzrHIpCM0 zbK(g;GD5fQgHO1eTFe*xjR#Uu0KQkiqoR-4+*{D_YR>bah#f-%&|cZVW&n>qFNRy$ z<~nZX_=po*ve(Hq;X>PF8SB%T%s!m+E1kv9LdSNx`^ct=pjBfYRZtT$i~F{eT{|8t z1(hM%>OlR?>xVI4Kk_c)KSYE473X)qx(zz`3CgbwZ$A0%Ji{7xos%MU3JUs(&V@ zqU|R}LzA?4QP_ocMgytkIY)9c^zcxUmDkXc^Q6StQuVy%n>s%prSY%=VmyY-jd$G@DU;uqyql}CrAgFq+ek~Jenn#;O=%@-2NOBhf38m z@%h@arKj3`simjN`?|l&YulU5>a6ZbO?TenEWx;C?Nrm&sH4qL=H%logzsy1vVw~2 zUO;mY;sW8MqVN1`qun0r?Mri};u7LMtKmd-gw?`JmB4G*ORC>ts;^wbZR1O$-3bi+ zlnVV6<;_K-uZW?q%n+yaLol^r$R+*krG9R+b4jvOadKaWlg3BWABZZO2-@obiM68I zP}J5Dbmzj=olA)oq8Rr?`Ny%40#fFMw&w>(X_+J}+ItJz?oMW)QO>v>YKkdW1L5*Q zuBI#v&!#Mp>#A69VUnqjj=02UrY6+=|srQ>-XkrfI5W>k{-qEBy>J3U0+Srhqlm?Nl1lKDBr}Rcg{F9})*L z2eI9RZyyn!){%5KkY*f0X}G#ExVqImMA`F<;39z# zz2mSZjmW)9h$g9@Oy*%tih`Ndeq+^lVio+sn(f4@W(sC!3dUv%cES>cj0EEKDnXc} z!kg@WXO;_Qb^&{Vr3-8K50=hX_^JPq1S5ESrr-glU<9l#G^{SR{}COmE<7wz@<`$@ zCPjhFreEPXyRhtjFi-!%vir_F{Ts{bE4(XHFb$ zD0d|ALod_E-pbGTZm>KyIQSf*8Twz(s@_J>bWe0$UpSsP^aX7QlcR1=ZclKG&MMEw=e-Jj3$5DS7u>(Ww=K2n za?Ib&-&tm~&9!UtgiXMOP7H-j$m8S^#&YC1qfRu1?JrBX7!*xBNb3vQ0j7Pq%-)m? zU*dd~0ob+vz_lmYr?>sPSHnWF9ECs9R(cBDQ|uCB4mA0yxo&l}$aQnPteI((+of(A zLlQdu9JT8`mcM1kf2L3TOv#4i%!OoBp-(-QAcsP^lajf0vIojAT@jhgL-p!*wGn6s zbK{JB446tgvOtsk=)Dm)=YPVT=r{rz@?_!4n7FaPesR>()0c!uoc^?O7dp|hwDags z@`w*yksnUJI*9Zk9Q7-V;5gH@eLr3m{-^=1#G3{+xiBdSPB}ru4Hi?X7w{q@Vcz`Hv|-S zLSAy+wVG&tTsR6#=W4!a6r_zMPVbOpj~1bPuEN69R_Yt?_yW?s~4Zi1t-8zk&V|^(4s8I3ufhy+TEYDMu&IIgavn9LzMk zuC~ZI4jQ2I7LCX~CeJqmTnq`YmmULfy%!={MTP`=GIHgS8`2_C9&B3rS9jkS`cEV=@(~X&d5XWQ0LaQSbIu;-l9UX$ z^*?4@oVCpdqhX!(87OAZu&v%?{Sq|=zEOiH{0TS1e`hap)e4kfHTn3JNz~>aAKW3r zScpw_r8lDL2rJ^_l5p|6kNShBY4RbPoGds_5>ft7e3+P;%HDn)aD>zu?VJWkeyHg=(M1n4b%c@)<9#NIf=Rd<$92xO79L-e>ZF)IRN1bma8Y`N;xx!YV{-1@z^y1Q^{G zK)2OkwbguTt3hk4fycZi^VSajg(W0ktAvWLjtZEi_tAe%7u)GL!jsUZ6VavvYnVNOLMgy z`l7)S<)kI0B-Nt9h`-UcXz)lmX{u;2K`DtcmuBrJh!0ZT^CQR!Ufq-6|6_0keoG)h zX*NM(HVq}$U4F(B%cw8PdzGHt?-8E#ASdvM=%7n0wVe@gex)SNT$&0|_0>pFD}uTw zE9jC(ZHMDOs?p4)X#l=Uq0)PCb6{^Vb%k6SMG^I^$p0xQoTnK}z3GcOcMzyGUf`5> zJb5pNUNeV&EwFw$x}NWgttaoI6aJzT{o*A@?GEf?;~6l{{1?y9kIvkW&b0r^)yV!B z95@Ils3`8A74*sn_2NnT=#2SzWh3fuC+1%+`F~+M@=FuJOVfWL#NQS$f~kM-KODFN zUiD&LeZWciADzMY`9H${cK*j2A^&>pi$m$^g1u>B`yTta)K9fdf3v%WPLQMeD zPb7~e`6T8eVe!R+>Xm>2MdKVaE;YzIHDV9>MdJu@{9>kvs0%4T5h!J#?P8m`u`dQX zPblol57?D3*fv!3W>j>q!cVA@1LXjkC-?Y7@4yy${d%ATaGC}2a+xD){Bd8uOU>#i z>%z%UfU+W-dT%lM?S-yqyJqi#xUuD6=f`2!46U|GtcZL&yRf*S)#e4D=9q&(LsHNi)VfNKhhR$4#rMSg{cpZn}zi6ndS}zD=#R#~P{2eH)K+ zaL8(xrH62h)l&bcWOvkeyu&SoO~AJ3K3awhabS`mIm6582wI&-hwAVnr#3OOs-45+ ze@wiN&Ypb6L-4$I*@YK?zEDHh<8CdoI<wduJAa;ZGQIIyfH+K%T%vIW$7!;UcXbP zX>Fk45FnuIIfj-qD{b88n;`4$kXcwf?QilJ2)qc7!3S27Z4*;2qA`e$jyV)R&LL^uUUS@ z>6jBP!>F2-V>R%Rd+pwuugqKvqRo6f*NF^;A<>)ZHwwPHu8-w0m#>tT=&go$@Mofr zSv8NmKIZ#3q7`@joxCodlqQg-jqPJIyyU>M_Rb?rF--7AxB^4o___kXn1Jy`h?VA3 z+%fpdn8VrpqZF4PWYvfPk8gkVIcA(;K>_%01q<2tQp-p8++xl0=pIg!`gHDPlu%R# zl6LgI#gk~4df62}E9{we!m^b}G!1JC*8JfA!JDUAH+lz>eUnsM@S(NZ?fYP;f`7FI zf;WiukC=7)M1KHRBxRVGT`QA6s$4wD{hbA0EUjLtz&7z4lo=15E01KJ!5-CPZ4}N) zjszx9qE9I|LOFM9f85b!ALW)e+kBlk?DHQGER<3Zy_ylO`n)hY0uYwB=nt`)5tKSt zAkA?$Y=}}2zS>45=uZS$j@P;Iic?LptlE%Skk~}9txVtSq_QSvtr4beqg34nFIgxD zo~rGAn@VZ^Ewb-(kyV#t?FNbrQz`j9IZO$`v)M~8)Ca`S0~;3Xau9ucAKAcez1i!%o1 zd=QzS)q@kFq9H~@M+zrL3O9fjhYZZY6j2r)ni|GeM-R-w5n+ZBQT_-_g#)I-0JUI& z&_Yx;(BiVcy^ww?%~ytD%y+ZRi^1KjV;l;ndLaP`#EPL9Zn6;xlo4Vq10}EjkkYIp zx1EQ=dWezp<$NHh`b01R7gO|IlC6srw2nM;9*X19E$7j#;vojfXAHxagGqq=U9vV( z=_(nU-9AnE?*`kI;ZspWl-WwWStUFVp7Yve>Dg#VhY)dx5Zny}&My4j zF8tZw_~xDX$zAvbfADoS5L_KX792v@9YRPNyI>o;cp61fPAlm=GRW?GPD{aA^_CQ8AP z!q^np|D&-e1*0Vre>9TUqE!qyPQ2KT{=%0E_kAK<6Ht7<2w0AX} z^zbNB#3^4{v@bP}yA2CI`lr!h)40W_=in=*op=nIUL+302jrkCrnNXE48*G%LkX~G zvq&8i1&Hxtlew+aO$mPv!{3gchtLECQLzj8-*);U{PDUKF})Qsy4^%}{wpR`zp?Y! zX_ohB$E{k_hWM%r!-?01*rW@in!$#6>JP^bqd%lSOj1vtm;mwS9gS!T^W4MHL(YAL z!8&)_uWjWw6N2%bIWJdFY4fYK?{k7sCy5;?&trxx?Gfy&FL-my{@@smo-Bt6^y zWPDj56+IZkmKxYvvm8ES_8!?utgM*3vZH5iGC&Ql1~R0Zb+Nu4 zQDD+|Q|k(m>RBXy0c_g8wjP$IMT##YOAfTWW|%UNP8r0%QChLggcNm*;_Q4k*znAk z7^%k2bO0&1!u0H3IIb?)Ggbrh{B%3cq>2=VI!Du2j@q;b32_t=clT&~N|1YUkR zY;}ch$+B6=XZp_-&vXvKV~@-`jx~35x;`R?d+eD2;HfH2mTZ@zGQHs?uBms7)A8DP z2dH|Rhuvd|TNp;5$6xufO(5VWk56lcCS`e`$hp8RpqcGh?@}J}G5+;!AoONSroXRC zc|>)YAr--Nn!Nt>jB(81tOT`e;N$cnMBwh^#$)KrVaEa>$eoZu=f}G94;hiuKc0lGvRmq`=bB} zF%9;)>^i+2_)O8?>YUj6{-5bD)0lwGxCgA?$``|7V37moS)ujL?K(nBrw^PUws zf}J4;ikMF?d&V#e;0!p9oP9{_1%0j>QgsizITCR3$IkpkwRhzzG2PK@U-*{pB-q+)y zh93yv8nEd$9zDgPLOW($o4JdFF`4U*`k-bHuNQUSo9oE$fpF=4iq7mtMb%?jl|yrk zilS6^1L&6E`~pl0RwsWc5L5dy!&eG2dzDyw^PVB1gaW{3CHAiSBfc_f2ewzEVFqHX z7?bL{D7(<3tq?uhCek-km1BfkBl)t2OIS@QE(ufD9Tc8qrv&d8maX9^y%}FmV$Dj4 z7Zp@xE2spz;fV6q9h9A9XD?pQx{WJ~{?=lm5HBjO`pSouLc%tq#e^&;g*<2_7jr0B z-2Mm%c+)0%i!o{GwX=rnWTL^QO;ff`i@EWc4En_cUd*_VbPj378bv!CaL(j3SNTzWgnD`6_rj>rJ8jLG^}``;F5RZIU2}Cq~5A zX)HRe4|O-rh`{rI;ma^-7avZVWR|CCs^scjAN&;+Qw+uK#4z6|Qw+wgW3p#0OAP0* zNrER@S|8Pwr3t~waBe>zcwsf{6_rW_{Ux)EKzV$OGD3Zipv<#Lq<`XrWJoTHfKsdi zY_*JVmQt)L8kwRn%Ri9!XE%ut`TPxQ#hsilSp#?pAbl*hGry!OcTyj46PbIp8LPhrDInKUJh;+TL)jAj6cg_$gahn z%0tBPrkuQ&NUoABq)lQ5^N%7yC7VqbSN&-ah5B!0n@Tp1j(ZS=N;dlc7(WfN$Z3Bt z!v@m*s1|$I{|(0jXW23Ic86H*P3nbsK9G(k(QccKY634KR8KYX+9?<=U|E7llIC7X zO2dYV25-Kd_U-=O&0m9cDelOm{YFd&JVRQVRd&{J_GB-vU7ts{)bq6IYqWMR3nrBMb71RoZtx5>jTY!xu$I?k99=tQidQ3tyI9281m@TTqMDJS zd5(qJ1d`lnli?cCJYmO0DUk`aAZMdM@cj7eMC!X+Qi#&F5IKSi7nD_sw^FhzSR9B@ ztt>=BSb<$>seuPo0JnLmV)qL;xGQe0cNfsV)X5P$#0)2hvH(?s3|1{WMX5gw@57p2clzYzX`cL zi&t;uE(hr6^-97fCEyU65oM6D3pf=+Fx1tw-b)q2#&4454oZi|M|a8@|z-w_v;N&ee;;k(?u7)~(%~}N~*sOgnuWgPcnM2&TtFk+oIP6Oo3U2WJBFIrc z;mTkLOE*2^PL;e>a<$%Jc`1(*UbR6O8$mRFnK5PCV2Ep(=m)N;eLyvSF!XYEM^rSq z!(8eVySd#=YLhx`9)IMZCsxun6V1{KEcT9OKb0Z1|8qFfoPII*e-g7#B3hKo1S0XB z_j>bG4-qfv1CD`)OhX6MDSpOLAo7MciYAJaw_5K!>f%a042zbGQjp z?j^XTHlsw%91owbe9q}PMsA<|cg`90f8oRTzRkd3L}2K zO|UUr!n|2{eZGH9IvEClDqfDh_}^1k;X5m4g1nkV>s%raR31*N4HOt$dH&qPNx#rG z^$I3kUcVKL#+J&<@|M0Jo*4S!X+IOz?;}s8-IiEVRB(mgjQ*W#;#@nOPQGdkGn%T&j@1?PjE~p5tL)Um%@+=3$+wlv6y3ET){>7f6VV z_DU|9<&jWF@0%5_9>I)kG-N7x4ZL-@J~ynZhSsP3}gdAHBi2JESr)v1l-`$4Frq zM?ag`Ud>V*n_|zkv8aAc=qTRHwA1Rize#ZD90Ot@KI ze0308J?;1=QgddbH4Y#wKC%d!a=1^M^zSX?e zTT=kYDt5{%@yDL3JT13;1KP*0f87dNk7iiwSg(vyR;lXNE<@SZaHQ4ptnQ#Q@DAqg zFt-Y>`8~KYj<{H@EWU7Ot|yIp_M{cacib#(GrDiSF)k^*dfKNEPlDpWhue+Zr#FKi zyMu0xZ+V&L{#Y<96wh0;bL;x4dI|09#e7LG_0M5-U(0SdjS82*-$y+t5*QP9STEk> z>=&v5VJS`}c3$S0sQe!?U9-yT+^$^77JvJfKXJBkW8NwpO-l1WmPyY%BuJOtUrE#7 z(|$AKyi3R{c&f=ueu`LTG;v?1%0eCs7yVYonnlPMirE{nY369Ahi`px=wYi97s=U^ zZo*$4*3i4OnR#)V*M4_&pI$p8J-M}Anb$C|K^$B*^P84t{p4_k{N}XyaE^TDFr3G= z1>_>F?ggT8Rx@KLVv$te6?r`VgO;?MBV)%59u9iPLxYc&8$VnWSSp~akw#zAl{}+6 zbl|M0P!X*eQhjKptzTD~qoZIbPF0eYtS&orn55iRo$W5GaF*P9`1?w>REndV2gpv91PlZ25vQte_*I3 z#?(oHvmFiMX&lF6nEoBK>j1m~t0dFHfxAe+o3L>xS7Cj+ zA^@bTYBmAvwCoQrDkVn9L!eL_T2aV{8jZ$nWevmwciQtX zsbFC|;9=VW;$b27ooMS@K z$6nL8S)O76Z3APY+ZKfve9)K9cn{iAer^}qJQ2?sr>L&x1)Osf+ZJ1L9NjFJHL=eb z5`G*cf+-1rsQxkKrnB94+-MHfT`kz!7R6l^z%VmlIA0*m>?wI=k`!I&`>P-8l{m0*KM=<>oApWm2-L9bQ{aD$v1Vdr>)zBI4L0i}lXS-10Uyw-VdC>mmQ=9E|2S9iJT#4HX}sI7bS|CQ zADU!SdynSw zvoAXTxIUVxwZJ&xj=5E{9J2|VJ7NN8G80PQ8*!Wz_gAe3JgB9PMGfzX?W!6HNU{J> z(-g&{Z+NyPKl>HM0#FAOgPt>_{Aji*CH+7T-j{c5FW`4giF-x%H;2~^qzA>MH?(`j zI`Td*syDgUG$yGZ5>!e_AHFDM(?AZYf&sL<7V9rM9}KCkt(5f+KOk)feuC&MOP*UU z&tT)A)x(ssz%Y)44B8b;ef!!-mJsVpj0tiAA~UG%hknqU1ca`1mxFz%-X4v5GSLmNFih$Ernj^-Hs^MZ05{)nk0rBW__k#ZOgdhrB|xqW6=v;vd& zk={?254=1-@aYRApj2}MiYJJt_lc}rkl1-baq!38WR|EmI_qneMimq)Y+E?+`r{DR zr9zzYKE6UX)S`gTkMw|`8y7YC3ia2gb^DX3GELq(YQ{P`682hFS)UP4=GVdJp5novDU>-n$eHri%#vFXR~BJu>d4Q+nA-H3nN4dYe4% z9{sEaH|>l)OUb%wxKyQ7Lx^03QWkLmrO$tEhuZA967yd#BAL`T?-oE6_;_#liTZ8FBdK} zVx867!MOAM6R~<*d?xzJpsa$oW4bq}3RF%(u9?+8(YW)TlwG|@BmBeBA};G%tC~S+ zm~WT6Ytz_kOK_f;(stx57<}s8E#(}knpq)~M8V%X+%jKhcb8q*w#jdJKd{z1_c8Wb zitzh|zdNG41?$x!czfmgDh+chHTz88wFPjm*BuN4s=n=$pmXo|Qw5e@lco9@(~tJ+ zQ1_6p>$uZe-$$zW-TGd8x>$RDZ*U=7Y^mtQkne9IEW;r(tR_=`A&8*dO7jpf2-n<- z^59*KK*YqHEBL9nZha5)x{XWISwD{}x#^OjyGda!TH;7**9Ysu9KpLm&`3z2m%OTh z$AhBS>wMwVihR~9dBN@TQ4my2w}$cf+5hs3b!2t`J$UqPCuVV+{A-zUN>0P-6O2+X5yxYA!@t@hW=KFBDn{34039gYr_&t?v>1 z0u9&Q?<4HVzC)&V&JMVQ;U0vpR52p-#&Ho8ZrbRD4ynFk&u*I2{icyKB5?oRcJA+C zSujZ-ffq%&dEmid5UII&<3YO`g=lUSp&HkB&h7JMt!wO@cdh8_C)9b41Z*C97(PfL_NI4&^V`%e_;Ci?Ocfu zN3nbALa!C8qWkDV19^fZ2d7eEQ5Nc8zDQSwXKo=IO-3%fJI*8Fm|FU|PwR@uIxnp@ zHaV&}KhJ{y*Z`3#$?}+qa;NC$f(3?zKo#0q(+BFsxTPDqnn6Uq&QIXbHIfx`80dQ3@t_bjovoT7S*2iKn2lzT7Ac! z>VQ<%tjs0}R(b$oLG+a}Waz?)=grD4(R+v5Q+hQ{aU1tR9KC24)OJ|@Sh8W&`m21m zWXGy)u^gnPbCP$f0(Hq3QN#h)bANIkWy!$0>Q>G~*rLJKrajMiXty*|Ut=q|blaNi zI`JoG1m$a9B(mzY-UO7mU=_YY?bPJKQ6#1Ymn!zmXwv9P4wmQq?ML86s6(^|)hfs8 zTJ)EOvg)$Rm9g8eOK?FPXI4uKZUy7XhA_4>Yi`B1tGA|0yyQamn71u@R!_l2X)B>@*TN?lZN|ek*Tqca@JD|*KF^{ZLP|2UX7^KEZVRw z$p<;g&mLdn3ZMUF2K86>U*{cm@n!#U-~#w*x2w-@^3k?2s&0T|YIjLR*A~~d<)p65 zZIWTpwZ(qyq|LVu04)R^(H|OiFBLxBA9~y$@rNqxvM7AfGIZB6Vst<36)SuqHS{1g zqDL$2WI3KJ@H<1POlNJaTYeZa8tcKZCA+lWu6Rbl}luaQ3+W z^mynu-oQo1;DTQNj^5D7^1ut<;8bh>QR`5j&%oXDAOKbhwxlS$Bu}Pfc(C}H1~dsO zIs}#US{2_Of>v>gHgHM?eic9HfMynpP8LhLc#5x@K}%jmdtMb4k0&9TM+v?KV|V%Ovz$+Mg2#m~Ifi#Fuk(hF-fxOX zd_qtVe+m6HvZDX~lJ$@9gB5$knvyqX8cZNO4Uonvm-tsMJx?wr_-I236OsZG1`HGO zSrb~fEu!cxI)*KZ(=BR)Ez?b zf5HrZMUYifP;#A7H>p$ec2&3kGVKsGV>&YJLqB6>JMDHdW0X1VsXt@OKkeK$WATz0 zM`ucj=}9eQ6s{c4l9>PDCwRs%MB6^=is!SoH6x%HYY6&+lf`c z+y_O}rk=C|Le$*69z2nMcaZzFU47+ou9M{xhZX^uFuKc6o>Z9KpCbXb0hs~(0WSff z0l5LF0aF3a0TEGtfwF-x=2~B&Xz@5%;-_ynpJ^^#_i3F~Y6ko5PHNJ|%mvaPO1p>^ zHf3gH2vJL!yONuwtX#NC7?Pn;hbwy#H0J*#6^-SZ%i+QlrW1HGNiow2cXwGkk9Trga+X-)%`pQjwj+DSjx)*sFO;M7gv#KnFK=K zRtAx!$&>y0)W_WQfmdsTZB}ABGR(W@L4EsZT(h8OL&;YK#RZG_iOgBLvX_A8=1pZ{ z3={;8CG<`;g3HvAiSj)Lc4^ne|1+S%CR?2{Vz9h<_B$Fbrx(@G()>s3%x2C zpZif^+OzQ&<+SvHNu<79Rk1=?m$s{pNF;L)Lw!{@#oON0<3 zFcF$LsD^~CZN-fcqiqyBsq1d7G6yir@?2Kr&y@7qShFoZx=y+VW zgaXt;6~)L(`l_Ma$UhbyJp7`2qr4LIfhO#u%vS+WzWEnB=)A0+3dYm=k^5+jzfmzi z0Ut5b>@S?3dli!oE4JU_QEuAQ+U;yi+N+p&Yg!iO@NA;l z`qEWL7I>zTu|(;rN(xX+LO%}AFo!XBL+r}&XM;aHR(a$#{XYSX407|Eehd2j%tmU< zZelmJo7*kyW_C-vmEGEIW4E>2+3oEPc1OFD-P!J9ceT6O-R&NBPrH}h+wNocHNtNk zCmRm!R~pg&NIeeJ6+7DRue&SEoIaQ3w~)$oWNW>rP_|TK*FNBlC$A!3W{r2%Zp@{q5f0StP;k8H$ ze`y|G3Xe>fG-cY1S##zsShQr>idAdYZP>JB+m2m(_8mBM?m@zpoqgV+ss{P0tnbQv;b$(AEmkz#rB6)22S>*q4h z2!aPA1_A&8V22D@+qP}{_iZ91EFvluA!-=t)r`_Z(wL- zY+`C=ZeeL?c?hw_!9&VI1T^+0KkI&KR(;GZQHhHXWp(= zqgI`I4H`9R)}mFLb{#r(>DHrHzX5}W3>z_O%(w}Yrc9eLYtFm{i(0FgkDfex@#@XH51+n#`|;~fKu}0nL{v;%LQ>VvWn_IHTKXj1rP=Rc=cp0vTfUS&)#g?cAH(B+f5(Bt^d?N=-m2}UFUaZ zUOlG~5EK#?K^=9~Q(prOHPToUO*Io06PM6j3oW(MS{rS((_RN1b<$ZEU3Jr44?XqL zTOWP()87CC4KmmeLk%c025}%Wiw@waR-@KSue|m~?jI*MBAgC{Vq*dclT9(zG}Fy6(=4;i zG1olvEs(U(B8x4tGYZrP zcMBf=3B%)z|LcykGM{jqs#KM$Nlvv5AK0@8AZ>3r2;kZMzt4TPZQHhO+qP}nwr$(C z{S9hkP;Hci{o7|zcz?p--#7n5yJjio(OFpi$LHYp`$H6_ zvIU{4;lCUFQ+u<`{>ARx=@`3R>9=?P?{6}H;T%BZ zcijZUMPj5xdSpdz6hv{9MP<}PeKbXDbVPUb#bAuYcud7?EW~oG#b)fpejLSVT*P(U z#bdn0>v$I*<5N0@F)Cv-A(JyLGczaivnWfmBCE458?z<*ay%DuGmr8*U-Cl>eftuY z*>YNbD{7^!qE)xL*4SEFd+TbwZJ-Ueu{POe+I(ATt8Jrgx4m}QPTG09YWMA>y=rgU z$M$(Bq<65Cq3nPE{mU`bkey^Bc9xCVMK)nq*_7R6Gj^BF*+aHqPuY^aWGnWTt=UJm zVPDyn{bW1#m+d(~cHltSk%MF>4wjucM0Vj&*_Fd&Hx8HGIYRc}NZFI4WG{~P*~a*6 zV|})9KHGSoZGz7>(Px|FvrTq}%t|-Kr<>~2P4nrd`*bsWx|u%RET3++PdCS>o9olf z^XcaMbPIgCg+ARPpKh^Fx5TGgDra+X*{0i41;Y;h5TGHl3- zOv{2eh|{>QnzC%fN=(N>ID|8Jpqg@Q%*ss9!Z?hxc&M84Y{Dwcz#=$;b9khh3T(=% z%*diRit~7^nu=`3YRtr9IED*&qMAx<&g#s};y8|rc&eJpY{44L!V)-vOL(T5Ds0J` z%*v8DiOYEI3|Fuf`yFu=+vGKDm)EgF-oQ?I6T9Rs?3TB&N8Z6+c^CVnM*r=xr*J@? z#zA=ohvZotmgjIpp2tyn0mtM;9G91HLSDv67h*fsV=k7{SM6D!xmn&ZsD@W%4ZPtj zsL#BNsImd`F_OxL%+JU!ENH}5ti^0B#i;t!n5|ix*;$&=^r;Ekunu#u45RB)Q?_MY z=44sM(5%fEQ#NNT$55`IgUlUtlzD^BGGEX~<_V_CoIy*OKWHTj1g&Mkpp7gPw3CH{ z_Oghdp{SqXYmVug2mlxeVAy0>>775JoS%R;B^;Q;DR{5qx`xww$OCsx+_iAm#$5+@ zU3~TUm01InAW0NUDt~OO#tBu8eY&rveqJs_Lncny8stsFm8NojRzKx~N2D*2wz!zHcDI4gSl& zGe7;AiT=`na7aQ8A2vfv^a9WaXP_d^!p+FTt$5UzKJL*CPvU8G$FumzxB3KM;A(u0 zez*YxFdFw_ET;Gt)36#ZVgrugV;rYLf5tEcLzu=Y7|UE1U`F)R#vImW9V})&HpEgk zVNV=+9} zygASFEXk61zNK3xFR$Ck zs<~RKwc4t^I;yj}s#I@*9@V2zX(6l>!gU~W^s#6DnZDO}t=9%^)MjnbR?lm@c4(LO zXul5Xu#V`cj_J6;oMnJ;tZ7Lhu4RotNExc6ToA=dQCjrZR~39o73C^lg(_AxRaXtw zR4sXjMRnES@Az785LNzWl)C@W%b^k+aslLf5%;9@{4|7$nYcNl5YYp~Wwq>)6wXrtrY8|WtORR_WV5yyF zU$V@;wtalv4#afeYX24UwF|zxBKHc4e3!WBoc{N{)CWWY;*o-iDD<4Gdj5^j81%R^ zgh^4zu(sho62D_VfGfBXi9GIzWDsaPK!l&?7r z2t5bGLC8Z3fN_jR4(qb6&pYrZwF%=Y?&kp>ghR|vr7f`@IYGfGLBXxo#9FWw92htP z4zc`(-vC_8bs#rzBgD&eon&reFM^J6D+BR3+6yZxxiJj}z$3S(!xB3FbQy{wm!8!5s890_m= z=OQuW!x&NN@A9KKIppb6a{(~a3;;cf;r!8(u>ccT$8)UbS?`WmGbv)tt0UIDCOUUs z%T*rNajnPo+~9FTqyTU9T=((zh%4`oSn?jFDUJ84k}B~&uj>oEKjO{dUfqv4LZ9kW zPSEH2juZ8R#&M=5Xe~EtlQy|n?bJ>er`_7^;GG`7?TZU!e j84$Uw`M;kINzwDcgB}RiIZp!N987Wm0000100000ycIT$ literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/SourceSerifPro-Bold.ttf.woff b/src/librustdoc/html/static/SourceSerifPro-Bold.ttf.woff deleted file mode 100644 index ca254318fe9ea9fc0f3313bc5df7ea5109f16921..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93248 zcmZU419T=q)9#y%osFH1H@0otwryi$^9?q}#rnqgAY#HI-|e^GRS+ux;0G(I2l<(pyqppMaAyqwScL;XbRs~7$Ir!-R0IJa zy3YUrJRbl+$O}!&yep?f$N0@R{>`lNP5S!1852e}2KE2|j57d${N47ubnl&9*38<& z6aXNn2LS4n0U$CtQkveR<|YQl-@NMIe60T=jP4&Q=HC~;uf=`We|-}P>?@p%xs9{? zw_GIOBFh2*=;&*4c6ruzM&JE#i@(PS1^{3Y;5nN=Yz*AL#|5eW=EMCDKX@|W($>Jn z1OQkK`sPms03d(Ew4Te_+c|y9w(;EuH3I-(DIIwpuKF*gKYqm0pxQR;A#y(eKtYec z?*UlWDVX{1Sr=XHbMvzu8XoM&cVEzN%>SF*L5%c`_4RjNn&SWbnY-WW@I&PA_(SyD zzX1&p=K-PhKkYU~!}|Ir=7#!^w{aj$piBUgd5{Qq5Srj75D)+=_!YSa*v?c=ii%+w zV+=D`WNHx2JtN(^!Ri7Ni03pK{fEY4eF4ZRDJ-IjoO7A}I};{i3dxK2>45`i)d*ue ziof;)6v^Wcrfm2>-%`1Q45WZtn>00s_^qJ~hF~3$l4DIPTj>8%x|IL>x22VW>3`E+ zXEx2*vAJzRQSCpuG2OMtA9Pxqu81@hMppfJk zYdEO)wunh981wpedv6fO?d_N=Ve1lTk0vauMoDK`DwRCa9Imj&h_8+;Yc47l@J=Zv z(plIOg{8F~;5aS;1BC5ihz9-8tPsw3&CN&md!5SY`5qY5wt^I zM=!iLN7g$%L44@9zK{7-fkQ!s+iDL855QYvgye)+DJvcQr?RsyZvbvUBy;Rbs$G-f zlUVg-G$r#9k(9}wCnv~y{mPo;<)c!$9v`b5%U9}+cP zr8Wvm|K_Cpd=0xm$@rBZd=v_a;42gA7W=SP30r1m$va4Y@=`s&Rqc zMDnPlKKF9PTfTy}TM8X**|-(?0mFvz%R{u)rd>mq`6rD^EXSwO^FkB%VP4Gk^^)A@ z6Ug*nGSeUp+c{K^DFGq|R_f@=(3)H_!4^X$550V z@nzB&Es)9RvkT}a(T{odr^4YQhYt~b$&d`rlnm(WHMVQbbF(fY zSNd-b=M{q=EM2D`9#G;u^aL!9$oo+F4VBLZ`Z>CV4yuEC9DqnAON_#1sABqsHv~`<2 zKeb0(7;TD1v3wFh=*h~bQ-v`IR)g>0@fORjRf=AoiY|`d*_p8Ea2#@+o-;i&)kogu?sy(5v^-Q9PEJr&Te9!Kj_(Q8Z?-3n#WfJBv*i=EE)Xn}VGdC=T9;{v>^z)_b!>=q| zzsFxFX4$_Wyoc@OwnSv`(&96x&xofpIhQ%TXW4x)ifY{m$L2FN7|gC9)5?)>%~-5E z&>Tj$h)A-u>3p?ml-t_=Jd#Ny@H(|$1%80f?^ylb6yxirvGurZ=iAye8uy*a z)`#_A;k+6{@;MYL;^KVug>k^_3niGl7s?_OqOoP=pqe%2GO zD)?Swx`RX|gT~={VGK;QJQ1v|%TAHh)!3{x{?Eacer|1zbN7(GD#_!`sgiP_x2Fv- z0Q~+n0>Jz=tAhlHgMfK`iU|AkQTGKw0?8J52H*Yq>5+m+S~H$(qumSn-dlyNgK&$! zbzLZYs7Sl#Sh+1(xocUuqglCUvl+kVC@nip1x+ZA86=<{B;+p4FDxu*EG(cbEacqJ zFWoO_-7lcsFXT7Cw6A7?OPei%bkaPv{PTwIvZ@bVmx?7yknk51tnftQQZx zANG$L4jLa0D1RqZcvhMO84gzb9eIiwXt5kSO4@jJSn(zlvb$X$+h80|0JQNu628@R3;W!J}F{4tdZO1=xjYES+hzOnPV~fONm^c^`gZlHIM4Z@8RDZmBZy zmI2ZE5A`5^c2oh+ePNJ!LC||azCu&cWMierBX`+dLECLS-a|DBl9htId01_IIVafq?0|fSmtJVy4%0Z2y zR!haZszh1M!X~z5bQ77@T!qJ?8dnD1MvM`8Jc>U= zBfD2_N58IZRsGWP*}2T4s#i+K(&kmfLBvt5j;&e_Rc2X4S(a6;RiW0p!N$xw!-m5; z^hPpQLt9YWpSBXSKW24iZDv(RIY+5S%KA~=sv}0ERY2M&x4k=%>UfYAd8CFJq>dW@ zlhk07IhUJf$0{<7(6gn@t9$3@Enx$OP9?6TyihB^f} z57XJddxhDsq>1N7r0M6zf7FeZGp&u&I(28TsY!=<80-FZLm1da7`R0ku0FVdQbX%NwyJfGmy5dhS*X6Evc}TGLIX5}3pEVbLQQ8!W%FqCcyvc#N0oyRMJz}?YVKq?BwpG0&Gh~^HKfSemnL$d-Hb>gLi{1>~4Gc z9Exjv$_CwRkhQ+AynAiu>)>nO>ey=6>&WiN23&DnXd&Ni zeTcw&Io~2{jiCFJo4eV@el90K;BO!!L;<`c9uTt`#o286f~$#K#|PG*`bRZLw<>_E zCNwIMqE>Db;7>N+Z)t%)Q3QUi;o8g`@m+?KAMykW zuZYPxi*{P2RdnfuY@-nJJ}zro$)9iXnOJ%9GedV;%2VXZvbvLz-ay6~1qC4O?6+wa zlZtW})#A@Lf_pdA6~BV6+4OGGHfjxZ!TP+nH9G#H#CPELwx-u{KGk`@W;E>O8=6Xb zN0Qc`kc}*ceVe4cjT27ZWn8$2B+;K-wJK?NmtU$r8&+i!dJfcq6JRwKL)gFPQo#a> zuqcbc&kGh!f4%!e^$34;`BD~+7*G%4e-ZfcRqlak?ft~xgU;H;>fC|!Wu)$V(V3X| z=c|@J@=iT!NZpe_O)93Ip1J%trpbZY%mLSNkK=Y5Tyl?VbO(bHsaQOZ+q+m;z=YD0 z3Hg+P@|2$Olo7^~@rNeU&om}{O?qBUMi9={(F5#XEV)v6VH1i2vcD{ z(_Vhl9)RiKFVg|~!+!C@9(DBY--jlI(qjHkrX!#k(q5{=C#n-Kj8mf$M;KLjM_(^EZr`)3o$8nYN3?(4(L%%r(_tai^h68WdngFJgkW+OdENLWEUSJXWRNM_0g z7p(>hmZG)nQvZ3*k<4ig<~PaY+$VxC%7=`JV-cem6O~TqQ1<1(qvR9om`{;lj$32) zo@0*UVoqvf_N-$L1z=9~rgjsl_d%$Sg{TjSF887@k0vh(v`+Zc*2G-0bxXeb{^JdJ< z#&FDr(#)pR%=*svrk3}Hl;dV5)cR=Sh8*Jt;NvDD<3^<8rXJLWEYt?@)Fv|2Ml{r> zE*ZOkj6?p61O1F6dF^d_?S1=3TO$}SFTCJOG3%Cyi3ILg_MWct;pBhptJ3t$G9+3~GuuCZqQ@4~^z z=8nWq=JsHI-M|RRHc0E;Y8~Y<)M&sN^{VeiO*oh|C!DGEkOvs1HYgNQuG!N%q zBm8pih=f}WEH z7P8`W(+%|5-AU1N)C=W@cCSF1PA^EBP%mMcQr;SKN{}@(Tj{TyQenSYOJv2FQ{)d3 zD{*#FE6IDD3ep`nO&pzT_EyPzwhJ;s(hJ%dzWUH06zAkfdab;4XN1GFU<>E0APVQs zAS~xULG#YJLHEw_L4L=E&{!wP&Qq_0_(adCeuf!B08qy~&SG&{d_ z0vpEVW?YazbIwR@1=+-h`Pn4zVK+z|q}in06Kvz z&fP@p0gwuCq4r>C_VX$|3>m^W8IEoatMGkT83X1Sec(}jBG6tZq)kXE4)AOC8#?{) zZisB8mXdZatDx&{ey8eZ%Y-@pCHde%_**I!M{=X7b} z!&UPC>cANPER(Hk1rC#`{^dPP*mbBWyoY|m%tEyi&vyKKQ?E|^8Z{PRHh?{M zq^-(Lw;0j6oi!L~NOLT8DbY^77~Q$6J5*+fcWiYj(oV4$-g%(gyJm=Y!gUGXPPdrp zyS>>PYRGde_Kaz_hf$0f>YnCDj`6o0K&?*>yl()cPmQS!r&@ zvZ3atiWqoJL497?A4x+ga}zZbm44OP(n{LW@QQ*39ie$7Eg7rU*J9Gfh(*^2c`<90 zinFx*tYuNnEfyi-8m9UhoFFp8HglyVkcs}snZrt0&9I9?8Xd8E%oBrU;mfaieAkV=ivecIU{NJE)pp%nP8NcaN3W?WOk$Yty_l{^UM^kvi6RAHK9 zG2{*jDJkY?)ns$Z3Yr<`*3pMPY&L+^29&k4QO!v7kgE0EV-VgY#s(6e=whzSGnm#}izZo7|pAd%)0jp%=_m zGsZN+1p_M2`mcK-Ke!=)8VKlyK3p%7azDKq8nHG@lrszc=)<7-xG2K-fFZCSSq)rD z$A!92(z*8=v$7f-mYVPQo-VE^6|TdE{rp2e1Fo1`hJADk6NSDiEb2H=S_NH!eeKW zXqi+cyfZ3YHL68-QJgErBH)p;|KaGcTE{=5Zk*!x(Vm-rFmLSP4@o?M$x3)9XSvGl zX7r2OZ}J4gB4-z2Y|J&2+<<$o@C0%p>-}@vsB`~yL;5<+6Do$RSE$!~bW_ohU(_xO4wddhT4GLSwlIe|VkIi4P<8b=?cDolE)P+uCv z;G7ne<(wSE>s%HDZ7NrYL?xyq3G^>Srjk>V0><&uEJpDXeFIwD(Pm=N=Uhr&hab&Q|)eLP?wB4>y(Yj$B zjc%{7wAz$y32#!f>Eohkx}Ge(aA!ME-PCE|xyoIi@G5mZ=m2`T+bvwS$2!tom8}NG zDsArXsT5s9k7{}6ohtK6c%;jzW)2qpCb%srb$Vw0-k0gP(CX!QPhynP?nDCVo(&fY zyeno$mr5@8&yo(j15a5y6)bkrmEEp4B+0k(TT`yoAYMQg^54Tw4Sh9VQnOVacaDG@ zzPc+Zdh&-aA|`IW5`Xtol6YRwOw#mJ9(R|3SiU+d>09!qFES>GzEXd8o09Ne@Jv#- zR9p|AfC|2PE5Us7gU>=HYMkL*Ne3$WlASJ z{@lXRDdSB>0?j;XPN8)3xF@AlAa58CBy=k|gVK|VnnhfGH&MztrJvHEcC3G za8K!!<~M73#Cs_Z*;m~nKb6EB_#T+x%i|3Nj>5jDpPGN_SnTsDFWqKKqI?y!#(b%w z-}05>JnNY-d=<5ZhXP5t%Ul170SmZGTZ4yyBHWd&@#H|;Eai1LR z#OsXNvAa^pJ3r`0I8sPVF$L}|zl92$wY7dzESCR`L7c5~R6S?D4Q7dy2=mqOFw3ta zVpCtT!3+F;BZo(M3Kb=a_=pjWd=obMIrPcDH{eqkF236sU|!qo$1KwhYthxU2 z&5(2QvJ$7(IY%b>W7s5ymmo$MPd@CxGaPyPGR-NKu8O(;G7mP1YYIeUW}d;f?*J}q zVAHsU4n}VL<1lQpu&Ft#4_;PTg|K;e@?M3hNpZ$-t=pRQS)THhi{1YHM$Gdk@qFq& zW0}fR;hd#|WblZJ2T9<(sy-1jdngL2=Bhpmb4%~Vq~~phYv_*7$APLOuqH);&b?0U z<|pm-_Pa+t3TNHj7ia%8D$(CesU%U7T)yKCVKw;x6lk|vO%r)Qf9sz1Ou4*FJrq8K7N2k$<> zfFAm=hjJMrbQ^a)!0Z~DMK~&Cp@yMxXpG#xN*d-9Z+TuYTL)-4kfqE(H_ur4Z_>U_6+T}%||I8 ztjwVz#iEp{%-5iMp*pl+;-c4~x;2n2Zz$zBLj6)uubeVCtLr&t|CjpCq`^9+&r#QQ z%;^R9lrZ=UDgY9|FZc`KZ%3u8W8?n+fc6+AEFljukC-XeG~;xSCD!dw-5u`WnSp~b zl;q&Ej!n>Qb`Ady=GW~fF5MeOZXu4K7^M8mX+*L%375odMCKOgP2y)^pqaH;IALM7 znjKR(cVgI@by+xcV&a+IS-7Qvn(S|poMB@6qG7=b#54MGx5mE~=Ej>Eh`f<($G013 zyAkll%^pa(k?|(r8>qSwd&m1iV@AA$tO~p$iV*)*Z%&yU5p7t-PEi>Vx?Ax~kuO1= zJ{nV7g-cO18thoHP7ymAd0Xj?)dc!I_~v%;3x~lXC-6fIgOcXJF#EGkgNAg2 zrGirF!{Yig*@I?vLp~cBVw<*07&)dA6$bqMj>*`u)<)YU$(S;&csBwoOmS9R8&mL1 zpExfl+g>Xh&MqO^ZfqO1E?L_?F6-Ma@!#rsi|9_NURyg0u1+CeYkUj!PT5{NKL2%{ z61+Bj@(El6esREo1MaQY#LZZ37-w=mzO4VRy3)NGUpD2CWB(DYKoQeY2#>~V{=+&E zevMZ!#?}zlRqwU5q^aS3iFhe|)qSOUsS;L+Xcae7igd)zYx&ktnrdN#g;8q^Z==zg z$HmU0;9GLyq(cVnB=!-xQ8`K3uw`vXIqBK3XYC(rlC?hDJ7sPZ@{F5bQvFsFPeQY=$2e4V6de;fhND$F?gT>oOG~9H7;wnEIU}y4$OM6*)>9^k+gJB z2?Ok_LS86%HHm8P>N41xA=`N@u|3gb??5v|(=IP}48}DXZ?D=j^p_JD;vYe91pt2? z@8U|OOr@F8wdtkwe*)DyW#9Ul$W~ifXrc;}zK|;A3&b9EiFcbleO1yQVxbc}Q`WuhLy=7hQd*g?ORdmbNjY zYn*M*$W?%M>Fj#Q9-7H!8{0jH6$h<=NSAoz-jNj`Ntyt0F6BxH^@~t13-2&{l*7X74PUD%emDh?$n0!G1=a%$d^QXZoeav@uj%I2S| z@LN9HtdCEbuiTfdGwUGcP?TOdTlyq=-Gen7*SKum**U|QY1J}YU9m+f)x^*txo!&E z!G*iqX7<_oUj7TEZ#KCWT1A?w&{#G1S^CCAmI+-QY(|KzR8jui+~3o2mt;<>OetHu zrf{6*&<^CR!;4$k7oHD^&x;&Ed17-U_nzi$aeJa>q;)9#po!jsoez2*Z*<=XPT{+} zLZg}{!abL?U(L1*>&UxOA!PosAmvvulYLosv4#|jXFAP&uVxjvJ2>D{V+45bO-4J z*{t`f|Mr(#BQVFe^jR8K)S|5VT$ns^k*Cb9GGqi!N*o0^^?B^JJNPz3Z`9kWvQ=r# zR-6uAiqTaq&7U1VJUqUYyf^yF`4vySBqM%`eksW_A7jPo%UzR}<3B=cxHEdAphaj3 zyVeuGVl{;kZsPNahRb`*LyDMFtcE@2B_9814b;t{V<(i2blS~pCaR3o+O2f|g&)a+ zyHny$s2iERBlk@3FXUVvb5zL19PT2Q4Gt0nH-{c4xzBVNv1kW*Jy7jBnuP2`!d5Xu zne0KrYBsZ+yluoGEi^et#T;}sp+H9KC8FWKPZu;(?)n^i>wziziYLv6K z)0!xKOtrS+{1?|)Wi{kE{F@#UHvs0RFbH7$e^h0&)V8p){%v3`URPY1_gUBHSfLe;)v0Buxs^6qQb@??q(E*%C_HMScGnD@Xh`0w#^3 z9b{`tW#-c=l$4frwn}dNyHt`ZS(=yAq^tlgN@^8m&eNWjJdAtVcGPWZ`I!J22eFx= ztxQ#!sx;=QtzziOQ<=uW4^^q6lLk($PZqV>Iy<_3_xBxJ*~>DjCiU3WRIE{Q{AQcgpGQP> zgU-wUrpd3fr>o1$cim>+I#|pqcQ*g64GyQt@r=LZ3X*V0U@QE(!s1XAgycYBQh}g( z)du4IgyI&Yd{_E)zG|JTSsL zTr8%cl)~HE^bn-Xyfpulwk%Dw;tVK3Y8>c_^mp$iHLP83phJ&v>_fw z+ije8kkF|A+RbdEyNDc37;0+FT6WwVDay*^8qT`O&LNrf1p?%33(=nA%z_6TSJojD>MN5m>E50 z9dmQ5@ocqbC%q8c?OD<@+SSV$599B?Go`?=e8se8F`3s)E z>}P{*{A~>d77=Nzb=XutMZ8@ku}8+U$>}ml1iwfMONdP>9!}yLNF3rf8(WzZX+CH0NlTi6iHl=`~pA28YtVL`9))%{>$If&gm5 z5f@Av2V=*lN+)bht_k!-6{~3`tjf>4D;?eWi=X}Wz6^TNRLFT0rTUojr}yc#06x37 zk3uCqsarlPb~1$NQNL?&O4Xbi?$NUsCxwhzIZp4yKR@cYEs66^f4Yz!kCMeg@$+zW zFZnbCMg+?-e6|X@&+{VlP`XT(J-Z^vK!e35TK9&r-j6~R4TfRM9K()same;cVy5Mm zHAV%VCzqkO-Y)n;m%;7#b*@E@6d9+yXjxFu|#PG@#NV* zGyebx-B@5P`;q(=Smpcj`J>_P*ktd%*c59HQ?^k@ zC}}}2DpYjFa^UUHi@3{!P7|NevvK*SZ%2Tm*dsryFCG#=(brN^GGgy;$eEOu1r*mPn#W?JpUlbLc$$j|ro$*HaVc^h7w`v*&Otu&%>Y zZ#zG{rAE*TV<)2mrTn?7hx0T#nJb$Y%T=u@9EAZ*$&yq_7kgiAKh04Eov9gnG!FP zRTMh?@p9x+tsSXdq{q?gaC^R}tLEIZ8yae&ZtE8b5=5jZX0ub_S^piO474D5{o$|h z2I~pmg?)~%Wdgd9)PzD0^K=#a54hd%K5 z78=O37;ALxrjsyJLOU$kebO*_0i*(C1|Zp$KJv659f%FFS?0!5;JBAMiUqUspj~L$ zn2^FjFKDnCDZx(NLT?>%>~U7Cfz1uKQm}8u^k)b) z7|mhI>X!C>m_`;bGGNWEDewG<;ym?KW*PgV#nPJkA%#v^^7l|c zOC3K`LMC4s-@>qLQ#?Q;oTj9PiW~!-XeMNWn#n&wx&%zDp9%dw!p7A$L^(y%*syV! zu?!zK(Z2(o*iX(b(k{*fb0}Drz~Wxft{_TGD}4vrPnY<&DQnbx&+13MBZ zLA0phDy$a@FlJf)-T5CvIof5iHDTh)6YW{Wby$`(E)uDJBFV!8i@{p1{oD?PcSb4_ zds`u*nAfxU?};Yi%7&Kq=9L5TcmD+So3F!(Vj=tlOmBa%QFc*l=XnBEo<#C;Smvcf z&pq8#) zw-4a;Y?4UED{;Y`uninLl&3tX$>-d3apqEfcrclyCM2Z9h$eym>hUf4b~wUelj&v@ z6dCWVDe6iRn>idAhwU_N{eGIq{{p}=ia|eL_|hi~jc#_N7k5|sR!nLe?_4jU5sned zSXC}oFGdd;>8)!!kKBb51UTaJw#-Zwm`F;E2|b+ zetTAYKEg|CRu$q^d~S;mW3v?K9O&|-v(9A(_|`W+bx~a=8Rlb%I;=3mfY$7mWlY~? zMOE1V0^Z3D^v72@Ax>Z9@~(fb6S?-uJjBe*a9B;|@^9dBjAe@&LqN_g_VJ@t1 z??^kUd98>P5h4rFW_1)3ei9o#s~U+X2kez@ zCo$hWmn;#6NicEFYUv6a`zrUKuXMxeXeejOrJ<^tlty*I7s!-J4fb!bek!*YoD(To zpnWA)8JWQIOU31*`8Aztj*SdT3ouGX()=i-cg^P}uFj*zS>wUPQeG5a1=ws-epOrhvqI zpf~$kI9@NCVD!ovcsKe^Ury7ku1u$v{Kiu0zej2Pl#%pczi2t!M!2=$`g4x4;ED1gkS#@Tvu3--7BDsmMdkR5vw;rW|N~n=R*3pT;t)LSmMUqk)vE zvkL3Xvx`jGBGcDbQ>{L&r^~fgm#xi;fY7sPr&fAfte@R@D%$eqoCT+($W+z?B6KMP zm3!~lWuyHNyYF-C>{X>wvwbf%2ePLiv+q|%fUgWpWr~;V)6lBmQEp<9b{>XIoK&fW z#b!KEmn88fU-~Y&C}V6V1*FP_H{pJ2@ixmkeLfhe0dvMh@>~@8>&DgT4T3j^T5|}YV`_BybJn3A{whnvY0zvd zpkarEP=m=`MM8QGURAsuTPyQ)Sn_Hs7J8X9m@@U}TRT(D#UL~`bsp3^gO&3NNiJe` z`M>kSYgCHoSC-Rc>L0s{$MvVvRM4FD%KfDEHA9vmhx>v$i|LixGl_cB`tD$xR*D2(5$8et>o;#zJ(r;L3wF@%(HQV4 zrzrPjysMmNTu!|VOz7t-Rm{&qFqdj(Q%<1&?YP;!-RPI%6>W0Fqij|+!(TCLLctaL z<$?tgnZ2Dv6RP(UEjZojMLp!)DSWLqmNg*PWDk>j=PBhz=-R*cN{!agRQOXvf|OUQ z^BFlko@N9OMrpnXjD?h+uO^U%=|~(T>6BRSFGqq~rT(q8vS= zCbmUyaYJx1YTaqQD;nYsJYv6@T|Uoz4`b%N8EQU z-fvene{L|IqBkF>f{C?Ytoq&_99jOk1zY0W#3dnl7QMyX7}T-Vx8^fV(!yG+`Cb=z zEpE7+uWxLa9JHjrWH@Q zkirlK$%2SNmF&1SE8l83lS|`d=S}6b8MG<$1>*s{c>Upt<(m2s zLUx+suw+267F$dH|z_VAJHa5xP~{TX{4 zc>6p`e7tybB_!8}K61q$+f9pm#9@(PN-AegQKn|*(Up^lgn3&-vPS3Si>*c}$_}UJkAOA@X)}!V??K*?xqjZ~c{>muo zH(j(eKab?j)WFNuKt{O5x}$qIWjS_r2QE+B3CH%yBwPu(^%_`YXxsyE_a?ih?|5|R z23J&F4h#zZyyw46g$#aTojEU4c=zsNrS@zQ?3gJAviBjgY#`u}Y=vG1B_-$uWzSJ{mA9Zy`_l=wnykVkik@dR(e60^r}d~F!MML8kXIsAL| zwa9>WLGbBj{PGhf_!qMm>9PB)?nmH>JybKfMU&x%*}OL3sYCZd?Fq1@@3_T36VD;v zCM@}+yk}phec^Q`$4&emFc_5OXwURPcxUY*`vi+aQZ;>R=6J*VSL9Z+b#iv!iTrV- zC(6M!;LS$UL4S!BP^WOi>AzB<-|vN{>|V7yepV$!F*m=)Eci9Xo6Pd?{f|bqo!Crg z;m_BtfyROD+?`w@(mI=(t+Qxn5h9(#tXrzB9k0=zCGo&?hgfg1jc*LJ?59Q_T8r&W zeUN+$*<0A+^we=75yWlD{f0IqK0I9rS`*)So%WngpGuXE3FpEmhv;&=Xm}&>wm$QA;exz?iv)^Qg0WH$DdG>UChu?4bGXTOC4?y zJt(#sS1pfjG4dMQnwLigRraBH7q)NZMt9Qn=)=lbp)lK#f||%!$^;?6S07Sj8vEoz;O0-K1-JK*6}*W z2^=R{@aNS2r0hY0h1S96{_6QamA3N?6-Jd70>*M-pjqil_*T#Z*OfYA^=_8R-=wE< zFm=B-FFp%58}G-{vg{R1Aig(z-#O839oO&2RcgZHZ{!T>PLdEcmVWYpyoHaRu|%Hj zmi*=7Ido3VC^3Vfdl#>{Kj^Cc<)pfb3*rIe#^5KY~`2 zgoLR)$X_(;oSg`~y>$@vpLWMtIw4yw{h|5Q_a@+NX^U0#CXHtUJhEHGQD4J5xjrus zHR9#dYhItLF?b~*CBhwTxikcFq_-^>R=Wf9{i~+(5a)?*(&wGeX^Pxw7Hhy0XpvS| zG%r_pmH~nm$eg$ZPoSxx^JtPm>`!Mx-DVx{-YHGKjj_a z9*Udz#pYPXKIB5;6#MMxmbUeHZ?*h_rgI8A+10Ht?*q1~i>bko8EvZIouP@Xl}rnJ z#C)>aYELEapv`uoRA!XTz3ZtvvxHwwTZ(Pog>@igbxw#7U@AghW-ndZg~$U>cTF?)Zq&g4dLYZehjML1 z!Y9*N?&90Nd~sJ~m{mNd+GHy-!P>fXgg`DxIB|GCh^*LvVMtt{0Ji zY37i5j6379OunwU1*l8d3e5`1j`N1th!!Kh6pFm#7D?!xrqb<@_^xq6Gp`JAcBFD?z!w zpL;0xSeNc<7-}@pv581`*~#zURveWiTLh6Gx=NE7(!WwDWY}XE>I@33LP7j9L<&(v zT#Gm!v^67ayg~z7s~RU*r_2#qo~czBqOO&u zQuHh%wGpCEs3TO{rlsVG(qP=vYZ+cNL$)jv}fJ z6fTXPc6bQ0ZJm(w*2mByMJx*P&V?V} ztco0l`<-~OD^Q2HBzZ?@tq~Vrs-F&Rijo;kq$!DPauO}bKD*i-BJ(iqnO8Er%&xj{ zEvMmhl)Du)F9GM6A+jq3KPYIQe3}O-{vEfKVA&h(G;LT9USsn2&3rV@Y{H=CZ5%?+ z{{eA8j=yAg9ZO}c%<8sA`?@1EiZy8oX!*KZS`vB9A9s19tMkQ?#S>)V_c9|Pfbrwo zrjCwQLt9$6-`|Ok>Nx*7oPQ%UF0Pl7RlCr8aQkTH_5?e3UDT^=9I3v~GR~#w1$0)w z2fc{Sw;Q@{srR9`TK3mjbeE{-=`g-ttzx~1i`;V6$7_Q zjC@82`aHVB;wR8OWI^(?=q^$rJozBk(2oQIqCOx@*>VVr~0tImAt^`@fP*1 z%2{+5a{^{PyvLS1urwnW4Y%;v)@yzh3QO~V&RzmM5%@kGK_jGGD+7pej#73z%l-va z56%AVX&at!)pcskePMeYxM9;TW8m-G%eD>2vPl~FqyO>PZQ0|7!IlE6`F8IS+x=N{ zed+h09elrLxhG%(kJBA=R{GNQS{fBh@|C0kNSYJev**6$e|0zm)-c+Y2Silx-+VMG znAwt|t1hAspn*qrSSvWaXFSRH1b9FE7m( zigjlRMO=D)S>BzN#w*dJI<@3Gt?dIAQe z`g7=h7+-YNugsAg_1`9hG{CCU7C(XRkzEaj}Pym>y~;SdMmV{4=P8{+u-r4^ZUULvHiPnd|Hn#k1yBPTil1<3a!#| z&!W2^EZ#J}OSg}WL`jOB0bs-D5Z*r$ZJ9EQik8`pHpm`la<&KM;dVBWv_Nb>KFjv-RhG{Z3=qqK)YmU>TY}-)fKl~~0-;7;c`Lm1n zWm^7r!hG9N$9YyZOhyR->FFth&%;4JDeJq%(sxQobn;+s2k`gEbS(EP+WvLL?V2_< zXy$hdyHl;_^+@lIqY?P+i}vronEe;TJLBnP!)>j4hNXLtP2^hB*~K@-RKz?N;cxl5 z(vAB{oYO4rik={^aOd@kfgS^8@!Yl4>*Up{^LzS*;+zO__ZSnF`V9F=?mYL(=hGwR z(^z%IK#!5PgljA(i=HHNrqlV$o*@4wjWdt#AoG%+L-(Uw$JYtHRuSOI&OfDhtu()r zFZs(4{!SzP;m1@wAFBS@M`y@kbJPXvVN2y)3E=g&$ESybndWppnN8=s^eag2s@;EH z{i_ckaeBnxO_#QUFHI~gyx86_KfW(%QDw7cshK_J^NFVUWV&104^LixIN#S3cei&; z4qbUkW?f3%60ipx`Ob8IX?agaI$G#j74tdNZlH`DpAqhr_bi?uZ!$ODq4T>=-HRS1 zzew(@F^*2YM+o-`xJL2}Im?~rocWR4C$3`onr?&ssw?y84k$|g8hQ{)lAl2L$gX

zX^UHI^TZ)O|^S8`o_P z=h_HmQgs781_f!|4x(q}di6MZ7rM1RZ}D;T4s?xW*3orXA=SIlTVdSzT=*&F2zr~+ zfc2;No$Yq9?}u@GT92+nxn_MmWF&W^w?db++_UH|dEYbV^FcS$?)+FRi23|@)s=a4 z2mFlWub~IA-a1Y_Jj$J?)43PL_}iUUmeCVyvE{%T{-6ftZc=DZ(GbrYtth!>L$G|T6IrRUo?LFWmD~iYQ>3)-Q&N=5C zc6N7WbI!YWd%Jr%=i}h+;4*MW&PlR@iUCwGe-%(sLCg^azJ66uQBgs%iJSe`>v{9` z?d=_)pWpvrcjwjgtFErDuCA`C?$#h)9X{`(Gw4~khxZDvu^UnjdfdZHEZU)C3Nk4! zp^}m8SUJO<9eMMfzMgZcYNtYO*Ir{gWGs5D$>o9fTQ445-glrJNJPVdcvRJN?()&y zWueHGHFTEBTDLl{3|R(CmG)0;*>a+q-?Dl2#*LfSZKA1BgWsYGYZEyy&e_*P4|s}Q zauFr4WOomGUn!yWs#I=Wyu7XUCwd9?Lk+(=QJT%Su5Y4u_Aq;Texpz$AEx~J1+@-(+p_DxLfYk~TF&(}G7*fO1t;)+~#Tbr+9-Rq!C^$ozuNKxtPKQ;b_WV25PPY8hRkL0JC`rN*XQ4#yu=iiry0Sn? zy%vXCCDSVXtwyC3m0q43rm32&eS|~RTixsX9OKd6sNI-qiBrLdbu`&r-_wfMfrK{K zeF4S7nK!m7u_#wEE!oiKtFLXHC4@S^)@B`)<)VtQhSSb zBiw>eGi@dW$+lOA*BMTL1r+uw^!j*vRxP{kiiNFi{qYv(4+6tMd5WQO3s6}&BbBH7 z4T24ejM1LL4!`MUI72pnn^K?cONnTO&2HMZBW&I|88x6ucM9IblL-8f|2(n z`~jYl*UN(}69kiKku!zXyE@2Od6(dUd|=j7@B(?K?)MZDfGI%UAf_;sM-q`r=5zXB z)uTdR_C<{G9FC4=Yy6QdP1U81P5HcP|RaU*X$yZ$sv$|<(!^KHLnUF3dKhPFuAv6hdipV&6zSr zMl^+!F9y(|5p=9#l|MuLpf8R|#JvZ&!e^U>w+Xmp*|Kf|; zo!*?mq7iNQr;?BM*UmYNHsHaM^t##~J)K^ADrNU{dC-7_wv5v7{+mFf5PgzMofaj$Km<&h<*-3k79g2Jbyvmh%(QU@?XUCbAiT3zW*N${Tzqy-yq+ANmwuc zSIi^NUl!65q6U0Qc$Pv&fU*^FfL2a zcrt+&y#Y9wnen6pEm{N3Mnh2Ze`6)!q|UGTzmXy^GZJfY_6N7L14pB=X85?NjbL;LcKZKa@IPvu-d!=p51qGS zcZ3tML%se=m6ZeEL+% z;Oq6GK{5S)2!8z)C=Jru1;$AgbF(9Yp(<|JXaEp-3^8AqGu`GcrGyHhLKKHMf&{m3 zs}8J;XLn5L<0dpU>+N)<$Hx-Q?WiyBG3rV~!Q^NrJ-4Q;bZU<9>fR6Z64aRont?Ig z3Q2u*b!=y`<`UhjBwG1VN4cYr;Y$TlVZ;{HQl;74IlDWDX9il%8QZppFY#$zevw2d z6JFj~1>ZwUN4bnTf-ZNd+r6qgHLX`K@5oQ3rpL^NV6F?H%d4IB^CK_@IhE48L;^m8 zuiz=5oF?bV6);|PUF~h;J7-mG^Jgx*?6Q^U{k8LJ&<-=S<28^~KfJMoR`%$Zkj`W9 zh-f%^t@ncAb-M&&zaG}oVu@B(>S-@q5*E7w?WuiNlFIJ8g}6r`@pj6N4MGZHJ~uF5BKI$vO_LGwCzSc!+pL&N>o6Lb*Ok+ zGQ;N!iJ+Cz2Q1zU>fQXvN$CZLw8pZpOrH$acEN?{Yu)`?r*C}5-}An$_w6#|f_vAf zHSy(@&UN|gfeRAQNMfi@#xv8aX?p9F$cb5v#OQ#tYoul9Mqync+=gxx7#N+9o$(}t z&00MuhTN<>87yn`w06+AlutHQ&7dIE@TuHNbVM-LSC$ik0Bw<_@AQFwaY7 z6eCZ;#^%_DQ>V=@NWJ~!$?d&6E0vuRz29W?8DNcO^6Rnj$}6wBvT}IU%EOh~%d_hP zf%UVq>-_$8^vG@|vx$~yqrhpVmuL`))f75hTXzEOL(eqJu6@AM<+Y_!HgA{bX$9zZ zAQ8O<)Ctj(CLTOT<}W7H3emS!WGr>Fazj*fFQ z^=Y?01!H5&;Weudx3nByz2-VBf5_ZM}8Uv&U-hIOCZA+bTzJ$fQ z4(7{cv;AG!sfkpz7xm{n23^x&Fg>2luHIBtc{N8GvnAA5IKylSTzIGHvUu8jDT086 z7E;^JJY9D5((~mxZ9Uai)ERWUi#?vTeVI9vdbYc;EVE+FRG%;V`Z~IK?2LK)8D>lk zXU5$0*;{V8WhJ`5wgX9c?3{Vye>-Q2m7;22XPY_5oim^8U6*F(%+apFVS!MOT8~^M z+1{8lYxrKE(#y=5bPakvJ7qF6CNp6oqbEA8kLdD9)wZK;-<8#U_pBGb>bCZTR;~^V zPTZ`~gFIio|KkH2GPhhYcJ=OVaklkGR?BX7mb`KCEa|V^M`lSZKQeOaQFfNR7iLM~ zZCyG`{%6xc4_-5Sj2gYcuu2Li=nAdn{~n9LV> zFGE>9aJE59h_hAY<+inHWwt}>b6K)MgI_BVHg)glQAMr2VXY=%3}oeMlW%^$UMKno z4xwiO?G#T){{=YUUkoQ17^FPa5A_CVI1j!>agtT?ES@3$-%;pG1-={FU|rk_su35f zQ~4<%I20}x!|}Y} z<`T2lL>ewiQpnICE8iS5tI<-j@O=%sYPol&3nVU#uI4?CpXI3={3hH;VxZ$dAS#tp z)}ob?OC$K%NYvDvQ*Pg`%r%>$5$HeqU343~8$`dSr3HTfj7M}Ix}Wz1cyhE0d6^55 z-k^C!x7M7|#!c#^%jlLHv8iLHBdAQdT$+I18`VeyG!8mq^B8`f;LtA_2#+y1j2Z^V zz9l$-KA;29UbP_l1EKE^%;^Y#8{G=HgXoV0{>KJ{4iu6hXhF%RKTh zT^HcN2+9Nz+1CNT>mxA)a3z7iMBp#caJrv(KS41RqjLpIpmD>9`pMiJ1Am*9x<=r=1)AakEFzjhKu($d3W}g_)3ad7%ke!4KjLro zj~0ug{?@N}D&b0hKm794eIOr&cmWS^Ku$vK=d>4Qeg>_^Pw`aDd>|rtN+unY%5TbZhLdtmg?20`%>2CW_!1UDztTm zI;tK=7;1My?U8!z$RKRg=%X7!C}Ah#0%=c{p~Q$HZBe^z>-gg8$G6(-QIw(U_f!|^ zZ?>lT)SBLut-Mfw#p?(YS?@z3%*R5I@(7XfK9ncVFTpeU9wYMna^rifB+q{%&tb$z zF|-DrU*YAL=hw;etBq&MMV?eU3c8O`e_b93juAz?X$*2Si@;}2_VzO~@j{LbN9l${Y@S3ZME(*}l+1chTP<>l#2(73 zwa)G?k1gf58(dzUTxJMbjkb8i>h9}sYYbVhU81+(=iDYWs9CMuXtBCY7#aLglg8Cr zbUG_}x7w0$8j!_fwb;yBSGU#V1{!_yx1m?@56PODOCw7gb7r}ZOghC9Ln=!m{Siss zVXe%PHYQC0_-9I((ngb5Zq$S|Cb`&XOg6rtKS*^E{6nA5oHL}&GHux9io&bOu9CyQ z_L^rUO%jPo zpMsA}TT(RrZdXJnHE~;5FZZr(Hit_QqcK{Hm}MHk64px1DPzv$_xb#$ydheK8a@~MTxaOZdCQgVM(9I}@+j#UT=WSrqY@w)T{udXvPA{EHP~{8n^hv zCYRMn@mGn(1~uko`a_}qOtvo=?8~;TOs7}2RcVgP^%yI49$OdI>+v1fU^6Kl0=`-A zytB)o@X%u{jJD%n(^5#Xe{-f1h#*6v$j6?&DJXdizEFd9p9rl!G|+yb(|NCZ(lLRe z2ji5d_C18GNnzOcac@|NZ~W*--PCU>x0|~E`%ivQ=ynT#Lp9CJG`&EBULZbWKUxcU zSa(9r9q&-Hh~~>XoZrf3aH8O${*L2>B>NoXZnIRR7X5_N27QSAi(o1B?PWOhoR%9G$O^Y=t);g@sk(*CUU%5UvblL3quqwWxwEO+bs^{OoQzLHP$6mSxHlH-4TpQ9(O$f!XV7LJ=;+XgR>t?cWai^b-8`&P#2d9?%G zjk=)@De*)ySG$M??w1VIPL1|b{E(>jaSbfpkXb_8%20Y3N;{x*;dH+*YurGaW6R?S zpOY`-i}?8*zsixG5f!;nWG|6=qzJL<(mya9qL0{PCLlLu1 z>yI1CQCC4G$wv#7ri@x{^u*9|l3{Fvmd;Q<+OtU7nlnI0!jKE)3bro~HaD-?y&JvR z^7S`Wk@2*(>FTlZt4r4O_z3Y4z`M`EyGvKdSHioFq4Dt{2YEL>4DXh%9v{29 zsqyYC>f*ghjgtP*z$^fxboTbXKGcO}ZdGkc<)-mNnXfZt3ONluLa`GOp9w2Ev=pX!Mi$%_jfqX+w?TVu*@T`fj13X7}0HkBS zfVv69$w0yY872@H4Iytu&;)_F8Hf$a%^Kvtp~2!9BKWb=%XGJXaUfimL+bAW+305VM=K?c$^ ze<%3FzDoGRPzaFc2qervX6HY~dlh|_@P{b_kgpR+l!27z|IT}ew}a*n1M$sY&OqXg zR`6azQ~1(4f9B^1f8Ijf1ma{MVSo%1h>L-Ed4EO|1mb2OHYhWLkJ0?$lv#$4(EMQ_ z9)PUGm(l!TAZd7OjFj;+kO-6+Czt~a!~u|L0tqsZCWvjmf8tqTgg;CffP9@mq70-Ad!!yh>uCNk5FhUt1Bo*bBf1G~!p~tLK33l=4bR)i^VRiJ zykUNMn5yzrM7uDTb^4ggIzzdTq1`r2}GZ}cH=oTwN&l?xyh*+9wJzd0TvTbN=}Z|Fh`@4 z<08pl)LRnNK9tFz2|-DIZl4&uPyNTRWH*gS;NR1KW9EwVy*vije!vCvAPxf3PXsNh z$PWyPgF(qa>#qUdasmD^ynS8qE}@S>#_;aTz&m$cYl{qAUkiK7Tm1x|SH9!xnBH>y z=w45koyzItW_f9Jq$E-Z@vz@7xH)iO$L0%E%FW9J{F$}u<`BA$q4Ez@mAw-|!z{p9 zI_Wxd1!VeBI{l;MRjD7R(?3pKMOgu1?I8gWde>coI=KM3{`xvb-pf>#%#jNiHP)vx znWwUx7tsV%IsZKr=lz|opDBIjODjY6U*=S5{ZQN%ks+r+V^_(gLW~Kvr@QCep#<1Y zcAZ|O%mh-OILWl@`;B(NB5zT9N}5(K z3qxmUDVnW*su4Y?uGkP3a zBBJMP9Yc3uL0`Hs>wO8bjr@hpoC(xk{l)0AY)2t1QshlmQ#2!#3+zrq?x_rAzCGm} z!v3a=t3@WtCp(2cA>{~nyWO|fMUTkZ^=LV?I0CgUzGdd@P734w{(#-#DOG0&2Xlf} z1q_R@%i(P;t)BFbIQSKX%7wn@F2j|elDI5phf3=z=kk4O?YeP+5bD-I z@7+OW7@n?vsUss;K9Pn(Cvj0eQ2uSxfE<78;K9k-r=YilXljy2>an-Z{5 zGz#`Im9JhK{&{I`E_Xxjawv0z@AryoHF&`bLVjiaO?(wqU2=!a0t!%tUwH4MMA${G+!eziM!FK04w(n86Wo!83wWb`pnur z@n@3*Bk^m}+qcG_iMMyrnEAJSmG0kT$N4@V|K88ijXh^CO)cR402$2;UdBP9v0$F8;0P*58)?lz5i^8}xS=`Z+!ce(18tn>LgX;7ZvH)&sE$Y6mD?J~I zPE8hv!fMUAB4|@>TI6W-XFs$Csq6KmXhO zLckGL8>9GZ$riod?Wz52b_AL+++tJ|^G1z!jOLXRBrQfABQ=1SF5OSHuoLOWUynp% zB8S0JvfJW9WHz|1LIHMD{e9?Rr&IjLpdj0QBARF#6{mu~U7SRXT6OcsmT^1+^-_P~g&L($XiwMmSY-r>rowUgB* zoi_AB37u?s$4A9pL9iRGLJg$vDIF2 znUqF}Os8;K8U1h_^f8l}%Zy^;V4^>>!dpb5L_YXnP;GMheGi6{m&vR-{9LK|K@l+J zKA+w5P5J}cL-*|09A@ZO71&kZppKFg`xf7gNU9)Gv&-o78OrUfb1!uH7cw@@&}&(0&kvoAHfw|jEkz{Sz?4i*X}a;d?u5})1SCRrnQ)x%)zjT zvg>qi1s`J>;#BsFCtky7x+|AV+3ib zS7*y}#l_A+?y~T3W5ozPY~hR^_SV&g!uhHP{<-1*)JSse(D0h%2>xnEcTanJPd7LX z2lFEI4x4;EP98)YEheIlwFPXbtv#iyt9h`2S#@7Psl8C zI3%BXh*y6PYv8>F>n$W=UuFKFTaHDxBqm1^JA4mCnyS$c23wjKR6qI=vI-my!2=J_ zzwiGzosR;2z8Nr*mFC$kx8EHIj;;)T$&)MjE=*0#20rV|xM{o=-Ut@q7Qj2Scs(l0bF(?g%)x0nsf(Mu1i!fnOu^tM zTf>p&=1918RIheBV^*!%uhyj6swu77Z_?UgPLD>X(|DXQo7UvhXfl;bMx*wdHSmpF ztw-JI=H_&&xjE%-GHM!c`2A4cs-w#ro80b_X~{Q!HGD(&T5kSY^e@n2DPEDzlQ0!H zXC2ViX^_wfG7V2`x=hHBt2fM00)=NF8*NOmHh6vICM0$193GKeW>Jb})@)f_9bPTq zd$pFNSS(hF(e~LLYx`XhZ}3S^&>h;hi5h9Q7@eVZjM3ASV?*D_Hp!}$f`L|>(Ur?! z^aJmf-r*gxt*3ku&BM|Ry2cw-e@+}FyP|%EDSR!@P3vEQuRs!BSVEcP2n`e3qsh|< zg=o48M^jYx3{?l$2;^~BP$E^Rqg@uCX+_Ijg>W>NSTE=}XK3J@PSMN?;do0XkSS2L zll*|)m8po4yl=GzovT{QL*xwQSMX)_idMUm%u#d_n!@^IQSyXRb75tSs6bho8n7`1xX?eK=#i_{QiW8o=RC34<8$=-N*ywQn>;dr%VZ*f z1WlFu<{VyY%xm)-oH2#bHrig^v*&owYl(X8J^(2Vrq;Rk<76-KwOCJ1p=jlGgZwht zpY&8%%+f@_hee`GWlJpeB9RZuhlqUWghCw@q?b@1RSnO!?dg>#Wdf-{q7loI@^TNN z+!{kbB%}nmTc?(YBcP=yymmy9lq+lsMYB;?OlBrzRzYA5=5(^?<;obN>KYf_~E2L*hNeC3%PV??;# zRm6-&x)+F)1+${rIZ7_-jtWFeB~8fx;wLCR`pARYCJ;7LhqtVAsmkhragnqcBl@!1 zttq#hA$v@i6(d%vbV{U3+d_$!W{Vl$paAMMy|^r?FKhNFNAy{_%XrH zwb<`l{o>>>{OkYYL_an0{M0D?yLDt4HTz+VoxknWrJsqQCiLc>JvCWg_K9+9`95Lc zH}}$_c@I4Ntd~U{LYq1$)KGlpw!tN{G;O?Q4B_Y6_wI6IuQakpQ6`{4DOuuN^3-#**O`Nl890 zf@@Ix+JLrfE7@wlYifg!N#wCNIodNkYW~gn8V&$OPVi#*fka{vz+4VL?9i3F#7wg}zQsJR^T>67gfBO5fcwF}Va_yU_ zul8kBDgW@)x^=5p0}tX5gZwwXn;sFo6s^ZS2Gp>n8Lz`4w}Wr-A?tDUWbFqLkJO;n z=*8~%Nui@;>s^_hOq!FHZ-2Y@n{r$%B_++x$XjX`$-XNUwER2iFl<^~olUFFePx#* zZV|69*X|alXv-4zWU4`WtK@toBDVQLo=9;OpDw#ZWc3EUo=7lI%o(3(+1Bd~ZA}QF za))~CoQ{#r6yK+{#wAjbQk)!AJ^o#UzWcapvM3PoC6a_y=jP)bs`Cz&C3>mMByAqu zoEfOtO|E7Jy2Plsu5Egq*0Ah~<-e-^ zNtX-iwNjDSuJs56>o#pV*E?{0`OlC>B~SWkW=Ue`M+Qr{>Ko{ACXMBxvM-a#Qq>?N zVYCnT_2l9JvZXA+1WsoiJj|;AxA^qFojSjW{yyEF0z)NRtW#^EIn^*%yjzdAZtJM_ z&0>L5V-8CsB86C@5=q2iV?=>h_T88agk$@*D(}5>^Od90HFMNp*=%-Z(lE#57X+ZO4w0n$ilqMwW;Y$Mk+Jvpq9ZugvL-G{5}Hzz?B>yb4n>e)L?Y* zdyc9kqVdUiXM8f&8LO@ei3y~WYq**@9U+4f{G7*ScIeuqibb6yt@Gb8^(SSPp^ z#=d^>S@2}M)AW%sKdzZT_2G`jH6v&q&BAC;u1RG;Lg{fHn~r5uYm!G_Dwi4jCTOvY zp2ZQZR+#X5fXy`~qt`(HZq&$*a=L1yS0N;;R@-Yop1=Hp+<9v>pZ&~i?JNCgdc}$r z74w%W zT*X8IVGLb}yAi0618A21!-m_)A6PvLy*?lOc^imRE6EQdjmR+VZ*5smF4XmO~YLuUjg-hhi7Zp%9Hzu8q=XCoft2W;f0pv%Yeakb6EG#-Wa)@8CH5|&BY=KMN~EDgg((4s9HB$Wlz54yqfz28 zDdFYG7nPWU5&@>fGE&0Ni!vpCUfV?P%i{H83YY0TfVw$YPXPVxFw5-s@c#B$TU;mYd8yQ(KwAG5TdslmP}+*;=>O-&_@1mf8c>x z`Zx0kk`48CLcQH2XU+!ialPA|&nBn~sa>&{%N>onnZG}y>+TFYoso#s8Akgf^-qy| zX6m~J{|p&YAE@sdo-f(tNjA^Q_UjY+p;YRt`7XF85O*z-CHjAz;}{7lbVwP#)S zeKUt=uCt#9zsau7f1rP&hiShgVjM*E`)9c)P@=HUsnXl|Bgo$xaJ2Zm^pjv14>dVk z(8YFbxFqfv^E&M0(}r;e$;~=|{)t2I-w#1M9ODV$FMR@lop%F9=r*2!quY8nS1nDm_E#21|=zNR(pYw?EqBY_lp$=m7; z4TOWK%HhORbMNMGXnD4CMPgaGZ&Nrpo#|SEn&KI|w^WJu)4!A9czR9Cno?J`TG}#0 zf5^3!$d0-Y%%*yL2~WX$8Pj%ZEmAXAq#hmhf1w7?6#Z0s`nUVeINa3 z@2blNJq}MmYw^3*q*KQ(JCYdKI~4L;0b~w1X$nA#z7G#lBAyr?>We6y4i7%F`jT_L zv+fp3^!9b=$vZwqzc@xb{Nr(Tm@t-*&;>d!iTPAJ89r zYmX1&NA4we3(}Vfw%yBIxL-ZmeoysywQ{_T{v#q^LLV21#q=E55s5|F;!3O|g2tXc z#Mr*8 zs@I(Z8Q|`#GI+c+S3ZxvB$P(?RNMDPDS4A&amrCm|9vHl6ed*LU z_yRO4{E}Q6&lVDVx$yJC-zJNdTx)-R)#2XW!>jW2UornnLJ3*5&HoNxj%Vqa0+~bs zP%QzI2o=zX|3$Rw!ym5Q_oBb{7@qb0+q}c_Z$Gkiz&lesGaknV@{U0uFo{C+3cQ44 zwFi)R-_X7n6gg`W{W~XrVc+mRBnIdw5P0`I>*|KOI_h-=d=v#;6`=Jv4&@XtKve|$1IY?3&;9|Gy&%t7 z6N_6V2$cjN*YF1!P#*_-yTku)%MSCueYHPy@JLM|sL5ZScLM>KGIg|K-cC?6jp~Fp z!ROjP(em1Ka#5Q|6qR;RP$d)cshB3!UT8;N-=FHN{FATtH6Gz#2#?omf*Rm8kw5@5 z+3tFiYX3mffE>-&K7mB=3~jO{;jI#=t2^)vJ>Tav9!&{vz%!>lULTp?#n0gD=x-zx zex~+;+6T}E6eqto0My3YgT9N+#FI~tKW;w!lHGiZefzJa+uPIWj<#%OIGz|zr-$S5 z;dFIxEWnEL#x=QPMvZE|F{~&cU{s+(^ z0qQ*(52Y!2G@{G#hEpF{_6hujgV2;|{F6hcR)36#fKDx*#tM2KDWMz^d1Oc%L^|E6 zUuMw%)%-5N$SEUkltR=(L8SXA8myN_`)j|Uxzs!VN8F8*WOhOZ6w+)(zpD8>I9Yo+ zPDRSgQsgR1#2(sh{Xq%qk9Rp^>RqZ zDO!8^zS-02Po)gZ^Ffp!x6O<$c0uhVA4QV`9L$y!W^Zt)e($n*)nEj&qf?otlF#YYJMB7;Zsl}l zc&yMP!`@_HAhIHtTp8BKBfgwTZBy5Nxc;03$;_O81oz^f)TIqkl#b>&%Auz}`mv88 zL+w7=k0@;U~kpn*q5DimilD+|r#|Ma= zxo2e*ARRmjxlQc{G!^r^ftS!el7|VR$vrNqBdANq9bTW_;?cXkxZkDndrTpt)#32u zOZ2-t@c;1UsJ&-;cg`Ld4f%~Ov&Lh#mhrDcFnTn8rQW46Sqk*K{{!`2Rj-!3iaMf>Rs~goW03r_Grv5qc1cX#J{!` zEhddiuk@+4UJd>3H1_Zwz^{_E6TRZgnc%EW|5fc*Vb9jBo`*R^`!|T+%31VT`C% zZoSbZ#Xs&G0IWuL1FPFcV_lDjc=yyLjRHx#hmkb+W-Z9e2dQl1n-8K+{A~T3HMq$8 z5PqKUxWru)1wWKg7h~~~GDCT~o69{O{8LpRm-nl@{n>0kytxv8llKv5!_qfDlGHTE z z`Bbuybec>KhsopwOgG{X@4J+acwcl2`yqoTo=4MSEv_A#lWoE||Um&u`o22A>R+S&qNX`y_RMQwAc< z-ixO%q7KZ>xo^3JF7px4^@H=@qfc}+F=t{eD6GMSYf3c^o%DFFUmucc6birD?iVW^ zMC;7Ect?1Ax-}v?#LH&IGb{3dGA}Hoy1LB)jZA4(*etWFOVWfhm=g(;e7->w0~{9v zj{Q6d?Wv%%IC7_5fqP+lG2*m_+!~8qW$FtSnlDOq8`W|44qL$R1hk?BW-N;4Y0lIl z+##&J{{8QRFLKSihWDZQM=?EX@ZSCe*YYrr2x3uASN@`H5mBLN(bK*tv#^dnDHA~-+cy<1y{42Sb*QGOsjZTVg zDcxeWY3mcAkkM=oHg&CIAn($$g*>B0eEe1e^G=uEZqzt6{SJQv#J21fwNs&UYxJ|B zN~2}8RN@%#3HtUWkjlUENN@7)1bCf_p8*`?1mH^e{Xw?;ex|&TvH}vOG#|62t?>I= z9)`KwiBwdaNA^Wi^!zRgak~d*@ot#R@A6qSL9NbXb6}_M_S=2S&3+hqHUO%51j|Fn zMSb+$u-xae>mzEt!{fmZ`ELW;Kpjj3Eq0SW0L0_k8`ueU1bCMT77iyxb&OBh?H-*b zq_O&N9UuO*I;gSQoROk`H=&Bg@@v`}A+%^%n~dRlgVz#BNQVa6$_!uHBry0@f=$APS7GgnEAW-s-u_0rfcU zI(t2z^dCFs?>$mzQPA}$i>(TgpkB{PoC3S&T(Em=WEKvF7OWqxe#rF%MZ^$lQ71*g z?oCcx)S~tJ^C_GPRQzC`1ZayWaAS8@)NVDVA`u>DY^qa$+j=J4XFN!8}ha9^o$SVE+@Z?^X7A&l|L;*-}`FYL(Y&#y{o z7xMYA+CEl+I{bid1-_~7ZOIkDcV`HADF4e_e_hj~;w@9S?bO$&cB5Mxv@{c1gpJ$1 zv5P$0SXzHYo}m>$uNThQx|_+iP0>+1pU6k2fYE0!y~~MP=uXi#Q8o*|a(kLOozBjt zQkT=&RjQsho6pakSE-&mm(S0h_hK~qWGwdNH-=A6O`RAXJ~1_Qa=1CR;>67Ki52nK z^vM+~;BTEWw2@FIWhwm}d6pBd3gG#A;DQn!ayr6FW;ZT!Z2d`d?JFy;x_0830esV` z2ZY6}4Bb~-tIQVV_50nNnjAi&O|tG6^YRS!zIIxb>@5)HmC zBdymo?qJ16pr#&0EHMEVlL%Uil{LjTzJ#6?kJnM3I=<{h1))%& z*E74xg?huAC_RE!AFf<|B^s&yco;ACbgZYjy$xwmb62$u;Vs3YL~fCzmi3j5 zuoAQ@A^jB=8%pZX#>)B@1Ygx&?V1tzy1aqlP>?^p-rMaJtmqn?<_Cs?K)(p+znsu- zp*aH(9#sL(v;pn3doWZWy4#6O1x~j)Fr6aXII2%XUx3Bw$0QyV^9@#g)A)b{8l8yZ zW~6OKD4H+`g_42sCcVYT7t1qS*CI4j`~DDKvn`EYDx0kc7h4DO`GJ^34V_E(pQv)I z&99Nf2J-pA)*?n$b9roMt2jOzr+Yp=lMuJ=Zb9v7ciJj* z+zr0{-9F(-bmy-;o)ClAtlm5(tJQEv^!)kPTg0O@V+c8GU-R=V)dBC+p*o z49QQ{X`;3hn%bArWa4Uo+*!1NZ{hP|3crB|P)jd@l(1gZI*8!kVD0f<{BuSzoKEGA zKs|UVsvJz0_mxGbX^f+lu0t)1rl`}6{zm8yzYE=lv(fiBFspM2AzHY-Uo7KF8Th9;+ZJtncUtQv;(<%B- zv;r3J36%i_O(lBYdr}golm6ZJsxvTsgE;O(uk#el32V$jic7BcESYGdWWnYW3O{d4 z(AKk1m9hn49Ia|@+fazKss-0+l=`SarBt*8y-hMxAF@rZix!)|>ah3JZfH7p#l*g9 zG?+KZH+-VIL+G=GLjGWYM^41A;ym2zswML@#iWS@MIk1NPn9%{1w8j65R>RxezKBn zvQ`R;md;#s`h(J|_ioth8EDE^j?BJ-Myhd}PD=q=z!xV|%j*tW#iR;0sMrbSM-Iw>a6BMxiPptsso z3Z}bxcfj^7odUJSi$iJ2EE;r9qrq9bj~S!cB9)=(c7|R zg;pfhNh+C4GSV6F1-6ctRyUm=Z<8zfW95;M&*oCWGRkdrClK0zJr1kiW{6ed)dxl-E_~5|6WmnW{XpgjaZ$~_rZY#DP z`q8LBZ&&FpQjKP^b?T`bRF_JIm)&(qCX!Of)xD|2vI1R~6y#A2?e;>%73>XK4s@ar zv-jB-;v_5?O*#?UW)$F%Jrx(+s?n=W0<}P?D+W>}k!3RFtwxaOw$J?b&1$GvdqAQ2 z%`Tr4d7bWbp_Fru_SYOvP#T2Ke};Zn@Qge+)am75G0VAcG&fO_J0M}2kE|xGN*Ppj51?fZ*|v*E9U+U**U9Wv z@Srz%MINsW*YmY=Al*`u3Lqu=&gPep& zpONi~;GxkGzA`MR^SE(oE_x=El?3|}4(l~qhxvLnU%*GopwXPr$gWod>vcxpyrxN& ziLcH*>Cz%6+UAh0IJPQmHRx@q7kcC5xFc*9`dmI9(O7>+e`hpSaB0?CZFxG z#?vx|%BqiT*|RGPwfkX2eh*?(d8i#K<&4PsMh8(rP`|jZl+7-v2os~ezATwo=ZdfB z9U5PeDO-lxzl?4d>^iT#Pi~bfUCQO7zVK`^qwhQdBi85C*u`4qL`!u}D~S|rg+8O~ zpkO_}Deo>Kv>%n?-jG-?jpl8+sZ3*L69Qk9JRA4ca?Tayz$toOM)Iy*Z5`+K@3^G% z++sB1%Gf5H8CCPXsmXnn3y(})P;D6cF6??&N~{c4EQ3gCi{m_{D(^8^+P+$)ld4k%vL}jJMe*O14DGauy{leRWPL18{|r*x;2=uYMN8I z_CPM?)LUg5g|BTg4d;1%G(8*(II!35Ywn4xi*>dQO-MAN?4&;$l}Ynk+a`ClTKwbW z9QZu`89vMtf-ZLh9reAE0(v7|v4~1R?qx=_{qWi9psargUDMws>FB7vB)jUm8*k%p zrtY}n(i_BAy*9a1iEfc@+`4*~thPh8ruKygBuCFb|61|omy0ghzvp_{2dudg@!UvC;Nb_C(5{aO6z)e?fnrlZS}xK8IeTDPl6+>h>#ZDAga?rv-CT zDEw1#Rnzr{#l5YLxY6d4phIfD%;iXC+6RRf-&9=F+B~3A4XeuAd#|`c5;gCbY#;Wd zv+)g0I%)InXgt4qbbPlZD!lBPuI-i9-ku7{iOrzT(;Av%wGi#N#ExnhFZa;Kizik| z_D3q`FVFVr0}hK{6OE;s^Xc|n>tWi0u_?6l?kG%kK(!47!whb$53+OddT6 zFk()J`z(Hy)i85V}hKT2g*mMNGk%3zYoY*`BzL|lS37psr1irNn=RH8f=l>Vr zoA6IqxQ=%Z4X^87Qhqms$4%g5bQ1V^4BWW@r|~dw9n!FPo+IVYXUg9~>U|UHy^ON5 z_1?hy90$LZ#d8Dl5}%uF-j1&Uo28xZfl`TUwdnPtC3Xw^ryjB5Qdk@KEA zyAKRXrn=H8oZh=$>(_-hdWa^jl9^0SYvKTR>N1_4(u^F932f(;TE+6+WLjG{5@%-UhEXb+ock$8TP7EgDqDLoi1uWMQsu}hQ{ zr6yd>ReOu^>W*rz^$;VWc9}|^o#~m`mJ>?&K5InMJUDEp_=0RK6xDlmor&aBv2H`5 zN70{Xf2~PJ1q?K=ONNkMZ_tUF9VT@2HxwUz|A+FMKaIj@t!7-=yCp)6t7Jx5?JauM z=7G#38~z2E>FY*_AQY(og3;}y$U+V6Qdlvr%?FW98*cAdAYw|`$CCmg@(tNUhd-0kO)lbDOVf1-czgy{by^m8j};hM~BBZBd^_@7(`x#{=F|-hwKNcmWmCllJ#4ieEpc*ZDyTKyVU1baej3%G2 z_5+jOZ-O5jR=Qd(-EosipDV&j!fCa+TsEt-@t1dcWQT`|FLf1ofStTJHEj56B6E9kmX3XMwLcGG4BkXXTYp=>SS5yV&%-B5JJVEgMb_Wn z;xCHfk}d~a(pCFo`$g@&ece51No9L2!-a_FRXmE_R2`x@#??(k?09I z?UOrJ4YVJtzV*l>Z=D`v;vt~nHR}7|Z35jLARA7(o=dN=aYt)`j9;=O2sNxxBkefI z<+v`;ETjIIbRZC!MSEKDPrZ_Cz(zYde>jM3fvm)<=&P6tjuD%B!6B}&xz$o1@sbS3oAf@^sYQ?H{*+Obp~FePT73)^L`Ldy~j8U71(5N5?Y=vk2;MVIjig|H|53&5?GGsscltRfORO+e72 zK5;haqdnl?B+mLuFG4nF%&&EKMrP7^i&3T2M%{C()mFOeTl?x=-y&K>uc&gQpe>fx zt`OrPS3+P9L)S`2MwqUp?b}!IhwI#AHmTQXdWTqEeHaL&QLo;umgz)Rt8fm@GXcHF zfYkjWquD;v6w6PUTymK{Xl<~koO9j#n;y#i4JK^nI9H~m1EDVfcsjF1jiios)abVKLX7Kltr z>aok_t(_Z>Ds9SIYhWOd_YVZpW69W9_Ljh4AU76Gj%ES_{-u#h7&$%og{5Pg==?MG za*lza_n{^tf$OCs##8r`VO{E^0pB1Q2^`f=3tu(RcC;)G|!hI9&VUBzAO#`Znh~P;nILvvEUEPpII=hYH&>LXmId zx;-Lz@N`((I!qKcz?VEkuWtE560u!M#o4)VMi~AHD%8dOZR;S$gQ(a}Ki!XUI|{ea zA3u(ls6H47r*WuyoF1?h623iN4FJQc$6#pGsh#iPJAvAcGxyqmN$&>fsPXN+?@TiE zB-^R)PBPog%>Cof1I;e7r?FJ0qj)BR$R`qTO(LJ3LO&ZpNE^`2o|CtBo;O>235YzX zMR|nGmBFq)p-hOLez+*kZHgmQn#~6XT77lywq4kM;@{TJ*a0KA$`O!2PAeJSXuiE zkoW*XwvNH}KCwnjXv%LSoXZ6US_3Rir1rtyzCKjn-SrY~g*i4v@9m~tK4daw5?+#+ z*de7wch!0MgARSv+&mt~_t25>4^Z*ZQaWTG;YT)BHr_rxcgNbwTGw4Cq~hd(Z4T%U=)QyEWhaKlub7;?JhUj)sQ;$jT?boEw?-~VZ@aR4@Q#BA?;Ipq zTyNp4pjV=_-#EhECRW1`)U_v4V$rBftj zmT1tIMUxSnsJ0ZvM+#MyZl-Bs15vHa&=Xe=X7q9YAxA(hKpT1vw{#Xxve{hJUeNQ? zJocHydFOcb9hhIm->Pd}U1`bcgbh`CMT@Tq_KEa-+)Yhsjv^Ea(F>H;ZKLu+rM*w2 z5+Mxf|9F)S#^NXT6?SH+wk@r}v7Q7!tyt4LJA=${!z8(Ck_=0BO#)N~sauGbLyVU5 z8nV_7{T?L#+9lVAh?qnSC(bc9PoncS-nnAcU8|edCitUvf1)sv;@?cm+$~gcsvJ$& z2KnLjx{*5%oPXz##d6mr>gb-WW51l(wJ)YQai`JIuqt@OssK&3G^=cJUIEGApF(@d z_cF4c0=tg788|AZeKU0>!RRlv#LPR}$YpIkJcE$tWP2Z9#6R_^rFNgnrI|Y?XRe;N zvi8Pc!~849v#10k_J+Q`+P}GW;2DSa@it-#ChMAodK4&E@Ol`^S=CFOm0I7~rbk+` z@d<$x7xvW+iigvBwhl2hf((5S#dwdc=blM%)7v!A_#RmRNL zPvh^yTvO)Qxxic6T3t}`ob&ZS`{$NSK6lXbb@I|HuDFz}BWn1YP>Tt)5Jfo7Y_V-zn;@c)<>_YBx%`Sbdsi`- z!h%HH;Z<0b7ht?XSj@>_>Th2=5R15iO8Y>%c9_lar7S$lY3nFDcV?lt$@=sCrb$ul zA0*M2vs}93G064xKyOKk+?-(-*UywQEFPaQNpmxYj~!!jhet-3?BT=N7R5sPu(G9m zUYYo3dZ^z42R8rz>z@J97JC1G@X%N{Q=%7e&Hd^9fNqv@eDY}kN| z*ZUtiYq%G6epxCvD=a>>9t-e$^55*=;Z3%;+9N-UQ+%t-8n?f*GpBoKr`*!%3S>ph z%I}9jedWLOnUGHVkGv+9t#o%NMgN)Ogkd+aSze<$f#SBaP)w_!r8I}m~e=tAr{hdMBF{2tf#O2AWJo^`5)#`jfP!W0YVD5zE1ca5$*9| zIQO!OOfPdXHH&9W&6K?I$Z5HmBue6!~F2}4xwD&PIR=`qZ+9KB-g7oj2`YSZ@j3tye7dP zc7P&S*;JejNhKG7k%cTBP7pm2kyTsDrCfI1=Gha|QLx8OYFaPevgN|orMcj!@yv4q zy^9p_`Plj&%;yP;7^sj+)jKh!3 zkbeI@=KXUx@QYcv866{V*Ziw=<_s1>D;wv6xhZhOCNq((1I{j&Hcsi(x~^Q$a-TgQcJ1ys=jhx1j4@;l#*(kBIJeYx)6tzD zkNBKYzKkE06-M+%g-E1_`DvuD<3PvQ#-ZuJ?5@qD&|&o0!V2^|o&{)264_gH|Kx(4 zne=+bwc;zWXHz;*Z0%^OYp^}EVYc>K0iiolIGI@&j)oEPMG zclYp%nL!28cxD3ozA_kC;rU%MsrHY%+kpI^zW@C{?fl$99=XHyRrC_+Yw%MNt@Q>~ zLa)*6rBW({f8$p!NTw{ARQ~hV^v3LZo%l`A8^0&IF@i>T zgcdl@tsTA2wfmM5py$|7Tzj1xEjyQ%2P-Nxh$|pB-PNY1wAYiOJDL(=OK50N0V0yL zrds<~JFMYpzibh;GT)R>?)Ue#%IaOohc2%grLEAFNe~a9R|5350Po^pWwW=f5X!hi zZE3`8Whf>M*)>*~N~+TE`_PvQh@o{O1&h>nc|2{h$)rYK_Qa5y!&HVm7?BgVb&s_( zz4s(g0Anv#ztmEv%Pp=Mf}lRi1blQ<%D+E%*9%32inTW?lH1!qC@ZDpXtyF+`y0}5 zYf;?xliEe-qMzI@Pce0DgE~@6C4|oYJ8LK9g9Wq-$s29EhtnPKaGJEp{Bz0V-03~w z9dWxyymc*uEkw&ic@3#u12ip-_??OAEX+aIk2~rtfX_F>Rq(b`A%Jiyh`$rCRiiF{@xC$gDJ{Fdt9|&vvgg^Y=55Ffw*I|m}iUCKQ zg!&va!Z+fBz@fxqSy~z$V!vTvXbee;2u;g+tTh#pB1smZYY{6)^=WBIX96^^0(x+{ zpNEL;7Gr8(D#;vsw?2gQI2(qi!$rnXt`_fW? zE4`*t9+}kB@m{Ms7*j+2TLW}NB=FI)ADZHDgQf>N_y`b?oDf79C9d^bX~W~4z#pNXa75VeCLnUp)bofyZv{n6gY!k}E` zoegG+g(PD?QndYOg3;NzM5;IeyCt;wIHo0+GK>~fCOY*;`a$DW0h!TFGk*op2N6=m z6Y)4-B3PnAm$9Pn>;b}KU4di|$L<8Wv*j!~)eq=KZv)+Sl41YesdLcu=tJt>sX%DU z>No537?YV~mS))(*qXZoG|RX(r;AO{Nr+w>pr`6PIZ6dn5}&s2S(HwcB@_Ln4^r-8 z5JHs3Nnv;@IdpE@r6)#L@r53p#RowM2|rZ!;Ag5-Z@(3x4g2(l=5r^HUp@fVfisdu z&hY^rrsogJ3bo3J<+b=6tyg0fbM~%Y zb?)9(`AhenaUR>WzjEIA1=j#ALa-WK#6B+oEjikoQKv<)C`Pw*qV=*Ny0RG|OCq0{ z=XL6pt@+X6jRz5*NX_4ykuR|7wKRP1oXeK#cP-T;qatPs zE}=@L`a?DUw%f`h`O(;PU|FQtBBc`ctV^TdizNbW$Zd6@C>d}Ft`L((6Vl6?FKTVM z{M;8-2JJzM+f%SXS?de(UTYJ4ZG*~eX~>>f27Z0 zbyrLE>}m86u>q2ej2{%j{|C>05{m;`(00PZ0C~P@UdMZrd=JlLwe|+Z2We0c-{GRc zhL+frXC0=DVTlC@Y2%4lLLd{=rk7fo8jlJ_Zg9iO*H~Ngr(|rF619JFjm{+lnPYY` z`hyA)syk1onk5scDm29( z1rlMZrKYN}-Y_B1ZeKFr$y@_2_@C|<9m&-C1r{>d@MNt)q~#Bcv`q8ZwF!a$p1=jD z1aQU970BVDt2<(aHwALB=RSDU8%qOM2x=QG+g?kQM)e(YoKWYu8OvaN7_ zk&l;Qtzi=KVk|-u8skb$NU!I_!A`WHSyLPT6V;!nh2N&C#tZaeEj=r4SnEcHTr`;y z$OSMKr|o~e=nE@|?dSX8uDdW5?FxpwBhPx*1yi{~lEl6kE1jGmWvj=&azW1JigfkF ztz|SKTP(@{GCvtTcv;83!NGkUmmN%`&?7jBzB;jD#Y8Q4&B2LtTU*YZJbYDtZsW!| z9-9B>d<|CsJNRBrOw6mqSqCyoTK(i!vlkNpDFTn+Ufx{TYIRlAynpc%2i)wZFi10XCdmPXQE#E z#Zj+dq2be6xw7unDHiK~9q)vvpkHw8=nJq4BEFT4)C%ChR-p2~cb#y9B=78>5&hQ= z6wM63#|b9N*<3UKwHu{Z_Pv|X8C^5PyW%3=mENUMum8Z$!U=m_Uypie4OoERyX$4c zv_I3{T3{kyN$0!zVQj6VQcI6JkY!d#>!1y7|FsWn{Tq@WzW*H^95f~N zc^BqqPDwvHll)Y8d*_BcS`|6UqQpc>TF;I4aq?a z!;_2q;CV+I*e^YJl8gW9LUuGjR}dV_70|(j8hBFZ+bY!HU}_MVP79nhE+$2*A1d#^ zbWYIY`gwA2H1n07gD0AhB|b1n*C2cUQ&Q+Y(ZTa2&~+dFsW=`N?cWP1iJ!fH>C8_m zd2jxNDSnUpv3K?;fasjnr2y87p<&hVe8hSo-gjc9{Fbp&?g2O{hvKAMXdyyF%KaZx zPQ$|gNvzqoIV%9V-1AI1GYfx(E{E<~u$u6FtktAIgN<_7LablTGyNW4!Lh37_x{Gb zmt25TIu>rC;XF*}vrw29E1KfwY%-r{z>o5nsQ%UW1r#i_#kzEpnijI=Ou`LZh+jW&#E|s#)s(Xg>yMK z$hsy(`)%t@px5G*x3Oz>@jdzY0(VLj@F}f&k$8FSlul!Bab(3ouhOCwOB{XA{$8t5 zMq5$m2ix87uRS%ATr)hhHaUuK4@J#hvBEM~sO?7&e`@_Xu3|W;cZ(F(fdVpS1jX9k zYu23Sve{2K?{u#`NjR_lMk* zf6h*3>``4@$(IRzO~rspqKvE4?(}#DZGZBELbqG^8_NCBkGiSfQf@bO|Mzbx^?2m6 z-gbnl-CgbcwqB{y-2AcrHiB8BB zzG&?8_YSRCHF~@E%(Ni!pIXYz&2G5ya@@^-j@~Z{`ohlp2ro!(OB11IQM`V~0l?wH z2!Q{Zz<-UJ2)qycL>hb_z@I1Z=h0OSIQ|3+r^|nU#q${g|20!ST3^+}ua(#VpS1M- zJUPK>$HXD!;0?7e3_rZ~ONH8tz1}bRy3uV<{x~N=&(|!%bXu}*wIoNcsDN5L04=bB zw;;{t=rBQQZq{qb$1dtf)S>?IT-1$1=dEv>*)(mb?g5?AjlSqa_O{-Rb~iFN7h!%k zXSd{pxq(uwQzh*yS&9jJPMF=8EpE)@GR5>C;&X{)DnV-iUIN-0$1$FJQFcx+SRWjV z^KgzDqI%t+Ah5n=#dXVabNkvhP6&te9)EH&mmUjBC998WO>Gyh?cdew3m;pnNpG2& z*plX9(%!w$UOmspX)V{=QCe8M((R;Ms9JaR;KWTEz=wM$a*fQ)47(BHIWrqG!d%C} zWz&b-a>C5Ue13Cw@3tL#GMlqJMCvg?Js$Q3Ehb!Zri1k8I({Twrnnugmo+s>Hz0Js zVwt4o>_+p>EM3cWv%sd-&s2&V(lgi4l`%EQpa$33YG7Af1pm(g{|C?}S-C9Vh$d=3 zIt};3z4^5%QI5e)_rzxCi3nqDFU><|G#K}GFq}_qsIIzpZ0N>qvDIPWu)*U?O=i=R zS&a%!B0~zHPOr(_bJ6Vdg?$?R@%4(#mhp+L8OrYK_DZu^p}(JL)yJS!DW+BIGV?6q zH%=?}qAuiWM~|U)X6_k(#@Og>Hfm#w@CJ5OGvvma; zef6d*{?v|8ckS1m2;VjGF@9f8itZEVYImY7^)3L^q_S1v`)a$<`)>M{GzT?Bz`Jt= zJ@OfAUE@RbgK&v;gmmcUH%CTl-@)5nAC`Cg08xbX(wYlhT6;v61I>AdN|38PhA18; z<6{qu4;9fOr=6l$I_(t2A6rU^WXWPFB@-pfv8Jt)>Gb5*Cit65Pi#X#)=b;2iRUd!=_6eaU-!>`R~^s&g|c4sgLwe8<4%Fxt;0a zxq;MJ$~zFMk9K6qY|c5lAc{}gwVY{J@@(x|I1#Ka#b;|{WpjnfM-@S}$bP#L|?Ypp>r~Q1+ZR#-cZPeoPB%>l}Q3Gm!~~gJW|?wr1zN z;?)v0eeGs69GxCLv_HQqBv>moCc-h7+oMu@CVK~`jr#Lugrbn!6;NxvV{HSg^~S@i zMUuw(!$oYT|CU(C$I^s=U!o1tDGD2?Dd|RpMr+?0p$Gbw?8e(~-?q zIhY8UcPU!endx^aANx8N3vRve*vfm$$l5WxqYY_Bw{ELG*8c&F_S9~oQRalTCr~pq zSX}!$s!GW4<{@$`{V3rjyN(C$EnUU${c7il4|Ud_YTvLs|9JoVZfk?FvtlK!Ciq`` zix!Ue-A=*hCw~t$2rjvd+&9O=1wu1}`3xtTqC<~%UJ70F?NM}d5d}NfZzhW8@8t@@C2l)kNFHU6srZd3B$h82+Z?kYIYURLRX5sQh@E2IP9_2ak$62@%HJuTU z8WlP8T+hNw4fwo^DZiY+JqT=*Gn6kc!gDnXZ&?JtkcC$k!9^_Gipm^#6AMoPoTZ2G zXM&*ztmiY7&!A=wo_#Dl$K@M!fQ1)O3kSc0g?o^PgWt)*eW;y-$H2mksENgMBL|NI zJK!&-C6ls&98t852ay~ff(67o8mR?(S@GIQS?z;Oe^`N&;;GZkRd*-4x4--C=WD*4 z2z^X^y3y+E^<4oIF}dB_Mces6Q;E=IM;l1ni2YAt7A{8T(QRPhA{K5%I~U;iZ5A#? zD>(4CShyA~BXDB-6Ff}}o+N=s>uUlmF&9qgE;Do&Ipswx+={B4@-MJ(Jt}kHkF#*)qVjLCa4iF;+tq>XEZl*9us}b4 znT4xSj>WT#YGUCjRABMc=|7j@PZzHd0X1>TXHbE~(?acI;W?D!wD$lDF94jy&(g`_ zXUaQSxQ~=yO23?elT{3Xw=nHm#(}@Z!nJ5k9bS7K;4v0%L)%%o+)RmBxD{>X;CY*c zOKCW5BLn;{unt<-SYN|M!Wad#;ldgPIj#XwV%$RpquvznM#ZB$QtN|V7M*c6GTj*( zb?}!P1u~(-YqpyM{+_ZSW^JjO5Qdf8_H57i#*|L)wO74C&)7Va?yl0V+|f23OaJ36{Ytd;jC_-$ZO|@Ee6SB-JG85ZSRG^^N-$sGge;iP zdJ*kxKkG`ZWPqd;0@*b-MlVR((4(jwxx3NmC>Zw7wZmgu?Ri*kKlEm8b6UF4gMIBq*l@r7uwN~B!Iuo!lh^jD|y`V z9;SSlUJ;U!Tp@5F@2d^TL(4dDF#{I@{CpZe1DDp}^Zx+&CHMsvu4l?S0KOJK&cc-( z{1f;s7Oo|5LMOoOEZo8Sc4Gvh9h8WLThCJ7!}}V;2fAHO7VhJHvoV{X{rF`TE@$Yc z*R#7wyQ)mPK3~TVBj*^w-^Prb6)c}sgg@;Je||?x5`ky&Ua;-`P!qA_iN_P2bxDb_ zL#I(X(tKy_%F|Ytc(2W1D7&iP)zm(9=5;1Rp^8x0&QKU)DGV&Y(VL*N{?14Ox4Z`x zNO?OACq4Ckrl-EbaJX$z`2by>vtD*BUN4snqQ&hK6-vyi`M?3TWgQ*t$~iC`Y#J`B znMS$W-L4Umbwbw9gu@-o9PG1p<$Mp^A1}==9R?6bF=B zYR`~1`)^V}d*Cw%0nwa_=6TYO5Q@V8_ZZnH!xg)OjAmokvir*HA) z_I9AWf!UbGriO5t$wzAqVgwa>%?`jQ@~{6l#}@q1gy4HY+F7e^<_?VZ&_H!r%F^R* zioqUhQ(kjMyFGm7LEqWk9nJN7+^Ll98vqvBQG{8@?84|Qalr(WJtA}~5i+pbTrLKh z?a5bBZ0YkmQ5)bt8xl2l1a1HM+wFx>?Egbe z;O_O|o9#(DhX?Kaj^vy7$+00>bInaQFt@z>Mul;9`rcB7!!I*POzNjP`woWV$+IVY zN6IuDuy~#G)GC;jJ<{7IY36@)xG>0+y_%b$2_K2BLNYgu6yBRjx$+`09wBR)%0;8L z6jNA)4yb;{T5e5J4W9~A!+%FV+`~S(x?2R!@qnFy0c4Pw`TGQs+bL@9kpUg%QuQ|Q z>XXN&q>ztUiOfcjZ+c;zg{UsKwFSBk)U)letX7^gCCVJqc3sLsxZJUNGDUF~u;vj` zl!?cC+zOBFGh5!!fv||luYiPhsWmjf5bDh!efSg1acB$Np@CmFn{y@!$PygYi*&N52A-bi3>pb4iF0<0Z7j(BGe(XT) zZbNY0il-(qL#8`kDLq}aGBkvWM*D2WKJ(v(}RBz4edtY;b@y+ z*Y?61IDSsOwhYUOiIa$FC@)yF*S1iLJZIoDnpB@UluV6I8664*GgxlD?UMf(*#4L; z^p4HXum9i;csupauchNSb_R80lgq=w;ANzDsta5^GyQ}%Sh;}(TzYS&^&&vJ;AL&R zE{r|Tg>JdBe+%nW_akuCC(Nso!@Bc!r){`^2W;tmn7(0uuQ!(Tp(2_iD&*j6KraMt z@6!&oHS{#02ah>1$joDpz%AV>&+s+k zym~dFG;X#E;@75x`)>KeDbH4UyUMMEK#AZ_g-#qV)p^3=x7>VCkA@YRn}kAR@yiA8 z&PUGlOHm5GrA4{UbHTEzYco>Ndx!d28~BC<&czm6n{;_Q(5l${~a0gTu|@zz!_9R6qFgL(P}vrxz#zn-)LT^6e*aO6#naQ_JI>qOWcbaLgQ<|y3P`A{=@BYA2d?PS1 zO@Yf3>uKqC#pBx5d2IOUc7Jp8`vgwcRV)f zj@7R=gXa0xQaE*H?jWC2v|O081N|~8e+$u+M2=G6lYR@*|3KB3G`{b}Eb!j$MTm=W zs_Pv`T6&Y%CO4^u4YSrSThEU}S+L&=RYn1k#|7@_8I+1Nkyx1~9T+O8#^DMkf)%n)Ef}_wlnJZ-H0gdYAy_D|q#&hLu^x|A$1kMw@ zu&^cS`@u6&ZB)7cEZIMC;Jz08dBLG5z}LI14lF+dR1z&Sb0hR)8|`Gt)&ks>(MNTg z5%6GyX1q?+@vwoV-@2sIM!A|M}*wn#A|?ss)yoa>_Pc97{TAJRT>DK$qW3tFS56WSrd9l{#nhaW%T7%AX#!zg}Y zau&jiC}>>4?^=u9#iS^RV}URVt8jB!S523J>xyi%T-3l|OJTE#kyA@BltUQX(y`|D zdXJs3X`)@2XJ!C$Z;rL{ajFZCsko0Zo8FPGRpN$Hq>{%Im(xqV_ZZ zW_s@499?}9S&7jgAilI%574-UW3D#fm*e?y7@nmgq3B zjYmy45-}CWF!BH}$krPK*@efD{2D#r8I?Af5h*uHSqeA(`` zj+&;c(-Ap*glq1?7G>^<)Hkj5XDa6KIJer4CL3<|(=ODN>f~Y?Ez+lV4Rh4)yZx70 zO2kRae?li*A8>>QS6rvprM0Q~;4N;8K=htk{<&rj>Dh)!ME8?$dX#e9Vp5z9#b&kU zD7)Z8y8}CoxO!ScpxT?tS#T-}mL)A6P#m{H`O)dmU z=a4Zd+BB@A>P|1perEacP8|!bPKn2I`rj&y9m&jo&cdK|MN$ATL@#Rd%JjiLgt+&b z2=kuO)9g^S@2?*7G@ZW!Jp6(fr`a*F-zS&5=aYK!L#w=MfT6V*fKhMUgK1w&j6 zAwAQ7!%43blRSsgWBCCj_$t2#oWy4 z9DeYz^oX@4-sl}}$y@+!fBhT$Fyjg0F(dza`@VC)1NQ3xe8G@B)qRHs8ui=lyAyJG z9eI10^W+{=0?gL79opP18RBzoIbqCdvD--=Yw7gW+o~_YIrnmZ$qn-glF@RTRo(pr z{TEdFFY8VJK#&fx>}tko$GgDB>uYKY{snYG>y)iFoi9{%&mcGUFK8$kThOc;wQkI< z(gmXC4~i&R?rB>w5Al@s7!RO@e4_Qo*!x-JsJmZ9Z|wozyYwV=!EH#$i^2}_RhqML z@!AwMP$s&(AINsx{1duH8ng^pzL83Jz~3+kI0_|8D2>U=51r$RKUi>LG%Agie$8u0 z@4l+X%xg}dZWL(+!Js$(RI`POtl&Cd+lBFgDStcT8?&@YO7AclmM&m1{;iiK?83c5 zZa@-(vYN#w3$!#Uds{jT_xP&Sy}_W;X}B?3ed1_1k+o6DOs|b?BICDh1Qnf{eKI`d zh~qEE)yQFFx>EBk1DE5Ah6Kas z{N9n~fi^n>G`acO2#Y`PTw<0A84lX=xXI`Yxn6-W-4$t>S1C&sI;*4uQ9V@jzTV`J zEEs$FchY7?wE=rUuIcmjOL1L%JNem|)x_8NN{K{gSDi&; z&Wu)QVUB*|5+$M;5FW7L{lB!5n_QWZ6HJvz&K&5a@!0>ykJMeM;+@6nhsA_N7m}C=gB;;?t!)36p(%=?1+#io)%hWPAt~l#spML zlEqd-xiLCf@apSYs<1ory$!uuwRa>)5Gk69A@k#kXtjLBi_t1H8Fkuoqg6qCaaU3^ zR~}(nzK@5gc`t-&K7^Yww~glc&)i?Z+J}(c?(c?eO)byxdEo)HRW+=H326x#GfIj$ zD9#LIoVkOCNnHVQftO9W06z z#X(Rdg4@XlhXfw2hYm31d89`b>B{)#*2vAJ&HlVEF7K3pc4JBBnb|FGc%Isl%w; z-qy{l2NVZ*{O8b~5&HOU@U!n)h!}iMyn?qcHTZOd7|31Kc6LS1RCW5XlzKx(Cxa%f`sfGpo*S05gqz=JWWo2fk~|$bvS{b`aXHkG^yEd%3Ox*|#()`vKk9ld!)sRW=uHH; zGJUs3{y2wM41XTVRvbOGQTh$*e4R{$%82GgiCecWmIlC4kN_Y!)?e1ma$;E)wK*cy zw`gr?OG(f5T$Zvbdwq9CMErQk3^F}`7ex_8EQUS*)?AmeBEQagM@Im|v$nbo(rdLs z=+siZNf{3b@e)Yf#K4N+pp3-~M3+X%nOWTnJRl`Q1B&3+ZI?NzgUwbRk#1D!Hyfp+Pg*wg6g^<8FE z>(TgUyfWSo&ujF&A!KOTvIDS8IbGqe$9PY)nX$URP zxS2BakW8qb636&rF zTS-w6QdQFDpUbeOrHM0RnP~Sjd&Xo7+Z#Sz?~tuK!z+j%flgqiciq}MMn!drnTgp! zkAz#R@4-EFuHp%nU>u4Nh~Enkf=Y@QL29(nav}(nvVU-KX$&YS@aUXh2uwagu8i$) z)_4YM=>4bj^T&l{8izEY1FJF$b_S(xZZsSN;2XzKr>1n7SY4(XKBa}(3s=BoB6`Sw zNOH9NC{WL4_`MZY=wK$x^o1_o4^+CpS3T?hvG8cT34TO!w5m6tJ$E#;(+oNKXLw2A zSVib{)pH@{RvO2UR3)0;48K?rE-xIx}1YL{5xWm zP!WvLoz4@Mb0ccj0zS~t+U(h9(S&7u)*%US@7q3BRJt4W%*r%62@(A&g>{f$c2S~} zk9$@8fH>kQRhm}J;>r0hmPW`iYKA#6nM>-*oA3wo5L+0l*3(&MQ+~VtQx5e}V{siL zsQOl(tYbCVFEck$Oo)9BzXmyTJ3CEctq+~*mfj|8ba0Zk1|Mi^Or)Xf@fj~wv4)!K zF4-8p;rQ}mr6jkHTw9(a`FDgDLO6tNBG7B*W=89GH+GF9K);Y`X(Aw=G%MT;#9;E! zC5u3Lp;z=K%u@RC0J1yOko^s!;T^*=N!BQOWU@-8@CI+m+k@G8v9xnpk{uf{X>Oe{ zcR(ERIaj*TcVcjQ;Bm(=%|wem8sFS#d{pL|p5g)BDx^3;JG|zXdmvL5dqf<(eK$V- z#HFXGQH}d83@aGwXxFYpf^J~NN|mg2m=>+|VERWeB3Iv=T;kt(J(`V`U24`*b8le1 z9=VBQIQE{e9otK^v&yUZK&`V}E(Rtq2gk2x#p|K49_Y&U5bEP{hfLNo>Ul@k(*SJz zn%nu6O{c4k(etWKsL_qP6Z{Xh2nq(b-~49klSmx_Rs&}V>G1VPPp2Ib_u}D`7B{2O zAN7xSLA?Hy8*g8YY<2CE%2JYA0_J|iw=MiYRCt@FNJr^nd46m1*wRy&lQaiLu^I8m-Q=Zgzb*>!*^o(iDX++?&H#i}OrGjgHL# z>c-GcsQ1SA9Zz0ywJ)+B_%C)mB?8`Wxh;I;!W+O!i;F|pPgeO&SF}irkj7-wos2Gb zv{nL0l0ngQyx{2++Mp*P>;}yMOSMKfjdJXfcz#l4&`bW7`k744^9Dj}AE&^{chF2D z#YW47!O*??B6>Wg8`onX`-KUt^y4>z@9wz)b(MW!0c z5uKRP_{mHY`kRdYb>h^&COM$nJc2LpbsU)rk2qgQ7Ux^L?J1UkSvOlhu^W&Kxf&47 z{mtgx`49J0bzTR}Rca2en^145s}fgb+j_3^2GvpmZcKEDOW+)>GftiA5q0E0T3sYO zK_=QS)5w*7gX%4Nrq@)Y2DLEUkpq&p8V|pwpsi38YjP;ka(g4jKykn#S{?##j%e|a zvL$L))s7$LeEV0!*Q;6K4R*92#w$hV547&5s$VsDRTNa7A2UABolHRkebTIG;!)Y_ zDtGi&8znC0UY?mx-?)9Vo41osvxhs?L1Hei5z%D13j%exbqB|ZZ{iqlS{3}}DFW)oES-y>ePl3;d@~n@JdO>nE1MR?ZaT-7Be`!>P{W~ zr#rkMF3$9LA&)K2Rh4v_=anVUh^SMRLaq;-`bf>%epR3nDd`#8n~h$H*H9){E5KqD z=n~vJb9&FUjPJ`f{6)DaaEkPDc2b<}bK$bR)=!}|G1li|uX+7w3XM%` z6{EY0HO259Hwk0FZAx5B?a*)BGv2mN&aq}F8SP>IpK$Kt z&WW~gU~CUn!jX#we2ef7VrNR!2t(_T_TkN!Rmfd1%%Iv+=7wt%MS+S+(j`_3Ry}2% z7V3Gne~@~tCGiadm01tl2xSAZ|09nLq;c}4z|jhJVmA-K>r2m19w2{ z386q#0095JAAI8toQ>%NGpl(g++vq4;w>WV5Bso7m!0pT06$+Ilkgw&9xK`NW3 z1pzW0=LI1;pGT&?-8{BQh@xnQX^HC~|XJf^VEb-!c~xaq+P0Q3PquTPe(spvLV8?4$> z-x{>KxtTWHpin3ktAxuLk0_NZ6stw6IiIkYE$6F5tVZUmr%;q+n6_Y;n9Nh3qm2hH zrKgKgipfKc)2(vf(A3QnhEvroGmcc%EmR__WyK`##j5I;IjdR;O(Tx}a%04jZVx zrSd9k+OI>i%3UUG+%{e4p30s0U@atz!0|kbM~&n@Z_3Sbz4l7fbT5|Drk&5&^k?G@ zh(($7C)*(Hx}IpSwm)`@UEX-Fm(0 zb$dGIG{Tgry8Z*w4;+mK05CfDRoQ#xL8xm@f*eQreL|;{1kEI);@WfK?j-rNYjXK1OZI6xKdz#0#zd zj|iq_p+{l^TZ}?8rnRACzj0BgZ7I&0{#X_E8_a z+jueVV@NrV5hvZ-M74&8Ot!A0oOjBy+V?`ct`lJVw;{70^SbSeph@o~@|Z<)6Dl!{ z%wlGdGTEhZ<(^2DA|TZJn48aCvfkGz{O|j?U+xD9fd2M>pIVyDMvD&L#m9FR(9GTMw(aXg?=YbMrN4_B~Uuv)J-*o@Zje8BCG z6%dcgW^+1S50p@?{ASK_`jJE6Cbt0u008*7UXJ>ePn(Cv`17w(WV+ z4bS_2*hu$(Ln06a8j(`E4I-gXI0}(UwhJU8kwhwiQlTC6wjR(f@QAOpcc2!G#A-(c-m-2Zzotr=Ud|47Abpu6nDP9^kN894?3R$#&?p8tqPpi|KCgxLj_pyYnkPfm?qJ{$GmCPx1KvC&e4o zh(sb0XvC`7?vO}-BvOe~GMzCQO~z7*)pET-p-?GQ3zah*Q7Ki*Rf|+}JYlg|ES3vZ zvRrXFUCx$^)bf0R!C*024HwfLkV$1SSdIQ0xY1}dS`3#mU9eeg)>@2Ka(%$za5-G} z7c-pDX?5CN50-Ph;PH4op7)os-0*pQ-kuLu^bnAO!3+f4ck>9`e=T3XB)*=#H(vcG zF~6JL)6mvlg8yi)`+3HRuKQWa%C`GO&I|AB>HmYz5J=R*W%PSQ!jVWcqE+m7NFka>#sN--tUJjKrozQA`I9`oZbG_hwKGEIgMZe42 zDu)dKcxMf3J3Uakotkh$P;7XeD+e~G!v;jd+>z4thCFPLKR3;=iir*H&s>j7zTi&S zHhIb~ud>wq1IZAZ4Zwr(y=d#=_W|ID)(2ub<)0aU@3>j4o~jg8JJ?!L_0hXm;Y(I2 z=?FkoDgU@e@1O(6Ik;dp8105qi<%b6=lhOx!yLaBnV7>IX zbk5x1%~_FI$~F3-bqHL&!~MxaXDb;An)G#0#!;uUxLcOeWPnpPl)#i;ohYzS8~0^t z%~#|zwEK18Me$;)hUh*1>C$*&XW$EjoXjTxj_WQ$yNO0)Bn(1O0gT?gZm-*3z?0ps z9j&2#a$iX$maVWa@37Yg;=$l|KEjC{{&1<~;+_((#~v=|yMg-<=6W^0BoLmV55j?Z z_NWleNPpZM`u2VW7lC{Hr(8!j0+SF{fH}^NvW%HCwlB@5SGTt}L#mF_s_+pFF(SvAXakoGq-IQhrE+AQ$hStcYKg@A@x3tzw}|WkJU(k zN|=C3Q-FHq?*{ra#j7!t`9n9f3#P?G(%9%!lLml)Hqw`nC=%DRiU1r7dd)v- zw(I(%@$rG@_+k{a`7L6?3mhT~?%v*ZDdS9GK*FZ>bDlgWTGn9QR9!-G4507ogkCr3L`*=a)(I&f09!hYp; z7=G^AXj1y3+X7dTz>b|bSl9OT{>Pp$bP@Pr3vdLW21v`fuU%>9%jkY|CXd0Y(d^mIZDrd^@Z~LLQVGTvzsT6MFtm#dOGa<9K zKEYF)dm4PXj4LkXOdwYLX#waMElWTlYnxciE1qV(FjJ5Cm3@NOVWA97_+mg!KA=v) zJHj!NTN&q;fP-S0Oj?_>f=3Zig>><_urg`LI7t~JWQDY_iDH>_Bvn#dQ7u~!RLgUu z-R4)y83_w3H;5-!Qh3>bQ%*=oaiQg{UFjLP6G& z?4>9VS9%>T@jRcab`cTjY7A0I!Suq~@DB>j-jdLBOToxN4JH-tY3RF)!^j~GCQ*ip z6>@XuNDUIp>9)ur4odC!ekRcv`A|5cU57i!a6QK3} zVti-3@T?L8s}`>EF5d3|82em#m<@Jk2+FT*=D1p%%tJZ0a%4I5W8{Fk1<3=Z26s=L z9d$aGYA?f{q6>l7AT~!MuGbU)%CK3$vg!0s!n!$}i@E5`(1vZ#DRrVP-u~1RSl7d> zM4qe8qkoz<+&ly@$8@ojo^F8T6I#NOIJ;dXdyAR|$w`PkwYDpV+>R%bz|`6r1a}@Z zqTb}l6*H?P9je(yggvb`K`-o)H(+jDFr3qMbTB(zwglflq(%i_bEOzL8%DHo?B(}} zTL$+Ylw2mVqB(yzW8}8a?$CUud=n0+*qblkpGs3wVBd%;uu`F}bJd~;z}`*Ops3E_ z4+EBZZjP=X)dMphPoJ8RW%zNrg{93m{i0Yg%$X4AJ;gR8UNqSdWc#LbXulQ5<=vr# z%|zazq{P3SC7Tc&r$w76{~b6SXG=EK-%;Pm$-eUA9H|a}56Fl4Qtj=JRF4X>?*jNo z#rV!FVZO7cE8GvnaxBZ7DpRGD5Xv78$rwAKG58*3-|X;y_l`^MwoY$~A_vq6GQR-f1=lI+kpXSd26@H2uA54-)q&U)9rv zLaeeAUy#OOKkqFMva=6WGiCtb-*3Ww_XFpL3qlKVYJyrf90H zu5hxn+U*V}{SV717#Zmr>T9bU?CthPBRSwlVSWFGCI`kxru)Z2sMxN#$$Q5xBJNG~ z4G;3O|Ij-WWV6uM&pB%8ce%h*TPJ&wu)>XVP0a)(L}Y}d#N-4eL95wrddzyz{BKv} zePN@24dGSRmpIwlZH@=iLHAkN-&!0@jEzo?E3{3@&T^7OvB_K(tIyX<{lX>u8I*qV+~pMEL@KPo6YuK{NSugc4~QoWrZw_tPjGsE6hz2x-Q3Q^vx>2A-(QhtCUBaJv*? zn~WdA1k9;Pnp5y5(V``sXxK4>bL!AD!;|${f)F|P2yjAFS0U?%vWHpdtR;$I*{4ne z)jytP+Vq~0_PDOIhpcoD`&c;CQ*)tP$iqkG!lK<@qQYxVi zJEk5o@lbbHMr!ngN#)dMmH3kd9`iCUkTVE;bj!b2M0_kS*RAts1WJrHCGVRmOb)on z6*iAtFDV_?MXpZbbd_0zLW>=WM(jbDt|-wg{i4ia0prOAtDOY0pkl+?q74yFFqY3q zRpRP##AwBAoyBLovtJ|UyfN{-SyWI=PjQY|Q5-$?m(<|MWsZW;%B=GaZWZ>OiSuAx zINa96MjoHzx!8BE^6LH6z|{spvcuQ1e@VH~FNo!{#HC1QPbm1DzZT#vS;ogqVS!6) zt7K%xTx_&dWnEgftBIq(HG4AUdpLjmP#P7!&Wc;}%DyTGvIcDSV(p0*l@_q~`kGZ# zS4RRnbE;HNgB>=!Lj$kJTW;2E(rTe+D~rzvKj?Ur;i%w$%9l@3Q}@)Ti4F)3D=!nA zk{or?o>YLBkX3T;{CEkFSH?kl{QDx!|&2ccbuWH_KWnE+A8;`hsD>$31|MdC5;; zrB`R`>1Kaw`T}7^u79sna-EIx>Dkab0sJ?Shxpw=0N?T!E)nMd0RyGczg^5+KGv3M4jBAKa_!H?Wu*AJ+*D> zProWc>)_B;an69%5RKSoE>f%A^VVh%ICQRuDBXq08EQAt^7H!YEOx!!_0*Y=54lfM zTt5eI*p#H6gx*!9L)^_Muqlp%!>QFvCK$$X5<13?ujMs^oqB3 zu}GWrgnjk$zGwAl%)0Tssm))z1=h`ioHngahuY_T0o)-Y&QLNJsF^by-Pu1~6_x1= zE?wnW?qY7YJ=X_9JOgB&fisUVdS|FTD_)<)GwHS7)QfBn=5zE>n5nTQb)r=PE=D{` z)|el2r6c9;e{_dC?`V0WW^UCE-n*d6Z=tzSeL7 zP6aWJ)^Jf*r%})*1&w?d{{A|W#K zVL1t*nd%W%hOXN&vJZHHPF^i{v)f>@llBqme0zYQ^0iM>A9SVkR(Tu!+y`*i;%L;p zy?RGSyLGP`xmd%X+z1ieCJGP{036K)t*0ZWzFR}_wPiS+fkDRpiGk&x*)qTJ z<#Dw6syG@~Os0l7rfd?lj`7^ba}&;tQQfC{6XcCSu`Q3Gt^Ij(l?y)OLtmf3t#l6JYB|HBaUM1JQjI&KplR+C?C7UdXQ?!zNIb}Wpp3MF556PCg;_Mvu zNaN9uTVr}o>^8VrBWsylUM1Zy_^4WqU4L;Mmr53zw-2hG`x#S`e&56`KWp^a;hLEr~|XB76FhnOn4GIv@Joi2>(dJU{GO&aV< zeDmQYTT;D)~>l}qwAw!QAPc;R_X4u5(tqLl;}nKJra>eO>EOdyeW8 zTXPI@Q7{qPKs#J2K9PrBMcf5UVk(X zckm8W)d0A~03ON#V`m>j_P0(tqy%U=sSAmS;t}Imyy?6sV@cLyg21bws5rp^iPYbJ z(kI>;=UuY437v<49@4o9X@{^La*7V>ya^@^q7@RM)`_?ca@USN^*AoRbWBIV*$U=e zq*i~b3!WamWfsC&m(kW`x!ScQyv+Gd5O7P7nZ-)at#!)O+P#56!hNrLm7D=`gt%sH zb*l_|GH4ASK)+0! z=KQ`U->ZbLKa;2w>2))mzhe$+xitiRpw1jVM$SafIm=YIRI+e;)|+3j#+sLCLevqZ zTJUV*wz;5bD<=4Q@ujOE*pAuxGKC;`LwHlb_dg}~nLYwPs+)jpSUQqf?>mC&9m!LFB z)m>q&YxcnMQ1s|=(=%~z_qN4Fb_po|>c{J3Z?o%m{_-=pfYgyz6Li@N4d}0PA3&XC zlv$Bx5z4y2nu+KH2+dyZXVpC_+G75E7=VLW`nVbS9aBBs2 z0B9OZ00Vrhe1qfaO54h`AoDcT;5B=L1nd(+ ziq=FK5I2AjHGm;C05dh@O*Ld;HRN(NR~RmKE)cAYbdtC=#qqMaJp&Y zO4Dm?`?szF{8Ayq26JBOyyd$1#u@2WY1m`7?t&PZHp|M$l$(`K z$H%mOT*QMtMa|$;8#Mf0Mpru9z3cWw+8Zt3@yjQhm7p;St@Okq=_kehkDHV+EPmAf zo|*!$H<{+A(Fk?^M#mES_t`n8MdOf(>2-R>|N3}PIb|`sY$j(@+idFRwEJ#%ZFRLb zCQ0A8Dd*67P2S{W@1XkZ=;b;8(c$qSuc+$#}bHwG?2Oj@-bJ8il3?m zOGehD1fkn#E-N@!l#bu7I@A%1M>qq`Hw+zV$+|EzaNMS0T{f+$8!TocSnuAU4r=T=^lfcJ4%twab zxL4c{0|L1`3na+^N;<@1RXPll9@(_tIvv=_054e(b27|P9RRV+pPV{aQXM490FpYy z`|K?e!A2f@GQihK^rJ-z{H-zMlD`f z!V~pusdz;k{YG>CLcBH%yR0|ik#s(*yf@@gb$(;lwJqpA$27(b{cOvgZWH`v5crmW z6@KoU{){*o|Bnw0UKrV|4^nR7w}o{sp-<}jiS+i)5c7Lh<_Mn#U_ak8%F{}&`8OZ; z&%MR1oz2?<@}Zx$($IDFZgS=*5*gA4$Hga@#b>Wb_1?TBpj&9uu$tg?z3ja0&jSvY4 zs62#D0mQNqX_SN%0nAoD_+ub1W9BlVH~xr(-x@#Izfi{bPXbKY3sFX>kpXu0z)a#j za(1lP0HZy2c05^s?X@90YYIf}D0I6NYHW=D4s$I!8sG3l#UClPQ znlS8L(Kbk1(t9m&yO96*1biLbxog`7ejW0$>+24H7aX>0;0}TpGP>*Y3cwp2w`=qY zLdqzXq|YcFP);Aikp;)3PdXX6Mh|{Gz)c>)m=1qb2S6kbsGts!QU`%Hh@=iR;SSGG z7HIhzx>g%-R0m{92uD=_ckZDEI}0H*`F0+r!jFYLdSq7LaI&IH{&`sLD83tzS8kut_yd_3-%Gs z`!x!d%Vci7y==-9!PdV_-ZKkT7p5u_xI6aC_b9DFfxQi4+)ZTmbXn6C+w&mgPD1{A zb`U$2v>qNvY+7Aq))m_>fKflAnQS+ysj<}XEPA0^>AKC_|dK8oO&3V(P^6K*CE?-6U^yzu2-n z{Ep~7HS;WiSL=B8ed4>t&{D;V;y&>X!SznMZIHqn)A6w9IIdP7iBFJAdl{tK#k{Oh zWmPY2q!1(`y%Q(G_Oekjk1afrs~BwJe{`aL{5a>HW5D=MeSaeFhp27)_kaibM($Aa zgX)&)f$OPVqq;|bQEx!4DymkdIg{VFFg(*3Yth)$5Xu#Gk*2sS{L|1oRbCfr;x=MW zNu&oW&#tb#->f~N0#$zEI%-hzey9F`@fMirofu>msy8f8dgSWs?A&bJ!yMcwF&8NA zrM5o|0fir(JkU^SyhDZo8PhI2oDC(k-yQ>y*Z?Iulz|?Nl})LeMqg?bswLD$UuzYv zB@B0$2=jakxMcE}mbB2##MCWlYwSi~+;-M0;d)AIHOyIWHLfLy9AEkyfgNcFSzL}~ z;^{0~!R#S*CJ1^=PkPJ59`ub$qL!!|tA@~zMjM<>-;3#tW^o6qHK8}?k#@dwkN5En zbl-{b1G`@D{kwYS)l-fgrFO9RU-dA^1!>*IG4t{yX7Wtn1Lkl^s0!JiciuV1UAip| z1?h8O8K@;i)qO?fEQOpPOPD27H`9~N3>_1-!#~M%!!y2myS^00Pb=ateBXBdT00ub zeEbY2hLashd{F}*t~NVj-@Z&+BQHorHY3D;M_hTyrg63ocu}Naa<;Oz(g(qxhdrfK5wJ|G-<6T_wxKDHl=l`PWt%KrPqPE`? zA_NZ>f(LikL4(5pgS!QHcMtCFFu1!rfuMuC4{j6O-7e=n_r2eD|M~5wp4DBoYpQ1N z-rc==G5i1XY%(6ry7mBvkYDp9=$GWTu+s1TiuAO&WL&7ORV*<#R)dpxlDQEK;vZC>d88L{C(Q}YxjUJ&2-)Fl z)j*#Q&#LT>UI>?q1-0hWbTnK)GKSP2$ASD<+fK!+5+_#{KfU~Xphoh*oJ1j#FyTrN zR7*CocK!j6gZQpVl4Snf^H_ctR}E^7%w&3gM1r$sUwyr*%Y4E7 zCQ{$~yQ>0J9bpzaH$Q7+g>w4GLe;6Qt9UXq+$P}Jc*{WS(w!ZK3A^psKb_1B5GJ%` zkFc?2KZZI^S-$==vvv7=Ho>{_w#-CIw2SJX7svafXNRc9MP*h^F`dDuqBue;1o)M*EOiCBELd>OJM%+e)>r@JPsZ zaYsM%y(fPd4kyg)3x;~Q3LZOxdR=58y@)7gOem|f*MaicV7-B$kSM~0jd{)}E&97C z7ycz#I1Ao-?p@-|>7(&h0!& z5Njsx%^%l@Ad$@>VvdTD@RQdXvoUXZX$g}~becVNdG9#eA_`*g48tJFU7h|z;bnn! zO#35pKk)F-bU^&BqLT^Pu#5^R=+H!TBEyV6mH|GRu&$E@ar>8IusagR027@3i-vnbBoeu zA!^X5KD9F)rWNxvqgK8FAGqN=9@$ODKm*rLjTzVjpTp*_raY*;C7s#+aZ9Dlb@O+E zH{AtDQ`6?<9HU3QB{j`WbDHFHT8VUs1Ra@=6qiDierZPHxP>EP@6EC)-rbb_GN?LYv?)>jd%ZGZ0hd>B0x}r0D>oE=s3Z>Bgv(Er&9eP>OKVs*vDyxaS{#)|@HW;VxWO{X)pGmjwnF%i)N~8n94?-I_4v zY@5XhTHMXHf7JUBELP%@wx9e_m^*FiZhRXH48J3EbZI2Pb__Zy9%MOz6>vxQf+<%L zM^B613;ZFWT(Z>i6S_>YZ94br$5bwrpPxygc1)HM6;hIG^3SMdeZEXG8Qr6#(BopZ zTNwyUI~dh2?U2VyifA&H=iSNly2E=1Kd49rA=hYp24sH!V zpt~BnI{$vu3IrSQ;$raec-!ow|Lal1&e3+yLWu+mY-5?sx~7?l`!QqzPWT`i@90+* zmIkHWDNkVbU<~_vS@hDT$2Ic^Wn)RDXJbgGfmSrjc_(K35$KW0#O>mth2o!VQ*NrI zT&jB+Ts`f?39rZ7@ucPX9Ffj-W?7$QL3@^JXS}s@$(SOewQ;CAM}U7QnU` zT>=e2Cv>8gj542q@sO^UdPFJ$_;eOB2^)sp(X`HXwxJvQYi+JVu^}TJTxn4rkk+si zom|PzsK@&83x`M_>19*YkC`gK=XSBCs6SgC)9?LJc4-Y~sjYR!f64u@bA|+cZ|qdA zfdLOZOnY~%(HJ;^w@l?~?k*3Uw26SR58cKO5iSd4T{Ck(esW=bS+(-YdALw( zbz=3soc8yW**>fLR+(Bsl}Fc;)vMKCa0hlO?P(fU%J>A#6LUO_J|?lqY*MeY#hd(E zy0c`m>7ZXel!=dCv!qmM;K8iU$2=++Ox$^|}Mu$BKVt%EUL~P|ewk zsu;nLR-{z^9$VEpro(gP=&zpaaFyjfV}z3)IG5$Ol+4DO&dQOt!A_KVc&w6}TJLm( zJ6F+bdOpG2{f!?pC!{&#q{|)9s;fs@r{$J1+n5XZjA=_4moN0?@`xTO-}CTXn=t&L z&_pgO!DiDv_^mcu1)DZb)_$R*uXVEKk0mEW zUVsr)Q*g-6RpHA+>Q56xM5Ecj-;L&euTMmjhoAcziA4Ken9EO&YFjBeyUjAeo+U$f zkOJ`+m~v5W<-}D-y;caBtPmJVEzO?oPTUT%ckJi! zH}o6++EQt)`*?d?1|hw~pVQQ#c-%$SH#M&uR>A*df(mI8vj?=|&%PLBiPRdkh1F zEeyMdzE*Xx5*1T#C@dZw^*i*ur+0GGkB*2Yq60v4xBn6`rvLoH@t66DrVhLlN)60L z%w?C&C4Z#p85=J*Xy@O)aNWjGEl8PKTuTQ`yMsP=D_8v)C>c{QnhlI-f2|)Pt0%3Co{(xI-0)3nz7zXG&KQ1gi2Y=v{ zUhQ|Iu?f1wabXy^f{S}DD=GAmG=JofUPTs&|FFE!%a8jwk?h{6XwG+$7=#~AFK@5> z{p*F3?=-#KD+0d9#RuRKbJi1pURF8*yfU^3O~ndG_CT z*HbL*BQCcaPgBl&0;c9I=794QbPICPKrV~db%70id&eq%s25JiSz2t=lN5}~ClMF5 zy=iC(1U0-}4lQ&a2-bu^trx}5%w4pm2d)YvKs+VIpFC3d3LasL69prllPAfb!oCpq zz~Ykn6t1CSx)J?!m&{*~QO*mFolq+c#`hhj%*I;{&LcewB)NABJ>Q4pdzN7Y1)niA zJ6bvri8ir^4m$4!uE$ANZnz}3A*mX75C0f%f@vB}2-r4PO!6t2BdS|DneggLOhIS^ zTsCson(5oCzovc)^Fa)Qo*gT1=swM<5Ux)f4PB2hnlDU?Bu85YQ4}7q@Q)y4FDax1 zmQ&o5w}H97eB47&2C;Ovzf@q5$(U!Mr8%oX0_|5;yeoyS375Zp#3`+YpKP~L%VC5+pQ9O@TYOAwpISc#CXv17ZA5Y{*7gz1#|zc2tnt`5?xV@lNZ5SSARkF~ zLt@myx~y}yg16D&NCewR;@PdvsJvmgcRD{vlbCsEn;rqi-}AD#J>_B_h*Wv}j%W*c z;zEJ#D}XjToT43+b30Nqd82FGM4Z6txa*?zaKkq}o^CI7X_%Az`J9^EiH&CD3pa0g zc!cm_39VROqYb$x;+>nNS-``FFQiv)T>HZf=ImAGL|=#Qqc$LjyC_e`@lQVJdt|Y? zW}sGX*BN1FHDvl^{XspWZSnCaA7YjA?AM^LH0!ST@@jmLcu${eL6bx4VG>Vsu|xf( z<_`uMv-!GsG_DCksWfGJu8`!r)8Jc;tN9r}ben>afy0FF4{m{6N3Nf^3S+h@e<9YJ z$Z$(XO&+5x_)rvFPo7@d5Xi~fv8YQ|xY!3I^oP(_<^<@fSVv>!vxmYTt}xegYglsBf%(R?tl~Ruo9;5kRoi znzB_EtsIj#i8f!_H0B;meEuN4L(}K*6GvmwaS@`FCDE-otd&QdW@OY1Al8dPRBF4` zY`p$$;)2E$k+0dWr?hU!BL_`cCQ|t6sR>PKys@3SSG&?&QPS;Ii*~Vs=knjQ^ot2{ zM{OPC7K>ul(@nnkFo5$BFjAjR2-DaSA*ip0eJn~P32h}BOEGTD735xXT&OO6Jj_Z8 z+_LbYi*eAM;+wf}B66PcVU*v9FKqn|OZeZyf_}uR1aupM~C?s|l)3Ah8Tep!NQagK*DJq|dkyUI! zVXa>YdLn-RG8nUWc-nO3XkXA37aGj7lM`BA;JUHY8@v1Bn+y26Vr=cvbG==@eXCAb z92D|(i7I_Rbg!Upi(*P=)(?5f!ly7*Fi`it+w%VuTl78|eqgwq79rwv#G6>1c0;9L&vJ!+mc`eK z>HTRdH^P0We@jW5ftJy_V%}4QJU;b;$=6T77SCdGe%{9*wJeu&2>NnIVM3p zFJOQhM?H4HC`*pk#41jSuUkQ^Y(*{$f${9K^ih7ODHrxxfe(%mj>pP=vn`yR<@`#* zs6qtV648)6PaRG%8h+F+mw)wQU*uo3NcjZNC=XG#ajV=#lf=u}!q@4Vg zaF<=&>m|f6O#3nByBHPX65XTC!x0c1e+U%$q$YlnG|j^)nom(iM-7JqwzdzD3l($r zR&kVjsSGpf%?>t(k~rsx+u~#yUjNRh2!de&+Dfa za%K+e58U4sJsJa5w@M3)o1<)I1H!5*AlqTd%WxIAXwG@MZ+U2{-|B?otah{S@IK~6 zX@!H2JVZ23J;#;mdJ>IO3-w>emtraP)$PsL;*+&epY=@dIJT8w4n3&-Q5fZ{KF zj(NBbzhDSwp6*yX@A4VQEqQ%8Yx z*0^bBcb5=GpszG-)l)2XV~s1}PH%Qo29}ZgZ^`I;kPZ@*TXz#yve~S(1AgwIxGs=Z zHqgSyuhoZ}TIz)IMe(>x*Z&k@q?DG7o=zIv`@G9rSKv^FRUM$r6VSzAKZch$XNh9~ z_?&ed#^3i)%Ggmw%rw?rKfbY?LsP03@GD66uf472_sH62df+Zv1bJFd&+UQQbxd^@ zm+aqhM&Pt_7~H!kqnM)$K4qtnQ-gV8JHBZ+=YtE_AdQN%rJbivE8J35;t$x&Lb;D_ z|J)}r+H@sS9EojuwvNGsaZ;5m#;w(z^)33TXSYVfoz+8&HTU6E=O-hh-G~J)B~)H( z@j9_AjmyruHqheOQJe0A4wQ8=ryJR~cO7CMu``uiD6FdI`X>^8^zNH%vRUXr#JAI1 z4CAoJJLZ^S*AtSLEVPSa_Ry_Rd1d&iI(Dw;^AWfaa0>el-;{ICzHYN~bjFv7>pyT4 zj$!^yb(i2ywXOlW17ng2=GFb`i4k~{Xn(EJocB7uHi+On@zu>hggx-AVPgCXgYS%Lu*YsbOW6uIebP|_;a^9@R z`$ja#u_L4|pLx#&zHea9t+~g*DcM?;;V4f(uuJ+4>uk@*ltFc8IOm#4}GiO0sOk^vk36lv@ft7Ro0Ll5IE{>_8X9o21l_N_AUg# z*4tLwJhWA`uq4|4kU4O&uP>a(Rr1(Av!bIr?~1Xvt=-KUc8=;WloSNrp~4lFQrTPS z@f^iK`&dz|Rq(h7L7xpXu(Fbi@7P9J>Bc=nO^vWgs-XINYy{J~_p-TrW^~+o1F~Q%2|bDECy<^xvnxDl{vTile*na~Cw9 z$8pz=A%XRm-<=*|zCFdERN$|rrr68vQHlyq^#mWs73>mweO5C~HSgo`4m4uq1uAYa zmuxP|DiJ+{3@2EtJxvhYBjEw2Tr75hl-b5AdRX?q%q+{rEJr6G<;=sFd=OpzaaJ~h zjc+Nb25+DCgXb`;-Pc=c$WE(9KN$|x%`S1BwVsz|@i=_VC)?>L#0{)b1R!I0^u;qH zNsS+HsTfOxqM+1@W{APLYnpgmF{a6C(0^_jG_VT$KH@L3V?|{=ZWn96!~))otm4Z$ zoAOfCO_v^*QzAR=;Q2$Rr)ek{6^NN|2H@oAym;)OAp=hRmO&KDMqRCfD( zIO}P`_9PgWpP8pSD)!gTE9pQyoe(k1eP?7PLCV5gl6BD8FZA!87QEfaDPIAu9M(Td zqmFLOrUR_H6T{515=kW-U|$nI$z`bR;d0D5nkDs!oi`HBeiG5o`AjAR&s}vp-OP_2 z@0NE-v48iI15mG*SPPtFy=kMD@jdy_51=UqT~zLT*o6_OgSV=x z5zB+`K`j&ID}eNIgXvxz!i6bjrCi~6L)c;za$hK)`!QHHpKQQ61-`lY@1<*fNqnHq z@~(G0GwDkwOF!;ETD+%taTcbernsJw%7z1aKy5%qf`)=Nf>yXt!`HH;2jUw{i~J(* z(q~~yF1|5!6w|Z|9z2uECmpvuGyX@9M;o?BwOP%HSAWE3>_?lLOZpDy9+OYGzLxtF+t;vzun)`3GfX+mItgco=uy!<&4 z#rbfxe`8onykTtu_@bA>_g8(oSZk4<>+dmuWNEciG&`;#)`ZF>+6$&ET#!Z3bnpy2 zHr3kqJl1QpI9kx!=T844X~~r=YpBM}WlU36=eQiT4pOjOy}UNL$^LxYe3Zg|;k&vv zO?wOzJ=Hus(xY(NTo-mEL>Q}XZdz~TT0U*R6jVlfvZ6cHVm}Brd}Ylam>it@O3wT{ItgOedPN z-5~~3LszJ~Fx7%@>&$81ngexnGs@AFn#WmtdC*!ab;V+H3E_v1Z|nIAO^nF%;utrD z9_AtFrs%14o=2bv{Rzzjzd2{st;JnFfm3I^bN+)|;0U9AqMec@jklk7sdw607$95W znR4D3crCX2LK@i4VcW41l~R83;Jy&9(J?OD(?o~4!0RVoaC+uRp4LJP$yD()h2Ki! zdGWXg{m6MuEGTxI2rZ#@zqLyzU`swJ)r%>ad9QevdBYU%ngu8we*hRi5i#Ae7xR=S zE?jjTN`klx71)2PDm4#?RK<_#@g|>ZCl3AaWO6~9uV8DC`Bj`aqEfCR54cg$k(T<( zn>E8UqrR>b2j*tBty$pmqvJig>LS#0_H9Q!X}@}4yO}uV-y$2qqAAyPl-X3ut>UlI z$8S`CJE3wY2Lvhe(uts?%?E95a>53zJdLT7>Qf?Q9FpbE!@baB%CC!BM5AKiKOa;6 zbC51{Fx{BBYiE_+FhJWBw?i-bURUw?-h%`x@X}TTPiq6|8rV> zqGjC1r-rv;+OsB6h+_L~+jx?VF8wpk`MkpEZ20j`E4G9o&Ne)I$2RS&3KK|DtF`S= zb=}_jAg|@%Huka$F@{y{A1XXaVp+S|k=6t%bASJq_AIW2{b2>+=@gf>UA&cb=*$wQ zHaMdPjoBG zxZ%oovcAoCV%#M|-BnF94%{ME{NZy8{tCZ&`O+tIMiW(&zAZ$!!o4k3>8{|=l<<7x z8DPYLijR!$vg|H?<^OBQZw)aUm%zTef42o)Kc)AN*dEu6MTM1>t6bdQ@cHG@if67p zv9M80UD(60WC(LN{(Z~ei=rBdgpa845&M=GdC52cxxo%x-(HapiHCEpbHWK;vZhZW&vJ-EHM-U8ccpMu?EESr=NTH_c^a zeRJdP*)o_np=s<#_lI#r%k#PFmSKCo;U<-DDyu1kC~5=EQzwnruUY~G(9g4jfjY`0VIKHB*4JzYcq4c3e)9lvYN%s=mvne-;TZ=^1Z+JILPmsLKd`;DbZuYrYDd;8y8Zp4*-JTjDIiF57)xFT}FH6r3#vgmhwaI#yxk5Pi z^K7kC)AzLVbEudGY7vf7v^B8n?l|Z1yTa_O^)OKx6~nu7=vwD4&FkuJ7@gOYuBX#3 zLrN8TT(MjT_(4$3rx`}esH>sVnf)Sioc;Id;~3kdOyuizmsw-q@-6f*7pyj#1tZoY z`X8Pj;iHvzFa0~ut>hYdoH`V9Pw1pbPpYg$;Ww%;tM}L9M3Q3-YYCI@_WkpIW^bC) zR@o@^grLw4U300h$$oVn1$Z#Nqd&)(@rrj}IQf_tOC+kMcH6f&bv}Muw)xst*C?W{1#xz`%*}1|1u=_v`_q2DyDHSsyBHLxt=qyV4|)O zaoPO>t!!(beuw$pg#D*|bti@m<7D+YnP&{Zqp1tLT>b3u7;Aa0hk9wK7+iWCU4^4x z9y2tYk4QJ+i`LSa_>Ejo<8sb7LG#F(qYplT2iIu1fu;w75PF-Z_r#se}+v;WVs-;I}M4HKWCrahEm4#&K!3kSMXhgN1U z?h0+Iv2*H5Ozr4}rKo>SOF=SOqncomohpV4u(A4{m~I1;LF=2@UITgYzaxy=|!ws$aDJm!9((RB(#%qRGSi7J8kX4 zPTRWXF0Wpn*NEpum1HRov9t|qt>1JhoKy8CQ1ANP2`sJu+mZ{m{?Odq#I2r0vv6wEvxTY&?INSjx$huo_Bxsung_P0d z2J-?o1F!Dow<|g4WQ6Oz1`EEL`vN)Lc>_LEnf+}q8DH*npfpc-tcMOys#!El&`!{# zK)wy{y_3PS`0Ci<`KKYDJ8W}I)+V;x_v7^`zg$yUY z?i+5Z!CKLd{S*kP!~~u^LIJ*=!_^c|xL$nFpo!`dayjiP$PkLtK0`aagpf|GxLZu2 zmbB-w-&m~4wG^AynYLAb; zCq05{B4x-&T6`PR087PM;QHrmz9?1ZB2vbd4}UOtX0SH$Dh&VDWp8Nv8X~ndVI2tW zyeB41(XiRo;FSYZHoO!T*~;+}#i zFYV^_Jio-CV~sPis2raKO{2J9zz4p0;A_kFVKnntJJgkD{9Ga2J|Y39pF<=n9;Kh5 z%yg}?VF)Vb9@-|)Q#IAbdpKnzzs9}wNmm##eff_jU^U>itC@E>>FZUbhixT4pYI^@ z_UPhm{lqoLl)-3!y#d`sBG*DENW@eMub{}1&~n4ijp5)xNJn=N({dM>?(0l(A|h%t z!6MzT@AglRWk%B^arB`$r1DR69Fv*jWmn3}?^AQab<=@IK%`fGWBOS|$Lag?vs2fX z!2)d#c9rJfcFUciF|M^IcfGr|#1yxs>6a+G?ifmo6aGJMP|ov8;h-u%pM3qb^$HXW!Ek937|8wvBZQ9`0ZVaQ@(L) zh)YW=LP5oVvYlTQ#Q3#?c;ZI+%7kKv?vxMu)rrVL>>S{)W5Gu*-d)Y)uR1!0q4llS?ngax{x zk=IVp`}QSMd&BHH@$ln*lWU+)6zjVYO}XwwOGYN;s@lYF$IDI=u{XIV?X@dhx5Ydd zN9l#cU6|+LD5B z3yYG%Xb(IyaYxO`c-4j?6l-${PoBv*kW*0{qk|Dwn`KhgRUQ{+S|91n4r$c}kZ4mw zV4L`*(aW-dk#pqhqA+v>wW2W5-t>(Jv*_;KdGerAekS}>;+QbX;loJ>= zRW1#T+$y=;*lbT2I#B#D;QD`*UeRum=2A@{{=Sp>JJuykygw(YN5dK6Gky5;LAw6( z+xNyM(@-p}arx4wczs1H*Wg2N{2;y2c|EHV}5eF)zUVfbsdspe!_mX!g#ixHKJ z366^~my0PHz<}w-g!snT7j@@z^bU3O-nZyo?r7Kt&<^U!4&%ul(aEmB3G5xw4hhj7 zI?*l*5ey+~hbC(em*$#a;u4PO0)y!ivHAk9`tp}AuN_Gk19VWAR)##}})<~Ry0=(6|Y=7pVg z3nL$P7V1Qxns-UeRjojG@f~vZKJ*?#Z;#F^srtOJv)lDbXIBF-Kap%YaeevZ)iud< zA-%IU^5k%TOAELY@9MX`hCZWq&759%J_~fM6Q999llb-#UqhbkeW$Z6E^aSh^161I z9`RqAy0*3Q#9~#wa0H;6|j_~II<4{d9p#S)m?Yl98F_-Q|!ei1=Hj4SV~M~isM*PMVzN*3x`^fe!*}aBET%~X+D;L{ zT{k$gnF98pG;>YO!J`Il>xqj7b_PRZ%{bLMo=VW6db#px|3HHrkBkq>!8D1$2d~ta zKVFG3qz~VSMK0_G6qd4%5{Ax81){XGcQ1!-`#Vz=8)r<0y(|L-SVW8UWLQ$(9Ta*M zHZsrCRHD=p&R`(y6~~eyDT)vOv>yg)SYyJ(;A7r9pJodtWsvc;m70uPh8+s zNEmlQnixm+XNI@T<)S3H3n@i|Ho4*`rZcf=kyRmhy#wjOaJ)c}EXuUTYJ0l49_(;` z%R;~H9@L4%@6E*_O}svXR+O!IFE3t(It;wfgcl5Ayc%Oo;uj z2RDk4zUy;&)Tj`MBe!4{j^6fs3&3Wty(sHZV6K42=X(w%W)6_q;;-n2u0T=bL?zDq z$`}-w8NNBxzHOg#3)tAlQ^mO|sci^@e$+1RYzf47B8!CWakGGSl1sFN4u2E9?z+Gg zvQNLCjFJdusB1JTHAT%^iEd!qH^NyCLax&~;`{{7bfM}!0(eGm-qigb{_NSi_Os!) z@hQtdXCrZ{nU+5bM`8$~Nid{$dlYdZ2$o8y`Ud&A?oR;Miz*5u%mRZi$T)Bc zlEOu9$+43tbSC7f^AC#C7vdYPq|CKmLIp>cL3w{P}~aFDj0pKV}%XFNwTr%L8s05qD)|#OMOCI-wuG zLynX9j0G_KTKqu(6C?Ywdc1LombwO5p2CY)@$r6sTC;XuQ%h@JgV&O2t(zy*wE?u1 zSy}IvzfV8k-&VKQrok0;V6%D+LOWy<_!Arv)1dIcuSr8IkC+_Br1q6F{Y1whDKwM1 zA@f)={D_)2*?@QaZ9f92o^8paZCVX?fw6^yJ27os^?xX5GA8 zIXrF+oMCRgauFXYb)BrB(Gba)mZyQOjd8c$;(C`=uqX@o2%S<>C=X3BO{wmCYSjNW zs5Wa-OX}0VxVLf;m{wyE`E0RiAX93M#gpz#^SP;qH2&x^YI!*zyb-*S7Pa^`er6) z$&H0tajFsL8W65?E7Nm4zx}wZVW&5=Qh(8-pL>tGqJR~2p5o{_RfAuGKI;PJ!FwBy z*pxgTaAn=UIBnh8E{EGQ zXiI)Y&~DZZJJFSGl$Es<;jOkEwB&xZDUaekXmLF#3wba(1}`Dv()NT+H)}OL2&KYT5hxkFP6UNH2kO8GnbnHeqylWC3-8aOALbn`TOF{#A zm$`I8Mw(^(p50n_ixGtjovMDbh05)$g=)TT^Cvc0%dO4dqyBcaY+`HD zTuNJ})@fJH9@jWI(4nLy9%zrPvM0eYw`Pem6FKTL7izK7V77Vt0Cr>Vj!@%Z z>QMh)-4V9#uC@!`)$em&FAw4I=TN&O@2~A-hw1U@ zAT@*nql@D6OUccLCh;o$4jZDEb5P><@060a<(BT0%6GU2QiCCxY?nD*O0TnBCBBD( zD?OOr2!aMKX{q!063EdW4 z(l&X5uAqK|%#M>OZZSGp#j9drZd|opqLX!Q`_rbtc`Ql)zdz za(`^{YIOml0gwBjl|@P-BM2kQg<(t!pzEWLmnU)m$h}tyr+LDMgV%?yyLdVl{<^|0 zw|J(2{-j7;+LQ76YuNeo&PY`*R2NMUwF^$mqzNmafE$QKp)iW2LBci=X4N0v(}rwV z%kaLUq8)JY; zyIB!*sonsJ-$?9gk?~g|S8qa+z1%=X8^72fKpVf@fJ0-v*kDDgI@^#Y(%$MeCh`h^ zU*CDVR-A1hzS%#6;LG{k65!Xjy0!S+GT_(ux-I#*`vZ)Lz+2s{Xu7aBfG#$$(311p zZljoGgV>b0rGp%mx#fb8l+}xRXlS(yda!A=^LmVFy#f$z6BY!g0N{TRDLGHACa&MrQ-vrQF<@R|0hn3U}SKMA8Qmwxa5D5k8{${~+0s;>N_c(Z>in+Us)x9qs;$y*^!#6|9fwgqO0@ zaEq6;lV^AC?j&?Cn)_st>>9m#PU<*yBs%mcb&#k|J*qX@{4llYAkcYORZj9CF&Bh; zfG)!E?I1A&6uOU2$DdoE1oX&^0h#}GMz#1dN%M}sD2uA&GSmqq1!LI;GmjrSUGgk| zF~(@7*h5W1%^t=>O#;l)E#@f~*z*q>FgW*%(mIkluyyspl-nJ6*Jq72`{b75#uj8& z7a+ESCoTO5kET-75D(q_tks?0C4|Sd6TzBIQa{FasPeNKajz@nf@JY5CsY`-pTp#)TrPZ44RD%kv;sSEw{vqmaQ3Ohl0nv#xYAF#p zz+c>JzU|Bp`+b=Y6My#r3*@1cL#z|jltL^_)Ra;za`zNNOe_vk%+mfEYbhejVbjFd z2d`)h3iU5ik`k*A#ro713%n`8#({$6|q-gT^A{=#9kta_F!dflCbeaF0iV^)t9PoCE7E-)``U)dnA;1^r z-PM<+IEoTpDld~{K#QeRn2Ol1o%@E0|I4UQ990Q#6=yLHZw0ZqQkz5>*eH#X_pcPB zYGFBM7-Y$h^7OClrAYatU9|}@X6)37F+z9hdg-}R3y107{#LBgK^j%eZ&3Zu&@fIe zA9aY*7#?-V)HwM!P&QgOK%X$`5TRkiHiD_?-a{j|Xp|{yqcmiVk!BQ&@~L&`dj@h{ z|92>I-F6eJ6mi0peS*M^U`~w4Luzh}`Ga~+jL-vjP7Iv)(F_F6n_v?10)J&MNz8V| zB1?>P#Ue=zf2EKUL-XJUBv!hbk|Tb9RV)23@E^5i18=_>B?}!OvyOas{*-1I8*#-l zL3r86B1cf)r$800u~mWzA+Q`(8sO6#z3dmMbCdiUGqi=S0ge?5pieiN`W`{4!9JKL z^)=;RpwyYg|F5r9XBOK}qrpD3mH2-(9Kw<rr49``DqaB{1nnftb5ikcKl*IyXcGcyaQ1%_pRFQnuY3#a=fZdEp$bv zzaU}YlEqQ{2My9VdyF@*U}#YOr|84z<0O+s9mwOU;vSKOiS_*jF0SJ8V+g#pbN&}A zuxR)d`z&6E6??ybk;ThsClSp{c~x2jODo1wnXVjeyv$yjh?lgLuF63x#&v9=9B#inTat)3S1Mju zQmhgMtd+xmbShEE{4kp*UN~C<;-Gzt43@}70nZiii5trmT<1#g=#pkj1PIHDL*T&-ZNY&{q zivm^BMk2)w!v=`%MpMN?rw_yo03k~W8I0TOmWDTS-)!h4SyAQd7LD!JgE+G z%qk|&zkaTq+?vv-#{C@_cqnj^ei(_R^!$gm+0`To`nafKb2>`fEWu(QzEqt0R(+>1 z6|28NL58=VFDDfgzEqTo8V>kZ?dPQuh40TASkTuWW30>@Scp1ap+i@qzdCxEWI%cA z$Bw;^IGZ6H_Ek%;^siOsyXja94fe8+X+btImPB@AoC^eYvQ!IB<}9mDGll(5Y@n2{ zGnM_bZp9(4JdLS%*G?8J91KO`KcJd2Q3281CEH|Q+Xxx{%*--_gUw5R zh|sY&NQxk_J7otCn44t<2mc#5nVIB6shpW)M!_~S3kv>fZszx|$Bi;JGx-H&Y-;kK ze*wV5%gt5z4?Kmr6nJxi z{M#UuMpnkKk6l~_CzM7`hAY(EKeeupT}Vd5ApLt0JxeCl8)UyIC8tt`(n!l-_9c=P zAs7s!zZnjFi4^~8jF}HC#*L|nT*j^Yd~Yxpjwqd+`M__yZ|B%CA zwh;CPA(3*TQ&n@bsNnyglKN&!iD3kWAr-pRp$#|D%P3aOyd zI>;vlFrv$c{R%%)GRl_z7o?9^OE8Q#6b}oC-O$ucP~6Zc%Eft<%_wX&#p43TH)#gh#y71SqL~r8n6<=x zr1=9rSdR*!{V%wWrlF87f>#HlSvAaR@g6U(a~ny@_IRCKioQ&`^O`5(x?_XdxMPd= ze{1Ck12lie@2ZX*$Lq-2h_i9tW|uJOwfBs2BX^3VCYW!?UHqdD{$!d9-y-*=N;emY zO^)GC)!WlH&OL2tgk3;n!}x|#>6YGkLgALrnMwYZ)RyVoC8il*z988SS&XdpbQ;@F zcf4j*!&H-K;TfJ|$*aO}PAeS2;uje=Hpw#H1DIr)?tL`T-PvKKVzOt2?ch<}{!N*( zjq&uX7@=`ZvkkK)^TOYSep_;=+m+GMU*?(NOmzt`S4(pVGG~)%A8){$sbaDISC{{L zIh29^Tt+FokD9UaH%Va6$Xg;GE8?EtSR{<*;C2Zyl#OoW zZknhSfZPD)VT%Hg2LemGBUA_;L3?j4<^M6EF!gN18G?+xMV9C>e%s>7UG)q@o#;lu z{J%m1Fu$jsVrU)h{GTBFS8Too2>-XmzfCzuYB?d%4i#gyj1ZImI_g9_bIyc?eg&E`^P@Efp8Ipiwc zEg0l2vow)r(-$^vYY#cwqw6gbbS{rHe=hK~b1pUhsd8t;7Nres=*y;9rnfKpIf5aF z=s|CvzcGNoiX}sxY8U^BAMXhGoYiqU^hoF~NPg;h;iEQfJ9I}FwwCZ0TGv6<+H8Ci z`~TGSol#9TUAqq=s8mrvI!Kk?q&Jb?rPqKEdKC!0iAXP@Lx6~M=^g2v&_M_-ARvSm zs&o(}C;GhS``+{8WKH($Ywv6CHET`Q-1o|wncZ+`;~$f=k~S`()54Y(S#(mRw~{=v zq~mAE;ik5kf-!;vPJET=L^h9W`Dj+m9PWdZWj`7n@AcpnE?C7*aKMke!Vqh_?Zbfx{@YPhf@6h@@$8luG`qQ+l)rZEn=#k&i zSK}kUZEwAAy@z%zkawAvz>hbOrR`|d+oK5oTl39e+bw?>Uve${-9RsnvTY^PX@$B*Dz>H^h8Ko^oen!=UuNg-NNpjj}6uLUSF({Gt-TnAvAF zrL^^yDE@5jY%cNa%HfhsCEKmYr^qMV!H^u86~xrR+rbN(z9|o0eP=_`c&p9bRk4ud+O%4NYLF|@1&JRgA6(vpCdjzmNU4>$#P4AhG-)tYC6=j`0SkAN zb}35z3$vcj%ISbH|V5R{dx1C8(LyiLu z+@p9IXfo08!9fg;SG=jtnb|ai0kP_%5RCFKfeZuY>@cJNjAFo7Ir$$pw*V$f?w>$! z+FA36h79#-7nN4^X>ObFghPKEnP=iJP67On{#Q0dS;nKkz^YI0z^mnD79$i&VetVk$* zWgdzvPm2*|m3x}l%cVsUgzFaT7QLf>rpSXlT%pgdeK~#|P(ao83;Uz_fllbiW zHK7QRI$cERyU>k;?E|#d2`VeQD_Q;PkX|y1%-TO~v}@Y-CVdoR;^aZA3REVda3Kc2 z6D*-x)jxC{tOA#RTMU;_AEHN8i^G0$7`|u8J^WevQomESG+Bo;nE2SyAPq%`B3x^7 zx#so>EgC*0^a*A8YS5y;DDF1x6mCv^#(_G=^Y0ibdh4JV6lTfNXF$;et1;x;Z&m9_ zwyb`;&^S^9{%E(1pU!Oh+*qZKEV(jb?PoJYgXs{q%;(|(ui11&cxe10n=NG5>?7UI zeYw=ABabPJx0dH}uxmhaD&5=%m;2B!YJHo-QI!y3A+RiU6H0GyK&J1QdlkJ{5?t0{ z7+kb)(`eze8NX_OYv5iDQ7s3M9w<)%maaOuaMB6X!i$L1sEz$+u2ST^?zq$@WX2%s!Q8@6e?se>1 z;o~O{QIG4A5<{pX2nS(Q)U?6`)N0P4S~lYF2YqsDmf;Vqp1UZk>F)QyXA|OtlPK$o zemSefSr2J=J6;BmRua1lChf_|!X}c{v- z^=-xaxh93c8Lo7^sbIEE*A`RBpTWq&OX|yJ+c|{|f@L$WXJY!LBl8s7tjOzn2E&)Rr zOZgk-iD9uNYcfK`|3owWjfQD_nLqrA&pPAu)Uih*H&m?gEzrUv-h!{vJli1F`-)}$ z3I|^1W^(R)KDr|7bDMCpB?Ou$y;-yBdb@4WbXx7JaW=QrwWTo?aDy)Ey;Q(i@F=<| z#Hnz?GOhZR9n+nKcV+y{=#i;q`4!!-Jd40@4-I$F?Y_`L`K-gR>9% z9dFfmjpp%%&pwcKd@g-fv4cbHFRROI~;1ccDZIkS}S^zBv;6|pTHfuwKj13_$C+zS4;#a&}Tp;rROLPosx z=JDqOdpL79;B%_f4EAbSKbBRSPW-?OG@tu3M@MT1iud?0TJvh=Vv^jmUdqQ9g*OMZ z!s6AxF9YT_@#X+-z{~Ut+@`IdIJQF%(d~e>8{$Ai#x@1W8684ldI#GfRk@(^!bf#KpsPBJXWN7S9 zSZJ8Lj|;3$XG`WvwvJ{l=L4jmr0rUL3Ktdpyr<5VT?7*{m=Ow|@fjO)LKwL$*1XQT z%Pm4&mF3<}LmFoOW(F8}9T|~b!d-1S-yX3%WV*)tA-!#myRE}W9D1~!|C?rUIOXCU z;t*QnCMO}>0AxFujp;CHH01PlnB|GzpN{!W>E{!viZbq0lWS{m&d}UwJJWx>m`ipe zSSQ1IVP_wrc<5|6);g!5i#ee_r=juk_YvuB7wIiH_4Y>1?~~8w^&>R?s^g8)9q)ww zjZ#*);No3U@LEGtNZ|ombN-#;lFYPd&eR3?C6S#F(f0S}Ed@TJN36r92YonDv>I){ z0&PDhZNCt0KMO{2LEC8b>udCLYVyM<-37CB_FRp=f1KcLPs%O;2}oPj}fRv<_wvRyk8v zW;0f1a4WNEtM=&&i@6JnssENBvsqC4^q*!12er?E%;rJgzk$BbfWA*}bWQn~jk-0X zg_}#xn}t~$$qEga8aoP`;%1ssOu}a_5*JBJ2~}JklvXk{PEsCFE8b*Hby_!QQMwQp z1ohg>iJQvW35hSM*^TZvOF;E^oQa_tQ;5U~?{A3vP?v)GN8&dhCOY%$aiKyeXOVx! za&bKe^si6=HN{Ryf37Ej9u(G#|CjiGC@B-Wpr-#37bH*zoe$(tjcMc9iF7!k4Rk>V z9iKwHgbskxr;OF@DE}%5NvI8o9B!;=$NyJBaAC~CY8dbM^#2$!iXbNFKU@UC|4mW< z$4KyR9FI8XH{+xUJdixg%php#)6CN#x1Mc@d<6g_(JeS}+dS`?0+l#|cMB4+~Bf4hf&u_GmN{1&>UhuWrY$C0~(V(Nb1AMtk!-<`W&rpsq^ZCyY6Q&+GlJAX{PHcaOAwOu?PYv8OUUpC%RJ;#~U znjflB@F8#glv|Z?N?mB8HBp^*8YI>=aXNQ+>A;5a35ZPopvS4wSf@AY<9e4z_3{K$ z{Ae*lf&u+4@f|l}F4+Yxes26ogjWr(C&Mp>v`|?kCbekD`X?*;&G_kINoyvvAy z(~qmq4oAB}LYiglO}g0kL^eA|;vS8NIZ>KcTKS3uQj=C1*f+iw(P90rT>7z#D1=si z&8@e677zXSP7Hm^Yq??_9x{6L<>jf@Z!JEuI}wZJ{A>=vV&3fvkTalU%w!_XFwGEW z)1&SC-JPx7&#qT+SxS0sMK%VWksTvqQY+kjpGd#GN%C;+lh8RQEJ>n_;DvpTg8 zQgP4u<_Z-X0STSB>J-63wqwueSQ8x9cSr`=*F{xnq)x-tzVr9d(t8ZXvG=k35>=$H zKjT-TKRt7QFKzW}Xa~sz&V*u_PAd%}i`U%Y$IYd1rATS=or1OFDavfoeF5bZSrY<* z0R|_ELgW#h^M3-BzlxCIp%4rx`8Af=s2;0VJW#fC1f@g&3OAVFQO>=Rr{KIL8pY+Mxz>+b*f1{rb% zhW!7vJPISAV75%e3fs3ylp?4LmzB0m-xZtW# zT9btp5=`4Brphi7B>(Y6{6Wt#Mgi;pHR|9ZU<~YG6;^*ub@Bg8P8Jvv#-u6y9b#~J zPsNpqpnInw!mnY>+13`ZXOn7ZD=s@h+G#C{YUcw&DDS#D4Y8M3p_D8eey{0BJQ5On z5IrAL$m|}3m~Y4@%|mI`b7;BB-whyoeNBFe6 z@day@O%pNdwLncCrqcY0X`Z(f6*QfoeC#WUCb$>u(A z$nKDzM@CrbU@s?^UDR@wr=JC;S8NZcC@29)9iSX6v>p@zM}j1SDR`h!^on|oN3O%g zF)SPg+O;NJ^V>xcOC%Dt7I`yx?g+JmH$<~WDJEPdN>lzZbA}C}`9(3pZyNNbaAVRr z7GF(8^bRc4tu54z9{aRCsp?<7c5J5V3YMC4kzf9`I|ud(&~c2IU-P=X)!+gQ(pmw0 zqJ)6;E3sYMH*3GI%B2bDVMpi}fuvpA$b~u*L84+);rX(bxp9U}Sp-4Z>O^>?O^EXXFYwJ0?IY->?)9*fN))Bcwro7>&k zaB50l4$a!e3${T~zl;=QPRK2HD1WZ9P`?0iamIN^vM8?LJKw=DN>Ds%fU zp<^oaV*_8aI496DMJGG;KPmU$d3;PM$e}@Qh_bN-Z*83BiXqlE^fmwehwR-64coS; z*yylsj^yw#r6!O2Nxss#TgTlA40tn7x72mAa2Gvz!E5Y40=%)4haUeL)vYq$*cCA3 zeRob{xZNy1I;(3YH9SjM#pCW3Q=Vc5J$Z=c2e?h0-v@l%Y1NqLZgquweX7C-K}+`T z0iL1!bE-sk{3EM4K~jqIWUX`sdw2lw)PFNtU(W+UfV@5a)~avk6aY84S4Nc*2wJ>H z0+@uKQvs^s=L7&PxKN3c?0ilY4#2aO93-VS|Dj3@fZw_W;@-)EdqrY^&yLAAjPfsG z9A)zDJP`vXryD;zY0k_2FB1nqjByH;?76q{OnYTjZKM3bRg?fjRMwPN8b&#S3l;2P zw^mJKIu3wft90QW(>7sur zkI&BpT8tALWz~YxiinY~X$`wSzmL9`PF9m2M0QZV`})mC=0Nze@zqdepxPC6MEFmE zaLg6!&w9r&pPb8r(U1eqG?R2YD-|d9{2VQPr01`*l|-MmgFT1@WPam}Cna|y_nh|m z(a}SkE~NF`wjWDy?(DYrz_#7Mwk1n2{mi!cfE{4i4lrd0VE5*&7yJ8_sT1>-sY9TP zM}vPg?y{Me2XCud7=Bida1JK&Xi{Tr-`e-f`@Sd}$|!i;cJtAP(p5mI9c?~{tCj>j*4vfx zQhQZmLZO$q1~K|Dr5+1+y_YAdWt;l63)wm+9EzTVO8rq3<+}U=d}Rrhp{(i3cnSTP z8XnFCDJb=VaQ6xuNg(PCH@iVik`0#)*6D1EF%s-O{y}nV&m!skcTMJFSS$5Bp@o@=-IH;pR{1qb)w=r=Od5($o^sFk z?yH=8>P5q(2BjwG{vmFe)cqlJ?5jp9xkh{L&Xi=jUOY2SO&|V_^>`14!-Fs8Qxx{R zjqxFZR#RZe{j4)cKCkt)7sWbVr0BT*k1P=2?x9{lF~2XD%%J5pd)tpP|EhpP%lSlP z(uU}yLfDKOF=XLspa^|vFm1>?o3FH^Ep4um9NL3QkKzNp=ZLkBG^Zvb-^dVGsje3+ z;J1@nQ2cn3>+4WMtUP4dr37GW4#*W`xM;Z~;O#dCmoZ*MUO&jWE)UQnbAL4Bqq4|} z`%$q!nB;>u)}BJT^pTIp%7Asp&5)l~(s@xmg{(N;eVD)XtG>oJKi%%w;`N2D?vMo+?a&; zb!~%K~2MFLD zWExJgtVb}Dy?^nv<%jXzkHZd)TyTrSxAs0KGDF4&^?xVa< zYX#-WS8~p4f=m6{F?xQZ!u7M}shy+f{QW7H+vweq&BLIm%ay~R0pRhXr#^`d%7Us? z^wjXuOkX}tX4WvRDJuV4)QebN(O%Wd;vt=j#jSt?Yfe0A2M%Y?Bq#NS6AXuDrto{RXDL2_q%AbZmP1?&A9ldn- zvbKrTxqvf2=cXDf$rp6wPNN)4Hd%w=?i@HNb+SIQi2fAxV67(v&#x z2QAAwUl?g=I=k1~+^l4F{^D6ab9FF36PX}({ca|0=7`3lfh&p|m4r%3JN#_pp?h<6 z5q?~T++xx{AzIz0Ucq|XH~k3D0UCZ0OPq$qU##ghGbZG<$$j6~IXVBX7ghHjT=REE zVXsVesxq+8vHTPSruedBW?T_7{onH~qXL z9Gi-<;{$yR-ha6aeRt>|aZsgtPeI#}bnpfIV}i!8d3vJUY{5uj^J*R!UF#(&nfn}O zmS_38dLUh`MKNzCXr&TbYVG5yPYMjnt*Dx7lD;;~bN%%I^ z{@IFpkjU zq&_wBgaE5DcZ{ddrf%p#EWbAveUGpv1AtvKW9&lw6WnhQnKb0;K5$->5$+pb4unoqXAqw>HrajeN8;*F5c+-)KKG~yJ0vs9mF8) zHjzq{(_lTdPxKu~U!+90=`2T#D-bixWlN~>5fLgS7KQeZv|D%@w4p2ez+WJ0O5Ku3 z%}7m<#M_#eXe%VA8{%D+dyfNCVt$`e7w;x zA*M_Xuha2Pl-l@5EZ_1?drvll-7t#>)H#j6rTn|aU7IDaeON;C6XRs^v!T%qp%YfW z$oA^I=cMO!Nt44O8%ihH4bn8>C`tJc*-OKx*nhC+qsS z5$I;;$veL|Ne%OFD|2;IK56Z;E38LJ#KUYGo+o721_7d!CqWD{DXT-d)4!x3-1s&v z6)xbH4L1_QbRO?%o(~SQdl)$Sk9ED`Npad>MR4>9JoiZtP@FE==Os=MJaHnpaZCI<9IzpG^5{AzP@$7WCaQQon6)cOrijp2z?2*_T26_9rQY#Sy1HB% zMy26L9$7g|&xXm4-^jhJ(G(u7`EGv5bD0r2TCkyVyix4?gUc_pUEQ3?E!k)2W`pUZ z)K`FtxSe4&$)b>u(bJ}ApYg#EKPuz7sN6(~+6G69tnjEeWs1b%chcDVJ{dP7VVhl> z+9&t@vLuzv?~A@iob0vF zOY_p)glMMO1Zh0Yk`c_+4KMR>T*eZunmou5_(7xsK@zDVP{e|Y_Aoxo0d~r+H~Mo% zBp+oTAMVooM7_hb$)9mKkLTa1i1YxC`mo*&*O>k|_qS=^4zQSSJ~v`aS{gwSu+)d^H$yKUJUYNspYryWDSOzCOBLEIjuW)dG0 zLO%TH5xs|5`4*mY&Ni(yxlosjxUWs8If=L~w_N_1O0nZL@9?`^gJ-zO1pj{Y5bsfJ zR7|v*vZ~7H(8w_73l8@3FJ+}p_KpsFJG&@q3M$I%%q)nhk%{rr!XiRKR9p=G^gglj zpR$zQL;=2k7f?WxOPes(J)B46jOxt~lk(+bNjNpz??)#yt0i%0v=Tt-tVfeLwL0&G z$B=UB=c~8irIr2vYSChaMG#Q)JB~F!N-0*)=69NCe}hlXZQNuvo8?6l+e8vN4@kY);1BmIQ{4UmKvwi5LgRU=-^Q$s_XEjC-Fr(aOuQ&d)&d)h6 z(V_#6J~`dLAO2C{=a?sN``L(-Tl@J$0Da)uu$@KV`M3`j$z=OuBy`d$$go;C+_Pce>4(6zUa9d0|8CFs_Z&oXLIVN&nfN1WZ{yj1Hn*@+#Q zKqKM4JJy1qQDxTVzBkeF0Q~9pY}75}_MG=|U@mzAk#8>96{B{7ncoT73%x?4XdRmo z{V#e&Ch;a-+P}MKJ^#sKG0uPYDMjkksmcZUwd&79>Tj#W)CkMg-dnai(6t_$pEBOj zO*4)fPN+lY8H-P5-vHCItTIZA&|)o)5dSseEk_#**irrYoeZ~y;I#mHRxEp+*xJP( zc?4}?;_?YeY3Y2@+fAu5(ONP1%egzkxgX}-TkH&*bMD)6?n!sHX-qe+tm7IyspyWW z=pU)*EvtYnR`l&w^kh}AJXB8^&p(XrCYA{F-iBCpvB;bnfkVZ%vd;>@p_IuGCb5_T zu?V180#YpWsaSN1Sh%iOJX|bHP%O4yEYed9eA@CJza=WRrQhFipsBa!Qp1ki)<)RY zj%dr8XUmpu%Z9li6MRiM@zC<~N8dPG0wATGi>7h5FDqXXj!|N`QKo`X>VQ#}jZqGZ zQF2j*hNDV+{KCiag%6br5eEyQ(1mcMXlROPI9xQWUNrKw`E5`zS1J0 zV$84CYc%ydlwB))CIgK)Q)!G?UamUk`OQ%P!!2Em(7A0#w`kC9!1g8YrzP|e%9z5X z1k^vNwL|ZgCT%;7Fuz(2F}zlS(ug0dp3VWw?r0|k?{B8loiwz+s2*)QsSSL@NTHHM zMVUnFM-qOYRF+-umC%eVQ^P9>kSs4jH(y*2^H{eeR}Y7CxA1-+Nlq`0Ss$%r9NV#^ z`M}cE<6PYxyZ7vnPsWgJ1*3TGg;<~{nA$hW@JcjyyF4(P{=}2)-079BqyKnWi_mLi zLt^?j4-*9^2W*#Omxh#!Z^7d7N~rtLVowmn^_xqp5_pHQBcFIL_E#s{r&aui9Uq+C zxcZ4;z5DiDy_&H6eP=Eh4{Uwkk*miQmb~xEH9!ZO-gn^YGl$jfyKoIk!%p^{D!PMV zG5c;6{aCOO8vBY~Sy&m3a|P@+>y<+1!S{4=})tLJ;(!7k*jVZuVq6te2+&!Jn6@wn+llS)r9)0K6@}9Hvvjs9< ztT7*Eu|1%!xmRER&jph75W>brUB~EI!$9=o zg~94YttBJ-V5g#1?e7cLYlWNylZys`)N_`kqYs1DeCH^lpUDS3ihF(l88Rx9!sko) zbQOey$eD$J2T)(XzIN`R8k>AVQ1`Xhc{q!}P6c<#l%&auTd{^zu3|o)K!_Ze`EArr z;+{45)t7T-9OAnkiT%qW#ukbH^*M<_E%jKv2Qz5QIe zVO9i7N#ihE?GrXq`1+j!H}eCQ0-E#;Ye@REfrtL~?$eW2!*AK|KX_BE_Q@ZG@?sw% z62y~GILWd>RMr-c;LI0Aq*<$9yxsNoc#sW@JA{nCs{$OI^4{YF>!TrqGj_r zSK-YKWG4M>jsp6cy{jTGNxVq&h2m)PU#0#cY46b)mtt f7WG97r8^C<#}#z-`S23!^JU{=fAN_v-4v@4O diff --git a/src/librustdoc/html/static/SourceSerifPro-It.ttf.woff b/src/librustdoc/html/static/SourceSerifPro-It.ttf.woff deleted file mode 100644 index a287bbe6ed3f871376686682bb455d71a13882b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36200 zcmZ6wb9ATA&oEruw#}_=+qP}n?bf!jwf(8FwQX!|n{U6r`}yn5xiWK-Omby1narFs z9tz^(K)^sh5Nip9_|pM1w*SyD|8f5RAS|RJ1_WgH@xvGY56wvRxSl7>3Jiib`Pzzfx^B)~DARyH- zAfP->T+cXUOEV+WA6?BKJ@)?)wH!pl@`w4uOZcIG#sZN+bwD9o+PQiH0fEr{*n|FY zJLk4WXUx{YnunuEzyYXXOOif9n1E&~d(XcQ z;8W;iq7<0mf90O|%Ib)#mH?eW!y>9dCI#N)Yd7%=Qtjw!%)oleLzrm-jcTV0V*3Ek z2_yUj8^{wlcEP2cR0=Kp_F6UGZlj}>FYlbk!?wn5qxF9uyUotDd*k#4Vehfbyjx{H zx7(h(MmK-T=Gqs18^F6A0=+|LR0}I&@a3z?dmZPozW8(Fiqp;G^$a=ZD8O;1qL@cJ zl_A>A=xQQMfo&Y!vbEEoYSTCs;#~DC?zXo>>Oe5_yaa7|vSmNzyn~8f7WbH=-s989 zK2(|>)b1npsY|-L*Bl~q(d>5Py*j-&UAAfPwMX8>Hk?Mcf#y;z)|IiK`+H3PDSf@z znlR78FL>%R`kxmnr-$p)!HJaaYWg?I^^(ABTR=g8R5POcOLwo6Q9f!>9_8$NNqh8P zzrSI}(_qg{`jphpKUmPaSe8^lv zgd$&Gn;anm`efC9X(aDArOI;J+url8c|+Yr(YVxJSJw0ss> zJ$09E#8*GkNVug8GNDmhiW1`_>_I5Ha9;-?I#kxktcd!E>uqw*(VDGmWc{O{{SN5$ zi5e%8QG#BFc)#&Wfnma8b8j-=nA%Q8ojPUZLF{&;dumP}O&`5IGtM`PG$+}RTa-1` z$-A4P708hF$38^6G)4WJso9GU$o=lKW?i?==*?9%HKD!0Tbpa0n^;A_+!f@jmP;t39K$Tnu9MRhP`VcA^YH|~ z-lgt}jlXd_ka@CfwfnF*kmTgM*y%Uxsv>+VK=l?ni3G;N#+IKVzzWtbIW>AL`ZCL# z8kS8l;dW+%Z?TMRR&>F~Y2Z*-5y0=Zb@660&>3+KdTL_w-B!+ysId5m_)s_Zv9jQ+ zyL77(59=@7!s`L2v3~m1t?5sFN<*z#yk=*=V(V;f>YZ{J@Wu~6p~r|W zRx0r-l;T2)T^{Mb!8_g|Y5z-AW|Py+nJ@FYjRdF&vCE z<;=P{)qhssoqF%Pc+f3;y6pJb559@!1KXPeeT|5pR1yS!K$eyTxkWmGIv=dr=}>UFhSjUFd1lrt;^8wgPo zOA-&ll0zWa2Tl;~UPP#As+ygvHiuV@W~!nT+bpV?I4al(UNF?eg}$ zv6u*`M#EbaDYUu2NHXe;iMeNmCP|bjD`flTa&b=81!mWp3b!)f~SUb*qmdM^hHHVH*t$4&7sB61?$>UYolNN z-ZEMp=f(QxfAmjt_)nYsYYj56{N}7{fX!VL=kCrzdd|AG&$I8SdmD+O6mzB@b`xMK z6P&5a8mT*d-`F^?ifKCvc*iG1^2!sVXwsd}F^0;el`2&--&hNXA5SDH3qVD%#toNo zGKo-)h2=m{%~7%(lSi?FMFxWKV@Okc5B_i-S_<)q{}MNn{v#WuEFV!>URlwqUD@Pq zT`+7NG-eu=g>T-*Wf+%nf7Iw@tq%qc83sv?Fpl9mpfabjrLv(iv(UFNxiH`Kw`stI zv#1fi$;wt7*ND`vdddQJ9i=tt(jj7_!M!8bq-|B?shlH~BX`A{w7X%OcUyd$J&}T$ zm08Ple3Ug2o0OEqMO;1F7ITg3X#P56e;-(eUs^FQt=WQ%Hbv74y%2A_n1rTQyRwY^ ztdJk)2&v2?(j)WpsGiG$Aq$cMNmS8NaiBmmy}eRIcZJygj$=<6!AUxM+q`v|oWU@f z=kMnQ5zl&DQxpDP$hYw3?8Y7AUuwKPxB$|t1EhVF>xh?Rd9KOtxB;XUjw?iy%bT)Na`qW+)KM7nzp;TupS&<8L!VoR{9f@8hq!pvjgAvU7p<(n;w=PwH~V;Ck1CvV@OBvc1Yg+KklcY z45x8dr;&N5h*2yRawU=MUVSM*WejHHK)W$=@(Eq`;`#GjOByDW$=TK|cc&pR@$Y+}6nQ`4?V8oGzi~3|-{Ax_qWp01tD8%hF>XG>in$#%|atTIJ!GEQGVnZoO=f`wdfq+}Rhs7Jt2tl%he(Iw?D4x|hBt zc?4U|9M!0L*(!wHy3^e{9^r)Oa;;*ZmL)UxBr>m^*LvTwY#sJgSf(on;GLPPF6 zTvMeQeED8-c=W4$cuv;!_+*5M&xC)tHI^15pPV?!k<>|9x$J;$toMT39o46vZ#~a; zrWJFe>T>GI{=Hr#cR-%hqVm4)_1xTpr(A1E--ZliLUPUYTB zyo3F6?f;IeR=Y2YjVB*B!1ku0Ju63M_7we*x=S`-Ytx3GkMLmRuIfcXn7E(%0lgJ^ z=I>&W1|A6m8fr;S5|vx}vSdUFLs9xkGGCKkb9$3U!*ySzBTWwU@j#d(bxeJ52xr{HUS&Ij zebmMtzb9E;s+#3iVn_ z);N|Kz*!Pd+C?@dDP^2!UBYxK=$#~F%9<&Blw@YgwJI5*nEIQ6JE!V5ijK45tN`$<^`;GN!8k%EnZs{T{U7| zZL56yIqh!w*8W+l2chRrPt{kj|5oq7H+KSuBHu5jdd3XSQOFH&jnJep?FfXhrtqq8 zi|}WOzoV<80Lx{|*OP&hkqpvhK6hq!K6inqk8eU&^eH*7O6BC`q8ckg?zHLR>=R&b z8JS|UxjP%lXzP}i+I3I6Aa_BZKYr0=aT<|~(E>{i1S{t!O%J(m9HhoEzc6q+WA}%> z_B)(*Jnemd`8T4`kxmT3u;g)Nqz`FYsfR6@O|2re23{Jqt=h0OP-mr1LYVWo#QY?o zg+5b&W*GgTwS`<8f@XU4$RCxIBN?4PlxbtnkOsdkI&@K3v%)WQEbBU-TVvb)39LkMvQ-b8-UTNwii3g8Ve+zO1WQNx zj^E(N0WHJ%-WDUbS#5P5epZL7X(kIJ2RC%%@H54(4H<7n4P$)d*=R4RHo1%$k#~|9 zJ&OgTH>1z3{^>2g_egj=Jowzw2zQXyPDSRUM$KWCrW*mTUiXDF$kJPk5TQj4>@3g{ zkgp)zuh~IJ#&i6_v9{0;g(ioG5f!Ji*plH&@hDYd5-Xb@!R2vD>PVW}*2-f}Z})a& z!ufT?TWf$){y#>vZvgH0#s%)jEg1uYrn=^-m3xO@*$rWQ`um<0@-h?!ie@E9eXwTDZOAWB+y_wwdqKRavlOl^BL6pQerv zu!W2=f1gG3&~Ibr?zNAf0sh^}Xt&%R=%Qp*<<&!V){Sh%f(dyAsX=W6(S}<)-ZHuF zn-zB=>L++(R9Fks8&xS_mMEBj+c=c2vw^g!zVnB8FY-dBnB+XTW!A-=_q0mrnQXhr zwc+%vpK))fX<&3C{pxF~h%1zu_2#i`_^mT4yjRIHBq-kOcm0GoyHXh5SrHxw)@skFyB|Q$xm~Hm0L-OFujJSWehi zo+@6gv+fi)gHvF%PM8pJxvGGY7@P>6subF}WSOwgN3GXz<@)sj>=W~FbYr;i3FMce z5kxebvRKOBt>&H7ZB^2wbv>@_^@5UNJVNob@O$OirazH7g=;eu?%=e|xiw(qrT_La z#NQ}1U%>Md=wn*H;Vk@M7o8SSCee^#DO4@faKWjfEU?^9!?B-=zau*A)#xbI#NCCc zKVu096YX8}e4Ha=t;d)#H##C*g(4jGReq0fC2hR%YHcSqEA>^ae}R$<60$5qaX=AK z>DWN?B}T$E#y6VG+)5ho)(Z)gWN}tzsCN^9n_FAkc8AJJ(XUgPTBHT>&lC{?`xSY- zTiuZ#MD*45ly)UGkp+X6tY%=P5UkrW(&uk=?F-TYPG;7RNcG=<2YZ1AH&qH#N8~_B3{B zykYxXNA7o9U_iEGJPmXi(D-RJ@N@qX9a$ECXXlBQh~hDcfBnVA?@c0yRM)kju37zVj5|>*QEJoA(h9nc6Jz;f{wt({~m=;(uyH?Nmj5 zck@nX3Dk1<4&nu^)*?|e*&@2Mp`$RqpOs0k!FLLa z36opKa;Ah?4_+p490r$ZBAS_oPt!hK{X1GK7otAdtBb2PyM2ROtn|5KQ55h_{eXE# z5d(>VKMH8>8c zQZ&UbNmOiC0TX)HofxW>VZOPA_vC*1HMeJs+8LM(y{bhOjCnpMCuOVa^2qyV_Aw1E zq^;TUm9~EQA04?!K@9_67i_hLC^b%voJei}EuLLXI&`7W>Q24Oyj^5Sar@mkk}>X} z2Umm)?i{K!_?d*FP`jd0*>5R-5<-p7tlR{DT>OMqWAySeQ$$WeZ6oBtE5`4}aM$yp z61Q_BKr`xARlgzq3GpZywCWeabV)e#T}xC2qX0*j15r+;c{p0XU?>nig- zU6bQAfC!)$5mVxi2*fmnhCl(k-5IZy z{?X-(RoL8O#nnqBw9YPx@#i_eT{0wh)CYtrE0Yi1X{3$RLh;c1m-W+Ou~my5>*Ddf zRD>9%THje#r53ajt}Z7-Jh1j7>%FY#ZRNwo&HV1dy&**;xeSckbpUSqK&`UhbNozX zzP3$=`Y1c4WHuhxp^HN^k6P20*Ko|@QX{T1MPGi5OIays>{uCjd(!3LY7g+3+eU#u z*!;{jp-ppkk}XsgH6fH>d2b{Uz7I*qLqC=QsQP57yV!TipEK7ooX7=hpQ~E7OBZqK z(50#Dv)hgCPOgE>m!Se$tH)?(X+jhDB2-{=a3IPsj4((%PcLHdkJO7dP1T4NSgZPc zGj!CjGtGwNHXWZlD<$O0QmO%e4v=Jx+YB7bGr*==u<%ifa#@<_qWv>-6y`ihc2Z6W zkeplNwRNk(-7Blus4`;sXKJ3Bx9#Q06wu?-piqiM(C>tV`xwwYl!dlUm}yktHMbgJ zVM2Y34WX5+`){wOrW{oX!ltax83f3`Vx#m|KEvMN5= z(Z5!OrLeIwfYh#ew8!nDi@L7Q?YlyrS6(nN7imdx|(2cJ5sy~oDmezCj z26lpo-t`Svz=&ZePG+R4(Kjiud~9vMqye{3e$=1U`CvzZ(-sOSPMQkq3^rH(XKrcX z#7baDMf-aSByTGa(g*md1aE++Jd5O9d%H{(t_p4vcqn2~qv9cl`1pt(z+N-)$9-dN z$a$nDyNKRe?$h#|znCV011WyImjgwG6rG9f9j150FEboD8-9(``%a7pV#02n&Ac`O zm&nR-qvS*}yPe-2ho?V@C-JIibh1HJV=5PieUn&ITFowb=SbcdT$8oD#Rg1;+0E_q za^ltsfBFHz5yP#c%t%9C&n1?Zr>2h@@^}U4qgQ_V9QWpKWMK;r!kl?&gre^{W(tjB z9_(O8K^ESHbR_^f1Mbd!Bl7+z{}&r_K<0LK6g*>kI7YFE%&nq?Fx6jX(y>PNj=Glb zyVs8a*O|lUAxm#pasmGO_r*LvP*3h2urWztKS*RsC~-90>O;0z7o;5z**@iMf($oY z78i^rbY@I)LoJPwBNT$p)-ZkJ>pNNVyQAMsn-(6BdBJ?FK>+>bb<%4azh`C5Yf1yX zX@QcJ;m^5{q11K%CC~{-qu${!uU?W2xmW9F51+@B5u2T4T5LXUg>=3YAsfslZu7h? zV+`(vh@wK}atmJu0_Qga>>07>q^w8o0m=mP^SZ=t{fytr4cc?HpFSJhsW8#Q)=HJs;!3tn6vAOA zitKAO>HrW3^e?)9QYFDFsw3mnHF<4hirge*e6`cEB|KGa z)drxgvkkE^ZwAst{sj+mydf}Qn!(h%T(ITRbkl4aHKkPfS1CAATSq%{@V8Y5;`&Bw z%j;#YgQofzg@>Q9kR1<9-=!o=YORu#ixeq_Mdh0ngwMH8aZuhH0 zS{Qp<^9Y(vdxQ0?7Pf3~Mbs>w#&SXaypwd?=eXumn#lfD<}lT0JR0VQf?#5uTy6Wb zc(CY84W5^00ogv zUV${@!fJO2N-3cWr%Z)j((R$JD5vi?qMyEv&#HS0J>|8k23nE? zS8fZ0XQhheS@g|klA_Gf(RwjP(90@^Z24a2IDP8<#gRi-oC;vwdbz3UI6jmi-f53u z_k*fSfr%J4T&h<v`#bdVpXsKF;kX&=5SoZOy6{>c=YvFW#;#MsFsWy+kOt!*H24 zf|VDm@wXdQX~6w3_o%J;BQ}wZ?Pf~ysf@@-7P}

0@P-(w2RJ5G`V3M6HgTDVY{pw?1VyTwO=xMnaVVUPRQ~D3rzpD_j;LxXf?^p z*^ziF@e`lDpCwvWRu2l#la}X8xiWi6Ea0NA86-)hri>}TvTy!}6;Jq}KEvX2nQ1TD zliq)LZW!1^yL)03s91S~-9wi6`%PQq>LUifR-4<=(qd4ng)0+~_5AY(4;wg#R9Tr@ zw5+2smz&8K^6y{C6Nh#1n4Ioz(yT<1xBAVU$`4M@^&StZ3*|`tK0gV@sL72ZGlvGm z4o?a;`4Yg043*uJL`-?mS~eR?Aj;)`eS#j3Xz zBz8&?-erd&AE0Db+VsMCWuUor1#ZfCyZPce3uG4WbCAR*1<`1TPMs1ds6Ydi-%$en z^Jc5#u;#&eBvE`Rp*b&f$&RR*}S;?rNSNuq)0ny&j38NgL z3z_Po`K-yt$R0ZlS%FvU(S3av#l38Zb3xd7>98xpA%370nwl#|#?cI=cIH-n74q(= z#|9+Bk?v603guPvH&ligbw%FyVQJ(CBHRD{?hWZyA`K{p#@~tAlnQtC#R5cgy86Q2 zkx8AuFdrD9EZ%}RJ52edlOQH}rqUK2c_);Oy*GR-G$9)vks5}@F^Un8-E(qSUx5Q; zr!8`@p`Y;RVmAH_j`ot-ieH7slYVFXirEB@C;pDAhx5Y96aMll4BUjhUf%Mcz9Zu0 zUpJUaAW|5Fjp12(2^ejU9SNZ3Z*#{e%N+qAs{X}a?yY=9{YQu*3s6>2>DDMn{#5sv zO^a#srlFNT#risI_?;Z})p$dB&*jz;BxbkR1ujmUOpcWsmyBW+(lzZ83Pd)=k(%Sm zS|ntRQ&L=8e5tamfaBWGtY_T4+Lt?0`)}I~CEnyYWghJ`92f16HCZSdE37=f|BRx( zcn^kG(&XIj&zi15^tCIo;EtL(LjtuLMDdP};5T8|;zj!M!=L^y1El_!0TFTWMCp?H zBk9D5$>#WsM9)bmcO#+E2_r2WARrkjd=Co`DoBB7ETW>tCm;!{R_ex` z*=eN6t*1toXC1ngI_dfA9qicoMKn?t^DSp-;AGgRar7O=;#TK+6Uv}Q%sh%@j~E$P zjP0|M5M?{udcSPn1P}R>y>2Sqv=>oh-pI9;DwjjMMIw6#t$;?`h!ju=kHx1NiPFd9 zVybFG-qzfBKe*Ws%#D8X>0+O^9Dsa4&DjrV2%m8L?R3Pn>ej_epnWK)2O9+YkP;TVG*bK3$QW8=)eoE`O2!k#XNBinie=}fOzXK%WkOCIqyF(#?n4DhW; zbKTgB=}s(CN~ugYoMHHzuZIlu`jhZ`MmgA!%lwlYWp4lN0%GnSG%qB5;MpZpPht&? z zW}vS5F!YXknh=$WZ@xPu z=#!Vu1RqHRuh1`iK>S~~OGKi0BFR?Z2y&vW1#m?y||{xnu4bxkq>D2rX_Q^GNIOSJ64g+d)Jbo8Qm@0@)M;sS5C;IVX7gTSMi>TXUh~55?L-ZTc z=4;~)n~fDRNYUFRSI1d)*-Ew^fAOpr$Ce?K$|j;USR=Y>J+imytrJIPSo8an-d6UVtP`KS78!&X+=?E?s{i`+;Rkay*_b2Ah{6#BH4=P z1+F97kqU_C1%piZ4)1{lK*|qj@_vgE1a<=nsxdf=ta5B4?JcW2z&Jg{uY}WT-*;no zsxl%D$x?BU@3}O=D_$cjFgQrH(WSt5MFM0y>8K8GsJ{vt|Gs zSU3(2LlUai*@hfw>16XMIkr@1F|a}ZF?u>}I5~&n?9(kic);Z#_YJ+sDE`r3ec-{v zhsy1v@O5N&7Zf!Ro6XL>ql2G&0|s==@xS=e-MO6pOk^|kga6IvfY?*jBiDoY*;0#< z#gBx=&$jurCR@?rGsaB^&Yy#T&6yDA82Ar{L8V4p)x)^lGDSQu#i_i1&o+FemWZ(u zPhQjNHtK*ya|jL_t=6NUsEba}aNOOZeq&HP7*SSODCrs77EmeowPx)~tc3g_){-V9 zTJaH<6-MJniQVirsEc1dCV`SyoW(U^kbFT*K;$Jnz==o1gjAB?c}3*S7JMHElBku3DKuw(2Nhb!kKTi+#XH<8UuVvNZJ<~feM zll1WCcc~f*yP7;wzQq1j%~E*){`p$Bx-d6#XrrJZ5wP{Dz!JA(>Hx^?J?sr07Ku_~ zNgOrv#1h~5&bgAv3pB9G0SqBFogciq^~8Ui|F=7RqwfojND|9-DRXdb+Tjd9{Bji% zYltlEGKg$+4+pEtv{Dt4S87vVGenzs2%IFT4dfEz>DK89qAB-oMw8g)a2`CY$@%S> z&>pcUGVrEkFmt;1H?v>}<5g;I05^!~@;YnhPCi~SixSU+%z$?4C)^ z`vE$E%UxPMaWCvwg8>*brB`**~%bZw6lz^?PzBRfx1q|9g-X5UznF{2Kt{f zmQ(($u-czv!7K9~=JUt;jCO{I>2+~-+fLXAc?Y2vNZiT#H?|khS54RCx%!v*voOeA zN2P3lTkq&mM(#tlxXkSJkYViz~M8hX8F6pwZ(bOjbu|*&JW4zD=KlX`pDVM zhG`rcoUs><$$vr1U>2f+tyX(zBEXjxc|M+%qy(ccC%S46H9IzbI`GAPWq)HfZlm(u z4!vi2kWq<2zhaMuVH?gOlm721-P`iHKJ~nv?I(HkHutH}M)@0=A)7yPm79X@XW=DF zu#RH60H32xDzn4i0Lo$;d#C%!u}eP}}4=XMk32=yskX9qVDRB}z7_F&jlF+EPQZT`&bRw0!+;Sdh6(-~t^~=2Md3bo#A~qzQL~IU-lb_qB$jIY-@yo~J znubIN?&d_xU>>g9($Qv3@FkaH`y2|cfgY|mfj$w??919c3Zi&K{Xns|fRAGA`#uig z+t0JAuBN5VacCc>xvD_Tc92cbi2@Mq6MCoBL2@apLY72Eyw*Hh=DZNDg7J90AMsp! zxB(DeCzfIhUNqb~z;=@si+Oz`{d_q#{yK1h^WN0g^KEx%jwKDnqFX(3^f3lNGg$4g@rQ(!3VhcA2(U`jZ11M2XoTf)F>Pt;xuKvT;dy=?KJWOFW>986u z$L5{A)SE__Jbs}l^BK2ragWBQP@P_fmk!e`N});n=r7_rYT&}QH_ex}v?%Qeh4ynS zBFr0sRNoQ9tS_^oTc6=4GlA(d=moapKV4JRz3b+CA@t9Y5H-?y1b4p_`?wv9H--hi zQfXn-q^t%B35s{SFW|t<`9yf)eQ^IG#c4KK_6TyOS)vToM^Bp{M-g_)C)U|iFtc{|9E4V+&Jk}{U-F4Y^ALd2$>UryhO}A=((4u zx;7U1nf4Ee|TDM^R z>2UlTXqMcPwIGJG`_)cRY_U69&I>Rcta1sCDU_^ z?ba{^l0BH5A!Yi;Nik9HGRkf^aLNpB5C*MYxvv5{SmAo+*w&M?=Ru4{KQS^Ko)p)U zD9A}9T?IuQVCqVvm4SILQ9NcvnTfk_hG?WOAhw@$9i0K!PAnRl5PwDLi}J9|_r$1PNJqqcqwqbB!ha~WL(*f5Ie`kTXs zd49r}R+yEGATN@F%* zg*9lG#=F}g@C{K`+`WmCCl7goOt1SV61|z+b`!d;CbVtjC7~RxKb42|$#UBJ`$2mNLk881@hQ>ne}6cFd-}Wn9>*aR<#U@1_Y{qwPUyWn3v;_G+EuLj zsXcqL>anfU1ogGw4;k{JF9SA1YhlU{gXp(GTajkpa2$M^Tko`7O$HZM8@)fADAsYw zGA3^dxa_%OM8|wP8j&^xSesmSbPx+%B7-H%9iL?x05ojp)4kUQG$l_G3RhfjWzV?F z&WV{vb|YdMe~JhfE1;f{LW*~zrW+;sZ{o&KnosP929iW27$ANne#3t3-9OTX{yuajr+#EbW}OoYW@fu z6E{{k#bfZCyA$5<3%I!x%2FlOmK>YVEg;=iV)wp#apu*wkq_7eyfv^jaEp_$Tjr55 zR0js4#ht+1;F^N-(c+N&_+;DBX-;cDC&e^#%V$U}+AJXopmketz;W1;Rb$@{OpHY(g3so^4^&oy}_C)wL-{BvzNz;#wmI<9+m5Kd5{W2wa>AjX2g_A49PN_m!FS@LabC`OAbttVN&Eq#1>YQe-j$MKZ zFonZN4VL?QQqyA3n8-6&sr*V>Z<=)Pqk67RF_IRh=#yMI#Qxi8unnLka-T3eyc@4n zdbRj)?B}4XwUxX~DUY%gRQ1_0bDFL(wf8I-F;SI-PR)-y!e}JLV@Fu@j_XyHx{e>v zL=@tqC?I&HH@8!$mNWm%4y0tmetI&4hkM)3Jp9+`Z$Y^JIZqGgU43s zp;6Kt=U5eZ2J8+1r>>QFxuxrEEP>@894F*n)>+(c`P?z0e5XuPvDx=*Lz^$d&hO?O zl;6eqI``%)p@XQ?1~2i#e+>|B^wcCAC;2gAXLR1GK!^T7<`ljptY4iiOo5skWh`JV z5*}2**J+Rb+2OYS+-TR!uV>OKEN8QC2MzdOl$}nZR*NN&m76yBcA!G09&d(GQ1F`8 zt8toaJ$|-HfgL(1{7cUh|2-uFPd)^3*iB7-h$DbjLkFmW>>mC|Ku$?%_+?6xx|p}q z%@MFaHnh`TWvGzvX#$+0dUm97tSxPgUF!%)@<#rli;_CNz}&M`l`XQR$F~)gvEZk- zbAH~=CZx!Rj9XJuygWTFz;Mtg3`Q@;!&}m6s4W^eal0!jO18tQbYaQS6_9O{-AV#- zld|+DDVJ$0RHuz-5X40aN*+*%itsbUM&>6h%r0hYR)v4p z>x;FVe65nM=$#bhW5O#-S$zD>kt36KE^Yk{h?u3kU+{KQ<>+SqrH(rD8S;5!dL;Pp z(1Sb8YYf(fvWv(g(V01HGx;E%-}dytwMf$)TXj9B{f4GJUyEQfX|}GlPS1)wR#GBT z_2mW51{KtY6m$%XBV2m`81Yx4f69ickT*I(q26rbvTk`p*ehgQm@ID-f1B{JB6kIg zW6?;j*iU;yo+YrhZh;{!e(oEcbj%U|LgTVp^uiJpZCLbLlrSm@*5$A(eazf}19kKk z96DTzh(6ZsVSgU?|fdhW4;Be8Y!Cv4N86s1c>#1eJ@=#s_wq|o(i90vvan>!J z6>m{43@;QQ_xtOvQ6JwLJm|o*jbSUx{&Cg@VR#+UWUFAMuI2jCMdPFe4(<`VG8ig2K;!SJJIuc^cnJnnY2*!kn9l% zXQOsQ)bi2f>D1G{>LO}$>?+}xdb%FZuito+=~GbZa7{xHK$kR_Uojs>vynRGf=Tj6 z!Y=LkecoELogw;c+#%yj`s9Zre(oH;KYVBV-oyk*@v8&`wxjbxSiUfCt8Cb^*QgJh zeYfqVlIWrd&I>Ek_-diQp7I?sQD{)tBkx?$O}`V3XM;)kPBpK90`HmM@M47pkaT&X zBlY+?z858fnXAj?poEe4q)S5cJWtsckzmIamN!3SaOmK80 z+sxm~GEcZgV{$Xwm;w3mk2hX-@*wCy#90txED?-ag#Y0a{{fciy4P?UT6OVuvt^(7 z=Fbp0|Ca)|r$VG|6YkvR2}>d!e$z^qj{+`mx^c;ZU=04pZxT(I9=i+8dHqeQ?`xAM zjglFCb>HSY%aC7>H!9s}UdLo26xq=j_Q%61;@UPgSP<%~r@zN~!lMX}2B!7V5 z@pHt7SYXcY#5s~RNg>u0#Q4P?gJ!+pw&TtJZUyE{amn(;E#Hj}zi1JQFN;wABPq2s zk+`=Jrdo|gccRTTyZovFlocQ6nPQ%A)op&0aS0MXaE;AtTI|-%2Iw~3JsTW ztCYSxjWyW(mg*yfB7FJmz3jl8srq0WZz;)*=HO-)-2&waB+S%w8p*v|(nveM@eyxb zK8GBD++k|`=O)Lpi}T_aEMca$k!&S>iTwTq;i3CC`7tzuaednKLpDt*w`|oum%I6H z3camXl4)upVh69w_qP=G;Wvtt_Vy9jPoja7OqnyO?wko;*d+ElbS#!gd1q zrUpqsoAsXFXPb9`+C<@{h#Ga3i&3&h2kb^u=#Hpc5J{O0jJloHq?D*wSy77$>Wtjx zx1Aw<<6jKT z9zTWN&}nQFZGZBOTgp`-TS+>Hk~f$9GmaGrpAU9B0fEpd1b+b7pOrmVLVkhB`S@K| z0eKxIZ$f#*S)BO?zR@oLs{cg$o~0rPZa-#rO`*uaRj=Q`31ZolcI5j%&}3`a&&4VYd`()e{s$N~)UILC*9=%q_Lq`hQ#L zaXdduv}E-Dyef<{iUM|Hqf@Hv>bo5s?VLuf5UuRXhV-WaCPBW;Jw_tT^=?)*Qd(f? zR62MiQ_80r+;?LGS#HvFT+H}cIH^gm=$}e2j+Or(0DeG$zu?ctKv|PQAu%4PWqMZI zgN0Pz%5ta6EemN->`>Cdc(75ZZE^^Ogg%gL$r9C*3UmhI)KEIqNdRJI_Ck1PJAMbn zYor;(z}%V!oOJE*hVfGertiGqr}WG!HsHDhzSYv5watT@u9)m_wkD@;nKIrum!kb{ zXk>A6gl6mvkyz|Yk>q1zVwj_zM`QY!CaD?G=c=LiZLN-;Gd1+S6RM-i&IK zO&UM@uPhdpXS#O|1oD0cS*iKa_(V<=<%~xzD!EM;O|LtD5dExLfBv98aqY~O>vvTq zui3HXx?Poe8}t>$0s54`Ep(dneKN&!s2LkVpE_$Q$OivHwtT zM>rbj?fJF!*5;VLZdBo$^iy=B_a6%lT91`;%gI=OA<;~pNJpbqP$iJe`#>MM!+nQf z2!C7SVA0Yhd6AWJjJ))MkQvEjTlN76Lb+ANm5tnVapk~@-F-W1=xfF!c{o`TS!E-H4Mu29N2d;YfXy9; z)l8cD7}c4n3O}W~>TzmE_WYA9saVqTVM{W2sjr+#S>V#ut9#zED2nB+o~IS->!kAZ z(~9MY0etPnm%c_RMl1nvDtrUpO(ckZqkJ64V{W0Q*)Qj=aoN1K2gvu3Y8{=T1h&T$ zO!)iqO3q``DW_YF32HJpSgL-O${-O>?7Co&MUN#cAHpJ5kci-lp>C?v72tgtxuf88 z4%95N!1y^|huT@NDb$fgGQaXoEc4LpE^-R_aam*Td}6`AB{=xO@jL4vf<--fey!l* z{tQ+G6{V5MGXd7usA_-6hbetkJW|nm#+SuBK1YXV!tU`&{f$)r>C4yLc>3VSug*@z zoL##!J8qa>cG-j5_g*njTf6D0j#M)LqRk#3+W7T)rmI${<+g7aOEJ!yAF@(~bwLwn#g z1c{?_m1-Jk?7o6OB^rNd&G_KH^V55^dp}m#?%A!)c=jOI)xGGm$+KPC?3pQK3-=ZP zby@3uhgV&;>QVHEehwc#Oc)jgxE*|oY!VEP&9&&dS-kD_tL6UE+G4rCvZhN+Mfsqh zmScW!`{?kB3n#|LR$QQ+` ztvAwQ_gZkjY6m@(s#!O-jyQ~5yHKv{P_7`720MV~ys!)0za@H?eaX74rzs006u1D% zPSolZxw2{a+YGorH?X#r@($Y5VL8&1t8^%xmB|{8xpDy920nmzXWBJAI@)8@vW9LIybe%OAbSRQKq<*Fof zopMSRfY~n^a_>WO-$qsl4a;3yBscc%){IUt-)=ug>>QH70O*oZJxPuCJNf+2n9um! z5l>HFW+}L>QV@Oqgr!zacG|4;SNnHUbZ;Tsj3F7%z-0{(tU1~pbD zC=-jh!<>aI_Y6*5xdCq2FLspj)!aCY*K$3DPR;7@#BQ8yF1=tGP#hbF!;M^iD2D2F z0cz{}P`zkW60g;wG^t(i=FeP!w7obCJ`F}1sn(~Ar|Shsrt5J}(umyO_vgOn=nb+o zUJ1rEDX50y&T?Nh8wxG0mFnqYGP3;KXfUFOI${C%nlGt}8J|BEYaJ>jlD%G~5XcQw zB8j39D8>qX+rn`ztR}-eDjpK&A$dNE4^M6wY3<k4)cp>Uq}DZG%?OfN^vO%i5xd?ixgQrb$;T zk;Y~HHhuo7=g}kRN{_z#eAEVh*1pmX5zjyi;WY0l=GN4=h-y?8R1gJ+{Jb1ic^Uhi zY9LSi3{mrl8c93fn&uWkO?#~9@p%FgE7JgU41s)*Nkv70@%SB#)j=o63P!7-G699x z>dT8ut<4>a3ncKP14-~NkmOf>-WT=@a>S4y<^T=16C~n{BFZ)V_ z959hbT2By@7&&O>lF)7&L*QntpSxP?5F#LjTEI<)eoVxHkP1d-OvH=k-xV;j!$b(= z^{s*H4gHvi2hogyYYqLFh+-f(*De!@BF@V(&F(n_(NrOyuI(OTc#U zWkWwE5}3V&_+O0dHIe1B9|3jn8ACrNl0%3OBm3uT@kioZViVR6MrNO%y@GfjMh==Z z%ZNXMbKs3wKhMps!CuA|=z%vF`Z19vLiS-~#ze-6KY%?L*N+MJ%=Eg{g`HtiL6D)=@>c5M4lurLM{45Lq8@mjgSIH z_L|6L#C6~xJZ$L4M0O!$1xEJI*W&lYBVdD}9~1GSd=FvdpoyGf@DE{`d zPD9bj2zIfvr!%IeJ)AfJ4mBI~?L9%&&2g@vu&t8TgFKTkYIQ2&{vA{+C(&i^Sa(d265Ww6QzWA%IH6zTWB@`#L7$!+n1~CEFhrhjhe9M+xrZsN zXsA*b6Dcb^#oEHUUP!MW@3QT*q6(vy#`QcC)zglzY9s-T6-=6SJ}x$wUnnNX)lFe4 z+gDg!)b#keWtK!J(&gr)5%{By(GI2Q_j+4D>+h>=Z)jm(Imag=AukiJ8NT7)02{c4 zyn*OBI-?vrum05~yZ8Vs3uP@9&Jpyn7OTZ2a5ezeTh}`Tmm?Gqb+0c;L7s6dPKTAD z8L!RBJ4UR-PTj}F$s2+K>xqld0%?CG2dywkHZSfgE%otUBi@0RaZw(J*qdp-e<(or zj_?diki-CRp}W*yP-``fw$$BOcA!>@me< zM@qF=Np?6FP@I%o9ItnkH}@8X3Nele`Qq+EN3}mz>L)2uQDCxAjp_BSXnF)O(9~p% zq@27=J49FCfYZg$HV)e9WJv3Y#$v%7Yf~6m{Qj}0vY(Uu9bTRHTk6o(KbZ_)wrT>WI5Gq9Tzj3bc96Yu?B4y6z{q@G_p1~tt@XmT zd;)3pJXDi=kyg`)`#c}Gc0)SrGlz?Oj%Ox2DPoU+MFWNXbl_^1xG;o(Og;Q2i%4-2?7{x1wR1aAO;c7g^{Uf!TJw+ zk6u2yB-H3k=FFilRcy5;d9H&odJ+I2Iv(z_S|V1`;nO*(k;EO!3S_Pr_0p`hLT4Ze z#N>#VX25-v6_7~x_CeISD5tgE#V%Dm#_eyui>ba9+L%UJf8^wCz7je%>j0jEZ{WAw z_l~Z0eBWOz?vx>Ch@@D5f;-yr6Qhd-Gkd+uOEHW3eOnGV_Z-GPy5l?x3%zx}DU24T zi^akG%5=2gkE@YlAPx>S`g*qaHX8LEjc{#US3Xf)o698)zG=XM!>E2vB00CmPzmz` z$41qHb5XUxlu!=De2Uf+Ydt}AuQaO3h9-h)GBGfj_a6k zs3C5|`G8p$qsBYS;gM?rw?YHn%PVS%qiBXUt}EPP+d3Nz%d4W?6A_JWgE*gz+GsOs zqfT?4gpT>j#f96pA;^5V9SxM#J6K<7r$vw3Vl!eGCAmN#-pDU?LyuE++NoI37l^2k z?5q!}oHr7ZJpo=s{`Q_ehS361K@19V(x}<_sQhVi0N1Q$?x?2Gi|vLR(nHjeSc+dm ztxM4~x^}!$BjNE`!0gw9^u|rvm%^OU{{-Htn)j$zk*>Ph^C0GLw~ICsL&@VdLH#Np z0yaw+Sy%Q>i$xW(F~RDxRMCx?WSEf1$>>fj1CSU3hm?RP$zN|lD*XcIcLrqT#6WjI zw7=pPWeG{5NLCjeOBnUr4ekLCA!&@hvMBzP84SzR@BGvDd!*9_9X6ZSdM?(@g zC1tu4F>n|dPJ(;=qe~hd&K_l^R6jSqGE_geNp|*+^mw$V;z{ps5M!oC1C})t6Eg)$L}zMo0Jb2Q~^U zE3kUPA6XJDxjEL$^O9->B=iib>m^nZnM7VhbqW9$JPhA5Mmc#btXY-hqPm#Tt&HR2 zgIfhi$!$bijJT~VO$)TkZuAQ=D~SqivqLegI6RUkU~@VZo=*pvupDlLWEJ#!IF@tz z8Omcj>y)g-2uw#jQY@cbPV_bPdLqQCqL2-RM^i$V9Etmk7FYv52JS*FP*@z%$_#E^ zJ0_eJJ-3iMiHQ|Ic1}xL7}^$c9cXFQMz4>R`JWdaV2ea%8J3SuOrm>EV z_4bYuh}SUkF1MhLcugMT?=3Hg(8lUcD zA|{J&M&+e!Z*Nu-RK_jJF=SZ?oOwo&x*ClxiEp2Ya{`zs3=9;C{r$!MPD$`FZb^wH zG%XQR&=uhmB%u-sSJ97;b&KdsJdVzYZq_(cMeS6c{U9_vfq9}v3=o8D^i$JmF7xe5 zAsI`k7Ulz>f(S@6R6XjM=)s4YlN5~Wz-s-hxMYfQg#;DZqR~pQQpuk%?A7_<5sL+N zte_{rmf1|zSKc-#-j+?~nJnY?m@8U{DS(n0qTOCM^RHM38H7tnZD#26!#HFH`{TXL~| z??ZB%4tZTbm1E&=5@PSt)aaT{F(DSmd~C)-d4=Vf1~2>9<+i6I%k{C&u07P&4SfgK zl`VTtwhq?)QeU49v@U{KpEo~Df4$Og2k)mQPA7oj%>?ft2{HsxYQMIY=EMApxaH@b zYPkEMhc}WWN|VgUdioUS3?*^pEsYgxxqz&YfHcC9bT-0*2HGKjgg4Vzb=tJY=<5cGz0~V>`fqxHwe=l0(;>t=|I% z{kmGeD@sYO80Zq52;GX`@@H>>6{LX*_IS@fc@{=g#5M~Hk9*TMn(8{oem)ZkH3Nw* z3muT%L6&1gn<%lTI!^O>!U;9l3?{M`Iw)}gmSY8*N8p(N*jQYCVl=FTW!}enWt->> zuO2C$I&t!Z-v9-L*uNWvW`?vf2&iO0H2MJ${#^ll7$ z&-EG!56fdwvryCaFBw?w{I=t(mO^2|0ZwpS8nH|{#$9Vi!jdbz#un^KCG38yplcDZ zW=XD?O_xfMdaQx~c6pK-)H}x4CW;&?jr-Y?bW^XbF3w_Ts7&8JqptYQ46j zTCdio!YHbZ^TO%w>6z)C>6ZaW>vGZ?QPui}zK9uLM?liJj0pF@s5ou<0rlG4Tg$@! ztkulxuKjH!z<}iTGjwElwLbDE`pesPL`L>6lTq*fg5wM5doBG3dJSc_Y<6rxsV&aU zRz`8b6PgzfY2~S8-w+kwJ{6m6rg)t%ifPGMgf69}qLAc^TK|RpsL!M5USJLU1fI91 z1NoL1cq{7m!Ru6G>;j$p3pz)G9}w8zI!6ty2x-TtdW#%J6gv0;xCGDd$9`*+V;i`; zwXRKJxdBlm!A}Xoz~LV;K8bSH&73#moZHQuCz?48iou1v=P72uW0+!m0gpqNV#j;% zD846;9VSKdIEtCY6qrZtJ$dXgDaMbZ*l`TS*l`p)kD-`ZKyeUL?4Et?CTjU;A43SHHUD>B^6PTzQ%>=s*tq3GBr8^Jpas{?r-)UjRAm z^B5=21;2%UgGa(xUaQv(FSrc8asLDQ1L*&L^nLCF4xUff)|Ke2rK&DiDX_!%%CS@3D3o@BxH)B*MYsk)>B|f5R|%}E zffrgg2f>ooQ$a9ek`d6bdco^ZAxLAKDT-uHw0VNp4N+TL!C9f!VdSZ;{Gscs#k=k< z7t> z&Dw49*ROr8{jr|ybJr0=^ogPtL`=~qdR=7v{hwTY1h`g3$FI0^&7WJp>GfPxxuJ3${zmy% z01mtcZZqD&!Gd?F#V;zLQ%>+g%$l>*E5TAgN(ekkP_=Tf1P+MaM8Vb^_WML{yoe4| zV@C=!R{R=tKpm|UA!g4dtmyY-R9cm|2fPigCaCr}saC0iFLZ;|)mQKe_!Edb;UB>3 zxL=j#M{BSk2_(zhk~Z0V5y9W{0~+{S`rtq&*NDX@(%BODQMRGQC(~V}frF_fxxP(_ z)Vi*Y;Uqfl-=uY{>q-wL!9=!KPv=HTgL-Fnw4BQI?95Mfjb{4F9pkzDvaXR#quhbl zGdpIR(BF>wOSL@ARCDoGzs!o(WxcCy zQdqJ(yMxJ*luhMV+X5PIwYhu_#X))sOxSN%{R7>)es4VtfZzfYIMwS|d;Vst=!Z{ zJ68;!(6^_#qAN3*^QD6J;816Irhnx8JDTIoi?-!*8{XKkddaDSMVg`4?aDZvVNPhA zwf5}K?IXbKeX~~ZI}+kq8fMhy#Ums5dx4pRUw$99yKImjU#Ew4U{!^X#OPgaXlER> z%m|Zf6X683`UTeKWCFTMvl37ySEn8O&MO=CQAGCbS?bDfT{(Qw;J))q$U5>df+P+v zkB@zj0K`UQznw+0Mhsa1G!k7NJP*%my-+xB`Bl4LCfUDz2;5X?-A+1?_86qX44RWi z8Pug3DDiY6N-{36rRV*wRuNosQWKu=?(NNCNFvUDMEwAI3rpiQ>Ls~UF}tFvQd(@s zYh5^rN(QOcJFXh}so}}hSFaj8bE5C$p_|jSWa|(1`nuu?tE-!9_1psoVf}{blRi4# zICI_7ix1@B!3Ty?XIwe5^OWJscdolOgV*+52$$m7gM?h+$x2k#^e9gvG3bFm{|3Bl zYxrBw{`6h2JJ_&Y(g&7+gV`r8YCYI`{ED9%S3H_$W<|M;K7s~7bsb%ZG?LE{P!^+= zTD4p;@TgTlm@tPu2Dif}X8-_TruED15Vk&N9vwbBcyZH+pxC^4@G$zAhX%R`F?whK z?^k~WNnS8|s34l^VM!ie&~tmukjK44f3~)JNEJhsOoW@vj&OX3=-mKGIn!L3tJKFY z-ry)i;|*j}ulflxdm10PZDk@la@ysWw_Yz+-C;H{%q7L)8$Wo)NPq9LyYF6J&cr;C zP##H?MLQw9jjkCEuMLkDQPs^`A6AL!S1K93I1Afu-4GPTXw1;pVenb2BYm*Hd1{)Z zY#paHN6t={3pcErxOk>ko4I&m@}imAyI-?VV7c|PE=Q(V>9V-2hpn$TH3cdvY14rEXCPuDD^4(#|*S1G5MY%o=UqXmv=K2CmfDgkr5fUK2 zf{|-r2Jv|dAt5uWa|@mhPKK}HNDJSYi|tChV#eTj3L}YG4~p}{;F!;M;|MOFMP+P8 zHFXI0}JnjJF_Hv>TnYoF|{2%ydobPBv7UNFaF9V?Rc2Jx7_IR?a~* zPolQrP>cEqf;1hX$6Fv1&PE~_VYrAaBpg1bI~j;E?x?~i9dL4RKxVl}N2k5nR9G&Y z$`~bo6Fvim$!&y!xc)t+y~$01D9Z&TRp$d@BNvFVMr=4;fG=Gnu%2kV%RbaEFvbDq zxQqA?)T>Cuu@dcJ5fzBb#qj%R+uJ{P9#q01n#CJDt*Vw|Wr`3j>0k+Z6(a(n* znIZVxNS)O(*_bQXs~Z*;Je{}=^<3xTG2p#YC??5)C_Fvr^TmUTFM(*6!e@!klheo2 zUaW-Tk`mJ3vteYthg6?Vz}cU{Q;EO8|7d$1xdqgv1;@NUCJDaC{hU802x=6bsz_?s z$E(q~UjlJ@8U7AL$~NmUbm_}xr0npHaWd@b6c3Xx<$3M2X6h8d8AZ?$VmE^wgM z796w2!V*?syr-XG9`UEa{;L$8V_hL`pLhPqkk5v$sxk5mQ+I!dqiu=}y4(WGoqEwS zbi|4*cN+ZfgMx=)S()7+%pV#3>_wPHee@0EIwg%aKTW5%Unl%qWCp%*)>-`Hk0TnS z=l=pKxwCyOV;cFSD}~EzJII~u*NbPLZO~jXYenDRB{;)tuyBA0_dbs=!U(d;OT5+6 z`&XIsORfknn1LAa{)|2xvrR;~=N+78x5tX#)ES6mv$ec0?{RV=UXAGM*N=LVu~3F_ z_-MON3Iq%({y%h2UW)pIfcO}0-qJBqf-cr7{%EwaAaL~U(Z0Gby!2@JTLKUY+TG%8 z@B+4DjU8>Hw9b#Lb64>Ur*uy(4GUrY>$?VXStnqhvVxqS{ z;|t18A+N|O54b!oNRBbf##070M)4vGzP!Y@|GKHEPfj*#qQtATg$B!SU17Wx6_Fp{ zRqXFyg;%33nEwpgE?5?7@3}!3vaik2TZ6^`7J9nccB;9Mq8)B?C@SXlXgJ;hzBaxm z>r$B1#_grmThF{w38%+8Yg6Nc+CZr1f=dQhvZRk?BEj0hgLNejUG&<2@Re-rn1?gY1>wDj;p3Ux(U4nzM#FzVJ4O zW>*nvO+{?L5?*MV+at6xRl*ql5^t>b&`=e61F8qwh;>^HG(Mrv3t4|ONxrAF4)wo> zWN&M|v%R&oj{fYU@xrx;dzR;F_$}cYf;x9mnI*?pviFw$Lf*kkOBHKXIZs*C2#s&7 z@9f{u`~C#{*D*I-#Ud-ZdSzF(2;EXZv-<4%H~dEGX}evx#+7Uv%9C9NW#@4X*`)8qxvb*A@Y9F&2NQ)}5SFZiNqT^0#({$8t z&gcSViVm;Qf!qtA`q zor^|?TXJsX@BP*a;~5o(ui9&}&25vRRkbG7byjNRs>trHu+C5&=kl^Q(jRk2SnB_$ zB(Fgo+m?T7uR&-2ePCcWCRYwbPpInq=k&}!m)s7?)PQj6Nup)U2PPXij#h{iObDa~k33tG~OU0mT3 zyJ>GQ0v(LVTsrcW_eL@@*XYD$qj1%zMl(8p8N-;|;yO3DX)OLRwsDMWJmZ^yPfTbc zI-A%e+~YQP*h3eSnv8kuHMuEFX(~Q5wP{RiI@9xz`#hkl8O&%VGxIGc%)%FDcQVg}UWf;ydMlgzzmbDz~*k^ewSkX#+Ze^=jm1$P9x-}TXXvQ+mn%1(mb@-0s z*5ym<@eMy%-v&0ck&SI)Q=8e`7PhpNt!-ml+YyZfBqR}uNkUSRk(?Byw7nhdXeT?{ z#jbXqnx-*DJ z98!^*9Ykb@x#&jDvUhjUD!JTZt#Y0A=?w$62) z^IhOV7rEFaE_Ip9UExYs5uY}c;VWV>p0iA5Dl=TobY{AS46Y@z>s;>!H@eBqZgH#I z-0lu{y35_}aj*N_?*R{b$ip7-sK-3+2~T>;)1L7^{@1gf^Sl?l=p`?E#j9TPx;MP( zEpL0ryWaD@4}9n&AN$0oKJ&RReCaFy=W9RlQ$J%BtNq+B{L-)d+Hd^U@BH2${L!EM z*FPM6!`O@i+)vpUjt<6-`mW67Y;Cnvv{otA7li&wL{qhz#pPdCi4zf<>K71Me#L62# zRmNsJKMm`LKY2%fN5#qS>p_*bPSHB$6BAme*-CrQ^!hpNJ)%rIrc95xl5 zn=ekiSEoV2k&B^&*B=z(pyiewI(Xt8JPw_A(2X3dhF+Zp74_G{=*Qlw^NqsUtPYx? zj|;zf6}H~T7CyEkA6swF3w?a)hkrl)C+e=WyYlWb-F4Sp_uW-=SF_RW{S)Dy;-2Gf zaKFR-9`^$GX7ZvdcUTvy&O^{54Z6+(&7-W|GXL)vV5p5GlxMg zM`Y~3ZFSukXIFtqYO=P{NoS!PoOyS=4zku1wXs=I=oHmH>?75x0g?(`x@MGwNS`#x zpO?92A8n-vX}O{YxvR{JvyCbuh3R&ds?v5SfpyB(vKz!DY!SP%R4ZCI%M6-L?%gIYd%l`A!mK2mHS)89a#k|V8evut&I;Pk z8uhbA<5{CuvqrCHjs7=lG?+E=vw~85VqGcXK}0+V#e+gT7{r5#co2#QrFc+?2V0BB zav&b-fp`W+;t}!U!6_b;;%!@2A|6Di?0AA-m&3Gkid)muNxf9DMo8Xe zlbb5p?A|3vz1fBEa`J7wR`PmFUZ>~Vc#nSJ8$rNydUee8^u&Kld7Lda<$JqSjZUaz zG56?y@UN~sUK6j+Jzjd`{$e`ahAnX!;Y*Rh**5$c2j>T|sp7Uw3;i_SS!_3^NM5BM z?eGuBIC`>;KV;+J>3;u*W4v*;ml$2?+SKFt<(B-38ON?Z8vdmj?_F=l>a`T{5_szI zY)6$#UDe7ahpK4)163gdvj71A000O8000C44gdmaWMyx1Z*6V>1VlzmQ~(-dd2(z3 z8fS84YXBN-VRUW)8UO|W000000RRF32mlNK0smV70RR910C)in#<3XzU=V}hFVX&; z1;7eg7Es%P8B|(82^xSAsMR_)u!lVFT@nNo0LGYVzK!V6P4+_cLkt)uMdn2>j z-A`lI8QY%L&bG$3ZQHhO+qUs++xEP%b0hDmwRgKueE*+++>BEO0YqUA-+)O;tJ4H= zeL4>5hag-4@I2Kp#NbKfg8RExsX-L`eWNBpRH;`dC5W^pjcNzcB$On=5sRlnR|XM? zL#EJ`gGfAv%%Lk6QFt6#LRSGq;|XL%w%%O_^}`~$N^X+7L$Xqg?EHb#~sIDv}%gIWznoN{602l-i_Fq&N0Ab+#pFQFJ8^-_` z0bmG#0RZ{{=m8)SnUD(wPy!VYk6LJgHlcf3LDf75RVNCn?lTA@z(6q=0B+!!s43ZJ zl#N3K0FzuKIUWSSAIT&OimS8znVIosliw)R}ZP zo%gJ%ykV_nA~bnq?Qf2OJm6`w*Vo5lQb#q_hwP(Ia*Cs^&iPAI_F*G-;u_D z42cC2i-G!GB7jT?vnvOJD1;Iy2YMd@Ae;H(W%X2lLXML2d=suF-1>`?hMcuHpu6v#C9x_m1}i$Q&}aOp--qd0#A6-%+;HWUg%QT>x1} z^TKk8>?6x~KZ01MzOV9cs5i2Kq+I1avKCk7o+gg^59A4XNM4f{e7$$Q0Em@dto42G zhIN+aKWYA*l9PNnUi}SaUR0mrXP8gPL7EJg)0BTg{nP5x)PF7mo@?Euc`e!4djQ5a ziEs56?_nN9+f@L?PzIF{j~d88Jv6b}#|D5V&X+rVaY+3P&$Dh*zfkkvlC*02BUh?&woo5;6tgj(ejA&xmFZ%7nE_^)nP6s_E#{bc$$Vh0np;kclg}yRRB}2vgPbYO zDrb*#%K6Co#SOZ}+%j&Wo8mTe7r3k3J?9)@Bu4s1?^4RQt*7M%8=Vf9Wn>9-KyN=GakBq_4+}>p$Q^0n=VTN5Z?OKOCIEGB1 zO@A4BEah!|+q=bj{+WMzoHdZydli3RP_7LS2w*4-lOfO^--eC~mm2qFaEHU)hoGju z8Ny$Du@@WcYFZp{A;+Fa0Y#KhMg>*WP)7qz{#$B_M^EB~PYvIx6V^Yo4AxDy$U=zCfV2B>hfON^XBnwau=jUU;Ev zBy{=gGNH_6oy!i3o*WUGUxoWGyIP*t;O@(=mG|qZ$?meB%G`$nf2BZ3t0cCtMqs5> z3#OVi2c*VJ?@DSbYLQ?NxWn?s-fXF}D~RV>>`AH04(s@(j9(FkII&9o{;5zd7;ryZ zu0zc}S5N5fu&*cW#7YP!{fEtJlsSleWcE8;RhLP9pWG;=?1UR*;pU?#pGU~5Is_+J zykIHBmw$v<6s~g0bCazc8@n>Lld)H2>|KueBz*c5ZW*(b@t!V}|5=h?#qp*jZO1v9 zXFe8cu9f`q7e8F!vX|WWlD}k+&t8^ga1twc)RNzg0;Qx{%3~>2jCV`Pv0TFOt(N2^ zZb;fgDR~8lA+bn())H_WH5jGPk-Q@@L#@r%$-Bo6NC%_Cv7mb{&`a!>6Pr9y<4)4C z3n%XbY3T}75b#S>@YG}(jZivn5R?W&)L04Xaz?hnH}%Aqfn||emk=F=V;%YBIXjO# zB^9V`oH$@jpX?{kG4@yC3xjCdtitH zo|;hzG&xK8ji;!0ti3a=<18pcCWivs%DsS(e7dQA5;&&GS@?skuswuUIq_+=iv;Y< z*`pKc%LNMg1s-onx!T7No79mHO-`mSH!$q6WD*-lkG?$17$ZE~l+4N&j&sB~h^@Sc zA=G=LAN56}r(6)ep2ctQ9MsDFa7@}NYj-7er zOy1Yib!mL(GMJ@C8B&2hM)5qQE=^%KyM%+$%YCv0=Z$r&Vojb!42gB-YZzk$cd;}U ze>2`=EU}#Ofh3@6(+-osxZi$}n18lN}B}%|k0xS3wZo@J)?5k3KA3iNlC%MO}^m3%NHMDq9GG1EG;FJCH z*)l^lv3%V{spDzC(vvMY6`yQTC3i|M$uV#E(nC3c>7Zm=ja8l~{Djw~%q7Qo?j4zT z80H6=y-)Kju8VmV`^>1rXHrTM$+KO(O__#1Fat{-oon~><#})hjne36s&(Ej>&)ll zp~C%Bd@xQq+({`*(wUU_qrru?E|x@mx{tKMlinzxw7wwkLf)f>(_LMtvmL$l)M8!^ zvE!JeZApce*$OA`%w?ugAgpqOoEh@ICFGgcynw(e#+}K%Q6H7fKE`f08iM&q$j5eH z9$sS~1qKrTme9u?v!;!1!C?!_()0URVa-vj;cF6Cx#MS8#V{DDUc}c^Ym-{7YEQ|} zJ$S22uG4(hPKSY}I~9{)C3S;^*p*7gI7EV+p^UDHZ`VMs0%tSR8I%9AIlVOyhTZomGu1?3re8b3)>C21_F z3|5uqfyE>yt2H?D&8=qIlFYOk+qS|vx24dYHak1{WIQYJD|qavC2Qnzot{9Kv}Vb8 zMcB>2a@5!(PI(txPTHe@T}gKv2g7_~&q~}4>aEUDFyhX{3W%+>Q)>FC@hjDgQDDzX z_?eUqjYAPnyAwJjxAn+ddfWNQYg?NVgP<$q4%GO9Qh2uyBjXX zjQeqaiZb$J6vCr0xELF`y2!~tw|z3g)j=J@ha2s^ zoR(ZHtCqbkrp%>uq-BI2^M_^6%Wh$O1$!T2I{@F-o-s=Zj8~dk0Qq&#nr&sCoD7Z}as|Z9YqzM>QSQbmbmX>*`5xGe3u4 z3`mciQqy)2b=ye-e%jKi7n!&4^T6q-qlV8M9rvS_#5LOHm03z^Xm9ZwF!eI^hNIOR z34M?wHtznLK=rkwKJBvBTh)AW7vxxbC%oBl+`Wj_pxjS2F&tC97^vr6XqnPSg}W1W zFPGSXS4^oh!;z%^hi&1!z@d^<#{Mhn6dzTW zwj`}LUjZ?Y^4N6cG(KXU*dg%?rfkp3p z!`%#JtY>F$c~PS{mtWser+4g@aQO{SJ9P{Hn6Hb|^@!|E^f-p#-y;xPLO){I+`zN+ zeV*||ldy&jd9Fz+B=)f)ahbR7eY{HEKZ3Euk(8F@xh`*m?78yhX{XLMbhH1PfV%C( zg0bnl-5fJI>fr{j)L)IGWH~VuNRA z-nwFgC7;Gb4D0a9zsL)MCw7%ZdSB)Z%&pTa7}A$8EMprbDH&SN=@Wu^8*y#OHIz+` zU3e`U-(DegowNU!5nMr{jTbKDy4RKSS$cS^g`C0B0A>U0#5KYYf5VnUhw*;C6Jjfr z2UgDAE^1iA8AY<(Y1*2vBDR;txEANAYVuC{MjW(rDCV{xpHTl~XnxDo3Hkj^9X^f0 zEHu%Vz$cQ{9F9+>h|V>*;5&m4bT$t$H#PV^`{(F4--FE(t7W}?a++F3Ke7LnJdOF_ z|LY#_y?K_CcS;v7IGG)V!wP+9Z(cvjDLVNzhyA}IkkZONCHB~3vL|35@zc$@MBeT= zoflvyJm&ei{0AO)wE^L)wtDcZ1#ssrSWEm71%#hruh@R>$A!WE(--bk2`yvOcqR2K z`sR&`X{*@o&!xVzo6nxc(A*H8*Ki(e5CqQ-f?pPBd-0b!>>Lf;+4(6_HTw>oz*{2c@+hzD&r z5%)6=n9dBwved@2-X^dYdoz(^Z8E2G22=RGP2*qu+q-Y(7H0CW&E_eagHX_csHc`Z z1)3RV1oCV<0d;;dK#p;wIm5>AFB^+bdrm0mM8pWFCrX+kjkNy!SH=HA)CB3E98?jb zs3An03y$g|`(_SP?}PQ(Orpl~P)5 z>QJY;G)c>~LMydZ+w>Nq4gV`-C{e+8a|-wJmfqq)HL00r35fF{UxPAg zB&HU%P*S%hQr2WGV?e95ni<-lP0ZAbdWkuDMXxYVujw`B>kYlZ0==sbSct3#Ax%J* zAfT0yiHrr5td@$^F=$1`SPQ3E4fk4xCoRF-R_}&Fw7R7*c{dfI$!$exbYn5nZY@sA z%_XV2y);=j*hbPVc2IJYos`{X7Zo=;iDtLDoCY_$f~ebFNyH7WA?}v95^~eq2)pg= zdfX90Pur(hw9 z7N%?wsurceVl>(SO_rqDa_@=<97H__ zb0{GW<52X~X_9_}TqQ;vS+ zm8Vw)6&O}gMTS&TiB6SOrb87~Xi!yE8r7gis`B@aaq{=fxm!K7s8_wTs!x5isbBrh z0~&B1)R6ZK%fEgyM#`K=X_WJ5jc0-;Xd>e^MN??jG)?n3Lo+pXM4u6MpcH+cR=-RyjeZlznd={C>YuG_um z4&C8=r|$CVV|sy!@^1{2@98~{ALs+V@8vFZ-8Z%6;BqfO9 zAMtHPlK28ih0>Do=*g47oW`h$);z~jGG!^5s;+=YHB!S@m3pXP8q)N%&6(6#BmX-t ziLWJg*keJ@`4p3SqL=t_-Gl0mTjI~&HXCM}3jnS(j-u~{dfV7@tsabwm~~DVj@tiC z=dmNMSpg=v0adq|P+lK!2+YNZtKAs?WX;QTxSTQ5Mx)rij^ndNN3|8Orxb1}g>y>b zrcyXi3a6C9Nu_W@DO^_y2TI{CrEp6r+)@hXl)_D=aG(@UDTR|t;f7MUt`rWG!d=ST zvNE@#%&jVOE6Uue(l)KM%_wctO52RmHmkHPx?Q(RUYT2P`);4SlDFUv-6479Z$bH+ zR{my`ziH)fM){j{*Y29UQn=u5-7R@#alzfYd-6);f)crA^X_k)a=E5tEGZdFntdlU z`!2cvyZ@6=N|xL&mXZm5>3-pi4ICSyC5IZ1jBTs$^!=M9$&TiCX|fbaTW5GuZso}u zB@>UNDd;<(G-6H3dgkK*CmS*RBfg`E^RXd!p+FLzlzEm7la5got$Cg#`c`VKperC! zh!lMkq!hY0WvO^-rY=Pw^E-Z2GxRde6fK%;Gr}f4%n(=WEV9Z9^Xvgjz(VZV4Rc`{ zobUp?ataKXL59=~)8<&+9oaJb^wA%+|C`QZ%fK8kOjO#sF>k;F6EWiIJjOp+lQJ4E z$IPhFD7LTT__)zgZS4XmQ{w9?*0n)>sWB{VS^o;48dm23004LaEX_lLoB;p@;jeAR z8U17T*tTse)+&d|adNUa>-VZk2F(Vtwky7wPm3pl@^%^#5-l}bf&fR+Rza5oU^i;J5 zZTgIuvS7`QBNy(x{cnuPD0!wvqjp{TjheP--L7Mo?!EK=7w7Z?)W~A9^-cWBqkSa{e((1G! zZB9EnBEkYxZ#s~MQU~?YAr4ohQ;nh%=rlTqE}|bx~THR;1NwUE0`)aE0oov^DKW zyVJfj&@if2)8W)beRLQdLnj%Lfrg$z=g}o}72QC$8Ic}C@1ck28Tuc+MW6Wmuj&>3 zK)=yHep6|hepratohmEMO$*ZEv@ER*Kmri<%m29Kl+Z|(L)DwwP7|JX0%~;8)mU#E*oY^R)vhngv=>g0$FXCGa2)tCK{qC+M+A^A`~7B z!5B=z9IU_w?7#sW!5Lh@b=<=S&1O=!o73h6_V54l^L2(HK&efwOJj?atapMxBkwh?kY>%F6!H?V|w^dQF5rlZ2!!@A*!IUipn@qX=#P(c`>l zjracKaiOo2M+&K=kxmAgWRXn{xs+1D1zgBQT+Ah0%4J;66EMhTBSjsY%vx1eZVm0^k01xsI z5Az6*@)(cv1W)o5PxFjbCn}j5)T9=*sY6}rQJ)4hq#4a=L}QxJ)UvKokQTJ06|Loh zA1IkNw51*G=|D$1(U~rEr5C;FMt6G9(`w30e13IWf2yg@l z5+ZEbVWt0Bga}dMh$n$WlBh;?lC6U^mc3Qmv|T&2Q@gZVd$d>k{v!LOzv$#oK0yTM zE8e(}3uN@q;AEBRD4nFUbdj#oO}fkf;%ct8>a3pXuc7)(0hOpgpUbq#7had?ORvlI zmDd&e+UuCU@w!sqdVRd!le6mgjV1cPSf&q+<@(52p^uF*ePXQCr^e&$OzEop{kQ(_ zzH=9&#c!_g%YVG435Io&8mpyxYqVx-wVu;k*7;T(spL{jjAJ;7GdPb+xQZLNjeDp~ zLz>f;&h(@|LmACPrZd+%T50<~!E?O8TYSP-tYIU2UD&0{X)enYWek0&K^tw=0aCO@ z5ysM&nzYq69VFH4arC1W?X+EoNHcpp{cXqg+JQ(ndjbQfLkH~yGR&UHK_Dnn^VSM4KAt^!2#z4pry)f!`* z)*9ngWlYdIW1`j@leEEDO&g8XwaJ*Q%|@&KzqLA`t;U1eW;~?r=9hLD(N3e&E@MEu zjX~`(hP2lh);=t7(UMDyt+>?Kn#&Yo8pCKrH?FYtbcWNI?p$f> z8H}I_J-Eu&GZ{%!dUCZ;Lm}sqmBJf;`b_)rd4@gPgq#voAxz4J63q@P-v8GrQn5Rd*>a&1JYOm*etWfh%$) z!sJHJ1kV|s6>_p~z@{lmC{aA+lq-SbI7Nw^#%W69EY4Rt_i&GL{X4>ElSjVdEq1OF zh2T1i!5F4W!i)7xA4W^O!fQ(YF+N-Jt3C|%nec``UA|70G)80n`GOR15+`$tk8RaH zi3rJx_qOlAdw*>oAna{yl`IJ#*(yxF^DOZb&sUkG3fnL0_sh|DCV3Q4pnN}t0zZX9 zj^jiX`6-lfo=u_LPa)=KR&FA{Grp4qziWn{%aNR9ogeL|bDZxG6Zz9~7+kBN6951J J00961006(=Dg7Sbqb+0kB_h|Gy$Eq$~yiTycIe#Qy^(q`(eQ zWhsd-S@D`mK^XwJJ_7)>HUVIqil1)5p%Tif z!T>PYaR2~8001E2hhbpdQBY=N`I7sh0W`iqUoR{{U7txQY1}@rxGog%f`P8QcmytGNxx z?Wq0Q4_lD;;?nuKJ%j1qY8lxlUfwL*l&$KtLRQ zwEG0_w+q`8Gzw`uZm3M*7eu{C{2PcvbkO>-?`Lt+_UTl4mPa5F)s# zKZGU#ep!K$J%AIpAn3b+4J13+n~vay_^wmRyHGs!rlz2oDfX!r4XzP*+N?JI?{mKH zls!BDe1b=YRWkR!ThjDu({*&x_-awapL}K^-N;k6d{N5&`rQ#FB8YYlbFXaq?0Z`v z7m@af(5pfdki( z56E{7i8y!J!V6w+LBNDKt^YsN9-j{ARaXgQWz9V-q>oT#xMjujQ`)$UqajsAI0qt6 zfk*hxOIm+gFP#e5l3Zjo&usHs=M6L*$fc-z|^yVB&Ky(ohfYTQUDOI+wC@v~YzyvL5=j zyVRKqN+-i33aeR~X57v#2icl1;*|(7mS8&mYbg!VX<_j~VLuxXLLV&V+r3F?i~1fnJX-t**OTrF=Rde^GY5 zq1XclQPK{1{b`pdTkdE`YmrYq5Z-$@%D<0NYfKG`MpUA{XYnotudBHk*Bo7#9bJ6i zemBJ$RiIASp=Ui5svp{oePyo1T+WmB&QSrin1&j^%9v8$4{UFmrf3(BGsph?%=?wy zCZ}lQ1M3?+Ni~#%`wi#FM|eS)qCgl*MVJIW*oErah8a62zxNoZn2ea@PmY@mN*p8^ z>NQV6wCX#l#*FY|Gl=@9TvALOr}XjkBB@{je%o<&g$~KJCto?3BG>0>P3r`r!YqhE zVl3tTODwMN3!XhlD+Pj?u_WJDzVBQ;W1sL~CH2NF(QV;A!3~!*#mOxYSU%nEU6#lH z0<_xQZE!A;#^)&^_Qy^Gm*_#(AUMf|8We)2yWI~ka9R?CMf&}|ZP1L@7+9eXBOBCV z;56xC-(lt#{@e?dEfRYX@*b+uOm|Q_I2~mjBCmZM}$4 z$@j5o5#p_Kwy}EuM6Y+jXyhWA1yfAJ^#PStaPpU)>8Mz!#8+9|uBBKN?cE8y4D?!h za>jW(Q$+L!8(O;~V(`-Lf6sn8+34r0z={yLrFo9nd04-x#HVbS>Ay zPFx9V!*3MM%Il7*JWPq z_gk877*FgfNjee5v6R5As8@ab*9a_+>mcF;sy(aB(CXrJbi_Y5DlDw}O>dXSz(?__ zAMG@DIoy!66Z6BVNk7;bRW$4Qomw6XeYJh}H|93c$}lWl>~2xJh@@PQ_E14*K`q9F zhHpmY$@`BRLa*E9G6GFQf{t@_T@?EKuJRkZ*InN|9WHwV-f>9DxJKDnpLB74H3JR` z3Q9@NMcA4j2jEViaa{NvR!UQaa=Fjv?GsH=6-M@k>~EYC_)wO?$g2_V)mhi9VbX)L zSILipE!>!d1I`ER!Ox!tN1TsuD_3k9q_3<(fTjNWjfPKTvxrJj&xD(G@_NV-g0+tr z4rWpX`H!6G<-?UQFO(`+%i{s(J1Rn$36w`^sH5!DgJn73I}eZiM>uaY>fhk@y*goa z@IfKr(W*k@cVX{sevMR!XrVhb+Fs=pJBDW1)_F?TI#K}+xYz@Mr?+7`grc1w{*2Q4 z=4k2py|V|vi{p!LiJ`0Mg5d>4GHDalWL9}2mG}>D`?{3?J~m#9jNp96pH=47&st;S zr??inK@uuq_z|5Dz+!i0(($oU*4+je>+yFMJWSU|0TvOqajyb{2d6z@8*o)q0)p=t zrnSLB9XwXW!9$a6E&fOCLToe0hj#hlDd4NLW0{MqJ^WF0&^J?=4YM8FCu^FQB3;=~ zP>T+Fz>3@l&cttM-acYA-gJ(#Pi88vXZfg2A5>>D@XuZ&VK?Mdrt1|JZHfHKZ$5bq zgpRv6>$;d_#JET{J-9xX+DctX%vDc(F3-OFuSRwcG3E%qYQ96w9o7&8uEssR2Yx0w1bv6IrcEE-w{mj}L@Af`@MVilxTQzxKZ&wFk z0H7is0bmo)0FePPP_QqLVShfnHGII3!Lo&(Aa_1d+>?>WYsQmobb6uRdaF=@h&Py< zS4E-+zZiBME4QR8cPuNnwJLXQHez=jW#y-6VMr9Q1BEmKMchOMMMZ^;MTJyEML_+6 zvi-u={X#nZB3@*I!el!fp`(|M!P)z8sH6bQxb9#$TQV^gH{?Hil70!2L35G;^^zfX z!@nbj1ILH`%ilkxdl?X1s6XBXTuLw!%zN^mF9?_?t7yf z%%ki1MK>~W*3WQ8!)#nM9@~N%o=wKCEyEj1dc9xvmQY6(un~CK^0j~<5SHp;-Kbd69tO2_)>rqCO_4KPY&?`7+<1P$5(ZGHN3)gzjmG|@5 z2Tsr2j(%O+s`|yH(=)jTHP7UZ#f{6b{jkGYpsjiiZDv_mS(a6;Rgw0Z!TR(X^SZ+t z%z6?}Lt9{*Ut5WppIMz*n_1Oi&SA=-ihe}5+K3T(RRY7K>+UUBbu3tmB67nta!1YY z+Dh=PM(wxKLfXXa9)O|%GeeCDh|P4jxsh2diZ^pep#dNLQf zIuAO>iuM^nF8c0Ak;by>Dq9a5eS#r;h@t-`dO9aMhkK*@gBv0zx&o9qQeny|4}O@w zdbjIT==xK<*E}|)?@ZNX=S-(?CvPV$U`r-afEIk~^~m$|^|#xf?@tpvH49CHBc~Y} zyV~d4``X9a2dhVTN7kPqga?j4($Tmwhd;JH0%D+>u8GhcNy$3n7d-+#>+uL3yW5^W zhGH5YvmrJb2Z(rI4It1D`J2u<(Iyy~Q>k)ip(mAIQuguJm-sHFip^v{4 z6#oQeF-)npiZ32htQSGw#biw>{}z~dB2}6A$k3gV@esSTtnOrCGLQqIp#fw;z8hvy zDQE`~Ex!du@Nb8@VwW+sn%+#>MyWur>q-X!X5;e}Fm85iv$OZ6vJtwbZ$fYu+a5A1ONRi z@KH}6d7~ROr0a>JBbU%f&s<84YI2}6bHI1p<+|B|l-}hT-NvFp{wtZs>-ASu$b`o7 zC+Z0^%?T6B2@9+x3%J%#l(e6OT1@;}EMVMI;yhYMeXK`=f_M6kATzBy6OTJ1C{s~i z(_TT-9)Rf}vFQNQLBHfdj|OHp)qx3#teJ(Zsl&KF4(G+6#Paa@@(|VX=zHskf7Vfv z)?oG;uj%|j(uj@d9XkFconk3v6FZ0^Uu z#Z}#i@rQ6%#u7>6knEa-1y9@K3Xxi%M;0-&CbhCf4bFZ$`K3K{!dX#7+R(Z%m8K@SKsH@A zxL`F{xEQHzmr~#{OE#-LnBOFqa~BWBq8L0Ti9?EJ{G)U#ho&zF0WF^tXg*1XJ#LNN zdxkxVk3FG--Lr;0aes%OgPxJu^^gc@TAv5$I=)D1%y&)^~ZanmU?Y%x)Rs(BR6MR-9ojEgB zR%3WpLs?c+I#zwqovG!WA1Bt2HSO`0)%uZlcYn46g|27Ur zHn(KHayR>PYX(Nhwt?DjR%>VvAx_&2pP!}@Z>Ql0qE7Td4(@AR5+dF|Jy*os#Pjg( zG(#_D56O7tvy+(;JBbY-yp{6Y@5nZ!hmuVJwcUP+evh$y+}kx0eivHM0!cml=D_ulLM_;IZBChN=1EVEKz?=pP;^r zSxIt=TS?#HRgiDHYT*H|I9sLfIL;|Z$j=$31?ocr(LhPzOxk(rAjE^TAPZ1dAT_8n z5C`NJI0woNyaUAs`W_j=;2fjEG#vj5?JOK4%g7ref61zhiAk+YxMBp78?XTBx2b>u z4dV*a&Zr+br{uQ69FoI=9MX4i>tqhH95QZkwy}yKwuwhPtq45hy%ep=c|0Jjhi#EF zS2244v=V%X{WlEzIn^HK3{kucM^}dxgg%^%0rQML$cR2M7|&z!CgfxXgjM@>U_XK@ z5(l}ZwB7Rx#G0$`%YDcbUi4L=X2KsIawV1*woW6TBp=3U*`lQShS}4SXSBHe{KYj(i>!VcN@>ov(5)o19aFFCHAr6~#{A6&aAyy7 z)OZ;e!aBFI2Ez^Mk7O>S+UXV|J9l)4$_xpPtS-dbsTV>!_jP+$4GE5UE)d!o7czae zHhM!0`Hm!>u9~t=3PUQq#FG<@p7}NSXLNW}!%^4oS9K#WE+}9|FY1vZ_ zoU%!~mh82<_l1RONa|z8qIwyS!b0T=27pQl$apd`t^QQx?4e061B&9-DDS(I{YBQyk45gtJh4Vm>Ib>})tJasluc}=DGb}pl^4PO^*>A>RKjWfIWM9IO4OsSifFgVo0B#sH#%od z%b(%fTn6U^ESaoKM~YI`$kf*@$*l}TN~qVY)~BccxiD-pN8$kE1ENKsweI-*&G9vZlrLNgSYi8stVrhbH#50@)4({aeaSXG#8spMpINzt|Eb5J@1 zbnLZm*DeWp3^)&|)`;Ato%%r=${mR$BXor$6#6#fo05bt;ijqPL9wPUnZBfm(jQ5n zc1X#{utusSnbTCzPlH-V@B45$09NbYtwBaLBauUD*0T?R1Q%FmAc0)~;*J8oW7kgg zE0)9>5$B1|5c4A*L(8YV=8j;Mr1f2CKgOfx|R|xx61XdY+ z$%@BBVuTGtLb*+GxdW^EsQxw!U^2K3*@nn!Yl1oDweHGBVJ}ta^^l`-Gf%GGmm~A98G+4CX|}FMQYYrHf{@_zoJVVk`^+HM;;0$Zj3`guZ@4*vD{Y`p&w(OE@I;_)T8QD=EuGVJD+s z(td+42o5#77;AmDnd}iZ4V0Rj){|`S7};U;W7S0`iUO zTJ5_o9WZ`?8d z3N^d%{wLu4u)^Q9a^5~~+nl~eMp?YDhma`aPCD<=-r~q?m#Y=h^viauLRI^keKfMY z!qRF(z9qCt-KLL+y6I}7^xTbOUu^@}z;~Iu_Rq7_WxpfA)6H)FqCMJ?@v>|sAX<52 zZ&$VW3T9N>EAK>wU&=jQK`nEzn2PA8q}1t&_3K;)bY{@Y@tVLYW!Mf+V0<#1FZ8OI z8C@*7*gH+!_X;>+?^LqbPFHcgT9>BW%x_J;REK&7o6mpyb7JVD^_-He`mlYNz~!U6 zoUEsK@GNHH>LZo9mz>D=jA4?dr~0t7n1JI0Tu$FqG<}vcLGqDF-DyfBcqTAO*;I8o zcuY|8(OV7@P#k;`F;V}J#5s&k%zQ#K2^3JB*qT%+yEz<9eG9T=`}oBb-u0_uLXVd6 zmZKEoNqb-AL%spkw<=>$;IG;NQR3_~og?gLo>r`{YULKxJm%V8oe8i&#QTsmoCWMLvLjj|3Z|NuIA3%#e0hPs@Y-zO5!q%uyHOw1< zQoJWU6Xwt2*3ggya^CXRREdN_-qO~fp#(AB%GOxQ1luf?^+{!EEQPX*U7W%YGgYLk zjG3|9Qs`S>m7)bOz?t|8&l zU2q@>QN2zSfR}B~4s< zmyp5m^#U%#CJURI)B2z#)fFh4`$w-8*qUSzmP_5{jQ7%{k3#eo)hj8VU;NqRUB(iv zhte5a2if2uEg!PbSyg>JcJ@#Na?NFZ7WSszvq{hEG|$j2qqhTXNkC1q5~Ew4`ZWr} z)z+JPJsNl2?I%Pb=b9n_;06ZY0|785K?igkFFW6CdwwSs&okUW|)P%>Fsrbu8?vXpWI)AZC15a|* z{^H>V4(4i_Tw2QM1?4CTQ?&UMhxvPyK!wqJnqguv2;f3?Otv{ zBi4{`83(^9;+BdSnIm-=aLNWhSK~JJ8E_&sZF6~1*n$^e9E(H6Iv8VWinGUh@1eJd z6UMskVIe4q?M|z(;@L=eP8)zwGbPlgSMRvq$JgLfOhPq1lF~8E5;eUS(wxl#mfhIX z>CMuYeO%IjX3@)@59uK-2iNYFS(#V|`|dWK@^0Tym_<=zh4xU$MKPuY>rwdnk(q_Y zQS1g3a1wqECQ_TIX(}cqvY99^D?KDq?yEj4b|wm_DoSCf7pf4b>aqQjQ-zz?YEULn z#hM4+|MH&Km2;NOR56=#ca{RGa?IH{D|Bf3vf;?-D$l5}A;@XZ&cd^y{nM$Nv1Wt* zr|C4y%SQBXlPXL+A12=-|2BhD9+om(xtn@-&OV7}GIMglrbjD%si>*N#zA|zvUc^1 z#B*Y!cJc$|8`5vbJ^(<_Y}G1bqw6lN(Zclqy+r)->>t**9TC|T*lMV>0T{L5Ruv7i z+?K%l3vfL17(8_7L?Q1fTo80Xj~f#K9n@)$tv!DGZ)9#JIBT%B?m~OgH8_RdvMUnl zh#68miv&Cji9{vuIb3InfN3{YJbH=rX&(?SP$GJo=MHXYsD!x()@d`<)GN931)vZnE?==klm zv#apz@#9`~3;4qc2LcjT0DuJiH$e55ZJ(32akV>-P&fSF@viCTK5nw-q4^p1x!ZwC zrc)*dFwUyRs^PSer=smoTbO5~XZS1Eh`e+xqA|&`NM(%K9&`Z&I9o0?$p3>0oT8Ub z1KvuX_AFr69?Z6v)D1z8iGiZ;E(HS4kecjh02{VE3Za_ZrFVn#+t3bcMl`KG=|yj! z8&uT}pH~#o6{Vc0@+=)IBfU6*N*>rsjC_8`u?%&`UJ|Z!enHR-Bv(|19O8)F{_%|u zdCiXc3w2#$z$hPEqVznjrP=+Tms#bR+2Nn-PAl4@+Uu)}ZL_b#ud`S;4Y&WUG9M|g zdERW^(B9kL7a?H4O~9SO*C9LuLIcPHlmoIw$mZDU`SCf{c-xuZXi-Dq!!sf=L)rfj zMvzCSM*a(3p9wRcujg7pN{T2nTK-_1_#R$cT8?u%Azqzojj{S~q8j>)K%po0wPoV; z3egK)ulMm5?kzt{nXxp0UsAx3jKvWin5P-{-7gl!bxzA+>pg@vjCCB##b*)^p090^#J|F1e>7437==|84J0oO z^T=yCA|4DC_|^lFvnmJxO#P3;MmaoTKd_6_;`p!GK5S@*XNYF~*qp{UH=2tqHAl}3 zwiQ>%d#oAPKqzN4HE^oVUvfSp&qAvTdK?71=)>Us9X*h|BXLzHDxOE3i+me8-|w=6 z>=5-NiAj+j!|Vq0|Aw6^i}gYYYpC)GEJ+|VhZ6k1+% zU09-^Y{Q>5nM-nKl)~4QPb#GpQZryJ1@LfmOFR&Fs&b!cH&1Nhw90T^<0i6)I)Ju?%z|8nf`)E_^bKMO<_`1-j8SA^Wxb=j zW6%+>4pa~;6>X1QkFA<+oi@KSzq7uxEcYmPh=@L}QKZAb!)zn6!@0!1#A_OOeky$m z5iJz$66LI+Tc+Zod8V3YXJd6{xJO$E1WW|UY>PLe5eAuU%RM1?27SW$LkkXlCDi1Y z{Z~Ue)6-d{X6x70K3e{lwDH<{Rz(^>8f{d*oAfij&aW=AF2t$gHl!@JEVC@xD#a?! zDoe(7-SrUEGvYPdbOt9J19+(IGp+|>1GVV!2gT{-6zoZ8QzPq^P66fU3b&A=aqpELKnoo_<)j$ z3Q>dj`m{bP;XiT2z}T=IbBL7y`5f9KFoxe_Te!_I7r$Ti8BLdZX|L71kh2Fku9e?V zKFM(;34i&kkRV9n%>=-cpbg{ikOi8P39-j@?2)xd6UH^|6~~AlF_vRC!i5Cg_S$T> zT%}Uvr<(I?g{kF7n)9rLBj(2+@tzbV;DWf;Wgll}@3_6`)G+YEYzDG+6dm$7)j^^D zZc6R6o# zZ|3-5Qet3cW9EpJ)Ty~$eLvrRF!t;`udeYP?=;@5%U;et^Zf)XOm?qw14~ec6#U`- zn&qmf_=`*&9T{8S6kgF19iylF!q$#wy*=uFt-W)#`J&DDadCZp{oVUDb8-Ff$=3`U z%cW~$2l|wE@|D-_o%kkH$e-A1IOIEIE*UHgy#eu`>S>$17M!41BxP};0i<5LK)i0x zmv=KXv!Li~emVa7My@w_PRN7j!|mc8vn-+SqCbXLhlj3JWRY{eizILa$t4UB?Bi&O zX%e^Im-S{%6S03*OSoB}b!jz)!ovulZtQ^evKn~cxa42=(72bbm-9 z7nzgwGAX$ZTQbwCs$J`mNB*t(u8>}#!igR({sya6Qg0l^5ns2p>`?7wJf?CNCbs>o zd1FhMW8vWAQ%gY1@^cNkW@Ro?3V~x4C6o1}IK5QDD5J=|(09v?Wj#(_MD@m8B(I_( z3h<-(gM~}-gL0eXyB^ixtpP@y=iA4ZS_g}$h2`ONWj_$NEL#S}M^S`u#bPZHu6t~1 zxE-u8*lJTT8Zf{m*E1C2y3TUHZ?{>`&GoH%MvqI#Mzta0)!Phl*loD4Vw2{$K^GgjSTX|$B;!z<2Uji$o z_&rj}vN+zS-Ner-l9<7NBuS*#zAIE$=26rdW0E*uS6it%mslYSv$8Y6rCqy{cMD)EAP-UiAK%*c*O$-Kv9)fgq|RqoO>buok{CB?btTU|s6`Zk78eGh zhVB~385~2R%OZRIk)%mHdGUkw zY$o0W?rdADk;W8&5BL4pi7bIWeLa;Cp|=fRx25OM-boyYolcz0haMXg30&}T`rtI0Wv$LtkP z{YLp5O=AveQb0F;cPHU{8^Aa^;%1TXX7QEZh+V9w(O2;vaiNCzP-zh*>M@K~h0t|F@XIf+ zOHnf38uVyJxnNQ>879RpPda?URiIvzCoekgCPL@QNaFQ&VygcAo|0E4;%HrDa{D8Y zWik;ofzK2=OJWvw8iild=He-u1%<>0UO#>pZC&8CX}ssePX9JvVeqn=*U8cQz*w+Z3-sC}R}qhurSex|WgQu5+2 zBIvSO4Td|li&@Nvv;5(&InF@WY}}I=pXxry1je#RC>aTHhj3pQ^f;9fCo-0wuX;Z? z${!F73kA0 z*-FqlqE;%Cas$Yzox+mVk>PGIr0kqr0x9M66g(0$z&AJFfKJi2;~q9M2~g8GB7avb zTZy72c6&21eE!$@hTp3F_Z?<`#bfBddby_!b_>Mvf~3vI&iy^v@Suwc>FxJbo$hDJNFCut90ECUDB~M~hSfKB(FYaL{HHbQvA+d4hQCs}*;~B4&ffOov$2O>TJB{( zpMxGhvpL1)1YZ2qzF~F#a4fI1M8<*N!pavv^G^LM1j}r8Vk7xGeNy40EhGOEubbIt zj9|tZl`!(M9K{KJ4Ksuw=trL`iQurRzOV{`c*JwlZ|$^+tt<3O9y2$|I!R+BS!*c zgL<=L*$H`1DwG^UX?$|Z>k=(NYC)_fViX-+KlHllTyqw63TPRau+(8Uzq>`aWOuNt zsA%RYt54CbX4nT>O2dY!Hdf-YFsk;=HzCr!O{o^CY7@-Kl^4gbY*w+*MCwLkSJ}L) z&d7ccUapmc+7d`vwJK=t6ls*RerfjW*8z+DH9$G}QI>n7c$=qS*qsX5hv&O_yW2}T z5bN7Cf79Bm9jrnn+_UE6Ad9MuEfI$1#R}DR{lCDd|y7X zsUwT4=P^3^=P+4$Nhr3He(y;$$%s_EpMO)rt8A2{s$#jhrj8I-`IytImXV_Qb7*W3 z*#8BeVy3r`+|)qdyNgWPrqR+uhtH16ecx0qw(vF7Q{U_<=zHanI$pVKaAfmBySMmW zRiIchDyuCJ@1VTjsQUv4^xz@?Ov1STw?Rx?#2t3KZqL|EuC~0tbE)w@?I81tS)Kc$ zp4&3huUjL2IyVbwJSsPRkRK95Ak~ip@hQ*GXc0MMi0Uqt*5AV zYI&OJmbKPo=&n5z72BAMXqWK)%T@gTGNJ|eR<_n%toC|xlcG>oQ7d)-Evrnr2!a^j^q zo?^n#eFc8_%|kg<)rl)Rs`H6Ca48)WG+lzZ^y4#dVo27=T`cu;`&7;^av42}8CA5P ziedTLqk1$W4MWOMOEqsG`8gQ|Cl#gn(0c>3ZCJ1}f7D`fqYH)Jgu-s?`o;AtY{ zjd_nvOQ(irQQBn^C<00re0@>G{PAnbYODYPGiXhe-+1~c#Iq7%1RB%8KevZg-7kx@ zq?9HJDiTkO&*sWy8szH$YgPAAB;u}Hb$3+$a-8c3#7#@8s|iSd1T9lAwUEO`Ggyhs z^c&d%tMmH7qU z28K_d+U)f-0A<(KRv~#kUZfcU4Pq!Y6nZT(bJDmal8dpBhZZma6>*^_s>uENXZ8+e=*#BK?$anvkRVNRP;T0yw-*4R^~zWE|ZlLp?U z%L}V;jFPG03$5#)jpp&ZKm%;*n*p-jQGZ;IA`R%Kwwnrg{Wbvget)ad@_J__`>7CD zwG~gkOj(CC#%SCZVpQz?mGK`v|C#Ii`f;J>LX@%Ey+X!Iw`~z*C#*s1^FZ)@)b)8^93#-ikqc4U@v#dp2FS-XGX?J{}bpUV&dca{2U z52N{2ytZxJj%w_;9qz)`KZ6X`=pT7G7}ERY(UWFWbwe4Kr89@#F}@ZzFIJTNM4oi4 zkByTC4Y>5rCf?B|)FRl`0m?P$;7GLcwI(Zhd3+KQ)`+p4j8)5Vr2MVvWb* z;K9QSF;mHvWn7kanQ(*=t3TYx~B>$L+`A$7EZ!jj(V0eGj(@ppHvRWhPZ? zYI$WIe8=Wh=PkXmm)=`1AZ~%M1!wdGS3xu5z5_1=g}1~H0rmoKuC1VlXN97z1Cj7i zlUwha{hTCnT#~>jaCYQh16KNVdu7uE)g^D-FJ!G~?9%71Ii3dbdr+;~*L+6^Ouu}H zyrDWYaLksG&yyX$?zwIu&!H3D-x*&}2f89VWv?ynVs>0}4)?FG?s1TJHPsuuqh}@s zavrHa#6Th!dY<6G^G_xZY0VJ4>GwouhT=q@JgvAtFMj*@x*__E?Ju~>`sleUGDaV~ z!;>ZLF5Nl()zc!%(TYA=vJ>R-#i_ZfwH9nRDY@E|-wrrd~ z`akSiR*r^m_E|j_6(kz}MALzrU8CIM{@y3{K+vInX7%`98RG@M4u&PkAGGn!%<0hX z!(BjadNRv>k#ND=W&2%Ro6H+tMZPtR9lr zFd%3hk`})UH80flkqq;*)?9DF=wWi>hG+2!NgVIx(KePUV6smUbn&8Rd#gn3hk^jw zC4yNNj3Tu^AVoDM06MxNK(?3Zy=4lGy|*O>#Sk)9k;M2z1&c1wF;}?xCeH54U$qa5 zjye2?S=)L!uxCwM$tLNtLW{qQQzzQfWP!!+;y0fC<>>kS^FwtK5k2As`;Ed;I$0Ho zg2SZZrgf^I>z@aNIfdFY!N)j8M+GIKI_x9cgXVSWyP~k<+47SBLh?z;^WtfdM294V z!j8&2Uu-_|73~tDdf7Z4xkHRRJ}+HoL)}fZcWq6+kk)ul4er)DqXjO70cDHmBSk{I=>kXOck^G)CgaZ(yR75km@{3BsNjS>lSBk%+R$I z;$;u=G4rB~MO7c7Qy0tO>#=lAc4vf{UW<1y@Uy@}S*L;n!`sE#!zEv%gq!bq?`{0y zJiUq+*t+NB{pxS1Hkb;TKdG;Ma8EfV1sbz;ApCs1c^w~vDwD}Qy`uCgXbx(K`#ef3bw7e?wc>GwP5$mi(Ey*XX`8a!h1pAQL) z$!?U3cE^FCS>nN;s`FM`_#;TU9NnS)e*AtHIr3AK)0ttHf{!#`+Jzy2#0SVu_QK^W zsPBT{Ln?;j=;ypdJ+14qd?g(C{I5nGL6ybjmc0{+D^L@PDOiOMyC&TG>XZvSOs?dg z9$9*(w*o=VZC|>!B=@-}>>U;LStXTHU(HQ)W&KC9y0HoU@F%X=!y3{u9qotau`=`1 zdpY4>;Ln5${lf8&_*FHRa{0!G+3Z(&YoHp<++v@-JnY^LwoeFVBgn4D$fEyKOwUrpt?lh}Hqx*iPq2%kSkmqq+Y!=_+W$xz% zj$hsQTR*|s!K3_dmIyk2C(p?rt5frRe3Uxg{x(XJ4?jQNt4@cA_(4ax*B-~1DHTjr zvNwD?D4zC2sgGaA3lCFemMDA2B#R2|D&jyOPhPO|Ci$%FP*9G=Us^xe&2Z6u*mtbY zm1fniv$XKnex_{fxyP;aVvBm)$;n78ga_U1>@-U!O9#9Dsf{BWk7x4WZi&w0Xdww{ zryY8IBe#|V@9y9jw+N7O-vfL)N$z=}#(&fGp3CKQrc%_GID?Q4Q$ei!0WBJTj?%tFmdELu>lS@oK!9+m@rk%ZApRB5R*2V0HRSMeu% zUIP54yVYTBRwVs&YxU~#9MSpNq-X}%;`XWNakI1cWWT)H4Jhg3>COq&n-U?*ZM~vj77O zaVmKD@`!KCV9k?ST2fWNoDV~O|Mg4>8Jeu<-JDv-yknbZWOKsj@Sl^Pb3Q z7$k6EB>YSLzTJD$j(tcckpEWqw6^Ylo3|^vxUKW6q649bTp%LLAC5d*)U_9K=7s5z zc7pb!{qr{$VTJt7mv8kVdqxB?CX_uG1#n%ovrk6X#iU%u-n<_1Om$RCSPJwIWWP@r ze>wQ3rOF=5&m(TS(rk-CTNcqM3#d}{iH7%e3cIDG+_~sp_kRQ@b`Hb#?)_>J5 zHv8>}yDd)ALPkJAs6 zrEZUM@*Rx~>v#i2)Ci)71>$hKlhkv^)A(5-UE}%vO|_Y!z*)!5%~qHQj~dt+V~1>Z ze3P8@dZVW`|F=V%$E;Sqj?%x-ufjhLuxP{^D|H$eI$4B7Urt3m24JtrF!>se>CnYw zo~2_ctj-HRqj4<%G1hiBm5)6lk005kn9=a{v&PcIEBSh@11>51*Y%*>Ug{;k8g&hXw?)5xa zf3KHBZk;CU3s;?ZlGsEEJRfc&#^~vBB&e3!Ru1ZGN+{8+tD2H$uLwSui0i8v6yFy+7WyxeM{=k zunHsV7x^OZ$d#|%56ueo@Oe>Fi`9}&wG{mraJ{|0ojFrSUan}*^-RNp^0E;N-R)0L zd<|C#iHJO>bk}S#bF|g_^`6(ht#|S*@ZNW|kkGCgSI+H8^DLC>dAy_{WD|uIRk23{ zD}t&Vb#!iD2AH`^-Jo8smb}9*E55nXQmZ@jh>~TCRRwvBm^JTihBgQl6yV*Q1YkH8_9e0e;1irJq_N!{q-_!xFR#SB0=(wv{JL^ zwd8fl??iWz_ar}xUdL8k%FOjvGA4~F>HPAG@^dj39vx@-xqtk}Y6&`?VS{zKA$DrJ zGxz%}M7L%>M7MmE5lfxJ^G0lp!E#hv!snV2)s{SA&c|rE65RnI(!tvsN_!nTuu4+L z&Nj2@b81I2$Q^g8AQ z%=R!#yvOE-Dk(8D0rp_M#oR>`NhxN?cLwmB;kV6XZ}I0O3yaGwhiF&#(LiA+6f9

=K7)cy&MM-4KyhJcQOumB9&yWI zax21{n5>+m#p zo^s^v+eG`FlFy(AVX$g@E2Jeqie3jfv0W=mQKE;TPip@ZdLs;QZ=(Jay0=@X|2`qa z20yKgU+G5&L-?rT8N6qrxk*0Gb}`PHs&0oC$zMdThbGBq(Q6eyie9JqchNnH--+&0 z{9W{B$Vxtg9+cZ#8qss;hB;1HC)USPwSBkJPaeHj@d$dq+&|ztsQqhm=t&4xT+3(^ z=xMlHa&|q~F4jLP++gj|b?{YfZ-pkw=g^bjk^Crn9k|4k#~dC1dn7;-><9qyePpaT zi4sl`yv-hVvE{cYEfzogG#^dTKy7wItV{0>#c9HJ!?IlI>ka>tTrs@v#^Lq87gO-x zOX7Q$(1dLuFc4Z2-(IAV+s?t#`@@~k*mZj8*;A%Bb(dc2GoODf1%4;&XX!JLZlCn| z`(lqdE_?#2{=f-ME7z=9NrS$S9KN+ zAHI0nf$38ZOdmLt-WNv#9Ydu*8(7-gnd=^)N#Wla?9bo+u1 zj%${aMGv#U)QI&yTm%zm%dKIMk=Y> zC3H)xjSidxsJ~>((-n^uBO*D{ejweI0?w-WZ zNWJUa-F9ndrYV;4M+c4U@@TXtogeIK_vVNDUOeqIJ_U`Zkaufu5C=&sS9r^DBgs%; zS9)*4(tL1XI9Yqc%dYo@=Uks%u`s7xF4OI$S?ZbYv%L6Be3h7PRXj|7z`Xn}OG#U{ zpnK?N{W{*>P}=J}(ZhTc#w5>>r@03!=Q7eQ&SlQ3ZiiOMXVGgREctiQJ&>0CPIMRO zlE01agSh1HqBrw9LZF`3R>3Pwb-Qh0Rqf|zyIUeD>G`{m8LFQ3*1X*zEUC2)`xYHH z`;8-g5l33D%yh7Z&f^j-i~gtq&vC}1!+8U=t;<+AJ!(&)9|X~ z?CN%f*z-NuKW&e$L%wQzD?}xqLr+3X@}uZ=kdnrE6vtC1=Ealp{FB%##`CD;v*@*O zr{v#7_rM)h`?12M!tEO2-Y@#^mHfNt9*9Uji(aevQ|OHlGQCt{$$4}g?kxX6-L724 z5I%>V1h3>r(Z$`JnVIMP7-IYu$!E}me=0Yl`J~UnX&N+L>PVcn)x+Isr%`GyH zdLzL)6+-kXp(6irR2&l*V4H}HR(vQyVx!(U+t#y1u5p=+5{25Mv2|$Ga#UEP4Hidz z=j_uOw7oI1wc8vDbipE5e};$cZtKj-Aub{?08(0RLyIHZ92j%kOByeUDf|t9 z#)3tpvB_+DSn%6K-uS%FX;3IMB+4)rT8uJalR+rdC|qm0b4}ENyd4DUT0d&daoycf zALj^t{7U4PEiK>+fp_H8GJ!Ghj(+q}E0Zs~ELVG`*;#5@smyWm6`*zKgq-ABoTK<- z*G@z3X8scD2f+Ik0rgss#=^*zYW%$FqnB6ztikr?%BU0umC-WYk3W3jHDst?bE{R) zf?93(4{G)C;{Bi3^xx|PwS|wZ_P^gfPQZx+z=<^<&xwD(1O2B=__$v7Z!qBB?SRYc zPg54?i=V~!f!6JzAa0;FF!^TVO6u=#dLu71UZFCLy?epi<=;sEvE|@imH6qvM{>of#cnD$SbFS|l9PJxX`OWsC%^H@EeScV;^=O04 z#@c_o)26J~)13^DS}iH`HI35Q8;PcKK})9Q;Pdq+sYc>Wr6$weTYVU#$Y`*0xWAZP z5z>Tht`=uvzC|7kD!TV(wNaz|p-`*UG3obqg{>w>k+nJ@u(Z$OLzIfFqbC#-29Rm4 zg(WLb4A8}{yu+SzxpHgYIh;Ora7PAh}(^%%Zp`Ra1cr4X)so^AJQYFA&4&_#GAC%Lxv3*WHc==B=?!#=cK z%FX>JbPCWz{~-4q-2(Km2=2)W&)-4`0`$ng*n2-be+FLy_m3WB?}KpvG)e!(_t^Uk zr2ip#{w1b??Y{0zN#m}p~s@F%}|SnF#I2 zYqQXXulh&)2CvruKWK*pG83M^0JM@7*7>F&gpe2vGWDBtZiFsg^~~asY0s(=UCDvQIszl^vGdE7eoXiH9L`*iYr{}11XiTD^GkL z(4Vdx%BVB0j2gYRW3u)p3YB-%PJQ7U-}puj-CWy?{E&h4(dR%`U66;6dn~nXVL(k34qp6ZXJta{W}`<*P7+H}^_)w%rDZfh{l+4NNs{vb;)tm8!KNDG&lYU16A^B{bDn2X10pL?}6!+4RLVFx_6;gd@ zc<{(U$z>NPGUK_KY<{kN({A+Ka8FPu6Yk$Va>a&w&awMrS8h)yrrRp(vR5zZ9uhlF zHtC)U{&#iH_thCI+wcD%{=O<>BV8YqkJA;=>Y@J!N9}HROv|uJAkbl{Jyr^_dSJYW zy6f7<7fI{71H1Y_A9#X!eQ$6#r+r*N*$dc8Dao3tW3&yu%$f)U|0=P1rc|7-ROWj; zC6}}4^%kA3k_TH`4$RH%FO~Ms%^hf|y}o8X7~C?mW=klvg+gRUk*{N8L+>neFNA|H zDQJYQCbr`m^s9p8+WVGF$6GR1lgALp!alfX@jw4weZP%&Fx}u0 z`WPM|U1e8y_pVB1Pj~m8sZf{S*AWVJ`21a=k75$1ov;5eF10_epc~rxBJ`UaaA`?7 zzeRL&0lt0&RQgV+oBa*ttiW~UTnLQ@d%If_a;I7?F&k7Ck)UmDdd(_be5jz$T2Zyb z-Q{i>Pvr76uhZ+&C_z83s#+7tN>m-vPt@l~8~_b%!C=8jOw|T_eGMDn{t8SM?m6uQ_g^HD6f30v3VHq|@|@EXaQ|iUJPz&f0>S?k>as;kc`v1z zE{gg5MLJi+$b{Wmtvk#ZBQD*Uxw$q^>rgN_(&~kNGPUl^Zi}V+%yl#SIxObSeMdWQ zJa^M&6F%R>Wt+~uv9r-4m*YD>%3hvT`y#QIr?NiJcbj~k^QBAn^4@>jUJkkj`dNFa z)PTKotLygCw|YohcB1i)=%jDO1+DGF#9q2`-LB0e(aDp>^exUMdwK8wyS-G1OlFlu zsMrSfvbQoabd0_19cAt1{=Q13igDKIROvg~*AC`a8&tDh`PGZ|a%E@d*rL6>>tpQY zo)@2g{`nlby|xvlmh9zi|G(|!K)Bgn{;+d%k+YX;2S+EtUX~{wk?rE_@Fn1 zRt_AwP;&4>Rc36_R{mnFFDTYZ&f2}=>dp5bwEH86PD&=%R;qKk>wr&V3-3^`QU@t1 z7dPZ;d!s!RvcpFnw%NmByDiM}RIuQrUWBwd;Aw-7fPZPR%ZsJyq#`q_@#!=Uhr*^6 z@NKPI2Q+T;V9}=XY0W;FTI*R@sF#WUf&=JfK)aI?u)hEY{Kvpw0XRud=b&6a3#Z^I zijr9-FXL$v3tj>EeuVFXI+&N&f^LkE)v5e1i{Edt_<53v z?y_FK{c`wkb=jd*z?z_bg#L(y=$Al6g_QFalyh&r94(8R6Im_!E|4{F0K9Ig9HpdQ z4!*Zh(9ynS1!1ZaWN3n%)1?`fJ`j(MoUG7 z?82zkYH^PCCl;%QURm#yNpz+{*ya>7cDY8I*7`Jz$f9LTLfTzk0ks7xl4w2X4k2Pk zgWCyRZvkER*6Bh`wWYHKVkWuT3WZH;0fliINtXz7Do;Sz5-)20Cdv$U#c`C8eOuAz zscZ4CC=JJR1!fyGP6H*gMhjmg#8RIW3q^b@{*~ROOy=UUzCKwzmsFB=Wb>mI$nQtL zB~tTSvO*J4KJ+!}n-Iy-HqF;0m8i!seExQy)*DmX7?snaw8#|L5M9w_wAeC1v(~G% z+r&~gV9@}U`#CHp=o9z*D}JpvuCf`_9G2@N;~W;9r;Y_^1X|G5fW?n~&(a9r->=W{ z0r-9b{{w;lp#fi*r|ze2#4Ln5dQTmK_7li!ECeXCQ)xt_r`Vl2>cfxBpPqZpc;k)f z2XYTs?tcJMn5i_iP*0&{r)n1hX_5jx#U^>+ekh4xc@EO}5m^-i-_H;VATN5F!2d$v ze*rjYE$S7dLRN}~QX#?<{NpQ~oelU)4Y*4mL=UhJ2%P3M!ST-*;po}s^tS^X%H`5y z0eZWx8xS9K#tm3VbcP0UhN+j42z`~+XoaTUbW60WD+-^N+tcYvC7o`s`>KzlmnaHy zzeQ2C-%<$rcomiLpDATMy2A+T-HlP;Bi61K^GRE`o@8$6vLeHZE3aM2Y<~Un%U|Ej zti1M0G8zndX)bS;j6snu0glJRADef6VI%V3?^9ZCMq~3X+n#)W8^TYVis0|mConqv z=GdplLh|axoo{wr+#wH*93k^67dBEquVc_cJ~Brk%dI)g2m~*)7%*n@qigC2Ixbp5 z02~Jj%8)+_`E$ey66Vzj(Jh%kjwY71Bvr7zsMnA8#VpyFA(~1>4Y8~x);F%#7ZDDM z5qy^4sX{$Y1l}b92_N}FeOF#!JE#dxli$BiNZ-?@e_41LP6iNCbRD%?g zYuMxZq)O7LBo#`2I050HDDJnk_lF4qt_Vv&heTRs35Yrg0il6*i!VVWeFLJ=yI24+ z9wQRIfm$HijDKxz;Nw+7ilN()T17mU_|>KJM{|#PC38)j-~&LaQb{;LG5jJ_mGi z_O6*wLZBV9Bzx*Qfl#|dC3z8o$}$2WEzKHBTC>4m)|QM}k(95HTjUCvENd+4Oa_BV zS2SiNv`ApY&*{y|SWJh`S{_(PdGxIX(><202rQT6|tDotS407 zL8zSnXetHA02vnA@UV}e{Xeb`Un**bNNJ%UqB9Caw4}L;GTFaZWoI&KvBZ+DB}i5g zjVY6iNg0bmLY~Z6XF|F?7_6j@X9^h&z7;(VUR0GDCwy5Pe)7AyJs}Otz4*o50u5=- zn`bLrApFsiAqp1e4-iF!gzkv6t~CojJv-Q>0q=GOQ1LE$k=pBGd#(- zLkX)P+7?@ph~zyT;aXN^Q>$b8aNK0GyJGf;qi$u+!(nbuay4nBhLR>)ALv%2*4YcY z$8Xs3)GR^>Phf=i)cmOHjN#GKs$|9NLnEIW8NPK4tRxM3;w}6lzK_IPD#wm#fEZ5~>eA8COQ)tT8Oy9Yym8}g>(<@2apU22XrI)fl1AxV2fSxz zW(v-n4M(I3i>xp_fX3&p8XmrCZtn8Ifh*>A-8wmW>#kjgSFSvq;|uyWShKS&EweeP zdPBdEKeb}TB*j}sb&4Hd_bt&(nv6MS2UxmcGCUrA{aA^Dr*S&L{zZy`dLXqy_G@?c z4ZBCGs_Iu;H@Hl>c+|8=BhVXMd3e_%shIL~mt7_IW}(X^Ksow>R3I8<=|pYl^Z0v& z&Niy&-{7yFliLQJxrVV5vb~a{xg$0djSa=%e{?A3DXh)q*A@zE^My5elvc~NYFf;5 zD6I1~+XipYVDSq@Yvgi+2Jt`8ow;myCS+jB7MxXCW z-zLpmU}wNx`w>P0>=w0z4ux7o__k-BvC@CwS*^UUzVhP30;^T^HX}{QTLMs1m)YxP_CXaeoDqm0+}B**Kz}MBBJ|GhC{AybZ;A3<-BkX;(Q1 zGRP7y2prvkP*&#ED+xlOl z;jY1F<_z|~Xq1I5ze;#~v9_M#Nh>oZqpJ36UnsR><=XSQJNI6{V&cF=&|x>|#*chr z?#{D&SKYL^e@C~o9*4Xi>h%jOz-DTYTXph2zJj7jOgmHX&;?H}Lp~WHH!XvFJOz*N z{=>S%JFRQC>DF$yBrJ#FGqY8h3|J6=yw-@Y1yVqL{g{pW@->}6p+}A&3u?$@nnH}h#jYMYq z2WBIzPVGeZpccB7l91RVckGOC>`L+UKh})UR;QqLL}jz7P(Z+@PD1J~pvVrXbH_#* z8%7uIGy43xXf)^%$b}N2Mq!lmCUPA`ODUH57P==r6B+dTg9rs|dSfPC4cc;T;Y2Us zU#xM8#1>D8UAPojRSND5-2zd=UeKMAhdh%lR>QIJB#g$U6&C81gePNdWPN?k=;fcZ1>JFh#P8U=euvkM0(XxUyT@R5A8&l6$dfKs(KlkrM8GsYu%)wm!%%tm5Z|U+ z)8ZiGw?)#*IZ6oFwH^{d+FuNH`Ie}tn;U~8X&CC(Si=K{NW%;fOL^G4gzV;<>Vmn zi-t%p7Y9i|nr?Iz%O4Js0>}`$h2;+iDH6%KWYxlL)Jy0|mOmUM2#|XSB+Nm&7XC)vL9Ju?!$CX?7gM(rNVHK?>Rr@> z57qgzFh%%t6t&>%SpIO3BtW`I8V7+i=W=ooC!`r7xm+A10cpB1+ZJvPk^;yOW^3x< zAVq?iP2+7!(@8MXdn|1l`e^1mHcAaaf7X-++RWWIK?pFd7;4J5UyS+avp)X9mE!23OKZs zrGAFy^06sa3o;%(@fjL#3eIoz^(RW*E$*?-M@l5e!MusOz@T`DA6T(7Lty zaOs?EuDW6ckegoD(YZd&Qp&5{zGiCW421};GXNK0LS(mDHMgBQ*;$hOqOl;q_JvXj z_3(p=>(`2$PSM&=V`evtNa)->bYu3)%x5SL*G|Bthnpq@q>Tt#)TKBy2l>St+MWP> zeLVasVHVWE>l#_{b@;G2WnZBO6yqP)a5a%d+K-0$xi?U*kVwsZ~W>9Er2?N~k4 z>$2f#my3U$FTc6Fb93Idaa6u${rXwSB^-@^02(bE_PVEtuieXD!W5EkAP-W;QJ~RVuUck_-3RO)CCh72;!(zN>$WjS$*Ypu6AE))UFT^ zE~`}`&^R~(N#pbRmahVVt)GeB*tO-NB=i-*oz*Q%ReSPD_!gh>bAhwbvbzAUd`U`3 zRWqn7EU0~@RC=uC8tgsL$XvS{@|e**I171s00 zbAA55+fbPvsy&Oci!8I$9!Kr9*I1E3lL8W>N1sK{09GBrnhP9z&ZT4TFM5s?!PVm8W`A^ZutFY0j+BChSwZ8ApwboenDsXSM_Vz9&!Jw zsYg7PN*+J&ZT0SNG)9;6>xIY~LbH#fIr`x=H=kHZB6269KQR)c<35Q=DS_ZvTQ?mU zik+Y`9kY3%H^k$)C6d0JC^uVOtk?gbyP;k}vM(N23tukNd^RO_DBNO=U(7_a$=YAP zHZ+-Pad;&9vfknLiS=Ty-(3EBi4NYDbPdzaV#?Dh5hg+dBB#jg9&=f5;d%~f`NOCT zwGTJmRhGvqP8_Z<9F8V^-bf@p+3qeF_))ph>WO=ufkJAg+udvAMdd07`liEbcW8}F zDUz?MmDBw)m&NK;>uvc+wyIXG8x{)L^3~9q7ZK}2Y3pGcPUt*BH6QKZhvXZoPgmE& z1|g@PK2f`y5I#N8p!{jbY2x}kw+_25yxgF0&h}Wfn9LPAK2@CQ>03*B`O^cH>dMVLd0_ z2RT3LWE%AA>x;WQJ9oJE<-S-Poo#!xvTlSWMO?cGyYJ%KYz}ZV&WWV!TdHe4onb!8 z|MdxVL{R(EUq1&;X06>eak>?4X62jnL%!LPu7e zT&|QlbXF(d9CrG%@m{50Yw^f65}rY6=ZgkP#oSk&TBX^nvP=9%^hbwM&SH#Jo+suh+$@DE@QilTFpp$0LJ$xJa`i*;^n@BAw~Y_c z259$qxe(y*Oy*9OGbw9!q&MQ!2N|8;;ELn^$yJfC*eXW*1Xer$F#|I;)0fq#?^mg_ z?3f~y1S`Htq~^pYKr&ok|8}U@5_d;b8hLlRcPc&@PWJExRu#kN%keX9?Ugo@Q5sH8 zkLHGgS-;(Av+~%Q*Z}_lsELg7F6y*Gj=XT6Xj?Yua`Q}p(RsCDmoIsbP@lBB+XBH3 zza^~A?U7_~Z!)J-sqXh?Ur#U=&tSPU=w%EC*_zeHB^D@=)TjzI5>qZxCn0w@yt{d- zl4ntie$A2>oNiKut^KQ_{gKij#xLV?+#S`ZHJ$jGXp2_ua@Ss5J(eC054K7)qEf-c z$b$*CuNpx5eDt-X93r|Oy3hr}LC-vt$>sSbi#BaE`S?h$Rv48Ml}Ii}Gt=lPyIuST zpCHp})~U1_6{Ay0L~>1QEc|;mf}%w#v=aZBobA~C(PumQn|I3MgxOENmo~~GNp82f zKr6Z&xAl};+(VKMMNe5_k;)AAo=S1es*z5sTc^>Rat8}VtEbeusz*akE<^EaGoXaPPIpJTIy3B{hQ+J=7O1fGdX%5#Qod*g${>k@QB!c zbEu!=4OPcTeH}11M`{U<#hjB(sTuI%RzYvcz)iZjalp{)mfv$X%g$3o&(6mGCuuZm zV@4D^!d^s;(Id&+yi{Z=Ih--li2Lqg3%oVrGHQ7ee&dGGJ|=FoL5thrbbB0ideBus zj}7QKPFkAFM>w8{{ZEoHhf^Rm*?FnZQfkPH_){Twn8hx7fyG|(SSj3i+XTLt*%n^x zLV;tP!N=AnqLD-*5*moZz-4$K9v{TdT-05yc6W7nf`hr-P#`$OPUQ!j3{s(eB$DL; zdO0?+c!h-PORVCyvD2e?#AWas!ai4g%Y)h67Kw;SIou`hcroY4J$+fN=3a011-o5> zPGTufm@S@x(&Vbx4Ry_?Lgzwhvc{}OqDt993*2kYGQC}xPdJ#MK_4fSi; zU98Sq6;_^6t2gj;77==?!S?Y`TxHN18NSNLkQo#%XaNmi4FcB1GYXG)^q@jZj^0)F zloHu65*Y~q@>0Xbi*k{IM_dBo;S=E~|MUcDOAMuSkyXib68cYMM% zvthubfjaERf2eb&j;dj}gaLw*y*=NiW#WeLc0pvbB-0U1g}32fJsGo`G+z=~WP;k8 z61%Xyv(WxokyQ#fDfAgMjekXazUI>inZk<~22Zi?58jm->%-rKFh}hV$i(*gC%-|} z^IpCjqXYv>CW?^(+Ov$MIZyGo(*XEQ zStM1-4FiUcq-BLwt&j;#x=QOu(1Ix+x(|8qeO!FLX={k)xwp5&5>YSv$qo%=;e&n% z1I(<5WWC^0^!B!tdx-x>orGS&0l+oX=zE+w$uDS*|n~-9EKWr}nvx2BqArGsIh3;s&i*q0}4QUbPMl zq}tn4>9)4CGp8dt0Pgd8A-$fY*X5j!Jp7mx1eeFdK2a%50LruNm07qN{Sb6n0(`PI ziehs9r42d!{w9b%crtCEe)#3ys1 z?pYq+q)@xXGPzMI*fP9n)wWbVS$Hp(ik45?idR&fmSBNLqxX5%nW5BJnqIqBFxH|{ zS%P_*M(<$H#>&9FcsmkDGrHf3%IKJhl3!(N|u_$1)OTwUgCPcjU62v6BUt?jAU~DqKIy>(BeW z!2r!ewbO9WD=&5O5pQC%3|%7KLLp)+e~b^Yqk$PRk21iXDR=yd^PJFuat2p~tVr?X zTIg-lGD~u*5FbrpnOkocDP($4yei{=OS^WLI-8yhp(ozJ%ofR6GX+EPvaELWO$xYC6C!edNd$7k0lhvhS>cC;QI5 z_D*!yT?p-{{d^ljH>CU1$RG{`B=FKKm9odX{v}QKq>Tx)G#Hecl18?;KQ4RL+~{Vg>9#c+;&@+GgJ`LHj~<|F_`5V8ULIMVBp+tvUWN{MG?~GOZ zb%8u{D?3=@SSJH6mPFa@_t2nv8WkX0Z21F3RJ0JPatmp=xJFeS%x~t>XtuFNNw{1nzz37gP9bWW1-=P;JM}Nx*a2M4iXIXBw z6Opoymo@TDq%BbtZr_3BqKP)X@OY8q;ctJP=A(xnl~q9M%(I}u0-B7dBe@8aYZ+mTO4F1}7?cIJ6_J42I*8b)E3iS6aTWX@9^c$J(%$LN$KRzrE z24#=H%|HI}g#646!S3#EiYB|+z77<*sR$>TX~F>o_B2U?;{dIvMn2QsqP0WXE8^ne_Jsf_+u*=`zz5YW;b75uWq=CAELP`YOT-zh67IfJyf_CeOgoHW(4CZn;> zX2K%BS#WZucDb0W*p|W?nAbp-+sIx{4Iw5nT`#|RGAB!dU`d`c&0Q6hHk_wx%_I2B zx9Kk0*f%YPE~&LjAsWH&npOYm_w1wJ{|Z*m36x^eKaI3#z5KjW(o#kyGfLB^oIg<1 zYOH}Q-aMC<8f7v@nqCj>on|{^X@L0K@bzb+T^q4f?$ks0G_6_`<_hd53kEj1uXXkgs6Zymhd~9P;DF~6TYKZ3&6Y#0*E1gYI zyhT|~K)$fuoftXUslE^x9M9F2+_%QX3yM`oX>AY z+Y43Y&3B`_?nLNTDY`|~4btA0O$!wwohF@XUlRE=U(8FZ-Kw<8p{o7F^l}Iq#D@SQr8 zX+x$jZ7X?#VIDslv{0BzFI~DG0=_VVcZ+J4o`BQUq)lm18q#^lw zu};%4Mbnidow;n+-ffBpuUUWXw0PYbG*BS&j?mGs(kWtg2Jja2$btV-;}*?-vGd&) z-Y5GGgvop~&eC{*CyVBU8#m!di-T@Wj#WB^KlzEEQkp@RT%@z`#wP?_1OBKcF{N-D z<7sI^>PY$hXsRuni6+x&b=;Q8j4PzY{1xH=PhfH1 zX+xA1XaBH&tUNXipXU*B+rtX2&~LQ$&4WS1T>rm{vQUm@4X|ttIqCI;z{Q^5==Jza zFb6+DJE7C3w`beJDp)w$E9X|ooI$K=UXFB~AP=%bg zP6-2uIpjb;a+pl`Hq*jF;~5s<2Px|Kd#Y#Q53~{T2JnMu4@JSRjWRAwQ9^7(FVt4o zQ}Fge3O|PR^(>r@5qKBmlyW&QAUW+6A~{{?Ns^)kQfRpp8|x_+{y|bW&<{xppoZ3Q zDXt(XoRo{h@ia-%0Vxz*itQYZ1(L$arD%f`PA zOH#B#3U@OOphL-}_$5iv4k;X5ihU%7n^JKpUL`43LJA3&Vw9xtQZ_Ed_iC%ji2x($ zecVA->=Eg$Pci+|^Ut?E|NO`=OF#Qr>6i79$QXJbZDre&UDA!-ud!=^V5RyU#xwOXks^QdO^iESk)B zeIhcP?wAWi)+VEU!SD!N`@^%TXm1Ghrz+uSy1&pHj;00*;dI+cnTg~;qFRiMq_g92 z)lrCyux;16@HV`mT|>#KXk*t*jx+(&aQB&P7Rd7-b7zBQ&J!zMkk{@5ajZ z%3w4+5Hp1xQfGg(u(8s2;MSIE&xNyUZF2VYwbOmODhz|B#Dn^mgPT+x#fLKHydRB3~Ll`7Ca;Pxa%JevtT zPTdG^;`Ten*PqkQzWpoJ2FuRQ@jLGrA3wQjbwCVEp*5sfJpoY)KdqodKuG=lN~^{G z7c;j`-@5-MTJga(=!R_VVf;6;ZgJsUYy-`u1UhqCn#?S7X=xV(3v_S)8U0SwW~u$( z|9*frSlUDfE2szUi9K|F?a|r;7rX$ugOL0GAa?}#e9XD3%?^6NwH$UaUW>m}j|kL$ zzZT=#cNec8d6=AmNLFw?45z?1E;|lZtIZI$ogEAB5D!wymao+@b?;SywM5{W50BRC znr7YHt~ug&Y6A}K6`7R|O+aUvQfZyVK7Z%%zMY14U$AU4Sy!MlPwo5WH@eEU{_|_b zbWUkk`nsZf2lm{s+P`MyNw03rMV*Y#kt91=yo=w4Se%-ilIluBg}J^+D$Uf(&9E&W z$8~z_Sg&`vS&lq{zATW0cUP*XglWDgbZWKx6X9&?(5it8HWmsSFBlj+e`De3H+g(C zD)_QY5>4k~JelAT!LQ@_woGe(c6NVn@BY~=`zzvoSs<>r=m+?G+(*vHVT3+VEIvkv za;Vq*Cfat-J+)ijG}oTTedd2?`qlq1BZ~p@Y@=eh9rH;ZJ)aMXi=BB=z)bBIm?-vTAkV3pJ^bpda}(?{>Fx8XDRC43G0L`>tCYKLow z(Iyln-|14uPKo4f5qHv z3U_RnecBTa_poV#*_nKPI+vTy=V!8P-zzNqgs$Kp11(~p-lcZY>Viux+=w?FJsduQ zw{3x{oQrSTa`g5iWEX}Aj-vNiTT(z7By^b(Rv;`q`auCbUh9+r#-=o)Mk+)vB}Djf zbfBIZol*M=%cY5h1#HDCVxf>81=Q=wW2~yx6tx8b=25sQji`|d`PhUUo~6XK+T*p0 zm(z-n2Nhg6$|k7^F%P|7>p)LPkENDNhqO&eYqiH}7jx-rS0FOqIK05FwI}rQQ4TR` z^cs1N5USUa!cA#Ji>de|A%|!&F~X0b1EeK>hF` z1^&#@^{mH6QqtS8ACvto@EdUQP#@6M0)4BWc9GG`0=q0&18Ncrg?@iar?+Y;-n=p} zduvC`H;HCLU6=Pgh*sXCdAxSU_jof8*LN;PKLv~)D7`)uq|Vqe!_9RJ5NRZ%5o8?5 zJ<_IeC>#PN9Sa3@Ho0CZGx=0r{YYOh-x_NX@bQ!_miD>F_zib|V74_|lPbw7GW@ys&{uu)9ywc2lywRRyo2c5}sz5{)p zdW0KY)HWT7A?#4ejB>`}&M=odmi3_-&S7@C`0CDe+KYCZllS>F=K2(5yC0S{C<@P@D;wf}8{w_eY zY#N}d2OvZEP-E3i4-(+1_I5UH3UY72zksw#4&MgsM=AUkK=d4>2M5q*{4PKk>QMr@ z7>^(+ehwf2YCx60YA(%=1ursEG&zIgJ_6YUkN_noC%Ju#rDEYAj!^}upAx750c~Es zR4_YQ9C|qe*J8`J5c6+C=>G0%T81gwuBQ3i(Fxp>!D~|?dxSU8lA+Xv*s+2?=dLv zJW}4V`MTmsy;ZI<=xvU6Cw?sz)2p>GXsLo2BIMhN;e0u0F#+5D>@q^;+;h)mE^=Rl z-Fx>M9(aJQ%gOjz>IQn6q+x_?D)oih3og)JNKc<;8XPp825HvecIvaxswTF4Qqks_ z$DEV$Sy4P>aw*kL9b=PN#L=+Ht$-VYO^OFwdUXn=E8>%sdv$V^Gwfqa9>y&Q)-ta<5swFGe(yb|KfyL&%smFg>~toLAoyFqzj(x0M6e;=NeCL zLUH_l<4HSp6Udzso)kDDh)3>HE-H`JX{4?r0 zddmrNUgwaOqp^bA!E?98Vr?#Zjno~9xTW@TAW$Z4Izn~f=U7XxZnC=8K)`DA`|*g^ zYW1=oilqG|$lKh9rTwMXYV&w(Y+Af93-!MpfA{zmb)Kf{9VU;*Wb}AmhmR4i@s!hK zbh(TsXX6(ztpdrphhA03L^tKmG+m#J4tULGJ}j*Wm#51^g~oyQcXDg{JFM3KF|qp%*FE?Paf&da+_1 zE?i^L>C{5A=5*EK6-6*UMSYn*^J6d;r8b$uAd$_T3s-;}uJFsJgF~ql8|0fci&t#B zpN?B7IDLxkn=~7t@dQpg?KI=o!L9f=J9g-9xS^irW$H?L{`fTX{K}R3Pke$+^MwUI zRatnJT}#C@)@wEbzXn6a-&Q{+)#4z>q<+Gk^~h{elV0l9k|R%930&|}CsQ;VZ4eeR z!ljA#^=VsXxliQJmkI`lL})aYJ*#Hg1VOJmE}$KBj3Fc5p9T!`l$>D5lGm7JGmJO3 z1#J#bz$&pS<(jf3l)ETCrqi{M6Ld``eF8B29Bh_%;VY#7f-3V0S_QTDzx6GM`&p4Lts+tb;2&`j6XwiJVy=Ednsun$5Mt#HvMxBfl_9H1Yk~rb&skVOUAS;9P%He_|E(j=iK@L^DuZnu$fUzB1T3WHKP8DZ~ODBi{O(RCZ+ zT8+Y}7)Wyfist(MZ^#@Z*D)mpxT1u@Cg{B$rmg`FGhJr0(%`eRH!P5LaA*gNGj6Tg zYCO47%*WKIVOAaZL=`$RsZ=s@2a`}ASE0cHsEtM&-_X}6>0@fdbp=MqoTx_AK7-0) z>N5C`tIs_WSBV=ALqtqD#WHWOrkK}CEIjte3mQgfSS+JR>0y|#1dF?Zdw`oPOE6RYbFEcrTtCB+kObMhVX zLM&F6+IgbAjE1}nW zDE6(2Jri>?3nwMMO5i&w0ShM*Pyq=j0v(~_==e}cIF^+^`f!O@)@nzN6AVJZ&wzq& zg9jh_C?B3#PTPkI;gzwXQ)E?VVzHdcB61e#la4F(VprNEwK$z-i7D+Ory~O^uEw9i z0t!>ySsr+h9h+qR1PYOR4Zf|uBCmP$xjC#HMgJ!(SzbW!x32cvS&Z?%(06aB9_&n4 z&*$RA)ilJD>pS@1IsBP=TqTo38Li&uqD@FrS%6T=b>9l(Gml;topG9h>tAJ?sQ9b|TG89?xUsBL*?>AuVhy4EERXIN~c%t zES7ez%%o$}7p|H(xF!*sJ_x^S6LktvAE8jPNb!y2UPidfai4uN1x^r_(lnVNj^dRU zhih+azW2V3zng@>(RJcbNQVAd6Usv&IbaGvg=YvR$jja@`~!c9+$#w$Jb>8;?ItDb z_m}Ykk+B7#2e|?n##P9m!_rr!u^9VR+l_uI%xP-(XmaS!H5pu@(>2+5J3GJ8+WHN2 z&!gM7*Nl&D+Xm%vyoT~ri*oW}eFQ@LAB;d;f!E@@8zT@PIJN&}uh+8ID4*)MphHq0 zcSvyq4%N#>?DZiC`|#!5LyoTnQhPO_Mn~qP-o}j?E*nlkf2-Mk`4jX#c0lFtUwau9 zENvyELs9R;7u5b`315MM-{JKNf}wZpJT?bj102gm%W&_oDr zJk2*2LMM+;ZVZlxxO4XLd87s=!XGi*{~h?#!TJq;ZjV!F6zCYarq;7zcD^k1lKSyU z?0nj$=8WSRDNn7pWWsR+pD(hsx8e!JA4jOQ-O9$@6XCSkpyo;CnawM?_FcI-gZ|me zFf<)va?xV!a)g7$=llvJUWMS{fYj&L-`grFNRy{mTS_?fL~w&BxTGyL36mUchT z{vh=77~C{s>v~p{GYxh()_3dcs~75L?x3CRtK%?sRC`z4%AAv0k(ju6bnN1Z_=@y7 zOslx|ZmiQ6Uyb*7@9S?peY2?!T@m-Y2swz>V3bsl>2=ej(bPjBtt*Uid+ z1*rHe^jsyGTS;m2%L7X^x95h7+jB!pXS@PAPij*s7y)17R41lhY=3d6_U5L-AB&rY zwmgj<^Y?0tPPJabh{L_^+Gt3QPpS8aJltk?@q9Hzv zN|2=UTRYEglOCfvF76#ZSdoO5=td6`x&t3WxBjE(vv6en?n9|*rh(`x6_mW0UIl&e zbXJ=z{0%he%Vc*+4^=n;EytXOq2(-AV-#~aP2Xmc>>84U!H{5olgxKHt5xQ#*fCUY zW-V8fB}2Z3^=eo%PU`+fcojUJJ|CGy+|-^lVVqXGoG|p>@22lXXlw1qTk(Tq$h_go zYmXu2n_$>#N6I^rET{lz?jE7LVXdsC?D%8_N@8f%_q@shjz6D zhH|dqs#3ImRnNMFFY<SqVsySN}s`#VuU=aQK=MQ+L5g|cw>)zee_U&CCRgEjOuc0{L)PwyW6vIrQ6N! zCux(?8`%i{@`#|rFH#u zdQfXJs9eUNJ6G)$F+z!gSLrsDv(cV_&c3OVnn<0V?v%>ggM|U3MQc}T>^R_Or|x!Q zW5D1`nykiP#$E<$VhbJUX8ddRO`0KM!>vQr6!WE2uYk zxBP-OPhO9-5N0T3n`RI(70iBXh3I0r1ZSdw5d(ihBBzxGiB=+2x=q0VPgAT|T6&Ra z;*lqiuO-(KtbI!&dGs;Hgt1-A6kB~++sLMxMZ=xj@;u0b25i0;%3XYOs0$wr{1s;6 zm}Wb($Bq#S4z;*lEkohrY|&L3jQR66{4d&HRC&`D1Q%^`@5I$RcK`R9z|g%{@49x} zg};?Oc*aQ=SB{>Px$umWFKUB&Zh|sZ=ns^(J`GxrI zXFrl_FF{HAou@HAY{6w9DhR%VD`}VuR(c|fL77M2J zanrzjR%o`lG`StCObMHB&?h0DI;#_byX<*DG#v(p*Ws*_1%VMgcoT#9gQmq3pGZzSiIOCxrFrMuRW_40Toi%(yL5{br( zaQa0{ILl2*BG=1bz#EEgOs`xi<%tA{DO>$5Cc!F+NXkc8W0DxeVp-T8bn;ByAzQo7 zH2DZJqdi*5p)DWq|GBQ`juJiR2Ri)C(*{3G%l+I? zw5c47L@AU8;_e({^hrR&2^t#CmG5-XGe@T40ce46$H>^F<&Ir#@vNqy-A+3F^eoXG z9q3*dtxFx#Te$)Y!W>^%Ke!v*eqx)N`tMJ9Lz9l;>W-0m*+~I+hbq{SF}Wm)^T~=#+7!BuGrTWhm(;`-U}-x zcCmY;X+gen=x5};lwE`2Vgk)FMQY5hDOkKA{lX$Lr8=`{J?{b$w%a5|iAWQ&XH!Dn z{~(&r&qgh7sl=Za2{F3Br(-1jyxMzdH#D%t+*YZ4dSv+KfojphX!If>f8R8=w>^GcwL(dJ^Ol)f%j@_ zS84t`{))F{*jkETC2!f;H+4!0jcM$=TB;{i5Ct3J&20><=u|=}gsZuTlugn_5S<-cg(hd+c?+-Vs|>?CRbC>t0ov zqElhEDN0+~H=dqdMbW^wBK~i@hY~;=d4Y=h3QRt94|usl+#JS2A+zLkoWEtIXzMKc z`nFYg?Og3m*~M46dQKjsi|F#Jot@hU#4F$2vXzfMiTBKIndjBE@=mHf_z3^vU9p+L z7`pUQ-o<;O(*tpQ58)>tdgb5H@5%XhjftpQ(4S26)Zze9kZ}yWQAw44Lnv=dTsRc&B_`eZf5=UH;2-PhOtPb^1k zuZ{*~Ji_}Dz6Eb#y;44@=ZW~wXfxX8aZeTuJV4WeQxDQy6NH&$kUz9mR1&Y86>6Pc zgGtTDryrmPpL`h4t&gv4v_q~tIaz2K=HbfGZwj~V&rNG>R$XY=ecKV~=hVOrBEw$< z`xjr-2L*<6V_1E)c#|i0gceR;|2nZMe{dgf)o^=ky%0}|u_zypwhpi2?K_xXoyra> z6$A3jjRe?opQ%>T4c%x`sAZ{{9ylVwPXzIPr`Kd<&P}N8rSh zAnpT?wS!v4G|$+(Ay-7<|_x} z$%(hK%&xIxWyidwBJrYq+dd(a=T>LyhA*=+?OHN%&uJug^UEg<)y-e;&Q9W0`9W?U z!QE8oIJqqp*bl>o@`TF-_i^ydouzWTKU7+uZ+AN-ilA0vi@B>k{iXi?LZ;!NgR>!v zt?VD#-pUu!4tq#27>a6WfpECL+^g5AQc-_bsP1KKI$vf-R!)=0^Pjx-B;LIjRq^3)%cm(ua+h?vL)StZ77QW&h`y%-klz2(b=?& z^a?W9Z{byJqvj!vsvhI0;H4OcN2cS+^*X6SCpQYbIvn$LNP>R3S|f7@B}FG2SsKAv z>Jh-Fq%0)L6<8i7X`Zd@YPvQ%WO|{-qEM(|>8bltc873-%~pGj-7_3+a8~Z?f+&J4S2o%wjx;Q0L}Vj^XZz2Zov+I=_5I3#Lz=@b#A5B;dxz-fGXmnPUUP@pcz| z?6?+puVL@$Dxr|SFpB?+oI2tK3Y$WI86g=g31q+R^*Y-|#3<(CaL zkEJ9iWXE&j@8c^KTe?vv2C_m@2>Y?o?cY80(C=Cfzi@eNq4Qw%N43|-0Y)7=zC}*I zdY?Xozrdch#17*xTVCCC;%koW!z3~iXvmr!Gobo1O;Jk{TLO}~sYXQqHLsk-&*bH8 zNe>&l{PQgKCR^osNiJo`E4CHXZEg0r$!^ped@h^WlFZnR;k3($XOV6eA;yyq8yxAB z1>WWS2A$lbGR5tcHdSG(BFm(*`3EE3-t$QCwR*7XjXdbH2zVjMkwjIlY%BGG%GK&z zi07UdDVMZ^T*3>xwB-`mO&)UTv_9I9^_AL`@@nFUB*YU~$a!sVp?^ZOF9n=A(IK~F ziEz`=xSr-?anV03d&gGpS7==pqeRYx)RU|1{gr@sd|<5I6f@{60{7O^mIK3mtH-`r zo=NwPy1jvffHyYmFS|1XZ5>sCXzyiOX6;mVMypuEjdi{C|Mm73@NFI0zqrnbY>~y1 zWyxZ)WXU2+mJBj8GsKPq4kryXX;Mm4X4*E}ZMVC{g)TGmwo5-;W@>k{T};xZEdS?@ zuEtlkM{>wbMTb7tnu%%Pcs-bp+V>$$l=M?Z4y$dG^^7um5tKF|Cr7`OY; zku|=q59W4ONm+EoocvXI2ayp79sH}2hyM_>X9}tS@8Lvhxq$A#eAKiKA0;l%Bc3%( z0$)$aGqEbx+|HWgt*)@wV2#BqO%)Ee+$fcotIDe@)9tESmIFQ(aCTkOASohSlD(l- zmCme;G3eu-biG2Ji9bdLnRunJCH&@mziKYxK3q}N@*-GX0C*VwvSNovj|=s>%8{5g zfVBW@w^CW8TBDdVADftN#AHSAY`pWkgO_b}`L#-!w7j)y=o_ba#lF?Ge&&n#K7W?? zeZ~l-m*xNsGF^&3G)q06DED9FGq>X?L$DuPZfMEg*c!pkGKrs8?D?d$4H4P|OE){Oe^!lJ>YJbPmp1Bb-TtI1tR@gR;xSOP$IF8_P>)zVt79M z3DeND{(85XlGp|q`Z1{I8B*roY@SDG9yBA&(_ax91`+xAH_|~|Vz?cY#c1CD&vhH) z|5=2{jRX91#J9b6)c$>XcSzEjH}Bqh_x6>xTIEF{AP#S)}xMjP4f=U(-EsYH;wBb4`d-{{wsbPBpBS zNKV%8xU;AK;ma?7q@P5QT|k@hsQ8)NL?W!PN|ySytb=>1Al3r25#$dbOw{PYzM-Cz zhe5Z(GZ}A9Wm!z_3Y)#qGK#te2YdXI+cHfu)uz3JVc9cy&x?}sJGaAdiM-|em?#H1W51o`Nj@(;rAeN@H@Dn0Q;MHkuEE_kD zfmn8axV#C*$ls+zqbkK5yBqgsl$Tv^b~^uwOvhbOMB==Jr*u_d3-0*xJ_vY~&j{k7*CBd~vwVDQ6LKSXd5oFF)n zN{J@(B&*5Hu@YF2L=}eDNFJ9igU#iBEN_tKe!QL(Mi-4A{9q$FjNPH%kA8|^(ejTK8E~%s99|U3+X>?$tSTyP;0}eOLr&_}uU| zryYF+Gl0gUd)GeyYyk12V~Lu{6dC%xwieq}AJY0XxqI=b-`Uc`=fu61@QftO0kf#u zLumDN+!{vRvsWV6(mCnp!~J~!MCaJ;qocQtkK>mdB zPMrG<2|4CWinl$BqmJEOH)4+DMlV~rRwukv7I8n`wYf3O4?V<2G0)Glam*(h!jhFh zW=R+aml12t0RJ6W%U=4wYOTS1?r{9yu-DY?7p8T55&!>Zlg*>jU%WSOv2hWL4VJr9mn|oWL!vqz&glKG8&4jUG2Kn1mkWI92DCG)(K^(7*RlGb<~W!3C-iBo zWnl6v-7DmKWO?#KmUKH~`b!iUeyB+EvDLJDpg_E=o?3oL&yxs4CJXI`F{8MDovWip zZ(AEDx<^!}{{c5rwDuygp&0zd$5sW05_!wTSW$RM;-@L3q;q(S4sOy!?v02mjOCNK z-)w2H5E&~Wl8Pz`LrTRarPZO+k6qOko4v9-FPT-ujIH~d>-RYGau-;d9X4|Av(jo# zSQVS@o9nxFK8_`{BW1F-8@Ft^scmgUIuxE6kH4Ec^5imRu9+u>${uGo^rucgk&nZi zd12~Zr~eV33o^YD*c1;ze8ZPnyEp8N9a~YLnSLIy%t}rAwxnhw%71AP(F3? z#_<=Xp8UdQY#RUXxjXJ3cwyn=A0-BdAN_z>jdI_XFui`}46acIW#A!}4qU^#$X>s( zrGqlT#nxc(T~yLggpYtrruaf`kh_vysqfVl;Oae{LMK)j13E zC@+p)(IQtlhT5NDc+ETFuJ09>Xp2?c^<-`086fh}X;wb^E|2e@0yI>dcWFkOfRHXq`(A~ z0u^xAid~gIf$?_{TnmfE_E!GaIMQN*krvtSk8toSC~kyNf>&eT@+)u#_lB9YI*Fgp zVXvB(7o+}!L_EJL;-BQMcJhz$lIF+W%gGc3=bE=2z=Vr5_LDpB+Wr<#^aKErX5MgjQc09O`eHx^go@m{y?zG zlb;Fj454Jr*{>BUf^e)PY`u@EXz1^xK3x6>uJg=0la6V(!sSwUrbzir&uf-WUjaN1r@ENZM?@h*?rny!FqZ69K&f-yv;S-3o=vV7 za8+*H6x@ujKKS5Qhdy(-F!ujJ#@?1+DVJYHXRr?*M^D&AE4lYLjapZBD}(~#`9Y$P zV=;PfFzI;w-g@EyI-_tZe15q@R)q%!dYPmGjzj8X< zJ-07Yf1Rh<+gfL~7*Ytu;=XjK+7t9kb{<#jIun!S(q?w`oyHvEWizpGIZnmbaXF84 zzeG&&^9;eVVHvn`=M7~AY{o6eSnih~Gq5YtG-A$+KTp<2 zKlHKs=gUZnd!(K#RZ$Ywa)3^>z8`JBL*{4l@3$AoYX@-V$2JHSGPY8o++~R}V~ZKX zR~6sstnkfZ!s+~!Go;VCJk0n>eeCf0!%|5c51$J&1g2Msqi!_tb2e_O$ezNTVcaG- z$uc);b(QFqT8muEoYWPJ!#ymaU)k>or120Wy}j*bsMbo#^j8eixWd?5Pa(l$I`N0hGI zlQ74vNAd38=MKZ|zkO8cD(H9pxR!7cx6t-obhz+m*!comA^!D8?$D4&_;hjm+zX-5 z{OaLwjXRv#V)FarDk2;Of+Alf+6bt4_KqhYI|C0I9&aHQyekaQdNttS1@%I)JC)(RpRmz_|KA%`8ZkHUmaq89XCVWa&xTyg@0&LE`v;d$CJjY!6)7IUc+uGaeG|R1; z)?WFwR}3GlmzTar;;b&YYj>&a+T%mabHjpP>2#L)=Nn37@SGxdO0l$i`}Y6dzFh&= zio{EWbCUwnq8Pg#>_!8)=c>87CF__B_=9na`$yKdz8o-a)Et9i(amJdW zc!OgQ9xyaPZVe4|?AUBvga~Y!V)H~28cffxaJ(sD-qzdj;|{EDsofebzfXIZYMn!P z8=Rd_GN0upMKn{+M|w;E%ia7Srl4sx1snCj`WPDid7h@Xc=_MIXkmVRf%(z=WBR#x zI+BkU>7ca;J8t|Grnq_Sxc&PykKnO|Q5I8e;rTdTL27E`&eeh} zh&Sd+G0b)X`28)zF7J5z-^s+i%J^r1^yT|pHavk{3TwBGU)AREwD?H1WCrhW&3krk zW&MHZYb3TivUZGDYIUY{G~ujHdSAn zwb}_K)*c%|6ZQ2IMU_UQ$(p-DGGPdz6{(1dg0&n0D*2AD^1Y4TaD^tt zx6S$+wq{NoX`2M0p-iV2%4Mdq)8HDtTODb?V&b446}AlGW#2@;+y^RMZ_x_u;*HhVqMZ)S;*> z-=$NP6l8yN0g0HHWcvIpe#UDku~CZQ@A&Ldrm#z^XyzGWB&H)-oUnAY1;E(@(BD7& zkV5dqFIqd@v2L%YMjLVk{2&WB95TKLnN-P?vBm}vAsZ%ig__A;Bn+K)+EUja+WUo+ z(d1Bj%%#FoVf>*J*IuEq-0qn1$Xu)~;2GQs5C7Lhs}=K>S)br}_%7xJYe948rhO#A zw)8v(s4hE{+1(lFb_n7srPI(lDE!M`1tTrt4x7=wAiw75+`+g`yEIZF9@rvE2(}D3 zeVS|>*Ui*%JCPhhqz5gyVk!C&es&R`-(T=^ob;%hJb!Rm%=-oTJAURNB9HzT=8PI% z!^I_1?j+^Pq;Bq1T_d30+X>+HFf;deTp1NM10}y?UR8n6Uvj4$d7Q)q*QINlOct`_*!vv_4X0Tu%gfg; zgpMJ*eb~V)M4?D+n2-CN+^Uj6zsKWHNydrjEre(Okmnf)QajKz!Jj9%5K=rUxe@*6 z@2vh~Vdb68XkfK`t!0`{Y;cz#@r?hatfuVD#RVS6q+98F_q#U|d3cCz-^Z}kAVMW- z#-dGUDlcHq+FyQUcJ=%`{(vYo9H7IRLQt_XU zJ$^vq!gDiz*VZQm$dmQrc=rFreI1D=LJ0Br1zDdb;_1nJz~$RL9{$>6Ye~Ca59)?4 z5g5c>4fVUS*_Q-({clwPmg58=DLXZfB9tc+|-G7jZJN<(wQqp1rDPgRvU;cKYSK|-} z@HsT2pgdyB{cpjhgJzj>sb<1@*w*MF5V3|!enLJ{D~{ZC@);ujGh!mgMzp?%tuS8_ zF|MWPzya1))YZjWi`+BLfNI5DqzYiQDsQdXjn3z-HL?F=V+>~5jqN>U|E@j8JT409 z;G%Y(f72*4BK^Yc>sop8wi*|))nr%vYYxXHTWpHmYd4CGs%Ae3(LcA~jP==FnSygI zvym+)92+dHY^9#H-N^WVVn@NW|BH4M^CTV<^e-AxNS71I;AM0I)7yyYWocQDY~obg zh;V}eogn5MxkFmz@lhH0YP=Z1YzISpKx0U)CEn%ATlgycvo4OBf9!F>2J6~@3i|03 zo{f=JQakRxOSgy&i^BS+{)tg!(j)!SgBw~!NF=6T_=qs=(3|T z9f2-Gxo%UNm35$DH?USWwWE1=eRW?{B=(k<3)PAW_}sS5^V_^`d1Fi7m&?c8X^vZ^ zr*;n>taoJGo(f%ykWW@s6}*P~hvs?asI7&prI7t>?IVoSCN~W5?!=#lue=gI;q}UM z3(a$$GN)7FS!jjFN}0^0?}7y$r_{ZKE5-1fL@FV+dLotl zj+IKTzsdm-EbgPax+=QOx)L&VJ9p!C#`d0m4K&j^pqDo%o^RG_H@$7R&WRv3J>2 zA|h94Ik${JS^d`f$%%BUYqBrcWHVNXl~QF#^FY#{b+!*VQ`?^F&(!uA>uY-x^5o90 ziK{H8Sg@kXE-NV&RhQZ`Qe|1GM6HyYEhTqn--J(nR4?Ek_B@49RJJc zQOp@JycQ1Ne&+=F=u}S7Y1ahrB~%PELjDLG<3Z)G_|8^`B%v!!0da*{RiRZWoVowz zmzFAOy%h|kuF$9zV}Zs9kANf+A^)VzX68*CH|b}wWdyoJNVX?ni}|gOSY-Cwds`G*ON%}dcD1g zM30X-XE%-Fy!W6Nc~){0B-<96tcH8PiU@yCq*ZDxfRxo5ZBPlwqETr?-d+?Bbok|E zl}>fJl>Aq&c2<_j{T%_OhH>;iyl41V^DLx>4JzoL7vb{E0IC{|rbY!|W{RIj|1;Xa z6t2*f$fQzPiB7>3-auA;AMa-M8=I z(b0!Nvax)8vv;r8KE1eU(e1v?wdIBC-s+f*?~=&X-un7riBc?a@ojY-^Kk43 z9}}6)q8Iq)?|#=T_=CV~7JT-n_ea`XhNe0}b5pj34|Pq30mjNLfn(^~PDV_&@%B(T)Q&!^}!fVX0n8;!H6~TW6 za)P(u_kT$6-xB<{aE#(}6ldPQy-*I?P0L~4m*vk*;vbF3k3TVocEvFvd-0uR{H1dZ#8H%HPV7DP&uB;dMX2VlA_YT}V zZl4M9>s9)IIysj*;F8Fuj%zeMr^ZH3^(o4aPst?l-9yK&z)dCXox<(aGCQ4ywwBw_ z6$O@QC)2``k!!n#ZW()d5X}O#F6`Jo(*pnkcXTNx@iv{9nLW{fTeT~RTXk&z!OP=2 zV{C3C5w6Kjdv$~R0hwApElO#=0dS=(7?fTG@FPu1n5!K`Y!5!PGrGNc;JLoqo$;Ly zF@4C(*8%5o9o7x%z#Ktq5Y}pO4cFruoUt_GBOI)_a;MKy+pJM>+4z0QG)Ce9L*Oe18 zY3=TT!zZxY$=&TL@py!uKDJ#rBFW9+$QUOot=OPRW723l-{=PbCBn@E02q980OkGx z(EkQ)t+zC`Bb?Y8VUpeBYrE1+QHLsyNAoz3ED$ntjLt+x&{$= z;ya^EFU5Dn)4s*%!N+~LB4)-!nMEC!=eW4%y0+GvV13uofxh>C>0_VB_dYRNe=7P_ zVVh3|Uy*ooJ@6?q4s>jHCcd1@!dLEpUFzd8bzv*dWz0IjO5Q3bs7MWY8A=6@{Gi*G zdusNFJtg&bK$PiwS*`>=nY&5u^GV?|l2UK(M(E-pGD{}#EYT4E$ErIcldJBGd|K^o z3|2RK)M`&-b+FN^ej>WLKNRZU9F1)r2!#d~K@%A7@cTQ)1HrL&zrTI#C0EzpuJ%1W zp2F|KDkdg9@1|p2aOiU8JU62-9*4gjJXo`DE|6!|JHi0<-A$eBU~lRQ4b)T(`tzd; z)$v^kS4S$9<&hS4vn`CR-$Ejb7Tp)--Ke?Qo%Q_YTB$=THDoNcg8`J@-gwcbj~wrk zq%(YhORm6o`bj&EjWL}-V#zL`EOO_4AF#3|i8R}5 z#~WALvvRvO5G=8kSZbWEd`H2n@$HHFP&E1)yOp&C2jwO4#NHC0KveEH>9k3b+c~R7 z4c_-ZgkmJ~W`4U|QL?FQL~s8fl##2Aep=rVi`iQzxLws^uV(U5bjw|2fU zGHVkxD78LUq{`z_DvX0|HJ!e4?fz+Hb(OPPC953HM7q4?>MQ0Y5|Y7DU%uNCOy<^ZevF{~07C&+?&+V<=b9fS0Qi2~NOL3+KJ)V`r zxCTZ3d_!y{d=^~aYk6tl_FKBX)BkA^yjkK6igTx7mpF)v5|b$G*ZCdzn?~lFd?)wI zv<%et;GMpAcD+2f{kqAQCa>Pp|ILp3MDSp4H@v~@1iAOZq?94;X_%II*>agwcL~yy z#J5SKZ*doLjR5Lg_wKzN-yXQ_@!sXWLnj)(HTmFaX3Z#l@^PlfZ@tbepCA7?{wez* zMzoAPf&_aq z$hdspI(P{vIQWYcmp~;4KTB~LSUC6@iff^qgFi=cMNv7gP+SS-6`X%L#ghemIl;a^ zPH;Q%h^>9UuBe;?6wegl6BKXY;^+d!P26_zT@(*PC8a0dKf^3Nc*$Pp{Rp?c{BDZJ zits*)C&0=n-%s)4_6jKO1P7-a3&r&X`j=hkGEO-bMD+^39P<&Mk^8Wp#|eof6a-5x z6)d%!J)TiFUVTuUyQUXJt?)Z6$9@y8k_7_NtKr9*lqlEO1s@sjx$t^U>65}&S7h0` z9Z@XHmO6R^56FB>8`7926N+J)l7uERY-ZZV>ITacFM(O64J>|v;-(_}MT$#coP(dE zxElHhPP772PKqtZ&%xc;&h!?cBe|Slp6Ppb=w$JsBHYd5LcDsUYnICu$*J22jZUZl8$ z#bp>@KxZhfWpOLU`_Xe0S1>rO_Z-F51$^0saW};+ysr>C88ax(h)Qu2eLqq3zMc2! zm3Hw36nFAIPu@ou-;K^vT$V3~Xt%?pU5#wJzQ~p@L}R4@_LuEv?CkkMc% zB^3~+oS_~l@?SY}9_ubIS<7&>~D+u9s-iq=%c?{pBe_PjoqfaW}>7a1WuM zXv5_F7WVx)_Wfd91YI2b0>w>5_*sg}C@#dfo8lF)ms9UKimU1SiK6%IFw4F_RD`?P z{wF#(p|h2xvm2MQ7B4BnU!k}Xx;XfY6qgjef0p91BK!=+wMF=I6jyL@zJ%gN*u;7N z0>w>SdiXAihiN$pmd+2c{nN$ct@D1QsNQah$BOViiYK6pQ+|x%#pMeq?&Q#UCHe@( zUGQh#6vdhT|2*6Ow0!bD!D;zx-xqPq=L;xaT<=+m6Mp0IG5%Lfe=V;ff6@$yB|C3z z6MOMqS~xjM?z#YGZ&e`XzF}ar+D3#1Qx*qflnG9{YOCrho!B}Nt)6rxawjDc5NR@g z#+CscrIOt1+O&@`a3EdQx!A~oHYhBeX!060d!&&yuL|)(P;3QX$AYt;C~(9IAd8p0q{f6H0*B^2;;ls-uSM#NYJ+L(+`QnEhp#aPqv6k zIF@E+Oo*L@j7bMOh7qRkS^NUUP2gp5A;#SluYd(AJ9BY6v~zG~t~|@m6=z}XEPCG! z8S*}{uMm1V+1=v;^FE7Tpt!vKV~{9K&<2Q(&e*nX+xDEXZQHhI&e*nX+qP}nGdu71 zUBulR8~bk~x;nZ$x+=0N^U3V4s?3A{p}y{Si`qBYhO*-5C+q}r%e>e9MZgPZ$>%Sd z6uIS;qtfP2pVP2 z29<0XYue3 zL)Fp{|4dLP14Z1M!Mm^44eu6Gr55hS-Mo-gq+cEx1Zw3&XK)jQ>g3a|`5145ADKPA zJRZ|f)L5-s-0wMIdd2nS-mzCQkmw~Sd5J}(7P<_c*LGPr+)Pk)y+9Tvn?WP@@Y^Fn zJ8HOc40X{@_toUPvHY$WclUtn7P|TELlmcw+k}QE$shj;n$f9|wQFpCs2j^rbH{1< zW;a&ay{yt2w1#rH2BBq*_Dm^Raz!*|S)8uLEU7{N=Gzh|Z*sdBM9r7~QIq~UrZmpb zmEXxH=S?KO&^8(Se|nj@diRui$ar=fg9P-(#GcWka_JvMPfF1V2JAQC5Q)ftW|Klk zD+YX9%+BD5$c<0aC-HyGgBSLH#wIu5e~b;ayVw6>)bA?sVv!1HL6XA@a41XUD5t13 zYA9SLE|KXstcb1MEfg{vVC;WY(qB|?b!GK7W$d}Y-Lz~gvtMOZI1JV<^r5E>LanIB z?nYo?@^rOZ_7l2b9k6|^tevguj;$PAw<$W1DHqjbx$PHQ#N)vuoF0?QP^75apc57+ za|cnN3+UYr|M9k2(*qW?8CS--I6FH%H!9|&)hlppn^!|+EYUh|JK?VUfvKt!F7GVP z+NuV0}?hI;^eBmz3oxk^-*7}x&h|U zBkU!&fu}@Z{$Z3=#MQ~zxUUkrCo)gf0a8~-?APwAEPz%0iMet-67`Ep<{IV&*trf z7V7)PjI0!g3V8B0+g(O#u$ z(Y?vQo=MH`*F9{*cMJJN>__*EE7|vpehe4oXln^!lw7&BTx`p3Ou;+5kUnscTNF22 z+%`?$jQU|on`jnQn`jYC&R93I%ZoSB&b8=wX6xWdQvXyN)saq4l-Lt{aiK{}_aJu* zy|)1KN5iPMM4M=AqE9t5d@oYK7_h&X{&iel z-e#Q`C|H>e;=q%97s^)11(e-MjQ9ku40*d+^{N!FpD1V;4p^QlU@4Q2X=mf8whrb- zLi1qqzT3Ro`ExDoV?frw#*XOhf-h2s26fSdO6PU_VVF?5Ba@z2idL~qhVR=rxo-1P zxv$60ugCcppT>l71!)fLOy_v_>zNm_ZXs7P$eKg6=(wUh#HvCx=W0nh%Hv`*7Q2N= zpPOiT^!1d8%d7zTPkRg7LYp6e&Z?G{nv>YsjjaXX(#3-~Nf-t3sHH)Zc!dHbNdOGu z5<`{)h|dx<4N`0Mik0*x!JEdmHGk6dhOT8%Dj}Xb8HDo((_sNUR{Qy!DeZ21;YEaBB9o47}OxG5pRBS@jSQ9qUok z2$xr3AkKO&L>>Rp6$BQ~iY6UEO2uX8DbV0-Ksu(?*A#koDOn}`ao0RGdlUH+5hid> zs5B8zOV7>a#EY5zMwiH%tsVQuf(NtEo+^t9R>k*xDsyL7BJr6O6Rhzjni1xDhwfY?AGOr0PnE-A zxAa{YarNFmB-q>&yTqWk-06byotTZcqPOC4iHeWx1pk(Dc+C4?q>H|-;tL|&2%zGw zZSGmAe)d~_6p4{MEy^pG^)R?ATgua{yd2`(I~h1oZEPBoVwszqj5Ll^x+sjmu{8PS zG*Iiwanj2+RjUZRlgb#cT39fhaM|&bBV{Nu7EWpw|2TvO3s%WfBc*k9KbJ3-4lP;8 zu^RV(o1|>&mx5z)mDDaM;pRM0Tw$IqWorcHtr^L#vPf2?gx-!nF>*%}wyIujq6c)Q zXK0~hdUVwH7tOI#j#C016`x1Y?A5KW*U?YYDRKcG0Y}!5-@}m(`4d6>BS+ zh9(&F>WT5<>vv@QSRM}-68p}LX!!>g5Cpd29NjGHsOU&ZzAS!(n6O-aJOV0&^!4n| zYMcZ(NpsBUcwk&7j7hSkVp*8yP&v23u~qI=Dk`qsDz_a=NLe_n=tY19RmG`y z&ns3;fq_CnQdH!TFi)I3&H8LxF4f2^VuG2@Cc&aophFmUF_e~U#R`yS#I6Ahn;}$I zRdrzr-Do-Cao~TgS6nrJWDnRlY_RGTDPH(7@;8i3pL@)POb0a+BCO2dSq+GnmFLrR zcSYtT`~5UQju#^|d~-y1uqI*78}gyO!p;}s<&|d2ys+*f)8HP=jgoi8u0llXH>x!W zVw&uH>XnUxM-wT_s!qHacY3(@jU241Zk2+@r%n)Oe3}XfNiSZTEPm=Rv#6c-BsqmR zHBgnm@F-c+qY43OR7Tmg7kxT-atUt6^u5#F>AiP7 ze4ULmmjSX#7*?rC>&QP2Ga%_x$=%|)b88ulEgjU_XZ#r@-uQoYRga=p9}!HDuO@!{ z7E&oW#^NRylcPo+lpxl)oD;ML=22wwG~_4`C;XbuVkV^EaQ}jA2mL|=4kfux+ zIdIC5MrxJYjgdr1rfn!)KP6{umTns?U}xdtb+_Q!8ZNo zw|j(ujj1MKKW^0iCm7jT--$ASZ^D#FF*_1{ruO!EdFkcOZ0MDDRzG0uQlGYT31RIWxu%=83C10B}-VT>bmmf%v;A;H)lSQ zZ_%}UY3}DKv6V7q#u@g&pjW(l+>iuDM8ClHIP=fMpLXj zU##xIq<}c1E+%9H0YX%@boEA`^7(ZwLiZ_bD=9>67$bZ?B05HJ=zu`Mp7?xHI68?| zr>}J@5l&EV!Bvj<68|pK)!AKCg}vKeRx; z+_W4a-JHcVKPjqTpfN7R9>l1fKsi$7V&anNGus`NP!P}89nQdr|Jj8lA0SRkg#TJW z({luK6Bg{~z!^VqlO^BmA=3+eTP#1xRD{CXCI#Y?z4SaTQ&|l7B6E9(0h}V%H!Y^2e3ViCyx(`5> z2!kMRoa-P$FSlxo8l*z>0O&91WcNQU%m=)bU3M8oUbYSQSJsF)&1La|R>CEb*h|Lf z5L?~41`}$MWi=U4iST9GE~c#;ho<5UBHqw;9i!|>X{}|2orUM;>$dy$+O30z`#nlu zZDthN5R!%zsz&duZ`!2Jf?OfK=*{0LqNQ`Dza$N#?Jy8-$1p0P(^(jU?@U;yHbGi- zusD3PUfeIvRF+=*gM~XV>QerW*~cjav9(EE2@ZT%Sq^{36UGg-H z&%x8ZVbU2T%6O~g_#D!r2tXHtd4P*}5xIK3I?wACC&LV@l8RRioDrzTy+^y`mkCce z)g$AjP4m}2^FTvTlHCUr`_CHo51^rkIu2UV9x~;v#PSl;z>Qz&Dz1pEVou?U7o+f& zrBsCFR<6G^MqCr?FdK9g@>EqVh%LrW&VLr&w@{#MB^|SdYk3O)CYmF&!eG<&b)|h^ zk=vKJ(~n$<>05ot+_kHFLK!+1x#)fRaUJN+XgqeYjU)MKo@3eyb{(IlLcc#4U-PDIUbN@x}=Sz9^=tz$nw z&n_*CYL;$Yn?Z4`TV1T`#=D`h%a}e7-S61_^c&diU>PZuNGX=LOwXmk)F2U2>AXHb zzgz-S-_+INaY0~`iARAAp077G`vg|MPU|ECP2=>;sH?S`23Db9L(glV=U@2Oc~nY-FEa|&+~7AeTHwl|SQHq+i7=mBh7=}EiXDRR+> zSLzC8C1h_NwAoJ)rAGzGm-pfXjcXfwtO`a`qflc^?*o;nz5pJ$S1%RWfb1bv_D&FrT zynx@OHQ|kbiX4>;&;!aH?{HIpnt#PZ_wC;b2G;xnKdJ^Uy}q1iuAn+HLV%D4eOt)t z`=)noJGdv|YNQ)+CEI_ZkpNJ!VNQ6eh*0pNP#_|h`dig=>4y**G@k8$B4|!wyUC9dZyu~N9WH5uo$XjVZ+D-3fz|0#0JZoX42aMd9!^8;k9_BC*N9Q z&vcmr$HixNqh^sqiT7IIRzL*+sE#pep(+?aHL5|5;zizc%mD2$4I;YfCgE?!2UPP` z1Ii{I1!~9L*uAj{CYTkQ4Uc;N(BvI8pFigRxN>qv-RG#rSx4oFFP+PQV`AQgxOB$p z)NCIMYP-q>uM^e+Nx{@K{%TuFb;;GImL^cX162(;Sujv5G?38Rw?A`Q3*NHW#18i7 zvDzdyi`)5$<%A!-(5tV=O#B495WTE_3J;xyFCUXJ?lrLF7e0#u2mw^!DMJn1AIBui zHz@<2E+hbiHo0B%wDPbc37U=M`gZD^COxyZG~+8Tj8R{Wk(ArhXRGNGT}TXd31tkg}(4g=qw9t79plj*Gnj%lW+#2H|jB9z`#HiQUv55$b-6+6e^oEX3_C2@IRatn>+~hFHA zrM+*-x9ThF(v`4&2Q)p4&>~w;+OWLP1Y)M%FX6byJIXv=sxE9UYk#kWMz;g;+h%8L z|3&R9dv7$stX-g@%Ch!2vvyULnQNx=^tE8EsCGL9(5YwUg=HUQ(6<7sWT-0X%WD)C zah|a}YVBZYcbR0UE6Nj+SJ)rfsE7Y`GwAvho;HAiD5g>%+&9AAl@7J!#nz5+vrId< z8r%`TWW(Cb5^X@5D-ErvnYIjDSg<-AP+%w5h4B6dhNMa8&NYeKeee^E1IqONgTpnM zNnVEV`C}W_CU{@8q0SW*xvHPOinWN&d?=i> zYzC@KTtR1367D<+zIG^Fsl)bovmtW&_Y2A;u3RQRQR9^kOEgBx9t|n{2!qEXy z9#~OcmaytN2g^|hDp9!N@@+LbgPEdI8rpC9yv34IFvu!}SFV{sp$1%MGPA)cef0b@ z`ii5l1W#-*w)w6Lu2tygZ3>QPHTk_ys_irHQ3~!i-;zI1j-rWhe@J709|mFP-B zYse?7DQRAV#3+xiAsN?7SGjPJ098wg2vfjz!oUz(N@ci`e?L=(tGH&SYnbETG`v8( z?KnOmubHxqQHuR+TbNC^d#Y(0Fs6p9t!fMMsT{&&Mus|D`XZ@2cB8Orb+7X@r_c72 zY&H}cms3ZGg^taJ851p!pY^VcMDOtA2zhzQm%Qj`6eA_JdKLIILnbPiIu`qT z7St0g%9tR-*GXQbqig7d_Jb;R95k*fh(G=^5awx3B=%ebvg~hG$_0OkBd>NP%`U_z z2Lt4cvP@K#Ii@)JCU!AU*--4dGrfF2BDMv$C+ctZ!n|1b>0=Bm9br&(sgAV6*@Mcv z*udZHLdh90qurODyk?y2?v+em?qa&fHsRhz=ZJgmEdmwS`A!sXy5ucKbs8W>utk$& zsAxj?#ZZz?vJ37rfu7NFQV~$|M>@!5tqKK?jo_(X;%?w-cU&D01t5l^|7myM`~c4( z=F++WN=LE)2FL?|-n{(i1FHQ)am9e(heVtM2t}2q1HkzQaCzErmB58RlMX<5y> zGcKOw4Y{cVoBE){;glK{%%;due0`-X%kGJmr1<`=U@WktN~_-fEp+7d7dCgbR zUlT}In3I1)zi|mqT@z4U3@c0;6Sg}Djq|V(jIzQjwNGbrLsgT!%&#+av33hYSlRqJ zNB>rI7;n3^@Xr;Yb`t^(^xKV%8v4D9KJCTeYK-JFvsQ!7VP!=ni?>rwrKjx`-6Kn- zaw1!K?|TYE<8Aa^)*Dvq&CLCk2est1O8T60vcoh!`!x(cl;TO-;YvK)L(EzdX}b_H zkyy(L$CsXu9_xt1a`*C;=Gf_rqI-iu+cjHNjMbOo9E#$Dwp`5^tt%@BN5H}95T=tA zlsK>${cy{;2gVI2msoGj_}ejhfzaoU!B*4PJIjRT3iU0O&0><}2$ArN%_dgEmT96E z+;8xNCcfn7u7~xOO%lRAQ76t-;*iUZY4MTfZLWQYckNfr=R*#Lad+q9yK=T_lm{)M z@3jX`r);!icCL%w5F7l0001P zfL0Si0Vn_fetSQ7MjO~0(+8%O^Nu)$&RaxVgjgSTp_k4(-v$1@K0L-@KW5#a%=3a& z){P4SWZF&(LUi7bOuf4~Y?I&xQ4G@{3DOKx&}6B`G47~pM&ZUlAP~Q)T@%sm5s4+@ zNQIKI-61ROvNgGPaa$LPM{eb3S->1>oFQiEy7%N38c6s+!kqLbF`ftYf>L@1jPy_sYJ!oO=aAv0Vn` zN3dP{B}y_~hLJj73QM@JFlH2JNM^wp*N#2W9)-7{Zwh$Oo$h5^Moi@&q zW?0uPv2I+|F3@&7Y~gxdHRz@Q!*U+h5|v3Bmn$BW8pd$tZAg^NA2c#ebDnfU(Y7Df zQ+-S2R8+TJhh&sFPguKdI@3LsIr71nOBR6PdK8Wr%6;CHnPz+L6{+f6ETv34ow4c7 z{?jKCWzw5$g|O{>qP^Pw*e#Ib{fJLyE@83men0NO^LamN;rm7afdl;&7Gwb3lxSO% zjb>GwT&>@zC^@J6CA3=}kLL@vy}1MfZ_|+o1;bGpfB#Nq#5?dlROFWzSLc-#Su=i7 z6s9VSmldXKoSPS#k2hj898YT2nvKF#hiQ$2e5wmu*|j6@^j$b%+~wdP6Q5!_4)^tO&j_X0&NSO-k?9~4;AYr zyWM_&G#DN4CkVJhCQ{}hatX(P`m}vEl-40)N?X5jwS5*=M7)qUauxcKLxSe!F|2Fb zh&S%-KQZoO2s!s*N1fYv)%u5Yw$7uhcgoV5_k7#V6JWfzLDO!t+U<+LNv|dH=tVPQ zDlzr+LS~Ut*`;x%?g-@qAe8&)o6lXcp4Tb7@B7%_(GL{(^UMEU)fDTEW^KNWWkD7( zsz!-nV&@k!VhPa*CG&aX(L@r>7%lhv19g8vk%%PnXkqR_sn20c?qSW&5mT=bF|VQ6 z|3A1?uwHRGozGW^)$o3SLSr&o4VE$-kV>aBS`SxpJfKo*#MfF4m9t#1TCM*&;#Bi| z!0wOb5sk=Zaynl37g4R)Y_>c8$iZ`yTLb>;wU6uN$Y1%ierWk6(|Tjcq=n~s9qrY; z=YPQy!+G3_B+Gg9{{ap1>uEhzHE4JHaXXex`%yF3b^A&8FIo=k$g(|-+t748j+)rE zJx;pdc;62j=>ETu2mpaXpp442@ceaf3fLZOncl;(g!sa&Q~ppxYQgUMpP zoUfeWg2U;2wp^f^;{yx|gTZRBm}-wiDwD=)_@ClNrBQD-SW0)sVzpjtHeAW}27|@n zaM@o>b3~)nZgV+U&hmuA<#B)BU&?UB)Ct5 z)qfK6d)Ph=ZtcbSjbyu>r=94yoh7YoyIo|x@V=h@|BN#@BDHWS{T`uk1R{-SCHoyB zv1B~8NICNvqtSRgjaW7J+y9km_`j9)`u~%tV{QKUpPbt)jovZ#XN>5S9}cusN)Pny-f1U| z_0s*)DSd-CYei-$+wh0hK4A3@=O+h^t!OxK(#Kv2TaC{AZdpo$0anRC0z-OrBF|iP z+=rzlSAoyKcH9CR*^{XXyyy6*Q~imZfiD1JG8Z2>wyOa3CJL32AP`;|FlzU@t#*3> zS9ZH*q?-20Z6%pVw%o3)-A)gP2c6&P2s>iv!?}iwdrG_xYbdYx2KGak>(%HIUwDQ- z5F7H@y<9Xc^>K6X+v^of1om-Msg`aSIxaL1W1Jm%86#_KUz$zZ+u`}rXxffz=G0|g z;Eg_nVp2b>3Y1CBtNZ)9M=XwI5rO@m5`ohLg!j!2ypkZ!78L%VhTJOJlDE{o0~viOBE$ z0AL*~8cOkW06w3JE?4VO6yT_EHJUPa@P>B5q;OCg3yo@0ACP1tbqSFoem$cAz#*^4 z?4x?Swl4|~4|t9*T3(CaJUT4TJ|ge#?QNGb)&%+wy+6hweSe4$I-Mv{h=M|U;plG* zSQH`6$U>S#Ak803xI_PhKmPHgGawHn^2kH;;0(jVQcCa1(N0u!SQCfzpOmh! zU%4KJoqIGGm%QjS!xqJ{W5o~Dwtl^n*b#&*0zYg44g*vJX*%_`Dein3-jB@WF#Ebp zeZGy{_W0bWj6BQlR}5MfF!T*?ShE-h@VP%0fkmC#yH!`2Pi z{2XDs`IU4=%)-hI;=$E0W6)LflS9pX5XaQfG82`PYIpPDF|u@x7WX>qNB72AYyO5v zI8>DFisX*z?Ig~F9~jtqvbMUpPOscuvARXCPzMXga&uc&>bgH{@t}xCb2Hx7N?+(l z>ys`g692_94TK%55iziuNgRo|jve+0iC_gQWd)nqCLF~U3c?yn@;}F7Rv;CzETkqo zo)fC>LjIn*o|`zd9O6I% zWr$clH+PoQ0MTDuTm+14mJrkMy#eYlb2o6zY>@wMB=p@Bn7N^#;eIa-+!Tgx#S=qI z9L?Q8#s`Q92O5TNsWnYId8%0KV6^~Z{mFV2cQJ0U-2gj5bO3Ao*?Kj1ac*&60lYwX z0dxH6dR2F^ZgE}#$$S5>_M*=A!ma}2>iPZn<@mvY@Pn)21Ni_l`~#r)2bj`}Vh6Jc z&~kqs)Dw4Q6K$(zkWyxJsPNT`8twcsb-__<*_@(H*)P zXHShCWjcszFU^jk6P{N;CQCiG#{=)mph>`@@suQP-3->*Omt>&!>0R`I^G6%f9eUe z^I=vZ$3^?mFGUM>9vqlsx=>12$6xXZHEv0q-L`_gSyi3*B-oBx%Y{R3#{*GdYHbai zI|m9ucXIfOnbm?0#q=WFj#dl52j<8NFgrE~*6}(jh@CD|f^QVDLEgtq@z=kO5p^7E z`91uW!L1uPn~AJo&d=2dsr9ofB$p}Im;*BA=F8`&!h{sqC%h80M5yyzrQiXuXHz9G zvSa8&pQVnQqcc$Dz|`BryLxyTZk%pmY4c65AVv&hCKzf@p%sxARW=yOuJIhocg10O zcQ9@BBw|eJ3Ou&%N}U9nSaOVad(L@l8P_&Z0}f zzeBlcMg2-f<-=s%7FZ}!&C~Q8k9*_O?AgEES3&)QNpfk&z1Sz4?*?(HOH6|C_K&pzT z;^9moR?&ecNMpaB^OghA(Tnn%fdyc6;HeJjzGJZBg1N zRfW|BR+d()&HkkCVHp`cEmd7@ZIy$)&F*M83+yPgcXV*Fe|&hlZ!DOK?V6jsXY3;U z-bByfAUBhQ-aaprg}!diK~t~O8IIa2(UX`JcART!#y>7REjTGUD=+~{)n?Ou)}7}6 z^yIG(OqBE_b*0rMcBWRV!@+dmeMaWDCI=H^gQJ7n6MWt?z?l;%|QEE)5o%btEHbWL$<5BX{Plez|Ic3K+;7;ey z?OV7npDo|^a!Qe--FA<~<@Q!jAwDf605~9kpEH*$TCOkrDsIL9)t7fbz5+#qxsG>S z5I?*xgXtHsBT>u&(S-iAdJgRgcK46G2>Gq6>-o1irdc~1v?7{i0_Pq+cCgASMBQNK5DT4^L;(!@ z)M^`No4nwt`0g9mgnryi>WNd{Q-%e+9=0PxW*|6T#n@n5+vZIWR~G1{b@Z>mr^ z-~tzz9CF=+R2XNuT8YzDW)TWac1Rkr2VuH`c+=F2Qu_t;Cu__$Vu-x*4J-3j1X#fs zK0_6WtH)u(71MPV@9~a4^{n%T`12-FK`~v0IU)sdw3uH~gCdqW@@(+ zgLGhVTH+gcypQK%-nq)E_LBov>jlXUUrR?5vZG!Q%4Ug55YL{F@i+-0y|-i;AJc^e zF0CvRkr=bFP?ME(XxXkNj*6@IWXkriNqmtTu=aYJ zlvP%T13I!QRZfHKH@rduuE(2i)~!=&pk^xy&j>!~c$8qN;C{-MPf?Qh)TRj!@DD34 z;~Wzlv{RmxftQe!v+sO)@sU=>L3;cEu;4b_6#L$AL9y>3X6)fZTseaV&f;WK|Iu>4 z48%CHLvw!-k#7S4$mDzu?I?bC{e->EbKrzHqMP*7074&Y12zss1M;$rw=pe7c?v$>tZ{W0sTR zl9zNAmxr?|%kcUb+2>m1=eTkJN(j2cC?mn1<--t&w-5XgQn`lrJzi|Nf3R&mFW`Sk zt~LvqMW9NJKsOO4f;31a=_uN6+MI@cke3G%;R%0anNyI*qHkyf9V9C9hg#wU7R}c- zh!+n0gJl$vyfQQW0ld`=tvh@3wnvZ2(+r0t&--(GpI-gd%gEv#i zPI~>}02C}2Z1%f8G(N3Xd0P;jRC>d{2pBHd%-7vWJlf6D7K#gqq^aH@7_f17AS7P$ z6By~$**dz}pX%NK7?JDW=agJ$BYe8n^o{`k{m6s=77zef03dTCV_OGXYa0L%VNq!% z08B%72P*(fQwL*908A@=CmR4v0MOre0e))%{nmm80Q}MXpB8@SIB8~qXR-z0gZI*S zI`nf&o2~ye{r=}6q}W?;yhDg&wlG+1d@5~=$R3Z6fj~JjQ4On+>-U8)(5yW*^Rg$m zPLcGfz_$zxUKM8bTMp8QZDu33*gkJ<27*ClyNl9Y7@whZ5iUQkug+rC*PqNdRoKVgi~##A3X(&L9Pg>V8dn!KlSZ$&y&K64m!(H6u;83n&`z&- zX%&jJN>A8TE$@3&jYO{-&6`*k+b*zf=4G{NcG%ZE?+f4z8ghn^IYZ8zVe8D2be317 zE;x6VWw?pC-gaLf2=Vljc?8TnLhGKPbgy`R7S5#Bcu_C1J($hWM`9$$7}ttc`a2u) zC|Y5B%#{q6xsm7$b==YNM$X)-9?B_PEMjgHxvUa64^EdcxyWeOnVyG#Dez&Zg6`Ea zLyHy4vy)Br8JlxdOIS|Qs3|CLI4UbTR~9vo)_nCO{D688Xsi5=_2Tj$J7rZ|(A%3I zzL)JFvOXRtxGd%b6FY^74x@j}8)LgR?ndUA+!;-(LXjO@i~kiE2nDvytE;Y^$_^;g z=^L+;4oPgF-q4mO@XBKv#Rd7|nbJ%8cu=F431N*^Raw;cejq=yL`y(q0rgjWxk470 zyu}(1`;7dspC#EnF^11w*J>v4T=sDST$O}r8bNWZgU za{v3D^|de|i6EaQ$G`AJfA>^7(2)hrl|GkfQG?|{lm2ov=(?cF&O<$7c_eK=As6v# z1SMn4Q*kL$&RaAR$P{Ir@pER1o+c8c2{9TYXbb4(+s?{3fo+M!&bH*>GPmb=iObD< zdHDMX^yHzPDSIIK^$Se)=rsX?BZDsc>XX&}*ysY^BKj!Vh^6#xYBo*1`wM}}E%k-NOJ znqicKiFqw1q4B<&((oh-`=hsA_9Hvu`Ys4C%C)CkCFI+5oJ;o_+fnJN6NK;QwFuM* znoIF>LPhpcBdJzzTzDuUJUkxBD0DoAs7_Kd%DG0^ap=btJJxYucQ|2sAFY*~;h?K* z$RZnQjsat?EHjUpo)6R1*1QyB^Hb=uw9WaqfmuxKLheZ&r$&*uvVoZJ!O8z}-Z;L- zk~qJ-<_vVJ*pqo0CzN>vhwRat=dAkV5$a2}=G@x5v?bcutN7n=8X{tH9U{YBalXVq zZPK+x#wTgRh55p9O4l5d`OS}tv029AjACewz=AYy|U(q;n1tT~>N_9ojhxOqi~5tgVQA67B<;Yj9q>%pR@ zaA*3Mxm2e}*>0m;QF$`vkbiK_c%X6^egcLqy;q<$B2@~u%!=W~ zXkW^g5|J?HiZmuBFN~*`E;Yt1uN1FqY*@Ct{09Bg9Z0VtVv!@_RMB0;;GCI~!sma) z3M-s-ablJ!;^D3fcc*?ZStnXYA=H1SIkVu5f6n*ju@B@(gDuHAW6{V-ej0Q>&Tr(7 zHtqSx!HRjJ5j(}LL1rOTNcuo6$03Pl*bpS9dq2p?N_K`TCt=_-immU%?^tl|5$uh{ z8Sv$Fe0jIiKddTi@|AZS3 zzUr9bgh#*_YfH>^9$L=I_*#IjelP7FXKV1-@How>`Xuj_sIBKK5|Rus^Mg;9qm6C% zNeSKz~M~XaRg@~%62NwN!Z0_X~^=F)Gf?QIL~L+K2$c0uI*zx z-e*lPU@B42<|Wbf7OQ*~wIl*YlvCUOEf$>Pn%`QA*cZt``UOX~*k2Gy9 z+TgY%YW7tfvD$64d2i}pgScjQ3~wD@+aGKiy+nCVeXVxk83Y$1O7&0uiA6kaeq~&z zi#rbBHoYFVBsX}jkT|YxH?>g%JT68tvXKDj7+K|+v0+P6ZcHccwupIC+G1%Ly_7q) zp%VYBTvRGz$O$K$c<~f_v$2YLwOi`YdivegA>vJSj?_~r_u%ZaUh`lrf6T7BLtK*= zW=_2#lfOytsbu0P5SLdk!FhcM?&^@pq7-EM+gCHLLG|8q%#H!EKtVh+X&*h>= z=AzH`tVj1ufXNUhg1sN-Cww^qh&@PvEsD4zEeaX4OCGbwF1t%CyT?48YUVs$Kw|tw(nc)m#3@Gd&|!VRoScOi#TyaD#{})XN9>8AJ+_?eZutVJ#|g0=Y4rw z38(=)s3Evz&t}PK(=j^ES^m0MO$37zadk`19Z&nB^c}oZ=PnH1Yd_rgaW@D&FhYxrmN=qJVm$kh>DUh?1bOl7O<3knlPH?gQFaGHN5Oyn_9%dR&&PW=1o&U7LJZJD z3_(y05Ks*vk_|AH4S`t=kXQ|&R<t;9J=x>U>h~SbkgyKrrN;sUF=Of475dg6iV$fb?b@tQs-v4`P?hleg&ld{pm!=W7BYZgYW+Lz089-hEqRu?@4!B`_95hMsK*l;kjMWVX;Vv3JiAn^)fGD; zQm1gzOzJn*^k7q=B80VaQ3$8-6^5?%)!$RbOxb_D7*<22`g}#|W!c*6Q)kCfyRCx| z2EsPc{Lf#xs}A4hkuk_P11wCQjj|`011{Z zNWKaMZt*>nE|FSkSnb3#4>~!}IDGL7rryYdLq~tFjW3T!YY~}uedNMjrNdB=5f2ER#AS*e7 zn9YaMk19&W$;T+CkF=Nsz2c&FmyK&!>XlHxd3R#>55iH|uRl;h%YcsRaiTHgCY5kJ z*=XWXbM)jkt8o*QL0g4N)rGJz@_~AHi}-YwO$cP4gQ(0rOvQ)-7q!X>l7}+{WK%bg z1dht*K{*zoopw@t(3eTbn6hhR4oHtZBrfPR%N|01uhYv6!LWWnSG>hIfVAZE&rzPD+f}{AG6PnAQITQurT>Pi z1TA0c_2Xx$#RvKG7xyrqTU}HvFj-(j z@7uZw-CnK|=SHF(kZ7E;8=a1hV8+iG?LErMX zLC4%f+?yIKo1)6gSKmKlXTR&RSEi-Jwkv=KQoTvL9wIFB8@zoP>#JYc{)836*%ZE6EugodeU3pV~s z$~q4SRAmhz+wuB$+z!fD#%eW*pub7Uq6gs}QEqMmV!V?s$L0ahaP@3E+eEYvc%XQF zF>e02?TmW#O$t;D!PbD&x$K&T2Mcw1bkvmEThpzuzBiW?Icn}4aKM}h8;+@%kX1Bd zhRn}WJZHN(`O*$>yn)b1FVFxRNB@vn>Xn#5`liQf2~8q0j8$@2Vpu|~J<#gV)RMNc zS>dm32XSnAdJT6*{kr_=*qbr;6>vby6YnrVgmYx2;th;u7JYm_Up6+drWVPnEEF_n zZ4hK>bPrro5e$PEa8GwD^uCFA^+=2;QMvl~PkGV2PF=JDD(y)JH~2+-1JwvW&Cm8i%O}Fb&M*I~ z5qB%QuMn7+N^qY(wPx#CvPad^?6t~Y?SD^4dp9eZMSB7Z-cDy6$3Q7$Yd|r;c%rPN z>(W1(TwcIKAF7>~r54I){<-P*KxLr&w;fd-?4C0mRlQ8v@W&>RY5dmzqfd*yJp8>KLK1G- z2dID*2(J9%)<>pRR81Y(kyqZO8%&oiE`yey0vmcO0m~4=<52&3Rm61PUz zf9HL6W$$^&nTW^;N-u@P4-0MdgCu%ZGaP`@{{Cq1;Y%zgPR0o7-yMcFq#%IXz=b6% zdJjMFrkL+-?PN93S_W4oa9F8_p`ah6RYe5YUSG%GIBl6xWJE ztX64+9c`o@qGDM=Ut%e7-b-~epxwvJ_9ANz-hKqpUO%iB5KY-3B`N5^a$s5)f^p3a zW5v}?>>zFUKd5>OsJ6DKTln6V0>z3IcXxMfai_RDAy}Yz@s{GQ!J#<8-KE7Hfm8moYNW+-uFfGIGYqI6GU`QW>LsTaJq@0qGHg+!$SK@J^ZMFuaw&f3q*8 zoV9*`HK6Kygi6hR@oe()a(I&RXp(oawEl|-;(9N%!h3ertb&=%cYabV>}7paC-kyb zuQG^N34@6=vq1W%x4s(UBGIq z_H$H;CzG0W?{}v`MkW?Y|c@~p6YS9rvvpD2^GS)J)Y~)AntFy(}<%uEa8iX3&k z&$hK7{~c`KH}63YTUX6H81JeT=qhba7U^lt-i@QME>wk83|Yho^0smZ9TF;wTF#NEhuZ~jy}rpWe)V@WuaOoI88A0s>^#( zhP#$N*zd|Q?Gwo3M@sVH9d*v!vIJb#WOoQjz!Q~RY`!kH_dXl!HmPJ&_*eK>wP`xU zHzTf_O0Od$sDrozT0J^VEwq*zy;LS9=>SPu!o;!i4xYhC@9}qte!!OKFmG@-u^p6J zwrz!Wjsx=|r*1{W^*xRIn<+VD-Ay`)YJ788@Z$pe5+>>*{A09c^(GVCL>PTV6F4#` z^i*S;Us*IC5tP%sgF_*HH^7V-%Zv_|SprEtO5av)3hUL62VX&T&c{K#tUt(zeI|~D zIG66Z0r5}B-mtmzkAb}vlj#NlA=2Nr1G|&OB|>Ev%xPb~QJLTdON7t8K;^fiYmv@+ zkD~RC^lO-k7SCxXjYdR;w~xwcULW7F>RjCJUoN1SkU&MGDp_tzHqv`>Imif?LLxja<5p2Sj{ELE#!AN9d5Be+Sk7c1!G?44-1RhUe_(rQ2xqz+$pit_U^y zu&z`VpDZd+`&9++IMcS%Y-(mkh2GU2ngscLLIl3#E~RO4%rIv41*WJLV$o%4RdgO* zL9iOm2l%u6YrWGSlOJeV&sAkq+&MPh+7n5fab^LRkEzY~Fp!~@Hx180s%sH`eD6Cf zi$ENS_#QK&O{Pk0UInntH`v`%c4$E=EC{1!zw%_ywOv3$GzM+M9>PWS++*>-aZqGM zea+vFfB`W`5~)~Li=O}o7*(%EYMkr zDw6C9x-Yxi7YYt(Fj`qO@3+OIQz&)#bJ_OcI@u-*EDf7IdpGS&j&0`0*xVU5W*MFO zQo1Yaa8{cq+)Fkv)3t3;VH^t`{)Q-#^_mOMqRLER9|oNp1pe`ENCiF*5!!nF>7l)@ z!#Flysya|Ucav@nRdh07rsB`vss`{C-Ag@8gNj7HW$Kaf8b88#h8F?VeuUi%V!c&Q ziF&wZjjohtr)nz%jH^0n2E2N8P8#Yyke!e`;QUvQ@oDvJt#pj5!SM}`{ya+D)oOiP zpZ-l4gG+Jwjqr%*@x)|Yj3}Sy=l5-6Ee$4lppXyFgY6Q0qqJgjLOH6>X4`9-n`m@c z=bIo!Q4d5_^~4;68fU-5z`HG2M4Z|zeXosN=>n!DxV&n}#Q``iz(BYw{Umj$N!34o ztf*9!?Ar~+YPhIJMN;+@lTf`d+2(Z-#%oQel^jEqpz@CIRlV>y0M-~P}0L*TsGI!;nbc?VgadP zM(3a@=XD-3RDHj4wDL^$xSF@vQLJA(xsb0M!DobB3*aj!#rEhTotobxn&XY$3@j~u zS#`(;NB18l%=PKX7laOqs!(IB>0H&W5*ftR9k#imKKLOlkz#qyQd1endTHX1Jez*8z+>H2j$BG6QggImk*0j zXRD(E(Bn>C8cPe`s5TS%#@hyJ8H7|mJi88{?x|k{@OtKJ?iOhVM7=YWTolxLkFFk! z1urdOKoGa+aWJ}bzhh3mE9j$Dp&x9XJ<~;>1);JkQ{CZbBLzniwj3;^UX319B)@D< z`bN9rUKT+(nMrL%5&>)s5A8Vw1M&&Yd^G~jeo<1{vmXI6p7HN5`&q(b9+$q}#$K#` z%cz~4c>T#|GSZk(GYIh15G4x}Eizk8Kk{w;s(rn-Ebmd-;DX6Y7H;UNL&$Cl3B8@n zAM|8{=1Qwx`~Ju}c&r|}Yn926FL1OzFWnzdyxz=xVu4w=1qS}Gd?sAX00wE1Sp~VY zG(uR8Xc04*dm~(>#*aCnb$qk#FAVSY5w5;0go|vOpXA+(>InvXqL@>QT!<@~mH1om zqIL+W&HJzM>pS0{cl#HOu=}q3m~{#@;I{B}Ix-+~_f>?iOJil>+uUjE=858roiIY0 zZOHds@C~D+^r8kfaW5}{Q<1QWM2M8C6;iiBcI`)zmx*UC-{A2UUpcGGhWO;h`%CaNvqH zA|a&y*oKQoyHiBs8{TqFtbkJTr&0#UVEFvs?lL+AR-zrSxSC*!#9Flhde3{2M{_wP zFS!k;79tZ3sYk5EE1)D3vIeZA@MSgusXlyel6DsnRN)k@r7iH&e5572wOaulk!QcQ z=b_>dVdlYMF+-%4S2!$kJke!XZkdwa;rwVR)JmTJV|2`@gDSr3!Zcpu>2dWu)jk0+ zEA0d%5%;oW`3F6s2tT~e-z@8nUl%Xad5QPQ(dr4&9o2!xNG-I&xss@Nmyb}{?(_X8 z*Fg5`^6M6?b5zSM*Anh?y^a%Xh;VLO@ms|@su(_Zp+=MiBxXoTKjaZgHq$^@?IU}5`v6aa z$=ptPQF2z~?{OM4d}DS)GX9dTi9bGD_qlq5=3`C@WWe=gpz1u4FZ~3oCAJ`!80DDz z28fc z>iHwjO}C?Z2j+eZBTyJAWggRyFZhgPxdbCG|6&z;Hh&W{|IDQV%Vx?6q<^o79d9}3 z|LY(Qh0qK9NtIxtdkEnJvS(w{w#PuB&%Row0h%r_O4jCLVxxZ4^@VMFVuiTg$0C@} zBe-Dl=-|%D3@IBAcp00hcGq+otJ$YIS6cfJ2j*@$LqlzIwk7IPOi!dRncQ3`jt;W= z$+2QVF`wHgVozhV%JJka$>m-U&~dD^YuWH&D*y3h=i%bWn(^uYt+Le5YV@wA^O;@- z`HzR+RqLsTqw}k_Kq;Qb_fSKy;}|!M{a)Gn0fI-MsndvmMP496B}4Yu(wi{$*bR^0 z7E!&AB*DPsdM!O_5^7AQNoIu#hKM(WVbVu9t^o0#bBT_^scexP3Jl_3rz* zT$#H%t}iALvLpZ}uhKb&LEi4KHuhZ`{@Wx{{vn|t{gm@LDErqfXbDhCpD>IrO34ab z=^6X&!igchhAd`M@UK@M*!-ZbF}wsZyoQXC?rTimaAy|#`evadxrE1gLf_RTuF->b z;j!YlAIDHCy_VM+jCXR6#Mk#xSeKYyx_PKoc6h9xa!k?3U42kL-bplHq+wzwPz5#R zK;Frmd1uRLS3kq^sqn!)D!t2+i#5;JWUgG(==~P^Y}qNoVg&dtjR-(UtN?#^5d|+w z4M7&j3?5#^x4;W?$ZOKr= zHcRNwa~<1fl9-2z5QUv@J?xczuhsK&AmM#NO;u3Yak9^hWNSq_ zI=cMH`Rp#3{uh|z#m>)cER0Q1k6l;IK~7%rHE>U^t6u)@ z?->J=IbjL^Hm(Zdvdem+g`{R2uLsz@D4SiwAR9B0<4t*4>szS|YT6^T9{_m)!|`w5 zqD-j%l!~Q=KUP+$k0DOfr+io=8AATbwu8V@ZFBz@DVY}D@673%zG7QTm}iN6NM&&#<_;v&a+ zaPj%~&#Dw06(#7=TzT9giNXMP@bZSgoOx-fbXKiPAZS=;S2 zvJ2xvPDA_IhGUM&-N#X_jX~rumed^AN)Yn(2sBQ}NONT;qr(g2oC+}e-ND^?5 zhF$v9Rj0we%B57#`((zVz4&7(Xy!w^t)0W%qK+jc>#Er&2C+)V#1X0qM(4P(EK=a$ zWWKcG;__6SPUoNRcy_k;ZS%YRLhwwqg?@Zr6JQP50;^H z5bo~ONe{`2>Tdz2>LjwI71aDf^-<%N_A6JOk`1&i$7Is+X%@Bj);UkL;l`5BqRTJ7 z#rH~Ryh*pxd0?o$VAVss7C;$)lD=XmwbJQdC~lHdPf7PlO%JjL%GQb|$u+66j>UZ8 zw;wfB~&k)APH?KP;HJ%}vMIu);YVl0vBh$3KL6BMy1qM)MKPxxcH;xRP(T`B)2 zh;*1dyN7(^a$_d={8JqBAs%gW(Mb7}6%}pLZVK*$y66MHtkoH+7Z&B5eox|%E^c>8 zNaKzm<Fl5|HA|3NHV7q9CnI0hd7d3i0F9{kn;Ae z4?xPo)iFhJ=k`(wd(3#FaWy?)m_lflr(R>R@(z<+veEAP7Q4*icG9M z^{UX^wD}eHtpONiokhM5d2ELUqUI0!igLe(*yjGIwdvVk3+6g)H_IKkL}3%jJern^ zbkVH9EL|Q#d9?c)3l;2>S0{&}-9%|y^wVLp`>jOf3tq`)Dukr!+D%`=m%N<$Q1(8@ zD94xUmW>8q5_nD0Y<(}KTV|WTjxN=Dsw2vdYHQ1>PZ6br7{p5GEl_8(s?MDCC%qV+nxTq$=vXFjO&PBT)j0I>hNo5}5GV$^&9(~LrPzQJ=o|4eIPaflSpvy42u zYl$9F5_7h6c6Mk64VGT069)_Xd&ei&nU3~;t%VUCdU?g9`1ynP+UmC6F_b&ni%B(B zZW>{wSKk8uCb#^)`xC94UHYE09Br`S6NAWY2r~)Dg{qGwcT`un+lf_HouEBAW?U{b zC9aX^j9O{Me%g(>C|@*iA>xSJCRM{)b<{{yt;)HjWcP6KAwczOK#upqc>=Y_`m6s{ z#7n7nly{Mf5B9>X$Bigy%$OHVS!-j${!_TK*GrT4dz?d>w)Bs)o{iCONmob>06~Gg z>BGFS%vo!rg{Sg%Z6Vnf14y24#ApO(-{dRt)Ff=TK`P6dvwx>9~*`UnzA}{7yEr7BHvu>w`Y_| zmn!c)=sfFMr#%gL7$K5Z+c@x&stj5qr?xJSGXElxS#j{lJ06yQ_X*Sh?D^0Xe0;3i zdAJL|4b>}JZ9QI}6Y54vMD1QH=fj%+u=+*vdbuXeO*dG(<*JG>m99er3LTsK_E41L zb7z!lf1wkjMd<6hO*eR6jmKfKN@{ER#b&g(5Bs+NVN#UnN_Jh^MpGO+*&j-EK7x)7 zS#a8(d%c}14`PPGH&}FfBm)~OcJOeyahmd*;w~O@Pfj(DiIY5i>SkW-_9qf!Jo?%L zXhq61&#@^l;zL~)U*LBG<#WpMs)lk!)L?eQ2>x((^--_|Y;o6_k0?!0@bVsJAF@opk~K)sLhqV= zt>9wbCNi3o$hd+HMw##zj%j2yBLbIw!LY0i+Rr$(wkD!bjnPq}$!hRAYK$;#k0Yzo zhiqw)?yo@Z@7Up<$_6onUQM2P+)Wm%qGQAvrJrC~Wu|&@f5vdwUM@4oB+Gm6}=_hmjbp-BssVi zA&J&2I6h1y4=R~awl=2`H;2i71CP%Si!nD;%#Q9X`WTpc9}%?nu+{uaN8 zdDeJc>bxO;8h^om4S5}YJ@%%q7SQfbo2R>pdNzL*pumXyxv?fdgAvueaV9_&9htYW zCqNe+wYhO8K&cX$u(2gTs}eP}F?9FEN1y{=JO*iMjfW*lj(Td3hfi5)YI1~!c~ntc zSzJ*Zo;QB1j+r#VY~_2L>WHSjRExEiFFtkuVLLS48`W_i^nOz43x?)IGFJtj*Jas6 z$arAK5zd2rWyMvpxeFmhd$idvp4N=d>UNyn`SZ@fiuFm6vF5^r5SM7P#4)ZYy~W$z zkr<@S&v>ROjeiDmBAJAsl0{i5QGDGzcmp{Uj|Oj9t$$kS>iB|wB@S6_WSwpsQ{E5- zC!}Ais?7>-zg7bEC#8W4Jys1>Ng(@O{3BEP*7;E~jP)-Vo5;}{QYsskD(jjmo33MP zN@E)sCtGYMJ7g!@Vkf(QlWkFw?O>5@bCT`8&)Qn~KGWWLYw)DqxqNyi{LI!lcY68w{I~xE z`GxG0n*Rv-E&Vg3tTFo*|C!c*VfC!>nN%E;)hn`^0o>zvu)%pS{dQ1Y;U2=GRagjN znkgEz@zPHL=Wp9+>1Sj7Vdx*cUSB+&S?p!izpp61P1uimO^bqRUY0<%HOR9w9irWD z%p3X=zpZs@7Y}umII7zn7VNsIpWE2n0Qr5A3l$bD@`s!UoYRD_ z*W|G;sSnwfL;P~5O8ZK?uWFh_py2fz-KH)bia7?HiZ`8om3c~OFL5XkPhwU>ugRg) z8*giBW%B$??2UIq@_#%CC|*^}UDM(VIfX~%P*ale3VK;o6{ong3qRV>mQEeiMb|rD zlJONvPMwn|{F)89=QzU>L%HM>i-s3)Ey2w^;bypL7Ry$LFGCfpW4FuJPwrXRCdoY7 z?4Z~@^kZiJ;Ovz^WR3~n9-q`5+tbA&Ccr1Q@V27Cei8}7P0e;z$B0lj994HcI0QzEC zxPzHMI@}|3_g=xR&dG5dGmYGR9(O8zj}GF&VMFViDS0$|!%M{o0OJfYowKPXCI@qk zCGy)^=Iug5_o8^st}M+sCIOn6!bPP{u8XTrI3)u>URjN<>Loc@haJ8`CnR?6?D0UO zp|l@I+Cni_F&E#c`Wb%cIGZn##BAn&lW0q1-q=1jaEKb>iGZ;2>Qa4Ci2BRTwQo=1 z1Jk#l7|4#xp``aAkb1!;4}{S_?_<#Ksqizec}%4yp$X=S

9MHs_oj@6Qz@1rU$v zJKYc?qyLh*Y-f3^UzKo7mHYhXY|Aa@U_l=a`^@HS{QO%>w8uA7M_-#l6{L)05|YWaA09hc+Ps<8FF{`=K6b?z}+sF zNEG%!{2As<3!Ogmy1G>u`LTOz_elfr=$-eVaqV0!!sAj$75g#s<6=j3=R&7_j<=c_POetw&95+a~i*{ znu17Z2adNGTTgP8zRYfNEOT5-7rtBNqdF$fah$p(ru;t zxU=0})_$soj4Q*4;U8+^Hu6A`2f7Bo*xBm<8^a)0W+i_5pax|zM(y2fnXpWUT{YX? z;djh#Zw<@tlNSq0E{O$ehX4$lS4;?N%i}&#SVxhRL_# zmBNvgYL9)#(*^GhX9VT#uyIH{dxvR9+j+sA&P~!?;|*)+vG8Lw?@hZe`^(Q~ikG}4 zA>EUE;-pky$bjr?Zr7IKd3%G7;mgNW$H(3e^MAK{Phiy0VVb&CnQl72V8LZa1!w|S$SIPwBjy72@q(>#NUw8%1X3VfB5*ZD85*g&L-0V|@s8BBg& z0!G&(UmFet*9}M8I1FiCbiYLo9qrgvvJiYmBHyR(mAz*;=M?u!?j9R}HL3la_SF{h-240XX#8>2C2 zzFDVe)atkh!^msHjd-8b;p+F}L>K4|#p!EXu%+nCl&vlArG!%#alW(fNYw$dA~lDc zG0VPP3A*qx=-{}g!zilpP^IVbBkQTp;|HzR-$?h=PN{Upv?hR)@jghTIe z_tfQb43(;{3#FPfoPC)giKWFg9ci}B!9;c=G1c*22jw=uD8UwB*Tz(M_4EKjvy)8-rxXdB2)QuImoKkL31zh`{ii81oOCr-cb@4OrT zVf0%@TSkqf6SiV-t0H{uZf|4-PZE@QJW^WG+6u4n`7unAggy(imoh+dDU7)1YxDi? z!r*P+wMU26$B%k4n#{JgHNW)Iwl^2jSf|qRnzJr>RD*d}+v~#{!A2v}T!#lt=W*(d za~WWp)C|`jNsn@Jl3aNo_1Bx#nV&CK2%j%z^pBIvphWlv<+DR|vo@JA({}Cf1(!se z#eA$zAI-d)63!@Zl|8SQ%Ep$PhJC*MiQ^W@8;W9?7xwfz$yT3J*6CZ{MS84jwu1#& zv6Rs=bymOY$SsZ#C1<89dM{MI%Z-cqkW)7=Ytq{)C8(SlUsRUmt``?Pg_EM zh@aI7C8sSEZ%*HENHd|y={z{CS=qj+oKeyHrkB0eS}{w=&8#lyZO`aD1Tjb_nzo)Vz#oh$1CC|_ko#b-h%r#AC_K!zh>GkMP9tpKj!tiWf&1N7S)I>4FSEAx-8+n+SR($c#0O) zyz+N7#Bl{!dI)jSSbDf|(wGZm3+sw#$;Z6_CqwXWz~fgvS~kV?8jk;sr7Q5{XW*U#}YKAJ)wu2$(vitBV-^6RNk{k&*aUi<#nA6 z9HSEBZjf}hsN<1|F#QjZWg^V$kY!*$q1x?G!&m}!Sj6;(9P5wi8_IeH^$4nZEk~?V zMM2}k9=rB$JAHE#xQL(J97W472Tpy;z&Dk z8N<9$dH$Hf9TxaM^e=bfJ_n>K7>7G^j{{OQjPA%CvlZ0!A8kNy-L_~1&6lIKx>+NXNenDsJ?sf{^y!e{2-t=cAJ(VATJPOEbCgA~EvwavPOdI~};%PlLVaO&#+zqg3vd2x1 zvZ%(w9M)|0^e;Ri8MfB#aZkjABM+&I$u;}h_HRQ9d6W%CI#z+T+bNL zDOEAiW}c1m6Dg&d%S-+g}#S~%){VISLdD}1J_G;M=4vIwU zu$<@pM&f}heSX{NC^a1LZZP2EW@PF@di4mI2B}pr-3VG#j?3yiXt9by=^40Zm;7Uj z#_8s|cdYBwuV{zWG4+Y9b6Dt!th4{(B|{u2=e4 zZGooBA<}n-04J3e-y&Dud-d;S{_==~p)Z~EAOG!u-iX)uVe^K>;lsua)>2mQvEY(% z&oO$FXg@mD4TXZE)P5dAdl)Qoock_g%_VaDy;%R9VgD{cDvo6|XY-H2=M<6egLWLA ztaSY;8KxIzN@P7-dP-T{ThctnJ?qj(%ir5wiiJb!e(rf881d&Gs<|!)R;1tap=}&c zRFM6dIc{pX^sk6sJK(5LSvwG@I6-#BG+d4@#c67Jt7Aje@c%mRbZ`i}W@?*+0!t0P z*5m6mZrHL{I6Su!FY>v9Hf(X!WU=az6#KupqKWsP)rMs#kB~?Yb7qi84sZsFe2+q^ zI;Y@U`4JUT#W~a7GR_sKbp4&I28~`rG*^~Ya#&2XqKKt?M00$Pa5$EG#>H!l>q+Un zHYl6Xui+}dxC%|$z)PN8FSr0=3}psW+LrKN1p~Y^92W)K3mRFw=f&DfKd?wHYQhI- z!Xb?iF(^Ga$059h)o9|~u&WyWaR%FdJU}4hK*QIe|K+5@J)p$f(B#lg_{X@Y{$zaS zbPf18P`l2&AJR^Lo#$5vpBNEekbf@AKJMvc8tH<+-^8<1cw!CWXQ2FCmqs)BeTE&( zZu;$gw;h3T-5-)8U{NMRu!NVP0Suk^e$Ew>NsqV<zgSK%&1qud&lBx@;@{q|dCH7Hn(+N!1TWGC$Ke^PULmAWLlIWb%=xVZwxO$oN zWdDXx^?NP$6B5ZL1=VErIR$4xmagN zZnE)=fsk%NlCgCA-vRFq|0J=&?&f&A)OBla zsz|`)c-mdzTHUwn-pnE7-7$DUhwCldT~S}VFV?M^Y=XWrFV(c5FzGfT@>+vh%7$l4 znOn?hjb^l5%57)zPp>lF4m_S6r2T)BSBd%0lQ*oz+*{0!pXOtK%nd+4YZFrP=K|o% zq4Ss#ATsy7^9aK`L3C{l||?e@rsn)0#V`slEI7UAm{#DI6@hW8^yQxMS>hfFP4_H&r@(iqiV>ds)bd?5KxR9 zKouHJ@gLFEK=_O$C5?&uS@U1=MGZj>OB46=7le=hYsAF;(@cdNZmNuhAdUGE&i|)7 z(?3yM{?o~ZuSsFCFb3dASCzd}srwy|BC!7Y{?%n`9NN))PqJ$em~Hxq0K2rW)ZcmA zFvoKF_j+mI_~Y&nPRHjvk#*w0af8jbU317L^gdZ<=v}+-;pFF;XO|;KoBSzVd*|Jg z^d>t7|H7m6BArfW=pxMlzaW3gLOviN!I2Fs44htf)cTpmssj$r4lSQ){2cU;l5v-F z_voY_9WcWR@EtG*<2zk{%2j*_t4@#1^zfC-U#2-mvRO4E$9CL>gIl8^Ikq?dLhJEE zEb@|vhg=q}VT&*gogvr`$&rbJ?mOq-k!l1QL2O#O@e*;k;g)BT zYat=zZ^T8OFz?nWWl^}*Q{w)h{U9W>LLNEekTeYrA>>U_`-z86fJrvYKZr5FBai-8 zU5%8BG$q#}qd9b&Eh2 zV+-VB8AIKFk+t9?H<>BmAR3 zYr#rf4W^Wv=+dA4^RxNPbc_)vjBS?d4dqT2R~*6r5!^xHg3ocyUo8I>NG%LWnUhr5 z2QhQ64Jj=F@LW^FT1UF{7h|o6XD5UCVQb1rcKe)m!bo|m2tU-36F>jLeFMN`2>L{b zI29}j<4ED-SwxHynqUZ$A>>iWQA3PUw@y5Fm>+gMWf|Z}NB@K)Hri(soceHVb>Kl@ zo*BGq-|vWco=(z9*yHH@WQEx|Xa+-kqWgc1FX(IhKfiqa3+`P1%P(P*|L2`@^eWm0 zzn~xYht9#Ao&Udw=iMm9zy4S^xcEHX^FJM@sK~D_#ntYnQI4_hCTb3cNS)5zKJ!|U zZvjq2F!DaZAg4E*C5G9V82izmgvJplOy8_gW^(*}*4I?DMBwt*hkbVmp%{PUw#ze> zX7hB+;(k^b6B`E~H~E=B_<##NvaYDi@8m674>}S}fp3T;S6|PNNk}Zr*EorP1d|al z@sxe;rtY`Cn|)72_Q#v4ujh6NV+WCp>wwWxb3nH@cUjZF6Hr7LyAn_wc(u(H zgPv&po1XfyPBX$Mu+FJMryKW*w5)T?60Hk7901fo89hRDDXHzJf*6q%LZ6AcIYr8j;-(Ua+!Za|pwJ zdGD3Byd!I2BbXra!})9&pw`~q$XJB4c8soejIS~~%Rc$IVw9M{%5DKHTGP+#`Qh3! z`>2*3Y3sYMAOn(-jtpQLz(r@l26iHBJjLPKUWCt-RP=AV%Yd0K;sApQ1>ae;2GuPY zAG$hxZ1lpnm=)DNg_q=V#g*hy+5a+x!4cWM97zrla^zmQpbu7 zeJmTP1+K}g>9E?zibV?ztH*h02UB|kysXSnw+-_Y! z2gT()zP60-e=ap|YRGHEMl1^~N#Zc2?Wu3CZ&#Df<=3yAErr%eIcnzevq96RHM0}9 zqlPZ%4)d;|)`oVzH7k$M$7fAnrZh0T)NSM%*4^-?PME|02t%WkMutv-~AzmVG>}f1q*i%SBRcf z8lX^j=kMXjsu8yE1!+zTTy7Okod3Wj+GH$ln4_5`epuUiL6!~VEGY4R!EVYnNjch- zLb`VJ#Q(w&qyB;fb3)x@Zj!uyYC+O)-9?%l-^7aYPgQa2@O`1oOc0tJ#^F zmBaq00+lNsw*Dv64?V}1@wJEOz&Uz{+|@mUCFkh&6K$^rn+CMg?#Df~J4`XDm`wZO zGe)2A6QR`=_YT&A5z?Y1m`Zbj#))sy61_?@e}=Q8&^B15xiQmOv1lp%KLUz0SdTfA zy|TFDej$4XuQ+Zul~37!`{ zow;>1X~|Gf3dosxoL@U{I5?U#ZzyP8v9&Ywy?K&D$Ju2YGqcxKyQp?PlJHk;%CPwq zpmRUoWuc7_C!JF;`IysY%y~hDEn+m?lPy9yEm$7MWdY-oZnx&M20fn}29}9aa@W&959Hvx(ez2fW=X@eWpmwha{t$+ zH(SGECw+MxCS|AfdR=O0r+m7V=W1uva;?`=PdW2IGxxAGhxN_e(Ot0hgqadGRpX z^}O;I1@)L^gaQ%XVGWq)0kUf5CIlpsbUDqJHRNeathz1ouSV-1jXm$MHf){=SPHUF zs-59$7<#mK3oXZ+w+)5^lSS!Ud$-u~ikcaf2Bw7))6)2Il>dmGy;hahp!Pe1r2k0k ze2HbL5uDGkH8B0d1IiWPQ+SEihS?;u-YX&zP5{{{xf_ zw$)lA+V~5$q2>CTZrx(A!jg7Px6GoOGtG#i#Xp(is-zeWFP;awUth;Hc7Ni2FB-c6 z{w?ALBNJW7MxD=#f#s>jPgi9=L}q$1$)U&{6hC_%ypEw3zRQ}GQd7rJ6I!Cfz3_a@Xfc_BS#TimxI9}Im1tHq#{Jg?PpG+poH~J5kp*k&jmF*1Q ziatN|wFa16%dMsnj<*jyn>x2mQy(A1bxc$HLSz@OvA2WxY;@AE@IjNwi}^;PlR94c zm2mYQe5sw{*fzF<2gXd4uZ7dG(Wd9NQkHhfi#}OmW8!pxX62{+v+iJ8&^l{I`2}^Q z03+oUefNtCTZ!z<-l@`3Q2CY>?mJWO-()o*z*P8aZhUZ)eo-@)tSeU&)2f8JJU>t~ zwv?S`(RZYybL^gG`P@huY+F-EXGj0@E}35X>5vZaWJlM1H#cV+B*uKTFcI9RTdG{Y zXy~8+kOvW89DF=yR~3^J3qQS)ca@)O|ByCV1Z8-(PF#(b$U_4uL|zYRR*qcDnpL2? zfKu)7Tzqj0y-22xdtI}89^nVgk*o~U9Bf*sAOGNRXQiHZjSyMQa@2xT0i3nto8ErV z2d0i)e$Gzgk<UGnQLKsVCMuFK!!~gKt^8VWuj9y7u$SR z^C%H$cD|cP(9Uv9;iSxRY)Eo;KzEbSZc9aG$I{S)OGrf~S-`6YN+12VlckE13Q2!5 zpN$H3KX`eL_{K(M;d{GT=}w~PJh8i-O2LUx7ajkC<*>sjtHeT$feW0J7c8e4j5zl> zjJ|gkRAk#7*cNFvtTJ#(H&MA9hA9&B(KA@3n^&lfgqpi+z=sCSN}S0IJ50T8g((rZ zE=0A<^jez0YDF9s~`Zs$Z#i7F~d1Y!`Nj=TBW&*@ms=zi!QKTTCi_t}_^N^7Wqu@4M5t<-i zgb_!D&}Ar4qc4MNJy9~_0f}A3x}}icM6ME?$Sa8zptg=AV_|8c)I7ZWhH&H^vj;FCg**qk6V zR=^&EAmMA@AmoleE*;IOC! z8>AVfn)7l7QOuz9T;zd$PcuP(WX;&pp71+Bno{W^%W9qZzB zuK&3c{y>z$-y|WRRM3K%iluDMXfW!J_yn1-$wlLp9Io!K%|;#4p5J2Xbr^jlna0S> z{QZ3sfTGt7UP@3h>9^r{42yZzKXOIG@wiWu!3+=B(%D6OA9>q;1=kQU+3so7LB5x~ zu|?Tq{#EfEQTp-aR5F~8u|*MDh#^5*=gN`)(=0st%N60P45N??R79FxqwW(tE-LP^ z+EofXDk3iHmpWOf`Hu25JhILT>JYOAy!}R+85dMiUf9sFcwj56ZeRqGwJj|@mILK1 z65$?e@Z?*YnB{ayg!5^AEGdzOmXriD2q{6a!lTt)BXgC*I~1UF(xte|zxITrsl$zP z_n4%C3_{A#l-wfR%-p><(sR!x&aklG==5*qGLa2ksJmQb*4k^${Z!#r8VI>e(k4!;BTrMk>q9#J7GGgBb)*A=246B86!`r&t!Fx5 zPoY-B#kX@htBnO|u_r~fbNW|dI?*~v9~q#UlIS9?O%}UU>_57FPyG^HTb8K<>lT1Z|?KD~f&r!53zWSN*t^__)WlCYM9WJ_SuUK(XE zL#}4v%rdkf0<2(!$z#zF0JjSKiKwXIrqav4G(JN!fJ%3oFF>Uz04)mppkmmPuc#h$ zvY%vXm%zw+P$Vjuki~EAWRfk4fwz-CyO^ZVr>?QOf1-$L2y;_Jl{Yylc>p%&DN&=x zfDn}56Tt7TQb_W6;;Q5am(9hYL+1H%l@c{R*|wsp12K;R-lM`MY) z@p)Qm!@GNWbCP^Uquqaf+0&=U50(I|pURsfU|mvemoDUheexZkON<)R^MuwZQsb96 z;3!|=L)fGbkIyYzTGMWnQyXRMFn-qz>f4#(4m4|0_U>cRC~vOKKPcQN0xWko87JS| zRL~V8Xm>*|8r@1p0hE=+oV&YGs9KYM6`a$De~+-!7x>*T&K`9p>O&iiZ}+s%-S-!c1da-jvkJStc*?BbX1n$Sk!JU;ghD=F zq*VKAc@KFoY+z^0g4jFLs(nuCUAhvgQ3!!REL|Jh>}OZqkr^B;0wX@+72EgZvisL< z&+>l7{X~=v%V5)AVH%n{5BYMTlC-U{p7YafxZc(aRwgyX498^&k}ISpfSYM-FRO$I?W0rU8;B6C^9Lq z#Z0T1ZYL)(A`N*7lo;Vp{O-iP%A6Qz#1~m|1Qw6>Nz-?gAhKmFv%;d8VIoRd0eDg!|ePx76E3_S@wObI>gP%Yr7**}GR&x92Do#~D3?~HMzIXKf8_VgTS?;L3i zL}$J3xzmDCofdg$<%3h1@3}HXln!i_=n~_&twE3NqeX^@sE%dd?qv*q`E*3oBO=F- zqc~|r5$9dcA4e!+^dsW!tpnn>11`)7A4X*BKvqxRdD}uT>NLB4&zyeOoG~@Bn{14W z>?TzJ4(Wlay{)`wth|S2Ze0aTAInec&2M1lH^isg8GJ>Q_hbp}JTQ7DD(!JuiTLfx zR=4w5ov_|K;l24!>(Dh)0sV<8yIuQTD5A6D&dRy_YQ@_9GMkd(%>l`?AC-$*dt^2l z#i9Ggwex6rqzL|}UeSFd=c_$O%MDTN11PTDQog>W#_D z`j!eub(wJmHY5k3(%v8OObPjH*+n;bXeIV1(!V_3NaN+4r1*4FI#cOno^=P!&UPkA zh=xW4!GiHK2w=_q@8qEI!LeYgkj8hSKZR(0dwjvclvFUevu$6Dcfp%_iS%5&8qqr1 zDY-jEn7_y8S+eAj&gYT3gv3^;#|yd@Te>y7R?oF2eGlAo+aV;6soCWQ)*rPWUD)N{ z?Vyf<*CP5N?S|#SR^Z2TueUMt{F@dt*oVN7hF1!O*8%hxgB1-(zPA zU7|_>av$mYg9Oo8z2GNc>Mz+<+sIOkm)v^`&%-*GL&ab3+BVYNqJqBWl71S@tQ#ll zu0@j*RYt^!|GaptZ)OKw~k9qG~t)?ui z^xD4T&qVsYT(%rmrdv#aDyLKnpSD-^hL_`~qqg_8L>@vfbA!?+nm?rk-=qet;*Q+d)+pCLORo%Df9;ZSY z9N=;BrMUIC+{JLTNO6F!bNOoGvT1;~dSc};M(OanXSLMHpR?zJKhgcIabpZM;?@kt zTLG=wp^ddLy4&Yr*fJ9k>m6zAP;#u`NdB0#6efDKHv*(U?I!a{b4T)KfnxHl&9y1(p^!jPN4dt;i-RNlO zOUennsP6kQi@m4;K1^kwf{BzF3om*Zaxkkrr9<-AOyeeEb-}0;e;rp6PvnAy!Rc@n z)bK4Q_M6a~s$9WvMfRoWqK^FFYRsRPR!tO{RTC-)U1ZnYMElLCL!yHC#3C1(LCn>v zm218UN;&QznC@$@-jCF-=YoBZBJU73^J{9wt6g^p%Ee(IR|fBHQhX#hxl}VhKr@6w z*o!+fwc+5;imx*dPSaiZ1N_424h~;<(X~&~zt}5Vx%t(U!*Qz<4A-Y^Rw72sxbR_M zL2X+q>9M-ukZhd6v=l9!qfdGvVEg=mB~p`rJMyA_=FA7o$WPsT z`ExGKSa0;@hC}T>VgDFG(cV5;e@l<>!S`1bGCdchCN6cUh=$}KjYcY{iX7P|*}We! z7x=ez!V+-@{oE%5r3;X)h4Ro@P*^PPmc6)dM#zW5 z1@Z05P!$0V+{Kx6hnH+(0WM`!vC|)vS93)*4L@eyT)5P1pgs`HpQ*h$#hb(!l6%-EGFO0v%&}M$MRs?X^}l^wDc2l?C{-n=u!yZ8cTkCyOmI40dN_%i(g#th@Zy zh3R@7kku1IwvxaTgp-k_E8N{^3=Vf;)>^n*Q#SM?5dHhm(EN##`aKu;SN+D)U;1wo zj3yy9a)~N1JPUg51+4EQI$)vsWVOp?1 z0|%r1*$8LfLuNG+u@SuiA~Q8Qk;T2<)JHO@4WKK+S6Wtp^BYi3FsW%}8Ol>y`D zH&x6WlpkfBO;#DIlz=cd1+L0C$~W5E>C6Za6$$P`EvdZ)_%NBD7?7$ev02`6PZM)3 zrC>q{s9FHbaego-pwZMLw7C^ytTV^|=0}I(F(9@|%kgBvH99jnj?Zz*ic6b0gWF8a`i}_h*MQT@~%y!uIDzbA9!rezBZ6%aVk8 znt0RX24vtvf1jMpCD~VhRaJVrdAP5ytgQk80{n$}1^Kp68*4IYaza~E3w*-E$YJsu z_0YkN4E>wGXV>W6s($KECKf)i|DCLO|Hc22ta#`D0}Pze@A_T?Jx#w$s%*XW@8|rO z2U+L@Nh|SWWQ>oy{%tTo5%;~{lTJ_lh!lzV-skENu{#uUii?Qjq!bgKBdy*Tlu8ZR zGYLqOX>eKmBb`&vKpz4c%Avs`)wW;^%;`ohy{2%d(N8bm0qv;4h&Ik-& zDtjpA{136azlodYW$wL%CYrnS-~a1gnN5mK(A{6}g#!L4khFgBuq0D=$Ftg-@~-+f z&79PTK3Y>E*%TB<}9{J&O97`T9 z4g^~L?yivhceqDSV`t62sVg7CMIGVFz64iTLI^LpNR;NG5BNWxae5XPnv7tD@w*% zDWx+()8e6d*P&TG&;l1|kt8&u3~TBENl78a4UrzbCM9f;Vv9-f6wTO7&G=Ex$Mu>| zcA6X`qd=7>cUTnWxfLj9tLFu(Da=0eIbWhad(iOq)UGJO4gzp1+9?HiQ@fmCF)@N?xAvcpf$efW;tf}{0}T{eJCu^~5`!H&Ap9k- z4s~i5S5YU^gDxSRWa%v(`yTQSPK?EhYm97uiFJPAb!dt_DG8>D28N=nerRHrUquv( zYzLg*^}J%?5k6Gatag>ske2hw-{!ifJA-$*cSGjhrzov!#;c6QjL|Fn zZ7(?1lYX{Km&}|y)Aq>A7u3y8=%l)VI?V_#s9qp~0%4x&0mAzbGN?YF9$^CgARVa7 zo=`{i2KDL@wyB=jjwr%YsxP+t6ro?x4clozs1o$T5=04Wf*x4B6QMxR2iwDCMmDMN z&KgypbO%xzQi3K4U~fusBg=~qzH3riL77D@eP&;ID}1UfG=?e*H$M+OTtjFD)fcr) zn0*zj@Ts=YAXXOAKFdE`n6HPcs8@WcuNQ$O;6Mqb zO)f=dQ%EqK*fv5Y z$yF!*7hzP>QRnevLcJzj=Sde~N7ES>Q#xO(=Bb)d)&m2MIq?phiJS`^10-I!7Riz< zx{?0@TBUnVDYfKBB-2FEmwa^3>brMWz3>8qL~ho)cb#5+1+1mmi3$*}&B7dEP$b8+&2%;AS}2pY_M7 zPR`d9#J#>}IeImGI9GyK<$k)ng^Qar#VMYOKygT(*Xyy$DB#b(tFm^l*h9Q5R6q5H ziOZyn5|`1A zqRN?9H8wt;ox;d0bNlh-+SLXI@1`m_=DNVD} zu@uWu!D=|V1N7vM`3=z@gF;@gHU^;FRVUbWq?ghF{wk7)iR0Q3@TXC4T+o_=;h3vJMs%;Dk5Ap3*fJKQ&2cy psj%n$fJ$y5H3ZbI{&joRV#LmkS=BE9<$FpQ0" + + searchState.loadingText + ""; + searchState.showResults(search); + loadSearch(); + } + }, + addCrateDropdown: function(crates) { + var elem = document.getElementById("crate-search"); - function clearInputTimeout() { - if (searchTimeout !== null) { - clearTimeout(searchTimeout); - searchTimeout = null; + 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) { @@ -205,65 +345,23 @@ function defocusSearchBar() { document.getElementsByTagName("body")[0].style.marginTop = ""; } - function showSearchResults(search) { - if (search === null || typeof search === 'undefined') { - search = getSearchElement(); - } - addClass(main, "hidden"); - removeClass(search, "hidden"); - mouseMovedAfterSearch = false; - document.title = searchTitle; - } - - function hideSearchResults(search) { - if (search === null || typeof search === 'undefined') { - search = getSearchElement(); - } - addClass(search, "hidden"); - removeClass(main, "hidden"); - document.title = titleBeforeSearch; - // We also remove the query parameter from the URL. - if (browserSupportsHistoryApi()) { - history.replaceState("", window.currentCrate + " - Rust", - getNakedUrl() + window.location.hash); - } - } - - // used for special search precedence - var TY_PRIMITIVE = itemTypes.indexOf("primitive"); - var TY_KEYWORD = itemTypes.indexOf("keyword"); - - function getQueryStringParams() { - 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; - } - - function browserSupportsHistoryApi() { - return window.history && typeof window.history.pushState === "function"; - } - function isHidden(elem) { return elem.offsetHeight === 0; } + var toggleAllDocsId = "toggle-all-docs"; var main = document.getElementById("main"); var savedHash = ""; function handleHashes(ev) { var elem; - var search = getSearchElement(); + 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. - hideSearchResults(search); + searchState.hideResults(search); var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); - if (browserSupportsHistoryApi()) { + if (searchState.browserSupportsHistoryApi()) { // `window.location.search`` contains all the query parameters, not just `search`. history.replaceState(hash, "", getNakedUrl() + window.location.search + "#" + hash); @@ -357,6 +455,15 @@ function defocusSearchBar() { handleHashes(ev); } + function openParentDetails(elem) { + while (elem) { + if (elem.tagName === "DETAILS") { + elem.open = true; + } + elem = elem.parentNode; + } + } + function expandSection(id) { var elem = document.getElementById(id); if (elem && isHidden(elem)) { @@ -371,6 +478,10 @@ function defocusSearchBar() { // The element is not visible, we need to make it appear! collapseDocs(collapses[0], "show"); } + // Open all ancestor

to make this element visible. + openParentDetails(h3.parentNode); + } else { + openParentDetails(elem.parentNode); } } } @@ -404,18 +515,19 @@ function defocusSearchBar() { function handleEscape(ev) { var help = getHelpElement(false); - var search = getSearchElement(); + var search = searchState.outputElement(); if (hasClass(help, "hidden") === false) { displayHelp(false, ev, help); } else if (hasClass(search, "hidden") === false) { - clearInputTimeout(); + searchState.clearInputTimeout(); ev.preventDefault(); - hideSearchResults(search); + searchState.hideResults(search); } - defocusSearchBar(); + 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 === true) { @@ -438,7 +550,7 @@ function defocusSearchBar() { case "S": displayHelp(false, ev); ev.preventDefault(); - focusSearchBar(); + searchState.focus(); break; case "+": @@ -461,8 +573,7 @@ function defocusSearchBar() { break; default: - var themePicker = getThemePickerElement(); - if (themePicker.parentNode.contains(ev.target)) { + if (getThemePickerElement().parentNode.contains(ev.target)) { handleThemeKeyDown(ev); } } @@ -475,7 +586,7 @@ function defocusSearchBar() { switch (getVirtualKey(ev)) { case "ArrowUp": ev.preventDefault(); - if (active.previousElementSibling && ev.target.id !== "theme-picker") { + if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) { active.previousElementSibling.focus(); } else { showThemeButtonState(); @@ -484,7 +595,7 @@ function defocusSearchBar() { break; case "ArrowDown": ev.preventDefault(); - if (active.nextElementSibling && ev.target.id !== "theme-picker") { + if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) { active.nextElementSibling.focus(); } else { showThemeButtonState(); @@ -494,1571 +605,125 @@ function defocusSearchBar() { case "Enter": case "Return": case "Space": - if (ev.target.id === "theme-picker" && themes.style.display === "none") { + 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 - } - } - - function findParentElement(elem, tagName) { - do { - if (elem && elem.tagName === tagName) { - return elem; - } - elem = elem.parentNode; - } while (elem); - return null; - } - - document.addEventListener("keypress", handleShortcut); - document.addEventListener("keydown", handleShortcut); - - document.addEventListener("mousemove", function() { mouseMovedAfterSearch = true; }); - - var handleSourceHighlight = (function() { - var prev_line_id = 0; - - var set_fragment = function(name) { - var x = window.scrollX, - y = window.scrollY; - if (browserSupportsHistoryApi()) { - history.replaceState(null, null, "#" + name); - highlightSourceLines(); - } 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); - } - }; - }()); - - document.addEventListener("click", function(ev) { - var helpElem = getHelpElement(false); - if (hasClass(ev.target, "help-button")) { - displayHelp(true, ev); - } else if (hasClass(ev.target, "collapse-toggle")) { - collapseDocs(ev.target, "toggle"); - } else if (hasClass(ev.target.parentNode, "collapse-toggle")) { - collapseDocs(ev.target.parentNode, "toggle"); - } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { - handleSourceHighlight(ev); - } else if (helpElem && hasClass(helpElem, "hidden") === false) { - var is_inside_help_popup = ev.target !== helpElem && helpElem.contains(ev.target); - if (is_inside_help_popup === false) { - addClass(helpElem, "hidden"); - removeClass(document.body, "blur"); - } - } else { - // Making a collapsed element visible on onhashchange seems - // too late - var a = findParentElement(ev.target, "A"); - if (a && a.hash) { - expandSection(a.hash.replace(/^#/, "")); - } - } - }); - - (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; - }; - } - }()); - - /** - * 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 = 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 (search_input.value === "") { - search_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("::"); - - split = split.filter(function(segment) { return segment !== ""; }); - - function transformResults(results, isType) { - 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; - if (isType !== true || obj.type) { - 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 (hasOwnProperty(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) { - var 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 !== true && - validateResult(name, path, split, parent) === false) - { - 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 = object[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 === true) { - 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 === true) { - 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 === true) { - 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]) === false) { - continue; - } - tmp = checkType(tmp, val, literalSearch); - if (literalSearch === true) { - if (tmp === true) { - return true; - } - continue; - } - lev_distance = Math.min(tmp, lev_distance); - if (lev_distance === 0) { - return 0; - } - } - } - return literalSearch === true ? 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]) === false) { - continue; - } - tmp = checkType(tmp, val, literalSearch); - if (literalSearch === true) { - if (tmp === true) { - return true; - } - continue; - } - lev_distance = Math.min(tmp, lev_distance); - if (lev_distance === 0) { - return 0; - } - } - } - return literalSearch === true ? 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 === false) { - 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 === true && results_in_args[fullId] === undefined) { - results_in_args[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } - if (returned === true && 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 === true) { - in_args = false; - var is_module = false; - - if (input === "*") { - is_module = true; - } else { - var allFound = true; - for (it = 0, len = inputs.length; allFound === true && it < len; it++) { - allFound = checkType(type, inputs[it], true); - } - in_args = allFound; - } - if (in_args === true) { - results_in_args[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } - if (returned === true) { - results_returned[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } - if (is_module === true) { - 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("::"); - var j; - for (j = 0, len = paths.length; j < len; ++j) { - if (paths[j] === "") { - paths.splice(j, 1); - j -= 1; - } - } - val = paths[paths.length - 1]; - var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1); - - var lev; - 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) === false) { - lev = MAX_LEV_DISTANCE + 1; - } else { - lev += 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), - }; - 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 initSearchNav() { - var hoverTimeout; - - var click_func = function(e) { - var el = e.target; - // to retrieve the real "owner" of the event. - while (el.tagName !== "TR") { - el = el.parentNode; - } - var dst = e.target.getElementsByTagName("a"); - if (dst.length < 1) { - return; - } - dst = dst[0]; - if (window.location.pathname === dst.pathname) { - hideSearchResults(); - document.location.href = dst.href; - } - }; - var mouseover_func = function(e) { - if (mouseMovedAfterSearch) { - var el = e.target; - // to retrieve the real "owner" of the event. - while (el.tagName !== "TR") { - el = el.parentNode; - } - clearTimeout(hoverTimeout); - hoverTimeout = setTimeout(function() { - onEachLazy(document.getElementsByClassName("search-results"), function(e) { - onEachLazy(e.getElementsByClassName("result"), function(i_e) { - removeClass(i_e, "highlighted"); - }); - }); - addClass(el, "highlighted"); - }, 20); - } - }; - onEachLazy(document.getElementsByClassName("search-results"), function(e) { - onEachLazy(e.getElementsByClassName("result"), function(i_e) { - i_e.onclick = click_func; - i_e.onmouseover = mouseover_func; - }); - }); - - search_input.onkeydown = function(e) { - // "actives" references the currently highlighted item in each search tab. - // Each array in "actives" represents a tab. - var actives = [[], [], []]; - // "current" is used to know which tab we're looking into. - var current = 0; - onEachLazy(document.getElementById("results").childNodes, function(e) { - onEachLazy(e.getElementsByClassName("highlighted"), function(h_e) { - actives[current].push(h_e); - }); - current += 1; - }); - - if (e.which === 38) { // up - if (e.ctrlKey) { // Going through result tabs. - printTab(currentTab > 0 ? currentTab - 1 : 2); - } else { - if (!actives[currentTab].length || - !actives[currentTab][0].previousElementSibling) { - return; - } - addClass(actives[currentTab][0].previousElementSibling, "highlighted"); - removeClass(actives[currentTab][0], "highlighted"); - } - e.preventDefault(); - } else if (e.which === 40) { // down - if (e.ctrlKey) { // Going through result tabs. - printTab(currentTab > 1 ? 0 : currentTab + 1); - } else if (!actives[currentTab].length) { - var results = document.getElementById("results").childNodes; - if (results.length > 0) { - var res = results[currentTab].getElementsByClassName("result"); - if (res.length > 0) { - addClass(res[0], "highlighted"); - } - } - } else if (actives[currentTab][0].nextElementSibling) { - addClass(actives[currentTab][0].nextElementSibling, "highlighted"); - removeClass(actives[currentTab][0], "highlighted"); - } - e.preventDefault(); - } else if (e.which === 13) { // return - if (actives[currentTab].length) { - document.location.href = - actives[currentTab][0].getElementsByTagName("a")[0].href; - } - } else if (e.which === 16) { // shift - // Does nothing, it's just to avoid losing "focus" on the highlighted element. - } else if (actives[currentTab].length > 0) { - removeClass(actives[currentTab][0], "highlighted"); - } - }; - } - - 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 = "" + path.replace(/::/g, "::"); - if (tmp.endsWith("")) { - return tmp.slice(0, tmp.length - 6); - } - return tmp; - } - - function addTab(array, query, display) { - var extraStyle = ""; - if (display === false) { - extraStyle = " style=\"display: none;\""; - } - - var output = ""; - var duplicates = {}; - var length = 0; - if (array.length > 0) { - output = ""; - - array.forEach(function(item) { - var name, type; - - name = item.name; - type = itemTypes[item.ty]; - - if (item.is_alias !== true) { - if (duplicates[item.fullPath]) { - return; - } - duplicates[item.fullPath] = true; - } - length += 1; - - output += ""; - }); - output += "
" + - "" + - (item.is_alias === true ? - ("" + item.alias + "  - see ") : "") + - item.displayPath + "" + - name + "" + - "" + - "" + item.desc + - " 
"; - } else { - output = "
No results :(
" + - "Try on
DuckDuckGo?

" + - "Or try looking in one of these:
"; - } - return [output, length]; - } - - function makeTabHeader(tabNb, text, nbElems) { - if (currentTab === tabNb) { - return ""; - } - return ""; - } - - function showResults(results) { - var search = getSearchElement(); - 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 !== getSearchLoadingText())) - { - var elem = document.createElement("a"); - elem.href = results.others[0].href; - elem.style.display = "none"; - // 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(search_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. - 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 = "

Results for " + escape(query.query) + - (query.type ? " (type: " + escape(query.type) + ")" : "") + "

" + - "
" + - makeTabHeader(0, "In Names", ret_others[1]) + - makeTabHeader(1, "In Parameters", ret_in_args[1]) + - makeTabHeader(2, "In Return Types", ret_returned[1]) + - "
" + - ret_others[0] + ret_in_args[0] + ret_returned[0] + "
"; - - search.innerHTML = output; - showSearchResults(search); - initSearchNav(); - 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], - }; + 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 } + } - function getFilterCrates() { - var elem = document.getElementById("crate-search"); - - if (elem && elem.value !== "All crates" && hasOwnProperty(rawSearchIndex, elem.value)) { - return elem.value; + function findParentElement(elem, tagName) { + do { + if (elem && elem.tagName === tagName) { + return elem; } - return undefined; - } + elem = elem.parentNode; + } while (elem); + return null; + } - function search(e, forced) { - var params = getQueryStringParams(); - var query = getQuery(search_input.value.trim()); + document.addEventListener("keypress", handleShortcut); + document.addEventListener("keydown", handleShortcut); - if (e) { - e.preventDefault(); - } + var handleSourceHighlight = (function() { + var prev_line_id = 0; - if (query.query.length === 0) { - return; - } - if (forced !== true && query.id === currentResults) { - if (query.query.length > 0) { - putBackSearch(search_input); - } - return; + var set_fragment = function(name) { + var x = window.scrollX, + y = window.scrollY; + if (searchState.browserSupportsHistoryApi()) { + history.replaceState(null, null, "#" + name); + highlightSourceLines(); + } else { + location.replace("#" + name); } + // Prevent jumps when selecting one or many lines + window.scrollTo(x, y); + }; - // Update document title to maintain a meaningful browser history - searchTitle = "Results for " + query.query + " - Rust"; - - // Because searching is incremental by character, only the most - // recent search query is added to the browser history. - if (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); - } - } + return function(ev) { + var cur_line_id = parseInt(ev.target.id, 10); + ev.preventDefault(); - 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 (!hasOwnProperty(rawSearchIndex, crate)) { continue; } - - var crateSize = 0; - - searchWords.push(crate); - var normalizedName = crate.indexOf("_") === -1 - ? crate - : crate.replace(/_/g, ""); - // 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: normalizedName, - }; - 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]}; + 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; } - // 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 normalizedName = word.indexOf("_") === -1 - ? word - : word.replace(/_/g, ""); - 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: normalizedName, - }; - id += 1; - searchIndex.push(row); - lastPath = row.path; - crateSize += 1; - } + set_fragment(prev_line_id + "-" + cur_line_id); + } else { + prev_line_id = cur_line_id; - if (aliases) { - ALIASES[crate] = {}; - var j, local_aliases; - for (var alias_name in aliases) { - if (!aliases.hasOwnProperty(alias_name)) { continue; } + set_fragment(cur_line_id); + } + }; + }()); - if (!ALIASES[crate].hasOwnProperty(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; + document.addEventListener("click", function(ev) { + var helpElem = getHelpElement(false); + if (hasClass(ev.target, "help-button")) { + displayHelp(true, ev); + } else if (hasClass(ev.target, "collapse-toggle")) { + collapseDocs(ev.target, "toggle"); + } else if (hasClass(ev.target.parentNode, "collapse-toggle")) { + collapseDocs(ev.target.parentNode, "toggle"); + } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { + handleSourceHighlight(ev); + } else if (helpElem && hasClass(helpElem, "hidden") === false) { + var is_inside_help_popup = ev.target !== helpElem && helpElem.contains(ev.target); + if (is_inside_help_popup === false) { + addClass(helpElem, "hidden"); + removeClass(document.body, "blur"); + } + } else { + // Making a collapsed element visible on onhashchange seems + // too late + var a = findParentElement(ev.target, "A"); + if (a && a.hash) { + expandSection(a.hash.replace(/^#/, "")); } - return searchWords; } + }); + + (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; - function registerSearchEvents() { - var searchAfter500ms = function() { - clearInputTimeout(); - if (search_input.value.length === 0) { - if (browserSupportsHistoryApi()) { - history.replaceState("", window.currentCrate + " - Rust", - getNakedUrl() + window.location.hash); + for (i = 0; i < len; ++i) { + match = url.match(/\/[^\/]*$/); + if (i < len - 1) { + stripped = match[0] + stripped; } - hideSearchResults(); - } else { - searchTimeout = setTimeout(search, 500); - } - }; - search_input.onkeyup = searchAfter500ms; - search_input.oninput = searchAfter500ms; - document.getElementsByClassName("search-form")[0].onsubmit = function(e) { - e.preventDefault(); - clearInputTimeout(); - search(); - }; - search_input.onchange = function(e) { - if (e.target !== document.activeElement) { - // To prevent doing anything when it's from a blur event. - return; + url = url.substring(0, url.length - match[0].length); } - // Do NOT e.preventDefault() here. It will prevent pasting. - 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); - }; - search_input.onpaste = search_input.onchange; - - 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 (browserSupportsHistoryApi()) { - // Store the previous so we can revert back to it later. - var previousTitle = document.title; - - window.addEventListener("popstate", function(e) { - var params = 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) { - search_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 { - search_input.value = ""; - // When browsing back from search results the main page - // visibility must be reset. - hideSearchResults(); - } - }); - } + var selectedVersion = document.getElementsByClassName("version-selector")[0].value; + url += "/" + selectedVersion + stripped; - // 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 = getQueryStringParams().search; - if (search_input.value === "" && qSearch) { - search_input.value = qSearch; - } - search(); + document.location.href = url; }; } - - index = buildIndex(rawSearchIndex); - registerSearchEvents(); - // If there's a search term in the URL, execute the search now. - if (getQueryStringParams().search) { - search(); - } - }; + }()); function addSidebarCrates(crates) { // Draw a convenient sidebar of known crates if we have a listing @@ -2152,6 +817,9 @@ function defocusSearchBar() { 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) { @@ -2166,7 +834,7 @@ function defocusSearchBar() { // (like "Send" and "Sync"). var inlined_types = new Set(); onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) { - var aliases = el.getAttribute("aliases"); + var aliases = el.getAttribute("data-aliases"); if (!aliases) { return; } @@ -2250,8 +918,10 @@ function defocusSearchBar() { return; } if (hasClass(innerToggle, "will-expand")) { - updateLocalStorage("rustdoc-collapse", "false"); removeClass(innerToggle, "will-expand"); + onEachLazy(document.getElementsByTagName("details"), function(e) { + e.open = true; + }); onEveryMatchingChild(innerToggle, "inner", function(e) { e.innerHTML = labelForToggleButton(false); }); @@ -2262,8 +932,10 @@ function defocusSearchBar() { }); } } else { - updateLocalStorage("rustdoc-collapse", "true"); addClass(innerToggle, "will-expand"); + onEachLazy(document.getElementsByTagName("details"), function(e) { + e.open = false; + }); onEveryMatchingChild(innerToggle, "inner", function(e) { var parent = e.parentNode; var superParent = null; @@ -2348,7 +1020,7 @@ function defocusSearchBar() { if (hasClass(relatedDoc, "item-info")) { relatedDoc = relatedDoc.nextElementSibling; } - if (hasClass(relatedDoc, "docblock") || hasClass(relatedDoc, "sub-variant")) { + if (hasClass(relatedDoc, "docblock")) { if (mode === "toggle") { if (hasClass(relatedDoc, "hidden-by-usual-hider")) { action = "show"; @@ -2414,40 +1086,18 @@ function defocusSearchBar() { } } - function collapser(e, collapse) { + function collapseNonInherent(e) { // inherent impl ids are like "impl" or impl-<number>'. // they will never be hidden by default. var n = e.parentElement; if (n.id.match(/^impl(?:-\d+)?$/) === null) { // Automatically minimize all non-inherent impls - if (collapse || hasClass(n, "impl")) { + if (hasClass(n, "impl")) { collapseDocs(e, "hide"); } } } - function autoCollapse(collapse) { - if (collapse) { - toggleAllDocs(true); - } else if (getSettingValue("auto-hide-trait-implementations") !== "false") { - var impl_list = document.getElementById("trait-implementations-list"); - - if (impl_list !== null) { - onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) { - collapser(e, collapse); - }); - } - - var blanket_list = document.getElementById("blanket-implementations-list"); - - if (blanket_list !== null) { - onEachLazy(blanket_list.getElementsByClassName("collapse-toggle"), function(e) { - collapser(e, collapse); - }); - } - } - } - function insertAfter(newNode, referenceNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } @@ -2505,6 +1155,23 @@ function defocusSearchBar() { var toggle = createSimpleToggle(false); var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true"; var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false"; + var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false"; + var hideTraitImplementations = + getSettingValue("auto-hide-trait-implementations") !== "false"; + + var impl_list = document.getElementById("trait-implementations-list"); + if (impl_list !== null) { + onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) { + collapseNonInherent(e); + }); + } + + var blanket_list = document.getElementById("blanket-implementations-list"); + if (blanket_list !== null) { + onEachLazy(blanket_list.getElementsByClassName("collapse-toggle"), function(e) { + collapseNonInherent(e); + }); + } var func = function(e) { var next = e.nextElementSibling; @@ -2534,23 +1201,18 @@ function defocusSearchBar() { if (!next) { return; } - if (hasClass(e, "impl") && - (next.getElementsByClassName("method").length > 0 || - next.getElementsByClassName("associatedconstant").length > 0)) { - var newToggle = toggle.cloneNode(true); - insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]); - // In case the option "auto-collapse implementors" is not set to false, we collapse - // all implementors. - if (hideImplementors === true && e.parentNode.id === "implementors-list") { - collapseDocs(newToggle, "hide"); - } - } }; onEachLazy(document.getElementsByClassName("method"), func); onEachLazy(document.getElementsByClassName("associatedconstant"), func); - onEachLazy(document.getElementsByClassName("impl"), funcImpl); var impl_call = function() {}; + onEachLazy(document.getElementsByTagName("details"), function (e) { + var showLargeItem = !hideLargeItemContents && hasClass(e, "type-contents-toggle"); + var showImplementor = !hideImplementors && hasClass(e, "implementors-toggle"); + if (showLargeItem || showImplementor) { + e.open = true; + } + }); if (hideMethodDocs === true) { impl_call = function(e, newToggle) { if (e.id.match(/^impl(?:-\d+)?$/) === null) { @@ -2611,7 +1273,7 @@ function defocusSearchBar() { if (currentType) { currentType = currentType.getElementsByClassName("rust")[0]; if (currentType) { - currentType.classList.forEach(function(item) { + onEachLazy(currentType.classList, function(item) { if (item !== "main") { className = item; return true; @@ -2619,18 +1281,7 @@ function defocusSearchBar() { }); } } - var showItemDeclarations = getSettingValue("auto-hide-" + className); - if (showItemDeclarations === null) { - if (className === "enum" || className === "macro") { - showItemDeclarations = "false"; - } else if (className === "struct" || className === "union" || className === "trait") { - showItemDeclarations = "true"; - } else { - // In case we found an unknown type, we just use the "parent" value. - showItemDeclarations = getSettingValue("auto-hide-declarations"); - } - } - showItemDeclarations = showItemDeclarations === "false"; + function buildToggleWrapper(e) { if (hasClass(e, "autohide")) { var wrap = e.previousElementSibling; @@ -2657,13 +1308,8 @@ function defocusSearchBar() { var extraClass; if (hasClass(e, "type-decl")) { - fontSize = "20px"; - otherMessage = " Show declaration"; - if (showItemDeclarations === false) { - extraClass = "collapsed"; - } - } else if (hasClass(e, "sub-variant")) { - otherMessage = " Show fields"; + // We do something special for these + return; } else if (hasClass(e, "non-exhaustive")) { otherMessage = " This "; if (hasClass(e, "non-exhaustive-struct")) { @@ -2686,11 +1332,8 @@ function defocusSearchBar() { otherMessage, fontSize, extraClass, - hasClass(e, "type-decl") === false || showItemDeclarations === true), + true), e); - if (hasClass(e, "type-decl") === true && showItemDeclarations === true) { - collapseDocs(e.previousSibling.childNodes[0], "toggle"); - } if (hasClass(e, "non-exhaustive") === true) { collapseDocs(e.previousSibling.childNodes[0], "toggle"); } @@ -2698,9 +1341,6 @@ function defocusSearchBar() { } onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper); - onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper); - - autoCollapse(getSettingValue("collapse") === "true"); var pageId = getPageId(); if (pageId !== null) { @@ -2708,38 +1348,6 @@ function defocusSearchBar() { } }()); - function createToggleWrapper(tog) { - var span = document.createElement("span"); - span.className = "toggle-label"; - span.style.display = "none"; - span.innerHTML = " Expand attributes"; - tog.appendChild(span); - - var wrapper = document.createElement("div"); - wrapper.className = "toggle-wrapper toggle-attributes"; - wrapper.appendChild(tog); - return wrapper; - } - - (function() { - // To avoid checking on "rustdoc-item-attributes" value on every loop... - var itemAttributesFunc = function() {}; - if (getSettingValue("auto-hide-attributes") !== "false") { - itemAttributesFunc = function(x) { - collapseDocs(x.previousSibling.childNodes[0], "toggle"); - }; - } - var attributesToggle = createToggleWrapper(createSimpleToggle(false)); - onEachLazy(main.getElementsByClassName("attributes"), function(i_e) { - var attr_tog = attributesToggle.cloneNode(true); - if (hasClass(i_e, "top-attr") === true) { - addClass(attr_tog, "top-attr"); - } - i_e.parentNode.insertBefore(attr_tog, i_e); - itemAttributesFunc(i_e); - }); - }()); - (function() { // To avoid checking on "rustdoc-line-numbers" value on every loop... var lineNumbersFunc = function() {}; @@ -2783,60 +1391,6 @@ function defocusSearchBar() { }; }); - // In the search display, allows to switch between tabs. - function printTab(nb) { - if (nb === 0 || nb === 1 || nb === 2) { - 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) { - elem.style.display = ""; - } else { - elem.style.display = "none"; - } - nb -= 1; - }); - } - - function putBackSearch(search_input) { - var search = getSearchElement(); - if (search_input.value !== "" && hasClass(search, "hidden")) { - showSearchResults(search); - if (browserSupportsHistoryApi()) { - var extra = "?search=" + encodeURIComponent(search_input.value); - history.replaceState(search_input.value, "", - getNakedUrl() + extra + window.location.hash); - } - document.title = searchTitle; - } - } - - function getSearchLoadingText() { - return "Loading search results..."; - } - - if (search_input) { - search_input.onfocus = function() { - putBackSearch(this); - }; - } - - var params = getQueryStringParams(); - if (params && params.search) { - var search = getSearchElement(); - search.innerHTML = "<h3 style=\"text-align: center;\">" + getSearchLoadingText() + "</h3>"; - showSearchResults(search); - } - var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; if (sidebar_menu) { sidebar_menu.onclick = function() { @@ -2860,39 +1414,15 @@ function defocusSearchBar() { // errors in mobile browsers). if (e.tagName === "H2" || e.tagName === "H3") { var nextTagName = e.nextElementSibling.tagName; - if (nextTagName == "H2" || nextTagName == "H3") { + if (nextTagName === "H2" || nextTagName === "H3") { e.nextElementSibling.style.display = "flex"; - } else { + } else if (nextTagName !== "DETAILS") { e.nextElementSibling.style.display = "block"; } } }); } - function addSearchOptions(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 buildHelperPopup() { var popup = document.createElement("aside"); addClass(popup, "hidden"); @@ -2950,53 +1480,37 @@ function defocusSearchBar() { container.appendChild(div_infos); popup.appendChild(container); - insertAfter(popup, getSearchElement()); + insertAfter(popup, searchState.outputElement()); // So that it's only built once and then it'll do nothing when called! buildHelperPopup = function() {}; } - function loadScript(url) { - var script = document.createElement('script'); - script.src = url; - document.head.append(script); - } + onHashChange(null); + window.onhashchange = onHashChange; + searchState.setup(); +}()); - function setupSearchLoader() { - var searchLoaded = false; - function loadSearch() { - if (!searchLoaded) { - searchLoaded = true; - loadScript(window.searchJS); - } - } +function copy_path(but) { + var parent = but.parentElement; + var path = []; - // `crates{version}.js` should always be loaded before this script, so we can use it safely. - addSearchOptions(window.ALL_CRATES); - addSidebarCrates(window.ALL_CRATES); + onEach(parent.childNodes, function(child) { + if (child.tagName === 'A') { + path.push(child.textContent); + } + }); - search_input.addEventListener("focus", function() { - search_input.origPlaceholder = search_input.placeholder; - search_input.placeholder = "Type your search here."; - loadSearch(); - }); - search_input.addEventListener("blur", function() { - search_input.placeholder = search_input.origPlaceholder; - }); - search_input.removeAttribute('disabled'); + 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'; - var crateSearchDropDown = document.getElementById("crate-search"); - // `crateSearchDropDown` can be null in case there is only crate because in that case, the - // crate filter dropdown is removed. - if (crateSearchDropDown) { - crateSearchDropDown.addEventListener("focus", loadSearch); - } - var params = getQueryStringParams(); - if (params.search !== undefined) { - loadSearch(); - } - } + document.body.appendChild(el); + el.select(); + document.execCommand('copy'); + document.body.removeChild(el); - onHashChange(null); - window.onhashchange = onHashChange; - setupSearchLoader(); -}()); + but.textContent = '✓'; +} diff --git a/src/librustdoc/html/static/noscript.css b/src/librustdoc/html/static/noscript.css index c9fed989ec..4d3332877c 100644 --- a/src/librustdoc/html/static/noscript.css +++ b/src/librustdoc/html/static/noscript.css @@ -33,3 +33,8 @@ rules. /* 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/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 4f287cde73..a95c90e999 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -18,26 +18,26 @@ font-display: swap; } -/* See SourceSerifPro-LICENSE.txt for the Source Serif Pro license. */ +/* See SourceSerif4-LICENSE.md for the Source Serif 4 license. */ @font-face { - font-family: 'Source Serif Pro'; + font-family: 'Source Serif 4'; font-style: normal; font-weight: 400; - src: local('Source Serif Pro'), url("SourceSerifPro-Regular.ttf.woff") format('woff'); + src: local('Source Serif 4'), url("SourceSerif4-Regular.ttf.woff") format('woff'); font-display: swap; } @font-face { - font-family: 'Source Serif Pro'; + font-family: 'Source Serif 4'; font-style: italic; font-weight: 400; - src: local('Source Serif Pro Italic'), url("SourceSerifPro-It.ttf.woff") format('woff'); + src: local('Source Serif 4 Italic'), url("SourceSerif4-It.ttf.woff") format('woff'); font-display: swap; } @font-face { - font-family: 'Source Serif Pro'; + font-family: 'Source Serif 4'; font-style: normal; font-weight: 700; - src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.ttf.woff") format('woff'); + src: local('Source Serif 4 Bold'), url("SourceSerif4-Bold.ttf.woff") format('woff'); font-display: swap; } @@ -48,14 +48,21 @@ 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'); + 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.woff") format('woff'); + src: url("SourceCodePro-Semibold.ttf.woff") format('woff'); font-display: swap; } @@ -83,7 +90,7 @@ html { /* General structure and fonts */ body { - font: 16px/1.4 "Source Serif Pro", serif; + font: 16px/1.4 "Source Serif 4", serif; margin: 0; position: relative; padding: 10px 15px 20px 15px; @@ -109,8 +116,13 @@ h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { 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; @@ -126,7 +138,8 @@ h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant { margin-bottom: 10px; position: relative; } -h3.impl, h3.method, h3.type { +h3.impl, h3.method, h4.method.trait-impl, h3.type, +h4.type.trait-impl, h4.associatedconstant.trait-impl { padding-left: 15px; } @@ -166,13 +179,10 @@ code, pre, a.test-arrow { border-radius: 3px; padding: 0 0.1em; } -.docblock pre code, .docblock-short pre code, .docblock code.spotlight { +.docblock pre code, .docblock-short pre code { padding: 0; padding-right: 1ex; } -.docblock code.spotlight :last-child { - padding-bottom: 0.6em; -} pre { padding: 14px; } @@ -378,17 +388,9 @@ nav.sub { position: relative; } -#results { - position: absolute; - right: 0; - left: 0; - overflow: auto; -} - #results > table { width: 100%; table-layout: fixed; - margin-bottom: 40px; } .content pre.line-numbers { @@ -417,7 +419,9 @@ nav.sub { text-overflow: ellipsis; margin: 0; } -.docblock-short code { +/* Wrap non-pre code blocks (`text`) but not (```text```). */ +.docblock > :not(pre) > code, +.docblock-short > :not(pre) > code { white-space: pre-wrap; } @@ -444,10 +448,11 @@ nav.sub { } .content .out-of-band { - float: right; + flex-grow: 0; + text-align: right; font-size: 23px; margin: 0px; - padding: 0px; + padding: 0 0 0 12px; font-weight: normal; } @@ -470,6 +475,7 @@ h4 > code, h3 > code, .invisible > code { } .content .in-band { + flex-grow: 1; margin: 0px; padding: 0px; } @@ -649,7 +655,8 @@ a { display: initial; } -.in-band:hover > .anchor, .impl:hover > .anchor { +.in-band:hover > .anchor, .impl:hover > .anchor, .method.trait-impl:hover > .anchor, +.type.trait-impl:hover > .anchor, .associatedconstant.trait-impl:hover > .anchor { display: inline-block; position: absolute; } @@ -851,7 +858,17 @@ body.blur > :not(#help) { font-size: 1.5em; } -.module-item .stab { +/* 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%; @@ -862,7 +879,8 @@ body.blur > :not(#help) { vertical-align: text-bottom; } -.module-item.unstable { +.module-item.unstable, +.import-item.unstable { opacity: 0.65; } @@ -950,6 +968,10 @@ a.test-arrow:hover{ color: inherit; } +.code-attribute { + font-weight: 300; +} + .collapse-toggle { font-weight: 300; position: absolute; @@ -1014,10 +1036,11 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { } .sub-variant, .sub-variant > h3 { - margin-top: 1px !important; + margin-top: 0px !important; + padding-top: 1px; } -#main > .sub-variant > h3 { +#main > details > .sub-variant > h3 { font-size: 15px; margin-left: 25px; margin-bottom: 5px; @@ -1039,12 +1062,6 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { margin-top: 3px; } -.enum > .toggle-wrapper + .docblock, .struct > .toggle-wrapper + .docblock { - margin-left: 30px; - margin-bottom: 20px; - margin-top: 5px; -} - .docblock > .section-header:first-child { margin-left: 15px; margin-top: 0; @@ -1054,30 +1071,10 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { left: -10px; } -.enum > .collapsed, .struct > .collapsed { - margin-bottom: 25px; -} - #main > .variant, #main > .structfield { display: block; } -.attributes { - display: block; - margin-top: 0px !important; - margin-right: 0px; - margin-bottom: 0px !important; - margin-left: 30px; -} -.toggle-attributes.collapsed { - margin-bottom: 0; -} -.impl-items > .toggle-attributes { - margin-left: 20px; -} -.impl-items .attributes { - font-weight: 500; -} :target > code { opacity: 1; @@ -1300,20 +1297,29 @@ h4 > .notable-traits { 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; } -#theme-picker, #settings-menu, .help-button { - padding: 4px; - width: 27px; - height: 29px; - border: 1px solid; - border-radius: 3px; - cursor: pointer; +#copy-path { + height: 30px; + font-size: 18px; + margin-left: 10px; + padding: 0 6px; + width: 28px; } #theme-choices { @@ -1346,7 +1352,7 @@ h4 > .notable-traits { 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. */ - .information:first-child > .tooltip { + .docblock > .information:first-child > .tooltip { margin-top: 16px; } } @@ -1444,10 +1450,6 @@ h4 > .notable-traits { padding: 0; } - .content .in-band { - width: 100%; - } - .content h4 > .out-of-band { position: inherit; } @@ -1472,10 +1474,6 @@ h4 > .notable-traits { display: none !important; } - h1.fqn { - overflow: initial; - } - .theme-picker { left: 10px; top: 54px; @@ -1561,6 +1559,10 @@ h4 > .notable-traits { left: -10px; } + .item-list > details.rustdoc-toggle > summary:not(.hideme)::before { + left: -10px; + } + #all-types { margin: 10px; } @@ -1755,16 +1757,56 @@ div.name.expand::before { top: 2px; } -/* This part is to fix the "Expand attributes" part in the type declaration. */ -.type-decl > pre > .toggle-wrapper.toggle-attributes.top-attr { - margin-left: 0 !important; +/* 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; } -.type-decl > pre > .docblock.attributes.top-attr { - margin-left: 1.8em !important; + +details.rustdoc-toggle > summary::-webkit-details-marker { + display: none; } -.type-decl > pre > .toggle-attributes { - margin-left: 2.2em; + +details.rustdoc-toggle > summary.hideme > span { + margin-left: 9px; } -.type-decl > pre > .docblock.attributes { - margin-left: 4em; + +details.rustdoc-toggle > summary::before { + content: "[+]"; + font-weight: 300; + font-size: 0.8em; + letter-spacing: 1px; + cursor: pointer; +} + +details.rustdoc-toggle > summary.hideme::before { + position: relative; +} + +details.rustdoc-toggle > summary:not(.hideme)::before { + position: absolute; + left: -23px; +} + +/* 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[open] { + position: relative; +} + +details.rustdoc-toggle[open] > summary.hideme > span { + display: none; +} + +details.rustdoc-toggle[open] > summary::before { + content: "[−]"; + display: inline; } diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/search.js new file mode 100644 index 0000000000..9fab435de4 --- /dev/null +++ b/src/librustdoc/html/static/search.js @@ -0,0 +1,1515 @@ +(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) { + elem.style.display = ""; + } else { + elem.style.display = "none"; + } + 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, isType) { + 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; + if (isType !== true || obj.type) { + 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 (hasOwnProperty(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) { + var 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 !== true && + validateResult(name, path, split, parent) === false) + { + 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 = object[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 === true) { + 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 === true) { + 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 === true) { + 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]) === false) { + continue; + } + tmp = checkType(tmp, val, literalSearch); + if (literalSearch === true) { + if (tmp === true) { + return true; + } + continue; + } + lev_distance = Math.min(tmp, lev_distance); + if (lev_distance === 0) { + return 0; + } + } + } + return literalSearch === true ? 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]) === false) { + continue; + } + tmp = checkType(tmp, val, literalSearch); + if (literalSearch === true) { + if (tmp === true) { + return true; + } + continue; + } + lev_distance = Math.min(tmp, lev_distance); + if (lev_distance === 0) { + return 0; + } + } + } + return literalSearch === true ? 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 === false) { + 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 === true && results_in_args[fullId] === undefined) { + results_in_args[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; + } + if (returned === true && 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 === true) { + in_args = false; + var is_module = false; + + if (input === "*") { + is_module = true; + } else { + var allFound = true; + for (it = 0, len = inputs.length; allFound === true && it < len; it++) { + allFound = checkType(type, inputs[it], true); + } + in_args = allFound; + } + if (in_args === true) { + results_in_args[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; + } + if (returned === true) { + results_returned[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; + } + if (is_module === true) { + 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) === false) { + lev = MAX_LEV_DISTANCE + 1; + } else { + lev += 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), + }; + 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 initSearchNav() { + var hoverTimeout; + + var click_func = function(e) { + var el = e.target; + // to retrieve the real "owner" of the event. + while (el.tagName !== "TR") { + el = el.parentNode; + } + var dst = e.target.getElementsByTagName("a"); + if (dst.length < 1) { + return; + } + dst = dst[0]; + if (window.location.pathname === dst.pathname) { + searchState.hideResults(); + document.location.href = dst.href; + } + }; + var mouseover_func = function(e) { + if (searchState.mouseMovedAfterSearch) { + var el = e.target; + // to retrieve the real "owner" of the event. + while (el.tagName !== "TR") { + el = el.parentNode; + } + clearTimeout(hoverTimeout); + hoverTimeout = setTimeout(function() { + onEachLazy(document.getElementsByClassName("search-results"), function(e) { + onEachLazy(e.getElementsByClassName("result"), function(i_e) { + removeClass(i_e, "highlighted"); + }); + }); + addClass(el, "highlighted"); + }, 20); + } + }; + onEachLazy(document.getElementsByClassName("search-results"), function(e) { + onEachLazy(e.getElementsByClassName("result"), function(i_e) { + i_e.onclick = click_func; + i_e.onmouseover = mouseover_func; + }); + }); + + searchState.input.onkeydown = function(e) { + // "actives" references the currently highlighted item in each search tab. + // Each array in "actives" represents a tab. + var actives = [[], [], []]; + // "current" is used to know which tab we're looking into. + var current = 0; + onEachLazy(document.getElementById("results").childNodes, function(e) { + onEachLazy(e.getElementsByClassName("highlighted"), function(h_e) { + actives[current].push(h_e); + }); + current += 1; + }); + var SHIFT = 16; + var CTRL = 17; + var ALT = 18; + + var currentTab = searchState.currentTab; + if (e.which === 38) { // up + if (e.ctrlKey) { // Going through result tabs. + printTab(currentTab > 0 ? currentTab - 1 : 2); + } else { + if (!actives[currentTab].length || + !actives[currentTab][0].previousElementSibling) { + return; + } + addClass(actives[currentTab][0].previousElementSibling, "highlighted"); + removeClass(actives[currentTab][0], "highlighted"); + } + e.preventDefault(); + } else if (e.which === 40) { // down + if (e.ctrlKey) { // Going through result tabs. + printTab(currentTab > 1 ? 0 : currentTab + 1); + } else if (!actives[currentTab].length) { + var results = document.getElementById("results").childNodes; + if (results.length > 0) { + var res = results[currentTab].getElementsByClassName("result"); + if (res.length > 0) { + addClass(res[0], "highlighted"); + } + } + } else if (actives[currentTab][0].nextElementSibling) { + addClass(actives[currentTab][0].nextElementSibling, "highlighted"); + removeClass(actives[currentTab][0], "highlighted"); + } + e.preventDefault(); + } else if (e.which === 13) { // return + if (actives[currentTab].length) { + var elem = actives[currentTab][0].getElementsByTagName("a")[0]; + document.location.href = elem.href; + } + } else if ([SHIFT, CTRL, ALT].indexOf(e.which) !== -1) { + // Does nothing, it's just to avoid losing "focus" on the highlighted element. + } else if (actives[currentTab].length > 0) { + removeClass(actives[currentTab][0], "highlighted"); + } + }; + } + + 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 extraStyle = ""; + if (display === false) { + extraStyle = " style=\"display: none;\""; + } + + var output = ""; + var duplicates = {}; + var length = 0; + if (array.length > 0) { + output = "<table class=\"search-results\"" + extraStyle + ">"; + + array.forEach(function(item) { + var name, type; + + name = item.name; + type = itemTypes[item.ty]; + + if (item.is_alias !== true) { + if (duplicates[item.fullPath]) { + return; + } + duplicates[item.fullPath] = true; + } + length += 1; + + output += "<tr class=\"" + type + " result\"><td>" + + "<a href=\"" + item.href + "\">" + + (item.is_alias === true ? + ("<span class=\"alias\"><b>" + item.alias + " </b></span><span " + + "class=\"grey\"><i> - see </i></span>") : "") + + item.displayPath + "<span class=\"" + type + "\">" + + name + "</span></a></td><td>" + + "<a href=\"" + item.href + "\">" + + "<span class=\"desc\">" + item.desc + + " </span></a></td></tr>"; + }); + output += "</table>"; + } else { + output = "<div class=\"search-failed\"" + extraStyle + ">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></div>"; + } + 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; + elem.style.display = "none"; + // 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><div id=\"results\">" + + ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>"; + + search.innerHTML = output; + searchState.showResults(search); + initSearchNav(); + 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" && hasOwnProperty(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 !== true && 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 (!hasOwnProperty(rawSearchIndex, crate)) { continue; } + + var crateSize = 0; + + searchWords.push(crate); + var normalizedName = crate.indexOf("_") === -1 + ? crate + : crate.replace(/_/g, ""); + // 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: normalizedName, + }; + 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 normalizedName = word.indexOf("_") === -1 + ? word + : word.replace(/_/g, ""); + 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: normalizedName, + }; + 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 (!aliases.hasOwnProperty(alias_name)) { continue; } + + if (!ALIASES[crate].hasOwnProperty(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; + + 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/sidebar-items.js b/src/librustdoc/html/static/sidebar-items.js new file mode 100644 index 0000000000..81172ba0d9 --- /dev/null +++ b/src/librustdoc/html/static/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({}); diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index b8b6fcbaf3..2ed87fdeda 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -1,9 +1,8 @@ // From rust: /* global resourcesSuffix */ - var darkThemes = ["dark", "ayu"]; -var currentTheme = document.getElementById("themeStyle"); -var mainTheme = document.getElementById("mainThemeStyle"); +window.currentTheme = document.getElementById("themeStyle"); +window.mainTheme = document.getElementById("mainThemeStyle"); var settingsDataset = (function () { var settingsElement = document.getElementById("default-settings"); @@ -137,7 +136,7 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { } } -// This function is called from "theme.js", generated in `html/render/mod.rs`. +// This function is called from "main.js". // eslint-disable-next-line no-unused-vars function useSystemTheme(value) { if (value === undefined) { @@ -161,8 +160,8 @@ var updateSystemTheme = (function() { .getPropertyValue('content'); switchTheme( - currentTheme, - mainTheme, + window.currentTheme, + window.mainTheme, JSON.parse(cssTheme) || "light", true ); @@ -180,10 +179,10 @@ var updateSystemTheme = (function() { if (mql.matches) { // prefers a dark theme - switchTheme(currentTheme, mainTheme, darkTheme, true); + switchTheme(window.currentTheme, window.mainTheme, darkTheme, true); } else { // prefers a light theme, or has no preference - switchTheme(currentTheme, mainTheme, lightTheme, true); + switchTheme(window.currentTheme, window.mainTheme, lightTheme, true); } // note: we save the theme so that it doesn't suddenly change when @@ -212,8 +211,8 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) { updateSystemTheme(); } else { switchTheme( - currentTheme, - mainTheme, + 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 index 7374aee71f..72396ec6b7 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -224,7 +224,9 @@ a { color: #39AFD7; } -.collapse-toggle { +.collapse-toggle, +details.rustdoc-toggle > summary.hideme > span, +details.rustdoc-toggle > summary::before { color: #999; } @@ -250,7 +252,8 @@ a { color: #929292; } -.module-item .stab { +.module-item .stab, +.import-item .stab { color: #000; } @@ -327,7 +330,8 @@ a.test-arrow:hover { color: #c5c5c5; } -.toggle-label { +.toggle-label, +.code-attribute { color: #999; } @@ -498,7 +502,7 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker, #settings-menu, .help-button { +#theme-picker, #settings-menu, .help-button, #copy-path { border-color: #5c6773; background-color: #0f1419; color: #fff; @@ -510,7 +514,8 @@ kbd { #theme-picker:hover, #theme-picker:focus, #settings-menu:hover, #settings-menu:focus, -.help-button:hover, .help-button:focus { +.help-button:hover, .help-button:focus, +#copy-path:hover, #copy-path:focus { border-color: #e0e0e0; } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 88ac3252bb..b2003b5274 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -186,7 +186,9 @@ a.test-arrow { color: #dedede; } -.collapse-toggle { +.collapse-toggle, +details.rustdoc-toggle > summary.hideme > span, +details.rustdoc-toggle > summary::before { color: #999; } @@ -215,13 +217,14 @@ a.test-arrow { box-shadow: 0 0 8px 4px #078dd8; } -.module-item .stab { +.module-item .stab, +.import-item .stab { color: #ddd; } .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; } -.stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; } -.stab.portability { background: #C4ECFF; border-color: #7BA5DB; 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 { @@ -272,7 +275,8 @@ a.test-arrow:hover{ background-color: #4e8bca; } -.toggle-label { +.toggle-label, +.code-attribute { color: #999; } @@ -388,7 +392,7 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker, #settings-menu, .help-button { +#theme-picker, #settings-menu, .help-button, #copy-path { border-color: #e0e0e0; background: #f0f0f0; color: #000; @@ -396,7 +400,8 @@ kbd { #theme-picker:hover, #theme-picker:focus, #settings-menu:hover, #settings-menu:focus, -.help-button:hover, .help-button:focus { +.help-button:hover, .help-button:focus, +#copy-path:hover, #copy-path:focus { border-color: #ffb900; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 9bc21102aa..04187773b6 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -184,7 +184,9 @@ a.test-arrow { color: #f5f5f5; } -.collapse-toggle { +.collapse-toggle, +details.rustdoc-toggle > summary.hideme > span, +details.rustdoc-toggle > summary::before { color: #999; } @@ -213,13 +215,14 @@ a.test-arrow { box-shadow: 0 0 8px #078dd8; } -.module-item .stab { +.module-item .stab, +.import-item .stab { color: #000; } .stab.unstable { background: #FFF5D6; border-color: #FFC600; } -.stab.deprecated { background: #F3DFFF; border-color: #7F0087; } -.stab.portability { background: #C4ECFF; border-color: #7BA5DB; } +.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; } +.stab.portability { background: #F3DFFF; border-color: #b07bdb; } .stab.portability > code { background: none; } #help > div { @@ -265,7 +268,8 @@ a.test-arrow:hover{ background-color: #4e8bca; } -.toggle-label { +.toggle-label, +.code-attribute { color: #999; } @@ -380,14 +384,15 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker, #settings-menu, .help-button { +#theme-picker, #settings-menu, .help-button, #copy-path { border-color: #e0e0e0; background-color: #fff; } #theme-picker:hover, #theme-picker:focus, #settings-menu:hover, #settings-menu:focus, -.help-button:hover, .help-button:focus { +.help-button:hover, .help-button:focus, +#copy-path:hover, #copy-path:focus { border-color: #717171; } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 701e106df6..6b1e1e9622 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -24,6 +24,9 @@ crate static NORMALIZE_CSS: &str = include_str!("static/normalize.css"); /// including search behavior and docblock folding, among others. crate static MAIN_JS: &str = include_str!("static/main.js"); +/// The file contents of `search.js`, which contains the search behavior. +crate static SEARCH_JS: &str = include_str!("static/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"); @@ -89,29 +92,32 @@ crate mod fira_sans { crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt"); } -/// Files related to the Source Serif Pro font. -crate mod source_serif_pro { - /// The file `SourceSerifPro-Regular.ttf.woff`, the Regular variant of the Source Serif Pro - /// font. - crate static REGULAR: &[u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff"); +/// 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"); - /// The file `SourceSerifPro-Bold.ttf.woff`, the Bold variant of the Source Serif Pro font. - crate static BOLD: &[u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff"); + /// 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"); - /// The file `SourceSerifPro-It.ttf.woff`, the Italic variant of the Source Serif Pro font. - crate static ITALIC: &[u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff"); + /// 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"); - /// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font. - crate static LICENSE: &[u8] = include_bytes!("static/SourceSerifPro-LICENSE.md"); + /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font. + crate static LICENSE: &[u8] = include_bytes!("static/SourceSerif4-LICENSE.md"); } /// Files related to the Source Code Pro font. crate mod source_code_pro { - /// The file `SourceCodePro-Regular.woff`, the Regular variant of the Source Code Pro font. - crate static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.woff"); + /// 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"); - /// The file `SourceCodePro-Semibold.woff`, the Semibold variant of the Source Code Pro font. - crate static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.woff"); + /// 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"); + + /// 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"); /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font. crate static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt"); @@ -121,4 +127,7 @@ crate mod source_code_pro { crate mod sidebar { /// File script to handle sidebar. crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js"); + + /// Top Level sidebar items script which will load a sidebar without items. + crate static ITEMS: &str = include_str!("static/sidebar-items.js"); } diff --git a/src/librustdoc/html/tests.rs b/src/librustdoc/html/tests.rs new file mode 100644 index 0000000000..5d537dabd0 --- /dev/null +++ b/src/librustdoc/html/tests.rs @@ -0,0 +1,44 @@ +use crate::html::format::href_relative_parts; + +fn assert_relative_path(expected: &[&str], relative_to_fqp: &[&str], fqp: &[&str]) { + let relative_to_fqp: Vec<String> = relative_to_fqp.iter().copied().map(String::from).collect(); + let fqp: Vec<String> = fqp.iter().copied().map(String::from).collect(); + assert_eq!(expected, href_relative_parts(&fqp, &relative_to_fqp)); +} + +#[test] +fn href_relative_parts_basic() { + let relative_to_fqp = &["std", "vec"]; + let fqp = &["std", "iter"]; + assert_relative_path(&["..", "iter"], relative_to_fqp, fqp); +} +#[test] +fn href_relative_parts_parent_module() { + let relative_to_fqp = &["std", "vec"]; + let fqp = &["std"]; + assert_relative_path(&[".."], relative_to_fqp, fqp); +} +#[test] +fn href_relative_parts_different_crate() { + let relative_to_fqp = &["std", "vec"]; + let fqp = &["core", "iter"]; + assert_relative_path(&["..", "..", "core", "iter"], relative_to_fqp, fqp); +} +#[test] +fn href_relative_parts_same_module() { + let relative_to_fqp = &["std", "vec"]; + let fqp = &["std", "vec"]; + assert_relative_path(&[], relative_to_fqp, fqp); +} +#[test] +fn href_relative_parts_child_module() { + let relative_to_fqp = &["std"]; + let fqp = &["std", "vec"]; + assert_relative_path(&["vec"], relative_to_fqp, fqp); +} +#[test] +fn href_relative_parts_root() { + let relative_to_fqp = &[]; + let fqp = &["std"]; + assert_relative_path(&["std"], relative_to_fqp, fqp); +} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 063d8aab1e..2d8c347c3c 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -10,7 +10,6 @@ use rustc_ast::ast; use rustc_hir::def::CtorKind; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; -use rustc_span::symbol::Symbol; use rustc_span::Pos; use rustdoc_json_types::*; @@ -24,32 +23,40 @@ use std::collections::HashSet; impl JsonRenderer<'_> { pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> { let deprecation = item.deprecation(self.tcx); - let clean::Item { source, name, attrs, kind, visibility, def_id } = item; - let inner = match *kind { + let links = self + .cache + .intra_doc_links + .get(&item.def_id) + .into_iter() + .flatten() + .filter_map(|clean::ItemLink { link, did, .. }| { + did.map(|did| (link.clone(), from_def_id(did))) + }) + .collect(); + let docs = item.attrs.collapsed_doc_value(); + let attrs = item + .attrs + .other_attrs + .iter() + .map(rustc_ast_pretty::pprust::attribute_to_string) + .collect(); + let span = item.span(self.tcx); + let clean::Item { name, attrs: _, kind: _, visibility, def_id, cfg: _ } = item; + let inner = match *item.kind { clean::StrippedItem(_) => return None, - x => from_clean_item_kind(x, self.tcx, &name), + _ => from_clean_item(item, self.tcx), }; Some(Item { id: from_def_id(def_id), crate_id: def_id.krate.as_u32(), name: name.map(|sym| sym.to_string()), - source: self.convert_span(source), + span: self.convert_span(span), visibility: self.convert_visibility(visibility), - docs: attrs.collapsed_doc_value(), - links: attrs - .links - .into_iter() - .filter_map(|clean::ItemLink { link, did, .. }| { - did.map(|did| (link, from_def_id(did))) - }) - .collect(), - attrs: attrs - .other_attrs - .iter() - .map(rustc_ast_pretty::pprust::attribute_to_string) - .collect(), + docs, + attrs, deprecation: deprecation.map(from_deprecation), inner, + links, }) } @@ -87,59 +94,78 @@ impl JsonRenderer<'_> { } } +crate trait FromWithTcx<T> { + fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self; +} + +crate trait IntoWithTcx<T> { + fn into_tcx(self, tcx: TyCtxt<'_>) -> T; +} + +impl<T, U> IntoWithTcx<U> for T +where + U: FromWithTcx<T>, +{ + fn into_tcx(self, tcx: TyCtxt<'_>) -> U { + U::from_tcx(self, tcx) + } +} + crate fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation { #[rustfmt::skip] let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation; Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) } } -impl From<clean::GenericArgs> for GenericArgs { - fn from(args: clean::GenericArgs) -> Self { +impl FromWithTcx<clean::GenericArgs> for GenericArgs { + fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self { use clean::GenericArgs::*; match args { AngleBracketed { args, bindings } => GenericArgs::AngleBracketed { - args: args.into_iter().map(Into::into).collect(), - bindings: bindings.into_iter().map(Into::into).collect(), + args: args.into_iter().map(|a| a.into_tcx(tcx)).collect(), + bindings: bindings.into_iter().map(|a| a.into_tcx(tcx)).collect(), }, Parenthesized { inputs, output } => GenericArgs::Parenthesized { - inputs: inputs.into_iter().map(Into::into).collect(), - output: output.map(Into::into), + inputs: inputs.into_iter().map(|a| a.into_tcx(tcx)).collect(), + output: output.map(|a| a.into_tcx(tcx)), }, } } } -impl From<clean::GenericArg> for GenericArg { - fn from(arg: clean::GenericArg) -> Self { +impl FromWithTcx<clean::GenericArg> for GenericArg { + fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self { use clean::GenericArg::*; match arg { Lifetime(l) => GenericArg::Lifetime(l.0.to_string()), - Type(t) => GenericArg::Type(t.into()), - Const(c) => GenericArg::Const(c.into()), + Type(t) => GenericArg::Type(t.into_tcx(tcx)), + Const(c) => GenericArg::Const(c.into_tcx(tcx)), } } } -impl From<clean::Constant> for Constant { - fn from(constant: clean::Constant) -> Self { - let clean::Constant { type_, expr, value, is_literal } = constant; - Constant { type_: type_.into(), expr, value, is_literal } +impl FromWithTcx<clean::Constant> for Constant { + fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self { + let expr = constant.expr(tcx); + let value = constant.value(tcx); + let is_literal = constant.is_literal(tcx); + Constant { type_: constant.type_.into_tcx(tcx), expr, value, is_literal } } } -impl From<clean::TypeBinding> for TypeBinding { - fn from(binding: clean::TypeBinding) -> Self { - TypeBinding { name: binding.name.to_string(), binding: binding.kind.into() } +impl FromWithTcx<clean::TypeBinding> for TypeBinding { + fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self { + TypeBinding { name: binding.name.to_string(), binding: binding.kind.into_tcx(tcx) } } } -impl From<clean::TypeBindingKind> for TypeBindingKind { - fn from(kind: clean::TypeBindingKind) -> Self { +impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind { + fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self { use clean::TypeBindingKind::*; match kind { - Equality { ty } => TypeBindingKind::Equality(ty.into()), + Equality { ty } => TypeBindingKind::Equality(ty.into_tcx(tcx)), Constraint { bounds } => { - TypeBindingKind::Constraint(bounds.into_iter().map(Into::into).collect()) + TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect()) } } } @@ -149,37 +175,40 @@ crate fn from_def_id(did: DefId) -> Id { Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index))) } -fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Symbol>) -> ItemEnum { +fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { use clean::ItemKind::*; - match item { - ModuleItem(m) => ItemEnum::Module(m.into()), - ImportItem(i) => ItemEnum::Import(i.into()), - StructItem(s) => ItemEnum::Struct(s.into()), - UnionItem(u) => ItemEnum::Union(u.into()), - StructFieldItem(f) => ItemEnum::StructField(f.into()), - EnumItem(e) => ItemEnum::Enum(e.into()), - VariantItem(v) => ItemEnum::Variant(v.into()), - FunctionItem(f) => ItemEnum::Function(f.into()), - ForeignFunctionItem(f) => ItemEnum::Function(f.into()), - TraitItem(t) => ItemEnum::Trait(t.into()), - TraitAliasItem(t) => ItemEnum::TraitAlias(t.into()), - MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true)), - TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false)), - ImplItem(i) => ItemEnum::Impl(i.into()), - StaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)), - ForeignStaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)), + let name = item.name; + let is_crate = item.is_crate(); + match *item.kind { + ModuleItem(m) => ItemEnum::Module(Module { is_crate, items: ids(m.items) }), + ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)), + StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)), + UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)), + StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)), + EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)), + VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)), + FunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)), + ForeignFunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)), + TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)), + TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)), + MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, tcx)), + TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, tcx)), + ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)), + StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), + ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), ForeignTypeItem => ItemEnum::ForeignType, - TypedefItem(t, _) => ItemEnum::Typedef(t.into()), - OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into()), - ConstantItem(c) => ItemEnum::Constant(c.into()), + TypedefItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)), + OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), + ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)), MacroItem(m) => ItemEnum::Macro(m.source), - ProcMacroItem(m) => ItemEnum::ProcMacro(m.into()), - AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into(), default: s }, + ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)), + AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into_tcx(tcx), default: s }, AssocTypeItem(g, t) => ItemEnum::AssocType { - bounds: g.into_iter().map(Into::into).collect(), - default: t.map(Into::into), + bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(), + default: t.map(|x| x.into_tcx(tcx)), }, - StrippedItem(inner) => from_clean_item_kind(*inner, tcx, name), + // `convert_item` early returns `None` for striped items + StrippedItem(_) => unreachable!(), PrimitiveItem(_) | KeywordItem(_) => { panic!("{:?} is not supported for JSON output", item) } @@ -190,18 +219,12 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Sy } } -impl From<clean::Module> for Module { - fn from(module: clean::Module) -> Self { - Module { is_crate: module.is_crate, items: ids(module.items) } - } -} - -impl From<clean::Struct> for Struct { - fn from(struct_: clean::Struct) -> Self { +impl FromWithTcx<clean::Struct> for Struct { + fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self { let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_; Struct { struct_type: from_ctor_kind(struct_type), - generics: generics.into(), + generics: generics.into_tcx(tcx), fields_stripped, fields: ids(fields), impls: Vec::new(), // Added in JsonRenderer::item @@ -209,11 +232,11 @@ impl From<clean::Struct> for Struct { } } -impl From<clean::Union> for Union { - fn from(struct_: clean::Union) -> Self { +impl FromWithTcx<clean::Union> for Union { + fn from_tcx(struct_: clean::Union, tcx: TyCtxt<'_>) -> Self { let clean::Union { generics, fields, fields_stripped } = struct_; Union { - generics: generics.into(), + generics: generics.into_tcx(tcx), fields_stripped, fields: ids(fields), impls: Vec::new(), // Added in JsonRenderer::item @@ -247,74 +270,81 @@ crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet<Qualifiers> { v } -impl From<clean::Function> for Function { - fn from(function: clean::Function) -> Self { +impl FromWithTcx<clean::Function> for Function { + fn from_tcx(function: clean::Function, tcx: TyCtxt<'_>) -> Self { let clean::Function { decl, generics, header } = function; Function { - decl: decl.into(), - generics: generics.into(), + decl: decl.into_tcx(tcx), + generics: generics.into_tcx(tcx), header: from_fn_header(&header), abi: header.abi.to_string(), } } } -impl From<clean::Generics> for Generics { - fn from(generics: clean::Generics) -> Self { +impl FromWithTcx<clean::Generics> for Generics { + fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self { Generics { - params: generics.params.into_iter().map(Into::into).collect(), - where_predicates: generics.where_predicates.into_iter().map(Into::into).collect(), + params: generics.params.into_iter().map(|x| x.into_tcx(tcx)).collect(), + where_predicates: generics + .where_predicates + .into_iter() + .map(|x| x.into_tcx(tcx)) + .collect(), } } } -impl From<clean::GenericParamDef> for GenericParamDef { - fn from(generic_param: clean::GenericParamDef) -> Self { - GenericParamDef { name: generic_param.name.to_string(), kind: generic_param.kind.into() } +impl FromWithTcx<clean::GenericParamDef> for GenericParamDef { + fn from_tcx(generic_param: clean::GenericParamDef, tcx: TyCtxt<'_>) -> Self { + GenericParamDef { + name: generic_param.name.to_string(), + kind: generic_param.kind.into_tcx(tcx), + } } } -impl From<clean::GenericParamDefKind> for GenericParamDefKind { - fn from(kind: clean::GenericParamDefKind) -> Self { +impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind { + fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self { use clean::GenericParamDefKind::*; match kind { Lifetime => GenericParamDefKind::Lifetime, Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type { - bounds: bounds.into_iter().map(Into::into).collect(), - default: default.map(Into::into), + bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), + default: default.map(|x| x.into_tcx(tcx)), }, - Const { did: _, ty } => GenericParamDefKind::Const(ty.into()), + Const { did: _, ty } => GenericParamDefKind::Const(ty.into_tcx(tcx)), } } } -impl From<clean::WherePredicate> for WherePredicate { - fn from(predicate: clean::WherePredicate) -> Self { +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 { - ty: ty.into(), - bounds: bounds.into_iter().map(Into::into).collect(), + ty: ty.into_tcx(tcx), + bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), }, RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate { lifetime: lifetime.0.to_string(), - bounds: bounds.into_iter().map(Into::into).collect(), + bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), }, EqPredicate { lhs, rhs } => { - WherePredicate::EqPredicate { lhs: lhs.into(), rhs: rhs.into() } + WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) } } } } } -impl From<clean::GenericBound> for GenericBound { - fn from(bound: clean::GenericBound) -> Self { +impl FromWithTcx<clean::GenericBound> for GenericBound { + fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self { use clean::GenericBound::*; match bound { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { GenericBound::TraitBound { - trait_: trait_.into(), - generic_params: generic_params.into_iter().map(Into::into).collect(), + trait_: trait_.into_tcx(tcx), + generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(), modifier: from_trait_bound_modifier(modifier), } } @@ -332,47 +362,47 @@ crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> T } } -impl From<clean::Type> for Type { - fn from(ty: clean::Type) -> Self { +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 { name: path.whole_name(), id: from_def_id(did), - args: path.segments.last().map(|args| Box::new(args.clone().args.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(Into::into).collect()) + .map(|v| v.into_iter().map(|x| x.into_tcx(tcx)).collect()) .unwrap_or_default(), }, Generic(s) => Type::Generic(s.to_string()), Primitive(p) => Type::Primitive(p.as_str().to_string()), - BareFunction(f) => Type::FunctionPointer(Box::new((*f).into())), - Tuple(t) => Type::Tuple(t.into_iter().map(Into::into).collect()), - Slice(t) => Type::Slice(Box::new((*t).into())), - Array(t, s) => Type::Array { type_: Box::new((*t).into()), len: s }, - ImplTrait(g) => Type::ImplTrait(g.into_iter().map(Into::into).collect()), + BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), + Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()), + Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), + Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s }, + ImplTrait(g) => Type::ImplTrait(g.into_iter().map(|x| x.into_tcx(tcx)).collect()), Never => Type::Never, Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { mutable: mutability == ast::Mutability::Mut, - type_: Box::new((*type_).into()), + type_: Box::new((*type_).into_tcx(tcx)), }, BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef { lifetime: lifetime.map(|l| l.0.to_string()), mutable: mutability == ast::Mutability::Mut, - type_: Box::new((*type_).into()), + type_: Box::new((*type_).into_tcx(tcx)), }, QPath { name, self_type, trait_ } => Type::QualifiedPath { name: name.to_string(), - self_type: Box::new((*self_type).into()), - trait_: Box::new((*trait_).into()), + self_type: Box::new((*self_type).into_tcx(tcx)), + trait_: Box::new((*trait_).into_tcx(tcx)), }, } } } -impl From<clean::BareFunctionDecl> for FunctionPointer { - fn from(bare_decl: clean::BareFunctionDecl) -> Self { +impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer { + fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self { let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl; FunctionPointer { header: if let rustc_hir::Unsafety::Unsafe = unsafety { @@ -382,24 +412,24 @@ impl From<clean::BareFunctionDecl> for FunctionPointer { } else { HashSet::new() }, - generic_params: generic_params.into_iter().map(Into::into).collect(), - decl: decl.into(), + generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(), + decl: decl.into_tcx(tcx), abi: abi.to_string(), } } } -impl From<clean::FnDecl> for FnDecl { - fn from(decl: clean::FnDecl) -> Self { - let clean::FnDecl { inputs, output, c_variadic, attrs: _ } = decl; +impl FromWithTcx<clean::FnDecl> for FnDecl { + fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self { + let clean::FnDecl { inputs, output, c_variadic } = decl; FnDecl { inputs: inputs .values .into_iter() - .map(|arg| (arg.name.to_string(), arg.type_.into())) + .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx))) .collect(), output: match output { - clean::FnRetTy::Return(t) => Some(t.into()), + clean::FnRetTy::Return(t) => Some(t.into_tcx(tcx)), clean::FnRetTy::DefaultReturn => None, }, c_variadic, @@ -407,22 +437,22 @@ impl From<clean::FnDecl> for FnDecl { } } -impl From<clean::Trait> for Trait { - fn from(trait_: clean::Trait) -> Self { +impl FromWithTcx<clean::Trait> for Trait { + fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self { let clean::Trait { unsafety, items, generics, bounds, is_auto } = trait_; Trait { is_auto, is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, items: ids(items), - generics: generics.into(), - bounds: bounds.into_iter().map(Into::into).collect(), + generics: generics.into_tcx(tcx), + bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), implementors: Vec::new(), // Added in JsonRenderer::item } } } -impl From<clean::Impl> for Impl { - fn from(impl_: clean::Impl) -> Self { +impl FromWithTcx<clean::Impl> for Impl { + fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { let clean::Impl { unsafety, generics, @@ -433,40 +463,45 @@ impl From<clean::Impl> for Impl { negative_polarity, synthetic, blanket_impl, + span: _span, } = impl_; Impl { is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, - generics: generics.into(), + generics: generics.into_tcx(tcx), provided_trait_methods: provided_trait_methods .into_iter() .map(|x| x.to_string()) .collect(), - trait_: trait_.map(Into::into), - for_: for_.into(), + trait_: trait_.map(|x| x.into_tcx(tcx)), + for_: for_.into_tcx(tcx), items: ids(items), negative: negative_polarity, synthetic, - blanket_impl: blanket_impl.map(Into::into), + blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)), } } } -crate fn from_function_method(function: clean::Function, has_body: bool) -> Method { +crate fn from_function_method( + function: clean::Function, + has_body: bool, + tcx: TyCtxt<'_>, +) -> Method { let clean::Function { header, decl, generics } = function; Method { - decl: decl.into(), - generics: generics.into(), + decl: decl.into_tcx(tcx), + generics: generics.into_tcx(tcx), header: from_fn_header(&header), abi: header.abi.to_string(), has_body, } } -impl From<clean::Enum> for Enum { - fn from(enum_: clean::Enum) -> Self { +impl FromWithTcx<clean::Enum> for Enum { + fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self { let clean::Enum { variants, generics, variants_stripped } = enum_; Enum { - generics: generics.into(), + generics: generics.into_tcx(tcx), variants_stripped, variants: ids(variants), impls: Vec::new(), // Added in JsonRenderer::item @@ -474,8 +509,8 @@ impl From<clean::Enum> for Enum { } } -impl From<clean::VariantStruct> for Struct { - fn from(struct_: clean::VariantStruct) -> Self { +impl FromWithTcx<clean::VariantStruct> for Struct { + fn from_tcx(struct_: clean::VariantStruct, _tcx: TyCtxt<'_>) -> Self { let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_; Struct { struct_type: from_ctor_kind(struct_type), @@ -487,29 +522,29 @@ impl From<clean::VariantStruct> for Struct { } } -impl From<clean::Variant> for Variant { - fn from(variant: clean::Variant) -> Self { +impl FromWithTcx<clean::Variant> for Variant { + fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self { use clean::Variant::*; match variant { CLike => Variant::Plain, - Tuple(t) => Variant::Tuple(t.into_iter().map(Into::into).collect()), + Tuple(t) => Variant::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()), Struct(s) => Variant::Struct(ids(s.fields)), } } } -impl From<clean::Import> for Import { - fn from(import: clean::Import) -> Self { +impl FromWithTcx<clean::Import> for Import { + fn from_tcx(import: clean::Import, _tcx: TyCtxt<'_>) -> Self { use clean::ImportKind::*; match import.kind { Simple(s) => Import { - span: import.source.path.whole_name(), + source: import.source.path.whole_name(), name: s.to_string(), id: import.source.did.map(from_def_id), glob: false, }, Glob => Import { - span: import.source.path.whole_name(), + source: import.source.path.whole_name(), name: import.source.path.last_name().to_string(), id: import.source.did.map(from_def_id), glob: true, @@ -518,8 +553,8 @@ impl From<clean::Import> for Import { } } -impl From<clean::ProcMacro> for ProcMacro { - fn from(mac: clean::ProcMacro) -> Self { +impl FromWithTcx<clean::ProcMacro> for ProcMacro { + fn from_tcx(mac: clean::ProcMacro, _tcx: TyCtxt<'_>) -> Self { ProcMacro { kind: from_macro_kind(mac.kind), helpers: mac.helpers.iter().map(|x| x.to_string()).collect(), @@ -536,41 +571,43 @@ crate fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind { } } -impl From<clean::Typedef> for Typedef { - fn from(typedef: clean::Typedef) -> Self { +impl FromWithTcx<clean::Typedef> for Typedef { + fn from_tcx(typedef: clean::Typedef, tcx: TyCtxt<'_>) -> Self { let clean::Typedef { type_, generics, item_type: _ } = typedef; - Typedef { type_: type_.into(), generics: generics.into() } + Typedef { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) } } } -impl From<clean::OpaqueTy> for OpaqueTy { - fn from(opaque: clean::OpaqueTy) -> Self { +impl FromWithTcx<clean::OpaqueTy> for OpaqueTy { + fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self { OpaqueTy { - bounds: opaque.bounds.into_iter().map(Into::into).collect(), - generics: opaque.generics.into(), + bounds: opaque.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), + generics: opaque.generics.into_tcx(tcx), } } } -fn from_clean_static(stat: clean::Static, tcx: TyCtxt<'_>) -> Static { - Static { - type_: stat.type_.into(), - mutable: stat.mutability == ast::Mutability::Mut, - expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(), +impl FromWithTcx<clean::Static> for Static { + fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { + Static { + type_: stat.type_.into_tcx(tcx), + mutable: stat.mutability == ast::Mutability::Mut, + expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(), + } } } -impl From<clean::TraitAlias> for TraitAlias { - fn from(alias: clean::TraitAlias) -> Self { +impl FromWithTcx<clean::TraitAlias> for TraitAlias { + fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self { TraitAlias { - generics: alias.generics.into(), - params: alias.bounds.into_iter().map(Into::into).collect(), + generics: alias.generics.into_tcx(tcx), + params: alias.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), } } } -impl From<ItemType> for ItemKind { - fn from(kind: ItemType) -> Self { +impl FromWithTcx<ItemType> for ItemKind { + fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self { use ItemType::*; match kind { Module => ItemKind::Module, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index b762fd7e18..96ea4b6c3b 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -14,7 +14,6 @@ use std::rc::Rc; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::edition::Edition; use rustdoc_json_types as types; @@ -24,7 +23,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; +use crate::json::conversions::{from_def_id, IntoWithTcx}; #[derive(Clone)] crate struct JsonRenderer<'tcx> { @@ -108,8 +107,8 @@ impl JsonRenderer<'tcx> { .last() .map(Clone::clone), visibility: types::Visibility::Public, - inner: types::ItemEnum::Trait(trait_item.clone().into()), - source: None, + inner: types::ItemEnum::Trait(trait_item.clone().into_tcx(self.tcx)), + span: None, docs: Default::default(), links: Default::default(), attrs: Default::default(), @@ -129,10 +128,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { "json" } + const RUN_ON_MODULE: bool = false; + fn init( krate: clean::Crate, options: RenderOptions, - _edition: Edition, cache: Cache, tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error> { @@ -169,8 +169,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { e.impls = self.get_impls(id) } let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone()); + // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check - // to make sure the items are unique. + // to make sure the items are unique. The main place this happens is when an item, is + // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod` if let Some(old_item) = removed { assert_eq!(old_item, new_item); } @@ -179,32 +181,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { Ok(()) } - fn mod_item_in(&mut self, item: &clean::Item, _module_name: &str) -> Result<(), Error> { - use clean::types::ItemKind::*; - if let ModuleItem(m) = &*item.kind { - for item in &m.items { - match &*item.kind { - // These don't have names so they don't get added to the output by default - ImportItem(_) => self.item(item.clone()).unwrap(), - ExternCrateItem { .. } => self.item(item.clone()).unwrap(), - ImplItem(i) => i.items.iter().for_each(|i| self.item(i.clone()).unwrap()), - _ => {} - } - } - } - self.item(item.clone()).unwrap(); - Ok(()) - } - - fn mod_item_out(&mut self, _item_name: &str) -> Result<(), Error> { - Ok(()) + fn mod_item_in(&mut self, _item: &clean::Item) -> Result<(), Error> { + unreachable!("RUN_ON_MODULE = false should never call mod_item_in") } - fn after_krate( - &mut self, - _krate: &clean::Crate, - _diag: &rustc_errors::Handler, - ) -> Result<(), Error> { + fn after_krate(&mut self) -> Result<(), Error> { debug!("Done with crate"); let mut index = (*self.index).clone().into_inner(); index.extend(self.get_trait_items()); @@ -225,7 +206,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { .map(|(k, (path, kind))| { ( from_def_id(k), - types::ItemSummary { crate_id: k.krate.as_u32(), path, kind: kind.into() }, + types::ItemSummary { + crate_id: k.krate.as_u32(), + path, + kind: kind.into_tcx(self.tcx), + }, ) }) .collect(), @@ -246,7 +231,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), - format_version: 4, + format_version: 5, }; let mut p = self.out_path.clone(); p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 9e84324544..943e2961d3 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -8,7 +8,7 @@ #![feature(box_syntax)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(test)] #![feature(crate_visibility_modifier)] #![feature(never_type)] @@ -16,7 +16,7 @@ #![feature(type_ascription)] #![feature(iter_intersperse)] #![recursion_limit = "256"] -#![deny(rustc::internal)] +#![warn(rustc::internal)] #[macro_use] extern crate lazy_static; @@ -30,7 +30,9 @@ extern crate tracing; // So if `rustc` was specified in Cargo.toml, this would spuriously rebuild crates. // // Dependencies listed in Cargo.toml do not need `extern crate`. + extern crate rustc_ast; +extern crate rustc_ast_lowering; extern crate rustc_ast_pretty; extern crate rustc_attr; extern crate rustc_data_structures; @@ -59,11 +61,20 @@ extern crate rustc_trait_selection; extern crate rustc_typeck; extern crate test as testing; +#[cfg(feature = "jemalloc")] +extern crate tikv_jemalloc_sys; +#[cfg(feature = "jemalloc")] +use tikv_jemalloc_sys as jemalloc_sys; +#[cfg(feature = "jemalloc")] +extern crate tikv_jemallocator; +#[cfg(feature = "jemalloc")] +use tikv_jemallocator as jemallocator; + use std::default::Default; use std::env; use std::process; -use rustc_driver::abort_on_err; +use rustc_driver::{abort_on_err, describe_lints}; use rustc_errors::ErrorReported; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; @@ -112,7 +123,48 @@ mod theme; mod visit_ast; mod visit_lib; +// See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs +// about jemallocator +#[cfg(feature = "jemalloc")] +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; + pub fn main() { + // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs + // about jemalloc-sys + #[cfg(feature = "jemalloc")] + { + use std::os::raw::{c_int, c_void}; + + #[used] + static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; + #[used] + static _F2: unsafe extern "C" fn(*mut *mut c_void, usize, usize) -> c_int = + jemalloc_sys::posix_memalign; + #[used] + static _F3: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::aligned_alloc; + #[used] + static _F4: unsafe extern "C" fn(usize) -> *mut c_void = jemalloc_sys::malloc; + #[used] + static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc; + #[used] + static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free; + + // On OSX, jemalloc doesn't directly override malloc/free, but instead + // registers itself with the allocator's zone APIs in a ctor. However, + // the linker doesn't seem to consider ctors as "used" when statically + // linking, so we need to explicitly depend on the function. + #[cfg(target_os = "macos")] + { + extern "C" { + fn _rjem_je_zone_register(); + } + + #[used] + static _F7: unsafe extern "C" fn() = _rjem_je_zone_register; + } + } + rustc_driver::set_sigpipe_handler(); rustc_driver::install_ice_hook(); @@ -235,7 +287,13 @@ fn opts() -> Vec<RustcOptGroup> { stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")), stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")), unstable("extern-html-root-url", |o| { - o.optmulti("", "extern-html-root-url", "base URL to use for dependencies", "NAME=URL") + o.optmulti( + "", + "extern-html-root-url", + "base URL to use for dependencies; for example, \ + \"std=/doc\" links std::vec::Vec to /doc/std/vec/struct.Vec.html", + "NAME=URL", + ) }), stable("plugin-path", |o| o.optmulti("", "plugin-path", "removed", "DIR")), stable("C", |o| { @@ -527,6 +585,14 @@ fn opts() -> Vec<RustcOptGroup> { unstable("print", |o| { o.optmulti("", "print", "Rustdoc information to print on stdout", "[unversioned-files]") }), + unstable("emit", |o| { + o.optmulti( + "", + "emit", + "Comma separated list of types of output for rustdoc to emit", + "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]", + ) + }), ] } @@ -585,14 +651,13 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( krate: clean::Crate, renderopts: config::RenderOptions, cache: formats::cache::Cache, - diag: &rustc_errors::Handler, - edition: rustc_span::edition::Edition, tcx: TyCtxt<'tcx>, ) -> MainResult { - match formats::run_format::<T>(krate, renderopts, cache, &diag, edition, tcx) { + match formats::run_format::<T>(krate, renderopts, cache, tcx) { Ok(_) => Ok(()), Err(e) => { - let mut msg = diag.struct_err(&format!("couldn't generate documentation: {}", e.error)); + let mut msg = + tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error)); let file = e.file.display().to_string(); if file.is_empty() { msg.emit() @@ -621,7 +686,6 @@ fn main_options(options: config::Options) -> MainResult { // need to move these items separately because we lose them by the time the closure is called, // but we can't create the Handler ahead of time because it's not Send - let diag_opts = (options.error_format, options.edition, options.debugging_opts.clone()); let show_coverage = options.show_coverage; let run_check = options.run_check; @@ -637,7 +701,6 @@ fn main_options(options: config::Options) -> MainResult { let default_passes = options.default_passes; let output_format = options.output_format; // FIXME: fix this clone (especially render_options) - let externs = options.externs.clone(); let manual_passes = options.manual_passes.clone(); let render_options = options.render_options.clone(); let config = core::create_config(options); @@ -646,10 +709,16 @@ fn main_options(options: config::Options) -> MainResult { compiler.enter(|queries| { let sess = compiler.session(); + if sess.opts.describe_lints { + let (_, lint_store) = &*queries.register_plugins()?.peek(); + describe_lints(sess, lint_store, true); + return Ok(()); + } + // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. - let resolver = core::create_resolver(externs, queries, &sess); + let resolver = core::create_resolver(queries, &sess); if sess.has_errors() { sess.fatal("Compilation failed, aborting rustdoc"); @@ -682,28 +751,12 @@ fn main_options(options: config::Options) -> MainResult { } info!("going to format"); - let (error_format, edition, debugging_options) = diag_opts; - let diag = core::new_handler(error_format, None, &debugging_options); match output_format { config::OutputFormat::Html => sess.time("render_html", || { - run_renderer::<html::render::Context<'_>>( - krate, - render_opts, - cache, - &diag, - edition, - tcx, - ) + run_renderer::<html::render::Context<'_>>(krate, render_opts, cache, tcx) }), config::OutputFormat::Json => sess.time("render_json", || { - run_renderer::<json::JsonRenderer<'_>>( - krate, - render_opts, - cache, - &diag, - edition, - tcx, - ) + run_renderer::<json::JsonRenderer<'_>>(krate, render_opts, cache, tcx) }), } }) diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index ffa2f7a47f..1b79811d4b 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -148,14 +148,13 @@ declare_rustdoc_lint! { } declare_rustdoc_lint! { - /// The `non_autolinks` lint detects when a URL could be written using - /// only angle brackets. This is a `rustdoc` only lint, see the - /// documentation in the [rustdoc book]. + /// The `bare_urls` lint detects when a URL is not a hyperlink. + /// This is a `rustdoc` only lint, see the documentation in the [rustdoc book]. /// - /// [rustdoc book]: ../../../rustdoc/lints.html#non_autolinks - NON_AUTOLINKS, + /// [rustdoc book]: ../../../rustdoc/lints.html#bare_urls + BARE_URLS, Warn, - "detects URLs that could be written using only angle brackets" + "detects URLs that are not hyperlinks" } crate static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| { @@ -166,7 +165,7 @@ crate static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| { PRIVATE_DOC_TESTS, INVALID_CODEBLOCK_ATTRIBUTES, INVALID_HTML_TAGS, - NON_AUTOLINKS, + BARE_URLS, MISSING_CRATE_LEVEL_DOCS, ] }); @@ -185,4 +184,6 @@ crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) { } lint_store .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links"); + lint_store.register_renamed("non_autolinks", "rustdoc::bare_urls"); + lint_store.register_renamed("rustdoc::non_autolinks", "rustdoc::bare_urls"); } diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs new file mode 100644 index 0000000000..56ef15eb88 --- /dev/null +++ b/src/librustdoc/passes/bare_urls.rs @@ -0,0 +1,111 @@ +use super::Pass; +use crate::clean::*; +use crate::core::DocContext; +use crate::fold::DocFolder; +use crate::html::markdown::opts; +use core::ops::Range; +use pulldown_cmark::{Event, Parser, Tag}; +use regex::Regex; +use rustc_errors::Applicability; +use std::lazy::SyncLazy; +use std::mem; + +crate const CHECK_BARE_URLS: Pass = Pass { + name: "check-bare-urls", + run: check_bare_urls, + description: "detects URLs that are not hyperlinks", +}; + +static URL_REGEX: SyncLazy<Regex> = SyncLazy::new(|| { + Regex::new(concat!( + r"https?://", // url scheme + r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains + r"[a-zA-Z]{2,63}", // root domain + r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)" // optional query or url fragments + )) + .expect("failed to build regex") +}); + +struct BareUrlsLinter<'a, 'tcx> { + cx: &'a mut DocContext<'tcx>, +} + +impl<'a, 'tcx> BareUrlsLinter<'a, 'tcx> { + fn find_raw_urls( + &self, + text: &str, + range: Range<usize>, + f: &impl Fn(&DocContext<'_>, &str, &str, Range<usize>), + ) { + trace!("looking for raw urls in {}", text); + // For now, we only check "full" URLs (meaning, starting with "http://" or "https://"). + for match_ in URL_REGEX.find_iter(&text) { + let url = match_.as_str(); + let url_range = match_.range(); + f( + self.cx, + "this URL is not a hyperlink", + url, + Range { start: range.start + url_range.start, end: range.start + url_range.end }, + ); + } + } +} + +crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { + BareUrlsLinter { cx }.fold_crate(krate) +} + +impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> { + fn fold_item(&mut self, item: Item) -> Option<Item> { + let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) { + Some(hir_id) => hir_id, + None => { + // If non-local, no need to check anything. + return Some(self.fold_item_recur(item)); + } + }; + let dox = item.attrs.collapsed_doc_value().unwrap_or_default(); + if !dox.is_empty() { + let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| { + let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs) + .unwrap_or_else(|| item.attr_span(cx.tcx)); + cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| { + lint.build(msg) + .note("bare URLs are not automatically turned into clickable links") + .span_suggestion( + sp, + "use an automatic link instead", + format!("<{}>", url), + Applicability::MachineApplicable, + ) + .emit() + }); + }; + + let mut p = Parser::new_ext(&dox, opts()).into_offset_iter(); + + while let Some((event, range)) = p.next() { + match event { + Event::Text(s) => self.find_raw_urls(&s, range, &report_diag), + // We don't want to check the text inside code blocks or links. + Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link(..))) => { + while let Some((event, _)) = p.next() { + match event { + Event::End(end) + if mem::discriminant(&end) == mem::discriminant(&tag) => + { + break; + } + _ => {} + } + } + } + _ => {} + } + } + } + + Some(self.fold_item_recur(item)) + } +} diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 0e97512862..c8b82fb156 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -7,7 +7,6 @@ use crate::passes::Pass; use rustc_lint::builtin::MISSING_DOCS; use rustc_middle::lint::LintLevelSource; use rustc_session::lint; -use rustc_span::symbol::sym; use rustc_span::FileName; use serde::Serialize; @@ -193,44 +192,13 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { // don't count items in stripped modules return Some(i); } - clean::ImportItem(..) | clean::ExternCrateItem { .. } => { - // docs on `use` and `extern crate` statements are not displayed, so they're not - // worth counting - return Some(i); - } - clean::ImplItem(ref impl_) - if i.attrs - .other_attrs - .iter() - .any(|item| item.has_name(sym::automatically_derived)) - || impl_.synthetic - || impl_.blanket_impl.is_some() => - { - // built-in derives get the `#[automatically_derived]` attribute, and - // synthetic/blanket impls are made up by rustdoc and can't be documented - // FIXME(misdreavus): need to also find items that came out of a derive macro - return Some(i); - } - clean::ImplItem(ref impl_) => { - let filename = i.source.filename(self.ctx.sess()); - if let Some(ref tr) = impl_.trait_ { - debug!( - "impl {:#} for {:#} in {}", - tr.print(&self.ctx.cache), - impl_.for_.print(&self.ctx.cache), - filename, - ); - - // don't count trait impls, the missing-docs lint doesn't so we shouldn't - // either - return Some(i); - } else { - // inherent impls *can* be documented, and those docs show up, but in most - // cases it doesn't make sense, as all methods on a type are in one single - // impl block - debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache), filename); - } - } + // docs on `use` and `extern crate` statements are not displayed, so they're not + // worth counting + clean::ImportItem(..) | clean::ExternCrateItem { .. } => {} + // Don't count trait impls, the missing-docs lint doesn't so we shouldn't either. + // Inherent impls *can* be documented, and those docs show up, but in most cases it + // doesn't make sense, as all methods on a type are in one single impl block + clean::ImplItem(_) => {} _ => { let has_docs = !i.attrs.doc_strings.is_empty(); let mut tests = Tests { found_tests: 0 }; @@ -243,7 +211,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { None, ); - let filename = i.source.filename(self.ctx.sess()); + let filename = i.span(self.ctx.tcx).filename(self.ctx.sess()); let has_doc_example = tests.found_tests != 0; let hir_id = self.ctx.tcx.hir().local_def_id_to_hir_id(i.def_id.expect_local()); let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 98886139f3..68a66806e0 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -9,7 +9,7 @@ use crate::clean; use crate::core::DocContext; use crate::fold::DocFolder; use crate::html::markdown::{self, RustCodeBlock}; -use crate::passes::{span_of_attrs, Pass}; +use crate::passes::Pass; crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass { name: "check-code-block-syntax", @@ -86,7 +86,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { // We couldn't calculate the span of the markdown block that had the error, so our // diagnostics are going to be a bit lacking. let mut diag = self.cx.sess().struct_span_warn( - super::span_of_attrs(&item.attrs).unwrap_or(item.source.span()), + item.attr_span(self.cx.tcx), "doc comment contains an invalid Rust code block", ); @@ -110,7 +110,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> { if let Some(dox) = &item.attrs.collapsed_doc_value() { - let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span()); + let sp = item.attr_span(self.cx.tcx); let extra = crate::html::markdown::ExtraInfo::new_did(self.cx.tcx, item.def_id, sp); for code_block in markdown::rust_code_blocks(&dox, &extra) { self.check_rust_syntax(&item, &dox, code_block); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index ec5994b762..aeaceeefc0 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -37,7 +37,8 @@ use crate::html::markdown::{markdown_links, MarkdownLink}; use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS}; use crate::passes::Pass; -use super::span_of_attrs; +mod early; +crate use early::IntraLinkCrateLoader; crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass { name: "collect-intra-doc-links", @@ -45,7 +46,7 @@ crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass { description: "resolves intra-doc links", }; -crate fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate { +fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate { LinkCollector { cx, mod_ids: Vec::new(), @@ -251,6 +252,7 @@ struct ResolutionInfo { extra_fragment: Option<String>, } +#[derive(Clone)] struct DiagnosticInfo<'a> { item: &'a Item, dox: &'a str, @@ -368,55 +370,28 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } /// Given a primitive type, try to resolve an associated item. - /// - /// HACK(jynelson): `item_str` is passed in instead of derived from `item_name` so the - /// lifetimes on `&'path` will work. fn resolve_primitive_associated_item( &self, prim_ty: PrimitiveType, ns: Namespace, - module_id: DefId, item_name: Symbol, - item_str: &'path str, - ) -> Result<(Res, Option<String>), ErrorKind<'path>> { + ) -> Option<(Res, String, Option<(DefKind, DefId)>)> { let tcx = self.cx.tcx; - prim_ty - .impls(tcx) - .into_iter() - .find_map(|&impl_| { - tcx.associated_items(impl_) - .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_) - .map(|item| { - let kind = item.kind; - self.kind_side_channel.set(Some((kind.as_def_kind(), item.def_id))); - match kind { - ty::AssocKind::Fn => "method", - ty::AssocKind::Const => "associatedconstant", - ty::AssocKind::Type => "associatedtype", - } - }) - .map(|out| { - ( - Res::Primitive(prim_ty), - Some(format!("{}#{}.{}", prim_ty.as_str(), out, item_str)), - ) - }) - }) - .ok_or_else(|| { - debug!( - "returning primitive error for {}::{} in {} namespace", - prim_ty.as_str(), - item_name, - ns.descr() - ); - ResolutionFailure::NotResolved { - module_id, - partial_res: Some(Res::Primitive(prim_ty)), - unresolved: item_str.into(), - } - .into() - }) + prim_ty.impls(tcx).into_iter().find_map(|&impl_| { + tcx.associated_items(impl_) + .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_) + .map(|item| { + let kind = item.kind; + let out = match kind { + ty::AssocKind::Fn => "method", + ty::AssocKind::Const => "associatedconstant", + ty::AssocKind::Type => "associatedtype", + }; + let fragment = format!("{}#{}.{}", prim_ty.as_str(), out, item_name); + (Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id))) + }) + }) } /// Resolves a string as a macro. @@ -490,8 +465,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { module_id: DefId, extra_fragment: &Option<String>, ) -> Result<(Res, Option<String>), ErrorKind<'path>> { - let tcx = self.cx.tcx; - if let Some(res) = self.resolve_path(path_str, ns, module_id) { match res { // FIXME(#76467): make this fallthrough to lookup the associated @@ -534,29 +507,58 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } })?; - // FIXME: are these both necessary? - let ty_res = if let Some(ty_res) = resolve_primitive(&path_root, TypeNS) + // FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support + // links to primitives when `#[doc(primitive)]` is present. It should give an ambiguity + // error instead and special case *only* modules with `#[doc(primitive)]`, not all + // primitives. + resolve_primitive(&path_root, TypeNS) .or_else(|| self.resolve_path(&path_root, TypeNS, module_id)) - { - ty_res - } else { - // FIXME: this is duplicated on the end of this function. - return if ns == Namespace::ValueNS { - self.variant_field(path_str, module_id) - } else { - Err(ResolutionFailure::NotResolved { - module_id, - partial_res: None, - unresolved: path_root.into(), + .and_then(|ty_res| { + let (res, fragment, side_channel) = + self.resolve_associated_item(ty_res, item_name, ns, module_id)?; + let result = if extra_fragment.is_some() { + let diag_res = side_channel.map_or(res, |(k, r)| Res::Def(k, r)); + Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(diag_res))) + } else { + // HACK(jynelson): `clean` expects the type, not the associated item + // but the disambiguator logic expects the associated item. + // Store the kind in a side channel so that only the disambiguator logic looks at it. + if let Some((kind, id)) = side_channel { + self.kind_side_channel.set(Some((kind, id))); + } + Ok((res, Some(fragment))) + }; + Some(result) + }) + .unwrap_or_else(|| { + if ns == Namespace::ValueNS { + self.variant_field(path_str, module_id) + } else { + Err(ResolutionFailure::NotResolved { + module_id, + partial_res: None, + unresolved: path_root.into(), + } + .into()) } - .into()) - }; - }; + }) + } - let res = match ty_res { - Res::Primitive(prim) => Some( - self.resolve_primitive_associated_item(prim, ns, module_id, item_name, item_str), - ), + /// Returns: + /// - None if no associated item was found + /// - Some((_, _, Some(_))) if an item was found and should go through a side channel + /// - Some((_, _, None)) otherwise + fn resolve_associated_item( + &mut self, + root_res: Res, + item_name: Symbol, + ns: Namespace, + module_id: DefId, + ) -> Option<(Res, String, Option<(DefKind, DefId)>)> { + let tcx = self.cx.tcx; + + match root_res { + Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name), Res::Def( DefKind::Struct | DefKind::Union @@ -599,59 +601,42 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::AssocKind::Const => "associatedconstant", ty::AssocKind::Type => "associatedtype", }; - Some(if extra_fragment.is_some() { - Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(ty_res))) - } else { - // HACK(jynelson): `clean` expects the type, not the associated item - // but the disambiguator logic expects the associated item. - // Store the kind in a side channel so that only the disambiguator logic looks at it. - self.kind_side_channel.set(Some((kind.as_def_kind(), id))); - Ok((ty_res, Some(format!("{}.{}", out, item_str)))) - }) - } else if ns == Namespace::ValueNS { - debug!("looking for variants or fields named {} for {:?}", item_name, did); - // FIXME(jynelson): why is this different from - // `variant_field`? - match tcx.type_of(did).kind() { - ty::Adt(def, _) => { - let field = if def.is_enum() { - def.all_fields().find(|item| item.ident.name == item_name) - } else { - def.non_enum_variant() - .fields - .iter() - .find(|item| item.ident.name == item_name) - }; - field.map(|item| { - if extra_fragment.is_some() { - let res = Res::Def( - if def.is_enum() { - DefKind::Variant - } else { - DefKind::Field - }, - item.did, - ); - Err(ErrorKind::AnchorFailure( - AnchorFailure::RustdocAnchorConflict(res), - )) - } else { - Ok(( - ty_res, - Some(format!( - "{}.{}", - if def.is_enum() { "variant" } else { "structfield" }, - item.ident - )), - )) - } - }) - } - _ => None, - } - } else { - None + // HACK(jynelson): `clean` expects the type, not the associated item + // but the disambiguator logic expects the associated item. + // Store the kind in a side channel so that only the disambiguator logic looks at it. + return Some(( + root_res, + format!("{}.{}", out, item_name), + Some((kind.as_def_kind(), id)), + )); + } + + if ns != Namespace::ValueNS { + return None; } + debug!("looking for variants or fields named {} for {:?}", item_name, did); + // FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?) + // NOTE: it's different from variant_field because it resolves fields and variants, + // not variant fields (2 path segments, not 3). + let def = match tcx.type_of(did).kind() { + ty::Adt(def, _) => def, + _ => return None, + }; + let field = if def.is_enum() { + def.all_fields().find(|item| item.ident.name == item_name) + } else { + def.non_enum_variant().fields.iter().find(|item| item.ident.name == item_name) + }?; + let kind = if def.is_enum() { DefKind::Variant } else { DefKind::Field }; + Some(( + root_res, + format!( + "{}.{}", + if def.is_enum() { "variant" } else { "structfield" }, + field.ident + ), + Some((kind, field.did)), + )) } Res::Def(DefKind::Trait, did) => tcx .associated_items(did) @@ -669,27 +654,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } }; - if extra_fragment.is_some() { - Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(ty_res))) - } else { - let res = Res::Def(item.kind.as_def_kind(), item.def_id); - Ok((res, Some(format!("{}.{}", kind, item_str)))) - } + let res = Res::Def(item.kind.as_def_kind(), item.def_id); + (res, format!("{}.{}", kind, item_name), None) }), _ => None, - }; - res.unwrap_or_else(|| { - if ns == Namespace::ValueNS { - self.variant_field(path_str, module_id) - } else { - Err(ResolutionFailure::NotResolved { - module_id, - partial_res: Some(ty_res), - unresolved: item_str.into(), - } - .into()) - } - }) + } } /// Used for reporting better errors. @@ -820,7 +789,7 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_ } impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { - fn fold_item(&mut self, mut item: Item) -> Option<Item> { + fn fold_item(&mut self, item: Item) -> Option<Item> { use rustc_middle::ty::DefIdTree; let parent_node = if item.is_fake() { @@ -884,7 +853,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } }); - if item.is_mod() && item.attrs.inner_docs { + let inner_docs = item.inner_docs(self.cx.tcx); + + if item.is_mod() && inner_docs { self.mod_ids.push(item.def_id); } @@ -905,13 +876,13 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { for md_link in markdown_links(&doc) { let link = self.resolve_link(&item, &doc, &self_name, parent_node, krate, md_link); if let Some(link) = link { - item.attrs.links.push(link); + self.cx.cache.intra_doc_links.entry(item.def_id).or_default().push(link); } } } Some(if item.is_mod() { - if !item.attrs.inner_docs { + if !inner_docs { self.mod_ids.push(item.def_id); } @@ -924,6 +895,117 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } +enum PreprocessingError<'a> { + Anchor(AnchorFailure), + Disambiguator(Range<usize>, String), + Resolution(ResolutionFailure<'a>, String, Option<Disambiguator>), +} + +impl From<AnchorFailure> for PreprocessingError<'_> { + fn from(err: AnchorFailure) -> Self { + Self::Anchor(err) + } +} + +struct PreprocessingInfo { + path_str: String, + disambiguator: Option<Disambiguator>, + extra_fragment: Option<String>, + link_text: String, +} + +/// Returns: +/// - `None` if the link should be ignored. +/// - `Some(Err)` if the link should emit an error +/// - `Some(Ok)` if the link is valid +/// +/// `link_buffer` is needed for lifetime reasons; it will always be overwritten and the contents ignored. +fn preprocess_link<'a>( + ori_link: &'a MarkdownLink, +) -> Option<Result<PreprocessingInfo, PreprocessingError<'a>>> { + // [] is mostly likely not supposed to be a link + if ori_link.link.is_empty() { + return None; + } + + // Bail early for real links. + if ori_link.link.contains('/') { + return None; + } + + let stripped = ori_link.link.replace("`", ""); + let mut parts = stripped.split('#'); + + let link = parts.next().unwrap(); + if link.trim().is_empty() { + // This is an anchor to an element of the current page, nothing to do in here! + return None; + } + let extra_fragment = parts.next(); + if parts.next().is_some() { + // A valid link can't have multiple #'s + return Some(Err(AnchorFailure::MultipleAnchors.into())); + } + + // 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), + 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) { + let no_backticks_range = range_between_backticks(&ori_link); + let disambiguator_range = (no_backticks_range.start + relative_range.start) + ..(no_backticks_range.start + relative_range.end); + return Some(Err(PreprocessingError::Disambiguator(disambiguator_range, err_msg))); + } else { + return None; + } + } + }; + + if should_ignore_link(path_str) { + 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) { + Ok(path) => path, + Err(err_kind) => { + debug!("link has malformed generics: {}", path_str); + return Some(Err(PreprocessingError::Resolution( + err_kind, + path_str.to_owned(), + disambiguator, + ))); + } + } + } else { + path_str.to_owned() + }; + + // Sanity check to make sure we don't have any angle brackets after stripping generics. + assert!(!path_str.contains(['<', '>'].as_slice())); + + // The link is not an intra-doc link if it still contains spaces after stripping generics. + if path_str.contains(' ') { + return None; + } + + Some(Ok(PreprocessingInfo { + path_str, + disambiguator, + extra_fragment: extra_fragment.map(String::from), + link_text, + })) +} + impl LinkCollector<'_, '_> { /// This is the entry point for resolving an intra-doc link. /// @@ -939,54 +1021,38 @@ impl LinkCollector<'_, '_> { ) -> Option<ItemLink> { trace!("considering link '{}'", ori_link.link); - // Bail early for real links. - if ori_link.link.contains('/') { - return None; - } - - // [] is mostly likely not supposed to be a link - if ori_link.link.is_empty() { - return None; - } - - let link = ori_link.link.replace("`", ""); - let parts = link.split('#').collect::<Vec<_>>(); - let (link, extra_fragment) = if parts.len() > 2 { - // A valid link can't have multiple #'s - anchor_failure( - self.cx, - &item, - &link, - dox, - ori_link.range, - AnchorFailure::MultipleAnchors, - ); - return None; - } else if parts.len() == 2 { - if parts[0].trim().is_empty() { - // This is an anchor to an element of the current page, nothing to do in here! - return None; - } - (parts[0], Some(parts[1].to_owned())) - } else { - (parts[0], None) - }; - - // Parse and strip the disambiguator from the link, if present. - let (mut path_str, disambiguator) = if let Ok((d, path)) = Disambiguator::from_str(&link) { - (path.trim(), Some(d)) - } else { - (link.trim(), None) + let diag_info = DiagnosticInfo { + item, + dox, + ori_link: &ori_link.link, + link_range: ori_link.range.clone(), }; - if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !*&;".contains(ch))) { - return None; - } + let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } = + match preprocess_link(&ori_link)? { + Ok(x) => x, + Err(err) => { + match err { + PreprocessingError::Anchor(err) => anchor_failure(self.cx, diag_info, err), + PreprocessingError::Disambiguator(range, msg) => { + disambiguator_error(self.cx, diag_info, range, &msg) + } + PreprocessingError::Resolution(err, path_str, disambiguator) => { + resolution_failure( + self, + diag_info, + &path_str, + disambiguator, + smallvec![err], + ); + } + } + return None; + } + }; + let mut path_str = &*path_str; - // 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()); + let inner_docs = item.inner_docs(self.cx.tcx); // In order to correctly resolve intra-doc links we need to // pick a base AST node to work from. If the documentation for @@ -999,11 +1065,8 @@ impl LinkCollector<'_, '_> { // we've already pushed this node onto the resolution stack but // for outer comments we explicitly try and resolve against the // parent_node first. - let base_node = if item.is_mod() && item.attrs.inner_docs { - self.mod_ids.last().copied() - } else { - parent_node - }; + let base_node = + if item.is_mod() && inner_docs { self.mod_ids.last().copied() } else { parent_node }; let mut module_id = if let Some(id) = base_node { id @@ -1012,11 +1075,9 @@ impl LinkCollector<'_, '_> { debug!("attempting to resolve item without parent module: {}", path_str); resolution_failure( self, - &item, + diag_info, path_str, disambiguator, - dox, - ori_link.range, smallvec![ResolutionFailure::NoParentItem], ); return None; @@ -1053,49 +1114,14 @@ impl LinkCollector<'_, '_> { module_id = DefId { krate, index: CRATE_DEF_INDEX }; } - // Strip generics from the path. - let stripped_path_string; - if path_str.contains(['<', '>'].as_slice()) { - stripped_path_string = match strip_generics_from_path(path_str) { - Ok(path) => path, - Err(err_kind) => { - debug!("link has malformed generics: {}", path_str); - resolution_failure( - self, - &item, - path_str, - disambiguator, - dox, - ori_link.range, - smallvec![err_kind], - ); - return None; - } - }; - path_str = &stripped_path_string; - } - // Sanity check to make sure we don't have any angle brackets after stripping generics. - assert!(!path_str.contains(['<', '>'].as_slice())); - - // The link is not an intra-doc link if it still contains spaces after stripping generics. - if path_str.contains(' ') { - return None; - } - - let diag_info = DiagnosticInfo { - item, - dox, - ori_link: &ori_link.link, - link_range: ori_link.range.clone(), - }; let (mut res, mut fragment) = self.resolve_with_disambiguator_cached( ResolutionInfo { module_id, dis: disambiguator, path_str: path_str.to_owned(), - extra_fragment, + extra_fragment: extra_fragment.map(String::from), }, - diag_info, + diag_info.clone(), // this struct should really be Copy, but Range is not :( matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut), )?; @@ -1113,10 +1139,7 @@ impl LinkCollector<'_, '_> { if fragment.is_some() { anchor_failure( self.cx, - &item, - path_str, - dox, - ori_link.range, + diag_info, AnchorFailure::RustdocAnchorConflict(prim), ); return None; @@ -1126,7 +1149,7 @@ impl LinkCollector<'_, '_> { } else { // `[char]` when a `char` module is in scope let candidates = vec![res, prim]; - ambiguity_error(self.cx, &item, path_str, dox, ori_link.range, candidates); + ambiguity_error(self.cx, diag_info, path_str, candidates); return None; } } @@ -1146,15 +1169,7 @@ impl LinkCollector<'_, '_> { diag.note(¬e); suggest_disambiguator(resolved, diag, path_str, dox, sp, &ori_link.range); }; - report_diagnostic( - self.cx.tcx, - BROKEN_INTRA_DOC_LINKS, - &msg, - &item, - dox, - &ori_link.range, - callback, - ); + report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, callback); }; let verify = |kind: DefKind, id: DefId| { @@ -1194,7 +1209,7 @@ impl LinkCollector<'_, '_> { if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src) && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst) { - privacy_error(self.cx, &item, &path_str, dox, &ori_link); + privacy_error(self.cx, &diag_info, &path_str); } } @@ -1226,9 +1241,7 @@ impl LinkCollector<'_, '_> { &ori_link.range, &item.attrs, ) - .unwrap_or_else(|| { - span_of_attrs(&item.attrs).unwrap_or(item.source.span()) - }); + .unwrap_or_else(|| item.attr_span(self.cx.tcx)); rustc_session::parse::feature_err( &self.cx.tcx.sess.parse_sess, @@ -1337,29 +1350,14 @@ impl LinkCollector<'_, '_> { } } } - resolution_failure( - self, - diag.item, - path_str, - disambiguator, - diag.dox, - diag.link_range, - smallvec![kind], - ); + resolution_failure(self, diag, path_str, disambiguator, smallvec![kind]); // This could just be a normal link or a broken link // we could potentially check if something is // "intra-doc-link-like" and warn in that case. None } Err(ErrorKind::AnchorFailure(msg)) => { - anchor_failure( - self.cx, - diag.item, - diag.ori_link, - diag.dox, - diag.link_range, - msg, - ); + anchor_failure(self.cx, diag, msg); None } } @@ -1376,14 +1374,7 @@ impl LinkCollector<'_, '_> { Ok(res) } Err(ErrorKind::AnchorFailure(msg)) => { - anchor_failure( - self.cx, - diag.item, - diag.ori_link, - diag.dox, - diag.link_range, - msg, - ); + anchor_failure(self.cx, diag, msg); return None; } Err(ErrorKind::Resolve(box kind)) => Err(kind), @@ -1391,14 +1382,7 @@ impl LinkCollector<'_, '_> { value_ns: match self.resolve(path_str, ValueNS, base_node, extra_fragment) { Ok(res) => Ok(res), Err(ErrorKind::AnchorFailure(msg)) => { - anchor_failure( - self.cx, - diag.item, - diag.ori_link, - diag.dox, - diag.link_range, - msg, - ); + anchor_failure(self.cx, diag, msg); return None; } Err(ErrorKind::Resolve(box kind)) => Err(kind), @@ -1427,11 +1411,9 @@ impl LinkCollector<'_, '_> { if len == 0 { resolution_failure( self, - diag.item, + diag, path_str, disambiguator, - diag.dox, - diag.link_range, candidates.into_iter().filter_map(|res| res.err()).collect(), ); // this could just be a normal link @@ -1448,14 +1430,7 @@ impl LinkCollector<'_, '_> { } // If we're reporting an ambiguity, don't mention the namespaces that failed let candidates = candidates.map(|candidate| candidate.ok().map(|(res, _)| res)); - ambiguity_error( - self.cx, - diag.item, - path_str, - diag.dox, - diag.link_range, - candidates.present_items().collect(), - ); + ambiguity_error(self.cx, diag, path_str, candidates.present_items().collect()); None } } @@ -1473,15 +1448,7 @@ impl LinkCollector<'_, '_> { break; } } - resolution_failure( - self, - diag.item, - path_str, - disambiguator, - diag.dox, - diag.link_range, - smallvec![kind], - ); + resolution_failure(self, diag, path_str, disambiguator, smallvec![kind]); None } } @@ -1490,6 +1457,43 @@ impl LinkCollector<'_, '_> { } } +/// Get the section of a link between the backticks, +/// or the whole link if there aren't any backticks. +/// +/// For example: +/// +/// ```text +/// [`Foo`] +/// ^^^ +/// ``` +fn range_between_backticks(ori_link: &MarkdownLink) -> Range<usize> { + let after_first_backtick_group = ori_link.link.bytes().position(|b| b != b'`').unwrap_or(0); + let before_second_backtick_group = ori_link + .link + .bytes() + .skip(after_first_backtick_group) + .position(|b| b == b'`') + .unwrap_or(ori_link.link.len()); + (ori_link.range.start + after_first_backtick_group) + ..(ori_link.range.start + before_second_backtick_group) +} + +/// Returns true if we should ignore `link` due to it being unlikely +/// that it is an intra-doc link. `link` should still have disambiguators +/// if there were any. +/// +/// The difference between this and [`should_ignore_link()`] is that this +/// check should only be used on links that still have disambiguators. +fn should_ignore_link_with_disambiguators(link: &str) -> bool { + link.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !*&;@()".contains(ch))) +} + +/// Returns true if we should ignore `path_str` due to it being unlikely +/// that it is an intra-doc link. +fn should_ignore_link(path_str: &str) -> bool { + path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !*&;".contains(ch))) +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] /// Disambiguators for a link. enum Disambiguator { @@ -1516,27 +1520,14 @@ impl Disambiguator { } } - /// Given a link, parse and return `(disambiguator, path_str)` - fn from_str(link: &str) -> Result<(Self, &str), ()> { + /// Given a link, parse and return `(disambiguator, path_str)`. + /// + /// 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>)> { use Disambiguator::{Kind, Namespace as NS, Primitive}; - let find_suffix = || { - let suffixes = [ - ("!()", DefKind::Macro(MacroKind::Bang)), - ("()", DefKind::Fn), - ("!", DefKind::Macro(MacroKind::Bang)), - ]; - for &(suffix, kind) in &suffixes { - if let Some(link) = link.strip_suffix(suffix) { - // Avoid turning `!` or `()` into an empty string - if !link.is_empty() { - return Ok((Kind(kind), link)); - } - } - } - Err(()) - }; - if let Some(idx) = link.find('@') { let (prefix, rest) = link.split_at(idx); let d = match prefix { @@ -1553,11 +1544,24 @@ impl Disambiguator { "value" => NS(Namespace::ValueNS), "macro" => NS(Namespace::MacroNS), "prim" | "primitive" => Primitive, - _ => return find_suffix(), + _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)), }; - Ok((d, &rest[1..])) + Ok(Some((d, &rest[1..]))) } else { - find_suffix() + let suffixes = [ + ("!()", DefKind::Macro(MacroKind::Bang)), + ("()", DefKind::Fn), + ("!", DefKind::Macro(MacroKind::Bang)), + ]; + for &(suffix, kind) in &suffixes { + if let Some(link) = link.strip_suffix(suffix) { + // Avoid turning `!` or `()` into an empty string + if !link.is_empty() { + return Ok(Some((Kind(kind), link))); + } + } + } + Ok(None) } } @@ -1678,9 +1682,7 @@ fn report_diagnostic( tcx: TyCtxt<'_>, lint: &'static Lint, msg: &str, - item: &Item, - dox: &str, - link_range: &Range<usize>, + DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>, decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option<rustc_span::Span>), ) { let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) { @@ -1692,13 +1694,12 @@ fn report_diagnostic( } }; - let attrs = &item.attrs; - let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); + let sp = item.attr_span(tcx); tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| { let mut diag = lint.build(msg); - let span = super::source_span_for_markdown_range(tcx, dox, link_range, attrs); + let span = super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs); if let Some(sp) = span { diag.set_span(sp); @@ -1734,11 +1735,9 @@ fn report_diagnostic( /// `std::io::Error::x`, this will resolve `std::io::Error`. fn resolution_failure( collector: &mut LinkCollector<'_, '_>, - item: &Item, + diag_info: DiagnosticInfo<'_>, path_str: &str, disambiguator: Option<Disambiguator>, - dox: &str, - link_range: Range<usize>, kinds: SmallVec<[ResolutionFailure<'_>; 3]>, ) { let tcx = collector.cx.tcx; @@ -1746,9 +1745,7 @@ fn resolution_failure( tcx, BROKEN_INTRA_DOC_LINKS, &format!("unresolved link to `{}`", path_str), - item, - dox, - &link_range, + &diag_info, |diag, sp| { let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx),); let assoc_item_not_allowed = |res: Res| { @@ -1908,9 +1905,9 @@ fn resolution_failure( disambiguator, diag, path_str, - dox, + diag_info.dox, sp, - &link_range, + &diag_info.link_range, ) } @@ -1957,37 +1954,53 @@ fn resolution_failure( } /// Report an anchor failure. -fn anchor_failure( - cx: &DocContext<'_>, - item: &Item, - path_str: &str, - dox: &str, - link_range: Range<usize>, - failure: AnchorFailure, -) { - let msg = match failure { - AnchorFailure::MultipleAnchors => format!("`{}` contains multiple anchors", path_str), - AnchorFailure::RustdocAnchorConflict(res) => format!( - "`{}` contains an anchor, but links to {kind}s are already anchored", - path_str, - kind = res.descr(), +fn anchor_failure(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, failure: AnchorFailure) { + let (msg, anchor_idx) = match failure { + AnchorFailure::MultipleAnchors => { + (format!("`{}` contains multiple anchors", diag_info.ori_link), 1) + } + AnchorFailure::RustdocAnchorConflict(res) => ( + format!( + "`{}` contains an anchor, but links to {kind}s are already anchored", + diag_info.ori_link, + kind = res.descr(), + ), + 0, ), }; - report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| { - if let Some(sp) = sp { - diag.span_label(sp, "contains invalid anchor"); + report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, |diag, sp| { + if let Some(mut sp) = sp { + if let Some((fragment_offset, _)) = + diag_info.ori_link.char_indices().filter(|(_, x)| *x == '#').nth(anchor_idx) + { + sp = sp.with_lo(sp.lo() + rustc_span::BytePos(fragment_offset as _)); + } + diag.span_label(sp, "invalid anchor"); + } + if let AnchorFailure::RustdocAnchorConflict(Res::Primitive(_)) = failure { + diag.note("this restriction may be lifted in a future release"); + diag.note("see https://github.com/rust-lang/rust/issues/83083 for more information"); } }); } +/// Report an error in the link disambiguator. +fn disambiguator_error( + cx: &DocContext<'_>, + mut diag_info: DiagnosticInfo<'_>, + disambiguator_range: Range<usize>, + msg: &str, +) { + diag_info.link_range = disambiguator_range; + report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |_diag, _sp| {}); +} + /// Report an ambiguity error, where there were multiple possible resolutions. fn ambiguity_error( cx: &DocContext<'_>, - item: &Item, + diag_info: DiagnosticInfo<'_>, path_str: &str, - dox: &str, - link_range: Range<usize>, candidates: Vec<Res>, ) { let mut msg = format!("`{}` is ", path_str); @@ -2014,7 +2027,7 @@ fn ambiguity_error( } } - report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| { + report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, |diag, sp| { if let Some(sp) = sp { diag.span_label(sp, "ambiguous link"); } else { @@ -2023,7 +2036,14 @@ fn ambiguity_error( for res in candidates { let disambiguator = Disambiguator::from_res(res); - suggest_disambiguator(disambiguator, diag, path_str, dox, sp, &link_range); + suggest_disambiguator( + disambiguator, + diag, + path_str, + diag_info.dox, + sp, + &diag_info.link_range, + ); } }); } @@ -2055,9 +2075,9 @@ fn suggest_disambiguator( } /// Report a link from a public item to a private one. -fn privacy_error(cx: &DocContext<'_>, item: &Item, path_str: &str, dox: &str, link: &MarkdownLink) { +fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str: &str) { let sym; - let item_name = match item.name { + let item_name = match diag_info.item.name { Some(name) => { sym = name.as_str(); &*sym @@ -2067,7 +2087,7 @@ fn privacy_error(cx: &DocContext<'_>, item: &Item, path_str: &str, dox: &str, li let msg = format!("public documentation for `{}` links to private item `{}`", item_name, path_str); - report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link.range, |diag, sp| { + report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| { if let Some(sp) = sp { diag.span_label(sp, "this item is private"); } diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs new file mode 100644 index 0000000000..7cba2523d1 --- /dev/null +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -0,0 +1,63 @@ +use rustc_ast as ast; +use rustc_hir::def::Namespace::TypeNS; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_interface::interface; + +use std::cell::RefCell; +use std::mem; +use std::rc::Rc; + +// Letting the resolver escape at the end of the function leads to inconsistencies between the +// crates the TyCtxt sees and the resolver sees (because the resolver could load more crates +// after escaping). Hopefully `IntraLinkCrateLoader` gets all the crates we need ... +crate struct IntraLinkCrateLoader { + current_mod: DefId, + crate resolver: Rc<RefCell<interface::BoxedResolver>>, +} + +impl IntraLinkCrateLoader { + crate fn new(resolver: Rc<RefCell<interface::BoxedResolver>>) -> Self { + let crate_id = LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(); + Self { current_mod: crate_id, resolver } + } +} + +impl ast::visit::Visitor<'_> for IntraLinkCrateLoader { + fn visit_attribute(&mut self, attr: &ast::Attribute) { + use crate::html::markdown::markdown_links; + use crate::passes::collect_intra_doc_links::preprocess_link; + + if let Some(doc) = attr.doc_str() { + for link in markdown_links(&doc.as_str()) { + let path_str = if let Some(Ok(x)) = preprocess_link(&link) { + x.path_str + } else { + continue; + }; + self.resolver.borrow_mut().access(|resolver| { + let _ = resolver.resolve_str_path_error( + attr.span, + &path_str, + TypeNS, + self.current_mod, + ); + }); + } + } + ast::visit::walk_attribute(self, attr); + } + + fn visit_item(&mut self, item: &ast::Item) { + use rustc_ast_lowering::ResolverAstLowering; + + if let ast::ItemKind::Mod(..) = item.kind { + let new_mod = + self.resolver.borrow_mut().access(|resolver| resolver.local_def_id(item.id)); + let old_mod = mem::replace(&mut self.current_mod, new_mod.to_def_id()); + ast::visit::walk_item(self, item); + self.current_mod = old_mod; + } else { + ast::visit::walk_item(self, item); + } + } +} diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 492cc9118f..12f16c9359 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -3,7 +3,7 @@ use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; -use rustc_data_structures::fx::{FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::ty::DefIdTree; use rustc_span::symbol::sym; @@ -117,19 +117,14 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } } - let items = if let Some(ref mut it) = krate.module { - if let ModuleItem(Module { ref mut items, .. }) = *it.kind { - items - } else { - panic!("collect-trait-impls can't run"); - } + let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind { + items } else { panic!("collect-trait-impls can't run"); }; items.extend(synth_impls); items.extend(new_items); - krate } diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs index 951258db9e..c8d2263d81 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/doc_test_lints.rs @@ -3,7 +3,7 @@ //! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests //! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests. -use super::{span_of_attrs, Pass}; +use super::Pass; use crate::clean; use crate::clean::*; use crate::core::DocContext; @@ -97,7 +97,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { if tests.found_tests == 0 && cx.tcx.sess.is_nightly_build() { if should_have_doc_example(cx, &item) { debug!("reporting error for {:?} (hir_id={:?})", item, hir_id); - let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span()); + let sp = item.attr_span(cx.tcx); cx.tcx.struct_span_lint_hir( crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id, @@ -109,7 +109,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { cx.tcx.struct_span_lint_hir( crate::lint::PRIVATE_DOC_TESTS, hir_id, - span_of_attrs(&item.attrs).unwrap_or(item.source.span()), + item.attr_span(cx.tcx), |lint| lint.build("documentation test in private item").emit(), ); } diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index 23364b6fec..f29d38e3e0 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -1,4 +1,4 @@ -use super::{span_of_attrs, Pass}; +use super::Pass; use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; @@ -181,7 +181,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { let sp = match super::source_span_for_markdown_range(tcx, &dox, range, &item.attrs) { Some(sp) => sp, - None => span_of_attrs(&item.attrs).unwrap_or(item.source.span()), + None => item.attr_span(tcx), }; tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| { lint.build(msg).emit() diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 4c639c8496..0e86fe4564 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -12,8 +12,8 @@ use crate::core::DocContext; mod stripper; crate use stripper::*; -mod non_autolinks; -crate use self::non_autolinks::CHECK_NON_AUTOLINKS; +mod bare_urls; +crate use self::bare_urls::CHECK_BARE_URLS; mod strip_hidden; crate use self::strip_hidden::STRIP_HIDDEN; @@ -30,7 +30,7 @@ crate use self::unindent_comments::UNINDENT_COMMENTS; mod propagate_doc_cfg; crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG; -mod collect_intra_doc_links; +crate mod collect_intra_doc_links; crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS; mod doc_test_lints; @@ -90,7 +90,7 @@ crate const PASSES: &[Pass] = &[ COLLECT_TRAIT_IMPLS, CALCULATE_DOC_COVERAGE, CHECK_INVALID_HTML_TAGS, - CHECK_NON_AUTOLINKS, + CHECK_BARE_URLS, ]; /// The list of passes run by default. @@ -105,12 +105,11 @@ crate const DEFAULT_PASSES: &[ConditionalPass] = &[ ConditionalPass::always(CHECK_CODE_BLOCK_SYNTAX), ConditionalPass::always(CHECK_INVALID_HTML_TAGS), ConditionalPass::always(PROPAGATE_DOC_CFG), - ConditionalPass::always(CHECK_NON_AUTOLINKS), + ConditionalPass::always(CHECK_BARE_URLS), ]; /// The list of default passes run when `--doc-coverage` is passed to rustdoc. crate const COVERAGE_PASSES: &[ConditionalPass] = &[ - ConditionalPass::always(COLLECT_TRAIT_IMPLS), ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate), ConditionalPass::always(CALCULATE_DOC_COVERAGE), diff --git a/src/librustdoc/passes/non_autolinks.rs b/src/librustdoc/passes/non_autolinks.rs deleted file mode 100644 index 16ad940c62..0000000000 --- a/src/librustdoc/passes/non_autolinks.rs +++ /dev/null @@ -1,134 +0,0 @@ -use super::{span_of_attrs, Pass}; -use crate::clean::*; -use crate::core::DocContext; -use crate::fold::DocFolder; -use crate::html::markdown::opts; -use core::ops::Range; -use pulldown_cmark::{Event, LinkType, Parser, Tag}; -use regex::Regex; -use rustc_errors::Applicability; - -crate const CHECK_NON_AUTOLINKS: Pass = Pass { - name: "check-non-autolinks", - run: check_non_autolinks, - description: "detects URLs that could be linkified", -}; - -const URL_REGEX: &str = concat!( - r"https?://", // url scheme - r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains - r"[a-zA-Z]{2,63}", // root domain - r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)" // optional query or url fragments -); - -struct NonAutolinksLinter<'a, 'tcx> { - cx: &'a mut DocContext<'tcx>, - regex: Regex, -} - -impl<'a, 'tcx> NonAutolinksLinter<'a, 'tcx> { - fn find_raw_urls( - &self, - text: &str, - range: Range<usize>, - f: &impl Fn(&DocContext<'_>, &str, &str, Range<usize>), - ) { - // For now, we only check "full" URLs (meaning, starting with "http://" or "https://"). - for match_ in self.regex.find_iter(&text) { - let url = match_.as_str(); - let url_range = match_.range(); - f( - self.cx, - "this URL is not a hyperlink", - url, - Range { start: range.start + url_range.start, end: range.start + url_range.end }, - ); - } - } -} - -crate fn check_non_autolinks(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - if !cx.tcx.sess.is_nightly_build() { - krate - } else { - let mut coll = - NonAutolinksLinter { cx, regex: Regex::new(URL_REGEX).expect("failed to build regex") }; - - coll.fold_crate(krate) - } -} - -impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> { - fn fold_item(&mut self, item: Item) -> Option<Item> { - let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) { - Some(hir_id) => hir_id, - None => { - // If non-local, no need to check anything. - return Some(self.fold_item_recur(item)); - } - }; - let dox = item.attrs.collapsed_doc_value().unwrap_or_default(); - if !dox.is_empty() { - let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| { - let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs) - .or_else(|| span_of_attrs(&item.attrs)) - .unwrap_or(item.source.span()); - cx.tcx.struct_span_lint_hir(crate::lint::NON_AUTOLINKS, hir_id, sp, |lint| { - lint.build(msg) - .span_suggestion( - sp, - "use an automatic link instead", - format!("<{}>", url), - Applicability::MachineApplicable, - ) - .emit() - }); - }; - - let mut p = Parser::new_ext(&dox, opts()).into_offset_iter(); - - while let Some((event, range)) = p.next() { - match event { - Event::Start(Tag::Link(kind, _, _)) => { - let ignore = matches!(kind, LinkType::Autolink | LinkType::Email); - let mut title = String::new(); - - while let Some((event, range)) = p.next() { - match event { - Event::End(Tag::Link(_, url, _)) => { - // NOTE: links cannot be nested, so we don't need to - // check `kind` - if url.as_ref() == title && !ignore && self.regex.is_match(&url) - { - report_diag( - self.cx, - "unneeded long form for URL", - &url, - range, - ); - } - break; - } - Event::Text(s) if !ignore => title.push_str(&s), - _ => {} - } - } - } - Event::Text(s) => self.find_raw_urls(&s, range, &report_diag), - Event::Start(Tag::CodeBlock(_)) => { - // We don't want to check the text inside the code blocks. - while let Some((event, _)) = p.next() { - match event { - Event::End(Tag::CodeBlock(_)) => break, - _ => {} - } - } - } - _ => {} - } - } - } - - Some(self.fold_item_recur(item)) - } -} diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 2369ff78b1..f5a362bfbe 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -24,7 +24,7 @@ impl DocFolder for CfgPropagator { fn fold_item(&mut self, mut item: Item) -> Option<Item> { let old_parent_cfg = self.parent_cfg.clone(); - let new_cfg = match (self.parent_cfg.take(), item.attrs.cfg.take()) { + let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) { (None, None) => None, (Some(rc), None) | (None, Some(rc)) => Some(rc), (Some(mut a), Some(b)) => { @@ -34,7 +34,7 @@ impl DocFolder for CfgPropagator { } }; self.parent_cfg = new_cfg.clone(); - item.attrs.cfg = new_cfg; + item.cfg = new_cfg; let result = self.fold_item_recur(item); self.parent_cfg = old_parent_cfg; diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index c742d32cb6..54c4ed22f1 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -2,8 +2,8 @@ use rustc_hir::def_id::DefIdSet; use rustc_span::symbol::sym; use std::mem; -use crate::clean::Item; -use crate::clean::{self, AttributesExt, NestedAttributesExt}; +use crate::clean; +use crate::clean::{Item, NestedAttributesExt}; use crate::core::DocContext; use crate::fold::{DocFolder, StripItem}; use crate::passes::{ImplStripper, Pass}; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b6782fb75d..c9071eea78 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -71,14 +71,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> { + let span = krate.item.inner; let mut top_level_module = self.visit_mod_contents( - krate.item.span, - &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }, + span, + &Spanned { span, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, - &krate.item.module, - None, + &krate.item, + self.cx.tcx.crate_name, ); - top_level_module.is_crate = true; // Attach the crate's exported macros to the top-level module. // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by @@ -114,7 +114,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { _ => continue 'exported_macros, }; // Descend into the child module that matches this path segment (if any). - match cur_mod.mods.iter_mut().find(|child| child.name == Some(path_segment_ty_ns)) { + match cur_mod.mods.iter_mut().find(|child| child.name == path_segment_ty_ns) { Some(child_mod) => cur_mod = &mut *child_mod, None => continue 'exported_macros, } @@ -130,10 +130,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn visit_mod_contents( &mut self, span: Span, - vis: &'tcx hir::Visibility<'_>, + vis: &hir::Visibility<'_>, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, - name: Option<Symbol>, + name: Symbol, ) -> Module<'tcx> { let mut om = Module::new(name); om.where_outer = span; @@ -150,7 +150,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om } - /// Tries to resolve the target of a `crate use` statement and inlines the + /// Tries to resolve the target of a `pub use` statement and inlines the /// target if it is defined locally and would not be documented otherwise, /// or when it is specifically requested with `please_inline`. /// (the latter is the case when the import is marked `doc(inline)`) @@ -183,7 +183,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { || use_attrs.lists(sym::doc).has_word(sym::hidden); // For cross-crate impl inlining we need to know whether items are - // reachable in documentation -- a previously nonreachable item can be + // reachable in documentation -- a previously unreachable item can be // made reachable by cross-crate inlining which we're checking here. // (this is done here because we need to know this upfront). if !res_did.is_local() && !is_no_inline { @@ -312,13 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.items.push((item, renamed)) } hir::ItemKind::Mod(ref m) => { - om.mods.push(self.visit_mod_contents( - item.span, - &item.vis, - item.hir_id(), - m, - Some(name), - )); + om.mods.push(self.visit_mod_contents(item.span, &item.vis, item.hir_id(), m, name)); } hir::ItemKind::Fn(..) | hir::ItemKind::ExternCrate(..) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 4e7794fe61..72a4d9a183 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -64,7 +64,7 @@ pub struct Item { pub name: Option<String>, /// The source location of this item (absent if it came from a macro expansion or inline /// assembly). - pub source: Option<Span>, + pub span: Option<Span>, /// By default all documented items are public, but you can tell rustdoc to output private items /// so this field is needed to differentiate. pub visibility: Visibility, @@ -461,7 +461,7 @@ pub struct Impl { #[serde(rename_all = "snake_case")] pub struct Import { /// The full path being imported. - pub span: String, + pub source: String, /// May be different from the last segment of `source` when renaming imports: /// `use source as name;` pub name: String, diff --git a/src/stage0.txt b/src/stage0.txt index 22c2799673..231e66719d 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,14 +12,14 @@ # stable release's version number. `date` is the date where the release we're # bootstrapping off was released. -date: 2021-03-25 -rustc: 1.51.0 +date: 2021-05-06 +rustc: 1.52.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-01-28 +#rustfmt: nightly-2021-03-25 # When making a stable release the process currently looks like: # diff --git a/src/test/assembly/asm/aarch64-modifiers.rs b/src/test/assembly/asm/aarch64-modifiers.rs index 150997ee80..d4a44b1739 100644 --- a/src/test/assembly/asm/aarch64-modifiers.rs +++ b/src/test/assembly/asm/aarch64-modifiers.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: -O // compile-flags: --target aarch64-unknown-linux-gnu diff --git a/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs index 8dd1f3c873..aa25562d32 100644 --- a/src/test/assembly/asm/aarch64-types.rs +++ b/src/test/assembly/asm/aarch64-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target aarch64-unknown-linux-gnu // needs-llvm-components: aarch64 diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs index ad4ab63f26..bb6cc1c987 100644 --- a/src/test/assembly/asm/arm-modifiers.rs +++ b/src/test/assembly/asm/arm-modifiers.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: -O // compile-flags: --target armv7-unknown-linux-gnueabihf diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs index 09901a7a39..b16fde571a 100644 --- a/src/test/assembly/asm/arm-types.rs +++ b/src/test/assembly/asm/arm-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target armv7-unknown-linux-gnueabihf // compile-flags: -C target-feature=+neon diff --git a/src/test/assembly/asm/hexagon-types.rs b/src/test/assembly/asm/hexagon-types.rs index 95135a3e5d..40352cdb4c 100644 --- a/src/test/assembly/asm/hexagon-types.rs +++ b/src/test/assembly/asm/hexagon-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target hexagon-unknown-linux-musl // needs-llvm-components: hexagon diff --git a/src/test/assembly/asm/mips-types.rs b/src/test/assembly/asm/mips-types.rs index 04e840dc16..60cfebdd99 100644 --- a/src/test/assembly/asm/mips-types.rs +++ b/src/test/assembly/asm/mips-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // revisions: mips32 mips64 // assembly-output: emit-asm //[mips32] compile-flags: --target mips-unknown-linux-gnu diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs index 77fd514135..75b6371fb7 100644 --- a/src/test/assembly/asm/nvptx-types.rs +++ b/src/test/assembly/asm/nvptx-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target nvptx64-nvidia-cuda // compile-flags: --crate-type cdylib diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs index 47518cdcf1..1ba73fcac9 100644 --- a/src/test/assembly/asm/riscv-types.rs +++ b/src/test/assembly/asm/riscv-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // revisions: riscv64 riscv32 // assembly-output: emit-asm //[riscv64] compile-flags: --target riscv64imac-unknown-none-elf diff --git a/src/test/assembly/asm/wasm-types.rs b/src/test/assembly/asm/wasm-types.rs index 94ca526222..a071a850c2 100644 --- a/src/test/assembly/asm/wasm-types.rs +++ b/src/test/assembly/asm/wasm-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // assembly-output: emit-asm // compile-flags: --target wasm32-unknown-unknown // compile-flags: --crate-type cdylib diff --git a/src/test/assembly/asm/x86-modifiers.rs b/src/test/assembly/asm/x86-modifiers.rs index e538167cd4..da2dc51d69 100644 --- a/src/test/assembly/asm/x86-modifiers.rs +++ b/src/test/assembly/asm/x86-modifiers.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // revisions: x86_64 i686 // assembly-output: emit-asm // compile-flags: -O diff --git a/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs index f636f1f529..b65b727d22 100644 --- a/src/test/assembly/asm/x86-types.rs +++ b/src/test/assembly/asm/x86-types.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // revisions: x86_64 i686 // assembly-output: emit-asm //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu @@ -748,10 +748,11 @@ check_reg!(eax_f64 f64 "eax" "mov"); // CHECK: #NO_APP check_reg!(eax_ptr ptr "eax" "mov"); -// CHECK-LABEL: ah_byte: -// CHECK: #APP -// CHECK: mov ah, ah -// CHECK: #NO_APP +// i686-LABEL: ah_byte: +// i686: #APP +// i686: mov ah, ah +// i686: #NO_APP +#[cfg(i686)] check_reg!(ah_byte i8 "ah" "mov"); // CHECK-LABEL: xmm0_i32: diff --git a/src/test/assembly/panic-no-unwind-no-uwtable.rs b/src/test/assembly/panic-no-unwind-no-uwtable.rs new file mode 100644 index 0000000000..499d4e6986 --- /dev/null +++ b/src/test/assembly/panic-no-unwind-no-uwtable.rs @@ -0,0 +1,8 @@ +// assembly-output: emit-asm +// only-x86_64-unknown-linux-gnu +// compile-flags: -C panic=unwind -C force-unwind-tables=n -O + +#![crate_type = "lib"] + +// CHECK-NOT: .cfi_startproc +pub fn foo() {} diff --git a/src/test/assembly/panic-unwind-no-uwtable.rs b/src/test/assembly/panic-unwind-no-uwtable.rs new file mode 100644 index 0000000000..8eed72b2fc --- /dev/null +++ b/src/test/assembly/panic-unwind-no-uwtable.rs @@ -0,0 +1,12 @@ +// assembly-output: emit-asm +// only-x86_64-unknown-linux-gnu +// compile-flags: -C panic=unwind -C force-unwind-tables=n + +#![crate_type = "lib"] + +// CHECK-LABEL: foo: +// CHECK: .cfi_startproc +#[no_mangle] +fn foo() { + panic!(); +} diff --git a/src/test/assembly/static-relocation-model.rs b/src/test/assembly/static-relocation-model.rs new file mode 100644 index 0000000000..0463045c15 --- /dev/null +++ b/src/test/assembly/static-relocation-model.rs @@ -0,0 +1,44 @@ +// min-llvm-version: 12.0.0 +// needs-llvm-components: aarch64 x86 +// revisions:X64 A64 +// assembly-output: emit-asm +// [X64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static +// [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type="rlib"] + +#[lang="sized"] +trait Sized {} + +#[lang="copy"] +trait Copy {} + +impl Copy for u8 {} + +extern "C" { + fn chaenomeles(); +} + +// CHECK-LABEL: banana: +// x64: movb chaenomeles, %{{[a,z]+}} +// A64: adrp [[REG:[a-z0-9]+]], chaenomeles +// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles] +#[no_mangle] +pub fn banana() -> u8 { + unsafe { + *(chaenomeles as *mut u8) + } +} + +// CHECK-LABEL: peach: +// x64: movb banana, %{{[a,z]+}} +// A64: adrp [[REG2:[a-z0-9]+]], banana +// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana] +#[no_mangle] +pub fn peach() -> u8 { + unsafe { + *(banana as *mut u8) + } +} diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs index f58117f44d..a3f1fb5e7a 100644 --- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager // compile-flags:-Zinline-in-all-cgus diff --git a/src/test/codegen-units/item-collection/function-as-argument.rs b/src/test/codegen-units/item-collection/function-as-argument.rs index 2329dec385..ea500c3111 100644 --- a/src/test/codegen-units/item-collection/function-as-argument.rs +++ b/src/test/codegen-units/item-collection/function-as-argument.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs index 948098b0cb..25cf5dad61 100644 --- a/src/test/codegen-units/item-collection/generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager // compile-flags:-Zinline-in-all-cgus diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index 919c43738f..e78226d408 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager -Zinline-in-all-cgus -Zmir-opt-level=0 #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/non-generic-closures.rs b/src/test/codegen-units/item-collection/non-generic-closures.rs index affdda3904..379fbcf261 100644 --- a/src/test/codegen-units/item-collection/non-generic-closures.rs +++ b/src/test/codegen-units/item-collection/non-generic-closures.rs @@ -3,7 +3,7 @@ // ignoring this test until MIR codegen has taken over completely // ignore-test -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs index 720421d3e0..06f76f7db3 100644 --- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager // compile-flags:-Zinline-in-all-cgus diff --git a/src/test/codegen-units/item-collection/trait-method-as-argument.rs b/src/test/codegen-units/item-collection/trait-method-as-argument.rs index 6817b33c61..235569728a 100644 --- a/src/test/codegen-units/item-collection/trait-method-as-argument.rs +++ b/src/test/codegen-units/item-collection/trait-method-as-argument.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs index 2ec572b437..8249e7cba9 100644 --- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs +++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager // compile-flags:-Zinline-in-all-cgus diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs index 232570779c..ae3b2e081f 100644 --- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs +++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags:-Zprint-mono-items=eager // compile-flags:-Zinline-in-all-cgus diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs index 6232b9edf8..8b0448ec47 100644 --- a/src/test/codegen-units/partitioning/extern-drop-glue.rs +++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation diff --git a/src/test/codegen-units/partitioning/extern-generic.rs b/src/test/codegen-units/partitioning/extern-generic.rs index 02930f96bd..c96df6e102 100644 --- a/src/test/codegen-units/partitioning/extern-generic.rs +++ b/src/test/codegen-units/partitioning/extern-generic.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/extern-generic -Zshare-generics=y diff --git a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs index 410b77b005..b86e325537 100644 --- a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs +++ b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/inlining-from-extern-crate diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index 3017e4f949..78d69fdb7d 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation // We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing diff --git a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs index a24943348f..d53f7b6229 100644 --- a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs +++ b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining-but-not-all diff --git a/src/test/codegen-units/partitioning/local-inlining.rs b/src/test/codegen-units/partitioning/local-inlining.rs index 0cc652eeb5..1ea804b2f9 100644 --- a/src/test/codegen-units/partitioning/local-inlining.rs +++ b/src/test/codegen-units/partitioning/local-inlining.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining diff --git a/src/test/codegen-units/partitioning/local-transitive-inlining.rs b/src/test/codegen-units/partitioning/local-transitive-inlining.rs index 0c8a67aeb3..56d108074e 100644 --- a/src/test/codegen-units/partitioning/local-transitive-inlining.rs +++ b/src/test/codegen-units/partitioning/local-transitive-inlining.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-transitive-inlining diff --git a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs index 6c55904c1b..e67090303a 100644 --- a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs @@ -3,7 +3,7 @@ // much sense at the moment. // ignore-test -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/methods-are-with-self-type diff --git a/src/test/codegen-units/partitioning/shared-generics.rs b/src/test/codegen-units/partitioning/shared-generics.rs index eb3196439b..17c1fbb2f7 100644 --- a/src/test/codegen-units/partitioning/shared-generics.rs +++ b/src/test/codegen-units/partitioning/shared-generics.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // no-prefer-dynamic // NOTE: We always compile this test with -Copt-level=0 because higher opt-levels // prevent drop-glue from participating in share-generics. diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index 8028c4f5f0..f6ae46b055 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // We specify -C incremental here because we want to test the partitioning for // incremental compilation diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs index 6cb2728359..613b0bf50e 100644 --- a/src/test/codegen/abi-efiapi.rs +++ b/src/test/codegen/abi-efiapi.rs @@ -23,8 +23,8 @@ trait Copy { } //x86_64: define win64cc void @has_efiapi //i686: define void @has_efiapi -//aarch64: define void @has_efiapi -//arm: define void @has_efiapi -//riscv: define void @has_efiapi +//aarch64: define dso_local void @has_efiapi +//arm: define dso_local void @has_efiapi +//riscv: define dso_local void @has_efiapi #[no_mangle] pub extern "efiapi" fn has_efiapi() {} diff --git a/src/test/codegen/abi-repr-ext.rs b/src/test/codegen/abi-repr-ext.rs index f93ccd7941..9dba1718ac 100644 --- a/src/test/codegen/abi-repr-ext.rs +++ b/src/test/codegen/abi-repr-ext.rs @@ -6,7 +6,7 @@ pub enum Type { Type2 = 1 } -// CHECK: define signext i8 @test() +// CHECK: define{{( dso_local)?}} signext i8 @test() #[no_mangle] pub extern "C" fn test() -> Type { Type::Type1 diff --git a/src/test/codegen/abi-sysv64.rs b/src/test/codegen/abi-sysv64.rs index 89c9bcee05..bb910d573b 100644 --- a/src/test/codegen/abi-sysv64.rs +++ b/src/test/codegen/abi-sysv64.rs @@ -1,17 +1,21 @@ // Checks if the correct annotation for the sysv64 ABI is passed to // llvm. Also checks that the abi-sysv64 feature gate allows usage // of the sysv64 abi. - -// ignore-arm -// ignore-aarch64 -// ignore-riscv64 sysv64 not supported - -// compile-flags: -C no-prepopulate-passes +// +// needs-llvm-components: x86 +// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu #![crate_type = "lib"] +#![no_core] +#![feature(abi_x86_interrupt, no_core, lang_items)] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} // CHECK: define x86_64_sysvcc i64 @has_sysv64_abi #[no_mangle] pub extern "sysv64" fn has_sysv64_abi(a: i64) -> i64 { - a * 2 + a } diff --git a/src/test/codegen/abi-x86-interrupt.rs b/src/test/codegen/abi-x86-interrupt.rs index 25c155c949..119004d261 100644 --- a/src/test/codegen/abi-x86-interrupt.rs +++ b/src/test/codegen/abi-x86-interrupt.rs @@ -2,17 +2,20 @@ // llvm. Also checks that the abi_x86_interrupt feature gate allows usage // of the x86-interrupt abi. -// ignore-arm -// ignore-aarch64 -// ignore-riscv64 x86-interrupt is not supported - -// compile-flags: -C no-prepopulate-passes +// needs-llvm-components: x86 +// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu #![crate_type = "lib"] -#![feature(abi_x86_interrupt)] +#![no_core] +#![feature(abi_x86_interrupt, no_core, lang_items)] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} // CHECK: define x86_intrcc i64 @has_x86_interrupt_abi #[no_mangle] pub extern "x86-interrupt" fn has_x86_interrupt_abi(a: i64) -> i64 { - a * 2 + a } diff --git a/src/test/codegen/align-enum.rs b/src/test/codegen/align-enum.rs index 95ca7cfe75..0f2cf5a761 100644 --- a/src/test/codegen/align-enum.rs +++ b/src/test/codegen/align-enum.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -// ignore-tidy-linelength +// #![crate_type = "lib"] diff --git a/src/test/codegen/align-struct.rs b/src/test/codegen/align-struct.rs index cda7235a3d..82eec67af0 100644 --- a/src/test/codegen/align-struct.rs +++ b/src/test/codegen/align-struct.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -// ignore-tidy-linelength +// #![crate_type = "lib"] diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs index c3ffaeb954..5b27f3f454 100644 --- a/src/test/codegen/alloc-optimisation.rs +++ b/src/test/codegen/alloc-optimisation.rs @@ -1,5 +1,5 @@ // -// no-system-llvm +// min-llvm-version: 10.0.1 // compile-flags: -O #![crate_type="lib"] diff --git a/src/test/codegen/asm-target-clobbers.rs b/src/test/codegen/asm-target-clobbers.rs new file mode 100644 index 0000000000..f637cdcd23 --- /dev/null +++ b/src/test/codegen/asm-target-clobbers.rs @@ -0,0 +1,21 @@ +// only-x86_64 +// revisions: base avx512 +// [avx512]compile-flags: -C target-feature=+avx512f + +#![crate_type = "rlib"] +#![feature(asm)] + +// CHECK-LABEL: @avx512_clobber +// base: call void asm sideeffect inteldialect "", "~{xmm31}"() +// avx512: call float asm sideeffect inteldialect "", "=&{xmm31}"() +#[no_mangle] +pub unsafe fn avx512_clobber() { + asm!("", out("zmm31") _, options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @eax_clobber +// CHECK: call i32 asm sideeffect inteldialect "", "=&{ax}"() +#[no_mangle] +pub unsafe fn eax_clobber() { + asm!("", out("eax") _, options(nostack, nomem, preserves_flags)); +} diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index 4e145b81ec..2b8c0dfc22 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -3,7 +3,7 @@ // - The generator types and variants are marked artificial // - Captured vars from the source are not marked artificial // -// ignore-tidy-linelength +// // compile-flags: -C debuginfo=2 --edition=2018 // only-msvc diff --git a/src/test/codegen/async-fn-debug.rs b/src/test/codegen/async-fn-debug.rs index 8fa4be1ae8..e9b774b48c 100644 --- a/src/test/codegen/async-fn-debug.rs +++ b/src/test/codegen/async-fn-debug.rs @@ -3,7 +3,7 @@ // - The generator types and variants are marked artificial // - Captured vars from the source are not marked artificial // -// ignore-tidy-linelength +// // compile-flags: -C debuginfo=2 --edition=2018 // ignore-msvc diff --git a/src/test/codegen/binary-search-index-no-bound-check.rs b/src/test/codegen/binary-search-index-no-bound-check.rs new file mode 100644 index 0000000000..110d1d5562 --- /dev/null +++ b/src/test/codegen/binary-search-index-no-bound-check.rs @@ -0,0 +1,19 @@ +// min-llvm-version: 11.0.0 +// compile-flags: -O +// ignore-debug: the debug assertions get in the way +#![crate_type = "lib"] + +// Make sure no bounds checks are emitted when slicing or indexing +// with an index from `binary_search`. + +// CHECK-LABEL: @binary_search_index_no_bounds_check +#[no_mangle] +pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 { + // CHECK-NOT: panic + // CHECK-NOT: slice_index_len_fail + if let Ok(idx) = s.binary_search(&b'\\') { + s[idx] + } else { + 42 + } +} diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs index 29c8268673..e038ed7045 100644 --- a/src/test/codegen/c-variadic.rs +++ b/src/test/codegen/c-variadic.rs @@ -1,6 +1,6 @@ // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// #![crate_type = "lib"] #![feature(c_variadic)] diff --git a/src/test/codegen/cdylib-external-inline-fns.rs b/src/test/codegen/cdylib-external-inline-fns.rs index 519be6b6a9..9118afd43d 100644 --- a/src/test/codegen/cdylib-external-inline-fns.rs +++ b/src/test/codegen/cdylib-external-inline-fns.rs @@ -2,42 +2,42 @@ #![crate_type = "cdylib"] -// CHECK: define void @a() +// CHECK: define{{( dso_local)?}} void @a() #[no_mangle] #[inline] pub extern "C" fn a() {} -// CHECK: define void @b() +// CHECK: define{{( dso_local)?}} void @b() #[export_name = "b"] #[inline] pub extern "C" fn b() {} -// CHECK: define void @c() +// CHECK: define{{( dso_local)?}} void @c() #[no_mangle] #[inline] extern "C" fn c() {} -// CHECK: define void @d() +// CHECK: define{{( dso_local)?}} void @d() #[export_name = "d"] #[inline] extern "C" fn d() {} -// CHECK: define void @e() +// CHECK: define{{( dso_local)?}} void @e() #[no_mangle] #[inline(always)] pub extern "C" fn e() {} -// CHECK: define void @f() +// CHECK: define{{( dso_local)?}} void @f() #[export_name = "f"] #[inline(always)] pub extern "C" fn f() {} -// CHECK: define void @g() +// CHECK: define{{( dso_local)?}} void @g() #[no_mangle] #[inline(always)] extern "C" fn g() {} -// CHECK: define void @h() +// CHECK: define{{( dso_local)?}} void @h() #[export_name = "h"] #[inline(always)] extern "C" fn h() {} diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs index fcb9002986..3aab4bea3d 100644 --- a/src/test/codegen/consts.rs +++ b/src/test/codegen/consts.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// #![crate_type = "lib"] diff --git a/src/test/codegen/dealloc-no-unwind.rs b/src/test/codegen/dealloc-no-unwind.rs index f047c7a180..3812ef44ff 100644 --- a/src/test/codegen/dealloc-no-unwind.rs +++ b/src/test/codegen/dealloc-no-unwind.rs @@ -1,4 +1,3 @@ -// // no-system-llvm // compile-flags: -O @@ -15,7 +14,7 @@ impl Drop for A { #[no_mangle] pub fn a(a: Box<i32>) { - // CHECK-LABEL: define void @a + // CHECK-LABEL: define{{.*}}void @a // CHECK: call void @__rust_dealloc // CHECK-NEXT: call void @foo let _a = A; diff --git a/src/test/codegen/debug-compile-unit-path.rs b/src/test/codegen/debug-compile-unit-path.rs index fcb66e0857..3661be046d 100644 --- a/src/test/codegen/debug-compile-unit-path.rs +++ b/src/test/codegen/debug-compile-unit-path.rs @@ -1,5 +1,5 @@ // compile-flags: -g --remap-path-prefix={{cwd}}=/cwd/ --remap-path-prefix={{src-base}}=/base/ -// ignore-tidy-linelength +// // // Ensure that we remap the compile unit directory and that we set it to the compilers current // working directory and not something else. diff --git a/src/test/codegen/default-requires-uwtable.rs b/src/test/codegen/default-requires-uwtable.rs new file mode 100644 index 0000000000..d4c4200c5d --- /dev/null +++ b/src/test/codegen/default-requires-uwtable.rs @@ -0,0 +1,15 @@ +// revisions: WINDOWS ANDROID +// needs-llvm-components: x86 arm +// compile-flags: -C panic=abort +// [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc +// [ANDROID] compile-flags: --target=armv7-linux-androideabi + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +// CHECK: attributes #{{.*}} uwtable +pub fn foo() {} diff --git a/src/test/codegen/enum-debug-clike.rs b/src/test/codegen/enum-debug-clike.rs index 134443931e..1e369a2c4e 100644 --- a/src/test/codegen/enum-debug-clike.rs +++ b/src/test/codegen/enum-debug-clike.rs @@ -1,7 +1,7 @@ // This tests that debug info for "c-like" enums is properly emitted. // This is ignored for the fallback mode on MSVC due to problems with PDB. -// ignore-tidy-linelength +// // ignore-msvc // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/enum-debug-niche-2.rs b/src/test/codegen/enum-debug-niche-2.rs index 0f78234d97..9c72ad9d24 100644 --- a/src/test/codegen/enum-debug-niche-2.rs +++ b/src/test/codegen/enum-debug-niche-2.rs @@ -1,7 +1,7 @@ // This tests that optimized enum debug info accurately reflects the enum layout. // This is ignored for the fallback mode on MSVC due to problems with PDB. -// ignore-tidy-linelength +// // ignore-msvc // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/external-no-mangle-fns.rs b/src/test/codegen/external-no-mangle-fns.rs index 41820b057f..70349b2ec4 100644 --- a/src/test/codegen/external-no-mangle-fns.rs +++ b/src/test/codegen/external-no-mangle-fns.rs @@ -4,30 +4,30 @@ #![crate_type = "lib"] #![no_std] -// CHECK: define void @a() +// CHECK: define{{( dso_local)?}} void @a() #[no_mangle] fn a() {} -// CHECK: define void @b() +// CHECK: define{{( dso_local)?}} void @b() #[no_mangle] pub fn b() {} mod private { - // CHECK: define void @c() + // CHECK: define{{( dso_local)?}} void @c() #[no_mangle] fn c() {} - // CHECK: define void @d() + // CHECK: define{{( dso_local)?}} void @d() #[no_mangle] pub fn d() {} } const HIDDEN: () = { - // CHECK: define void @e() + // CHECK: define{{( dso_local)?}} void @e() #[no_mangle] fn e() {} - // CHECK: define void @f() + // CHECK: define{{( dso_local)?}} void @f() #[no_mangle] pub fn f() {} }; @@ -38,13 +38,13 @@ const HIDDEN: () = { // CHECK-NEXT: define internal #[inline(never)] fn x() { - // CHECK: define void @g() + // CHECK: define{{( dso_local)?}} void @g() #[no_mangle] fn g() { x(); } - // CHECK: define void @h() + // CHECK: define{{( dso_local)?}} void @h() #[no_mangle] pub fn h() {} @@ -54,22 +54,22 @@ fn x() { } } -// CHECK: define void @i() +// CHECK: define{{( dso_local)?}} void @i() #[no_mangle] #[inline] fn i() {} -// CHECK: define void @j() +// CHECK: define{{( dso_local)?}} void @j() #[no_mangle] #[inline] pub fn j() {} -// CHECK: define void @k() +// CHECK: define{{( dso_local)?}} void @k() #[no_mangle] #[inline(always)] fn k() {} -// CHECK: define void @l() +// CHECK: define{{( dso_local)?}} void @l() #[no_mangle] #[inline(always)] pub fn l() {} diff --git a/src/test/codegen/fewer-names.rs b/src/test/codegen/fewer-names.rs index 53a926d49e..7307e0379d 100644 --- a/src/test/codegen/fewer-names.rs +++ b/src/test/codegen/fewer-names.rs @@ -7,11 +7,11 @@ #[no_mangle] pub fn sum(x: u32, y: u32) -> u32 { -// YES-LABEL: define i32 @sum(i32 %0, i32 %1) +// YES-LABEL: define{{.*}}i32 @sum(i32 %0, i32 %1) // YES-NEXT: %3 = add i32 %1, %0 // YES-NEXT: ret i32 %3 -// NO-LABEL: define i32 @sum(i32 %x, i32 %y) +// NO-LABEL: define{{.*}}i32 @sum(i32 %x, i32 %y) // NO-NEXT: start: // NO-NEXT: %z = add i32 %y, %x // NO-NEXT: ret i32 %z diff --git a/src/test/codegen/ffi-const.rs b/src/test/codegen/ffi-const.rs index 67baf6fdd3..d9cfa5429b 100644 --- a/src/test/codegen/ffi-const.rs +++ b/src/test/codegen/ffi-const.rs @@ -5,7 +5,7 @@ pub fn bar() { unsafe { foo() } } extern "C" { - // CHECK-LABEL: declare void @foo() + // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readnone{{.*}} } #[ffi_const] pub fn foo(); diff --git a/src/test/codegen/ffi-pure.rs b/src/test/codegen/ffi-pure.rs index 3afb0856c9..5bdb2ee912 100644 --- a/src/test/codegen/ffi-pure.rs +++ b/src/test/codegen/ffi-pure.rs @@ -5,7 +5,7 @@ pub fn bar() { unsafe { foo() } } extern "C" { - // CHECK-LABEL: declare void @foo() + // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readonly{{.*}} } #[ffi_pure] pub fn foo(); diff --git a/src/test/codegen/ffi-returns-twice.rs b/src/test/codegen/ffi-returns-twice.rs index 75301dfd34..0fbe03f0bb 100644 --- a/src/test/codegen/ffi-returns-twice.rs +++ b/src/test/codegen/ffi-returns-twice.rs @@ -5,8 +5,7 @@ pub fn bar() { unsafe { foo() } } extern "C" { - // CHECK-LABEL: declare void @foo() - // CHECK-SAME: [[ATTRS:#[0-9]+]] - // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} } + // CHECK: declare{{( dso_local)?}} void @foo(){{.*}}[[ATTRS:#[0-9]+]] + // CHECK: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} } #[ffi_returns_twice] pub fn foo(); } diff --git a/src/test/codegen/force-no-unwind-tables.rs b/src/test/codegen/force-no-unwind-tables.rs new file mode 100644 index 0000000000..3ee23f05eb --- /dev/null +++ b/src/test/codegen/force-no-unwind-tables.rs @@ -0,0 +1,11 @@ +// compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n +// ignore-windows + +#![crate_type="lib"] + +// CHECK-LABEL: define{{.*}}void @foo +// CHECK-NOT: attributes #{{.*}} uwtable +#[no_mangle] +fn foo() { + panic!(); +} diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index a1da4faf5d..7a8646c71b 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -1,5 +1,5 @@ -// compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// compile-flags: -O -C no-prepopulate-passes +// // min-system-llvm-version: 12.0 #![crate_type = "lib"] diff --git a/src/test/codegen/gdb_debug_script_load.rs b/src/test/codegen/gdb_debug_script_load.rs index 178269f611..856b67bf9d 100644 --- a/src/test/codegen/gdb_debug_script_load.rs +++ b/src/test/codegen/gdb_debug_script_load.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // ignore-windows // ignore-macos // ignore-wasm diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 82a1568ea9..4f8a320ee9 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -3,7 +3,7 @@ // - The generator types and variants are marked artificial // - Captured vars from the source are not marked artificial // -// ignore-tidy-linelength +// // compile-flags: -C debuginfo=2 // only-msvc diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 5c7c641481..86ac6db702 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -3,7 +3,7 @@ // - The generator types and variants are marked artificial // - Captured vars from the source are not marked artificial // -// ignore-tidy-linelength +// // compile-flags: -C debuginfo=2 --edition=2018 // ignore-msvc diff --git a/src/test/codegen/inline-debuginfo.rs b/src/test/codegen/inline-debuginfo.rs index 1546dfa10a..5b230361f3 100644 --- a/src/test/codegen/inline-debuginfo.rs +++ b/src/test/codegen/inline-debuginfo.rs @@ -1,6 +1,6 @@ #![crate_type="rlib"] // compile-flags: -Copt-level=3 -g -// ignore-tidy-linelength +// #[no_mangle] #[inline(always)] diff --git a/src/test/codegen/instrument-mcount.rs b/src/test/codegen/instrument-mcount.rs index 518a2a0da2..b26076e7a7 100644 --- a/src/test/codegen/instrument-mcount.rs +++ b/src/test/codegen/instrument-mcount.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -Z instrument-mcount #![crate_type = "lib"] diff --git a/src/test/codegen/intrinsics/nontemporal.rs b/src/test/codegen/intrinsics/nontemporal.rs index 3a41fb4fab..d13f3e51ba 100644 --- a/src/test/codegen/intrinsics/nontemporal.rs +++ b/src/test/codegen/intrinsics/nontemporal.rs @@ -5,7 +5,7 @@ #[no_mangle] pub fn a(a: &mut u32, b: u32) { - // CHECK-LABEL: define void @a + // CHECK-LABEL: define{{.*}}void @a // CHECK: store i32 %b, i32* %a, align 4, !nontemporal unsafe { std::intrinsics::nontemporal_store(a, b); diff --git a/src/test/codegen/issue-32031.rs b/src/test/codegen/issue-32031.rs index cf672266bc..82ba325572 100644 --- a/src/test/codegen/issue-32031.rs +++ b/src/test/codegen/issue-32031.rs @@ -5,7 +5,7 @@ #[no_mangle] pub struct F32(f32); -// CHECK: define float @add_newtype_f32(float %a, float %b) +// CHECK: define{{.*}}float @add_newtype_f32(float %a, float %b) #[inline(never)] #[no_mangle] pub fn add_newtype_f32(a: F32, b: F32) -> F32 { @@ -15,7 +15,7 @@ pub fn add_newtype_f32(a: F32, b: F32) -> F32 { #[no_mangle] pub struct F64(f64); -// CHECK: define double @add_newtype_f64(double %a, double %b) +// CHECK: define{{.*}}double @add_newtype_f64(double %a, double %b) #[inline(never)] #[no_mangle] pub fn add_newtype_f64(a: F64, b: F64) -> F64 { diff --git a/src/test/codegen/issue-44056-macos-tls-align.rs b/src/test/codegen/issue-44056-macos-tls-align.rs index 2270eca501..1a3923f1bb 100644 --- a/src/test/codegen/issue-44056-macos-tls-align.rs +++ b/src/test/codegen/issue-44056-macos-tls-align.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // only-macos // no-system-llvm // compile-flags: -O diff --git a/src/test/codegen/issue-73338-effecient-cmp.rs b/src/test/codegen/issue-73338-effecient-cmp.rs new file mode 100644 index 0000000000..85c2bbfd04 --- /dev/null +++ b/src/test/codegen/issue-73338-effecient-cmp.rs @@ -0,0 +1,39 @@ +// This test checks that comparison operation +// generated by #[derive(PartialOrd)] +// doesn't contain jumps for C enums + +// compile-flags: -Copt-level=3 + +#![crate_type="lib"] + +#[repr(u32)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd)] +pub enum Foo { + Zero, + One, + Two, +} + +#[no_mangle] +pub fn compare_less(a: Foo, b: Foo)->bool{ + // CHECK-NOT: br {{.*}} + a < b +} + +#[no_mangle] +pub fn compare_le(a: Foo, b: Foo)->bool{ + // CHECK-NOT: br {{.*}} + a <= b +} + +#[no_mangle] +pub fn compare_ge(a: Foo, b: Foo)->bool{ + // CHECK-NOT: br {{.*}} + a >= b +} + +#[no_mangle] +pub fn compare_greater(a: Foo, b: Foo)->bool{ + // CHECK-NOT: br {{.*}} + a > b +} diff --git a/src/test/codegen/issue-83623-SIMD-PartialEq.rs b/src/test/codegen/issue-83623-SIMD-PartialEq.rs new file mode 100644 index 0000000000..b22b7f5240 --- /dev/null +++ b/src/test/codegen/issue-83623-SIMD-PartialEq.rs @@ -0,0 +1,46 @@ +// This test checks that jumps generated by logical operators can be optimized away + +// compile-flags: -Copt-level=3 +// only-64bit + +#![crate_type="lib"] + +pub struct Blueprint { + pub fuel_tank_size: u32, + pub payload: u32, + pub wheel_diameter: u32, + pub wheel_width: u32, + pub storage: u32, +} + +// && chains should not prevent SIMD optimizations for primitives +impl PartialEq for Blueprint{ + fn eq(&self, other: &Self)->bool{ + // CHECK-NOT: call{{.*}}bcmp + // CHECK-NOT: call{{.*}}memcmp + // CHECK-NOT: br {{.*}} + self.fuel_tank_size == other.fuel_tank_size + && self.payload == other.payload + && self.wheel_diameter == other.wheel_diameter + && self.wheel_width == other.wheel_width + && self.storage == other.storage + } +} + +#[derive(PartialEq)] +pub struct Blueprint2 { + pub fuel_tank_size: u32, + pub payload: u32, + pub wheel_diameter: u32, + pub wheel_width: u32, + pub storage: u32, +} + +// Derived PartialEq should not generate jumps and should use SIMD +#[no_mangle] +pub fn partial_eq_should_not_jump(a: &Blueprint2, b:&Blueprint2)->bool{ + // CHECK-NOT: call{{.*}}bcmp + // CHECK-NOT: call{{.*}}memcmp + // CHECK-NOT: br {{.*}} + a==b +} diff --git a/src/test/codegen/issue-84268.rs b/src/test/codegen/issue-84268.rs new file mode 100644 index 0000000000..7ca1954470 --- /dev/null +++ b/src/test/codegen/issue-84268.rs @@ -0,0 +1,23 @@ +// compile-flags: -O --crate-type=rlib +#![feature(platform_intrinsics, repr_simd)] + +extern "platform-intrinsic" { + fn simd_fabs<T>(x: T) -> T; + fn simd_eq<T, U>(x: T, y: T) -> U; +} + +#[repr(simd)] +pub struct V([f32; 4]); + +#[repr(simd)] +pub struct M([i32; 4]); + +#[no_mangle] +// CHECK-LABEL: @is_infinite +pub fn is_infinite(v: V) -> M { + // CHECK: fabs + // CHECK: cmp oeq + unsafe { + simd_eq(simd_fabs(v), V([f32::INFINITY; 4])) + } +} diff --git a/src/test/codegen/lto-removes-invokes.rs b/src/test/codegen/lto-removes-invokes.rs index b8f9f36c8e..3979a97dc0 100644 --- a/src/test/codegen/lto-removes-invokes.rs +++ b/src/test/codegen/lto-removes-invokes.rs @@ -10,7 +10,7 @@ fn main() { fn foo() { let _a = Box::new(3); bar(); -// CHECK-LABEL: define void @foo +// CHECK-LABEL: define dso_local void @foo // CHECK: call void @bar } diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs index 43a6be465b..c8cd692328 100644 --- a/src/test/codegen/naked-functions.rs +++ b/src/test/codegen/naked-functions.rs @@ -4,7 +4,7 @@ #![feature(naked_functions)] // CHECK: Function Attrs: naked -// CHECK-NEXT: define void @naked_empty() +// CHECK-NEXT: define{{.*}}void @naked_empty() #[no_mangle] #[naked] pub fn naked_empty() { @@ -15,14 +15,14 @@ pub fn naked_empty() { // CHECK: Function Attrs: naked #[no_mangle] #[naked] -// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %a)?}}) +// CHECK-NEXT: define{{.*}}void @naked_with_args(i{{[0-9]+( %a)?}}) pub fn naked_with_args(a: isize) { // CHECK-NEXT: {{.+}}: // CHECK: ret void } // CHECK: Function Attrs: naked -// CHECK-NEXT: define i{{[0-9]+}} @naked_with_return() +// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_return() #[no_mangle] #[naked] pub fn naked_with_return() -> isize { @@ -32,7 +32,7 @@ pub fn naked_with_return() -> isize { } // CHECK: Function Attrs: naked -// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}}) +// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}}) #[no_mangle] #[naked] pub fn naked_with_args_and_return(a: isize) -> isize { diff --git a/src/test/codegen/noalias-unpin.rs b/src/test/codegen/noalias-unpin.rs new file mode 100644 index 0000000000..8ca9b98eee --- /dev/null +++ b/src/test/codegen/noalias-unpin.rs @@ -0,0 +1,15 @@ +// compile-flags: -O -Z mutable-noalias=yes + +#![crate_type = "lib"] + +pub struct SelfRef { + self_ref: *mut SelfRef, + _pin: std::marker::PhantomPinned +} + +// CHECK-LABEL: @test_self_ref( +// CHECK-NOT: noalias +#[no_mangle] +pub unsafe fn test_self_ref(s: &mut SelfRef) { + (*s.self_ref).self_ref = std::ptr::null_mut(); +} diff --git a/src/test/codegen/optimize-attr-1.rs b/src/test/codegen/optimize-attr-1.rs index a8be10ba3c..22abe06e7a 100644 --- a/src/test/codegen/optimize-attr-1.rs +++ b/src/test/codegen/optimize-attr-1.rs @@ -6,7 +6,7 @@ #![feature(optimize_attribute)] #![crate_type="rlib"] -// CHECK-LABEL: define i32 @nothing +// CHECK-LABEL: define{{.*}}i32 @nothing // CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]] // NO-OPT: ret i32 4 // SIZE-OPT: ret i32 4 @@ -16,7 +16,7 @@ pub fn nothing() -> i32 { 2 + 2 } -// CHECK-LABEL: define i32 @size +// CHECK-LABEL: define{{.*}}i32 @size // CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]] // NO-OPT: ret i32 6 // SIZE-OPT: ret i32 6 @@ -27,7 +27,7 @@ pub fn size() -> i32 { 3 + 3 } -// CHECK-LABEL: define i32 @speed +// CHECK-LABEL: define{{.*}}i32 @speed // NO-OPT-SAME: [[NOTHING_ATTRS]] // SPEED-OPT-SAME: [[NOTHING_ATTRS]] // SIZE-OPT-SAME: [[SPEED_ATTRS:#[0-9]+]] diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index c31e8457dc..dfa7803d4f 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -1,5 +1,5 @@ -// ignore-tidy-linelength -// compile-flags: -C no-prepopulate-passes +// +// compile-flags: -O -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/panic-unwind-default-uwtable.rs b/src/test/codegen/panic-unwind-default-uwtable.rs new file mode 100644 index 0000000000..4c85008cf3 --- /dev/null +++ b/src/test/codegen/panic-unwind-default-uwtable.rs @@ -0,0 +1,6 @@ +// compile-flags: -C panic=unwind -C no-prepopulate-passes + +#![crate_type = "lib"] + +// CHECK: attributes #{{.*}} uwtable +pub fn foo() {} diff --git a/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs b/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs index b87a20e75f..887915955b 100644 --- a/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs +++ b/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -g --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src diff --git a/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs index 57e877ef0d..59092dbf63 100644 --- a/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs +++ b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -g --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src #![crate_type = "lib"] diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs index 20475bab0f..c2d01c7fec 100644 --- a/src/test/codegen/remap_path_prefix/main.rs +++ b/src/test/codegen/remap_path_prefix/main.rs @@ -1,5 +1,5 @@ // ignore-windows -// ignore-tidy-linelength +// // compile-flags: -g -C no-prepopulate-passes --remap-path-prefix={{cwd}}=/the/cwd --remap-path-prefix={{src-base}}=/the/src // aux-build:remap_path_prefix_aux.rs diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index 8e08b78ad1..9e904fc82a 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -1,5 +1,5 @@ // compile-flags: -O -// ignore-tidy-linelength +// #![crate_type = "lib"] diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs index 847b94fac7..3017adb443 100644 --- a/src/test/codegen/repr-transparent-aggregates-1.rs +++ b/src/test/codegen/repr-transparent-aggregates-1.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// // min-system-llvm-version: 12.0 // ignore-arm @@ -34,19 +34,19 @@ pub enum TeBigS { Variant(BigS), } -// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], %BigS* [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]]) +// CHECK: define{{.*}}void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], %BigS* [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]]) #[no_mangle] pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} } -// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], %TsBigS* [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]]) +// CHECK: define{{.*}}void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], %TsBigS* [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]]) #[no_mangle] pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } -// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], %TuBigS* [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]]) +// CHECK: define{{.*}}void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], %TuBigS* [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]]) #[no_mangle] pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } -// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], %"TeBigS::Variant"* [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]]) +// CHECK: define{{.*}}void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], %"TeBigS::Variant"* [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]]) #[no_mangle] pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } @@ -70,18 +70,18 @@ pub enum TeBigU { Variant(BigU), } -// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], %BigU* [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]]) +// CHECK: define{{.*}}void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], %BigU* [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]]) #[no_mangle] pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} } -// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], %TsBigU* [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]]) +// CHECK: define{{.*}}void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], %TsBigU* [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]]) #[no_mangle] pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } -// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], %TuBigU* [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]]) +// CHECK: define{{.*}}void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], %TuBigU* [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]]) #[no_mangle] pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } -// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], %"TeBigU::Variant"* [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]]) +// CHECK: define{{.*}}void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], %"TeBigU::Variant"* [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]]) #[no_mangle] pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs index 1fb12d92bd..429d760b4a 100644 --- a/src/test/codegen/repr-transparent-aggregates-2.rs +++ b/src/test/codegen/repr-transparent-aggregates-2.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// // min-system-llvm-version: 12.0 // ignore-aarch64 diff --git a/src/test/codegen/repr-transparent-aggregates-3.rs b/src/test/codegen/repr-transparent-aggregates-3.rs index 3381764bfc..21176ac0e7 100644 --- a/src/test/codegen/repr-transparent-aggregates-3.rs +++ b/src/test/codegen/repr-transparent-aggregates-3.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// // min-system-llvm-version: 12.0 // only-mips64 diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs index 2999731351..7add522c15 100644 --- a/src/test/codegen/repr-transparent.rs +++ b/src/test/codegen/repr-transparent.rs @@ -17,21 +17,21 @@ pub struct Zst2(()); #[repr(transparent)] pub struct F32(f32); -// CHECK: define float @test_F32(float %_1) +// CHECK: define{{.*}}float @test_F32(float %_1) #[no_mangle] pub extern "C" fn test_F32(_: F32) -> F32 { loop {} } #[repr(transparent)] pub struct Ptr(*mut u8); -// CHECK: define i8* @test_Ptr(i8* %_1) +// CHECK: define{{.*}}i8* @test_Ptr(i8* %_1) #[no_mangle] pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} } #[repr(transparent)] pub struct WithZst(u64, Zst1); -// CHECK: define i64 @test_WithZst(i64 %_1) +// CHECK: define{{.*}}i64 @test_WithZst(i64 %_1) #[no_mangle] pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} } @@ -39,14 +39,14 @@ pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} } pub struct WithZeroSizedArray(*const f32, [i8; 0]); // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever. -// CHECK: define i32* @test_WithZeroSizedArray(i32* %_1) +// CHECK: define{{.*}}i32* @test_WithZeroSizedArray(i32* %_1) #[no_mangle] pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} } #[repr(transparent)] pub struct Generic<T>(T); -// CHECK: define double @test_Generic(double %_1) +// CHECK: define{{.*}}double @test_Generic(double %_1) #[no_mangle] pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} } @@ -56,14 +56,14 @@ pub struct GenericPlusZst<T>(T, Zst2); #[repr(u8)] pub enum Bool { True, False, FileNotFound } -// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1) +// CHECK: define{{( dso_local)?}}{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1) #[no_mangle] pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} } #[repr(transparent)] pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>); -// CHECK: define i16* @test_LifetimePhantom(i16* %_1) +// CHECK: define{{.*}}i16* @test_LifetimePhantom(i16* %_1) #[no_mangle] pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} } @@ -73,28 +73,28 @@ pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> } pub struct Px; -// CHECK: define float @test_UnitPhantom(float %_1) +// CHECK: define{{.*}}float @test_UnitPhantom(float %_1) #[no_mangle] pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} } #[repr(transparent)] pub struct TwoZsts(Zst1, i8, Zst2); -// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1) +// CHECK: define{{( dso_local)?}}{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1) #[no_mangle] pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} } #[repr(transparent)] pub struct Nested1(Zst2, Generic<f64>); -// CHECK: define double @test_Nested1(double %_1) +// CHECK: define{{.*}}double @test_Nested1(double %_1) #[no_mangle] pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} } #[repr(transparent)] pub struct Nested2(Nested1, Zst1); -// CHECK: define double @test_Nested2(double %_1) +// CHECK: define{{.*}}double @test_Nested2(double %_1) #[no_mangle] pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} } @@ -104,7 +104,7 @@ struct f32x4(f32, f32, f32, f32); #[repr(transparent)] pub struct Vector(f32x4); -// CHECK: define <4 x float> @test_Vector(<4 x float> %_1) +// CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1) #[no_mangle] pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} } @@ -114,7 +114,7 @@ impl<T: ?Sized> Mirror for T { type It = Self; } #[repr(transparent)] pub struct StructWithProjection(<f32 as Mirror>::It); -// CHECK: define float @test_Projection(float %_1) +// CHECK: define{{.*}}float @test_Projection(float %_1) #[no_mangle] pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } @@ -123,7 +123,7 @@ pub enum EnumF32 { Variant(F32) } -// CHECK: define float @test_EnumF32(float %_1) +// CHECK: define{{.*}}float @test_EnumF32(float %_1) #[no_mangle] pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} } @@ -132,7 +132,7 @@ pub enum EnumF32WithZsts { Variant(Zst1, F32, Zst2) } -// CHECK: define float @test_EnumF32WithZsts(float %_1) +// CHECK: define{{.*}}float @test_EnumF32WithZsts(float %_1) #[no_mangle] pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} } @@ -141,7 +141,7 @@ pub union UnionF32 { field: F32, } -// CHECK: define float @test_UnionF32(float %_1) +// CHECK: define{{.*}}float @test_UnionF32(float %_1) #[no_mangle] pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } @@ -152,7 +152,7 @@ pub union UnionF32WithZsts { zst2: Zst2, } -// CHECK: define float @test_UnionF32WithZsts(float %_1) +// CHECK: define{{.*}}float @test_UnionF32WithZsts(float %_1) #[no_mangle] pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} } diff --git a/src/test/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/src/test/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs index 180ba07764..693f0d99c4 100644 --- a/src/test/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs +++ b/src/test/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes // only-riscv64 // only-linux diff --git a/src/test/codegen/riscv-abi/riscv64-lp64d-abi.rs b/src/test/codegen/riscv-abi/riscv64-lp64d-abi.rs index 0b6e1878d4..1555acadfb 100644 --- a/src/test/codegen/riscv-abi/riscv64-lp64d-abi.rs +++ b/src/test/codegen/riscv-abi/riscv64-lp64d-abi.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes // only-riscv64 // only-linux diff --git a/src/test/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs b/src/test/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs index 1cea6e3db2..f08fabed42 100644 --- a/src/test/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs +++ b/src/test/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes // only-riscv64 // only-linux diff --git a/src/test/codegen/sanitizer-recover.rs b/src/test/codegen/sanitizer-recover.rs index 433d32abd3..7ce0fa0a20 100644 --- a/src/test/codegen/sanitizer-recover.rs +++ b/src/test/codegen/sanitizer-recover.rs @@ -16,27 +16,27 @@ // MSAN-RECOVER: @__msan_keep_going = weak_odr {{.*}}constant i32 1 // MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}}constant i32 1 -// ASAN-LABEL: define i32 @penguin( +// ASAN-LABEL: define dso_local i32 @penguin( // ASAN: call void @__asan_report_load4(i64 %0) // ASAN: unreachable // ASAN: } // -// ASAN-RECOVER-LABEL: define i32 @penguin( +// ASAN-RECOVER-LABEL: define dso_local i32 @penguin( // ASAN-RECOVER: call void @__asan_report_load4_noabort( // ASAN-RECOVER-NOT: unreachable // ASAN: } // -// MSAN-LABEL: define i32 @penguin( +// MSAN-LABEL: define dso_local i32 @penguin( // MSAN: call void @__msan_warning{{(_with_origin_noreturn\(i32 0\)|_noreturn\(\))}} // MSAN: unreachable // MSAN: } // -// MSAN-RECOVER-LABEL: define i32 @penguin( +// MSAN-RECOVER-LABEL: define dso_local i32 @penguin( // MSAN-RECOVER: call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}} // MSAN-RECOVER-NOT: unreachable // MSAN-RECOVER: } // -// MSAN-RECOVER-LTO-LABEL: define i32 @penguin( +// MSAN-RECOVER-LTO-LABEL: define dso_local i32 @penguin( // MSAN-RECOVER-LTO: call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}} // MSAN-RECOVER-LTO-NOT: unreachable // MSAN-RECOVER-LTO: } diff --git a/src/test/codegen/scalar-pair-bool.rs b/src/test/codegen/scalar-pair-bool.rs index 4704c8ad79..473272158d 100644 --- a/src/test/codegen/scalar-pair-bool.rs +++ b/src/test/codegen/scalar-pair-bool.rs @@ -2,25 +2,25 @@ #![crate_type = "lib"] -// CHECK: define { i8, i8 } @pair_bool_bool(i1 zeroext %pair.0, i1 zeroext %pair.1) +// CHECK: define{{.*}}{ i8, i8 } @pair_bool_bool(i1 zeroext %pair.0, i1 zeroext %pair.1) #[no_mangle] pub fn pair_bool_bool(pair: (bool, bool)) -> (bool, bool) { pair } -// CHECK: define { i8, i32 } @pair_bool_i32(i1 zeroext %pair.0, i32 %pair.1) +// CHECK: define{{.*}}{ i8, i32 } @pair_bool_i32(i1 zeroext %pair.0, i32 %pair.1) #[no_mangle] pub fn pair_bool_i32(pair: (bool, i32)) -> (bool, i32) { pair } -// CHECK: define { i32, i8 } @pair_i32_bool(i32 %pair.0, i1 zeroext %pair.1) +// CHECK: define{{.*}}{ i32, i8 } @pair_i32_bool(i32 %pair.0, i1 zeroext %pair.1) #[no_mangle] pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) { pair } -// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1) +// CHECK: define{{.*}}{ i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1) #[no_mangle] pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) { // Make sure it can operate directly on the unpacked args @@ -30,7 +30,7 @@ pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) { (a && b, a || b) } -// CHECK: define void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1) +// CHECK: define{{.*}}void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1) #[no_mangle] pub fn pair_branches((a, b): (bool, bool)) { // Make sure it can branch directly on the unpacked bool args diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs index 0a687078cd..e7bb2327a6 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @fabs_32x2 #[no_mangle] pub unsafe fn fabs_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.fabs.v2f32 + // CHECK: call <2 x float> @llvm.fabs.v2f32 simd_fabs(a) } // CHECK-LABEL: @fabs_32x4 #[no_mangle] pub unsafe fn fabs_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.fabs.v4f32 + // CHECK: call <4 x float> @llvm.fabs.v4f32 simd_fabs(a) } // CHECK-LABEL: @fabs_32x8 #[no_mangle] pub unsafe fn fabs_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.fabs.v8f32 + // CHECK: call <8 x float> @llvm.fabs.v8f32 simd_fabs(a) } // CHECK-LABEL: @fabs_32x16 #[no_mangle] pub unsafe fn fabs_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.fabs.v16f32 + // CHECK: call <16 x float> @llvm.fabs.v16f32 simd_fabs(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @fabs_64x4 #[no_mangle] pub unsafe fn fabs_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.fabs.v4f64 + // CHECK: call <4 x double> @llvm.fabs.v4f64 simd_fabs(a) } // CHECK-LABEL: @fabs_64x2 #[no_mangle] pub unsafe fn fabs_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.fabs.v2f64 + // CHECK: call <2 x double> @llvm.fabs.v2f64 simd_fabs(a) } // CHECK-LABEL: @fabs_64x8 #[no_mangle] pub unsafe fn fabs_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.fabs.v8f64 + // CHECK: call <8 x double> @llvm.fabs.v8f64 simd_fabs(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs index 9d47339d16..e33482d755 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @ceil_32x2 #[no_mangle] pub unsafe fn ceil_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.ceil.v2f32 + // CHECK: call <2 x float> @llvm.ceil.v2f32 simd_ceil(a) } // CHECK-LABEL: @ceil_32x4 #[no_mangle] pub unsafe fn ceil_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.ceil.v4f32 + // CHECK: call <4 x float> @llvm.ceil.v4f32 simd_ceil(a) } // CHECK-LABEL: @ceil_32x8 #[no_mangle] pub unsafe fn ceil_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.ceil.v8f32 + // CHECK: call <8 x float> @llvm.ceil.v8f32 simd_ceil(a) } // CHECK-LABEL: @ceil_32x16 #[no_mangle] pub unsafe fn ceil_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.ceil.v16f32 + // CHECK: call <16 x float> @llvm.ceil.v16f32 simd_ceil(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @ceil_64x4 #[no_mangle] pub unsafe fn ceil_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.ceil.v4f64 + // CHECK: call <4 x double> @llvm.ceil.v4f64 simd_ceil(a) } // CHECK-LABEL: @ceil_64x2 #[no_mangle] pub unsafe fn ceil_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.ceil.v2f64 + // CHECK: call <2 x double> @llvm.ceil.v2f64 simd_ceil(a) } // CHECK-LABEL: @ceil_64x8 #[no_mangle] pub unsafe fn ceil_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.ceil.v8f64 + // CHECK: call <8 x double> @llvm.ceil.v8f64 simd_ceil(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs index 770b2a7303..0f52952bc0 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @fcos_32x2 #[no_mangle] pub unsafe fn fcos_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.cos.v2f32 + // CHECK: call <2 x float> @llvm.cos.v2f32 simd_fcos(a) } // CHECK-LABEL: @fcos_32x4 #[no_mangle] pub unsafe fn fcos_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.cos.v4f32 + // CHECK: call <4 x float> @llvm.cos.v4f32 simd_fcos(a) } // CHECK-LABEL: @fcos_32x8 #[no_mangle] pub unsafe fn fcos_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.cos.v8f32 + // CHECK: call <8 x float> @llvm.cos.v8f32 simd_fcos(a) } // CHECK-LABEL: @fcos_32x16 #[no_mangle] pub unsafe fn fcos_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.cos.v16f32 + // CHECK: call <16 x float> @llvm.cos.v16f32 simd_fcos(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @fcos_64x4 #[no_mangle] pub unsafe fn fcos_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.cos.v4f64 + // CHECK: call <4 x double> @llvm.cos.v4f64 simd_fcos(a) } // CHECK-LABEL: @fcos_64x2 #[no_mangle] pub unsafe fn fcos_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.cos.v2f64 + // CHECK: call <2 x double> @llvm.cos.v2f64 simd_fcos(a) } // CHECK-LABEL: @fcos_64x8 #[no_mangle] pub unsafe fn fcos_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.cos.v8f64 + // CHECK: call <8 x double> @llvm.cos.v8f64 simd_fcos(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs index 33c8605066..1154acf692 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @exp_32x2 #[no_mangle] pub unsafe fn exp_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.exp.v2f32 + // CHECK: call <2 x float> @llvm.exp.v2f32 simd_fexp(a) } // CHECK-LABEL: @exp_32x4 #[no_mangle] pub unsafe fn exp_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.exp.v4f32 + // CHECK: call <4 x float> @llvm.exp.v4f32 simd_fexp(a) } // CHECK-LABEL: @exp_32x8 #[no_mangle] pub unsafe fn exp_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.exp.v8f32 + // CHECK: call <8 x float> @llvm.exp.v8f32 simd_fexp(a) } // CHECK-LABEL: @exp_32x16 #[no_mangle] pub unsafe fn exp_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.exp.v16f32 + // CHECK: call <16 x float> @llvm.exp.v16f32 simd_fexp(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @exp_64x4 #[no_mangle] pub unsafe fn exp_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.exp.v4f64 + // CHECK: call <4 x double> @llvm.exp.v4f64 simd_fexp(a) } // CHECK-LABEL: @exp_64x2 #[no_mangle] pub unsafe fn exp_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.exp.v2f64 + // CHECK: call <2 x double> @llvm.exp.v2f64 simd_fexp(a) } // CHECK-LABEL: @exp_64x8 #[no_mangle] pub unsafe fn exp_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.exp.v8f64 + // CHECK: call <8 x double> @llvm.exp.v8f64 simd_fexp(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs index f7a8986242..929dc9ac8d 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @exp2_32x2 #[no_mangle] pub unsafe fn exp2_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.exp2.v2f32 + // CHECK: call <2 x float> @llvm.exp2.v2f32 simd_fexp2(a) } // CHECK-LABEL: @exp2_32x4 #[no_mangle] pub unsafe fn exp2_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.exp2.v4f32 + // CHECK: call <4 x float> @llvm.exp2.v4f32 simd_fexp2(a) } // CHECK-LABEL: @exp2_32x8 #[no_mangle] pub unsafe fn exp2_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.exp2.v8f32 + // CHECK: call <8 x float> @llvm.exp2.v8f32 simd_fexp2(a) } // CHECK-LABEL: @exp2_32x16 #[no_mangle] pub unsafe fn exp2_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.exp2.v16f32 + // CHECK: call <16 x float> @llvm.exp2.v16f32 simd_fexp2(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @exp2_64x4 #[no_mangle] pub unsafe fn exp2_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.exp2.v4f64 + // CHECK: call <4 x double> @llvm.exp2.v4f64 simd_fexp2(a) } // CHECK-LABEL: @exp2_64x2 #[no_mangle] pub unsafe fn exp2_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.exp2.v2f64 + // CHECK: call <2 x double> @llvm.exp2.v2f64 simd_fexp2(a) } // CHECK-LABEL: @exp2_64x8 #[no_mangle] pub unsafe fn exp2_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.exp2.v8f64 + // CHECK: call <8 x double> @llvm.exp2.v8f64 simd_fexp2(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs index a4070317a6..56ca644f6b 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @floor_32x2 #[no_mangle] pub unsafe fn floor_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.floor.v2f32 + // CHECK: call <2 x float> @llvm.floor.v2f32 simd_floor(a) } // CHECK-LABEL: @floor_32x4 #[no_mangle] pub unsafe fn floor_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.floor.v4f32 + // CHECK: call <4 x float> @llvm.floor.v4f32 simd_floor(a) } // CHECK-LABEL: @floor_32x8 #[no_mangle] pub unsafe fn floor_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.floor.v8f32 + // CHECK: call <8 x float> @llvm.floor.v8f32 simd_floor(a) } // CHECK-LABEL: @floor_32x16 #[no_mangle] pub unsafe fn floor_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.floor.v16f32 + // CHECK: call <16 x float> @llvm.floor.v16f32 simd_floor(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @floor_64x4 #[no_mangle] pub unsafe fn floor_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.floor.v4f64 + // CHECK: call <4 x double> @llvm.floor.v4f64 simd_floor(a) } // CHECK-LABEL: @floor_64x2 #[no_mangle] pub unsafe fn floor_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.floor.v2f64 + // CHECK: call <2 x double> @llvm.floor.v2f64 simd_floor(a) } // CHECK-LABEL: @floor_64x8 #[no_mangle] pub unsafe fn floor_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.floor.v8f64 + // CHECK: call <8 x double> @llvm.floor.v8f64 simd_floor(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs index 0800a498cb..fd65cb72ba 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @fma_32x2 #[no_mangle] pub unsafe fn fma_32x2(a: f32x2, b: f32x2, c: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.fma.v2f32 + // CHECK: call <2 x float> @llvm.fma.v2f32 simd_fma(a, b, c) } // CHECK-LABEL: @fma_32x4 #[no_mangle] pub unsafe fn fma_32x4(a: f32x4, b: f32x4, c: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.fma.v4f32 + // CHECK: call <4 x float> @llvm.fma.v4f32 simd_fma(a, b, c) } // CHECK-LABEL: @fma_32x8 #[no_mangle] pub unsafe fn fma_32x8(a: f32x8, b: f32x8, c: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.fma.v8f32 + // CHECK: call <8 x float> @llvm.fma.v8f32 simd_fma(a, b, c) } // CHECK-LABEL: @fma_32x16 #[no_mangle] pub unsafe fn fma_32x16(a: f32x16, b: f32x16, c: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.fma.v16f32 + // CHECK: call <16 x float> @llvm.fma.v16f32 simd_fma(a, b, c) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @fma_64x4 #[no_mangle] pub unsafe fn fma_64x4(a: f64x4, b: f64x4, c: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.fma.v4f64 + // CHECK: call <4 x double> @llvm.fma.v4f64 simd_fma(a, b, c) } // CHECK-LABEL: @fma_64x2 #[no_mangle] pub unsafe fn fma_64x2(a: f64x2, b: f64x2, c: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.fma.v2f64 + // CHECK: call <2 x double> @llvm.fma.v2f64 simd_fma(a, b, c) } // CHECK-LABEL: @fma_64x8 #[no_mangle] pub unsafe fn fma_64x8(a: f64x8, b: f64x8, c: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.fma.v8f64 + // CHECK: call <8 x double> @llvm.fma.v8f64 simd_fma(a, b, c) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs index adc44ffd81..adc1919256 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @fsqrt_32x2 #[no_mangle] pub unsafe fn fsqrt_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.sqrt.v2f32 + // CHECK: call <2 x float> @llvm.sqrt.v2f32 simd_fsqrt(a) } // CHECK-LABEL: @fsqrt_32x4 #[no_mangle] pub unsafe fn fsqrt_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.sqrt.v4f32 + // CHECK: call <4 x float> @llvm.sqrt.v4f32 simd_fsqrt(a) } // CHECK-LABEL: @fsqrt_32x8 #[no_mangle] pub unsafe fn fsqrt_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.sqrt.v8f32 + // CHECK: call <8 x float> @llvm.sqrt.v8f32 simd_fsqrt(a) } // CHECK-LABEL: @fsqrt_32x16 #[no_mangle] pub unsafe fn fsqrt_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.sqrt.v16f32 + // CHECK: call <16 x float> @llvm.sqrt.v16f32 simd_fsqrt(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @fsqrt_64x4 #[no_mangle] pub unsafe fn fsqrt_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.sqrt.v4f64 + // CHECK: call <4 x double> @llvm.sqrt.v4f64 simd_fsqrt(a) } // CHECK-LABEL: @fsqrt_64x2 #[no_mangle] pub unsafe fn fsqrt_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.sqrt.v2f64 + // CHECK: call <2 x double> @llvm.sqrt.v2f64 simd_fsqrt(a) } // CHECK-LABEL: @fsqrt_64x8 #[no_mangle] pub unsafe fn fsqrt_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.sqrt.v8f64 + // CHECK: call <8 x double> @llvm.sqrt.v8f64 simd_fsqrt(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs index 9c236f1963..c072519c0d 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @log_32x2 #[no_mangle] pub unsafe fn log_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.log.v2f32 + // CHECK: call <2 x float> @llvm.log.v2f32 simd_flog(a) } // CHECK-LABEL: @log_32x4 #[no_mangle] pub unsafe fn log_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.log.v4f32 + // CHECK: call <4 x float> @llvm.log.v4f32 simd_flog(a) } // CHECK-LABEL: @log_32x8 #[no_mangle] pub unsafe fn log_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.log.v8f32 + // CHECK: call <8 x float> @llvm.log.v8f32 simd_flog(a) } // CHECK-LABEL: @log_32x16 #[no_mangle] pub unsafe fn log_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.log.v16f32 + // CHECK: call <16 x float> @llvm.log.v16f32 simd_flog(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @log_64x4 #[no_mangle] pub unsafe fn log_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.log.v4f64 + // CHECK: call <4 x double> @llvm.log.v4f64 simd_flog(a) } // CHECK-LABEL: @log_64x2 #[no_mangle] pub unsafe fn log_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.log.v2f64 + // CHECK: call <2 x double> @llvm.log.v2f64 simd_flog(a) } // CHECK-LABEL: @log_64x8 #[no_mangle] pub unsafe fn log_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.log.v8f64 + // CHECK: call <8 x double> @llvm.log.v8f64 simd_flog(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs index a922161aff..5fd6489950 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @log10_32x2 #[no_mangle] pub unsafe fn log10_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.log10.v2f32 + // CHECK: call <2 x float> @llvm.log10.v2f32 simd_flog10(a) } // CHECK-LABEL: @log10_32x4 #[no_mangle] pub unsafe fn log10_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.log10.v4f32 + // CHECK: call <4 x float> @llvm.log10.v4f32 simd_flog10(a) } // CHECK-LABEL: @log10_32x8 #[no_mangle] pub unsafe fn log10_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.log10.v8f32 + // CHECK: call <8 x float> @llvm.log10.v8f32 simd_flog10(a) } // CHECK-LABEL: @log10_32x16 #[no_mangle] pub unsafe fn log10_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.log10.v16f32 + // CHECK: call <16 x float> @llvm.log10.v16f32 simd_flog10(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @log10_64x4 #[no_mangle] pub unsafe fn log10_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.log10.v4f64 + // CHECK: call <4 x double> @llvm.log10.v4f64 simd_flog10(a) } // CHECK-LABEL: @log10_64x2 #[no_mangle] pub unsafe fn log10_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.log10.v2f64 + // CHECK: call <2 x double> @llvm.log10.v2f64 simd_flog10(a) } // CHECK-LABEL: @log10_64x8 #[no_mangle] pub unsafe fn log10_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.log10.v8f64 + // CHECK: call <8 x double> @llvm.log10.v8f64 simd_flog10(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs index 9624acb383..35175f0ca5 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @log2_32x2 #[no_mangle] pub unsafe fn log2_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.log2.v2f32 + // CHECK: call <2 x float> @llvm.log2.v2f32 simd_flog2(a) } // CHECK-LABEL: @log2_32x4 #[no_mangle] pub unsafe fn log2_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.log2.v4f32 + // CHECK: call <4 x float> @llvm.log2.v4f32 simd_flog2(a) } // CHECK-LABEL: @log2_32x8 #[no_mangle] pub unsafe fn log2_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.log2.v8f32 + // CHECK: call <8 x float> @llvm.log2.v8f32 simd_flog2(a) } // CHECK-LABEL: @log2_32x16 #[no_mangle] pub unsafe fn log2_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.log2.v16f32 + // CHECK: call <16 x float> @llvm.log2.v16f32 simd_flog2(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @log2_64x4 #[no_mangle] pub unsafe fn log2_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.log2.v4f64 + // CHECK: call <4 x double> @llvm.log2.v4f64 simd_flog2(a) } // CHECK-LABEL: @log2_64x2 #[no_mangle] pub unsafe fn log2_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.log2.v2f64 + // CHECK: call <2 x double> @llvm.log2.v2f64 simd_flog2(a) } // CHECK-LABEL: @log2_64x8 #[no_mangle] pub unsafe fn log2_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.log2.v8f64 + // CHECK: call <8 x double> @llvm.log2.v8f64 simd_flog2(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs index 6639e5d652..3b8d611ab6 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @fpow_32x2 #[no_mangle] pub unsafe fn fpow_32x2(a: f32x2, b: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.pow.v2f32 + // CHECK: call <2 x float> @llvm.pow.v2f32 simd_fpow(a, b) } // CHECK-LABEL: @fpow_32x4 #[no_mangle] pub unsafe fn fpow_32x4(a: f32x4, b: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.pow.v4f32 + // CHECK: call <4 x float> @llvm.pow.v4f32 simd_fpow(a, b) } // CHECK-LABEL: @fpow_32x8 #[no_mangle] pub unsafe fn fpow_32x8(a: f32x8, b: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.pow.v8f32 + // CHECK: call <8 x float> @llvm.pow.v8f32 simd_fpow(a, b) } // CHECK-LABEL: @fpow_32x16 #[no_mangle] pub unsafe fn fpow_32x16(a: f32x16, b: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.pow.v16f32 + // CHECK: call <16 x float> @llvm.pow.v16f32 simd_fpow(a, b) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @fpow_64x4 #[no_mangle] pub unsafe fn fpow_64x4(a: f64x4, b: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.pow.v4f64 + // CHECK: call <4 x double> @llvm.pow.v4f64 simd_fpow(a, b) } // CHECK-LABEL: @fpow_64x2 #[no_mangle] pub unsafe fn fpow_64x2(a: f64x2, b: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.pow.v2f64 + // CHECK: call <2 x double> @llvm.pow.v2f64 simd_fpow(a, b) } // CHECK-LABEL: @fpow_64x8 #[no_mangle] pub unsafe fn fpow_64x8(a: f64x8, b: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.pow.v8f64 + // CHECK: call <8 x double> @llvm.pow.v8f64 simd_fpow(a, b) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs index 5e82ea023d..e80c50c107 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @fpowi_32x2 #[no_mangle] pub unsafe fn fpowi_32x2(a: f32x2, b: i32) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.powi.v2f32 + // CHECK: call <2 x float> @llvm.powi.v2f32 simd_fpowi(a, b) } // CHECK-LABEL: @fpowi_32x4 #[no_mangle] pub unsafe fn fpowi_32x4(a: f32x4, b: i32) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.powi.v4f32 + // CHECK: call <4 x float> @llvm.powi.v4f32 simd_fpowi(a, b) } // CHECK-LABEL: @fpowi_32x8 #[no_mangle] pub unsafe fn fpowi_32x8(a: f32x8, b: i32) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.powi.v8f32 + // CHECK: call <8 x float> @llvm.powi.v8f32 simd_fpowi(a, b) } // CHECK-LABEL: @fpowi_32x16 #[no_mangle] pub unsafe fn fpowi_32x16(a: f32x16, b: i32) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.powi.v16f32 + // CHECK: call <16 x float> @llvm.powi.v16f32 simd_fpowi(a, b) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @fpowi_64x4 #[no_mangle] pub unsafe fn fpowi_64x4(a: f64x4, b: i32) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.powi.v4f64 + // CHECK: call <4 x double> @llvm.powi.v4f64 simd_fpowi(a, b) } // CHECK-LABEL: @fpowi_64x2 #[no_mangle] pub unsafe fn fpowi_64x2(a: f64x2, b: i32) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.powi.v2f64 + // CHECK: call <2 x double> @llvm.powi.v2f64 simd_fpowi(a, b) } // CHECK-LABEL: @fpowi_64x8 #[no_mangle] pub unsafe fn fpowi_64x8(a: f64x8, b: i32) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.powi.v8f64 + // CHECK: call <8 x double> @llvm.powi.v8f64 simd_fpowi(a, b) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs index 8ca2ca8607..9e3fab49af 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs @@ -32,28 +32,28 @@ extern "platform-intrinsic" { // CHECK-LABEL: @fsin_32x2 #[no_mangle] pub unsafe fn fsin_32x2(a: f32x2) -> f32x2 { - // CHECK: call fast <2 x float> @llvm.sin.v2f32 + // CHECK: call <2 x float> @llvm.sin.v2f32 simd_fsin(a) } // CHECK-LABEL: @fsin_32x4 #[no_mangle] pub unsafe fn fsin_32x4(a: f32x4) -> f32x4 { - // CHECK: call fast <4 x float> @llvm.sin.v4f32 + // CHECK: call <4 x float> @llvm.sin.v4f32 simd_fsin(a) } // CHECK-LABEL: @fsin_32x8 #[no_mangle] pub unsafe fn fsin_32x8(a: f32x8) -> f32x8 { - // CHECK: call fast <8 x float> @llvm.sin.v8f32 + // CHECK: call <8 x float> @llvm.sin.v8f32 simd_fsin(a) } // CHECK-LABEL: @fsin_32x16 #[no_mangle] pub unsafe fn fsin_32x16(a: f32x16) -> f32x16 { - // CHECK: call fast <16 x float> @llvm.sin.v16f32 + // CHECK: call <16 x float> @llvm.sin.v16f32 simd_fsin(a) } @@ -73,20 +73,20 @@ pub struct f64x8(pub f64, pub f64, pub f64, pub f64, // CHECK-LABEL: @fsin_64x4 #[no_mangle] pub unsafe fn fsin_64x4(a: f64x4) -> f64x4 { - // CHECK: call fast <4 x double> @llvm.sin.v4f64 + // CHECK: call <4 x double> @llvm.sin.v4f64 simd_fsin(a) } // CHECK-LABEL: @fsin_64x2 #[no_mangle] pub unsafe fn fsin_64x2(a: f64x2) -> f64x2 { - // CHECK: call fast <2 x double> @llvm.sin.v2f64 + // CHECK: call <2 x double> @llvm.sin.v2f64 simd_fsin(a) } // CHECK-LABEL: @fsin_64x8 #[no_mangle] pub unsafe fn fsin_64x8(a: f64x8) -> f64x8 { - // CHECK: call fast <8 x double> @llvm.sin.v8f64 + // CHECK: call <8 x double> @llvm.sin.v8f64 simd_fsin(a) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs index 267c995e07..6fb0ceb402 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs index 87c8b0d87d..4a98d797b5 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs index 3b1f4398f9..e2e0fc16df 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs index 9fce849e52..050a0e5b42 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -1,4 +1,4 @@ -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 56466a78d5..7d9b0d2a77 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -1,6 +1,5 @@ -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes -// min-llvm-version 8.0 #![crate_type = "lib"] diff --git a/src/test/codegen/staticlib-external-inline-fns.rs b/src/test/codegen/staticlib-external-inline-fns.rs index 8876ab7376..432c063e82 100644 --- a/src/test/codegen/staticlib-external-inline-fns.rs +++ b/src/test/codegen/staticlib-external-inline-fns.rs @@ -2,42 +2,42 @@ #![crate_type = "staticlib"] -// CHECK: define void @a() +// CHECK: define{{.*}}void @a() #[no_mangle] #[inline] pub extern "C" fn a() {} -// CHECK: define void @b() +// CHECK: define{{.*}}void @b() #[export_name = "b"] #[inline] pub extern "C" fn b() {} -// CHECK: define void @c() +// CHECK: define{{.*}}void @c() #[no_mangle] #[inline] extern "C" fn c() {} -// CHECK: define void @d() +// CHECK: define{{.*}}void @d() #[export_name = "d"] #[inline] extern "C" fn d() {} -// CHECK: define void @e() +// CHECK: define{{.*}}void @e() #[no_mangle] #[inline(always)] pub extern "C" fn e() {} -// CHECK: define void @f() +// CHECK: define{{.*}}void @f() #[export_name = "f"] #[inline(always)] pub extern "C" fn f() {} -// CHECK: define void @g() +// CHECK: define{{.*}}void @g() #[no_mangle] #[inline(always)] extern "C" fn g() {} -// CHECK: define void @h() +// CHECK: define{{.*}}void @h() #[export_name = "h"] #[inline(always)] extern "C" fn h() {} diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs index 4ea003e99a..17f051a5bc 100644 --- a/src/test/codegen/stores.rs +++ b/src/test/codegen/stores.rs @@ -1,5 +1,5 @@ // compile-flags: -C no-prepopulate-passes -// ignore-tidy-linelength +// #![crate_type = "lib"] diff --git a/src/test/codegen/target-cpu-on-functions.rs b/src/test/codegen/target-cpu-on-functions.rs index 7544ac0130..c043eceb5c 100644 --- a/src/test/codegen/target-cpu-on-functions.rs +++ b/src/test/codegen/target-cpu-on-functions.rs @@ -2,7 +2,7 @@ // "target-cpu" attribute in LLVM. // no-prefer-dynamic -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals #![crate_type = "staticlib"] diff --git a/src/test/codegen/transmute-scalar.rs b/src/test/codegen/transmute-scalar.rs index 78b4aa3fb8..e9584929f3 100644 --- a/src/test/codegen/transmute-scalar.rs +++ b/src/test/codegen/transmute-scalar.rs @@ -5,7 +5,7 @@ // FIXME(eddyb) all of these tests show memory stores and loads, even after a // scalar `bitcast`, more special-casing is required to remove `alloca` usage. -// CHECK: define i32 @f32_to_bits(float %x) +// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float %x) // CHECK: %2 = bitcast float %x to i32 // CHECK-NEXT: store i32 %2, i32* %0 // CHECK-NEXT: %3 = load i32, i32* %0 @@ -15,7 +15,7 @@ pub fn f32_to_bits(x: f32) -> u32 { unsafe { std::mem::transmute(x) } } -// CHECK: define i8 @bool_to_byte(i1 zeroext %b) +// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 zeroext %b) // CHECK: %1 = zext i1 %b to i8 // CHECK-NEXT: store i8 %1, i8* %0 // CHECK-NEXT: %2 = load i8, i8* %0 @@ -25,7 +25,7 @@ pub fn bool_to_byte(b: bool) -> u8 { unsafe { std::mem::transmute(b) } } -// CHECK: define zeroext i1 @byte_to_bool(i8 %byte) +// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte) // CHECK: %1 = trunc i8 %byte to i1 // CHECK-NEXT: %2 = zext i1 %1 to i8 // CHECK-NEXT: store i8 %2, i8* %0 @@ -37,7 +37,7 @@ pub unsafe fn byte_to_bool(byte: u8) -> bool { std::mem::transmute(byte) } -// CHECK: define i8* @ptr_to_ptr(i16* %p) +// CHECK-LABEL: define{{.*}}i8* @ptr_to_ptr(i16* %p) // CHECK: %2 = bitcast i16* %p to i8* // CHECK-NEXT: store i8* %2, i8** %0 // CHECK-NEXT: %3 = load i8*, i8** %0 @@ -54,7 +54,7 @@ pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 { // Tests below show the non-special-cased behavior (with the possible // future special-cased instructions in the "NOTE(eddyb)" comments). -// CHECK: define [[USIZE:i[0-9]+]] @ptr_to_int(i16* %p) +// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(i16* %p) // NOTE(eddyb) see above, the following two CHECK lines should ideally be this: // %2 = ptrtoint i16* %p to [[USIZE]] @@ -69,7 +69,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize { unsafe { std::mem::transmute(p) } } -// CHECK: define i16* @int_to_ptr([[USIZE]] %i) +// CHECK: define{{.*}}i16* @int_to_ptr([[USIZE]] %i) // NOTE(eddyb) see above, the following two CHECK lines should ideally be this: // %2 = inttoptr [[USIZE]] %i to i16* diff --git a/src/test/codegen/tune-cpu-on-functions.rs b/src/test/codegen/tune-cpu-on-functions.rs index 9121799cdb..ed8dc0e938 100644 --- a/src/test/codegen/tune-cpu-on-functions.rs +++ b/src/test/codegen/tune-cpu-on-functions.rs @@ -2,7 +2,7 @@ // "tune-cpu" attribute in LLVM. // no-prefer-dynamic -// ignore-tidy-linelength +// // compile-flags: -C no-prepopulate-passes -C panic=abort -C linker-plugin-lto -Cpasses=name-anon-globals -Z tune-cpu=generic #![crate_type = "staticlib"] diff --git a/src/test/codegen/unwind-extern-imports.rs b/src/test/codegen/unwind-extern-imports.rs index a2ba24aca2..e28397eb13 100644 --- a/src/test/codegen/unwind-extern-imports.rs +++ b/src/test/codegen/unwind-extern-imports.rs @@ -6,28 +6,28 @@ extern "C" { // CHECK: Function Attrs:{{.*}}nounwind -// CHECK-NEXT: declare void @extern_fn +// CHECK-NEXT: declare{{.*}}void @extern_fn fn extern_fn(); // CHECK-NOT: Function Attrs:{{.*}}nounwind -// CHECK: declare void @unwinding_extern_fn +// CHECK: declare{{.*}}void @unwinding_extern_fn #[unwind(allowed)] fn unwinding_extern_fn(); // CHECK-NOT: nounwind -// CHECK: declare void @aborting_extern_fn +// CHECK: declare{{.*}}void @aborting_extern_fn #[unwind(aborts)] fn aborting_extern_fn(); // FIXME: we want to have the attribute here } extern "Rust" { // CHECK-NOT: nounwind -// CHECK: declare void @rust_extern_fn +// CHECK: declare{{.*}}void @rust_extern_fn fn rust_extern_fn(); // CHECK-NOT: nounwind -// CHECK: declare void @rust_unwinding_extern_fn +// CHECK: declare{{.*}}void @rust_unwinding_extern_fn #[unwind(allowed)] fn rust_unwinding_extern_fn(); // CHECK-NOT: nounwind -// CHECK: declare void @rust_aborting_extern_fn +// CHECK: declare{{.*}}void @rust_aborting_extern_fn #[unwind(aborts)] fn rust_aborting_extern_fn(); // FIXME: we want to have the attribute here } diff --git a/src/test/codegen/var-names.rs b/src/test/codegen/var-names.rs index 3140a7c6b6..8f1b038708 100644 --- a/src/test/codegen/var-names.rs +++ b/src/test/codegen/var-names.rs @@ -2,7 +2,7 @@ #![crate_type = "lib"] -// CHECK-LABEL: define i32 @test(i32 %a, i32 %b) +// CHECK-LABEL: define{{.*}}i32 @test(i32 %a, i32 %b) #[no_mangle] pub fn test(a: u32, b: u32) -> u32 { let c = a + b; diff --git a/src/test/codegen/vec-in-place.rs b/src/test/codegen/vec-in-place.rs new file mode 100644 index 0000000000..72ed7492be --- /dev/null +++ b/src/test/codegen/vec-in-place.rs @@ -0,0 +1,14 @@ +// ignore-debug: the debug assertions get in the way +// compile-flags: -O +// min-llvm-version: 11.0 +#![crate_type = "lib"] + +// Ensure that trivial casts of vec elements are O(1) + +// CHECK-LABEL: @vec_iterator_cast +#[no_mangle] +pub fn vec_iterator_cast(vec: Vec<isize>) -> Vec<usize> { + // CHECK-NOT: loop + // CHECK-NOT: call + vec.into_iter().map(|e| e as usize).collect() +} diff --git a/src/test/codegen/wasm_casts_nontrapping.rs b/src/test/codegen/wasm_casts_nontrapping.rs deleted file mode 100644 index bd6073d8c2..0000000000 --- a/src/test/codegen/wasm_casts_nontrapping.rs +++ /dev/null @@ -1,162 +0,0 @@ -// only-wasm32 -// compile-flags: -C target-feature=+nontrapping-fptoint -#![crate_type = "lib"] - -// CHECK-LABEL: @cast_f64_i64 -#[no_mangle] -pub fn cast_f64_i64(a: f64) -> i64 { - // CHECK: tail call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double {{.*}}) - // CHECK-NEXT: ret i64 {{.*}} - a as _ -} - -// CHECK-LABEL: @cast_f64_i32 -#[no_mangle] -pub fn cast_f64_i32(a: f64) -> i32 { - // CHECK: tail call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double {{.*}}) - // CHECK-NEXT: ret i32 {{.*}} - a as _ -} - -// CHECK-LABEL: @cast_f32_i64 -#[no_mangle] -pub fn cast_f32_i64(a: f32) -> i64 { - // CHECK: tail call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float {{.*}}) - // CHECK-NEXT: ret i64 {{.*}} - a as _ -} - -// CHECK-LABEL: @cast_f32_i32 -#[no_mangle] -pub fn cast_f32_i32(a: f32) -> i32 { - // CHECK: tail call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float {{.*}}) - // CHECK-NEXT: ret i32 {{.*}} - a as _ -} - - -// CHECK-LABEL: @cast_f64_u64 -#[no_mangle] -pub fn cast_f64_u64(a: f64) -> u64 { - // CHECK: tail call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double {{.*}}) - // CHECK-NEXT: ret i64 {{.*}} - a as _ -} - -// CHECK-LABEL: @cast_f64_u32 -#[no_mangle] -pub fn cast_f64_u32(a: f64) -> u32 { - // CHECK: tail call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double {{.*}}) - // CHECK-NEXT: ret i32 {{.*}} - a as _ -} - -// CHECK-LABEL: @cast_f32_u64 -#[no_mangle] -pub fn cast_f32_u64(a: f32) -> u64 { - // CHECK: tail call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float {{.*}}) - // CHECK-NEXT: ret i64 {{.*}} - a as _ -} - -// CHECK-LABEL: @cast_f32_u32 -#[no_mangle] -pub fn cast_f32_u32(a: f32) -> u32 { - // CHECK: tail call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float {{.*}}) - // CHECK-NEXT: ret i32 {{.*}} - a as _ -} - -// CHECK-LABEL: @cast_f32_u8 -#[no_mangle] -pub fn cast_f32_u8(a: f32) -> u8 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui float {{.*}} to i8 - // CHECK-NEXT: select i1 {{.*}}, i8 {{.*}}, i8 {{.*}} - // CHECK-NEXT: ret i8 {{.*}} - a as _ -} - - - -// CHECK-LABEL: @cast_unchecked_f64_i64 -#[no_mangle] -pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi double {{.*}} to i64 - // CHECK-NEXT: ret i64 {{.*}} - a.to_int_unchecked() -} - -// CHECK-LABEL: @cast_unchecked_f64_i32 -#[no_mangle] -pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi double {{.*}} to i32 - // CHECK-NEXT: ret i32 {{.*}} - a.to_int_unchecked() -} - -// CHECK-LABEL: @cast_unchecked_f32_i64 -#[no_mangle] -pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi float {{.*}} to i64 - // CHECK-NEXT: ret i64 {{.*}} - a.to_int_unchecked() -} - -// CHECK-LABEL: @cast_unchecked_f32_i32 -#[no_mangle] -pub unsafe fn cast_unchecked_f32_i32(a: f32) -> i32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi float {{.*}} to i32 - // CHECK-NEXT: ret i32 {{.*}} - a.to_int_unchecked() -} - - -// CHECK-LABEL: @cast_unchecked_f64_u64 -#[no_mangle] -pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui double {{.*}} to i64 - // CHECK-NEXT: ret i64 {{.*}} - a.to_int_unchecked() -} - -// CHECK-LABEL: @cast_unchecked_f64_u32 -#[no_mangle] -pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui double {{.*}} to i32 - // CHECK-NEXT: ret i32 {{.*}} - a.to_int_unchecked() -} - -// CHECK-LABEL: @cast_unchecked_f32_u64 -#[no_mangle] -pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui float {{.*}} to i64 - // CHECK-NEXT: ret i64 {{.*}} - a.to_int_unchecked() -} - -// CHECK-LABEL: @cast_unchecked_f32_u32 -#[no_mangle] -pub unsafe fn cast_unchecked_f32_u32(a: f32) -> u32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui float {{.*}} to i32 - // CHECK-NEXT: ret i32 {{.*}} - a.to_int_unchecked() -} - -// CHECK-LABEL: @cast_unchecked_f32_u8 -#[no_mangle] -pub unsafe fn cast_unchecked_f32_u8(a: f32) -> u8 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui float {{.*}} to i8 - // CHECK-NEXT: ret i8 {{.*}} - a.to_int_unchecked() -} diff --git a/src/test/codegen/wasm_casts_trapping.rs b/src/test/codegen/wasm_casts_trapping.rs index ed51faa7be..baf130a879 100644 --- a/src/test/codegen/wasm_casts_trapping.rs +++ b/src/test/codegen/wasm_casts_trapping.rs @@ -1,5 +1,6 @@ // only-wasm32 // compile-flags: -C target-feature=-nontrapping-fptoint +// min-llvm-version: 12.0 #![crate_type = "lib"] // CHECK-LABEL: @cast_f64_i64 @@ -7,7 +8,7 @@ pub fn cast_f64_i64(a: f64) -> i64 { // CHECK-NOT: fptosi double {{.*}} to i64 // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i64.f64{{.*}} a as _ } @@ -16,7 +17,7 @@ pub fn cast_f64_i64(a: f64) -> i64 { pub fn cast_f64_i32(a: f64) -> i32 { // CHECK-NOT: fptosi double {{.*}} to i32 // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i32.f64{{.*}} a as _ } @@ -25,7 +26,7 @@ pub fn cast_f64_i32(a: f64) -> i32 { pub fn cast_f32_i64(a: f32) -> i64 { // CHECK-NOT: fptosi float {{.*}} to i64 // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i64.f32{{.*}} a as _ } @@ -34,7 +35,7 @@ pub fn cast_f32_i64(a: f32) -> i64 { pub fn cast_f32_i32(a: f32) -> i32 { // CHECK-NOT: fptosi float {{.*}} to i32 // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptosi.sat.i32.f32{{.*}} a as _ } @@ -43,7 +44,7 @@ pub fn cast_f32_i32(a: f32) -> i32 { pub fn cast_f64_u64(a: f64) -> u64 { // CHECK-NOT: fptoui double {{.*}} to i64 // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i64.f64{{.*}} a as _ } @@ -52,7 +53,7 @@ pub fn cast_f64_u64(a: f64) -> u64 { pub fn cast_f64_u32(a: f64) -> u32 { // CHECK-NOT: fptoui double {{.*}} to i32 // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i32.f64{{.*}} a as _ } @@ -61,7 +62,7 @@ pub fn cast_f64_u32(a: f64) -> u32 { pub fn cast_f32_u64(a: f32) -> u64 { // CHECK-NOT: fptoui float {{.*}} to i64 // CHECK-NOT: select i1 {{.*}}, i64 {{.*}}, i64 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i64.f32{{.*}} a as _ } @@ -70,16 +71,16 @@ pub fn cast_f32_u64(a: f32) -> u64 { pub fn cast_f32_u32(a: f32) -> u32 { // CHECK-NOT: fptoui float {{.*}} to i32 // CHECK-NOT: select i1 {{.*}}, i32 {{.*}}, i32 {{.*}} - // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i32.f32{{.*}} a as _ } // CHECK-LABEL: @cast_f32_u8 #[no_mangle] pub fn cast_f32_u8(a: f32) -> u8 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui float {{.*}} to i8 - // CHECK-NEXT: select i1 {{.*}}, i8 {{.*}}, i8 {{.*}} + // CHECK-NOT: fptoui float {{.*}} to i8 + // CHECK-NOT: select i1 {{.*}}, i8 {{.*}}, i8 {{.*}} + // CHECK: {{.*}} call {{.*}} @llvm.fptoui.sat.i8.f32{{.*}} a as _ } diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index 85e11c10c6..f3e465dc65 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Require a gdb or lldb that can read DW_TAG_variant_part. // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index 04bdf72890..155088c61f 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs index 11a115e239..b417567dcf 100644 --- a/src/test/debuginfo/by-value-non-immediate-argument.rs +++ b/src/test/debuginfo/by-value-non-immediate-argument.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // min-lldb-version: 310 diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs index f859fe8d1c..2ed49de58c 100644 --- a/src/test/debuginfo/c-style-enum-in-composite.rs +++ b/src/test/debuginfo/c-style-enum-in-composite.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index 5706d5c4cc..dce34fc0dc 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // ignore-aarch64 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // min-lldb-version: 310 diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs index 868f2285f3..1532c83dfa 100644 --- a/src/test/debuginfo/destructured-for-loop-variable.rs +++ b/src/test/debuginfo/destructured-for-loop-variable.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // min-lldb-version: 310 // This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs index 2033966ada..0d94cd224e 100644 --- a/src/test/debuginfo/evec-in-struct.rs +++ b/src/test/debuginfo/evec-in-struct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/extern-c-fn.rs b/src/test/debuginfo/extern-c-fn.rs index 5043e7d9b8..17a452ec63 100644 --- a/src/test/debuginfo/extern-c-fn.rs +++ b/src/test/debuginfo/extern-c-fn.rs @@ -5,17 +5,16 @@ // === GDB TESTS =================================================================================== // gdb-command:run -// gdb-command:print s -// gdbg-check:$1 = [...]"abcd" -// gdbr-check:$1 = [...]"abcd\000" +// gdb-command:printf "s = \"%s\"\n", s +// gdb-check:s = "abcd" // gdb-command:print len -// gdb-check:$2 = 20 +// gdb-check:$1 = 20 // gdb-command:print local0 -// gdb-check:$3 = 19 +// gdb-check:$2 = 19 // gdb-command:print local1 -// gdb-check:$4 = true +// gdb-check:$3 = true // gdb-command:print local2 -// gdb-check:$5 = 20.5 +// gdb-check:$4 = 20.5 // gdb-command:continue diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index 8c86d2cf43..dea1339517 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // min-lldb-version: 310 diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs index 2a8359de52..3314f0a4e4 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-lldb // ignore-android: FIXME(#10381) // min-gdb-version: 8.1 diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index 0023f69d27..b65471011f 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Require a gdb that can read DW_TAG_variant_part. // min-gdb-version: 8.2 diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index f776729222..85fe8ac08f 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // compile-flags:-g // Some versions of the non-rust-enabled LLDB print the wrong generic diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 678ca8df04..764330ae27 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // min-lldb-version: 310 // Require a gdb that can read DW_TAG_variant_part. diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 1d122ce285..170a610c62 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Some versions of the non-rust-enabled LLDB print the wrong generic // parameter type names in this test. // rust-lldb diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index 89aa78a6e1..60362e54e7 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Require a gdb or lldb that can read DW_TAG_variant_part. // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index c2cc6f9d24..a68e4c0a55 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -3,7 +3,6 @@ // Require a gdb that can read DW_TAG_variant_part. // min-gdb-version: 8.2 -// ignore-tidy-linelength // compile-flags:-g diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index 94ca0289b7..80f4c2e115 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // min-lldb-version: 310 // ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 diff --git a/src/test/debuginfo/multi-byte-chars.rs b/src/test/debuginfo/multi-byte-chars.rs index 5382dd1a32..5c68a88f2f 100644 --- a/src/test/debuginfo/multi-byte-chars.rs +++ b/src/test/debuginfo/multi-byte-chars.rs @@ -2,8 +2,6 @@ // compile-flags:-g -#![feature(non_ascii_idents)] - // This test checks whether debuginfo generation can handle multi-byte UTF-8 // characters at the end of a block. There's no need to do anything in the // debugger -- just make sure that the compiler doesn't crash. diff --git a/src/test/debuginfo/option-like-enum.rs b/src/test/debuginfo/option-like-enum.rs index 67a3d133ed..04d08b9e6a 100644 --- a/src/test/debuginfo/option-like-enum.rs +++ b/src/test/debuginfo/option-like-enum.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // min-lldb-version: 310 diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs index 380e882a0f..196d85b418 100644 --- a/src/test/debuginfo/packed-struct-with-destructor.rs +++ b/src/test/debuginfo/packed-struct-with-destructor.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs index 9654847ce5..7d1893a943 100644 --- a/src/test/debuginfo/packed-struct.rs +++ b/src/test/debuginfo/packed-struct.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // min-lldb-version: 310 // ignore-gdb-version: 7.11.90 - 7.12.9 diff --git a/src/test/debuginfo/pretty-huge-vec.rs b/src/test/debuginfo/pretty-huge-vec.rs index cbd2278f7e..67155b4e9f 100644 --- a/src/test/debuginfo/pretty-huge-vec.rs +++ b/src/test/debuginfo/pretty-huge-vec.rs @@ -13,7 +13,7 @@ // gdb-check:$1 = Vec(size=1000000000) = {[...]...} // gdb-command: print slice -// gdb-check:$2 = &[u8] {data_ptr: [...]"\000", length: 1000000000} +// gdb-check:$2 = &[u8] {data_ptr: [...], length: 1000000000} #![allow(unused_variables)] diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index 8026550882..93597aa7e2 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-windows failing on win32 bot // ignore-freebsd: gdb package too new // ignore-android: FIXME(#10381) diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs index e41acc2e1e..b7bfe44b6e 100644 --- a/src/test/debuginfo/simd.rs +++ b/src/test/debuginfo/simd.rs @@ -1,6 +1,5 @@ // Need a fix for LLDB first... // ignore-lldb -// ignore-tidy-linelength // FIXME: LLVM generates invalid debug info for variables requiring // dynamic stack realignment, which is the case on s390x for vector diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs index 49aa3bcbca..aa3cf023a7 100644 --- a/src/test/debuginfo/simple-struct.rs +++ b/src/test/debuginfo/simple-struct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // min-lldb-version: 310 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index db20e9d3e4..41d15af14e 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // min-lldb-version: 310 // ignore-gdb-version: 7.11.90 - 7.12.9 // ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 diff --git a/src/test/debuginfo/struct-in-struct.rs b/src/test/debuginfo/struct-in-struct.rs index a76a4c05d9..a9e7797ec7 100644 --- a/src/test/debuginfo/struct-in-struct.rs +++ b/src/test/debuginfo/struct-in-struct.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 34f75a4e30..3d819e3689 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Require a gdb or lldb that can read DW_TAG_variant_part. // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/struct-with-destructor.rs b/src/test/debuginfo/struct-with-destructor.rs index ebae953cb4..4334cd9028 100644 --- a/src/test/debuginfo/struct-with-destructor.rs +++ b/src/test/debuginfo/struct-with-destructor.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/tuple-in-struct.rs b/src/test/debuginfo/tuple-in-struct.rs index c43c1f7bf6..759eab8e8a 100644 --- a/src/test/debuginfo/tuple-in-struct.rs +++ b/src/test/debuginfo/tuple-in-struct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/tuple-struct.rs b/src/test/debuginfo/tuple-struct.rs index 78b6e6a54d..b8702f970a 100644 --- a/src/test/debuginfo/tuple-struct.rs +++ b/src/test/debuginfo/tuple-struct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index 87b0bc6294..39ead172e6 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Require a gdb or lldb that can read DW_TAG_variant_part. // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 43e68fedbf..cc4a4476d1 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-lldb // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 8ab6d14173..695cdc4f41 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -83,6 +83,55 @@ // lldbr-check:(isize) closure_local = 8 // lldb-command:continue + +// === CDB TESTS =================================================================================== + +// cdb-command: g + +// cdb-command: dx variable +// cdb-check:variable : 1 [Type: [...]] +// cdb-command: dx constant +// cdb-check:constant : 2 [Type: [...]] +// cdb-command: dx a_struct +// cdb-check:a_struct [Type: var_captured_in_nested_closure::Struct] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx struct_ref +// cdb-check:struct_ref : 0x[...] [Type: var_captured_in_nested_closure::Struct *] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx owned +// cdb-check:owned : 0x[...] : 6 [Type: [...] *] +// cdb-check: 6 [Type: [...]] +// 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-command: g + +// cdb-command: dx variable +// cdb-check:variable : 1 [Type: [...]] +// cdb-command: dx constant +// cdb-check:constant : 2 [Type: [...]] +// cdb-command: dx a_struct +// cdb-check:a_struct [Type: var_captured_in_nested_closure::Struct] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx struct_ref +// cdb-check:struct_ref : 0x[...] [Type: var_captured_in_nested_closure::Struct *] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx owned +// cdb-check:owned : 0x[...] : 6 [Type: [...] *] +// cdb-check: 6 [Type: [...]] +// cdb-command: dx closure_local +// cdb-check:closure_local : 8 [Type: [...]] + #![allow(unused_variables)] #![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index f53f8aaa67..1bbb79c37a 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -73,6 +73,48 @@ // lldbg-check:[...]$9 = 6 // lldbr-check:(isize) *owned = 6 + +// === CDB TESTS =================================================================================== + +// cdb-command: g + +// cdb-command: dx variable +// cdb-check:variable : 1 [Type: [...]] +// cdb-command: dx constant +// cdb-check:constant : 2 [Type: [...]] +// cdb-command: dx a_struct +// cdb-check:a_struct [Type: var_captured_in_stack_closure::Struct] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx struct_ref +// cdb-check:struct_ref : 0x[...] [Type: var_captured_in_stack_closure::Struct *] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx owned +// cdb-check:owned : 0x[...] : 6 [Type: [...] *] + + +// cdb-command: g + +// cdb-command: dx variable +// cdb-check:variable : 2 [Type: [...]] +// cdb-command: dx constant +// cdb-check:constant : 2 [Type: [...]] +// cdb-command: dx a_struct +// cdb-check:a_struct [Type: var_captured_in_stack_closure::Struct] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx struct_ref +// cdb-check:struct_ref : 0x[...] [Type: var_captured_in_stack_closure::Struct *] +// cdb-check: [+0x[...]] a : -3 [Type: [...]] +// cdb-check: [+0x[...]] b : 4.500000 [Type: [...]] +// cdb-check: [+0x[...]] c : 0x5 [Type: unsigned [...]] +// cdb-command: dx owned +// cdb-check:owned : 0x[...] : 6 [Type: [...] *] + #![feature(box_syntax)] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs index c385491bd1..e109b1bf2a 100644 --- a/src/test/debuginfo/vec-slices.rs +++ b/src/test/debuginfo/vec-slices.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // ignore-windows // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // min-lldb-version: 310 diff --git a/src/test/incremental/commandline-args.rs b/src/test/incremental/commandline-args.rs index 08a0232f66..35b7183db7 100644 --- a/src/test/incremental/commandline-args.rs +++ b/src/test/incremental/commandline-args.rs @@ -2,20 +2,23 @@ // the cache while changing an untracked one doesn't. // ignore-asmjs wasm2js does not support source maps yet -// revisions:rpass1 rpass2 rpass3 +// revisions:rpass1 rpass2 rpass3 rpass4 // compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![rustc_partition_codegened(module="commandline_args", cfg="rpass2")] #![rustc_partition_reused(module="commandline_args", cfg="rpass3")] +#![rustc_partition_codegened(module="commandline_args", cfg="rpass4")] // Between revisions 1 and 2, we are changing the debuginfo-level, which should // invalidate the cache. Between revisions 2 and 3, we are adding `--verbose` -// which should have no effect on the cache: +// which should have no effect on the cache. Between revisions, we are adding +// `--remap-path-prefix` which should invalidate the cache: //[rpass1] compile-flags: -C debuginfo=0 //[rpass2] compile-flags: -C debuginfo=2 //[rpass3] compile-flags: -C debuginfo=2 --verbose +//[rpass4] compile-flags: -C debuginfo=2 --verbose --remap-path-prefix=/home/bors/rust=src pub fn main() { // empty diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index 7a92313433..93e70d3792 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -12,7 +12,6 @@ #![allow(warnings)] #![feature(rustc_attrs)] #![feature(unboxed_closures)] -#![feature(link_args)] #![crate_type = "rlib"] // Change function name -------------------------------------------------------- @@ -146,21 +145,6 @@ extern "C" { pub fn add_function2(); } -// Change link-args ------------------------------------------------------------ -#[cfg(cfail1)] -#[link_args = "-foo -bar"] -extern "C" { - pub fn change_link_args(c: i32); -} - -#[cfg(not(cfail1))] -#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")] -#[rustc_clean(cfg = "cfail3")] -#[link_args = "-foo -bar -baz"] -extern "C" { - pub fn change_link_args(c: i32); -} - // Change link-name ------------------------------------------------------------ #[cfg(cfail1)] #[link(name = "foo")] diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index ed67b2dcb0..c8530c70f7 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -118,7 +118,7 @@ pub fn type_parameter<T>() {} pub fn lifetime_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_parameter<'a>() {} @@ -150,7 +150,7 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -183,7 +183,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index ae8f2ace21..ee7b258cec 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -312,7 +312,7 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -360,7 +360,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of" + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -388,7 +388,7 @@ impl Foo { // body will be affected. So if you start to see `typeck` // appear dirty, that might be the cause. -nmatsakis #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\ - type_of")] + type_of,fn_sig")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } } diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index aabdaa6641..4f5f6169f3 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -3,6 +3,7 @@ // revisions: cfail1 cfail2 // build-pass (FIXME(62277): could be check-pass?) +// compile-flags: -Z query-dep-graph #![crate_type = "rlib"] #![feature(rustc_attrs)] diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs index 19df2972f8..1fb0f8aa84 100644 --- a/src/test/incremental/ich_resolve_results.rs +++ b/src/test/incremental/ich_resolve_results.rs @@ -2,6 +2,7 @@ // `use` to something different. // revisions: rpass1 rpass2 rpass3 +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] diff --git a/src/test/incremental/issue-80691-bad-eval-cache.rs b/src/test/incremental/issue-80691-bad-eval-cache.rs new file mode 100644 index 0000000000..1a644fd88d --- /dev/null +++ b/src/test/incremental/issue-80691-bad-eval-cache.rs @@ -0,0 +1,184 @@ +// revisions: rfail1 rfail2 +// failure-status: 101 +// error-pattern: not implemented + +pub trait Interner { + type InternedVariableKinds; +} + +trait RustIrDatabase<I: Interner> { + fn associated_ty_data(&self) -> AssociatedTyDatum<I>; + fn impl_datum(&self) -> ImplDatum<I>; +} + +trait Fold<I: Interner> { + type Result; +} +impl<T, I: Interner> Fold<I> for Binders<T> +where + T: HasInterner<Interner = I> + Fold<I>, + <T as Fold<I>>::Result: HasInterner<Interner = I>, + I: Interner, +{ + type Result = Binders<T::Result>; +} +impl<I: Interner> Fold<I> for WhereClause<I> { + type Result = Binders<WhereClause<I>>; +} + +trait HasInterner { + type Interner: Interner; +} +impl<T: HasInterner> HasInterner for Vec<T> { + type Interner = T::Interner; +} +impl<T: HasInterner + ?Sized> HasInterner for &T { + type Interner = T::Interner; +} + +pub struct VariableKind<I: Interner> { + _marker: std::marker::PhantomData<I>, +} + +struct VariableKinds<I: Interner> { + _interned: I::InternedVariableKinds, +} + +struct WhereClause<I: Interner> { + _marker: std::marker::PhantomData<I>, +} +impl<I: Interner> HasInterner for WhereClause<I> { + type Interner = I; +} + +struct Binders<T> { + _marker: std::marker::PhantomData<T>, +} +impl<T: HasInterner> HasInterner for Binders<T> { + type Interner = T::Interner; +} +impl<T> Binders<&T> { + fn cloned(self) -> Binders<T> { + unimplemented!() + } +} +impl<T: HasInterner> Binders<T> { + fn map_ref<'a, U, OP>(&'a self, _op: OP) -> Binders<U> + where + OP: FnOnce(&'a T) -> U, + U: HasInterner<Interner = T::Interner>, + { + unimplemented!() + } +} +impl<T, I: Interner> Binders<T> +where + T: Fold<I> + HasInterner<Interner = I>, + I: Interner, +{ + fn substitute(self) -> T::Result { + unimplemented!() + } +} +impl<V, U> IntoIterator for Binders<V> +where + V: HasInterner + IntoIterator<Item = U>, + U: HasInterner<Interner = V::Interner>, +{ + type Item = Binders<U>; + type IntoIter = BindersIntoIterator<V>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +struct BindersIntoIterator<V: HasInterner> { + _binders: VariableKinds<V::Interner>, +} +impl<V> Iterator for BindersIntoIterator<V> +where + V: HasInterner + IntoIterator, + <V as IntoIterator>::Item: HasInterner<Interner = V::Interner>, +{ + type Item = Binders<<V as IntoIterator>::Item>; + fn next(&mut self) -> Option<Self::Item> { + unimplemented!() + } +} + +struct ImplDatum<I: Interner> { + binders: Binders<ImplDatumBound<I>>, +} +struct ImplDatumBound<I: Interner> { + where_clauses: Vec<Binders<WhereClause<I>>>, +} +impl<I: Interner> HasInterner for ImplDatumBound<I> { + type Interner = I; +} + +struct AssociatedTyDatum<I: Interner> { + binders: Binders<AssociatedTyDatumBound<I>>, +} + +struct AssociatedTyDatumBound<I: Interner> { + where_clauses: Vec<Binders<WhereClause<I>>>, +} +impl<I: Interner> HasInterner for AssociatedTyDatumBound<I> { + type Interner = I; +} + +struct ClauseBuilder<'me, I: Interner> { + db: &'me dyn RustIrDatabase<I>, +} +impl<'me, I: Interner> ClauseBuilder<'me, I> { + fn new() -> Self { + unimplemented!() + } + fn push_clause(&mut self, _conditions: impl Iterator<Item = Binders<Binders<WhereClause<I>>>>) { + unimplemented!() + } +} + +pub(crate) struct Forest<I: Interner> { + _marker: std::marker::PhantomData<I>, +} + +impl<I: Interner> Forest<I> { + fn iter_answers<'f>(&'f self) { + let builder = &mut ClauseBuilder::<I>::new(); + let impl_datum = builder.db.impl_datum(); + let impl_where_clauses = impl_datum + .binders + .map_ref(|b| &b.where_clauses) + .into_iter() + .map(|wc| wc.cloned().substitute()); + let associated_ty = builder.db.associated_ty_data(); + let assoc_ty_where_clauses = associated_ty + .binders + .map_ref(|b| &b.where_clauses) + .into_iter() + .map(|wc| wc.cloned().substitute()); + builder.push_clause(impl_where_clauses.chain(assoc_ty_where_clauses)); + } +} + +pub struct SLGSolver { + pub(crate) forest: Forest<ChalkIr>, +} +impl SLGSolver { + fn new() -> Self { + unimplemented!() + } + fn solve_multiple(&self) { + let _answers = self.forest.iter_answers(); + } +} + +pub struct ChalkIr; +impl Interner for ChalkIr { + type InternedVariableKinds = Vec<VariableKind<ChalkIr>>; +} + +fn main() { + let solver = SLGSolver::new(); + solver.solve_multiple(); +} diff --git a/src/test/incremental/issue-84252-global-alloc.rs b/src/test/incremental/issue-84252-global-alloc.rs new file mode 100644 index 0000000000..d2438df89f --- /dev/null +++ b/src/test/incremental/issue-84252-global-alloc.rs @@ -0,0 +1,12 @@ +// revisions: cfail1 cfail2 +// build-pass + +#![crate_type="lib"] +#![crate_type="cdylib"] + +#[allow(unused_imports)] +use std::alloc::System; + +#[cfg(cfail1)] +#[global_allocator] +static ALLOC: System = System; diff --git a/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs new file mode 100644 index 0000000000..2453af5b6b --- /dev/null +++ b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs @@ -0,0 +1,11 @@ +// revisions: rpass1 rpass2 + +extern crate respan; + +#[macro_use] +#[path = "invalid-span-helper-mod.rs"] +mod invalid_span_helper_mod; + +// Invoke a macro from a different file - this +// allows us to get tokens with spans from different files +helper!(1); diff --git a/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs new file mode 100644 index 0000000000..747174b1eb --- /dev/null +++ b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs @@ -0,0 +1,14 @@ +#[macro_export] +macro_rules! helper { + // Use `:tt` instead of `:ident` so that we don't get a `None`-delimited group + ($first:tt) => { + pub fn foo<T>() { + // The span of `$first` comes from another file, + // so the expression `1 + $first` ends up with an + // 'invalid' span that starts and ends in different files. + // We use the `respan!` macro to give all tokens the same + // `SyntaxContext`, so that the parser will try to merge the spans. + respan::respan!(let a = 1 + $first;); + } + } +} diff --git a/src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs b/src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs new file mode 100644 index 0000000000..5088eab629 --- /dev/null +++ b/src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + + +/// Copies the resolution information (the `SyntaxContext`) of the first +/// token to all other tokens in the stream. Does not recurse into groups. +#[proc_macro] +pub fn respan(input: TokenStream) -> TokenStream { + let first_span = input.clone().into_iter().next().unwrap().span(); + input.into_iter().map(|mut tree| { + tree.set_span(tree.span().resolved_at(first_span)); + tree + }).collect() +} diff --git a/src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs b/src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs new file mode 100644 index 0000000000..f358460b33 --- /dev/null +++ b/src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs @@ -0,0 +1,24 @@ +// revisions: rpass1 rpass2 +// aux-build:respan.rs +// aux-build:invalid-span-helper-lib.rs + +// This issue has several different parts. The high level idea is: +// 1. We create an 'invalid' span with the help of the `respan` proc-macro, +// The compiler attempts to prevent the creation of invalid spans by +// refusing to join spans with different `SyntaxContext`s. We work around +// this by applying the same `SyntaxContext` to the span of every token, +// using `Span::resolved_at` +// 2. We using this invalid span in the body of a function, causing it to get +// encoded into the `optimized_mir` +// 3. We call the function from a different crate - since the function is generic, +// monomorphization runs, causing `optimized_mir` to get called. +// 4. We re-run compilation using our populated incremental cache, but without +// making any changes. When we recompile the crate containing our generic function +// (`invalid_span_helper_lib`), we load the span from the incremental cache, and +// write it into the crate metadata. + +extern crate invalid_span_helper_lib; + +fn main() { + invalid_span_helper_lib::foo::<u8>(); +} diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs index 2574ef5199..37728af951 100644 --- a/src/test/incremental/spans_significant_w_panic.rs +++ b/src/test/incremental/spans_significant_w_panic.rs @@ -3,7 +3,7 @@ // revisions:rpass1 rpass2 -// compile-flags: -C overflow-checks=on +// compile-flags: -C overflow-checks=on -Z query-dep-graph #![feature(rustc_attrs)] diff --git a/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index a956811262..9fa478f8a8 100644 --- a/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -130,12 +130,12 @@ fn address_of_reborrow() -> () { StorageLive(_2); // scope 0 at $DIR/address-of.rs:4:14: 4:21 _2 = [const 0_i32; 10]; // scope 0 at $DIR/address-of.rs:4:14: 4:21 _1 = &_2; // scope 0 at $DIR/address-of.rs:4:13: 4:21 - FakeRead(ForLet, _1); // scope 0 at $DIR/address-of.rs:4:9: 4:10 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/address-of.rs:4:9: 4:10 StorageLive(_3); // scope 1 at $DIR/address-of.rs:5:9: 5:14 StorageLive(_4); // scope 1 at $DIR/address-of.rs:5:22: 5:29 _4 = [const 0_i32; 10]; // scope 1 at $DIR/address-of.rs:5:22: 5:29 _3 = &mut _4; // scope 1 at $DIR/address-of.rs:5:17: 5:29 - FakeRead(ForLet, _3); // scope 1 at $DIR/address-of.rs:5:9: 5:14 + FakeRead(ForLet(None), _3); // scope 1 at $DIR/address-of.rs:5:9: 5:14 StorageLive(_5); // scope 2 at $DIR/address-of.rs:7:5: 7:18 StorageLive(_6); // scope 2 at $DIR/address-of.rs:7:5: 7:18 _6 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:7:5: 7:6 @@ -170,25 +170,25 @@ fn address_of_reborrow() -> () { StorageDead(_13); // scope 2 at $DIR/address-of.rs:11:20: 11:21 StorageLive(_15); // scope 2 at $DIR/address-of.rs:13:9: 13:10 _15 = &raw const (*_1); // scope 2 at $DIR/address-of.rs:13:23: 13:24 - FakeRead(ForLet, _15); // scope 2 at $DIR/address-of.rs:13:9: 13:10 + FakeRead(ForLet(None), _15); // scope 2 at $DIR/address-of.rs:13:9: 13:10 AscribeUserType(_15, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 2 at $DIR/address-of.rs:13:12: 13:20 StorageLive(_16); // scope 3 at $DIR/address-of.rs:14:9: 14:10 _16 = &raw const (*_1); // scope 3 at $DIR/address-of.rs:14:31: 14:32 - FakeRead(ForLet, _16); // scope 3 at $DIR/address-of.rs:14:9: 14:10 + FakeRead(ForLet(None), _16); // scope 3 at $DIR/address-of.rs:14:9: 14:10 AscribeUserType(_16, o, UserTypeProjection { base: UserType(5), projs: [] }); // scope 3 at $DIR/address-of.rs:14:12: 14:28 StorageLive(_17); // scope 4 at $DIR/address-of.rs:15:9: 15:10 StorageLive(_18); // scope 4 at $DIR/address-of.rs:15:30: 15:31 _18 = &raw const (*_1); // scope 4 at $DIR/address-of.rs:15:30: 15:31 _17 = move _18 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 4 at $DIR/address-of.rs:15:30: 15:31 StorageDead(_18); // scope 4 at $DIR/address-of.rs:15:30: 15:31 - FakeRead(ForLet, _17); // scope 4 at $DIR/address-of.rs:15:9: 15:10 + FakeRead(ForLet(None), _17); // scope 4 at $DIR/address-of.rs:15:9: 15:10 AscribeUserType(_17, o, UserTypeProjection { base: UserType(7), projs: [] }); // scope 4 at $DIR/address-of.rs:15:12: 15:27 StorageLive(_19); // scope 5 at $DIR/address-of.rs:16:9: 16:10 StorageLive(_20); // scope 5 at $DIR/address-of.rs:16:27: 16:28 _20 = &raw const (*_1); // scope 5 at $DIR/address-of.rs:16:27: 16:28 _19 = move _20 as *const [i32] (Pointer(Unsize)); // scope 5 at $DIR/address-of.rs:16:27: 16:28 StorageDead(_20); // scope 5 at $DIR/address-of.rs:16:27: 16:28 - FakeRead(ForLet, _19); // scope 5 at $DIR/address-of.rs:16:9: 16:10 + FakeRead(ForLet(None), _19); // scope 5 at $DIR/address-of.rs:16:9: 16:10 AscribeUserType(_19, o, UserTypeProjection { base: UserType(9), projs: [] }); // scope 5 at $DIR/address-of.rs:16:12: 16:24 StorageLive(_21); // scope 6 at $DIR/address-of.rs:18:5: 18:18 StorageLive(_22); // scope 6 at $DIR/address-of.rs:18:5: 18:18 @@ -218,25 +218,25 @@ fn address_of_reborrow() -> () { StorageDead(_27); // scope 6 at $DIR/address-of.rs:21:22: 21:23 StorageLive(_29); // scope 6 at $DIR/address-of.rs:23:9: 23:10 _29 = &raw const (*_3); // scope 6 at $DIR/address-of.rs:23:23: 23:24 - FakeRead(ForLet, _29); // scope 6 at $DIR/address-of.rs:23:9: 23:10 + FakeRead(ForLet(None), _29); // scope 6 at $DIR/address-of.rs:23:9: 23:10 AscribeUserType(_29, o, UserTypeProjection { base: UserType(13), projs: [] }); // scope 6 at $DIR/address-of.rs:23:12: 23:20 StorageLive(_30); // scope 7 at $DIR/address-of.rs:24:9: 24:10 _30 = &raw const (*_3); // scope 7 at $DIR/address-of.rs:24:31: 24:32 - FakeRead(ForLet, _30); // scope 7 at $DIR/address-of.rs:24:9: 24:10 + FakeRead(ForLet(None), _30); // scope 7 at $DIR/address-of.rs:24:9: 24:10 AscribeUserType(_30, o, UserTypeProjection { base: UserType(15), projs: [] }); // scope 7 at $DIR/address-of.rs:24:12: 24:28 StorageLive(_31); // scope 8 at $DIR/address-of.rs:25:9: 25:10 StorageLive(_32); // scope 8 at $DIR/address-of.rs:25:30: 25:31 _32 = &raw const (*_3); // scope 8 at $DIR/address-of.rs:25:30: 25:31 _31 = move _32 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 8 at $DIR/address-of.rs:25:30: 25:31 StorageDead(_32); // scope 8 at $DIR/address-of.rs:25:30: 25:31 - FakeRead(ForLet, _31); // scope 8 at $DIR/address-of.rs:25:9: 25:10 + FakeRead(ForLet(None), _31); // scope 8 at $DIR/address-of.rs:25:9: 25:10 AscribeUserType(_31, o, UserTypeProjection { base: UserType(17), projs: [] }); // scope 8 at $DIR/address-of.rs:25:12: 25:27 StorageLive(_33); // scope 9 at $DIR/address-of.rs:26:9: 26:10 StorageLive(_34); // scope 9 at $DIR/address-of.rs:26:27: 26:28 _34 = &raw const (*_3); // scope 9 at $DIR/address-of.rs:26:27: 26:28 _33 = move _34 as *const [i32] (Pointer(Unsize)); // scope 9 at $DIR/address-of.rs:26:27: 26:28 StorageDead(_34); // scope 9 at $DIR/address-of.rs:26:27: 26:28 - FakeRead(ForLet, _33); // scope 9 at $DIR/address-of.rs:26:9: 26:10 + FakeRead(ForLet(None), _33); // scope 9 at $DIR/address-of.rs:26:9: 26:10 AscribeUserType(_33, o, UserTypeProjection { base: UserType(19), projs: [] }); // scope 9 at $DIR/address-of.rs:26:12: 26:24 StorageLive(_35); // scope 10 at $DIR/address-of.rs:28:5: 28:16 StorageLive(_36); // scope 10 at $DIR/address-of.rs:28:5: 28:16 @@ -266,25 +266,25 @@ fn address_of_reborrow() -> () { StorageDead(_41); // scope 10 at $DIR/address-of.rs:31:20: 31:21 StorageLive(_43); // scope 10 at $DIR/address-of.rs:33:9: 33:10 _43 = &raw mut (*_3); // scope 10 at $DIR/address-of.rs:33:21: 33:22 - FakeRead(ForLet, _43); // scope 10 at $DIR/address-of.rs:33:9: 33:10 + FakeRead(ForLet(None), _43); // scope 10 at $DIR/address-of.rs:33:9: 33:10 AscribeUserType(_43, o, UserTypeProjection { base: UserType(23), projs: [] }); // scope 10 at $DIR/address-of.rs:33:12: 33:18 StorageLive(_44); // scope 11 at $DIR/address-of.rs:34:9: 34:10 _44 = &raw mut (*_3); // scope 11 at $DIR/address-of.rs:34:29: 34:30 - FakeRead(ForLet, _44); // scope 11 at $DIR/address-of.rs:34:9: 34:10 + FakeRead(ForLet(None), _44); // scope 11 at $DIR/address-of.rs:34:9: 34:10 AscribeUserType(_44, o, UserTypeProjection { base: UserType(25), projs: [] }); // scope 11 at $DIR/address-of.rs:34:12: 34:26 StorageLive(_45); // scope 12 at $DIR/address-of.rs:35:9: 35:10 StorageLive(_46); // scope 12 at $DIR/address-of.rs:35:28: 35:29 _46 = &raw mut (*_3); // scope 12 at $DIR/address-of.rs:35:28: 35:29 _45 = move _46 as *mut dyn std::marker::Send (Pointer(Unsize)); // scope 12 at $DIR/address-of.rs:35:28: 35:29 StorageDead(_46); // scope 12 at $DIR/address-of.rs:35:28: 35:29 - FakeRead(ForLet, _45); // scope 12 at $DIR/address-of.rs:35:9: 35:10 + FakeRead(ForLet(None), _45); // scope 12 at $DIR/address-of.rs:35:9: 35:10 AscribeUserType(_45, o, UserTypeProjection { base: UserType(27), projs: [] }); // scope 12 at $DIR/address-of.rs:35:12: 35:25 StorageLive(_47); // scope 13 at $DIR/address-of.rs:36:9: 36:10 StorageLive(_48); // scope 13 at $DIR/address-of.rs:36:25: 36:26 _48 = &raw mut (*_3); // scope 13 at $DIR/address-of.rs:36:25: 36:26 _47 = move _48 as *mut [i32] (Pointer(Unsize)); // scope 13 at $DIR/address-of.rs:36:25: 36:26 StorageDead(_48); // scope 13 at $DIR/address-of.rs:36:25: 36:26 - FakeRead(ForLet, _47); // scope 13 at $DIR/address-of.rs:36:9: 36:10 + FakeRead(ForLet(None), _47); // scope 13 at $DIR/address-of.rs:36:9: 36:10 AscribeUserType(_47, o, UserTypeProjection { base: UserType(29), projs: [] }); // scope 13 at $DIR/address-of.rs:36:12: 36:22 _0 = const (); // scope 0 at $DIR/address-of.rs:3:26: 37:2 StorageDead(_47); // scope 13 at $DIR/address-of.rs:37:1: 37:2 diff --git a/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir index e058b0aaa8..195f3e2e65 100644 --- a/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir @@ -24,19 +24,19 @@ fn borrow_and_cast(_1: i32) -> () { StorageLive(_3); // scope 0 at $DIR/address-of.rs:42:13: 42:15 _3 = &_1; // scope 0 at $DIR/address-of.rs:42:13: 42:15 _2 = &raw const (*_3); // scope 0 at $DIR/address-of.rs:42:13: 42:15 - FakeRead(ForLet, _2); // scope 0 at $DIR/address-of.rs:42:9: 42:10 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/address-of.rs:42:9: 42:10 StorageDead(_3); // scope 0 at $DIR/address-of.rs:42:29: 42:30 StorageLive(_4); // scope 1 at $DIR/address-of.rs:43:9: 43:10 StorageLive(_5); // scope 1 at $DIR/address-of.rs:43:13: 43:19 _5 = &mut _1; // scope 1 at $DIR/address-of.rs:43:13: 43:19 _4 = &raw const (*_5); // scope 1 at $DIR/address-of.rs:43:13: 43:19 - FakeRead(ForLet, _4); // scope 1 at $DIR/address-of.rs:43:9: 43:10 + FakeRead(ForLet(None), _4); // scope 1 at $DIR/address-of.rs:43:9: 43:10 StorageDead(_5); // scope 1 at $DIR/address-of.rs:43:33: 43:34 StorageLive(_6); // scope 2 at $DIR/address-of.rs:44:9: 44:10 StorageLive(_7); // scope 2 at $DIR/address-of.rs:44:13: 44:19 _7 = &mut _1; // scope 2 at $DIR/address-of.rs:44:13: 44:19 _6 = &raw mut (*_7); // scope 2 at $DIR/address-of.rs:44:13: 44:19 - FakeRead(ForLet, _6); // scope 2 at $DIR/address-of.rs:44:9: 44:10 + FakeRead(ForLet(None), _6); // scope 2 at $DIR/address-of.rs:44:9: 44:10 StorageDead(_7); // scope 2 at $DIR/address-of.rs:44:31: 44:32 _0 = const (); // scope 0 at $DIR/address-of.rs:41:32: 45:2 StorageDead(_6); // scope 2 at $DIR/address-of.rs:45:1: 45:2 diff --git a/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index 7e0ca3dea4..e751b825c0 100644 --- a/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -28,7 +28,7 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/basic_assignment.rs:11:9: 11:17 _1 = const false; // scope 0 at $DIR/basic_assignment.rs:11:20: 11:25 - FakeRead(ForLet, _1); // scope 0 at $DIR/basic_assignment.rs:11:9: 11:17 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/basic_assignment.rs:11:9: 11:17 StorageLive(_2); // scope 1 at $DIR/basic_assignment.rs:12:9: 12:17 StorageLive(_3); // scope 2 at $DIR/basic_assignment.rs:16:16: 16:24 _3 = _1; // scope 2 at $DIR/basic_assignment.rs:16:16: 16:24 @@ -36,7 +36,7 @@ fn main() -> () { StorageDead(_3); // scope 2 at $DIR/basic_assignment.rs:16:23: 16:24 StorageLive(_4); // scope 2 at $DIR/basic_assignment.rs:18:9: 18:15 _4 = Option::<Box<u32>>::None; // scope 2 at $DIR/basic_assignment.rs:18:36: 18:40 - FakeRead(ForLet, _4); // scope 2 at $DIR/basic_assignment.rs:18:9: 18:15 + FakeRead(ForLet(None), _4); // scope 2 at $DIR/basic_assignment.rs:18:9: 18:15 AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 2 at $DIR/basic_assignment.rs:18:17: 18:33 StorageLive(_5); // scope 3 at $DIR/basic_assignment.rs:19:9: 19:15 StorageLive(_6); // scope 4 at $DIR/basic_assignment.rs:23:14: 23:20 diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index a137d7fadb..a046539665 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -18,7 +18,7 @@ fn main() -> () { _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 - _0 = const (); // scope 0 at $DIR/const_allocation.rs:7:11: 9:2 + nop; // scope 0 at $DIR/const_allocation.rs:7:11: 9:2 return; // scope 0 at $DIR/const_allocation.rs:9:2: 9:2 } } diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index ef98cf9c09..2385943920 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -18,7 +18,7 @@ fn main() -> () { _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 - _0 = const (); // scope 0 at $DIR/const_allocation.rs:7:11: 9:2 + nop; // scope 0 at $DIR/const_allocation.rs:7:11: 9:2 return; // scope 0 at $DIR/const_allocation.rs:9:2: 9:2 } } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index d2e764f856..1e4bd4ba91 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -18,7 +18,7 @@ fn main() -> () { _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 - _0 = const (); // scope 0 at $DIR/const_allocation2.rs:4:11: 6:2 + nop; // scope 0 at $DIR/const_allocation2.rs:4:11: 6:2 return; // scope 0 at $DIR/const_allocation2.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index 00bf91f90b..f943beced3 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -18,7 +18,7 @@ fn main() -> () { _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 - _0 = const (); // scope 0 at $DIR/const_allocation2.rs:4:11: 6:2 + nop; // scope 0 at $DIR/const_allocation2.rs:4:11: 6:2 return; // scope 0 at $DIR/const_allocation2.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index 519002da39..5c95afb586 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -18,7 +18,7 @@ fn main() -> () { _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 - _0 = const (); // scope 0 at $DIR/const_allocation3.rs:4:11: 6:2 + nop; // scope 0 at $DIR/const_allocation3.rs:4:11: 6:2 return; // scope 0 at $DIR/const_allocation3.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index 73c4288c32..3d1858de22 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -18,7 +18,7 @@ fn main() -> () { _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 - _0 = const (); // scope 0 at $DIR/const_allocation3.rs:4:11: 6:2 + nop; // scope 0 at $DIR/const_allocation3.rs:4:11: 6:2 return; // scope 0 at $DIR/const_allocation3.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 47c3239b8b..48e2bf8f7e 100644 --- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -99,7 +99,6 @@ _13 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:21:13: 21:22 StorageDead(_15); // scope 8 at $DIR/const_debuginfo.rs:21:21: 21:22 StorageDead(_14); // scope 8 at $DIR/const_debuginfo.rs:21:21: 21:22 - _0 = const (); // scope 0 at $DIR/const_debuginfo.rs:8:11: 22:2 StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:22:1: 22:2 StorageDead(_12); // scope 7 at $DIR/const_debuginfo.rs:22:1: 22:2 StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:22:1: 22:2 diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 5ba76c4f0b..2566d745ec 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -22,7 +22,7 @@ - // + ty: &i32 - // + val: Value(Scalar(alloc0)) + // + ty: &[&i32; 1] -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, [], Some(promoted[0])) ++ // + 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)) } @@ -30,7 +30,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, [], Some(promoted[0])) } ++ // + 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]) }) } + _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 diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 1565cc7d5e..093e228a0c 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -24,7 +24,7 @@ - // + ty: *const i32 - // + val: Value(Scalar(alloc2)) + // + ty: &[&i32; 1] -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, [], Some(promoted[0])) ++ // + 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)) } @@ -32,7 +32,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, [], Some(promoted[0])) } ++ // + 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]) }) } + _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 diff --git a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff index 54877f9f53..c3b2e535f0 100644 --- a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff @@ -23,7 +23,7 @@ + _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:5:13: 5:28 StorageDead(_2); // scope 0 at $DIR/aggregate.rs:5:27: 5:28 StorageDead(_3); // scope 0 at $DIR/aggregate.rs:5:28: 5:29 - _0 = const (); // scope 0 at $DIR/aggregate.rs:4:11: 6:2 + nop; // scope 0 at $DIR/aggregate.rs:4:11: 6:2 StorageDead(_1); // scope 0 at $DIR/aggregate.rs:6:1: 6:2 return; // scope 0 at $DIR/aggregate.rs:6:2: 6:2 } diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff index 4664934690..e69f887cea 100644 --- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff @@ -30,7 +30,7 @@ + _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:5:18: 5:33 StorageDead(_3); // scope 0 at $DIR/array_index.rs:5:33: 5:34 StorageDead(_2); // scope 0 at $DIR/array_index.rs:5:33: 5:34 - _0 = const (); // scope 0 at $DIR/array_index.rs:4:11: 6:2 + nop; // scope 0 at $DIR/array_index.rs:4:11: 6:2 StorageDead(_1); // scope 0 at $DIR/array_index.rs:6:1: 6:2 return; // scope 0 at $DIR/array_index.rs:6:2: 6:2 } diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff index 4664934690..e69f887cea 100644 --- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff @@ -30,7 +30,7 @@ + _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:5:18: 5:33 StorageDead(_3); // scope 0 at $DIR/array_index.rs:5:33: 5:34 StorageDead(_2); // scope 0 at $DIR/array_index.rs:5:33: 5:34 - _0 = const (); // scope 0 at $DIR/array_index.rs:4:11: 6:2 + nop; // scope 0 at $DIR/array_index.rs:4:11: 6:2 StorageDead(_1); // scope 0 at $DIR/array_index.rs:6:1: 6:2 return; // scope 0 at $DIR/array_index.rs:6:2: 6:2 } diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff index ba081f95fa..8d4852e372 100644 --- a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff @@ -45,7 +45,7 @@ - _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19 - _0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:3:11: 6:2 + nop; // scope 0 at $DIR/bad_op_div_by_zero.rs:3:11: 6:2 StorageDead(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:6:1: 6:2 StorageDead(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:6:1: 6:2 return; // scope 0 at $DIR/bad_op_div_by_zero.rs:6:2: 6:2 diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff index a843cacf4d..ae1fa64e74 100644 --- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff @@ -45,7 +45,7 @@ - _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19 - _0 = const (); // scope 0 at $DIR/bad_op_mod_by_zero.rs:3:11: 6:2 + nop; // scope 0 at $DIR/bad_op_mod_by_zero.rs:3:11: 6:2 StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:6:1: 6:2 StorageDead(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:6:1: 6:2 return; // scope 0 at $DIR/bad_op_mod_by_zero.rs:6:2: 6:2 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index 8c10b3518d..0517e7fac4 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -28,10 +28,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 // ty::Const // + ty: &[i32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + 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(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 @@ -50,7 +50,7 @@ bb1: { _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:25: 7:26 - _0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6 + nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6 StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:8:5: 8:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:1: 9:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:2: 9:2 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index 8c10b3518d..0517e7fac4 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -28,10 +28,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 // ty::Const // + ty: &[i32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + 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(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 @@ -50,7 +50,7 @@ bb1: { _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:25: 7:26 - _0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6 + nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:6:5: 8:6 StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:8:5: 8:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:1: 9:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:9:2: 9:2 diff --git a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff index 1412162d78..9fcbd32ca6 100644 --- a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff @@ -28,7 +28,7 @@ bb1: { StorageDead(_3); // scope 0 at $DIR/boxes.rs:12:26: 12:27 - _0 = const (); // scope 0 at $DIR/boxes.rs:11:11: 13:2 + nop; // scope 0 at $DIR/boxes.rs:11:11: 13:2 StorageDead(_1); // scope 0 at $DIR/boxes.rs:13:1: 13:2 return; // scope 0 at $DIR/boxes.rs:13:2: 13:2 } diff --git a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff index 1ccc154582..21326d8b1c 100644 --- a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff @@ -19,7 +19,7 @@ StorageLive(_2); // scope 1 at $DIR/cast.rs:6:9: 6:10 - _2 = const 42_u32 as u8 (Misc); // scope 1 at $DIR/cast.rs:6:13: 6:24 + _2 = const 42_u8; // scope 1 at $DIR/cast.rs:6:13: 6:24 - _0 = const (); // scope 0 at $DIR/cast.rs:3:11: 7:2 + nop; // scope 0 at $DIR/cast.rs:3:11: 7:2 StorageDead(_2); // scope 1 at $DIR/cast.rs:7:1: 7:2 StorageDead(_1); // scope 0 at $DIR/cast.rs:7:1: 7:2 return; // scope 0 at $DIR/cast.rs:7:2: 7:2 diff --git a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff index 3397ef9585..40705bece5 100644 --- a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff @@ -23,7 +23,7 @@ bb1: { - _1 = move (_2.0: u32); // scope 0 at $DIR/checked_add.rs:5:18: 5:23 + _1 = const 2_u32; // scope 0 at $DIR/checked_add.rs:5:18: 5:23 - _0 = const (); // scope 0 at $DIR/checked_add.rs:4:11: 6:2 + nop; // scope 0 at $DIR/checked_add.rs:4:11: 6:2 StorageDead(_1); // scope 0 at $DIR/checked_add.rs:6:1: 6:2 return; // scope 0 at $DIR/checked_add.rs:6:2: 6:2 } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff index 6034645864..28c80b346e 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff @@ -19,10 +19,10 @@ _3 = const FOO; // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, [], None) + // + val: Unevaluated(FOO, [], None) // mir::Constant // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, [], None) } + // + 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 }) } _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 @@ -39,7 +39,7 @@ bb1: { StorageDead(_5); // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:11: 8:12 StorageDead(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:12: 8:13 - _0 = const (); // scope 0 at $DIR/const_prop_fails_gracefully.rs:5:11: 9:2 + nop; // scope 0 at $DIR/const_prop_fails_gracefully.rs:5:11: 9:2 StorageDead(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:9:1: 9:2 return; // scope 0 at $DIR/const_prop_fails_gracefully.rs:9:2: 9:2 } diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir b/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir index 30512d0bbe..c2f75e5dae 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir @@ -4,6 +4,7 @@ fn hello() -> () { let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:11:14: 11:14 bb0: { + _0 = const (); // scope 0 at $DIR/control-flow-simplification.rs:14:6: 14:6 return; // scope 0 at $DIR/control-flow-simplification.rs:15:2: 15:2 } } diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff index 99fa0dcbc9..706cd63a73 100644 --- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff @@ -41,7 +41,7 @@ _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:11:13: 11:68 StorageDead(_2); // scope 0 at $DIR/discriminant.rs:11:67: 11:68 StorageDead(_3); // scope 0 at $DIR/discriminant.rs:11:68: 11:69 - _0 = const (); // scope 0 at $DIR/discriminant.rs:10:11: 12:2 + nop; // scope 0 at $DIR/discriminant.rs:10:11: 12:2 StorageDead(_1); // scope 0 at $DIR/discriminant.rs:12:1: 12:2 return; // scope 0 at $DIR/discriminant.rs:12:2: 12:2 } diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff index 99fa0dcbc9..706cd63a73 100644 --- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff @@ -41,7 +41,7 @@ _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:11:13: 11:68 StorageDead(_2); // scope 0 at $DIR/discriminant.rs:11:67: 11:68 StorageDead(_3); // scope 0 at $DIR/discriminant.rs:11:68: 11:69 - _0 = const (); // scope 0 at $DIR/discriminant.rs:10:11: 12:2 + nop; // scope 0 at $DIR/discriminant.rs:10:11: 12:2 StorageDead(_1); // scope 0 at $DIR/discriminant.rs:12:1: 12:2 return; // scope 0 at $DIR/discriminant.rs:12:2: 12:2 } diff --git a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff index 9ddb34e58e..e39c164183 100644 --- a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff @@ -28,7 +28,7 @@ - _1 = move (_3.0: u8); // scope 0 at $DIR/indirect.rs:5:13: 5:29 + _1 = const 3_u8; // scope 0 at $DIR/indirect.rs:5:13: 5:29 StorageDead(_2); // scope 0 at $DIR/indirect.rs:5:28: 5:29 - _0 = const (); // scope 0 at $DIR/indirect.rs:4:11: 6:2 + nop; // scope 0 at $DIR/indirect.rs:4:11: 6:2 StorageDead(_1); // scope 0 at $DIR/indirect.rs:6:1: 6:2 return; // scope 0 at $DIR/indirect.rs:6:2: 6:2 } diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff index 6bf553bc58..c5af2801b4 100644 --- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -11,8 +11,7 @@ StorageLive(_1); // scope 0 at $DIR/issue-66971.rs:16:5: 16:23 StorageLive(_2); // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 StorageLive(_3); // scope 0 at $DIR/issue-66971.rs:16:13: 16:15 -- (_2.0: ()) = move _3; // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 -+ (_2.0: ()) = const (); // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 + nop; // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 StorageDead(_3); // scope 0 at $DIR/issue-66971.rs:16:21: 16:22 @@ -25,7 +24,7 @@ bb1: { StorageDead(_2); // scope 0 at $DIR/issue-66971.rs:16:22: 16:23 StorageDead(_1); // scope 0 at $DIR/issue-66971.rs:16:23: 16:24 - _0 = const (); // scope 0 at $DIR/issue-66971.rs:15:11: 17:2 + nop; // scope 0 at $DIR/issue-66971.rs:15:11: 17:2 return; // scope 0 at $DIR/issue-66971.rs:17:2: 17:2 } } diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff index da35bf18c7..f20dc0785d 100644 --- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -28,7 +28,7 @@ bb1: { StorageDead(_2); // scope 0 at $DIR/issue-67019.rs:11:19: 11:20 StorageDead(_1); // scope 0 at $DIR/issue-67019.rs:11:20: 11:21 - _0 = const (); // scope 0 at $DIR/issue-67019.rs:10:11: 12:2 + nop; // scope 0 at $DIR/issue-67019.rs:10:11: 12:2 return; // scope 0 at $DIR/issue-67019.rs:12:2: 12:2 } } diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff index fa790822b6..8276318f1e 100644 --- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff @@ -29,7 +29,7 @@ _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32 StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:6:32: 6:33 StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:6:32: 6:33 - _0 = const (); // scope 0 at $DIR/large_array_index.rs:4:11: 7:2 + nop; // scope 0 at $DIR/large_array_index.rs:4:11: 7:2 StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:7:1: 7:2 return; // scope 0 at $DIR/large_array_index.rs:7:2: 7:2 } diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff index fa790822b6..8276318f1e 100644 --- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff @@ -29,7 +29,7 @@ _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32 StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:6:32: 6:33 StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:6:32: 6:33 - _0 = const (); // scope 0 at $DIR/large_array_index.rs:4:11: 7:2 + nop; // scope 0 at $DIR/large_array_index.rs:4:11: 7:2 StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:7:1: 7:2 return; // scope 0 at $DIR/large_array_index.rs:7:2: 7:2 } diff --git a/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff index 349f1557a8..f159cfa025 100644 --- a/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff @@ -19,7 +19,7 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:7:9: 7:10 - _2 = _1; // scope 1 at $DIR/mutable_variable.rs:7:13: 7:14 + _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:7:13: 7:14 - _0 = const (); // scope 0 at $DIR/mutable_variable.rs:4:11: 8:2 + nop; // scope 0 at $DIR/mutable_variable.rs:4:11: 8:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable.rs:8:1: 8:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable.rs:8:1: 8:2 return; // scope 0 at $DIR/mutable_variable.rs:8:2: 8:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index 12b02e9034..b22eab0500 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -23,7 +23,7 @@ + // 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 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } - _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate.rs:4:11: 8:2 + 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 return; // scope 0 at $DIR/mutable_variable_aggregate.rs:8:2: 8:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff index 6dc0e8ab3c..32e425d9b1 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff @@ -25,7 +25,7 @@ ((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:7:5: 7:13 StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:8:9: 8:10 _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:8:13: 8:14 - _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:4:11: 9:2 + nop; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:4:11: 9:2 StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:9:1: 9:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:9:1: 9:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:9:1: 9:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff index 08dd2d4da3..86fac1270d 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff @@ -26,7 +26,7 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10 - _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 + _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 - _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 9:2 + nop; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 9:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:9:1: 9:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:9:1: 9:2 return; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:9:2: 9:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index f6e173620e..5dad8e721f 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -34,11 +34,11 @@ _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 StorageDead(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:19: 9:20 - _2 = const (); // scope 2 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6 + nop; // scope 2 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6 StorageDead(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:10:5: 10:6 StorageLive(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:11:9: 11:10 _5 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:11:13: 11:14 - _0 = const (); // scope 0 at $DIR/mutable_variable_no_prop.rs:6:11: 12:2 + nop; // scope 0 at $DIR/mutable_variable_no_prop.rs:6:11: 12:2 StorageDead(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:12:1: 12:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:12:1: 12:2 return; // scope 0 at $DIR/mutable_variable_no_prop.rs:12:2: 12:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index 63bdcb2bc1..49854f7fba 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -41,7 +41,7 @@ _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:8:13: 8:16 StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:9: 9:10 _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:13: 9:16 - _0 = const (); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:4:11: 10:2 + nop; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:4:11: 10:2 StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2 StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff index a10bac4f3e..df802294c0 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff @@ -60,7 +60,7 @@ - _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38 StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:14:38: 14:39 - _0 = const (); // scope 0 at $DIR/optimizes_into_variable.rs:11:11: 15:2 + nop; // scope 0 at $DIR/optimizes_into_variable.rs:11:11: 15:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:15:1: 15:2 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff index a10bac4f3e..df802294c0 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff @@ -60,7 +60,7 @@ - _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38 StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:14:38: 14:39 - _0 = const (); // scope 0 at $DIR/optimizes_into_variable.rs:11:11: 15:2 + nop; // scope 0 at $DIR/optimizes_into_variable.rs:11:11: 15:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:15:1: 15:2 diff --git a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff index 07c78be69c..0d141a070f 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff @@ -42,7 +42,7 @@ StorageDead(_2); // scope 0 at $DIR/read_immutable_static.rs:7:21: 7:22 StorageDead(_5); // scope 0 at $DIR/read_immutable_static.rs:7:22: 7:23 StorageDead(_3); // scope 0 at $DIR/read_immutable_static.rs:7:22: 7:23 - _0 = const (); // scope 0 at $DIR/read_immutable_static.rs:6:11: 8:2 + nop; // scope 0 at $DIR/read_immutable_static.rs:6:11: 8:2 StorageDead(_1); // scope 0 at $DIR/read_immutable_static.rs:8:1: 8:2 return; // scope 0 at $DIR/read_immutable_static.rs:8:2: 8:2 } diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff index 4fd1b8b227..ae77443e01 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff @@ -14,16 +14,16 @@ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/ref_deref.rs:5:6: 5:10 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11 StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11 - _0 = const (); // scope 0 at $DIR/ref_deref.rs:4:11: 6:2 + nop; // scope 0 at $DIR/ref_deref.rs:4:11: 6:2 return; // scope 0 at $DIR/ref_deref.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff index e7ebfee7f3..402a28f3f9 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff @@ -17,10 +17,10 @@ + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 + // ty::Const + // + ty: &i32 -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) ++ // + val: Unevaluated(main, [], Some(promoted[0])) + // mir::Constant + // + span: $DIR/ref_deref.rs:5:6: 5:10 -+ // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) } ++ // + 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]) }) } + _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 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index 812c7c9771..b97d7d1be1 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -14,15 +14,15 @@ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 // ty::Const // + ty: &(i32, i32) - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + 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(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 - _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:4:11: 6:2 + nop; // scope 0 at $DIR/ref_deref_project.rs:4:11: 6:2 return; // scope 0 at $DIR/ref_deref_project.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff index 588c291bcc..48ede27112 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff @@ -17,10 +17,10 @@ + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 + // ty::Const + // + ty: &(i32, i32) -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) ++ // + 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(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) } ++ // + 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]) }) } + _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 diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff index 02eb3155be..1aeeae91d2 100644 --- a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff @@ -22,7 +22,7 @@ _1 = move _2 as *const fn() (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41 StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:4:40: 4:41 StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:4:41: 4:42 - _0 = const (); // scope 0 at $DIR/reify_fn_ptr.rs:3:11: 5:2 + nop; // scope 0 at $DIR/reify_fn_ptr.rs:3:11: 5:2 return; // scope 0 at $DIR/reify_fn_ptr.rs:5:2: 5:2 } } diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff index 98f409f326..1d9e4712d5 100644 --- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff @@ -35,7 +35,7 @@ StorageDead(_2); // scope 0 at $DIR/repeat.rs:6:31: 6:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:6:32: 6:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:6:32: 6:33 - _0 = const (); // scope 0 at $DIR/repeat.rs:5:11: 7:2 + nop; // scope 0 at $DIR/repeat.rs:5:11: 7:2 StorageDead(_1); // scope 0 at $DIR/repeat.rs:7:1: 7:2 return; // scope 0 at $DIR/repeat.rs:7:2: 7:2 } diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff index 98f409f326..1d9e4712d5 100644 --- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff @@ -35,7 +35,7 @@ StorageDead(_2); // scope 0 at $DIR/repeat.rs:6:31: 6:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:6:32: 6:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:6:32: 6:33 - _0 = const (); // scope 0 at $DIR/repeat.rs:5:11: 7:2 + nop; // scope 0 at $DIR/repeat.rs:5:11: 7:2 StorageDead(_1); // scope 0 at $DIR/repeat.rs:7:1: 7:2 return; // scope 0 at $DIR/repeat.rs:7:2: 7:2 } diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff index a4232d178a..af48ff0b09 100644 --- a/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff @@ -27,7 +27,7 @@ bb1: { StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:4:14: 4:15 StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:4:15: 4:16 - _0 = const (); // scope 0 at $DIR/scalar_literal_propagation.rs:2:11: 5:2 + nop; // scope 0 at $DIR/scalar_literal_propagation.rs:2:11: 5:2 StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:5:1: 5:2 return; // scope 0 at $DIR/scalar_literal_propagation.rs:5:2: 5:2 } diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index 240cc8e231..27791852d6 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -21,10 +21,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 // ty::Const // + ty: &[u32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 @@ -46,7 +46,7 @@ StorageDead(_4); // scope 0 at $DIR/slice_len.rs:5:33: 5:34 StorageDead(_2); // scope 0 at $DIR/slice_len.rs:5:33: 5:34 StorageDead(_1); // scope 0 at $DIR/slice_len.rs:5:33: 5:34 - _0 = const (); // scope 0 at $DIR/slice_len.rs:4:11: 6:2 + nop; // scope 0 at $DIR/slice_len.rs:4:11: 6:2 return; // scope 0 at $DIR/slice_len.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index 240cc8e231..27791852d6 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -21,10 +21,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 // ty::Const // + ty: &[u32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 @@ -46,7 +46,7 @@ StorageDead(_4); // scope 0 at $DIR/slice_len.rs:5:33: 5:34 StorageDead(_2); // scope 0 at $DIR/slice_len.rs:5:33: 5:34 StorageDead(_1); // scope 0 at $DIR/slice_len.rs:5:33: 5:34 - _0 = const (); // scope 0 at $DIR/slice_len.rs:4:11: 6:2 + nop; // scope 0 at $DIR/slice_len.rs:4:11: 6:2 return; // scope 0 at $DIR/slice_len.rs:6:2: 6:2 } } diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff index da4b135d4c..176581fc5b 100644 --- a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff @@ -30,7 +30,7 @@ bb1: { StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:5:14: 5:15 StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:5:15: 5:16 - _0 = const (); // scope 0 at $DIR/tuple_literal_propagation.rs:2:11: 6:2 + nop; // scope 0 at $DIR/tuple_literal_propagation.rs:2:11: 6:2 StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:6:1: 6:2 return; // scope 0 at $DIR/tuple_literal_propagation.rs:6:2: 6:2 } diff --git a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff index 5a3a99e493..0864eaba71 100644 --- a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff @@ -25,14 +25,14 @@ _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:14:10: 14:22 (*_3) = const 5_i32; // scope 2 at $DIR/const_prop_miscompile.rs:14:9: 14:26 StorageDead(_3); // scope 2 at $DIR/const_prop_miscompile.rs:14:26: 14:27 - _2 = const (); // scope 2 at $DIR/const_prop_miscompile.rs:13:5: 15:6 + nop; // scope 2 at $DIR/const_prop_miscompile.rs:13:5: 15:6 StorageDead(_2); // scope 1 at $DIR/const_prop_miscompile.rs:15:5: 15:6 StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:16:9: 16:10 StorageLive(_5); // scope 1 at $DIR/const_prop_miscompile.rs:16:13: 16:20 _5 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:16:15: 16:18 _4 = Eq(move _5, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:16:13: 16:25 StorageDead(_5); // scope 1 at $DIR/const_prop_miscompile.rs:16:24: 16:25 - _0 = const (); // scope 0 at $DIR/const_prop_miscompile.rs:11:10: 17:2 + nop; // scope 0 at $DIR/const_prop_miscompile.rs:11:10: 17:2 StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:17:1: 17:2 StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:17:1: 17:2 return; // scope 0 at $DIR/const_prop_miscompile.rs:17:2: 17:2 diff --git a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff index 648260c7c2..f7375cb611 100644 --- a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff +++ b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff @@ -26,7 +26,7 @@ _4 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:7:15: 7:18 _3 = Eq(move _4, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:7:13: 7:25 StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:7:24: 7:25 - _0 = const (); // scope 0 at $DIR/const_prop_miscompile.rs:4:10: 8:2 + nop; // scope 0 at $DIR/const_prop_miscompile.rs:4:10: 8:2 StorageDead(_3); // scope 1 at $DIR/const_prop_miscompile.rs:8:1: 8:2 StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:8:1: 8:2 return; // scope 0 at $DIR/const_prop_miscompile.rs:8:2: 8:2 diff --git a/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff index e11d24cac8..500d6d20db 100644 --- a/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff @@ -62,7 +62,7 @@ bb6: { StorageDead(_3); // scope 1 at $DIR/branch.rs:20:5: 20:6 - _0 = const (); // scope 0 at $DIR/branch.rs:12:11: 21:2 + nop; // scope 0 at $DIR/branch.rs:12:11: 21:2 - StorageDead(_2); // scope 1 at $DIR/branch.rs:21:1: 21:2 - StorageDead(_1); // scope 0 at $DIR/branch.rs:21:1: 21:2 + nop; // scope 1 at $DIR/branch.rs:21:1: 21:2 diff --git a/src/test/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff index dce8800e98..383f00f012 100644 --- a/src/test/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff @@ -21,7 +21,7 @@ StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:16:12: 16:13 StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:16:13: 16:14 _1 = const 5_u8; // scope 0 at $DIR/copy_propagation_arg.rs:17:5: 17:10 - _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:15:19: 18:2 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:15:19: 18:2 return; // scope 0 at $DIR/copy_propagation_arg.rs:18:2: 18:2 } } diff --git a/src/test/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff index 2f8c76eb65..2349d5b077 100644 --- a/src/test/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/copy_propagation_arg.baz.DestinationPropagation.diff @@ -15,7 +15,7 @@ + nop; // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:23:5: 23:10 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10 - _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:21:20: 24:2 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:21:20: 24:2 return; // scope 0 at $DIR/copy_propagation_arg.rs:24:2: 24:2 } } diff --git a/src/test/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff index 2dea530db3..f955a9c043 100644 --- a/src/test/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff @@ -25,7 +25,7 @@ - StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:11:5: 11:17 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17 - _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:9:19: 12:2 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:9:19: 12:2 return; // scope 0 at $DIR/copy_propagation_arg.rs:12:2: 12:2 } } diff --git a/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff index 621a747e13..32d7e301c1 100644 --- a/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff @@ -58,7 +58,6 @@ + _6 = _4; // scope 3 at $DIR/cycle.rs:14:10: 14:11 StorageDead(_6); // scope 3 at $DIR/cycle.rs:14:11: 14:12 StorageDead(_5); // scope 3 at $DIR/cycle.rs:14:12: 14:13 - _0 = const (); // scope 0 at $DIR/cycle.rs:8:11: 15:2 - StorageDead(_3); // scope 2 at $DIR/cycle.rs:15:1: 15:2 - StorageDead(_2); // scope 1 at $DIR/cycle.rs:15:1: 15:2 - StorageDead(_1); // scope 0 at $DIR/cycle.rs:15:1: 15:2 diff --git a/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff index a3368dcfcc..9be0738ea9 100644 --- a/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff @@ -33,7 +33,6 @@ _4 = (_1.0: u32); // scope 2 at $DIR/union.rs:15:19: 15:24 StorageDead(_4); // scope 1 at $DIR/union.rs:15:26: 15:27 StorageDead(_3); // scope 1 at $DIR/union.rs:15:27: 15:28 - _0 = const (); // scope 0 at $DIR/union.rs:8:11: 16:2 StorageDead(_1); // scope 0 at $DIR/union.rs:16:1: 16:2 return; // scope 0 at $DIR/union.rs:16:2: 16:2 } diff --git a/src/test/mir-opt/early_otherwise_branch_68867.rs b/src/test/mir-opt/early_otherwise_branch_68867.rs index e11337643d..02221c4cf4 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.rs +++ b/src/test/mir-opt/early_otherwise_branch_68867.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts // example from #68867 diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff index 1b292cdd79..2893ee9ac3 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff @@ -2,299 +2,299 @@ + // MIR for `try_sum` after SimplifyBranches-final fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result<ViewportPercentageLength, ()> { - debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:18:5: 18:6 - debug other => _2; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:5: 19:10 - let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:6: 20:42 - let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 - let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 - let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 - let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:18: 22:23 - let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 - let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:30 - let mut _9: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 - let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:23: 26:34 - let mut _11: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 - let _12: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - let _13: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - let mut _14: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 - let mut _15: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 - let mut _16: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 - let _17: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 - let _18: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 - let mut _19: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 - let mut _20: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 - let mut _21: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 - let _22: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - let _23: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - let mut _24: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 - let mut _25: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 - let mut _26: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 - let _27: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 - let _28: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 - let mut _29: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 - let mut _30: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 - let mut _31: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 - let mut _32: !; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:27:14: 27:28 - let mut _33: (); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:27:25: 27:27 -+ let mut _34: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 -+ let mut _35: bool; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 + debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:17:5: 17:6 + debug other => _2; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:18:5: 18:10 + let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:6: 19:42 + let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 + let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 + let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23 + let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 + let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 + let mut _9: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34 + let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 + let mut _11: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 + let _12: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + let _13: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + let mut _14: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 + let mut _15: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 + let mut _16: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 + let _17: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + let _18: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + let mut _19: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 + let mut _20: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 + let mut _21: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 + let _22: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + let _23: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + let mut _24: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 + let mut _25: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 + let mut _26: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 + let _27: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + let _28: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + let mut _29: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 + let mut _30: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 + let mut _31: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 + let mut _32: !; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:14: 26:28 + let mut _33: (); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27 ++ let mut _34: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 ++ let mut _35: bool; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 scope 1 { -- debug one => _12; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 -- debug other => _13; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 -+ debug one => _15; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 -+ debug other => _16; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 +- debug one => _12; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 +- debug other => _13; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 ++ debug one => _15; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 ++ debug other => _16; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 } scope 2 { -- debug one => _17; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 -- debug other => _18; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 -+ debug one => _20; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 -+ debug other => _21; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 +- debug one => _17; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 +- debug other => _18; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 ++ debug one => _20; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 ++ debug other => _21; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 } scope 3 { -- debug one => _22; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 -- debug other => _23; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 -+ debug one => _25; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 -+ debug other => _26; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 +- debug one => _22; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 +- debug other => _23; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 ++ debug one => _25; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 ++ debug other => _26; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 } scope 4 { -- debug one => _27; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 -- debug other => _28; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 -+ debug one => _30; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 -+ debug other => _31; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 +- debug one => _27; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 +- debug other => _28; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 ++ debug one => _30; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 ++ debug other => _31; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 } bb0: { -- StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -- StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 -- StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 -- _5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 -+ (_4.0: &ViewportPercentageLength) = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 - StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:18: 22:23 - _6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:18: 22:23 -- (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 - (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 - StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:24 -- StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:24 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:24 - _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ _35 = Ne(_34, _11); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ StorageDead(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 +- StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 +- StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 +- StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 +- _5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 ++ (_4.0: &ViewportPercentageLength) = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 + StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23 + _6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23 +- (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 +- StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 + _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 +- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ _35 = Ne(_34, _11); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ StorageDead(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 } bb1: { -- _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 -- switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 +- _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 +- switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 - } - - bb2: { -+ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:25: 27:27 - StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:25: 27:27 - ((_0 as Err).0: ()) = const (); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:21: 27:28 - discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:21: 27:28 - StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:27: 27:28 -- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:6: 28:7 -- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:1: 29:2 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:6: 28:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:1: 29:2 - return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:2: 29:2 ++ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27 + StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27 +- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28 + discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28 + StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:27: 26:28 +- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 +- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 + return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 } + bb2: { ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 ++ _15 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 ++ _16 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 ++ ((((_0 as Ok).0: ViewportPercentageLength) as Vw).0: f32) = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50 ++ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50 ++ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 ++ } ++ + bb3: { +- _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 +- switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 -+ _15 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 ++ _20 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 -+ _16 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vw).0: f32) = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 -+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 ++ _21 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 ++ ((((_0 as Ok).0: ViewportPercentageLength) as Vh).0: f32) = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 ++ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 ++ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -+ } -+ - bb3: { -- _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:30 -- switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:30 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 -+ _20 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 -+ _21 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vh).0: f32) = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:48: 24:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:48: 24:49 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:35: 24:50 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:35: 24:50 -+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 } bb4: { -- _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 -- switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 +- _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34 +- switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 ++ _25 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 ++ _26 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 ++ ((((_0 as Ok).0: ViewportPercentageLength) as Vmin).0: f32) = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56 ++ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56 ++ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 + } + + bb5: { +- _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 +- switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 -+ _25 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 ++ _30 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 -+ _26 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vmin).0: f32) = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 -+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 ++ _31 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 ++ ((((_0 as Ok).0: ViewportPercentageLength) as Vmax).0: f32) = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 ++ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 ++ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 - } - - bb5: { -- _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:23: 26:34 -- switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:23: 26:34 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 -+ _30 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 -+ _31 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 -+ ((((_0 as Ok).0: ViewportPercentageLength) as Vmax).0: f32) = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:54: 26:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:54: 26:55 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:39: 26:56 -+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:39: 26:56 -+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 } bb6: { -- StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 -- _12 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 -- StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 -- _13 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 -- StorageLive(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 -- StorageLive(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 -- _15 = _12; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 -- StorageLive(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 -- _16 = _13; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 -- _14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 -- StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 -- StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 -- ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 -- discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 -- StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 -- StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 -- StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:5: 28:7 -+ discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:5: 28:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:6: 28:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:1: 29:2 -+ return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:2: 29:2 +- StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 +- _12 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 +- StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 +- _13 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 +- StorageLive(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 +- StorageLive(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 +- _15 = _12; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 +- StorageLive(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 +- _16 = _13; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 +- _14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 +- StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49 +- StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49 +- ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50 +- discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50 +- StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 +- StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 +- StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 ++ discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 ++ return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 } bb7: { -- StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 -- _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 -- StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 -- _18 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 -- StorageLive(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 -- StorageLive(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 -- _20 = _17; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 -- StorageLive(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 -- _21 = _18; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 -- _19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 -- StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:48: 24:49 -- StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:48: 24:49 -- ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:35: 24:50 -- discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:35: 24:50 -- StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 -- StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 -- StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 +- StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 +- _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 +- StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 +- _18 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 +- StorageLive(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 +- StorageLive(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 +- _20 = _17; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 +- StorageLive(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 +- _21 = _18; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 +- _19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 +- StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 +- StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 +- ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 +- discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 +- StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 +- StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 +- StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 - } - - bb8: { -- StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 -- _22 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 -- StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 -- _23 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 -- StorageLive(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 -- StorageLive(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 -- _25 = _22; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 -- StorageLive(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 -- _26 = _23; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 -- _24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 -- StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 -- StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 -- ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 -- discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 -- StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 -- StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 -- StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 +- StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 +- _22 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 +- StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 +- _23 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 +- StorageLive(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 +- StorageLive(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 +- _25 = _22; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 +- StorageLive(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 +- _26 = _23; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 +- _24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 +- StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55 +- StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55 +- ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56 +- discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56 +- StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 +- StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 +- StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 - } - - bb9: { -- StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 -- _27 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 -- StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 -- _28 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 -- StorageLive(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 -- StorageLive(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 -- _30 = _27; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 -- StorageLive(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 -- _31 = _28; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 -- _29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 -- StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:54: 26:55 -- StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:54: 26:55 -- ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:39: 26:56 -- discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:39: 26:56 -- StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 -- StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 -- StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 +- StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 +- _27 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 +- StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 +- _28 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 +- StorageLive(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 +- StorageLive(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 +- _30 = _27; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 +- StorageLive(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 +- _31 = _28; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 +- _29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 +- StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 +- StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 +- ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 +- discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 +- StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 +- StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 +- StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 - } - - bb10: { -- ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:5: 28:7 -- discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:5: 28:7 -- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:6: 28:7 -- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:1: 29:2 -- return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:2: 29:2 -+ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 -+ switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 +- ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 +- discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 +- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 +- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 +- return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 ++ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 ++ switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 } } diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index d20ee78459..9039989e0f 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -2,215 +2,215 @@ + // MIR for `try_sum` after EarlyOtherwiseBranch fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result<ViewportPercentageLength, ()> { - debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:18:5: 18:6 - debug other => _2; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:5: 19:10 - let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:20:6: 20:42 - let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 - let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 - let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 - let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:18: 22:23 - let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 - let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:30 - let mut _9: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 - let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:23: 26:34 - let mut _11: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 - let _12: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - let _13: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - let mut _14: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 - let mut _15: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 - let mut _16: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 - let _17: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 - let _18: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 - let mut _19: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 - let mut _20: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 - let mut _21: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 - let _22: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - let _23: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - let mut _24: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 - let mut _25: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 - let mut _26: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 - let _27: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 - let _28: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 - let mut _29: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 - let mut _30: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 - let mut _31: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 - let mut _32: !; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:27:14: 27:28 - let mut _33: (); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:27:25: 27:27 -+ let mut _34: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 -+ let mut _35: bool; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 + debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:17:5: 17:6 + debug other => _2; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:18:5: 18:10 + let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:19:6: 19:42 + let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 + let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 + let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23 + let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 + let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 + let mut _9: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34 + let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 + let mut _11: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 + let _12: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + let _13: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + let mut _14: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 + let mut _15: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 + let mut _16: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 + let _17: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + let _18: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + let mut _19: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 + let mut _20: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 + let mut _21: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 + let _22: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + let _23: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + let mut _24: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 + let mut _25: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 + let mut _26: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 + let _27: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + let _28: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + let mut _29: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 + let mut _30: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 + let mut _31: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 + let mut _32: !; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:14: 26:28 + let mut _33: (); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27 ++ let mut _34: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 ++ let mut _35: bool; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 scope 1 { - debug one => _12; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - debug other => _13; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + debug one => _12; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + debug other => _13; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 } scope 2 { - debug one => _17; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 - debug other => _18; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 + debug one => _17; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + debug other => _18; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 } scope 3 { - debug one => _22; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - debug other => _23; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + debug one => _22; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + debug other => _23; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 } scope 4 { - debug one => _27; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 - debug other => _28; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 + debug one => _27; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + debug other => _28; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 } bb0: { - StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 - StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 - StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 - _5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:15: 22:16 - StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:18: 22:23 - _6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:18: 22:23 - (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 - (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:24 - StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:24 - StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:23: 22:24 - _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ _35 = Ne(_34, _11); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ StorageDead(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 -+ switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:11: 23:18 + StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 + StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 + _5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:15: 21:16 + StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23 + _6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:18: 21:23 + (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 + StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 + _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 +- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ _35 = Ne(_34, _11); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ StorageDead(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 ++ switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18 } bb1: { -- _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 -- switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 +- _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 +- switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 - } - - bb2: { -+ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:25: 27:27 - StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:25: 27:27 - ((_0 as Err).0: ()) = const (); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:21: 27:28 - discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:21: 27:28 - StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:27: 27:28 - StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:6: 28:7 - StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:1: 29:2 - return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:2: 29:2 ++ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27 + StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27 +- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28 + discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28 + StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:27: 26:28 + StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 + StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 + return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 } - bb3: { -- _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:30 -- switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:21: 24:30 +- _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 +- switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 - } - - bb4: { -- _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 -- switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 +- _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34 +- switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34 - } - - bb5: { -- _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:23: 26:34 -- switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:23: 26:34 +- _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 +- switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34 - } - - bb6: { + bb2: { - StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - _12 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - _13 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - StorageLive(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 - StorageLive(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 - _15 = _12; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 - StorageLive(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 - _16 = _13; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 - _14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 - StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 - StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 - ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 - discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 - StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 - StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 - StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 + StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + _12 = (((*(_4.0: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + _13 = (((*(_4.1: &ViewportPercentageLength)) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + StorageLive(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 + StorageLive(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 + _15 = _12; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:41 + StorageLive(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 + _16 = _13; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:44: 22:49 + _14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 + StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49 + StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49 + ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50 + discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50 + StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 + StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 + StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 } - bb7: { + bb3: { - StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 - _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:14: 24:17 - StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 - _18 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:24: 24:29 - StorageLive(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 - StorageLive(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 - _20 = _17; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:41 - StorageLive(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 - _21 = _18; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:49 - _19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:38: 24:49 - StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:48: 24:49 - StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:48: 24:49 - ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:35: 24:50 - discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:35: 24:50 - StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 - StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 - StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:49: 24:50 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 + StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + _18 = (((*(_4.1: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + StorageLive(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 + StorageLive(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 + _20 = _17; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:41 + StorageLive(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 + _21 = _18; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:44: 23:49 + _19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 + StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 + StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49 + ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 + discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50 + StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 + StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 + StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 } - bb8: { + bb4: { - StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - _22 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - _23 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - StorageLive(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 - StorageLive(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 - _25 = _22; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 - StorageLive(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 - _26 = _23; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 - _24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 - StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 - StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 - ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 - discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 - StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 - StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 - StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 + StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + _22 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + _23 = (((*(_4.1: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + StorageLive(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 + StorageLive(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 + _25 = _22; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:47 + StorageLive(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 + _26 = _23; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:50: 24:55 + _24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 + StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55 + StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55 + ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56 + discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56 + StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 + StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 + StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 } - bb9: { + bb5: { - StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 - _27 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:16: 26:19 - StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 - _28 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:28: 26:33 - StorageLive(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 - StorageLive(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 - _30 = _27; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:47 - StorageLive(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 - _31 = _28; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:50: 26:55 - _29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:44: 26:55 - StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:54: 26:55 - StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:54: 26:55 - ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:39: 26:56 - discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:39: 26:56 - StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 - StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 - StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:55: 26:56 -- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 -+ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:8: 28:6 + StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + _27 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + _28 = (((*(_4.1: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + StorageLive(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 + StorageLive(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 + _30 = _27; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:47 + StorageLive(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 + _31 = _28; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:50: 25:55 + _29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 + StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 + StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55 + ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 + discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56 + StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 + StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 + StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56 +- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 ++ goto -> bb6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6 } - bb10: { + bb6: { - ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:5: 28:7 - discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:5: 28:7 - StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:6: 28:7 - StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:1: 29:2 - return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:29:2: 29:2 + ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 + discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 + StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 + StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 + return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 + } + + bb7: { -+ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 -+ switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30 ++ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 ++ switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30 } } diff --git a/src/test/mir-opt/exponential-or.rs b/src/test/mir-opt/exponential-or.rs index 1d6f7b8189..0b8be8385d 100644 --- a/src/test/mir-opt/exponential-or.rs +++ b/src/test/mir-opt/exponential-or.rs @@ -1,7 +1,5 @@ // Test that simple or-patterns don't get expanded to exponentially large CFGs -#![feature(or_patterns)] - // EMIT_MIR exponential_or.match_tuple.SimplifyCfg-initial.after.mir fn match_tuple(x: (u32, bool, Option<i32>, u32)) -> u32 { match x { diff --git a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir index 0db0f8349b..93507879a6 100644 --- a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir @@ -1,83 +1,83 @@ // MIR for `match_tuple` after SimplifyCfg-initial fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 { - debug x => _1; // in scope 0 at $DIR/exponential-or.rs:6:16: 6:17 - let mut _0: u32; // return place in scope 0 at $DIR/exponential-or.rs:6:53: 6:56 - let mut _2: isize; // in scope 0 at $DIR/exponential-or.rs:8:37: 8:48 - let mut _3: bool; // in scope 0 at $DIR/exponential-or.rs:8:70: 8:77 - let mut _4: bool; // in scope 0 at $DIR/exponential-or.rs:8:70: 8:77 - let mut _5: bool; // in scope 0 at $DIR/exponential-or.rs:8:62: 8:67 - let mut _6: bool; // in scope 0 at $DIR/exponential-or.rs:8:62: 8:67 - let _7: u32; // in scope 0 at $DIR/exponential-or.rs:8:10: 8:21 - let _8: u32; // in scope 0 at $DIR/exponential-or.rs:8:57: 8:78 - let mut _9: u32; // in scope 0 at $DIR/exponential-or.rs:8:83: 8:84 - let mut _10: u32; // in scope 0 at $DIR/exponential-or.rs:8:87: 8:88 + debug x => _1; // in scope 0 at $DIR/exponential-or.rs:4:16: 4:17 + let mut _0: u32; // return place in scope 0 at $DIR/exponential-or.rs:4:53: 4:56 + let mut _2: isize; // in scope 0 at $DIR/exponential-or.rs:6:37: 6:48 + let mut _3: bool; // in scope 0 at $DIR/exponential-or.rs:6:70: 6:77 + let mut _4: bool; // in scope 0 at $DIR/exponential-or.rs:6:70: 6:77 + let mut _5: bool; // in scope 0 at $DIR/exponential-or.rs:6:62: 6:67 + let mut _6: bool; // in scope 0 at $DIR/exponential-or.rs:6:62: 6:67 + let _7: u32; // in scope 0 at $DIR/exponential-or.rs:6:10: 6:21 + let _8: u32; // in scope 0 at $DIR/exponential-or.rs:6:57: 6:78 + let mut _9: u32; // in scope 0 at $DIR/exponential-or.rs:6:83: 6:84 + let mut _10: u32; // in scope 0 at $DIR/exponential-or.rs:6:87: 6:88 scope 1 { - debug y => _7; // in scope 1 at $DIR/exponential-or.rs:8:10: 8:21 - debug z => _8; // in scope 1 at $DIR/exponential-or.rs:8:57: 8:78 + debug y => _7; // in scope 1 at $DIR/exponential-or.rs:6:10: 6:21 + debug z => _8; // in scope 1 at $DIR/exponential-or.rs:6:57: 6:78 } bb0: { - FakeRead(ForMatchedPlace, _1); // scope 0 at $DIR/exponential-or.rs:7:11: 7:12 - switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:8:15: 8:16 + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential-or.rs:5:11: 5:12 + switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:15: 6:16 } bb1: { - _0 = const 0_u32; // scope 0 at $DIR/exponential-or.rs:9:14: 9:15 - goto -> bb10; // scope 0 at $DIR/exponential-or.rs:7:5: 10:6 + _0 = const 0_u32; // scope 0 at $DIR/exponential-or.rs:7:14: 7:15 + goto -> bb10; // scope 0 at $DIR/exponential-or.rs:5:5: 8:6 } bb2: { - _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential-or.rs:8:37: 8:48 - switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:8:37: 8:48 + _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential-or.rs:6:37: 6:48 + switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:37: 6:48 } bb3: { - switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:8:42: 8:43 + switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:42: 6:43 } bb4: { - _5 = Le(const 6_u32, (_1.3: u32)); // scope 0 at $DIR/exponential-or.rs:8:62: 8:67 - switchInt(move _5) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential-or.rs:8:62: 8:67 + _5 = Le(const 6_u32, (_1.3: u32)); // scope 0 at $DIR/exponential-or.rs:6:62: 6:67 + switchInt(move _5) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential-or.rs:6:62: 6:67 } bb5: { - _6 = Le((_1.3: u32), const 9_u32); // scope 0 at $DIR/exponential-or.rs:8:62: 8:67 - switchInt(move _6) -> [false: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential-or.rs:8:62: 8:67 + _6 = Le((_1.3: u32), const 9_u32); // scope 0 at $DIR/exponential-or.rs:6:62: 6:67 + switchInt(move _6) -> [false: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential-or.rs:6:62: 6:67 } bb6: { - _3 = Le(const 13_u32, (_1.3: u32)); // scope 0 at $DIR/exponential-or.rs:8:70: 8:77 - switchInt(move _3) -> [false: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential-or.rs:8:70: 8:77 + _3 = Le(const 13_u32, (_1.3: u32)); // scope 0 at $DIR/exponential-or.rs:6:70: 6:77 + switchInt(move _3) -> [false: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential-or.rs:6:70: 6:77 } bb7: { - _4 = Le((_1.3: u32), const 16_u32); // scope 0 at $DIR/exponential-or.rs:8:70: 8:77 - switchInt(move _4) -> [false: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential-or.rs:8:70: 8:77 + _4 = Le((_1.3: u32), const 16_u32); // scope 0 at $DIR/exponential-or.rs:6:70: 6:77 + switchInt(move _4) -> [false: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential-or.rs:6:70: 6:77 } bb8: { - falseEdge -> [real: bb9, imaginary: bb1]; // scope 0 at $DIR/exponential-or.rs:8:9: 8:79 + falseEdge -> [real: bb9, imaginary: bb1]; // scope 0 at $DIR/exponential-or.rs:6:9: 6:79 } bb9: { - StorageLive(_7); // scope 0 at $DIR/exponential-or.rs:8:10: 8:21 - _7 = (_1.0: u32); // scope 0 at $DIR/exponential-or.rs:8:10: 8:21 - StorageLive(_8); // scope 0 at $DIR/exponential-or.rs:8:57: 8:78 - _8 = (_1.3: u32); // scope 0 at $DIR/exponential-or.rs:8:57: 8:78 - StorageLive(_9); // scope 1 at $DIR/exponential-or.rs:8:83: 8:84 - _9 = _7; // scope 1 at $DIR/exponential-or.rs:8:83: 8:84 - StorageLive(_10); // scope 1 at $DIR/exponential-or.rs:8:87: 8:88 - _10 = _8; // scope 1 at $DIR/exponential-or.rs:8:87: 8:88 - _0 = BitXor(move _9, move _10); // scope 1 at $DIR/exponential-or.rs:8:83: 8:88 - StorageDead(_10); // scope 1 at $DIR/exponential-or.rs:8:87: 8:88 - StorageDead(_9); // scope 1 at $DIR/exponential-or.rs:8:87: 8:88 - StorageDead(_8); // scope 0 at $DIR/exponential-or.rs:8:87: 8:88 - StorageDead(_7); // scope 0 at $DIR/exponential-or.rs:8:87: 8:88 - goto -> bb10; // scope 0 at $DIR/exponential-or.rs:7:5: 10:6 + StorageLive(_7); // scope 0 at $DIR/exponential-or.rs:6:10: 6:21 + _7 = (_1.0: u32); // scope 0 at $DIR/exponential-or.rs:6:10: 6:21 + StorageLive(_8); // scope 0 at $DIR/exponential-or.rs:6:57: 6:78 + _8 = (_1.3: u32); // scope 0 at $DIR/exponential-or.rs:6:57: 6:78 + StorageLive(_9); // scope 1 at $DIR/exponential-or.rs:6:83: 6:84 + _9 = _7; // scope 1 at $DIR/exponential-or.rs:6:83: 6:84 + StorageLive(_10); // scope 1 at $DIR/exponential-or.rs:6:87: 6:88 + _10 = _8; // scope 1 at $DIR/exponential-or.rs:6:87: 6:88 + _0 = BitXor(move _9, move _10); // scope 1 at $DIR/exponential-or.rs:6:83: 6:88 + StorageDead(_10); // scope 1 at $DIR/exponential-or.rs:6:87: 6:88 + StorageDead(_9); // scope 1 at $DIR/exponential-or.rs:6:87: 6:88 + StorageDead(_8); // scope 0 at $DIR/exponential-or.rs:6:87: 6:88 + StorageDead(_7); // scope 0 at $DIR/exponential-or.rs:6:87: 6:88 + goto -> bb10; // scope 0 at $DIR/exponential-or.rs:5:5: 8:6 } bb10: { - return; // scope 0 at $DIR/exponential-or.rs:11:2: 11:2 + return; // scope 0 at $DIR/exponential-or.rs:9:2: 9:2 } } diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index caa02abf01..3a50ed224b 100644 --- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -51,7 +51,7 @@ } bb2: { - discriminant(_6) = 2; // scope 1 at $DIR/funky_arms.rs:21:17: 21:41 + discriminant(_6) = 1; // scope 1 at $DIR/funky_arms.rs:21:17: 21:41 goto -> bb4; // scope 1 at $DIR/funky_arms.rs:19:16: 22:6 } diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index b9fe84fcd0..1aabee83be 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -35,10 +35,10 @@ fn bar() -> bool { _10 = const bar::promoted[1]; // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[1])) + // + val: Unevaluated(bar, [], Some(promoted[1])) // mir::Constant // + span: $DIR/inline-retag.rs:12:7: 12:9 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[1])) } + // + 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]) }) } 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 @@ -49,10 +49,10 @@ fn bar() -> bool { _9 = const bar::promoted[0]; // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(bar, [], Some(promoted[0])) // mir::Constant // + span: $DIR/inline-retag.rs:12:11: 12:14 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } 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 diff --git a/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index e5ce03a453..d62f78eaa3 100644 --- a/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -28,7 +28,6 @@ fn main() -> () { StorageLive(_5); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 _5 = move (_3.0: ()); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 StorageLive(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 - _6 = const (); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 StorageDead(_6); // scope 2 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 StorageDead(_5); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:5: 6:10 StorageDead(_4); // scope 1 at $DIR/issue-76997-inline-scopes-parenting.rs:6:9: 6:10 diff --git a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir index e9e5a101a6..8355b2d195 100644 --- a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir @@ -14,7 +14,7 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/issue-38669.rs:5:9: 5:25 _1 = const false; // scope 0 at $DIR/issue-38669.rs:5:28: 5:33 - FakeRead(ForLet, _1); // scope 0 at $DIR/issue-38669.rs:5:9: 5:25 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/issue-38669.rs:5:9: 5:25 goto -> bb1; // scope 1 at $DIR/issue-38669.rs:6:5: 11:6 } diff --git a/src/test/mir-opt/issue_49232.main.mir_map.0.mir b/src/test/mir-opt/issue_49232.main.mir_map.0.mir index 79f5495c78..06fbbda3d9 100644 --- a/src/test/mir-opt/issue_49232.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_49232.main.mir_map.0.mir @@ -24,7 +24,7 @@ fn main() -> () { StorageLive(_2); // scope 0 at $DIR/issue-49232.rs:7:13: 7:19 StorageLive(_3); // scope 0 at $DIR/issue-49232.rs:8:19: 8:23 _3 = const true; // scope 0 at $DIR/issue-49232.rs:8:19: 8:23 - FakeRead(ForMatchedPlace, _3); // scope 0 at $DIR/issue-49232.rs:8:19: 8:23 + FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue-49232.rs:8:19: 8:23 switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue-49232.rs:9:17: 9:22 } @@ -51,7 +51,7 @@ fn main() -> () { } bb8: { - FakeRead(ForLet, _2); // scope 0 at $DIR/issue-49232.rs:7:13: 7:19 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-49232.rs:7:13: 7:19 StorageDead(_3); // scope 0 at $DIR/issue-49232.rs:12:10: 12:11 StorageLive(_5); // scope 1 at $DIR/issue-49232.rs:13:9: 13:22 StorageLive(_6); // scope 1 at $DIR/issue-49232.rs:13:14: 13:21 diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir index cf66a501e3..2e6783b7f3 100644 --- a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir +++ b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir @@ -38,7 +38,7 @@ fn main() -> () { _2 = [move _3, move _4]; // scope 1 at $DIR/issue-72181.rs:26:13: 26:43 StorageDead(_4); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 StorageDead(_3); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 - FakeRead(ForLet, _2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + FakeRead(ForLet(None), _2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 StorageLive(_5); // scope 2 at $DIR/issue-72181.rs:27:13: 27:30 StorageLive(_6); // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 _6 = const 0_usize; // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir index cf66a501e3..2e6783b7f3 100644 --- a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir +++ b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir @@ -38,7 +38,7 @@ fn main() -> () { _2 = [move _3, move _4]; // scope 1 at $DIR/issue-72181.rs:26:13: 26:43 StorageDead(_4); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 StorageDead(_3); // scope 1 at $DIR/issue-72181.rs:26:42: 26:43 - FakeRead(ForLet, _2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 + FakeRead(ForLet(None), _2); // scope 1 at $DIR/issue-72181.rs:26:9: 26:10 StorageLive(_5); // scope 2 at $DIR/issue-72181.rs:27:13: 27:30 StorageLive(_6); // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 _6 = const 0_usize; // scope 4 at $DIR/issue-72181.rs:27:24: 27:25 diff --git a/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir index 7571d7bb94..7def08ece2 100644 --- a/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir +++ b/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir @@ -9,7 +9,7 @@ fn f(_1: Void) -> ! { bb0: { StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2 StorageLive(_3); // scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15 - FakeRead(ForMatchedPlace, _1); // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12 + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12 unreachable; // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12 } diff --git a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir index 1fd91c2056..3c26b20c35 100644 --- a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir @@ -29,7 +29,7 @@ fn main() -> () { bb1: { StorageDead(_3); // scope 2 at $DIR/issue-72181-1.rs:17:43: 17:44 - FakeRead(ForLet, _2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10 AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-72181-1.rs:16:12: 16:16 StorageLive(_4); // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9 StorageLive(_5); // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8 diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff index f6e6614bb6..95a8ef997f 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -63,10 +63,10 @@ _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index f6e6614bb6..95a8ef997f 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -63,10 +63,10 @@ _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff index bd24522271..261eb3b27e 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff @@ -58,7 +58,7 @@ } bb1: { - _0 = const (); // scope 0 at $DIR/issue-73223.rs:4:17: 4:23 + nop; // scope 0 at $DIR/issue-73223.rs:4:17: 4:23 StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 @@ -84,10 +84,10 @@ _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 @@ -146,13 +146,13 @@ } bb4: { - _8 = const (); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_14); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_13); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 + nop; // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2 StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index bd24522271..261eb3b27e 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -58,7 +58,7 @@ } bb1: { - _0 = const (); // scope 0 at $DIR/issue-73223.rs:4:17: 4:23 + nop; // scope 0 at $DIR/issue-73223.rs:4:17: 4:23 StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 @@ -84,10 +84,10 @@ _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 @@ -146,13 +146,13 @@ } bb4: { - _8 = const (); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_14); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_13); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 + nop; // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2 StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index 7913ad260e..1fa324c33d 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -107,7 +107,7 @@ StorageDead(_14); // scope 1 at $DIR/issue_76432.rs:9:84: 9:85 StorageDead(_13); // scope 1 at $DIR/issue_76432.rs:9:84: 9:85 StorageDead(_9); // scope 1 at $DIR/issue_76432.rs:11:6: 11:7 - _0 = const (); // scope 0 at $DIR/issue_76432.rs:6:44: 12:2 + nop; // scope 0 at $DIR/issue_76432.rs:6:44: 12:2 StorageDead(_5); // scope 0 at $DIR/issue_76432.rs:12:1: 12:2 StorageDead(_2); // scope 0 at $DIR/issue_76432.rs:12:1: 12:2 return; // scope 0 at $DIR/issue_76432.rs:12:2: 12:2 diff --git a/src/test/mir-opt/issues/issue-75439.rs b/src/test/mir-opt/issues/issue-75439.rs index 44d6bc619d..b914055813 100644 --- a/src/test/mir-opt/issues/issue-75439.rs +++ b/src/test/mir-opt/issues/issue-75439.rs @@ -1,7 +1,6 @@ // EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff #![feature(const_fn_transmute)] -#![feature(or_patterns)] use std::mem::transmute; diff --git a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 43422b36e1..d5edf16525 100644 --- a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -2,17 +2,17 @@ + // MIR for `foo` after MatchBranchSimplification fn foo(_1: [u8; 16]) -> Option<[u8; 4]> { - debug bytes => _1; // in scope 0 at $DIR/issue-75439.rs:8:12: 8:17 - let mut _0: std::option::Option<[u8; 4]>; // return place in scope 0 at $DIR/issue-75439.rs:8:32: 8:47 - let _2: [u32; 4]; // in scope 0 at $DIR/issue-75439.rs:10:9: 10:15 - let mut _3: [u8; 16]; // in scope 0 at $DIR/issue-75439.rs:10:47: 10:52 - let mut _5: [u8; 4]; // in scope 0 at $DIR/issue-75439.rs:13:14: 13:38 - let mut _6: u32; // in scope 0 at $DIR/issue-75439.rs:13:33: 13:35 + debug bytes => _1; // in scope 0 at $DIR/issue-75439.rs:7:12: 7:17 + let mut _0: std::option::Option<[u8; 4]>; // return place in scope 0 at $DIR/issue-75439.rs:7:32: 7:47 + let _2: [u32; 4]; // in scope 0 at $DIR/issue-75439.rs:9:9: 9:15 + let mut _3: [u8; 16]; // in scope 0 at $DIR/issue-75439.rs:9:47: 9:52 + let mut _5: [u8; 4]; // in scope 0 at $DIR/issue-75439.rs:12:14: 12:38 + let mut _6: u32; // in scope 0 at $DIR/issue-75439.rs:12:33: 12:35 scope 1 { - debug dwords => _2; // in scope 1 at $DIR/issue-75439.rs:10:9: 10:15 - let _4: u32; // in scope 1 at $DIR/issue-75439.rs:12:27: 12:29 + debug dwords => _2; // in scope 1 at $DIR/issue-75439.rs:9:9: 9:15 + let _4: u32; // in scope 1 at $DIR/issue-75439.rs:11:27: 11:29 scope 3 { - debug ip => _4; // in scope 3 at $DIR/issue-75439.rs:12:27: 12:29 + debug ip => _4; // in scope 3 at $DIR/issue-75439.rs:11:27: 11:29 scope 4 { } } @@ -21,67 +21,67 @@ } bb0: { - StorageLive(_2); // scope 0 at $DIR/issue-75439.rs:10:9: 10:15 - StorageLive(_3); // scope 2 at $DIR/issue-75439.rs:10:47: 10:52 - _3 = _1; // scope 2 at $DIR/issue-75439.rs:10:47: 10:52 - _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue-75439.rs:10:37: 10:53 + StorageLive(_2); // scope 0 at $DIR/issue-75439.rs:9:9: 9:15 + StorageLive(_3); // scope 2 at $DIR/issue-75439.rs:9:47: 9:52 + _3 = _1; // scope 2 at $DIR/issue-75439.rs:9:47: 9:52 + _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue-75439.rs:9:37: 9:53 // mir::Constant - // + span: $DIR/issue-75439.rs:10:37: 10:46 + // + span: $DIR/issue-75439.rs:9:37: 9:46 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {std::intrinsics::transmute::<[u8; 16], [u32; 4]>}, val: Value(Scalar(<ZST>)) } } bb1: { - StorageDead(_3); // scope 2 at $DIR/issue-75439.rs:10:52: 10:53 - switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:13: 12:14 + StorageDead(_3); // scope 2 at $DIR/issue-75439.rs:9:52: 9:53 + switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:11:13: 11:14 } bb2: { - switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:16: 12:17 + switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:11:16: 11:17 } bb3: { - switchInt(_2[2 of 4]) -> [0_u32: bb6, 4294901760_u32: bb7, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:19: 12:20 + switchInt(_2[2 of 4]) -> [0_u32: bb6, 4294901760_u32: bb7, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:11:19: 11:20 } bb4: { - discriminant(_0) = 0; // scope 1 at $DIR/issue-75439.rs:15:9: 15:13 - goto -> bb9; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + discriminant(_0) = 0; // scope 1 at $DIR/issue-75439.rs:14:9: 14:13 + goto -> bb9; // scope 1 at $DIR/issue-75439.rs:11:5: 15:6 } bb5: { - StorageLive(_5); // scope 3 at $DIR/issue-75439.rs:13:14: 13:38 - StorageLive(_6); // scope 4 at $DIR/issue-75439.rs:13:33: 13:35 - _6 = _4; // scope 4 at $DIR/issue-75439.rs:13:33: 13:35 - _5 = transmute::<u32, [u8; 4]>(move _6) -> bb8; // scope 4 at $DIR/issue-75439.rs:13:23: 13:36 + StorageLive(_5); // scope 3 at $DIR/issue-75439.rs:12:14: 12:38 + StorageLive(_6); // scope 4 at $DIR/issue-75439.rs:12:33: 12:35 + _6 = _4; // scope 4 at $DIR/issue-75439.rs:12:33: 12:35 + _5 = transmute::<u32, [u8; 4]>(move _6) -> bb8; // scope 4 at $DIR/issue-75439.rs:12:23: 12:36 // mir::Constant - // + span: $DIR/issue-75439.rs:13:23: 13:32 + // + span: $DIR/issue-75439.rs:12:23: 12:32 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {std::intrinsics::transmute::<u32, [u8; 4]>}, val: Value(Scalar(<ZST>)) } } bb6: { - StorageLive(_4); // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 - _4 = _2[3 of 4]; // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 - goto -> bb5; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + StorageLive(_4); // scope 1 at $DIR/issue-75439.rs:11:27: 11:29 + _4 = _2[3 of 4]; // scope 1 at $DIR/issue-75439.rs:11:27: 11:29 + goto -> bb5; // scope 1 at $DIR/issue-75439.rs:11:5: 15:6 } bb7: { - StorageLive(_4); // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 - _4 = _2[3 of 4]; // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 - goto -> bb5; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + StorageLive(_4); // scope 1 at $DIR/issue-75439.rs:11:27: 11:29 + _4 = _2[3 of 4]; // scope 1 at $DIR/issue-75439.rs:11:27: 11:29 + goto -> bb5; // scope 1 at $DIR/issue-75439.rs:11:5: 15:6 } bb8: { - StorageDead(_6); // scope 4 at $DIR/issue-75439.rs:13:35: 13:36 - ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue-75439.rs:13:9: 13:39 - discriminant(_0) = 1; // scope 3 at $DIR/issue-75439.rs:13:9: 13:39 - StorageDead(_5); // scope 3 at $DIR/issue-75439.rs:13:38: 13:39 - StorageDead(_4); // scope 1 at $DIR/issue-75439.rs:14:5: 14:6 - goto -> bb9; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + StorageDead(_6); // scope 4 at $DIR/issue-75439.rs:12:35: 12:36 + ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue-75439.rs:12:9: 12:39 + discriminant(_0) = 1; // scope 3 at $DIR/issue-75439.rs:12:9: 12:39 + StorageDead(_5); // scope 3 at $DIR/issue-75439.rs:12:38: 12:39 + StorageDead(_4); // scope 1 at $DIR/issue-75439.rs:13:5: 13:6 + goto -> bb9; // scope 1 at $DIR/issue-75439.rs:11:5: 15:6 } bb9: { - StorageDead(_2); // scope 0 at $DIR/issue-75439.rs:17:1: 17:2 - return; // scope 0 at $DIR/issue-75439.rs:17:2: 17:2 + StorageDead(_2); // scope 0 at $DIR/issue-75439.rs:16:1: 16:2 + return; // scope 0 at $DIR/issue-75439.rs:16:2: 16:2 } } diff --git a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir index f109937dbf..99c7ac8d5b 100644 --- a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir +++ b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir @@ -41,7 +41,7 @@ fn main() -> () { bb4: { StorageLive(_6); // scope 0 at $DIR/loop_test.rs:14:13: 14:14 _6 = const 1_i32; // scope 0 at $DIR/loop_test.rs:14:17: 14:18 - FakeRead(ForLet, _6); // scope 0 at $DIR/loop_test.rs:14:13: 14:14 + FakeRead(ForLet(None), _6); // scope 0 at $DIR/loop_test.rs:14:13: 14:14 StorageDead(_6); // scope 0 at $DIR/loop_test.rs:16:5: 16:6 goto -> bb3; // scope 0 at $DIR/loop_test.rs:1:1: 1:1 } diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index 7da2ff0200..a37df4da9a 100644 --- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -47,10 +47,10 @@ _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[2])) + // + val: Unevaluated(discriminant, [T], Some(promoted[2])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:70:42: 70:44 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[2])) } + // + 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]) }) } _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 @@ -71,10 +71,10 @@ _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 // ty::Const // + ty: &() - // + val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[1])) + // + val: Unevaluated(discriminant, [T], Some(promoted[1])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:71:42: 71:45 - // + literal: Const { ty: &(), val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[1])) } + // + 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]) }) } _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 @@ -95,10 +95,10 @@ _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 // ty::Const // + ty: &E - // + val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[0])) + // + val: Unevaluated(discriminant, [T], Some(promoted[0])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:72:42: 72:47 - // + literal: Const { ty: &E, val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[0])) } + // + 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]) }) } _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/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 95beab2ec9..3395cbfbdf 100644 --- a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -31,7 +31,7 @@ } bb0: { -- FakeRead(ForMatchedPlace, _2); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 +- FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 - switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15 + switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15 } diff --git a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir index 2332e5beaf..5af242376c 100644 --- a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir +++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir @@ -27,7 +27,7 @@ fn full_tested_match() -> () { StorageLive(_1); // scope 0 at $DIR/match_false_edges.rs:15:13: 19:6 StorageLive(_2); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27 _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27 - FakeRead(ForMatchedPlace, _2); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27 + FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27 _3 = discriminant(_2); // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16 switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16 } @@ -54,10 +54,10 @@ fn full_tested_match() -> () { _11 = const full_tested_match::promoted[0]; // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15 // ty::Const // + ty: &std::option::Option<i32> - // + val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, [], Some(promoted[0])) + // + 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(WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } _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 diff --git a/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir index c7b1cce061..a4ebf8a024 100644 --- a/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir +++ b/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir @@ -26,7 +26,7 @@ fn full_tested_match2() -> () { StorageLive(_1); // scope 0 at $DIR/match_false_edges.rs:26:13: 30:6 StorageLive(_2); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27 _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27 - FakeRead(ForMatchedPlace, _2); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27 + FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27 _3 = discriminant(_2); // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16 switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16 } diff --git a/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir index 9b8ce2c1ed..5de52b324f 100644 --- a/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir +++ b/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir @@ -37,7 +37,7 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/match_false_edges.rs:35:13: 40:6 StorageLive(_2); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26 _2 = Option::<i32>::Some(const 1_i32); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26 - FakeRead(ForMatchedPlace, _2); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26 + FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26 _4 = discriminant(_2); // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17 switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17 } diff --git a/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir index e3bc4f80f2..5bb910947c 100644 --- a/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir @@ -21,12 +21,12 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/match_test.rs:7:9: 7:10 _1 = const 3_i32; // scope 0 at $DIR/match_test.rs:7:13: 7:14 - FakeRead(ForLet, _1); // scope 0 at $DIR/match_test.rs:7:9: 7:10 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/match_test.rs:7:9: 7:10 StorageLive(_2); // scope 1 at $DIR/match_test.rs:8:9: 8:10 _2 = const true; // scope 1 at $DIR/match_test.rs:8:13: 8:17 - FakeRead(ForLet, _2); // scope 1 at $DIR/match_test.rs:8:9: 8:10 + FakeRead(ForLet(None), _2); // scope 1 at $DIR/match_test.rs:8:9: 8:10 StorageLive(_3); // scope 2 at $DIR/match_test.rs:12:5: 17:6 - FakeRead(ForMatchedPlace, _1); // scope 2 at $DIR/match_test.rs:12:11: 12:12 + FakeRead(ForMatchedPlace(None), _1); // scope 2 at $DIR/match_test.rs:12:11: 12:12 _6 = Le(const 0_i32, _1); // scope 2 at $DIR/match_test.rs:13:9: 13:14 switchInt(move _6) -> [false: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:13:9: 13:14 } diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff index 9f0db1db1b..96b03477d0 100644 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff @@ -13,7 +13,7 @@ - } - - bb1: { -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:8:5: 10:6 +- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb2: { diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff index 9f0db1db1b..96b03477d0 100644 --- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff @@ -13,7 +13,7 @@ - } - - bb1: { -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:8:5: 10:6 +- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb2: { diff --git a/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff b/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff index 3dd526cfbc..dbcb8813d5 100644 --- a/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff +++ b/src/test/mir-opt/multiple_return_terminators.test.MultipleReturnTerminators.diff @@ -4,24 +4,8 @@ fn test(_1: bool) -> () { debug x => _1; // in scope 0 at $DIR/multiple_return_terminators.rs:4:9: 4:10 let mut _0: (); // return place in scope 0 at $DIR/multiple_return_terminators.rs:4:18: 4:18 - let mut _2: bool; // in scope 0 at $DIR/multiple_return_terminators.rs:5:8: 5:9 bb0: { - StorageLive(_2); // scope 0 at $DIR/multiple_return_terminators.rs:5:8: 5:9 - _2 = _1; // scope 0 at $DIR/multiple_return_terminators.rs:5:8: 5:9 - switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6 - } - - bb1: { - goto -> bb3; // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6 - } - - bb2: { - goto -> bb3; // scope 0 at $DIR/multiple_return_terminators.rs:5:5: 9:6 - } - - bb3: { - StorageDead(_2); // scope 0 at $DIR/multiple_return_terminators.rs:9:5: 9:6 return; // scope 0 at $DIR/multiple_return_terminators.rs:10:2: 10:2 } } diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index 8c939d5fc3..39e6cee11b 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -46,7 +46,7 @@ fn main() -> () { bb0: { StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 _1 = [const Const(Value(Scalar(0x00000001)): usize), const Const(Value(Scalar(0x00000002)): usize), const Const(Value(Scalar(0x00000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26 - FakeRead(ForLet, _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 + FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 _3 = const Const(Value(Scalar(0x00000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 @@ -57,10 +57,10 @@ fn main() -> () { bb1: { _2 = &'_#3r _1[_3]; // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:18:13: 18:18 - FakeRead(ForLet, _2); // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 + FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 StorageLive(_6); // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 _6 = _2; // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14 - FakeRead(ForLet, _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 + FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6 diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 00704baa6c..6021b6529f 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -46,7 +46,7 @@ fn main() -> () { bb0: { StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 _1 = [const Const(Value(Scalar(0x0000000000000001)): usize), const Const(Value(Scalar(0x0000000000000002)): usize), const Const(Value(Scalar(0x0000000000000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26 - FakeRead(ForLet, _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 + FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 _3 = const Const(Value(Scalar(0x0000000000000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 @@ -57,10 +57,10 @@ fn main() -> () { bb1: { _2 = &'_#3r _1[_3]; // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:18:13: 18:18 - FakeRead(ForLet, _2); // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 + FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 StorageLive(_6); // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 _6 = _2; // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14 - FakeRead(ForLet, _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 + FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6 diff --git a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir index d2d96ff468..f54c8f8ab4 100644 --- a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir +++ b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir @@ -36,7 +36,7 @@ fn main() -> () { } bb1: { - FakeRead(ForLet, _1); // scope 0 at $DIR/receiver-ptr-mutability.rs:14:9: 14:12 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/receiver-ptr-mutability.rs:14:9: 14:12 AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/receiver-ptr-mutability.rs:14:14: 14:23 StorageLive(_2); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12 StorageLive(_3); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8 @@ -63,7 +63,7 @@ fn main() -> () { _7 = &_8; // scope 1 at $DIR/receiver-ptr-mutability.rs:18:35: 18:41 _6 = &_7; // scope 1 at $DIR/receiver-ptr-mutability.rs:18:34: 18:41 _5 = &(*_6); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:34: 18:41 - FakeRead(ForLet, _5); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:9: 18:16 + FakeRead(ForLet(None), _5); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:9: 18:16 AscribeUserType(_5, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:18: 18:31 StorageDead(_6); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:41: 18:42 StorageLive(_10); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 diff --git a/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff index 47027311b4..4aa388fc67 100644 --- a/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff +++ b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff @@ -13,7 +13,7 @@ let mut _8: bool; // in scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21 bb0: { -- FakeRead(ForMatchedPlace, _1); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 +- FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 + nop; // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 _3 = discriminant(_1); // scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16 switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16 diff --git a/src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff index 2fc64fa8f5..8793af5c07 100644 --- a/src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff +++ b/src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff @@ -14,6 +14,7 @@ StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:21:5: 21:12 StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:21:10: 21:11 _3 = move _1; // scope 0 at $DIR/remove_unneeded_drops.rs:21:10: 21:11 + nop; // scope 1 at $DIR/remove_unneeded_drops.rs:21:5: 21:12 drop(_3) -> [return: bb2, unwind: bb1]; // scope 1 at $DIR/remove_unneeded_drops.rs:21:5: 21:12 } @@ -24,7 +25,7 @@ bb2: { StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:21:11: 21:12 StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:21:12: 21:13 - _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:20:32: 22:2 + nop; // scope 0 at $DIR/remove_unneeded_drops.rs:20:32: 22:2 return; // scope 0 at $DIR/remove_unneeded_drops.rs:22:2: 22:2 } } diff --git a/src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff index 18fdac1bc0..2377abdb15 100644 --- a/src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff +++ b/src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff @@ -14,6 +14,7 @@ StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:9:5: 9:12 StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:9:10: 9:11 _3 = move _1; // scope 0 at $DIR/remove_unneeded_drops.rs:9:10: 9:11 + nop; // scope 1 at $DIR/remove_unneeded_drops.rs:9:5: 9:12 drop(_3) -> [return: bb2, unwind: bb1]; // scope 1 at $DIR/remove_unneeded_drops.rs:9:5: 9:12 } @@ -24,7 +25,7 @@ bb2: { StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:9:11: 9:12 StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:9:12: 9:13 - _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:8:27: 10:2 + nop; // scope 0 at $DIR/remove_unneeded_drops.rs:8:27: 10:2 return; // scope 0 at $DIR/remove_unneeded_drops.rs:10:2: 10:2 } } diff --git a/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff index 1eb3d73676..75bd732e3c 100644 --- a/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff +++ b/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff @@ -14,13 +14,14 @@ StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:4:5: 4:12 StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:4:10: 4:11 _3 = _1; // scope 0 at $DIR/remove_unneeded_drops.rs:4:10: 4:11 +- nop; // scope 1 at $DIR/remove_unneeded_drops.rs:4:5: 4:12 - drop(_3) -> bb1; // scope 1 at $DIR/remove_unneeded_drops.rs:4:5: 4:12 - } - - bb1: { StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:4:11: 4:12 StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:4:12: 4:13 - _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:3:17: 5:2 +- nop; // scope 0 at $DIR/remove_unneeded_drops.rs:3:17: 5:2 return; // scope 0 at $DIR/remove_unneeded_drops.rs:5:2: 5:2 } } diff --git a/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff index 9b8a50e854..b3da2cfb24 100644 --- a/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff +++ b/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff @@ -14,13 +14,14 @@ StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:14:5: 14:12 StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:14:10: 14:11 _3 = _1; // scope 0 at $DIR/remove_unneeded_drops.rs:14:10: 14:11 +- nop; // scope 1 at $DIR/remove_unneeded_drops.rs:14:5: 14:12 - drop(_3) -> bb1; // scope 1 at $DIR/remove_unneeded_drops.rs:14:5: 14:12 - } - - bb1: { StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:14:11: 14:12 StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:14:12: 14:13 - _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:13:36: 15:2 +- nop; // scope 0 at $DIR/remove_unneeded_drops.rs:13:36: 15:2 return; // scope 0 at $DIR/remove_unneeded_drops.rs:15:2: 15:2 } } diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir b/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir new file mode 100644 index 0000000000..33bd9eb9b1 --- /dev/null +++ b/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir @@ -0,0 +1,13 @@ +// MIR for `get_union` after RemoveZsts + +fn get_union() -> Foo { + let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:12:19: 12:22 + let mut _1: (); // in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:13:14: 13:16 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:13:14: 13:16 + (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:13:5: 13:18 + StorageDead(_1); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:13:17: 13:18 + return; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:14:2: 14:2 + } +} diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.rs b/src/test/mir-opt/remove_zsts_dont_touch_unions.rs new file mode 100644 index 0000000000..7a6f86b808 --- /dev/null +++ b/src/test/mir-opt/remove_zsts_dont_touch_unions.rs @@ -0,0 +1,19 @@ +// compile-flags: -Zmir-opt-level=3 + +// Ensure RemoveZsts doesn't remove ZST assignments to union fields, +// which causes problems in Miri. + +union Foo { + x: (), + y: u64, +} + +// EMIT_MIR remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir +fn get_union() -> Foo { + Foo { x: () } +} + + +fn main() { + get_union(); +} diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 8c7d79262b..894f64c776 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -149,10 +149,10 @@ fn main() -> () { _27 = const main::promoted[0]; // scope 7 at $DIR/retag.rs:47:21: 47:23 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/retag.rs:47:21: 47:23 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + 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]) }) } Retag(_27); // scope 7 at $DIR/retag.rs:47:21: 47:23 _23 = &(*_27); // scope 7 at $DIR/retag.rs:47:21: 47:23 Retag(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23 diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir index 5bcb20ca72..841cca7c38 100644 --- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir +++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir @@ -5,7 +5,7 @@ fn match_bool(_1: bool) -> usize { let mut _0: usize; // return place in scope 0 at $DIR/simple-match.rs:5:27: 5:32 bb0: { - FakeRead(ForMatchedPlace, _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12 + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12 switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13 } diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir index 5bcb20ca72..841cca7c38 100644 --- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir +++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir @@ -5,7 +5,7 @@ fn match_bool(_1: bool) -> usize { let mut _0: usize; // return place in scope 0 at $DIR/simple-match.rs:5:27: 5:32 bb0: { - FakeRead(ForMatchedPlace, _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12 + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12 switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13 } diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff index adcda7fcde..7495b0d407 100644 --- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff @@ -50,7 +50,7 @@ bb4: { StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7 - _0 = const (); // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 + nop; // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:23:1: 23:2 return; // scope 0 at $DIR/simplify-arm-identity.rs:23:2: 23:2 } diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff index adcda7fcde..7495b0d407 100644 --- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff @@ -50,7 +50,7 @@ bb4: { StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7 - _0 = const (); // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 + nop; // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:23:1: 23:2 return; // scope 0 at $DIR/simplify-arm-identity.rs:23:2: 23:2 } diff --git a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff index 2cd57cb847..b6ce74d728 100644 --- a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff +++ b/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff @@ -22,13 +22,13 @@ } bb2: { - _0 = const (); // scope 0 at $DIR/simplify_if.rs:8:6: 8:6 + nop; // scope 0 at $DIR/simplify_if.rs:8:6: 8:6 goto -> bb4; // scope 0 at $DIR/simplify_if.rs:6:5: 8:6 } bb3: { StorageDead(_2); // scope 0 at $DIR/simplify_if.rs:7:15: 7:16 - _0 = const (); // scope 0 at $DIR/simplify_if.rs:6:14: 8:6 + nop; // scope 0 at $DIR/simplify_if.rs:6:14: 8:6 goto -> bb4; // scope 0 at $DIR/simplify_if.rs:6:5: 8:6 } diff --git a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff index ff9e2671ad..2995d1e86e 100644 --- a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff @@ -25,7 +25,6 @@ - StorageDead(_3); // scope 1 at $DIR/simplify-locals.rs:16:25: 16:26 - StorageDead(_4); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27 - StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27 -- _0 = const (); // scope 0 at $DIR/simplify-locals.rs:13:8: 17:2 StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:17:1: 17:2 return; // scope 0 at $DIR/simplify-locals.rs:17:2: 17:2 } diff --git a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff index caa2a17700..97cbf2acf0 100644 --- a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff @@ -11,7 +11,6 @@ - StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 - discriminant(_1) = 0; // scope 0 at $DIR/simplify-locals.rs:22:13: 22:17 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:22:17: 22:18 -- _0 = const (); // scope 0 at $DIR/simplify-locals.rs:20:9: 23:2 return; // scope 0 at $DIR/simplify-locals.rs:23:2: 23:2 } } diff --git a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff index 80496d9a42..1448001dd4 100644 --- a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff @@ -31,7 +31,6 @@ - // + literal: Const { ty: E, val: Value(Scalar(0x01)) } - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:28:25: 28:26 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:28:26: 28:27 -- _0 = const (); // scope 0 at $DIR/simplify-locals.rs:26:9: 29:2 return; // scope 0 at $DIR/simplify-locals.rs:29:2: 29:2 } } diff --git a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff index 7d36e1a992..cf5785438b 100644 --- a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff @@ -23,7 +23,6 @@ - StorageLive(_3); // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 - _3 = &mut _1; // scope 2 at $DIR/simplify-locals.rs:36:13: 36:19 - StorageDead(_3); // scope 2 at $DIR/simplify-locals.rs:36:19: 36:20 -- _0 = const (); // scope 0 at $DIR/simplify-locals.rs:32:8: 37:2 StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:37:1: 37:2 return; // scope 0 at $DIR/simplify-locals.rs:37:2: 37:2 } diff --git a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff index 89275418d6..54b167bc68 100644 --- a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff @@ -15,7 +15,6 @@ - _1 = (*_2); // scope 1 at $DIR/simplify-locals.rs:44:14: 44:15 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:44:17: 44:18 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:44:17: 44:18 -- _0 = const (); // scope 0 at $DIR/simplify-locals.rs:42:9: 45:2 return; // scope 0 at $DIR/simplify-locals.rs:45:2: 45:2 } } diff --git a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff index b2344c871e..06216efcec 100644 --- a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff @@ -15,7 +15,6 @@ - _1 = &mut (*_2); // scope 1 at $DIR/simplify-locals.rs:50:14: 50:20 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:50:22: 50:23 -- _0 = const (); // scope 0 at $DIR/simplify-locals.rs:48:9: 51:2 return; // scope 0 at $DIR/simplify-locals.rs:51:2: 51:2 } } diff --git a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff index 95982f0a9c..ee9d2934af 100644 --- a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff @@ -19,7 +19,6 @@ - StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 - StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 - StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:56:23: 56:24 -- _0 = const (); // scope 0 at $DIR/simplify-locals.rs:54:9: 57:2 return; // scope 0 at $DIR/simplify-locals.rs:57:2: 57:2 } } diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff index 69da1c7be8..70725e5f14 100644 --- a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff @@ -30,7 +30,7 @@ } bb1: { -- _0 = const (); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:8:6: 8:6 + _0 = const (); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:8:6: 8:6 goto -> bb7; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:5: 8:6 } @@ -51,12 +51,12 @@ } bb4: { -- _0 = const (); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:21: 7:10 + _0 = const (); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:21: 7:10 goto -> bb6; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:9: 7:10 } bb5: { -- _0 = const (); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:7:10: 7:10 + _0 = const (); // scope 1 at $DIR/simplify-locals-fixedpoint.rs:7:10: 7:10 goto -> bb6; // scope 1 at $DIR/simplify-locals-fixedpoint.rs:5:9: 7:10 } diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff index 8d6d531bd3..a698d8abcd 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff @@ -23,8 +23,6 @@ - StorageLive(_1); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 - StorageLive(_2); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23 - StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27 -- (_1.0: ()) = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 -- (_1.1: ()) = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 - StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:27: 13:28 - StorageDead(_2); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:27: 13:28 - StorageDead(_1); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:28: 13:29 @@ -32,8 +30,6 @@ - StorageLive(_5); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 - StorageLive(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 - StorageLive(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 -- (_5.0: ()) = const (); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 -- (_5.1: ()) = const (); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 - StorageDead(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 - StorageDead(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 - _4 = use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 @@ -71,7 +67,6 @@ - StorageDead(_9); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:34: 16:35 - StorageDead(_11); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 - StorageDead(_8); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 -- _0 = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:12:11: 17:2 + StorageDead(_2); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 return; // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:17:2: 17:2 } diff --git a/src/test/mir-opt/simplify_match.main.ConstProp.diff b/src/test/mir-opt/simplify_match.main.ConstProp.diff index 0fdc364514..3f5efcffc1 100644 --- a/src/test/mir-opt/simplify_match.main.ConstProp.diff +++ b/src/test/mir-opt/simplify_match.main.ConstProp.diff @@ -21,7 +21,7 @@ } bb1: { - _0 = const (); // scope 0 at $DIR/simplify_match.rs:8:18: 8:20 + nop; // scope 0 at $DIR/simplify_match.rs:8:18: 8:20 goto -> bb3; // scope 0 at $DIR/simplify_match.rs:6:5: 9:6 } diff --git a/src/test/mir-opt/storage_ranges.main.nll.0.mir b/src/test/mir-opt/storage_ranges.main.nll.0.mir index 6fa83d3de6..e02580135a 100644 --- a/src/test/mir-opt/storage_ranges.main.nll.0.mir +++ b/src/test/mir-opt/storage_ranges.main.nll.0.mir @@ -39,7 +39,7 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/storage_ranges.rs:4:9: 4:10 _1 = const 0_i32; // scope 0 at $DIR/storage_ranges.rs:4:13: 4:14 - FakeRead(ForLet, _1); // scope 0 at $DIR/storage_ranges.rs:4:9: 4:10 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/storage_ranges.rs:4:9: 4:10 StorageLive(_2); // scope 1 at $DIR/storage_ranges.rs:5:5: 7:6 StorageLive(_3); // scope 1 at $DIR/storage_ranges.rs:6:13: 6:14 StorageLive(_4); // scope 1 at $DIR/storage_ranges.rs:6:18: 6:25 @@ -48,14 +48,14 @@ fn main() -> () { _4 = Option::<i32>::Some(move _5); // scope 1 at $DIR/storage_ranges.rs:6:18: 6:25 StorageDead(_5); // scope 1 at $DIR/storage_ranges.rs:6:24: 6:25 _3 = &_4; // scope 1 at $DIR/storage_ranges.rs:6:17: 6:25 - FakeRead(ForLet, _3); // scope 1 at $DIR/storage_ranges.rs:6:13: 6:14 + FakeRead(ForLet(None), _3); // scope 1 at $DIR/storage_ranges.rs:6:13: 6:14 _2 = const (); // scope 1 at $DIR/storage_ranges.rs:5:5: 7:6 StorageDead(_4); // scope 1 at $DIR/storage_ranges.rs:7:5: 7:6 StorageDead(_3); // scope 1 at $DIR/storage_ranges.rs:7:5: 7:6 StorageDead(_2); // scope 1 at $DIR/storage_ranges.rs:7:5: 7:6 StorageLive(_6); // scope 1 at $DIR/storage_ranges.rs:8:9: 8:10 _6 = const 1_i32; // scope 1 at $DIR/storage_ranges.rs:8:13: 8:14 - FakeRead(ForLet, _6); // scope 1 at $DIR/storage_ranges.rs:8:9: 8:10 + FakeRead(ForLet(None), _6); // scope 1 at $DIR/storage_ranges.rs:8:9: 8:10 _0 = const (); // scope 0 at $DIR/storage_ranges.rs:3:11: 9:2 StorageDead(_6); // scope 1 at $DIR/storage_ranges.rs:9:1: 9:2 StorageDead(_1); // scope 0 at $DIR/storage_ranges.rs:9:1: 9:2 diff --git a/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir b/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir index 06161373be..78ddabd0d3 100644 --- a/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir +++ b/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir @@ -20,7 +20,6 @@ fn main() -> () { _3 = &/*tls*/ mut FOO; // scope 2 at $DIR/tls-access.rs:9:9: 9:12 (*_3) = const 42_u8; // scope 2 at $DIR/tls-access.rs:9:9: 9:17 StorageDead(_3); // scope 2 at $DIR/tls-access.rs:9:17: 9:18 - _0 = const (); // scope 1 at $DIR/tls-access.rs:7:5: 10:6 StorageDead(_2); // scope 1 at $DIR/tls-access.rs:10:5: 10:6 StorageDead(_1); // scope 1 at $DIR/tls-access.rs:10:5: 10:6 return; // scope 0 at $DIR/tls-access.rs:11:2: 11:2 diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir index d18f6308de..7f81d9fc48 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir @@ -48,7 +48,7 @@ fn move_out_by_subslice() -> () { bb4: { StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 - FakeRead(ForLet, _1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10 StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 _6 = move _1[0..2]; // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:10:27: 13:2 diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir index eda8e5fd3a..62ab494c06 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir @@ -48,7 +48,7 @@ fn move_out_from_end() -> () { bb4: { StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 - FakeRead(ForLet, _1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10 StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 _6 = move _1[1 of 2]; // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:4:24: 7:2 diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff index 2d53fefca5..de8a29ea25 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff @@ -25,7 +25,7 @@ } bb1: { - _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + nop; // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 } @@ -35,7 +35,7 @@ bb3: { _1 = const 1_i32; // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15 - _0 = const (); // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 + nop; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 } diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff index 2d53fefca5..de8a29ea25 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff @@ -25,7 +25,7 @@ } bb1: { - _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + nop; // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 } @@ -35,7 +35,7 @@ bb3: { _1 = const 1_i32; // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15 - _0 = const (); // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 + nop; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 } diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir index eb3ab1c31e..b91aae054d 100644 --- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir +++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir @@ -20,40 +20,36 @@ fn while_loop(_1: bool) -> () { bb1: { StorageDead(_3); // scope 0 at $DIR/while-storage.rs:10:21: 10:22 - switchInt(_2) -> [false: bb2, otherwise: bb3]; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 + switchInt(_2) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 } bb2: { - goto -> bb7; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 - } - - bb3: { StorageLive(_4); // scope 0 at $DIR/while-storage.rs:11:12: 11:23 StorageLive(_5); // scope 0 at $DIR/while-storage.rs:11:21: 11:22 _5 = _1; // scope 0 at $DIR/while-storage.rs:11:21: 11:22 - _4 = get_bool(move _5) -> bb4; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 + _4 = get_bool(move _5) -> bb3; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 // mir::Constant // + span: $DIR/while-storage.rs:11:12: 11:20 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) } } - bb4: { + bb3: { StorageDead(_5); // scope 0 at $DIR/while-storage.rs:11:22: 11:23 - switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:11:9: 13:10 + switchInt(move _4) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/while-storage.rs:11:9: 13:10 } - bb5: { + bb4: { StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10 - goto -> bb7; // scope 0 at $DIR/while-storage.rs:1:1: 1:1 + goto -> bb6; // scope 0 at $DIR/while-storage.rs:1:1: 1:1 } - bb6: { + bb5: { StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10 StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6 goto -> bb0; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 } - bb7: { + bb6: { StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6 return; // scope 0 at $DIR/while-storage.rs:15:2: 15:2 } diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile index af75ec5e24..d3d398f1fa 100644 --- a/src/test/run-make-fulldeps/coverage-reports/Makefile +++ b/src/test/run-make-fulldeps/coverage-reports/Makefile @@ -59,14 +59,7 @@ endif # if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators # appear to be normalized to `/` in those files, thankfully.) LLVM_COV_IGNORE_FILES=\ - --ignore-filename-regex=uses_crate.rs - -# When generating `expected_*` results (using `x.py test --bless`), the `--debug` flag is forced. -# If assertions are disabled, the command will fail with an error, rather than attempt to generate -# only partial results. -ifdef RUSTC_BLESS_TEST -DEBUG_FLAG=--debug -endif + --ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs)' all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs)) @@ -82,13 +75,13 @@ endif %: $(SOURCEDIR)/lib/%.rs # Compile the test library with coverage instrumentation $(RUSTC) $(SOURCEDIR)/lib/$@.rs \ - $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/lib/$@.rs) \ + $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \ --crate-type rlib -Zinstrument-coverage %: $(SOURCEDIR)/%.rs # Compile the test program with coverage instrumentation $(RUSTC) $(SOURCEDIR)/$@.rs \ - $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \ + $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \ -L "$(TMPDIR)" -Zinstrument-coverage # Run it in order to generate some profiling data, @@ -107,7 +100,7 @@ endif # Run it through rustdoc as well to cover doctests LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \ $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \ - $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \ + $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \ -L "$(TMPDIR)" -Zinstrument-coverage \ -Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@ @@ -177,76 +170,3 @@ else false \ ) endif - -#################################################################################################### - -# The following Makefile content was used to copy the generated `counters` files -# to `expected_` files (when `--bless`ed) and to compare them via `diff`; but for -# multiple reasons, these files cannot easily be used for test validation: -# -# * Output lines can be produced in non-deterministic order (depending on the -# target platform, and sometimes on unrelated codegen changes). -# * Some lines include demangled function names, making them more challenging -# to interpret and compare. -# -# The files are still generated (in `$(TMPDIR)`) to support developers wanting -# to inspect the counters, for debugging purposes. -# -# ifdef RUSTC_BLESS_TEST -# cp "$(TMPDIR)"/actual_show_coverage_counters.$@.txt \ -# expected_show_coverage_counters.$@.txt -# else -# -# ifdef DEBUG_FLAG -# $(DIFF) expected_show_coverage_counters.$@.txt "$(TMPDIR)"/actual_show_coverage_counters.$@.txt || \ -# ( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \ -# >&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \ -# ) || \ -# ( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \ -# >&2 echo '(Ignore anyway until mangled function names in "counters" files are demangled.)' \ -# ) -# endif -# -# endif - -#################################################################################################### - -# The following Makefile content, and short JSON script, were used to generate -# coverage reports in JSON when the `llvm-cov show` reports were less reliable for -# testing. At the present time, however, the `llvm-cov show` results, and methods -# for comparing them, are working for all tests, making the JSON reports redundant. -# -# If this changes in the future, the scripts are left here, commented out, but can -# be resurrected if desired. This could be used to compare *only* the JSON files; -# and in that case, the `llvm-cov show` reports can be ignored by inserting -# `// ignore-llvm-cov-show-diffs` at the top of the source file. -# -# # Generate a coverage report in JSON, using `llvm-cov export`, and fail if -# # there are differences from the expected output. -# "$(LLVM_BIN_DIR)"/llvm-cov export \ -# $(LLVM_COV_IGNORE_FILES) \ -# --summary-only \ -# --instr-profile="$(TMPDIR)"/$@.profdata \ -# $(call BIN,"$(TMPDIR)"/$@) \ -# | "$(PYTHON)" $(BASEDIR)/prettify_json.py \ -# > "$(TMPDIR)"/actual_export_coverage.$@.json -# -# ifdef RUSTC_BLESS_TEST -# cp "$(TMPDIR)"/actual_export_coverage.$@.json expected_export_coverage.$@.json -# else -# # Check that exported JSON coverage data matches what we expect (`--bless` refreshes `expected`) -# $(DIFF) expected_export_coverage.$@.json "$(TMPDIR)"/actual_export_coverage.$@.json -# endif -# -# # # If generating coverage reports in JSON, this Makefile is accompanied by -# # # a Python script, `prettify_json.py`, which is defined: -# # -# # #!/usr/bin/env python -# # -# # import sys -# # import json -# # -# # # Try to decode line in order to ensure it is a valid JSON document -# # for line in sys.stdin: -# # parsed = json.loads(line) -# # print (json.dumps(parsed, indent=2, separators=(',', ': '), sort_keys=True)) diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt index 3f9403e6f7..ae9487473d 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt @@ -1,6 +1,6 @@ 1| |#![allow(unused_assignments, dead_code)] 2| | - 3| |// compile-flags: --edition=2018 + 3| |// compile-flags: --edition=2018 -C opt-level=1 4| | 5| 1|async fn c(x: u8) -> u8 { 6| 1| if x == 8 { @@ -66,7 +66,8 @@ 63| 1| 0 64| 1| } 65| 1| } - 66| 1| fn d() -> u8 { 1 } + 66| 1| fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed + ^0 67| 1| fn f() -> u8 { 1 } 68| 1| match x { 69| 1| y if c(x) == y + 1 => { d(); } @@ -115,11 +116,14 @@ 109| | 110| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output { 111| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) }; - 112| 1| + 112| 1| use std::hint::unreachable_unchecked; 113| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new( - 114| 1| |_| unimplemented!("clone"), - 115| 1| |_| unimplemented!("wake"), - 116| 1| |_| unimplemented!("wake_by_ref"), + 114| 1| |_| unsafe { unreachable_unchecked() }, // clone + ^0 + 115| 1| |_| unsafe { unreachable_unchecked() }, // wake + ^0 + 116| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref + ^0 117| 1| |_| (), 118| 1| ); 119| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt new file mode 100644 index 0000000000..8a445433ab --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt @@ -0,0 +1,115 @@ + 1| |// compile-flags: --edition=2018 + 2| | + 3| |use core::{ + 4| | future::Future, + 5| | marker::Send, + 6| | pin::Pin, + 7| |}; + 8| | + 9| 1|fn non_async_func() { + 10| 1| println!("non_async_func was covered"); + 11| 1| let b = true; + 12| 1| if b { + 13| 1| println!("non_async_func println in block"); + 14| 1| } + 15| 1|} + 16| | + 17| |// FIXME(#83985): The auto-generated closure in an async function is failing to include + 18| |// the println!() and `let` assignment lines in the coverage code region(s), as it does in the + 19| |// non-async function above, unless the `println!()` is inside a covered block. + 20| 1|async fn async_func() { + 21| 1| println!("async_func was covered"); + 22| 1| let b = true; + 23| 1| if b { + 24| 1| println!("async_func println in block"); + 25| 1| } + ^0 + 26| 1|} + 27| | + 28| |// FIXME(#83985): As above, this async function only has the `println!()` macro call, which is not + 29| |// showing coverage, so the entire async closure _appears_ uncovered; but this is not exactly true. + 30| |// It's only certain kinds of lines and/or their context that results in missing coverage. + 31| 1|async fn async_func_just_println() { + 32| 1| println!("async_func_just_println was covered"); + 33| 1|} + 34| | + 35| 1|fn main() { + 36| 1| println!("codecovsample::main"); + 37| 1| + 38| 1| non_async_func(); + 39| 1| + 40| 1| executor::block_on(async_func()); + 41| 1| executor::block_on(async_func_just_println()); + 42| 1|} + 43| | + 44| |mod executor { + 45| | use core::{ + 46| | future::Future, + 47| | pin::Pin, + 48| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + 49| | }; + 50| | + 51| 2| pub fn block_on<F: Future>(mut future: F) -> F::Output { + 52| 2| let mut future = unsafe { Pin::new_unchecked(&mut future) }; + 53| 2| use std::hint::unreachable_unchecked; + 54| 2| static VTABLE: RawWakerVTable = RawWakerVTable::new( + 55| 2| |_| unsafe { unreachable_unchecked() }, // clone + ^0 + 56| 2| |_| unsafe { unreachable_unchecked() }, // wake + ^0 + 57| 2| |_| unsafe { unreachable_unchecked() }, // wake_by_ref + ^0 + 58| 2| |_| (), + 59| 2| ); + 60| 2| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + 61| 2| let mut context = Context::from_waker(&waker); + 62| | + 63| | loop { + 64| 2| if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + 65| 2| break val; + 66| 0| } + 67| | } + 68| 2| } + ------------------ + | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func::{closure#0}>>: + | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output { + | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) }; + | 53| 1| use std::hint::unreachable_unchecked; + | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new( + | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone + | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake + | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref + | 58| 1| |_| (), + | 59| 1| ); + | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + | 61| 1| let mut context = Context::from_waker(&waker); + | 62| | + | 63| | loop { + | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + | 65| 1| break val; + | 66| 0| } + | 67| | } + | 68| 1| } + ------------------ + | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func_just_println::{closure#0}>>: + | 51| 1| pub fn block_on<F: Future>(mut future: F) -> F::Output { + | 52| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) }; + | 53| 1| use std::hint::unreachable_unchecked; + | 54| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new( + | 55| 1| |_| unsafe { unreachable_unchecked() }, // clone + | 56| 1| |_| unsafe { unreachable_unchecked() }, // wake + | 57| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref + | 58| 1| |_| (), + | 59| 1| ); + | 60| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + | 61| 1| let mut context = Context::from_waker(&waker); + | 62| | + | 63| | loop { + | 64| 1| if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + | 65| 1| break val; + | 66| 0| } + | 67| | } + | 68| 1| } + ------------------ + 69| |} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt index 7261cf0a3b..a39e3a16fc 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments, unused_variables)] - 2| | + 2| |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs 3| 1|fn main() { 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.continue.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.continue.txt new file mode 100644 index 0000000000..28e0f1953e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.continue.txt @@ -0,0 +1,75 @@ + 1| |#![allow(unused_assignments, unused_variables)] + 2| | + 3| 1|fn main() { + 4| 1| let is_true = std::env::args().len() == 1; + 5| 1| + 6| 1| let mut x = 0; + 7| 11| for _ in 0..10 { + ^10 + 8| 10| match is_true { + 9| | true => { + 10| 10| continue; + 11| | } + 12| 0| _ => { + 13| 0| x = 1; + 14| 0| } + 15| 0| } + 16| 0| x = 3; + 17| | } + 18| 11| for _ in 0..10 { + ^10 + 19| 10| match is_true { + 20| 0| false => { + 21| 0| x = 1; + 22| 0| } + 23| | _ => { + 24| 10| continue; + 25| | } + 26| | } + 27| 0| x = 3; + 28| | } + 29| 11| for _ in 0..10 { + ^10 + 30| 10| match is_true { + 31| 10| true => { + 32| 10| x = 1; + 33| 10| } + 34| | _ => { + 35| 0| continue; + 36| | } + 37| | } + 38| 10| x = 3; + 39| | } + 40| 11| for _ in 0..10 { + ^10 + 41| 10| if is_true { + 42| 10| continue; + 43| 0| } + 44| 0| x = 3; + 45| | } + 46| 11| for _ in 0..10 { + ^10 + 47| 10| match is_true { + 48| 0| false => { + 49| 0| x = 1; + 50| 0| } + 51| 10| _ => { + 52| 10| let _ = x; + 53| 10| } + 54| | } + 55| 10| x = 3; + 56| | } + 57| 1| for _ in 0..10 { + 58| 1| match is_true { + 59| 0| false => { + 60| 0| x = 1; + 61| 0| } + 62| | _ => { + 63| 1| break; + 64| | } + 65| | } + 66| 0| x = 3; + 67| | } + 68| | let _ = x; + 69| 1|} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt index 8f67170561..1b6bb9ff88 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt @@ -23,6 +23,12 @@ 22| 1|//! ``` 23| 2|//! #[derive(Debug, PartialEq)] ^1 + ------------------ + | Unexecuted instantiation: <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::ne + ------------------ + | <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::eq: + | 23| 2|//! #[derive(Debug, PartialEq)] + ------------------ 24| 1|//! struct SomeError { 25| 1|//! msg: String, 26| 1|//! } @@ -50,7 +56,7 @@ 46| 1|//! println!("called some_func()"); 47| 1|//! } 48| |//! - 49| |//! #[derive(Debug)] + 49| 0|//! #[derive(Debug)] 50| |//! struct SomeError; 51| |//! 52| |//! extern crate doctest_crate; diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt index 6148d89ed7..31d3ddea8d 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt @@ -47,7 +47,7 @@ 46| 6|} 47| | 48| |#[inline(always)] - 49| |fn error() { - 50| | panic!("error"); - 51| |} + 49| 0|fn error() { + 50| 0| panic!("error"); + 51| 0|} diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-83601.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-83601.txt new file mode 100644 index 0000000000..46f3add942 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-83601.txt @@ -0,0 +1,22 @@ + 1| |// Shows that rust-lang/rust/83601 is resolved + 2| | + 3| 3|#[derive(Debug, PartialEq, Eq)] + ^2 + ------------------ + | <issue_83601::Foo as core::cmp::PartialEq>::eq: + | 3| 2|#[derive(Debug, PartialEq, Eq)] + ------------------ + | Unexecuted instantiation: <issue_83601::Foo as core::cmp::PartialEq>::ne + ------------------ + 4| |struct Foo(u32); + 5| | + 6| 1|fn main() { + 7| 1| let bar = Foo(1); + 8| 0| assert_eq!(bar, Foo(1)); + 9| 1| let baz = Foo(0); + 10| 0| assert_ne!(baz, Foo(1)); + 11| 1| println!("{:?}", Foo(1)); + 12| 1| println!("{:?}", bar); + 13| 1| println!("{:?}", baz); + 14| 1|} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt index 474f02b700..81d5c7d903 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt @@ -1,7 +1,7 @@ 1| |#![allow(unused_assignments, unused_variables, while_true)] 2| | - 3| |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the - 4| |// structure of this `fmt` function. + 3| |// This test confirms that (1) unexecuted infinite loops are handled correctly by the + 4| |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. 5| | 6| |struct DebugTest; 7| | @@ -16,23 +16,51 @@ ^0 16| | } else { 17| | } - 18| 1| Ok(()) - 19| 1| } - 20| |} - 21| | - 22| 1|fn main() { - 23| 1| let debug_test = DebugTest; - 24| 1| println!("{:?}", debug_test); - 25| 1|} - 26| | - 27| |/* - 28| | - 29| |This is the error message generated, before the issue was fixed: - 30| | - 31| |error: internal compiler error: compiler/rustc_mir/src/transform/coverage/mod.rs:374:42: - 32| |Error processing: DefId(0:6 ~ bug_incomplete_cov_graph_traversal_simplified[317d]::{impl#0}::fmt): - 33| |Error { message: "`TraverseCoverageGraphWithLoops` missed some `BasicCoverageBlock`s: - 34| |[bcb6, bcb7, bcb9]" } - 35| | - 36| |*/ + 18| | + 19| 10| for i in 0..10 { + 20| 10| if true { + 21| 10| if false { + 22| | while true {} + 23| 10| } + 24| 10| write!(f, "error")?; + ^0 + 25| | } else { + 26| | } + 27| | } + 28| 1| Ok(()) + 29| 1| } + 30| |} + 31| | + 32| |struct DisplayTest; + 33| | + 34| |impl std::fmt::Display for DisplayTest { + 35| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + 36| 1| if false { + 37| | } else { + 38| 1| if false { + 39| | while true {} + 40| 1| } + 41| 1| write!(f, "error")?; + ^0 + 42| | } + 43| 10| for i in 0..10 { + 44| 10| if false { + 45| | } else { + 46| 10| if false { + 47| | while true {} + 48| 10| } + 49| 10| write!(f, "error")?; + ^0 + 50| | } + 51| | } + 52| 1| Ok(()) + 53| 1| } + 54| |} + 55| | + 56| 1|fn main() { + 57| 1| let debug_test = DebugTest; + 58| 1| println!("{:?}", debug_test); + 59| 1| let display_test = DisplayTest; + 60| 1| println!("{}", display_test); + 61| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.no_cov_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.no_cov_crate.txt new file mode 100644 index 0000000000..c4a7b0cc7e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.no_cov_crate.txt @@ -0,0 +1,18 @@ + 1| |// Enables `no_coverage` on the entire crate + 2| |#![feature(no_coverage)] + 3| | + 4| |#[no_coverage] + 5| |fn do_not_add_coverage_1() { + 6| | println!("called but not covered"); + 7| |} + 8| | + 9| |#[no_coverage] + 10| |fn do_not_add_coverage_2() { + 11| | println!("called but not covered"); + 12| |} + 13| | + 14| 1|fn main() { + 15| 1| do_not_add_coverage_1(); + 16| 1| do_not_add_coverage_2(); + 17| 1|} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.partial_eq.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.partial_eq.txt index 9cc9a4d47a..fc26665334 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.partial_eq.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.partial_eq.txt @@ -2,7 +2,12 @@ 2| |// structure of this test. 3| | 4| 2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] - ^0 ^0 ^0 ^0 ^1 ^1 ^0^0 + ^0 ^0 ^0 ^1 ^1 ^0^0 + ------------------ + | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::ne + ------------------ + | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::eq + ------------------ 5| |pub struct Version { 6| | major: usize, 7| | minor: usize, diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt index c9ebffde03..9fca52451e 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt @@ -9,7 +9,7 @@ 9| | } 10| 6|} 11| | - 12| 1|fn main() -> Result<(),()> { + 12| 1|fn test1() -> Result<(),()> { 13| 1| let mut 14| 1| countdown = 10 15| | ; @@ -35,4 +35,91 @@ 34| | } 35| 0| Ok(()) 36| 1|} + 37| | + 38| |struct Thing1; + 39| |impl Thing1 { + 40| 18| fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> { + 41| 18| if return_error { + 42| 1| Err(()) + 43| | } else { + 44| 17| Ok(Thing2{}) + 45| | } + 46| 18| } + 47| |} + 48| | + 49| |struct Thing2; + 50| |impl Thing2 { + 51| 17| fn call(&self, return_error: bool) -> Result<u32,()> { + 52| 17| if return_error { + 53| 2| Err(()) + 54| | } else { + 55| 15| Ok(57) + 56| | } + 57| 17| } + 58| |} + 59| | + 60| 1|fn test2() -> Result<(),()> { + 61| 1| let thing1 = Thing1{}; + 62| 1| let mut + 63| 1| countdown = 10 + 64| | ; + 65| | for + 66| 6| _ + 67| | in + 68| 6| 0..10 + 69| | { + 70| 6| countdown + 71| 6| -= 1 + 72| 6| ; + 73| 6| if + 74| 6| countdown < 5 + 75| | { + 76| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); + ^0 + 77| 1| thing1 + 78| 1| . + 79| 1| get_thing_2(/*return_error=*/ false) + 80| 0| ? + 81| | . + 82| 1| call(/*return_error=*/ true) + 83| 1| . + 84| 1| expect_err( + 85| 1| "call should fail" + 86| 1| ); + 87| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; + ^0 ^0 ^0 + 88| 0| assert_eq!(val, 57); + 89| 0| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; + 90| 0| assert_eq!(val, 57); + 91| | } + 92| | else + 93| | { + 94| 5| let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; + ^0 ^0 + 95| 5| assert_eq!(val, 57); + 96| 5| let val = thing1 + 97| 5| .get_thing_2(/*return_error=*/ false)? + ^0 + 98| 5| .call(/*return_error=*/ false)?; + ^0 + 99| 5| assert_eq!(val, 57); + 100| 5| let val = thing1 + 101| 5| .get_thing_2(/*return_error=*/ false) + 102| 0| ? + 103| 5| .call(/*return_error=*/ false) + 104| 0| ? + 105| | ; + 106| 5| assert_eq!(val, 57); + 107| | } + 108| | } + 109| 0| Ok(()) + 110| 1|} + 111| | + 112| 1|fn main() -> Result<(),()> { + 113| 1| test1().expect_err("test1 should fail"); + 114| 1| test2() + 115| 1| ? + 116| | ; + 117| 0| Ok(()) + 118| 1|} diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.unused.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.unused.txt new file mode 100644 index 0000000000..15fcf21c0e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.unused.txt @@ -0,0 +1,62 @@ + 1| 2|fn foo<T>(x: T) { + 2| 2| let mut i = 0; + 3| 22| while i < 10 { + 4| 20| i != 0 || i != 0; + ^2 + 5| 20| i += 1; + 6| | } + 7| 2|} + ------------------ + | unused::foo::<f32>: + | 1| 1|fn foo<T>(x: T) { + | 2| 1| let mut i = 0; + | 3| 11| while i < 10 { + | 4| 10| i != 0 || i != 0; + | ^1 + | 5| 10| i += 1; + | 6| | } + | 7| 1|} + ------------------ + | unused::foo::<u32>: + | 1| 1|fn foo<T>(x: T) { + | 2| 1| let mut i = 0; + | 3| 11| while i < 10 { + | 4| 10| i != 0 || i != 0; + | ^1 + | 5| 10| i += 1; + | 6| | } + | 7| 1|} + ------------------ + 8| | + 9| 0|fn unused_template_func<T>(x: T) { + 10| 0| let mut i = 0; + 11| 0| while i < 10 { + 12| 0| i != 0 || i != 0; + 13| 0| i += 1; + 14| | } + 15| 0|} + 16| | + 17| 0|fn unused_func(mut a: u32) { + 18| 0| if a != 0 { + 19| 0| a += 1; + 20| 0| } + 21| 0|} + 22| | + 23| 0|fn unused_func2(mut a: u32) { + 24| 0| if a != 0 { + 25| 0| a += 1; + 26| 0| } + 27| 0|} + 28| | + 29| 0|fn unused_func3(mut a: u32) { + 30| 0| if a != 0 { + 31| 0| a += 1; + 32| 0| } + 33| 0|} + 34| | + 35| 1|fn main() -> Result<(), u8> { + 36| 1| foo::<u32>(0); + 37| 1| foo::<f32>(0.0); + 38| 1| Ok(()) + 39| 1|} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt index bc2f673349..f5beb9ef24 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments, unused_variables)] - 2| | + 2| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations 3| |use std::fmt::Debug; 4| | 5| 1|pub fn used_function() { @@ -19,27 +19,29 @@ 18| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); 19| 2|} ------------------ - | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>: + | used_crate::used_only_from_bin_crate_generic_function::<&str>: | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); | 19| 1|} ------------------ - | used_crate::used_only_from_bin_crate_generic_function::<&str>: + | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>: | 17| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); | 19| 1|} ------------------ - 20| | + | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_> + ------------------ + 20| |// Expect for above function: `Unexecuted instantiation` (see below) 21| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { 22| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); 23| 2|} ------------------ - | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: + | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); | 23| 1|} ------------------ - | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: + | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); | 23| 1|} @@ -63,6 +65,17 @@ 29| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { 30| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); 31| 2|} + ------------------ + | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: + | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | 31| 1|} + ------------------ + | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: + | 29| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + | 30| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | 31| 1|} + ------------------ 32| | 33| 0|pub fn unused_generic_function<T: Debug>(arg: T) { 34| 0| println!("unused_generic_function with {:?}", arg); @@ -94,46 +107,42 @@ 60| 1| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); 61| 1|} 62| | - 63| |// FIXME(#79651): `used_from_bin_crate_and_lib_crate_generic_function()` is covered and executed - 64| |// `2` times, but the coverage output also shows (at the bottom of the coverage report): - 65| |// ------------------ - 66| |// | Unexecuted instantiation: <some function name here> - 67| |// ------------------ - 68| |// - 69| |// Note, the function name shown in the error seems to change depending on the structure of the - 70| |// code, for some reason, including: - 71| |// - 72| |// * used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str> - 73| |// * used_crate::use_this_lib_crate + 63| |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results, + 64| |// for example: + 65| |// + 66| |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_> + 67| |// + 68| |// These notices appear when `llvm-cov` shows instantiations. This may be a + 69| |// default option, but it can be suppressed with: + 70| |// + 71| |// ```shell + 72| |// $ `llvm-cov show --show-instantiations=0 ...` + 73| |// ``` 74| |// - 75| |// The `Unexecuted instantiation` error may be related to more than one generic function. Since the - 76| |// reporting is not consistent, it may not be obvious if there are multiple problems here; however, - 77| |// `used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>` (which I have seen - 78| |// with this error) is the only generic function missing instantiaion coverage counts. + 75| |// The notice is triggered because the function is unused by the library itself, + 76| |// and when the library is compiled, a synthetic function is generated, so + 77| |// unused function coverage can be reported. Coverage can be skipped for unused + 78| |// generic functions with: 79| |// - 80| |// The `&str` variant was called from within this `lib` crate, and the `bin` crate also calls this - 81| |// function, but with `T` type `&Vec<i32>`. - 82| |// - 83| |// I believe the reason is that one or both crates are generating `Zero` counters for what it - 84| |// believes are "Unreachable" instantiations, but those instantiations are counted from the - 85| |// coverage map in the other crate. - 86| |// - 87| |// See `add_unreachable_coverage()` in `mapgen.rs` for more on how these `Zero` counters are added - 88| |// for what the funciton believes are `DefId`s that did not get codegenned. I suspect the issue - 89| |// may be related to this process, but this needs to be confirmed. It may not be possible to know - 90| |// for sure if a function is truly unused and should be reported with `Zero` coverage if it may - 91| |// still get used from an external crate. (Something to look at: If the `DefId` in MIR corresponds - 92| |// _only_ to the generic function without type parameters, is the `DefId` in the codegenned set, - 93| |// instantiated with one of the type parameters (in either or both crates) a *different* `DefId`? - 94| |// If so, `add_unreachable_coverage()` would assume the MIR `DefId` was uncovered, and would add - 95| |// unreachable coverage. - 96| |// - 97| |// I didn't think they could be different, but if they can, we would need to find the `DefId` for - 98| |// the generic function MIR and include it in the set of "codegenned" DefIds if any instantiation - 99| |// of that generic function does exist. - 100| |// - 101| |// Note, however, for `used_with_same_type_from_bin_crate_and_lib_crate_generic_function()` both - 102| |// crates use this function with the same type variant. The function does not have multiple - 103| |// instantiations, so the coverage analysis is not confused. No "Unexecuted instantiations" errors - 104| |// are reported. + 80| |// ```shell + 81| |// $ `rustc -Z instrument-coverage=except-unused-generics ...` + 82| |// ``` + 83| |// + 84| |// Even though this function is used by `uses_crate.rs` (and + 85| |// counted), with substitutions for `T`, those instantiations are only generated + 86| |// when the generic function is actually used (from the binary, not from this + 87| |// library crate). So the test result shows coverage for all instantiated + 88| |// versions and their generic type substitutions, plus the `Unexecuted + 89| |// instantiation` message for the non-substituted version. This is valid, but + 90| |// unfortunately a little confusing. + 91| |// + 92| |// The library crate has its own coverage map, and the only way to show unused + 93| |// coverage of a generic function is to include the generic function in the + 94| |// coverage map, marked as an "unused function". If the library were used by + 95| |// another binary that never used this generic function, then it would be valid + 96| |// to show the unused generic, with unknown substitution (`_`). + 97| |// + 98| |// The alternative is to exclude all generics from being included in the "unused + 99| |// functions" list, which would then omit coverage results for + 100| |// `unused_generic_function<T>()`, below. diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt new file mode 100644 index 0000000000..cc98956e30 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt @@ -0,0 +1,139 @@ + 1| |#![allow(unused_assignments, unused_variables)] + 2| | + 3| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations + 4| | + 5| |use std::fmt::Debug; + 6| | + 7| 1|pub fn used_function() { + 8| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + 9| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + 10| | // dependent conditions. + 11| 1| let is_true = std::env::args().len() == 1; + 12| 1| let mut countdown = 0; + 13| 1| if is_true { + 14| 1| countdown = 10; + 15| 1| } + ^0 + 16| 1| use_this_lib_crate(); + 17| 1|} + 18| | + 19| |#[inline(always)] + 20| 1|pub fn used_inline_function() { + 21| | // Initialize test constants in a way that cannot be determined at compile time, to ensure + 22| | // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + 23| | // dependent conditions. + 24| 1| let is_true = std::env::args().len() == 1; + 25| 1| let mut countdown = 0; + 26| 1| if is_true { + 27| 1| countdown = 10; + 28| 1| } + ^0 + 29| 1| use_this_lib_crate(); + 30| 1|} + 31| | + 32| | + 33| | + 34| | + 35| | + 36| | + 37| | + 38| |#[inline(always)] + 39| 2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { + 40| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + 41| 2|} + ------------------ + | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>: + | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { + | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | 41| 1|} + ------------------ + | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>: + | 39| 1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { + | 40| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); + | 41| 1|} + ------------------ + | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_> + ------------------ + 42| |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) + 43| | + 44| |#[inline(always)] + 45| 4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { + 46| 4| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + 47| 4|} + ------------------ + | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: + | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { + | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | 47| 2|} + ------------------ + | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>: + | 45| 2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { + | 46| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); + | 47| 2|} + ------------------ + 48| | + 49| |#[inline(always)] + 50| 3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + 51| 3| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + 52| 3|} + ------------------ + | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>: + | 50| 1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + | 51| 1| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | 52| 1|} + ------------------ + | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>: + | 50| 2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + | 51| 2| println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | 52| 2|} + ------------------ + 53| | + 54| |#[inline(always)] + 55| 3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + 56| 3| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + 57| 3|} + ------------------ + | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: + | 55| 1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + | 56| 1| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | 57| 1|} + ------------------ + | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>: + | 55| 2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { + | 56| 2| println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); + | 57| 2|} + ------------------ + 58| | + 59| |#[inline(always)] + 60| 0|pub fn unused_generic_function<T: Debug>(arg: T) { + 61| 0| println!("unused_generic_function with {:?}", arg); + 62| 0|} + 63| | + 64| |#[inline(always)] + 65| 0|pub fn unused_function() { + 66| 0| let is_true = std::env::args().len() == 1; + 67| 0| let mut countdown = 2; + 68| 0| if !is_true { + 69| 0| countdown = 20; + 70| 0| } + 71| 0|} + 72| | + 73| |#[inline(always)] + 74| 0|fn unused_private_function() { + 75| 0| let is_true = std::env::args().len() == 1; + 76| 0| let mut countdown = 2; + 77| 0| if !is_true { + 78| 0| countdown = 20; + 79| 0| } + 80| 0|} + 81| | + 82| 2|fn use_this_lib_crate() { + 83| 2| used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); + 84| 2| used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + 85| 2| "used from library used_crate.rs", + 86| 2| ); + 87| 2| let some_vec = vec![5, 6, 7, 8]; + 88| 2| used_only_from_this_lib_crate_generic_function(some_vec); + 89| 2| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); + 90| 2|} + diff --git a/src/test/run-make-fulldeps/coverage-spanview/Makefile b/src/test/run-make-fulldeps/coverage-spanview/Makefile deleted file mode 100644 index b0bfa7074d..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/Makefile +++ /dev/null @@ -1,96 +0,0 @@ -# needs-profiler-support -# min-llvm-version: 11.0 - --include ../coverage/coverage_tools.mk - -BASEDIR=../coverage-spanview -SOURCEDIR=../coverage - -define SPANVIEW_HEADER -<!DOCTYPE html> -<!-- - -Preview this file as rendered HTML from the github source at: -https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.%s/%s - -For revisions in Pull Requests (PR): - * Replace "rust-lang" with the github PR author - * Replace "master" with the PR branch name - ---> -endef -export SPANVIEW_HEADER - -all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs)) - -# Ensure there are no `expected` results for tests that may have been removed or renamed -.PHONY: clear_expected_if_blessed -clear_expected_if_blessed: -ifdef RUSTC_BLESS_TEST - rm -rf expected_mir_dump.*/ -endif - --include clear_expected_if_blessed - -# FIXME(richkadel): The actions for these two types of targets (libraries and binaries) should be -# combined. - -%: $(SOURCEDIR)/lib/%.rs - # Compile the test library with coverage instrumentation - $(RUSTC) $(SOURCEDIR)/lib/$@.rs \ - $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/lib/$@.rs) \ - --crate-type rlib \ - -Ztrim-diagnostic-paths=no \ - -Zinstrument-coverage \ - -Zdump-mir=InstrumentCoverage \ - -Zdump-mir-spanview \ - -Zdump-mir-dir="$(TMPDIR)"/mir_dump.$@ - - for path in "$(TMPDIR)"/mir_dump.$@/*; do \ - file="$$(basename "$$path")"; \ - urlescaped="$$("$(PYTHON)" $(BASEDIR)/escape_url.py $$file)" || exit $$?; \ - printf "$$SPANVIEW_HEADER\n" "$@" "$$urlescaped" > "$$path".modified; \ - tail -n +2 "$$path" >> "$$path".modified; \ - mv "$$path".modified "$$path"; \ - done && true # for/done ends in non-zero status - -ifdef RUSTC_BLESS_TEST - mkdir -p expected_mir_dump.$@ - cp "$(TMPDIR)"/mir_dump.$@/*InstrumentCoverage.0.html expected_mir_dump.$@/ -else - # Check that the selected `mir_dump` files match what we expect (`--bless` refreshes `expected`) - mkdir -p "$(TMPDIR)"/actual_mir_dump.$@ - rm -f "$(TMPDIR)"/actual_mir_dump.$@/* - cp "$(TMPDIR)"/mir_dump.$@/*InstrumentCoverage.0.html "$(TMPDIR)"/actual_mir_dump.$@/ - $(DIFF) -r expected_mir_dump.$@/ "$(TMPDIR)"/actual_mir_dump.$@/ -endif - -%: $(SOURCEDIR)/%.rs - # Compile the test program with coverage instrumentation - $(RUSTC) $(SOURCEDIR)/$@.rs \ - $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \ - -L "$(TMPDIR)" \ - -Ztrim-diagnostic-paths=no \ - -Zinstrument-coverage \ - -Zdump-mir=InstrumentCoverage \ - -Zdump-mir-spanview \ - -Zdump-mir-dir="$(TMPDIR)"/mir_dump.$@ - - for path in "$(TMPDIR)"/mir_dump.$@/*; do \ - file="$$(basename "$$path")"; \ - urlescaped="$$("$(PYTHON)" $(BASEDIR)/escape_url.py $$file)" || exit $$?; \ - printf "$$SPANVIEW_HEADER\n" "$@" "$$urlescaped" > "$$path".modified; \ - tail -n +2 "$$path" >> "$$path".modified; \ - mv "$$path".modified "$$path"; \ - done && true # for/done ends in non-zero status - -ifdef RUSTC_BLESS_TEST - mkdir -p expected_mir_dump.$@ - cp "$(TMPDIR)"/mir_dump.$@/*InstrumentCoverage.0.html expected_mir_dump.$@/ -else - # Check that the selected `mir_dump` files match what we expect (`--bless` refreshes `expected`) - mkdir -p "$(TMPDIR)"/actual_mir_dump.$@ - rm -f "$(TMPDIR)"/actual_mir_dump.$@/* - cp "$(TMPDIR)"/mir_dump.$@/*InstrumentCoverage.0.html "$(TMPDIR)"/actual_mir_dump.$@/ - $(DIFF) -r expected_mir_dump.$@/ "$(TMPDIR)"/actual_mir_dump.$@/ -endif diff --git a/src/test/run-make-fulldeps/coverage-spanview/escape_url.py b/src/test/run-make-fulldeps/coverage-spanview/escape_url.py deleted file mode 100644 index b725ed4630..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/escape_url.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python - -import sys - -# Support python 2 or 3 -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - -# Converts the input string into a valid URL parameter string. -print (quote(' '.join(sys.argv[1:]))) diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 176587af25..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,106 +0,0 @@ -<!DOCTYPE html> -<!-- - -Preview this file as rendered HTML from the github source at: -https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.main.-------.InstrumentCoverage.0.html - -For revisions in Pull Requests (PR): - * Replace "rust-lang" with the github PR author - * Replace "master" with the PR branch name - ---> -<html> -<head> -<title>abort.main - Coverage Spans - - - -
@0⦊fn main() -> Result<(), u8> { - let mut countdown = 10⦉@0; - while @1,2⦊countdown > 0⦉@1,2 { - if @3,5⦊countdown < 5⦉@3,5 @6,8⦊{ - might_abort(false); - }⦉@6,8@7⦊‸⦉@7 - // See discussion (below the `Notes` section) on coverage results for the closing brace. - if @9⦊countdown < 5⦉@9 @10,12⦊{ might_abort(false); }⦉@10,12@11⦊‸⦉@11 // Counts for different regions on one line. - // For the following example, the closing brace is the last character on the line. - // This shows the character after the closing brace is highlighted, even if that next - // character is a newline. - if @13⦊countdown < 5⦉@13 @14,16⦊{ might_abort(false); }⦉@14,16@15⦊‸⦉@15 - @17,18⦊countdown -= 1⦉@17,18; - } - @4⦊Ok(()) -}⦉@4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html deleted file mode 100644 index a302b974ae..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.abort/abort.might_abort.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - -abort.might_abort - Coverage Spans - - - -
@0⦊fn might_abort(should_abort: bool) ⦉@0{ - if @0⦊should_abort⦉@0 { - @1,3,4⦊println!("aborting..."); - panic!("panics and aborts");⦉@1,3,4 - } else @2,5,6⦊{ - println!("Don't Panic"); - } -}⦉@2,5,6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 365e94cd31..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - -assert.main - Coverage Spans - - - -
@0⦊fn main() -> Result<(),u8> { - let mut countdown = 10⦉@0; - while @1,2⦊countdown > 0⦉@1,2 { - if @3,5⦊countdown == 1⦉@3,5 @6,8⦊{ - might_fail_assert(3); - }⦉@6,8 else if @7⦊countdown < 5⦉@7 @9,11⦊{ - might_fail_assert(2); - }⦉@9,11@10⦊‸⦉@10 - @13,14⦊countdown -= 1⦉@13,14; - } - @4⦊Ok(()) -}⦉@4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html deleted file mode 100644 index db72a5306f..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.assert/assert.might_fail_assert.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - -assert.might_fail_assert - Coverage Spans - - - -
@0,1,2,3,4⦊fn might_fail_assert(one_plus_one: u32) ⦉@0,1,2,3,4{ - @0,1,2,3,4⦊println!("does 1 + 1 = {}?", one_plus_one);⦉@0,1,2,3,4 - assert_eq!(@0,1,2,3,4⦊1 + 1⦉@0,1,2,3,4, one_plus_one, @5,7⦊"the argument was wrong"⦉@5,7); -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 21bfce701f..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -async.c-{closure#0} - Coverage Spans - - - -
@0⦊{ - if x == 8⦉@0 { - @1⦊1⦉@1 - } else { - @2⦊0⦉@2 - } -}@3⦊‸⦉@3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c.-------.InstrumentCoverage.0.html deleted file mode 100644 index 3eee0dd410..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.c.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -async.c - Coverage Spans - - - -
@0,1⦊async fn c(x: u8) -> u8 ⦉@0,1{ - if x == 8 { - 1 - } else { - 0 - } -}
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 7cf34f0779..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -async.d-{closure#0} - Coverage Spans - - - -
@0⦊‸⦉@0{ 1 }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d.-------.InstrumentCoverage.0.html deleted file mode 100644 index 5c7f6e0022..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.d.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -async.d - Coverage Spans - - - -
@0,1⦊async fn d() -> u8 ⦉@0,1{ 1 }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 1f95a7d35a..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -async.e-{closure#0} - Coverage Spans - - - -
@0⦊‸⦉@0{ 1 }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e.-------.InstrumentCoverage.0.html deleted file mode 100644 index ee3b7b1d7f..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.e.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -async.e - Coverage Spans - - - -
@0,1⦊async fn e() -> u8 ⦉@0,1{ 1 }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 64fc1568b0..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - -async.executor-block_on-VTABLE-{closure#0} - Coverage Spans - - - -
@0,1,2,3⦊‸⦉@0,1,2,3$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+))
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#1}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#1}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 1bbcfa5744..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#1}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - -async.executor-block_on-VTABLE-{closure#1} - Coverage Spans - - - -
@0,1,2,3⦊‸⦉@0,1,2,3$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+))
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#2}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#2}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 14cb98d20c..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#2}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - -async.executor-block_on-VTABLE-{closure#2} - Coverage Spans - - - -
@0,1,2,3⦊‸⦉@0,1,2,3$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+))
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#3}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#3}.-------.InstrumentCoverage.0.html deleted file mode 100644 index ef2fe7d068..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on-VTABLE-{closure#3}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -async.executor-block_on-VTABLE-{closure#3} - Coverage Spans - - - -
|_| @0⦊()⦉@0
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html deleted file mode 100644 index 9a5bd6e42c..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.executor-block_on.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - -async.executor-block_on - Coverage Spans - - - -
@0,1,2,3,4,5⦊pub fn block_on<F: Future>(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - - static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unimplemented!("clone"), - |_| unimplemented!("wake"), - |_| unimplemented!("wake_by_ref"), - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker)⦉@0,1,2,3,4,5; - - loop { - if let Poll::Ready(@10,12,14,15,16,17⦊val⦉@10,12,14,15,16,17) = @6,7,8,9⦊future.as_mut().poll(&mut context)⦉@6,7,8,9 { - break @10,12,14,15,16,17⦊val⦉@10,12,14,15,16,17; - }@11,13⦊‸⦉@11,13 - } - }@10,12,14,15,16,17⦊‸⦉@10,12,14,15,16,17
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 74b62673ac..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -async.f-{closure#0} - Coverage Spans - - - -
@0⦊‸⦉@0{ 1 }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f.-------.InstrumentCoverage.0.html deleted file mode 100644 index a31bca54df..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.f.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -async.f - Coverage Spans - - - -
@0,1⦊async fn f() -> u8 ⦉@0,1{ 1 }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index b8c53cccab..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -async.foo-{closure#0} - Coverage Spans - - - -
@0⦊‸⦉@0{ [false; 10] }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo.-------.InstrumentCoverage.0.html deleted file mode 100644 index cf72a9d532..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.foo.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -async.foo - Coverage Spans - - - -
@0,1⦊async fn foo() -> [bool; 10] ⦉@0,1{ [false; 10] }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index b10012621b..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -async.g-{closure#0} - Coverage Spans - - - -
@0,3,4⦊{ - match x⦉@0,3,4 { - @17⦊y⦉@17 if @0,3,4⦊e()⦉@0,3,4.await == @10,13,15,16⦊y⦉@10,13,15,16 => @17⦊()⦉@17, - @33⦊y⦉@33 if @1,19,20⦊f()⦉@1,19,20.await == @26,29,31,32⦊y⦉@26,29,31,32 => @33⦊()⦉@33, - _ => @2⦊()⦉@2, - } -}@35,36⦊‸⦉@35,36
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g.-------.InstrumentCoverage.0.html deleted file mode 100644 index 973995477b..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.g.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -async.g - Coverage Spans - - - -
@0,1⦊pub async fn g(x: u8) ⦉@0,1{ - match x { - y if e().await == y => (), - y if f().await == y => (), - _ => (), - } -}
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 6b4b43f836..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -async.h-{closure#0} - Coverage Spans - - - -
@0,2,3⦊{ // The function signature is counted when called, but the body is not - // executed (not awaited) so the open brace has a `0` count (at least when - // displayed with `llvm-cov show` in color-mode). - match x⦉@0,2,3 { - @17⦊y⦉@17 if @0,2,3⦊foo()⦉@0,2,3.await[@9,12,14,15,16⦊y⦉@9,12,14,15,16] => @17⦊()⦉@17, - _ => @1⦊()⦉@1, - } -}@19,20⦊‸⦉@19,20
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h.-------.InstrumentCoverage.0.html deleted file mode 100644 index f2ea01281f..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.h.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - -async.h - Coverage Spans - - - -
@0,1⦊async fn h(x: usize) ⦉@0,1{ // The function signature is counted when called, but the body is not - // executed (not awaited) so the open brace has a `0` count (at least when - // displayed with `llvm-cov show` in color-mode). - match x { - y if foo().await[y] => (), - _ => (), - } -}
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 49297870fa..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - -async.i-{closure#0} - Coverage Spans - - - -
@0,3,4⦊{ // line coverage is 1, but there are 2 regions: - // (a) the function signature, counted when the function is called; and - // (b) the open brace for the function body, counted once when the body is - // executed asynchronously. - match x⦉@0,3,4 { - @18,20⦊y⦉@18,20 if @0,3,4⦊c(x)⦉@0,3,4.await == @10,13,15,16,17⦊y + 1⦉@10,13,15,16,17 => { @18,20⦊d()⦉@18,20.await; } - @48⦊y⦉@48 if @1,33,34⦊f()⦉@1,33,34.await == @40,43,45,46,47⦊y + 1⦉@40,43,45,46,47 => @48⦊()⦉@48, - _ => @2⦊()⦉@2, - } -}@50,51⦊‸⦉@50,51
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i.-------.InstrumentCoverage.0.html deleted file mode 100644 index e5dc6ecd4e..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.i.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - -async.i - Coverage Spans - - - -
@0,1⦊async fn i(x: u8) ⦉@0,1{ // line coverage is 1, but there are 2 regions: - // (a) the function signature, counted when the function is called; and - // (b) the open brace for the function body, counted once when the body is - // executed asynchronously. - match x { - y if c(x).await == y + 1 => { d().await; } - y if f().await == y + 1 => (), - _ => (), - } -}
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html deleted file mode 100644 index e6384b7598..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-c.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - -async.j-c - Coverage Spans - - - -
@0⦊fn c(x: u8) -> u8 { - if x == 8⦉@0 { - @1⦊1⦉@1 // This line appears covered, but the 1-character expression span covering the `1` - // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because - // `fn j()` executes the open brace for the funciton body, followed by the function's - // first executable statement, `match x`. Inner function declarations are not - // "visible" to the MIR for `j()`, so the code region counts all lines between the - // open brace and the first statement as executed, which is, in a sense, true. - // `llvm-cov show` overcomes this kind of situation by showing the actual counts - // of the enclosed coverages, (that is, the `1` expression was not executed, and - // accurately displays a `0`). - } else { - @2⦊0⦉@2 - } - }@3⦊‸⦉@3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-d.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-d.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4eed8ee60d..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-d.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -async.j-d - Coverage Spans - - - -
@0⦊fn d() -> u8 { 1 }⦉@0
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-f.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-f.-------.InstrumentCoverage.0.html deleted file mode 100644 index 6e80c8c786..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j-f.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -async.j-f - Coverage Spans - - - -
@0⦊fn f() -> u8 { 1 }⦉@0
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j.-------.InstrumentCoverage.0.html deleted file mode 100644 index 7cc751074a..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.j.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - -async.j - Coverage Spans - - - -
@0,3,4,5⦊fn j(x: u8) { - // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`. - fn c(x: u8) -> u8 { - if x == 8 { - 1 // This line appears covered, but the 1-character expression span covering the `1` - // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because - // `fn j()` executes the open brace for the funciton body, followed by the function's - // first executable statement, `match x`. Inner function declarations are not - // "visible" to the MIR for `j()`, so the code region counts all lines between the - // open brace and the first statement as executed, which is, in a sense, true. - // `llvm-cov show` overcomes this kind of situation by showing the actual counts - // of the enclosed coverages, (that is, the `1` expression was not executed, and - // accurately displays a `0`). - } else { - 0 - } - } - fn d() -> u8 { 1 } - fn f() -> u8 { 1 } - match x⦉@0,3,4,5 { - @6,8⦊y⦉@6,8 if @0,3,4,5⦊c(x) == y + 1⦉@0,3,4,5 => @6,8⦊{ d(); }⦉@6,8 - @12⦊y⦉@12 if @1,9,10,11⦊f() == y + 1⦉@1,9,10,11 => @12⦊()⦉@12, - _ => @2⦊()⦉@2, - } -}@14⦊‸⦉@14
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.k.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.k.-------.InstrumentCoverage.0.html deleted file mode 100644 index 5792521bb2..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.k.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -async.k - Coverage Spans - - - -
@0⦊fn k(x: u8) { // unused function - match x⦉@0 { - 1 => @1,4⦊()⦉@1,4, - 2 => @2,5⦊()⦉@2,5, - _ => @3⦊()⦉@3, - } -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.l.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.l.-------.InstrumentCoverage.0.html deleted file mode 100644 index cd92b88c24..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.l.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -async.l - Coverage Spans - - - -
@0⦊fn l(x: u8) { - match x⦉@0 { - 1 => @1,4⦊()⦉@1,4, - 2 => @2,5⦊()⦉@2,5, - _ => @3⦊()⦉@3, - } -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 9cf86ce34a..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - -async.m-{closure#0} - Coverage Spans - - - -
@0,1⦊{ x - 1 }⦉@0,1
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m.-------.InstrumentCoverage.0.html deleted file mode 100644 index 04412c1d99..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.m.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -async.m - Coverage Spans - - - -
@0,1⦊async fn m(x: u8) -> u8 ⦉@0,1{ x - 1 }
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index b892af0ed3..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.async/async.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - -async.main - Coverage Spans - - - -
@0,1,2,3,4,5,6,7,8,9,10,11,12,13⦊fn main() { - let _ = g(10); - let _ = h(9); - let mut future = Box::pin(i(8)); - j(7); - l(6); - let _ = m(5); - executor::block_on(future.as_mut()); -}⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 3998295a05..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - -closure.main-{closure#0} - Coverage Spans - - - -
|| - @0⦊{ - let mut countdown = 0; - if is_false⦉@0 @1⦊{ - countdown = 10; - }⦉@1@2⦊‸⦉@2 - @3,4⦊"alt string 2".to_owned() - }⦉@3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#10}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#10}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 3bdfe71b48..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#10}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - -closure.main-{closure#10} - Coverage Spans - - - -
|| - @0⦊{ - let mut countdown = 0; - if is_false⦉@0 @1⦊{ - countdown = 10; - }⦉@1@2⦊‸⦉@2 - @3,4⦊"alt string 1".to_owned() - }⦉@3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#11}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#11}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4b3f04b5a0..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#11}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - -closure.main-{closure#11} - Coverage Spans - - - -
|| - @0⦊{ - let mut countdown = 0; - if is_false⦉@0 @1⦊{ - countdown = 10; - }⦉@1@2⦊‸⦉@2 - @3,4⦊"alt string 3".to_owned() - }⦉@3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#1}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#1}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 8ae494178f..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#1}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - -closure.main-{closure#1} - Coverage Spans - - - -
|| - @0⦊{ - let mut countdown = 0; - if is_false⦉@0 @1⦊{ - countdown = 10; - }⦉@1@2⦊‸⦉@2 - @3,4⦊"alt string 4".to_owned() - }⦉@3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#2}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#2}.-------.InstrumentCoverage.0.html deleted file mode 100644 index ad40ba57d6..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#2}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - -closure.main-{closure#2} - Coverage Spans - - - -
|val| - @0⦊{ - let mut countdown = 0; - if is_false⦉@0 @1⦊{ - countdown = 10; - }⦉@1@2⦊‸⦉@2 - @3,4,5,6,7⦊format!("'{}'", val) - }⦉@3,4,5,6,7
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#3}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#3}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 23101d76a8..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#3}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - -closure.main-{closure#3} - Coverage Spans - - - -
| - mut countdown - | - @0⦊{ - if is_false⦉@0 @1⦊{ - countdown = 10; - }⦉@1@2⦊‸⦉@2 - @3,4⦊"closure should be unused".to_owned() - }⦉@3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#4}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#4}.-------.InstrumentCoverage.0.html deleted file mode 100644 index df0172bdf7..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#4}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - -closure.main-{closure#4} - Coverage Spans - - - -
| _unused_arg: u8 | @0,1⦊countdown += 1⦉@0,1
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#5}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#5}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 1c19aa8eee..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#5}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - -closure.main-{closure#5} - Coverage Spans - - - -
@0,1,2⦊{ - $crate::io::_print($crate::format_args_nl!($($arg)*)); - }⦉@0,1,2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#6}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#6}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 74c75c6c46..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#6}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - -closure.main-{closure#6} - Coverage Spans - - - -
| _unused_arg: u8 | @0,1,2⦊{ println!("not called") }⦉@0,1,2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#7}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#7}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 386fb1b9e6..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#7}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - -closure.main-{closure#7} - Coverage Spans - - - -
| _unused_arg: u8 | @0,1,2⦊{ - println!("not called") - }⦉@0,1,2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#8}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#8}.-------.InstrumentCoverage.0.html deleted file mode 100644 index f9da6ac9df..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#8}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - -closure.main-{closure#8} - Coverage Spans - - - -
| - _unused_arg: u8 - | @0,1,2⦊{ println!("not called") }⦉@0,1,2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#9}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#9}.-------.InstrumentCoverage.0.html deleted file mode 100644 index e259fc9bb6..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main-{closure#9}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - -closure.main-{closure#9} - Coverage Spans - - - -
| - _unused_arg: u8 - | @0,1,2⦊{ println!("not called") }⦉@0,1,2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index a7d1728114..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.closure/closure.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,10921 +0,0 @@ - - - - -closure.main - Coverage Spans - - - -
@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - let is_false = ! is_true; - - let mut some_string = Some(String::from("the string content")); - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 1".to_owned() - }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊ - ) - ); - - some_string = Some(String::from("the string content")); - let - a - = - ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 2".to_owned() - }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - some_string = None; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 3".to_owned() - }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊ - ) - ); - - some_string = None; - let - a - = - ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 4".to_owned() - }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - let - quote_closure - = - ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42|val| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - format!("'{}'", val) - }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - println!( - "Repeated, quoted string: {:?}" - , - std::iter::repeat("repeat me") - .take(5) - .map - ( - quote_closure - ) - .collect::<Vec<_>>() - ); - - let - _unused_closure - = - ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| - mut countdown - | - { - if is_false { - countdown = 10; - } - "closure should be unused".to_owned() - }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - - let mut countdown = 10; - let _short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | countdown += 1@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - - // Macros can sometimes confuse the coverage results. Compare this next assignment, with an - // unused closure that invokes the `println!()` macro, with the closure assignment above, that - // does not use a macro. The closure above correctly shows `0` executions. - let _short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | println!("not called")@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - // The closure assignment above is executed, with a line count of `1`, but the `println!()` - // could not have been called, and yet, there is no indication that it wasn't... - - // ...but adding block braces gives the expected result, showing the block was not executed. - let _short_unused_closure_block = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | { println!("not called") }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - - let _shortish_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| _unused_arg: u8 | { - println!("not called") - }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - - let _as_short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| - _unused_arg: u8 - | { println!("not called") }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊; - - let _almost_as_short_unused_closure = ⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42| - _unused_arg: u8 - | { println!("not called") }@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42⦊ - ; -}⦉@0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 0aa6fe6568..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.conditions/conditions.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,307 +0,0 @@ - - - - -conditions.main - Coverage Spans - - - -
@0⦊fn main() ⦉@0{ - let @0⦊mut countdown = 0; - if true⦉@0 @1⦊{ - countdown = 10; - }⦉@1@2⦊‸⦉@2 - - const B: u32 = 100; - let @21⦊x⦉@21 = if @3⦊countdown > 7⦉@3 { - @4,6⦊countdown -= 4; - B⦉@4,6 - } else if @5⦊countdown > 2⦉@5 { - if @7⦊countdown < 1⦉@7 || @15⦊countdown > 5⦉@15 || @11⦊countdown != 9⦉@11 @17⦊{ - countdown = 0; - }⦉@17@18⦊‸⦉@18 - @19,20⦊countdown -= 5; - countdown⦉@19,20 - } else { - @8⦊return⦉@8; - }; - - let @21⦊mut countdown = 0; - if true⦉@21 @22⦊{ - countdown = 10; - }⦉@22@23⦊‸⦉@23 - - if @24⦊countdown > 7⦉@24 @25,27⦊{ - countdown -= 4; - }⦉@25,27 else if @26⦊countdown > 2⦉@26 { - if @28⦊countdown < 1⦉@28 || @36⦊countdown > 5⦉@36 || @32⦊countdown != 9⦉@32 @38⦊{ - countdown = 0; - }⦉@38@39⦊‸⦉@39 - @40,41⦊countdown -= 5⦉@40,41; - } else { - @29⦊return⦉@29; - } - - if @42⦊true⦉@42 { - let @43⦊mut countdown = 0; - if true⦉@43 @45⦊{ - countdown = 10; - }⦉@45@46⦊‸⦉@46 - - if @47⦊countdown > 7⦉@47 @48,50⦊{ - countdown -= 4; - }⦉@48,50 - else if @49⦊countdown > 2⦉@49 { - if @51⦊countdown < 1⦉@51 || @59⦊countdown > 5⦉@59 || @55⦊countdown != 9⦉@55 @61⦊{ - countdown = 0; - }⦉@61@62⦊‸⦉@62 - @63,64⦊countdown -= 5⦉@63,64; - } else { - @52⦊return⦉@52; - } - }@44⦊‸⦉@44 // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal - // `true` was const-evaluated. The compiler knows the `if` block will be executed. - - let @66⦊mut countdown = 0; - if true⦉@66 @67⦊{ - countdown = 1; - }⦉@67@68⦊‸⦉@68 - - let @89⦊z⦉@89 = if @69⦊countdown > 7⦉@69 @70,72⦊{ - countdown -= 4; - }⦉@70,72 else if @71⦊countdown > 2⦉@71 { - if @73⦊countdown < 1⦉@73 || @81⦊countdown > 5⦉@81 || @77⦊countdown != 9⦉@77 @83⦊{ - countdown = 0; - }⦉@83@84⦊‸⦉@84 - @85,86⦊countdown -= 5⦉@85,86; - } else { - let @74,87,88⦊should_be_reachable = countdown; - println!("reached"); - return⦉@74,87,88; - }; - - let @107⦊w⦉@107 = if @89⦊countdown > 7⦉@89 @90,92⦊{ - countdown -= 4; - }⦉@90,92 else if @91⦊countdown > 2⦉@91 { - if @93⦊countdown < 1⦉@93 || @101⦊countdown > 5⦉@101 || @97⦊countdown != 9⦉@97 @103⦊{ - countdown = 0; - }⦉@103@104⦊‸⦉@104 - @105,106⦊countdown -= 5⦉@105,106; - } else { - @94⦊return⦉@94; - }; -}@111⦊‸⦉@111
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index be06ddd126..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - -dead_code.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true⦉@0,1,2,3 @4⦊{ - countdown = 10; - }⦉@4@5⦊‸⦉@5 -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html deleted file mode 100644 index 7f2d8d3c8e..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_fn.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - -dead_code.unused_fn - Coverage Spans - - - -
@0,1,2,3⦊fn unused_fn() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true⦉@0,1,2,3 @4⦊{ - countdown = 10; - }⦉@4@5⦊‸⦉@5 -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html deleted file mode 100644 index be44f71348..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.dead_code/dead_code.unused_pub_fn_not_in_library.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - -dead_code.unused_pub_fn_not_in_library - Coverage Spans - - - -
@0,1,2,3⦊pub fn unused_pub_fn_not_in_library() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true⦉@0,1,2,3 @4⦊{ - countdown = 10; - }⦉@4@5⦊‸⦉@5 -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 95813decf9..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - -doctest.main - Coverage Spans - - - -
@0⦊fn main() ⦉@0{ - if @0⦊true⦉@0 { - @4⦊@3⦊assert_eq!(1, 1);⦉@3⦉@4 - } else { - @6⦊@5⦊assert_eq!(1, 2);⦉@5⦉@6 - } -}@7⦊‸⦉@7
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html deleted file mode 100644 index 3a41d3482b..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - -doctest_crate.fn_run_in_doctests - Coverage Spans - - - -
@0⦊pub fn fn_run_in_doctests(conditional: usize) ⦉@0{ - match @0⦊conditional⦉@0 { - 1 => @7⦊@6⦊assert_eq!(1, 1)⦉@6⦉@7, // this is run, - 2 => @10⦊@9⦊assert_eq!(1, 1)⦉@9⦉@10, // this, - 3 => @13⦊@12⦊assert_eq!(1, 1)⦉@12⦉@13, // and this too - _ => @15⦊@14⦊assert_eq!(1, 2)⦉@14⦉@15, // however this is not - } -}@16⦊‸⦉@16
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 66a6e776a0..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - -drop_trait.main - Coverage Spans - - - -
@0⦊fn main() -> Result<(),u8> { - let _firecracker = Firework { strength: 1 }; - - let _tnt = Firework { strength: 100 }; - - if true⦉@0 { - @1,3,4,8,9⦊println!("Exiting with error..."); - return Err(1)⦉@1,3,4,8,9; - }@2,5,6,7⦊ - - let _ = Firework { strength: 1000 }; - - Ok(())⦉@2,5,6,7 -}@10⦊‸⦉@10
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.{impl#0}-drop.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.{impl#0}-drop.-------.InstrumentCoverage.0.html deleted file mode 100644 index 57d56c5cf7..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.drop_trait/drop_trait.{impl#0}-drop.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -drop_trait.{impl#0}-drop - Coverage Spans - - - -
@0,1,2,3⦊fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - }⦉@0,1,2,3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 098c140425..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,237 +0,0 @@ - - - - -generics.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() -> Result<(),u8> { - let mut firecracker = Firework { strength: 1 }; - firecracker.set_strength(2); - - let mut tnt = Firework { strength: 100.1 }; - tnt.set_strength(200.1); - tnt.set_strength(300.3); - - if true⦉@0,1,2,3 { - @4,6,7,11,12⦊println!("Exiting with error..."); - return Err(1)⦉@4,6,7,11,12; - }@5,8,9,10⦊ // The remaining lines below have no coverage because `if true` (with the constant literal - // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`. - // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown - // in other tests, the lines below would have coverage (which would show they had `0` - // executions, assuming the condition still evaluated to `true`). - - let _ = Firework { strength: 1000 }; - - Ok(())⦉@5,8,9,10 -}@13⦊‸⦉@13
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#0}-set_strength.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#0}-set_strength.-------.InstrumentCoverage.0.html deleted file mode 100644 index 329641d47b..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#0}-set_strength.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - -generics.{impl#0}-set_strength - Coverage Spans - - - -
@0⦊fn set_strength(&mut self, new_strength: T) { - self.strength = new_strength; - }⦉@0
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#1}-drop.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#1}-drop.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4908bc7b4a..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.generics/generics.{impl#1}-drop.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -generics.{impl#1}-drop - Coverage Spans - - - -
@0,1,2,3⦊fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - }⦉@0,1,2,3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index d6eccf5784..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if/if.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - -if.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let - is_true - = - std::env::args().len() - == - 1 - ; - let - mut - countdown - = - 0 - ; - if - is_true⦉@0,1,2,3 - @4⦊{ - countdown - = - 10 - ; - }⦉@4@5⦊‸⦉@5 -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index e0f0ac4020..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.if_else/if_else.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - -if_else.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if - is_true⦉@0,1,2,3 - @4⦊{ - countdown - = - 10 - ; - }⦉@4 - else // Note coverage region difference without semicolon - { - @5⦊countdown - = - 100⦉@5 - } - - if - @6⦊is_true⦉@6 - @7⦊{ - countdown - = - 10 - ; - }⦉@7 - else - @8⦊{ - countdown - = - 100 - ; - }⦉@8 -}@9⦊‸⦉@9
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html deleted file mode 100644 index 6287516636..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - -inline.display - Coverage Spans - - - -
@0,1⦊fn display<T: Display>(xs: &[T]) ⦉@0,1{ - for @6,8,9,10,11⦊x⦉@6,8,9,10,11 in @6,8,9,10,11⦊xs { - print!("{}", x); - }⦉@6,8,9,10,11 - @5,12,13⦊println!(); -}⦉@5,12,13
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html deleted file mode 100644 index bbf19c3e44..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - -inline.error - Coverage Spans - - - -
@0,1⦊fn error() { - panic!("error"); -}⦉@0,1
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html deleted file mode 100644 index 8e8efb6d9f..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -inline.length - Coverage Spans - - - -
@0,1⦊fn length<T>(xs: &[T]) -> usize { - xs.len() -}⦉@0,1
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4ec2e9beed..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - -inline.main - Coverage Spans - - - -
@0,1⦊fn main() { - permutations(&['a', 'b', 'c']); -}⦉@0,1
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html deleted file mode 100644 index fd72973ccd..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - -inline.permutate - Coverage Spans - - - -
@0,1⦊fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) { - let n = length(xs); - if k == n⦉@0,1 @2,4⦊{ - display(xs); - }⦉@2,4 else if @3⦊k < n⦉@3 { - for @12,14,15,16,17,18⦊i⦉@12,14,15,16,17,18 in @5,7⦊k..n⦉@5,7 @12,14,15,16,17,18⦊{ - swap(xs, i, k); - permutate(xs, k + 1); - swap(xs, i, k); - }⦉@12,14,15,16,17,18 - } else @6,19⦊{ - error(); - }⦉@6,19 -}@21⦊‸⦉@21
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4bfd22f3cd..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - -inline.permutations - Coverage Spans - - - -
@0,1,2,3,4⦊fn permutations<T: Copy + Display>(xs: &[T]) { - let mut ys = xs.to_owned(); - permutate(&mut ys, 0); -}⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4c3f63093d..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - -inline.swap - Coverage Spans - - - -
@0,1,2,3,4⦊fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) { - let t = xs[i]; - xs[i] = xs[j]; - xs[j] = t; -}⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-InTrait-default_trait_func.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-InTrait-default_trait_func.-------.InstrumentCoverage.0.html deleted file mode 100644 index 1dc5bb64e0..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-InTrait-default_trait_func.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - -inner_items.main-InTrait-default_trait_func - Coverage Spans - - - -
@0,1,2⦊fn default_trait_func(&mut self) { - in_func(IN_CONST); - self.trait_func(IN_CONST); - }⦉@0,1,2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-in_func.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-in_func.-------.InstrumentCoverage.0.html deleted file mode 100644 index 82724e5e86..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-in_func.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - -inner_items.main-in_func - Coverage Spans - - - -
@0,1,2,3,4⦊fn in_func(a: u32) { - let b = 1; - let c = a + b; - println!("c = {}", c) - }⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-{impl#0}-trait_func.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-{impl#0}-trait_func.-------.InstrumentCoverage.0.html deleted file mode 100644 index b00a781a0a..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main-{impl#0}-trait_func.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - -inner_items.main-{impl#0}-trait_func - Coverage Spans - - - -
@0,1,2⦊fn trait_func(&mut self, incr: u32) { - self.in_struct_field += incr; - in_func(self.in_struct_field); - }⦉@0,1,2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4a1003dfbe..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inner_items/inner_items.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - -inner_items.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() ⦉@0,1,2,3{ - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let @0,1,2,3⦊is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true⦉@0,1,2,3 @4⦊{ - countdown = 10; - }⦉@4@5⦊‸⦉@5 - - mod in_mod { - const IN_MOD_CONST: u32 = 1000; - } - - fn in_func(a: u32) { - let b = 1; - let c = a + b; - println!("c = {}", c) - } - - struct InStruct { - in_struct_field: u32, - } - - const IN_CONST: u32 = 1234; - - trait InTrait { - fn trait_func(&mut self, incr: u32); - - fn default_trait_func(&mut self) { - in_func(IN_CONST); - self.trait_func(IN_CONST); - } - } - - impl InTrait for InStruct { - fn trait_func(&mut self, incr: u32) { - self.in_struct_field += incr; - in_func(self.in_struct_field); - } - } - - type InType = String; - - if @6⦊is_true⦉@6 @7,9⦊{ - in_func(countdown); - }⦉@7,9@8⦊‸⦉@8 - - let @10,11⦊mut val = InStruct { - in_struct_field: 101, - }; - - val.default_trait_func(); -}⦉@10,11
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 358e2e2bbb..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.lazy_boolean/lazy_boolean.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - -lazy_boolean.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let (mut a, mut b, mut c) = (0, 0, 0); - if is_true⦉@0,1,2,3 @4⦊{ - a = 1; - b = 10; - c = 100; - }⦉@4@5⦊‸⦉@5 - let - @10⦊somebool⦉@10 - = - @6⦊a < b⦉@6 - || - @9⦊b < c⦉@9 - ; - let - @14⦊somebool⦉@14 - = - @10⦊b < a⦉@10 - || - @13⦊b < c⦉@13 - ; - let @18⦊somebool⦉@18 = @14⦊a < b⦉@14 && @17⦊b < c⦉@17; - let @22⦊somebool⦉@22 = @18⦊b < a⦉@18 && @21⦊b < c⦉@21; - - if - @22⦊! - is_true⦉@22 - @23⦊{ - a = 2 - ; - }⦉@23@24⦊‸⦉@24 - - if - @25⦊is_true⦉@25 - @26⦊{ - b = 30 - ; - }⦉@26 - else - @27⦊{ - c = 400 - ; - }⦉@27 - - if @28⦊!is_true⦉@28 @29⦊{ - a = 2; - }⦉@29@30⦊‸⦉@30 - - if @31⦊is_true⦉@31 @32⦊{ - b = 30; - }⦉@32 else @33⦊{ - c = 400; - }⦉@33 -}@34⦊‸⦉@34
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loop_break_value/loop_break_value.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loop_break_value/loop_break_value.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 076d036c2a..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loop_break_value/loop_break_value.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - -loop_break_value.main - Coverage Spans - - - -
@0,1⦊fn main() { - let result - = - loop - { - break - 10 - ; - } - ; -}⦉@0,1
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 95e8f0b71e..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - -loops_branches.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - let debug_test = DebugTest; - println!("{:?}", debug_test); -}⦉@0,1,2,3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html deleted file mode 100644 index f6f08b6a77..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.loops_branches/loops_branches.{impl#0}-fmt.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - -loops_branches.{impl#0}-fmt - Coverage Spans - - - -
@0⦊fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if true⦉@0 { - if @1⦊false⦉@1 { - while @4,5⦊true⦉@4,5 @6,8⦊{ - }⦉@6,8 - }@3⦊‸⦉@3 - @9,10,11,12⦊write!(f, "error")⦉@9,10,11,12@14,16,17,18⦊?⦉@14,16,17,18; - } else @2⦊{ - }⦉@2 - @19⦊Ok(())⦉@19 - }@20⦊‸⦉@20
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 013c292ce9..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - -match_or_pattern.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut a: u8 = 0; - let mut b: u8 = 0; - if is_true⦉@0,1,2,3 @4⦊{ - a = 2; - b = 0; - }⦉@4@5⦊‸⦉@5 - match @6⦊(a, b)⦉@6 { - // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. - // This test confirms a fix for Issue #79569. - (0 | 1, 2 | 3) => @9,10⦊{}⦉@9,10 - _ => @7⦊{}⦉@7 - } - if @11⦊is_true⦉@11 @12⦊{ - a = 0; - b = 0; - }⦉@12@13⦊‸⦉@13 - match @14⦊(a, b)⦉@14 { - (0 | 1, 2 | 3) => @17,18⦊{}⦉@17,18 - _ => @15⦊{}⦉@15 - } - if @19⦊is_true⦉@19 @20⦊{ - a = 2; - b = 2; - }⦉@20@21⦊‸⦉@21 - match @22⦊(a, b)⦉@22 { - (0 | 1, 2 | 3) => @25,26⦊{}⦉@25,26 - _ => @23⦊{}⦉@23 - } - if @27⦊is_true⦉@27 @28⦊{ - a = 0; - b = 2; - }⦉@28@29⦊‸⦉@29 - match @30⦊(a, b)⦉@30 { - (0 | 1, 2 | 3) => @33,34⦊{}⦉@33,34 - _ => @31⦊{}⦉@31 - } -}@35⦊‸⦉@35
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 1abc24156d..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.nested_loops/nested_loops.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - -nested_loops.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - let is_true = std::env::args().len() == 1; - let mut countdown = 10⦉@0,1,2,3; - - 'outer: while @4,5⦊countdown > 0⦉@4,5 { - let @6,8,9⦊mut a = 100; - let mut b = 100⦉@6,8,9; - for @14,16⦊_⦉@14,16 in @10,11,12⦊0..50⦉@10,11,12 { - if @14,16⦊a < 30⦉@14,16 { - @17⦊break⦉@17; - }@18,19,20⦊ - a -= 5; - b -= 5; - if b < 90⦉@18,19,20 { - @21,23⦊a -= 10; - if is_true⦉@21,23 { - @24⦊break 'outer⦉@24; - } else @25,26⦊{ - a -= 2; - }⦉@25,26 - }@22⦊‸⦉@22 - } - @28,29⦊countdown -= 1⦉@28,29; - } -}@30⦊‸⦉@30
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 2a9b1b10ef..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - -overflow.main - Coverage Spans - - - -
@0⦊fn main() -> Result<(),u8> { - let mut countdown = 10⦉@0; - while @1,2⦊countdown > 0⦉@1,2 { - if @3,5⦊countdown == 1⦉@3,5 @6,8,9,10,11⦊{ - let result = might_overflow(10); - println!("Result: {}", result); - }⦉@6,8,9,10,11 else if @7⦊countdown < 5⦉@7 @12,14,15,16,17⦊{ - let result = might_overflow(1); - println!("Result: {}", result); - }⦉@12,14,15,16,17@13⦊‸⦉@13 - @19,20⦊countdown -= 1⦉@19,20; - } - @4⦊Ok(()) -}⦉@4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html deleted file mode 100644 index c6043f0bd0..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.overflow/overflow.might_overflow.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,394 +0,0 @@ - - - - -overflow.might_overflow - Coverage Spans - - - -
@0⦊fn might_overflow(to_add: u32) -> u32 { - if to_add > 5⦉@0 @1,3,4⦊{ - println!("this will probably overflow"); - }⦉@1,3,4@2⦊‸⦉@2 - let @5,6,7,8,9,10,11,12,13⦊add_to = u32::MAX - 5; - println!("does {} + {} overflow?", add_to, to_add); - let result = to_add + add_to; - println!("continuing after overflow check"); - result -}⦉@5,6,7,8,9,10,11,12,13
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 5b097f118e..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - -panic_unwind.main - Coverage Spans - - - -
@0⦊fn main() -> Result<(), u8> { - let mut countdown = 10⦉@0; - while @1,2⦊countdown > 0⦉@1,2 { - if @3,5⦊countdown == 1⦉@3,5 @6,8⦊{ - might_panic(true); - }⦉@6,8 else if @7⦊countdown < 5⦉@7 @9,11⦊{ - might_panic(false); - }⦉@9,11@10⦊‸⦉@10 - @13,14⦊countdown -= 1⦉@13,14; - } - @4⦊Ok(()) -}⦉@4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html deleted file mode 100644 index 32988629ba..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.panic_unwind/panic_unwind.might_panic.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - -panic_unwind.might_panic - Coverage Spans - - - -
@0⦊fn might_panic(should_panic: bool) ⦉@0{ - if @0⦊should_panic⦉@0 { - @1,3,4⦊println!("panicking..."); - panic!("panics");⦉@1,3,4 - } else @2,5,6⦊{ - println!("Don't Panic"); - } -}⦉@2,5,6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 3e307c4f46..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,295 +0,0 @@ - - - - -partial_eq.main - Coverage Spans - - - -
@0,1,2,3,4,5,6,7,8⦊fn main() { - let version_3_2_1 = Version::new(3, 2, 1); - let version_3_3_0 = Version::new(3, 3, 0); - - println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); -}⦉@0,1,2,3,4,5,6,7,8
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#0}-new.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#0}-new.-------.InstrumentCoverage.0.html deleted file mode 100644 index 820ccf74d1..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#0}-new.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - -partial_eq.{impl#0}-new - Coverage Spans - - - -
@0⦊pub fn new(major: usize, minor: usize, patch: usize) -> Self { - Self { - major, - minor, - patch, - } - }⦉@0
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#1}-cmp.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#1}-cmp.-------.InstrumentCoverage.0.html deleted file mode 100644 index ee4c10afd8..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#1}-cmp.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -partial_eq.{impl#1}-cmp - Coverage Spans - - - -
@0,1⦊‸⦉@0,1Ord@15⦊‸⦉@15
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html deleted file mode 100644 index 2f5092bd51..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#2}-partial_cmp.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -partial_eq.{impl#2}-partial_cmp - Coverage Spans - - - -
@0,1⦊‸⦉@0,1PartialOrd@18⦊‸⦉@18
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#4}-assert_receiver_is_total_eq.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#4}-assert_receiver_is_total_eq.-------.InstrumentCoverage.0.html deleted file mode 100644 index ebb8b1c15c..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#4}-assert_receiver_is_total_eq.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -partial_eq.{impl#4}-assert_receiver_is_total_eq - Coverage Spans - - - -
@0⦊‸⦉@0Eq
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html deleted file mode 100644 index 2e128181c5..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-eq.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -partial_eq.{impl#6}-eq - Coverage Spans - - - -
@0⦊‸⦉@0PartialEq@4⦊‸⦉@4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html deleted file mode 100644 index 637b1c6208..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#6}-ne.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - -partial_eq.{impl#6}-ne - Coverage Spans - - - -
@0⦊‸⦉@0PartialEq@4⦊‸⦉@4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html deleted file mode 100644 index 930492f248..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - -partial_eq.{impl#7}-fmt - Coverage Spans - - - -
@0,1,2,3,4,5⦊Debug⦉@0,1,2,3,4,5
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#8}-clone.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#8}-clone.-------.InstrumentCoverage.0.html deleted file mode 100644 index f1c9839334..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#8}-clone.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - -partial_eq.{impl#8}-clone - Coverage Spans - - - -
@0,1,2,3⦊Clone⦉@0,1,2,3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 6b911eea34..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_loop/simple_loop.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - -simple_loop.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - - if - is_true⦉@0,1,2,3 - @4⦊{ - countdown - = - 10 - ; - }⦉@4@5⦊‸⦉@5 - - loop - { - if - @7,8⦊countdown - == - 0⦉@7,8 - { - @9⦊break⦉@9 - ; - }@10,11⦊ - countdown - -= - 1⦉@10,11 - ; - } -}@9⦊‸⦉@9
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index a56692d9c2..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.simple_match/simple_match.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - -simple_match.main - Coverage Spans - - - -
@0,1,2,3⦊fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 1; - if is_true⦉@0,1,2,3 @4⦊{ - countdown = 0; - }⦉@4@5⦊‸⦉@5 - - for - @12,14,16⦊_⦉@12,14,16 - in - @8,9,10⦊0..2⦉@8,9,10 - { - let z - ; - match - @12,14,16⦊countdown⦉@12,14,16 - { - @17⦊x⦉@17 - if - @12,14,16⦊x - < - 1⦉@12,14,16 - => - @17⦊{ - z = countdown - ; - let y = countdown - ; - countdown = 10 - ; - }⦉@17 - _ - => - @15⦊{}⦉@15 - } - } -}@11⦊‸⦉@11
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 8cbd265c6a..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.tight_inf_loop/tight_inf_loop.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - -tight_inf_loop.main - Coverage Spans - - - -
@0⦊fn main() { - if false⦉@0 { - @3,4⦊loop {}⦉@3,4 - }@2⦊ -}⦉@2
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html deleted file mode 100644 index a8a3139334..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.call.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -try_error_result.call - Coverage Spans - - - -
@0⦊fn call(return_error: bool) -> Result<(),()> { - if return_error⦉@0 { - @1⦊Err(())⦉@1 - } else { - @2⦊Ok(())⦉@2 - } -}@3⦊‸⦉@3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 5b0c5cb072..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.try_error_result/try_error_result.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - -try_error_result.main - Coverage Spans - - - -
@0,1⦊fn main() -> Result<(),()> { - let mut - countdown = 10⦉@0,1 - ; - for - @6,8,9⦊_⦉@6,8,9 - in - @2,3,4⦊0..10⦉@2,3,4 - { - @6,8,9⦊countdown - -= 1 - ; - if - countdown < 5⦉@6,8,9 - { - @10,12,13⦊call(/*return_error=*/ true)⦉@10,12,13@15,17,18,19⦊?⦉@15,17,18,19; - @14,20,21⦊call(/*return_error=*/ false)⦉@14,20,21@23,25,26,27⦊?⦉@23,25,26,27; - } - else - { - @11,28,29⦊call(/*return_error=*/ false)⦉@11,28,29@31,33,34,35⦊?⦉@31,33,34,35; - } - } - @5⦊Ok(())⦉@5 -}@38⦊‸⦉@38
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index 65e21ecef1..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - -used_crate.unused_function - Coverage Spans - - - -
@0,1,2,3⦊pub fn unused_function() { - let is_true = std::env::args().len() == 1; - let mut countdown = 2; - if !is_true⦉@0,1,2,3 @4⦊{ - countdown = 20; - }⦉@4@5⦊‸⦉@5 -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_generic_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_generic_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index 02154a2268..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_generic_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -used_crate.unused_generic_function - Coverage Spans - - - -
@0,1,2,3,4⦊pub fn unused_generic_function<T: Debug>(arg: T) { - println!("unused_generic_function with {:?}", arg); -}⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index 78228594e3..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.unused_private_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - -used_crate.unused_private_function - Coverage Spans - - - -
@0,1,2,3⦊fn unused_private_function() { - let is_true = std::env::args().len() == 1; - let mut countdown = 2; - if !is_true⦉@0,1,2,3 @4⦊{ - countdown = 20; - }⦉@4@5⦊‸⦉@5 -}@6⦊‸⦉@6
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html deleted file mode 100644 index 8f618d2e24..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.use_this_lib_crate.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - -used_crate.use_this_lib_crate - Coverage Spans - - - -
@0,1,2,3,4,5,6,7,8⦊fn use_this_lib_crate() { - used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); - used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - "used from library used_crate.rs", - ); - let some_vec = vec![5, 6, 7, 8]; - used_only_from_this_lib_crate_generic_function(some_vec); - used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); -}⦉@0,1,2,3,4,5,6,7,8
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index 61a709c472..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -used_crate.used_from_bin_crate_and_lib_crate_generic_function - Coverage Spans - - - -
@0,1,2,3,4⦊pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); -}⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index 974a24b2c6..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - -used_crate.used_function - Coverage Spans - - - -
@0,1,2,3⦊pub fn used_function() ⦉@0,1,2,3{ - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let @0,1,2,3⦊is_true = std::env::args().len() == 1; - let mut countdown = 0; - if is_true⦉@0,1,2,3 @4⦊{ - countdown = 10; - }⦉@4@5⦊‸⦉@5 - @6,7⦊use_this_lib_crate(); -}⦉@6,7
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_bin_crate_generic_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_bin_crate_generic_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index 68035339fe..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_bin_crate_generic_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -used_crate.used_only_from_bin_crate_generic_function - Coverage Spans - - - -
@0,1,2,3,4⦊pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) { - println!("used_only_from_bin_crate_generic_function with {:?}", arg); -}⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_this_lib_crate_generic_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_this_lib_crate_generic_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index 63944eb9ab..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_only_from_this_lib_crate_generic_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -used_crate.used_only_from_this_lib_crate_generic_function - Coverage Spans - - - -
@0,1,2,3,4⦊pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); -}⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_with_same_type_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_with_same_type_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html deleted file mode 100644 index b146180fbd..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.used_crate/used_crate.used_with_same_type_from_bin_crate_and_lib_crate_generic_function.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -used_crate.used_with_same_type_from_bin_crate_and_lib_crate_generic_function - Coverage Spans - - - -
@0,1,2,3,4⦊pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) { - println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); -}⦉@0,1,2,3,4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 28cf051ecf..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.uses_crate/uses_crate.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - -uses_crate.main - Coverage Spans - - - -
@0,1,2,3,4,5,6,7,8,9⦊fn main() { - used_crate::used_function(); - let some_vec = vec![1, 2, 3, 4]; - used_crate::used_only_from_bin_crate_generic_function(&some_vec); - used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); - used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); - used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?"); -}⦉@0,1,2,3,4,5,6,7,8,9
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index f037a8ee5c..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while/while.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - -while.main - Coverage Spans - - - -
@0⦊fn main() { - let num = 9⦉@0; - while @1,2⦊num >= 10⦉@1,2 @3,5⦊{ - }⦉@3,5 -}@4⦊‸⦉@4
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index fcb5418e1d..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.while_early_ret/while_early_ret.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - -while_early_ret.main - Coverage Spans - - - -
@0⦊fn main() -> Result<(),u8> { - let mut countdown = 10⦉@0; - while - @1,2⦊countdown - > - 0⦉@1,2 - { - if - @3,5⦊countdown - < - 5⦉@3,5 - { - return - if - @6⦊countdown - > - 8⦉@6 - { - @8⦊Ok(())⦉@8 - } - else - { - @9⦊Err(1)⦉@9 - } - ; - }@7,11⦊ - countdown - -= - 1⦉@7,11 - ; - } - @4⦊Ok(())⦉@4 -}@12⦊‸⦉@12
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#0}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#0}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 1e68c345f8..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#0}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - -yield.main-{closure#0} - Coverage Spans - - - -
|| @0⦊{ - yield 1⦉@0; - return @1⦊"foo" - }⦉@1
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#1}.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#1}.-------.InstrumentCoverage.0.html deleted file mode 100644 index 842d7823bf..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main-{closure#1}.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - -yield.main-{closure#1} - Coverage Spans - - - -
|| @0⦊{ - yield 1⦉@0; - @1⦊yield 2⦉@1; - @2⦊yield 3⦉@2; - return @3⦊"foo" - }⦉@3
- - diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main.-------.InstrumentCoverage.0.html deleted file mode 100644 index 4c0c0d562b..0000000000 --- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.yield/yield.main.-------.InstrumentCoverage.0.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - -yield.main - Coverage Spans - - - -
@0,1,2⦊fn main() ⦉@0,1,2{ - let @0,1,2⦊mut generator⦉@0,1,2 = || { - yield 1; - return "foo" - }; - - match @0,1,2⦊Pin::new(&mut generator).resume(()) { - GeneratorState::Yielded(1)⦉@0,1,2 => @4,6,7,8⦊{}⦉@4,6,7,8 - _ => @5⦊panic!("unexpected value from resume")⦉@5, - } - match @4,6,7,8⦊Pin::new(&mut generator).resume(())⦉@4,6,7,8 { - GeneratorState::Complete(@10,11⦊"foo"⦉@10,11) => @12,13,14,15⦊{}⦉@12,13,14,15 - _ => @9⦊panic!("unexpected value from resume")⦉@9, - } - - let @12,13,14,15⦊mut generator⦉@12,13,14,15 = || { - yield 1; - yield 2; - yield 3; - return "foo" - }; - - match @12,13,14,15⦊Pin::new(&mut generator).resume(()) { - GeneratorState::Yielded(1)⦉@12,13,14,15 => @17,19,20,21⦊{}⦉@17,19,20,21 - _ => @18⦊panic!("unexpected value from resume")⦉@18, - } - match @17,19,20,21⦊Pin::new(&mut generator).resume(()) { - GeneratorState::Yielded(2)⦉@17,19,20,21 => @23,25⦊{}⦉@23,25 - _ => @24⦊panic!("unexpected value from resume")⦉@24, - } -}@23,25⦊‸⦉@23,25
- - diff --git a/src/test/run-make-fulldeps/coverage/async.rs b/src/test/run-make-fulldeps/coverage/async.rs index d5ec32deac..a6e3877470 100644 --- a/src/test/run-make-fulldeps/coverage/async.rs +++ b/src/test/run-make-fulldeps/coverage/async.rs @@ -1,6 +1,6 @@ #![allow(unused_assignments, dead_code)] -// compile-flags: --edition=2018 +// compile-flags: --edition=2018 -C opt-level=1 async fn c(x: u8) -> u8 { if x == 8 { @@ -63,7 +63,7 @@ fn j(x: u8) { 0 } } - fn d() -> u8 { 1 } + fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed fn f() -> u8 { 1 } match x { y if c(x) == y + 1 => { d(); } @@ -109,11 +109,11 @@ mod executor { pub fn block_on(mut future: F) -> F::Output { let mut future = unsafe { Pin::new_unchecked(&mut future) }; - + use std::hint::unreachable_unchecked; static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unimplemented!("clone"), - |_| unimplemented!("wake"), - |_| unimplemented!("wake_by_ref"), + |_| unsafe { unreachable_unchecked() }, // clone + |_| unsafe { unreachable_unchecked() }, // wake + |_| unsafe { unreachable_unchecked() }, // wake_by_ref |_| (), ); let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; diff --git a/src/test/run-make-fulldeps/coverage/async2.rs b/src/test/run-make-fulldeps/coverage/async2.rs new file mode 100644 index 0000000000..6171d95ff5 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/async2.rs @@ -0,0 +1,69 @@ +// compile-flags: --edition=2018 + +use core::{ + future::Future, + marker::Send, + pin::Pin, +}; + +fn non_async_func() { + println!("non_async_func was covered"); + let b = true; + if b { + println!("non_async_func println in block"); + } +} + +// FIXME(#83985): The auto-generated closure in an async function is failing to include +// the println!() and `let` assignment lines in the coverage code region(s), as it does in the +// non-async function above, unless the `println!()` is inside a covered block. +async fn async_func() { + println!("async_func was covered"); + let b = true; + if b { + println!("async_func println in block"); + } +} + +// FIXME(#83985): As above, this async function only has the `println!()` macro call, which is not +// showing coverage, so the entire async closure _appears_ uncovered; but this is not exactly true. +// It's only certain kinds of lines and/or their context that results in missing coverage. +async fn async_func_just_println() { + println!("async_func_just_println was covered"); +} + +fn main() { + println!("codecovsample::main"); + + non_async_func(); + + executor::block_on(async_func()); + executor::block_on(async_func_just_println()); +} + +mod executor { + use core::{ + future::Future, + pin::Pin, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + }; + + pub fn block_on(mut future: F) -> F::Output { + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + use std::hint::unreachable_unchecked; + static VTABLE: RawWakerVTable = RawWakerVTable::new( + |_| unsafe { unreachable_unchecked() }, // clone + |_| unsafe { unreachable_unchecked() }, // wake + |_| unsafe { unreachable_unchecked() }, // wake_by_ref + |_| (), + ); + let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + let mut context = Context::from_waker(&waker); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} diff --git a/src/test/run-make-fulldeps/coverage/closure.rs b/src/test/run-make-fulldeps/coverage/closure.rs index 914cb0fe05..796512f0c7 100644 --- a/src/test/run-make-fulldeps/coverage/closure.rs +++ b/src/test/run-make-fulldeps/coverage/closure.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments, unused_variables)] - +// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/src/test/run-make-fulldeps/coverage/continue.rs b/src/test/run-make-fulldeps/coverage/continue.rs new file mode 100644 index 0000000000..624aa98341 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/continue.rs @@ -0,0 +1,69 @@ +#![allow(unused_assignments, unused_variables)] + +fn main() { + let is_true = std::env::args().len() == 1; + + let mut x = 0; + for _ in 0..10 { + match is_true { + true => { + continue; + } + _ => { + x = 1; + } + } + x = 3; + } + for _ in 0..10 { + match is_true { + false => { + x = 1; + } + _ => { + continue; + } + } + x = 3; + } + for _ in 0..10 { + match is_true { + true => { + x = 1; + } + _ => { + continue; + } + } + x = 3; + } + for _ in 0..10 { + if is_true { + continue; + } + x = 3; + } + for _ in 0..10 { + match is_true { + false => { + x = 1; + } + _ => { + let _ = x; + } + } + x = 3; + } + for _ in 0..10 { + match is_true { + false => { + x = 1; + } + _ => { + break; + } + } + x = 3; + } + let _ = x; +} diff --git a/src/test/run-make-fulldeps/coverage/coverage_tools.mk b/src/test/run-make-fulldeps/coverage/coverage_tools.mk index 38643aaf90..aa1dc7b91c 100644 --- a/src/test/run-make-fulldeps/coverage/coverage_tools.mk +++ b/src/test/run-make-fulldeps/coverage/coverage_tools.mk @@ -4,11 +4,3 @@ # -include ../coverage/coverage_tools.mk -include ../tools.mk - -# ISSUE(76038): When targeting MSVC, Rust binaries built with both `-Z instrument-coverage` and -# `-C link-dead-code` typically crash (with a seg-fault) or at best generate an empty `*.profraw` -# file, required for coverage reports. -# -# Enabling `-C link-dead-code` is not necessary when compiling with `-Z instrument-coverage`, -# due to improvements in the coverage map generation, to add unreachable functions known to Rust. -# Therefore, `-C link-dead-code` is no longer automatically enabled. diff --git a/src/test/run-make-fulldeps/coverage/issue-83601.rs b/src/test/run-make-fulldeps/coverage/issue-83601.rs new file mode 100644 index 0000000000..0b72a81947 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/issue-83601.rs @@ -0,0 +1,14 @@ +// Shows that rust-lang/rust/83601 is resolved + +#[derive(Debug, PartialEq, Eq)] +struct Foo(u32); + +fn main() { + let bar = Foo(1); + assert_eq!(bar, Foo(1)); + let baz = Foo(0); + assert_ne!(baz, Foo(1)); + println!("{:?}", Foo(1)); + println!("{:?}", bar); + println!("{:?}", baz); +} diff --git a/src/test/run-make-fulldeps/coverage/lib/used_crate.rs b/src/test/run-make-fulldeps/coverage/lib/used_crate.rs index e5555f9193..eaa93115ae 100644 --- a/src/test/run-make-fulldeps/coverage/lib/used_crate.rs +++ b/src/test/run-make-fulldeps/coverage/lib/used_crate.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments, unused_variables)] - +// compile-flags: -C opt-level=3 # validates coverage now works with optimizations use std::fmt::Debug; pub fn used_function() { @@ -17,7 +17,7 @@ pub fn used_function() { pub fn used_only_from_bin_crate_generic_function(arg: T) { println!("used_only_from_bin_crate_generic_function with {:?}", arg); } - +// Expect for above function: `Unexecuted instantiation` (see below) pub fn used_only_from_this_lib_crate_generic_function(arg: T) { println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); } @@ -60,45 +60,41 @@ fn use_this_lib_crate() { used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); } -// FIXME(#79651): `used_from_bin_crate_and_lib_crate_generic_function()` is covered and executed -// `2` times, but the coverage output also shows (at the bottom of the coverage report): -// ------------------ -// | Unexecuted instantiation: -// ------------------ +// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results, +// for example: // -// Note, the function name shown in the error seems to change depending on the structure of the -// code, for some reason, including: +// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_> // -// * used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str> -// * used_crate::use_this_lib_crate +// These notices appear when `llvm-cov` shows instantiations. This may be a +// default option, but it can be suppressed with: // -// The `Unexecuted instantiation` error may be related to more than one generic function. Since the -// reporting is not consistent, it may not be obvious if there are multiple problems here; however, -// `used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>` (which I have seen -// with this error) is the only generic function missing instantiaion coverage counts. +// ```shell +// $ `llvm-cov show --show-instantiations=0 ...` +// ``` // -// The `&str` variant was called from within this `lib` crate, and the `bin` crate also calls this -// function, but with `T` type `&Vec`. +// The notice is triggered because the function is unused by the library itself, +// and when the library is compiled, a synthetic function is generated, so +// unused function coverage can be reported. Coverage can be skipped for unused +// generic functions with: // -// I believe the reason is that one or both crates are generating `Zero` counters for what it -// believes are "Unreachable" instantiations, but those instantiations are counted from the -// coverage map in the other crate. +// ```shell +// $ `rustc -Z instrument-coverage=except-unused-generics ...` +// ``` // -// See `add_unreachable_coverage()` in `mapgen.rs` for more on how these `Zero` counters are added -// for what the funciton believes are `DefId`s that did not get codegenned. I suspect the issue -// may be related to this process, but this needs to be confirmed. It may not be possible to know -// for sure if a function is truly unused and should be reported with `Zero` coverage if it may -// still get used from an external crate. (Something to look at: If the `DefId` in MIR corresponds -// _only_ to the generic function without type parameters, is the `DefId` in the codegenned set, -// instantiated with one of the type parameters (in either or both crates) a *different* `DefId`? -// If so, `add_unreachable_coverage()` would assume the MIR `DefId` was uncovered, and would add -// unreachable coverage. +// Even though this function is used by `uses_crate.rs` (and +// counted), with substitutions for `T`, those instantiations are only generated +// when the generic function is actually used (from the binary, not from this +// library crate). So the test result shows coverage for all instantiated +// versions and their generic type substitutions, plus the `Unexecuted +// instantiation` message for the non-substituted version. This is valid, but +// unfortunately a little confusing. // -// I didn't think they could be different, but if they can, we would need to find the `DefId` for -// the generic function MIR and include it in the set of "codegenned" DefIds if any instantiation -// of that generic function does exist. +// The library crate has its own coverage map, and the only way to show unused +// coverage of a generic function is to include the generic function in the +// coverage map, marked as an "unused function". If the library were used by +// another binary that never used this generic function, then it would be valid +// to show the unused generic, with unknown substitution (`_`). // -// Note, however, for `used_with_same_type_from_bin_crate_and_lib_crate_generic_function()` both -// crates use this function with the same type variant. The function does not have multiple -// instantiations, so the coverage analysis is not confused. No "Unexecuted instantiations" errors -// are reported. +// The alternative is to exclude all generics from being included in the "unused +// functions" list, which would then omit coverage results for +// `unused_generic_function()`, below. diff --git a/src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs b/src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs new file mode 100644 index 0000000000..4a052756d4 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/lib/used_inline_crate.rs @@ -0,0 +1,90 @@ +#![allow(unused_assignments, unused_variables)] + +// compile-flags: -C opt-level=3 # validates coverage now works with optimizations + +use std::fmt::Debug; + +pub fn used_function() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + let mut countdown = 0; + if is_true { + countdown = 10; + } + use_this_lib_crate(); +} + +#[inline(always)] +pub fn used_inline_function() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + let mut countdown = 0; + if is_true { + countdown = 10; + } + use_this_lib_crate(); +} + + + + + + + +#[inline(always)] +pub fn used_only_from_bin_crate_generic_function(arg: T) { + println!("used_only_from_bin_crate_generic_function with {:?}", arg); +} +// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) + +#[inline(always)] +pub fn used_only_from_this_lib_crate_generic_function(arg: T) { + println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { + println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { + println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn unused_generic_function(arg: T) { + println!("unused_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn unused_function() { + let is_true = std::env::args().len() == 1; + let mut countdown = 2; + if !is_true { + countdown = 20; + } +} + +#[inline(always)] +fn unused_private_function() { + let is_true = std::env::args().len() == 1; + let mut countdown = 2; + if !is_true { + countdown = 20; + } +} + +fn use_this_lib_crate() { + used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); + used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + "used from library used_crate.rs", + ); + let some_vec = vec![5, 6, 7, 8]; + used_only_from_this_lib_crate_generic_function(some_vec); + used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); +} diff --git a/src/test/run-make-fulldeps/coverage/loops_branches.rs b/src/test/run-make-fulldeps/coverage/loops_branches.rs index 938421d32e..4d9bbad336 100644 --- a/src/test/run-make-fulldeps/coverage/loops_branches.rs +++ b/src/test/run-make-fulldeps/coverage/loops_branches.rs @@ -1,7 +1,7 @@ #![allow(unused_assignments, unused_variables, while_true)] -// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the -// structure of this `fmt` function. +// This test confirms that (1) unexecuted infinite loops are handled correctly by the +// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. struct DebugTest; @@ -15,6 +15,40 @@ impl std::fmt::Debug for DebugTest { write!(f, "error")?; } else { } + + for i in 0..10 { + if true { + if false { + while true {} + } + write!(f, "error")?; + } else { + } + } + Ok(()) + } +} + +struct DisplayTest; + +impl std::fmt::Display for DisplayTest { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if false { + } else { + if false { + while true {} + } + write!(f, "error")?; + } + for i in 0..10 { + if false { + } else { + if false { + while true {} + } + write!(f, "error")?; + } + } Ok(()) } } @@ -22,15 +56,6 @@ impl std::fmt::Debug for DebugTest { fn main() { let debug_test = DebugTest; println!("{:?}", debug_test); + let display_test = DisplayTest; + println!("{}", display_test); } - -/* - -This is the error message generated, before the issue was fixed: - -error: internal compiler error: compiler/rustc_mir/src/transform/coverage/mod.rs:374:42: -Error processing: DefId(0:6 ~ bug_incomplete_cov_graph_traversal_simplified[317d]::{impl#0}::fmt): -Error { message: "`TraverseCoverageGraphWithLoops` missed some `BasicCoverageBlock`s: -[bcb6, bcb7, bcb9]" } - -*/ diff --git a/src/test/run-make-fulldeps/coverage/no_cov_crate.rs b/src/test/run-make-fulldeps/coverage/no_cov_crate.rs new file mode 100644 index 0000000000..300570db7e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/no_cov_crate.rs @@ -0,0 +1,17 @@ +// Enables `no_coverage` on the entire crate +#![feature(no_coverage)] + +#[no_coverage] +fn do_not_add_coverage_1() { + println!("called but not covered"); +} + +#[no_coverage] +fn do_not_add_coverage_2() { + println!("called but not covered"); +} + +fn main() { + do_not_add_coverage_1(); + do_not_add_coverage_2(); +} diff --git a/src/test/run-make-fulldeps/coverage/try_error_result.rs b/src/test/run-make-fulldeps/coverage/try_error_result.rs index 13c455172d..cd0acf7230 100644 --- a/src/test/run-make-fulldeps/coverage/try_error_result.rs +++ b/src/test/run-make-fulldeps/coverage/try_error_result.rs @@ -9,7 +9,7 @@ fn call(return_error: bool) -> Result<(),()> { } } -fn main() -> Result<(),()> { +fn test1() -> Result<(),()> { let mut countdown = 10 ; @@ -34,3 +34,85 @@ fn main() -> Result<(),()> { } Ok(()) } + +struct Thing1; +impl Thing1 { + fn get_thing_2(&self, return_error: bool) -> Result { + if return_error { + Err(()) + } else { + Ok(Thing2{}) + } + } +} + +struct Thing2; +impl Thing2 { + fn call(&self, return_error: bool) -> Result { + if return_error { + Err(()) + } else { + Ok(57) + } + } +} + +fn test2() -> Result<(),()> { + let thing1 = Thing1{}; + let mut + countdown = 10 + ; + for + _ + in + 0..10 + { + countdown + -= 1 + ; + if + countdown < 5 + { + thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); + thing1 + . + get_thing_2(/*return_error=*/ false) + ? + . + call(/*return_error=*/ true) + . + expect_err( + "call should fail" + ); + let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; + assert_eq!(val, 57); + let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; + assert_eq!(val, 57); + } + else + { + let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; + assert_eq!(val, 57); + let val = thing1 + .get_thing_2(/*return_error=*/ false)? + .call(/*return_error=*/ false)?; + assert_eq!(val, 57); + let val = thing1 + .get_thing_2(/*return_error=*/ false) + ? + .call(/*return_error=*/ false) + ? + ; + assert_eq!(val, 57); + } + } + Ok(()) +} + +fn main() -> Result<(),()> { + test1().expect_err("test1 should fail"); + test2() + ? + ; + Ok(()) +} diff --git a/src/test/run-make-fulldeps/coverage/unused.rs b/src/test/run-make-fulldeps/coverage/unused.rs new file mode 100644 index 0000000000..fb6113eb01 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/unused.rs @@ -0,0 +1,39 @@ +fn foo(x: T) { + let mut i = 0; + while i < 10 { + i != 0 || i != 0; + i += 1; + } +} + +fn unused_template_func(x: T) { + let mut i = 0; + while i < 10 { + i != 0 || i != 0; + i += 1; + } +} + +fn unused_func(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn unused_func2(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn unused_func3(mut a: u32) { + if a != 0 { + a += 1; + } +} + +fn main() -> Result<(), u8> { + foo::(0); + foo::(0.0); + Ok(()) +} diff --git a/src/test/run-make-fulldeps/coverage/uses_crate.rs b/src/test/run-make-fulldeps/coverage/uses_crate.rs index 8d24b1ca3e..20cb05fe5b 100644 --- a/src/test/run-make-fulldeps/coverage/uses_crate.rs +++ b/src/test/run-make-fulldeps/coverage/uses_crate.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments, unused_variables)] - +// compile-flags: -C opt-level=3 # validates coverage now works with optimizations extern crate used_crate; fn main() { diff --git a/src/test/run-make-fulldeps/coverage/uses_inline_crate.rs b/src/test/run-make-fulldeps/coverage/uses_inline_crate.rs new file mode 100644 index 0000000000..a7fe8532be --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/uses_inline_crate.rs @@ -0,0 +1,17 @@ +#![allow(unused_assignments, unused_variables)] + +// compile-flags: -C opt-level=3 # validates coverage now works with optimizations + +extern crate used_inline_crate; + +fn main() { + used_inline_crate::used_function(); + used_inline_crate::used_inline_function(); + let some_vec = vec![1, 2, 3, 4]; + used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec); + used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); + used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); + used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + "interesting?", + ); +} diff --git a/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile b/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile index 50ff3dd56c..371f94715a 100644 --- a/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile +++ b/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile @@ -1,7 +1,7 @@ -include ../tools.mk # rust-lang/rust#70924: Test that if we add rust-src component in between two -# incremetnal compiles, the compiler does not ICE on the second. +# incremental compiles, the compiler does not ICE on the second. # This test uses `ln -s` rather than copying to save testing time, but its # usage doesn't work on windows. So ignore windows. diff --git a/src/test/run-make-fulldeps/issue-47551/Makefile b/src/test/run-make-fulldeps/issue-47551/Makefile new file mode 100644 index 0000000000..f4495e6b67 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-47551/Makefile @@ -0,0 +1,9 @@ +# only-linux +# ignore-32bit + +-include ../tools.mk + +all: + $(RUSTC) eh_frame-terminator.rs + $(call RUN,eh_frame-terminator) | $(CGREP) '1122334455667788' + objdump --dwarf=frames $(TMPDIR)/eh_frame-terminator | $(CGREP) 'ZERO terminator' diff --git a/src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs b/src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs new file mode 100644 index 0000000000..2f740dc4fa --- /dev/null +++ b/src/test/run-make-fulldeps/issue-47551/eh_frame-terminator.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(backtrace)] +#[derive(Clone, Copy)] +struct Foo { + array: [u64; 10240], +} + +impl Foo { + const fn new() -> Self { + Self { + array: [0x1122_3344_5566_7788; 10240] + } + } +} + +static BAR: [Foo; 10240] = [Foo::new(); 10240]; + +fn main() { + let bt = std::backtrace::Backtrace::force_capture(); + println!("Hello, world! {:?}", bt); + println!("{:x}", BAR[0].array[0]); +} diff --git a/src/test/run-make-fulldeps/issue-83045/Makefile b/src/test/run-make-fulldeps/issue-83045/Makefile new file mode 100644 index 0000000000..34853cb1d3 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/Makefile @@ -0,0 +1,33 @@ +include ../../run-make-fulldeps/tools.mk + +# This test case creates a situation where the crate loader would run +# into an ICE when confronted with an invalid setup where it cannot +# find the dependency of a direct dependency. +# +# The test case makes sure that the compiler produces the expected +# error message but does not ICE immediately after. +# +# See https://github.com/rust-lang/rust/issues/83045 + +# This is a platform-independent issue, no need to waste time testing +# everywhere. +# only-x86_64 +# only-linux + +# NOTE: We use BARE_RUSTC below so that the compiler can't find liba.rlib +# If we used RUSTC the additional '-L TMPDIR' option would allow rustc to +# actually find the crate. +# +# We check that we get the expected error message +# But that we do not get an ICE + +all: + $(RUSTC) --crate-name=a --crate-type=rlib a.rs --verbose + $(RUSTC) --crate-name=b --crate-type=rlib --extern a=$(TMPDIR)/liba.rlib b.rs --verbose + $(BARE_RUSTC) --out-dir $(TMPDIR) \ + --extern b=$(TMPDIR)/libb.rlib \ + --crate-type=rlib \ + --edition=2018 \ + c.rs 2>&1 | tee $(TMPDIR)/output.txt || exit 0 + $(CGREP) E0463 < $(TMPDIR)/output.txt + $(CGREP) -v "internal compiler error" < $(TMPDIR)/output.txt diff --git a/src/test/run-make-fulldeps/issue-83045/a.rs b/src/test/run-make-fulldeps/issue-83045/a.rs new file mode 100644 index 0000000000..66d9f758e9 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/a.rs @@ -0,0 +1 @@ +// empty on purpose diff --git a/src/test/run-make-fulldeps/issue-83045/b.rs b/src/test/run-make-fulldeps/issue-83045/b.rs new file mode 100644 index 0000000000..f4876cfa45 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/b.rs @@ -0,0 +1 @@ +extern crate a; diff --git a/src/test/run-make-fulldeps/issue-83045/c.rs b/src/test/run-make-fulldeps/issue-83045/c.rs new file mode 100644 index 0000000000..e0c4525499 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-83045/c.rs @@ -0,0 +1 @@ +use b as _; diff --git a/src/test/run-make-fulldeps/link-args-order/Makefile b/src/test/run-make-fulldeps/link-args-order/Makefile index 98c1e0eac3..f94e882ccb 100644 --- a/src/test/run-make-fulldeps/link-args-order/Makefile +++ b/src/test/run-make-fulldeps/link-args-order/Makefile @@ -6,5 +6,5 @@ RUSTC_FLAGS = -C linker-flavor=ld -C link-arg=a -C link-args="b c" -C link-args= RUSTC_FLAGS_PRE = -C linker-flavor=ld -Z pre-link-arg=a -Z pre-link-args="b c" -Z pre-link-args="d e" -Z pre-link-arg=f all: - $(RUSTC) $(RUSTC_FLAGS) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f" "g"' + $(RUSTC) $(RUSTC_FLAGS) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f"' $(RUSTC) $(RUSTC_FLAGS_PRE) empty.rs 2>&1 | $(CGREP) '"a" "b" "c" "d" "e" "f"' diff --git a/src/test/run-make-fulldeps/link-args-order/empty.rs b/src/test/run-make-fulldeps/link-args-order/empty.rs index 2439171004..f328e4d9d0 100644 --- a/src/test/run-make-fulldeps/link-args-order/empty.rs +++ b/src/test/run-make-fulldeps/link-args-order/empty.rs @@ -1,6 +1 @@ -#![feature(link_args)] - -#[link_args = "g"] -extern "C" {} - fn main() {} diff --git a/src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt b/src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt index c5a9bf2438..4b20cd5d74 100644 --- a/src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt +++ b/src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt @@ -6,10 +6,11 @@ FiraSans-Regular.woff FiraSans-Regular.woff2 LICENSE-APACHE.txt LICENSE-MIT.txt +SourceCodePro-It.ttf.woff SourceCodePro-LICENSE.txt -SourceCodePro-Regular.woff -SourceCodePro-Semibold.woff -SourceSerifPro-Bold.ttf.woff -SourceSerifPro-It.ttf.woff -SourceSerifPro-LICENSE.md -SourceSerifPro-Regular.ttf.woff +SourceCodePro-Regular.ttf.woff +SourceCodePro-Semibold.ttf.woff +SourceSerif4-Bold.ttf.woff +SourceSerif4-It.ttf.woff +SourceSerif4-LICENSE.md +SourceSerif4-Regular.ttf.woff diff --git a/src/test/run-make/const_fn_mir/dump.mir b/src/test/run-make/const_fn_mir/dump.mir index 724b263008..45d018cf30 100644 --- a/src/test/run-make/const_fn_mir/dump.mir +++ b/src/test/run-make/const_fn_mir/dump.mir @@ -12,6 +12,7 @@ fn main() -> () { } bb1: { + _0 = const (); // scope 0 at main.rs:8:11: 10:2 return; // scope 0 at main.rs:10:2: 10:2 } } diff --git a/src/test/run-make/emit-shared-files/Makefile b/src/test/run-make/emit-shared-files/Makefile new file mode 100644 index 0000000000..d89b526d43 --- /dev/null +++ b/src/test/run-make/emit-shared-files/Makefile @@ -0,0 +1,46 @@ +-include ../../run-make-fulldeps/tools.mk + +INVOCATION_ONLY = $(TMPDIR)/invocation-only +TOOLCHAIN_ONLY = $(TMPDIR)/toolchain-only +ALL_SHARED = $(TMPDIR)/all-shared + +all: invocation-only toolchain-only all-shared + +invocation-only: + $(RUSTDOC) -Z unstable-options --emit=invocation-specific --output $(INVOCATION_ONLY) --resource-suffix=-xxx --theme y.css --extend-css z.css x.rs + [ -e $(INVOCATION_ONLY)/search-index-xxx.js ] + [ -e $(INVOCATION_ONLY)/settings.html ] + [ -e $(INVOCATION_ONLY)/x/all.html ] + [ -e $(INVOCATION_ONLY)/x/index.html ] + [ -e $(INVOCATION_ONLY)/theme-xxx.css ] # generated from z.css + ! [ -e $(INVOCATION_ONLY)/storage-xxx.js ] + ! [ -e $(INVOCATION_ONLY)/SourceSerif4-It.ttf.woff ] + + # FIXME: this probably shouldn't have a suffix + [ -e $(INVOCATION_ONLY)/y-xxx.css ] + # FIXME: this is technically incorrect (see `write_shared`) + ! [ -e $(INVOCATION_ONLY)/main-xxx.js ] + +toolchain-only: + $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs + [ -e $(TOOLCHAIN_ONLY)/storage-xxx.js ] + ! [ -e $(TOOLCHAIN_ONLY)/SourceSerif4-It.ttf.woff ] + ! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ] + ! [ -e $(TOOLCHAIN_ONLY)/x/index.html ] + ! [ -e $(TOOLCHAIN_ONLY)/theme.css ] + + [ -e $(TOOLCHAIN_ONLY)/main-xxx.js ] + ! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ] + +all-shared: + $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs + [ -e $(ALL_SHARED)/storage-xxx.js ] + [ -e $(ALL_SHARED)/SourceSerif4-It.ttf.woff ] + ! [ -e $(ALL_SHARED)/search-index-xxx.js ] + ! [ -e $(ALL_SHARED)/settings.html ] + ! [ -e $(ALL_SHARED)/x ] + ! [ -e $(ALL_SHARED)/src ] + ! [ -e $(ALL_SHARED)/theme.css ] + + [ -e $(ALL_SHARED)/main-xxx.js ] + ! [ -e $(ALL_SHARED)/y-xxx.css ] diff --git a/src/test/run-make/emit-shared-files/x.rs b/src/test/run-make/emit-shared-files/x.rs new file mode 100644 index 0000000000..5df7576133 --- /dev/null +++ b/src/test/run-make/emit-shared-files/x.rs @@ -0,0 +1 @@ +// nothing to see here diff --git a/src/test/run-make/emit-shared-files/y.css b/src/test/run-make/emit-shared-files/y.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/run-make/emit-shared-files/z.css b/src/test/run-make/emit-shared-files/z.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/run-make/incr-prev-body-beyond-eof/Makefile b/src/test/run-make/incr-prev-body-beyond-eof/Makefile index 49a7ee5f90..24eea3acae 100644 --- a/src/test/run-make/incr-prev-body-beyond-eof/Makefile +++ b/src/test/run-make/incr-prev-body-beyond-eof/Makefile @@ -1,7 +1,7 @@ -include ../../run-make-fulldeps/tools.mk +# ignore-none no-std is not supported +# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` -# FIXME https://github.com/rust-lang/rust/issues/78911 -# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64) +include ../../run-make-fulldeps/tools.mk # Tests that we don't ICE during incremental compilation after modifying a # function span such that its previous end line exceeds the number of lines @@ -14,6 +14,6 @@ all: mkdir $(SRC) mkdir $(INCR) cp a.rs $(SRC)/main.rs - $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs + $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET) cp b.rs $(SRC)/main.rs - $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs + $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET) diff --git a/src/test/run-make/issue-36710/Makefile b/src/test/run-make/issue-36710/Makefile index b0e8451ff5..b5270ad2ba 100644 --- a/src/test/run-make/issue-36710/Makefile +++ b/src/test/run-make/issue-36710/Makefile @@ -1,13 +1,20 @@ -include ../../run-make-fulldeps/tools.mk +# ignore-riscv64 $(call RUN,foo) expects to run the target executable natively +# so it won't work with remote-test-server +# ignore-arm Another build using remote-test-server +# ignore-none no-std is not supported +# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM +# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM +# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` +# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain +# (see dist-i586-gnu-i586-i686-musl Dockerfile) -# FIXME https://github.com/rust-lang/rust/issues/78911 -# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64) +include ../../run-make-fulldeps/tools.mk all: foo $(call RUN,foo) foo: foo.rs $(call NATIVE_STATICLIB,foo) - $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) + $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET) $(TMPDIR)/libfoo.o: foo.cpp $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/Makefile b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile index 76ecaba0f6..2f796e5b2f 100644 --- a/src/test/run-make/issue-83112-incr-test-moved-file/Makefile +++ b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile @@ -1,7 +1,7 @@ include ../../run-make-fulldeps/tools.mk -# FIXME https://github.com/rust-lang/rust/issues/78911 -# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64) +# ignore-none no-std is not supported +# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std' # Regression test for issue #83112 # The generated test harness code contains spans with a dummy location, @@ -20,6 +20,6 @@ all: mkdir $(SRC)/mydir mkdir $(INCR) cp main.rs $(SRC)/main.rs - $(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs + $(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET) mv $(SRC)/main.rs $(SRC)/mydir/main.rs - $(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs + $(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs --target $(TARGET) diff --git a/src/test/run-make/unstable-flag-required/Makefile b/src/test/run-make/unstable-flag-required/Makefile new file mode 100644 index 0000000000..b8769d5f69 --- /dev/null +++ b/src/test/run-make/unstable-flag-required/Makefile @@ -0,0 +1,4 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr diff --git a/src/test/run-make/unstable-flag-required/README.md b/src/test/run-make/unstable-flag-required/README.md new file mode 100644 index 0000000000..e5251fdf9b --- /dev/null +++ b/src/test/run-make/unstable-flag-required/README.md @@ -0,0 +1,3 @@ +This is a collection of tests that verify `--unstable-options` is required. +It should eventually be removed in favor of UI tests once compiletest stops +passing --unstable-options by default (#82639). diff --git a/src/test/run-make/unstable-flag-required/output-format-json.stderr b/src/test/run-make/unstable-flag-required/output-format-json.stderr new file mode 100644 index 0000000000..fb4079beb2 --- /dev/null +++ b/src/test/run-make/unstable-flag-required/output-format-json.stderr @@ -0,0 +1,2 @@ +error: the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578) + diff --git a/src/test/run-make/unstable-flag-required/x.rs b/src/test/run-make/unstable-flag-required/x.rs new file mode 100644 index 0000000000..5df7576133 --- /dev/null +++ b/src/test/run-make/unstable-flag-required/x.rs @@ -0,0 +1 @@ +// nothing to see here diff --git a/src/test/run-make/wasm-abi/Makefile b/src/test/run-make/wasm-abi/Makefile new file mode 100644 index 0000000000..61fc4e8f57 --- /dev/null +++ b/src/test/run-make/wasm-abi/Makefile @@ -0,0 +1,7 @@ +-include ../../run-make-fulldeps/tools.mk + +# only-wasm32-bare + +all: + $(RUSTC) foo.rs --target wasm32-unknown-unknown + $(NODE) foo.js $(TMPDIR)/foo.wasm diff --git a/src/test/run-make/wasm-abi/foo.js b/src/test/run-make/wasm-abi/foo.js new file mode 100644 index 0000000000..9e9a65401a --- /dev/null +++ b/src/test/run-make/wasm-abi/foo.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const process = require('process'); +const assert = require('assert'); +const buffer = fs.readFileSync(process.argv[2]); + +const m = new WebAssembly.Module(buffer); +const i = new WebAssembly.Instance(m, { + host: { + two_i32: () => [100, 101], + two_i64: () => [102n, 103n], + two_f32: () => [104, 105], + two_f64: () => [106, 107], + mishmash: () => [108, 109, 110, 111n, 112, 113], + } +}); + +assert.deepEqual(i.exports.return_two_i32(), [1, 2]) +assert.deepEqual(i.exports.return_two_i64(), [3, 4]) +assert.deepEqual(i.exports.return_two_f32(), [5, 6]) +assert.deepEqual(i.exports.return_two_f64(), [7, 8]) +assert.deepEqual(i.exports.return_mishmash(), [9, 10, 11, 12, 13, 14]) +i.exports.call_imports(); diff --git a/src/test/run-make/wasm-abi/foo.rs b/src/test/run-make/wasm-abi/foo.rs new file mode 100644 index 0000000000..0678eb3ff5 --- /dev/null +++ b/src/test/run-make/wasm-abi/foo.rs @@ -0,0 +1,87 @@ +#![crate_type = "cdylib"] +#![deny(warnings)] +#![feature(wasm_abi)] + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoI32 { + pub a: i32, + pub b: i32, +} + +#[no_mangle] +pub extern "wasm" fn return_two_i32() -> TwoI32 { + TwoI32 { a: 1, b: 2 } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoI64 { + pub a: i64, + pub b: i64, +} + +#[no_mangle] +pub extern "wasm" fn return_two_i64() -> TwoI64 { + TwoI64 { a: 3, b: 4 } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoF32 { + pub a: f32, + pub b: f32, +} + +#[no_mangle] +pub extern "wasm" fn return_two_f32() -> TwoF32 { + TwoF32 { a: 5., b: 6. } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoF64 { + pub a: f64, + pub b: f64, +} + +#[no_mangle] +pub extern "wasm" fn return_two_f64() -> TwoF64 { + TwoF64 { a: 7., b: 8. } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct Mishmash { + pub a: f64, + pub b: f32, + pub c: i32, + pub d: i64, + pub e: TwoI32, +} + +#[no_mangle] +pub extern "wasm" fn return_mishmash() -> Mishmash { + Mishmash { a: 9., b: 10., c: 11, d: 12, e: TwoI32 { a: 13, b: 14 } } +} + +#[link(wasm_import_module = "host")] +extern "wasm" { + fn two_i32() -> TwoI32; + fn two_i64() -> TwoI64; + fn two_f32() -> TwoF32; + fn two_f64() -> TwoF64; + fn mishmash() -> Mishmash; +} + +#[no_mangle] +pub unsafe extern "C" fn call_imports() { + assert_eq!(two_i32(), TwoI32 { a: 100, b: 101 }); + assert_eq!(two_i64(), TwoI64 { a: 102, b: 103 }); + assert_eq!(two_f32(), TwoF32 { a: 104., b: 105. }); + assert_eq!(two_f64(), TwoF64 { a: 106., b: 107. }); + assert_eq!( + mishmash(), + Mishmash { a: 108., b: 109., c: 110, d: 111, e: TwoI32 { a: 112, b: 113 } } + ); +} diff --git a/src/test/rustdoc-gui/README.md b/src/test/rustdoc-gui/README.md new file mode 100644 index 0000000000..499a98a3d2 --- /dev/null +++ b/src/test/rustdoc-gui/README.md @@ -0,0 +1,12 @@ +The tests present here are used to test the generated HTML from rustdoc. The +goal is to prevent unsound/unexpected GUI changes. + +This is using the [browser-ui-test] framework to do so. It works as follows: + +It wraps [puppeteer] to send commands to a web browser in order to navigate and +test what's being currently displayed in the web page. + +You can find more information and its documentation in its [repository][browser-ui-test]. + +[browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/ +[puppeteer]: https://pptr.dev/ 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 index 0000000000..9aa72a3ad5 --- /dev/null +++ b/src/test/rustdoc-gui/check_info_sign_position.goml @@ -0,0 +1,9 @@ +goto: file://|DOC_PATH|/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: (".docblock > .information > .compile_fail", { "margin-top": "16px" }) +// Checks that the other codeblocks don't have this top margin. +assert: ("ol > li > .information > .compile_fail", { "margin-top": "0px" }) +assert: ("ol > li > .information > .ignore", { "margin-top": "0px" }) +assert: (".docblock > .information > .ignore", { "margin-top": "0px" }) diff --git a/src/test/rustdoc-gui/hash-item-expansion.goml b/src/test/rustdoc-gui/hash-item-expansion.goml new file mode 100644 index 0000000000..d736d15d18 --- /dev/null +++ b/src/test/rustdoc-gui/hash-item-expansion.goml @@ -0,0 +1,18 @@ +// This test ensures that the element corresponding to the hash is displayed. +goto: file://|DOC_PATH|/struct.Foo.html#method.borrow +// In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)". +assert: ("#blanket-implementations-list > details:nth-child(2)", "open", "") +// Please note the "\" below is needed because otherwise ".borrow" would be interpreted as +// a class selector. +assert: ("#method\.borrow", {"display": "flex"}) +// We first check that the impl block is open by default. +assert: ("#implementations + details", "open", "") +// We collapse it. +click: "#implementations + details > summary" +// We check that it was collapsed as expected. +assert-false: ("#implementations + details", "open", "") +// To ensure that we will click on the currently hidden method. +assert: (".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: ("#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 index 0000000000..686d98f973 --- /dev/null +++ b/src/test/rustdoc-gui/impl-default-expansion.goml @@ -0,0 +1,3 @@ +// This test ensures that the impl blocks are open by default. +goto: file://|DOC_PATH|/struct.Foo.html +assert: ("#main > details.implementors-toggle", "open", "") diff --git a/src/test/rustdoc-gui/lib.rs b/src/test/rustdoc-gui/lib.rs index 15d8dcc6e8..eeba3e3f90 100644 --- a/src/test/rustdoc-gui/lib.rs +++ b/src/test/rustdoc-gui/lib.rs @@ -29,7 +29,9 @@ pub struct Foo; impl Foo { #[must_use] - pub fn must_use(&self) -> bool { true } + pub fn must_use(&self) -> bool { + true + } } /// Just a normal enum. @@ -47,26 +49,45 @@ pub fn some_more_function(t: &T) -> String { /// 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(); - /// Some func 3. - fn func3(); + fn hello(); } +/// ```compile_fail +/// whatever +/// ``` +/// /// Check for "i" signs in lists! /// /// 1. elem 1 -/// 2.test 1 -/// ```compile_fail -/// fn foo() {} -/// ``` +/// 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 }, +} diff --git a/src/test/rustdoc-gui/nojs-attr-pos.goml b/src/test/rustdoc-gui/nojs-attr-pos.goml deleted file mode 100644 index 35daa4cb9e..0000000000 --- a/src/test/rustdoc-gui/nojs-attr-pos.goml +++ /dev/null @@ -1,5 +0,0 @@ -// Check that the attributes are well positioned when javascript is disabled (since -// there is no toggle to display) -javascript: false -goto: file://|DOC_PATH|/struct.Foo.html -assert: (".attributes", {"margin-left": "0px"}) 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 index 0000000000..a4df102d24 --- /dev/null +++ b/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml @@ -0,0 +1,21 @@ +goto: file://|DOC_PATH|/index.html +write: (".search-input", "Foo") +// Waiting for the search results to appear... +wait-for: "#titles" +assert: ("#titles > button:nth-of-type(1)", "class", "selected") + +// To go back to the original "state" +goto: file://|DOC_PATH|/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: ("#titles > button:nth-of-type(3)", "class", "selected") + +// To go back to the original "state" +goto: file://|DOC_PATH|/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: ("#titles > button:nth-of-type(1)", "class", "selected") 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 index 0000000000..914486e1c2 --- /dev/null +++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml @@ -0,0 +1,7 @@ +goto: file://|DOC_PATH|/trait.AnotherOne.html +assert: (".sidebar-links a:nth-of-type(1)", "another") +assert: (".sidebar-links a:nth-of-type(2)", "func1") +assert: (".sidebar-links a:nth-of-type(3)", "func2") +assert: (".sidebar-links a:nth-of-type(4)", "func3") +assert: (".sidebar-links a:nth-of-type(5)", "hello") +assert: (".sidebar-links a:nth-of-type(6)", "why_not") diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs index 5bb66f7f6f..b0e717d8a8 100644 --- a/src/test/rustdoc-json/nested.rs +++ b/src/test/rustdoc-json/nested.rs @@ -24,7 +24,7 @@ pub mod l1 { // @has - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id pub struct L4; } - // @is nested.json "$.index[*][?(@.inner.span=='l3::L4')].kind" \"import\" - // @is - "$.index[*][?(@.inner.span=='l3::L4')].inner.glob" false + // @is nested.json "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\" + // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false pub use l3::L4; } diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod.rs b/src/test/rustdoc-json/reexport/in_root_and_mod.rs new file mode 100644 index 0000000000..e3cecbdd7f --- /dev/null +++ b/src/test/rustdoc-json/reexport/in_root_and_mod.rs @@ -0,0 +1,15 @@ +#![feature(no_core)] +#![no_core] + +mod foo { + // @set foo_id = in_root_and_mod.json "$.index[*][?(@.name=='Foo')].id" + pub struct Foo; +} + +// @has - "$.index[*][?(@.name=='in_root_and_mod')].inner.items[*]" $foo_id +pub use foo::Foo; + +pub mod bar { + // @has - "$.index[*][?(@.name=='bar')].inner.items[*]" $foo_id + pub use crate::foo::Foo; +} diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs new file mode 100644 index 0000000000..2daadf7620 --- /dev/null +++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -0,0 +1,20 @@ +#![feature(no_core)] +#![no_core] + +pub mod foo { + // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id" + // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id + pub struct Bar; +} + +// @set root_import_id = - "$.index[*][?(@.inner.source=='foo::Bar')].id" +// @is - "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id +// @has - "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id +pub use foo::Bar; + +pub mod baz { + // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id" + // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id + // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id + pub use crate::foo::Bar; +} diff --git a/src/test/rustdoc-json/reexport/rename_private.rs b/src/test/rustdoc-json/reexport/rename_private.rs new file mode 100644 index 0000000000..fb8296f233 --- /dev/null +++ b/src/test/rustdoc-json/reexport/rename_private.rs @@ -0,0 +1,14 @@ +// edition:2018 + +#![no_core] +#![feature(no_core)] +// @!has rename_private.json "$.index[*][?(@.name=='inner')]" +mod inner { + // @!has - "$.index[*][?(@.name=='Public')]" + pub struct Public; +} + +// @set newname_id = - "$.index[*][?(@.name=='NewName')].id" +// @is - "$.index[*][?(@.name=='NewName')].kind" \"struct\" +// @has - "$.index[*][?(@.name=='rename_private')].inner.items[*]" $newname_id +pub use inner::Public as NewName; diff --git a/src/test/rustdoc-json/reexport/rename_public.rs b/src/test/rustdoc-json/reexport/rename_public.rs index 8c2d7200d0..2dd438d223 100644 --- a/src/test/rustdoc-json/reexport/rename_public.rs +++ b/src/test/rustdoc-json/reexport/rename_public.rs @@ -13,5 +13,5 @@ pub mod inner { // @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id" // @!has - "$.index[*][?(@.inner.name=='Public')]" // @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $import_id -// @is - "$.index[*][?(@.inner.name=='NewName')].inner.span" \"inner::Public\" +// @is - "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\" pub use inner::Public as NewName; diff --git a/src/test/rustdoc-json/reexport/simple_public.rs b/src/test/rustdoc-json/reexport/simple_public.rs index 0c97a2e7b4..2e4de301f6 100644 --- a/src/test/rustdoc-json/reexport/simple_public.rs +++ b/src/test/rustdoc-json/reexport/simple_public.rs @@ -14,5 +14,5 @@ pub mod inner { // @set import_id = - "$.index[*][?(@.inner.name=='Public')].id" // @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id -// @is - "$.index[*][?(@.inner.name=='Public')].inner.span" \"inner::Public\" +// @is - "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\" pub use inner::Public; diff --git a/src/test/rustdoc-ui/auxiliary/panic-item.rs b/src/test/rustdoc-ui/auxiliary/panic-item.rs new file mode 100644 index 0000000000..17b26850d4 --- /dev/null +++ b/src/test/rustdoc-ui/auxiliary/panic-item.rs @@ -0,0 +1,17 @@ +// no-prefer-dynamic +#![crate_type = "lib"] +#![no_std] +#![feature(lang_items)] + +use core::panic::PanicInfo; +use core::sync::atomic::{self, Ordering}; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop { + atomic::compiler_fence(Ordering::SeqCst); + } +} + +#[lang = "eh_personality"] +fn foo() {} diff --git a/src/test/rustdoc-ui/bare-urls.fixed b/src/test/rustdoc-ui/bare-urls.fixed new file mode 100644 index 0000000000..23aa5c44c2 --- /dev/null +++ b/src/test/rustdoc-ui/bare-urls.fixed @@ -0,0 +1,60 @@ +// run-rustfix + +#![deny(rustdoc::bare_urls)] + +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// +//~^ ERROR this URL is not a hyperlink +/// hey! +//~^ ERROR this URL is not a hyperlink +pub fn c() {} + +/// +/// [a](http://a.com) +/// [b] +/// +/// [b]: http://b.com +/// +/// ``` +/// This link should not be linted: http://example.com +/// +/// Nor this one: or this one: [x](http://example.com) +/// ``` +/// +/// [should_not.lint](should_not.lint) +pub fn everything_is_fine_here() {} + +#[allow(rustdoc::bare_urls)] +pub mod foo { + /// https://somewhere.com/a?hello=12&bye=11#xyz + pub fn bar() {} +} diff --git a/src/test/rustdoc-ui/url-improvements.rs b/src/test/rustdoc-ui/bare-urls.rs similarity index 84% rename from src/test/rustdoc-ui/url-improvements.rs rename to src/test/rustdoc-ui/bare-urls.rs index d0b43de2f0..592f57343b 100644 --- a/src/test/rustdoc-ui/url-improvements.rs +++ b/src/test/rustdoc-ui/bare-urls.rs @@ -1,14 +1,6 @@ -#![deny(rustdoc::non_autolinks)] +// run-rustfix -/// [http://aa.com](http://aa.com) -//~^ ERROR unneeded long form for URL -/// [http://bb.com] -//~^ ERROR unneeded long form for URL -/// -/// [http://bb.com]: http://bb.com -/// -/// [http://c.com][http://c.com] -pub fn a() {} +#![deny(rustdoc::bare_urls)] /// https://somewhere.com //~^ ERROR this URL is not a hyperlink @@ -54,12 +46,14 @@ pub fn c() {} /// /// ``` /// This link should not be linted: http://example.com +/// +/// Nor this one: or this one: [x](http://example.com) /// ``` /// /// [should_not.lint](should_not.lint) pub fn everything_is_fine_here() {} -#[allow(rustdoc::non_autolinks)] +#[allow(rustdoc::bare_urls)] pub mod foo { /// https://somewhere.com/a?hello=12&bye=11#xyz pub fn bar() {} diff --git a/src/test/rustdoc-ui/url-improvements.stderr b/src/test/rustdoc-ui/bare-urls.stderr similarity index 63% rename from src/test/rustdoc-ui/url-improvements.stderr rename to src/test/rustdoc-ui/bare-urls.stderr index f377973656..7097a8ddf3 100644 --- a/src/test/rustdoc-ui/url-improvements.stderr +++ b/src/test/rustdoc-ui/bare-urls.stderr @@ -1,122 +1,143 @@ -error: unneeded long form for URL - --> $DIR/url-improvements.rs:3:5 - | -LL | /// [http://aa.com](http://aa.com) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` - | -note: the lint level is defined here - --> $DIR/url-improvements.rs:1:9 - | -LL | #![deny(rustdoc::non_autolinks)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unneeded long form for URL - --> $DIR/url-improvements.rs:5:5 - | -LL | /// [http://bb.com] - | ^^^^^^^^^^^^^^^ help: use an automatic link instead: `` - error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:13:5 + --> $DIR/bare-urls.rs:5:5 | LL | /// https://somewhere.com | ^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | +note: the lint level is defined here + --> $DIR/bare-urls.rs:3:9 + | +LL | #![deny(rustdoc::bare_urls)] + | ^^^^^^^^^^^^^^^^^^ + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:15:5 + --> $DIR/bare-urls.rs:7:5 | LL | /// https://somewhere.com/a | ^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:17:5 + --> $DIR/bare-urls.rs:9:5 | LL | /// https://www.somewhere.com | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:19:5 + --> $DIR/bare-urls.rs:11:5 | LL | /// https://www.somewhere.com/a | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:21:5 + --> $DIR/bare-urls.rs:13:5 | LL | /// https://subdomain.example.com | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:23:5 + --> $DIR/bare-urls.rs:15:5 | LL | /// https://somewhere.com? | ^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:25:5 + --> $DIR/bare-urls.rs:17:5 | LL | /// https://somewhere.com/a? | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:27:5 + --> $DIR/bare-urls.rs:19:5 | LL | /// https://somewhere.com?hello=12 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:29:5 + --> $DIR/bare-urls.rs:21:5 | LL | /// https://somewhere.com/a?hello=12 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:31:5 + --> $DIR/bare-urls.rs:23:5 | LL | /// https://example.com?hello=12#xyz | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:33:5 + --> $DIR/bare-urls.rs:25:5 | LL | /// https://example.com/a?hello=12#xyz | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:35:5 + --> $DIR/bare-urls.rs:27:5 | LL | /// https://example.com#xyz | ^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:37:5 + --> $DIR/bare-urls.rs:29:5 | LL | /// https://example.com/a#xyz | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:39:5 + --> $DIR/bare-urls.rs:31:5 | LL | /// https://somewhere.com?hello=12&bye=11 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:41:5 + --> $DIR/bare-urls.rs:33:5 | LL | /// https://somewhere.com/a?hello=12&bye=11 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:43:5 + --> $DIR/bare-urls.rs:35:5 | LL | /// https://somewhere.com?hello=12&bye=11#xyz | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links error: this URL is not a hyperlink - --> $DIR/url-improvements.rs:45:10 + --> $DIR/bare-urls.rs:37:10 | LL | /// hey! https://somewhere.com/a?hello=12&bye=11#xyz | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | + = note: bare URLs are not automatically turned into clickable links -error: aborting due to 19 previous errors +error: aborting due to 17 previous errors diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.stderr b/src/test/rustdoc-ui/check-doc-alias-attr.stderr index f99d69dc10..250568be33 100644 --- a/src/test/rustdoc-ui/check-doc-alias-attr.stderr +++ b/src/test/rustdoc-ui/check-doc-alias-attr.stderr @@ -10,7 +10,7 @@ error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of s LL | #[doc(alias = 0)] | ^^^^^^^^^ -error: '\"' character isn't allowed in `#[doc(alias = "...")]` +error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:9:15 | LL | #[doc(alias = "\"")] @@ -60,7 +60,7 @@ error: `#[doc(alias("a"))]` expects string literals LL | #[doc(alias(0))] | ^ -error: '\"' character isn't allowed in `#[doc(alias("..."))]` +error: '"' character isn't allowed in `#[doc(alias("..."))]` --> $DIR/check-doc-alias-attr.rs:20:13 | LL | #[doc(alias("\""))] diff --git a/src/test/rustdoc-ui/commandline-argfile-missing.rs b/src/test/rustdoc-ui/commandline-argfile-missing.rs index 020c3ff3c7..5a6465bd06 100644 --- a/src/test/rustdoc-ui/commandline-argfile-missing.rs +++ b/src/test/rustdoc-ui/commandline-argfile-missing.rs @@ -1,6 +1,5 @@ // Check to see if we can get parameters from an @argsfile file // -// ignore-tidy-linelength // normalize-stderr-test: "os error \d+" -> "os error $$ERR" // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args diff --git a/src/test/rustdoc-ui/coverage/traits.rs b/src/test/rustdoc-ui/coverage/traits.rs index 7d5cf049e7..2a108dac2a 100644 --- a/src/test/rustdoc-ui/coverage/traits.rs +++ b/src/test/rustdoc-ui/coverage/traits.rs @@ -2,6 +2,7 @@ // check-pass #![feature(trait_alias)] +#![feature(min_type_alias_impl_trait)] /// look at this trait right here pub trait ThisTrait { @@ -16,6 +17,7 @@ pub trait ThisTrait { } /// so what happens if we take some struct... +#[derive(Clone)] pub struct SomeStruct; /// ...and slap this trait on it? @@ -29,10 +31,8 @@ impl ThisTrait for SomeStruct { /// but what about those aliases? i hear they're pretty exotic pub trait MyAlias = ThisTrait + Send + Sync; -// FIXME(58624): once rustdoc can process opaque `impl Trait` types, -// we need to make sure they're counted -// /// woah, getting all opaque in here -// pub type ThisExists = impl ThisTrait; -// -// /// why don't we get a little more concrete -// pub fn defines() -> ThisExists { SomeStruct {} } +/// woah, getting all opaque in here +pub type ThisExists = impl ThisTrait; + +/// why don't we get a little more concrete +pub fn defines() -> ThisExists { SomeStruct {} } diff --git a/src/test/rustdoc-ui/coverage/traits.stdout b/src/test/rustdoc-ui/coverage/traits.stdout index e04d48b498..5053d02090 100644 --- a/src/test/rustdoc-ui/coverage/traits.stdout +++ b/src/test/rustdoc-ui/coverage/traits.stdout @@ -1,7 +1,7 @@ +-------------------------------------+------------+------------+------------+------------+ | File | Documented | Percentage | Examples | Percentage | +-------------------------------------+------------+------------+------------+------------+ -| ...st/rustdoc-ui/coverage/traits.rs | 6 | 85.7% | 0 | 0.0% | +| ...st/rustdoc-ui/coverage/traits.rs | 8 | 88.9% | 0 | 0.0% | +-------------------------------------+------------+------------+------------+------------+ -| Total | 6 | 85.7% | 0 | 0.0% | +| Total | 8 | 88.9% | 0 | 0.0% | +-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/doc-spotlight.fixed b/src/test/rustdoc-ui/doc-spotlight.fixed new file mode 100644 index 0000000000..94b69a9987 --- /dev/null +++ b/src/test/rustdoc-ui/doc-spotlight.fixed @@ -0,0 +1,9 @@ +// check-pass +// run-rustfix + +#![feature(doc_notable_trait)] + +#[doc(notable_trait)] +//~^ WARN unknown `doc` attribute `spotlight` +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +trait MyTrait {} diff --git a/src/test/rustdoc-ui/doc-spotlight.rs b/src/test/rustdoc-ui/doc-spotlight.rs new file mode 100644 index 0000000000..cc5f159a80 --- /dev/null +++ b/src/test/rustdoc-ui/doc-spotlight.rs @@ -0,0 +1,9 @@ +// check-pass +// run-rustfix + +#![feature(doc_notable_trait)] + +#[doc(spotlight)] +//~^ WARN unknown `doc` attribute `spotlight` +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +trait MyTrait {} diff --git a/src/test/rustdoc-ui/doc-spotlight.stderr b/src/test/rustdoc-ui/doc-spotlight.stderr new file mode 100644 index 0000000000..e5fa6293f3 --- /dev/null +++ b/src/test/rustdoc-ui/doc-spotlight.stderr @@ -0,0 +1,14 @@ +warning: unknown `doc` attribute `spotlight` + --> $DIR/doc-spotlight.rs:6:7 + | +LL | #[doc(spotlight)] + | ^^^^^^^^^ help: use `notable_trait` instead + | + = note: `#[warn(invalid_doc_attributes)]` 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 #82730 + = note: `doc(spotlight)` was renamed to `doc(notable_trait)` + = note: `doc(spotlight)` is now a no-op + +warning: 1 warning emitted + diff --git a/src/test/rustdoc-ui/intra-doc/anchors.rs b/src/test/rustdoc-ui/intra-doc/anchors.rs index 009b291be1..6785cb7abe 100644 --- a/src/test/rustdoc-ui/intra-doc/anchors.rs +++ b/src/test/rustdoc-ui/intra-doc/anchors.rs @@ -43,3 +43,7 @@ pub fn enum_link() {} /// [u32#hello] //~^ ERROR `u32#hello` contains an anchor pub fn x() {} + +/// [prim@usize#x] +//~^ ERROR `prim@usize#x` contains an anchor +pub mod usize {} diff --git a/src/test/rustdoc-ui/intra-doc/anchors.stderr b/src/test/rustdoc-ui/intra-doc/anchors.stderr index 97b0cea0c1..d63e1ee60b 100644 --- a/src/test/rustdoc-ui/intra-doc/anchors.stderr +++ b/src/test/rustdoc-ui/intra-doc/anchors.stderr @@ -1,32 +1,53 @@ -error: `Foo::f#hola` contains an anchor, but links to fields are already anchored - --> $DIR/anchors.rs:25:15 +error: `prim@usize#x` contains an anchor, but links to builtin types are already anchored + --> $DIR/anchors.rs:47:6 | -LL | /// Or maybe [Foo::f#hola]. - | ^^^^^^^^^^^ contains invalid anchor +LL | /// [prim@usize#x] + | ^^^^^^^^^^-- + | | + | invalid anchor | note: the lint level is defined here --> $DIR/anchors.rs:1:9 | LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this restriction may be lifted in a future release + = note: see https://github.com/rust-lang/rust/issues/83083 for more information + +error: `Foo::f#hola` contains an anchor, but links to fields are already anchored + --> $DIR/anchors.rs:25:15 + | +LL | /// Or maybe [Foo::f#hola]. + | ^^^^^^----- + | | + | invalid anchor error: `hello#people#!` contains multiple anchors --> $DIR/anchors.rs:31:28 | LL | /// Another anchor error: [hello#people#!]. - | ^^^^^^^^^^^^^^ contains invalid anchor + | ^^^^^^^^^^^^-- + | | + | invalid anchor error: `Enum::A#whatever` contains an anchor, but links to variants are already anchored --> $DIR/anchors.rs:37:28 | LL | /// Damn enum's variants: [Enum::A#whatever]. - | ^^^^^^^^^^^^^^^^ contains invalid anchor + | ^^^^^^^--------- + | | + | invalid anchor error: `u32#hello` contains an anchor, but links to builtin types are already anchored --> $DIR/anchors.rs:43:6 | LL | /// [u32#hello] - | ^^^^^^^^^ contains invalid anchor + | ^^^------ + | | + | invalid anchor + | + = note: this restriction may be lifted in a future release + = note: see https://github.com/rust-lang/rust/issues/83083 for more information -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/rustdoc-ui/intra-doc/double-anchor.stderr b/src/test/rustdoc-ui/intra-doc/double-anchor.stderr index c0241b98b7..6addb010e0 100644 --- a/src/test/rustdoc-ui/intra-doc/double-anchor.stderr +++ b/src/test/rustdoc-ui/intra-doc/double-anchor.stderr @@ -2,7 +2,9 @@ warning: `with#anchor#error` contains multiple anchors --> $DIR/double-anchor.rs:5:18 | LL | /// docs [label][with#anchor#error] - | ^^^^^^^^^^^^^^^^^ contains invalid anchor + | ^^^^^^^^^^^------ + | | + | invalid anchor | = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs new file mode 100644 index 0000000000..417618c745 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs @@ -0,0 +1,6 @@ +#![deny(warnings)] + +//! Email me at . +//~^ ERROR unknown disambiguator `hello` + +//! This should *not* warn: . diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr new file mode 100644 index 0000000000..de215b2163 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr @@ -0,0 +1,15 @@ +error: unknown disambiguator `hello` + --> $DIR/email-address-localhost.rs:3:18 + | +LL | //! Email me at . + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/email-address-localhost.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs new file mode 100644 index 0000000000..e429e75b21 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs @@ -0,0 +1,6 @@ +// check-pass + +//! [my_module] +//~^ WARN public documentation for `private_from_crate_level` links to private item `my_module` + +mod my_module {} diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr new file mode 100644 index 0000000000..6172cd2e31 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr @@ -0,0 +1,11 @@ +warning: public documentation for `private_from_crate_level` links to private item `my_module` + --> $DIR/private-from-crate-level.rs:3:6 + | +LL | //! [my_module] + | ^^^^^^^^^ this item is private + | + = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default + = note: this link will resolve properly if you pass `--document-private-items` + +warning: 1 warning emitted + diff --git a/src/test/rustdoc-ui/intra-doc/private.private.stderr b/src/test/rustdoc-ui/intra-doc/private.private.stderr index cae5b1f20e..392321f9c6 100644 --- a/src/test/rustdoc-ui/intra-doc/private.private.stderr +++ b/src/test/rustdoc-ui/intra-doc/private.private.stderr @@ -1,19 +1,27 @@ warning: public documentation for `DocMe` links to private item `DontDocMe` - --> $DIR/private.rs:5:11 + --> $DIR/private.rs:7:11 | -LL | /// docs [DontDocMe] [DontDocMe::f] +LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] | ^^^^^^^^^ this item is private | = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default = note: this link resolves only because you passed `--document-private-items`, but will break without warning: public documentation for `DocMe` links to private item `DontDocMe::f` - --> $DIR/private.rs:5:23 + --> $DIR/private.rs:7:23 | -LL | /// docs [DontDocMe] [DontDocMe::f] +LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] | ^^^^^^^^^^^^ this item is private | = note: this link resolves only because you passed `--document-private-items`, but will break without -warning: 2 warnings emitted +warning: public documentation for `DocMe` links to private item `DontDocMe::x` + --> $DIR/private.rs:7:38 + | +LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] + | ^^^^^^^^^^^^ this item is private + | + = note: this link resolves only because you passed `--document-private-items`, but will break without + +warning: 3 warnings emitted diff --git a/src/test/rustdoc-ui/intra-doc/private.public.stderr b/src/test/rustdoc-ui/intra-doc/private.public.stderr index 05b202e37f..5d1c34b916 100644 --- a/src/test/rustdoc-ui/intra-doc/private.public.stderr +++ b/src/test/rustdoc-ui/intra-doc/private.public.stderr @@ -1,19 +1,27 @@ warning: public documentation for `DocMe` links to private item `DontDocMe` - --> $DIR/private.rs:5:11 + --> $DIR/private.rs:7:11 | -LL | /// docs [DontDocMe] [DontDocMe::f] +LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] | ^^^^^^^^^ this item is private | = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default = note: this link will resolve properly if you pass `--document-private-items` warning: public documentation for `DocMe` links to private item `DontDocMe::f` - --> $DIR/private.rs:5:23 + --> $DIR/private.rs:7:23 | -LL | /// docs [DontDocMe] [DontDocMe::f] +LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] | ^^^^^^^^^^^^ this item is private | = note: this link will resolve properly if you pass `--document-private-items` -warning: 2 warnings emitted +warning: public documentation for `DocMe` links to private item `DontDocMe::x` + --> $DIR/private.rs:7:38 + | +LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] + | ^^^^^^^^^^^^ this item is private + | + = note: this link will resolve properly if you pass `--document-private-items` + +warning: 3 warnings emitted diff --git a/src/test/rustdoc-ui/intra-doc/private.rs b/src/test/rustdoc-ui/intra-doc/private.rs index 3782864305..525332ddaa 100644 --- a/src/test/rustdoc-ui/intra-doc/private.rs +++ b/src/test/rustdoc-ui/intra-doc/private.rs @@ -2,12 +2,16 @@ // revisions: public private // [private]compile-flags: --document-private-items -/// docs [DontDocMe] [DontDocMe::f] +// make sure to update `rustdoc/intra-doc/private.rs` if you update this file + +/// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] //~^ WARNING public documentation for `DocMe` links to private item `DontDocMe` +//~| WARNING public documentation for `DocMe` links to private item `DontDocMe::x` //~| WARNING public documentation for `DocMe` links to private item `DontDocMe::f` -// FIXME: for [private] we should also make sure the link was actually generated pub struct DocMe; -struct DontDocMe; +struct DontDocMe { + x: usize, +} impl DontDocMe { fn f() {} diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs new file mode 100644 index 0000000000..925fc515a3 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs @@ -0,0 +1,13 @@ +#![deny(warnings)] + +//! Linking to [foo@banana] and [`bar@banana!()`]. +//~^ ERROR unknown disambiguator `foo` +//~| ERROR unknown disambiguator `bar` +//! And to [no disambiguator](@nectarine) and [another](@apricot!()). +//~^ ERROR unknown disambiguator `` +//~| ERROR unknown disambiguator `` +//! And with weird backticks: [``foo@hello``] [foo`@`hello]. +//~^ ERROR unknown disambiguator `foo` +//~| ERROR unknown disambiguator `foo` + +fn main() {} diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr new file mode 100644 index 0000000000..195aaca32a --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr @@ -0,0 +1,45 @@ +error: unknown disambiguator `foo` + --> $DIR/unknown-disambiguator.rs:3:17 + | +LL | //! Linking to [foo@banana] and [`bar@banana!()`]. + | ^^^ + | +note: the lint level is defined here + --> $DIR/unknown-disambiguator.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]` + +error: unknown disambiguator `bar` + --> $DIR/unknown-disambiguator.rs:3:35 + | +LL | //! Linking to [foo@banana] and [`bar@banana!()`]. + | ^^^ + +error: unknown disambiguator `foo` + --> $DIR/unknown-disambiguator.rs:9:34 + | +LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello]. + | ^^^ + +error: unknown disambiguator `foo` + --> $DIR/unknown-disambiguator.rs:9:48 + | +LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello]. + | ^^^ + +error: unknown disambiguator `` + --> $DIR/unknown-disambiguator.rs:6:31 + | +LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()). + | ^ + +error: unknown disambiguator `` + --> $DIR/unknown-disambiguator.rs:6:57 + | +LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()). + | ^ + +error: aborting due to 6 previous errors + diff --git a/src/test/rustdoc-ui/invalid-theme-name.rs b/src/test/rustdoc-ui/invalid-theme-name.rs new file mode 100644 index 0000000000..c22ebf0271 --- /dev/null +++ b/src/test/rustdoc-ui/invalid-theme-name.rs @@ -0,0 +1,3 @@ +// compile-flags:--theme {{src-base}}/invalid-theme-name.rs +// error-pattern: invalid argument +// error-pattern: must have a .css extension diff --git a/src/test/rustdoc-ui/invalid-theme-name.stderr b/src/test/rustdoc-ui/invalid-theme-name.stderr new file mode 100644 index 0000000000..80204442db --- /dev/null +++ b/src/test/rustdoc-ui/invalid-theme-name.stderr @@ -0,0 +1,4 @@ +error: invalid argument: "$DIR/invalid-theme-name.rs" + | + = help: arguments to --theme must have a .css extension + diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.rs b/src/test/rustdoc-ui/issue-83883-describe-lints.rs new file mode 100644 index 0000000000..a261b782d4 --- /dev/null +++ b/src/test/rustdoc-ui/issue-83883-describe-lints.rs @@ -0,0 +1,8 @@ +// compile-flags: -W help +// check-pass +// +// ignore-tidy-linelength +// +// normalize-stdout-test: "( +name default meaning\n +---- ------- -------\n)?( *[[:word:]:-]+ (allow |warn |deny |forbid ) [^\n]+\n)+" -> " $$NAMES $$LEVELS $$MEANINGS" +// normalize-stdout-test: " +name sub-lints\n +---- ---------\n( *[[:word:]:-]+ [^\n]+\n)+" -> " $$NAMES $$SUB_LINTS" +// normalize-stdout-test: " +rustdoc::all( (rustdoc::[[:word:]-]+, )*rustdoc::[[:word:]-]+)?" -> " rustdoc::all $$GROUPS$4" diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout new file mode 100644 index 0000000000..651faf5761 --- /dev/null +++ b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout @@ -0,0 +1,25 @@ + +Available lint options: + -W Warn about + -A Allow + -D Deny + -F Forbid (deny and all attempts to override) + + +Lint checks provided by rustc: + + $NAMES $LEVELS $MEANINGS + +Lint groups provided by rustc: + + $NAMES $SUB_LINTS + +Lint checks provided by plugins loaded by this crate: + + $NAMES $LEVELS $MEANINGS + +Lint groups provided by plugins loaded by this crate: + + rustdoc::all $GROUPS + + diff --git a/src/test/rustdoc-ui/output-format-html-stable.rs b/src/test/rustdoc-ui/output-format-html-stable.rs new file mode 100644 index 0000000000..fa0362640b --- /dev/null +++ b/src/test/rustdoc-ui/output-format-html-stable.rs @@ -0,0 +1,4 @@ +// compile-flags: --output-format html +// check-pass +// This tests that `--output-format html` is accepted without `-Z unstable-options`, +// since it has been stable since 1.0. diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.rs b/src/test/rustdoc-ui/renamed-lint-still-applies.rs index 8c61c1ccb6..05a32d3cc3 100644 --- a/src/test/rustdoc-ui/renamed-lint-still-applies.rs +++ b/src/test/rustdoc-ui/renamed-lint-still-applies.rs @@ -4,3 +4,8 @@ // stable channel. //! [x] //~^ ERROR unresolved link + +#![deny(rustdoc::non_autolinks)] +//~^ WARNING renamed to `rustdoc::bare_urls` +//! http://example.com +//~^ ERROR not a hyperlink diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr index 8a12991558..3040cad532 100644 --- a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr +++ b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr @@ -1,3 +1,11 @@ +warning: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls` + --> $DIR/renamed-lint-still-applies.rs:8: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 | @@ -12,5 +20,18 @@ 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: aborting due to previous error +error: this URL is not a hyperlink + --> $DIR/renamed-lint-still-applies.rs:10:5 + | +LL | //! http://example.com + | ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | +note: the lint level is defined here + --> $DIR/renamed-lint-still-applies.rs:8: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 diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.rs b/src/test/rustdoc-ui/unknown-renamed-lints.rs index a05c0c8116..9096cce127 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.rs +++ b/src/test/rustdoc-ui/unknown-renamed-lints.rs @@ -8,8 +8,12 @@ //~^ ERROR unknown lint: `rustdoc::x` #![deny(intra_doc_link_resolution_failure)] //~^ ERROR renamed to `rustdoc::broken_intra_doc_links` - #![deny(non_autolinks)] +//~^ ERROR renamed to `rustdoc::bare_urls` +#![deny(rustdoc::non_autolinks)] +//~^ 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. diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.stderr b/src/test/rustdoc-ui/unknown-renamed-lints.stderr index 98bfb83c70..51e06821cf 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.stderr +++ b/src/test/rustdoc-ui/unknown-renamed-lints.stderr @@ -28,19 +28,31 @@ note: the lint level is defined here LL | #![deny(renamed_and_removed_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error: lint `non_autolinks` has been renamed to `rustdoc::bare_urls` + --> $DIR/unknown-renamed-lints.rs:11:9 + | +LL | #![deny(non_autolinks)] + | ^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls` + +error: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls` + --> $DIR/unknown-renamed-lints.rs:13:9 + | +LL | #![deny(rustdoc::non_autolinks)] + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls` + error: lint `rustdoc` has been removed: use `rustdoc::all` instead - --> $DIR/unknown-renamed-lints.rs:16:9 + --> $DIR/unknown-renamed-lints.rs:20:9 | LL | #![deny(rustdoc)] | ^^^^^^^ error: unknown lint: `rustdoc::intra_doc_link_resolution_failure` - --> $DIR/unknown-renamed-lints.rs:20:9 + --> $DIR/unknown-renamed-lints.rs:24:9 | LL | #![deny(rustdoc::intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Compilation failed, aborting rustdoc -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors diff --git a/src/test/rustdoc-ui/unused-extern-crate.rs b/src/test/rustdoc-ui/unused-extern-crate.rs new file mode 100644 index 0000000000..f703a18379 --- /dev/null +++ b/src/test/rustdoc-ui/unused-extern-crate.rs @@ -0,0 +1,3 @@ +// check-pass +// aux-crate:panic_item=panic-item.rs +// @has unused_extern_crate/index.html diff --git a/src/test/rustdoc/assoc-item-cast.rs b/src/test/rustdoc/assoc-item-cast.rs index dc62fac6a9..273fc62aa1 100644 --- a/src/test/rustdoc/assoc-item-cast.rs +++ b/src/test/rustdoc/assoc-item-cast.rs @@ -1,6 +1,5 @@ #![crate_name = "foo"] -// ignore-tidy-linelength pub trait Expression { type SqlType; diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index 5f0fdbb322..8fda171002 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_type="lib"] // @has assoc_types/trait.Index.html @@ -8,14 +6,14 @@ pub trait Index { type Output: ?Sized; // @has - '//*[@id="tymethod.index"]//code' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" - // @has - '//*[@id="tymethod.index"]//code//a[@href="../assoc_types/trait.Index.html#associatedtype.Output"]' \ + // @has - '//*[@id="tymethod.index"]//code//a[@href="trait.Index.html#associatedtype.Output"]' \ // "Output" fn index<'a>(&'a self, index: I) -> &'a Self::Output; } // @has assoc_types/fn.use_output.html // @has - '//*[@class="rust fn"]' '-> &T::Output' -// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Index.html#associatedtype.Output"]' 'Output' +// @has - '//*[@class="rust fn"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output' pub fn use_output>(obj: &T, index: usize) -> &T::Output { obj.index(index) } @@ -26,12 +24,12 @@ pub trait Feed { // @has assoc_types/fn.use_input.html // @has - '//*[@class="rust fn"]' 'T::Input' -// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Feed.html#associatedtype.Input"]' 'Input' +// @has - '//*[@class="rust fn"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input' pub fn use_input(_feed: &T, _element: T::Input) { } // @has assoc_types/fn.cmp_input.html // @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq' -// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Feed.html#associatedtype.Input"]' 'Input' +// @has - '//*[@class="rust fn"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input' pub fn cmp_input(a: &T::Input, b: &U::Input) -> bool where T::Input: PartialEq { diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index aa4ad261c8..4b66b5271c 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // edition:2018 // @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option' pub async fn foo() -> Option { diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index 54c5939f90..51cd4a6cbf 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -1,21 +1,21 @@ #![crate_name = "foo"] -// @has foo/fn.f.html '//*[@class="docblock attributes"]' '#[no_mangle]' +// @has foo/fn.f.html '//*[@class="rust fn"]' '#[no_mangle]' #[no_mangle] pub extern "C" fn f() {} -// @has foo/fn.g.html '//*[@class="docblock attributes"]' '#[export_name = "bar"]' +// @has foo/fn.g.html '//*[@class="rust fn"]' '#[export_name = "bar"]' #[export_name = "bar"] pub extern "C" fn g() {} -// @matches foo/enum.Foo.html '//*[@class="docblock attributes top-attr"]' \ -// '(?m)\A#\[repr\(i64\)\]\n#\[must_use\]\Z' +// @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 attributes top-attr"]' '#[repr(C, align(8))]' +// @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/auto_aliases.rs b/src/test/rustdoc/auto_aliases.rs index b8f3527510..56e0770ab5 100644 --- a/src/test/rustdoc/auto_aliases.rs +++ b/src/test/rustdoc/auto_aliases.rs @@ -1,6 +1,6 @@ #![feature(auto_traits)] -// @has auto_aliases/trait.Bar.html '//h3[@aliases="auto_aliases::Foo"]' 'impl Bar for Foo' +// @has auto_aliases/trait.Bar.html '//h3[@data-aliases="auto_aliases::Foo"]' 'impl Bar for Foo' pub struct Foo; pub auto trait Bar {} diff --git a/src/test/rustdoc/auxiliary/primitive-doc.rs b/src/test/rustdoc/auxiliary/primitive-doc.rs new file mode 100644 index 0000000000..a5b69740dd --- /dev/null +++ b/src/test/rustdoc/auxiliary/primitive-doc.rs @@ -0,0 +1,6 @@ +// compile-flags: --crate-type lib --edition 2018 + +#[doc(primitive = "usize")] +/// This is the built-in type `usize`. +mod usize { +} diff --git a/src/test/rustdoc/check-styled-link.rs b/src/test/rustdoc/check-styled-link.rs index b479820dfb..ed4a5ea213 100644 --- a/src/test/rustdoc/check-styled-link.rs +++ b/src/test/rustdoc/check-styled-link.rs @@ -2,7 +2,7 @@ pub struct Foo; -// @has foo/struct.Bar.html '//a[@href="../foo/struct.Foo.html"]' 'Foo' +// @has foo/struct.Bar.html '//a[@href="struct.Foo.html"]' 'Foo' /// Code-styled reference to [`Foo`]. pub struct Bar; diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index 11ba68a388..fb5c8517f6 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_name = "foo"] #![unstable(feature = "humans", diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs index 85be89719e..77432ba153 100644 --- a/src/test/rustdoc/const-generics/add-impl.rs +++ b/src/test/rustdoc/const-generics/add-impl.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![feature(const_generics)] #![crate_name = "foo"] @@ -10,7 +8,7 @@ pub struct Simd { inner: T, } -// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]/h3/code' 'impl Add> for Simd' +// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3/code' 'impl Add> for Simd' impl Add for Simd { type Output = Self; diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index 03f5bb2ca4..04fb339533 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![feature(const_generics)] #![crate_name = "foo"] diff --git a/src/test/rustdoc/const-generics/type-alias.rs b/src/test/rustdoc/const-generics/type-alias.rs index 85160dc07a..ebda5b1940 100644 --- a/src/test/rustdoc/const-generics/type-alias.rs +++ b/src/test/rustdoc/const-generics/type-alias.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![crate_name = "foo"] // @has foo/type.CellIndex.html '//pre[@class="rust typedef"]' 'type CellIndex = [i64; D];' diff --git a/src/test/rustdoc/cross-crate-primitive-doc.rs b/src/test/rustdoc/cross-crate-primitive-doc.rs new file mode 100644 index 0000000000..05376e4680 --- /dev/null +++ b/src/test/rustdoc/cross-crate-primitive-doc.rs @@ -0,0 +1,9 @@ +// aux-build:primitive-doc.rs +// compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options + +#![no_std] + +extern crate primitive_doc; + +// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize' +pub fn foo() -> usize { 0 } diff --git a/src/test/rustdoc/decl_macro.rs b/src/test/rustdoc/decl_macro.rs index e48a56f906..ede3f455a2 100644 --- a/src/test/rustdoc/decl_macro.rs +++ b/src/test/rustdoc/decl_macro.rs @@ -1,3 +1,5 @@ +// compile-flags: --document-private-items + #![feature(decl_macro)] // @has decl_macro/macro.my_macro.html //pre 'pub macro my_macro() {' @@ -37,3 +39,18 @@ pub macro my_macro_multi { pub macro by_example_single { ($foo:expr) => {} } + +mod a { + mod b { + // @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) {' + pub(in a) macro by_example_vis_named { + ($foo:expr) => {} + } + } + } +} diff --git a/src/test/rustdoc/default-trait-method-link.rs b/src/test/rustdoc/default-trait-method-link.rs index e4f0bdab16..7bcd2a3c14 100644 --- a/src/test/rustdoc/default-trait-method-link.rs +++ b/src/test/rustdoc/default-trait-method-link.rs @@ -1,7 +1,7 @@ #![crate_name = "foo"] -// @has foo/trait.Foo.html '//a[@href="../foo/trait.Foo.html#tymethod.req"]' 'req' -// @has foo/trait.Foo.html '//a[@href="../foo/trait.Foo.html#method.prov"]' 'prov' +// @has foo/trait.Foo.html '//a[@href="trait.Foo.html#tymethod.req"]' 'req' +// @has foo/trait.Foo.html '//a[@href="trait.Foo.html#method.prov"]' 'prov' /// Always make sure to implement [`req`], but you don't have to implement [`prov`]. /// diff --git a/src/test/rustdoc/doc-spotlight.rs b/src/test/rustdoc/doc-notable_trait.rs similarity index 78% rename from src/test/rustdoc/doc-spotlight.rs rename to src/test/rustdoc/doc-notable_trait.rs index ddd46c3c21..58a24b855d 100644 --- a/src/test/rustdoc/doc-spotlight.rs +++ b/src/test/rustdoc/doc-notable_trait.rs @@ -1,4 +1,4 @@ -#![feature(doc_spotlight)] +#![feature(doc_notable_trait)] pub struct Wrapper { inner: T, @@ -6,9 +6,9 @@ pub struct Wrapper { impl SomeTrait for Wrapper {} -#[doc(spotlight)] +#[doc(notable_trait)] pub trait SomeTrait { - // @has doc_spotlight/trait.SomeTrait.html + // @has doc_notable_trait/trait.SomeTrait.html // @has - '//code[@class="content"]' 'impl SomeTrait for Wrapper' fn wrap_me(self) -> Wrapper where Self: Sized { Wrapper { @@ -21,7 +21,7 @@ pub struct SomeStruct; impl SomeTrait for SomeStruct {} impl SomeStruct { - // @has doc_spotlight/struct.SomeStruct.html + // @has doc_notable_trait/struct.SomeStruct.html // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' // @has - '//code[@class="content"]' 'impl SomeTrait for Wrapper' pub fn new() -> SomeStruct { @@ -29,7 +29,7 @@ impl SomeStruct { } } -// @has doc_spotlight/fn.bare_fn.html +// @has doc_notable_trait/fn.bare_fn.html // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' pub fn bare_fn() -> SomeStruct { SomeStruct diff --git a/src/test/rustdoc/double-quote-escape.rs b/src/test/rustdoc/double-quote-escape.rs index 243d8ad796..546af2c121 100644 --- a/src/test/rustdoc/double-quote-escape.rs +++ b/src/test/rustdoc/double-quote-escape.rs @@ -1,6 +1,5 @@ #![crate_name = "foo"] -// ignore-tidy-linelength pub trait Foo { fn foo() {} diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs index 7b938af3c7..cec504ea15 100644 --- a/src/test/rustdoc/duplicate-cfg.rs +++ b/src/test/rustdoc/duplicate-cfg.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_name = "foo"] #![feature(doc_cfg)] diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index 112d632971..1e644bb973 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -1,8 +1,8 @@ // @has issue_33054/impls/struct.Foo.html // @has - '//code' 'impl Foo' // @has - '//code' 'impl Bar for Foo' -// @count - '//*[@id="trait-implementations-list"]/*[@class="impl"]' 1 -// @count - '//*[@id="main"]/*[@class="impl"]' 1 +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 +// @count - '//*[@id="main"]/details/summary/*[@class="impl"]' 1 // @has issue_33054/impls/bar/trait.Bar.html // @has - '//code' 'impl Bar for Foo' // @count - '//*[@class="struct"]' 1 diff --git a/src/test/rustdoc/empty-impls.rs b/src/test/rustdoc/empty-impls.rs new file mode 100644 index 0000000000..86dec32e62 --- /dev/null +++ b/src/test/rustdoc/empty-impls.rs @@ -0,0 +1,19 @@ +#![crate_name = "foo"] + +// @has foo/struct.Foo.html +// @has - '//div[@id="synthetic-implementations-list"]/h3[@id="impl-Send"]' 'impl Send for Foo' +pub struct Foo; + +pub trait EmptyTrait {} + +// @has - '//div[@id="trait-implementations-list"]/h3[@id="impl-EmptyTrait"]' 'impl EmptyTrait for Foo' +impl EmptyTrait for Foo {} + +pub trait NotEmpty { + fn foo(&self); +} + +// @has - '//div[@id="trait-implementations-list"]/details/summary/h3[@id="impl-NotEmpty"]' 'impl NotEmpty for Foo' +impl NotEmpty for Foo { + fn foo(&self) {} +} diff --git a/src/test/rustdoc/fn-type.rs b/src/test/rustdoc/fn-type.rs index f5e123aed9..3959aeb6cf 100644 --- a/src/test/rustdoc/fn-type.rs +++ b/src/test/rustdoc/fn-type.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_name = "foo"] #![crate_type = "lib"] diff --git a/src/test/rustdoc/for-lifetime.rs b/src/test/rustdoc/for-lifetime.rs index 299794b63b..34a7eae31c 100644 --- a/src/test/rustdoc/for-lifetime.rs +++ b/src/test/rustdoc/for-lifetime.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_name = "foo"] #![crate_type = "lib"] diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index 44e2c4d3fb..a2adc0e63c 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -1,6 +1,5 @@ // aux-build:impl_trait_aux.rs // edition:2018 -// ignore-tidy-linelength extern crate impl_trait_aux; diff --git a/src/test/rustdoc/intra-doc-crate/self.rs b/src/test/rustdoc/intra-doc-crate/self.rs index 4db63b12b6..8c36a7fa00 100644 --- a/src/test/rustdoc/intra-doc-crate/self.rs +++ b/src/test/rustdoc/intra-doc-crate/self.rs @@ -3,7 +3,7 @@ extern crate cross_crate_self; -// @has self/struct.S.html '//a[@href="../self/struct.S.html#method.f"]' "Self::f" -// @has self/struct.S.html '//a[@href="../self/struct.S.html"]' "Self" +// @has self/struct.S.html '//a[@href="struct.S.html#method.f"]' "Self::f" +// @has self/struct.S.html '//a[@href="struct.S.html"]' "Self" // @has self/struct.S.html '//a[@href="../cross_crate_self/index.html"]' "crate" pub use cross_crate_self::S; diff --git a/src/test/rustdoc/intra-doc/anchors.rs b/src/test/rustdoc/intra-doc/anchors.rs index e4f0c737bd..8ec1a7b4f9 100644 --- a/src/test/rustdoc/intra-doc/anchors.rs +++ b/src/test/rustdoc/intra-doc/anchors.rs @@ -4,7 +4,7 @@ pub struct Something; // @has anchors/struct.SomeOtherType.html -// @has - '//a/@href' '../anchors/struct.Something.html#Anchor!' +// @has - '//a/@href' 'struct.Something.html#Anchor!' /// I want... /// diff --git a/src/test/rustdoc/intra-doc/associated-defaults.rs b/src/test/rustdoc/intra-doc/associated-defaults.rs index f99d9b5bae..68647127fe 100644 --- a/src/test/rustdoc/intra-doc/associated-defaults.rs +++ b/src/test/rustdoc/intra-doc/associated-defaults.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![deny(intra_doc_link_resolution_failure)] #![feature(associated_type_defaults)] @@ -10,14 +9,14 @@ pub trait TraitWithDefault { } /// Link to [UsesDefaults::T] and [UsesDefaults::f] -// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="../associated_defaults/struct.UsesDefaults.html#associatedtype.T"]' 'UsesDefaults::T' -// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="../associated_defaults/struct.UsesDefaults.html#method.f"]' 'UsesDefaults::f' +// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="struct.UsesDefaults.html#associatedtype.T"]' 'UsesDefaults::T' +// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="struct.UsesDefaults.html#method.f"]' 'UsesDefaults::f' pub struct UsesDefaults; impl TraitWithDefault for UsesDefaults {} /// Link to [OverridesDefaults::T] and [OverridesDefaults::f] -// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="../associated_defaults/struct.OverridesDefaults.html#associatedtype.T"]' 'OverridesDefaults::T' -// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="../associated_defaults/struct.OverridesDefaults.html#method.f"]' 'OverridesDefaults::f' +// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="struct.OverridesDefaults.html#associatedtype.T"]' 'OverridesDefaults::T' +// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="struct.OverridesDefaults.html#method.f"]' 'OverridesDefaults::f' pub struct OverridesDefaults; impl TraitWithDefault for OverridesDefaults { type T = bool; diff --git a/src/test/rustdoc/intra-doc/associated-items.rs b/src/test/rustdoc/intra-doc/associated-items.rs index 09dfbfcf68..2757418bc6 100644 --- a/src/test/rustdoc/intra-doc/associated-items.rs +++ b/src/test/rustdoc/intra-doc/associated-items.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![deny(intra_doc_link_resolution_failure)] /// [`std::collections::BTreeMap::into_iter`] @@ -10,10 +9,10 @@ pub fn foo() {} /// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input] -// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html"]' 'MyStruct' -// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#method.method"]' 'link from struct' -// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#method.clone"]' 'MyStruct::clone' -// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#associatedtype.Input"]' 'MyStruct::Input' +// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html"]' 'MyStruct' +// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#method.method"]' 'link from struct' +// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#method.clone"]' 'MyStruct::clone' +// @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#associatedtype.Input"]' 'MyStruct::Input' pub struct MyStruct { foo: () } impl Clone for MyStruct { @@ -31,7 +30,7 @@ impl T for MyStruct { type Input = usize; /// [link from method][MyStruct::method] on method - // @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#method.method"]' 'link from method' + // @has 'associated_items/struct.MyStruct.html' '//a[@href="struct.MyStruct.html#method.method"]' 'link from method' fn method(i: usize) { } } diff --git a/src/test/rustdoc/intra-doc/auxiliary/empty.rs b/src/test/rustdoc/intra-doc/auxiliary/empty.rs new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/src/test/rustdoc/intra-doc/auxiliary/empty.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/rustdoc/intra-doc/auxiliary/empty2.rs b/src/test/rustdoc/intra-doc/auxiliary/empty2.rs new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/src/test/rustdoc/intra-doc/auxiliary/empty2.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/rustdoc/auxiliary/issue-66159-1.rs b/src/test/rustdoc/intra-doc/auxiliary/issue-66159-1.rs similarity index 100% rename from src/test/rustdoc/auxiliary/issue-66159-1.rs rename to src/test/rustdoc/intra-doc/auxiliary/issue-66159-1.rs diff --git a/src/test/rustdoc/intra-doc/basic.rs b/src/test/rustdoc/intra-doc/basic.rs index 7760546e1f..39f5c298bc 100644 --- a/src/test/rustdoc/intra-doc/basic.rs +++ b/src/test/rustdoc/intra-doc/basic.rs @@ -1,21 +1,21 @@ // @has basic/index.html -// @has - '//a/@href' '../basic/struct.ThisType.html' -// @has - '//a/@href' '../basic/struct.ThisType.html#method.this_method' -// @has - '//a/@href' '../basic/enum.ThisEnum.html' -// @has - '//a/@href' '../basic/enum.ThisEnum.html#variant.ThisVariant' -// @has - '//a/@href' '../basic/trait.ThisTrait.html' -// @has - '//a/@href' '../basic/trait.ThisTrait.html#tymethod.this_associated_method' -// @has - '//a/@href' '../basic/trait.ThisTrait.html#associatedtype.ThisAssociatedType' -// @has - '//a/@href' '../basic/trait.ThisTrait.html#associatedconstant.THIS_ASSOCIATED_CONST' -// @has - '//a/@href' '../basic/trait.ThisTrait.html' -// @has - '//a/@href' '../basic/type.ThisAlias.html' -// @has - '//a/@href' '../basic/union.ThisUnion.html' -// @has - '//a/@href' '../basic/fn.this_function.html' -// @has - '//a/@href' '../basic/constant.THIS_CONST.html' -// @has - '//a/@href' '../basic/static.THIS_STATIC.html' -// @has - '//a/@href' '../basic/macro.this_macro.html' -// @has - '//a/@href' '../basic/trait.SoAmbiguous.html' -// @has - '//a/@href' '../basic/fn.SoAmbiguous.html' +// @has - '//a/@href' 'struct.ThisType.html' +// @has - '//a/@href' 'struct.ThisType.html#method.this_method' +// @has - '//a/@href' 'enum.ThisEnum.html' +// @has - '//a/@href' 'enum.ThisEnum.html#variant.ThisVariant' +// @has - '//a/@href' 'trait.ThisTrait.html' +// @has - '//a/@href' 'trait.ThisTrait.html#tymethod.this_associated_method' +// @has - '//a/@href' 'trait.ThisTrait.html#associatedtype.ThisAssociatedType' +// @has - '//a/@href' 'trait.ThisTrait.html#associatedconstant.THIS_ASSOCIATED_CONST' +// @has - '//a/@href' 'trait.ThisTrait.html' +// @has - '//a/@href' 'type.ThisAlias.html' +// @has - '//a/@href' 'union.ThisUnion.html' +// @has - '//a/@href' 'fn.this_function.html' +// @has - '//a/@href' 'constant.THIS_CONST.html' +// @has - '//a/@href' 'static.THIS_STATIC.html' +// @has - '//a/@href' 'macro.this_macro.html' +// @has - '//a/@href' 'trait.SoAmbiguous.html' +// @has - '//a/@href' 'fn.SoAmbiguous.html' //! In this crate we would like to link to: //! //! * [`ThisType`](ThisType) @@ -46,7 +46,7 @@ macro_rules! this_macro { () => {}; } -// @has basic/struct.ThisType.html '//a/@href' '../basic/macro.this_macro.html' +// @has basic/struct.ThisType.html '//a/@href' 'macro.this_macro.html' /// another link to [`this_macro!()`] pub struct ThisType; @@ -72,10 +72,10 @@ pub trait SoAmbiguous {} pub fn SoAmbiguous() {} -// @has basic/struct.SomeOtherType.html '//a/@href' '../basic/struct.ThisType.html' -// @has - '//a/@href' '../basic/struct.ThisType.html#method.this_method' -// @has - '//a/@href' '../basic/enum.ThisEnum.html' -// @has - '//a/@href' '../basic/enum.ThisEnum.html#variant.ThisVariant' +// @has basic/struct.SomeOtherType.html '//a/@href' 'struct.ThisType.html' +// @has - '//a/@href' 'struct.ThisType.html#method.this_method' +// @has - '//a/@href' 'enum.ThisEnum.html' +// @has - '//a/@href' 'enum.ThisEnum.html#variant.ThisVariant' /// Shortcut links for: /// * [`ThisType`] /// * [`ThisType::this_method`] diff --git a/src/test/rustdoc/intra-doc/cross-crate/additional_doc.rs b/src/test/rustdoc/intra-doc/cross-crate/additional_doc.rs index 837390b3c7..85c5866ca7 100644 --- a/src/test/rustdoc/intra-doc/cross-crate/additional_doc.rs +++ b/src/test/rustdoc/intra-doc/cross-crate/additional_doc.rs @@ -4,7 +4,7 @@ extern crate my_rand; -// @has 'additional_doc/trait.Rng.html' '//a[@href="../additional_doc/trait.Rng.html"]' 'Rng' +// @has 'additional_doc/trait.Rng.html' '//a[@href="trait.Rng.html"]' 'Rng' // @has 'additional_doc/trait.Rng.html' '//a[@href="../my_rand/trait.RngCore.html"]' 'RngCore' /// This is an [`Rng`]. pub use my_rand::Rng; diff --git a/src/test/rustdoc/intra-doc/cross-crate/hidden.rs b/src/test/rustdoc/intra-doc/cross-crate/hidden.rs index 9c9d4c6494..31337f20f1 100644 --- a/src/test/rustdoc/intra-doc/cross-crate/hidden.rs +++ b/src/test/rustdoc/intra-doc/cross-crate/hidden.rs @@ -6,5 +6,5 @@ extern crate hidden_dep; -// @has 'hidden/struct.Ready.html' '//a/@href' '../hidden/fn.ready.html' +// @has 'hidden/struct.Ready.html' '//a/@href' 'fn.ready.html' pub use hidden_dep::future::{ready, Ready}; diff --git a/src/test/rustdoc/intra-doc/cross-crate/macro.rs b/src/test/rustdoc/intra-doc/cross-crate/macro.rs index 311b16dff1..62659ce689 100644 --- a/src/test/rustdoc/intra-doc/cross-crate/macro.rs +++ b/src/test/rustdoc/intra-doc/cross-crate/macro.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // aux-build:macro_inner.rs // aux-build:proc_macro.rs // build-aux-docs diff --git a/src/test/rustdoc/intra-doc/cross-crate/submodule-outer.rs b/src/test/rustdoc/intra-doc/cross-crate/submodule-outer.rs index 45f561328f..db7952b5ac 100644 --- a/src/test/rustdoc/intra-doc/cross-crate/submodule-outer.rs +++ b/src/test/rustdoc/intra-doc/cross-crate/submodule-outer.rs @@ -11,6 +11,6 @@ pub mod bar { // NOTE: we re-exported both `Foo` and `Bar` here, // NOTE: so they are inlined and therefore we link to the current module. -// @has 'submodule_outer/trait.Foo.html' '//a[@href="../submodule_outer/bar/trait.Bar.html"]' 'Bar' -// @has 'submodule_outer/trait.Foo.html' '//a[@href="../submodule_outer/trait.Baz.html"]' 'Baz' +// @has 'submodule_outer/trait.Foo.html' '//a[@href="bar/trait.Bar.html"]' 'Bar' +// @has 'submodule_outer/trait.Foo.html' '//a[@href="trait.Baz.html"]' 'Baz' pub use ::bar_::{Foo, Baz}; diff --git a/src/test/rustdoc/intra-doc/cross-crate/traits.rs b/src/test/rustdoc/intra-doc/cross-crate/traits.rs index 07decb4801..68f5cb3a09 100644 --- a/src/test/rustdoc/intra-doc/cross-crate/traits.rs +++ b/src/test/rustdoc/intra-doc/cross-crate/traits.rs @@ -1,6 +1,5 @@ // aux-build:traits.rs // build-aux-docs -// ignore-tidy-line-length #![deny(broken_intra_doc_links)] extern crate inner; diff --git a/src/test/rustdoc/intra-doc/disambiguators-removed.rs b/src/test/rustdoc/intra-doc/disambiguators-removed.rs index aa0ced62aa..d782c5cf5d 100644 --- a/src/test/rustdoc/intra-doc/disambiguators-removed.rs +++ b/src/test/rustdoc/intra-doc/disambiguators-removed.rs @@ -1,28 +1,27 @@ -// ignore-tidy-linelength #![deny(intra_doc_link_resolution_failure)] // first try backticks /// Trait: [`trait@Name`], fn: [`fn@Name`], [`Name`][`macro@Name`] // @has disambiguators_removed/struct.AtDisambiguator.html -// @has - '//a[@href="../disambiguators_removed/trait.Name.html"][code]' "Name" -// @has - '//a[@href="../disambiguators_removed/fn.Name.html"][code]' "Name" -// @has - '//a[@href="../disambiguators_removed/macro.Name.html"][code]' "Name" +// @has - '//a[@href="trait.Name.html"][code]' "Name" +// @has - '//a[@href="fn.Name.html"][code]' "Name" +// @has - '//a[@href="macro.Name.html"][code]' "Name" pub struct AtDisambiguator; /// fn: [`Name()`], macro: [`Name!`] // @has disambiguators_removed/struct.SymbolDisambiguator.html -// @has - '//a[@href="../disambiguators_removed/fn.Name.html"][code]' "Name()" -// @has - '//a[@href="../disambiguators_removed/macro.Name.html"][code]' "Name!" +// @has - '//a[@href="fn.Name.html"][code]' "Name()" +// @has - '//a[@href="macro.Name.html"][code]' "Name!" pub struct SymbolDisambiguator; // Now make sure that backticks aren't added if they weren't already there /// [fn@Name] // @has disambiguators_removed/trait.Name.html -// @has - '//a[@href="../disambiguators_removed/fn.Name.html"]' "Name" -// @!has - '//a[@href="../disambiguators_removed/fn.Name.html"][code]' "Name" +// @has - '//a[@href="fn.Name.html"]' "Name" +// @!has - '//a[@href="fn.Name.html"][code]' "Name" // FIXME: this will turn !() into ! alone /// [Name!()] -// @has - '//a[@href="../disambiguators_removed/macro.Name.html"]' "Name!" +// @has - '//a[@href="macro.Name.html"]' "Name!" pub trait Name {} #[allow(non_snake_case)] @@ -30,22 +29,22 @@ pub trait Name {} // Try collapsed reference links /// [macro@Name][] // @has disambiguators_removed/fn.Name.html -// @has - '//a[@href="../disambiguators_removed/macro.Name.html"]' "Name" +// @has - '//a[@href="macro.Name.html"]' "Name" // Try links that have the same text as a generated URL -/// Weird URL aligned [../disambiguators_removed/macro.Name.html][trait@Name] -// @has - '//a[@href="../disambiguators_removed/trait.Name.html"]' "../disambiguators_removed/macro.Name.html" +/// Weird URL aligned [macro.Name.html][trait@Name] +// @has - '//a[@href="trait.Name.html"]' "macro.Name.html" pub fn Name() {} #[macro_export] // Rustdoc doesn't currently handle links that have weird interspersing of inline code blocks. /// [fn@Na`m`e] // @has disambiguators_removed/macro.Name.html -// @has - '//a[@href="../disambiguators_removed/fn.Name.html"]' "fn@Name" +// @has - '//a[@href="fn.Name.html"]' "fn@Name" // It also doesn't handle any case where the code block isn't the whole link text: /// [trait@`Name`] -// @has - '//a[@href="../disambiguators_removed/trait.Name.html"]' "trait@Name" +// @has - '//a[@href="trait.Name.html"]' "trait@Name" macro_rules! Name { () => () } diff --git a/src/test/rustdoc/intra-doc/email-address.rs b/src/test/rustdoc/intra-doc/email-address.rs new file mode 100644 index 0000000000..c407eb80da --- /dev/null +++ b/src/test/rustdoc/intra-doc/email-address.rs @@ -0,0 +1,6 @@ +//! Email me at . +//! Email me at . +//! Email me at (this warns but will still become a link). +// @has email_address/index.html '//a[@href="mailto:hello@example.com"]' 'hello@example.com' +// @has email_address/index.html '//a[@href="mailto:hello-world@example.com"]' 'hello-world@example.com' +// @has email_address/index.html '//a[@href="mailto:hello@localhost"]' 'hello@localhost' diff --git a/src/test/rustdoc/intra-doc/enum-struct-field.rs b/src/test/rustdoc/intra-doc/enum-struct-field.rs index 70bf343a9a..2270a1fafa 100644 --- a/src/test/rustdoc/intra-doc/enum-struct-field.rs +++ b/src/test/rustdoc/intra-doc/enum-struct-field.rs @@ -11,4 +11,4 @@ pub enum Foo { /// I want [Foo::X::y]. pub fn foo() {} -// @has foo/fn.foo.html '//a/@href' '../foo/enum.Foo.html#variant.X.field.y' +// @has foo/fn.foo.html '//a/@href' 'enum.Foo.html#variant.X.field.y' diff --git a/src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs b/src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs new file mode 100644 index 0000000000..5d8dcf8bc1 --- /dev/null +++ b/src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs @@ -0,0 +1,19 @@ +// This test is just a little cursed. +// aux-build:issue-66159-1.rs +// aux-crate:priv:issue_66159_1=issue-66159-1.rs +// aux-build:empty.rs +// aux-crate:priv:empty=empty.rs +// aux-build:empty2.rs +// aux-crate:priv:empty2=empty2.rs +// build-aux-docs +// compile-flags:-Z unstable-options --edition 2018 + +// @has extern_crate_only_used_in_link/index.html +// @has - '//a[@href="../issue_66159_1/struct.Something.html"]' 'issue_66159_1::Something' +//! [issue_66159_1::Something] + +// @has - '//a[@href="../empty/index.html"]' 'empty' +//! [`empty`] + +// @has - '//a[@href="../empty2/index.html"]' 'empty2' +//! [empty2] diff --git a/src/test/rustdoc/intra-doc/extern-type.rs b/src/test/rustdoc/intra-doc/extern-type.rs index e1934698d1..f37ae62dde 100644 --- a/src/test/rustdoc/intra-doc/extern-type.rs +++ b/src/test/rustdoc/intra-doc/extern-type.rs @@ -12,6 +12,6 @@ impl ExternType { // @has 'extern_type/foreigntype.ExternType.html' // @has 'extern_type/fn.links_to_extern_type.html' \ -// 'href="../extern_type/foreigntype.ExternType.html#method.f"' +// 'href="foreigntype.ExternType.html#method.f"' /// See also [ExternType::f] pub fn links_to_extern_type() {} diff --git a/src/test/rustdoc/intra-doc/issue-82209.rs b/src/test/rustdoc/intra-doc/issue-82209.rs index 76618cdce4..68a5672a8d 100644 --- a/src/test/rustdoc/intra-doc/issue-82209.rs +++ b/src/test/rustdoc/intra-doc/issue-82209.rs @@ -8,4 +8,4 @@ pub enum Foo { }, } -// @has foo/enum.Foo.html '//a/@href' '../foo/enum.Foo.html#variant.Bar.field.abc' +// @has foo/enum.Foo.html '//a/@href' 'enum.Foo.html#variant.Bar.field.abc' diff --git a/src/test/rustdoc/intra-doc/mod-ambiguity.rs b/src/test/rustdoc/intra-doc/mod-ambiguity.rs index feb013b22b..24b9dc30a9 100644 --- a/src/test/rustdoc/intra-doc/mod-ambiguity.rs +++ b/src/test/rustdoc/intra-doc/mod-ambiguity.rs @@ -6,11 +6,11 @@ pub fn foo() { } pub mod foo {} -// @has mod_ambiguity/struct.A.html '//a/@href' '../mod_ambiguity/foo/index.html' +// @has mod_ambiguity/struct.A.html '//a/@href' 'foo/index.html' /// Module is [`module@foo`] pub struct A; -// @has mod_ambiguity/struct.B.html '//a/@href' '../mod_ambiguity/fn.foo.html' +// @has mod_ambiguity/struct.B.html '//a/@href' 'fn.foo.html' /// Function is [`fn@foo`] pub struct B; diff --git a/src/test/rustdoc/intra-doc/non-path-primitives.rs b/src/test/rustdoc/intra-doc/non-path-primitives.rs index ffa02b0c63..ee71537d15 100644 --- a/src/test/rustdoc/intra-doc/non-path-primitives.rs +++ b/src/test/rustdoc/intra-doc/non-path-primitives.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![crate_name = "foo"] #![feature(intra_doc_pointers)] #![deny(rustdoc::broken_intra_doc_links)] diff --git a/src/test/rustdoc/intra-doc/prim-assoc.rs b/src/test/rustdoc/intra-doc/prim-assoc.rs index d687cbd69b..4099ececfa 100644 --- a/src/test/rustdoc/intra-doc/prim-assoc.rs +++ b/src/test/rustdoc/intra-doc/prim-assoc.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![deny(broken_intra_doc_links)] //! [i32::MAX] diff --git a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs index 434e033898..695a7fbfb5 100644 --- a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs +++ b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs @@ -2,7 +2,6 @@ // build-aux-docs // ignore-cross-compile // ignore-windows -// ignore-tidy-linelength #![deny(broken_intra_doc_links)] #![feature(no_core, lang_items)] diff --git a/src/test/rustdoc/intra-doc/prim-methods-local.rs b/src/test/rustdoc/intra-doc/prim-methods-local.rs index 9888f29db5..f0b939a468 100644 --- a/src/test/rustdoc/intra-doc/prim-methods-local.rs +++ b/src/test/rustdoc/intra-doc/prim-methods-local.rs @@ -3,7 +3,6 @@ #![no_core] #![crate_type = "rlib"] -// ignore-tidy-linelength // @has prim_methods_local/index.html // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char' diff --git a/src/test/rustdoc/intra-doc/prim-methods.rs b/src/test/rustdoc/intra-doc/prim-methods.rs index f19cff7d34..6de15e76d1 100644 --- a/src/test/rustdoc/intra-doc/prim-methods.rs +++ b/src/test/rustdoc/intra-doc/prim-methods.rs @@ -1,6 +1,5 @@ #![deny(broken_intra_doc_links)] -// ignore-tidy-linelength // @has prim_methods/index.html // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char' diff --git a/src/test/rustdoc/intra-doc/prim-precedence.rs b/src/test/rustdoc/intra-doc/prim-precedence.rs index ed2c2cda71..478b40b0b5 100644 --- a/src/test/rustdoc/intra-doc/prim-precedence.rs +++ b/src/test/rustdoc/intra-doc/prim-precedence.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![deny(broken_intra_doc_links)] pub mod char { @@ -12,6 +11,6 @@ pub mod char { pub struct MyString; /// See also [crate::char] and [mod@char] -// @has prim_precedence/struct.MyString2.html '//*[@href="../prim_precedence/char/index.html"]' 'crate::char' -// @has - '//*[@href="../prim_precedence/char/index.html"]' 'mod@char' +// @has prim_precedence/struct.MyString2.html '//*[@href="char/index.html"]' 'crate::char' +// @has - '//*[@href="char/index.html"]' 'mod@char' pub struct MyString2; diff --git a/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs index 548eb090a3..cf83ead4db 100644 --- a/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs +++ b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs @@ -1,6 +1,5 @@ #![deny(broken_intra_doc_links)] -// ignore-tidy-linelength // @has primitive_non_default_impl/fn.str_methods.html /// [`str::trim`] diff --git a/src/test/rustdoc/intra-doc/private.rs b/src/test/rustdoc/intra-doc/private.rs index f86ca44403..2756a7998e 100644 --- a/src/test/rustdoc/intra-doc/private.rs +++ b/src/test/rustdoc/intra-doc/private.rs @@ -1,6 +1,17 @@ #![crate_name = "private"] // compile-flags: --document-private-items -/// docs [DontDocMe] -// @has private/struct.DocMe.html '//*a[@href="../private/struct.DontDocMe.html"]' 'DontDocMe' + +// make sure to update `rustdoc-ui/intra-doc/private.rs` if you update this file + +/// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x] +// @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html"]' 'DontDocMe' +// @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html#method.f"]' 'DontDocMe::f' +// @has private/struct.DocMe.html '//*a[@href="struct.DontDocMe.html#structfield.x"]' 'DontDocMe::x' pub struct DocMe; -struct DontDocMe; +struct DontDocMe { + x: usize, +} + +impl DontDocMe { + fn f() {} +} diff --git a/src/test/rustdoc/intra-doc/proc-macro.rs b/src/test/rustdoc/intra-doc/proc-macro.rs index ab4626ccfc..fce10a130b 100644 --- a/src/test/rustdoc/intra-doc/proc-macro.rs +++ b/src/test/rustdoc/intra-doc/proc-macro.rs @@ -9,17 +9,17 @@ pub use proc_macro_macro::{DeriveA, attr_a}; use proc_macro_macro::{DeriveB, attr_b}; // @has proc_macro/struct.Foo.html -// @has - '//a/@href' '../proc_macro/derive.DeriveA.html' -// @has - '//a/@href' '../proc_macro/attr.attr_a.html' -// @has - '//a/@href' '../proc_macro/trait.DeriveTrait.html' +// @has - '//a/@href' 'derive.DeriveA.html' +// @has - '//a/@href' 'attr.attr_a.html' +// @has - '//a/@href' 'trait.DeriveTrait.html' // @has - '//a/@href' '../proc_macro_macro/derive.DeriveB.html' // @has - '//a/@href' '../proc_macro_macro/attr.attr_b.html' /// Link to [DeriveA], [attr_a], [DeriveB], [attr_b], [DeriveTrait] pub struct Foo; // @has proc_macro/struct.Bar.html -// @has - '//a/@href' '../proc_macro/derive.DeriveA.html' -// @has - '//a/@href' '../proc_macro/attr.attr_a.html' +// @has - '//a/@href' 'derive.DeriveA.html' +// @has - '//a/@href' 'attr.attr_a.html' /// Link to [deriveA](derive@DeriveA) [attr](macro@attr_a) pub struct Bar; diff --git a/src/test/rustdoc/intra-doc/pub-use.rs b/src/test/rustdoc/intra-doc/pub-use.rs index dd52249abc..579fa68cee 100644 --- a/src/test/rustdoc/intra-doc/pub-use.rs +++ b/src/test/rustdoc/intra-doc/pub-use.rs @@ -13,7 +13,7 @@ extern crate inner; // @has outer/index.html // @ has - '//a[@href="https://doc.rust-lang.org/nightly/std/env/fn.var.html"]' "std::env" -// @ has - '//a[@href="../outer/fn.f.html"]' "g" +// @ has - '//a[@href="fn.f.html"]' "g" pub use f as g; // FIXME: same as above diff --git a/src/test/rustdoc/intra-doc/raw-ident-self.rs b/src/test/rustdoc/intra-doc/raw-ident-self.rs index d289797f14..177c3016fb 100644 --- a/src/test/rustdoc/intra-doc/raw-ident-self.rs +++ b/src/test/rustdoc/intra-doc/raw-ident-self.rs @@ -5,7 +5,7 @@ pub mod r#impl { impl S { /// See [Self::b]. // @has raw_ident_self/impl/struct.S.html - // @has - '//a[@href="../../raw_ident_self/impl/struct.S.html#method.b"]' 'Self::b' + // @has - '//a[@href="struct.S.html#method.b"]' 'Self::b' pub fn a() {} pub fn b() {} diff --git a/src/test/rustdoc/intra-doc/reexport-additional-docs.rs b/src/test/rustdoc/intra-doc/reexport-additional-docs.rs index 96f3580f30..64683bacd6 100644 --- a/src/test/rustdoc/intra-doc/reexport-additional-docs.rs +++ b/src/test/rustdoc/intra-doc/reexport-additional-docs.rs @@ -3,13 +3,13 @@ #![crate_name = "foo"] extern crate inner; -// @has foo/struct.Inner.html '//a[@href="../foo/fn.with_code.html"]' 'crate::with_code' +// @has foo/struct.Inner.html '//a[@href="fn.with_code.html"]' 'crate::with_code' /// [crate::with_code] -// @has - '//a[@href="../foo/fn.with_code.html"]' 'different text' +// @has - '//a[@href="fn.with_code.html"]' 'different text' /// [different text][with_code] -// @has - '//a[@href="../foo/fn.me_too.html"]' 'me_too' +// @has - '//a[@href="fn.me_too.html"]' 'me_too' #[doc = "[me_too]"] -// @has - '//a[@href="../foo/fn.me_three.html"]' 'reference link' +// @has - '//a[@href="fn.me_three.html"]' 'reference link' /// This [reference link] #[doc = "has an attr in the way"] /// diff --git a/src/test/rustdoc/intra-doc/self.rs b/src/test/rustdoc/intra-doc/self.rs index 81545fec74..0ba7df8a78 100644 --- a/src/test/rustdoc/intra-doc/self.rs +++ b/src/test/rustdoc/intra-doc/self.rs @@ -1,9 +1,8 @@ #![crate_name = "foo"] -// ignore-tidy-linelength -// @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new' -// @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new' +// @has foo/index.html '//a/@href' 'struct.Foo.html#method.new' +// @has foo/struct.Foo.html '//a/@href' 'struct.Foo.html#method.new' /// Use [`new`] to create a new instance. /// @@ -16,8 +15,8 @@ impl Foo { } } -// @has foo/index.html '//a/@href' '../foo/struct.Bar.html#method.new2' -// @has foo/struct.Bar.html '//a/@href' '../foo/struct.Bar.html#method.new2' +// @has foo/index.html '//a/@href' 'struct.Bar.html#method.new2' +// @has foo/struct.Bar.html '//a/@href' 'struct.Bar.html#method.new2' /// Use [`new2`] to create a new instance. /// @@ -31,7 +30,7 @@ impl Bar { } pub struct MyStruct { - // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#structfield.struct_field' + // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#structfield.struct_field' /// [`struct_field`] /// @@ -40,7 +39,7 @@ pub struct MyStruct { } pub enum MyEnum { - // @has foo/enum.MyEnum.html '//a/@href' '../foo/enum.MyEnum.html#variant.EnumVariant' + // @has foo/enum.MyEnum.html '//a/@href' 'enum.MyEnum.html#variant.EnumVariant' /// [`EnumVariant`] /// @@ -49,7 +48,7 @@ pub enum MyEnum { } pub union MyUnion { - // @has foo/union.MyUnion.html '//a/@href' '../foo/union.MyUnion.html#structfield.union_field' + // @has foo/union.MyUnion.html '//a/@href' 'union.MyUnion.html#structfield.union_field' /// [`union_field`] /// @@ -58,21 +57,21 @@ pub union MyUnion { } pub trait MyTrait { - // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedtype.AssoType' + // @has foo/trait.MyTrait.html '//a/@href' 'trait.MyTrait.html#associatedtype.AssoType' /// [`AssoType`] /// /// [`AssoType`]: Self::AssoType type AssoType; - // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedconstant.ASSO_CONST' + // @has foo/trait.MyTrait.html '//a/@href' 'trait.MyTrait.html#associatedconstant.ASSO_CONST' /// [`ASSO_CONST`] /// /// [`ASSO_CONST`]: Self::ASSO_CONST const ASSO_CONST: i32 = 1; - // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#method.asso_fn' + // @has foo/trait.MyTrait.html '//a/@href' 'trait.MyTrait.html#method.asso_fn' /// [`asso_fn`] /// @@ -81,7 +80,7 @@ pub trait MyTrait { } impl MyStruct { - // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.for_impl' + // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#method.for_impl' /// [`for_impl`] /// @@ -92,21 +91,21 @@ impl MyStruct { } impl MyTrait for MyStruct { - // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType' + // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedtype.AssoType' /// [`AssoType`] /// /// [`AssoType`]: Self::AssoType type AssoType = u32; - // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST' + // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedconstant.ASSO_CONST' /// [`ASSO_CONST`] /// /// [`ASSO_CONST`]: Self::ASSO_CONST const ASSO_CONST: i32 = 10; - // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.asso_fn' + // @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#method.asso_fn' /// [`asso_fn`] /// diff --git a/src/test/rustdoc/intra-doc/trait-impl.rs b/src/test/rustdoc/intra-doc/trait-impl.rs index fab8406d52..cf60dc1dbd 100644 --- a/src/test/rustdoc/intra-doc/trait-impl.rs +++ b/src/test/rustdoc/intra-doc/trait-impl.rs @@ -1,26 +1,25 @@ #![crate_name = "foo"] -// ignore-tidy-linelength pub struct MyStruct; impl MyTrait for MyStruct { -// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType' +// @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedtype.AssoType' /// [`AssoType`] /// /// [`AssoType`]: MyStruct::AssoType type AssoType = u32; -// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST' +// @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#associatedconstant.ASSO_CONST' /// [`ASSO_CONST`] /// /// [`ASSO_CONST`]: MyStruct::ASSO_CONST const ASSO_CONST: i32 = 10; -// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.trait_fn' +// @has foo/struct.MyStruct.html '//a/@href' 'struct.MyStruct.html#method.trait_fn' /// [`trait_fn`] /// diff --git a/src/test/rustdoc/intra-doc/trait-item.rs b/src/test/rustdoc/intra-doc/trait-item.rs index de8585f4c9..7602aced56 100644 --- a/src/test/rustdoc/intra-doc/trait-item.rs +++ b/src/test/rustdoc/intra-doc/trait-item.rs @@ -1,9 +1,8 @@ -// ignore-tidy-linelength #![deny(broken_intra_doc_links)] /// Link to [S::assoc_fn()] /// Link to [Default::default()] -// @has trait_item/struct.S.html '//*[@href="../trait_item/struct.S.html#method.assoc_fn"]' 'S::assoc_fn()' +// @has trait_item/struct.S.html '//*[@href="struct.S.html#method.assoc_fn"]' 'S::assoc_fn()' // @has - '//*[@href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html#tymethod.default"]' 'Default::default()' pub struct S; diff --git a/src/test/rustdoc/intra-doc/true-false.rs b/src/test/rustdoc/intra-doc/true-false.rs index 7b21e93414..db637ece36 100644 --- a/src/test/rustdoc/intra-doc/true-false.rs +++ b/src/test/rustdoc/intra-doc/true-false.rs @@ -1,7 +1,6 @@ #![deny(broken_intra_doc_links)] #![crate_name = "foo"] -// ignore-tidy-linelength // @has foo/index.html // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'true' diff --git a/src/test/rustdoc/intra-link-self-cache.rs b/src/test/rustdoc/intra-link-self-cache.rs index add1530a5a..63bf7fa576 100644 --- a/src/test/rustdoc/intra-link-self-cache.rs +++ b/src/test/rustdoc/intra-link-self-cache.rs @@ -1,12 +1,12 @@ #![crate_name = "foo"] -// @has foo/enum.E1.html '//a/@href' '../foo/enum.E1.html#variant.A' +// @has foo/enum.E1.html '//a/@href' 'enum.E1.html#variant.A' /// [Self::A::b] pub enum E1 { A { b: usize } } -// @has foo/enum.E2.html '//a/@href' '../foo/enum.E2.html#variant.A' +// @has foo/enum.E2.html '//a/@href' 'enum.E2.html#variant.A' /// [Self::A::b] pub enum E2 { diff --git a/src/test/rustdoc/issue-21474.rs b/src/test/rustdoc/issue-21474.rs index 896fc1a78f..5de26abace 100644 --- a/src/test/rustdoc/issue-21474.rs +++ b/src/test/rustdoc/issue-21474.rs @@ -7,5 +7,5 @@ mod inner { pub trait Blah { } // @count issue_21474/struct.What.html \ -// '//*[@id="trait-implementations-list"]/*[@class="impl"]' 1 +// '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 pub struct What; diff --git a/src/test/rustdoc/issue-28478.rs b/src/test/rustdoc/issue-28478.rs index 4cc4056025..497276e682 100644 --- a/src/test/rustdoc/issue-28478.rs +++ b/src/test/rustdoc/issue-28478.rs @@ -23,9 +23,9 @@ impl Foo { } impl Bar for Foo { - // @has - '//*[@href="../issue_28478/trait.Bar.html#associatedtype.Bar"]' 'Bar' - // @has - '//*[@href="../issue_28478/trait.Bar.html#associatedconstant.Baz"]' 'Baz' - // @has - '//*[@href="../issue_28478/trait.Bar.html#tymethod.bar"]' 'bar' + // @has - '//*[@href="trait.Bar.html#associatedtype.Bar"]' 'Bar' + // @has - '//*[@href="trait.Bar.html#associatedconstant.Baz"]' 'Baz' + // @has - '//*[@href="trait.Bar.html#tymethod.bar"]' 'bar' fn bar() {} - // @has - '//*[@href="../issue_28478/trait.Bar.html#method.baz"]' 'baz' + // @has - '//*[@href="trait.Bar.html#method.baz"]' 'baz' } diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs index d7e0f37b28..2b25da77d7 100644 --- a/src/test/rustdoc/issue-29503.rs +++ b/src/test/rustdoc/issue-29503.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - use std::fmt; // @has issue_29503/trait.MyTrait.html @@ -7,7 +5,7 @@ pub trait MyTrait { fn my_string(&self) -> String; } -// @has - "//div[@id='implementors-list']/h3[@id='impl-MyTrait']//code" "impl MyTrait for T where T: Debug" +// @has - "//div[@id='implementors-list']//h3[@id='impl-MyTrait']//code" "impl MyTrait for T where T: Debug" impl MyTrait for T where T: fmt::Debug { fn my_string(&self) -> String { format!("{:?}", self) diff --git a/src/test/rustdoc/issue-45584.rs b/src/test/rustdoc/issue-45584.rs index 0225c0c5c2..8a5f041382 100644 --- a/src/test/rustdoc/issue-45584.rs +++ b/src/test/rustdoc/issue-45584.rs @@ -4,12 +4,12 @@ pub trait Bar {} // @has 'foo/struct.Foo1.html' pub struct Foo1; -// @count - '//*[@id="trait-implementations-list"]/*[@class="impl"]' 1 +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 // @has - '//*[@class="impl"]' "impl Bar for Foo1" impl Bar for Foo1 {} // @has 'foo/struct.Foo2.html' pub struct Foo2; -// @count - '//*[@id="trait-implementations-list"]/*[@class="impl"]' 1 +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 // @has - '//*[@class="impl"]' "impl Bar<&'static Foo2, Foo2> for u8" impl Bar<&'static Foo2, Foo2> for u8 {} diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs index 74502be622..0820512e52 100644 --- a/src/test/rustdoc/issue-50159.rs +++ b/src/test/rustdoc/issue-50159.rs @@ -13,8 +13,8 @@ impl Signal2 for B where B: Signal { // @has issue_50159/struct.Switch.html // @has - '//code' 'impl Send for Switch where ::Item: Send' // @has - '//code' 'impl Sync for Switch where ::Item: Sync' -// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0 -// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 5 +// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 pub struct Switch { pub inner: ::Item2, } diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs index d9accf9c59..d018c94816 100644 --- a/src/test/rustdoc/issue-51236.rs +++ b/src/test/rustdoc/issue-51236.rs @@ -7,7 +7,7 @@ pub mod traits { } // @has issue_51236/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl Send for \ // Owned where >::Reader: Send" pub struct Owned where T: for<'a> ::traits::Owned<'a> { marker: PhantomData<>::Reader>, diff --git a/src/test/rustdoc/issue-53812.rs b/src/test/rustdoc/issue-53812.rs index 3ebf154077..ddc14e6867 100644 --- a/src/test/rustdoc/issue-53812.rs +++ b/src/test/rustdoc/issue-53812.rs @@ -12,9 +12,9 @@ macro_rules! array_impls { } } -// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]//h3[1]' 'MyStruct<[T; 0]>' -// @has - '//*[@id="implementors-list"]//h3[2]' 'MyStruct<[T; 1]>' -// @has - '//*[@id="implementors-list"]//h3[3]' 'MyStruct<[T; 2]>' -// @has - '//*[@id="implementors-list"]//h3[4]' 'MyStruct<[T; 3]>' -// @has - '//*[@id="implementors-list"]//h3[5]' 'MyStruct<[T; 10]>' +// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]/h3[1]' 'MyStruct<[T; 0]>' +// @has - '//*[@id="implementors-list"]/h3[2]' 'MyStruct<[T; 1]>' +// @has - '//*[@id="implementors-list"]/h3[3]' 'MyStruct<[T; 2]>' +// @has - '//*[@id="implementors-list"]/h3[4]' 'MyStruct<[T; 3]>' +// @has - '//*[@id="implementors-list"]/h3[5]' 'MyStruct<[T; 10]>' array_impls! { 10 3 2 1 0 } diff --git a/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs index 263b1eb0bd..47da94a4cc 100644 --- a/src/test/rustdoc/issue-54705.rs +++ b/src/test/rustdoc/issue-54705.rs @@ -3,10 +3,10 @@ pub trait ScopeHandle<'scope> {} // @has issue_54705/struct.ScopeFutureContents.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'scope, S> \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'scope, S> \ // Send for ScopeFutureContents<'scope, S> where S: Sync" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'scope, S> \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'scope, S> \ // Sync for ScopeFutureContents<'scope, S> where S: Sync" pub struct ScopeFutureContents<'scope, S> where S: ScopeHandle<'scope>, diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs index d312a51145..d1877f39ba 100644 --- a/src/test/rustdoc/issue-55321.rs +++ b/src/test/rustdoc/issue-55321.rs @@ -1,16 +1,16 @@ #![feature(negative_impls)] // @has issue_55321/struct.A.html -// @has - '//*[@id="trait-implementations-list"]/*[@class="impl"]//code' "impl !Send for A" -// @has - '//*[@id="trait-implementations-list"]/*[@class="impl"]//code' "impl !Sync for A" +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' "impl !Send for A" +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' "impl !Sync for A" pub struct A(); impl !Send for A {} impl !Sync for A {} // @has issue_55321/struct.B.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl !Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl !Send for \ // B" -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl !Sync for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl !Sync for \ // B" pub struct B(A, Box); diff --git a/src/test/rustdoc/issue-55364.rs b/src/test/rustdoc/issue-55364.rs index 200a29fc7e..f156d225bd 100644 --- a/src/test/rustdoc/issue-55364.rs +++ b/src/test/rustdoc/issue-55364.rs @@ -1,22 +1,20 @@ -// ignore-tidy-linelength - // First a module with inner documentation // @has issue_55364/subone/index.html // These foo/bar links in the module's documentation should refer inside `subone` -// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.foo.html"]' 'foo' -// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.bar.html"]' 'bar' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' pub mod subone { //! See either [foo] or [bar]. // This should refer to subone's `bar` // @has issue_55364/subone/fn.foo.html - // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.bar.html"]' 'bar' + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' /// See [bar] pub fn foo() {} // This should refer to subone's `foo` // @has issue_55364/subone/fn.bar.html - // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subone/fn.foo.html"]' 'foo' + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' /// See [foo] pub fn bar() {} } @@ -25,11 +23,11 @@ pub mod subone { // @has issue_55364/subtwo/index.html // These foo/bar links in the module's documentation should not reference inside `subtwo` -// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.foo.html"]' 'foo' -// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.bar.html"]' 'bar' +// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' +// @!has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' // Instead it should be referencing the top level functions -// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.foo.html"]' 'foo' -// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.bar.html"]' 'bar' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/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' @@ -39,13 +37,13 @@ pub mod subtwo { // Despite the module's docs referring to the top level foo/bar, // this should refer to subtwo's `bar` // @has issue_55364/subtwo/fn.foo.html - // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.bar.html"]' 'bar' + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' /// See [bar] pub fn foo() {} // Despite the module's docs referring to the top level foo/bar, // this should refer to subtwo's `foo` // @has issue_55364/subtwo/fn.bar.html - // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/subtwo/fn.foo.html"]' 'foo' + // @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' /// See [foo] pub fn bar() {} } @@ -61,8 +59,8 @@ pub fn bar() {} // @has issue_55364/subthree/index.html // This module should also refer to the top level foo/bar -// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.foo.html"]' 'foo' -// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../../issue_55364/fn.bar.html"]' 'bar' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar' pub mod subthree { //! See either [foo][super::foo] or [bar][super::bar] } @@ -70,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="../../../../../../issue_55364/subone/fn.foo.html"]' 'other foo' -// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../../issue_55364/subtwo/fn.bar.html"]' 'other bar' +// @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' pub mod subfour { pub mod subfive { pub mod subsix { diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs index 5b67817fa4..b932a3d347 100644 --- a/src/test/rustdoc/issue-56822.rs +++ b/src/test/rustdoc/issue-56822.rs @@ -17,7 +17,7 @@ impl<'a, T> MyTrait for Inner<'a, T> { } // @has issue_56822/struct.Parser.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'a> Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'a> Send for \ // Parser<'a>" pub struct Parser<'a> { field: > as MyTrait>::Output diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs index 6acc862773..79b8b70c54 100644 --- a/src/test/rustdoc/issue-60726.rs +++ b/src/test/rustdoc/issue-60726.rs @@ -26,9 +26,9 @@ where {} // @has issue_60726/struct.IntoIter.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl !Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl !Send for \ // IntoIter" -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl !Sync for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl !Sync for \ // IntoIter" pub struct IntoIter{ hello:DynTrait>, diff --git a/src/test/rustdoc/issue-66159.rs b/src/test/rustdoc/issue-66159.rs deleted file mode 100644 index 003d079a47..0000000000 --- a/src/test/rustdoc/issue-66159.rs +++ /dev/null @@ -1,10 +0,0 @@ -// aux-crate:priv:issue_66159_1=issue-66159-1.rs -// compile-flags:-Z unstable-options - -// The issue was an ICE which meant that we never actually generated the docs -// so if we have generated the docs, we're okay. -// Since we don't generate the docs for the auxiliary files, we can't actually -// verify that the struct is linked correctly. - -// @has issue_66159/index.html -//! [issue_66159_1::Something] diff --git a/src/test/rustdoc/issue-72340.rs b/src/test/rustdoc/issue-72340.rs index 6ed3bfbe3e..64044cfe94 100644 --- a/src/test/rustdoc/issue-72340.rs +++ b/src/test/rustdoc/issue-72340.rs @@ -10,7 +10,7 @@ impl Body { } impl Default for Body { - // @has foo/struct.Body.html '//a/@href' '../foo/struct.Body.html#method.empty' + // @has foo/struct.Body.html '//a/@href' 'struct.Body.html#method.empty' /// Returns [`Body::empty()`](Body::empty). fn default() -> Body { diff --git a/src/test/rustdoc/issue-75588.rs b/src/test/rustdoc/issue-75588.rs index 835ed02ac0..aebffeff5f 100644 --- a/src/test/rustdoc/issue-75588.rs +++ b/src/test/rustdoc/issue-75588.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // aux-build:realcore.rs // aux-build:real_gimli.rs diff --git a/src/test/rustdoc/item-hide-threshold.rs b/src/test/rustdoc/item-hide-threshold.rs new file mode 100644 index 0000000000..8986f72636 --- /dev/null +++ b/src/test/rustdoc/item-hide-threshold.rs @@ -0,0 +1,156 @@ +#![allow(unused)] + +// @has 'item_hide_threshold/struct.PubStruct.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +pub struct PubStruct { + pub a: usize, + pub b: usize, +} + +// @has 'item_hide_threshold/struct.BigPubStruct.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +pub struct BigPubStruct { + pub a: usize, + pub b: usize, + pub c: usize, + pub d: usize, + pub e: usize, + pub f: usize, + pub g: usize, + pub h: usize, + pub i: usize, + pub j: usize, + pub k: usize, + pub l: usize, + pub m: usize, +} + +// @has 'item_hide_threshold/union.BigUnion.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +pub union BigUnion { + pub a: usize, + pub b: usize, + pub c: usize, + pub d: usize, + pub e: usize, + pub f: usize, + pub g: usize, + pub h: usize, + pub i: usize, + pub j: usize, + pub k: usize, + pub l: usize, + pub m: usize, +} + +// @has 'item_hide_threshold/union.Union.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +pub union Union { + pub a: usize, + pub b: usize, + pub c: usize, +} + +// @has 'item_hide_threshold/struct.PrivStruct.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @has - '//div[@class="docblock type-decl"]' 'fields omitted' +pub struct PrivStruct { + a: usize, + b: usize, +} + +// @has 'item_hide_threshold/enum.Enum.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +pub enum Enum { + A, B, C, + D { + a: u8, + b: u8 + } +} + +// @has 'item_hide_threshold/enum.LargeEnum.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show variants' +pub enum LargeEnum { + A, B, C, D, E, F(u8), G, H, I, J, K, L, M +} + +// @has 'item_hide_threshold/trait.Trait.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +pub trait Trait { + type A; + #[must_use] + fn foo(); + fn bar(); +} + +// @has 'item_hide_threshold/trait.GinormousTrait.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated items' +pub trait GinormousTrait { + type A; + type B; + type C; + type D; + type E; + type F; + type G; + type H; + type I; + type J; + type K; + type L; + type M; + const N: usize = 1; + #[must_use] + fn foo(); + fn bar(); +} + +// @has 'item_hide_threshold/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' +pub trait HugeTrait { + type A; + const M: usize = 1; + const N: usize = 1; + const O: usize = 1; + const P: usize = 1; + const Q: usize = 1; + const R: usize = 1; + const S: usize = 1; + const T: usize = 1; + const U: usize = 1; + const V: usize = 1; + const W: usize = 1; + const X: usize = 1; + #[must_use] + fn foo(); + fn bar(); +} + +// @has 'item_hide_threshold/trait.BigTrait.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show methods' +pub trait BigTrait { + type A; + #[must_use] + fn foo(); + fn bar(); + fn baz(); + fn quux(); + fn frob(); + fn greeble(); + fn blap(); + fn whoop(); + fn pow(); + fn bang(); + fn oomph(); + fn argh(); + fn wap(); + fn ouch(); +} diff --git a/src/test/rustdoc/link-assoc-const.rs b/src/test/rustdoc/link-assoc-const.rs index f9eb2b722d..75a2531a30 100644 --- a/src/test/rustdoc/link-assoc-const.rs +++ b/src/test/rustdoc/link-assoc-const.rs @@ -1,7 +1,7 @@ #![crate_name = "foo"] -// @has foo/index.html '//a[@href="../foo/foo/constant.FIRSTCONST.html"]' 'foo::FIRSTCONST' -// @has foo/index.html '//a[@href="../foo/struct.Bar.html#associatedconstant.CONST"]' 'Bar::CONST' +// @has foo/index.html '//a[@href="foo/constant.FIRSTCONST.html"]' 'foo::FIRSTCONST' +// @has foo/index.html '//a[@href="struct.Bar.html#associatedconstant.CONST"]' 'Bar::CONST' //! We have here [`foo::FIRSTCONST`] and [`Bar::CONST`]. diff --git a/src/test/rustdoc/playground-arg.rs b/src/test/rustdoc/playground-arg.rs index dbe2297f81..69c8962653 100644 --- a/src/test/rustdoc/playground-arg.rs +++ b/src/test/rustdoc/playground-arg.rs @@ -1,5 +1,4 @@ // compile-flags: --playground-url=https://example.com/ -Z unstable-options -// ignore-tidy-linelength #![crate_name = "foo"] diff --git a/src/test/rustdoc/playground.rs b/src/test/rustdoc/playground.rs index 9971c7b429..877ea1cfba 100644 --- a/src/test/rustdoc/playground.rs +++ b/src/test/rustdoc/playground.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_name = "foo"] #![doc(html_playground_url = "https://www.example.com/")] diff --git a/src/test/rustdoc/prim-title.rs b/src/test/rustdoc/prim-title.rs deleted file mode 100644 index fa3fd512fa..0000000000 --- a/src/test/rustdoc/prim-title.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![crate_name = "foo"] - -// @has foo/primitive.u8.html '//head/title' 'u8 - Rust' -// @!has - '//head/title' 'foo' -#[doc(primitive = "u8")] -/// `u8` docs -mod u8 {} diff --git a/src/test/rustdoc/primitive-link.rs b/src/test/rustdoc/primitive-link.rs index 3041ff7768..dd455e45bf 100644 --- a/src/test/rustdoc/primitive-link.rs +++ b/src/test/rustdoc/primitive-link.rs @@ -1,6 +1,5 @@ #![crate_name = "foo"] -// ignore-tidy-linelength // @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32' // @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64' diff --git a/src/test/rustdoc/proc-macro.rs b/src/test/rustdoc/proc-macro.rs index 82196e413e..f6d1f2cf91 100644 --- a/src/test/rustdoc/proc-macro.rs +++ b/src/test/rustdoc/proc-macro.rs @@ -61,12 +61,12 @@ pub fn some_derive(_item: TokenStream) -> TokenStream { // @has some_macros/foo/index.html mod foo { // @has - '//code' 'pub use some_proc_macro;' - // @has - '//a/@href' '../../some_macros/macro.some_proc_macro.html' + // @has - '//a/@href' '../macro.some_proc_macro.html' pub use some_proc_macro; // @has - '//code' 'pub use some_proc_attr;' - // @has - '//a/@href' '../../some_macros/attr.some_proc_attr.html' + // @has - '//a/@href' '../attr.some_proc_attr.html' pub use some_proc_attr; // @has - '//code' 'pub use some_derive;' - // @has - '//a/@href' '../../some_macros/derive.SomeDerive.html' + // @has - '//a/@href' '../derive.SomeDerive.html' pub use some_derive; } diff --git a/src/test/rustdoc/raw-ident-eliminate-r-hashtag.rs b/src/test/rustdoc/raw-ident-eliminate-r-hashtag.rs index f895a4c210..ad19036126 100644 --- a/src/test/rustdoc/raw-ident-eliminate-r-hashtag.rs +++ b/src/test/rustdoc/raw-ident-eliminate-r-hashtag.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_type="lib"] pub mod internal { @@ -10,13 +8,13 @@ pub mod internal { /// /// [name]: mod /// [other name]: crate::internal::mod - // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//*a[@href="../../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'name' - // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//*a[@href="../../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'other name' + // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//*a[@href="struct.mod.html"]' 'name' + // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//*a[@href="struct.mod.html"]' 'other name' pub struct B; } /// See [name]. /// /// [name]: internal::mod -// @has 'raw_ident_eliminate_r_hashtag/struct.A.html' '//*a[@href="../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'name' +// @has 'raw_ident_eliminate_r_hashtag/struct.A.html' '//*a[@href="internal/struct.mod.html"]' 'name' pub struct A; diff --git a/src/test/rustdoc/reexport-stability-tags-deprecated-and-portability.rs b/src/test/rustdoc/reexport-stability-tags-deprecated-and-portability.rs new file mode 100644 index 0000000000..a79d05904e --- /dev/null +++ b/src/test/rustdoc/reexport-stability-tags-deprecated-and-portability.rs @@ -0,0 +1,48 @@ +#![crate_name = "foo"] +#![feature(doc_cfg)] + +pub mod tag { + #[deprecated(since = "0.1.8", note = "Use bar() instead")] + pub trait Deprecated {} + + #[doc(cfg(feature = "sync"))] + pub trait Portability {} + + #[deprecated(since = "0.1.8", note = "Use bar() instead")] + #[doc(cfg(feature = "sync"))] + pub trait Both {} + + pub trait None {} +} + +// @has foo/mod1/index.html +pub mod mod1 { + // @has - '//code' 'pub use tag::Deprecated;' + // @has - '//span' 'Deprecated' + // @!has - '//span' 'sync' + pub use tag::Deprecated; +} + +// @has foo/mod2/index.html +pub mod mod2 { + // @has - '//code' 'pub use tag::Portability;' + // @!has - '//span' 'Deprecated' + // @has - '//span' 'sync' + pub use tag::Portability; +} + +// @has foo/mod3/index.html +pub mod mod3 { + // @has - '//code' 'pub use tag::Both;' + // @has - '//span' 'Deprecated' + // @has - '//span' 'sync' + pub use tag::Both; +} + +// @has foo/mod4/index.html +pub mod mod4 { + // @has - '//code' 'pub use tag::None;' + // @!has - '//span' 'Deprecated' + // @!has - '//span' 'sync' + pub use tag::None; +} diff --git a/src/test/rustdoc/reexport-stability-tags-unstable-and-portability.rs b/src/test/rustdoc/reexport-stability-tags-unstable-and-portability.rs new file mode 100644 index 0000000000..ff8a910f59 --- /dev/null +++ b/src/test/rustdoc/reexport-stability-tags-unstable-and-portability.rs @@ -0,0 +1,61 @@ +#![crate_name = "foo"] +#![feature(doc_cfg)] +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod tag { + #[unstable(feature = "humans", issue = "none")] + pub trait Unstable {} + + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(cfg(feature = "sync"))] + pub trait Portability {} + + #[unstable(feature = "humans", issue = "none")] + #[doc(cfg(feature = "sync"))] + pub trait Both {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub trait None {} +} + +// @has foo/mod1/index.html +#[stable(feature = "rust1", since = "1.0.0")] +pub mod mod1 { + // @has - '//code' 'pub use tag::Unstable;' + // @has - '//span' 'Experimental' + // @!has - '//span' 'sync' + #[stable(feature = "rust1", since = "1.0.0")] + pub use tag::Unstable; +} + +// @has foo/mod2/index.html +#[stable(feature = "rust1", since = "1.0.0")] +pub mod mod2 { + // @has - '//code' 'pub use tag::Portability;' + // @!has - '//span' 'Experimental' + // @has - '//span' 'sync' + #[stable(feature = "rust1", since = "1.0.0")] + pub use tag::Portability; +} + +// @has foo/mod3/index.html +#[stable(feature = "rust1", since = "1.0.0")] +pub mod mod3 { + // @has - '//code' 'pub use tag::Both;' + // @has - '//span' 'Experimental' + // @has - '//span' 'sync' + #[stable(feature = "rust1", since = "1.0.0")] + pub use tag::Both; +} + +// @has foo/mod4/index.html +#[stable(feature = "rust1", since = "1.0.0")] +pub mod mod4 { + // @has - '//code' 'pub use tag::None;' + // @!has - '//span' 'Experimental' + // @!has - '//span' 'sync' + #[stable(feature = "rust1", since = "1.0.0")] + pub use tag::None; +} diff --git a/src/test/rustdoc/smart-punct.rs b/src/test/rustdoc/smart-punct.rs index a1ca269955..5319892c99 100644 --- a/src/test/rustdoc/smart-punct.rs +++ b/src/test/rustdoc/smart-punct.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_name = "foo"] //! This is the "start" of the 'document'! How'd you know that "it's" the start? diff --git a/src/test/rustdoc/src-links-external.rs b/src/test/rustdoc/src-links-external.rs index 0469e4ad62..8012e44221 100644 --- a/src/test/rustdoc/src-links-external.rs +++ b/src/test/rustdoc/src-links-external.rs @@ -1,7 +1,6 @@ // aux-build:src-links-external.rs // build-aux-docs // ignore-cross-compile -// ignore-tidy-linelength #![crate_name = "foo"] diff --git a/src/test/rustdoc/struct-arg-pattern.rs b/src/test/rustdoc/struct-arg-pattern.rs new file mode 100644 index 0000000000..3c0369e3d3 --- /dev/null +++ b/src/test/rustdoc/struct-arg-pattern.rs @@ -0,0 +1,10 @@ +#![crate_name = "foo"] + +struct BodyId { + hir_id: usize, +} + +// @has 'foo/fn.body_owner.html' '//*[@class="rust fn"]' 'pub fn body_owner(_: BodyId)' +pub fn body_owner(BodyId { hir_id }: BodyId) { + // ... +} diff --git a/src/test/rustdoc/struct-field.rs b/src/test/rustdoc/struct-field.rs index 532e29bc69..998683bdde 100644 --- a/src/test/rustdoc/struct-field.rs +++ b/src/test/rustdoc/struct-field.rs @@ -1,10 +1,9 @@ #![crate_name = "foo"] -// ignore-tidy-linelength -// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/struct.Foo.html#structfield.bar"]' 'Foo::bar' -// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/union.Bar.html#structfield.foo"]' 'Bar::foo' -// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/enum.Uniooon.html#variant.X"]' 'Uniooon::X' +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="struct.Foo.html#structfield.bar"]' 'Foo::bar' +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="union.Bar.html#structfield.foo"]' 'Bar::foo' +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="enum.Uniooon.html#variant.X"]' 'Uniooon::X' //! Test with [Foo::bar], [Bar::foo], [Uniooon::X] diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs index 38de5316b6..0dd3a3f7a8 100644 --- a/src/test/rustdoc/synthetic_auto/basic.rs +++ b/src/test/rustdoc/synthetic_auto/basic.rs @@ -1,8 +1,8 @@ // @has basic/struct.Foo.html // @has - '//code' 'impl Send for Foo where T: Send' // @has - '//code' 'impl Sync for Foo where T: Sync' -// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0 -// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 5 +// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 pub struct Foo { field: T, } diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index 80a717718c..d951a20e2d 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -20,7 +20,7 @@ mod foo { } // @has complex/struct.NotOuter.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'a, T, K: \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'a, T, K: \ // ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, >::MyItem: Copy, 'a: 'static" diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index 6d0a68f9b0..05c88f1082 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -9,10 +9,10 @@ where {} // @has lifetimes/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Send \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Send \ // for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Sync \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Sync \ // for Foo<'c, K> where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index d20b4744af..88ddd57349 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -1,12 +1,12 @@ // @has manual/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' 'impl Sync for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' 'impl Sync for \ // Foo where T: Sync' // -// @has - '//*[@id="trait-implementations-list"]/*[@class="impl"]//code' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' \ // 'impl Send for Foo' // -// @count - '//*[@id="trait-implementations-list"]/*[@class="impl"]' 1 -// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 4 +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4 pub struct Foo { field: T, } diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs index 30713849da..53801542c9 100644 --- a/src/test/rustdoc/synthetic_auto/negative.rs +++ b/src/test/rustdoc/synthetic_auto/negative.rs @@ -3,10 +3,10 @@ pub struct Inner { } // @has negative/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl !Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl !Send for \ // Outer" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl \ // !Sync for Outer" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index e710ce1c2e..d4d93a87ff 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -9,10 +9,10 @@ where } // @has nested/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' 'impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' 'impl Send for \ // Foo where T: Copy' // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' \ // 'impl Sync for Foo where T: Sync' pub struct Foo { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index cf173111ec..3a23dc2cf9 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -9,7 +9,7 @@ where } // @has no_redundancy/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl Send for \ // Outer where T: Copy + Send" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index 5346521f8d..060491e3cf 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -23,10 +23,10 @@ where } // @has project/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Send \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Send \ // for Foo<'c, K> where K: MyTrait, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Sync \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Sync \ // for Foo<'c, K> where K: MyTrait, ::MyItem: OtherTrait, 'c: 'static," pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs index 905aa20918..ecdbdf41b2 100644 --- a/src/test/rustdoc/synthetic_auto/self-referential.rs +++ b/src/test/rustdoc/synthetic_auto/self-referential.rs @@ -23,7 +23,7 @@ impl Pattern for Wrapper { // @has self_referential/struct.WriteAndThen.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl Send for \ // WriteAndThen where ::Value: Send" pub struct WriteAndThen(pub P1::Value,pub > as Pattern>::Value) where P1: Pattern; diff --git a/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs index 59493744b6..a10e694c1b 100644 --- a/src/test/rustdoc/synthetic_auto/static-region.rs +++ b/src/test/rustdoc/synthetic_auto/static-region.rs @@ -3,7 +3,7 @@ pub trait OwnedTrait<'a> { } // @has static_region/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl Send for \ // Owned where >::Reader: Send" pub struct Owned where T: OwnedTrait<'static> { marker: >::Reader, diff --git a/src/test/rustdoc/tab_title.rs b/src/test/rustdoc/tab_title.rs new file mode 100644 index 0000000000..7dce6092de --- /dev/null +++ b/src/test/rustdoc/tab_title.rs @@ -0,0 +1,44 @@ +#![crate_name = "foo"] +#![feature(doc_keyword)] + +// tests for the html element + +// @has foo/index.html '//head/title' 'foo - Rust' + +// @has foo/fn.widget_count.html '//head/title' 'widget_count in foo - Rust' +/// blah +pub fn widget_count() {} + +// @has foo/struct.Widget.html '//head/title' 'Widget in foo - Rust' +pub struct Widget; + +// @has foo/constant.ANSWER.html '//head/title' 'ANSWER in foo - Rust' +pub const ANSWER: u8 = 42; + +// @has foo/blah/index.html '//head/title' 'foo::blah - Rust' +pub mod blah { + // @has foo/blah/struct.Widget.html '//head/title' 'Widget in foo::blah - Rust' + pub struct Widget; + + // @has foo/blah/trait.Awesome.html '//head/title' 'Awesome in foo::blah - Rust' + pub trait Awesome {} + + // @has foo/blah/fn.make_widget.html '//head/title' 'make_widget in foo::blah - Rust' + pub fn make_widget() {} + + // @has foo/macro.cool_macro.html '//head/title' 'cool_macro in foo - Rust' + #[macro_export] + macro_rules! cool_macro { + ($t:tt) => { $t } + } +} + +// @has foo/keyword.continue.html '//head/title' 'continue - Rust' +#[doc(keyword = "continue")] +mod continue_keyword {} + +// @has foo/primitive.u8.html '//head/title' 'u8 - Rust' +// @!has - '//head/title' 'foo' +#[doc(primitive = "u8")] +/// `u8` docs +mod u8 {} diff --git a/src/test/rustdoc/trait-attributes.rs b/src/test/rustdoc/trait-attributes.rs index a6ee046ede..2bb24a8219 100644 --- a/src/test/rustdoc/trait-attributes.rs +++ b/src/test/rustdoc/trait-attributes.rs @@ -1,9 +1,8 @@ #![crate_name = "foo"] -// ignore-tidy-linelength pub trait Foo { - // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//span[@class="docblock attributes"]' '#[must_use]' + // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]' #[must_use] fn foo(); } @@ -12,11 +11,11 @@ pub trait Foo { pub struct Bar; impl Bar { - // @has foo/struct.Bar.html '//h4[@id="method.bar"]//span[@class="docblock attributes"]' '#[must_use]' + // @has foo/struct.Bar.html '//h4[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]' #[must_use] pub fn bar() {} - // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//span[@class="docblock attributes"]' '#[must_use]' + // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]' #[must_use] pub fn bar2() {} } diff --git a/src/test/rustdoc/trait-impl-items-links-and-anchors.rs b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs new file mode 100644 index 0000000000..c6a9313e82 --- /dev/null +++ b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs @@ -0,0 +1,65 @@ +pub trait MyTrait { + type Assoc; + const VALUE: u32; + fn trait_function(&self); + fn defaulted(&self) {} + fn defaulted_override(&self) {} +} + + +impl MyTrait for String { + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-1"]//a[@class="type"]/@href' #associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-1"]//a[@class="anchor"]/@href' #associatedtype.Assoc-1 + type Assoc = (); + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-1"]//a[@class="constant"]/@href' #associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-1"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-1 + const VALUE: u32 = 5; + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@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 '//h4[@id="method.defaulted_override-1"]//a[@class="fnname"]/@href' #method.defaulted_override + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-1"]//a[@class="anchor"]/@href' #method.defaulted_override-1 + fn defaulted_override(&self) {} +} + +impl MyTrait for Vec<u8> { + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-2"]//a[@class="type"]/@href' #associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-2"]//a[@class="anchor"]/@href' #associatedtype.Assoc-2 + type Assoc = (); + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-2"]//a[@class="constant"]/@href' #associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-2"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-2 + const VALUE: u32 = 5; + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-1"]//a[@class="anchor"]/@href' #method.trait_function-1 + fn trait_function(&self) {} + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-2"]//a[@class="fnname"]/@href' #method.defaulted_override + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-2"]//a[@class="anchor"]/@href' #method.defaulted_override-2 + fn defaulted_override(&self) {} +} + +impl MyTrait for MyStruct { + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-3"]//a[@class="type"]/@href' #associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc + type Assoc = bool; + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-3"]//a[@class="constant"]/@href' #associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE + const VALUE: u32 = 20; + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-2"]//a[@class="fnname"]/@href' #tymethod.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-2"]//a[@class="anchor"]/@href' #method.trait_function-2 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' trait.MyTrait.html#tymethod.trait_function + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@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 '//h4[@id="method.defaulted_override-3"]//a[@class="fnname"]/@href' #method.defaulted_override + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-3"]//a[@class="anchor"]/@href' #method.defaulted_override-3 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted_override"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted_override + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override + fn defaulted_override(&self) {} + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted"]//a[@class="anchor"]/@href' #method.defaulted +} + +pub struct MyStruct; diff --git a/src/test/rustdoc/trait-self-link.rs b/src/test/rustdoc/trait-self-link.rs index bac28b4401..e311dadff0 100644 --- a/src/test/rustdoc/trait-self-link.rs +++ b/src/test/rustdoc/trait-self-link.rs @@ -1,4 +1,4 @@ -// @has trait_self_link/trait.Foo.html //a/@href ../trait_self_link/trait.Foo.html +// @has trait_self_link/trait.Foo.html //a/@href trait.Foo.html pub trait Foo {} pub struct Bar; diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index 8b1a3887f1..51cea4f6ba 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -33,7 +33,7 @@ macro_rules! fake_lint_pass { if !cx.sess().contains_name(attrs, $attr) { cx.lint(CRATE_NOT_OKAY, |lint| { let msg = format!("crate is not marked with #![{}]", $attr); - lint.build(&msg).set_span(krate.item.span).emit() + lint.build(&msg).set_span(krate.item.inner).emit() }); } )* diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index c9269d2b9b..ef5353e6d8 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -31,7 +31,7 @@ impl<'tcx> LateLintPass<'tcx> for Pass { if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) { cx.lint(CRATE_NOT_OKAY, |lint| { lint.build("crate is not marked with #![crate_okay]") - .set_span(krate.item.span) + .set_span(krate.item.inner) .emit() }); } diff --git a/src/test/ui/anon-params/anon-params-edition-hygiene.rs b/src/test/ui/anon-params/anon-params-edition-hygiene.rs index 14e11c5696..6936205f8b 100644 --- a/src/test/ui/anon-params/anon-params-edition-hygiene.rs +++ b/src/test/ui/anon-params/anon-params-edition-hygiene.rs @@ -2,6 +2,9 @@ // edition:2018 // aux-build:anon-params-edition-hygiene.rs +// This warning is still surfaced +#![allow(anonymous_parameters)] + #[macro_use] extern crate anon_params_edition_hygiene; diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs index d8a9ae6ca2..5a6283e9f1 100644 --- a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs +++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs @@ -2,8 +2,6 @@ // run-pass -#![feature(const_fn)] - #[derive(PartialEq, Debug, Clone)] struct N(u8); diff --git a/src/test/ui/asm/bad-reg.rs b/src/test/ui/asm/bad-reg.rs index 016ea9329c..da302b2487 100644 --- a/src/test/ui/asm/bad-reg.rs +++ b/src/test/ui/asm/bad-reg.rs @@ -37,6 +37,8 @@ fn main() { //~^ 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 // Explicit register conflicts // (except in/lateout which don't conflict) diff --git a/src/test/ui/asm/bad-reg.stderr b/src/test/ui/asm/bad-reg.stderr index c6b7d310df..2bfb4854c3 100644 --- a/src/test/ui/asm/bad-reg.stderr +++ b/src/test/ui/asm/bad-reg.stderr @@ -94,8 +94,14 @@ error: invalid register `k0`: the k0 AVX mask register cannot be used as an oper 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:40:18 + | +LL | asm!("", in("ah") foo); + | ^^^^^^^^^^^^ + error: register `al` conflicts with register `ax` - --> $DIR/bad-reg.rs:44:33 + --> $DIR/bad-reg.rs:46:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -103,7 +109,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `ax` error: register `ax` conflicts with register `ax` - --> $DIR/bad-reg.rs:46:33 + --> $DIR/bad-reg.rs:48:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `ax` @@ -111,13 +117,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `ax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:49:34 + --> $DIR/bad-reg.rs:51:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -125,7 +131,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:51:34 + --> $DIR/bad-reg.rs:53:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -133,10 +139,10 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:51:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors diff --git a/src/test/ui/asm/const.rs b/src/test/ui/asm/const.rs index e08da24f44..0f6a7cd447 100644 --- a/src/test/ui/asm/const.rs +++ b/src/test/ui/asm/const.rs @@ -1,41 +1,21 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // only-x86_64 // run-pass #![feature(asm)] -use std::mem::size_of; - -trait Proj { - const C: usize; -} -impl Proj for i8 { - const C: usize = 8; -} -impl Proj for i16 { - const C: usize = 16; +fn const_generic<const X: usize>() -> usize { + unsafe { + let a: usize; + asm!("mov {}, {}", out(reg) a, const X); + a + } } const fn constfn(x: usize) -> usize { x } -fn generic<T: Proj>() { - unsafe { - let a: usize; - asm!("mov {}, {}", out(reg) a, const size_of::<T>()); - assert_eq!(a, size_of::<T>()); - - let b: usize; - asm!("mov {}, {}", out(reg) b, const size_of::<T>() + constfn(5)); - assert_eq!(b, size_of::<T>() + 5); - - let c: usize; - asm!("mov {}, {}", out(reg) c, const T::C); - assert_eq!(c, T::C); - } -} - fn main() { unsafe { let a: usize; @@ -51,6 +31,6 @@ fn main() { assert_eq!(c, 10); } - generic::<i8>(); - generic::<i16>(); + let d = const_generic::<5>(); + assert_eq!(d, 5); } diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr index b1b61f0211..bcae1d565f 100644 --- a/src/test/ui/asm/inline-syntax.arm.stderr +++ b/src/test/ui/asm/inline-syntax.arm.stderr @@ -1,14 +1,74 @@ -error: att syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:22:15 +error: unknown directive + --> $DIR/inline-syntax.rs:25:15 + | +LL | asm!(".intel_syntax noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> <inline asm>:1:2 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:28:15 + | +LL | asm!(".intel_syntax aaa noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> <inline asm>:1:2 + | +LL | .intel_syntax aaa noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:31:15 | LL | asm!(".att_syntax noprefix", "nop"); - | ^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + | ^ + | +note: instantiated into assembly here + --> <inline asm>:1:2 + | +LL | .att_syntax noprefix + | ^ -error: att syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:25:15 +error: unknown directive + --> $DIR/inline-syntax.rs:34:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + | ^ + | +note: instantiated into assembly here + --> <inline asm>:1:2 + | +LL | .att_syntax bbb noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:37:15 + | +LL | asm!(".intel_syntax noprefix; nop"); + | ^ + | +note: instantiated into assembly here + --> <inline asm>:1:2 + | +LL | .intel_syntax noprefix; nop + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:43:13 + | +LL | .intel_syntax noprefix + | ^ + | +note: instantiated into assembly here + --> <inline asm>:2:13 + | +LL | .intel_syntax noprefix + | ^ -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs index 9e9c7badfc..13ded19cfe 100644 --- a/src/test/ui/asm/inline-syntax.rs +++ b/src/test/ui/asm/inline-syntax.rs @@ -1,9 +1,16 @@ +// needs-llvm-components: arm // revisions: x86_64 arm //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//[x86_64] check-pass +//[x86_64_allowed] compile-flags: --target x86_64-unknown-linux-gnu +//[x86_64_allowed] check-pass //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf +//[arm] build-fail #![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] #![no_core] +#![cfg_attr(x86_64_allowed, allow(bad_asm_style))] #[rustc_builtin_macro] macro_rules! asm { @@ -13,26 +20,30 @@ macro_rules! asm { #[lang = "sized"] trait Sized {} -fn main() { +pub fn main() { unsafe { asm!(".intel_syntax noprefix", "nop"); - //[x86_64]~^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^ WARN avoid using `.intel_syntax` + //[arm]~^^ ERROR unknown directive asm!(".intel_syntax aaa noprefix", "nop"); - //[x86_64]~^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^ WARN avoid using `.intel_syntax` + //[arm]~^^ ERROR unknown directive asm!(".att_syntax noprefix", "nop"); - //[x86_64]~^ ERROR using the .att_syntax directive may cause issues - //[arm]~^^ att syntax is the default syntax on this target + //[x86_64]~^ WARN avoid using `.att_syntax` + //[arm]~^^ ERROR unknown directive asm!(".att_syntax bbb noprefix", "nop"); - //[x86_64]~^ ERROR using the .att_syntax directive may cause issues - //[arm]~^^ att syntax is the default syntax on this target + //[x86_64]~^ WARN avoid using `.att_syntax` + //[arm]~^^ ERROR unknown directive asm!(".intel_syntax noprefix; nop"); - //[x86_64]~^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^ WARN avoid using `.intel_syntax` + //[arm]~^^ ERROR unknown directive asm!( r" .intel_syntax noprefix nop" ); - //[x86_64]~^^^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^^^ WARN avoid using `.intel_syntax` + //[arm]~^^^^ ERROR unknown directive } } diff --git a/src/test/ui/asm/inline-syntax.x86_64.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr index c54c2742a5..02b29b0901 100644 --- a/src/test/ui/asm/inline-syntax.x86_64.stderr +++ b/src/test/ui/asm/inline-syntax.x86_64.stderr @@ -1,50 +1,40 @@ -error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:18:15 +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:25:15 | LL | asm!(".intel_syntax noprefix", "nop"); - | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(bad_asm_style)]` on by default -error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:20:15 +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:28:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: using the .att_syntax directive may cause issues, use the att_syntax option instead - --> $DIR/inline-syntax.rs:22:15 +warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead + --> $DIR/inline-syntax.rs:31:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ - | -help: remove the assembler directive and replace it with options(att_syntax) - | -LL | asm!("", "nop", options(att_syntax)); - | -- ^^^^^^^^^^^^^^^^^^^^^ -error: using the .att_syntax directive may cause issues, use the att_syntax option instead - --> $DIR/inline-syntax.rs:25:15 +warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead + --> $DIR/inline-syntax.rs:34:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: remove the assembler directive and replace it with options(att_syntax) - | -LL | asm!("", "nop", options(att_syntax)); - | -- ^^^^^^^^^^^^^^^^^^^^^ -error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:28:15 +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:37:15 | LL | asm!(".intel_syntax noprefix; nop"); - | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + | ^^^^^^^^^^^^^^^^^^^^^^ -error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:33:14 +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:43:13 | -LL | .intel_syntax noprefix - | ______________^ -LL | | nop" - | |_ help: remove this assembler directive +LL | .intel_syntax noprefix + | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +warning: 6 warnings emitted diff --git a/src/test/ui/asm/naked-invalid-attr.rs b/src/test/ui/asm/naked-invalid-attr.rs index cdb6c17454..2576d1124c 100644 --- a/src/test/ui/asm/naked-invalid-attr.rs +++ b/src/test/ui/asm/naked-invalid-attr.rs @@ -1,6 +1,6 @@ // Checks that #[naked] attribute can be placed on function definitions only. // -// ignore-wasm32 asm unsupported +// needs-asm-support #![feature(asm)] #![feature(naked_functions)] #![naked] //~ ERROR should be applied to a function definition diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/parse-error.rs index 538a3fde8f..f2e9d9ca08 100644 --- a/src/test/ui/asm/parse-error.rs +++ b/src/test/ui/asm/parse-error.rs @@ -36,17 +36,23 @@ fn main() { //~^ ERROR expected one of asm!("{}", options(), const foo); //~^ ERROR arguments are not allowed after options + //~^^ ERROR attempt to use a non-constant value in a constant asm!("{a}", a = const foo, a = const bar); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used + //~^^^ ERROR attempt to use a non-constant value in a constant + //~^^^^ ERROR attempt to use a non-constant value in a constant asm!("", a = in("eax") foo); //~^ ERROR explicit register arguments cannot have names asm!("{a}", in("eax") foo, a = const bar); //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant asm!("{a}", in("eax") foo, a = const bar); //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant asm!("{1}", in("eax") foo, const bar); //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant asm!("", options(), ""); //~^ ERROR expected one of asm!("{}", in(reg) foo, "{}", out(reg) foo); diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr index dfbfc0abe3..4ab9d86948 100644 --- a/src/test/ui/asm/parse-error.stderr +++ b/src/test/ui/asm/parse-error.stderr @@ -91,7 +91,7 @@ LL | asm!("{}", options(), const foo); | previous options error: duplicate argument named `a` - --> $DIR/parse-error.rs:39:36 + --> $DIR/parse-error.rs:40:36 | LL | asm!("{a}", a = const foo, a = const bar); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -99,7 +99,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | previously here error: argument never used - --> $DIR/parse-error.rs:39:36 + --> $DIR/parse-error.rs:40:36 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^^^^^^^^^^^ argument never used @@ -107,13 +107,13 @@ LL | asm!("{a}", a = const foo, a = const bar); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: explicit register arguments cannot have names - --> $DIR/parse-error.rs:42:18 + --> $DIR/parse-error.rs:45:18 | LL | asm!("", a = in("eax") foo); | ^^^^^^^^^^^^^^^^^ error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:44:36 + --> $DIR/parse-error.rs:47:36 | LL | asm!("{a}", in("eax") foo, a = const bar); | ------------- ^^^^^^^^^^^^^ named argument @@ -121,7 +121,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | explicit register argument error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:46:36 + --> $DIR/parse-error.rs:50:36 | LL | asm!("{a}", in("eax") foo, a = const bar); | ------------- ^^^^^^^^^^^^^ named argument @@ -129,7 +129,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | explicit register argument error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/parse-error.rs:48:36 + --> $DIR/parse-error.rs:53:36 | LL | asm!("{1}", in("eax") foo, const bar); | ------------- ^^^^^^^^^ positional argument @@ -137,19 +137,19 @@ LL | asm!("{1}", in("eax") foo, const bar); | explicit register argument error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` - --> $DIR/parse-error.rs:50:29 + --> $DIR/parse-error.rs:56:29 | LL | asm!("", options(), ""); | ^^ expected one of 8 possible tokens error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:52:33 + --> $DIR/parse-error.rs:58:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); | ^^^^ expected one of 8 possible tokens error: asm template must be a string literal - --> $DIR/parse-error.rs:54:14 + --> $DIR/parse-error.rs:60:14 | LL | asm!(format!("{{{}}}", 0), in(reg) foo); | ^^^^^^^^^^^^^^^^^^^^ @@ -157,12 +157,67 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:56:21 + --> $DIR/parse-error.rs:62:21 | LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); | ^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 25 previous errors +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:37:37 + | +LL | let mut foo = 0; + | ---------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{}", options(), const foo); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:40:31 + | +LL | let mut foo = 0; + | ---------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:40:46 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:47:46 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{a}", in("eax") foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:50:46 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{a}", in("eax") foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:53:42 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{1}", in("eax") foo, const bar); + | ^^^ non-constant value + +error: aborting due to 31 previous errors +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/srcloc.rs index 1477e3dd56..ed8cefc58b 100644 --- a/src/test/ui/asm/srcloc.rs +++ b/src/test/ui/asm/srcloc.rs @@ -1,7 +1,7 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // only-x86_64 // build-fail - +// compile-flags: -Ccodegen-units=1 #![feature(asm)] // Checks that inline asm errors are mapped to the correct line in the source code. diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs index 9931697e41..634ef010e6 100644 --- a/src/test/ui/asm/sym.rs +++ b/src/test/ui/asm/sym.rs @@ -1,4 +1,4 @@ -// no-system-llvm +// min-llvm-version: 10.0.1 // only-x86_64 // only-linux // run-pass @@ -76,5 +76,5 @@ fn main() { std::thread::spawn(|| { assert_eq!(static_addr!(S1), &S1 as *const u32); assert_eq!(static_tls_addr!(S2), &S2 as *const u32); - }); + }).join().unwrap(); } diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs index 7880382c3b..57a91aaa93 100644 --- a/src/test/ui/asm/type-check-1.rs +++ b/src/test/ui/asm/type-check-1.rs @@ -21,5 +21,23 @@ fn main() { //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time asm!("{}", inout(reg) v[..]); //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time + + // Constants must be... constant + + let x = 0; + const fn const_foo(x: i32) -> i32 { + x + } + const fn const_bar<T>(x: T) -> T { + x + } + asm!("{}", const x); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_foo(0)); + asm!("{}", const const_foo(x)); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_bar(0)); + asm!("{}", const const_bar(x)); + //~^ ERROR attempt to use a non-constant value in a constant } } diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr index 556e83fdb0..eefab6d397 100644 --- a/src/test/ui/asm/type-check-1.stderr +++ b/src/test/ui/asm/type-check-1.stderr @@ -1,3 +1,30 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/type-check-1.rs:34:26 + | +LL | let x = 0; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | asm!("{}", const x); + | ^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/type-check-1.rs:37:36 + | +LL | let x = 0; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | asm!("{}", const const_foo(x)); + | ^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/type-check-1.rs:40:36 + | +LL | let x = 0; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | asm!("{}", const const_bar(x)); + | ^ non-constant value + error: invalid asm output --> $DIR/type-check-1.rs:10:29 | @@ -37,6 +64,7 @@ LL | asm!("{}", inout(reg) v[..]); = help: the trait `Sized` is not implemented for `[u64]` = note: all inline asm arguments must have a statically known size -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0435. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/asm/type-check-2.rs b/src/test/ui/asm/type-check-2.rs index 01c8b4eb65..0677167ccf 100644 --- a/src/test/ui/asm/type-check-2.rs +++ b/src/test/ui/asm/type-check-2.rs @@ -28,31 +28,19 @@ fn main() { // Const operands must be integer or floats, and must be constants. - let x = 0; - const C: i32 = 0; - const fn const_foo(x: i32) -> i32 { - x - } - const fn const_bar<T>(x: T) -> T { - x - } + asm!("{}", const 0); asm!("{}", const 0i32); asm!("{}", const 0f32); asm!("{}", const 0 as *mut u8); //~^ ERROR asm `const` arguments must be integer or floating-point values - asm!("{}", const &0); - //~^ ERROR asm `const` arguments must be integer or floating-point values - asm!("{}", const x); - //~^ ERROR argument 1 is required to be a constant - asm!("{}", const const_foo(0)); - asm!("{}", const const_foo(x)); - //~^ ERROR argument 1 is required to be a constant - asm!("{}", const const_bar(0)); - asm!("{}", const const_bar(x)); - //~^ ERROR argument 1 is required to be a constant + + // This currently causes an ICE: https://github.com/rust-lang/rust/issues/81857 + // asm!("{}", const &0); + // ERROR asm `const` arguments must be integer or floating-point values // Sym operands must point to a function or static + const C: i32 = 0; static S: i32 = 0; asm!("{}", sym S); asm!("{}", sym main); diff --git a/src/test/ui/asm/type-check-2.stderr b/src/test/ui/asm/type-check-2.stderr index a520bea8f1..830ca7b555 100644 --- a/src/test/ui/asm/type-check-2.stderr +++ b/src/test/ui/asm/type-check-2.stderr @@ -1,25 +1,19 @@ error: asm `const` arguments must be integer or floating-point values - --> $DIR/type-check-2.rs:41:26 + --> $DIR/type-check-2.rs:34:20 | LL | asm!("{}", const 0 as *mut u8); - | ^^^^^^^^^^^^ - -error: asm `const` arguments must be integer or floating-point values - --> $DIR/type-check-2.rs:43:26 - | -LL | asm!("{}", const &0); - | ^^ + | ^^^^^^^^^^^^^^^^^^ error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:66:32 + --> $DIR/type-check-2.rs:54:32 | LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `[closure@$DIR/type-check-2.rs:78:28: 78:38]` for inline assembly - --> $DIR/type-check-2.rs:78:28 +error: cannot use value of type `[closure@$DIR/type-check-2.rs:66:28: 66:38]` for inline assembly + --> $DIR/type-check-2.rs:66:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -27,7 +21,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec<i32>` for inline assembly - --> $DIR/type-check-2.rs:80:28 + --> $DIR/type-check-2.rs:68:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -36,7 +30,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:82:28 + --> $DIR/type-check-2.rs:70:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -44,7 +38,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:84:28 + --> $DIR/type-check-2.rs:72:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -52,7 +46,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:92:31 + --> $DIR/type-check-2.rs:80:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -60,7 +54,7 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:95:31 + --> $DIR/type-check-2.rs:83:31 | LL | asm!("{}", inout(reg) r); | ^ @@ -68,35 +62,17 @@ LL | asm!("{}", inout(reg) r); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: asm `sym` operand must point to a fn or static - --> $DIR/type-check-2.rs:59:24 + --> $DIR/type-check-2.rs:47:24 | LL | asm!("{}", sym C); | ^ error: asm `sym` operand must point to a fn or static - --> $DIR/type-check-2.rs:61:24 + --> $DIR/type-check-2.rs:49:24 | LL | asm!("{}", sym x); | ^ -error: argument 1 is required to be a constant - --> $DIR/type-check-2.rs:45:9 - | -LL | asm!("{}", const x); - | ^^^^^^^^^^^^^^^^^^^^ - -error: argument 1 is required to be a constant - --> $DIR/type-check-2.rs:48:9 - | -LL | asm!("{}", const const_foo(x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: argument 1 is required to be a constant - --> $DIR/type-check-2.rs:51:9 - | -LL | asm!("{}", const const_bar(x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/type-check-2.rs:13:28 | @@ -127,7 +103,7 @@ LL | let v: Vec<u64> = vec![0, 1, 2]; LL | asm!("{}", inout(reg) v[0]); | ^ cannot borrow as mutable -error: aborting due to 18 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0381, E0596. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/assign-imm-local-twice.rs b/src/test/ui/assign-imm-local-twice.rs index c1c9bf6281..b50f6ab5de 100644 --- a/src/test/ui/assign-imm-local-twice.rs +++ b/src/test/ui/assign-imm-local-twice.rs @@ -1,6 +1,6 @@ fn test() { let v: isize; - //~^ HELP make this binding mutable + //~^ HELP consider making this binding mutable //~| SUGGESTION mut v v = 1; //~ NOTE first assignment println!("v={}", v); diff --git a/src/test/ui/assign-imm-local-twice.stderr b/src/test/ui/assign-imm-local-twice.stderr index df0f4c4d80..bba5d8dffe 100644 --- a/src/test/ui/assign-imm-local-twice.stderr +++ b/src/test/ui/assign-imm-local-twice.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `v` --> $DIR/assign-imm-local-twice.rs:7:5 | LL | let v: isize; - | - help: make this binding mutable: `mut v` + | - help: consider making this binding mutable: `mut v` ... LL | v = 1; | ----- first assignment to `v` diff --git a/src/test/ui/associated-consts/associated-const-in-trait.rs b/src/test/ui/associated-consts/associated-const-in-trait.rs index cc3acd5395..f3024120df 100644 --- a/src/test/ui/associated-consts/associated-const-in-trait.rs +++ b/src/test/ui/associated-consts/associated-const-in-trait.rs @@ -1,6 +1,6 @@ // #29924 -#![feature(const_fn, associated_consts)] +#![feature(associated_consts)] trait Trait { const N: usize; diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs index 1b6d6d0ff5..48de593342 100644 --- a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs +++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - trait Foo { type Item; } diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr index bda1debeac..e72ef0e4b3 100644 --- a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr +++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr @@ -1,12 +1,12 @@ error[E0391]: cycle detected when computing the super traits of `Baz` with associated type name `Item` - --> $DIR/ambiguous-associated-type2.rs:9:1 + --> $DIR/ambiguous-associated-type2.rs:7:1 | LL | trait Baz: Foo + Bar<Self::Item> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...which again requires computing the super traits of `Baz` with associated type name `Item`, completing the cycle note: cycle used when computing the super traits of `Baz` - --> $DIR/ambiguous-associated-type2.rs:9:1 + --> $DIR/ambiguous-associated-type2.rs:7:1 | LL | trait Baz: Foo + Bar<Self::Item> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr b/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr index bde2d034e2..bd3cac1f88 100644 --- a/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr @@ -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/duplicate.rs:6:32 + --> $DIR/duplicate.rs:4:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ 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 warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/duplicate.rs:8:12 + --> $DIR/duplicate.rs:6:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ 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:13:36 + --> $DIR/duplicate.rs:11:36 | LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -24,7 +24,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:15:36 + --> $DIR/duplicate.rs:13:36 | LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -32,7 +32,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:17:39 + --> $DIR/duplicate.rs:15:39 | LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -40,7 +40,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:19:45 + --> $DIR/duplicate.rs:17:45 | LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -48,7 +48,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:21:45 + --> $DIR/duplicate.rs:19:45 | LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -56,7 +56,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:23:48 + --> $DIR/duplicate.rs:21:48 | LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -64,7 +64,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:26:34 + --> $DIR/duplicate.rs:24:34 | LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -72,7 +72,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:28:34 + --> $DIR/duplicate.rs:26:34 | LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -80,7 +80,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:30:37 + --> $DIR/duplicate.rs:28:37 | LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -88,7 +88,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:32:43 + --> $DIR/duplicate.rs:30:43 | LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -96,7 +96,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:34:43 + --> $DIR/duplicate.rs:32:43 | LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -104,7 +104,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:36:46 + --> $DIR/duplicate.rs:34:46 | LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -112,7 +112,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:39:35 + --> $DIR/duplicate.rs:37:35 | LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -120,7 +120,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:41:35 + --> $DIR/duplicate.rs:39:35 | LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -128,7 +128,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:43:38 + --> $DIR/duplicate.rs:41:38 | LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -136,7 +136,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:45:44 + --> $DIR/duplicate.rs:43:44 | LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -144,7 +144,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:47:44 + --> $DIR/duplicate.rs:45:44 | LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -152,7 +152,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:49:47 + --> $DIR/duplicate.rs:47:47 | LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -160,7 +160,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:52:32 + --> $DIR/duplicate.rs:50:32 | LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -168,7 +168,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:54:32 + --> $DIR/duplicate.rs:52:32 | LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -176,7 +176,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:56:35 + --> $DIR/duplicate.rs:54:35 | LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -184,7 +184,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:58:43 + --> $DIR/duplicate.rs:56:43 | LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -192,7 +192,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:60:43 + --> $DIR/duplicate.rs:58:43 | LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -200,7 +200,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:62:46 + --> $DIR/duplicate.rs:60:46 | LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -208,7 +208,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:68:40 + --> $DIR/duplicate.rs:66:40 | LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -216,7 +216,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:70:40 + --> $DIR/duplicate.rs:68:40 | LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -224,7 +224,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:72:43 + --> $DIR/duplicate.rs:70:43 | LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -232,7 +232,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:75:39 + --> $DIR/duplicate.rs:73:39 | LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -240,7 +240,7 @@ LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:77:39 + --> $DIR/duplicate.rs:75:39 | LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -248,7 +248,7 @@ LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:79:42 + --> $DIR/duplicate.rs:77:42 | LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -256,7 +256,7 @@ LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:81:40 + --> $DIR/duplicate.rs:79:40 | LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -264,7 +264,7 @@ LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:83:40 + --> $DIR/duplicate.rs:81:40 | LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -272,7 +272,7 @@ LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:85:43 + --> $DIR/duplicate.rs:83:43 | LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -280,7 +280,7 @@ LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:88:46 + --> $DIR/duplicate.rs:86:46 | LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -288,7 +288,7 @@ LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:90:46 + --> $DIR/duplicate.rs:88:46 | LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -296,7 +296,7 @@ LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:92:49 + --> $DIR/duplicate.rs:90:49 | LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -304,7 +304,7 @@ LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empt | `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:93:35 | LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -312,7 +312,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:97:35 + --> $DIR/duplicate.rs:95:35 | LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -320,7 +320,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:99:38 + --> $DIR/duplicate.rs:97:38 | LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -328,7 +328,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:101:44 + --> $DIR/duplicate.rs:99:44 | LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -336,7 +336,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:103:44 + --> $DIR/duplicate.rs:101:44 | LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -344,7 +344,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:105:47 + --> $DIR/duplicate.rs:103:47 | LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -352,7 +352,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:108:36 + --> $DIR/duplicate.rs:106:36 | LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -360,7 +360,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:110:36 + --> $DIR/duplicate.rs:108:36 | LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -368,7 +368,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:112:39 + --> $DIR/duplicate.rs:110:39 | LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -376,7 +376,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:114:40 + --> $DIR/duplicate.rs:112:40 | LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -384,7 +384,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:116:40 + --> $DIR/duplicate.rs:114:40 | LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; | ---------- ^^^^^^^^^^ re-bound here @@ -392,7 +392,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:118:43 + --> $DIR/duplicate.rs:116:43 | LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -400,7 +400,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:121:36 + --> $DIR/duplicate.rs:119:36 | LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -408,7 +408,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:123:36 + --> $DIR/duplicate.rs:121:36 | LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -416,7 +416,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:125:39 + --> $DIR/duplicate.rs:123:39 | LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -424,7 +424,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:127:34 + --> $DIR/duplicate.rs:125:34 | LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -432,7 +432,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:129:34 + --> $DIR/duplicate.rs:127:34 | LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -440,7 +440,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:131:37 + --> $DIR/duplicate.rs:129:37 | LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -448,7 +448,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:133:45 + --> $DIR/duplicate.rs:131:45 | LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -456,7 +456,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:135:45 + --> $DIR/duplicate.rs:133:45 | LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -464,7 +464,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:137:48 + --> $DIR/duplicate.rs:135:48 | LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -472,7 +472,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:139:46 + --> $DIR/duplicate.rs:137:46 | LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -480,7 +480,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:139:46 + --> $DIR/duplicate.rs:137:46 | LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -488,7 +488,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:142:46 + --> $DIR/duplicate.rs:140:46 | LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -496,7 +496,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:142:46 + --> $DIR/duplicate.rs:140:46 | LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -504,7 +504,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:145:49 + --> $DIR/duplicate.rs:143:49 | LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -512,7 +512,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:145:49 + --> $DIR/duplicate.rs:143:49 | LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -520,7 +520,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:155:40 + --> $DIR/duplicate.rs:153:40 | LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -528,7 +528,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:157:44 + --> $DIR/duplicate.rs:155:44 | LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | ---------- ^^^^^^^^^^ re-bound here @@ -536,7 +536,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:159:43 + --> $DIR/duplicate.rs:157:43 | LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -544,7 +544,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:148:43 + --> $DIR/duplicate.rs:146:43 | LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; } | ---------- ^^^^^^^^^^ re-bound here @@ -552,7 +552,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:150:43 + --> $DIR/duplicate.rs:148:43 | LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; } | ---------- ^^^^^^^^^^ re-bound here @@ -560,7 +560,7 @@ 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:152:46 + --> $DIR/duplicate.rs:150:46 | LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; } | ------------- ^^^^^^^^^^^^^ re-bound here diff --git a/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr b/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr index cc775dee4a..500e527a01 100644 --- a/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr @@ -1,5 +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:8:12 + --> $DIR/duplicate.rs:6:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ 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:13:36 + --> $DIR/duplicate.rs:11:36 | LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -16,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:15:36 + --> $DIR/duplicate.rs:13:36 | LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -24,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:17:39 + --> $DIR/duplicate.rs:15:39 | LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -32,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:19:45 + --> $DIR/duplicate.rs:17:45 | LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -40,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:21:45 + --> $DIR/duplicate.rs:19:45 | LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -48,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:23:48 + --> $DIR/duplicate.rs:21:48 | LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -56,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:26:34 + --> $DIR/duplicate.rs:24:34 | LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -64,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:28:34 + --> $DIR/duplicate.rs:26:34 | LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -72,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:30:37 + --> $DIR/duplicate.rs:28:37 | LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -80,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:32:43 + --> $DIR/duplicate.rs:30:43 | LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -88,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:34:43 + --> $DIR/duplicate.rs:32:43 | LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -96,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:36:46 + --> $DIR/duplicate.rs:34:46 | LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -104,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:39:35 + --> $DIR/duplicate.rs:37:35 | LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -112,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:41:35 + --> $DIR/duplicate.rs:39:35 | LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -120,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:43:38 + --> $DIR/duplicate.rs:41:38 | LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -128,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:45:44 + --> $DIR/duplicate.rs:43:44 | LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -136,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:47:44 + --> $DIR/duplicate.rs:45:44 | LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -144,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:49:47 + --> $DIR/duplicate.rs:47:47 | LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -152,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:52:32 + --> $DIR/duplicate.rs:50:32 | LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -160,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:54:32 + --> $DIR/duplicate.rs:52:32 | LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -168,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:56:35 + --> $DIR/duplicate.rs:54:35 | LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -176,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:58:43 + --> $DIR/duplicate.rs:56:43 | LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -184,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:60:43 + --> $DIR/duplicate.rs:58:43 | LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -192,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:62:46 + --> $DIR/duplicate.rs:60:46 | LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -200,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:68:40 + --> $DIR/duplicate.rs:66:40 | LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -208,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:70:40 + --> $DIR/duplicate.rs:68:40 | LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -216,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:72:43 + --> $DIR/duplicate.rs:70:43 | LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -224,7 +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:75:39 + --> $DIR/duplicate.rs:73:39 | LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -232,7 +232,7 @@ LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:77:39 + --> $DIR/duplicate.rs:75:39 | LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -240,7 +240,7 @@ LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:79:42 + --> $DIR/duplicate.rs:77:42 | LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -248,7 +248,7 @@ LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:81:40 + --> $DIR/duplicate.rs:79:40 | LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -256,7 +256,7 @@ LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:83:40 + --> $DIR/duplicate.rs:81:40 | LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -264,7 +264,7 @@ LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:85:43 + --> $DIR/duplicate.rs:83:43 | LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -272,7 +272,7 @@ LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:88:46 + --> $DIR/duplicate.rs:86:46 | LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -280,7 +280,7 @@ LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:90:46 + --> $DIR/duplicate.rs:88:46 | LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -288,7 +288,7 @@ LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:92:49 + --> $DIR/duplicate.rs:90:49 | LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -296,7 +296,7 @@ LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empt | `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:93:35 | LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -304,7 +304,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:97:35 + --> $DIR/duplicate.rs:95:35 | LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -312,7 +312,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:99:38 + --> $DIR/duplicate.rs:97:38 | LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -320,7 +320,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:101:44 + --> $DIR/duplicate.rs:99:44 | LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -328,7 +328,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:103:44 + --> $DIR/duplicate.rs:101:44 | LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -336,7 +336,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:105:47 + --> $DIR/duplicate.rs:103:47 | LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -344,7 +344,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:108:36 + --> $DIR/duplicate.rs:106:36 | LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -352,7 +352,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:110:36 + --> $DIR/duplicate.rs:108:36 | LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -360,7 +360,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:112:39 + --> $DIR/duplicate.rs:110:39 | LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -368,7 +368,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:114:40 + --> $DIR/duplicate.rs:112:40 | LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -376,7 +376,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:116:40 + --> $DIR/duplicate.rs:114:40 | LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; | ---------- ^^^^^^^^^^ re-bound here @@ -384,7 +384,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:118:43 + --> $DIR/duplicate.rs:116:43 | LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -392,7 +392,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:121:36 + --> $DIR/duplicate.rs:119:36 | LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -400,7 +400,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:123:36 + --> $DIR/duplicate.rs:121:36 | LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -408,7 +408,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:125:39 + --> $DIR/duplicate.rs:123:39 | LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -416,7 +416,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:127:34 + --> $DIR/duplicate.rs:125:34 | LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -424,7 +424,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:129:34 + --> $DIR/duplicate.rs:127:34 | LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -432,7 +432,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:131:37 + --> $DIR/duplicate.rs:129:37 | LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -440,7 +440,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:133:45 + --> $DIR/duplicate.rs:131:45 | LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -448,7 +448,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:135:45 + --> $DIR/duplicate.rs:133:45 | LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -456,7 +456,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:137:48 + --> $DIR/duplicate.rs:135:48 | LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -464,7 +464,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:139:46 + --> $DIR/duplicate.rs:137:46 | LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -472,7 +472,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:139:46 + --> $DIR/duplicate.rs:137:46 | LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -480,7 +480,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:142:46 + --> $DIR/duplicate.rs:140:46 | LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -488,7 +488,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:142:46 + --> $DIR/duplicate.rs:140:46 | LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -496,7 +496,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:145:49 + --> $DIR/duplicate.rs:143:49 | LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -504,7 +504,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:145:49 + --> $DIR/duplicate.rs:143:49 | LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -512,7 +512,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:155:40 + --> $DIR/duplicate.rs:153:40 | LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -520,7 +520,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:157:44 + --> $DIR/duplicate.rs:155:44 | LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | ---------- ^^^^^^^^^^ re-bound here @@ -528,7 +528,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:159:43 + --> $DIR/duplicate.rs:157:43 | LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -536,7 +536,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:148:43 + --> $DIR/duplicate.rs:146:43 | LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; } | ---------- ^^^^^^^^^^ re-bound here @@ -544,7 +544,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:150:43 + --> $DIR/duplicate.rs:148:43 | LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; } | ---------- ^^^^^^^^^^ re-bound here @@ -552,7 +552,7 @@ 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:152:46 + --> $DIR/duplicate.rs:150:46 | LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; } | ------------- ^^^^^^^^^^^^^ re-bound here diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs index a7bbeaf38e..c3319a7050 100644 --- a/src/test/ui/associated-type-bounds/duplicate.rs +++ b/src/test/ui/associated-type-bounds/duplicate.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![feature(associated_type_bounds)] // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] diff --git a/src/test/ui/associated-type-bounds/hrtb.rs b/src/test/ui/associated-type-bounds/hrtb.rs new file mode 100644 index 0000000000..7ab3836493 --- /dev/null +++ b/src/test/ui/associated-type-bounds/hrtb.rs @@ -0,0 +1,65 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait A<'a> {} +trait B<'b> {} +fn foo<T>() +where + for<'a> T: A<'a> + 'a, +{ +} +trait C<'c>: for<'a> A<'a> + for<'b> B<'b> { + type As; +} +struct D<T> +where + T: for<'c> C<'c, As: A<'c>>, +{ + t: std::marker::PhantomData<T>, +} + +trait E<'e> { + type As; +} +trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {} +struct G<T> +where + for<'f> T: F<'f, As: E<'f>> + 'f, +{ + t: std::marker::PhantomData<T>, +} + +trait I<'a, 'b, 'c> { + type As; +} +trait H<'d, 'e>: for<'f> I<'d, 'f, 'e> + 'd {} +fn foo2<T>() +where + T: for<'g> H<'g, 'g, As: for<'h> H<'h, 'g> + 'g>, +{ +} + +fn foo3<T>() +where + T: for<'i> H<'i, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'i, 'k, 'j> + 'j> + 'i>, +{ +} +fn foo4<T>() +where + T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'l, 'k, 'j> + 'j> + 'i>, +{ +} + +struct X<'x, 'y> { + x: std::marker::PhantomData<&'x ()>, + y: std::marker::PhantomData<&'y ()>, +} + +fn foo5<T>() +where + T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> H<'j, 'k, As = X<'j, 'k>> + 'j> + 'i> +{ +} + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/issue-79949.rs b/src/test/ui/associated-type-bounds/issue-79949.rs new file mode 100644 index 0000000000..9f924f1fd8 --- /dev/null +++ b/src/test/ui/associated-type-bounds/issue-79949.rs @@ -0,0 +1,26 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(associated_type_bounds)] +#![feature(generic_associated_types)] + +trait MP { + type T<'a>; +} +struct S(String); +impl MP for S { + type T<'a> = &'a str; +} + +trait SR: MP { + fn sr<IM>(&self) -> i32 + where + for<'a> IM: T<T: U<<Self as MP>::T<'a>>>; +} + +trait T { + type T; +} +trait U<X> {} + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/issue-81193.rs b/src/test/ui/associated-type-bounds/issue-81193.rs new file mode 100644 index 0000000000..d2aa54ab95 --- /dev/null +++ b/src/test/ui/associated-type-bounds/issue-81193.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait A<'a, 'b> {} + +trait B<'a, 'b, 'c> {} + +fn err<'u, 'a, F>() +where + for<'b> F: Iterator<Item: for<'c> B<'a, 'b, 'c> + for<'c> A<'a, 'c>>, +{ +} + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/issue-83017.rs b/src/test/ui/associated-type-bounds/issue-83017.rs new file mode 100644 index 0000000000..8f0a9ea356 --- /dev/null +++ b/src/test/ui/associated-type-bounds/issue-83017.rs @@ -0,0 +1,39 @@ +#![feature(associated_type_bounds)] + +trait TraitA<'a> { + type AsA; +} + +trait TraitB<'a, 'b> { + type AsB; +} + +trait TraitC<'a, 'b, 'c> {} + +struct X; + +impl<'a, 'b, 'c> TraitC<'a, 'b, 'c> for X {} + +struct Y; + +impl<'a, 'b> TraitB<'a, 'b> for Y { + type AsB = X; +} + +struct Z; + +impl<'a> TraitA<'a> for Z { + type AsA = Y; +} + +fn foo<T>() +where + for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>, +{ +} + +fn main() { + foo::<Z>(); + //~^ ERROR: the trait bound `for<'a, 'b> <Z as TraitA<'a>>::AsA: TraitB<'a, 'b>` is not satisfied + //~| ERROR: the trait bound `for<'a, 'b, 'c> <<Z as TraitA<'a>>::AsA as TraitB<'a, 'b>>::AsB: TraitC<'a, 'b, 'c>` is not satisfied +} diff --git a/src/test/ui/associated-type-bounds/issue-83017.stderr b/src/test/ui/associated-type-bounds/issue-83017.stderr new file mode 100644 index 0000000000..4eb71fd028 --- /dev/null +++ b/src/test/ui/associated-type-bounds/issue-83017.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `for<'a, 'b> <Z as TraitA<'a>>::AsA: TraitB<'a, 'b>` is not satisfied + --> $DIR/issue-83017.rs:36:5 + | +LL | fn foo<T>() + | --- required by a bound in this +LL | where +LL | for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>, + | ------------------------------------------------------- required by this bound in `foo` +... +LL | foo::<Z>(); + | ^^^^^^^^ the trait `for<'a, 'b> TraitB<'a, 'b>` is not implemented for `<Z as TraitA<'a>>::AsA` + +error[E0277]: the trait bound `for<'a, 'b, 'c> <<Z as TraitA<'a>>::AsA as TraitB<'a, 'b>>::AsB: TraitC<'a, 'b, 'c>` is not satisfied + --> $DIR/issue-83017.rs:36:5 + | +LL | fn foo<T>() + | --- required by a bound in this +LL | where +LL | for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>, + | -------------------------- required by this bound in `foo` +... +LL | foo::<Z>(); + | ^^^^^^^^ the trait `for<'a, 'b, 'c> TraitC<'a, 'b, 'c>` is not implemented for `<<Z as TraitA<'a>>::AsA as TraitB<'a, 'b>>::AsB` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/associated-types-coherence-failure.stderr b/src/test/ui/associated-types/associated-types-coherence-failure.stderr index 2c53b0a224..211613b371 100644 --- a/src/test/ui/associated-types/associated-types-coherence-failure.stderr +++ b/src/test/ui/associated-types/associated-types-coherence-failure.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>`: +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>` --> $DIR/associated-types-coherence-failure.rs:21:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned { @@ -7,7 +7,7 @@ LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwn LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_`: +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` --> $DIR/associated-types-coherence-failure.rs:28:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned { diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 920f832281..3c7dc1fc3c 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -15,7 +15,10 @@ LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> u8 { 0 } - | ^^ expected associated type, found `u8` + | ^^ + | | + | expected associated type, found `u8` + | help: change the output type to match the trait: `<A<T> as Tr>::Ty` | = note: expected fn pointer `fn() -> <A<T> as Tr>::Ty` found fn pointer `fn() -> u8` @@ -30,7 +33,10 @@ LL | default type Ty = bool; | ----------------------- expected this associated type LL | LL | fn make() -> bool { true } - | ^^^^ expected associated type, found `bool` + | ^^^^ + | | + | expected associated type, found `bool` + | help: change the output type to match the trait: `<B<T> as Tr>::Ty` | = note: expected fn pointer `fn() -> <B<T> as Tr>::Ty` found fn pointer `fn() -> bool` diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 274d09fd09..af4e6f0a5c 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -31,8 +31,8 @@ LL | type Bar: Clone = Vec<T>; = note: required because of the requirements on the impl of `Clone` for `Vec<T>` help: consider restricting type parameter `T` | -LL | trait Foo<T: Clone> { - | ^^^^^^^ +LL | trait Foo<T: std::clone::Clone> { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(): Foo<Self>` is not satisfied --> $DIR/defaults-suitability.rs:34:5 @@ -99,8 +99,8 @@ LL | type Baz = T; | help: consider further restricting type parameter `T` | -LL | Self::Baz: Clone, T: Clone - | ^^^^^^^^^^ +LL | Self::Baz: Clone, T: std::clone::Clone + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index b0e9e33a6c..89e05b61fc 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32` --> $DIR/impl-trait-return-missing-constraint.rs:25:13 | LL | fn bar() -> impl Bar { - | -------- the expected opaque type + | -------- the found opaque type ... LL | fn baz() -> impl Bar<Item = i32> { - | ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32` + | ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type | - = note: expected associated type `<impl Bar as Foo>::Item` - found type `i32` + = note: expected type `i32` + found associated type `<impl Bar as Foo>::Item` help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32` | LL | fn bar() -> impl Bar<Item = i32> { diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.stderr b/src/test/ui/associated-types/impl-wf-cycle-1.stderr index 82328048c9..1d8d2b0149 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-1.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr @@ -10,7 +10,11 @@ LL | | LL | | } | |_^ | - = note: required because of the requirements on the impl of `Grault` for `(T,)` +note: required because of the requirements on the impl of `Grault` for `(T,)` + --> $DIR/impl-wf-cycle-1.rs:15:17 + | +LL | impl<T: Grault> Grault for (T,) + | ^^^^^^ ^^^^ = note: 1 redundant requirements hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` @@ -20,7 +24,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` LL | type A = (); | ^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `Grault` for `(T,)` +note: required because of the requirements on the impl of `Grault` for `(T,)` + --> $DIR/impl-wf-cycle-1.rs:15:17 + | +LL | impl<T: Grault> Grault for (T,) + | ^^^^^^ ^^^^ = note: 1 redundant requirements hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` @@ -30,7 +38,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` LL | type B = bool; | ^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `Grault` for `(T,)` +note: required because of the requirements on the impl of `Grault` for `(T,)` + --> $DIR/impl-wf-cycle-1.rs:15:17 + | +LL | impl<T: Grault> Grault for (T,) + | ^^^^^^ ^^^^ = note: 1 redundant requirements hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.stderr b/src/test/ui/associated-types/impl-wf-cycle-2.stderr index 5cd18a33ad..a17e63f28f 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-2.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-2.stderr @@ -10,7 +10,11 @@ LL | | LL | | } | |_^ | - = note: required because of the requirements on the impl of `Grault` for `(T,)` +note: required because of the requirements on the impl of `Grault` for `(T,)` + --> $DIR/impl-wf-cycle-2.rs:7:17 + | +LL | impl<T: Grault> Grault for (T,) + | ^^^^^^ ^^^^ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` --> $DIR/impl-wf-cycle-2.rs:11:5 @@ -18,7 +22,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` LL | type A = (); | ^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `Grault` for `(T,)` +note: required because of the requirements on the impl of `Grault` for `(T,)` + --> $DIR/impl-wf-cycle-2.rs:7:17 + | +LL | impl<T: Grault> Grault for (T,) + | ^^^^^^ ^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-23208.rs b/src/test/ui/associated-types/issue-23208.rs similarity index 100% rename from src/test/ui/issues/issue-23208.rs rename to src/test/ui/associated-types/issue-23208.rs diff --git a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr index 02396bd00a..b6122bd54d 100644 --- a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr +++ b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr @@ -9,8 +9,8 @@ LL | copy::<dyn Setup<From=T>>(t) | help: consider restricting type parameter `T` | -LL | pub fn copy_any<T: Copy>(t: &T) -> T { - | ^^^^^^ +LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31597.rs b/src/test/ui/associated-types/issue-31597.rs similarity index 100% rename from src/test/ui/issues/issue-31597.rs rename to src/test/ui/associated-types/issue-31597.rs diff --git a/src/test/ui/associated-types/issue-43784-associated-type.stderr b/src/test/ui/associated-types/issue-43784-associated-type.stderr index d5105ae3b5..0e653a7d3b 100644 --- a/src/test/ui/associated-types/issue-43784-associated-type.stderr +++ b/src/test/ui/associated-types/issue-43784-associated-type.stderr @@ -9,8 +9,8 @@ LL | type Assoc = T; | help: consider restricting type parameter `T` | -LL | impl<T: Copy> Complete for T { - | ^^^^^^ +LL | impl<T: std::marker::Copy> Complete for T { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr index 8ef7108795..b7db5d3858 100644 --- a/src/test/ui/associated-types/issue-44153.stderr +++ b/src/test/ui/associated-types/issue-44153.stderr @@ -5,9 +5,13 @@ LL | fn visit() {} | ---------- required by `Visit::visit` ... LL | <() as Visit>::visit(); - | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&()` + | ^^^^^^^^^^^^^^^^^^^^ expected `&()`, found `()` | - = note: required because of the requirements on the impl of `Visit` for `()` +note: required because of the requirements on the impl of `Visit` for `()` + --> $DIR/issue-44153.rs:13:10 + | +LL | impl<'a> Visit for () where + | ^^^^^ ^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr index f644eb5a1f..fc020e40b5 100644 --- a/src/test/ui/associated-types/issue-65774-1.stderr +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -13,7 +13,11 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied LL | let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config); | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` | - = note: required because of the requirements on the impl of `MyDisplay` for `&mut T` +note: required because of the requirements on the impl of `MyDisplay` for `&mut T` + --> $DIR/issue-65774-1.rs:5:24 + | +LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + | ^^^^^^^^^ ^^^^^^^^^ = note: required for the cast to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/async-trait-fn.rs b/src/test/ui/async-await/async-trait-fn.rs index f0403b7662..e2062e8272 100644 --- a/src/test/ui/async-await/async-trait-fn.rs +++ b/src/test/ui/async-await/async-trait-fn.rs @@ -2,6 +2,10 @@ trait T { async fn foo() {} //~ ERROR functions in traits cannot be declared `async` async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async` + async fn baz() { //~ ERROR functions in traits cannot be declared `async` + // Nested item must not ICE. + fn a() {} + } } fn main() {} diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index 6080b2815e..1eb8969a80 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -20,6 +20,22 @@ LL | async fn bar(&self) {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait -error: aborting due to 2 previous errors +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:5:5 + | +LL | async fn baz() { + | ^---- + | | + | _____`async` because of this + | | +LL | | // Nested item must not ICE. +LL | | fn a() {} +LL | | } + | |_____^ + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0706`. diff --git a/src/test/ui/async-await/issue-61452.stderr b/src/test/ui/async-await/issue-61452.stderr index 5eb4b54871..f2dec87baf 100644 --- a/src/test/ui/async-await/issue-61452.stderr +++ b/src/test/ui/async-await/issue-61452.stderr @@ -13,7 +13,7 @@ LL | pub async fn g(x: usize) { | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/async-await/issue-61949-self-return-type.rs b/src/test/ui/async-await/issue-61949-self-return-type.rs index 6a28c69193..43429ba232 100644 --- a/src/test/ui/async-await/issue-61949-self-return-type.rs +++ b/src/test/ui/async-await/issue-61949-self-return-type.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // edition:2018 // This test checks that `Self` is prohibited as a return type. See #61949 for context. diff --git a/src/test/ui/async-await/issue-61949-self-return-type.stderr b/src/test/ui/async-await/issue-61949-self-return-type.stderr index 4eeef871c5..52b726e186 100644 --- a/src/test/ui/async-await/issue-61949-self-return-type.stderr +++ b/src/test/ui/async-await/issue-61949-self-return-type.stderr @@ -1,5 +1,5 @@ error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/issue-61949-self-return-type.rs:11:40 + --> $DIR/issue-61949-self-return-type.rs:10:40 | LL | pub async fn new(_bar: &'a i32) -> Self { | ^^^^ help: consider spelling out the type instead: `Foo<'a>` diff --git a/src/test/ui/async-await/issue-67651.stderr b/src/test/ui/async-await/issue-67651.stderr index 99857c215e..89017f6cc3 100644 --- a/src/test/ui/async-await/issue-67651.stderr +++ b/src/test/ui/async-await/issue-67651.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `From` for type `()`: +error[E0119]: conflicting implementations of trait `From` for type `()` --> $DIR/issue-67651.rs:11:1 | LL | impl From for () { diff --git a/src/test/ui/async-await/issue-68523.rs b/src/test/ui/async-await/issue-68523.rs index 718c597e71..7a67661a01 100644 --- a/src/test/ui/async-await/issue-68523.rs +++ b/src/test/ui/async-await/issue-68523.rs @@ -2,6 +2,5 @@ async fn main() -> Result<i32, ()> { //~^ ERROR `main` function is not allowed to be `async` -//~^^ ERROR `main` has invalid return type `impl Future` Ok(1) } diff --git a/src/test/ui/async-await/issue-68523.stderr b/src/test/ui/async-await/issue-68523.stderr index 6f67af04cd..dfdf078e30 100644 --- a/src/test/ui/async-await/issue-68523.stderr +++ b/src/test/ui/async-await/issue-68523.stderr @@ -1,18 +1,9 @@ -error[E0277]: `main` has invalid return type `impl Future` - --> $DIR/issue-68523.rs:3:20 - | -LL | async fn main() -> Result<i32, ()> { - | ^^^^^^^^^^^^^^^ `main` can only return types that implement `Termination` - | - = help: consider using `()`, or a `Result` - error[E0752]: `main` function is not allowed to be `async` --> $DIR/issue-68523.rs:3:1 | LL | async fn main() -> Result<i32, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0752. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0752`. diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index 11fca2dd8e..5f39cf6dde 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -11,8 +11,8 @@ LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` help: consider restricting type parameter `U` | -LL | fn foo<T: Send, U: Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { - | ^^^^^^ +LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-72590-type-error-sized.stderr b/src/test/ui/async-await/issue-72590-type-error-sized.stderr index 0f90a4c336..50dfeffde7 100644 --- a/src/test/ui/async-await/issue-72590-type-error-sized.stderr +++ b/src/test/ui/async-await/issue-72590-type-error-sized.stderr @@ -17,7 +17,11 @@ LL | async fn frob(self) {} | ^^^^ doesn't have a size known at compile-time | = help: within `Foo`, the trait `Sized` is not implemented for `str` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/issue-72590-type-error-sized.rs:5:8 + | +LL | struct Foo { + | ^^^ = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | diff --git a/src/test/ui/async-await/issues/issue-64964.rs b/src/test/ui/async-await/issues/issue-64964.rs index 11f6cb6af9..5313d1715c 100644 --- a/src/test/ui/async-await/issues/issue-64964.rs +++ b/src/test/ui/async-await/issues/issue-64964.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/issue-64964 // edition:2018 // Regression test for ICE related to `await`ing in a method + incr. comp. (#64964) diff --git a/src/test/ui/async-await/large_moves.rs b/src/test/ui/async-await/large_moves.rs new file mode 100644 index 0000000000..4fac046bee --- /dev/null +++ b/src/test/ui/async-await/large_moves.rs @@ -0,0 +1,24 @@ +#![deny(large_assignments)] +#![feature(large_assignments)] +#![move_size_limit = "1000"] +// build-fail +// only-x86_64 + +// edition:2018 + +fn main() { + let x = async { //~ ERROR large_assignments + let y = [0; 9999]; + dbg!(y); + thing(&y).await; + dbg!(y); + }; + let z = (x, 42); //~ ERROR large_assignments + //~^ ERROR large_assignments + let a = z.0; //~ ERROR large_assignments + let b = z.1; +} + +async fn thing(y: &[u8]) { + dbg!(y); +} diff --git a/src/test/ui/async-await/large_moves.stderr b/src/test/ui/async-await/large_moves.stderr new file mode 100644 index 0000000000..8c47ec0ed9 --- /dev/null +++ b/src/test/ui/async-await/large_moves.stderr @@ -0,0 +1,38 @@ +error: moving 10024 bytes + --> $DIR/large_moves.rs:10:13 + | +LL | let x = async { + | _____________^ +LL | | let y = [0; 9999]; +LL | | dbg!(y); +LL | | thing(&y).await; +LL | | dbg!(y); +LL | | }; + | |_____^ value moved from here + | +note: the lint level is defined here + --> $DIR/large_moves.rs:1:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 10024 bytes + --> $DIR/large_moves.rs:16:14 + | +LL | let z = (x, 42); + | ^ value moved from here + +error: moving 10024 bytes + --> $DIR/large_moves.rs:16:13 + | +LL | let z = (x, 42); + | ^^^^^^^ value moved from here + +error: moving 10024 bytes + --> $DIR/large_moves.rs:18:13 + | +LL | let a = z.0; + | ^^^ value moved from here + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/async-await/pin-needed-to-poll-2.rs b/src/test/ui/async-await/pin-needed-to-poll-2.rs new file mode 100644 index 0000000000..6ce70336d0 --- /dev/null +++ b/src/test/ui/async-await/pin-needed-to-poll-2.rs @@ -0,0 +1,48 @@ +use std::{ + future::Future, + pin::Pin, + marker::Unpin, + task::{Context, Poll}, +}; + +struct Sleep(std::marker::PhantomPinned); + +impl Future for Sleep { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + Poll::Ready(()) + } +} + +impl Drop for Sleep { + fn drop(&mut self) {} +} + +fn sleep() -> Sleep { + Sleep(std::marker::PhantomPinned) +} + + +struct MyFuture { + sleep: Sleep, +} + +impl MyFuture { + fn new() -> Self { + Self { + sleep: sleep(), + } + } +} + +impl Future for MyFuture { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + Pin::new(&mut self.sleep).poll(cx) + //~^ ERROR `PhantomPinned` cannot be unpinned + } +} + +fn main() {} diff --git a/src/test/ui/async-await/pin-needed-to-poll-2.stderr b/src/test/ui/async-await/pin-needed-to-poll-2.stderr new file mode 100644 index 0000000000..c4d21de8aa --- /dev/null +++ b/src/test/ui/async-await/pin-needed-to-poll-2.stderr @@ -0,0 +1,17 @@ +error[E0277]: `PhantomPinned` cannot be unpinned + --> $DIR/pin-needed-to-poll-2.rs:43:9 + | +LL | Pin::new(&mut self.sleep).poll(cx) + | ^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `Sleep` + --> $DIR/pin-needed-to-poll-2.rs:8:8 + | +LL | struct Sleep(std::marker::PhantomPinned); + | ^^^^^ + = note: required by `Pin::<P>::new` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/pin-needed-to-poll.rs b/src/test/ui/async-await/pin-needed-to-poll.rs new file mode 100644 index 0000000000..0d1fe684f6 --- /dev/null +++ b/src/test/ui/async-await/pin-needed-to-poll.rs @@ -0,0 +1,47 @@ +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; + +struct Sleep; + +impl Future for Sleep { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + Poll::Ready(()) + } +} + +impl Drop for Sleep { + fn drop(&mut self) {} +} + +fn sleep() -> Sleep { + Sleep +} + + +struct MyFuture { + sleep: Sleep, +} + +impl MyFuture { + fn new() -> Self { + Self { + sleep: sleep(), + } + } +} + +impl Future for MyFuture { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + self.sleep.poll(cx) + //~^ ERROR no method named `poll` found for struct `Sleep` in the current scope + } +} + +fn main() {} diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr new file mode 100644 index 0000000000..0756a4d59c --- /dev/null +++ b/src/test/ui/async-await/pin-needed-to-poll.stderr @@ -0,0 +1,22 @@ +error[E0599]: no method named `poll` found for struct `Sleep` in the current scope + --> $DIR/pin-needed-to-poll.rs:42:20 + | +LL | struct Sleep; + | ------------- method `poll` not found for this +... +LL | self.sleep.poll(cx) + | ^^^^ method not found in `Sleep` + | + ::: $SRC_DIR/core/src/future/future.rs:LL:COL + | +LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; + | ---- the method is available for `Pin<&mut Sleep>` here + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Pin::new(&mut self.sleep).poll(cx) + | ^^^^^^^^^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/attr-main-2.rs b/src/test/ui/attr-main-2.rs deleted file mode 100644 index 3a51f83ba3..0000000000 --- a/src/test/ui/attr-main-2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -#![feature(main)] - -pub fn main() { - panic!() -} - -#[main] -fn foo() { -} diff --git a/src/test/ui/attr-main.rs b/src/test/ui/attr-main.rs deleted file mode 100644 index 9c4caaa4a4..0000000000 --- a/src/test/ui/attr-main.rs +++ /dev/null @@ -1,8 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![feature(main)] - -#[main] -fn foo() { -} diff --git a/src/test/ui/attr.rs b/src/test/ui/attr.rs deleted file mode 100644 index 9c4caaa4a4..0000000000 --- a/src/test/ui/attr.rs +++ /dev/null @@ -1,8 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![feature(main)] - -#[main] -fn foo() { -} diff --git a/src/test/ui/binding/issue-53114-safety-checks.rs b/src/test/ui/binding/issue-53114-safety-checks.rs index 28adb7571a..ca4f0efd23 100644 --- a/src/test/ui/binding/issue-53114-safety-checks.rs +++ b/src/test/ui/binding/issue-53114-safety-checks.rs @@ -20,13 +20,13 @@ fn let_wild_gets_unsafe_field() { let u1 = U { a: I(0) }; let u2 = U { a: I(1) }; let p = P { a: &2, b: &3 }; - let _ = &p.b; //~ WARN E0133 + let _ = &p.b; //~ WARN reference to packed field //~^ WARN will become a hard error let _ = u1.a; // #53114: should eventually signal error as well let _ = &u2.a; //~ ERROR [E0133] // variation on above with `_` in substructure - let (_,) = (&p.b,); //~ WARN E0133 + let (_,) = (&p.b,); //~ WARN reference to packed field //~^ WARN will become a hard error let (_,) = (u1.a,); //~ ERROR [E0133] let (_,) = (&u2.a,); //~ ERROR [E0133] @@ -36,13 +36,13 @@ fn match_unsafe_field_to_wild() { let u1 = U { a: I(0) }; let u2 = U { a: I(1) }; let p = P { a: &2, b: &3 }; - match &p.b { _ => { } } //~ WARN E0133 + match &p.b { _ => { } } //~ WARN reference to packed field //~^ WARN will become a hard error match u1.a { _ => { } } //~ ERROR [E0133] match &u2.a { _ => { } } //~ ERROR [E0133] // variation on above with `_` in substructure - match (&p.b,) { (_,) => { } } //~ WARN E0133 + match (&p.b,) { (_,) => { } } //~ WARN reference to packed field //~^ WARN will become a hard error match (u1.a,) { (_,) => { } } //~ ERROR [E0133] match (&u2.a,) { (_,) => { } } //~ ERROR [E0133] diff --git a/src/test/ui/binding/issue-53114-safety-checks.stderr b/src/test/ui/binding/issue-53114-safety-checks.stderr index d4b8dfbade..9e7deea452 100644 --- a/src/test/ui/binding/issue-53114-safety-checks.stderr +++ b/src/test/ui/binding/issue-53114-safety-checks.stderr @@ -1,13 +1,43 @@ -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) +warning: reference to packed field is unaligned --> $DIR/issue-53114-safety-checks.rs:23:13 | LL | let _ = &p.b; | ^^^^ | - = note: `#[warn(safe_packed_borrows)]` on by default + = note: `#[warn(unaligned_references)]` 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 #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: 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: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:29:17 + | +LL | let (_,) = (&p.b,); + | ^^^^ + | + = 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) + +warning: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:39:11 + | +LL | match &p.b { _ => { } } + | ^^^^ + | + = 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) + +warning: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:45:12 + | +LL | match (&p.b,) { (_,) => { } } + | ^^^^ + | + = 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[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:26:13 @@ -17,16 +47,6 @@ LL | let _ = &u2.a; | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-53114-safety-checks.rs:29:17 - | -LL | let (_,) = (&p.b,); - | ^^^^ - | - = 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 - error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:31:17 | @@ -43,16 +63,6 @@ LL | let (_,) = (&u2.a,); | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-53114-safety-checks.rs:39:11 - | -LL | match &p.b { _ => { } } - | ^^^^ - | - = 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 - error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:41:11 | @@ -69,16 +79,6 @@ LL | match &u2.a { _ => { } } | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-53114-safety-checks.rs:45:12 - | -LL | match (&p.b,) { (_,) => { } } - | ^^^^ - | - = 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 - error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:47:12 | diff --git a/src/test/ui/shadow.rs b/src/test/ui/binding/shadow.rs similarity index 100% rename from src/test/ui/shadow.rs rename to src/test/ui/binding/shadow.rs diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 6649e67a50..397bdac605 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -6,7 +6,11 @@ LL | b + 3 | = help: the following implementations were found: <f64 as Scalar> - = note: required because of the requirements on the impl of `Add<{integer}>` for `Bob` +note: required because of the requirements on the impl of `Add<{integer}>` for `Bob` + --> $DIR/issue-22645.rs:8:19 + | +LL | impl<RHS: Scalar> Add <RHS> for Bob { + | ^^^^^^^^^ ^^^ error[E0308]: mismatched types --> $DIR/issue-22645.rs:15:3 diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs index 97f96ab692..2839a65dea 100644 --- a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs +++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs @@ -1,6 +1,5 @@ // Tests using a combination of pattern features has the expected borrow checking behavior #![feature(bindings_after_at)] -#![feature(or_patterns)] #![feature(box_patterns)] enum Test { diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr index 96e313b39e..2204dcabc9 100644 --- a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr +++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr @@ -1,5 +1,5 @@ error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:38:9 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:37:9 | LL | ref foo @ [.., ref mut bar] => (), | -------^^^^^^^^-----------^ @@ -8,7 +8,7 @@ LL | ref foo @ [.., ref mut bar] => (), | immutable borrow, by `foo`, occurs here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:122:9 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:121:9 | LL | ref foo @ Some(box ref mut s) => (), | -------^^^^^^^^^^^^---------^ @@ -17,7 +17,7 @@ LL | ref foo @ Some(box ref mut s) => (), | immutable borrow, by `foo`, occurs here error[E0382]: borrow of moved value: `x` - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:20:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:19:5 | LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) { | - move occurs because `x` has type `[String; 4]`, which does not implement the `Copy` trait @@ -29,7 +29,7 @@ LL | &x; | ^^ value borrowed here after move error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:30:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:29:5 | LL | ref mut foo @ [.., _] => Some(foo), | --------------------- mutable borrow occurs here @@ -41,7 +41,7 @@ LL | drop(r); | - mutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:52:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:51:5 | LL | [ref foo @ .., ref bar] => Some(foo), | ------------ immutable borrow occurs here @@ -53,7 +53,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:64:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:63:5 | LL | ref foo @ [.., ref bar] => Some(foo), | ----------------------- immutable borrow occurs here @@ -65,7 +65,7 @@ LL | drop(r); | - immutable borrow later used here error[E0382]: borrow of moved value: `x` - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:78:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:77:5 | LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) { | - move occurs because `x` has type `Option<Test>`, which does not implement the `Copy` trait @@ -80,7 +80,7 @@ LL | &x; | ^^ value borrowed here after move error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:88:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:87:5 | LL | ref foo @ Some(Test::Foo | Test::Bar) => Some(foo), | ------------------------------------- immutable borrow occurs here @@ -92,7 +92,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:100:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:99:5 | LL | ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo), | ----------------------------------------- mutable borrow occurs here @@ -104,7 +104,7 @@ LL | drop(r); | - mutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:114:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:113:5 | LL | ref foo @ Some(box ref s) => Some(foo), | ------------------------- immutable borrow occurs here @@ -116,7 +116,7 @@ LL | drop(r); | - immutable borrow later used here error[E0382]: borrow of moved value: `x` - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:136:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:135:5 | LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) { | - move occurs because `x` has type `[Option<Test>; 4]`, which does not implement the `Copy` trait @@ -131,7 +131,7 @@ LL | &x; | ^^ value borrowed here after move error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:146:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:145:5 | LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a), | ------------------------------------------------- immutable borrow occurs here @@ -143,7 +143,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:158:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:157:5 | LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b), | ---------- immutable borrow occurs here @@ -155,7 +155,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:172:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:171:5 | LL | [_, ref a @ Some(box ref b), ..] => Some(a), | ----------------------- immutable borrow occurs here @@ -167,7 +167,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:188:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:187:5 | LL | [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), | ------------------------------------------- immutable borrow occurs here @@ -179,7 +179,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:202:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:201:5 | LL | [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), | ----------------------------------------------- mutable borrow occurs here @@ -191,7 +191,7 @@ LL | drop(r); | - mutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:216:5 + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:215:5 | LL | ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), | ------------------------------------------------------------ immutable borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-asm.stderr b/src/test/ui/borrowck/borrowck-asm.stderr index 3dccca7841..74cf5a55b7 100644 --- a/src/test/ui/borrowck/borrowck-asm.stderr +++ b/src/test/ui/borrowck/borrowck-asm.stderr @@ -29,7 +29,7 @@ LL | let x = 3; | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | unsafe { LL | llvm_asm!("nop" : "=r"(x)); | ^ cannot assign twice to immutable variable @@ -41,7 +41,7 @@ LL | let x = 3; | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | unsafe { LL | llvm_asm!("nop" : "+r"(x)); | ^ cannot assign twice to immutable variable diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index c8bfbe0729..0e6c0635ad 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - pub struct Foo { x: u32 } diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr index e386aa1f1f..0f2ebbcbf3 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:256:13 + --> $DIR/borrowck-describe-lvalue.rs:254:13 | LL | let y = &mut x; | ------ first mutable borrow occurs here @@ -9,7 +9,7 @@ LL | *y = 1; | ------ first borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:266:20 + --> $DIR/borrowck-describe-lvalue.rs:264:20 | LL | let y = &mut x; | ------ first mutable borrow occurs here @@ -19,7 +19,7 @@ LL | *y = 1; | ------ first borrow later used here error: captured variable cannot escape `FnMut` closure body - --> $DIR/borrowck-describe-lvalue.rs:264:16 + --> $DIR/borrowck-describe-lvalue.rs:262:16 | LL | let mut x = 0; | ----- variable defined here @@ -38,7 +38,7 @@ LL | | } = note: ...therefore, they cannot allow references to captured variables to escape error[E0503]: cannot use `f.x` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:39:9 + --> $DIR/borrowck-describe-lvalue.rs:37:9 | LL | let x = f.x(); | - borrow of `f` occurs here @@ -48,7 +48,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `g.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:46:9 + --> $DIR/borrowck-describe-lvalue.rs:44:9 | LL | let x = g.x(); | - borrow of `g` occurs here @@ -58,7 +58,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `h.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:53:9 + --> $DIR/borrowck-describe-lvalue.rs:51:9 | LL | let x = &mut h.0; | -------- borrow of `h.0` occurs here @@ -68,7 +68,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `e.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:61:20 + --> $DIR/borrowck-describe-lvalue.rs:59:20 | LL | let x = e.x(); | - borrow of `e` occurs here @@ -80,7 +80,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `u.a` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:69:9 + --> $DIR/borrowck-describe-lvalue.rs:67:9 | LL | let x = &mut u.a; | -------- borrow of `u.a` occurs here @@ -90,7 +90,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `f.x` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:76:9 + --> $DIR/borrowck-describe-lvalue.rs:74:9 | LL | let x = f.x(); | - borrow of `*f` occurs here @@ -100,7 +100,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `g.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:83:9 + --> $DIR/borrowck-describe-lvalue.rs:81:9 | LL | let x = g.x(); | - borrow of `*g` occurs here @@ -110,7 +110,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `h.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:90:9 + --> $DIR/borrowck-describe-lvalue.rs:88:9 | LL | let x = &mut h.0; | -------- borrow of `h.0` occurs here @@ -120,7 +120,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `e.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:98:20 + --> $DIR/borrowck-describe-lvalue.rs:96:20 | LL | let x = e.x(); | - borrow of `*e` occurs here @@ -132,7 +132,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `u.a` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:107:9 + --> $DIR/borrowck-describe-lvalue.rs:105:9 | LL | let x = &mut u.a; | -------- borrow of `u.a` occurs here @@ -142,7 +142,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:115:15 + --> $DIR/borrowck-describe-lvalue.rs:113:15 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -154,7 +154,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:120:18 + --> $DIR/borrowck-describe-lvalue.rs:118:18 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -166,7 +166,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:125:25 + --> $DIR/borrowck-describe-lvalue.rs:123:25 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -178,7 +178,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:130:28 + --> $DIR/borrowck-describe-lvalue.rs:128:28 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -190,7 +190,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:141:15 + --> $DIR/borrowck-describe-lvalue.rs:139:15 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -202,7 +202,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:146:18 + --> $DIR/borrowck-describe-lvalue.rs:144:18 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -214,7 +214,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:151:15 + --> $DIR/borrowck-describe-lvalue.rs:149:15 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -226,7 +226,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:156:18 + --> $DIR/borrowck-describe-lvalue.rs:154:18 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -238,7 +238,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `e` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:169:13 + --> $DIR/borrowck-describe-lvalue.rs:167:13 | LL | let x = &mut e; | ------ borrow of `e` occurs here @@ -250,7 +250,7 @@ LL | drop(x); | - borrow later used here error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:169:18 + --> $DIR/borrowck-describe-lvalue.rs:167:18 | LL | let x = &mut e; | ------ mutable borrow occurs here @@ -262,7 +262,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:173:23 + --> $DIR/borrowck-describe-lvalue.rs:171:23 | LL | let x = &mut e; | ------ mutable borrow occurs here @@ -274,7 +274,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:186:22 + --> $DIR/borrowck-describe-lvalue.rs:184:22 | LL | let x = &mut s; | ------ mutable borrow occurs here @@ -286,7 +286,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:192:28 + --> $DIR/borrowck-describe-lvalue.rs:190:28 | LL | let x = &mut s; | ------ mutable borrow occurs here @@ -298,7 +298,7 @@ LL | drop(x); | - mutable borrow later used here error[E0503]: cannot use `*v` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:234:9 + --> $DIR/borrowck-describe-lvalue.rs:232:9 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -309,7 +309,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[_].y` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:234:9 + --> $DIR/borrowck-describe-lvalue.rs:232:9 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -320,7 +320,7 @@ LL | drop(x); | - borrow later used here error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:245:24 + --> $DIR/borrowck-describe-lvalue.rs:243:24 | LL | let x = &mut v; | ------ mutable borrow occurs here @@ -332,7 +332,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:208:29 + --> $DIR/borrowck-describe-lvalue.rs:206:29 | LL | let x = &mut block; | ---------- mutable borrow occurs here @@ -343,7 +343,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:223:33 + --> $DIR/borrowck-describe-lvalue.rs:221:33 | LL | let x = &mut block; | ---------- mutable borrow occurs here @@ -354,7 +354,7 @@ LL | drop(x); | - mutable borrow later used here error[E0382]: use of moved value: `x` - --> $DIR/borrowck-describe-lvalue.rs:276:22 + --> $DIR/borrowck-describe-lvalue.rs:274:22 | LL | drop(x); | - value moved here diff --git a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.stderr b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.stderr index 5661ca52cb..dd22d7e2e2 100644 --- a/src/test/ui/borrowck/borrowck-match-binding-is-assignment.stderr +++ b/src/test/ui/borrowck/borrowck-match-binding-is-assignment.stderr @@ -5,7 +5,7 @@ LL | x => { | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable @@ -16,7 +16,7 @@ LL | E::Foo(x) => { | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable @@ -27,7 +27,7 @@ LL | S { bar: x } => { | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable @@ -38,7 +38,7 @@ LL | (x,) => { | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable @@ -49,7 +49,7 @@ LL | [x,_,_] => { | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/borrowck/borrowck-union-borrow.rs b/src/test/ui/borrowck/borrowck-union-borrow.rs index 63901680bd..f01915398a 100644 --- a/src/test/ui/borrowck/borrowck-union-borrow.rs +++ b/src/test/ui/borrowck/borrowck-union-borrow.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #[derive(Clone, Copy)] union U { a: u8, diff --git a/src/test/ui/borrowck/borrowck-union-borrow.stderr b/src/test/ui/borrowck/borrowck-union-borrow.stderr index ca10e299c5..395cd0b485 100644 --- a/src/test/ui/borrowck/borrowck-union-borrow.stderr +++ b/src/test/ui/borrowck/borrowck-union-borrow.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-union-borrow.rs:25:23 + --> $DIR/borrowck-union-borrow.rs:23:23 | LL | let ra = &u.a; | ---- immutable borrow occurs here @@ -9,7 +9,7 @@ LL | drop(ra); | -- immutable borrow later used here error[E0506]: cannot assign to `u.a` because it is borrowed - --> $DIR/borrowck-union-borrow.rs:30:13 + --> $DIR/borrowck-union-borrow.rs:28:13 | LL | let ra = &u.a; | ---- borrow of `u.a` occurs here @@ -19,7 +19,7 @@ LL | drop(ra); | -- borrow later used here error[E0502]: cannot borrow `u` (via `u.b`) as mutable because it is also borrowed as immutable (via `u.a`) - --> $DIR/borrowck-union-borrow.rs:46:23 + --> $DIR/borrowck-union-borrow.rs:44:23 | LL | let ra = &u.a; | ---- immutable borrow occurs here (via `u.a`) @@ -31,7 +31,7 @@ LL | drop(ra); = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a` error[E0506]: cannot assign to `u.b` because it is borrowed - --> $DIR/borrowck-union-borrow.rs:51:13 + --> $DIR/borrowck-union-borrow.rs:49:13 | LL | let ra = &u.a; | ---- borrow of `u.b` occurs here @@ -41,7 +41,7 @@ LL | drop(ra); | -- borrow later used here error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-union-borrow.rs:57:22 + --> $DIR/borrowck-union-borrow.rs:55:22 | LL | let rma = &mut u.a; | -------- mutable borrow occurs here @@ -51,7 +51,7 @@ LL | drop(rma); | --- mutable borrow later used here error[E0503]: cannot use `u.a` because it was mutably borrowed - --> $DIR/borrowck-union-borrow.rs:62:21 + --> $DIR/borrowck-union-borrow.rs:60:21 | LL | let ra = &mut u.a; | -------- borrow of `u.a` occurs here @@ -61,7 +61,7 @@ LL | drop(ra); | -- borrow later used here error[E0499]: cannot borrow `u.a` as mutable more than once at a time - --> $DIR/borrowck-union-borrow.rs:67:24 + --> $DIR/borrowck-union-borrow.rs:65:24 | LL | let rma = &mut u.a; | -------- first mutable borrow occurs here @@ -71,7 +71,7 @@ LL | drop(rma); | --- first borrow later used here error[E0506]: cannot assign to `u.a` because it is borrowed - --> $DIR/borrowck-union-borrow.rs:72:13 + --> $DIR/borrowck-union-borrow.rs:70:13 | LL | let rma = &mut u.a; | -------- borrow of `u.a` occurs here @@ -81,7 +81,7 @@ LL | drop(rma); | --- borrow later used here error[E0502]: cannot borrow `u` (via `u.b`) as immutable because it is also borrowed as mutable (via `u.a`) - --> $DIR/borrowck-union-borrow.rs:78:22 + --> $DIR/borrowck-union-borrow.rs:76:22 | LL | let rma = &mut u.a; | -------- mutable borrow occurs here (via `u.a`) @@ -93,7 +93,7 @@ LL | drop(rma); = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a` error[E0503]: cannot use `u.b` because it was mutably borrowed - --> $DIR/borrowck-union-borrow.rs:83:21 + --> $DIR/borrowck-union-borrow.rs:81:21 | LL | let ra = &mut u.a; | -------- borrow of `u.a` occurs here @@ -104,7 +104,7 @@ LL | drop(ra); | -- borrow later used here error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time - --> $DIR/borrowck-union-borrow.rs:89:24 + --> $DIR/borrowck-union-borrow.rs:87:24 | LL | let rma = &mut u.a; | -------- first mutable borrow occurs here (via `u.a`) @@ -116,7 +116,7 @@ LL | drop(rma); = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a` error[E0506]: cannot assign to `u.b` because it is borrowed - --> $DIR/borrowck-union-borrow.rs:94:13 + --> $DIR/borrowck-union-borrow.rs:92:13 | LL | let rma = &mut u.a; | -------- borrow of `u.b` occurs here diff --git a/src/test/ui/borrowck/immutable-arg.stderr b/src/test/ui/borrowck/immutable-arg.stderr index 7255ca327e..bddb0633a0 100644 --- a/src/test/ui/borrowck/immutable-arg.stderr +++ b/src/test/ui/borrowck/immutable-arg.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign to immutable argument `_x` --> $DIR/immutable-arg.rs:2:5 | LL | fn foo(_x: u32) { - | -- help: make this binding mutable: `mut _x` + | -- help: consider making this binding mutable: `mut _x` LL | _x = 4; | ^^^^^^ cannot assign to immutable argument diff --git a/src/test/ui/borrowck/issue-45199.rs b/src/test/ui/borrowck/issue-45199.rs index cbd45cbb61..ded46e56e3 100644 --- a/src/test/ui/borrowck/issue-45199.rs +++ b/src/test/ui/borrowck/issue-45199.rs @@ -1,6 +1,6 @@ fn test_drop_replace() { let b: Box<isize>; - //~^ HELP make this binding mutable + //~^ HELP consider making this binding mutable //~| SUGGESTION mut b b = Box::new(1); //~ NOTE first assignment b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b` @@ -9,13 +9,13 @@ fn test_drop_replace() { fn test_call() { let b = Box::new(1); //~ NOTE first assignment - //~| HELP make this binding mutable + //~| HELP consider making this binding mutable //~| SUGGESTION mut b b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b` //~| NOTE cannot assign twice to immutable } -fn test_args(b: Box<i32>) { //~ HELP make this binding mutable +fn test_args(b: Box<i32>) { //~ HELP consider making this binding mutable //~| SUGGESTION mut b b = Box::new(2); //~ ERROR cannot assign to immutable argument `b` //~| NOTE cannot assign to immutable argument diff --git a/src/test/ui/borrowck/issue-45199.stderr b/src/test/ui/borrowck/issue-45199.stderr index 83b634051b..47aa309082 100644 --- a/src/test/ui/borrowck/issue-45199.stderr +++ b/src/test/ui/borrowck/issue-45199.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `b` --> $DIR/issue-45199.rs:6:5 | LL | let b: Box<isize>; - | - help: make this binding mutable: `mut b` + | - help: consider making this binding mutable: `mut b` ... LL | b = Box::new(1); | - first assignment to `b` @@ -16,7 +16,7 @@ LL | let b = Box::new(1); | - | | | first assignment to `b` - | help: make this binding mutable: `mut b` + | help: consider making this binding mutable: `mut b` ... LL | b = Box::new(2); | ^ cannot assign twice to immutable variable @@ -25,7 +25,7 @@ error[E0384]: cannot assign to immutable argument `b` --> $DIR/issue-45199.rs:20:5 | LL | fn test_args(b: Box<i32>) { - | - help: make this binding mutable: `mut b` + | - help: consider making this binding mutable: `mut b` LL | LL | b = Box::new(2); | ^ cannot assign to immutable argument diff --git a/src/test/ui/borrowck/or-patterns.rs b/src/test/ui/borrowck/or-patterns.rs index 5b31e2d76a..aeab3b92e9 100644 --- a/src/test/ui/borrowck/or-patterns.rs +++ b/src/test/ui/borrowck/or-patterns.rs @@ -1,8 +1,6 @@ // Test that borrow check considers all choices in an or pattern, even the // unreachable ones. -#![feature(or_patterns)] - fn or_pattern_moves_all(x: ((String, String),)) { match x { ((y, _) | (_, y),) => (), diff --git a/src/test/ui/borrowck/or-patterns.stderr b/src/test/ui/borrowck/or-patterns.stderr index 9593b94537..dd5797c3f7 100644 --- a/src/test/ui/borrowck/or-patterns.stderr +++ b/src/test/ui/borrowck/or-patterns.stderr @@ -1,5 +1,5 @@ error[E0382]: borrow of moved value: `x.0.0` - --> $DIR/or-patterns.rs:10:5 + --> $DIR/or-patterns.rs:8:5 | LL | ((y, _) | (_, y),) => (), | - value moved here @@ -10,7 +10,7 @@ LL | &x.0 .0; = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x.0.1` - --> $DIR/or-patterns.rs:12:5 + --> $DIR/or-patterns.rs:10:5 | LL | ((y, _) | (_, y),) => (), | - value moved here @@ -21,7 +21,7 @@ LL | &x.0 .1; = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable - --> $DIR/or-patterns.rs:20:5 + --> $DIR/or-patterns.rs:18:5 | LL | ((ref y, _) | (_, ref y),) => y, | ----- immutable borrow occurs here @@ -33,7 +33,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable - --> $DIR/or-patterns.rs:22:5 + --> $DIR/or-patterns.rs:20:5 | LL | ((ref y, _) | (_, ref y),) => y, | ----- immutable borrow occurs here @@ -45,7 +45,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable - --> $DIR/or-patterns.rs:31:5 + --> $DIR/or-patterns.rs:29:5 | LL | ((ref mut y, _) | (_, ref mut y),) => y, | --------- mutable borrow occurs here @@ -57,7 +57,7 @@ LL | drop(r); | - mutable borrow later used here error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable - --> $DIR/or-patterns.rs:33:5 + --> $DIR/or-patterns.rs:31:5 | LL | ((ref mut y, _) | (_, ref mut y),) => y, | --------- mutable borrow occurs here @@ -69,7 +69,7 @@ LL | drop(r); | - mutable borrow later used here error[E0382]: borrow of moved value: `x.0.0` - --> $DIR/or-patterns.rs:40:5 + --> $DIR/or-patterns.rs:38:5 | LL | let ((y, _) | (_, y),) = x; | - value moved here @@ -79,7 +79,7 @@ LL | &x.0 .0; = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x.0.1` - --> $DIR/or-patterns.rs:42:5 + --> $DIR/or-patterns.rs:40:5 | LL | let ((y, _) | (_, y),) = x; | - value moved here @@ -90,7 +90,7 @@ LL | &x.0 .1; = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable - --> $DIR/or-patterns.rs:48:5 + --> $DIR/or-patterns.rs:46:5 | LL | let ((ref r, _) | (_, ref r),) = x; | ----- immutable borrow occurs here @@ -101,7 +101,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable - --> $DIR/or-patterns.rs:50:5 + --> $DIR/or-patterns.rs:48:5 | LL | let ((ref r, _) | (_, ref r),) = x; | ----- immutable borrow occurs here @@ -113,7 +113,7 @@ LL | drop(r); | - immutable borrow later used here error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable - --> $DIR/or-patterns.rs:57:5 + --> $DIR/or-patterns.rs:55:5 | LL | let ((ref mut r, _) | (_, ref mut r),) = x; | --------- mutable borrow occurs here @@ -124,7 +124,7 @@ LL | drop(r); | - mutable borrow later used here error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable - --> $DIR/or-patterns.rs:59:5 + --> $DIR/or-patterns.rs:57:5 | LL | let ((ref mut r, _) | (_, ref mut r),) = x; | --------- mutable borrow occurs here diff --git a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr index 9f31c3f87c..bba3393fc1 100644 --- a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr +++ b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr @@ -1,5 +1,5 @@ error[E0503]: cannot use `i` because it was mutably borrowed - --> $DIR/two-phase-allow-access-during-reservation.rs:30:19 + --> $DIR/two-phase-allow-access-during-reservation.rs:28:19 | LL | /*1*/ let p = &mut i; // (reservation of `i` starts here) | ------ borrow of `i` occurs here @@ -11,7 +11,7 @@ LL | /*3*/ *p += 1; // (mutable borrow of `i` starts here, since `p` | ------- borrow later used here error[E0503]: cannot use `i` because it was mutably borrowed - --> $DIR/two-phase-allow-access-during-reservation.rs:35:19 + --> $DIR/two-phase-allow-access-during-reservation.rs:33:19 | LL | /*1*/ let p = &mut i; // (reservation of `i` starts here) | ------ borrow of `i` occurs here diff --git a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.rs b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.rs index 07169afefc..3afa679ce3 100644 --- a/src/test/ui/borrowck/two-phase-allow-access-during-reservation.rs +++ b/src/test/ui/borrowck/two-phase-allow-access-during-reservation.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // revisions: nll_target // The following revisions are disabled due to missing support for two_phase_beyond_autoref diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr index 7b64d9d400..2cbdc0901b 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable - --> $DIR/two-phase-reservation-sharing-interference.rs:36:17 + --> $DIR/two-phase-reservation-sharing-interference.rs:34:17 | LL | let shared = &vec; | ---- immutable borrow occurs here diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs index de6f66c1c3..f7392bfeaa 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // revisions: nll_target // The following revisions are disabled due to missing support from two-phase beyond autorefs diff --git a/src/test/ui/bound-suggestions.fixed b/src/test/ui/bound-suggestions.fixed index be61b7dda2..31fdd2b67e 100644 --- a/src/test/ui/bound-suggestions.fixed +++ b/src/test/ui/bound-suggestions.fixed @@ -5,37 +5,37 @@ use std::fmt::Debug; // Rustfix should add this, or use `std::fmt::Debug` instead. #[allow(dead_code)] -fn test_impl(t: impl Sized + Debug) { +fn test_impl(t: impl Sized + std::fmt::Debug) { println!("{:?}", t); //~^ ERROR doesn't implement } #[allow(dead_code)] -fn test_no_bounds<T: Debug>(t: T) { +fn test_no_bounds<T: std::fmt::Debug>(t: T) { println!("{:?}", t); //~^ ERROR doesn't implement } #[allow(dead_code)] -fn test_one_bound<T: Sized + Debug>(t: T) { +fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) { println!("{:?}", t); //~^ ERROR doesn't implement } #[allow(dead_code)] -fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: Debug { +fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { println!("{:?} {:?}", x, y); //~^ ERROR doesn't implement } #[allow(dead_code)] -fn test_one_bound_where<X>(x: X) where X: Sized + Debug { +fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug { println!("{:?}", x); //~^ ERROR doesn't implement } #[allow(dead_code)] -fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: Debug { +fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: std::fmt::Debug { println!("{:?}", x); //~^ ERROR doesn't implement } diff --git a/src/test/ui/bound-suggestions.stderr b/src/test/ui/bound-suggestions.stderr index 12e67e9026..ebf43bdb27 100644 --- a/src/test/ui/bound-suggestions.stderr +++ b/src/test/ui/bound-suggestions.stderr @@ -8,8 +8,8 @@ LL | println!("{:?}", t); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting this bound | -LL | fn test_impl(t: impl Sized + Debug) { - | ^^^^^^^ +LL | fn test_impl(t: impl Sized + std::fmt::Debug) { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:15:22 @@ -21,8 +21,8 @@ LL | println!("{:?}", t); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -LL | fn test_no_bounds<T: Debug>(t: T) { - | ^^^^^^^ +LL | fn test_no_bounds<T: std::fmt::Debug>(t: T) { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:21:22 @@ -34,8 +34,8 @@ LL | println!("{:?}", t); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting this bound | -LL | fn test_one_bound<T: Sized + Debug>(t: T) { - | ^^^^^^^ +LL | fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `Y` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:27:30 @@ -47,8 +47,8 @@ LL | println!("{:?} {:?}", x, y); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `Y` | -LL | fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: Debug { - | ^^^^^^^^^^ +LL | fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: `X` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:33:22 @@ -60,8 +60,8 @@ LL | println!("{:?}", x); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting this bound | -LL | fn test_one_bound_where<X>(x: X) where X: Sized + Debug { - | ^^^^^^^ +LL | fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `X` doesn't implement `Debug` --> $DIR/bound-suggestions.rs:39:22 @@ -73,8 +73,8 @@ LL | println!("{:?}", x); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `X` | -LL | fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: Debug { - | ^^^^^^^^^^ +LL | fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized, X: std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/bound-suggestions.rs:44:46 diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr index 7e8ac113b4..7ff986ec38 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr @@ -10,8 +10,8 @@ LL | impl <T: Sync+'static> Foo for (T,) { } = note: required because it appears within the type `(T,)` help: consider further restricting this bound | -LL | impl <T: Sync+'static + Send> Foo for (T,) { } - | ^^^^^^ +LL | impl <T: Sync+'static + std::marker::Send> Foo for (T,) { } + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` cannot be shared between threads safely --> $DIR/builtin-superkinds-double-superkind.rs:9:16 @@ -25,8 +25,8 @@ LL | impl <T: Send> Foo for (T,T) { } = note: required because it appears within the type `(T, T)` help: consider further restricting this bound | -LL | impl <T: Send + Sync> Foo for (T,T) { } - | ^^^^^^ +LL | impl <T: Send + std::marker::Sync> Foo for (T,T) { } + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index 2b4b6e548b..0d1d747272 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -9,11 +9,15 @@ LL | impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { } LL | pub trait RequiresRequiresShareAndSend : RequiresShare + Send { } | ---- required by this bound in `RequiresRequiresShareAndSend` | - = note: required because it appears within the type `X<T>` +note: required because it appears within the type `X<T>` + --> $DIR/builtin-superkinds-in-metadata.rs:9:8 + | +LL | struct X<T>(T); + | ^ help: consider further restricting this bound | -LL | impl <T:Sync+'static + Send> RequiresRequiresShareAndSend for X<T> { } - | ^^^^^^ +LL | impl <T:Sync+'static + std::marker::Send> RequiresRequiresShareAndSend for X<T> { } + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr index ff2cd1c4c8..ad80b3fa8d 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -9,8 +9,8 @@ LL | impl <T: Sync+'static> Foo for T { } | help: consider further restricting this bound | -LL | impl <T: Sync+'static + Send> Foo for T { } - | ^^^^^^ +LL | impl <T: Sync+'static + std::marker::Send> Foo for T { } + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs index ac153cb574..aed099a53e 100644 --- a/src/test/ui/cast/cast-ptr-to-int-const.rs +++ b/src/test/ui/cast/cast-ptr-to-int-const.rs @@ -1,11 +1,25 @@ // gate-test-const_raw_ptr_to_usize_cast +// revisions: with_feature without_feature + +#![cfg_attr(with_feature, feature(const_raw_ptr_to_usize_cast))] fn main() { - const X: u32 = unsafe { - main as u32 //~ ERROR casting pointers to integers in constants is unstable + const X: usize = unsafe { + main as usize //[without_feature]~ ERROR casting pointers to integers in constants is unstable }; const Y: u32 = 0; - const Z: u32 = unsafe { - &Y as *const u32 as u32 //~ ERROR is unstable + const Z: usize = unsafe { + &Y as *const u32 as usize //[without_feature]~ ERROR is unstable + }; + // Cast in `const` without `unsafe` block + const SAFE: usize = { + &Y as *const u32 as usize //[without_feature]~ ERROR is unstable + //[with_feature]~^ 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 //[without_feature]~ ERROR is unstable + //[with_feature]~^ ERROR cast of pointer to int is unsafe and requires unsafe +} diff --git a/src/test/ui/cast/cast-ptr-to-int-const.stderr b/src/test/ui/cast/cast-ptr-to-int-const.stderr deleted file mode 100644 index f523b14a98..0000000000 --- a/src/test/ui/cast/cast-ptr-to-int-const.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/cast-ptr-to-int-const.rs:5:9 - | -LL | main as u32 - | ^^^^^^^^^^^ - | - = 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/cast-ptr-to-int-const.rs:9:9 - | -LL | &Y as *const u32 as u32 - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = 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 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/cast/cast-ptr-to-int-const.with_feature.stderr b/src/test/ui/cast/cast-ptr-to-int-const.with_feature.stderr new file mode 100644 index 0000000000..8282bc3db0 --- /dev/null +++ b/src/test/ui/cast/cast-ptr-to-int-const.with_feature.stderr @@ -0,0 +1,19 @@ +error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block + --> $DIR/cast-ptr-to-int-const.rs:16: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:23: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.without_feature.stderr b/src/test/ui/cast/cast-ptr-to-int-const.without_feature.stderr new file mode 100644 index 0000000000..c87fa1a14a --- /dev/null +++ b/src/test/ui/cast/cast-ptr-to-int-const.without_feature.stderr @@ -0,0 +1,39 @@ +error[E0658]: casting pointers to integers in constants is unstable + --> $DIR/cast-ptr-to-int-const.rs:8: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/cast-ptr-to-int-const.rs:12: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 constants is unstable + --> $DIR/cast-ptr-to-int-const.rs:16: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/cast-ptr-to-int-const.rs:23: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 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/cast/fat-ptr-cast-rpass.rs b/src/test/ui/cast/fat-ptr-cast-rpass.rs index 5f5e621d76..9fa2255e1b 100644 --- a/src/test/ui/cast/fat-ptr-cast-rpass.rs +++ b/src/test/ui/cast/fat-ptr-cast-rpass.rs @@ -1,5 +1,8 @@ // 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; @@ -37,5 +40,4 @@ fn main() { assert_eq!(b, d); assert_eq!(c, d as usize); - } diff --git a/src/test/ui/cast/issue-84213.fixed b/src/test/ui/cast/issue-84213.fixed new file mode 100644 index 0000000000..e1a60557a2 --- /dev/null +++ b/src/test/ui/cast/issue-84213.fixed @@ -0,0 +1,15 @@ +// run-rustfix + +struct Something { + pub field: u32, +} + +fn main() { + let mut something = Something { field: 1337 }; + + let _pointer_to_something = &something as *const Something; + //~^ ERROR: non-primitive cast + + let _mut_pointer_to_something = &mut something as *mut Something; + //~^ ERROR: non-primitive cast +} diff --git a/src/test/ui/cast/issue-84213.rs b/src/test/ui/cast/issue-84213.rs new file mode 100644 index 0000000000..3df264bdff --- /dev/null +++ b/src/test/ui/cast/issue-84213.rs @@ -0,0 +1,15 @@ +// run-rustfix + +struct Something { + pub field: u32, +} + +fn main() { + let mut something = Something { field: 1337 }; + + let _pointer_to_something = something as *const Something; + //~^ ERROR: non-primitive cast + + let _mut_pointer_to_something = something as *mut Something; + //~^ ERROR: non-primitive cast +} diff --git a/src/test/ui/cast/issue-84213.stderr b/src/test/ui/cast/issue-84213.stderr new file mode 100644 index 0000000000..a76aac5801 --- /dev/null +++ b/src/test/ui/cast/issue-84213.stderr @@ -0,0 +1,25 @@ +error[E0605]: non-primitive cast: `Something` as `*const Something` + --> $DIR/issue-84213.rs:10:33 + | +LL | let _pointer_to_something = something as *const Something; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: borrow the value for the cast to be valid + | +LL | let _pointer_to_something = &something as *const Something; + | ^ + +error[E0605]: non-primitive cast: `Something` as `*mut Something` + --> $DIR/issue-84213.rs:13:37 + | +LL | let _mut_pointer_to_something = something as *mut Something; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: borrow the value for the cast to be valid + | +LL | let _mut_pointer_to_something = &mut something as *mut Something; + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/src/test/ui/cleanup-shortcircuit.rs b/src/test/ui/cleanup-shortcircuit.rs index 4f5197a5ba..fe867ce1fb 100644 --- a/src/test/ui/cleanup-shortcircuit.rs +++ b/src/test/ui/cleanup-shortcircuit.rs @@ -3,6 +3,9 @@ // pretty-expanded FIXME #23616 +#![allow(deref_nullptr)] + + use std::env; pub fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs index 6fce295150..82ec60a2e7 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs @@ -23,7 +23,7 @@ fn test_missing_unsafe_warning_on_repr_packed() { let c = || { println!("{}", foo.x); - //~^ WARNING: borrow of packed field is unsafe and requires unsafe function or block + //~^ WARNING: reference to packed field is unaligned //~| WARNING: this was previously accepted by the compiler but is being phased out let _z = foo.x; }; diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr index 440b2c54c0..e8cc164be8 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr @@ -7,16 +7,16 @@ 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: borrow of packed field is unsafe and requires unsafe function or block (error E0133) +warning: reference to packed field is unaligned --> $DIR/repr_packed.rs:25:24 | LL | println!("{}", foo.x); | ^^^^^ | - = note: `#[warn(safe_packed_borrows)]` on by default + = note: `#[warn(unaligned_references)]` 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 #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: 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 diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed new file mode 100644 index 0000000000..300f67e8b1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed @@ -0,0 +1,133 @@ +// run-rustfix + +#![deny(disjoint_capture_drop_reorder)] +//~^ NOTE: the lint level is defined here + +// Test cases for types that implement a insignificant drop (stlib defined) + +// `t` needs Drop because one of its elements needs drop, +// therefore precise capture might affect drop ordering +fn test1_all_need_migration() { + let t = (String::new(), String::new()); + let t1 = (String::new(), String::new()); + 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 + + let _t = t.0; + let _t1 = t1.0; + let _t2 = t2.0; + }; + + c(); +} + +// 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 +fn test2_only_precise_paths_need_migration() { + let t = (String::new(), String::new()); + let t1 = (String::new(), String::new()); + 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 + let _t = t.0; + let _t1 = t1.0; + let _t2 = t2; + }; + + c(); +} + +// 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. +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 + let _t = t.0; + println!("{}", t1.1); + }; + + c(); +} + +// 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. +fn test4_only_non_copy_types_need_migration() { + let t = (String::new(), String::new()); + + // `t1` is Copy because all of its elements are Copy + 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 + let _t = t.0; + let _t1 = t1.0; + }; + + c(); +} + +fn test5_only_drop_types_need_migration() { + struct S(i32, i32); + + let t = (String::new(), String::new()); + + // `s` doesn't implement Drop or any elements within it, and doesn't 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 + let _t = t.0; + let _s = s.0; + }; + + c(); +} + +// 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. +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 + println!("{} {}", t1.1, t.1); + }; + + c(); +} + +// 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, +// otherwise we won't need to, since we can get away with just by ref capture in that case. +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 + let _t = t.0; + }; + + c(); +} + +fn main() { + test1_all_need_migration(); + test2_only_precise_paths_need_migration(); + test3_only_by_value_need_migration(); + test4_only_non_copy_types_need_migration(); + test5_only_drop_types_need_migration(); + test6_move_closures_non_copy_types_might_need_migration(); + test7_drop_non_drop_aggregate_need_migration(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs index 02b3736209..a17c70d3e2 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs @@ -1,3 +1,5 @@ +// run-rustfix + #![deny(disjoint_capture_drop_reorder)] //~^ NOTE: the lint level is defined here @@ -11,8 +13,9 @@ fn test1_all_need_migration() { let t2 = (String::new(), String::new()); let c = || { - //~^ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| NOTE: drop(&(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 + let _t = t.0; let _t1 = t1.0; let _t2 = t2.0; @@ -29,8 +32,8 @@ 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` - //~| NOTE: drop(&(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 let _t = t.0; let _t1 = t1.0; let _t2 = t2; @@ -45,8 +48,8 @@ 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; println!("{}", t1.1); }; @@ -63,8 +66,8 @@ 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _t1 = t1.0; }; @@ -81,8 +84,8 @@ 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _s = s.0; }; @@ -96,8 +99,8 @@ 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` - //~| NOTE: drop(&(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 println!("{} {}", t1.1, t.1); }; @@ -111,8 +114,8 @@ 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr index 656c132c12..69c12d2bb5 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr @@ -1,25 +1,33 @@ error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:13:13 + --> $DIR/insignificant_drop.rs:15:13 | LL | let c = || { | _____________^ LL | | LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; +LL | | +... | LL | | let _t2 = t2.0; LL | | }; | |_____^ | note: the lint level is defined here - --> $DIR/insignificant_drop.rs:1:9 + --> $DIR/insignificant_drop.rs:3:9 | LL | #![deny(disjoint_capture_drop_reorder)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: drop(&(t, t1, t2)); +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; + ... error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:31:13 + --> $DIR/insignificant_drop.rs:34:13 | LL | let c = || { | _____________^ @@ -31,10 +39,18 @@ LL | | let _t2 = t2; LL | | }; | |_____^ | - = note: drop(&(t, t1)); +help: add a dummy let to cause `t`, `t1` to be fully captured + | +LL | let c = || { let _ = (&t, &t1); +LL | +LL | +LL | let _t = t.0; +LL | let _t1 = t1.0; +LL | let _t2 = t2; + ... error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:47:13 + --> $DIR/insignificant_drop.rs:50:13 | LL | let c = || { | _____________^ @@ -45,10 +61,18 @@ LL | | println!("{}", t1.1); LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | println!("{}", t1.1); +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:65:13 + --> $DIR/insignificant_drop.rs:68:13 | LL | let c = || { | _____________^ @@ -59,10 +83,18 @@ LL | | let _t1 = t1.0; LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | let _t1 = t1.0; +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:83:13 + --> $DIR/insignificant_drop.rs:86:13 | LL | let c = || { | _____________^ @@ -73,10 +105,18 @@ LL | | let _s = s.0; LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | let _s = s.0; +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:98:13 + --> $DIR/insignificant_drop.rs:101:13 | LL | let c = move || { | _____________^ @@ -86,10 +126,17 @@ LL | | println!("{} {}", t1.1, t.1); LL | | }; | |_____^ | - = note: drop(&(t1, t)); +help: add a dummy let to cause `t1`, `t` to be fully captured + | +LL | let c = move || { let _ = (&t1, &t); +LL | +LL | +LL | println!("{} {}", t1.1, t.1); +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:113:13 + --> $DIR/insignificant_drop.rs:116:13 | LL | let c = || { | _____________^ @@ -99,7 +146,14 @@ LL | | let _t = t.0; LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | }; + | error: aborting due to 7 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs new file mode 100644 index 0000000000..3a6af00254 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs @@ -0,0 +1,10 @@ +// run-pass + +#![warn(disjoint_capture_drop_reorder)] + +fn main() { + if let a = "" { + //~^ WARNING: irrefutable `if let` pattern + drop(|_: ()| drop(a)); + } +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr new file mode 100644 index 0000000000..7e5da949cb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr @@ -0,0 +1,15 @@ +warning: irrefutable `if let` pattern + --> $DIR/issue-78720.rs:6:5 + | +LL | / if let a = "" { +LL | | +LL | | drop(|_: ()| drop(a)); +LL | | } + | |_____^ + | + = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed new file mode 100644 index 0000000000..a3e51a2b8e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed @@ -0,0 +1,40 @@ +// run-rustfix +#![deny(disjoint_capture_drop_reorder)] +//~^ NOTE: the lint level is defined here + +// Test the two possible cases for automated migartion using rustfix +// - Closure contains a block i.e. `|| { .. };` +// - Closure contains just an expr `|| ..;` + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +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` + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + }; + + c(); +} + +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` + //~| HELP: add a dummy let to cause `t` to be fully captured + + c(); +} + +fn main() { + closure_contains_block(); + closure_doesnt_contain_block(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs new file mode 100644 index 0000000000..0eb837b688 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs @@ -0,0 +1,40 @@ +// run-rustfix +#![deny(disjoint_capture_drop_reorder)] +//~^ NOTE: the lint level is defined here + +// Test the two possible cases for automated migartion using rustfix +// - Closure contains a block i.e. `|| { .. };` +// - Closure contains just an expr `|| ..;` + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +fn closure_contains_block() { + let t = (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 + let _t = t.0; + }; + + c(); +} + +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` + //~| HELP: add a dummy let to cause `t` to be fully captured + + c(); +} + +fn main() { + closure_contains_block(); + closure_doesnt_contain_block(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr new file mode 100644 index 0000000000..e6173217ed --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr @@ -0,0 +1,38 @@ +error: drop order affected for closure because of `capture_disjoint_fields` + --> $DIR/migrations_rustfix.rs:19:13 + | +LL | let c = || { + | _____________^ +LL | | +LL | | +LL | | let _t = t.0; +LL | | }; + | |_____^ + | +note: the lint level is defined here + --> $DIR/migrations_rustfix.rs:2:9 + | +LL | #![deny(disjoint_capture_drop_reorder)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | }; + | + +error: drop order affected for closure because of `capture_disjoint_fields` + --> $DIR/migrations_rustfix.rs:30:13 + | +LL | let c = || t.0; + | ^^^^^^ + | +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; t.0 }; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed new file mode 100644 index 0000000000..b739035c78 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed @@ -0,0 +1,56 @@ +// run-rustfix + +#![deny(disjoint_capture_drop_reorder)] + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +struct ConstainsDropField(Foo, Foo); + +// Test that lint is triggered if a path that implements Drop is not captured by move +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 + let _t = t.0; + let _t = &t.1; + }; + + c(); +} + +struct S; +impl Drop for S { + fn drop(&mut self) { + } +} + +struct T(S, S); +struct U(T, T); + +// Test precise analysis for the lint works with paths longer than one. +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 + let _x = u.0.0; + let _x = u.0.1; + let _x = u.1.0; + }; + + c(); +} + +fn main() { + test_precise_analysis_drop_paths_not_captured_by_move(); + test_precise_analysis_long_path_missing(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs index 79702cc6b5..e1f29c9d0e 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs @@ -1,5 +1,6 @@ +// run-rustfix + #![deny(disjoint_capture_drop_reorder)] -//~^ NOTE: the lint level is defined here #[derive(Debug)] struct Foo(i32); @@ -11,35 +12,13 @@ impl Drop for Foo { struct ConstainsDropField(Foo, Foo); -#[derive(Debug)] -struct ContainsAndImplsDrop(Foo); -impl Drop for ContainsAndImplsDrop { - fn drop(&mut self) { - println!("{:?} dropped", self.0); - } -} - -// Test that even if all paths starting at root variable that implement Drop are captured, -// the lint is triggered if the root variable implements drop and isn't captured. -fn test_precise_analysis_parent_root_impl_drop_not_captured() { - let t = ContainsAndImplsDrop(Foo(10)); - - let c = || { - //~^ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| NOTE: drop(&(t)); - let _t = t.0; - }; - - c(); -} - // Test that lint is triggered if a path that implements Drop is not captured by move 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _t = &t.1; }; @@ -61,8 +40,8 @@ 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` - //~| NOTE: drop(&(u)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `u` to be fully captured let _x = u.0.0; let _x = u.0.1; let _x = u.1.0; @@ -72,7 +51,6 @@ fn test_precise_analysis_long_path_missing() { } fn main() { - test_precise_analysis_parent_root_impl_drop_not_captured(); test_precise_analysis_drop_paths_not_captured_by_move(); test_precise_analysis_long_path_missing(); } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr index 968ca395f9..7135ded13c 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr @@ -1,37 +1,32 @@ error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/precise.rs:27:13 + --> $DIR/precise.rs:19:13 | LL | let c = || { | _____________^ LL | | LL | | LL | | let _t = t.0; +LL | | let _t = &t.1; LL | | }; | |_____^ | note: the lint level is defined here - --> $DIR/precise.rs:1:9 + --> $DIR/precise.rs:3:9 | LL | #![deny(disjoint_capture_drop_reorder)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: drop(&(t)); - -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/precise.rs:40:13 +help: add a dummy let to cause `t` to be fully captured | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t = &t.1; -LL | | }; - | |_____^ +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | let _t = &t.1; +LL | }; | - = note: drop(&(t)); error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/precise.rs:63:13 + --> $DIR/precise.rs:42:13 | LL | let c = || { | _____________^ @@ -43,7 +38,15 @@ LL | | let _x = u.1.0; LL | | }; | |_____^ | - = note: drop(&(u)); +help: add a dummy let to cause `u` to be fully captured + | +LL | let c = || { let _ = &u; +LL | +LL | +LL | let _x = u.0.0; +LL | let _x = u.0.1; +LL | let _x = u.1.0; + ... -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed new file mode 100644 index 0000000000..e1b212153f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed @@ -0,0 +1,136 @@ +// run-rustfix +#![deny(disjoint_capture_drop_reorder)] +//~^ NOTE: the lint level is defined here + +// Test cases for types that implement a significant drop (user defined) + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +#[derive(Debug)] +struct ConstainsDropField(Foo, Foo); + +// `t` needs Drop because one of its elements needs drop, +// therefore precise capture might affect drop ordering +fn test1_all_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + 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 + let _t = t.0; + let _t1 = t1.0; + let _t2 = t2.0; + }; + + c(); +} + +// 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 +fn test2_only_precise_paths_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + 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 + let _t = t.0; + let _t1 = t1.0; + let _t2 = t2; + }; + + c(); +} + +// 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. +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 + let _t = t.0; + println!("{:?}", t1.1); + }; + + c(); +} + +// The root variable might not implement drop themselves but some path starting +// at the root variable might implement Drop. +// +// If this path isn't captured we need to migrate for the root variable. +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 + let _t = t.0; + }; + + c(); +} + +// 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, +// otherwise we won't need to, since we can get away with just by ref capture in that case. +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 + let _t = t.0; + }; + + c(); +} + +// 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 + let _t = t.1; + }; + + c(); +} + +// 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. +fn test7_move_closures_non_copy_types_might_need_migration() { + let t = (Foo(0), Foo(0)); + 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 + println!("{:?} {:?}", t1.1, t.1); + }; + + c(); +} + +fn main() { + test1_all_need_migration(); + test2_only_precise_paths_need_migration(); + test3_only_by_value_need_migration(); + test4_type_contains_drop_need_migration(); + test5_drop_non_drop_aggregate_need_migration(); + test6_significant_insignificant_drop_aggregate_need_migration(); + test7_move_closures_non_copy_types_might_need_migration(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs index ed5e4ea8be..106b293351 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs @@ -1,3 +1,4 @@ +// run-rustfix #![deny(disjoint_capture_drop_reorder)] //~^ NOTE: the lint level is defined here @@ -22,8 +23,8 @@ fn test1_all_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { - //~^ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| NOTE: drop(&(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 let _t = t.0; let _t1 = t1.0; let _t2 = t2.0; @@ -40,8 +41,8 @@ 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` - //~| NOTE: drop(&(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 let _t = t.0; let _t1 = t1.0; let _t2 = t2; @@ -56,8 +57,8 @@ 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; println!("{:?}", t1.1); }; @@ -73,8 +74,8 @@ 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -88,8 +89,8 @@ 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` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -98,13 +99,11 @@ fn test5_drop_non_drop_aggregate_need_migration() { // Test migration analysis in case of Significant and Insignificant Drop aggregates. fn test6_significant_insignificant_drop_aggregate_need_migration() { - struct S(i32, i32); - let t = (Foo(0), String::new()); let c = || { - //~^ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| NOTE: drop(&(t)); + //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; }; @@ -118,8 +117,8 @@ 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` - //~| NOTE: drop(&(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 println!("{:?} {:?}", t1.1, t.1); }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr index 6c21b27b49..ee29fe1306 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr @@ -1,5 +1,5 @@ error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:24:13 + --> $DIR/significant_drop.rs:25:13 | LL | let c = || { | _____________^ @@ -12,14 +12,22 @@ LL | | }; | |_____^ | note: the lint level is defined here - --> $DIR/significant_drop.rs:1:9 + --> $DIR/significant_drop.rs:2:9 | LL | #![deny(disjoint_capture_drop_reorder)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: drop(&(t, t1, t2)); +help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + | +LL | let c = || { let _ = (&t, &t1, &t2); +LL | +LL | +LL | let _t = t.0; +LL | let _t1 = t1.0; +LL | let _t2 = t2.0; + ... error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:42:13 + --> $DIR/significant_drop.rs:43:13 | LL | let c = || { | _____________^ @@ -31,10 +39,18 @@ LL | | let _t2 = t2; LL | | }; | |_____^ | - = note: drop(&(t, t1)); +help: add a dummy let to cause `t`, `t1` to be fully captured + | +LL | let c = || { let _ = (&t, &t1); +LL | +LL | +LL | let _t = t.0; +LL | let _t1 = t1.0; +LL | let _t2 = t2; + ... error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:58:13 + --> $DIR/significant_drop.rs:59:13 | LL | let c = || { | _____________^ @@ -45,10 +61,18 @@ LL | | println!("{:?}", t1.1); LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | println!("{:?}", t1.1); +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:75:13 + --> $DIR/significant_drop.rs:76:13 | LL | let c = || { | _____________^ @@ -58,10 +82,17 @@ LL | | let _t = t.0; LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:90:13 + --> $DIR/significant_drop.rs:91:13 | LL | let c = || { | _____________^ @@ -71,10 +102,17 @@ LL | | let _t = t.0; LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.0; +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:105:13 + --> $DIR/significant_drop.rs:104:13 | LL | let c = || { | _____________^ @@ -84,10 +122,17 @@ LL | | let _t = t.1; LL | | }; | |_____^ | - = note: drop(&(t)); +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; +LL | +LL | +LL | let _t = t.1; +LL | }; + | error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:120:13 + --> $DIR/significant_drop.rs:119:13 | LL | let c = move || { | _____________^ @@ -97,7 +142,14 @@ LL | | println!("{:?} {:?}", t1.1, t.1); LL | | }; | |_____^ | - = note: drop(&(t1, t)); +help: add a dummy let to cause `t1`, `t` to be fully captured + | +LL | let c = move || { let _ = (&t1, &t); +LL | +LL | +LL | println!("{:?} {:?}", t1.1, t.1); +LL | }; + | error: aborting due to 7 previous errors diff --git a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr index 48f18b1ebe..273eae9955 100644 --- a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr +++ b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -9,8 +9,8 @@ LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static { | help: consider further restricting this bound | -LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + Send { - | ^^^^^^ +LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + std::marker::Send { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr index d649eeccb8..7df29d5a09 100644 --- a/src/test/ui/closures/closure-bounds-subtype.stderr +++ b/src/test/ui/closures/closure-bounds-subtype.stderr @@ -9,8 +9,8 @@ LL | take_const_owned(f); | help: consider further restricting this bound | -LL | fn give_owned<F>(f: F) where F: FnOnce() + Send + Sync { - | ^^^^^^ +LL | fn give_owned<F>(f: F) where F: FnOnce() + Send + std::marker::Sync { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-84128.rs b/src/test/ui/closures/issue-84128.rs new file mode 100644 index 0000000000..f81d7cfaa6 --- /dev/null +++ b/src/test/ui/closures/issue-84128.rs @@ -0,0 +1,16 @@ +// test for issue 84128 +// missing suggestion for similar ADT type with diffetent generic paramenter +// on closure ReturnNoExpression + +struct Foo<T>(T); + +fn main() { + || { + if false { + return Foo(0); + } + + Foo(()) + //~^ ERROR mismatched types [E0308] + }; +} diff --git a/src/test/ui/closures/issue-84128.stderr b/src/test/ui/closures/issue-84128.stderr new file mode 100644 index 0000000000..70d9273ddf --- /dev/null +++ b/src/test/ui/closures/issue-84128.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-84128.rs:13:13 + | +LL | Foo(()) + | ^^ expected integer, found `()` + | +note: return type inferred to be `{integer}` here + --> $DIR/issue-84128.rs:10:20 + | +LL | return Foo(0); + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr index de2ffc2e5d..aff51ee9e2 100644 --- a/src/test/ui/codemap_tests/two_files.stderr +++ b/src/test/ui/codemap_tests/two_files.stderr @@ -5,10 +5,9 @@ LL | impl Bar for Baz { } | ^^^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/two_files_data.rs:5:1 | -LL | type Bar = dyn Foo; - | ^^^^^^^^^^^^^^^^^^^ +LL | trait Bar = dyn Foo; + | error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index b7ba4fa46d..357dd25389 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́` LL | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted + = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/unicode_2.rs b/src/test/ui/codemap_tests/unicode_2.rs index fa69115b2d..3301e7a18d 100644 --- a/src/test/ui/codemap_tests/unicode_2.rs +++ b/src/test/ui/codemap_tests/unicode_2.rs @@ -1,5 +1,3 @@ -#![feature(non_ascii_idents)] - fn main() { let _ = ("a̐éö̲", 0u7); //~ ERROR invalid width let _ = ("아あ", 1i42); //~ ERROR invalid width diff --git a/src/test/ui/codemap_tests/unicode_2.stderr b/src/test/ui/codemap_tests/unicode_2.stderr index c01942712d..a776a4a1e7 100644 --- a/src/test/ui/codemap_tests/unicode_2.stderr +++ b/src/test/ui/codemap_tests/unicode_2.stderr @@ -1,5 +1,5 @@ error: invalid width `7` for integer literal - --> $DIR/unicode_2.rs:4:25 + --> $DIR/unicode_2.rs:2:25 | LL | let _ = ("a̐éö̲", 0u7); | ^^^ @@ -7,7 +7,7 @@ LL | let _ = ("a̐éö̲", 0u7); = help: valid widths are 8, 16, 32, 64 and 128 error: invalid width `42` for integer literal - --> $DIR/unicode_2.rs:5:20 + --> $DIR/unicode_2.rs:3:20 | LL | let _ = ("아あ", 1i42); | ^^^^ @@ -15,7 +15,7 @@ LL | let _ = ("아あ", 1i42); = help: valid widths are 8, 16, 32, 64 and 128 error[E0425]: cannot find value `a̐é` in this scope - --> $DIR/unicode_2.rs:6:13 + --> $DIR/unicode_2.rs:4:13 | LL | let _ = a̐é; | ^^ not found in this scope diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr index e95826ed4d..9156972a1d 100644 --- a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr +++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait`: +error[E0119]: conflicting implementations of trait `MyTrait` --> $DIR/coherence-blanket-conflicts-with-blanket-implemented.rs:24:1 | LL | impl<T:Even> MyTrait for T { diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr index ea9838b452..8400968e12 100644 --- a/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr +++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait`: +error[E0119]: conflicting implementations of trait `MyTrait` --> $DIR/coherence-blanket-conflicts-with-blanket-unimplemented.rs:20:1 | LL | impl<T:Even> MyTrait for T { diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr index a2008f0426..c25c436929 100644 --- a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr +++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `go_trait::GoMut` for type `MyThingy`: +error[E0119]: conflicting implementations of trait `go_trait::GoMut` for type `MyThingy` --> $DIR/coherence-blanket-conflicts-with-specific-cross-crate.rs:15:1 | LL | impl GoMut for MyThingy { diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr index af4f4d09d7..c2a925213d 100644 --- a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr +++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait<MyType>` for type `MyType`: +error[E0119]: conflicting implementations of trait `MyTrait<MyType>` for type `MyType` --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:22:1 | LL | impl<T> MyTrait<T> for T { diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr index 6922f3ebff..e1a5dffebd 100644 --- a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr +++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType` --> $DIR/coherence-blanket-conflicts-with-specific-trait.rs:20:1 | LL | impl<T:OtherTrait> MyTrait for T { diff --git a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.stderr b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.stderr index 4bc2827647..ba60a2ea92 100644 --- a/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.stderr +++ b/src/test/ui/coherence/coherence-blanket-conflicts-with-specific.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType` --> $DIR/coherence-blanket-conflicts-with-specific.rs:19:1 | LL | impl<T> MyTrait for T { diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr index 4d9f815c79..5295170cd8 100644 --- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr @@ -7,7 +7,7 @@ LL | LL | impl<T: MyTrait> !Send for TestType<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`: +error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>` --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1 | LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {} diff --git a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr index 827d26ab43..d0d86c72ff 100644 --- a/src/test/ui/coherence/coherence-cross-crate-conflict.stderr +++ b/src/test/ui/coherence/coherence-cross-crate-conflict.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize`: +error[E0119]: conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize` --> $DIR/coherence-cross-crate-conflict.rs:9:1 | LL | impl<A> Foo for A { diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr index 49271edf8e..7dabd97b94 100644 --- a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -1,4 +1,4 @@ -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(fn(&'r ()))` --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1 | LL | impl Trait for for<'r> fn(fn(&'r ())) {} diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr index a3e7f0bcde..c8accc9974 100644 --- a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr @@ -1,4 +1,4 @@ -error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`: +error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32` --> $DIR/coherence-fn-implied-bounds.rs:21:1 | LL | impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} diff --git a/src/test/ui/coherence/coherence-fn-inputs.stderr b/src/test/ui/coherence/coherence-fn-inputs.stderr index 56ab873a39..82bd8a35f4 100644 --- a/src/test/ui/coherence/coherence-fn-inputs.stderr +++ b/src/test/ui/coherence/coherence-fn-inputs.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`: +error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)` --> $DIR/coherence-fn-inputs.rs:15:1 | LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr index 97aa491272..c249fa43c3 100644 --- a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr @@ -1,4 +1,4 @@ -error: conflicting implementations of trait `TheTrait` for type `fn(&u8)`: +error: conflicting implementations of trait `TheTrait` for type `fn(&u8)` --> $DIR/coherence-free-vs-bound-region.rs:16:1 | LL | impl<'a> TheTrait for fn(&'a u8) {} diff --git a/src/test/ui/coherence/coherence-impls-copy.stderr b/src/test/ui/coherence/coherence-impls-copy.stderr index 8cc24f099e..2ac0706d72 100644 --- a/src/test/ui/coherence/coherence-impls-copy.stderr +++ b/src/test/ui/coherence/coherence-impls-copy.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`: +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32` --> $DIR/coherence-impls-copy.rs:5:1 | LL | impl Copy for i32 {} @@ -7,7 +7,7 @@ LL | impl Copy for i32 {} = note: conflicting implementation in crate `core`: - impl Copy for i32; -error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`: +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync` --> $DIR/coherence-impls-copy.rs:29:1 | LL | impl Copy for &'static NotSync {} @@ -17,7 +17,7 @@ LL | impl Copy for &'static NotSync {} - impl<T> Copy for &T where T: ?Sized; -error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`: +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]` --> $DIR/coherence-impls-copy.rs:34:1 | LL | impl Copy for &'static [NotSync] {} diff --git a/src/test/ui/coherence/coherence-impls-send.stderr b/src/test/ui/coherence/coherence-impls-send.stderr index edca31b5da..46e9e7e986 100644 --- a/src/test/ui/coherence/coherence-impls-send.stderr +++ b/src/test/ui/coherence/coherence-impls-send.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::marker::Send` for type `&[NotSync]`: +error[E0119]: conflicting implementations of trait `std::marker::Send` for type `&[NotSync]` --> $DIR/coherence-impls-send.rs:25:1 | LL | unsafe impl Send for &'static [NotSync] {} diff --git a/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr index a74ffbb3af..8a43ad7b7f 100644 --- a/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr +++ b/src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait`: +error[E0119]: conflicting implementations of trait `MyTrait` --> $DIR/coherence-no-direct-lifetime-dispatch.rs:6:1 | LL | impl<T> MyTrait for T {} diff --git a/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.stderr b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.stderr index 5e8bfbcc3c..6a0880334b 100644 --- a/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.stderr +++ b/src/test/ui/coherence/coherence-overlap-all-t-and-tuple.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `From<(_,)>` for type `(_,)`: +error[E0119]: conflicting implementations of trait `From<(_,)>` for type `(_,)` --> $DIR/coherence-overlap-all-t-and-tuple.rs:16:1 | LL | impl <T> From<T> for T { diff --git a/src/test/ui/coherence/coherence-overlap-downstream.stderr b/src/test/ui/coherence/coherence-overlap-downstream.stderr index 6fb398562d..9ab099489d 100644 --- a/src/test/ui/coherence/coherence-overlap-downstream.stderr +++ b/src/test/ui/coherence/coherence-overlap-downstream.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Sweet`: +error[E0119]: conflicting implementations of trait `Sweet` --> $DIR/coherence-overlap-downstream.rs:8:1 | LL | impl<T:Sugar> Sweet for T { } @@ -6,7 +6,7 @@ LL | impl<T:Sugar> Sweet for T { } LL | impl<T:Fruit> Sweet for T { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32`: +error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` --> $DIR/coherence-overlap-downstream.rs:14:1 | LL | impl<X, T> Foo<X> for T where T: Bar<X> {} diff --git a/src/test/ui/coherence/coherence-overlap-issue-23516.stderr b/src/test/ui/coherence/coherence-overlap-issue-23516.stderr index fe4c5cf349..85eb189e10 100644 --- a/src/test/ui/coherence/coherence-overlap-issue-23516.stderr +++ b/src/test/ui/coherence/coherence-overlap-issue-23516.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Sweet` for type `std::boxed::Box<_>`: +error[E0119]: conflicting implementations of trait `Sweet` for type `std::boxed::Box<_>` --> $DIR/coherence-overlap-issue-23516.rs:8:1 | LL | impl<T:Sugar> Sweet for T { } diff --git a/src/test/ui/coherence/coherence-overlap-messages.stderr b/src/test/ui/coherence/coherence-overlap-messages.stderr index 28147f52fa..5a97296eeb 100644 --- a/src/test/ui/coherence/coherence-overlap-messages.stderr +++ b/src/test/ui/coherence/coherence-overlap-messages.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Foo`: +error[E0119]: conflicting implementations of trait `Foo` --> $DIR/coherence-overlap-messages.rs:4:1 | LL | impl<T> Foo for T {} @@ -6,7 +6,7 @@ LL | impl<T> Foo for T {} LL | impl<U> Foo for U {} | ^^^^^^^^^^^^^^^^^ conflicting implementation -error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)`: +error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)` --> $DIR/coherence-overlap-messages.rs:11:1 | LL | impl<T> Bar for (T, u8) {} @@ -14,7 +14,7 @@ LL | impl<T> Bar for (T, u8) {} LL | impl<T> Bar for (u8, T) {} | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)` -error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8`: +error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8` --> $DIR/coherence-overlap-messages.rs:17:1 | LL | impl<T> Baz<u8> for T {} @@ -22,7 +22,7 @@ LL | impl<T> Baz<u8> for T {} LL | impl<T> Baz<T> for u8 {} | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8` -error[E0119]: conflicting implementations of trait `Quux<_, _>`: +error[E0119]: conflicting implementations of trait `Quux<_, _>` --> $DIR/coherence-overlap-messages.rs:23:1 | LL | impl<T, U, V> Quux<U, V> for T {} @@ -30,7 +30,7 @@ LL | impl<T, U, V> Quux<U, V> for T {} LL | impl<T, U> Quux<U, U> for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error[E0119]: conflicting implementations of trait `Quux<_, _>`: +error[E0119]: conflicting implementations of trait `Quux<_, _>` --> $DIR/coherence-overlap-messages.rs:25:1 | LL | impl<T, U, V> Quux<U, V> for T {} diff --git a/src/test/ui/coherence/coherence-overlap-upstream.stderr b/src/test/ui/coherence/coherence-overlap-upstream.stderr index 8d3de9a243..8272c88758 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Foo` for type `i16`: +error[E0119]: conflicting implementations of trait `Foo` for type `i16` --> $DIR/coherence-overlap-upstream.rs:13:1 | LL | impl<T> Foo for T where T: Remote {} diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr index 06a840255b..51f6faab3c 100644 --- a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr +++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32`: +error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32` --> $DIR/coherence-projection-conflict-orphan.rs:16:1 | LL | impl Foo<i32> for i32 { } diff --git a/src/test/ui/coherence/coherence-projection-conflict-ty-param.stderr b/src/test/ui/coherence/coherence-projection-conflict-ty-param.stderr index c5c9b0ac33..85d3d358f8 100644 --- a/src/test/ui/coherence/coherence-projection-conflict-ty-param.stderr +++ b/src/test/ui/coherence/coherence-projection-conflict-ty-param.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Foo<_>` for type `std::option::Option<_>`: +error[E0119]: conflicting implementations of trait `Foo<_>` for type `std::option::Option<_>` --> $DIR/coherence-projection-conflict-ty-param.rs:10:1 | LL | impl <P, T: Foo<P>> Foo<P> for Option<T> {} diff --git a/src/test/ui/coherence/coherence-projection-conflict.stderr b/src/test/ui/coherence/coherence-projection-conflict.stderr index aed6910b52..e7d1fb2934 100644 --- a/src/test/ui/coherence/coherence-projection-conflict.stderr +++ b/src/test/ui/coherence/coherence-projection-conflict.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32`: +error[E0119]: conflicting implementations of trait `Foo<i32>` for type `i32` --> $DIR/coherence-projection-conflict.rs:11:1 | LL | impl Foo<i32> for i32 { } diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr index 7f751a24c7..6f95f0a06b 100644 --- a/src/test/ui/coherence/coherence-subtyping.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -1,4 +1,4 @@ -warning: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: +warning: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` --> $DIR/coherence-subtyping.rs:15:1 | LL | impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} diff --git a/src/test/ui/coherence/coherence-tuple-conflict.stderr b/src/test/ui/coherence/coherence-tuple-conflict.stderr index f6c2bc32aa..09ad5e5b22 100644 --- a/src/test/ui/coherence/coherence-tuple-conflict.stderr +++ b/src/test/ui/coherence/coherence-tuple-conflict.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `(_, _)`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `(_, _)` --> $DIR/coherence-tuple-conflict.rs:15:1 | LL | impl<T> MyTrait for (T,T) { diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.stderr b/src/test/ui/coherence/coherence-wasm-bindgen.stderr index c77483bb84..432646e532 100644 --- a/src/test/ui/coherence/coherence-wasm-bindgen.stderr +++ b/src/test/ui/coherence/coherence-wasm-bindgen.stderr @@ -1,4 +1,4 @@ -error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn std::ops::Fn(&_) -> _`: +error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn std::ops::Fn(&_) -> _` --> $DIR/coherence-wasm-bindgen.rs:28:1 | LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr index cf6c6fb8c7..db73065018 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyFundamentalStruct<(MyType,)>`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyFundamentalStruct<(MyType,)>` --> $DIR/coherence_copy_like_err_fundamental_struct_tuple.rs:16:1 | LL | impl<T: lib::MyCopy> MyTrait for T { } diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.stderr index cf79e851bf..3bc3dffda5 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_struct.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_struct.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyStruct<MyType>`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `lib::MyStruct<MyType>` --> $DIR/coherence_copy_like_err_struct.rs:19:1 | LL | impl<T: lib::MyCopy> MyTrait for T { } diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.stderr index 52f66427df..090497ec18 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_tuple.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `(MyType,)`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `(MyType,)` --> $DIR/coherence_copy_like_err_tuple.rs:18:1 | LL | impl<T: lib::MyCopy> MyTrait for T { } diff --git a/src/test/ui/command-line-diagnostics.stderr b/src/test/ui/command-line-diagnostics.stderr index b3f8d8a643..6223ad880d 100644 --- a/src/test/ui/command-line-diagnostics.stderr +++ b/src/test/ui/command-line-diagnostics.stderr @@ -5,7 +5,7 @@ LL | let x = 42; | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x = 43; | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/command/command-setgroups.rs b/src/test/ui/command/command-setgroups.rs index 2067314f74..aff67f91bb 100644 --- a/src/test/ui/command/command-setgroups.rs +++ b/src/test/ui/command/command-setgroups.rs @@ -1,6 +1,5 @@ // run-pass // ignore-windows - this is a unix-specific test -// ignore-cloudabi // ignore-emscripten // ignore-sgx // ignore-musl - returns dummy result for _SC_NGROUPS_MAX diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs index 020c3ff3c7..5a6465bd06 100644 --- a/src/test/ui/commandline-argfile-missing.rs +++ b/src/test/ui/commandline-argfile-missing.rs @@ -1,6 +1,5 @@ // Check to see if we can get parameters from an @argsfile file // -// ignore-tidy-linelength // normalize-stderr-test: "os error \d+" -> "os error $$ERR" // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args diff --git a/src/test/ui/compare-method/bad-self-type.rs b/src/test/ui/compare-method/bad-self-type.rs new file mode 100644 index 0000000000..f42a9e49ab --- /dev/null +++ b/src/test/ui/compare-method/bad-self-type.rs @@ -0,0 +1,26 @@ +use std::future::Future; +use std::task::{Context, Poll}; + +fn main() {} + +struct MyFuture {} + +impl Future for MyFuture { + type Output = (); + fn poll(self, _: &mut Context<'_>) -> Poll<()> { + //~^ ERROR method `poll` has an incompatible type for trait + todo!() + } +} + +trait T { + fn foo(self); + fn bar(self) -> Option<()>; +} + +impl T for MyFuture { + fn foo(self: Box<Self>) {} + //~^ ERROR method `foo` has an incompatible type for trait + fn bar(self) {} + //~^ ERROR method `bar` has an incompatible type for trait +} diff --git a/src/test/ui/compare-method/bad-self-type.stderr b/src/test/ui/compare-method/bad-self-type.stderr new file mode 100644 index 0000000000..76f91fbf24 --- /dev/null +++ b/src/test/ui/compare-method/bad-self-type.stderr @@ -0,0 +1,46 @@ +error[E0053]: method `poll` has an incompatible type for trait + --> $DIR/bad-self-type.rs:10:13 + | +LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> { + | ^^^^ + | | + | expected struct `Pin`, found struct `MyFuture` + | help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>` + | + = note: expected fn pointer `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>` + found fn pointer `fn(MyFuture, &mut Context<'_>) -> Poll<_>` + +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/bad-self-type.rs:22:18 + | +LL | fn foo(self); + | ---- type in trait +... +LL | fn foo(self: Box<Self>) {} + | ------^^^^^^^^^ + | | | + | | expected struct `MyFuture`, found struct `Box` + | help: change the self-receiver type to match the trait: `self` + | + = note: expected fn pointer `fn(MyFuture)` + found fn pointer `fn(Box<MyFuture>)` + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/bad-self-type.rs:24:18 + | +LL | fn bar(self) -> Option<()>; + | ---------- type in trait +... +LL | fn bar(self) {} + | ^ expected enum `Option`, found `()` + | + = note: expected fn pointer `fn(MyFuture) -> Option<()>` + found fn pointer `fn(MyFuture)` +help: change the output type to match the trait + | +LL | fn bar(self) -> Option<()> {} + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index f1f8a663f2..d581628ea4 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -5,8 +5,10 @@ LL | fn b<C:Clone,D>(&self, x: C) -> C; | - type in trait ... LL | fn b<F:Clone,G>(&self, _x: G) -> G { panic!() } - | - - ^ expected type parameter `F`, found type parameter `G` - | | | + | - - ^ + | | | | + | | | expected type parameter `F`, found type parameter `G` + | | | help: change the parameter type to match the trait: `F` | | found type parameter | expected type parameter | diff --git a/src/test/ui/const-generics/const-argument-if-length.full.stderr b/src/test/ui/const-generics/const-argument-if-length.full.stderr index 5dca01f0dc..c6088e665a 100644 --- a/src/test/ui/const-generics/const-argument-if-length.full.stderr +++ b/src/test/ui/const-generics/const-argument-if-length.full.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/const-argument-if-length.rs:7:28 | LL | pub const fn is_zst<T: ?Sized>() -> usize { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | if std::mem::size_of::<T>() == 0 { | ^ doesn't have a size known at compile-time | @@ -15,7 +15,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/const-argument-if-length.rs:16:12 | LL | pub struct AtLeastByte<T: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | value: T, | ^ doesn't have a size known at compile-time | diff --git a/src/test/ui/const-generics/const-argument-if-length.min.stderr b/src/test/ui/const-generics/const-argument-if-length.min.stderr index ea177c1974..bc06e8d7fb 100644 --- a/src/test/ui/const-generics/const-argument-if-length.min.stderr +++ b/src/test/ui/const-generics/const-argument-if-length.min.stderr @@ -11,7 +11,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/const-argument-if-length.rs:16:12 | LL | pub struct AtLeastByte<T: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | value: T, | ^ doesn't have a size known at compile-time | diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr index 1beb5315d1..84b2665d5b 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr @@ -3,48 +3,52 @@ error: unconstrained generic constant | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:10 | LL | [u8; std::mem::size_of::<T>() - 1]: Sized, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: unconstrained generic constant --> $DIR/cross_crate_predicate.rs:7:13 | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:4:27 | LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: unconstrained generic constant --> $DIR/cross_crate_predicate.rs:7:13 | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:10 | LL | [u8; std::mem::size_of::<T>() - 1]: Sized, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: unconstrained generic constant --> $DIR/cross_crate_predicate.rs:7:13 | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:4:27 | LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr index 8cdc9b5775..7c11a47b2f 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr @@ -4,11 +4,7 @@ error: unconstrained generic constant LL | [0; size_of::<Foo<T>>()] | ^^^^^^^^^^^^^^^^^^^ | -help: try adding a `where` bound using this expression: `where [u8; size_of::<Foo<T>>()]: Sized` - --> $DIR/different-fn.rs:10:9 - | -LL | [0; size_of::<Foo<T>>()] - | ^^^^^^^^^^^^^^^^^^^ + = help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:` error: aborting due to previous error diff --git a/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs b/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs new file mode 100644 index 0000000000..92a410afcb --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(const_generics)] +#![feature(const_evaluatable_checked)] +#![allow(incomplete_features)] + +// This test is a repro for #82279. It checks that we don't error +// when calling is_const_evaluatable on `std::mem::size_of::<T>()` +// when looking for candidates that may prove `T: Foo` in `foo` + +trait Foo {} + +#[allow(dead_code)] +fn foo<T: Foo>() {} + +impl<T> Foo for T where [(); std::mem::size_of::<T>()]: {} + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs new file mode 100644 index 0000000000..6514409698 --- /dev/null +++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -0,0 +1,15 @@ +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +pub struct Defaulted<const N: usize=3>; +impl Defaulted { + pub fn new() -> Self { + Defaulted + } +} +impl<const N: usize> Defaulted<N> { + pub fn value(&self) -> usize { + N + } +} 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 new file mode 100644 index 0000000000..e0e2b6c69f --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr @@ -0,0 +1,18 @@ +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 + diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr new file mode 100644 index 0000000000..58abd8db9f --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:6:47 + | +LL | struct Foo<const N: usize, const M: usize = { N + 1 }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = 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/complex-generic-default-expr.rs:10:62 + | +LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T); + | ^ 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: aborting due to 2 previous errors + diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs new file mode 100644 index 0000000000..a7b712f7b4 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -0,0 +1,14 @@ +// revisions: full min +#![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 + +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 + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.rs b/src/test/ui/const-generics/defaults/complex-unord-param.rs index 82b3627d22..d24e403e01 100644 --- a/src/test/ui/const-generics/defaults/complex-unord-param.rs +++ b/src/test/ui/const-generics/defaults/complex-unord-param.rs @@ -6,16 +6,16 @@ #![allow(dead_code)] struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { - //[min]~^ ERROR type parameters must be declared prior to const parameters - args: &'a [&'a [T; M]; N], - specifier: A, + //[min]~^ ERROR type parameters must be declared prior to const parameters + args: &'a [&'a [T; M]; N], + specifier: A, } fn main() { - let array = [1, 2, 3]; - let nest = [&array]; - let _ = NestedArrays { - args: &nest, - specifier: true, - }; + let array = [1, 2, 3]; + let nest = [&array]; + let _ = NestedArrays { + args: &nest, + specifier: true, + }; } diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs new file mode 100644 index 0000000000..4fa21b8b1f --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -0,0 +1,30 @@ +// run-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + + +pub struct ConstDefault<const N: usize = 3>; + +impl<const N: usize> ConstDefault<N> { + fn foo(self) -> usize { + N + } +} + +impl ConstDefault { + fn new() -> Self { + ConstDefault + } + + fn bar(self) {} +} + +pub fn main() { + let s = ConstDefault::new(); + assert_eq!(s.foo(), 3); + + let w = ConstDefault::<3>; + w.bar(); +} diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs new file mode 100644 index 0000000000..59ac261f44 --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs @@ -0,0 +1,23 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo<const N: usize, const M: usize = N>([u8; N], [u8; M]); + +fn foo<const N: usize>() -> Foo<N> { + let x = [0; N]; + Foo(x, x) +} + +// To check that we actually apply the correct substs for const param defaults. +fn concrete_foo() -> Foo<13> { + Foo(Default::default(), Default::default()) +} + + +fn main() { + let val = foo::<13>(); + assert_eq!(val.0, val.1); + + let val = concrete_foo(); + assert_eq!(val.0, val.1); +} diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs new file mode 100644 index 0000000000..3f534ca030 --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo<const N: usize, T = [u8; N]>(T); + +impl<const N: usize> Foo<N> { + fn new() -> Self { + Foo([0; N]) + } +} + +fn main() { + assert_eq!(Foo::new().0, [0; 10]); +} diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs new file mode 100644 index 0000000000..3febb7cffb --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-annotation.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(staged_api)] + +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +#![stable(feature = "const_default_test", since="none")] + + +#[unstable(feature = "const_default_stable", issue="none")] +pub struct ConstDefaultUnstable<const N: usize = 3>; + +#[stable(feature = "const_default_unstable", since="none")] +pub struct ConstDefaultStable<const N: usize = { + #[stable(feature = "const_default_unstable_val", since="none")] + 3 +}>; + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-on-impl.full.stderr b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr new file mode 100644 index 0000000000..c417a26842 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:8:12 + | +LL | impl<const N: usize = 1> Foo<N> {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/default-on-impl.min.stderr b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr new file mode 100644 index 0000000000..c417a26842 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:8:12 + | +LL | impl<const N: usize = 1> Foo<N> {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs new file mode 100644 index 0000000000..735549defe --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo<const N: usize>; + +impl<const N: usize = 1> Foo<N> {} +//~^ ERROR defaults for const parameters are only allowed + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs new file mode 100644 index 0000000000..4bb56c6a1c --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -0,0 +1,5 @@ +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo<const N: u8 = { 255 + 1 }>; +//~^ ERROR evaluation of constant value failed +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr new file mode 100644 index 0000000000..8464ea98bf --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/default-param-wf-concrete.rs:3:28 + | +LL | struct Foo<const N: u8 = { 255 + 1 }>; + | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs new file mode 100644 index 0000000000..32acf567cf --- /dev/null +++ b/src/test/ui/const-generics/defaults/external.rs @@ -0,0 +1,29 @@ +// aux-build:const_defaulty.rs +// check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +extern crate const_defaulty; +use const_defaulty::Defaulted; + +struct Local<const N: usize=4>; +impl Local { + fn new() -> Self { + Local + } +} +impl<const N: usize>Local<N> { + fn value(&self) -> usize { + N + } +} + +fn main() { + let v = Defaulted::new(); + assert_eq!(v.value(), 3); + + let l = Local::new(); + assert_eq!(l.value(), 4); +} diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr index c4a666a829..29d835e36c 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr @@ -1,5 +1,5 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:28 + --> $DIR/intermixed-lifetime.rs:7:28 | LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T); | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>` diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr index 69a490978d..985e7b655e 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr @@ -1,26 +1,14 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:28 + --> $DIR/intermixed-lifetime.rs:7:28 | LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T); - | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` + | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:32 - | -LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T); - | ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: lifetime parameters must be declared prior to const parameters +error: lifetime parameters must be declared prior to type parameters --> $DIR/intermixed-lifetime.rs:10:37 | LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T); - | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:10:28 - | -LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T); - | -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` + | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs index 9e83bf92a5..307e3aaf1f 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -1,15 +1,13 @@ -// revisions: full min // Checks that lifetimes cannot be interspersed between consts and types. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] struct Foo<const N: usize, 'a, T = u32>(&'a (), T); //~^ Error lifetime parameters must be declared prior to const parameters -//[min]~^^ Error type parameters must be declared prior to const parameters struct Bar<const N: usize, T = u32, 'a>(&'a (), T); -//[full]~^ Error lifetime parameters must be declared prior to type parameters -//[min]~^^ Error type parameters must be declared prior to const parameters -//[min]~| Error lifetime parameters must be declared prior to const parameters +//~^ Error lifetime parameters must be declared prior to type parameters fn main() {} diff --git a/src/test/ui/const-generics/defaults/mismatch.full.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr new file mode 100644 index 0000000000..be4f364d8e --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.full.stderr @@ -0,0 +1,52 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:12:28 + | +LL | let e: Example::<13> = (); + | ------------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:14:34 + | +LL | let e: Example2::<u32, 13> = (); + | ------------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:16:34 + | +LL | let e: Example3::<13, u32> = (); + | ------------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:18:28 + | +LL | let e: Example3::<7> = (); + | ------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7_usize>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:22:28 + | +LL | let e: Example4::<7> = (); + | ------------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr new file mode 100644 index 0000000000..be4f364d8e --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.min.stderr @@ -0,0 +1,52 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:12:28 + | +LL | let e: Example::<13> = (); + | ------------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:14:34 + | +LL | let e: Example2::<u32, 13> = (); + | ------------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:16:34 + | +LL | let e: Example3::<13, u32> = (); + | ------------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:18:28 + | +LL | let e: Example3::<7> = (); + | ------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7_usize>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:22:28 + | +LL | let e: Example4::<7> = (); + | ------------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs new file mode 100644 index 0000000000..68a640c0a0 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.rs @@ -0,0 +1,24 @@ +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +pub struct Example<const N: usize=13>; +pub struct Example2<T=u32, const N: usize=13>(T); +pub struct Example3<const N: usize=13, T=u32>(T); +pub struct Example4<const N: usize=13, const M: usize=4>; + +fn main() { + let e: Example::<13> = (); + //~^ Error: mismatched types + let e: Example2::<u32, 13> = (); + //~^ Error: mismatched types + let e: Example3::<13, u32> = (); + //~^ Error: mismatched types + let e: Example3::<7> = (); + //~^ Error: mismatched types + // FIXME(const_generics_defaults): There should be a note for the error below, but it is + // missing. + let e: Example4::<7> = (); + //~^ Error: mismatched types +} diff --git a/src/test/ui/const-generics/defaults/needs-feature.rs b/src/test/ui/const-generics/defaults/needs-feature.rs index 7eb7764a64..b58dee0712 100644 --- a/src/test/ui/const-generics/defaults/needs-feature.rs +++ b/src/test/ui/const-generics/defaults/needs-feature.rs @@ -10,5 +10,5 @@ struct A<const N: usize, T=u32>(T); //[min]~^ ERROR type parameters must be declared prior fn main() { - let _: A<3> = A(0); + let _: A<3> = A(0); } diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs new file mode 100644 index 0000000000..7a57950dfc --- /dev/null +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -0,0 +1,13 @@ +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +trait Foo<const KIND: bool = true> {} + +fn foo<const SIZE: usize = 5>() {} + +struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = FROM>; diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout new file mode 100644 index 0000000000..f549993c41 --- /dev/null +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -0,0 +1,20 @@ +#![feature(prelude_import)] +#![no_std] +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +trait Foo<const KIND : bool = true> { } + +fn foo<const SIZE : usize = 5>() { } + +struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize = + FROM>; diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs new file mode 100644 index 0000000000..c64c2974c8 --- /dev/null +++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -0,0 +1,14 @@ +// Regression test for #82792. + +// run-pass + +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +#[repr(C)] +pub struct Loaf<T: Sized, const N: usize = 1> { + head: [T; N], + slice: [T], +} + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr deleted file mode 100644 index 0746c64ac8..0000000000 --- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: type parameters must be declared prior to const parameters - --> $DIR/simple-defaults.rs:8:40 - | -LL | struct FixedOutput<'a, const N: usize, T=u32> { - | ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs index 1f1b6c2260..c003cb2c5a 100644 --- a/src/test/ui/const-generics/defaults/simple-defaults.rs +++ b/src/test/ui/const-generics/defaults/simple-defaults.rs @@ -1,17 +1,17 @@ -// [full] run-pass -// revisions: min full -// Checks some basic test cases for defaults. +// run-pass +// Checks that type param defaults are allowed after const params. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] #![allow(dead_code)] struct FixedOutput<'a, const N: usize, T=u32> { - //[min]~^ ERROR type parameters must be declared prior to const parameters - out: &'a [T; N], + out: &'a [T; N], } trait FixedOutputter { - fn out(&self) -> FixedOutput<'_, 10>; + fn out(&self) -> FixedOutput<'_, 10>; } fn main() {} diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs new file mode 100644 index 0000000000..e68075ee3c --- /dev/null +++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs @@ -0,0 +1,19 @@ +// check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +struct N; + +struct Foo<const N: usize = 1, T = N>(T); + +impl Foo { + fn new() -> Self { + Foo(N) + } +} + +fn main() { + let Foo::<1, N>(N) = Foo::new(); +} diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr index 96deb4a8b5..eb0bcb2821 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr @@ -1,19 +1,8 @@ -error: type parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 +error: generic parameters with a default must be trailing + --> $DIR/wrong-order.rs:6:10 | LL | struct A<T = u32, const N: usize> { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted - -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wrong-order.rs:2:27 - | -LL | #![cfg_attr(full, feature(const_generics))] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr index b19da76f41..eb0bcb2821 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr @@ -1,10 +1,8 @@ -error: type parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 +error: generic parameters with a default must be trailing + --> $DIR/wrong-order.rs:6:10 | LL | struct A<T = u32, const N: usize> { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index 4f1c05011b..88e9e96ba4 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -1,8 +1,10 @@ // revisions: full min -#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] struct A<T = u32, const N: usize> { - //~^ ERROR type parameters with a default must be trailing + //~^ ERROR generic parameters with a default must be trailing arg: T, } diff --git a/src/test/ui/const-generics/diagnostics.stderr b/src/test/ui/const-generics/diagnostics.stderr index 7d038ff955..c8ee6ad61e 100644 --- a/src/test/ui/const-generics/diagnostics.stderr +++ b/src/test/ui/const-generics/diagnostics.stderr @@ -31,9 +31,12 @@ error[E0747]: type provided when a constant was expected --> $DIR/diagnostics.rs:12:19 | LL | impl<N> Foo for B<N> {} - | - ^ - | | - | help: consider changing this type paramater to a `const`-generic: `const N: u8` + | ^ + | +help: consider changing this type parameter to be a `const` generic + | +LL | impl<const N: u8> Foo for B<N> {} + | ^^^^^^^^^^^ error[E0747]: unresolved item provided when a constant was expected --> $DIR/diagnostics.rs:16:32 diff --git a/src/test/ui/const-generics/issues/issue-56445.full.stderr b/src/test/ui/const-generics/issues/issue-56445-1.full.stderr similarity index 92% rename from src/test/ui/const-generics/issues/issue-56445.full.stderr rename to src/test/ui/const-generics/issues/issue-56445-1.full.stderr index 61fba92c19..8416d64e1c 100644 --- a/src/test/ui/const-generics/issues/issue-56445.full.stderr +++ b/src/test/ui/const-generics/issues/issue-56445-1.full.stderr @@ -1,5 +1,5 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-56445.rs:3:27 + --> $DIR/issue-56445-1.rs:3:27 | LL | #![cfg_attr(full, feature(const_generics))] | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![cfg_attr(full, feature(const_generics))] = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information error[E0771]: use of non-static lifetime `'a` in const generic - --> $DIR/issue-56445.rs:8:26 + --> $DIR/issue-56445-1.rs:8:26 | LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | ^^ diff --git a/src/test/ui/const-generics/issues/issue-56445.min.stderr b/src/test/ui/const-generics/issues/issue-56445-1.min.stderr similarity index 91% rename from src/test/ui/const-generics/issues/issue-56445.min.stderr rename to src/test/ui/const-generics/issues/issue-56445-1.min.stderr index 80702dd4bc..f7056f27cb 100644 --- a/src/test/ui/const-generics/issues/issue-56445.min.stderr +++ b/src/test/ui/const-generics/issues/issue-56445-1.min.stderr @@ -1,5 +1,5 @@ error[E0771]: use of non-static lifetime `'a` in const generic - --> $DIR/issue-56445.rs:8:26 + --> $DIR/issue-56445-1.rs:8:26 | LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | ^^ diff --git a/src/test/ui/const-generics/issues/issue-56445.rs b/src/test/ui/const-generics/issues/issue-56445-1.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue-56445.rs rename to src/test/ui/const-generics/issues/issue-56445-1.rs diff --git a/src/test/ui/const-generics/issues/issue-56445-2.rs b/src/test/ui/const-generics/issues/issue-56445-2.rs new file mode 100644 index 0000000000..e078c8487c --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-56445-2.rs @@ -0,0 +1,11 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-502095133 +struct OnDiskDirEntry<'a> { _s: &'a usize } + +impl<'a> OnDiskDirEntry<'a> { + const LFN_FRAGMENT_LEN: usize = 2; + + fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } } + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-56445-2.stderr b/src/test/ui/const-generics/issues/issue-56445-2.stderr new file mode 100644 index 0000000000..770c80cbbd --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-56445-2.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-56445-2.rs:7:38 + | +LL | fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } } + | ^^^^ + | +note: not a concrete type + --> $DIR/issue-56445-2.rs:4:10 + | +LL | impl<'a> OnDiskDirEntry<'a> { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-56445-3.rs b/src/test/ui/const-generics/issues/issue-56445-3.rs new file mode 100644 index 0000000000..c29df14586 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-56445-3.rs @@ -0,0 +1,12 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-524494170 +pub struct Memory<'rom> { + rom: &'rom [u8], + ram: [u8; Self::SIZE], + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants +} + +impl<'rom> Memory<'rom> { + pub const SIZE: usize = 0x8000; +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-56445-3.stderr b/src/test/ui/const-generics/issues/issue-56445-3.stderr new file mode 100644 index 0000000000..f1c49eecfb --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-56445-3.stderr @@ -0,0 +1,8 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-56445-3.rs:4:15 + | +LL | ram: [u8; Self::SIZE], + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-61336-2.full.stderr b/src/test/ui/const-generics/issues/issue-61336-2.full.stderr index 9f8e68d211..ef0cafcb9b 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.full.stderr @@ -16,8 +16,8 @@ LL | [x; { N }] = note: the `Copy` trait is required because the repeated element will be copied help: consider restricting type parameter `T` | -LL | fn g<T: Copy, const N: usize>(x: T) -> [T; N] { - | ^^^^^^ +LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61336-2.min.stderr b/src/test/ui/const-generics/issues/issue-61336-2.min.stderr index 82d17a87e0..e5fe50513a 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.min.stderr @@ -7,8 +7,8 @@ LL | [x; { N }] = note: the `Copy` trait is required because the repeated element will be copied help: consider restricting type parameter `T` | -LL | fn g<T: Copy, const N: usize>(x: T) -> [T; N] { - | ^^^^^^ +LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-61336.full.stderr b/src/test/ui/const-generics/issues/issue-61336.full.stderr index 974e2af6fd..fcfd39387c 100644 --- a/src/test/ui/const-generics/issues/issue-61336.full.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.full.stderr @@ -16,8 +16,8 @@ LL | [x; N] = note: the `Copy` trait is required because the repeated element will be copied help: consider restricting type parameter `T` | -LL | fn g<T: Copy, const N: usize>(x: T) -> [T; N] { - | ^^^^^^ +LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61336.min.stderr b/src/test/ui/const-generics/issues/issue-61336.min.stderr index 19c7153582..91580313e1 100644 --- a/src/test/ui/const-generics/issues/issue-61336.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.min.stderr @@ -7,8 +7,8 @@ LL | [x; N] = note: the `Copy` trait is required because the repeated element will be copied help: consider restricting type parameter `T` | -LL | fn g<T: Copy, const N: usize>(x: T) -> [T; N] { - | ^^^^^^ +LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-64494.min.stderr b/src/test/ui/const-generics/issues/issue-64494.min.stderr index 936ab7f6e7..846db0c91b 100644 --- a/src/test/ui/const-generics/issues/issue-64494.min.stderr +++ b/src/test/ui/const-generics/issues/issue-64494.min.stderr @@ -16,7 +16,7 @@ LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {} = 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[E0119]: conflicting implementations of trait `MyTrait`: +error[E0119]: conflicting implementations of trait `MyTrait` --> $DIR/issue-64494.rs:18:1 | LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {} diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs index bbfd2183b0..45318ca68f 100644 --- a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs +++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs @@ -1,4 +1,3 @@ -// run-pass #![feature(const_generics)] #![allow(incomplete_features, unused_braces)] @@ -15,4 +14,5 @@ where fn main() { Foo::foo(); + //~^ ERROR the function or associated item } diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr new file mode 100644 index 0000000000..a82a60696b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr @@ -0,0 +1,15 @@ +error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied + --> $DIR/issue-69654-run-pass.rs:16:10 + | +LL | struct Foo<const N: usize> {} + | -------------------------- function or associated item `foo` not found for this +... +LL | Foo::foo(); + | ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `[u8; _]: Bar<[(); _]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/const-generics/issues/issue-69654.rs b/src/test/ui/const-generics/issues/issue-69654.rs index 7e775999eb..b1214b12a1 100644 --- a/src/test/ui/const-generics/issues/issue-69654.rs +++ b/src/test/ui/const-generics/issues/issue-69654.rs @@ -15,4 +15,5 @@ where fn main() { Foo::foo(); + //~^ ERROR the function or associated item } diff --git a/src/test/ui/const-generics/issues/issue-69654.stderr b/src/test/ui/const-generics/issues/issue-69654.stderr index 70af7bf25d..0ce7640f68 100644 --- a/src/test/ui/const-generics/issues/issue-69654.stderr +++ b/src/test/ui/const-generics/issues/issue-69654.stderr @@ -4,6 +4,19 @@ error[E0423]: expected value, found type parameter `T` LL | impl<T> Bar<T> for [u8; T] {} | ^ not a value -error: aborting due to previous error +error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied + --> $DIR/issue-69654.rs:17:10 + | +LL | struct Foo<const N: usize> {} + | -------------------------- function or associated item `foo` not found for this +... +LL | Foo::foo(); + | ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `[u8; _]: Bar<[(); _]>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0423, E0599. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs b/src/test/ui/const-generics/issues/issue-70273-assoc-fn.rs similarity index 100% rename from src/test/ui/const-generics/issues/issue70273-assoc-fn.rs rename to src/test/ui/const-generics/issues/issue-70273-assoc-fn.rs diff --git a/src/test/ui/const-generics/issues/issue-84408.rs b/src/test/ui/const-generics/issues/issue-84408.rs new file mode 100644 index 0000000000..e1ba850a4c --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-84408.rs @@ -0,0 +1,38 @@ +// Regression test for #84408. +// check-pass + +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait Melon<const X: usize> { + fn new(arr: [i32; X]) -> Self; + fn change<T: Melon<X>>(self) -> T; +} + +struct Foo([i32; 5]); +struct Bar<const A: usize, const B: usize>([i32; A + B]) +where + [(); A + B]: ; + +impl Melon<5> for Foo { + fn new(arr: [i32; 5]) -> Self { + Foo(arr) + } + fn change<T: Melon<5>>(self) -> T { + T::new(self.0) + } +} + +impl<const A: usize, const B: usize> Melon<{ A + B }> for Bar<A, B> +where + [(); A + B]: , +{ + fn new(arr: [i32; A + B]) -> Self { + Bar(arr) + } + fn change<T: Melon<{ A + B }>>(self) -> T { + T::new(self.0) + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/const_default_first.rs b/src/test/ui/const-generics/min_const_generics/const_default_first.rs new file mode 100644 index 0000000000..ae82c85eb7 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/const_default_first.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features, dead_code)] + +struct Both<const N: usize=3, T> { +//~^ ERROR: generic parameters with a default must be + v: T +} diff --git a/src/test/ui/const-generics/min_const_generics/const_default_first.stderr b/src/test/ui/const-generics/min_const_generics/const_default_first.stderr new file mode 100644 index 0000000000..f7a2e484fc --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/const_default_first.stderr @@ -0,0 +1,8 @@ +error: generic parameters with a default must be trailing + --> $DIR/const_default_first.rs:6:19 + | +LL | struct Both<const N: usize=3, T> { + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.rs b/src/test/ui/const-generics/min_const_generics/default_function_param.rs index 5b0a42a455..ebdb5a65bc 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.rs @@ -1,4 +1,6 @@ -fn foo<const SIZE: usize = 5>() {} -//~^ ERROR default values for const generic parameters are experimental +#![crate_type = "lib"] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] -fn main() {} +fn foo<const SIZE: usize = 5usize>() {} +//~^ ERROR defaults for const parameters are diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr index 31b5ad5123..243ac0db5f 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr @@ -1,12 +1,8 @@ -error[E0658]: default values for const generic parameters are experimental - --> $DIR/default_function_param.rs:1:26 +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_function_param.rs:5:14 | -LL | fn foo<const SIZE: usize = 5>() {} - | ^^^ - | - = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information - = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable +LL | fn foo<const SIZE: usize = 5usize>() {} + | ^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/min_const_generics/invalid-patterns.stderr b/src/test/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr similarity index 75% rename from src/test/ui/const-generics/min_const_generics/invalid-patterns.stderr rename to src/test/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr index 04f716fa73..415a53a562 100644 --- a/src/test/ui/const-generics/min_const_generics/invalid-patterns.stderr +++ b/src/test/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr @@ -1,58 +1,70 @@ error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:28:21 + --> $DIR/invalid-patterns.rs:29:21 | LL | get_flag::<false, 0xFF>(); | ^^^^ expected `char`, found `u8` error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:30:14 + --> $DIR/invalid-patterns.rs:31:14 | LL | get_flag::<7, 'c'>(); | ^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:32:14 + --> $DIR/invalid-patterns.rs:33:14 | LL | get_flag::<42, 0x5ad>(); | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:32:18 + --> $DIR/invalid-patterns.rs:33:18 | LL | get_flag::<42, 0x5ad>(); | ^^^^^ expected `char`, found `u8` error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:37:21 + --> $DIR/invalid-patterns.rs:38:21 | LL | get_flag::<false, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, 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: 4, align: 4) { + __ __ __ __ │ ░░░░ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:39:14 + --> $DIR/invalid-patterns.rs:40:14 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, 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: 1, align: 1) { + 42 │ B + } error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:41:14 + --> $DIR/invalid-patterns.rs:42:14 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, 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: 1, align: 1) { + 42 │ B + } error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:41:47 + --> $DIR/invalid-patterns.rs:42:47 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, 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: 4, align: 4) { + __ __ __ __ │ ░░░░ + } error: aborting due to 8 previous errors diff --git a/src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr new file mode 100644 index 0000000000..415a53a562 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr @@ -0,0 +1,72 @@ +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:29:21 + | +LL | get_flag::<false, 0xFF>(); + | ^^^^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:31:14 + | +LL | get_flag::<7, 'c'>(); + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:14 + | +LL | get_flag::<42, 0x5ad>(); + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:18 + | +LL | get_flag::<42, 0x5ad>(); + | ^^^^^ expected `char`, found `u8` + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:38:21 + | +LL | get_flag::<false, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, 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: 4, align: 4) { + __ __ __ __ │ ░░░░ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:40:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, 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: 1, align: 1) { + 42 │ B + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:42:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, 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: 1, align: 1) { + 42 │ B + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:42:47 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, 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: 4, align: 4) { + __ __ __ __ │ ░░░░ + } + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs b/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs index a120eee67e..682e0eced9 100644 --- a/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs +++ b/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth use std::mem::transmute; fn get_flag<const FlagSet: bool, const ShortName: char>() -> Option<char> { diff --git a/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs new file mode 100644 index 0000000000..435a63a528 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs @@ -0,0 +1,27 @@ +// run-pass +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features, dead_code)] + +struct Both<T=u32, const N: usize=3> { + arr: [T; N] +} + +trait BothTrait<T=u32, const N: usize=3> {} + +enum BothEnum<T=u32, const N: usize=3> { + Dummy([T; N]) +} + +struct OppOrder<const N: usize=3, T=u32> { + arr: [T; N] +} + +fn main() { + let _ = OppOrder::<3, u32> { + arr: [0,0,0], + }; + let _ = Both::<u8, 1> { + arr: [0], + }; +} diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs index f56687ecd9..6ded9f13bc 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs @@ -1,4 +1,3 @@ -// build-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -10,5 +9,5 @@ where A<N>: Bar<N>; fn main() { - let _ = A; + let _ = A; //~ERROR the trait bound } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr new file mode 100644 index 0000000000..6830288acc --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -0,0 +1,17 @@ +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}>` + | + = help: the following implementations were found: + <A<7_usize> as Bar<N>> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs index 12444ec531..2d00141fbf 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -24,4 +23,6 @@ fn main() { // `t` is `ty::Infer(TyVar(_#1t))` // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr new file mode 100644 index 0000000000..9532fc21a3 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-2.rs:25:9 + | +LL | t = foo; + | ^^^ cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs index 187e27382f..2e306f8c4c 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -15,4 +14,6 @@ fn main() { // `t` is `ty::Infer(TyVar(_#1t))` // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr new file mode 100644 index 0000000000..2551d68f97 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-3.rs:16:9 + | +LL | t = foo; + | ^^^ + | | + | cyclic type of infinite size + | help: try using a conversion method: `foo.to_vec()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs index 8e42ceb6d7..9c7f5ab91e 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs @@ -1,4 +1,3 @@ -// build-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -8,5 +7,5 @@ fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] { fn main() { let mut arr = Default::default(); - arr = bind(arr); + arr = bind(arr); //~ ERROR mismatched type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr new file mode 100644 index 0000000000..5685eedbde --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-4.rs:10:11 + | +LL | arr = bind(arr); + | ^^^^^^^^^ encountered a self-referencing constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index debb272da3..e8fd9e7769 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,22 +1,17 @@ -error: type parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 +error: generic parameters with a default must be trailing + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar<T = [u8; N], const N: usize>(T); | ^ | = note: using type defaults and const parameters in the same parameter list is currently not permitted -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 - | -LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U); - | ^ the anonymous constant must not depend on the parameter `T` - -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar<T = [u8; N], const N: usize>(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 171efca193..5fa6423306 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,5 +1,5 @@ -error: type parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 +error: generic parameters with a default must be trailing + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar<T = [u8; N], const N: usize>(T); | ^ @@ -7,7 +7,7 @@ LL | struct Bar<T = [u8; N], const N: usize>(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error: generic parameters may not be used in const operations - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44 | LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U); | ^ cannot perform const operation using `T` @@ -15,11 +15,12 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U); = 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: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar<T = [u8; N], const N: usize>(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index a85e2a2f2c..76c1b84aef 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -1,15 +1,12 @@ // revisions: full min - #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U); -//[full]~^ ERROR constant values inside of type parameter defaults -//[min]~^^ ERROR generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations -// FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar<T = [u8; N], const N: usize>(T); -//~^ ERROR constant values inside of type parameter defaults -//~| ERROR type parameters with a default +//~^ ERROR generic parameters with a default cannot use forward declared identifiers +//~| ERROR generic parameters with a default fn main() {} diff --git a/src/test/ui/const-ptr/out_of_bounds_read.rs b/src/test/ui/const-ptr/out_of_bounds_read.rs deleted file mode 100644 index 183aa9e512..0000000000 --- a/src/test/ui/const-ptr/out_of_bounds_read.rs +++ /dev/null @@ -1,16 +0,0 @@ -// error-pattern: any use of this value will cause an error - -#![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 deleted file mode 100644 index 87b7c377b0..0000000000 --- a/src/test/ui/const-ptr/out_of_bounds_read.stderr +++ /dev/null @@ -1,62 +0,0 @@ -error: any use of this value will cause an error - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL - | -LL | unsafe { copy_nonoverlapping(src, dst, count) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4 - | inside `copy_nonoverlapping::<u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL - | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | inside `_READ` at $DIR/out_of_bounds_read.rs:13:33 - | - ::: $DIR/out_of_bounds_read.rs:13:5 - | -LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; - | ------------------------------------------------------ - | - = 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 - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL - | -LL | unsafe { copy_nonoverlapping(src, dst, count) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4 - | inside `copy_nonoverlapping::<u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL - | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:14:39 - | - ::: $DIR/out_of_bounds_read.rs:14:5 - | -LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; - | -------------------------------------------------------- - | - = 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 - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL - | -LL | unsafe { copy_nonoverlapping(src, dst, count) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4 - | inside `copy_nonoverlapping::<u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL - | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - | inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:15:37 - | - ::: $DIR/out_of_bounds_read.rs:15:5 - | -LL | const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; - | -------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/const_evaluatable/needs_where_clause.stderr b/src/test/ui/const_evaluatable/needs_where_clause.stderr index 945105d1a2..7b41e39b7d 100644 --- a/src/test/ui/const_evaluatable/needs_where_clause.stderr +++ b/src/test/ui/const_evaluatable/needs_where_clause.stderr @@ -4,11 +4,7 @@ error: unconstrained generic constant LL | b: [f32; complex_maths::<T>(N)], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try adding a `where` bound using this expression: `where [u8; complex_maths::<T>(N)]: Sized` - --> $DIR/needs_where_clause.rs:11:12 - | -LL | b: [f32; complex_maths::<T>(N)], - | ^^^^^^^^^^^^^^^^^^^^^ + = help: try adding a `where` bound using this expression: `where [(); complex_maths::<T>(N)]:` error: aborting due to previous error diff --git a/src/test/ui/const_evaluatable/no_where_clause.stderr b/src/test/ui/const_evaluatable/no_where_clause.stderr index 84a65f0d1d..3e5c2f5cad 100644 --- a/src/test/ui/const_evaluatable/no_where_clause.stderr +++ b/src/test/ui/const_evaluatable/no_where_clause.stderr @@ -4,11 +4,7 @@ error: unconstrained generic constant LL | b: [f32; complex_maths(N)], | ^^^^^^^^^^^^^^^^^^^^^^^ | -help: try adding a `where` bound using this expression: `where [u8; complex_maths(N)]: Sized` - --> $DIR/no_where_clause.rs:10:12 - | -LL | b: [f32; complex_maths(N)], - | ^^^^^^^^^^^^^^^^ + = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:` error: aborting due to previous error diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs index 9c02d232e1..66b76627c0 100644 --- a/src/test/ui/consts/cast-discriminant-zst-enum.rs +++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs @@ -1,6 +1,6 @@ // run-pass // Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32. -#![feature(test)] +#![feature(bench_black_box)] use std::hint::black_box; #[derive(Copy, Clone)] diff --git a/src/test/ui/consts/const-err4.stderr b/src/test/ui/consts/const-err4.32bit.stderr similarity index 76% rename from src/test/ui/consts/const-err4.stderr rename to src/test/ui/consts/const-err4.32bit.stderr index 081b09e330..1dbda8cbcd 100644 --- a/src/test/ui/consts/const-err4.stderr +++ b/src/test/ui/consts/const-err4.32bit.stderr @@ -1,10 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const-err4.rs:8:11 + --> $DIR/const-err4.rs:9:11 | LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + __ __ __ __ │ ░░░░ + } error: aborting due to previous error diff --git a/src/test/ui/consts/const-err4.64bit.stderr b/src/test/ui/consts/const-err4.64bit.stderr new file mode 100644 index 0000000000..2eea3ea709 --- /dev/null +++ b/src/test/ui/consts/const-err4.64bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-err4.rs:9:11 + | +LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-err4.rs b/src/test/ui/consts/const-err4.rs index 70d9bc149d..f0625faa80 100644 --- a/src/test/ui/consts/const-err4.rs +++ b/src/test/ui/consts/const-err4.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth #[derive(Copy, Clone)] union Foo { a: isize, diff --git a/src/test/ui/consts/const-eval/auxiliary/stability.rs b/src/test/ui/consts/const-eval/auxiliary/stability.rs index 70531114f2..e615955186 100644 --- a/src/test/ui/consts/const-eval/auxiliary/stability.rs +++ b/src/test/ui/consts/const-eval/auxiliary/stability.rs @@ -3,7 +3,6 @@ #![crate_type="rlib"] #![stable(feature = "rust1", since = "1.0.0")] -#![feature(const_fn)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs index 9b99a685b6..bd517e568e 100644 --- a/src/test/ui/consts/const-eval/conditional_array_execution.rs +++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs @@ -10,7 +10,7 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; fn main() { println!("{}", FOO); - //~^ ERROR + //~^ ERROR evaluation of constant value failed //~| WARN erroneous constant used [const_err] //~| WARN this was previously accepted by the compiler but is being phased out } diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index 6a205ce978..e6fecef9fb 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed LL | let x: &'static i32 = &X; | ^ referenced constant has errors query stack during panic: -#0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]` +#0 [normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]` #1 [optimized_mir] optimizing MIR for `main` #2 [collect_and_partition_mono_items] collect_and_partition_mono_items end of query stack diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr similarity index 83% rename from src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr rename to src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr index ccd1378478..187e2760ad 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr @@ -1,13 +1,16 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:25:5 + --> $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 | = 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────────╼ │ ╾──────╼ + } error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:28:43 + --> $DIR/const-pointer-values-in-various-types.rs:29:43 | LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -19,7 +22,7 @@ LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_ = 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-pointer-values-in-various-types.rs:32:45 + --> $DIR/const-pointer-values-in-various-types.rs:33:45 | LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -30,7 +33,7 @@ LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uin = 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-pointer-values-in-various-types.rs:36:45 + --> $DIR/const-pointer-values-in-various-types.rs:37:45 | LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -41,23 +44,29 @@ LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uin = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:40:5 + --> $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 | = 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───────╼ │ ╾──────╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:43:5 + --> $DIR/const-pointer-values-in-various-types.rs:44:5 | LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + } error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:46:43 + --> $DIR/const-pointer-values-in-various-types.rs:47:43 | LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -68,7 +77,7 @@ LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 = 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-pointer-values-in-various-types.rs:50:45 + --> $DIR/const-pointer-values-in-various-types.rs:51:45 | LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -79,7 +88,7 @@ LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int = 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-pointer-values-in-various-types.rs:54:45 + --> $DIR/const-pointer-values-in-various-types.rs:55:45 | LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -90,23 +99,29 @@ LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:58:5 + --> $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 | = 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───────╼ │ ╾──────╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:61:5 + --> $DIR/const-pointer-values-in-various-types.rs:62:5 | LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + } error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:64:45 + --> $DIR/const-pointer-values-in-various-types.rs:65:45 | LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -117,15 +132,18 @@ LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.flo = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:68:5 + --> $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 | = 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───────╼ │ ╾──────╼ + } error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:71:47 + --> $DIR/const-pointer-values-in-various-types.rs:72:47 | LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -136,7 +154,7 @@ LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.t = 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-pointer-values-in-various-types.rs:75:47 + --> $DIR/const-pointer-values-in-various-types.rs:76:47 | LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -147,7 +165,7 @@ LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.c = 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-pointer-values-in-various-types.rs:79:39 + --> $DIR/const-pointer-values-in-various-types.rs:80:39 | LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -158,7 +176,7 @@ LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; = 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-pointer-values-in-various-types.rs:83:41 + --> $DIR/const-pointer-values-in-various-types.rs:84:41 | LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -169,7 +187,7 @@ LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 } = 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-pointer-values-in-various-types.rs:87:41 + --> $DIR/const-pointer-values-in-various-types.rs:88:41 | LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -180,15 +198,18 @@ LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 } = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:91:5 + --> $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 | = 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───────╼ │ ╾──────╼ + } error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:94:43 + --> $DIR/const-pointer-values-in-various-types.rs:95:43 | LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -199,7 +220,7 @@ LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_12 = 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-pointer-values-in-various-types.rs:98:39 + --> $DIR/const-pointer-values-in-various-types.rs:99:39 | LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -210,7 +231,7 @@ LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; = 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-pointer-values-in-various-types.rs:102:41 + --> $DIR/const-pointer-values-in-various-types.rs:103:41 | LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -221,7 +242,7 @@ LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; = 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-pointer-values-in-various-types.rs:106:41 + --> $DIR/const-pointer-values-in-various-types.rs:107:41 | LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -232,15 +253,18 @@ LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:110:5 + --> $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 | = 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───────╼ │ ╾──────╼ + } error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:113:43 + --> $DIR/const-pointer-values-in-various-types.rs:114:43 | LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -251,7 +275,7 @@ LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 = 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-pointer-values-in-various-types.rs:117:41 + --> $DIR/const-pointer-values-in-various-types.rs:118:41 | LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -262,15 +286,18 @@ LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error[E0080]: it is undefined behavior to use this value - --> $DIR/const-pointer-values-in-various-types.rs:121:5 + --> $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 | = 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───────╼ │ ╾──────╼ + } error: any use of this value will cause an error - --> $DIR/const-pointer-values-in-various-types.rs:124:43 + --> $DIR/const-pointer-values-in-various-types.rs:125:43 | LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -281,7 +308,7 @@ LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_ = 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-pointer-values-in-various-types.rs:128:43 + --> $DIR/const-pointer-values-in-various-types.rs:129:43 | LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs index 90bc191020..a1a932639d 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs @@ -1,4 +1,5 @@ // only-x86_64 +// stderr-per-bitwidth #[repr(C)] union Nonsense { diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.rs b/src/test/ui/consts/const-eval/const_fn_ptr.rs index 045fe9ad11..b3c677c698 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr.rs +++ b/src/test/ui/consts/const-eval/const_fn_ptr.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -Zunleash-the-miri-inside-of-you -#![feature(const_fn)] fn double(x: usize) -> usize { x * 2 } const fn double_const(x: usize) -> usize { x * 2 } diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.stderr b/src/test/ui/consts/const-eval/const_fn_ptr.stderr index ab18020056..a16ac7b2a2 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr.stderr @@ -1,27 +1,27 @@ warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/const_fn_ptr.rs:12:5 + --> $DIR/const_fn_ptr.rs:11:5 | LL | X(x) | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_fn_ptr.rs:16:5 + --> $DIR/const_fn_ptr.rs:15:5 | LL | X_CONST(x) | ^^^^^^^^^^ help: skipping check for `const_fn_fn_ptr_basics` feature - --> $DIR/const_fn_ptr.rs:19:14 + --> $DIR/const_fn_ptr.rs:18:14 | LL | const fn foo(x: fn(usize) -> usize, y: usize) -> usize { | ^ help: skipping check for `const_fn_fn_ptr_basics` feature - --> $DIR/const_fn_ptr.rs:20:5 + --> $DIR/const_fn_ptr.rs:19:5 | LL | x(y) | ^ help: skipping check that does not even have a feature gate - --> $DIR/const_fn_ptr.rs:20:5 + --> $DIR/const_fn_ptr.rs:19:5 | LL | x(y) | ^^^^ diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs index 14bd6558e7..1896eba82f 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -Zunleash-the-miri-inside-of-you -#![feature(const_fn)] #![allow(unused)] fn double(x: usize) -> usize { x * 2 } diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail.stderr index 0a7182fd39..ec5de57590 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail.stderr @@ -1,7 +1,7 @@ warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/const_fn_ptr_fail.rs:10:5 + --> $DIR/const_fn_ptr_fail.rs:9:5 | LL | X(x) // FIXME: this should error someday | ^^^^ diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs index 0a2532973f..804ebf6600 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs @@ -1,7 +1,6 @@ // build-fail // compile-flags: -Zunleash-the-miri-inside-of-you -#![feature(const_fn)] #![allow(const_err)] fn double(x: usize) -> usize { diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr index 2afedf3056..4f7a771f41 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_fn_ptr_fail2.rs:20:16 + --> $DIR/const_fn_ptr_fail2.rs:19:16 | LL | assert_eq!(Y, 4); | ^ referenced constant has errors error[E0080]: evaluation of constant value failed - --> $DIR/const_fn_ptr_fail2.rs:22:16 + --> $DIR/const_fn_ptr_fail2.rs:21:16 | LL | assert_eq!(Z, 4); | ^ referenced constant has errors @@ -13,17 +13,17 @@ LL | assert_eq!(Z, 4); warning: skipping const checks | help: skipping check for `const_fn_fn_ptr_basics` feature - --> $DIR/const_fn_ptr_fail2.rs:12:14 + --> $DIR/const_fn_ptr_fail2.rs:11:14 | LL | const fn bar(x: fn(usize) -> usize, y: usize) -> usize { | ^ help: skipping check for `const_fn_fn_ptr_basics` feature - --> $DIR/const_fn_ptr_fail2.rs:13:5 + --> $DIR/const_fn_ptr_fail2.rs:12:5 | LL | x(y) | ^ help: skipping check that does not even have a feature gate - --> $DIR/const_fn_ptr_fail2.rs:13:5 + --> $DIR/const_fn_ptr_fail2.rs:12:5 | LL | x(y) | ^^^^ diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs index 3729285956..4b3cf70739 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.rs @@ -3,7 +3,6 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr index ca80a9ab39..69e3ca716a 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -1,5 +1,5 @@ error: `foo` is not yet stable as a const fn - --> $DIR/dont_promote_unstable_const_fn.rs:15:25 + --> $DIR/dont_promote_unstable_const_fn.rs:14:25 | LL | const fn bar() -> u32 { foo() } | ^^^^^ @@ -7,7 +7,7 @@ LL | const fn bar() -> u32 { foo() } = help: add `#![feature(foo)]` to the crate attributes to enable error[E0716]: temporary value dropped while borrowed - --> $DIR/dont_promote_unstable_const_fn.rs:18:28 + --> $DIR/dont_promote_unstable_const_fn.rs:17:28 | LL | let _: &'static u32 = &foo(); | ------------ ^^^^^ creates a temporary which is freed while still in use @@ -17,7 +17,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/dont_promote_unstable_const_fn.rs:22:28 + --> $DIR/dont_promote_unstable_const_fn.rs:21:28 | LL | let _: &'static u32 = &meh(); | ------------ ^^^^^ creates a temporary which is freed while still in use @@ -28,7 +28,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/dont_promote_unstable_const_fn.rs:23:26 + --> $DIR/dont_promote_unstable_const_fn.rs:22:26 | LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use diff --git a/src/test/ui/consts/const-eval/double_promotion.rs b/src/test/ui/consts/const-eval/double_promotion.rs index 48f4426d9c..9ee2777a64 100644 --- a/src/test/ui/consts/const-eval/double_promotion.rs +++ b/src/test/ui/consts/const-eval/double_promotion.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(const_fn, rustc_attrs)] +#![feature(rustc_attrs)] #[rustc_args_required_const(0)] pub const fn a(value: u8) -> u8 { diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs index 3f7bab0658..26162aa622 100644 --- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs +++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs @@ -1,5 +1,3 @@ -#![feature(const_fn)] - fn main() {} #[repr(C)] diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr index 4c8492b22f..bc3b6aa665 100644 --- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr +++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr @@ -1,5 +1,5 @@ error[E0658]: unions in const fn are unstable - --> $DIR/feature-gate-const_fn_union.rs:12:5 + --> $DIR/feature-gate-const_fn_union.rs:10:5 | LL | Foo { u }.i | ^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr similarity index 76% rename from src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.stderr rename to src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index 866f877f54..92d990f149 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -1,10 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc_intrinsic_uninit.rs:8:1 + --> $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 | = 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──╼ │ ╾──╼ + } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr new file mode 100644 index 0000000000..6d63233997 --- /dev/null +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -0,0 +1,14 @@ +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 + | + = 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────────╼ │ ╾──────╼ + } + +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/heap/alloc_intrinsic_uninit.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs index 998b6cef84..63a3fd4e09 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth // compile-test #![feature(core_intrinsics)] #![feature(const_heap)] diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs index 79f1301a2f..a88e219704 100644 --- a/src/test/ui/consts/const-eval/issue-44578.rs +++ b/src/test/ui/consts/const-eval/issue-44578.rs @@ -25,5 +25,5 @@ impl Foo for u16 { fn main() { println!("{}", <Bar<u16, u8> as Foo>::AMT); - //~^ ERROR evaluation of constant value failed [E0080] + //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/consts/const-eval/issue-49296.rs b/src/test/ui/consts/const-eval/issue-49296.rs index 9fd9e8f364..f2d9758b8d 100644 --- a/src/test/ui/consts/const-eval/issue-49296.rs +++ b/src/test/ui/consts/const-eval/issue-49296.rs @@ -1,7 +1,7 @@ // issue-49296: Unsafe shenigans in constants can result in missing errors -#![feature(const_fn)] #![feature(const_fn_union)] +#![feature(const_fn_trait_bound)] const unsafe fn transmute<T: Copy, U: Copy>(t: T) -> U { #[repr(C)] diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs index 3edd4e0868..1a99c77c6d 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs @@ -1,4 +1,4 @@ -#![feature(const_fn, const_fn_union)] +#![feature(const_fn_union)] #![allow(const_err)] diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs index 7887e42653..c9e4871bb7 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs @@ -1,4 +1,4 @@ -#![feature(const_fn, const_fn_union)] +#![feature(const_fn_union)] #![deny(const_err)] diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr similarity index 74% rename from src/test/ui/consts/const-eval/ref_to_int_match.stderr rename to src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr index cb0ba5d992..c14457490a 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr @@ -1,19 +1,22 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ref_to_int_match.rs:25:1 + --> $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 | = 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──╼ │ ╾──╼ + } error: could not evaluate constant pattern - --> $DIR/ref_to_int_match.rs:7:14 + --> $DIR/ref_to_int_match.rs:8:14 | LL | 10..=BAR => {}, | ^^^ error: could not evaluate constant pattern - --> $DIR/ref_to_int_match.rs:7:14 + --> $DIR/ref_to_int_match.rs:8:14 | LL | 10..=BAR => {}, | ^^^ diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr new file mode 100644 index 0000000000..6ea1cf145a --- /dev/null +++ b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr @@ -0,0 +1,26 @@ +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 + | + = 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────────╼ │ ╾──────╼ + } + +error: could not evaluate constant pattern + --> $DIR/ref_to_int_match.rs:8:14 + | +LL | 10..=BAR => {}, + | ^^^ + +error: could not evaluate constant pattern + --> $DIR/ref_to_int_match.rs:8:14 + | +LL | 10..=BAR => {}, + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.rs b/src/test/ui/consts/const-eval/ref_to_int_match.rs index 87136a109d..0741e425d9 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.rs +++ b/src/test/ui/consts/const-eval/ref_to_int_match.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth #![feature(const_fn_union)] fn main() { diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs index 9e5cb0d4eb..cae8fcf106 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] #![feature(staged_api)] diff --git a/src/test/ui/consts/const-eval/transmute-const.stderr b/src/test/ui/consts/const-eval/transmute-const.32bit.stderr similarity index 76% rename from src/test/ui/consts/const-eval/transmute-const.stderr rename to src/test/ui/consts/const-eval/transmute-const.32bit.stderr index 46a4049827..89c7220788 100644 --- a/src/test/ui/consts/const-eval/transmute-const.stderr +++ b/src/test/ui/consts/const-eval/transmute-const.32bit.stderr @@ -1,10 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/transmute-const.rs:3:1 + --> $DIR/transmute-const.rs:4:1 | LL | static FOO: bool = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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: 1, align: 1) { + 03 │ . + } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/transmute-const.64bit.stderr b/src/test/ui/consts/const-eval/transmute-const.64bit.stderr new file mode 100644 index 0000000000..89c7220788 --- /dev/null +++ b/src/test/ui/consts/const-eval/transmute-const.64bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/transmute-const.rs:4:1 + | +LL | static FOO: bool = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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: 1, align: 1) { + 03 │ . + } + +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/transmute-const.rs b/src/test/ui/consts/const-eval/transmute-const.rs index 1cfad00ca7..d9d0a3aea0 100644 --- a/src/test/ui/consts/const-eval/transmute-const.rs +++ b/src/test/ui/consts/const-eval/transmute-const.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth use std::mem; static FOO: bool = unsafe { mem::transmute(3u8) }; diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr similarity index 79% rename from src/test/ui/consts/const-eval/ub-enum.stderr rename to src/test/ui/consts/const-eval/ub-enum.32bit.stderr index db95b996c1..2274366fa2 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr @@ -5,6 +5,9 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001 at .<enum-tag>, 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) { + 01 00 00 00 │ .... + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:27:1 @@ -13,6 +16,9 @@ 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 | = 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──╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:30:1 @@ -21,6 +27,9 @@ 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 | = 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─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:42:1 @@ -29,6 +38,9 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000 at .<enum-tag>, 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) { + 00 00 00 00 │ .... + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:44:1 @@ -37,6 +49,9 @@ 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 | = 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─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:47:1 @@ -45,6 +60,9 @@ 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 | = 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─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:56:1 @@ -53,6 +71,9 @@ 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 | = 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) { + __ __ __ __ │ ░░░░ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 @@ -61,6 +82,9 @@ 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 | = 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─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:77:1 @@ -69,6 +93,9 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(B)>.0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 01 │ . + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:79:1 @@ -77,6 +104,9 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(D)>.0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 03 │ . + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:87:1 @@ -85,6 +115,9 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`) | = 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) { + 78 00 00 00 ff ff ff ff │ x....... + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:92:1 @@ -93,6 +126,9 @@ LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(Ok)>.0.1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 00 00 00 00 00 00 00 00 │ ........ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:94:1 @@ -101,6 +137,9 @@ LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(Ok)>.0.1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 00 00 00 00 00 00 00 00 │ ........ + } error: aborting due to 13 previous errors diff --git a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr new file mode 100644 index 0000000000..29d97962f3 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr @@ -0,0 +1,146 @@ +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 + | + = 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) { + 01 00 00 00 00 00 00 00 │ ........ + } + +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 + | + = 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────────╼ │ ╾──────╼ + } + +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 + | + = 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───────╼ │ ╾──────╼ + } + +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 + | + = 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) { + 00 00 00 00 00 00 00 00 │ ........ + } + +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 + | + = 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───────╼ │ ╾──────╼ + } + +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 + | + = 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───────╼ │ ╾──────╼ + } + +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 + | + = 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) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } + +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 + | + = 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───────╼ │ ╾──────╼ + } + +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 + | + = 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) { + 01 │ . + } + +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 + | + = 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) { + 03 │ . + } + +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`) + | + = 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) { + 78 00 00 00 ff ff ff ff │ x....... + } + +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 + | + = 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) { + 00 00 00 00 00 00 00 00 │ ........ + } + +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 + | + = 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) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index dc94f2368c..e408d8ec07 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,4 +1,4 @@ -// normalize-stderr-64bit "0x0000000000" -> "0x00" +// stderr-per-bitwidth #![feature(never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here diff --git a/src/test/ui/consts/const-eval/ub-int-array.stderr b/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr similarity index 76% rename from src/test/ui/consts/const-eval/ub-int-array.stderr rename to src/test/ui/consts/const-eval/ub-int-array.32bit.stderr index 92f654847d..c13271a1e5 100644 --- a/src/test/ui/consts/const-eval/ub-int-array.stderr +++ b/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr @@ -11,6 +11,9 @@ LL | | }; | |__^ type validation failed: encountered uninitialized bytes at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 12, align: 4) { + __ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:23:1 @@ -25,6 +28,9 @@ LL | | }; | |__^ type validation failed: encountered uninitialized bytes at [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: 12, align: 4) { + 00 00 00 00 01 __ 01 01 02 02 __ 02 │ .....░....░. + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-int-array.rs:43:1 @@ -39,6 +45,9 @@ LL | | }; | |__^ type validation failed: encountered uninitialized bytes at [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: 12, align: 4) { + 00 00 00 00 01 01 01 01 02 02 02 __ │ ...........░ + } error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr b/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr new file mode 100644 index 0000000000..c13271a1e5 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr @@ -0,0 +1,54 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-int-array.rs:14:1 + | +LL | / const UNINIT_INT_0: [u32; 3] = unsafe { +LL | | +LL | | +LL | | [ +... | +LL | | ] +LL | | }; + | |__^ type validation failed: encountered uninitialized bytes at [0] + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 12, align: 4) { + __ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-int-array.rs:23:1 + | +LL | / const UNINIT_INT_1: [u32; 3] = unsafe { +LL | | +LL | | +LL | | mem::transmute( +... | +LL | | ) +LL | | }; + | |__^ type validation failed: encountered uninitialized bytes at [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: 12, align: 4) { + 00 00 00 00 01 __ 01 01 02 02 __ 02 │ .....░....░. + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-int-array.rs:43:1 + | +LL | / const UNINIT_INT_2: [u32; 3] = unsafe { +LL | | +LL | | +LL | | mem::transmute( +... | +LL | | ) +LL | | }; + | |__^ type validation failed: encountered uninitialized bytes at [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: 12, align: 4) { + 00 00 00 00 01 01 01 01 02 02 02 __ │ ...........░ + } + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-int-array.rs b/src/test/ui/consts/const-eval/ub-int-array.rs index 6801c7fa3f..635cbb8cef 100644 --- a/src/test/ui/consts/const-eval/ub-int-array.rs +++ b/src/test/ui/consts/const-eval/ub-int-array.rs @@ -1,5 +1,5 @@ #![allow(const_err)] // make sure we cannot allow away the errors tested here - +// stderr-per-bitwidth //! Test the "array of int" fast path in validity checking, and in particular whether it //! points at the right array element. diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr similarity index 78% rename from src/test/ui/consts/const-eval/ub-nonnull.stderr rename to src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr index 94496b77fe..3affde739a 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr @@ -1,13 +1,16 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:11:1 + --> $DIR/ub-nonnull.rs:12:1 | LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } error: any use of this value will cause an error - --> $DIR/ub-nonnull.rs:18:30 + --> $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 @@ -20,7 +23,7 @@ LL | | } }; | |____- | note: the lint level is defined here - --> $DIR/ub-nonnull.rs:14:8 + --> $DIR/ub-nonnull.rs:15:8 | LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen | ^^^^^^^^^ @@ -28,44 +31,59 @@ LL | #[deny(const_err)] // this triggers a `const_err` so validation does not ev = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:23:1 + --> $DIR/ub-nonnull.rs:24:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 00 │ . + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:25:1 + --> $DIR/ub-nonnull.rs:26:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:33:1 + --> $DIR/ub-nonnull.rs:34:1 | LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, 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) { + __ │ ░ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:41:1 + --> $DIR/ub-nonnull.rs:42:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 2a 00 00 00 │ *... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:47:1 + --> $DIR/ub-nonnull.rs:48:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 14 00 00 00 │ .... + } error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr new file mode 100644 index 0000000000..63815c46ef --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr @@ -0,0 +1,90 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:12:1 + | +LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error: any use of this value will cause an error + --> $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> + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:24:1 + | +LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 00 │ . + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:26:1 + | +LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:34:1 + | +LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, 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) { + __ │ ░ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:42:1 + | +LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 2a 00 00 00 │ *... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:48:1 + | +LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 14 00 00 00 │ .... + } + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index e4ced600b4..0bc406e01a 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth #![feature(rustc_attrs)] #![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr similarity index 73% rename from src/test/ui/consts/const-eval/ub-ref-ptr.stderr rename to src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr index 7d76c5cb43..32e13baa3f 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr @@ -1,90 +1,123 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:12:1 + --> $DIR/ub-ref-ptr.rs:13:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 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: 4, align: 4) { + ╾─alloc2──╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:16:1 + --> $DIR/ub-ref-ptr.rs:17:1 | LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 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: 4, align: 4) { + ╾─alloc6──╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:20:1 + --> $DIR/ub-ref-ptr.rs:21:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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: 4, align: 4) { + 00 00 00 00 │ .... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:23:1 + --> $DIR/ub-ref-ptr.rs:24:1 | LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL box | = 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) { + 00 00 00 00 │ .... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:29:1 + --> $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 | = 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─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:32:1 + --> $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 | = 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─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:35:1 + --> $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 | = 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─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:38:1 + --> $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) | = 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) { + 39 05 00 00 │ 9... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:41:1 + --> $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) | = 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) { + 39 05 00 00 │ 9... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:44:1 + --> $DIR/ub-ref-ptr.rs:45:1 | LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized raw 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: 4, align: 4) { + __ __ __ __ │ ░░░░ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref-ptr.rs:46:1 + --> $DIR/ub-ref-ptr.rs:47:1 | LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a function 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: 4, align: 4) { + __ __ __ __ │ ░░░░ + } error: aborting due to 11 previous errors diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr new file mode 100644 index 0000000000..8bd4637a80 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr @@ -0,0 +1,124 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:13:1 + | +LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 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: 8) { + ╾───────alloc2────────╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:17:1 + | +LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 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: 8) { + ╾───────alloc6────────╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:21:1 + | +LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:24:1 + | +LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL box + | + = 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) { + 00 00 00 00 00 00 00 00 │ ........ + } + +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 + | + = 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───────╼ │ ╾──────╼ + } + +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 + | + = 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───────╼ │ ╾──────╼ + } + +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 + | + = 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───────╼ │ ╾──────╼ + } + +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) + | + = 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) { + 39 05 00 00 00 00 00 00 │ 9....... + } + +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) + | + = 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) { + 39 05 00 00 00 00 00 00 │ 9....... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:45:1 + | +LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized raw 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: 8) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:47:1 + | +LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a function 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: 8) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.rs b/src/test/ui/consts/const-eval/ub-ref-ptr.rs index f6075987d1..8857ae4caa 100644 --- a/src/test/ui/consts/const-eval/ub-ref-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-ref-ptr.rs @@ -1,4 +1,5 @@ // ignore-tidy-linelength +// stderr-per-bitwidth #![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr similarity index 81% rename from src/test/ui/consts/const-eval/ub-uninhabit.stderr rename to src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr index 16f5316a44..4155a8a2ef 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr @@ -1,26 +1,31 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:14:1 + --> $DIR/ub-uninhabit.rs:15:1 | LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) {} error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:17:1 + --> $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> | = 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) { + 01 00 00 00 │ .... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-uninhabit.rs:20:1 + --> $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] | = 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) {} error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr new file mode 100644 index 0000000000..def795c7f5 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr @@ -0,0 +1,32 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-uninhabit.rs:15:1 + | +LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) {} + +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> + | + = 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) { + 01 00 00 00 00 00 00 00 │ ........ + } + +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] + | + = 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) {} + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index b81bca3849..33fbd14c47 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth #![allow(const_err)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr similarity index 77% rename from src/test/ui/consts/const-eval/ub-upvars.stderr rename to src/test/ui/consts/const-eval/ub-upvars.32bit.stderr index afd6c9035c..62756518a0 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-upvars.rs:5:1 + --> $DIR/ub-upvars.rs:6:1 | LL | / const BAD_UPVAR: &dyn FnOnce() = &{ LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; @@ -9,6 +9,9 @@ LL | | }; | |__^ type validation failed: encountered a NULL reference at .<deref>.<dyn-downcast>.<captured-var(bad_ref)> | = 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──╼ │ ╾──╼╾──╼ + } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr new file mode 100644 index 0000000000..e9fabd9a3b --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -0,0 +1,18 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-upvars.rs:6:1 + | +LL | / const BAD_UPVAR: &dyn FnOnce() = &{ +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)> + | + = 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────────╼ │ ╾──────╼╾──────╼ + } + +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/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs index 5d19276557..57dd7b9e58 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.rs +++ b/src/test/ui/consts/const-eval/ub-upvars.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth #![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr similarity index 73% rename from src/test/ui/consts/const-eval/ub-wide-ptr.stderr rename to src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr index be9ec16a06..7ca5c647d8 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr @@ -1,61 +1,82 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:37:1 + --> $DIR/ub-wide-ptr.rs:38:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = 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──╼ e7 03 00 00 │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:39:1 + --> $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 | = 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─╼ ff ff ff ff │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:42:1 + --> $DIR/ub-wide-ptr.rs:43:1 | LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:45:1 + --> $DIR/ub-wide-ptr.rs:46:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:47:1 + --> $DIR/ub-wide-ptr.rs:48:1 | LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾─allocN─╼ ff ff ff ff │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:51:1 + --> $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> | = 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─╼ 01 00 00 00 │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:54:1 + --> $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 | = 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─╼ 01 00 00 00 │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:61:1 + --> $DIR/ub-wide-ptr.rs:62:1 | LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { LL | | @@ -65,65 +86,89 @@ LL | | }; | |__^ type validation failed: encountered uninitialized 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) { + 2a 00 00 00 __ __ __ __ │ *...░░░░ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:67:1 + --> $DIR/ub-wide-ptr.rs:68:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = 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─╼ e7 03 00 00 │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:70:1 + --> $DIR/ub-wide-ptr.rs:71:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:73:1 + --> $DIR/ub-wide-ptr.rs:74:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation) | = 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─╼ e7 03 00 00 │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:76:1 + --> $DIR/ub-wide-ptr.rs:77:1 | LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:80:1 + --> $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 | = 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) { + ╾─allocN─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:86:1 + --> $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 | = 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) { + ╾─allocN─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:89:1 + --> $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 | = 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) { + ╾─allocN─╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:96:1 + --> $DIR/ub-wide-ptr.rs:97:1 | LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { LL | | @@ -133,95 +178,128 @@ LL | | }; | |__^ type validation failed: encountered uninitialized raw 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) { + 2a 00 00 00 __ __ __ __ │ *...░░░░ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:104:1 + --> $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 | = 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-wide-ptr.rs:107:1 + --> $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 | = 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-wide-ptr.rs:110:1 + --> $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 | = 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─╼ 04 00 00 00 │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:112:1 + --> $DIR/ub-wide-ptr.rs:113:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned 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) { + ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:114:1 + --> $DIR/ub-wide-ptr.rs:115:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:116:1 + --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:118:1 + --> $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 | = 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-wide-ptr.rs:122:1 + --> $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 | = 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-wide-ptr.rs:126:1 + --> $DIR/ub-wide-ptr.rs:127:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾allocN─╼ 00 00 00 00 │ ╾──╼.... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:128:1 + --> $DIR/ub-wide-ptr.rs:129:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:134:5 + --> $DIR/ub-wide-ptr.rs:135:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inbounds test failed: 0x0 is not a valid pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:138:5 + --> $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 diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr new file mode 100644 index 0000000000..e42c65a151 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr @@ -0,0 +1,309 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:38:1 + | +LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) + | + = 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────────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........ + } + +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 + | + = 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───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:43:1 + | +LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:46:1 + | +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:48:1 + | +LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + } + +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> + | + = 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───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +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 + | + = 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───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:62:1 + | +LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit::<usize> { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered uninitialized 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) { + __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:68:1 + | +LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) + | + = 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───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:71:1 + | +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:74:1 + | +LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation) + | + = 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───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:77:1 + | +LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length 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) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +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 + | + = 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) { + ╾───────allocN───────╼ │ ╾──────╼ + } + +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 + | + = 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) { + ╾───────allocN───────╼ │ ╾──────╼ + } + +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 + | + = 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) { + ╾───────allocN───────╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:97:1 + | +LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit::<usize> { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered uninitialized raw 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) { + __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + } + +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 + | + = 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-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 + | + = 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-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 + | + = 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───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:113:1 + | +LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned 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) { + ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:115:1 + | +LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:117:1 + | +LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼ + } + +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 + | + = 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-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 + | + = 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-wide-ptr.rs:127:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾──────allocN───────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:129:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:135:5 + | +LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inbounds test failed: 0x0 is not a valid pointer + +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 + +error: aborting due to 28 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 2975118cdb..0fb9f7960c 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth // ignore-tidy-linelength #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.rs b/src/test/ui/consts/const-eval/union-const-eval-field.rs index 7f29a5bc24..8026371833 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.rs +++ b/src/test/ui/consts/const-eval/union-const-eval-field.rs @@ -1,4 +1,4 @@ -#![feature(const_fn)] +// only-x86_64 type Field1 = i32; type Field2 = f32; diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.stderr b/src/test/ui/consts/const-eval/union-const-eval-field.stderr index 9193bd9dea..e5a107ff01 100644 --- a/src/test/ui/consts/const-eval/union-const-eval-field.stderr +++ b/src/test/ui/consts/const-eval/union-const-eval-field.stderr @@ -5,6 +5,9 @@ LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/union-ice.rs b/src/test/ui/consts/const-eval/union-ice.rs index 5a14c7fd99..4189619b2a 100644 --- a/src/test/ui/consts/const-eval/union-ice.rs +++ b/src/test/ui/consts/const-eval/union-ice.rs @@ -1,4 +1,4 @@ -#![feature(const_fn)] +// only-x86_64 type Field1 = i32; type Field3 = i64; diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index 2545167aa0..6d44b3c8b2 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -5,6 +5,9 @@ LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } error[E0080]: it is undefined behavior to use this value --> $DIR/union-ice.rs:16:1 @@ -16,6 +19,9 @@ LL | | }; | |__^ type validation failed: encountered uninitialized bytes at .b, 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) { + __ __ __ __ __ __ __ __ 2a __ __ __ __ __ __ __ │ ░░░░░░░░*░░░░░░░ + } error[E0080]: it is undefined behavior to use this value --> $DIR/union-ice.rs:26:1 @@ -30,6 +36,11 @@ LL | | }; | |__^ type validation failed: encountered uninitialized bytes at .b[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: 40, align: 8) { + 0x00 │ 15 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ + 0x10 │ 17 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 │ ................ + 0x20 │ 2a __ __ __ __ __ __ __ │ *░░░░░░░ + } error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/union-ub.stderr b/src/test/ui/consts/const-eval/union-ub.32bit.stderr similarity index 75% rename from src/test/ui/consts/const-eval/union-ub.stderr rename to src/test/ui/consts/const-eval/union-ub.32bit.stderr index e8869d0d76..d3e4bad968 100644 --- a/src/test/ui/consts/const-eval/union-ub.stderr +++ b/src/test/ui/consts/const-eval/union-ub.32bit.stderr @@ -1,18 +1,24 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub.rs:32:1 + --> $DIR/union-ub.rs:33:1 | LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x2a, 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: 1, align: 1) { + 2a │ * + } error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub.rs:34:1 + --> $DIR/union-ub.rs:35:1 | LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, 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: 1, align: 1) { + __ │ ░ + } error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/union-ub.64bit.stderr b/src/test/ui/consts/const-eval/union-ub.64bit.stderr new file mode 100644 index 0000000000..d3e4bad968 --- /dev/null +++ b/src/test/ui/consts/const-eval/union-ub.64bit.stderr @@ -0,0 +1,25 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/union-ub.rs:33:1 + | +LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x2a, 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: 1, align: 1) { + 2a │ * + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/union-ub.rs:35:1 + | +LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, 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: 1, align: 1) { + __ │ ░ + } + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/union-ub.rs b/src/test/ui/consts/const-eval/union-ub.rs index 512359f5b1..c1bfe69a70 100644 --- a/src/test/ui/consts/const-eval/union-ub.rs +++ b/src/test/ui/consts/const-eval/union-ub.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth #![allow(const_err)] // make sure we cannot allow away the errors tested here #[repr(C)] diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr similarity index 97% rename from src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr rename to src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr index 3f22fac11f..e25abab7e3 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr @@ -26,6 +26,7 @@ LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 0, align: 1) {} warning: the type `!` does not permit zero-initialization --> $DIR/validate_uninhabited_zsts.rs:5:14 diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr new file mode 100644 index 0000000000..e25abab7e3 --- /dev/null +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr @@ -0,0 +1,56 @@ +warning: any use of this value will cause an error + --> $DIR/validate_uninhabited_zsts.rs:5:14 + | +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> + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_uninhabited_zsts.rs:18:1 + | +LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0] + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 0, align: 1) {} + +warning: the type `!` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:5:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `#[warn(invalid_value)]` on by default + = note: the `!` type has no valid value + +warning: the type `Empty` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:18:35 + | +LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: enums with no variants have no valid value + +error: aborting due to previous error; 3 warnings emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs index 4e1c71cd60..112ace5e97 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs @@ -1,4 +1,4 @@ -#![feature(const_fn)] +// stderr-per-bitwidth #![feature(const_fn_transmute)] const fn foo() -> ! { diff --git a/src/test/ui/consts/const-fn-error.rs b/src/test/ui/consts/const-fn-error.rs index 68a4d414ff..b9c5a0e040 100644 --- a/src/test/ui/consts/const-fn-error.rs +++ b/src/test/ui/consts/const-fn-error.rs @@ -1,5 +1,3 @@ -#![feature(const_fn)] - const X : usize = 2; const fn f(x: usize) -> usize { diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr index 86b1eebcb2..f5e69bba4c 100644 --- a/src/test/ui/consts/const-fn-error.stderr +++ b/src/test/ui/consts/const-fn-error.stderr @@ -1,5 +1,5 @@ error[E0744]: `for` is not allowed in a `const fn` - --> $DIR/const-fn-error.rs:7:5 + --> $DIR/const-fn-error.rs:5:5 | LL | / for i in 0..x { LL | | @@ -11,13 +11,13 @@ LL | | } | |_____^ error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/const-fn-error.rs:7:14 + --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ error[E0658]: mutable references are not allowed in constant functions - --> $DIR/const-fn-error.rs:7:14 + --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ @@ -26,22 +26,22 @@ LL | for i in 0..x { = 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/const-fn-error.rs:7:14 + --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ error[E0080]: evaluation of constant value failed - --> $DIR/const-fn-error.rs:7:14 + --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ | | | calling non-const function `<std::ops::Range<usize> as IntoIterator>::into_iter` - | inside `f` at $DIR/const-fn-error.rs:7:14 + | inside `f` at $DIR/const-fn-error.rs:5:14 ... LL | let a : [i32; f(X)]; - | ---- inside `main::{constant#0}` at $DIR/const-fn-error.rs:20:19 + | ---- inside `main::{constant#0}` at $DIR/const-fn-error.rs:18:19 error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-fn-mismatch.rs b/src/test/ui/consts/const-fn-mismatch.rs index d4cfba6460..3107b8128e 100644 --- a/src/test/ui/consts/const-fn-mismatch.rs +++ b/src/test/ui/consts/const-fn-mismatch.rs @@ -3,8 +3,6 @@ // it if the trait fn is const (but right now no trait fns can be // const). -#![feature(const_fn)] - trait Foo { fn f() -> u32; } diff --git a/src/test/ui/consts/const-fn-mismatch.stderr b/src/test/ui/consts/const-fn-mismatch.stderr index 0f4ce010fe..a86a06b3ef 100644 --- a/src/test/ui/consts/const-fn-mismatch.stderr +++ b/src/test/ui/consts/const-fn-mismatch.stderr @@ -1,5 +1,5 @@ error[E0379]: functions in traits cannot be declared const - --> $DIR/const-fn-mismatch.rs:13:5 + --> $DIR/const-fn-mismatch.rs:11:5 | LL | const fn f() -> u32 { | ^^^^^ functions in traits cannot be const diff --git a/src/test/ui/consts/const-fn-not-in-trait.rs b/src/test/ui/consts/const-fn-not-in-trait.rs index 1006d85468..00bae3f3b9 100644 --- a/src/test/ui/consts/const-fn-not-in-trait.rs +++ b/src/test/ui/consts/const-fn-not-in-trait.rs @@ -1,7 +1,5 @@ // Test that const fn is illegal in a trait declaration, whether or -// not a default is provided. - -#![feature(const_fn)] +// not a default is provided, and even with the feature gate. trait Foo { const fn f() -> u32; diff --git a/src/test/ui/consts/const-fn-not-in-trait.stderr b/src/test/ui/consts/const-fn-not-in-trait.stderr index 12ce306603..5d364eb882 100644 --- a/src/test/ui/consts/const-fn-not-in-trait.stderr +++ b/src/test/ui/consts/const-fn-not-in-trait.stderr @@ -1,11 +1,11 @@ error[E0379]: functions in traits cannot be declared const - --> $DIR/const-fn-not-in-trait.rs:7:5 + --> $DIR/const-fn-not-in-trait.rs:5:5 | LL | const fn f() -> u32; | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/const-fn-not-in-trait.rs:9:5 + --> $DIR/const-fn-not-in-trait.rs:7:5 | LL | const fn g() -> u32 { | ^^^^^ functions in traits cannot be const diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs index 0446ece421..726d6e9f74 100644 --- a/src/test/ui/consts/const-fn-not-safe-for-const.rs +++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs @@ -1,6 +1,6 @@ // Test that we can't call random fns in a const fn or do other bad things. -#![feature(const_fn, const_fn_transmute)] +#![feature(const_fn_transmute)] use std::mem::transmute; diff --git a/src/test/ui/consts/const-fn-type-name-any.rs b/src/test/ui/consts/const-fn-type-name-any.rs index 4ccfb42098..448c4fc044 100644 --- a/src/test/ui/consts/const-fn-type-name-any.rs +++ b/src/test/ui/consts/const-fn-type-name-any.rs @@ -1,6 +1,5 @@ // run-pass -#![feature(const_fn)] #![feature(const_type_name)] #![allow(dead_code)] diff --git a/src/test/ui/consts/const-fn-type-name.rs b/src/test/ui/consts/const-fn-type-name.rs index 72fac19c19..fd4f60cb88 100644 --- a/src/test/ui/consts/const-fn-type-name.rs +++ b/src/test/ui/consts/const-fn-type-name.rs @@ -1,7 +1,6 @@ // run-pass #![feature(core_intrinsics)] -#![feature(const_fn)] #![feature(const_type_name)] #![allow(dead_code)] diff --git a/src/test/ui/consts/const-fn.rs b/src/test/ui/consts/const-fn.rs index 7b924aa46a..1928c51885 100644 --- a/src/test/ui/consts/const-fn.rs +++ b/src/test/ui/consts/const-fn.rs @@ -3,7 +3,8 @@ // A very basic test of const fn functionality. -#![feature(const_fn, const_indexing)] +#![feature(const_indexing)] +#![feature(const_fn_trait_bound)] const fn add(x: u32, y: u32) -> u32 { x + y diff --git a/src/test/ui/consts/const-int-unchecked.rs b/src/test/ui/consts/const-int-unchecked.rs index 41d8f7a097..2ccc5d27bb 100644 --- a/src/test/ui/consts/const-int-unchecked.rs +++ b/src/test/ui/consts/const-int-unchecked.rs @@ -186,4 +186,13 @@ 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 +// 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 +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 + fn main() {} diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr index e5ecbbc71a..999b26543e 100644 --- a/src/test/ui/consts/const-int-unchecked.stderr +++ b/src/test/ui/consts/const-int-unchecked.stderr @@ -516,5 +516,27 @@ LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -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> -error: aborting due to 47 previous errors +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:191: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> + +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:194: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> + +error: aborting due to 49 previous errors diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs index 24df647f05..03b2f9e3c7 100644 --- a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -1,6 +1,5 @@ // check-pass #![feature(const_mut_refs)] -#![feature(const_fn)] #![feature(raw_ref_op)] struct Foo { diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs index 166ba20f12..f35f3c5e8e 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -1,5 +1,4 @@ #![feature(const_mut_refs)] -#![feature(const_fn)] #![feature(raw_ref_op)] #![feature(const_raw_ptr_deref)] diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr index cbae74cce6..fb43ce2131 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -1,11 +1,11 @@ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:12:21 + --> $DIR/mut_ref_in_final.rs:11:21 | LL | const B: *mut i32 = &mut 4; | ^^^^^^ error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:18:40 + --> $DIR/mut_ref_in_final.rs:17:40 | LL | const B3: Option<&mut i32> = Some(&mut 42); | ----------^^- @@ -15,7 +15,7 @@ LL | const B3: Option<&mut i32> = Some(&mut 42); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:21:42 + --> $DIR/mut_ref_in_final.rs:20:42 | LL | const B4: Option<&mut i32> = helper(&mut 42); | ------------^^- @@ -25,7 +25,7 @@ LL | const B4: Option<&mut i32> = helper(&mut 42); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:36:65 + --> $DIR/mut_ref_in_final.rs:35:65 | LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -35,7 +35,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:39:67 + --> $DIR/mut_ref_in_final.rs:38:67 | LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -45,7 +45,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:42:71 + --> $DIR/mut_ref_in_final.rs:41:71 | LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index 90977efd2b..638a98130a 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -1,5 +1,4 @@ #![feature(const_mut_refs)] -#![feature(const_fn)] #![feature(raw_ref_op)] #![feature(const_raw_ptr_deref)] diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index 45ae055614..6d3d18f6e6 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -1,12 +1,12 @@ error: any use of this value will cause an error - --> $DIR/mut_ref_in_final_dynamic_check.rs:15:10 + --> $DIR/mut_ref_in_final_dynamic_check.rs:14:10 | LL | Some(&mut *(42 as *mut i32)) | ^^^^^^^^^^^^^^^^^^^^^^ | | | unable to turn bytes into a pointer - | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:15:10 - | inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:20:29 + | 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(); | ------------------------------------- @@ -16,7 +16,7 @@ LL | const A: Option<&mut i32> = helper(); = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error: encountered dangling pointer in final constant - --> $DIR/mut_ref_in_final_dynamic_check.rs:27:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1 | LL | const B: Option<&mut i32> = helper2(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-points-to-static.stderr b/src/test/ui/consts/const-points-to-static.32bit.stderr similarity index 74% rename from src/test/ui/consts/const-points-to-static.stderr rename to src/test/ui/consts/const-points-to-static.32bit.stderr index 465537fb3d..c582678e2d 100644 --- a/src/test/ui/consts/const-points-to-static.stderr +++ b/src/test/ui/consts/const-points-to-static.32bit.stderr @@ -1,15 +1,18 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const-points-to-static.rs:5:1 + --> $DIR/const-points-to-static.rs:6:1 | LL | const TEST: &u8 = &MY_STATIC; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to a static variable | = 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──╼ │ ╾──╼ + } warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/const-points-to-static.rs:5:20 + --> $DIR/const-points-to-static.rs:6:20 | LL | const TEST: &u8 = &MY_STATIC; | ^^^^^^^^^ diff --git a/src/test/ui/consts/const-points-to-static.64bit.stderr b/src/test/ui/consts/const-points-to-static.64bit.stderr new file mode 100644 index 0000000000..1112499a3e --- /dev/null +++ b/src/test/ui/consts/const-points-to-static.64bit.stderr @@ -0,0 +1,22 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-points-to-static.rs:6:1 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to a static variable + | + = 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────────╼ │ ╾──────╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const-points-to-static.rs:6:20 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-points-to-static.rs b/src/test/ui/consts/const-points-to-static.rs index 7087b6e6a6..4359230685 100644 --- a/src/test/ui/consts/const-points-to-static.rs +++ b/src/test/ui/consts/const-points-to-static.rs @@ -1,11 +1,13 @@ // compile-flags: -Zunleash-the-miri-inside-of-you +// stderr-per-bitwidth #![allow(dead_code)] const TEST: &u8 = &MY_STATIC; //~^ ERROR it is undefined behavior to use this value //~| NOTE encountered a reference pointing to a static variable -//~| NOTE +//~| NOTE undefined behavior +//~| NOTE the raw bytes of the constant static MY_STATIC: u8 = 4; diff --git a/src/test/ui/consts/const_constructor/const-construct-call.rs b/src/test/ui/consts/const_constructor/const-construct-call.rs index d3e6cf78bc..cb735d7b30 100644 --- a/src/test/ui/consts/const_constructor/const-construct-call.rs +++ b/src/test/ui/consts/const_constructor/const-construct-call.rs @@ -1,11 +1,7 @@ -// Test that constructors are considered to be const fns with the required feature. +// Test that constructors are considered to be const fns // run-pass -// revisions: min_const_fn const_fn - -#![cfg_attr(const_fn, feature(const_fn))] - // Ctor(..) is transformed to Ctor { 0: ... } in THIR lowering, so directly // calling constructors doesn't require them to be const. diff --git a/src/test/ui/consts/const_constructor/const_constructor_qpath.rs b/src/test/ui/consts/const_constructor/const_constructor_qpath.rs index 18aa3d8e81..7c55f470fd 100644 --- a/src/test/ui/consts/const_constructor/const_constructor_qpath.rs +++ b/src/test/ui/consts/const_constructor/const_constructor_qpath.rs @@ -1,8 +1,5 @@ -// revisions: min_const_fn const_fn // run-pass -#![cfg_attr(const_fn, feature(const_fn))] - trait ConstDefault { const DEFAULT: Self; } diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index d016d236db..a47f6af029 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -1,6 +1,6 @@ // run-pass #![feature(const_discriminant)] -#![feature(test)] +#![feature(bench_black_box)] #![allow(dead_code)] use std::mem::{discriminant, Discriminant}; diff --git a/src/test/ui/consts/const_fn_trait_bound.gated.stderr b/src/test/ui/consts/const_fn_trait_bound.gated.stderr new file mode 100644 index 0000000000..ded05cb17c --- /dev/null +++ b/src/test/ui/consts/const_fn_trait_bound.gated.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/const_fn_trait_bound.rs:17:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const_fn_trait_bound.rs b/src/test/ui/consts/const_fn_trait_bound.rs new file mode 100644 index 0000000000..b1ef820d82 --- /dev/null +++ b/src/test/ui/consts/const_fn_trait_bound.rs @@ -0,0 +1,17 @@ +// gate-test-const_fn_trait_bound + +// revisions: stock gated + +#![feature(rustc_attrs)] +#![cfg_attr(gated, feature(const_fn_trait_bound))] + +const fn test1<T: std::ops::Add>() {} +//[stock]~^ trait bounds +const fn test2(_x: &dyn Send) {} +//[stock]~^ trait bounds +const fn test3() -> &'static dyn Send { loop {} } +//[stock]~^ trait bounds + + +#[rustc_error] +fn main() {} //[gated]~ fatal error triggered by #[rustc_error] diff --git a/src/test/ui/consts/const_fn_trait_bound.stock.stderr b/src/test/ui/consts/const_fn_trait_bound.stock.stderr new file mode 100644 index 0000000000..2ad45f3afd --- /dev/null +++ b/src/test/ui/consts/const_fn_trait_bound.stock.stderr @@ -0,0 +1,30 @@ +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/const_fn_trait_bound.rs:8:16 + | +LL | const fn test1<T: std::ops::Add>() {} + | ^ + | + = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable + +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/const_fn_trait_bound.rs:10:16 + | +LL | const fn test2(_x: &dyn Send) {} + | ^^ + | + = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable + +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable + --> $DIR/const_fn_trait_bound.rs:12:21 + | +LL | const fn test3() -> &'static dyn Send { loop {} } + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information + = help: add `#![feature(const_fn_trait_bound)]` 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/consts/const_fn_unsize.gated.stderr b/src/test/ui/consts/const_fn_unsize.gated.stderr new file mode 100644 index 0000000000..8a65c274ca --- /dev/null +++ b/src/test/ui/consts/const_fn_unsize.gated.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/const_fn_unsize.rs:16:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const_fn_unsize.rs b/src/test/ui/consts/const_fn_unsize.rs new file mode 100644 index 0000000000..0cab3b0a03 --- /dev/null +++ b/src/test/ui/consts/const_fn_unsize.rs @@ -0,0 +1,16 @@ +// gate-test-const_fn_unsize + +// revisions: stock gated + +#![feature(rustc_attrs)] +#![cfg_attr(gated, feature(const_fn_unsize))] + +use std::ptr::NonNull; + +const fn test() { + let _x = NonNull::<[i32; 0]>::dangling() as NonNull<[i32]>; + //[stock]~^ unsizing cast +} + +#[rustc_error] +fn main() {} //[gated]~ fatal error triggered by #[rustc_error] diff --git a/src/test/ui/consts/const_fn_unsize.stock.stderr b/src/test/ui/consts/const_fn_unsize.stock.stderr new file mode 100644 index 0000000000..cc746d4f17 --- /dev/null +++ b/src/test/ui/consts/const_fn_unsize.stock.stderr @@ -0,0 +1,12 @@ +error[E0658]: unsizing casts to types besides slices are not allowed in const fn + --> $DIR/const_fn_unsize.rs:11:14 + | +LL | let _x = NonNull::<[i32; 0]>::dangling() as NonNull<[i32]>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #64992 <https://github.com/rust-lang/rust/issues/64992> for more information + = help: add `#![feature(const_fn_unsize)]` 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/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs index 2fd6e06067..1f68de8eed 100644 --- a/src/test/ui/consts/const_let_assign3.rs +++ b/src/test/ui/consts/const_let_assign3.rs @@ -1,5 +1,3 @@ -#![feature(const_fn)] - struct S { state: u32, } diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr index 3eac61c0ce..89073f975e 100644 --- a/src/test/ui/consts/const_let_assign3.stderr +++ b/src/test/ui/consts/const_let_assign3.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constant functions - --> $DIR/const_let_assign3.rs:8:18 + --> $DIR/const_let_assign3.rs:6:18 | LL | const fn foo(&mut self, x: u32) { | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | const fn foo(&mut self, x: u32) { = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constants - --> $DIR/const_let_assign3.rs:16:5 + --> $DIR/const_let_assign3.rs:14:5 | LL | s.foo(3); | ^ @@ -17,7 +17,7 @@ LL | s.foo(3); = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constants - --> $DIR/const_let_assign3.rs:22:13 + --> $DIR/const_let_assign3.rs:20:13 | LL | let y = &mut x; | ^^^^^^ diff --git a/src/test/ui/consts/const_unsafe_unreachable.rs b/src/test/ui/consts/const_unsafe_unreachable.rs index cfed6e5deb..1fec491ca9 100644 --- a/src/test/ui/consts/const_unsafe_unreachable.rs +++ b/src/test/ui/consts/const_unsafe_unreachable.rs @@ -1,6 +1,5 @@ // run-pass -#![feature(const_fn)] #![feature(const_unreachable_unchecked)] const unsafe fn foo(x: bool) -> bool { diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.rs b/src/test/ui/consts/const_unsafe_unreachable_ub.rs index 0bd37876cc..4ae3a88c45 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.rs +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.rs @@ -1,6 +1,5 @@ // build-fail -#![feature(const_fn)] #![feature(const_unreachable_unchecked)] const unsafe fn foo(x: bool) -> bool { diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr index 3f122b2a85..68d8747d28 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr @@ -6,16 +6,16 @@ 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:9:18 - | inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:14:28 + | 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:14:1 + ::: $DIR/const_unsafe_unreachable_ub.rs:13:1 | LL | const BAR: bool = unsafe { foo(false) }; | ---------------------------------------- | note: the lint level is defined here - --> $DIR/const_unsafe_unreachable_ub.rs:13:8 + --> $DIR/const_unsafe_unreachable_ub.rs:12:8 | LL | #[warn(const_err)] | ^^^^^^^^^ @@ -23,13 +23,13 @@ LL | #[warn(const_err)] = 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:17:14 + --> $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:17:3 + --> $DIR/const_unsafe_unreachable_ub.rs:16:3 | LL | assert_eq!(BAR, true); | ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors diff --git a/src/test/ui/consts/control-flow/basics.rs b/src/test/ui/consts/control-flow/basics.rs index 6dd6192941..3a4f24bbcc 100644 --- a/src/test/ui/consts/control-flow/basics.rs +++ b/src/test/ui/consts/control-flow/basics.rs @@ -3,7 +3,6 @@ // run-pass #![feature(const_panic)] -#![feature(const_fn)] const X: u32 = 4; const Y: u32 = 5; diff --git a/src/test/ui/consts/issue-32829-2.rs b/src/test/ui/consts/issue-32829-2.rs index c93c84b5fb..e0fcf27833 100644 --- a/src/test/ui/consts/issue-32829-2.rs +++ b/src/test/ui/consts/issue-32829-2.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - const bad : u32 = { { 5; diff --git a/src/test/ui/consts/issue-32829-2.stderr b/src/test/ui/consts/issue-32829-2.stderr index 8d7423f29a..1d265875c5 100644 --- a/src/test/ui/consts/issue-32829-2.stderr +++ b/src/test/ui/consts/issue-32829-2.stderr @@ -1,17 +1,17 @@ error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants - --> $DIR/issue-32829-2.rs:12:9 + --> $DIR/issue-32829-2.rs:10:9 | LL | invalid(); | ^^^^^^^^^ error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/issue-32829-2.rs:34:9 + --> $DIR/issue-32829-2.rs:32:9 | LL | invalid(); | ^^^^^^^^^ error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/issue-32829-2.rs:56:9 + --> $DIR/issue-32829-2.rs:54:9 | LL | invalid(); | ^^^^^^^^^ diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/consts/issue-52060.rs similarity index 100% rename from src/test/ui/issues/issue-52060.rs rename to src/test/ui/consts/issue-52060.rs diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/consts/issue-52060.stderr similarity index 100% rename from src/test/ui/issues/issue-52060.stderr rename to src/test/ui/consts/issue-52060.stderr diff --git a/src/test/ui/consts/issue-63952.stderr b/src/test/ui/consts/issue-63952.32bit.stderr similarity index 77% rename from src/test/ui/consts/issue-63952.stderr rename to src/test/ui/consts/issue-63952.32bit.stderr index 503c5706fa..6d52ed065b 100644 --- a/src/test/ui/consts/issue-63952.stderr +++ b/src/test/ui/consts/issue-63952.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/issue-63952.rs:16:1 + --> $DIR/issue-63952.rs:17:1 | LL | / const SLICE_WAY_TOO_LONG: &[u8] = unsafe { LL | | SliceTransmute { @@ -11,6 +11,9 @@ LL | | }; | |__^ type validation failed: 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) { + ╾─alloc3──╼ ff ff ff ff │ ╾──╼.... + } error: aborting due to previous error diff --git a/src/test/ui/consts/issue-63952.64bit.stderr b/src/test/ui/consts/issue-63952.64bit.stderr new file mode 100644 index 0000000000..3335c5bf72 --- /dev/null +++ b/src/test/ui/consts/issue-63952.64bit.stderr @@ -0,0 +1,20 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-63952.rs:17:1 + | +LL | / const SLICE_WAY_TOO_LONG: &[u8] = unsafe { +LL | | SliceTransmute { +LL | | repr: SliceRepr { +LL | | ptr: &42, +... | +LL | | .slice +LL | | }; + | |__^ type validation failed: 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) { + ╾───────alloc3────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/issue-63952.rs b/src/test/ui/consts/issue-63952.rs index f50e1e51f6..5c83e6f45c 100644 --- a/src/test/ui/consts/issue-63952.rs +++ b/src/test/ui/consts/issue-63952.rs @@ -1,4 +1,5 @@ // Regression test for #63952, shouldn't hang. +// stderr-per-bitwidth #[repr(C)] #[derive(Copy, Clone)] diff --git a/src/test/ui/consts/issue-79690.stderr b/src/test/ui/consts/issue-79690.64bit.stderr similarity index 68% rename from src/test/ui/consts/issue-79690.stderr rename to src/test/ui/consts/issue-79690.64bit.stderr index ca56ff2205..2639bc4812 100644 --- a/src/test/ui/consts/issue-79690.stderr +++ b/src/test/ui/consts/issue-79690.64bit.stderr @@ -1,10 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/issue-79690.rs:29:1 + --> $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 | = 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────────╼ │ ╾──────╼╾──────╼ + } error: aborting due to previous error diff --git a/src/test/ui/consts/issue-79690.rs b/src/test/ui/consts/issue-79690.rs index a2e7b97b31..56747bf5a1 100644 --- a/src/test/ui/consts/issue-79690.rs +++ b/src/test/ui/consts/issue-79690.rs @@ -1,5 +1,6 @@ // ignore-32bit // This test gives a different error on 32-bit architectures. +// stderr-per-bitwidth union Transmute<T: Copy, U: Copy> { t: T, diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index ee5434b147..e6ce7e1252 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -130,23 +130,23 @@ LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.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[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:84:16 | LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t } | ^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:86:18 | LL | const fn foo11_2<T: Send>(t: T) -> T { t } | ^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0013]: constant functions cannot refer to statics --> $DIR/min_const_fn.rs:90:27 @@ -209,41 +209,41 @@ LL | const fn inc(x: &mut i32) { *x += 1 } = 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[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:110:6 | LL | impl<T: std::fmt::Debug> Foo<T> { | ^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:115:6 | LL | impl<T: std::fmt::Debug + Sized> Foo<T> { | ^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:120:6 | LL | impl<T: Sync + Sized> Foo<T> { | ^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:126:34 | LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {} | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:126:19 @@ -253,14 +253,14 @@ LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {} | | | constant functions cannot evaluate destructors -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:129:22 | LL | const fn no_apit(_x: impl std::fmt::Debug) {} | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:129:18 @@ -270,50 +270,50 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | | | constant functions cannot evaluate destructors -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:132:23 | LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} | ^^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:134:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0723]: unsizing casts to types besides slices are not allowed in const fn +error[E0658]: unsizing casts to types besides slices are not allowed in const fn --> $DIR/min_const_fn.rs:134:63 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^ | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = note: see issue #64992 <https://github.com/rust-lang/rust/issues/64992> for more information + = help: add `#![feature(const_fn_unsize)]` to the crate attributes to enable -error[E0723]: unsizing casts to types besides slices are not allowed in const fn +error[E0658]: unsizing casts to types besides slices are not allowed in const fn --> $DIR/min_const_fn.rs:134:63 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^ | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = note: see issue #64992 <https://github.com/rust-lang/rust/issues/64992> for more information + = help: add `#![feature(const_fn_unsize)]` to the crate attributes to enable -error[E0723]: unsizing casts to types besides slices are not allowed in const fn +error[E0658]: unsizing casts to types besides slices are not allowed in const fn --> $DIR/min_const_fn.rs:141:42 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } | ^^^ | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = note: see issue #64992 <https://github.com/rust-lang/rust/issues/64992> for more information + = help: add `#![feature(const_fn_unsize)]` to the crate attributes to enable error[E0658]: function pointers cannot appear in constant functions --> $DIR/min_const_fn.rs:144:21 @@ -344,5 +344,5 @@ LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } error: aborting due to 39 previous errors -Some errors have detailed explanations: E0013, E0493, E0658, E0723. +Some errors have detailed explanations: E0013, E0493, E0658. For more information about an error, try `rustc --explain E0013`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr index 1394db591c..cf635d6569 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr @@ -1,21 +1,21 @@ -error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn_dyn.rs:9:5 | LL | x.0.field; | ^^^^^^^^^ | = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0723]: unsizing casts to types besides slices are not allowed in const fn +error[E0658]: unsizing casts to types besides slices are not allowed in const fn --> $DIR/min_const_fn_dyn.rs:12:66 | LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } | ^^ | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = note: see issue #64992 <https://github.com/rust-lang/rust/issues/64992> for more information + = help: add `#![feature(const_fn_unsize)]` to the crate attributes to enable error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index 292e2dd167..35aa587d3d 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn, const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(const_fn_floating_point_arithmetic, foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs index 0f48341ddf..962a57bb8e 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn, const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(const_fn_floating_point_arithmetic, foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] @@ -25,7 +25,7 @@ const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR not yet stable as #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.0.0")] -// conformity is required, even with `const_fn` feature gate +// conformity is required const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~^ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs index d17dcb2811..194f5fc1e5 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn, foo, foo2)] +#![feature(foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/ui/mir_check_nonconst.rs b/src/test/ui/consts/mir_check_nonconst.rs similarity index 100% rename from src/test/ui/mir_check_nonconst.rs rename to src/test/ui/consts/mir_check_nonconst.rs diff --git a/src/test/ui/mir_check_nonconst.stderr b/src/test/ui/consts/mir_check_nonconst.stderr similarity index 100% rename from src/test/ui/mir_check_nonconst.stderr rename to src/test/ui/consts/mir_check_nonconst.stderr diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr similarity index 74% rename from src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr rename to src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr index 2e40b38dac..6ca18290b4 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr @@ -1,43 +1,51 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static2.rs:10:1 + --> $DIR/const_refers_to_static2.rs:11:1 | LL | / const REF_INTERIOR_MUT: &usize = { LL | | LL | | +LL | | LL | | static FOO: AtomicUsize = AtomicUsize::new(0); LL | | unsafe { &*(&FOO as *const _ as *const usize) } LL | | }; | |__^ type validation failed: encountered a reference pointing to a static variable | = 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──╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static2.rs:18:1 + --> $DIR/const_refers_to_static2.rs:20:1 | LL | / const READ_IMMUT: &usize = { LL | | LL | | +LL | | LL | | static FOO: usize = 0; LL | | &FOO LL | | }; | |__^ type validation failed: encountered a reference pointing to a static variable | = 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──╼ │ ╾──╼ + } warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static2.rs:14:18 + --> $DIR/const_refers_to_static2.rs:16:18 | LL | unsafe { &*(&FOO as *const _ as *const usize) } | ^^^ help: skipping check for `const_raw_ptr_deref` feature - --> $DIR/const_refers_to_static2.rs:14:14 + --> $DIR/const_refers_to_static2.rs:16:14 | LL | unsafe { &*(&FOO as *const _ as *const usize) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static2.rs:22:6 + --> $DIR/const_refers_to_static2.rs:25:6 | LL | &FOO | ^^^ diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr new file mode 100644 index 0000000000..5521cd34aa --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr @@ -0,0 +1,55 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static2.rs:11:1 + | +LL | / const REF_INTERIOR_MUT: &usize = { +LL | | +LL | | +LL | | +LL | | static FOO: AtomicUsize = AtomicUsize::new(0); +LL | | unsafe { &*(&FOO as *const _ as *const usize) } +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = 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────────╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static2.rs:20:1 + | +LL | / const READ_IMMUT: &usize = { +LL | | +LL | | +LL | | +LL | | static FOO: usize = 0; +LL | | &FOO +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = 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────────╼ │ ╾──────╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static2.rs:16:18 + | +LL | unsafe { &*(&FOO as *const _ as *const usize) } + | ^^^ +help: skipping check for `const_raw_ptr_deref` feature + --> $DIR/const_refers_to_static2.rs:16:14 + | +LL | unsafe { &*(&FOO as *const _ as *const usize) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static2.rs:25:6 + | +LL | &FOO + | ^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs index b5db685ef2..2548474d4f 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs @@ -1,4 +1,5 @@ // compile-flags: -Zunleash-the-miri-inside-of-you +// stderr-per-bitwidth #![allow(const_err)] use std::sync::atomic::AtomicUsize; @@ -9,7 +10,8 @@ use std::sync::atomic::Ordering; const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this value //~| NOTE encountered a reference pointing to a static variable -//~| NOTE +//~| NOTE undefined behavior +//~| NOTE the raw bytes of the constant static FOO: AtomicUsize = AtomicUsize::new(0); unsafe { &*(&FOO as *const _ as *const usize) } }; @@ -17,7 +19,8 @@ const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this valu // ok some day perhaps const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value //~| NOTE encountered a reference pointing to a static variable -//~| NOTE +//~| NOTE undefined behavior +//~| NOTE the raw bytes of the constant static FOO: usize = 0; &FOO }; diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr similarity index 75% rename from src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr rename to src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index a9d6fde6c0..73d1d7c5b9 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -1,41 +1,49 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:11:1 + --> $DIR/const_refers_to_static_cross_crate.rs:12:1 | LL | / const SLICE_MUT: &[u8; 1] = { LL | | LL | | +LL | | LL | | unsafe { &static_cross_crate::ZERO } LL | | }; | |__^ type validation failed: encountered a reference pointing to a static variable | = 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──╼ │ ╾──╼ + } error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:44:9 + --> $DIR/const_refers_to_static_cross_crate.rs:47:9 | LL | SLICE_MUT => true, | ^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:17:1 + --> $DIR/const_refers_to_static_cross_crate.rs:19:1 | LL | / const U8_MUT: &u8 = { LL | | LL | | +LL | | LL | | unsafe { &static_cross_crate::ZERO[0] } LL | | }; | |__^ type validation failed: encountered a reference pointing to a static variable | = 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──╼ │ ╾──╼ + } error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:53:9 + --> $DIR/const_refers_to_static_cross_crate.rs:56:9 | LL | U8_MUT => true, | ^^^^^^ warning: any use of this value will cause an error - --> $DIR/const_refers_to_static_cross_crate.rs:26:15 + --> $DIR/const_refers_to_static_cross_crate.rs:29:15 | LL | / const U8_MUT2: &u8 = { LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } @@ -48,7 +56,7 @@ LL | | }; | |__- | note: the lint level is defined here - --> $DIR/const_refers_to_static_cross_crate.rs:24:8 + --> $DIR/const_refers_to_static_cross_crate.rs:27:8 | LL | #[warn(const_err)] | ^^^^^^^^^ @@ -56,13 +64,13 @@ LL | #[warn(const_err)] = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:64:9 + --> $DIR/const_refers_to_static_cross_crate.rs:67:9 | LL | U8_MUT2 => true, | ^^^^^^^ warning: any use of this value will cause an error - --> $DIR/const_refers_to_static_cross_crate.rs:34:51 + --> $DIR/const_refers_to_static_cross_crate.rs:37:51 | LL | / const U8_MUT3: &u8 = { LL | | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } @@ -75,7 +83,7 @@ LL | | }; | |__- | note: the lint level is defined here - --> $DIR/const_refers_to_static_cross_crate.rs:32:8 + --> $DIR/const_refers_to_static_cross_crate.rs:35:8 | LL | #[warn(const_err)] | ^^^^^^^^^ @@ -83,31 +91,31 @@ LL | #[warn(const_err)] = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:72:9 + --> $DIR/const_refers_to_static_cross_crate.rs:75:9 | LL | U8_MUT3 => true, | ^^^^^^^ error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:44:9 + --> $DIR/const_refers_to_static_cross_crate.rs:47:9 | LL | SLICE_MUT => true, | ^^^^^^^^^ error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:53:9 + --> $DIR/const_refers_to_static_cross_crate.rs:56:9 | LL | U8_MUT => true, | ^^^^^^ error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:64:9 + --> $DIR/const_refers_to_static_cross_crate.rs:67:9 | LL | U8_MUT2 => true, | ^^^^^^^ error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:72:9 + --> $DIR/const_refers_to_static_cross_crate.rs:75:9 | LL | U8_MUT3 => true, | ^^^^^^^ @@ -115,57 +123,57 @@ LL | U8_MUT3 => true, warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:14:15 + --> $DIR/const_refers_to_static_cross_crate.rs:16:15 | LL | unsafe { &static_cross_crate::ZERO } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:14:15 + --> $DIR/const_refers_to_static_cross_crate.rs:16:15 | LL | unsafe { &static_cross_crate::ZERO } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:20:15 + --> $DIR/const_refers_to_static_cross_crate.rs:23:15 | LL | unsafe { &static_cross_crate::ZERO[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:20:15 + --> $DIR/const_refers_to_static_cross_crate.rs:23:15 | LL | unsafe { &static_cross_crate::ZERO[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:20:15 + --> $DIR/const_refers_to_static_cross_crate.rs:23:15 | LL | unsafe { &static_cross_crate::ZERO[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:26:17 + --> $DIR/const_refers_to_static_cross_crate.rs:29:17 | LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:34:20 + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:34:20 + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:34:20 + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_panic` feature - --> $DIR/const_refers_to_static_cross_crate.rs:34:77 + --> $DIR/const_refers_to_static_cross_crate.rs:37:77 | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static_cross_crate.rs:34:20 + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr new file mode 100644 index 0000000000..7228f7178f --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -0,0 +1,184 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:12:1 + | +LL | / const SLICE_MUT: &[u8; 1] = { +LL | | +LL | | +LL | | +LL | | unsafe { &static_cross_crate::ZERO } +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = 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────────╼ │ ╾──────╼ + } + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:47:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:19:1 + | +LL | / const U8_MUT: &u8 = { +LL | | +LL | | +LL | | +LL | | unsafe { &static_cross_crate::ZERO[0] } +LL | | }; + | |__^ type validation failed: encountered a reference pointing to a static variable + | + = 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────────╼ │ ╾──────╼ + } + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:56:9 + | +LL | U8_MUT => true, + | ^^^^^^ + +warning: any use of this value will cause an error + --> $DIR/const_refers_to_static_cross_crate.rs:29:15 + | +LL | / const U8_MUT2: &u8 = { +LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static +LL | | +LL | | +LL | | +LL | | +LL | | }; + | |__- + | +note: the lint level is defined here + --> $DIR/const_refers_to_static_cross_crate.rs:27: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: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:67:9 + | +LL | U8_MUT2 => true, + | ^^^^^^^ + +warning: any use of this value will cause an error + --> $DIR/const_refers_to_static_cross_crate.rs:37:51 + | +LL | / const U8_MUT3: &u8 = { +LL | | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | | ^^^^^^^^^^^ constant accesses static +LL | | +LL | | +... | +LL | | +LL | | }; + | |__- + | +note: the lint level is defined here + --> $DIR/const_refers_to_static_cross_crate.rs:35: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: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:75:9 + | +LL | U8_MUT3 => true, + | ^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:47:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:56:9 + | +LL | U8_MUT => true, + | ^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:67:9 + | +LL | U8_MUT2 => true, + | ^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:75:9 + | +LL | U8_MUT3 => true, + | ^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:16:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:16:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:23:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:23:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:23:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:29:17 + | +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check for `const_panic` feature + --> $DIR/const_refers_to_static_cross_crate.rs:37:77 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:37:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors; 3 warnings emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index 7bbe9c8770..53f70198f4 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -1,5 +1,6 @@ // compile-flags: -Zunleash-the-miri-inside-of-you // aux-build:static_cross_crate.rs +// stderr-per-bitwidth #![allow(const_err)] #![feature(exclusive_range_pattern, half_open_range_patterns)] @@ -10,13 +11,15 @@ extern crate static_cross_crate; // Allowing this would be a disaster for pattern matching, we could violate exhaustiveness checking! const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior to use this value //~| NOTE encountered a reference pointing to a static variable -//~| NOTE +//~| NOTE undefined behavior +//~| NOTE the raw bytes of the constant unsafe { &static_cross_crate::ZERO } }; const U8_MUT: &u8 = { //~ ERROR undefined behavior to use this value //~| NOTE encountered a reference pointing to a static variable -//~| NOTE +//~| NOTE undefined behavior +//~| NOTE the raw bytes of the constant unsafe { &static_cross_crate::ZERO[0] } }; diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr similarity index 72% rename from src/test/ui/consts/miri_unleashed/mutable_references_err.stderr rename to src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 0c206dd51a..62126ef2ba 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_err.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references_err.rs:16:1 + --> $DIR/mutable_references_err.rs:17:1 | LL | / const MUH: Meh = Meh { LL | | x: &UnsafeCell::new(42), @@ -7,37 +7,46 @@ LL | | }; | |__^ type validation failed: encountered `UnsafeCell` in a `const` at .x.<deref> | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc2──╼ │ ╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references_err.rs:26:1 + --> $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 | = 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──╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references_err.rs:30:1 + --> $DIR/mutable_references_err.rs:31:1 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: 4, align: 4) { + ╾─alloc10─╼ │ ╾──╼ + } warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:17:8 + --> $DIR/mutable_references_err.rs:18:8 | LL | x: &UnsafeCell::new(42), | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:26:27 + --> $DIR/mutable_references_err.rs:27:27 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:30:25 + --> $DIR/mutable_references_err.rs:31:25 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^ diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr new file mode 100644 index 0000000000..606184e573 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -0,0 +1,56 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:17:1 + | +LL | / const MUH: Meh = Meh { +LL | | x: &UnsafeCell::new(42), +LL | | }; + | |__^ type validation failed: encountered `UnsafeCell` in a `const` at .x.<deref> + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc2────────╼ │ ╾──────╼ + } + +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 + | + = 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────────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:31:1 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: 8) { + ╾───────alloc10───────╼ │ ╾──────╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:18:8 + | +LL | x: &UnsafeCell::new(42), + | ^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:27:27 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:31:25 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.rs b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs index 195414dbad..722b9cf94e 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_err.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth // compile-flags: -Zunleash-the-miri-inside-of-you #![allow(const_err)] diff --git a/src/test/ui/consts/offset_ub.rs b/src/test/ui/consts/offset_ub.rs index 4f943ed9ad..7ce45ba9c4 100644 --- a/src/test/ui/consts/offset_ub.rs +++ b/src/test/ui/consts/offset_ub.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![feature(const_ptr_offset)] use std::ptr; diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr index 5e8b7a8e0b..082142fbbb 100644 --- a/src/test/ui/consts/offset_ub.stderr +++ b/src/test/ui/consts/offset_ub.stderr @@ -6,9 +6,9 @@ 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:7:46 + | inside `BEFORE_START` at $DIR/offset_ub.rs:6:46 | - ::: $DIR/offset_ub.rs:7:1 + ::: $DIR/offset_ub.rs:6:1 | LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; | ------------------------------------------------------------------------------ @@ -25,9 +25,9 @@ LL | unsafe { intrinsics::offset(self, count) } | | | inbounds test failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1 | 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:8:43 + | inside `AFTER_END` at $DIR/offset_ub.rs:7:43 | - ::: $DIR/offset_ub.rs:8:1 + ::: $DIR/offset_ub.rs:7:1 | LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; | -------------------------------------------------------------------------- @@ -43,9 +43,9 @@ LL | unsafe { intrinsics::offset(self, count) } | | | inbounds test failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100 | 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:9:45 + | inside `AFTER_ARRAY` at $DIR/offset_ub.rs:8:45 | - ::: $DIR/offset_ub.rs:9:1 + ::: $DIR/offset_ub.rs:8:1 | LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; | ------------------------------------------------------------------------------ @@ -61,9 +61,9 @@ 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:11:43 + | inside `OVERFLOW` at $DIR/offset_ub.rs:10:43 | - ::: $DIR/offset_ub.rs:11:1 + ::: $DIR/offset_ub.rs:10:1 | LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; | ---------------------------------------------------------------------------------- @@ -79,9 +79,9 @@ 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:12:44 + | inside `UNDERFLOW` at $DIR/offset_ub.rs:11:44 | - ::: $DIR/offset_ub.rs:12:1 + ::: $DIR/offset_ub.rs:11:1 | LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; | ----------------------------------------------------------------------------------- @@ -97,9 +97,9 @@ 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:13:56 + | inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:12:56 | - ::: $DIR/offset_ub.rs:13:1 + ::: $DIR/offset_ub.rs:12:1 | LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; | --------------------------------------------------------------------------------------------- @@ -115,9 +115,9 @@ 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:14:57 + | inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:57 | - ::: $DIR/offset_ub.rs:14:1 + ::: $DIR/offset_ub.rs:13:1 | LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; | -------------------------------------------------------------------------------------- @@ -133,9 +133,9 @@ LL | unsafe { intrinsics::offset(self, count) } | | | inbounds test failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0 | 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:16:50 + | inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:15:50 | - ::: $DIR/offset_ub.rs:16:1 + ::: $DIR/offset_ub.rs:15:1 | LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; | ------------------------------------------------------------------------------- @@ -151,9 +151,9 @@ LL | unsafe { intrinsics::offset(self, count) as *mut T } | | | unable to turn bytes into a 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:17:42 + | inside `DANGLING` at $DIR/offset_ub.rs:16:42 | - ::: $DIR/offset_ub.rs:17:1 + ::: $DIR/offset_ub.rs:16:1 | LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) }; | --------------------------------------------------------------------------------------------- @@ -169,9 +169,9 @@ LL | unsafe { intrinsics::offset(self, count) } | | | inbounds test 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:20:50 + | inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:19:50 | - ::: $DIR/offset_ub.rs:20:1 + ::: $DIR/offset_ub.rs:19:1 | LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) }; | ------------------------------------------------------------------------------- @@ -187,9 +187,9 @@ LL | unsafe { intrinsics::offset(self, count) } | | | unable to turn bytes into a 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:23:47 + | inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:22:47 | - ::: $DIR/offset_ub.rs:23:1 + ::: $DIR/offset_ub.rs:22:1 | LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) }; | --------------------------------------------------------------------------------------------- diff --git a/src/test/ui/consts/promote-not.rs b/src/test/ui/consts/promote-not.rs index 0d0c78b0fc..20c1169c26 100644 --- a/src/test/ui/consts/promote-not.rs +++ b/src/test/ui/consts/promote-not.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength // Test various things that we do not want to promote. #![allow(unconditional_panic, const_err)] -#![feature(const_fn, const_fn_union)] +#![feature(const_fn_union)] use std::cell::Cell; diff --git a/src/test/ui/consts/rustc-args-required-const.rs b/src/test/ui/consts/rustc-args-required-const.rs index 87f979f1b2..0723b66879 100644 --- a/src/test/ui/consts/rustc-args-required-const.rs +++ b/src/test/ui/consts/rustc-args-required-const.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, const_fn)] +#![feature(rustc_attrs)] #[rustc_args_required_const(0)] fn foo(_a: i32) { diff --git a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs index 651462d7ef..2b970390f0 100644 --- a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs +++ b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs @@ -1,6 +1,6 @@ #![stable(feature = "core", since = "1.6.0")] #![feature(staged_api)] -#![feature(const_precise_live_drops, const_fn)] +#![feature(const_precise_live_drops)] enum Either<T, S> { Left(T), diff --git a/src/test/ui/consts/std/alloc.stderr b/src/test/ui/consts/std/alloc.32bit.stderr similarity index 79% rename from src/test/ui/consts/std/alloc.stderr rename to src/test/ui/consts/std/alloc.32bit.stderr index 26b7a24ebf..bb9ccbba37 100644 --- a/src/test/ui/consts/std/alloc.stderr +++ b/src/test/ui/consts/std/alloc.32bit.stderr @@ -1,10 +1,13 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:7:1 + --> $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 | = 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) { + 00 10 00 00 00 00 00 00 │ ........ + } error: aborting due to previous error diff --git a/src/test/ui/consts/std/alloc.64bit.stderr b/src/test/ui/consts/std/alloc.64bit.stderr new file mode 100644 index 0000000000..2c891b1d79 --- /dev/null +++ b/src/test/ui/consts/std/alloc.64bit.stderr @@ -0,0 +1,14 @@ +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 + | + = 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) { + 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/std/alloc.rs b/src/test/ui/consts/std/alloc.rs index 65ac7e4492..14eadc4487 100644 --- a/src/test/ui/consts/std/alloc.rs +++ b/src/test/ui/consts/std/alloc.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth use std::alloc::Layout; // ok diff --git a/src/test/ui/consts/unsizing-cast-non-null.stderr b/src/test/ui/consts/unsizing-cast-non-null.stderr index dc08ccd02b..79691cddfb 100644 --- a/src/test/ui/consts/unsizing-cast-non-null.stderr +++ b/src/test/ui/consts/unsizing-cast-non-null.stderr @@ -1,12 +1,12 @@ -error[E0723]: unsizing casts to types besides slices are not allowed in const fn +error[E0658]: unsizing casts to types besides slices are not allowed in const fn --> $DIR/unsizing-cast-non-null.rs:6:5 | LL | NonNull::<[T; 0]>::dangling() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = note: see issue #64992 <https://github.com/rust-lang/rust/issues/64992> for more information + = help: add `#![feature(const_fn_unsize)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs index 43951c6854..2fbbbbffac 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.rs +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs @@ -6,7 +6,7 @@ #![stable(feature = "core", since = "1.6.0")] #![feature(rustc_const_unstable)] #![feature(staged_api)] -#![feature(const_fn)] +#![feature(const_fn_trait_bound)] enum Opt<T> { Some(T), diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.32bit.stderr similarity index 75% rename from src/test/ui/consts/validate_never_arrays.stderr rename to src/test/ui/consts/validate_never_arrays.32bit.stderr index 77f0a2ebd4..2d1bba391e 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.32bit.stderr @@ -1,26 +1,35 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/validate_never_arrays.rs:3:1 + --> $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] | = 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) { + 01 00 00 00 │ .... + } error[E0080]: it is undefined behavior to use this value - --> $DIR/validate_never_arrays.rs:6:1 + --> $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] | = 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) { + 01 00 00 00 01 00 00 00 │ ........ + } error[E0080]: it is undefined behavior to use this value - --> $DIR/validate_never_arrays.rs:7:1 + --> $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] | = 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) { + 01 00 00 00 2a 00 00 00 │ ....*... + } error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/validate_never_arrays.64bit.stderr b/src/test/ui/consts/validate_never_arrays.64bit.stderr new file mode 100644 index 0000000000..dd677f1b21 --- /dev/null +++ b/src/test/ui/consts/validate_never_arrays.64bit.stderr @@ -0,0 +1,36 @@ +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] + | + = 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) { + 01 00 00 00 00 00 00 00 │ ........ + } + +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] + | + = 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) { + 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ + } + +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] + | + = 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) { + 01 00 00 00 00 00 00 00 2a 00 00 00 00 00 00 00 │ ........*....... + } + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/validate_never_arrays.rs b/src/test/ui/consts/validate_never_arrays.rs index c7144f05ec..1990fb0739 100644 --- a/src/test/ui/consts/validate_never_arrays.rs +++ b/src/test/ui/consts/validate_never_arrays.rs @@ -1,3 +1,4 @@ +// stderr-per-bitwidth #![feature(const_raw_ptr_deref, never_type)] const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr index 36cf57bd3c..79095452f9 100644 --- a/src/test/ui/copy-a-resource.stderr +++ b/src/test/ui/copy-a-resource.stderr @@ -6,14 +6,6 @@ LL | struct Foo { ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Foo>` here - | the method is available for `Rc<Foo>` here | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/crate-loading/missing-std.rs b/src/test/ui/crate-loading/missing-std.rs new file mode 100644 index 0000000000..442a7c01e5 --- /dev/null +++ b/src/test/ui/crate-loading/missing-std.rs @@ -0,0 +1,11 @@ +// compile-flags: --target x86_64-unknown-uefi +// rustc-env:CARGO=/usr/bin/cargo +// rustc-env:RUSTUP_HOME=/home/bors/.rustup +#![no_core] +extern crate core; +//~^ ERROR can't find crate for `core` +//~| NOTE can't find crate +//~| NOTE target may not be installed +//~| HELP consider building the standard library from source with `cargo build -Zbuild-std` +//~| HELP consider downloading the target with `rustup target add x86_64-unknown-uefi` +fn main() {} diff --git a/src/test/ui/crate-loading/missing-std.stderr b/src/test/ui/crate-loading/missing-std.stderr new file mode 100644 index 0000000000..25808efdfa --- /dev/null +++ b/src/test/ui/crate-loading/missing-std.stderr @@ -0,0 +1,13 @@ +error[E0463]: can't find crate for `core` + --> $DIR/missing-std.rs:5:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ can't find crate + | + = note: the `x86_64-unknown-uefi` target may not be installed + = help: consider downloading the target with `rustup target add x86_64-unknown-uefi` + = help: consider building the standard library from source with `cargo build -Zbuild-std` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs index 0d11d933af..a0ee3ad31e 100644 --- a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs +++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs @@ -1,7 +1,7 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-assoc-type-codegen #![feature(rustc_attrs)] #![allow(warnings)] diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.rs b/src/test/ui/dep-graph/dep-graph-caller-callee.rs index b12c635d2e..c95ea53650 100644 --- a/src/test/ui/dep-graph/dep-graph-caller-callee.rs +++ b/src/test/ui/dep-graph/dep-graph-caller-callee.rs @@ -1,7 +1,7 @@ // Test that immediate callers have to change when callee changes, but // not callers' callers. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-caller-callee #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.rs b/src/test/ui/dep-graph/dep-graph-check-attr.rs new file mode 100644 index 0000000000..1026efc1b1 --- /dev/null +++ b/src/test/ui/dep-graph/dep-graph-check-attr.rs @@ -0,0 +1,20 @@ +// Test that using rustc_clean/dirty/if_this_changed/then_this_would_need +// are forbidden when `-Z query-dep-graph` is not enabled. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +#[rustc_dirty(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +fn main() {} + +#[rustc_if_this_changed(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +struct Foo<T> { + f: T, +} + +#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +type TypeAlias<T> = Foo<T>; + +#[rustc_then_this_would_need(variances_of)] //~ ERROR attribute requires -Z query-dep-graph +trait Use<T> {} diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.stderr b/src/test/ui/dep-graph/dep-graph-check-attr.stderr new file mode 100644 index 0000000000..945a4237c1 --- /dev/null +++ b/src/test/ui/dep-graph/dep-graph-check-attr.stderr @@ -0,0 +1,26 @@ +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:8:1 + | +LL | #[rustc_dirty(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:11:1 + | +LL | #[rustc_if_this_changed(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:16:1 + | +LL | #[rustc_clean(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:19:1 + | +LL | #[rustc_then_this_would_need(variances_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.rs b/src/test/ui/dep-graph/dep-graph-struct-signature.rs index 7ef6fac48c..50a670b877 100644 --- a/src/test/ui/dep-graph/dep-graph-struct-signature.rs +++ b/src/test/ui/dep-graph/dep-graph-struct-signature.rs @@ -1,7 +1,7 @@ // Test cases where a changing struct appears in the signature of fns // and methods. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-struct-signature #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs index 1b3bf5a393..c0a6617316 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs @@ -1,7 +1,7 @@ // Test that adding an impl to a trait `Foo` DOES affect functions // that only use `Bar` if they have methods in common. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits-same-method #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs index ebfe8ccc3d..56e9762ddb 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs @@ -1,7 +1,7 @@ // Test that adding an impl to a trait `Foo` does not affect functions // that only use `Bar`, so long as they do not have methods in common. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits #![feature(rustc_attrs)] #![allow(warnings)] diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.rs b/src/test/ui/dep-graph/dep-graph-trait-impl.rs index 9dd201e2a1..3bbe3e745c 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl.rs +++ b/src/test/ui/dep-graph/dep-graph-trait-impl.rs @@ -1,7 +1,7 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl #![feature(rustc_attrs)] #![allow(warnings)] diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.rs b/src/test/ui/dep-graph/dep-graph-type-alias.rs index c9151ce79c..5c5e24693a 100644 --- a/src/test/ui/dep-graph/dep-graph-type-alias.rs +++ b/src/test/ui/dep-graph/dep-graph-type-alias.rs @@ -1,6 +1,6 @@ // Test that changing what a `type` points to does not go unnoticed. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-type-alias #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.rs b/src/test/ui/dep-graph/dep-graph-variance-alias.rs index 927ea55977..6cc1f44104 100644 --- a/src/test/ui/dep-graph/dep-graph-variance-alias.rs +++ b/src/test/ui/dep-graph/dep-graph-variance-alias.rs @@ -1,7 +1,7 @@ // Test that changing what a `type` points to does not go unnoticed // by the variance analysis. -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-variance-alias #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs index 560e296888..b6c791c15f 100644 --- a/src/test/ui/deprecation/deprecation-lint.rs +++ b/src/test/ui/deprecation/deprecation-lint.rs @@ -1,5 +1,4 @@ // aux-build:deprecation-lint.rs -// ignore-tidy-linelength #![deny(deprecated)] #![allow(warnings)] diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr index 12c76f0f4a..959cf93bac 100644 --- a/src/test/ui/deprecation/deprecation-lint.stderr +++ b/src/test/ui/deprecation/deprecation-lint.stderr @@ -1,737 +1,737 @@ error: use of deprecated function `deprecation_lint::deprecated`: text - --> $DIR/deprecation-lint.rs:17:9 + --> $DIR/deprecation-lint.rs:16:9 | LL | deprecated(); | ^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deprecation-lint.rs:4:9 + --> $DIR/deprecation-lint.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:22:9 + --> $DIR/deprecation-lint.rs:21:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:24:9 + --> $DIR/deprecation-lint.rs:23:9 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_text`: text - --> $DIR/deprecation-lint.rs:26:9 + --> $DIR/deprecation-lint.rs:25:9 | LL | deprecated_text(); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:31:9 + --> $DIR/deprecation-lint.rs:30:9 | LL | ... Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:33:9 + --> $DIR/deprecation-lint.rs:32:9 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:35:17 + --> $DIR/deprecation-lint.rs:34:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:39:17 + --> $DIR/deprecation-lint.rs:38:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:41:17 + --> $DIR/deprecation-lint.rs:40:17 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:43:17 + --> $DIR/deprecation-lint.rs:42:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:45:17 + --> $DIR/deprecation-lint.rs:44:17 | LL | let _ = nested::DeprecatedStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:49:17 + --> $DIR/deprecation-lint.rs:48:17 | LL | let _ = nested::DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:51:17 + --> $DIR/deprecation-lint.rs:50:17 | LL | ... let _ = nested::Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:53:17 + --> $DIR/deprecation-lint.rs:52:17 | LL | ... let _ = nested::DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_text`: text - --> $DIR/deprecation-lint.rs:60:25 + --> $DIR/deprecation-lint.rs:59:25 | LL | macro_test_arg!(deprecated_text()); | ^^^^^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_text`: text - --> $DIR/deprecation-lint.rs:61:41 + --> $DIR/deprecation-lint.rs:60:41 | 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:66:9 + --> $DIR/deprecation-lint.rs:65:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:68:9 + --> $DIR/deprecation-lint.rs:67:9 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:70:9 + --> $DIR/deprecation-lint.rs:69:9 | LL | ... Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:72:9 + --> $DIR/deprecation-lint.rs:71:9 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text - --> $DIR/deprecation-lint.rs:82:10 + --> $DIR/deprecation-lint.rs:81:10 | LL | impl DeprecatedTrait for S {} | ^^^^^^^^^^^^^^^ error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text - --> $DIR/deprecation-lint.rs:83:24 + --> $DIR/deprecation-lint.rs:82:24 | LL | trait LocalTrait : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::Deprecated`: text - --> $DIR/deprecation-lint.rs:114:17 + --> $DIR/deprecation-lint.rs:113:17 | LL | let x = Deprecated { | ^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::Deprecated`: text - --> $DIR/deprecation-lint.rs:123:13 + --> $DIR/deprecation-lint.rs:122:13 | LL | let Deprecated { | ^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::Deprecated`: text - --> $DIR/deprecation-lint.rs:129:13 + --> $DIR/deprecation-lint.rs:128:13 | LL | let Deprecated | ^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::Deprecated2`: text - --> $DIR/deprecation-lint.rs:133:17 + --> $DIR/deprecation-lint.rs:132:17 | LL | let x = Deprecated2(1, 2, 3); | ^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::Deprecated2`: text - --> $DIR/deprecation-lint.rs:143:13 + --> $DIR/deprecation-lint.rs:142:13 | LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::Deprecated2`: text - --> $DIR/deprecation-lint.rs:152:13 + --> $DIR/deprecation-lint.rs:151:13 | LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text - --> $DIR/deprecation-lint.rs:163:9 + --> $DIR/deprecation-lint.rs:162:9 | LL | deprecated_mod::deprecated(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated`: text - --> $DIR/deprecation-lint.rs:246:9 + --> $DIR/deprecation-lint.rs:245:9 | LL | deprecated(); | ^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:251:9 + --> $DIR/deprecation-lint.rs:250:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:253:9 + --> $DIR/deprecation-lint.rs:252:9 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_text`: text - --> $DIR/deprecation-lint.rs:255:9 + --> $DIR/deprecation-lint.rs:254:9 | LL | deprecated_text(); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:260:9 + --> $DIR/deprecation-lint.rs:259:9 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:262:9 + --> $DIR/deprecation-lint.rs:261:9 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_future`: text - --> $DIR/deprecation-lint.rs:265:9 + --> $DIR/deprecation-lint.rs:264:9 | LL | deprecated_future(); | ^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_future_text`: text - --> $DIR/deprecation-lint.rs:266:9 + --> $DIR/deprecation-lint.rs:265:9 | LL | deprecated_future_text(); | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `this_crate::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:268:17 + --> $DIR/deprecation-lint.rs:267:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ error: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:273:17 + --> $DIR/deprecation-lint.rs:272:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:275:17 + --> $DIR/deprecation-lint.rs:274:17 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:277:17 + --> $DIR/deprecation-lint.rs:276:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:279:17 + --> $DIR/deprecation-lint.rs:278:17 | LL | let _ = nested::DeprecatedStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:284:17 + --> $DIR/deprecation-lint.rs:283:17 | LL | let _ = nested::DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:286:17 + --> $DIR/deprecation-lint.rs:285:17 | LL | ... let _ = nested::Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:288:17 + --> $DIR/deprecation-lint.rs:287:17 | LL | ... let _ = nested::DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:293:9 + --> $DIR/deprecation-lint.rs:292:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:295:9 + --> $DIR/deprecation-lint.rs:294:9 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:297:9 + --> $DIR/deprecation-lint.rs:296:9 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:299:9 + --> $DIR/deprecation-lint.rs:298:9 | 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:317:13 + --> $DIR/deprecation-lint.rs:316:13 | LL | bar(); | ^^^ error: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/deprecation-lint.rs:336:10 + --> $DIR/deprecation-lint.rs:335:10 | LL | impl DeprecatedTrait for S { } | ^^^^^^^^^^^^^^^ error: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/deprecation-lint.rs:338:24 + --> $DIR/deprecation-lint.rs:337:24 | LL | trait LocalTrait : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ error: use of deprecated struct `this_crate2::Deprecated`: text - --> $DIR/deprecation-lint.rs:390:17 + --> $DIR/deprecation-lint.rs:389:17 | LL | let x = Deprecated { | ^^^^^^^^^^ error: use of deprecated struct `this_crate2::Deprecated`: text - --> $DIR/deprecation-lint.rs:399:13 + --> $DIR/deprecation-lint.rs:398:13 | LL | let Deprecated { | ^^^^^^^^^^ error: use of deprecated struct `this_crate2::Deprecated`: text - --> $DIR/deprecation-lint.rs:405:13 + --> $DIR/deprecation-lint.rs:404:13 | LL | let Deprecated | ^^^^^^^^^^ error: use of deprecated tuple struct `this_crate2::Deprecated2`: text - --> $DIR/deprecation-lint.rs:410:17 + --> $DIR/deprecation-lint.rs:409:17 | LL | let x = Deprecated2(1, 2, 3); | ^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate2::Deprecated2`: text - --> $DIR/deprecation-lint.rs:420:13 + --> $DIR/deprecation-lint.rs:419:13 | LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate2::Deprecated2`: text - --> $DIR/deprecation-lint.rs:429:13 + --> $DIR/deprecation-lint.rs:428:13 | LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text - --> $DIR/deprecation-lint.rs:18:13 + --> $DIR/deprecation-lint.rs:17:13 | LL | foo.method_deprecated(); | ^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text - --> $DIR/deprecation-lint.rs:19:9 + --> $DIR/deprecation-lint.rs:18:9 | LL | Foo::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text - --> $DIR/deprecation-lint.rs:20:9 + --> $DIR/deprecation-lint.rs:19:9 | LL | <Foo>::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:21:13 + --> $DIR/deprecation-lint.rs:20:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:23:9 + --> $DIR/deprecation-lint.rs:22:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text - --> $DIR/deprecation-lint.rs:27:13 + --> $DIR/deprecation-lint.rs:26:13 | LL | ... foo.method_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text - --> $DIR/deprecation-lint.rs:28:9 + --> $DIR/deprecation-lint.rs:27:9 | LL | ... Foo::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text - --> $DIR/deprecation-lint.rs:29:9 + --> $DIR/deprecation-lint.rs:28:9 | LL | ... <Foo>::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:30:13 + --> $DIR/deprecation-lint.rs:29:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:32:9 + --> $DIR/deprecation-lint.rs:31:9 | LL | ... <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated field `deprecation_lint::DeprecatedStruct::i`: text - --> $DIR/deprecation-lint.rs:36:13 + --> $DIR/deprecation-lint.rs:35:13 | LL | i: 0 | ^^^^ error: use of deprecated field `deprecation_lint::nested::DeprecatedStruct::i`: text - --> $DIR/deprecation-lint.rs:46:13 + --> $DIR/deprecation-lint.rs:45:13 | LL | i: 0 | ^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:65:13 + --> $DIR/deprecation-lint.rs:64:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:67:9 + --> $DIR/deprecation-lint.rs:66:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:69:13 + --> $DIR/deprecation-lint.rs:68:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:71:9 + --> $DIR/deprecation-lint.rs:70:9 | LL | ... <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:76:13 + --> $DIR/deprecation-lint.rs:75:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:77:13 + --> $DIR/deprecation-lint.rs:76:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated field `deprecation_lint::Stable::override2`: text - --> $DIR/deprecation-lint.rs:87:13 + --> $DIR/deprecation-lint.rs:86:13 | LL | override2: 3, | ^^^^^^^^^^^^ error: use of deprecated field `deprecation_lint::Stable::override2`: text - --> $DIR/deprecation-lint.rs:91:17 + --> $DIR/deprecation-lint.rs:90:17 | LL | let _ = x.override2; | ^^^^^^^^^^^ error: use of deprecated field `deprecation_lint::Stable::override2`: text - --> $DIR/deprecation-lint.rs:95:13 + --> $DIR/deprecation-lint.rs:94:13 | LL | override2: _ | ^^^^^^^^^^^^ error: use of deprecated field `deprecation_lint::Stable2::2`: text - --> $DIR/deprecation-lint.rs:103:17 + --> $DIR/deprecation-lint.rs:102:17 | LL | let _ = x.2; | ^^^ error: use of deprecated field `deprecation_lint::Stable2::2`: text - --> $DIR/deprecation-lint.rs:108:20 + --> $DIR/deprecation-lint.rs:107:20 | LL | _) | ^ error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:116:13 + --> $DIR/deprecation-lint.rs:115:13 | LL | inherit: 1, | ^^^^^^^^^^ error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:120:17 + --> $DIR/deprecation-lint.rs:119:17 | LL | let _ = x.inherit; | ^^^^^^^^^ error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:125:13 + --> $DIR/deprecation-lint.rs:124:13 | LL | inherit: _, | ^^^^^^^^^^ error: use of deprecated field `deprecation_lint::Deprecated2::0`: text - --> $DIR/deprecation-lint.rs:136:17 + --> $DIR/deprecation-lint.rs:135:17 | LL | let _ = x.0; | ^^^ error: use of deprecated field `deprecation_lint::Deprecated2::1`: text - --> $DIR/deprecation-lint.rs:138:17 + --> $DIR/deprecation-lint.rs:137:17 | LL | let _ = x.1; | ^^^ error: use of deprecated field `deprecation_lint::Deprecated2::2`: text - --> $DIR/deprecation-lint.rs:140:17 + --> $DIR/deprecation-lint.rs:139:17 | LL | let _ = x.2; | ^^^ error: use of deprecated field `deprecation_lint::Deprecated2::0`: text - --> $DIR/deprecation-lint.rs:145:14 + --> $DIR/deprecation-lint.rs:144:14 | LL | (_, | ^ error: use of deprecated field `deprecation_lint::Deprecated2::1`: text - --> $DIR/deprecation-lint.rs:147:14 + --> $DIR/deprecation-lint.rs:146:14 | LL | _, | ^ error: use of deprecated field `deprecation_lint::Deprecated2::2`: text - --> $DIR/deprecation-lint.rs:149:14 + --> $DIR/deprecation-lint.rs:148:14 | LL | _) | ^ error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text - --> $DIR/deprecation-lint.rs:247:13 + --> $DIR/deprecation-lint.rs:246:13 | LL | foo.method_deprecated(); | ^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text - --> $DIR/deprecation-lint.rs:248:9 + --> $DIR/deprecation-lint.rs:247:9 | LL | Foo::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text - --> $DIR/deprecation-lint.rs:249:9 + --> $DIR/deprecation-lint.rs:248:9 | LL | <Foo>::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:250:13 + --> $DIR/deprecation-lint.rs:249:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:252:9 + --> $DIR/deprecation-lint.rs:251:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/deprecation-lint.rs:256:13 + --> $DIR/deprecation-lint.rs:255:13 | LL | ... foo.method_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/deprecation-lint.rs:257:9 + --> $DIR/deprecation-lint.rs:256:9 | LL | ... Foo::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/deprecation-lint.rs:258:9 + --> $DIR/deprecation-lint.rs:257:9 | LL | ... <Foo>::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:259:13 + --> $DIR/deprecation-lint.rs:258:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:261:9 + --> $DIR/deprecation-lint.rs:260:9 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated field `this_crate::DeprecatedStruct::i`: text - --> $DIR/deprecation-lint.rs:270:13 + --> $DIR/deprecation-lint.rs:269:13 | LL | i: 0 | ^^^^ error: use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text - --> $DIR/deprecation-lint.rs:281:13 + --> $DIR/deprecation-lint.rs:280:13 | LL | i: 0 | ^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:292:13 + --> $DIR/deprecation-lint.rs:291:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:294:9 + --> $DIR/deprecation-lint.rs:293:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:296:13 + --> $DIR/deprecation-lint.rs:295:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:298:9 + --> $DIR/deprecation-lint.rs:297:9 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:303:13 + --> $DIR/deprecation-lint.rs:302:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:304:13 + --> $DIR/deprecation-lint.rs:303:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable::override2`: text - --> $DIR/deprecation-lint.rs:363:13 + --> $DIR/deprecation-lint.rs:362:13 | LL | override2: 3, | ^^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable::override2`: text - --> $DIR/deprecation-lint.rs:367:17 + --> $DIR/deprecation-lint.rs:366:17 | LL | let _ = x.override2; | ^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable::override2`: text - --> $DIR/deprecation-lint.rs:371:13 + --> $DIR/deprecation-lint.rs:370:13 | LL | override2: _ | ^^^^^^^^^^^^ error: use of deprecated field `this_crate2::Stable2::2`: text - --> $DIR/deprecation-lint.rs:379:17 + --> $DIR/deprecation-lint.rs:378:17 | LL | let _ = x.2; | ^^^ error: use of deprecated field `this_crate2::Stable2::2`: text - --> $DIR/deprecation-lint.rs:384:20 + --> $DIR/deprecation-lint.rs:383:20 | LL | _) | ^ error: use of deprecated field `this_crate2::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:392:13 + --> $DIR/deprecation-lint.rs:391:13 | LL | inherit: 1, | ^^^^^^^^^^ error: use of deprecated field `this_crate2::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:396:17 + --> $DIR/deprecation-lint.rs:395:17 | LL | let _ = x.inherit; | ^^^^^^^^^ error: use of deprecated field `this_crate2::Deprecated::inherit`: text - --> $DIR/deprecation-lint.rs:401:13 + --> $DIR/deprecation-lint.rs:400:13 | LL | inherit: _, | ^^^^^^^^^^ error: use of deprecated field `this_crate2::Deprecated2::0`: text - --> $DIR/deprecation-lint.rs:413:17 + --> $DIR/deprecation-lint.rs:412:17 | LL | let _ = x.0; | ^^^ error: use of deprecated field `this_crate2::Deprecated2::1`: text - --> $DIR/deprecation-lint.rs:415:17 + --> $DIR/deprecation-lint.rs:414:17 | LL | let _ = x.1; | ^^^ error: use of deprecated field `this_crate2::Deprecated2::2`: text - --> $DIR/deprecation-lint.rs:417:17 + --> $DIR/deprecation-lint.rs:416:17 | LL | let _ = x.2; | ^^^ error: use of deprecated field `this_crate2::Deprecated2::0`: text - --> $DIR/deprecation-lint.rs:422:14 + --> $DIR/deprecation-lint.rs:421:14 | LL | (_, | ^ error: use of deprecated field `this_crate2::Deprecated2::1`: text - --> $DIR/deprecation-lint.rs:424:14 + --> $DIR/deprecation-lint.rs:423:14 | LL | _, | ^ error: use of deprecated field `this_crate2::Deprecated2::2`: text - --> $DIR/deprecation-lint.rs:426:14 + --> $DIR/deprecation-lint.rs:425:14 | LL | _) | ^ diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.rs b/src/test/ui/deprecation/rustc_deprecation-in-future.rs index 11f7960b75..3715f8eb22 100644 --- a/src/test/ui/deprecation/rustc_deprecation-in-future.rs +++ b/src/test/ui/deprecation/rustc_deprecation-in-future.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![deny(deprecated_in_future)] #![feature(staged_api)] diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.stderr b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr index b5a7dd3c28..1c3339a8a9 100644 --- a/src/test/ui/deprecation/rustc_deprecation-in-future.stderr +++ b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr @@ -1,17 +1,17 @@ error: use of unit struct `S1` that will be deprecated in future version 99.99.99: effectively never - --> $DIR/rustc_deprecation-in-future.rs:18:13 + --> $DIR/rustc_deprecation-in-future.rs:16:13 | LL | let _ = S1; | ^^ | note: the lint level is defined here - --> $DIR/rustc_deprecation-in-future.rs:3:9 + --> $DIR/rustc_deprecation-in-future.rs:1:9 | LL | #![deny(deprecated_in_future)] | ^^^^^^^^^^^^^^^^^^^^ error: use of unit struct `S2` that will be deprecated in a future Rust version: literally never - --> $DIR/rustc_deprecation-in-future.rs:19:13 + --> $DIR/rustc_deprecation-in-future.rs:17:13 | LL | let _ = S2; | ^^ diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs index 580410aecf..4fd695585b 100644 --- a/src/test/ui/deref-suggestion.rs +++ b/src/test/ui/deref-suggestion.rs @@ -45,4 +45,30 @@ fn main() { //~^ ERROR mismatched types let r = R { i: i }; //~^ ERROR mismatched types + + + let a = &1; + let b = &2; + let val: i32 = if true { + a + 1 + } else { + b + //~^ ERROR mismatched types + }; + let val: i32 = if true { + let _ = 2; + a + 1 + } else { + let _ = 2; + b + //~^ ERROR mismatched types + }; + let val = if true { + *a + } else if true { + //~^ ERROR incompatible types + b + } else { + &0 + }; } diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index f59f05db9c..632a279d79 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -89,6 +89,43 @@ LL | let r = R { i: i }; | expected `u32`, found `&{integer}` | help: consider dereferencing the borrow: `*i` -error: aborting due to 10 previous errors +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:55:9 + | +LL | b + | ^ + | | + | expected `i32`, found `&{integer}` + | help: consider dereferencing the borrow: `*b` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:63:9 + | +LL | b + | ^ + | | + | expected `i32`, found `&{integer}` + | help: consider dereferencing the borrow: `*b` + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/deref-suggestion.rs:68:12 + | +LL | let val = if true { + | _______________- +LL | | *a + | | -- expected because of this +LL | | } else if true { + | |____________^ +LL | || +LL | || b +LL | || } else { +LL | || &0 +LL | || }; + | || ^ + | ||_____| + | |______`if` and `else` have incompatible types + | expected `i32`, found `&{integer}` + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index ffee7004f8..fd993d0f9d 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -12,14 +12,6 @@ LL | struct NotClone; ... LL | Bar::<NotClone> { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Bar<NotClone>>` here - | the method is available for `Rc<Bar<NotClone>>` here | = note: the following trait bounds were not satisfied: `NotClone: Clone` diff --git a/src/test/ui/derives/derive-macro-const-default.rs b/src/test/ui/derives/derive-macro-const-default.rs new file mode 100644 index 0000000000..a844f2d202 --- /dev/null +++ b/src/test/ui/derives/derive-macro-const-default.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(incomplete_features)] +#![feature(const_generics_defaults)] + +#[derive(Clone, PartialEq, Debug)] +struct Example<T, const N: usize = 1usize>([T; N]); + +fn main() { + let a = Example([(); 16]); + let b = a.clone(); + if a != b { + let _c = format!("{:?}", a); + } +} diff --git a/src/test/ui/derives/deriving-with-repr-packed.rs b/src/test/ui/derives/deriving-with-repr-packed.rs index d354cef66b..b78eeaa905 100644 --- a/src/test/ui/derives/deriving-with-repr-packed.rs +++ b/src/test/ui/derives/deriving-with-repr-packed.rs @@ -1,4 +1,4 @@ -#![deny(safe_packed_borrows)] +#![deny(unaligned_references)] // check that derive on a packed struct with non-Copy fields // correctly. This can't be made to work perfectly because diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr index d739257c8d..3caa563a08 100644 --- a/src/test/ui/derives/deriving-with-repr-packed.stderr +++ b/src/test/ui/derives/deriving-with-repr-packed.stderr @@ -7,10 +7,10 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)] note: the lint level is defined here --> $DIR/deriving-with-repr-packed.rs:1:9 | -LL | #![deny(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ +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 #46043 <https://github.com/rust-lang/rust/issues/46043> + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133) @@ -20,7 +20,7 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)] | ^^^^^^^^^ | = 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: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) @@ -30,7 +30,7 @@ LL | #[derive(PartialEq, Eq)] | ^^^^^^^^^ | = 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: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) @@ -40,7 +40,7 @@ LL | #[derive(PartialEq)] | ^^^^^^^^^ | = 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: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/bad/bad-expr-lhs.rs b/src/test/ui/destructuring-assignment/bad-expr-lhs.rs similarity index 100% rename from src/test/ui/bad/bad-expr-lhs.rs rename to src/test/ui/destructuring-assignment/bad-expr-lhs.rs diff --git a/src/test/ui/bad/bad-expr-lhs.stderr b/src/test/ui/destructuring-assignment/bad-expr-lhs.stderr similarity index 100% rename from src/test/ui/bad/bad-expr-lhs.stderr rename to src/test/ui/destructuring-assignment/bad-expr-lhs.stderr diff --git a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr index 26c24d7432..d05d6d120b 100644 --- a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr +++ b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr @@ -47,19 +47,46 @@ error: unexpected `,` in pattern --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:67:10 | LL | for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) { - | -^----------- help: try adding parentheses to match on a tuple: `(x, _barr_body)` + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL | for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) { + | ^^^^^^^^^^^^^^^ +help: ...or a vertical bar to match on multiple alternatives + | +LL | for x | _barr_body in women.iter().map(|woman| woman.allosomes.clone()) { + | ^^^^^^^^^^^^^^ error: unexpected `,` in pattern --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:75:10 | LL | for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) { - | -^------------------- help: try adding parentheses to match on a tuple: `(x, y @ Allosome::Y(_))` + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL | for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: ...or a vertical bar to match on multiple alternatives + | +LL | for x | y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^ error: unexpected `,` in pattern --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:84:14 | LL | let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned() - | -----^---- help: try adding parentheses to match on a tuple: `(women, men)` + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL | let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned() + | ^^^^^^^^^^^^ +help: ...or a vertical bar to match on multiple alternatives + | +LL | let women | men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned() + | ^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/did_you_mean/pub-macro-rules.rs b/src/test/ui/did_you_mean/pub-macro-rules.rs new file mode 100644 index 0000000000..c5393703f7 --- /dev/null +++ b/src/test/ui/did_you_mean/pub-macro-rules.rs @@ -0,0 +1,16 @@ +#[macro_use] mod bleh { + pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation + ($n:ident) => ( + fn $n () -> i32 { + 1 + } + ) + } + +} + +foo!(meh); + +fn main() { + println!("{}", meh()); +} diff --git a/src/test/ui/did_you_mean/pub-macro-rules.stderr b/src/test/ui/did_you_mean/pub-macro-rules.stderr new file mode 100644 index 0000000000..0bde5783b8 --- /dev/null +++ b/src/test/ui/did_you_mean/pub-macro-rules.stderr @@ -0,0 +1,8 @@ +error: can't qualify macro_rules invocation with `pub` + --> $DIR/pub-macro-rules.rs:2:5 + | +LL | pub macro_rules! foo { + | ^^^ help: try exporting the macro: `#[macro_export]` + +error: aborting due to previous error + diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index c5b42416ea..2d52172a6f 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -8,16 +8,56 @@ LL | is_send::<A>(); | ^^^^^^^^^^^^ | = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit`) - = note: required because it appears within the type `J` - = note: required because it appears within the type `I` - = note: required because it appears within the type `H` - = note: required because it appears within the type `G` - = note: required because it appears within the type `F` - = note: required because it appears within the type `E` - = note: required because it appears within the type `D` - = note: required because it appears within the type `C` - = note: required because it appears within the type `B` - = note: required because it appears within the type `A` +note: required because it appears within the type `J` + --> $DIR/recursion_limit.rs:24:9 + | +LL | link! { J, K } + | ^ +note: required because it appears within the type `I` + --> $DIR/recursion_limit.rs:23:9 + | +LL | link! { I, J } + | ^ +note: required because it appears within the type `H` + --> $DIR/recursion_limit.rs:22:9 + | +LL | link! { H, I } + | ^ +note: required because it appears within the type `G` + --> $DIR/recursion_limit.rs:21:9 + | +LL | link! { G, H } + | ^ +note: required because it appears within the type `F` + --> $DIR/recursion_limit.rs:20:9 + | +LL | link! { F, G } + | ^ +note: required because it appears within the type `E` + --> $DIR/recursion_limit.rs:19:9 + | +LL | link! { E, F } + | ^ +note: required because it appears within the type `D` + --> $DIR/recursion_limit.rs:18:9 + | +LL | link! { D, E } + | ^ +note: required because it appears within the type `C` + --> $DIR/recursion_limit.rs:17:9 + | +LL | link! { C, D } + | ^ +note: required because it appears within the type `B` + --> $DIR/recursion_limit.rs:16:9 + | +LL | link! { B, C } + | ^ +note: required because it appears within the type `A` + --> $DIR/recursion_limit.rs:15:9 + | +LL | link! { A, B } + | ^ error: aborting due to previous error diff --git a/src/test/ui/dst/dst-bad-deep.stderr b/src/test/ui/dst/dst-bad-deep.stderr index ea6b239047..71e57b3e06 100644 --- a/src/test/ui/dst/dst-bad-deep.stderr +++ b/src/test/ui/dst/dst-bad-deep.stderr @@ -5,8 +5,16 @@ LL | let h: &Fat<Fat<[isize]>> = &Fat { ptr: *g }; | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Fat<Fat<[isize]>>`, the trait `Sized` is not implemented for `[isize]` - = note: required because it appears within the type `Fat<[isize]>` - = note: required because it appears within the type `Fat<Fat<[isize]>>` +note: required because it appears within the type `Fat<[isize]>` + --> $DIR/dst-bad-deep.rs:6:8 + | +LL | struct Fat<T: ?Sized> { + | ^^^ +note: required because it appears within the type `Fat<Fat<[isize]>>` + --> $DIR/dst-bad-deep.rs:6:8 + | +LL | struct Fat<T: ?Sized> { + | ^^^ = note: structs must have a statically known size to be initialized error: aborting due to previous error diff --git a/src/test/ui/dst/dst-object-from-unsized-type.stderr b/src/test/ui/dst/dst-object-from-unsized-type.stderr index 49940112a9..2d12265df9 100644 --- a/src/test/ui/dst/dst-object-from-unsized-type.stderr +++ b/src/test/ui/dst/dst-object-from-unsized-type.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/dst-object-from-unsized-type.rs:8:23 | LL | fn test1<T: ?Sized + Foo>(t: &T) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | let u: &dyn Foo = t; | ^ doesn't have a size known at compile-time | @@ -12,7 +12,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/dst-object-from-unsized-type.rs:13:23 | LL | fn test2<T: ?Sized + Foo>(t: &T) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | let v: &dyn Foo = t as &dyn Foo; | ^ doesn't have a size known at compile-time | diff --git a/src/test/ui/entry-point/auxiliary/main_functions.rs b/src/test/ui/entry-point/auxiliary/main_functions.rs new file mode 100644 index 0000000000..cc7992a42c --- /dev/null +++ b/src/test/ui/entry-point/auxiliary/main_functions.rs @@ -0,0 +1 @@ +pub fn boilerplate() {} diff --git a/src/test/ui/entry-point/imported_main_conflict.rs b/src/test/ui/entry-point/imported_main_conflict.rs new file mode 100644 index 0000000000..2839688f34 --- /dev/null +++ b/src/test/ui/entry-point/imported_main_conflict.rs @@ -0,0 +1,7 @@ +#![feature(imported_main)] +//~^ ERROR `main` is ambiguous (glob import vs glob import in the same module) +mod m1 { pub(crate) fn main() {} } +mod m2 { pub(crate) fn main() {} } + +use m1::*; +use m2::*; diff --git a/src/test/ui/entry-point/imported_main_conflict.stderr b/src/test/ui/entry-point/imported_main_conflict.stderr new file mode 100644 index 0000000000..36cb98d94e --- /dev/null +++ b/src/test/ui/entry-point/imported_main_conflict.stderr @@ -0,0 +1,18 @@ +error[E0659]: `main` is ambiguous (glob import vs glob import in the same module) + | +note: `main` could refer to the function imported here + --> $DIR/imported_main_conflict.rs:6:5 + | +LL | use m1::*; + | ^^^^^ + = help: consider adding an explicit import of `main` to disambiguate +note: `main` could also refer to the function imported here + --> $DIR/imported_main_conflict.rs:7:5 + | +LL | use m2::*; + | ^^^^^ + = help: consider adding an explicit import of `main` to disambiguate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs new file mode 100644 index 0000000000..559f10de10 --- /dev/null +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs @@ -0,0 +1,12 @@ +#![feature(imported_main)] +#![feature(min_type_alias_impl_trait, impl_trait_in_bindings)] +#![allow(incomplete_features)] +//~^^^ ERROR `main` function not found in crate +pub mod foo { + type MainFn = impl Fn(); + + fn bar() {} + pub const BAR: MainFn = bar; +} + +use foo::BAR as main; diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr new file mode 100644 index 0000000000..9b879fc09f --- /dev/null +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -0,0 +1,17 @@ +error[E0601]: `main` function not found in crate `imported_main_const_fn_item_type_forbidden` + --> $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 | | #![allow(incomplete_features)] +LL | | +... | +LL | | +LL | | use foo::BAR as main; + | |_____----------------^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs` + | | + | non-function item at `crate::main` is found + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/entry-point/imported_main_const_forbidden.rs b/src/test/ui/entry-point/imported_main_const_forbidden.rs new file mode 100644 index 0000000000..989a6c97a8 --- /dev/null +++ b/src/test/ui/entry-point/imported_main_const_forbidden.rs @@ -0,0 +1,7 @@ +#![feature(imported_main)] +//~^ ERROR `main` function not found in crate +pub mod foo { + pub const BAR: usize = 42; +} + +use foo::BAR as main; diff --git a/src/test/ui/entry-point/imported_main_const_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_forbidden.stderr new file mode 100644 index 0000000000..4640513c2b --- /dev/null +++ b/src/test/ui/entry-point/imported_main_const_forbidden.stderr @@ -0,0 +1,17 @@ +error[E0601]: `main` function not found in crate `imported_main_const_forbidden` + --> $DIR/imported_main_const_forbidden.rs:1:1 + | +LL | / #![feature(imported_main)] +LL | | +LL | | pub mod foo { +LL | | pub const BAR: usize = 42; +LL | | } +LL | | +LL | | use foo::BAR as main; + | |_____----------------^ consider adding a `main` function to `$DIR/imported_main_const_forbidden.rs` + | | + | non-function item at `crate::main` is found + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/entry-point/imported_main_from_extern_crate.rs b/src/test/ui/entry-point/imported_main_from_extern_crate.rs new file mode 100644 index 0000000000..6bbf67fa54 --- /dev/null +++ b/src/test/ui/entry-point/imported_main_from_extern_crate.rs @@ -0,0 +1,9 @@ +// build-fail +// aux-build:main_functions.rs + +#![feature(imported_main)] + +extern crate main_functions; +pub use main_functions::boilerplate as main; //~ ERROR entry symbol `main` from foreign crate + +// FIXME: Should be run-pass diff --git a/src/test/ui/entry-point/imported_main_from_extern_crate.stderr b/src/test/ui/entry-point/imported_main_from_extern_crate.stderr new file mode 100644 index 0000000000..8792e1e414 --- /dev/null +++ b/src/test/ui/entry-point/imported_main_from_extern_crate.stderr @@ -0,0 +1,10 @@ +error: entry symbol `main` from foreign crate is not yet supported. + --> $DIR/imported_main_from_extern_crate.rs:7:9 + | +LL | pub use main_functions::boilerplate as main; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #28937 <https://github.com/rust-lang/rust/issues/28937> for more information + +error: aborting due to previous error + diff --git a/src/test/ui/entry-point/imported_main_from_inner_mod.rs b/src/test/ui/entry-point/imported_main_from_inner_mod.rs new file mode 100644 index 0000000000..45750072a7 --- /dev/null +++ b/src/test/ui/entry-point/imported_main_from_inner_mod.rs @@ -0,0 +1,9 @@ +// run-pass +#![feature(imported_main)] + +pub mod foo { + pub fn bar() { + println!("Hello world!"); + } +} +use foo::bar as main; diff --git a/src/test/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs b/src/test/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs new file mode 100644 index 0000000000..4762fbb7c5 --- /dev/null +++ b/src/test/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs @@ -0,0 +1,11 @@ +// check-pass +#![feature(rustc_attrs)] + +#[rustc_main] +fn actual_main() {} + +mod foo { + pub(crate) fn something() {} +} + +use foo::something as main; diff --git a/src/test/ui/error-codes/E0063.rs b/src/test/ui/error-codes/E0063.rs index 58527cc0c5..48c9c13f01 100644 --- a/src/test/ui/error-codes/E0063.rs +++ b/src/test/ui/error-codes/E0063.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - struct SingleFoo { x: i32 } diff --git a/src/test/ui/error-codes/E0063.stderr b/src/test/ui/error-codes/E0063.stderr index 5dc4927071..235e204025 100644 --- a/src/test/ui/error-codes/E0063.stderr +++ b/src/test/ui/error-codes/E0063.stderr @@ -1,23 +1,23 @@ error[E0063]: missing field `x` in initializer of `SingleFoo` - --> $DIR/E0063.rs:32:13 + --> $DIR/E0063.rs:30:13 | LL | let w = SingleFoo { }; | ^^^^^^^^^ missing `x` error[E0063]: missing fields `y` and `z` in initializer of `PluralFoo` - --> $DIR/E0063.rs:34:13 + --> $DIR/E0063.rs:32:13 | LL | let x = PluralFoo {x: 1}; | ^^^^^^^^^ missing `y` and `z` error[E0063]: missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` - --> $DIR/E0063.rs:36:13 + --> $DIR/E0063.rs:34:13 | LL | let y = TruncatedFoo{x:1}; | ^^^^^^^^^^^^ missing `a`, `b`, `y` and 1 other field error[E0063]: missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo` - --> $DIR/E0063.rs:38:13 + --> $DIR/E0063.rs:36:13 | LL | let z = TruncatedPluralFoo{x:1}; | ^^^^^^^^^^^^^^^^^^ missing `a`, `b`, `c` and 2 other fields diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr index ac70e88762..b961fc8aee 100644 --- a/src/test/ui/error-codes/E0106.stderr +++ b/src/test/ui/error-codes/E0106.stderr @@ -23,17 +23,6 @@ LL | A(u8), LL | B(&'a bool), | -error[E0106]: missing lifetime specifier - --> $DIR/E0106.rs:10:14 - | -LL | type MyStr = &str; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type MyStr<'a> = &'a str; - | ^^^^ ^^^ - error[E0106]: missing lifetime specifier --> $DIR/E0106.rs:17:10 | @@ -61,6 +50,17 @@ LL | LL | buzz: Buzz<'a, 'a>, | +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:10:14 + | +LL | type MyStr = &str; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type MyStr<'a> = &'a str; + | ^^^^ ^^^ + error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/error-codes/E0119.stderr b/src/test/ui/error-codes/E0119.stderr index e7690aa30b..e08a2c7fcb 100644 --- a/src/test/ui/error-codes/E0119.stderr +++ b/src/test/ui/error-codes/E0119.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `Foo`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `Foo` --> $DIR/E0119.rs:13:1 | LL | impl<T> MyTrait for T { diff --git a/src/test/ui/error-codes/E0128.stderr b/src/test/ui/error-codes/E0128.stderr index 253aa166bd..eb66d46936 100644 --- a/src/test/ui/error-codes/E0128.stderr +++ b/src/test/ui/error-codes/E0128.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/E0128.rs:1:14 | LL | struct Foo<T=U, U=()> { - | ^ defaulted type parameters cannot be forward declared + | ^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0137.rs b/src/test/ui/error-codes/E0137.rs deleted file mode 100644 index b8299c71bd..0000000000 --- a/src/test/ui/error-codes/E0137.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(main)] - -#[main] -fn foo() {} - -#[main] -fn f() {} -//~^ ERROR E0137 diff --git a/src/test/ui/error-codes/E0137.stderr b/src/test/ui/error-codes/E0137.stderr deleted file mode 100644 index f4d5e10369..0000000000 --- a/src/test/ui/error-codes/E0137.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0137]: multiple functions with a `#[main]` attribute - --> $DIR/E0137.rs:7:1 - | -LL | fn foo() {} - | ----------- first `#[main]` function -... -LL | fn f() {} - | ^^^^^^^^^ additional `#[main]` function - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0137`. diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 46966f22b6..390c1e3e8e 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -8,7 +8,11 @@ LL | impl<T> Foo for T where Bar<T>: Foo {} | ^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`E0275`) - = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` +note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/E0275.rs:5:9 + | +LL | impl<T> Foo for T where Bar<T>: Foo {} + | ^^^ ^ = note: 127 redundant requirements hidden = note: required because of the requirements on the impl of `Foo` for `Bar<T>` diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr index a0ab1641ca..afd0e032dc 100644 --- a/src/test/ui/error-codes/E0277-2.stderr +++ b/src/test/ui/error-codes/E0277-2.stderr @@ -8,9 +8,21 @@ LL | is_send::<Foo>(); | ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely | = help: within `Foo`, the trait `Send` is not implemented for `*const u8` - = note: required because it appears within the type `Baz` - = note: required because it appears within the type `Bar` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Baz` + --> $DIR/E0277-2.rs:9:8 + | +LL | struct Baz { + | ^^^ +note: required because it appears within the type `Bar` + --> $DIR/E0277-2.rs:5:8 + | +LL | struct Bar { + | ^^^ +note: required because it appears within the type `Foo` + --> $DIR/E0277-2.rs:1:8 + | +LL | struct Foo { + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr index 1f54af4d15..dea0bb259f 100644 --- a/src/test/ui/error-codes/E0277.stderr +++ b/src/test/ui/error-codes/E0277.stderr @@ -9,8 +9,8 @@ LL | fn f(p: Path) { } = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn f(&p: Path) { } - | ^ +LL | fn f(p: &Path) { } + | ^ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/E0277.rs:15:15 diff --git a/src/test/ui/error-codes/e0119/complex-impl.stderr b/src/test/ui/error-codes/e0119/complex-impl.stderr index d617d81292..04babb0644 100644 --- a/src/test/ui/error-codes/e0119/complex-impl.stderr +++ b/src/test/ui/error-codes/e0119/complex-impl.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `complex_impl_support::External` for type `(Q, complex_impl_support::M<'_, '_, '_, std::boxed::Box<_>, _, _>)`: +error[E0119]: conflicting implementations of trait `complex_impl_support::External` for type `(Q, complex_impl_support::M<'_, '_, '_, std::boxed::Box<_>, _, _>)` --> $DIR/complex-impl.rs:9:1 | LL | impl<R> External for (Q, R) {} diff --git a/src/test/ui/error-codes/e0119/conflict-with-std.stderr b/src/test/ui/error-codes/e0119/conflict-with-std.stderr index 68551f4377..3ff96a6a4d 100644 --- a/src/test/ui/error-codes/e0119/conflict-with-std.stderr +++ b/src/test/ui/error-codes/e0119/conflict-with-std.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::convert::AsRef<Q>` for type `std::boxed::Box<Q>`: +error[E0119]: conflicting implementations of trait `std::convert::AsRef<Q>` for type `std::boxed::Box<Q>` --> $DIR/conflict-with-std.rs:5:1 | LL | impl AsRef<Q> for Box<Q> { @@ -8,7 +8,7 @@ LL | impl AsRef<Q> for Box<Q> { - impl<T, A> AsRef<T> for Box<T, A> where A: Allocator, T: ?Sized; -error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S`: +error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S` --> $DIR/conflict-with-std.rs:12:1 | LL | impl From<S> for S { @@ -17,7 +17,7 @@ LL | impl From<S> for S { = note: conflicting implementation in crate `core`: - impl<T> From<T> for T; -error[E0119]: conflicting implementations of trait `std::convert::TryFrom<X>` for type `X`: +error[E0119]: conflicting implementations of trait `std::convert::TryFrom<X>` for type `X` --> $DIR/conflict-with-std.rs:19:1 | LL | impl TryFrom<X> for X { diff --git a/src/test/ui/error-codes/e0119/issue-23563.stderr b/src/test/ui/error-codes/e0119/issue-23563.stderr index 912a80fec7..f149cef587 100644 --- a/src/test/ui/error-codes/e0119/issue-23563.stderr +++ b/src/test/ui/error-codes/e0119/issue-23563.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `a::LolFrom<&[_]>` for type `LocalType<_>`: +error[E0119]: conflicting implementations of trait `a::LolFrom<&[_]>` for type `LocalType<_>` --> $DIR/issue-23563.rs:13:1 | LL | impl<'a, T> LolFrom<&'a [T]> for LocalType<T> { diff --git a/src/test/ui/error-codes/e0119/issue-27403.stderr b/src/test/ui/error-codes/e0119/issue-27403.stderr index ea74c9b21b..c11a504874 100644 --- a/src/test/ui/error-codes/e0119/issue-27403.stderr +++ b/src/test/ui/error-codes/e0119/issue-27403.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::convert::Into<_>` for type `GenX<_>`: +error[E0119]: conflicting implementations of trait `std::convert::Into<_>` for type `GenX<_>` --> $DIR/issue-27403.rs:5:1 | LL | impl<S> Into<S> for GenX<S> { diff --git a/src/test/ui/error-codes/e0119/issue-28981.stderr b/src/test/ui/error-codes/e0119/issue-28981.stderr index e12dd76233..56e8e1eb54 100644 --- a/src/test/ui/error-codes/e0119/issue-28981.stderr +++ b/src/test/ui/error-codes/e0119/issue-28981.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::ops::Deref` for type `&_`: +error[E0119]: conflicting implementations of trait `std::ops::Deref` for type `&_` --> $DIR/issue-28981.rs:5:1 | LL | impl<Foo> Deref for Foo { } diff --git a/src/test/ui/error-codes/e0119/so-37347311.stderr b/src/test/ui/error-codes/e0119/so-37347311.stderr index a9fbd0fee4..f1c2b0d297 100644 --- a/src/test/ui/error-codes/e0119/so-37347311.stderr +++ b/src/test/ui/error-codes/e0119/so-37347311.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>`: +error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>` --> $DIR/so-37347311.rs:11:1 | LL | impl<S: Storage> From<S::Error> for MyError<S> { diff --git a/src/test/ui/export-fully-qualified.rs b/src/test/ui/export-fully-qualified.rs index 40f26c7095..4e73a2c548 100644 --- a/src/test/ui/export-fully-qualified.rs +++ b/src/test/ui/export-fully-qualified.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // In this test baz isn't resolved when called as foo.baz even though // it's called from inside foo. This is somewhat surprising and may // want to change eventually. diff --git a/src/test/ui/export-fully-qualified.stderr b/src/test/ui/export-fully-qualified.stderr index a8af0c7c9b..7ee352e123 100644 --- a/src/test/ui/export-fully-qualified.stderr +++ b/src/test/ui/export-fully-qualified.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` - --> $DIR/export-fully-qualified.rs:8:20 + --> $DIR/export-fully-qualified.rs:6:20 | LL | pub fn bar() { foo::baz(); } | ^^^ use of undeclared crate or module `foo` diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr index 278db45655..72e4be5182 100644 --- a/src/test/ui/extern/extern-types-unsized.stderr +++ b/src/test/ui/extern/extern-types-unsized.stderr @@ -23,7 +23,11 @@ LL | assert_sized::<Foo>(); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Foo`, the trait `Sized` is not implemented for `A` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/extern-types-unsized.rs:9:8 + | +LL | struct Foo { + | ^^^ help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized<T: ?Sized>() {} @@ -39,7 +43,11 @@ LL | assert_sized::<Bar<A>>(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Bar<A>`, the trait `Sized` is not implemented for `A` - = note: required because it appears within the type `Bar<A>` +note: required because it appears within the type `Bar<A>` + --> $DIR/extern-types-unsized.rs:14:8 + | +LL | struct Bar<T: ?Sized> { + | ^^^ help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized<T: ?Sized>() {} @@ -55,8 +63,16 @@ LL | assert_sized::<Bar<Bar<A>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Bar<Bar<A>>`, the trait `Sized` is not implemented for `A` - = note: required because it appears within the type `Bar<A>` - = note: required because it appears within the type `Bar<Bar<A>>` +note: required because it appears within the type `Bar<A>` + --> $DIR/extern-types-unsized.rs:14:8 + | +LL | struct Bar<T: ?Sized> { + | ^^^ +note: required because it appears within the type `Bar<Bar<A>>` + --> $DIR/extern-types-unsized.rs:14:8 + | +LL | struct Bar<T: ?Sized> { + | ^^^ help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized<T: ?Sized>() {} diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index 74c6e501c9..7b731a1d71 100644 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -19,7 +19,9 @@ // revisions: no thin fat //[no]compile-flags: -C lto=no -//[thin]compile-flags: -C lto=thin +// FIXME(#83854) running this revision with 1 CGU triggers llvm assert in register allocator +// when executed in i686-gnu-nopt runner. +//[thin]compile-flags: -C lto=thin -Ccodegen-units=2 //[fat]compile-flags: -C lto=fat #![feature(core_panic)] diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index bc15fcb0e3..32e6d0c90b 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -40,7 +40,9 @@ //[no1]compile-flags: -C opt-level=1 -C lto=no //[no2]compile-flags: -C opt-level=2 -C lto=no //[no3]compile-flags: -C opt-level=3 -C lto=no -//[thin0]compile-flags: -C opt-level=0 -C lto=thin +// FIXME(#83854) running this revision with 1 CGU triggers llvm assert in register allocator +// when executed in dist-i586-gnu-i586-i686-musl runner. +//[thin0]compile-flags: -C opt-level=0 -C lto=thin -Ccodegen-units=2 //[thin1]compile-flags: -C opt-level=1 -C lto=thin //[thin2]compile-flags: -C opt-level=2 -C lto=thin //[thin3]compile-flags: -C opt-level=3 -C lto=thin diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs index 31f09cc61f..49cf2e158e 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.rs +++ b/src/test/ui/feature-gates/feature-gate-abi.rs @@ -1,5 +1,4 @@ // only-x86_64 -// ignore-tidy-linelength // gate-test-intrinsics // gate-test-platform_intrinsics // gate-test-abi_vectorcall @@ -11,9 +10,9 @@ // Functions extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change -//~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental -//~^ ERROR intrinsic must be in + //~^ 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 @@ -22,13 +21,14 @@ 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 { extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental - //~^ ERROR intrinsic must be in + //~^ 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 @@ -37,6 +37,7 @@ trait Tr { 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 @@ -46,6 +47,7 @@ trait Tr { 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; @@ -53,9 +55,9 @@ struct S; // Methods in trait impl impl Tr for S { extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental - //~^ ERROR intrinsic must be in + //~^ 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 @@ -64,14 +66,15 @@ impl Tr for S { 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 impl S { extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental - //~^ ERROR intrinsic must be in + //~^ 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 @@ -80,6 +83,7 @@ impl S { 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 @@ -88,11 +92,12 @@ type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are ex 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 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 @@ -105,5 +110,6 @@ 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() {} diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index 25f0c259d1..078d21ad36 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -1,5 +1,5 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:13:8 + --> $DIR/feature-gate-abi.rs:12: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:15:8 + --> $DIR/feature-gate-abi.rs:14:8 | LL | extern "platform-intrinsic" fn f2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | extern "platform-intrinsic" fn f2() {} = 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:17:8 + --> $DIR/feature-gate-abi.rs:16:8 | LL | extern "vectorcall" fn f3() {} | ^^^^^^^^^^^^ @@ -24,7 +24,7 @@ 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:18:8 + --> $DIR/feature-gate-abi.rs:17:8 | LL | extern "rust-call" fn f4(_: ()) {} | ^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | extern "rust-call" fn f4(_: ()) {} = 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:19:8 + --> $DIR/feature-gate-abi.rs:18:8 | LL | extern "msp430-interrupt" fn f5() {} | ^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | extern "msp430-interrupt" fn f5() {} = 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:20:8 + --> $DIR/feature-gate-abi.rs:19:8 | LL | extern "ptx-kernel" fn f6() {} | ^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | extern "ptx-kernel" fn f6() {} = 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:21:8 + --> $DIR/feature-gate-abi.rs:20:8 | LL | extern "x86-interrupt" fn f7() {} | ^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | extern "x86-interrupt" fn f7() {} = 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:22:8 + --> $DIR/feature-gate-abi.rs:21:8 | LL | extern "thiscall" fn f8() {} | ^^^^^^^^^^ @@ -68,7 +68,7 @@ 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:23:8 + --> $DIR/feature-gate-abi.rs:22:8 | LL | extern "amdgpu-kernel" fn f9() {} | ^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | extern "amdgpu-kernel" fn f9() {} = 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:24:8 + --> $DIR/feature-gate-abi.rs:23:8 | LL | extern "efiapi" fn f10() {} | ^^^^^^^^ @@ -85,6 +85,15 @@ 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 | @@ -172,8 +181,17 @@ 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:41:12 + --> $DIR/feature-gate-abi.rs:42:12 | LL | extern "vectorcall" fn dm3() {} | ^^^^^^^^^^^^ @@ -181,7 +199,7 @@ 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:42:12 + --> $DIR/feature-gate-abi.rs:43:12 | LL | extern "rust-call" fn dm4(_: ()) {} | ^^^^^^^^^^^ @@ -190,7 +208,7 @@ LL | extern "rust-call" fn dm4(_: ()) {} = 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:43:12 + --> $DIR/feature-gate-abi.rs:44:12 | LL | extern "msp430-interrupt" fn dm5() {} | ^^^^^^^^^^^^^^^^^^ @@ -199,7 +217,7 @@ LL | extern "msp430-interrupt" fn dm5() {} = 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:44:12 + --> $DIR/feature-gate-abi.rs:45:12 | LL | extern "ptx-kernel" fn dm6() {} | ^^^^^^^^^^^^ @@ -208,7 +226,7 @@ LL | extern "ptx-kernel" fn dm6() {} = 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:45:12 + --> $DIR/feature-gate-abi.rs:46:12 | LL | extern "x86-interrupt" fn dm7() {} | ^^^^^^^^^^^^^^^ @@ -217,7 +235,7 @@ LL | extern "x86-interrupt" fn dm7() {} = 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:46:12 + --> $DIR/feature-gate-abi.rs:47:12 | LL | extern "thiscall" fn dm8() {} | ^^^^^^^^^^ @@ -225,7 +243,7 @@ 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:47:12 + --> $DIR/feature-gate-abi.rs:48:12 | LL | extern "amdgpu-kernel" fn dm9() {} | ^^^^^^^^^^^^^^^ @@ -234,7 +252,7 @@ LL | extern "amdgpu-kernel" fn dm9() {} = 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:48:12 + --> $DIR/feature-gate-abi.rs:49:12 | LL | extern "efiapi" fn dm10() {} | ^^^^^^^^ @@ -242,8 +260,17 @@ 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:55:12 + --> $DIR/feature-gate-abi.rs:57:12 | LL | extern "rust-intrinsic" fn m1() {} | ^^^^^^^^^^^^^^^^ @@ -251,7 +278,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:57:12 + --> $DIR/feature-gate-abi.rs:59:12 | LL | extern "platform-intrinsic" fn m2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -260,7 +287,7 @@ LL | extern "platform-intrinsic" fn m2() {} = 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:59:12 + --> $DIR/feature-gate-abi.rs:61:12 | LL | extern "vectorcall" fn m3() {} | ^^^^^^^^^^^^ @@ -268,7 +295,7 @@ 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:60:12 + --> $DIR/feature-gate-abi.rs:62:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -277,7 +304,7 @@ LL | extern "rust-call" fn m4(_: ()) {} = 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:61:12 + --> $DIR/feature-gate-abi.rs:63:12 | LL | extern "msp430-interrupt" fn m5() {} | ^^^^^^^^^^^^^^^^^^ @@ -286,7 +313,7 @@ LL | extern "msp430-interrupt" fn m5() {} = 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:62:12 + --> $DIR/feature-gate-abi.rs:64:12 | LL | extern "ptx-kernel" fn m6() {} | ^^^^^^^^^^^^ @@ -295,7 +322,7 @@ LL | extern "ptx-kernel" fn m6() {} = 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:63:12 + --> $DIR/feature-gate-abi.rs:65:12 | LL | extern "x86-interrupt" fn m7() {} | ^^^^^^^^^^^^^^^ @@ -304,7 +331,7 @@ LL | extern "x86-interrupt" fn m7() {} = 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:64:12 + --> $DIR/feature-gate-abi.rs:66:12 | LL | extern "thiscall" fn m8() {} | ^^^^^^^^^^ @@ -312,7 +339,7 @@ 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:65:12 + --> $DIR/feature-gate-abi.rs:67:12 | LL | extern "amdgpu-kernel" fn m9() {} | ^^^^^^^^^^^^^^^ @@ -321,7 +348,7 @@ LL | extern "amdgpu-kernel" fn m9() {} = 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:66:12 + --> $DIR/feature-gate-abi.rs:68:12 | LL | extern "efiapi" fn m10() {} | ^^^^^^^^ @@ -329,8 +356,17 @@ 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:71:12 + --> $DIR/feature-gate-abi.rs:74:12 | LL | extern "rust-intrinsic" fn im1() {} | ^^^^^^^^^^^^^^^^ @@ -338,7 +374,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:73:12 + --> $DIR/feature-gate-abi.rs:76:12 | LL | extern "platform-intrinsic" fn im2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -347,7 +383,7 @@ LL | extern "platform-intrinsic" fn im2() {} = 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:75:12 + --> $DIR/feature-gate-abi.rs:78:12 | LL | extern "vectorcall" fn im3() {} | ^^^^^^^^^^^^ @@ -355,7 +391,7 @@ 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:76:12 + --> $DIR/feature-gate-abi.rs:79:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -364,7 +400,7 @@ LL | extern "rust-call" fn im4(_: ()) {} = 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:77:12 + --> $DIR/feature-gate-abi.rs:80:12 | LL | extern "msp430-interrupt" fn im5() {} | ^^^^^^^^^^^^^^^^^^ @@ -373,7 +409,7 @@ LL | extern "msp430-interrupt" fn im5() {} = 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:78:12 + --> $DIR/feature-gate-abi.rs:81:12 | LL | extern "ptx-kernel" fn im6() {} | ^^^^^^^^^^^^ @@ -382,7 +418,7 @@ LL | extern "ptx-kernel" fn im6() {} = 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:79:12 + --> $DIR/feature-gate-abi.rs:82:12 | LL | extern "x86-interrupt" fn im7() {} | ^^^^^^^^^^^^^^^ @@ -391,7 +427,7 @@ LL | extern "x86-interrupt" fn im7() {} = 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:80:12 + --> $DIR/feature-gate-abi.rs:83:12 | LL | extern "thiscall" fn im8() {} | ^^^^^^^^^^ @@ -399,7 +435,7 @@ 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:81:12 + --> $DIR/feature-gate-abi.rs:84:12 | LL | extern "amdgpu-kernel" fn im9() {} | ^^^^^^^^^^^^^^^ @@ -408,7 +444,7 @@ LL | extern "amdgpu-kernel" fn im9() {} = 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:82:12 + --> $DIR/feature-gate-abi.rs:85:12 | LL | extern "efiapi" fn im10() {} | ^^^^^^^^ @@ -416,8 +452,17 @@ 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:86:18 + --> $DIR/feature-gate-abi.rs:90:18 | LL | type A1 = extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^ @@ -425,7 +470,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:87:18 + --> $DIR/feature-gate-abi.rs:91:18 | LL | type A2 = extern "platform-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^ @@ -434,7 +479,7 @@ LL | type A2 = extern "platform-intrinsic" fn(); = 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:88:18 + --> $DIR/feature-gate-abi.rs:92:18 | LL | type A3 = extern "vectorcall" fn(); | ^^^^^^^^^^^^ @@ -442,7 +487,7 @@ 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:89:18 + --> $DIR/feature-gate-abi.rs:93:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -451,7 +496,7 @@ LL | type A4 = extern "rust-call" fn(_: ()); = 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:90:18 + --> $DIR/feature-gate-abi.rs:94:18 | LL | type A5 = extern "msp430-interrupt" fn(); | ^^^^^^^^^^^^^^^^^^ @@ -460,16 +505,16 @@ LL | type A5 = extern "msp430-interrupt" fn(); = 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:91:18 + --> $DIR/feature-gate-abi.rs:95:18 | -LL | type A6 = extern "ptx-kernel" fn (); +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:92:18 + --> $DIR/feature-gate-abi.rs:96:18 | LL | type A7 = extern "x86-interrupt" fn(); | ^^^^^^^^^^^^^^^ @@ -478,7 +523,7 @@ LL | type A7 = extern "x86-interrupt" fn(); = 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:93:18 + --> $DIR/feature-gate-abi.rs:97:18 | LL | type A8 = extern "thiscall" fn(); | ^^^^^^^^^^ @@ -486,7 +531,7 @@ 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:94:18 + --> $DIR/feature-gate-abi.rs:98:18 | LL | type A9 = extern "amdgpu-kernel" fn(); | ^^^^^^^^^^^^^^^ @@ -495,7 +540,7 @@ LL | type A9 = extern "amdgpu-kernel" fn(); = 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:95:19 + --> $DIR/feature-gate-abi.rs:99:19 | LL | type A10 = extern "efiapi" fn(); | ^^^^^^^^ @@ -503,8 +548,17 @@ 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:98:8 + --> $DIR/feature-gate-abi.rs:103:8 | LL | extern "rust-intrinsic" {} | ^^^^^^^^^^^^^^^^ @@ -512,7 +566,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:99:8 + --> $DIR/feature-gate-abi.rs:104:8 | LL | extern "platform-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^ @@ -521,7 +575,7 @@ LL | extern "platform-intrinsic" {} = 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:100:8 + --> $DIR/feature-gate-abi.rs:105:8 | LL | extern "vectorcall" {} | ^^^^^^^^^^^^ @@ -529,7 +583,7 @@ 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:101:8 + --> $DIR/feature-gate-abi.rs:106:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -538,7 +592,7 @@ LL | extern "rust-call" {} = 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:102:8 + --> $DIR/feature-gate-abi.rs:107:8 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^ @@ -547,7 +601,7 @@ LL | extern "msp430-interrupt" {} = 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:103:8 + --> $DIR/feature-gate-abi.rs:108:8 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^ @@ -556,7 +610,7 @@ LL | extern "ptx-kernel" {} = 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:104:8 + --> $DIR/feature-gate-abi.rs:109:8 | LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^ @@ -565,7 +619,7 @@ LL | extern "x86-interrupt" {} = 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:105:8 + --> $DIR/feature-gate-abi.rs:110:8 | LL | extern "thiscall" {} | ^^^^^^^^^^ @@ -573,7 +627,7 @@ 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:106:8 + --> $DIR/feature-gate-abi.rs:111:8 | LL | extern "amdgpu-kernel" {} | ^^^^^^^^^^^^^^^ @@ -582,7 +636,7 @@ LL | extern "amdgpu-kernel" {} = 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:107:8 + --> $DIR/feature-gate-abi.rs:112:8 | LL | extern "efiapi" {} | ^^^^^^^^ @@ -590,6 +644,15 @@ 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 | @@ -603,41 +666,41 @@ LL | extern "platform-intrinsic" fn m2(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:13:33 + --> $DIR/feature-gate-abi.rs:12:33 | LL | extern "rust-intrinsic" fn f1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:15:37 + --> $DIR/feature-gate-abi.rs:14:37 | LL | extern "platform-intrinsic" fn f2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:55:37 + --> $DIR/feature-gate-abi.rs:57:37 | LL | extern "rust-intrinsic" fn m1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:57:41 + --> $DIR/feature-gate-abi.rs:59:41 | LL | extern "platform-intrinsic" fn m2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:71:38 + --> $DIR/feature-gate-abi.rs:74:38 | LL | extern "rust-intrinsic" fn im1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:73:42 + --> $DIR/feature-gate-abi.rs:76:42 | LL | extern "platform-intrinsic" fn im2() {} | ^^ -error: aborting due to 76 previous errors +error: aborting due to 83 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.rs b/src/test/ui/feature-gates/feature-gate-const_fn.rs index 691c367aeb..b97aa214f8 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.rs +++ b/src/test/ui/feature-gates/feature-gate-const_fn.rs @@ -3,10 +3,8 @@ const fn foo() -> usize { 0 } // ok trait Foo { - const fn foo() -> u32; //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const - const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const + const fn foo() -> u32; //~ ERROR functions in traits cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const } impl Foo for u32 { diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.stderr b/src/test/ui/feature-gates/feature-gate-const_fn.stderr index 843e563013..1e7fd669b1 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_fn.stderr @@ -5,36 +5,17 @@ LL | const fn foo() -> u32; | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-const_fn.rs:8:5 + --> $DIR/feature-gate-const_fn.rs:7:5 | LL | const fn bar() -> u32 { 0 } | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-const_fn.rs:13:5 + --> $DIR/feature-gate-const_fn.rs:11:5 | LL | const fn foo() -> u32 { 0 } | ^^^^^ functions in traits cannot be const -error[E0658]: const fn is unstable - --> $DIR/feature-gate-const_fn.rs:6:5 - | -LL | const fn foo() -> u32; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0658]: const fn is unstable - --> $DIR/feature-gate-const_fn.rs:8:5 - | -LL | const fn bar() -> u32 { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0379, E0658. -For more information about an error, try `rustc --explain E0379`. +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr index f13803b80f..5cd38ebab3 100644 --- a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr @@ -1,4 +1,4 @@ -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 | LL | fn avg<T=i32>(_: T) {} @@ -8,7 +8,7 @@ LL | fn avg<T=i32>(_: T) {} = 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 #36887 <https://github.com/rust-lang/rust/issues/36887> -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 | LL | impl<T=i32> S<T> {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs new file mode 100644 index 0000000000..7f3392eada --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.rs @@ -0,0 +1,4 @@ +#[doc(notable_trait)] //~ ERROR: `#[doc(notable_trait)]` is experimental +trait SomeTrait {} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr new file mode 100644 index 0000000000..1f9bef40c4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-doc_notable_trait.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[doc(notable_trait)]` is experimental + --> $DIR/feature-gate-doc_notable_trait.rs:1:1 + | +LL | #[doc(notable_trait)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information + = help: add `#![feature(doc_notable_trait)]` 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-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs deleted file mode 100644 index 452b45b344..0000000000 --- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental -trait SomeTrait {} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr deleted file mode 100644 index 010d74054a..0000000000 --- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: `#[doc(spotlight)]` is experimental - --> $DIR/feature-gate-doc_spotlight.rs:1:1 - | -LL | #[doc(spotlight)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information - = help: add `#![feature(doc_spotlight)]` 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-edition_macro_pats.rs b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs deleted file mode 100644 index bd8a21ea36..0000000000 --- a/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Feature gate test for `edition_macro_pats` feature. - -macro_rules! foo { - ($x:pat2018) => {}; //~ERROR `pat2018` and `pat2021` are unstable - ($x:pat2021) => {}; //~ERROR `pat2018` and `pat2021` are unstable -} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr deleted file mode 100644 index 89bfb239d9..0000000000 --- a/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0658]: `pat2018` and `pat2021` are unstable. - --> $DIR/feature-gate-edition_macro_pats.rs:4:9 - | -LL | ($x:pat2018) => {}; - | ^^^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(edition_macro_pats)]` to the crate attributes to enable - -error[E0658]: `pat2018` and `pat2021` are unstable. - --> $DIR/feature-gate-edition_macro_pats.rs:5:9 - | -LL | ($x:pat2021) => {}; - | ^^^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(edition_macro_pats)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr index 266008cc0d..4afbde5021 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr @@ -69,8 +69,8 @@ LL | type Pointer2<U32> = Box<U32>; | help: consider restricting type parameter `U32` | -LL | type Pointer2<U32: Clone> = Box<U32>; - | ^^^^^^^ +LL | type Pointer2<U32: std::clone::Clone> = Box<U32>; + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-imported_main.rs b/src/test/ui/feature-gates/feature-gate-imported_main.rs new file mode 100644 index 0000000000..b351d0d0e9 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-imported_main.rs @@ -0,0 +1,6 @@ +pub mod foo { + pub fn bar() { + println!("Hello world!"); + } +} +use foo::bar as main; //~ ERROR using an imported function as entry point diff --git a/src/test/ui/feature-gates/feature-gate-imported_main.stderr b/src/test/ui/feature-gates/feature-gate-imported_main.stderr new file mode 100644 index 0000000000..3b879fdfc6 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-imported_main.stderr @@ -0,0 +1,12 @@ +error[E0658]: using an imported function as entry point `main` is experimental + --> $DIR/feature-gate-imported_main.rs:6:5 + | +LL | use foo::bar as main; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #28937 <https://github.com/rust-lang/rust/issues/28937> for more information + = help: add `#![feature(imported_main)]` 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-in_band_lifetimes.stderr b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr index 0f0406b8e1..497b8a429e 100644 --- a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr +++ b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr @@ -1,3 +1,87 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/feature-gate-in_band_lifetimes.rs:50:14 + | +LL | impl MyTrait<'a> for Y<&'a u8> { + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'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/feature-gate-in_band_lifetimes.rs:50:25 + | +LL | impl MyTrait<'a> for Y<&'a u8> { + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'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/feature-gate-in_band_lifetimes.rs:53:31 + | +LL | fn my_lifetime(&self) -> &'a u8 { self.0 } + | ^^ undeclared lifetime + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes +help: consider introducing lifetime `'a` here + | +LL | impl<'a> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'a` here + | +LL | fn my_lifetime<'a>(&self) -> &'a u8 { self.0 } + | ^^^^ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:55:27 + | +LL | fn any_lifetime() -> &'b u8 { &0 } + | ^^ undeclared lifetime + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes +help: consider introducing lifetime `'b` here + | +LL | impl<'b> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | fn any_lifetime<'b>() -> &'b u8 { &0 } + | ^^^^ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:57:27 + | +LL | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } + | ^^ undeclared lifetime + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes +help: consider introducing lifetime `'b` here + | +LL | impl<'b> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 } + | ^^^^ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:57:40 + | +LL | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } + | ^^ undeclared lifetime + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes +help: consider introducing lifetime `'b` here + | +LL | impl<'b> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 } + | ^^^^ + error[E0261]: use of undeclared lifetime name `'x` --> $DIR/feature-gate-in_band_lifetimes.rs:3:12 | @@ -142,90 +226,6 @@ help: consider introducing lifetime `'b` here LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8; | ^^^^ -error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/feature-gate-in_band_lifetimes.rs:50:14 - | -LL | impl MyTrait<'a> for Y<&'a u8> { - | - ^^ undeclared lifetime - | | - | help: consider introducing lifetime `'a` here: `<'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/feature-gate-in_band_lifetimes.rs:50:25 - | -LL | impl MyTrait<'a> for Y<&'a u8> { - | - ^^ undeclared lifetime - | | - | help: consider introducing lifetime `'a` here: `<'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/feature-gate-in_band_lifetimes.rs:53:31 - | -LL | fn my_lifetime(&self) -> &'a u8 { self.0 } - | ^^ undeclared lifetime - | - = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes -help: consider introducing lifetime `'a` here - | -LL | impl<'a> MyTrait<'a> for Y<&'a u8> { - | ^^^^ -help: consider introducing lifetime `'a` here - | -LL | fn my_lifetime<'a>(&self) -> &'a u8 { self.0 } - | ^^^^ - -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/feature-gate-in_band_lifetimes.rs:55:27 - | -LL | fn any_lifetime() -> &'b u8 { &0 } - | ^^ undeclared lifetime - | - = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes -help: consider introducing lifetime `'b` here - | -LL | impl<'b> MyTrait<'a> for Y<&'a u8> { - | ^^^^ -help: consider introducing lifetime `'b` here - | -LL | fn any_lifetime<'b>() -> &'b u8 { &0 } - | ^^^^ - -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/feature-gate-in_band_lifetimes.rs:57:27 - | -LL | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } - | ^^ undeclared lifetime - | - = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes -help: consider introducing lifetime `'b` here - | -LL | impl<'b> MyTrait<'a> for Y<&'a u8> { - | ^^^^ -help: consider introducing lifetime `'b` here - | -LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 } - | ^^^^ - -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/feature-gate-in_band_lifetimes.rs:57:40 - | -LL | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } - | ^^ undeclared lifetime - | - = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes -help: consider introducing lifetime `'b` here - | -LL | impl<'b> MyTrait<'a> for Y<&'a u8> { - | ^^^^ -help: consider introducing lifetime `'b` here - | -LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 } - | ^^^^ - error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/feature-gates/feature-gate-large-assignments.rs b/src/test/ui/feature-gates/feature-gate-large-assignments.rs new file mode 100644 index 0000000000..7e9e574bfa --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-large-assignments.rs @@ -0,0 +1,5 @@ +// check that `move_size_limit is feature-gated + +#![move_size_limit = "42"] //~ ERROR the `#[move_size_limit]` attribute is an experimental feature + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-large-assignments.stderr b/src/test/ui/feature-gates/feature-gate-large-assignments.stderr new file mode 100644 index 0000000000..8ddc3043e9 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-large-assignments.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[move_size_limit]` attribute is an experimental feature + --> $DIR/feature-gate-large-assignments.rs:3:1 + | +LL | #![move_size_limit = "42"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83518 <https://github.com/rust-lang/rust/issues/83518> for more information + = help: add `#![feature(large_assignments)]` 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-link_args.rs b/src/test/ui/feature-gates/feature-gate-link_args.rs deleted file mode 100644 index e1c651f46f..0000000000 --- a/src/test/ui/feature-gates/feature-gate-link_args.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Test that `#[link_args]` attribute is gated by `link_args` -// feature gate, both when it occurs where expected (atop -// `extern { }` blocks) and where unexpected. - -// sidestep warning (which is correct, but misleading for -// purposes of this test) -#![allow(unused_attributes)] -#![link_args = "-l unexpected_use_as_inner_attr_on_mod"] -//~^ ERROR the `link_args` attribute is experimental - -#[link_args = "-l expected_use_case"] -//~^ ERROR the `link_args` attribute is experimental -extern "C" {} - -#[link_args = "-l unexected_use_on_non_extern_item"] -//~^ ERROR: the `link_args` attribute is experimental -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-link_args.stderr b/src/test/ui/feature-gates/feature-gate-link_args.stderr deleted file mode 100644 index ae4918f5c9..0000000000 --- a/src/test/ui/feature-gates/feature-gate-link_args.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead - --> $DIR/feature-gate-link_args.rs:11:1 - | -LL | #[link_args = "-l expected_use_case"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #29596 <https://github.com/rust-lang/rust/issues/29596> for more information - = help: add `#![feature(link_args)]` to the crate attributes to enable - -error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead - --> $DIR/feature-gate-link_args.rs:15:1 - | -LL | #[link_args = "-l unexected_use_on_non_extern_item"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #29596 <https://github.com/rust-lang/rust/issues/29596> for more information - = help: add `#![feature(link_args)]` to the crate attributes to enable - -error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead - --> $DIR/feature-gate-link_args.rs:8:1 - | -LL | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #29596 <https://github.com/rust-lang/rust/issues/29596> for more information - = help: add `#![feature(link_args)]` 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/feature-gates/feature-gate-main.rs b/src/test/ui/feature-gates/feature-gate-main.rs deleted file mode 100644 index 9c304a1792..0000000000 --- a/src/test/ui/feature-gates/feature-gate-main.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[main] -fn foo() {} //~ ERROR: declaration of a non-standard `#[main]` function may change over time diff --git a/src/test/ui/feature-gates/feature-gate-main.stderr b/src/test/ui/feature-gates/feature-gate-main.stderr deleted file mode 100644 index f0ef3b38c6..0000000000 --- a/src/test/ui/feature-gates/feature-gate-main.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: declaration of a non-standard `#[main]` function may change over time, for now a top-level `fn main()` is required - --> $DIR/feature-gate-main.rs:2:1 - | -LL | fn foo() {} - | ^^^^^^^^^^^ - | - = note: see issue #29634 <https://github.com/rust-lang/rust/issues/29634> for more information - = help: add `#![feature(main)]` 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-min_const_fn.rs b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs index 5a01e053ed..8f9b433009 100644 --- a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs @@ -3,10 +3,8 @@ const fn foo() -> usize { 0 } // stabilized trait Foo { - const fn foo() -> u32; //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const - const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const + const fn foo() -> u32; //~ ERROR functions in traits cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const } impl Foo for u32 { diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr index 56a882e30f..d7a5859136 100644 --- a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr @@ -5,36 +5,17 @@ LL | const fn foo() -> u32; | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-min_const_fn.rs:8:5 + --> $DIR/feature-gate-min_const_fn.rs:7:5 | LL | const fn bar() -> u32 { 0 } | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-min_const_fn.rs:13:5 + --> $DIR/feature-gate-min_const_fn.rs:11:5 | LL | const fn foo() -> u32 { 0 } | ^^^^^ functions in traits cannot be const -error[E0658]: const fn is unstable - --> $DIR/feature-gate-min_const_fn.rs:6:5 - | -LL | const fn foo() -> u32; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0658]: const fn is unstable - --> $DIR/feature-gate-min_const_fn.rs:8:5 - | -LL | const fn bar() -> u32 { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0379, E0658. -For more information about an error, try `rustc --explain E0379`. +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/feature-gates/feature-gate-naked_functions.rs b/src/test/ui/feature-gates/feature-gate-naked_functions.rs index 06bddc422c..71ca5b9373 100644 --- a/src/test/ui/feature-gates/feature-gate-naked_functions.rs +++ b/src/test/ui/feature-gates/feature-gate-naked_functions.rs @@ -1,3 +1,4 @@ +// needs-asm-support #![feature(asm)] #[naked] diff --git a/src/test/ui/feature-gates/feature-gate-naked_functions.stderr b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr index d95561d201..653d7b738d 100644 --- a/src/test/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:3:1 + --> $DIR/feature-gate-naked_functions.rs:4:1 | LL | #[naked] | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | #[naked] = help: add `#![feature(naked_functions)]` to the crate attributes to enable error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:9:1 + --> $DIR/feature-gate-naked_functions.rs:10:1 | LL | #[naked] | ^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-no_coverage.rs b/src/test/ui/feature-gates/feature-gate-no_coverage.rs new file mode 100644 index 0000000000..fd4c6f7605 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-no_coverage.rs @@ -0,0 +1,13 @@ +#![crate_type = "lib"] + +#[derive(PartialEq, Eq)] // ensure deriving `Eq` does not enable `feature(no_coverage)` +struct Foo { + a: u8, + b: u32, +} + +#[no_coverage] //~ ERROR the `#[no_coverage]` attribute is an experimental feature +fn requires_feature_no_coverage() -> bool { + let bar = Foo { a: 0, b: 0 }; + bar == Foo { a: 0, b: 0 } +} diff --git a/src/test/ui/feature-gates/feature-gate-no_coverage.stderr b/src/test/ui/feature-gates/feature-gate-no_coverage.stderr new file mode 100644 index 0000000000..f7167e0b77 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-no_coverage.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[no_coverage]` attribute is an experimental feature + --> $DIR/feature-gate-no_coverage.rs:9:1 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + | + = note: see issue #84605 <https://github.com/rust-lang/rust/issues/84605> for more information + = help: add `#![feature(no_coverage)]` 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-non_ascii_idents.rs b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs deleted file mode 100644 index 5cc04ad5cd..0000000000 --- a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.rs +++ /dev/null @@ -1,33 +0,0 @@ -extern crate core as bäz; //~ ERROR non-ascii idents - -use föö::bar; //~ ERROR non-ascii idents - -mod föö { //~ ERROR non-ascii idents - pub fn bar() {} -} - -fn bär( //~ ERROR non-ascii idents - bäz: isize //~ ERROR non-ascii idents - ) { - let _ö: isize; //~ ERROR non-ascii idents - - match (1, 2) { - (_ä, _) => {} //~ ERROR non-ascii idents - } -} - -struct Föö { //~ ERROR non-ascii idents - föö: isize //~ ERROR non-ascii idents -} - -enum Bär { //~ ERROR non-ascii idents - Bäz { //~ ERROR non-ascii idents - qüx: isize //~ ERROR non-ascii idents - } -} - -extern "C" { - fn qüx(); //~ ERROR non-ascii idents -} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr deleted file mode 100644 index e9392ace4c..0000000000 --- a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr +++ /dev/null @@ -1,120 +0,0 @@ -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:1:22 - | -LL | extern crate core as bäz; - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:3:5 - | -LL | use föö::bar; - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:5:5 - | -LL | mod föö { - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:9:4 - | -LL | fn bär( - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:10:5 - | -LL | bäz: isize - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:12:9 - | -LL | let _ö: isize; - | ^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:15:10 - | -LL | (_ä, _) => {} - | ^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:19:8 - | -LL | struct Föö { - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:20:5 - | -LL | föö: isize - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:23:6 - | -LL | enum Bär { - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:24:5 - | -LL | Bäz { - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:25:9 - | -LL | qüx: isize - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/feature-gate-non_ascii_idents.rs:30:8 - | -LL | fn qüx(); - | ^^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error: aborting due to 13 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs index 8945360b7b..37348e476d 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs @@ -12,7 +12,7 @@ trait NonObjectSafe3 { } trait NonObjectSafe4 { - fn foo(&self, &Self); + fn foo(&self, s: &Self); } fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) { diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr index b61d560445..12195bc107 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -57,12 +57,12 @@ LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> { | = 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> - --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:19 + --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22 | LL | trait NonObjectSafe4 { | -------------- this trait cannot be made into an object... -LL | fn foo(&self, &Self); - | ^^^^^ ...because method `foo` references the `Self` type in this parameter +LL | fn foo(&self, s: &Self); + | ^^^^^ ...because method `foo` references the `Self` type in this parameter error[E0038]: the trait `NonObjectSafe1` cannot be made into an object --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 diff --git a/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr b/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr index 5ce4c5cccb..0526c6dc83 100644 --- a/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr +++ b/src/test/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyMarker`: +error[E0119]: conflicting implementations of trait `MyMarker` --> $DIR/feature-gate-overlapping_marker_traits.rs:6:1 | LL | impl<T: Display> MyMarker for T {} diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs deleted file mode 100644 index 5504ec317a..0000000000 --- a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub macro_rules! m1 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable - -#[cfg(FALSE)] -pub macro_rules! m2 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable - -pub(crate) macro_rules! m3 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable - -pub(in self) macro_rules! m4 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr deleted file mode 100644 index bfaec398d9..0000000000 --- a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0658]: `pub` on `macro_rules` items is unstable - --> $DIR/feature-gate-pub_macro_rules.rs:1:1 - | -LL | pub macro_rules! m1 { () => {} } - | ^^^ - | - = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information - = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable - -error[E0658]: `pub` on `macro_rules` items is unstable - --> $DIR/feature-gate-pub_macro_rules.rs:4:1 - | -LL | pub macro_rules! m2 { () => {} } - | ^^^ - | - = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information - = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable - -error[E0658]: `pub` on `macro_rules` items is unstable - --> $DIR/feature-gate-pub_macro_rules.rs:6:1 - | -LL | pub(crate) macro_rules! m3 { () => {} } - | ^^^^^^^^^^ - | - = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information - = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable - -error[E0658]: `pub` on `macro_rules` items is unstable - --> $DIR/feature-gate-pub_macro_rules.rs:8:1 - | -LL | pub(in self) macro_rules! m4 { () => {} } - | ^^^^^^^^^^^^ - | - = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information - = help: add `#![feature(pub_macro_rules)]` 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-rustc-attrs-1.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs index 9f5c92349e..04f816ea50 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate. #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr index 82dec1fd4c..822368a594 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable - --> $DIR/feature-gate-rustc-attrs-1.rs:5:1 + --> $DIR/feature-gate-rustc-attrs-1.rs:3:1 | LL | #[rustc_variance] | ^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[rustc_variance] = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable - --> $DIR/feature-gate-rustc-attrs-1.rs:6:1 + --> $DIR/feature-gate-rustc-attrs-1.rs:4:1 | LL | #[rustc_error] | ^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[rustc_error] = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable - --> $DIR/feature-gate-rustc-attrs-1.rs:7:1 + --> $DIR/feature-gate-rustc-attrs-1.rs:5:1 | LL | #[rustc_nonnull_optimization_guaranteed] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr index f3fa641209..78904b383f 100644 --- a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -107,7 +107,11 @@ LL | | } | |_^ doesn't have a size known at compile-time | = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)` - = note: required because it appears within the type `Dst<(dyn A + 'static)>` +note: required because it appears within the type `Dst<(dyn A + 'static)>` + --> $DIR/feature-gate-trivial_bounds.rs:48:8 + | +LL | struct Dst<X: ?Sized> { + | ^^^ = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr index 71acbb174a..3631a03938 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr +++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr @@ -8,8 +8,8 @@ LL | fn foo(x: dyn Foo) { = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn foo(&x: dyn Foo) { - | ^ +LL | fn foo(x: &dyn Foo) { + | ^ error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time --> $DIR/feature-gate-unsized_fn_params.rs:24:5 diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr index 5225422087..0919c2f3a1 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr +++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr @@ -8,8 +8,8 @@ LL | fn f(f: dyn FnOnce()) {} = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn f(&f: dyn FnOnce()) {} - | ^ +LL | fn f(f: &dyn FnOnce()) {} + | ^ error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-wasm_abi.rs b/src/test/ui/feature-gates/feature-gate-wasm_abi.rs new file mode 100644 index 0000000000..8c8de07636 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-wasm_abi.rs @@ -0,0 +1,7 @@ +extern "wasm" fn foo() { + //~^ ERROR: wasm ABI is experimental and subject to change +} + +fn main() { + foo(); +} diff --git a/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr b/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr new file mode 100644 index 0000000000..c4113fd6af --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr @@ -0,0 +1,12 @@ +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:1:8 + | +LL | extern "wasm" fn foo() { + | ^^^^^^ + | + = 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 + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index 6404b2c311..d1fbd38ce0 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -8,12 +8,11 @@ // which would mess up the treatment of other cases in // issue-43106-gating-of-builtin-attrs.rs) -// ignore-tidy-linelength #![macro_export] //~^ ERROR: `macro_export` attribute cannot be used at crate level -#![main] -//~^ ERROR: `main` attribute cannot be used at crate level +#![rustc_main] //~ ERROR: the `#[rustc_main]` attribute is used internally to specify +//~^ ERROR: `rustc_main` attribute cannot be used at crate level #![start] //~^ ERROR: `start` attribute cannot be used at crate level #![repr()] @@ -107,24 +106,6 @@ mod export_name { //~| NOTE not a function or static } -#[main] -//~^ ERROR: `main` attribute can only be used on functions -mod main { - mod inner { #![main] } - //~^ ERROR: `main` attribute can only be used on functions - - // for `fn f()` case, see feature-gate-main.rs - - #[main] struct S; - //~^ ERROR: `main` attribute can only be used on functions - - #[main] type T = S; - //~^ ERROR: `main` attribute can only be used on functions - - #[main] impl S { } - //~^ ERROR: `main` attribute can only be used on functions -} - #[start] //~^ ERROR: `start` attribute can only be used on functions mod start { diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 3ca1bd2ea7..ae2c428cc7 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -1,5 +1,13 @@ +error[E0658]: the `#[rustc_main]` attribute is used internally to specify test entry point function + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1 + | +LL | #![rustc_main] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:41:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5 | LL | #[inline = "2100"] fn f() { } | ^^^^^^^^^^^^^^^^^^ @@ -8,68 +16,38 @@ LL | #[inline = "2100"] fn f() { } = 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 #57571 <https://github.com/rust-lang/rust/issues/57571> -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:110:1 - | -LL | #[main] - | ^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:17 - | -LL | mod inner { #![main] } - | ^^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:118:5 - | -LL | #[main] struct S; - | ^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:121:5 - | -LL | #[main] type T = S; - | ^^^^^^^ - -error: `main` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:124:5 - | -LL | #[main] impl S { } - | ^^^^^^^ - error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:128:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:1 | LL | #[start] | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:131:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:112:17 | LL | mod inner { #![start] } | ^^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:136:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:5 | LL | #[start] struct S; | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:139:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:120:5 | LL | #[start] type T = S; | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:142:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:5 | LL | #[start] impl S { } | ^^^^^^^^ error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:31:1 | LL | #[inline] | ^^^^^^^^^ @@ -84,7 +62,7 @@ LL | | } | |_- not a function or closure error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:60:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:59:1 | LL | #[no_link] | ^^^^^^^^^^ @@ -99,7 +77,7 @@ LL | | } | |_- not an `extern crate` item error: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:86:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:85:1 | LL | #[export_name = "2200"] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,137 +92,138 @@ LL | | } | |_- not a function or static error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 | LL | #![no_link] | ^^^^^^^^^^^ error: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1 | LL | #![export_name = "2200"] | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1 | LL | #![inline] | ^^^^^^^^^^ error: `macro_export` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:13:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 | LL | #![macro_export] | ^^^^^^^^^^^^^^^^ -error: `main` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:15:1 +error: `rustc_main` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1 | -LL | #![main] - | ^^^^^^^^ +LL | #![rustc_main] + | ^^^^^^^^^^^^^^ error: `start` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1 | LL | #![start] | ^^^^^^^^^ error: `repr` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:18:1 | LL | #![repr()] | ^^^^^^^^^^ error: `path` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:20:1 | LL | #![path = "3800"] | ^^^^^^^^^^^^^^^^^ error: `automatically_derived` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:22:1 | LL | #![automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:37:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:17 | LL | mod inner { #![inline] } | ------------^^^^^^^^^^-- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:47:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 | LL | #[inline] struct S; | ^^^^^^^^^ --------- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:51:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:50:5 | LL | #[inline] type T = S; | ^^^^^^^^^ ----------- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:55:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:5 | LL | #[inline] impl S { } | ^^^^^^^^^ ---------- not a function or closure error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:65:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:64:17 | LL | mod inner { #![no_link] } | ------------^^^^^^^^^^^-- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:69:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:68:5 | LL | #[no_link] fn f() { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:73:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:72:5 | LL | #[no_link] struct S; | ^^^^^^^^^^ --------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:77:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:76:5 | LL | #[no_link]type T = S; | ^^^^^^^^^^----------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:81:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:5 | LL | #[no_link] impl S { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:90:17 | LL | mod inner { #![export_name="2200"] } | ------------^^^^^^^^^^^^^^^^^^^^^^-- not a function or static error: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:97:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5 | LL | #[export_name = "2200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static error: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:101:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:5 | LL | #[export_name = "2200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static error: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:105:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:104:5 | LL | #[export_name = "2200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static -error: aborting due to 36 previous errors +error: aborting due to 32 previous errors -For more information about this error, try `rustc --explain E0518`. +Some errors have detailed explanations: E0518, E0658. +For more information about an error, try `rustc --explain E0518`. diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 21f40524f6..19a60f1bcf 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -34,7 +34,6 @@ // occurrences in the source text. // check-pass -// ignore-tidy-linelength #![feature(test, plugin_registrar)] #![warn(unused_attributes, unknown_lints)] diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index c864ccc868..c207c05455 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -1,179 +1,179 @@ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:52:9 | LL | #![warn(x5400)] | ^^^^^ | note: the lint level is defined here - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:39:28 | LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:10 | LL | #![allow(x5300)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:11 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:11 | LL | #![forbid(x5200)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:9 | LL | #![deny(x5100)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:111:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:110:8 | LL | #[warn(x5400)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:25 | LL | mod inner { #![warn(x5400)] } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:12 | LL | #[warn(x5400)] fn f() { } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12 | LL | #[warn(x5400)] struct S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:12 | LL | #[warn(x5400)] type T = S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:12 | LL | #[warn(x5400)] impl S { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:130:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:9 | LL | #[allow(x5300)] | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:26 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:26 | LL | mod inner { #![allow(x5300)] } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:13 | LL | #[allow(x5300)] fn f() { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13 | LL | #[allow(x5300)] struct S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:13 | LL | #[allow(x5300)] type T = S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:13 | LL | #[allow(x5300)] impl S { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:149:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:10 | LL | #[forbid(x5200)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:27 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:27 | LL | mod inner { #![forbid(x5200)] } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:14 | LL | #[forbid(x5200)] fn f() { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14 | LL | #[forbid(x5200)] struct S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:14 | LL | #[forbid(x5200)] type T = S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:14 | LL | #[forbid(x5200)] impl S { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:168:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:8 | LL | #[deny(x5100)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:25 | LL | mod inner { #![deny(x5100)] } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:12 | LL | #[deny(x5100)] fn f() { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12 | LL | #[deny(x5100)] struct S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:180:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:12 | LL | #[deny(x5100)] type T = S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:12 | LL | #[deny(x5100)] impl S { } | ^^^^^ warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:441:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:440:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ @@ -181,13 +181,13 @@ LL | mod inner { #![macro_escape] } = help: try an outer attribute: `#[macro_use]` warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:437:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:17 | LL | mod inner { #![plugin_registrar] } | ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version @@ -195,49 +195,49 @@ LL | mod inner { #![plugin_registrar] } = note: `#[warn(deprecated)]` on by default warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:236:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5 | LL | #[plugin_registrar] struct S; | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:241:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:5 | LL | #[plugin_registrar] type T = S; | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:246:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:5 | LL | #[plugin_registrar] impl S { } | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:223:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:222:1 | LL | #[plugin_registrar] | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:1 | LL | #![plugin_registrar] | ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version warning: use of deprecated attribute `crate_id`: no longer used. - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:91:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:1 | LL | #![crate_id = "10"] | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute warning: use of deprecated attribute `no_start`: no longer used. - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:100:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:99:1 | LL | #![no_start] | ^^^^^^^^^^^^ help: remove this attribute warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ @@ -252,14 +252,14 @@ LL | | } | |_- not a function or static | note: the lint level is defined here - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:39:9 | LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:1 | LL | #[cold] | ^^^^^^^ @@ -276,7 +276,7 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:529:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:1 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -293,7 +293,7 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:568:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:1 | LL | #[link_section = "1800"] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -310,7 +310,7 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1 | LL | #![cold] | ^^^^^^^^ @@ -318,7 +318,7 @@ LL | #![cold] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:73:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 | LL | #![link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -326,7 +326,7 @@ LL | #![link_name = "1900"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:76:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:75:1 | LL | #![link_section = "1800"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -334,7 +334,7 @@ LL | #![link_section = "1800"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:17 | LL | mod inner { #![no_mangle] } | ------------^^^^^^^^^^^^^-- not a function or static @@ -342,7 +342,7 @@ LL | mod inner { #![no_mangle] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5 | LL | #[no_mangle] struct S; | ^^^^^^^^^^^^ --------- not a function or static @@ -350,7 +350,7 @@ LL | #[no_mangle] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:5 | LL | #[no_mangle] type T = S; | ^^^^^^^^^^^^ ----------- not a function or static @@ -358,7 +358,7 @@ LL | #[no_mangle] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:5 | LL | #[no_mangle] impl S { } | ^^^^^^^^^^^^ ---------- not a function or static @@ -366,7 +366,7 @@ LL | #[no_mangle] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:506:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:17 | LL | mod inner { #![cold] } | ------------^^^^^^^^-- not a function @@ -374,7 +374,7 @@ LL | mod inner { #![cold] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:5 | LL | #[cold] struct S; | ^^^^^^^ --------- not a function @@ -382,7 +382,7 @@ LL | #[cold] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:517:5 | LL | #[cold] type T = S; | ^^^^^^^ ----------- not a function @@ -390,7 +390,7 @@ LL | #[cold] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5 | LL | #[cold] impl S { } | ^^^^^^^ ---------- not a function @@ -398,7 +398,7 @@ LL | #[cold] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:534:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -408,13 +408,13 @@ LL | extern "C" { } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! help: try `#[link(name = "1900")]` instead - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:534:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:542:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:17 | LL | mod inner { #![link_name="1900"] } | ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static @@ -422,7 +422,7 @@ LL | mod inner { #![link_name="1900"] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:546:5 | LL | #[link_name = "1900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -430,7 +430,7 @@ LL | #[link_name = "1900"] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:5 | LL | #[link_name = "1900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static @@ -438,7 +438,7 @@ LL | #[link_name = "1900"] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:557:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:556:5 | LL | #[link_name = "1900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static @@ -446,7 +446,7 @@ LL | #[link_name = "1900"] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:562:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:561:5 | LL | #[link_name = "1900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -454,7 +454,7 @@ LL | #[link_name = "1900"] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:574:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:573:17 | LL | mod inner { #![link_section="1800"] } | ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static @@ -462,7 +462,7 @@ LL | mod inner { #![link_section="1800"] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:581:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:580:5 | LL | #[link_section = "1800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static @@ -470,7 +470,7 @@ LL | #[link_section = "1800"] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:586:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:585:5 | LL | #[link_section = "1800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static @@ -478,7 +478,7 @@ LL | #[link_section = "1800"] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:591:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:590:5 | LL | #[link_section = "1800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static @@ -486,7 +486,7 @@ LL | #[link_section = "1800"] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:96:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:95:12 | LL | #![feature(rust1)] | ^^^^^ @@ -494,847 +494,847 @@ LL | #![feature(rust1)] = note: `#[warn(stable_features)]` on by default warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:1 | LL | #![plugin_registrar] | ^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1 | LL | #![should_panic] | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1 | LL | #![ignore] | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 | LL | #![proc_macro_derive()] | ^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:5 | LL | #[macro_use] fn f() { } | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:194:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:5 | LL | #[macro_use] struct S; | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:196:5 | LL | #[macro_use] type T = S; | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:200:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:5 | LL | #[macro_use] impl S { } | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:203:1 | LL | #[macro_export] | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:206:17 | LL | mod inner { #![macro_export] } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:210:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:209:5 | LL | #[macro_export] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5 | LL | #[macro_export] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:215:5 | LL | #[macro_export] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:218:5 | LL | #[macro_export] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:223:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:222:1 | LL | #[plugin_registrar] | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:17 | LL | mod inner { #![plugin_registrar] } | ^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:236:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5 | LL | #[plugin_registrar] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:241:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:5 | LL | #[plugin_registrar] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:246:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:5 | LL | #[plugin_registrar] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:300:5 | LL | #[path = "3800"] fn f() { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:304:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:303:5 | LL | #[path = "3800"] struct S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:307:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:306:5 | LL | #[path = "3800"] type T = S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:310:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:309:5 | LL | #[path = "3800"] impl S { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:314:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:317:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:17 | LL | mod inner { #![automatically_derived] } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:320:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:319:5 | LL | #[automatically_derived] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:323:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:322:5 | LL | #[automatically_derived] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:326:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:5 | LL | #[automatically_derived] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:328:5 | LL | #[automatically_derived] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:1 | LL | #[should_panic] | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:17 | LL | mod inner { #![should_panic] } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:366:5 | LL | #[should_panic] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:369:5 | LL | #[should_panic] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:372:5 | LL | #[should_panic] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:375:5 | LL | #[should_panic] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:1 | LL | #[ignore] | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:382:17 | LL | mod inner { #![ignore] } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:385:5 | LL | #[ignore] fn f() { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:388:5 | LL | #[ignore] struct S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:391:5 | LL | #[ignore] type T = S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:394:5 | LL | #[ignore] impl S { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:1 | LL | #[no_implicit_prelude] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:17 | LL | mod inner { #![no_implicit_prelude] } | ^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5 | LL | #[no_implicit_prelude] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:5 | LL | #[no_implicit_prelude] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:410:5 | LL | #[no_implicit_prelude] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:413:5 | LL | #[no_implicit_prelude] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1 | LL | #[reexport_test_harness_main = "2900"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17 | LL | mod inner { #![reexport_test_harness_main="2900"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5 | LL | #[reexport_test_harness_main = "2900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5 | LL | #[reexport_test_harness_main = "2900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5 | LL | #[reexport_test_harness_main = "2900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5 | LL | #[reexport_test_harness_main = "2900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:444:5 | LL | #[macro_escape] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:447:5 | LL | #[macro_escape] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:5 | LL | #[macro_escape] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:453:5 | LL | #[macro_escape] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:1 | LL | #[no_std] | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:1 | LL | #[no_std] | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:478:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:478:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:662:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:662:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:670:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:670:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:678:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:678:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:1 | LL | #[no_main] | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:1 | LL | #[no_main] | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:739:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:739:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:792:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:792:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/thread-local-const-init.rs b/src/test/ui/feature-gates/thread-local-const-init.rs new file mode 100644 index 0000000000..6584ffa7cf --- /dev/null +++ b/src/test/ui/feature-gates/thread-local-const-init.rs @@ -0,0 +1,4 @@ +thread_local!(static X: u32 = const { 0 }); +//~^ ERROR: use of unstable library feature 'thread_local_const_init' + +fn main() {} diff --git a/src/test/ui/feature-gates/thread-local-const-init.stderr b/src/test/ui/feature-gates/thread-local-const-init.stderr new file mode 100644 index 0000000000..a35b18a9c2 --- /dev/null +++ b/src/test/ui/feature-gates/thread-local-const-init.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature 'thread_local_const_init' + --> $DIR/thread-local-const-init.rs:1:1 + | +LL | thread_local!(static X: u32 = const { 0 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #84223 <https://github.com/rust-lang/rust/issues/84223> for more information + = help: add `#![feature(thread_local_const_init)]` to the crate attributes to enable + = note: this error originates in a macro (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 E0658`. diff --git a/src/test/ui/bad/bad-main.rs b/src/test/ui/fn/bad-main.rs similarity index 100% rename from src/test/ui/bad/bad-main.rs rename to src/test/ui/fn/bad-main.rs diff --git a/src/test/ui/bad/bad-main.stderr b/src/test/ui/fn/bad-main.stderr similarity index 100% rename from src/test/ui/bad/bad-main.stderr rename to src/test/ui/fn/bad-main.stderr diff --git a/src/test/ui/issues/issue-45729-unsafe-in-generator.rs b/src/test/ui/generator/issue-45729-unsafe-in-generator.rs similarity index 100% rename from src/test/ui/issues/issue-45729-unsafe-in-generator.rs rename to src/test/ui/generator/issue-45729-unsafe-in-generator.rs diff --git a/src/test/ui/issues/issue-45729-unsafe-in-generator.stderr b/src/test/ui/generator/issue-45729-unsafe-in-generator.stderr similarity index 100% rename from src/test/ui/issues/issue-45729-unsafe-in-generator.stderr rename to src/test/ui/generator/issue-45729-unsafe-in-generator.stderr diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr index 881064d2f8..74ac53a7f9 100644 --- a/src/test/ui/generator/static-not-unpin.stderr +++ b/src/test/ui/generator/static-not-unpin.stderr @@ -6,6 +6,8 @@ LL | fn assert_unpin<T: Unpin>(_: T) { ... LL | assert_unpin(generator); | ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` + | + = note: consider using `Box::pin` error: aborting due to previous error diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 30e23ea8f6..3f1f33a3b1 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -16,10 +16,10 @@ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature- --> $DIR/type-mismatch-signature-deduction.rs:5:13 | LL | fn foo() -> impl Generator<Return = i32> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result` | - = note: expected enum `Result<{integer}, _>` - found type `i32` + = note: expected type `i32` + found enum `Result<{integer}, _>` error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs index 2dbd1840de..6527eb4750 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.rs +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(generic_associated_types)] //~^ WARNING: the feature `generic_associated_types` is incomplete #![feature(associated_type_defaults)] @@ -22,6 +20,7 @@ impl<T> Foo for Fooer<T> { } fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} +//~^ the trait `Foo` cannot be made into an object fn main() { diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr index f3769827f0..49dfce8b4b 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr @@ -1,5 +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.rs:3:12 + --> $DIR/gat-in-trait-path.rs:1:12 | LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,21 @@ 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 +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:22:13 + | +LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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 + | +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 +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 089a214667..50e1c50644 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -6,6 +6,7 @@ trait Foo { type A<'a> where Self: 'a; type B<'a, 'b> where 'a: 'b; type C where Self: Clone; + fn d() where Self: Clone; } #[derive(Copy, Clone)] @@ -19,6 +20,8 @@ impl<T> Foo for Fooy<T> { //~| ERROR lifetime bound not satisfied type C where Self: Copy = String; //~^ ERROR the trait bound `T: Copy` is not satisfied + fn d() where Self: Copy {} + //~^ ERROR the trait bound `T: Copy` is not satisfied } fn main() {} diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 645d292714..58bcb13e68 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -1,5 +1,5 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/impl_bounds.rs:15:5 + --> $DIR/impl_bounds.rs:16:5 | LL | type A<'a> where Self: 'static = (&'a ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,53 +8,80 @@ 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:17:5 + --> $DIR/impl_bounds.rs:18: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 17:16 - --> $DIR/impl_bounds.rs:17:16 +note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 18:16 + --> $DIR/impl_bounds.rs:18: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 17:12 - --> $DIR/impl_bounds.rs:17:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 18:12 + --> $DIR/impl_bounds.rs:18:12 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ error[E0478]: lifetime bound not satisfied - --> $DIR/impl_bounds.rs:17:5 + --> $DIR/impl_bounds.rs:18: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 17:12 - --> $DIR/impl_bounds.rs:17:12 +note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 18:12 + --> $DIR/impl_bounds.rs:18: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 17:16 - --> $DIR/impl_bounds.rs:17:16 +note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 18:16 + --> $DIR/impl_bounds.rs:18: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:20:5 + --> $DIR/impl_bounds.rs:21: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: the requirement `Fooy<T>: Copy` appears on the associated impl type but not on the corresponding associated trait type +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 + | +LL | trait Foo { + | --- in this trait +... +LL | type C where Self: Clone; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy` +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 + | +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: the requirement `Fooy<T>: Copy` appears on the impl method `d` but not on the corresponding trait method + --> $DIR/impl_bounds.rs:9:8 + | +LL | trait Foo { + | --- in this trait +... +LL | fn d() where Self: Clone; + | ^ this trait method doesn't have the requirement `Fooy<T>: Copy` help: consider restricting type parameter `T` | -LL | impl<T: Copy> Foo for Fooy<T> { - | ^^^^^^ +LL | impl<T: std::marker::Copy> Foo for Fooy<T> { + | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0277, E0310, E0478. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs index ff38b3e93e..6ee865072a 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.rs +++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(generic_associated_types)] //~^ WARNING: the feature `generic_associated_types` is incomplete @@ -8,5 +6,6 @@ trait X { } fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} +//~^ ERROR the trait `X` cannot be made into an object fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr index 0fbf704df7..65998afa7f 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr +++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr @@ -1,5 +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-pass.rs:3:12 + --> $DIR/issue-67510-pass.rs:1:12 | LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,21 @@ 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 +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510-pass.rs:8:19 + | +LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ `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 + | +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 +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr index b380f0da2e..c92800c374 100644 --- a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -18,8 +18,8 @@ LL | type Item<'a> = T; | help: consider restricting type parameter `T` | -LL | impl<T: Copy> UnsafeCopy for T { - | ^^^^^^ +LL | impl<T: std::marker::Copy> UnsafeCopy for T { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index 61950478c3..e44547b10c 100644 --- a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -19,8 +19,8 @@ LL | type F<'a> = Self; = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` help: consider restricting type parameter `T` | -LL | impl<T: Fn<()>> Fun for T { - | ^^^^^^^^ +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr index 1398061898..fd0b4733d9 100644 --- a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -19,8 +19,8 @@ LL | type F<'a> = Self; = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` help: consider restricting type parameter `T` | -LL | impl<T: Fn<()>> Fun for T { - | ^^^^^^^^ +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr index 8112425146..0c23c870f0 100644 --- a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -19,8 +19,8 @@ LL | type F<'a> = Self; = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` help: consider restricting type parameter `T` | -LL | impl<T: Fn<()>> Fun for T { - | ^^^^^^^^ +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index 22f50b3949..85d8d3f8e9 100644 --- a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -19,8 +19,8 @@ LL | type F<'a> = Self; = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` help: consider restricting type parameter `T` | -LL | impl<T: Fn<()>> Fun for T { - | ^^^^^^^^ +LL | impl<T: std::ops::Fn<()>> Fun for T { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generic-associated-types/issue-70303.rs b/src/test/ui/generic-associated-types/issue-70303.rs new file mode 100644 index 0000000000..a1cb2295b6 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-70303.rs @@ -0,0 +1,60 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait Document { + type Cursor<'a>: DocCursor<'a>; + + fn cursor(&self) -> Self::Cursor<'_>; +} + +struct DocumentImpl {} + +impl Document for DocumentImpl { + type Cursor<'a> = DocCursorImpl<'a>; + + fn cursor(&self) -> Self::Cursor<'_> { + DocCursorImpl { + document: &self, + } + } +} + + +trait DocCursor<'a> {} + +struct DocCursorImpl<'a> { + document: &'a DocumentImpl, +} + +impl<'a> DocCursor<'a> for DocCursorImpl<'a> {} + +struct Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + cursor: Cursor, + _phantom: std::marker::PhantomData<&'d ()>, +} + + +impl<'d, Cursor> Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + pub fn from<Doc>(document: &'d Doc) -> Lexer<'d, Cursor> + where + Doc: Document<Cursor<'d> = Cursor>, + { + Lexer { + cursor: document.cursor(), + _phantom: std::marker::PhantomData, + } + } +} + +pub fn main() { + let doc = DocumentImpl {}; + let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); +} diff --git a/src/test/ui/generic-associated-types/issue-70304.rs b/src/test/ui/generic-associated-types/issue-70304.rs new file mode 100644 index 0000000000..225f61d132 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-70304.rs @@ -0,0 +1,63 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait Document { + type Cursor<'a>: DocCursor<'a>; + + fn cursor(&self) -> Self::Cursor<'_>; +} + +struct DocumentImpl {} + +impl Document for DocumentImpl { + type Cursor<'a> = DocCursorImpl<'a>; + + fn cursor(&self) -> Self::Cursor<'_> { + DocCursorImpl { + document: &self, + } + } +} + + +trait DocCursor<'a> {} + +struct DocCursorImpl<'a> { + document: &'a DocumentImpl, +} + +impl<'a> DocCursor<'a> for DocCursorImpl<'a> {} + +struct Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + cursor: Cursor, + _phantom: std::marker::PhantomData<&'d ()>, +} + + +impl<'d, Cursor> Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + pub fn from<Doc>(document: &'d Doc) -> Lexer<'d, Cursor> + where + Doc: Document<Cursor<'d> = Cursor>, + { + Lexer { + cursor: document.cursor(), + _phantom: std::marker::PhantomData, + } + } +} + +fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { + //~^ ERROR: missing lifetime specifier + DocumentImpl {} +} + +pub fn main() { + let doc = create_doc(); + let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); +} diff --git a/src/test/ui/generic-associated-types/issue-70304.stderr b/src/test/ui/generic-associated-types/issue-70304.stderr new file mode 100644 index 0000000000..dfa8601897 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-70304.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-70304.rs:55:41 + | +LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn create_doc() -> impl Document<Cursor<'static> = DocCursorImpl<'_>> { + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/generic-associated-types/issue-71176.rs b/src/test/ui/generic-associated-types/issue-71176.rs new file mode 100644 index 0000000000..470476bf47 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-71176.rs @@ -0,0 +1,21 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait Provider { + type A<'a>; + //~^ ERROR: missing generics for associated type +} + +impl Provider for () { + type A<'a> = (); +} + +struct Holder<B> { + inner: Box<dyn Provider<A = B>>, +} + +fn main() { + Holder { + inner: Box::new(()), + }; +} diff --git a/src/test/ui/generic-associated-types/issue-71176.stderr b/src/test/ui/generic-associated-types/issue-71176.stderr new file mode 100644 index 0000000000..dd19dd4ad8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-71176.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `Provider::A` + --> $DIR/issue-71176.rs:5:10 + | +LL | type A<'a>; + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-71176.rs:5:10 + | +LL | type A<'a>; + | ^ -- +help: use angle brackets to add missing lifetime argument + | +LL | type A<'a><'a>; + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/issue-74824.stderr b/src/test/ui/generic-associated-types/issue-74824.stderr index 34a2c1932e..7a7b5fd4f1 100644 --- a/src/test/ui/generic-associated-types/issue-74824.stderr +++ b/src/test/ui/generic-associated-types/issue-74824.stderr @@ -19,8 +19,8 @@ LL | type Copy<T>: Copy = Box<T>; = note: required because of the requirements on the impl of `Clone` for `Box<T>` help: consider restricting type parameter `T` | -LL | type Copy<T: Clone>: Copy = Box<T>; - | ^^^^^^^ +LL | type Copy<T: std::clone::Clone>: Copy = Box<T>; + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs index 5e73a88298..9643c82db7 100644 --- a/src/test/ui/generic-associated-types/issue-76535.rs +++ b/src/test/ui/generic-associated-types/issue-76535.rs @@ -36,4 +36,6 @@ impl SuperTrait for SuperStruct { fn main() { let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); + //~^ ERROR the trait `SuperTrait` cannot be made into an object + //~^^ ERROR the trait `SuperTrait` cannot be made into an object } diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr index 17661e0d90..d31560f12f 100644 --- a/src/test/ui/generic-associated-types/issue-76535.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.stderr @@ -23,6 +23,39 @@ help: use angle brackets to add missing lifetime argument LL | type SubType<'a><'a>: SubTrait; | ^^^^ -error: aborting due to previous error; 1 warning emitted +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:38: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 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +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:38: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 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = 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 -For more information about this error, try `rustc --explain E0107`. +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-78671.rs b/src/test/ui/generic-associated-types/issue-78671.rs new file mode 100644 index 0000000000..4e47d3c665 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-78671.rs @@ -0,0 +1,15 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait CollectionFamily { + type Member<T>; + //~^ ERROR: missing generics for associated type +} +fn floatify() { + Box::new(Family) as &dyn CollectionFamily<Member=usize> + //~^ the trait `CollectionFamily` cannot be made into an object +} + +struct Family; + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.stderr new file mode 100644 index 0000000000..c9febfb59a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-78671.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:5:10 + | +LL | type Member<T>; + | ^^^^^^ expected 1 type argument + | +note: associated type defined here, with 1 type parameter: `T` + --> $DIR/issue-78671.rs:5:10 + | +LL | type Member<T>; + | ^^^^^^ - +help: use angle brackets to add missing type argument + | +LL | type Member<T><T>; + | ^^^ + +error[E0038]: the trait `CollectionFamily` cannot be made into an object + --> $DIR/issue-78671.rs:9: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 + | +LL | trait CollectionFamily { + | ---------------- this trait cannot be made into an object... +LL | type Member<T>; + | ^^^^^^ ...because it contains the generic associated type `Member` + +error: aborting due to 2 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-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs index aeb33ca546..b2ba3c24ab 100644 --- a/src/test/ui/generic-associated-types/issue-79422.rs +++ b/src/test/ui/generic-associated-types/issue-79422.rs @@ -42,5 +42,6 @@ impl<K, V: Default> MapLike<K, V> for Source { fn main() { let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; - //~^^ ERROR type mismatch resolving + //~^^ the trait `MapLike` cannot be made into an object + //~^^ the trait `MapLike` cannot be made into an object } diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr index a119bff03e..4973ae1972 100644 --- a/src/test/ui/generic-associated-types/issue-79422.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.stderr @@ -14,17 +14,39 @@ help: use angle brackets to add missing lifetime argument LL | type VRefCont<'a><'a>: RefCont<'a, V>; | ^^^^ -error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'static> == (dyn RefCont<'_, u8> + 'static)` +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:44: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 + | +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +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:43:13 | LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn RefCont`, found reference + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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 | - = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` - found reference `&'static u8` - = note: required for the cast to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>` +LL | trait MapLike<K, V> { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V>; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>` + = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0271. -For more information about an error, try `rustc --explain E0107`. +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-79636-1.rs b/src/test/ui/generic-associated-types/issue-79636-1.rs new file mode 100644 index 0000000000..17f9387e29 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79636-1.rs @@ -0,0 +1,24 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait Monad { + type Unwrapped; + type Wrapped<B>; + //~^ ERROR: missing generics for associated type `Monad::Wrapped` + + fn bind<B, F>(self, f: F) -> Self::Wrapped<B> { + todo!() + } +} + +fn join<MOuter, MInner, A>(outer: MOuter) -> MOuter::Wrapped<A> +where + MOuter: Monad<Unwrapped = MInner>, + MInner: Monad<Unwrapped = A, Wrapped = MOuter::Wrapped<A>>, +{ + outer.bind(|inner| inner) +} + +fn main() { + assert_eq!(join(Some(Some(true))), Some(true)); +} diff --git a/src/test/ui/generic-associated-types/issue-79636-1.stderr b/src/test/ui/generic-associated-types/issue-79636-1.stderr new file mode 100644 index 0000000000..58eeb43f70 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79636-1.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `Monad::Wrapped` + --> $DIR/issue-79636-1.rs:6:10 + | +LL | type Wrapped<B>; + | ^^^^^^^ expected 1 type argument + | +note: associated type defined here, with 1 type parameter: `B` + --> $DIR/issue-79636-1.rs:6:10 + | +LL | type Wrapped<B>; + | ^^^^^^^ - +help: use angle brackets to add missing type argument + | +LL | type Wrapped<B><B>; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/issue-79636-2.rs b/src/test/ui/generic-associated-types/issue-79636-2.rs new file mode 100644 index 0000000000..5a65421937 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79636-2.rs @@ -0,0 +1,18 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait SomeTrait { + type Wrapped<A>: SomeTrait; + //~^ ERROR: missing generics for associated type `SomeTrait::Wrapped` + + fn f() -> (); +} + +fn program<W>() -> () +where + W: SomeTrait<Wrapped = W>, +{ + return W::f(); +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-79636-2.stderr b/src/test/ui/generic-associated-types/issue-79636-2.stderr new file mode 100644 index 0000000000..d5e3c56ebb --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79636-2.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `SomeTrait::Wrapped` + --> $DIR/issue-79636-2.rs:5:10 + | +LL | type Wrapped<A>: SomeTrait; + | ^^^^^^^ expected 1 type argument + | +note: associated type defined here, with 1 type parameter: `A` + --> $DIR/issue-79636-2.rs:5:10 + | +LL | type Wrapped<A>: SomeTrait; + | ^^^^^^^ - +help: use angle brackets to add missing type argument + | +LL | type Wrapped<A><A>: SomeTrait; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr index 95cebbb868..d45ef83873 100644 --- a/src/test/ui/generic-associated-types/shadowing.stderr +++ b/src/test/ui/generic-associated-types/shadowing.stderr @@ -14,14 +14,6 @@ LL | impl<T> NoShadowT<T> for Option<T> { LL | type Bar<T> = i32; | ^ already used -error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope - --> $DIR/shadowing.rs:5:14 - | -LL | trait Shadow<'a> { - | -- first declared here -LL | type Bar<'a>; - | ^^ lifetime `'a` already in scope - error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope --> $DIR/shadowing.rs:14:14 | @@ -30,6 +22,14 @@ LL | impl<'a> NoShadow<'a> for &'a u32 { 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 + | +LL | trait Shadow<'a> { + | -- first declared here +LL | type Bar<'a>; + | ^^ lifetime `'a` already in scope + error: aborting due to 4 previous errors Some errors have detailed explanations: E0403, E0496. diff --git a/src/test/ui/generic-associated-types/trait-objects.rs b/src/test/ui/generic-associated-types/trait-objects.rs new file mode 100644 index 0000000000..997a550b0e --- /dev/null +++ b/src/test/ui/generic-associated-types/trait-objects.rs @@ -0,0 +1,16 @@ +#![feature(generic_associated_types)] +#![allow(incomplete_features)] + +trait StreamingIterator { + type Item<'a> where Self: 'a; + fn size_hint(&self) -> (usize, Option<usize>); + // Uncommenting makes `StreamingIterator` not object safe +// fn next(&mut self) -> Self::Item<'_>; +} + +fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { + //~^ the trait `StreamingIterator` cannot be made into an object + x.size_hint().0 +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr new file mode 100644 index 0000000000..a8f1768ba2 --- /dev/null +++ b/src/test/ui/generic-associated-types/trait-objects.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:11:16 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/bad/bad-mid-path-type-params.rs b/src/test/ui/generics/bad-mid-path-type-params.rs similarity index 100% rename from src/test/ui/bad/bad-mid-path-type-params.rs rename to src/test/ui/generics/bad-mid-path-type-params.rs diff --git a/src/test/ui/bad/bad-mid-path-type-params.stderr b/src/test/ui/generics/bad-mid-path-type-params.stderr similarity index 100% rename from src/test/ui/bad/bad-mid-path-type-params.stderr rename to src/test/ui/generics/bad-mid-path-type-params.stderr diff --git a/src/test/ui/generics/generic-function-item-where-type.rs b/src/test/ui/generics/generic-function-item-where-type.rs new file mode 100644 index 0000000000..e1b0578cad --- /dev/null +++ b/src/test/ui/generics/generic-function-item-where-type.rs @@ -0,0 +1,6 @@ +fn foo<U>() {} + +fn main() { + foo::<main>() + //~^ ERROR constant provided when a type was expected +} diff --git a/src/test/ui/generics/generic-function-item-where-type.stderr b/src/test/ui/generics/generic-function-item-where-type.stderr new file mode 100644 index 0000000000..88594129ca --- /dev/null +++ b/src/test/ui/generics/generic-function-item-where-type.stderr @@ -0,0 +1,12 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/generic-function-item-where-type.rs:4:11 + | +LL | foo::<main>() + | ^^^^ + | + = help: `main` is a function item, not a type + = help: function item types cannot be named directly + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index 8d9883dc7a..16ea71d48c 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -1,10 +1,10 @@ struct Heap; struct Vec<A = Heap, T>(A, T); -//~^ ERROR type parameters with a default must be trailing +//~^ ERROR generic parameters with a default must be trailing struct Foo<A, B = Vec<C>, C>(A, B, C); -//~^ ERROR type parameters with a default must be trailing -//~| ERROR type parameters with a default cannot use forward declared identifiers +//~^ ERROR generic parameters with a default must be trailing +//~| ERROR generic parameters with a default cannot use fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index fb359f673a..713ba091b8 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -1,20 +1,20 @@ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/generic-non-trailing-defaults.rs:3:12 | LL | struct Vec<A = Heap, T>(A, T); | ^ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/generic-non-trailing-defaults.rs:6:15 | LL | struct Foo<A, B = Vec<C>, C>(A, B, C); | ^ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/generic-non-trailing-defaults.rs:6:23 | LL | struct Foo<A, B = Vec<C>, C>(A, B, C); - | ^ defaulted type parameters cannot be forward declared + | ^ defaulted generic parameters cannot be forward declared error: aborting due to 3 previous errors diff --git a/src/test/ui/generics/generic-type-params-forward-mention.rs b/src/test/ui/generics/generic-type-params-forward-mention.rs index ac0cab20d7..000c47095d 100644 --- a/src/test/ui/generics/generic-type-params-forward-mention.rs +++ b/src/test/ui/generics/generic-type-params-forward-mention.rs @@ -1,6 +1,6 @@ // Ensure that we get an error and not an ICE for this problematic case. struct Foo<T = Option<U>, U = bool>(T, U); -//~^ ERROR type parameters with a default cannot use forward declared identifiers +//~^ ERROR generic parameters with a default cannot use forward declared identifiers fn main() { let x: Foo; } diff --git a/src/test/ui/generics/generic-type-params-forward-mention.stderr b/src/test/ui/generics/generic-type-params-forward-mention.stderr index 97389c337f..fa661c274e 100644 --- a/src/test/ui/generics/generic-type-params-forward-mention.stderr +++ b/src/test/ui/generics/generic-type-params-forward-mention.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/generic-type-params-forward-mention.rs:2:23 | LL | struct Foo<T = Option<U>, U = bool>(T, U); - | ^ defaulted type parameters cannot be forward declared + | ^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr index 1106a06782..ce853d4d36 100644 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -4,6 +4,17 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here LL | fn should_error<T>() where T : Into<&u32> {} | ^ explicit lifetime name needed here +error[E0106]: missing lifetime specifier + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17 + | +LL | fn bar<'b, L: X<&'b Nested<i32>>>(){} + | ^ expected named lifetime parameter + | +help: consider using the `'b` lifetime + | +LL | fn bar<'b, L: X<'b, &'b Nested<i32>>>(){} + | ^^^ + error[E0106]: missing lifetime specifier --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:21 | @@ -22,17 +33,6 @@ help: consider using one of the available lifetimes here LL | fn foo<'b, L: X<'lifetime, &'b Nested<K>>>(); | ^^^^^^^^^^ -error[E0106]: missing lifetime specifier - --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17 - | -LL | fn bar<'b, L: X<&'b Nested<i32>>>(){} - | ^ expected named lifetime parameter - | -help: consider using the `'b` lifetime - | -LL | fn bar<'b, L: X<'b, &'b Nested<i32>>>(){} - | ^^^ - error: aborting due to 3 previous errors Some errors have detailed explanations: E0106, E0637. diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr index 73bd76aa5f..94fdd355d4 100644 --- a/src/test/ui/generics/wrong-number-of-args.stderr +++ b/src/test/ui/generics/wrong-number-of-args.stderr @@ -1,36 +1,3 @@ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:44:14 - | -LL | type A = Ty; - | ^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Ty<'a>; - | ^^^^ ^^^^^^ - -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:54:17 - | -LL | type C = Ty<usize>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type C<'a> = Ty<'a, usize>; - | ^^^^ ^^^ - -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:100:22 - | -LL | type B = Box<dyn GenericLifetime>; - | ^^^^^^^^^^^^^^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type B<'a> = Box<dyn GenericLifetime<'a>>; - | ^^^^ ^^^^^^^^^^^^^^^^^^^ - error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied --> $DIR/wrong-number-of-args.rs:6:14 | @@ -165,6 +132,17 @@ help: use angle brackets to add missing type argument LL | type A = Ty<T>; | ^^^ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:44:14 + | +LL | type A = Ty; + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Ty<'a>; + | ^^^^ ^^^^^^ + error[E0107]: this struct takes 1 type argument but 0 type arguments were supplied --> $DIR/wrong-number-of-args.rs:50:14 | @@ -181,6 +159,17 @@ help: add missing type argument LL | type B = Ty<'static, T>; | ^^^ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:54:17 + | +LL | type C = Ty<usize>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type C<'a> = Ty<'a, usize>; + | ^^^^ ^^^ + error[E0107]: missing generics for struct `type_and_type_and_type::Ty` --> $DIR/wrong-number-of-args.rs:64:14 | @@ -243,6 +232,17 @@ note: trait defined here, with 0 type parameters LL | trait NonGeneric { | ^^^^^^^^^^ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:100:22 + | +LL | type B = Box<dyn GenericLifetime>; + | ^^^^^^^^^^^^^^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type B<'a> = Box<dyn GenericLifetime<'a>>; + | ^^^^ ^^^^^^^^^^^^^^^^^^^ + error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied --> $DIR/wrong-number-of-args.rs:104:22 | diff --git a/src/test/ui/hrtb/complex.rs b/src/test/ui/hrtb/complex.rs new file mode 100644 index 0000000000..8cdfe247e0 --- /dev/null +++ b/src/test/ui/hrtb/complex.rs @@ -0,0 +1,28 @@ +// check-pass + +trait A<'a> {} +trait B<'b> {} +fn foo<T>() where for<'a> T: A<'a> + 'a {} +trait C<'c>: for<'a> A<'a> + for<'b> B<'b> { + type As; +} +struct D<T> where T: for<'c> C<'c, As=&'c ()> { + t: std::marker::PhantomData<T>, +} +trait E<'e, 'g> { + type As; +} +trait F<'f>: for<'a> A<'a> + for<'e> E<'e, 'f> {} +struct G<T> where T: for<'f> F<'f, As=&'f ()> { + t: std::marker::PhantomData<T>, +} +trait H<'a, 'b> { + type As; +} +trait I<'a>: for<'b> H<'a, 'b> {} + +struct J<T> where T: for<'i> I<'i, As=&'i ()> { + t: std::marker::PhantomData<T>, +} + +fn main() {} diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 2342a4f6e1..7b81beeed4 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -15,7 +15,11 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42 LL | let v = Unit2.m( | ^ expected struct `Unit4`, found struct `Unit3` | - = note: required because of the requirements on the impl of `for<'r> T0<'r, (<Unit2 as Ty<'r>>::V,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>` +note: required because of the requirements on the impl of `for<'r> T0<'r, (<Unit2 as Ty<'r>>::V,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>` + --> $DIR/issue-62203-hrtb-ice.rs:17:16 + | +LL | impl<'a, A, T> T0<'a, A> for L<T> + | ^^^^^^^^^ ^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr index d24336883e..2913a955dc 100644 --- a/src/test/ui/hygiene/trait_items.stderr +++ b/src/test/ui/hygiene/trait_items.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `f` found for unit type `()` in the current scope --> $DIR/trait_items.rs:17:24 | +LL | fn f(&self) {} + | - the method is available for `()` here +... LL | fn f() { ::baz::m!(); } | ------------ in this macro invocation ... diff --git a/src/test/ui/impl-trait/auto-trait.full_tait.stderr b/src/test/ui/impl-trait/auto-trait.full_tait.stderr index 7ac08ab492..314617748b 100644 --- a/src/test/ui/impl-trait/auto-trait.full_tait.stderr +++ b/src/test/ui/impl-trait/auto-trait.full_tait.stderr @@ -7,7 +7,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[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`: +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>` --> $DIR/auto-trait.rs:24:1 | LL | impl<T: Send> AnotherTrait for T {} diff --git a/src/test/ui/impl-trait/auto-trait.min_tait.stderr b/src/test/ui/impl-trait/auto-trait.min_tait.stderr index a497dd67e9..75a5b0cb87 100644 --- a/src/test/ui/impl-trait/auto-trait.min_tait.stderr +++ b/src/test/ui/impl-trait/auto-trait.min_tait.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`: +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>` --> $DIR/auto-trait.rs:24:1 | LL | impl<T: Send> AnotherTrait for T {} diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index 5bf3ec733f..d3056fb885 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // edition:2018 #![feature(impl_trait_in_bindings)] diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index a7d06c7166..ba3a2e7f8d 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -1,5 +1,5 @@ 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:4:12 + --> $DIR/bound-normalization-fail.rs:3:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -8,32 +8,32 @@ LL | #![feature(impl_trait_in_bindings)] = 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:27:32 + --> $DIR/bound-normalization-fail.rs:26:32 | LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | - = note: expected type `()` - found associated type `<T as impl_trait::Trait>::Assoc` + = 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> { | ^^^^^^^^^^^^ error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/bound-normalization-fail.rs:43:41 + --> $DIR/bound-normalization-fail.rs:42:41 | 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:43:41 + --> $DIR/bound-normalization-fail.rs:42:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | - = note: expected type `()` - found associated type `<T as lifetimes::Trait<'static>>::Assoc` + = 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> { diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index 1443b76048..3318866c52 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -35,8 +35,10 @@ LL | let _: i32 = Leak::leak(hide(0_i32)); | = note: expected type `i32` found associated type `<impl Foo as Leak>::T` - = help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32` + | +LL | fn hide<T: Foo>(x: T) -> impl Foo<T = i32> { + | ^^^^^^^^^ error[E0308]: mismatched types --> $DIR/equality2.rs:38:10 diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr index 638a0093fb..d37670db08 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr +++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr @@ -5,8 +5,10 @@ LL | fn foo<A: Debug>(&self, a: &A, b: &impl Debug); | -- type in trait ... LL | fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { } - | - ^^^^^^^^^^^ expected type parameter `B`, found type parameter `impl Debug` - | | + | - ^^^^^^^^^^^ + | | | + | | expected type parameter `B`, found type parameter `impl Debug` + | | help: change the parameter type to match the trait: `&B` | expected type parameter | = note: expected fn pointer `fn(&(), &B, &impl Debug)` diff --git a/src/test/ui/impl-trait-in-bindings-issue-73003.rs b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs similarity index 100% rename from src/test/ui/impl-trait-in-bindings-issue-73003.rs rename to src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs diff --git a/src/test/ui/impl-trait-in-bindings-issue-73003.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr similarity index 100% rename from src/test/ui/impl-trait-in-bindings-issue-73003.stderr rename to src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr diff --git a/src/test/ui/impl-trait-in-bindings.rs b/src/test/ui/impl-trait/impl-trait-in-bindings.rs similarity index 100% rename from src/test/ui/impl-trait-in-bindings.rs rename to src/test/ui/impl-trait/impl-trait-in-bindings.rs diff --git a/src/test/ui/impl-trait-in-bindings.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings.stderr similarity index 100% rename from src/test/ui/impl-trait-in-bindings.stderr rename to src/test/ui/impl-trait/impl-trait-in-bindings.stderr diff --git a/src/test/ui/impl-trait/issue-55872-1.full_tait.stderr b/src/test/ui/impl-trait/issue-55872-1.full_tait.stderr index 5195333884..286dd7aafb 100644 --- a/src/test/ui/impl-trait/issue-55872-1.full_tait.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.full_tait.stderr @@ -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/issue-55872-1.rs:4:32 + --> $DIR/issue-55872-1.rs:3:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ 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[E0276]: impl has stricter requirements than trait - --> $DIR/issue-55872-1.rs:18:5 + --> $DIR/issue-55872-1.rs:17:5 | LL | fn foo<T>() -> Self::E; | ----------------------- definition of `foo` from trait @@ -17,7 +17,7 @@ LL | fn foo<T: Default>() -> Self::E { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Default` error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)` - --> $DIR/issue-55872-1.rs:14:14 + --> $DIR/issue-55872-1.rs:13:14 | LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` @@ -25,11 +25,11 @@ LL | type E = impl Copy; = note: required because it appears within the type `(S, T)` help: consider further restricting this bound | -LL | impl<S: Default + Copy> Bar for S { - | ^^^^^^ +LL | impl<S: Default + std::marker::Copy> Bar for S { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)` - --> $DIR/issue-55872-1.rs:14:14 + --> $DIR/issue-55872-1.rs:13:14 | LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` @@ -37,11 +37,11 @@ LL | type E = impl Copy; = note: required because it appears within the type `(S, T)` help: consider further restricting this bound | -LL | fn foo<T: Default + Copy>() -> Self::E { - | ^^^^^^ +LL | fn foo<T: Default + std::marker::Copy>() -> Self::E { + | ^^^^^^^^^^^^^^^^^^^ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-1.rs:18:37 + --> $DIR/issue-55872-1.rs:17:37 | LL | fn foo<T: Default>() -> Self::E { | _____________________________________^ diff --git a/src/test/ui/impl-trait/issue-55872-1.min_tait.stderr b/src/test/ui/impl-trait/issue-55872-1.min_tait.stderr index 26fc200c2a..653299f4cb 100644 --- a/src/test/ui/impl-trait/issue-55872-1.min_tait.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.min_tait.stderr @@ -1,5 +1,5 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/issue-55872-1.rs:18:5 + --> $DIR/issue-55872-1.rs:17:5 | LL | fn foo<T>() -> Self::E; | ----------------------- definition of `foo` from trait @@ -8,7 +8,7 @@ LL | fn foo<T: Default>() -> Self::E { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Default` error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)` - --> $DIR/issue-55872-1.rs:14:14 + --> $DIR/issue-55872-1.rs:13:14 | LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` @@ -16,11 +16,11 @@ LL | type E = impl Copy; = note: required because it appears within the type `(S, T)` help: consider further restricting this bound | -LL | impl<S: Default + Copy> Bar for S { - | ^^^^^^ +LL | impl<S: Default + std::marker::Copy> Bar for S { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)` - --> $DIR/issue-55872-1.rs:14:14 + --> $DIR/issue-55872-1.rs:13:14 | LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` @@ -28,11 +28,11 @@ LL | type E = impl Copy; = note: required because it appears within the type `(S, T)` help: consider further restricting this bound | -LL | fn foo<T: Default + Copy>() -> Self::E { - | ^^^^^^ +LL | fn foo<T: Default + std::marker::Copy>() -> Self::E { + | ^^^^^^^^^^^^^^^^^^^ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-1.rs:18:37 + --> $DIR/issue-55872-1.rs:17:37 | LL | fn foo<T: Default>() -> Self::E { | _____________________________________^ diff --git a/src/test/ui/impl-trait/issue-55872-1.rs b/src/test/ui/impl-trait/issue-55872-1.rs index e5e437cd84..a9e9c9b5be 100644 --- a/src/test/ui/impl-trait/issue-55872-1.rs +++ b/src/test/ui/impl-trait/issue-55872-1.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] diff --git a/src/test/ui/impl-trait/issue-55872-2.full_tait.stderr b/src/test/ui/impl-trait/issue-55872-2.full_tait.stderr index 14a5c0ba97..a8fc681a09 100644 --- a/src/test/ui/impl-trait/issue-55872-2.full_tait.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.full_tait.stderr @@ -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/issue-55872-2.rs:7:32 + --> $DIR/issue-55872-2.rs:6:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -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[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/issue-55872-2.rs:17:14 + --> $DIR/issue-55872-2.rs:16:14 | LL | type E = impl std::marker::Copy; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:19:28 + --> $DIR/issue-55872-2.rs:18:28 | LL | fn foo<T>() -> Self::E { | ____________________________^ diff --git a/src/test/ui/impl-trait/issue-55872-2.min_tait.stderr b/src/test/ui/impl-trait/issue-55872-2.min_tait.stderr index c8df502345..57f81443dc 100644 --- a/src/test/ui/impl-trait/issue-55872-2.min_tait.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.min_tait.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/issue-55872-2.rs:17:14 + --> $DIR/issue-55872-2.rs:16:14 | LL | type E = impl std::marker::Copy; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:19:28 + --> $DIR/issue-55872-2.rs:18:28 | LL | fn foo<T>() -> Self::E { | ____________________________^ diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index 9c2e9b860c..cd72b2eec3 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -1,5 +1,4 @@ // edition:2018 -// ignore-tidy-linelength // ignore-compare-mode-chalk // revisions: min_tait full_tait diff --git a/src/test/ui/impl-trait/issue-55872.full_tait.stderr b/src/test/ui/impl-trait/issue-55872.full_tait.stderr index 5a35689a73..e549fec1c2 100644 --- a/src/test/ui/impl-trait/issue-55872.full_tait.stderr +++ b/src/test/ui/impl-trait/issue-55872.full_tait.stderr @@ -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/issue-55872.rs:5:32 + --> $DIR/issue-55872.rs:4:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ 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: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872.rs:17:28 + --> $DIR/issue-55872.rs:16:28 | LL | fn foo<T>() -> Self::E { | ____________________________^ diff --git a/src/test/ui/impl-trait/issue-55872.min_tait.stderr b/src/test/ui/impl-trait/issue-55872.min_tait.stderr index 9baf283464..341dba95ca 100644 --- a/src/test/ui/impl-trait/issue-55872.min_tait.stderr +++ b/src/test/ui/impl-trait/issue-55872.min_tait.stderr @@ -1,5 +1,5 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872.rs:17:28 + --> $DIR/issue-55872.rs:16:28 | LL | fn foo<T>() -> Self::E { | ____________________________^ diff --git a/src/test/ui/impl-trait/issue-55872.rs b/src/test/ui/impl-trait/issue-55872.rs index 9a31cf521b..e3fc523fec 100644 --- a/src/test/ui/impl-trait/issue-55872.rs +++ b/src/test/ui/impl-trait/issue-55872.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-compare-mode-chalk // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] diff --git a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr index bd4d4fdf2a..8e42b9d46d 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr @@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<' --> $DIR/issue-70877.rs:11:12 | LL | type FooRet = impl std::fmt::Debug; - | -------------------- the expected opaque type + | -------------------- the found opaque type ... LL | type Foo = impl Iterator<Item = FooItem>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found enum `Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found opaque type | - = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` - found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>` + = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>` + found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr index bd4d4fdf2a..8e42b9d46d 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr @@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<' --> $DIR/issue-70877.rs:11:12 | LL | type FooRet = impl std::fmt::Debug; - | -------------------- the expected opaque type + | -------------------- the found opaque type ... LL | type Foo = impl Iterator<Item = FooItem>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found enum `Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found opaque type | - = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` - found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>` + = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>` + found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs new file mode 100644 index 0000000000..d9d2e3929b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs @@ -0,0 +1,12 @@ +struct Foo<T = impl Copy>(T); +//~^ ERROR `impl Trait` not allowed outside of function and inherent 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 + +// should not cause ICE +fn x() -> Foo { + Foo(0) +} + +fn main() -> Result<()> {} diff --git a/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr new file mode 100644 index 0000000000..eef6844adf --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr @@ -0,0 +1,15 @@ +error[E0562]: `impl Trait` not allowed outside of function and inherent 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 + --> $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>; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/negative-reasoning.full_tait.stderr b/src/test/ui/impl-trait/negative-reasoning.full_tait.stderr index 2611205893..bccbc8cb36 100644 --- a/src/test/ui/impl-trait/negative-reasoning.full_tait.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.full_tait.stderr @@ -7,7 +7,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[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`: +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>` --> $DIR/negative-reasoning.rs:22:1 | LL | impl<T: std::fmt::Debug> AnotherTrait for T {} diff --git a/src/test/ui/impl-trait/negative-reasoning.min_tait.stderr b/src/test/ui/impl-trait/negative-reasoning.min_tait.stderr index bd74b56fec..5727a372dd 100644 --- a/src/test/ui/impl-trait/negative-reasoning.min_tait.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.min_tait.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`: +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>` --> $DIR/negative-reasoning.rs:22:1 | LL | impl<T: std::fmt::Debug> AnotherTrait for T {} diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 64ddcb81c0..b993115502 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -37,6 +37,9 @@ LL | use no_method_suggested_traits::Reexported; error[E0599]: no method named `method` found for type `char` in the current scope --> $DIR/no-method-suggested-traits.rs:30:9 | +LL | fn method(&self) {} + | ------ the method is available for `char` here +... LL | 'a'.method(); | ^^^^^^ method not found in `char` | @@ -63,6 +66,11 @@ error[E0599]: no method named `method` found for type `i32` in the current scope | LL | 1i32.method(); | ^^^^^^ method not found in `i32` + | + ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12 + | +LL | fn method(&self) {} + | ------ the method is available for `i32` here | = 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: diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs new file mode 100644 index 0000000000..b4fd6b3e74 --- /dev/null +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs @@ -0,0 +1,20 @@ +pub trait Super { + type Assoc; +} + +impl Super for () { + type Assoc = u8; +} + +pub trait Test {} + +impl<T> Test for T where T: Super<Assoc = ()> {} + +fn test() -> impl Test { + //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()` + () +} + +fn main() { + let a = test(); +} diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr new file mode 100644 index 0000000000..54eb5a96c9 --- /dev/null +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -0,0 +1,15 @@ +error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()` + --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14 + | +LL | fn test() -> impl Test { + | ^^^^^^^^^ expected `()`, found `u8` + | +note: required because of the requirements on the impl of `Test` for `()` + --> $DIR/projection-mismatch-in-impl-where-clause.rs:11:9 + | +LL | impl<T> Test for T where T: Super<Assoc = ()> {} + | ^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index 961bb73511..bea2433983 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -1,8 +1,11 @@ error[E0053]: method `fmt` has an incompatible type for trait - --> $DIR/trait_type.rs:7:4 + --> $DIR/trait_type.rs:7:21 | LL | fn fmt(&self, x: &str) -> () { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | ^^^^ + | | + | types differ in mutability + | help: change the parameter type to match the trait: `&mut Formatter<'_>` | = note: expected fn pointer `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` found fn pointer `fn(&MyType, &str)` diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index 72b880fb92..c3e21c81f0 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -56,12 +56,10 @@ fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } 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 nested `impl Trait` is not allowed -//~| ERROR cannot resolve opaque type // 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 cannot resolve opaque type // Disallowed fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() } @@ -120,7 +118,6 @@ trait DummyTrait { impl DummyTrait for () { type Out = impl Debug; //~^ ERROR `impl Trait` in type aliases is unstable - //~^^ ERROR could not find defining uses fn in_trait_impl_parameter(_: impl Debug) { } // Allowed @@ -156,7 +153,6 @@ extern "C" fn in_extern_fn_return() -> impl Debug { type InTypeAlias<R> = impl Debug; //~^ ERROR `impl Trait` in type aliases is unstable -//~^^ ERROR could not find defining uses type InReturnInTypeAlias<R> = fn() -> impl Debug; //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types @@ -218,6 +214,34 @@ fn in_Fn_return_in_fn_where_clause<T>() { } +// Disallowed +struct InStructGenericParamDefault<T = impl Debug>(T); +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + +// Disallowed +enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) } +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + +// Disallowed +trait InTraitGenericParamDefault<T = impl Debug> {} +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + +// Disallowed +type InTypeAliasGenericParamDefault<T = impl Debug> = T; +//~^ ERROR `impl Trait` not allowed outside of function and inherent 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 + +// 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 + fn main() { let _in_local_variable: impl Fn() = || {}; //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 3fdeddc0a8..09ec4d5b20 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic | outer `impl Trait` error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:121:16 + --> $DIR/where-allowed.rs:119:16 | LL | type Out = impl Debug; | ^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Out = impl Debug; = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:157:23 + --> $DIR/where-allowed.rs:154:23 | LL | type InTypeAlias<R> = impl Debug; | ^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | type InTypeAlias<R> = impl Debug; = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:161:39 + --> $DIR/where-allowed.rs:157:39 | LL | type InReturnInTypeAlias<R> = fn() -> impl Debug; | ^^^^^^^^^^ @@ -110,139 +110,175 @@ 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 - --> $DIR/where-allowed.rs:62:59 + --> $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 - --> $DIR/where-allowed.rs:67:38 + --> $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 - --> $DIR/where-allowed.rs:71:40 + --> $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 - --> $DIR/where-allowed.rs:84:32 + --> $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 - --> $DIR/where-allowed.rs:88:41 + --> $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 - --> $DIR/where-allowed.rs:92:27 + --> $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 - --> $DIR/where-allowed.rs:97:25 + --> $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 - --> $DIR/where-allowed.rs:99:20 + --> $DIR/where-allowed.rs:97:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:110:23 + --> $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 - --> $DIR/where-allowed.rs:128:34 + --> $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 - --> $DIR/where-allowed.rs:141:33 + --> $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 - --> $DIR/where-allowed.rs:144:31 + --> $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 - --> $DIR/where-allowed.rs:161:39 + --> $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 - --> $DIR/where-allowed.rs:166:16 + --> $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 - --> $DIR/where-allowed.rs:171:24 + --> $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 - --> $DIR/where-allowed.rs:176:6 + --> $DIR/where-allowed.rs:172:6 | LL | impl impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:182:24 + --> $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 - --> $DIR/where-allowed.rs:188:11 + --> $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 - --> $DIR/where-allowed.rs:195:15 + --> $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 - --> $DIR/where-allowed.rs:202:24 + --> $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 - --> $DIR/where-allowed.rs:209:17 + --> $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 - --> $DIR/where-allowed.rs:216:22 + --> $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 - --> $DIR/where-allowed.rs:222:29 + --> $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 + --> $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 + --> $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 + --> $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 + --> $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 + --> $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 + --> $DIR/where-allowed.rs:246:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ @@ -250,44 +286,31 @@ 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 - --> $DIR/where-allowed.rs:224:46 + --> $DIR/where-allowed.rs:248:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ -error[E0720]: cannot resolve opaque type - --> $DIR/where-allowed.rs:56:49 - | -LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } - | ^^^^^^^^^^^^^^^^^^^ -------- this returned value is of `!` type - | | - | cannot resolve opaque type - | - = help: this error will resolve once the item's body returns a concrete type - -error[E0720]: cannot resolve opaque type - --> $DIR/where-allowed.rs:62:46 +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:234:7 | -LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } - | ^^^^^^^^^^^^^^^^^^^^^^^ -------- this returned value is of `!` type - | | - | cannot resolve opaque type +LL | impl <T = impl Debug> T {} + | ^ | - = help: this error will resolve once the item's body returns a concrete type + = note: `#[deny(invalid_type_param_default)]` 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 #36887 <https://github.com/rust-lang/rust/issues/36887> -error: could not find defining uses - --> $DIR/where-allowed.rs:121:16 +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:240:36 | -LL | type Out = impl Debug; - | ^^^^^^^^^^ - -error: could not find defining uses - --> $DIR/where-allowed.rs:157:23 +LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {} + | ^ | -LL | type InTypeAlias<R> = impl Debug; - | ^^^^^^^^^^ + = 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 #36887 <https://github.com/rust-lang/rust/issues/36887> -error: aborting due to 44 previous errors +error: aborting due to 48 previous errors -Some errors have detailed explanations: E0562, E0658, E0666, E0720. +Some errors have detailed explanations: E0562, E0658, E0666. For more information about an error, try `rustc --explain E0562`. diff --git a/src/test/ui/imports/extern-prelude-extern-crate-fail.rs b/src/test/ui/imports/extern-prelude-extern-crate-fail.rs index 4a0c612020..feb1ab09dc 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-fail.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-fail.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // aux-build:two_macros.rs // compile-flags:--extern non_existent diff --git a/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr index 2d7a1bf468..011ea02050 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr +++ b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr @@ -1,5 +1,5 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` - --> $DIR/extern-prelude-extern-crate-fail.rs:18:9 + --> $DIR/extern-prelude-extern-crate-fail.rs:16:9 | LL | extern crate std as non_existent; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | define_std_as_non_existent!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module `two_macros` - --> $DIR/extern-prelude-extern-crate-fail.rs:12:9 + --> $DIR/extern-prelude-extern-crate-fail.rs:10:9 | LL | two_macros::m!(); | ^^^^^^^^^^ use of undeclared crate or module `two_macros` diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.rs b/src/test/ui/imports/local-modularized-tricky-fail-2.rs index e637edadb0..386de88bc3 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-2.rs +++ b/src/test/ui/imports/local-modularized-tricky-fail-2.rs @@ -1,48 +1,22 @@ -// `#[macro_export] macro_rules` that doesn't originate from macro expansions can be placed -// into the root module soon enough to act as usual items and shadow globs and preludes. +// Crate-local macro expanded `macro_export` macros cannot be accessed with module-relative paths. -#![feature(decl_macro)] - -// `macro_export` shadows globs -use inner1::*; - -mod inner1 { - pub macro exported() {} -} - -exported!(); - -mod deep { - fn deep() { - type Deeper = [u8; { - #[macro_export] - macro_rules! exported { - () => ( struct Б; ) //~ ERROR non-ascii idents are not fully supported - } - - 0 - }]; +macro_rules! define_exported { () => { + #[macro_export] + macro_rules! exported { + () => () } -} +}} -// `macro_export` shadows std prelude -fn main() { - panic!(); -} +define_exported!(); -mod inner3 { - #[macro_export] - macro_rules! panic { - () => ( struct Г; ) //~ ERROR non-ascii idents are not fully supported - } +mod m { + use exported; + //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot + //~| WARN this was previously accepted } -// `macro_export` shadows builtin macros -include!(); - -mod inner4 { - #[macro_export] - macro_rules! include { - () => ( struct Д; ) //~ ERROR non-ascii idents are not fully supported - } +fn main() { + ::exported!(); + //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot + //~| WARN this was previously accepted } diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr index 714c04add5..5cc6fa1e40 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr @@ -1,42 +1,43 @@ -error[E0658]: non-ascii idents are not fully supported - --> $DIR/local-modularized-tricky-fail-2.rs:20:32 +error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths + --> $DIR/local-modularized-tricky-fail-2.rs:13:9 | -LL | exported!(); - | ------------ in this macro invocation -... -LL | () => ( struct Б; ) - | ^ +LL | use exported; + | ^^^^^^^^ | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/local-modularized-tricky-fail-2.rs:36:24 + = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` 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 #52234 <https://github.com/rust-lang/rust/issues/52234> +note: the macro is defined here + --> $DIR/local-modularized-tricky-fail-2.rs:5:5 | -LL | panic!(); - | --------- in this macro invocation +LL | / macro_rules! exported { +LL | | () => () +LL | | } + | |_____^ ... -LL | () => ( struct Г; ) - | ^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable +LL | define_exported!(); + | ------------------- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: non-ascii idents are not fully supported - --> $DIR/local-modularized-tricky-fail-2.rs:46:24 +error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths + --> $DIR/local-modularized-tricky-fail-2.rs:19:5 | -LL | include!(); - | ----------- in this macro invocation -... -LL | () => ( struct Д; ) - | ^ +LL | ::exported!(); + | ^^^^^^^^^^ + | + = 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 #52234 <https://github.com/rust-lang/rust/issues/52234> +note: the macro is defined here + --> $DIR/local-modularized-tricky-fail-2.rs:5:5 | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable +LL | / macro_rules! exported { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_exported!(); + | ------------------- in this macro invocation = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/imports/local-modularized-tricky-fail-3.rs b/src/test/ui/imports/local-modularized-tricky-fail-3.rs deleted file mode 100644 index 386de88bc3..0000000000 --- a/src/test/ui/imports/local-modularized-tricky-fail-3.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Crate-local macro expanded `macro_export` macros cannot be accessed with module-relative paths. - -macro_rules! define_exported { () => { - #[macro_export] - macro_rules! exported { - () => () - } -}} - -define_exported!(); - -mod m { - use exported; - //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot - //~| WARN this was previously accepted -} - -fn main() { - ::exported!(); - //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot - //~| WARN this was previously accepted -} diff --git a/src/test/ui/imports/local-modularized-tricky-fail-3.stderr b/src/test/ui/imports/local-modularized-tricky-fail-3.stderr deleted file mode 100644 index 4494a88a5c..0000000000 --- a/src/test/ui/imports/local-modularized-tricky-fail-3.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths - --> $DIR/local-modularized-tricky-fail-3.rs:13:9 - | -LL | use exported; - | ^^^^^^^^ - | - = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` 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 #52234 <https://github.com/rust-lang/rust/issues/52234> -note: the macro is defined here - --> $DIR/local-modularized-tricky-fail-3.rs:5:5 - | -LL | / macro_rules! exported { -LL | | () => () -LL | | } - | |_____^ -... -LL | define_exported!(); - | ------------------- in this macro invocation - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths - --> $DIR/local-modularized-tricky-fail-3.rs:19:5 - | -LL | ::exported!(); - | ^^^^^^^^^^ - | - = 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 #52234 <https://github.com/rust-lang/rust/issues/52234> -note: the macro is defined here - --> $DIR/local-modularized-tricky-fail-3.rs:5:5 - | -LL | / macro_rules! exported { -LL | | () => () -LL | | } - | |_____^ -... -LL | define_exported!(); - | ------------------- in this macro invocation - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/imports/local-modularized-tricky-pass.rs b/src/test/ui/imports/local-modularized-tricky-pass-1.rs similarity index 100% rename from src/test/ui/imports/local-modularized-tricky-pass.rs rename to src/test/ui/imports/local-modularized-tricky-pass-1.rs diff --git a/src/test/ui/imports/local-modularized-tricky-pass-2.rs b/src/test/ui/imports/local-modularized-tricky-pass-2.rs new file mode 100644 index 0000000000..d5efbdf78a --- /dev/null +++ b/src/test/ui/imports/local-modularized-tricky-pass-2.rs @@ -0,0 +1,50 @@ +// check-pass +// +// `#[macro_export] macro_rules` that doesn't originate from macro expansions can be placed +// into the root module soon enough to act as usual items and shadow globs and preludes. + +#![feature(decl_macro)] + +// `macro_export` shadows globs +use inner1::*; + +mod inner1 { + pub macro exported() {} +} + +exported!(); + +mod deep { + fn deep() { + type Deeper = [u8; { + #[macro_export] + macro_rules! exported { + () => ( struct Б; ) + } + + 0 + }]; + } +} + +// `macro_export` shadows std prelude +fn main() { + panic!(); +} + +mod inner3 { + #[macro_export] + macro_rules! panic { + () => ( struct Г; ) + } +} + +// `macro_export` shadows builtin macros +include!(); + +mod inner4 { + #[macro_export] + macro_rules! include { + () => ( struct Д; ) + } +} diff --git a/src/test/ui/imports/tool-mod-child.rs b/src/test/ui/imports/tool-mod-child.rs new file mode 100644 index 0000000000..4581dc2e2a --- /dev/null +++ b/src/test/ui/imports/tool-mod-child.rs @@ -0,0 +1,7 @@ +use clippy::a; //~ ERROR unresolved import `clippy` +use clippy::a::b; //~ ERROR failed to resolve: maybe a missing crate `clippy`? + +use rustdoc::a; //~ ERROR unresolved import `rustdoc` +use rustdoc::a::b; //~ ERROR failed to resolve: maybe a missing crate `rustdoc`? + +fn main() {} diff --git a/src/test/ui/imports/tool-mod-child.stderr b/src/test/ui/imports/tool-mod-child.stderr new file mode 100644 index 0000000000..efab4f6a74 --- /dev/null +++ b/src/test/ui/imports/tool-mod-child.stderr @@ -0,0 +1,28 @@ +error[E0433]: failed to resolve: maybe a missing crate `clippy`? + --> $DIR/tool-mod-child.rs:2:5 + | +LL | use clippy::a::b; + | ^^^^^^ maybe a missing crate `clippy`? + +error[E0432]: unresolved import `clippy` + --> $DIR/tool-mod-child.rs:1:5 + | +LL | use clippy::a; + | ^^^^^^ maybe a missing crate `clippy`? + +error[E0433]: failed to resolve: maybe a missing crate `rustdoc`? + --> $DIR/tool-mod-child.rs:5:5 + | +LL | use rustdoc::a::b; + | ^^^^^^^ maybe a missing crate `rustdoc`? + +error[E0432]: unresolved import `rustdoc` + --> $DIR/tool-mod-child.rs:4:5 + | +LL | use rustdoc::a; + | ^^^^^^^ maybe a missing crate `rustdoc`? + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/inference/issue-81522.rs b/src/test/ui/inference/issue-81522.rs new file mode 100644 index 0000000000..902f8fdde5 --- /dev/null +++ b/src/test/ui/inference/issue-81522.rs @@ -0,0 +1,31 @@ +// Regression test for #81522. +// Ensures that `#[allow(unstable_name_collisions)]` appended to things other than function +// suppresses the corresponding diagnostics emitted from inside them. +// But note that this attribute doesn't work for macro invocations if it is appended directly. + +// aux-build:inference_unstable_iterator.rs +// aux-build:inference_unstable_itertools.rs +// run-pass + +extern crate inference_unstable_iterator; +extern crate inference_unstable_itertools; + +#[allow(unused_imports)] +use inference_unstable_iterator::IpuIterator; +use inference_unstable_itertools::IpuItertools; + +fn main() { + // expression statement + #[allow(unstable_name_collisions)] + 'x'.ipu_flatten(); + + // let statement + #[allow(unstable_name_collisions)] + let _ = 'x'.ipu_flatten(); + + // block expression + #[allow(unstable_name_collisions)] + { + 'x'.ipu_flatten(); + } +} diff --git a/src/test/ui/inference/issue-83606.rs b/src/test/ui/inference/issue-83606.rs new file mode 100644 index 0000000000..be56a3020c --- /dev/null +++ b/src/test/ui/inference/issue-83606.rs @@ -0,0 +1,10 @@ +// Regression test for #83606. + +fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] { + [0; N] +} + +fn main() { + let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`! + //~^ ERROR: type annotations needed for `[usize; _]` +} diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr new file mode 100644 index 0000000000..65f3336b93 --- /dev/null +++ b/src/test/ui/inference/issue-83606.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for `[usize; _]` + --> $DIR/issue-83606.rs:8:13 + | +LL | let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`! + | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` + | | + | consider giving this pattern the explicit type `[usize; _]`, where the type parameter `N` is specified + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/bad/bad-intrinsic-monomorphization.rs b/src/test/ui/intrinsics/bad-intrinsic-monomorphization.rs similarity index 100% rename from src/test/ui/bad/bad-intrinsic-monomorphization.rs rename to src/test/ui/intrinsics/bad-intrinsic-monomorphization.rs diff --git a/src/test/ui/bad/bad-intrinsic-monomorphization.stderr b/src/test/ui/intrinsics/bad-intrinsic-monomorphization.stderr similarity index 100% rename from src/test/ui/bad/bad-intrinsic-monomorphization.stderr rename to src/test/ui/intrinsics/bad-intrinsic-monomorphization.stderr diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs index 2bf40db5ad..592409ba89 100644 --- a/src/test/ui/intrinsics/intrinsic-alignment.rs +++ b/src/test/ui/intrinsics/intrinsic-alignment.rs @@ -1,7 +1,7 @@ // run-pass // ignore-wasm32-bare seems not important to test here -#![feature(intrinsics, main)] +#![feature(intrinsics)] mod rusti { extern "rust-intrinsic" { @@ -21,7 +21,6 @@ mod rusti { target_os = "solaris", target_os = "vxworks"))] mod m { - #[main] #[cfg(target_arch = "x86")] pub fn main() { unsafe { @@ -30,7 +29,6 @@ mod m { } } - #[main] #[cfg(not(target_arch = "x86"))] pub fn main() { unsafe { @@ -42,7 +40,6 @@ mod m { #[cfg(target_env = "sgx")] mod m { - #[main] #[cfg(target_arch = "x86_64")] pub fn main() { unsafe { @@ -54,7 +51,6 @@ mod m { #[cfg(target_os = "windows")] mod m { - #[main] pub fn main() { unsafe { assert_eq!(::rusti::pref_align_of::<u64>(), 8); @@ -62,3 +58,7 @@ mod m { } } } + +fn main() { + m::main(); +} diff --git a/src/test/ui/intrinsics/issue-84297-reifying-copy.rs b/src/test/ui/intrinsics/issue-84297-reifying-copy.rs new file mode 100644 index 0000000000..08ba9ce7ec --- /dev/null +++ b/src/test/ui/intrinsics/issue-84297-reifying-copy.rs @@ -0,0 +1,9 @@ +// check-pass + +fn main() { + let _unused = if true { + core::ptr::copy::<i32> + } else { + core::ptr::copy_nonoverlapping::<i32> + }; +} diff --git a/src/test/ui/issue-83639.rs b/src/test/ui/issue-83639.rs new file mode 100644 index 0000000000..6ddbedfa0b --- /dev/null +++ b/src/test/ui/issue-83639.rs @@ -0,0 +1,6 @@ +// check-fail +// ignore-tidy-tab + +fn main() { + """ " //~ ERROR +} diff --git a/src/test/ui/issue-83639.stderr b/src/test/ui/issue-83639.stderr new file mode 100644 index 0000000000..4c10df1917 --- /dev/null +++ b/src/test/ui/issue-83639.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `" "` + --> $DIR/issue-83639.rs:5:7 + | +LL | """ " + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to previous error + diff --git a/src/test/ui/issue-85713-align-with-no-arg.rs b/src/test/ui/issue-85713-align-with-no-arg.rs new file mode 100644 index 0000000000..1afb8e7cb5 --- /dev/null +++ b/src/test/ui/issue-85713-align-with-no-arg.rs @@ -0,0 +1,6 @@ +#[repr(align)] +//~^ ERROR unrecognized representation hint +//~| ERROR unrecognized representation hint +pub struct Foo; + +pub fn main() { } diff --git a/src/test/ui/issue-85713-align-with-no-arg.stderr b/src/test/ui/issue-85713-align-with-no-arg.stderr new file mode 100644 index 0000000000..99b22ec698 --- /dev/null +++ b/src/test/ui/issue-85713-align-with-no-arg.stderr @@ -0,0 +1,15 @@ +error[E0552]: unrecognized representation hint + --> $DIR/issue-85713-align-with-no-arg.rs:1:8 + | +LL | #[repr(align)] + | ^^^^^ + +error[E0552]: unrecognized representation hint + --> $DIR/issue-85713-align-with-no-arg.rs:1:8 + | +LL | #[repr(align)] + | ^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0552`. diff --git a/src/test/ui/issues/issue-13033.stderr b/src/test/ui/issues/issue-13033.stderr index 57447fa48a..6c3651ff12 100644 --- a/src/test/ui/issues/issue-13033.stderr +++ b/src/test/ui/issues/issue-13033.stderr @@ -8,7 +8,7 @@ LL | fn bar(&mut self, other: &dyn Foo) {} | ^^^^^^^^ | | | types differ in mutability - | help: consider changing the mutability to match the trait: `&mut dyn Foo` + | help: change the parameter type to match the trait: `&mut dyn Foo` | = note: expected fn pointer `fn(&mut Baz, &mut dyn Foo)` found fn pointer `fn(&mut Baz, &dyn Foo)` diff --git a/src/test/ui/issues/issue-15487.rs b/src/test/ui/issues/issue-15487.rs deleted file mode 100644 index 34ac53be5b..0000000000 --- a/src/test/ui/issues/issue-15487.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass -#![allow(unused_attributes)] -// ignore-windows -// ignore-wasm32-bare no libs to link -// ignore-sgx no libs to link -#![feature(link_args)] - -#[link_args = "-lc -lm"] -#[link_args = " -lc"] -#[link_args = "-lc "] -extern "C" {} - -fn main() {} diff --git a/src/test/ui/issues/issue-18183.stderr b/src/test/ui/issues/issue-18183.stderr index c8f8ac9296..a7dc64708d 100644 --- a/src/test/ui/issues/issue-18183.stderr +++ b/src/test/ui/issues/issue-18183.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/issue-18183.rs:1:20 | LL | pub struct Foo<Bar=Bar>(Bar); - | ^^^ defaulted type parameters cannot be forward declared + | ^^^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18400.stderr b/src/test/ui/issues/issue-18400.stderr index 3bd9c656e8..92d5308844 100644 --- a/src/test/ui/issues/issue-18400.stderr +++ b/src/test/ui/issues/issue-18400.stderr @@ -5,7 +5,11 @@ LL | 0.contains(bits); | ^^^^^^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_18400`) - = note: required because of the requirements on the impl of `Set<&[_]>` for `{integer}` +note: required because of the requirements on the impl of `Set<&[_]>` for `{integer}` + --> $DIR/issue-18400.rs:6:16 + | +LL | impl<'a, T, S> Set<&'a [T]> for S where + | ^^^^^^^^^^^^ ^ = note: 128 redundant requirements hidden = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}` diff --git a/src/test/ui/issues/issue-20225.stderr b/src/test/ui/issues/issue-20225.stderr index 3bcc50ded8..6f4813ca62 100644 --- a/src/test/ui/issues/issue-20225.stderr +++ b/src/test/ui/issues/issue-20225.stderr @@ -1,33 +1,42 @@ error[E0053]: method `call` has an incompatible type for trait - --> $DIR/issue-20225.rs:6:3 + --> $DIR/issue-20225.rs:6:43 | LL | impl<'a, T> Fn<(&'a T,)> for Foo { | - this type parameter LL | extern "rust-call" fn call(&self, (_,): (T,)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T` + | ^^^^ + | | + | expected `&T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` | = note: expected fn pointer `extern "rust-call" fn(&Foo, (&'a T,))` found fn pointer `extern "rust-call" fn(&Foo, (T,))` error[E0053]: method `call_mut` has an incompatible type for trait - --> $DIR/issue-20225.rs:11:3 + --> $DIR/issue-20225.rs:11:51 | LL | impl<'a, T> FnMut<(&'a T,)> for Foo { | - this type parameter LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T` + | ^^^^ + | | + | expected `&T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` | = note: expected fn pointer `extern "rust-call" fn(&mut Foo, (&'a T,))` found fn pointer `extern "rust-call" fn(&mut Foo, (T,))` error[E0053]: method `call_once` has an incompatible type for trait - --> $DIR/issue-20225.rs:18:3 + --> $DIR/issue-20225.rs:18:47 | LL | impl<'a, T> FnOnce<(&'a T,)> for Foo { | - this type parameter ... LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T` + | ^^^^ + | | + | expected `&T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` | = note: expected fn pointer `extern "rust-call" fn(Foo, (&'a T,))` found fn pointer `extern "rust-call" fn(Foo, (T,))` diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index b167bb77b5..7fb1e3f2bb 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -16,7 +16,11 @@ LL | impl<T> Foo for T where NoData<T>: Foo { | ^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) - = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` +note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:8:9 + | +LL | impl<T> Foo for T where NoData<T>: Foo { + | ^^^ ^ = note: 127 redundant requirements hidden = note: required because of the requirements on the impl of `Foo` for `NoData<T>` @@ -30,8 +34,16 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz { | ^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) - = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` +note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:28:9 + | +LL | impl<T> Bar for T where EvenLessData<T>: Baz { + | ^^^ ^ +note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:36:9 + | +LL | impl<T> Baz for T where AlmostNoData<T>: Bar { + | ^^^ ^ = note: 126 redundant requirements hidden = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>` @@ -45,8 +57,16 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar { | ^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) - = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` +note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:36:9 + | +LL | impl<T> Baz for T where AlmostNoData<T>: Bar { + | ^^^ ^ +note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:28:9 + | +LL | impl<T> Bar for T where EvenLessData<T>: Baz { + | ^^^ ^ = note: 126 redundant requirements hidden = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>` @@ -60,7 +80,11 @@ LL | impl<T> Foo for T where NoData<T>: Foo { | ^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) - = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` +note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:8:9 + | +LL | impl<T> Foo for T where NoData<T>: Foo { + | ^^^ ^ = note: 127 redundant requirements hidden = note: required because of the requirements on the impl of `Foo` for `NoData<T>` @@ -74,8 +98,16 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz { | ^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) - = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` +note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:28:9 + | +LL | impl<T> Bar for T where EvenLessData<T>: Baz { + | ^^^ ^ +note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:36:9 + | +LL | impl<T> Baz for T where AlmostNoData<T>: Bar { + | ^^^ ^ = note: 126 redundant requirements hidden = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>` @@ -89,8 +121,16 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar { | ^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) - = note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` +note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:36:9 + | +LL | impl<T> Baz for T where AlmostNoData<T>: Bar { + | ^^^ ^ +note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-20413.rs:28:9 + | +LL | impl<T> Bar for T where EvenLessData<T>: Baz { + | ^^^ ^ = note: 126 redundant requirements hidden = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>` diff --git a/src/test/ui/issues/issue-21332.stderr b/src/test/ui/issues/issue-21332.stderr index 35863fbebe..d92966da17 100644 --- a/src/test/ui/issues/issue-21332.stderr +++ b/src/test/ui/issues/issue-21332.stderr @@ -1,8 +1,11 @@ error[E0053]: method `next` has an incompatible type for trait - --> $DIR/issue-21332.rs:5:5 + --> $DIR/issue-21332.rs:5:27 | LL | fn next(&mut self) -> Result<i32, i32> { Ok(7) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found enum `Result` + | ^^^^^^^^^^^^^^^^ + | | + | expected enum `Option`, found enum `Result` + | help: change the output type to match the trait: `Option<i32>` | = note: expected fn pointer `fn(&mut S) -> Option<i32>` found fn pointer `fn(&mut S) -> Result<i32, i32>` diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index c65a97d999..fd3db95469 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -5,7 +5,11 @@ LL | let _: Box<dyn for<'b> Wrap<'b>> = Box::new(Wrapper(process)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator | = help: the trait `Iterator` is not implemented for `<P as Process<'_>>::Item` - = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>` +note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>` + --> $DIR/issue-22872.rs:7:13 + | +LL | impl<'b, P> Wrap<'b> for Wrapper<P> + | ^^^^^^^^ ^^^^^^^^^^ = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` help: consider further restricting the associated type | diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index ce3bffe602..5008a49998 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -5,7 +5,11 @@ LL | type Next = <GetNext<T::Next> as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) - = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` +note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` + --> $DIR/issue-23122-2.rs:8:15 + | +LL | impl<T: Next> Next for GetNext<T> { + | ^^^^ ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26812.rs b/src/test/ui/issues/issue-26812.rs index b2494a91a3..3391ea4b35 100644 --- a/src/test/ui/issues/issue-26812.rs +++ b/src/test/ui/issues/issue-26812.rs @@ -1,6 +1,6 @@ #![feature(default_type_parameter_fallback)] fn avg<T=T::Item>(_: T) {} -//~^ ERROR type parameters with a default cannot use forward declared identifiers +//~^ ERROR generic parameters with a default cannot use forward declared identifiers fn main() {} diff --git a/src/test/ui/issues/issue-26812.stderr b/src/test/ui/issues/issue-26812.stderr index 8d507a7ea0..fd1bbb9c56 100644 --- a/src/test/ui/issues/issue-26812.stderr +++ b/src/test/ui/issues/issue-26812.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/issue-26812.rs:3:10 | LL | fn avg<T=T::Item>(_: T) {} - | ^^^^^^^ defaulted type parameters cannot be forward declared + | ^^^^^^^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/issues/issue-27060-2.stderr index c4faecbdf2..5dbcc96e87 100644 --- a/src/test/ui/issues/issue-27060-2.stderr +++ b/src/test/ui/issues/issue-27060-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/issue-27060-2.rs:3:11 | LL | pub struct Bad<T: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | data: T, | ^ doesn't have a size known at compile-time | diff --git a/src/test/ui/issues/issue-27060-rpass.rs b/src/test/ui/issues/issue-27060-rpass.rs index b20d614b30..d9159f6669 100644 --- a/src/test/ui/issues/issue-27060-rpass.rs +++ b/src/test/ui/issues/issue-27060-rpass.rs @@ -8,14 +8,12 @@ pub struct Good { } // kill this test when that turns to a hard error -#[allow(safe_packed_borrows)] +#[allow(unaligned_references)] fn main() { let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] }; - unsafe { - let _ = &good.data; // ok - let _ = &good.data2[0]; // ok - } + let _ = &good.data; // ok + let _ = &good.data2[0]; // ok let _ = &good.data; let _ = &good.data2[0]; diff --git a/src/test/ui/issues/issue-27060.rs b/src/test/ui/issues/issue-27060.rs index 78f2022ed3..5317a61671 100644 --- a/src/test/ui/issues/issue-27060.rs +++ b/src/test/ui/issues/issue-27060.rs @@ -5,7 +5,7 @@ pub struct Good { aligned: [u8; 32], } -#[deny(safe_packed_borrows)] +#[deny(unaligned_references)] fn main() { let good = Good { data: &0, @@ -13,14 +13,14 @@ fn main() { aligned: [0; 32] }; - unsafe { - let _ = &good.data; // ok - let _ = &good.data2[0]; // ok - } + 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 borrow of packed field is unsafe + let _ = &good.data; //~ ERROR reference to packed field //~| hard error - let _ = &good.data2[0]; //~ ERROR borrow of packed field is unsafe + 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 diff --git a/src/test/ui/issues/issue-27060.stderr b/src/test/ui/issues/issue-27060.stderr index d14ae4d41d..09297884ed 100644 --- a/src/test/ui/issues/issue-27060.stderr +++ b/src/test/ui/issues/issue-27060.stderr @@ -1,5 +1,5 @@ -error: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-27060.rs:21:13 +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:16:13 | LL | let _ = &good.data; | ^^^^^^^^^^ @@ -7,21 +7,41 @@ LL | let _ = &good.data; note: the lint level is defined here --> $DIR/issue-27060.rs:8:8 | -LL | #[deny(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ +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 #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: 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: borrow of packed field is unsafe and requires unsafe function or block (error E0133) +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 #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: 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 2 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr index e044352e95..b3bc946292 100644 --- a/src/test/ui/issues/issue-2823.stderr +++ b/src/test/ui/issues/issue-2823.stderr @@ -6,14 +6,6 @@ LL | struct C { ... LL | let _d = c.clone(); | ^^^^^ method not found in `C` - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<C>` here - | the method is available for `Rc<C>` here | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-28568.stderr b/src/test/ui/issues/issue-28568.stderr index 7729b9d240..be3f7c6278 100644 --- a/src/test/ui/issues/issue-28568.stderr +++ b/src/test/ui/issues/issue-28568.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `MyStruct`: +error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `MyStruct` --> $DIR/issue-28568.rs:7:1 | LL | impl Drop for MyStruct { diff --git a/src/test/ui/issues/issue-3214.rs b/src/test/ui/issues/issue-3214.rs index 9bb164f1dd..ccfaf23b4b 100644 --- a/src/test/ui/issues/issue-3214.rs +++ b/src/test/ui/issues/issue-3214.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - fn foo<T>() { struct Foo { x: T, //~ ERROR can't use generic parameters from outer function diff --git a/src/test/ui/issues/issue-3214.stderr b/src/test/ui/issues/issue-3214.stderr index c2268924bc..0da095b7fd 100644 --- a/src/test/ui/issues/issue-3214.stderr +++ b/src/test/ui/issues/issue-3214.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer function - --> $DIR/issue-3214.rs:5:12 + --> $DIR/issue-3214.rs:3:12 | LL | fn foo<T>() { | --- - type parameter from outer function @@ -10,7 +10,7 @@ LL | x: T, | ^ use of generic parameter from outer function error[E0107]: this struct takes 0 type arguments but 1 type argument was supplied - --> $DIR/issue-3214.rs:8:22 + --> $DIR/issue-3214.rs:6:22 | LL | impl<T> Drop for Foo<T> { | ^^^--- help: remove these generics @@ -18,13 +18,13 @@ LL | impl<T> Drop for Foo<T> { | expected 0 type arguments | note: struct defined here, with 0 type parameters - --> $DIR/issue-3214.rs:4:12 + --> $DIR/issue-3214.rs:2:12 | LL | struct Foo { | ^^^ error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-3214.rs:8:10 + --> $DIR/issue-3214.rs:6:10 | LL | impl<T> Drop for Foo<T> { | ^ unconstrained type parameter diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index e91dae08b3..043658c950 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, --> $DIR/issue-33941.rs:4:14 | LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple | - = note: expected tuple `(&_, &_)` - found reference `&_` + = 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 because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` = note: required by `into_iter` @@ -23,10 +23,10 @@ error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, --> $DIR/issue-33941.rs:4:14 | LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple | - = note: expected tuple `(&_, &_)` - found reference `&_` + = 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` diff --git a/src/test/ui/issues/issue-35869.stderr b/src/test/ui/issues/issue-35869.stderr index f80561bf6b..71b2a9df09 100644 --- a/src/test/ui/issues/issue-35869.stderr +++ b/src/test/ui/issues/issue-35869.stderr @@ -5,7 +5,10 @@ LL | fn foo(_: fn(u8) -> ()); | ------------ type in trait ... LL | fn foo(_: fn(u16) -> ()) {} - | ^^^^^^^^^^^^^ expected `u8`, found `u16` + | ^^^^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `fn(u8)` | = note: expected fn pointer `fn(fn(u8))` found fn pointer `fn(fn(u16))` @@ -17,7 +20,10 @@ LL | fn bar(_: Option<u8>); | ---------- type in trait ... LL | fn bar(_: Option<u16>) {} - | ^^^^^^^^^^^ expected `u8`, found `u16` + | ^^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `Option<u8>` | = note: expected fn pointer `fn(Option<u8>)` found fn pointer `fn(Option<u16>)` @@ -29,7 +35,10 @@ LL | fn baz(_: (u8, u16)); | --------- type in trait ... LL | fn baz(_: (u16, u16)) {} - | ^^^^^^^^^^ expected `u8`, found `u16` + | ^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `(u8, u16)` | = note: expected fn pointer `fn((u8, _))` found fn pointer `fn((u16, _))` @@ -41,7 +50,10 @@ LL | fn qux() -> u8; | -- type in trait ... LL | fn qux() -> u16 { 5u16 } - | ^^^ expected `u8`, found `u16` + | ^^^ + | | + | expected `u8`, found `u16` + | help: change the output type to match the trait: `u8` | = note: expected fn pointer `fn() -> u8` found fn pointer `fn() -> u16` diff --git a/src/test/ui/issues/issue-38821.stderr b/src/test/ui/issues/issue-38821.stderr index e355094261..296efab751 100644 --- a/src/test/ui/issues/issue-38821.stderr +++ b/src/test/ui/issues/issue-38821.stderr @@ -4,7 +4,11 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat LL | #[derive(Debug, Copy, Clone)] | ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType` | - = note: required because of the requirements on the impl of `IntoNullable` for `<Col as Expression>::SqlType` +note: required because of the requirements on the impl of `IntoNullable` for `<Col as Expression>::SqlType` + --> $DIR/issue-38821.rs:9:18 + | +LL | impl<T: NotNull> IntoNullable for T { + | ^^^^^^^^^^^^ ^ = note: this error originates in a derive macro (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-39970.stderr b/src/test/ui/issues/issue-39970.stderr index 6f342b459c..2a0693a581 100644 --- a/src/test/ui/issues/issue-39970.stderr +++ b/src/test/ui/issues/issue-39970.stderr @@ -5,9 +5,13 @@ LL | fn visit() {} | ---------- required by `Visit::visit` ... LL | <() as Visit>::visit(); - | ^^^^^^^^^^^^^^^^^^^^ expected `&()`, found `()` + | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&()` | - = note: required because of the requirements on the impl of `Visit` for `()` +note: required because of the requirements on the impl of `Visit` for `()` + --> $DIR/issue-39970.rs:13:6 + | +LL | impl Visit for () where + | ^^^^^ ^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr index 95cacbc32a..38c3af935c 100644 --- a/src/test/ui/issues/issue-40827.stderr +++ b/src/test/ui/issues/issue-40827.stderr @@ -8,9 +8,17 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | ^ `Rc<Foo>` cannot be shared between threads safely | = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>` - = note: required because it appears within the type `Bar` +note: required because it appears within the type `Bar` + --> $DIR/issue-40827.rs:6:6 + | +LL | enum Bar { + | ^^^ = note: required because of the requirements on the impl of `Send` for `Arc<Bar>` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/issue-40827.rs:4:8 + | +LL | struct Foo(Arc<Bar>); + | ^^^ error[E0277]: `Rc<Foo>` cannot be sent between threads safely --> $DIR/issue-40827.rs:14:5 @@ -22,9 +30,17 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | ^ `Rc<Foo>` cannot be sent between threads safely | = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>` - = note: required because it appears within the type `Bar` +note: required because it appears within the type `Bar` + --> $DIR/issue-40827.rs:6:6 + | +LL | enum Bar { + | ^^^ = note: required because of the requirements on the impl of `Send` for `Arc<Bar>` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/issue-40827.rs:4:8 + | +LL | struct Foo(Arc<Bar>); + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index cde285f73d..11d77857d6 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_, _>`: +error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_, _>` --> $DIR/issue-41974.rs:7:1 | LL | impl<T> Drop for T where T: A { diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr index 3f63cb8e78..3a3767c349 100644 --- a/src/test/ui/issues/issue-43189.stderr +++ b/src/test/ui/issues/issue-43189.stderr @@ -3,6 +3,11 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope | LL | ().a(); | ^ method not found in `()` + | + ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8 + | +LL | fn a(&self) {} + | - the method is available for `()` here | = 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: diff --git a/src/test/ui/issues/issue-43355.stderr b/src/test/ui/issues/issue-43355.stderr index 75c69e5b3e..23d8ed1848 100644 --- a/src/test/ui/issues/issue-43355.stderr +++ b/src/test/ui/issues/issue-43355.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: +error[E0119]: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A` --> $DIR/issue-43355.rs:13:1 | LL | impl<X, T> Trait1<X> for T where T: Trait2<X> { diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/issues/issue-43784-supertrait.stderr index c73536ba97..45a2350ddf 100644 --- a/src/test/ui/issues/issue-43784-supertrait.stderr +++ b/src/test/ui/issues/issue-43784-supertrait.stderr @@ -9,8 +9,8 @@ LL | impl<T> Complete for T {} | help: consider restricting type parameter `T` | -LL | impl<T: Copy> Complete for T {} - | ^^^^^^ +LL | impl<T: std::marker::Copy> Complete for T {} + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-44023.rs b/src/test/ui/issues/issue-44023.rs index 4c38ddfcdf..e4320b7dac 100644 --- a/src/test/ui/issues/issue-44023.rs +++ b/src/test/ui/issues/issue-44023.rs @@ -1,5 +1,3 @@ -#![feature(non_ascii_idents)] - pub fn main () {} fn საჭმელად_გემრიელი_სადილი ( ) -> isize { //~ ERROR mismatched types diff --git a/src/test/ui/issues/issue-44023.stderr b/src/test/ui/issues/issue-44023.stderr index fc54e7c62b..9e97012416 100644 --- a/src/test/ui/issues/issue-44023.stderr +++ b/src/test/ui/issues/issue-44023.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-44023.rs:5:36 + --> $DIR/issue-44023.rs:3:36 | LL | fn საჭმელად_გემრიელი_სადილი ( ) -> isize { | ------------------------ ^^^^^ expected `isize`, found `()` diff --git a/src/test/ui/issues/issue-45157.rs b/src/test/ui/issues/issue-45157.rs index bd18784289..8d2bf22a03 100644 --- a/src/test/ui/issues/issue-45157.rs +++ b/src/test/ui/issues/issue-45157.rs @@ -1,6 +1,5 @@ #![allow(unused)] -// ignore-tidy-linelength #[derive(Clone, Copy, Default)] struct S { diff --git a/src/test/ui/issues/issue-45157.stderr b/src/test/ui/issues/issue-45157.stderr index 1b879e0b48..57fd8d49c8 100644 --- a/src/test/ui/issues/issue-45157.stderr +++ b/src/test/ui/issues/issue-45157.stderr @@ -1,5 +1,5 @@ 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:28:20 + --> $DIR/issue-45157.rs:27:20 | LL | let mref = &mut u.s.a; | ---------- mutable borrow occurs here (via `u.s.a`) diff --git a/src/test/ui/issues/issue-47725.rs b/src/test/ui/issues/issue-47725.rs index 21108da500..9ec55be587 100644 --- a/src/test/ui/issues/issue-47725.rs +++ b/src/test/ui/issues/issue-47725.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![warn(unused_attributes)] //~ NOTE lint level is defined here #[link_name = "foo"] diff --git a/src/test/ui/issues/issue-47725.stderr b/src/test/ui/issues/issue-47725.stderr index b1e8d3292e..c7a9bfe317 100644 --- a/src/test/ui/issues/issue-47725.stderr +++ b/src/test/ui/issues/issue-47725.stderr @@ -1,11 +1,11 @@ error: malformed `link_name` attribute input - --> $DIR/issue-47725.rs:18:1 + --> $DIR/issue-47725.rs:17:1 | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` warning: attribute should be applied to a foreign function or static - --> $DIR/issue-47725.rs:4:1 + --> $DIR/issue-47725.rs:3:1 | LL | #[link_name = "foo"] | ^^^^^^^^^^^^^^^^^^^^ @@ -14,14 +14,14 @@ LL | struct Foo; | ----------- not a foreign function or static | note: the lint level is defined here - --> $DIR/issue-47725.rs:2:9 + --> $DIR/issue-47725.rs:1:9 | LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-47725.rs:9:1 + --> $DIR/issue-47725.rs:8:1 | LL | #[link_name = "foobar"] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,13 +33,13 @@ LL | | } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! help: try `#[link(name = "foobar")]` instead - --> $DIR/issue-47725.rs:9:1 + --> $DIR/issue-47725.rs:8:1 | LL | #[link_name = "foobar"] | ^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a foreign function or static - --> $DIR/issue-47725.rs:18:1 + --> $DIR/issue-47725.rs:17:1 | LL | #[link_name] | ^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | | } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! help: try `#[link(name = "...")]` instead - --> $DIR/issue-47725.rs:18:1 + --> $DIR/issue-47725.rs:17:1 | LL | #[link_name] | ^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-48728.stderr b/src/test/ui/issues/issue-48728.stderr index a0698c2079..ca2e234cee 100644 --- a/src/test/ui/issues/issue-48728.stderr +++ b/src/test/ui/issues/issue-48728.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Node<[_]>`: +error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Node<[_]>` --> $DIR/issue-48728.rs:4:10 | LL | #[derive(Clone)] diff --git a/src/test/ui/issues/issue-53251.rs b/src/test/ui/issues/issue-53251.rs index 309b9800b7..937271d42f 100644 --- a/src/test/ui/issues/issue-53251.rs +++ b/src/test/ui/issues/issue-53251.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - struct S; impl S { diff --git a/src/test/ui/issues/issue-53251.stderr b/src/test/ui/issues/issue-53251.stderr index 5d1a6d4a52..1676c508a4 100644 --- a/src/test/ui/issues/issue-53251.stderr +++ b/src/test/ui/issues/issue-53251.stderr @@ -1,5 +1,5 @@ error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied - --> $DIR/issue-53251.rs:13:20 + --> $DIR/issue-53251.rs:11:20 | LL | S::f::<i64>(); | ^------- help: remove these generics @@ -10,14 +10,14 @@ LL | impl_add!(a b); | --------------- in this macro invocation | note: associated function defined here, with 0 type parameters - --> $DIR/issue-53251.rs:6:8 + --> $DIR/issue-53251.rs:4:8 | LL | fn f() {} | ^ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied - --> $DIR/issue-53251.rs:13:20 + --> $DIR/issue-53251.rs:11:20 | LL | S::f::<i64>(); | ^------- help: remove these generics @@ -28,7 +28,7 @@ LL | impl_add!(a b); | --------------- in this macro invocation | note: associated function defined here, with 0 type parameters - --> $DIR/issue-53251.rs:6:8 + --> $DIR/issue-53251.rs:4:8 | LL | fn f() {} | ^ diff --git a/src/test/ui/issues/issue-54044.rs b/src/test/ui/issues/issue-54044.rs index 3f0b8bc5e3..809ea7a87d 100644 --- a/src/test/ui/issues/issue-54044.rs +++ b/src/test/ui/issues/issue-54044.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![deny(unused_attributes)] //~ NOTE lint level is defined here #[cold] diff --git a/src/test/ui/issues/issue-54044.stderr b/src/test/ui/issues/issue-54044.stderr index a13e84bbee..0200a6a629 100644 --- a/src/test/ui/issues/issue-54044.stderr +++ b/src/test/ui/issues/issue-54044.stderr @@ -1,5 +1,5 @@ error: attribute should be applied to a function - --> $DIR/issue-54044.rs:4:1 + --> $DIR/issue-54044.rs:3:1 | LL | #[cold] | ^^^^^^^ @@ -8,14 +8,14 @@ LL | struct Foo; | ----------- not a function | note: the lint level is defined here - --> $DIR/issue-54044.rs:2:9 + --> $DIR/issue-54044.rs:1:9 | LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: attribute should be applied to a function - --> $DIR/issue-54044.rs:10:5 + --> $DIR/issue-54044.rs:9:5 | LL | #[cold] | ^^^^^^^ diff --git a/src/test/ui/issues/issue-56175.stderr b/src/test/ui/issues/issue-56175.stderr index ee3f609f47..e6b0fffce6 100644 --- a/src/test/ui/issues/issue-56175.stderr +++ b/src/test/ui/issues/issue-56175.stderr @@ -3,6 +3,11 @@ error[E0599]: no method named `trait_method` found for struct `FooStruct` in the | LL | reexported_trait::FooStruct.trait_method(); | ^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:3:12 + | +LL | fn trait_method(&self) { + | ------------ the method is available for `FooStruct` here | = 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: @@ -15,6 +20,11 @@ error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in t | LL | reexported_trait::FooStruct.trait_method_b(); | ^^^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:7:12 + | +LL | fn trait_method_b(&self) { + | -------------- the method is available for `FooStruct` here | = 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: diff --git a/src/test/ui/issues/issue-5883.rs b/src/test/ui/issues/issue-5883.rs index 0de5350239..82866b3555 100644 --- a/src/test/ui/issues/issue-5883.rs +++ b/src/test/ui/issues/issue-5883.rs @@ -4,9 +4,9 @@ struct Struct { r: dyn A + 'static } -fn new_struct(r: dyn A + 'static) - -> Struct { //~^ ERROR the size for values of type - //~^ ERROR the size for values of type +fn new_struct( + r: dyn A + 'static //~ ERROR the size for values of type +) -> Struct { //~ ERROR the size for values of type Struct { r: r } } diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr index 5798733e04..de598a70ee 100644 --- a/src/test/ui/issues/issue-5883.stderr +++ b/src/test/ui/issues/issue-5883.stderr @@ -1,27 +1,30 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:7:15 + --> $DIR/issue-5883.rs:8:5 | -LL | fn new_struct(r: dyn A + 'static) - | ^ doesn't have a size known at compile-time +LL | r: dyn A + 'static + | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn A + 'static)` = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn new_struct(&r: dyn A + 'static) - | ^ +LL | r: &dyn A + 'static + | ^ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:8:8 + --> $DIR/issue-5883.rs:9:6 | -LL | -> Struct { - | ^^^^^^ doesn't have a size known at compile-time -LL | +LL | ) -> Struct { + | ^^^^^^ doesn't have a size known at compile-time LL | Struct { r: r } | --------------- this returned value is of type `Struct` | = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` - = note: required because it appears within the type `Struct` +note: required because it appears within the type `Struct` + --> $DIR/issue-5883.rs:3:8 + | +LL | struct Struct { + | ^^^^^^ = note: the return type of a function must have a statically known size error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-60622.rs b/src/test/ui/issues/issue-60622.rs index 1d9bd2dd2d..1018c88ae5 100644 --- a/src/test/ui/issues/issue-60622.rs +++ b/src/test/ui/issues/issue-60622.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![deny(warnings)] struct Borked {} diff --git a/src/test/ui/issues/issue-60622.stderr b/src/test/ui/issues/issue-60622.stderr index 47f2f181f2..f970a63e4b 100644 --- a/src/test/ui/issues/issue-60622.stderr +++ b/src/test/ui/issues/issue-60622.stderr @@ -1,5 +1,5 @@ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/issue-60622.rs:12:11 + --> $DIR/issue-60622.rs:10:11 | LL | fn a(&self) {} | - the late bound lifetime parameter is introduced here @@ -8,7 +8,7 @@ LL | b.a::<'_, T>(); | ^^ | note: the lint level is defined here - --> $DIR/issue-60622.rs:3:9 + --> $DIR/issue-60622.rs:1:9 | LL | #![deny(warnings)] | ^^^^^^^^ @@ -17,7 +17,7 @@ LL | #![deny(warnings)] = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868> error[E0107]: this associated function takes 0 type arguments but 1 type argument was supplied - --> $DIR/issue-60622.rs:12:7 + --> $DIR/issue-60622.rs:10:7 | LL | b.a::<'_, T>(); | ^ --- help: remove this type argument @@ -25,7 +25,7 @@ LL | b.a::<'_, T>(); | expected 0 type arguments | note: associated function defined here, with 0 type parameters - --> $DIR/issue-60622.rs:8:8 + --> $DIR/issue-60622.rs:6:8 | LL | fn a(&self) {} | ^ diff --git a/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs b/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs index 6e030f1cc4..e04dec24e4 100644 --- a/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs +++ b/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs @@ -1,5 +1,6 @@ // run-fail // compile-flags: -C opt-level=3 +// min-llvm-version: 11.0 // error-pattern: index out of bounds: the len is 0 but the index is 16777216 // ignore-wasm no panic or subprocess support // ignore-emscripten no panic or subprocess support diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr index 48c71d76af..4dd6b4bbb6 100644 --- a/src/test/ui/issues/issue-69725.stderr +++ b/src/test/ui/issues/issue-69725.stderr @@ -8,14 +8,6 @@ LL | let _ = Struct::<A>::new().clone(); | LL | pub struct Struct<A>(A); | ------------------------ doesn't satisfy `Struct<A>: Clone` - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Struct<A>>` here - | the method is available for `Rc<Struct<A>>` here | = note: the following trait bounds were not satisfied: `A: Clone` diff --git a/src/test/ui/issues/issue-7013.stderr b/src/test/ui/issues/issue-7013.stderr index 5f3156a540..98ed67507b 100644 --- a/src/test/ui/issues/issue-7013.stderr +++ b/src/test/ui/issues/issue-7013.stderr @@ -6,7 +6,11 @@ LL | let a = A {v: box B{v: None} as Box<dyn Foo + Send>}; | = help: within `B`, the trait `Send` is not implemented for `Rc<RefCell<A>>` = note: required because it appears within the type `Option<Rc<RefCell<A>>>` - = note: required because it appears within the type `B` +note: required because it appears within the type `B` + --> $DIR/issue-7013.rs:10:8 + | +LL | struct B { + | ^ = note: required for the cast to the object type `dyn Foo + Send` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-78720.rs b/src/test/ui/issues/issue-78720.rs index 57615d1a20..4cdb9f4911 100644 --- a/src/test/ui/issues/issue-78720.rs +++ b/src/test/ui/issues/issue-78720.rs @@ -4,7 +4,7 @@ fn server() -> impl { } trait FilterBase2 { - fn map2<F>(self, F) -> Map2<F> {} + fn map2<F>(self, f: F) -> Map2<F> {} //~^ ERROR mismatched types //~^^ ERROR the size for values of type `Self` cannot be known at compilation time } diff --git a/src/test/ui/issues/issue-78720.stderr b/src/test/ui/issues/issue-78720.stderr index a3a14e34ac..ee15826d18 100644 --- a/src/test/ui/issues/issue-78720.stderr +++ b/src/test/ui/issues/issue-78720.stderr @@ -25,10 +25,10 @@ LL | struct Map2<Segment2, F> { | ^^^ error[E0308]: mismatched types - --> $DIR/issue-78720.rs:7:36 + --> $DIR/issue-78720.rs:7:39 | -LL | fn map2<F>(self, F) -> Map2<F> {} - | ^^ expected struct `Map2`, found `()` +LL | fn map2<F>(self, f: F) -> Map2<F> {} + | ^^ expected struct `Map2`, found `()` | = note: expected struct `Map2<F>` found unit type `()` @@ -36,17 +36,17 @@ LL | fn map2<F>(self, F) -> Map2<F> {} error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-78720.rs:7:16 | -LL | fn map2<F>(self, F) -> Map2<F> {} +LL | fn map2<F>(self, f: F) -> Map2<F> {} | ^^^^ doesn't have a size known at compile-time | = help: unsized fn params are gated as an unstable feature help: consider further restricting `Self` | -LL | fn map2<F>(self, F) -> Map2<F> where Self: Sized {} - | ^^^^^^^^^^^^^^^^^ +LL | fn map2<F>(self, f: F) -> Map2<F> where Self: Sized {} + | ^^^^^^^^^^^^^^^^^ help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn map2<F>(&self, F) -> Map2<F> {} +LL | fn map2<F>(&self, f: F) -> Map2<F> {} | ^ error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-82833-slice-miscompile.rs b/src/test/ui/issues/issue-82833-slice-miscompile.rs index b14e5f6fb1..8cf6a3137e 100644 --- a/src/test/ui/issues/issue-82833-slice-miscompile.rs +++ b/src/test/ui/issues/issue-82833-slice-miscompile.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Copt-level=0 -Cdebuginfo=2 -// ignore-tidy-linelength // Make sure LLVM does not miscompile this. diff --git a/src/test/ui/issues/issue-83048.rs b/src/test/ui/issues/issue-83048.rs new file mode 100644 index 0000000000..520ae97439 --- /dev/null +++ b/src/test/ui/issues/issue-83048.rs @@ -0,0 +1,5 @@ +// compile-flags: -Z unpretty=thir-tree + +pub fn main() { + break; //~ ERROR: `break` outside of a loop [E0268] +} diff --git a/src/test/ui/issues/issue-83048.stderr b/src/test/ui/issues/issue-83048.stderr new file mode 100644 index 0000000000..62d67d7584 --- /dev/null +++ b/src/test/ui/issues/issue-83048.stderr @@ -0,0 +1,9 @@ +error[E0268]: `break` outside of a loop + --> $DIR/issue-83048.rs:4:5 + | +LL | break; + | ^^^^^ cannot `break` outside of a loop + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0268`. diff --git a/src/test/ui/issues/issue-83924.fixed b/src/test/ui/issues/issue-83924.fixed new file mode 100644 index 0000000000..aa40da12b8 --- /dev/null +++ b/src/test/ui/issues/issue-83924.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +fn main() { + let mut values = vec![10, 11, 12]; + let v = &mut values; + + let mut max = 0; + + for n in &mut *v { + max = std::cmp::max(max, *n); + } + + println!("max is {}", max); + println!("Converting to percentages of maximum value..."); + for n in v { + //~^ ERROR: use of moved value: `v` [E0382] + *n = 100 * (*n) / max; + } + println!("values: {:#?}", values); +} diff --git a/src/test/ui/issues/issue-83924.rs b/src/test/ui/issues/issue-83924.rs new file mode 100644 index 0000000000..22b80fe2f3 --- /dev/null +++ b/src/test/ui/issues/issue-83924.rs @@ -0,0 +1,20 @@ +// run-rustfix + +fn main() { + let mut values = vec![10, 11, 12]; + let v = &mut values; + + let mut max = 0; + + for n in v { + max = std::cmp::max(max, *n); + } + + println!("max is {}", max); + println!("Converting to percentages of maximum value..."); + for n in v { + //~^ ERROR: use of moved value: `v` [E0382] + *n = 100 * (*n) / max; + } + println!("values: {:#?}", values); +} diff --git a/src/test/ui/issues/issue-83924.stderr b/src/test/ui/issues/issue-83924.stderr new file mode 100644 index 0000000000..682bc323cb --- /dev/null +++ b/src/test/ui/issues/issue-83924.stderr @@ -0,0 +1,25 @@ +error[E0382]: use of moved value: `v` + --> $DIR/issue-83924.rs:15:14 + | +LL | let v = &mut values; + | - move occurs because `v` has type `&mut Vec<i32>`, which does not implement the `Copy` trait +... +LL | for n in v { + | - `v` moved due to this implicit call to `.into_iter()` +... +LL | for n in v { + | ^ value used here after move + | +note: this function takes ownership of the receiver `self`, which moves `v` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^ +help: consider creating a fresh reborrow of `v` here + | +LL | for n in &mut *v { + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/iterators/array-of-ranges.rs b/src/test/ui/iterators/array-of-ranges.rs index d2dfc7ec32..037540a3e8 100644 --- a/src/test/ui/iterators/array-of-ranges.rs +++ b/src/test/ui/iterators/array-of-ranges.rs @@ -1,23 +1,16 @@ +// check-pass + fn main() { for _ in [0..1] {} -//~^ ERROR is not an iterator for _ in [0..=1] {} -//~^ ERROR is not an iterator for _ in [0..] {} -//~^ ERROR is not an iterator for _ in [..1] {} -//~^ ERROR is not an iterator for _ in [..=1] {} -//~^ ERROR is not an iterator let start = 0; let end = 0; for _ in [start..end] {} -//~^ ERROR is not an iterator let array_of_range = [start..end]; for _ in array_of_range {} -//~^ ERROR is not an iterator for _ in [0..1, 2..3] {} -//~^ ERROR is not an iterator for _ in [0..=1] {} -//~^ ERROR is not an iterator } diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr deleted file mode 100644 index 601983a615..0000000000 --- a/src/test/ui/iterators/array-of-ranges.stderr +++ /dev/null @@ -1,102 +0,0 @@ -error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:2:14 - | -LL | for _ in [0..1] {} - | ^^^^^^ if you meant to iterate between two values, remove the square brackets - | - = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` - = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` - = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` - = note: required by `into_iter` - -error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:4:14 - | -LL | for _ in [0..=1] {} - | ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` - = note: required by `into_iter` - -error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:6:14 - | -LL | for _ in [0..] {} - | ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]` - = note: required by `into_iter` - -error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:8:14 - | -LL | for _ in [..1] {} - | ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]` - = note: required by `into_iter` - -error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:10:14 - | -LL | for _ in [..=1] {} - | ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]` - = note: required by `into_iter` - -error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:14:14 - | -LL | for _ in [start..end] {} - | ^^^^^^^^^^^^ if you meant to iterate between two values, remove the square brackets - | - = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` - = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` - = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` - = note: required by `into_iter` - -error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:17:14 - | -LL | for _ in array_of_range {} - | ^^^^^^^^^^^^^^ if you meant to iterate between two values, remove the square brackets - | - = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` - = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` - = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` - = note: required by `into_iter` - -error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator - --> $DIR/array-of-ranges.rs:19:14 - | -LL | for _ in [0..1, 2..3] {} - | ^^^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]` - = note: required by `into_iter` - -error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator - --> $DIR/array-of-ranges.rs:21:14 - | -LL | for _ in [0..=1] {} - | ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` - = note: required by `into_iter` - -error: aborting due to 9 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/iterators/array.rs b/src/test/ui/iterators/array.rs index 33c84f6fa3..5985c74e11 100644 --- a/src/test/ui/iterators/array.rs +++ b/src/test/ui/iterators/array.rs @@ -1,9 +1,8 @@ +// check-pass + fn main() { for _ in [1, 2] {} -//~^ ERROR is not an iterator let x = [1, 2]; for _ in x {} -//~^ ERROR is not an iterator for _ in [1.0, 2.0] {} -//~^ ERROR is not an iterator } diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr deleted file mode 100644 index 68c6de5493..0000000000 --- a/src/test/ui/iterators/array.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0277]: `[{integer}; 2]` is not an iterator - --> $DIR/array.rs:2:14 - | -LL | for _ in [1, 2] {} - | ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` - = note: required by `into_iter` - -error[E0277]: `[{integer}; 2]` is not an iterator - --> $DIR/array.rs:5:14 - | -LL | for _ in x {} - | ^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` - = note: required by `into_iter` - -error[E0277]: `[{float}; 2]` is not an iterator - --> $DIR/array.rs:7:14 - | -LL | for _ in [1.0, 2.0] {} - | ^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it - | - = help: the trait `Iterator` is not implemented for `[{float}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` - = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]` - = note: required by `into_iter` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.rs b/src/test/ui/iterators/into-iter-on-arrays-2018.rs new file mode 100644 index 0000000000..5661397b3c --- /dev/null +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.rs @@ -0,0 +1,39 @@ +// check-pass +// edition:2018 + +use std::array::IntoIter; +use std::ops::Deref; +use std::rc::Rc; +use std::slice::Iter; + +fn main() { + let array = [0; 10]; + + // 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 + + 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 + + // The `array_into_iter` lint doesn't cover other wrappers that deref to an array. + let _: Iter<'_, i32> = Rc::new(array).into_iter(); + let _: Iter<'_, i32> = Array(array).into_iter(); + + // But you can always use the trait method explicitly as an array. + let _: IntoIter<i32, 10> = IntoIterator::into_iter(array); +} + +/// User type that dereferences to an array. +struct Array([i32; 10]); + +impl Deref for Array { + type Target = [i32; 10]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr new file mode 100644 index 0000000000..b43338382f --- /dev/null +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr @@ -0,0 +1,42 @@ +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 + | +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! + = 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-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! + = 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 + | +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! + = 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-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! + = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145> + diff --git a/src/test/ui/iterators/into-iter-on-arrays-2021.rs b/src/test/ui/iterators/into-iter-on-arrays-2021.rs new file mode 100644 index 0000000000..ec54ed0051 --- /dev/null +++ b/src/test/ui/iterators/into-iter-on-arrays-2021.rs @@ -0,0 +1,33 @@ +// check-pass +// edition:2021 +// compile-flags: -Zunstable-options + +use std::array::IntoIter; +use std::ops::Deref; +use std::rc::Rc; + +fn main() { + let array = [0; 10]; + + // In 2021, the method dispatches to `IntoIterator for [T; N]`. + let _: IntoIter<i32, 10> = array.into_iter(); + let _: IntoIter<i32, 10> = Box::new(array).into_iter(); + + // The `array_into_iter` lint doesn't cover other wrappers that deref to an array. + let _: IntoIter<i32, 10> = Rc::new(array).into_iter(); + let _: IntoIter<i32, 10> = Array(array).into_iter(); + + // You can always use the trait method explicitly as an array. + let _: IntoIter<i32, 10> = IntoIterator::into_iter(array); +} + +/// User type that dereferences to an array. +struct Array([i32; 10]); + +impl Deref for Array { + type Target = [i32; 10]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr index 4678bafd19..73844329e3 100644 --- a/src/test/ui/iterators/ranges.stderr +++ b/src/test/ui/iterators/ranges.stderr @@ -2,9 +2,10 @@ error[E0277]: `RangeTo<{integer}>` is not an iterator --> $DIR/ranges.rs:2:14 | LL | for _ in ..10 {} - | ^^^^ `RangeTo<{integer}>` is not an iterator + | ^^^^ if you meant to iterate until a value, add a starting value | = 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` @@ -12,9 +13,10 @@ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator --> $DIR/ranges.rs:4:14 | LL | for _ in ..=10 {} - | ^^^^^ `RangeToInclusive<{integer}>` is not an iterator + | ^^^^^ if you meant to iterate until a value (including it), add a starting value | = 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` diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr index 1653006682..1d77bcb753 100644 --- a/src/test/ui/iterators/string.stderr +++ b/src/test/ui/iterators/string.stderr @@ -2,7 +2,7 @@ error[E0277]: `String` is not an iterator --> $DIR/string.rs:2:14 | LL | for _ in "".to_owned() {} - | ^^^^^^^^^^^^^ `String` is not an iterator + | ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `String` = note: required because of the requirements on the impl of `IntoIterator` for `String` diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr index 7e0f6e0b2d..c635ebdbb7 100644 --- a/src/test/ui/kindck/kindck-impl-type-params-2.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr @@ -7,7 +7,11 @@ LL | fn take_param<T:Foo>(foo: &T) { } LL | take_param(&x); | ^^ the trait `Copy` is not implemented for `Box<{integer}>` | - = note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` +note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` + --> $DIR/kindck-impl-type-params-2.rs:6:14 + | +LL | impl<T:Copy> Foo for T { + | ^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr index b01b8258e7..035501009b 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr @@ -4,12 +4,16 @@ error[E0277]: `T` cannot be sent between threads safely LL | let a = &t as &dyn Gettable<T>; | ^^ `T` cannot be sent between threads safely | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn f<T: Send>(val: T) { - | ^^^^^^ +LL | fn f<T: std::marker::Send>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:18:13 @@ -17,12 +21,16 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | let a = &t as &dyn Gettable<T>; | ^^ the trait `Copy` is not implemented for `T` | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn f<T: Copy>(val: T) { - | ^^^^^^ +LL | fn f<T: std::marker::Copy>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:25:31 @@ -30,12 +38,16 @@ error[E0277]: `T` cannot be sent between threads safely LL | let a: &dyn Gettable<T> = &t; | ^^ `T` cannot be sent between threads safely | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn g<T: Send>(val: T) { - | ^^^^^^ +LL | fn g<T: std::marker::Send>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:25:31 @@ -43,12 +55,16 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | let a: &dyn Gettable<T> = &t; | ^^ the trait `Copy` is not implemented for `T` | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn g<T: Copy>(val: T) { - | ^^^^^^ +LL | fn g<T: std::marker::Copy>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:38:13 @@ -56,7 +72,11 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | let a = t as Box<dyn Gettable<String>>; | ^ the trait `Copy` is not implemented for `String` | - = note: required because of the requirements on the impl of `Gettable<String>` for `S<String>` +note: required because of the requirements on the impl of `Gettable<String>` for `S<String>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<String>` error[E0277]: the trait bound `Foo: Copy` is not satisfied @@ -65,7 +85,11 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied LL | let a: Box<dyn Gettable<Foo>> = t; | ^ the trait `Copy` is not implemented for `Foo` | - = note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>` +note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<Foo>` error: aborting due to 6 previous errors diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr index ddf8adf363..241fe367fd 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.stderr @@ -4,12 +4,16 @@ error[E0277]: `T` cannot be sent between threads safely LL | let a = &t as &dyn Gettable<T>; | ^^ `T` cannot be sent between threads safely | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn f<T: Send>(val: T) { - | ^^^^^^ +LL | fn f<T: std::marker::Send>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:18:13 @@ -17,12 +21,16 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | let a = &t as &dyn Gettable<T>; | ^^ the trait `Copy` is not implemented for `T` | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn f<T: Copy>(val: T) { - | ^^^^^^ +LL | fn f<T: std::marker::Copy>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:25:31 @@ -30,12 +38,16 @@ error[E0277]: `T` cannot be sent between threads safely LL | let a: &dyn Gettable<T> = &t; | ^^ `T` cannot be sent between threads safely | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn g<T: Send>(val: T) { - | ^^^^^^ +LL | fn g<T: std::marker::Send>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:25:31 @@ -43,12 +55,16 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | let a: &dyn Gettable<T> = &t; | ^^ the trait `Copy` is not implemented for `T` | - = note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` +note: required because of the requirements on the impl of `Gettable<T>` for `S<T>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<T>` help: consider restricting type parameter `T` | -LL | fn g<T: Copy>(val: T) { - | ^^^^^^ +LL | fn g<T: std::marker::Copy>(val: T) { + | ^^^^^^^^^^^^^^^^^^^ error[E0477]: the type `&'a isize` does not fulfill the required lifetime --> $DIR/kindck-impl-type-params.rs:32:13 @@ -64,7 +80,11 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | let a = t as Box<dyn Gettable<String>>; | ^ the trait `Copy` is not implemented for `String` | - = note: required because of the requirements on the impl of `Gettable<String>` for `S<String>` +note: required because of the requirements on the impl of `Gettable<String>` for `S<String>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<String>` error[E0277]: the trait bound `Foo: Copy` is not satisfied @@ -73,7 +93,11 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied LL | let a: Box<dyn Gettable<Foo>> = t; | ^ the trait `Copy` is not implemented for `Foo` | - = note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>` +note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>` + --> $DIR/kindck-impl-type-params.rs:14:32 + | +LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} + | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<Foo>` error: aborting due to 7 previous errors diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr index 64e56f8c79..86eaca83f2 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -7,7 +7,11 @@ LL | fn take_param<T:Foo>(foo: &T) { } LL | take_param(&x); | ^^ the trait `Copy` is not implemented for `Box<{integer}>` | - = note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` +note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` + --> $DIR/kindck-inherited-copy-bound.rs:14:14 + | +LL | impl<T:Copy> Foo for T { + | ^^^ ^ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/kindck-inherited-copy-bound.rs:28:19 diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr index 57f7551fd4..49c5cd40b5 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -7,7 +7,11 @@ LL | fn take_param<T:Foo>(foo: &T) { } LL | take_param(&x); | ^^ the trait `Copy` is not implemented for `Box<{integer}>` | - = note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` +note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` + --> $DIR/kindck-inherited-copy-bound.rs:14:14 + | +LL | impl<T:Copy> Foo for T { + | ^^^ ^ error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/kindck-inherited-copy-bound.rs:28:13 diff --git a/src/test/ui/kinds-of-primitive-impl.rs b/src/test/ui/kinds-of-primitive-impl.rs index cbd4d7ae90..b045b050d7 100644 --- a/src/test/ui/kinds-of-primitive-impl.rs +++ b/src/test/ui/kinds-of-primitive-impl.rs @@ -1,6 +1,3 @@ -// ignore-tidy-linelength - - impl u8 { //~^ error: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive pub const B: u8 = 0; diff --git a/src/test/ui/kinds-of-primitive-impl.stderr b/src/test/ui/kinds-of-primitive-impl.stderr index d19c85b17f..f1fb295308 100644 --- a/src/test/ui/kinds-of-primitive-impl.stderr +++ b/src/test/ui/kinds-of-primitive-impl.stderr @@ -1,5 +1,5 @@ error[E0390]: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive - --> $DIR/kinds-of-primitive-impl.rs:4:1 + --> $DIR/kinds-of-primitive-impl.rs:1:1 | LL | / impl u8 { LL | | @@ -10,7 +10,7 @@ LL | | } = help: consider using a trait to implement this constant error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive - --> $DIR/kinds-of-primitive-impl.rs:9:1 + --> $DIR/kinds-of-primitive-impl.rs:6:1 | LL | / impl str { LL | | @@ -22,7 +22,7 @@ LL | | } = help: consider using a trait to implement these methods error[E0390]: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive - --> $DIR/kinds-of-primitive-impl.rs:15:1 + --> $DIR/kinds-of-primitive-impl.rs:12:1 | LL | / impl char { LL | | diff --git a/src/test/ui/lifetimes/issue-83737-binders-across-types.rs b/src/test/ui/lifetimes/issue-83737-binders-across-types.rs new file mode 100644 index 0000000000..e130561e46 --- /dev/null +++ b/src/test/ui/lifetimes/issue-83737-binders-across-types.rs @@ -0,0 +1,14 @@ +// build-pass +// compile-flags: --edition 2018 +// compile-flags: --crate-type rlib + +use std::future::Future; + +async fn handle<F>(slf: &F) +where + F: Fn(&()) -> Box<dyn Future<Output = ()> + Unpin>, +{ + (slf)(&()).await; +} + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-83737-erasing-bound-vars.rs b/src/test/ui/lifetimes/issue-83737-erasing-bound-vars.rs new file mode 100644 index 0000000000..c496a3556c --- /dev/null +++ b/src/test/ui/lifetimes/issue-83737-erasing-bound-vars.rs @@ -0,0 +1,14 @@ +// build-pass +// compile-flags: --edition 2018 +// compile-flags: --crate-type rlib + +use std::future::Future; + +async fn handle<F>(slf: &F) +where + F: Fn(&()) -> Box<dyn for<'a> Future<Output = ()> + Unpin>, +{ + (slf)(&()).await; +} + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs b/src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs new file mode 100644 index 0000000000..7f0ea730dd --- /dev/null +++ b/src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs @@ -0,0 +1,8 @@ +// check-fail + +struct Foo {} +impl Foo { + fn bar(foo: Foo<Target = usize>) {} + //~^ associated type bindings are not allowed here +} +fn main() {} diff --git a/src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr b/src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr new file mode 100644 index 0000000000..f7bdee6336 --- /dev/null +++ b/src/test/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-83753-invalid-associated-type-supertrait-hrtb.rs:5:21 + | +LL | fn bar(foo: Foo<Target = usize>) {} + | ^^^^^^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.rs b/src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.rs new file mode 100644 index 0000000000..604687ce71 --- /dev/null +++ b/src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.rs @@ -0,0 +1,7 @@ +// check-fail + +static STATIC_VAR_FIVE: &One(); +//~^ cannot find type +//~| free static item without body + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr b/src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr new file mode 100644 index 0000000000..e57933da55 --- /dev/null +++ b/src/test/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr @@ -0,0 +1,17 @@ +error: free static item without body + --> $DIR/issue-83907-invalid-fn-like-path.rs:3:1 + | +LL | static STATIC_VAR_FIVE: &One(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= <expr>;` + +error[E0412]: cannot find type `One` in this scope + --> $DIR/issue-83907-invalid-fn-like-path.rs:3:26 + | +LL | static STATIC_VAR_FIVE: &One(); + | ^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/lifetimes/issue-84398.rs b/src/test/ui/lifetimes/issue-84398.rs new file mode 100644 index 0000000000..1912fa59b7 --- /dev/null +++ b/src/test/ui/lifetimes/issue-84398.rs @@ -0,0 +1,20 @@ +// check-pass + +pub trait Deserialize<'de>: Sized {} +pub trait DeserializeOwned: for<'de> Deserialize<'de> {} + +pub trait Extensible { + type Config; +} + +// The `C` here generates a `C: Sized` candidate +pub trait Installer<C> { + fn init<B: Extensible<Config = C>>(&mut self) -> () + where + // This clause generates a `for<'de> C: Sized` candidate + B::Config: DeserializeOwned, + { + } +} + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-84604.rs b/src/test/ui/lifetimes/issue-84604.rs new file mode 100644 index 0000000000..df8368da0a --- /dev/null +++ b/src/test/ui/lifetimes/issue-84604.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags: -Zsymbol-mangling-version=v0 + +pub fn f<T: ?Sized>() {} +pub trait Frob<T: ?Sized> {} +fn main() { + f::<dyn Frob<str>>(); + f::<dyn for<'a> Frob<str>>(); +} diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr index 5751c31948..bbd62902d9 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr @@ -12,7 +12,7 @@ error[E0384]: cannot assign to immutable argument `y` --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:4:5 | LL | fn foo(mut x: Ref, y: &u32) { - | - help: make this binding mutable: `mut y` + | - help: consider making this binding mutable: `mut y` LL | y = x.b; | ^^^^^^^ cannot assign to immutable argument diff --git a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr index c646912d3b..b47a47d631 100644 --- a/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/liveness-assign-imm-local-notes.rs:10:9 | LL | let x; - | - help: make this binding mutable: `mut x` + | - help: consider making this binding mutable: `mut x` ... LL | x = 2; | ----- first assignment to `x` @@ -13,7 +13,7 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/liveness-assign-imm-local-notes.rs:21:13 | LL | let x; - | - help: make this binding mutable: `mut x` + | - help: consider making this binding mutable: `mut x` ... LL | x = 2; | ----- first assignment to `x` @@ -24,7 +24,7 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/liveness-assign-imm-local-notes.rs:30:13 | LL | let x; - | - help: make this binding mutable: `mut x` + | - help: consider making this binding mutable: `mut x` ... LL | x = 1; | ^^^^^ cannot assign twice to immutable variable @@ -33,7 +33,7 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/liveness-assign-imm-local-notes.rs:32:13 | LL | let x; - | - help: make this binding mutable: `mut x` + | - help: consider making this binding mutable: `mut x` ... LL | x = 1; | ----- first assignment to `x` diff --git a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr index 30142e24cd..16333a7ca3 100644 --- a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr +++ b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr @@ -1,3 +1,13 @@ +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 + | +LL | struct Test { + | - help: consider introducing lifetime `'b` here: `<'b>` +LL | a: &'b str, + | ^^ undeclared lifetime + | + = 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 `'b` --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13 | @@ -14,16 +24,6 @@ help: consider introducing lifetime `'b` here LL | fn foo<'b>(&'b self) {} | ^^^^ -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 - | -LL | struct Test { - | - help: consider introducing lifetime `'b` here: `<'b>` -LL | a: &'b str, - | ^^ undeclared lifetime - | - = 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 `'b` --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 | diff --git a/src/test/ui/bad/bad-extern-link-attrs.rs b/src/test/ui/linkage-attr/bad-extern-link-attrs.rs similarity index 100% rename from src/test/ui/bad/bad-extern-link-attrs.rs rename to src/test/ui/linkage-attr/bad-extern-link-attrs.rs diff --git a/src/test/ui/bad/bad-extern-link-attrs.stderr b/src/test/ui/linkage-attr/bad-extern-link-attrs.stderr similarity index 100% rename from src/test/ui/bad/bad-extern-link-attrs.stderr rename to src/test/ui/linkage-attr/bad-extern-link-attrs.stderr diff --git a/src/test/ui/linkage-attr/invalid-link-args.rs b/src/test/ui/linkage-attr/invalid-link-args.rs deleted file mode 100644 index 7418691d01..0000000000 --- a/src/test/ui/linkage-attr/invalid-link-args.rs +++ /dev/null @@ -1,14 +0,0 @@ -// build-fail -// dont-check-compiler-stderr -// ignore-msvc due to linker-flavor=ld -// error-pattern:aFdEfSeVEEE -// compile-flags: -C linker-flavor=ld - -/* Make sure invalid link_args are printed to stderr. */ - -#![feature(link_args)] - -#[link_args = "aFdEfSeVEEE"] -extern "C" {} - -fn main() {} diff --git a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs index 7b2f5365ac..3a0910658b 100644 --- a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs +++ b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs @@ -4,6 +4,8 @@ // build-fail // aux-build:def_colliding_external.rs +// FIXME(#83838) codegen-units=1 triggers llvm asserts +// compile-flags: -Ccodegen-units=16 extern crate def_colliding_external as dep1; diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs index b712f3225e..c1df9ccef2 100644 --- a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs +++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs @@ -1,5 +1,6 @@ // build-fail - +// FIXME(#83838) codegen-units=1 triggers llvm asserts +// compile-flags: -Ccodegen-units=16 #![feature(linkage)] mod dep1 { diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr index d008acc6e7..7e395e6737 100644 --- a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr +++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr @@ -1,5 +1,5 @@ error: symbol `collision` is already defined - --> $DIR/linkage-detect-local-generated-name-collision.rs:9:9 + --> $DIR/linkage-detect-local-generated-name-collision.rs:10:9 | LL | pub static collision: *const i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/bad/bad-lint-cap.rs b/src/test/ui/lint/bad-lint-cap.rs similarity index 100% rename from src/test/ui/bad/bad-lint-cap.rs rename to src/test/ui/lint/bad-lint-cap.rs diff --git a/src/test/ui/bad/bad-lint-cap.stderr b/src/test/ui/lint/bad-lint-cap.stderr similarity index 100% rename from src/test/ui/bad/bad-lint-cap.stderr rename to src/test/ui/lint/bad-lint-cap.stderr diff --git a/src/test/ui/bad/bad-lint-cap2.rs b/src/test/ui/lint/bad-lint-cap2.rs similarity index 100% rename from src/test/ui/bad/bad-lint-cap2.rs rename to src/test/ui/lint/bad-lint-cap2.rs diff --git a/src/test/ui/bad/bad-lint-cap2.stderr b/src/test/ui/lint/bad-lint-cap2.stderr similarity index 100% rename from src/test/ui/bad/bad-lint-cap2.stderr rename to src/test/ui/lint/bad-lint-cap2.stderr diff --git a/src/test/ui/bad/bad-lint-cap3.rs b/src/test/ui/lint/bad-lint-cap3.rs similarity index 100% rename from src/test/ui/bad/bad-lint-cap3.rs rename to src/test/ui/lint/bad-lint-cap3.rs diff --git a/src/test/ui/bad/bad-lint-cap3.stderr b/src/test/ui/lint/bad-lint-cap3.stderr similarity index 100% rename from src/test/ui/bad/bad-lint-cap3.stderr rename to src/test/ui/lint/bad-lint-cap3.stderr diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.rs b/src/test/ui/lint/dead-code/lint-dead-code-2.rs index 88db4f88c3..2cfe6e539d 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.rs +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.rs @@ -1,6 +1,6 @@ #![allow(unused_variables)] #![deny(dead_code)] -#![feature(main, start)] +#![feature(rustc_attrs, start)] struct Foo; @@ -21,7 +21,7 @@ fn live_fn() {} fn dead_fn() {} //~ ERROR: function is never used -#[main] +#[rustc_main] fn dead_fn2() {} //~ ERROR: function is never used fn used_fn() {} diff --git a/src/test/ui/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs similarity index 100% rename from src/test/ui/fn_must_use.rs rename to src/test/ui/lint/fn_must_use.rs diff --git a/src/test/ui/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr similarity index 100% rename from src/test/ui/fn_must_use.stderr rename to src/test/ui/lint/fn_must_use.stderr diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.fixed b/src/test/ui/lint/issue-54538-unused-parens-lint.fixed index c70c39b5f6..0b3fe9371f 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.fixed +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.fixed @@ -1,7 +1,6 @@ // run-rustfix #![feature(box_patterns, stmt_expr_attributes)] -#![feature(or_patterns)] #![allow( dead_code, diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs index 9dd3b63c0f..1e78ec5f7d 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs @@ -1,7 +1,6 @@ // run-rustfix #![feature(box_patterns, stmt_expr_attributes)] -#![feature(or_patterns)] #![allow( dead_code, diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr index ee46685775..e6d0a359c5 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr @@ -1,149 +1,149 @@ error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:17:9 + --> $DIR/issue-54538-unused-parens-lint.rs:16:9 | LL | let (a) = 0; | ^^^ help: remove these parentheses | note: the lint level is defined here - --> $DIR/issue-54538-unused-parens-lint.rs:14:9 + --> $DIR/issue-54538-unused-parens-lint.rs:13:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:18:9 + --> $DIR/issue-54538-unused-parens-lint.rs:17:9 | LL | for (a) in 0..1 {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:19:12 + --> $DIR/issue-54538-unused-parens-lint.rs:18:12 | LL | if let (a) = 0 {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:20:15 + --> $DIR/issue-54538-unused-parens-lint.rs:19:15 | LL | while let (a) = 0 {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:21:12 + --> $DIR/issue-54538-unused-parens-lint.rs:20:12 | LL | fn foo((a): u8) {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:22:14 + --> $DIR/issue-54538-unused-parens-lint.rs:21:14 | LL | let _ = |(a): u8| 0; | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:50:12 + --> $DIR/issue-54538-unused-parens-lint.rs:49:12 | LL | if let (0 | 1) = 0 {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:51:13 + --> $DIR/issue-54538-unused-parens-lint.rs:50:13 | LL | if let ((0 | 1),) = (0,) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:52:13 + --> $DIR/issue-54538-unused-parens-lint.rs:51:13 | LL | if let [(0 | 1)] = [0] {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:53:16 + --> $DIR/issue-54538-unused-parens-lint.rs:52:16 | LL | if let 0 | (1 | 2) = 0 {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:55:15 + --> $DIR/issue-54538-unused-parens-lint.rs:54:15 | LL | if let TS((0 | 1)) = TS(0) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:57:20 + --> $DIR/issue-54538-unused-parens-lint.rs:56:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:67:9 + --> $DIR/issue-54538-unused-parens-lint.rs:66:9 | LL | (_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:68:9 + --> $DIR/issue-54538-unused-parens-lint.rs:67:9 | LL | (y) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:69:9 + --> $DIR/issue-54538-unused-parens-lint.rs:68:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:70:9 + --> $DIR/issue-54538-unused-parens-lint.rs:69:9 | LL | (e @ 1...2) => {} | ^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:76:9 + --> $DIR/issue-54538-unused-parens-lint.rs:75:9 | LL | (e @ &(1...2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:77:10 + --> $DIR/issue-54538-unused-parens-lint.rs:76:10 | LL | &(_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:88:9 + --> $DIR/issue-54538-unused-parens-lint.rs:87:9 | LL | (_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:89:9 + --> $DIR/issue-54538-unused-parens-lint.rs:88:9 | LL | (y) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:90:9 + --> $DIR/issue-54538-unused-parens-lint.rs:89:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:91:9 + --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (e @ 1..=2) => {} | ^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:97:9 + --> $DIR/issue-54538-unused-parens-lint.rs:96:9 | LL | (e @ &(1..=2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:98:10 + --> $DIR/issue-54538-unused-parens-lint.rs:97:10 | LL | &(_) => {} | ^^^ help: remove these parentheses diff --git a/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.rs b/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.rs index b21f1ef6b2..e3631d014d 100644 --- a/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.rs +++ b/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.rs @@ -1,7 +1,6 @@ // FIXME: should be run-rustfix, but rustfix doesn't currently support multipart suggestions, see // #53934 -#![feature(or_patterns)] #![deny(unused)] pub enum MyEnum { diff --git a/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.stderr b/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.stderr index 9cff290090..8aefe243a9 100644 --- a/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.stderr +++ b/src/test/ui/lint/issue-67691-unused-field-in-or-pattern.stderr @@ -1,11 +1,11 @@ error: unused variable: `j` - --> $DIR/issue-67691-unused-field-in-or-pattern.rs:21:16 + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:20:16 | LL | A { i, j } | B { i, j } => { | ^ ^ | note: the lint level is defined here - --> $DIR/issue-67691-unused-field-in-or-pattern.rs:5:9 + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:4:9 | LL | #![deny(unused)] | ^^^^^^ @@ -16,7 +16,7 @@ LL | A { i, j: _ } | B { i, j: _ } => { | ^^^^ ^^^^ error: unused variable: `j` - --> $DIR/issue-67691-unused-field-in-or-pattern.rs:31:16 + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:30:16 | LL | A { i, ref j } | B { i, ref j } => { | ^^^^^ ^^^^^ @@ -27,7 +27,7 @@ LL | A { i, j: _ } | B { i, j: _ } => { | ^^^^ ^^^^ error: unused variable: `j` - --> $DIR/issue-67691-unused-field-in-or-pattern.rs:41:21 + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:40:21 | LL | Some(A { i, j } | B { i, j }) => { | ^ ^ @@ -38,7 +38,7 @@ LL | Some(A { i, j: _ } | B { i, j: _ }) => { | ^^^^ ^^^^ error: unused variable: `j` - --> $DIR/issue-67691-unused-field-in-or-pattern.rs:53:21 + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:52:21 | LL | Some(A { i, ref j } | B { i, ref j }) => { | ^^^^^ ^^^^^ @@ -49,7 +49,7 @@ LL | Some(A { i, j: _ } | B { i, j: _ }) => { | ^^^^ ^^^^ error: unused variable: `i` - --> $DIR/issue-67691-unused-field-in-or-pattern.rs:63:24 + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:62:24 | LL | MixedEnum::A { i } | MixedEnum::B(i) => { | ^ ^ @@ -60,7 +60,7 @@ LL | MixedEnum::A { i: _ } | MixedEnum::B(_) => { | ^^^^ ^ error: unused variable: `i` - --> $DIR/issue-67691-unused-field-in-or-pattern.rs:71:24 + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:70:24 | LL | MixedEnum::A { ref i } | MixedEnum::B(ref i) => { | ^^^^^ ^^^^^ diff --git a/src/test/ui/lint/issue-83477.rs b/src/test/ui/lint/issue-83477.rs new file mode 100644 index 0000000000..0eba52acfa --- /dev/null +++ b/src/test/ui/lint/issue-83477.rs @@ -0,0 +1,16 @@ +// check-pass +#![warn(rustc::internal)] + +#[allow(rustc::foo::bar::default_hash_types)] +//~^ WARN unknown lint: `rustc::foo::bar::default_hash_types` +//~| HELP did you mean +//~| SUGGESTION rustc::default_hash_types +#[allow(rustc::foo::default_hash_types)] +//~^ WARN unknown lint: `rustc::foo::default_hash_types` +//~| HELP did you mean +//~| 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 +} diff --git a/src/test/ui/lint/issue-83477.stderr b/src/test/ui/lint/issue-83477.stderr new file mode 100644 index 0000000000..dbe0c9e013 --- /dev/null +++ b/src/test/ui/lint/issue-83477.stderr @@ -0,0 +1,30 @@ +warning: unknown lint: `rustc::foo::bar::default_hash_types` + --> $DIR/issue-83477.rs:4:9 + | +LL | #[allow(rustc::foo::bar::default_hash_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` + | + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `rustc::foo::default_hash_types` + --> $DIR/issue-83477.rs:8:9 + | +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:13:31 + | +LL | let _ = std::collections::HashMap::<String, String>::new(); + | ^^^^^^^ help: use: `FxHashMap` + | +note: the lint level is defined here + --> $DIR/issue-83477.rs:2:9 + | +LL | #![warn(rustc::internal)] + | ^^^^^^^^^^^^^^^ + = note: `#[warn(rustc::default_hash_types)]` implied by `#[warn(rustc::internal)]` + = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary + +warning: 3 warnings emitted + diff --git a/src/test/ui/lint/lint-deref-nullptr.rs b/src/test/ui/lint/lint-deref-nullptr.rs new file mode 100644 index 0000000000..d052dbd9b6 --- /dev/null +++ b/src/test/ui/lint/lint-deref-nullptr.rs @@ -0,0 +1,38 @@ +// test the deref_nullptr lint + +#![deny(deref_nullptr)] + +use std::ptr; + +struct Struct { + field: u8, +} + +fn f() { + unsafe { + let a = 1; + let ub = *(a as *const i32); + let ub = *(0 as *const i32); + //~^ ERROR dereferencing a null pointer + let ub = *ptr::null::<i32>(); + //~^ ERROR dereferencing a null pointer + let ub = *ptr::null_mut::<i32>(); + //~^ ERROR dereferencing a null pointer + let ub = *(ptr::null::<i16>() as *const i32); + //~^ ERROR dereferencing a null pointer + let ub = *(ptr::null::<i16>() as *mut i32 as *mut usize as *const u8); + //~^ ERROR dereferencing a null pointer + let ub = &*ptr::null::<i32>(); + //~^ ERROR dereferencing a null pointer + let ub = &*ptr::null_mut::<i32>(); + //~^ ERROR dereferencing a null pointer + ptr::addr_of!(*ptr::null::<i32>()); + //~^ ERROR dereferencing a null pointer + ptr::addr_of_mut!(*ptr::null_mut::<i32>()); + //~^ ERROR dereferencing a null pointer + let offset = ptr::addr_of!((*ptr::null::<Struct>()).field); + //~^ ERROR dereferencing a null pointer + } +} + +fn main() {} diff --git a/src/test/ui/lint/lint-deref-nullptr.stderr b/src/test/ui/lint/lint-deref-nullptr.stderr new file mode 100644 index 0000000000..c6f432e4e4 --- /dev/null +++ b/src/test/ui/lint/lint-deref-nullptr.stderr @@ -0,0 +1,68 @@ +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:15:18 + | +LL | let ub = *(0 as *const i32); + | ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + | +note: the lint level is defined here + --> $DIR/lint-deref-nullptr.rs:3:9 + | +LL | #![deny(deref_nullptr)] + | ^^^^^^^^^^^^^ + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:17:18 + | +LL | let ub = *ptr::null::<i32>(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:19:18 + | +LL | let ub = *ptr::null_mut::<i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:21:18 + | +LL | let ub = *(ptr::null::<i16>() as *const i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:23:18 + | +LL | let ub = *(ptr::null::<i16>() as *mut i32 as *mut usize as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:25:19 + | +LL | let ub = &*ptr::null::<i32>(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:27:19 + | +LL | let ub = &*ptr::null_mut::<i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:29:23 + | +LL | ptr::addr_of!(*ptr::null::<i32>()); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:31:27 + | +LL | ptr::addr_of_mut!(*ptr::null_mut::<i32>()); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:33:36 + | +LL | let offset = ptr::addr_of!((*ptr::null::<Struct>()).field); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs index 710eebe4b6..9f0c87dcaa 100644 --- a/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs +++ b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs @@ -3,7 +3,6 @@ #![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(non_ascii_idents)] #![deny(non_snake_case)] // This name is neither upper nor lower case diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs index 034499145b..527d0ea943 100644 --- a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] #![forbid(non_camel_case_types)] -#![feature(non_ascii_idents)] // Some scripts (e.g., hiragana) don't have a concept of // upper/lowercase diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr index 3710026565..6c2aa225e6 100644 --- a/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr @@ -1,5 +1,5 @@ error: type `χa` should have an upper camel case name - --> $DIR/lint-nonstandard-style-unicode-1.rs:15:8 + --> $DIR/lint-nonstandard-style-unicode-1.rs:14:8 | LL | struct χa; | ^^ help: convert the identifier to upper camel case: `Χa` @@ -11,37 +11,37 @@ LL | #![forbid(non_camel_case_types)] | ^^^^^^^^^^^^^^^^^^^^ error: type `__χa` should have an upper camel case name - --> $DIR/lint-nonstandard-style-unicode-1.rs:23:8 + --> $DIR/lint-nonstandard-style-unicode-1.rs:22:8 | LL | struct __χa; | ^^^^ help: convert the identifier to upper camel case: `Χa` error: type `对__否` should have an upper camel case name - --> $DIR/lint-nonstandard-style-unicode-1.rs:28:8 + --> $DIR/lint-nonstandard-style-unicode-1.rs:27:8 | LL | struct 对__否; | ^^^^^^ help: convert the identifier to upper camel case: `对_否` error: type `ヒ__χ` should have an upper camel case name - --> $DIR/lint-nonstandard-style-unicode-1.rs:31:8 + --> $DIR/lint-nonstandard-style-unicode-1.rs:30:8 | LL | struct ヒ__χ; | ^^^^^ help: convert the identifier to upper camel case: `ヒΧ` error: type `Hello_你好` should have an upper camel case name - --> $DIR/lint-nonstandard-style-unicode-1.rs:37:8 + --> $DIR/lint-nonstandard-style-unicode-1.rs:36:8 | LL | struct Hello_你好; | ^^^^^^^^^^ help: convert the identifier to upper camel case: `Hello你好` error: type `Hello_World` should have an upper camel case name - --> $DIR/lint-nonstandard-style-unicode-1.rs:40:8 + --> $DIR/lint-nonstandard-style-unicode-1.rs:39:8 | LL | struct Hello_World; | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `HelloWorld` error: type `你_ӟ` should have an upper camel case name - --> $DIR/lint-nonstandard-style-unicode-1.rs:43:8 + --> $DIR/lint-nonstandard-style-unicode-1.rs:42:8 | LL | struct 你_ӟ; | ^^^^ help: convert the identifier to upper camel case: `你Ӟ` diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs index 0b52a5fde3..9690be5908 100644 --- a/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] #![forbid(non_snake_case)] -#![feature(non_ascii_idents)] // Some scripts (e.g., hiragana) don't have a concept of // upper/lowercase diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr index 0b309e315a..8eb0654e0a 100644 --- a/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr @@ -1,5 +1,5 @@ error: function `Ц` should have a snake case name - --> $DIR/lint-nonstandard-style-unicode-2.rs:18:4 + --> $DIR/lint-nonstandard-style-unicode-2.rs:17:4 | LL | fn Ц() {} | ^ help: convert the identifier to snake case: `ц` @@ -11,7 +11,7 @@ LL | #![forbid(non_snake_case)] | ^^^^^^^^^^^^^^ error: function `分__隔` should have a snake case name - --> $DIR/lint-nonstandard-style-unicode-2.rs:23:4 + --> $DIR/lint-nonstandard-style-unicode-2.rs:22:4 | LL | fn 分__隔() {} | ^^^^^^ help: convert the identifier to snake case: `分_隔` diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs index b17c2de39a..9175be7a0f 100644 --- a/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] #![forbid(non_upper_case_globals)] -#![feature(non_ascii_idents)] // Some scripts (e.g., hiragana) don't have a concept of // upper/lowercase diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr index 44bd5ad55f..970e6b838a 100644 --- a/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr +++ b/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr @@ -1,5 +1,5 @@ error: static variable `τεχ` should have an upper case name - --> $DIR/lint-nonstandard-style-unicode-3.rs:18:8 + --> $DIR/lint-nonstandard-style-unicode-3.rs:17:8 | LL | static τεχ: f32 = 3.14159265; | ^^^ help: convert the identifier to upper case: `ΤΕΧ` diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs index a6fde11495..5bdddf7141 100644 --- a/src/test/ui/lint/lint-stability-deprecated.rs +++ b/src/test/ui/lint/lint-stability-deprecated.rs @@ -3,7 +3,6 @@ // aux-build:inherited_stability.rs // aux-build:stability_cfg1.rs // aux-build:stability-cfg2.rs -// ignore-tidy-linelength #![warn(deprecated)] #![feature(staged_api, unstable_test_feature)] diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr index d8dd83b0d0..47dc8e4a63 100644 --- a/src/test/ui/lint/lint-stability-deprecated.stderr +++ b/src/test/ui/lint/lint-stability-deprecated.stderr @@ -1,653 +1,653 @@ warning: use of deprecated function `lint_stability::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:25:9 + --> $DIR/lint-stability-deprecated.rs:24:9 | LL | deprecated(); | ^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-stability-deprecated.rs:7:9 + --> $DIR/lint-stability-deprecated.rs:6:9 | LL | #![warn(deprecated)] | ^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:30:9 + --> $DIR/lint-stability-deprecated.rs:29:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:32:9 + --> $DIR/lint-stability-deprecated.rs:31:9 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:34:9 + --> $DIR/lint-stability-deprecated.rs:33:9 | LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:39:9 + --> $DIR/lint-stability-deprecated.rs:38:9 | LL | ... Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:41:9 + --> $DIR/lint-stability-deprecated.rs:40:9 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:43:9 + --> $DIR/lint-stability-deprecated.rs:42:9 | LL | deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:48:9 + --> $DIR/lint-stability-deprecated.rs:47:9 | LL | ... Trait::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:50:9 + --> $DIR/lint-stability-deprecated.rs:49:9 | LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:52:9 + --> $DIR/lint-stability-deprecated.rs:51:9 | LL | deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:57:9 + --> $DIR/lint-stability-deprecated.rs:56:9 | 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:59:9 + --> $DIR/lint-stability-deprecated.rs:58:9 | LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:109:17 + --> $DIR/lint-stability-deprecated.rs:108:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedUnstableStruct`: text - --> $DIR/lint-stability-deprecated.rs:112:17 + --> $DIR/lint-stability-deprecated.rs:111:17 | LL | let _ = DeprecatedUnstableStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:119:17 + --> $DIR/lint-stability-deprecated.rs:118:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedUnstableUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:120:17 + --> $DIR/lint-stability-deprecated.rs:119:17 | LL | let _ = DeprecatedUnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated variant `lint_stability::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:124:17 + --> $DIR/lint-stability-deprecated.rs:123:17 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`: text - --> $DIR/lint-stability-deprecated.rs:125:17 + --> $DIR/lint-stability-deprecated.rs:124:17 | LL | let _ = Enum::DeprecatedUnstableVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:129:17 + --> $DIR/lint-stability-deprecated.rs:128:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedUnstableTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:130:17 + --> $DIR/lint-stability-deprecated.rs:129:17 | LL | let _ = DeprecatedUnstableTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:139:25 + --> $DIR/lint-stability-deprecated.rs:138:25 | LL | macro_test_arg!(deprecated_text()); | ^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:140:25 + --> $DIR/lint-stability-deprecated.rs:139:25 | LL | macro_test_arg!(deprecated_unstable_text()); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:141:41 + --> $DIR/lint-stability-deprecated.rs:140:41 | 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:146:9 + --> $DIR/lint-stability-deprecated.rs:145:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:148:9 + --> $DIR/lint-stability-deprecated.rs:147:9 | 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:150:9 + --> $DIR/lint-stability-deprecated.rs:149:9 | LL | ... Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:152:9 + --> $DIR/lint-stability-deprecated.rs:151:9 | 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:154:9 + --> $DIR/lint-stability-deprecated.rs:153:9 | LL | ... Trait::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:156:9 + --> $DIR/lint-stability-deprecated.rs:155:9 | 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:158:9 + --> $DIR/lint-stability-deprecated.rs:157:9 | 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:160:9 + --> $DIR/lint-stability-deprecated.rs:159:9 | LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:188:10 + --> $DIR/lint-stability-deprecated.rs:187:10 | LL | impl DeprecatedTrait for S {} | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:190:25 + --> $DIR/lint-stability-deprecated.rs:189:25 | LL | trait LocalTrait2 : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:209:9 + --> $DIR/lint-stability-deprecated.rs:208:9 | LL | unstable_mod::deprecated(); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:331:9 + --> $DIR/lint-stability-deprecated.rs:330:9 | LL | deprecated(); | ^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:336:9 + --> $DIR/lint-stability-deprecated.rs:335:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:338:9 + --> $DIR/lint-stability-deprecated.rs:337:9 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:340:9 + --> $DIR/lint-stability-deprecated.rs:339:9 | LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:345:9 + --> $DIR/lint-stability-deprecated.rs:344:9 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:347:9 + --> $DIR/lint-stability-deprecated.rs:346:9 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `this_crate::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:385:17 + --> $DIR/lint-stability-deprecated.rs:384:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:392:17 + --> $DIR/lint-stability-deprecated.rs:391:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:396:17 + --> $DIR/lint-stability-deprecated.rs:395:17 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:400:17 + --> $DIR/lint-stability-deprecated.rs:399:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:407:9 + --> $DIR/lint-stability-deprecated.rs:406:9 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:409:9 + --> $DIR/lint-stability-deprecated.rs:408:9 | 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:411:9 + --> $DIR/lint-stability-deprecated.rs:410:9 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:413:9 + --> $DIR/lint-stability-deprecated.rs:412:9 | 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:440:9 + --> $DIR/lint-stability-deprecated.rs:439:9 | LL | fn_in_body(); | ^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:460:10 + --> $DIR/lint-stability-deprecated.rs:459:10 | LL | impl DeprecatedTrait for S { } | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:462:24 + --> $DIR/lint-stability-deprecated.rs:461:24 | LL | trait LocalTrait : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text - --> $DIR/lint-stability-deprecated.rs:448:13 + --> $DIR/lint-stability-deprecated.rs:447:13 | LL | fn_in_body(); | ^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:98:48 + --> $DIR/lint-stability-deprecated.rs:97:48 | LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:103:13 + --> $DIR/lint-stability-deprecated.rs:102:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:26:13 + --> $DIR/lint-stability-deprecated.rs:25:13 | LL | foo.method_deprecated(); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:27:9 + --> $DIR/lint-stability-deprecated.rs:26:9 | LL | Foo::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:28:9 + --> $DIR/lint-stability-deprecated.rs:27:9 | LL | <Foo>::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:29:13 + --> $DIR/lint-stability-deprecated.rs:28:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:31:9 + --> $DIR/lint-stability-deprecated.rs:30:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:35:13 + --> $DIR/lint-stability-deprecated.rs:34:13 | LL | ... foo.method_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:36:9 + --> $DIR/lint-stability-deprecated.rs:35:9 | LL | ... Foo::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:37:9 + --> $DIR/lint-stability-deprecated.rs:36:9 | LL | ... <Foo>::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:38:13 + --> $DIR/lint-stability-deprecated.rs:37:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ 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:39:9 | LL | ... <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:44:13 + --> $DIR/lint-stability-deprecated.rs:43:13 | LL | ... foo.method_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:45:9 + --> $DIR/lint-stability-deprecated.rs:44:9 | LL | ... Foo::method_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:46:9 + --> $DIR/lint-stability-deprecated.rs:45:9 | LL | ... <Foo>::method_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:47:13 + --> $DIR/lint-stability-deprecated.rs:46:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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:48:9 | LL | ... <Foo>::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:53:13 + --> $DIR/lint-stability-deprecated.rs:52:13 | LL | ... foo.method_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:54:9 + --> $DIR/lint-stability-deprecated.rs:53:9 | LL | ... Foo::method_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:55:9 + --> $DIR/lint-stability-deprecated.rs:54:9 | LL | ... <Foo>::method_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:56:13 + --> $DIR/lint-stability-deprecated.rs:55:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:57:9 | LL | ... <Foo>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `lint_stability::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:110:13 + --> $DIR/lint-stability-deprecated.rs:109:13 | LL | i: 0 | ^^^^ warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:114:13 + --> $DIR/lint-stability-deprecated.rs:113:13 | LL | i: 0 | ^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:145:13 + --> $DIR/lint-stability-deprecated.rs:144:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:147:9 + --> $DIR/lint-stability-deprecated.rs:146:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:149:13 + --> $DIR/lint-stability-deprecated.rs:148:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ 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:150:9 | LL | ... <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:153:13 + --> $DIR/lint-stability-deprecated.rs:152:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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:154:9 | LL | ... <Foo>::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:157:13 + --> $DIR/lint-stability-deprecated.rs:156:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:158:9 | LL | ... <Foo>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:176:13 + --> $DIR/lint-stability-deprecated.rs:175:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:177:13 + --> $DIR/lint-stability-deprecated.rs:176:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:178:13 + --> $DIR/lint-stability-deprecated.rs:177:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:179:13 + --> $DIR/lint-stability-deprecated.rs:178:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:332:13 + --> $DIR/lint-stability-deprecated.rs:331:13 | LL | foo.method_deprecated(); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:333:9 + --> $DIR/lint-stability-deprecated.rs:332:9 | LL | Foo::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:334:9 + --> $DIR/lint-stability-deprecated.rs:333:9 | LL | <Foo>::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:335:13 + --> $DIR/lint-stability-deprecated.rs:334:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:337:9 + --> $DIR/lint-stability-deprecated.rs:336:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:341:13 + --> $DIR/lint-stability-deprecated.rs:340:13 | LL | ... foo.method_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:342:9 + --> $DIR/lint-stability-deprecated.rs:341:9 | LL | ... Foo::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:343:9 + --> $DIR/lint-stability-deprecated.rs:342:9 | LL | ... <Foo>::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:344:13 + --> $DIR/lint-stability-deprecated.rs:343:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ 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:345:9 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:387:13 + --> $DIR/lint-stability-deprecated.rs:386:13 | LL | i: 0 | ^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:406:13 + --> $DIR/lint-stability-deprecated.rs:405:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:408:9 + --> $DIR/lint-stability-deprecated.rs:407:9 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:410:13 + --> $DIR/lint-stability-deprecated.rs:409:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ 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:411:9 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:429:13 + --> $DIR/lint-stability-deprecated.rs:428:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:430:13 + --> $DIR/lint-stability-deprecated.rs:429:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:98:48 + --> $DIR/lint-stability-deprecated.rs:97:48 | LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:103:13 + --> $DIR/lint-stability-deprecated.rs:102:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:103:13 + --> $DIR/lint-stability-deprecated.rs:102:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs index 2c711f9940..e7da825ae3 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs @@ -1,4 +1,3 @@ -#![feature(non_ascii_idents)] #![deny(confusable_idents)] #![allow(uncommon_codepoints, non_upper_case_globals)] diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr index b9af60963a..e9906c83d1 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr @@ -1,5 +1,5 @@ error: identifier pair considered confusable between `s` and `s` - --> $DIR/lint-confusable-idents.rs:9:9 + --> $DIR/lint-confusable-idents.rs:8:9 | LL | const s: usize = 42; | -- this is where the previous identifier occurred @@ -8,13 +8,13 @@ LL | let s = "rust"; | ^ | note: the lint level is defined here - --> $DIR/lint-confusable-idents.rs:2:9 + --> $DIR/lint-confusable-idents.rs:1:9 | LL | #![deny(confusable_idents)] | ^^^^^^^^^^^^^^^^^ error: identifier pair considered confusable between `s_s` and `s_s` - --> $DIR/lint-confusable-idents.rs:10:9 + --> $DIR/lint-confusable-idents.rs:9:9 | LL | const s_s: usize = 42; | --- this is where the previous identifier occurred diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs index a5b45466da..f62c8a1903 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(non_ascii_idents)] #![deny(mixed_script_confusables)] struct ΑctuallyNotLatin; diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs index 4637b03f25..7ee9c41f6a 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs @@ -1,4 +1,3 @@ -#![feature(non_ascii_idents)] #![deny(mixed_script_confusables)] struct ΑctuallyNotLatin; diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr index 6f75a1ece3..4018b381fb 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr @@ -1,11 +1,11 @@ error: The usage of Script Group `Greek` in this crate consists solely of mixed script confusables - --> $DIR/lint-mixed-script-confusables.rs:4:8 + --> $DIR/lint-mixed-script-confusables.rs:3:8 | LL | struct ΑctuallyNotLatin; | ^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-mixed-script-confusables.rs:2:9 + --> $DIR/lint-mixed-script-confusables.rs:1:9 | LL | #![deny(mixed_script_confusables)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | #![deny(mixed_script_confusables)] = note: Please recheck to make sure their usages are indeed what you want. error: The usage of Script Group `Cyrillic` in this crate consists solely of mixed script confusables - --> $DIR/lint-mixed-script-confusables.rs:11:5 + --> $DIR/lint-mixed-script-confusables.rs:10:5 | LL | mod роре { | ^^^^ @@ -22,7 +22,7 @@ LL | mod роре { = note: Please recheck to make sure their usages are indeed what you want. error: The usage of Script Group `Japanese, Katakana` in this crate consists solely of mixed script confusables - --> $DIR/lint-mixed-script-confusables.rs:13:11 + --> $DIR/lint-mixed-script-confusables.rs:12:11 | LL | const エ: &'static str = "アイウ"; | ^^ diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs index 20d00cf701..8ae1744096 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs @@ -1,4 +1,3 @@ -#![feature(non_ascii_idents)] #![deny(non_ascii_idents)] const חלודה: usize = 2; //~ ERROR identifier contains non-ASCII characters diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr index 048b6ff5d6..8ed7f093ce 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr @@ -1,23 +1,23 @@ error: identifier contains non-ASCII characters - --> $DIR/lint-non-ascii-idents.rs:4:7 + --> $DIR/lint-non-ascii-idents.rs:3:7 | LL | const חלודה: usize = 2; | ^^^^^ | note: the lint level is defined here - --> $DIR/lint-non-ascii-idents.rs:2:9 + --> $DIR/lint-non-ascii-idents.rs:1:9 | LL | #![deny(non_ascii_idents)] | ^^^^^^^^^^^^^^^^ error: identifier contains non-ASCII characters - --> $DIR/lint-non-ascii-idents.rs:6:4 + --> $DIR/lint-non-ascii-idents.rs:5:4 | LL | fn coöperation() {} | ^^^^^^^^^^^ error: identifier contains non-ASCII characters - --> $DIR/lint-non-ascii-idents.rs:9:9 + --> $DIR/lint-non-ascii-idents.rs:8:9 | LL | let naïveté = 2; | ^^^^^^^ diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs index b5e251e047..81a3427a10 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs @@ -1,4 +1,3 @@ -#![feature(non_ascii_idents)] #![deny(uncommon_codepoints)] const µ: f64 = 0.000001; //~ ERROR identifier contains uncommon Unicode codepoints diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr index 05ea3d5de7..d435282a6e 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr @@ -1,23 +1,23 @@ error: identifier contains uncommon Unicode codepoints - --> $DIR/lint-uncommon-codepoints.rs:4:7 + --> $DIR/lint-uncommon-codepoints.rs:3:7 | LL | const µ: f64 = 0.000001; | ^ | note: the lint level is defined here - --> $DIR/lint-uncommon-codepoints.rs:2:9 + --> $DIR/lint-uncommon-codepoints.rs:1:9 | LL | #![deny(uncommon_codepoints)] | ^^^^^^^^^^^^^^^^^^^ error: identifier contains uncommon Unicode codepoints - --> $DIR/lint-uncommon-codepoints.rs:6:4 + --> $DIR/lint-uncommon-codepoints.rs:5:4 | LL | fn dijkstra() {} | ^^^^^^^ error: identifier contains uncommon Unicode codepoints - --> $DIR/lint-uncommon-codepoints.rs:9:9 + --> $DIR/lint-uncommon-codepoints.rs:8:9 | LL | let ㇻㇲㇳ = "rust"; | ^^^^^^ diff --git a/src/test/ui/lint/special-upper-lower-cases.rs b/src/test/ui/lint/special-upper-lower-cases.rs index 71ebf05dd3..761be61fa0 100644 --- a/src/test/ui/lint/special-upper-lower-cases.rs +++ b/src/test/ui/lint/special-upper-lower-cases.rs @@ -5,7 +5,6 @@ // check-pass -#![feature(non_ascii_idents)] #![allow(uncommon_codepoints, unused)] struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝; diff --git a/src/test/ui/lint/special-upper-lower-cases.stderr b/src/test/ui/lint/special-upper-lower-cases.stderr index e3b451a15a..2aa13c33be 100644 --- a/src/test/ui/lint/special-upper-lower-cases.stderr +++ b/src/test/ui/lint/special-upper-lower-cases.stderr @@ -1,5 +1,5 @@ warning: type `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name - --> $DIR/special-upper-lower-cases.rs:11:8 + --> $DIR/special-upper-lower-cases.rs:10:8 | LL | struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝; | ^^^^^^^^^ should have an UpperCamelCase name @@ -7,13 +7,13 @@ LL | struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝; = note: `#[warn(non_camel_case_types)]` on by default warning: type `𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name - --> $DIR/special-upper-lower-cases.rs:15:8 + --> $DIR/special-upper-lower-cases.rs:14:8 | LL | struct 𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝; | ^^^^^^^^^^^ should have an UpperCamelCase name warning: static variable `𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲` should have an upper case name - --> $DIR/special-upper-lower-cases.rs:18:8 + --> $DIR/special-upper-lower-cases.rs:17:8 | LL | static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1; | ^^^^^^^^^^^^ should have an UPPER_CASE name @@ -21,7 +21,7 @@ LL | static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1; = note: `#[warn(non_upper_case_globals)]` on by default warning: variable `𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢` should have a snake case name - --> $DIR/special-upper-lower-cases.rs:22:9 + --> $DIR/special-upper-lower-cases.rs:21:9 | LL | let 𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢 = 1; | ^^^^^^^^^ should have a snake_case name diff --git a/src/test/ui/lint/unaligned_references.rs b/src/test/ui/lint/unaligned_references.rs index c4e5d06564..d06b06b504 100644 --- a/src/test/ui/lint/unaligned_references.rs +++ b/src/test/ui/lint/unaligned_references.rs @@ -8,22 +8,43 @@ pub struct Good { aligned: [u8; 32], } +#[repr(packed(2))] +pub struct Packed2 { + x: u32, + y: u16, + z: u8, +} + fn main() { unsafe { let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; let _ = &good.ptr; //~ ERROR reference to packed field + //~^ previously accepted let _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted // Error even when turned into raw pointer immediately. let _ = &good.data as *const _; //~ ERROR reference to packed field + //~^ previously accepted let _: *const _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted // Error on method call. let _ = good.data.clone(); //~ ERROR reference to packed field + //~^ previously accepted // Error for nested fields. let _ = &good.data2[0]; //~ ERROR reference to packed field + //~^ previously accepted let _ = &*good.ptr; // ok, behind a pointer let _ = &good.aligned; // ok, has align 1 let _ = &good.aligned[2]; // ok, has align 1 } + + unsafe { + let packed2 = Packed2 { x: 0, y: 0, z: 0 }; + let _ = &packed2.x; //~ ERROR reference to packed field + //~^ previously accepted + let _ = &packed2.y; // ok, has align 2 in packed(2) struct + let _ = &packed2.z; // ok, has align 1 + } } diff --git a/src/test/ui/lint/unaligned_references.stderr b/src/test/ui/lint/unaligned_references.stderr index 8786b9c05d..b4cce3cfea 100644 --- a/src/test/ui/lint/unaligned_references.stderr +++ b/src/test/ui/lint/unaligned_references.stderr @@ -1,5 +1,5 @@ error: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:15:17 + --> $DIR/unaligned_references.rs:22:17 | LL | let _ = &good.ptr; | ^^^^^^^^^ @@ -9,47 +9,69 @@ note: the lint level is defined here | 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/unaligned_references.rs:16:17 + --> $DIR/unaligned_references.rs:24:17 | 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/unaligned_references.rs:18:17 + --> $DIR/unaligned_references.rs:27:17 | LL | let _ = &good.data as *const _; | ^^^^^^^^^^ | + = 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/unaligned_references.rs:19:27 + --> $DIR/unaligned_references.rs:29:27 | LL | let _: *const _ = &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/unaligned_references.rs:21:17 + --> $DIR/unaligned_references.rs:32:17 | LL | let _ = good.data.clone(); | ^^^^^^^^^ | + = 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/unaligned_references.rs:23:17 + --> $DIR/unaligned_references.rs:35:17 | 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 6 previous errors +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:45:17 + | +LL | let _ = &packed2.x; + | ^^^^^^^^^^ + | + = 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 7 previous errors diff --git a/src/test/ui/lint/unaligned_references_external_macro.rs b/src/test/ui/lint/unaligned_references_external_macro.rs index 6ac501fb0e..cb597c38e7 100644 --- a/src/test/ui/lint/unaligned_references_external_macro.rs +++ b/src/test/ui/lint/unaligned_references_external_macro.rs @@ -1,10 +1,9 @@ // aux-build:unaligned_references_external_crate.rs -#![allow(safe_packed_borrows)] - extern crate unaligned_references_external_crate; unaligned_references_external_crate::mac! { //~ERROR reference to packed field is unaligned + //~^ previously accepted #[repr(packed)] pub struct X { pub field: u16 diff --git a/src/test/ui/lint/unaligned_references_external_macro.stderr b/src/test/ui/lint/unaligned_references_external_macro.stderr index 140294b65c..4e7c6bfc98 100644 --- a/src/test/ui/lint/unaligned_references_external_macro.stderr +++ b/src/test/ui/lint/unaligned_references_external_macro.stderr @@ -1,7 +1,8 @@ error: reference to packed field is unaligned - --> $DIR/unaligned_references_external_macro.rs:7:1 + --> $DIR/unaligned_references_external_macro.rs:5:1 | LL | / unaligned_references_external_crate::mac! { +LL | | LL | | #[repr(packed)] LL | | pub struct X { LL | | pub field: u16 @@ -10,15 +11,18 @@ LL | | } | |_^ | note: the lint level is defined here - --> $DIR/unaligned_references_external_macro.rs:7:1 + --> $DIR/unaligned_references_external_macro.rs:5:1 | LL | / unaligned_references_external_crate::mac! { +LL | | LL | | #[repr(packed)] LL | | pub struct X { LL | | pub field: u16 LL | | } LL | | } | |_^ + = 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) diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index 78d3060886..122933c3c4 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // This test checks that calling `mem::{uninitialized,zeroed}` with certain types results // in a lint. diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index de1b6c7617..0af185ef61 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,5 +1,5 @@ error: the type `&T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:41:32 + --> $DIR/uninitialized-zeroed.rs:40:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -8,14 +8,14 @@ LL | let _val: &'static T = mem::zeroed(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: the lint level is defined here - --> $DIR/uninitialized-zeroed.rs:7:9 + --> $DIR/uninitialized-zeroed.rs:6:9 | LL | #![deny(invalid_value)] | ^^^^^^^^^^^^^ = note: references must be non-null error: the type `&T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:42:32 + --> $DIR/uninitialized-zeroed.rs:41:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: references must be non-null error: the type `Wrap<&T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:44:38 + --> $DIR/uninitialized-zeroed.rs:43:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:18:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:45:38 + --> $DIR/uninitialized-zeroed.rs:44:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:18:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:52:23 + --> $DIR/uninitialized-zeroed.rs:51:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: the `!` type has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:53:23 + --> $DIR/uninitialized-zeroed.rs:52:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: the `!` type has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:55:30 + --> $DIR/uninitialized-zeroed.rs:54:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: the `!` type has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:56:30 + --> $DIR/uninitialized-zeroed.rs:55:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: the `!` type has no valid value error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:58:26 + --> $DIR/uninitialized-zeroed.rs:57:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _val: Void = mem::zeroed(); = note: enums with no variants have no valid value error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:59:26 + --> $DIR/uninitialized-zeroed.rs:58:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _val: Void = mem::uninitialized(); = note: enums with no variants have no valid value error: the type `&i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:61:34 + --> $DIR/uninitialized-zeroed.rs:60:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: references must be non-null error: the type `&i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:62:34 + --> $DIR/uninitialized-zeroed.rs:61:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: references must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:64:25 + --> $DIR/uninitialized-zeroed.rs:63:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -153,13 +153,13 @@ LL | let _val: Ref = mem::zeroed(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:12 + --> $DIR/uninitialized-zeroed.rs:14:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:65:25 + --> $DIR/uninitialized-zeroed.rs:64:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let _val: Ref = mem::uninitialized(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:12 + --> $DIR/uninitialized-zeroed.rs:14:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:67:26 + --> $DIR/uninitialized-zeroed.rs:66:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _val: fn() = mem::zeroed(); = note: function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:68:26 + --> $DIR/uninitialized-zeroed.rs:67:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: function pointers must be non-null error: the type `Wrap<fn()>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:70:32 + --> $DIR/uninitialized-zeroed.rs:69:32 | LL | let _val: Wrap<fn()> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -205,13 +205,13 @@ LL | let _val: Wrap<fn()> = mem::zeroed(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:18:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<fn()>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:71:32 + --> $DIR/uninitialized-zeroed.rs:70:32 | LL | let _val: Wrap<fn()> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -220,13 +220,13 @@ LL | let _val: Wrap<fn()> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:18:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum<fn()>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:73:36 + --> $DIR/uninitialized-zeroed.rs:72:36 | LL | let _val: WrapEnum<fn()> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -235,13 +235,13 @@ LL | let _val: WrapEnum<fn()> = mem::zeroed(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:19:28 + --> $DIR/uninitialized-zeroed.rs:18:28 | LL | enum WrapEnum<T> { Wrapped(T) } | ^ error: the type `WrapEnum<fn()>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:74:36 + --> $DIR/uninitialized-zeroed.rs:73:36 | LL | let _val: WrapEnum<fn()> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,13 +250,13 @@ LL | let _val: WrapEnum<fn()> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:19:28 + --> $DIR/uninitialized-zeroed.rs:18:28 | LL | enum WrapEnum<T> { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:76:42 + --> $DIR/uninitialized-zeroed.rs:75:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -265,13 +265,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:16 + --> $DIR/uninitialized-zeroed.rs:15:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:77:42 + --> $DIR/uninitialized-zeroed.rs:76:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -280,13 +280,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:16 + --> $DIR/uninitialized-zeroed.rs:15:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `NonNull<i32>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:79:34 + --> $DIR/uninitialized-zeroed.rs:78:34 | LL | let _val: NonNull<i32> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -297,7 +297,7 @@ LL | let _val: NonNull<i32> = mem::zeroed(); = note: `std::ptr::NonNull<i32>` must be non-null error: the type `NonNull<i32>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:80:34 + --> $DIR/uninitialized-zeroed.rs:79:34 | LL | let _val: NonNull<i32> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -308,7 +308,7 @@ LL | let _val: NonNull<i32> = mem::uninitialized(); = note: `std::ptr::NonNull<i32>` must be non-null error: the type `*const dyn Send` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:82:37 + --> $DIR/uninitialized-zeroed.rs:81:37 | LL | let _val: *const dyn Send = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -319,7 +319,7 @@ LL | let _val: *const dyn Send = mem::zeroed(); = note: the vtable of a wide raw pointer must be non-null error: the type `*const dyn Send` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:83:37 + --> $DIR/uninitialized-zeroed.rs:82:37 | LL | let _val: *const dyn Send = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -330,7 +330,7 @@ LL | let _val: *const dyn Send = mem::uninitialized(); = note: the vtable of a wide raw pointer must be non-null error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:87:26 + --> $DIR/uninitialized-zeroed.rs:86:26 | LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -341,7 +341,7 @@ LL | let _val: bool = mem::uninitialized(); = note: booleans must be either `true` or `false` error: the type `Wrap<char>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:90:32 + --> $DIR/uninitialized-zeroed.rs:89:32 | LL | let _val: Wrap<char> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -350,13 +350,13 @@ LL | let _val: Wrap<char> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: characters must be a valid Unicode codepoint (in this struct field) - --> $DIR/uninitialized-zeroed.rs:18:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `NonBig` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:93:28 + --> $DIR/uninitialized-zeroed.rs:92:28 | LL | let _val: NonBig = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +367,7 @@ LL | let _val: NonBig = mem::uninitialized(); = note: `NonBig` must be initialized inside its custom valid range error: the type `Fruit` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:96:27 + --> $DIR/uninitialized-zeroed.rs:95:27 | LL | let _val: Fruit = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -376,7 +376,7 @@ LL | let _val: Fruit = mem::uninitialized(); | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | note: enums have to be initialized to a variant - --> $DIR/uninitialized-zeroed.rs:27:1 + --> $DIR/uninitialized-zeroed.rs:26:1 | LL | / enum Fruit { LL | | Apple, @@ -385,7 +385,7 @@ LL | | } | |_^ error: the type `&i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:99:34 + --> $DIR/uninitialized-zeroed.rs:98:34 | LL | let _val: &'static i32 = mem::transmute(0usize); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -396,7 +396,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); = note: references must be non-null error: the type `&[i32]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:100:36 + --> $DIR/uninitialized-zeroed.rs:99:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -407,7 +407,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); = note: references must be non-null error: the type `NonZeroU32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:101:32 + --> $DIR/uninitialized-zeroed.rs:100:32 | LL | let _val: NonZeroU32 = mem::transmute(0); | ^^^^^^^^^^^^^^^^^ @@ -418,7 +418,7 @@ LL | let _val: NonZeroU32 = mem::transmute(0); = note: `std::num::NonZeroU32` must be non-null error: the type `NonNull<i32>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:104:34 + --> $DIR/uninitialized-zeroed.rs:103:34 | LL | let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -429,7 +429,7 @@ LL | let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init(); = note: `std::ptr::NonNull<i32>` must be non-null error: the type `NonNull<i32>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:105:34 + --> $DIR/uninitialized-zeroed.rs:104:34 | LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -440,7 +440,7 @@ LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init(); = note: `std::ptr::NonNull<i32>` must be non-null error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:106:26 + --> $DIR/uninitialized-zeroed.rs:105:26 | LL | let _val: bool = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs index c9e1851b9a..08911c5bde 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs @@ -1,6 +1,6 @@ fn test() { let v: isize; - //~^ HELP make this binding mutable + //~^ HELP consider making this binding mutable //~| SUGGESTION mut v loop { v = 1; //~ ERROR cannot assign twice to immutable variable `v` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr index 69dff734ee..66cdce7dac 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `v` --> $DIR/liveness-assign-imm-local-in-loop.rs:6:9 | LL | let v: isize; - | - help: make this binding mutable: `mut v` + | - help: consider making this binding mutable: `mut v` ... LL | v = 1; | ^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs index f24f7d2bcf..1752d96908 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs @@ -1,6 +1,6 @@ fn test() { let v: isize; - //~^ HELP make this binding mutable + //~^ HELP consider making this binding mutable //~| SUGGESTION mut v v = 2; //~ NOTE first assignment v += 1; //~ ERROR cannot assign twice to immutable variable `v` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr index 182958dd49..5db9539cbf 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `v` --> $DIR/liveness-assign-imm-local-in-op-eq.rs:6:5 | LL | let v: isize; - | - help: make this binding mutable: `mut v` + | - help: consider making this binding mutable: `mut v` ... LL | v = 2; | ----- first assignment to `v` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs index 8963e32717..c9b16e4391 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs @@ -1,6 +1,6 @@ fn test() { let b = Box::new(1); //~ NOTE first assignment - //~| HELP make this binding mutable + //~| HELP consider making this binding mutable //~| SUGGESTION mut b drop(b); b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr index 7c4af624b2..bb7e7e27a4 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr @@ -5,7 +5,7 @@ LL | let b = Box::new(1); | - | | | first assignment to `b` - | help: make this binding mutable: `mut b` + | help: consider making this binding mutable: `mut b` ... LL | b = Box::new(2); | ^ cannot assign twice to immutable variable diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs index 4ab222af8d..4bb2db27a1 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs @@ -1,6 +1,6 @@ fn test() { let v: isize = 1; //~ NOTE first assignment - //~| HELP make this binding mutable + //~| HELP consider making this binding mutable //~| SUGGESTION mut v v.clone(); v = 2; //~ ERROR cannot assign twice to immutable variable `v` diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr index 6f5d557487..80458a70a0 100644 --- a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr +++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr @@ -5,7 +5,7 @@ LL | let v: isize = 1; | - | | | first assignment to `v` - | help: make this binding mutable: `mut v` + | help: consider making this binding mutable: `mut v` ... LL | v = 2; | ^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/llvm-asm/llvm-asm-out-assign-imm.stderr b/src/test/ui/llvm-asm/llvm-asm-out-assign-imm.stderr index 9b0aa6be1e..3e5893f68b 100644 --- a/src/test/ui/llvm-asm/llvm-asm-out-assign-imm.stderr +++ b/src/test/ui/llvm-asm/llvm-asm-out-assign-imm.stderr @@ -2,7 +2,7 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/llvm-asm-out-assign-imm.rs:25:39 | LL | let x: isize; - | - help: make this binding mutable: `mut x` + | - help: consider making this binding mutable: `mut x` LL | x = 1; | ----- first assignment to `x` ... diff --git a/src/test/ui/loops/loop-no-implicit-break.rs b/src/test/ui/loops/loop-no-implicit-break.rs new file mode 100644 index 0000000000..93078cb4b1 --- /dev/null +++ b/src/test/ui/loops/loop-no-implicit-break.rs @@ -0,0 +1,31 @@ +fn main() { + let a: i8 = loop { + 1 //~ ERROR mismatched types + }; + + let b: i8 = loop { + break 1; + }; +} + +fn foo() -> i8 { + let a: i8 = loop { + 1 //~ ERROR mismatched types + }; + + let b: i8 = loop { + break 1; + }; + + loop { + 1 //~ ERROR mismatched types + } + + loop { + return 1; + } + + loop { + 1 //~ ERROR mismatched types + } +} diff --git a/src/test/ui/loops/loop-no-implicit-break.stderr b/src/test/ui/loops/loop-no-implicit-break.stderr new file mode 100644 index 0000000000..5087662e7b --- /dev/null +++ b/src/test/ui/loops/loop-no-implicit-break.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:3:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 1; + | ^^^^^ ^ + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:13:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 1; + | ^^^^^ ^ + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:21:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ^^^^^^ ^ + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:29:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ^^^^^^ ^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs index a0f3aeffe9..3a860f508f 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs +++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs @@ -1,6 +1,5 @@ // check-pass -// ignore-tidy-linelength // Issue #21633: reject duplicate loop labels in function bodies. // diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr index 724c36e520..6c53d04e10 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr +++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr @@ -1,5 +1,5 @@ warning: label name `'fl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:14:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:13:7 | LL | { 'fl: for _ in 0..10 { break; } } | --- first declared here @@ -7,7 +7,7 @@ LL | { 'fl: loop { break; } } | ^^^ label `'fl` already in scope warning: label name `'lf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:16:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:15:7 | LL | { 'lf: loop { break; } } | --- first declared here @@ -15,7 +15,7 @@ LL | { 'lf: for _ in 0..10 { break; } } | ^^^ label `'lf` already in scope warning: label name `'wl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:18:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:17:7 | LL | { 'wl: while 2 > 1 { break; } } | --- first declared here @@ -23,7 +23,7 @@ LL | { 'wl: loop { break; } } | ^^^ label `'wl` already in scope warning: label name `'lw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:20:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:19:7 | LL | { 'lw: loop { break; } } | --- first declared here @@ -31,7 +31,7 @@ LL | { 'lw: while 2 > 1 { break; } } | ^^^ label `'lw` already in scope warning: label name `'fw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:22:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:21:7 | LL | { 'fw: for _ in 0..10 { break; } } | --- first declared here @@ -39,7 +39,7 @@ LL | { 'fw: while 2 > 1 { break; } } | ^^^ label `'fw` already in scope warning: label name `'wf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:24:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:23:7 | LL | { 'wf: while 2 > 1 { break; } } | --- first declared here @@ -47,7 +47,7 @@ LL | { 'wf: for _ in 0..10 { break; } } | ^^^ label `'wf` already in scope warning: label name `'tl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:26:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:25:7 | LL | { 'tl: while let Some(_) = None::<i32> { break; } } | --- first declared here @@ -55,7 +55,7 @@ LL | { 'tl: loop { break; } } | ^^^ label `'tl` already in scope warning: label name `'lt` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels-2.rs:28:7 + --> $DIR/loops-reject-duplicate-labels-2.rs:27:7 | LL | { 'lt: loop { break; } } | --- first declared here diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.rs b/src/test/ui/loops/loops-reject-duplicate-labels.rs index a501ac1858..d9334ce385 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels.rs +++ b/src/test/ui/loops/loops-reject-duplicate-labels.rs @@ -1,6 +1,5 @@ // check-pass -// ignore-tidy-linelength // Issue #21633: reject duplicate loop labels in function bodies. // This is testing the exact cases that are in the issue description. diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.stderr b/src/test/ui/loops/loops-reject-duplicate-labels.stderr index 2d11281201..5bdf64849f 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels.stderr +++ b/src/test/ui/loops/loops-reject-duplicate-labels.stderr @@ -1,5 +1,5 @@ warning: label name `'fl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:11:5 + --> $DIR/loops-reject-duplicate-labels.rs:10:5 | LL | 'fl: for _ in 0..10 { break; } | --- first declared here @@ -7,7 +7,7 @@ LL | 'fl: loop { break; } | ^^^ label `'fl` already in scope warning: label name `'lf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:14:5 + --> $DIR/loops-reject-duplicate-labels.rs:13:5 | LL | 'lf: loop { break; } | --- first declared here @@ -15,7 +15,7 @@ LL | 'lf: for _ in 0..10 { break; } | ^^^ label `'lf` already in scope warning: label name `'wl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:16:5 + --> $DIR/loops-reject-duplicate-labels.rs:15:5 | LL | 'wl: while 2 > 1 { break; } | --- first declared here @@ -23,7 +23,7 @@ LL | 'wl: loop { break; } | ^^^ label `'wl` already in scope warning: label name `'lw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:18:5 + --> $DIR/loops-reject-duplicate-labels.rs:17:5 | LL | 'lw: loop { break; } | --- first declared here @@ -31,7 +31,7 @@ LL | 'lw: while 2 > 1 { break; } | ^^^ label `'lw` already in scope warning: label name `'fw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:20:5 + --> $DIR/loops-reject-duplicate-labels.rs:19:5 | LL | 'fw: for _ in 0..10 { break; } | --- first declared here @@ -39,7 +39,7 @@ LL | 'fw: while 2 > 1 { break; } | ^^^ label `'fw` already in scope warning: label name `'wf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:22:5 + --> $DIR/loops-reject-duplicate-labels.rs:21:5 | LL | 'wf: while 2 > 1 { break; } | --- first declared here @@ -47,7 +47,7 @@ LL | 'wf: for _ in 0..10 { break; } | ^^^ label `'wf` already in scope warning: label name `'tl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:24:5 + --> $DIR/loops-reject-duplicate-labels.rs:23:5 | LL | 'tl: while let Some(_) = None::<i32> { break; } | --- first declared here @@ -55,7 +55,7 @@ LL | 'tl: loop { break; } | ^^^ label `'tl` already in scope warning: label name `'lt` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:26:5 + --> $DIR/loops-reject-duplicate-labels.rs:25:5 | LL | 'lt: loop { break; } | --- first declared here diff --git a/src/test/ui/macros/attr-empty-expr.rs b/src/test/ui/macros/attr-empty-expr.rs new file mode 100644 index 0000000000..d4d1a3ee71 --- /dev/null +++ b/src/test/ui/macros/attr-empty-expr.rs @@ -0,0 +1,11 @@ +// AST-based macro attributes expanding to an empty expression produce an error and not ICE. + +#![feature(custom_test_frameworks)] +#![feature(stmt_expr_attributes)] +#![feature(test)] + +fn main() { + let _ = #[test] 0; //~ ERROR removing an expression is not supported in this position + let _ = #[bench] 1; //~ ERROR removing an expression is not supported in this position + let _ = #[test_case] 2; //~ ERROR removing an expression is not supported in this position +} diff --git a/src/test/ui/macros/attr-empty-expr.stderr b/src/test/ui/macros/attr-empty-expr.stderr new file mode 100644 index 0000000000..53721053bc --- /dev/null +++ b/src/test/ui/macros/attr-empty-expr.stderr @@ -0,0 +1,20 @@ +error: removing an expression is not supported in this position + --> $DIR/attr-empty-expr.rs:8:13 + | +LL | let _ = #[test] 0; + | ^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/attr-empty-expr.rs:9:13 + | +LL | let _ = #[bench] 1; + | ^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/attr-empty-expr.rs:10:13 + | +LL | let _ = #[test_case] 2; + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/macros/builtin-std-paths-fail.stderr b/src/test/ui/macros/builtin-std-paths-fail.stderr index 4f1a76b0d6..ba62610119 100644 --- a/src/test/ui/macros/builtin-std-paths-fail.stderr +++ b/src/test/ui/macros/builtin-std-paths-fail.stderr @@ -10,6 +10,18 @@ error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` LL | core::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:2:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:4:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + error[E0433]: failed to resolve: could not find `bench` in `core` --> $DIR/builtin-std-paths-fail.rs:7:9 | @@ -34,17 +46,17 @@ error[E0433]: failed to resolve: could not find `test` in `core` LL | #[core::test] | ^^^^ could not find `test` in `core` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:4:11 +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:14:10 | -LL | core::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:2:11 +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:16:10 | -LL | core::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` --> $DIR/builtin-std-paths-fail.rs:14:10 @@ -82,18 +94,6 @@ error[E0433]: failed to resolve: could not find `test` in `std` LL | #[std::test] | ^^^^ could not find `test` in `std` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` - --> $DIR/builtin-std-paths-fail.rs:16:10 - | -LL | std::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` - -error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` - --> $DIR/builtin-std-paths-fail.rs:14:10 - | -LL | std::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` - error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/concat-rpass.rs b/src/test/ui/macros/concat-rpass.rs similarity index 100% rename from src/test/ui/concat-rpass.rs rename to src/test/ui/macros/concat-rpass.rs diff --git a/src/test/ui/macros/edition-macro-pats.rs b/src/test/ui/macros/edition-macro-pats.rs index ea1f9bff6b..040894712a 100644 --- a/src/test/ui/macros/edition-macro-pats.rs +++ b/src/test/ui/macros/edition-macro-pats.rs @@ -1,11 +1,9 @@ // run-pass - -#![feature(or_patterns)] -#![feature(edition_macro_pats)] +// edition:2021 macro_rules! foo { - (a $x:pat2018) => {}; - (b $x:pat2021) => {}; + (a $x:pat_param) => {}; + (b $x:pat) => {}; } fn main() { diff --git a/src/test/ui/macros/issue-83340.rs b/src/test/ui/macros/issue-83340.rs new file mode 100644 index 0000000000..d26200295c --- /dev/null +++ b/src/test/ui/macros/issue-83340.rs @@ -0,0 +1,8 @@ +// check-fail + +fn main() { + println!( + "\ +\n {} │", //~ ERROR: 1 positional argument in format string, but no arguments were given + ); +} diff --git a/src/test/ui/macros/issue-83340.stderr b/src/test/ui/macros/issue-83340.stderr new file mode 100644 index 0000000000..1935de02b5 --- /dev/null +++ b/src/test/ui/macros/issue-83340.stderr @@ -0,0 +1,8 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-83340.rs:6:4 + | +LL | \n {} │", + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/macros/issue-83344.rs b/src/test/ui/macros/issue-83344.rs new file mode 100644 index 0000000000..c5f7f72358 --- /dev/null +++ b/src/test/ui/macros/issue-83344.rs @@ -0,0 +1,6 @@ +// check-fail + +fn main() { + println!("{}\ +"); //~^ ERROR: 1 positional argument in format string, but no arguments were given +} diff --git a/src/test/ui/macros/issue-83344.stderr b/src/test/ui/macros/issue-83344.stderr new file mode 100644 index 0000000000..1ef70f87a1 --- /dev/null +++ b/src/test/ui/macros/issue-83344.stderr @@ -0,0 +1,8 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-83344.rs:4:15 + | +LL | println!("{}\ + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/macros/issue-84195-lint-anon-const.rs b/src/test/ui/macros/issue-84195-lint-anon-const.rs new file mode 100644 index 0000000000..71c7683201 --- /dev/null +++ b/src/test/ui/macros/issue-84195-lint-anon-const.rs @@ -0,0 +1,14 @@ +// Regression test for issue #84195 +// Checks that we properly fire lints that occur inside +// anon consts. + +#![deny(semicolon_in_expressions_from_macros)] + +macro_rules! len { + () => { 0; }; //~ ERROR trailing semicolon + //~| WARN this was previously accepted +} + +fn main() { + let val: [u8; len!()] = []; +} diff --git a/src/test/ui/macros/issue-84195-lint-anon-const.stderr b/src/test/ui/macros/issue-84195-lint-anon-const.stderr new file mode 100644 index 0000000000..558e0349e2 --- /dev/null +++ b/src/test/ui/macros/issue-84195-lint-anon-const.stderr @@ -0,0 +1,20 @@ +error: trailing semicolon in macro used in expression position + --> $DIR/issue-84195-lint-anon-const.rs:8:14 + | +LL | () => { 0; }; + | ^ +... +LL | let val: [u8; len!()] = []; + | ------ in this macro invocation + | +note: the lint level is defined here + --> $DIR/issue-84195-lint-anon-const.rs:5:9 + | +LL | #![deny(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/macros/issue-85432-ungated-attr-macro.rs b/src/test/ui/macros/issue-85432-ungated-attr-macro.rs new file mode 100644 index 0000000000..bac124c6f4 --- /dev/null +++ b/src/test/ui/macros/issue-85432-ungated-attr-macro.rs @@ -0,0 +1,30 @@ +// check-pass +// Regression test for issue #85432 +// Ensures that we don't incorrectly gate nonterminals +// in key-value macros when we need to reparse due to +// the presence of `#[derive]` + +macro_rules! with_doc_comment { + ($comment:expr, $item:item) => { + #[doc = $comment] + $item + }; +} + +macro_rules! database_table_doc { + () => { + "" + }; +} + +with_doc_comment! { + database_table_doc!(), + #[derive(Debug)] + struct Image { + #[cfg(FALSE)] + _f: (), + } + +} + +fn main() {} diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.rs b/src/test/ui/macros/macro-export-on-modularized-macros.rs deleted file mode 100644 index 467c6ba7b7..0000000000 --- a/src/test/ui/macros/macro-export-on-modularized-macros.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(decl_macro)] -#![feature(pub_macro_rules)] - -#[macro_export] -macro m1() {} //~ ERROR `#[macro_export]` cannot be used on `macro` items - -#[macro_export] -pub macro_rules! m2 { () => {} } -//~^ ERROR `#[macro_export]` cannot be used on `macro_rules` with `pub` - -fn main() {} diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.stderr b/src/test/ui/macros/macro-export-on-modularized-macros.stderr deleted file mode 100644 index 8bb031e12c..0000000000 --- a/src/test/ui/macros/macro-export-on-modularized-macros.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: `#[macro_export]` cannot be used on `macro` items - --> $DIR/macro-export-on-modularized-macros.rs:5:1 - | -LL | macro m1() {} - | ^^^^^^^^^^^^^ - -error: `#[macro_export]` cannot be used on `macro_rules` with `pub` - --> $DIR/macro-export-on-modularized-macros.rs:8:1 - | -LL | pub macro_rules! m2 { () => {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.fixed b/src/test/ui/macros/macro-or-patterns-back-compat.fixed new file mode 100644 index 0000000000..f829129d51 --- /dev/null +++ b/src/test/ui/macros/macro-or-patterns-back-compat.fixed @@ -0,0 +1,24 @@ +// run-rustfix + +#![deny(or_patterns_back_compat)] +#![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_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! 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 + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +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); +} diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.rs b/src/test/ui/macros/macro-or-patterns-back-compat.rs new file mode 100644 index 0000000000..1cdaa1cd63 --- /dev/null +++ b/src/test/ui/macros/macro-or-patterns-back-compat.rs @@ -0,0 +1,24 @@ +// run-rustfix + +#![deny(or_patterns_back_compat)] +#![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_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! 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 + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +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); +} diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.stderr b/src/test/ui/macros/macro-or-patterns-back-compat.stderr new file mode 100644 index 0000000000..01d220dd0b --- /dev/null +++ b/src/test/ui/macros/macro-or-patterns-back-compat.stderr @@ -0,0 +1,32 @@ +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 + | +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 + | +LL | #![deny(or_patterns_back_compat)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +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 + | +LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } + | ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param` + +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 + | +LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} } + | ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param` + +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 + | +LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + | ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs new file mode 100644 index 0000000000..f5a97eca21 --- /dev/null +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs @@ -0,0 +1,20 @@ +// edition:2021 +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +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); +} diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr new file mode 100644 index 0000000000..a5987a2555 --- /dev/null +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr @@ -0,0 +1,26 @@ +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:3:28 + | +LL | macro_rules! foo { ($x:pat | $y:pat) => {} } + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32 + | +LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36 + | +LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs new file mode 100644 index 0000000000..54bd13d7eb --- /dev/null +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } // should be ok +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } // should be ok +macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { // should be ok + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +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); +} diff --git a/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs new file mode 100644 index 0000000000..b4be03aadd --- /dev/null +++ b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs @@ -0,0 +1,22 @@ +// edition:2021 + +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +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 `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat)|+ => $expr_arm:pat),+ ) => { //~ ERROR `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +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); +} diff --git a/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr new file mode 100644 index 0000000000..8aebe98515 --- /dev/null +++ b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr @@ -0,0 +1,26 @@ +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:4:28 + | +LL | macro_rules! foo { ($x:pat | $y:pat) => {} } + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:7:28 + | +LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} } + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:9:35 + | +LL | ( $expr:expr , $( $( $pat:pat)|+ => $expr_arm:pat),+ ) => { + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/macros/none-delim-lookahead.rs b/src/test/ui/macros/none-delim-lookahead.rs new file mode 100644 index 0000000000..bf4fddea14 --- /dev/null +++ b/src/test/ui/macros/none-delim-lookahead.rs @@ -0,0 +1,15 @@ +// check-pass + +macro_rules! make_struct { + ($name:ident) => { + #[derive(Debug)] + struct Foo { + #[cfg(not(FALSE))] + field: fn($name: bool) + } + } +} + +make_struct!(param_name); + +fn main() {} diff --git a/src/test/ui/macros/pub-macro-rules-fail.rs b/src/test/ui/macros/pub-macro-rules-fail.rs deleted file mode 100644 index bdb4c73f18..0000000000 --- a/src/test/ui/macros/pub-macro-rules-fail.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![feature(pub_macro_rules)] - -#[macro_use] -mod m { - pub macro_rules! mac { () => {} } - - // `pub` `macro_rules` cannot be redefined in the same module. - pub macro_rules! mac { () => {} } //~ ERROR the name `mac` is defined multiple times - - pub(self) macro_rules! private_mac { () => {} } -} - -const _: () = { - pub macro_rules! block_mac { () => {} } -}; - -mod n { - // Scope of `pub` `macro_rules` is not extended by `#[macro_use]`. - mac!(); //~ ERROR cannot find macro `mac` in this scope - - // `pub` `macro_rules` doesn't put the macro into the root module, unlike `#[macro_export]`. - crate::mac!(); //~ ERROR failed to resolve: maybe a missing crate `mac` - crate::block_mac!(); //~ ERROR failed to resolve: maybe a missing crate `block_mac` - - crate::m::private_mac!(); //~ ERROR macro `private_mac` is private -} - -fn main() {} diff --git a/src/test/ui/macros/pub-macro-rules-fail.stderr b/src/test/ui/macros/pub-macro-rules-fail.stderr deleted file mode 100644 index 588d79dd76..0000000000 --- a/src/test/ui/macros/pub-macro-rules-fail.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0428]: the name `mac` is defined multiple times - --> $DIR/pub-macro-rules-fail.rs:8:5 - | -LL | pub macro_rules! mac { () => {} } - | -------------------- previous definition of the macro `mac` here -... -LL | pub macro_rules! mac { () => {} } - | ^^^^^^^^^^^^^^^^^^^^ `mac` redefined here - | - = note: `mac` must be defined only once in the macro namespace of this module - -error[E0433]: failed to resolve: maybe a missing crate `mac`? - --> $DIR/pub-macro-rules-fail.rs:22:12 - | -LL | crate::mac!(); - | ^^^ maybe a missing crate `mac`? - -error[E0433]: failed to resolve: maybe a missing crate `block_mac`? - --> $DIR/pub-macro-rules-fail.rs:23:12 - | -LL | crate::block_mac!(); - | ^^^^^^^^^ maybe a missing crate `block_mac`? - -error: cannot find macro `mac` in this scope - --> $DIR/pub-macro-rules-fail.rs:19:5 - | -LL | mac!(); - | ^^^ - | - = note: consider importing this macro: - m::mac - -error[E0603]: macro `private_mac` is private - --> $DIR/pub-macro-rules-fail.rs:25:15 - | -LL | crate::m::private_mac!(); - | ^^^^^^^^^^^ private macro - | -note: the macro `private_mac` is defined here - --> $DIR/pub-macro-rules-fail.rs:10:5 - | -LL | pub(self) macro_rules! private_mac { () => {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0428, E0433, E0603. -For more information about an error, try `rustc --explain E0428`. diff --git a/src/test/ui/macros/pub-macro-rules.rs b/src/test/ui/macros/pub-macro-rules.rs deleted file mode 100644 index cd4a845f7c..0000000000 --- a/src/test/ui/macros/pub-macro-rules.rs +++ /dev/null @@ -1,20 +0,0 @@ -// check-pass - -#![feature(pub_macro_rules)] - -mod m { - // `pub` `macro_rules` can be used earlier in item order than they are defined. - foo!(); - - pub macro_rules! foo { () => {} } - - // `pub(...)` works too. - pub(super) macro_rules! bar { () => {} } -} - -// `pub` `macro_rules` are available by module path. -m::foo!(); - -m::bar!(); - -fn main() {} diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs index f75d08813c..f3acd80a7a 100644 --- a/src/test/ui/main-wrong-location.rs +++ b/src/test/ui/main-wrong-location.rs @@ -1,6 +1,6 @@ mod m { //~^ ERROR `main` function not found - // An inferred main entry point (that doesn't use #[main]) + // An inferred main entry point // must appear at the top of the crate fn main() { } } diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr index e301c2ff09..754ff0f80e 100644 --- a/src/test/ui/main-wrong-location.stderr +++ b/src/test/ui/main-wrong-location.stderr @@ -3,7 +3,7 @@ error[E0601]: `main` function not found in crate `main_wrong_location` | LL | / mod m { LL | | -LL | | // An inferred main entry point (that doesn't use #[main]) +LL | | // An inferred main entry point LL | | // must appear at the top of the crate LL | | fn main() { } LL | | } @@ -15,7 +15,7 @@ note: here is a function named `main` LL | fn main() { } | ^^^^^^^^^^^^^ = note: you have one or more functions named `main` not defined at the crate level - = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them + = help: consider moving the `main` function definitions error: aborting due to previous error diff --git a/src/test/ui/match/issue-72680.rs b/src/test/ui/match/issue-72680.rs index 5b933edc82..c13cace760 100644 --- a/src/test/ui/match/issue-72680.rs +++ b/src/test/ui/match/issue-72680.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(or_patterns)] - fn main() { assert!(f("", 0)); assert!(f("a", 1)); diff --git a/src/test/ui/match/issue-82392.rs b/src/test/ui/match/issue-82392.rs new file mode 100644 index 0000000000..d26d883040 --- /dev/null +++ b/src/test/ui/match/issue-82392.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() { + if true { + } else if let Some(a) = Some(3) { + } +} diff --git a/src/test/ui/match/issue-82392.stdout b/src/test/ui/match/issue-82392.stdout new file mode 100644 index 0000000000..8ff76c64fc --- /dev/null +++ b/src/test/ui/match/issue-82392.stdout @@ -0,0 +1,20 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() ({ + (if (true as bool) + ({ } as + ()) else {match ((Some as + fn(i32) -> Option<i32> {Option::<i32>::Some})((3 + as + i32)) + as Option<i32>) { + Some(a) => { } + _ => { } + }} as ()) + } as ()) diff --git a/src/test/ui/match/issue-84434.rs b/src/test/ui/match/issue-84434.rs new file mode 100644 index 0000000000..423481fd5f --- /dev/null +++ b/src/test/ui/match/issue-84434.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/84434 +// check-pass + +use std::path::Path; +struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), +} +const MY_A: A = A { + func: |check, a, b| { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }, +}; + +fn main() {} diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.rs b/src/test/ui/methods/method-call-lifetime-args-fail.rs index 8a840ba62c..af17385125 100644 --- a/src/test/ui/methods/method-call-lifetime-args-fail.rs +++ b/src/test/ui/methods/method-call-lifetime-args-fail.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - struct S; impl S { diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-fail.stderr index 34a2e3dec2..2907309c27 100644 --- a/src/test/ui/methods/method-call-lifetime-args-fail.stderr +++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr @@ -1,5 +1,5 @@ error[E0107]: this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied - --> $DIR/method-call-lifetime-args-fail.rs:18:7 + --> $DIR/method-call-lifetime-args-fail.rs:16:7 | LL | S.early::<'static>(); | ^^^^^ ------- supplied 1 lifetime argument @@ -7,7 +7,7 @@ LL | S.early::<'static>(); | expected 2 lifetime arguments | note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/method-call-lifetime-args-fail.rs:8:8 + --> $DIR/method-call-lifetime-args-fail.rs:6:8 | LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } | ^^^^^ -- -- @@ -17,7 +17,7 @@ LL | S.early::<'static, 'b>(); | ^^^^ error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied - --> $DIR/method-call-lifetime-args-fail.rs:20:7 + --> $DIR/method-call-lifetime-args-fail.rs:18:7 | LL | S.early::<'static, 'static, 'static>(); | ^^^^^ --------- help: remove this lifetime argument @@ -25,181 +25,181 @@ LL | S.early::<'static, 'static, 'static>(); | expected 2 lifetime arguments | note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/method-call-lifetime-args-fail.rs:8:8 + --> $DIR/method-call-lifetime-args-fail.rs:6:8 | LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } | ^^^^^ -- -- error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:29:15 + --> $DIR/method-call-lifetime-args-fail.rs:27:15 | LL | S::late::<'static>(S, &0, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:6:13 + --> $DIR/method-call-lifetime-args-fail.rs:4:13 | LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} | ^^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:31:15 + --> $DIR/method-call-lifetime-args-fail.rs:29:15 | LL | S::late::<'static, 'static>(S, &0, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:6:13 + --> $DIR/method-call-lifetime-args-fail.rs:4:13 | LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} | ^^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:33:15 + --> $DIR/method-call-lifetime-args-fail.rs:31:15 | LL | S::late::<'static, 'static, 'static>(S, &0, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:6:13 + --> $DIR/method-call-lifetime-args-fail.rs:4:13 | LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} | ^^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:36:21 + --> $DIR/method-call-lifetime-args-fail.rs:34:21 | LL | S::late_early::<'static, 'static>(S, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:9:19 + --> $DIR/method-call-lifetime-args-fail.rs:7:19 | LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } | ^^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:38:21 + --> $DIR/method-call-lifetime-args-fail.rs:36:21 | LL | S::late_early::<'static, 'static, 'static>(S, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:9:19 + --> $DIR/method-call-lifetime-args-fail.rs:7:19 | LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } | ^^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:42:24 + --> $DIR/method-call-lifetime-args-fail.rs:40:24 | LL | S::late_implicit::<'static>(S, &0, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:7:31 + --> $DIR/method-call-lifetime-args-fail.rs:5:31 | LL | fn late_implicit(self, _: &u8, _: &u8) {} | ^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:44:24 + --> $DIR/method-call-lifetime-args-fail.rs:42:24 | LL | S::late_implicit::<'static, 'static>(S, &0, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:7:31 + --> $DIR/method-call-lifetime-args-fail.rs:5:31 | LL | fn late_implicit(self, _: &u8, _: &u8) {} | ^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:46:24 + --> $DIR/method-call-lifetime-args-fail.rs:44:24 | LL | S::late_implicit::<'static, 'static, 'static>(S, &0, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:7:31 + --> $DIR/method-call-lifetime-args-fail.rs:5:31 | LL | fn late_implicit(self, _: &u8, _: &u8) {} | ^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:49:30 + --> $DIR/method-call-lifetime-args-fail.rs:47:30 | LL | S::late_implicit_early::<'static, 'static>(S, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:10:41 + --> $DIR/method-call-lifetime-args-fail.rs:8:41 | LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } | ^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:51:30 + --> $DIR/method-call-lifetime-args-fail.rs:49:30 | LL | S::late_implicit_early::<'static, 'static, 'static>(S, &0); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:10:41 + --> $DIR/method-call-lifetime-args-fail.rs:8:41 | LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } | ^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:54:35 + --> $DIR/method-call-lifetime-args-fail.rs:52:35 | LL | S::late_implicit_self_early::<'static, 'static>(&S); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:11:37 + --> $DIR/method-call-lifetime-args-fail.rs:9:37 | LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } | ^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:56:35 + --> $DIR/method-call-lifetime-args-fail.rs:54:35 | LL | S::late_implicit_self_early::<'static, 'static, 'static>(&S); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:11:37 + --> $DIR/method-call-lifetime-args-fail.rs:9:37 | LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } | ^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:59:28 + --> $DIR/method-call-lifetime-args-fail.rs:57:28 | LL | S::late_unused_early::<'static, 'static>(S); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:12:26 + --> $DIR/method-call-lifetime-args-fail.rs:10:26 | LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} } | ^^ error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-fail.rs:61:28 + --> $DIR/method-call-lifetime-args-fail.rs:59:28 | LL | S::late_unused_early::<'static, 'static, 'static>(S); | ^^^^^^^ | note: the late bound lifetime parameter is introduced here - --> $DIR/method-call-lifetime-args-fail.rs:12:26 + --> $DIR/method-call-lifetime-args-fail.rs:10:26 | LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} } | ^^ error[E0107]: this associated function takes 2 lifetime arguments but only 1 lifetime argument was supplied - --> $DIR/method-call-lifetime-args-fail.rs:65:8 + --> $DIR/method-call-lifetime-args-fail.rs:63:8 | LL | S::early::<'static>(S); | ^^^^^ ------- supplied 1 lifetime argument @@ -207,7 +207,7 @@ LL | S::early::<'static>(S); | expected 2 lifetime arguments | note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/method-call-lifetime-args-fail.rs:8:8 + --> $DIR/method-call-lifetime-args-fail.rs:6:8 | LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } | ^^^^^ -- -- @@ -217,7 +217,7 @@ LL | S::early::<'static, 'b>(S); | ^^^^ error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied - --> $DIR/method-call-lifetime-args-fail.rs:67:8 + --> $DIR/method-call-lifetime-args-fail.rs:65:8 | LL | S::early::<'static, 'static, 'static>(S); | ^^^^^ --------- help: remove this lifetime argument @@ -225,7 +225,7 @@ LL | S::early::<'static, 'static, 'static>(S); | expected 2 lifetime arguments | note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/method-call-lifetime-args-fail.rs:8:8 + --> $DIR/method-call-lifetime-args-fail.rs:6:8 | LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } | ^^^^^ -- -- diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs new file mode 100644 index 0000000000..4d404d015e --- /dev/null +++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs @@ -0,0 +1,10 @@ +// Test that when in MIR the amount of local_decls and amount of normalized_input_tys don't match +// that an out-of-bounds access does not occur. +#![feature(c_variadic)] + +fn main() {} + +fn foo(_: Bar, ...) -> impl {} +//~^ 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 diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr new file mode 100644 index 0000000000..eb17268489 --- /dev/null +++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -0,0 +1,21 @@ +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 {} + | ^^^ + +error: at least one trait must be specified + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:24 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^^ + +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:11 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr index e0a3ce922b..6ce8126b9f 100644 --- a/src/test/ui/mismatched_types/E0053.stderr +++ b/src/test/ui/mismatched_types/E0053.stderr @@ -5,7 +5,10 @@ LL | fn foo(x: u16); | --- type in trait ... LL | fn foo(x: i16) { } - | ^^^ expected `u16`, found `i16` + | ^^^ + | | + | expected `u16`, found `i16` + | help: change the parameter type to match the trait: `u16` | = note: expected fn pointer `fn(u16)` found fn pointer `fn(i16)` @@ -20,7 +23,7 @@ LL | fn bar(&mut self) { } | ^^^^^^^^^ | | | types differ in mutability - | help: consider changing the mutability to match the trait: `&self` + | help: change the self-receiver type to match the trait: `self: &Bar` | = note: expected fn pointer `fn(&Bar)` found fn pointer `fn(&mut Bar)` diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs index 0e3ea4bc8c..6aa34354a7 100644 --- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs +++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs @@ -8,7 +8,7 @@ struct ChunkingIterator<T, S: 'static + Iterator<Item = T>> { impl<T, S: Iterator<Item = T>> Iterator for ChunkingIterator<T, S> { type Item = IteratorChunk<T, S>; //~ ERROR missing lifetime - fn next(&mut self) -> Option<IteratorChunk<T, S>> { //~ ERROR `impl` + fn next(&mut self) -> Option<IteratorChunk<T, S>> { todo!() } } diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr index 5df35fa571..1e035ff99d 100644 --- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr +++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr @@ -9,22 +9,6 @@ help: consider introducing a named lifetime parameter LL | type Item<'a> = IteratorChunk<'a, T, S>; | ^^^^ ^^^ -error: `impl` item signature doesn't match `trait` item signature - --> $DIR/issue-74918-missing-lifetime.rs:11:5 - | -LL | fn next(&mut self) -> Option<IteratorChunk<T, S>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'_, T, S>>` - | - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | -LL | fn next(&mut self) -> Option<Self::Item>; - | ----------------------------------------- expected `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, _, _>>` - | - = note: expected `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, _, _>>` - found `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'_, _, _>>` - = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr index 161843473b..2ac4d1c33a 100644 --- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr +++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -5,7 +5,10 @@ LL | fn foo(x: u16); | --- type in trait ... LL | fn foo(x: i16) { } - | ^^^ expected `u16`, found `i16` + | ^^^ + | | + | expected `u16`, found `i16` + | help: change the parameter type to match the trait: `u16` | = note: expected fn pointer `fn(u16)` found fn pointer `fn(i16)` @@ -20,7 +23,7 @@ LL | fn bar(&mut self, bar: &Bar) { } | ^^^^ | | | types differ in mutability - | help: consider changing the mutability to match the trait: `&mut Bar` + | help: change the parameter type to match the trait: `&mut Bar` | = note: expected fn pointer `fn(&mut Bar, &mut Bar)` found fn pointer `fn(&mut Bar, &Bar)` diff --git a/src/test/ui/multiple-main-2.rs b/src/test/ui/multiple-main-2.rs deleted file mode 100644 index e4685b1e00..0000000000 --- a/src/test/ui/multiple-main-2.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(main)] - -#[main] -fn bar() { -} - -#[main] -fn foo() { //~ ERROR multiple functions with a `#[main]` attribute -} diff --git a/src/test/ui/multiple-main-2.stderr b/src/test/ui/multiple-main-2.stderr deleted file mode 100644 index 24bc9a8878..0000000000 --- a/src/test/ui/multiple-main-2.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0137]: multiple functions with a `#[main]` attribute - --> $DIR/multiple-main-2.rs:8:1 - | -LL | / fn bar() { -LL | | } - | |_- first `#[main]` function -... -LL | / fn foo() { -LL | | } - | |_^ additional `#[main]` function - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0137`. diff --git a/src/test/ui/multiple-main-3.rs b/src/test/ui/multiple-main-3.rs deleted file mode 100644 index d1b5ae9a83..0000000000 --- a/src/test/ui/multiple-main-3.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(main)] - -#[main] -fn main1() { -} - -mod foo { - #[main] - fn main2() { //~ ERROR multiple functions with a `#[main]` attribute - } -} diff --git a/src/test/ui/multiple-main-3.stderr b/src/test/ui/multiple-main-3.stderr deleted file mode 100644 index ec171b76a2..0000000000 --- a/src/test/ui/multiple-main-3.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0137]: multiple functions with a `#[main]` attribute - --> $DIR/multiple-main-3.rs:9:5 - | -LL | / fn main1() { -LL | | } - | |_- first `#[main]` function -... -LL | / fn main2() { -LL | | } - | |_____^ additional `#[main]` function - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0137`. diff --git a/src/test/ui/mut/mut-pattern-internal-mutability.stderr b/src/test/ui/mut/mut-pattern-internal-mutability.stderr index eaa33453a7..6583546aa5 100644 --- a/src/test/ui/mut/mut-pattern-internal-mutability.stderr +++ b/src/test/ui/mut/mut-pattern-internal-mutability.stderr @@ -5,7 +5,7 @@ LL | let &mut x = foo; | - | | | first assignment to `x` - | help: make this binding mutable: `mut x` + | help: consider making this binding mutable: `mut x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/mut/mutable-enum-indirect.stderr b/src/test/ui/mut/mutable-enum-indirect.stderr index 3be6acb41a..5b26f94115 100644 --- a/src/test/ui/mut/mutable-enum-indirect.stderr +++ b/src/test/ui/mut/mutable-enum-indirect.stderr @@ -8,7 +8,11 @@ LL | bar(&x); | ^^^ `NoSync` cannot be shared between threads safely | = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/mutable-enum-indirect.rs:11:6 + | +LL | enum Foo { A(NoSync) } + | ^^^ = note: required because it appears within the type `&Foo` error: aborting due to previous error diff --git a/src/test/ui/never_type/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs index c96c4784dc..6979c3ec44 100644 --- a/src/test/ui/never_type/defaulted-never-note.rs +++ b/src/test/ui/never_type/defaulted-never-note.rs @@ -26,7 +26,9 @@ fn smeg() { foo(_x); //~^ ERROR the trait bound //~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented - //~| NOTE the trait is implemented for `()` + //~| NOTE this trait is implemented for `()` + //~| NOTE this error might have been caused + //~| HELP did you intend } fn main() { diff --git a/src/test/ui/never_type/defaulted-never-note.stderr b/src/test/ui/never_type/defaulted-never-note.stderr index 69691883de..9973837502 100644 --- a/src/test/ui/never_type/defaulted-never-note.stderr +++ b/src/test/ui/never_type/defaulted-never-note.stderr @@ -7,7 +7,9 @@ LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {} LL | foo(_x); | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` | - = note: the trait is implemented for `()`. Possibly this error has been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information). Consider whether you meant to use the type `()` here instead. + = note: this trait is implemented for `()`. + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information). + = help: did you intend to use the type `()` here instead? error: aborting due to previous error diff --git a/src/test/ui/never_type/never-from-impl-is-reserved.stderr b/src/test/ui/never_type/never-from-impl-is-reserved.stderr index 8b8d0f4ea7..871c512052 100644 --- a/src/test/ui/never_type/never-from-impl-is-reserved.stderr +++ b/src/test/ui/never_type/never-from-impl-is-reserved.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo`: +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo` --> $DIR/never-from-impl-is-reserved.rs:10:1 | LL | impl MyTrait for MyFoo {} diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 4e122d930f..ff16bf0e07 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) i32)), + for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) i32)), (), ] diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index 44d1d2327f..22398f0857 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)), + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)), (), ] diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index fa9f994c4f..11420efaa0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -10,7 +10,7 @@ LL | | }, | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#4r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 0555f79bcb..98c3c28fb4 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 0932f94154..30ef343b26 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -10,7 +10,7 @@ LL | | }) | = note: defining type: case1::{closure#0} with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)), + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)), (), ] @@ -49,7 +49,7 @@ LL | | }) | = note: defining type: case2::{closure#0} with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)), + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)), (), ] = note: number of external vids: 2 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index bf6e2a922e..29993b129c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -12,7 +12,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) u32>)), + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index a3d993848c..cb505d8b1e 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -12,7 +12,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 60dca1baa4..2ec9d4d8db 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index cbb10eb187..21e4232c78 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -10,7 +10,7 @@ LL | | }, | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index f9f1d8bb6f..8b9b043542 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 1587c28e1b..060ce690f0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 44f743310b..5fc1d5c436 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, (), ] diff --git a/src/test/ui/nll/issue-51268.rs b/src/test/ui/nll/issue-51268.rs index 12d0449abb..dcdedf7d4c 100644 --- a/src/test/ui/nll/issue-51268.rs +++ b/src/test/ui/nll/issue-51268.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - struct Bar; impl Bar { diff --git a/src/test/ui/nll/issue-51268.stderr b/src/test/ui/nll/issue-51268.stderr index 420c94f8e1..e6dadc9f6c 100644 --- a/src/test/ui/nll/issue-51268.stderr +++ b/src/test/ui/nll/issue-51268.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `self.thing` as mutable because it is also borrowed as immutable - --> $DIR/issue-51268.rs:16:9 + --> $DIR/issue-51268.rs:14:9 | LL | self.thing.bar(|| { | ^ --- -- immutable borrow occurs here diff --git a/src/test/ui/nll/issue-57100.rs b/src/test/ui/nll/issue-57100.rs index c7f3e9d730..f15929334b 100644 --- a/src/test/ui/nll/issue-57100.rs +++ b/src/test/ui/nll/issue-57100.rs @@ -1,6 +1,5 @@ #![allow(unused)] -// ignore-tidy-linelength // This tests the error messages for borrows of union fields when the unions are embedded in other // structs or unions. diff --git a/src/test/ui/nll/issue-57100.stderr b/src/test/ui/nll/issue-57100.stderr index 5f733c1403..523c3e8d0a 100644 --- a/src/test/ui/nll/issue-57100.stderr +++ b/src/test/ui/nll/issue-57100.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`) - --> $DIR/issue-57100.rs:43:20 + --> $DIR/issue-57100.rs:42:20 | LL | let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8; | -------------------------------------- mutable borrow occurs here (via `r.r2_union.f3_union.s1_leaf.l1_u8`) @@ -13,7 +13,7 @@ LL | println!("{} {}", mref, nref) = note: `r.r2_union.f3_union.s2_leaf.l1_u8` is a field of the union `Second`, so it overlaps the field `r.r2_union.f3_union.s1_leaf.l1_u8` error[E0502]: cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`) - --> $DIR/issue-57100.rs:61:20 + --> $DIR/issue-57100.rs:60:20 | LL | let mref = &mut r.r2_union.f2_leaf.l1_u8; | ----------------------------- mutable borrow occurs here (via `r.r2_union.f2_leaf.l1_u8`) diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index dbf76cd132..baf223b786 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::<T>::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)), + for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), (), ] = note: number of external vids: 2 @@ -31,7 +31,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::<T>::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)), + for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr index ef7fb4ad7b..2ee32029b4 100644 --- a/src/test/ui/no-send-res-ports.stderr +++ b/src/test/ui/no-send-res-ports.stderr @@ -17,8 +17,16 @@ LL | F: Send + 'static, | ---- required by this bound in `spawn` | = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]`, the trait `Send` is not implemented for `Rc<()>` - = note: required because it appears within the type `Port<()>` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Port<()>` + --> $DIR/no-send-res-ports.rs:5:8 + | +LL | struct Port<T>(Rc<T>); + | ^^^^ +note: required because it appears within the type `Foo` + --> $DIR/no-send-res-ports.rs:9:12 + | +LL | struct Foo { + | ^^^ = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]` error: aborting due to previous error diff --git a/src/test/ui/no_send-enum.stderr b/src/test/ui/no_send-enum.stderr index b617fe410f..9d755839d3 100644 --- a/src/test/ui/no_send-enum.stderr +++ b/src/test/ui/no_send-enum.stderr @@ -8,7 +8,11 @@ LL | bar(x); | ^^^ `NoSend` cannot be sent between threads safely | = help: within `Foo`, the trait `Send` is not implemented for `NoSend` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/no_send-enum.rs:8:6 + | +LL | enum Foo { + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/no_share-enum.stderr b/src/test/ui/no_share-enum.stderr index 4a93edc100..a8ab69200e 100644 --- a/src/test/ui/no_share-enum.stderr +++ b/src/test/ui/no_share-enum.stderr @@ -8,7 +8,11 @@ LL | bar(x); | ^^^ `NoSync` cannot be shared between threads safely | = help: within `Foo`, the trait `Sync` is not implemented for `NoSync` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/no_share-enum.rs:8:6 + | +LL | enum Foo { A(NoSync) } + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr index 8395a3a056..99af04e7cd 100644 --- a/src/test/ui/non-copyable-void.stderr +++ b/src/test/ui/non-copyable-void.stderr @@ -3,14 +3,6 @@ error[E0599]: no method named `clone` found for enum `c_void` in the current sco | LL | let _z = (*y).clone(); | ^^^^^ method not found in `c_void` - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<c_void>` here - | the method is available for `Rc<c_void>` here error: aborting due to previous error diff --git a/src/test/ui/non-ice-error-on-worker-io-fail.rs b/src/test/ui/non-ice-error-on-worker-io-fail.rs index 30779fc65c..134e7d420e 100644 --- a/src/test/ui/non-ice-error-on-worker-io-fail.rs +++ b/src/test/ui/non-ice-error-on-worker-io-fail.rs @@ -24,7 +24,6 @@ // On Linux, we get an error like the below // normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /does-not-exist/" -// ignore-tidy-linelength // ignore-windows - this is a unix-specific test // ignore-emscripten - the file-system issues do not replicate here // ignore-wasm - the file-system issues do not replicate here diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr index b8e467d840..4674c16eb4 100644 --- a/src/test/ui/noncopyable-class.stderr +++ b/src/test/ui/noncopyable-class.stderr @@ -6,14 +6,6 @@ LL | struct Foo { ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Foo>` here - | the method is available for `Rc<Foo>` here | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/or-patterns/already-bound-name.rs b/src/test/ui/or-patterns/already-bound-name.rs index 543d7c21c8..65c25293d9 100644 --- a/src/test/ui/or-patterns/already-bound-name.rs +++ b/src/test/ui/or-patterns/already-bound-name.rs @@ -1,8 +1,6 @@ // This test ensures that the "already bound identifier in a product pattern" // correctly accounts for or-patterns. -#![feature(or_patterns)] - enum E<T> { A(T, T), B(T) } use E::*; diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr index 483154a5e3..6611216562 100644 --- a/src/test/ui/or-patterns/already-bound-name.stderr +++ b/src/test/ui/or-patterns/already-bound-name.stderr @@ -1,89 +1,89 @@ error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:11:13 + --> $DIR/already-bound-name.rs:9:13 | LL | let (a, a) = (0, 1); // Standard duplication without an or-pattern. | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:14:15 + --> $DIR/already-bound-name.rs:12:15 | LL | let (a, A(a, _) | B(a)) = (0, A(1, 2)); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:14:25 + --> $DIR/already-bound-name.rs:12:25 | LL | let (a, A(a, _) | B(a)) = (0, A(1, 2)); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:18:26 + --> $DIR/already-bound-name.rs:16:26 | LL | let (A(a, _) | B(a), a) = (A(0, 1), 2); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:21:15 + --> $DIR/already-bound-name.rs:19:15 | LL | let (A(a, a) | B(a)) = A(0, 1); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:24:22 + --> $DIR/already-bound-name.rs:22:22 | LL | let (B(a) | A(a, a)) = A(0, 1); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:28:21 + --> $DIR/already-bound-name.rs:26:21 | LL | B(a) | A(a, a) => {} // Let's ensure `match` has no funny business. | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:32:37 + --> $DIR/already-bound-name.rs:30:37 | LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:32:47 + --> $DIR/already-bound-name.rs:30:47 | LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:37:37 + --> $DIR/already-bound-name.rs:35:37 | LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:37:47 + --> $DIR/already-bound-name.rs:35:47 | LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); | ^ used in a pattern more than once error[E0408]: variable `a` is not bound in all patterns - --> $DIR/already-bound-name.rs:37:10 + --> $DIR/already-bound-name.rs:35:10 | LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); | ^^^^ pattern doesn't bind `a` - variable not in all patterns error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:42:50 + --> $DIR/already-bound-name.rs:40:50 | LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:42:60 + --> $DIR/already-bound-name.rs:40:60 | LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); | ^ used in a pattern more than once error[E0308]: mismatched types - --> $DIR/already-bound-name.rs:32:32 + --> $DIR/already-bound-name.rs:30:32 | LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); | - ^ ------- this expression has type `E<E<{integer}>>` diff --git a/src/test/ui/or-patterns/basic-switch.rs b/src/test/ui/or-patterns/basic-switch.rs index 6daa9d9255..674fbc3cc9 100644 --- a/src/test/ui/or-patterns/basic-switch.rs +++ b/src/test/ui/or-patterns/basic-switch.rs @@ -3,8 +3,6 @@ // run-pass -#![feature(or_patterns)] - #[derive(Debug)] enum Test { Foo, diff --git a/src/test/ui/or-patterns/basic-switchint.rs b/src/test/ui/or-patterns/basic-switchint.rs index c5a6d894ea..adb902caf0 100644 --- a/src/test/ui/or-patterns/basic-switchint.rs +++ b/src/test/ui/or-patterns/basic-switchint.rs @@ -3,8 +3,6 @@ // run-pass -#![feature(or_patterns)] - #[derive(Debug, PartialEq)] enum MatchArm { Arm(usize), diff --git a/src/test/ui/or-patterns/bindings-runpass-1.rs b/src/test/ui/or-patterns/bindings-runpass-1.rs index 0087167af7..3406d5197c 100644 --- a/src/test/ui/or-patterns/bindings-runpass-1.rs +++ b/src/test/ui/or-patterns/bindings-runpass-1.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(or_patterns)] - fn two_bindings(x: &((bool, bool), u8)) -> u8 { match x { &((true, y) | (y, true), z @ (0 | 4)) => (y as u8) + z, diff --git a/src/test/ui/or-patterns/bindings-runpass-2.rs b/src/test/ui/or-patterns/bindings-runpass-2.rs index 0e1eb7b2e0..5b9bb748c7 100644 --- a/src/test/ui/or-patterns/bindings-runpass-2.rs +++ b/src/test/ui/or-patterns/bindings-runpass-2.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(or_patterns)] - fn or_at(x: Result<u32, u32>) -> u32 { match x { Ok(x @ 4) | Err(x @ (6 | 8)) => x, diff --git a/src/test/ui/or-patterns/box-patterns.rs b/src/test/ui/or-patterns/box-patterns.rs index aafd479938..73051401c1 100644 --- a/src/test/ui/or-patterns/box-patterns.rs +++ b/src/test/ui/or-patterns/box-patterns.rs @@ -2,7 +2,6 @@ // run-pass -#![feature(or_patterns)] #![feature(box_patterns)] #[derive(Debug, PartialEq)] diff --git a/src/test/ui/or-patterns/consistent-bindings.rs b/src/test/ui/or-patterns/consistent-bindings.rs index 853ddcf241..ecae1d8a27 100644 --- a/src/test/ui/or-patterns/consistent-bindings.rs +++ b/src/test/ui/or-patterns/consistent-bindings.rs @@ -4,8 +4,6 @@ // check-pass -#![feature(or_patterns)] - fn main() { // One level: let (Ok(a) | Err(a)) = Ok(0); diff --git a/src/test/ui/or-patterns/const-fn.rs b/src/test/ui/or-patterns/const-fn.rs index 55c6f60915..ca512ac711 100644 --- a/src/test/ui/or-patterns/const-fn.rs +++ b/src/test/ui/or-patterns/const-fn.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(or_patterns)] const fn foo((Ok(a) | Err(a)): Result<i32, i32>) { let x = Ok(3); diff --git a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs index f2d5de75b6..5999e04e0e 100644 --- a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs +++ b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs @@ -1,4 +1,3 @@ -#![feature(or_patterns)] #![deny(unreachable_patterns)] // We wrap patterns in a tuple because top-level or-patterns were special-cased. diff --git a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr index d3ae798ead..44f334eee9 100644 --- a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr +++ b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `(2_u8..=u8::MAX, _)` not covered - --> $DIR/exhaustiveness-non-exhaustive.rs:6:11 + --> $DIR/exhaustiveness-non-exhaustive.rs:5:11 | LL | match (0u8, 0u8) { | ^^^^^^^^^^ pattern `(2_u8..=u8::MAX, _)` not covered @@ -8,7 +8,7 @@ LL | match (0u8, 0u8) { = note: the matched value is of type `(u8, u8)` error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered - --> $DIR/exhaustiveness-non-exhaustive.rs:10:11 + --> $DIR/exhaustiveness-non-exhaustive.rs:9:11 | LL | match ((0u8,),) { | ^^^^^^^^^ pattern `((4_u8..=u8::MAX))` not covered @@ -17,7 +17,7 @@ LL | match ((0u8,),) { = note: the matched value is of type `((u8,),)` error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered - --> $DIR/exhaustiveness-non-exhaustive.rs:14:11 + --> $DIR/exhaustiveness-non-exhaustive.rs:13:11 | LL | match (Some(0u8),) { | ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX))` not covered diff --git a/src/test/ui/or-patterns/exhaustiveness-pass.rs b/src/test/ui/or-patterns/exhaustiveness-pass.rs index 8dcf8792f6..e8c8a0e7ba 100644 --- a/src/test/ui/or-patterns/exhaustiveness-pass.rs +++ b/src/test/ui/or-patterns/exhaustiveness-pass.rs @@ -1,4 +1,3 @@ -#![feature(or_patterns)] #![deny(unreachable_patterns)] // check-pass diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs index bdb7a1ec92..8429799cab 100644 --- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs +++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -1,4 +1,3 @@ -#![feature(or_patterns)] #![deny(unreachable_patterns)] // We wrap patterns in a tuple because top-level or-patterns were special-cased. diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index 51991fc603..a84681e005 100644 --- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -1,138 +1,138 @@ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:8:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:7:9 | LL | (1,) => {} | ^^^^ | note: the lint level is defined here - --> $DIR/exhaustiveness-unreachable-pattern.rs:2:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:13:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:12:9 | LL | (2,) => {} | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:18:9 | LL | (1 | 2,) => {} | ^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:23:9 | LL | (1, 3) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 | LL | (1, 4) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 | LL | (2, 4) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:27:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 | LL | (2 | 1, 4) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:28:9 | LL | (1, 4 | 5) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:36:9 | LL | (Some(1),) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:38:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 | LL | (None,) => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:42:9 | LL | ((1..=4,),) => {} | ^^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:48:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:47:14 | LL | (1 | 1,) => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:52:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:51:19 | LL | (0 | 1) | 1 => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:58:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:57:14 | LL | 0 | (0 | 0) => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:58:18 + --> $DIR/exhaustiveness-unreachable-pattern.rs:57:18 | LL | 0 | (0 | 0) => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:66:13 + --> $DIR/exhaustiveness-unreachable-pattern.rs:65:13 | LL | / Some( LL | | 0 | 0) => {} | |______________________^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:72:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:71:15 | LL | | 0 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:74:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:73:15 | LL | | 0] => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:82:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:81:10 | LL | [1 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:94:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:93:10 | LL | [true | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:101:36 + --> $DIR/exhaustiveness-unreachable-pattern.rs:100:36 | LL | (true | false, None | Some(true | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:106:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:105:14 | LL | (true | ^^^^ @@ -143,25 +143,25 @@ LL | (true | false, None | Some(t_or_f!())) => {} = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:117:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 | LL | Some(0 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:136:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:135:19 | LL | | false) => {} | ^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:144:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:143:15 | LL | | true) => {} | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:150:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:149:15 | LL | | true, | ^^^^ diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs deleted file mode 100644 index de8e1bba55..0000000000 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Test feature gating for a sole leading `|` in `let`. - -fn main() {} - -#[cfg(FALSE)] -fn gated_leading_vert_in_let() { - for | A in 0 {} //~ ERROR or-patterns syntax is experimental -} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr deleted file mode 100644 index abcee43553..0000000000 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-for.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns-leading-for.rs:7:9 - | -LL | for | A in 0 {} - | ^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` 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/or-patterns/feature-gate-or_patterns-leading-let.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs deleted file mode 100644 index 6c592550ec..0000000000 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Test feature gating for a sole leading `|` in `let`. - -fn main() {} - -#[cfg(FALSE)] -fn gated_leading_vert_in_let() { - let | A; //~ ERROR or-patterns syntax is experimental - //~^ ERROR top-level or-patterns are not allowed -} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr deleted file mode 100644 index d556532cd6..0000000000 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: top-level or-patterns are not allowed in `let` bindings - --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 - | -LL | let | A; - | ^^^ help: remove the `|`: `A` - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 - | -LL | let | A; - | ^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.rs b/src/test/ui/or-patterns/feature-gate-or_patterns.rs deleted file mode 100644 index 8bb45e606b..0000000000 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.rs +++ /dev/null @@ -1,54 +0,0 @@ -fn main() {} - -pub fn example(x: Option<usize>) { - match x { - Some(0 | 1 | 2) => {} - //~^ ERROR: or-patterns syntax is experimental - _ => {} - } -} - -// Test the `pat` macro fragment parser: -macro_rules! accept_pat { - ($p:pat) => {} -} - -accept_pat!((p | q)); //~ ERROR or-patterns syntax is experimental -accept_pat!((p | q,)); //~ ERROR or-patterns syntax is experimental -accept_pat!(TS(p | q)); //~ ERROR or-patterns syntax is experimental -accept_pat!(NS { f: p | q }); //~ ERROR or-patterns syntax is experimental -accept_pat!([p | q]); //~ ERROR or-patterns syntax is experimental - -// Non-macro tests: - -#[cfg(FALSE)] -fn or_patterns() { - // Gated: - - let | A | B; //~ ERROR or-patterns syntax is experimental - //~^ ERROR top-level or-patterns are not allowed - let A | B; //~ ERROR or-patterns syntax is experimental - //~^ ERROR top-level or-patterns are not allowed - for | A | B in 0 {} //~ ERROR or-patterns syntax is experimental - for A | B in 0 {} //~ ERROR or-patterns syntax is experimental - fn fun((A | B): _) {} //~ ERROR or-patterns syntax is experimental - let _ = |(A | B): u8| (); //~ ERROR or-patterns syntax is experimental - let (A | B); //~ ERROR or-patterns syntax is experimental - let (A | B,); //~ ERROR or-patterns syntax is experimental - let A(B | C); //~ ERROR or-patterns syntax is experimental - let E::V(B | C); //~ ERROR or-patterns syntax is experimental - let S { f1: B | C, f2 }; //~ ERROR or-patterns syntax is experimental - let E::V { f1: B | C, f2 }; //~ ERROR or-patterns syntax is experimental - let [A | B]; //~ ERROR or-patterns syntax is experimental - - // Top level of `while`, `if`, and `match` arms are allowed: - - while let | A = 0 {} - while let A | B = 0 {} - if let | A = 0 {} - if let A | B = 0 {} - match 0 { - | A => {}, - A | B => {}, - } -} diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr deleted file mode 100644 index 7988af5b94..0000000000 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr +++ /dev/null @@ -1,186 +0,0 @@ -error: top-level or-patterns are not allowed in `let` bindings - --> $DIR/feature-gate-or_patterns.rs:28:9 - | -LL | let | A | B; - | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` - -error: top-level or-patterns are not allowed in `let` bindings - --> $DIR/feature-gate-or_patterns.rs:30:9 - | -LL | let A | B; - | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:5:14 - | -LL | Some(0 | 1 | 2) => {} - | ^^^^^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:28:9 - | -LL | let | A | B; - | ^^^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:30:9 - | -LL | let A | B; - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:32:9 - | -LL | for | A | B in 0 {} - | ^^^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:33:9 - | -LL | for A | B in 0 {} - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:34:13 - | -LL | fn fun((A | B): _) {} - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:35:15 - | -LL | let _ = |(A | B): u8| (); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:36:10 - | -LL | let (A | B); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:37:10 - | -LL | let (A | B,); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:38:11 - | -LL | let A(B | C); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:39:14 - | -LL | let E::V(B | C); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:40:17 - | -LL | let S { f1: B | C, f2 }; - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:41:20 - | -LL | let E::V { f1: B | C, f2 }; - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:42:10 - | -LL | let [A | B]; - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:16:14 - | -LL | accept_pat!((p | q)); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:17:14 - | -LL | accept_pat!((p | q,)); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:18:16 - | -LL | accept_pat!(TS(p | q)); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:19:21 - | -LL | accept_pat!(NS { f: p | q }); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:20:14 - | -LL | accept_pat!([p | q]); - | ^^^^^ - | - = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information - = help: add `#![feature(or_patterns)]` to the crate attributes to enable - -error: aborting due to 21 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed index 65e04325e1..b9490aaf9d 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed @@ -2,7 +2,6 @@ // run-rustfix -#![feature(or_patterns)] #![allow(warnings)] fn main() {} diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.rs b/src/test/ui/or-patterns/fn-param-wrap-parens.rs index aeb4a05ea8..8e703d274c 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.rs +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.rs @@ -2,7 +2,6 @@ // run-rustfix -#![feature(or_patterns)] #![allow(warnings)] fn main() {} diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr index 96193c17ae..7327028413 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr @@ -1,5 +1,5 @@ error: top-level or-patterns are not allowed in function parameters - --> $DIR/fn-param-wrap-parens.rs:14:9 + --> $DIR/fn-param-wrap-parens.rs:13:9 | LL | fn fun1(A | B: E) {} | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` diff --git a/src/test/ui/or-patterns/for-loop.rs b/src/test/ui/or-patterns/for-loop.rs index b79af6c402..11b61cb69f 100644 --- a/src/test/ui/or-patterns/for-loop.rs +++ b/src/test/ui/or-patterns/for-loop.rs @@ -1,8 +1,6 @@ // Check that or patterns are lowered correctly in `for` loops. // run-pass -#![feature(or_patterns)] - fn main() { let v = vec![Ok(2), Err(3), Ok(5)]; let mut w = Vec::new(); diff --git a/src/test/ui/or-patterns/if-let-while-let.rs b/src/test/ui/or-patterns/if-let-while-let.rs index 9256360b29..92a1bb2566 100644 --- a/src/test/ui/or-patterns/if-let-while-let.rs +++ b/src/test/ui/or-patterns/if-let-while-let.rs @@ -1,8 +1,6 @@ // Check that or patterns are lowered correctly in `if let` and `while let` expressions. // run-pass -#![feature(or_patterns)] - fn main() { let mut opt = Some(3); let mut w = Vec::new(); diff --git a/src/test/ui/or-patterns/inconsistent-modes.rs b/src/test/ui/or-patterns/inconsistent-modes.rs index 2300e9f9f3..a87a10ce8a 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.rs +++ b/src/test/ui/or-patterns/inconsistent-modes.rs @@ -1,6 +1,5 @@ // This test ensures that or patterns require binding mode consistency across arms. -#![feature(or_patterns)] #![allow(non_camel_case_types)] fn main() { // One level: diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr index 99791431ea..dae6bb41e7 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.stderr +++ b/src/test/ui/or-patterns/inconsistent-modes.stderr @@ -1,5 +1,5 @@ error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:7:26 + --> $DIR/inconsistent-modes.rs:6:26 | LL | let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); | - ^ bound in different ways @@ -7,7 +7,7 @@ LL | let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:9:30 + --> $DIR/inconsistent-modes.rs:8:30 | LL | let (Ok(ref mut a) | Err(a)): Result<u8, &mut u8> = Ok(0); | - ^ bound in different ways @@ -15,25 +15,25 @@ LL | let (Ok(ref mut a) | Err(a)): Result<u8, &mut u8> = Ok(0); | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:11:34 + --> $DIR/inconsistent-modes.rs:10:34 | LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); | - first binding ^ bound in different ways error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:14:40 + --> $DIR/inconsistent-modes.rs:13:40 | LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); | - first binding ^ bound in different ways error[E0409]: variable `b` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:14:47 + --> $DIR/inconsistent-modes.rs:13:47 | LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); | - first binding ^ bound in different ways error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:20:39 + --> $DIR/inconsistent-modes.rs:19:39 | LL | let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); | - ^ bound in different ways @@ -41,7 +41,7 @@ LL | let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:24:34 + --> $DIR/inconsistent-modes.rs:23:34 | LL | let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); | - ^ bound in different ways @@ -49,7 +49,7 @@ LL | let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); | first binding error[E0308]: mismatched types - --> $DIR/inconsistent-modes.rs:11:26 + --> $DIR/inconsistent-modes.rs:10:26 | LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); | ----- ^^^^^^^^^ -------------------- expected due to this @@ -62,7 +62,7 @@ LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/inconsistent-modes.rs:14:32 + --> $DIR/inconsistent-modes.rs:13:32 | LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); | ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>` diff --git a/src/test/ui/or-patterns/issue-67514-irrefutable-param.rs b/src/test/ui/or-patterns/issue-67514-irrefutable-param.rs index 0c2ae44e54..73931def89 100644 --- a/src/test/ui/or-patterns/issue-67514-irrefutable-param.rs +++ b/src/test/ui/or-patterns/issue-67514-irrefutable-param.rs @@ -2,8 +2,6 @@ // check-pass -#![feature(or_patterns)] - fn foo((Some(_) | None): Option<u32>) {} fn main() { diff --git a/src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs b/src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs index 1a65a1e544..7339a7e23f 100644 --- a/src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs +++ b/src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs @@ -1,7 +1,5 @@ // check-pass -#![feature(or_patterns)] - enum MyEnum { FirstCase(u8), OtherCase(u16), diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs index 8e83acc6dc..3538aad5d7 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs @@ -1,5 +1,3 @@ -#![feature(or_patterns)] - fn main() { let (0 | (1 | 2)) = 0; //~ ERROR refutable pattern in local binding match 0 { diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index 9ed942d9e0..61175b84ee 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -1,5 +1,5 @@ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered - --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:10 + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:2:10 | LL | let (0 | (1 | 2)) = 0; | ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered @@ -13,7 +13,7 @@ LL | if let (0 | (1 | 2)) = 0 { /* */ } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered - --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11 + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11 | LL | match 0 { | ^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs index 2f080ebf78..408ac24f39 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs @@ -1,7 +1,5 @@ // check-pass -#![feature(or_patterns)] - fn main() { let (0 | (1 | _)) = 0; if let 0 | (1 | 2) = 0 {} diff --git a/src/test/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs b/src/test/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs index eb6706e500..8a3c640b10 100644 --- a/src/test/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs +++ b/src/test/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs @@ -2,7 +2,6 @@ #![deny(unreachable_patterns)] -#![feature(or_patterns)] fn main() { match (3,42) { (a,_) | (_,a) if a > 10 => {println!("{}", a)} diff --git a/src/test/ui/or-patterns/let-pattern.rs b/src/test/ui/or-patterns/let-pattern.rs index 7f22aa9d9f..97207e83e2 100644 --- a/src/test/ui/or-patterns/let-pattern.rs +++ b/src/test/ui/or-patterns/let-pattern.rs @@ -1,5 +1,3 @@ -#![feature(or_patterns)] - // run-pass fn or_pat_let(x: Result<u32, u32>) -> u32 { diff --git a/src/test/ui/or-patterns/macro-pat.rs b/src/test/ui/or-patterns/macro-pat.rs index 8749407675..8c581b630d 100644 --- a/src/test/ui/or-patterns/macro-pat.rs +++ b/src/test/ui/or-patterns/macro-pat.rs @@ -3,8 +3,6 @@ // ignore-test // FIXME(mark-i-m): enable this test again when 2021 machinery is available -#![feature(or_patterns)] - use Foo::*; #[derive(Eq, PartialEq, Debug)] diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs index cf98a47210..d1cb73aafa 100644 --- a/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs @@ -1,8 +1,6 @@ // Regression test for #71297 // edition:2018 -#![feature(or_patterns)] - async fn a((x | s): String) {} //~^ ERROR variable `x` is not bound in all patterns //~| ERROR variable `s` is not bound in all patterns diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr index d5c77ee39c..81602fffa8 100644 --- a/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr @@ -1,5 +1,5 @@ error[E0408]: variable `s` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:6:13 + --> $DIR/mismatched-bindings-async-fn.rs:4:13 | LL | async fn a((x | s): String) {} | ^ - variable not in all patterns @@ -7,7 +7,7 @@ LL | async fn a((x | s): String) {} | pattern doesn't bind `s` error[E0408]: variable `x` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:6:17 + --> $DIR/mismatched-bindings-async-fn.rs:4:17 | LL | async fn a((x | s): String) {} | - ^ pattern doesn't bind `x` @@ -15,7 +15,7 @@ LL | async fn a((x | s): String) {} | variable not in all patterns error[E0408]: variable `s` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:11:10 + --> $DIR/mismatched-bindings-async-fn.rs:9:10 | LL | let (x | s) = String::new(); | ^ - variable not in all patterns @@ -23,7 +23,7 @@ LL | let (x | s) = String::new(); | pattern doesn't bind `s` error[E0408]: variable `x` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:11:14 + --> $DIR/mismatched-bindings-async-fn.rs:9:14 | LL | let (x | s) = String::new(); | - ^ pattern doesn't bind `x` diff --git a/src/test/ui/or-patterns/missing-bindings.rs b/src/test/ui/or-patterns/missing-bindings.rs index 5dd1f16b65..7c26012c0e 100644 --- a/src/test/ui/or-patterns/missing-bindings.rs +++ b/src/test/ui/or-patterns/missing-bindings.rs @@ -2,7 +2,6 @@ // edition:2018 -#![feature(or_patterns)] #![allow(non_camel_case_types)] fn main() {} diff --git a/src/test/ui/or-patterns/missing-bindings.stderr b/src/test/ui/or-patterns/missing-bindings.stderr index 4702bc6bbf..c173a3a9ab 100644 --- a/src/test/ui/or-patterns/missing-bindings.stderr +++ b/src/test/ui/or-patterns/missing-bindings.stderr @@ -1,5 +1,5 @@ error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/missing-bindings.rs:20:10 + --> $DIR/missing-bindings.rs:19:10 | LL | let (alpha | beta | charlie) = alpha; | ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta` @@ -8,7 +8,7 @@ LL | let (alpha | beta | charlie) = alpha; | pattern doesn't bind `beta` error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/missing-bindings.rs:22:14 + --> $DIR/missing-bindings.rs:21:14 | LL | Some(alpha | beta) => {} | ^^^^^ ---- variable not in all patterns @@ -16,7 +16,7 @@ LL | Some(alpha | beta) => {} | pattern doesn't bind `beta` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:34:20 + --> $DIR/missing-bindings.rs:33:20 | LL | let (A(a, _) | _) = X; | - ^ pattern doesn't bind `a` @@ -24,7 +24,7 @@ LL | let (A(a, _) | _) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:35:10 + --> $DIR/missing-bindings.rs:34:10 | LL | let (_ | B(a)) = X; | ^ - variable not in all patterns @@ -32,7 +32,7 @@ LL | let (_ | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:36:10 + --> $DIR/missing-bindings.rs:35:10 | LL | let (A(..) | B(a)) = X; | ^^^^^ - variable not in all patterns @@ -40,7 +40,7 @@ LL | let (A(..) | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:37:20 + --> $DIR/missing-bindings.rs:36:20 | LL | let (A(a, _) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -48,7 +48,7 @@ LL | let (A(a, _) | B(_)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:38:20 + --> $DIR/missing-bindings.rs:37:20 | LL | let (A(_, a) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -56,7 +56,7 @@ LL | let (A(_, a) | B(_)) = X; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:39:20 + --> $DIR/missing-bindings.rs:38:20 | LL | let (A(a, b) | B(a)) = X; | - ^^^^ pattern doesn't bind `b` @@ -64,7 +64,7 @@ LL | let (A(a, b) | B(a)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:43:10 + --> $DIR/missing-bindings.rs:42:10 | LL | let (A(A(..) | B(_), _) | B(a)) = Y; | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -72,7 +72,7 @@ LL | let (A(A(..) | B(_), _) | B(a)) = Y; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:44:12 + --> $DIR/missing-bindings.rs:43:12 | LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | ^^^^^ - variable not in all patterns @@ -80,7 +80,7 @@ LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:22 + --> $DIR/missing-bindings.rs:45:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -88,7 +88,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:22 + --> $DIR/missing-bindings.rs:45:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -96,7 +96,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:12 + --> $DIR/missing-bindings.rs:45:12 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^ - variable not in all patterns @@ -104,7 +104,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `c` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:33 + --> $DIR/missing-bindings.rs:45:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -112,7 +112,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:33 + --> $DIR/missing-bindings.rs:45:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -120,7 +120,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:33 + --> $DIR/missing-bindings.rs:45:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `c` @@ -128,7 +128,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `d` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:33 + --> $DIR/missing-bindings.rs:45:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `d` @@ -136,7 +136,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `e` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:10 + --> $DIR/missing-bindings.rs:45:10 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -144,7 +144,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `e` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:62:29 + --> $DIR/missing-bindings.rs:61:29 | LL | Ok(a) | Err(_), | - ^^^^^^ pattern doesn't bind `a` @@ -152,7 +152,7 @@ LL | Ok(a) | Err(_), | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:70:21 + --> $DIR/missing-bindings.rs:69:21 | LL | A(_, a) | | - variable not in all patterns @@ -160,7 +160,7 @@ LL | B(b), | ^^^^ pattern doesn't bind `a` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:69:21 + --> $DIR/missing-bindings.rs:68:21 | LL | A(_, a) | | ^^^^^^^ pattern doesn't bind `b` @@ -168,7 +168,7 @@ LL | B(b), | - variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:73:17 + --> $DIR/missing-bindings.rs:72:17 | LL | A(_, a) | | - variable not in all patterns @@ -177,7 +177,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `a` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:73:17 + --> $DIR/missing-bindings.rs:72:17 | LL | B(b), | - variable not in all patterns @@ -186,7 +186,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `b` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:77:13 + --> $DIR/missing-bindings.rs:76:13 | LL | B(Ok(a) | Err(a)) | - variable not in all patterns @@ -198,7 +198,7 @@ LL | V3(c), | ^^^^^ pattern doesn't bind `a` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:58:13 + --> $DIR/missing-bindings.rs:57:13 | LL | / V1( LL | | @@ -216,7 +216,7 @@ LL | V3(c), | ^^^^^ pattern doesn't bind `b` error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:58:13 + --> $DIR/missing-bindings.rs:57:13 | LL | / V1( LL | | diff --git a/src/test/ui/or-patterns/mix-with-wild.rs b/src/test/ui/or-patterns/mix-with-wild.rs index 37f20df1b3..d9911cda1b 100644 --- a/src/test/ui/or-patterns/mix-with-wild.rs +++ b/src/test/ui/or-patterns/mix-with-wild.rs @@ -4,7 +4,6 @@ // 2) or-patterns should work with simplifyable patterns. // run-pass -#![feature(or_patterns)] pub fn test(x: Option<usize>) -> bool { match x { diff --git a/src/test/ui/or-patterns/multiple-pattern-typo.rs b/src/test/ui/or-patterns/multiple-pattern-typo.rs index 4d06101044..5f20125330 100644 --- a/src/test/ui/or-patterns/multiple-pattern-typo.rs +++ b/src/test/ui/or-patterns/multiple-pattern-typo.rs @@ -1,4 +1,4 @@ -#![feature(or_patterns)] +//! Test for `||` in or-patterns fn main() { let x = 3; diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs index 11c8a7b69f..fa470de7fb 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs @@ -1,8 +1,6 @@ // Here we test type checking of bindings when combined with or-patterns. // Specifically, we ensure that introducing bindings of different types result in type errors. -#![feature(or_patterns)] - fn main() { enum Blah { A(isize, isize, usize), diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr index 26e14b539d..00ce46c569 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:13:39 + --> $DIR/or-patterns-binding-type-mismatch.rs:11:39 | LL | match Blah::A(1, 1, 2) { | ---------------- this expression has type `Blah` @@ -11,7 +11,7 @@ LL | Blah::A(_, x, y) | Blah::B(x, y) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:17:44 + --> $DIR/or-patterns-binding-type-mismatch.rs:15:44 | LL | match Some(Blah::A(1, 1, 2)) { | ---------------------- this expression has type `Option<Blah>` @@ -23,7 +23,7 @@ LL | Some(Blah::A(_, x, y) | Blah::B(x, y)) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:21:19 + --> $DIR/or-patterns-binding-type-mismatch.rs:19:19 | LL | match (0u8, 1u16) { | ----------- this expression has type `(u8, u16)` @@ -35,7 +35,7 @@ LL | (x, y) | (y, x) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:21:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:19:22 | LL | match (0u8, 1u16) { | ----------- this expression has type `(u8, u16)` @@ -47,7 +47,7 @@ LL | (x, y) | (y, x) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:26:41 + --> $DIR/or-patterns-binding-type-mismatch.rs:24:41 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` @@ -59,7 +59,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:26:50 + --> $DIR/or-patterns-binding-type-mismatch.rs:24:50 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` @@ -71,7 +71,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:26:59 + --> $DIR/or-patterns-binding-type-mismatch.rs:24:59 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` @@ -83,7 +83,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:26:62 + --> $DIR/or-patterns-binding-type-mismatch.rs:24:62 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` @@ -93,7 +93,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:34:42 + --> $DIR/or-patterns-binding-type-mismatch.rs:32:42 | LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { | - ^ ---------------- this expression has type `Blah` @@ -104,7 +104,7 @@ LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:38:47 + --> $DIR/or-patterns-binding-type-mismatch.rs:36:47 | LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) { | - ^ ---------------------- this expression has type `Option<Blah>` @@ -115,7 +115,7 @@ LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:42:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:40:22 | LL | if let (x, y) | (y, x) = (0u8, 1u16) { | - ^ ----------- this expression has type `(u8, u16)` @@ -126,7 +126,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:42:25 + --> $DIR/or-patterns-binding-type-mismatch.rs:40:25 | LL | if let (x, y) | (y, x) = (0u8, 1u16) { | - ^ ----------- this expression has type `(u8, u16)` @@ -137,7 +137,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:47:44 + --> $DIR/or-patterns-binding-type-mismatch.rs:45:44 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | - ^ expected `u16`, found `u8` @@ -150,7 +150,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:47:53 + --> $DIR/or-patterns-binding-type-mismatch.rs:45:53 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | - ^ expected `u8`, found `u16` @@ -163,7 +163,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:47:62 + --> $DIR/or-patterns-binding-type-mismatch.rs:45:62 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | - ^ expected `u32`, found `u16` @@ -176,7 +176,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:47:65 + --> $DIR/or-patterns-binding-type-mismatch.rs:45:65 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | - first introduced with type `u8` here ^ expected `u8`, found `u32` @@ -187,7 +187,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:55:40 + --> $DIR/or-patterns-binding-type-mismatch.rs:53:40 | LL | let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); | - ^ ---------------- this expression has type `Blah` @@ -198,7 +198,7 @@ LL | let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:58:20 + --> $DIR/or-patterns-binding-type-mismatch.rs:56:20 | LL | let ((x, y) | (y, x)) = (0u8, 1u16); | - ^ ----------- this expression has type `(u8, u16)` @@ -209,7 +209,7 @@ LL | let ((x, y) | (y, x)) = (0u8, 1u16); = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:58:23 + --> $DIR/or-patterns-binding-type-mismatch.rs:56:23 | LL | let ((x, y) | (y, x)) = (0u8, 1u16); | - ^ ----------- this expression has type `(u8, u16)` @@ -220,7 +220,7 @@ LL | let ((x, y) | (y, x)) = (0u8, 1u16); = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:62:42 + --> $DIR/or-patterns-binding-type-mismatch.rs:60:42 | LL | fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} | - ^ ---- expected due to this @@ -231,7 +231,7 @@ LL | fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:65:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:63:22 | LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} | - ^ --------- expected due to this @@ -242,7 +242,7 @@ LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:65:25 + --> $DIR/or-patterns-binding-type-mismatch.rs:63:25 | LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} | - ^ --------- expected due to this diff --git a/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs index f98b038ae8..e56f9ffe23 100644 --- a/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs +++ b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs @@ -2,7 +2,6 @@ // check-pass -#![feature(or_patterns)] #![allow(irrefutable_let_patterns)] fn main() { diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs index 27a5374ff1..358e9d034c 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -1,8 +1,6 @@ // Test some cases where or-patterns may ostensibly be allowed but are in fact not. // This is not a semantic test. We only test parsing. -#![feature(or_patterns)] - fn main() {} enum E { A, B } diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index 929b2088f7..5406d51c64 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -1,29 +1,29 @@ error: top-level or-patterns are not allowed in function parameters - --> $DIR/or-patterns-syntactic-fail.rs:17:13 + --> $DIR/or-patterns-syntactic-fail.rs:15:13 | LL | fn fun1(A | B: E) {} | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` error: top-level or-patterns are not allowed in function parameters - --> $DIR/or-patterns-syntactic-fail.rs:20:13 + --> $DIR/or-patterns-syntactic-fail.rs:18:13 | LL | fn fun2(| A | B: E) {} | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` error: top-level or-patterns are not allowed in `let` bindings - --> $DIR/or-patterns-syntactic-fail.rs:25:9 + --> $DIR/or-patterns-syntactic-fail.rs:23:9 | LL | let A | B: E = A; | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` error: top-level or-patterns are not allowed in `let` bindings - --> $DIR/or-patterns-syntactic-fail.rs:28:9 + --> $DIR/or-patterns-syntactic-fail.rs:26:9 | LL | let | A | B: E = A; | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` error[E0369]: no implementation for `E | ()` - --> $DIR/or-patterns-syntactic-fail.rs:13:22 + --> $DIR/or-patterns-syntactic-fail.rs:11:22 | LL | let _ = |A | B: E| (); | ----^ -- () diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs index 3da238f7b9..6f9a631b09 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -3,8 +3,6 @@ // check-pass -#![feature(or_patterns)] - fn main() {} // Test the `pat` macro fragment parser: diff --git a/src/test/ui/or-patterns/remove-leading-vert.fixed b/src/test/ui/or-patterns/remove-leading-vert.fixed index d23858d42d..b1cd0a9443 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.fixed +++ b/src/test/ui/or-patterns/remove-leading-vert.fixed @@ -2,7 +2,6 @@ // run-rustfix -#![feature(or_patterns)] #![allow(warnings)] fn main() {} diff --git a/src/test/ui/or-patterns/remove-leading-vert.rs b/src/test/ui/or-patterns/remove-leading-vert.rs index e753765b3e..dc12382aa3 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.rs +++ b/src/test/ui/or-patterns/remove-leading-vert.rs @@ -2,7 +2,6 @@ // run-rustfix -#![feature(or_patterns)] #![allow(warnings)] fn main() {} diff --git a/src/test/ui/or-patterns/remove-leading-vert.stderr b/src/test/ui/or-patterns/remove-leading-vert.stderr index 0a2b143288..af51c67e1c 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.stderr +++ b/src/test/ui/or-patterns/remove-leading-vert.stderr @@ -1,11 +1,11 @@ error: top-level or-patterns are not allowed in function parameters - --> $DIR/remove-leading-vert.rs:12:14 + --> $DIR/remove-leading-vert.rs:11:14 | LL | fn fun1( | A: E) {} | ^^^ help: remove the `|`: `A` error: unexpected `||` before function parameter - --> $DIR/remove-leading-vert.rs:13:14 + --> $DIR/remove-leading-vert.rs:12:14 | LL | fn fun2( || A: E) {} | ^^ help: remove the `||` @@ -13,31 +13,31 @@ LL | fn fun2( || A: E) {} = note: alternatives in or-patterns are separated with `|`, not `||` error: unexpected token `||` in pattern - --> $DIR/remove-leading-vert.rs:15:11 + --> $DIR/remove-leading-vert.rs:14:11 | LL | let ( || A): (E); | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` in pattern - --> $DIR/remove-leading-vert.rs:18:11 + --> $DIR/remove-leading-vert.rs:17:11 | LL | let [ || A ]: [E; 1]; | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` in pattern - --> $DIR/remove-leading-vert.rs:20:13 + --> $DIR/remove-leading-vert.rs:19:13 | LL | let TS( || A ): TS; | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: unexpected token `||` in pattern - --> $DIR/remove-leading-vert.rs:22:17 + --> $DIR/remove-leading-vert.rs:21:17 | LL | let NS { f: || A }: NS; | ^^ help: use a single `|` to separate multiple alternative patterns: `|` error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:27:13 + --> $DIR/remove-leading-vert.rs:26:13 | LL | let ( A | ): E; | - ^ help: remove the `|` @@ -45,7 +45,7 @@ LL | let ( A | ): E; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:28:12 + --> $DIR/remove-leading-vert.rs:27:12 | LL | let (a |,): (E,); | - ^ help: remove the `|` @@ -53,7 +53,7 @@ LL | let (a |,): (E,); | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:29:17 + --> $DIR/remove-leading-vert.rs:28:17 | LL | let ( A | B | ): E; | - ^ help: remove the `|` @@ -61,7 +61,7 @@ LL | let ( A | B | ): E; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:30:17 + --> $DIR/remove-leading-vert.rs:29:17 | LL | let [ A | B | ]: [E; 1]; | - ^ help: remove the `|` @@ -69,7 +69,7 @@ LL | let [ A | B | ]: [E; 1]; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:31:18 + --> $DIR/remove-leading-vert.rs:30:18 | LL | let S { f: B | }; | - ^ help: remove the `|` @@ -77,7 +77,7 @@ LL | let S { f: B | }; | while parsing this or-pattern starting here error: unexpected token `||` in pattern - --> $DIR/remove-leading-vert.rs:32:13 + --> $DIR/remove-leading-vert.rs:31:13 | LL | let ( A || B | ): E; | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` @@ -85,7 +85,7 @@ LL | let ( A || B | ): E; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:32:18 + --> $DIR/remove-leading-vert.rs:31:18 | LL | let ( A || B | ): E; | - ^ help: remove the `|` @@ -93,7 +93,7 @@ LL | let ( A || B | ): E; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:35:11 + --> $DIR/remove-leading-vert.rs:34:11 | LL | A | => {} | - ^ help: remove the `|` @@ -101,7 +101,7 @@ LL | A | => {} | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:36:11 + --> $DIR/remove-leading-vert.rs:35:11 | LL | A || => {} | - ^^ help: remove the `||` @@ -111,7 +111,7 @@ LL | A || => {} = note: alternatives in or-patterns are separated with `|`, not `||` error: unexpected token `||` in pattern - --> $DIR/remove-leading-vert.rs:37:11 + --> $DIR/remove-leading-vert.rs:36:11 | LL | A || B | => {} | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` @@ -119,7 +119,7 @@ LL | A || B | => {} | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:37:16 + --> $DIR/remove-leading-vert.rs:36:16 | LL | A || B | => {} | - ^ help: remove the `|` @@ -127,7 +127,7 @@ LL | A || B | => {} | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:39:17 + --> $DIR/remove-leading-vert.rs:38:17 | LL | | A | B | => {} | - ^ help: remove the `|` @@ -135,7 +135,7 @@ LL | | A | B | => {} | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:46:11 + --> $DIR/remove-leading-vert.rs:45:11 | LL | let a | : u8 = 0; | - ^ help: remove the `|` @@ -143,7 +143,7 @@ LL | let a | : u8 = 0; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:47:11 + --> $DIR/remove-leading-vert.rs:46:11 | LL | let a | = 0; | - ^ help: remove the `|` @@ -151,7 +151,7 @@ LL | let a | = 0; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:48:11 + --> $DIR/remove-leading-vert.rs:47:11 | LL | let a | ; | - ^ help: remove the `|` diff --git a/src/test/ui/or-patterns/search-via-bindings.rs b/src/test/ui/or-patterns/search-via-bindings.rs index 067e617373..d98606deda 100644 --- a/src/test/ui/or-patterns/search-via-bindings.rs +++ b/src/test/ui/or-patterns/search-via-bindings.rs @@ -2,8 +2,6 @@ // run-pass -#![feature(or_patterns)] - fn search(target: (bool, bool, bool)) -> u32 { let x = ((false, true), (false, true), (false, true)); let mut guard_count = 0; diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs index 05c907e824..ed5eace0b7 100644 --- a/src/test/ui/or-patterns/slice-patterns.rs +++ b/src/test/ui/or-patterns/slice-patterns.rs @@ -2,8 +2,6 @@ // run-pass -#![feature(or_patterns)] - #[derive(Debug, PartialEq)] enum MatchArm { Arm(usize), diff --git a/src/test/ui/or-patterns/struct-like.rs b/src/test/ui/or-patterns/struct-like.rs index 3794a8b6c1..7de690d2d8 100644 --- a/src/test/ui/or-patterns/struct-like.rs +++ b/src/test/ui/or-patterns/struct-like.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(or_patterns)] - #[derive(Debug)] enum Other { One, diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs index 812d23fb58..fb3875e680 100644 --- a/src/test/ui/packed/packed-struct-address-of-element.rs +++ b/src/test/ui/packed/packed-struct-address-of-element.rs @@ -1,6 +1,6 @@ // run-pass #![allow(dead_code)] -#![deny(safe_packed_borrows)] +#![deny(unaligned_references)] #![feature(raw_ref_op)] // ignore-emscripten weird assertion? diff --git a/src/test/ui/packed/packed-struct-borrow-element-64bit.rs b/src/test/ui/packed/packed-struct-borrow-element-64bit.rs new file mode 100644 index 0000000000..ad932fdcd0 --- /dev/null +++ b/src/test/ui/packed/packed-struct-borrow-element-64bit.rs @@ -0,0 +1,17 @@ +// run-pass (note: this is spec-UB, but it works for now) +// ignore-32bit (needs `usize` to be 8-aligned to reproduce all the errors below) +#![allow(dead_code)] +// ignore-emscripten weird assertion? + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +pub fn main() { + let foo = Foo4C { bar: 1, baz: 2 }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted + assert_eq!(*brw, 2); +} diff --git a/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr new file mode 100644 index 0000000000..766d8a72c3 --- /dev/null +++ b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr @@ -0,0 +1,13 @@ +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element-64bit.rs:14:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = note: `#[warn(unaligned_references)]` 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 #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: 1 warning emitted + diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs index 0072b6191e..fb6c9c11d5 100644 --- a/src/test/ui/packed/packed-struct-borrow-element.rs +++ b/src/test/ui/packed/packed-struct-borrow-element.rs @@ -22,14 +22,12 @@ struct Foo4C { pub fn main() { let foo = Foo1 { bar: 1, baz: 2 }; - let brw = unsafe { &foo.baz }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted assert_eq!(*brw, 2); let foo = Foo2 { bar: 1, baz: 2 }; - let brw = unsafe { &foo.baz }; - assert_eq!(*brw, 2); - - let foo = Foo4C { bar: 1, baz: 2 }; - let brw = unsafe { &foo.baz }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted assert_eq!(*brw, 2); } diff --git a/src/test/ui/packed/packed-struct-borrow-element.stderr b/src/test/ui/packed/packed-struct-borrow-element.stderr new file mode 100644 index 0000000000..5764e951a4 --- /dev/null +++ b/src/test/ui/packed/packed-struct-borrow-element.stderr @@ -0,0 +1,23 @@ +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:25:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = note: `#[warn(unaligned_references)]` 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 #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: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:30:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = 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) + +warning: 2 warnings emitted + diff --git a/src/test/ui/panic-runtime/two-panic-runtimes.rs b/src/test/ui/panic-runtime/two-panic-runtimes.rs index c968b5ea1e..7ec658ebcf 100644 --- a/src/test/ui/panic-runtime/two-panic-runtimes.rs +++ b/src/test/ui/panic-runtime/two-panic-runtimes.rs @@ -1,7 +1,6 @@ // build-fail // dont-check-compiler-stderr // error-pattern:cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 -// ignore-tidy-linelength // aux-build:panic-runtime-unwind.rs // aux-build:panic-runtime-unwind2.rs // aux-build:panic-runtime-lang-items.rs diff --git a/src/test/ui/panic-runtime/unwind-tables-panic-required.rs b/src/test/ui/panic-runtime/unwind-tables-panic-required.rs deleted file mode 100644 index 6393a27046..0000000000 --- a/src/test/ui/panic-runtime/unwind-tables-panic-required.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Tests that the compiler errors if the user tries to turn off unwind tables -// when they are required. -// -// dont-check-compiler-stderr -// compile-flags: -C panic=unwind -C force-unwind-tables=no -// ignore-tidy-linelength -// -// error-pattern: panic=unwind requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`. - -pub fn main() { -} diff --git a/src/test/ui/panic-runtime/unwind-tables-target-required.rs b/src/test/ui/panic-runtime/unwind-tables-target-required.rs index 14c1789376..3abb52b675 100644 --- a/src/test/ui/panic-runtime/unwind-tables-target-required.rs +++ b/src/test/ui/panic-runtime/unwind-tables-target-required.rs @@ -3,7 +3,6 @@ // // only-x86_64-windows-msvc // compile-flags: -C force-unwind-tables=no -// ignore-tidy-linelength // // error-pattern: target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`. diff --git a/src/test/ui/bad/bad-crate-name.rs b/src/test/ui/parser/bad-crate-name.rs similarity index 100% rename from src/test/ui/bad/bad-crate-name.rs rename to src/test/ui/parser/bad-crate-name.rs diff --git a/src/test/ui/bad/bad-crate-name.stderr b/src/test/ui/parser/bad-crate-name.stderr similarity index 100% rename from src/test/ui/bad/bad-crate-name.stderr rename to src/test/ui/parser/bad-crate-name.stderr diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index 97f19b3da4..87ba230eab 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - fn main() {} extern "C" { diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 6ac27078ea..d9815fc739 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,5 +1,5 @@ error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub` - --> $DIR/duplicate-visibility.rs:6:9 + --> $DIR/duplicate-visibility.rs:4:9 | LL | extern "C" { | - while parsing this item list starting here diff --git a/src/test/ui/issues/issue-48508-aux.rs b/src/test/ui/parser/issue-48508-aux.rs similarity index 100% rename from src/test/ui/issues/issue-48508-aux.rs rename to src/test/ui/parser/issue-48508-aux.rs diff --git a/src/test/ui/issues/issue-48508.rs b/src/test/ui/parser/issue-48508.rs similarity index 95% rename from src/test/ui/issues/issue-48508.rs rename to src/test/ui/parser/issue-48508.rs index 8dc9351260..37d04c5d65 100644 --- a/src/test/ui/issues/issue-48508.rs +++ b/src/test/ui/parser/issue-48508.rs @@ -10,7 +10,6 @@ // ignore-pretty issue #37195 // ignore-asmjs wasm2js does not support source maps yet -#![feature(non_ascii_idents)] #![allow(uncommon_codepoints)] #[path = "issue-48508-aux.rs"] diff --git a/src/test/ui/parser/issue-63116.stderr b/src/test/ui/parser/issue-63116.stderr index e249a93df9..4766dfafea 100644 --- a/src/test/ui/parser/issue-63116.stderr +++ b/src/test/ui/parser/issue-63116.stderr @@ -12,11 +12,11 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;` LL | impl W <s(f;Y(;] | ^ expected one of 7 possible tokens -error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `:`, `<`, `=`, `>`, `?`, `[`, `_`, `async`, `const`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;` - --> $DIR/issue-63116.rs:3:15 +error: mismatched closing delimiter: `]` + --> $DIR/issue-63116.rs:3:16 | LL | impl W <s(f;Y(;] - | -^ help: `)` may belong here + | - ^ mismatched closing delimiter | | | unclosed delimiter diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs index 5ec143fae2..aed428bfc2 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // The problem in #66357 was that the call trace: // // - parse_fn_block_decl diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr index c3810999d2..332711df72 100644 --- a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr @@ -1,11 +1,11 @@ error: expected one of `,` or `:`, found `(` - --> $DIR/issue-66357-unexpected-unreachable.rs:14:13 + --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 | LL | fn f() { |[](* } | ^ expected one of `,` or `:` error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` - --> $DIR/issue-66357-unexpected-unreachable.rs:14:14 + --> $DIR/issue-66357-unexpected-unreachable.rs:12:14 | LL | fn f() { |[](* } | -^ help: `)` may belong here diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs b/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.rs similarity index 100% rename from src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs rename to src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.rs diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.stderr similarity index 100% rename from src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr rename to src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.stderr diff --git a/src/test/ui/parser/issue-84117.rs b/src/test/ui/parser/issue-84117.rs new file mode 100644 index 0000000000..0f20073591 --- /dev/null +++ b/src/test/ui/parser/issue-84117.rs @@ -0,0 +1,9 @@ +fn main() { + let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + //~^ ERROR expected one of `>`, a const expression + //~| ERROR expected one of `>`, a const expression, lifetime, or type, found `}` + //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,` + //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,` + //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,` +} +//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `}` diff --git a/src/test/ui/parser/issue-84117.stderr b/src/test/ui/parser/issue-84117.stderr new file mode 100644 index 0000000000..d667a4977d --- /dev/null +++ b/src/test/ui/parser/issue-84117.stderr @@ -0,0 +1,49 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `}` + --> $DIR/issue-84117.rs:2:67 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ------------ ^ expected one of `>`, a const expression, lifetime, or type + | | | + | | help: use `=` if you meant to assign + | while parsing the type for `inner_local` + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,` + --> $DIR/issue-84117.rs:2:65 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ^ expected one of 7 possible tokens + +error: expected one of `,`, `:`, `=`, or `>`, found `}` + --> $DIR/issue-84117.rs:8:1 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ------------ help: use `=` if you meant to assign - expected one of `,`, `:`, `=`, or `>` + | | + | while parsing the type for `outer_local` +... +LL | } + | ^ unexpected token + +error: expected one of `>`, a const expression, lifetime, or type, found `}` + --> $DIR/issue-84117.rs:2:67 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ------------ ^ expected one of `>`, a const expression, lifetime, or type + | | | + | | help: use `=` if you meant to assign + | while parsing the type for `inner_local` + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,` + --> $DIR/issue-84117.rs:2:65 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ^ expected one of 7 possible tokens + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,` + --> $DIR/issue-84117.rs:2:33 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ^ expected one of 7 possible tokens + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/issue-8537.stderr b/src/test/ui/parser/issue-8537.stderr index 85e2b77d86..5a29ce2221 100644 --- a/src/test/ui/parser/issue-8537.stderr +++ b/src/test/ui/parser/issue-8537.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize` LL | "invalid-ab_isize" | ^^^^^^^^^^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted + = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted error: aborting due to previous error diff --git a/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.rs b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.rs index f3ae3aba9b..7e7995d672 100644 --- a/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.rs +++ b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.rs @@ -4,9 +4,7 @@ fn main() { (()é); //~^ ERROR: expected one of `)`, `,`, `.`, `?`, or an operator //~| ERROR: cannot find value `é` in this scope - //~| ERROR: non-ascii idents are not fully supported (()氷); //~^ ERROR: expected one of `)`, `,`, `.`, `?`, or an operator //~| ERROR: cannot find value `氷` in this scope - //~| ERROR: non-ascii idents are not fully supported } diff --git a/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.stderr b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.stderr index 892cc92b1b..21e71aa121 100644 --- a/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.stderr +++ b/src/test/ui/parser/multibyte-char-use-seperator-issue-80134.stderr @@ -8,7 +8,7 @@ LL | (()é); | help: missing `,` error: expected one of `)`, `,`, `.`, `?`, or an operator, found `氷` - --> $DIR/multibyte-char-use-seperator-issue-80134.rs:8:8 + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:7:8 | LL | (()氷); | -^ @@ -23,30 +23,11 @@ LL | (()é); | ^ not found in this scope error[E0425]: cannot find value `氷` in this scope - --> $DIR/multibyte-char-use-seperator-issue-80134.rs:8:8 + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:7:8 | LL | (()氷); | ^^ not found in this scope -error[E0658]: non-ascii idents are not fully supported - --> $DIR/multibyte-char-use-seperator-issue-80134.rs:4:8 - | -LL | (()é); - | ^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/multibyte-char-use-seperator-issue-80134.rs:8:8 - | -LL | (()氷); - | ^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0425, E0658. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/parser/unicode-quote-chars.rs b/src/test/ui/parser/unicode-quote-chars.rs index eeaea3628b..868d2b227b 100644 --- a/src/test/ui/parser/unicode-quote-chars.rs +++ b/src/test/ui/parser/unicode-quote-chars.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - fn main() { println!(“hello world”); //~^ ERROR unknown start of token: \u{201c} diff --git a/src/test/ui/parser/unicode-quote-chars.stderr b/src/test/ui/parser/unicode-quote-chars.stderr index d9ec92b3f8..04ea0c6e95 100644 --- a/src/test/ui/parser/unicode-quote-chars.stderr +++ b/src/test/ui/parser/unicode-quote-chars.stderr @@ -1,5 +1,5 @@ error: unknown start of token: \u{201c} - --> $DIR/unicode-quote-chars.rs:4:14 + --> $DIR/unicode-quote-chars.rs:2:14 | LL | println!(“hello world”); | ^ @@ -10,7 +10,7 @@ LL | println!("hello world"); | ^^^^^^^^^^^^^ error: unknown start of token: \u{201d} - --> $DIR/unicode-quote-chars.rs:4:26 + --> $DIR/unicode-quote-chars.rs:2:26 | LL | println!(“hello world”); | ^ @@ -21,7 +21,7 @@ LL | println!(“hello world"); | ^ error: expected `,`, found `world` - --> $DIR/unicode-quote-chars.rs:4:21 + --> $DIR/unicode-quote-chars.rs:2:21 | LL | println!(“hello world”); | ^^^^^ expected `,` diff --git a/src/test/ui/parser/use-unclosed-brace.rs b/src/test/ui/parser/use-unclosed-brace.rs new file mode 100644 index 0000000000..41742f37f3 --- /dev/null +++ b/src/test/ui/parser/use-unclosed-brace.rs @@ -0,0 +1,12 @@ +// error-pattern: expected one of `,`, `::`, `as`, or `}`, found `;` +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected item, found `}` +use foo::{bar, baz; + +use std::fmt::Display; + +mod bar { } + +mod baz { } + +fn main() {} diff --git a/src/test/ui/parser/use-unclosed-brace.stderr b/src/test/ui/parser/use-unclosed-brace.stderr new file mode 100644 index 0000000000..d29a68f821 --- /dev/null +++ b/src/test/ui/parser/use-unclosed-brace.stderr @@ -0,0 +1,27 @@ +error: this file contains an unclosed delimiter + --> $DIR/use-unclosed-brace.rs:12:14 + | +LL | use foo::{bar, baz; + | - unclosed delimiter +... +LL | fn main() {} + | ^ + +error: expected one of `,`, `::`, `as`, or `}`, found `;` + --> $DIR/use-unclosed-brace.rs:4:19 + | +LL | use foo::{bar, baz; + | - ^ + | | | + | | expected one of `,`, `::`, `as`, or `}` + | | help: `}` may belong here + | unclosed delimiter + +error: expected item, found `}` + --> $DIR/use-unclosed-brace.rs:12:14 + | +LL | fn main() {} + | ^ expected item + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs index 404f409075..fe993a6ee1 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -1,4 +1,5 @@ #![feature(c_variadic)] +#![allow(anonymous_parameters)] fn main() {} diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr index ebfe4979fb..10fd05c0be 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -1,203 +1,203 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:5:19 + --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19 | LL | fn f1_1(x: isize, ...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 | LL | fn f1_2(...) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 | LL | fn f1_2(...) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 + --> $DIR/variadic-ffi-semantic-restrictions.rs:13:30 | LL | extern "C" fn f2_1(x: isize, ...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + --> $DIR/variadic-ffi-semantic-restrictions.rs:16:20 | LL | extern "C" fn f2_2(...) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + --> $DIR/variadic-ffi-semantic-restrictions.rs:16:20 | LL | extern "C" fn f2_2(...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:23:30 + --> $DIR/variadic-ffi-semantic-restrictions.rs:24:30 | LL | extern "C" fn f3_1(x: isize, ...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:26:20 + --> $DIR/variadic-ffi-semantic-restrictions.rs:27:20 | LL | extern "C" fn f3_2(...) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:26:20 + --> $DIR/variadic-ffi-semantic-restrictions.rs:27:20 | LL | extern "C" fn f3_2(...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:30:20 + --> $DIR/variadic-ffi-semantic-restrictions.rs:31:20 | LL | extern "C" fn f3_3(..., x: isize) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:30:20 + --> $DIR/variadic-ffi-semantic-restrictions.rs:31:20 | LL | extern "C" fn f3_3(..., x: isize) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:36:13 | LL | fn e_f1(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:37:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:38:13 | LL | fn e_f2(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:44:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:45:23 | LL | fn i_f1(x: isize, ...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13 | LL | fn i_f2(...) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13 | LL | fn i_f2(...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:49:28 + --> $DIR/variadic-ffi-semantic-restrictions.rs:50:28 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:53:28 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23 + --> $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 - --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:63:23 | LL | fn t_f2(x: isize, ...); | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 | LL | fn t_f3(...) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 | LL | fn t_f3(...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13 | LL | fn t_f4(...); | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13 | LL | fn t_f4(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13 | LL | fn t_f6(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13 | LL | fn t_f6(..., x: isize); | ^^^ diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs index ca8826f03f..cffff80eea 100644 --- a/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs @@ -3,7 +3,6 @@ // run-pass #![feature(bindings_after_at)] -#![feature(or_patterns)] #![feature(box_patterns)] #[derive(Debug, PartialEq)] diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs index 65c2b3741b..a99ec0158f 100644 --- a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs @@ -3,7 +3,6 @@ // run-pass #![feature(bindings_after_at)] -#![feature(or_patterns)] #[derive(Debug, PartialEq)] enum MatchArm { diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns.rs index a0e14004ab..caf6d91e00 100644 --- a/src/test/ui/pattern/bindings-after-at/or-patterns.rs +++ b/src/test/ui/pattern/bindings-after-at/or-patterns.rs @@ -3,7 +3,6 @@ // run-pass #![feature(bindings_after_at)] -#![feature(or_patterns)] #[derive(Debug, PartialEq)] enum MatchArm { diff --git a/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.rs b/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.rs index e8b5b492b7..09df15f754 100644 --- a/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.rs +++ b/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.rs @@ -2,7 +2,6 @@ // The code that is tested here lives in resolve (see `resolve_pattern_inner`). #![feature(bindings_after_at)] -#![feature(or_patterns)] fn main() { fn f(a @ a @ a: ()) {} diff --git a/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr b/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr index cba17d82e9..77a4937322 100644 --- a/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr +++ b/src/test/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr @@ -1,59 +1,59 @@ error[E0415]: identifier `a` is bound more than once in this parameter list - --> $DIR/pat-at-same-name-both.rs:8:14 + --> $DIR/pat-at-same-name-both.rs:7:14 | LL | fn f(a @ a @ a: ()) {} | ^ used as parameter more than once error[E0415]: identifier `a` is bound more than once in this parameter list - --> $DIR/pat-at-same-name-both.rs:8:18 + --> $DIR/pat-at-same-name-both.rs:7:18 | LL | fn f(a @ a @ a: ()) {} | ^ used as parameter more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:13:20 + --> $DIR/pat-at-same-name-both.rs:12:20 | LL | Ok(a @ b @ a) | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:15:23 + --> $DIR/pat-at-same-name-both.rs:14:23 | LL | | Err(a @ b @ a) | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:20:13 + --> $DIR/pat-at-same-name-both.rs:19:13 | LL | let a @ a @ a = (); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:20:17 + --> $DIR/pat-at-same-name-both.rs:19:17 | LL | let a @ a @ a = (); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:23:21 + --> $DIR/pat-at-same-name-both.rs:22:21 | LL | let ref a @ ref a = (); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:25:29 + --> $DIR/pat-at-same-name-both.rs:24:29 | LL | let ref mut a @ ref mut a = (); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:28:17 + --> $DIR/pat-at-same-name-both.rs:27:17 | LL | let a @ (Ok(a) | Err(a)) = Ok(()); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/pat-at-same-name-both.rs:28:26 + --> $DIR/pat-at-same-name-both.rs:27:26 | LL | let a @ (Ok(a) | Err(a)) = Ok(()); | ^ used in a pattern more than once diff --git a/src/test/ui/issues/issue-10392.rs b/src/test/ui/pattern/issue-10392.rs similarity index 100% rename from src/test/ui/issues/issue-10392.rs rename to src/test/ui/pattern/issue-10392.rs diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr index 285c203f38..d0726f05cc 100644 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -16,7 +16,7 @@ LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; | --- | | | first assignment to `_x1` - | help: make this binding mutable: `mut _x1` + | help: consider making this binding mutable: `mut _x1` LL | _x1 = U; | ^^^^^^^ cannot assign twice to immutable variable @@ -74,7 +74,7 @@ LL | let (ref _x0, _x1, ref _x2, ..) = tup; | --- | | | first assignment to `_x1` - | help: make this binding mutable: `mut _x1` + | help: consider making this binding mutable: `mut _x1` LL | _x1 = U; | ^^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs b/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs index 75658c490c..7c9aa51e74 100644 --- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs +++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { } //~^ ERROR refutable pattern in function argument: `(_, _)` not covered diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr index 99af71cadf..74ec646e31 100644 --- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr +++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -1,5 +1,5 @@ error[E0005]: refutable pattern in function argument: `(_, _)` not covered - --> $DIR/refutable-pattern-errors.rs:3:9 + --> $DIR/refutable-pattern-errors.rs:1:9 | LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { } | ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered @@ -7,7 +7,7 @@ LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { } = note: the matched value is of type `(isize, (Option<isize>, isize))` error[E0005]: refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered - --> $DIR/refutable-pattern-errors.rs:7:9 + --> $DIR/refutable-pattern-errors.rs:5:9 | LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); | ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered diff --git a/src/test/ui/phantom-auto-trait.stderr b/src/test/ui/phantom-auto-trait.stderr index 779919f9d6..de13176ddc 100644 --- a/src/test/ui/phantom-auto-trait.stderr +++ b/src/test/ui/phantom-auto-trait.stderr @@ -7,13 +7,21 @@ LL | fn is_zen<T: Zen>(_: T) {} LL | is_zen(x) | ^ `T` cannot be shared between threads safely | - = note: required because of the requirements on the impl of `Zen` for `&T` +note: required because of the requirements on the impl of `Zen` for `&T` + --> $DIR/phantom-auto-trait.rs:10:24 + | +LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} + | ^^^ ^^^^^ = note: required because it appears within the type `PhantomData<&T>` - = note: required because it appears within the type `Guard<'_, T>` +note: required because it appears within the type `Guard<'_, T>` + --> $DIR/phantom-auto-trait.rs:12:8 + | +LL | struct Guard<'a, T: 'a> { + | ^^^^^ help: consider restricting type parameter `T` | -LL | fn not_sync<T: Sync>(x: Guard<T>) { - | ^^^^^^ +LL | fn not_sync<T: std::marker::Sync>(x: Guard<T>) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` cannot be shared between threads safely --> $DIR/phantom-auto-trait.rs:26:12 @@ -24,14 +32,26 @@ LL | fn is_zen<T: Zen>(_: T) {} LL | is_zen(x) | ^ `T` cannot be shared between threads safely | - = note: required because of the requirements on the impl of `Zen` for `&T` +note: required because of the requirements on the impl of `Zen` for `&T` + --> $DIR/phantom-auto-trait.rs:10:24 + | +LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} + | ^^^ ^^^^^ = note: required because it appears within the type `PhantomData<&T>` - = note: required because it appears within the type `Guard<'_, T>` - = note: required because it appears within the type `Nested<Guard<'_, T>>` +note: required because it appears within the type `Guard<'_, T>` + --> $DIR/phantom-auto-trait.rs:12:8 + | +LL | struct Guard<'a, T: 'a> { + | ^^^^^ +note: required because it appears within the type `Nested<Guard<'_, T>>` + --> $DIR/phantom-auto-trait.rs:16:8 + | +LL | struct Nested<T>(T); + | ^^^^^^ help: consider restricting type parameter `T` | -LL | fn nested_not_sync<T: Sync>(x: Nested<Guard<T>>) { - | ^^^^^^ +LL | fn nested_not_sync<T: std::marker::Sync>(x: Nested<Guard<T>>) { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs index b4e98debcf..c07aeed99c 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.rs +++ b/src/test/ui/privacy/associated-item-privacy-trait.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![feature(decl_macro, associated_type_defaults)] #![allow(unused, private_in_public)] diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index 8e58a2fa08..e36ce8d541 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -1,5 +1,5 @@ error: type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private - --> $DIR/associated-item-privacy-trait.rs:17:21 + --> $DIR/associated-item-privacy-trait.rs:15:21 | LL | let value = <Pub as PrivTr>::method; | ^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -10,7 +10,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private - --> $DIR/associated-item-privacy-trait.rs:19:9 + --> $DIR/associated-item-privacy-trait.rs:17:9 | LL | value; | ^^^^^ private type @@ -21,7 +21,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'r> fn(&'r Self) {<Self as PrivTr>::method}` is private - --> $DIR/associated-item-privacy-trait.rs:21:13 + --> $DIR/associated-item-privacy-trait.rs:19:13 | LL | Pub.method(); | ^^^^^^ private type @@ -32,7 +32,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: associated constant `<Pub as PrivTr>::CONST` is private - --> $DIR/associated-item-privacy-trait.rs:23:9 + --> $DIR/associated-item-privacy-trait.rs:21:9 | LL | <Pub as PrivTr>::CONST; | ^^^^^^^^^^^^^^^^^^^^^^ private associated constant @@ -43,7 +43,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: associated type `<Pub as PrivTr>::AssocTy` is private - --> $DIR/associated-item-privacy-trait.rs:25:16 + --> $DIR/associated-item-privacy-trait.rs:23:16 | LL | let _: <Pub as PrivTr>::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^ private associated type @@ -54,7 +54,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:27:34 + --> $DIR/associated-item-privacy-trait.rs:25:34 | LL | pub type InSignatureTy = <Pub as PrivTr>::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^ private trait @@ -65,7 +65,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:29:34 + --> $DIR/associated-item-privacy-trait.rs:27:34 | LL | pub trait InSignatureTr: PrivTr {} | ^^^^^^ private trait @@ -76,7 +76,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:31:14 + --> $DIR/associated-item-privacy-trait.rs:29:14 | LL | impl PrivTr for u8 {} | ^^^^^^ private trait @@ -87,7 +87,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:48:21 + --> $DIR/associated-item-privacy-trait.rs:46:21 | LL | let value = <Pub as PubTr>::method; | ^^^^^^^^^^^^^^^^^^^^^^ private type @@ -98,7 +98,7 @@ LL | priv_signature::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:50:9 + --> $DIR/associated-item-privacy-trait.rs:48:9 | LL | value; | ^^^^^ private type @@ -109,7 +109,7 @@ LL | priv_signature::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:52:13 + --> $DIR/associated-item-privacy-trait.rs:50:13 | LL | Pub.method(loop {}); | ^^^^^^ private type @@ -120,7 +120,7 @@ LL | priv_signature::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:69:21 + --> $DIR/associated-item-privacy-trait.rs:67:21 | LL | let value = <Pub as PubTr>::method::<Priv>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -131,7 +131,7 @@ LL | priv_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:71:9 + --> $DIR/associated-item-privacy-trait.rs:69:9 | LL | value; | ^^^^^ private type @@ -142,7 +142,7 @@ LL | priv_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:73:9 + --> $DIR/associated-item-privacy-trait.rs:71:9 | LL | Pub.method::<Priv>(); | ^^^^^^^^^^^^^^^^^^^^ private type @@ -153,7 +153,7 @@ LL | priv_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:93:21 + --> $DIR/associated-item-privacy-trait.rs:91:21 | LL | let value = <Pub as PubTr>::method; | ^^^^^^^^^^^^^^^^^^^^^^ private type @@ -164,7 +164,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:95:9 + --> $DIR/associated-item-privacy-trait.rs:93:9 | LL | value; | ^^^^^ private type @@ -175,7 +175,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:97:21 + --> $DIR/associated-item-privacy-trait.rs:95:21 | LL | let value = <Pub as PubTr<_>>::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -186,7 +186,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:99:9 + --> $DIR/associated-item-privacy-trait.rs:97:9 | LL | value; | ^^^^^ private type @@ -197,7 +197,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:101:9 + --> $DIR/associated-item-privacy-trait.rs:99:9 | LL | Pub.method(); | ^^^^^^^^^^^^ private type @@ -208,7 +208,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:104:21 + --> $DIR/associated-item-privacy-trait.rs:102:21 | LL | let value = <Priv as PubTr<_>>::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -219,7 +219,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:106:9 + --> $DIR/associated-item-privacy-trait.rs:104:9 | LL | value; | ^^^^^ private type @@ -230,7 +230,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:108:9 + --> $DIR/associated-item-privacy-trait.rs:106:9 | LL | Priv.method(); | ^^^^^^^^^^^^^ private type @@ -241,7 +241,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:111:9 + --> $DIR/associated-item-privacy-trait.rs:109:9 | LL | <Pub as PubTr>::CONST; | ^^^^^^^^^^^^^^^^^^^^^ private type @@ -252,7 +252,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:113:9 + --> $DIR/associated-item-privacy-trait.rs:111:9 | LL | <Pub as PubTr<_>>::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -263,7 +263,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:115:9 + --> $DIR/associated-item-privacy-trait.rs:113:9 | LL | <Priv as PubTr<_>>::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -274,7 +274,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:119:30 + --> $DIR/associated-item-privacy-trait.rs:117:30 | LL | let _: <Pub as PubTr<_>>::AssocTy; | ^ private type @@ -285,7 +285,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:121:17 + --> $DIR/associated-item-privacy-trait.rs:119:17 | LL | let _: <Priv as PubTr<_>>::AssocTy; | ^^^^ private type @@ -296,7 +296,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:124:35 + --> $DIR/associated-item-privacy-trait.rs:122:35 | LL | pub type InSignatureTy1 = <Pub as PubTr>::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -307,7 +307,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:126:35 + --> $DIR/associated-item-privacy-trait.rs:124:35 | LL | pub type InSignatureTy2 = <Priv as PubTr<Pub>>::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type @@ -318,7 +318,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:128:14 + --> $DIR/associated-item-privacy-trait.rs:126:14 | LL | impl PubTr for u8 {} | ^^^^^ private type diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr index 714f28941f..d09a8aae74 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -57,6 +57,9 @@ error[E0747]: constant provided when a type was expected | LL | let _x: Box<Bar>; | ^^^ + | + = help: `Bar` is a function item, not a type + = help: function item types cannot be named directly error: aborting due to 4 previous errors diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index c7ad8ec503..fdf0549cf5 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -83,12 +83,18 @@ error[E0747]: constant provided when a type was expected | LL | let _x : Box<Bar>; | ^^^ + | + = help: `Bar` is a function item, not a type + = help: function item types cannot be named directly error[E0747]: constant provided when a type was expected --> $DIR/privacy-ns2.rs:48:17 | LL | let _x: Box<Bar>; | ^^^ + | + = help: `Bar` is a function item, not a type + = help: function item types cannot be named directly error: aborting due to 8 previous errors diff --git a/src/test/ui/proc-macro/attr-complex-fn.stdout b/src/test/ui/proc-macro/attr-complex-fn.stdout index a395a9ac3e..72783efe08 100644 --- a/src/test/ui/proc-macro/attr-complex-fn.stdout +++ b/src/test/ui/proc-macro/attr-complex-fn.stdout @@ -80,67 +80,67 @@ PRINT-ATTR INPUT (DISPLAY): impl < T > MyTrait < T > for MyStruct < { true } > { PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "impl", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:1: 21:5 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:5: 21:6 (#0), }, Ident { ident: "T", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:6: 21:7 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:7: 21:8 (#0), }, Ident { ident: "MyTrait", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:9: 21:16 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:16: 21:17 (#0), }, Ident { ident: "T", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:17: 21:18 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:18: 21:19 (#0), }, Ident { ident: "for", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:20: 21:23 (#0), }, Ident { ident: "MyStruct", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:24: 21:32 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:32: 21:33 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "true", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:34: 21:38 (#0), }, ], - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:33: 21:39 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:39: 21:40 (#0), }, Group { delimiter: Brace, @@ -148,24 +148,24 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:23:5: 23:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:23:6: 23:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:23:8: 23:19 (#0), }, ], - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:23:7: 23:20 (#0), }, ], - span: $DIR/attr-complex-fn.rs:21:1: 24:2 (#0), + span: $DIR/attr-complex-fn.rs:21:41: 24:2 (#0), }, ] diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout index 11f4923532..4c48e41ff3 100644 --- a/src/test/ui/proc-macro/attribute-after-derive.stdout +++ b/src/test/ui/proc-macro/attribute-after-derive.stdout @@ -87,32 +87,16 @@ PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive { } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0), + span: $DIR/attribute-after-derive.rs:18:1: 18:7 (#0), }, Ident { ident: "AttributeDerive", - span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0), - }, -] -PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { } -PRINT-ATTR INPUT (DEBUG): TokenStream [ - Ident { - ident: "struct", - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), - }, - Ident { - ident: "DeriveAttribute", - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:18:8: 18:23 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:18:24: 21:2 (#0), }, ] PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { } @@ -120,29 +104,45 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:24:1: 24:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_attr", - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:24:3: 24:13 (#0), }, ], - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:24:2: 24:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:25:1: 25:7 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:25:8: 25:23 (#0), }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:25:24: 28:2 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 25:7 (#0), }, Ident { ident: "DeriveAttribute", - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:25:8: 25:23 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:25:24: 28:2 (#0), }, ] diff --git a/src/test/ui/proc-macro/auxiliary/issue-75801.rs b/src/test/ui/proc-macro/auxiliary/issue-75801.rs new file mode 100644 index 0000000000..d6c031d7d4 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-75801.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn foo(_args: TokenStream, item: TokenStream) -> TokenStream { + item +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-79825.rs b/src/test/ui/proc-macro/auxiliary/issue-79825.rs new file mode 100644 index 0000000000..930891b1d4 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-79825.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn assert_input(args: TokenStream, input: TokenStream) -> TokenStream { + assert_eq!(input.to_string(), "trait Alias = Sized ;"); + assert!(args.is_empty()); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/auxiliary/issue-83510.rs b/src/test/ui/proc-macro/auxiliary/issue-83510.rs new file mode 100644 index 0000000000..1d6ef3914a --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/issue-83510.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dance_like_you_want_to_ice(_: TokenStream) -> TokenStream { + r#" + impl Foo { + type Bar = Box<()> + Baz; + } + "# + .parse() + .unwrap() +} diff --git a/src/test/ui/proc-macro/auxiliary/multiple-derives.rs b/src/test/ui/proc-macro/auxiliary/multiple-derives.rs new file mode 100644 index 0000000000..e3f6607b2a --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/multiple-derives.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +macro_rules! make_derives { + ($($name:ident),*) => { + $( + #[proc_macro_derive($name)] + pub fn $name(input: TokenStream) -> TokenStream { + println!("Derive {}: {}", stringify!($name), input); + TokenStream::new() + } + )* + } +} + +make_derives!(First, Second, Third, Fourth, Fifth); diff --git a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs index 52ebe8e7fb..27676a5cb8 100644 --- a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs +++ b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs @@ -2,14 +2,15 @@ pub struct FirstStruct; #[macro_export] macro_rules! outer_macro { - ($name:ident) => { + ($name:ident, $attr_struct_name:ident) => { #[macro_export] macro_rules! inner_macro { - ($wrapper:ident) => { - $wrapper!($name) + ($bang_macro:ident, $attr_macro:ident) => { + $bang_macro!($name); + #[$attr_macro] struct $attr_struct_name {} } } } } -outer_macro!(FirstStruct); +outer_macro!(FirstStruct, FirstAttrStruct); diff --git a/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs b/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs index a6903283aa..ea5ff46657 100644 --- a/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs +++ b/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs @@ -10,6 +10,7 @@ use proc_macro::{TokenStream, quote}; #[proc_macro_attribute] pub fn first_attr(_: TokenStream, input: TokenStream) -> TokenStream { let recollected: TokenStream = input.into_iter().collect(); + println!("First recollected: {:#?}", recollected); quote! { #[second_attr] $recollected @@ -18,6 +19,7 @@ pub fn first_attr(_: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn second_attr(_: TokenStream, input: TokenStream) -> TokenStream { - let _recollected: TokenStream = input.into_iter().collect(); + let recollected: TokenStream = input.into_iter().collect(); + println!("Second recollected: {:#?}", recollected); TokenStream::new() } diff --git a/src/test/ui/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs index 1a50036164..7a46aee462 100644 --- a/src/test/ui/proc-macro/auxiliary/test-macros.rs +++ b/src/test/ui/proc-macro/auxiliary/test-macros.rs @@ -83,21 +83,52 @@ fn print_helper(input: TokenStream, kind: &str) -> TokenStream { print_helper_ext(input, kind, true) } +fn deep_recollect(input: TokenStream) -> TokenStream { + input.into_iter().map(|tree| { + match tree { + TokenTree::Group(group) => { + let inner = deep_recollect(group.stream()); + let mut new_group = TokenTree::Group( + proc_macro::Group::new(group.delimiter(), inner) + ); + new_group.set_span(group.span()); + new_group + } + _ => tree, + } + }).collect() +} + fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream { let input_display = format!("{}", input); let input_debug = format!("{:#?}", input); - let recollected = input.into_iter().collect(); + let recollected = input.clone().into_iter().collect(); let recollected_display = format!("{}", recollected); let recollected_debug = format!("{:#?}", recollected); + + let deep_recollected = deep_recollect(input); + let deep_recollected_display = format!("{}", deep_recollected); + let deep_recollected_debug = format!("{:#?}", deep_recollected); + + + println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display); if recollected_display != input_display { println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display); } + + if deep_recollected_display != recollected_display { + println!("PRINT-{} DEEP-RE-COLLECTED (DISPLAY): {}", kind, deep_recollected_display); + } + if debug { println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug); if recollected_debug != input_debug { println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug); } + if deep_recollected_debug != recollected_debug { + println!("PRINT-{} DEEP-RE-COLLETED (DEBUG): {}", kind, deep_recollected_debug); + } } recollected } diff --git a/src/test/ui/proc-macro/cfg-eval-inner.rs b/src/test/ui/proc-macro/cfg-eval-inner.rs new file mode 100644 index 0000000000..5fd3ca0d16 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-inner.rs @@ -0,0 +1,39 @@ +// compile-flags: -Z span-debug +// aux-build:test-macros.rs +// check-pass + +#![feature(cfg_eval)] +#![feature(custom_inner_attributes)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +struct Foo<T>(T); + +impl Foo<[u8; { + #![cfg_attr(not(FALSE), rustc_dummy(cursed_inner))] + #![allow(unused)] + struct Inner { + field: [u8; { + #![cfg_attr(not(FALSE), rustc_dummy(another_cursed_inner))] + 1 + }] + } + + 0 +}]> { + #![cfg_eval] + #![print_attr] + #![cfg_attr(not(FALSE), rustc_dummy(evaluated_attr))] + + fn bar() { + #[cfg(FALSE)] let a = 1; + } +} + +fn main() {} diff --git a/src/test/ui/proc-macro/cfg-eval-inner.stdout b/src/test/ui/proc-macro/cfg-eval-inner.stdout new file mode 100644 index 0000000000..1f2b003958 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-inner.stdout @@ -0,0 +1,247 @@ +PRINT-ATTR INPUT (DISPLAY): impl Foo < +[u8 ; + { + # ! [rustc_dummy(cursed_inner)] # ! [allow(unused)] struct Inner + { field : [u8 ; { # ! [rustc_dummy(another_cursed_inner)] 1 }] } 0 + }] > { # ! [rustc_dummy(evaluated_attr)] fn bar() { } } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/cfg-eval-inner.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/cfg-eval-inner.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/cfg-eval-inner.rs:18:11: 18:13 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:18:13: 18:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:19:29: 19:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "cursed_inner", + span: $DIR/cfg-eval-inner.rs:19:41: 19:53 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:19:40: 19:54 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/cfg-eval-inner.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/cfg-eval-inner.rs:20:8: 20:13 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused", + span: $DIR/cfg-eval-inner.rs:20:14: 20:20 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:20:13: 20:21 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:20:7: 20:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/cfg-eval-inner.rs:21:5: 21:11 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/cfg-eval-inner.rs:21:12: 21:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/cfg-eval-inner.rs:22:9: 22:14 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:22:14: 22:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/cfg-eval-inner.rs:22:17: 22:19 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:22:19: 22:20 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:23:14: 23:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:23:37: 23:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "another_cursed_inner", + span: $DIR/cfg-eval-inner.rs:23:49: 23:69 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:23:48: 23:70 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/cfg-eval-inner.rs:24:13: 24:14 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:22:21: 25:10 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:22:16: 25:11 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:21:18: 26:6 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/cfg-eval-inner.rs:28:5: 28:6 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:18:15: 29:2 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:18:10: 29:3 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:29:3: 29:4 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:32:6: 32:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:32:29: 32:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "evaluated_attr", + span: $DIR/cfg-eval-inner.rs:32:41: 32:55 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:32:40: 32:56 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0), + }, + Ident { + ident: "fn", + span: $DIR/cfg-eval-inner.rs:34:5: 34:7 (#0), + }, + Ident { + ident: "bar", + span: $DIR/cfg-eval-inner.rs:34:8: 34:11 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval-inner.rs:34:11: 34:13 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/cfg-eval-inner.rs:34:14: 36:6 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:29:5: 37:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/cfg-eval.rs b/src/test/ui/proc-macro/cfg-eval.rs index ea397df545..fa6d015e48 100644 --- a/src/test/ui/proc-macro/cfg-eval.rs +++ b/src/test/ui/proc-macro/cfg-eval.rs @@ -5,7 +5,7 @@ #![feature(cfg_eval)] #![feature(proc_macro_hygiene)] #![feature(stmt_expr_attributes)] - +#![feature(rustc_attrs)] #![no_std] // Don't load unnecessary hygiene information from std extern crate std; @@ -28,5 +28,10 @@ struct S1 { struct S2 {} fn main() { - let _ = #[cfg_eval] #[print_attr](#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1); + // Subtle - we need a trailing comma after the '1' - otherwise, `#[cfg_eval]` will + // turn this into `(#[cfg(all())] 1)`, which is a parenthesized expression, not a tuple + // expression. `#[cfg]` is not supported inside parenthesized expressions, so this will + // produce an error when attribute collection runs. + let _ = #[cfg_eval] #[print_attr] #[cfg_attr(not(FALSE), rustc_dummy)] + (#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1,); } diff --git a/src/test/ui/proc-macro/cfg-eval.stdout b/src/test/ui/proc-macro/cfg-eval.stdout index b98e8961bf..6732caf08d 100644 --- a/src/test/ui/proc-macro/cfg-eval.stdout +++ b/src/test/ui/proc-macro/cfg-eval.stdout @@ -2,11 +2,11 @@ PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8 PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:17:1: 17:7 (#0), }, Ident { ident: "S1", - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:17:8: 17:10 (#0), }, Group { delimiter: Brace, @@ -14,122 +14,137 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:20:5: 20:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:20:7: 20:10 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "all", - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:20:11: 20:14 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:20:14: 20:24 (#0), }, ], - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:20:10: 20:25 (#0), }, ], - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:20:6: 20:26 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:22:5: 22:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:22:31: 22:36 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:22:36: 22:38 (#0), }, ], - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:22:5: 22:6 (#0), }, Ident { ident: "field_true", - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:23:5: 23:15 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:23:15: 23:16 (#0), }, Ident { ident: "u8", - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:23:17: 23:19 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:23:19: 23:20 (#0), }, ], - span: $DIR/cfg-eval.rs:17:1: 24:2 (#0), + span: $DIR/cfg-eval.rs:17:11: 24:2 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): (#[cfg(all())] 1,) +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] (#[cfg(all())] 1,) PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:35:39: 35:40 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval.rs:35:62: 35:73 (#0), + }, + ], + span: $DIR/cfg-eval.rs:35:39: 35:40 (#0), + }, Group { delimiter: Parenthesis, stream: TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:23: 36:24 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:25: 36:28 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "all", - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:29: 36:32 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:32: 36:42 (#0), }, ], - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:28: 36:43 (#0), }, ], - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:24: 36:44 (#0), }, Literal { kind: Integer, symbol: "1", suffix: None, - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:45: 36:46 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:46: 36:47 (#0), }, ], - span: $DIR/cfg-eval.rs:31:38: 31:80 (#0), + span: $DIR/cfg-eval.rs:36:5: 36:48 (#0), }, ] diff --git a/src/test/ui/proc-macro/derive-expand-order.rs b/src/test/ui/proc-macro/derive-expand-order.rs new file mode 100644 index 0000000000..0cf1ceb91d --- /dev/null +++ b/src/test/ui/proc-macro/derive-expand-order.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:multiple-derives.rs + +extern crate multiple_derives; + +use multiple_derives::*; + +#[derive(First)] +#[derive(Second)] +#[derive(Third, Fourth)] +#[derive(Fifth)] +pub struct Foo {} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-expand-order.stdout b/src/test/ui/proc-macro/derive-expand-order.stdout new file mode 100644 index 0000000000..3ac1adf92c --- /dev/null +++ b/src/test/ui/proc-macro/derive-expand-order.stdout @@ -0,0 +1,5 @@ +Derive First: #[derive(Second)] #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo { } +Derive Second: #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo { } +Derive Third: #[derive(Fifth)] pub struct Foo { } +Derive Fourth: #[derive(Fifth)] pub struct Foo { } +Derive Fifth: pub struct Foo { } diff --git a/src/test/ui/proc-macro/expand-to-derive.stdout b/src/test/ui/proc-macro/expand-to-derive.stdout index 7eb6864334..a6437982a3 100644 --- a/src/test/ui/proc-macro/expand-to-derive.stdout +++ b/src/test/ui/proc-macro/expand-to-derive.stdout @@ -1,40 +1,40 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo { field : - [bool ; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }], + [bool ; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }] } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:16:9: 16:15 (#4), }, Ident { ident: "Foo", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:16:16: 16:19 (#4), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "field", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:18:13: 18:18 (#4), }, Punct { ch: ':', spacing: Alone, - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:18:18: 18:19 (#4), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "bool", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:18:21: 18:25 (#4), }, Punct { ch: ';', spacing: Alone, - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:18:25: 18:26 (#4), }, Group { delimiter: Brace, @@ -42,68 +42,63 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0), }, ], - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), }, Ident { ident: "struct", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0), }, Ident { ident: "Inner", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "other_inner_field", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0), }, Ident { ident: "u8", - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0), }, ], - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:20:17: 20:18 (#4), }, ], - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:18:27: 21:14 (#4), }, ], - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:18:20: 21:15 (#4), }, ], - span: $DIR/expand-to-derive.rs:16:9: 22:10 (#4), + span: $DIR/expand-to-derive.rs:16:20: 22:10 (#4), }, ] diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr index 9b946b5e24..5a4ed65ecd 100644 --- a/src/test/ui/proc-macro/generate-mod.stderr +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -46,7 +46,8 @@ LL | #[derive(generate_mod::CheckDerive)] | = note: `#[warn(proc_macro_derive_resolution_fallback)]` 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 #50504 <https://github.com/rust-lang/rust/issues/50504> + = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: cannot find type `OuterDerive` in this scope --> $DIR/generate-mod.rs:16:10 @@ -55,7 +56,8 @@ LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | = 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 #50504 <https://github.com/rust-lang/rust/issues/50504> + = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:23:14 @@ -64,7 +66,8 @@ LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | = 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 #50504 <https://github.com/rust-lang/rust/issues/50504> + = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: cannot find type `OuterDerive` in this scope --> $DIR/generate-mod.rs:23:14 @@ -73,7 +76,8 @@ LL | #[derive(generate_mod::CheckDerive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | = 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 #50504 <https://github.com/rust-lang/rust/issues/50504> + = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> + = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors; 4 warnings emitted diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs index d9687490ca..2b742771d6 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs @@ -43,7 +43,8 @@ mod with_version { struct Foo; impl_macros!(Foo); //~ WARN using an old version //~| WARN this was previously - arrays!(Foo); + arrays!(Foo); //~ WARN using an old version + //~| WARN this was previously other!(Foo); } @@ -77,5 +78,11 @@ mod actori_web_version_test { tuple_from_req!(Foo); } +mod with_good_js_sys_version { + include!("js-sys-0.3.40/src/lib.rs"); + struct Foo; + arrays!(Foo); +} + fn main() {} diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr index e2b680f8d2..effcd68cf9 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr @@ -31,13 +31,29 @@ 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 a macro (in Nightly builds, run with -Z macro-backtrace for more info) +warning: using an old version of `js-sys` + --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 + | +LL | #[my_macro] struct Two($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:46:5 + | +LL | arrays!(Foo); + | ------------- 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = 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 a macro (in Nightly builds, run with -Z macro-backtrace for more info) + warning: using an old version of `actix-web` --> $DIR/actix-web/src/extract.rs:5:34 | LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:54:5 + ::: $DIR/group-compat-hack.rs:55:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation @@ -53,7 +69,7 @@ warning: using an old version of `actix-web` LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:62:5 + ::: $DIR/group-compat-hack.rs:63:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation @@ -63,7 +79,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 a macro (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 4 warnings emitted +warning: 5 warnings emitted Future incompatibility report: Future breakage date: None, diagnostic: warning: using an old version of `time-macros-impl` @@ -100,6 +116,23 @@ 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 a macro (in Nightly builds, run with -Z macro-backtrace for more info) +Future breakage date: None, diagnostic: +warning: using an old version of `js-sys` + --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 + | +LL | #[my_macro] struct Two($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:46:5 + | +LL | arrays!(Foo); + | ------------- 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 #83125 <https://github.com/rust-lang/rust/issues/83125> + = 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 a macro (in Nightly builds, run with -Z macro-backtrace for more info) + Future breakage date: None, diagnostic: warning: using an old version of `actix-web` --> $DIR/actix-web/src/extract.rs:5:34 @@ -107,7 +140,7 @@ warning: using an old version of `actix-web` LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:54:5 + ::: $DIR/group-compat-hack.rs:55:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation @@ -124,7 +157,7 @@ warning: using an old version of `actix-web` LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:62:5 + ::: $DIR/group-compat-hack.rs:63:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout index 3fe744e12f..82d6bc33bf 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout @@ -1,10 +1,11 @@ Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#6) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:27:18: 27:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#6) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#6) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:13: 29:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:13: 29:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:32: 5:37 (#10) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }] Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:30:12: 30:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }] Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:18: 44:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }] Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:46:13: 46:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:62:21: 62:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:70:21: 70:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:33: 5:35 (#43) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:77:21: 77:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:33: 5:35 (#48) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:48:12: 48:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:55:21: 55:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:63:21: 63:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:71:21: 71:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:33: 5:35 (#43) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:78:21: 78:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:33: 5:35 (#48) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.40/src/lib.rs:5:21: 5:27 (#53) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.40/src/lib.rs:5:28: 5:31 (#53) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:84:13: 84:16 (#0) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:32: 5:37 (#53) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:31: 5:38 (#53) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.40/src/lib.rs:5:38: 5:39 (#53) }] diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs new file mode 100644 index 0000000000..d1a66940eb --- /dev/null +++ b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs @@ -0,0 +1,7 @@ +// ignore-test this is not a test + +macro_rules! arrays { + ($name:ident) => { + #[my_macro] struct Two($name); + } +} diff --git a/src/test/ui/proc-macro/inner-attrs.rs b/src/test/ui/proc-macro/inner-attrs.rs index 6a353ca326..14ec57ad62 100644 --- a/src/test/ui/proc-macro/inner-attrs.rs +++ b/src/test/ui/proc-macro/inner-attrs.rs @@ -1,10 +1,10 @@ -// check-pass // compile-flags: -Z span-debug --error-format human // aux-build:test-macros.rs - +// edition:2018 #![feature(custom_inner_attributes)] #![feature(proc_macro_hygiene)] #![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] #![no_std] // Don't load unnecessary hygiene information from std extern crate std; @@ -19,25 +19,94 @@ fn foo() { #![print_target_and_args(fourth)] } +#[print_target_and_args(mod_first)] +#[print_target_and_args(mod_second)] +mod inline_mod { + #![print_target_and_args(mod_third)] + #![print_target_and_args(mod_fourth)] +} + struct MyStruct { field: bool } +#[derive(Print)] +struct MyDerivePrint { + field: [u8; { + match true { + #![cfg_attr(not(FALSE), rustc_dummy(first))] + #![cfg_attr(not(FALSE), rustc_dummy(second))] + _ => { + #![cfg_attr(not(FALSE), rustc_dummy(third))] + true + } + }; + 0 + }] +} + fn bar() { (#![print_target_and_args(fifth)] 1, 2); + //~^ ERROR expected non-macro inner attribute, found attribute macro + + #[print_target_and_args(tuple_attrs)] ( + #![cfg_attr(FALSE, rustc_dummy)] + 3, 4, { + #![cfg_attr(not(FALSE), rustc_dummy(innermost))] + 5 + } + ); + + #[print_target_and_args(array_attrs)] [ + #![rustc_dummy(inner)] + true; 0 + ]; + + #[print_target_and_args(tuple_attrs)] ( + #![cfg_attr(FALSE, rustc_dummy)] + 3, 4, { + #![cfg_attr(not(FALSE), rustc_dummy(innermost))] + 5 + } + ); + + #[print_target_and_args(array_attrs)] [ + #![rustc_dummy(inner)] + true; 0 + ]; [#![print_target_and_args(sixth)] 1 , 2]; + //~^ ERROR expected non-macro inner attribute, found attribute macro [#![print_target_and_args(seventh)] true ; 5]; - + //~^ ERROR expected non-macro inner attribute, found attribute macro match 0 { #![print_target_and_args(eighth)] + //~^ ERROR expected non-macro inner attribute, found attribute macro _ => {} } MyStruct { #![print_target_and_args(ninth)] field: true }; + //~^ ERROR expected non-macro inner attribute, found attribute macro + + for _ in &[true] { + #![print_attr] //~ ERROR expected non-macro inner attribute + } + + let _ = { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; + + let _ = async { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; + + { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; } + extern { fn weird_extern() { #![print_target_and_args_consume(tenth)] diff --git a/src/test/ui/proc-macro/inner-attrs.stderr b/src/test/ui/proc-macro/inner-attrs.stderr new file mode 100644 index 0000000000..7f22c5f30d --- /dev/null +++ b/src/test/ui/proc-macro/inner-attrs.stderr @@ -0,0 +1,56 @@ +error: expected non-macro inner attribute, found attribute macro `print_target_and_args` + --> $DIR/inner-attrs.rs:49:9 + | +LL | (#![print_target_and_args(fifth)] 1, 2); + | ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_target_and_args` + --> $DIR/inner-attrs.rs:78:9 + | +LL | [#![print_target_and_args(sixth)] 1 , 2]; + | ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_target_and_args` + --> $DIR/inner-attrs.rs:80:9 + | +LL | [#![print_target_and_args(seventh)] true ; 5]; + | ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_target_and_args` + --> $DIR/inner-attrs.rs:84:12 + | +LL | #![print_target_and_args(eighth)] + | ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_target_and_args` + --> $DIR/inner-attrs.rs:89:19 + | +LL | MyStruct { #![print_target_and_args(ninth)] field: true }; + | ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:93:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:97:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:101:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:105:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/proc-macro/inner-attrs.stdout b/src/test/ui/proc-macro/inner-attrs.stdout index 2fd8d8a242..2f442e8300 100644 --- a/src/test/ui/proc-macro/inner-attrs.stdout +++ b/src/test/ui/proc-macro/inner-attrs.stdout @@ -11,40 +11,40 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:16:1: 16:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:16:3: 16:24 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "second", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:16:25: 16:31 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:16:24: 16:32 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:16:2: 16:33 (#0), }, Ident { ident: "fn", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:1: 17:3 (#0), }, Ident { ident: "foo", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:4: 17:7 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:7: 17:9 (#0), }, Group { delimiter: Brace, @@ -52,72 +52,72 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:5: 18:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:6: 18:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:8: 18:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "third", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:30: 18:35 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:29: 18:36 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:7: 18:37 (#0), }, Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:5: 19:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:6: 19:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:8: 19:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "fourth", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:30: 19:36 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:29: 19:37 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:7: 19:38 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:10: 20:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): second PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "second", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:16:25: 16:31 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): fn foo() @@ -125,16 +125,16 @@ PRINT-ATTR INPUT (DISPLAY): fn foo() PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:1: 17:3 (#0), }, Ident { ident: "foo", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:4: 17:7 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:7: 17:9 (#0), }, Group { delimiter: Brace, @@ -142,88 +142,88 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:5: 18:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:6: 18:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:8: 18:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "third", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:30: 18:35 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:29: 18:36 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:7: 18:37 (#0), }, Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:5: 19:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:6: 19:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:8: 19:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "fourth", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:30: 19:36 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:29: 19:37 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:7: 19:38 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:10: 20:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): third PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "third", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:18:30: 18:35 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): fn foo() { # ! [print_target_and_args(fourth)] } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:1: 17:3 (#0), }, Ident { ident: "foo", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:4: 17:7 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:7: 17:9 (#0), }, Group { delimiter: Brace, @@ -231,290 +231,925 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:5: 19:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:6: 19:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:8: 19:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "fourth", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:30: 19:36 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:29: 19:37 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:7: 19:38 (#0), }, ], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:10: 20:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): fourth PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "fourth", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:19:30: 19:36 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): fn foo() { } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:1: 17:3 (#0), }, Ident { ident: "foo", - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:4: 17:7 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:7: 17:9 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/inner-attrs.rs:17:1: 20:2 (#0), + span: $DIR/inner-attrs.rs:17:10: 20:2 (#0), }, ] -PRINT-ATTR_ARGS INPUT (DISPLAY): fifth +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_first PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { - ident: "fifth", - span: $DIR/inner-attrs.rs:27:31: 27:36 (#0), + ident: "mod_first", + span: $DIR/inner-attrs.rs:22:25: 22:34 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): (1, 2) ; +PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod +{ + # ! [print_target_and_args(mod_third)] # ! + [print_target_and_args(mod_fourth)] +} PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:23:1: 23:2 (#0), + }, Group { - delimiter: Parenthesis, + delimiter: Bracket, stream: TokenStream [ - Literal { - kind: Integer, - symbol: "1", - suffix: None, - span: $DIR/inner-attrs.rs:27:5: 27:45 (#0), + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:23:3: 23:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_second", + span: $DIR/inner-attrs.rs:23:25: 23:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:23:24: 23:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:23:2: 23:37 (#0), + }, + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:24:1: 24:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:24:5: 24:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:25:5: 25:6 (#0), }, Punct { - ch: ',', + ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:27:5: 27:45 (#0), + span: $DIR/inner-attrs.rs:25:6: 25:7 (#0), }, - Literal { - kind: Integer, - symbol: "2", - suffix: None, - span: $DIR/inner-attrs.rs:27:5: 27:45 (#0), + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:25:8: 25:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:25:30: 25:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:29: 25:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:7: 25:41 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:26:5: 26:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:26:6: 26:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:26:8: 26:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:26:30: 26:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:29: 26:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:7: 26:42 (#0), }, ], - span: $DIR/inner-attrs.rs:27:5: 27:45 (#0), + span: $DIR/inner-attrs.rs:24:16: 27:2 (#0), }, - Punct { - ch: ';', - spacing: Alone, - span: $DIR/inner-attrs.rs:27:5: 27:45 (#0), +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_second +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_second", + span: $DIR/inner-attrs.rs:23:25: 23:35 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod +{ + # ! [print_target_and_args(mod_third)] # ! + [print_target_and_args(mod_fourth)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:24:1: 24:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:24:5: 24:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:25:5: 25:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:25:6: 25:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:25:8: 25:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:25:30: 25:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:29: 25:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:7: 25:41 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:26:5: 26:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:26:6: 26:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:26:8: 26:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:26:30: 26:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:29: 26:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:7: 26:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:24:16: 27:2 (#0), }, ] -PRINT-ATTR_ARGS INPUT (DISPLAY): sixth +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { - ident: "sixth", - span: $DIR/inner-attrs.rs:29:31: 29:36 (#0), + ident: "mod_third", + span: $DIR/inner-attrs.rs:25:30: 25:39 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): [1, 2] ; +PRINT-ATTR INPUT (DISPLAY): mod inline_mod { # ! [print_target_and_args(mod_fourth)] } PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:24:1: 24:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:24:5: 24:15 (#0), + }, Group { - delimiter: Bracket, + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:26:5: 26:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:26:6: 26:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:26:8: 26:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:26:30: 26:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:29: 26:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:7: 26:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:24:16: 27:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_fourth +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:26:30: 26:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:24:1: 24:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:24:5: 24:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:24:16: 27:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint +{ + field : + [u8 ; + { + match true + { + # ! [rustc_dummy(first)] # ! [rustc_dummy(second)] _ => + { # ! [rustc_dummy(third)] true } + } ; 0 + }] +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/inner-attrs.rs:34:1: 34:7 (#0), + }, + Ident { + ident: "MyDerivePrint", + span: $DIR/inner-attrs.rs:34:8: 34:21 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/inner-attrs.rs:35:5: 35:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/inner-attrs.rs:35:10: 35:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/inner-attrs.rs:35:13: 35:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:35:15: 35:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "match", + span: $DIR/inner-attrs.rs:36:9: 36:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/inner-attrs.rs:36:15: 36:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:37:13: 37:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:37:14: 37:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:37:37: 37:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "first", + span: $DIR/inner-attrs.rs:37:49: 37:54 (#0), + }, + ], + span: $DIR/inner-attrs.rs:37:48: 37:55 (#0), + }, + ], + span: $DIR/inner-attrs.rs:37:13: 37:14 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:38:13: 38:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:38:14: 38:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:38:37: 38:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second", + span: $DIR/inner-attrs.rs:38:49: 38:55 (#0), + }, + ], + span: $DIR/inner-attrs.rs:38:48: 38:56 (#0), + }, + ], + span: $DIR/inner-attrs.rs:38:13: 38:14 (#0), + }, + Ident { + ident: "_", + span: $DIR/inner-attrs.rs:39:13: 39:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/inner-attrs.rs:39:15: 39:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/inner-attrs.rs:39:15: 39:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:40:17: 40:18 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:40:18: 40:19 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:40:41: 40:52 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:40:53: 40:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:40:52: 40:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:40:17: 40:18 (#0), + }, + Ident { + ident: "true", + span: $DIR/inner-attrs.rs:41:17: 41:21 (#0), + }, + ], + span: $DIR/inner-attrs.rs:39:18: 42:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:36:20: 43:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:43:10: 43:11 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/inner-attrs.rs:44:9: 44:10 (#0), + }, + ], + span: $DIR/inner-attrs.rs:35:17: 45:6 (#0), + }, + ], + span: $DIR/inner-attrs.rs:35:12: 45:7 (#0), + }, + ], + span: $DIR/inner-attrs.rs:34:22: 46:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "tuple_attrs", + span: $DIR/inner-attrs.rs:52:29: 52:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): (3, 4, { # ! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Group { + delimiter: Parenthesis, stream: TokenStream [ Literal { kind: Integer, - symbol: "1", + symbol: "3", suffix: None, - span: $DIR/inner-attrs.rs:29:5: 29:46 (#0), + span: $DIR/inner-attrs.rs:54:9: 54:10 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/inner-attrs.rs:29:5: 29:46 (#0), + span: $DIR/inner-attrs.rs:54:10: 54:11 (#0), }, Literal { kind: Integer, - symbol: "2", + symbol: "4", suffix: None, - span: $DIR/inner-attrs.rs:29:5: 29:46 (#0), + span: $DIR/inner-attrs.rs:54:12: 54:13 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:54:13: 54:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:55:13: 55:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:55:14: 55:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/inner-attrs.rs:55:16: 55:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/inner-attrs.rs:55:25: 55:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/inner-attrs.rs:55:29: 55:34 (#0), + }, + ], + span: $DIR/inner-attrs.rs:55:28: 55:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:55:35: 55:36 (#0), + }, + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:55:37: 55:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "innermost", + span: $DIR/inner-attrs.rs:55:49: 55:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:55:48: 55:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:55:24: 55:60 (#0), + }, + ], + span: $DIR/inner-attrs.rs:55:15: 55:61 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/inner-attrs.rs:56:13: 56:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:54:15: 57:10 (#0), }, ], - span: $DIR/inner-attrs.rs:29:5: 29:46 (#0), + span: $DIR/inner-attrs.rs:52:43: 58:6 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:29:5: 29:46 (#0), + span: $DIR/inner-attrs.rs:58:6: 58:7 (#0), }, ] -PRINT-ATTR_ARGS INPUT (DISPLAY): seventh +PRINT-ATTR_ARGS INPUT (DISPLAY): array_attrs PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { - ident: "seventh", - span: $DIR/inner-attrs.rs:30:31: 30:38 (#0), + ident: "array_attrs", + span: $DIR/inner-attrs.rs:60:29: 60:40 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): [true ; 5] ; +PRINT-ATTR INPUT (DISPLAY): [# ! [rustc_dummy(inner)] true ; 0] ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:61:9: 61:10 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:61:10: 61:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:61:12: 61:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "inner", + span: $DIR/inner-attrs.rs:61:24: 61:29 (#0), + }, + ], + span: $DIR/inner-attrs.rs:61:23: 61:30 (#0), + }, + ], + span: $DIR/inner-attrs.rs:61:11: 61:31 (#0), + }, Ident { ident: "true", - span: $DIR/inner-attrs.rs:30:5: 30:51 (#0), + span: $DIR/inner-attrs.rs:62:9: 62:13 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:30:5: 30:51 (#0), + span: $DIR/inner-attrs.rs:62:13: 62:14 (#0), }, Literal { kind: Integer, - symbol: "5", + symbol: "0", suffix: None, - span: $DIR/inner-attrs.rs:30:5: 30:51 (#0), + span: $DIR/inner-attrs.rs:62:15: 62:16 (#0), }, ], - span: $DIR/inner-attrs.rs:30:5: 30:51 (#0), + span: $DIR/inner-attrs.rs:60:43: 63:6 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:30:5: 30:51 (#0), + span: $DIR/inner-attrs.rs:63:6: 63:7 (#0), }, ] -PRINT-ATTR_ARGS INPUT (DISPLAY): eighth +PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { - ident: "eighth", - span: $DIR/inner-attrs.rs:34:34: 34:40 (#0), + ident: "tuple_attrs", + span: $DIR/inner-attrs.rs:65:29: 65:40 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): match 0 { _ => { } } +PRINT-ATTR INPUT (DISPLAY): (3, 4, { # ! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ - Ident { - ident: "match", - span: $DIR/inner-attrs.rs:33:5: 36:6 (#0), - }, - Literal { - kind: Integer, - symbol: "0", - suffix: None, - span: $DIR/inner-attrs.rs:33:5: 36:6 (#0), - }, Group { - delimiter: Brace, + delimiter: Parenthesis, stream: TokenStream [ - Ident { - ident: "_", - span: $DIR/inner-attrs.rs:33:5: 36:6 (#0), + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/inner-attrs.rs:67:9: 67:10 (#0), }, Punct { - ch: '=', - spacing: Joint, - span: $DIR/inner-attrs.rs:33:5: 36:6 (#0), + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:67:10: 67:11 (#0), + }, + Literal { + kind: Integer, + symbol: "4", + suffix: None, + span: $DIR/inner-attrs.rs:67:12: 67:13 (#0), }, Punct { - ch: '>', + ch: ',', spacing: Alone, - span: $DIR/inner-attrs.rs:33:5: 36:6 (#0), + span: $DIR/inner-attrs.rs:67:13: 67:14 (#0), }, Group { delimiter: Brace, - stream: TokenStream [], - span: $DIR/inner-attrs.rs:33:5: 36:6 (#0), + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:68:13: 68:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:68:14: 68:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/inner-attrs.rs:68:16: 68:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/inner-attrs.rs:68:25: 68:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/inner-attrs.rs:68:29: 68:34 (#0), + }, + ], + span: $DIR/inner-attrs.rs:68:28: 68:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:68:35: 68:36 (#0), + }, + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:68:37: 68:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "innermost", + span: $DIR/inner-attrs.rs:68:49: 68:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:68:48: 68:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:68:24: 68:60 (#0), + }, + ], + span: $DIR/inner-attrs.rs:68:15: 68:61 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/inner-attrs.rs:69:13: 69:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:67:15: 70:10 (#0), }, ], - span: $DIR/inner-attrs.rs:33:5: 36:6 (#0), + span: $DIR/inner-attrs.rs:65:43: 71:6 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:71:6: 71:7 (#0), }, ] -PRINT-ATTR_ARGS INPUT (DISPLAY): ninth +PRINT-ATTR_ARGS INPUT (DISPLAY): array_attrs PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { - ident: "ninth", - span: $DIR/inner-attrs.rs:38:41: 38:46 (#0), + ident: "array_attrs", + span: $DIR/inner-attrs.rs:73:29: 73:40 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): MyStruct { field : true, } ; +PRINT-ATTR INPUT (DISPLAY): [# ! [rustc_dummy(inner)] true ; 0] ; PRINT-ATTR INPUT (DEBUG): TokenStream [ - Ident { - ident: "MyStruct", - span: $DIR/inner-attrs.rs:38:5: 38:63 (#0), - }, Group { - delimiter: Brace, + delimiter: Bracket, stream: TokenStream [ - Ident { - ident: "field", - span: $DIR/inner-attrs.rs:38:5: 38:63 (#0), + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:74:9: 74:10 (#0), }, Punct { - ch: ':', + ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:38:5: 38:63 (#0), + span: $DIR/inner-attrs.rs:74:10: 74:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:74:12: 74:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "inner", + span: $DIR/inner-attrs.rs:74:24: 74:29 (#0), + }, + ], + span: $DIR/inner-attrs.rs:74:23: 74:30 (#0), + }, + ], + span: $DIR/inner-attrs.rs:74:11: 74:31 (#0), }, Ident { ident: "true", - span: $DIR/inner-attrs.rs:38:5: 38:63 (#0), + span: $DIR/inner-attrs.rs:75:9: 75:13 (#0), }, Punct { - ch: ',', + ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:38:5: 38:63 (#0), + span: $DIR/inner-attrs.rs:75:13: 75:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/inner-attrs.rs:75:15: 75:16 (#0), }, ], - span: $DIR/inner-attrs.rs:38:5: 38:63 (#0), + span: $DIR/inner-attrs.rs:73:43: 76:6 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:38:5: 38:63 (#0), + span: $DIR/inner-attrs.rs:76:6: 76:7 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): tenth PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "tenth", - span: $DIR/inner-attrs.rs:43:42: 43:47 (#0), + span: $DIR/inner-attrs.rs:112:42: 112:47 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): fn weird_extern() { } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", - span: $DIR/inner-attrs.rs:42:5: 44:6 (#0), + span: $DIR/inner-attrs.rs:111:5: 111:7 (#0), }, Ident { ident: "weird_extern", - span: $DIR/inner-attrs.rs:42:5: 44:6 (#0), + span: $DIR/inner-attrs.rs:111:8: 111:20 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:42:5: 44:6 (#0), + span: $DIR/inner-attrs.rs:111:20: 111:22 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/inner-attrs.rs:42:5: 44:6 (#0), + span: $DIR/inner-attrs.rs:111:23: 113:6 (#0), }, ] diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr index 2b2e28fdb2..079e134c6f 100644 --- a/src/test/ui/proc-macro/issue-36935.stderr +++ b/src/test/ui/proc-macro/issue-36935.stderr @@ -1,11 +1,3 @@ -error: proc-macro derive panicked - --> $DIR/issue-36935.rs:6:20 - | -LL | #[derive(Identity, Panic)] - | ^^^^^ - | - = help: message: panic-derive - error[E0428]: the name `Baz` is defined multiple times --> $DIR/issue-36935.rs:7:1 | @@ -17,6 +9,14 @@ LL | struct Baz { | = note: `Baz` must be defined only once in the type namespace of this module +error: proc-macro derive panicked + --> $DIR/issue-36935.rs:6:20 + | +LL | #[derive(Identity, Panic)] + | ^^^^^ + | + = help: message: panic-derive + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs index a59cacb8bd..039878af56 100644 --- a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs +++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -3,6 +3,5 @@ // Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely. // `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`. #![feature(custom_inner_attributes)] -//~^ ERROR `main` function not found in crate `issue_59191_replace_root_with_fn` [E0601] #![issue_59191::no_main] //~^ ERROR expected crate top-level item to be a module after macro expansion, found a function diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr index 5995a4891f..579041c525 100644 --- a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr +++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr @@ -1,19 +1,10 @@ error: expected crate top-level item to be a module after macro expansion, found a function - --> $DIR/issue-59191-replace-root-with-fn.rs:7:1 + --> $DIR/issue-59191-replace-root-with-fn.rs:6:1 | LL | #![issue_59191::no_main] | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0601]: `main` function not found in crate `issue_59191_replace_root_with_fn` - --> $DIR/issue-59191-replace-root-with-fn.rs:5:1 - | -LL | / #![feature(custom_inner_attributes)] -LL | | -LL | | #![issue_59191::no_main] - | |________________________^ consider adding a `main` function to `$DIR/issue-59191-replace-root-with-fn.rs` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/proc-macro/issue-75801.rs b/src/test/ui/proc-macro/issue-75801.rs new file mode 100644 index 0000000000..b07cde0fab --- /dev/null +++ b/src/test/ui/proc-macro/issue-75801.rs @@ -0,0 +1,19 @@ +// aux-build: issue-75801.rs + +// Regression test for #75801. + +#[macro_use] +extern crate issue_75801; + +macro_rules! foo { + ($arg:expr) => { + #[foo] + fn bar() { + let _bar: u32 = $arg; + } + }; +} + +foo!("baz"); //~ ERROR: mismatched types [E0308] + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-75801.stderr b/src/test/ui/proc-macro/issue-75801.stderr new file mode 100644 index 0000000000..ee0a9bd778 --- /dev/null +++ b/src/test/ui/proc-macro/issue-75801.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-75801.rs:17:6 + | +LL | let _bar: u32 = $arg; + | --- expected due to this +... +LL | foo!("baz"); + | ^^^^^ expected `u32`, found `&str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout index 7cbc0c669a..d7adc5331c 100644 --- a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout @@ -1279,152 +1279,152 @@ PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_hel [u8 ; { #[cfg(not(FALSE))] struct Inner ; match true - { #[allow(warnings)] false => { } _ => { } } ; #[print_helper(c)] + { #[allow(warnings)] false => { }, _ => { } } ; #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { # ! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum - { Foo(#[cfg(not(FALSE))] i32, u8), } struct + { Foo(#[cfg(not(FALSE))] i32, u8) } struct TupleStruct(#[cfg(not(FALSE))] i32, u8) ; 0 - }], #[print_helper(d)] fourth : B, + }], #[print_helper(d)] fourth : B } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "a", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "dead_code", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:39 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:40 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:1: 24:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:3: 24:15 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "b", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:17 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:18 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:2: 24:19 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:1: 25:7 (#0), }, Ident { ident: "Foo", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:8: 25:11 (#0), }, Punct { ch: '<', - spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:12 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:29: 25:30 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:31 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "second", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:46 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:46: 27:47 (#0), }, Ident { ident: "bool", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:48: 27:52 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:52: 27:53 (#0), }, Ident { ident: "third", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:5: 28:10 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:11 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:15 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:16 (#0), }, Group { delimiter: Brace, @@ -1432,58 +1432,58 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:9: 30:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:11: 30:14 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:10: 30:27 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:34 (#0), }, Ident { ident: "Inner", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:40 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:40: 30:41 (#0), }, Ident { ident: "match", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:32:9: 32:14 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:19 (#0), }, Group { delimiter: Brace, @@ -1491,146 +1491,151 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:36: 34:41 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "warnings", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:42: 34:50 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:41: 34:51 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), }, Ident { ident: "false", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:54: 34:59 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:34:63: 34:65 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:65: 34:66 (#0), }, Ident { ident: "_", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:18: 35:20 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:32:20: 36:10 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:36:10: 36:11 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:11: 43:23 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "c", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:24: 43:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:23: 43:26 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:10: 43:27 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:28: 43:29 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:30: 43:33 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:34: 43:37 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:38: 43:43 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:37: 43:44 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:33: 43:45 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:29: 43:46 (#0), }, Ident { ident: "fn", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:47: 43:49 (#0), }, Ident { ident: "kept_fn", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:50: 43:57 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:57: 43:59 (#0), }, Group { delimiter: Brace, @@ -1638,82 +1643,82 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:14 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:15 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:16: 44:19 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:20: 44:23 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:24: 44:29 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:23: 44:30 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:19: 44:31 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:44:15: 44:32 (#0), }, Ident { ident: "let", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0), }, Ident { ident: "my_val", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:23 (#0), }, Punct { ch: '=', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:24: 45:25 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:26: 45:30 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:30: 45:31 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:43:60: 46:10 (#0), }, Ident { ident: "enum", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:9: 48:13 (#0), }, Ident { ident: "TupleEnum", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:14: 48:23 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "Foo", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:13: 49:16 (#0), }, Group { delimiter: Parenthesis, @@ -1721,69 +1726,64 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:17: 52:18 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:19: 52:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:23: 52:26 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:27: 52:32 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:26: 52:33 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:22: 52:34 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:18: 52:35 (#0), }, Ident { ident: "i32", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:36: 52:39 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:39: 52:40 (#0), }, Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:53:39: 53:41 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:16: 54:14 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:24: 55:10 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:9: 57:15 (#0), }, Ident { ident: "TupleStruct", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:16: 57:27 (#0), }, Group { delimiter: Parenthesis, @@ -1791,120 +1791,115 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:13: 59:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:15: 59:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:19: 59:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:23: 59:28 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:22: 59:29 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:18: 59:30 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:14: 59:31 (#0), }, Ident { ident: "i32", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:32: 59:35 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:35: 59:36 (#0), }, Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:61:13: 61:15 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:27: 62:10 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:62:10: 62:11 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:68:9: 68:10 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:17: 69:6 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:12: 69:7 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:69:7: 69:8 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:70:5: 70:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:70:7: 70:19 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "d", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:70:20: 70:21 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:70:19: 70:22 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:70:6: 70:23 (#0), }, Ident { ident: "fourth", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:71:5: 71:11 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:71:11: 71:12 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:71:13: 71:14 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:1: 72:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:32: 72:2 (#0), }, ] diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout index 40da5aa93b..607c2954c7 100644 --- a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout +++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout @@ -1,6 +1,7 @@ PRINT-BANG INPUT (DISPLAY): foo ! { #[fake_attr] mod bar { #![doc = r" Foo"] } } +PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo ! { #[fake_attr] mod bar { # ! [doc = r" Foo"] } } PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "foo", @@ -34,48 +35,48 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "mod", - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 27:8 (#0), }, Ident { ident: "bar", - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:27:9: 27:12 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Punct { ch: '#', - spacing: Joint, - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "doc", - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), }, Punct { ch: '=', spacing: Alone, - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), }, Literal { kind: StrRaw(0), symbol: " Foo", suffix: None, - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), }, ], - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), }, ], - span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0), + span: $DIR/issue-78675-captured-inner-attrs.rs:27:13: 29:6 (#0), }, ], span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4), diff --git a/src/test/ui/proc-macro/issue-79825.rs b/src/test/ui/proc-macro/issue-79825.rs new file mode 100644 index 0000000000..f628469ce3 --- /dev/null +++ b/src/test/ui/proc-macro/issue-79825.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:issue-79825.rs +#![feature(trait_alias)] + +extern crate issue_79825; + +#[issue_79825::assert_input] +trait Alias = Sized; + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-81555.rs b/src/test/ui/proc-macro/issue-81555.rs new file mode 100644 index 0000000000..693f1f7dc3 --- /dev/null +++ b/src/test/ui/proc-macro/issue-81555.rs @@ -0,0 +1,15 @@ +// check-pass +// aux-build:test-macros.rs +#![feature(stmt_expr_attributes, proc_macro_hygiene)] + +extern crate test_macros; + +use test_macros::identity_attr; + +#[identity_attr] +fn main() { + let _x; + let y = (); + #[identity_attr] + _x = y; +} diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs new file mode 100644 index 0000000000..25adc5d257 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs @@ -0,0 +1,10 @@ +// Regression test for issue #83469 +// Ensures that we recover from `#[global_alloc]` on an invalid +// stmt without an ICE + +fn outer() { + #[global_allocator] + fn inner() {} //~ ERROR allocators must be statics +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr new file mode 100644 index 0000000000..ec0e3c4c75 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr @@ -0,0 +1,8 @@ +error: allocators must be statics + --> $DIR/issue-83469-global-alloc-invalid-stmt.rs:7:5 + | +LL | fn inner() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/issue-83510.rs b/src/test/ui/proc-macro/issue-83510.rs new file mode 100644 index 0000000000..2b1aec4df0 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83510.rs @@ -0,0 +1,11 @@ +// aux-build: issue-83510.rs + +extern crate issue_83510; + +issue_83510::dance_like_you_want_to_ice!(); +//~^ ERROR: cannot find type `Foo` in this scope +//~| ERROR: expected trait, found struct `Box` +//~| ERROR: cannot find trait `Baz` in this scope +//~| ERROR: inherent associated types are unstable + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-83510.stderr b/src/test/ui/proc-macro/issue-83510.stderr new file mode 100644 index 0000000000..e080355090 --- /dev/null +++ b/src/test/ui/proc-macro/issue-83510.stderr @@ -0,0 +1,38 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0404]: expected trait, found struct `Box` + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0405]: cannot find trait `Baz` in this scope + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: inherent associated types are unstable + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0404, E0405, E0412, E0658. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout b/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout index 5db18590bd..a0b0cbb19e 100644 --- a/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout +++ b/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout @@ -5,172 +5,167 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo { let a = #[rustc_dummy(first)] #[rustc_dummy(second)] { # ! [allow(unused)] 30 } ; 0 - }], + }] } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:17:9: 17:15 (#4), }, Ident { ident: "Foo", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:17:16: 17:19 (#4), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "val", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:16 (#4), }, Punct { ch: ':', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:18:16: 18:17 (#4), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "bool", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:18:19: 18:23 (#4), }, Punct { ch: ';', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:18:23: 18:24 (#4), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:17: 19:20 (#4), }, Ident { ident: "a", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:21: 19:22 (#4), }, Punct { ch: '=', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:23: 19:24 (#4), }, Punct { ch: '#', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:48: 19:59 (#4), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "first", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:60: 19:65 (#4), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:59: 19:66 (#4), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4), }, Punct { ch: '#', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:26:36: 26:47 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "second", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:26:48: 26:54 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:26:47: 26:55 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Punct { ch: '#', - spacing: Joint, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:27:6: 27:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:27:29: 27:34 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "unused", - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:27:35: 27:41 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:27:34: 27:42 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0), }, Literal { kind: Integer, symbol: "30", suffix: None, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:28:5: 28:7 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:26:58: 29:2 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:19:74: 19:75 (#4), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:20:17: 20:18 (#4), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:18:25: 21:14 (#4), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:18:18: 21:15 (#4), }, ], - span: $DIR/macro-rules-derive-cfg.rs:17:9: 22:10 (#4), + span: $DIR/macro-rules-derive-cfg.rs:17:20: 22:10 (#4), }, ] diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs index 7e839f747f..2536b2fa90 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.rs +++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // aux-build:make-macro.rs // aux-build:meta-macro.rs // edition:2018 diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout index aa51fc8240..b7a37ab10e 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -1,8 +1,7 @@ Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) -Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }] +Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:23:37: 23:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:23:43: 23:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:23:43: 23:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:23:45: 23:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:23:50: 23:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:23:51: 23:53 (#4) }] Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }] #![feature /* 0#0 */(prelude_import)] -// ignore-tidy-linelength // aux-build:make-macro.rs // aux-build:meta-macro.rs // edition:2018 diff --git a/src/test/ui/proc-macro/nested-derive-cfg.stdout b/src/test/ui/proc-macro/nested-derive-cfg.stdout index cf4e5d94d8..9a562c971c 100644 --- a/src/test/ui/proc-macro/nested-derive-cfg.stdout +++ b/src/test/ui/proc-macro/nested-derive-cfg.stdout @@ -1,94 +1,81 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo -{ - my_array : - [bool ; { struct Inner { non_removed_inner_field : usize, } 0 }], -} +{ my_array : [bool ; { struct Inner { non_removed_inner_field : usize } 0 }] } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:12:1: 12:7 (#0), }, Ident { ident: "Foo", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:12:8: 12:11 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "my_array", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:14:5: 14:13 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:14:13: 14:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "bool", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:14:16: 14:20 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:14:20: 14:21 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:15:9: 15:15 (#0), }, Ident { ident: "Inner", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:15:16: 15:21 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "non_removed_inner_field", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:17:13: 17:36 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:17:36: 17:37 (#0), }, Ident { ident: "usize", - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:17:38: 17:43 (#0), }, ], - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:15:22: 18:10 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:19:9: 19:10 (#0), }, ], - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:14:22: 20:6 (#0), }, ], - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:14:15: 20:7 (#0), }, ], - span: $DIR/nested-derive-cfg.rs:12:1: 21:2 (#0), + span: $DIR/nested-derive-cfg.rs:12:12: 21:2 (#0), }, ] diff --git a/src/test/ui/proc-macro/nested-macro-rules.rs b/src/test/ui/proc-macro/nested-macro-rules.rs index 2fef0e5fad..25ffcfad7c 100644 --- a/src/test/ui/proc-macro/nested-macro-rules.rs +++ b/src/test/ui/proc-macro/nested-macro-rules.rs @@ -1,7 +1,7 @@ // run-pass // aux-build:nested-macro-rules.rs // aux-build:test-macros.rs -// compile-flags: -Z span-debug +// compile-flags: -Z span-debug -Z macro-backtrace // edition:2018 #![no_std] // Don't load unnecessary hygiene information from std @@ -10,14 +10,14 @@ extern crate std; extern crate nested_macro_rules; extern crate test_macros; -use test_macros::print_bang; +use test_macros::{print_bang, print_attr}; use nested_macro_rules::FirstStruct; struct SecondStruct; fn main() { - nested_macro_rules::inner_macro!(print_bang); + nested_macro_rules::inner_macro!(print_bang, print_attr); - nested_macro_rules::outer_macro!(SecondStruct); - inner_macro!(print_bang); + nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); + inner_macro!(print_bang, print_attr); } diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout index dcafe3b4bd..8292617fc1 100644 --- a/src/test/ui/proc-macro/nested-macro-rules.stdout +++ b/src/test/ui/proc-macro/nested-macro-rules.stdout @@ -5,10 +5,32 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "FirstStruct", - span: $DIR/auxiliary/nested-macro-rules.rs:15:14: 15:25 (#7), + span: $DIR/auxiliary/nested-macro-rules.rs:16:14: 16:25 (#7), }, ], - span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#6), + span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#6), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#6), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "FirstAttrStruct", + span: $DIR/auxiliary/nested-macro-rules.rs:16:27: 16:42 (#7), + }, + ], + span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#6), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#6), }, ] PRINT-BANG INPUT (DISPLAY): SecondStruct @@ -18,9 +40,31 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "SecondStruct", - span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#13), + span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16), }, ], - span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#12), + span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#15), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "SecondAttrStruct", + span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16), + }, + ], + span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#15), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#15), }, ] diff --git a/src/test/ui/proc-macro/nodelim-groups.stdout b/src/test/ui/proc-macro/nodelim-groups.stdout index 6b410f0bfb..4ffe3f35e8 100644 --- a/src/test/ui/proc-macro/nodelim-groups.stdout +++ b/src/test/ui/proc-macro/nodelim-groups.stdout @@ -71,6 +71,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1) +PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): "hi" "hello" . len() + "world" . len() (1 + 1) PRINT-BANG INPUT (DEBUG): TokenStream [ Literal { kind: Str, diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.rs b/src/test/ui/proc-macro/nonterminal-recollect-attr.rs index 5d4649b78c..79c4ad4cd2 100644 --- a/src/test/ui/proc-macro/nonterminal-recollect-attr.rs +++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.rs @@ -1,6 +1,10 @@ // check-pass +// compile-flags: -Z span-debug // aux-build:nonterminal-recollect-attr.rs +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + extern crate nonterminal_recollect_attr; use nonterminal_recollect_attr::*; diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout new file mode 100644 index 0000000000..7331a25abd --- /dev/null +++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout @@ -0,0 +1,72 @@ +First recollected: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "pub", + span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), + }, + ], + span: $DIR/nonterminal-recollect-attr.rs:14:9: 14:11 (#4), + }, + Ident { + ident: "struct", + span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4), + }, + Ident { + ident: "u8", + span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4), + }, + ], + span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4), + }, +] +Second recollected: TokenStream [ + Ident { + ident: "pub", + span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4), + }, + Ident { + ident: "u8", + span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4), + }, + ], + span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4), + }, +] diff --git a/src/test/ui/proc-macro/simple-tuple.rs b/src/test/ui/proc-macro/simple-tuple.rs new file mode 100644 index 0000000000..c94c5877e2 --- /dev/null +++ b/src/test/ui/proc-macro/simple-tuple.rs @@ -0,0 +1,19 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs +// edition:2018 + +#![feature(proc_macro_hygiene)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +fn main() { + #[print_target_and_args(my_arg)] ( + #![cfg_attr(not(FALSE), allow(unused))] + 1, 2, 3 + ); +} diff --git a/src/test/ui/proc-macro/simple-tuple.stdout b/src/test/ui/proc-macro/simple-tuple.stdout new file mode 100644 index 0000000000..1cc8579a46 --- /dev/null +++ b/src/test/ui/proc-macro/simple-tuple.stdout @@ -0,0 +1,79 @@ +PRINT-ATTR_ARGS INPUT (DISPLAY): my_arg +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "my_arg", + span: $DIR/simple-tuple.rs:15:29: 15:35 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): (# ! [allow(unused)] 1, 2, 3) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/simple-tuple.rs:16:9: 16:10 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/simple-tuple.rs:16:10: 16:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/simple-tuple.rs:16:33: 16:38 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused", + span: $DIR/simple-tuple.rs:16:39: 16:45 (#0), + }, + ], + span: $DIR/simple-tuple.rs:16:38: 16:46 (#0), + }, + ], + span: $DIR/simple-tuple.rs:16:9: 16:10 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/simple-tuple.rs:17:9: 17:10 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/simple-tuple.rs:17:10: 17:11 (#0), + }, + Literal { + kind: Integer, + symbol: "2", + suffix: None, + span: $DIR/simple-tuple.rs:17:12: 17:13 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/simple-tuple.rs:17:13: 17:14 (#0), + }, + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/simple-tuple.rs:17:15: 17:16 (#0), + }, + ], + span: $DIR/simple-tuple.rs:15:38: 18:6 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/simple-tuple.rs:18:6: 18:7 (#0), + }, +] diff --git a/src/test/ui/proc-macro/trait-fn-args-2015.rs b/src/test/ui/proc-macro/trait-fn-args-2015.rs index 3a448d4b22..6b8df78a06 100644 --- a/src/test/ui/proc-macro/trait-fn-args-2015.rs +++ b/src/test/ui/proc-macro/trait-fn-args-2015.rs @@ -3,6 +3,8 @@ // check-pass // aux-build:test-macros.rs +#![allow(anonymous_parameters)] + #[macro_use] extern crate test_macros; diff --git a/src/test/ui/proc-macro/weird-braces.stdout b/src/test/ui/proc-macro/weird-braces.stdout index 25f0eaf0dd..990829456e 100644 --- a/src/test/ui/proc-macro/weird-braces.stdout +++ b/src/test/ui/proc-macro/weird-braces.stdout @@ -15,40 +15,40 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:17:1: 17:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:17:3: 17:24 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "second_outer", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:17:25: 17:37 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:17:24: 17:38 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:17:2: 17:39 (#0), }, Ident { ident: "impl", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), }, Ident { ident: "Bar", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), }, Group { delimiter: Brace, @@ -57,54 +57,54 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "1", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), }, Ident { ident: "for", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), }, Ident { ident: "Foo", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "true", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), }, Group { delimiter: Brace, @@ -112,72 +112,72 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:5: 19:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:6: 19:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:8: 19:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "first_inner", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:29: 19:42 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:7: 19:43 (#0), }, Punct { ch: '#', spacing: Joint, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "second_inner", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): second_outer PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "second_outer", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:17:25: 17:37 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > @@ -188,16 +188,16 @@ PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "impl", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), }, Ident { ident: "Bar", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), }, Group { delimiter: Brace, @@ -206,54 +206,54 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "1", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), }, Ident { ident: "for", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), }, Ident { ident: "Foo", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "true", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), }, Group { delimiter: Brace, @@ -261,72 +261,72 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:5: 19:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:6: 19:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:8: 19:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "first_inner", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:29: 19:42 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:7: 19:43 (#0), }, Punct { ch: '#', spacing: Joint, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "second_inner", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): first_inner PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "first_inner", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > @@ -334,16 +334,16 @@ PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "impl", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), }, Ident { ident: "Bar", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), }, Group { delimiter: Brace, @@ -352,54 +352,54 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "1", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), }, Ident { ident: "for", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), }, Ident { ident: "Foo", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "true", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), }, Group { delimiter: Brace, @@ -407,58 +407,58 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "second_inner", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): second_inner PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "second_inner", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > { } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "impl", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), }, Ident { ident: "Bar", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), }, Group { delimiter: Brace, @@ -467,58 +467,58 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "1", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), }, Ident { ident: "for", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), }, Ident { ident: "Foo", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "true", - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), }, ], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/weird-braces.rs:18:1: 21:2 (#0), + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), }, ] diff --git a/src/test/ui/recursion/issue-83150.rs b/src/test/ui/recursion/issue-83150.rs new file mode 100644 index 0000000000..650ad22d20 --- /dev/null +++ b/src/test/ui/recursion/issue-83150.rs @@ -0,0 +1,11 @@ +// build-fail + //~^ overflow evaluating + +fn main() { + let mut iter = 0u8..1; + func(&mut iter) +} + +fn func<T: Iterator<Item = u8>>(iter: &mut T) { + func(&mut iter.map(|x| x + 1)) +} diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr new file mode 100644 index 0000000000..943d513309 --- /dev/null +++ b/src/test/ui/recursion/issue-83150.stderr @@ -0,0 +1,8 @@ +error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>: Iterator` + | + = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_83150`) + = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/recursion/recursive-requirements.stderr b/src/test/ui/recursion/recursive-requirements.stderr index 6c0be0f7f8..0518cc507b 100644 --- a/src/test/ui/recursion/recursive-requirements.stderr +++ b/src/test/ui/recursion/recursive-requirements.stderr @@ -8,7 +8,11 @@ LL | let _: AssertSync<Foo> = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely | = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/recursive-requirements.rs:5:12 + | +LL | pub struct Foo { + | ^^^ error[E0277]: `*const Foo` cannot be shared between threads safely --> $DIR/recursive-requirements.rs:16:12 @@ -20,9 +24,17 @@ LL | let _: AssertSync<Foo> = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely | = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo` - = note: required because it appears within the type `Bar` +note: required because it appears within the type `Bar` + --> $DIR/recursive-requirements.rs:10:12 + | +LL | pub struct Bar { + | ^^^ = note: required because it appears within the type `PhantomData<Bar>` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/recursive-requirements.rs:5:12 + | +LL | pub struct Foo { + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs index 6de08f66d7..8b491ee4e3 100644 --- a/src/test/ui/regions/regions-enum-not-wf.rs +++ b/src/test/ui/regions/regions-enum-not-wf.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Various examples of structs whose fields are not well-formed. #![allow(dead_code)] diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr index 36686eaf92..553a3e71c1 100644 --- a/src/test/ui/regions/regions-enum-not-wf.stderr +++ b/src/test/ui/regions/regions-enum-not-wf.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:19:18 + --> $DIR/regions-enum-not-wf.rs:17:18 | LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -7,7 +7,7 @@ LL | Ref1Variant1(RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:24:25 + --> $DIR/regions-enum-not-wf.rs:22:25 | LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -16,7 +16,7 @@ LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:37:23 + --> $DIR/regions-enum-not-wf.rs:35:23 | LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr index ad0e7bd5af..5f6ff280e6 100644 --- a/src/test/ui/regions/regions-name-undeclared.stderr +++ b/src/test/ui/regions/regions-name-undeclared.stderr @@ -1,3 +1,23 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-name-undeclared.rs:28:13 + | +LL | enum E { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | E1(&'a isize) + | ^^ undeclared lifetime + | + = 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/regions-name-undeclared.rs:31:13 + | +LL | struct S { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | f: &'a isize + | ^^ undeclared lifetime + | + = 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 `'b` --> $DIR/regions-name-undeclared.rs:16:24 | @@ -56,26 +76,6 @@ LL | type X = Option<&'a isize>; | = 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/regions-name-undeclared.rs:28:13 - | -LL | enum E { - | - help: consider introducing lifetime `'a` here: `<'a>` -LL | E1(&'a isize) - | ^^ undeclared lifetime - | - = 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/regions-name-undeclared.rs:31:13 - | -LL | struct S { - | - help: consider introducing lifetime `'a` here: `<'a>` -LL | f: &'a isize - | ^^ undeclared lifetime - | - = 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/regions-name-undeclared.rs:33:14 | diff --git a/src/test/ui/reify-intrinsic.rs b/src/test/ui/reify-intrinsic.rs index 09baa059e5..9eb2f72401 100644 --- a/src/test/ui/reify-intrinsic.rs +++ b/src/test/ui/reify-intrinsic.rs @@ -1,6 +1,6 @@ // check-fail -#![feature(intrinsics)] +#![feature(core_intrinsics, intrinsics)] fn a() { let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; @@ -12,4 +12,12 @@ fn b() { //~^ ERROR casting } +fn c() { + let _ = [ + std::intrinsics::likely, + std::intrinsics::unlikely, + //~^ ERROR cannot coerce + ]; +} + fn main() {} diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr index 675447f972..69c11b5c56 100644 --- a/src/test/ui/reify-intrinsic.stderr +++ b/src/test/ui/reify-intrinsic.stderr @@ -19,7 +19,16 @@ error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0308]: cannot coerce intrinsics to function pointers + --> $DIR/reify-intrinsic.rs:18:9 + | +LL | std::intrinsics::unlikely, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers + | + = note: expected type `extern "rust-intrinsic" fn(_) -> _ {likely}` + found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}` + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0606. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/resolve/auxiliary/issue-80079.rs b/src/test/ui/resolve/auxiliary/issue-80079.rs new file mode 100644 index 0000000000..190ca75aba --- /dev/null +++ b/src/test/ui/resolve/auxiliary/issue-80079.rs @@ -0,0 +1,18 @@ +#![crate_type = "lib"] + +pub mod public { + use private_import; + + // should not be suggested since it is private + struct Foo; + + mod private_module { + // should not be suggested since it is private + pub struct Foo; + } +} + +mod private_import { + // should not be suggested since it is private + pub struct Foo; +} diff --git a/src/test/ui/bad/bad-env-capture.rs b/src/test/ui/resolve/bad-env-capture.rs similarity index 100% rename from src/test/ui/bad/bad-env-capture.rs rename to src/test/ui/resolve/bad-env-capture.rs diff --git a/src/test/ui/bad/bad-env-capture.stderr b/src/test/ui/resolve/bad-env-capture.stderr similarity index 100% rename from src/test/ui/bad/bad-env-capture.stderr rename to src/test/ui/resolve/bad-env-capture.stderr diff --git a/src/test/ui/bad/bad-env-capture2.rs b/src/test/ui/resolve/bad-env-capture2.rs similarity index 100% rename from src/test/ui/bad/bad-env-capture2.rs rename to src/test/ui/resolve/bad-env-capture2.rs diff --git a/src/test/ui/bad/bad-env-capture2.stderr b/src/test/ui/resolve/bad-env-capture2.stderr similarity index 100% rename from src/test/ui/bad/bad-env-capture2.stderr rename to src/test/ui/resolve/bad-env-capture2.stderr diff --git a/src/test/ui/bad/bad-env-capture3.rs b/src/test/ui/resolve/bad-env-capture3.rs similarity index 100% rename from src/test/ui/bad/bad-env-capture3.rs rename to src/test/ui/resolve/bad-env-capture3.rs diff --git a/src/test/ui/bad/bad-env-capture3.stderr b/src/test/ui/resolve/bad-env-capture3.stderr similarity index 100% rename from src/test/ui/bad/bad-env-capture3.stderr rename to src/test/ui/resolve/bad-env-capture3.stderr diff --git a/src/test/ui/bad/bad-expr-path.rs b/src/test/ui/resolve/bad-expr-path.rs similarity index 100% rename from src/test/ui/bad/bad-expr-path.rs rename to src/test/ui/resolve/bad-expr-path.rs diff --git a/src/test/ui/bad/bad-expr-path.stderr b/src/test/ui/resolve/bad-expr-path.stderr similarity index 100% rename from src/test/ui/bad/bad-expr-path.stderr rename to src/test/ui/resolve/bad-expr-path.stderr diff --git a/src/test/ui/bad/bad-expr-path2.rs b/src/test/ui/resolve/bad-expr-path2.rs similarity index 100% rename from src/test/ui/bad/bad-expr-path2.rs rename to src/test/ui/resolve/bad-expr-path2.rs diff --git a/src/test/ui/bad/bad-expr-path2.stderr b/src/test/ui/resolve/bad-expr-path2.stderr similarity index 100% rename from src/test/ui/bad/bad-expr-path2.stderr rename to src/test/ui/resolve/bad-expr-path2.stderr diff --git a/src/test/ui/bad/bad-module.rs b/src/test/ui/resolve/bad-module.rs similarity index 100% rename from src/test/ui/bad/bad-module.rs rename to src/test/ui/resolve/bad-module.rs diff --git a/src/test/ui/bad/bad-module.stderr b/src/test/ui/resolve/bad-module.stderr similarity index 100% rename from src/test/ui/bad/bad-module.stderr rename to src/test/ui/resolve/bad-module.stderr diff --git a/src/test/ui/bad/bad-type-env-capture.rs b/src/test/ui/resolve/bad-type-env-capture.rs similarity index 100% rename from src/test/ui/bad/bad-type-env-capture.rs rename to src/test/ui/resolve/bad-type-env-capture.rs diff --git a/src/test/ui/bad/bad-type-env-capture.stderr b/src/test/ui/resolve/bad-type-env-capture.stderr similarity index 100% rename from src/test/ui/bad/bad-type-env-capture.stderr rename to src/test/ui/resolve/bad-type-env-capture.stderr diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr index 4d0b0af58a..6fc61cae84 100644 --- a/src/test/ui/resolve/issue-3907.stderr +++ b/src/test/ui/resolve/issue-3907.stderr @@ -5,10 +5,9 @@ LL | impl Foo for S { | ^^^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/issue-3907.rs:5:1 | -LL | type Foo = dyn issue_3907::Foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Foo = dyn issue_3907::Foo; + | help: consider importing this trait instead | LL | use issue_3907::Foo; diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr index b2084a7a42..e94877fded 100644 --- a/src/test/ui/resolve/issue-5035-2.stderr +++ b/src/test/ui/resolve/issue-5035-2.stderr @@ -8,8 +8,8 @@ LL | fn foo(_x: K) {} = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn foo(&_x: K) {} - | ^ +LL | fn foo(_x: &K) {} + | ^ error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr index 41dff2fe54..a8aa50b7c3 100644 --- a/src/test/ui/resolve/issue-5035.stderr +++ b/src/test/ui/resolve/issue-5035.stderr @@ -11,16 +11,16 @@ LL | trait I {} | ------- similarly named trait `I` defined here LL | type K = dyn I; LL | impl K for isize {} - | ^ - | | - | type aliases cannot be used as traits - | help: a trait with a similar name exists: `I` + | ^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/issue-5035.rs:2:1 | -LL | type K = dyn I; - | ^^^^^^^^^^^^^^^ +LL | trait K = dyn I; + | +help: a trait with a similar name exists + | +LL | impl I for isize {} + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-80079.rs b/src/test/ui/resolve/issue-80079.rs new file mode 100644 index 0000000000..4795ed062c --- /dev/null +++ b/src/test/ui/resolve/issue-80079.rs @@ -0,0 +1,12 @@ +// aux-build:issue-80079.rs + +// using a module from another crate should not cause errors to suggest private +// items in that module + +extern crate issue_80079; + +use issue_80079::public; + +fn main() { + let _ = Foo; //~ ERROR cannot find value `Foo` in this scope +} diff --git a/src/test/ui/resolve/issue-80079.stderr b/src/test/ui/resolve/issue-80079.stderr new file mode 100644 index 0000000000..93e8c0341a --- /dev/null +++ b/src/test/ui/resolve/issue-80079.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `Foo` in this scope + --> $DIR/issue-80079.rs:11:13 + | +LL | let _ = 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/resolve/issue-81508.rs b/src/test/ui/resolve/issue-81508.rs new file mode 100644 index 0000000000..23605cd2fd --- /dev/null +++ b/src/test/ui/resolve/issue-81508.rs @@ -0,0 +1,22 @@ +// Confusing diagnostic when using variable as a type: +// +// Previous warnings indicate Foo is not used, when in fact it is +// used improperly as a variable or constant. New warning points +// out user may be trying to use variable as a type. Test demonstrates +// cases for both local variable and const. + +fn main() { + let Baz: &str = ""; + + println!("{}", Baz::Bar); //~ ERROR: failed to resolve: use of undeclared type `Baz` +} + +#[allow(non_upper_case_globals)] +pub const Foo: &str = ""; + +mod submod { + use super::Foo; + fn function() { + println!("{}", Foo::Bar); //~ ERROR: failed to resolve: use of undeclared type `Foo` + } +} diff --git a/src/test/ui/resolve/issue-81508.stderr b/src/test/ui/resolve/issue-81508.stderr new file mode 100644 index 0000000000..15555631b9 --- /dev/null +++ b/src/test/ui/resolve/issue-81508.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared type `Baz` + --> $DIR/issue-81508.rs:11:20 + | +LL | let Baz: &str = ""; + | --- help: `Baz` is defined here, but is not a type +LL | +LL | println!("{}", Baz::Bar); + | ^^^ use of undeclared type `Baz` + +error[E0433]: failed to resolve: use of undeclared type `Foo` + --> $DIR/issue-81508.rs:20:24 + | +LL | use super::Foo; + | ---------- help: `Foo` is defined here, but is not a type +LL | fn function() { +LL | println!("{}", Foo::Bar); + | ^^^ use of undeclared type `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/resolve/issue-82865.rs b/src/test/ui/resolve/issue-82865.rs new file mode 100644 index 0000000000..07d88c413b --- /dev/null +++ b/src/test/ui/resolve/issue-82865.rs @@ -0,0 +1,13 @@ +// Regression test for #82865. + +#![feature(decl_macro)] + +use x::y::z; //~ ERROR: failed to resolve: maybe a missing crate `x`? + +macro mac () { + Box::z //~ ERROR: no function or associated item +} + +fn main() { + mac!(); +} diff --git a/src/test/ui/resolve/issue-82865.stderr b/src/test/ui/resolve/issue-82865.stderr new file mode 100644 index 0000000000..027d7a0e0e --- /dev/null +++ b/src/test/ui/resolve/issue-82865.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: maybe a missing crate `x`? + --> $DIR/issue-82865.rs:5:5 + | +LL | use x::y::z; + | ^ maybe a missing crate `x`? + +error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope + --> $DIR/issue-82865.rs:8:10 + | +LL | Box::z + | ^ function or associated item not found in `Box<_, _>` +... +LL | mac!(); + | ------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/no-implicit-prelude.rs b/src/test/ui/resolve/no-implicit-prelude.rs similarity index 100% rename from src/test/ui/no-implicit-prelude.rs rename to src/test/ui/resolve/no-implicit-prelude.rs diff --git a/src/test/ui/no-implicit-prelude.stderr b/src/test/ui/resolve/no-implicit-prelude.stderr similarity index 100% rename from src/test/ui/no-implicit-prelude.stderr rename to src/test/ui/resolve/no-implicit-prelude.stderr diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr index 2974d08eb2..8addc0303f 100644 --- a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr +++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr @@ -11,10 +11,9 @@ LL | fn g<F:Typedef(isize) -> isize>(x: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits | help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias - --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:4:1 | -LL | type Typedef = isize; - | ^^^^^^^^^^^^^^^^^^^^^ +LL | trait Typedef = isize; + | error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs index 70ec0e3033..9464ffe872 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -1,3 +1,4 @@ +// needs-asm-support #![feature(asm, naked_functions)] #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr index 1b49148d62..5f17d6b2b5 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -1,11 +1,11 @@ error[E0736]: cannot use `#[track_caller]` with `#[naked]` - --> $DIR/error-with-naked.rs:3:1 + --> $DIR/error-with-naked.rs:4:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0736]: cannot use `#[track_caller]` with `#[naked]` - --> $DIR/error-with-naked.rs:12:5 + --> $DIR/error-with-naked.rs:13:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs index 84b7c6701e..f0850d5c1f 100644 --- a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs +++ b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs @@ -3,7 +3,6 @@ // revisions: default mir-opt //[mir-opt] compile-flags: -Zmir-opt-level=4 -#![feature(option_expect_none, option_unwrap_none)] #![allow(unconditional_panic)] //! Test that panic locations for `#[track_caller]` functions in std have the correct @@ -32,10 +31,6 @@ fn main() { assert_panicked(|| nope.unwrap()); assert_panicked(|| nope.expect("")); - let yep: Option<()> = Some(()); - assert_panicked(|| yep.unwrap_none()); - assert_panicked(|| yep.expect_none("")); - let oops: Result<(), ()> = Err(()); assert_panicked(|| oops.unwrap()); assert_panicked(|| oops.expect("")); diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs index 6de08f66d7..8b491ee4e3 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Various examples of structs whose fields are not well-formed. #![allow(dead_code)] diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr index 36686eaf92..553a3e71c1 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:19:18 + --> $DIR/regions-enum-not-wf.rs:17:18 | LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -7,7 +7,7 @@ LL | Ref1Variant1(RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:24:25 + --> $DIR/regions-enum-not-wf.rs:22:25 | LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -16,7 +16,7 @@ LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:37:23 + --> $DIR/regions-enum-not-wf.rs:35:23 | LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs index 310545b92d..c07ba54af4 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs @@ -1,5 +1,3 @@ -#![feature(non_ascii_idents)] - extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг` fn main() {} diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr index 11108f2fb8..a8f3abe599 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr @@ -1,5 +1,5 @@ error: cannot load a crate with a non-ascii name `ьаг` - --> $DIR/crate_name_nonascii_forbidden-1.rs:3:1 + --> $DIR/crate_name_nonascii_forbidden-1.rs:1:1 | LL | extern crate ьаг; | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs index 0249848b35..f8e033937c 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs @@ -1,6 +1,5 @@ // compile-flags:--extern му_сгате // edition:2018 -#![feature(non_ascii_idents)] use му_сгате::baz; //~ ERROR cannot load a crate with a non-ascii name `му_сгате` diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr index 8d3548ed33..05fc4fb22a 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr @@ -1,5 +1,5 @@ error: cannot load a crate with a non-ascii name `му_сгате` - --> $DIR/crate_name_nonascii_forbidden-2.rs:5:5 + --> $DIR/crate_name_nonascii_forbidden-2.rs:4:5 | LL | use му_сгате::baz; | ^^^^^^^^ diff --git a/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.rs b/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.rs new file mode 100644 index 0000000000..ad68254043 --- /dev/null +++ b/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.rs @@ -0,0 +1,9 @@ +#![feature(extern_types)] + +extern "C" { + type 一; //~ items in `extern` blocks cannot use non-ascii identifiers + fn 二(); //~ items in `extern` blocks cannot use non-ascii identifiers + static 三: usize; //~ items in `extern` blocks cannot use non-ascii identifiers +} + +fn main() {} diff --git a/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr b/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr new file mode 100644 index 0000000000..ab8832e916 --- /dev/null +++ b/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr @@ -0,0 +1,34 @@ +error: items in `extern` blocks cannot use non-ascii identifiers + --> $DIR/extern_block_nonascii_forbidden.rs:4:10 + | +LL | extern "C" { + | ---------- in this `extern` block +LL | type 一; + | ^^ + | + = note: This limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information + +error: items in `extern` blocks cannot use non-ascii identifiers + --> $DIR/extern_block_nonascii_forbidden.rs:5:8 + | +LL | extern "C" { + | ---------- in this `extern` block +LL | type 一; +LL | fn 二(); + | ^^ + | + = note: This limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information + +error: items in `extern` blocks cannot use non-ascii identifiers + --> $DIR/extern_block_nonascii_forbidden.rs:6:12 + | +LL | extern "C" { + | ---------- in this `extern` block +... +LL | static 三: usize; + | ^^ + | + = note: This limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/rfc-2457/idents-normalized.rs b/src/test/ui/rfc-2457/idents-normalized.rs index 109cec7548..1023fee37d 100644 --- a/src/test/ui/rfc-2457/idents-normalized.rs +++ b/src/test/ui/rfc-2457/idents-normalized.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(non_ascii_idents)] struct Résumé; // ['LATIN SMALL LETTER E WITH ACUTE'] diff --git a/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs index efd2932f15..e949e2319c 100644 --- a/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs +++ b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs @@ -1,5 +1,3 @@ -#![feature(non_ascii_idents)] - mod řųśť; //~ trying to load file for //~^ file not found for diff --git a/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr index be729836f4..e857a1e60e 100644 --- a/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr +++ b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr @@ -1,13 +1,13 @@ error[E0583]: file not found for module `řųśť` - --> $DIR/mod_file_nonascii_forbidden.rs:3:1 + --> $DIR/mod_file_nonascii_forbidden.rs:1:1 | LL | mod řųśť; | ^^^^^^^^^ | = help: to create the module `řųśť`, create file "$DIR/řųśť.rs" -error[E0754]: trying to load file for module `řųśť` with non ascii identifer name - --> $DIR/mod_file_nonascii_forbidden.rs:3:5 +error[E0754]: trying to load file for module `řųśť` with non-ascii identifier name + --> $DIR/mod_file_nonascii_forbidden.rs:1:5 | LL | mod řųśť; | ^^^^ diff --git a/src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs b/src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs index e9f3fba2fb..94327846d6 100644 --- a/src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs +++ b/src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(non_ascii_idents)] #[path="auxiliary/mod_file_nonascii_with_path_allowed-aux.rs"] mod řųśť; diff --git a/src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs b/src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs index dd27da432b..e1d836b7c3 100644 --- a/src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs +++ b/src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(non_ascii_idents)] mod řųśť { const IS_GREAT: bool = true; diff --git a/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs index a408c97571..0325d6436a 100644 --- a/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs +++ b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs @@ -1,5 +1,3 @@ -#![feature(non_ascii_idents)] - #[no_mangle] pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier diff --git a/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr index 4ca83e4103..b4b2b0c7ee 100644 --- a/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr +++ b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr @@ -1,5 +1,5 @@ error[E0754]: `#[no_mangle]` requires ASCII identifier - --> $DIR/no_mangle_nonascii_forbidden.rs:4:1 + --> $DIR/no_mangle_nonascii_forbidden.rs:2:1 | LL | pub fn řųśť() {} | ^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs index fcfa610ec8..54f2f451bb 100644 --- a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -1,6 +1,7 @@ // aux-build:ident-mac.rs #![feature(c_variadic)] +#![allow(anonymous_parameters)] extern crate ident_mac; use ident_mac::id; diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr index 38c5050f34..e74d05d49b 100644 --- a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr @@ -1,173 +1,173 @@ error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:10:23 + --> $DIR/proc-macro-cannot-be-used.rs:11:23 | LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:10:40 + --> $DIR/proc-macro-cannot-be-used.rs:11:40 | LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:14:40 + --> $DIR/proc-macro-cannot-be-used.rs:15:40 | LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:17:30 + --> $DIR/proc-macro-cannot-be-used.rs:18:30 | LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:17:40 + --> $DIR/proc-macro-cannot-be-used.rs:18:40 | LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:21:11 + --> $DIR/proc-macro-cannot-be-used.rs:22:11 | LL | fn free(#[id] arg1: u8) { | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:23:18 + --> $DIR/proc-macro-cannot-be-used.rs:24:18 | LL | let lam = |#[id] W(x), #[id] y: usize| (); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:23:30 + --> $DIR/proc-macro-cannot-be-used.rs:24:30 | LL | let lam = |#[id] W(x), #[id] y: usize| (); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:29:20 + --> $DIR/proc-macro-cannot-be-used.rs:30:20 | LL | fn inherent1(#[id] self, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:29:32 + --> $DIR/proc-macro-cannot-be-used.rs:30:32 | LL | fn inherent1(#[id] self, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:32:20 + --> $DIR/proc-macro-cannot-be-used.rs:33:20 | LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:32:33 + --> $DIR/proc-macro-cannot-be-used.rs:33:33 | LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:35:24 + --> $DIR/proc-macro-cannot-be-used.rs:36:24 | LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:35:44 + --> $DIR/proc-macro-cannot-be-used.rs:36:44 | LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:38:24 + --> $DIR/proc-macro-cannot-be-used.rs:39:24 | LL | fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:38:47 + --> $DIR/proc-macro-cannot-be-used.rs:39:47 | LL | fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:41:40 + --> $DIR/proc-macro-cannot-be-used.rs:42:40 | LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:41:56 + --> $DIR/proc-macro-cannot-be-used.rs:42:56 | LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:47:17 + --> $DIR/proc-macro-cannot-be-used.rs:48:17 | LL | fn trait1(#[id] self, #[id] arg1: u8); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:47:29 + --> $DIR/proc-macro-cannot-be-used.rs:48:29 | LL | fn trait1(#[id] self, #[id] arg1: u8); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:50:17 + --> $DIR/proc-macro-cannot-be-used.rs:51:17 | LL | fn trait2(#[id] &self, #[id] arg1: u8); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:50:30 + --> $DIR/proc-macro-cannot-be-used.rs:51:30 | LL | fn trait2(#[id] &self, #[id] arg1: u8); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:53:21 + --> $DIR/proc-macro-cannot-be-used.rs:54:21 | LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:53:41 + --> $DIR/proc-macro-cannot-be-used.rs:54:41 | LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:56:21 + --> $DIR/proc-macro-cannot-be-used.rs:57:21 | LL | fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:56:44 + --> $DIR/proc-macro-cannot-be-used.rs:57:44 | LL | fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:56:60 + --> $DIR/proc-macro-cannot-be-used.rs:57:60 | LL | fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:60:40 + --> $DIR/proc-macro-cannot-be-used.rs:61:40 | LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); | ^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `id` - --> $DIR/proc-macro-cannot-be-used.rs:60:56 + --> $DIR/proc-macro-cannot-be-used.rs:61:56 | LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); | ^^ not a non-macro attribute diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 194929fa28..5a66af1d29 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -5,7 +5,6 @@ #![allow(incomplete_features)] #![feature(const_trait_impl)] -#![feature(const_fn)] struct NonConstAdd(i32); diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs index 8e6ef12810..fa5570d545 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -1,6 +1,5 @@ #![allow(incomplete_features)] #![feature(const_trait_impl)] -#![feature(const_fn)] pub trait Plus { fn plus(self, rhs: Self) -> Self; diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 0c320d54c7..d3f350e1b6 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -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:26:5 + --> $DIR/call-const-trait-method-fail.rs:25:5 | LL | a.plus(b) | ^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs index 6a2112ea55..ec6f45f956 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs @@ -2,7 +2,6 @@ #![allow(incomplete_features)] #![feature(const_trait_impl)] -#![feature(const_fn)] struct Int(i32); diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs index 6a511f4ed3..c37990b1af 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -2,8 +2,8 @@ // check-pass -#![feature(const_fn)] #![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] #![allow(incomplete_features)] struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index b39d27779f..d553b2ab8e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -1,8 +1,8 @@ // check-pass -#![feature(const_fn)] #![feature(const_trait_impl)] #![feature(const_trait_bound_opt_out)] +#![feature(const_fn_trait_bound)] #![allow(incomplete_features)] struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs index 6d4bfe722d..dc4d5561d4 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -1,4 +1,4 @@ -#![feature(const_fn)] +#![feature(const_fn_trait_bound)] #![feature(const_trait_impl)] #![feature(const_trait_bound_opt_out)] #![allow(incomplete_features)] diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs index f0e3214222..1fc2c4fe44 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(const_fn)] +#![feature(const_fn_trait_bound)] #![feature(const_trait_impl)] #![feature(const_trait_bound_opt_out)] #![allow(incomplete_features)] diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs index 2c8f6354dc..9aefe6380c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -1,7 +1,6 @@ // FIXME(jschievink): this is not rejected correctly (only when the non-const impl is actually used) // ignore-test -#![feature(const_fn)] #![feature(const_trait_impl)] #![allow(incomplete_features)] diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs index e968e6ec7b..74b0d5fbe4 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -2,8 +2,8 @@ // check-pass -#![feature(const_fn)] #![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] #![allow(incomplete_features)] struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr index 2b4fa66ecf..99560ed068 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32`: +error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32` --> $DIR/const-and-non-const-impl.rs:6:1 | LL | impl const std::ops::Add for i32 { @@ -7,7 +7,7 @@ LL | impl const std::ops::Add for i32 { = note: conflicting implementation in crate `core`: - impl Add for i32; -error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int`: +error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int` --> $DIR/const-and-non-const-impl.rs:24:1 | LL | impl std::ops::Add for Int { diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs index 3506237d1f..4452ad7ea2 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs @@ -4,7 +4,7 @@ #![cfg_attr(gated, feature(const_trait_bound_opt_out))] #![allow(incomplete_features)] #![feature(rustc_attrs)] -#![feature(const_fn)] +#![feature(const_fn_trait_bound)] trait T { const CONST: i32; diff --git a/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs index 7829ffe2a3..d368082031 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs @@ -2,7 +2,7 @@ #![allow(incomplete_features)] #![feature(const_trait_impl)] -#![feature(const_fn)] +#![feature(const_fn_trait_bound)] use std::marker::PhantomData; diff --git a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs index 655d4d7400..ad14dd62bc 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs @@ -1,6 +1,6 @@ // Regression test for #69615. -#![feature(const_trait_impl, const_fn)] +#![feature(const_trait_impl)] #![allow(incomplete_features)] pub trait MyTrait { diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr index 54d7cfd5d7..5b2ebccef1 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr @@ -1,4 +1,4 @@ -error[E0723]: trait methods cannot be stable const fn +error: trait methods cannot be stable const fn --> $DIR/stability.rs:14:5 | LL | / fn sub(self, rhs: Self) -> Self { @@ -17,4 +17,3 @@ LL | Int(1i32) + Int(2i32) error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr index b5dd0c9d2a..a3d9467943 100644 --- a/src/test/ui/rfc1623.nll.stderr +++ b/src/test/ui/rfc1623.nll.stderr @@ -11,7 +11,11 @@ LL | | }; | = help: within `&SomeStruct`, the trait `Sync` is not implemented for `dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>` = note: required because it appears within the type `&dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>` - = note: required because it appears within the type `SomeStruct` +note: required because it appears within the type `SomeStruct` + --> $DIR/rfc1623.rs:11:8 + | +LL | struct SomeStruct<'x, 'y, 'z: 'x> { + | ^^^^^^^^^^ = note: required because it appears within the type `&SomeStruct` = note: shared static variables must have a type that implements `Sync` diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index 4b1898345a..2cf5a073fe 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `foobar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:22:11 | +LL | fn foobar(&self) { } + | ------ the method is available for `u32` here +... LL | x.foobar(); | ^^^^^^ method not found in `u32` | @@ -11,6 +14,9 @@ LL | x.foobar(); error[E0599]: no method named `bar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:28:7 | +LL | fn bar(&self) { } + | --- the method is available for `u32` here +... LL | x.bar(); | ^^^ method not found in `u32` | diff --git a/src/test/ui/rustdoc/check-doc-alias-attr.stderr b/src/test/ui/rustdoc/check-doc-alias-attr.stderr index f99d69dc10..250568be33 100644 --- a/src/test/ui/rustdoc/check-doc-alias-attr.stderr +++ b/src/test/ui/rustdoc/check-doc-alias-attr.stderr @@ -10,7 +10,7 @@ error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of s LL | #[doc(alias = 0)] | ^^^^^^^^^ -error: '\"' character isn't allowed in `#[doc(alias = "...")]` +error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:9:15 | LL | #[doc(alias = "\"")] @@ -60,7 +60,7 @@ error: `#[doc(alias("a"))]` expects string literals LL | #[doc(alias(0))] | ^ -error: '\"' character isn't allowed in `#[doc(alias("..."))]` +error: '"' character isn't allowed in `#[doc(alias("..."))]` --> $DIR/check-doc-alias-attr.rs:20:13 | LL | #[doc(alias("\""))] diff --git a/src/test/ui/sanitize/address.rs b/src/test/ui/sanitize/address.rs index cee73b0425..9a26a351d9 100644 --- a/src/test/ui/sanitize/address.rs +++ b/src/test/ui/sanitize/address.rs @@ -7,7 +7,7 @@ // error-pattern: AddressSanitizer: stack-buffer-overflow // error-pattern: 'xs' (line 15) <== Memory access at offset -#![feature(test)] +#![feature(bench_black_box)] use std::hint::black_box; diff --git a/src/test/ui/sanitize/hwaddress.rs b/src/test/ui/sanitize/hwaddress.rs index ad5d024545..bb6986740d 100644 --- a/src/test/ui/sanitize/hwaddress.rs +++ b/src/test/ui/sanitize/hwaddress.rs @@ -1,12 +1,13 @@ // needs-sanitizer-support // needs-sanitizer-hwaddress // -// compile-flags: -Z sanitizer=hwaddress -O -g +// FIXME(#83989): codegen-units=1 triggers linker errors on aarch64-gnu +// compile-flags: -Z sanitizer=hwaddress -O -g -C codegen-units=16 // // run-fail // error-pattern: HWAddressSanitizer: tag-mismatch -#![feature(test)] +#![feature(bench_black_box)] use std::hint::black_box; diff --git a/src/test/ui/sanitize/leak.rs b/src/test/ui/sanitize/leak.rs index c9f10fe4f4..f63f81352d 100644 --- a/src/test/ui/sanitize/leak.rs +++ b/src/test/ui/sanitize/leak.rs @@ -6,7 +6,7 @@ // run-fail // error-pattern: LeakSanitizer: detected memory leaks -#![feature(test)] +#![feature(bench_black_box)] use std::hint::black_box; use std::mem; diff --git a/src/test/ui/sanitize/memory.rs b/src/test/ui/sanitize/memory.rs index a26649a580..48a482a13a 100644 --- a/src/test/ui/sanitize/memory.rs +++ b/src/test/ui/sanitize/memory.rs @@ -13,7 +13,7 @@ #![feature(core_intrinsics)] #![feature(start)] -#![feature(test)] +#![feature(bench_black_box)] use std::hint::black_box; use std::mem::MaybeUninit; diff --git a/src/test/ui/sanitize/unsupported-target.rs b/src/test/ui/sanitize/unsupported-target.rs index 6ccc9988cd..3fb749815f 100644 --- a/src/test/ui/sanitize/unsupported-target.rs +++ b/src/test/ui/sanitize/unsupported-target.rs @@ -1,6 +1,5 @@ // compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu -// error-pattern: error: `-Zsanitizer=leak` only works with targets: - +// error-pattern: error: leak sanitizer is not supported for this target #![feature(no_core)] #![no_core] #![no_main] diff --git a/src/test/ui/sanitize/unsupported-target.stderr b/src/test/ui/sanitize/unsupported-target.stderr index 093678707f..9bb8405020 100644 --- a/src/test/ui/sanitize/unsupported-target.stderr +++ b/src/test/ui/sanitize/unsupported-target.stderr @@ -1,4 +1,4 @@ -error: `-Zsanitizer=leak` only works with targets: aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu +error: leak sanitizer is not supported for this target error: aborting due to previous error diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr index 2954a499c1..b804ddfb02 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr @@ -9,6 +9,11 @@ LL | fn foo(self: Box<Self>) {} ... LL | A.foo(); | ^^^ method not found in `A` + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(A).foo(); + | ^^^^^^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 89fe84c0d2..e1ed0e42f9 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -10,6 +10,11 @@ LL | struct A; ... LL | A.foo() | ^^^ method not found in `A` + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(A).foo() + | ^^^^^^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr index 362907ecbd..c3b9084aff 100644 --- a/src/test/ui/shadowed/shadowed-trait-methods.stderr +++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `f` found for unit type `()` in the current scope --> $DIR/shadowed-trait-methods.rs:13:8 | +LL | pub trait T { fn f(&self) {} } + | - the method is available for `()` here +... LL | ().f() | ^ method not found in `()` | diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs index 4d23a1911a..9736d1b964 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs @@ -1,6 +1,5 @@ // build-fail // ignore-emscripten -// ignore-tidy-linelength #![feature(repr_simd, platform_intrinsics)] #![allow(non_camel_case_types)] #[repr(simd)] diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr index 1ed472a485..0e88540bcc 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr @@ -1,11 +1,11 @@ error[E0511]: invalid monomorphization of `simd_saturating_add` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type - --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:34:9 + --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:33:9 | LL | simd_saturating_add(z, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_saturating_sub` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type - --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:36:9 + --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:35:9 | LL | simd_saturating_sub(z, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-float-math.rs b/src/test/ui/simd/simd-intrinsic-float-math.rs index 220a59535c..7a4f746655 100644 --- a/src/test/ui/simd/simd-intrinsic-float-math.rs +++ b/src/test/ui/simd/simd-intrinsic-float-math.rs @@ -20,16 +20,20 @@ extern "platform-intrinsic" { fn simd_fabs<T>(x: T) -> T; fn simd_fsin<T>(x: T) -> T; fn simd_fcos<T>(x: T) -> T; - fn simd_ceil<T>(x: T) -> T; fn simd_fexp<T>(x: T) -> T; fn simd_fexp2<T>(x: T) -> T; - fn simd_floor<T>(x: T) -> T; fn simd_fma<T>(x: T, y: T, z: T) -> T; fn simd_flog<T>(x: T) -> T; fn simd_flog10<T>(x: T) -> T; fn simd_flog2<T>(x: T) -> T; fn simd_fpow<T>(x: T, y: T) -> T; fn simd_fpowi<T>(x: T, y: i32) -> T; + + // rounding functions + fn simd_ceil<T>(x: T) -> T; + fn simd_floor<T>(x: T) -> T; + fn simd_round<T>(x: T) -> T; + fn simd_trunc<T>(x: T) -> T; } macro_rules! assert_approx_eq_f32 { @@ -64,18 +68,12 @@ fn main() { let r = simd_fcos(z); assert_approx_eq!(x, r); - let r = simd_ceil(h); - assert_approx_eq!(x, r); - let r = simd_fexp(z); assert_approx_eq!(x, r); let r = simd_fexp2(z); assert_approx_eq!(x, r); - let r = simd_floor(h); - assert_approx_eq!(z, r); - let r = simd_fma(x, h, h); assert_approx_eq!(x, r); @@ -99,5 +97,18 @@ fn main() { let r = simd_fsin(z); assert_approx_eq!(z, r); + + // rounding functions + let r = simd_floor(h); + assert_eq!(z, r); + + let r = simd_ceil(h); + assert_eq!(x, r); + + let r = simd_round(h); + assert_eq!(x, r); + + let r = simd_trunc(h); + assert_eq!(z, r); } } diff --git a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs index 8b5afeac0b..7193fb3527 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs @@ -2,7 +2,6 @@ #![allow(non_camel_case_types)] // ignore-emscripten -// min-system-llvm-version: 9.0 // Test that the simd_reduce_{op} intrinsics produce the correct results. diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation.rs b/src/test/ui/simd/simd-type-generic-monomorphisation.rs index 0275f0ce4c..12f9d65d77 100644 --- a/src/test/ui/simd/simd-type-generic-monomorphisation.rs +++ b/src/test/ui/simd/simd-type-generic-monomorphisation.rs @@ -2,7 +2,6 @@ #![feature(repr_simd, platform_intrinsics)] -// ignore-tidy-linelength // error-pattern:monomorphising SIMD type `Simd2<X>` with a non-primitive-scalar (integer/float/pointer) element type `X` diff --git a/src/test/ui/simd/simd-type.rs b/src/test/ui/simd/simd-type.rs index 73d032a0c8..d82c70b8d8 100644 --- a/src/test/ui/simd/simd-type.rs +++ b/src/test/ui/simd/simd-type.rs @@ -1,7 +1,6 @@ #![feature(repr_simd)] #![allow(non_camel_case_types)] -// ignore-tidy-linelength #[repr(simd)] struct empty; //~ ERROR SIMD vector cannot be empty diff --git a/src/test/ui/simd/simd-type.stderr b/src/test/ui/simd/simd-type.stderr index 823f10f5da..4e4a19ea32 100644 --- a/src/test/ui/simd/simd-type.stderr +++ b/src/test/ui/simd/simd-type.stderr @@ -1,35 +1,35 @@ error[E0075]: SIMD vector cannot be empty - --> $DIR/simd-type.rs:7:1 + --> $DIR/simd-type.rs:6:1 | LL | struct empty; | ^^^^^^^^^^^^^ error[E0075]: SIMD vector cannot be empty - --> $DIR/simd-type.rs:10:1 + --> $DIR/simd-type.rs:9:1 | LL | struct empty2([f32; 0]); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0076]: SIMD vector should be homogeneous - --> $DIR/simd-type.rs:16:1 + --> $DIR/simd-type.rs:15:1 | LL | struct i64f64(i64, f64); | ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/simd-type.rs:21:1 + --> $DIR/simd-type.rs:20:1 | LL | struct FooV(Foo, Foo); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/simd-type.rs:24:1 + --> $DIR/simd-type.rs:23:1 | LL | struct FooV2([Foo; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0075]: SIMD vector cannot have more than 32768 elements - --> $DIR/simd-type.rs:27:1 + --> $DIR/simd-type.rs:26:1 | LL | struct TooBig([f32; 65536]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/single-primitive-inherent-impl.rs b/src/test/ui/single-primitive-inherent-impl.rs index baa23396c1..75c62feec3 100644 --- a/src/test/ui/single-primitive-inherent-impl.rs +++ b/src/test/ui/single-primitive-inherent-impl.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![crate_type = "lib"] #![feature(lang_items)] #![no_std] diff --git a/src/test/ui/single-primitive-inherent-impl.stderr b/src/test/ui/single-primitive-inherent-impl.stderr index 50a0d5bef8..349a12eac0 100644 --- a/src/test/ui/single-primitive-inherent-impl.stderr +++ b/src/test/ui/single-primitive-inherent-impl.stderr @@ -1,5 +1,5 @@ error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive - --> $DIR/single-primitive-inherent-impl.rs:11:1 + --> $DIR/single-primitive-inherent-impl.rs:9:1 | LL | / impl str { LL | | diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr index b5a1877ea1..eb5d80bc4d 100644 --- a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr @@ -28,8 +28,8 @@ LL | default type U<'a> = &'a T; = note: required because of the requirements on the impl of `PartialEq` for `&'a T` help: consider further restricting this bound | -LL | impl<T: 'static + PartialEq> X for T { - | ^^^^^^^^^^^ +LL | impl<T: 'static + std::cmp::PartialEq> X for T { + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 2 warnings emitted diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr index 57b90c457c..e416f30cb4 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -19,8 +19,8 @@ LL | default impl<U> Foo<'static, U> for () {} | help: consider restricting type parameter `U` | -LL | default impl<U: Eq> Foo<'static, U> for () {} - | ^^^^ +LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {} + | ^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/specialization/issue-33017.rs b/src/test/ui/specialization/issue-33017.rs new file mode 100644 index 0000000000..4d19230df6 --- /dev/null +++ b/src/test/ui/specialization/issue-33017.rs @@ -0,0 +1,45 @@ +// Test to ensure that trait bounds are propertly +// checked on specializable associated types + +#![allow(incomplete_features)] +#![feature(specialization)] + +trait UncheckedCopy: Sized { + type Output: From<Self> + Copy + Into<Self>; +} + +impl<T> UncheckedCopy for T { + default type Output = Self; + //~^ ERROR: the trait bound `T: Copy` is not satisfied +} + +fn unchecked_copy<T: UncheckedCopy>(other: &T::Output) -> T { + (*other).into() +} + +fn bug(origin: String) { + // Turn the String into it's Output type... + // Which we can just do by `.into()`, the assoc type states `From<Self>`. + let origin_output = origin.into(); + + // Make a copy of String::Output, which is a String... + let mut copy: String = unchecked_copy::<String>(&origin_output); + + // Turn the Output type into a String again, + // Which we can just do by `.into()`, the assoc type states `Into<Self>`. + let mut origin: String = origin_output.into(); + + // assert both Strings use the same buffer. + assert_eq!(copy.as_ptr(), origin.as_ptr()); + + // Any use of the copy we made becomes invalid, + drop(origin); + + // OH NO! UB UB UB UB! + copy.push_str(" world!"); + println!("{}", copy); +} + +fn main() { + bug(String::from("hello")); +} diff --git a/src/test/ui/specialization/issue-33017.stderr b/src/test/ui/specialization/issue-33017.stderr new file mode 100644 index 0000000000..bff4618d0b --- /dev/null +++ b/src/test/ui/specialization/issue-33017.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-33017.rs:12:5 + | +LL | type Output: From<Self> + Copy + Into<Self>; + | ---- required by this bound in `UncheckedCopy::Output` +... +LL | default type Output = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> UncheckedCopy for T { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr index bd5ed498d9..a93f27ff05 100644 --- a/src/test/ui/specialization/issue-38091-2.stderr +++ b/src/test/ui/specialization/issue-38091-2.stderr @@ -10,7 +10,11 @@ LL | #![feature(specialization)] error[E0275]: overflow evaluating the requirement `i32: Check` | - = note: required because of the requirements on the impl of `Iterate` for `i32` +note: required because of the requirements on the impl of `Iterate` for `i32` + --> $DIR/issue-38091-2.rs:11:13 + | +LL | impl<'a, T> Iterate<'a> for T + | ^^^^^^^^^^^ ^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/specialization/issue-39448.rs b/src/test/ui/specialization/issue-39448.rs index 9dd47a4a17..a15c4bd6b7 100644 --- a/src/test/ui/specialization/issue-39448.rs +++ b/src/test/ui/specialization/issue-39448.rs @@ -18,7 +18,7 @@ impl FromA<u8> for u16 { } trait FromA<T> { - fn from(T) -> Self; + fn from(t: T) -> Self; } impl<T: A, U: A + FromA<T>> FromA<T> for U { diff --git a/src/test/ui/specialization/issue-39448.stderr b/src/test/ui/specialization/issue-39448.stderr index 98e49b1bab..c4fc44c737 100644 --- a/src/test/ui/specialization/issue-39448.stderr +++ b/src/test/ui/specialization/issue-39448.stderr @@ -14,8 +14,16 @@ error[E0275]: overflow evaluating the requirement `T: FromA<U>` LL | x.foo(y.to()).to() | ^^ | - = note: required because of the requirements on the impl of `FromA<U>` for `T` - = note: required because of the requirements on the impl of `ToA<T>` for `U` +note: required because of the requirements on the impl of `FromA<U>` for `T` + --> $DIR/issue-39448.rs:24:29 + | +LL | impl<T: A, U: A + FromA<T>> FromA<T> for U { + | ^^^^^^^^ ^ +note: required because of the requirements on the impl of `ToA<T>` for `U` + --> $DIR/issue-39448.rs:34:12 + | +LL | impl<T, U> ToA<U> for T + | ^^^^^^ ^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/specialization/issue-51892.rs b/src/test/ui/specialization/issue-51892.rs new file mode 100644 index 0000000000..3cd0711ae4 --- /dev/null +++ b/src/test/ui/specialization/issue-51892.rs @@ -0,0 +1,19 @@ +#![allow(incomplete_features)] +#![feature(const_generics)] +#![feature(const_evaluatable_checked)] +#![feature(specialization)] + +pub trait Trait { + type Type; +} + +impl<T: ?Sized> Trait for T { + default type Type = [u8; 1]; +} + +impl<T: Trait> Trait for *const T { + type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()]; + //~^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/src/test/ui/specialization/issue-51892.stderr b/src/test/ui/specialization/issue-51892.stderr new file mode 100644 index 0000000000..2d30164380 --- /dev/null +++ b/src/test/ui/specialization/issue-51892.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-51892.rs:15:5 + | +LL | type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<<T as Trait>::Type>()]:` + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr index 27070f8e4a..ab3cf27d0d 100644 --- a/src/test/ui/specialization/issue-52050.stderr +++ b/src/test/ui/specialization/issue-52050.stderr @@ -8,7 +8,7 @@ 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 -error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`: +error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()` --> $DIR/issue-52050.rs:28:1 | LL | / impl<I> IntoPyDictPointer for I diff --git a/src/test/ui/specialization/issue-68830-spurious-diagnostics.rs b/src/test/ui/specialization/issue-68830-spurious-diagnostics.rs new file mode 100644 index 0000000000..d11ec79833 --- /dev/null +++ b/src/test/ui/specialization/issue-68830-spurious-diagnostics.rs @@ -0,0 +1,23 @@ +// A regression test for #68830. This checks we don't emit +// a verbose `conflicting implementations` error. + +#![feature(specialization)] +#![allow(incomplete_features)] + +struct BadStruct { + err: MissingType //~ ERROR: cannot find type `MissingType` in this scope +} + +trait MyTrait<T> { + fn foo(); +} + +impl<T, D> MyTrait<T> for D { + default fn foo() {} +} + +impl<T> MyTrait<T> for BadStruct { + fn foo() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr b/src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr new file mode 100644 index 0000000000..833f61dca8 --- /dev/null +++ b/src/test/ui/specialization/issue-68830-spurious-diagnostics.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/issue-68830-spurious-diagnostics.rs:8:10 + | +LL | err: MissingType + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr index 92208231b1..fa59d7a031 100644 --- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -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[317d]::Id::This) }, (I,)), [])` --> $DIR/repeated_projection_type.rs:19:1 | LL | / impl<I, V: Id<This = (I,)>> X for V { diff --git a/src/test/ui/specialization/specialization-feature-gate-overlap.stderr b/src/test/ui/specialization/specialization-feature-gate-overlap.stderr index baaf7aa433..9157ad0d46 100644 --- a/src/test/ui/specialization/specialization-feature-gate-overlap.stderr +++ b/src/test/ui/specialization/specialization-feature-gate-overlap.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Foo` for type `u8`: +error[E0119]: conflicting implementations of trait `Foo` for type `u8` --> $DIR/specialization-feature-gate-overlap.rs:13:1 | LL | impl<T> Foo for T { diff --git a/src/test/ui/specialization/specialization-overlap.stderr b/src/test/ui/specialization/specialization-overlap.stderr index 7e5c96ac1c..3ccbe1616e 100644 --- a/src/test/ui/specialization/specialization-overlap.stderr +++ b/src/test/ui/specialization/specialization-overlap.stderr @@ -8,7 +8,7 @@ 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 -error[E0119]: conflicting implementations of trait `Foo` for type `std::vec::Vec<_>`: +error[E0119]: conflicting implementations of trait `Foo` for type `std::vec::Vec<_>` --> $DIR/specialization-overlap.rs:5:1 | LL | impl<T: Clone> Foo for T {} @@ -16,7 +16,7 @@ LL | impl<T: Clone> Foo for T {} LL | impl<T> Foo for Vec<T> {} | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::vec::Vec<_>` -error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)`: +error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)` --> $DIR/specialization-overlap.rs:9:1 | LL | impl<T> Bar for (T, u8) {} @@ -24,7 +24,7 @@ LL | impl<T> Bar for (T, u8) {} LL | impl<T> Bar for (u8, T) {} | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)` -error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8`: +error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8` --> $DIR/specialization-overlap.rs:13:1 | LL | impl<T> Baz<T> for u8 {} @@ -32,7 +32,7 @@ LL | impl<T> Baz<T> for u8 {} LL | impl<T> Baz<u8> for T {} | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8` -error[E0119]: conflicting implementations of trait `Qux`: +error[E0119]: conflicting implementations of trait `Qux` --> $DIR/specialization-overlap.rs:17:1 | LL | impl<T: Clone> Qux for T {} diff --git a/src/test/ui/stability-attribute/generics-default-stability-where.rs b/src/test/ui/stability-attribute/generics-default-stability-where.rs index 3fd14e25d0..4afbca2626 100644 --- a/src/test/ui/stability-attribute/generics-default-stability-where.rs +++ b/src/test/ui/stability-attribute/generics-default-stability-where.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // aux-build:unstable_generic_param.rs extern crate unstable_generic_param; diff --git a/src/test/ui/stability-attribute/generics-default-stability-where.stderr b/src/test/ui/stability-attribute/generics-default-stability-where.stderr index 19fa09f311..61253adc89 100644 --- a/src/test/ui/stability-attribute/generics-default-stability-where.stderr +++ b/src/test/ui/stability-attribute/generics-default-stability-where.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability-where.rs:8:45 + --> $DIR/generics-default-stability-where.rs:7:45 | LL | impl<T> Trait3<usize> for T where T: Trait2<usize> { | ^^^^^ diff --git a/src/test/ui/stability-attribute/generics-default-stability.rs b/src/test/ui/stability-attribute/generics-default-stability.rs index d6f28e3e44..67f2334efc 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.rs +++ b/src/test/ui/stability-attribute/generics-default-stability.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // aux-build:unstable_generic_param.rs #![feature(unstable_default6)] diff --git a/src/test/ui/stability-attribute/generics-default-stability.stderr b/src/test/ui/stability-attribute/generics-default-stability.stderr index 45194413cc..99523f8eb6 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.stderr +++ b/src/test/ui/stability-attribute/generics-default-stability.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:17:13 + --> $DIR/generics-default-stability.rs:16:13 | LL | impl Trait1<usize> for S { | ^^^^^ @@ -7,7 +7,7 @@ LL | impl Trait1<usize> for S { = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:21:13 + --> $DIR/generics-default-stability.rs:20:13 | LL | impl Trait1<isize> for S { | ^^^^^ @@ -15,7 +15,7 @@ LL | impl Trait1<isize> for S { = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:25:13 + --> $DIR/generics-default-stability.rs:24:13 | LL | impl Trait2<usize> for S { | ^^^^^ @@ -23,7 +23,7 @@ LL | impl Trait2<usize> for S { = help: add `#![feature(unstable_default)]` to the crate attributes to enable warning: use of deprecated struct `unstable_generic_param::Struct4`: test - --> $DIR/generics-default-stability.rs:84:29 + --> $DIR/generics-default-stability.rs:83:29 | LL | let _: Struct4<isize> = Struct4 { field: 1 }; | ^^^^^^^ @@ -31,217 +31,217 @@ LL | let _: Struct4<isize> = Struct4 { field: 1 }; = note: `#[warn(deprecated)]` on by default warning: use of deprecated struct `unstable_generic_param::Struct4`: test - --> $DIR/generics-default-stability.rs:84:12 + --> $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:89:12 + --> $DIR/generics-default-stability.rs:88:12 | LL | let _: Struct4 = STRUCT4; | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct4`: test - --> $DIR/generics-default-stability.rs:90:12 + --> $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:91:29 + --> $DIR/generics-default-stability.rs:90:29 | LL | let _: Struct4<isize> = Struct4 { field: 0 }; | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct4`: test - --> $DIR/generics-default-stability.rs:91:12 + --> $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:97:29 + --> $DIR/generics-default-stability.rs:96:29 | LL | let _: Struct5<isize> = Struct5 { field: 1 }; | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct5`: test - --> $DIR/generics-default-stability.rs:97:12 + --> $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:102:12 + --> $DIR/generics-default-stability.rs:101:12 | LL | let _: Struct5 = STRUCT5; | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct5`: test - --> $DIR/generics-default-stability.rs:103:12 + --> $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:105:29 + --> $DIR/generics-default-stability.rs:104:29 | LL | let _: Struct5<isize> = Struct5 { field: 0 }; | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct5`: test - --> $DIR/generics-default-stability.rs:105:12 + --> $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:160:28 + --> $DIR/generics-default-stability.rs:159:28 | LL | let _: Alias4<isize> = Alias4::Some(1); | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test - --> $DIR/generics-default-stability.rs:160:12 + --> $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:164:12 + --> $DIR/generics-default-stability.rs:163:12 | LL | let _: Alias4 = ALIAS4; | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test - --> $DIR/generics-default-stability.rs:165:12 + --> $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:166:28 + --> $DIR/generics-default-stability.rs:165:28 | LL | let _: Alias4<isize> = Alias4::Some(0); | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test - --> $DIR/generics-default-stability.rs:166:12 + --> $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:171:28 + --> $DIR/generics-default-stability.rs:170:28 | LL | let _: Alias5<isize> = Alias5::Some(1); | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test - --> $DIR/generics-default-stability.rs:171:12 + --> $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:175:12 + --> $DIR/generics-default-stability.rs:174:12 | LL | let _: Alias5 = ALIAS5; | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test - --> $DIR/generics-default-stability.rs:176:12 + --> $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:178:28 + --> $DIR/generics-default-stability.rs:177:28 | LL | let _: Alias5<isize> = Alias5::Some(0); | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test - --> $DIR/generics-default-stability.rs:178:12 + --> $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:232:27 + --> $DIR/generics-default-stability.rs:231:27 | LL | let _: Enum4<isize> = Enum4::Some(1); | ^^^^^^^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test - --> $DIR/generics-default-stability.rs:232:12 + --> $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:236:12 + --> $DIR/generics-default-stability.rs:235:12 | LL | let _: Enum4 = ENUM4; | ^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test - --> $DIR/generics-default-stability.rs:237:12 + --> $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:238:27 + --> $DIR/generics-default-stability.rs:237:27 | LL | let _: Enum4<isize> = Enum4::Some(0); | ^^^^^^^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test - --> $DIR/generics-default-stability.rs:238:12 + --> $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:243:27 + --> $DIR/generics-default-stability.rs:242:27 | LL | let _: Enum5<isize> = Enum5::Some(1); | ^^^^^^^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test - --> $DIR/generics-default-stability.rs:243:12 + --> $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:247:12 + --> $DIR/generics-default-stability.rs:246:12 | LL | let _: Enum5 = ENUM5; | ^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test - --> $DIR/generics-default-stability.rs:248:12 + --> $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:250:27 + --> $DIR/generics-default-stability.rs:249:27 | LL | let _: Enum5<isize> = Enum5::Some(0); | ^^^^^^^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test - --> $DIR/generics-default-stability.rs:250:12 + --> $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:36:20 + --> $DIR/generics-default-stability.rs:35:20 | LL | let _: Struct1<isize> = Struct1 { field: 1 }; | ^^^^^ @@ -249,7 +249,7 @@ LL | let _: Struct1<isize> = Struct1 { field: 1 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:40:20 + --> $DIR/generics-default-stability.rs:39:20 | LL | let _: Struct1<usize> = STRUCT1; | ^^^^^ @@ -257,7 +257,7 @@ LL | let _: Struct1<usize> = STRUCT1; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:41:20 + --> $DIR/generics-default-stability.rs:40:20 | LL | let _: Struct1<isize> = Struct1 { field: 0 }; | ^^^^^ @@ -265,7 +265,7 @@ LL | let _: Struct1<isize> = Struct1 { field: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:70:27 + --> $DIR/generics-default-stability.rs:69:27 | LL | let _: Struct3<isize, usize> = STRUCT3; | ^^^^^ @@ -273,7 +273,7 @@ LL | let _: Struct3<isize, usize> = STRUCT3; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:72:27 + --> $DIR/generics-default-stability.rs:71:27 | LL | let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; | ^^^^^ @@ -281,7 +281,7 @@ LL | let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:73:27 + --> $DIR/generics-default-stability.rs:72:27 | LL | let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; | ^^^^^ @@ -289,7 +289,7 @@ LL | let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:97:20 + --> $DIR/generics-default-stability.rs:96:20 | LL | let _: Struct5<isize> = Struct5 { field: 1 }; | ^^^^^ @@ -297,7 +297,7 @@ LL | let _: Struct5<isize> = Struct5 { field: 1 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:103:20 + --> $DIR/generics-default-stability.rs:102:20 | LL | let _: Struct5<usize> = STRUCT5; | ^^^^^ @@ -305,7 +305,7 @@ LL | let _: Struct5<usize> = STRUCT5; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:105:20 + --> $DIR/generics-default-stability.rs:104:20 | LL | let _: Struct5<isize> = Struct5 { field: 0 }; | ^^^^^ @@ -313,7 +313,7 @@ LL | let _: Struct5<isize> = Struct5 { field: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:113:19 + --> $DIR/generics-default-stability.rs:112:19 | LL | let _: Alias1<isize> = Alias1::Some(1); | ^^^^^ @@ -321,7 +321,7 @@ LL | let _: Alias1<isize> = Alias1::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:117:19 + --> $DIR/generics-default-stability.rs:116:19 | LL | let _: Alias1<usize> = ALIAS1; | ^^^^^ @@ -329,7 +329,7 @@ LL | let _: Alias1<usize> = ALIAS1; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:118:19 + --> $DIR/generics-default-stability.rs:117:19 | LL | let _: Alias1<isize> = Alias1::Some(0); | ^^^^^ @@ -337,7 +337,7 @@ LL | let _: Alias1<isize> = Alias1::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:146:26 + --> $DIR/generics-default-stability.rs:145:26 | LL | let _: Alias3<isize, usize> = ALIAS3; | ^^^^^ @@ -345,7 +345,7 @@ LL | let _: Alias3<isize, usize> = ALIAS3; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:148:26 + --> $DIR/generics-default-stability.rs:147:26 | LL | let _: Alias3<isize, isize> = Alias3::Ok(0); | ^^^^^ @@ -353,7 +353,7 @@ LL | let _: Alias3<isize, isize> = Alias3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:149:26 + --> $DIR/generics-default-stability.rs:148:26 | LL | let _: Alias3<usize, usize> = Alias3::Ok(0); | ^^^^^ @@ -361,7 +361,7 @@ LL | let _: Alias3<usize, usize> = Alias3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:171:19 + --> $DIR/generics-default-stability.rs:170:19 | LL | let _: Alias5<isize> = Alias5::Some(1); | ^^^^^ @@ -369,7 +369,7 @@ LL | let _: Alias5<isize> = Alias5::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:176:19 + --> $DIR/generics-default-stability.rs:175:19 | LL | let _: Alias5<usize> = ALIAS5; | ^^^^^ @@ -377,7 +377,7 @@ LL | let _: Alias5<usize> = ALIAS5; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:178:19 + --> $DIR/generics-default-stability.rs:177:19 | LL | let _: Alias5<isize> = Alias5::Some(0); | ^^^^^ @@ -385,7 +385,7 @@ LL | let _: Alias5<isize> = Alias5::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:185:18 + --> $DIR/generics-default-stability.rs:184:18 | LL | let _: Enum1<isize> = Enum1::Some(1); | ^^^^^ @@ -393,7 +393,7 @@ LL | let _: Enum1<isize> = Enum1::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:189:18 + --> $DIR/generics-default-stability.rs:188:18 | LL | let _: Enum1<usize> = ENUM1; | ^^^^^ @@ -401,7 +401,7 @@ LL | let _: Enum1<usize> = ENUM1; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:190:18 + --> $DIR/generics-default-stability.rs:189:18 | LL | let _: Enum1<isize> = Enum1::Some(0); | ^^^^^ @@ -409,7 +409,7 @@ LL | let _: Enum1<isize> = Enum1::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:218:25 + --> $DIR/generics-default-stability.rs:217:25 | LL | let _: Enum3<isize, usize> = ENUM3; | ^^^^^ @@ -417,7 +417,7 @@ LL | let _: Enum3<isize, usize> = ENUM3; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:220:25 + --> $DIR/generics-default-stability.rs:219:25 | LL | let _: Enum3<isize, isize> = Enum3::Ok(0); | ^^^^^ @@ -425,7 +425,7 @@ LL | let _: Enum3<isize, isize> = Enum3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:221:25 + --> $DIR/generics-default-stability.rs:220:25 | LL | let _: Enum3<usize, usize> = Enum3::Ok(0); | ^^^^^ @@ -433,7 +433,7 @@ LL | let _: Enum3<usize, usize> = Enum3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:243:18 + --> $DIR/generics-default-stability.rs:242:18 | LL | let _: Enum5<isize> = Enum5::Some(1); | ^^^^^ @@ -441,7 +441,7 @@ LL | let _: Enum5<isize> = Enum5::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:248:18 + --> $DIR/generics-default-stability.rs:247:18 | LL | let _: Enum5<usize> = ENUM5; | ^^^^^ @@ -449,7 +449,7 @@ LL | let _: Enum5<usize> = ENUM5; = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'unstable_default' - --> $DIR/generics-default-stability.rs:250:18 + --> $DIR/generics-default-stability.rs:249:18 | LL | let _: Enum5<isize> = Enum5::Some(0); | ^^^^^ @@ -457,7 +457,7 @@ LL | let _: Enum5<isize> = Enum5::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'box_alloc_param' - --> $DIR/generics-default-stability.rs:257:24 + --> $DIR/generics-default-stability.rs:256:24 | LL | let _: Box1<isize, System> = Box1::new(1); | ^^^^^^ @@ -465,25 +465,25 @@ LL | let _: Box1<isize, System> = Box1::new(1); = help: add `#![feature(box_alloc_param)]` to the crate attributes to enable warning: use of deprecated field `unstable_generic_param::Struct4::field`: test - --> $DIR/generics-default-stability.rs:84:39 + --> $DIR/generics-default-stability.rs:83:39 | LL | let _: Struct4<isize> = Struct4 { field: 1 }; | ^^^^^^^^ warning: use of deprecated field `unstable_generic_param::Struct4::field`: test - --> $DIR/generics-default-stability.rs:91:39 + --> $DIR/generics-default-stability.rs:90:39 | LL | let _: Struct4<isize> = Struct4 { field: 0 }; | ^^^^^^^^ warning: use of deprecated field `unstable_generic_param::Struct5::field`: test - --> $DIR/generics-default-stability.rs:97:39 + --> $DIR/generics-default-stability.rs:96:39 | LL | let _: Struct5<isize> = Struct5 { field: 1 }; | ^^^^^^^^ warning: use of deprecated field `unstable_generic_param::Struct5::field`: test - --> $DIR/generics-default-stability.rs:105:39 + --> $DIR/generics-default-stability.rs:104:39 | LL | let _: Struct5<isize> = Struct5 { field: 0 }; | ^^^^^^^^ diff --git a/src/test/ui/bad/bad-const-type.rs b/src/test/ui/static/bad-const-type.rs similarity index 100% rename from src/test/ui/bad/bad-const-type.rs rename to src/test/ui/static/bad-const-type.rs diff --git a/src/test/ui/bad/bad-const-type.stderr b/src/test/ui/static/bad-const-type.stderr similarity index 100% rename from src/test/ui/bad/bad-const-type.stderr rename to src/test/ui/static/bad-const-type.stderr diff --git a/src/test/ui/issues/issue-1701.rs b/src/test/ui/structs-enums/issue-1701.rs similarity index 100% rename from src/test/ui/issues/issue-1701.rs rename to src/test/ui/structs-enums/issue-1701.rs diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.rs b/src/test/ui/structs/structure-constructor-type-mismatch.rs index 56c8ffb3e6..efc6304a6f 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.rs +++ b/src/test/ui/structs/structure-constructor-type-mismatch.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - struct Point<T> { x: T, y: T, diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr index 4611414967..6438127868 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr +++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:19:12 + --> $DIR/structure-constructor-type-mismatch.rs:17:12 | LL | x: 1, | ^ @@ -8,7 +8,7 @@ LL | x: 1, | help: use a float literal: `1.0` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:22:12 + --> $DIR/structure-constructor-type-mismatch.rs:20:12 | LL | y: 2, | ^ @@ -17,7 +17,7 @@ LL | y: 2, | help: use a float literal: `2.0` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:28:12 + --> $DIR/structure-constructor-type-mismatch.rs:26:12 | LL | x: 3, | ^ @@ -26,7 +26,7 @@ LL | x: 3, | help: use a float literal: `3.0` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:31:12 + --> $DIR/structure-constructor-type-mismatch.rs:29:12 | LL | y: 4, | ^ @@ -35,7 +35,7 @@ LL | y: 4, | help: use a float literal: `4.0` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:37:12 + --> $DIR/structure-constructor-type-mismatch.rs:35:12 | LL | x: 5, | ^ @@ -44,7 +44,7 @@ LL | x: 5, | help: use a float literal: `5.0` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:44:12 + --> $DIR/structure-constructor-type-mismatch.rs:42:12 | LL | x: 7, | ^ @@ -53,7 +53,7 @@ LL | x: 7, | help: use a float literal: `7.0` error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied - --> $DIR/structure-constructor-type-mismatch.rs:50:15 + --> $DIR/structure-constructor-type-mismatch.rs:48:15 | LL | let pt3 = PointF::<i32> { | ^^^^^^------- help: remove these generics @@ -61,13 +61,13 @@ LL | let pt3 = PointF::<i32> { | expected 0 type arguments | note: type alias defined here, with 0 type parameters - --> $DIR/structure-constructor-type-mismatch.rs:8:6 + --> $DIR/structure-constructor-type-mismatch.rs:6:6 | LL | type PointF = Point<f32>; | ^^^^^^ error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:51:12 + --> $DIR/structure-constructor-type-mismatch.rs:49:12 | LL | x: 9, | ^ @@ -76,7 +76,7 @@ LL | x: 9, | help: use a float literal: `9.0` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:52:12 + --> $DIR/structure-constructor-type-mismatch.rs:50:12 | LL | y: 10, | ^^ @@ -85,7 +85,7 @@ LL | y: 10, | help: use a float literal: `10.0` error[E0107]: this type alias takes 0 type arguments but 1 type argument was supplied - --> $DIR/structure-constructor-type-mismatch.rs:56:9 + --> $DIR/structure-constructor-type-mismatch.rs:54:9 | LL | PointF::<u32> { .. } => {} | ^^^^^^------- help: remove these generics @@ -93,13 +93,13 @@ LL | PointF::<u32> { .. } => {} | expected 0 type arguments | note: type alias defined here, with 0 type parameters - --> $DIR/structure-constructor-type-mismatch.rs:8:6 + --> $DIR/structure-constructor-type-mismatch.rs:6:6 | LL | type PointF = Point<f32>; | ^^^^^^ error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:56:9 + --> $DIR/structure-constructor-type-mismatch.rs:54:9 | LL | match (Point { x: 1, y: 2 }) { | ---------------------- this expression has type `Point<{integer}>` @@ -110,7 +110,7 @@ LL | PointF::<u32> { .. } => {} found struct `Point<f32>` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:61:9 + --> $DIR/structure-constructor-type-mismatch.rs:59:9 | LL | match (Point { x: 1, y: 2 }) { | ---------------------- this expression has type `Point<{integer}>` @@ -121,7 +121,7 @@ LL | PointF { .. } => {} found struct `Point<f32>` error[E0308]: mismatched types - --> $DIR/structure-constructor-type-mismatch.rs:69:9 + --> $DIR/structure-constructor-type-mismatch.rs:67:9 | LL | match (Pair { x: 1, y: 2 }) { | --------------------- this expression has type `Pair<{integer}, {integer}>` diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/substs-ppaux.normal.stderr index 89be3d29e0..5bbf422581 100644 --- a/src/test/ui/substs-ppaux.normal.stderr +++ b/src/test/ui/substs-ppaux.normal.stderr @@ -80,7 +80,11 @@ LL | <str as Foo<u8>>::bar; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str` +note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str` + --> $DIR/substs-ppaux.rs:11:17 + | +LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} + | ^^^^^^^^^^^^^^ ^ error: aborting due to 5 previous errors diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr index e37d087fcc..20d7655337 100644 --- a/src/test/ui/substs-ppaux.verbose.stderr +++ b/src/test/ui/substs-ppaux.verbose.stderr @@ -80,7 +80,11 @@ LL | <str as Foo<u8>>::bar; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8>` for `str` +note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8>` for `str` + --> $DIR/substs-ppaux.rs:11:17 + | +LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} + | ^^^^^^^^^^^^^^ ^ error: aborting due to 5 previous errors diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr index 9437fbe61c..5cb3a40403 100644 --- a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr +++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -5,7 +5,7 @@ LL | struct X<T>(T); | - required by this bound in `X` ... LL | struct Struct5<T: ?Sized>{ - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | _t: X<T>, | ^^^^ doesn't have a size known at compile-time | diff --git a/src/test/ui/suggestions/as-ref-2.fixed b/src/test/ui/suggestions/as-ref-2.fixed new file mode 100644 index 0000000000..13bbb233f3 --- /dev/null +++ b/src/test/ui/suggestions/as-ref-2.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +struct Struct; + +fn bar(_: &Struct) -> Struct { + Struct +} + +fn main() { + let foo = Some(Struct); + let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s)); + let _y = foo; //~ERROR use of moved value: `foo` +} diff --git a/src/test/ui/suggestions/as-ref-2.rs b/src/test/ui/suggestions/as-ref-2.rs new file mode 100644 index 0000000000..74d61cdd95 --- /dev/null +++ b/src/test/ui/suggestions/as-ref-2.rs @@ -0,0 +1,13 @@ +// run-rustfix + +struct Struct; + +fn bar(_: &Struct) -> Struct { + Struct +} + +fn main() { + let foo = Some(Struct); + let _x: Option<Struct> = foo.map(|s| bar(&s)); + let _y = foo; //~ERROR use of moved value: `foo` +} diff --git a/src/test/ui/suggestions/as-ref-2.stderr b/src/test/ui/suggestions/as-ref-2.stderr new file mode 100644 index 0000000000..f2eddf2fb0 --- /dev/null +++ b/src/test/ui/suggestions/as-ref-2.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/as-ref-2.rs:12:14 + | +LL | let foo = Some(Struct); + | --- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait +LL | let _x: Option<Struct> = foo.map(|s| bar(&s)); + | ---------------- `foo` moved due to this method call +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 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { + | ^^^^ +help: consider calling `.as_ref()` to borrow the type's contents + | +LL | let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s)); + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/suggestions/as-ref.rs b/src/test/ui/suggestions/as-ref.rs index 03f04c389f..46d9461538 100644 --- a/src/test/ui/suggestions/as-ref.rs +++ b/src/test/ui/suggestions/as-ref.rs @@ -1,25 +1,20 @@ struct Foo; + fn takes_ref(_: &Foo) {} fn main() { - let ref opt = Some(Foo); - opt.map(|arg| takes_ref(arg)); - //~^ ERROR mismatched types [E0308] - opt.and_then(|arg| Some(takes_ref(arg))); - //~^ ERROR mismatched types [E0308] - let ref opt: Result<_, ()> = Ok(Foo); - opt.map(|arg| takes_ref(arg)); - //~^ ERROR mismatched types [E0308] - opt.and_then(|arg| Ok(takes_ref(arg))); - //~^ ERROR mismatched types [E0308] - let x: &Option<usize> = &Some(3); - let y: Option<&usize> = x; - //~^ ERROR mismatched types [E0308] - let x: &Result<usize, usize> = &Ok(3); - let y: Result<&usize, &usize> = x; - //~^ ERROR mismatched types [E0308] - // note: do not suggest because of `E: usize` - let x: &Result<usize, usize> = &Ok(3); - let y: Result<&usize, usize> = x; - //~^ ERROR mismatched types [E0308] + let ref opt = Some(Foo); + opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + opt.and_then(|arg| Some(takes_ref(arg))); //~ ERROR mismatched types [E0308] + let ref opt: Result<_, ()> = Ok(Foo); + opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + opt.and_then(|arg| Ok(takes_ref(arg))); //~ ERROR mismatched types [E0308] + let x: &Option<usize> = &Some(3); + let y: Option<&usize> = x; //~ ERROR mismatched types [E0308] + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, &usize> = x; + //~^ ERROR mismatched types [E0308] + // note: do not suggest because of `E: usize` + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, usize> = x; //~ ERROR mismatched types [E0308] } diff --git a/src/test/ui/suggestions/as-ref.stderr b/src/test/ui/suggestions/as-ref.stderr index 7e4d7fb393..dc5d7efd75 100644 --- a/src/test/ui/suggestions/as-ref.stderr +++ b/src/test/ui/suggestions/as-ref.stderr @@ -1,70 +1,70 @@ error[E0308]: mismatched types - --> $DIR/as-ref.rs:6:27 + --> $DIR/as-ref.rs:7:29 | -LL | opt.map(|arg| takes_ref(arg)); - | --- ^^^ expected `&Foo`, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().map` +LL | opt.map(|arg| takes_ref(arg)); + | --- ^^^ expected `&Foo`, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().map` error[E0308]: mismatched types - --> $DIR/as-ref.rs:8:37 + --> $DIR/as-ref.rs:8:39 | -LL | opt.and_then(|arg| Some(takes_ref(arg))); - | -------- ^^^ expected `&Foo`, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().and_then` +LL | opt.and_then(|arg| Some(takes_ref(arg))); + | -------- ^^^ expected `&Foo`, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().and_then` error[E0308]: mismatched types - --> $DIR/as-ref.rs:11:27 + --> $DIR/as-ref.rs:10:29 | -LL | opt.map(|arg| takes_ref(arg)); - | --- ^^^ expected `&Foo`, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().map` +LL | opt.map(|arg| takes_ref(arg)); + | --- ^^^ expected `&Foo`, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().map` error[E0308]: mismatched types - --> $DIR/as-ref.rs:13:35 + --> $DIR/as-ref.rs:11:37 | -LL | opt.and_then(|arg| Ok(takes_ref(arg))); - | -------- ^^^ expected `&Foo`, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().and_then` +LL | opt.and_then(|arg| Ok(takes_ref(arg))); + | -------- ^^^ expected `&Foo`, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().and_then` error[E0308]: mismatched types - --> $DIR/as-ref.rs:16:27 + --> $DIR/as-ref.rs:13:29 | -LL | let y: Option<&usize> = x; - | -------------- ^ - | | | - | | expected enum `Option`, found `&Option<usize>` - | | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()` - | expected due to this +LL | let y: Option<&usize> = x; + | -------------- ^ + | | | + | | expected enum `Option`, found `&Option<usize>` + | | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()` + | expected due to this | = note: expected enum `Option<&usize>` found reference `&Option<usize>` error[E0308]: mismatched types - --> $DIR/as-ref.rs:19:35 + --> $DIR/as-ref.rs:15:37 | -LL | let y: Result<&usize, &usize> = x; - | ---------------------- ^ expected enum `Result`, found reference - | | - | expected due to this +LL | let y: Result<&usize, &usize> = x; + | ---------------------- ^ expected enum `Result`, found reference + | | + | expected due to this | = note: expected enum `Result<&usize, &usize>` found reference `&Result<usize, usize>` help: you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()` | -LL | let y: Result<&usize, &usize> = x.as_ref(); - | ^^^^^^^^^^ +LL | let y: Result<&usize, &usize> = x.as_ref(); + | ^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/as-ref.rs:23:34 + --> $DIR/as-ref.rs:19:36 | -LL | let y: Result<&usize, usize> = x; - | --------------------- ^ expected enum `Result`, found reference - | | - | expected due to this +LL | let y: Result<&usize, usize> = x; + | --------------------- ^ expected enum `Result`, found reference + | | + | expected due to this | = note: expected enum `Result<&usize, usize>` found reference `&Result<usize, usize>` diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 32961b7f87..3786457fb1 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -46,6 +46,7 @@ error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned 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` error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned @@ -54,6 +55,7 @@ error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned 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` error[E0308]: mismatched types diff --git a/src/test/ui/suggestions/import-trait-for-method-call.rs b/src/test/ui/suggestions/import-trait-for-method-call.rs new file mode 100644 index 0000000000..4dbadbdf98 --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.rs @@ -0,0 +1,16 @@ +use std::hash::BuildHasher; + +fn next_u64() -> u64 { + let bh = std::collections::hash_map::RandomState::new(); + let h = bh.build_hasher(); + h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher` +} + +trait Bar {} +impl Bar for String {} + +fn main() { + let s = String::from("hey"); + let x: &dyn Bar = &s; + x.as_ref(); //~ ERROR the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds +} diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr new file mode 100644 index 0000000000..a2b9b9d14a --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr @@ -0,0 +1,36 @@ +error[E0599]: no method named `finish` found for struct `DefaultHasher` in the current scope + --> $DIR/import-trait-for-method-call.rs:6:7 + | +LL | h.finish() + | ^^^^^^ method not found in `DefaultHasher` + | + ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL + | +LL | fn finish(&self) -> u64; + | ------ the method is available for `DefaultHasher` here + | + = 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 std::hash::Hasher; + | + +error[E0599]: the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds were not satisfied + --> $DIR/import-trait-for-method-call.rs:15:7 + | +LL | trait Bar {} + | --------- doesn't satisfy `dyn Bar: AsRef<_>` +... +LL | x.as_ref(); + | ^^^^^^ method cannot be called on `&dyn Bar` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `dyn Bar: AsRef<_>` + which is required by `&dyn Bar: AsRef<_>` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_ref`, perhaps you need to implement it: + candidate #1: `AsRef` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 2854b830ba..26efd50bb8 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -7,6 +7,7 @@ LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} LL | foo(String::new()); | ^^^ the trait `From<String>` is not implemented for `&str` | + = note: to coerce a `String` into a `&str`, use `&*` as a prefix = note: required because of the requirements on the impl of `Into<&str>` for `String` error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-82361.stderr b/src/test/ui/suggestions/issue-82361.stderr index c19d59ccd4..4c78293ebb 100644 --- a/src/test/ui/suggestions/issue-82361.stderr +++ b/src/test/ui/suggestions/issue-82361.stderr @@ -21,10 +21,10 @@ LL | | 1 | | - expected because of this LL | | } else { LL | | &1 - | | -^ + | | ^^ | | | | | expected integer, found `&{integer}` - | | help: consider removing the `&` + | | help: consider removing the borrow: `1` LL | | }; | |_____- `if` and `else` have incompatible types @@ -36,10 +36,10 @@ LL | | 1 | | - expected because of this LL | | } else { LL | | &mut 1 - | | -----^ + | | ^^^^^^ | | | | | expected integer, found `&mut {integer}` - | | help: consider removing the `&mut` + | | help: consider removing the borrow: `1` LL | | }; | |_____- `if` and `else` have incompatible types diff --git a/src/test/ui/suggestions/issue-83892.fixed b/src/test/ui/suggestions/issue-83892.fixed new file mode 100644 index 0000000000..dd093a7a0e --- /dev/null +++ b/src/test/ui/suggestions/issue-83892.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +fn func() -> u8 { + 0 +} + +fn main() { + match () { + () => func() //~ ERROR mismatched types + }; +} diff --git a/src/test/ui/suggestions/issue-83892.rs b/src/test/ui/suggestions/issue-83892.rs new file mode 100644 index 0000000000..1d56ecee86 --- /dev/null +++ b/src/test/ui/suggestions/issue-83892.rs @@ -0,0 +1,11 @@ +// run-rustfix + +fn func() -> u8 { + 0 +} + +fn main() { + match () { + () => func() //~ ERROR mismatched types + } +} diff --git a/src/test/ui/suggestions/issue-83892.stderr b/src/test/ui/suggestions/issue-83892.stderr new file mode 100644 index 0000000000..baf6b1447e --- /dev/null +++ b/src/test/ui/suggestions/issue-83892.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-83892.rs:9:15 + | +LL | fn main() { + | - expected `()` because of default return type +LL | match () { +LL | () => func() + | ^^^^^^ expected `()`, found `u8` +LL | } + | - help: consider using a semicolon here: `;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-83943.fixed b/src/test/ui/suggestions/issue-83943.fixed new file mode 100644 index 0000000000..e0d4ee29eb --- /dev/null +++ b/src/test/ui/suggestions/issue-83943.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + if true { + "A".to_string() + } else { + "B".to_string() //~ ERROR `if` and `else` have incompatible types + }; +} diff --git a/src/test/ui/suggestions/issue-83943.rs b/src/test/ui/suggestions/issue-83943.rs new file mode 100644 index 0000000000..68d50c1775 --- /dev/null +++ b/src/test/ui/suggestions/issue-83943.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + if true { + "A".to_string() + } else { + "B" //~ ERROR `if` and `else` have incompatible types + }; +} diff --git a/src/test/ui/suggestions/issue-83943.stderr b/src/test/ui/suggestions/issue-83943.stderr new file mode 100644 index 0000000000..a26700ea3c --- /dev/null +++ b/src/test/ui/suggestions/issue-83943.stderr @@ -0,0 +1,18 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-83943.rs:7:9 + | +LL | / if true { +LL | | "A".to_string() + | | --------------- expected because of this +LL | | } else { +LL | | "B" + | | ^^^ + | | | + | | expected struct `String`, found `&str` + | | help: try using a conversion method: `"B".to_string()` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr deleted file mode 100644 index b509610b89..0000000000 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr +++ /dev/null @@ -1,92 +0,0 @@ -error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/missing-lifetimes-in-signature.rs:37:11 - | -LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | - ^^ undeclared lifetime - | | - | help: consider introducing lifetime `'a` here: `'a,` - -error: lifetime may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:15:37 - | -LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() - | - ^^^^^^^^^^^^^ 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 | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ - -error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:25:37 - | -LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 25:26... - --> $DIR/missing-lifetimes-in-signature.rs:25:26 - | -LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^ - -error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:47:45 - | -LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 47:34... - --> $DIR/missing-lifetimes-in-signature.rs:47:34 - | -LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^ - -error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:59:58 - | -LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined on the method body at 59:47... - --> $DIR/missing-lifetimes-in-signature.rs:59:47 - | -LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ^^^^^^ - -error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:68:45 - | -LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ^^^^^^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 68:34... - --> $DIR/missing-lifetimes-in-signature.rs:68:34 - | -LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ^^^^^^ - -error[E0621]: explicit lifetime required in the type of `dest` - --> $DIR/missing-lifetimes-in-signature.rs:73:5 - | -LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` -... -LL | / move || { -LL | | *dest = g.get(); -LL | | } - | |_____^ lifetime `'a` required - -error[E0309]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:79:44 - | -LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `G: 'a`... - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0261, E0309, E0621. -For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index 94dd826a15..dd434ea531 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -16,14 +16,13 @@ fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() where G: Get<T> { - move || { //~ ERROR `dest` + move || { *dest = g.get(); } } // After applying suggestion for `foo`: fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ -//~^ ERROR the parameter type `G` may not live long enough where G: Get<T> { @@ -45,7 +44,6 @@ where // After applying suggestion for `baz`: fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ -//~^ ERROR the parameter type `G` may not live long enough where G: Get<T> { @@ -57,7 +55,6 @@ where // Same as above, but show that we pay attention to lifetime names from parent item impl<'a> Foo { fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - //~^ ERROR the parameter type `G` may not live long enough move || { *dest = g.get(); } @@ -66,7 +63,6 @@ impl<'a> Foo { // After applying suggestion for `qux`: fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a -//~^ ERROR explicit lifetime required in the type of `dest` where G: Get<T> { @@ -77,7 +73,6 @@ where // Potential incorrect attempt: fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a -//~^ ERROR the parameter type `G` may not live long enough where G: Get<T> { diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 789fff7acc..916a6c2bf1 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -1,112 +1,11 @@ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/missing-lifetimes-in-signature.rs:37:11 + --> $DIR/missing-lifetimes-in-signature.rs:36:11 | LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ | - ^^ undeclared lifetime | | | help: consider introducing lifetime `'a` here: `'a,` -error[E0759]: `dest` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/missing-lifetimes-in-signature.rs:19:5 - | -LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() - | ------ this data with an anonymous lifetime `'_`... -... -LL | / move || { -LL | | *dest = g.get(); -LL | | } - | |_____^ ...is captured here... - | -note: ...and is required to live as long as `'static` here - --> $DIR/missing-lifetimes-in-signature.rs:15:37 - | -LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() - | ^^^^^^^^^^^^^ -help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound - | -LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^ - -error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:25:37 - | -LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 25:26... - --> $DIR/missing-lifetimes-in-signature.rs:25:26 - | -LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^ -note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: 32:6]` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:25:37 - | -LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ -help: consider introducing an explicit lifetime bound - | -LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ^^^^^ ^^^^ - -error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:47:45 - | -LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 47:34... - --> $DIR/missing-lifetimes-in-signature.rs:47:34 - | -LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^ -note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: 54:6]` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:47:45 - | -LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ^^^^^^^^^^^^^^^^^^ -help: consider introducing an explicit lifetime bound - | -LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b - | ^^^ ^^^^^^^ ^^^^ - -error[E0311]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:59:58 - | -LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `G` must be valid for the anonymous lifetime defined on the method body at 59:47... - --> $DIR/missing-lifetimes-in-signature.rs:59:47 - | -LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ^^^^^^ -note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10]` will meet its required lifetime bounds - --> $DIR/missing-lifetimes-in-signature.rs:59:58 - | -LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ^^^^^^^^^^^^^^^^^^ -help: consider introducing an explicit lifetime bound - | -LL | fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c { - | ^^^ ^^^^^^^ ^^^^ - -error[E0621]: explicit lifetime required in the type of `dest` - --> $DIR/missing-lifetimes-in-signature.rs:68:45 - | -LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required - | | - | help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` - -error[E0309]: the parameter type `G` may not live long enough - --> $DIR/missing-lifetimes-in-signature.rs:79:44 - | -LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a - | - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6]` will meet its required lifetime bounds - | | - | help: consider adding an explicit lifetime bound...: `G: 'a` - -error: aborting due to 7 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0261, E0309, E0621, E0759. -For more information about an error, try `rustc --explain E0261`. +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index e6cec5cbd4..489926ea78 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -142,30 +142,6 @@ help: consider using the `'static` lifetime LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:50:44 - | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); - | ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime - | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^ - -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:50:44 - | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); - | ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime - | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^ - error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:43:44 | @@ -256,6 +232,18 @@ help: add missing lifetime argument LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:50:44 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:50:45 | @@ -274,6 +262,18 @@ help: add missing lifetime argument LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:50:44 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^^^^^^ + error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:50:45 | diff --git a/src/test/ui/suggestions/path-by-value.stderr b/src/test/ui/suggestions/path-by-value.stderr index 19fc3406cc..5919a6f749 100644 --- a/src/test/ui/suggestions/path-by-value.stderr +++ b/src/test/ui/suggestions/path-by-value.stderr @@ -9,8 +9,8 @@ LL | fn f(p: Path) { } = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn f(&p: Path) { } - | ^ +LL | fn f(p: &Path) { } + | ^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr index b08e22eaab..3ee2860b4f 100644 --- a/src/test/ui/suggestions/path-display.stderr +++ b/src/test/ui/suggestions/path-display.stderr @@ -2,10 +2,10 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display` --> $DIR/path-display.rs:5:20 | LL | println!("{}", path); - | ^^^^ `Path` cannot be formatted with the default formatter + | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it | = help: the trait `std::fmt::Display` is not implemented for `Path` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = 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 a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/suggestions/restrict-type-argument.stderr b/src/test/ui/suggestions/restrict-type-argument.stderr index 7a7242a636..33af13d943 100644 --- a/src/test/ui/suggestions/restrict-type-argument.stderr +++ b/src/test/ui/suggestions/restrict-type-argument.stderr @@ -9,8 +9,8 @@ LL | is_send(val); | help: consider further restricting this bound | -LL | fn use_impl_sync(val: impl Sync + Send) { - | ^^^^^^ +LL | fn use_impl_sync(val: impl Sync + std::marker::Send) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:8:13 @@ -23,8 +23,8 @@ LL | is_send(val); | help: consider further restricting this bound | -LL | fn use_where<S>(val: S) where S: Sync + Send { - | ^^^^^^ +LL | fn use_where<S>(val: S) where S: Sync + std::marker::Send { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:12:13 @@ -37,8 +37,8 @@ LL | is_send(val); | help: consider further restricting this bound | -LL | fn use_bound<S: Sync + Send>(val: S) { - | ^^^^^^ +LL | fn use_bound<S: Sync + std::marker::Send>(val: S) { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:20:13 @@ -51,8 +51,8 @@ LL | is_send(val); | help: consider further restricting this bound | -LL | Sync + Send - | ^^^^^^ +LL | Sync + std::marker::Send + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:24:13 @@ -65,8 +65,8 @@ LL | is_send(val); | help: consider further restricting this bound | -LL | fn use_bound_and_where<S: Sync>(val: S) where S: std::fmt::Debug + Send { - | ^^^^^^ +LL | fn use_bound_and_where<S: Sync>(val: S) where S: std::fmt::Debug + std::marker::Send { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:28:13 @@ -79,8 +79,8 @@ LL | is_send(val); | help: consider restricting type parameter `S` | -LL | fn use_unbound<S: Send>(val: S) { - | ^^^^^^ +LL | fn use_unbound<S: std::marker::Send>(val: S) { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr index 7155d88be9..3dd2b19fbf 100644 --- a/src/test/ui/symbol-names/basic.legacy.stderr +++ b/src/test/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17hfcf1daab33c43a6aE) +error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::hfcf1daab33c43a6a) +error: demangling(basic::main::h6c535bbea2051f85) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr index bd32a39a65..b6012e4159 100644 --- a/src/test/ui/symbol-names/impl1.legacy.stderr +++ b/src/test/ui/symbol-names/impl1.legacy.stderr @@ -1,71 +1,71 @@ error: symbol-name(_ZN5impl13foo3Foo3bar17<SYMBOL_HASH>) - --> $DIR/impl1.rs:15:9 + --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(impl1::foo::Foo::bar::<SYMBOL_HASH>) - --> $DIR/impl1.rs:15:9 + --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(impl1::foo::Foo::bar) - --> $DIR/impl1.rs:15:9 + --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(foo::Foo::bar) - --> $DIR/impl1.rs:22:9 + --> $DIR/impl1.rs:21:9 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17<SYMBOL_HASH>) - --> $DIR/impl1.rs:33:9 + --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(impl1::bar::<impl impl1::foo::Foo>::baz::<SYMBOL_HASH>) - --> $DIR/impl1.rs:33:9 + --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz) - --> $DIR/impl1.rs:33:9 + --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(bar::<impl foo::Foo>::baz) - --> $DIR/impl1.rs:40:9 + --> $DIR/impl1.rs:39:9 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ 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$6method17<SYMBOL_HASH>) - --> $DIR/impl1.rs:63:13 + --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method::<SYMBOL_HASH>) - --> $DIR/impl1.rs:63:13 + --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) - --> $DIR/impl1.rs:63:13 + --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:70:13 + --> $DIR/impl1.rs:69:13 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 771695330d..b0b31a57d0 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -1,5 +1,4 @@ // build-fail -// ignore-tidy-linelength // revisions: legacy v0 //[legacy]compile-flags: -Z symbol-mangling-version=legacy //[v0]compile-flags: -Z symbol-mangling-version=v0 diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr deleted file mode 100644 index 20e48782a3..0000000000 --- a/src/test/ui/symbol-names/impl1.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: symbol-name(_ZN5impl13foo3Foo3bar17he53b9bee7600ed8dE) - --> $DIR/impl1.rs:8:9 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: def-path(foo::Foo::bar) - --> $DIR/impl1.rs:9:9 - | -LL | #[rustc_def_path] - | ^^^^^^^^^^^^^^^^^ - -error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h86c41f0462d901d4E) - --> $DIR/impl1.rs:18:9 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: def-path(bar::<impl foo::Foo>::baz) - --> $DIR/impl1.rs:19:9 - | -LL | #[rustc_def_path] - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors - diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr index 3a6610935d..e5b0deee36 100644 --- a/src/test/ui/symbol-names/impl1.v0.stderr +++ b/src/test/ui/symbol-names/impl1.v0.stderr @@ -1,71 +1,71 @@ error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar) - --> $DIR/impl1.rs:15:9 + --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(<impl1[17891616a171812d]::foo::Foo>::bar) - --> $DIR/impl1.rs:15:9 + --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<impl1::foo::Foo>::bar) - --> $DIR/impl1.rs:15:9 + --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(foo::Foo::bar) - --> $DIR/impl1.rs:22:9 + --> $DIR/impl1.rs:21:9 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz) - --> $DIR/impl1.rs:33:9 + --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(<impl1[17891616a171812d]::foo::Foo>::baz) - --> $DIR/impl1.rs:33:9 + --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<impl1::foo::Foo>::baz) - --> $DIR/impl1.rs:33:9 + --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(bar::<impl foo::Foo>::baz) - --> $DIR/impl1.rs:40:9 + --> $DIR/impl1.rs:39:9 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ error: symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) - --> $DIR/impl1.rs:63:13 + --> $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) - --> $DIR/impl1.rs:63:13 + --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:63:13 + --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:70:13 + --> $DIR/impl1.rs:69:13 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 9575875f5a..8357678399 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -1,17 +1,17 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hb8ca3eb2682b1b51E) - --> $DIR/issue-60925.rs:22:9 +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE) + --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hb8ca3eb2682b1b51) - --> $DIR/issue-60925.rs:22:9 +error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h6244e5288326926a) + --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo) - --> $DIR/issue-60925.rs:22:9 + --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs index 47c9230c0e..3238eb1e57 100644 --- a/src/test/ui/symbol-names/issue-60925.rs +++ b/src/test/ui/symbol-names/issue-60925.rs @@ -1,5 +1,4 @@ // build-fail -// ignore-tidy-linelength // revisions: legacy v0 //[legacy]compile-flags: -Z symbol-mangling-version=legacy //[v0]compile-flags: -Z symbol-mangling-version=v0 diff --git a/src/test/ui/symbol-names/issue-60925.stderr b/src/test/ui/symbol-names/issue-60925.stderr deleted file mode 100644 index ae753f0ceb..0000000000 --- a/src/test/ui/symbol-names/issue-60925.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: symbol-name(_ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo17h059a991a004536adE) - --> $DIR/issue-60925.rs:16:9 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo::h059a991a004536ad) - --> $DIR/issue-60925.rs:16:9 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo) - --> $DIR/issue-60925.rs:16:9 - | -LL | #[rustc_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/symbol-names/issue-60925.v0.stderr b/src/test/ui/symbol-names/issue-60925.v0.stderr index aed60a58af..6a5885e1ea 100644 --- a/src/test/ui/symbol-names/issue-60925.v0.stderr +++ b/src/test/ui/symbol-names/issue-60925.v0.stderr @@ -1,17 +1,17 @@ error: symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) - --> $DIR/issue-60925.rs:22:9 + --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo) - --> $DIR/issue-60925.rs:22:9 + --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo) - --> $DIR/issue-60925.rs:22:9 + --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/issue-75326.legacy.stderr b/src/test/ui/symbol-names/issue-75326.legacy.stderr index 2ad16bdb81..aadc0cf43a 100644 --- a/src/test/ui/symbol-names/issue-75326.legacy.stderr +++ b/src/test/ui/symbol-names/issue-75326.legacy.stderr @@ -1,17 +1,17 @@ error: symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next17SYMBOL_HASH) - --> $DIR/issue-75326.rs:42:5 + --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next::SYMBOL_HASH) - --> $DIR/issue-75326.rs:42:5 + --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next) - --> $DIR/issue-75326.rs:42:5 + --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/issue-75326.rs b/src/test/ui/symbol-names/issue-75326.rs index faf36715b1..4d061cafef 100644 --- a/src/test/ui/symbol-names/issue-75326.rs +++ b/src/test/ui/symbol-names/issue-75326.rs @@ -1,5 +1,4 @@ // build-fail -// ignore-tidy-linelength // revisions: legacy v0 //[legacy]compile-flags: -Z symbol-mangling-version=legacy //[v0]compile-flags: -Z symbol-mangling-version=v0 diff --git a/src/test/ui/symbol-names/issue-75326.v0.stderr b/src/test/ui/symbol-names/issue-75326.v0.stderr index 1f57952acd..98844aafb6 100644 --- a/src/test/ui/symbol-names/issue-75326.v0.stderr +++ b/src/test/ui/symbol-names/issue-75326.v0.stderr @@ -1,17 +1,17 @@ error: symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_) - --> $DIR/issue-75326.rs:42:5 + --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next) - --> $DIR/issue-75326.rs:42:5 + --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(<issue_75326::Foo<_, _> as issue_75326::Iterator2>::next) - --> $DIR/issue-75326.rs:42:5 + --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/test-attrs/test-main-not-dead-attr.rs b/src/test/ui/test-attrs/test-main-not-dead-attr.rs index 628b1896ac..0b2a9a3541 100644 --- a/src/test/ui/test-attrs/test-main-not-dead-attr.rs +++ b/src/test/ui/test-attrs/test-main-not-dead-attr.rs @@ -1,9 +1,9 @@ // run-pass // compile-flags: --test -#![feature(main)] +#![feature(rustc_attrs)] #![deny(dead_code)] -#[main] +#[rustc_main] fn foo() { panic!(); } diff --git a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs index bf5482056d..346aa868eb 100644 --- a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs +++ b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs @@ -1,14 +1,14 @@ // run-pass // compile-flags: --test -#![feature(main)] +#![feature(rustc_attrs)] #![allow(dead_code)] mod a { fn b() { (|| { - #[main] + #[rustc_main] fn c() { panic!(); } })(); } diff --git a/src/test/ui/trait-impl-bound-suggestions.fixed b/src/test/ui/trait-impl-bound-suggestions.fixed index db3a95f5c4..744e7bef04 100644 --- a/src/test/ui/trait-impl-bound-suggestions.fixed +++ b/src/test/ui/trait-impl-bound-suggestions.fixed @@ -10,7 +10,7 @@ struct ConstrainedStruct<X: Copy> { } #[allow(dead_code)] -trait InsufficientlyConstrainedGeneric<X=()> where X: Copy { +trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy { fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> { //~^ ERROR the trait bound `X: Copy` is not satisfied ConstrainedStruct { x } diff --git a/src/test/ui/trait-impl-bound-suggestions.stderr b/src/test/ui/trait-impl-bound-suggestions.stderr index 3a21e9c6b2..110ca79908 100644 --- a/src/test/ui/trait-impl-bound-suggestions.stderr +++ b/src/test/ui/trait-impl-bound-suggestions.stderr @@ -9,8 +9,8 @@ LL | fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> { | help: consider further restricting type parameter `X` | -LL | trait InsufficientlyConstrainedGeneric<X=()> where X: Copy { - | ^^^^^^^^^^^^^ +LL | trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/alias/issue-83613.rs b/src/test/ui/traits/alias/issue-83613.rs new file mode 100644 index 0000000000..146920ac68 --- /dev/null +++ b/src/test/ui/traits/alias/issue-83613.rs @@ -0,0 +1,13 @@ +#![feature(min_type_alias_impl_trait)] +trait OpaqueTrait {} +impl<T> OpaqueTrait for T {} +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { + || 0 +} +trait AnotherTrait {} +impl<T: Send> AnotherTrait for T {} +impl AnotherTrait for OpaqueType {} +//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait` +//~| ERROR cannot implement trait on type alias impl trait +fn main() {} diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr new file mode 100644 index 0000000000..0ab39ae667 --- /dev/null +++ b/src/test/ui/traits/alias/issue-83613.stderr @@ -0,0 +1,23 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait` + --> $DIR/issue-83613.rs:10:1 + | +LL | impl<T: Send> AnotherTrait for T {} + | -------------------------------- first implementation here +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait` + +error: cannot implement trait on type alias impl trait + --> $DIR/issue-83613.rs:10:1 + | +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type alias impl trait defined here + --> $DIR/issue-83613.rs:4:19 + | +LL | type OpaqueType = impl OpaqueTrait; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed new file mode 100644 index 0000000000..8a94abaeb0 --- /dev/null +++ b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +trait Strings = Iterator<Item=String>; + +struct Struct<S: Strings>(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs new file mode 100644 index 0000000000..40c678c281 --- /dev/null +++ b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +type Strings = Iterator<Item=String>; + +struct Struct<S: Strings>(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr new file mode 100644 index 0000000000..6e03eeada4 --- /dev/null +++ b/src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found type alias `Strings` + --> $DIR/suggest-trait-alias-instead-of-type.rs:10:18 + | +LL | struct Struct<S: Strings>(S); + | ^^^^^^^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait Strings = Iterator<Item=String>; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/traits/associated_type_bound/issue-51446.rs b/src/test/ui/traits/associated_type_bound/issue-51446.rs new file mode 100644 index 0000000000..7dd95de73b --- /dev/null +++ b/src/test/ui/traits/associated_type_bound/issue-51446.rs @@ -0,0 +1,34 @@ +// Regression test for #51446. +// check-pass + +trait Foo { + type Item; + fn get(&self) -> Self::Item; +} + +fn blah<T, F>(x: T, f: F) -> B<T::Item, impl Fn(T::Item)> +where + T: Foo, + F: Fn(T::Item), +{ + B { x: x.get(), f } +} + +pub struct B<T, F> +where + F: Fn(T), +{ + pub x: T, + pub f: F, +} + +impl Foo for i32 { + type Item = i32; + fn get(&self) -> i32 { + *self + } +} + +fn main() { + let _ = blah(0, |_| ()); +} diff --git a/src/test/ui/bad/bad-method-typaram-kind.rs b/src/test/ui/traits/bad-method-typaram-kind.rs similarity index 100% rename from src/test/ui/bad/bad-method-typaram-kind.rs rename to src/test/ui/traits/bad-method-typaram-kind.rs diff --git a/src/test/ui/bad/bad-method-typaram-kind.stderr b/src/test/ui/traits/bad-method-typaram-kind.stderr similarity index 79% rename from src/test/ui/bad/bad-method-typaram-kind.stderr rename to src/test/ui/traits/bad-method-typaram-kind.stderr index 5b68d97a9e..fd3999ae6f 100644 --- a/src/test/ui/bad/bad-method-typaram-kind.stderr +++ b/src/test/ui/traits/bad-method-typaram-kind.stderr @@ -6,8 +6,8 @@ LL | 1.bar::<T>(); | help: consider further restricting this bound | -LL | fn foo<T:'static + Send>() { - | ^^^^^^ +LL | fn foo<T:'static + std::marker::Send>() { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/bad/bad-sized.rs b/src/test/ui/traits/bad-sized.rs similarity index 100% rename from src/test/ui/bad/bad-sized.rs rename to src/test/ui/traits/bad-sized.rs diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/traits/bad-sized.stderr similarity index 100% rename from src/test/ui/bad/bad-sized.stderr rename to src/test/ui/traits/bad-sized.stderr diff --git a/src/test/ui/traits/bound/not-on-bare-trait.stderr b/src/test/ui/traits/bound/not-on-bare-trait.stderr index e7fc0fa5ec..b8ae88ace0 100644 --- a/src/test/ui/traits/bound/not-on-bare-trait.stderr +++ b/src/test/ui/traits/bound/not-on-bare-trait.stderr @@ -16,8 +16,8 @@ LL | fn foo(_x: Foo + Send) { = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn foo(&_x: Foo + Send) { - | ^ +LL | fn foo(_x: &Foo + Send) { + | ^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index b2702d977f..40386f7061 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -10,9 +10,21 @@ LL | SourceDatabase::parse(db); = note: required because it appears within the type `*const SalsaStorage` = note: required because it appears within the type `Unique<SalsaStorage>` = note: required because it appears within the type `Box<SalsaStorage>` - = note: required because it appears within the type `Runtime<RootDatabase>` - = note: required because it appears within the type `RootDatabase` - = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase` +note: required because it appears within the type `Runtime<RootDatabase>` + --> $DIR/cycle-cache-err-60010.rs:23:8 + | +LL | struct Runtime<DB: Database> { + | ^^^^^^^ +note: required because it appears within the type `RootDatabase` + --> $DIR/cycle-cache-err-60010.rs:20:8 + | +LL | struct RootDatabase { + | ^^^^^^^^^^^^ +note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase` + --> $DIR/cycle-cache-err-60010.rs:43:9 + | +LL | impl<T> SourceDatabase for T + | ^^^^^^^^^^^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/traits/inductive-overflow/lifetime.rs b/src/test/ui/traits/inductive-overflow/lifetime.rs index 205d50a2ed..e23dfa57cd 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.rs +++ b/src/test/ui/traits/inductive-overflow/lifetime.rs @@ -16,7 +16,7 @@ struct C<'a>(&'a ()); struct X<T: Y>(T::P); impl<T: NotAuto> NotAuto for Box<T> {} -impl<T: Y> NotAuto for X<T> where T::P: NotAuto {} +impl<T: Y> NotAuto for X<T> where T::P: NotAuto {} //~ NOTE: required impl<'a> NotAuto for C<'a> {} fn is_send<S: NotAuto>() {} @@ -26,5 +26,4 @@ fn main() { // Should only be a few notes. is_send::<X<C<'static>>>(); //~^ ERROR overflow evaluating - //~| NOTE: required } diff --git a/src/test/ui/traits/inductive-overflow/lifetime.stderr b/src/test/ui/traits/inductive-overflow/lifetime.stderr index 659f9e26e3..752154b35c 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.stderr +++ b/src/test/ui/traits/inductive-overflow/lifetime.stderr @@ -7,7 +7,11 @@ LL | fn is_send<S: NotAuto>() {} LL | is_send::<X<C<'static>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>` +note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>` + --> $DIR/lifetime.rs:19:12 + | +LL | impl<T: Y> NotAuto for X<T> where T::P: NotAuto {} + | ^^^^^^^ ^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/inductive-overflow/simultaneous.stderr b/src/test/ui/traits/inductive-overflow/simultaneous.stderr index 88e0631eeb..94a255fcb8 100644 --- a/src/test/ui/traits/inductive-overflow/simultaneous.stderr +++ b/src/test/ui/traits/inductive-overflow/simultaneous.stderr @@ -7,7 +7,11 @@ LL | fn is_ee<T: Combo>(t: T) { LL | is_ee(4); | ^^^^^ | - = note: required because of the requirements on the impl of `Combo` for `{integer}` +note: required because of the requirements on the impl of `Combo` for `{integer}` + --> $DIR/simultaneous.rs:11:34 + | +LL | impl<T: Tweedledee + Tweedledum> Combo for T {} + | ^^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/traits/inductive-overflow/supertrait.stderr b/src/test/ui/traits/inductive-overflow/supertrait.stderr index dfb967601e..5ed1c2cc2d 100644 --- a/src/test/ui/traits/inductive-overflow/supertrait.stderr +++ b/src/test/ui/traits/inductive-overflow/supertrait.stderr @@ -7,7 +7,11 @@ LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } LL | let (a, b) = copy(NoClone); | ^^^^ | - = note: required because of the requirements on the impl of `Magic` for `NoClone` +note: required because of the requirements on the impl of `Magic` for `NoClone` + --> $DIR/supertrait.rs:5:16 + | +LL | impl<T: Magic> Magic for T {} + | ^^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/traits/inductive-overflow/two-traits.stderr b/src/test/ui/traits/inductive-overflow/two-traits.stderr index d3f2931f25..508a12d859 100644 --- a/src/test/ui/traits/inductive-overflow/two-traits.stderr +++ b/src/test/ui/traits/inductive-overflow/two-traits.stderr @@ -9,8 +9,8 @@ LL | type X = Self; | help: consider further restricting this bound | -LL | impl<T: Magic + Sync> Magic for T { - | ^^^^^^ +LL | impl<T: Magic + std::marker::Sync> Magic for T { + | ^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `*mut (): Magic` --> $DIR/two-traits.rs:20:5 diff --git a/src/test/ui/traits/issue-33140-hack-boundaries.stderr b/src/test/ui/traits/issue-33140-hack-boundaries.stderr index ae65701ecb..c87f1ff1f3 100644 --- a/src/test/ui/traits/issue-33140-hack-boundaries.stderr +++ b/src/test/ui/traits/issue-33140-hack-boundaries.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)`: +error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)` --> $DIR/issue-33140-hack-boundaries.rs:18:1 | LL | impl Trait1 for dyn Send {} @@ -14,7 +14,7 @@ LL | impl Trait2 for dyn Send {} LL | impl !Trait2 for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)`: +error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)` --> $DIR/issue-33140-hack-boundaries.rs:32:1 | LL | impl Trait3<dyn Sync> for dyn Send {} @@ -22,7 +22,7 @@ LL | impl Trait3<dyn Sync> for dyn Send {} LL | impl Trait3<dyn Sync> for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` -error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)`: +error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)` --> $DIR/issue-33140-hack-boundaries.rs:39:1 | LL | impl<T: ?Sized> Trait4a for T {} @@ -30,7 +30,7 @@ LL | impl<T: ?Sized> Trait4a for T {} LL | impl Trait4a for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` -error[E0119]: conflicting implementations of trait `Trait4b` for type `()`: +error[E0119]: conflicting implementations of trait `Trait4b` for type `()` --> $DIR/issue-33140-hack-boundaries.rs:46:1 | LL | impl Trait4b for () {} @@ -38,7 +38,7 @@ LL | impl Trait4b for () {} LL | impl Trait4b for () {} | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` -error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)`: +error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)` --> $DIR/issue-33140-hack-boundaries.rs:53:1 | LL | impl Trait4c for dyn Trait1 + Send {} @@ -46,7 +46,7 @@ LL | impl Trait4c for dyn Trait1 + Send {} LL | impl Trait4c for dyn Trait1 + Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + std::marker::Send + 'static)` -error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send`: +error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send` --> $DIR/issue-33140-hack-boundaries.rs:60:1 | LL | impl<'a> Trait4d for dyn Send + 'a {} @@ -54,7 +54,7 @@ LL | impl<'a> Trait4d for dyn Send + 'a {} LL | impl<'a> Trait4d for dyn Send + 'a {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn std::marker::Send` -error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)`: +error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)` --> $DIR/issue-33140-hack-boundaries.rs:67:1 | LL | impl Trait5 for dyn Send {} diff --git a/src/test/ui/traits/issue-33140.stderr b/src/test/ui/traits/issue-33140.stderr index 9a900d2fc9..392c56a282 100644 --- a/src/test/ui/traits/issue-33140.stderr +++ b/src/test/ui/traits/issue-33140.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: +error[E0119]: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)` --> $DIR/issue-33140.rs:9:1 | LL | impl Trait for dyn Send + Sync { @@ -7,7 +7,7 @@ LL | impl Trait for dyn Send + Sync { LL | impl Trait for dyn Sync + Send { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` -error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: +error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)` --> $DIR/issue-33140.rs:22:1 | LL | impl Trait2 for dyn Send + Sync { diff --git a/src/test/ui/issues/issue-78372.rs b/src/test/ui/traits/issue-78372.rs similarity index 100% rename from src/test/ui/issues/issue-78372.rs rename to src/test/ui/traits/issue-78372.rs diff --git a/src/test/ui/issues/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr similarity index 100% rename from src/test/ui/issues/issue-78372.stderr rename to src/test/ui/traits/issue-78372.stderr diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index 68d527dc78..30daf8e277 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -20,6 +20,9 @@ error[E0599]: no method named `b` found for struct `S` in the current scope LL | struct S; | --------- method `b` not found for this ... +LL | fn b(&self) { } + | - the method is available for `S` here +... LL | S.b(); | ^ method not found in `S` | diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr index d39daaba20..01e36a4a62 100644 --- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr +++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr @@ -6,14 +6,6 @@ LL | struct Qux; ... LL | Qux.clone(); | ^^^^^ method not found in `Qux` - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Qux>` here - | the method is available for `Rc<Qux>` here | = help: items from traits can only be used if the trait is implemented and in scope = note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr index 83b1b83d19..4f7d1be793 100644 --- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -69,7 +69,11 @@ LL | is_send(Box::new(Outer2(TestType))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely | = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType` - = note: required because it appears within the type `Outer2<dummy3::TestType>` +note: required because it appears within the type `Outer2<dummy3::TestType>` + --> $DIR/negated-auto-traits-error.rs:12:8 + | +LL | struct Outer2<T>(T); + | ^^^^^^ = note: required because of the requirements on the impl of `Send` for `Unique<Outer2<dummy3::TestType>>` = note: required because it appears within the type `Box<Outer2<dummy3::TestType>>` @@ -86,7 +90,11 @@ LL | is_sync(Outer2(TestType)); | help: consider borrowing here: `&Outer2(TestType)` | = note: the trait bound `main::TestType: Sync` is not satisfied - = note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>` +note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>` + --> $DIR/negated-auto-traits-error.rs:14:22 + | +LL | unsafe impl<T: Send> Sync for Outer2<T> {} + | ^^^^ ^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr index 7cce45d2c8..b970ad7620 100644 --- a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr +++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `LocalTrait` for type `std::string::String`: +error[E0119]: conflicting implementations of trait `LocalTrait` for type `std::string::String` --> $DIR/rely-on-negative-impl-in-coherence.rs:19:1 | LL | impl<T: ForeignTrait> LocalTrait for T { } diff --git a/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr index 94a0c287f4..910c5e29da 100644 --- a/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr +++ b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::marker::Send` for type `MyStruct`: +error[E0119]: conflicting implementations of trait `std::marker::Send` for type `MyStruct` --> $DIR/overlap-not-permitted-for-builtin-trait.rs:7:1 | LL | impl !Send for MyStruct {} diff --git a/src/test/ui/traits/reservation-impl/coherence-conflict.stderr b/src/test/ui/traits/reservation-impl/coherence-conflict.stderr index 1a227a85c0..a811d7e320 100644 --- a/src/test/ui/traits/reservation-impl/coherence-conflict.stderr +++ b/src/test/ui/traits/reservation-impl/coherence-conflict.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `OtherTrait` for type `()`: +error[E0119]: conflicting implementations of trait `OtherTrait` for type `()` --> $DIR/coherence-conflict.rs:11:1 | LL | impl OtherTrait for () {} diff --git a/src/test/ui/traits/suggest-where-clause.stderr b/src/test/ui/traits/suggest-where-clause.stderr index 86d589ffa9..0257064808 100644 --- a/src/test/ui/traits/suggest-where-clause.stderr +++ b/src/test/ui/traits/suggest-where-clause.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `U` cannot be known at compilation tim --> $DIR/suggest-where-clause.rs:7:20 | LL | fn check<T: Iterator, U: ?Sized>() { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | // suggest a where-clause, if needed LL | mem::size_of::<U>(); | ^ doesn't have a size known at compile-time @@ -16,7 +16,7 @@ error[E0277]: the size for values of type `U` cannot be known at compilation tim --> $DIR/suggest-where-clause.rs:10:5 | LL | fn check<T: Iterator, U: ?Sized>() { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | mem::size_of::<Misc<U>>(); | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -26,7 +26,11 @@ LL | mem::size_of::<Misc<U>>(); LL | pub const fn size_of<T>() -> usize { | - required by this bound in `std::mem::size_of` | - = note: required because it appears within the type `Misc<U>` +note: required because it appears within the type `Misc<U>` + --> $DIR/suggest-where-clause.rs:3:8 + | +LL | struct Misc<T:?Sized>(T); + | ^^^^ error[E0277]: the trait bound `u64: From<T>` is not satisfied --> $DIR/suggest-where-clause.rs:15:5 diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs index 5772450477..e4abb96b4b 100644 --- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs +++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // Check that creating/matching on an enum variant through an alias with // the wrong braced/unit form is caught as an error. diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr index b0de3ee42e..f80abade0f 100644 --- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr +++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -1,23 +1,23 @@ error[E0533]: expected unit struct, unit variant or constant, found struct variant `Alias::Braced` - --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:5 + --> $DIR/incorrect-variant-form-through-alias-caught.rs:8:5 | LL | Alias::Braced; | ^^^^^^^^^^^^^ error[E0533]: expected unit struct, unit variant or constant, found struct variant `Alias::Braced` - --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9 + --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:9 | LL | let Alias::Braced = panic!(); | ^^^^^^^^^^^^^ error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced` - --> $DIR/incorrect-variant-form-through-alias-caught.rs:14:9 + --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9 | LL | let Alias::Braced(..) = panic!(); | ^^^^^^^^^^^^^^^^^ not a tuple variant or struct error[E0618]: expected function, found enum variant `Alias::Unit` - --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:5 + --> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5 | LL | enum Enum { Braced {}, Unit, Tuple() } | ---- `Alias::Unit` defined here @@ -33,7 +33,7 @@ LL | Alias::Unit; | ^^^^^^^^^^^ error[E0164]: expected tuple struct or tuple variant, found unit variant `Alias::Unit` - --> $DIR/incorrect-variant-form-through-alias-caught.rs:19:9 + --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:9 | LL | let Alias::Unit() = panic!(); | ^^^^^^^^^^^^^ not a tuple variant or struct diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.full_tait.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.full_tait.stderr index 871ef22f3e..cfb1fe9c19 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.full_tait.stderr @@ -15,8 +15,8 @@ LL | type X<T> = impl Clone; | help: consider restricting type parameter `T` | -LL | type X<T: Clone> = impl Clone; - | ^^^^^^^ +LL | type X<T: std::clone::Clone> = impl Clone; + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.min_tait.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.min_tait.stderr index 20656e5e55..735b96d5df 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.min_tait.stderr @@ -6,8 +6,8 @@ LL | type X<T> = impl Clone; | help: consider restricting type parameter `T` | -LL | type X<T: Clone> = impl Clone; - | ^^^^^^^ +LL | type X<T: std::clone::Clone> = impl Clone; + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.full_tait.stderr index 8a0c411c77..aab64e72b7 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.full_tait.stderr @@ -28,8 +28,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, U)` help: consider restricting type parameter `T` | -LL | type Two<T: Debug, U> = impl Debug; - | ^^^^^^^ +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error[E0277]: `U` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use5.rs:11:18 @@ -40,8 +40,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, U)` help: consider restricting type parameter `U` | -LL | type Two<T, U: Debug> = impl Debug; - | ^^^^^^^ +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.min_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.min_tait.stderr index 35115ccb2d..5c8c5b8977 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.min_tait.stderr @@ -19,8 +19,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, U)` help: consider restricting type parameter `T` | -LL | type Two<T: Debug, U> = impl Debug; - | ^^^^^^^ +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error[E0277]: `U` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use5.rs:11:18 @@ -31,8 +31,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, U)` help: consider restricting type parameter `U` | -LL | type Two<T, U: Debug> = impl Debug; - | ^^^^^^^ +LL | type Two<T, U: std::fmt::Debug> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.full_tait.stderr index 8f72c333e8..a69e99bf8b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.full_tait.stderr @@ -28,8 +28,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, T)` help: consider restricting type parameter `T` | -LL | type Two<T: Debug, U> = impl Debug; - | ^^^^^^^ +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.min_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.min_tait.stderr index 922c9a7420..a377ef2d87 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.min_tait.stderr @@ -19,8 +19,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, T)` help: consider restricting type parameter `T` | -LL | type Two<T: Debug, U> = impl Debug; - | ^^^^^^^ +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.full_tait.stderr index a93321d4d0..e73ac88500 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.full_tait.stderr @@ -28,8 +28,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, u32)` help: consider restricting type parameter `T` | -LL | type Two<T: Debug, U> = impl Debug; - | ^^^^^^^ +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.min_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.min_tait.stderr index 25ac60799f..d7edce7a49 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.min_tait.stderr @@ -19,8 +19,8 @@ LL | type Two<T, U> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(T, u32)` help: consider restricting type parameter `T` | -LL | type Two<T: Debug, U> = impl Debug; - | ^^^^^^^ +LL | type Two<T: std::fmt::Debug, U> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.full_tait.stderr index 098be7929d..0b3d72d67b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.full_tait.stderr @@ -40,8 +40,8 @@ LL | type Two<A, B> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)` help: consider restricting type parameter `A` | -LL | type Two<A: Debug, B> = impl Debug; - | ^^^^^^^ +LL | type Two<A: std::fmt::Debug, B> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error[E0277]: `B` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use9.rs:10:18 @@ -52,8 +52,8 @@ LL | type Two<A, B> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)` help: consider restricting type parameter `B` | -LL | type Two<A, B: Debug> = impl Debug; - | ^^^^^^^ +LL | type Two<A, B: std::fmt::Debug> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.min_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.min_tait.stderr index b59e10c1b0..fd1081d7b7 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.min_tait.stderr @@ -31,8 +31,8 @@ LL | type Two<A, B> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)` help: consider restricting type parameter `A` | -LL | type Two<A: Debug, B> = impl Debug; - | ^^^^^^^ +LL | type Two<A: std::fmt::Debug, B> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error[E0277]: `B` doesn't implement `Debug` --> $DIR/generic_duplicate_param_use9.rs:10:18 @@ -43,8 +43,8 @@ LL | type Two<A, B> = impl Debug; = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)` help: consider restricting type parameter `B` | -LL | type Two<A, B: Debug> = impl Debug; - | ^^^^^^^ +LL | type Two<A, B: std::fmt::Debug> = impl Debug; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.full_tait.stderr index ca263ba4f5..7ab73d2427 100644 --- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.full_tait.stderr @@ -30,8 +30,8 @@ LL | fn underconstrained<U>(_: U) -> Underconstrained<U> { | help: consider restricting type parameter `U` | -LL | fn underconstrained<U: Debug>(_: U) -> Underconstrained<U> { - | ^^^^^^^ +LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `V` doesn't implement `Debug` --> $DIR/generic_underconstrained2.rs:21:43 @@ -44,8 +44,8 @@ LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> { | help: consider restricting type parameter `V` | -LL | fn underconstrained2<U, V: Debug>(_: U, _: V) -> Underconstrained2<V> { - | ^^^^^^^ +LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> { + | ^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.min_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.min_tait.stderr index 6ce32f457e..a4f5f4b864 100644 --- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.min_tait.stderr @@ -21,8 +21,8 @@ LL | fn underconstrained<U>(_: U) -> Underconstrained<U> { | help: consider restricting type parameter `U` | -LL | fn underconstrained<U: Debug>(_: U) -> Underconstrained<U> { - | ^^^^^^^ +LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `V` doesn't implement `Debug` --> $DIR/generic_underconstrained2.rs:21:43 @@ -35,8 +35,8 @@ LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> { | help: consider restricting type parameter `V` | -LL | fn underconstrained2<U, V: Debug>(_: U, _: V) -> Underconstrained2<V> { - | ^^^^^^^ +LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> { + | ^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.full_tait.stderr b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.full_tait.stderr index 30521b8bf7..6d1a59aafe 100644 --- a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.full_tait.stderr @@ -7,7 +7,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[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_`: +error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_` --> $DIR/incoherent-assoc-imp-trait.rs:13:1 | LL | impl<F> FnOnce<()> for &F { diff --git a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.min_tait.stderr b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.min_tait.stderr index a0427624ec..5c02b602d5 100644 --- a/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.min_tait.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_`: +error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_` --> $DIR/incoherent-assoc-imp-trait.rs:13:1 | LL | impl<F> FnOnce<()> for &F { diff --git a/src/test/ui/type-alias-impl-trait/issue-52843.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-52843.full_tait.stderr index 14f4f62d7a..35ac0993b2 100644 --- a/src/test/ui/type-alias-impl-trait/issue-52843.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-52843.full_tait.stderr @@ -15,8 +15,8 @@ LL | type Foo<T> = impl Default; | help: consider restricting type parameter `T` | -LL | type Foo<T: Default> = impl Default; - | ^^^^^^^^^ +LL | type Foo<T: std::default::Default> = impl Default; + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-52843.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-52843.min_tait.stderr index 6dda27f515..9fb760f34c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-52843.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-52843.min_tait.stderr @@ -6,8 +6,8 @@ LL | type Foo<T> = impl Default; | help: consider restricting type parameter `T` | -LL | type Foo<T: Default> = impl Default; - | ^^^^^^^^^ +LL | type Foo<T: std::default::Default> = impl Default; + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-53598.full_tait.stderr index 8c2d713c16..ee4b7eef0b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53598.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53598.full_tait.stderr @@ -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/issue-53598.rs:5:32 + --> $DIR/issue-53598.rs:4:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ 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: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-53598.rs:24:42 + --> $DIR/issue-53598.rs:23:42 | LL | fn foo<T: Debug>(_: T) -> Self::Item { | __________________________________________^ diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-53598.min_tait.stderr index cb5d6ec804..728721b6db 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53598.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53598.min_tait.stderr @@ -1,5 +1,5 @@ error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-53598.rs:24:42 + --> $DIR/issue-53598.rs:23:42 | LL | fn foo<T: Debug>(_: T) -> Self::Item { | __________________________________________^ diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.rs b/src/test/ui/type-alias-impl-trait/issue-53598.rs index 1388c587db..38067a7222 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53598.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53598.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-compare-mode-chalk // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-57700.full_tait.stderr index f92a5997a9..4336532cdb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57700.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57700.full_tait.stderr @@ -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/issue-57700.rs:6:32 + --> $DIR/issue-57700.rs:5:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ 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: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-57700.rs:20:58 + --> $DIR/issue-57700.rs:19:58 | LL | fn foo(self: impl Deref<Target = Self>) -> Self::Bar { | __________________________________________________________^ diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-57700.min_tait.stderr index 1aaa42b99a..47ab31cd79 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57700.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57700.min_tait.stderr @@ -1,5 +1,5 @@ error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-57700.rs:20:58 + --> $DIR/issue-57700.rs:19:58 | LL | fn foo(self: impl Deref<Target = Self>) -> Self::Bar { | __________________________________________________________^ diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.rs b/src/test/ui/type-alias-impl-trait/issue-57700.rs index c7a123ad24..476a188cde 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57700.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57700.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // ignore-compare-mode-chalk #![feature(arbitrary_self_types)] // revisions: min_tait full_tait diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr index f544f61df9..53a0016c08 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr @@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28 --> $DIR/issue-63279.rs:8:16 | LL | type Closure = impl FnOnce(); - | ^^^^^^^^^^^^^ expected opaque type, found `()` + | ^^^^^^^^^^^^^ expected `()`, found opaque type | - = note: expected opaque type `impl FnOnce<()>` - found unit type `()` + = note: expected unit type `()` + found opaque type `impl FnOnce<()>` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr index bdf414d0ba..be386ab90e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr @@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28 --> $DIR/issue-63279.rs:8:16 | LL | type Closure = impl FnOnce(); - | ^^^^^^^^^^^^^ expected opaque type, found `()` + | ^^^^^^^^^^^^^ expected `()`, found opaque type | - = note: expected opaque type `impl FnOnce<()>` - found unit type `()` + = note: expected unit type `()` + found opaque type `impl FnOnce<()>` error: aborting due to 2 previous errors diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index d8c7f595e6..ddfa31cf62 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -56,8 +56,8 @@ LL | trait Base<T = String>: Super<T> { } | help: consider further restricting type parameter `T` | -LL | trait Base<T = String>: Super<T> where T: Copy { } - | ^^^^^^^^^^^^^ +LL | trait Base<T = String>: Super<T> where T: std::marker::Copy { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add `u8` to `i32` --> $DIR/type-check-defaults.rs:24:66 diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/typeck/issue-65611.rs similarity index 97% rename from src/test/ui/issues/issue-65611.rs rename to src/test/ui/typeck/issue-65611.rs index b74ee1b0c6..7645311496 100644 --- a/src/test/ui/issues/issue-65611.rs +++ b/src/test/ui/typeck/issue-65611.rs @@ -17,7 +17,7 @@ pub unsafe trait Array { pub trait Index : PartialEq + Copy { fn to_usize(self) -> usize; - fn from(usize) -> Self; + fn from(i: usize) -> Self; } impl Index for usize { diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/typeck/issue-65611.stderr similarity index 100% rename from src/test/ui/issues/issue-65611.stderr rename to src/test/ui/typeck/issue-65611.stderr diff --git a/src/test/ui/typeck/issue-75883.rs b/src/test/ui/typeck/issue-75883.rs new file mode 100644 index 0000000000..3a59ca049b --- /dev/null +++ b/src/test/ui/typeck/issue-75883.rs @@ -0,0 +1,22 @@ +// Regression test for #75883. + +pub struct UI {} + +impl UI { + pub fn run() -> Result<_> { + //~^ ERROR: this enum takes 2 type arguments but only 1 type argument was supplied + //~| ERROR: the type placeholder `_` is not allowed within types on item signatures + let mut ui = UI {}; + ui.interact(); + + unimplemented!(); + } + + pub fn interact(&mut self) -> Result<_> { + //~^ ERROR: this enum takes 2 type arguments but only 1 type argument was supplied + //~| ERROR: the type placeholder `_` is not allowed within types on item signatures + unimplemented!(); + } +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-75883.stderr b/src/test/ui/typeck/issue-75883.stderr new file mode 100644 index 0000000000..a6b2eb8f97 --- /dev/null +++ b/src/test/ui/typeck/issue-75883.stderr @@ -0,0 +1,52 @@ +error[E0107]: this enum takes 2 type arguments but only 1 type argument was supplied + --> $DIR/issue-75883.rs:6:21 + | +LL | pub fn run() -> Result<_> { + | ^^^^^^ - supplied 1 type argument + | | + | expected 2 type arguments + | +note: enum defined here, with 2 type parameters: `T`, `E` + --> $SRC_DIR/core/src/result.rs:LL:COL + | +LL | pub enum Result<T, E> { + | ^^^^^^ - - +help: add missing type argument + | +LL | pub fn run() -> Result<_, E> { + | ^^^ + +error[E0107]: this enum takes 2 type arguments but only 1 type argument was supplied + --> $DIR/issue-75883.rs:15:35 + | +LL | pub fn interact(&mut self) -> Result<_> { + | ^^^^^^ - supplied 1 type argument + | | + | expected 2 type arguments + | +note: enum defined here, with 2 type parameters: `T`, `E` + --> $SRC_DIR/core/src/result.rs:LL:COL + | +LL | pub enum Result<T, E> { + | ^^^^^^ - - +help: add missing type argument + | +LL | pub fn interact(&mut self) -> Result<_, E> { + | ^^^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $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 + --> $DIR/issue-75883.rs:6:28 + | +LL | pub fn run() -> Result<_> { + | ^ not allowed in type signatures + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0121. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/typeck/issue-80779.rs b/src/test/ui/typeck/issue-80779.rs new file mode 100644 index 0000000000..6791976196 --- /dev/null +++ b/src/test/ui/typeck/issue-80779.rs @@ -0,0 +1,13 @@ +// Regression test for #80779. + +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 + g(val) +} + +pub fn g(_: T<'static>) -> _ {} +//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures + +fn main() {} diff --git a/src/test/ui/typeck/issue-80779.stderr b/src/test/ui/typeck/issue-80779.stderr new file mode 100644 index 0000000000..aca494520f --- /dev/null +++ b/src/test/ui/typeck/issue-80779.stderr @@ -0,0 +1,21 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-80779.rs:10:28 + | +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 + --> $DIR/issue-80779.rs:5:29 + | +LL | pub fn f<'a>(val: T<'a>) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.rs b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.rs new file mode 100644 index 0000000000..16ec2a5464 --- /dev/null +++ b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.rs @@ -0,0 +1,7 @@ +// Regression test for #83621. + +extern "C" { + static x: _; //~ ERROR: [E0121] +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr new file mode 100644 index 0000000000..b1bec4c082 --- /dev/null +++ b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr @@ -0,0 +1,9 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-83621-placeholder-static-in-extern.rs:4:15 + | +LL | static x: _; + | ^ 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/typeck/issue-84831.rs b/src/test/ui/typeck/issue-84831.rs new file mode 100644 index 0000000000..c646f71072 --- /dev/null +++ b/src/test/ui/typeck/issue-84831.rs @@ -0,0 +1,9 @@ +fn f() { + std::<0>; //~ ERROR expected value +} +fn j() { + std::<_ as _>; //~ ERROR expected value + //~^ ERROR expected one of `,` or `>`, found keyword `as` +} + +fn main () {} diff --git a/src/test/ui/typeck/issue-84831.stderr b/src/test/ui/typeck/issue-84831.stderr new file mode 100644 index 0000000000..e3cce10a00 --- /dev/null +++ b/src/test/ui/typeck/issue-84831.stderr @@ -0,0 +1,26 @@ +error: expected one of `,` or `>`, found keyword `as` + --> $DIR/issue-84831.rs:5:13 + | +LL | std::<_ as _>; + | ^^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | std::<{ _ as _ }>; + | ^ ^ + +error[E0423]: expected value, found crate `std` + --> $DIR/issue-84831.rs:2:5 + | +LL | std::<0>; + | ^^^^^^^^ not a value + +error[E0423]: expected value, found crate `std` + --> $DIR/issue-84831.rs:5:5 + | +LL | std::<_ as _>; + | ^^^^^^^^^^^^^ not a value + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr index 1f21e12597..a9b49ee326 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -19,7 +19,11 @@ LL | is_sync::<MyTypeWUnsafe>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<u8>` cannot be shared between threads safely | = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell<u8>` - = note: required because it appears within the type `MyTypeWUnsafe` +note: required because it appears within the type `MyTypeWUnsafe` + --> $DIR/typeck-default-trait-impl-negation-sync.rs:21:8 + | +LL | struct MyTypeWUnsafe { + | ^^^^^^^^^^^^^ error[E0277]: `Managed` cannot be shared between threads safely --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:5 @@ -31,7 +35,11 @@ LL | is_sync::<MyTypeManaged>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely | = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed` - = note: required because it appears within the type `MyTypeManaged` +note: required because it appears within the type `MyTypeManaged` + --> $DIR/typeck-default-trait-impl-negation-sync.rs:25:8 + | +LL | struct MyTypeManaged { + | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr index 4fb423b9a2..7398b48a23 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -9,8 +9,8 @@ LL | fn is_send<T:Send>() { | help: consider restricting type parameter `T` | -LL | fn foo<T: Send>() { - | ^^^^^^ +LL | fn foo<T: std::marker::Send>() { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr index 2a6ae736d7..91585e78d4 100644 --- a/src/test/ui/typeck/typeck-unsafe-always-share.stderr +++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr @@ -30,7 +30,11 @@ LL | test(ms); | ^^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely | = help: within `MySync<NoSync>`, the trait `Sync` is not implemented for `UnsafeCell<NoSync>` - = note: required because it appears within the type `MySync<NoSync>` +note: required because it appears within the type `MySync<NoSync>` + --> $DIR/typeck-unsafe-always-share.rs:8:8 + | +LL | struct MySync<T> { + | ^^^^^^ error[E0277]: `NoSync` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:30:10 diff --git a/src/test/ui/typeof/type_mismatch.rs b/src/test/ui/typeof/type_mismatch.rs new file mode 100644 index 0000000000..3f8339fa5b --- /dev/null +++ b/src/test/ui/typeof/type_mismatch.rs @@ -0,0 +1,9 @@ +// Test that using typeof results in the correct type mismatch errors instead of always assuming +// `usize`, in addition to the pre-existing "typeof is reserved and unimplemented" error +fn main() { + const a: u8 = 1; + let b: typeof(a) = 1i8; + //~^ ERROR `typeof` is a reserved keyword but unimplemented + //~| ERROR mismatched types + //~| expected `u8`, found `i8` +} diff --git a/src/test/ui/typeof/type_mismatch.stderr b/src/test/ui/typeof/type_mismatch.stderr new file mode 100644 index 0000000000..12fd7c9963 --- /dev/null +++ b/src/test/ui/typeof/type_mismatch.stderr @@ -0,0 +1,23 @@ +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/type_mismatch.rs:5:12 + | +LL | let b: typeof(a) = 1i8; + | ^^^^^^^^^ reserved keyword + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:24 + | +LL | let b: typeof(a) = 1i8; + | --------- ^^^ expected `u8`, found `i8` + | | + | expected due to this + | +help: change the type of the numeric literal from `i8` to `u8` + | +LL | let b: typeof(a) = 1u8; + | ^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0516. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/union/union-deref.rs b/src/test/ui/union/union-deref.rs index df598eea9e..48f5b36bd1 100644 --- a/src/test/ui/union/union-deref.rs +++ b/src/test/ui/union/union-deref.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength //! 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 index f7722764cd..6af050bc4b 100644 --- a/src/test/ui/union/union-deref.stderr +++ b/src/test/ui/union/union-deref.stderr @@ -1,5 +1,5 @@ error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:15:14 + --> $DIR/union-deref.rs:14:14 | LL | unsafe { u.f.0 = Vec::new() }; | ^^^ @@ -8,7 +8,7 @@ LL | unsafe { u.f.0 = Vec::new() }; = 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:17:19 + --> $DIR/union-deref.rs:16:19 | LL | unsafe { &mut u.f.0 }; | ^^^ @@ -17,7 +17,7 @@ LL | unsafe { &mut u.f.0 }; = 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:14 + --> $DIR/union-deref.rs:18:14 | LL | unsafe { u.f.0.push(0) }; | ^^^ @@ -26,7 +26,7 @@ LL | unsafe { u.f.0.push(0) }; = 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:23:14 + --> $DIR/union-deref.rs:22:14 | LL | unsafe { u.f.0.0 = Vec::new() }; | ^^^^^ @@ -35,7 +35,7 @@ LL | unsafe { u.f.0.0 = Vec::new() }; = 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:19 + --> $DIR/union-deref.rs:24:19 | LL | unsafe { &mut u.f.0.0 }; | ^^^^^ @@ -44,7 +44,7 @@ LL | unsafe { &mut u.f.0.0 }; = 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:14 + --> $DIR/union-deref.rs:26:14 | LL | unsafe { u.f.0.0.push(0) }; | ^^^^^ diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index a793bf58d2..546394664d 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -25,14 +25,6 @@ LL | struct CloneNoCopy; ... LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<U5<CloneNoCopy>>` here - | the method is available for `Rc<U5<CloneNoCopy>>` here | = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` diff --git a/src/test/ui/union/union-derive.stderr b/src/test/ui/union/union-derive.stderr index 919c6d5ced..6ef72c901a 100644 --- a/src/test/ui/union/union-derive.stderr +++ b/src/test/ui/union/union-derive.stderr @@ -1,20 +1,14 @@ error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:9:5 - | -LL | Debug, - | ^^^^^ - -error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:8:5 + --> $DIR/union-derive.rs:4:5 | -LL | Default, - | ^^^^^^^ +LL | PartialEq, + | ^^^^^^^^^ error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:7:5 + --> $DIR/union-derive.rs:5:5 | -LL | Hash, - | ^^^^ +LL | PartialOrd, + | ^^^^^^^^^^ error: this trait cannot be derived for unions --> $DIR/union-derive.rs:6:5 @@ -23,16 +17,22 @@ LL | Ord, | ^^^ error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:5:5 + --> $DIR/union-derive.rs:7:5 | -LL | PartialOrd, - | ^^^^^^^^^^ +LL | Hash, + | ^^^^ error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:4:5 + --> $DIR/union-derive.rs:8:5 | -LL | PartialEq, - | ^^^^^^^^^ +LL | Default, + | ^^^^^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:9:5 + | +LL | Debug, + | ^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr index cebeeb59a7..b916bbe8ad 100644 --- a/src/test/ui/union/union-sized-field.stderr +++ b/src/test/ui/union/union-sized-field.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/union-sized-field.rs:4:12 | LL | union Foo<T: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | value: T, | ^ doesn't have a size known at compile-time | @@ -21,7 +21,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/union-sized-field.rs:9:12 | LL | struct Foo2<T: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | value: T, | ^ doesn't have a size known at compile-time | @@ -40,7 +40,7 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim --> $DIR/union-sized-field.rs:15:11 | LL | enum Foo3<T: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | Value(T), | ^ doesn't have a size known at compile-time | diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 4bbacfc0a8..6a355dd256 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -10,14 +10,6 @@ LL | trait Foo { LL | let _z = y.clone(); | ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Box<dyn Foo>>` here - | the method is available for `Rc<Box<dyn Foo>>` here - | ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | LL | / pub struct Box< diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index dd0b7fc548..a4421bcf80 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -7,14 +7,6 @@ LL | struct R { LL | let _j = i.clone(); | ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Box<R>>` here - | the method is available for `Rc<Box<R>>` here - | ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | LL | / pub struct Box< diff --git a/src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs b/src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs new file mode 100644 index 0000000000..b0d738855d --- /dev/null +++ b/src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs @@ -0,0 +1,25 @@ +// check-pass + +// This is issue #85435. But the real story is reflected in issue #85561, where +// a bug in the implementation of feature(capture_disjoint_fields) () was +// exposed to non-feature-gated code by a diagnostic changing PR that removed +// the gating in one case. + +// This test is double-checking that the case of interest continues to work as +// expected in the *absence* of that feature gate. At the time of this writing, +// enabling the feature gate will cause this test to fail. We obviously cannot +// stabilize that feature until it can correctly handle this test. + +fn main() { + let val: u8 = 5; + let u8_ptr: *const u8 = &val; + let _closure = || { + unsafe { + let tmp = *u8_ptr; + tmp + + // Just dereferencing and returning directly compiles fine: + // *u8_ptr + } + }; +} diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs deleted file mode 100644 index 540612a7dc..0000000000 --- a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs +++ /dev/null @@ -1,67 +0,0 @@ -#![feature(unsafe_block_in_unsafe_fn)] - -#[repr(packed)] -pub struct Packed { - data: &'static u32, -} - -const PACKED: Packed = Packed { data: &0 }; - -#[allow(safe_packed_borrows)] -#[allow(unsafe_op_in_unsafe_fn)] -unsafe fn allow_allow() { - &PACKED.data; // allowed -} - -#[allow(safe_packed_borrows)] -#[warn(unsafe_op_in_unsafe_fn)] -unsafe fn allow_warn() { - &PACKED.data; // allowed -} - -#[allow(safe_packed_borrows)] -#[deny(unsafe_op_in_unsafe_fn)] -unsafe fn allow_deny() { - &PACKED.data; // allowed -} - -#[warn(safe_packed_borrows)] -#[allow(unsafe_op_in_unsafe_fn)] -unsafe fn warn_allow() { - &PACKED.data; // allowed -} - -#[warn(safe_packed_borrows)] -#[warn(unsafe_op_in_unsafe_fn)] -unsafe fn warn_warn() { - &PACKED.data; //~ WARN - //~| WARNING this was previously accepted by the compiler but is being phased out -} - -#[warn(safe_packed_borrows)] -#[deny(unsafe_op_in_unsafe_fn)] -unsafe fn warn_deny() { - &PACKED.data; //~ WARN - //~| WARNING this was previously accepted by the compiler but is being phased out -} - -#[deny(safe_packed_borrows)] -#[allow(unsafe_op_in_unsafe_fn)] -unsafe fn deny_allow() { - &PACKED.data; // allowed -} - -#[deny(safe_packed_borrows)] -#[warn(unsafe_op_in_unsafe_fn)] -unsafe fn deny_warn() { - &PACKED.data; //~ WARN -} - -#[deny(safe_packed_borrows)] -#[deny(unsafe_op_in_unsafe_fn)] -unsafe fn deny_deny() { - &PACKED.data; //~ ERROR - //~| WARNING this was previously accepted by the compiler but is being phased out -} - -fn main() {} diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr deleted file mode 100644 index fda1515964..0000000000 --- a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr +++ /dev/null @@ -1,60 +0,0 @@ -warning: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:37:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:34:8 - | -LL | #[warn(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ - = 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 - -warning: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:44:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:41:8 - | -LL | #[warn(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ - = 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 - -warning: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:57:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:55:8 - | -LL | #[warn(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - -error: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:63:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:60:8 - | -LL | #[deny(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ - = 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 - -error: aborting due to previous error; 3 warnings emitted - diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr index 1b1a584a01..4523d41b60 100644 --- a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr @@ -14,7 +14,11 @@ LL | A as fn(str) -> A<str>; | ^ doesn't have a size known at compile-time | = help: within `A<str>`, the trait `Sized` is not implemented for `str` - = note: required because it appears within the type `A<str>` +note: required because it appears within the type `A<str>` + --> $DIR/issue-50940-with-feature.rs:5:12 + | +LL | struct A<X: ?Sized>(X); + | ^ = note: the return type of a function must have a statically known size error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr index 9fb401aec2..a7f57e3fd1 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs.stderr @@ -15,7 +15,11 @@ LL | udrop::<A<[u8]>>(A { 0: *foo() }); | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` - = note: required because it appears within the type `A<[u8]>` +note: required because it appears within the type `A<[u8]>` + --> $DIR/unsized-exprs.rs:3:8 + | +LL | struct A<X: ?Sized>(X); + | ^ = note: structs must have a statically known size to be initialized error[E0277]: the size for values of type `[u8]` cannot be known at compilation time @@ -25,7 +29,11 @@ LL | udrop::<A<[u8]>>(A(*foo())); | ^ doesn't have a size known at compile-time | = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` - = note: required because it appears within the type `A<[u8]>` +note: required because it appears within the type `A<[u8]>` + --> $DIR/unsized-exprs.rs:3:8 + | +LL | struct A<X: ?Sized>(X); + | ^ = note: the return type of a function must have a statically known size error: aborting due to 3 previous errors diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.rs b/src/test/ui/unsized/return-unsized-from-trait-method.rs index 2d265d5db5..ebe6edd101 100644 --- a/src/test/ui/unsized/return-unsized-from-trait-method.rs +++ b/src/test/ui/unsized/return-unsized-from-trait-method.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // regression test for #26376 trait Foo { diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.stderr b/src/test/ui/unsized/return-unsized-from-trait-method.stderr index 7ecdd28616..4dd7cf5e02 100644 --- a/src/test/ui/unsized/return-unsized-from-trait-method.stderr +++ b/src/test/ui/unsized/return-unsized-from-trait-method.stderr @@ -1,5 +1,5 @@ error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined - --> $DIR/return-unsized-from-trait-method.rs:11:17 + --> $DIR/return-unsized-from-trait-method.rs:9:17 | LL | let _ = f.foo(); | ^^^^^^^ diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr index b2ff3159c9..19978ae24c 100644 --- a/src/test/ui/unsized/unsized-bare-typaram.stderr +++ b/src/test/ui/unsized/unsized-bare-typaram.stderr @@ -6,7 +6,7 @@ LL | fn bar<T: Sized>() { } LL | fn foo<T: ?Sized>() { bar::<T>() } | - ^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr index 3057d4789b..601db7d1cd 100644 --- a/src/test/ui/unsized/unsized-enum.stderr +++ b/src/test/ui/unsized/unsized-enum.stderr @@ -7,7 +7,7 @@ LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory. LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() } | - ^^^^^^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box<U>` --> $DIR/unsized-enum.rs:4:10 diff --git a/src/test/ui/unsized/unsized-enum2.stderr b/src/test/ui/unsized/unsized-enum2.stderr index 0a0896638e..1b6c858581 100644 --- a/src/test/ui/unsized/unsized-enum2.stderr +++ b/src/test/ui/unsized/unsized-enum2.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `W` cannot be known at compilation tim --> $DIR/unsized-enum2.rs:23:8 | LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | // parameter LL | VA(W), | ^ doesn't have a size known at compile-time @@ -22,7 +22,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized-enum2.rs:25:11 | LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | VB{x: X}, | ^ doesn't have a size known at compile-time @@ -42,7 +42,7 @@ error[E0277]: the size for values of type `Y` cannot be known at compilation tim --> $DIR/unsized-enum2.rs:27:15 | LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | VC(isize, Y), | ^ doesn't have a size known at compile-time @@ -62,7 +62,7 @@ error[E0277]: the size for values of type `Z` cannot be known at compilation tim --> $DIR/unsized-enum2.rs:29:21 | LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | VD{u: isize, x: Z}, | ^ doesn't have a size known at compile-time @@ -301,7 +301,11 @@ LL | VI(Path1), | ^^^^^ doesn't have a size known at compile-time | = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)` - = note: required because it appears within the type `Path1` +note: required because it appears within the type `Path1` + --> $DIR/unsized-enum2.rs:16:8 + | +LL | struct Path1(dyn PathHelper1); + | ^^^^^ = note: no field of an enum variant 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 @@ -320,7 +324,11 @@ LL | VJ{x: Path2}, | ^^^^^ doesn't have a size known at compile-time | = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)` - = note: required because it appears within the type `Path2` +note: required because it appears within the type `Path2` + --> $DIR/unsized-enum2.rs:17:8 + | +LL | struct Path2(dyn PathHelper2); + | ^^^^^ = note: no field of an enum variant 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 @@ -339,7 +347,11 @@ LL | VK(isize, Path3), | ^^^^^ doesn't have a size known at compile-time | = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)` - = note: required because it appears within the type `Path3` +note: required because it appears within the type `Path3` + --> $DIR/unsized-enum2.rs:18:8 + | +LL | struct Path3(dyn PathHelper3); + | ^^^^^ = note: no field of an enum variant 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 @@ -358,7 +370,11 @@ LL | VL{u: isize, x: Path4}, | ^^^^^ doesn't have a size known at compile-time | = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)` - = note: required because it appears within the type `Path4` +note: required because it appears within the type `Path4` + --> $DIR/unsized-enum2.rs:19:8 + | +LL | struct Path4(dyn PathHelper4); + | ^^^^^ = note: no field of an enum variant 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 diff --git a/src/test/ui/unsized/unsized-fn-arg.fixed b/src/test/ui/unsized/unsized-fn-arg.fixed new file mode 100644 index 0000000000..2c686c6c2b --- /dev/null +++ b/src/test/ui/unsized/unsized-fn-arg.fixed @@ -0,0 +1,6 @@ +// run-rustfix +#![crate_type="lib"] +#![allow(unused)] + +fn f<T: ?Sized>(t: &T) {} +//~^ ERROR the size for values of type `T` cannot be known at compilation time diff --git a/src/test/ui/unsized/unsized-fn-arg.rs b/src/test/ui/unsized/unsized-fn-arg.rs new file mode 100644 index 0000000000..9fc08bd6d3 --- /dev/null +++ b/src/test/ui/unsized/unsized-fn-arg.rs @@ -0,0 +1,6 @@ +// run-rustfix +#![crate_type="lib"] +#![allow(unused)] + +fn f<T: ?Sized>(t: T) {} +//~^ ERROR the size for values of type `T` cannot be known at compilation time diff --git a/src/test/ui/unsized/unsized-fn-arg.stderr b/src/test/ui/unsized/unsized-fn-arg.stderr new file mode 100644 index 0000000000..6b802ddf54 --- /dev/null +++ b/src/test/ui/unsized/unsized-fn-arg.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/unsized-fn-arg.rs:5:17 + | +LL | fn f<T: ?Sized>(t: T) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn f<T: ?Sized>(t: &T) {} + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr index 9d8a1c6773..9d072eda4e 100644 --- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -7,7 +7,7 @@ LL | LL | impl<X: ?Sized> S5<X> { | - ^^^^^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box<Y>` --> $DIR/unsized-inherent-impl-self-type.rs:5:11 diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr index 6661cf358b..e38375bff4 100644 --- a/src/test/ui/unsized/unsized-struct.stderr +++ b/src/test/ui/unsized/unsized-struct.stderr @@ -7,7 +7,7 @@ LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory. LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() } | - ^^^^^^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` --> $DIR/unsized-struct.rs:4:12 @@ -26,9 +26,13 @@ LL | fn is_sized<T:Sized>() { } LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() } | - ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | - = note: required because it appears within the type `Bar<T>` +note: required because it appears within the type `Bar<T>` + --> $DIR/unsized-struct.rs:11:8 + | +LL | struct Bar<T: ?Sized> { data: T } + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr index d1b590d813..aef0d0cbb8 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -7,7 +7,7 @@ LL | LL | impl<X: ?Sized> T3<X> for S5<X> { | - ^^^^^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box<Y>` --> $DIR/unsized-trait-impl-self-type.rs:8:11 diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr index 17fe16ed4f..f48d4ef9f1 100644 --- a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -7,7 +7,7 @@ LL | trait T2<Z> { LL | impl<X: ?Sized> T2<X> for S4<X> { | - ^^^^^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | help: consider relaxing the implicit `Sized` restriction | diff --git a/src/test/ui/unsized-tuple-impls.rs b/src/test/ui/unsized/unsized-tuple-impls.rs similarity index 100% rename from src/test/ui/unsized-tuple-impls.rs rename to src/test/ui/unsized/unsized-tuple-impls.rs diff --git a/src/test/ui/unsized.rs b/src/test/ui/unsized/unsized.rs similarity index 100% rename from src/test/ui/unsized.rs rename to src/test/ui/unsized/unsized.rs diff --git a/src/test/ui/unsized2.rs b/src/test/ui/unsized/unsized2.rs similarity index 100% rename from src/test/ui/unsized2.rs rename to src/test/ui/unsized/unsized2.rs diff --git a/src/test/ui/unsized3-rpass.rs b/src/test/ui/unsized/unsized3-rpass.rs similarity index 100% rename from src/test/ui/unsized3-rpass.rs rename to src/test/ui/unsized/unsized3-rpass.rs diff --git a/src/test/ui/unsized3.rs b/src/test/ui/unsized/unsized3.rs similarity index 100% rename from src/test/ui/unsized3.rs rename to src/test/ui/unsized/unsized3.rs diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized/unsized3.stderr similarity index 74% rename from src/test/ui/unsized3.stderr rename to src/test/ui/unsized/unsized3.stderr index 7ed43c38f1..bd36008aca 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized/unsized3.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized3.rs:7:13 | LL | fn f1<X: ?Sized>(x: &X) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f2::<X>(x); | ^ doesn't have a size known at compile-time ... @@ -18,7 +18,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized3.rs:18:13 | LL | fn f3<X: ?Sized + T>(x: &X) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f4::<X>(x); | ^ doesn't have a size known at compile-time ... @@ -37,11 +37,15 @@ LL | fn f5<Y>(x: &Y) {} | - required by this bound in `f5` ... LL | fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f5(x1); | ^^ doesn't have a size known at compile-time | - = note: required because it appears within the type `S<X>` +note: required because it appears within the type `S<X>` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S<X: ?Sized> { + | ^ help: consider relaxing the implicit `Sized` restriction | LL | fn f5<Y: ?Sized>(x: &Y) {} @@ -51,22 +55,30 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized3.rs:40:8 | LL | fn f9<X: ?Sized>(x1: Box<S<X>>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f5(&(*x1, 34)); | ^^^^^^^^^^ doesn't have a size known at compile-time | - = note: required because it appears within the type `S<X>` +note: required because it appears within the type `S<X>` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S<X: ?Sized> { + | ^ = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:45:9 | LL | fn f10<X: ?Sized>(x1: Box<S<X>>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f5(&(32, *x1)); | ^^^^^^^^^ doesn't have a size known at compile-time | - = note: required because it appears within the type `S<X>` +note: required because it appears within the type `S<X>` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S<X: ?Sized> { + | ^ = note: required because it appears within the type `({integer}, S<X>)` = note: tuples must have a statically known size to be initialized @@ -77,11 +89,15 @@ LL | fn f5<Y>(x: &Y) {} | - required by this bound in `f5` ... LL | fn f10<X: ?Sized>(x1: Box<S<X>>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f5(&(32, *x1)); | ^^^^^^^^^^ doesn't have a size known at compile-time | - = note: required because it appears within the type `S<X>` +note: required because it appears within the type `S<X>` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S<X: ?Sized> { + | ^ = note: required because it appears within the type `({integer}, S<X>)` help: consider relaxing the implicit `Sized` restriction | diff --git a/src/test/ui/unsized5.rs b/src/test/ui/unsized/unsized5.rs similarity index 100% rename from src/test/ui/unsized5.rs rename to src/test/ui/unsized/unsized5.rs diff --git a/src/test/ui/unsized5.stderr b/src/test/ui/unsized/unsized5.stderr similarity index 93% rename from src/test/ui/unsized5.stderr rename to src/test/ui/unsized/unsized5.stderr index a7539b0672..0bfd456552 100644 --- a/src/test/ui/unsized5.stderr +++ b/src/test/ui/unsized/unsized5.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized5.rs:4:9 | LL | struct S1<X: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f1: X, | ^ doesn't have a size known at compile-time | @@ -21,7 +21,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized5.rs:10:8 | LL | struct S2<X: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | f: isize, LL | g: X, | ^ doesn't have a size known at compile-time @@ -77,7 +77,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized5.rs:25:8 | LL | enum E<X: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | V1(X, isize), | ^ doesn't have a size known at compile-time | @@ -96,7 +96,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized5.rs:29:12 | LL | enum F<X: ?Sized> { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | V2{f1: X, f: isize}, | ^ doesn't have a size known at compile-time | diff --git a/src/test/ui/unsized6.rs b/src/test/ui/unsized/unsized6.rs similarity index 100% rename from src/test/ui/unsized6.rs rename to src/test/ui/unsized/unsized6.rs diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized/unsized6.stderr similarity index 85% rename from src/test/ui/unsized6.stderr rename to src/test/ui/unsized/unsized6.stderr index 71dac236fa..8e5734dffb 100644 --- a/src/test/ui/unsized6.stderr +++ b/src/test/ui/unsized/unsized6.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `Y` cannot be known at compilation tim --> $DIR/unsized6.rs:9:9 | LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | let y: Y; | ^ doesn't have a size known at compile-time @@ -14,7 +14,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:7:12 | LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | let _: W; // <-- this is OK, no bindings created, no initializer. LL | let _: (isize, (X, isize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -25,7 +25,7 @@ error[E0277]: the size for values of type `Z` cannot be known at compilation tim --> $DIR/unsized6.rs:11:12 | LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | let y: (isize, (Z, usize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -36,7 +36,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:15:9 | LL | fn f2<X: ?Sized, Y: ?Sized>(x: &X) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | let y: X; | ^ doesn't have a size known at compile-time | @@ -47,7 +47,7 @@ error[E0277]: the size for values of type `Y` cannot be known at compilation tim --> $DIR/unsized6.rs:17:12 | LL | fn f2<X: ?Sized, Y: ?Sized>(x: &X) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | let y: (isize, (Y, isize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -58,7 +58,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:22:9 | LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | @@ -69,7 +69,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:24:9 | LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | let y = *x2; | ^ doesn't have a size known at compile-time @@ -81,7 +81,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:26:10 | LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | let (y, z) = (*x3, 4); | ^ doesn't have a size known at compile-time @@ -93,7 +93,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:30:9 | LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | @@ -104,7 +104,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:32:9 | LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | let y = *x2; | ^ doesn't have a size known at compile-time @@ -116,7 +116,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:34:10 | LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { - | - this type parameter needs to be `Sized` + | - this type parameter needs to be `std::marker::Sized` ... LL | let (y, z) = (*x3, 4); | ^ doesn't have a size known at compile-time @@ -130,13 +130,13 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn g1<X: ?Sized>(x: X) {} | - ^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn g1<X: ?Sized>(&x: X) {} - | ^ +LL | fn g1<X: ?Sized>(x: &X) {} + | ^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:40:22 @@ -144,13 +144,13 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn g2<X: ?Sized + T>(x: X) {} | - ^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn g2<X: ?Sized + T>(&x: X) {} - | ^ +LL | fn g2<X: ?Sized + T>(x: &X) {} + | ^ error: aborting due to 13 previous errors diff --git a/src/test/ui/unsized7.rs b/src/test/ui/unsized/unsized7.rs similarity index 100% rename from src/test/ui/unsized7.rs rename to src/test/ui/unsized/unsized7.rs diff --git a/src/test/ui/unsized7.stderr b/src/test/ui/unsized/unsized7.stderr similarity index 89% rename from src/test/ui/unsized7.stderr rename to src/test/ui/unsized/unsized7.stderr index 5f9a2604ed..7dbddd4ed2 100644 --- a/src/test/ui/unsized7.stderr +++ b/src/test/ui/unsized/unsized7.stderr @@ -7,7 +7,7 @@ LL | trait T1<Z: T> { LL | impl<X: ?Sized + T> T1<X> for S3<X> { | - ^^^^^ doesn't have a size known at compile-time | | - | this type parameter needs to be `Sized` + | this type parameter needs to be `std::marker::Sized` | help: consider relaxing the implicit `Sized` restriction | diff --git a/src/test/ui/unused/unused-doc-comments-for-macros.rs b/src/test/ui/unused/unused-doc-comments-for-macros.rs new file mode 100644 index 0000000000..05828ebb2c --- /dev/null +++ b/src/test/ui/unused/unused-doc-comments-for-macros.rs @@ -0,0 +1,17 @@ +#![deny(unused_doc_comments)] +#![feature(rustc_attrs)] + +macro_rules! foo { () => {}; } + +fn main() { + /// line1 //~ ERROR: unused doc comment + /// line2 + /// line3 + foo!(); + + // Ensure we still detect another doc-comment block. + /// line1 //~ ERROR: unused doc comment + /// line2 + /// line3 + foo!(); +} diff --git a/src/test/ui/unused/unused-doc-comments-for-macros.stderr b/src/test/ui/unused/unused-doc-comments-for-macros.stderr new file mode 100644 index 0000000000..f4f5bb71e5 --- /dev/null +++ b/src/test/ui/unused/unused-doc-comments-for-macros.stderr @@ -0,0 +1,31 @@ +error: unused doc comment + --> $DIR/unused-doc-comments-for-macros.rs:7:5 + | +LL | / /// line1 +LL | | /// line2 +LL | | /// line3 + | |_____--------^ + | | + | rustdoc does not generate documentation for macro invocations + | +note: the lint level is defined here + --> $DIR/unused-doc-comments-for-macros.rs:1:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +error: unused doc comment + --> $DIR/unused-doc-comments-for-macros.rs:13:5 + | +LL | / /// line1 +LL | | /// line2 +LL | | /// line3 + | |_____--------^ + | | + | rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/useless-comment.rs b/src/test/ui/unused/useless-comment.rs similarity index 100% rename from src/test/ui/useless-comment.rs rename to src/test/ui/unused/useless-comment.rs diff --git a/src/test/ui/useless-comment.stderr b/src/test/ui/unused/useless-comment.stderr similarity index 100% rename from src/test/ui/useless-comment.stderr rename to src/test/ui/unused/useless-comment.stderr diff --git a/src/test/ui/unwind-no-uwtable.rs b/src/test/ui/unwind-no-uwtable.rs new file mode 100644 index 0000000000..f249d3f457 --- /dev/null +++ b/src/test/ui/unwind-no-uwtable.rs @@ -0,0 +1,34 @@ +// run-pass +// ignore-windows target requires uwtable +// ignore-wasm32-bare no proper panic=unwind support +// compile-flags: -C panic=unwind -C force-unwind-tables=n + +use std::panic::{self, AssertUnwindSafe}; + +struct Increase<'a>(&'a mut u8); + +impl Drop for Increase<'_> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +#[inline(never)] +fn unwind() { + panic!(); +} + +#[inline(never)] +fn increase(count: &mut u8) { + let _increase = Increase(count); + unwind(); +} + +fn main() { + let mut count = 0; + assert!(panic::catch_unwind(AssertUnwindSafe( + #[inline(never)] + || increase(&mut count) + )).is_err()); + assert_eq!(count, 1); +} diff --git a/src/test/ui/utf8_idents-rpass.rs b/src/test/ui/utf8_idents-rpass.rs index 582b67bc29..206744a58f 100644 --- a/src/test/ui/utf8_idents-rpass.rs +++ b/src/test/ui/utf8_idents-rpass.rs @@ -2,8 +2,6 @@ // #![allow(non_snake_case)] -#![feature(non_ascii_idents)] - pub fn main() { let ε = 0.00001f64; let Π = 3.14f64; diff --git a/src/test/ui/utf8_idents.rs b/src/test/ui/utf8_idents.rs index 6c54086cc2..1f6326dd94 100644 --- a/src/test/ui/utf8_idents.rs +++ b/src/test/ui/utf8_idents.rs @@ -1,15 +1,16 @@ -#![allow(mixed_script_confusables)] +// check-pass +// +#![allow(mixed_script_confusables, non_camel_case_types)] fn foo< - 'β, //~ ERROR non-ascii idents are not fully supported - γ //~ ERROR non-ascii idents are not fully supported - //~^ WARN type parameter `γ` should have an upper camel case name + 'β, + γ >() {} struct X { - δ: usize //~ ERROR non-ascii idents are not fully supported + δ: usize } pub fn main() { - let α = 0.00001f64; //~ ERROR non-ascii idents are not fully supported + let α = 0.00001f64; } diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr deleted file mode 100644 index 2fc0b1c39e..0000000000 --- a/src/test/ui/utf8_idents.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error[E0658]: non-ascii idents are not fully supported - --> $DIR/utf8_idents.rs:4:5 - | -LL | 'β, - | ^^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/utf8_idents.rs:5:5 - | -LL | γ - | ^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/utf8_idents.rs:10:5 - | -LL | δ: usize - | ^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -error[E0658]: non-ascii idents are not fully supported - --> $DIR/utf8_idents.rs:14:9 - | -LL | let α = 0.00001f64; - | ^ - | - = note: see issue #55467 <https://github.com/rust-lang/rust/issues/55467> for more information - = help: add `#![feature(non_ascii_idents)]` to the crate attributes to enable - -warning: type parameter `γ` should have an upper camel case name - --> $DIR/utf8_idents.rs:5:5 - | -LL | γ - | ^ help: convert the identifier to upper camel case: `Γ` - | - = note: `#[warn(non_camel_case_types)]` on by default - -error: aborting due to 4 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/wf/wf-enum-bound.stderr b/src/test/ui/wf/wf-enum-bound.stderr index e7bc858225..7819110dd9 100644 --- a/src/test/ui/wf/wf-enum-bound.stderr +++ b/src/test/ui/wf/wf-enum-bound.stderr @@ -9,8 +9,8 @@ LL | where T: ExtraCopy<U> | help: consider further restricting type parameter `U` | -LL | where T: ExtraCopy<U>, U: Copy - | ^^^^^^^^^ +LL | where T: ExtraCopy<U>, U: std::marker::Copy + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr index c97ce53885..4bfb2413fe 100644 --- a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr @@ -9,8 +9,8 @@ LL | f: IsCopy<A> | help: consider restricting type parameter `A` | -LL | enum AnotherEnum<A: Copy> { - | ^^^^^^ +LL | enum AnotherEnum<A: std::marker::Copy> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields.stderr b/src/test/ui/wf/wf-enum-fields.stderr index 85da1bf583..c8a75afbab 100644 --- a/src/test/ui/wf/wf-enum-fields.stderr +++ b/src/test/ui/wf/wf-enum-fields.stderr @@ -9,8 +9,8 @@ LL | SomeVariant(IsCopy<A>) | help: consider restricting type parameter `A` | -LL | enum SomeEnum<A: Copy> { - | ^^^^^^ +LL | enum SomeEnum<A: std::marker::Copy> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr index 22598e58bd..e463e3db88 100644 --- a/src/test/ui/wf/wf-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-fn-where-clause.stderr @@ -9,8 +9,8 @@ LL | fn foo<T,U>() where T: ExtraCopy<U> | help: consider further restricting type parameter `U` | -LL | fn foo<T,U>() where T: ExtraCopy<U>, U: Copy - | ^^^^^^^^^ +LL | fn foo<T,U>() where T: ExtraCopy<U>, U: std::marker::Copy + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time --> $DIR/wf-fn-where-clause.rs:12:16 diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr index d6010d1d79..9687658feb 100644 --- a/src/test/ui/wf/wf-in-fn-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-arg.stderr @@ -9,8 +9,8 @@ LL | fn bar<T>(_: &MustBeCopy<T>) | help: consider restricting type parameter `T` | -LL | fn bar<T: Copy>(_: &MustBeCopy<T>) - | ^^^^^^ +LL | fn bar<T: std::marker::Copy>(_: &MustBeCopy<T>) + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-ret.stderr b/src/test/ui/wf/wf-in-fn-ret.stderr index c22252657f..f9a962578e 100644 --- a/src/test/ui/wf/wf-in-fn-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-ret.stderr @@ -9,8 +9,8 @@ LL | fn bar<T>() -> MustBeCopy<T> | help: consider restricting type parameter `T` | -LL | fn bar<T: Copy>() -> MustBeCopy<T> - | ^^^^^^ +LL | fn bar<T: std::marker::Copy>() -> MustBeCopy<T> + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-arg.stderr b/src/test/ui/wf/wf-in-fn-type-arg.stderr index 6d249f5f91..33300b3964 100644 --- a/src/test/ui/wf/wf-in-fn-type-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr @@ -9,8 +9,8 @@ LL | x: fn(MustBeCopy<T>) | help: consider restricting type parameter `T` | -LL | struct Bar<T: Copy> { - | ^^^^^^ +LL | struct Bar<T: std::marker::Copy> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-ret.stderr b/src/test/ui/wf/wf-in-fn-type-ret.stderr index 30ff365b11..1ffc47e6d8 100644 --- a/src/test/ui/wf/wf-in-fn-type-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr @@ -9,8 +9,8 @@ LL | x: fn() -> MustBeCopy<T> | help: consider restricting type parameter `T` | -LL | struct Foo<T: Copy> { - | ^^^^^^ +LL | struct Foo<T: std::marker::Copy> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-where-clause.stderr b/src/test/ui/wf/wf-in-fn-where-clause.stderr index 64e9694c0e..7cb9af11d7 100644 --- a/src/test/ui/wf/wf-in-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-in-fn-where-clause.stderr @@ -9,8 +9,8 @@ LL | where T: MustBeCopy<U> | help: consider further restricting type parameter `U` | -LL | where T: MustBeCopy<U>, U: Copy - | ^^^^^^^^^ +LL | where T: MustBeCopy<U>, U: std::marker::Copy + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-obj-type-trait.stderr b/src/test/ui/wf/wf-in-obj-type-trait.stderr index 55ea08ccbe..8606eabf59 100644 --- a/src/test/ui/wf/wf-in-obj-type-trait.stderr +++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr @@ -9,8 +9,8 @@ LL | x: dyn Object<MustBeCopy<T>> | help: consider restricting type parameter `T` | -LL | struct Bar<T: Copy> { - | ^^^^^^ +LL | struct Bar<T: std::marker::Copy> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr index 7bbdd4bcf2..8e0ce557e6 100644 --- a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -9,8 +9,8 @@ LL | fn foo(self) where T: ExtraCopy<U> | help: consider restricting type parameter `U` | -LL | impl<T,U: Copy> Foo<T,U> { - | ^^^^^^ +LL | impl<T,U: std::marker::Copy> Foo<T,U> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr index 2a44e1cdc7..bf8077ba88 100644 --- a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr @@ -9,8 +9,8 @@ LL | impl<T,U> Foo<T,U> where T: ExtraCopy<U> | help: consider further restricting type parameter `U` | -LL | impl<T,U> Foo<T,U> where T: ExtraCopy<U>, U: Copy - | ^^^^^^^^^ +LL | impl<T,U> Foo<T,U> where T: ExtraCopy<U>, U: std::marker::Copy + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-bound.stderr b/src/test/ui/wf/wf-struct-bound.stderr index 948693ac6f..e85f359143 100644 --- a/src/test/ui/wf/wf-struct-bound.stderr +++ b/src/test/ui/wf/wf-struct-bound.stderr @@ -9,8 +9,8 @@ LL | where T: ExtraCopy<U> | help: consider further restricting type parameter `U` | -LL | where T: ExtraCopy<U>, U: Copy - | ^^^^^^^^^ +LL | where T: ExtraCopy<U>, U: std::marker::Copy + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-field.stderr b/src/test/ui/wf/wf-struct-field.stderr index 04e62a7fcb..62ef6bb60c 100644 --- a/src/test/ui/wf/wf-struct-field.stderr +++ b/src/test/ui/wf/wf-struct-field.stderr @@ -9,8 +9,8 @@ LL | data: IsCopy<A> | help: consider restricting type parameter `A` | -LL | struct SomeStruct<A: Copy> { - | ^^^^^^ +LL | struct SomeStruct<A: std::marker::Copy> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-associated-type-bound.stderr b/src/test/ui/wf/wf-trait-associated-type-bound.stderr index 166e3626f0..51adfdb6bd 100644 --- a/src/test/ui/wf/wf-trait-associated-type-bound.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-bound.stderr @@ -9,8 +9,8 @@ LL | type Type1: ExtraCopy<T>; | help: consider restricting type parameter `T` | -LL | trait SomeTrait<T: Copy> { - | ^^^^^^ +LL | trait SomeTrait<T: std::marker::Copy> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-bound.stderr b/src/test/ui/wf/wf-trait-bound.stderr index abb97adcfd..c9e818f8e7 100644 --- a/src/test/ui/wf/wf-trait-bound.stderr +++ b/src/test/ui/wf/wf-trait-bound.stderr @@ -9,8 +9,8 @@ LL | where T: ExtraCopy<U> | help: consider further restricting type parameter `U` | -LL | where T: ExtraCopy<U>, U: Copy - | ^^^^^^^^^ +LL | where T: ExtraCopy<U>, U: std::marker::Copy + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-superbound.stderr b/src/test/ui/wf/wf-trait-superbound.stderr index db337a7c6d..6926983527 100644 --- a/src/test/ui/wf/wf-trait-superbound.stderr +++ b/src/test/ui/wf/wf-trait-superbound.stderr @@ -9,8 +9,8 @@ LL | trait SomeTrait<T>: ExtraCopy<T> { | help: consider restricting type parameter `T` | -LL | trait SomeTrait<T: Copy>: ExtraCopy<T> { - | ^^^^^^ +LL | trait SomeTrait<T: std::marker::Copy>: ExtraCopy<T> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 916c6dc6d5..356ba347cc 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -9,8 +9,8 @@ LL | require_copy(self.x); | help: consider restricting type parameter `T` | -LL | impl<T: Copy> Foo<T> { - | ^^^^^^ +LL | impl<T: std::marker::Copy> Foo<T> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index 8814018964..d84242cfe1 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -9,8 +9,8 @@ LL | require_copy(self.x); | help: consider restricting type parameter `T` | -LL | impl<T: Copy> Foo<T> for Bar<T> { - | ^^^^^^ +LL | impl<T: std::marker::Copy> Foo<T> for Bar<T> { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wrong-mul-method-signature.stderr b/src/test/ui/wrong-mul-method-signature.stderr index 4c367fb9e9..9f8896f01e 100644 --- a/src/test/ui/wrong-mul-method-signature.stderr +++ b/src/test/ui/wrong-mul-method-signature.stderr @@ -1,26 +1,35 @@ error[E0053]: method `mul` has an incompatible type for trait - --> $DIR/wrong-mul-method-signature.rs:16:5 + --> $DIR/wrong-mul-method-signature.rs:16:21 | LL | fn mul(self, s: &f64) -> Vec1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found `&f64` + | ^^^^ + | | + | expected `f64`, found `&f64` + | help: change the parameter type to match the trait: `f64` | = note: expected fn pointer `fn(Vec1, f64) -> Vec1` found fn pointer `fn(Vec1, &f64) -> Vec1` error[E0053]: method `mul` has an incompatible type for trait - --> $DIR/wrong-mul-method-signature.rs:33:5 + --> $DIR/wrong-mul-method-signature.rs:33:21 | LL | fn mul(self, s: f64) -> Vec2 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found `f64` + | ^^^ + | | + | expected struct `Vec2`, found `f64` + | help: change the parameter type to match the trait: `Vec2` | = note: expected fn pointer `fn(Vec2, Vec2) -> f64` found fn pointer `fn(Vec2, f64) -> Vec2` error[E0053]: method `mul` has an incompatible type for trait - --> $DIR/wrong-mul-method-signature.rs:52:5 + --> $DIR/wrong-mul-method-signature.rs:52:29 | LL | fn mul(self, s: f64) -> f64 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `f64` + | ^^^ + | | + | expected `i32`, found `f64` + | help: change the output type to match the trait: `i32` | = note: expected fn pointer `fn(Vec3, _) -> i32` found fn pointer `fn(Vec3, _) -> f64` diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 0a6bac48eb..fc608eaabc 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -9,6 +9,8 @@ struct Test { sha: &'static str, lock: Option<&'static str>, packages: &'static [&'static str], + features: Option<&'static [&'static str]>, + manifest_path: Option<&'static str>, } const TEST_REPOS: &[Test] = &[ @@ -18,6 +20,8 @@ const TEST_REPOS: &[Test] = &[ sha: "cf056ea5e8052c1feea6141e40ab0306715a2c33", lock: None, packages: &[], + features: None, + manifest_path: None, }, Test { name: "ripgrep", @@ -25,6 +29,8 @@ const TEST_REPOS: &[Test] = &[ sha: "3de31f752729525d85a3d1575ac1978733b3f7e7", lock: None, packages: &[], + features: None, + manifest_path: None, }, Test { name: "tokei", @@ -32,6 +38,8 @@ const TEST_REPOS: &[Test] = &[ sha: "fdf3f8cb279a7aeac0696c87e5d8b0cd946e4f9e", lock: None, packages: &[], + features: None, + manifest_path: None, }, Test { name: "xsv", @@ -39,6 +47,8 @@ const TEST_REPOS: &[Test] = &[ sha: "3de6c04269a7d315f7e9864b9013451cd9580a08", lock: None, packages: &[], + features: None, + manifest_path: None, }, Test { name: "servo", @@ -48,6 +58,23 @@ const TEST_REPOS: &[Test] = &[ // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox. // This takes much less time to build than all of Servo and supports stable Rust. packages: &["selectors"], + features: None, + manifest_path: None, + }, + Test { + name: "diesel", + repo: "https://github.com/diesel-rs/diesel", + sha: "91493fe47175076f330ce5fc518f0196c0476f56", + lock: None, + packages: &[], + // Test the embeded sqlite variant of diesel + // This does not require any dependency to be present, + // sqlite will be compiled as part of the build process + features: Some(&["sqlite", "libsqlite3-sys/bundled"]), + // We are only interested in testing diesel itself + // not any other crate present in the diesel workspace + // (This is required to set the feature flags above) + manifest_path: Some("diesel/Cargo.toml"), }, ]; @@ -68,7 +95,7 @@ fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) { if let Some(lockfile) = test.lock { fs::write(&dir.join("Cargo.lock"), lockfile).unwrap(); } - if !run_cargo_test(cargo, &dir, test.packages) { + if !run_cargo_test(cargo, &dir, test.packages, test.features, test.manifest_path) { panic!("tests failed for {}", test.repo); } } @@ -120,12 +147,31 @@ fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf { out_dir } -fn run_cargo_test(cargo_path: &Path, crate_path: &Path, packages: &[&str]) -> bool { +fn run_cargo_test( + cargo_path: &Path, + crate_path: &Path, + packages: &[&str], + features: Option<&[&str]>, + manifest_path: Option<&str>, +) -> bool { let mut command = Command::new(cargo_path); command.arg("test"); + + if let Some(path) = manifest_path { + command.arg(format!("--manifest-path={}", path)); + } + + if let Some(features) = features { + command.arg("--no-default-features"); + for feature in features { + command.arg(format!("--features={}", feature)); + } + } + for name in packages { command.arg("-p").arg(name); } + let status = command // Disable rust-lang/cargo's cross-compile tests .env("CFG_DISABLE_CROSS_TESTS", "1") diff --git a/src/tools/clippy/.github/PULL_REQUEST_TEMPLATE.md b/src/tools/clippy/.github/PULL_REQUEST_TEMPLATE.md index a3f114e0bb..780ee9d63d 100644 --- a/src/tools/clippy/.github/PULL_REQUEST_TEMPLATE.md +++ b/src/tools/clippy/.github/PULL_REQUEST_TEMPLATE.md @@ -3,7 +3,9 @@ Thank you for making Clippy better! We're collecting our changelog from pull request descriptions. If your PR only includes internal changes, you can just write `changelog: none`. Otherwise, please write a short comment -explaining your change. +explaining your change. Also, it's helpful for us that +the lint name is put into brackets `[]` and backticks `` ` ` ``, +e.g. ``[`lint_name`]``. If your PR fixes an issue, you can add "fixes #issue_number" into this PR description. This way the issue will be automatically closed when @@ -29,4 +31,5 @@ Delete this line and everything above before opening your PR. --- *Please write a short comment explaining your change (or "none" for internal only changes)* + changelog: diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml index 47253eecc4..ae6f1aa1b3 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_bors.yml @@ -34,15 +34,16 @@ jobs: run: | MESSAGE=$(git log --format=%B -n 1) PR=$(echo "$MESSAGE" | grep -o "#[0-9]*" | head -1 | sed -e 's/^#//') - output=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR" | \ - python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \ - grep "^changelog: " | \ - sed "s/changelog: //g") - if [[ -z "$output" ]]; then + body=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR" | \ + python -c "import sys, json; print(json.load(sys.stdin)['body'])") + output=$(grep "^changelog:\s*\S" <<< "$body" | sed "s/changelog:\s*//g") || { echo "ERROR: PR body must contain 'changelog: ...'" exit 1 - elif [[ "$output" = "none" ]]; then + } + if [[ "$output" = "none" ]]; then echo "WARNING: changelog is 'none'" + else + echo "changelog: $output" fi env: PYTHONIOENCODING: 'utf-8' diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 41c334c681..204d56e2a9 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,146 @@ document. ## Unreleased / In Rust Nightly -[3e41797...master](https://github.com/rust-lang/rust-clippy/compare/3e41797...master) +[6ed6f1e...master](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...master) + +## Rust 1.52 + +Current beta, release 2021-05-06 + +[3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e) + +### New Lints + +* [`from_str_radix_10`] + [#6717](https://github.com/rust-lang/rust-clippy/pull/6717) +* [`implicit_clone`] + [#6730](https://github.com/rust-lang/rust-clippy/pull/6730) +* [`semicolon_if_nothing_returned`] + [#6681](https://github.com/rust-lang/rust-clippy/pull/6681) +* [`manual_flatten`] + [#6646](https://github.com/rust-lang/rust-clippy/pull/6646) +* [`inconsistent_struct_constructor`] + [#6769](https://github.com/rust-lang/rust-clippy/pull/6769) +* [`iter_count`] + [#6791](https://github.com/rust-lang/rust-clippy/pull/6791) +* [`default_numeric_fallback`] + [#6662](https://github.com/rust-lang/rust-clippy/pull/6662) +* [`bytes_nth`] + [#6695](https://github.com/rust-lang/rust-clippy/pull/6695) +* [`filter_map_identity`] + [#6685](https://github.com/rust-lang/rust-clippy/pull/6685) +* [`manual_map`] + [#6573](https://github.com/rust-lang/rust-clippy/pull/6573) + +### Moves and Deprecations + +* Moved [`upper_case_acronyms`] to `pedantic` + [#6775](https://github.com/rust-lang/rust-clippy/pull/6775) +* Moved [`manual_map`] to `nursery` + [#6796](https://github.com/rust-lang/rust-clippy/pull/6796) +* Moved [`unnecessary_wraps`] to `pedantic` + [#6765](https://github.com/rust-lang/rust-clippy/pull/6765) +* Moved [`trivial_regex`] to `nursery` + [#6696](https://github.com/rust-lang/rust-clippy/pull/6696) +* Moved [`naive_bytecount`] to `pedantic` + [#6825](https://github.com/rust-lang/rust-clippy/pull/6825) +* Moved [`upper_case_acronyms`] to `style` + [#6788](https://github.com/rust-lang/rust-clippy/pull/6788) +* Moved [`manual_map`] to `style` + [#6801](https://github.com/rust-lang/rust-clippy/pull/6801) + +### Enhancements + +* [`disallowed_method`]: Now supports functions in addition to methods + [#6674](https://github.com/rust-lang/rust-clippy/pull/6674) +* [`upper_case_acronyms`]: Added a new configuration `upper-case-acronyms-aggressive` to + trigger the lint if there is more than one uppercase character next to each other + [#6788](https://github.com/rust-lang/rust-clippy/pull/6788) +* [`collapsible_match`]: Now supports block comparison with different value names + [#6754](https://github.com/rust-lang/rust-clippy/pull/6754) +* [`unnecessary_wraps`]: Will now suggest removing unnecessary wrapped return unit type, like `Option<()>` + [#6665](https://github.com/rust-lang/rust-clippy/pull/6665) +* Improved value usage detection in closures + [#6698](https://github.com/rust-lang/rust-clippy/pull/6698) + +### False Positive Fixes + +* [`use_self`]: No longer lints in macros + [#6833](https://github.com/rust-lang/rust-clippy/pull/6833) +* [`use_self`]: Fixed multiple false positives for: generics, associated types and derive implementations + [#6179](https://github.com/rust-lang/rust-clippy/pull/6179) +* [`missing_inline_in_public_items`]: No longer lints for procedural macros + [#6814](https://github.com/rust-lang/rust-clippy/pull/6814) +* [`inherent_to_string`]: No longer lints on functions with function generics + [#6771](https://github.com/rust-lang/rust-clippy/pull/6771) +* [`doc_markdown`]: Add `OpenDNS` to the default configuration as an allowed identifier + [#6783](https://github.com/rust-lang/rust-clippy/pull/6783) +* [`missing_panics_doc`]: No longer lints on [`unreachable!`](https://doc.rust-lang.org/std/macro.unreachable.html) + [#6700](https://github.com/rust-lang/rust-clippy/pull/6700) +* [`collapsible_if`]: No longer lints on if statements with attributes + [#6701](https://github.com/rust-lang/rust-clippy/pull/6701) +* [`match_same_arms`]: Only considers empty blocks as equal if the tokens contained are the same + [#6843](https://github.com/rust-lang/rust-clippy/pull/6843) +* [`redundant_closure`]: Now ignores macros + [#6871](https://github.com/rust-lang/rust-clippy/pull/6871) +* [`manual_map`]: Fixed false positives when control flow statements like `return`, `break` etc. are used + [#6801](https://github.com/rust-lang/rust-clippy/pull/6801) +* [`vec_init_then_push`]: Fixed false positives for loops and if statements + [#6697](https://github.com/rust-lang/rust-clippy/pull/6697) +* [`len_without_is_empty`]: Will now consider multiple impl blocks and `#[allow]` on + the `len` method as well as the type definition. + [#6853](https://github.com/rust-lang/rust-clippy/pull/6853) +* [`let_underscore_drop`]: Only lints on types which implement `Drop` + [#6682](https://github.com/rust-lang/rust-clippy/pull/6682) +* [`unit_arg`]: No longer lints on unit arguments when they come from a path expression. + [#6601](https://github.com/rust-lang/rust-clippy/pull/6601) +* [`cargo_common_metadata`]: No longer lints if + [`publish = false`](https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field) + is defined in the manifest + [#6650](https://github.com/rust-lang/rust-clippy/pull/6650) + +### Suggestion Fixes/Improvements + +* [`collapsible_match`]: Fixed lint message capitalization + [#6766](https://github.com/rust-lang/rust-clippy/pull/6766) +* [`or_fun_call`]: Improved suggestions for `or_insert(vec![])` + [#6790](https://github.com/rust-lang/rust-clippy/pull/6790) +* [`manual_map`]: No longer expands macros in the suggestions + [#6801](https://github.com/rust-lang/rust-clippy/pull/6801) +* Aligned Clippy's lint messages with the rustc dev guide + [#6787](https://github.com/rust-lang/rust-clippy/pull/6787) + +### ICE Fixes + +* [`zero_sized_map_values`] + [#6866](https://github.com/rust-lang/rust-clippy/pull/6866) + +### Documentation Improvements + +* [`useless_format`]: Improved the documentation example + [#6854](https://github.com/rust-lang/rust-clippy/pull/6854) +* Clippy's [`README.md`]: Includes a new subsection on running Clippy as a rustc wrapper + [#6782](https://github.com/rust-lang/rust-clippy/pull/6782) + +### Others +* Running `cargo clippy` after `cargo check` now works as expected + (`cargo clippy` and `cargo check` no longer shares the same build cache) + [#6687](https://github.com/rust-lang/rust-clippy/pull/6687) +* Cargo now re-runs Clippy if arguments after `--` provided to `cargo clippy` are changed. + [#6834](https://github.com/rust-lang/rust-clippy/pull/6834) +* Extracted Clippy's `utils` module into the new `clippy_utils` crate + [#6756](https://github.com/rust-lang/rust-clippy/pull/6756) +* Clippy lintcheck tool improvements + [#6800](https://github.com/rust-lang/rust-clippy/pull/6800) + [#6735](https://github.com/rust-lang/rust-clippy/pull/6735) + [#6764](https://github.com/rust-lang/rust-clippy/pull/6764) + [#6708](https://github.com/rust-lang/rust-clippy/pull/6708) + [#6780](https://github.com/rust-lang/rust-clippy/pull/6780) + [#6686](https://github.com/rust-lang/rust-clippy/pull/6686) ## Rust 1.51 -Current beta, release 2021-03-25 +Current stable, released 2021-03-25 [4911ab1...3e41797](https://github.com/rust-lang/rust-clippy/compare/4911ab1...3e41797) @@ -44,7 +179,7 @@ Current beta, release 2021-03-25 * Replace [`find_map`] with [`manual_find_map`] [#6591](https://github.com/rust-lang/rust-clippy/pull/6591) -* [`unknown_clippy_lints`] Now integrated in the `unknown_lints` rustc lint +* `unknown_clippy_lints` Now integrated in the `unknown_lints` rustc lint [#6653](https://github.com/rust-lang/rust-clippy/pull/6653) ### Enhancements @@ -125,7 +260,7 @@ Current beta, release 2021-03-25 ## Rust 1.50 -Current stable, released 2021-02-11 +Released 2021-02-11 [b20d4c1...4bd77a1](https://github.com/rust-lang/rust-clippy/compare/b20d4c1...4bd77a1) @@ -145,7 +280,7 @@ Current stable, 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 `panic_fmt` +* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panic` [#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) @@ -284,7 +419,7 @@ Released 2020-12-31 [#6037](https://github.com/rust-lang/rust-clippy/pull/6037) * Rename `zero_width_space` to [`invisible_characters`] [#6105](https://github.com/rust-lang/rust-clippy/pull/6105) -* Deprecate [`drop_bounds`] (uplifted) +* Deprecate `drop_bounds` (uplifted) [#6111](https://github.com/rust-lang/rust-clippy/pull/6111) * Move [`string_lit_as_bytes`] to `nursery` [#6117](https://github.com/rust-lang/rust-clippy/pull/6117) @@ -883,7 +1018,7 @@ Released 2020-03-12 [#5015](https://github.com/rust-lang/rust-clippy/pull/5015) * Move [`range_plus_one`] to pedantic group [#5057](https://github.com/rust-lang/rust-clippy/pull/5057) * Move [`debug_assert_with_mut_call`] to nursery group [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) -* Deprecate [`unused_label`] [#4930](https://github.com/rust-lang/rust-clippy/pull/4930) +* Deprecate `unused_label` [#4930](https://github.com/rust-lang/rust-clippy/pull/4930) ### Enhancements @@ -911,7 +1046,7 @@ Released 2020-03-12 * [`wildcard_enum_match_arm`] [#4934](https://github.com/rust-lang/rust-clippy/pull/4934) * [`cognitive_complexity`] [#4935](https://github.com/rust-lang/rust-clippy/pull/4935) * [`decimal_literal_representation`] [#4956](https://github.com/rust-lang/rust-clippy/pull/4956) -* [`unknown_clippy_lints`] [#4963](https://github.com/rust-lang/rust-clippy/pull/4963) +* `unknown_clippy_lints` [#4963](https://github.com/rust-lang/rust-clippy/pull/4963) * [`explicit_into_iter_loop`] [#4978](https://github.com/rust-lang/rust-clippy/pull/4978) * [`useless_attribute`] [#5022](https://github.com/rust-lang/rust-clippy/pull/5022) * [`if_let_some_result`] [#5032](https://github.com/rust-lang/rust-clippy/pull/5032) @@ -945,7 +1080,7 @@ Released 2020-01-30 [Inside Rust Blog](https://blog.rust-lang.org/inside-rust/2019/11/04/Clippy-removes-plugin-interface.html) for details [#4714](https://github.com/rust-lang/rust-clippy/pull/4714) * Move [`use_self`] to nursery group [#4863](https://github.com/rust-lang/rust-clippy/pull/4863) -* Deprecate [`into_iter_on_array`] [#4788](https://github.com/rust-lang/rust-clippy/pull/4788) +* Deprecate `into_iter_on_array` [#4788](https://github.com/rust-lang/rust-clippy/pull/4788) * Expand [`string_lit_as_bytes`] to also trigger when literal has escapes [#4808](https://github.com/rust-lang/rust-clippy/pull/4808) * Fix false positive in `comparison_chain` [#4842](https://github.com/rust-lang/rust-clippy/pull/4842) @@ -1147,7 +1282,7 @@ Released 2019-05-20 [1fac380..37f5c1e](https://github.com/rust-lang/rust-clippy/compare/1fac380...37f5c1e) -* New lint: [`drop_bounds`] to detect `T: Drop` bounds +* New lint: `drop_bounds` to detect `T: Drop` bounds * Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) * Rename `cyclomatic_complexity` to [`cognitive_complexity`], start work on making lint more practical for Rust code * Move [`get_unwrap`] to the restriction category @@ -1240,7 +1375,7 @@ Released 2019-01-17 * New lints: [`slow_vector_initialization`], [`mem_discriminant_non_enum`], [`redundant_clone`], [`wildcard_dependencies`], - [`into_iter_on_ref`], [`into_iter_on_array`], [`deprecated_cfg_attr`], + [`into_iter_on_ref`], `into_iter_on_array`, [`deprecated_cfg_attr`], [`mem_discriminant_non_enum`], [`cargo_common_metadata`] * Add support for `u128` and `i128` to integer related lints * Add float support to `mistyped_literal_suffixes` @@ -1514,7 +1649,7 @@ Released 2018-09-13 ## 0.0.166 * Rustup to *rustc 1.22.0-nightly (b7960878b 2017-10-18)* -* New lints: [`explicit_write`], `identity_conversion`, [`implicit_hasher`], [`invalid_ref`], [`option_map_or_none`], +* New lints: [`explicit_write`], `identity_conversion`, [`implicit_hasher`], `invalid_ref`, [`option_map_or_none`], [`range_minus_one`], [`range_plus_one`], [`transmute_int_to_bool`], [`transmute_int_to_char`], [`transmute_int_to_float`] @@ -1902,7 +2037,7 @@ Released 2018-09-13 ## 0.0.64 — 2016-04-26 * Rustup to *rustc 1.10.0-nightly (645dd013a 2016-04-24)* -* New lints: [`temporary_cstring_as_ptr`], [`unsafe_removed_from_name`], and [`mem_forget`] +* New lints: `temporary_cstring_as_ptr`, [`unsafe_removed_from_name`], and [`mem_forget`] ## 0.0.63 — 2016-04-08 * Rustup to *rustc 1.9.0-nightly (7979dd608 2016-04-07)* @@ -1956,7 +2091,7 @@ Released 2018-09-13 ## 0.0.49 — 2016-03-09 * Update to *rustc 1.9.0-nightly (eabfc160f 2016-03-08)* -* New lints: [`overflow_check_conditional`], [`unused_label`], [`new_without_default`] +* New lints: [`overflow_check_conditional`], `unused_label`, [`new_without_default`] ## 0.0.48 — 2016-03-07 * Fixed: ICE in [`needless_range_loop`] with globals @@ -1970,6 +2105,7 @@ Released 2018-09-13 [configuration file]: ./rust-clippy#configuration [pull3665]: https://github.com/rust-lang/rust-clippy/pull/3665 [adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md +[`README.md`]: https://github.com/rust-lang/rust-clippy/blob/master/README.md <!-- lint disable no-unused-definitions --> <!-- begin autogenerated links to lint list --> @@ -1988,11 +2124,13 @@ Released 2018-09-13 [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name [`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints [`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions +[`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison [`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison [`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const [`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box [`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec [`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local +[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code [`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow [`bytes_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_nth [`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata @@ -2011,6 +2149,7 @@ Released 2018-09-13 [`clone_double_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref [`clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy [`clone_on_ref_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_ref_ptr +[`cloned_instead_of_copied`]: https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied [`cmp_nan`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_nan [`cmp_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_null [`cmp_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_owned @@ -2041,7 +2180,6 @@ Released 2018-09-13 [`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use [`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg [`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens -[`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds [`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy [`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument @@ -2079,6 +2217,7 @@ Released 2018-09-13 [`filter_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_next [`find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#find_map [`flat_map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_identity +[`flat_map_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option [`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic [`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const @@ -2103,6 +2242,7 @@ Released 2018-09-13 [`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result [`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else +[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond [`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher @@ -2126,10 +2266,9 @@ Released 2018-09-13 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division -[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering -[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref +[`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons [`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters @@ -2232,6 +2371,7 @@ Released 2018-09-13 [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main +[`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark @@ -2245,6 +2385,7 @@ Released 2018-09-13 [`new_without_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default [`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect [`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal +[`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 [`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref @@ -2252,6 +2393,7 @@ Released 2018-09-13 [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref [`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref [`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap +[`option_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_filter_map [`option_if_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn @@ -2261,7 +2403,6 @@ Released 2018-09-13 [`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional [`panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic [`panic_in_result_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_in_result_fn -[`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params [`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap [`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite @@ -2347,7 +2488,6 @@ Released 2018-09-13 [`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment -[`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr [`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some [`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display [`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo @@ -2376,13 +2516,13 @@ Released 2018-09-13 [`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg [`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord -[`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation +[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by [`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap [`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps @@ -2400,7 +2540,6 @@ Released 2018-09-13 [`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice [`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect [`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount -[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label [`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self [`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit [`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index 5954ab25d1..02d2b63c9e 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -18,6 +18,8 @@ All contributors are expected to follow the [Rust Code of Conduct]. - [Finding something to fix/improve](#finding-something-to-fiximprove) - [Writing code](#writing-code) - [Getting code-completion for rustc internals to work](#getting-code-completion-for-rustc-internals-to-work) + - [IntelliJ Rust](#intellij-rust) + - [Rust Analyzer](#rust-analyzer) - [How Clippy works](#how-clippy-works) - [Syncing changes between Clippy and `rust-lang/rust`](#syncing-changes-between-clippy-and-rust-langrust) - [Patching git-subtree to work with big repos](#patching-git-subtree-to-work-with-big-repos) @@ -105,21 +107,41 @@ quick read. ## Getting code-completion for rustc internals to work -Unfortunately, [`rust-analyzer`][ra_homepage] does not (yet?) understand how Clippy uses compiler-internals +### IntelliJ Rust +Unfortunately, [`IntelliJ Rust`][IntelliJ_rust_homepage] does not (yet?) understand how Clippy uses compiler-internals using `extern crate` and it also needs to be able to read the source files of the rustc-compiler which are not available via a `rustup` component at the time of writing. To work around this, you need to have a copy of the [rustc-repo][rustc_repo] available which can be obtained via `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 rust-analyzer will be able to understand. -Run `cargo dev ra_setup --repo-path <repo-path>` where `<repo-path>` is an absolute path to the rustc repo +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 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 rust-analyzer to understand most of the types that Clippy uses. Just make sure to remove the dependencies again before finally making a pull request! -[ra_homepage]: https://rust-analyzer.github.io/ [rustc_repo]: https://github.com/rust-lang/rust/ +[IntelliJ_rust_homepage]: https://intellij-rust.github.io/ + +### Rust Analyzer +As of [#6869][6869], [`rust-analyzer`][ra_homepage] can understand that Clippy uses compiler-internals +using `extern crate` when `package.metadata.rust-analyzer.rustc_private` is set to `true` in Clippys `Cargo.toml.` +You will required a `nightly` toolchain with the `rustc-dev` component installed. +Make sure that in the `rust-analyzer` configuration, you set +``` +{ "rust-analyzer.rustcSource": "discover" } +``` +and +``` +{ "rust-analyzer.updates.channel": "nightly" } +``` +You should be able to see information on things like `Expr` or `EarlyContext` now if you hover them, also +a lot more type hints. +This will work with `rust-analyzer 2021-03-15` shipped in nightly `1.52.0-nightly (107896c32 2021-03-15)` or later. + +[ra_homepage]: https://rust-analyzer.github.io/ +[6869]: https://github.com/rust-lang/rust-clippy/pull/6869 ## How Clippy works diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 2b9488de28..cade44a0a9 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.52" +version = "0.1.53" 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" @@ -37,6 +37,8 @@ clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } serde = { version = "1.0", features = ["derive"] } derive-new = "0.5" regex = "1.4" +quote = "1" +syn = { version = "1", features = ["full"] } # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index 63057609bb..8c0c16c443 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 400 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 450 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) 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. diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs index a26d6aba10..1517cdc941 100644 --- a/src/tools/clippy/clippy_dev/src/fmt.rs +++ b/src/tools/clippy/clippy_dev/src/fmt.rs @@ -68,7 +68,7 @@ pub fn run(check: bool, verbose: bool) { continue; } - success &= rustfmt(context, &path)?; + success &= rustfmt(context, path)?; } Ok(success) @@ -90,7 +90,7 @@ pub fn run(check: bool, verbose: bool) { }, CliError::RaSetupActive => { eprintln!( - "error: a local rustc repo is enabled as path dependency via `cargo dev ra_setup`. + "error: a local rustc repo is enabled as path dependency via `cargo dev ide_setup`. 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/ra_setup.rs b/src/tools/clippy/clippy_dev/src/ide_setup.rs similarity index 97% rename from src/tools/clippy/clippy_dev/src/ra_setup.rs rename to src/tools/clippy/clippy_dev/src/ide_setup.rs index d0e2193ddc..defb1133e4 100644 --- a/src/tools/clippy/clippy_dev/src/ra_setup.rs +++ b/src/tools/clippy/clippy_dev/src/ide_setup.rs @@ -55,7 +55,7 @@ fn inject_deps_into_manifest( // do not inject deps if we have aleady done so if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") { eprintln!( - "cargo dev ra_setup: warning: deps already found inside {}, doing nothing.", + "cargo dev ide_setup: warning: deps already found inside {}, doing nothing.", manifest_path ); return Ok(()); diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index a95abfacea..1e5a140e96 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -12,8 +12,8 @@ use walkdir::WalkDir; pub mod bless; pub mod fmt; +pub mod ide_setup; pub mod new_lint; -pub mod ra_setup; pub mod serve; pub mod stderr_length_check; pub mod update_lints; @@ -101,7 +101,7 @@ impl Lint { #[must_use] pub fn gen_lint_group_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { lints - .map(|l| format!(" LintId::of(&{}::{}),", l.module, l.name.to_uppercase())) + .map(|l| format!(" LintId::of({}::{}),", l.module, l.name.to_uppercase())) .sorted() .collect::<Vec<String>>() } @@ -154,17 +154,17 @@ pub fn gen_register_lint_list<'a>( let header = " store.register_lints(&[".to_string(); let footer = " ]);".to_string(); let internal_lints = internal_lints - .sorted_by_key(|l| format!(" &{}::{},", l.module, l.name.to_uppercase())) + .sorted_by_key(|l| format!(" {}::{},", l.module, l.name.to_uppercase())) .map(|l| { format!( - " #[cfg(feature = \"internal-lints\")]\n &{}::{},", + " #[cfg(feature = \"internal-lints\")]\n {}::{},", l.module, l.name.to_uppercase() ) }); let other_lints = usable_lints - .sorted_by_key(|l| format!(" &{}::{},", l.module, l.name.to_uppercase())) - .map(|l| format!(" &{}::{},", l.module, l.name.to_uppercase())) + .sorted_by_key(|l| format!(" {}::{},", l.module, l.name.to_uppercase())) + .map(|l| format!(" {}::{},", l.module, l.name.to_uppercase())) .sorted(); let mut lint_list = vec![header]; lint_list.extend(internal_lints); @@ -550,9 +550,9 @@ fn test_gen_lint_group_list() { Lint::new("internal", "internal_style", "abc", None, "module_name"), ]; let expected = vec![ - " LintId::of(&module_name::ABC),".to_string(), - " LintId::of(&module_name::INTERNAL),".to_string(), - " LintId::of(&module_name::SHOULD_ASSERT_EQ),".to_string(), + " LintId::of(module_name::ABC),".to_string(), + " LintId::of(module_name::INTERNAL),".to_string(), + " LintId::of(module_name::SHOULD_ASSERT_EQ),".to_string(), ]; assert_eq!(expected, gen_lint_group_list(lints.iter())); } diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 2a9f3e5348..f4da783502 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] use clap::{App, Arg, ArgMatches, SubCommand}; -use clippy_dev::{bless, fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints}; +use clippy_dev::{bless, fmt, ide_setup, new_lint, serve, stderr_length_check, update_lints}; fn main() { let matches = get_clap_config(); @@ -34,7 +34,7 @@ fn main() { ("limit_stderr_length", _) => { stderr_length_check::check(); }, - ("ra_setup", Some(matches)) => ra_setup::run(matches.value_of("rustc-repo-path")), + ("ide_setup", Some(matches)) => ide_setup::run(matches.value_of("rustc-repo-path")), ("serve", Some(matches)) => { let port = matches.value_of("port").unwrap().parse().unwrap(); let lint = matches.value_of("lint"); @@ -138,8 +138,8 @@ 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("ra_setup") - .about("Alter dependencies so rust-analyzer can find rustc internals") + 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") diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index d951ca0e63..4676c2affa 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -44,7 +44,7 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str create_test(&lint).context("Unable to create a test for the new lint") } -fn create_lint(lint: &LintData) -> io::Result<()> { +fn create_lint(lint: &LintData<'_>) -> io::Result<()> { let (pass_type, pass_lifetimes, pass_import, context_import) = match lint.pass { "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), "late" => ("LateLintPass", "<'_>", "use rustc_hir::*;", "LateContext"), @@ -68,7 +68,7 @@ fn create_lint(lint: &LintData) -> io::Result<()> { write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes()) } -fn create_test(lint: &LintData) -> io::Result<()> { +fn create_test(lint: &LintData<'_>) -> io::Result<()> { fn create_project_layout<P: Into<PathBuf>>(lint_name: &str, location: P, case: &str, hint: &str) -> io::Result<()> { let mut path = location.into().join(case); fs::create_dir(&path)?; diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 6bd6c07927..05cdd9d064 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.1.52" +version = "0.1.53" # end automatic update authors = ["The Rust Clippy Developers"] description = "A bunch of helpful lints to avoid common pitfalls in Rust" @@ -20,7 +20,6 @@ pulldown-cmark = { version = "0.8", default-features = false } quine-mc_cluskey = "0.2.2" regex-syntax = "0.6" serde = { version = "1.0", features = ["derive"] } -smallvec = { version = "1", features = ["union"] } toml = "0.5.3" unicode-normalization = "0.1" semver = "0.11" @@ -28,8 +27,6 @@ rustc-semver = "1.1.0" # NOTE: cargo requires serde feat in its url dep # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864> url = { version = "2.1.0", features = ["serde"] } -quote = "1" -syn = { version = "1", features = ["full"] } [features] deny-warnings = [] diff --git a/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs new file mode 100644 index 0000000000..5fbf4bdbd1 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs @@ -0,0 +1,173 @@ +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +use crate::consts::{constant, Constant}; + +use clippy_utils::comparisons::{normalize_comparison, Rel}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_isize_or_usize; +use clippy_utils::{clip, int_bits, unsext}; + +declare_clippy_lint! { + /// **What it does:** Checks for comparisons where one side of the relation is + /// either the minimum or maximum value for its type and warns if it involves a + /// case that is always true or always false. Only integer and boolean types are + /// checked. + /// + /// **Why is this bad?** An expression like `min <= x` may misleadingly imply + /// that it is possible for `x` to be less than the minimum. Expressions like + /// `max < x` are probably mistakes. + /// + /// **Known problems:** For `usize` the size of the current compile target will + /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such + /// a comparison to detect target pointer width will trigger this lint. One can + /// use `mem::sizeof` and compare its value or conditional compilation + /// attributes + /// like `#[cfg(target_pointer_width = "64")] ..` instead. + /// + /// **Example:** + /// + /// ```rust + /// let vec: Vec<isize> = Vec::new(); + /// if vec.len() <= 0 {} + /// if 100 > i32::MAX {} + /// ``` + pub ABSURD_EXTREME_COMPARISONS, + correctness, + "a comparison with a maximum or minimum value that is always true or false" +} + +declare_lint_pass!(AbsurdExtremeComparisons => [ABSURD_EXTREME_COMPARISONS]); + +impl<'tcx> LateLintPass<'tcx> for AbsurdExtremeComparisons { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Binary(ref cmp, lhs, rhs) = expr.kind { + if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { + if !expr.span.from_expansion() { + let msg = "this comparison involving the minimum or maximum element for this \ + type contains a case that is always true or always false"; + + let conclusion = match result { + AbsurdComparisonResult::AlwaysFalse => "this comparison is always false".to_owned(), + AbsurdComparisonResult::AlwaysTrue => "this comparison is always true".to_owned(), + AbsurdComparisonResult::InequalityImpossible => format!( + "the case where the two sides are not equal never occurs, consider using `{} == {}` \ + instead", + snippet(cx, lhs.span, "lhs"), + snippet(cx, rhs.span, "rhs") + ), + }; + + let help = format!( + "because `{}` is the {} value for this type, {}", + snippet(cx, culprit.expr.span, "x"), + match culprit.which { + ExtremeType::Minimum => "minimum", + ExtremeType::Maximum => "maximum", + }, + conclusion + ); + + span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help); + } + } + } + } +} + +enum ExtremeType { + Minimum, + Maximum, +} + +struct ExtremeExpr<'a> { + which: ExtremeType, + expr: &'a Expr<'a>, +} + +enum AbsurdComparisonResult { + AlwaysFalse, + AlwaysTrue, + InequalityImpossible, +} + +fn is_cast_between_fixed_and_target<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + if let ExprKind::Cast(cast_exp, _) = expr.kind { + let precast_ty = cx.typeck_results().expr_ty(cast_exp); + let cast_ty = cx.typeck_results().expr_ty(expr); + + return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty); + } + + false +} + +fn detect_absurd_comparison<'tcx>( + cx: &LateContext<'tcx>, + op: BinOpKind, + lhs: &'tcx Expr<'_>, + rhs: &'tcx Expr<'_>, +) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> { + use AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible}; + use ExtremeType::{Maximum, Minimum}; + // absurd comparison only makes sense on primitive types + // primitive types don't implement comparison operators with each other + if cx.typeck_results().expr_ty(lhs) != cx.typeck_results().expr_ty(rhs) { + return None; + } + + // comparisons between fix sized types and target sized types are considered unanalyzable + if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) { + return None; + } + + let (rel, normalized_lhs, normalized_rhs) = normalize_comparison(op, lhs, rhs)?; + + let lx = detect_extreme_expr(cx, normalized_lhs); + let rx = detect_extreme_expr(cx, normalized_rhs); + + Some(match rel { + Rel::Lt => { + match (lx, rx) { + (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x + (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min + _ => return None, + } + }, + Rel::Le => { + match (lx, rx) { + (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x + (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x + (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min + (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max + _ => return None, + } + }, + Rel::Ne | Rel::Eq => return None, + }) +} + +fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> { + let ty = cx.typeck_results().expr_ty(expr); + + let cv = constant(cx, cx.typeck_results(), expr)?.0; + + let which = match (ty.kind(), cv) { + (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum, + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => { + ExtremeType::Minimum + }, + + (&ty::Bool, Constant::Bool(true)) => ExtremeType::Maximum, + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => { + ExtremeType::Maximum + }, + (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::MAX, uty) == i => ExtremeType::Maximum, + + _ => return None, + }; + Some(ExtremeExpr { which, expr }) +} diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs index 1d511a86c9..3d04abe094 100644 --- a/src/tools/clippy/clippy_lints/src/approx_const.rs +++ b/src/tools/clippy/clippy_lints/src/approx_const.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/arithmetic.rs b/src/tools/clippy/clippy_lints/src/arithmetic.rs index 61fdf9495b..c560f545d6 100644 --- a/src/tools/clippy/clippy_lints/src/arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/arithmetic.rs @@ -1,5 +1,5 @@ use crate::consts::constant_simple; -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs index c30d65bbc5..4b31e16094 100644 --- a/src/tools/clippy/clippy_lints/src/as_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs @@ -1,10 +1,9 @@ +use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::span_lint_and_help; - declare_clippy_lint! { /// **What it does:** Checks for usage of `as` conversions. /// diff --git a/src/tools/clippy/clippy_lints/src/asm_syntax.rs b/src/tools/clippy/clippy_lints/src/asm_syntax.rs index ef1f1a14af..b970c71b75 100644 --- a/src/tools/clippy/clippy_lints/src/asm_syntax.rs +++ b/src/tools/clippy/clippy_lints/src/asm_syntax.rs @@ -1,6 +1,6 @@ use std::fmt; -use crate::utils::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions}; use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs index 77b26faaa5..c565e29d07 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs @@ -1,5 +1,7 @@ use crate::consts::{constant, Constant}; -use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, snippet_opt, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet_opt; +use clippy_utils::{is_direct_expn_of, is_expn_of, match_panic_call}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -69,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { return; } if_chain! { - if let ExprKind::Unary(_, ref lit) = e.kind; + if let ExprKind::Unary(_, lit) = e.kind; if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), lit); if is_true; then { @@ -80,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { if assert_span.from_expansion() { return; } - if let Some(assert_match) = match_assert_with_message(&cx, e) { + if let Some(assert_match) = match_assert_with_message(cx, e) { match assert_match { // matched assert but not message AssertKind::WithoutMessage(false) => lint_false_without_message(), @@ -111,24 +113,23 @@ enum AssertKind { /// where `message` is any expression and `c` is a constant bool. fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<AssertKind> { if_chain! { - if let ExprKind::If(ref cond, ref then, _) = expr.kind; - if let ExprKind::Unary(UnOp::Not, ref expr) = cond.kind; + if let ExprKind::If(cond, then, _) = expr.kind; + if let ExprKind::Unary(UnOp::Not, expr) = cond.kind; // bind the first argument of the `assert!` macro if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), expr); // block - if let ExprKind::Block(ref block, _) = then.kind; + if let ExprKind::Block(block, _) = then.kind; if block.stmts.is_empty(); if let Some(block_expr) = &block.expr; // inner block is optional. unwrap it if it exists, or use the expression as is otherwise. if let Some(begin_panic_call) = match block_expr.kind { - ExprKind::Block(ref inner_block, _) => &inner_block.expr, + ExprKind::Block(inner_block, _) => &inner_block.expr, _ => &block.expr, }; // function call - if let Some(args) = match_panic_call(cx, begin_panic_call); - if args.len() == 1; + if let Some(arg) = match_panic_call(cx, begin_panic_call); // bind the second argument of the `assert!` macro if it exists - if let panic_message = snippet_opt(cx, args[0].span); + if let panic_message = snippet_opt(cx, arg.span); // second argument of begin_panic is irrelevant // as is the second match arm then { diff --git a/src/tools/clippy/clippy_lints/src/assign_ops.rs b/src/tools/clippy/clippy_lints/src/assign_ops.rs index e13f62d042..bc6eec0051 100644 --- a/src/tools/clippy/clippy_lints/src/assign_ops.rs +++ b/src/tools/clippy/clippy_lints/src/assign_ops.rs @@ -1,7 +1,8 @@ -use crate::utils::{ - eq_expr_value, get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, -}; -use crate::utils::{higher, sugg}; +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 if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -92,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps { $($trait_name:ident),+) => { match $op { $(hir::BinOpKind::$trait_name => { - let [krate, module] = crate::utils::paths::OPS_MODULE; + 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 diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs index 869a5c28d0..e6c7c68f91 100644 --- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs +++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs @@ -1,4 +1,6 @@ -use crate::utils::{implements_trait, snippet, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::{AsyncGeneratorKind, Body, BodyId, ExprKind, GeneratorKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs index 703d8a6f62..7ceb01f559 100644 --- a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs @@ -1,4 +1,5 @@ -use crate::utils::{match_def_path, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::match_def_path; use if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind}; @@ -84,7 +85,7 @@ fn match_ordering_def_path(cx: &LateContext<'_>, did: DefId, orderings: &[&str]) fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind; + if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind; let method = method_path.ident.name.as_str(); if type_is_atomic(cx, &args[0]); if method == "load" || method == "store"; @@ -119,7 +120,7 @@ fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::Call(ref func, ref args) = expr.kind; + if let ExprKind::Call(func, args) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if ["fence", "compiler_fence"] @@ -151,7 +152,7 @@ fn opt_ordering_defid(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<DefId> fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind; + if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind; let method = method_path.ident.name.as_str(); if type_is_atomic(cx, &args[0]); if method == "compare_exchange" || method == "compare_exchange_weak" || method == "fetch_update"; diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 6250810bc4..c5b01461c1 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -1,9 +1,8 @@ //! checks for attributes -use crate::utils::{ - first_line_of_span, is_present_in_source, match_panic_def_id, snippet_opt, span_lint, span_lint_and_help, - span_lint_and_sugg, span_lint_and_then, without_block_comments, -}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::match_panic_def_id; +use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; use if_chain::if_chain; use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_errors::Applicability; @@ -251,12 +250,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) { if let Some(items) = &attr.meta_item_list() { if let Some(ident) = attr.ident() { - let ident = &*ident.as_str(); - match ident { - "allow" | "warn" | "deny" | "forbid" => { - check_clippy_lint_names(cx, ident, items); - }, - _ => {}, + if is_lint_level(ident.name) { + check_clippy_lint_names(cx, ident.name, items); } if items.is_empty() || !attr.has_name(sym::deprecated) { return; @@ -289,60 +284,54 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { return; } if let Some(lint_list) = &attr.meta_item_list() { - if let Some(ident) = attr.ident() { - match &*ident.as_str() { - "allow" | "warn" | "deny" | "forbid" => { - // permit `unused_imports`, `deprecated`, `unreachable_pub`, - // `clippy::wildcard_imports`, and `clippy::enum_glob_use` for `use` items - // and `unused_imports` for `extern crate` items with `macro_use` - for lint in lint_list { - match item.kind { - ItemKind::Use(..) => { - if is_word(lint, sym!(unused_imports)) - || is_word(lint, sym::deprecated) - || is_word(lint, sym!(unreachable_pub)) - || is_word(lint, sym!(unused)) - || extract_clippy_lint(lint) - .map_or(false, |s| s == "wildcard_imports") - || extract_clippy_lint(lint).map_or(false, |s| s == "enum_glob_use") - { - return; - } - }, - ItemKind::ExternCrate(..) => { - if is_word(lint, sym!(unused_imports)) && skip_unused_imports { - return; - } - if is_word(lint, sym!(unused_extern_crates)) { - return; - } - }, - _ => {}, + if attr.ident().map_or(false, |ident| is_lint_level(ident.name)) { + // permit `unused_imports`, `deprecated`, `unreachable_pub`, + // `clippy::wildcard_imports`, and `clippy::enum_glob_use` for `use` items + // and `unused_imports` for `extern crate` items with `macro_use` + for lint in lint_list { + match item.kind { + ItemKind::Use(..) => { + if is_word(lint, sym!(unused_imports)) + || is_word(lint, sym::deprecated) + || is_word(lint, sym!(unreachable_pub)) + || is_word(lint, sym!(unused)) + || extract_clippy_lint(lint).map_or(false, |s| s == "wildcard_imports") + || extract_clippy_lint(lint).map_or(false, |s| s == "enum_glob_use") + { + return; + } + }, + ItemKind::ExternCrate(..) => { + if is_word(lint, sym!(unused_imports)) && skip_unused_imports { + return; + } + if is_word(lint, sym!(unused_extern_crates)) { + return; } - } - let line_span = first_line_of_span(cx, attr.span); - - if let Some(mut sugg) = snippet_opt(cx, line_span) { - if sugg.contains("#[") { - span_lint_and_then( - cx, - USELESS_ATTRIBUTE, + }, + _ => {}, + } + } + let line_span = first_line_of_span(cx, attr.span); + + if let Some(mut sugg) = snippet_opt(cx, line_span) { + if sugg.contains("#[") { + span_lint_and_then( + cx, + USELESS_ATTRIBUTE, + line_span, + "useless lint attribute", + |diag| { + sugg = sugg.replacen("#[", "#![", 1); + diag.span_suggestion( line_span, - "useless lint attribute", - |diag| { - sugg = sugg.replacen("#[", "#![", 1); - diag.span_suggestion( - line_span, - "if you just forgot a `!`, use", - sugg, - Applicability::MaybeIncorrect, - ); - }, + "if you just forgot a `!`, use", + sugg, + Applicability::MaybeIncorrect, ); - } - } - }, - _ => {}, + }, + ); + } } } } @@ -372,18 +361,18 @@ fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<SymbolStr> { if meta_item.path.segments.len() > 1; if let tool_name = meta_item.path.segments[0].ident; if tool_name.name == sym::clippy; - let lint_name = meta_item.path.segments.last().unwrap().ident.name; then { + let lint_name = meta_item.path.segments.last().unwrap().ident.name; return Some(lint_name.as_str()); } } None } -fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) { +fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) { for lint in items { if let Some(lint_name) = extract_clippy_lint(lint) { - if lint_name == "restriction" && ident != "allow" { + if lint_name == "restriction" && name != sym::allow { span_lint_and_help( cx, BLANKET_CLIPPY_RESTRICTION_LINTS, @@ -431,7 +420,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_ |stmt| match &stmt.kind { StmtKind::Local(_) => true, StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr), - _ => false, + StmtKind::Item(_) => false, }, ) } @@ -565,7 +554,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) { // check for `rustfmt_skip` and `rustfmt::skip` if let Some(skip_item) = &items[1].meta_item(); if skip_item.has_name(sym!(rustfmt_skip)) || - skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym!(skip); + skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip; // Only lint outer attributes, because custom inner attributes are unstable // Tracking issue: https://github.com/rust-lang/rust/issues/54726 if let AttrStyle::Outer = attr.style; @@ -603,7 +592,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { if let NestedMetaItem::MetaItem(meta) = item { match &meta.kind { MetaItemKind::List(list) => { - mismatched.extend(find_mismatched_target_os(&list)); + mismatched.extend(find_mismatched_target_os(list)); }, MetaItemKind::Word => { if_chain! { @@ -614,7 +603,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { } } }, - _ => {}, + MetaItemKind::NameValue(..) => {}, } } } @@ -630,7 +619,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { then { let mess = "operating system used in target family position"; - span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, &mess, |diag| { + span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| { // Avoid showing the unix suggestion multiple times in case // we have more than one mismatch for unix-like systems let mut unix_suggested = false; @@ -648,3 +637,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { } } } + +fn is_lint_level(symbol: Symbol) -> bool { + matches!(symbol, sym::allow | sym::warn | sym::deny | sym::forbid) +} diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index 14b6a156c6..1739a57a24 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -1,4 +1,5 @@ -use crate::utils::{match_def_path, paths, span_lint_and_note}; +use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::{match_def_path, paths}; use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -100,7 +101,7 @@ impl LateLintPass<'_> for AwaitHolding { let typeck_results = cx.tcx.typeck_body(body_id); check_interior_types( cx, - &typeck_results.generator_interior_types.as_ref().skip_binder(), + typeck_results.generator_interior_types.as_ref().skip_binder(), body.value.span, ); } diff --git a/src/tools/clippy/clippy_lints/src/bit_mask.rs b/src/tools/clippy/clippy_lints/src/bit_mask.rs index a4ee54076e..f7daf3dab4 100644 --- a/src/tools/clippy/clippy_lints/src/bit_mask.rs +++ b/src/tools/clippy/clippy_lints/src/bit_mask.rs @@ -1,6 +1,6 @@ use crate::consts::{constant, Constant}; -use crate::utils::sugg::Sugg; -use crate::utils::{span_lint, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::sugg::Sugg; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs index 153870fb41..b26ef33e05 100644 --- a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs +++ b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_data_structures::fx::FxHashSet; use rustc_hir::{Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs index b53f80fd8b..badcf8d2a4 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs @@ -1,7 +1,7 @@ -use crate::utils::{ - differing_macro_contexts, get_parent_expr, get_trait_def_id, implements_trait, paths, - snippet_block_with_applicability, span_lint, span_lint_and_sugg, -}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::source::snippet_block_with_applicability; +use clippy_utils::ty::implements_trait; +use clippy_utils::{differing_macro_contexts, get_parent_expr}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; @@ -10,6 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// **What it does:** Checks for `if` conditions that use blocks containing an @@ -61,7 +62,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> { if let Some(parent) = get_parent_expr(self.cx, expr); if let ExprKind::MethodCall(_, _, args, _) = parent.kind; let caller = self.cx.typeck_results().expr_ty(&args[0]); - if let Some(iter_id) = get_trait_def_id(self.cx, &paths::ITERATOR); + if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator); if implements_trait(self.cx, caller, iter_id, &[]); then { return; diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs new file mode 100644 index 0000000000..bee706ed40 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -0,0 +1,75 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{ast_utils, is_direct_expn_of}; +use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** This lint warns about boolean comparisons in assert-like macros. + /// + /// **Why is this bad?** It is shorter to use the equivalent. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // Bad + /// assert_eq!("a".is_empty(), false); + /// assert_ne!("a".is_empty(), true); + /// + /// // Good + /// assert!(!"a".is_empty()); + /// ``` + pub BOOL_ASSERT_COMPARISON, + style, + "Using a boolean as comparison value in an assert_* macro when there is no need" +} + +declare_lint_pass!(BoolAssertComparison => [BOOL_ASSERT_COMPARISON]); + +fn is_bool_lit(e: &Expr) -> bool { + matches!( + e.kind, + ExprKind::Lit(Lit { + kind: LitKind::Bool(_), + .. + }) + ) && !e.span.from_expansion() +} + +impl EarlyLintPass for BoolAssertComparison { + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { + let macros = ["assert_eq", "debug_assert_eq"]; + let inverted_macros = ["assert_ne", "debug_assert_ne"]; + + for mac in macros.iter().chain(inverted_macros.iter()) { + if let Some(span) = is_direct_expn_of(e.span, mac) { + if let Some([a, b]) = ast_utils::extract_assert_macro_args(e) { + let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize; + + if nb_bool_args != 1 { + // If there are two boolean arguments, we definitely don't understand + // what's going on, so better leave things as is... + // + // Or there is simply no boolean and then we can leave things as is! + return; + } + + let non_eq_mac = &mac[..mac.len() - 3]; + span_lint_and_sugg( + cx, + BOOL_ASSERT_COMPARISON, + span, + &format!("used `{}!` with a literal bool", mac), + "replace it with", + format!("{}!(..)", non_eq_mac), + Applicability::MaybeIncorrect, + ); + return; + } + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 0713303ec4..67f0e0c787 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -1,7 +1,7 @@ -use crate::utils::{ - eq_expr_value, get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt, - span_lint_and_sugg, span_lint_and_then, -}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use clippy_utils::{eq_expr_value, get_trait_def_id, in_macro, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -261,7 +261,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> { } METHODS_WITH_NEGATION .iter() - .cloned() + .copied() .flat_map(|(a, b)| vec![(a, b), (b, a)]) .find(|&(a, _)| { let path: &str = &path.ident.name.as_str(); diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs index eb5dc7ceec..877ae002d3 100644 --- a/src/tools/clippy/clippy_lints/src/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/bytecount.rs @@ -1,6 +1,7 @@ -use crate::utils::{ - contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, span_lint_and_sugg, -}; +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 if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; @@ -37,59 +38,55 @@ 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(ref count, _, ref count_args, _) = expr.kind; + if let ExprKind::MethodCall(count, _, count_args, _) = expr.kind; if count.ident.name == sym!(count); if count_args.len() == 1; - if let ExprKind::MethodCall(ref filter, _, ref filter_args, _) = count_args[0].kind; + if let ExprKind::MethodCall(filter, _, filter_args, _) = count_args[0].kind; if filter.ident.name == sym!(filter); if filter_args.len() == 2; if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].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 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(), + &paths::SLICE_ITER); then { - let body = cx.tcx.hir().body(body_id); - if_chain! { - if body.params.len() == 1; - if let Some(argname) = get_pat_name(&body.params[0].pat); - if let ExprKind::Binary(ref op, ref l, ref r) = body.value.kind; - if op.node == BinOpKind::Eq; - if match_type(cx, - cx.typeck_results().expr_ty(&filter_args[0]).peel_refs(), - &paths::SLICE_ITER); - 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(ref path, _, ref args, _) = - filter_args[0].kind { - let p = path.ident.name; - if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 { - &args[0] - } else { - &filter_args[0] - } - } else { - &filter_args[0] - }; - let mut applicability = Applicability::MaybeIncorrect; - span_lint_and_sugg( - cx, - NAIVE_BYTECOUNT, - expr.span, - "you appear to be counting bytes the naive way", - "consider using the bytecount crate", - format!("bytecount::count({}, {})", - snippet_with_applicability(cx, haystack.span, "..", &mut applicability), - snippet_with_applicability(cx, needle.span, "..", &mut applicability)), - applicability, - ); + 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 { + let p = path.ident.name; + if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 { + &args[0] + } else { + &filter_args[0] + } + } else { + &filter_args[0] + }; + let mut applicability = Applicability::MaybeIncorrect; + span_lint_and_sugg( + cx, + NAIVE_BYTECOUNT, + expr.span, + "you appear to be counting bytes the naive way", + "consider using the bytecount crate", + format!("bytecount::count({}, {})", + snippet_with_applicability(cx, haystack.span, "..", &mut applicability), + snippet_with_applicability(cx, needle.span, "..", &mut applicability)), + applicability, + ); } }; } @@ -101,10 +98,10 @@ fn check_arg(name: Symbol, arg: Symbol, needle: &Expr<'_>) -> bool { fn get_path_name(expr: &Expr<'_>) -> Option<Symbol> { match expr.kind { - ExprKind::Box(ref e) | ExprKind::AddrOf(BorrowKind::Ref, _, ref e) | ExprKind::Unary(UnOp::Deref, ref e) => { + ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) | ExprKind::Unary(UnOp::Deref, e) => { get_path_name(e) }, - ExprKind::Block(ref b, _) => { + ExprKind::Block(b, _) => { if b.stmts.is_empty() { b.expr.as_ref().and_then(|p| get_path_name(p)) } else { diff --git a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs index cc2869ab49..8097a1c832 100644 --- a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs @@ -2,7 +2,8 @@ use std::path::PathBuf; -use crate::utils::{run_lints, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::run_lints; use rustc_hir::{hir_id::CRATE_HIR_ID, Crate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -19,11 +20,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```toml - /// # This `Cargo.toml` is missing an authors field: + /// # This `Cargo.toml` is missing a description field: /// [package] /// name = "clippy" /// version = "0.0.212" - /// description = "A bunch of helpful lints to avoid common pitfalls in Rust" /// repository = "https://github.com/rust-lang/rust-clippy" /// readme = "README.md" /// license = "MIT OR Apache-2.0" @@ -31,14 +31,13 @@ declare_clippy_lint! { /// categories = ["development-tools", "development-tools::cargo-plugins"] /// ``` /// - /// Should include an authors field like: + /// Should include a description field like: /// /// ```toml /// # This `Cargo.toml` includes all common metadata /// [package] /// name = "clippy" /// version = "0.0.212" - /// authors = ["Someone <someone@rust-lang.org>"] /// description = "A bunch of helpful lints to avoid common pitfalls in Rust" /// repository = "https://github.com/rust-lang/rust-clippy" /// readme = "README.md" @@ -96,10 +95,6 @@ impl LateLintPass<'_> for CargoCommonMetadata { // only run the lint if publish is `None` (`publish = true` or skipped entirely) // or if the vector isn't empty (`publish = ["something"]`) if package.publish.as_ref().filter(|publish| publish.is_empty()).is_none() || self.ignore_publish { - if is_empty_vec(&package.authors) { - missing_warning(cx, &package, "package.authors"); - } - if is_empty_str(&package.description) { missing_warning(cx, &package, "package.description"); } diff --git a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs index b15fe65352..c9ef379be5 100644 --- a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_help; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind, PathSegment}; diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs index 478832a516..869deecfbd 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs @@ -1,10 +1,12 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_constant; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::is_isize_or_usize; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, FloatTy, Ty}; -use crate::utils::{in_constant, is_isize_or_usize, snippet_opt, span_lint_and_sugg}; - use super::{utils, CAST_LOSSLESS}; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index 33b06b8fe7..833ad122e0 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -1,9 +1,9 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::is_isize_or_usize; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, FloatTy, Ty}; -use crate::utils::{is_isize_or_usize, span_lint}; - use super::{utils, CAST_POSSIBLE_TRUNCATION}; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs index 56d301ed3e..2c5c1d7cb4 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs @@ -1,9 +1,9 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::is_isize_or_usize; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::Ty; -use crate::utils::{is_isize_or_usize, span_lint}; - use super::{utils, CAST_POSSIBLE_WRAP}; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs index a1c3900ce1..63ac8fd2dd 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs @@ -1,9 +1,9 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::is_isize_or_usize; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, FloatTy, Ty}; -use crate::utils::{is_isize_or_usize, span_lint}; - use super::{utils, CAST_PRECISION_LOSS}; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs index 87fb5557be..62a119d662 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -1,17 +1,16 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_hir_ty_cfg_dependant; +use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, GenericArg}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::sym; use rustc_target::abi::LayoutOf; -use if_chain::if_chain; - -use crate::utils::{is_hir_ty_cfg_dependant, span_lint}; - use super::CAST_PTR_ALIGNMENT; pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Cast(ref cast_expr, cast_to) = expr.kind { + if let ExprKind::Cast(cast_expr, cast_to) = expr.kind { if is_hir_ty_cfg_dependant(cx, cast_to) { return; } diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs index 3fdc1c6168..d9bf1ea58b 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs @@ -1,11 +1,9 @@ +use clippy_utils::diagnostics::span_lint; +use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; -use if_chain::if_chain; - -use crate::utils::span_lint; - use super::CAST_REF_TO_MUT; pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs index 9656fbebd7..040e0ca886 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs @@ -1,12 +1,11 @@ +use crate::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{method_chain_args, sext}; +use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use if_chain::if_chain; - -use crate::consts::{constant, Constant}; -use crate::utils::{method_chain_args, sext, span_lint}; - use super::CAST_SIGN_LOSS; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { @@ -31,7 +30,7 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast } // Don't lint for positive constants. - let const_val = constant(cx, &cx.typeck_results(), cast_op); + let const_val = constant(cx, cx.typeck_results(), cast_op); if_chain! { if let Some((Constant::Int(n), _)) = const_val; if let ty::Int(ity) = *cast_from.kind(); @@ -42,14 +41,14 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast } // Don't lint for the result of methods that always return non-negative values. - if let ExprKind::MethodCall(ref path, _, _, _) = cast_op.kind { + if let ExprKind::MethodCall(path, _, _, _) = cast_op.kind { let mut method_name = path.ident.name.as_str(); let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"]; if_chain! { if method_name == "unwrap"; if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]); - if let ExprKind::MethodCall(ref inner_path, _, _, _) = &arglist[0][0].kind; + if let ExprKind::MethodCall(inner_path, _, _, _) = &arglist[0][0].kind; then { method_name = inner_path.ident.name.as_str(); } diff --git a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs index ccaad1b8f2..099a0de881 100644 --- a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs +++ b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs @@ -1,13 +1,12 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_with_applicability; +use if_chain::if_chain; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, UintTy}; -use if_chain::if_chain; - -use crate::utils::{snippet_with_applicability, span_lint_and_then}; - use super::CHAR_LIT_AS_U8; pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs index a8d508585b..35350d8a25 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs @@ -1,10 +1,10 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, UintTy}; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; - use super::{utils, FN_TO_NUMERIC_CAST}; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs index 0085c7b27b..6287f479b5 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs @@ -1,10 +1,10 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; - use super::{utils, FN_TO_NUMERIC_CAST_WITH_TRUNCATION}; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index b726bd75f1..ae4fdd12c4 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -12,14 +12,13 @@ mod ptr_as_ptr; mod unnecessary_cast; mod utils; +use clippy_utils::is_hir_ty_cfg_dependant; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use crate::utils::is_hir_ty_cfg_dependant; - declare_clippy_lint! { /// **What it does:** Checks for casts from any numerical to a float type where /// the receiving type cannot store all values from the original type without @@ -373,7 +372,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { return; } - if let ExprKind::Cast(ref cast_expr, cast_to) = expr.kind { + if let ExprKind::Cast(cast_expr, cast_to) = expr.kind { if is_hir_ty_cfg_dependant(cx, cast_to) { return; } diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs index abfbadf364..3132d3a5cf 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs @@ -1,22 +1,19 @@ use std::borrow::Cow; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{meets_msrv, msrvs}; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Mutability, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, TypeAndMut}; use rustc_semver::RustcVersion; -use if_chain::if_chain; - -use crate::utils::sugg::Sugg; -use crate::utils::{meets_msrv, span_lint_and_sugg}; - use super::PTR_AS_PTR; -const PTR_AS_PTR_MSRV: RustcVersion = RustcVersion::new(1, 38, 0); - pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: &Option<RustcVersion>) { - if !meets_msrv(msrv.as_ref(), &PTR_AS_PTR_MSRV) { + if !meets_msrv(msrv.as_ref(), &msrvs::POINTER_CAST) { return; } diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index fa2a07ef1d..9ed359922f 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,3 +1,7 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::numeric_literal::NumericLiteral; +use clippy_utils::source::snippet_opt; +use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Lit, UnOp}; @@ -5,10 +9,6 @@ use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; -use if_chain::if_chain; - -use crate::utils::{numeric_literal::NumericLiteral, snippet_opt, span_lint, span_lint_and_sugg}; - use super::UNNECESSARY_CAST; pub(super) fn check( @@ -44,9 +44,18 @@ pub(super) fn check( lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to); }, LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {}, + LitKind::Int(_, LitIntType::Signed(_) | LitIntType::Unsigned(_)) + | LitKind::Float(_, LitFloatType::Suffixed(_)) + if cast_from.kind() == cast_to.kind() => + { + if let Some(src) = snippet_opt(cx, lit.span) { + let num_lit = NumericLiteral::from_lit_kind(&src, &lit.node).unwrap(); + lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to); + } + }, _ => { if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) { - span_lint( + span_lint_and_sugg( cx, UNNECESSARY_CAST, expr.span, @@ -54,6 +63,9 @@ pub(super) fn check( "casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to ), + "try", + literal_str, + Applicability::MachineApplicable, ); return true; } diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index 54bc69e058..8d3123e1ec 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -1,5 +1,8 @@ //! lint on manually implemented checked conversions that could be transformed into `try_from` +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{meets_msrv, msrvs, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -9,10 +12,6 @@ use rustc_middle::lint::in_external_macro; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use crate::utils::{meets_msrv, snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; - -const CHECKED_CONVERSIONS_MSRV: RustcVersion = RustcVersion::new(1, 34, 0); - declare_clippy_lint! { /// **What it does:** Checks for explicit bounds checking when casting. /// @@ -57,13 +56,13 @@ impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]); impl<'tcx> LateLintPass<'tcx> for CheckedConversions { fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) { - if !meets_msrv(self.msrv.as_ref(), &CHECKED_CONVERSIONS_MSRV) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::TRY_FROM) { return; } let result = if_chain! { if !in_external_macro(cx.sess(), item.span); - if let ExprKind::Binary(op, ref left, ref right) = &item.kind; + if let ExprKind::Binary(op, left, right) = &item.kind; then { match op.node { @@ -199,7 +198,7 @@ impl ConversionType { /// Check for `expr <= (to_type::MAX as from_type)` fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { if_chain! { - if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind; + if let ExprKind::Binary(ref op, left, right) = &expr.kind; if let Some((candidate, check)) = normalize_le_ge(op, left, right); if let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX"); @@ -218,7 +217,7 @@ fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { } // First of we need a binary containing the expression & the cast - if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind { + if let ExprKind::Binary(ref op, left, right) = &expr.kind { normalize_le_ge(op, right, left).and_then(|(l, r)| check_function(l, r)) } else { None @@ -259,7 +258,7 @@ fn get_types_from_cast<'a>( // or `to_type::MAX as from_type` let call_from_cast: Option<(&Expr<'_>, &str)> = if_chain! { // to_type::max_value(), from_type - if let ExprKind::Cast(ref limit, ref from_type) = &expr.kind; + if let ExprKind::Cast(limit, from_type) = &expr.kind; if let TyKind::Path(ref from_type_path) = &from_type.kind; if let Some(from_sym) = int_ty_to_sym(from_type_path); @@ -274,7 +273,7 @@ fn get_types_from_cast<'a>( let limit_from: Option<(&Expr<'_>, &str)> = call_from_cast.or_else(|| { if_chain! { // `from_type::from, to_type::max_value()` - if let ExprKind::Call(ref from_func, ref args) = &expr.kind; + if let ExprKind::Call(from_func, args) = &expr.kind; // `to_type::max_value()` if args.len() == 1; if let limit = &args[0]; @@ -316,14 +315,13 @@ fn get_types_from_cast<'a>( /// Gets the type which implements the called function fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function: &str) -> Option<&'a str> { if_chain! { - if let QPath::TypeRelative(ref ty, ref path) = &path; + if let QPath::TypeRelative(ty, path) = &path; if path.ident.name.as_str() == function; - if let TyKind::Path(QPath::Resolved(None, ref tp)) = &ty.kind; + if let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind; if let [int] = &*tp.segments; - let name = &int.ident.name.as_str(); - then { - candidates.iter().find(|c| name == *c).cloned() + let name = &int.ident.name.as_str(); + candidates.iter().find(|c| name == *c).copied() } else { None } @@ -333,12 +331,11 @@ fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function: /// Gets the type as a string, if it is a supported integer fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> { if_chain! { - if let QPath::Resolved(_, ref path) = *path; + if let QPath::Resolved(_, path) = *path; if let [ty] = &*path.segments; - let name = &ty.ident.name.as_str(); - then { - INTS.iter().find(|c| name == *c).cloned() + let name = &ty.ident.name.as_str(); + INTS.iter().find(|c| name == *c).copied() } else { None } diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index 658d445dfe..f62c6a9c32 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -1,5 +1,9 @@ //! calculate cognitive complexity and warn about overly complex functions +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::LimitStack; use rustc_ast::ast::Attribute; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId}; @@ -9,8 +13,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::{sym, BytePos}; -use crate::utils::{is_type_diagnostic_item, snippet_opt, span_lint_and_help, LimitStack}; - declare_clippy_lint! { /// **What it does:** Checks for methods with high cognitive complexity. /// @@ -150,7 +152,7 @@ impl<'tcx> Visitor<'tcx> for CcHelper { ExprKind::If(_, _, _) => { self.cc += 1; }, - ExprKind::Match(_, ref arms, _) => { + ExprKind::Match(_, arms, _) => { if arms.len() > 1 { self.cc += 1; } diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs index 34f0e6ab02..dae5c86bd4 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs @@ -12,15 +12,15 @@ //! //! This lint is **warn** by default +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::{snippet_block, snippet_block_with_applicability}; +use clippy_utils::sugg::Sugg; use if_chain::if_chain; use rustc_ast::ast; +use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::sugg::Sugg; -use crate::utils::{snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then}; -use rustc_errors::Applicability; - declare_clippy_lint! { /// **What it does:** Checks for nested `if` statements which can be collapsed /// by `&&`-combining their conditions. diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs index 3c45525684..ab22578abd 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs @@ -1,10 +1,11 @@ -use crate::utils::visitors::LocalUsedVisitor; -use crate::utils::{path_to_local, span_lint_and_then, SpanlessEq}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::{is_lang_ctor, path_to_local, SpanlessEq}; use if_chain::if_chain; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, QPath, StmtKind, UnOp}; +use rustc_hir::LangItem::OptionNone; +use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{DefIdTree, TyCtxt, TypeckResults}; +use rustc_middle::ty::TypeckResults; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{MultiSpan, Span}; @@ -51,7 +52,7 @@ declare_lint_pass!(CollapsibleMatch => [COLLAPSIBLE_MATCH]); impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if let ExprKind::Match(_expr, arms, _source) = expr.kind { - if let Some(wild_arm) = arms.iter().rfind(|arm| arm_is_wild_like(arm, cx.tcx)) { + if let Some(wild_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) { for arm in arms { check_arm(arm, wild_arm, cx); } @@ -61,8 +62,8 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch { } fn check_arm<'tcx>(arm: &Arm<'tcx>, wild_outer_arm: &Arm<'tcx>, cx: &LateContext<'tcx>) { + let expr = strip_singleton_blocks(arm.body); if_chain! { - let expr = strip_singleton_blocks(arm.body); if let ExprKind::Match(expr_in, arms_inner, _) = expr.kind; // the outer arm pattern and the inner match if expr_in.span.ctxt() == arm.pat.span.ctxt(); @@ -74,7 +75,7 @@ fn check_arm<'tcx>(arm: &Arm<'tcx>, wild_outer_arm: &Arm<'tcx>, cx: &LateContext // match <local> { .. } if let Some(binding_id) = path_to_local(strip_ref_operators(expr_in, cx.typeck_results())); // 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(arm_inner, cx.tcx)); + 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) = (&arms_inner[wild_inner_arm_idx], &arms_inner[1 - wild_inner_arm_idx]); if !pat_contains_or(non_wild_inner_arm.pat); @@ -125,13 +126,13 @@ fn strip_singleton_blocks<'hir>(mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> /// A "wild-like" pattern is wild ("_") or `None`. /// For this lint to apply, both the outer and inner match expressions /// must have "wild-like" branches that can be combined. -fn arm_is_wild_like(arm: &Arm<'_>, tcx: TyCtxt<'_>) -> bool { +fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { if arm.guard.is_some() { return false; } match arm.pat.kind { PatKind::Binding(..) | PatKind::Wild => true, - PatKind::Path(QPath::Resolved(None, path)) if is_none_ctor(path.res, tcx) => true, + PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone), _ => false, } } @@ -163,17 +164,6 @@ fn pat_contains_or(pat: &Pat<'_>) -> bool { result } -fn is_none_ctor(res: Res, tcx: TyCtxt<'_>) -> bool { - if let Some(none_id) = tcx.lang_items().option_none_variant() { - if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = res { - if let Some(variant_id) = tcx.parent(id) { - return variant_id == none_id; - } - } - } - false -} - /// 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> { diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs index e309db2599..42e153909c 100644 --- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs +++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs @@ -1,6 +1,6 @@ -use crate::utils::{ - get_trait_def_id, if_sequence, implements_trait, parent_node_is_if_expr, paths, span_lint_and_help, SpanlessEq, -}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::implements_trait; +use clippy_utils::{get_trait_def_id, if_sequence, is_else_clause, paths, SpanlessEq}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { } // We only care about the top-most `if` in the chain - if parent_node_is_if_expr(expr, cx) { + if is_else_clause(cx.tcx, expr) { return; } @@ -71,10 +71,8 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { } for cond in conds.windows(2) { - if let ( - &ExprKind::Binary(ref kind1, ref lhs1, ref rhs1), - &ExprKind::Binary(ref kind2, ref lhs2, ref rhs2), - ) = (&cond[0].kind, &cond[1].kind) + if let (&ExprKind::Binary(ref kind1, lhs1, rhs1), &ExprKind::Binary(ref kind2, lhs2, rhs2)) = + (&cond[0].kind, &cond[1].kind) { if !kind_is_cmp(kind1.node) || !kind_is_cmp(kind2.node) { return; diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index 944aaafb46..f956d171bf 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -1,8 +1,19 @@ -use crate::utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash}; -use crate::utils::{get_parent_expr, if_sequence, span_lint_and_note}; -use rustc_hir::{Block, Expr, ExprKind}; +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, +}; +use if_chain::if_chain; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::{Block, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{source_map::Span, symbol::Symbol, BytePos}; +use std::borrow::Cow; declare_clippy_lint! { /// **What it does:** Checks for consecutive `if`s with the same condition. @@ -103,47 +114,478 @@ declare_clippy_lint! { "`if` with the same `then` and `else` blocks" } -declare_lint_pass!(CopyAndPaste => [IFS_SAME_COND, SAME_FUNCTIONS_IN_IF_CONDITION, IF_SAME_THEN_ELSE]); +declare_clippy_lint! { + /// **What it does:** Checks if the `if` and `else` block contain shared code that can be + /// moved out of the blocks. + /// + /// **Why is this bad?** Duplicate code is less maintainable. + /// + /// **Known problems:** Hopefully none. + /// + /// **Example:** + /// ```ignore + /// let foo = if … { + /// println!("Hello World"); + /// 13 + /// } else { + /// println!("Hello World"); + /// 42 + /// }; + /// ``` + /// + /// Could be written as: + /// ```ignore + /// println!("Hello World"); + /// let foo = if … { + /// 13 + /// } else { + /// 42 + /// }; + /// ``` + pub BRANCHES_SHARING_CODE, + complexity, + "`if` statement with shared code in all blocks" +} + +declare_lint_pass!(CopyAndPaste => [ + IFS_SAME_COND, + SAME_FUNCTIONS_IN_IF_CONDITION, + IF_SAME_THEN_ELSE, + BRANCHES_SHARING_CODE +]); impl<'tcx> LateLintPass<'tcx> for CopyAndPaste { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !expr.span.from_expansion() { - // skip ifs directly in else, it will be checked in the parent if - if let Some(&Expr { - kind: ExprKind::If(_, _, Some(ref else_expr)), - .. - }) = get_parent_expr(cx, expr) - { - if else_expr.hir_id == expr.hir_id { - return; + if let ExprKind::If(_, _, _) = expr.kind { + // skip ifs directly in else, it will be checked in the parent if + if let Some(&Expr { + kind: ExprKind::If(_, _, Some(else_expr)), + .. + }) = get_parent_expr(cx, expr) + { + if else_expr.hir_id == expr.hir_id { + return; + } } + + let (conds, blocks) = if_sequence(expr); + // Conditions + lint_same_cond(cx, &conds); + lint_same_fns_in_if_cond(cx, &conds); + // Block duplication + lint_same_then_else(cx, &blocks, conds.len() == blocks.len(), expr); } + } + } +} + +/// Implementation of `BRANCHES_SHARING_CODE` and `IF_SAME_THEN_ELSE` if the blocks are equal. +fn lint_same_then_else<'tcx>( + cx: &LateContext<'tcx>, + blocks: &[&Block<'tcx>], + has_conditional_else: bool, + expr: &'tcx Expr<'_>, +) { + // We only lint ifs with multiple blocks + if blocks.len() < 2 || is_else_clause(cx.tcx, expr) { + return; + } - let (conds, blocks) = if_sequence(expr); - lint_same_then_else(cx, &blocks); - lint_same_cond(cx, &conds); - lint_same_fns_in_if_cond(cx, &conds); + // Check if each block has shared code + let has_expr = blocks[0].expr.is_some(); + + let (start_eq, mut end_eq, expr_eq) = if let Some(block_eq) = scan_block_for_eq(cx, blocks) { + (block_eq.start_eq, block_eq.end_eq, block_eq.expr_eq) + } else { + return; + }; + + // BRANCHES_SHARING_CODE prerequisites + if has_conditional_else || (start_eq == 0 && end_eq == 0 && (has_expr && !expr_eq)) { + return; + } + + // Only the start is the same + if start_eq != 0 && end_eq == 0 && (!has_expr || !expr_eq) { + let block = blocks[0]; + let start_stmts = block.stmts.split_at(start_eq).0; + + let mut start_walker = UsedValueFinderVisitor::new(cx); + for stmt in start_stmts { + intravisit::walk_stmt(&mut start_walker, stmt); } + + emit_branches_sharing_code_lint( + cx, + start_eq, + 0, + false, + check_for_warn_of_moved_symbol(cx, &start_walker.def_symbols, expr), + blocks, + expr, + ); + } else if end_eq != 0 || (has_expr && expr_eq) { + let block = blocks[blocks.len() - 1]; + let (start_stmts, block_stmts) = block.stmts.split_at(start_eq); + let (block_stmts, end_stmts) = block_stmts.split_at(block_stmts.len() - end_eq); + + // Scan start + let mut start_walker = UsedValueFinderVisitor::new(cx); + for stmt in start_stmts { + intravisit::walk_stmt(&mut start_walker, stmt); + } + let mut moved_syms = start_walker.def_symbols; + + // Scan block + let mut block_walker = UsedValueFinderVisitor::new(cx); + for stmt in block_stmts { + intravisit::walk_stmt(&mut block_walker, stmt); + } + let mut block_defs = block_walker.defs; + + // Scan moved stmts + let mut moved_start: Option<usize> = None; + let mut end_walker = UsedValueFinderVisitor::new(cx); + for (index, stmt) in end_stmts.iter().enumerate() { + intravisit::walk_stmt(&mut end_walker, stmt); + + for value in &end_walker.uses { + // Well we can't move this and all prev statements. So reset + if block_defs.contains(value) { + moved_start = Some(index + 1); + end_walker.defs.drain().for_each(|x| { + block_defs.insert(x); + }); + + end_walker.def_symbols.clear(); + } + } + + end_walker.uses.clear(); + } + + if let Some(moved_start) = moved_start { + end_eq -= moved_start; + } + + let end_linable = block.expr.map_or_else( + || end_eq != 0, + |expr| { + intravisit::walk_expr(&mut end_walker, expr); + end_walker.uses.iter().any(|x| !block_defs.contains(x)) + }, + ); + + if end_linable { + end_walker.def_symbols.drain().for_each(|x| { + moved_syms.insert(x); + }); + } + + emit_branches_sharing_code_lint( + cx, + start_eq, + end_eq, + end_linable, + check_for_warn_of_moved_symbol(cx, &moved_syms, expr), + blocks, + expr, + ); } } -/// Implementation of `IF_SAME_THEN_ELSE`. -fn lint_same_then_else(cx: &LateContext<'_>, blocks: &[&Block<'_>]) { - let eq: &dyn Fn(&&Block<'_>, &&Block<'_>) -> bool = - &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) }; +struct BlockEqual { + /// The amount statements that are equal from the start + start_eq: usize, + /// The amount statements that are equal from the end + end_eq: usize, + /// An indication if the block expressions are the same. This will also be true if both are + /// `None` + expr_eq: bool, +} - if let Some((i, j)) = search_same_sequenced(blocks, eq) { - span_lint_and_note( +/// This function can also trigger the `IF_SAME_THEN_ELSE` in which case it'll return `None` to +/// abort any further processing and avoid duplicate lint triggers. +fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> Option<BlockEqual> { + let mut start_eq = usize::MAX; + let mut end_eq = usize::MAX; + let mut expr_eq = true; + for win in blocks.windows(2) { + let l_stmts = win[0].stmts; + let r_stmts = win[1].stmts; + + // `SpanlessEq` now keeps track of the locals and is therefore context sensitive clippy#6752. + // The comparison therefore needs to be done in a way that builds the correct context. + let mut evaluator = SpanlessEq::new(cx); + let mut evaluator = evaluator.inter_expr(); + + let current_start_eq = count_eq(&mut l_stmts.iter(), &mut r_stmts.iter(), |l, r| evaluator.eq_stmt(l, r)); + + let current_end_eq = { + // We skip the middle statements which can't be equal + let end_comparison_count = l_stmts.len().min(r_stmts.len()) - current_start_eq; + let it1 = l_stmts.iter().skip(l_stmts.len() - end_comparison_count); + let it2 = r_stmts.iter().skip(r_stmts.len() - end_comparison_count); + it1.zip(it2) + .fold(0, |acc, (l, r)| if evaluator.eq_stmt(l, r) { acc + 1 } else { 0 }) + }; + let block_expr_eq = both(&win[0].expr, &win[1].expr, |l, r| evaluator.eq_expr(l, r)); + + // IF_SAME_THEN_ELSE + if_chain! { + 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); + then { + span_lint_and_note( + cx, + IF_SAME_THEN_ELSE, + win[0].span, + "this `if` has identical blocks", + Some(win[1].span), + "same as this", + ); + + return None; + } + } + + start_eq = start_eq.min(current_start_eq); + end_eq = end_eq.min(current_end_eq); + expr_eq &= block_expr_eq; + } + + let has_expr = blocks[0].expr.is_some(); + if has_expr && !expr_eq { + end_eq = 0; + } + + // Check if the regions are overlapping. Set `end_eq` to prevent the overlap + let min_block_size = blocks.iter().map(|x| x.stmts.len()).min().unwrap(); + if (start_eq + end_eq) > min_block_size { + end_eq = min_block_size - start_eq; + } + + Some(BlockEqual { + start_eq, + end_eq, + expr_eq, + }) +} + +fn check_for_warn_of_moved_symbol( + cx: &LateContext<'tcx>, + symbols: &FxHashSet<Symbol>, + if_expr: &'tcx Expr<'_>, +) -> bool { + get_enclosing_block(cx, if_expr.hir_id).map_or(false, |block| { + let ignore_span = block.span.shrink_to_lo().to(if_expr.span); + + symbols + .iter() + .filter(|sym| !sym.as_str().starts_with('_')) + .any(move |sym| { + let mut walker = ContainsName { + name: *sym, + result: false, + }; + + // Scan block + block + .stmts + .iter() + .filter(|stmt| !ignore_span.overlaps(stmt.span)) + .for_each(|stmt| intravisit::walk_stmt(&mut walker, stmt)); + + if let Some(expr) = block.expr { + intravisit::walk_expr(&mut walker, expr); + } + + walker.result + }) + }) +} + +fn emit_branches_sharing_code_lint( + cx: &LateContext<'tcx>, + start_stmts: usize, + end_stmts: usize, + lint_end: bool, + warn_about_moved_symbol: bool, + blocks: &[&Block<'tcx>], + if_expr: &'tcx Expr<'_>, +) { + if start_stmts == 0 && !lint_end { + return; + } + + // (help, span, suggestion) + let mut suggestions: Vec<(&str, Span, String)> = vec![]; + let mut add_expr_note = false; + + // Construct suggestions + if start_stmts > 0 { + let block = blocks[0]; + let span_start = first_line_of_span(cx, if_expr.span).shrink_to_lo(); + let span_end = block.stmts[start_stmts - 1].span.source_callsite(); + + let cond_span = first_line_of_span(cx, if_expr.span).until(block.span); + let cond_snippet = reindent_multiline(snippet(cx, cond_span, "_"), false, None); + let cond_indent = indent_of(cx, cond_span); + let moved_span = block.stmts[0].span.source_callsite().to(span_end); + let moved_snippet = reindent_multiline(snippet(cx, moved_span, "_"), true, None); + let suggestion = moved_snippet.to_string() + "\n" + &cond_snippet + "{"; + let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, cond_indent); + + let span = span_start.to(span_end); + suggestions.push(("start", span, suggestion.to_string())); + } + + if lint_end { + let block = blocks[blocks.len() - 1]; + let span_end = block.span.shrink_to_hi(); + + let moved_start = if end_stmts == 0 && block.expr.is_some() { + block.expr.unwrap().span + } else { + block.stmts[block.stmts.len() - end_stmts].span + } + .source_callsite(); + let moved_end = block + .expr + .map_or_else(|| block.stmts[block.stmts.len() - 1].span, |expr| expr.span) + .source_callsite(); + + let moved_span = moved_start.to(moved_end); + let moved_snipped = reindent_multiline(snippet(cx, moved_span, "_"), true, None); + let indent = indent_of(cx, if_expr.span.shrink_to_hi()); + let suggestion = "}\n".to_string() + &moved_snipped; + let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, indent); + + let mut span = moved_start.to(span_end); + // Improve formatting if the inner block has indention (i.e. normal Rust formatting) + let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt()); + if snippet_opt(cx, test_span) + .map(|snip| snip == " ") + .unwrap_or_default() + { + span = span.with_lo(test_span.lo()); + } + + suggestions.push(("end", span, suggestion.to_string())); + add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit() + } + + let add_optional_msgs = |diag: &mut DiagnosticBuilder<'_>| { + if add_expr_note { + diag.note("The end suggestion probably needs some adjustments to use the expression result correctly"); + } + + if warn_about_moved_symbol { + diag.warn("Some moved values might need to be renamed to avoid wrong references"); + } + }; + + // Emit lint + if suggestions.len() == 1 { + let (place_str, span, sugg) = suggestions.pop().unwrap(); + let msg = format!("all if blocks contain the same code at the {}", place_str); + let help = format!("consider moving the {} statements out like this", place_str); + span_lint_and_then(cx, BRANCHES_SHARING_CODE, span, msg.as_str(), |diag| { + diag.span_suggestion(span, help.as_str(), sugg, Applicability::Unspecified); + + add_optional_msgs(diag); + }); + } else if suggestions.len() == 2 { + let (_, end_span, end_sugg) = suggestions.pop().unwrap(); + let (_, start_span, start_sugg) = suggestions.pop().unwrap(); + span_lint_and_then( cx, - IF_SAME_THEN_ELSE, - j.span, - "this `if` has identical blocks", - Some(i.span), - "same as this", + BRANCHES_SHARING_CODE, + start_span, + "all if blocks contain the same code at the start and the end. Here at the start", + move |diag| { + diag.span_note(end_span, "and here at the end"); + + diag.span_suggestion( + start_span, + "consider moving the start statements out like this", + start_sugg, + Applicability::Unspecified, + ); + + diag.span_suggestion( + end_span, + "and consider moving the end statements out like this", + end_sugg, + Applicability::Unspecified, + ); + + add_optional_msgs(diag); + }, ); } } +/// This visitor collects `HirId`s and Symbols of defined symbols and `HirId`s of used values. +struct UsedValueFinderVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + + /// The `HirId`s of defined values in the scanned statements + defs: FxHashSet<HirId>, + + /// The Symbols of the defined symbols in the scanned statements + def_symbols: FxHashSet<Symbol>, + + /// The `HirId`s of the used values + uses: FxHashSet<HirId>, +} + +impl<'a, 'tcx> UsedValueFinderVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'tcx>) -> Self { + UsedValueFinderVisitor { + cx, + defs: FxHashSet::default(), + def_symbols: FxHashSet::default(), + uses: FxHashSet::default(), + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for UsedValueFinderVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::All(self.cx.tcx.hir()) + } + + fn visit_local(&mut self, l: &'tcx rustc_hir::Local<'tcx>) { + let local_id = l.pat.hir_id; + self.defs.insert(local_id); + + if let Some(sym) = l.pat.simple_ident() { + self.def_symbols.insert(sym.name); + } + + if let Some(expr) = l.init { + intravisit::walk_expr(self, expr); + } + } + + fn visit_qpath(&mut self, qpath: &'tcx rustc_hir::QPath<'tcx>, id: HirId, _span: rustc_span::Span) { + if let rustc_hir::QPath::Resolved(_, path) = *qpath { + if path.segments.len() == 1 { + if let rustc_hir::def::Res::Local(var) = self.cx.qpath_res(qpath, id) { + self.uses.insert(var); + } + } + } + } +} + /// Implementation of `IFS_SAME_COND`. fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) { let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 { @@ -197,15 +639,3 @@ fn lint_same_fns_in_if_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) { ); } } - -fn search_same_sequenced<T, Eq>(exprs: &[T], eq: Eq) -> Option<(&T, &T)> -where - Eq: Fn(&T, &T) -> bool, -{ - for win in exprs.windows(2) { - if eq(&win[0], &win[1]) { - return Some((&win[0], &win[1])); - } - } - None -} diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index 004bce5f62..35079c6bed 100644 --- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs @@ -1,7 +1,11 @@ -use crate::utils::{is_copy, match_path, paths, span_lint_and_note}; +use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::ty::is_copy; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +use if_chain::if_chain; declare_clippy_lint! { /// **What it does:** Checks for types that implement `Copy` as well as @@ -33,14 +37,16 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); impl<'tcx> LateLintPass<'tcx> for CopyIterator { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), - .. - }) = item.kind - { + if_chain! { + if let ItemKind::Impl(Impl { + of_trait: Some(ref trait_ref), + .. + }) = item.kind; let ty = cx.tcx.type_of(item.def_id); - - if is_copy(cx, ty) && match_path(&trait_ref.path, &paths::ITERATOR) { + if is_copy(cx, ty); + if let Some(trait_id) = trait_ref.trait_def_id(); + if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id); + then { span_lint_and_note( cx, COPY_ITERATOR, diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs index 200b6a565c..7b5cce6462 100644 --- a/src/tools/clippy/clippy_lints/src/create_dir.rs +++ b/src/tools/clippy/clippy_lints/src/create_dir.rs @@ -1,4 +1,6 @@ -use crate::utils::{match_def_path, paths, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; @@ -31,7 +33,7 @@ declare_lint_pass!(CreateDir => [CREATE_DIR]); impl LateLintPass<'_> for CreateDir { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::Call(ref func, ref args) = expr.kind; + if let ExprKind::Call(func, args) = expr.kind; if let ExprKind::Path(ref path) = func.kind; if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR); diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs index e513dcce64..286cc7e223 100644 --- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs +++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs @@ -1,4 +1,5 @@ -use crate::utils::{snippet_opt, span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::source::snippet_opt; use rustc_ast::ast; use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 6fa1378b8c..710da8fe9e 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -1,7 +1,6 @@ -use crate::utils::{ - any_parent_is_automatically_derived, contains_name, match_def_path, paths, snippet_with_macro_callsite, -}; -use crate::utils::{span_lint_and_note, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; +use clippy_utils::source::snippet_with_macro_callsite; +use clippy_utils::{any_parent_is_automatically_derived, contains_name, match_def_path, paths}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -78,33 +77,33 @@ impl LateLintPass<'_> for Default { if_chain! { // Avoid cases already linted by `field_reassign_with_default` if !self.reassigned_linted.contains(&expr.span); - if let ExprKind::Call(ref path, ..) = expr.kind; + if let ExprKind::Call(path, ..) = expr.kind; if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); if let ExprKind::Path(ref qpath) = path.kind; if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type. if let QPath::Resolved(None, _path) = qpath; + let expr_ty = cx.typeck_results().expr_ty(expr); + if let ty::Adt(def, ..) = expr_ty.kind(); then { - let expr_ty = cx.typeck_results().expr_ty(expr); - if let ty::Adt(def, ..) = expr_ty.kind() { - // TODO: Work out a way to put "whatever the imported way of referencing - // this type in this file" rather than a fully-qualified type. - let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did)); - span_lint_and_sugg( - cx, - DEFAULT_TRAIT_ACCESS, - expr.span, - &format!("calling `{}` is more clear than this expression", replacement), - "try", - replacement, - Applicability::Unspecified, // First resolve the TODO above - ); - } + // TODO: Work out a way to put "whatever the imported way of referencing + // this type in this file" rather than a fully-qualified type. + let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did)); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("calling `{}` is more clear than this expression", replacement), + "try", + replacement, + Applicability::Unspecified, // First resolve the TODO above + ); } } } + #[allow(clippy::too_many_lines)] fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) { // start from the `let mut _ = _::default();` and look at all the following // statements, see if they re-assign the fields of the binding @@ -198,6 +197,24 @@ impl LateLintPass<'_> for Default { .collect::<Vec<String>>() .join(", "); + // give correct suggestion if generics are involved (see #6944) + let binding_type = if_chain! { + if let ty::Adt(adt_def, substs) = binding_type.kind(); + if !substs.is_empty(); + then { + let adt_def_ty_name = cx.tcx.item_name(adt_def.did); + let generic_args = substs.iter().collect::<Vec<_>>(); + let tys_str = generic_args + .iter() + .map(ToString::to_string) + .collect::<Vec<_>>() + .join(", "); + format!("{}::<{}>", adt_def_ty_name, &tys_str) + } else { + binding_type.to_string() + } + }; + let sugg = if ext_with_default { if field_list.is_empty() { format!("{}::default()", binding_type) @@ -229,7 +246,7 @@ impl LateLintPass<'_> for Default { /// Checks if the given expression is the `default` method belonging to the `Default` trait. fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool { if_chain! { - if let ExprKind::Call(ref fn_expr, _) = &expr.kind; + if let ExprKind::Call(fn_expr, _) = &expr.kind; if let ExprKind::Path(qpath) = &fn_expr.kind; if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); then { @@ -245,11 +262,11 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> { if_chain! { // only take assignments - if let StmtKind::Semi(ref later_expr) = this.kind; - if let ExprKind::Assign(ref assign_lhs, ref assign_rhs, _) = later_expr.kind; + if let StmtKind::Semi(later_expr) = this.kind; + if let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind; // only take assignments to fields where the left-hand side field is a field of // the same binding as the previous statement - if let ExprKind::Field(ref binding, field_ident) = assign_lhs.kind; + if let ExprKind::Field(binding, field_ident) = assign_lhs.kind; if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind; if let Some(second_binding_name) = path.segments.last(); if second_binding_name.ident.name == binding_name; diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 369efacc9b..6e88394268 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -1,3 +1,6 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use if_chain::if_chain; use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::{ @@ -10,10 +13,7 @@ use rustc_middle::{ ty::{self, FloatTy, IntTy, PolyFnSig, Ty}, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; - -use if_chain::if_chain; - -use crate::utils::{snippet, span_lint_and_sugg}; +use std::iter; declare_clippy_lint! { /// **What it does:** Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type @@ -108,7 +108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { match &expr.kind { ExprKind::Call(func, args) => { if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) { - for (expr, bound) in args.iter().zip(fn_sig.skip_binder().inputs().iter()) { + for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) { // Push found arg type, then visit arg. self.ty_bounds.push(TyBound::Ty(bound)); self.visit_expr(expr); @@ -121,7 +121,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { ExprKind::MethodCall(_, _, args, _) => { if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) { let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder(); - for (expr, bound) in args.iter().zip(fn_sig.inputs().iter()) { + for (expr, bound) in iter::zip(*args, fn_sig.inputs()) { self.ty_bounds.push(TyBound::Ty(bound)); self.visit_expr(expr); self.ty_bounds.pop(); @@ -131,8 +131,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { }, ExprKind::Struct(_, fields, base) => { + let ty = self.cx.typeck_results().expr_ty(expr); if_chain! { - let ty = self.cx.typeck_results().expr_ty(expr); if let Some(adt_def) = ty.ty_adt_def(); if adt_def.is_struct(); if let Some(variant) = adt_def.variants.iter().next(); diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 89088c533e..4688b3d510 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -93,15 +93,6 @@ declare_deprecated_lint! { "the replacement suggested by this lint had substantially different behavior" } -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This lint has been superseded by the warn-by-default - /// `invalid_value` rustc lint. - pub INVALID_REF, - "superseded by rustc lint `invalid_value`" -} - declare_deprecated_lint! { /// **What it does:** Nothing. This lint has been deprecated. /// @@ -110,24 +101,6 @@ declare_deprecated_lint! { "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint" } -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This lint has been uplifted to rustc and is now called - /// `array_into_iter`. - pub INTO_ITER_ON_ARRAY, - "this lint has been uplifted to rustc and is now called `array_into_iter`" -} - -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This lint has been uplifted to rustc and is now called - /// `unused_labels`. - pub UNUSED_LABEL, - "this lint has been uplifted to rustc and is now called `unused_labels`" -} - declare_deprecated_lint! { /// **What it does:** Nothing. This lint has been deprecated. /// @@ -147,44 +120,17 @@ declare_deprecated_lint! { declare_deprecated_lint! { /// **What it does:** Nothing. This lint has been deprecated. /// - /// **Deprecation reason:** This lint has been uplifted to rustc and is now called - /// `drop_bounds`. - pub DROP_BOUNDS, - "this lint has been uplifted to rustc and is now called `drop_bounds`" -} - -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This lint has been uplifted to rustc and is now called - /// `temporary_cstring_as_ptr`. - pub TEMPORARY_CSTRING_AS_PTR, - "this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr`" -} - -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This lint has been uplifted to rustc and is now called - /// `panic_fmt`. - pub PANIC_PARAMS, - "this lint has been uplifted to rustc and is now called `panic_fmt`" -} - -declare_deprecated_lint! { - /// **What it does:** Nothing. This lint has been deprecated. - /// - /// **Deprecation reason:** This lint has been integrated into the `unknown_lints` - /// rustc lint. - pub UNKNOWN_CLIPPY_LINTS, - "this lint has been integrated into the `unknown_lints` rustc lint" + /// **Deprecation reason:** This lint has been replaced by `manual_find_map`, a + /// more specific lint. + pub FIND_MAP, + "this lint has been replaced by `manual_find_map`, a more specific lint" } declare_deprecated_lint! { /// **What it does:** Nothing. This lint has been deprecated. /// - /// **Deprecation reason:** This lint has been replaced by `manual_find_map`, a + /// **Deprecation reason:** This lint has been replaced by `manual_filter_map`, a /// more specific lint. - pub FIND_MAP, - "this lint has been replaced by `manual_find_map`, a more specific lint" + pub FILTER_MAP, + "this lint has been replaced by `manual_filter_map`, a more specific lint" } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index b5fb51af1c..1415f8e235 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1,11 +1,14 @@ -use crate::utils::{get_parent_expr, implements_trait, snippet, span_lint_and_sugg}; -use if_chain::if_chain; -use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX, PREC_PREFIX}; +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 rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; +use rustc_middle::ty::{self, Ty, TyCtxt, TyS, TypeckResults}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::{symbol::sym, Span}; declare_clippy_lint! { /// **What it does:** Checks for explicit `deref()` or `deref_mut()` method calls. @@ -34,76 +37,265 @@ declare_clippy_lint! { "Explicit use of deref or deref_mut method while not in a method chain." } -declare_lint_pass!(Dereferencing => [ - EXPLICIT_DEREF_METHODS +impl_lint_pass!(Dereferencing => [ + EXPLICIT_DEREF_METHODS, ]); +#[derive(Default)] +pub struct Dereferencing { + state: Option<(State, StateData)>, + + // While parsing a `deref` method call in ufcs form, the path to the function is itself an + // expression. This is to store the id of that expression so it can be skipped when + // `check_expr` is called for it. + skip_expr: Option<HirId>, +} + +struct StateData { + /// Span of the top level expression + span: Span, + /// The required mutability + target_mut: Mutability, +} + +enum State { + // Any number of deref method calls. + DerefMethod { + // The number of calls in a sequence which changed the referenced type + ty_changed_count: usize, + is_final_ufcs: bool, + }, +} + +// A reference operation considered by this lint pass +enum RefOp { + Method(Mutability), + Deref, + AddrOf, +} + impl<'tcx> LateLintPass<'tcx> for Dereferencing { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if !expr.span.from_expansion(); - if let ExprKind::MethodCall(ref method_name, _, ref args, _) = &expr.kind; - if args.len() == 1; - - then { - if let Some(parent_expr) = get_parent_expr(cx, expr) { - // Check if we have the whole call chain here - if let ExprKind::MethodCall(..) = parent_expr.kind { - return; - } - // Check for Expr that we don't want to be linted - let precedence = parent_expr.precedence(); - match precedence { - // Lint a Call is ok though - ExprPrecedence::Call | ExprPrecedence::AddrOf => (), - _ => { - if precedence.order() >= PREC_PREFIX && precedence.order() <= PREC_POSTFIX { - return; - } - } + // Skip path expressions from deref calls. e.g. `Deref::deref(e)` + if Some(expr.hir_id) == self.skip_expr.take() { + return; + } + + // Stop processing sub expressions when a macro call is seen + if in_macro(expr.span) { + if let Some((state, data)) = self.state.take() { + report(cx, expr, state, data); + } + return; + } + + let typeck = cx.typeck_results(); + let (kind, sub_expr) = if let Some(x) = try_parse_ref_op(cx.tcx, typeck, expr) { + x + } else { + // The whole chain of reference operations has been seen + if let Some((state, data)) = self.state.take() { + report(cx, expr, state, data); + } + return; + }; + + match (self.state.take(), kind) { + (None, kind) => { + let parent = get_parent_node(cx.tcx, expr.hir_id); + let expr_ty = typeck.expr_ty(expr); + + match kind { + RefOp::Method(target_mut) + if !is_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id) + && is_linted_explicit_deref_position(parent, expr.hir_id, expr.span) => + { + self.state = Some(( + State::DerefMethod { + ty_changed_count: if deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)) { + 0 + } else { + 1 + }, + is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), + }, + StateData { + span: expr.span, + target_mut, + }, + )); } + _ => (), } - let name = method_name.ident.as_str(); - lint_deref(cx, &*name, &args[0], args[0].span, expr.span); - } + }, + (Some((State::DerefMethod { ty_changed_count, .. }, data)), RefOp::Method(_)) => { + self.state = Some(( + State::DerefMethod { + ty_changed_count: if deref_method_same_type(typeck.expr_ty(expr), typeck.expr_ty(sub_expr)) { + ty_changed_count + } else { + ty_changed_count + 1 + }, + is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), + }, + data, + )); + }, + + (Some((state, data)), _) => report(cx, expr, state, data), } } } -fn lint_deref(cx: &LateContext<'_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) { - match method_name { - "deref" => { - let impls_deref_trait = cx.tcx.lang_items().deref_trait().map_or(false, |id| { - implements_trait(cx, cx.typeck_results().expr_ty(&call_expr), id, &[]) - }); - if impls_deref_trait { - span_lint_and_sugg( - cx, - EXPLICIT_DEREF_METHODS, - expr_span, - "explicit deref method call", - "try this", - format!("&*{}", &snippet(cx, var_span, "..")), - Applicability::MachineApplicable, - ); - } +fn try_parse_ref_op( + tcx: TyCtxt<'tcx>, + typeck: &'tcx TypeckResults<'_>, + expr: &'tcx Expr<'_>, +) -> Option<(RefOp, &'tcx Expr<'tcx>)> { + let (def_id, arg) = match expr.kind { + ExprKind::MethodCall(_, _, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg), + ExprKind::Call( + Expr { + kind: ExprKind::Path(path), + hir_id, + .. + }, + [arg], + ) => (typeck.qpath_res(path, *hir_id).opt_def_id()?, arg), + ExprKind::Unary(UnOp::Deref, sub_expr) if !typeck.expr_ty(sub_expr).is_unsafe_ptr() => { + return Some((RefOp::Deref, sub_expr)); }, - "deref_mut" => { - let impls_deref_mut_trait = cx.tcx.lang_items().deref_mut_trait().map_or(false, |id| { - implements_trait(cx, cx.typeck_results().expr_ty(&call_expr), id, &[]) - }); - if impls_deref_mut_trait { - span_lint_and_sugg( - cx, - EXPLICIT_DEREF_METHODS, - expr_span, - "explicit deref_mut method call", - "try this", - format!("&mut *{}", &snippet(cx, var_span, "..")), - Applicability::MachineApplicable, - ); - } + ExprKind::AddrOf(BorrowKind::Ref, _, sub_expr) => return Some((RefOp::AddrOf, sub_expr)), + _ => return None, + }; + if tcx.is_diagnostic_item(sym::deref_method, def_id) { + Some((RefOp::Method(Mutability::Not), arg)) + } else if tcx.trait_of_item(def_id)? == tcx.lang_items().deref_mut_trait()? { + Some((RefOp::Method(Mutability::Mut), arg)) + } else { + None + } +} + +// Checks whether the type for a deref call actually changed the type, not just the mutability of +// the reference. +fn deref_method_same_type(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { + match (result_ty.kind(), arg_ty.kind()) { + (ty::Ref(_, result_ty, _), ty::Ref(_, arg_ty, _)) => TyS::same_type(result_ty, arg_ty), + + // The result type for a deref method is always a reference + // Not matching the previous pattern means the argument type is not a reference + // This means that the type did change + _ => false, + } +} + +// Checks whether the parent node is a suitable context for switching from a deref method to the +// deref operator. +fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId, child_span: Span) -> bool { + let parent = match parent { + Some(Node::Expr(e)) if e.span.ctxt() == child_span.ctxt() => e, + _ => return true, + }; + match parent.kind { + // Leave deref calls in the middle of a method chain. + // e.g. x.deref().foo() + ExprKind::MethodCall(_, _, [self_arg, ..], _) if self_arg.hir_id == child_id => false, + + // Leave deref calls resulting in a called function + // e.g. (x.deref())() + ExprKind::Call(func_expr, _) if func_expr.hir_id == child_id => false, + + // Makes an ugly suggestion + // e.g. *x.deref() => *&*x + ExprKind::Unary(UnOp::Deref, _) + // Postfix expressions would require parens + | ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) + | ExprKind::Field(..) + | ExprKind::Index(..) + | ExprKind::Err => false, + + ExprKind::Box(..) + | ExprKind::ConstBlock(..) + | ExprKind::Array(_) + | ExprKind::Call(..) + | ExprKind::MethodCall(..) + | ExprKind::Tup(..) + | ExprKind::Binary(..) + | ExprKind::Unary(..) + | ExprKind::Lit(..) + | ExprKind::Cast(..) + | ExprKind::Type(..) + | ExprKind::DropTemps(..) + | ExprKind::If(..) + | ExprKind::Loop(..) + | ExprKind::Match(..) + | ExprKind::Closure(..) + | ExprKind::Block(..) + | ExprKind::Assign(..) + | ExprKind::AssignOp(..) + | ExprKind::Path(..) + | ExprKind::AddrOf(..) + | ExprKind::Break(..) + | ExprKind::Continue(..) + | ExprKind::Ret(..) + | ExprKind::InlineAsm(..) + | ExprKind::LlvmInlineAsm(..) + | ExprKind::Struct(..) + | ExprKind::Repeat(..) + | ExprKind::Yield(..) => true, + } +} + +#[allow(clippy::needless_pass_by_value)] +fn report(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData) { + match state { + State::DerefMethod { + ty_changed_count, + is_final_ufcs, + } => { + let mut app = Applicability::MachineApplicable; + let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); + let ty = cx.typeck_results().expr_ty(expr); + let (_, ref_count) = peel_mid_ty_refs(ty); + let deref_str = if ty_changed_count >= ref_count && ref_count != 0 { + // a deref call changing &T -> &U requires two deref operators the first time + // this occurs. One to remove the reference, a second to call the deref impl. + "*".repeat(ty_changed_count + 1) + } else { + "*".repeat(ty_changed_count) + }; + let addr_of_str = if ty_changed_count < ref_count { + // Check if a reborrow from &mut T -> &T is required. + if data.target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) { + "&*" + } else { + "" + } + } else if data.target_mut == Mutability::Mut { + "&mut " + } else { + "&" + }; + + let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { + format!("({})", expr_str) + } else { + expr_str.into_owned() + }; + + span_lint_and_sugg( + cx, + EXPLICIT_DEREF_METHODS, + data.span, + match data.target_mut { + Mutability::Not => "explicit `deref` method call", + Mutability::Mut => "explicit `deref_mut` method call", + }, + "try this", + format!("{}{}{}", addr_of_str, deref_str, expr_str), + app, + ); }, - _ => (), } } diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 6d3094ed6b..647af3bdc0 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -1,8 +1,7 @@ -use crate::utils::paths; -use crate::utils::{ - get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_def_path, span_lint_and_help, - span_lint_and_note, span_lint_and_then, -}; +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 if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor}; @@ -13,7 +12,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; +use rustc_span::{def_id::LOCAL_CRATE, source_map::Span}; declare_clippy_lint! { /// **What it does:** Checks for deriving `Hash` but implementing `PartialEq` @@ -200,7 +199,7 @@ fn check_hash_peq<'tcx>( then { // Look for the PartialEq implementations for `ty` cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { - let peq_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); + let peq_is_automatically_derived = is_automatically_derived(cx.tcx.get_attrs(impl_id)); if peq_is_automatically_derived == hash_is_automatically_derived { return; @@ -254,7 +253,7 @@ fn check_ord_partial_ord<'tcx>( then { // Look for the PartialOrd implementations for `ty` cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { - let partial_ord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); + let partial_ord_is_automatically_derived = is_automatically_derived(cx.tcx.get_attrs(impl_id)); if partial_ord_is_automatically_derived == ord_is_automatically_derived { return; @@ -294,48 +293,53 @@ fn check_ord_partial_ord<'tcx>( /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) { - if cx - .tcx - .lang_items() - .clone_trait() - .map_or(false, |id| Some(id) == trait_ref.trait_def_id()) - { - if !is_copy(cx, ty) { + let clone_id = match cx.tcx.lang_items().clone_trait() { + Some(id) if trait_ref.trait_def_id() == Some(id) => id, + _ => return, + }; + let copy_id = match cx.tcx.lang_items().copy_trait() { + Some(id) => id, + None => return, + }; + let (ty_adt, ty_subs) = match *ty.kind() { + // Unions can't derive clone. + ty::Adt(adt, subs) if !adt.is_union() => (adt, subs), + _ => return, + }; + // If the current self type doesn't implement Copy (due to generic constraints), search to see if + // there's a Copy impl for any instance of the adt. + if !is_copy(cx, ty) { + if ty_subs.non_erasable_generics().next().is_some() { + let has_copy_impl = cx + .tcx + .all_local_trait_impls(LOCAL_CRATE) + .get(©_id) + .map_or(false, |impls| { + impls + .iter() + .any(|&id| matches!(cx.tcx.type_of(id).kind(), ty::Adt(adt, _) if ty_adt.did == adt.did)) + }); + if !has_copy_impl { + return; + } + } else { return; } - - match *ty.kind() { - ty::Adt(def, _) if def.is_union() => return, - - // Some types are not Clone by default but could be cloned “by hand” if necessary - ty::Adt(def, substs) => { - for variant in &def.variants { - for field in &variant.fields { - if let ty::FnDef(..) = field.ty(cx.tcx, substs).kind() { - return; - } - } - for subst in substs { - if let ty::subst::GenericArgKind::Type(subst) = subst.unpack() { - if let ty::Param(_) = subst.kind() { - return; - } - } - } - } - }, - _ => (), - } - - span_lint_and_note( - cx, - EXPL_IMPL_CLONE_ON_COPY, - item.span, - "you are implementing `Clone` explicitly on a `Copy` type", - Some(item.span), - "consider deriving `Clone` or removing `Copy`", - ); } + // Derive constrains all generic types to requiring Clone. Check if any type is not constrained for + // this impl. + if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) { + return; + } + + span_lint_and_note( + cx, + EXPL_IMPL_CLONE_ON_COPY, + item.span, + "you are implementing `Clone` explicitly on a `Copy` type", + Some(item.span), + "consider deriving `Clone` or removing `Copy`", + ); } /// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint. diff --git a/src/tools/clippy/clippy_lints/src/disallowed_method.rs b/src/tools/clippy/clippy_lints/src/disallowed_method.rs index 56dc6d18a5..ded0a0fff5 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_method.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_method.rs @@ -1,4 +1,5 @@ -use crate::utils::{fn_def_id, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::fn_def_id; use rustc_data_structures::fx::FxHashSet; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 90b02d52f8..fb53b55ebd 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -1,7 +1,6 @@ -use crate::utils::{ - implements_trait, is_entrypoint_fn, is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args, - return_ty, span_lint, span_lint_and_note, -}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; +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; use itertools::Itertools; use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind}; @@ -12,7 +11,7 @@ use rustc_errors::emitter::EmitterWriter; use rustc_errors::Handler; use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::{Expr, ExprKind, QPath}; +use rustc_hir::{AnonConst, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; @@ -584,7 +583,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) { let returns_nothing = match &sig.decl.output { FnRetTy::Default(..) => true, FnRetTy::Ty(ty) if ty.kind.is_unit() => true, - _ => false, + FnRetTy::Ty(_) => false, }; if returns_nothing && !is_async && !block.stmts.is_empty() { @@ -711,16 +710,22 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { // check for `begin_panic` if_chain! { - if let ExprKind::Call(ref func_expr, _) = expr.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.kind; + if let ExprKind::Call(func_expr, _) = expr.kind; + if let ExprKind::Path(QPath::Resolved(_, path)) = func_expr.kind; if let Some(path_def_id) = path.res.opt_def_id(); if match_panic_def_id(self.cx, path_def_id); if is_expn_of(expr.span, "unreachable").is_none(); + if !is_expn_of_debug_assertions(expr.span); then { self.panic_span = Some(expr.span); } } + // check for `assert_eq` or `assert_ne` + if is_expn_of(expr.span, "assert_eq").is_some() || is_expn_of(expr.span, "assert_ne").is_some() { + self.panic_span = Some(expr.span); + } + // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { let reciever_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs(); @@ -735,7 +740,15 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { intravisit::walk_expr(self, expr); } + // Panics in const blocks will cause compilation to fail. + fn visit_anon_const(&mut self, _: &'tcx AnonConst) {} + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } } + +fn is_expn_of_debug_assertions(span: Span) -> bool { + const MACRO_NAMES: &[&str] = &["debug_assert", "debug_assert_eq", "debug_assert_ne"]; + MACRO_NAMES.iter().any(|name| is_expn_of(span, name).is_some()) +} diff --git a/src/tools/clippy/clippy_lints/src/double_comparison.rs b/src/tools/clippy/clippy_lints/src/double_comparison.rs index 19f56195ec..58543ae6e4 100644 --- a/src/tools/clippy/clippy_lints/src/double_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/double_comparison.rs @@ -1,13 +1,14 @@ //! Lint on unnecessary double comparisons. Some examples: +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::eq_expr_value; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use crate::utils::{eq_expr_value, snippet_with_applicability, span_lint_and_sugg}; - declare_clippy_lint! { /// **What it does:** Checks for double comparisons that could be simplified to a single expression. /// @@ -46,7 +47,7 @@ impl<'tcx> DoubleComparisons { }, _ => return, }; - if !(eq_expr_value(cx, &llhs, &rlhs) && eq_expr_value(cx, &lrhs, &rrhs)) { + if !(eq_expr_value(cx, llhs, rlhs) && eq_expr_value(cx, lrhs, rrhs)) { return; } macro_rules! lint_double_comparison { @@ -87,7 +88,7 @@ impl<'tcx> DoubleComparisons { impl<'tcx> LateLintPass<'tcx> for DoubleComparisons { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.kind { + if let ExprKind::Binary(ref kind, lhs, rhs) = expr.kind { Self::check_binop(cx, kind.node, lhs, rhs, expr.span); } } diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs index abbcaf43f4..e4e4a93b01 100644 --- a/src/tools/clippy/clippy_lints/src/double_parens.rs +++ b/src/tools/clippy/clippy_lints/src/double_parens.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -50,7 +50,7 @@ impl EarlyLintPass for DoubleParens { match expr.kind { ExprKind::Paren(ref in_paren) => match in_paren.kind { ExprKind::Paren(_) | ExprKind::Tup(_) => { - span_lint(cx, DOUBLE_PARENS, expr.span, &msg); + span_lint(cx, DOUBLE_PARENS, expr.span, msg); }, _ => {}, }, @@ -58,7 +58,7 @@ impl EarlyLintPass for DoubleParens { if params.len() == 1 { let param = ¶ms[0]; if let ExprKind::Paren(_) = param.kind { - span_lint(cx, DOUBLE_PARENS, param.span, &msg); + span_lint(cx, DOUBLE_PARENS, param.span, msg); } } }, @@ -66,7 +66,7 @@ impl EarlyLintPass for DoubleParens { if params.len() == 2 { let param = ¶ms[1]; if let ExprKind::Paren(_) = param.kind { - span_lint(cx, DOUBLE_PARENS, param.span, &msg); + span_lint(cx, DOUBLE_PARENS, param.span, msg); } } }, diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index 2aea00d883..b5b2976063 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,6 @@ -use crate::utils::{is_copy, match_def_path, paths, span_lint_and_note}; +use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::ty::is_copy; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -111,7 +113,7 @@ declare_lint_pass!(DropForgetRef => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COP impl<'tcx> LateLintPass<'tcx> for DropForgetRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Call(ref path, ref args) = expr.kind; + if let ExprKind::Call(path, args) = expr.kind; if let ExprKind::Path(ref qpath) = path.kind; if args.len() == 1; if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); diff --git a/src/tools/clippy/clippy_lints/src/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/duration_subsec.rs index c0529a34cc..529807770f 100644 --- a/src/tools/clippy/clippy_lints/src/duration_subsec.rs +++ b/src/tools/clippy/clippy_lints/src/duration_subsec.rs @@ -1,3 +1,5 @@ +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::match_type; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -6,8 +8,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; use crate::consts::{constant, Constant}; -use crate::utils::paths; -use crate::utils::{match_type, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::paths; declare_clippy_lint! { /// **What it does:** Checks for calculation of subsecond microseconds or milliseconds @@ -41,8 +43,8 @@ declare_lint_pass!(DurationSubsec => [DURATION_SUBSEC]); impl<'tcx> LateLintPass<'tcx> for DurationSubsec { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.kind; - if let ExprKind::MethodCall(ref method_path, _ , ref args, _) = left.kind; + if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, left, right) = expr.kind; + if let ExprKind::MethodCall(method_path, _ , args, _) = left.kind; if match_type(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), &paths::DURATION); if let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right); then { diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs index 95123e6ff6..26984df953 100644 --- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs +++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs @@ -1,12 +1,11 @@ //! Lint on if expressions with an else if, but without a final else branch. +use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::span_lint_and_help; - declare_clippy_lint! { /// **What it does:** Checks for usage of if expressions with an `else if` branch, /// but without a final `else` branch. diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs index 077c3b75fb..c92984a983 100644 --- a/src/tools/clippy/clippy_lints/src/empty_enum.rs +++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs @@ -1,6 +1,6 @@ //! lint when there is an enum with no variants -use crate::utils::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index 5557596992..8db5050a5a 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -1,15 +1,19 @@ -use crate::utils::SpanlessEq; -use crate::utils::{get_item_name, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt}; -use crate::utils::{snippet_with_applicability, span_lint_and_then}; -use if_chain::if_chain; +use clippy_utils::{ + can_move_expr_to_closure_no_visit, + diagnostics::span_lint_and_sugg, + is_expr_final_block_expr, is_expr_used_or_unified, match_def_path, paths, peel_hir_expr_while, + source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context}, + SpanlessEq, +}; use rustc_errors::Applicability; -use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{BorrowKind, Expr, ExprKind, UnOp}; +use rustc_hir::{ + intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}, + Block, Expr, ExprKind, Guard, HirId, Local, Stmt, StmtKind, UnOp, +}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; -use rustc_span::sym; +use rustc_span::{Span, SyntaxContext, DUMMY_SP}; +use std::fmt::Write; declare_clippy_lint! { /// **What it does:** Checks for uses of `contains_key` + `insert` on `HashMap` @@ -17,15 +21,14 @@ declare_clippy_lint! { /// /// **Why is this bad?** Using `entry` is more efficient. /// - /// **Known problems:** Some false negatives, eg.: + /// **Known problems:** The suggestion may have type inference errors in some cases. e.g. /// ```rust - /// # use std::collections::HashMap; - /// # let mut map = HashMap::new(); - /// # let v = 1; - /// # let k = 1; - /// if !map.contains_key(&k) { - /// map.insert(k.clone(), v); - /// } + /// let mut map = std::collections::HashMap::new(); + /// let _ = if !map.contains_key(&0) { + /// map.insert(0, 0) + /// } else { + /// None + /// }; /// ``` /// /// **Example:** @@ -54,132 +57,584 @@ declare_clippy_lint! { declare_lint_pass!(HashMapPass => [MAP_ENTRY]); impl<'tcx> LateLintPass<'tcx> for HashMapPass { + #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.kind { - if let ExprKind::Unary(UnOp::Not, ref check) = check.kind { - if let Some((ty, map, key)) = check_cond(cx, check) { - // in case of `if !m.contains_key(&k) { m.insert(k, v); }` - // we can give a better error message - let sole_expr = { - else_block.is_none() - && if let ExprKind::Block(ref then_block, _) = then_block.kind { - (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1 - } else { - true - } - // XXXManishearth we can also check for if/else blocks containing `None`. - }; - - let mut visitor = InsertVisitor { - cx, - span: expr.span, - ty, - map, - key, - sole_expr, - }; - - walk_expr(&mut visitor, &**then_block); + let (cond_expr, then_expr, else_expr) = match expr.kind { + ExprKind::If(c, t, e) => (c, t, e), + _ => return, + }; + let (map_ty, contains_expr) = match try_parse_contains(cx, cond_expr) { + Some(x) => x, + None => return, + }; + + let then_search = match find_insert_calls(cx, &contains_expr, then_expr) { + Some(x) => x, + None => return, + }; + + let mut app = Applicability::MachineApplicable; + let map_str = snippet_with_context(cx, contains_expr.map.span, contains_expr.call_ctxt, "..", &mut app).0; + let key_str = snippet_with_context(cx, contains_expr.key.span, contains_expr.call_ctxt, "..", &mut app).0; + let sugg = if let Some(else_expr) = else_expr { + let else_search = match find_insert_calls(cx, &contains_expr, else_expr) { + Some(search) => search, + None => return, + }; + + if then_search.edits.is_empty() && else_search.edits.is_empty() { + // No insertions + return; + } else if then_search.edits.is_empty() || else_search.edits.is_empty() { + // if .. { insert } else { .. } or if .. { .. } else { insert } + let ((then_str, entry_kind), else_str) = match (else_search.edits.is_empty(), contains_expr.negated) { + (true, true) => ( + then_search.snippet_vacant(cx, then_expr.span, &mut app), + snippet_with_applicability(cx, else_expr.span, "{ .. }", &mut app), + ), + (true, false) => ( + then_search.snippet_occupied(cx, then_expr.span, &mut app), + snippet_with_applicability(cx, else_expr.span, "{ .. }", &mut app), + ), + (false, true) => ( + else_search.snippet_occupied(cx, else_expr.span, &mut app), + snippet_with_applicability(cx, then_expr.span, "{ .. }", &mut app), + ), + (false, false) => ( + else_search.snippet_vacant(cx, else_expr.span, &mut app), + snippet_with_applicability(cx, then_expr.span, "{ .. }", &mut app), + ), + }; + format!( + "if let {}::{} = {}.entry({}) {} else {}", + map_ty.entry_path(), + entry_kind, + map_str, + key_str, + then_str, + else_str, + ) + } else { + // if .. { insert } else { insert } + let ((then_str, then_entry), (else_str, else_entry)) = if contains_expr.negated { + ( + then_search.snippet_vacant(cx, then_expr.span, &mut app), + else_search.snippet_occupied(cx, else_expr.span, &mut app), + ) + } else { + ( + then_search.snippet_occupied(cx, then_expr.span, &mut app), + else_search.snippet_vacant(cx, else_expr.span, &mut app), + ) + }; + let indent_str = snippet_indent(cx, expr.span); + let indent_str = indent_str.as_deref().unwrap_or(""); + format!( + "match {}.entry({}) {{\n{indent} {entry}::{} => {}\n\ + {indent} {entry}::{} => {}\n{indent}}}", + map_str, + key_str, + then_entry, + reindent_multiline(then_str.into(), true, Some(4 + indent_str.len())), + else_entry, + reindent_multiline(else_str.into(), true, Some(4 + indent_str.len())), + entry = map_ty.entry_path(), + indent = indent_str, + ) + } + } else { + if then_search.edits.is_empty() { + // no insertions + return; + } + + // if .. { insert } + if !then_search.allow_insert_closure { + let (body_str, entry_kind) = if contains_expr.negated { + then_search.snippet_vacant(cx, then_expr.span, &mut app) + } else { + then_search.snippet_occupied(cx, then_expr.span, &mut app) + }; + format!( + "if let {}::{} = {}.entry({}) {}", + map_ty.entry_path(), + entry_kind, + map_str, + key_str, + body_str, + ) + } else if let Some(insertion) = then_search.as_single_insertion() { + let value_str = snippet_with_context(cx, insertion.value.span, then_expr.span.ctxt(), "..", &mut app).0; + if contains_expr.negated { + if insertion.value.can_have_side_effects() { + format!("{}.entry({}).or_insert_with(|| {});", map_str, key_str, value_str) + } else { + format!("{}.entry({}).or_insert({});", map_str, key_str, value_str) + } + } else { + // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here. + // This would need to be a different lint. + return; } - } else if let Some(ref else_block) = *else_block { - if let Some((ty, map, key)) = check_cond(cx, check) { - let mut visitor = InsertVisitor { - cx, - span: expr.span, - ty, - map, - key, - sole_expr: false, - }; - - walk_expr(&mut visitor, else_block); + } else { + let block_str = then_search.snippet_closure(cx, then_expr.span, &mut app); + if contains_expr.negated { + format!("{}.entry({}).or_insert_with(|| {});", map_str, key_str, block_str) + } else { + // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here. + // This would need to be a different lint. + return; } } - } + }; + + span_lint_and_sugg( + cx, + MAP_ENTRY, + expr.span, + &format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()), + "try this", + sugg, + app, + ); } } -fn check_cond<'a>(cx: &LateContext<'_>, check: &'a Expr<'a>) -> Option<(&'static str, &'a Expr<'a>, &'a Expr<'a>)> { - if_chain! { - if let ExprKind::MethodCall(ref path, _, ref params, _) = check.kind; - if params.len() >= 2; - if path.ident.name == sym!(contains_key); - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref key) = params[1].kind; - then { - let map = ¶ms[0]; - let obj_ty = cx.typeck_results().expr_ty(map).peel_refs(); +#[derive(Clone, Copy)] +enum MapType { + Hash, + BTree, +} +impl MapType { + fn name(self) -> &'static str { + match self { + Self::Hash => "HashMap", + Self::BTree => "BTreeMap", + } + } + fn entry_path(self) -> &'static str { + match self { + Self::Hash => "std::collections::hash_map::Entry", + Self::BTree => "std::collections::btree_map::Entry", + } + } +} - return if match_type(cx, obj_ty, &paths::BTREEMAP) { - Some(("BTreeMap", map, key)) - } - else if is_type_diagnostic_item(cx, obj_ty, sym::hashmap_type) { - Some(("HashMap", map, key)) - } - else { - None +struct ContainsExpr<'tcx> { + negated: bool, + map: &'tcx Expr<'tcx>, + key: &'tcx Expr<'tcx>, + call_ctxt: SyntaxContext, +} +fn try_parse_contains(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(MapType, ContainsExpr<'tcx>)> { + let mut negated = false; + let expr = peel_hir_expr_while(expr, |e| match e.kind { + ExprKind::Unary(UnOp::Not, e) => { + negated = !negated; + Some(e) + }, + _ => None, + }); + match expr.kind { + ExprKind::MethodCall( + _, + _, + [map, Expr { + kind: ExprKind::AddrOf(_, _, key), + span: key_span, + .. + }], + _, + ) if key_span.ctxt() == expr.span.ctxt() => { + let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; + let expr = ContainsExpr { + negated, + map, + key, + call_ctxt: expr.span.ctxt(), }; + if match_def_path(cx, id, &paths::BTREEMAP_CONTAINS_KEY) { + Some((MapType::BTree, expr)) + } else if match_def_path(cx, id, &paths::HASHMAP_CONTAINS_KEY) { + Some((MapType::Hash, expr)) + } else { + None + } + }, + _ => None, + } +} + +struct InsertExpr<'tcx> { + map: &'tcx Expr<'tcx>, + key: &'tcx Expr<'tcx>, + value: &'tcx Expr<'tcx>, +} +fn try_parse_insert(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> { + if let ExprKind::MethodCall(_, _, [map, key, value], _) = expr.kind { + let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; + if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) { + Some(InsertExpr { map, key, value }) + } else { + None } + } else { + None } +} - None +/// An edit that will need to be made to move the expression to use the entry api +#[derive(Clone, Copy)] +enum Edit<'tcx> { + /// A semicolon that needs to be removed. Used to create a closure for `insert_with`. + RemoveSemi(Span), + /// An insertion into the map. + Insertion(Insertion<'tcx>), +} +impl Edit<'tcx> { + fn as_insertion(self) -> Option<Insertion<'tcx>> { + if let Self::Insertion(i) = self { Some(i) } else { None } + } +} +#[derive(Clone, Copy)] +struct Insertion<'tcx> { + call: &'tcx Expr<'tcx>, + value: &'tcx Expr<'tcx>, } -struct InsertVisitor<'a, 'tcx, 'b> { - cx: &'a LateContext<'tcx>, - span: Span, - ty: &'static str, - map: &'b Expr<'b>, - key: &'b Expr<'b>, - sole_expr: bool, +/// This visitor needs to do a multiple things: +/// * Find all usages of the map. An insertion can only be made before any other usages of the map. +/// * Determine if there's an insertion using the same key. There's no need for the entry api +/// otherwise. +/// * Determine if the final statement executed is an insertion. This is needed to use +/// `or_insert_with`. +/// * Determine if there's any sub-expression that can't be placed in a closure. +/// * Determine if there's only a single insert statement. `or_insert` can be used in this case. +#[allow(clippy::struct_excessive_bools)] +struct InsertSearcher<'cx, 'tcx> { + cx: &'cx LateContext<'tcx>, + /// The map expression used in the contains call. + map: &'tcx Expr<'tcx>, + /// The key expression used in the contains call. + key: &'tcx Expr<'tcx>, + /// The context of the top level block. All insert calls must be in the same context. + ctxt: SyntaxContext, + /// Whether this expression can be safely moved into a closure. + allow_insert_closure: bool, + /// Whether this expression can use the entry api. + can_use_entry: bool, + /// Whether this expression is the final expression in this code path. This may be a statement. + in_tail_pos: bool, + // Is this expression a single insert. A slightly better suggestion can be made in this case. + is_single_insert: bool, + /// If the visitor has seen the map being used. + is_map_used: bool, + /// The locations where changes need to be made for the suggestion. + edits: Vec<Edit<'tcx>>, + /// A stack of loops the visitor is currently in. + loops: Vec<HirId>, } +impl<'tcx> InsertSearcher<'_, 'tcx> { + /// Visit the expression as a branch in control flow. Multiple insert calls can be used, but + /// only if they are on separate code paths. This will return whether the map was used in the + /// given expression. + fn visit_cond_arm(&mut self, e: &'tcx Expr<'_>) -> bool { + let is_map_used = self.is_map_used; + let in_tail_pos = self.in_tail_pos; + self.visit_expr(e); + let res = self.is_map_used; + self.is_map_used = is_map_used; + self.in_tail_pos = in_tail_pos; + res + } -impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { - type Map = Map<'tcx>; + /// Visits an expression which is not itself in a tail position, but other sibling expressions + /// may be. e.g. if conditions + fn visit_non_tail_expr(&mut self, e: &'tcx Expr<'_>) { + let in_tail_pos = self.in_tail_pos; + self.in_tail_pos = false; + self.visit_expr(e); + self.in_tail_pos = in_tail_pos; + } +} +impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { + type Map = ErasedMap<'tcx>; + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } + + fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { + match stmt.kind { + StmtKind::Semi(e) => { + self.visit_expr(e); + + if self.in_tail_pos && self.allow_insert_closure { + // The spans are used to slice the top level expression into multiple parts. This requires that + // they all come from the same part of the source code. + if stmt.span.ctxt() == self.ctxt && e.span.ctxt() == self.ctxt { + self.edits + .push(Edit::RemoveSemi(stmt.span.trim_start(e.span).unwrap_or(DUMMY_SP))); + } else { + self.allow_insert_closure = false; + } + } + }, + StmtKind::Expr(e) => self.visit_expr(e), + StmtKind::Local(Local { init: Some(e), .. }) => { + self.allow_insert_closure &= !self.in_tail_pos; + self.in_tail_pos = false; + self.is_single_insert = false; + self.visit_expr(e); + }, + _ => { + self.allow_insert_closure &= !self.in_tail_pos; + self.is_single_insert = false; + }, + } + } + + fn visit_block(&mut self, block: &'tcx Block<'_>) { + // If the block is in a tail position, then the last expression (possibly a statement) is in the + // tail position. The rest, however, are not. + match (block.stmts, block.expr) { + ([], None) => { + self.allow_insert_closure &= !self.in_tail_pos; + }, + ([], Some(expr)) => self.visit_expr(expr), + (stmts, Some(expr)) => { + let in_tail_pos = self.in_tail_pos; + self.in_tail_pos = false; + for stmt in stmts { + self.visit_stmt(stmt); + } + self.in_tail_pos = in_tail_pos; + self.visit_expr(expr); + }, + ([stmts @ .., stmt], None) => { + let in_tail_pos = self.in_tail_pos; + self.in_tail_pos = false; + for stmt in stmts { + self.visit_stmt(stmt); + } + self.in_tail_pos = in_tail_pos; + self.visit_stmt(stmt); + }, + } + } fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::MethodCall(ref path, _, ref params, _) = expr.kind; - if params.len() == 3; - if path.ident.name == sym!(insert); - if get_item_name(self.cx, self.map) == get_item_name(self.cx, ¶ms[0]); - if SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]); - if snippet_opt(self.cx, self.map.span) == snippet_opt(self.cx, params[0].span); - then { - span_lint_and_then(self.cx, MAP_ENTRY, self.span, - &format!("usage of `contains_key` followed by `insert` on a `{}`", self.ty), |diag| { - if self.sole_expr { - let mut app = Applicability::MachineApplicable; - let help = format!("{}.entry({}).or_insert({});", - snippet_with_applicability(self.cx, self.map.span, "map", &mut app), - snippet_with_applicability(self.cx, params[1].span, "..", &mut app), - snippet_with_applicability(self.cx, params[2].span, "..", &mut app)); - - diag.span_suggestion( - self.span, - "consider using", - help, - Applicability::MachineApplicable, // snippet - ); + if !self.can_use_entry { + return; + } + + match try_parse_insert(self.cx, expr) { + Some(insert_expr) if SpanlessEq::new(self.cx).eq_expr(self.map, insert_expr.map) => { + // Multiple inserts, inserts with a different key, and inserts from a macro can't use the entry api. + if self.is_map_used + || !SpanlessEq::new(self.cx).eq_expr(self.key, insert_expr.key) + || expr.span.ctxt() != self.ctxt + { + self.can_use_entry = false; + return; + } + + self.edits.push(Edit::Insertion(Insertion { + call: expr, + value: insert_expr.value, + })); + self.is_map_used = true; + self.allow_insert_closure &= self.in_tail_pos; + + // The value doesn't affect whether there is only a single insert expression. + let is_single_insert = self.is_single_insert; + self.visit_non_tail_expr(insert_expr.value); + self.is_single_insert = is_single_insert; + }, + _ if SpanlessEq::new(self.cx).eq_expr(self.map, expr) => { + self.is_map_used = true; + }, + _ => match expr.kind { + ExprKind::If(cond_expr, then_expr, Some(else_expr)) => { + self.is_single_insert = false; + self.visit_non_tail_expr(cond_expr); + // Each branch may contain it's own insert expression. + let mut is_map_used = self.visit_cond_arm(then_expr); + is_map_used |= self.visit_cond_arm(else_expr); + self.is_map_used = is_map_used; + }, + ExprKind::Match(scrutinee_expr, arms, _) => { + self.is_single_insert = false; + self.visit_non_tail_expr(scrutinee_expr); + // Each branch may contain it's own insert expression. + let mut is_map_used = self.is_map_used; + for arm in arms { + if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard { + self.visit_non_tail_expr(guard) + } + is_map_used |= self.visit_cond_arm(arm.body); } - else { - let help = format!("consider using `{}.entry({})`", - snippet(self.cx, self.map.span, "map"), - snippet(self.cx, params[1].span, "..")); - - diag.span_label( - self.span, - &help, - ); + self.is_map_used = is_map_used; + }, + ExprKind::Loop(block, ..) => { + self.loops.push(expr.hir_id); + self.is_single_insert = false; + self.allow_insert_closure &= !self.in_tail_pos; + // Don't allow insertions inside of a loop. + let edit_len = self.edits.len(); + self.visit_block(block); + if self.edits.len() != edit_len { + self.can_use_entry = false; } - }); - } + self.loops.pop(); + }, + ExprKind::Block(block, _) => self.visit_block(block), + ExprKind::InlineAsm(_) | ExprKind::LlvmInlineAsm(_) => { + self.can_use_entry = false; + }, + _ => { + self.allow_insert_closure &= !self.in_tail_pos; + self.allow_insert_closure &= can_move_expr_to_closure_no_visit(self.cx, expr, &self.loops); + // Sub expressions are no longer in the tail position. + self.is_single_insert = false; + self.in_tail_pos = false; + walk_expr(self, expr); + }, + }, } + } +} + +struct InsertSearchResults<'tcx> { + edits: Vec<Edit<'tcx>>, + allow_insert_closure: bool, + is_single_insert: bool, +} +impl InsertSearchResults<'tcx> { + fn as_single_insertion(&self) -> Option<Insertion<'tcx>> { + self.is_single_insert.then(|| self.edits[0].as_insertion().unwrap()) + } - if !self.sole_expr { - walk_expr(self, expr); + fn snippet( + &self, + cx: &LateContext<'_>, + mut span: Span, + app: &mut Applicability, + write_wrapped: impl Fn(&mut String, Insertion<'_>, SyntaxContext, &mut Applicability), + ) -> String { + let ctxt = span.ctxt(); + let mut res = String::new(); + for insertion in self.edits.iter().filter_map(|e| e.as_insertion()) { + res.push_str(&snippet_with_applicability( + cx, + span.until(insertion.call.span), + "..", + app, + )); + if is_expr_used_or_unified(cx.tcx, insertion.call) { + write_wrapped(&mut res, insertion, ctxt, app); + } else { + let _ = write!( + res, + "e.insert({})", + snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0 + ); + } + span = span.trim_start(insertion.call.span).unwrap_or(DUMMY_SP); } + res.push_str(&snippet_with_applicability(cx, span, "..", app)); + res } - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None + + fn snippet_occupied(&self, cx: &LateContext<'_>, span: Span, app: &mut Applicability) -> (String, &'static str) { + ( + self.snippet(cx, span, app, |res, insertion, ctxt, app| { + // Insertion into a map would return `Some(&mut value)`, but the entry returns `&mut value` + let _ = write!( + res, + "Some(e.insert({}))", + snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0 + ); + }), + "Occupied(mut e)", + ) } + + fn snippet_vacant(&self, cx: &LateContext<'_>, span: Span, app: &mut Applicability) -> (String, &'static str) { + ( + self.snippet(cx, span, app, |res, insertion, ctxt, app| { + // Insertion into a map would return `None`, but the entry returns a mutable reference. + let _ = if is_expr_final_block_expr(cx.tcx, insertion.call) { + write!( + res, + "e.insert({});\n{}None", + snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0, + snippet_indent(cx, insertion.call.span).as_deref().unwrap_or(""), + ) + } else { + write!( + res, + "{{ e.insert({}); None }}", + snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0, + ) + }; + }), + "Vacant(e)", + ) + } + + fn snippet_closure(&self, cx: &LateContext<'_>, mut span: Span, app: &mut Applicability) -> String { + let ctxt = span.ctxt(); + let mut res = String::new(); + for edit in &self.edits { + match *edit { + Edit::Insertion(insertion) => { + // Cut out the value from `map.insert(key, value)` + res.push_str(&snippet_with_applicability( + cx, + span.until(insertion.call.span), + "..", + app, + )); + res.push_str(&snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0); + span = span.trim_start(insertion.call.span).unwrap_or(DUMMY_SP); + }, + Edit::RemoveSemi(semi_span) => { + // Cut out the semicolon. This allows the value to be returned from the closure. + res.push_str(&snippet_with_applicability(cx, span.until(semi_span), "..", app)); + span = span.trim_start(semi_span).unwrap_or(DUMMY_SP); + }, + } + } + res.push_str(&snippet_with_applicability(cx, span, "..", app)); + res + } +} + +fn find_insert_calls( + cx: &LateContext<'tcx>, + contains_expr: &ContainsExpr<'tcx>, + expr: &'tcx Expr<'_>, +) -> Option<InsertSearchResults<'tcx>> { + let mut s = InsertSearcher { + cx, + map: contains_expr.map, + key: contains_expr.key, + ctxt: expr.span.ctxt(), + edits: Vec::new(), + is_map_used: false, + allow_insert_closure: true, + can_use_entry: true, + in_tail_pos: true, + is_single_insert: true, + loops: Vec::new(), + }; + s.visit_expr(expr); + let allow_insert_closure = s.allow_insert_closure; + let is_single_insert = s.is_single_insert; + let edits = s.edits; + s.can_use_entry.then(|| InsertSearchResults { + edits, + allow_insert_closure, + is_single_insert, + }) } diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index aa235642ac..7a98ae39d3 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -2,7 +2,7 @@ //! don't fit into an `i32` use crate::consts::{miri_to_const, Constant}; -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::util::IntTypeExt; diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index 67a4635385..0ecc0bc3eb 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -1,7 +1,8 @@ //! lint on enum variants that are prefixed or suffixed by the same characters -use crate::utils::{camel_case, is_present_in_source}; -use crate::utils::{span_lint, span_lint_and_help}; +use clippy_utils::camel_case; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::source::is_present_in_source; use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind}; use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs index 6308f6e2e7..90f391b5f5 100644 --- a/src/tools/clippy/clippy_lints/src/eq_op.rs +++ b/src/tools/clippy/clippy_lints/src/eq_op.rs @@ -1,7 +1,7 @@ -use crate::utils::{ - ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, implements_trait, in_macro, is_copy, is_expn_of, - multispan_sugg, snippet, span_lint, span_lint_and_then, -}; +use clippy_utils::diagnostics::{multispan_sugg, span_lint, span_lint_and_then}; +use clippy_utils::source::snippet; +use clippy_utils::ty::{implements_trait, is_copy}; +use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, in_macro, is_expn_of}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, StmtKind}; @@ -65,12 +65,12 @@ const ASSERT_MACRO_NAMES: [&str; 4] = ["assert_eq", "assert_ne", "debug_assert_e impl<'tcx> LateLintPass<'tcx> for EqOp { #[allow(clippy::similar_names, clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Block(ref block, _) = e.kind { + if let ExprKind::Block(block, _) = e.kind { for stmt in block.stmts { for amn in &ASSERT_MACRO_NAMES { if_chain! { if is_expn_of(stmt.span, amn).is_some(); - if let StmtKind::Semi(ref matchexpr) = stmt.kind; + if let StmtKind::Semi(matchexpr) = stmt.kind; if let Some(macro_args) = higher::extract_assert_macro_args(matchexpr); if macro_args.len() == 2; let (lhs, rhs) = (macro_args[0], macro_args[1]); @@ -88,12 +88,12 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { } } } - if let ExprKind::Binary(op, ref left, ref right) = e.kind { + if let ExprKind::Binary(op, left, right) = e.kind { if e.span.from_expansion() { return; } let macro_with_not_op = |expr_kind: &ExprKind<'_>| { - if let ExprKind::Unary(_, ref expr) = *expr_kind { + if let ExprKind::Unary(_, expr) = *expr_kind { in_macro(expr.span) } else { false @@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { // do not suggest to dereference literals (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {}, // &foo == &bar - (&ExprKind::AddrOf(BorrowKind::Ref, _, ref l), &ExprKind::AddrOf(BorrowKind::Ref, _, ref r)) => { + (&ExprKind::AddrOf(BorrowKind::Ref, _, l), &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => { let lty = cx.typeck_results().expr_ty(l); let rty = cx.typeck_results().expr_ty(r); let lcpy = is_copy(cx, lty); @@ -198,7 +198,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { } }, // &foo == bar - (&ExprKind::AddrOf(BorrowKind::Ref, _, ref l), _) => { + (&ExprKind::AddrOf(BorrowKind::Ref, _, l), _) => { let lty = cx.typeck_results().expr_ty(l); let lcpy = is_copy(cx, lty); if (requires_ref || lcpy) @@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { } }, // foo == &bar - (_, &ExprKind::AddrOf(BorrowKind::Ref, _, ref r)) => { + (_, &ExprKind::AddrOf(BorrowKind::Ref, _, r)) => { let rty = cx.typeck_results().expr_ty(r); let rcpy = is_copy(cx, rty); if (requires_ref || rcpy) diff --git a/src/tools/clippy/clippy_lints/src/erasing_op.rs b/src/tools/clippy/clippy_lints/src/erasing_op.rs index dbd1ff514f..f95ca86a2d 100644 --- a/src/tools/clippy/clippy_lints/src/erasing_op.rs +++ b/src/tools/clippy/clippy_lints/src/erasing_op.rs @@ -1,10 +1,10 @@ +use clippy_utils::diagnostics::span_lint; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use crate::consts::{constant_simple, Constant}; -use crate::utils::span_lint; declare_clippy_lint! { /// **What it does:** Checks for erasing operations, e.g., `x * 0`. @@ -34,7 +34,7 @@ impl<'tcx> LateLintPass<'tcx> for ErasingOp { if e.span.from_expansion() { return; } - if let ExprKind::Binary(ref cmp, ref left, ref right) = e.kind { + if let ExprKind::Binary(ref cmp, left, right) = e.kind { match cmp.node { BinOpKind::Mul | BinOpKind::BitAnd => { check(cx, left, e.span); diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 9721675754..3581ab4190 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -1,3 +1,5 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::contains_ty; use rustc_hir::intravisit; use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node}; use rustc_infer::infer::TyCtxtInferExt; @@ -11,8 +13,6 @@ use rustc_target::abi::LayoutOf; use rustc_target::spec::abi::Abi; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; -use crate::utils::{contains_ty, span_lint}; - #[derive(Copy, Clone)] pub struct BoxedLocal { pub too_large_for_stack: u64, @@ -186,7 +186,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } - fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) { } + fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {} } impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index c461732fd3..2f1aa53236 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -1,3 +1,9 @@ +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::{is_adjusted, iter_input_pats}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath}; @@ -6,13 +12,6 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{ - implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_sugg, span_lint_and_then, - type_is_unsafe_function, -}; -use clippy_utils::higher; -use clippy_utils::higher::VecArgs; - declare_clippy_lint! { /// **What it does:** Checks for closures which just call another function where /// the function can be called directly. `unsafe` functions or calls where types @@ -88,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { } fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.kind { + if let ExprKind::Closure(_, decl, eid, _, _) = expr.kind { let body = cx.tcx.hir().body(eid); let ex = &body.value; @@ -110,7 +109,7 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { } if_chain!( - if let ExprKind::Call(ref caller, ref args) = ex.kind; + if let ExprKind::Call(caller, args) = ex.kind; if let ExprKind::Path(_) = caller.kind; @@ -143,7 +142,7 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { ); if_chain!( - if let ExprKind::MethodCall(ref path, _, ref args, _) = ex.kind; + if let ExprKind::MethodCall(path, _, args, _) = ex.kind; // Not the same number of arguments, there is no way the closure is the same as the function return; if args.len() == decl.inputs.len(); @@ -179,7 +178,7 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a let actual_type_of_self = &cx.typeck_results().node_type(self_arg.hir_id); if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) { - if match_borrow_depth(expected_type_of_self, &actual_type_of_self) + if match_borrow_depth(expected_type_of_self, actual_type_of_self) && implements_trait(cx, actual_type_of_self, trait_id, &[]) { return Some(cx.tcx.def_path_str(trait_id)); @@ -188,8 +187,8 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a cx.tcx.impl_of_method(method_def_id).and_then(|_| { //a type may implicitly implement other type's methods (e.g. Deref) - if match_types(expected_type_of_self, &actual_type_of_self) { - return Some(get_type_name(cx, &actual_type_of_self)); + if match_types(expected_type_of_self, actual_type_of_self) { + return Some(get_type_name(cx, actual_type_of_self)); } None }) @@ -197,7 +196,7 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a fn match_borrow_depth(lhs: Ty<'_>, rhs: Ty<'_>) -> bool { match (&lhs.kind(), &rhs.kind()) { - (ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_borrow_depth(&t1, &t2), + (ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_borrow_depth(t1, t2), (l, r) => !matches!((l, r), (ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _))), } } @@ -219,7 +218,7 @@ fn match_types(lhs: Ty<'_>, rhs: Ty<'_>) -> bool { fn get_type_name(cx: &LateContext<'_>, ty: Ty<'_>) -> String { match ty.kind() { ty::Adt(t, _) => cx.tcx.def_path_str(t.did), - ty::Ref(_, r, _) => get_type_name(cx, &r), + ty::Ref(_, r, _) => get_type_name(cx, r), _ => ty.to_string(), } } @@ -231,7 +230,7 @@ fn compare_inputs( for (closure_input, function_arg) in closure_inputs.zip(call_args) { if let PatKind::Binding(_, _, ident, _) = closure_input.pat.kind { // XXXManishearth Should I be checking the binding mode here? - if let ExprKind::Path(QPath::Resolved(None, ref p)) = function_arg.kind { + if let ExprKind::Path(QPath::Resolved(None, p)) = function_arg.kind { if p.segments.len() != 1 { // If it's a proper path, it can't be a local variable return false; diff --git a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs index 83cee11c3a..762f64fe37 100644 --- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs +++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs @@ -1,4 +1,5 @@ -use crate::utils::{get_parent_expr, path_to_local, path_to_local_id, span_lint, span_lint_and_note}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; +use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -70,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Find a write to a local variable. match expr.kind { - ExprKind::Assign(ref lhs, ..) | ExprKind::AssignOp(_, ref lhs, _) => { + ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) => { if let Some(var) = path_to_local(lhs) { let mut visitor = ReadVisitor { cx, @@ -86,12 +87,12 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { match stmt.kind { - StmtKind::Local(ref local) => { - if let Local { init: Some(ref e), .. } = **local { + StmtKind::Local(local) => { + if let Local { init: Some(e), .. } = local { DivergenceVisitor { cx }.visit_expr(e); } }, - StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => DivergenceVisitor { cx }.maybe_walk_expr(e), + StmtKind::Expr(e) | StmtKind::Semi(e) => DivergenceVisitor { cx }.maybe_walk_expr(e), StmtKind::Item(..) => {}, } } @@ -105,7 +106,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { ExprKind::Closure(..) => {}, - ExprKind::Match(ref e, arms, _) => { + ExprKind::Match(e, arms, _) => { self.visit_expr(e); for arm in arms { if let Some(Guard::If(if_expr)) = arm.guard { @@ -129,7 +130,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e), - ExprKind::Call(ref func, _) => { + ExprKind::Call(func, _) => { let typ = self.cx.typeck_results().expr_ty(func); match typ.kind() { ty::FnDef(..) | ty::FnPtr(_) => { @@ -265,14 +266,14 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr<'_>) - fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt<'_>) -> StopEarly { match stmt.kind { - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => check_expr(vis, expr), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => check_expr(vis, expr), // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. - StmtKind::Local(ref local) => local + StmtKind::Local(local) => local .init .as_ref() .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)), - _ => StopEarly::KeepGoing, + StmtKind::Item(..) => StopEarly::KeepGoing, } } @@ -342,7 +343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { /// Returns `true` if `expr` is the LHS of an assignment, like `expr = ...`. fn is_in_assignment_position(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let Some(parent) = get_parent_expr(cx, expr) { - if let ExprKind::Assign(ref lhs, ..) = parent.kind { + if let ExprKind::Assign(lhs, ..) = parent.kind { return lhs.hir_id == expr.hir_id; } } diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index 6f22f65dea..4e2dbf005d 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -1,10 +1,9 @@ -use crate::utils::{attr_by_name, in_macro, match_path_ast, span_lint_and_help}; -use rustc_ast::ast::{ - AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind, -}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::in_macro; +use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::Span; +use rustc_span::{sym, Span}; use std::convert::TryInto; @@ -127,7 +126,9 @@ impl_lint_pass!(ExcessiveBools => [STRUCT_EXCESSIVE_BOOLS, FN_PARAMS_EXCESSIVE_B fn is_bool_ty(ty: &Ty) -> bool { if let TyKind::Path(None, path) = &ty.kind { - return match_path_ast(path, &["bool"]); + if let [name] = path.segments.as_slice() { + return name.ident.name == sym::bool; + } } false } @@ -139,7 +140,7 @@ impl EarlyLintPass for ExcessiveBools { } match &item.kind { ItemKind::Struct(variant_data, _) => { - if attr_by_name(&item.attrs, "repr").is_some() { + if item.attrs.iter().any(|attr| attr.has_name(sym::repr)) { return; } diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index 316f748486..60ad2e8ee1 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -1,4 +1,5 @@ -use crate::utils::{indent_of, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::indent_of; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index 9158592700..16246e548b 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_entrypoint_fn, match_def_path, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_entrypoint_fn, match_def_path, paths}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; @@ -27,20 +28,18 @@ declare_lint_pass!(Exit => [EXIT]); impl<'tcx> LateLintPass<'tcx> for Exit { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Call(ref path_expr, ref _args) = e.kind; + if let ExprKind::Call(path_expr, _args) = e.kind; if let ExprKind::Path(ref path) = path_expr.kind; if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::EXIT); + let parent = cx.tcx.hir().get_parent_item(e.hir_id); + if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find(parent); + // If the next item up is a function we check if it is an entry point + // and only then emit a linter warning + let def_id = cx.tcx.hir().local_def_id(parent); + if !is_entrypoint_fn(cx, def_id.to_def_id()); then { - let parent = cx.tcx.hir().get_parent_item(e.hir_id); - if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find(parent) { - // If the next item up is a function we check if it is an entry point - // and only then emit a linter warning - let def_id = cx.tcx.hir().local_def_id(parent); - if !is_entrypoint_fn(cx, def_id.to_def_id()) { - span_lint(cx, EXIT, e.span, "usage of `process::exit`"); - } - } + span_lint(cx, EXIT, e.span, "usage of `process::exit`"); } } } diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index f8038d06e5..da4936ff25 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_expn_of, match_function_call, paths, span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::{is_expn_of, match_function_call, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -33,11 +34,11 @@ 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(ref unwrap_fun, _, ref unwrap_args, _) = expr.kind; + if let ExprKind::MethodCall(unwrap_fun, _, unwrap_args, _) = expr.kind; if unwrap_fun.ident.name == sym::unwrap; // match call to write_fmt if !unwrap_args.is_empty(); - if let ExprKind::MethodCall(ref write_fun, _, write_args, _) = + if let ExprKind::MethodCall(write_fun, _, write_args, _) = unwrap_args[0].kind; if write_fun.ident.name == sym!(write_fmt); // match calls to std::io::stdout() / std::io::stderr () @@ -134,10 +135,10 @@ 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(_, ref output_args) = write_args[1].kind; + if let ExprKind::Call(_, output_args) = write_args[1].kind; if !output_args.is_empty(); - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref output_string_expr) = output_args[0].kind; - if let ExprKind::Array(ref string_exprs) = output_string_expr.kind; + 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; diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index f466dddc13..2937fcb9ca 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -1,4 +1,6 @@ -use crate::utils::{is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_expn_of, match_panic_def_id, method_chain_args}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -79,8 +81,8 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { // check for `begin_panic` if_chain! { - if let ExprKind::Call(ref func_expr, _) = expr.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.kind; + if let ExprKind::Call(func_expr, _) = expr.kind; + if let ExprKind::Path(QPath::Resolved(_, path)) = func_expr.kind; if let Some(path_def_id) = path.res.opt_def_id(); if match_panic_def_id(self.lcx, path_def_id); if is_expn_of(expr.span, "unreachable").is_none(); diff --git a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs index c1c08597ee..b5ebe5f90b 100644 --- a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs +++ b/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs @@ -1,4 +1,5 @@ -use crate::utils::{match_def_path, paths, span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{match_def_path, paths, sugg}; use if_chain::if_chain; use rustc_ast::util::parser::AssocOp; use rustc_errors::Applicability; @@ -47,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs { let rhs; // check if expr is a binary expression with a lt or gt operator - if let ExprKind::Binary(op, ref left, ref right) = expr.kind { + if let ExprKind::Binary(op, left, right) = expr.kind { match op.node { BinOpKind::Lt => { lhs = left; @@ -87,8 +88,8 @@ impl<'tcx> LateLintPass<'tcx> for FloatEqualityWithoutAbs { if let ty::Float(_) = t_val_r.kind(); then { - let sug_l = sugg::Sugg::hir(cx, &val_l, ".."); - let sug_r = sugg::Sugg::hir(cx, &val_r, ".."); + let sug_l = sugg::Sugg::hir(cx, val_l, ".."); + let sug_r = sugg::Sugg::hir(cx, val_r, ".."); // format the suggestion let suggestion = format!("{}.abs()", sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()); // spans the lint diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index 8e256f3468..7968e7b764 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -1,4 +1,5 @@ -use crate::utils::{numeric_literal, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::numeric_literal; use if_chain::if_chain; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_errors::Applicability; @@ -60,8 +61,8 @@ declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]); impl<'tcx> LateLintPass<'tcx> for FloatLiteral { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + let ty = cx.typeck_results().expr_ty(expr); if_chain! { - let ty = cx.typeck_results().expr_ty(expr); if let ty::Float(fty) = *ty.kind(); if let hir::ExprKind::Lit(ref lit) = expr.kind; if let LitKind::Float(sym, lit_float_ty) = lit.node; diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs index 086a791520..e0b687b020 100644 --- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs @@ -2,7 +2,8 @@ use crate::consts::{ constant, constant_simple, Constant, Constant::{Int, F32, F64}, }; -use crate::utils::{eq_expr_value, get_parent_expr, numeric_literal, span_lint_and_sugg, sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{eq_expr_value, get_parent_expr, numeric_literal, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; @@ -130,7 +131,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su let mut suggestion = Sugg::hir(cx, expr, ".."); if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind { - expr = &inner_expr; + expr = inner_expr; } if_chain! { @@ -312,8 +313,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { Spanned { node: BinOpKind::Add, .. }, - ref lhs, - ref rhs, + lhs, + rhs, ) = parent.kind { let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; @@ -328,7 +329,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { "{}.mul_add({}, {})", Sugg::hir(cx, &args[0], ".."), Sugg::hir(cx, &args[0], ".."), - Sugg::hir(cx, &other_addend, ".."), + Sugg::hir(cx, other_addend, ".."), ), Applicability::MachineApplicable, ); @@ -355,18 +356,18 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> { Spanned { node: BinOpKind::Add, .. }, - ref add_lhs, - ref add_rhs, + add_lhs, + add_rhs, ) = args[0].kind { // check if expression of the form x * x + y * y if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lmul_lhs, ref lmul_rhs) = add_lhs.kind; - if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref rmul_lhs, ref rmul_rhs) = add_rhs.kind; + if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lmul_lhs, lmul_rhs) = add_lhs.kind; + if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, rmul_lhs, rmul_rhs) = add_rhs.kind; if eq_expr_value(cx, lmul_lhs, lmul_rhs); if eq_expr_value(cx, rmul_lhs, rmul_rhs); then { - return Some(format!("{}.hypot({})", Sugg::hir(cx, &lmul_lhs, ".."), Sugg::hir(cx, &rmul_lhs, ".."))); + return Some(format!("{}.hypot({})", Sugg::hir(cx, lmul_lhs, ".."), Sugg::hir(cx, rmul_lhs, ".."))); } } @@ -375,13 +376,13 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> { if let ExprKind::MethodCall( PathSegment { ident: lmethod_name, .. }, ref _lspan, - ref largs, + largs, _ ) = add_lhs.kind; if let ExprKind::MethodCall( PathSegment { ident: rmethod_name, .. }, ref _rspan, - ref rargs, + rargs, _ ) = add_rhs.kind; if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"; @@ -415,11 +416,11 @@ fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // and suggest usage of `x.exp_m1() - (y - 1)` instead fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) = expr.kind; + if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind; if cx.typeck_results().expr_ty(lhs).is_floating_point(); if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs); if F32(1.0) == value || F64(1.0) == value; - if let ExprKind::MethodCall(ref path, _, ref method_args, _) = lhs.kind; + if let ExprKind::MethodCall(path, _, method_args, _) = lhs.kind; if cx.typeck_results().expr_ty(&method_args[0]).is_floating_point(); if path.ident.name.as_str() == "exp"; then { @@ -441,7 +442,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lhs, ref rhs) = &expr.kind; + if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lhs, rhs) = &expr.kind; if cx.typeck_results().expr_ty(lhs).is_floating_point(); if cx.typeck_results().expr_ty(rhs).is_floating_point(); then { @@ -603,8 +604,8 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { if_chain! { - if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, ref args_a, _) = expr_a.kind; - if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, ref args_b, _) = expr_b.kind; + if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind; + if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind; then { return method_name_a.as_str() == method_name_b.as_str() && args_a.len() == args_b.len() && @@ -629,8 +630,8 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { rhs, ) = &expr.kind; if are_same_base_logs(cx, lhs, rhs); - if let ExprKind::MethodCall(_, _, ref largs, _) = lhs.kind; - if let ExprKind::MethodCall(_, _, ref rargs, _) = rhs.kind; + if let ExprKind::MethodCall(_, _, largs, _) = lhs.kind; + if let ExprKind::MethodCall(_, _, rargs, _) = rhs.kind; then { span_lint_and_sugg( cx, @@ -674,7 +675,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { expr.span, "conversion to degrees can be done more accurately", "consider using", - format!("{}.to_degrees()", Sugg::hir(cx, &mul_lhs, "..")), + format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..")), Applicability::MachineApplicable, ); } else if @@ -687,7 +688,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { expr.span, "conversion to radians can be done more accurately", "consider using", - format!("{}.to_radians()", Sugg::hir(cx, &mul_lhs, "..")), + format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..")), Applicability::MachineApplicable, ); } @@ -697,7 +698,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind { + if let ExprKind::MethodCall(path, _, args, _) = &expr.kind { let recv_ty = cx.typeck_results().expr_ty(&args[0]); if recv_ty.is_floating_point() { diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index fd6bf19db9..c2b055ed64 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -1,8 +1,9 @@ -use crate::utils::paths; -use crate::utils::{ - is_expn_of, is_type_diagnostic_item, last_path_segment, match_def_path, match_function_call, snippet, snippet_opt, - span_lint_and_then, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::paths; +use clippy_utils::source::{snippet, snippet_opt}; +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; @@ -78,8 +79,8 @@ fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg: fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> { if_chain! { - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref format_args) = expr.kind; - if let ExprKind::Array(ref elems) = arms[0].body.kind; + 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` @@ -88,10 +89,10 @@ fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: & 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(ref pats, None) = arms[0].pat.kind; + 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(); + 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; } @@ -100,15 +101,15 @@ fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: & return Some(format!("{:?}.to_string()", s.as_str())); } } else { - let snip = snippet(cx, format_args.span, "<arg>"); - if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind { + 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!("{}", snip)); + return Some(format!("{}", sugg)); } } else if let ExprKind::Binary(..) = format_args.kind { - return Some(format!("{}", snip)); + return Some(format!("{}", sugg)); } - return Some(format!("{}.to_string()", snip)); + return Some(format!("{}.to_string()", sugg.maybe_par())); } } } @@ -120,23 +121,23 @@ fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Strin 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, _, ref arr) = args[0].kind; - if let ExprKind::Array(ref pieces) = arr.kind; + 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, _, ref arg1) = args[1].kind; - if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind; + 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(ref tup) = matchee.kind; + 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)) + return Some(format!("{}.to_string()", s_expand)); } } else if s.as_str().is_empty() { return on_argumentv1_new(cx, &tup[0], arms); @@ -152,16 +153,16 @@ fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<S if args.len() == 3; if check_unformatted(&args[2]); // Argument 1 in `new_v1_formatted()` - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind; - if let ExprKind::Array(ref pieces) = arr.kind; + 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, _, ref arg1) = args[1].kind; - if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind; + 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(ref tup) = matchee.kind; + if let ExprKind::Tup(tup) = matchee.kind; then { return on_argumentv1_new(cx, &tup[0], arms); } @@ -182,14 +183,14 @@ 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, _, ref expr) = expr.kind; - if let ExprKind::Array(ref exprs) = expr.kind; + if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind; + if let ExprKind::Array(exprs) = expr.kind; if exprs.len() == 1; // struct `core::fmt::rt::v1::Argument` - if let ExprKind::Struct(_, ref fields, _) = exprs[0].kind; + if let ExprKind::Struct(_, fields, _) = exprs[0].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(_, ref fields, _) = format_field.expr.kind; + if let ExprKind::Struct(_, fields, _) = format_field.expr.kind; if let Some(precision_field) = fields.iter().find(|f| f.ident.name == sym::precision); if let ExprKind::Path(ref precision_path) = precision_field.expr.kind; if last_path_segment(precision_path).ident.name == sym::Implied; diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index 1bd16e6cce..3bd6a09d36 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -1,4 +1,6 @@ -use crate::utils::{differing_macro_contexts, snippet_opt, span_lint_and_help, span_lint_and_note}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note}; +use clippy_utils::differing_macro_contexts; +use clippy_utils::source::snippet_opt; use if_chain::if_chain; use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -213,11 +215,23 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” if let Some(else_snippet) = snippet_opt(cx, else_span); - if let Some(else_pos) = else_snippet.find("else"); - if else_snippet[else_pos..].contains('\n'); - let else_desc = if is_if(else_) { "if" } else { "{..}" }; + if let Some((pre_else, post_else)) = else_snippet.split_once("else"); + if let Some((_, post_else_post_eol)) = post_else.split_once('\n'); then { + // Allow allman style braces `} \n else \n {` + if_chain! { + if is_block(else_); + if let Some((_, pre_else_post_eol)) = pre_else.split_once('\n'); + // Exactly one eol before and after the else + if !pre_else_post_eol.contains('\n'); + if !post_else_post_eol.contains('\n'); + then { + return; + } + } + + let else_desc = if is_if(else_) { "if" } else { "{..}" }; span_lint_and_note( cx, SUSPICIOUS_ELSE_FORMATTING, diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index b644bb0799..3560672a74 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -1,13 +1,12 @@ -use crate::utils::paths::INTO; -use crate::utils::{match_def_path, meets_msrv, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::paths::INTO; +use clippy_utils::{match_def_path, meets_msrv, msrvs}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; -const FROM_OVER_INTO_MSRV: RustcVersion = RustcVersion::new(1, 41, 0); - declare_clippy_lint! { /// **What it does:** Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead. /// @@ -56,7 +55,7 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]); impl LateLintPass<'_> for FromOverInto { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { - if !meets_msrv(self.msrv.as_ref(), &FROM_OVER_INTO_MSRV) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::RE_REBALANCING_COHERENCE) { return; } @@ -72,7 +71,7 @@ impl LateLintPass<'_> for FromOverInto { cx.tcx.sess.source_map().guess_head_span(item.span), "an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true", None, - "consider to implement `From` instead", + &format!("consider to implement `From<{}>` instead", impl_trait_ref.self_ty()), ); } } diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs index 0933f98301..3da5bc95b6 100644 --- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs +++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs @@ -1,3 +1,6 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, PrimTy, QPath, TyKind}; @@ -6,10 +9,6 @@ use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; -use crate::utils::is_type_diagnostic_item; -use crate::utils::span_lint_and_sugg; -use crate::utils::sugg::Sugg; - declare_clippy_lint! { /// **What it does:** /// Checks for function invocations of the form `primitive::from_str_radix(s, 10)` diff --git a/src/tools/clippy/clippy_lints/src/functions.rs b/src/tools/clippy/clippy_lints/src/functions.rs deleted file mode 100644 index c474db06fe..0000000000 --- a/src/tools/clippy/clippy_lints/src/functions.rs +++ /dev/null @@ -1,736 +0,0 @@ -use crate::utils::{ - attr_by_name, attrs::is_proc_macro, is_must_use_ty, is_trait_impl_item, is_type_diagnostic_item, iter_input_pats, - match_def_path, must_use_attr, path_to_local, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help, - span_lint_and_then, trait_ref_of_method, type_is_unsafe_function, -}; -use if_chain::if_chain; -use rustc_ast::ast::Attribute; -use rustc_data_structures::fx::FxHashSet; -use rustc_errors::Applicability; -use rustc_hir as hir; -use rustc_hir::intravisit; -use rustc_hir::{def::Res, def_id::DefId, QPath}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::hir::map::Map; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::source_map::Span; -use rustc_span::sym; -use rustc_target::spec::abi::Abi; -use rustc_typeck::hir_ty_to_ty; - -declare_clippy_lint! { - /// **What it does:** Checks for functions with too many parameters. - /// - /// **Why is this bad?** Functions with lots of parameters are considered bad - /// style and reduce readability (“what does the 5th parameter mean?”). Consider - /// grouping some parameters into a new type. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// # struct Color; - /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { - /// // .. - /// } - /// ``` - pub TOO_MANY_ARGUMENTS, - complexity, - "functions with too many arguments" -} - -declare_clippy_lint! { - /// **What it does:** Checks for functions with a large amount of lines. - /// - /// **Why is this bad?** Functions with a lot of lines are harder to understand - /// due to having to look at a larger amount of code to understand what the - /// function is doing. Consider splitting the body of the function into - /// multiple functions. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// fn im_too_long() { - /// println!(""); - /// // ... 100 more LoC - /// println!(""); - /// } - /// ``` - pub TOO_MANY_LINES, - pedantic, - "functions with too many lines" -} - -declare_clippy_lint! { - /// **What it does:** Checks for public functions that dereference raw pointer - /// arguments but are not marked unsafe. - /// - /// **Why is this bad?** The function should probably be marked `unsafe`, since - /// for an arbitrary raw pointer, there is no way of telling for sure if it is - /// valid. - /// - /// **Known problems:** - /// - /// * It does not check functions recursively so if the pointer is passed to a - /// private non-`unsafe` function which does the dereferencing, the lint won't - /// trigger. - /// * It only checks for arguments whose type are raw pointers, not raw pointers - /// got from an argument in some other way (`fn foo(bar: &[*const u8])` or - /// `some_argument.get_raw_ptr()`). - /// - /// **Example:** - /// ```rust,ignore - /// // Bad - /// pub fn foo(x: *const u8) { - /// println!("{}", unsafe { *x }); - /// } - /// - /// // Good - /// pub unsafe fn foo(x: *const u8) { - /// println!("{}", unsafe { *x }); - /// } - /// ``` - pub NOT_UNSAFE_PTR_ARG_DEREF, - correctness, - "public functions dereferencing raw pointer arguments but not marked `unsafe`" -} - -declare_clippy_lint! { - /// **What it does:** Checks for a [`#[must_use]`] attribute on - /// unit-returning functions and methods. - /// - /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute - /// - /// **Why is this bad?** Unit values are useless. The attribute is likely - /// a remnant of a refactoring that removed the return type. - /// - /// **Known problems:** None. - /// - /// **Examples:** - /// ```rust - /// #[must_use] - /// fn useless() { } - /// ``` - pub MUST_USE_UNIT, - style, - "`#[must_use]` attribute on a unit-returning function / method" -} - -declare_clippy_lint! { - /// **What it does:** Checks for a [`#[must_use]`] attribute without - /// further information on functions and methods that return a type already - /// marked as `#[must_use]`. - /// - /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute - /// - /// **Why is this bad?** The attribute isn't needed. Not using the result - /// will already be reported. Alternatively, one can add some text to the - /// attribute to improve the lint message. - /// - /// **Known problems:** None. - /// - /// **Examples:** - /// ```rust - /// #[must_use] - /// fn double_must_use() -> Result<(), ()> { - /// unimplemented!(); - /// } - /// ``` - pub DOUBLE_MUST_USE, - style, - "`#[must_use]` attribute on a `#[must_use]`-returning function / method" -} - -declare_clippy_lint! { - /// **What it does:** Checks for public functions that have no - /// [`#[must_use]`] attribute, but return something not already marked - /// must-use, have no mutable arg and mutate no statics. - /// - /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute - /// - /// **Why is this bad?** Not bad at all, this lint just shows places where - /// you could add the attribute. - /// - /// **Known problems:** The lint only checks the arguments for mutable - /// types without looking if they are actually changed. On the other hand, - /// it also ignores a broad range of potentially interesting side effects, - /// because we cannot decide whether the programmer intends the function to - /// be called for the side effect or the result. Expect many false - /// positives. At least we don't lint if the result type is unit or already - /// `#[must_use]`. - /// - /// **Examples:** - /// ```rust - /// // this could be annotated with `#[must_use]`. - /// fn id<T>(t: T) -> T { t } - /// ``` - pub MUST_USE_CANDIDATE, - pedantic, - "function or method that could take a `#[must_use]` attribute" -} - -declare_clippy_lint! { - /// **What it does:** Checks for public functions that return a `Result` - /// with an `Err` type of `()`. It suggests using a custom type that - /// implements [`std::error::Error`]. - /// - /// **Why is this bad?** Unit does not implement `Error` and carries no - /// further information about what went wrong. - /// - /// **Known problems:** Of course, this lint assumes that `Result` is used - /// for a fallible operation (which is after all the intended use). However - /// code may opt to (mis)use it as a basic two-variant-enum. In that case, - /// the suggestion is misguided, and the code should use a custom enum - /// instead. - /// - /// **Examples:** - /// ```rust - /// pub fn read_u8() -> Result<u8, ()> { Err(()) } - /// ``` - /// should become - /// ```rust,should_panic - /// use std::fmt; - /// - /// #[derive(Debug)] - /// pub struct EndOfStream; - /// - /// impl fmt::Display for EndOfStream { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "End of Stream") - /// } - /// } - /// - /// impl std::error::Error for EndOfStream { } - /// - /// pub fn read_u8() -> Result<u8, EndOfStream> { Err(EndOfStream) } - ///# fn main() { - ///# read_u8().unwrap(); - ///# } - /// ``` - /// - /// Note that there are crates that simplify creating the error type, e.g. - /// [`thiserror`](https://docs.rs/thiserror). - pub RESULT_UNIT_ERR, - style, - "public function returning `Result` with an `Err` type of `()`" -} - -#[derive(Copy, Clone)] -pub struct Functions { - threshold: u64, - max_lines: u64, -} - -impl Functions { - pub fn new(threshold: u64, max_lines: u64) -> Self { - Self { threshold, max_lines } - } -} - -impl_lint_pass!(Functions => [ - TOO_MANY_ARGUMENTS, - TOO_MANY_LINES, - NOT_UNSAFE_PTR_ARG_DEREF, - MUST_USE_UNIT, - DOUBLE_MUST_USE, - MUST_USE_CANDIDATE, - RESULT_UNIT_ERR, -]); - -impl<'tcx> LateLintPass<'tcx> for Functions { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - kind: intravisit::FnKind<'tcx>, - decl: &'tcx hir::FnDecl<'_>, - body: &'tcx hir::Body<'_>, - span: Span, - hir_id: hir::HirId, - ) { - let unsafety = match kind { - intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety, - intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety, - intravisit::FnKind::Closure => return, - }; - - // don't warn for implementations, it's not their fault - if !is_trait_impl_item(cx, hir_id) { - // don't lint extern functions decls, it's not their fault either - match kind { - intravisit::FnKind::Method( - _, - &hir::FnSig { - header: hir::FnHeader { abi: Abi::Rust, .. }, - .. - }, - _, - ) - | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => { - self.check_arg_number(cx, decl, span.with_hi(decl.output.span().hi())) - }, - _ => {}, - } - } - - Self::check_raw_ptr(cx, unsafety, decl, body, hir_id); - self.check_line_number(cx, span, body); - } - - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { - let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = must_use_attr(attrs); - if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.hir_id()); - let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - if is_public { - check_result_unit_err(cx, &sig.decl, item.span, fn_header_span); - } - if let Some(attr) = attr { - check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr); - return; - } - if is_public && !is_proc_macro(cx.sess(), attrs) && attr_by_name(attrs, "no_mangle").is_none() { - check_must_use_candidate( - cx, - &sig.decl, - cx.tcx.hir().body(*body_id), - item.span, - item.hir_id(), - item.span.with_hi(sig.decl.output.span().hi()), - "this function could have a `#[must_use]` attribute", - ); - } - } - } - - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { - if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.hir_id()); - let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() { - check_result_unit_err(cx, &sig.decl, item.span, fn_header_span); - } - let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = must_use_attr(attrs); - if let Some(attr) = attr { - check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr); - } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.hir_id()).is_none() - { - check_must_use_candidate( - cx, - &sig.decl, - cx.tcx.hir().body(*body_id), - item.span, - item.hir_id(), - item.span.with_hi(sig.decl.output.span().hi()), - "this method could have a `#[must_use]` attribute", - ); - } - } - } - - fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { - // don't lint extern functions decls, it's not their fault - if sig.header.abi == Abi::Rust { - self.check_arg_number(cx, &sig.decl, item.span.with_hi(sig.decl.output.span().hi())); - } - let is_public = cx.access_levels.is_exported(item.hir_id()); - let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - if is_public { - check_result_unit_err(cx, &sig.decl, item.span, fn_header_span); - } - - let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = must_use_attr(attrs); - if let Some(attr) = attr { - check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr); - } - if let hir::TraitFn::Provided(eid) = *eid { - let body = cx.tcx.hir().body(eid); - Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id()); - - if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) { - check_must_use_candidate( - cx, - &sig.decl, - body, - item.span, - item.hir_id(), - item.span.with_hi(sig.decl.output.span().hi()), - "this method could have a `#[must_use]` attribute", - ); - } - } - } - } -} - -impl<'tcx> Functions { - fn check_arg_number(self, cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span) { - let args = decl.inputs.len() as u64; - if args > self.threshold { - span_lint( - cx, - TOO_MANY_ARGUMENTS, - fn_span, - &format!("this function has too many arguments ({}/{})", args, self.threshold), - ); - } - } - - fn check_line_number(self, cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>) { - if in_external_macro(cx.sess(), span) { - return; - } - - let code_snippet = snippet(cx, body.value.span, ".."); - let mut line_count: u64 = 0; - let mut in_comment = false; - let mut code_in_line; - - // Skip the surrounding function decl. - let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1); - let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len()); - let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines(); - - for mut line in function_lines { - code_in_line = false; - loop { - line = line.trim_start(); - if line.is_empty() { - break; - } - if in_comment { - if let Some(i) = line.find("*/") { - line = &line[i + 2..]; - in_comment = false; - continue; - } - } else { - let multi_idx = line.find("/*").unwrap_or_else(|| line.len()); - let single_idx = line.find("//").unwrap_or_else(|| line.len()); - code_in_line |= multi_idx > 0 && single_idx > 0; - // Implies multi_idx is below line.len() - if multi_idx < single_idx { - line = &line[multi_idx + 2..]; - in_comment = true; - continue; - } - } - break; - } - if code_in_line { - line_count += 1; - } - } - - if line_count > self.max_lines { - span_lint( - cx, - TOO_MANY_LINES, - span, - &format!("this function has too many lines ({}/{})", line_count, self.max_lines), - ) - } - } - - fn check_raw_ptr( - cx: &LateContext<'tcx>, - unsafety: hir::Unsafety, - decl: &'tcx hir::FnDecl<'_>, - body: &'tcx hir::Body<'_>, - hir_id: hir::HirId, - ) { - let expr = &body.value; - if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) { - let raw_ptrs = iter_input_pats(decl, body) - .zip(decl.inputs.iter()) - .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty)) - .collect::<FxHashSet<_>>(); - - if !raw_ptrs.is_empty() { - let typeck_results = cx.tcx.typeck_body(body.id()); - let mut v = DerefVisitor { - cx, - ptrs: raw_ptrs, - typeck_results, - }; - - intravisit::walk_expr(&mut v, expr); - } - } - } -} - -fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) { - if_chain! { - if !in_external_macro(cx.sess(), item_span); - if let hir::FnRetTy::Return(ref ty) = decl.output; - let ty = hir_ty_to_ty(cx.tcx, ty); - if is_type_diagnostic_item(cx, ty, sym::result_type); - if let ty::Adt(_, substs) = ty.kind(); - let err_ty = substs.type_at(1); - if err_ty.is_unit(); - then { - span_lint_and_help( - cx, - RESULT_UNIT_ERR, - fn_header_span, - "this returns a `Result<_, ()>", - None, - "use a custom Error type instead", - ); - } - } -} - -fn check_needless_must_use( - cx: &LateContext<'_>, - decl: &hir::FnDecl<'_>, - item_id: hir::HirId, - item_span: Span, - fn_header_span: Span, - attr: &Attribute, -) { - if in_external_macro(cx.sess(), item_span) { - return; - } - if returns_unit(decl) { - span_lint_and_then( - cx, - MUST_USE_UNIT, - fn_header_span, - "this unit-returning function has a `#[must_use]` attribute", - |diag| { - diag.span_suggestion( - attr.span, - "remove the attribute", - "".into(), - Applicability::MachineApplicable, - ); - }, - ); - } else if !attr.is_value_str() && is_must_use_ty(cx, return_ty(cx, item_id)) { - span_lint_and_help( - cx, - DOUBLE_MUST_USE, - fn_header_span, - "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`", - None, - "either add some descriptive text or remove the attribute", - ); - } -} - -fn check_must_use_candidate<'tcx>( - cx: &LateContext<'tcx>, - decl: &'tcx hir::FnDecl<'_>, - body: &'tcx hir::Body<'_>, - item_span: Span, - item_id: hir::HirId, - fn_span: Span, - msg: &str, -) { - if has_mutable_arg(cx, body) - || mutates_static(cx, body) - || in_external_macro(cx.sess(), item_span) - || returns_unit(decl) - || !cx.access_levels.is_exported(item_id) - || is_must_use_ty(cx, return_ty(cx, item_id)) - { - return; - } - span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| { - if let Some(snippet) = snippet_opt(cx, fn_span) { - diag.span_suggestion( - fn_span, - "add the attribute", - format!("#[must_use] {}", snippet), - Applicability::MachineApplicable, - ); - } - }); -} - -fn returns_unit(decl: &hir::FnDecl<'_>) -> bool { - match decl.output { - hir::FnRetTy::DefaultReturn(_) => true, - hir::FnRetTy::Return(ref ty) => match ty.kind { - hir::TyKind::Tup(ref tys) => tys.is_empty(), - hir::TyKind::Never => true, - _ => false, - }, - } -} - -fn has_mutable_arg(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool { - let mut tys = FxHashSet::default(); - body.params.iter().any(|param| is_mutable_pat(cx, ¶m.pat, &mut tys)) -} - -fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut FxHashSet<DefId>) -> bool { - if let hir::PatKind::Wild = pat.kind { - return false; // ignore `_` patterns - } - if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) { - is_mutable_ty(cx, &cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys) - } else { - false - } -} - -static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]]; - -fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut FxHashSet<DefId>) -> bool { - match *ty.kind() { - // primitive types are never mutable - ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, - ty::Adt(ref adt, ref substs) => { - tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env) - || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path)) - && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)) - }, - ty::Tuple(ref substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)), - ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys), - ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => { - mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys) - }, - // calling something constitutes a side effect, so return true on all callables - // also never calls need not be used, so return true for them, too - _ => true, - } -} - -fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> { - if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) { - Some(id) - } else { - None - } -} - -struct DerefVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - ptrs: FxHashSet<hir::HirId>, - typeck_results: &'a ty::TypeckResults<'tcx>, -} - -impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - match expr.kind { - hir::ExprKind::Call(ref f, args) => { - let ty = self.typeck_results.expr_ty(f); - - if type_is_unsafe_function(self.cx, ty) { - for arg in args { - self.check_arg(arg); - } - } - }, - hir::ExprKind::MethodCall(_, _, args, _) => { - let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap(); - let base_type = self.cx.tcx.type_of(def_id); - - if type_is_unsafe_function(self.cx, base_type) { - for arg in args { - self.check_arg(arg); - } - } - }, - hir::ExprKind::Unary(hir::UnOp::Deref, ref ptr) => self.check_arg(ptr), - _ => (), - } - - intravisit::walk_expr(self, expr); - } - - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { - intravisit::NestedVisitorMap::None - } -} - -impl<'a, 'tcx> DerefVisitor<'a, 'tcx> { - fn check_arg(&self, ptr: &hir::Expr<'_>) { - if let Some(id) = path_to_local(ptr) { - if self.ptrs.contains(&id) { - span_lint( - self.cx, - NOT_UNSAFE_PTR_ARG_DEREF, - ptr.span, - "this public function dereferences a raw pointer but is not marked `unsafe`", - ); - } - } - } -} - -struct StaticMutVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - mutates_static: bool, -} - -impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall}; - - if self.mutates_static { - return; - } - match expr.kind { - Call(_, args) | MethodCall(_, _, args, _) => { - let mut tys = FxHashSet::default(); - for arg in args { - if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) - && is_mutable_ty( - self.cx, - self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg), - arg.span, - &mut tys, - ) - && is_mutated_static(arg) - { - self.mutates_static = true; - return; - } - tys.clear(); - } - }, - Assign(ref target, ..) | AssignOp(_, ref target, _) | AddrOf(_, hir::Mutability::Mut, ref target) => { - self.mutates_static |= is_mutated_static(target) - }, - _ => {}, - } - } - - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { - intravisit::NestedVisitorMap::None - } -} - -fn is_mutated_static(e: &hir::Expr<'_>) -> bool { - use hir::ExprKind::{Field, Index, Path}; - - match e.kind { - Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)), - Path(_) => true, - Field(ref inner, _) | Index(ref inner, _) => is_mutated_static(inner), - _ => false, - } -} - -fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool { - let mut v = StaticMutVisitor { - cx, - mutates_static: false, - }; - intravisit::walk_expr(&mut v, &body.value); - v.mutates_static -} diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs new file mode 100644 index 0000000000..2beb9bc94b --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs @@ -0,0 +1,267 @@ +mod must_use; +mod not_unsafe_ptr_arg_deref; +mod result_unit_err; +mod too_many_arguments; +mod too_many_lines; + +use rustc_hir as hir; +use rustc_hir::intravisit; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; + +declare_clippy_lint! { + /// **What it does:** Checks for functions with too many parameters. + /// + /// **Why is this bad?** Functions with lots of parameters are considered bad + /// style and reduce readability (“what does the 5th parameter mean?”). Consider + /// grouping some parameters into a new type. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// # struct Color; + /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { + /// // .. + /// } + /// ``` + pub TOO_MANY_ARGUMENTS, + complexity, + "functions with too many arguments" +} + +declare_clippy_lint! { + /// **What it does:** Checks for functions with a large amount of lines. + /// + /// **Why is this bad?** Functions with a lot of lines are harder to understand + /// due to having to look at a larger amount of code to understand what the + /// function is doing. Consider splitting the body of the function into + /// multiple functions. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// fn im_too_long() { + /// println!(""); + /// // ... 100 more LoC + /// println!(""); + /// } + /// ``` + pub TOO_MANY_LINES, + pedantic, + "functions with too many lines" +} + +declare_clippy_lint! { + /// **What it does:** Checks for public functions that dereference raw pointer + /// arguments but are not marked `unsafe`. + /// + /// **Why is this bad?** The function should probably be marked `unsafe`, since + /// for an arbitrary raw pointer, there is no way of telling for sure if it is + /// valid. + /// + /// **Known problems:** + /// + /// * It does not check functions recursively so if the pointer is passed to a + /// private non-`unsafe` function which does the dereferencing, the lint won't + /// trigger. + /// * It only checks for arguments whose type are raw pointers, not raw pointers + /// got from an argument in some other way (`fn foo(bar: &[*const u8])` or + /// `some_argument.get_raw_ptr()`). + /// + /// **Example:** + /// ```rust,ignore + /// // Bad + /// pub fn foo(x: *const u8) { + /// println!("{}", unsafe { *x }); + /// } + /// + /// // Good + /// pub unsafe fn foo(x: *const u8) { + /// println!("{}", unsafe { *x }); + /// } + /// ``` + pub NOT_UNSAFE_PTR_ARG_DEREF, + correctness, + "public functions dereferencing raw pointer arguments but not marked `unsafe`" +} + +declare_clippy_lint! { + /// **What it does:** Checks for a [`#[must_use]`] attribute on + /// unit-returning functions and methods. + /// + /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute + /// + /// **Why is this bad?** Unit values are useless. The attribute is likely + /// a remnant of a refactoring that removed the return type. + /// + /// **Known problems:** None. + /// + /// **Examples:** + /// ```rust + /// #[must_use] + /// fn useless() { } + /// ``` + pub MUST_USE_UNIT, + style, + "`#[must_use]` attribute on a unit-returning function / method" +} + +declare_clippy_lint! { + /// **What it does:** Checks for a [`#[must_use]`] attribute without + /// further information on functions and methods that return a type already + /// marked as `#[must_use]`. + /// + /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute + /// + /// **Why is this bad?** The attribute isn't needed. Not using the result + /// will already be reported. Alternatively, one can add some text to the + /// attribute to improve the lint message. + /// + /// **Known problems:** None. + /// + /// **Examples:** + /// ```rust + /// #[must_use] + /// fn double_must_use() -> Result<(), ()> { + /// unimplemented!(); + /// } + /// ``` + pub DOUBLE_MUST_USE, + style, + "`#[must_use]` attribute on a `#[must_use]`-returning function / method" +} + +declare_clippy_lint! { + /// **What it does:** Checks for public functions that have no + /// [`#[must_use]`] attribute, but return something not already marked + /// must-use, have no mutable arg and mutate no statics. + /// + /// [`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute + /// + /// **Why is this bad?** Not bad at all, this lint just shows places where + /// you could add the attribute. + /// + /// **Known problems:** The lint only checks the arguments for mutable + /// types without looking if they are actually changed. On the other hand, + /// it also ignores a broad range of potentially interesting side effects, + /// because we cannot decide whether the programmer intends the function to + /// be called for the side effect or the result. Expect many false + /// positives. At least we don't lint if the result type is unit or already + /// `#[must_use]`. + /// + /// **Examples:** + /// ```rust + /// // this could be annotated with `#[must_use]`. + /// fn id<T>(t: T) -> T { t } + /// ``` + pub MUST_USE_CANDIDATE, + pedantic, + "function or method that could take a `#[must_use]` attribute" +} + +declare_clippy_lint! { + /// **What it does:** Checks for public functions that return a `Result` + /// with an `Err` type of `()`. It suggests using a custom type that + /// implements `std::error::Error`. + /// + /// **Why is this bad?** Unit does not implement `Error` and carries no + /// further information about what went wrong. + /// + /// **Known problems:** Of course, this lint assumes that `Result` is used + /// for a fallible operation (which is after all the intended use). However + /// code may opt to (mis)use it as a basic two-variant-enum. In that case, + /// the suggestion is misguided, and the code should use a custom enum + /// instead. + /// + /// **Examples:** + /// ```rust + /// pub fn read_u8() -> Result<u8, ()> { Err(()) } + /// ``` + /// should become + /// ```rust,should_panic + /// use std::fmt; + /// + /// #[derive(Debug)] + /// pub struct EndOfStream; + /// + /// impl fmt::Display for EndOfStream { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "End of Stream") + /// } + /// } + /// + /// impl std::error::Error for EndOfStream { } + /// + /// pub fn read_u8() -> Result<u8, EndOfStream> { Err(EndOfStream) } + ///# fn main() { + ///# read_u8().unwrap(); + ///# } + /// ``` + /// + /// Note that there are crates that simplify creating the error type, e.g. + /// [`thiserror`](https://docs.rs/thiserror). + pub RESULT_UNIT_ERR, + style, + "public function returning `Result` with an `Err` type of `()`" +} + +#[derive(Copy, Clone)] +pub struct Functions { + too_many_arguments_threshold: u64, + too_many_lines_threshold: u64, +} + +impl Functions { + pub fn new(too_many_arguments_threshold: u64, too_many_lines_threshold: u64) -> Self { + Self { + too_many_arguments_threshold, + too_many_lines_threshold, + } + } +} + +impl_lint_pass!(Functions => [ + TOO_MANY_ARGUMENTS, + TOO_MANY_LINES, + NOT_UNSAFE_PTR_ARG_DEREF, + MUST_USE_UNIT, + DOUBLE_MUST_USE, + MUST_USE_CANDIDATE, + RESULT_UNIT_ERR, +]); + +impl<'tcx> LateLintPass<'tcx> for Functions { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: intravisit::FnKind<'tcx>, + decl: &'tcx hir::FnDecl<'_>, + body: &'tcx hir::Body<'_>, + span: Span, + hir_id: hir::HirId, + ) { + too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold); + too_many_lines::check_fn(cx, span, body, self.too_many_lines_threshold); + not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id); + } + + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { + must_use::check_item(cx, item); + result_unit_err::check_item(cx, item); + } + + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { + must_use::check_impl_item(cx, item); + result_unit_err::check_impl_item(cx, item); + } + + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { + too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold); + not_unsafe_ptr_arg_deref::check_trait_item(cx, item); + must_use::check_trait_item(cx, item); + result_unit_err::check_trait_item(cx, item); + } +} diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs new file mode 100644 index 0000000000..20288427b4 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -0,0 +1,272 @@ +use rustc_ast::ast::Attribute; +use rustc_errors::Applicability; +use rustc_hir::def_id::DefIdSet; +use rustc_hir::{self as hir, def::Res, intravisit, QPath}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::{ + hir::map::Map, + lint::in_external_macro, + ty::{self, Ty}, +}; +use rustc_span::{sym, Span}; + +use clippy_utils::attrs::is_proc_macro; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::is_must_use_ty; +use clippy_utils::{match_def_path, must_use_attr, return_ty, trait_ref_of_method}; + +use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT}; + +pub(super) fn check_item(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { + let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attr = must_use_attr(attrs); + if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind { + let is_public = cx.access_levels.is_exported(item.hir_id()); + let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); + if let Some(attr) = attr { + check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); + return; + } else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) { + check_must_use_candidate( + cx, + sig.decl, + cx.tcx.hir().body(*body_id), + item.span, + item.hir_id(), + item.span.with_hi(sig.decl.output.span().hi()), + "this function could have a `#[must_use]` attribute", + ); + } + } +} + +pub(super) fn check_impl_item(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { + if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { + let is_public = cx.access_levels.is_exported(item.hir_id()); + let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); + let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attr = must_use_attr(attrs); + if let Some(attr) = attr { + check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); + } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.hir_id()).is_none() { + check_must_use_candidate( + cx, + sig.decl, + cx.tcx.hir().body(*body_id), + item.span, + item.hir_id(), + item.span.with_hi(sig.decl.output.span().hi()), + "this method could have a `#[must_use]` attribute", + ); + } + } +} + +pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { + if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { + let is_public = cx.access_levels.is_exported(item.hir_id()); + let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); + + let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attr = must_use_attr(attrs); + if let Some(attr) = attr { + check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); + } else if let hir::TraitFn::Provided(eid) = *eid { + let body = cx.tcx.hir().body(eid); + if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) { + check_must_use_candidate( + cx, + sig.decl, + body, + item.span, + item.hir_id(), + item.span.with_hi(sig.decl.output.span().hi()), + "this method could have a `#[must_use]` attribute", + ); + } + } + } +} + +fn check_needless_must_use( + cx: &LateContext<'_>, + decl: &hir::FnDecl<'_>, + item_id: hir::HirId, + item_span: Span, + fn_header_span: Span, + attr: &Attribute, +) { + if in_external_macro(cx.sess(), item_span) { + return; + } + if returns_unit(decl) { + span_lint_and_then( + cx, + MUST_USE_UNIT, + fn_header_span, + "this unit-returning function has a `#[must_use]` attribute", + |diag| { + diag.span_suggestion( + attr.span, + "remove the attribute", + "".into(), + Applicability::MachineApplicable, + ); + }, + ); + } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) { + span_lint_and_help( + cx, + DOUBLE_MUST_USE, + fn_header_span, + "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`", + None, + "either add some descriptive text or remove the attribute", + ); + } +} + +fn check_must_use_candidate<'tcx>( + cx: &LateContext<'tcx>, + decl: &'tcx hir::FnDecl<'_>, + body: &'tcx hir::Body<'_>, + item_span: Span, + item_id: hir::HirId, + fn_span: Span, + msg: &str, +) { + if has_mutable_arg(cx, body) + || mutates_static(cx, body) + || in_external_macro(cx.sess(), item_span) + || returns_unit(decl) + || !cx.access_levels.is_exported(item_id) + || is_must_use_ty(cx, return_ty(cx, item_id)) + { + return; + } + span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| { + if let Some(snippet) = snippet_opt(cx, fn_span) { + diag.span_suggestion( + fn_span, + "add the attribute", + format!("#[must_use] {}", snippet), + Applicability::MachineApplicable, + ); + } + }); +} + +fn returns_unit(decl: &hir::FnDecl<'_>) -> bool { + match decl.output { + hir::FnRetTy::DefaultReturn(_) => true, + hir::FnRetTy::Return(ty) => match ty.kind { + hir::TyKind::Tup(tys) => tys.is_empty(), + hir::TyKind::Never => true, + _ => false, + }, + } +} + +fn has_mutable_arg(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool { + let mut tys = DefIdSet::default(); + body.params.iter().any(|param| is_mutable_pat(cx, param.pat, &mut tys)) +} + +fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) -> bool { + if let hir::PatKind::Wild = pat.kind { + return false; // ignore `_` patterns + } + if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) { + is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys) + } else { + false + } +} + +static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]]; + +fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool { + match *ty.kind() { + // primitive types are never mutable + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, + ty::Adt(adt, substs) => { + tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env) + || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path)) + && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)) + }, + ty::Tuple(substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)), + ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys), + ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => { + mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys) + }, + // calling something constitutes a side effect, so return true on all callables + // also never calls need not be used, so return true for them, too + _ => true, + } +} + +struct StaticMutVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + mutates_static: bool, +} + +impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { + use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall}; + + if self.mutates_static { + return; + } + match expr.kind { + Call(_, args) | MethodCall(_, _, args, _) => { + let mut tys = DefIdSet::default(); + for arg in args { + if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) + && is_mutable_ty( + self.cx, + self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg), + arg.span, + &mut tys, + ) + && is_mutated_static(arg) + { + self.mutates_static = true; + return; + } + tys.clear(); + } + }, + Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => { + self.mutates_static |= is_mutated_static(target) + }, + _ => {}, + } + } + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { + intravisit::NestedVisitorMap::None + } +} + +fn is_mutated_static(e: &hir::Expr<'_>) -> bool { + use hir::ExprKind::{Field, Index, Path}; + + match e.kind { + Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)), + Path(_) => true, + Field(inner, _) | Index(inner, _) => is_mutated_static(inner), + _ => false, + } +} + +fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool { + let mut v = StaticMutVisitor { + cx, + mutates_static: false, + }; + intravisit::walk_expr(&mut v, &body.value); + v.mutates_static +} diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs new file mode 100644 index 0000000000..b8ea699086 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -0,0 +1,124 @@ +use rustc_hir::{self as hir, intravisit, HirIdSet}; +use rustc_lint::LateContext; +use rustc_middle::{hir::map::Map, ty}; + +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::type_is_unsafe_function; +use clippy_utils::{iter_input_pats, path_to_local}; + +use super::NOT_UNSAFE_PTR_ARG_DEREF; + +pub(super) fn check_fn( + cx: &LateContext<'tcx>, + kind: intravisit::FnKind<'tcx>, + decl: &'tcx hir::FnDecl<'tcx>, + body: &'tcx hir::Body<'tcx>, + hir_id: hir::HirId, +) { + let unsafety = match kind { + intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety, + intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety, + intravisit::FnKind::Closure => return, + }; + + check_raw_ptr(cx, unsafety, decl, body, hir_id); +} + +pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { + if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind { + let body = cx.tcx.hir().body(eid); + check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.hir_id()); + } +} + +fn check_raw_ptr( + cx: &LateContext<'tcx>, + unsafety: hir::Unsafety, + decl: &'tcx hir::FnDecl<'tcx>, + body: &'tcx hir::Body<'tcx>, + hir_id: hir::HirId, +) { + let expr = &body.value; + if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) { + let raw_ptrs = iter_input_pats(decl, body) + .zip(decl.inputs.iter()) + .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty)) + .collect::<HirIdSet>(); + + if !raw_ptrs.is_empty() { + let typeck_results = cx.tcx.typeck_body(body.id()); + let mut v = DerefVisitor { + cx, + ptrs: raw_ptrs, + typeck_results, + }; + + intravisit::walk_expr(&mut v, expr); + } + } +} + +fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> { + if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) { + Some(id) + } else { + None + } +} + +struct DerefVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + ptrs: HirIdSet, + typeck_results: &'a ty::TypeckResults<'tcx>, +} + +impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { + match expr.kind { + hir::ExprKind::Call(f, args) => { + let ty = self.typeck_results.expr_ty(f); + + if type_is_unsafe_function(self.cx, ty) { + for arg in args { + self.check_arg(arg); + } + } + }, + hir::ExprKind::MethodCall(_, _, args, _) => { + let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap(); + let base_type = self.cx.tcx.type_of(def_id); + + if type_is_unsafe_function(self.cx, base_type) { + for arg in args { + self.check_arg(arg); + } + } + }, + hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => self.check_arg(ptr), + _ => (), + } + + intravisit::walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { + intravisit::NestedVisitorMap::None + } +} + +impl<'a, 'tcx> DerefVisitor<'a, 'tcx> { + fn check_arg(&self, ptr: &hir::Expr<'_>) { + if let Some(id) = path_to_local(ptr) { + if self.ptrs.contains(&id) { + span_lint( + self.cx, + NOT_UNSAFE_PTR_ARG_DEREF, + ptr.span, + "this public function dereferences a raw pointer but is not marked `unsafe`", + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs b/src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs new file mode 100644 index 0000000000..c073f312d3 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs @@ -0,0 +1,66 @@ +use rustc_hir as hir; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; +use rustc_span::{sym, Span}; +use rustc_typeck::hir_ty_to_ty; + +use if_chain::if_chain; + +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::trait_ref_of_method; +use clippy_utils::ty::is_type_diagnostic_item; + +use super::RESULT_UNIT_ERR; + +pub(super) fn check_item(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { + if let hir::ItemKind::Fn(ref sig, ref _generics, _) = item.kind { + let is_public = cx.access_levels.is_exported(item.hir_id()); + let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); + if is_public { + check_result_unit_err(cx, sig.decl, item.span, fn_header_span); + } + } +} + +pub(super) fn check_impl_item(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { + if let hir::ImplItemKind::Fn(ref sig, _) = item.kind { + let is_public = cx.access_levels.is_exported(item.hir_id()); + let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); + if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() { + check_result_unit_err(cx, sig.decl, item.span, fn_header_span); + } + } +} + +pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { + if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { + let is_public = cx.access_levels.is_exported(item.hir_id()); + let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); + if is_public { + check_result_unit_err(cx, sig.decl, item.span, fn_header_span); + } + } +} + +fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) { + if_chain! { + if !in_external_macro(cx.sess(), item_span); + if let hir::FnRetTy::Return(ty) = decl.output; + let ty = hir_ty_to_ty(cx.tcx, ty); + if is_type_diagnostic_item(cx, ty, sym::result_type); + if let ty::Adt(_, substs) = ty.kind(); + let err_ty = substs.type_at(1); + if err_ty.is_unit(); + then { + span_lint_and_help( + cx, + RESULT_UNIT_ERR, + fn_header_span, + "this returns a `Result<_, ()>`", + None, + "use a custom `Error` type instead", + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs new file mode 100644 index 0000000000..63a14d8d4c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs @@ -0,0 +1,73 @@ +use rustc_hir::{self as hir, intravisit}; +use rustc_lint::LateContext; +use rustc_span::Span; +use rustc_target::spec::abi::Abi; + +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_trait_impl_item; + +use super::TOO_MANY_ARGUMENTS; + +pub(super) fn check_fn( + cx: &LateContext<'tcx>, + kind: intravisit::FnKind<'tcx>, + decl: &'tcx hir::FnDecl<'_>, + span: Span, + hir_id: hir::HirId, + too_many_arguments_threshold: u64, +) { + // don't warn for implementations, it's not their fault + if !is_trait_impl_item(cx, hir_id) { + // don't lint extern functions decls, it's not their fault either + match kind { + intravisit::FnKind::Method( + _, + &hir::FnSig { + header: hir::FnHeader { abi: Abi::Rust, .. }, + .. + }, + _, + ) + | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => check_arg_number( + cx, + decl, + span.with_hi(decl.output.span().hi()), + too_many_arguments_threshold, + ), + _ => {}, + } + } +} + +pub(super) fn check_trait_item( + cx: &LateContext<'tcx>, + item: &'tcx hir::TraitItem<'_>, + too_many_arguments_threshold: u64, +) { + if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { + // don't lint extern functions decls, it's not their fault + if sig.header.abi == Abi::Rust { + check_arg_number( + cx, + sig.decl, + item.span.with_hi(sig.decl.output.span().hi()), + too_many_arguments_threshold, + ); + } + } +} + +fn check_arg_number(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span, too_many_arguments_threshold: u64) { + let args = decl.inputs.len() as u64; + if args > too_many_arguments_threshold { + span_lint( + cx, + TOO_MANY_ARGUMENTS, + fn_span, + &format!( + "this function has too many arguments ({}/{})", + args, too_many_arguments_threshold + ), + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs new file mode 100644 index 0000000000..aa5494d5a7 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs @@ -0,0 +1,68 @@ +use rustc_hir as hir; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_span::Span; + +use clippy_utils::diagnostics::span_lint; +use clippy_utils::source::snippet; + +use super::TOO_MANY_LINES; + +pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>, too_many_lines_threshold: u64) { + if in_external_macro(cx.sess(), span) { + return; + } + + let code_snippet = snippet(cx, body.value.span, ".."); + let mut line_count: u64 = 0; + let mut in_comment = false; + let mut code_in_line; + + // Skip the surrounding function decl. + let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1); + let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len()); + let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines(); + + for mut line in function_lines { + code_in_line = false; + loop { + line = line.trim_start(); + if line.is_empty() { + break; + } + if in_comment { + if let Some(i) = line.find("*/") { + line = &line[i + 2..]; + in_comment = false; + continue; + } + } else { + let multi_idx = line.find("/*").unwrap_or_else(|| line.len()); + let single_idx = line.find("//").unwrap_or_else(|| line.len()); + code_in_line |= multi_idx > 0 && single_idx > 0; + // Implies multi_idx is below line.len() + if multi_idx < single_idx { + line = &line[multi_idx + 2..]; + in_comment = true; + continue; + } + } + break; + } + if code_in_line { + line_count += 1; + } + } + + if line_count > too_many_lines_threshold { + span_lint( + cx, + TOO_MANY_LINES, + span, + &format!( + "this function has too many lines ({}/{})", + line_count, too_many_lines_threshold + ), + ) + } +} diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 9e1a8864a3..04730ace88 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -1,4 +1,5 @@ -use crate::utils; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::return_ty; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, HirId}; use rustc_infer::infer::TyCtxtInferExt; @@ -61,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if let FnKind::Closure = kind { return; } - let ret_ty = utils::return_ty(cx, hir_id); + let ret_ty = return_ty(cx, hir_id); if let Opaque(id, subst) = *ret_ty.kind() { let preds = cx.tcx.explicit_item_bounds(id); let mut is_future = false; @@ -84,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { fulfillment_cx.select_all_or_error(&infcx) }); if let Err(send_errors) = send_result { - utils::span_lint_and_then( + span_lint_and_then( cx, FUTURE_NOT_SEND, span, diff --git a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs index cdd8a42e7c..3707e79217 100644 --- a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs +++ b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs @@ -1,6 +1,9 @@ //! lint on using `x.get(x.len() - 1)` instead of `x.last()` -use crate::utils::{is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::SpanlessEq; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -48,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for GetLastWithLen { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { // Is a method call - if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; + if let ExprKind::MethodCall(path, _, args, _) = expr.kind; // Method name is "get" if path.ident.name == sym!(get); diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs index 8501d34770..366b3b46a8 100644 --- a/src/tools/clippy/clippy_lints/src/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/identity_op.rs @@ -1,3 +1,4 @@ +use clippy_utils::source::snippet; use if_chain::if_chain; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -6,7 +7,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use crate::consts::{constant_simple, Constant}; -use crate::utils::{clip, snippet, span_lint, unsext}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{clip, unsext}; declare_clippy_lint! { /// **What it does:** Checks for identity operations, e.g., `x + 0`. @@ -33,7 +35,7 @@ impl<'tcx> LateLintPass<'tcx> for IdentityOp { if e.span.from_expansion() { return; } - if let ExprKind::Binary(cmp, ref left, ref right) = e.kind { + if let ExprKind::Binary(cmp, left, right) = e.kind { if is_allowed(cx, cmp, left, right) { return; } diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs index 58511c6d57..f661f7ede8 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs @@ -1,4 +1,6 @@ -use crate::utils::{is_type_diagnostic_item, span_lint_and_help, SpanlessEq}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::SpanlessEq; use if_chain::if_chain; use rustc_hir::intravisit::{self as visit, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, ExprKind, MatchSource}; @@ -53,8 +55,8 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex { cx, }; if let ExprKind::Match( - ref op, - ref arms, + op, + arms, MatchSource::IfLetDesugar { contains_else_clause: true, }, @@ -62,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex { { op_visit.visit_expr(op); if op_visit.mutex_lock_called { - for arm in *arms { + for arm in arms { arm_visit.visit_arm(arm); } @@ -92,13 +94,10 @@ impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if_chain! { - if let Some(mutex) = is_mutex_lock_call(self.cx, expr); - then { - self.found_mutex = Some(mutex); - self.mutex_lock_called = true; - return; - } + if let Some(mutex) = is_mutex_lock_call(self.cx, expr) { + self.found_mutex = Some(mutex); + self.mutex_lock_called = true; + return; } visit::walk_expr(self, expr); } @@ -119,13 +118,10 @@ impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - if_chain! { - if let Some(mutex) = is_mutex_lock_call(self.cx, expr); - then { - self.found_mutex = Some(mutex); - self.mutex_lock_called = true; - return; - } + if let Some(mutex) = is_mutex_lock_call(self.cx, expr) { + self.found_mutex = Some(mutex); + self.mutex_lock_called = true; + return; } visit::walk_expr(self, expr); } diff --git a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs index 1194bd7e55..611da3744e 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs @@ -1,4 +1,7 @@ -use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::method_chain_args; +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::{Expr, ExprKind, MatchSource, PatKind, QPath}; @@ -41,9 +44,9 @@ declare_lint_pass!(OkIfLet => [IF_LET_SOME_RESULT]); impl<'tcx> LateLintPass<'tcx> for OkIfLet { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { //begin checking variables - if let ExprKind::Match(ref op, ref body, MatchSource::IfLetDesugar { .. }) = expr.kind; //test if expr is if let - if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _) - if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation + if let ExprKind::Match(op, body, MatchSource::IfLetDesugar { .. }) = expr.kind; //test if expr is if let + if let ExprKind::MethodCall(_, ok_span, result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _) + if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _) = body[0].pat.kind; //get operation if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&result_types[0]), sym::result_type); if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some"; diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs index b86d2e7665..c56f67df06 100644 --- a/src/tools/clippy/clippy_lints/src/if_not_else.rs +++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs @@ -1,13 +1,12 @@ //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition +use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::span_lint_and_help; - declare_clippy_lint! { /// **What it does:** Checks for usage of `!` or `!=` in an if condition with an /// else branch. diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs new file mode 100644 index 0000000000..eadcd0867a --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs @@ -0,0 +1,116 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet_with_macro_callsite; +use clippy_utils::{is_else_clause, is_lang_ctor, meets_msrv, msrvs}; +use if_chain::if_chain; +use rustc_hir::LangItem::{OptionNone, OptionSome}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +declare_clippy_lint! { + /// **What it does:** Checks for if-else that could be written to `bool::then`. + /// + /// **Why is this bad?** Looks a little redundant. Using `bool::then` helps it have less lines of code. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// # let v = vec![0]; + /// let a = if v.is_empty() { + /// println!("true!"); + /// Some(42) + /// } else { + /// None + /// }; + /// ``` + /// + /// Could be written: + /// + /// ```rust + /// # let v = vec![0]; + /// let a = v.is_empty().then(|| { + /// println!("true!"); + /// 42 + /// }); + /// ``` + pub IF_THEN_SOME_ELSE_NONE, + restriction, + "Finds if-else that could be written using `bool::then`" +} + +pub struct IfThenSomeElseNone { + msrv: Option<RustcVersion>, +} + +impl IfThenSomeElseNone { + #[must_use] + pub fn new(msrv: Option<RustcVersion>) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(IfThenSomeElseNone => [IF_THEN_SOME_ELSE_NONE]); + +impl LateLintPass<'_> for IfThenSomeElseNone { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::BOOL_THEN) { + return; + } + + if in_external_macro(cx.sess(), expr.span) { + return; + } + + // We only care about the top-most `if` in the chain + if is_else_clause(cx.tcx, expr) { + return; + } + + if_chain! { + if let ExprKind::If(cond, then, Some(els)) = expr.kind; + if let ExprKind::Block(then_block, _) = then.kind; + if let Some(then_expr) = then_block.expr; + if let ExprKind::Call(then_call, [then_arg]) = then_expr.kind; + if let ExprKind::Path(ref then_call_qpath) = then_call.kind; + if is_lang_ctor(cx, then_call_qpath, OptionSome); + if let ExprKind::Block(els_block, _) = els.kind; + if els_block.stmts.is_empty(); + if let Some(els_expr) = els_block.expr; + if let ExprKind::Path(ref qpath) = els_expr.kind; + if is_lang_ctor(cx, qpath, OptionNone); + then { + let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]"); + let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) { + format!("({})", cond_snip) + } else { + cond_snip.into_owned() + }; + let arg_snip = snippet_with_macro_callsite(cx, then_arg.span, ""); + let closure_body = if then_block.stmts.is_empty() { + arg_snip.into_owned() + } else { + format!("{{ /* snippet */ {} }}", arg_snip) + }; + let help = format!( + "consider using `bool::then` like: `{}.then(|| {})`", + cond_snip, + closure_body, + ); + span_lint_and_help( + cx, + IF_THEN_SOME_ELSE_NONE, + expr.span, + "this could be simplified with `bool::then`", + None, + &help, + ); + } + } + } + + extract_msrv_attr!(LateContext); +} diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs new file mode 100644 index 0000000000..03fe0d16d4 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -0,0 +1,378 @@ +#![allow(rustc::default_hash_types)] + +use std::borrow::Cow; +use std::collections::BTreeMap; + +use rustc_errors::DiagnosticBuilder; +use rustc_hir as hir; +use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, NestedVisitorMap, Visitor}; +use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{Ty, TyS, TypeckResults}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Span; +use rustc_span::symbol::sym; +use rustc_typeck::hir_ty_to_ty; + +use if_chain::if_chain; + +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; +use clippy_utils::paths; +use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{differing_macro_contexts, match_def_path}; + +declare_clippy_lint! { + /// **What it does:** Checks for public `impl` or `fn` missing generalization + /// over different hashers and implicitly defaulting to the default hashing + /// algorithm (`SipHash`). + /// + /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be + /// used with them. + /// + /// **Known problems:** Suggestions for replacing constructors can contain + /// false-positives. Also applying suggestions can require modification of other + /// pieces of code, possibly including external crates. + /// + /// **Example:** + /// ```rust + /// # use std::collections::HashMap; + /// # use std::hash::{Hash, BuildHasher}; + /// # trait Serialize {}; + /// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { } + /// + /// pub fn foo(map: &mut HashMap<i32, i32>) { } + /// ``` + /// could be rewritten as + /// ```rust + /// # use std::collections::HashMap; + /// # use std::hash::{Hash, BuildHasher}; + /// # trait Serialize {}; + /// impl<K: Hash + Eq, V, S: BuildHasher> Serialize for HashMap<K, V, S> { } + /// + /// pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { } + /// ``` + pub IMPLICIT_HASHER, + pedantic, + "missing generalization over different hashers" +} + +declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]); + +impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { + #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)] + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + use rustc_span::BytePos; + + fn suggestion<'tcx>( + cx: &LateContext<'tcx>, + diag: &mut DiagnosticBuilder<'_>, + generics_span: Span, + generics_suggestion_span: Span, + target: &ImplicitHasherType<'_>, + vis: ImplicitHasherConstructorVisitor<'_, '_, '_>, + ) { + let generics_snip = snippet(cx, generics_span, ""); + // trim `<` `>` + let generics_snip = if generics_snip.is_empty() { + "" + } else { + &generics_snip[1..generics_snip.len() - 1] + }; + + multispan_sugg( + diag, + "consider adding a type parameter", + vec![ + ( + generics_suggestion_span, + format!( + "<{}{}S: ::std::hash::BuildHasher{}>", + generics_snip, + if generics_snip.is_empty() { "" } else { ", " }, + if vis.suggestions.is_empty() { + "" + } else { + // request users to add `Default` bound so that generic constructors can be used + " + Default" + }, + ), + ), + ( + target.span(), + format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + ), + ], + ); + + if !vis.suggestions.is_empty() { + multispan_sugg(diag, "...and use generic constructor", vis.suggestions); + } + } + + if !cx.access_levels.is_exported(item.hir_id()) { + return; + } + + match item.kind { + ItemKind::Impl(ref impl_) => { + let mut vis = ImplicitHasherTypeVisitor::new(cx); + vis.visit_ty(impl_.self_ty); + + for target in &vis.found { + if differing_macro_contexts(item.span, target.span()) { + return; + } + + let generics_suggestion_span = impl_.generics.span.substitute_dummy({ + let pos = snippet_opt(cx, item.span.until(target.span())) + .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))); + if let Some(pos) = pos { + Span::new(pos, pos, item.span.data().ctxt) + } else { + return; + } + }); + + let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); + for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) { + ctr_vis.visit_impl_item(item); + } + + span_lint_and_then( + cx, + IMPLICIT_HASHER, + target.span(), + &format!( + "impl for `{}` should be generalized over different hashers", + target.type_name() + ), + move |diag| { + suggestion(cx, diag, impl_.generics.span, generics_suggestion_span, target, ctr_vis); + }, + ); + } + }, + ItemKind::Fn(ref sig, ref generics, body_id) => { + let body = cx.tcx.hir().body(body_id); + + for ty in sig.decl.inputs { + let mut vis = ImplicitHasherTypeVisitor::new(cx); + vis.visit_ty(ty); + + for target in &vis.found { + if in_external_macro(cx.sess(), generics.span) { + continue; + } + let generics_suggestion_span = generics.span.substitute_dummy({ + let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span)) + .and_then(|snip| { + let i = snip.find("fn")?; + Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32)) + }) + .expect("failed to create span for type parameters"); + Span::new(pos, pos, item.span.data().ctxt) + }); + + let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); + ctr_vis.visit_body(body); + + span_lint_and_then( + cx, + IMPLICIT_HASHER, + target.span(), + &format!( + "parameter of type `{}` should be generalized over different hashers", + target.type_name() + ), + move |diag| { + suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis); + }, + ); + } + } + }, + _ => {}, + } + } +} + +enum ImplicitHasherType<'tcx> { + HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>), + HashSet(Span, Ty<'tcx>, Cow<'static, str>), +} + +impl<'tcx> ImplicitHasherType<'tcx> { + /// Checks that `ty` is a target type without a `BuildHasher`. + fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> { + if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind { + let params: Vec<_> = path + .segments + .last() + .as_ref()? + .args + .as_ref()? + .args + .iter() + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }) + .collect(); + let params_len = params.len(); + + let ty = hir_ty_to_ty(cx.tcx, hir_ty); + + if is_type_diagnostic_item(cx, ty, sym::hashmap_type) && params_len == 2 { + Some(ImplicitHasherType::HashMap( + hir_ty.span, + ty, + snippet(cx, params[0].span, "K"), + snippet(cx, params[1].span, "V"), + )) + } else if is_type_diagnostic_item(cx, ty, sym::hashset_type) && params_len == 1 { + Some(ImplicitHasherType::HashSet( + hir_ty.span, + ty, + snippet(cx, params[0].span, "T"), + )) + } else { + None + } + } else { + None + } + } + + fn type_name(&self) -> &'static str { + match *self { + ImplicitHasherType::HashMap(..) => "HashMap", + ImplicitHasherType::HashSet(..) => "HashSet", + } + } + + fn type_arguments(&self) -> String { + match *self { + ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v), + ImplicitHasherType::HashSet(.., ref t) => format!("{}", t), + } + } + + fn ty(&self) -> Ty<'tcx> { + match *self { + ImplicitHasherType::HashMap(_, ty, ..) | ImplicitHasherType::HashSet(_, ty, ..) => ty, + } + } + + fn span(&self) -> Span { + match *self { + ImplicitHasherType::HashMap(span, ..) | ImplicitHasherType::HashSet(span, ..) => span, + } + } +} + +struct ImplicitHasherTypeVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + found: Vec<ImplicitHasherType<'tcx>>, +} + +impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'tcx>) -> Self { + Self { cx, found: vec![] } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) { + if let Some(target) = ImplicitHasherType::new(self.cx, t) { + self.found.push(target); + } + + walk_ty(self, t); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} + +/// Looks for default-hasher-dependent constructors like `HashMap::new`. +struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { + cx: &'a LateContext<'tcx>, + maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>, + target: &'b ImplicitHasherType<'tcx>, + suggestions: BTreeMap<Span, String>, +} + +impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { + fn new(cx: &'a LateContext<'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self { + Self { + cx, + maybe_typeck_results: cx.maybe_typeck_results(), + target, + suggestions: BTreeMap::new(), + } + } +} + +impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { + type Map = Map<'tcx>; + + fn visit_body(&mut self, body: &'tcx Body<'_>) { + let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body.id())); + walk_body(self, body); + self.maybe_typeck_results = old_maybe_typeck_results; + } + + fn visit_expr(&mut self, e: &'tcx Expr<'_>) { + if_chain! { + if let ExprKind::Call(fun, args) = e.kind; + if let ExprKind::Path(QPath::TypeRelative(ty, method)) = fun.kind; + if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind; + if let Some(ty_did) = ty_path.res.opt_def_id(); + then { + if !TyS::same_type(self.target.ty(), self.maybe_typeck_results.unwrap().expr_ty(e)) { + return; + } + + if match_def_path(self.cx, ty_did, &paths::HASHMAP) { + if method.ident.name == sym::new { + self.suggestions + .insert(e.span, "HashMap::default()".to_string()); + } else if method.ident.name == sym!(with_capacity) { + self.suggestions.insert( + e.span, + format!( + "HashMap::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); + } + } else if match_def_path(self.cx, ty_did, &paths::HASHSET) { + if method.ident.name == sym::new { + self.suggestions + .insert(e.span, "HashSet::default()".to_string()); + } else if method.ident.name == sym!(with_capacity) { + self.suggestions.insert( + e.span, + format!( + "HashSet::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); + } + } + } + } + + walk_expr(self, e); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) + } +} diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index b4f814e1dc..6b379b0d59 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -1,4 +1,6 @@ -use crate::utils::{match_panic_def_id, snippet_opt, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::match_panic_def_id; +use clippy_utils::source::snippet_opt; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; @@ -98,10 +100,10 @@ fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) { if check_all_arms { for arm in arms { - expr_match(cx, &arm.body); + expr_match(cx, arm.body); } } else { - expr_match(cx, &arms.first().expect("`if let` doesn't have a single arm").body); + expr_match(cx, arms.first().expect("`if let` doesn't have a single arm").body); } }, // skip if it already has a return statement diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 16e162badb..4069a685ea 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -1,8 +1,9 @@ -use crate::utils::{in_macro, match_qpath, span_lint_and_sugg, SpanlessEq}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{in_macro, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, StmtKind}; +use rustc_hir::{lang_items::LangItem, BinOpKind, Expr, ExprKind, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -45,21 +46,21 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if let ExprKind::If(cond, then, None) = &expr.kind; // Check if the conditional expression is a binary operation - if let ExprKind::Binary(ref cond_op, ref cond_left, ref cond_right) = cond.kind; + if let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind; // Ensure that the binary operator is >, != and < if BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node; // Check if the true condition block has only one statement - if let ExprKind::Block(ref block, _) = then.kind; + if let ExprKind::Block(block, _) = then.kind; if block.stmts.len() == 1 && block.expr.is_none(); // Check if assign operation is done - if let StmtKind::Semi(ref e) = block.stmts[0].kind; + if let StmtKind::Semi(e) = block.stmts[0].kind; if let Some(target) = subtracts_one(cx, e); // Extracting out the variable name - if let ExprKind::Path(QPath::Resolved(_, ref ares_path)) = target.kind; + if let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind; then { // Handle symmetric conditions in the if statement @@ -86,7 +87,13 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { // Get the variable name let var_name = ares_path.segments[0].ident.name.as_str(); - const INT_TYPES: [&str; 5] = ["i8", "i16", "i32", "i64", "i128"]; + const INT_TYPES: [LangItem; 5] = [ + LangItem::I8, + LangItem::I16, + LangItem::I32, + LangItem::I64, + LangItem::Isize + ]; match cond_num_val.kind { ExprKind::Lit(ref cond_lit) => { @@ -98,17 +105,30 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { }; } }, - ExprKind::Path(ref cond_num_path) => { - if INT_TYPES.iter().any(|int_type| match_qpath(cond_num_path, &[int_type, "MIN"])) { - print_lint_and_sugg(cx, &var_name, expr); - }; + ExprKind::Path(QPath::TypeRelative(_, name)) => { + if_chain! { + if name.ident.as_str() == "MIN"; + if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id); + if let Some(impl_id) = cx.tcx.impl_of_method(const_id); + let mut int_ids = INT_TYPES.iter().filter_map(|&ty| cx.tcx.lang_items().require(ty).ok()); + if int_ids.any(|int_id| int_id == impl_id); + then { + print_lint_and_sugg(cx, &var_name, expr) + } + } }, - ExprKind::Call(ref func, _) => { - if let ExprKind::Path(ref cond_num_path) = func.kind { - if INT_TYPES.iter().any(|int_type| match_qpath(cond_num_path, &[int_type, "min_value"])) { - print_lint_and_sugg(cx, &var_name, expr); + ExprKind::Call(func, []) => { + if_chain! { + if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind; + if name.ident.as_str() == "min_value"; + if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id); + if let Some(impl_id) = cx.tcx.impl_of_method(func_id); + let mut int_ids = INT_TYPES.iter().filter_map(|&ty| cx.tcx.lang_items().require(ty).ok()); + if int_ids.any(|int_id| int_id == impl_id); + then { + print_lint_and_sugg(cx, &var_name, expr) } - }; + } }, _ => (), } @@ -119,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &Expr<'a>) -> Option<&'a Expr<'a>> { match expr.kind { - ExprKind::AssignOp(ref op1, ref target, ref value) => { + ExprKind::AssignOp(ref op1, target, value) => { if_chain! { if BinOpKind::Sub == op1.node; // Check if literal being subtracted is one @@ -132,9 +152,9 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &Expr<'a>) -> Option<&'a Expr<' } } }, - ExprKind::Assign(ref target, ref value, _) => { + ExprKind::Assign(target, value, _) => { if_chain! { - if let ExprKind::Binary(ref op1, ref left1, ref right1) = value.kind; + if let ExprKind::Binary(ref op1, left1, right1) = value.kind; if BinOpKind::Sub == op1.node; if SpanlessEq::new(cx).eq_expr(left1, target); diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs index 48aef74e4d..d138c3a8ac 100644 --- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs @@ -1,3 +1,7 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; +use clippy_utils::source::snippet; +use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::{self as hir, ExprKind}; @@ -5,13 +9,10 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; -use if_chain::if_chain; - -use crate::utils::{snippet, span_lint_and_sugg}; - declare_clippy_lint! { - /// **What it does:** Checks for struct constructors where the order of the field init - /// shorthand in the constructor is inconsistent with the order in the struct definition. + /// **What it does:** Checks for struct constructors where all fields are shorthand and + /// the order of the field init shorthand in the constructor is inconsistent + /// with the order in the struct definition. /// /// **Why is this bad?** Since the order of fields in a constructor doesn't affect the /// resulted instance as the below example indicates, @@ -25,11 +26,11 @@ declare_clippy_lint! { /// let x = 1; /// let y = 2; /// - /// // This assertion never fails. + /// // This assertion never fails: /// assert_eq!(Foo { x, y }, Foo { y, x }); /// ``` /// - /// inconsistent order means nothing and just decreases readability and consistency. + /// inconsistent order can be confusing and decreases readability and consistency. /// /// **Known problems:** None. /// @@ -42,6 +43,7 @@ declare_clippy_lint! { /// } /// let x = 1; /// let y = 2; + /// /// Foo { y, x }; /// ``` /// @@ -65,6 +67,7 @@ declare_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRU impl LateLintPass<'_> for InconsistentStructConstructor { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { + if !in_macro(expr.span); if let ExprKind::Struct(qpath, fields, base) = expr.kind; let ty = cx.typeck_results().expr_ty(expr); if let Some(adt_def) = ty.ty_adt_def(); @@ -107,7 +110,7 @@ impl LateLintPass<'_> for InconsistentStructConstructor { cx, INCONSISTENT_STRUCT_CONSTRUCTOR, expr.span, - "inconsistent struct constructor", + "struct constructor field order is inconsistent with struct definition field order", "try", sugg, Applicability::MachineApplicable, diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index c919ec097a..1c54599abc 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -1,7 +1,8 @@ //! lint on indexing and slicing operations use crate::consts::{constant, Constant}; -use crate::utils::{higher, span_lint, span_lint_and_help}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::higher; use rustc_ast::ast::RangeLimits; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -87,7 +88,7 @@ declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING] impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Index(ref array, ref index) = &expr.kind { + if let ExprKind::Index(array, index) = &expr.kind { let ty = cx.typeck_results().expr_ty(array).peel_refs(); if let Some(range) = higher::range(index) { // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..] diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index 7040ac3191..afee20ce43 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -1,9 +1,10 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::{implements_trait, match_type}; +use clippy_utils::{get_trait_def_id, higher, is_qpath_def_path, paths}; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint}; - declare_clippy_lint! { /// **What it does:** Checks for iteration that is guaranteed to be infinite. /// @@ -138,7 +139,7 @@ const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { match expr.kind { - ExprKind::MethodCall(ref method, _, ref args, _) => { + ExprKind::MethodCall(method, _, args, _) => { for &(name, len, heuristic, cap) in &HEURISTICS { if method.ident.name.as_str() == name && args.len() == len { return (match heuristic { @@ -158,11 +159,11 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { } Finite }, - ExprKind::Block(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), - ExprKind::Box(ref e) | ExprKind::AddrOf(BorrowKind::Ref, _, ref e) => is_infinite(cx, e), - ExprKind::Call(ref path, _) => { + ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), + ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e), + ExprKind::Call(path, _) => { if let ExprKind::Path(ref qpath) = path.kind { - match_qpath(qpath, &paths::REPEAT).into() + is_qpath_def_path(cx, qpath, path.hir_id, &paths::ITER_REPEAT).into() } else { Finite } @@ -214,7 +215,7 @@ const INFINITE_COLLECTORS: [&[&str]; 8] = [ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { match expr.kind { - ExprKind::MethodCall(ref method, _, ref args, _) => { + ExprKind::MethodCall(method, _, args, _) => { for &(name, len) in &COMPLETING_METHODS { if method.ident.name.as_str() == name && args.len() == len { return is_infinite(cx, &args[0]); @@ -239,7 +240,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { } } }, - ExprKind::Binary(op, ref l, ref r) => { + ExprKind::Binary(op, l, r) => { if op.node.is_comparison() { return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite); } diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index 005c461f10..c31013e49b 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -1,7 +1,8 @@ //! lint on inherent implementations -use crate::utils::{in_macro, span_lint_and_then}; -use rustc_data_structures::fx::FxHashMap; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::in_macro; +use rustc_hir::def_id::DefIdMap; use rustc_hir::{def_id, Crate, Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -42,7 +43,7 @@ declare_clippy_lint! { #[allow(clippy::module_name_repetitions)] #[derive(Default)] pub struct MultipleInherentImpl { - impls: FxHashMap<def_id::DefId, Span>, + impls: DefIdMap<Span>, } impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]); diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index c1f3e1d9d6..b023e13e84 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -1,14 +1,12 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method}; use if_chain::if_chain; use rustc_hir::{ImplItem, ImplItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; -use crate::utils::{ - get_trait_def_id, implements_trait, is_type_diagnostic_item, paths, return_ty, span_lint_and_help, - trait_ref_of_method, -}; - declare_clippy_lint! { /// **What it does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`. /// diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 00acbd6cc3..20f00bd51b 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -1,7 +1,7 @@ //! checks for `#[inline]` on trait methods without bodies -use crate::utils::span_lint_and_then; -use crate::utils::sugg::DiagnosticBuilderExt; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::DiagnosticBuilderExt; use rustc_ast::ast::Attribute; use rustc_errors::Applicability; use rustc_hir::{TraitFn, TraitItem, TraitItemKind}; diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs index 260b8988d3..c4a1222b51 100644 --- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs +++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs @@ -1,12 +1,12 @@ //! lint on blocks unnecessarily using >= with a + 1 or - 1 +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{snippet_opt, span_lint_and_sugg}; - declare_clippy_lint! { /// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block /// diff --git a/src/tools/clippy/clippy_lints/src/integer_division.rs b/src/tools/clippy/clippy_lints/src/integer_division.rs index 39b4605e72..e5482f675e 100644 --- a/src/tools/clippy/clippy_lints/src/integer_division.rs +++ b/src/tools/clippy/clippy_lints/src/integer_division.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_help; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs new file mode 100644 index 0000000000..c67c02eefa --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs @@ -0,0 +1,221 @@ +use std::cmp::Ordering; + +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, IntTy, UintTy}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; +use rustc_target::abi::LayoutOf; + +use crate::consts::{constant, Constant}; + +use clippy_utils::comparisons::Rel; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::source::snippet; +use clippy_utils::{comparisons, sext}; + +declare_clippy_lint! { + /// **What it does:** Checks for comparisons where the relation is always either + /// true or false, but where one side has been upcast so that the comparison is + /// necessary. Only integer types are checked. + /// + /// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300` + /// will mistakenly imply that it is possible for `x` to be outside the range of + /// `u8`. + /// + /// **Known problems:** + /// https://github.com/rust-lang/rust-clippy/issues/886 + /// + /// **Example:** + /// ```rust + /// let x: u8 = 1; + /// (x as u32) > 300; + /// ``` + pub INVALID_UPCAST_COMPARISONS, + pedantic, + "a comparison involving an upcast which is always true or false" +} + +declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]); + +#[derive(Copy, Clone, Debug, Eq)] +enum FullInt { + S(i128), + U(u128), +} + +impl FullInt { + #[allow(clippy::cast_sign_loss)] + #[must_use] + fn cmp_s_u(s: i128, u: u128) -> Ordering { + if s < 0 { + Ordering::Less + } else if u > (i128::MAX as u128) { + Ordering::Greater + } else { + (s as u128).cmp(&u) + } + } +} + +impl PartialEq for FullInt { + #[must_use] + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal + } +} + +impl PartialOrd for FullInt { + #[must_use] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(match (self, other) { + (&Self::S(s), &Self::S(o)) => s.cmp(&o), + (&Self::U(s), &Self::U(o)) => s.cmp(&o), + (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o), + (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(), + }) + } +} + +impl Ord for FullInt { + #[must_use] + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other) + .expect("`partial_cmp` for FullInt can never return `None`") + } +} + +fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> { + if let ExprKind::Cast(cast_exp, _) = expr.kind { + let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp); + let cast_ty = cx.typeck_results().expr_ty(expr); + // if it's a cast from i32 to u32 wrapping will invalidate all these checks + if cx.layout_of(pre_cast_ty).ok().map(|l| l.size) == cx.layout_of(cast_ty).ok().map(|l| l.size) { + return None; + } + match pre_cast_ty.kind() { + ty::Int(int_ty) => Some(match int_ty { + IntTy::I8 => (FullInt::S(i128::from(i8::MIN)), FullInt::S(i128::from(i8::MAX))), + IntTy::I16 => (FullInt::S(i128::from(i16::MIN)), FullInt::S(i128::from(i16::MAX))), + IntTy::I32 => (FullInt::S(i128::from(i32::MIN)), FullInt::S(i128::from(i32::MAX))), + IntTy::I64 => (FullInt::S(i128::from(i64::MIN)), FullInt::S(i128::from(i64::MAX))), + IntTy::I128 => (FullInt::S(i128::MIN), FullInt::S(i128::MAX)), + IntTy::Isize => (FullInt::S(isize::MIN as i128), FullInt::S(isize::MAX as i128)), + }), + ty::Uint(uint_ty) => Some(match uint_ty { + UintTy::U8 => (FullInt::U(u128::from(u8::MIN)), FullInt::U(u128::from(u8::MAX))), + UintTy::U16 => (FullInt::U(u128::from(u16::MIN)), FullInt::U(u128::from(u16::MAX))), + UintTy::U32 => (FullInt::U(u128::from(u32::MIN)), FullInt::U(u128::from(u32::MAX))), + UintTy::U64 => (FullInt::U(u128::from(u64::MIN)), FullInt::U(u128::from(u64::MAX))), + UintTy::U128 => (FullInt::U(u128::MIN), FullInt::U(u128::MAX)), + UintTy::Usize => (FullInt::U(usize::MIN as u128), FullInt::U(usize::MAX as u128)), + }), + _ => None, + } + } else { + None + } +} + +fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> { + let val = constant(cx, cx.typeck_results(), expr)?.0; + if let Constant::Int(const_int) = val { + match *cx.typeck_results().expr_ty(expr).kind() { + ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), + ty::Uint(_) => Some(FullInt::U(const_int)), + _ => None, + } + } else { + None + } +} + +fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) { + if let ExprKind::Cast(cast_val, _) = expr.kind { + span_lint( + cx, + INVALID_UPCAST_COMPARISONS, + span, + &format!( + "because of the numeric bounds on `{}` prior to casting, this expression is always {}", + snippet(cx, cast_val.span, "the expression"), + if always { "true" } else { "false" }, + ), + ); + } +} + +fn upcast_comparison_bounds_err<'tcx>( + cx: &LateContext<'tcx>, + span: Span, + rel: comparisons::Rel, + lhs_bounds: Option<(FullInt, FullInt)>, + lhs: &'tcx Expr<'_>, + rhs: &'tcx Expr<'_>, + invert: bool, +) { + if let Some((lb, ub)) = lhs_bounds { + if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { + if rel == Rel::Eq || rel == Rel::Ne { + if norm_rhs_val < lb || norm_rhs_val > ub { + err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); + } + } else if match rel { + Rel::Lt => { + if invert { + norm_rhs_val < lb + } else { + ub < norm_rhs_val + } + }, + Rel::Le => { + if invert { + norm_rhs_val <= lb + } else { + ub <= norm_rhs_val + } + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { + err_upcast_comparison(cx, span, lhs, true) + } else if match rel { + Rel::Lt => { + if invert { + norm_rhs_val >= ub + } else { + lb >= norm_rhs_val + } + }, + Rel::Le => { + if invert { + norm_rhs_val > ub + } else { + lb > norm_rhs_val + } + }, + Rel::Eq | Rel::Ne => unreachable!(), + } { + err_upcast_comparison(cx, span, lhs, false) + } + } + } +} + +impl<'tcx> LateLintPass<'tcx> for InvalidUpcastComparisons { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Binary(ref cmp, lhs, rhs) = expr.kind { + let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); + let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { + val + } else { + return; + }; + + let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); + let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); + + upcast_comparison_bounds_err(cx, expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false); + upcast_comparison_bounds_err(cx, expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs index 0927d21844..c69571f32a 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs @@ -1,6 +1,6 @@ //! lint when items are used after statements -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Block, ItemKind, StmtKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index a76595ed08..48dc5fefe9 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -1,5 +1,5 @@ use crate::rustc_target::abi::LayoutOf; -use crate::utils::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_and_then; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index ab4cb33612..f166748d86 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -1,6 +1,7 @@ //! lint when there is a large size difference between variants on an enum -use crate::utils::{snippet_opt, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind, VariantData}; use rustc_lint::{LateContext, LateLintPass}; @@ -112,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { ); if variant.fields.len() == 1 { let span = match def.variants[i].data { - VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => { + VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) => { fields[0].ty.span }, VariantData::Unit(..) => unreachable!(), diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 9a448ab125..c46b98022c 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -1,13 +1,13 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet; +use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::{self, ConstKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use if_chain::if_chain; - use crate::rustc_target::abi::LayoutOf; -use crate::utils::{snippet, span_lint_and_help}; declare_clippy_lint! { /// **What it does:** Checks for local arrays that may be too large. diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 1e1023b274..bb57adff7b 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -1,19 +1,21 @@ -use crate::utils::{ - get_item_name, get_parent_as_impl, is_allowed, snippet_with_applicability, span_lint, span_lint_and_sugg, - span_lint_and_then, -}; +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 if_chain::if_chain; use rustc_ast::ast::LitKind; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; +use rustc_hir::def_id::DefIdSet; use rustc_hir::{ def_id::DefId, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, ImplItem, ImplItemKind, ImplicitSelfKind, Item, ItemKind, Mutability, Node, TraitItemRef, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, AssocKind, FnSig}; +use rustc_middle::ty::{self, AssocKind, FnSig, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::{Span, Spanned, Symbol}; +use rustc_span::{ + source_map::{Span, Spanned, Symbol}, + symbol::sym, +}; declare_clippy_lint! { /// **What it does:** Checks for getting the length of something via `.len()` @@ -119,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { return; } - if let ItemKind::Trait(_, _, _, _, ref trait_items) = item.kind { + if let ItemKind::Trait(_, _, _, _, trait_items) = item.kind { check_trait_items(cx, item, trait_items); } } @@ -138,6 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { 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 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) { Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"), @@ -149,7 +152,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { } _ => return, }; - check_for_is_empty(cx, sig.span, sig.decl.implicit_self, ty_id, name, kind) + check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind) } } } @@ -159,7 +162,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { return; } - if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.kind { + if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind { match cmp { BinOpKind::Eq => { check_cmp(cx, expr.span, left, right, "", 0); // len == 0 @@ -196,7 +199,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items } // fill the set with current and super traits - fn fill_trait_set(traitt: DefId, set: &mut FxHashSet<DefId>, cx: &LateContext<'_>) { + fn fill_trait_set(traitt: DefId, set: &mut DefIdSet, cx: &LateContext<'_>) { if set.insert(traitt) { for supertrait in rustc_trait_selection::traits::supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); @@ -205,7 +208,7 @@ 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")) { - let mut current_and_super_traits = FxHashSet::default(); + let mut current_and_super_traits = DefIdSet::default(); fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx); let is_empty_method_found = current_and_super_traits @@ -232,10 +235,62 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items } } +#[derive(Debug, Clone, Copy)] +enum LenOutput<'tcx> { + Integral, + Option(DefId), + Result(DefId, Ty<'tcx>), +} +fn parse_len_output(cx: &LateContext<'_>, sig: FnSig<'tcx>) -> Option<LenOutput<'tcx>> { + match *sig.output().kind() { + ty::Int(_) | ty::Uint(_) => Some(LenOutput::Integral), + ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) => { + subs.type_at(0).is_integral().then(|| LenOutput::Option(adt.did)) + }, + ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::result_type, adt.did) => subs + .type_at(0) + .is_integral() + .then(|| LenOutput::Result(adt.did, subs.type_at(1))), + _ => None, + } +} + +impl LenOutput<'_> { + fn matches_is_empty_output(self, ty: Ty<'_>) -> bool { + match (self, ty.kind()) { + (_, &ty::Bool) => true, + (Self::Option(id), &ty::Adt(adt, subs)) if id == adt.did => subs.type_at(0).is_bool(), + (Self::Result(id, err_ty), &ty::Adt(adt, subs)) if id == adt.did => { + subs.type_at(0).is_bool() && TyS::same_type(subs.type_at(1), err_ty) + }, + _ => false, + } + } + + fn expected_sig(self, self_kind: ImplicitSelfKind) -> String { + let self_ref = match self_kind { + ImplicitSelfKind::ImmRef => "&", + ImplicitSelfKind::MutRef => "&mut ", + _ => "", + }; + match self { + Self::Integral => format!("expected signature: `({}self) -> bool`", self_ref), + Self::Option(_) => format!( + "expected signature: `({}self) -> bool` or `({}self) -> Option<bool>", + self_ref, self_ref + ), + Self::Result(..) => format!( + "expected signature: `({}self) -> bool` or `({}self) -> Result<bool>", + self_ref, self_ref + ), + } + } +} + /// Checks if the given signature matches the expectations for `is_empty` -fn check_is_empty_sig(cx: &LateContext<'_>, sig: FnSig<'_>, self_kind: ImplicitSelfKind) -> bool { +fn check_is_empty_sig(sig: FnSig<'_>, self_kind: ImplicitSelfKind, len_output: LenOutput<'_>) -> bool { match &**sig.inputs_and_output { - [arg, res] if *res == cx.tcx.types.bool => { + [arg, res] if len_output.matches_is_empty_output(res) => { matches!( (arg.kind(), self_kind), (ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::ImmRef) @@ -251,6 +306,7 @@ fn check_for_is_empty( cx: &LateContext<'_>, span: Span, self_kind: ImplicitSelfKind, + output: LenOutput<'_>, impl_ty: DefId, item_name: Symbol, item_kind: &str, @@ -290,7 +346,7 @@ fn check_for_is_empty( }, Some(is_empty) if !(is_empty.fn_has_self_parameter - && check_is_empty_sig(cx, cx.tcx.fn_sig(is_empty.def_id).skip_binder(), self_kind)) => + && check_is_empty_sig(cx.tcx.fn_sig(is_empty.def_id).skip_binder(), self_kind, output)) => { ( format!( @@ -310,21 +366,13 @@ fn check_for_is_empty( db.span_note(span, "`is_empty` defined here"); } if let Some(self_kind) = self_kind { - db.note(&format!( - "expected signature: `({}self) -> bool`", - match self_kind { - ImplicitSelfKind::ImmRef => "&", - ImplicitSelfKind::MutRef => "&mut ", - _ => "", - } - )); + db.note(&output.expected_sig(self_kind)); } }); } fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { - if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) - { + if let (&ExprKind::MethodCall(method_path, _, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) { // check if we are in an is_empty() method if let Some(name) = get_item_name(cx, method) { if name.as_str() == "is_empty" { @@ -402,7 +450,7 @@ fn is_empty_string(expr: &Expr<'_>) -> bool { } fn is_empty_array(expr: &Expr<'_>) -> bool { - if let ExprKind::Array(ref arr) = expr.kind { + if let ExprKind::Array(arr) = expr.kind { return arr.is_empty(); } false @@ -431,17 +479,17 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { cx.tcx .associated_items(*imp) .in_definition_order() - .any(|item| is_is_empty(cx, &item)) + .any(|item| is_is_empty(cx, item)) }) } let ty = &cx.typeck_results().expr_ty(expr).peel_refs(); match ty.kind() { - ty::Dynamic(ref tt, ..) => tt.principal().map_or(false, |principal| { + ty::Dynamic(tt, ..) => tt.principal().map_or(false, |principal| { cx.tcx .associated_items(principal.def_id()) .in_definition_order() - .any(|item| is_is_empty(cx, &item)) + .any(|item| is_is_empty(cx, item)) }), ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::Adt(id, _) => has_is_empty_impl(cx, id.did), diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 5863eef8a2..67eae4d87b 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -1,4 +1,6 @@ -use crate::utils::{path_to_local_id, snippet, span_lint_and_then, visitors::LocalUsedVisitor}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::{path_to_local_id, visitors::LocalUsedVisitor}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -59,13 +61,13 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { while let Some(stmt) = it.next() { if_chain! { if let Some(expr) = it.peek(); - if let hir::StmtKind::Local(ref local) = stmt.kind; + if let hir::StmtKind::Local(local) = stmt.kind; if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind; - if let hir::StmtKind::Expr(ref if_) = expr.kind; - if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.kind; + if let hir::StmtKind::Expr(if_) = expr.kind; + if let hir::ExprKind::If(cond, then, ref else_) = if_.kind; let mut used_visitor = LocalUsedVisitor::new(cx, canonical_id); if !used_visitor.check_expr(cond); - if let hir::ExprKind::Block(ref then, _) = then.kind; + if let hir::ExprKind::Block(then, _) = then.kind; if let Some(value) = check_assign(cx, canonical_id, &*then); if !used_visitor.check_expr(value); then { @@ -77,20 +79,20 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { ); if has_interior_mutability { return; } - let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { - if let hir::ExprKind::Block(ref else_, _) = else_.kind { + let (default_multi_stmts, default) = if let Some(else_) = *else_ { + if let hir::ExprKind::Block(else_, _) = else_.kind { if let Some(default) = check_assign(cx, canonical_id, else_) { (else_.stmts.len() > 1, default) - } else if let Some(ref default) = local.init { - (true, &**default) + } else if let Some(default) = local.init { + (true, default) } else { continue; } } else { continue; } - } else if let Some(ref default) = local.init { - (false, &**default) + } else if let Some(default) = local.init { + (false, default) } else { continue; }; @@ -142,8 +144,8 @@ fn check_assign<'tcx>( if_chain! { if block.expr.is_none(); if let Some(expr) = block.stmts.iter().last(); - if let hir::StmtKind::Semi(ref expr) = expr.kind; - if let hir::ExprKind::Assign(ref var, ref value, _) = expr.kind; + if let hir::StmtKind::Semi(expr) = expr.kind; + if let hir::ExprKind::Assign(var, value, _) = expr.kind; if path_to_local_id(var, decl); then { let mut v = LocalUsedVisitor::new(cx, decl); diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 7e96dfcc7d..17e23781db 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -1,3 +1,6 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::{is_must_use_ty, match_type}; +use clippy_utils::{is_must_use_func_call, paths}; use if_chain::if_chain; use rustc_hir::{Local, PatKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -5,8 +8,6 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help}; - declare_clippy_lint! { /// **What it does:** Checks for `let _ = <expr>` /// where expr is #[must_use] @@ -115,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { if_chain! { if let PatKind::Wild = local.pat.kind; - if let Some(ref init) = local.init; + if let Some(init) = local.init; then { let init_ty = cx.typeck_results().expr_ty(init); let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() { diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 04e151df8e..8c74284fa4 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -4,8 +4,9 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(once_cell)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] #![feature(control_flow_enum)] @@ -16,13 +17,12 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] // warn on rustc internal lints -#![deny(rustc::internal)] +#![warn(rustc::internal)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) extern crate rustc_ast; extern crate rustc_ast_pretty; -extern crate rustc_attr; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_errors; @@ -42,7 +42,7 @@ extern crate rustc_target; extern crate rustc_trait_selection; extern crate rustc_typeck; -use crate::utils::parse_msrv; +use clippy_utils::parse_msrv; use rustc_data_structures::fx::FxHashSet; use rustc_lint::LintId; use rustc_session::Session; @@ -165,6 +165,7 @@ mod consts; mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` +mod absurd_extreme_comparisons; mod approx_const; mod arithmetic; mod as_conversions; @@ -178,6 +179,7 @@ mod await_holding_invalid; mod bit_mask; mod blacklisted_name; mod blocks_in_if_conditions; +mod bool_assert_comparison; mod booleans; mod bytecount; mod cargo_common_metadata; @@ -231,6 +233,8 @@ mod identity_op; mod if_let_mutex; mod if_let_some_result; mod if_not_else; +mod if_then_some_else_none; +mod implicit_hasher; mod implicit_return; mod implicit_saturating_sub; mod inconsistent_struct_constructor; @@ -241,6 +245,7 @@ mod inherent_to_string; mod inline_fn_without_body; mod int_plus_one; mod integer_division; +mod invalid_upcast_comparisons; mod items_after_statements; mod large_const_arrays; mod large_enum_variant; @@ -288,6 +293,7 @@ mod needless_bool; mod needless_borrow; mod needless_borrowed_ref; mod needless_continue; +mod needless_for_each; mod needless_pass_by_value; mod needless_question_mark; mod needless_update; @@ -297,6 +303,7 @@ mod new_without_default; mod no_effect; mod non_copy_const; mod non_expressive_names; +mod non_octal_unix_permissions; mod open_options; mod option_env_unwrap; mod option_if_let_else; @@ -349,7 +356,9 @@ mod types; mod undropped_manually_drops; mod unicode; mod unit_return_expecting_ord; +mod unit_types; mod unnamed_address; +mod unnecessary_self_imports; mod unnecessary_sort_by; mod unnecessary_wraps; mod unnested_or_patterns; @@ -384,6 +393,7 @@ pub use crate::utils::conf::Conf; /// /// Used in `./src/driver.rs`. pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) { + // NOTE: Do not add any more pre-expansion passes. These should be removed eventually. store.register_pre_expansion_pass(|| box write::Write::default()); store.register_pre_expansion_pass(|| box attrs::EarlyAttributes); store.register_pre_expansion_pass(|| box dbg_macro::DbgMacro); @@ -487,22 +497,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: "clippy::unsafe_vector_initialization", "the replacement suggested by this lint had substantially different behavior", ); - store.register_removed( - "clippy::invalid_ref", - "superseded by rustc lint `invalid_value`", - ); store.register_removed( "clippy::unused_collect", "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint", ); - store.register_removed( - "clippy::into_iter_on_array", - "this lint has been uplifted to rustc and is now called `array_into_iter`", - ); - store.register_removed( - "clippy::unused_label", - "this lint has been uplifted to rustc and is now called `unused_labels`", - ); store.register_removed( "clippy::replace_consts", "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants", @@ -511,500 +509,499 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: "clippy::regex_macro", "the regex! macro has been removed from the regex crate in 2018", ); - store.register_removed( - "clippy::drop_bounds", - "this lint has been uplifted to rustc and is now called `drop_bounds`", - ); - store.register_removed( - "clippy::temporary_cstring_as_ptr", - "this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr`", - ); - store.register_removed( - "clippy::panic_params", - "this lint has been uplifted to rustc and is now called `panic_fmt`", - ); - store.register_removed( - "clippy::unknown_clippy_lints", - "this lint has been integrated into the `unknown_lints` rustc lint", - ); store.register_removed( "clippy::find_map", "this lint has been replaced by `manual_find_map`, a more specific lint", ); + store.register_removed( + "clippy::filter_map", + "this lint has been replaced by `manual_filter_map`, a more specific lint", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` // begin register lints, do not remove this comment, it’s used in `update_lints` store.register_lints(&[ #[cfg(feature = "internal-lints")] - &utils::internal_lints::CLIPPY_LINTS_INTERNAL, + utils::internal_lints::CLIPPY_LINTS_INTERNAL, + #[cfg(feature = "internal-lints")] + utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS, #[cfg(feature = "internal-lints")] - &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS, + utils::internal_lints::COMPILER_LINT_FUNCTIONS, #[cfg(feature = "internal-lints")] - &utils::internal_lints::COMPILER_LINT_FUNCTIONS, + utils::internal_lints::DEFAULT_LINT, #[cfg(feature = "internal-lints")] - &utils::internal_lints::DEFAULT_LINT, + utils::internal_lints::IF_CHAIN_STYLE, #[cfg(feature = "internal-lints")] - &utils::internal_lints::INTERNING_DEFINED_SYMBOL, + utils::internal_lints::INTERNING_DEFINED_SYMBOL, #[cfg(feature = "internal-lints")] - &utils::internal_lints::INVALID_PATHS, + utils::internal_lints::INVALID_PATHS, #[cfg(feature = "internal-lints")] - &utils::internal_lints::LINT_WITHOUT_LINT_PASS, + utils::internal_lints::LINT_WITHOUT_LINT_PASS, #[cfg(feature = "internal-lints")] - &utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM, + utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM, #[cfg(feature = "internal-lints")] - &utils::internal_lints::OUTER_EXPN_EXPN_DATA, + utils::internal_lints::OUTER_EXPN_EXPN_DATA, #[cfg(feature = "internal-lints")] - &utils::internal_lints::PRODUCE_ICE, + utils::internal_lints::PRODUCE_ICE, #[cfg(feature = "internal-lints")] - &utils::internal_lints::UNNECESSARY_SYMBOL_STR, - &approx_const::APPROX_CONSTANT, - &arithmetic::FLOAT_ARITHMETIC, - &arithmetic::INTEGER_ARITHMETIC, - &as_conversions::AS_CONVERSIONS, - &asm_syntax::INLINE_ASM_X86_ATT_SYNTAX, - &asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX, - &assertions_on_constants::ASSERTIONS_ON_CONSTANTS, - &assign_ops::ASSIGN_OP_PATTERN, - &assign_ops::MISREFACTORED_ASSIGN_OP, - &async_yields_async::ASYNC_YIELDS_ASYNC, - &atomic_ordering::INVALID_ATOMIC_ORDERING, - &attrs::BLANKET_CLIPPY_RESTRICTION_LINTS, - &attrs::DEPRECATED_CFG_ATTR, - &attrs::DEPRECATED_SEMVER, - &attrs::EMPTY_LINE_AFTER_OUTER_ATTR, - &attrs::INLINE_ALWAYS, - &attrs::MISMATCHED_TARGET_OS, - &attrs::USELESS_ATTRIBUTE, - &await_holding_invalid::AWAIT_HOLDING_LOCK, - &await_holding_invalid::AWAIT_HOLDING_REFCELL_REF, - &bit_mask::BAD_BIT_MASK, - &bit_mask::INEFFECTIVE_BIT_MASK, - &bit_mask::VERBOSE_BIT_MASK, - &blacklisted_name::BLACKLISTED_NAME, - &blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS, - &booleans::LOGIC_BUG, - &booleans::NONMINIMAL_BOOL, - &bytecount::NAIVE_BYTECOUNT, - &cargo_common_metadata::CARGO_COMMON_METADATA, - &case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, - &casts::CAST_LOSSLESS, - &casts::CAST_POSSIBLE_TRUNCATION, - &casts::CAST_POSSIBLE_WRAP, - &casts::CAST_PRECISION_LOSS, - &casts::CAST_PTR_ALIGNMENT, - &casts::CAST_REF_TO_MUT, - &casts::CAST_SIGN_LOSS, - &casts::CHAR_LIT_AS_U8, - &casts::FN_TO_NUMERIC_CAST, - &casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - &casts::PTR_AS_PTR, - &casts::UNNECESSARY_CAST, - &checked_conversions::CHECKED_CONVERSIONS, - &cognitive_complexity::COGNITIVE_COMPLEXITY, - &collapsible_if::COLLAPSIBLE_ELSE_IF, - &collapsible_if::COLLAPSIBLE_IF, - &collapsible_match::COLLAPSIBLE_MATCH, - &comparison_chain::COMPARISON_CHAIN, - &copies::IFS_SAME_COND, - &copies::IF_SAME_THEN_ELSE, - &copies::SAME_FUNCTIONS_IN_IF_CONDITION, - ©_iterator::COPY_ITERATOR, - &create_dir::CREATE_DIR, - &dbg_macro::DBG_MACRO, - &default::DEFAULT_TRAIT_ACCESS, - &default::FIELD_REASSIGN_WITH_DEFAULT, - &default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK, - &dereference::EXPLICIT_DEREF_METHODS, - &derive::DERIVE_HASH_XOR_EQ, - &derive::DERIVE_ORD_XOR_PARTIAL_ORD, - &derive::EXPL_IMPL_CLONE_ON_COPY, - &derive::UNSAFE_DERIVE_DESERIALIZE, - &disallowed_method::DISALLOWED_METHOD, - &doc::DOC_MARKDOWN, - &doc::MISSING_ERRORS_DOC, - &doc::MISSING_PANICS_DOC, - &doc::MISSING_SAFETY_DOC, - &doc::NEEDLESS_DOCTEST_MAIN, - &double_comparison::DOUBLE_COMPARISONS, - &double_parens::DOUBLE_PARENS, - &drop_forget_ref::DROP_COPY, - &drop_forget_ref::DROP_REF, - &drop_forget_ref::FORGET_COPY, - &drop_forget_ref::FORGET_REF, - &duration_subsec::DURATION_SUBSEC, - &else_if_without_else::ELSE_IF_WITHOUT_ELSE, - &empty_enum::EMPTY_ENUM, - &entry::MAP_ENTRY, - &enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, - &enum_variants::ENUM_VARIANT_NAMES, - &enum_variants::MODULE_INCEPTION, - &enum_variants::MODULE_NAME_REPETITIONS, - &enum_variants::PUB_ENUM_VARIANT_NAMES, - &eq_op::EQ_OP, - &eq_op::OP_REF, - &erasing_op::ERASING_OP, - &escape::BOXED_LOCAL, - &eta_reduction::REDUNDANT_CLOSURE, - &eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS, - &eval_order_dependence::DIVERGING_SUB_EXPRESSION, - &eval_order_dependence::EVAL_ORDER_DEPENDENCE, - &excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS, - &excessive_bools::STRUCT_EXCESSIVE_BOOLS, - &exhaustive_items::EXHAUSTIVE_ENUMS, - &exhaustive_items::EXHAUSTIVE_STRUCTS, - &exit::EXIT, - &explicit_write::EXPLICIT_WRITE, - &fallible_impl_from::FALLIBLE_IMPL_FROM, - &float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS, - &float_literal::EXCESSIVE_PRECISION, - &float_literal::LOSSY_FLOAT_LITERAL, - &floating_point_arithmetic::IMPRECISE_FLOPS, - &floating_point_arithmetic::SUBOPTIMAL_FLOPS, - &format::USELESS_FORMAT, - &formatting::POSSIBLE_MISSING_COMMA, - &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, - &formatting::SUSPICIOUS_ELSE_FORMATTING, - &formatting::SUSPICIOUS_UNARY_OP_FORMATTING, - &from_over_into::FROM_OVER_INTO, - &from_str_radix_10::FROM_STR_RADIX_10, - &functions::DOUBLE_MUST_USE, - &functions::MUST_USE_CANDIDATE, - &functions::MUST_USE_UNIT, - &functions::NOT_UNSAFE_PTR_ARG_DEREF, - &functions::RESULT_UNIT_ERR, - &functions::TOO_MANY_ARGUMENTS, - &functions::TOO_MANY_LINES, - &future_not_send::FUTURE_NOT_SEND, - &get_last_with_len::GET_LAST_WITH_LEN, - &identity_op::IDENTITY_OP, - &if_let_mutex::IF_LET_MUTEX, - &if_let_some_result::IF_LET_SOME_RESULT, - &if_not_else::IF_NOT_ELSE, - &implicit_return::IMPLICIT_RETURN, - &implicit_saturating_sub::IMPLICIT_SATURATING_SUB, - &inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR, - &indexing_slicing::INDEXING_SLICING, - &indexing_slicing::OUT_OF_BOUNDS_INDEXING, - &infinite_iter::INFINITE_ITER, - &infinite_iter::MAYBE_INFINITE_ITER, - &inherent_impl::MULTIPLE_INHERENT_IMPL, - &inherent_to_string::INHERENT_TO_STRING, - &inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, - &inline_fn_without_body::INLINE_FN_WITHOUT_BODY, - &int_plus_one::INT_PLUS_ONE, - &integer_division::INTEGER_DIVISION, - &items_after_statements::ITEMS_AFTER_STATEMENTS, - &large_const_arrays::LARGE_CONST_ARRAYS, - &large_enum_variant::LARGE_ENUM_VARIANT, - &large_stack_arrays::LARGE_STACK_ARRAYS, - &len_zero::COMPARISON_TO_EMPTY, - &len_zero::LEN_WITHOUT_IS_EMPTY, - &len_zero::LEN_ZERO, - &let_if_seq::USELESS_LET_IF_SEQ, - &let_underscore::LET_UNDERSCORE_DROP, - &let_underscore::LET_UNDERSCORE_LOCK, - &let_underscore::LET_UNDERSCORE_MUST_USE, - &lifetimes::EXTRA_UNUSED_LIFETIMES, - &lifetimes::NEEDLESS_LIFETIMES, - &literal_representation::DECIMAL_LITERAL_REPRESENTATION, - &literal_representation::INCONSISTENT_DIGIT_GROUPING, - &literal_representation::LARGE_DIGIT_GROUPS, - &literal_representation::MISTYPED_LITERAL_SUFFIXES, - &literal_representation::UNREADABLE_LITERAL, - &literal_representation::UNUSUAL_BYTE_GROUPINGS, - &loops::EMPTY_LOOP, - &loops::EXPLICIT_COUNTER_LOOP, - &loops::EXPLICIT_INTO_ITER_LOOP, - &loops::EXPLICIT_ITER_LOOP, - &loops::FOR_KV_MAP, - &loops::FOR_LOOPS_OVER_FALLIBLES, - &loops::ITER_NEXT_LOOP, - &loops::MANUAL_FLATTEN, - &loops::MANUAL_MEMCPY, - &loops::MUT_RANGE_BOUND, - &loops::NEEDLESS_COLLECT, - &loops::NEEDLESS_RANGE_LOOP, - &loops::NEVER_LOOP, - &loops::SAME_ITEM_PUSH, - &loops::SINGLE_ELEMENT_LOOP, - &loops::WHILE_IMMUTABLE_CONDITION, - &loops::WHILE_LET_LOOP, - &loops::WHILE_LET_ON_ITERATOR, - ¯o_use::MACRO_USE_IMPORTS, - &main_recursion::MAIN_RECURSION, - &manual_async_fn::MANUAL_ASYNC_FN, - &manual_map::MANUAL_MAP, - &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, - &manual_ok_or::MANUAL_OK_OR, - &manual_strip::MANUAL_STRIP, - &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, - &matches::INFALLIBLE_DESTRUCTURING_MATCH, - &matches::MATCH_AS_REF, - &matches::MATCH_BOOL, - &matches::MATCH_LIKE_MATCHES_MACRO, - &matches::MATCH_OVERLAPPING_ARM, - &matches::MATCH_REF_PATS, - &matches::MATCH_SAME_ARMS, - &matches::MATCH_SINGLE_BINDING, - &matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS, - &matches::MATCH_WILD_ERR_ARM, - &matches::REDUNDANT_PATTERN_MATCHING, - &matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, - &matches::SINGLE_MATCH, - &matches::SINGLE_MATCH_ELSE, - &matches::WILDCARD_ENUM_MATCH_ARM, - &matches::WILDCARD_IN_OR_PATTERNS, - &mem_discriminant::MEM_DISCRIMINANT_NON_ENUM, - &mem_forget::MEM_FORGET, - &mem_replace::MEM_REPLACE_OPTION_WITH_NONE, - &mem_replace::MEM_REPLACE_WITH_DEFAULT, - &mem_replace::MEM_REPLACE_WITH_UNINIT, - &methods::BIND_INSTEAD_OF_MAP, - &methods::BYTES_NTH, - &methods::CHARS_LAST_CMP, - &methods::CHARS_NEXT_CMP, - &methods::CLONE_DOUBLE_REF, - &methods::CLONE_ON_COPY, - &methods::CLONE_ON_REF_PTR, - &methods::EXPECT_FUN_CALL, - &methods::EXPECT_USED, - &methods::FILETYPE_IS_FILE, - &methods::FILTER_MAP, - &methods::FILTER_MAP_IDENTITY, - &methods::FILTER_MAP_NEXT, - &methods::FILTER_NEXT, - &methods::FLAT_MAP_IDENTITY, - &methods::FROM_ITER_INSTEAD_OF_COLLECT, - &methods::GET_UNWRAP, - &methods::IMPLICIT_CLONE, - &methods::INEFFICIENT_TO_STRING, - &methods::INSPECT_FOR_EACH, - &methods::INTO_ITER_ON_REF, - &methods::ITERATOR_STEP_BY_ZERO, - &methods::ITER_CLONED_COLLECT, - &methods::ITER_COUNT, - &methods::ITER_NEXT_SLICE, - &methods::ITER_NTH, - &methods::ITER_NTH_ZERO, - &methods::ITER_SKIP_NEXT, - &methods::MANUAL_FILTER_MAP, - &methods::MANUAL_FIND_MAP, - &methods::MANUAL_SATURATING_ARITHMETIC, - &methods::MAP_COLLECT_RESULT_UNIT, - &methods::MAP_FLATTEN, - &methods::MAP_UNWRAP_OR, - &methods::NEW_RET_NO_SELF, - &methods::OK_EXPECT, - &methods::OPTION_AS_REF_DEREF, - &methods::OPTION_MAP_OR_NONE, - &methods::OR_FUN_CALL, - &methods::RESULT_MAP_OR_INTO_OPTION, - &methods::SEARCH_IS_SOME, - &methods::SHOULD_IMPLEMENT_TRAIT, - &methods::SINGLE_CHAR_ADD_STR, - &methods::SINGLE_CHAR_PATTERN, - &methods::SKIP_WHILE_NEXT, - &methods::STRING_EXTEND_CHARS, - &methods::SUSPICIOUS_MAP, - &methods::UNINIT_ASSUMED_INIT, - &methods::UNNECESSARY_FILTER_MAP, - &methods::UNNECESSARY_FOLD, - &methods::UNNECESSARY_LAZY_EVALUATIONS, - &methods::UNWRAP_USED, - &methods::USELESS_ASREF, - &methods::WRONG_PUB_SELF_CONVENTION, - &methods::WRONG_SELF_CONVENTION, - &methods::ZST_OFFSET, - &minmax::MIN_MAX, - &misc::CMP_NAN, - &misc::CMP_OWNED, - &misc::FLOAT_CMP, - &misc::FLOAT_CMP_CONST, - &misc::MODULO_ONE, - &misc::SHORT_CIRCUIT_STATEMENT, - &misc::TOPLEVEL_REF_ARG, - &misc::USED_UNDERSCORE_BINDING, - &misc::ZERO_PTR, - &misc_early::BUILTIN_TYPE_SHADOW, - &misc_early::DOUBLE_NEG, - &misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, - &misc_early::MIXED_CASE_HEX_LITERALS, - &misc_early::REDUNDANT_PATTERN, - &misc_early::UNNEEDED_FIELD_PATTERN, - &misc_early::UNNEEDED_WILDCARD_PATTERN, - &misc_early::UNSEPARATED_LITERAL_SUFFIX, - &misc_early::ZERO_PREFIXED_LITERAL, - &missing_const_for_fn::MISSING_CONST_FOR_FN, - &missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, - &missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, - &modulo_arithmetic::MODULO_ARITHMETIC, - &multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, - &mut_key::MUTABLE_KEY_TYPE, - &mut_mut::MUT_MUT, - &mut_mutex_lock::MUT_MUTEX_LOCK, - &mut_reference::UNNECESSARY_MUT_PASSED, - &mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL, - &mutex_atomic::MUTEX_ATOMIC, - &mutex_atomic::MUTEX_INTEGER, - &needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE, - &needless_bool::BOOL_COMPARISON, - &needless_bool::NEEDLESS_BOOL, - &needless_borrow::NEEDLESS_BORROW, - &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, - &needless_continue::NEEDLESS_CONTINUE, - &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, - &needless_question_mark::NEEDLESS_QUESTION_MARK, - &needless_update::NEEDLESS_UPDATE, - &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, - &neg_multiply::NEG_MULTIPLY, - &new_without_default::NEW_WITHOUT_DEFAULT, - &no_effect::NO_EFFECT, - &no_effect::UNNECESSARY_OPERATION, - &non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, - &non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST, - &non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, - &non_expressive_names::MANY_SINGLE_CHAR_NAMES, - &non_expressive_names::SIMILAR_NAMES, - &open_options::NONSENSICAL_OPEN_OPTIONS, - &option_env_unwrap::OPTION_ENV_UNWRAP, - &option_if_let_else::OPTION_IF_LET_ELSE, - &overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, - &panic_in_result_fn::PANIC_IN_RESULT_FN, - &panic_unimplemented::PANIC, - &panic_unimplemented::TODO, - &panic_unimplemented::UNIMPLEMENTED, - &panic_unimplemented::UNREACHABLE, - &partialeq_ne_impl::PARTIALEQ_NE_IMPL, - &pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE, - &pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF, - &path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, - &pattern_type_mismatch::PATTERN_TYPE_MISMATCH, - &precedence::PRECEDENCE, - &ptr::CMP_NULL, - &ptr::MUT_FROM_REF, - &ptr::PTR_ARG, - &ptr_eq::PTR_EQ, - &ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, - &question_mark::QUESTION_MARK, - &ranges::MANUAL_RANGE_CONTAINS, - &ranges::RANGE_MINUS_ONE, - &ranges::RANGE_PLUS_ONE, - &ranges::RANGE_ZIP_WITH_LEN, - &ranges::REVERSED_EMPTY_RANGES, - &redundant_clone::REDUNDANT_CLONE, - &redundant_closure_call::REDUNDANT_CLOSURE_CALL, - &redundant_else::REDUNDANT_ELSE, - &redundant_field_names::REDUNDANT_FIELD_NAMES, - &redundant_pub_crate::REDUNDANT_PUB_CRATE, - &redundant_slicing::REDUNDANT_SLICING, - &redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES, - &ref_option_ref::REF_OPTION_REF, - &reference::DEREF_ADDROF, - &reference::REF_IN_DEREF, - ®ex::INVALID_REGEX, - ®ex::TRIVIAL_REGEX, - &repeat_once::REPEAT_ONCE, - &returns::LET_AND_RETURN, - &returns::NEEDLESS_RETURN, - &self_assignment::SELF_ASSIGNMENT, - &semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED, - &serde_api::SERDE_API_MISUSE, - &shadow::SHADOW_REUSE, - &shadow::SHADOW_SAME, - &shadow::SHADOW_UNRELATED, - &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, - &size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT, - &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, - &stable_sort_primitive::STABLE_SORT_PRIMITIVE, - &strings::STRING_ADD, - &strings::STRING_ADD_ASSIGN, - &strings::STRING_FROM_UTF8_AS_BYTES, - &strings::STRING_LIT_AS_BYTES, - &strings::STRING_TO_STRING, - &strings::STR_TO_STRING, - &suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS, - &suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, - &suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, - &swap::ALMOST_SWAPPED, - &swap::MANUAL_SWAP, - &tabs_in_doc_comments::TABS_IN_DOC_COMMENTS, - &temporary_assignment::TEMPORARY_ASSIGNMENT, - &to_digit_is_some::TO_DIGIT_IS_SOME, - &to_string_in_display::TO_STRING_IN_DISPLAY, - &trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS, - &trait_bounds::TYPE_REPETITION_IN_BOUNDS, - &transmute::CROSSPOINTER_TRANSMUTE, - &transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, - &transmute::TRANSMUTE_BYTES_TO_STR, - &transmute::TRANSMUTE_FLOAT_TO_INT, - &transmute::TRANSMUTE_INT_TO_BOOL, - &transmute::TRANSMUTE_INT_TO_CHAR, - &transmute::TRANSMUTE_INT_TO_FLOAT, - &transmute::TRANSMUTE_PTR_TO_PTR, - &transmute::TRANSMUTE_PTR_TO_REF, - &transmute::UNSOUND_COLLECTION_TRANSMUTE, - &transmute::USELESS_TRANSMUTE, - &transmute::WRONG_TRANSMUTE, - &transmuting_null::TRANSMUTING_NULL, - &try_err::TRY_ERR, - &types::ABSURD_EXTREME_COMPARISONS, - &types::BORROWED_BOX, - &types::BOX_VEC, - &types::IMPLICIT_HASHER, - &types::INVALID_UPCAST_COMPARISONS, - &types::LET_UNIT_VALUE, - &types::LINKEDLIST, - &types::OPTION_OPTION, - &types::RC_BUFFER, - &types::REDUNDANT_ALLOCATION, - &types::TYPE_COMPLEXITY, - &types::UNIT_ARG, - &types::UNIT_CMP, - &types::VEC_BOX, - &undropped_manually_drops::UNDROPPED_MANUALLY_DROPS, - &unicode::INVISIBLE_CHARACTERS, - &unicode::NON_ASCII_LITERAL, - &unicode::UNICODE_NOT_NFC, - &unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD, - &unnamed_address::FN_ADDRESS_COMPARISONS, - &unnamed_address::VTABLE_ADDRESS_COMPARISONS, - &unnecessary_sort_by::UNNECESSARY_SORT_BY, - &unnecessary_wraps::UNNECESSARY_WRAPS, - &unnested_or_patterns::UNNESTED_OR_PATTERNS, - &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, - &unused_io_amount::UNUSED_IO_AMOUNT, - &unused_self::UNUSED_SELF, - &unused_unit::UNUSED_UNIT, - &unwrap::PANICKING_UNWRAP, - &unwrap::UNNECESSARY_UNWRAP, - &unwrap_in_result::UNWRAP_IN_RESULT, - &upper_case_acronyms::UPPER_CASE_ACRONYMS, - &use_self::USE_SELF, - &useless_conversion::USELESS_CONVERSION, - &vec::USELESS_VEC, - &vec_init_then_push::VEC_INIT_THEN_PUSH, - &vec_resize_to_zero::VEC_RESIZE_TO_ZERO, - &verbose_file_reads::VERBOSE_FILE_READS, - &wildcard_dependencies::WILDCARD_DEPENDENCIES, - &wildcard_imports::ENUM_GLOB_USE, - &wildcard_imports::WILDCARD_IMPORTS, - &write::PRINTLN_EMPTY_STRING, - &write::PRINT_LITERAL, - &write::PRINT_STDERR, - &write::PRINT_STDOUT, - &write::PRINT_WITH_NEWLINE, - &write::USE_DEBUG, - &write::WRITELN_EMPTY_STRING, - &write::WRITE_LITERAL, - &write::WRITE_WITH_NEWLINE, - &zero_div_zero::ZERO_DIVIDED_BY_ZERO, - &zero_sized_map_values::ZERO_SIZED_MAP_VALUES, + utils::internal_lints::UNNECESSARY_SYMBOL_STR, + absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS, + approx_const::APPROX_CONSTANT, + arithmetic::FLOAT_ARITHMETIC, + arithmetic::INTEGER_ARITHMETIC, + as_conversions::AS_CONVERSIONS, + asm_syntax::INLINE_ASM_X86_ATT_SYNTAX, + asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX, + assertions_on_constants::ASSERTIONS_ON_CONSTANTS, + assign_ops::ASSIGN_OP_PATTERN, + assign_ops::MISREFACTORED_ASSIGN_OP, + async_yields_async::ASYNC_YIELDS_ASYNC, + atomic_ordering::INVALID_ATOMIC_ORDERING, + attrs::BLANKET_CLIPPY_RESTRICTION_LINTS, + attrs::DEPRECATED_CFG_ATTR, + attrs::DEPRECATED_SEMVER, + attrs::EMPTY_LINE_AFTER_OUTER_ATTR, + attrs::INLINE_ALWAYS, + attrs::MISMATCHED_TARGET_OS, + attrs::USELESS_ATTRIBUTE, + await_holding_invalid::AWAIT_HOLDING_LOCK, + await_holding_invalid::AWAIT_HOLDING_REFCELL_REF, + bit_mask::BAD_BIT_MASK, + bit_mask::INEFFECTIVE_BIT_MASK, + bit_mask::VERBOSE_BIT_MASK, + blacklisted_name::BLACKLISTED_NAME, + blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS, + bool_assert_comparison::BOOL_ASSERT_COMPARISON, + booleans::LOGIC_BUG, + booleans::NONMINIMAL_BOOL, + bytecount::NAIVE_BYTECOUNT, + cargo_common_metadata::CARGO_COMMON_METADATA, + case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, + casts::CAST_LOSSLESS, + casts::CAST_POSSIBLE_TRUNCATION, + casts::CAST_POSSIBLE_WRAP, + casts::CAST_PRECISION_LOSS, + casts::CAST_PTR_ALIGNMENT, + casts::CAST_REF_TO_MUT, + casts::CAST_SIGN_LOSS, + casts::CHAR_LIT_AS_U8, + casts::FN_TO_NUMERIC_CAST, + casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, + casts::PTR_AS_PTR, + casts::UNNECESSARY_CAST, + checked_conversions::CHECKED_CONVERSIONS, + cognitive_complexity::COGNITIVE_COMPLEXITY, + collapsible_if::COLLAPSIBLE_ELSE_IF, + collapsible_if::COLLAPSIBLE_IF, + collapsible_match::COLLAPSIBLE_MATCH, + comparison_chain::COMPARISON_CHAIN, + copies::BRANCHES_SHARING_CODE, + copies::IFS_SAME_COND, + copies::IF_SAME_THEN_ELSE, + copies::SAME_FUNCTIONS_IN_IF_CONDITION, + copy_iterator::COPY_ITERATOR, + create_dir::CREATE_DIR, + dbg_macro::DBG_MACRO, + default::DEFAULT_TRAIT_ACCESS, + default::FIELD_REASSIGN_WITH_DEFAULT, + default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK, + dereference::EXPLICIT_DEREF_METHODS, + derive::DERIVE_HASH_XOR_EQ, + derive::DERIVE_ORD_XOR_PARTIAL_ORD, + derive::EXPL_IMPL_CLONE_ON_COPY, + derive::UNSAFE_DERIVE_DESERIALIZE, + disallowed_method::DISALLOWED_METHOD, + doc::DOC_MARKDOWN, + doc::MISSING_ERRORS_DOC, + doc::MISSING_PANICS_DOC, + doc::MISSING_SAFETY_DOC, + doc::NEEDLESS_DOCTEST_MAIN, + double_comparison::DOUBLE_COMPARISONS, + double_parens::DOUBLE_PARENS, + drop_forget_ref::DROP_COPY, + drop_forget_ref::DROP_REF, + drop_forget_ref::FORGET_COPY, + drop_forget_ref::FORGET_REF, + duration_subsec::DURATION_SUBSEC, + else_if_without_else::ELSE_IF_WITHOUT_ELSE, + empty_enum::EMPTY_ENUM, + entry::MAP_ENTRY, + enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, + enum_variants::ENUM_VARIANT_NAMES, + enum_variants::MODULE_INCEPTION, + enum_variants::MODULE_NAME_REPETITIONS, + enum_variants::PUB_ENUM_VARIANT_NAMES, + eq_op::EQ_OP, + eq_op::OP_REF, + erasing_op::ERASING_OP, + escape::BOXED_LOCAL, + eta_reduction::REDUNDANT_CLOSURE, + eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS, + eval_order_dependence::DIVERGING_SUB_EXPRESSION, + eval_order_dependence::EVAL_ORDER_DEPENDENCE, + excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS, + excessive_bools::STRUCT_EXCESSIVE_BOOLS, + exhaustive_items::EXHAUSTIVE_ENUMS, + exhaustive_items::EXHAUSTIVE_STRUCTS, + exit::EXIT, + explicit_write::EXPLICIT_WRITE, + fallible_impl_from::FALLIBLE_IMPL_FROM, + float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS, + float_literal::EXCESSIVE_PRECISION, + float_literal::LOSSY_FLOAT_LITERAL, + floating_point_arithmetic::IMPRECISE_FLOPS, + floating_point_arithmetic::SUBOPTIMAL_FLOPS, + format::USELESS_FORMAT, + formatting::POSSIBLE_MISSING_COMMA, + formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, + formatting::SUSPICIOUS_ELSE_FORMATTING, + formatting::SUSPICIOUS_UNARY_OP_FORMATTING, + from_over_into::FROM_OVER_INTO, + from_str_radix_10::FROM_STR_RADIX_10, + functions::DOUBLE_MUST_USE, + functions::MUST_USE_CANDIDATE, + functions::MUST_USE_UNIT, + functions::NOT_UNSAFE_PTR_ARG_DEREF, + functions::RESULT_UNIT_ERR, + functions::TOO_MANY_ARGUMENTS, + functions::TOO_MANY_LINES, + future_not_send::FUTURE_NOT_SEND, + get_last_with_len::GET_LAST_WITH_LEN, + identity_op::IDENTITY_OP, + if_let_mutex::IF_LET_MUTEX, + if_let_some_result::IF_LET_SOME_RESULT, + if_not_else::IF_NOT_ELSE, + if_then_some_else_none::IF_THEN_SOME_ELSE_NONE, + implicit_hasher::IMPLICIT_HASHER, + implicit_return::IMPLICIT_RETURN, + implicit_saturating_sub::IMPLICIT_SATURATING_SUB, + inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR, + indexing_slicing::INDEXING_SLICING, + indexing_slicing::OUT_OF_BOUNDS_INDEXING, + infinite_iter::INFINITE_ITER, + infinite_iter::MAYBE_INFINITE_ITER, + inherent_impl::MULTIPLE_INHERENT_IMPL, + inherent_to_string::INHERENT_TO_STRING, + inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, + inline_fn_without_body::INLINE_FN_WITHOUT_BODY, + int_plus_one::INT_PLUS_ONE, + integer_division::INTEGER_DIVISION, + invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS, + items_after_statements::ITEMS_AFTER_STATEMENTS, + large_const_arrays::LARGE_CONST_ARRAYS, + large_enum_variant::LARGE_ENUM_VARIANT, + large_stack_arrays::LARGE_STACK_ARRAYS, + len_zero::COMPARISON_TO_EMPTY, + len_zero::LEN_WITHOUT_IS_EMPTY, + len_zero::LEN_ZERO, + let_if_seq::USELESS_LET_IF_SEQ, + let_underscore::LET_UNDERSCORE_DROP, + let_underscore::LET_UNDERSCORE_LOCK, + let_underscore::LET_UNDERSCORE_MUST_USE, + lifetimes::EXTRA_UNUSED_LIFETIMES, + lifetimes::NEEDLESS_LIFETIMES, + literal_representation::DECIMAL_LITERAL_REPRESENTATION, + literal_representation::INCONSISTENT_DIGIT_GROUPING, + literal_representation::LARGE_DIGIT_GROUPS, + literal_representation::MISTYPED_LITERAL_SUFFIXES, + literal_representation::UNREADABLE_LITERAL, + literal_representation::UNUSUAL_BYTE_GROUPINGS, + loops::EMPTY_LOOP, + loops::EXPLICIT_COUNTER_LOOP, + loops::EXPLICIT_INTO_ITER_LOOP, + loops::EXPLICIT_ITER_LOOP, + loops::FOR_KV_MAP, + loops::FOR_LOOPS_OVER_FALLIBLES, + loops::ITER_NEXT_LOOP, + loops::MANUAL_FLATTEN, + loops::MANUAL_MEMCPY, + loops::MUT_RANGE_BOUND, + loops::NEEDLESS_COLLECT, + loops::NEEDLESS_RANGE_LOOP, + loops::NEVER_LOOP, + loops::SAME_ITEM_PUSH, + loops::SINGLE_ELEMENT_LOOP, + loops::WHILE_IMMUTABLE_CONDITION, + loops::WHILE_LET_LOOP, + loops::WHILE_LET_ON_ITERATOR, + macro_use::MACRO_USE_IMPORTS, + main_recursion::MAIN_RECURSION, + manual_async_fn::MANUAL_ASYNC_FN, + manual_map::MANUAL_MAP, + manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, + manual_ok_or::MANUAL_OK_OR, + manual_strip::MANUAL_STRIP, + 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, + matches::INFALLIBLE_DESTRUCTURING_MATCH, + matches::MATCH_AS_REF, + matches::MATCH_BOOL, + matches::MATCH_LIKE_MATCHES_MACRO, + matches::MATCH_OVERLAPPING_ARM, + matches::MATCH_REF_PATS, + matches::MATCH_SAME_ARMS, + matches::MATCH_SINGLE_BINDING, + matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS, + matches::MATCH_WILD_ERR_ARM, + matches::REDUNDANT_PATTERN_MATCHING, + matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, + matches::SINGLE_MATCH, + matches::SINGLE_MATCH_ELSE, + matches::WILDCARD_ENUM_MATCH_ARM, + matches::WILDCARD_IN_OR_PATTERNS, + mem_discriminant::MEM_DISCRIMINANT_NON_ENUM, + mem_forget::MEM_FORGET, + mem_replace::MEM_REPLACE_OPTION_WITH_NONE, + mem_replace::MEM_REPLACE_WITH_DEFAULT, + mem_replace::MEM_REPLACE_WITH_UNINIT, + methods::BIND_INSTEAD_OF_MAP, + methods::BYTES_NTH, + methods::CHARS_LAST_CMP, + methods::CHARS_NEXT_CMP, + methods::CLONED_INSTEAD_OF_COPIED, + methods::CLONE_DOUBLE_REF, + methods::CLONE_ON_COPY, + methods::CLONE_ON_REF_PTR, + methods::EXPECT_FUN_CALL, + methods::EXPECT_USED, + methods::FILETYPE_IS_FILE, + methods::FILTER_MAP_IDENTITY, + methods::FILTER_MAP_NEXT, + methods::FILTER_NEXT, + methods::FLAT_MAP_IDENTITY, + methods::FLAT_MAP_OPTION, + methods::FROM_ITER_INSTEAD_OF_COLLECT, + methods::GET_UNWRAP, + methods::IMPLICIT_CLONE, + methods::INEFFICIENT_TO_STRING, + methods::INSPECT_FOR_EACH, + methods::INTO_ITER_ON_REF, + methods::ITERATOR_STEP_BY_ZERO, + methods::ITER_CLONED_COLLECT, + methods::ITER_COUNT, + methods::ITER_NEXT_SLICE, + methods::ITER_NTH, + methods::ITER_NTH_ZERO, + methods::ITER_SKIP_NEXT, + methods::MANUAL_FILTER_MAP, + methods::MANUAL_FIND_MAP, + methods::MANUAL_SATURATING_ARITHMETIC, + methods::MAP_COLLECT_RESULT_UNIT, + methods::MAP_FLATTEN, + methods::MAP_UNWRAP_OR, + methods::NEW_RET_NO_SELF, + methods::OK_EXPECT, + methods::OPTION_AS_REF_DEREF, + methods::OPTION_FILTER_MAP, + methods::OPTION_MAP_OR_NONE, + methods::OR_FUN_CALL, + methods::RESULT_MAP_OR_INTO_OPTION, + methods::SEARCH_IS_SOME, + methods::SHOULD_IMPLEMENT_TRAIT, + methods::SINGLE_CHAR_ADD_STR, + methods::SINGLE_CHAR_PATTERN, + methods::SKIP_WHILE_NEXT, + methods::STRING_EXTEND_CHARS, + methods::SUSPICIOUS_MAP, + methods::UNINIT_ASSUMED_INIT, + methods::UNNECESSARY_FILTER_MAP, + methods::UNNECESSARY_FOLD, + methods::UNNECESSARY_LAZY_EVALUATIONS, + methods::UNWRAP_USED, + methods::USELESS_ASREF, + methods::WRONG_PUB_SELF_CONVENTION, + methods::WRONG_SELF_CONVENTION, + methods::ZST_OFFSET, + minmax::MIN_MAX, + misc::CMP_NAN, + misc::CMP_OWNED, + misc::FLOAT_CMP, + misc::FLOAT_CMP_CONST, + misc::MODULO_ONE, + misc::SHORT_CIRCUIT_STATEMENT, + misc::TOPLEVEL_REF_ARG, + misc::USED_UNDERSCORE_BINDING, + misc::ZERO_PTR, + misc_early::BUILTIN_TYPE_SHADOW, + misc_early::DOUBLE_NEG, + misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, + misc_early::MIXED_CASE_HEX_LITERALS, + misc_early::REDUNDANT_PATTERN, + misc_early::UNNEEDED_FIELD_PATTERN, + misc_early::UNNEEDED_WILDCARD_PATTERN, + misc_early::UNSEPARATED_LITERAL_SUFFIX, + misc_early::ZERO_PREFIXED_LITERAL, + missing_const_for_fn::MISSING_CONST_FOR_FN, + missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, + missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, + modulo_arithmetic::MODULO_ARITHMETIC, + multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, + mut_key::MUTABLE_KEY_TYPE, + mut_mut::MUT_MUT, + mut_mutex_lock::MUT_MUTEX_LOCK, + mut_reference::UNNECESSARY_MUT_PASSED, + mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL, + mutex_atomic::MUTEX_ATOMIC, + mutex_atomic::MUTEX_INTEGER, + needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE, + needless_bool::BOOL_COMPARISON, + needless_bool::NEEDLESS_BOOL, + needless_borrow::NEEDLESS_BORROW, + needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, + needless_continue::NEEDLESS_CONTINUE, + needless_for_each::NEEDLESS_FOR_EACH, + needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, + needless_question_mark::NEEDLESS_QUESTION_MARK, + needless_update::NEEDLESS_UPDATE, + neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, + neg_multiply::NEG_MULTIPLY, + new_without_default::NEW_WITHOUT_DEFAULT, + no_effect::NO_EFFECT, + no_effect::UNNECESSARY_OPERATION, + non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, + non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST, + non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, + non_expressive_names::MANY_SINGLE_CHAR_NAMES, + non_expressive_names::SIMILAR_NAMES, + non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS, + open_options::NONSENSICAL_OPEN_OPTIONS, + option_env_unwrap::OPTION_ENV_UNWRAP, + option_if_let_else::OPTION_IF_LET_ELSE, + overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, + panic_in_result_fn::PANIC_IN_RESULT_FN, + panic_unimplemented::PANIC, + panic_unimplemented::TODO, + panic_unimplemented::UNIMPLEMENTED, + panic_unimplemented::UNREACHABLE, + partialeq_ne_impl::PARTIALEQ_NE_IMPL, + pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE, + pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF, + path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, + pattern_type_mismatch::PATTERN_TYPE_MISMATCH, + precedence::PRECEDENCE, + ptr::CMP_NULL, + ptr::INVALID_NULL_PTR_USAGE, + ptr::MUT_FROM_REF, + ptr::PTR_ARG, + ptr_eq::PTR_EQ, + ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, + question_mark::QUESTION_MARK, + ranges::MANUAL_RANGE_CONTAINS, + ranges::RANGE_MINUS_ONE, + ranges::RANGE_PLUS_ONE, + ranges::RANGE_ZIP_WITH_LEN, + ranges::REVERSED_EMPTY_RANGES, + redundant_clone::REDUNDANT_CLONE, + redundant_closure_call::REDUNDANT_CLOSURE_CALL, + redundant_else::REDUNDANT_ELSE, + redundant_field_names::REDUNDANT_FIELD_NAMES, + redundant_pub_crate::REDUNDANT_PUB_CRATE, + redundant_slicing::REDUNDANT_SLICING, + redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES, + ref_option_ref::REF_OPTION_REF, + reference::DEREF_ADDROF, + reference::REF_IN_DEREF, + regex::INVALID_REGEX, + regex::TRIVIAL_REGEX, + repeat_once::REPEAT_ONCE, + returns::LET_AND_RETURN, + returns::NEEDLESS_RETURN, + self_assignment::SELF_ASSIGNMENT, + semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED, + serde_api::SERDE_API_MISUSE, + shadow::SHADOW_REUSE, + shadow::SHADOW_SAME, + shadow::SHADOW_UNRELATED, + single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, + size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT, + slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, + stable_sort_primitive::STABLE_SORT_PRIMITIVE, + strings::STRING_ADD, + strings::STRING_ADD_ASSIGN, + strings::STRING_FROM_UTF8_AS_BYTES, + strings::STRING_LIT_AS_BYTES, + strings::STRING_TO_STRING, + strings::STR_TO_STRING, + suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS, + suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, + suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, + swap::ALMOST_SWAPPED, + swap::MANUAL_SWAP, + tabs_in_doc_comments::TABS_IN_DOC_COMMENTS, + temporary_assignment::TEMPORARY_ASSIGNMENT, + to_digit_is_some::TO_DIGIT_IS_SOME, + to_string_in_display::TO_STRING_IN_DISPLAY, + trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS, + trait_bounds::TYPE_REPETITION_IN_BOUNDS, + transmute::CROSSPOINTER_TRANSMUTE, + transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + transmute::TRANSMUTE_BYTES_TO_STR, + transmute::TRANSMUTE_FLOAT_TO_INT, + transmute::TRANSMUTE_INT_TO_BOOL, + transmute::TRANSMUTE_INT_TO_CHAR, + transmute::TRANSMUTE_INT_TO_FLOAT, + transmute::TRANSMUTE_PTR_TO_PTR, + transmute::TRANSMUTE_PTR_TO_REF, + transmute::UNSOUND_COLLECTION_TRANSMUTE, + transmute::USELESS_TRANSMUTE, + transmute::WRONG_TRANSMUTE, + transmuting_null::TRANSMUTING_NULL, + try_err::TRY_ERR, + types::BORROWED_BOX, + types::BOX_VEC, + types::LINKEDLIST, + types::OPTION_OPTION, + types::RC_BUFFER, + types::REDUNDANT_ALLOCATION, + types::TYPE_COMPLEXITY, + types::VEC_BOX, + undropped_manually_drops::UNDROPPED_MANUALLY_DROPS, + unicode::INVISIBLE_CHARACTERS, + unicode::NON_ASCII_LITERAL, + unicode::UNICODE_NOT_NFC, + unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD, + unit_types::LET_UNIT_VALUE, + unit_types::UNIT_ARG, + unit_types::UNIT_CMP, + unnamed_address::FN_ADDRESS_COMPARISONS, + unnamed_address::VTABLE_ADDRESS_COMPARISONS, + unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS, + unnecessary_sort_by::UNNECESSARY_SORT_BY, + unnecessary_wraps::UNNECESSARY_WRAPS, + unnested_or_patterns::UNNESTED_OR_PATTERNS, + unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + unused_io_amount::UNUSED_IO_AMOUNT, + unused_self::UNUSED_SELF, + unused_unit::UNUSED_UNIT, + unwrap::PANICKING_UNWRAP, + unwrap::UNNECESSARY_UNWRAP, + unwrap_in_result::UNWRAP_IN_RESULT, + upper_case_acronyms::UPPER_CASE_ACRONYMS, + use_self::USE_SELF, + useless_conversion::USELESS_CONVERSION, + vec::USELESS_VEC, + vec_init_then_push::VEC_INIT_THEN_PUSH, + vec_resize_to_zero::VEC_RESIZE_TO_ZERO, + verbose_file_reads::VERBOSE_FILE_READS, + wildcard_dependencies::WILDCARD_DEPENDENCIES, + wildcard_imports::ENUM_GLOB_USE, + wildcard_imports::WILDCARD_IMPORTS, + write::PRINTLN_EMPTY_STRING, + write::PRINT_LITERAL, + write::PRINT_STDERR, + write::PRINT_STDOUT, + write::PRINT_WITH_NEWLINE, + write::USE_DEBUG, + write::WRITELN_EMPTY_STRING, + write::WRITE_LITERAL, + write::WRITE_WITH_NEWLINE, + zero_div_zero::ZERO_DIVIDED_BY_ZERO, + zero_sized_map_values::ZERO_SIZED_MAP_VALUES, ]); // end register lints, do not remove this comment, it’s used in `update_lints` @@ -1016,6 +1013,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box utils::inspector::DeepCodeInspector); store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new()); + store.register_late_pass(|| box utils::internal_lints::IfChainStyle); store.register_late_pass(|| box utils::internal_lints::InvalidPaths); store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default()); store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default()); @@ -1026,7 +1024,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box await_holding_invalid::AwaitHolding); store.register_late_pass(|| box serde_api::SerdeApi); let vec_box_size_threshold = conf.vec_box_size_threshold; - store.register_late_pass(move || box types::Types::new(vec_box_size_threshold)); + let type_complexity_threshold = conf.type_complexity_threshold; + store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold)); store.register_late_pass(|| box booleans::NonminimalBool); store.register_late_pass(|| box eq_op::EqOp); store.register_late_pass(|| box enum_clike::UnportableVariant); @@ -1037,6 +1036,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box ptr_eq::PtrEq); store.register_late_pass(|| box needless_bool::NeedlessBool); store.register_late_pass(|| box needless_bool::BoolComparison); + store.register_late_pass(|| box needless_for_each::NeedlessForEach); store.register_late_pass(|| box approx_const::ApproxConstant); store.register_late_pass(|| box misc::MiscLints); store.register_late_pass(|| box eta_reduction::EtaReduction); @@ -1055,6 +1055,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub); store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback); store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor); + store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions); + store.register_early_pass(|| box unnecessary_self_imports::UnnecessarySelfImports); let msrv = conf.msrv.as_ref().and_then(|s| { parse_msrv(s, None, None).or_else(|| { @@ -1075,21 +1077,19 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv)); store.register_late_pass(move || box use_self::UseSelf::new(msrv)); store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv)); - store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark::new(msrv)); + store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark); store.register_late_pass(move || box casts::Casts::new(msrv)); + store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv)); store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount); store.register_late_pass(|| box map_clone::MapClone); store.register_late_pass(|| box map_err_ignore::MapErrIgnore); store.register_late_pass(|| box shadow::Shadow); - store.register_late_pass(|| box types::LetUnitValue); - store.register_late_pass(|| box types::UnitCmp); + store.register_late_pass(|| box unit_types::UnitTypes); store.register_late_pass(|| box loops::Loops); store.register_late_pass(|| box main_recursion::MainRecursion::default()); store.register_late_pass(|| box lifetimes::Lifetimes); store.register_late_pass(|| box entry::HashMapPass); - let type_complexity_threshold = conf.type_complexity_threshold; - store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold)); store.register_late_pass(|| box minmax::MinMaxPass); store.register_late_pass(|| box open_options::OpenOptions); store.register_late_pass(|| box zero_div_zero::ZeroDiv); @@ -1111,8 +1111,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box get_last_with_len::GetLastWithLen); store.register_late_pass(|| box drop_forget_ref::DropForgetRef); store.register_late_pass(|| box empty_enum::EmptyEnum); - store.register_late_pass(|| box types::AbsurdExtremeComparisons); - store.register_late_pass(|| box types::InvalidUpcastComparisons); + store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons); + store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons); store.register_late_pass(|| box regex::Regex::default()); store.register_late_pass(|| box copies::CopyAndPaste); store.register_late_pass(|| box copy_iterator::CopyIterator); @@ -1122,9 +1122,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box new_without_default::NewWithoutDefault::default()); let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>(); store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone())); - let too_many_arguments_threshold1 = conf.too_many_arguments_threshold; - let too_many_lines_threshold2 = conf.too_many_lines_threshold; - store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold1, too_many_lines_threshold2)); + let too_many_arguments_threshold = conf.too_many_arguments_threshold; + let too_many_lines_threshold = conf.too_many_lines_threshold; + store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold)); let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>(); store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone())); store.register_late_pass(|| box neg_multiply::NegMultiply); @@ -1156,9 +1156,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box infinite_iter::InfiniteIter); store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody); store.register_late_pass(|| box useless_conversion::UselessConversion::default()); - store.register_late_pass(|| box types::ImplicitHasher); + store.register_late_pass(|| box implicit_hasher::ImplicitHasher); store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom); - store.register_late_pass(|| box types::UnitArg); store.register_late_pass(|| box double_comparison::DoubleComparisons); store.register_late_pass(|| box question_mark::QuestionMark); store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings); @@ -1241,7 +1240,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); store.register_late_pass(|| box unnamed_address::UnnamedAddress); - store.register_late_pass(|| box dereference::Dereferencing); + store.register_late_pass(|| box dereference::Dereferencing::default()); store.register_late_pass(|| box option_if_let_else::OptionIfLetElse); store.register_late_pass(|| box future_not_send::FutureNotSend); store.register_late_pass(|| box if_let_mutex::IfLetMutex); @@ -1254,7 +1253,6 @@ 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, }); - store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns); 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); @@ -1280,785 +1278,801 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box redundant_slicing::RedundantSlicing); store.register_late_pass(|| box from_str_radix_10::FromStrRadix10); store.register_late_pass(|| box manual_map::ManualMap); + 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_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ - LintId::of(&arithmetic::FLOAT_ARITHMETIC), - LintId::of(&arithmetic::INTEGER_ARITHMETIC), - LintId::of(&as_conversions::AS_CONVERSIONS), - LintId::of(&asm_syntax::INLINE_ASM_X86_ATT_SYNTAX), - LintId::of(&asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX), - LintId::of(&create_dir::CREATE_DIR), - LintId::of(&dbg_macro::DBG_MACRO), - LintId::of(&default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK), - LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE), - LintId::of(&exhaustive_items::EXHAUSTIVE_ENUMS), - LintId::of(&exhaustive_items::EXHAUSTIVE_STRUCTS), - LintId::of(&exit::EXIT), - LintId::of(&float_literal::LOSSY_FLOAT_LITERAL), - LintId::of(&implicit_return::IMPLICIT_RETURN), - LintId::of(&indexing_slicing::INDEXING_SLICING), - LintId::of(&inherent_impl::MULTIPLE_INHERENT_IMPL), - LintId::of(&integer_division::INTEGER_DIVISION), - LintId::of(&let_underscore::LET_UNDERSCORE_MUST_USE), - LintId::of(&literal_representation::DECIMAL_LITERAL_REPRESENTATION), - LintId::of(&map_err_ignore::MAP_ERR_IGNORE), - LintId::of(&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS), - LintId::of(&matches::WILDCARD_ENUM_MATCH_ARM), - LintId::of(&mem_forget::MEM_FORGET), - LintId::of(&methods::CLONE_ON_REF_PTR), - LintId::of(&methods::EXPECT_USED), - LintId::of(&methods::FILETYPE_IS_FILE), - LintId::of(&methods::GET_UNWRAP), - LintId::of(&methods::UNWRAP_USED), - LintId::of(&methods::WRONG_PUB_SELF_CONVENTION), - 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_inline::MISSING_INLINE_IN_PUBLIC_ITEMS), - LintId::of(&modulo_arithmetic::MODULO_ARITHMETIC), - LintId::of(&panic_in_result_fn::PANIC_IN_RESULT_FN), - LintId::of(&panic_unimplemented::PANIC), - LintId::of(&panic_unimplemented::TODO), - LintId::of(&panic_unimplemented::UNIMPLEMENTED), - LintId::of(&panic_unimplemented::UNREACHABLE), - LintId::of(&pattern_type_mismatch::PATTERN_TYPE_MISMATCH), - LintId::of(&semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED), - LintId::of(&shadow::SHADOW_REUSE), - LintId::of(&shadow::SHADOW_SAME), - LintId::of(&strings::STRING_ADD), - LintId::of(&strings::STRING_TO_STRING), - LintId::of(&strings::STR_TO_STRING), - LintId::of(&types::RC_BUFFER), - LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT), - LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), - LintId::of(&write::PRINT_STDERR), - LintId::of(&write::PRINT_STDOUT), - LintId::of(&write::USE_DEBUG), + LintId::of(arithmetic::FLOAT_ARITHMETIC), + LintId::of(arithmetic::INTEGER_ARITHMETIC), + LintId::of(as_conversions::AS_CONVERSIONS), + LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX), + LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX), + LintId::of(create_dir::CREATE_DIR), + LintId::of(dbg_macro::DBG_MACRO), + LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK), + LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE), + LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS), + LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS), + LintId::of(exit::EXIT), + LintId::of(float_literal::LOSSY_FLOAT_LITERAL), + LintId::of(if_then_some_else_none::IF_THEN_SOME_ELSE_NONE), + LintId::of(implicit_return::IMPLICIT_RETURN), + LintId::of(indexing_slicing::INDEXING_SLICING), + LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL), + LintId::of(integer_division::INTEGER_DIVISION), + LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE), + LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION), + LintId::of(map_err_ignore::MAP_ERR_IGNORE), + LintId::of(matches::REST_PAT_IN_FULLY_BOUND_STRUCTS), + LintId::of(matches::WILDCARD_ENUM_MATCH_ARM), + LintId::of(mem_forget::MEM_FORGET), + LintId::of(methods::CLONE_ON_REF_PTR), + LintId::of(methods::EXPECT_USED), + LintId::of(methods::FILETYPE_IS_FILE), + LintId::of(methods::GET_UNWRAP), + LintId::of(methods::UNWRAP_USED), + LintId::of(methods::WRONG_PUB_SELF_CONVENTION), + 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_inline::MISSING_INLINE_IN_PUBLIC_ITEMS), + LintId::of(modulo_arithmetic::MODULO_ARITHMETIC), + LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN), + LintId::of(panic_unimplemented::PANIC), + LintId::of(panic_unimplemented::TODO), + LintId::of(panic_unimplemented::UNIMPLEMENTED), + LintId::of(panic_unimplemented::UNREACHABLE), + LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH), + LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED), + LintId::of(shadow::SHADOW_REUSE), + LintId::of(shadow::SHADOW_SAME), + LintId::of(strings::STRING_ADD), + LintId::of(strings::STRING_TO_STRING), + LintId::of(strings::STR_TO_STRING), + LintId::of(types::RC_BUFFER), + LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS), + LintId::of(unwrap_in_result::UNWRAP_IN_RESULT), + LintId::of(verbose_file_reads::VERBOSE_FILE_READS), + LintId::of(write::PRINT_STDERR), + LintId::of(write::PRINT_STDOUT), + LintId::of(write::USE_DEBUG), ]); store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ - LintId::of(&attrs::INLINE_ALWAYS), - LintId::of(&await_holding_invalid::AWAIT_HOLDING_LOCK), - LintId::of(&await_holding_invalid::AWAIT_HOLDING_REFCELL_REF), - LintId::of(&bit_mask::VERBOSE_BIT_MASK), - LintId::of(&bytecount::NAIVE_BYTECOUNT), - LintId::of(&case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS), - LintId::of(&casts::CAST_LOSSLESS), - LintId::of(&casts::CAST_POSSIBLE_TRUNCATION), - LintId::of(&casts::CAST_POSSIBLE_WRAP), - LintId::of(&casts::CAST_PRECISION_LOSS), - LintId::of(&casts::CAST_PTR_ALIGNMENT), - LintId::of(&casts::CAST_SIGN_LOSS), - LintId::of(&casts::PTR_AS_PTR), - LintId::of(&checked_conversions::CHECKED_CONVERSIONS), - LintId::of(&copies::SAME_FUNCTIONS_IN_IF_CONDITION), - LintId::of(©_iterator::COPY_ITERATOR), - LintId::of(&default::DEFAULT_TRAIT_ACCESS), - LintId::of(&dereference::EXPLICIT_DEREF_METHODS), - LintId::of(&derive::EXPL_IMPL_CLONE_ON_COPY), - LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE), - LintId::of(&doc::DOC_MARKDOWN), - LintId::of(&doc::MISSING_ERRORS_DOC), - LintId::of(&doc::MISSING_PANICS_DOC), - LintId::of(&empty_enum::EMPTY_ENUM), - LintId::of(&enum_variants::MODULE_NAME_REPETITIONS), - LintId::of(&enum_variants::PUB_ENUM_VARIANT_NAMES), - LintId::of(&eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), - LintId::of(&excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS), - LintId::of(&excessive_bools::STRUCT_EXCESSIVE_BOOLS), - LintId::of(&functions::MUST_USE_CANDIDATE), - LintId::of(&functions::TOO_MANY_LINES), - LintId::of(&if_not_else::IF_NOT_ELSE), - LintId::of(&implicit_saturating_sub::IMPLICIT_SATURATING_SUB), - LintId::of(&infinite_iter::MAYBE_INFINITE_ITER), - LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS), - LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS), - LintId::of(&let_underscore::LET_UNDERSCORE_DROP), - LintId::of(&literal_representation::LARGE_DIGIT_GROUPS), - LintId::of(&literal_representation::UNREADABLE_LITERAL), - LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP), - LintId::of(&loops::EXPLICIT_ITER_LOOP), - LintId::of(¯o_use::MACRO_USE_IMPORTS), - LintId::of(&manual_ok_or::MANUAL_OK_OR), - LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), - LintId::of(&matches::MATCH_BOOL), - LintId::of(&matches::MATCH_SAME_ARMS), - LintId::of(&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS), - LintId::of(&matches::MATCH_WILD_ERR_ARM), - LintId::of(&matches::SINGLE_MATCH_ELSE), - LintId::of(&methods::FILTER_MAP), - LintId::of(&methods::FILTER_MAP_NEXT), - LintId::of(&methods::IMPLICIT_CLONE), - LintId::of(&methods::INEFFICIENT_TO_STRING), - LintId::of(&methods::MAP_FLATTEN), - LintId::of(&methods::MAP_UNWRAP_OR), - LintId::of(&misc::USED_UNDERSCORE_BINDING), - LintId::of(&misc_early::UNSEPARATED_LITERAL_SUFFIX), - LintId::of(&mut_mut::MUT_MUT), - LintId::of(&needless_continue::NEEDLESS_CONTINUE), - LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), - LintId::of(&non_expressive_names::SIMILAR_NAMES), - LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE), - LintId::of(&pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE), - LintId::of(&pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF), - LintId::of(&ranges::RANGE_MINUS_ONE), - LintId::of(&ranges::RANGE_PLUS_ONE), - LintId::of(&redundant_else::REDUNDANT_ELSE), - LintId::of(&ref_option_ref::REF_OPTION_REF), - LintId::of(&shadow::SHADOW_UNRELATED), - LintId::of(&strings::STRING_ADD_ASSIGN), - LintId::of(&trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS), - LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS), - LintId::of(&types::IMPLICIT_HASHER), - LintId::of(&types::INVALID_UPCAST_COMPARISONS), - LintId::of(&types::LET_UNIT_VALUE), - LintId::of(&types::LINKEDLIST), - LintId::of(&types::OPTION_OPTION), - LintId::of(&unicode::NON_ASCII_LITERAL), - LintId::of(&unicode::UNICODE_NOT_NFC), - LintId::of(&unnecessary_wraps::UNNECESSARY_WRAPS), - LintId::of(&unnested_or_patterns::UNNESTED_OR_PATTERNS), - LintId::of(&unused_self::UNUSED_SELF), - LintId::of(&wildcard_imports::ENUM_GLOB_USE), - LintId::of(&wildcard_imports::WILDCARD_IMPORTS), - LintId::of(&zero_sized_map_values::ZERO_SIZED_MAP_VALUES), + LintId::of(attrs::INLINE_ALWAYS), + LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK), + LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF), + LintId::of(bit_mask::VERBOSE_BIT_MASK), + LintId::of(bytecount::NAIVE_BYTECOUNT), + LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS), + LintId::of(casts::CAST_LOSSLESS), + LintId::of(casts::CAST_POSSIBLE_TRUNCATION), + LintId::of(casts::CAST_POSSIBLE_WRAP), + LintId::of(casts::CAST_PRECISION_LOSS), + LintId::of(casts::CAST_PTR_ALIGNMENT), + LintId::of(casts::CAST_SIGN_LOSS), + LintId::of(casts::PTR_AS_PTR), + LintId::of(checked_conversions::CHECKED_CONVERSIONS), + LintId::of(copies::SAME_FUNCTIONS_IN_IF_CONDITION), + LintId::of(copy_iterator::COPY_ITERATOR), + LintId::of(default::DEFAULT_TRAIT_ACCESS), + LintId::of(dereference::EXPLICIT_DEREF_METHODS), + LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY), + LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE), + LintId::of(doc::DOC_MARKDOWN), + LintId::of(doc::MISSING_ERRORS_DOC), + LintId::of(doc::MISSING_PANICS_DOC), + LintId::of(empty_enum::EMPTY_ENUM), + LintId::of(enum_variants::MODULE_NAME_REPETITIONS), + LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES), + LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), + LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS), + LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS), + LintId::of(functions::MUST_USE_CANDIDATE), + LintId::of(functions::TOO_MANY_LINES), + LintId::of(if_not_else::IF_NOT_ELSE), + LintId::of(implicit_hasher::IMPLICIT_HASHER), + LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB), + LintId::of(infinite_iter::MAYBE_INFINITE_ITER), + LintId::of(invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS), + LintId::of(items_after_statements::ITEMS_AFTER_STATEMENTS), + LintId::of(large_stack_arrays::LARGE_STACK_ARRAYS), + LintId::of(let_underscore::LET_UNDERSCORE_DROP), + LintId::of(literal_representation::LARGE_DIGIT_GROUPS), + LintId::of(literal_representation::UNREADABLE_LITERAL), + LintId::of(loops::EXPLICIT_INTO_ITER_LOOP), + LintId::of(loops::EXPLICIT_ITER_LOOP), + LintId::of(macro_use::MACRO_USE_IMPORTS), + LintId::of(manual_ok_or::MANUAL_OK_OR), + LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS), + LintId::of(matches::MATCH_BOOL), + LintId::of(matches::MATCH_SAME_ARMS), + LintId::of(matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS), + LintId::of(matches::MATCH_WILD_ERR_ARM), + LintId::of(matches::SINGLE_MATCH_ELSE), + LintId::of(methods::CLONED_INSTEAD_OF_COPIED), + LintId::of(methods::FILTER_MAP_NEXT), + LintId::of(methods::FLAT_MAP_OPTION), + LintId::of(methods::IMPLICIT_CLONE), + LintId::of(methods::INEFFICIENT_TO_STRING), + LintId::of(methods::MAP_FLATTEN), + LintId::of(methods::MAP_UNWRAP_OR), + LintId::of(misc::USED_UNDERSCORE_BINDING), + LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX), + LintId::of(mut_mut::MUT_MUT), + LintId::of(needless_continue::NEEDLESS_CONTINUE), + LintId::of(needless_for_each::NEEDLESS_FOR_EACH), + LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), + LintId::of(non_expressive_names::SIMILAR_NAMES), + LintId::of(option_if_let_else::OPTION_IF_LET_ELSE), + LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE), + LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF), + LintId::of(ranges::RANGE_MINUS_ONE), + LintId::of(ranges::RANGE_PLUS_ONE), + LintId::of(redundant_else::REDUNDANT_ELSE), + LintId::of(ref_option_ref::REF_OPTION_REF), + LintId::of(shadow::SHADOW_UNRELATED), + LintId::of(strings::STRING_ADD_ASSIGN), + LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS), + LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS), + LintId::of(transmute::TRANSMUTE_PTR_TO_PTR), + LintId::of(types::LINKEDLIST), + LintId::of(types::OPTION_OPTION), + LintId::of(unicode::NON_ASCII_LITERAL), + LintId::of(unicode::UNICODE_NOT_NFC), + LintId::of(unit_types::LET_UNIT_VALUE), + LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS), + LintId::of(unnested_or_patterns::UNNESTED_OR_PATTERNS), + LintId::of(unused_self::UNUSED_SELF), + LintId::of(wildcard_imports::ENUM_GLOB_USE), + LintId::of(wildcard_imports::WILDCARD_IMPORTS), + LintId::of(zero_sized_map_values::ZERO_SIZED_MAP_VALUES), ]); #[cfg(feature = "internal-lints")] store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ - LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL), - LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), - LintId::of(&utils::internal_lints::COMPILER_LINT_FUNCTIONS), - LintId::of(&utils::internal_lints::DEFAULT_LINT), - LintId::of(&utils::internal_lints::INTERNING_DEFINED_SYMBOL), - LintId::of(&utils::internal_lints::INVALID_PATHS), - LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS), - LintId::of(&utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM), - LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA), - LintId::of(&utils::internal_lints::PRODUCE_ICE), - LintId::of(&utils::internal_lints::UNNECESSARY_SYMBOL_STR), + LintId::of(utils::internal_lints::CLIPPY_LINTS_INTERNAL), + LintId::of(utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), + LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS), + LintId::of(utils::internal_lints::DEFAULT_LINT), + LintId::of(utils::internal_lints::IF_CHAIN_STYLE), + LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL), + LintId::of(utils::internal_lints::INVALID_PATHS), + LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS), + LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM), + LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA), + LintId::of(utils::internal_lints::PRODUCE_ICE), + LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR), ]); store.register_group(true, "clippy::all", Some("clippy"), vec![ - LintId::of(&approx_const::APPROX_CONSTANT), - LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(&assign_ops::ASSIGN_OP_PATTERN), - LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP), - LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC), - LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING), - LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), - LintId::of(&attrs::DEPRECATED_CFG_ATTR), - LintId::of(&attrs::DEPRECATED_SEMVER), - LintId::of(&attrs::MISMATCHED_TARGET_OS), - LintId::of(&attrs::USELESS_ATTRIBUTE), - LintId::of(&bit_mask::BAD_BIT_MASK), - LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK), - LintId::of(&blacklisted_name::BLACKLISTED_NAME), - LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), - LintId::of(&booleans::LOGIC_BUG), - LintId::of(&booleans::NONMINIMAL_BOOL), - LintId::of(&casts::CAST_REF_TO_MUT), - LintId::of(&casts::CHAR_LIT_AS_U8), - LintId::of(&casts::FN_TO_NUMERIC_CAST), - LintId::of(&casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), - LintId::of(&casts::UNNECESSARY_CAST), - LintId::of(&collapsible_if::COLLAPSIBLE_ELSE_IF), - LintId::of(&collapsible_if::COLLAPSIBLE_IF), - LintId::of(&collapsible_match::COLLAPSIBLE_MATCH), - LintId::of(&comparison_chain::COMPARISON_CHAIN), - LintId::of(&copies::IFS_SAME_COND), - LintId::of(&copies::IF_SAME_THEN_ELSE), - LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT), - LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD), - LintId::of(&doc::MISSING_SAFETY_DOC), - LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), - LintId::of(&double_comparison::DOUBLE_COMPARISONS), - LintId::of(&double_parens::DOUBLE_PARENS), - LintId::of(&drop_forget_ref::DROP_COPY), - LintId::of(&drop_forget_ref::DROP_REF), - LintId::of(&drop_forget_ref::FORGET_COPY), - LintId::of(&drop_forget_ref::FORGET_REF), - LintId::of(&duration_subsec::DURATION_SUBSEC), - LintId::of(&entry::MAP_ENTRY), - LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), - LintId::of(&enum_variants::ENUM_VARIANT_NAMES), - LintId::of(&enum_variants::MODULE_INCEPTION), - LintId::of(&eq_op::EQ_OP), - LintId::of(&eq_op::OP_REF), - LintId::of(&erasing_op::ERASING_OP), - LintId::of(&escape::BOXED_LOCAL), - LintId::of(&eta_reduction::REDUNDANT_CLOSURE), - LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION), - LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE), - LintId::of(&explicit_write::EXPLICIT_WRITE), - LintId::of(&float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), - LintId::of(&float_literal::EXCESSIVE_PRECISION), - LintId::of(&format::USELESS_FORMAT), - LintId::of(&formatting::POSSIBLE_MISSING_COMMA), - 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), - LintId::of(&functions::MUST_USE_UNIT), - LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF), - LintId::of(&functions::RESULT_UNIT_ERR), - LintId::of(&functions::TOO_MANY_ARGUMENTS), - LintId::of(&get_last_with_len::GET_LAST_WITH_LEN), - LintId::of(&identity_op::IDENTITY_OP), - LintId::of(&if_let_mutex::IF_LET_MUTEX), - LintId::of(&if_let_some_result::IF_LET_SOME_RESULT), - LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), - LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING), - LintId::of(&infinite_iter::INFINITE_ITER), - LintId::of(&inherent_to_string::INHERENT_TO_STRING), - LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), - LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), - LintId::of(&int_plus_one::INT_PLUS_ONE), - LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS), - LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), - LintId::of(&len_zero::COMPARISON_TO_EMPTY), - LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), - LintId::of(&len_zero::LEN_ZERO), - LintId::of(&let_underscore::LET_UNDERSCORE_LOCK), - LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES), - LintId::of(&lifetimes::NEEDLESS_LIFETIMES), - LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), - LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES), - LintId::of(&literal_representation::UNUSUAL_BYTE_GROUPINGS), - LintId::of(&loops::EMPTY_LOOP), - LintId::of(&loops::EXPLICIT_COUNTER_LOOP), - LintId::of(&loops::FOR_KV_MAP), - LintId::of(&loops::FOR_LOOPS_OVER_FALLIBLES), - LintId::of(&loops::ITER_NEXT_LOOP), - LintId::of(&loops::MANUAL_FLATTEN), - LintId::of(&loops::MANUAL_MEMCPY), - LintId::of(&loops::MUT_RANGE_BOUND), - LintId::of(&loops::NEEDLESS_COLLECT), - LintId::of(&loops::NEEDLESS_RANGE_LOOP), - LintId::of(&loops::NEVER_LOOP), - LintId::of(&loops::SAME_ITEM_PUSH), - LintId::of(&loops::SINGLE_ELEMENT_LOOP), - LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), - LintId::of(&loops::WHILE_LET_LOOP), - LintId::of(&loops::WHILE_LET_ON_ITERATOR), - LintId::of(&main_recursion::MAIN_RECURSION), - LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), - LintId::of(&manual_map::MANUAL_MAP), - LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), - 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), - LintId::of(&matches::MATCH_AS_REF), - LintId::of(&matches::MATCH_LIKE_MATCHES_MACRO), - LintId::of(&matches::MATCH_OVERLAPPING_ARM), - LintId::of(&matches::MATCH_REF_PATS), - LintId::of(&matches::MATCH_SINGLE_BINDING), - LintId::of(&matches::REDUNDANT_PATTERN_MATCHING), - LintId::of(&matches::SINGLE_MATCH), - LintId::of(&matches::WILDCARD_IN_OR_PATTERNS), - LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), - LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE), - LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT), - LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT), - LintId::of(&methods::BIND_INSTEAD_OF_MAP), - LintId::of(&methods::BYTES_NTH), - LintId::of(&methods::CHARS_LAST_CMP), - LintId::of(&methods::CHARS_NEXT_CMP), - LintId::of(&methods::CLONE_DOUBLE_REF), - LintId::of(&methods::CLONE_ON_COPY), - LintId::of(&methods::EXPECT_FUN_CALL), - 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), - LintId::of(&methods::ITER_CLONED_COLLECT), - LintId::of(&methods::ITER_COUNT), - LintId::of(&methods::ITER_NEXT_SLICE), - LintId::of(&methods::ITER_NTH), - LintId::of(&methods::ITER_NTH_ZERO), - LintId::of(&methods::ITER_SKIP_NEXT), - LintId::of(&methods::MANUAL_FILTER_MAP), - LintId::of(&methods::MANUAL_FIND_MAP), - LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC), - LintId::of(&methods::MAP_COLLECT_RESULT_UNIT), - LintId::of(&methods::NEW_RET_NO_SELF), - LintId::of(&methods::OK_EXPECT), - LintId::of(&methods::OPTION_AS_REF_DEREF), - LintId::of(&methods::OPTION_MAP_OR_NONE), - LintId::of(&methods::OR_FUN_CALL), - LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION), - LintId::of(&methods::SEARCH_IS_SOME), - LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), - LintId::of(&methods::SINGLE_CHAR_ADD_STR), - LintId::of(&methods::SINGLE_CHAR_PATTERN), - LintId::of(&methods::SKIP_WHILE_NEXT), - LintId::of(&methods::STRING_EXTEND_CHARS), - LintId::of(&methods::SUSPICIOUS_MAP), - LintId::of(&methods::UNINIT_ASSUMED_INIT), - LintId::of(&methods::UNNECESSARY_FILTER_MAP), - LintId::of(&methods::UNNECESSARY_FOLD), - LintId::of(&methods::UNNECESSARY_LAZY_EVALUATIONS), - LintId::of(&methods::USELESS_ASREF), - LintId::of(&methods::WRONG_SELF_CONVENTION), - LintId::of(&methods::ZST_OFFSET), - LintId::of(&minmax::MIN_MAX), - LintId::of(&misc::CMP_NAN), - LintId::of(&misc::CMP_OWNED), - LintId::of(&misc::FLOAT_CMP), - LintId::of(&misc::MODULO_ONE), - LintId::of(&misc::SHORT_CIRCUIT_STATEMENT), - LintId::of(&misc::TOPLEVEL_REF_ARG), - LintId::of(&misc::ZERO_PTR), - LintId::of(&misc_early::BUILTIN_TYPE_SHADOW), - LintId::of(&misc_early::DOUBLE_NEG), - LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), - LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), - LintId::of(&misc_early::REDUNDANT_PATTERN), - LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN), - LintId::of(&misc_early::ZERO_PREFIXED_LITERAL), - LintId::of(&mut_key::MUTABLE_KEY_TYPE), - LintId::of(&mut_mutex_lock::MUT_MUTEX_LOCK), - LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), - LintId::of(&mutex_atomic::MUTEX_ATOMIC), - LintId::of(&needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), - LintId::of(&needless_bool::BOOL_COMPARISON), - LintId::of(&needless_bool::NEEDLESS_BOOL), - LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(&needless_question_mark::NEEDLESS_QUESTION_MARK), - LintId::of(&needless_update::NEEDLESS_UPDATE), - LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), - LintId::of(&neg_multiply::NEG_MULTIPLY), - LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), - LintId::of(&no_effect::NO_EFFECT), - LintId::of(&no_effect::UNNECESSARY_OPERATION), - LintId::of(&non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), - LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), - LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), - LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES), - LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), - LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), - LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), - LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), - LintId::of(&precedence::PRECEDENCE), - LintId::of(&ptr::CMP_NULL), - LintId::of(&ptr::MUT_FROM_REF), - LintId::of(&ptr::PTR_ARG), - LintId::of(&ptr_eq::PTR_EQ), - LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), - LintId::of(&question_mark::QUESTION_MARK), - LintId::of(&ranges::MANUAL_RANGE_CONTAINS), - LintId::of(&ranges::RANGE_ZIP_WITH_LEN), - LintId::of(&ranges::REVERSED_EMPTY_RANGES), - LintId::of(&redundant_clone::REDUNDANT_CLONE), - LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL), - LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), - LintId::of(&redundant_slicing::REDUNDANT_SLICING), - LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), - LintId::of(&reference::DEREF_ADDROF), - LintId::of(&reference::REF_IN_DEREF), - LintId::of(®ex::INVALID_REGEX), - LintId::of(&repeat_once::REPEAT_ONCE), - LintId::of(&returns::LET_AND_RETURN), - LintId::of(&returns::NEEDLESS_RETURN), - LintId::of(&self_assignment::SELF_ASSIGNMENT), - 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(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), - LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), - LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), - LintId::of(&swap::ALMOST_SWAPPED), - LintId::of(&swap::MANUAL_SWAP), - LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), - LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), - LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME), - LintId::of(&to_string_in_display::TO_STRING_IN_DISPLAY), - LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), - LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), - LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR), - LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT), - LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL), - LintId::of(&transmute::TRANSMUTE_INT_TO_CHAR), - LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT), - LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR), - LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), - LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE), - LintId::of(&transmute::WRONG_TRANSMUTE), - LintId::of(&transmuting_null::TRANSMUTING_NULL), - LintId::of(&try_err::TRY_ERR), - LintId::of(&types::ABSURD_EXTREME_COMPARISONS), - LintId::of(&types::BORROWED_BOX), - LintId::of(&types::BOX_VEC), - LintId::of(&types::REDUNDANT_ALLOCATION), - LintId::of(&types::TYPE_COMPLEXITY), - LintId::of(&types::UNIT_ARG), - LintId::of(&types::UNIT_CMP), - LintId::of(&types::VEC_BOX), - LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), - LintId::of(&unicode::INVISIBLE_CHARACTERS), - LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), - LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), - LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), - LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), - LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), - LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), - LintId::of(&unused_unit::UNUSED_UNIT), - LintId::of(&unwrap::PANICKING_UNWRAP), - LintId::of(&unwrap::UNNECESSARY_UNWRAP), - LintId::of(&upper_case_acronyms::UPPER_CASE_ACRONYMS), - LintId::of(&useless_conversion::USELESS_CONVERSION), - LintId::of(&vec::USELESS_VEC), - LintId::of(&vec_init_then_push::VEC_INIT_THEN_PUSH), - LintId::of(&vec_resize_to_zero::VEC_RESIZE_TO_ZERO), - LintId::of(&write::PRINTLN_EMPTY_STRING), - LintId::of(&write::PRINT_LITERAL), - LintId::of(&write::PRINT_WITH_NEWLINE), - LintId::of(&write::WRITELN_EMPTY_STRING), - LintId::of(&write::WRITE_LITERAL), - LintId::of(&write::WRITE_WITH_NEWLINE), - LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), + LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), + LintId::of(approx_const::APPROX_CONSTANT), + LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), + LintId::of(assign_ops::ASSIGN_OP_PATTERN), + LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), + LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), + LintId::of(atomic_ordering::INVALID_ATOMIC_ORDERING), + LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), + LintId::of(attrs::DEPRECATED_CFG_ATTR), + LintId::of(attrs::DEPRECATED_SEMVER), + LintId::of(attrs::MISMATCHED_TARGET_OS), + LintId::of(attrs::USELESS_ATTRIBUTE), + LintId::of(bit_mask::BAD_BIT_MASK), + LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), + LintId::of(blacklisted_name::BLACKLISTED_NAME), + LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), + LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), + LintId::of(booleans::LOGIC_BUG), + LintId::of(booleans::NONMINIMAL_BOOL), + LintId::of(casts::CAST_REF_TO_MUT), + LintId::of(casts::CHAR_LIT_AS_U8), + LintId::of(casts::FN_TO_NUMERIC_CAST), + LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), + LintId::of(casts::UNNECESSARY_CAST), + LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF), + LintId::of(collapsible_if::COLLAPSIBLE_IF), + LintId::of(collapsible_match::COLLAPSIBLE_MATCH), + LintId::of(comparison_chain::COMPARISON_CHAIN), + LintId::of(copies::BRANCHES_SHARING_CODE), + LintId::of(copies::IFS_SAME_COND), + LintId::of(copies::IF_SAME_THEN_ELSE), + LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), + LintId::of(derive::DERIVE_HASH_XOR_EQ), + LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(doc::MISSING_SAFETY_DOC), + LintId::of(doc::NEEDLESS_DOCTEST_MAIN), + LintId::of(double_comparison::DOUBLE_COMPARISONS), + LintId::of(double_parens::DOUBLE_PARENS), + LintId::of(drop_forget_ref::DROP_COPY), + LintId::of(drop_forget_ref::DROP_REF), + LintId::of(drop_forget_ref::FORGET_COPY), + LintId::of(drop_forget_ref::FORGET_REF), + LintId::of(duration_subsec::DURATION_SUBSEC), + LintId::of(entry::MAP_ENTRY), + LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), + LintId::of(enum_variants::ENUM_VARIANT_NAMES), + LintId::of(enum_variants::MODULE_INCEPTION), + LintId::of(eq_op::EQ_OP), + LintId::of(eq_op::OP_REF), + LintId::of(erasing_op::ERASING_OP), + LintId::of(escape::BOXED_LOCAL), + LintId::of(eta_reduction::REDUNDANT_CLOSURE), + LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION), + LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), + LintId::of(explicit_write::EXPLICIT_WRITE), + LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), + LintId::of(float_literal::EXCESSIVE_PRECISION), + LintId::of(format::USELESS_FORMAT), + LintId::of(formatting::POSSIBLE_MISSING_COMMA), + 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), + LintId::of(functions::MUST_USE_UNIT), + LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF), + LintId::of(functions::RESULT_UNIT_ERR), + LintId::of(functions::TOO_MANY_ARGUMENTS), + LintId::of(get_last_with_len::GET_LAST_WITH_LEN), + LintId::of(identity_op::IDENTITY_OP), + LintId::of(if_let_mutex::IF_LET_MUTEX), + LintId::of(if_let_some_result::IF_LET_SOME_RESULT), + LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), + LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING), + LintId::of(infinite_iter::INFINITE_ITER), + LintId::of(inherent_to_string::INHERENT_TO_STRING), + LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), + LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), + LintId::of(int_plus_one::INT_PLUS_ONE), + LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), + LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), + LintId::of(len_zero::COMPARISON_TO_EMPTY), + LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY), + LintId::of(len_zero::LEN_ZERO), + LintId::of(let_underscore::LET_UNDERSCORE_LOCK), + LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES), + LintId::of(lifetimes::NEEDLESS_LIFETIMES), + LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING), + LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES), + LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS), + LintId::of(loops::EMPTY_LOOP), + LintId::of(loops::EXPLICIT_COUNTER_LOOP), + LintId::of(loops::FOR_KV_MAP), + LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), + LintId::of(loops::ITER_NEXT_LOOP), + LintId::of(loops::MANUAL_FLATTEN), + LintId::of(loops::MANUAL_MEMCPY), + LintId::of(loops::MUT_RANGE_BOUND), + LintId::of(loops::NEEDLESS_COLLECT), + LintId::of(loops::NEEDLESS_RANGE_LOOP), + LintId::of(loops::NEVER_LOOP), + LintId::of(loops::SAME_ITEM_PUSH), + LintId::of(loops::SINGLE_ELEMENT_LOOP), + LintId::of(loops::WHILE_IMMUTABLE_CONDITION), + LintId::of(loops::WHILE_LET_LOOP), + LintId::of(loops::WHILE_LET_ON_ITERATOR), + LintId::of(main_recursion::MAIN_RECURSION), + LintId::of(manual_async_fn::MANUAL_ASYNC_FN), + LintId::of(manual_map::MANUAL_MAP), + LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), + 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), + LintId::of(matches::MATCH_AS_REF), + LintId::of(matches::MATCH_LIKE_MATCHES_MACRO), + LintId::of(matches::MATCH_OVERLAPPING_ARM), + LintId::of(matches::MATCH_REF_PATS), + LintId::of(matches::MATCH_SINGLE_BINDING), + LintId::of(matches::REDUNDANT_PATTERN_MATCHING), + LintId::of(matches::SINGLE_MATCH), + LintId::of(matches::WILDCARD_IN_OR_PATTERNS), + LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), + LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), + LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT), + LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), + LintId::of(methods::BIND_INSTEAD_OF_MAP), + LintId::of(methods::BYTES_NTH), + LintId::of(methods::CHARS_LAST_CMP), + LintId::of(methods::CHARS_NEXT_CMP), + LintId::of(methods::CLONE_DOUBLE_REF), + LintId::of(methods::CLONE_ON_COPY), + LintId::of(methods::EXPECT_FUN_CALL), + 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), + LintId::of(methods::ITER_CLONED_COLLECT), + LintId::of(methods::ITER_COUNT), + LintId::of(methods::ITER_NEXT_SLICE), + LintId::of(methods::ITER_NTH), + LintId::of(methods::ITER_NTH_ZERO), + LintId::of(methods::ITER_SKIP_NEXT), + LintId::of(methods::MANUAL_FILTER_MAP), + LintId::of(methods::MANUAL_FIND_MAP), + LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), + LintId::of(methods::MAP_COLLECT_RESULT_UNIT), + LintId::of(methods::NEW_RET_NO_SELF), + LintId::of(methods::OK_EXPECT), + LintId::of(methods::OPTION_AS_REF_DEREF), + LintId::of(methods::OPTION_FILTER_MAP), + LintId::of(methods::OPTION_MAP_OR_NONE), + LintId::of(methods::OR_FUN_CALL), + LintId::of(methods::RESULT_MAP_OR_INTO_OPTION), + LintId::of(methods::SEARCH_IS_SOME), + LintId::of(methods::SHOULD_IMPLEMENT_TRAIT), + LintId::of(methods::SINGLE_CHAR_ADD_STR), + LintId::of(methods::SINGLE_CHAR_PATTERN), + LintId::of(methods::SKIP_WHILE_NEXT), + LintId::of(methods::STRING_EXTEND_CHARS), + LintId::of(methods::SUSPICIOUS_MAP), + LintId::of(methods::UNINIT_ASSUMED_INIT), + LintId::of(methods::UNNECESSARY_FILTER_MAP), + LintId::of(methods::UNNECESSARY_FOLD), + LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS), + LintId::of(methods::USELESS_ASREF), + LintId::of(methods::WRONG_SELF_CONVENTION), + LintId::of(methods::ZST_OFFSET), + LintId::of(minmax::MIN_MAX), + LintId::of(misc::CMP_NAN), + LintId::of(misc::CMP_OWNED), + LintId::of(misc::FLOAT_CMP), + LintId::of(misc::MODULO_ONE), + LintId::of(misc::SHORT_CIRCUIT_STATEMENT), + LintId::of(misc::TOPLEVEL_REF_ARG), + LintId::of(misc::ZERO_PTR), + LintId::of(misc_early::BUILTIN_TYPE_SHADOW), + LintId::of(misc_early::DOUBLE_NEG), + LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), + LintId::of(misc_early::MIXED_CASE_HEX_LITERALS), + LintId::of(misc_early::REDUNDANT_PATTERN), + LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN), + LintId::of(misc_early::ZERO_PREFIXED_LITERAL), + LintId::of(mut_key::MUTABLE_KEY_TYPE), + LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK), + LintId::of(mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(mutex_atomic::MUTEX_ATOMIC), + LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), + LintId::of(needless_bool::BOOL_COMPARISON), + LintId::of(needless_bool::NEEDLESS_BOOL), + LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), + LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), + LintId::of(needless_update::NEEDLESS_UPDATE), + LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), + LintId::of(neg_multiply::NEG_MULTIPLY), + LintId::of(new_without_default::NEW_WITHOUT_DEFAULT), + LintId::of(no_effect::NO_EFFECT), + LintId::of(no_effect::UNNECESSARY_OPERATION), + LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), + LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), + LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), + LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), + 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), + LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), + LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), + LintId::of(precedence::PRECEDENCE), + LintId::of(ptr::CMP_NULL), + LintId::of(ptr::INVALID_NULL_PTR_USAGE), + LintId::of(ptr::MUT_FROM_REF), + LintId::of(ptr::PTR_ARG), + LintId::of(ptr_eq::PTR_EQ), + LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), + LintId::of(question_mark::QUESTION_MARK), + LintId::of(ranges::MANUAL_RANGE_CONTAINS), + LintId::of(ranges::RANGE_ZIP_WITH_LEN), + LintId::of(ranges::REVERSED_EMPTY_RANGES), + LintId::of(redundant_clone::REDUNDANT_CLONE), + LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL), + LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES), + LintId::of(redundant_slicing::REDUNDANT_SLICING), + LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), + LintId::of(reference::DEREF_ADDROF), + LintId::of(reference::REF_IN_DEREF), + LintId::of(regex::INVALID_REGEX), + LintId::of(repeat_once::REPEAT_ONCE), + LintId::of(returns::LET_AND_RETURN), + LintId::of(returns::NEEDLESS_RETURN), + LintId::of(self_assignment::SELF_ASSIGNMENT), + 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(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), + LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), + LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), + LintId::of(swap::ALMOST_SWAPPED), + LintId::of(swap::MANUAL_SWAP), + LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), + LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT), + LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), + LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY), + LintId::of(transmute::CROSSPOINTER_TRANSMUTE), + LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), + LintId::of(transmute::TRANSMUTE_BYTES_TO_STR), + LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT), + LintId::of(transmute::TRANSMUTE_INT_TO_BOOL), + LintId::of(transmute::TRANSMUTE_INT_TO_CHAR), + LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT), + LintId::of(transmute::TRANSMUTE_PTR_TO_REF), + LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), + LintId::of(transmute::WRONG_TRANSMUTE), + LintId::of(transmuting_null::TRANSMUTING_NULL), + LintId::of(try_err::TRY_ERR), + LintId::of(types::BORROWED_BOX), + LintId::of(types::BOX_VEC), + LintId::of(types::REDUNDANT_ALLOCATION), + LintId::of(types::TYPE_COMPLEXITY), + LintId::of(types::VEC_BOX), + LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), + LintId::of(unicode::INVISIBLE_CHARACTERS), + LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), + LintId::of(unit_types::UNIT_ARG), + LintId::of(unit_types::UNIT_CMP), + LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS), + LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS), + LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY), + LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), + LintId::of(unused_io_amount::UNUSED_IO_AMOUNT), + LintId::of(unused_unit::UNUSED_UNIT), + LintId::of(unwrap::PANICKING_UNWRAP), + LintId::of(unwrap::UNNECESSARY_UNWRAP), + LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS), + LintId::of(useless_conversion::USELESS_CONVERSION), + LintId::of(vec::USELESS_VEC), + LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH), + LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO), + LintId::of(write::PRINTLN_EMPTY_STRING), + LintId::of(write::PRINT_LITERAL), + LintId::of(write::PRINT_WITH_NEWLINE), + LintId::of(write::WRITELN_EMPTY_STRING), + LintId::of(write::WRITE_LITERAL), + LintId::of(write::WRITE_WITH_NEWLINE), + LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO), ]); 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(&casts::FN_TO_NUMERIC_CAST), - LintId::of(&casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), - LintId::of(&collapsible_if::COLLAPSIBLE_ELSE_IF), - LintId::of(&collapsible_if::COLLAPSIBLE_IF), - LintId::of(&collapsible_match::COLLAPSIBLE_MATCH), - LintId::of(&comparison_chain::COMPARISON_CHAIN), - LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT), - LintId::of(&doc::MISSING_SAFETY_DOC), - LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), - LintId::of(&enum_variants::ENUM_VARIANT_NAMES), - LintId::of(&enum_variants::MODULE_INCEPTION), - 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), - LintId::of(&functions::MUST_USE_UNIT), - LintId::of(&functions::RESULT_UNIT_ERR), - LintId::of(&if_let_some_result::IF_LET_SOME_RESULT), - LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), - LintId::of(&inherent_to_string::INHERENT_TO_STRING), - LintId::of(&len_zero::COMPARISON_TO_EMPTY), - LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), - 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), - LintId::of(&loops::WHILE_LET_ON_ITERATOR), - LintId::of(&main_recursion::MAIN_RECURSION), - LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), - LintId::of(&manual_map::MANUAL_MAP), - LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), - LintId::of(&map_clone::MAP_CLONE), - LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), - LintId::of(&matches::MATCH_LIKE_MATCHES_MACRO), - LintId::of(&matches::MATCH_OVERLAPPING_ARM), - LintId::of(&matches::MATCH_REF_PATS), - LintId::of(&matches::REDUNDANT_PATTERN_MATCHING), - LintId::of(&matches::SINGLE_MATCH), - LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE), - LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT), - 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), - LintId::of(&methods::ITER_NTH_ZERO), - LintId::of(&methods::ITER_SKIP_NEXT), - LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC), - LintId::of(&methods::MAP_COLLECT_RESULT_UNIT), - LintId::of(&methods::NEW_RET_NO_SELF), - LintId::of(&methods::OK_EXPECT), - LintId::of(&methods::OPTION_MAP_OR_NONE), - LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION), - LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), - LintId::of(&methods::SINGLE_CHAR_ADD_STR), - LintId::of(&methods::STRING_EXTEND_CHARS), - LintId::of(&methods::UNNECESSARY_FOLD), - LintId::of(&methods::UNNECESSARY_LAZY_EVALUATIONS), - LintId::of(&methods::WRONG_SELF_CONVENTION), - LintId::of(&misc::TOPLEVEL_REF_ARG), - LintId::of(&misc::ZERO_PTR), - LintId::of(&misc_early::BUILTIN_TYPE_SHADOW), - LintId::of(&misc_early::DOUBLE_NEG), - LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), - LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), - LintId::of(&misc_early::REDUNDANT_PATTERN), - LintId::of(&mut_mutex_lock::MUT_MUTEX_LOCK), - LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), - LintId::of(&neg_multiply::NEG_MULTIPLY), - LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), - LintId::of(&non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), - LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), - LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), - LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES), - LintId::of(&ptr::CMP_NULL), - LintId::of(&ptr::PTR_ARG), - LintId::of(&ptr_eq::PTR_EQ), - LintId::of(&question_mark::QUESTION_MARK), - LintId::of(&ranges::MANUAL_RANGE_CONTAINS), - LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES), - LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), - LintId::of(&returns::LET_AND_RETURN), - LintId::of(&returns::NEEDLESS_RETURN), - LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), - LintId::of(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), - LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), - LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME), - LintId::of(&try_err::TRY_ERR), - LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), - LintId::of(&unused_unit::UNUSED_UNIT), - LintId::of(&upper_case_acronyms::UPPER_CASE_ACRONYMS), - LintId::of(&write::PRINTLN_EMPTY_STRING), - LintId::of(&write::PRINT_LITERAL), - LintId::of(&write::PRINT_WITH_NEWLINE), - LintId::of(&write::WRITELN_EMPTY_STRING), - LintId::of(&write::WRITE_LITERAL), - LintId::of(&write::WRITE_WITH_NEWLINE), + 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), + LintId::of(casts::FN_TO_NUMERIC_CAST), + LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), + LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF), + LintId::of(collapsible_if::COLLAPSIBLE_IF), + LintId::of(collapsible_match::COLLAPSIBLE_MATCH), + LintId::of(comparison_chain::COMPARISON_CHAIN), + LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), + LintId::of(doc::MISSING_SAFETY_DOC), + LintId::of(doc::NEEDLESS_DOCTEST_MAIN), + LintId::of(enum_variants::ENUM_VARIANT_NAMES), + LintId::of(enum_variants::MODULE_INCEPTION), + 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), + LintId::of(functions::MUST_USE_UNIT), + LintId::of(functions::RESULT_UNIT_ERR), + LintId::of(if_let_some_result::IF_LET_SOME_RESULT), + LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), + LintId::of(inherent_to_string::INHERENT_TO_STRING), + LintId::of(len_zero::COMPARISON_TO_EMPTY), + LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY), + 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), + LintId::of(loops::WHILE_LET_ON_ITERATOR), + LintId::of(main_recursion::MAIN_RECURSION), + LintId::of(manual_async_fn::MANUAL_ASYNC_FN), + LintId::of(manual_map::MANUAL_MAP), + LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), + LintId::of(map_clone::MAP_CLONE), + LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH), + LintId::of(matches::MATCH_LIKE_MATCHES_MACRO), + LintId::of(matches::MATCH_OVERLAPPING_ARM), + LintId::of(matches::MATCH_REF_PATS), + LintId::of(matches::REDUNDANT_PATTERN_MATCHING), + LintId::of(matches::SINGLE_MATCH), + LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), + LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT), + 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), + LintId::of(methods::ITER_NTH_ZERO), + LintId::of(methods::ITER_SKIP_NEXT), + LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), + LintId::of(methods::MAP_COLLECT_RESULT_UNIT), + LintId::of(methods::NEW_RET_NO_SELF), + LintId::of(methods::OK_EXPECT), + LintId::of(methods::OPTION_MAP_OR_NONE), + LintId::of(methods::RESULT_MAP_OR_INTO_OPTION), + LintId::of(methods::SHOULD_IMPLEMENT_TRAIT), + LintId::of(methods::SINGLE_CHAR_ADD_STR), + LintId::of(methods::STRING_EXTEND_CHARS), + LintId::of(methods::UNNECESSARY_FOLD), + LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS), + LintId::of(methods::WRONG_SELF_CONVENTION), + LintId::of(misc::TOPLEVEL_REF_ARG), + LintId::of(misc::ZERO_PTR), + LintId::of(misc_early::BUILTIN_TYPE_SHADOW), + LintId::of(misc_early::DOUBLE_NEG), + LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), + LintId::of(misc_early::MIXED_CASE_HEX_LITERALS), + LintId::of(misc_early::REDUNDANT_PATTERN), + LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK), + LintId::of(mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(neg_multiply::NEG_MULTIPLY), + LintId::of(new_without_default::NEW_WITHOUT_DEFAULT), + LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), + LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), + LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), + LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), + LintId::of(ptr::CMP_NULL), + LintId::of(ptr::PTR_ARG), + LintId::of(ptr_eq::PTR_EQ), + LintId::of(question_mark::QUESTION_MARK), + LintId::of(ranges::MANUAL_RANGE_CONTAINS), + LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES), + LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), + LintId::of(returns::LET_AND_RETURN), + LintId::of(returns::NEEDLESS_RETURN), + LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), + LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), + LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), + LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), + LintId::of(try_err::TRY_ERR), + LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), + LintId::of(unused_unit::UNUSED_UNIT), + LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS), + LintId::of(write::PRINTLN_EMPTY_STRING), + LintId::of(write::PRINT_LITERAL), + LintId::of(write::PRINT_WITH_NEWLINE), + LintId::of(write::WRITELN_EMPTY_STRING), + LintId::of(write::WRITE_LITERAL), + LintId::of(write::WRITE_WITH_NEWLINE), ]); 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), - LintId::of(&casts::UNNECESSARY_CAST), - LintId::of(&double_comparison::DOUBLE_COMPARISONS), - 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), - LintId::of(&get_last_with_len::GET_LAST_WITH_LEN), - LintId::of(&identity_op::IDENTITY_OP), - LintId::of(&int_plus_one::INT_PLUS_ONE), - LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES), - 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), - LintId::of(&matches::MATCH_SINGLE_BINDING), - LintId::of(&matches::WILDCARD_IN_OR_PATTERNS), - LintId::of(&methods::BIND_INSTEAD_OF_MAP), - LintId::of(&methods::CLONE_ON_COPY), - LintId::of(&methods::FILTER_MAP_IDENTITY), - LintId::of(&methods::FILTER_NEXT), - LintId::of(&methods::FLAT_MAP_IDENTITY), - LintId::of(&methods::INSPECT_FOR_EACH), - LintId::of(&methods::ITER_COUNT), - LintId::of(&methods::MANUAL_FILTER_MAP), - LintId::of(&methods::MANUAL_FIND_MAP), - LintId::of(&methods::OPTION_AS_REF_DEREF), - 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), - LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN), - LintId::of(&misc_early::ZERO_PREFIXED_LITERAL), - LintId::of(&needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), - LintId::of(&needless_bool::BOOL_COMPARISON), - LintId::of(&needless_bool::NEEDLESS_BOOL), - LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(&needless_question_mark::NEEDLESS_QUESTION_MARK), - LintId::of(&needless_update::NEEDLESS_UPDATE), - LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), - LintId::of(&no_effect::NO_EFFECT), - LintId::of(&no_effect::UNNECESSARY_OPERATION), - LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), - LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), - LintId::of(&precedence::PRECEDENCE), - LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), - LintId::of(&ranges::RANGE_ZIP_WITH_LEN), - LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL), - LintId::of(&redundant_slicing::REDUNDANT_SLICING), - LintId::of(&reference::DEREF_ADDROF), - LintId::of(&reference::REF_IN_DEREF), - LintId::of(&repeat_once::REPEAT_ONCE), - LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES), - LintId::of(&swap::MANUAL_SWAP), - LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), - LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), - LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), - LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR), - LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT), - LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL), - LintId::of(&transmute::TRANSMUTE_INT_TO_CHAR), - LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT), - LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR), - LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), - LintId::of(&types::BORROWED_BOX), - LintId::of(&types::TYPE_COMPLEXITY), - LintId::of(&types::UNIT_ARG), - LintId::of(&types::VEC_BOX), - LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY), - LintId::of(&unwrap::UNNECESSARY_UNWRAP), - LintId::of(&useless_conversion::USELESS_CONVERSION), - LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), + 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), + LintId::of(casts::UNNECESSARY_CAST), + LintId::of(copies::BRANCHES_SHARING_CODE), + LintId::of(double_comparison::DOUBLE_COMPARISONS), + 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), + LintId::of(get_last_with_len::GET_LAST_WITH_LEN), + LintId::of(identity_op::IDENTITY_OP), + LintId::of(int_plus_one::INT_PLUS_ONE), + LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES), + 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), + LintId::of(matches::MATCH_SINGLE_BINDING), + LintId::of(matches::WILDCARD_IN_OR_PATTERNS), + LintId::of(methods::BIND_INSTEAD_OF_MAP), + LintId::of(methods::CLONE_ON_COPY), + LintId::of(methods::FILTER_MAP_IDENTITY), + LintId::of(methods::FILTER_NEXT), + LintId::of(methods::FLAT_MAP_IDENTITY), + LintId::of(methods::INSPECT_FOR_EACH), + LintId::of(methods::ITER_COUNT), + LintId::of(methods::MANUAL_FILTER_MAP), + LintId::of(methods::MANUAL_FIND_MAP), + 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), + LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN), + LintId::of(misc_early::ZERO_PREFIXED_LITERAL), + LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), + LintId::of(needless_bool::BOOL_COMPARISON), + LintId::of(needless_bool::NEEDLESS_BOOL), + LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), + LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), + LintId::of(needless_update::NEEDLESS_UPDATE), + LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), + LintId::of(no_effect::NO_EFFECT), + LintId::of(no_effect::UNNECESSARY_OPERATION), + LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), + LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), + LintId::of(precedence::PRECEDENCE), + LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), + LintId::of(ranges::RANGE_ZIP_WITH_LEN), + LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL), + LintId::of(redundant_slicing::REDUNDANT_SLICING), + LintId::of(reference::DEREF_ADDROF), + LintId::of(reference::REF_IN_DEREF), + LintId::of(repeat_once::REPEAT_ONCE), + LintId::of(strings::STRING_FROM_UTF8_AS_BYTES), + LintId::of(swap::MANUAL_SWAP), + LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT), + LintId::of(transmute::CROSSPOINTER_TRANSMUTE), + LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), + LintId::of(transmute::TRANSMUTE_BYTES_TO_STR), + LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT), + LintId::of(transmute::TRANSMUTE_INT_TO_BOOL), + LintId::of(transmute::TRANSMUTE_INT_TO_CHAR), + LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT), + LintId::of(transmute::TRANSMUTE_PTR_TO_REF), + LintId::of(types::BORROWED_BOX), + LintId::of(types::TYPE_COMPLEXITY), + LintId::of(types::VEC_BOX), + LintId::of(unit_types::UNIT_ARG), + LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY), + LintId::of(unwrap::UNNECESSARY_UNWRAP), + LintId::of(useless_conversion::USELESS_CONVERSION), + LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO), ]); store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![ - LintId::of(&approx_const::APPROX_CONSTANT), - LintId::of(&async_yields_async::ASYNC_YIELDS_ASYNC), - LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING), - LintId::of(&attrs::DEPRECATED_SEMVER), - LintId::of(&attrs::MISMATCHED_TARGET_OS), - LintId::of(&attrs::USELESS_ATTRIBUTE), - LintId::of(&bit_mask::BAD_BIT_MASK), - LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK), - LintId::of(&booleans::LOGIC_BUG), - LintId::of(&casts::CAST_REF_TO_MUT), - LintId::of(&copies::IFS_SAME_COND), - LintId::of(&copies::IF_SAME_THEN_ELSE), - LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD), - LintId::of(&drop_forget_ref::DROP_COPY), - LintId::of(&drop_forget_ref::DROP_REF), - LintId::of(&drop_forget_ref::FORGET_COPY), - LintId::of(&drop_forget_ref::FORGET_REF), - 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), - LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING), - LintId::of(&infinite_iter::INFINITE_ITER), - LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), - 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), - LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), - LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT), - LintId::of(&methods::CLONE_DOUBLE_REF), - LintId::of(&methods::ITERATOR_STEP_BY_ZERO), - LintId::of(&methods::UNINIT_ASSUMED_INIT), - LintId::of(&methods::ZST_OFFSET), - LintId::of(&minmax::MIN_MAX), - LintId::of(&misc::CMP_NAN), - LintId::of(&misc::FLOAT_CMP), - LintId::of(&misc::MODULO_ONE), - LintId::of(&mut_key::MUTABLE_KEY_TYPE), - LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), - LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), - LintId::of(&ptr::MUT_FROM_REF), - LintId::of(&ranges::REVERSED_EMPTY_RANGES), - LintId::of(®ex::INVALID_REGEX), - 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), - LintId::of(&transmute::WRONG_TRANSMUTE), - LintId::of(&transmuting_null::TRANSMUTING_NULL), - LintId::of(&types::ABSURD_EXTREME_COMPARISONS), - LintId::of(&types::UNIT_CMP), - LintId::of(&undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), - LintId::of(&unicode::INVISIBLE_CHARACTERS), - LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), - LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), - LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), - LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), - LintId::of(&unwrap::PANICKING_UNWRAP), - LintId::of(&vec_resize_to_zero::VEC_RESIZE_TO_ZERO), + LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), + LintId::of(approx_const::APPROX_CONSTANT), + LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), + LintId::of(atomic_ordering::INVALID_ATOMIC_ORDERING), + LintId::of(attrs::DEPRECATED_SEMVER), + LintId::of(attrs::MISMATCHED_TARGET_OS), + LintId::of(attrs::USELESS_ATTRIBUTE), + LintId::of(bit_mask::BAD_BIT_MASK), + LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), + LintId::of(booleans::LOGIC_BUG), + LintId::of(casts::CAST_REF_TO_MUT), + LintId::of(copies::IFS_SAME_COND), + LintId::of(copies::IF_SAME_THEN_ELSE), + LintId::of(derive::DERIVE_HASH_XOR_EQ), + LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(drop_forget_ref::DROP_COPY), + LintId::of(drop_forget_ref::DROP_REF), + LintId::of(drop_forget_ref::FORGET_COPY), + LintId::of(drop_forget_ref::FORGET_REF), + 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), + LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING), + LintId::of(infinite_iter::INFINITE_ITER), + LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), + 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), + LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), + LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), + LintId::of(methods::CLONE_DOUBLE_REF), + LintId::of(methods::ITERATOR_STEP_BY_ZERO), + LintId::of(methods::UNINIT_ASSUMED_INIT), + LintId::of(methods::ZST_OFFSET), + LintId::of(minmax::MIN_MAX), + 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), + LintId::of(ptr::INVALID_NULL_PTR_USAGE), + LintId::of(ptr::MUT_FROM_REF), + LintId::of(ranges::REVERSED_EMPTY_RANGES), + LintId::of(regex::INVALID_REGEX), + 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), + LintId::of(transmute::WRONG_TRANSMUTE), + LintId::of(transmuting_null::TRANSMUTING_NULL), + LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), + LintId::of(unicode::INVISIBLE_CHARACTERS), + LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), + LintId::of(unit_types::UNIT_CMP), + LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS), + LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS), + LintId::of(unused_io_amount::UNUSED_IO_AMOUNT), + LintId::of(unwrap::PANICKING_UNWRAP), + LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO), ]); store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ - LintId::of(&entry::MAP_ENTRY), - LintId::of(&escape::BOXED_LOCAL), - LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS), - LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), - LintId::of(&loops::MANUAL_MEMCPY), - LintId::of(&loops::NEEDLESS_COLLECT), - LintId::of(&methods::EXPECT_FUN_CALL), - LintId::of(&methods::ITER_NTH), - LintId::of(&methods::OR_FUN_CALL), - LintId::of(&methods::SINGLE_CHAR_PATTERN), - LintId::of(&misc::CMP_OWNED), - LintId::of(&mutex_atomic::MUTEX_ATOMIC), - LintId::of(&redundant_clone::REDUNDANT_CLONE), - LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), - LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE), - LintId::of(&types::BOX_VEC), - LintId::of(&types::REDUNDANT_ALLOCATION), - LintId::of(&vec::USELESS_VEC), - LintId::of(&vec_init_then_push::VEC_INIT_THEN_PUSH), + LintId::of(entry::MAP_ENTRY), + LintId::of(escape::BOXED_LOCAL), + LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), + LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), + LintId::of(loops::MANUAL_MEMCPY), + LintId::of(loops::NEEDLESS_COLLECT), + LintId::of(methods::EXPECT_FUN_CALL), + LintId::of(methods::ITER_NTH), + LintId::of(methods::OR_FUN_CALL), + LintId::of(methods::SINGLE_CHAR_PATTERN), + LintId::of(misc::CMP_OWNED), + LintId::of(mutex_atomic::MUTEX_ATOMIC), + LintId::of(redundant_clone::REDUNDANT_CLONE), + LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), + LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), + LintId::of(types::BOX_VEC), + LintId::of(types::REDUNDANT_ALLOCATION), + LintId::of(vec::USELESS_VEC), + LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH), ]); store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![ - LintId::of(&cargo_common_metadata::CARGO_COMMON_METADATA), - LintId::of(&multiple_crate_versions::MULTIPLE_CRATE_VERSIONS), - LintId::of(&wildcard_dependencies::WILDCARD_DEPENDENCIES), + LintId::of(cargo_common_metadata::CARGO_COMMON_METADATA), + LintId::of(multiple_crate_versions::MULTIPLE_CRATE_VERSIONS), + LintId::of(wildcard_dependencies::WILDCARD_DEPENDENCIES), ]); store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ - LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR), - LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY), - LintId::of(&disallowed_method::DISALLOWED_METHOD), - LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), - LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS), - LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS), - LintId::of(&future_not_send::FUTURE_NOT_SEND), - LintId::of(&let_if_seq::USELESS_LET_IF_SEQ), - 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(&needless_borrow::NEEDLESS_BORROW), - LintId::of(&path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE), - LintId::of(&redundant_pub_crate::REDUNDANT_PUB_CRATE), - LintId::of(®ex::TRIVIAL_REGEX), - LintId::of(&strings::STRING_LIT_AS_BYTES), - LintId::of(&transmute::USELESS_TRANSMUTE), - LintId::of(&use_self::USE_SELF), + LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR), + LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY), + LintId::of(disallowed_method::DISALLOWED_METHOD), + LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM), + LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS), + LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS), + LintId::of(future_not_send::FUTURE_NOT_SEND), + LintId::of(let_if_seq::USELESS_LET_IF_SEQ), + 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(needless_borrow::NEEDLESS_BORROW), + LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE), + LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE), + LintId::of(regex::TRIVIAL_REGEX), + LintId::of(strings::STRING_LIT_AS_BYTES), + LintId::of(transmute::USELESS_TRANSMUTE), + LintId::of(use_self::USE_SELF), ]); } @@ -2129,6 +2143,15 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::identity_conversion", "clippy::useless_conversion"); ls.register_renamed("clippy::zero_width_space", "clippy::invisible_characters"); ls.register_renamed("clippy::single_char_push_str", "clippy::single_char_add_str"); + + // uplifted lints + ls.register_renamed("clippy::invalid_ref", "invalid_value"); + ls.register_renamed("clippy::into_iter_on_array", "array_into_iter"); + 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::unknown_clippy_lints", "unknown_lints"); } // only exists to let the dogfood integration test works. diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 3ac6e6cbbe..116ad07283 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -1,4 +1,5 @@ -use crate::utils::{in_macro, span_lint, trait_ref_of_method}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{in_macro, trait_ref_of_method}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::intravisit::{ walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty, @@ -80,7 +81,7 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]); impl<'tcx> LateLintPass<'tcx> for Lifetimes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Fn(ref sig, ref generics, id) = item.kind { - check_fn_inner(cx, &sig.decl, Some(id), generics, item.span, true); + check_fn_inner(cx, sig.decl, Some(id), generics, item.span, true); } } @@ -89,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { let report_extra_lifetimes = trait_ref_of_method(cx, item.hir_id()).is_none(); check_fn_inner( cx, - &sig.decl, + sig.decl, Some(id), &item.generics, item.span, @@ -104,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { TraitFn::Required(_) => None, TraitFn::Provided(id) => Some(id), }; - check_fn_inner(cx, &sig.decl, body, &item.generics, item.span, true); + check_fn_inner(cx, sig.decl, body, &item.generics, item.span, true); } } } @@ -148,7 +149,7 @@ fn check_fn_inner<'tcx>( .last() .expect("a path must have at least one segment") .args; - if let Some(ref params) = *params { + if let Some(params) = *params { let lifetimes = params.args.iter().filter_map(|arg| match arg { GenericArg::Lifetime(lt) => Some(lt), _ => None, @@ -162,7 +163,7 @@ fn check_fn_inner<'tcx>( } } } - if could_use_elision(cx, decl, body, &generics.params) { + if could_use_elision(cx, decl, body, generics.params) { span_lint( cx, NEEDLESS_LIFETIMES, @@ -200,7 +201,7 @@ fn could_use_elision<'tcx>( input_visitor.visit_ty(arg); } // extract lifetimes in output type - if let Return(ref ty) = func.output { + if let Return(ty) = func.output { output_visitor.visit_ty(ty); } for lt in named_generics { @@ -415,12 +416,12 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl // a predicate like F: Trait or F: for<'a> Trait<'a> let mut visitor = RefVisitor::new(cx); // walk the type F, it may not contain LT refs - walk_ty(&mut visitor, &pred.bounded_ty); + walk_ty(&mut visitor, pred.bounded_ty); if !visitor.all_lts().is_empty() { return true; } // if the bounds define new lifetimes, they are fine to occur - let allowed_lts = allowed_lts_from(&pred.bound_generic_params); + let allowed_lts = allowed_lts_from(pred.bound_generic_params); // now walk the bounds for bound in pred.bounds.iter() { walk_param_bound(&mut visitor, bound); @@ -432,8 +433,8 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl }, WherePredicate::EqPredicate(ref pred) => { let mut visitor = RefVisitor::new(cx); - walk_ty(&mut visitor, &pred.lhs_ty); - walk_ty(&mut visitor, &pred.rhs_ty); + walk_ty(&mut visitor, pred.lhs_ty); + walk_ty(&mut visitor, pred.rhs_ty); if !visitor.lts.is_empty() { return true; } diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index 87a957a9bd..e93b2e36b8 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -1,10 +1,11 @@ //! Lints concerned with the grouping of digits with underscores in integral or //! floating-point literal expressions. -use crate::utils::{ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use clippy_utils::{ in_macro, numeric_literal::{NumericLiteral, Radix}, - snippet_opt, span_lint_and_sugg, }; use if_chain::if_chain; use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind}; @@ -12,6 +13,7 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use std::iter; declare_clippy_lint! { /// **What it does:** Warns if a long integral or floating-point constant does @@ -247,7 +249,7 @@ impl LiteralDigitGrouping { fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) { if_chain! { if let Some(src) = snippet_opt(cx, lit.span); - if let Some(mut num_lit) = NumericLiteral::from_lit(&src, &lit); + if let Some(mut num_lit) = NumericLiteral::from_lit(&src, lit); then { if !Self::check_for_mistyped_suffix(cx, lit.span, &mut num_lit) { return; @@ -348,7 +350,7 @@ impl LiteralDigitGrouping { let group_sizes: Vec<usize> = num_lit.integer.split('_').map(str::len).collect(); if UUID_GROUP_LENS.len() == group_sizes.len() { - UUID_GROUP_LENS.iter().zip(&group_sizes).all(|(&a, &b)| a == b) + iter::zip(&UUID_GROUP_LENS, &group_sizes).all(|(&a, &b)| a == b) } else { false } @@ -437,7 +439,7 @@ impl DecimalLiteralRepresentation { if_chain! { if let LitKind::Int(val, _) = lit.kind; if let Some(src) = snippet_opt(cx, lit.span); - if let Some(num_lit) = NumericLiteral::from_lit(&src, &lit); + if let Some(num_lit) = NumericLiteral::from_lit(&src, lit); if num_lit.radix == Radix::Decimal; if val >= u128::from(self.threshold); then { diff --git a/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs b/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs index 43e85538f2..dda09fecdf 100644 --- a/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs @@ -1,5 +1,6 @@ use super::EMPTY_LOOP; -use crate::utils::{is_in_panic_handler, is_no_std_crate, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{is_in_panic_handler, is_no_std_crate}; use rustc_hir::{Block, Expr}; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs index 8d98b940c6..98e60f7ed8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs @@ -1,7 +1,9 @@ use super::{ get_span_of_entire_for_loop, make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT_COUNTER_LOOP, }; -use crate::utils::{get_enclosing_block, is_integer_const, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{get_enclosing_block, is_integer_const}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr}; @@ -24,7 +26,7 @@ pub(super) fn check<'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. - if let Some(block) = get_enclosing_block(&cx, expr.hir_id) { + if let Some(block) = get_enclosing_block(cx, expr.hir_id) { for id in increment_visitor.into_results() { let mut initialize_visitor = InitializeVisitor::new(cx, expr, id); walk_block(&mut initialize_visitor, block); diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs index 1d778205a2..c7a28f42ea 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs @@ -1,23 +1,25 @@ use super::EXPLICIT_INTO_ITER_LOOP; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{match_trait_method, paths}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::TyS; -pub(super) fn check(cx: &LateContext<'_>, args: &'hir [Expr<'hir>], arg: &Expr<'_>) { - let receiver_ty = cx.typeck_results().expr_ty(&args[0]); - let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(&args[0]); - if !TyS::same_type(receiver_ty, receiver_ty_adjusted) { +pub(super) fn check(cx: &LateContext<'_>, self_arg: &'hir Expr<'hir>, call_expr: &Expr<'_>) { + let self_ty = cx.typeck_results().expr_ty(self_arg); + let self_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg); + if !(TyS::same_type(self_ty, self_ty_adjusted) && match_trait_method(cx, call_expr, &paths::INTO_ITERATOR)) { return; } let mut applicability = Applicability::MachineApplicable; - let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); + let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); span_lint_and_sugg( cx, EXPLICIT_INTO_ITER_LOOP, - arg.span, + call_expr.span, "it is more concise to loop over containers instead of using explicit \ iteration methods", "to write this more concisely, try", diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index 9683e59a39..ce02ad013b 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -1,19 +1,20 @@ use super::EXPLICIT_ITER_LOOP; -use crate::utils::{match_trait_method, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::{is_type_diagnostic_item, match_type}; +use clippy_utils::{match_trait_method, paths}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, TyS}; use rustc_span::sym; -use crate::utils::{is_type_diagnostic_item, match_type, paths}; - -pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) { +pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, method_name: &str) { let should_lint = match method_name { - "iter" | "iter_mut" => is_ref_iterable_type(cx, &args[0]), + "iter" | "iter_mut" => is_ref_iterable_type(cx, self_arg), "into_iter" if match_trait_method(cx, arg, &paths::INTO_ITERATOR) => { - let receiver_ty = cx.typeck_results().expr_ty(&args[0]); - let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(&args[0]); + let receiver_ty = cx.typeck_results().expr_ty(self_arg); + let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg); let ref_receiver_ty = cx.tcx.mk_ref( cx.tcx.lifetimes.re_erased, ty::TypeAndMut { @@ -31,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], arg: &Expr<'_>, met } let mut applicability = Applicability::MachineApplicable; - let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability); + let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); let muta = if method_name == "iter_mut" { "mut " } else { "" }; span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs index 6ee9b95a3b..666b8c5872 100644 --- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs +++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs @@ -1,6 +1,9 @@ use super::FOR_KV_MAP; -use crate::utils::visitors::LocalUsedVisitor; -use crate::utils::{is_type_diagnostic_item, match_type, multispan_sugg, paths, snippet, span_lint_and_then, sugg}; +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; +use clippy_utils::source::snippet; +use clippy_utils::ty::{is_type_diagnostic_item, match_type}; +use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::{paths, sugg}; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; @@ -16,7 +19,7 @@ pub(super) fn check<'tcx>( ) { let pat_span = pat.span; - if let PatKind::Tuple(ref pat, _) = pat.kind { + if let PatKind::Tuple(pat, _) = pat.kind { if pat.len() == 2 { let arg_span = arg.span; let (new_pat_span, kind, ty, mutbl) = match *cx.typeck_results().expr_ty(arg).kind() { @@ -32,7 +35,7 @@ pub(super) fn check<'tcx>( Mutability::Mut => "_mut", }; let arg = match arg.kind { - ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) => &**expr, + ExprKind::AddrOf(BorrowKind::Ref, _, expr) => expr, _ => arg, }; diff --git a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs b/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs index db22d90a30..d49b0517dc 100644 --- a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs +++ b/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs @@ -1,5 +1,7 @@ use super::FOR_LOOPS_OVER_FALLIBLES; -use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir::{Expr, Pat}; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs index cf78bbc49a..9148fbfd49 100644 --- a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs @@ -1,10 +1,12 @@ use super::ITER_NEXT_LOOP; -use crate::utils::{match_trait_method, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_trait_method; use rustc_hir::Expr; use rustc_lint::LateContext; +use rustc_span::sym; pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, expr: &Expr<'_>) -> bool { - if match_trait_method(cx, arg, &paths::ITERATOR) { + if is_trait_method(cx, arg, sym::Iterator) { span_lint( cx, ITER_NEXT_LOOP, diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs index 3d3ae6f315..64ff7574f8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs @@ -1,10 +1,13 @@ use super::utils::make_iterator_snippet; use super::MANUAL_FLATTEN; -use crate::utils::{is_ok_ctor, is_some_ctor, path_to_local_id, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{is_lang_ctor, path_to_local_id}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, StmtKind}; +use rustc_hir::LangItem::{OptionSome, ResultOk}; +use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, StmtKind}; use rustc_lint::LateContext; +use rustc_middle::ty; use rustc_span::source_map::Span; /// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the @@ -16,7 +19,7 @@ pub(super) fn check<'tcx>( body: &'tcx Expr<'_>, span: Span, ) { - if let ExprKind::Block(ref block, _) = body.kind { + if let ExprKind::Block(block, _) = body.kind { // Ensure the `if let` statement is the only expression or statement in the for-loop let inner_expr = if block.stmts.len() == 1 && block.expr.is_none() { let match_stmt = &block.stmts[0]; @@ -34,25 +37,31 @@ pub(super) fn check<'tcx>( if_chain! { if let Some(inner_expr) = inner_expr; if let ExprKind::Match( - ref match_expr, ref match_arms, MatchSource::IfLetDesugar{ contains_else_clause: false } + match_expr, match_arms, MatchSource::IfLetDesugar{ contains_else_clause: false } ) = inner_expr.kind; // Ensure match_expr in `if let` statement is the same as the pat from the for-loop if let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind; if path_to_local_id(match_expr, pat_hir_id); // Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result` - if let PatKind::TupleStruct(QPath::Resolved(None, path), _, _) = match_arms[0].pat.kind; - let some_ctor = is_some_ctor(cx, path.res); - let ok_ctor = is_ok_ctor(cx, path.res); + if let PatKind::TupleStruct(ref qpath, _, _) = match_arms[0].pat.kind; + let some_ctor = is_lang_ctor(cx, qpath, OptionSome); + let ok_ctor = is_lang_ctor(cx, qpath, ResultOk); if some_ctor || ok_ctor; - let if_let_type = if some_ctor { "Some" } else { "Ok" }; - then { + let if_let_type = if some_ctor { "Some" } else { "Ok" }; // Prepare the error message let msg = format!("unnecessary `if let` since only the `{}` variant of the iterator element is used", if_let_type); // Prepare the help message let mut applicability = Applicability::MaybeIncorrect; let arg_snippet = make_iterator_snippet(cx, arg, &mut applicability); + let copied = match cx.typeck_results().expr_ty(match_expr).kind() { + ty::Ref(_, inner, _) => match inner.kind() { + ty::Ref(..) => ".copied()", + _ => "" + } + _ => "" + }; span_lint_and_then( cx, @@ -60,7 +69,7 @@ pub(super) fn check<'tcx>( span, &msg, |diag| { - let sugg = format!("{}.flatten()", arg_snippet); + let sugg = format!("{}{}.flatten()", arg_snippet, copied); diag.span_suggestion( arg.span, "try", diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index 11660a8fe0..c91fe88757 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -1,8 +1,9 @@ use super::{get_span_of_entire_for_loop, IncrementVisitor, InitializeVisitor, MANUAL_MEMCPY}; -use crate::utils::sugg::Sugg; -use crate::utils::{ - get_enclosing_block, higher, is_type_diagnostic_item, path_to_local, snippet, span_lint_and_sugg, sugg, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg}; use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; @@ -60,10 +61,10 @@ pub(super) fn check<'tcx>( if_chain! { if let ExprKind::Index(base_left, idx_left) = lhs.kind; if let ExprKind::Index(base_right, idx_right) = rhs.kind; - if is_slice_like(cx, cx.typeck_results().expr_ty(base_left)) - && is_slice_like(cx, cx.typeck_results().expr_ty(base_right)); - if let Some((start_left, offset_left)) = get_details_from_idx(cx, &idx_left, &starts); - if let Some((start_right, offset_right)) = get_details_from_idx(cx, &idx_right, &starts); + if is_slice_like(cx, cx.typeck_results().expr_ty(base_left)); + if is_slice_like(cx, cx.typeck_results().expr_ty(base_right)); + if let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts); + if let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts); // Source and destination must be different if path_to_local(base_left) != path_to_local(base_right); @@ -167,8 +168,8 @@ fn build_manual_memcpy_suggestion<'tcx>( }, }; - let (dst_offset, dst_limit) = print_offset_and_limit(&dst); - let (src_offset, src_limit) = print_offset_and_limit(&src); + let (dst_offset, dst_limit) = print_offset_and_limit(dst); + let (src_offset, src_limit) = print_offset_and_limit(src); let dst_base_str = snippet(cx, dst.base.span, "???"); let src_base_str = snippet(cx, src.base.span, "???"); @@ -437,7 +438,7 @@ fn get_loop_counters<'a, 'tcx>( // For each candidate, check the parent block to see if // it's initialized to zero at the start of the loop. - get_enclosing_block(&cx, expr.hir_id).and_then(|block| { + get_enclosing_block(cx, expr.hir_id).and_then(|block| { increment_visitor .into_results() .filter_map(move |var_id| { diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index 2a372c6307..a4bc3e6bd1 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -18,7 +18,7 @@ mod while_immutable_condition; mod while_let_loop; mod while_let_on_iterator; -use crate::utils::higher; +use clippy_utils::higher; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -562,7 +562,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { // check for `loop { if let {} else break }` that could be `while let` // (also matches an explicit "match" instead of "if let") // (even if the "match" or "if let" is used for declaration) - if let ExprKind::Loop(ref block, _, LoopSource::Loop, _) = expr.kind { + if let ExprKind::Loop(block, _, LoopSource::Loop, _) = expr.kind { // also check for empty `loop {}` statements, skipping those in #[panic_handler] empty_loop::check(cx, expr, block); while_let_loop::check(cx, expr, block); @@ -570,7 +570,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { while_let_on_iterator::check(cx, expr); - if let Some((cond, body)) = higher::while_loop(&expr) { + if let Some((cond, body)) = higher::while_loop(expr) { while_immutable_condition::check(cx, cond, body); } @@ -602,22 +602,19 @@ fn check_for_loop<'tcx>( fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) { let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used - if let ExprKind::MethodCall(ref method, _, ref args, _) = arg.kind { - // just the receiver, no arguments - if args.len() == 1 { - let method_name = &*method.ident.as_str(); - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - match method_name { - "iter" | "iter_mut" => explicit_iter_loop::check(cx, args, arg, method_name), - "into_iter" => { - explicit_iter_loop::check(cx, args, arg, method_name); - explicit_into_iter_loop::check(cx, args, arg); - }, - "next" => { - next_loop_linted = iter_next_loop::check(cx, arg, expr); - }, - _ => {}, - } + if let ExprKind::MethodCall(method, _, [self_arg], _) = arg.kind { + let method_name = &*method.ident.as_str(); + // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x + match method_name { + "iter" | "iter_mut" => explicit_iter_loop::check(cx, self_arg, arg, method_name), + "into_iter" => { + explicit_iter_loop::check(cx, self_arg, arg, method_name); + explicit_into_iter_loop::check(cx, self_arg, arg); + }, + "next" => { + next_loop_linted = iter_next_loop::check(cx, arg, expr); + }, + _ => {}, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index cb56512db6..1425d50f56 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -1,11 +1,11 @@ use super::MUT_RANGE_BOUND; -use crate::utils::{higher, path_to_local, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{higher, path_to_local}; use if_chain::if_chain; use rustc_hir::{BindingAnnotation, Expr, HirId, Node, PatKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; -use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty; +use rustc_middle::{mir::FakeReadCause, ty}; use rustc_span::source_map::Span; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; @@ -108,7 +108,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { } } - fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _:HirId) { } + fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {} } impl MutatePairDelegate<'_, '_> { diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs index 92560c8062..4d73aef76e 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs @@ -1,17 +1,17 @@ use super::NEEDLESS_COLLECT; -use crate::utils::sugg::Sugg; -use crate::utils::{ - is_type_diagnostic_item, match_trait_method, match_type, path_to_local_id, paths, snippet, span_lint_and_sugg, - span_lint_and_then, -}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::snippet; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::{is_type_diagnostic_item, match_type}; +use clippy_utils::{is_trait_method, path_to_local_id, paths}; 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, HirId, Local, Pat, PatKind, QPath, StmtKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; -use rustc_span::source_map::Span; use rustc_span::symbol::{sym, Ident}; +use rustc_span::{MultiSpan, Span}; const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; @@ -21,88 +21,60 @@ pub(super) fn check<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { } fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { if_chain! { - if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind; - if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind; - if chain_method.ident.name == sym!(collect) && match_trait_method(cx, &args[0], &paths::ITERATOR); - if let Some(ref generic_args) = chain_method.args; + 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); - then { - let ty = cx.typeck_results().node_type(ty.hir_id); - if is_type_diagnostic_item(cx, ty, sym::vec_type) || - is_type_diagnostic_item(cx, ty, sym::vecdeque_type) || - match_type(cx, ty, &paths::BTREEMAP) || - is_type_diagnostic_item(cx, ty, sym::hashmap_type) { - if method.ident.name == sym!(len) { - let span = shorten_needless_collect_span(expr); - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - span, - NEEDLESS_COLLECT_MSG, - "replace with", - "count()".to_string(), - Applicability::MachineApplicable, - ); - } - if method.ident.name == sym!(is_empty) { - let span = shorten_needless_collect_span(expr); - span_lint_and_sugg( - cx, - NEEDLESS_COLLECT, - span, - NEEDLESS_COLLECT_MSG, - "replace with", - "next().is_none()".to_string(), - Applicability::MachineApplicable, - ); - } - if method.ident.name == sym!(contains) { - let contains_arg = snippet(cx, args[1].span, "??"); - let span = shorten_needless_collect_span(expr); - span_lint_and_then( - cx, - NEEDLESS_COLLECT, - span, - NEEDLESS_COLLECT_MSG, - |diag| { - let (arg, pred) = contains_arg - .strip_prefix('&') - .map_or(("&x", &*contains_arg), |s| ("x", s)); - diag.span_suggestion( - span, - "replace with", - format!( - "any(|{}| x == {})", - arg, pred - ), - Applicability::MachineApplicable, - ); - } - ); - } + let ty = cx.typeck_results().node_type(ty.hir_id); + if is_type_diagnostic_item(cx, ty, sym::vec_type) + || is_type_diagnostic_item(cx, ty, sym::vecdeque_type) + || match_type(cx, ty, &paths::BTREEMAP) + || is_type_diagnostic_item(cx, ty, sym::hashmap_type); + if let Some(sugg) = match &*method.ident.name.as_str() { + "len" => Some("count()".to_string()), + "is_empty" => Some("next().is_none()".to_string()), + "contains" => { + let contains_arg = snippet(cx, args[1].span, "??"); + let (arg, pred) = contains_arg + .strip_prefix('&') + .map_or(("&x", &*contains_arg), |s| ("x", s)); + Some(format!("any(|{}| x == {})", arg, pred)) } + _ => None, + }; + then { + span_lint_and_sugg( + cx, + NEEDLESS_COLLECT, + method0_span.with_hi(expr.span.hi()), + NEEDLESS_COLLECT_MSG, + "replace with", + sugg, + Applicability::MachineApplicable, + ); } } } fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { - if let ExprKind::Block(ref block, _) = expr.kind { - for ref stmt in block.stmts { + 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(ref init_expr), .. } + init: Some(init_expr), .. } ) = stmt.kind; - if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind; - if method_name.ident.name == sym!(collect) && match_trait_method(cx, &init_expr, &paths::ITERATOR); - if let Some(ref generic_args) = method_name.args; + 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(generic_args) = method_name.args; if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); if let ty = cx.typeck_results().node_type(ty.hir_id); if is_type_diagnostic_item(cx, ty, sym::vec_type) || is_type_diagnostic_item(cx, ty, sym::vecdeque_type) || match_type(cx, ty, &paths::LINKED_LIST); if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident); - if iter_calls.len() == 1; + if let [iter_call] = &*iter_calls; then { let mut used_count_visitor = UsedCountVisitor { cx, @@ -115,11 +87,12 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo } // Suggest replacing iter_call with iter_replacement, and removing stmt - let iter_call = &iter_calls[0]; + let mut span = MultiSpan::from_span(collect_span); + span.push_span_label(iter_call.span, "the iterator could be used here instead".into()); span_lint_and_then( cx, super::NEEDLESS_COLLECT, - stmt.span.until(iter_call.span), + span, NEEDLESS_COLLECT_MSG, |diag| { let iter_replacement = format!("{}{}", Sugg::hir(cx, iter_source, ".."), iter_call.get_iter_method(cx)); @@ -130,7 +103,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo (iter_call.span, iter_replacement) ], Applicability::MachineApplicable,// MaybeIncorrect, - ).emit(); + ); }, ); } @@ -192,8 +165,8 @@ 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, _, ref args, _) = &expr.kind; - if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. }) = args.get(0); + 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 { @@ -220,7 +193,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { } // Check if the collection is used for anything else if_chain! { - if let Expr { kind: ExprKind::Path(QPath::Resolved(_, ref path)), .. } = expr; + if let Expr { kind: ExprKind::Path(QPath::Resolved(_, path)), .. } = expr; if let &[name] = &path.segments; if name.ident == self.target; then { @@ -270,14 +243,3 @@ fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) visitor.visit_block(block); if visitor.seen_other { None } else { Some(visitor.uses) } } - -fn shorten_needless_collect_span(expr: &Expr<'_>) -> Span { - if_chain! { - if let ExprKind::MethodCall(.., args, _) = &expr.kind; - if let ExprKind::MethodCall(_, span, ..) = &args[0].kind; - then { - return expr.span.with_lo(span.lo()); - } - } - unreachable!(); -} diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 5f02e4b9d8..3065bcc3e6 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -1,8 +1,10 @@ use super::NEEDLESS_RANGE_LOOP; -use crate::utils::visitors::LocalUsedVisitor; -use crate::utils::{ - contains_name, has_iter_method, higher, is_integer_const, match_trait_method, multispan_sugg, path_to_local_id, - paths, snippet, span_lint_and_then, sugg, SpanlessEq, +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; +use clippy_utils::source::snippet; +use clippy_utils::ty::has_iter_method; +use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::{ + contains_name, higher, is_integer_const, match_trait_method, path_to_local_id, paths, sugg, SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast; @@ -15,7 +17,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::middle::region; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{sym, Symbol}; -use std::iter::Iterator; +use std::iter::{self, Iterator}; use std::mem; /// Checks for looping over a range and then indexing a sequence with it. @@ -94,7 +96,7 @@ pub(super) fn check<'tcx>( let take = if let Some(end) = *end { let mut take_expr = end; - if let ExprKind::Binary(ref op, ref left, ref right) = end.kind { + if let ExprKind::Binary(ref op, left, right) = end.kind { if let BinOpKind::Add = op.node { let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left); let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right); @@ -188,10 +190,10 @@ pub(super) fn check<'tcx>( fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool { if_chain! { - if let ExprKind::MethodCall(ref method, _, ref len_args, _) = expr.kind; + if let ExprKind::MethodCall(method, _, len_args, _) = expr.kind; if len_args.len() == 1; if method.ident.name == sym!(len); - if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].kind; + if let ExprKind::Path(QPath::Resolved(_, path)) = len_args[0].kind; if path.segments.len() == 1; if path.segments[0].ident.name == var; then { @@ -252,51 +254,49 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { if_chain! { // the indexed container is referenced by a name if let ExprKind::Path(ref seqpath) = seqexpr.kind; - if let QPath::Resolved(None, ref seqvar) = *seqpath; + if let QPath::Resolved(None, seqvar) = *seqpath; if seqvar.segments.len() == 1; + let index_used_directly = path_to_local_id(idx, self.var); + let indexed_indirectly = { + let mut used_visitor = LocalUsedVisitor::new(self.cx, self.var); + walk_expr(&mut used_visitor, idx); + used_visitor.used + }; + if indexed_indirectly || index_used_directly; then { - let index_used_directly = path_to_local_id(idx, self.var); - let indexed_indirectly = { - let mut used_visitor = LocalUsedVisitor::new(self.cx, self.var); - walk_expr(&mut used_visitor, idx); - used_visitor.used - }; - - if indexed_indirectly || index_used_directly { - if self.prefer_mutable { - self.indexed_mut.insert(seqvar.segments[0].ident.name); + if self.prefer_mutable { + self.indexed_mut.insert(seqvar.segments[0].ident.name); + } + let res = self.cx.qpath_res(seqpath, seqexpr.hir_id); + match res { + Res::Local(hir_id) => { + let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); + let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id); + let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); + if indexed_indirectly { + self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent)); + } + if index_used_directly { + self.indexed_directly.insert( + seqvar.segments[0].ident.name, + (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)), + ); + } + return false; // no need to walk further *on the variable* } - let res = self.cx.qpath_res(seqpath, seqexpr.hir_id); - match res { - Res::Local(hir_id) => { - let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); - let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id); - let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); - if indexed_indirectly { - self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent)); - } - if index_used_directly { - self.indexed_directly.insert( - seqvar.segments[0].ident.name, - (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)), - ); - } - return false; // no need to walk further *on the variable* + Res::Def(DefKind::Static | DefKind::Const, ..) => { + if indexed_indirectly { + self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); } - Res::Def(DefKind::Static | DefKind::Const, ..) => { - if indexed_indirectly { - self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); - } - if index_used_directly { - self.indexed_directly.insert( - seqvar.segments[0].ident.name, - (None, self.cx.typeck_results().node_type(seqexpr.hir_id)), - ); - } - return false; // no need to walk further *on the variable* + if index_used_directly { + self.indexed_directly.insert( + seqvar.segments[0].ident.name, + (None, self.cx.typeck_results().node_type(seqexpr.hir_id)), + ); } - _ => (), + return false; // no need to walk further *on the variable* } + _ => (), } } } @@ -310,7 +310,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { if_chain! { // a range index op - if let ExprKind::MethodCall(ref meth, _, ref args, _) = expr.kind; + if let ExprKind::MethodCall(meth, _, args, _) = expr.kind; if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX)) || (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); if !self.check(&args[1], &args[0], expr); @@ -319,7 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { if_chain! { // an index op - if let ExprKind::Index(ref seqexpr, ref idx) = expr.kind; + if let ExprKind::Index(seqexpr, idx) = expr.kind; if !self.check(idx, seqexpr, expr); then { return } } @@ -340,19 +340,19 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { let old = self.prefer_mutable; match expr.kind { - ExprKind::AssignOp(_, ref lhs, ref rhs) | ExprKind::Assign(ref lhs, ref rhs, _) => { + ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => { self.prefer_mutable = true; self.visit_expr(lhs); self.prefer_mutable = false; self.visit_expr(rhs); }, - ExprKind::AddrOf(BorrowKind::Ref, mutbl, ref expr) => { + ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => { if mutbl == Mutability::Mut { self.prefer_mutable = true; } self.visit_expr(expr); }, - ExprKind::Call(ref f, args) => { + ExprKind::Call(f, args) => { self.visit_expr(f); for expr in args { let ty = self.cx.typeck_results().expr_ty_adjusted(expr); @@ -367,7 +367,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { }, ExprKind::MethodCall(_, _, args, _) => { let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); - for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) { + for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) { self.prefer_mutable = false; if let ty::Ref(_, _, mutbl) = *ty.kind() { if mutbl == Mutability::Mut { diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 45e1001d75..e97b7c9417 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -1,11 +1,11 @@ use super::NEVER_LOOP; -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, Stmt, StmtKind}; use rustc_lint::LateContext; use std::iter::{once, Iterator}; pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Loop(ref block, _, _, _) = expr.kind { + if let ExprKind::Loop(block, _, _, _) = expr.kind { match never_loop_block(block, expr.hir_id) { NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"), NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (), @@ -76,36 +76,36 @@ fn never_loop_expr_seq<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_lo fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> { match stmt.kind { - StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e), - StmtKind::Local(ref local) => local.init.as_deref(), - _ => None, + StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some(e), + StmtKind::Local(local) => local.init.as_deref(), + StmtKind::Item(..) => None, } } fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { match expr.kind { - ExprKind::Box(ref e) - | ExprKind::Unary(_, ref e) - | ExprKind::Cast(ref e, _) - | ExprKind::Type(ref e, _) - | ExprKind::Field(ref e, _) - | ExprKind::AddrOf(_, _, ref e) - | ExprKind::Struct(_, _, Some(ref e)) - | ExprKind::Repeat(ref e, _) - | ExprKind::DropTemps(ref e) => never_loop_expr(e, main_loop_id), - ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es, _) | ExprKind::Tup(ref es) => { + ExprKind::Box(e) + | ExprKind::Unary(_, e) + | ExprKind::Cast(e, _) + | ExprKind::Type(e, _) + | ExprKind::Field(e, _) + | ExprKind::AddrOf(_, _, e) + | ExprKind::Struct(_, _, Some(e)) + | ExprKind::Repeat(e, _) + | ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id), + ExprKind::Array(es) | ExprKind::MethodCall(_, _, es, _) | ExprKind::Tup(es) => { never_loop_expr_all(&mut es.iter(), main_loop_id) }, - ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id), - ExprKind::Binary(_, ref e1, ref e2) - | ExprKind::Assign(ref e1, ref e2, _) - | ExprKind::AssignOp(_, ref e1, ref e2) - | ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id), - ExprKind::Loop(ref b, _, _, _) => { + ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), main_loop_id), + ExprKind::Binary(_, e1, e2) + | ExprKind::Assign(e1, e2, _) + | ExprKind::AssignOp(_, e1, e2) + | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), main_loop_id), + ExprKind::Loop(b, _, _, _) => { // Break can come from the inner loop so remove them. absorb_break(&never_loop_block(b, main_loop_id)) }, - ExprKind::If(ref e, ref e2, ref e3) => { + ExprKind::If(e, e2, ref e3) => { let e1 = never_loop_expr(e, main_loop_id); let e2 = never_loop_expr(e2, main_loop_id); let e3 = e3 @@ -113,7 +113,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { .map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id)); combine_seq(e1, combine_branches(e2, e3)) }, - ExprKind::Match(ref e, ref arms, _) => { + ExprKind::Match(e, arms, _) => { let e = never_loop_expr(e, main_loop_id); if arms.is_empty() { e @@ -122,7 +122,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { combine_seq(e, arms) } }, - ExprKind::Block(ref b, _) => never_loop_block(b, main_loop_id), + ExprKind::Block(b, _) => never_loop_block(b, main_loop_id), ExprKind::Continue(d) => { let id = d .target_id @@ -136,18 +136,18 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { ExprKind::Break(_, ref e) | ExprKind::Ret(ref e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| { combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak) }), - ExprKind::InlineAsm(ref asm) => asm + ExprKind::InlineAsm(asm) => asm .operands .iter() .map(|(o, _)| match o { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } - | InlineAsmOperand::Const { expr } | InlineAsmOperand::Sym { expr } => never_loop_expr(expr, main_loop_id), InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id), InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id) }, + InlineAsmOperand::Const { .. } => NeverLoopResult::Otherwise, }) .fold(NeverLoopResult::Otherwise, combine_both), ExprKind::Struct(_, _, None) diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index f3585830e4..cb2c83e902 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -1,9 +1,13 @@ use super::SAME_ITEM_PUSH; -use crate::utils::{implements_trait, is_type_diagnostic_item, snippet_with_macro_callsite, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::path_to_local; +use clippy_utils::source::snippet_with_macro_callsite; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use if_chain::if_chain; +use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Node, Pat, PatKind, Stmt, StmtKind}; +use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; use rustc_span::symbol::sym; @@ -39,59 +43,55 @@ pub(super) fn check<'tcx>( } // Determine whether it is safe to lint the body - let mut same_item_push_visitor = SameItemPushVisitor { - should_lint: true, - vec_push: None, - cx, - }; + let mut same_item_push_visitor = SameItemPushVisitor::new(cx); walk_expr(&mut same_item_push_visitor, body); - if same_item_push_visitor.should_lint { - if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push { - let vec_ty = cx.typeck_results().expr_ty(vec); - let ty = vec_ty.walk().nth(1).unwrap().expect_ty(); - if cx - .tcx - .lang_items() - .clone_trait() - .map_or(false, |id| implements_trait(cx, ty, id, &[])) - { - // Make sure that the push does not involve possibly mutating values - match pushed_item.kind { - ExprKind::Path(ref qpath) => { - match cx.qpath_res(qpath, pushed_item.hir_id) { - // immutable bindings that are initialized with literal or constant - Res::Local(hir_id) => { - if_chain! { - let node = cx.tcx.hir().get(hir_id); - if let Node::Binding(pat) = node; - if let PatKind::Binding(bind_ann, ..) = pat.kind; - if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable); - let parent_node = cx.tcx.hir().get_parent_node(hir_id); - if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node); - if let Some(init) = parent_let_expr.init; - then { - match init.kind { - // immutable bindings that are initialized with literal - ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item), - // immutable bindings that are initialized with constant - ExprKind::Path(ref path) => { - if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) { - emit_lint(cx, vec, pushed_item); - } + if_chain! { + if same_item_push_visitor.should_lint(); + if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push; + let vec_ty = cx.typeck_results().expr_ty(vec); + let ty = vec_ty.walk().nth(1).unwrap().expect_ty(); + if cx + .tcx + .lang_items() + .clone_trait() + .map_or(false, |id| implements_trait(cx, ty, id, &[])); + then { + // Make sure that the push does not involve possibly mutating values + match pushed_item.kind { + ExprKind::Path(ref qpath) => { + match cx.qpath_res(qpath, pushed_item.hir_id) { + // immutable bindings that are initialized with literal or constant + Res::Local(hir_id) => { + let node = cx.tcx.hir().get(hir_id); + if_chain! { + if let Node::Binding(pat) = node; + if let PatKind::Binding(bind_ann, ..) = pat.kind; + if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable); + let parent_node = cx.tcx.hir().get_parent_node(hir_id); + if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node); + if let Some(init) = parent_let_expr.init; + then { + match init.kind { + // immutable bindings that are initialized with literal + ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item), + // immutable bindings that are initialized with constant + ExprKind::Path(ref path) => { + if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) { + emit_lint(cx, vec, pushed_item); } - _ => {}, } + _ => {}, } } - }, - // constant - Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item), - _ => {}, - } - }, - ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item), - _ => {}, - } + } + }, + // constant + Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item), + _ => {}, + } + }, + ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item), + _ => {}, } } } @@ -99,10 +99,38 @@ pub(super) fn check<'tcx>( // Scans the body of the for loop and determines whether lint should be given struct SameItemPushVisitor<'a, 'tcx> { - should_lint: bool, + non_deterministic_expr: bool, + multiple_pushes: bool, // this field holds the last vec push operation visited, which should be the only push seen vec_push: Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>, cx: &'a LateContext<'tcx>, + used_locals: FxHashSet<HirId>, +} + +impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> { + fn new(cx: &'a LateContext<'tcx>) -> Self { + Self { + non_deterministic_expr: false, + multiple_pushes: false, + vec_push: None, + cx, + used_locals: FxHashSet::default(), + } + } + + fn should_lint(&self) -> bool { + if_chain! { + if !self.non_deterministic_expr; + if !self.multiple_pushes; + if let Some((vec, _)) = self.vec_push; + if let Some(hir_id) = path_to_local(vec); + then { + !self.used_locals.contains(&hir_id) + } else { + false + } + } + } } impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> { @@ -111,9 +139,14 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { match &expr.kind { // Non-determinism may occur ... don't give a lint - ExprKind::Loop(..) | ExprKind::Match(..) => self.should_lint = false, + ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::If(..) => self.non_deterministic_expr = true, ExprKind::Block(block, _) => self.visit_block(block), - _ => {}, + _ => { + if let Some(hir_id) = path_to_local(expr) { + self.used_locals.insert(hir_id); + } + walk_expr(self, expr); + }, } } @@ -128,7 +161,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> { if vec_push_option.is_none() { // Current statement is not a push so visit inside match &s.kind { - StmtKind::Expr(expr) | StmtKind::Semi(expr) => self.visit_expr(&expr), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => self.visit_expr(expr), _ => {}, } } else { @@ -138,7 +171,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> { self.vec_push = vec_push_option; } else { // There are multiple pushes ... don't lint - self.should_lint = false; + self.multiple_pushes = true; } } } diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index 38400c93c9..0fd09ff719 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -1,5 +1,7 @@ use super::{get_span_of_entire_for_loop, SINGLE_ELEMENT_LOOP}; -use crate::utils::{indent_of, single_segment_path, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::single_segment_path; +use clippy_utils::source::{indent_of, snippet}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind}; @@ -12,13 +14,19 @@ pub(super) fn check<'tcx>( body: &'tcx Expr<'_>, expr: &'tcx Expr<'_>, ) { + let arg_expr = match arg.kind { + ExprKind::AddrOf(BorrowKind::Ref, _, ref_arg) => ref_arg, + ExprKind::MethodCall(method, _, args, _) if args.len() == 1 && method.ident.name == rustc_span::sym::iter => { + &args[0] + }, + _ => return, + }; if_chain! { - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg_expr) = arg.kind; if let PatKind::Binding(.., target, _) = pat.kind; if let ExprKind::Array([arg_expression]) = arg_expr.kind; if let ExprKind::Path(ref list_item) = arg_expression.kind; if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name); - if let ExprKind::Block(ref block, _) = body.kind; + if let ExprKind::Block(block, _) = body.kind; if !block.stmts.is_empty(); then { diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index 9e38e17719..4db6644b9d 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -1,16 +1,14 @@ -use crate::utils::{ - get_parent_expr, get_trait_def_id, has_iter_method, implements_trait, is_integer_const, path_to_local, - path_to_local_id, paths, sugg, -}; +use clippy_utils::ty::{has_iter_method, implements_trait}; +use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg}; use if_chain::if_chain; -use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; +use rustc_hir::HirIdMap; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Stmt, StmtKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; use rustc_span::source_map::Span; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{sym, Symbol}; use std::iter::Iterator; #[derive(Debug, PartialEq)] @@ -22,9 +20,9 @@ enum IncrementVisitorVarState { /// Scan a for loop for variables that are incremented exactly once and not used after that. pub(super) struct IncrementVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, // context reference - states: FxHashMap<HirId, IncrementVisitorVarState>, // incremented variables - depth: u32, // depth of conditional expressions + cx: &'a LateContext<'tcx>, // context reference + states: HirIdMap<IncrementVisitorVarState>, // incremented variables + depth: u32, // depth of conditional expressions done: bool, } @@ -32,7 +30,7 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> { pub(super) fn new(cx: &'a LateContext<'tcx>) -> Self { Self { cx, - states: FxHashMap::default(), + states: HirIdMap::default(), depth: 0, done: false, } @@ -67,7 +65,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { } match parent.kind { - ExprKind::AssignOp(op, ref lhs, ref rhs) => { + ExprKind::AssignOp(op, lhs, rhs) => { if lhs.hir_id == expr.hir_id { *state = if op.node == BinOpKind::Add && is_integer_const(self.cx, rhs, 1) @@ -81,7 +79,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { }; } }, - ExprKind::Assign(ref lhs, _, _) if lhs.hir_id == expr.hir_id => { + ExprKind::Assign(lhs, _, _) if lhs.hir_id == expr.hir_id => { *state = IncrementVisitorVarState::DontWarn }, ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => { @@ -155,7 +153,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { // Look for declarations of the variable if_chain! { - if let StmtKind::Local(ref local) = stmt.kind; + if let StmtKind::Local(local) = stmt.kind; if local.pat.hir_id == self.var_id; if let PatKind::Binding(.., ident, _) = local.pat.kind; then { @@ -193,10 +191,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { if let Some(parent) = get_parent_expr(self.cx, expr) { match parent.kind { - ExprKind::AssignOp(_, ref lhs, _) if lhs.hir_id == expr.hir_id => { + ExprKind::AssignOp(_, lhs, _) if lhs.hir_id == expr.hir_id => { self.state = InitializeVisitorState::DontWarn; }, - ExprKind::Assign(ref lhs, ref rhs, _) if lhs.hir_id == expr.hir_id => { + ExprKind::Assign(lhs, rhs, _) if lhs.hir_id == expr.hir_id => { self.state = if_chain! { if self.depth == 0; if let InitializeVisitorState::Declared(name) @@ -275,7 +273,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } match expr.kind { - ExprKind::Assign(ref path, _, _) | ExprKind::AssignOp(_, ref path, _) => { + ExprKind::Assign(path, _, _) | ExprKind::AssignOp(_, path, _) => { if path_to_local_id(path, self.iterator) { self.nesting = RuledOut; } @@ -316,7 +314,7 @@ pub(super) fn get_span_of_entire_for_loop(expr: &Expr<'_>) -> Span { /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the /// actual `Iterator` that the loop uses. pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String { - let impls_iterator = get_trait_def_id(cx, &paths::ITERATOR).map_or(false, |id| { + let impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| { implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[]) }); if impls_iterator { @@ -329,7 +327,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic // (&mut x).into_iter() ==> x.iter_mut() match &arg.kind { ExprKind::AddrOf(BorrowKind::Ref, mutability, arg_inner) - if has_iter_method(cx, cx.typeck_results().expr_ty(&arg_inner)).is_some() => + if has_iter_method(cx, cx.typeck_results().expr_ty(arg_inner)).is_some() => { let meth_name = match mutability { Mutability::Mut => "iter_mut", @@ -337,7 +335,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic }; format!( "{}.{}()", - sugg::Sugg::hir_with_applicability(cx, &arg_inner, "_", applic_ref).maybe_par(), + sugg::Sugg::hir_with_applicability(cx, arg_inner, "_", applic_ref).maybe_par(), meth_name, ) } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs index 05e0a72256..de267cc77d 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs @@ -1,15 +1,15 @@ use super::WHILE_IMMUTABLE_CONDITION; use crate::consts::constant; -use crate::utils::span_lint_and_then; -use crate::utils::usage::mutated_variables; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::usage::mutated_variables; use if_chain::if_chain; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::DefIdMap; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{def_id, Expr, ExprKind, HirId, QPath}; +use rustc_hir::HirIdSet; +use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; -use std::iter::Iterator; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { if constant(cx, cx.typeck_results(), cond).is_some() { @@ -19,8 +19,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &' let mut var_visitor = VarCollectorVisitor { cx, - ids: FxHashSet::default(), - def_ids: FxHashMap::default(), + ids: HirIdSet::default(), + def_ids: DefIdMap::default(), skip: false, }; var_visitor.visit_expr(cond); @@ -93,8 +93,8 @@ impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor { /// All variables definition IDs are collected struct VarCollectorVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - ids: FxHashSet<HirId>, - def_ids: FxHashMap<def_id::DefId, bool>, + ids: HirIdSet, + def_ids: DefIdMap<bool>, skip: bool, } @@ -103,9 +103,8 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { if_chain! { if let ExprKind::Path(ref qpath) = ex.kind; if let QPath::Resolved(None, _) = *qpath; - let res = self.cx.qpath_res(qpath, ex.hir_id); then { - match res { + match self.cx.qpath_res(qpath, ex.hir_id) { Res::Local(hir_id) => { self.ids.insert(hir_id); }, diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs index 65d8f2f111..9c17207985 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs @@ -1,5 +1,6 @@ use super::WHILE_LET_LOOP; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, MatchSource, StmtKind}; use rustc_lint::{LateContext, LintContext}; @@ -10,14 +11,14 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &' let inner_stmt_expr = extract_expr_from_first_stmt(loop_block); // or extract the first expression (if any) from the block if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(loop_block)) { - if let ExprKind::Match(ref matchexpr, ref arms, ref source) = inner.kind { + if let ExprKind::Match(matchexpr, arms, ref source) = inner.kind { // ensure "if let" compatible match structure match *source { MatchSource::Normal | MatchSource::IfLetDesugar { .. } => { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() - && is_simple_break_expr(&arms[1].body) + && is_simple_break_expr(arms[1].body) { if in_external_macro(cx.sess(), expr.span) { return; @@ -56,7 +57,7 @@ fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr< if block.stmts.is_empty() { return None; } - if let StmtKind::Local(ref local) = block.stmts[0].kind { + if let StmtKind::Local(local) = block.stmts[0].kind { local.init //.map(|expr| expr) } else { None @@ -66,9 +67,9 @@ fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr< /// If a block begins with an expression (with or without semicolon), return it. fn extract_first_expr<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { match block.expr { - Some(ref expr) if block.stmts.is_empty() => Some(expr), + Some(expr) if block.stmts.is_empty() => Some(expr), None if !block.stmts.is_empty() => match block.stmts[0].kind { - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => Some(expr), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => Some(expr), StmtKind::Local(..) | StmtKind::Item(..) => None, }, _ => None, @@ -81,7 +82,7 @@ fn extract_first_expr<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { fn is_simple_break_expr(expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Break(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true, - ExprKind::Block(ref b, _) => extract_first_expr(b).map_or(false, |subexpr| is_simple_break_expr(subexpr)), + ExprKind::Block(b, _) => extract_first_expr(b).map_or(false, |subexpr| is_simple_break_expr(subexpr)), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index e5a47694fa..82715d9baf 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -1,9 +1,11 @@ use super::utils::{LoopNestVisitor, Nesting}; use super::WHILE_LET_ON_ITERATOR; -use crate::utils::usage::mutated_variables; -use crate::utils::{ - get_enclosing_block, get_trait_def_id, implements_trait, is_refutable, last_path_segment, match_trait_method, - path_to_local, path_to_local_id, paths, snippet_with_applicability, span_lint_and_sugg, +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::implements_trait; +use clippy_utils::usage::mutated_variables; +use clippy_utils::{ + get_enclosing_block, is_refutable, is_trait_method, last_path_segment, path_to_local, path_to_local_id, }; use if_chain::if_chain; use rustc_errors::Applicability; @@ -11,23 +13,20 @@ use rustc_hir::intravisit::{walk_block, walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, ExprKind, HirId, MatchSource, Node, PatKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; - use rustc_span::symbol::sym; pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Match(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.kind { + if let ExprKind::Match(match_expr, arms, MatchSource::WhileLetDesugar) = expr.kind { let pat = &arms[0].pat.kind; - if let ( - &PatKind::TupleStruct(ref qpath, ref pat_args, _), - &ExprKind::MethodCall(ref method_path, _, ref method_args, _), - ) = (pat, &match_expr.kind) + if let (&PatKind::TupleStruct(ref qpath, pat_args, _), &ExprKind::MethodCall(method_path, _, method_args, _)) = + (pat, &match_expr.kind) { let iter_expr = &method_args[0]; // Don't lint when the iterator is recreated on every iteration if_chain! { if let ExprKind::MethodCall(..) | ExprKind::Call(..) = iter_expr.kind; - if let Some(iter_def_id) = get_trait_def_id(cx, &paths::ITERATOR); + if let Some(iter_def_id) = cx.tcx.get_diagnostic_item(sym::Iterator); if implements_trait(cx, cx.typeck_results().expr_ty(iter_expr), iter_def_id, &[]); then { return; @@ -36,11 +35,11 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let lhs_constructor = last_path_segment(qpath); if method_path.ident.name == sym::next - && match_trait_method(cx, match_expr, &paths::ITERATOR) + && is_trait_method(cx, match_expr, sym::Iterator) && lhs_constructor.ident.name == sym::Some && (pat_args.is_empty() - || !is_refutable(cx, &pat_args[0]) - && !is_used_inside(cx, iter_expr, &arms[0].body) + || !is_refutable(cx, pat_args[0]) + && !is_used_inside(cx, iter_expr, arms[0].body) && !is_iterator_used_after_while_let(cx, iter_expr) && !is_nested(cx, expr, &method_args[0])) { diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 6d9c78393c..ec03daff87 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -1,4 +1,6 @@ -use crate::utils::{in_macro, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; +use clippy_utils::source::snippet; use hir::def::{DefKind, Res}; use if_chain::if_chain; use rustc_ast::ast; @@ -7,7 +9,7 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{edition::Edition, Span}; +use rustc_span::{edition::Edition, sym, Span}; declare_clippy_lint! { /// **What it does:** Checks for `#[macro_use] use...`. @@ -108,10 +110,9 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { if cx.sess().opts.edition >= Edition::Edition2018; if let hir::ItemKind::Use(path, _kind) = &item.kind; let attrs = cx.tcx.hir().attrs(item.hir_id()); - if let Some(mac_attr) = attrs - .iter() - .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); + if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use)); if let Res::Def(DefKind::Mod, id) = path.res; + if !id.is_local(); then { for kid in cx.tcx.item_children(id).iter() { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { diff --git a/src/tools/clippy/clippy_lints/src/main_recursion.rs b/src/tools/clippy/clippy_lints/src/main_recursion.rs index 1b274c79d3..07d8a440ae 100644 --- a/src/tools/clippy/clippy_lints/src/main_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/main_recursion.rs @@ -1,10 +1,11 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet; +use clippy_utils::{is_entrypoint_fn, is_no_std_crate}; +use if_chain::if_chain; use rustc_hir::{Crate, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use crate::utils::{is_entrypoint_fn, is_no_std_crate, snippet, span_lint_and_help}; -use if_chain::if_chain; - declare_clippy_lint! { /// **What it does:** Checks for recursion using the entrypoint. /// diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 2e2e693592..5d88ff3b99 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -1,5 +1,7 @@ -use crate::utils::paths::FUTURE_FROM_GENERATOR; -use crate::utils::{match_function_call, position_before_rarrow, snippet_block, snippet_opt, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::match_function_call; +use clippy_utils::paths::FUTURE_FROM_GENERATOR; +use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; diff --git a/src/tools/clippy/clippy_lints/src/manual_map.rs b/src/tools/clippy/clippy_lints/src/manual_map.rs index ac1d51e199..0b873534f2 100644 --- a/src/tools/clippy/clippy_lints/src/manual_map.rs +++ b/src/tools/clippy/clippy_lints/src/manual_map.rs @@ -1,19 +1,14 @@ -use crate::{ - map_unit_fn::OPTION_MAP_UNIT_FN, - matches::MATCH_AS_REF, - utils::{ - can_partially_move_ty, is_allowed, is_type_diagnostic_item, match_def_path, match_var, paths, - peel_hir_expr_refs, peel_mid_ty_refs_is_mutable, snippet_with_applicability, snippet_with_context, - span_lint_and_sugg, - }, +use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF}; +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, }; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::Applicability; -use rustc_hir::{ - def::Res, - intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}, - Arm, BindingAnnotation, Block, Expr, ExprKind, Mutability, Pat, PatKind, Path, QPath, -}; +use rustc_hir::LangItem::{OptionNone, OptionSome}; +use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, 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}; @@ -51,13 +46,16 @@ declare_lint_pass!(ManualMap => [MANUAL_MAP]); impl LateLintPass<'_> for ManualMap { #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) { - return; - } - - if let ExprKind::Match(scrutinee, [arm1 @ Arm { guard: None, .. }, arm2 @ Arm { guard: None, .. }], _) = - expr.kind + if let ExprKind::Match( + scrutinee, + [arm1 @ Arm { guard: None, .. }, arm2 @ Arm { guard: None, .. }], + match_kind, + ) = expr.kind { + if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) { + return; + } + let (scrutinee_ty, ty_ref_count, ty_mutability) = peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrutinee)); if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::option_type) @@ -104,12 +102,18 @@ impl LateLintPass<'_> for ManualMap { None => return, }; + // 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) { return; } + // `map` won't perform any adjustments. + if !cx.typeck_results().expr_adjustments(some_expr).is_empty() { + return; + } + if !can_move_expr_to_closure(cx, some_expr) { return; } @@ -129,7 +133,7 @@ impl LateLintPass<'_> for ManualMap { // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; - let scrutinee_str = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); + let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { format!("({})", scrutinee_str) @@ -160,7 +164,7 @@ impl LateLintPass<'_> for ManualMap { "|{}{}| {}", annotation, some_binding, - snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app) + snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0 ) }, } @@ -168,8 +172,8 @@ impl LateLintPass<'_> for ManualMap { // TODO: handle explicit reference annotations. format!( "|{}| {}", - snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app), - snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app) + snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0, + snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0 ) } else { // Refutable bindings and mixed reference annotations can't be handled by `map`. @@ -182,58 +186,17 @@ impl LateLintPass<'_> for ManualMap { expr.span, "manual implementation of `Option::map`", "try this", - format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str), + if matches!(match_kind, MatchSource::IfLetDesugar { .. }) && is_else_clause(cx.tcx, expr) { + format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str) + } else { + format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str) + }, app, ); } } } -// Checks if the expression can be moved into a closure as is. -fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { - struct V<'cx, 'tcx> { - cx: &'cx LateContext<'tcx>, - make_closure: bool, - } - impl Visitor<'tcx> for V<'_, 'tcx> { - type Map = ErasedMap<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None - } - - fn visit_expr(&mut self, e: &'tcx Expr<'_>) { - match e.kind { - ExprKind::Break(..) - | ExprKind::Continue(_) - | ExprKind::Ret(_) - | ExprKind::Yield(..) - | ExprKind::InlineAsm(_) - | ExprKind::LlvmInlineAsm(_) => { - self.make_closure = false; - }, - // Accessing a field of a local value can only be done if the type isn't - // partially moved. - ExprKind::Field(base_expr, _) - if matches!( - base_expr.kind, - ExprKind::Path(QPath::Resolved(_, Path { res: Res::Local(_), .. })) - ) && can_partially_move_ty(self.cx, self.cx.typeck_results().expr_ty(base_expr)) => - { - // TODO: check if the local has been partially moved. Assume it has for now. - self.make_closure = false; - return; - } - _ => (), - }; - walk_expr(self, e); - } - } - - let mut v = V { cx, make_closure: true }; - v.visit_expr(expr); - v.make_closure -} - // 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>> { @@ -266,20 +229,9 @@ fn try_parse_pattern(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: SyntaxCon match pat.kind { PatKind::Wild => Some(OptionPat::Wild), PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt), - PatKind::Path(QPath::Resolved(None, path)) - if path - .res - .opt_def_id() - .map_or(false, |id| match_def_path(cx, id, &paths::OPTION_NONE)) => - { - Some(OptionPat::None) - }, - PatKind::TupleStruct(QPath::Resolved(None, path), [pattern], _) - if path - .res - .opt_def_id() - .map_or(false, |id| match_def_path(cx, id, &paths::OPTION_SOME)) - && pat.span.ctxt() == ctxt => + PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone) => Some(OptionPat::None), + PatKind::TupleStruct(ref qpath, [pattern], _) + if is_lang_ctor(cx, qpath, OptionSome) && pat.span.ctxt() == ctxt => { Some(OptionPat::Some { pattern, ref_count }) }, @@ -295,17 +247,11 @@ fn get_some_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ctxt: SyntaxConte match expr.kind { ExprKind::Call( Expr { - kind: ExprKind::Path(QPath::Resolved(None, path)), + kind: ExprKind::Path(ref qpath), .. }, [arg], - ) if ctxt == expr.span.ctxt() => { - if match_def_path(cx, path.res.opt_def_id()?, &paths::OPTION_SOME) { - Some(arg) - } else { - None - } - }, + ) if ctxt == expr.span.ctxt() && is_lang_ctor(cx, qpath, OptionSome) => Some(arg), ExprKind::Block( Block { stmts: [], @@ -321,10 +267,7 @@ fn get_some_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ctxt: SyntaxConte // Checks for the `None` value. fn is_none_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { match expr.kind { - ExprKind::Path(QPath::Resolved(None, path)) => path - .res - .opt_def_id() - .map_or(false, |id| match_def_path(cx, id, &paths::OPTION_NONE)), + ExprKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone), ExprKind::Block( Block { stmts: [], diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 7e6d4d3a21..54f714b54b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -1,15 +1,15 @@ -use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then}; +use clippy_utils::attrs::is_doc_hidden; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; +use clippy_utils::{meets_msrv, msrvs}; use if_chain::if_chain; -use rustc_ast::ast::{Attribute, Item, ItemKind, FieldDef, Variant, VariantData, VisibilityKind}; -use rustc_attr as attr; +use rustc_ast::ast::{FieldDef, Item, ItemKind, Variant, VariantData, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{sym, Span}; -const MANUAL_NON_EXHAUSTIVE_MSRV: RustcVersion = RustcVersion::new(1, 40, 0); - declare_clippy_lint! { /// **What it does:** Checks for manual implementations of the non-exhaustive pattern. /// @@ -74,7 +74,7 @@ impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]); impl EarlyLintPass for ManualNonExhaustive { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::NON_EXHAUSTIVE) { return; } @@ -100,19 +100,11 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants fn is_non_exhaustive_marker(variant: &Variant) -> bool { matches!(variant.data, VariantData::Unit(_)) && variant.ident.as_str().starts_with('_') - && variant.attrs.iter().any(|a| is_doc_hidden(a)) - } - - fn is_doc_hidden(attr: &Attribute) -> bool { - attr.has_name(sym::doc) - && match attr.meta_item_list() { - Some(l) => attr::list_contains_name(&l, sym::hidden), - None => false, - } + && is_doc_hidden(&variant.attrs) } + let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)); if_chain! { - let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)); if let Some(marker) = markers.next(); if markers.count() == 0 && variants.len() > 1; then { diff --git a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs index efb05b8ffd..847c8c648b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs +++ b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs @@ -1,9 +1,10 @@ -use crate::utils::{ - indent_of, is_type_diagnostic_item, match_qpath, path_to_local_id, paths, reindent_multiline, snippet_opt, - span_lint_and_sugg, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_lang_ctor, path_to_local_id}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::LangItem::{ResultErr, ResultOk}; use rustc_hir::{Expr, ExprKind, PatKind}; use rustc_lint::LintContext; use rustc_lint::{LateContext, LateLintPass}; @@ -54,7 +55,7 @@ impl LateLintPass<'_> for ManualOkOr { let or_expr = &args[1]; if is_ok_wrapping(cx, &args[2]); if let ExprKind::Call(Expr { kind: ExprKind::Path(err_path), .. }, &[ref err_arg]) = or_expr.kind; - if match_qpath(err_path, &paths::RESULT_ERR); + if is_lang_ctor(cx, err_path, ResultErr); if let Some(method_receiver_snippet) = snippet_opt(cx, method_receiver.span); if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span); if let Some(indent) = indent_of(cx, scrutinee.span); @@ -81,7 +82,7 @@ impl LateLintPass<'_> for ManualOkOr { fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool { if let ExprKind::Path(ref qpath) = map_expr.kind { - if match_qpath(qpath, &paths::RESULT_OK) { + if is_lang_ctor(cx, qpath, ResultOk) { return true; } } @@ -90,7 +91,7 @@ fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool { let body = cx.tcx.hir().body(body_id); if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind; if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, &[ref ok_arg]) = body.value.kind; - if match_qpath(ok_path, &paths::RESULT_OK); + if is_lang_ctor(cx, ok_path, ResultOk); then { path_to_local_id(ok_arg, param_id) } else { false } } } diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index 42a92104a4..23428524de 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -1,9 +1,8 @@ use crate::consts::{constant, Constant}; -use crate::utils::usage::mutated_variables; -use crate::utils::{ - eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, snippet, span_lint_and_then, -}; - +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; +use clippy_utils::source::snippet; +use clippy_utils::usage::mutated_variables; +use clippy_utils::{eq_expr_value, higher, match_def_path, meets_msrv, msrvs, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_hir::def::Res; @@ -18,8 +17,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Spanned; use rustc_span::Span; -const MANUAL_STRIP_MSRV: RustcVersion = RustcVersion::new(1, 45, 0); - declare_clippy_lint! { /// **What it does:** /// Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using @@ -75,7 +72,7 @@ enum StripKind { impl<'tcx> LateLintPass<'tcx> for ManualStrip { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::STR_STRIP_PREFIX) { return; } @@ -92,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { } else { return; }; - let target_res = cx.qpath_res(&target_path, target_arg.hir_id); + let target_res = cx.qpath_res(target_path, target_arg.hir_id); if target_res == Res::Err { return; }; @@ -175,7 +172,7 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t // Tests if `expr` is a `&str`. fn is_ref_str(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - match cx.typeck_results().expr_ty_adjusted(&expr).kind() { + match cx.typeck_results().expr_ty_adjusted(expr).kind() { ty::Ref(_, ty, _) => ty.is_str(), _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs index b452225b5d..520162559e 100644 --- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs @@ -1,9 +1,13 @@ use crate::consts::constant_simple; -use crate::utils; -use crate::utils::{path_to_local_id, sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::usage::contains_return_break_continue_macro; +use clippy_utils::{in_constant, is_lang_ctor, path_to_local_id, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Arm, Expr, ExprKind, Pat, PatKind}; +use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; +use rustc_hir::{Arm, Expr, ExprKind, PatKind}; use rustc_lint::LintContext; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -42,7 +46,7 @@ declare_lint_pass!(ManualUnwrapOr => [MANUAL_UNWRAP_OR]); impl LateLintPass<'_> for ManualUnwrapOr { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if in_external_macro(cx.sess(), expr.span) { + if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) { return; } lint_manual_unwrap_or(cx, expr); @@ -65,26 +69,24 @@ impl Case { } fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - fn applicable_or_arm<'a>(arms: &'a [Arm<'a>]) -> Option<&'a Arm<'a>> { + fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'a Arm<'a>> { if_chain! { if arms.len() == 2; if arms.iter().all(|arm| arm.guard.is_none()); - if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| + if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| { match arm.pat.kind { - PatKind::Path(ref some_qpath) => - utils::match_qpath(some_qpath, &utils::paths::OPTION_NONE), - PatKind::TupleStruct(ref err_qpath, &[Pat { kind: PatKind::Wild, .. }], _) => - utils::match_qpath(err_qpath, &utils::paths::RESULT_ERR), + PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone), + 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 unwrap_qpath, &[unwrap_pat], _) = unwrap_arm.pat.kind; - if utils::match_qpath(unwrap_qpath, &utils::paths::OPTION_SOME) - || utils::match_qpath(unwrap_qpath, &utils::paths::RESULT_OK); + 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); - if !utils::usage::contains_return_break_continue_macro(or_arm.body); + if !contains_return_break_continue_macro(or_arm.body); then { Some(or_arm) } else { @@ -96,28 +98,37 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if_chain! { if let ExprKind::Match(scrutinee, match_arms, _) = expr.kind; let ty = cx.typeck_results().expr_ty(scrutinee); - if let Some(case) = if utils::is_type_diagnostic_item(cx, ty, sym::option_type) { + if let Some(case) = if is_type_diagnostic_item(cx, ty, sym::option_type) { Some(Case::Option) - } else if utils::is_type_diagnostic_item(cx, ty, sym::result_type) { + } else if is_type_diagnostic_item(cx, ty, sym::result_type) { Some(Case::Result) } else { None }; - if let Some(or_arm) = applicable_or_arm(match_arms); - if let Some(or_body_snippet) = utils::snippet_opt(cx, or_arm.body.span); - if let Some(indent) = utils::indent_of(cx, expr.span); + if let Some(or_arm) = applicable_or_arm(cx, match_arms); + if let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span); + if let Some(indent) = indent_of(cx, expr.span); if constant_simple(cx, cx.typeck_results(), or_arm.body).is_some(); then { let reindented_or_body = - utils::reindent_multiline(or_body_snippet.into(), true, Some(indent)); - utils::span_lint_and_sugg( + reindent_multiline(or_body_snippet.into(), true, Some(indent)); + + let suggestion = if scrutinee.span.from_expansion() { + // we don't want parenthesis around macro, e.g. `(some_macro!()).unwrap_or(0)` + sugg::Sugg::hir_with_macro_callsite(cx, scrutinee, "..") + } + else { + sugg::Sugg::hir(cx, scrutinee, "..").maybe_par() + }; + + span_lint_and_sugg( cx, MANUAL_UNWRAP_OR, expr.span, &format!("this pattern reimplements `{}`", case.unwrap_fn_path()), "replace with", format!( "{}.unwrap_or({})", - sugg::Sugg::hir(cx, scrutinee, "..").maybe_par(), + suggestion, reindented_or_body, ), Applicability::MachineApplicable, diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs index 4b685c09a0..99c35ae3bb 100644 --- a/src/tools/clippy/clippy_lints/src/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/map_clone.rs @@ -1,7 +1,8 @@ -use crate::utils::paths; -use crate::utils::{ - is_copy, is_type_diagnostic_item, match_trait_method, remove_blocks, snippet_with_applicability, span_lint_and_sugg, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use clippy_utils::remove_blocks; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::{is_copy, is_type_diagnostic_item}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -51,17 +52,17 @@ impl<'tcx> LateLintPass<'tcx> for MapClone { } if_chain! { - if let hir::ExprKind::MethodCall(ref method, _, ref args, _) = e.kind; + if let hir::ExprKind::MethodCall(method, _, args, _) = e.kind; if args.len() == 2; if method.ident.name == sym::map; let ty = cx.typeck_results().expr_ty(&args[0]); - if is_type_diagnostic_item(cx, ty, sym::option_type) || match_trait_method(cx, e, &paths::ITERATOR); + if is_type_diagnostic_item(cx, ty, sym::option_type) || is_trait_method(cx, e, sym::Iterator); if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind; - let closure_body = cx.tcx.hir().body(body_id); - let closure_expr = remove_blocks(&closure_body.value); then { + let closure_body = cx.tcx.hir().body(body_id); + let closure_expr = remove_blocks(&closure_body.value); match closure_body.params[0].pat.kind { - hir::PatKind::Ref(ref inner, hir::Mutability::Not) => if let hir::PatKind::Binding( + hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding( hir::BindingAnnotation::Unannotated, .., name, None ) = inner.kind { if ident_eq(name, closure_expr) { @@ -70,14 +71,14 @@ impl<'tcx> LateLintPass<'tcx> for MapClone { }, hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => { match closure_expr.kind { - hir::ExprKind::Unary(hir::UnOp::Deref, ref inner) => { + hir::ExprKind::Unary(hir::UnOp::Deref, inner) => { if ident_eq(name, inner) { if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() { lint(cx, e.span, args[0].span, true); } } }, - hir::ExprKind::MethodCall(ref method, _, [obj], _) => if_chain! { + hir::ExprKind::MethodCall(method, _, [obj], _) => if_chain! { if ident_eq(name, obj) && method.ident.name == sym::clone; if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id); if let Some(trait_id) = cx.tcx.trait_of_item(fn_id); @@ -108,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone { } fn ident_eq(name: Ident, path: &hir::Expr<'_>) -> bool { - if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.kind { + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = path.kind { path.segments.len() == 1 && path.segments[0].ident == name } else { false diff --git a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs index 76fe8e776e..425a9734e5 100644 --- a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs +++ b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs @@ -1,5 +1,4 @@ -use crate::utils::span_lint_and_help; - +use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{CaptureBy, Expr, ExprKind, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -113,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore { } // check if this is a method call (e.g. x.foo()) - if let ExprKind::MethodCall(ref method, _t_span, ref args, _) = e.kind { + if let ExprKind::MethodCall(method, _t_span, args, _) = e.kind { // only work if the method name is `map_err` and there are only 2 arguments (e.g. x.map_err(|_|[1] // Enum::Variant[2])) if method.ident.as_str() == "map_err" && args.len() == 2 { diff --git a/src/tools/clippy/clippy_lints/src/map_identity.rs b/src/tools/clippy/clippy_lints/src/map_identity.rs index 9f9c108a85..41cda23510 100644 --- a/src/tools/clippy/clippy_lints/src/map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/map_identity.rs @@ -1,7 +1,6 @@ -use crate::utils::{ - is_adjusted, is_type_diagnostic_item, match_path, match_trait_method, match_var, paths, remove_blocks, - span_lint_and_sugg, -}; +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}; @@ -62,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for MapIdentity { /// 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(ref method, _, ref args, _) = expr.kind; + 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 match_trait_method(cx, expr, &paths::ITERATOR) + 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 { @@ -81,7 +80,7 @@ fn get_map_argument<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a 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(QPath::Resolved(_, ref path)) => match_path(path, &paths::STD_CONVERT_IDENTITY), + ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY), _ => false, } } @@ -100,12 +99,12 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { match body.kind { ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat), - ExprKind::Ret(Some(ref ret_val)) => match_expr_param(cx, ret_val, params[0].pat), - ExprKind::Block(ref block, _) => { + 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(ref expr) | StmtKind::Expr(ref expr) = block.stmts[0].kind; - if let ExprKind::Ret(Some(ref ret_val)) = expr.kind; + 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 { diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index 01126e8619..57cd907e77 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -1,4 +1,7 @@ -use crate::utils::{is_type_diagnostic_item, iter_input_pats, method_chain_args, snippet, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{iter_input_pats, method_chain_args}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -130,7 +133,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> // Calls can't be reduced any more Some(expr.span) }, - hir::ExprKind::Block(ref block, _) => { + hir::ExprKind::Block(block, _) => { match (block.stmts, block.expr.as_ref()) { (&[], Some(inner_expr)) => { // If block only contains an expression, @@ -141,8 +144,8 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> // If block only contains statements, // reduce `{ X; }` to `X` or `X;` match inner_stmt.kind { - hir::StmtKind::Local(ref local) => Some(local.span), - hir::StmtKind::Expr(ref e) => Some(e.span), + hir::StmtKind::Local(local) => Some(local.span), + hir::StmtKind::Expr(e) => Some(e.span), hir::StmtKind::Semi(..) => Some(inner_stmt.span), hir::StmtKind::Item(..) => None, } @@ -165,17 +168,15 @@ fn unit_closure<'tcx>( cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, ) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> { - if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.kind { + if_chain! { + if let hir::ExprKind::Closure(_, decl, inner_expr_id, _, _) = expr.kind; let body = cx.tcx.hir().body(inner_expr_id); let body_expr = &body.value; - - if_chain! { - if decl.inputs.len() == 1; - if is_unit_expression(cx, body_expr); - if let Some(binding) = iter_input_pats(&decl, body).next(); - then { - return Some((binding, body_expr)); - } + if decl.inputs.len() == 1; + if is_unit_expression(cx, body_expr); + if let Some(binding) = iter_input_pats(decl, body).next(); + then { + return Some((binding, body_expr)); } } None @@ -266,7 +267,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnit { return; } - if let hir::StmtKind::Semi(ref expr) = stmt.kind { + if let hir::StmtKind::Semi(expr) = stmt.kind { if let Some(arglists) = method_chain_args(expr, &["map"]) { lint_map_unit_fn(cx, stmt, expr, arglists[0]); } diff --git a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs index 086dae9422..ca6fb0831f 100644 --- a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs +++ b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs @@ -1,4 +1,6 @@ -use crate::utils::{is_type_diagnostic_item, is_type_lang_item, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +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, MatchSource}; @@ -49,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchOnVecItems { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if_chain! { if !in_external_macro(cx.sess(), expr.span); - if let ExprKind::Match(ref match_expr, _, MatchSource::Normal) = expr.kind; + if let ExprKind::Match(match_expr, _, MatchSource::Normal) = expr.kind; if let Some(idx_expr) = is_vec_indexing(cx, match_expr); if let ExprKind::Index(vec, idx) = idx_expr.kind; @@ -76,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchOnVecItems { fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::Index(ref array, ref index) = expr.kind; + if let ExprKind::Index(array, index) = expr.kind; if is_vector(cx, array); if !is_full_range(cx, index); diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index 8570cd724b..a70e8b2608 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -1,32 +1,37 @@ use crate::consts::{constant, miri_to_const, Constant}; -use crate::utils::sugg::Sugg; -use crate::utils::visitors::LocalUsedVisitor; -use crate::utils::{ - expr_block, get_parent_expr, implements_trait, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, - is_type_diagnostic_item, is_wild, match_qpath, match_type, meets_msrv, multispan_sugg, path_to_local, - path_to_local_id, peel_hir_pat_refs, peel_mid_ty_refs, peel_n_hir_expr_refs, remove_blocks, snippet, snippet_block, - snippet_opt, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, - span_lint_and_then, strip_pat_refs, +use clippy_utils::diagnostics::{ + multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, }; -use crate::utils::{paths, search_same, SpanlessEq, SpanlessHash}; +use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability}; +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, + path_to_local, path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns, remove_blocks, + strip_pat_refs, +}; +use clippy_utils::{paths, search_same, SpanlessEq, SpanlessHash}; use if_chain::if_chain; use rustc_ast::ast::LitKind; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; -use rustc_hir::def::CtorKind; +use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{ - Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Guard, HirId, Local, MatchSource, Mutability, Node, Pat, - PatKind, QPath, RangeEnd, + self as hir, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Guard, HirId, Local, MatchSource, + Mutability, Node, Pat, PatKind, PathSegment, QPath, RangeEnd, TyKind, }; +use rustc_hir::{HirIdMap, HirIdSet}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Ty, TyS}; +use rustc_middle::ty::{self, Ty, TyS, VariantDef}; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::sym; use std::cmp::Ordering; use std::collections::hash_map::Entry; +use std::iter; use std::ops::Bound; declare_clippy_lint! { @@ -419,7 +424,12 @@ declare_clippy_lint! { /// **Why is this bad?** It's more concise and clear to just use the proper /// utility function /// - /// **Known problems:** None. + /// **Known problems:** This will change the drop order for the matched type. Both `if let` and + /// `while let` will drop the value at the end of the block, both `if` and `while` will drop the + /// value before entering the block. For most types this change will not matter, but for a few + /// types this will not be an acceptable change (e.g. locks). See the + /// [reference](https://doc.rust-lang.org/reference/destructors.html#drop-scopes) for more about + /// drop order. /// /// **Example:** /// @@ -569,8 +579,6 @@ impl_lint_pass!(Matches => [ MATCH_SAME_ARMS, ]); -const MATCH_LIKE_MATCHES_MACRO_MSRV: RustcVersion = RustcVersion::new(1, 42, 0); - impl<'tcx> LateLintPass<'tcx> for Matches { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if in_external_macro(cx.sess(), expr.span) || in_macro(expr.span) { @@ -579,7 +587,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { redundant_pattern_match::check(cx, expr); - if meets_msrv(self.msrv.as_ref(), &MATCH_LIKE_MATCHES_MACRO_MSRV) { + if meets_msrv(self.msrv.as_ref(), &msrvs::MATCHES_MACRO) { if !check_match_like_matches(cx, expr) { lint_match_arms(cx, expr); } @@ -587,7 +595,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { lint_match_arms(cx, expr); } - if let ExprKind::Match(ref ex, ref arms, MatchSource::Normal) = expr.kind { + if let ExprKind::Match(ex, arms, MatchSource::Normal) = expr.kind { check_single_match(cx, ex, arms, expr); check_match_bool(cx, ex, arms, expr); check_overlapping_arms(cx, ex, arms); @@ -602,7 +610,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { check_match_single_binding(cx, ex, arms, expr); } } - if let ExprKind::Match(ref ex, ref arms, _) = expr.kind { + if let ExprKind::Match(ex, arms, _) = expr.kind { check_match_ref_pats(cx, ex, arms, expr); } } @@ -611,14 +619,14 @@ impl<'tcx> LateLintPass<'tcx> for Matches { if_chain! { if !in_external_macro(cx.sess(), local.span); if !in_macro(local.span); - if let Some(ref expr) = local.init; - if let ExprKind::Match(ref target, ref arms, MatchSource::Normal) = expr.kind; + if let Some(expr) = local.init; + if let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind; if arms.len() == 1 && arms[0].guard.is_none(); if let PatKind::TupleStruct( - QPath::Resolved(None, ref variant_name), ref args, _) = arms[0].pat.kind; + 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; - let body = remove_blocks(&arms[0].body); + 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); then { @@ -647,7 +655,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { if_chain! { if !in_external_macro(cx.sess(), pat.span); if !in_macro(pat.span); - if let PatKind::Struct(QPath::Resolved(_, ref path), fields, true) = pat.kind; + if let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind; if let Some(def_id) = path.res.opt_def_id(); let ty = cx.tcx.type_of(def_id); if let ty::Adt(def, _) = ty.kind(); @@ -730,12 +738,15 @@ fn report_single_match_single_pattern( format!(" else {}", expr_block(cx, els, None, "..", Some(expr.span))) }); + let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat); let (msg, sugg) = if_chain! { - let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat); if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind; let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex)); - if let Some(trait_id) = cx.tcx.lang_items().structural_peq_trait(); - if ty.is_integral() || ty.is_char() || ty.is_str() || implements_trait(cx, ty, trait_id, &[]); + if let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait(); + if let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait(); + if ty.is_integral() || ty.is_char() || ty.is_str() + || (implements_trait(cx, ty, spe_trait_id, &[]) + && implements_trait(cx, ty, pe_trait_id, &[ty.into()])); then { // scrutinee derives PartialEq and the pattern is a constant. let pat_ref_count = match pat.kind { @@ -759,7 +770,7 @@ fn report_single_match_single_pattern( // PartialEq for different reference counts may not exist. "&".repeat(ref_count_diff), snippet(cx, arms[0].pat.span, ".."), - expr_block(cx, &arms[0].body, None, "..", Some(expr.span)), + expr_block(cx, arms[0].body, None, "..", Some(expr.span)), els_str, ); (msg, sugg) @@ -769,7 +780,7 @@ fn report_single_match_single_pattern( "if let {} = {} {}{}", snippet(cx, arms[0].pat.span, ".."), snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, "..", Some(expr.span)), + expr_block(cx, arms[0].body, None, "..", Some(expr.span)), els_str, ); (msg, sugg) @@ -807,7 +818,7 @@ fn check_single_match_opt_like( ]; let path = match arms[1].pat.kind { - PatKind::TupleStruct(ref path, ref inner, _) => { + PatKind::TupleStruct(ref path, inner, _) => { // Contains any non wildcard patterns (e.g., `Err(err)`)? if !inner.iter().all(is_wild) { return; @@ -839,7 +850,7 @@ fn check_match_bool(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: move |diag| { if arms.len() == 2 { // no guards - let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pat.kind { + let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind { if let ExprKind::Lit(ref lit) = arm_bool.kind { match lit.node { LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)), @@ -915,14 +926,14 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm let ex_ty = cx.typeck_results().expr_ty(ex).peel_refs(); if is_type_diagnostic_item(cx, ex_ty, sym::result_type) { for arm in arms { - if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pat.kind { + if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind { let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)); if path_str == "Err" { let mut matching_wild = inner.iter().any(is_wild); let mut ident_bind_name = String::from("_"); if !matching_wild { // Looking for unused bindings (i.e.: `_e`) - inner.iter().for_each(|pat| { + for pat in inner.iter() { if let PatKind::Binding(_, id, ident, None) = pat.kind { if ident.as_str().starts_with('_') && !LocalUsedVisitor::new(cx, id).check_expr(arm.body) @@ -931,11 +942,11 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm matching_wild = true; } } - }); + } } if_chain! { if matching_wild; - if let ExprKind::Block(ref block, _) = arm.body.kind; + if let ExprKind::Block(block, _) = arm.body.kind; if is_panic_block(block); then { // `Err(_)` or `Err(_e)` arm with `panic!` found @@ -954,122 +965,194 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm } } -fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { - let ty = cx.typeck_results().expr_ty(ex); - if !ty.is_enum() { - // If there isn't a nice closed set of possible values that can be conveniently enumerated, - // don't complain about not enumerating the mall. - return; +enum CommonPrefixSearcher<'a> { + None, + Path(&'a [PathSegment<'a>]), + Mixed, +} +impl CommonPrefixSearcher<'a> { + fn with_path(&mut self, path: &'a [PathSegment<'a>]) { + match path { + [path @ .., _] => self.with_prefix(path), + [] => (), + } + } + + fn with_prefix(&mut self, path: &'a [PathSegment<'a>]) { + match self { + Self::None => *self = Self::Path(path), + Self::Path(self_path) + if path + .iter() + .map(|p| p.ident.name) + .eq(self_path.iter().map(|p| p.ident.name)) => {}, + Self::Path(_) => *self = Self::Mixed, + Self::Mixed => (), + } } +} + +fn is_doc_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool { + let attrs = cx.tcx.get_attrs(variant_def.def_id); + clippy_utils::attrs::is_doc_hidden(attrs) +} + +#[allow(clippy::too_many_lines)] +fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { + let ty = cx.typeck_results().expr_ty(ex).peel_refs(); + let adt_def = match ty.kind() { + ty::Adt(adt_def, _) + if adt_def.is_enum() + && !(is_type_diagnostic_item(cx, ty, sym::option_type) + || is_type_diagnostic_item(cx, ty, sym::result_type)) => + { + adt_def + }, + _ => return, + }; // First pass - check for violation, but don't do much book-keeping because this is hopefully // the uncommon case, and the book-keeping is slightly expensive. let mut wildcard_span = None; let mut wildcard_ident = None; + let mut has_non_wild = false; for arm in arms { - if let PatKind::Wild = arm.pat.kind { - wildcard_span = Some(arm.pat.span); - } else if let PatKind::Binding(_, _, ident, None) = arm.pat.kind { - wildcard_span = Some(arm.pat.span); - wildcard_ident = Some(ident); + match peel_hir_pat_refs(arm.pat).0.kind { + PatKind::Wild => wildcard_span = Some(arm.pat.span), + PatKind::Binding(_, _, ident, None) => { + wildcard_span = Some(arm.pat.span); + wildcard_ident = Some(ident); + }, + _ => has_non_wild = true, } } + let wildcard_span = match wildcard_span { + Some(x) if has_non_wild => x, + _ => return, + }; - if let Some(wildcard_span) = wildcard_span { - // Accumulate the variants which should be put in place of the wildcard because they're not - // already covered. + // 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 mut missing_variants = vec![]; - if let ty::Adt(def, _) = ty.kind() { - for variant in &def.variants { - missing_variants.push(variant); + let mut path_prefix = CommonPrefixSearcher::None; + for arm in arms { + // Guards mean that this case probably isn't exhaustively covered. Technically + // this is incorrect, as we should really check whether each variant is exhaustively + // covered by the set of guards that cover it, but that's really hard to do. + recurse_or_patterns(arm.pat, |pat| { + let path = match &peel_hir_pat_refs(pat).0.kind { + PatKind::Path(path) => { + #[allow(clippy::match_same_arms)] + let id = match cx.qpath_res(path, pat.hir_id) { + Res::Def(DefKind::Const | DefKind::ConstParam | DefKind::AnonConst, _) => return, + Res::Def(_, id) => id, + _ => return, + }; + if arm.guard.is_none() { + missing_variants.retain(|e| e.ctor_def_id != Some(id)); + } + path + }, + PatKind::TupleStruct(path, patterns, ..) => { + if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() { + if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) { + missing_variants.retain(|e| e.ctor_def_id != Some(id)); + } + } + path + }, + PatKind::Struct(path, patterns, ..) => { + if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() { + if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p.pat)) { + missing_variants.retain(|e| e.def_id != id); + } + } + path + }, + _ => return, + }; + match path { + QPath::Resolved(_, path) => path_prefix.with_path(path.segments), + QPath::TypeRelative( + hir::Ty { + kind: TyKind::Path(QPath::Resolved(_, path)), + .. + }, + _, + ) => path_prefix.with_prefix(path.segments), + _ => (), } - } + }); + } - for arm in arms { - if arm.guard.is_some() { - // Guards mean that this case probably isn't exhaustively covered. Technically - // this is incorrect, as we should really check whether each variant is exhaustively - // covered by the set of guards that cover it, but that's really hard to do. - continue; - } - if let PatKind::Path(ref path) = arm.pat.kind { - if let QPath::Resolved(_, p) = path { - missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); - } - } else if let PatKind::TupleStruct(QPath::Resolved(_, p), ref patterns, ..) = arm.pat.kind { - // Some simple checks for exhaustive patterns. - // There is a room for improvements to detect more cases, - // but it can be more expensive to do so. - let is_pattern_exhaustive = - |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None)); - if patterns.iter().all(is_pattern_exhaustive) { - missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id())); + let format_suggestion = |variant: &VariantDef| { + format!( + "{}{}{}{}", + if let Some(ident) = wildcard_ident { + format!("{} @ ", ident.name) + } else { + String::new() + }, + if let CommonPrefixSearcher::Path(path_prefix) = path_prefix { + let mut s = String::new(); + for seg in path_prefix { + s.push_str(&seg.ident.as_str()); + s.push_str("::"); } + s + } else { + let mut s = cx.tcx.def_path_str(adt_def.did); + s.push_str("::"); + s + }, + variant.ident.name, + match variant.ctor_kind { + CtorKind::Fn if variant.fields.len() == 1 => "(_)", + CtorKind::Fn => "(..)", + CtorKind::Const => "", + CtorKind::Fictive => "{ .. }", } - } - - let mut suggestion: Vec<String> = missing_variants - .iter() - .map(|v| { - let suffix = match v.ctor_kind { - CtorKind::Fn => "(..)", - CtorKind::Const | CtorKind::Fictive => "", - }; - let ident_str = if let Some(ident) = wildcard_ident { - format!("{} @ ", ident.name) - } else { - String::new() - }; - // This path assumes that the enum type is imported into scope. - format!("{}{}{}", ident_str, cx.tcx.def_path_str(v.def_id), suffix) - }) - .collect(); - - if suggestion.is_empty() { - return; - } - - let mut message = "wildcard match will miss any future added variants"; + ) + }; - if let ty::Adt(def, _) = ty.kind() { - if def.is_variant_list_non_exhaustive() { - message = "match on non-exhaustive enum doesn't explicitly match all known variants"; - suggestion.push(String::from("_")); - } - } + match missing_variants.as_slice() { + [] => (), + [x] if !adt_def.is_variant_list_non_exhaustive() && !is_doc_hidden(cx, x) => span_lint_and_sugg( + cx, + MATCH_WILDCARD_FOR_SINGLE_VARIANTS, + wildcard_span, + "wildcard matches only a single variant and will also match any future added variants", + "try this", + format_suggestion(x), + Applicability::MaybeIncorrect, + ), + variants => { + let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect(); + let message = if adt_def.is_variant_list_non_exhaustive() { + suggestions.push("_".into()); + "wildcard matches known variants and will also match future added variants" + } else { + "wildcard match will also match any future added variants" + }; - if suggestion.len() == 1 { - // No need to check for non-exhaustive enum as in that case len would be greater than 1 span_lint_and_sugg( cx, - MATCH_WILDCARD_FOR_SINGLE_VARIANTS, + WILDCARD_ENUM_MATCH_ARM, wildcard_span, message, "try this", - suggestion[0].clone(), + suggestions.join(" | "), Applicability::MaybeIncorrect, ) - }; - - span_lint_and_sugg( - cx, - WILDCARD_ENUM_MATCH_ARM, - wildcard_span, - message, - "try this", - suggestion.join(" | "), - Applicability::MaybeIncorrect, - ) - } + }, + }; } // If the block contains only a `panic!` macro (as expression or statement) fn is_panic_block(block: &Block<'_>) -> bool { match (&block.expr, block.stmts.len(), block.stmts.first()) { - (&Some(ref exp), 0, _) => { - is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none() - }, + (&Some(exp), 0, _) => is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none(), (&None, 1, Some(stmt)) => { is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none() }, @@ -1080,7 +1163,7 @@ fn is_panic_block(block: &Block<'_>) -> bool { fn check_match_ref_pats(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if has_only_ref_pats(arms) { let mut suggs = Vec::with_capacity(arms.len() + 1); - let (title, msg) = if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = ex.kind { + let (title, msg) = if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = ex.kind { let span = ex.span.source_callsite(); suggs.push((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string())); ( @@ -1097,7 +1180,7 @@ fn check_match_ref_pats(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], e }; suggs.extend(arms.iter().filter_map(|a| { - if let PatKind::Ref(ref refp, _) = a.pat.kind { + if let PatKind::Ref(refp, _) = a.pat.kind { Some((a.pat.span, snippet(cx, refp.span, "..").to_string())) } else { None @@ -1114,10 +1197,10 @@ fn check_match_ref_pats(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], e fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { - let arm_ref: Option<BindingAnnotation> = if is_none_arm(&arms[0]) { - is_ref_some_arm(&arms[1]) - } else if is_none_arm(&arms[1]) { - is_ref_some_arm(&arms[0]) + let arm_ref: Option<BindingAnnotation> = if is_none_arm(cx, &arms[0]) { + is_ref_some_arm(cx, &arms[1]) + } else if is_none_arm(cx, &arms[1]) { + is_ref_some_arm(cx, &arms[0]) } else { None }; @@ -1166,7 +1249,7 @@ fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp fn check_wild_in_or_pats(cx: &LateContext<'_>, arms: &[Arm<'_>]) { for arm in arms { - if let PatKind::Or(ref fields) = arm.pat.kind { + if let PatKind::Or(fields) = arm.pat.kind { // look for multiple fields in this arm that contains at least one Wild pattern if fields.len() > 1 && fields.iter().any(is_wild) { span_lint_and_help( @@ -1232,7 +1315,7 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr // strip potential borrows (#6503), but only if the type is a reference let mut ex_new = ex; if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind { - if let ty::Ref(..) = cx.typeck_results().expr_ty(&ex_inner).kind() { + if let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind() { ex_new = ex_inner; } }; @@ -1284,6 +1367,7 @@ fn find_bool_lit(ex: &ExprKind<'_>, desugared: bool) -> Option<bool> { } } +#[allow(clippy::too_many_lines)] fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) { if in_macro(expr.span) || arms.len() != 1 || is_refutable(cx, arms[0].pat) { return; @@ -1308,7 +1392,7 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A let matched_vars = ex.span; let bind_names = arms[0].pat.span; - let match_body = remove_blocks(&arms[0].body); + let match_body = remove_blocks(arms[0].body); let mut snippet_body = if match_body.span.from_expansion() { Sugg::hir_with_macro_callsite(cx, match_body, "..").to_string() } else { @@ -1319,13 +1403,13 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A match match_body.kind { ExprKind::Block(block, _) => { // macro + expr_ty(body) == () - if block.span.from_expansion() && cx.typeck_results().expr_ty(&match_body).is_unit() { + if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() { snippet_body.push(';'); } }, _ => { // expr_ty(body) == () - if cx.typeck_results().expr_ty(&match_body).is_unit() { + if cx.typeck_results().expr_ty(match_body).is_unit() { snippet_body.push(';'); } }, @@ -1358,7 +1442,18 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); cbrace_start = format!("{{\n{}", indent); } - }; + } + // If the parent is already an arm, and the body is another match statement, + // we need curly braces around suggestion + let parent_node_id = cx.tcx.hir().get_parent_node(expr.hir_id); + if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) { + if let ExprKind::Match(..) = arm.body.kind { + cbrace_end = format!("\n{}}}", indent); + // Fix body indent due to the match + indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); + cbrace_start = format!("{{\n{}", indent); + } + } ( expr.span, format!( @@ -1399,8 +1494,8 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A /// Returns true if the `ex` match expression is in a local (`let`) statement fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'a>> { + let map = &cx.tcx.hir(); if_chain! { - let map = &cx.tcx.hir(); if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id)); if let Some(Node::Local(parent_let_expr)) = map.find(map.get_parent_node(parent_arm_expr.hir_id)); then { @@ -1413,11 +1508,8 @@ fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<' /// Gets all arms that are unbounded `PatRange`s. fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<Constant>> { arms.iter() - .flat_map(|arm| { - if let Arm { - ref pat, guard: None, .. - } = *arm - { + .filter_map(|arm| { + if let Arm { pat, guard: None, .. } = *arm { if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind { let lhs = match lhs { Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0, @@ -1437,7 +1529,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) }); } - if let PatKind::Lit(ref value) = pat.kind { + if let PatKind::Lit(value) = pat.kind { let value = constant(cx, cx.typeck_results(), value)?.0; return Some(SpannedRange { span: pat.span, @@ -1484,28 +1576,28 @@ fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges { fn is_unit_expr(expr: &Expr<'_>) -> bool { match expr.kind { - ExprKind::Tup(ref v) if v.is_empty() => true, - ExprKind::Block(ref b, _) if b.stmts.is_empty() && b.expr.is_none() => true, + ExprKind::Tup(v) if v.is_empty() => true, + ExprKind::Block(b, _) if b.stmts.is_empty() && b.expr.is_none() => true, _ => false, } } // Checks if arm has the form `None => None` -fn is_none_arm(arm: &Arm<'_>) -> bool { - matches!(arm.pat.kind, PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE)) +fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { + matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone)) } // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`) -fn is_ref_some_arm(arm: &Arm<'_>) -> Option<BindingAnnotation> { +fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<BindingAnnotation> { if_chain! { - if let PatKind::TupleStruct(ref path, ref pats, _) = arm.pat.kind; - if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME); - if let PatKind::Binding(rb, .., ident, _) = pats[0].kind; + if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind; + if is_lang_ctor(cx, qpath, OptionSome); + if let PatKind::Binding(rb, .., ident, _) = first_pat.kind; if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut; - if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).kind; + if let ExprKind::Call(e, args) = remove_blocks(arm.body).kind; if let ExprKind::Path(ref some_path) = e.kind; - if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1; - if let ExprKind::Path(QPath::Resolved(_, ref path2)) = args[0].kind; + if is_lang_ctor(cx, some_path, OptionSome) && args.len() == 1; + if let ExprKind::Path(QPath::Resolved(_, path2)) = args[0].kind; if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name; then { return Some(rb) @@ -1587,7 +1679,7 @@ where values.sort(); - for (a, b) in values.iter().zip(values.iter().skip(1)) { + for (a, b) in iter::zip(&values, values.iter().skip(1)) { match (a, b) { (&Kind::Start(_, ra), &Kind::End(_, rb)) => { if ra.node != rb.node { @@ -1597,7 +1689,7 @@ where (&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (), _ => { // skip if the range `a` is completely included into the range `b` - if let Ordering::Equal | Ordering::Less = a.cmp(&b) { + if let Ordering::Equal | Ordering::Less = a.cmp(b) { let kind_a = Kind::End(a.range().node.1, a.range()); let kind_b = Kind::End(b.range().node.1, b.range()); if let Ordering::Equal | Ordering::Greater = kind_a.cmp(&kind_b) { @@ -1614,47 +1706,215 @@ where mod redundant_pattern_match { use super::REDUNDANT_PATTERN_MATCHING; - use crate::utils::{match_qpath, match_trait_method, paths, snippet, span_lint_and_then}; + use clippy_utils::diagnostics::span_lint_and_then; + use clippy_utils::source::{snippet, snippet_with_applicability}; + use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, is_type_lang_item, match_type}; + use clippy_utils::{is_lang_ctor, is_qpath_def_path, is_trait_method, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; + use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; - use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind, QPath}; + use rustc_hir::LangItem::{OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk}; + use rustc_hir::{ + intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}, + Arm, Block, Expr, ExprKind, LangItem, MatchSource, Node, PatKind, QPath, + }; use rustc_lint::LateContext; + use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; use rustc_span::sym; pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Match(op, arms, ref match_source) = &expr.kind { match match_source { MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), - MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms, "if"), - MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, arms, "while"), + MatchSource::IfLetDesugar { contains_else_clause } => { + find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause) + }, + MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, &arms[0], "while", false), _ => {}, } } } + /// Checks if the drop order for a type matters. Some std types implement drop solely to + /// deallocate memory. For these types, and composites containing them, changing the drop order + /// won't result in any observable side effects. + fn type_needs_ordered_drop(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + type_needs_ordered_drop_inner(cx, ty, &mut FxHashSet::default()) + } + + fn type_needs_ordered_drop_inner(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &mut FxHashSet<Ty<'tcx>>) -> bool { + if !seen.insert(ty) { + return false; + } + if !ty.needs_drop(cx.tcx, cx.param_env) { + false + } else if !cx + .tcx + .lang_items() + .drop_trait() + .map_or(false, |id| implements_trait(cx, ty, id, &[])) + { + // This type doesn't implement drop, so no side effects here. + // Check if any component type has any. + match ty.kind() { + ty::Tuple(_) => ty.tuple_fields().any(|ty| type_needs_ordered_drop_inner(cx, ty, seen)), + ty::Array(ty, _) => type_needs_ordered_drop_inner(cx, ty, seen), + ty::Adt(adt, subs) => adt + .all_fields() + .map(|f| f.ty(cx.tcx, subs)) + .any(|ty| type_needs_ordered_drop_inner(cx, ty, seen)), + _ => true, + } + } + // Check for std types which implement drop, but only for memory allocation. + else if is_type_diagnostic_item(cx, ty, sym::vec_type) + || is_type_lang_item(cx, ty, LangItem::OwnedBox) + || is_type_diagnostic_item(cx, ty, sym::Rc) + || is_type_diagnostic_item(cx, ty, sym::Arc) + || is_type_diagnostic_item(cx, ty, sym::cstring_type) + || match_type(cx, ty, &paths::BTREEMAP) + || match_type(cx, ty, &paths::LINKED_LIST) + || match_type(cx, ty, &paths::WEAK_RC) + || match_type(cx, ty, &paths::WEAK_ARC) + { + // Check all of the generic arguments. + if let ty::Adt(_, subs) = ty.kind() { + subs.types().any(|ty| type_needs_ordered_drop_inner(cx, ty, seen)) + } else { + true + } + } else { + true + } + } + + // Extract the generic arguments out of a type + fn try_get_generic_ty(ty: Ty<'_>, index: usize) -> Option<Ty<'_>> { + if_chain! { + if let ty::Adt(_, subs) = ty.kind(); + if let Some(sub) = subs.get(index); + if let GenericArgKind::Type(sub_ty) = sub.unpack(); + then { + Some(sub_ty) + } else { + None + } + } + } + + // Checks if there are any temporaries created in the given expression for which drop order + // matters. + fn temporaries_need_ordered_drop(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + struct V<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + res: bool, + } + impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> { + type Map = ErasedMap<'tcx>; + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + match expr.kind { + // Taking the reference of a value leaves a temporary + // e.g. In `&String::new()` the string is a temporary value. + // Remaining fields are temporary values + // e.g. In `(String::new(), 0).1` the string is a temporary value. + ExprKind::AddrOf(_, _, expr) | ExprKind::Field(expr, _) => { + if !matches!(expr.kind, ExprKind::Path(_)) { + if type_needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(expr)) { + self.res = true; + } else { + self.visit_expr(expr); + } + } + }, + // the base type is alway taken by reference. + // e.g. In `(vec![0])[0]` the vector is a temporary value. + ExprKind::Index(base, index) => { + if !matches!(base.kind, ExprKind::Path(_)) { + if type_needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(base)) { + self.res = true; + } else { + self.visit_expr(base); + } + } + self.visit_expr(index); + }, + // Method calls can take self by reference. + // e.g. In `String::new().len()` the string is a temporary value. + ExprKind::MethodCall(_, _, [self_arg, args @ ..], _) => { + if !matches!(self_arg.kind, ExprKind::Path(_)) { + let self_by_ref = self + .cx + .typeck_results() + .type_dependent_def_id(expr.hir_id) + .map_or(false, |id| self.cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref()); + if self_by_ref + && type_needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(self_arg)) + { + self.res = true; + } else { + self.visit_expr(self_arg) + } + } + args.iter().for_each(|arg| self.visit_expr(arg)); + }, + // Either explicitly drops values, or changes control flow. + ExprKind::DropTemps(_) + | ExprKind::Ret(_) + | ExprKind::Break(..) + | ExprKind::Yield(..) + | ExprKind::Block(Block { expr: None, .. }, _) + | ExprKind::Loop(..) => (), + + // Only consider the final expression. + ExprKind::Block(Block { expr: Some(expr), .. }, _) => self.visit_expr(expr), + + _ => walk_expr(self, expr), + } + } + } + + let mut v = V { cx, res: false }; + v.visit_expr(expr); + v.res + } + fn find_sugg_for_if_let<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, - op: &Expr<'_>, - arms: &[Arm<'_>], + op: &'tcx Expr<'tcx>, + arm: &Arm<'_>, keyword: &'static str, + has_else: bool, ) { - let good_method = match arms[0].pat.kind { - PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => { - if let PatKind::Wild = patterns[0].kind { - if match_qpath(path, &paths::RESULT_OK) { - "is_ok()" - } else if match_qpath(path, &paths::RESULT_ERR) { - "is_err()" - } else if match_qpath(path, &paths::OPTION_SOME) { - "is_some()" - } else if match_qpath(path, &paths::POLL_READY) { - "is_ready()" - } else if match_qpath(path, &paths::IPADDR_V4) { - "is_ipv4()" - } else if match_qpath(path, &paths::IPADDR_V6) { - "is_ipv6()" + // also look inside refs + let mut kind = &arm.pat.kind; + // if we have &None for example, peel it so we can detect "if let None = x" + if let PatKind::Ref(inner, _mutability) = kind { + kind = &inner.kind; + } + let op_ty = cx.typeck_results().expr_ty(op); + // Determine which function should be used, and the type contained by the corresponding + // variant. + let (good_method, inner_ty) = match kind { + PatKind::TupleStruct(ref path, [sub_pat], _) => { + if let PatKind::Wild = sub_pat.kind { + if is_lang_ctor(cx, path, ResultOk) { + ("is_ok()", try_get_generic_ty(op_ty, 0).unwrap_or(op_ty)) + } else if is_lang_ctor(cx, path, ResultErr) { + ("is_err()", try_get_generic_ty(op_ty, 1).unwrap_or(op_ty)) + } else if is_lang_ctor(cx, path, OptionSome) { + ("is_some()", op_ty) + } else if is_lang_ctor(cx, path, PollReady) { + ("is_ready()", op_ty) + } else if is_qpath_def_path(cx, path, sub_pat.hir_id, &paths::IPADDR_V4) { + ("is_ipv4()", op_ty) + } else if is_qpath_def_path(cx, path, sub_pat.hir_id, &paths::IPADDR_V6) { + ("is_ipv6()", op_ty) } else { return; } @@ -1663,23 +1923,42 @@ mod redundant_pattern_match { } }, PatKind::Path(ref path) => { - if match_qpath(path, &paths::OPTION_NONE) { + let method = if is_lang_ctor(cx, path, OptionNone) { "is_none()" - } else if match_qpath(path, &paths::POLL_PENDING) { + } else if is_lang_ctor(cx, path, PollPending) { "is_pending()" } else { return; - } + }; + // `None` and `Pending` don't have an inner type. + (method, cx.tcx.types.unit) }, _ => return, }; + // If this is the last expression in a block or there is an else clause then the whole + // type needs to be considered, not just the inner type of the branch being matched on. + // Note the last expression in a block is dropped after all local bindings. + let check_ty = if has_else + || (keyword == "if" && matches!(cx.tcx.hir().parent_iter(expr.hir_id).next(), Some((_, Node::Block(..))))) + { + op_ty + } else { + inner_ty + }; + + // All temporaries created in the scrutinee expression are dropped at the same time as the + // scrutinee would be, so they have to be considered as well. + // e.g. in `if let Some(x) = foo.lock().unwrap().baz.as_ref() { .. }` the lock will be held + // for the duration if body. + let needs_drop = type_needs_ordered_drop(cx, check_ty) || temporaries_need_ordered_drop(cx, op); + // check that `while_let_on_iterator` lint does not trigger if_chain! { if keyword == "while"; if let ExprKind::MethodCall(method_path, _, _, _) = op.kind; if method_path.ident.name == sym::next; - if match_trait_method(cx, op, &paths::ITERATOR); + if is_trait_method(cx, op, sym::Iterator); then { return; } @@ -1692,7 +1971,7 @@ mod redundant_pattern_match { span_lint_and_then( cx, REDUNDANT_PATTERN_MATCHING, - arms[0].pat.span, + arm.pat.span, &format!("redundant pattern matching, consider using `{}`", good_method), |diag| { // while let ... = ... { ... } @@ -1706,12 +1985,20 @@ mod redundant_pattern_match { // while let ... = ... { ... } // ^^^^^^^^^^^^^^^^^^^ let span = expr_span.until(op_span.shrink_to_hi()); - diag.span_suggestion( - span, - "try this", - format!("{} {}.{}", keyword, snippet(cx, op_span, "_"), good_method), - Applicability::MachineApplicable, // snippet - ); + + let mut app = if needs_drop { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; + let sugg = snippet_with_applicability(cx, op_span, "_", &mut app); + + diag.span_suggestion(span, "try this", format!("{} {}.{}", keyword, sugg, good_method), app); + + if needs_drop { + diag.note("this will change drop order of the result, as well as all temporaries"); + diag.note("add `#[allow(clippy::redundant_pattern_matching)]` if this is important"); + } }, ); } @@ -1722,11 +2009,12 @@ mod redundant_pattern_match { let found_good_method = match node_pair { ( - PatKind::TupleStruct(ref path_left, ref patterns_left, _), - PatKind::TupleStruct(ref path_right, ref patterns_right, _), + PatKind::TupleStruct(ref path_left, patterns_left, _), + PatKind::TupleStruct(ref path_right, patterns_right, _), ) if patterns_left.len() == 1 && patterns_right.len() == 1 => { if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) { find_good_method_for_match( + cx, arms, path_left, path_right, @@ -1737,6 +2025,7 @@ mod redundant_pattern_match { ) .or_else(|| { find_good_method_for_match( + cx, arms, path_left, path_right, @@ -1750,12 +2039,13 @@ mod redundant_pattern_match { None } }, - (PatKind::TupleStruct(ref path_left, ref patterns, _), PatKind::Path(ref path_right)) - | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, ref patterns, _)) + (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right)) + | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _)) if patterns.len() == 1 => { if let PatKind::Wild = patterns[0].kind { find_good_method_for_match( + cx, arms, path_left, path_right, @@ -1766,6 +2056,7 @@ mod redundant_pattern_match { ) .or_else(|| { find_good_method_for_match( + cx, arms, path_left, path_right, @@ -1806,7 +2097,9 @@ mod redundant_pattern_match { } } + #[allow(clippy::too_many_arguments)] fn find_good_method_for_match<'a>( + cx: &LateContext<'_>, arms: &[Arm<'_>], path_left: &QPath<'_>, path_right: &QPath<'_>, @@ -1815,9 +2108,13 @@ mod redundant_pattern_match { should_be_left: &'a str, should_be_right: &'a str, ) -> Option<&'a str> { - let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) { + let body_node_pair = if is_qpath_def_path(cx, path_left, arms[0].pat.hir_id, expected_left) + && is_qpath_def_path(cx, path_right, arms[1].pat.hir_id, expected_right) + { (&(*arms[0].body).kind, &(*arms[1].body).kind) - } else if match_qpath(path_right, expected_left) && match_qpath(path_left, expected_right) { + } else if is_qpath_def_path(cx, path_right, arms[1].pat.hir_id, expected_left) + && is_qpath_def_path(cx, path_left, arms[0].pat.hir_id, expected_right) + { (&(*arms[1].body).kind, &(*arms[0].body).kind) } else { return None; @@ -1873,10 +2170,10 @@ fn test_overlapping() { /// Implementation of `MATCH_SAME_ARMS`. fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) { - if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.kind { + if let ExprKind::Match(_, arms, MatchSource::Normal) = expr.kind { let hash = |&(_, arm): &(usize, &Arm<'_>)| -> u64 { let mut h = SpanlessHash::new(cx); - h.hash_expr(&arm.body); + h.hash_expr(arm.body); h.finish() }; @@ -1884,7 +2181,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) { let min_index = usize::min(lindex, rindex); let max_index = usize::max(lindex, rindex); - let mut local_map: FxHashMap<HirId, HirId> = FxHashMap::default(); + let mut local_map: HirIdMap<HirId> = HirIdMap::default(); let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| { if_chain! { if let Some(a_id) = path_to_local(a); @@ -1912,7 +2209,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) { (min_index..=max_index).all(|index| arms[index].guard.is_none()) && SpanlessEq::new(cx) .expr_fallback(eq_fallback) - .eq_expr(&lhs.body, &rhs.body) + .eq_expr(lhs.body, rhs.body) // these checks could be removed to allow unused bindings && bindings_eq(lhs.pat, local_map.keys().copied().collect()) && bindings_eq(rhs.pat, local_map.values().copied().collect()) @@ -1968,7 +2265,7 @@ fn pat_contains_local(pat: &Pat<'_>, id: HirId) -> bool { } /// Returns true if all the bindings in the `Pat` are in `ids` and vice versa -fn bindings_eq(pat: &Pat<'_>, mut ids: FxHashSet<HirId>) -> bool { +fn bindings_eq(pat: &Pat<'_>, mut ids: HirIdSet) -> bool { let mut result = true; pat.each_binding_or_first(&mut |_, id, _, _| result &= ids.remove(&id)); result && ids.is_empty() diff --git a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs index c71c2ee7d7..a735c616f6 100644 --- a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs +++ b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs @@ -1,10 +1,12 @@ -use crate::utils::{match_def_path, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::ty::walk_ptrs_ty_depth; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; - use std::iter; declare_clippy_lint! { @@ -32,7 +34,7 @@ declare_lint_pass!(MemDiscriminant => [MEM_DISCRIMINANT_NON_ENUM]); impl<'tcx> LateLintPass<'tcx> for MemDiscriminant { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Call(ref func, ref func_args) = expr.kind; + if let ExprKind::Call(func, func_args) = expr.kind; // is `mem::discriminant` if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); @@ -57,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for MemDiscriminant { let mut derefs_needed = ptr_depth; let mut cur_expr = param; while derefs_needed > 0 { - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref inner_expr) = cur_expr.kind { + if let ExprKind::AddrOf(BorrowKind::Ref, _, inner_expr) = cur_expr.kind { derefs_needed -= 1; cur_expr = inner_expr; } else { diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs index d34f9761e2..a28cb5f32f 100644 --- a/src/tools/clippy/clippy_lints/src/mem_forget.rs +++ b/src/tools/clippy/clippy_lints/src/mem_forget.rs @@ -1,4 +1,5 @@ -use crate::utils::{match_def_path, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{match_def_path, paths}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -27,7 +28,7 @@ declare_lint_pass!(MemForget => [MEM_FORGET]); impl<'tcx> LateLintPass<'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Call(ref path_expr, ref args) = e.kind { + if let ExprKind::Call(path_expr, args) = e.kind { if let ExprKind::Path(ref qpath) = path_expr.kind { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { if match_def_path(cx, def_id, &paths::MEM_FORGET) { diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs index 19087b0207..183daee361 100644 --- a/src/tools/clippy/clippy_lints/src/mem_replace.rs +++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs @@ -1,9 +1,10 @@ -use crate::utils::{ - in_macro, match_def_path, match_qpath, meets_msrv, paths, snippet, snippet_with_applicability, span_lint_and_help, - span_lint_and_sugg, span_lint_and_then, -}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::{in_macro, is_diag_trait_item, is_lang_ctor, match_def_path, meets_msrv, msrvs, paths}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; +use rustc_hir::LangItem::OptionNone; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -101,21 +102,21 @@ impl_lint_pass!(MemReplace => fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { if let ExprKind::Path(ref replacement_qpath) = src.kind { // Check that second argument is `Option::None` - if match_qpath(replacement_qpath, &paths::OPTION_NONE) { + if is_lang_ctor(cx, replacement_qpath, OptionNone) { // Since this is a late pass (already type-checked), // and we already know that the second argument is an // `Option`, we do not need to check the first // argument's type. All that's left is to get // replacee's path. let replaced_path = match dest.kind { - ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, ref replaced) => { - if let ExprKind::Path(QPath::Resolved(None, ref replaced_path)) = replaced.kind { + ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => { + if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind { replaced_path } else { return; } }, - ExprKind::Path(QPath::Resolved(None, ref replaced_path)) => replaced_path, + ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path, _ => return, }; @@ -160,7 +161,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' } if_chain! { - if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind; + if let ExprKind::Call(repl_func, repl_args) = src.kind; if repl_args.is_empty(); if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); @@ -194,38 +195,66 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' } } -fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { - if let ExprKind::Call(ref repl_func, _) = src.kind { - if_chain! { - if !in_external_macro(cx.tcx.sess, expr_span); - if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; - if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); - if match_def_path(cx, repl_def_id, &paths::DEFAULT_TRAIT_METHOD); - then { - span_lint_and_then( - cx, - MEM_REPLACE_WITH_DEFAULT, - expr_span, - "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`", - |diag| { - if !in_macro(expr_span) { - let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, "")); +/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent" +/// constructor from the std library +fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool { + let std_types_symbols = &[ + sym::string_type, + sym::vec_type, + sym::vecdeque_type, + sym::LinkedList, + sym::hashmap_type, + sym::BTreeMap, + sym::hashset_type, + sym::BTreeSet, + sym::BinaryHeap, + ]; - diag.span_suggestion( - expr_span, - "consider using", - suggestion, - Applicability::MachineApplicable - ); - } - } - ); + if let QPath::TypeRelative(_, method) = path { + if method.ident.name == sym::new { + if let Some(impl_did) = cx.tcx.impl_of_method(def_id) { + if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() { + return std_types_symbols + .iter() + .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did)); + } } } } + false } -const MEM_REPLACE_WITH_DEFAULT_MSRV: RustcVersion = RustcVersion::new(1, 40, 0); +fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { + if_chain! { + if let ExprKind::Call(repl_func, _) = src.kind; + if !in_external_macro(cx.tcx.sess, expr_span); + if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; + if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); + if is_diag_trait_item(cx, repl_def_id, sym::Default) + || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath); + + then { + span_lint_and_then( + cx, + MEM_REPLACE_WITH_DEFAULT, + expr_span, + "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`", + |diag| { + if !in_macro(expr_span) { + let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, "")); + + diag.span_suggestion( + expr_span, + "consider using", + suggestion, + Applicability::MachineApplicable + ); + } + } + ); + } + } +} pub struct MemReplace { msrv: Option<RustcVersion>, @@ -242,15 +271,15 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { // Check that `expr` is a call to `mem::replace()` - if let ExprKind::Call(ref func, ref func_args) = expr.kind; + if let ExprKind::Call(func, func_args) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::MEM_REPLACE); - if let [dest, src] = &**func_args; + if let [dest, src] = func_args; then { check_replace_option_with_none(cx, src, dest, expr.span); check_replace_with_uninit(cx, src, dest, expr.span); - if meets_msrv(self.msrv.as_ref(), &MEM_REPLACE_WITH_DEFAULT_MSRV) { + if meets_msrv(self.msrv.as_ref(), &msrvs::MEM_TAKE) { check_replace_with_default(cx, src, dest, expr.span); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs index 5decb81d9f..287bff886b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs @@ -1,101 +1,82 @@ use super::{contains_return, BIND_INSTEAD_OF_MAP}; -use crate::utils::{ - in_macro, match_qpath, match_type, method_calls, multispan_sugg_with_applicability, paths, remove_blocks, snippet, - snippet_with_macro_callsite, span_lint_and_sugg, span_lint_and_then, visitors::find_all_ret_expressions, -}; +use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::{snippet, snippet_with_macro_callsite}; +use clippy_utils::{in_macro, remove_blocks, visitors::find_all_ret_expressions}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::{LangItem, QPath}; use rustc_lint::LateContext; +use rustc_middle::ty::DefIdTree; use rustc_span::Span; pub(crate) struct OptionAndThenSome; impl BindInsteadOfMap for OptionAndThenSome { - const TYPE_NAME: &'static str = "Option"; - const TYPE_QPATH: &'static [&'static str] = &paths::OPTION; - + const VARIANT_LANG_ITEM: LangItem = LangItem::OptionSome; const BAD_METHOD_NAME: &'static str = "and_then"; - const BAD_VARIANT_NAME: &'static str = "Some"; - const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::OPTION_SOME; - const GOOD_METHOD_NAME: &'static str = "map"; } pub(crate) struct ResultAndThenOk; impl BindInsteadOfMap for ResultAndThenOk { - const TYPE_NAME: &'static str = "Result"; - const TYPE_QPATH: &'static [&'static str] = &paths::RESULT; - + const VARIANT_LANG_ITEM: LangItem = LangItem::ResultOk; const BAD_METHOD_NAME: &'static str = "and_then"; - const BAD_VARIANT_NAME: &'static str = "Ok"; - const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::RESULT_OK; - const GOOD_METHOD_NAME: &'static str = "map"; } pub(crate) struct ResultOrElseErrInfo; impl BindInsteadOfMap for ResultOrElseErrInfo { - const TYPE_NAME: &'static str = "Result"; - const TYPE_QPATH: &'static [&'static str] = &paths::RESULT; - + const VARIANT_LANG_ITEM: LangItem = LangItem::ResultErr; const BAD_METHOD_NAME: &'static str = "or_else"; - const BAD_VARIANT_NAME: &'static str = "Err"; - const BAD_VARIANT_QPATH: &'static [&'static str] = &paths::RESULT_ERR; - const GOOD_METHOD_NAME: &'static str = "map_err"; } pub(crate) trait BindInsteadOfMap { - const TYPE_NAME: &'static str; - const TYPE_QPATH: &'static [&'static str]; - + const VARIANT_LANG_ITEM: LangItem; const BAD_METHOD_NAME: &'static str; - const BAD_VARIANT_NAME: &'static str; - const BAD_VARIANT_QPATH: &'static [&'static str]; - const GOOD_METHOD_NAME: &'static str; - fn no_op_msg() -> String { - format!( + fn no_op_msg(cx: &LateContext<'_>) -> Option<String> { + let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?; + let item_id = cx.tcx.parent(variant_id)?; + Some(format!( "using `{}.{}({})`, which is a no-op", - Self::TYPE_NAME, + cx.tcx.item_name(item_id), Self::BAD_METHOD_NAME, - Self::BAD_VARIANT_NAME - ) + cx.tcx.item_name(variant_id), + )) } - fn lint_msg() -> String { - format!( + fn lint_msg(cx: &LateContext<'_>) -> Option<String> { + let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?; + let item_id = cx.tcx.parent(variant_id)?; + Some(format!( "using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`", - Self::TYPE_NAME, + cx.tcx.item_name(item_id), Self::BAD_METHOD_NAME, - Self::BAD_VARIANT_NAME, + cx.tcx.item_name(variant_id), Self::GOOD_METHOD_NAME - ) + )) } fn lint_closure_autofixable( cx: &LateContext<'_>, expr: &hir::Expr<'_>, - args: &[hir::Expr<'_>], + recv: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>, closure_args_span: Span, ) -> bool { if_chain! { - if let hir::ExprKind::Call(ref some_expr, ref some_args) = closure_expr.kind; - if let hir::ExprKind::Path(ref qpath) = some_expr.kind; - if match_qpath(qpath, Self::BAD_VARIANT_QPATH); - if some_args.len() == 1; + if let hir::ExprKind::Call(some_expr, [inner_expr]) = closure_expr.kind; + if let hir::ExprKind::Path(QPath::Resolved(_, path)) = some_expr.kind; + if Self::is_variant(cx, path.res); + if !contains_return(inner_expr); + if let Some(msg) = Self::lint_msg(cx); then { - let inner_expr = &some_args[0]; - - if contains_return(inner_expr) { - return false; - } - let some_inner_snip = if inner_expr.span.from_expansion() { snippet_with_macro_callsite(cx, inner_expr.span, "_") } else { @@ -103,13 +84,13 @@ pub(crate) trait BindInsteadOfMap { }; let closure_args_snip = snippet(cx, closure_args_span, ".."); - let option_snip = snippet(cx, args[0].span, ".."); + let option_snip = snippet(cx, recv.span, ".."); let note = format!("{}.{}({} {})", option_snip, Self::GOOD_METHOD_NAME, closure_args_snip, some_inner_snip); span_lint_and_sugg( cx, BIND_INSTEAD_OF_MAP, expr.span, - Self::lint_msg().as_ref(), + &msg, "try this", note, Applicability::MachineApplicable, @@ -126,68 +107,84 @@ pub(crate) trait BindInsteadOfMap { let can_sugg: bool = find_all_ret_expressions(cx, closure_expr, |ret_expr| { if_chain! { if !in_macro(ret_expr.span); - if let hir::ExprKind::Call(ref func_path, ref args) = ret_expr.kind; - if let hir::ExprKind::Path(ref qpath) = func_path.kind; - if match_qpath(qpath, Self::BAD_VARIANT_QPATH); - if args.len() == 1; - if !contains_return(&args[0]); + if let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind; + if let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind; + if Self::is_variant(cx, path.res); + if !contains_return(arg); then { - suggs.push((ret_expr.span, args[0].span.source_callsite())); + suggs.push((ret_expr.span, arg.span.source_callsite())); true } else { false } } }); - - if can_sugg { - span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, Self::lint_msg().as_ref(), |diag| { - multispan_sugg_with_applicability( - diag, - "try this", - Applicability::MachineApplicable, - std::iter::once((*method_calls(expr, 1).2.get(0).unwrap(), Self::GOOD_METHOD_NAME.into())).chain( - suggs - .into_iter() - .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())), - ), - ) - }); - } - can_sugg + let (span, msg) = if_chain! { + if can_sugg; + if let hir::ExprKind::MethodCall(_, span, ..) = expr.kind; + if let Some(msg) = Self::lint_msg(cx); + then { (span, msg) } else { return false; } + }; + span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| { + multispan_sugg_with_applicability( + diag, + "try this", + Applicability::MachineApplicable, + std::iter::once((span, Self::GOOD_METHOD_NAME.into())).chain( + suggs + .into_iter() + .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())), + ), + ) + }); + true } /// Lint use of `_.and_then(|x| Some(y))` for `Option`s - fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) -> bool { - if !match_type(cx, cx.typeck_results().expr_ty(&args[0]), Self::TYPE_QPATH) { - return false; + fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool { + if_chain! { + if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def(); + if let Ok(vid) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM); + if Some(adt.did) == cx.tcx.parent(vid); + then {} else { return false; } } - match args[1].kind { + match arg.kind { hir::ExprKind::Closure(_, _, body_id, closure_args_span, _) => { let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); - if Self::lint_closure_autofixable(cx, expr, args, closure_expr, closure_args_span) { + if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, closure_args_span) { true } else { Self::lint_closure(cx, expr, closure_expr) } }, // `_.and_then(Some)` case, which is no-op. - hir::ExprKind::Path(ref qpath) if match_qpath(qpath, Self::BAD_VARIANT_QPATH) => { - span_lint_and_sugg( - cx, - BIND_INSTEAD_OF_MAP, - expr.span, - Self::no_op_msg().as_ref(), - "use the expression directly", - snippet(cx, args[0].span, "..").into(), - Applicability::MachineApplicable, - ); + hir::ExprKind::Path(QPath::Resolved(_, path)) if Self::is_variant(cx, path.res) => { + if let Some(msg) = Self::no_op_msg(cx) { + span_lint_and_sugg( + cx, + BIND_INSTEAD_OF_MAP, + expr.span, + &msg, + "use the expression directly", + snippet(cx, recv.span, "..").into(), + Applicability::MachineApplicable, + ); + } true }, _ => false, } } + + fn is_variant(cx: &LateContext<'_>, res: Res) -> bool { + if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res { + if let Ok(variant_id) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM) { + return cx.tcx.parent(id) == Some(variant_id); + } + } + false + } } diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs index 71a7e195e4..2ad3e673c5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs @@ -1,39 +1,34 @@ -use crate::utils::{is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg}; -use if_chain::if_chain; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_span::sym; use super::BYTES_NTH; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &'tcx [Expr<'tcx>]) { - if_chain! { - if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind; - let ty = cx.typeck_results().expr_ty(&iter_args[0]).peel_refs(); - let caller_type = if is_type_diagnostic_item(cx, ty, sym::string_type) { - Some("String") - } else if ty.is_str() { - Some("str") - } else { - None - }; - if let Some(caller_type) = caller_type; - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - BYTES_NTH, - expr.span, - &format!("called `.byte().nth()` on a `{}`", caller_type), - "try", - format!( - "{}.as_bytes().get({})", - snippet_with_applicability(cx, iter_args[0].span, "..", &mut applicability), - snippet_with_applicability(cx, args[1].span, "..", &mut applicability) - ), - applicability, - ); - } - } +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, n_arg: &'tcx Expr<'tcx>) { + let ty = cx.typeck_results().expr_ty(recv).peel_refs(); + let caller_type = if ty.is_str() { + "str" + } else if is_type_diagnostic_item(cx, ty, sym::string_type) { + "String" + } else { + return; + }; + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + BYTES_NTH, + expr.span, + &format!("called `.byte().nth()` on a `{}`", caller_type), + "try", + format!( + "{}.as_bytes().get({})", + snippet_with_applicability(cx, recv.span, "..", &mut applicability), + snippet_with_applicability(cx, n_arg.span, "..", &mut applicability) + ), + applicability, + ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs new file mode 100644 index 0000000000..514c411876 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs @@ -0,0 +1,54 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{method_chain_args, single_segment_path}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_lint::Lint; +use rustc_middle::ty; +use rustc_span::sym; + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. +pub(super) fn check( + cx: &LateContext<'_>, + info: &crate::methods::BinaryExprInfo<'_>, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprKind::Call(fun, arg_char) = info.other.kind; + if arg_char.len() == 1; + if let hir::ExprKind::Path(ref qpath) = fun.kind; + if let Some(segment) = single_segment_path(qpath); + if segment.ident.name == sym::Some; + then { + let mut applicability = Applicability::MachineApplicable; + let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs(); + + if *self_ty.kind() != ty::Str { + return false; + } + + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}({})", + if info.eq { "" } else { "!" }, + snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), + suggest, + snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)), + applicability, + ); + + return true; + } + } + + false +} diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs new file mode 100644 index 0000000000..4275857757 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs @@ -0,0 +1,44 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::method_chain_args; +use clippy_utils::source::snippet_with_applicability; +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_lint::Lint; + +/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + info: &crate::methods::BinaryExprInfo<'_>, + chain_methods: &[&str], + lint: &'static Lint, + suggest: &str, +) -> bool { + if_chain! { + if let Some(args) = method_chain_args(info.chain, chain_methods); + if let hir::ExprKind::Lit(ref lit) = info.other.kind; + if let ast::LitKind::Char(c) = lit.node; + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{}` method", suggest), + "like this", + format!("{}{}.{}('{}')", + if info.eq { "" } else { "!" }, + snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), + suggest, + c), + applicability, + ); + + true + } else { + false + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs new file mode 100644 index 0000000000..07bbc5ca1b --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp.rs @@ -0,0 +1,13 @@ +use crate::methods::chars_cmp; +use rustc_lint::LateContext; + +use super::CHARS_LAST_CMP; + +/// Checks for the `CHARS_LAST_CMP` lint. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + if chars_cmp::check(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { + true + } else { + chars_cmp::check(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with") + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs new file mode 100644 index 0000000000..c29ee0ec8c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/chars_last_cmp_with_unwrap.rs @@ -0,0 +1,13 @@ +use crate::methods::chars_cmp_with_unwrap; +use rustc_lint::LateContext; + +use super::CHARS_LAST_CMP; + +/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + if chars_cmp_with_unwrap::check(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { + true + } else { + chars_cmp_with_unwrap::check(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs new file mode 100644 index 0000000000..a6701d8830 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp.rs @@ -0,0 +1,8 @@ +use rustc_lint::LateContext; + +use super::CHARS_NEXT_CMP; + +/// Checks for the `CHARS_NEXT_CMP` lint. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + crate::methods::chars_cmp::check(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") +} diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs new file mode 100644 index 0000000000..28ede28e93 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/chars_next_cmp_with_unwrap.rs @@ -0,0 +1,8 @@ +use rustc_lint::LateContext; + +use super::CHARS_NEXT_CMP; + +/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, info: &crate::methods::BinaryExprInfo<'_>) -> bool { + crate::methods::chars_cmp_with_unwrap::check(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") +} diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index 4a130ed47d..ce2e8fa8b1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -1,15 +1,39 @@ -use crate::utils::{is_copy, span_lint_and_then, sugg}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::get_parent_node; +use clippy_utils::source::snippet_with_context; +use clippy_utils::sugg; +use clippy_utils::ty::is_copy; use rustc_errors::Applicability; -use rustc_hir as hir; +use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, adjustment::Adjust}; +use rustc_span::symbol::{sym, Symbol}; use std::iter; use super::CLONE_DOUBLE_REF; use super::CLONE_ON_COPY; /// Checks for the `CLONE_ON_COPY` lint. -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'_>) { +#[allow(clippy::too_many_lines)] +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, args: &[Expr<'_>]) { + let arg = match args { + [arg] if method_name == sym::clone => arg, + _ => return, + }; + if cx + .typeck_results() + .type_dependent_def_id(expr.hir_id) + .and_then(|id| cx.tcx.trait_of_item(id)) + .zip(cx.tcx.lang_items().clone_trait()) + .map_or(true, |(x, y)| x != y) + { + return; + } + let arg_adjustments = cx.typeck_results().expr_adjustments(arg); + let arg_ty = arg_adjustments + .last() + .map_or_else(|| cx.typeck_results().expr_ty(arg), |a| a.target); + let ty = cx.typeck_results().expr_ty(expr); if let ty::Ref(_, inner, _) = arg_ty.kind() { if let ty::Ref(_, innermost, _) = inner.kind() { @@ -53,57 +77,57 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr< } if is_copy(cx, ty) { - let snip; - if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg) { - let parent = cx.tcx.hir().get_parent_node(expr.hir_id); - match &cx.tcx.hir().get(parent) { - hir::Node::Expr(parent) => match parent.kind { - // &*x is a nop, &x.clone() is not - hir::ExprKind::AddrOf(..) => return, - // (*x).func() is useless, x.clone().func() can work in case func borrows mutably - hir::ExprKind::MethodCall(_, _, parent_args, _) if expr.hir_id == parent_args[0].hir_id => { - return; - }, - - _ => {}, - }, - hir::Node::Stmt(stmt) => { - if let hir::StmtKind::Local(ref loc) = stmt.kind { - if let hir::PatKind::Ref(..) = loc.pat.kind { - // let ref y = *x borrows x, let ref y = x.clone() does not - return; - } - } - }, - _ => {}, + let parent_is_suffix_expr = match get_parent_node(cx.tcx, expr.hir_id) { + Some(Node::Expr(parent)) => match parent.kind { + // &*x is a nop, &x.clone() is not + ExprKind::AddrOf(..) => return, + // (*x).func() is useless, x.clone().func() can work in case func borrows self + ExprKind::MethodCall(_, _, [self_arg, ..], _) + if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) => + { + return; + } + ExprKind::MethodCall(_, _, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true, + ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) + | ExprKind::Field(..) + | ExprKind::Index(..) => true, + _ => false, + }, + // local binding capturing a reference + Some(Node::Local(l)) + if matches!( + l.pat.kind, + PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) + ) => + { + return; } + _ => false, + }; - // x.clone() might have dereferenced x, possibly through Deref impls - if cx.typeck_results().expr_ty(arg) == ty { - snip = Some(("try removing the `clone` call", format!("{}", snippet))); - } else { - let deref_count = cx - .typeck_results() - .expr_adjustments(arg) - .iter() - .filter(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_))) - .count(); - let derefs: String = iter::repeat('*').take(deref_count).collect(); - snip = Some(("try dereferencing it", format!("{}{}", derefs, snippet))); - } + let mut app = Applicability::MachineApplicable; + let snip = snippet_with_context(cx, arg.span, expr.span.ctxt(), "_", &mut app).0; + + let deref_count = arg_adjustments + .iter() + .take_while(|adj| matches!(adj.kind, Adjust::Deref(_))) + .count(); + let (help, sugg) = if deref_count == 0 { + ("try removing the `clone` call", snip.into()) + } else if parent_is_suffix_expr { + ("try dereferencing it", format!("({}{})", "*".repeat(deref_count), snip)) } else { - snip = None; - } - span_lint_and_then( + ("try dereferencing it", format!("{}{}", "*".repeat(deref_count), snip)) + }; + + span_lint_and_sugg( cx, CLONE_ON_COPY, expr.span, &format!("using `clone` on type `{}` which implements the `Copy` trait", ty), - |diag| { - if let Some((text, snip)) = snip { - diag.span_suggestion(expr.span, text, snip, Applicability::MachineApplicable); - } - }, + help, + sugg, + app, ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs index 3d5a68d69d..6417bc8130 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs @@ -1,13 +1,20 @@ -use crate::utils::{is_type_diagnostic_item, match_type, paths, snippet_with_macro_callsite, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::paths; +use clippy_utils::source::snippet_with_macro_callsite; +use clippy_utils::ty::{is_type_diagnostic_item, match_type}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::symbol::sym; +use rustc_span::symbol::{sym, Symbol}; use super::CLONE_ON_REF_PTR; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { + if !(args.len() == 1 && method_name == sym::clone) { + return; + } + let arg = &args[0]; let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs(); if let ty::Adt(_, subst) = obj_ty.kind() { diff --git a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs new file mode 100644 index 0000000000..ecec6da3aa --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs @@ -0,0 +1,45 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::{get_iterator_item_ty, is_copy}; +use clippy_utils::{is_trait_method, meets_msrv, msrvs}; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_semver::RustcVersion; +use rustc_span::{sym, Span}; + +use super::CLONED_INSTEAD_OF_COPIED; + +pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, msrv: Option<&RustcVersion>) { + let recv_ty = cx.typeck_results().expr_ty_adjusted(recv); + let inner_ty = match recv_ty.kind() { + // `Option<T>` -> `T` + ty::Adt(adt, subst) + if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) && meets_msrv(msrv, &msrvs::OPTION_COPIED) => + { + subst.type_at(0) + }, + _ if is_trait_method(cx, expr, sym::Iterator) && meets_msrv(msrv, &msrvs::ITERATOR_COPIED) => { + match get_iterator_item_ty(cx, recv_ty) { + // <T as Iterator>::Item + Some(ty) => ty, + _ => return, + } + }, + _ => return, + }; + match inner_ty.kind() { + // &T where T: Copy + ty::Ref(_, ty, _) if is_copy(cx, ty) => {}, + _ => return, + }; + span_lint_and_sugg( + cx, + CLONED_INSTEAD_OF_COPIED, + span, + "used `cloned` where `copied` could be used instead", + "try", + "copied".into(), + Applicability::MachineApplicable, + ) +} diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs index 6866e9c652..03cb41697d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs @@ -1,4 +1,7 @@ -use crate::utils::{is_expn_of, is_type_diagnostic_item, snippet, snippet_with_applicability, span_lint_and_sugg}; +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::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -97,9 +100,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa applicability: &mut Applicability, ) -> Vec<String> { if_chain! { - if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref format_arg) = a.kind; - if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.kind; - if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.kind; + 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 @@ -152,7 +155,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa 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(ref inner_fun, ref inner_args) = arg_root.kind; + 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 { diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs index 90b781bd9d..63a834fdce 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_type_diagnostic_item, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::sym; @@ -6,8 +7,8 @@ use rustc_span::sym; use super::EXPECT_USED; /// lint use of `expect()` for `Option`s and `Result`s -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) { - let obj_ty = cx.typeck_results().expr_ty(&expect_args[0]).peel_refs(); +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { + let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); let mess = if is_type_diagnostic_item(cx, obj_ty, sym::option_type) { Some((EXPECT_USED, "an Option", "None")) diff --git a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs index b03835f97e..7b2967feb0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs @@ -1,4 +1,6 @@ -use crate::utils::{get_parent_expr, match_type, paths, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::match_type; +use clippy_utils::{get_parent_expr, paths}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; @@ -6,8 +8,8 @@ use rustc_span::source_map::Span; use super::FILETYPE_IS_FILE; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - let ty = cx.typeck_results().expr_ty(&args[0]); +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { + let ty = cx.typeck_results().expr_ty(recv); if !match_type(cx, ty, &paths::FILE_TYPE) { return; diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs deleted file mode 100644 index 8da867fce5..0000000000 --- a/src/tools/clippy/clippy_lints/src/methods/filter_flat_map.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::utils::{match_trait_method, paths, span_lint_and_help}; -use rustc_hir as hir; -use rustc_lint::LateContext; - -use super::FILTER_MAP; - -/// lint use of `filter().flat_map()` for `Iterators` -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - _filter_args: &'tcx [hir::Expr<'_>], - _map_args: &'tcx [hir::Expr<'_>], -) { - // lint if caller of `.filter().flat_map()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter(..).flat_map(..)` on an `Iterator`"; - let hint = "this is more succinctly expressed by calling `.flat_map(..)` \ - and filtering by returning `iter::empty()`"; - span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint); - } -} diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index f559160004..35fae450ee 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -1,85 +1,174 @@ -use crate::utils::{match_trait_method, path_to_local_id, paths, snippet, span_lint_and_sugg, SpanlessEq}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{indent_of, reindent_multiline, snippet}; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_trait_method, path_to_local_id, remove_blocks, SpanlessEq}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::{Expr, ExprKind, PatKind, UnOp}; +use rustc_hir::def::Res; +use rustc_hir::{Expr, ExprKind, PatKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty::TyS; -use rustc_span::symbol::sym; +use rustc_span::source_map::Span; +use rustc_span::symbol::{sym, Symbol}; +use std::borrow::Cow; use super::MANUAL_FILTER_MAP; use super::MANUAL_FIND_MAP; +use super::OPTION_FILTER_MAP; + +fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool { + match &expr.kind { + hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name, + hir::ExprKind::Path(QPath::Resolved(_, segments)) => { + segments.segments.last().unwrap().ident.name == method_name + }, + hir::ExprKind::Closure(_, _, c, _, _) => { + let body = cx.tcx.hir().body(*c); + let closure_expr = remove_blocks(&body.value); + let arg_id = body.params[0].pat.hir_id; + match closure_expr.kind { + hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, _, args, _) => { + if_chain! { + if ident.name == method_name; + if let hir::ExprKind::Path(path) = &args[0].kind; + if let Res::Local(ref local) = cx.qpath_res(path, args[0].hir_id); + then { + return arg_id == *local + } + } + false + }, + _ => false, + } + }, + _ => false, + } +} + +fn is_option_filter_map<'tcx>(cx: &LateContext<'tcx>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool { + is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some)) +} + +/// lint use of `filter().map()` for `Iterators` +fn lint_filter_some_map_unwrap( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + filter_recv: &hir::Expr<'_>, + filter_arg: &hir::Expr<'_>, + map_arg: &hir::Expr<'_>, + target_span: Span, + methods_span: Span, +) { + let iterator = is_trait_method(cx, expr, sym::Iterator); + let option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv), sym::option_type); + if (iterator || option) && is_option_filter_map(cx, filter_arg, map_arg) { + let msg = "`filter` for `Some` followed by `unwrap`"; + let help = "consider using `flatten` instead"; + let sugg = format!( + "{}", + reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, target_span),) + ); + span_lint_and_sugg( + cx, + OPTION_FILTER_MAP, + methods_span, + msg, + help, + sugg, + Applicability::MachineApplicable, + ); + } +} /// lint use of `filter().map()` or `find().map()` for `Iterators` -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, is_find: bool) { +#[allow(clippy::too_many_arguments)] +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &hir::Expr<'_>, + filter_recv: &hir::Expr<'_>, + filter_arg: &hir::Expr<'_>, + filter_span: Span, + map_recv: &hir::Expr<'_>, + map_arg: &hir::Expr<'_>, + map_span: Span, + is_find: bool, +) { + lint_filter_some_map_unwrap( + cx, + expr, + filter_recv, + filter_arg, + map_arg, + map_span, + filter_span.with_hi(expr.span.hi()), + ); if_chain! { - if let ExprKind::MethodCall(_, _, [map_recv, map_arg], map_span) = expr.kind; - if let ExprKind::MethodCall(_, _, [_, filter_arg], filter_span) = map_recv.kind; - if match_trait_method(cx, map_recv, &paths::ITERATOR); + if is_trait_method(cx, map_recv, sym::Iterator); - // filter(|x| ...is_some())... - if let ExprKind::Closure(_, _, filter_body_id, ..) = filter_arg.kind; - let filter_body = cx.tcx.hir().body(filter_body_id); - if let [filter_param] = filter_body.params; - // optional ref pattern: `filter(|&x| ..)` - let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind { - (ref_pat, true) - } else { - (filter_param.pat, false) - }; - // closure ends with is_some() or is_ok() - if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind; - if let ExprKind::MethodCall(path, _, [filter_arg], _) = filter_body.value.kind; - if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).ty_adt_def(); - if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::option_type, opt_ty.did) { - Some(false) - } else if cx.tcx.is_diagnostic_item(sym::result_type, opt_ty.did) { - Some(true) - } else { - None - }; - if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" }; + // filter(|x| ...is_some())... + if let ExprKind::Closure(_, _, filter_body_id, ..) = filter_arg.kind; + let filter_body = cx.tcx.hir().body(filter_body_id); + if let [filter_param] = filter_body.params; + // optional ref pattern: `filter(|&x| ..)` + let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind { + (ref_pat, true) + } else { + (filter_param.pat, false) + }; + // closure ends with is_some() or is_ok() + if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind; + if let ExprKind::MethodCall(path, _, [filter_arg], _) = filter_body.value.kind; + if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).ty_adt_def(); + if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::option_type, opt_ty.did) { + Some(false) + } else if cx.tcx.is_diagnostic_item(sym::result_type, opt_ty.did) { + Some(true) + } else { + None + }; + if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" }; - // ...map(|x| ...unwrap()) - if let ExprKind::Closure(_, _, map_body_id, ..) = map_arg.kind; - let map_body = cx.tcx.hir().body(map_body_id); - if let [map_param] = map_body.params; - if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind; - // closure ends with expect() or unwrap() - if let ExprKind::MethodCall(seg, _, [map_arg, ..], _) = map_body.value.kind; - if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or); + // ...map(|x| ...unwrap()) + if let ExprKind::Closure(_, _, map_body_id, ..) = map_arg.kind; + let map_body = cx.tcx.hir().body(map_body_id); + if let [map_param] = map_body.params; + if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind; + // closure ends with expect() or unwrap() + if let ExprKind::MethodCall(seg, _, [map_arg, ..], _) = map_body.value.kind; + if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or); - let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| { - // in `filter(|x| ..)`, replace `*x` with `x` - let a_path = if_chain! { - if !is_filter_param_ref; - if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind; - then { expr_path } else { a } - }; - // let the filter closure arg and the map closure arg be equal - if_chain! { - if path_to_local_id(a_path, filter_param_id); - if path_to_local_id(b, map_param_id); - if TyS::same_type(cx.typeck_results().expr_ty_adjusted(a), cx.typeck_results().expr_ty_adjusted(b)); - then { - return true; + let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| { + // in `filter(|x| ..)`, replace `*x` with `x` + let a_path = if_chain! { + if !is_filter_param_ref; + if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind; + then { expr_path } else { a } + }; + // let the filter closure arg and the map closure arg be equal + if_chain! { + if path_to_local_id(a_path, filter_param_id); + if path_to_local_id(b, map_param_id); + if TyS::same_type(cx.typeck_results().expr_ty_adjusted(a), cx.typeck_results().expr_ty_adjusted(b)); + then { + return true; + } } - } - false - }; - if SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg); - then { - let span = filter_span.to(map_span); - let (filter_name, lint) = if is_find { - ("find", MANUAL_FIND_MAP) - } else { - ("filter", MANUAL_FILTER_MAP) + false }; - let msg = format!("`{}(..).map(..)` can be simplified as `{0}_map(..)`", filter_name); - let to_opt = if is_result { ".ok()" } else { "" }; - let sugg = format!("{}_map(|{}| {}{})", filter_name, map_param_ident, - snippet(cx, map_arg.span, ".."), to_opt); - span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable); - } + if SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg); + then { + let span = filter_span.with_hi(expr.span.hi()); + let (filter_name, lint) = if is_find { + ("find", MANUAL_FIND_MAP) + } else { + ("filter", MANUAL_FILTER_MAP) + }; + let msg = format!("`{}(..).map(..)` can be simplified as `{0}_map(..)`", filter_name); + let to_opt = if is_result { ".ok()" } else { "" }; + let sugg = format!("{}_map(|{}| {}{})", filter_name, map_param_ident, + snippet(cx, map_arg.span, ".."), to_opt); + span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable); + } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs deleted file mode 100644 index a6db138623..0000000000 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_flat_map.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::utils::{match_trait_method, paths, span_lint_and_help}; -use rustc_hir as hir; -use rustc_lint::LateContext; - -use super::FILTER_MAP; - -/// lint use of `filter_map().flat_map()` for `Iterators` -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - _filter_args: &'tcx [hir::Expr<'_>], - _map_args: &'tcx [hir::Expr<'_>], -) { - // lint if caller of `.filter_map().flat_map()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter_map(..).flat_map(..)` on an `Iterator`"; - let hint = "this is more succinctly expressed by calling `.flat_map(..)` \ - and filtering by returning `iter::empty()`"; - span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint); - } -} diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs index 9e646360a4..403fe8d354 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs @@ -1,21 +1,15 @@ -use crate::utils::{match_qpath, match_trait_method, path_to_local_id, paths, span_lint_and_sugg}; +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 rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::source_map::Span; +use rustc_span::{source_map::Span, sym}; use super::FILTER_MAP_IDENTITY; -pub(super) fn check( - cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - filter_map_args: &[hir::Expr<'_>], - filter_map_span: Span, -) { - if match_trait_method(cx, expr, &paths::ITERATOR) { - let arg_node = &filter_map_args[1].kind; - +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, @@ -29,8 +23,8 @@ pub(super) fn check( }; if_chain! { - if let hir::ExprKind::Closure(_, _, body_id, _, _) = arg_node; - let body = cx.tcx.hir().body(*body_id); + 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); @@ -39,14 +33,8 @@ pub(super) fn check( } } - if_chain! { - if let hir::ExprKind::Path(ref qpath) = arg_node; - - if match_qpath(qpath, &paths::STD_CONVERT_IDENTITY); - - then { - apply_lint("called `filter_map(std::convert::identity)` 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`"); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs deleted file mode 100644 index d015b4c7b3..0000000000 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_map.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::utils::{match_trait_method, paths, span_lint_and_help}; -use rustc_hir as hir; -use rustc_lint::LateContext; - -use super::FILTER_MAP; - -/// lint use of `filter_map().map()` for `Iterators` -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - _filter_args: &'tcx [hir::Expr<'_>], - _map_args: &'tcx [hir::Expr<'_>], -) { - // lint if caller of `.filter_map().map()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let msg = "called `filter_map(..).map(..)` on an `Iterator`"; - let hint = "this is more succinctly expressed by only calling `.filter_map(..)` instead"; - span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint); - } -} diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs index a789df922f..f0d69a1f42 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs @@ -1,29 +1,31 @@ -use crate::utils::{match_trait_method, meets_msrv, paths, snippet, span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::source::snippet; +use clippy_utils::{is_trait_method, meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_semver::RustcVersion; +use rustc_span::sym; use super::FILTER_MAP_NEXT; -const FILTER_MAP_NEXT_MSRV: RustcVersion = RustcVersion::new(1, 30, 0); - pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, - filter_args: &'tcx [hir::Expr<'_>], + recv: &'tcx hir::Expr<'_>, + arg: &'tcx hir::Expr<'_>, msrv: Option<&RustcVersion>, ) { - if match_trait_method(cx, expr, &paths::ITERATOR) { - if !meets_msrv(msrv, &FILTER_MAP_NEXT_MSRV) { + if is_trait_method(cx, expr, sym::Iterator) { + if !meets_msrv(msrv, &msrvs::ITERATOR_FIND_MAP) { return; } let msg = "called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling \ `.find_map(..)` instead"; - let filter_snippet = snippet(cx, filter_args[1].span, ".."); + let filter_snippet = snippet(cx, arg.span, ".."); if filter_snippet.lines().count() <= 1 { - let iter_snippet = snippet(cx, filter_args[0].span, ".."); + let iter_snippet = snippet(cx, recv.span, ".."); span_lint_and_sugg( cx, FILTER_MAP_NEXT, diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs index 81619e7301..172714f6b0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs @@ -1,19 +1,27 @@ -use crate::utils::{match_trait_method, paths, snippet, span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::is_trait_method; +use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_span::sym; use super::FILTER_NEXT; /// lint use of `filter().next()` for `Iterators` -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) { +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + recv: &'tcx hir::Expr<'_>, + filter_arg: &'tcx hir::Expr<'_>, +) { // lint if caller of `.filter().next()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { + if is_trait_method(cx, expr, sym::Iterator) { let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \ `.find(..)` instead"; - let filter_snippet = snippet(cx, filter_args[1].span, ".."); + let filter_snippet = snippet(cx, filter_arg.span, ".."); if filter_snippet.lines().count() <= 1 { - let iter_snippet = snippet(cx, filter_args[0].span, ".."); + let iter_snippet = snippet(cx, recv.span, ".."); // add note if not multi-line span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs index ce3194f8a2..25f8434cb9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs @@ -1,9 +1,10 @@ -use crate::utils::{match_qpath, match_trait_method, paths, span_lint_and_sugg}; +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 rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::source_map::Span; +use rustc_span::{source_map::Span, sym}; use super::FLAT_MAP_IDENTITY; @@ -11,12 +12,10 @@ use super::FLAT_MAP_IDENTITY; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, - flat_map_args: &'tcx [hir::Expr<'_>], + flat_map_arg: &'tcx hir::Expr<'_>, flat_map_span: Span, ) { - if match_trait_method(cx, expr, &paths::ITERATOR) { - let arg_node = &flat_map_args[1].kind; - + if is_trait_method(cx, expr, sym::Iterator) { let apply_lint = |message: &str| { span_lint_and_sugg( cx, @@ -30,11 +29,11 @@ pub(super) fn check<'tcx>( }; if_chain! { - if let hir::ExprKind::Closure(_, _, body_id, _, _) = arg_node; - let body = cx.tcx.hir().body(*body_id); + 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(_, ref path)) = body.value.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; @@ -44,14 +43,8 @@ pub(super) fn check<'tcx>( } } - if_chain! { - if let hir::ExprKind::Path(ref qpath) = arg_node; - - if match_qpath(qpath, &paths::STD_CONVERT_IDENTITY); - - then { - apply_lint("called `flat_map(std::convert::identity)` 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`"); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs new file mode 100644 index 0000000000..12d560653e --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs @@ -0,0 +1,34 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_span::{source_map::Span, sym}; + +use super::FLAT_MAP_OPTION; +use clippy_utils::ty::is_type_diagnostic_item; + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, span: Span) { + if !is_trait_method(cx, expr, sym::Iterator) { + return; + } + let arg_ty = cx.typeck_results().expr_ty_adjusted(arg); + let sig = match arg_ty.kind() { + ty::Closure(_, substs) => substs.as_closure().sig(), + _ if arg_ty.is_fn() => arg_ty.fn_sig(cx.tcx), + _ => return, + }; + if !is_type_diagnostic_item(cx, sig.output().skip_binder(), sym::option_type) { + return; + } + span_lint_and_sugg( + cx, + FLAT_MAP_OPTION, + span, + "used `flat_map` where `filter_map` could be used instead", + "try", + "filter_map".into(), + Applicability::MachineApplicable, + ) +} diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index e50d0a3340..28d0e8cd4a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -1,21 +1,23 @@ -use crate::utils::{get_trait_def_id, implements_trait, paths, span_lint_and_sugg, sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::implements_trait; +use clippy_utils::{is_expr_path_def_path, paths, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::Ty; +use rustc_span::sym; use super::FROM_ITER_INSTEAD_OF_COLLECT; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - let ty = cx.typeck_results().expr_ty(expr); - let arg_ty = cx.typeck_results().expr_ty(&args[0]); - +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func: &hir::Expr<'_>) { if_chain! { - if let Some(from_iter_id) = get_trait_def_id(cx, &paths::FROM_ITERATOR); - if let Some(iter_id) = get_trait_def_id(cx, &paths::ITERATOR); + if is_expr_path_def_path(cx, func, &paths::FROM_ITERATOR_METHOD); + let ty = cx.typeck_results().expr_ty(expr); + let arg_ty = cx.typeck_results().expr_ty(&args[0]); + if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); - if implements_trait(cx, ty, from_iter_id, &[]) && implements_trait(cx, arg_ty, iter_id, &[]); + if implements_trait(cx, arg_ty, iter_id, &[]); then { // `expr` implements `FromIterator` trait let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par(); @@ -35,8 +37,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp } fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -> String { + let call_site = expr.span.source_callsite(); if_chain! { - let call_site = expr.span.source_callsite(); if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site); let snippet_split = snippet.split("::").collect::<Vec<_>>(); if let Some((_, elements)) = snippet_split.split_last(); diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs index e157db2712..54f2806438 100644 --- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs @@ -1,7 +1,8 @@ -use crate::methods::derefs_to_slice; -use crate::utils::{ - get_parent_expr, is_type_diagnostic_item, match_type, paths, snippet_with_applicability, span_lint_and_sugg, -}; +use super::utils::derefs_to_slice; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::{is_type_diagnostic_item, match_type}; +use clippy_utils::{get_parent_expr, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -10,18 +11,20 @@ use rustc_span::sym; use super::GET_UNWRAP; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args: &'tcx [hir::Expr<'_>], is_mut: bool) { +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &hir::Expr<'_>, + recv: &'tcx hir::Expr<'tcx>, + get_arg: &'tcx hir::Expr<'_>, + is_mut: bool, +) { // Note: we don't want to lint `get_mut().unwrap` for `HashMap` or `BTreeMap`, // because they do not implement `IndexMut` let mut applicability = Applicability::MachineApplicable; - let expr_ty = cx.typeck_results().expr_ty(&get_args[0]); - let get_args_str = if get_args.len() > 1 { - snippet_with_applicability(cx, get_args[1].span, "..", &mut applicability) - } else { - return; // not linting on a .get().unwrap() chain or variant - }; + let expr_ty = cx.typeck_results().expr_ty(recv); + let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability); let mut needs_ref; - let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() { + let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() { needs_ref = get_args_str.parse::<usize>().is_ok(); "slice" } else if is_type_diagnostic_item(cx, expr_ty, sym::vec_type) { @@ -76,7 +79,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args format!( "{}{}[{}]", borrow_str, - snippet_with_applicability(cx, get_args[0].span, "..", &mut applicability), + snippet_with_applicability(cx, recv.span, "..", &mut applicability), get_args_str ), applicability, diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs index a769493d11..81c42de145 100644 --- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs @@ -1,28 +1,36 @@ -use crate::utils::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{is_diag_item_method, is_diag_trait_item}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::ExprKind; use rustc_lint::LateContext; use rustc_middle::ty::TyS; -use rustc_span::symbol::Symbol; +use rustc_span::{sym, Span}; use super::IMPLICIT_CLONE; -use clippy_utils::is_diagnostic_assoc_item; -pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, trait_diagnostic: Symbol) { +pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, span: Span) { if_chain! { - if let ExprKind::MethodCall(method_path, _, [arg], _) = &expr.kind; - let return_type = cx.typeck_results().expr_ty(&expr); - let input_type = cx.typeck_results().expr_ty(arg).peel_refs(); - if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); + if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); + if match method_name { + "to_os_string" => is_diag_item_method(cx, method_def_id, sym::OsStr), + "to_owned" => is_diag_trait_item(cx, method_def_id, sym::ToOwned), + "to_path_buf" => is_diag_item_method(cx, method_def_id, sym::Path), + "to_vec" => cx.tcx.impl_of_method(method_def_id) + .map(|impl_did| Some(impl_did) == cx.tcx.lang_items().slice_alloc_impl()) + == Some(true), + _ => false, + }; + let return_type = cx.typeck_results().expr_ty(expr); + let input_type = cx.typeck_results().expr_ty(recv).peel_refs(); if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did)); if TyS::same_type(return_type, input_type); - if is_diagnostic_assoc_item(cx, expr_def_id, trait_diagnostic); then { span_lint_and_sugg( - cx,IMPLICIT_CLONE,method_path.ident.span, - &format!("implicitly cloning a `{}` by calling `{}` on its dereferenced type", ty_name, method_path.ident.name), + cx, + IMPLICIT_CLONE, + span, + &format!("implicitly cloning a `{}` by calling `{}` on its dereferenced type", ty_name, method_name), "consider using", "clone".to_string(), Applicability::MachineApplicable diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs index 3045b09c23..950ec62c9f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs @@ -1,20 +1,24 @@ -use super::INEFFICIENT_TO_STRING; -use crate::utils::{ - is_type_diagnostic_item, match_def_path, paths, snippet_with_applicability, span_lint_and_then, walk_ptrs_ty_depth, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::{is_type_diagnostic_item, walk_ptrs_ty_depth}; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::sym; +use rustc_span::symbol::{sym, Symbol}; + +use super::INEFFICIENT_TO_STRING; /// Checks for the `INEFFICIENT_TO_STRING` lint -pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) { +pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { if_chain! { + if args.len() == 1 && method_name == sym!(to_string); if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD); if let Some(substs) = cx.typeck_results().node_substs_opt(expr.hir_id); + let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); let self_ty = substs.type_at(0); let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty); if deref_count >= 1; @@ -31,7 +35,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr self_ty, deref_self_ty )); let mut applicability = Applicability::MachineApplicable; - let arg_snippet = snippet_with_applicability(cx, arg.span, "..", &mut applicability); + let arg_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability); diag.span_suggestion( expr.span, "try dereferencing the receiver", diff --git a/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs b/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs index 959457a5bf..7fd3ef1a62 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs @@ -1,14 +1,14 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_trait_method; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::source_map::Span; - -use crate::utils::{match_trait_method, paths, span_lint_and_help}; +use rustc_span::{source_map::Span, sym}; use super::INSPECT_FOR_EACH; /// lint use of `inspect().for_each()` for `Iterators` pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, inspect_span: Span) { - if match_trait_method(cx, expr, &paths::ITERATOR) { + if is_trait_method(cx, expr, sym::Iterator) { let msg = "called `inspect(..).for_each(..)` on an `Iterator`"; let hint = "move the code from `inspect(..)` to `for_each(..)` and remove the `inspect(..)`"; span_lint_and_help( diff --git a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs index 1e8315dbee..da13b4ba37 100644 --- a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs @@ -1,30 +1,43 @@ -use crate::utils::{has_iter_method, match_trait_method, paths, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use clippy_utils::ty::has_iter_method; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{sym, Symbol}; use super::INTO_ITER_ON_REF; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, self_ref_ty: Ty<'_>, method_span: Span) { - if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) { - return; - } - if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ref_ty) { - span_lint_and_sugg( - cx, - INTO_ITER_ON_REF, - method_span, - &format!( - "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`", - method_name, kind, - ), - "call directly", - method_name.to_string(), - Applicability::MachineApplicable, - ); +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + method_span: Span, + method_name: Symbol, + args: &[hir::Expr<'_>], +) { + let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); + if_chain! { + if let ty::Ref(..) = self_ty.kind(); + if method_name == sym::into_iter; + if is_trait_method(cx, expr, sym::IntoIterator); + if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty); + then { + span_lint_and_sugg( + cx, + INTO_ITER_ON_REF, + method_span, + &format!( + "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`", + method_name, kind, + ), + "call directly", + method_name.to_string(), + Applicability::MachineApplicable, + ); + } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs index c3e48ffa5f..739f313716 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs @@ -1,5 +1,6 @@ -use crate::methods::derefs_to_slice; -use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg}; +use crate::methods::utils::derefs_to_slice; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -8,10 +9,10 @@ use rustc_span::sym; use super::ITER_CLONED_COLLECT; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) { if_chain! { if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type); - if let Some(slice) = derefs_to_slice(cx, &iter_args[0], cx.typeck_results().expr_ty(&iter_args[0])); + if let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv)); if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()); then { diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs index 869440e016..c6b7c7cd17 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs @@ -1,6 +1,8 @@ -use crate::methods::derefs_to_slice; -use crate::utils::{is_type_diagnostic_item, match_type, paths, snippet_with_applicability, span_lint_and_sugg}; - +use super::utils::derefs_to_slice; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::paths; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::{is_type_diagnostic_item, match_type}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; @@ -8,9 +10,9 @@ use rustc_span::sym; use super::ITER_COUNT; -pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &'tcx [Expr<'tcx>], iter_method: &str) { - let ty = cx.typeck_results().expr_ty(&iter_args[0]); - let caller_type = if derefs_to_slice(cx, &iter_args[0], ty).is_some() { +pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, iter_method: &str) { + let ty = cx.typeck_results().expr_ty(recv); + let caller_type = if derefs_to_slice(cx, recv, ty).is_some() { "slice" } else if is_type_diagnostic_item(cx, ty, sym::vec_type) { "Vec" @@ -40,7 +42,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &' "try", format!( "{}.len()", - snippet_with_applicability(cx, iter_args[0].span, "..", &mut applicability), + snippet_with_applicability(cx, recv.span, "..", &mut applicability), ), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs index 3c03a949cf..a49851de38 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs @@ -1,5 +1,8 @@ -use crate::methods::derefs_to_slice; -use crate::utils::{get_parent_expr, higher, is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg}; +use super::utils::derefs_to_slice; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{get_parent_expr, higher}; use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; @@ -10,9 +13,7 @@ use rustc_span::symbol::sym; use super::ITER_NEXT_SLICE; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, iter_args: &'tcx [hir::Expr<'_>]) { - let caller_expr = &iter_args[0]; - +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, caller_expr: &'tcx hir::Expr<'_>) { // Skip lint if the `iter().next()` expression is a for loop argument, // since it is already covered by `&loops::ITER_NEXT_LOOP` let mut parent_expr_opt = get_parent_expr(cx, expr); @@ -26,7 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite if derefs_to_slice(cx, caller_expr, cx.typeck_results().expr_ty(caller_expr)).is_some() { // caller is a Slice if_chain! { - if let hir::ExprKind::Index(ref caller_var, ref index_expr) = &caller_expr.kind; + if let hir::ExprKind::Index(caller_var, index_expr) = &caller_expr.kind; if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen }) = higher::range(index_expr); if let hir::ExprKind::Lit(ref start_lit) = &start_expr.kind; @@ -44,12 +45,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite ); } } - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(caller_expr), sym::vec_type) - || matches!( - &cx.typeck_results().expr_ty(caller_expr).peel_refs().kind(), - ty::Array(_, _) - ) - { + } else if is_vec_or_array(cx, caller_expr) { // caller is a Vec or an Array let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( @@ -66,3 +62,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, ite ); } } + +fn is_vec_or_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { + is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type) + || matches!(&cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Array(_, _)) +} diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs index cc3e56ea87..c2232239fe 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs @@ -1,6 +1,7 @@ -use crate::methods::derefs_to_slice; +use super::utils::derefs_to_slice; use crate::methods::iter_nth_zero; -use crate::utils::{is_type_diagnostic_item, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::symbol::sym; @@ -10,20 +11,20 @@ use super::ITER_NTH; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, - nth_and_iter_args: &[&'tcx [hir::Expr<'tcx>]], + iter_recv: &'tcx hir::Expr<'tcx>, + nth_recv: &hir::Expr<'_>, + nth_arg: &hir::Expr<'_>, is_mut: bool, ) { - let iter_args = nth_and_iter_args[1]; let mut_str = if is_mut { "_mut" } else { "" }; - let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.typeck_results().expr_ty(&iter_args[0])).is_some() { + let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() { "slice" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym::vec_type) { + } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::vec_type) { "Vec" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym::vecdeque_type) { + } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::vecdeque_type) { "VecDeque" } else { - let nth_args = nth_and_iter_args[0]; - iter_nth_zero::check(cx, expr, &nth_args); + iter_nth_zero::check(cx, expr, nth_recv, nth_arg); return; // caller is not a type that we want to lint }; diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs index 247192d81f..52d7c15332 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs @@ -1,16 +1,19 @@ use crate::consts::{constant, Constant}; -use crate::utils::{match_trait_method, paths, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_span::sym; use super::ITER_NTH_ZERO; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args: &'tcx [hir::Expr<'_>]) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { if_chain! { - if match_trait_method(cx, expr, &paths::ITERATOR); - if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &nth_args[1]); + if is_trait_method(cx, expr, sym::Iterator); + if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg); then { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( @@ -19,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args expr.span, "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", "try calling `.next()` instead of `.nth(0)`", - format!("{}.next()", snippet_with_applicability(cx, nth_args[0].span, "..", &mut applicability)), + format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut applicability)), applicability, ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs index 5f5969134e..e32594757d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs @@ -1,24 +1,24 @@ -use crate::utils::{match_trait_method, paths, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_span::sym; use super::ITER_SKIP_NEXT; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[hir::Expr<'_>]) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { // lint if caller of skip is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - if let [caller, n] = skip_args { - let hint = format!(".nth({})", snippet(cx, n.span, "..")); - span_lint_and_sugg( - cx, - ITER_SKIP_NEXT, - expr.span.trim_start(caller.span).unwrap(), - "called `skip(..).next()` on an iterator", - "use `nth` instead", - hint, - Applicability::MachineApplicable, - ); - } + if is_trait_method(cx, expr, sym::Iterator) { + span_lint_and_sugg( + cx, + ITER_SKIP_NEXT, + expr.span.trim_start(recv.span).unwrap(), + "called `skip(..).next()` on an iterator", + "use `nth` instead", + format!(".nth({})", snippet(cx, arg.span, "..")), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs index 3e05d7f76b..06b12998b1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs @@ -1,13 +1,15 @@ use crate::consts::{constant, Constant}; -use crate::utils::{match_trait_method, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_trait_method; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_span::sym; use super::ITERATOR_STEP_BY_ZERO; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) { - if match_trait_method(cx, expr, &paths::ITERATOR) { - if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &args[1]) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { + if is_trait_method(cx, expr, sym::Iterator) { + if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg) { span_lint( cx, ITERATOR_STEP_BY_ZERO, diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 0b414e0eb9..2fddea7068 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -1,4 +1,6 @@ -use crate::utils::{match_qpath, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_qpath_def_path; +use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; @@ -6,11 +8,14 @@ use rustc_hir as hir; use rustc_lint::LateContext; use rustc_target::abi::LayoutOf; -pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr<'_>]], arith: &str) { - let unwrap_arg = &args[0][1]; - let arith_lhs = &args[1][0]; - let arith_rhs = &args[1][1]; - +pub fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + arith_lhs: &hir::Expr<'_>, + arith_rhs: &hir::Expr<'_>, + unwrap_arg: &hir::Expr<'_>, + arith: &str, +) { let ty = cx.typeck_results().expr_ty(arith_lhs); if !ty.is_integral() { return; @@ -39,44 +44,28 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr<'_> // "mul" is omitted because lhs can be negative. _ => return, } - - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - super::MANUAL_SATURATING_ARITHMETIC, - expr.span, - "manual saturating arithmetic", - &format!("try using `saturating_{}`", arith), - format!( - "{}.saturating_{}({})", - snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability), - arith, - snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability), - ), - applicability, - ); } else { match (mm, arith) { (MinMax::Max, "add" | "mul") | (MinMax::Min, "sub") => (), _ => return, } - - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - super::MANUAL_SATURATING_ARITHMETIC, - expr.span, - "manual saturating arithmetic", - &format!("try using `saturating_{}`", arith), - format!( - "{}.saturating_{}({})", - snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability), - arith, - snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability), - ), - applicability, - ); } + + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + super::MANUAL_SATURATING_ARITHMETIC, + expr.span, + "manual saturating arithmetic", + &format!("try using `saturating_{}`", arith), + format!( + "{}.saturating_{}({})", + snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability), + arith, + snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability), + ), + applicability, + ); } #[derive(PartialEq, Eq)] @@ -105,11 +94,11 @@ fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option<M // `std::T::MAX` `std::T::MIN` constants if let hir::ExprKind::Path(path) = &expr.kind { - if match_qpath(path, &["core", &ty_str, "MAX"][..]) { + if is_qpath_def_path(cx, path, expr.hir_id, &["core", &ty_str, "MAX"][..]) { return Some(MinMax::Max); } - if match_qpath(path, &["core", &ty_str, "MIN"][..]) { + if is_qpath_def_path(cx, path, expr.hir_id, &["core", &ty_str, "MIN"][..]) { return Some(MinMax::Min); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs index 5b20e268d9..82063ad70b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs @@ -1,4 +1,7 @@ -use crate::utils::{is_type_diagnostic_item, match_trait_method, paths, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -11,13 +14,13 @@ use super::MAP_COLLECT_RESULT_UNIT; pub(super) fn check( cx: &LateContext<'_>, expr: &hir::Expr<'_>, - map_args: &[hir::Expr<'_>], - collect_args: &[hir::Expr<'_>], + iter: &hir::Expr<'_>, + map_fn: &hir::Expr<'_>, + collect_recv: &hir::Expr<'_>, ) { if_chain! { // called on Iterator - if let [map_expr] = collect_args; - if match_trait_method(cx, map_expr, &paths::ITERATOR); + if is_trait_method(cx, collect_recv, sym::Iterator); // return of collect `Result<(),_>` let collect_ret_ty = cx.typeck_results().expr_ty(expr); if is_type_diagnostic_item(cx, collect_ret_ty, sym::result_type); @@ -25,7 +28,6 @@ pub(super) fn check( if let Some(result_t) = substs.types().next(); if result_t.is_unit(); // get parts for snippet - if let [iter, map_fn] = map_args; then { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs index 14a14e4f9e..e8ad16bc0d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs @@ -1,4 +1,7 @@ -use crate::utils::{is_type_diagnostic_item, match_trait_method, paths, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_trait_method; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -8,10 +11,15 @@ use rustc_span::symbol::sym; use super::MAP_FLATTEN; /// lint use of `map().flatten()` for `Iterators` and 'Options' -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_args: &'tcx [hir::Expr<'_>]) { +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + recv: &'tcx hir::Expr<'_>, + map_arg: &'tcx hir::Expr<'_>, +) { // lint if caller of `.map().flatten()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { - let map_closure_ty = cx.typeck_results().expr_ty(&map_args[1]); + if is_trait_method(cx, expr, sym::Iterator) { + let map_closure_ty = cx.typeck_results().expr_ty(map_arg); let is_map_to_option = match map_closure_ty.kind() { ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(_) => { let map_closure_sig = match map_closure_ty.kind() { @@ -31,12 +39,12 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map // `(...).map(...)` has type `impl Iterator<Item=impl Iterator<...>> "flat_map" }; - let func_snippet = snippet(cx, map_args[1].span, ".."); + let func_snippet = snippet(cx, map_arg.span, ".."); let hint = format!(".{0}({1})", method_to_use, func_snippet); span_lint_and_sugg( cx, MAP_FLATTEN, - expr.span.with_lo(map_args[0].span.hi()), + expr.span.with_lo(recv.span.hi()), "called `map(..).flatten()` on an `Iterator`", &format!("try using `{}` instead", method_to_use), hint, @@ -45,13 +53,13 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map } // lint if caller of `.map().flatten()` is an Option - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::option_type) { - let func_snippet = snippet(cx, map_args[1].span, ".."); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type) { + let func_snippet = snippet(cx, map_arg.span, ".."); let hint = format!(".and_then({})", func_snippet); span_lint_and_sugg( cx, MAP_FLATTEN, - expr.span.with_lo(map_args[0].span.hi()), + expr.span.with_lo(recv.span.hi()), "called `map(..).flatten()` on an `Option`", "try using `and_then` instead", hint, diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index 63b2cf87f3..4d8365fcda 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -1,5 +1,8 @@ -use crate::utils::usage::mutated_variables; -use crate::utils::{is_type_diagnostic_item, meets_msrv, snippet, span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::usage::mutated_variables; +use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -8,29 +11,29 @@ use rustc_span::symbol::sym; use super::MAP_UNWRAP_OR; -const MAP_UNWRAP_OR_MSRV: RustcVersion = RustcVersion::new(1, 41, 0); - /// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s /// Return true if lint triggered pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, - map_args: &'tcx [hir::Expr<'_>], - unwrap_args: &'tcx [hir::Expr<'_>], + recv: &'tcx hir::Expr<'_>, + map_arg: &'tcx hir::Expr<'_>, + unwrap_arg: &'tcx hir::Expr<'_>, msrv: Option<&RustcVersion>, ) -> bool { - if !meets_msrv(msrv, &MAP_UNWRAP_OR_MSRV) { + // lint if the caller of `map()` is an `Option` + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); + + if is_result && !meets_msrv(msrv, &msrvs::RESULT_MAP_OR_ELSE) { return false; } - // lint if the caller of `map()` is an `Option` - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::option_type); - let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::result_type); if is_option || is_result { // Don't make a suggestion that may fail to compile due to mutably borrowing // the same variable twice. - let map_mutated_vars = mutated_variables(&map_args[0], cx); - let unwrap_mutated_vars = mutated_variables(&unwrap_args[1], cx); + let map_mutated_vars = mutated_variables(recv, cx); + let unwrap_mutated_vars = mutated_variables(unwrap_arg, cx); if let (Some(map_mutated_vars), Some(unwrap_mutated_vars)) = (map_mutated_vars, unwrap_mutated_vars) { if map_mutated_vars.intersection(&unwrap_mutated_vars).next().is_some() { return false; @@ -48,14 +51,14 @@ pub(super) fn check<'tcx>( `.map_or_else(<g>, <f>)` instead" }; // get snippets for args to map() and unwrap_or_else() - let map_snippet = snippet(cx, map_args[1].span, ".."); - let unwrap_snippet = snippet(cx, unwrap_args[1].span, ".."); + let map_snippet = snippet(cx, map_arg.span, ".."); + let unwrap_snippet = snippet(cx, unwrap_arg.span, ".."); // lint, with note if neither arg is > 1 line and both map() and // unwrap_or_else() have the same span let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; - let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt(); + let same_span = map_arg.span.ctxt() == unwrap_arg.span.ctxt(); if same_span && !multiline { - let var_snippet = snippet(cx, map_args[0].span, ".."); + let var_snippet = snippet(cx, recv.span, ".."); span_lint_and_sugg( cx, MAP_UNWRAP_OR, diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 7fd14c4f9b..e15dbb899b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1,18 +1,23 @@ mod bind_instead_of_map; mod bytes_nth; +mod chars_cmp; +mod chars_cmp_with_unwrap; +mod chars_last_cmp; +mod chars_last_cmp_with_unwrap; +mod chars_next_cmp; +mod chars_next_cmp_with_unwrap; mod clone_on_copy; mod clone_on_ref_ptr; +mod cloned_instead_of_copied; mod expect_fun_call; mod expect_used; mod filetype_is_file; -mod filter_flat_map; mod filter_map; -mod filter_map_flat_map; mod filter_map_identity; -mod filter_map_map; mod filter_map_next; mod filter_next; mod flat_map_identity; +mod flat_map_option; mod from_iter_instead_of_collect; mod get_unwrap; mod implicit_clone; @@ -36,6 +41,7 @@ mod option_map_or_none; mod option_map_unwrap_or; mod or_fun_call; mod search_is_some; +mod single_char_add_str; mod single_char_insert_string; mod single_char_pattern; mod single_char_push_string; @@ -48,28 +54,72 @@ mod unnecessary_fold; mod unnecessary_lazy_eval; mod unwrap_used; mod useless_asref; +mod utils; mod wrong_self_convention; mod zst_offset; use bind_instead_of_map::BindInsteadOfMap; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item}; +use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, paths, return_ty}; use if_chain::if_chain; -use rustc_ast::ast; -use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::{TraitItem, TraitItemKind}; -use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; +use rustc_hir::def::Res; +use rustc_hir::{Expr, ExprKind, PrimTy, QPath, TraitItem, TraitItemKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, TraitRef, Ty, TyS}; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::symbol::{sym, SymbolStr}; +use rustc_span::symbol::SymbolStr; +use rustc_span::{sym, Span}; use rustc_typeck::hir_ty_to_ty; -use crate::utils::{ - contains_return, contains_ty, get_trait_def_id, implements_trait, in_macro, is_copy, is_type_diagnostic_item, - iter_input_pats, match_def_path, match_qpath, method_calls, method_chain_args, paths, return_ty, - single_segment_path, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq, -}; +declare_clippy_lint! { + /// **What it does:** Checks for usages of `cloned()` on an `Iterator` or `Option` where + /// `copied()` could be used instead. + /// + /// **Why is this bad?** `copied()` is better because it guarantees that the type being cloned + /// implements `Copy`. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// [1, 2, 3].iter().cloned(); + /// ``` + /// Use instead: + /// ```rust + /// [1, 2, 3].iter().copied(); + /// ``` + pub CLONED_INSTEAD_OF_COPIED, + pedantic, + "used `cloned` where `copied` could be used instead" +} + +declare_clippy_lint! { + /// **What it does:** Checks for usages of `Iterator::flat_map()` where `filter_map()` could be + /// used instead. + /// + /// **Why is this bad?** When applicable, `filter_map()` is more clear since it shows that + /// `Option` is used to produce 0 or 1 items. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// let nums: Vec<i32> = ["1", "2", "whee!"].iter().flat_map(|x| x.parse().ok()).collect(); + /// ``` + /// Use instead: + /// ```rust + /// let nums: Vec<i32> = ["1", "2", "whee!"].iter().filter_map(|x| x.parse().ok()).collect(); + /// ``` + pub FLAT_MAP_OPTION, + pedantic, + "used `flat_map` where `filter_map` could be used instead" +} declare_clippy_lint! { /// **What it does:** Checks for `.unwrap()` calls on `Option`s and on `Result`s. @@ -191,13 +241,25 @@ declare_clippy_lint! { /// **What it does:** Checks for methods with certain name prefixes and which /// doesn't match how self is taken. The actual rules are: /// - /// |Prefix |`self` taken | - /// |-------|----------------------| - /// |`as_` |`&self` or `&mut self`| - /// |`from_`| none | - /// |`into_`|`self` | - /// |`is_` |`&self` or none | - /// |`to_` |`&self` | + /// |Prefix |Postfix |`self` taken | `self` type | + /// |-------|------------|-----------------------|--------------| + /// |`as_` | none |`&self` or `&mut self` | any | + /// |`from_`| none | none | any | + /// |`into_`| none |`self` | any | + /// |`is_` | none |`&self` or none | any | + /// |`to_` | `_mut` |`&mut self` | any | + /// |`to_` | not `_mut` |`self` | `Copy` | + /// |`to_` | not `_mut` |`&self` | not `Copy` | + /// + /// Note: Clippy doesn't trigger methods with `to_` prefix in: + /// - Traits definition. + /// Clippy can not tell if a type that implements a trait is `Copy` or not. + /// - Traits implementation, when `&self` is taken. + /// The method signature is controlled by the trait and often `&self` is required for all types that implement the trait + /// (see e.g. the `std::string::ToString` trait). + /// + /// Please find more info here: + /// https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv /// /// **Why is this bad?** Consistency breeds readability. If you follow the /// conventions, your users won't be surprised that they, e.g., need to supply a @@ -455,35 +517,6 @@ declare_clippy_lint! { "using combinations of `flatten` and `map` which can usually be written as a single method call" } -declare_clippy_lint! { - /// **What it does:** Checks for usage of `_.filter(_).map(_)`, - /// `_.filter(_).flat_map(_)`, `_.filter_map(_).flat_map(_)` and similar. - /// - /// **Why is this bad?** Readability, this can be written more concisely as - /// `_.filter_map(_)`. - /// - /// **Known problems:** Often requires a condition + Option/Iterator creation - /// inside the closure. - /// - /// **Example:** - /// ```rust - /// let vec = vec![1]; - /// - /// // Bad - /// vec.iter().filter(|x| **x == 0).map(|x| *x * 2); - /// - /// // Good - /// vec.iter().filter_map(|x| if *x == 0 { - /// Some(*x * 2) - /// } else { - /// None - /// }); - /// ``` - pub FILTER_MAP, - pedantic, - "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call" -} - declare_clippy_lint! { /// **What it does:** Checks for usage of `_.filter(_).map(_)` that can be written more simply /// as `filter_map(_)`. @@ -582,26 +615,31 @@ declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for an iterator or string search (such as `find()`, - /// `position()`, or `rposition()`) followed by a call to `is_some()`. + /// `position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`. /// - /// **Why is this bad?** Readability, this can be written more concisely as - /// `_.any(_)` or `_.contains(_)`. + /// **Why is this bad?** Readability, this can be written more concisely as: + /// * `_.any(_)`, or `_.contains(_)` for `is_some()`, + /// * `!_.any(_)`, or `!_.contains(_)` for `is_none()`. /// /// **Known problems:** None. /// /// **Example:** /// ```rust - /// # let vec = vec![1]; + /// let vec = vec![1]; /// vec.iter().find(|x| **x == 0).is_some(); + /// + /// let _ = "hello world".find("world").is_none(); /// ``` /// Could be written as /// ```rust - /// # let vec = vec![1]; + /// let vec = vec![1]; /// vec.iter().any(|x| *x == 0); + /// + /// let _ = !"hello world".contains("world"); /// ``` pub SEARCH_IS_SOME, complexity, - "using an iterator or string search followed by `is_some()`, which is more succinctly expressed as a call to `any()` or `contains()`" + "using an iterator or string search followed by `is_some()` or `is_none()`, which is more succinctly expressed as a call to `any()` or `contains()` (with negation in case of `is_none()`)" } declare_clippy_lint! { @@ -882,6 +920,28 @@ declare_clippy_lint! { "using `Iterator::step_by(0)`, which will panic at runtime" } +declare_clippy_lint! { + /// **What it does:** Checks for indirect collection of populated `Option` + /// + /// **Why is this bad?** `Option` is like a collection of 0-1 things, so `flatten` + /// automatically does this without suspicious-looking `unwrap` calls. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// let _ = std::iter::empty::<Option<i32>>().filter(Option::is_some).map(Option::unwrap); + /// ``` + /// Use instead: + /// ```rust + /// let _ = std::iter::empty::<Option<i32>>().flatten(); + /// ``` + pub OPTION_FILTER_MAP, + complexity, + "filtering `Option` for `Some` then force-unwrapping, which can be one type-safe operation" +} + declare_clippy_lint! { /// **What it does:** Checks for the use of `iter.nth(0)`. /// @@ -1626,6 +1686,8 @@ impl_lint_pass!(Methods => [ CLONE_ON_COPY, CLONE_ON_REF_PTR, CLONE_DOUBLE_REF, + CLONED_INSTEAD_OF_COPIED, + FLAT_MAP_OPTION, INEFFICIENT_TO_STRING, NEW_RET_NO_SELF, SINGLE_CHAR_PATTERN, @@ -1633,10 +1695,10 @@ impl_lint_pass!(Methods => [ SEARCH_IS_SOME, FILTER_NEXT, SKIP_WHILE_NEXT, - FILTER_MAP, FILTER_MAP_IDENTITY, MANUAL_FILTER_MAP, MANUAL_FIND_MAP, + OPTION_FILTER_MAP, FILTER_MAP_NEXT, FLAT_MAP_IDENTITY, MAP_FLATTEN, @@ -1667,151 +1729,48 @@ impl_lint_pass!(Methods => [ IMPLICIT_CLONE ]); +/// Extracts a method call name, args, and `Span` of the method name. +fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(SymbolStr, &'tcx [hir::Expr<'tcx>], Span)> { + if let ExprKind::MethodCall(path, span, args, _) = recv.kind { + if !args.iter().any(|e| e.span.from_expansion()) { + return Some((path.ident.name.as_str(), args, span)); + } + } + None +} + +/// Same as `method_call` but the `SymbolStr` is dereferenced into a temporary `&str` +macro_rules! method_call { + ($expr:expr) => { + method_call($expr) + .as_ref() + .map(|&(ref name, args, span)| (&**name, args, span)) + }; +} + impl<'tcx> LateLintPass<'tcx> for Methods { - #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if in_macro(expr.span) { return; } - let (method_names, arg_lists, method_spans) = method_calls(expr, 2); - let method_names: Vec<SymbolStr> = method_names.iter().map(|s| s.as_str()).collect(); - let method_names: Vec<&str> = method_names.iter().map(|s| &**s).collect(); - - match method_names.as_slice() { - ["unwrap", "get"] => get_unwrap::check(cx, expr, arg_lists[1], false), - ["unwrap", "get_mut"] => get_unwrap::check(cx, expr, arg_lists[1], true), - ["unwrap", ..] => unwrap_used::check(cx, expr, arg_lists[0]), - ["expect", "ok"] => ok_expect::check(cx, expr, arg_lists[1]), - ["expect", ..] => expect_used::check(cx, expr, arg_lists[0]), - ["unwrap_or", "map"] => option_map_unwrap_or::check(cx, expr, arg_lists[1], arg_lists[0], method_spans[1]), - ["unwrap_or_else", "map"] => { - if !map_unwrap_or::check(cx, expr, arg_lists[1], arg_lists[0], self.msrv.as_ref()) { - unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "unwrap_or"); - } - }, - ["map_or", ..] => option_map_or_none::check(cx, expr, arg_lists[0]), - ["and_then", ..] => { - let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, arg_lists[0]); - let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, arg_lists[0]); - if !biom_option_linted && !biom_result_linted { - unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "and"); - } - }, - ["or_else", ..] => { - if !bind_instead_of_map::ResultOrElseErrInfo::check(cx, expr, arg_lists[0]) { - unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "or"); - } - }, - ["next", "filter"] => filter_next::check(cx, expr, arg_lists[1]), - ["next", "skip_while"] => skip_while_next::check(cx, expr, arg_lists[1]), - ["next", "iter"] => iter_next_slice::check(cx, expr, arg_lists[1]), - ["map", "filter"] => filter_map::check(cx, expr, false), - ["map", "filter_map"] => filter_map_map::check(cx, expr, arg_lists[1], arg_lists[0]), - ["next", "filter_map"] => filter_map_next::check(cx, expr, arg_lists[1], self.msrv.as_ref()), - ["map", "find"] => filter_map::check(cx, expr, true), - ["flat_map", "filter"] => filter_flat_map::check(cx, expr, arg_lists[1], arg_lists[0]), - ["flat_map", "filter_map"] => filter_map_flat_map::check(cx, expr, arg_lists[1], arg_lists[0]), - ["flat_map", ..] => flat_map_identity::check(cx, expr, arg_lists[0], method_spans[0]), - ["flatten", "map"] => map_flatten::check(cx, expr, arg_lists[1]), - ["is_some", "find"] => search_is_some::check(cx, expr, "find", arg_lists[1], arg_lists[0], method_spans[1]), - ["is_some", "position"] => { - search_is_some::check(cx, expr, "position", arg_lists[1], arg_lists[0], method_spans[1]) - }, - ["is_some", "rposition"] => { - search_is_some::check(cx, expr, "rposition", arg_lists[1], arg_lists[0], method_spans[1]) - }, - ["extend", ..] => string_extend_chars::check(cx, expr, arg_lists[0]), - ["count", "into_iter"] => iter_count::check(cx, expr, &arg_lists[1], "into_iter"), - ["count", "iter"] => iter_count::check(cx, expr, &arg_lists[1], "iter"), - ["count", "iter_mut"] => iter_count::check(cx, expr, &arg_lists[1], "iter_mut"), - ["nth", "iter"] => iter_nth::check(cx, expr, &arg_lists, false), - ["nth", "iter_mut"] => iter_nth::check(cx, expr, &arg_lists, true), - ["nth", "bytes"] => bytes_nth::check(cx, expr, &arg_lists[1]), - ["nth", ..] => iter_nth_zero::check(cx, expr, arg_lists[0]), - ["step_by", ..] => iterator_step_by_zero::check(cx, expr, arg_lists[0]), - ["next", "skip"] => iter_skip_next::check(cx, expr, arg_lists[1]), - ["collect", "cloned"] => iter_cloned_collect::check(cx, expr, arg_lists[1]), - ["as_ref"] => useless_asref::check(cx, expr, "as_ref", arg_lists[0]), - ["as_mut"] => useless_asref::check(cx, expr, "as_mut", arg_lists[0]), - ["fold", ..] => unnecessary_fold::check(cx, expr, arg_lists[0], method_spans[0]), - ["filter_map", ..] => { - unnecessary_filter_map::check(cx, expr, arg_lists[0]); - filter_map_identity::check(cx, expr, arg_lists[0], method_spans[0]); - }, - ["count", "map"] => suspicious_map::check(cx, expr), - ["assume_init"] => uninit_assumed_init::check(cx, &arg_lists[0][0], expr), - ["unwrap_or", arith @ ("checked_add" | "checked_sub" | "checked_mul")] => { - manual_saturating_arithmetic::check(cx, expr, &arg_lists, &arith["checked_".len()..]) - }, - ["add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub"] => { - zst_offset::check(cx, expr, arg_lists[0]) - }, - ["is_file", ..] => filetype_is_file::check(cx, expr, arg_lists[0]), - ["map", "as_ref"] => { - option_as_ref_deref::check(cx, expr, arg_lists[1], arg_lists[0], false, self.msrv.as_ref()) - }, - ["map", "as_mut"] => { - option_as_ref_deref::check(cx, expr, arg_lists[1], arg_lists[0], true, self.msrv.as_ref()) - }, - ["unwrap_or_else", ..] => unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "unwrap_or"), - ["get_or_insert_with", ..] => unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "get_or_insert"), - ["ok_or_else", ..] => unnecessary_lazy_eval::check(cx, expr, arg_lists[0], "ok_or"), - ["collect", "map"] => map_collect_result_unit::check(cx, expr, arg_lists[1], arg_lists[0]), - ["for_each", "inspect"] => inspect_for_each::check(cx, expr, method_spans[1]), - ["to_owned", ..] => implicit_clone::check(cx, expr, sym::ToOwned), - ["to_os_string", ..] => implicit_clone::check(cx, expr, sym::OsStr), - ["to_path_buf", ..] => implicit_clone::check(cx, expr, sym::Path), - ["to_vec", ..] => implicit_clone::check(cx, expr, sym::slice), - _ => {}, - } + check_methods(cx, expr, self.msrv.as_ref()); match expr.kind { - hir::ExprKind::Call(ref func, ref args) => { - if let hir::ExprKind::Path(path) = &func.kind { - if match_qpath(path, &["from_iter"]) { - from_iter_instead_of_collect::check(cx, expr, args); - } - } + hir::ExprKind::Call(func, args) => { + from_iter_instead_of_collect::check(cx, expr, args, func); }, - hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => { + hir::ExprKind::MethodCall(method_call, ref method_span, args, _) => { or_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args); expect_fun_call::check(cx, expr, *method_span, &method_call.ident.as_str(), args); - - let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]); - if args.len() == 1 && method_call.ident.name == sym::clone { - clone_on_copy::check(cx, expr, &args[0], self_ty); - clone_on_ref_ptr::check(cx, expr, &args[0]); - } - if args.len() == 1 && method_call.ident.name == sym!(to_string) { - inefficient_to_string::check(cx, expr, &args[0], self_ty); - } - - if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { - if match_def_path(cx, fn_def_id, &paths::PUSH_STR) { - single_char_push_string::check(cx, expr, args); - } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) { - single_char_insert_string::check(cx, expr, args); - } - } - - match self_ty.kind() { - ty::Ref(_, ty, _) if *ty.kind() == ty::Str => { - for &(method, pos) in &PATTERN_METHODS { - if method_call.ident.name.as_str() == method && args.len() > pos { - single_char_pattern::check(cx, expr, &args[pos]); - } - } - }, - ty::Ref(..) if method_call.ident.name == sym::into_iter => { - into_iter_on_ref::check(cx, expr, self_ty, *method_span); - }, - _ => (), - } + clone_on_copy::check(cx, expr, method_call.ident.name, args); + clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args); + inefficient_to_string::check(cx, expr, method_call.ident.name, args); + single_char_add_str::check(cx, expr, args); + into_iter_on_ref::check(cx, expr, *method_span, method_call.ident.name, args); + single_char_pattern::check(cx, expr, method_call.ident.name, args); }, - hir::ExprKind::Binary(op, ref lhs, ref rhs) - if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => - { + hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { let mut info = BinaryExprInfo { expr, chain: lhs, @@ -1819,7 +1778,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { eq: op.node == hir::BinOpKind::Eq, }; lint_binary_expr_with_method_call(cx, &mut info); - } + }, _ => (), } } @@ -1834,14 +1793,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { let item = cx.tcx.hir().expect_item(parent); let self_ty = cx.tcx.type_of(item.def_id); - // if this impl block implements a trait, lint in trait definition instead - if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { - return; - } - + let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })); if_chain! { if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind; - if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next(); + if let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next(); let method_sig = cx.tcx.fn_sig(impl_item.def_id); let method_sig = cx.tcx.erase_late_bound_regions(method_sig); @@ -1852,15 +1807,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let Some(first_arg_ty) = first_arg_ty; then { - if cx.access_levels.is_exported(impl_item.hir_id()) { + // if this impl block implements a trait, lint in trait definition instead + if !implements_trait && cx.access_levels.is_exported(impl_item.hir_id()) { // check missing trait implementations for method_config in &TRAIT_METHODS { if name == method_config.method_name && sig.decl.inputs.len() == method_config.param_count && - method_config.output_type.matches(cx, &sig.decl.output) && + method_config.output_type.matches(&sig.decl.output) && method_config.self_kind.matches(cx, self_ty, first_arg_ty) && fn_header_equals(method_config.fn_header, sig.header) && - method_config.lifetime_param_cond(&impl_item) + method_config.lifetime_param_cond(impl_item) { span_lint_and_help( cx, @@ -1888,16 +1844,27 @@ impl<'tcx> LateLintPass<'tcx> for Methods { item.vis.node.is_pub(), self_ty, first_arg_ty, - first_arg.pat.span + first_arg.pat.span, + implements_trait, + false ); } } + // if this impl block implements a trait, lint in trait definition instead + if implements_trait { + return; + } + if let hir::ImplItemKind::Fn(_, _) = impl_item.kind { let ret_ty = return_ty(cx, impl_item.hir_id()); // walk the return type and check for Self (this does not check associated types) - if contains_ty(ret_ty, self_ty) { + 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; } @@ -1907,7 +1874,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods { for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { // walk the associated type and check for Self - if contains_ty(projection_predicate.ty, self_ty) { + if let Some(self_adt) = self_ty.ty_adt_def() { + if contains_adt_constructor(projection_predicate.ty, self_adt) { + return; + } + } else if contains_ty(projection_predicate.ty, self_ty) { return; } } @@ -1933,18 +1904,19 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if_chain! { if let TraitItemKind::Fn(ref sig, _) = item.kind; if let Some(first_arg_ty) = sig.decl.inputs.iter().next(); - let first_arg_span = first_arg_ty.span; - let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty); - let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty(); - then { + let first_arg_span = first_arg_ty.span; + let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty); + let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty(); wrong_self_convention::check( cx, &item.ident.name.as_str(), false, self_ty, first_arg_ty, - first_arg_span + first_arg_span, + false, + true ); } } @@ -1970,46 +1942,137 @@ impl<'tcx> LateLintPass<'tcx> for Methods { extract_msrv_attr!(LateContext); } -fn derefs_to_slice<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'tcx>, - ty: Ty<'tcx>, -) -> Option<&'tcx hir::Expr<'tcx>> { - fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { - match ty.kind() { - ty::Slice(_) => true, - ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), - ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type), - ty::Array(_, size) => size - .try_eval_usize(cx.tcx, cx.param_env) - .map_or(false, |size| size < 32), - ty::Ref(_, inner, _) => may_slice(cx, inner), - _ => false, - } - } - - if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind { - if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) { - Some(&args[0]) - } else { - None - } - } else { - match ty.kind() { - ty::Slice(_) => Some(expr), - ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr), - ty::Ref(_, inner, _) => { - if may_slice(cx, inner) { - Some(expr) - } else { - None +#[allow(clippy::too_many_lines)] +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, _]) => { + zst_offset::check(cx, expr, recv) + }, + ("and_then", [arg]) => { + let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg); + let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, recv, arg); + if !biom_option_linted && !biom_result_linted { + unnecessary_lazy_eval::check(cx, expr, recv, arg, "and"); } }, - _ => None, + ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv), + ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv), + ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv), + ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, msrv), + ("collect", []) => match method_call!(recv) { + Some(("cloned", [recv2], _)) => iter_cloned_collect::check(cx, expr, recv2), + Some(("map", [m_recv, m_arg], _)) => { + map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv); + }, + _ => {}, + }, + ("count", []) => match method_call!(recv) { + Some((name @ ("into_iter" | "iter" | "iter_mut"), [recv2], _)) => { + iter_count::check(cx, expr, recv2, name); + }, + Some(("map", [_, arg], _)) => suspicious_map::check(cx, expr, recv, arg), + _ => {}, + }, + ("expect", [_]) => match method_call!(recv) { + 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), + ("filter_map", [arg]) => { + unnecessary_filter_map::check(cx, expr, arg); + filter_map_identity::check(cx, expr, arg, span); + }, + ("flat_map", [arg]) => { + flat_map_identity::check(cx, expr, arg, span); + flat_map_option::check(cx, expr, arg, span); + }, + ("flatten", []) => { + if let Some(("map", [recv, map_arg], _)) = method_call!(recv) { + map_flatten::check(cx, expr, recv, map_arg); + } + }, + ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span), + ("for_each", [_]) => { + if let Some(("inspect", [_, _], span2)) = method_call!(recv) { + inspect_for_each::check(cx, expr, span2); + } + }, + ("get_or_insert_with", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert"), + ("is_file", []) => filetype_is_file::check(cx, expr, recv), + ("is_none", []) => check_is_some_is_none(cx, expr, recv, false), + ("is_some", []) => check_is_some_is_none(cx, expr, recv, true), + ("map", [m_arg]) => { + if let Some((name, [recv2, args @ ..], span2)) = method_call!(recv) { + match (name, args) { + ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, msrv), + ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, msrv), + ("filter", [f_arg]) => { + filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false) + }, + ("find", [f_arg]) => filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, true), + _ => {}, + } + } + }, + ("map_or", [def, map]) => option_map_or_none::check(cx, expr, recv, def, map), + ("next", []) => { + if let Some((name, [recv, args @ ..], _)) = method_call!(recv) { + match (name, args) { + ("filter", [arg]) => filter_next::check(cx, expr, recv, arg), + ("filter_map", [arg]) => filter_map_next::check(cx, expr, recv, arg, msrv), + ("iter", []) => iter_next_slice::check(cx, expr, recv), + ("skip", [arg]) => iter_skip_next::check(cx, expr, recv, arg), + ("skip_while", [_]) => skip_while_next::check(cx, expr), + _ => {}, + } + } + }, + ("nth", [n_arg]) => match method_call!(recv) { + Some(("bytes", [recv2], _)) => bytes_nth::check(cx, expr, recv2, n_arg), + Some(("iter", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false), + Some(("iter_mut", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true), + _ => iter_nth_zero::check(cx, expr, recv, n_arg), + }, + ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"), + ("or_else", [arg]) => { + if !bind_instead_of_map::ResultOrElseErrInfo::check(cx, expr, recv, arg) { + unnecessary_lazy_eval::check(cx, expr, recv, arg, "or"); + } + }, + ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg), + ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => { + implicit_clone::check(cx, name, expr, recv, span); + }, + ("unwrap", []) => match method_call!(recv) { + Some(("get", [recv, get_arg], _)) => get_unwrap::check(cx, expr, recv, get_arg, false), + Some(("get_mut", [recv, get_arg], _)) => get_unwrap::check(cx, expr, recv, get_arg, true), + _ => unwrap_used::check(cx, expr, recv), + }, + ("unwrap_or", [u_arg]) => match method_call!(recv) { + Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), [lhs, rhs], _)) => { + manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); + }, + Some(("map", [m_recv, m_arg], span)) => { + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span) + }, + _ => {}, + }, + ("unwrap_or_else", [u_arg]) => match method_call!(recv) { + Some(("map", [recv, map_arg], _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, msrv) => {}, + _ => unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"), + }, + _ => {}, } } } +fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) { + if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call!(recv) { + search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span) + } +} + /// Used for `lint_binary_expr_with_method_call`. #[derive(Copy, Clone)] struct BinaryExprInfo<'a> { @@ -2022,7 +2085,7 @@ struct BinaryExprInfo<'a> { /// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExprInfo<'_>) { macro_rules! lint_with_both_lhs_and_rhs { - ($func:ident, $cx:expr, $info:ident) => { + ($func:expr, $cx:expr, $info:ident) => { if !$func($cx, $info) { ::std::mem::swap(&mut $info.chain, &mut $info.other); if $func($cx, $info) { @@ -2032,145 +2095,10 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr }; } - lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_last_cmp, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_next_cmp_with_unwrap, cx, info); - lint_with_both_lhs_and_rhs!(lint_chars_last_cmp_with_unwrap, cx, info); -} - -/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints. -fn lint_chars_cmp( - cx: &LateContext<'_>, - info: &BinaryExprInfo<'_>, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.kind; - if arg_char.len() == 1; - if let hir::ExprKind::Path(ref qpath) = fun.kind; - if let Some(segment) = single_segment_path(qpath); - if segment.ident.name == sym::Some; - then { - let mut applicability = Applicability::MachineApplicable; - let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs(); - - if *self_ty.kind() != ty::Str { - return false; - } - - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}({})", - if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), - suggest, - snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)), - applicability, - ); - - return true; - } - } - - false -} - -/// Checks for the `CHARS_NEXT_CMP` lint. -fn lint_chars_next_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with") -} - -/// Checks for the `CHARS_LAST_CMP` lint. -fn lint_chars_last_cmp<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") { - true - } else { - lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with") - } -} - -/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`. -fn lint_chars_cmp_with_unwrap<'tcx>( - cx: &LateContext<'tcx>, - info: &BinaryExprInfo<'_>, - chain_methods: &[&str], - lint: &'static Lint, - suggest: &str, -) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Lit(ref lit) = info.other.kind; - if let ast::LitKind::Char(c) = lit.node; - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{}` method", suggest), - "like this", - format!("{}{}.{}('{}')", - if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability), - suggest, - c), - applicability, - ); - - true - } else { - false - } - } -} - -/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`. -fn lint_chars_next_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with") -} - -/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`. -fn lint_chars_last_cmp_with_unwrap<'tcx>(cx: &LateContext<'tcx>, info: &BinaryExprInfo<'_>) -> bool { - if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") { - true - } else { - lint_chars_cmp_with_unwrap(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with") - } -} - -fn get_hint_if_single_char_arg( - cx: &LateContext<'_>, - arg: &hir::Expr<'_>, - applicability: &mut Applicability, -) -> Option<String> { - if_chain! { - if let hir::ExprKind::Lit(lit) = &arg.kind; - if let ast::LitKind::Str(r, style) = lit.node; - let string = r.as_str(); - if string.chars().count() == 1; - then { - let snip = snippet_with_applicability(cx, arg.span, &string, applicability); - let ch = if let ast::StrStyle::Raw(nhash) = style { - let nhash = nhash as usize; - // for raw string: r##"a"## - &snip[(nhash + 2)..(snip.len() - 1 - nhash)] - } else { - // for regular string: "a" - &snip[1..(snip.len() - 1)] - }; - let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch }); - Some(hint) - } else { - None - } - } + lint_with_both_lhs_and_rhs!(chars_next_cmp::check, cx, info); + lint_with_both_lhs_and_rhs!(chars_last_cmp::check, cx, info); + lint_with_both_lhs_and_rhs!(chars_next_cmp_with_unwrap::check, cx, info); + lint_with_both_lhs_and_rhs!(chars_last_cmp_with_unwrap::check, cx, info); } const FN_HEADER: hir::FnHeader = hir::FnHeader { @@ -2336,10 +2264,10 @@ impl SelfKind { #[must_use] fn description(self) -> &'static str { match self { - Self::Value => "self by value", - Self::Ref => "self by reference", - Self::RefMut => "self by mutable reference", - Self::No => "no self", + Self::Value => "`self` by value", + Self::Ref => "`self` by reference", + Self::RefMut => "`self` by mutable reference", + Self::No => "no `self`", } } } @@ -2353,22 +2281,22 @@ enum OutType { } impl OutType { - fn matches(self, cx: &LateContext<'_>, ty: &hir::FnRetTy<'_>) -> bool { - let is_unit = |ty: &hir::Ty<'_>| SpanlessEq::new(cx).eq_ty_kind(&ty.kind, &hir::TyKind::Tup(&[])); + fn matches(self, ty: &hir::FnRetTy<'_>) -> bool { + let is_unit = |ty: &hir::Ty<'_>| matches!(ty.kind, hir::TyKind::Tup(&[])); match (self, ty) { (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true, - (Self::Unit, &hir::FnRetTy::Return(ref ty)) if is_unit(ty) => true, - (Self::Bool, &hir::FnRetTy::Return(ref ty)) if is_bool(ty) => true, - (Self::Any, &hir::FnRetTy::Return(ref ty)) if !is_unit(ty) => true, - (Self::Ref, &hir::FnRetTy::Return(ref ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)), + (Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true, + (Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true, + (Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true, + (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)), _ => false, } } } fn is_bool(ty: &hir::Ty<'_>) -> bool { - if let hir::TyKind::Path(ref p) = ty.kind { - match_qpath(p, &["bool"]) + if let hir::TyKind::Path(QPath::Resolved(_, path)) = ty.kind { + matches!(path.res, Res::PrimTy(PrimTy::Bool)) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs index c1706cc7cc..d0b1b4b84b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs @@ -1,4 +1,5 @@ -use crate::utils::{implements_trait, is_type_diagnostic_item, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; @@ -8,11 +9,11 @@ use rustc_span::sym; use super::OK_EXPECT; /// lint use of `ok().expect()` for `Result`s -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if_chain! { // lint if the caller of `ok()` is a `Result` - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&ok_args[0]), sym::result_type); - let result_type = cx.typeck_results().expr_ty(&ok_args[0]); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); + let result_type = cx.typeck_results().expr_ty(recv); if let Some(error_type) = get_error_type(cx, result_type); if has_debug_impl(error_type, cx); diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 89067dbfe0..5a57135038 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -1,7 +1,7 @@ -use crate::utils::{ - is_type_diagnostic_item, match_def_path, meets_msrv, path_to_local_id, paths, remove_blocks, snippet, - span_lint_and_sugg, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{match_def_path, meets_msrv, msrvs, path_to_local_id, paths, remove_blocks}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -12,24 +12,22 @@ use rustc_span::sym; use super::OPTION_AS_REF_DEREF; -const OPTION_AS_REF_DEREF_MSRV: RustcVersion = RustcVersion::new(1, 40, 0); - /// lint use of `_.as_ref().map(Deref::deref)` for `Option`s pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, - as_ref_args: &[hir::Expr<'_>], - map_args: &[hir::Expr<'_>], + as_ref_recv: &hir::Expr<'_>, + map_arg: &hir::Expr<'_>, is_mut: bool, msrv: Option<&RustcVersion>, ) { - if !meets_msrv(msrv, &OPTION_AS_REF_DEREF_MSRV) { + if !meets_msrv(msrv, &msrvs::OPTION_AS_DEREF) { return; } let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not); - let option_ty = cx.typeck_results().expr_ty(&as_ref_args[0]); + let option_ty = cx.typeck_results().expr_ty(as_ref_recv); if !is_type_diagnostic_item(cx, option_ty, sym::option_type) { return; } @@ -46,9 +44,9 @@ pub(super) fn check<'tcx>( &paths::VEC_AS_MUT_SLICE, ]; - let is_deref = match map_args[1].kind { + let is_deref = match map_arg.kind { hir::ExprKind::Path(ref expr_qpath) => cx - .qpath_res(expr_qpath, map_args[1].hir_id) + .qpath_res(expr_qpath, map_arg.hir_id) .opt_def_id() .map_or(false, |fun_def_id| { deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path)) @@ -77,10 +75,10 @@ pub(super) fn check<'tcx>( } } }, - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref inner) if same_mutability(m) => { + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, inner) if same_mutability(m) => { if_chain! { - if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner1) = inner.kind; - if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner2) = inner1.kind; + if let hir::ExprKind::Unary(hir::UnOp::Deref, inner1) = inner.kind; + if let hir::ExprKind::Unary(hir::UnOp::Deref, inner2) = inner1.kind; then { path_to_local_id(inner2, closure_body.params[0].pat.hir_id) } else { @@ -96,12 +94,12 @@ pub(super) fn check<'tcx>( if is_deref { let current_method = if is_mut { - format!(".as_mut().map({})", snippet(cx, map_args[1].span, "..")) + format!(".as_mut().map({})", snippet(cx, map_arg.span, "..")) } else { - format!(".as_ref().map({})", snippet(cx, map_args[1].span, "..")) + format!(".as_ref().map({})", snippet(cx, map_arg.span, "..")) }; let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" }; - let hint = format!("{}.{}()", snippet(cx, as_ref_args[0].span, ".."), method_hint); + let hint = format!("{}.{}()", snippet(cx, as_ref_recv.span, ".."), method_hint); let suggestion = format!("try using {} instead", method_hint); let msg = format!( diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs index 64f6ebc506..36a1c13d5b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs @@ -1,6 +1,10 @@ -use crate::utils::{is_type_diagnostic_item, match_qpath, paths, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_lang_ctor; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; use rustc_hir as hir; +use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_lint::LateContext; use rustc_span::symbol::sym; @@ -8,9 +12,15 @@ use super::OPTION_MAP_OR_NONE; use super::RESULT_MAP_OR_INTO_OPTION; /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map_or_args: &'tcx [hir::Expr<'_>]) { - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_or_args[0]), sym::option_type); - let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_or_args[0]), sym::result_type); +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + recv: &'tcx hir::Expr<'_>, + def_arg: &'tcx hir::Expr<'_>, + map_arg: &'tcx hir::Expr<'_>, +) { + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); // There are two variants of this `map_or` lint: // (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>` @@ -22,8 +32,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map } let (lint_name, msg, instead, hint) = { - let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].kind { - match_qpath(qpath, &paths::OPTION_NONE) + let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind { + is_lang_ctor(cx, qpath, OptionNone) } else { return; }; @@ -33,15 +43,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map return; } - let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_or_args[2].kind { - match_qpath(qpath, &paths::OPTION_SOME) + let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind { + is_lang_ctor(cx, qpath, OptionSome) } else { false }; if is_option { - let self_snippet = snippet(cx, map_or_args[0].span, ".."); - let func_snippet = snippet(cx, map_or_args[2].span, ".."); + let self_snippet = snippet(cx, recv.span, ".."); + let func_snippet = snippet(cx, map_arg.span, ".."); let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \ `and_then(..)` instead"; ( @@ -53,7 +63,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map } else if f_arg_is_some { let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \ `ok()` instead"; - let self_snippet = snippet(cx, map_or_args[0].span, ".."); + let self_snippet = snippet(cx, recv.span, ".."); ( RESULT_MAP_OR_INTO_OPTION, msg, diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 7cdd49bbf0..5bca49dec2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,5 +1,8 @@ -use crate::utils::{differing_macro_contexts, snippet_with_applicability, span_lint_and_then}; -use crate::utils::{is_copy, is_type_diagnostic_item}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::differing_macro_contexts; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_copy; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; @@ -15,13 +18,15 @@ use super::MAP_UNWRAP_OR; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &rustc_hir::Expr<'_>, - map_args: &'tcx [rustc_hir::Expr<'_>], - unwrap_args: &'tcx [rustc_hir::Expr<'_>], + recv: &rustc_hir::Expr<'_>, + map_arg: &'tcx rustc_hir::Expr<'_>, + unwrap_recv: &rustc_hir::Expr<'_>, + unwrap_arg: &'tcx rustc_hir::Expr<'_>, map_span: Span, ) { // lint if the caller of `map()` is an `Option` - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::option_type) { - if !is_copy(cx, cx.typeck_results().expr_ty(&unwrap_args[1])) { + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type) { + if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { // Do not lint if the `map` argument uses identifiers in the `map` // argument that are also used in the `unwrap_or` argument @@ -29,27 +34,27 @@ pub(super) fn check<'tcx>( cx, identifiers: FxHashSet::default(), }; - unwrap_visitor.visit_expr(&unwrap_args[1]); + unwrap_visitor.visit_expr(unwrap_arg); let mut map_expr_visitor = MapExprVisitor { cx, identifiers: unwrap_visitor.identifiers, found_identifier: false, }; - map_expr_visitor.visit_expr(&map_args[1]); + map_expr_visitor.visit_expr(map_arg); if map_expr_visitor.found_identifier { return; } } - if differing_macro_contexts(unwrap_args[1].span, map_span) { + if differing_macro_contexts(unwrap_arg.span, map_span) { return; } let mut applicability = Applicability::MachineApplicable; // get snippet for unwrap_or() - let unwrap_snippet = snippet_with_applicability(cx, unwrap_args[1].span, "..", &mut applicability); + let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability); // lint message // comparing the snippet from source to raw text ("None") below is safe // because we already have checked the type. @@ -67,14 +72,14 @@ pub(super) fn check<'tcx>( ); span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { - let map_arg_span = map_args[1].span; + let map_arg_span = map_arg.span; let mut suggestion = vec![ ( map_span, String::from(if unwrap_snippet_none { "and_then" } else { "map_or" }), ), - (expr.span.with_lo(unwrap_args[0].span.hi()), String::from("")), + (expr.span.with_lo(unwrap_recv.span.hi()), String::from("")), ]; if !unwrap_snippet_none { diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index 5f7fc431d2..800172f4cf 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -1,15 +1,16 @@ -use crate::utils::eager_or_lazy::is_lazyness_candidate; -use crate::utils::{ - contains_return, get_trait_def_id, implements_trait, is_type_diagnostic_item, last_path_segment, match_type, paths, - snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint_and_sugg, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::eager_or_lazy::is_lazyness_candidate; +use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_macro_callsite}; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type}; +use clippy_utils::{contains_return, get_trait_def_id, last_path_segment, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; +use rustc_hir::{BlockCheckMode, UnsafeSource}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::source_map::Span; -use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, sym}; use std::borrow::Cow; use super::OR_FUN_CALL; @@ -37,8 +38,8 @@ pub(super) fn check<'tcx>( if !or_has_args; if name == "unwrap_or"; if let hir::ExprKind::Path(ref qpath) = fun.kind; - let path = &*last_path_segment(qpath).ident.as_str(); - if ["default", "new"].contains(&path); + let path = last_path_segment(qpath).ident.name; + if matches!(path, kw::Default | sym::new); let arg_ty = cx.typeck_results().expr_ty(arg); if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); if implements_trait(cx, arg_ty, default_trait_id, &[]); @@ -85,12 +86,12 @@ pub(super) fn check<'tcx>( (&paths::RESULT, true, &["or", "unwrap_or"], "else"), ]; - if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = &arg.kind { + if let hir::ExprKind::MethodCall(path, _, args, _) = &arg.kind { if path.ident.as_str() == "len" { let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs(); match ty.kind() { - ty::Slice(_) | ty::Array(_, _) => return, + ty::Slice(_) | ty::Array(_, _) | ty::Str => return, _ => (), } @@ -104,7 +105,7 @@ pub(super) fn check<'tcx>( if KNOW_TYPES.iter().any(|k| k.2.contains(&name)); if is_lazyness_candidate(cx, arg); - if !contains_return(&arg); + if !contains_return(arg); let self_ty = cx.typeck_results().expr_ty(self_expr); @@ -157,7 +158,7 @@ pub(super) fn check<'tcx>( if args.len() == 2 { match args[1].kind { - hir::ExprKind::Call(ref fun, ref or_args) => { + hir::ExprKind::Call(fun, or_args) => { let or_has_args = !or_args.is_empty(); if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) { let fun_span = if or_has_args { None } else { Some(fun.span) }; @@ -167,7 +168,16 @@ pub(super) fn check<'tcx>( hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => { check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None); }, - _ => {}, + hir::ExprKind::Block(block, _) => { + if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules { + if let Some(block_expr) = block.expr { + if let hir::ExprKind::MethodCall(..) = block_expr.kind { + check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None); + } + } + } + }, + _ => (), } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs index e9e6544322..ecec6fc3bb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs @@ -1,7 +1,7 @@ -use crate::utils::{ - is_type_diagnostic_item, match_trait_method, paths, snippet, snippet_with_applicability, span_lint_and_help, - span_lint_and_sugg, strip_pat_refs, -}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_trait_method, strip_pat_refs}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -14,35 +14,38 @@ use rustc_span::symbol::sym; use super::SEARCH_IS_SOME; /// lint searching an Iterator followed by `is_some()` -/// or calling `find()` on a string followed by `is_some()` +/// or calling `find()` on a string followed by `is_some()` or `is_none()` +#[allow(clippy::too_many_arguments, clippy::too_many_lines)] pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, + cx: &LateContext<'_>, expr: &'tcx hir::Expr<'_>, search_method: &str, - search_args: &'tcx [hir::Expr<'_>], - is_some_args: &'tcx [hir::Expr<'_>], + is_some: bool, + search_recv: &hir::Expr<'_>, + search_arg: &'tcx hir::Expr<'_>, + is_some_recv: &hir::Expr<'_>, method_span: Span, ) { + let option_check_method = if is_some { "is_some" } else { "is_none" }; // lint if caller of search is an Iterator - if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) { + if is_trait_method(cx, is_some_recv, sym::Iterator) { let msg = format!( - "called `is_some()` after searching an `Iterator` with `{}`", - search_method + "called `{}()` after searching an `Iterator` with `{}`", + option_check_method, search_method ); - let hint = "this is more succinctly expressed by calling `any()`"; - let search_snippet = snippet(cx, search_args[1].span, ".."); + let search_snippet = snippet(cx, search_arg.span, ".."); if search_snippet.lines().count() <= 1 { // suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()` // suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()` let any_search_snippet = if_chain! { if search_method == "find"; - if let hir::ExprKind::Closure(_, _, body_id, ..) = search_args[1].kind; + if let hir::ExprKind::Closure(_, _, body_id, ..) = search_arg.kind; let closure_body = cx.tcx.hir().body(body_id); if let Some(closure_arg) = closure_body.params.get(0); then { if let hir::PatKind::Ref(..) = closure_arg.pat.kind { Some(search_snippet.replacen('&', "", 1)) - } else if let PatKind::Binding(_, _, ident, _) = strip_pat_refs(&closure_arg.pat).kind { + } else if let PatKind::Binding(_, _, ident, _) = strip_pat_refs(closure_arg.pat).kind { let name = &*ident.name.as_str(); Some(search_snippet.replace(&format!("*{}", name), name)) } else { @@ -53,20 +56,45 @@ pub(super) fn check<'tcx>( } }; // add note if not multi-line - span_lint_and_sugg( - cx, - SEARCH_IS_SOME, - method_span.with_hi(expr.span.hi()), - &msg, - "use `any()` instead", - format!( - "any({})", - any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str) - ), - Applicability::MachineApplicable, - ); + if is_some { + span_lint_and_sugg( + cx, + SEARCH_IS_SOME, + method_span.with_hi(expr.span.hi()), + &msg, + "use `any()` instead", + format!( + "any({})", + any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str) + ), + Applicability::MachineApplicable, + ); + } else { + let iter = snippet(cx, search_recv.span, ".."); + span_lint_and_sugg( + cx, + SEARCH_IS_SOME, + expr.span, + &msg, + "use `!_.any()` instead", + format!( + "!{}.any({})", + iter, + any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str) + ), + Applicability::MachineApplicable, + ); + } } else { - span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, &msg, None, hint); + let hint = format!( + "this is more succinctly expressed by calling `any()`{}", + if option_check_method == "is_none" { + " with negation" + } else { + "" + } + ); + span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, &msg, None, &hint); } } // lint if `find()` is called by `String` or `&str` @@ -80,21 +108,40 @@ pub(super) fn check<'tcx>( } }; if_chain! { - if is_string_or_str_slice(&search_args[0]); - if is_string_or_str_slice(&search_args[1]); + if is_string_or_str_slice(search_recv); + if is_string_or_str_slice(search_arg); then { - let msg = "called `is_some()` after calling `find()` on a string"; - let mut applicability = Applicability::MachineApplicable; - let find_arg = snippet_with_applicability(cx, search_args[1].span, "..", &mut applicability); - span_lint_and_sugg( - cx, - SEARCH_IS_SOME, - method_span.with_hi(expr.span.hi()), - msg, - "use `contains()` instead", - format!("contains({})", find_arg), - applicability, - ); + let msg = format!("called `{}()` after calling `find()` on a string", option_check_method); + match option_check_method { + "is_some" => { + let mut applicability = Applicability::MachineApplicable; + let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability); + span_lint_and_sugg( + cx, + SEARCH_IS_SOME, + method_span.with_hi(expr.span.hi()), + &msg, + "use `contains()` instead", + format!("contains({})", find_arg), + applicability, + ); + }, + "is_none" => { + let string = snippet(cx, search_recv.span, ".."); + let mut applicability = Applicability::MachineApplicable; + let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability); + span_lint_and_sugg( + cx, + SEARCH_IS_SOME, + expr.span, + &msg, + "use `!_.contains()` instead", + format!("!{}.contains({})", string, find_arg), + applicability, + ); + }, + _ => (), + } } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs new file mode 100644 index 0000000000..9a5fabcf7c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs @@ -0,0 +1,14 @@ +use crate::methods::{single_char_insert_string, single_char_push_string}; +use clippy_utils::{match_def_path, paths}; +use rustc_hir as hir; +use rustc_lint::LateContext; + +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { + if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { + if match_def_path(cx, fn_def_id, &paths::PUSH_STR) { + single_char_push_string::check(cx, expr, args); + } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) { + single_char_insert_string::check(cx, expr, args); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs index 0ce8b66978..6cdc954c03 100644 --- a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs @@ -1,5 +1,6 @@ -use crate::methods::get_hint_if_single_char_arg; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use super::utils::get_hint_if_single_char_arg; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs index 61cbc9d2f0..f4090c7c61 100644 --- a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs @@ -1,23 +1,35 @@ -use crate::methods::get_hint_if_single_char_arg; -use crate::utils::span_lint_and_sugg; +use super::utils::get_hint_if_single_char_arg; +use clippy_utils::diagnostics::span_lint_and_sugg; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_span::symbol::Symbol; use super::SINGLE_CHAR_PATTERN; /// lint for length-1 `str`s for methods in `PATTERN_METHODS` -pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { - let mut applicability = Applicability::MachineApplicable; - if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability) { - span_lint_and_sugg( - cx, - SINGLE_CHAR_PATTERN, - arg.span, - "single-character string constant used as pattern", - "try using a `char` instead", - hint, - applicability, - ); +pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) { + for &(method, pos) in &crate::methods::PATTERN_METHODS { + if_chain! { + if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(&args[0]).kind(); + if *ty.kind() == ty::Str; + if method_name.as_str() == method && args.len() > pos; + let arg = &args[pos]; + let mut applicability = Applicability::MachineApplicable; + if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability); + then { + span_lint_and_sugg( + cx, + SINGLE_CHAR_PATTERN, + arg.span, + "single-character string constant used as pattern", + "try using a `char` instead", + hint, + applicability, + ); + } + } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs index deacc70b71..0237d39cbd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs @@ -1,5 +1,6 @@ -use crate::methods::get_hint_if_single_char_arg; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use super::utils::get_hint_if_single_char_arg; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs b/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs index 8ba6ae9520..9f0b6c34ea 100644 --- a/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/skip_while_next.rs @@ -1,13 +1,15 @@ -use crate::utils::{match_trait_method, paths, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_trait_method; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_span::sym; use super::SKIP_WHILE_NEXT; /// lint use of `skip_while().next()` for `Iterators` -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, _skip_while_args: &'tcx [hir::Expr<'_>]) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { // lint if caller of `.skip_while().next()` is an Iterator - if match_trait_method(cx, expr, &paths::ITERATOR) { + if is_trait_method(cx, expr, sym::Iterator) { span_lint_and_help( cx, SKIP_WHILE_NEXT, diff --git a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs index 0a08ea2617..6e7890a308 100644 --- a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs +++ b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs @@ -1,4 +1,7 @@ -use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::method_chain_args; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -7,36 +10,36 @@ use rustc_span::symbol::sym; use super::STRING_EXTEND_CHARS; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - let obj_ty = cx.typeck_results().expr_ty(&args[0]).peel_refs(); - if is_type_diagnostic_item(cx, obj_ty, sym::string_type) { - let arg = &args[1]; - if let Some(arglists) = method_chain_args(arg, &["chars"]) { - let target = &arglists[0][0]; - let self_ty = cx.typeck_results().expr_ty(target).peel_refs(); - let ref_str = if *self_ty.kind() == ty::Str { - "" - } else if is_type_diagnostic_item(cx, self_ty, sym::string_type) { - "&" - } else { - return; - }; +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { + let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + if !is_type_diagnostic_item(cx, obj_ty, sym::string_type) { + return; + } + if let Some(arglists) = method_chain_args(arg, &["chars"]) { + let target = &arglists[0][0]; + let self_ty = cx.typeck_results().expr_ty(target).peel_refs(); + let ref_str = if *self_ty.kind() == ty::Str { + "" + } else if is_type_diagnostic_item(cx, self_ty, sym::string_type) { + "&" + } else { + return; + }; - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - STRING_EXTEND_CHARS, - expr.span, - "calling `.extend(_.chars())`", - "try this", - format!( - "{}.push_str({}{})", - snippet_with_applicability(cx, args[0].span, "..", &mut applicability), - ref_str, - snippet_with_applicability(cx, target.span, "..", &mut applicability) - ), - applicability, - ); - } + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + STRING_EXTEND_CHARS, + expr.span, + "calling `.extend(_.chars())`", + "try this", + format!( + "{}.push_str({}{})", + snippet_with_applicability(cx, recv.span, "..", &mut applicability), + ref_str, + snippet_with_applicability(cx, target.span, "..", &mut applicability) + ), + applicability, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs index e135a826dc..0fd0668c73 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs @@ -1,16 +1,35 @@ -use crate::utils::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::usage::mutated_variables; +use clippy_utils::{expr_or_init, is_trait_method}; +use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_span::sym; use super::SUSPICIOUS_MAP; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>) { - span_lint_and_help( - cx, - SUSPICIOUS_MAP, - expr.span, - "this call to `map()` won't have an effect on the call to `count()`", - None, - "make sure you did not confuse `map` with `filter` or `for_each`", - ); +pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) { + if_chain! { + if is_trait_method(cx, count_recv, sym::Iterator); + let closure = expr_or_init(cx, map_arg); + if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(closure.hir_id); + let closure_body = cx.tcx.hir().body(body_id); + if !cx.typeck_results().expr_ty(&closure_body.value).is_unit(); + then { + if let Some(map_mutated_vars) = mutated_variables(&closure_body.value, cx) { + // A variable is used mutably inside of the closure. Suppress the lint. + if !map_mutated_vars.is_empty() { + return; + } + } + span_lint_and_help( + cx, + SUSPICIOUS_MAP, + expr.span, + "this call to `map()` won't have an effect on the call to `count()`", + None, + "make sure you did not confuse `map` with `filter` or `for_each`", + ); + } + } } diff --git a/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs b/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs index 798b66192c..1a5894e48d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs +++ b/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs @@ -1,4 +1,5 @@ -use crate::utils::{match_def_path, match_qpath, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_expr_path_def_path, match_def_path, paths}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; @@ -7,18 +8,17 @@ use rustc_middle::ty::{self, Ty}; use super::UNINIT_ASSUMED_INIT; /// lint for `MaybeUninit::uninit().assume_init()` (we already have the latter) -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, outer: &hir::Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if_chain! { - if let hir::ExprKind::Call(ref callee, ref args) = expr.kind; + if let hir::ExprKind::Call(callee, args) = recv.kind; if args.is_empty(); - if let hir::ExprKind::Path(ref path) = callee.kind; - if match_qpath(path, &paths::MEM_MAYBEUNINIT_UNINIT); - if !is_maybe_uninit_ty_valid(cx, cx.typeck_results().expr_ty_adjusted(outer)); + if is_expr_path_def_path(cx, callee, &paths::MEM_MAYBEUNINIT_UNINIT); + if !is_maybe_uninit_ty_valid(cx, cx.typeck_results().expr_ty_adjusted(expr)); then { span_lint( cx, UNINIT_ASSUMED_INIT, - outer.span, + expr.span, "this call for this type may be undefined behavior" ); } @@ -27,9 +27,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, outer: &hir::Exp fn is_maybe_uninit_ty_valid(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { match ty.kind() { - ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component), - ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)), - ty::Adt(ref adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT), + ty::Array(component, _) => is_maybe_uninit_ty_valid(cx, component), + ty::Tuple(types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)), + ty::Adt(adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index 12b2cf0a16..b61c4ffe9b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -1,28 +1,29 @@ -use crate::utils::usage::mutated_variables; -use crate::utils::{match_qpath, match_trait_method, path_to_local_id, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::usage::mutated_variables; +use clippy_utils::{is_lang_ctor, is_trait_method, path_to_local_id}; use rustc_hir as hir; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; - -use if_chain::if_chain; +use rustc_span::sym; use super::UNNECESSARY_FILTER_MAP; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - if !match_trait_method(cx, expr, &paths::ITERATOR) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>) { + if !is_trait_method(cx, expr, sym::Iterator) { return; } - if let hir::ExprKind::Closure(_, _, body_id, ..) = args[1].kind { + if let hir::ExprKind::Closure(_, _, body_id, ..) = arg.kind { let body = cx.tcx.hir().body(body_id); let arg_id = body.params[0].pat.hir_id; let mutates_arg = mutated_variables(&body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id)); - let (mut found_mapping, mut found_filtering) = check_expression(&cx, arg_id, &body.value); + let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, &body.value); - let mut return_visitor = ReturnVisitor::new(&cx, arg_id); + let mut return_visitor = ReturnVisitor::new(cx, arg_id); return_visitor.visit_expr(&body.value); found_mapping |= return_visitor.found_mapping; found_filtering |= return_visitor.found_filtering; @@ -52,43 +53,38 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp // returns (found_mapping, found_filtering) fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> (bool, bool) { match &expr.kind { - hir::ExprKind::Call(ref func, ref args) => { - if_chain! { - if let hir::ExprKind::Path(ref path) = func.kind; - then { - if match_qpath(path, &paths::OPTION_SOME) { - if path_to_local_id(&args[0], arg_id) { - return (false, false) - } - return (true, false); + hir::ExprKind::Call(func, args) => { + if let hir::ExprKind::Path(ref path) = func.kind { + if is_lang_ctor(cx, path, OptionSome) { + if path_to_local_id(&args[0], arg_id) { + return (false, false); } - // We don't know. It might do anything. - return (true, true); + return (true, false); } } (true, true) }, - hir::ExprKind::Block(ref block, _) => block + hir::ExprKind::Block(block, _) => block .expr .as_ref() - .map_or((false, false), |expr| check_expression(cx, arg_id, &expr)), + .map_or((false, false), |expr| check_expression(cx, arg_id, expr)), hir::ExprKind::Match(_, arms, _) => { let mut found_mapping = false; let mut found_filtering = false; for arm in *arms { - let (m, f) = check_expression(cx, arg_id, &arm.body); + let (m, f) = check_expression(cx, arg_id, arm.body); found_mapping |= m; found_filtering |= f; } (found_mapping, found_filtering) }, // There must be an else_arm or there will be a type error - hir::ExprKind::If(_, ref if_arm, Some(ref else_arm)) => { + hir::ExprKind::If(_, if_arm, Some(else_arm)) => { let if_check = check_expression(cx, arg_id, if_arm); let else_check = check_expression(cx, arg_id, else_arm); (if_check.0 | else_check.0, if_check.1 | else_check.1) }, - hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true), + hir::ExprKind::Path(path) if is_lang_ctor(cx, path, OptionNone) => (false, true), _ => (true, true), } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index a26443f4ee..75517c48a2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -1,22 +1,27 @@ -use crate::utils::{ - match_trait_method, path_to_local_id, paths, remove_blocks, snippet_with_applicability, span_lint_and_sugg, - strip_pat_refs, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{is_trait_method, path_to_local_id, remove_blocks, strip_pat_refs}; use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::PatKind; use rustc_lint::LateContext; -use rustc_span::source_map::Span; +use rustc_span::{source_map::Span, sym}; use super::UNNECESSARY_FOLD; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir::Expr<'_>], fold_span: Span) { +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + init: &hir::Expr<'_>, + acc: &hir::Expr<'_>, + fold_span: Span, +) { fn check_fold_with_op( cx: &LateContext<'_>, expr: &hir::Expr<'_>, - fold_args: &[hir::Expr<'_>], + acc: &hir::Expr<'_>, fold_span: Span, op: hir::BinOpKind, replacement_method_name: &str, @@ -24,18 +29,18 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir ) { if_chain! { // Extract the body of the closure passed to fold - if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].kind; + if let hir::ExprKind::Closure(_, _, body_id, _, _) = acc.kind; let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); // Check if the closure body is of the form `acc <op> some_expr(x)` - if let hir::ExprKind::Binary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.kind; + if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind; if bin_op.node == op; // Extract the names of the two arguments to the closure if let [param_a, param_b] = closure_body.params; - if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(¶m_a.pat).kind; - if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(¶m_b.pat).kind; + if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind; + if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind; if path_to_local_id(left_expr, first_arg_id); if replacement_has_args || path_to_local_id(right_expr, second_arg_id); @@ -71,29 +76,18 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: &[hir } // Check that this is a call to Iterator::fold rather than just some function called fold - if !match_trait_method(cx, expr, &paths::ITERATOR) { + if !is_trait_method(cx, expr, sym::Iterator) { return; } - assert!( - fold_args.len() == 3, - "Expected fold_args to have three entries - the receiver, the initial value and the closure" - ); - // Check if the first argument to .fold is a suitable literal - if let hir::ExprKind::Lit(ref lit) = fold_args[1].kind { + if let hir::ExprKind::Lit(ref lit) = init.kind { match lit.node { - ast::LitKind::Bool(false) => { - check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::Or, "any", true) - }, - ast::LitKind::Bool(true) => { - check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::And, "all", true) - }, - ast::LitKind::Int(0, _) => { - check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::Add, "sum", false) - }, + ast::LitKind::Bool(false) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, "any", true), + ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true), + ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false), ast::LitKind::Int(1, _) => { - check_fold_with_op(cx, expr, fold_args, fold_span, hir::BinOpKind::Mul, "product", false) + check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false) }, _ => (), } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index a17259d697..b7380883a5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -1,5 +1,7 @@ -use crate::utils::{eager_or_lazy, usage}; -use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{eager_or_lazy, usage}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -12,14 +14,15 @@ use super::UNNECESSARY_LAZY_EVALUATIONS; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, - args: &'tcx [hir::Expr<'_>], + recv: &'tcx hir::Expr<'_>, + arg: &'tcx hir::Expr<'_>, simplify_using: &str, ) { - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym::option_type); - let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]), sym::result_type); + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); if is_option || is_result { - if let hir::ExprKind::Closure(_, _, eid, _, _) = args[1].kind { + if let hir::ExprKind::Closure(_, _, eid, _, _) = arg.kind { let body = cx.tcx.hir().body(eid); let body_expr = &body.value; @@ -53,7 +56,7 @@ pub(super) fn check<'tcx>( &format!("use `{}` instead", simplify_using), format!( "{0}.{1}({2})", - snippet(cx, args[0].span, ".."), + snippet(cx, recv.span, ".."), simplify_using, snippet(cx, body_expr.span, ".."), ), diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs index 094c3fc45c..7fd1948594 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_type_diagnostic_item, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::sym; @@ -6,8 +7,8 @@ use rustc_span::sym; use super::UNWRAP_USED; /// lint use of `unwrap()` for `Option`s and `Result`s -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) { - let obj_ty = cx.typeck_results().expr_ty(&unwrap_args[0]).peel_refs(); +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { + let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); let mess = if is_type_diagnostic_item(cx, obj_ty, sym::option_type) { Some((UNWRAP_USED, "an Option", "None")) diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs index e4554f8d48..e0b1de68b3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs @@ -1,6 +1,7 @@ -use crate::utils::{ - get_parent_expr, match_trait_method, paths, snippet_with_applicability, span_lint_and_sugg, walk_ptrs_ty_depth, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::walk_ptrs_ty_depth; +use clippy_utils::{get_parent_expr, match_trait_method, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -9,12 +10,11 @@ use rustc_lint::LateContext; use super::USELESS_ASREF; /// Checks for the `USELESS_ASREF` lint. -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, as_ref_args: &[hir::Expr<'_>]) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, recvr: &hir::Expr<'_>) { // when we get here, we've already checked that the call name is "as_ref" or "as_mut" // check if the call is to the actual `AsRef` or `AsMut` trait if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) { // check if the type after `as_ref` or `as_mut` is the same as before - let recvr = &as_ref_args[0]; let rcv_ty = cx.typeck_results().expr_ty(recvr); let res_ty = cx.typeck_results().expr_ty(expr); let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty); diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs new file mode 100644 index 0000000000..0daea47816 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs @@ -0,0 +1,75 @@ +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty}; +use rustc_span::symbol::sym; + +pub(super) fn derefs_to_slice<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ty: Ty<'tcx>, +) -> Option<&'tcx hir::Expr<'tcx>> { + fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { + match ty.kind() { + ty::Slice(_) => true, + ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), + ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type), + ty::Array(_, size) => size.try_eval_usize(cx.tcx, cx.param_env).is_some(), + ty::Ref(_, inner, _) => may_slice(cx, inner), + _ => false, + } + } + + if let hir::ExprKind::MethodCall(path, _, args, _) = expr.kind { + if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) { + Some(&args[0]) + } else { + None + } + } else { + match ty.kind() { + ty::Slice(_) => Some(expr), + ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr), + ty::Ref(_, inner, _) => { + if may_slice(cx, inner) { + Some(expr) + } else { + None + } + }, + _ => None, + } + } +} + +pub(super) fn get_hint_if_single_char_arg( + cx: &LateContext<'_>, + arg: &hir::Expr<'_>, + applicability: &mut Applicability, +) -> Option<String> { + if_chain! { + if let hir::ExprKind::Lit(lit) = &arg.kind; + if let ast::LitKind::Str(r, style) = lit.node; + let string = r.as_str(); + if string.chars().count() == 1; + then { + let snip = snippet_with_applicability(cx, arg.span, &string, applicability); + let ch = if let ast::StrStyle::Raw(nhash) = style { + let nhash = nhash as usize; + // for raw string: r##"a"## + &snip[(nhash + 2)..(snip.len() - 1 - nhash)] + } else { + // for regular string: "a" + &snip[1..(snip.len() - 1)] + }; + let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch }); + Some(hint) + } else { + None + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs index 90fab57743..6e2bcb113c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs +++ b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs @@ -1,5 +1,6 @@ use crate::methods::SelfKind; -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_copy; use rustc_lint::LateContext; use rustc_middle::ty::TyS; use rustc_span::source_map::Span; @@ -9,26 +10,51 @@ use super::WRONG_PUB_SELF_CONVENTION; use super::WRONG_SELF_CONVENTION; #[rustfmt::skip] -const CONVENTIONS: [(Convention, &[SelfKind]); 7] = [ - (Convention::Eq("new"), &[SelfKind::No]), - (Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]), - (Convention::StartsWith("from_"), &[SelfKind::No]), - (Convention::StartsWith("into_"), &[SelfKind::Value]), - (Convention::StartsWith("is_"), &[SelfKind::Ref, SelfKind::No]), - (Convention::Eq("to_mut"), &[SelfKind::RefMut]), - (Convention::StartsWith("to_"), &[SelfKind::Ref]), +const CONVENTIONS: [(&[Convention], &[SelfKind]); 9] = [ + (&[Convention::Eq("new")], &[SelfKind::No]), + (&[Convention::StartsWith("as_")], &[SelfKind::Ref, SelfKind::RefMut]), + (&[Convention::StartsWith("from_")], &[SelfKind::No]), + (&[Convention::StartsWith("into_")], &[SelfKind::Value]), + (&[Convention::StartsWith("is_")], &[SelfKind::Ref, SelfKind::No]), + (&[Convention::Eq("to_mut")], &[SelfKind::RefMut]), + (&[Convention::StartsWith("to_"), Convention::EndsWith("_mut")], &[SelfKind::RefMut]), + + // Conversion using `to_` can use borrowed (non-Copy types) or owned (Copy types). + // Source: https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv + (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false), + Convention::IsTraitItem(false)], &[SelfKind::Ref]), + (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true), + Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Value]), ]; + enum Convention { Eq(&'static str), StartsWith(&'static str), + EndsWith(&'static str), + NotEndsWith(&'static str), + IsSelfTypeCopy(bool), + ImplementsTrait(bool), + IsTraitItem(bool), } impl Convention { #[must_use] - fn check(&self, other: &str) -> bool { + fn check<'tcx>( + &self, + cx: &LateContext<'tcx>, + self_ty: &'tcx TyS<'tcx>, + other: &str, + implements_trait: bool, + is_trait_item: bool, + ) -> bool { match *self { Self::Eq(this) => this == other, Self::StartsWith(this) => other.starts_with(this) && this != other, + Self::EndsWith(this) => other.ends_with(this) && this != other, + Self::NotEndsWith(this) => !Self::EndsWith(this).check(cx, self_ty, other, implements_trait, is_trait_item), + Self::IsSelfTypeCopy(is_true) => is_true == is_copy(cx, self_ty), + Self::ImplementsTrait(is_true) => is_true == implements_trait, + Self::IsTraitItem(is_true) => is_true == is_trait_item, } } } @@ -36,12 +62,26 @@ impl Convention { impl fmt::Display for Convention { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { - Self::Eq(this) => this.fmt(f), - Self::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), + Self::Eq(this) => format!("`{}`", this).fmt(f), + Self::StartsWith(this) => format!("`{}*`", this).fmt(f), + Self::EndsWith(this) => format!("`*{}`", this).fmt(f), + Self::NotEndsWith(this) => format!("`~{}`", this).fmt(f), + Self::IsSelfTypeCopy(is_true) => { + format!("`self` type is{} `Copy`", if is_true { "" } else { " not" }).fmt(f) + }, + Self::ImplementsTrait(is_true) => { + let (negation, s_suffix) = if is_true { ("", "s") } else { (" does not", "") }; + format!("method{} implement{} a trait", negation, s_suffix).fmt(f) + }, + Self::IsTraitItem(is_true) => { + let suffix = if is_true { " is" } else { " is not" }; + format!("method{} a trait item", suffix).fmt(f) + }, } } } +#[allow(clippy::too_many_arguments)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, item_name: &str, @@ -49,27 +89,72 @@ pub(super) fn check<'tcx>( self_ty: &'tcx TyS<'tcx>, first_arg_ty: &'tcx TyS<'tcx>, first_arg_span: Span, + implements_trait: bool, + is_trait_item: bool, ) { let lint = if is_pub { WRONG_PUB_SELF_CONVENTION } else { WRONG_SELF_CONVENTION }; - if let Some((ref conv, self_kinds)) = &CONVENTIONS.iter().find(|(ref conv, _)| conv.check(item_name)) { + if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| { + convs + .iter() + .all(|conv| conv.check(cx, self_ty, item_name, implements_trait, is_trait_item)) + }) { + // don't lint if it implements a trait but not willing to check `Copy` types conventions (see #7032) + if implements_trait + && !conventions + .iter() + .any(|conv| matches!(conv, Convention::IsSelfTypeCopy(_))) + { + return; + } if !self_kinds.iter().any(|k| k.matches(cx, self_ty, first_arg_ty)) { - span_lint( + let suggestion = { + if conventions.len() > 1 { + // Don't mention `NotEndsWith` when there is also `StartsWith` convention present + let cut_ends_with_conv = conventions.iter().any(|conv| matches!(conv, Convention::StartsWith(_))) + && conventions + .iter() + .any(|conv| matches!(conv, Convention::NotEndsWith(_))); + + let s = conventions + .iter() + .filter_map(|conv| { + if (cut_ends_with_conv && matches!(conv, Convention::NotEndsWith(_))) + || matches!(conv, Convention::ImplementsTrait(_)) + || matches!(conv, Convention::IsTraitItem(_)) + { + None + } else { + Some(conv.to_string()) + } + }) + .collect::<Vec<_>>() + .join(" and "); + + format!("methods with the following characteristics: ({})", &s) + } else { + format!("methods called {}", &conventions[0]) + } + }; + + span_lint_and_help( cx, lint, first_arg_span, &format!( - "methods called `{}` usually take {}; consider choosing a less ambiguous name", - conv, + "{} usually take {}", + suggestion, &self_kinds .iter() .map(|k| k.description()) .collect::<Vec<_>>() .join(" or ") ), + None, + "consider choosing a less ambiguous name", ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs index f133572673..866cf61667 100644 --- a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs +++ b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; @@ -6,10 +6,9 @@ use rustc_middle::ty; use super::ZST_OFFSET; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if_chain! { - if args.len() == 2; - if let ty::RawPtr(ty::TypeAndMut { ref ty, .. }) = cx.typeck_results().expr_ty(&args[0]).kind(); + if let ty::RawPtr(ty::TypeAndMut { ty, .. }) = cx.typeck_results().expr_ty(recv).kind(); if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)); if layout.is_zst(); then { diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs index 8d0c3b8e0f..45948f4d92 100644 --- a/src/tools/clippy/clippy_lints/src/minmax.rs +++ b/src/tools/clippy/clippy_lints/src/minmax.rs @@ -1,5 +1,6 @@ use crate::consts::{constant_simple, Constant}; -use crate::utils::{match_def_path, match_trait_method, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{match_def_path, match_trait_method, paths}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -66,7 +67,7 @@ enum MinMax { fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> { match expr.kind { - ExprKind::Call(ref path, ref args) => { + ExprKind::Call(path, args) => { if let ExprKind::Path(ref qpath) = path.kind { cx.typeck_results() .qpath_res(qpath, path.hir_id) @@ -84,7 +85,7 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons None } }, - ExprKind::MethodCall(ref path, _, ref args, _) => { + ExprKind::MethodCall(path, _, args, _) => { if_chain! { if let [obj, _] = args; if cx.typeck_results().expr_ty(obj).is_floating_point() || match_trait_method(cx, expr, &paths::ORD); diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index acdc245456..0b0cd9be46 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -1,3 +1,6 @@ +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::ty::implements_trait; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -15,11 +18,10 @@ use rustc_span::source_map::{ExpnKind, Span}; use rustc_span::symbol::sym; use crate::consts::{constant, Constant}; -use crate::utils::sugg::Sugg; -use crate::utils::{ - get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_diagnostic_assoc_item, is_integer_const, - iter_input_pats, last_path_segment, match_qpath, snippet, snippet_opt, span_lint, span_lint_and_sugg, - span_lint_and_then, span_lint_hir_and_then, unsext, SpanlessEq, +use clippy_utils::sugg::Sugg; +use clippy_utils::{ + expr_path_res, get_item_name, get_parent_expr, higher, in_constant, is_diag_trait_item, is_integer_const, + iter_input_pats, last_path_segment, match_any_def_paths, paths, unsext, SpanlessEq, }; declare_clippy_lint! { @@ -302,55 +304,54 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if_chain! { if !in_external_macro(cx.tcx.sess, stmt.span); - if let StmtKind::Local(ref local) = stmt.kind; + if let StmtKind::Local(local) = stmt.kind; if let PatKind::Binding(an, .., name, None) = local.pat.kind; - if let Some(ref init) = local.init; + if let Some(init) = local.init; if !higher::is_from_for_desugar(local); + if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut; then { - if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut { - // use the macro callsite when the init span (but not the whole local span) - // comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];` - let sugg_init = if init.span.from_expansion() && !local.span.from_expansion() { - Sugg::hir_with_macro_callsite(cx, init, "..") - } else { - Sugg::hir(cx, init, "..") - }; - let (mutopt, initref) = if an == BindingAnnotation::RefMut { - ("mut ", sugg_init.mut_addr()) - } else { - ("", sugg_init.addr()) - }; - let tyopt = if let Some(ref ty) = local.ty { - format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "..")) - } else { - String::new() - }; - span_lint_hir_and_then( - cx, - TOPLEVEL_REF_ARG, - init.hir_id, - local.pat.span, - "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", - |diag| { - diag.span_suggestion( - stmt.span, - "try", - format!( - "let {name}{tyopt} = {initref};", - name=snippet(cx, name.span, ".."), - tyopt=tyopt, - initref=initref, - ), - Applicability::MachineApplicable, - ); - } - ); - } + // use the macro callsite when the init span (but not the whole local span) + // comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];` + let sugg_init = if init.span.from_expansion() && !local.span.from_expansion() { + Sugg::hir_with_macro_callsite(cx, init, "..") + } else { + Sugg::hir(cx, init, "..") + }; + let (mutopt, initref) = if an == BindingAnnotation::RefMut { + ("mut ", sugg_init.mut_addr()) + } else { + ("", sugg_init.addr()) + }; + let tyopt = if let Some(ty) = local.ty { + format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "..")) + } else { + String::new() + }; + span_lint_hir_and_then( + cx, + TOPLEVEL_REF_ARG, + init.hir_id, + local.pat.span, + "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", + |diag| { + diag.span_suggestion( + stmt.span, + "try", + format!( + "let {name}{tyopt} = {initref};", + name=snippet(cx, name.span, ".."), + tyopt=tyopt, + initref=initref, + ), + Applicability::MachineApplicable, + ); + } + ); } }; if_chain! { - if let StmtKind::Semi(ref expr) = stmt.kind; - if let ExprKind::Binary(ref binop, ref a, ref b) = expr.kind; + if let StmtKind::Semi(expr) = stmt.kind; + if let ExprKind::Binary(ref binop, a, b) = expr.kind; if binop.node == BinOpKind::And || binop.node == BinOpKind::Or; if let Some(sugg) = Sugg::hir_opt(cx, a); then { @@ -377,11 +378,11 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match expr.kind { - ExprKind::Cast(ref e, ref ty) => { + ExprKind::Cast(e, ty) => { check_cast(cx, expr.span, e, ty); return; }, - ExprKind::Binary(ref cmp, ref left, ref right) => { + ExprKind::Binary(ref cmp, left, right) => { check_binary(cx, expr, cmp, left, right); return; }, @@ -460,21 +461,18 @@ fn check_nan(cx: &LateContext<'_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { if_chain! { if !in_constant(cx, cmp_expr.hir_id); if let Some((value, _)) = constant(cx, cx.typeck_results(), expr); + if match value { + Constant::F32(num) => num.is_nan(), + Constant::F64(num) => num.is_nan(), + _ => false, + }; then { - let needs_lint = match value { - Constant::F32(num) => num.is_nan(), - Constant::F64(num) => num.is_nan(), - _ => false, - }; - - if needs_lint { - span_lint( - cx, - CMP_NAN, - cmp_expr.span, - "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead", - ); - } + span_lint( + cx, + CMP_NAN, + cmp_expr.span, + "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead", + ); } } } @@ -503,12 +501,12 @@ fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { // Return true if `expr` is the result of `signum()` invoked on a float value. fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { // The negation of a signum is still a signum - if let ExprKind::Unary(UnOp::Neg, ref child_expr) = expr.kind { - return is_signum(cx, &child_expr); + if let ExprKind::Unary(UnOp::Neg, child_expr) = expr.kind { + return is_signum(cx, child_expr); } if_chain! { - if let ExprKind::MethodCall(ref method_name, _, ref expressions, _) = expr.kind; + if let ExprKind::MethodCall(method_name, _, expressions, _) = expr.kind; if sym!(signum) == method_name.ident.name; // Check that the receiver of the signum() is a float (expressions[0] is the receiver of // the method call) @@ -554,11 +552,11 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: } let (arg_ty, snip) = match expr.kind { - ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => { + ExprKind::MethodCall(.., args, _) if args.len() == 1 => { if_chain!( if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if is_diagnostic_assoc_item(cx, expr_def_id, sym::ToString) - || is_diagnostic_assoc_item(cx, expr_def_id, sym::ToOwned); + if is_diag_trait_item(cx, expr_def_id, sym::ToString) + || is_diag_trait_item(cx, expr_def_id, sym::ToOwned); then { (cx.typeck_results().expr_ty(&args[0]), snippet(cx, args[0].span, "..")) } else { @@ -566,13 +564,13 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: } ) }, - ExprKind::Call(ref path, ref v) if v.len() == 1 => { - if let ExprKind::Path(ref path) = path.kind { - if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) { - (cx.typeck_results().expr_ty(&v[0]), snippet(cx, v[0].span, "..")) - } else { - return; - } + ExprKind::Call(path, [arg]) => { + if expr_path_res(cx, path) + .opt_def_id() + .and_then(|id| match_any_def_paths(cx, id, &[&paths::FROM_STR_METHOD, &paths::FROM_FROM])) + .is_some() + { + (cx.typeck_results().expr_ty(arg), snippet(cx, arg.span, "..")) } else { return; } @@ -651,7 +649,7 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: /// of what it means for an expression to be "used". fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { get_parent_expr(cx, expr).map_or(true, |parent| match parent.kind { - ExprKind::Assign(_, ref rhs, _) | ExprKind::AssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), + ExprKind::Assign(_, rhs, _) | ExprKind::AssignOp(_, _, rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), _ => is_used(cx, parent), }) } diff --git a/src/tools/clippy/clippy_lints/src/misc_early.rs b/src/tools/clippy/clippy_lints/src/misc_early.rs index 84a0df92f5..3c6a7071c2 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early.rs @@ -1,4 +1,5 @@ -use crate::utils::{snippet_opt, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::snippet_opt; use rustc_ast::ast::{ BindingMode, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, NodeId, Pat, PatKind, UnOp, diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index b0998a8012..59cbc481ed 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -1,7 +1,7 @@ -use crate::utils::qualify_min_const_fn::is_min_const_fn; -use crate::utils::{ - fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, meets_msrv, span_lint, trait_ref_of_method, -}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::qualify_min_const_fn::is_min_const_fn; +use clippy_utils::ty::has_drop; +use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, meets_msrv, msrvs, trait_ref_of_method}; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; @@ -12,8 +12,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; use rustc_typeck::hir_ty_to_ty; -const MISSING_CONST_FOR_FN_MSRV: RustcVersion = RustcVersion::new(1, 37, 0); - declare_clippy_lint! { /// **What it does:** /// @@ -97,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { span: Span, hir_id: HirId, ) { - if !meets_msrv(self.msrv.as_ref(), &MISSING_CONST_FOR_FN_MSRV) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::CONST_IF_MATCH) { return; } @@ -138,8 +136,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { let mir = cx.tcx.optimized_mir(def_id); - if let Err((span, err)) = is_min_const_fn(cx.tcx, &mir) { - if rustc_mir::const_eval::is_min_const_fn(cx.tcx, def_id.to_def_id()) { + if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, self.msrv.as_ref()) { + if cx.tcx.is_const_fn_raw(def_id.to_def_id()) { cx.tcx.sess.span_err(span, &err); } } else { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 985a66b6cf..dfab3e8a93 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -5,10 +5,10 @@ // [`missing_doc`]: https://github.com/rust-lang/rust/blob/cf9cf7c923eb01146971429044f216a3ca905e06/compiler/rustc_lint/src/builtin.rs#L415 // -use crate::utils::span_lint; +use clippy_utils::attrs::is_doc_hidden; +use clippy_utils::diagnostics::span_lint; use if_chain::if_chain; use rustc_ast::ast::{self, MetaItem, MetaItemKind}; -use rustc_ast::attr; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; @@ -93,9 +93,9 @@ impl MissingDoc { return; } - let has_doc = attrs - .iter() - .any(|a| a.is_doc_comment() || a.doc_str().is_some() || a.is_value_str() || Self::has_include(a.meta())); + let has_doc = attrs.iter().any(|a| { + a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta()) + }); if !has_doc { span_lint( cx, @@ -111,14 +111,7 @@ impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]); impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) { - let doc_hidden = self.doc_hidden() - || attrs.iter().any(|attr| { - attr.has_name(sym::doc) - && match attr.meta_item_list() { - None => false, - Some(l) => attr::list_contains_name(&l[..], sym::hidden), - } - }); + let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs); self.doc_hidden_stack.push(doc_hidden); } @@ -128,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID); - self.check_missing_docs_attrs(cx, attrs, krate.item.span, "the", "crate"); + self.check_missing_docs_attrs(cx, attrs, krate.item.inner, "the", "crate"); } fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index da59c82099..041fe64a1a 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::{self, LateContext, LateLintPass, LintContext}; @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let attrs = cx.tcx.hir().attrs(it.hir_id()); check_missing_inline_attrs(cx, attrs, it.span, desc); }, - hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, trait_items) => { + hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, _bounds, trait_items) => { // note: we need to check if the trait is exported so we can't use // `LateLintPass::check_trait_item` here. for tit in trait_items { diff --git a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs index da3ae1d652..64e9dc8546 100644 --- a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs @@ -1,9 +1,10 @@ use crate::consts::{constant, Constant}; -use crate::utils::{sext, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sext; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::fmt::Display; diff --git a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs index c1773cef7a..584daa5e11 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs @@ -1,6 +1,7 @@ //! lint on multiple versions of a crate being used -use crate::utils::{run_lints, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::run_lints; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::{Crate, CRATE_HIR_ID}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 908b7bb7ce..1786d5805d 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -1,10 +1,12 @@ -use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{match_def_path, paths, trait_ref_of_method}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use std::iter; declare_clippy_lint! { /// **What it does:** Checks for sets/maps with mutable key types. @@ -57,21 +59,21 @@ declare_lint_pass!(MutableKeyType => [ MUTABLE_KEY_TYPE ]); impl<'tcx> LateLintPass<'tcx> for MutableKeyType { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { if let hir::ItemKind::Fn(ref sig, ..) = item.kind { - check_sig(cx, item.hir_id(), &sig.decl); + check_sig(cx, item.hir_id(), sig.decl); } } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) { if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind { if trait_ref_of_method(cx, item.hir_id()).is_none() { - check_sig(cx, item.hir_id(), &sig.decl); + check_sig(cx, item.hir_id(), sig.decl); } } } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) { if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { - check_sig(cx, item.hir_id(), &sig.decl); + check_sig(cx, item.hir_id(), sig.decl); } } @@ -86,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) { let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id); let fn_sig = cx.tcx.fn_sig(fn_def_id); - for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) { + for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) { check_ty(cx, hir_ty.span, ty); } check_ty(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output())); diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index d7239b328b..4b9c51d0c1 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -1,4 +1,5 @@ -use crate::utils::{higher, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::higher; use rustc_hir as hir; use rustc_hir::intravisit; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -61,7 +62,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { // Let's ignore the generated code. intravisit::walk_expr(self, arg); intravisit::walk_expr(self, body); - } else if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, ref e) = expr.kind { + } else if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e) = expr.kind { if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) = e.kind { span_lint( self.cx, @@ -84,7 +85,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { if let hir::TyKind::Rptr( _, hir::MutTy { - ty: ref pty, + ty: pty, mutbl: hir::Mutability::Mut, }, ) = ty.kind diff --git a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs index df1cecb328..b9ba74c7d0 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Mutability}; diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs index 3f0b765df1..cea6fce119 100644 --- a/src/tools/clippy/clippy_lints/src/mut_reference.rs +++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs @@ -1,9 +1,10 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use std::iter; declare_clippy_lint! { /// **What it does:** Detects passing a mutable reference to a function that only @@ -32,7 +33,7 @@ declare_lint_pass!(UnnecessaryMutPassed => [UNNECESSARY_MUT_PASSED]); impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { match e.kind { - ExprKind::Call(ref fn_expr, ref arguments) => { + ExprKind::Call(fn_expr, arguments) => { if let ExprKind::Path(ref path) = fn_expr.kind { check_arguments( cx, @@ -43,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { ); } }, - ExprKind::MethodCall(ref path, _, ref arguments, _) => { + ExprKind::MethodCall(path, _, arguments, _) => { let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap(); let substs = cx.typeck_results().node_substs(e.hir_id); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); @@ -64,7 +65,7 @@ fn check_arguments<'tcx>( match type_definition.kind() { ty::FnDef(..) | ty::FnPtr(_) => { let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); - for (argument, parameter) in arguments.iter().zip(parameters.iter()) { + for (argument, parameter) in iter::zip(arguments, parameters) { match parameter.kind() { ty::Ref(_, _, Mutability::Not) | ty::RawPtr(ty::TypeAndMut { diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs index 9caacb5db7..7dfe12cd4e 100644 --- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs +++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs @@ -1,4 +1,5 @@ -use crate::utils::{higher, is_direct_expn_of, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{higher, is_direct_expn_of}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index 40b236493a..354e2c3fb7 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -2,7 +2,8 @@ //! //! This lint is **warn** by default -use crate::utils::{is_type_diagnostic_item, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs index 7687962bdd..3e2b2782ed 100644 --- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs @@ -1,4 +1,5 @@ -use crate::utils::{in_macro, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; use if_chain::if_chain; use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index f283ff1715..dd45819863 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -2,8 +2,10 @@ //! //! This lint is **warn** by default -use crate::utils::sugg::Sugg; -use crate::utils::{is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; +use clippy_utils::{is_else_clause, is_expn_of}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; @@ -69,7 +71,7 @@ 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 let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.kind { + if let ExprKind::If(pred, then_block, Some(else_expr)) = e.kind { let reduce = |ret, not| { let mut applicability = Applicability::MachineApplicable; let snip = Sugg::hir_with_applicability(cx, pred, "<predicate>", &mut applicability); @@ -79,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool { snip = snip.make_return(); } - if parent_node_is_if_expr(&e, &cx) { + if is_else_clause(cx.tcx, e) { snip = snip.blockify() } @@ -93,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool { applicability, ); }; - if let ExprKind::Block(ref then_block, _) = then_block.kind { + if let ExprKind::Block(then_block, _) = then_block.kind { match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) { (RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => { span_lint( @@ -223,7 +225,7 @@ fn check_comparison<'a, 'tcx>( ) { use self::Expression::{Bool, Other}; - if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind { + if let ExprKind::Binary(op, left_side, right_side) = e.kind { let (l_ty, r_ty) = ( cx.typeck_results().expr_ty(left_side), cx.typeck_results().expr_ty(right_side), @@ -235,7 +237,7 @@ fn check_comparison<'a, 'tcx>( let mut applicability = Applicability::MachineApplicable; if let BinOpKind::Eq = op.node { - let expression_info = one_side_is_unary_not(&left_side, &right_side); + let expression_info = one_side_is_unary_not(left_side, right_side); if expression_info.one_side_is_unary_not { span_lint_and_sugg( cx, @@ -322,9 +324,9 @@ fn fetch_bool_block(block: &Block<'_>) -> Expression { match (&*block.stmts, block.expr.as_ref()) { (&[], Some(e)) => fetch_bool_expr(&**e), (&[ref e], None) => { - if let StmtKind::Semi(ref e) = e.kind { + if let StmtKind::Semi(e) = e.kind { if let ExprKind::Ret(_) = e.kind { - fetch_bool_expr(&**e) + fetch_bool_expr(e) } else { Expression::Other } @@ -338,7 +340,7 @@ fn fetch_bool_block(block: &Block<'_>) -> Expression { fn fetch_bool_expr(expr: &Expr<'_>) -> Expression { match expr.kind { - ExprKind::Block(ref block, _) => fetch_bool_block(block), + ExprKind::Block(block, _) => fetch_bool_block(block), ExprKind::Lit(ref lit_ptr) => { if let LitKind::Bool(value) = lit_ptr.node { Expression::Bool(value) @@ -346,7 +348,7 @@ fn fetch_bool_expr(expr: &Expr<'_>) -> Expression { Expression::Other } }, - ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) { + ExprKind::Ret(Some(expr)) => match fetch_bool_expr(expr) { Expression::Bool(value) => Expression::RetBool(value), _ => Expression::Other, }, diff --git a/src/tools/clippy/clippy_lints/src/needless_borrow.rs b/src/tools/clippy/clippy_lints/src/needless_borrow.rs index 1aadcfd87b..eef3c16730 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrow.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrow.rs @@ -2,7 +2,9 @@ //! //! This lint is **warn** by default -use crate::utils::{is_automatically_derived, snippet_opt, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_automatically_derived; +use clippy_utils::source::snippet_opt; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, Item, Mutability, Pat, PatKind}; @@ -46,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow { if e.span.from_expansion() || self.derived_item.is_some() { return; } - if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = e.kind { + if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = e.kind { if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() { for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) { if let [Adjustment { diff --git a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs index f449f397e7..0e976b130e 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs @@ -1,4 +1,5 @@ -use crate::utils::{snippet_with_applicability, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, Mutability, Node, Pat, PatKind}; @@ -50,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef { if_chain! { // Only lint immutable refs, because `&mut ref T` may be useful. - if let PatKind::Ref(ref sub_pat, Mutability::Not) = pat.kind; + if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind; // Check sub_pat got a `ref` keyword (excluding `ref mut`). if let PatKind::Binding(BindingAnnotation::Ref, .., spanned_name, _) = sub_pat.kind; diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index 30fe2d6225..91c97ef7c2 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -33,14 +33,14 @@ //! ``` //! //! This lint is **warn** by default. +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::{indent_of, snippet, snippet_block}; use rustc_ast::ast; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::Span; -use crate::utils::{indent_of, snippet, snippet_block, span_lint_and_help}; - declare_clippy_lint! { /// **What it does:** The lint checks for `if`-statements appearing in loops /// that contain a `continue` statement in either their main blocks or their diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs new file mode 100644 index 0000000000..079b6642d5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs @@ -0,0 +1,167 @@ +use rustc_errors::Applicability; +use rustc_hir::{ + intravisit::{walk_expr, NestedVisitorMap, Visitor}, + Expr, ExprKind, Stmt, StmtKind, +}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{source_map::Span, sym, Symbol}; + +use if_chain::if_chain; + +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_trait_method; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::has_iter_method; + +declare_clippy_lint! { + /// **What it does:** Checks for usage of `for_each` that would be more simply written as a + /// `for` loop. + /// + /// **Why is this bad?** `for_each` may be used after applying iterator transformers like + /// `filter` for better readability and performance. It may also be used to fit a simple + /// operation on one line. + /// But when none of these apply, a simple `for` loop is more idiomatic. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// let v = vec![0, 1, 2]; + /// v.iter().for_each(|elem| { + /// println!("{}", elem); + /// }) + /// ``` + /// Use instead: + /// ```rust + /// let v = vec![0, 1, 2]; + /// for elem in v.iter() { + /// println!("{}", elem); + /// } + /// ``` + pub NEEDLESS_FOR_EACH, + pedantic, + "using `for_each` where a `for` loop would be simpler" +} + +declare_lint_pass!(NeedlessForEach => [NEEDLESS_FOR_EACH]); + +impl LateLintPass<'_> for NeedlessForEach { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { + let expr = match stmt.kind { + StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr, + _ => return, + }; + + if_chain! { + // Check the method name is `for_each`. + if let ExprKind::MethodCall(method_name, _, [for_each_recv, for_each_arg], _) = expr.kind; + if method_name.ident.name == Symbol::intern("for_each"); + // Check `for_each` is an associated function of `Iterator`. + if is_trait_method(cx, expr, sym::Iterator); + // Checks the receiver of `for_each` is also a method call. + if let ExprKind::MethodCall(_, _, [iter_recv], _) = for_each_recv.kind; + // Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or + // `v.foo().iter().for_each()` must be skipped. + if matches!( + iter_recv.kind, + ExprKind::Array(..) | ExprKind::Call(..) | ExprKind::Path(..) + ); + // Checks the type of the `iter` method receiver is NOT a user defined type. + if has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some(); + // Skip the lint if the body is not block because this is simpler than `for` loop. + // e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop. + if let ExprKind::Closure(_, _, body_id, ..) = for_each_arg.kind; + let body = cx.tcx.hir().body(body_id); + if let ExprKind::Block(..) = body.value.kind; + then { + let mut ret_collector = RetCollector::default(); + ret_collector.visit_expr(&body.value); + + // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`. + if ret_collector.ret_in_loop { + return; + } + + let (mut applicability, ret_suggs) = if ret_collector.spans.is_empty() { + (Applicability::MachineApplicable, None) + } else { + ( + Applicability::MaybeIncorrect, + Some( + ret_collector + .spans + .into_iter() + .map(|span| (span, "continue".to_string())) + .collect(), + ), + ) + }; + + let sugg = format!( + "for {} in {} {}", + snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability), + snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability), + snippet_with_applicability(cx, body.value.span, "..", &mut applicability), + ); + + span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| { + diag.span_suggestion(stmt.span, "try", sugg, applicability); + if let Some(ret_suggs) = ret_suggs { + diag.multipart_suggestion("...and replace `return` with `continue`", ret_suggs, applicability); + } + }) + } + } + } +} + +/// This type plays two roles. +/// 1. Collect spans of `return` in the closure body. +/// 2. Detect use of `return` in `Loop` in the closure body. +/// +/// NOTE: The functionality of this type is similar to +/// [`crate::utilts::visitors::find_all_ret_expressions`], but we can't use +/// `find_all_ret_expressions` instead of this type. The reasons are: +/// 1. `find_all_ret_expressions` passes the argument of `ExprKind::Ret` to a callback, but what we +/// need here is `ExprKind::Ret` itself. +/// 2. We can't trace current loop depth with `find_all_ret_expressions`. +#[derive(Default)] +struct RetCollector { + spans: Vec<Span>, + ret_in_loop: bool, + loop_depth: u16, +} + +impl<'tcx> Visitor<'tcx> for RetCollector { + type Map = Map<'tcx>; + + fn visit_expr(&mut self, expr: &Expr<'_>) { + match expr.kind { + ExprKind::Ret(..) => { + if self.loop_depth > 0 && !self.ret_in_loop { + self.ret_in_loop = true + } + + self.spans.push(expr.span) + }, + + ExprKind::Loop(..) => { + self.loop_depth += 1; + walk_expr(self, expr); + self.loop_depth -= 1; + return; + }, + + _ => {}, + } + + walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index d439577f9c..e33a33e238 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -1,14 +1,15 @@ -use crate::utils::ptr::get_spans; -use crate::utils::{ - get_trait_def_id, implements_trait, is_copy, is_self, is_type_diagnostic_item, multispan_sugg, paths, snippet, - snippet_opt, span_lint_and_then, -}; +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; +use clippy_utils::ptr::get_spans; +use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item}; +use clippy_utils::{get_trait_def_id, is_self, paths}; use if_chain::if_chain; use rustc_ast::ast::Attribute; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Node, PatKind, QPath, TyKind}; +use rustc_hir::{HirIdMap, HirIdSet}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; @@ -207,7 +208,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if is_type_diagnostic_item(cx, ty, sym::vec_type); if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); - if let TyKind::Path(QPath::Resolved(_, ref path)) = input.kind; + if let TyKind::Path(QPath::Resolved(_, path)) = input.kind; if let Some(elem_ty) = path.segments.iter() .find(|seg| seg.ident.name == sym::Vec) .and_then(|ps| ps.args.as_ref()) @@ -278,7 +279,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { spans.extend( deref_span .iter() - .cloned() + .copied() .map(|span| (span, format!("*{}", snippet(cx, span, "<expr>")))), ); spans.sort_by_key(|&(span, _)| span); @@ -310,10 +311,10 @@ fn requires_exact_signature(attrs: &[Attribute]) -> bool { #[derive(Default)] struct MovedVariablesCtxt { - moved_vars: FxHashSet<HirId>, + moved_vars: HirIdSet, /// Spans which need to be prefixed with `*` for dereferencing the /// suggested additional reference. - spans_need_deref: FxHashMap<HirId, FxHashSet<Span>>, + spans_need_deref: HirIdMap<FxHashSet<Span>>, } impl MovedVariablesCtxt { @@ -335,5 +336,5 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt { fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {} - fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) { } + fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {} } diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index a3293f1b36..7b156a8c49 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -1,13 +1,15 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{differing_macro_contexts, is_lang_ctor}; +use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::LangItem::{OptionSome, ResultOk}; use rustc_hir::{Body, Expr, ExprKind, LangItem, MatchSource, QPath}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_semver::RustcVersion; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; -use crate::utils; -use if_chain::if_chain; - declare_clippy_lint! { /// **What it does:** /// Suggests alternatives for useless applications of `?` in terminating expressions @@ -59,21 +61,7 @@ declare_clippy_lint! { "Suggest `value.inner_option` instead of `Some(value.inner_option?)`. The same goes for `Result<T, E>`." } -const NEEDLESS_QUESTION_MARK_RESULT_MSRV: RustcVersion = RustcVersion::new(1, 13, 0); -const NEEDLESS_QUESTION_MARK_OPTION_MSRV: RustcVersion = RustcVersion::new(1, 22, 0); - -pub struct NeedlessQuestionMark { - msrv: Option<RustcVersion>, -} - -impl NeedlessQuestionMark { - #[must_use] - pub fn new(msrv: Option<RustcVersion>) -> Self { - Self { msrv } - } -} - -impl_lint_pass!(NeedlessQuestionMark => [NEEDLESS_QUESTION_MARK]); +declare_lint_pass!(NeedlessQuestionMark => [NEEDLESS_QUESTION_MARK]); #[derive(Debug)] enum SomeOkCall<'a> { @@ -107,7 +95,7 @@ impl LateLintPass<'_> for NeedlessQuestionMark { _ => return, }; - if let Some(ok_some_call) = is_some_or_ok_call(self, cx, e) { + if let Some(ok_some_call) = is_some_or_ok_call(cx, e) { emit_lint(cx, &ok_some_call); } } @@ -123,14 +111,12 @@ impl LateLintPass<'_> for NeedlessQuestionMark { if_chain! { if let Some(expr) = expr_opt; - if let Some(ok_some_call) = is_some_or_ok_call(self, cx, expr); + if let Some(ok_some_call) = is_some_or_ok_call(cx, expr); then { emit_lint(cx, &ok_some_call); } }; } - - extract_msrv_attr!(LateContext); } fn emit_lint(cx: &LateContext<'_>, expr: &SomeOkCall<'_>) { @@ -138,27 +124,23 @@ fn emit_lint(cx: &LateContext<'_>, expr: &SomeOkCall<'_>) { SomeOkCall::OkCall(outer, inner) | SomeOkCall::SomeCall(outer, inner) => (outer, inner), }; - utils::span_lint_and_sugg( + span_lint_and_sugg( cx, NEEDLESS_QUESTION_MARK, entire_expr.span, "question mark operator is useless here", "try", - format!("{}", utils::snippet(cx, inner_expr.span, r#""...""#)), + format!("{}", snippet(cx, inner_expr.span, r#""...""#)), Applicability::MachineApplicable, ); } -fn is_some_or_ok_call<'a>( - nqml: &NeedlessQuestionMark, - cx: &'a LateContext<'_>, - expr: &'a Expr<'_>, -) -> Option<SomeOkCall<'a>> { +fn is_some_or_ok_call<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option<SomeOkCall<'a>> { if_chain! { // Check outer expression matches CALL_IDENT(ARGUMENT) format if let ExprKind::Call(path, args) = &expr.kind; - if let ExprKind::Path(QPath::Resolved(None, path)) = &path.kind; - if utils::is_some_ctor(cx, path.res) || utils::is_ok_ctor(cx, path.res); + if let ExprKind::Path(ref qpath) = &path.kind; + if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk); // Extract inner expression from ARGUMENT if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar) = &args[0].kind; @@ -171,30 +153,33 @@ fn is_some_or_ok_call<'a>( // question mark operator let inner_expr = &args[0]; + // if the inner expr is inside macro but the outer one is not, do not lint (#6921) + if differing_macro_contexts(expr.span, inner_expr.span) { + return None; + } + let inner_ty = cx.typeck_results().expr_ty(inner_expr); let outer_ty = cx.typeck_results().expr_ty(expr); // Check if outer and inner type are Option - let outer_is_some = utils::is_type_diagnostic_item(cx, outer_ty, sym::option_type); - let inner_is_some = utils::is_type_diagnostic_item(cx, inner_ty, sym::option_type); + let outer_is_some = is_type_diagnostic_item(cx, outer_ty, sym::option_type); + let inner_is_some = is_type_diagnostic_item(cx, inner_ty, sym::option_type); // Check for Option MSRV - let meets_option_msrv = utils::meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_OPTION_MSRV); - if outer_is_some && inner_is_some && meets_option_msrv { + if outer_is_some && inner_is_some { return Some(SomeOkCall::SomeCall(expr, inner_expr)); } // Check if outer and inner type are Result - let outer_is_result = utils::is_type_diagnostic_item(cx, outer_ty, sym::result_type); - let inner_is_result = utils::is_type_diagnostic_item(cx, inner_ty, sym::result_type); + let outer_is_result = is_type_diagnostic_item(cx, outer_ty, sym::result_type); + let inner_is_result = is_type_diagnostic_item(cx, inner_ty, sym::result_type); // Additional check: if the error type of the Result can be converted // via the From trait, then don't match let does_not_call_from = !has_implicit_error_from(cx, expr, inner_expr); // Must meet Result MSRV - let meets_result_msrv = utils::meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_RESULT_MSRV); - if outer_is_result && inner_is_result && does_not_call_from && meets_result_msrv { + if outer_is_result && inner_is_result && does_not_call_from { return Some(SomeOkCall::OkCall(expr, inner_expr)); } } diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs index 41cf541ecf..8f325404de 100644 --- a/src/tools/clippy/clippy_lints/src/needless_update.rs +++ b/src/tools/clippy/clippy_lints/src/needless_update.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -49,7 +49,7 @@ declare_lint_pass!(NeedlessUpdate => [NEEDLESS_UPDATE]); impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Struct(_, ref fields, Some(ref base)) = expr.kind { + if let ExprKind::Struct(_, fields, Some(base)) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); if let ty::Adt(def, _) = ty.kind() { if fields.len() == def.non_enum_variant().fields.len() diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index ec0ad58ca9..0704173a01 100644 --- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,11 +1,12 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::implements_trait; +use clippy_utils::{self, get_trait_def_id, paths}; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{self, paths, span_lint}; - declare_clippy_lint! { /// **What it does:** /// Checks for the usage of negated comparison operators on types which only implement @@ -50,8 +51,8 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { if_chain! { if !in_external_macro(cx.sess(), expr.span); - if let ExprKind::Unary(UnOp::Not, ref inner) = expr.kind; - if let ExprKind::Binary(ref op, ref left, _) = inner.kind; + if let ExprKind::Unary(UnOp::Not, inner) = expr.kind; + if let ExprKind::Binary(ref op, left, _) = inner.kind; if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node; then { @@ -59,8 +60,8 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { let ty = cx.typeck_results().expr_ty(left); let implements_ord = { - if let Some(id) = utils::get_trait_def_id(cx, &paths::ORD) { - utils::implements_trait(cx, ty, id, &[]) + if let Some(id) = get_trait_def_id(cx, &paths::ORD) { + implements_trait(cx, ty, id, &[]) } else { return; } @@ -68,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { let implements_partial_ord = { if let Some(id) = cx.tcx.lang_items().partial_ord_trait() { - utils::implements_trait(cx, ty, id, &[]) + implements_trait(cx, ty, id, &[]) } else { return; } diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index ef7cc65cfc..34fd012572 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -1,3 +1,4 @@ +use clippy_utils::diagnostics::span_lint; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -5,7 +6,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use crate::consts::{self, Constant}; -use crate::utils::span_lint; declare_clippy_lint! { /// **What it does:** Checks for multiplication by -1 as a form of negation. @@ -28,12 +28,12 @@ declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]); #[allow(clippy::match_same_arms)] impl<'tcx> LateLintPass<'tcx> for NegMultiply { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref op, ref left, ref right) = e.kind { + if let ExprKind::Binary(ref op, left, right) = e.kind { if BinOpKind::Mul == op.node { match (&left.kind, &right.kind) { (&ExprKind::Unary(..), &ExprKind::Unary(..)) => {}, - (&ExprKind::Unary(UnOp::Neg, ref lit), _) => check_mul(cx, e.span, lit, right), - (_, &ExprKind::Unary(UnOp::Neg, ref lit)) => check_mul(cx, e.span, lit, left), + (&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right), + (_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left), _ => {}, } } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index de2899c346..a5f91eb035 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -1,6 +1,8 @@ -use crate::utils::paths; -use crate::utils::sugg::DiagnosticBuilderExt; -use crate::utils::{get_trait_def_id, return_ty, span_lint_hir_and_then}; +use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::paths; +use clippy_utils::source::snippet; +use clippy_utils::sugg::DiagnosticBuilderExt; +use clippy_utils::{get_trait_def_id, return_ty}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -61,7 +63,10 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { #[allow(clippy::too_many_lines)] fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { if let hir::ItemKind::Impl(hir::Impl { - of_trait: None, items, .. + of_trait: None, + ref generics, + items, + .. }) = item.kind { for assoc_item in items { @@ -92,59 +97,60 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // impl of `Default` return; } - if sig.decl.inputs.is_empty() && name == sym::new && cx.access_levels.is_reachable(id) { + if_chain! { + if sig.decl.inputs.is_empty(); + if name == sym::new; + if cx.access_levels.is_reachable(id); let self_def_id = cx.tcx.hir().local_def_id(cx.tcx.hir().get_parent_item(id)); let self_ty = cx.tcx.type_of(self_def_id); - if_chain! { - if TyS::same_type(self_ty, return_ty(cx, id)); - if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); - then { - if self.impling_types.is_none() { - let mut impls = HirIdSet::default(); - cx.tcx.for_each_impl(default_trait_id, |d| { - if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() { - if let Some(local_def_id) = ty_def.did.as_local() { - impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id)); - } - } - }); - self.impling_types = Some(impls); - } - - // Check if a Default implementation exists for the Self type, regardless of - // generics - if_chain! { - if let Some(ref impling_types) = self.impling_types; - if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def(); - if let Some(self_local_did) = self_def.did.as_local(); - then { - let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did); - if impling_types.contains(&self_id) { - return; + if TyS::same_type(self_ty, return_ty(cx, id)); + if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); + then { + if self.impling_types.is_none() { + let mut impls = HirIdSet::default(); + cx.tcx.for_each_impl(default_trait_id, |d| { + if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() { + if let Some(local_def_id) = ty_def.did.as_local() { + impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id)); } } - } + }); + self.impling_types = Some(impls); + } - span_lint_hir_and_then( - cx, - NEW_WITHOUT_DEFAULT, - id, - impl_item.span, - &format!( - "you should consider adding a `Default` implementation for `{}`", - self_ty - ), - |diag| { - diag.suggest_prepend_item( - cx, - item.span, - "try this", - &create_new_without_default_suggest_msg(self_ty), - Applicability::MaybeIncorrect, - ); - }, - ); + // Check if a Default implementation exists for the Self type, regardless of + // generics + if_chain! { + if let Some(ref impling_types) = self.impling_types; + if let Some(self_def) = cx.tcx.type_of(self_def_id).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 impling_types.contains(&self_id); + then { + return; + } } + + let generics_sugg = snippet(cx, generics.span, ""); + span_lint_hir_and_then( + cx, + NEW_WITHOUT_DEFAULT, + id, + impl_item.span, + &format!( + "you should consider adding a `Default` implementation for `{}`", + self_ty + ), + |diag| { + diag.suggest_prepend_item( + cx, + item.span, + "try this", + &create_new_without_default_suggest_msg(self_ty, &generics_sugg), + Applicability::MaybeIncorrect, + ); + }, + ); } } } @@ -154,12 +160,12 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { } } -fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String { +fn create_new_without_default_suggest_msg(ty: Ty<'_>, generics_sugg: &str) -> String { #[rustfmt::skip] format!( -"impl Default for {} {{ +"impl{} Default for {} {{ fn default() -> Self {{ Self::new() }} -}}", ty) +}}", generics_sugg, ty) } diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 69302d695c..cfcaf50947 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -1,4 +1,6 @@ -use crate::utils::{has_drop, snippet_opt, span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::has_drop; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource}; @@ -49,23 +51,21 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Lit(..) | ExprKind::Closure(..) => true, ExprKind::Path(..) => !has_drop(cx, cx.typeck_results().expr_ty(expr)), - ExprKind::Index(ref a, ref b) | ExprKind::Binary(_, ref a, ref b) => { - has_no_effect(cx, a) && has_no_effect(cx, b) - }, - ExprKind::Array(ref v) | ExprKind::Tup(ref v) => v.iter().all(|val| has_no_effect(cx, val)), - ExprKind::Repeat(ref inner, _) - | ExprKind::Cast(ref inner, _) - | ExprKind::Type(ref inner, _) - | ExprKind::Unary(_, ref inner) - | ExprKind::Field(ref inner, _) - | ExprKind::AddrOf(_, _, ref inner) - | ExprKind::Box(ref inner) => has_no_effect(cx, inner), - ExprKind::Struct(_, ref fields, ref base) => { + ExprKind::Index(a, b) | ExprKind::Binary(_, a, b) => has_no_effect(cx, a) && has_no_effect(cx, b), + ExprKind::Array(v) | ExprKind::Tup(v) => v.iter().all(|val| has_no_effect(cx, val)), + ExprKind::Repeat(inner, _) + | ExprKind::Cast(inner, _) + | ExprKind::Type(inner, _) + | ExprKind::Unary(_, inner) + | ExprKind::Field(inner, _) + | ExprKind::AddrOf(_, _, inner) + | ExprKind::Box(inner) => has_no_effect(cx, inner), + ExprKind::Struct(_, fields, ref base) => { !has_drop(cx, cx.typeck_results().expr_ty(expr)) - && fields.iter().all(|field| has_no_effect(cx, &field.expr)) + && fields.iter().all(|field| has_no_effect(cx, field.expr)) && base.as_ref().map_or(true, |base| has_no_effect(cx, base)) }, - ExprKind::Call(ref callee, ref args) => { + ExprKind::Call(callee, args) => { if let ExprKind::Path(ref qpath) = callee.kind { let res = cx.qpath_res(qpath, callee.hir_id); match res { @@ -79,7 +79,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { false } }, - ExprKind::Block(ref block, _) => { + ExprKind::Block(block, _) => { block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| has_no_effect(cx, expr)) }, _ => false, @@ -90,7 +90,7 @@ declare_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION]); impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if let StmtKind::Semi(ref expr) = stmt.kind { + if let StmtKind::Semi(expr) = stmt.kind { if has_no_effect(cx, expr) { span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); } else if let Some(reduced) = reduce_expression(cx, expr) { @@ -125,26 +125,26 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec return None; } match expr.kind { - ExprKind::Index(ref a, ref b) => Some(vec![&**a, &**b]), - ExprKind::Binary(ref binop, ref a, ref b) if binop.node != BinOpKind::And && binop.node != BinOpKind::Or => { - Some(vec![&**a, &**b]) + ExprKind::Index(a, b) => Some(vec![a, b]), + ExprKind::Binary(ref binop, a, b) if binop.node != BinOpKind::And && binop.node != BinOpKind::Or => { + Some(vec![a, b]) }, - ExprKind::Array(ref v) | ExprKind::Tup(ref v) => Some(v.iter().collect()), - ExprKind::Repeat(ref inner, _) - | ExprKind::Cast(ref inner, _) - | ExprKind::Type(ref inner, _) - | ExprKind::Unary(_, ref inner) - | ExprKind::Field(ref inner, _) - | ExprKind::AddrOf(_, _, ref inner) - | ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), - ExprKind::Struct(_, ref fields, ref base) => { + ExprKind::Array(v) | ExprKind::Tup(v) => Some(v.iter().collect()), + ExprKind::Repeat(inner, _) + | ExprKind::Cast(inner, _) + | ExprKind::Type(inner, _) + | ExprKind::Unary(_, inner) + | ExprKind::Field(inner, _) + | ExprKind::AddrOf(_, _, inner) + | ExprKind::Box(inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])), + ExprKind::Struct(_, fields, ref base) => { if has_drop(cx, cx.typeck_results().expr_ty(expr)) { None } else { Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect()) } }, - ExprKind::Call(ref callee, ref args) => { + ExprKind::Call(callee, args) => { if let ExprKind::Path(ref qpath) = callee.kind { let res = cx.qpath_res(qpath, callee.hir_id); match res { @@ -159,7 +159,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec None } }, - ExprKind::Block(ref block, _) => { + ExprKind::Block(block, _) => { if block.stmts.is_empty() { block.expr.as_ref().and_then(|e| { match block.rules { diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 8aebce6791..d775cd7c7f 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -4,6 +4,9 @@ use std::ptr; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::in_constant; +use if_chain::if_chain; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ @@ -18,9 +21,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use rustc_typeck::hir_ty_to_ty; -use crate::utils::{in_constant, span_lint_and_then}; -use if_chain::if_chain; - // FIXME: this is a correctness problem but there's no suitable // warn-by-default category. declare_clippy_lint! { @@ -179,9 +179,15 @@ fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty< fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let substs = cx.typeck_results().node_substs(hir_id); - let result = cx - .tcx - .const_eval_resolve(cx.param_env, ty::WithOptConstParam::unknown(def_id), substs, None, None); + let result = cx.tcx.const_eval_resolve( + cx.param_env, + ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id), + substs, + promoted: None, + }, + None, + ); is_value_unfrozen_raw(cx, result, ty) } @@ -301,19 +307,17 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { // we should use here as a frozen variant is a potential to be frozen // similar to unknown layouts. // e.g. `layout_of(...).is_err() || has_frozen_variant(...);` + let ty = hir_ty_to_ty(cx.tcx, hir_ty); + let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + if is_unfrozen(cx, normalized); + if is_value_unfrozen_poly(cx, *body_id, normalized); then { - let ty = hir_ty_to_ty(cx.tcx, hir_ty); - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); - if is_unfrozen(cx, normalized) - && is_value_unfrozen_poly(cx, *body_id, normalized) - { - lint( - cx, - Source::Assoc { - item: impl_item.span, - }, - ); - } + lint( + cx, + Source::Assoc { + item: impl_item.span, + }, + ); } } }, diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index d5222a030d..4c8bceaf2c 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -1,4 +1,4 @@ -use crate::utils::{span_lint, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use rustc_ast::ast::{ Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat, PatKind, diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs new file mode 100644 index 0000000000..a83daea97b --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs @@ -0,0 +1,106 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{snippet_opt, snippet_with_applicability}; +use clippy_utils::ty::match_type; +use clippy_utils::{match_def_path, paths}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for non-octal values used to set Unix file permissions. + /// + /// **Why is this bad?** They will be converted into octal, creating potentially + /// unintended file permissions. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust,ignore + /// use std::fs::OpenOptions; + /// use std::os::unix::fs::OpenOptionsExt; + /// + /// let mut options = OpenOptions::new(); + /// options.mode(644); + /// ``` + /// Use instead: + /// ```rust,ignore + /// use std::fs::OpenOptions; + /// use std::os::unix::fs::OpenOptionsExt; + /// + /// let mut options = OpenOptions::new(); + /// options.mode(0o644); + /// ``` + pub NON_OCTAL_UNIX_PERMISSIONS, + correctness, + "use of non-octal value to set unix file permissions, which will be translated into octal" +} + +declare_lint_pass!(NonOctalUnixPermissions => [NON_OCTAL_UNIX_PERMISSIONS]); + +impl LateLintPass<'_> for NonOctalUnixPermissions { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + match &expr.kind { + ExprKind::MethodCall(path, _, [func, param], _) => { + let obj_ty = cx.typeck_results().expr_ty(func).peel_refs(); + + if_chain! { + if (path.ident.name == sym!(mode) + && (match_type(cx, obj_ty, &paths::OPEN_OPTIONS) + || match_type(cx, obj_ty, &paths::DIR_BUILDER))) + || (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS)); + if let ExprKind::Lit(_) = param.kind; + + then { + let snip = match snippet_opt(cx, param.span) { + Some(s) => s, + _ => return, + }; + + if !snip.starts_with("0o") { + show_error(cx, param); + } + } + } + }, + ExprKind::Call(func, [param]) => { + if_chain! { + if let ExprKind::Path(ref path) = func.kind; + if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); + if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE); + if let ExprKind::Lit(_) = param.kind; + + then { + let snip = match snippet_opt(cx, param.span) { + Some(s) => s, + _ => return, + }; + + if !snip.starts_with("0o") { + show_error(cx, param); + } + } + } + }, + _ => {}, + }; + } +} + +fn show_error(cx: &LateContext<'_>, param: &Expr<'_>) { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + NON_OCTAL_UNIX_PERMISSIONS, + param.span, + "using a non-octal value to set unix file permissions", + "consider using an octal literal instead", + format!( + "0o{}", + snippet_with_applicability(cx, param.span, "0o..", &mut applicability,), + ), + applicability, + ); +} diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs index 07ca196990..9efe45336b 100644 --- a/src/tools/clippy/clippy_lints/src/open_options.rs +++ b/src/tools/clippy/clippy_lints/src/open_options.rs @@ -1,4 +1,6 @@ -use crate::utils::{match_type, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::paths; +use clippy_utils::ty::match_type; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -29,7 +31,7 @@ declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]); impl<'tcx> LateLintPass<'tcx> for OpenOptions { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::MethodCall(ref path, _, ref arguments, _) = e.kind { + if let ExprKind::MethodCall(path, _, arguments, _) = e.kind { let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs(); if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { let mut options = Vec::new(); @@ -57,7 +59,7 @@ enum OpenOption { } fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) { - if let ExprKind::MethodCall(ref path, _, ref arguments, _) = argument.kind { + if let ExprKind::MethodCall(path, _, arguments, _) = argument.kind { let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs(); // Only proceed if this is a call on some object of type std::fs::OpenOptions diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs index fd653044a1..b6f518661b 100644 --- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs @@ -1,8 +1,10 @@ -use crate::utils::{is_direct_expn_of, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_direct_expn_of; use if_chain::if_chain; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// **What it does:** Checks for usage of `option_env!(...).unwrap()` and @@ -36,8 +38,7 @@ impl EarlyLintPass for OptionEnvUnwrap { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if_chain! { if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind; - let method_name = path_segment.ident.as_str(); - if method_name == "expect" || method_name == "unwrap"; + if matches!(path_segment.ident.name, sym::expect | sym::unwrap); if let ExprKind::Call(caller, _) = &args[0].kind; if is_direct_expn_of(caller.span, "option_env").is_some(); then { diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs index 9ef0d267b0..e527adbb89 100644 --- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs @@ -1,10 +1,11 @@ -use crate::utils; -use crate::utils::eager_or_lazy; -use crate::utils::sugg::Sugg; -use crate::utils::{is_type_diagnostic_item, paths, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::usage::contains_return_break_continue_macro; +use clippy_utils::{eager_or_lazy, get_enclosing_block, in_macro, is_lang_ctor}; use if_chain::if_chain; - use rustc_errors::Applicability; +use rustc_hir::LangItem::OptionSome; use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -65,9 +66,9 @@ declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]); /// Returns true iff the given expression is the result of calling `Result::ok` fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool { - if let ExprKind::MethodCall(ref path, _, &[ref receiver], _) = &expr.kind { + if let ExprKind::MethodCall(path, _, &[ref receiver], _) = &expr.kind { path.ident.name.as_str() == "ok" - && is_type_diagnostic_item(cx, &cx.typeck_results().expr_ty(&receiver), sym::result_type) + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::result_type) } else { false } @@ -96,9 +97,9 @@ fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> { ) = &arm.body.kind { if let [] = statements { - Some(&expr) + Some(expr) } else { - Some(&arm.body) + Some(arm.body) } } else { None @@ -108,7 +109,7 @@ fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> { /// If this is the else body of an if/else expression, then we need to wrap /// it in curly braces. Otherwise, we don't. fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { + get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { let mut should_wrap = false; if let Some(Expr { @@ -158,15 +159,15 @@ fn detect_option_if_let_else<'tcx>( expr: &'_ Expr<'tcx>, ) -> Option<OptionIfLetElseOccurence> { if_chain! { - if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly + if !in_macro(expr.span); // Don't lint macros, because it behaves weirdly if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; 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 utils::match_qpath(struct_qpath, &paths::OPTION_SOME); + if is_lang_ctor(cx, struct_qpath, OptionSome); if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind; - if !utils::usage::contains_return_break_continue_macro(arms[0].body); - if !utils::usage::contains_return_break_continue_macro(arms[1].body); + if !contains_return_break_continue_macro(arms[0].body); + if !contains_return_break_continue_macro(arms[1].body); then { let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" }; let some_body = extract_body_from_arm(&arms[0])?; diff --git a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs index 3c041bac23..e222782c2c 100644 --- a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs +++ b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs @@ -1,4 +1,5 @@ -use crate::utils::{span_lint, SpanlessEq}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::SpanlessEq; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; @@ -30,11 +31,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r); if_chain! { - if let ExprKind::Binary(ref op, ref first, ref second) = expr.kind; - if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = first.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path3)) = second.kind; + if let ExprKind::Binary(ref op, first, second) = expr.kind; + if let ExprKind::Binary(ref op2, ident1, ident2) = first.kind; + if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind; + if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind; + if let ExprKind::Path(QPath::Resolved(_, path3)) = second.kind; if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); if cx.typeck_results().expr_ty(ident1).is_integral(); if cx.typeck_results().expr_ty(ident2).is_integral(); @@ -55,11 +56,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { } if_chain! { - if let ExprKind::Binary(ref op, ref first, ref second) = expr.kind; - if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = second.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.kind; - if let ExprKind::Path(QPath::Resolved(_, ref path3)) = first.kind; + if let ExprKind::Binary(ref op, first, second) = expr.kind; + if let ExprKind::Binary(ref op2, ident1, ident2) = second.kind; + if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind; + if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind; + if let ExprKind::Path(QPath::Resolved(_, path3)) = first.kind; if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); if cx.typeck_results().expr_ty(ident1).is_integral(); if cx.typeck_results().expr_ty(ident2).is_integral(); diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs index 207423a186..cef74d87e7 100644 --- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs +++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs @@ -1,4 +1,6 @@ -use crate::utils::{find_macro_calls, is_type_diagnostic_item, return_ty, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{find_macro_calls, is_expn_of, return_ty}; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_lint::{LateContext, LateLintPass}; @@ -50,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn { } fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) { - let panics = find_macro_calls( + let mut panics = find_macro_calls( &[ "unimplemented", "unreachable", @@ -59,12 +61,10 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir "assert", "assert_eq", "assert_ne", - "debug_assert", - "debug_assert_eq", - "debug_assert_ne", ], body, ); + panics.retain(|span| is_expn_of(*span, "debug_assert").is_none()); if !panics.is_empty() { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs index 359620cc07..1a680e7607 100644 --- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs +++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_expn_of, match_panic_call, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_expn_of, match_panic_call}; use if_chain::if_chain; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; @@ -73,7 +74,7 @@ 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() { + if match_panic_call(cx, expr).is_some() && is_expn_of(expr.span, "debug_assert").is_none() { let span = get_outer_span(expr); if is_expn_of(expr.span, "unimplemented").is_some() { span_lint( @@ -96,11 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { fn get_outer_span(expr: &Expr<'_>) -> Span { if_chain! { if expr.span.from_expansion(); - let first = expr.span.ctxt().outer_expn_data(); - if first.call_site.from_expansion(); - let second = first.call_site.ctxt().outer_expn_data(); + let first = expr.span.ctxt().outer_expn_data().call_site; + if first.from_expansion(); then { - second.call_site + first.ctxt().outer_expn_data().call_site } else { expr.span } diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index aca1ed5ca6..1251ddd9a0 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_automatically_derived, span_lint_hir}; +use clippy_utils::diagnostics::span_lint_hir; +use clippy_utils::is_automatically_derived; use if_chain::if_chain; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index ff700aa514..6b64846c24 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -1,6 +1,10 @@ use std::cmp; +use std::iter; -use crate::utils::{is_copy, is_self_ty, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_self_ty; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_copy; use if_chain::if_chain; use rustc_ast::attr; use rustc_errors::Applicability; @@ -38,6 +42,14 @@ declare_clippy_lint! { /// false positives in cases involving multiple lifetimes that are bounded by /// each other. /// + /// Also, it does not take account of other similar cases where getting memory addresses + /// matters; namely, returning the pointer to the argument in question, + /// and passing the argument, as both references and pointers, + /// to a function that needs the memory address. For further details, refer to + /// [this issue](https://github.com/rust-lang/rust-clippy/issues/5953) + /// that explains a real case in which this false positive + /// led to an **undefined behaviour** introduced with unsafe code. + /// /// **Example:** /// /// ```rust @@ -119,7 +131,7 @@ impl<'tcx> PassByRefOrValue { let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir().body(id)); - for (index, (input, &ty)) in decl.inputs.iter().zip(fn_sig.inputs()).enumerate() { + for (index, (input, &ty)) in iter::zip(decl.inputs, fn_sig.inputs()).enumerate() { // All spans generated from a proc-macro invocation are the same... match span { Some(s) if s == input.span => return, @@ -138,11 +150,11 @@ impl<'tcx> PassByRefOrValue { }; if_chain! { - if !output_lts.contains(&input_lt); + if !output_lts.contains(input_lt); if is_copy(cx, ty); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); if size <= self.ref_min_size; - if let hir::TyKind::Rptr(_, MutTy { ty: ref decl_ty, .. }) = input.kind; + if let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind; then { let value_type = if is_self_ty(decl_ty) { "self".into() diff --git a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs index 4a7b0ad07a..0024592638 100644 --- a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs +++ b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -44,7 +45,7 @@ declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]); impl<'tcx> LateLintPass<'tcx> for PathBufPushOverwrite { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; + if let ExprKind::MethodCall(path, _, args, _) = expr.kind; if path.ident.name == sym!(push); if args.len() == 2; if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::PathBuf); diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index e76c8624b6..9bab783998 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -1,6 +1,7 @@ -use crate::utils::{last_path_segment, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::last_path_segment; use rustc_hir::{ - intravisit, Body, Expr, ExprKind, PatField, FnDecl, HirId, LocalSource, MatchSource, Mutability, Pat, PatKind, + intravisit, Body, Expr, ExprKind, FnDecl, HirId, LocalSource, MatchSource, Mutability, Pat, PatField, PatKind, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -9,6 +10,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use std::iter; declare_clippy_lint! { /// **What it does:** Checks for patterns that aren't exact representations of the types @@ -85,7 +87,7 @@ declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]); impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if let StmtKind::Local(ref local) = stmt.kind { + if let StmtKind::Local(local) = stmt.kind { if let Some(init) = &local.init { if let Some(init_ty) = cx.typeck_results().node_type_opt(init.hir_id) { let pat = &local.pat; @@ -103,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Match(ref expr, arms, source) = expr.kind { + if let ExprKind::Match(expr, arms, source) = expr.kind { match source { MatchSource::Normal | MatchSource::IfLetDesugar { .. } | MatchSource::WhileLetDesugar => { if let Some(expr_ty) = cx.typeck_results().node_type_opt(expr.hir_id) { @@ -133,8 +135,8 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { hir_id: HirId, ) { if let Some(fn_sig) = cx.typeck_results().liberated_fn_sigs().get(hir_id) { - for (param, ty) in body.params.iter().zip(fn_sig.inputs().iter()) { - apply_lint(cx, ¶m.pat, ty, DerefPossible::Impossible); + for (param, ty) in iter::zip(body.params, fn_sig.inputs()) { + apply_lint(cx, param.pat, ty, DerefPossible::Impossible); } } } @@ -186,7 +188,7 @@ fn find_first_mismatch<'tcx>( ty: Ty<'tcx>, level: Level, ) -> Option<(Span, Mutability, Level)> { - if let PatKind::Ref(ref sub_pat, _) = pat.kind { + if let PatKind::Ref(sub_pat, _) = pat.kind { if let TyKind::Ref(_, sub_ty, _) = ty.kind() { return find_first_mismatch(cx, sub_pat, sub_ty, Level::Lower); } @@ -198,8 +200,8 @@ fn find_first_mismatch<'tcx>( } } - if let PatKind::Struct(ref qpath, ref field_pats, _) = pat.kind { - if let TyKind::Adt(ref adt_def, ref substs_ref) = ty.kind() { + if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind { + if let TyKind::Adt(adt_def, substs_ref) = ty.kind() { if let Some(variant) = get_variant(adt_def, qpath) { let field_defs = &variant.fields; return find_first_mismatch_in_struct(cx, field_pats, field_defs, substs_ref); @@ -207,8 +209,8 @@ fn find_first_mismatch<'tcx>( } } - if let PatKind::TupleStruct(ref qpath, ref pats, _) = pat.kind { - if let TyKind::Adt(ref adt_def, ref substs_ref) = ty.kind() { + if let PatKind::TupleStruct(ref qpath, pats, _) = pat.kind { + if let TyKind::Adt(adt_def, substs_ref) = ty.kind() { if let Some(variant) = get_variant(adt_def, qpath) { let field_defs = &variant.fields; let ty_iter = field_defs.iter().map(|field_def| field_def.ty(cx.tcx, substs_ref)); @@ -217,7 +219,7 @@ fn find_first_mismatch<'tcx>( } } - if let PatKind::Tuple(ref pats, _) = pat.kind { + if let PatKind::Tuple(pats, _) = pat.kind { if let TyKind::Tuple(..) = ty.kind() { return find_first_mismatch_in_tuple(cx, pats, ty.tuple_fields()); } diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs index c9d18c3cb7..9cf00c953b 100644 --- a/src/tools/clippy/clippy_lints/src/precedence.rs +++ b/src/tools/clippy/clippy_lints/src/precedence.rs @@ -1,4 +1,5 @@ -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 6ea2d8b06d..b0674f9067 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -1,10 +1,10 @@ //! Checks for usage of `&Vec[_]` and `&String`. -use crate::utils::ptr::get_spans; -use crate::utils::{ - is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg, - span_lint_and_then, walk_ptrs_hir_ty, -}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +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 if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ @@ -15,6 +15,7 @@ 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::symbol::Symbol; use rustc_span::{sym, MultiSpan}; use std::borrow::Cow; @@ -94,7 +95,7 @@ declare_clippy_lint! { /// ``` pub CMP_NULL, style, - "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead." + "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead" } declare_clippy_lint! { @@ -119,12 +120,33 @@ declare_clippy_lint! { "fns that create mutable refs from immutable ref args" } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]); +declare_clippy_lint! { + /// **What it does:** This lint checks for invalid usages of `ptr::null`. + /// + /// **Why is this bad?** This causes undefined behavior. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```ignore + /// // Bad. Undefined behavior + /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); } + /// ``` + /// + /// // Good + /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); } + /// ``` + pub INVALID_NULL_PTR_USAGE, + correctness, + "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead" +} + +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Fn(ref sig, _, body_id) = item.kind { - check_fn(cx, &sig.decl, item.hir_id(), Some(body_id)); + check_fn(cx, sig.decl, item.hir_id(), Some(body_id)); } } @@ -136,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { return; // ignore trait impls } } - check_fn(cx, &sig.decl, item.hir_id(), Some(body_id)); + check_fn(cx, sig.decl, item.hir_id(), Some(body_id)); } } @@ -147,13 +169,13 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { } else { None }; - check_fn(cx, &sig.decl, item.hir_id(), body_id); + check_fn(cx, sig.decl, item.hir_id(), body_id); } } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref op, ref l, ref r) = expr.kind { - if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) { + if let ExprKind::Binary(ref op, l, r) = expr.kind { + if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(cx, l) || is_null_path(cx, r)) { span_lint( cx, CMP_NULL, @@ -161,6 +183,55 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { "comparing with null is better expressed by the `.is_null()` method", ); } + } else { + check_invalid_ptr_usage(cx, expr); + } + } +} + +fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + // (fn_path, arg_indices) - `arg_indices` are the `arg` positions where null would cause U.B. + const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], &[usize]); 16] = [ + (&paths::SLICE_FROM_RAW_PARTS, &[0]), + (&paths::SLICE_FROM_RAW_PARTS_MUT, &[0]), + (&paths::PTR_COPY, &[0, 1]), + (&paths::PTR_COPY_NONOVERLAPPING, &[0, 1]), + (&paths::PTR_READ, &[0]), + (&paths::PTR_READ_UNALIGNED, &[0]), + (&paths::PTR_READ_VOLATILE, &[0]), + (&paths::PTR_REPLACE, &[0]), + (&paths::PTR_SLICE_FROM_RAW_PARTS, &[0]), + (&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, &[0]), + (&paths::PTR_SWAP, &[0, 1]), + (&paths::PTR_SWAP_NONOVERLAPPING, &[0, 1]), + (&paths::PTR_WRITE, &[0]), + (&paths::PTR_WRITE_UNALIGNED, &[0]), + (&paths::PTR_WRITE_VOLATILE, &[0]), + (&paths::PTR_WRITE_BYTES, &[0]), + ]; + + if_chain! { + if let ExprKind::Call(ref fun, ref args) = expr.kind; + if let ExprKind::Path(ref qpath) = fun.kind; + if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); + let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>(); + if let Some(&(_, arg_indices)) = INVALID_NULL_PTR_USAGE_TABLE + .iter() + .find(|&&(fn_path, _)| fn_path == fun_def_path); + then { + for &arg_idx in arg_indices { + if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) { + span_lint_and_sugg( + cx, + INVALID_NULL_PTR_USAGE, + arg.span, + "pointer must be non-null", + "change this to", + "core::ptr::NonNull::dangling().as_ptr()".to_string(), + Applicability::MachineApplicable, + ); + } + } } } } @@ -262,35 +333,34 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: } } else if match_type(cx, ty, &paths::COW) { if_chain! { - if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.kind; - if let TyKind::Path(QPath::Resolved(None, ref pp)) = ty.kind; + if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind; + if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind; if let [ref bx] = *pp.segments; - if let Some(ref params) = bx.args; + if let Some(params) = bx.args; if !params.parenthesized; if let Some(inner) = params.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, }); + let replacement = snippet_opt(cx, inner.span); + if let Some(r) = replacement; then { - let replacement = snippet_opt(cx, inner.span); - if let Some(r) = replacement { - span_lint_and_sugg( - cx, - PTR_ARG, - arg.span, - "using a reference to `Cow` is not recommended", - "change this to", - "&".to_owned() + &r, - Applicability::Unspecified, - ); - } + span_lint_and_sugg( + cx, + PTR_ARG, + arg.span, + "using a reference to `Cow` is not recommended", + "change this to", + "&".to_owned() + &r, + Applicability::Unspecified, + ); } } } } } - if let FnRetTy::Return(ref ty) = decl.output { + if let FnRetTy::Return(ty) = decl.output { if let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) { let mut immutables = vec![]; for (_, ref mutbl, ref argspan) in decl @@ -323,8 +393,8 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: fn get_only_generic_arg_snippet(cx: &LateContext<'_>, arg: &Ty<'_>) -> Option<String> { if_chain! { - if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind; - if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last(); + if let TyKind::Path(QPath::Resolved(_, path)) = walk_ptrs_hir_ty(arg).kind; + if let Some(&PathSegment{args: Some(parameters), ..}) = path.segments.last(); let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, @@ -346,13 +416,12 @@ fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, } } -fn is_null_path(expr: &Expr<'_>) -> bool { - if let ExprKind::Call(ref pathexp, ref args) = expr.kind { - if args.is_empty() { - if let ExprKind::Path(ref path) = pathexp.kind { - return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT); - } - } +fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let ExprKind::Call(pathexp, []) = expr.kind { + expr_path_res(cx, pathexp).opt_def_id().map_or(false, |id| { + match_any_def_paths(cx, id, &[&paths::PTR_NULL, &paths::PTR_NULL_MUT]).is_some() + }) + } else { + false } - false } diff --git a/src/tools/clippy/clippy_lints/src/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/ptr_eq.rs index 3be792ce5e..77cfa3f6b1 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_eq.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_eq.rs @@ -1,4 +1,6 @@ -use crate::utils; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; +use clippy_utils::source::snippet_opt; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -40,24 +42,24 @@ static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers"; impl LateLintPass<'_> for PtrEq { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if utils::in_macro(expr.span) { + if in_macro(expr.span) { return; } - if let ExprKind::Binary(ref op, ref left, ref right) = expr.kind { + if let ExprKind::Binary(ref op, left, right) = expr.kind { if BinOpKind::Eq == op.node { let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { (Some(lhs), Some(rhs)) => (lhs, rhs), - _ => (&**left, &**right), + _ => (left, right), }; if_chain! { if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left); if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right); - if let Some(left_snip) = utils::snippet_opt(cx, left_var.span); - if let Some(right_snip) = utils::snippet_opt(cx, right_var.span); + if let Some(left_snip) = snippet_opt(cx, left_var.span); + if let Some(right_snip) = snippet_opt(cx, right_var.span); then { - utils::span_lint_and_sugg( + span_lint_and_sugg( cx, PTR_EQ, expr.span, @@ -77,7 +79,7 @@ impl LateLintPass<'_> for PtrEq { // E.g., `foo as *const _ as usize` returns `foo as *const _`. fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize { - if let ExprKind::Cast(ref expr, _) = cast_expr.kind { + if let ExprKind::Cast(expr, _) = cast_expr.kind { return Some(expr); } } @@ -88,7 +90,7 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_> // E.g., `foo as *const _` returns `foo`. fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if cx.typeck_results().expr_ty(cast_expr).is_unsafe_ptr() { - if let ExprKind::Cast(ref expr, _) = cast_expr.kind { + if let ExprKind::Cast(expr, _) = cast_expr.kind { return Some(expr); } } diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs index e0996804a5..afb198f495 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,4 +1,5 @@ -use crate::utils::{snippet_opt, span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -77,8 +78,8 @@ impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast { // If the given expression is a cast from a usize, return the lhs of the cast fn expr_as_cast_from_usize<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { - if let ExprKind::Cast(ref cast_lhs_expr, _) = expr.kind { - if is_expr_ty_usize(cx, &cast_lhs_expr) { + if let ExprKind::Cast(cast_lhs_expr, _) = expr.kind { + if is_expr_ty_usize(cx, cast_lhs_expr) { return Some(cast_lhs_expr); } } @@ -91,7 +92,7 @@ fn expr_as_ptr_offset_call<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> { - if let ExprKind::MethodCall(ref path_segment, _, ref args, _) = expr.kind { + if let ExprKind::MethodCall(path_segment, _, args, _) = expr.kind { if is_expr_ty_raw_ptr(cx, &args[0]) { if path_segment.ident.name == sym::offset { return Some((&args[0], &args[1], Method::Offset)); diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 6c480d48c7..30bee21390 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -1,17 +1,17 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_lang_ctor; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{eq_expr_value, path_to_local_id}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{def, BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatKind, StmtKind}; +use rustc_hir::LangItem::{OptionNone, OptionSome}; +use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; -use crate::utils::sugg::Sugg; -use crate::utils::{ - eq_expr_value, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability, - span_lint_and_sugg, -}; - declare_clippy_lint! { /// **What it does:** Checks for expressions that could be replaced by the question mark operator. /// @@ -101,15 +101,14 @@ impl QuestionMark { if Self::is_option(cx, subject); if let PatKind::TupleStruct(path1, fields, None) = &arms[0].pat.kind; - if match_qpath(path1, &["Some"]); - if let PatKind::Binding(annot, _, bind, _) = &fields[0].kind; + if is_lang_ctor(cx, path1, OptionSome); + if let PatKind::Binding(annot, bind_id, _, _) = fields[0].kind; let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut); if let ExprKind::Block(block, None) = &arms[0].body.kind; if block.stmts.is_empty(); if let Some(trailing_expr) = &block.expr; - if let ExprKind::Path(path) = &trailing_expr.kind; - if match_qpath(path, &[&bind.as_str()]); + if path_to_local_id(trailing_expr, bind_id); if let PatKind::Wild = arms[1].pat.kind; if Self::expression_returns_none(cx, arms[1].body); @@ -149,23 +148,15 @@ impl QuestionMark { fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { match expression.kind { - ExprKind::Block(ref block, _) => { + ExprKind::Block(block, _) => { if let Some(return_expression) = Self::return_expression(block) { - return Self::expression_returns_none(cx, &return_expression); - } - - false - }, - ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr), - ExprKind::Path(ref qp) => { - if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) = - cx.qpath_res(qp, expression.hir_id) - { - return match_def_path(cx, def_id, &paths::OPTION_NONE); + return Self::expression_returns_none(cx, return_expression); } false }, + ExprKind::Ret(Some(expr)) => Self::expression_returns_none(cx, expr), + ExprKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone), _ => false, } } @@ -175,7 +166,7 @@ impl QuestionMark { if_chain! { if block.stmts.len() == 1; if let Some(expr) = block.stmts.iter().last(); - if let StmtKind::Semi(ref expr) = expr.kind; + if let StmtKind::Semi(expr) = expr.kind; if let ExprKind::Ret(Some(ret_expr)) = expr.kind; then { diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index 59503817c0..7169f96eaf 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -1,4 +1,9 @@ use crate::consts::{constant, Constant}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; +use clippy_utils::sugg::Sugg; +use clippy_utils::{get_parent_expr, in_constant, is_integer_const, meets_msrv, msrvs, single_segment_path}; +use clippy_utils::{higher, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; @@ -12,13 +17,6 @@ use rustc_span::sym; use rustc_span::symbol::Ident; use std::cmp::Ordering; -use crate::utils::sugg::Sugg; -use crate::utils::{ - get_parent_expr, in_constant, is_integer_const, meets_msrv, single_segment_path, snippet, snippet_opt, - snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then, -}; -use crate::utils::{higher, SpanlessEq}; - declare_clippy_lint! { /// **What it does:** Checks for zipping a collection with the range of /// `0.._.len()`. @@ -161,8 +159,6 @@ declare_clippy_lint! { "manually reimplementing {`Range`, `RangeInclusive`}`::contains`" } -const MANUAL_RANGE_CONTAINS_MSRV: RustcVersion = RustcVersion::new(1, 35, 0); - pub struct Ranges { msrv: Option<RustcVersion>, } @@ -185,11 +181,11 @@ impl_lint_pass!(Ranges => [ impl<'tcx> LateLintPass<'tcx> for Ranges { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match expr.kind { - ExprKind::MethodCall(ref path, _, ref args, _) => { + ExprKind::MethodCall(path, _, args, _) => { check_range_zip_with_len(cx, path, args, expr.span); }, - ExprKind::Binary(ref op, ref l, ref r) => { - if meets_msrv(self.msrv.as_ref(), &MANUAL_RANGE_CONTAINS_MSRV) { + ExprKind::Binary(ref op, l, r) => { + if meets_msrv(self.msrv.as_ref(), &msrvs::RANGE_CONTAINS) { check_possible_range_contains(cx, op.node, l, r, expr); } }, @@ -289,7 +285,7 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<' } fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant, Ident, Span, Span, Ordering, bool)> { - if let ExprKind::Binary(ref op, ref l, ref r) = ex.kind { + if let ExprKind::Binary(ref op, l, r) = ex.kind { let (inclusive, ordering) = match op.node { BinOpKind::Gt => (false, Ordering::Greater), BinOpKind::Ge => (true, Ordering::Greater), @@ -322,32 +318,29 @@ fn match_ident(e: &Expr<'_>) -> Option<Ident> { } fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args: &[Expr<'_>], span: Span) { - let name = path.ident.as_str(); - if name == "zip" && args.len() == 2 { - let iter = &args[0].kind; - let zip_arg = &args[1]; - if_chain! { - // `.iter()` call - if let ExprKind::MethodCall(ref iter_path, _, ref iter_args, _) = *iter; - if iter_path.ident.name == sym::iter; - // range expression in `.zip()` call: `0..x.len()` - if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg); - if is_integer_const(cx, start, 0); - // `.len()` call - if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind; - if len_path.ident.name == sym!(len) && len_args.len() == 1; - // `.iter()` and `.len()` called on same `Path` - if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind; - if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].kind; - if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments); - then { - span_lint(cx, - RANGE_ZIP_WITH_LEN, - span, - &format!("it is more idiomatic to use `{}.iter().enumerate()`", - snippet(cx, iter_args[0].span, "_")) - ); - } + if_chain! { + if path.ident.as_str() == "zip"; + if let [iter, zip_arg] = args; + // `.iter()` call + if let ExprKind::MethodCall(iter_path, _, iter_args, _) = iter.kind; + if iter_path.ident.name == sym::iter; + // range expression in `.zip()` call: `0..x.len()` + if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg); + 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; + // `.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; + if SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments); + then { + span_lint(cx, + RANGE_ZIP_WITH_LEN, + span, + &format!("it is more idiomatic to use `{}.iter().enumerate()`", + snippet(cx, iter_args[0].span, "_")) + ); } } } @@ -513,8 +506,8 @@ fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<' Spanned { node: BinOpKind::Add, .. }, - ref lhs, - ref rhs, + lhs, + rhs, ) => { if is_integer_const(cx, lhs, 1) { Some(rhs) @@ -534,8 +527,8 @@ fn y_minus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr< Spanned { node: BinOpKind::Sub, .. }, - ref lhs, - ref rhs, + lhs, + rhs, ) if is_integer_const(cx, rhs, 1) => Some(lhs), _ => None, } diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index f90d482056..7dafce60d5 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -1,7 +1,7 @@ -use crate::utils::{ - fn_has_unsatisfiable_preds, has_drop, is_copy, is_type_diagnostic_item, match_def_path, paths, snippet_opt, - span_lint_hir, span_lint_hir_and_then, walk_ptrs_ty_depth, -}; +use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, walk_ptrs_ty_depth}; +use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths}; use if_chain::if_chain; use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation}; use rustc_errors::Applicability; @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { .into_results_cursor(mir); let mut possible_borrower = { let mut vis = PossibleBorrowerVisitor::new(cx, mir); - vis.visit_body(&mir); + vis.visit_body(mir); vis.into_map(cx, maybe_storage_live_result) }; @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { continue; } - if let ty::Adt(ref def, _) = arg_ty.kind() { + if let ty::Adt(def, _) = arg_ty.kind() { if match_def_path(cx, def.did, &paths::MEM_MANUALLY_DROP) { continue; } @@ -199,79 +199,72 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { (local, deref_clone_ret) }; - let is_temp = mir.local_kind(ret_local) == mir::LocalKind::Temp; - - // 1. `local` can be moved out if it is not used later. - // 2. If `ret_local` is a temporary and is neither consumed nor mutated, we can remove this `clone` - // call anyway. - let (used, consumed_or_mutated) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold( - (false, !is_temp), - |(used, consumed), (tbb, tdata)| { - // Short-circuit - if (used && consumed) || - // Give up on loops - tdata.terminator().successors().any(|s| *s == bb) - { - return (true, true); + let clone_usage = if local == ret_local { + CloneUsage { + cloned_used: false, + cloned_consume_or_mutate_loc: None, + clone_consumed_or_mutated: true, + } + } else { + let clone_usage = visit_clone_usage(local, ret_local, mir, bb); + if clone_usage.cloned_used && clone_usage.clone_consumed_or_mutated { + // cloned value is used, and the clone is modified or moved + continue; + } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc { + // cloned value is mutated, and the clone is alive. + if possible_borrower.is_alive_at(ret_local, loc) { + continue; } + } + clone_usage + }; - let mut vis = LocalUseVisitor { - used: (local, false), - consumed_or_mutated: (ret_local, false), - }; - vis.visit_basic_block_data(tbb, tdata); - (used || vis.used.1, consumed || vis.consumed_or_mutated.1) - }, - ); - - if !used || !consumed_or_mutated { - let span = terminator.source_info.span; - let scope = terminator.source_info.scope; - let node = mir.source_scopes[scope] - .local_data - .as_ref() - .assert_crate_local() - .lint_root; - - if_chain! { - if let Some(snip) = snippet_opt(cx, span); - if let Some(dot) = snip.rfind('.'); - then { - let sugg_span = span.with_lo( - span.lo() + BytePos(u32::try_from(dot).unwrap()) - ); - let mut app = Applicability::MaybeIncorrect; - - let call_snip = &snip[dot + 1..]; - // Machine applicable when `call_snip` looks like `foobar()` - if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) { - if call_snip.as_bytes().iter().all(|b| b.is_ascii_alphabetic() || *b == b'_') { - app = Applicability::MachineApplicable; - } + let span = terminator.source_info.span; + let scope = terminator.source_info.scope; + let node = mir.source_scopes[scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; + + if_chain! { + if let Some(snip) = snippet_opt(cx, span); + if let Some(dot) = snip.rfind('.'); + then { + let sugg_span = span.with_lo( + span.lo() + BytePos(u32::try_from(dot).unwrap()) + ); + let mut app = Applicability::MaybeIncorrect; + + let call_snip = &snip[dot + 1..]; + // Machine applicable when `call_snip` looks like `foobar()` + if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) { + if call_snip.as_bytes().iter().all(|b| b.is_ascii_alphabetic() || *b == b'_') { + app = Applicability::MachineApplicable; } + } - span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| { - diag.span_suggestion( - sugg_span, - "remove this", - String::new(), - app, + span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| { + diag.span_suggestion( + sugg_span, + "remove this", + String::new(), + app, + ); + if clone_usage.cloned_used { + diag.span_note( + span, + "cloned value is neither consumed nor mutated", ); - if used { - diag.span_note( - span, - "cloned value is neither consumed nor mutated", - ); - } else { - diag.span_note( - span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())), - "this value is dropped without further use", - ); - } - }); - } else { - span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone"); - } + } else { + diag.span_note( + span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())), + "this value is dropped without further use", + ); + } + }); + } else { + span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone"); } } } @@ -365,49 +358,97 @@ fn base_local_and_movability<'tcx>( (local, deref || field || slice) } -struct LocalUseVisitor { - used: (mir::Local, bool), - consumed_or_mutated: (mir::Local, bool), +#[derive(Default)] +struct CloneUsage { + /// Whether the cloned value is used after the clone. + cloned_used: bool, + /// The first location where the cloned value is consumed or mutated, if any. + cloned_consume_or_mutate_loc: Option<mir::Location>, + /// Whether the clone value is mutated. + clone_consumed_or_mutated: bool, } - -impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { - fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) { - let statements = &data.statements; - for (statement_index, statement) in statements.iter().enumerate() { - self.visit_statement(statement, mir::Location { block, statement_index }); - } - - self.visit_terminator( - data.terminator(), - mir::Location { - block, - statement_index: statements.len(), - }, - ); +fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, bb: mir::BasicBlock) -> CloneUsage { + struct V { + cloned: mir::Local, + clone: mir::Local, + result: CloneUsage, } + impl<'tcx> mir::visit::Visitor<'tcx> for V { + fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) { + let statements = &data.statements; + for (statement_index, statement) in statements.iter().enumerate() { + self.visit_statement(statement, mir::Location { block, statement_index }); + } - fn visit_place(&mut self, place: &mir::Place<'tcx>, ctx: PlaceContext, _: mir::Location) { - let local = place.local; - - if local == self.used.0 - && !matches!( - ctx, - PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) - ) - { - self.used.1 = true; + self.visit_terminator( + data.terminator(), + mir::Location { + block, + statement_index: statements.len(), + }, + ); } - if local == self.consumed_or_mutated.0 { - match ctx { - PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) - | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { - self.consumed_or_mutated.1 = true; - }, - _ => {}, + fn visit_place(&mut self, place: &mir::Place<'tcx>, ctx: PlaceContext, loc: mir::Location) { + let local = place.local; + + if local == self.cloned + && !matches!( + ctx, + PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) + ) + { + self.result.cloned_used = true; + self.result.cloned_consume_or_mutate_loc = self.result.cloned_consume_or_mutate_loc.or_else(|| { + matches!( + ctx, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) + | PlaceContext::MutatingUse(MutatingUseContext::Borrow) + ) + .then(|| loc) + }); + } else if local == self.clone { + match ctx { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) + | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { + self.result.clone_consumed_or_mutated = true; + }, + _ => {}, + } } } } + + let init = CloneUsage { + cloned_used: false, + cloned_consume_or_mutate_loc: None, + // Consider non-temporary clones consumed. + // TODO: Actually check for mutation of non-temporaries. + clone_consumed_or_mutated: mir.local_kind(clone) != mir::LocalKind::Temp, + }; + traversal::ReversePostorder::new(mir, bb) + .skip(1) + .fold(init, |usage, (tbb, tdata)| { + // Short-circuit + if (usage.cloned_used && usage.clone_consumed_or_mutated) || + // Give up on loops + tdata.terminator().successors().any(|s| *s == bb) + { + return CloneUsage { + cloned_used: true, + clone_consumed_or_mutated: true, + ..usage + }; + } + + let mut v = V { + cloned, + clone, + result: usage, + }; + v.visit_basic_block_data(tbb, tdata); + v.result + }) } /// Determines liveness of each local purely based on `StorageLive`/`Dead`. @@ -547,7 +588,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> { // 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() { + if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_continue() { return; } @@ -556,7 +597,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> { mir::Operand::Copy(p) | mir::Operand::Move(p) => { self.possible_borrower.add(p.local, *dest); }, - _ => (), + mir::Operand::Constant(..) => (), } } } @@ -578,7 +619,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { let mut visit_op = |op: &mir::Operand<'_>| match op { mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local), - _ => (), + mir::Operand::Constant(..) => (), }; match rvalue { @@ -623,4 +664,9 @@ impl PossibleBorrowerMap<'_, '_> { self.bitset.0 == self.bitset.1 } + + fn is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool { + self.maybe_live.seek_after_primary_effect(at); + self.maybe_live.contains(local) + } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index f398b3fff2..92921bedf4 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -1,4 +1,5 @@ -use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; use rustc_ast::ast; use rustc_ast::visit as ast_visit; @@ -110,10 +111,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if_chain! { - if let hir::ExprKind::Call(ref closure, _) = expr.kind; - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; - if self.path.segments[0].ident == path.segments[0].ident - && self.path.res == path.res; + if let hir::ExprKind::Call(closure, _) = expr.kind; + if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind; + if self.path.segments[0].ident == path.segments[0].ident; + if self.path.res == path.res; then { self.count += 1; } @@ -132,14 +133,14 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { for w in block.stmts.windows(2) { if_chain! { - if let hir::StmtKind::Local(ref local) = w[0].kind; - if let Option::Some(ref t) = local.init; + if let hir::StmtKind::Local(local) = w[0].kind; + if let Option::Some(t) = local.init; if let hir::ExprKind::Closure(..) = t.kind; if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind; - if let hir::StmtKind::Semi(ref second) = w[1].kind; - if let hir::ExprKind::Assign(_, ref call, _) = second.kind; - if let hir::ExprKind::Call(ref closure, _) = call.kind; - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind; + if let hir::StmtKind::Semi(second) = w[1].kind; + if let hir::ExprKind::Assign(_, call, _) = second.kind; + if let hir::ExprKind::Call(closure, _) = call.kind; + if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind; if ident == path.segments[0].ident; if count_closure_usage(cx, block, path) == 1; then { diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs index 3d585cd27a..061526c6f0 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_else.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_ast::visit::{walk_expr, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs index 9688ef3933..d5ee8d3468 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs @@ -1,4 +1,5 @@ -use crate::utils::{meets_msrv, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{meets_msrv, msrvs}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -6,8 +7,6 @@ use rustc_middle::lint::in_external_macro; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; -const REDUNDANT_FIELD_NAMES_MSRV: RustcVersion = RustcVersion::new(1, 17, 0); - declare_clippy_lint! { /// **What it does:** Checks for fields in struct literals where shorthands /// could be used. @@ -51,7 +50,7 @@ impl_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]); impl EarlyLintPass for RedundantFieldNames { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if !meets_msrv(self.msrv.as_ref(), &REDUNDANT_FIELD_NAMES_MSRV) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::FIELD_INIT_SHORTHAND) { return; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index c876bae230..e091095de1 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind, VisibilityKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index e5ced13514..9c6cd7b4fa 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -1,12 +1,14 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_context; +use clippy_utils::ty::is_type_lang_item; +use clippy_utils::{get_parent_expr, in_macro}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, LangItem}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::{lint::in_external_macro, ty::TyS}; +use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyS; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{is_type_lang_item, snippet_with_applicability, span_lint_and_sugg}; - declare_clippy_lint! { /// **What it does:** Checks for redundant slicing expressions which use the full range, and /// do not change the type. @@ -39,26 +41,44 @@ declare_lint_pass!(RedundantSlicing => [REDUNDANT_SLICING]); impl LateLintPass<'_> for RedundantSlicing { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) { + if in_macro(expr.span) { return; } + let ctxt = expr.span.ctxt(); if_chain! { - if let ExprKind::AddrOf(_, _, addressee) = expr.kind; + if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind; + if addressee.span.ctxt() == ctxt; if let ExprKind::Index(indexed, range) = addressee.kind; if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull); if TyS::same_type(cx.typeck_results().expr_ty(expr), cx.typeck_results().expr_ty(indexed)); then { let mut app = Applicability::MachineApplicable; - let hint = snippet_with_applicability(cx, indexed.span, "..", &mut app).into_owned(); + let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; + + let (reborrow_str, help_str) = if mutability == Mutability::Mut { + // The slice was used to reborrow the mutable reference. + ("&mut *", "reborrow the original value instead") + } else if matches!( + get_parent_expr(cx, expr), + Some(Expr { + kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _), + .. + }) + ) { + // The slice was used to make a temporary reference. + ("&*", "reborrow the original value instead") + } else { + ("", "use the original value instead") + }; span_lint_and_sugg( cx, REDUNDANT_SLICING, expr.span, "redundant slicing of the whole range", - "use the original slice instead", - hint, + help_str, + format!("{}{}", reborrow_str, snip), app, ); } diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index fcfa3c1275..48107d9c03 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,12 +1,12 @@ -use crate::utils::{meets_msrv, snippet, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::{meets_msrv, msrvs}; use rustc_ast::ast::{Item, ItemKind, Ty, TyKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; -const REDUNDANT_STATIC_LIFETIMES_MSRV: RustcVersion = RustcVersion::new(1, 17, 0); - declare_clippy_lint! { /// **What it does:** Checks for constants and statics with an explicit `'static` lifetime. /// @@ -98,7 +98,7 @@ impl RedundantStaticLifetimes { impl EarlyLintPass for RedundantStaticLifetimes { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if !meets_msrv(self.msrv.as_ref(), &REDUNDANT_STATIC_LIFETIMES_MSRV) { + if !meets_msrv(self.msrv.as_ref(), &msrvs::STATIC_IN_CONST) { return; } diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index 8cd6692ce0..0cf4e0ce7f 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -1,12 +1,13 @@ -use crate::utils::{last_path_segment, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::last_path_segment; +use clippy_utils::source::snippet; +use if_chain::if_chain; +use rustc_errors::Applicability; use rustc_hir::{GenericArg, Mutability, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; -use if_chain::if_chain; -use rustc_errors::Applicability; - declare_clippy_lint! { /// **What it does:** Checks for usage of `&Option<&T>`. /// @@ -43,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { if let Some(def_id) = res.opt_def_id(); if cx.tcx.is_diagnostic_item(sym::option_type, def_id); - if let Some(ref params) = last_path_segment(qpath).args ; + if let Some(params) = last_path_segment(qpath).args ; if !params.parenthesized; if let Some(inner_ty) = params.args.iter().find_map(|arg| match arg { GenericArg::Type(inner_ty) => Some(inner_ty), diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs index e1450466a7..d6336389b0 100644 --- a/src/tools/clippy/clippy_lints/src/reference.rs +++ b/src/tools/clippy/clippy_lints/src/reference.rs @@ -1,5 +1,7 @@ -use crate::utils::sugg::Sugg; -use crate::utils::{in_macro, snippet_opt, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; +use clippy_utils::source::{snippet_opt, snippet_with_applicability}; +use clippy_utils::sugg::Sugg; use if_chain::if_chain; use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp}; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index 1edea61314..4b5306de58 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -1,5 +1,6 @@ use crate::consts::{constant, Constant}; -use crate::utils::{match_def_path, paths, span_lint, span_lint_and_help}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_ast::ast::{LitKind, StrStyle}; use rustc_data_structures::fx::FxHashSet; @@ -59,7 +60,7 @@ impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); impl<'tcx> LateLintPass<'tcx> for Regex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Call(ref fun, ref args) = expr.kind; + if let ExprKind::Call(fun, args) = expr.kind; if let ExprKind::Path(ref qpath) = fun.kind; if args.len() == 1; if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); @@ -133,7 +134,7 @@ fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> { fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { if_chain! { - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind; + if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind; if let ExprKind::Array(exprs) = expr.kind; then { for expr in exprs { diff --git a/src/tools/clippy/clippy_lints/src/repeat_once.rs b/src/tools/clippy/clippy_lints/src/repeat_once.rs index d34e744eb9..560a5e7c92 100644 --- a/src/tools/clippy/clippy_lints/src/repeat_once.rs +++ b/src/tools/clippy/clippy_lints/src/repeat_once.rs @@ -1,5 +1,8 @@ use crate::consts::{constant_context, Constant}; -use crate::utils::{in_macro, is_type_diagnostic_item, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; @@ -42,10 +45,10 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { if_chain! { if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind; if path.ident.name == sym!(repeat); - if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(&count); + if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(count); if !in_macro(receiver.span); then { - let ty = cx.typeck_results().expr_ty(&receiver).peel_refs(); + let ty = cx.typeck_results().expr_ty(receiver).peel_refs(); if ty.is_str() { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 40c0f1f458..b565c77aae 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -1,3 +1,6 @@ +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::snippet_opt; +use clippy_utils::{fn_def_id, in_macro, path_to_local_id}; use if_chain::if_chain; use rustc_ast::ast::Attribute; use rustc_errors::Applicability; @@ -11,8 +14,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::sym; -use crate::utils::{fn_def_id, in_macro, match_qpath, snippet_opt, span_lint_and_sugg, span_lint_and_then}; - declare_clippy_lint! { /// **What it does:** Checks for `let`-bindings, which are subsequently /// returned. @@ -83,9 +84,8 @@ impl<'tcx> LateLintPass<'tcx> for Return { if local.ty.is_none(); if cx.tcx.hir().attrs(local.hir_id).is_empty(); if let Some(initexpr) = &local.init; - if let PatKind::Binding(.., ident, _) = local.pat.kind; - if let ExprKind::Path(qpath) = &retexpr.kind; - if match_qpath(qpath, &[&*ident.name.as_str()]); + if let PatKind::Binding(_, local_id, _, _) = local.pat.kind; + if path_to_local_id(retexpr, local_id); if !last_statement_borrows(cx, initexpr); if !in_external_macro(cx.sess(), initexpr.span); if !in_external_macro(cx.sess(), retexpr.span); @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { err.span_label(local.span, "unnecessary `let` binding"); if let Some(mut snippet) = snippet_opt(cx, initexpr.span) { - if !cx.typeck_results().expr_adjustments(&retexpr).is_empty() { + if !cx.typeck_results().expr_adjustments(retexpr).is_empty() { snippet.push_str(" as _"); } err.multipart_suggestion( @@ -142,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { check_final_expr(cx, &body.value, Some(body.value.span), replacement) }, FnKind::ItemFn(..) | FnKind::Method(..) => { - if let ExprKind::Block(ref block, _) = body.value.kind { + if let ExprKind::Block(block, _) = body.value.kind { check_block_return(cx, block); } }, @@ -159,7 +159,7 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, block: &Block<'tcx>) { check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty); } else if let Some(stmt) = block.stmts.iter().last() { match stmt.kind { - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { + StmtKind::Expr(expr) | StmtKind::Semi(expr) => { check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty); }, _ => (), @@ -191,11 +191,11 @@ fn check_final_expr<'tcx>( } }, // a whole block? check it! - ExprKind::Block(ref block, _) => { + ExprKind::Block(block, _) => { check_block_return(cx, block); }, ExprKind::If(_, then, else_clause_opt) => { - if let ExprKind::Block(ref ifblock, _) = then.kind { + if let ExprKind::Block(ifblock, _) = then.kind { check_block_return(cx, ifblock); } if let Some(else_clause) = else_clause_opt { @@ -206,22 +206,23 @@ fn check_final_expr<'tcx>( // an if/if let expr, check both exprs // note, if without else is going to be a type checking error anyways // (except for unit type functions) so we don't match it - ExprKind::Match(_, ref arms, source) => match source { + ExprKind::Match(_, arms, source) => match source { MatchSource::Normal => { for arm in arms.iter() { - check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); + check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Block); } }, MatchSource::IfLetDesugar { contains_else_clause: true, } => { - if let ExprKind::Block(ref ifblock, _) = arms[0].body.kind { + if let ExprKind::Block(ifblock, _) = arms[0].body.kind { check_block_return(cx, ifblock); } check_final_expr(cx, arms[1].body, None, RetReplacement::Empty); }, _ => (), }, + ExprKind::DropTemps(expr) => check_final_expr(cx, expr, None, RetReplacement::Empty), _ => (), } } diff --git a/src/tools/clippy/clippy_lints/src/self_assignment.rs b/src/tools/clippy/clippy_lints/src/self_assignment.rs index e096c9aebc..e7925c4fbd 100644 --- a/src/tools/clippy/clippy_lints/src/self_assignment.rs +++ b/src/tools/clippy/clippy_lints/src/self_assignment.rs @@ -1,4 +1,6 @@ -use crate::utils::{eq_expr_value, snippet, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::eq_expr_value; +use clippy_utils::source::snippet; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs index 839c995e52..553987a426 100644 --- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs @@ -1,4 +1,6 @@ -use crate::utils::{in_macro, snippet_with_macro_callsite, span_lint_and_sugg, sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_macro_callsite; +use clippy_utils::{in_macro, sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Block, ExprKind}; @@ -49,7 +51,7 @@ impl LateLintPass<'_> for SemicolonIfNothingReturned { return; } - let sugg = sugg::Sugg::hir_with_macro_callsite(cx, &expr, ".."); + let sugg = sugg::Sugg::hir_with_macro_callsite(cx, expr, ".."); let suggestion = format!("{0};", sugg); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs index 90cf1b6c86..169f7d2628 100644 --- a/src/tools/clippy/clippy_lints/src/serde_api.rs +++ b/src/tools/clippy/clippy_lints/src/serde_api.rs @@ -1,4 +1,5 @@ -use crate::utils::{get_trait_def_id, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{get_trait_def_id, paths}; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 32f6bc7464..d6101bd5e3 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -1,4 +1,6 @@ -use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::{contains_name, higher, iter_input_pats}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind, @@ -128,12 +130,12 @@ fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: & let len = bindings.len(); for stmt in block.stmts { match stmt.kind { - StmtKind::Local(ref local) => check_local(cx, local, bindings), - StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings), + StmtKind::Local(local) => check_local(cx, local, bindings), + StmtKind::Expr(e) | StmtKind::Semi(e) => check_expr(cx, e, bindings), StmtKind::Item(..) => {}, } } - if let Some(ref o) = block.expr { + if let Some(o) = block.expr { check_expr(cx, o, bindings); } bindings.truncate(len); @@ -147,16 +149,16 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: & return; } let Local { - ref pat, + pat, ref ty, ref init, span, .. } = *local; - if let Some(ref t) = *ty { + if let Some(t) = *ty { check_ty(cx, t, bindings) } - if let Some(ref o) = *init { + if let Some(o) = *init { check_expr(cx, o, bindings); check_pat(cx, pat, Some(o), span, bindings); } else { @@ -194,34 +196,34 @@ fn check_pat<'tcx>( bindings.push((name, ident.span)); } } - if let Some(ref p) = *inner { + if let Some(p) = *inner { check_pat(cx, p, init, span, bindings); } }, PatKind::Struct(_, pfields, _) => { if let Some(init_struct) = init { - if let ExprKind::Struct(_, ref efields, _) = init_struct.kind { + if let ExprKind::Struct(_, efields, _) = init_struct.kind { for field in pfields { let name = field.ident.name; let efield = efields .iter() .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None }); - check_pat(cx, &field.pat, efield, span, bindings); + check_pat(cx, field.pat, efield, span, bindings); } } else { for field in pfields { - check_pat(cx, &field.pat, init, span, bindings); + check_pat(cx, field.pat, init, span, bindings); } } } else { for field in pfields { - check_pat(cx, &field.pat, None, span, bindings); + check_pat(cx, field.pat, None, span, bindings); } } }, PatKind::Tuple(inner, _) => { if let Some(init_tup) = init { - if let ExprKind::Tup(ref tup) = init_tup.kind { + if let ExprKind::Tup(tup) = init_tup.kind { for (i, p) in inner.iter().enumerate() { check_pat(cx, p, Some(&tup[i]), p.span, bindings); } @@ -236,10 +238,10 @@ fn check_pat<'tcx>( } } }, - PatKind::Box(ref inner) => { + PatKind::Box(inner) => { if let Some(initp) = init { - if let ExprKind::Box(ref inner_init) = initp.kind { - check_pat(cx, inner, Some(&**inner_init), span, bindings); + if let ExprKind::Box(inner_init) = initp.kind { + check_pat(cx, inner, Some(inner_init), span, bindings); } else { check_pat(cx, inner, init, span, bindings); } @@ -247,7 +249,7 @@ fn check_pat<'tcx>( check_pat(cx, inner, init, span, bindings); } }, - PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings), + PatKind::Ref(inner, _) => check_pat(cx, inner, init, span, bindings), // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), _ => (), } @@ -321,11 +323,10 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut return; } match expr.kind { - ExprKind::Unary(_, ref e) - | ExprKind::Field(ref e, _) - | ExprKind::AddrOf(_, _, ref e) - | ExprKind::Box(ref e) => check_expr(cx, e, bindings), - ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, ..) => check_block(cx, block, bindings), + ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => { + check_expr(cx, e, bindings) + }, + ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings), // ExprKind::Call // ExprKind::MethodCall ExprKind::Array(v) | ExprKind::Tup(v) => { @@ -333,18 +334,18 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut check_expr(cx, e, bindings) } }, - ExprKind::If(ref cond, ref then, ref otherwise) => { + ExprKind::If(cond, then, ref otherwise) => { check_expr(cx, cond, bindings); - check_expr(cx, &**then, bindings); - if let Some(ref o) = *otherwise { + check_expr(cx, then, bindings); + if let Some(o) = *otherwise { check_expr(cx, o, bindings); } }, - ExprKind::Match(ref init, arms, _) => { + ExprKind::Match(init, arms, _) => { check_expr(cx, init, bindings); let len = bindings.len(); for arm in arms { - check_pat(cx, &arm.pat, Some(&**init), arm.pat.span, bindings); + check_pat(cx, arm.pat, Some(init), arm.pat.span, bindings); // This is ugly, but needed to get the right type if let Some(ref guard) = arm.guard { match guard { @@ -355,7 +356,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut }, } } - check_expr(cx, &arm.body, bindings); + check_expr(cx, arm.body, bindings); bindings.truncate(len); } }, @@ -365,14 +366,12 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) { match ty.kind { - TyKind::Slice(ref sty) => check_ty(cx, sty, bindings), - TyKind::Array(ref fty, ref anon_const) => { + TyKind::Slice(sty) => check_ty(cx, sty, bindings), + TyKind::Array(fty, ref anon_const) => { check_ty(cx, fty, bindings); check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings); }, - TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => { - check_ty(cx, mty, bindings) - }, + TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings), TyKind::Tup(tup) => { for t in tup { check_ty(cx, t, bindings) @@ -385,12 +384,12 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<( fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool { match expr.kind { - ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner), - ExprKind::Block(ref block, _) => { + ExprKind::Box(inner) | ExprKind::AddrOf(_, _, inner) => is_self_shadow(name, inner), + ExprKind::Block(block, _) => { block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e)) }, - ExprKind::Unary(op, ref inner) => (UnOp::Deref == op) && is_self_shadow(name, inner), - ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path), + ExprKind::Unary(op, inner) => (UnOp::Deref == op) && is_self_shadow(name, inner), + ExprKind::Path(QPath::Resolved(_, path)) => path_eq_name(name, path), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs index 1fc4ff5c2e..a45bb10238 100644 --- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs +++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs @@ -1,10 +1,10 @@ -use crate::utils::{in_macro, span_lint_and_sugg}; -use if_chain::if_chain; -use rustc_ast::{Item, ItemKind, UseTreeKind}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::in_macro; +use rustc_ast::{ptr::P, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::edition::Edition; +use rustc_span::{edition::Edition, symbol::kw, Span, Symbol}; declare_clippy_lint! { /// **What it does:** Checking for imports with single component use path. @@ -37,26 +37,144 @@ declare_clippy_lint! { declare_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]); impl EarlyLintPass for SingleComponentPathImports { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if_chain! { - if !in_macro(item.span); - if cx.sess.opts.edition >= Edition::Edition2018; - if !item.vis.kind.is_pub(); - if let ItemKind::Use(use_tree) = &item.kind; - if let segments = &use_tree.prefix.segments; - if segments.len() == 1; - if let UseTreeKind::Simple(None, _, _) = use_tree.kind; - then { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { + if cx.sess.opts.edition < Edition::Edition2018 { + return; + } + check_mod(cx, &krate.items); + } +} + +fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) { + // keep track of imports reused with `self` keyword, + // such as `self::crypto_hash` in the example below + // ```rust,ignore + // use self::crypto_hash::{Algorithm, Hasher}; + // ``` + let mut imports_reused_with_self = Vec::new(); + + // keep track of single use statements + // such as `crypto_hash` in the example below + // ```rust,ignore + // use crypto_hash; + // ``` + let mut single_use_usages = Vec::new(); + + // keep track of macros defined in the module as we don't want it to trigger on this (#7106) + // ```rust,ignore + // macro_rules! foo { () => {} }; + // pub(crate) use foo; + // ``` + let mut macros = Vec::new(); + + for item in items { + track_uses( + cx, + &item, + &mut imports_reused_with_self, + &mut single_use_usages, + &mut macros, + ); + } + + for single_use in &single_use_usages { + if !imports_reused_with_self.contains(&single_use.0) { + let can_suggest = single_use.2; + if can_suggest { span_lint_and_sugg( cx, SINGLE_COMPONENT_PATH_IMPORTS, - item.span, + single_use.1, "this import is redundant", "remove it entirely", String::new(), - Applicability::MachineApplicable + Applicability::MachineApplicable, + ); + } else { + span_lint_and_help( + cx, + SINGLE_COMPONENT_PATH_IMPORTS, + single_use.1, + "this import is redundant", + None, + "remove this import", ); } } } } + +fn track_uses( + cx: &EarlyContext<'_>, + item: &Item, + imports_reused_with_self: &mut Vec<Symbol>, + single_use_usages: &mut Vec<(Symbol, Span, bool)>, + macros: &mut Vec<Symbol>, +) { + if in_macro(item.span) || item.vis.kind.is_pub() { + return; + } + + match &item.kind { + ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => { + check_mod(cx, &items); + }, + ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => { + macros.push(item.ident.name); + }, + ItemKind::Use(use_tree) => { + let segments = &use_tree.prefix.segments; + + let should_report = + |name: &Symbol| !macros.contains(name) || matches!(item.vis.kind, VisibilityKind::Inherited); + + // keep track of `use some_module;` usages + if segments.len() == 1 { + if let UseTreeKind::Simple(None, _, _) = use_tree.kind { + let name = segments[0].ident.name; + if should_report(&name) { + single_use_usages.push((name, item.span, true)); + } + } + return; + } + + if segments.is_empty() { + // keep track of `use {some_module, some_other_module};` usages + if let UseTreeKind::Nested(trees) = &use_tree.kind { + for tree in trees { + let segments = &tree.0.prefix.segments; + if segments.len() == 1 { + if let UseTreeKind::Simple(None, _, _) = tree.0.kind { + let name = segments[0].ident.name; + if should_report(&name) { + single_use_usages.push((name, tree.0.span, false)); + } + } + } + } + } + } else { + // keep track of `use self::some_module` usages + if segments[0].ident.name == kw::SelfLower { + // simple case such as `use self::module::SomeStruct` + if segments.len() > 1 { + imports_reused_with_self.push(segments[1].ident.name); + return; + } + + // nested case such as `use self::{module1::Struct1, module2::Struct2}` + if let UseTreeKind::Nested(trees) = &use_tree.kind { + for tree in trees { + let segments = &tree.0.prefix.segments; + if !segments.is_empty() { + imports_reused_with_self.push(segments[0].ident.name); + } + } + } + } + } + }, + _ => {}, + } +} diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs index 87e386baad..cd2bdec170 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -1,7 +1,8 @@ //! Lint on use of `size_of` or `size_of_val` of T in an expression //! expecting a count of T -use crate::utils::{match_def_path, paths, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_hir::BinOpKind; use rustc_hir::{Expr, ExprKind}; @@ -64,8 +65,8 @@ fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted: bool) fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> { const FUNCTIONS: [&[&str]; 8] = [ - &paths::COPY_NONOVERLAPPING, - &paths::COPY, + &paths::PTR_COPY_NONOVERLAPPING, + &paths::PTR_COPY, &paths::WRITE_BYTES, &paths::PTR_SWAP_NONOVERLAPPING, &paths::PTR_SLICE_FROM_RAW_PARTS, diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 96f6881556..191781be00 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -1,5 +1,7 @@ -use crate::utils::sugg::Sugg; -use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{get_enclosing_block, is_expr_path_def_path, path_to_local, path_to_local_id, paths, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -8,7 +10,7 @@ use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::sym; declare_clippy_lint! { /// **What it does:** Checks slow zero-filled vector initialization @@ -45,8 +47,8 @@ declare_lint_pass!(SlowVectorInit => [SLOW_VECTOR_INITIALIZATION]); /// assigned to a variable. For example, `let mut vec = Vec::with_capacity(0)` or /// `vec = Vec::with_capacity(0)` struct VecAllocation<'tcx> { - /// Symbol of the local variable name - variable_name: Symbol, + /// HirId of the variable + local_id: HirId, /// Reference to the expression which allocates the vector allocation_expr: &'tcx Expr<'tcx>, @@ -69,18 +71,17 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Matches initialization on reassignements. For example: `vec = Vec::with_capacity(100)` if_chain! { - if let ExprKind::Assign(ref left, ref right, _) = expr.kind; + if let ExprKind::Assign(left, right, _) = expr.kind; - // Extract variable name - if let ExprKind::Path(QPath::Resolved(_, ref path)) = left.kind; - if let Some(variable_name) = path.segments.get(0); + // Extract variable + if let Some(local_id) = path_to_local(left); // Extract len argument - if let Some(ref len_arg) = Self::is_vec_with_capacity(right); + if let Some(len_arg) = Self::is_vec_with_capacity(cx, right); then { let vi = VecAllocation { - variable_name: variable_name.ident.name, + local_id, allocation_expr: right, len_expr: len_arg, }; @@ -93,14 +94,14 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` if_chain! { - if let StmtKind::Local(ref local) = stmt.kind; - if let PatKind::Binding(BindingAnnotation::Mutable, .., variable_name, None) = local.pat.kind; - if let Some(ref init) = local.init; - if let Some(ref len_arg) = Self::is_vec_with_capacity(init); + if let StmtKind::Local(local) = stmt.kind; + if let PatKind::Binding(BindingAnnotation::Mutable, local_id, _, None) = local.pat.kind; + if let Some(init) = local.init; + if let Some(len_arg) = Self::is_vec_with_capacity(cx, init); then { let vi = VecAllocation { - variable_name: variable_name.name, + local_id, allocation_expr: init, len_expr: len_arg, }; @@ -114,19 +115,18 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { impl SlowVectorInit { /// Checks if the given expression is `Vec::with_capacity(..)`. It will return the expression /// of the first argument of `with_capacity` call if it matches or `None` if it does not. - fn is_vec_with_capacity<'tcx>(expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + fn is_vec_with_capacity<'tcx>(cx: &LateContext<'_>, expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::Call(ref func, ref args) = expr.kind; - if let ExprKind::Path(ref path) = func.kind; - if match_qpath(path, &["Vec", "with_capacity"]); - if args.len() == 1; - + if let ExprKind::Call(func, [arg]) = expr.kind; + if let ExprKind::Path(QPath::TypeRelative(ty, name)) = func.kind; + if name.ident.as_str() == "with_capacity"; + if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::vec_type); then { - return Some(&args[0]); + Some(arg) + } else { + None } } - - None } /// Search initialization for the given vector @@ -207,11 +207,9 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) { if_chain! { if self.initialization_found; - if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; - if let ExprKind::Path(ref qpath_subj) = args[0].kind; - if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]); + if let ExprKind::MethodCall(path, _, [self_arg, extend_arg], _) = expr.kind; + if path_to_local_id(self_arg, self.vec_alloc.local_id); if path.ident.name == sym!(extend); - if let Some(ref extend_arg) = args.get(1); if self.is_repeat_take(extend_arg); then { @@ -224,11 +222,9 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) { if_chain! { if self.initialization_found; - if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; - if let ExprKind::Path(ref qpath_subj) = args[0].kind; - if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]); + if let ExprKind::MethodCall(path, _, [self_arg, len_arg, fill_arg], _) = expr.kind; + if path_to_local_id(self_arg, self.vec_alloc.local_id); if path.ident.name == sym!(resize); - if let (Some(ref len_arg), Some(fill_arg)) = (args.get(1), args.get(2)); // Check that is filled with 0 if let ExprKind::Lit(ref lit) = fill_arg.kind; @@ -246,15 +242,15 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Returns `true` if give expression is `repeat(0).take(...)` fn is_repeat_take(&self, expr: &Expr<'_>) -> bool { if_chain! { - if let ExprKind::MethodCall(ref take_path, _, ref take_args, _) = expr.kind; + if let ExprKind::MethodCall(take_path, _, take_args, _) = expr.kind; if take_path.ident.name == sym!(take); // Check that take is applied to `repeat(0)` - if let Some(ref repeat_expr) = take_args.get(0); - if Self::is_repeat_zero(repeat_expr); + if let Some(repeat_expr) = take_args.get(0); + if self.is_repeat_zero(repeat_expr); // Check that len expression is equals to `with_capacity` expression - if let Some(ref len_arg) = take_args.get(1); + if let Some(len_arg) = take_args.get(1); if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr); then { @@ -266,21 +262,19 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { } /// Returns `true` if given expression is `repeat(0)` - fn is_repeat_zero(expr: &Expr<'_>) -> bool { + fn is_repeat_zero(&self, expr: &Expr<'_>) -> bool { if_chain! { - if let ExprKind::Call(ref fn_expr, ref repeat_args) = expr.kind; - if let ExprKind::Path(ref qpath_repeat) = fn_expr.kind; - if match_qpath(&qpath_repeat, &["repeat"]); - if let Some(ref repeat_arg) = repeat_args.get(0); + if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind; + if is_expr_path_def_path(self.cx, fn_expr, &paths::ITER_REPEAT); if let ExprKind::Lit(ref lit) = repeat_arg.kind; if let LitKind::Int(0, _) = lit.node; then { - return true + true + } else { + false } } - - false } } @@ -290,7 +284,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { if self.initialization_found { match stmt.kind { - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => { + StmtKind::Expr(expr) | StmtKind::Semi(expr) => { self.search_slow_extend_filling(expr); self.search_slow_resize_filling(expr); }, @@ -305,7 +299,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { fn visit_block(&mut self, block: &'tcx Block<'_>) { if self.initialization_found { - if let Some(ref s) = block.stmts.get(0) { + if let Some(s) = block.stmts.get(0) { self.visit_stmt(s) } diff --git a/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs b/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs index 276a933881..65790375c7 100644 --- a/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs +++ b/src/tools/clippy/clippy_lints/src/stable_sort_primitive.rs @@ -1,7 +1,6 @@ -use crate::utils::{is_slice_of_primitives, span_lint_and_then, sugg::Sugg}; - +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{is_slice_of_primitives, sugg::Sugg}; use if_chain::if_chain; - use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 31dd596547..9d91b53e1b 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -1,3 +1,9 @@ +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg}; +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 if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -7,14 +13,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; use rustc_span::sym; -use if_chain::if_chain; - -use crate::utils::SpanlessEq; -use crate::utils::{ - get_parent_expr, is_allowed, is_type_diagnostic_item, match_function_call, method_calls, paths, span_lint, - span_lint_and_help, span_lint_and_sugg, -}; - declare_clippy_lint! { /// **What it does:** Checks for string appends of the form `x = x + y` (without /// `let`!). @@ -121,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd { Spanned { node: BinOpKind::Add, .. }, - ref left, + left, _, ) = e.kind { @@ -129,7 +127,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd { if !is_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) { let parent = get_parent_expr(cx, e); if let Some(p) = parent { - if let ExprKind::Assign(ref target, _, _) = p.kind { + if let ExprKind::Assign(target, _, _) = p.kind { // avoid duplicate matches if SpanlessEq::new(cx).eq_expr(target, left) { return; @@ -144,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd { "you added something to a string. Consider using `String::push_str()` instead", ); } - } else if let ExprKind::Assign(ref target, ref src, _) = e.kind { + } else if let ExprKind::Assign(target, src, _) = e.kind { if is_string(cx, target) && is_add(cx, src, target) { span_lint( cx, @@ -168,10 +166,10 @@ fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool { Spanned { node: BinOpKind::Add, .. }, - ref left, + left, _, ) => SpanlessEq::new(cx).eq_expr(target, left), - ExprKind::Block(ref block, _) => { + ExprKind::Block(block, _) => { block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target)) }, _ => false, @@ -205,7 +203,6 @@ declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - use crate::utils::{snippet, snippet_with_applicability}; use rustc_ast::LitKind; if_chain! { @@ -213,8 +210,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { if let Some(args) = match_function_call(cx, e, &paths::STR_FROM_UTF8); // Find string::as_bytes - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref args) = args[0].kind; - if let ExprKind::Index(ref left, ref right) = args.kind; + if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind; + if let ExprKind::Index(left, right) = args.kind; let (method_names, expressions, _) = method_calls(left, 1); if method_names.len() == 1; if expressions.len() == 1; @@ -287,6 +284,35 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { } } } + + if_chain! { + if let ExprKind::MethodCall(path, _, [recv], _) = &e.kind; + if path.ident.name == sym!(into_bytes); + if let ExprKind::MethodCall(path, _, [recv], _) = &recv.kind; + if matches!(&*path.ident.name.as_str(), "to_owned" | "to_string"); + if let ExprKind::Lit(lit) = &recv.kind; + if let LitKind::Str(lit_content, _) = &lit.node; + + if lit_content.as_str().is_ascii(); + if lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT; + if !recv.span.from_expansion(); + then { + let mut applicability = Applicability::MachineApplicable; + + span_lint_and_sugg( + cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `into_bytes()` on a string literal", + "consider using a byte string literal instead", + format!( + "b{}.to_vec()", + snippet_with_applicability(cx, recv.span, r#""..""#, &mut applicability) + ), + applicability, + ); + } + } } } diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index 9acc47deb0..4272935bc3 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -1,5 +1,6 @@ -use crate::utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter}; -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; use core::ops::{Add, AddAssign}; use if_chain::if_chain; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, StmtKind}; @@ -194,7 +195,7 @@ fn attempt_to_emit_no_difference_lint( i: usize, expected_loc: IdentLocation, ) { - if let Some(binop) = binops.get(i).cloned() { + if let Some(binop) = binops.get(i).copied() { // We need to try and figure out which identifier we should // suggest using instead. Since there could be multiple // replacement candidates in a given expression, and we're @@ -224,7 +225,7 @@ fn attempt_to_emit_no_difference_lint( emit_suggestion( cx, binop.span, - replace_left_sugg(cx, &binop, &sugg, &mut applicability), + replace_left_sugg(cx, binop, &sugg, &mut applicability), applicability, ); return; @@ -246,7 +247,7 @@ fn attempt_to_emit_no_difference_lint( emit_suggestion( cx, binop.span, - replace_right_sugg(cx, &binop, &sugg, &mut applicability), + replace_right_sugg(cx, binop, &sugg, &mut applicability), applicability, ); return; @@ -275,8 +276,8 @@ fn ident_swap_sugg( location: IdentLocation, applicability: &mut Applicability, ) -> Option<String> { - let left_ident = get_ident(&binop.left, location)?; - let right_ident = get_ident(&binop.right, location)?; + let left_ident = get_ident(binop.left, location)?; + let right_ident = get_ident(binop.right, location)?; let sugg = match ( paired_identifiers.contains(&left_ident), @@ -292,8 +293,7 @@ fn ident_swap_sugg( // ends up duplicating a clause, the `logic_bug` lint // should catch it. - let right_suggestion = - suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?; + let right_suggestion = suggestion_with_swapped_ident(cx, binop.right, location, left_ident, applicability)?; replace_right_sugg(cx, binop, &right_suggestion, applicability) }, @@ -301,15 +301,14 @@ fn ident_swap_sugg( // We haven't seen a pair involving the left one, so // it's probably what is wanted. - let right_suggestion = - suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?; + let right_suggestion = suggestion_with_swapped_ident(cx, binop.right, location, left_ident, applicability)?; replace_right_sugg(cx, binop, &right_suggestion, applicability) }, (true, false) => { // We haven't seen a pair involving the right one, so // it's probably what is wanted. - let left_suggestion = suggestion_with_swapped_ident(cx, &binop.left, location, right_ident, applicability)?; + let left_suggestion = suggestion_with_swapped_ident(cx, binop.left, location, right_ident, applicability)?; replace_left_sugg(cx, binop, &left_suggestion, applicability) }, diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index 0b7d08cb16..512abde11a 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -1,4 +1,5 @@ -use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{get_trait_def_id, paths, trait_ref_of_method}; use if_chain::if_chain; use rustc_hir as hir; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; @@ -67,14 +68,13 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { // 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! { - let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id); 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 mut visitor = BinaryExprVisitor { nb_binops: 0 }; - 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; @@ -158,7 +158,7 @@ fn check_binop( expected_ops: &[hir::BinOpKind], ) -> Option<&'static str> { let mut trait_ids = vec![]; - let [krate, module] = crate::utils::paths::OPS_MODULE; + let [krate, module] = paths::OPS_MODULE; for &t in traits { let path = [krate, module, t]; diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index 9d8a0c2483..19967e2c97 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -1,7 +1,8 @@ -use crate::utils::sugg::Sugg; -use crate::utils::{ - differing_macro_contexts, eq_expr_value, is_type_diagnostic_item, snippet_with_applicability, span_lint_and_then, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{differing_macro_contexts, eq_expr_value}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind}; @@ -77,26 +78,26 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { for w in block.stmts.windows(3) { if_chain! { // let t = foo(); - if let StmtKind::Local(ref tmp) = w[0].kind; - if let Some(ref tmp_init) = tmp.init; + if let StmtKind::Local(tmp) = w[0].kind; + if let Some(tmp_init) = tmp.init; if let PatKind::Binding(.., ident, None) = tmp.pat.kind; // foo() = bar(); - if let StmtKind::Semi(ref first) = w[1].kind; - if let ExprKind::Assign(ref lhs1, ref rhs1, _) = first.kind; + if let StmtKind::Semi(first) = w[1].kind; + if let ExprKind::Assign(lhs1, rhs1, _) = first.kind; // bar() = t; - if let StmtKind::Semi(ref second) = w[2].kind; - if let ExprKind::Assign(ref lhs2, ref rhs2, _) = second.kind; - if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.kind; + if let StmtKind::Semi(second) = w[2].kind; + if let ExprKind::Assign(lhs2, rhs2, _) = second.kind; + if let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind; if rhs2.segments.len() == 1; if ident.name == rhs2.segments[0].ident.name; if eq_expr_value(cx, tmp_init, lhs1); if eq_expr_value(cx, rhs1, lhs2); then { - if let ExprKind::Field(ref lhs1, _) = lhs1.kind { - if let ExprKind::Field(ref lhs2, _) = lhs2.kind { + if let ExprKind::Field(lhs1, _) = lhs1.kind { + if let ExprKind::Field(lhs2, _) = lhs2.kind { if lhs1.hir_id.owner == lhs2.hir_id.owner { return; } @@ -191,8 +192,8 @@ enum Slice<'a> { /// Checks if both expressions are index operations into "slice-like" types. fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<'_>) -> Slice<'a> { - if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.kind { - if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.kind { + if let ExprKind::Index(lhs1, idx1) = lhs1.kind { + if let ExprKind::Index(lhs2, idx2) = lhs2.kind { if eq_expr_value(cx, lhs1, lhs2) { let ty = cx.typeck_results().expr_ty(lhs1).peel_refs(); @@ -216,11 +217,11 @@ fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr< fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) { for w in block.stmts.windows(2) { if_chain! { - if let StmtKind::Semi(ref first) = w[0].kind; - if let StmtKind::Semi(ref second) = w[1].kind; + if let StmtKind::Semi(first) = w[0].kind; + if let StmtKind::Semi(second) = w[1].kind; if !differing_macro_contexts(first.span, second.span); - if let ExprKind::Assign(ref lhs0, ref rhs0, _) = first.kind; - if let ExprKind::Assign(ref lhs1, ref rhs1, _) = second.kind; + if let ExprKind::Assign(lhs0, rhs0, _) = first.kind; + if let ExprKind::Assign(lhs1, rhs1, _) = second.kind; if eq_expr_value(cx, lhs0, rhs1); if eq_expr_value(cx, lhs1, rhs0); then { diff --git a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs index 74ccd9235d..e2c144709f 100644 --- a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs +++ b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -86,7 +86,7 @@ impl TabsInDocComments { impl EarlyLintPass for TabsInDocComments { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attribute: &ast::Attribute) { - Self::warn_if_tabs_in_doc(cx, &attribute); + Self::warn_if_tabs_in_doc(cx, attribute); } } @@ -104,30 +104,32 @@ fn get_chunks_of_tabs(the_str: &str) -> Vec<(u32, u32)> { // tracker to decide if the last group of tabs is not closed by a non-tab character let mut is_active = false; - let chars_array: Vec<_> = the_str.chars().collect(); + // Note that we specifically need the char _byte_ indices here, not the positional indexes + // within the char array to deal with multi-byte characters properly. `char_indices` does + // exactly that. It provides an iterator over tuples of the form `(byte position, char)`. + let char_indices: Vec<_> = the_str.char_indices().collect(); - if chars_array == vec!['\t'] { + if let [(_, '\t')] = char_indices.as_slice() { return vec![(0, 1)]; } - for (index, arr) in chars_array.windows(2).enumerate() { - let index = u32::try_from(index).expect(line_length_way_to_long); - match arr { - ['\t', '\t'] => { + for entry in char_indices.windows(2) { + match entry { + [(_, '\t'), (_, '\t')] => { // either string starts with double tab, then we have to set it active, // otherwise is_active is true anyway is_active = true; }, - [_, '\t'] => { + [(_, _), (index_b, '\t')] => { // as ['\t', '\t'] is excluded, this has to be a start of a tab group, // set indices accordingly is_active = true; - current_start = index + 1; + current_start = u32::try_from(*index_b).unwrap(); }, - ['\t', _] => { + [(_, '\t'), (index_b, _)] => { // this now has to be an end of the group, hence we have to push a new tuple is_active = false; - spans.push((current_start, index + 1)); + spans.push((current_start, u32::try_from(*index_b).unwrap())); }, _ => {}, } @@ -137,7 +139,7 @@ fn get_chunks_of_tabs(the_str: &str) -> Vec<(u32, u32)> { if is_active { spans.push(( current_start, - u32::try_from(the_str.chars().count()).expect(line_length_way_to_long), + u32::try_from(char_indices.last().unwrap().0 + 1).expect(line_length_way_to_long), )); } @@ -148,6 +150,13 @@ fn get_chunks_of_tabs(the_str: &str) -> Vec<(u32, u32)> { mod tests_for_get_chunks_of_tabs { use super::get_chunks_of_tabs; + #[test] + fn test_unicode_han_string() { + let res = get_chunks_of_tabs(" \u{4f4d}\t"); + + assert_eq!(res, vec![(4, 5)]); + } + #[test] fn test_empty_string() { let res = get_chunks_of_tabs(""); diff --git a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs index fb89186636..8ef25dc816 100644 --- a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs +++ b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_adjusted, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_adjusted; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs index eeda39bfa2..c66a596c78 100644 --- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs @@ -1,4 +1,6 @@ -use crate::utils::{match_def_path, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::match_def_path; +use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs index 84ec2aa18a..4fb297ac6c 100644 --- a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs +++ b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_diagnostic_assoc_item, match_def_path, path_to_local_id, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_diag_trait_item, match_def_path, path_to_local_id, paths}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -91,10 +92,10 @@ impl LateLintPass<'_> for ToStringInDisplay { if_chain! { if self.in_display_impl; if let Some(self_hir_id) = self.self_hir_id; - if let ExprKind::MethodCall(ref path, _, args, _) = expr.kind; + if let ExprKind::MethodCall(path, _, args, _) = expr.kind; if path.ident.name == sym!(to_string); if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if is_diagnostic_assoc_item(cx, expr_def_id, sym::ToString); + if is_diag_trait_item(cx, expr_def_id, sym::ToString); if path_to_local_id(&args[0], self_hir_id); then { span_lint( diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index daff5f81e8..b0589b0512 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -1,4 +1,6 @@ -use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_help, SpanlessHash}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::{in_macro, SpanlessHash}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; @@ -105,7 +107,7 @@ impl TraitBounds { if let WherePredicate::BoundPredicate(ref p) = bound; if p.bounds.len() as u64 <= self.max_trait_bounds; if !in_macro(p.span); - let h = hash(&p.bounded_ty); + let h = hash(p.bounded_ty); if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>()); then { @@ -168,7 +170,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { if_chain! { if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate; if !in_macro(bound_predicate.span); - if let TyKind::Path(QPath::Resolved(_, Path { ref segments, .. })) = bound_predicate.bounded_ty.kind; + if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind; if let Some(segment) = segments.first(); if let Some(trait_resolutions_direct) = map.get(&segment.ident); then { diff --git a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs index ce87defaa9..25d0543c86 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs @@ -1,5 +1,5 @@ use super::CROSSPOINTER_TRANSMUTE; -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index c1870f5208..569113910c 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -12,7 +12,7 @@ mod useless_transmute; mod utils; mod wrong_transmute; -use crate::utils::{in_constant, match_def_path, paths}; +use clippy_utils::{in_constant, match_def_path, paths}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -274,7 +274,7 @@ declare_clippy_lint! { /// let _ = unsafe{ &*(&1u32 as *const u32 as *const f32) }; /// ``` pub TRANSMUTE_PTR_TO_PTR, - complexity, + pedantic, "transmutes from a pointer to a pointer / a reference to a reference" } @@ -325,7 +325,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { #[allow(clippy::similar_names, clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Call(ref path_expr, ref args) = e.kind; + if let ExprKind::Call(path_expr, args) = e.kind; if let ExprKind::Path(ref qpath) = path_expr.kind; if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::TRANSMUTE); diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs index 562d880e39..3aa3c393ba 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -1,5 +1,6 @@ use super::TRANSMUTE_FLOAT_TO_INT; -use crate::utils::{span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; use if_chain::if_chain; use rustc_ast as ast; use rustc_errors::Applicability; @@ -29,16 +30,16 @@ pub(super) fn check<'tcx>( let mut arg = sugg::Sugg::hir(cx, expr, ".."); if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind { - expr = &inner_expr; + expr = inner_expr; } if_chain! { // if the expression is a float literal and it is unsuffixed then // add a suffix so the suggestion is valid and unambiguous - let op = format!("{}{}", arg, float_ty.name_str()).into(); if let ExprKind::Lit(lit) = &expr.kind; if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node; then { + let op = format!("{}{}", arg, float_ty.name_str()).into(); match arg { sugg::Sugg::MaybeParen(_) => arg = sugg::Sugg::MaybeParen(op), _ => arg = sugg::Sugg::NonParen(op) diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs index 5b609f906a..cc0a5643e2 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs @@ -1,5 +1,6 @@ use super::TRANSMUTE_INT_TO_BOOL; -use crate::utils::{span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs index 29d2450618..8f884e6a4a 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -1,5 +1,6 @@ use super::TRANSMUTE_INT_TO_CHAR; -use crate::utils::{span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs index f83fba8966..2b6a4cff81 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -1,5 +1,6 @@ use super::TRANSMUTE_INT_TO_FLOAT; -use crate::utils::{span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index f4e60a3020..7b646bfc0c 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -1,5 +1,6 @@ use super::TRANSMUTE_PTR_TO_PTR; -use crate::utils::{span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index f5dbbbe33b..f14eef9364 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -1,6 +1,7 @@ use super::utils::get_type_snippet; use super::TRANSMUTE_PTR_TO_REF; -use crate::utils::{span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability, QPath}; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 01b00bb0a2..d105e37abf 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -1,5 +1,7 @@ use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR}; -use crate::utils::{snippet, span_lint_and_sugg, span_lint_and_then, sugg}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::snippet; +use clippy_utils::sugg; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index dea896622f..e2c6d130f3 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -1,6 +1,7 @@ use super::utils::can_be_expressed_as_pointer_cast; use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS; -use crate::utils::{span_lint_and_then, sugg}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs index 503c5e0ff3..de9277e016 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs @@ -1,6 +1,7 @@ use super::utils::is_layout_incompatible; use super::UNSOUND_COLLECTION_TRANSMUTE; -use crate::utils::{match_def_path, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{match_def_path, paths}; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs index 83441514af..445bcf60fa 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs @@ -1,5 +1,6 @@ use super::USELESS_TRANSMUTE; -use crate::utils::{span_lint, span_lint_and_then, sugg}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 55008d8ec3..f359b606e4 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -1,4 +1,6 @@ -use crate::utils::{is_normalizable, last_path_segment, snippet}; +use clippy_utils::last_path_segment; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_normalizable; use if_chain::if_chain; use rustc_hir::{Expr, GenericArg, QPath, TyKind}; use rustc_lint::LateContext; @@ -14,7 +16,7 @@ use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; pub(super) fn get_type_snippet(cx: &LateContext<'_>, path: &QPath<'_>, to_ref_ty: Ty<'_>) -> String { let seg = last_path_segment(path); if_chain! { - if let Some(ref params) = seg.args; + if let Some(params) = seg.args; if !params.parenthesized; if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), diff --git a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs index d6d77f2c83..2118f3d695 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs @@ -1,5 +1,5 @@ use super::WRONG_TRANSMUTE; -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs index 2ba2b646f0..888ecab104 100644 --- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs @@ -1,5 +1,6 @@ use crate::consts::{constant_context, Constant}; -use crate::utils::{match_qpath, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_expr_path_def_path, paths}; use if_chain::if_chain; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; @@ -36,18 +37,15 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull { } if_chain! { - if let ExprKind::Call(ref func, ref args) = expr.kind; - if let ExprKind::Path(ref path) = func.kind; - if match_qpath(path, &paths::STD_MEM_TRANSMUTE); - if args.len() == 1; + if let ExprKind::Call(func, [arg]) = expr.kind; + if is_expr_path_def_path(cx, func, &paths::TRANSMUTE); then { - // Catching transmute over constants that resolve to `null`. let mut const_eval_context = constant_context(cx, cx.typeck_results()); if_chain! { - if let ExprKind::Path(ref _qpath) = args[0].kind; - let x = const_eval_context.expr(&args[0]); + if let ExprKind::Path(ref _qpath) = arg.kind; + let x = const_eval_context.expr(arg); if let Some(Constant::RawPtr(0)) = x; then { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG) @@ -57,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull { // Catching: // `std::mem::transmute(0 as *const i32)` if_chain! { - if let ExprKind::Cast(ref inner_expr, ref _cast_ty) = args[0].kind; + if let ExprKind::Cast(inner_expr, _cast_ty) = arg.kind; if let ExprKind::Lit(ref lit) = inner_expr.kind; if let LitKind::Int(0, _) = lit.node; then { @@ -68,10 +66,8 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull { // Catching: // `std::mem::transmute(std::ptr::null::<i32>())` if_chain! { - if let ExprKind::Call(ref func1, ref args1) = args[0].kind; - if let ExprKind::Path(ref path1) = func1.kind; - if match_qpath(path1, &paths::STD_PTR_NULL); - if args1.is_empty(); + if let ExprKind::Call(func1, []) = arg.kind; + if is_expr_path_def_path(cx, func1, &paths::PTR_NULL); then { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG) } diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs index 73e3a04aec..ebb39ea487 100644 --- a/src/tools/clippy/clippy_lints/src/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/try_err.rs @@ -1,9 +1,10 @@ -use crate::utils::{ - differing_macro_contexts, in_macro, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet, - snippet_with_macro_callsite, span_lint_and_sugg, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{snippet, snippet_with_macro_callsite}; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{differing_macro_contexts, get_parent_expr, in_macro, is_lang_ctor, match_def_path, paths}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::LangItem::ResultErr; use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -60,15 +61,15 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { // }; if_chain! { if !in_external_macro(cx.tcx.sess, expr.span); - if let ExprKind::Match(ref match_arg, _, MatchSource::TryDesugar) = expr.kind; - if let ExprKind::Call(ref match_fun, ref try_args) = match_arg.kind; + if let ExprKind::Match(match_arg, _, MatchSource::TryDesugar) = expr.kind; + if let ExprKind::Call(match_fun, try_args) = match_arg.kind; if let ExprKind::Path(ref match_fun_path) = match_fun.kind; if matches!(match_fun_path, QPath::LangItem(LangItem::TryIntoResult, _)); - if let Some(ref try_arg) = try_args.get(0); - if let ExprKind::Call(ref err_fun, ref err_args) = try_arg.kind; - if let Some(ref err_arg) = err_args.get(0); + if let Some(try_arg) = try_args.get(0); + if let ExprKind::Call(err_fun, err_args) = try_arg.kind; + if let Some(err_arg) = err_args.get(0); if let ExprKind::Path(ref err_fun_path) = err_fun.kind; - if match_qpath(err_fun_path, &paths::RESULT_ERR); + if is_lang_ctor(cx, err_fun_path, ResultErr); if let Some(return_ty) = find_return_type(cx, &expr.kind); then { let prefix; @@ -101,10 +102,15 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { } else { snippet(cx, err_arg.span, "_") }; + let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) { + "" // already returns + } else { + "return " + }; let suggestion = if err_ty == expr_err_ty { - format!("return {}{}{}", prefix, origin_snippet, suffix) + format!("{}{}{}{}", ret_prefix, prefix, origin_snippet, suffix) } else { - format!("return {}{}.into(){}", prefix, origin_snippet, suffix) + format!("{}{}{}.into(){}", ret_prefix, prefix, origin_snippet, suffix) }; span_lint_and_sugg( @@ -123,9 +129,9 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { /// Finds function return type by examining return expressions in match arms. fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> { - if let ExprKind::Match(_, ref arms, MatchSource::TryDesugar) = expr { + if let ExprKind::Match(_, arms, MatchSource::TryDesugar) = expr { for arm in arms.iter() { - if let ExprKind::Ret(Some(ref ret)) = arm.body.kind { + if let ExprKind::Ret(Some(ret)) = arm.body.kind { return Some(cx.typeck_results().expr_ty(ret)); } } @@ -138,9 +144,8 @@ fn result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t if_chain! { if let ty::Adt(_, subst) = ty.kind(); if is_type_diagnostic_item(cx, ty, sym::result_type); - let err_ty = subst.type_at(1); then { - Some(err_ty) + Some(subst.type_at(1)) } else { None } @@ -156,10 +161,8 @@ fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option< if let ty::Adt(ready_def, ready_subst) = ready_ty.kind(); if cx.tcx.is_diagnostic_item(sym::result_type, ready_def.did); - let err_ty = ready_subst.type_at(1); - then { - Some(err_ty) + Some(ready_subst.type_at(1)) } else { None } @@ -179,10 +182,8 @@ fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> if let ty::Adt(some_def, some_subst) = some_ty.kind(); if cx.tcx.is_diagnostic_item(sym::result_type, some_def.did); - let err_ty = some_subst.type_at(1); - then { - Some(err_ty) + Some(some_subst.type_at(1)) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 81090040d9..bdeff035e5 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -1,3 +1,7 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::{match_def_path, paths}; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath, @@ -5,10 +9,6 @@ use rustc_hir::{ }; use rustc_lint::LateContext; -use if_chain::if_chain; - -use crate::utils::{match_path, paths, snippet, span_lint_and_sugg}; - use super::BORROWED_BOX; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, mut_ty: &MutTy<'_>) -> bool { @@ -19,16 +19,16 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m if_chain! { if let Some(def_id) = def.opt_def_id(); if Some(def_id) == cx.tcx.lang_items().owned_box(); - if let QPath::Resolved(None, ref path) = *qpath; + if let QPath::Resolved(None, path) = *qpath; if let [ref bx] = *path.segments; - if let Some(ref params) = bx.args; + if let Some(params) = bx.args; if !params.parenthesized; if let Some(inner) = params.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, }); then { - if is_any_trait(inner) { + if is_any_trait(cx, inner) { // Ignore `Box<Any>` types; see issue #1884 for details. return false; } @@ -84,13 +84,14 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m } // Returns true if given type is `Any` trait. -fn is_any_trait(t: &hir::Ty<'_>) -> bool { +fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool { if_chain! { - if let TyKind::TraitObject(ref traits, ..) = t.kind; + if let TyKind::TraitObject(traits, ..) = t.kind; if !traits.is_empty(); + if let Some(trait_did) = traits[0].trait_ref.trait_def_id(); // Only Send/Sync can be used as additional traits, so it is enough to // check only the first trait. - if match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT); + if match_def_path(cx, trait_did, &paths::ANY_TRAIT); then { return true; } diff --git a/src/tools/clippy/clippy_lints/src/types/box_vec.rs b/src/tools/clippy/clippy_lints/src/types/box_vec.rs index 6aa98e435e..d8b1953457 100644 --- a/src/tools/clippy/clippy_lints/src/types/box_vec.rs +++ b/src/tools/clippy/clippy_lints/src/types/box_vec.rs @@ -1,9 +1,9 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_ty_param_diagnostic_item; use rustc_hir::{self as hir, def_id::DefId, QPath}; use rustc_lint::LateContext; use rustc_span::symbol::sym; -use crate::utils::{is_ty_param_diagnostic_item, span_lint_and_help}; - use super::BOX_VEC; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/types/linked_list.rs b/src/tools/clippy/clippy_lints/src/types/linked_list.rs index 47eb4ede4e..a9fbe7aa31 100644 --- a/src/tools/clippy/clippy_lints/src/types/linked_list.rs +++ b/src/tools/clippy/clippy_lints/src/types/linked_list.rs @@ -1,8 +1,8 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{match_def_path, paths}; use rustc_hir::{self as hir, def_id::DefId}; use rustc_lint::LateContext; -use crate::utils::{match_def_path, paths, span_lint_and_help}; - use super::LINKEDLIST; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, def_id: DefId) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 4a1a608e8a..d9b47a699d 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -1,46 +1,22 @@ -#![allow(rustc::default_hash_types)] - mod borrowed_box; mod box_vec; mod linked_list; mod option_option; mod rc_buffer; mod redundant_allocation; +mod type_complexity; mod utils; mod vec_box; -use std::borrow::Cow; -use std::cmp::Ordering; -use std::collections::BTreeMap; - -use if_chain::if_chain; -use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::FnKind; use rustc_hir::{ - BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem, - ImplItemKind, Item, ItemKind, Local, MatchSource, MutTy, Node, QPath, Stmt, StmtKind, TraitFn, TraitItem, + Body, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem, TraitItemKind, TyKind, }; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::hir::map::Map; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, IntTy, Ty, TyS, TypeckResults, UintTy}; -use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; -use rustc_span::hygiene::{ExpnKind, MacroKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; -use rustc_span::symbol::sym; -use rustc_target::abi::LayoutOf; -use rustc_target::spec::abi::Abi; -use rustc_typeck::hir_ty_to_ty; - -use crate::consts::{constant, Constant}; -use crate::utils::paths; -use crate::utils::{ - clip, comparisons, differing_macro_contexts, higher, indent_of, int_bits, is_isize_or_usize, - is_type_diagnostic_item, match_path, multispan_sugg, reindent_multiline, sext, snippet, snippet_opt, - snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_then, unsext, -}; declare_clippy_lint! { /// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code. @@ -253,55 +229,119 @@ declare_clippy_lint! { "shared ownership of a buffer type" } +declare_clippy_lint! { + /// **What it does:** Checks for types used in structs, parameters and `let` + /// declarations above a certain complexity threshold. + /// + /// **Why is this bad?** Too complex types make the code less readable. Consider + /// using a `type` definition to simplify them. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// # use std::rc::Rc; + /// struct Foo { + /// inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>, + /// } + /// ``` + pub TYPE_COMPLEXITY, + complexity, + "usage of very complex types that might be better factored into `type` definitions" +} + 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]); +impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, TYPE_COMPLEXITY]); impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) { - // Skip trait implementations; see issue #605. - if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) { - if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { - return; - } + let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) + { + matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) + } else { + false + }; + + self.check_fn_decl( + cx, + decl, + CheckTyContext { + is_in_trait_impl, + ..CheckTyContext::default() + }, + ); + } + + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + match item.kind { + ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(cx, ty, CheckTyContext::default()), + // functions, enums, structs, impls and traits are covered + _ => (), } + } - self.check_fn_decl(cx, decl); + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { + match item.kind { + ImplItemKind::Const(ty, _) | ImplItemKind::TyAlias(ty) => self.check_ty( + cx, + ty, + CheckTyContext { + is_in_trait_impl: true, + ..CheckTyContext::default() + }, + ), + // methods are covered by check_fn + ImplItemKind::Fn(..) => (), + } } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { - self.check_ty(cx, &field.ty, false); + self.check_ty(cx, field.ty, CheckTyContext::default()); } fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) { match item.kind { - TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_ty(cx, ty, false), - TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, &sig.decl), - _ => (), + TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { + self.check_ty(cx, ty, CheckTyContext::default()) + }, + TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, CheckTyContext::default()), + TraitItemKind::Type(..) => (), } } fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { - if let Some(ref ty) = local.ty { - self.check_ty(cx, ty, true); + if let Some(ty) = local.ty { + self.check_ty( + cx, + ty, + CheckTyContext { + is_local: true, + ..CheckTyContext::default() + }, + ); } } } impl Types { - pub fn new(vec_box_size_threshold: u64) -> Self { - Self { vec_box_size_threshold } + pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64) -> Self { + Self { + vec_box_size_threshold, + type_complexity_threshold, + } } - fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>) { + fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) { for input in decl.inputs { - self.check_ty(cx, input, false); + self.check_ty(cx, input, context); } - if let FnRetTy::Return(ref ty) = decl.output { - self.check_ty(cx, ty, false); + if let FnRetTy::Return(ty) = decl.output { + self.check_ty(cx, ty, context); } } @@ -309,12 +349,22 @@ impl Types { /// lint found. /// /// The parameter `is_local` distinguishes the context of the type. - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, is_local: bool) { + fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) { if hir_ty.span.from_expansion() { return; } + + if !context.is_nested_call && type_complexity::check(cx, hir_ty, self.type_complexity_threshold) { + return; + } + + // Skip trait implementations; see issue #605. + if context.is_in_trait_impl { + return; + } + match hir_ty.kind { - TyKind::Path(ref qpath) if !is_local => { + TyKind::Path(ref qpath) if !context.is_local => { let hir_id = hir_ty.hir_id; let res = cx.qpath_res(qpath, hir_id); if let Some(def_id) = res.opt_def_id() { @@ -331,8 +381,9 @@ impl Types { } } match *qpath { - QPath::Resolved(Some(ref ty), ref p) => { - self.check_ty(cx, ty, is_local); + QPath::Resolved(Some(ty), p) => { + context.is_nested_call = true; + self.check_ty(cx, ty, context); for ty in p.segments.iter().flat_map(|seg| { seg.args .as_ref() @@ -342,10 +393,11 @@ impl Types { _ => None, }) }) { - self.check_ty(cx, ty, is_local); + self.check_ty(cx, ty, context); } }, - QPath::Resolved(None, ref p) => { + QPath::Resolved(None, p) => { + context.is_nested_call = true; for ty in p.segments.iter().flat_map(|seg| { seg.args .as_ref() @@ -355,17 +407,18 @@ impl Types { _ => None, }) }) { - self.check_ty(cx, ty, is_local); + self.check_ty(cx, ty, context); } }, - QPath::TypeRelative(ref ty, ref seg) => { - self.check_ty(cx, ty, is_local); - if let Some(ref params) = seg.args { + QPath::TypeRelative(ty, seg) => { + context.is_nested_call = true; + self.check_ty(cx, ty, context); + if let Some(params) = seg.args { for ty in params.args.iter().filter_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, }) { - self.check_ty(cx, ty, is_local); + self.check_ty(cx, ty, context); } } }, @@ -373,1116 +426,19 @@ impl Types { } }, TyKind::Rptr(ref lt, ref mut_ty) => { + context.is_nested_call = true; if !borrowed_box::check(cx, hir_ty, lt, mut_ty) { - self.check_ty(cx, &mut_ty.ty, is_local); + self.check_ty(cx, mut_ty.ty, context); } }, - TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => { - self.check_ty(cx, ty, is_local) + TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(MutTy { ty, .. }) => { + context.is_nested_call = true; + self.check_ty(cx, ty, context) }, TyKind::Tup(tys) => { + context.is_nested_call = true; for ty in tys { - self.check_ty(cx, ty, is_local); - } - }, - _ => {}, - } - } -} - -declare_clippy_lint! { - /// **What it does:** Checks for binding a unit value. - /// - /// **Why is this bad?** A unit value cannot usefully be used anywhere. So - /// binding one is kind of pointless. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// let x = { - /// 1; - /// }; - /// ``` - pub LET_UNIT_VALUE, - pedantic, - "creating a `let` binding to a value of unit type, which usually can't be used afterwards" -} - -declare_lint_pass!(LetUnitValue => [LET_UNIT_VALUE]); - -impl<'tcx> LateLintPass<'tcx> for LetUnitValue { - fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if let StmtKind::Local(ref local) = stmt.kind { - if is_unit(cx.typeck_results().pat_ty(&local.pat)) { - if in_external_macro(cx.sess(), stmt.span) || local.pat.span.from_expansion() { - return; - } - if higher::is_from_for_desugar(local) { - return; - } - span_lint_and_then( - cx, - LET_UNIT_VALUE, - stmt.span, - "this let-binding has unit value", - |diag| { - if let Some(expr) = &local.init { - let snip = snippet_with_macro_callsite(cx, expr.span, "()"); - diag.span_suggestion( - stmt.span, - "omit the `let` binding", - format!("{};", snip), - Applicability::MachineApplicable, // snippet - ); - } - }, - ); - } - } - } -} - -declare_clippy_lint! { - /// **What it does:** Checks for comparisons to unit. This includes all binary - /// comparisons (like `==` and `<`) and asserts. - /// - /// **Why is this bad?** Unit is always equal to itself, and thus is just a - /// clumsily written constant. Mostly this happens when someone accidentally - /// adds semicolons at the end of the operands. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// # fn foo() {}; - /// # fn bar() {}; - /// # fn baz() {}; - /// if { - /// foo(); - /// } == { - /// bar(); - /// } { - /// baz(); - /// } - /// ``` - /// is equal to - /// ```rust - /// # fn foo() {}; - /// # fn bar() {}; - /// # fn baz() {}; - /// { - /// foo(); - /// bar(); - /// baz(); - /// } - /// ``` - /// - /// For asserts: - /// ```rust - /// # fn foo() {}; - /// # fn bar() {}; - /// assert_eq!({ foo(); }, { bar(); }); - /// ``` - /// will always succeed - pub UNIT_CMP, - correctness, - "comparing unit values" -} - -declare_lint_pass!(UnitCmp => [UNIT_CMP]); - -impl<'tcx> LateLintPass<'tcx> for UnitCmp { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if expr.span.from_expansion() { - if let Some(callee) = expr.span.source_callee() { - if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind { - if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind { - let op = cmp.node; - if op.is_comparison() && is_unit(cx.typeck_results().expr_ty(left)) { - let result = match &*symbol.as_str() { - "assert_eq" | "debug_assert_eq" => "succeed", - "assert_ne" | "debug_assert_ne" => "fail", - _ => return, - }; - span_lint( - cx, - UNIT_CMP, - expr.span, - &format!( - "`{}` of unit values detected. This will always {}", - symbol.as_str(), - result - ), - ); - } - } - } - } - return; - } - if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind { - let op = cmp.node; - if op.is_comparison() && is_unit(cx.typeck_results().expr_ty(left)) { - let result = match op { - BinOpKind::Eq | BinOpKind::Le | BinOpKind::Ge => "true", - _ => "false", - }; - span_lint( - cx, - UNIT_CMP, - expr.span, - &format!( - "{}-comparison of unit values detected. This will always be {}", - op.as_str(), - result - ), - ); - } - } - } -} - -declare_clippy_lint! { - /// **What it does:** Checks for passing a unit value as an argument to a function without using a - /// unit literal (`()`). - /// - /// **Why is this bad?** This is likely the result of an accidental semicolon. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust,ignore - /// foo({ - /// let a = bar(); - /// baz(a); - /// }) - /// ``` - pub UNIT_ARG, - complexity, - "passing unit to a function" -} - -declare_lint_pass!(UnitArg => [UNIT_ARG]); - -impl<'tcx> LateLintPass<'tcx> for UnitArg { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if expr.span.from_expansion() { - return; - } - - // apparently stuff in the desugaring of `?` can trigger this - // so check for that here - // only the calls to `Try::from_error` is marked as desugared, - // so we need to check both the current Expr and its parent. - if is_questionmark_desugar_marked_call(expr) { - return; - } - if_chain! { - let map = &cx.tcx.hir(); - let opt_parent_node = map.find(map.get_parent_node(expr.hir_id)); - if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; - if is_questionmark_desugar_marked_call(parent_expr); - then { - return; - } - } - - match expr.kind { - ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => { - let args_to_recover = args - .iter() - .filter(|arg| { - if is_unit(cx.typeck_results().expr_ty(arg)) && !is_unit_literal(arg) { - !matches!( - &arg.kind, - ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..) - ) - } else { - false - } - }) - .collect::<Vec<_>>(); - if !args_to_recover.is_empty() { - lint_unit_args(cx, expr, &args_to_recover); - } - }, - _ => (), - } - } -} - -fn fmt_stmts_and_call( - cx: &LateContext<'_>, - call_expr: &Expr<'_>, - call_snippet: &str, - args_snippets: &[impl AsRef<str>], - non_empty_block_args_snippets: &[impl AsRef<str>], -) -> String { - let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0); - let call_snippet_with_replacements = args_snippets - .iter() - .fold(call_snippet.to_owned(), |acc, arg| acc.replacen(arg.as_ref(), "()", 1)); - - let mut stmts_and_call = non_empty_block_args_snippets - .iter() - .map(|it| it.as_ref().to_owned()) - .collect::<Vec<_>>(); - stmts_and_call.push(call_snippet_with_replacements); - stmts_and_call = stmts_and_call - .into_iter() - .map(|v| reindent_multiline(v.into(), true, Some(call_expr_indent)).into_owned()) - .collect(); - - let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent))); - // expr is not in a block statement or result expression position, wrap in a block - let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id)); - if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) { - let block_indent = call_expr_indent + 4; - stmts_and_call_snippet = - reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned(); - stmts_and_call_snippet = format!( - "{{\n{}{}\n{}}}", - " ".repeat(block_indent), - &stmts_and_call_snippet, - " ".repeat(call_expr_indent) - ); - } - stmts_and_call_snippet -} - -fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) { - let mut applicability = Applicability::MachineApplicable; - let (singular, plural) = if args_to_recover.len() > 1 { - ("", "s") - } else { - ("a ", "") - }; - span_lint_and_then( - cx, - UNIT_ARG, - expr.span, - &format!("passing {}unit value{} to a function", singular, plural), - |db| { - let mut or = ""; - args_to_recover - .iter() - .filter_map(|arg| { - if_chain! { - if let ExprKind::Block(block, _) = arg.kind; - if block.expr.is_none(); - if let Some(last_stmt) = block.stmts.iter().last(); - if let StmtKind::Semi(last_expr) = last_stmt.kind; - if let Some(snip) = snippet_opt(cx, last_expr.span); - then { - Some(( - last_stmt.span, - snip, - )) - } - else { - None - } - } - }) - .for_each(|(span, sugg)| { - db.span_suggestion( - span, - "remove the semicolon from the last statement in the block", - sugg, - Applicability::MaybeIncorrect, - ); - or = "or "; - applicability = Applicability::MaybeIncorrect; - }); - - let arg_snippets: Vec<String> = args_to_recover - .iter() - .filter_map(|arg| snippet_opt(cx, arg.span)) - .collect(); - let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover - .iter() - .filter(|arg| !is_empty_block(arg)) - .filter_map(|arg| snippet_opt(cx, arg.span)) - .collect(); - - if let Some(call_snippet) = snippet_opt(cx, expr.span) { - let sugg = fmt_stmts_and_call( - cx, - expr, - &call_snippet, - &arg_snippets, - &arg_snippets_without_empty_blocks, - ); - - if arg_snippets_without_empty_blocks.is_empty() { - db.multipart_suggestion( - &format!("use {}unit literal{} instead", singular, plural), - args_to_recover - .iter() - .map(|arg| (arg.span, "()".to_string())) - .collect::<Vec<_>>(), - applicability, - ); - } else { - let plural = arg_snippets_without_empty_blocks.len() > 1; - let empty_or_s = if plural { "s" } else { "" }; - let it_or_them = if plural { "them" } else { "it" }; - db.span_suggestion( - expr.span, - &format!( - "{}move the expression{} in front of the call and replace {} with the unit literal `()`", - or, empty_or_s, it_or_them - ), - sugg, - applicability, - ); - } - } - }, - ); -} - -fn is_empty_block(expr: &Expr<'_>) -> bool { - matches!( - expr.kind, - ExprKind::Block( - Block { - stmts: &[], - expr: None, - .. - }, - _, - ) - ) -} - -fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool { - use rustc_span::hygiene::DesugaringKind; - if let ExprKind::Call(ref callee, _) = expr.kind { - callee.span.is_desugaring(DesugaringKind::QuestionMark) - } else { - false - } -} - -fn is_unit(ty: Ty<'_>) -> bool { - matches!(ty.kind(), ty::Tuple(slice) if slice.is_empty()) -} - -fn is_unit_literal(expr: &Expr<'_>) -> bool { - matches!(expr.kind, ExprKind::Tup(ref slice) if slice.is_empty()) -} - -declare_clippy_lint! { - /// **What it does:** Checks for types used in structs, parameters and `let` - /// declarations above a certain complexity threshold. - /// - /// **Why is this bad?** Too complex types make the code less readable. Consider - /// using a `type` definition to simplify them. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// # use std::rc::Rc; - /// struct Foo { - /// inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>, - /// } - /// ``` - pub TYPE_COMPLEXITY, - complexity, - "usage of very complex types that might be better factored into `type` definitions" -} - -pub struct TypeComplexity { - threshold: u64, -} - -impl TypeComplexity { - #[must_use] - pub fn new(threshold: u64) -> Self { - Self { threshold } - } -} - -impl_lint_pass!(TypeComplexity => [TYPE_COMPLEXITY]); - -impl<'tcx> LateLintPass<'tcx> for TypeComplexity { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - _: FnKind<'tcx>, - decl: &'tcx FnDecl<'_>, - _: &'tcx Body<'_>, - _: Span, - _: HirId, - ) { - self.check_fndecl(cx, decl); - } - - fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::FieldDef<'_>) { - // enum variants are also struct fields now - self.check_type(cx, &field.ty); - } - - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - match item.kind { - ItemKind::Static(ref ty, _, _) | ItemKind::Const(ref ty, _) => self.check_type(cx, ty), - // functions, enums, structs, impls and traits are covered - _ => (), - } - } - - fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - match item.kind { - TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), - TraitItemKind::Fn(FnSig { ref decl, .. }, TraitFn::Required(_)) => self.check_fndecl(cx, decl), - // methods with default impl are covered by check_fn - _ => (), - } - } - - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { - match item.kind { - ImplItemKind::Const(ref ty, _) | ImplItemKind::TyAlias(ref ty) => self.check_type(cx, ty), - // methods are covered by check_fn - _ => (), - } - } - - fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { - if let Some(ref ty) = local.ty { - self.check_type(cx, ty); - } - } -} - -impl<'tcx> TypeComplexity { - fn check_fndecl(&self, cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>) { - for arg in decl.inputs { - self.check_type(cx, arg); - } - if let FnRetTy::Return(ref ty) = decl.output { - self.check_type(cx, ty); - } - } - - fn check_type(&self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) { - if ty.span.from_expansion() { - return; - } - let score = { - let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; - visitor.visit_ty(ty); - visitor.score - }; - - if score > self.threshold { - span_lint( - cx, - TYPE_COMPLEXITY, - ty.span, - "very complex type used. Consider factoring parts into `type` definitions", - ); - } - } -} - -/// Walks a type and assigns a complexity score to it. -struct TypeComplexityVisitor { - /// total complexity score of the type - score: u64, - /// current nesting level - nest: u64, -} - -impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { - type Map = Map<'tcx>; - - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { - let (add_score, sub_nest) = match ty.kind { - // _, &x and *x have only small overhead; don't mess with nesting level - TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0), - - // the "normal" components of a type: named types, arrays/tuples - TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), - - // function types bring a lot of overhead - TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1), - - TyKind::TraitObject(ref param_bounds, ..) => { - let has_lifetime_parameters = param_bounds.iter().any(|bound| { - bound - .bound_generic_params - .iter() - .any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. })) - }); - if has_lifetime_parameters { - // complex trait bounds like A<'a, 'b> - (50 * self.nest, 1) - } else { - // simple trait bounds like A + B - (20 * self.nest, 0) - } - }, - - _ => (0, 0), - }; - self.score += add_score; - self.nest += sub_nest; - walk_ty(self, ty); - self.nest -= sub_nest; - } - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None - } -} - -declare_clippy_lint! { - /// **What it does:** Checks for comparisons where one side of the relation is - /// either the minimum or maximum value for its type and warns if it involves a - /// case that is always true or always false. Only integer and boolean types are - /// checked. - /// - /// **Why is this bad?** An expression like `min <= x` may misleadingly imply - /// that it is possible for `x` to be less than the minimum. Expressions like - /// `max < x` are probably mistakes. - /// - /// **Known problems:** For `usize` the size of the current compile target will - /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such - /// a comparison to detect target pointer width will trigger this lint. One can - /// use `mem::sizeof` and compare its value or conditional compilation - /// attributes - /// like `#[cfg(target_pointer_width = "64")] ..` instead. - /// - /// **Example:** - /// - /// ```rust - /// let vec: Vec<isize> = Vec::new(); - /// if vec.len() <= 0 {} - /// if 100 > i32::MAX {} - /// ``` - pub ABSURD_EXTREME_COMPARISONS, - correctness, - "a comparison with a maximum or minimum value that is always true or false" -} - -declare_lint_pass!(AbsurdExtremeComparisons => [ABSURD_EXTREME_COMPARISONS]); - -enum ExtremeType { - Minimum, - Maximum, -} - -struct ExtremeExpr<'a> { - which: ExtremeType, - expr: &'a Expr<'a>, -} - -enum AbsurdComparisonResult { - AlwaysFalse, - AlwaysTrue, - InequalityImpossible, -} - -fn is_cast_between_fixed_and_target<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { - if let ExprKind::Cast(ref cast_exp, _) = expr.kind { - let precast_ty = cx.typeck_results().expr_ty(cast_exp); - let cast_ty = cx.typeck_results().expr_ty(expr); - - return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty); - } - - false -} - -fn detect_absurd_comparison<'tcx>( - cx: &LateContext<'tcx>, - op: BinOpKind, - lhs: &'tcx Expr<'_>, - rhs: &'tcx Expr<'_>, -) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> { - use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible}; - use crate::types::ExtremeType::{Maximum, Minimum}; - use crate::utils::comparisons::{normalize_comparison, Rel}; - - // absurd comparison only makes sense on primitive types - // primitive types don't implement comparison operators with each other - if cx.typeck_results().expr_ty(lhs) != cx.typeck_results().expr_ty(rhs) { - return None; - } - - // comparisons between fix sized types and target sized types are considered unanalyzable - if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) { - return None; - } - - let (rel, normalized_lhs, normalized_rhs) = normalize_comparison(op, lhs, rhs)?; - - let lx = detect_extreme_expr(cx, normalized_lhs); - let rx = detect_extreme_expr(cx, normalized_rhs); - - Some(match rel { - Rel::Lt => { - match (lx, rx) { - (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, AlwaysFalse), // max < x - (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, AlwaysFalse), // x < min - _ => return None, - } - }, - Rel::Le => { - match (lx, rx) { - (Some(l @ ExtremeExpr { which: Minimum, .. }), _) => (l, AlwaysTrue), // min <= x - (Some(l @ ExtremeExpr { which: Maximum, .. }), _) => (l, InequalityImpossible), // max <= x - (_, Some(r @ ExtremeExpr { which: Minimum, .. })) => (r, InequalityImpossible), // x <= min - (_, Some(r @ ExtremeExpr { which: Maximum, .. })) => (r, AlwaysTrue), // x <= max - _ => return None, - } - }, - Rel::Ne | Rel::Eq => return None, - }) -} - -fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> { - use crate::types::ExtremeType::{Maximum, Minimum}; - - let ty = cx.typeck_results().expr_ty(expr); - - let cv = constant(cx, cx.typeck_results(), expr)?.0; - - let which = match (ty.kind(), cv) { - (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum, - (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => { - Minimum - }, - - (&ty::Bool, Constant::Bool(true)) => Maximum, - (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => { - Maximum - }, - (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::MAX, uty) == i => Maximum, - - _ => return None, - }; - Some(ExtremeExpr { which, expr }) -} - -impl<'tcx> LateLintPass<'tcx> for AbsurdExtremeComparisons { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible}; - use crate::types::ExtremeType::{Maximum, Minimum}; - - if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind { - if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { - if !expr.span.from_expansion() { - let msg = "this comparison involving the minimum or maximum element for this \ - type contains a case that is always true or always false"; - - let conclusion = match result { - AlwaysFalse => "this comparison is always false".to_owned(), - AlwaysTrue => "this comparison is always true".to_owned(), - InequalityImpossible => format!( - "the case where the two sides are not equal never occurs, consider using `{} == {}` \ - instead", - snippet(cx, lhs.span, "lhs"), - snippet(cx, rhs.span, "rhs") - ), - }; - - let help = format!( - "because `{}` is the {} value for this type, {}", - snippet(cx, culprit.expr.span, "x"), - match culprit.which { - Minimum => "minimum", - Maximum => "maximum", - }, - conclusion - ); - - span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help); - } - } - } - } -} - -declare_clippy_lint! { - /// **What it does:** Checks for comparisons where the relation is always either - /// true or false, but where one side has been upcast so that the comparison is - /// necessary. Only integer types are checked. - /// - /// **Why is this bad?** An expression like `let x : u8 = ...; (x as u32) > 300` - /// will mistakenly imply that it is possible for `x` to be outside the range of - /// `u8`. - /// - /// **Known problems:** - /// https://github.com/rust-lang/rust-clippy/issues/886 - /// - /// **Example:** - /// ```rust - /// let x: u8 = 1; - /// (x as u32) > 300; - /// ``` - pub INVALID_UPCAST_COMPARISONS, - pedantic, - "a comparison involving an upcast which is always true or false" -} - -declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]); - -#[derive(Copy, Clone, Debug, Eq)] -enum FullInt { - S(i128), - U(u128), -} - -impl FullInt { - #[allow(clippy::cast_sign_loss)] - #[must_use] - fn cmp_s_u(s: i128, u: u128) -> Ordering { - if s < 0 { - Ordering::Less - } else if u > (i128::MAX as u128) { - Ordering::Greater - } else { - (s as u128).cmp(&u) - } - } -} - -impl PartialEq for FullInt { - #[must_use] - fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal - } -} - -impl PartialOrd for FullInt { - #[must_use] - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(match (self, other) { - (&Self::S(s), &Self::S(o)) => s.cmp(&o), - (&Self::U(s), &Self::U(o)) => s.cmp(&o), - (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o), - (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(), - }) - } -} - -impl Ord for FullInt { - #[must_use] - fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other) - .expect("`partial_cmp` for FullInt can never return `None`") - } -} - -fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> { - if let ExprKind::Cast(ref cast_exp, _) = expr.kind { - let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp); - let cast_ty = cx.typeck_results().expr_ty(expr); - // if it's a cast from i32 to u32 wrapping will invalidate all these checks - if cx.layout_of(pre_cast_ty).ok().map(|l| l.size) == cx.layout_of(cast_ty).ok().map(|l| l.size) { - return None; - } - match pre_cast_ty.kind() { - ty::Int(int_ty) => Some(match int_ty { - IntTy::I8 => (FullInt::S(i128::from(i8::MIN)), FullInt::S(i128::from(i8::MAX))), - IntTy::I16 => (FullInt::S(i128::from(i16::MIN)), FullInt::S(i128::from(i16::MAX))), - IntTy::I32 => (FullInt::S(i128::from(i32::MIN)), FullInt::S(i128::from(i32::MAX))), - IntTy::I64 => (FullInt::S(i128::from(i64::MIN)), FullInt::S(i128::from(i64::MAX))), - IntTy::I128 => (FullInt::S(i128::MIN), FullInt::S(i128::MAX)), - IntTy::Isize => (FullInt::S(isize::MIN as i128), FullInt::S(isize::MAX as i128)), - }), - ty::Uint(uint_ty) => Some(match uint_ty { - UintTy::U8 => (FullInt::U(u128::from(u8::MIN)), FullInt::U(u128::from(u8::MAX))), - UintTy::U16 => (FullInt::U(u128::from(u16::MIN)), FullInt::U(u128::from(u16::MAX))), - UintTy::U32 => (FullInt::U(u128::from(u32::MIN)), FullInt::U(u128::from(u32::MAX))), - UintTy::U64 => (FullInt::U(u128::from(u64::MIN)), FullInt::U(u128::from(u64::MAX))), - UintTy::U128 => (FullInt::U(u128::MIN), FullInt::U(u128::MAX)), - UintTy::Usize => (FullInt::U(usize::MIN as u128), FullInt::U(usize::MAX as u128)), - }), - _ => None, - } - } else { - None - } -} - -fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> { - let val = constant(cx, cx.typeck_results(), expr)?.0; - if let Constant::Int(const_int) = val { - match *cx.typeck_results().expr_ty(expr).kind() { - ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), - ty::Uint(_) => Some(FullInt::U(const_int)), - _ => None, - } - } else { - None - } -} - -fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) { - if let ExprKind::Cast(ref cast_val, _) = expr.kind { - span_lint( - cx, - INVALID_UPCAST_COMPARISONS, - span, - &format!( - "because of the numeric bounds on `{}` prior to casting, this expression is always {}", - snippet(cx, cast_val.span, "the expression"), - if always { "true" } else { "false" }, - ), - ); - } -} - -fn upcast_comparison_bounds_err<'tcx>( - cx: &LateContext<'tcx>, - span: Span, - rel: comparisons::Rel, - lhs_bounds: Option<(FullInt, FullInt)>, - lhs: &'tcx Expr<'_>, - rhs: &'tcx Expr<'_>, - invert: bool, -) { - use crate::utils::comparisons::Rel; - - if let Some((lb, ub)) = lhs_bounds { - if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { - if rel == Rel::Eq || rel == Rel::Ne { - if norm_rhs_val < lb || norm_rhs_val > ub { - err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); - } - } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val < lb - } else { - ub < norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val <= lb - } else { - ub <= norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } { - err_upcast_comparison(cx, span, lhs, true) - } else if match rel { - Rel::Lt => { - if invert { - norm_rhs_val >= ub - } else { - lb >= norm_rhs_val - } - }, - Rel::Le => { - if invert { - norm_rhs_val > ub - } else { - lb > norm_rhs_val - } - }, - Rel::Eq | Rel::Ne => unreachable!(), - } { - err_upcast_comparison(cx, span, lhs, false) - } - } - } -} - -impl<'tcx> LateLintPass<'tcx> for InvalidUpcastComparisons { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind { - let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs); - let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { - val - } else { - return; - }; - - let lhs_bounds = numeric_cast_precast_bounds(cx, normalized_lhs); - let rhs_bounds = numeric_cast_precast_bounds(cx, normalized_rhs); - - upcast_comparison_bounds_err(cx, expr.span, rel, lhs_bounds, normalized_lhs, normalized_rhs, false); - upcast_comparison_bounds_err(cx, expr.span, rel, rhs_bounds, normalized_rhs, normalized_lhs, true); - } - } -} - -declare_clippy_lint! { - /// **What it does:** Checks for public `impl` or `fn` missing generalization - /// over different hashers and implicitly defaulting to the default hashing - /// algorithm (`SipHash`). - /// - /// **Why is this bad?** `HashMap` or `HashSet` with custom hashers cannot be - /// used with them. - /// - /// **Known problems:** Suggestions for replacing constructors can contain - /// false-positives. Also applying suggestions can require modification of other - /// pieces of code, possibly including external crates. - /// - /// **Example:** - /// ```rust - /// # use std::collections::HashMap; - /// # use std::hash::{Hash, BuildHasher}; - /// # trait Serialize {}; - /// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { } - /// - /// pub fn foo(map: &mut HashMap<i32, i32>) { } - /// ``` - /// could be rewritten as - /// ```rust - /// # use std::collections::HashMap; - /// # use std::hash::{Hash, BuildHasher}; - /// # trait Serialize {}; - /// impl<K: Hash + Eq, V, S: BuildHasher> Serialize for HashMap<K, V, S> { } - /// - /// pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { } - /// ``` - pub IMPLICIT_HASHER, - pedantic, - "missing generalization over different hashers" -} - -declare_lint_pass!(ImplicitHasher => [IMPLICIT_HASHER]); - -impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { - #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)] - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - use rustc_span::BytePos; - - fn suggestion<'tcx>( - cx: &LateContext<'tcx>, - diag: &mut DiagnosticBuilder<'_>, - generics_span: Span, - generics_suggestion_span: Span, - target: &ImplicitHasherType<'_>, - vis: ImplicitHasherConstructorVisitor<'_, '_, '_>, - ) { - let generics_snip = snippet(cx, generics_span, ""); - // trim `<` `>` - let generics_snip = if generics_snip.is_empty() { - "" - } else { - &generics_snip[1..generics_snip.len() - 1] - }; - - multispan_sugg( - diag, - "consider adding a type parameter", - vec![ - ( - generics_suggestion_span, - format!( - "<{}{}S: ::std::hash::BuildHasher{}>", - generics_snip, - if generics_snip.is_empty() { "" } else { ", " }, - if vis.suggestions.is_empty() { - "" - } else { - // request users to add `Default` bound so that generic constructors can be used - " + Default" - }, - ), - ), - ( - target.span(), - format!("{}<{}, S>", target.type_name(), target.type_arguments(),), - ), - ], - ); - - if !vis.suggestions.is_empty() { - multispan_sugg(diag, "...and use generic constructor", vis.suggestions); - } - } - - if !cx.access_levels.is_exported(item.hir_id()) { - return; - } - - match item.kind { - ItemKind::Impl(ref impl_) => { - let mut vis = ImplicitHasherTypeVisitor::new(cx); - vis.visit_ty(impl_.self_ty); - - for target in &vis.found { - if differing_macro_contexts(item.span, target.span()) { - return; - } - - let generics_suggestion_span = impl_.generics.span.substitute_dummy({ - let pos = snippet_opt(cx, item.span.until(target.span())) - .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))); - if let Some(pos) = pos { - Span::new(pos, pos, item.span.data().ctxt) - } else { - return; - } - }); - - let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); - for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) { - ctr_vis.visit_impl_item(item); - } - - span_lint_and_then( - cx, - IMPLICIT_HASHER, - target.span(), - &format!( - "impl for `{}` should be generalized over different hashers", - target.type_name() - ), - move |diag| { - suggestion(cx, diag, impl_.generics.span, generics_suggestion_span, target, ctr_vis); - }, - ); - } - }, - ItemKind::Fn(ref sig, ref generics, body_id) => { - let body = cx.tcx.hir().body(body_id); - - for ty in sig.decl.inputs { - let mut vis = ImplicitHasherTypeVisitor::new(cx); - vis.visit_ty(ty); - - for target in &vis.found { - if in_external_macro(cx.sess(), generics.span) { - continue; - } - let generics_suggestion_span = generics.span.substitute_dummy({ - let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span)) - .and_then(|snip| { - let i = snip.find("fn")?; - Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32)) - }) - .expect("failed to create span for type parameters"); - Span::new(pos, pos, item.span.data().ctxt) - }); - - let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); - ctr_vis.visit_body(body); - - span_lint_and_then( - cx, - IMPLICIT_HASHER, - target.span(), - &format!( - "parameter of type `{}` should be generalized over different hashers", - target.type_name() - ), - move |diag| { - suggestion(cx, diag, generics.span, generics_suggestion_span, target, ctr_vis); - }, - ); - } + self.check_ty(cx, ty, context); } }, _ => {}, @@ -1490,179 +446,9 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } } -enum ImplicitHasherType<'tcx> { - HashMap(Span, Ty<'tcx>, Cow<'static, str>, Cow<'static, str>), - HashSet(Span, Ty<'tcx>, Cow<'static, str>), -} - -impl<'tcx> ImplicitHasherType<'tcx> { - /// Checks that `ty` is a target type without a `BuildHasher`. - fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> { - if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.kind { - let params: Vec<_> = path - .segments - .last() - .as_ref()? - .args - .as_ref()? - .args - .iter() - .filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }) - .collect(); - let params_len = params.len(); - - let ty = hir_ty_to_ty(cx.tcx, hir_ty); - - if is_type_diagnostic_item(cx, ty, sym::hashmap_type) && params_len == 2 { - Some(ImplicitHasherType::HashMap( - hir_ty.span, - ty, - snippet(cx, params[0].span, "K"), - snippet(cx, params[1].span, "V"), - )) - } else if is_type_diagnostic_item(cx, ty, sym::hashset_type) && params_len == 1 { - Some(ImplicitHasherType::HashSet( - hir_ty.span, - ty, - snippet(cx, params[0].span, "T"), - )) - } else { - None - } - } else { - None - } - } - - fn type_name(&self) -> &'static str { - match *self { - ImplicitHasherType::HashMap(..) => "HashMap", - ImplicitHasherType::HashSet(..) => "HashSet", - } - } - - fn type_arguments(&self) -> String { - match *self { - ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v), - ImplicitHasherType::HashSet(.., ref t) => format!("{}", t), - } - } - - fn ty(&self) -> Ty<'tcx> { - match *self { - ImplicitHasherType::HashMap(_, ty, ..) | ImplicitHasherType::HashSet(_, ty, ..) => ty, - } - } - - fn span(&self) -> Span { - match *self { - ImplicitHasherType::HashMap(span, ..) | ImplicitHasherType::HashSet(span, ..) => span, - } - } -} - -struct ImplicitHasherTypeVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - found: Vec<ImplicitHasherType<'tcx>>, -} - -impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> { - fn new(cx: &'a LateContext<'tcx>) -> Self { - Self { cx, found: vec![] } - } -} - -impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) { - if let Some(target) = ImplicitHasherType::new(self.cx, t) { - self.found.push(target); - } - - walk_ty(self, t); - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None - } -} - -/// Looks for default-hasher-dependent constructors like `HashMap::new`. -struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { - cx: &'a LateContext<'tcx>, - maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>, - target: &'b ImplicitHasherType<'tcx>, - suggestions: BTreeMap<Span, String>, -} - -impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { - fn new(cx: &'a LateContext<'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self { - Self { - cx, - maybe_typeck_results: cx.maybe_typeck_results(), - target, - suggestions: BTreeMap::new(), - } - } -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { - type Map = Map<'tcx>; - - fn visit_body(&mut self, body: &'tcx Body<'_>) { - let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body.id())); - walk_body(self, body); - self.maybe_typeck_results = old_maybe_typeck_results; - } - - fn visit_expr(&mut self, e: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(ref fun, ref args) = e.kind; - if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.kind; - if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind; - then { - if !TyS::same_type(self.target.ty(), self.maybe_typeck_results.unwrap().expr_ty(e)) { - return; - } - - if match_path(ty_path, &paths::HASHMAP) { - if method.ident.name == sym::new { - self.suggestions - .insert(e.span, "HashMap::default()".to_string()); - } else if method.ident.name == sym!(with_capacity) { - self.suggestions.insert( - e.span, - format!( - "HashMap::with_capacity_and_hasher({}, Default::default())", - snippet(self.cx, args[0].span, "capacity"), - ), - ); - } - } else if match_path(ty_path, &paths::HASHSET) { - if method.ident.name == sym::new { - self.suggestions - .insert(e.span, "HashSet::default()".to_string()); - } else if method.ident.name == sym!(with_capacity) { - self.suggestions.insert( - e.span, - format!( - "HashSet::with_capacity_and_hasher({}, Default::default())", - snippet(self.cx, args[0].span, "capacity"), - ), - ); - } - } - } - } - - walk_expr(self, e); - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) - } +#[derive(Clone, Copy, Default)] +struct CheckTyContext { + is_in_trait_impl: bool, + is_local: bool, + is_nested_call: bool, } diff --git a/src/tools/clippy/clippy_lints/src/types/option_option.rs b/src/tools/clippy/clippy_lints/src/types/option_option.rs index dc5db963b4..b2692c4807 100644 --- a/src/tools/clippy/clippy_lints/src/types/option_option.rs +++ b/src/tools/clippy/clippy_lints/src/types/option_option.rs @@ -1,9 +1,9 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_ty_param_diagnostic_item; use rustc_hir::{self as hir, def_id::DefId, QPath}; use rustc_lint::LateContext; use rustc_span::symbol::sym; -use crate::utils::{is_ty_param_diagnostic_item, span_lint}; - use super::OPTION_OPTION; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs index e34b95147e..ef629a35d1 100644 --- a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs +++ b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs @@ -1,12 +1,11 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{get_qpath_generic_tys, is_ty_param_diagnostic_item}; use rustc_errors::Applicability; use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind}; use rustc_lint::LateContext; use rustc_span::symbol::sym; -use crate::utils::{ - get_qpath_generic_tys, is_ty_param_diagnostic_item, snippet_with_applicability, span_lint_and_sugg, -}; - use super::RC_BUFFER; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index 5da6db179c..c0c1f34058 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -1,13 +1,11 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::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}; use rustc_lint::LateContext; use rustc_span::symbol::sym; -use crate::utils::{ - get_qpath_generic_tys, is_ty_param_diagnostic_item, is_ty_param_lang_item, snippet_with_applicability, - span_lint_and_sugg, -}; - use super::{utils, REDUNDANT_ALLOCATION}; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs new file mode 100644 index 0000000000..d8c4b67520 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -0,0 +1,79 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_hir as hir; +use rustc_hir::intravisit::{walk_ty, NestedVisitorMap, Visitor}; +use rustc_hir::{GenericParamKind, TyKind}; +use rustc_lint::LateContext; +use rustc_middle::hir::map::Map; +use rustc_target::spec::abi::Abi; + +use super::TYPE_COMPLEXITY; + +pub(super) fn check(cx: &LateContext<'_>, ty: &hir::Ty<'_>, type_complexity_threshold: u64) -> bool { + let score = { + let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; + visitor.visit_ty(ty); + visitor.score + }; + + if score > type_complexity_threshold { + span_lint( + cx, + TYPE_COMPLEXITY, + ty.span, + "very complex type used. Consider factoring parts into `type` definitions", + ); + true + } else { + false + } +} + +/// Walks a type and assigns a complexity score to it. +struct TypeComplexityVisitor { + /// total complexity score of the type + score: u64, + /// current nesting level + nest: u64, +} + +impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { + type Map = Map<'tcx>; + + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { + let (add_score, sub_nest) = match ty.kind { + // _, &x and *x have only small overhead; don't mess with nesting level + TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0), + + // the "normal" components of a type: named types, arrays/tuples + TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), + + // function types bring a lot of overhead + TyKind::BareFn(bare) if bare.abi == Abi::Rust => (50 * self.nest, 1), + + TyKind::TraitObject(param_bounds, _, _) => { + let has_lifetime_parameters = param_bounds.iter().any(|bound| { + bound + .bound_generic_params + .iter() + .any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. })) + }); + if has_lifetime_parameters { + // complex trait bounds like A<'a, 'b> + (50 * self.nest, 1) + } else { + // simple trait bounds like A + B + (20 * self.nest, 0) + } + }, + + _ => (0, 0), + }; + self.score += add_score; + self.nest += sub_nest; + walk_ty(self, ty); + self.nest -= sub_nest; + } + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } +} diff --git a/src/tools/clippy/clippy_lints/src/types/utils.rs b/src/tools/clippy/clippy_lints/src/types/utils.rs index 4d64748f99..0fa75f8f0a 100644 --- a/src/tools/clippy/clippy_lints/src/types/utils.rs +++ b/src/tools/clippy/clippy_lints/src/types/utils.rs @@ -1,15 +1,13 @@ +use clippy_utils::last_path_segment; +use if_chain::if_chain; use rustc_hir::{GenericArg, QPath, TyKind}; use rustc_lint::LateContext; use rustc_span::source_map::Span; -use crate::utils::last_path_segment; - -use if_chain::if_chain; - pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> { let last = last_path_segment(qpath); if_chain! { - if let Some(ref params) = last.args; + if let Some(params) = last.args; if !params.parenthesized; if let Some(ty) = params.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 2530cc133c..7a44417462 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -1,3 +1,7 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::last_path_segment; +use clippy_utils::source::snippet; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind}; use rustc_lint::LateContext; @@ -6,10 +10,6 @@ use rustc_span::symbol::sym; use rustc_target::abi::LayoutOf; use rustc_typeck::hir_ty_to_ty; -use if_chain::if_chain; - -use crate::utils::{last_path_segment, snippet, span_lint_and_sugg}; - use super::VEC_BOX; pub(super) fn check( @@ -22,7 +22,7 @@ pub(super) fn check( if cx.tcx.is_diagnostic_item(sym::vec_type, def_id) { if_chain! { // Get the _ part of Vec<_> - if let Some(ref last) = last_path_segment(qpath).args; + if let Some(last) = last_path_segment(qpath).args; if let Some(ty) = last.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, @@ -33,7 +33,7 @@ pub(super) fn check( if let Some(def_id) = res.opt_def_id(); if Some(def_id) == cx.tcx.lang_items().owned_box(); // At this point, we know ty is Box<T>, now get T - if let Some(ref last) = last_path_segment(ty_qpath).args; + if let Some(last) = last_path_segment(ty_qpath).args; if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, diff --git a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs index 5443f1601f..f4f5e1233e 100644 --- a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs +++ b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs @@ -1,4 +1,6 @@ -use crate::utils::{is_type_lang_item, match_function_call, paths, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_type_lang_item; +use clippy_utils::{match_function_call, paths}; use rustc_hir::{lang_items, Expr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -33,7 +35,7 @@ declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]); impl LateLintPass<'tcx> for UndroppedManuallyDrops { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(ref args) = match_function_call(cx, expr, &paths::DROP) { + if let Some(args) = match_function_call(cx, expr, &paths::DROP) { let ty = cx.typeck_results().expr_ty(&args[0]); if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop) { span_lint_and_help( diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs index 93d59cc7fc..d81e31f5a2 100644 --- a/src/tools/clippy/clippy_lints/src/unicode.rs +++ b/src/tools/clippy/clippy_lints/src/unicode.rs @@ -1,4 +1,6 @@ -use crate::utils::{is_allowed, snippet, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_allowed; +use clippy_utils::source::snippet; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, HirId}; diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index c6ae8b9b59..1c420a5042 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -1,4 +1,5 @@ -use crate::utils::{get_trait_def_id, paths, span_lint, span_lint_and_help}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::{get_trait_def_id, paths}; use if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, StmtKind}; @@ -43,7 +44,7 @@ fn get_trait_predicates_for_trait_id<'tcx>( for (pred, _) in generics.predicates { if_chain! { if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind().skip_binder(); - let trait_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(poly_trait_pred)); + let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); if let Some(trait_def_id) = trait_id; if trait_def_id == trait_pred.trait_ref.def_id; then { @@ -57,12 +58,12 @@ fn get_trait_predicates_for_trait_id<'tcx>( fn get_projection_pred<'tcx>( cx: &LateContext<'tcx>, generics: GenericPredicates<'tcx>, - pred: TraitPredicate<'tcx>, + trait_pred: TraitPredicate<'tcx>, ) -> Option<ProjectionPredicate<'tcx>> { generics.predicates.iter().find_map(|(proj_pred, _)| { - if let ty::PredicateKind::Projection(proj_pred) = proj_pred.kind().skip_binder() { - let projection_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(proj_pred)); - if projection_pred.projection_ty.substs == pred.trait_ref.substs { + if let ty::PredicateKind::Projection(pred) = proj_pred.kind().skip_binder() { + let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); + if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs { return Some(projection_pred); } } @@ -115,8 +116,8 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa let ty = cx.tcx.erase_late_bound_regions(ret_ty); if ty.is_unit(); then { + let body = cx.tcx.hir().body(body_id); if_chain! { - let body = cx.tcx.hir().body(body_id); if let ExprKind::Block(block, _) = body.value.kind; if block.expr.is_none(); if let Some(stmt) = block.stmts.last(); @@ -137,7 +138,7 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind { + if let ExprKind::MethodCall(_, _, args, _) = expr.kind { let arg_indices = get_args_to_check(cx, expr); for (i, trait_name) in arg_indices { if i < args.len() { diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs new file mode 100644 index 0000000000..fad647dfb2 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -0,0 +1,39 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::higher; +use clippy_utils::source::snippet_with_macro_callsite; +use rustc_errors::Applicability; +use rustc_hir::{Stmt, StmtKind}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; + +use super::LET_UNIT_VALUE; + +pub(super) fn check(cx: &LateContext<'_>, stmt: &Stmt<'_>) { + if let StmtKind::Local(local) = stmt.kind { + if cx.typeck_results().pat_ty(local.pat).is_unit() { + if in_external_macro(cx.sess(), stmt.span) || local.pat.span.from_expansion() { + return; + } + if higher::is_from_for_desugar(local) { + return; + } + span_lint_and_then( + cx, + LET_UNIT_VALUE, + stmt.span, + "this let-binding has unit value", + |diag| { + if let Some(expr) = &local.init { + let snip = snippet_with_macro_callsite(cx, expr.span, "()"); + diag.span_suggestion( + stmt.span, + "omit the `let` binding", + format!("{};", snip), + Applicability::MachineApplicable, // snippet + ); + } + }, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/unit_types/mod.rs b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs new file mode 100644 index 0000000000..64420a0393 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs @@ -0,0 +1,107 @@ +mod let_unit_value; +mod unit_arg; +mod unit_cmp; +mod utils; + +use rustc_hir::{Expr, Stmt}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for binding a unit value. + /// + /// **Why is this bad?** A unit value cannot usefully be used anywhere. So + /// binding one is kind of pointless. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// let x = { + /// 1; + /// }; + /// ``` + pub LET_UNIT_VALUE, + pedantic, + "creating a `let` binding to a value of unit type, which usually can't be used afterwards" +} + +declare_clippy_lint! { + /// **What it does:** Checks for comparisons to unit. This includes all binary + /// comparisons (like `==` and `<`) and asserts. + /// + /// **Why is this bad?** Unit is always equal to itself, and thus is just a + /// clumsily written constant. Mostly this happens when someone accidentally + /// adds semicolons at the end of the operands. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// # fn foo() {}; + /// # fn bar() {}; + /// # fn baz() {}; + /// if { + /// foo(); + /// } == { + /// bar(); + /// } { + /// baz(); + /// } + /// ``` + /// is equal to + /// ```rust + /// # fn foo() {}; + /// # fn bar() {}; + /// # fn baz() {}; + /// { + /// foo(); + /// bar(); + /// baz(); + /// } + /// ``` + /// + /// For asserts: + /// ```rust + /// # fn foo() {}; + /// # fn bar() {}; + /// assert_eq!({ foo(); }, { bar(); }); + /// ``` + /// will always succeed + pub UNIT_CMP, + correctness, + "comparing unit values" +} + +declare_clippy_lint! { + /// **What it does:** Checks for passing a unit value as an argument to a function without using a + /// unit literal (`()`). + /// + /// **Why is this bad?** This is likely the result of an accidental semicolon. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust,ignore + /// foo({ + /// let a = bar(); + /// baz(a); + /// }) + /// ``` + pub UNIT_ARG, + complexity, + "passing unit to a function" +} + +declare_lint_pass!(UnitTypes => [LET_UNIT_VALUE, UNIT_CMP, UNIT_ARG]); + +impl LateLintPass<'_> for UnitTypes { + fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) { + let_unit_value::check(cx, stmt); + } + + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + unit_cmp::check(cx, expr); + unit_arg::check(cx, expr); + } +} diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs new file mode 100644 index 0000000000..57be2d2f67 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -0,0 +1,207 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{self as hir, Block, Expr, ExprKind, MatchSource, Node, StmtKind}; +use rustc_lint::LateContext; + +use super::{utils, UNIT_ARG}; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if expr.span.from_expansion() { + return; + } + + // apparently stuff in the desugaring of `?` can trigger this + // so check for that here + // only the calls to `Try::from_error` is marked as desugared, + // so we need to check both the current Expr and its parent. + if is_questionmark_desugar_marked_call(expr) { + return; + } + let map = &cx.tcx.hir(); + let opt_parent_node = map.find(map.get_parent_node(expr.hir_id)); + if_chain! { + if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; + if is_questionmark_desugar_marked_call(parent_expr); + then { + return; + } + } + + match expr.kind { + ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => { + let args_to_recover = args + .iter() + .filter(|arg| { + if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) { + !matches!( + &arg.kind, + ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..) + ) + } else { + false + } + }) + .collect::<Vec<_>>(); + if !args_to_recover.is_empty() { + lint_unit_args(cx, expr, &args_to_recover); + } + }, + _ => (), + } +} + +fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool { + use rustc_span::hygiene::DesugaringKind; + if let ExprKind::Call(callee, _) = expr.kind { + callee.span.is_desugaring(DesugaringKind::QuestionMark) + } else { + false + } +} + +fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) { + let mut applicability = Applicability::MachineApplicable; + let (singular, plural) = if args_to_recover.len() > 1 { + ("", "s") + } else { + ("a ", "") + }; + span_lint_and_then( + cx, + UNIT_ARG, + expr.span, + &format!("passing {}unit value{} to a function", singular, plural), + |db| { + let mut or = ""; + args_to_recover + .iter() + .filter_map(|arg| { + if_chain! { + if let ExprKind::Block(block, _) = arg.kind; + if block.expr.is_none(); + if let Some(last_stmt) = block.stmts.iter().last(); + if let StmtKind::Semi(last_expr) = last_stmt.kind; + if let Some(snip) = snippet_opt(cx, last_expr.span); + then { + Some(( + last_stmt.span, + snip, + )) + } + else { + None + } + } + }) + .for_each(|(span, sugg)| { + db.span_suggestion( + span, + "remove the semicolon from the last statement in the block", + sugg, + Applicability::MaybeIncorrect, + ); + or = "or "; + applicability = Applicability::MaybeIncorrect; + }); + + let arg_snippets: Vec<String> = args_to_recover + .iter() + .filter_map(|arg| snippet_opt(cx, arg.span)) + .collect(); + let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover + .iter() + .filter(|arg| !is_empty_block(arg)) + .filter_map(|arg| snippet_opt(cx, arg.span)) + .collect(); + + if let Some(call_snippet) = snippet_opt(cx, expr.span) { + let sugg = fmt_stmts_and_call( + cx, + expr, + &call_snippet, + &arg_snippets, + &arg_snippets_without_empty_blocks, + ); + + if arg_snippets_without_empty_blocks.is_empty() { + db.multipart_suggestion( + &format!("use {}unit literal{} instead", singular, plural), + args_to_recover + .iter() + .map(|arg| (arg.span, "()".to_string())) + .collect::<Vec<_>>(), + applicability, + ); + } else { + let plural = arg_snippets_without_empty_blocks.len() > 1; + let empty_or_s = if plural { "s" } else { "" }; + let it_or_them = if plural { "them" } else { "it" }; + db.span_suggestion( + expr.span, + &format!( + "{}move the expression{} in front of the call and replace {} with the unit literal `()`", + or, empty_or_s, it_or_them + ), + sugg, + applicability, + ); + } + } + }, + ); +} + +fn is_empty_block(expr: &Expr<'_>) -> bool { + matches!( + expr.kind, + ExprKind::Block( + Block { + stmts: &[], + expr: None, + .. + }, + _, + ) + ) +} + +fn fmt_stmts_and_call( + cx: &LateContext<'_>, + call_expr: &Expr<'_>, + call_snippet: &str, + args_snippets: &[impl AsRef<str>], + non_empty_block_args_snippets: &[impl AsRef<str>], +) -> String { + let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0); + let call_snippet_with_replacements = args_snippets + .iter() + .fold(call_snippet.to_owned(), |acc, arg| acc.replacen(arg.as_ref(), "()", 1)); + + let mut stmts_and_call = non_empty_block_args_snippets + .iter() + .map(|it| it.as_ref().to_owned()) + .collect::<Vec<_>>(); + stmts_and_call.push(call_snippet_with_replacements); + stmts_and_call = stmts_and_call + .into_iter() + .map(|v| reindent_multiline(v.into(), true, Some(call_expr_indent)).into_owned()) + .collect(); + + let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent))); + // expr is not in a block statement or result expression position, wrap in a block + let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id)); + if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) { + let block_indent = call_expr_indent + 4; + stmts_and_call_snippet = + reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned(); + stmts_and_call_snippet = format!( + "{{\n{}{}\n{}}}", + " ".repeat(block_indent), + &stmts_and_call_snippet, + " ".repeat(call_expr_indent) + ); + } + stmts_and_call_snippet +} diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs new file mode 100644 index 0000000000..85257f3113 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs @@ -0,0 +1,56 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::hygiene::{ExpnKind, MacroKind}; + +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(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() { + let result = match &*symbol.as_str() { + "assert_eq" | "debug_assert_eq" => "succeed", + "assert_ne" | "debug_assert_ne" => "fail", + _ => return, + }; + span_lint( + cx, + UNIT_CMP, + expr.span, + &format!( + "`{}` of unit values detected. This will always {}", + symbol.as_str(), + result + ), + ); + } + } + } + } + return; + } + + 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() { + let result = match op { + BinOpKind::Eq | BinOpKind::Le | BinOpKind::Ge => "true", + _ => "false", + }; + span_lint( + cx, + UNIT_CMP, + expr.span, + &format!( + "{}-comparison of unit values detected. This will always be {}", + op.as_str(), + result + ), + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/unit_types/utils.rs b/src/tools/clippy/clippy_lints/src/unit_types/utils.rs new file mode 100644 index 0000000000..9a3750b235 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unit_types/utils.rs @@ -0,0 +1,5 @@ +use rustc_hir::{Expr, ExprKind}; + +pub(super) fn is_unit_literal(expr: &Expr<'_>) -> bool { + matches!(expr.kind, ExprKind::Tup(slice) if slice.is_empty()) +} diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs index 9582c162e7..9cca05b1f1 100644 --- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs +++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs @@ -1,4 +1,5 @@ -use crate::utils::{match_def_path, paths, span_lint, span_lint_and_help}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -76,7 +77,7 @@ impl LateLintPass<'_> for UnnamedAddress { } if_chain! { - if let ExprKind::Binary(binop, ref left, ref right) = expr.kind; + if let ExprKind::Binary(binop, left, right) = expr.kind; if is_comparison(binop.node); if is_trait_ptr(cx, left) && is_trait_ptr(cx, right); then { @@ -92,7 +93,7 @@ impl LateLintPass<'_> for UnnamedAddress { } if_chain! { - if let ExprKind::Call(ref func, [ref _left, ref _right]) = expr.kind; + if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::PTR_EQ) || @@ -113,10 +114,10 @@ impl LateLintPass<'_> for UnnamedAddress { } if_chain! { - if let ExprKind::Binary(binop, ref left, ref right) = expr.kind; + if let ExprKind::Binary(binop, left, right) = expr.kind; if is_comparison(binop.node); - if cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr() && - cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr(); + if cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr(); + if cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr(); if is_fn_def(cx, left) || is_fn_def(cx, right); then { span_lint( diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs new file mode 100644 index 0000000000..48c54d79cf --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs @@ -0,0 +1,67 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use if_chain::if_chain; +use rustc_ast::{Item, ItemKind, UseTreeKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::kw; + +declare_clippy_lint! { + /// **What it does:** Checks for imports ending in `::{self}`. + /// + /// **Why is this bad?** In most cases, this can be written much more cleanly by omitting `::{self}`. + /// + /// **Known problems:** Removing `::{self}` will cause any non-module items at the same path to also be imported. + /// This might cause a naming conflict (https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt + /// to detect this scenario and that is why it is a restriction lint. + /// + /// **Example:** + /// + /// ```rust + /// use std::io::{self}; + /// ``` + /// Use instead: + /// ```rust + /// use std::io; + /// ``` + pub UNNECESSARY_SELF_IMPORTS, + restriction, + "imports ending in `::{self}`, which can be omitted" +} + +declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]); + +impl EarlyLintPass for UnnecessarySelfImports { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if_chain! { + if let ItemKind::Use(use_tree) = &item.kind; + if let UseTreeKind::Nested(nodes) = &use_tree.kind; + if let [(self_tree, _)] = &**nodes; + if let [self_seg] = &*self_tree.prefix.segments; + if self_seg.ident.name == kw::SelfLower; + if let Some(last_segment) = use_tree.prefix.segments.last(); + + then { + span_lint_and_then( + cx, + UNNECESSARY_SELF_IMPORTS, + item.span, + "import ending with `::{self}`", + |diag| { + diag.span_suggestion( + last_segment.span().with_hi(item.span.hi()), + "consider omitting `::{self}`", + format!( + "{}{};", + last_segment.ident, + if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {}", alias) } else { String::new() }, + ), + Applicability::MaybeIncorrect, + ); + diag.note("this will slightly change semantics; any non-module items at the same path will also be imported"); + }, + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs index 00a707107b..347d858b64 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs @@ -1,5 +1,6 @@ -use crate::utils; -use crate::utils::sugg::Sugg; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath}; @@ -8,6 +9,7 @@ use rustc_middle::ty::{self, subst::GenericArgKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; use rustc_span::symbol::Ident; +use std::iter; declare_clippy_lint! { /// **What it does:** @@ -78,17 +80,14 @@ fn mirrored_exprs( mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) }, // Two arrays with mirrored contents - (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => left_exprs - .iter() - .zip(right_exprs.iter()) - .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => { + iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) + }, // The two exprs are function calls. // Check to see that the function itself and its arguments are mirrored (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => { mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) - && left_args - .iter() - .zip(right_args.iter()) + && iter::zip(*left_args, *right_args) .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) }, // The two exprs are method calls. @@ -99,16 +98,13 @@ fn mirrored_exprs( ExprKind::MethodCall(right_segment, _, right_args, _), ) => { left_segment.ident == right_segment.ident - && left_args - .iter() - .zip(right_args.iter()) + && iter::zip(*left_args, *right_args) .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) }, // Two tuples with mirrored contents - (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => left_exprs - .iter() - .zip(right_exprs.iter()) - .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => { + iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) + }, // Two binary ops, which are the same operation and which have mirrored arguments (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => { left_op.node == right_op.node @@ -145,10 +141,7 @@ fn mirrored_exprs( }, )), ) => { - (left_segments - .iter() - .zip(right_segments.iter()) - .all(|(left, right)| left.ident == right.ident) + (iter::zip(*left_segments, *right_segments).all(|(left, right)| left.ident == right.ident) && left_segments .iter() .all(|seg| &seg.ident != a_ident && &seg.ident != b_ident)) @@ -176,7 +169,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> { if let name = name_ident.ident.name.to_ident_string(); if name == "sort_by" || name == "sort_unstable_by"; if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args; - if utils::is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::vec_type); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::vec_type); if let closure_body = cx.tcx.hir().body(*closure_body_id); if let &[ Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..}, @@ -186,15 +179,15 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> { if method_path.ident.name == sym::cmp; then { let (closure_body, closure_arg, reverse) = if mirrored_exprs( - &cx, - &left_expr, - &left_ident, - &right_expr, - &right_ident + cx, + left_expr, + left_ident, + right_expr, + right_ident ) { - (Sugg::hir(cx, &left_expr, "..").to_string(), left_ident.name.to_string(), false) - } else if mirrored_exprs(&cx, &left_expr, &right_ident, &right_expr, &left_ident) { - (Sugg::hir(cx, &left_expr, "..").to_string(), right_ident.name.to_string(), true) + (Sugg::hir(cx, left_expr, "..").to_string(), left_ident.name.to_string(), false) + } else if mirrored_exprs(cx, left_expr, right_ident, right_expr, left_ident) { + (Sugg::hir(cx, left_expr, "..").to_string(), right_ident.name.to_string(), true) } else { return None; }; @@ -232,7 +225,7 @@ fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { impl LateLintPass<'_> for UnnecessarySortBy { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { match detect_lint(cx, expr) { - Some(LintTrigger::SortByKey(trigger)) => utils::span_lint_and_sugg( + Some(LintTrigger::SortByKey(trigger)) => span_lint_and_sugg( cx, UNNECESSARY_SORT_BY, expr.span, @@ -255,7 +248,7 @@ impl LateLintPass<'_> for UnnecessarySortBy { Applicability::MachineApplicable }, ), - Some(LintTrigger::Sort(trigger)) => utils::span_lint_and_sugg( + Some(LintTrigger::Sort(trigger)) => span_lint_and_sugg( cx, UNNECESSARY_SORT_BY, expr.span, diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 8e076397c1..f2f1410aed 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -1,10 +1,10 @@ -use crate::utils::{ - contains_return, in_macro, match_qpath, paths, return_ty, snippet, span_lint_and_then, - visitors::find_all_ret_expressions, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::{contains_return, in_macro, is_lang_ctor, return_ty, visitors::find_all_ret_expressions}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; +use rustc_hir::LangItem::{OptionSome, ResultOk}; use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { } }, FnKind::Closure => return, - _ => (), + FnKind::Method(..) => (), } // Abort if the method is implementing a trait or of it a trait method. @@ -86,11 +86,11 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { } // Get the wrapper and inner types, if can't, abort. - let (return_type_label, path, inner_type) = if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id).kind() { + let (return_type_label, lang_item, inner_type) = if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id).kind() { if cx.tcx.is_diagnostic_item(sym::option_type, adt_def.did) { - ("Option", &paths::OPTION_SOME, subst.type_at(0)) + ("Option", OptionSome, subst.type_at(0)) } else if cx.tcx.is_diagnostic_item(sym::result_type, adt_def.did) { - ("Result", &paths::RESULT_OK, subst.type_at(0)) + ("Result", ResultOk, subst.type_at(0)) } else { return; } @@ -104,14 +104,12 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { if_chain! { if !in_macro(ret_expr.span); // Check if a function call. - if let ExprKind::Call(ref func, ref args) = ret_expr.kind; - // Get the Path of the function call. - if let ExprKind::Path(ref qpath) = func.kind; + if let ExprKind::Call(func, [arg]) = ret_expr.kind; // Check if OPTION_SOME or RESULT_OK, depending on return type. - if match_qpath(qpath, path); - if args.len() == 1; + if let ExprKind::Path(qpath) = &func.kind; + if is_lang_ctor(cx, qpath, lang_item); // Make sure the function argument does not contain a return expression. - if !contains_return(&args[0]); + if !contains_return(arg); then { suggs.push( ( @@ -119,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { if inner_type.is_unit() { "".to_string() } else { - snippet(cx, args[0].span.source_callsite(), "..").to_string() + snippet(cx, arg.span.source_callsite(), "..").to_string() } ) ); diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index fa613bb7da..3e985fa72b 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -1,14 +1,16 @@ #![allow(clippy::wildcard_imports, clippy::enum_glob_use)] -use crate::utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path}; -use crate::utils::{over, span_lint_and_then}; +use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{meets_msrv, msrvs, over}; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::{self as ast, Pat, PatKind, PatKind::*, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::DUMMY_SP; use std::cell::Cell; @@ -49,34 +51,51 @@ declare_clippy_lint! { "unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`" } -declare_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]); +#[derive(Clone, Copy)] +pub struct UnnestedOrPatterns { + msrv: Option<RustcVersion>, +} + +impl UnnestedOrPatterns { + #[must_use] + pub fn new(msrv: Option<RustcVersion>) -> Self { + Self { msrv } + } +} + +impl_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]); impl EarlyLintPass for UnnestedOrPatterns { fn check_arm(&mut self, cx: &EarlyContext<'_>, a: &ast::Arm) { - lint_unnested_or_patterns(cx, &a.pat); + if meets_msrv(self.msrv.as_ref(), &msrvs::OR_PATTERNS) { + lint_unnested_or_patterns(cx, &a.pat); + } } fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - if let ast::ExprKind::Let(pat, _) = &e.kind { - lint_unnested_or_patterns(cx, pat); + if meets_msrv(self.msrv.as_ref(), &msrvs::OR_PATTERNS) { + if let ast::ExprKind::Let(pat, _) = &e.kind { + lint_unnested_or_patterns(cx, pat); + } } } fn check_param(&mut self, cx: &EarlyContext<'_>, p: &ast::Param) { - lint_unnested_or_patterns(cx, &p.pat); + if meets_msrv(self.msrv.as_ref(), &msrvs::OR_PATTERNS) { + lint_unnested_or_patterns(cx, &p.pat); + } } fn check_local(&mut self, cx: &EarlyContext<'_>, l: &ast::Local) { - lint_unnested_or_patterns(cx, &l.pat); + if meets_msrv(self.msrv.as_ref(), &msrvs::OR_PATTERNS) { + lint_unnested_or_patterns(cx, &l.pat); + } } + + extract_msrv_attr!(EarlyContext); } fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) { - if !cx.sess.features_untracked().or_patterns { - // Do not suggest nesting the patterns if the feature `or_patterns` is not enabled. - return; - } - if let Ident(.., None) | Lit(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) = pat.kind { // This is a leaf pattern, so cloning is unprofitable. return; diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs index 154082a0fd..16ad9d2dfd 100644 --- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs +++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint; +use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 43166d2678..3387f35bac 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_try, match_trait_method, paths, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{is_try, match_trait_method, paths}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -35,38 +36,48 @@ declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]); impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { let expr = match s.kind { - hir::StmtKind::Semi(ref expr) | hir::StmtKind::Expr(ref expr) => &**expr, + hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr, _ => return, }; match expr.kind { - hir::ExprKind::Match(ref res, _, _) if is_try(expr).is_some() => { - if let hir::ExprKind::Call(ref func, ref args) = res.kind { + hir::ExprKind::Match(res, _, _) if is_try(cx, expr).is_some() => { + if let hir::ExprKind::Call(func, args) = res.kind { if matches!( func.kind, hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _)) ) { - check_method_call(cx, &args[0], expr); + check_map_error(cx, &args[0], expr); } } else { - check_method_call(cx, res, expr); + check_map_error(cx, res, expr); } }, - - hir::ExprKind::MethodCall(ref path, _, ref args, _) => match &*path.ident.as_str() { + hir::ExprKind::MethodCall(path, _, args, _) => match &*path.ident.as_str() { "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { - check_method_call(cx, &args[0], expr); + check_map_error(cx, &args[0], expr); }, _ => (), }, - _ => (), } } } +fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { + let mut call = call; + while let hir::ExprKind::MethodCall(ref path, _, ref args, _) = call.kind { + if matches!(&*path.ident.as_str(), "or" | "or_else" | "ok") { + call = &args[0]; + } else { + break; + } + } + check_method_call(cx, call, expr); +} + fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { - if let hir::ExprKind::MethodCall(ref path, _, _, _) = call.kind { + if let hir::ExprKind::MethodCall(path, _, _, _) = call.kind { let symbol = &*path.ident.as_str(); let read_trait = match_trait_method(cx, call, &paths::IO_READ); let write_trait = match_trait_method(cx, call, &paths::IO_WRITE); diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 812482cf5c..15343cf90f 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -1,11 +1,10 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::visitors::LocalUsedVisitor; use if_chain::if_chain; use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::span_lint_and_help; -use crate::utils::visitors::LocalUsedVisitor; - declare_clippy_lint! { /// **What it does:** Checks methods that contain a `self` argument but don't use it /// @@ -50,21 +49,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { if assoc_item.fn_has_self_parameter; if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; let body = cx.tcx.hir().body(*body_id); - if !body.params.is_empty(); + if let [self_param, ..] = body.params; + let self_hir_id = self_param.pat.hir_id; + if !LocalUsedVisitor::new(cx, self_hir_id).check_body(body); then { - let self_param = &body.params[0]; - let self_hir_id = self_param.pat.hir_id; - if !LocalUsedVisitor::new(cx, self_hir_id).check_body(body) { - span_lint_and_help( - cx, - UNUSED_SELF, - self_param.span, - "unused `self` argument", - None, - "consider refactoring to a associated function", - ); - return; - } + span_lint_and_help( + cx, + UNUSED_SELF, + self_param.span, + "unused `self` argument", + None, + "consider refactoring to a associated function", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs index a31cd5fda8..ce2d0b3ab2 100644 --- a/src/tools/clippy/clippy_lints/src/unused_unit.rs +++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs @@ -1,3 +1,5 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::position_before_rarrow; use if_chain::if_chain; use rustc_ast::ast; use rustc_ast::visit::FnKind; @@ -7,8 +9,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::BytePos; -use crate::utils::{position_before_rarrow, span_lint_and_sugg}; - declare_clippy_lint! { /// **What it does:** Checks for unit (`()`) expressions that can be removed. /// @@ -45,7 +45,7 @@ impl EarlyLintPass for UnusedUnit { fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { if_chain! { - if let Some(ref stmt) = block.stmts.last(); + if let Some(stmt) = block.stmts.last(); if let ast::StmtKind::Expr(ref expr) = stmt.kind; if is_unit_expr(expr) && !stmt.span.from_expansion(); then { diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index 2fb0463c5a..d4efee56ef 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -1,6 +1,6 @@ -use crate::utils::{ - differing_macro_contexts, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated, -}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{differing_macro_contexts, usage::is_potentially_mutated}; use if_chain::if_chain; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp}; @@ -166,8 +166,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } else { // find `unwrap[_err]()` calls: if_chain! { - if let ExprKind::MethodCall(ref method_name, _, ref args, _) = expr.kind; - if let ExprKind::Path(QPath::Resolved(None, ref path)) = args[0].kind; + if let ExprKind::MethodCall(method_name, _, args, _) = expr.kind; + if let ExprKind::Path(QPath::Resolved(None, path)) = args[0].kind; if [sym::unwrap, sym!(unwrap_err)].contains(&method_name.ident.name); let call_to_unwrap = method_name.ident.name == sym::unwrap; if let Some(unwrappable) = self.unwrappables.iter() diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs index 8cb7429849..d17aa6d842 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs @@ -1,6 +1,10 @@ -use crate::utils::{is_type_diagnostic_item, method_chain_args, return_ty, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{method_chain_args, return_ty}; use if_chain::if_chain; use rustc_hir as hir; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::{Expr, ImplItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::ty; @@ -66,9 +70,6 @@ impl<'tcx> LateLintPass<'tcx> for UnwrapInResult { } } -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::{Expr, ImplItemKind}; - struct FindExpectUnwrap<'a, 'tcx> { lcx: &'a LateContext<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, @@ -109,31 +110,27 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> { } fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) { - if_chain! { - - if let ImplItemKind::Fn(_, body_id) = impl_item.kind; - then { - let body = cx.tcx.hir().body(body_id); - let mut fpu = FindExpectUnwrap { - lcx: cx, - typeck_results: cx.tcx.typeck(impl_item.def_id), - result: Vec::new(), - }; - fpu.visit_expr(&body.value); + if let ImplItemKind::Fn(_, body_id) = impl_item.kind { + let body = cx.tcx.hir().body(body_id); + let mut fpu = FindExpectUnwrap { + lcx: cx, + typeck_results: cx.tcx.typeck(impl_item.def_id), + result: Vec::new(), + }; + fpu.visit_expr(&body.value); - // if we've found one, lint - if !fpu.result.is_empty() { - span_lint_and_then( - cx, - UNWRAP_IN_RESULT, - impl_span, - "used unwrap or expect in a function that returns result or option", - move |diag| { - diag.help( - "unwrap and expect should not be used in a function that returns result or option" ); - diag.span_note(fpu.result, "potential non-recoverable error(s)"); - }); - } + // if we've found one, lint + if !fpu.result.is_empty() { + span_lint_and_then( + cx, + UNWRAP_IN_RESULT, + impl_span, + "used unwrap or expect in a function that returns result or option", + move |diag| { + diag.help("unwrap and expect should not be used in a function that returns result or option"); + diag.span_note(fpu.result, "potential non-recoverable error(s)"); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 0470e1dbbb..4ac2ec55b9 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -1,7 +1,6 @@ -use crate::utils::span_lint_and_sugg; -use if_chain::if_chain; +use clippy_utils::diagnostics::span_lint_and_sugg; use itertools::Itertools; -use rustc_ast::ast::{Item, ItemKind, Variant}; +use rustc_ast::ast::{Item, ItemKind, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -81,7 +80,7 @@ fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) { // assume that two-letter words are some kind of valid abbreviation like FP for false positive // (and don't warn) if (ident.chars().all(|c| c.is_ascii_uppercase()) && ident.len() > 2) - // otherwise, warn if we have SOmeTHING lIKE THIs but only warn with the aggressive + // otherwise, warn if we have SOmeTHING lIKE THIs but only warn with the aggressive // upper-case-acronyms-aggressive config option enabled || (be_aggressive && ident != &corrected) { @@ -99,19 +98,21 @@ fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) { impl EarlyLintPass for UpperCaseAcronyms { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &Item) { - if_chain! { - if !in_external_macro(cx.sess(), it.span); + // do not lint public items or in macros + if !in_external_macro(cx.sess(), it.span) && !matches!(it.vis.kind, VisibilityKind::Public) { if matches!( it.kind, - ItemKind::TyAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..) - ); - then { + ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) + ) { check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive); + } else if let ItemKind::Enum(ref enumdef, _) = it.kind { + // check enum variants seperately because again we only want to lint on private enums and + // the fn check_variant does not know about the vis of the enum of its variants + enumdef + .variants + .iter() + .for_each(|variant| check_ident(cx, &variant.ident, self.upper_case_acronyms_aggressive)); } } } - - fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &Variant) { - check_ident(cx, &v.ident, self.upper_case_acronyms_aggressive); - } } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index f0523cec62..aa4d16633f 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -1,6 +1,7 @@ -use crate::utils::{in_macro, meets_msrv, snippet_opt, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use clippy_utils::{in_macro, meets_msrv, msrvs}; use if_chain::if_chain; - use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -61,8 +62,6 @@ pub struct UseSelf { stack: Vec<StackItem>, } -const USE_SELF_MSRV: RustcVersion = RustcVersion::new(1, 37, 0); - impl UseSelf { #[must_use] pub fn new(msrv: Option<RustcVersion>) -> Self { @@ -103,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { of_trait, .. }) => { - let should_check = if let TyKind::Path(QPath::Resolved(_, ref item_path)) = hir_self_ty.kind { + 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(_))) @@ -196,7 +195,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) { if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) { let mut visitor = SkipTyCollector::default(); - visitor.visit_ty(&impl_hir_ty); + visitor.visit_ty(impl_hir_ty); types_to_skip.extend(visitor.types_to_skip); } } @@ -235,7 +234,10 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } 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(), &USE_SELF_MSRV) { + if in_macro(hir_ty.span) + || in_impl(cx, hir_ty) + || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS) + { return; } @@ -287,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - if in_macro(expr.span) | !meets_msrv(self.msrv.as_ref(), &USE_SELF_MSRV) { + if in_macro(expr.span) || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS) { return; } @@ -332,7 +334,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { // unit enum variants (`Enum::A`) ExprKind::Path(qpath) => { if expr_ty_matches(cx, expr, self_ty) { - span_lint_on_qpath_resolved(cx, &qpath, true); + span_lint_on_qpath_resolved(cx, qpath, true); } }, _ => (), diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index c533485398..7edb280be7 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -1,8 +1,8 @@ -use crate::utils::sugg::Sugg; -use crate::utils::{ - get_parent_expr, is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet, - snippet_with_macro_callsite, span_lint_and_help, span_lint_and_sugg, -}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::source::{snippet, snippet_with_macro_callsite}; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{get_parent_expr, match_def_path, match_trait_method, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, HirId, MatchSource}; @@ -53,17 +53,17 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } match e.kind { - ExprKind::Match(_, ref arms, MatchSource::TryDesugar) => { + ExprKind::Match(_, arms, MatchSource::TryDesugar) => { let e = match arms[0].body.kind { - ExprKind::Ret(Some(ref e)) | ExprKind::Break(_, Some(ref e)) => e, + ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e)) => e, _ => return, }; - if let ExprKind::Call(_, ref args) = e.kind { + if let ExprKind::Call(_, args) = e.kind { self.try_desugar_arm.push(args[0].hir_id); } }, - ExprKind::MethodCall(ref name, .., ref args, _) => { + ExprKind::MethodCall(name, .., args, _) => { if match_trait_method(cx, e, &paths::INTO) && &*name.ident.as_str() == "into" { let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(&args[0]); @@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } if match_trait_method(cx, e, &paths::INTO_ITERATOR) && name.ident.name == sym::into_iter { if let Some(parent_expr) = get_parent_expr(cx, e) { - if let ExprKind::MethodCall(ref parent_name, ..) = parent_expr.kind { + if let ExprKind::MethodCall(parent_name, ..) = parent_expr.kind { if parent_name.ident.name != sym::into_iter { return; } @@ -103,38 +103,35 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { ); } } - if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into" { - if_chain! { - 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); - if let ty::Adt(_, substs) = a.kind(); - if let Some(a_type) = substs.types().next(); - if TyS::same_type(a_type, b); - - then { - span_lint_and_help( - cx, - USELESS_CONVERSION, - e.span, - &format!("useless conversion to the same type: `{}`", b), - None, - "consider removing `.try_into()`", - ); - } + if_chain! { + if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "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); + if let ty::Adt(_, substs) = a.kind(); + if let Some(a_type) = substs.types().next(); + if TyS::same_type(a_type, b); + then { + span_lint_and_help( + cx, + USELESS_CONVERSION, + e.span, + &format!("useless conversion to the same type: `{}`", b), + None, + "consider removing `.try_into()`", + ); } } }, - ExprKind::Call(ref path, ref args) => { + ExprKind::Call(path, args) => { if_chain! { if args.len() == 1; if let ExprKind::Path(ref qpath) = path.kind; if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); - let a = cx.typeck_results().expr_ty(e); - let b = cx.typeck_results().expr_ty(&args[0]); - then { + let a = cx.typeck_results().expr_ty(e); + let b = cx.typeck_results().expr_ty(&args[0]); if_chain! { if match_def_path(cx, def_id, &paths::TRY_FROM); if is_type_diagnostic_item(cx, a, sym::result_type); diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index c576148008..e70f8a09eb 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -1,7 +1,7 @@ //! A group of attributes that can be attached to Rust code in order //! to generate a clippy lint detecting said code automatically. -use crate::utils::get_attr; +use clippy_utils::get_attr; use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_ast::walk_list; use rustc_data_structures::fx::FxHashMap; @@ -203,13 +203,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { print!(" if let ExprKind::"); let current = format!("{}.kind", self.current); match expr.kind { - ExprKind::Box(ref inner) => { + ExprKind::Box(inner) => { let inner_pat = self.next("inner"); println!("Box(ref {}) = {};", inner_pat, current); self.current = inner_pat; self.visit_expr(inner); }, - ExprKind::Array(ref elements) => { + ExprKind::Array(elements) => { let elements_pat = self.next("elements"); println!("Array(ref {}) = {};", elements_pat, current); println!(" if {}.len() == {};", elements_pat, elements.len()); @@ -218,7 +218,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(element); } }, - ExprKind::Call(ref func, ref args) => { + ExprKind::Call(func, args) => { let func_pat = self.next("func"); let args_pat = self.next("args"); println!("Call(ref {}, ref {}) = {};", func_pat, args_pat, current); @@ -230,14 +230,14 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(arg); } }, - ExprKind::MethodCall(ref _method_name, ref _generics, ref _args, ref _fn_span) => { + ExprKind::MethodCall(_method_name, ref _generics, _args, ref _fn_span) => { println!( "MethodCall(ref method_name, ref generics, ref args, ref fn_span) = {};", current ); println!(" // unimplemented: `ExprKind::MethodCall` is not further destructured at the moment"); }, - ExprKind::Tup(ref elements) => { + ExprKind::Tup(elements) => { let elements_pat = self.next("elements"); println!("Tup(ref {}) = {};", elements_pat, current); println!(" if {}.len() == {};", elements_pat, elements.len()); @@ -246,7 +246,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.visit_expr(element); } }, - ExprKind::Binary(ref op, ref left, ref right) => { + ExprKind::Binary(ref op, left, right) => { let op_pat = self.next("op"); let left_pat = self.next("left"); let right_pat = self.next("right"); @@ -260,7 +260,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = right_pat; self.visit_expr(right); }, - ExprKind::Unary(ref op, ref inner) => { + ExprKind::Unary(ref op, inner) => { let inner_pat = self.next("inner"); println!("Unary(UnOp::{:?}, ref {}) = {};", op, inner_pat, current); self.current = inner_pat; @@ -296,7 +296,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, } }, - ExprKind::Cast(ref expr, ref ty) => { + ExprKind::Cast(expr, ty) => { let cast_pat = self.next("expr"); let cast_ty = self.next("cast_ty"); let qp_label = self.next("qp"); @@ -310,13 +310,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = cast_pat; self.visit_expr(expr); }, - ExprKind::Type(ref expr, ref _ty) => { + ExprKind::Type(expr, _ty) => { let cast_pat = self.next("expr"); println!("Type(ref {}, _) = {};", cast_pat, current); self.current = cast_pat; self.visit_expr(expr); }, - ExprKind::Loop(ref body, _, desugaring, _) => { + ExprKind::Loop(body, _, desugaring, _) => { let body_pat = self.next("body"); let des = loop_desugaring_name(desugaring); let label_pat = self.next("label"); @@ -324,10 +324,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = body_pat; self.visit_block(body); }, - ExprKind::If(ref cond, ref then, ref opt_else) => { + ExprKind::If(cond, then, ref opt_else) => { let cond_pat = self.next("cond"); let then_pat = self.next("then"); - if let Some(ref else_) = *opt_else { + if let Some(else_) = *opt_else { let else_pat = self.next("else_"); println!( "If(ref {}, ref {}, Some(ref {})) = {};", @@ -343,7 +343,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = then_pat; self.visit_expr(then); }, - ExprKind::Match(ref expr, ref arms, desugaring) => { + ExprKind::Match(expr, arms, desugaring) => { let des = desugaring_name(desugaring); let expr_pat = self.next("expr"); let arms_pat = self.next("arms"); @@ -353,18 +353,18 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!(" if {}.len() == {};", arms_pat, arms.len()); for (i, arm) in arms.iter().enumerate() { self.current = format!("{}[{}].body", arms_pat, i); - self.visit_expr(&arm.body); + self.visit_expr(arm.body); if let Some(ref guard) = arm.guard { let guard_pat = self.next("guard"); println!(" if let Some(ref {}) = {}[{}].guard;", guard_pat, arms_pat, i); match guard { - hir::Guard::If(ref if_expr) => { + hir::Guard::If(if_expr) => { let if_expr_pat = self.next("expr"); println!(" if let Guard::If(ref {}) = {};", if_expr_pat, guard_pat); self.current = if_expr_pat; self.visit_expr(if_expr); }, - hir::Guard::IfLet(ref if_let_pat, ref if_let_expr) => { + hir::Guard::IfLet(if_let_pat, if_let_expr) => { let if_let_pat_pat = self.next("pat"); let if_let_expr_pat = self.next("expr"); println!( @@ -379,26 +379,26 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } } self.current = format!("{}[{}].pat", arms_pat, i); - self.visit_pat(&arm.pat); + self.visit_pat(arm.pat); } }, - ExprKind::Closure(ref _capture_clause, ref _func, _, _, _) => { + ExprKind::Closure(ref _capture_clause, _func, _, _, _) => { println!("Closure(ref capture_clause, ref func, _, _, _) = {};", current); println!(" // unimplemented: `ExprKind::Closure` is not further destructured at the moment"); }, - ExprKind::Yield(ref sub, _) => { + ExprKind::Yield(sub, _) => { let sub_pat = self.next("sub"); println!("Yield(ref sub) = {};", current); self.current = sub_pat; self.visit_expr(sub); }, - ExprKind::Block(ref block, _) => { + ExprKind::Block(block, _) => { let block_pat = self.next("block"); println!("Block(ref {}) = {};", block_pat, current); self.current = block_pat; self.visit_block(block); }, - ExprKind::Assign(ref target, ref value, _) => { + ExprKind::Assign(target, value, _) => { let target_pat = self.next("target"); let value_pat = self.next("value"); println!( @@ -410,7 +410,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; self.visit_expr(value); }, - ExprKind::AssignOp(ref op, ref target, ref value) => { + ExprKind::AssignOp(ref op, target, value) => { let op_pat = self.next("op"); let target_pat = self.next("target"); let value_pat = self.next("value"); @@ -424,7 +424,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; self.visit_expr(value); }, - ExprKind::Field(ref object, ref field_ident) => { + ExprKind::Field(object, ref field_ident) => { let obj_pat = self.next("object"); let field_name_pat = self.next("field_name"); println!("Field(ref {}, ref {}) = {};", obj_pat, field_name_pat, current); @@ -432,7 +432,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = obj_pat; self.visit_expr(object); }, - ExprKind::Index(ref object, ref index) => { + ExprKind::Index(object, index) => { let object_pat = self.next("object"); let index_pat = self.next("index"); println!("Index(ref {}, ref {}) = {};", object_pat, index_pat, current); @@ -447,7 +447,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = path_pat; self.print_qpath(path); }, - ExprKind::AddrOf(kind, mutability, ref inner) => { + ExprKind::AddrOf(kind, mutability, inner) => { let inner_pat = self.next("inner"); println!( "AddrOf(BorrowKind::{:?}, Mutability::{:?}, ref {}) = {};", @@ -458,7 +458,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, ExprKind::Break(ref _destination, ref opt_value) => { let destination_pat = self.next("destination"); - if let Some(ref value) = *opt_value { + if let Some(value) = *opt_value { let value_pat = self.next("value"); println!("Break(ref {}, Some(ref {})) = {};", destination_pat, value_pat, current); self.current = value_pat; @@ -474,7 +474,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { // FIXME: implement label printing }, ExprKind::Ret(ref opt_value) => { - if let Some(ref value) = *opt_value { + if let Some(value) = *opt_value { let value_pat = self.next("value"); println!("Ret(Some(ref {})) = {};", value_pat, current); self.current = value_pat; @@ -491,10 +491,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("LlvmInlineAsm(_) = {};", current); println!(" // unimplemented: `ExprKind::LlvmInlineAsm` is not further destructured at the moment"); }, - ExprKind::Struct(ref path, ref fields, ref opt_base) => { + ExprKind::Struct(path, fields, ref opt_base) => { let path_pat = self.next("path"); let fields_pat = self.next("fields"); - if let Some(ref base) = *opt_base { + if let Some(base) = *opt_base { let base_pat = self.next("base"); println!( "Struct(ref {}, ref {}, Some(ref {})) = {};", @@ -516,7 +516,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = value_pat; }, // FIXME: compute length (needs type info) - ExprKind::Repeat(ref value, _) => { + ExprKind::Repeat(value, _) => { let value_pat = self.next("value"); println!("Repeat(ref {}, _) = {};", value_pat, current); println!("// unimplemented: repeat count check"); @@ -526,7 +526,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { ExprKind::Err => { println!("Err = {}", current); }, - ExprKind::DropTemps(ref expr) => { + ExprKind::DropTemps(expr) => { let expr_pat = self.next("expr"); println!("DropTemps(ref {}) = {};", expr_pat, current); self.current = expr_pat; @@ -560,7 +560,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { BindingAnnotation::RefMut => "BindingAnnotation::RefMut", }; let name_pat = self.next("name"); - if let Some(ref sub) = *sub { + if let Some(sub) = *sub { let sub_pat = self.next("sub"); println!( "Binding({}, _, {}, Some(ref {})) = {};", @@ -573,7 +573,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } println!(" if {}.as_str() == \"{}\";", name_pat, ident.as_str()); }, - PatKind::Struct(ref path, ref fields, ignore) => { + PatKind::Struct(ref path, fields, ignore) => { let path_pat = self.next("path"); let fields_pat = self.next("fields"); println!( @@ -585,13 +585,13 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); }, - PatKind::Or(ref fields) => { + PatKind::Or(fields) => { let fields_pat = self.next("fields"); println!("Or(ref {}) = {};", fields_pat, current); println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); }, - PatKind::TupleStruct(ref path, ref fields, skip_pos) => { + PatKind::TupleStruct(ref path, fields, skip_pos) => { let path_pat = self.next("path"); let fields_pat = self.next("fields"); println!( @@ -609,25 +609,25 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = path_pat; self.print_qpath(path); }, - PatKind::Tuple(ref fields, skip_pos) => { + PatKind::Tuple(fields, skip_pos) => { let fields_pat = self.next("fields"); println!("Tuple(ref {}, {:?}) = {};", fields_pat, skip_pos, current); println!(" if {}.len() == {};", fields_pat, fields.len()); println!(" // unimplemented: field checks"); }, - PatKind::Box(ref pat) => { + PatKind::Box(pat) => { let pat_pat = self.next("pat"); println!("Box(ref {}) = {};", pat_pat, current); self.current = pat_pat; self.visit_pat(pat); }, - PatKind::Ref(ref pat, muta) => { + PatKind::Ref(pat, muta) => { let pat_pat = self.next("pat"); println!("Ref(ref {}, Mutability::{:?}) = {};", pat_pat, muta, current); self.current = pat_pat; self.visit_pat(pat); }, - PatKind::Lit(ref lit_expr) => { + PatKind::Lit(lit_expr) => { let lit_expr_pat = self.next("lit_expr"); println!("Lit(ref {}) = {}", lit_expr_pat, current); self.current = lit_expr_pat; @@ -645,10 +645,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = end_pat; walk_list!(self, visit_expr, end); }, - PatKind::Slice(ref start, ref middle, ref end) => { + PatKind::Slice(start, ref middle, end) => { let start_pat = self.next("start"); let end_pat = self.next("end"); - if let Some(ref middle) = middle { + if let Some(middle) = middle { let middle_pat = self.next("middle"); println!( "Slice(ref {}, Some(ref {}), ref {}) = {};", @@ -678,17 +678,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { let current = format!("{}.kind", self.current); match s.kind { // A local (let) binding: - StmtKind::Local(ref local) => { + StmtKind::Local(local) => { let local_pat = self.next("local"); println!("Local(ref {}) = {};", local_pat, current); - if let Some(ref init) = local.init { + if let Some(init) = local.init { let init_pat = self.next("init"); println!(" if let Some(ref {}) = {}.init;", init_pat, local_pat); self.current = init_pat; self.visit_expr(init); } self.current = format!("{}.pat", local_pat); - self.visit_pat(&local.pat); + self.visit_pat(local.pat); }, // An item binding: StmtKind::Item(_) => { @@ -696,7 +696,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, // Expr without trailing semi-colon (must have unit type): - StmtKind::Expr(ref e) => { + StmtKind::Expr(e) => { let e_pat = self.next("e"); println!("Expr(ref {}, _) = {}", e_pat, current); self.current = e_pat; @@ -704,7 +704,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { }, // Expr with trailing semi-colon (may have any type): - StmtKind::Semi(ref e) => { + StmtKind::Semi(e) => { let e_pat = self.next("e"); println!("Semi(ref {}, _) = {}", e_pat, current); self.current = e_pat; @@ -752,7 +752,7 @@ fn loop_desugaring_name(des: hir::LoopSource) -> &'static str { fn print_path(path: &QPath<'_>, first: &mut bool) { match *path { - QPath::Resolved(_, ref path) => { + QPath::Resolved(_, path) => { for segment in path.segments { if *first { *first = false; @@ -762,7 +762,7 @@ fn print_path(path: &QPath<'_>, first: &mut bool) { print!("{:?}", segment.ident.as_str()); } }, - QPath::TypeRelative(ref ty, ref segment) => match ty.kind { + QPath::TypeRelative(ty, segment) => match ty.kind { hir::TyKind::Path(ref inner_path) => { print_path(inner_path, first); if *first { diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 9139a0966c..d56855a71c 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -106,7 +106,7 @@ macro_rules! define_Conf { pub use self::helpers::Conf; define_Conf! { - /// Lint: REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN. The minimum rust version that the project supports + /// Lint: CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR. The minimum rust version that the project supports (msrv, "msrv": Option<String>, None), /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses (blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()), diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index 64ee9e65bb..4665eeeff7 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -1,6 +1,6 @@ //! checks for attributes -use crate::utils::get_attr; +use clippy_utils::get_attr; use rustc_ast::ast::{Attribute, InlineAsmTemplatePiece}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector { match item.vis.node { hir::VisibilityKind::Public => println!("public"), hir::VisibilityKind::Crate(_) => println!("visible crate wide"), - hir::VisibilityKind::Restricted { ref path, .. } => println!( + hir::VisibilityKind::Restricted { path, .. } => println!( "visible in module `{}`", rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false)) ), @@ -99,13 +99,13 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector { if !has_attr(cx.sess(), cx.tcx.hir().attrs(arm.hir_id)) { return; } - print_pat(cx, &arm.pat, 1); + print_pat(cx, arm.pat, 1); if let Some(ref guard) = arm.guard { println!("guard:"); print_guard(cx, guard, 1); } println!("body:"); - print_expr(cx, &arm.body, 1); + print_expr(cx, arm.body, 1); } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) { @@ -113,17 +113,17 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector { return; } match stmt.kind { - hir::StmtKind::Local(ref local) => { + hir::StmtKind::Local(local) => { println!("local variable of type {}", cx.typeck_results().node_type(local.hir_id)); println!("pattern:"); - print_pat(cx, &local.pat, 0); - if let Some(ref e) = local.init { + print_pat(cx, local.pat, 0); + if let Some(e) = local.init { println!("init expression:"); print_expr(cx, e, 0); } }, hir::StmtKind::Item(_) => println!("item decl"), - hir::StmtKind::Expr(ref e) | hir::StmtKind::Semi(ref e) => print_expr(cx, e, 0), + hir::StmtKind::Expr(e) | hir::StmtKind::Semi(e) => print_expr(cx, e, 0), } } // fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx @@ -151,7 +151,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { cx.typeck_results().adjustments().get(expr.hir_id) ); match expr.kind { - hir::ExprKind::Box(ref e) => { + hir::ExprKind::Box(e) => { println!("{}Box", ind); print_expr(cx, e, indent + 1); }, @@ -161,7 +161,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, e, indent + 1); } }, - hir::ExprKind::Call(ref func, args) => { + hir::ExprKind::Call(func, args) => { println!("{}Call", ind); println!("{}function:", ind); print_expr(cx, func, indent + 1); @@ -170,7 +170,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, arg, indent + 1); } }, - hir::ExprKind::MethodCall(ref path, _, args, _) => { + hir::ExprKind::MethodCall(path, _, args, _) => { println!("{}MethodCall", ind); println!("{}method name: {}", ind, path.ident.name); for arg in args { @@ -183,7 +183,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, e, indent + 1); } }, - hir::ExprKind::Binary(op, ref lhs, ref rhs) => { + hir::ExprKind::Binary(op, lhs, rhs) => { println!("{}Binary", ind); println!("{}op: {:?}", ind, op.node); println!("{}lhs:", ind); @@ -191,7 +191,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprKind::Unary(op, ref inner) => { + hir::ExprKind::Unary(op, inner) => { println!("{}Unary", ind); println!("{}op: {:?}", ind, op); print_expr(cx, inner, indent + 1); @@ -200,12 +200,12 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}Lit", ind); println!("{}{:?}", ind, lit); }, - hir::ExprKind::Cast(ref e, ref target) => { + hir::ExprKind::Cast(e, target) => { println!("{}Cast", ind); print_expr(cx, e, indent + 1); println!("{}target type: {:?}", ind, target); }, - hir::ExprKind::Type(ref e, ref target) => { + hir::ExprKind::Type(e, target) => { println!("{}Type", ind); print_expr(cx, e, indent + 1); println!("{}target type: {:?}", ind, target); @@ -213,16 +213,16 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { hir::ExprKind::Loop(..) => { println!("{}Loop", ind); }, - hir::ExprKind::If(ref cond, _, ref else_opt) => { + hir::ExprKind::If(cond, _, ref else_opt) => { println!("{}If", ind); println!("{}condition:", ind); print_expr(cx, cond, indent + 1); - if let Some(ref els) = *else_opt { + if let Some(els) = *else_opt { println!("{}else:", ind); print_expr(cx, els, indent + 1); } }, - hir::ExprKind::Match(ref cond, _, ref source) => { + hir::ExprKind::Match(cond, _, ref source) => { println!("{}Match", ind); println!("{}condition:", ind); print_expr(cx, cond, indent + 1); @@ -232,21 +232,21 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}Closure", ind); println!("{}clause: {:?}", ind, clause); }, - hir::ExprKind::Yield(ref sub, _) => { + hir::ExprKind::Yield(sub, _) => { println!("{}Yield", ind); print_expr(cx, sub, indent + 1); }, hir::ExprKind::Block(_, _) => { println!("{}Block", ind); }, - hir::ExprKind::Assign(ref lhs, ref rhs, _) => { + hir::ExprKind::Assign(lhs, rhs, _) => { println!("{}Assign", ind); println!("{}lhs:", ind); print_expr(cx, lhs, indent + 1); println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprKind::AssignOp(ref binop, ref lhs, ref rhs) => { + hir::ExprKind::AssignOp(ref binop, lhs, rhs) => { println!("{}AssignOp", ind); println!("{}op: {:?}", ind, binop.node); println!("{}lhs:", ind); @@ -254,31 +254,31 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}rhs:", ind); print_expr(cx, rhs, indent + 1); }, - hir::ExprKind::Field(ref e, ident) => { + hir::ExprKind::Field(e, ident) => { println!("{}Field", ind); println!("{}field name: {}", ind, ident.name); println!("{}struct expr:", ind); print_expr(cx, e, indent + 1); }, - hir::ExprKind::Index(ref arr, ref idx) => { + hir::ExprKind::Index(arr, idx) => { println!("{}Index", ind); println!("{}array expr:", ind); print_expr(cx, arr, indent + 1); println!("{}index expr:", ind); print_expr(cx, idx, indent + 1); }, - hir::ExprKind::Path(hir::QPath::Resolved(ref ty, ref path)) => { + hir::ExprKind::Path(hir::QPath::Resolved(ref ty, path)) => { println!("{}Resolved Path, {:?}", ind, ty); println!("{}path: {:?}", ind, path); }, - hir::ExprKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => { + hir::ExprKind::Path(hir::QPath::TypeRelative(ty, seg)) => { println!("{}Relative Path, {:?}", ind, ty); println!("{}seg: {:?}", ind, seg); }, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, ..)) => { println!("{}Lang Item Path, {:?}", ind, lang_item.name()); }, - hir::ExprKind::AddrOf(kind, ref muta, ref e) => { + hir::ExprKind::AddrOf(kind, ref muta, e) => { println!("{}AddrOf", ind); println!("kind: {:?}", kind); println!("mutability: {:?}", muta); @@ -286,18 +286,18 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { }, hir::ExprKind::Break(_, ref e) => { println!("{}Break", ind); - if let Some(ref e) = *e { + if let Some(e) = *e { print_expr(cx, e, indent + 1); } }, hir::ExprKind::Continue(_) => println!("{}Again", ind), hir::ExprKind::Ret(ref e) => { println!("{}Ret", ind); - if let Some(ref e) = *e { + if let Some(e) = *e { print_expr(cx, e, indent + 1); } }, - hir::ExprKind::InlineAsm(ref asm) => { + hir::ExprKind::InlineAsm(asm) => { println!("{}InlineAsm", ind); println!("{}template: {}", ind, InlineAsmTemplatePiece::to_string(asm.template)); println!("{}options: {:?}", ind, asm.options); @@ -306,7 +306,6 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { match op { hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::InOut { expr, .. } - | hir::InlineAsmOperand::Const { expr } | hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1), hir::InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { @@ -319,10 +318,14 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, out_expr, indent + 1); } }, + hir::InlineAsmOperand::Const { anon_const } => { + println!("{}anon_const:", ind); + print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1); + }, } } }, - hir::ExprKind::LlvmInlineAsm(ref asm) => { + hir::ExprKind::LlvmInlineAsm(asm) => { let inputs = &asm.inputs_exprs; let outputs = &asm.outputs_exprs; println!("{}LlvmInlineAsm", ind); @@ -335,14 +338,14 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, e, indent + 1); } }, - hir::ExprKind::Struct(ref path, fields, ref base) => { + hir::ExprKind::Struct(path, fields, ref base) => { println!("{}Struct", ind); println!("{}path: {:?}", ind, path); for field in fields { println!("{}field \"{}\":", ind, field.ident.name); - print_expr(cx, &field.expr, indent + 1); + print_expr(cx, field.expr, indent + 1); } - if let Some(ref base) = *base { + if let Some(base) = *base { println!("{}base:", ind); print_expr(cx, base, indent + 1); } @@ -352,7 +355,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { println!("{}anon_const:", ind); print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1); }, - hir::ExprKind::Repeat(ref val, ref anon_const) => { + hir::ExprKind::Repeat(val, ref anon_const) => { println!("{}Repeat", ind); println!("{}value:", ind); print_expr(cx, val, indent + 1); @@ -362,7 +365,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { hir::ExprKind::Err => { println!("{}Err", ind); }, - hir::ExprKind::DropTemps(ref e) => { + hir::ExprKind::DropTemps(e) => { println!("{}DropTemps", ind); print_expr(cx, e, indent + 1); }, @@ -375,7 +378,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) { match item.vis.node { hir::VisibilityKind::Public => println!("public"), hir::VisibilityKind::Crate(_) => println!("visible crate wide"), - hir::VisibilityKind::Restricted { ref path, .. } => println!( + hir::VisibilityKind::Restricted { path, .. } => println!( "visible in module `{}`", rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false)) ), @@ -395,7 +398,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) { println!("weird extern crate without a crate id"); } }, - hir::ItemKind::Use(ref path, ref kind) => println!("{:?}, {:?}", path, kind), + hir::ItemKind::Use(path, ref kind) => println!("{:?}, {:?}", path, kind), hir::ItemKind::Static(..) => println!("static item of type {:#?}", cx.tcx.type_of(did)), hir::ItemKind::Const(..) => println!("const item of type {:#?}", cx.tcx.type_of(did)), hir::ItemKind::Fn(..) => { @@ -404,7 +407,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) { }, hir::ItemKind::Mod(..) => println!("module"), hir::ItemKind::ForeignMod { abi, .. } => println!("foreign module with abi: {}", abi), - hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm), + hir::ItemKind::GlobalAsm(asm) => println!("global asm: {:?}", asm), hir::ItemKind::TyAlias(..) => { println!("type alias for {:?}", cx.tcx.type_of(did)); }, @@ -454,7 +457,7 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) { println!("{}Binding", ind); println!("{}mode: {:?}", ind, mode); println!("{}name: {}", ind, ident.name); - if let Some(ref inner) = *inner { + if let Some(inner) = *inner { println!("{}inner:", ind); print_pat(cx, inner, indent + 1); } @@ -479,7 +482,7 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) { if field.is_shorthand { println!("{} in shorthand notation", ind); } - print_pat(cx, &field.pat, indent + 1); + print_pat(cx, field.pat, indent + 1); } }, hir::PatKind::TupleStruct(ref path, fields, opt_dots_position) => { @@ -496,11 +499,11 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) { print_pat(cx, field, indent + 1); } }, - hir::PatKind::Path(hir::QPath::Resolved(ref ty, ref path)) => { + hir::PatKind::Path(hir::QPath::Resolved(ref ty, path)) => { println!("{}Resolved Path, {:?}", ind, ty); println!("{}path: {:?}", ind, path); }, - hir::PatKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => { + hir::PatKind::Path(hir::QPath::TypeRelative(ty, seg)) => { println!("{}Relative Path, {:?}", ind, ty); println!("{}seg: {:?}", ind, seg); }, @@ -516,16 +519,16 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) { print_pat(cx, field, indent + 1); } }, - hir::PatKind::Box(ref inner) => { + hir::PatKind::Box(inner) => { println!("{}Box", ind); print_pat(cx, inner, indent + 1); }, - hir::PatKind::Ref(ref inner, ref muta) => { + hir::PatKind::Ref(inner, ref muta) => { println!("{}Ref", ind); println!("{}mutability: {:?}", ind, muta); print_pat(cx, inner, indent + 1); }, - hir::PatKind::Lit(ref e) => { + hir::PatKind::Lit(e) => { println!("{}Lit", ind); print_expr(cx, e, indent + 1); }, @@ -549,7 +552,7 @@ fn print_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, indent: usize) { print_pat(cx, pat, indent + 1); } println!("i:"); - if let Some(ref pat) = *range { + if let Some(pat) = *range { print_pat(cx, pat, indent + 1); } println!("[y, z]:"); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index 0a347516c3..3d3d0e19d2 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -1,7 +1,10 @@ use crate::consts::{constant_simple, Constant}; -use crate::utils::{ - is_expn_of, match_def_path, match_qpath, match_type, method_calls, path_to_res, paths, run_lints, snippet, - span_lint, span_lint_and_help, span_lint_and_sugg, SpanlessEq, +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +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, }; use if_chain::if_chain; use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, ModKind, NodeId}; @@ -14,15 +17,17 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::{ - BinOpKind, Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Node, Path, StmtKind, Ty, TyKind, UnOp, + BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MatchSource, MutTy, Mutability, Node, Path, Stmt, + StmtKind, Ty, TyKind, UnOp, }; -use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; -use rustc_span::source_map::{Span, Spanned}; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{Symbol, SymbolStr}; +use rustc_span::{BytePos, Span}; use rustc_typeck::hir_ty_to_ty; use std::borrow::{Borrow, Cow}; @@ -297,6 +302,13 @@ declare_clippy_lint! { "unnecessary conversion between Symbol and string" } +declare_clippy_lint! { + /// Finds unidiomatic usage of `if_chain!` + pub IF_CHAIN_STYLE, + internal, + "non-idiomatic `if_chain!` usage" +} + declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]); impl EarlyLintPass for ClippyLintsInternal { @@ -342,12 +354,12 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { return; } - if let hir::ItemKind::Static(ref ty, Mutability::Not, body_id) = item.kind { + if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind { if is_lint_ref_type(cx, ty) { let expr = &cx.tcx.hir().body(body_id).value; if_chain! { - if let ExprKind::AddrOf(_, _, ref inner_exp) = expr.kind; - if let ExprKind::Struct(_, ref fields, _) = inner_exp.kind; + if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind; + if let ExprKind::Struct(_, fields, _) = inner_exp.kind; let field = fields .iter() .find(|f| f.ident.as_str() == "desc") @@ -374,7 +386,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { { if let hir::ItemKind::Impl(hir::Impl { of_trait: None, - items: ref impl_item_refs, + items: impl_item_refs, .. }) = item.kind { @@ -426,7 +438,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &Ty<'_>) -> bool { if let TyKind::Rptr( _, MutTy { - ty: ref inner, + ty: inner, mutbl: Mutability::Not, }, ) = ty.kind @@ -487,7 +499,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions { } if_chain! { - if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind; + if let ExprKind::MethodCall(path, _, args, _) = expr.kind; let fn_name = path.ident; if let Some(sugg) = self.map.get(&*fn_name.as_str()); let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs(); @@ -566,9 +578,8 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { } if_chain! { - if let ExprKind::Call(ref func, ref and_then_args) = expr.kind; - if let ExprKind::Path(ref path) = func.kind; - if match_qpath(path, &["span_lint_and_then"]); + if let ExprKind::Call(func, and_then_args) = expr.kind; + if is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]); if and_then_args.len() == 5; if let ExprKind::Closure(_, _, body_id, _, _) = &and_then_args[4].kind; let body = cx.tcx.hir().body(*body_id); @@ -576,10 +587,10 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { let stmts = &block.stmts; if stmts.len() == 1 && block.expr.is_none(); if let StmtKind::Semi(only_expr) = &stmts[0].kind; - if let ExprKind::MethodCall(ref ps, _, ref span_call_args, _) = &only_expr.kind; - let and_then_snippets = get_and_then_snippets(cx, and_then_args); - let mut sle = SpanlessEq::new(cx).deny_side_effects(); + if let ExprKind::MethodCall(ps, _, span_call_args, _) = &only_expr.kind; then { + let and_then_snippets = get_and_then_snippets(cx, and_then_args); + let mut sle = SpanlessEq::new(cx).deny_side_effects(); match &*ps.ident.as_str() { "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => { suggest_suggestion(cx, expr, &and_then_snippets, &span_suggestion_snippets(cx, span_call_args)); @@ -750,8 +761,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem { if_chain! { // Check if this is a call to utils::match_type() if let ExprKind::Call(fn_path, [context, ty, ty_path]) = expr.kind; - if let ExprKind::Path(fn_qpath) = &fn_path.kind; - if match_qpath(&fn_qpath, &["utils", "match_type"]); + if is_expr_path_def_path(cx, fn_path, &["clippy_utils", "ty", "match_type"]); // Extract the path to the matched type if let Some(segments) = path_to_matched_type(cx, ty_path); let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect(); @@ -760,6 +770,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem { let diag_items = cx.tcx.diagnostic_items(ty_did.krate); if let Some(item_name) = diag_items.iter().find_map(|(k, v)| if *v == ty_did { Some(k) } else { None }); then { + // TODO: check paths constants from external crates. let cx_snippet = snippet(cx, context.span, "_"); let ty_snippet = snippet(cx, ty.span, "_"); @@ -767,9 +778,9 @@ impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem { cx, MATCH_TYPE_ON_DIAGNOSTIC_ITEM, expr.span, - "usage of `utils::match_type()` on a type diagnostic item", + "usage of `clippy_utils::ty::match_type()` on a type diagnostic item", "try", - format!("utils::is_type_diagnostic_item({}, {}, sym::{})", cx_snippet, ty_snippet, item_name), + format!("clippy_utils::ty::is_type_diagnostic_item({}, {}, sym::{})", cx_snippet, ty_snippet, item_name), Applicability::MaybeIncorrect, ); } @@ -1063,3 +1074,159 @@ impl<'tcx> SymbolStrExpr<'tcx> { } } } + +declare_lint_pass!(IfChainStyle => [IF_CHAIN_STYLE]); + +impl<'tcx> LateLintPass<'tcx> for IfChainStyle { + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { + let (local, after, if_chain_span) = if_chain! { + if let [Stmt { kind: StmtKind::Local(local), .. }, after @ ..] = block.stmts; + if let Some(if_chain_span) = is_expn_of(block.span, "if_chain"); + then { (local, after, if_chain_span) } else { return } + }; + if is_first_if_chain_expr(cx, block.hir_id, if_chain_span) { + span_lint( + cx, + IF_CHAIN_STYLE, + if_chain_local_span(cx, local, if_chain_span), + "`let` expression should be above the `if_chain!`", + ); + } else if local.span.ctxt() == block.span.ctxt() && is_if_chain_then(after, block.expr, if_chain_span) { + span_lint( + cx, + IF_CHAIN_STYLE, + if_chain_local_span(cx, local, if_chain_span), + "`let` expression should be inside `then { .. }`", + ) + } + } + + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + let (cond, then, els) = match expr.kind { + ExprKind::If(cond, then, els) => (Some(cond), then, els.is_some()), + ExprKind::Match( + _, + [arm, ..], + MatchSource::IfLetDesugar { + contains_else_clause: els, + }, + ) => (None, arm.body, els), + _ => return, + }; + let then_block = match then.kind { + ExprKind::Block(block, _) => block, + _ => return, + }; + let if_chain_span = is_expn_of(expr.span, "if_chain"); + if !els { + check_nested_if_chains(cx, expr, then_block, if_chain_span); + } + let if_chain_span = match if_chain_span { + None => return, + Some(span) => span, + }; + // check for `if a && b;` + if_chain! { + if let Some(cond) = cond; + if let ExprKind::Binary(op, _, _) = cond.kind; + if op.node == BinOpKind::And; + if cx.sess().source_map().is_multiline(cond.span); + then { + span_lint(cx, IF_CHAIN_STYLE, cond.span, "`if a && b;` should be `if a; if b;`"); + } + } + if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span) + && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span) + { + span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`") + } + } +} + +fn check_nested_if_chains( + cx: &LateContext<'_>, + if_expr: &Expr<'_>, + then_block: &Block<'_>, + if_chain_span: Option<Span>, +) { + #[rustfmt::skip] + let (head, tail) = match *then_block { + Block { stmts, expr: Some(tail), .. } => (stmts, tail), + Block { + stmts: &[ + ref head @ .., + Stmt { kind: StmtKind::Expr(tail) | StmtKind::Semi(tail), .. } + ], + .. + } => (head, tail), + _ => return, + }; + if_chain! { + if matches!(tail.kind, + ExprKind::If(_, _, None) + | ExprKind::Match(.., MatchSource::IfLetDesugar { contains_else_clause: false })); + let sm = cx.sess().source_map(); + if head + .iter() + .all(|stmt| matches!(stmt.kind, StmtKind::Local(..)) && !sm.is_multiline(stmt.span)); + if if_chain_span.is_some() || !is_else_clause(cx.tcx, if_expr); + then {} else { return } + } + let (span, msg) = match (if_chain_span, is_expn_of(tail.span, "if_chain")) { + (None, Some(_)) => (if_expr.span, "this `if` can be part of the inner `if_chain!`"), + (Some(_), None) => (tail.span, "this `if` can be part of the outer `if_chain!`"), + (Some(a), Some(b)) if a != b => (b, "this `if_chain!` can be merged with the outer `if_chain!`"), + _ => return, + }; + span_lint_and_then(cx, IF_CHAIN_STYLE, span, msg, |diag| { + let (span, msg) = match head { + [] => return, + [stmt] => (stmt.span, "this `let` statement can also be in the `if_chain!`"), + [a, .., b] => ( + a.span.to(b.span), + "these `let` statements can also be in the `if_chain!`", + ), + }; + diag.span_help(span, msg); + }); +} + +fn is_first_if_chain_expr(cx: &LateContext<'_>, hir_id: HirId, if_chain_span: Span) -> bool { + cx.tcx + .hir() + .parent_iter(hir_id) + .find(|(_, node)| { + #[rustfmt::skip] + !matches!(node, Node::Expr(Expr { kind: ExprKind::Block(..), .. }) | Node::Stmt(_)) + }) + .map_or(false, |(id, _)| { + is_expn_of(cx.tcx.hir().span(id), "if_chain") != Some(if_chain_span) + }) +} + +/// Checks a trailing slice of statements and expression of a `Block` to see if they are part +/// of the `then {..}` portion of an `if_chain!` +fn is_if_chain_then(stmts: &[Stmt<'_>], expr: Option<&Expr<'_>>, if_chain_span: Span) -> bool { + let span = if let [stmt, ..] = stmts { + stmt.span + } else if let Some(expr) = expr { + expr.span + } else { + // empty `then {}` + return true; + }; + is_expn_of(span, "if_chain").map_or(true, |span| span != if_chain_span) +} + +/// Creates a `Span` for `let x = ..;` in an `if_chain!` call. +fn if_chain_local_span(cx: &LateContext<'_>, local: &Local<'_>, if_chain_span: Span) -> Span { + let mut span = local.pat.span; + if let Some(init) = local.init { + span = span.to(init.span); + } + span.adjust(if_chain_span.ctxt().outer_expn()); + let sm = cx.sess().source_map(); + let span = sm.span_extend_to_prev_str(span, "let", false); + let span = sm.span_extend_to_next_char(span, ';', false); + Span::new(span.lo() - BytePos(3), span.hi() + BytePos(1), span.ctxt()) +} diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index be9a07f8d7..d8b31344e6 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -3,5 +3,3 @@ pub mod conf; pub mod inspector; #[cfg(feature = "internal-lints")] pub mod internal_lints; - -pub use clippy_utils::*; diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index c132e4de4f..febd4b6ff7 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -1,9 +1,12 @@ use crate::consts::{constant, Constant}; use crate::rustc_target::abi::LayoutOf; -use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::higher; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_copy; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind}; +use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -46,10 +49,10 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { if_chain! { if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(expr).kind(); if let ty::Slice(..) = ty.kind(); - if let ExprKind::AddrOf(BorrowKind::Ref, _, ref addressee) = expr.kind; + if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind; if let Some(vec_args) = higher::vec_macro(cx, addressee); then { - self.check_vec_macro(cx, &vec_args, expr.span); + self.check_vec_macro(cx, &vec_args, mutability, expr.span); } } @@ -67,14 +70,20 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { .ctxt() .outer_expn_data() .call_site; - self.check_vec_macro(cx, &vec_args, span); + self.check_vec_macro(cx, &vec_args, Mutability::Not, span); } } } } impl UselessVec { - fn check_vec_macro<'tcx>(self, cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) { + fn check_vec_macro<'tcx>( + self, + cx: &LateContext<'tcx>, + vec_args: &higher::VecArgs<'tcx>, + mutability: Mutability, + span: Span, + ) { let mut applicability = Applicability::MachineApplicable; let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { @@ -84,11 +93,22 @@ impl UselessVec { return; } - format!( - "&[{}; {}]", - snippet_with_applicability(cx, elem.span, "elem", &mut applicability), - snippet_with_applicability(cx, len.span, "len", &mut applicability) - ) + match mutability { + Mutability::Mut => { + format!( + "&mut [{}; {}]", + snippet_with_applicability(cx, elem.span, "elem", &mut applicability), + snippet_with_applicability(cx, len.span, "len", &mut applicability) + ) + }, + Mutability::Not => { + format!( + "&[{}; {}]", + snippet_with_applicability(cx, elem.span, "elem", &mut applicability), + snippet_with_applicability(cx, len.span, "len", &mut applicability) + ) + }, + } } else { return; } @@ -101,9 +121,22 @@ impl UselessVec { } let span = args[0].span.to(last.span); - format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) + match mutability { + Mutability::Mut => { + format!( + "&mut [{}]", + snippet_with_applicability(cx, span, "..", &mut applicability) + ) + }, + Mutability::Not => { + format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) + }, + } } else { - "&[]".into() + match mutability { + Mutability::Mut => "&mut []".into(), + Mutability::Not => "&[]".into(), + } } }, }; diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs index 8d111f98ad..c7190e2f97 100644 --- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs @@ -1,6 +1,7 @@ -use crate::utils::{ - is_type_diagnostic_item, match_def_path, path_to_local, path_to_local_id, paths, snippet, span_lint_and_sugg, -}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{match_def_path, path_to_local, path_to_local_id, paths}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -107,22 +108,21 @@ impl LateLintPass<'_> for VecInitThenPush { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if self.searcher.is_none() { - if_chain! { - if !in_external_macro(cx.sess(), expr.span); - if let ExprKind::Assign(left, right, _) = expr.kind; - if let Some(id) = path_to_local(left); - if let Some(init_kind) = get_vec_init_kind(cx, right); - then { - self.searcher = Some(VecPushSearcher { - local_id: id, - init: init_kind, - lhs_is_local: false, - lhs_span: left.span, - err_span: expr.span, - found: 0, - }); - } + if_chain! { + if self.searcher.is_none(); + if !in_external_macro(cx.sess(), expr.span); + if let ExprKind::Assign(left, right, _) = expr.kind; + if let Some(id) = path_to_local(left); + if let Some(init_kind) = get_vec_init_kind(cx, right); + then { + self.searcher = Some(VecPushSearcher { + local_id: id, + init: init_kind, + lhs_is_local: false, + lhs_span: left.span, + err_span: expr.span, + found: 0, + }); } } } diff --git a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs index d2494b321e..5540e87405 100644 --- a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs +++ b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs @@ -1,15 +1,14 @@ -use crate::utils::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; +use rustc_ast::LitKind; use rustc_errors::Applicability; +use rustc_hir as hir; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use crate::utils::{match_def_path, paths}; -use rustc_ast::LitKind; -use rustc_hir as hir; - declare_clippy_lint! { /// **What it does:** Finds occurrences of `Vec::resize(0, an_int)` /// @@ -31,7 +30,7 @@ declare_lint_pass!(VecResizeToZero => [VEC_RESIZE_TO_ZERO]); impl<'tcx> LateLintPass<'tcx> for VecResizeToZero { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let hir::ExprKind::MethodCall(path_segment, _, ref args, _) = expr.kind; + if let hir::ExprKind::MethodCall(path_segment, _, args, _) = expr.kind; if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if match_def_path(cx, method_def_id, &paths::VEC_RESIZE) && args.len() == 3; if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = args[1].kind; diff --git a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs index 32574d9d6c..ec209b3095 100644 --- a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs +++ b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs @@ -1,4 +1,6 @@ -use crate::utils::{match_type, paths, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::paths; +use clippy_utils::ty::match_type; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs index cd1864f461..60c3489a44 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs @@ -1,4 +1,5 @@ -use crate::utils::{run_lints, span_lint}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::run_lints; use rustc_hir::{hir_id::CRATE_HIR_ID, Crate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 094b1a4234..51c1117d20 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -1,4 +1,6 @@ -use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; +use clippy_utils::source::{snippet, snippet_with_applicability}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 553e6b000e..7e962472c0 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -1,20 +1,19 @@ use std::borrow::Cow; -use std::ops::Range; - -use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then}; -use if_chain::if_chain; -use rustc_ast::ast::{ - Expr, ExprKind, ImplKind, Item, ItemKind, LitKind, MacCall, StrLit, StrStyle, -}; -use rustc_ast::token; +use std::iter; +use std::ops::{Deref, Range}; + +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::{snippet_opt, snippet_with_applicability}; +use rustc_ast::ast::{Expr, ExprKind, ImplKind, Item, ItemKind, MacCall, Path, StrLit, StrStyle}; +use rustc_ast::token::{self, LitKind}; use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; use rustc_lexer::unescape::{self, EscapeError}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_parse::parser; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::symbol::kw; -use rustc_span::{sym, BytePos, Span}; +use rustc_span::symbol::{kw, Symbol}; +use rustc_span::{sym, BytePos, Span, DUMMY_SP}; declare_clippy_lint! { /// **What it does:** This lint warns when you use `println!("")` to @@ -355,7 +354,120 @@ fn newline_span(fmtstr: &StrLit) -> Span { sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi) } +/// Stores a list of replacement spans for each argument, but only if all the replacements used an +/// empty format string. +#[derive(Default)] +struct SimpleFormatArgs { + unnamed: Vec<Vec<Span>>, + named: Vec<(Symbol, Vec<Span>)>, +} +impl SimpleFormatArgs { + fn get_unnamed(&self) -> impl Iterator<Item = &[Span]> { + self.unnamed.iter().map(|x| match x.as_slice() { + // Ignore the dummy span added from out of order format arguments. + [DUMMY_SP] => &[], + x => x, + }) + } + + fn get_named(&self, n: &Path) -> &[Span] { + self.named.iter().find(|x| *n == x.0).map_or(&[], |x| x.1.as_slice()) + } + + fn push(&mut self, arg: rustc_parse_format::Argument<'_>, span: Span) { + use rustc_parse_format::{ + AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, + }; + + const SIMPLE: FormatSpec<'_> = FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + precision_span: None, + width: CountImplied, + width_span: None, + ty: "", + ty_span: None, + }; + + match arg.position { + ArgumentIs(n) | ArgumentImplicitlyIs(n) => { + if self.unnamed.len() <= n { + // Use a dummy span to mark all unseen arguments. + self.unnamed.resize_with(n, || vec![DUMMY_SP]); + if arg.format == SIMPLE { + self.unnamed.push(vec![span]); + } else { + self.unnamed.push(Vec::new()); + } + } else { + let args = &mut self.unnamed[n]; + match (args.as_mut_slice(), arg.format == SIMPLE) { + // A non-empty format string has been seen already. + ([], _) => (), + // Replace the dummy span, if it exists. + ([dummy @ DUMMY_SP], true) => *dummy = span, + ([_, ..], true) => args.push(span), + ([_, ..], false) => *args = Vec::new(), + } + } + }, + ArgumentNamed(n) => { + if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) { + match x.1.as_slice() { + // A non-empty format string has been seen already. + [] => (), + [_, ..] if arg.format == SIMPLE => x.1.push(span), + [_, ..] => x.1 = Vec::new(), + } + } else if arg.format == SIMPLE { + self.named.push((n, vec![span])); + } else { + self.named.push((n, Vec::new())); + } + }, + }; + } +} + impl Write { + /// Parses a format string into a collection of spans for each argument. This only keeps track + /// of empty format arguments. Will also lint usages of debug format strings outside of debug + /// impls. + fn parse_fmt_string(&self, cx: &EarlyContext<'_>, str_lit: &StrLit) -> Option<SimpleFormatArgs> { + use rustc_parse_format::{ParseMode, Parser, Piece}; + + let str_sym = str_lit.symbol_unescaped.as_str(); + let style = match str_lit.style { + StrStyle::Cooked => None, + StrStyle::Raw(n) => Some(n as usize), + }; + + let mut parser = Parser::new(&str_sym, style, snippet_opt(cx, str_lit.span), false, ParseMode::Format); + let mut args = SimpleFormatArgs::default(); + + while let Some(arg) = parser.next() { + let arg = match arg { + Piece::String(_) => continue, + Piece::NextArgument(arg) => arg, + }; + let span = parser + .arg_places + .last() + .map_or(DUMMY_SP, |&x| str_lit.span.from_inner(x)); + + if !self.in_debug_impl && arg.format.ty == "?" { + // FIXME: modify rustc's fmt string parser to give us the current span + span_lint(cx, USE_DEBUG, span, "use of `Debug`-based formatting"); + } + + args.push(arg, span); + } + + parser.errors.is_empty().then(move || args) + } + /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two /// `Option`s. The first `Option` of the tuple is the macro's format string. It includes /// the contents of the string, whether it's a raw string, and the span of the literal in the @@ -376,124 +488,97 @@ impl Write { /// (Some("string to write: {}"), Some(buf)) /// ``` #[allow(clippy::too_many_lines)] - fn check_tts<'a>( - &self, - cx: &EarlyContext<'a>, - tts: TokenStream, - is_write: bool, - ) -> (Option<StrLit>, Option<Expr>) { - use rustc_parse_format::{ - AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, - FormatSpec, ParseMode, Parser, Piece, - }; - + fn check_tts<'a>(&self, cx: &EarlyContext<'a>, tts: TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) { let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, false, None); - let mut expr: Option<Expr> = None; - if is_write { - expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { - Ok(p) => Some(p.into_inner()), - Err(_) => return (None, None), - }; - // might be `writeln!(foo)` - if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() { - return (None, expr); + let expr = if is_write { + match parser + .parse_expr() + .map(rustc_ast::ptr::P::into_inner) + .map_err(|mut e| e.cancel()) + { + // write!(e, ...) + Ok(p) if parser.eat(&token::Comma) => Some(p), + // write!(e) or error + e => return (None, e.ok()), } - } + } else { + None + }; let fmtstr = match parser.parse_str_lit() { Ok(fmtstr) => fmtstr, Err(_) => return (None, expr), }; - let tmp = fmtstr.symbol.as_str(); - let mut args = vec![]; - let mut fmt_parser = Parser::new(&tmp, None, None, false, ParseMode::Format); - while let Some(piece) = fmt_parser.next() { - if !fmt_parser.errors.is_empty() { - return (None, expr); - } - if let Piece::NextArgument(arg) = piece { - if !self.in_debug_impl && arg.format.ty == "?" { - // FIXME: modify rustc's fmt string parser to give us the current span - span_lint( - cx, - USE_DEBUG, - parser.prev_token.span, - "use of `Debug`-based formatting", - ); - } - args.push(arg); - } - } + + let args = match self.parse_fmt_string(cx, &fmtstr) { + Some(args) => args, + None => return (Some(fmtstr), expr), + }; + let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL }; - let mut idx = 0; + let mut unnamed_args = args.get_unnamed(); loop { - const SIMPLE: FormatSpec<'_> = FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - precision_span: None, - width: CountImplied, - width_span: None, - ty: "", - ty_span: None, - }; if !parser.eat(&token::Comma) { return (Some(fmtstr), expr); } + + let comma_span = parser.prev_token.span; let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) { expr } else { return (Some(fmtstr), None); }; - match &token_expr.kind { - ExprKind::Lit(lit) - if !matches!(lit.kind, LitKind::Int(..) | LitKind::Float(..)) => - { - let mut all_simple = true; - let mut seen = false; - for arg in &args { - match arg.position { - ArgumentImplicitlyIs(n) | ArgumentIs(n) => { - if n == idx { - all_simple &= arg.format == SIMPLE; - seen = true; - } - } - ArgumentNamed(_) => {} - } - } - if all_simple && seen { - span_lint(cx, lint, token_expr.span, "literal with an empty format string"); - } - idx += 1; - } - ExprKind::Assign(lhs, rhs, _) => { - if_chain! { - if let ExprKind::Lit(ref lit) = rhs.kind; - if !matches!(lit.kind, LitKind::Int(..) | LitKind::Float(..)); - if let ExprKind::Path(_, p) = &lhs.kind; - then { - let mut all_simple = true; - let mut seen = false; - for arg in &args { - match arg.position { - ArgumentImplicitlyIs(_) | ArgumentIs(_) => {}, - ArgumentNamed(name) => { - if *p == name { - seen = true; - all_simple &= arg.format == SIMPLE; - } - }, - } - } - if all_simple && seen { - span_lint(cx, lint, rhs.span, "literal with an empty format string"); - } - } - } + let (fmt_spans, lit) = match &token_expr.kind { + ExprKind::Lit(lit) => (unnamed_args.next().unwrap_or(&[]), lit), + ExprKind::Assign(lhs, rhs, _) => match (&lhs.kind, &rhs.kind) { + (ExprKind::Path(_, p), ExprKind::Lit(lit)) => (args.get_named(p), lit), + _ => continue, + }, + _ => { + unnamed_args.next(); + continue; + }, + }; + + let replacement: String = match lit.token.kind { + LitKind::Integer | LitKind::Float | LitKind::Err => continue, + LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => { + lit.token.symbol.as_str().replace("{", "{{").replace("}", "}}") + }, + LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => { + lit.token.symbol.as_str().replace("{", "{{").replace("}", "}}") + }, + LitKind::StrRaw(_) | LitKind::Str | LitKind::ByteStrRaw(_) | LitKind::ByteStr => continue, + LitKind::Byte | LitKind::Char => match &*lit.token.symbol.as_str() { + "\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"", + "\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue, + "\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\", + "\\'" => "'", + "{" => "{{", + "}" => "}}", + x if matches!(fmtstr.style, StrStyle::Raw(_)) && x.starts_with('\\') => continue, + x => x, } - _ => idx += 1, + .into(), + LitKind::Bool => lit.token.symbol.as_str().deref().into(), + }; + + if !fmt_spans.is_empty() { + span_lint_and_then( + cx, + lint, + token_expr.span, + "literal with an empty format string", + |diag| { + diag.multipart_suggestion( + "try this", + iter::once((comma_span.to(token_expr.span), String::new())) + .chain(fmt_spans.iter().copied().zip(iter::repeat(replacement))) + .collect(), + Applicability::MachineApplicable, + ); + }, + ); } } } @@ -524,17 +609,11 @@ impl Write { cx, PRINT_WITH_NEWLINE, mac.span(), - &format!( - "using `{}!()` with a format string that ends in a single newline", - name - ), + &format!("using `{}!()` with a format string that ends in a single newline", name), |err| { err.multipart_suggestion( &format!("use `{}!` instead", suggested), - vec![ - (mac.path.span, suggested), - (newline_span(&fmt_str), String::new()), - ], + vec![(mac.path.span, suggested), (newline_span(&fmt_str), String::new())], Applicability::MachineApplicable, ); }, diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs index 11d96e15ff..350b1cf25f 100644 --- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs +++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs @@ -1,5 +1,5 @@ use crate::consts::{constant_simple, Constant}; -use crate::utils::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_help; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -31,7 +31,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // check for instances of 0.0/0.0 if_chain! { - if let ExprKind::Binary(ref op, ref left, ref right) = expr.kind; + if let ExprKind::Binary(ref op, left, right) = expr.kind; if let BinOpKind::Div = op.node; // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index adf7077e65..f93f0047f5 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -1,3 +1,6 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::paths; +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}; @@ -7,8 +10,6 @@ use rustc_span::sym; use rustc_target::abi::LayoutOf as _; use rustc_typeck::hir_ty_to_ty; -use crate::utils::{is_normalizable, is_type_diagnostic_item, match_type, paths, span_lint_and_help}; - declare_clippy_lint! { /// **What it does:** Checks for maps with zero-sized value types anywhere in the code. /// @@ -49,7 +50,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues { if !in_trait_impl(cx, hir_ty.hir_id); let ty = ty_from_hir_ty(cx, hir_ty); if is_type_diagnostic_item(cx, ty, sym::hashmap_type) || match_type(cx, ty, &paths::BTREEMAP); - if let Adt(_, ref substs) = ty.kind(); + if let Adt(_, substs) = ty.kind(); let ty = substs.type_at(1); // Do this to prevent `layout_of` crashing, being unable to fully normalize `ty`. if is_normalizable(cx, cx.param_env, ty); diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 9e07f140cf..d04c5f889d 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.52" +version = "0.1.53" authors = ["The Rust Clippy Developers"] edition = "2018" publish = false @@ -10,8 +10,6 @@ if_chain = "1.0.0" itertools = "0.9" regex-syntax = "0.6" serde = { version = "1.0", features = ["derive"] } -smallvec = { version = "1", features = ["union"] } -toml = "0.5.3" unicode-normalization = "0.1" rustc-semver="1.1.0" diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index ea9a910d1b..93e10c836c 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -5,6 +5,7 @@ #![allow(clippy::similar_names, clippy::wildcard_imports, clippy::enum_glob_use)] use crate::{both, over}; +use if_chain::if_chain; use rustc_ast::ptr::P; use rustc_ast::{self as ast, *}; use rustc_span::symbol::Ident; @@ -169,9 +170,9 @@ 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_path(&lse.path, &rse.path) && - eq_struct_rest(&lse.rest, &rse.rest) && - unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r)) + 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)) }, _ => false, } @@ -408,6 +409,10 @@ pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool { eq_path(&l.prefix, &r.prefix) && eq_use_tree_kind(&l.kind, &r.kind) } +pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { + eq_expr(&l.value, &r.value) +} + pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { use UseTreeKind::*; match (l, r) { @@ -418,10 +423,6 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { } } -pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { - eq_expr(&l.value, &r.value) -} - pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { matches!( (l, r), @@ -571,3 +572,34 @@ pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool { _ => false, } } + +/// Extract args from an assert-like macro. +/// +/// Currently working with: +/// - `assert_eq!` and `assert_ne!` +/// - `debug_assert_eq!` and `debug_assert_ne!` +/// +/// For example: +/// +/// `debug_assert_eq!(a, b)` will return Some([a, b]) +pub fn extract_assert_macro_args(mut expr: &Expr) -> Option<[&Expr; 2]> { + if_chain! { + if let ExprKind::If(_, ref block, _) = expr.kind; + if let StmtKind::Semi(ref e) = block.stmts.get(0)?.kind; + then { + expr = e; + } + } + if_chain! { + if let ExprKind::Block(ref block, _) = expr.kind; + if let StmtKind::Expr(ref expr) = block.stmts.get(0)?.kind; + if let ExprKind::Match(ref match_expr, _) = expr.kind; + if let ExprKind::Tup(ref tup) = match_expr.kind; + if let [a, b, ..] = tup.as_slice(); + if let (&ExprKind::AddrOf(_, _, ref a), &ExprKind::AddrOf(_, _, ref b)) = (&a.kind, &b.kind); + then { + return Some([&*a, &*b]); + } + } + None +} diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 8d28421d70..c0584e1e22 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -1,4 +1,4 @@ -use rustc_ast::ast; +use rustc_ast::{ast, attr}; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::sym; @@ -148,3 +148,12 @@ pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'s pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool { attrs.iter().any(|attr| sess.is_proc_macro_attr(attr)) } + +/// Return true if the attributes contain `#[doc(hidden)]` +pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool { + attrs + .iter() + .filter(|attr| attr.has_name(sym::doc)) + .filter_map(ast::Attribute::meta_item_list) + .any(|l| attr::list_contains_name(&l, sym::hidden)) +} diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 802c01055a..2a305d8bcb 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -15,6 +15,7 @@ use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; use std::convert::TryInto; use std::hash::{Hash, Hasher}; +use std::iter; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] @@ -139,9 +140,7 @@ impl Constant { (&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r), (&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r), (&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)), - (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => l - .iter() - .zip(r.iter()) + (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => iter::zip(l, r) .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) .find(|r| r.map_or(true, |o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), @@ -341,9 +340,11 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .tcx .const_eval_resolve( self.param_env, - ty::WithOptConstParam::unknown(def_id), - substs, - None, + ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id), + substs, + promoted: None, + }, None, ) .ok() diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 269be217c2..7f827f1759 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -8,14 +8,16 @@ use std::env; fn docs_link(diag: &mut DiagnosticBuilder<'_>, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { - diag.help(&format!( - "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}", - &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { - // extract just major + minor version and ignore patch versions - format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap()) - }), - lint.name_lower().replacen("clippy::", "", 1) - )); + if let Some(lint) = lint.name_lower().strip_prefix("clippy::") { + diag.help(&format!( + "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}", + &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { + // extract just major + minor version and ignore patch versions + format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap()) + }), + lint + )); + } } } @@ -131,9 +133,11 @@ pub fn span_lint_and_note<'a, T: LintContext>( /// /// If you need to customize your lint output a lot, use this function. /// If you change the signature, remember to update the internal lint `CollapsibleCalls` -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) +pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str, f: F) where - F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), + C: LintContext, + S: Into<MultiSpan>, + F: FnOnce(&mut DiagnosticBuilder<'_>), { cx.struct_span_lint(lint, sp, |diag| { let mut diag = diag.build(msg); @@ -214,6 +218,11 @@ where multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg) } +/// Create a suggestion made from several `span → replacement`. +/// +/// rustfix currently doesn't support the automatic application of suggestions with +/// multiple spans. This is tracked in issue [rustfix#141](https://github.com/rust-lang/rustfix/issues/141). +/// Suggestions with multiple spans will be silently ignored. pub fn multispan_sugg_with_applicability<I>( diag: &mut DiagnosticBuilder<'_>, help_msg: &str, diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index 8013c4e4fc..88b115a63d 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -9,7 +9,8 @@ //! - or-fun-call //! - option-if-let-else -use crate::{is_ctor_or_promotable_const_function, is_type_diagnostic_item}; +use crate::is_ctor_or_promotable_const_function; +use crate::ty::is_type_diagnostic_item; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 7f7d9c5f56..07ae6e924e 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1,12 +1,13 @@ use crate::consts::{constant_context, constant_simple}; -use crate::{differing_macro_contexts, snippet_opt}; +use crate::differing_macro_contexts; +use crate::source::snippet_opt; use rustc_ast::ast::InlineAsmTemplatePiece; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def::Res; +use rustc_hir::HirIdMap; use rustc_hir::{ - BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, ExprField, PatField, FnRetTy, - GenericArg, GenericArgs, Guard, HirId, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatKind, Path, + BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprField, ExprKind, FnRetTy, GenericArg, + GenericArgs, Guard, HirId, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, }; use rustc_lexer::{tokenize, TokenKind}; @@ -57,13 +58,14 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { /// Use this method to wrap comparisons that may involve inter-expression context. /// See `self.locals`. - fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> { + pub fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> { HirEqInterExpr { inner: self, - locals: FxHashMap::default(), + locals: HirIdMap::default(), } } + #[allow(dead_code)] pub fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool { self.inter_expr().eq_block(left, right) } @@ -79,28 +81,36 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { pub fn eq_path_segments(&mut self, left: &[PathSegment<'_>], right: &[PathSegment<'_>]) -> bool { self.inter_expr().eq_path_segments(left, right) } - - pub fn eq_ty_kind(&mut self, left: &TyKind<'_>, right: &TyKind<'_>) -> bool { - self.inter_expr().eq_ty_kind(left, right) - } } -struct HirEqInterExpr<'a, 'b, 'tcx> { +pub struct HirEqInterExpr<'a, 'b, 'tcx> { inner: &'a mut SpanlessEq<'b, 'tcx>, // When binding are declared, the binding ID in the left expression is mapped to the one on the // right. For example, when comparing `{ let x = 1; x + 2 }` and `{ let y = 1; y + 2 }`, // these blocks are considered equal since `x` is mapped to `y`. - locals: FxHashMap<HirId, HirId>, + locals: HirIdMap<HirId>, } impl HirEqInterExpr<'_, '_, '_> { - fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool { + pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool { match (&left.kind, &right.kind) { (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => { - self.eq_pat(&l.pat, &r.pat) + // This additional check ensures that the type of the locals are equivalent even if the init + // expression or type have some inferred parts. + if let Some(typeck) = self.inner.maybe_typeck_results { + let l_ty = typeck.pat_ty(&l.pat); + let r_ty = typeck.pat_ty(&r.pat); + if !rustc_middle::ty::TyS::same_type(l_ty, r_ty) { + return false; + } + } + + // eq_pat adds the HirIds to the locals map. We therefor call it last to make sure that + // these only get added if the init and type is equal. + both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) - && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) + && self.eq_pat(&l.pat, &r.pat) }, (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => { self.eq_expr(l, r) @@ -162,7 +172,7 @@ impl HirEqInterExpr<'_, '_, '_> { } #[allow(clippy::similar_names)] - fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool { + pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool { if !self.inner.allow_side_effects && differing_macro_contexts(left.span, right.span) { return false; } @@ -251,7 +261,7 @@ impl HirEqInterExpr<'_, '_, '_> { (&ExprKind::Struct(ref l_path, ref lf, ref lo), &ExprKind::Struct(ref r_path, ref rf, ref ro)) => { self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) - && over(lf, rf, |l, r| self.eq_field(l, r)) + && over(lf, rf, |l, r| self.eq_expr_field(l, r)) }, (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup), (&ExprKind::Unary(l_op, ref le), &ExprKind::Unary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), @@ -266,7 +276,7 @@ impl HirEqInterExpr<'_, '_, '_> { over(left, right, |l, r| self.eq_expr(l, r)) } - fn eq_field(&mut self, left: &ExprField<'_>, right: &ExprField<'_>) -> bool { + fn eq_expr_field(&mut self, left: &ExprField<'_>, right: &ExprField<'_>) -> bool { left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr) } @@ -290,7 +300,7 @@ impl HirEqInterExpr<'_, '_, '_> { left.name == right.name } - fn eq_fieldpat(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool { + fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool { let (PatField { ident: li, pat: lp, .. }, PatField { ident: ri, pat: rp, .. }) = (&left, &right); li.name == ri.name && self.eq_pat(lp, rp) } @@ -300,7 +310,7 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), (&PatKind::Struct(ref lp, ref la, ..), &PatKind::Struct(ref rp, ref ra, ..)) => { - self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_fieldpat(l, r)) + self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat_field(l, r)) }, (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs @@ -377,13 +387,9 @@ impl HirEqInterExpr<'_, '_, '_> { left.ident.name == right.ident.name && both(&left.args, &right.args, |l, r| self.eq_path_parameters(l, r)) } - fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { - self.eq_ty_kind(&left.kind, &right.kind) - } - #[allow(clippy::similar_names)] - fn eq_ty_kind(&mut self, left: &TyKind<'_>, right: &TyKind<'_>) -> bool { - match (left, right) { + fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { + match (&left.kind, &right.kind) { (&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec), (&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => { let cx = self.inner.cx; @@ -428,7 +434,7 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace ) }) - .ne([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().cloned()) => + .ne([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().copied()) => { kind }, @@ -490,6 +496,15 @@ pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } +/// Counts how many elements of the slices are equal as per `eq_fn`. +pub fn count_eq<X: Sized>( + left: &mut dyn Iterator<Item = X>, + right: &mut dyn Iterator<Item = X>, + mut eq_fn: impl FnMut(&X, &X) -> bool, +) -> usize { + left.zip(right).take_while(|(l, r)| eq_fn(l, r)).count() +} + /// Checks if two expressions evaluate to the same value, and don't contain any side effects. pub fn eq_expr_value(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>) -> bool { SpanlessEq::new(cx).deny_side_effects().eq_expr(left, right) @@ -670,7 +685,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(out_expr); } }, - InlineAsmOperand::Const { expr } | InlineAsmOperand::Sym { expr } => self.hash_expr(expr), + InlineAsmOperand::Const { anon_const } => self.hash_body(anon_const.body), + InlineAsmOperand::Sym { expr } => self.hash_expr(expr), } } }, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index d81b89dd00..e81a92eb74 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1,6 +1,7 @@ #![feature(box_patterns)] #![feature(in_band_lifetimes)] -#![feature(or_patterns)] +#![feature(iter_zip)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(rustc_private)] #![recursion_limit = "512"] #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] @@ -9,6 +10,7 @@ // (Currently there is no way to opt into sysroot crates without `extern crate`.) extern crate rustc_ast; extern crate rustc_ast_pretty; +extern crate rustc_attr; extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_hir; @@ -32,59 +34,56 @@ pub mod attrs; pub mod camel_case; pub mod comparisons; pub mod consts; -mod diagnostics; +pub mod diagnostics; pub mod eager_or_lazy; pub mod higher; mod hir_utils; +pub mod msrvs; pub mod numeric_literal; pub mod paths; pub mod ptr; pub mod qualify_min_const_fn; +pub mod source; pub mod sugg; +pub mod ty; pub mod usage; pub mod visitors; pub use self::attrs::*; -pub use self::diagnostics::*; -pub use self::hir_utils::{both, eq_expr_value, over, SpanlessEq, SpanlessHash}; +pub use self::hir_utils::{both, count_eq, eq_expr_value, over, SpanlessEq, SpanlessHash}; -use std::borrow::Cow; use std::collections::hash_map::Entry; use std::hash::BuildHasherDefault; use if_chain::if_chain; -use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind, Mutability}; +use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::Node; +use rustc_hir::intravisit::{self, walk_expr, ErasedMap, NestedVisitorMap, Visitor}; +use rustc_hir::LangItem::{ResultErr, ResultOk}; use rustc_hir::{ - def, Arm, Block, Body, Constness, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, Item, - ItemKind, LangItem, MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, - TyKind, Unsafety, + def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, + ImplItem, ImplItemKind, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path, PathSegment, + QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, }; -use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::exports::Export; use rustc_middle::hir::map::Map; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, layout::IntegerExt, DefIdTree, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; +use rustc_middle::ty as rustc_ty; +use rustc_middle::ty::{layout::IntegerExt, DefIdTree, Ty, TyCtxt, TypeFoldable}; use rustc_semver::RustcVersion; use rustc_session::Session; -use rustc_span::hygiene::{self, ExpnKind, MacroKind}; +use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; use rustc_span::sym; use rustc_span::symbol::{kw, Symbol}; -use rustc_span::{BytePos, Pos, Span, SyntaxContext, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::Integer; -use rustc_trait_selection::traits::query::normalize::AtExt; -use smallvec::SmallVec; use crate::consts::{constant, Constant}; -use std::collections::HashMap; +use crate::ty::{can_partially_move_ty, is_recursively_primitive_type}; pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> { if let Ok(version) = RustcVersion::parse(msrv) { @@ -137,6 +136,58 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { rhs.ctxt() != lhs.ctxt() } +/// If the given expression is a local binding, find the initializer expression. +/// If that initializer expression is another local binding, find its initializer again. +/// This process repeats as long as possible (but usually no more than once). Initializer +/// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`] +/// instead. +/// +/// Examples: +/// ```ignore +/// let abc = 1; +/// // ^ output +/// let def = abc; +/// dbg!(def) +/// // ^^^ input +/// +/// // or... +/// let abc = 1; +/// let def = abc + 2; +/// // ^^^^^^^ output +/// dbg!(def) +/// // ^^^ input +/// ``` +pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> { + while let Some(init) = path_to_local(expr) + .and_then(|id| find_binding_init(cx, id)) + .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty()) + { + expr = init; + } + expr +} + +/// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable. +/// By only considering immutable bindings, we guarantee that the returned expression represents the +/// value of the binding wherever it is referenced. +/// +/// Example: For `let x = 1`, if the `HirId` of `x` is provided, the `Expr` `1` is returned. +/// Note: If you have an expression that references a binding `x`, use `path_to_local` to get the +/// canonical binding `HirId`. +pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { + let hir = cx.tcx.hir(); + if_chain! { + if let Some(Node::Binding(pat)) = hir.find(hir_id); + if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..)); + let parent = hir.get_parent_node(hir_id); + if let Some(Node::Local(local)) = hir.find(parent); + then { + return local.init; + } + } + None +} + /// Returns `true` if the given `NodeId` is inside a constant context /// /// # Example @@ -174,6 +225,19 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool { } } +/// Checks if a `QPath` resolves to a constructor of a `LangItem`. +/// For example, use this to check whether a function call or a pattern is `Some(..)`. +pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem) -> bool { + if let QPath::Resolved(_, path) = qpath { + if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res { + if let Ok(item_id) = cx.tcx.lang_items().require(lang_item) { + return cx.tcx.parent(ctor_id) == Some(item_id); + } + } + } + false +} + /// Returns `true` if this `span` was expanded by any macro. #[must_use] pub fn in_macro(span: Span) -> bool { @@ -184,54 +248,11 @@ pub fn in_macro(span: Span) -> bool { } } -// If the snippet is empty, it's an attribute that was inserted during macro -// expansion and we want to ignore those, because they could come from external -// sources that the user has no control over. -// For some reason these attributes don't have any expansion info on them, so -// we have to check it this way until there is a better way. -pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool { - if let Some(snippet) = snippet_opt(cx, span) { - if snippet.is_empty() { - return false; - } - } - true -} - /// Checks if given pattern is a wildcard (`_`) pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool { matches!(pat.kind, PatKind::Wild) } -/// Checks if type is struct, enum or union type with the given def path. -/// -/// If the type is a diagnostic item, use `is_type_diagnostic_item` instead. -/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem` -pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool { - match ty.kind() { - ty::Adt(adt, _) => match_def_path(cx, adt.did, path), - _ => false, - } -} - -/// Checks if the type is equal to a diagnostic item -/// -/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem` -pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool { - match ty.kind() { - ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did), - _ => false, - } -} - -/// Checks if the type is equal to a lang item -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, - _ => false, - } -} - /// Checks if the first type parameter is a lang item. pub fn is_ty_param_lang_item(cx: &LateContext<'_>, qpath: &QPath<'tcx>, item: LangItem) -> Option<&'tcx hir::Ty<'tcx>> { let ty = get_qpath_generic_tys(qpath).next()?; @@ -266,32 +287,37 @@ pub fn is_ty_param_diagnostic_item( } } -/// Return `true` if the passed `typ` is `isize` or `usize`. -pub fn is_isize_or_usize(typ: Ty<'_>) -> bool { - matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize)) -} - /// Checks if the method call given in `expr` belongs to the given trait. +/// This is a deprecated function, consider using [`is_trait_method`]. pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool { let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); let trt_id = cx.tcx.trait_of_item(def_id); trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path)) } -/// Checks if the method call given in `expr` belongs to a trait or other container with a given -/// diagnostic item -pub fn is_diagnostic_assoc_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool { - cx.tcx - .opt_associated_item(def_id) - .and_then(|associated_item| match associated_item.container { - ty::TraitContainer(assoc_def_id) => Some(assoc_def_id), - ty::ImplContainer(assoc_def_id) => match cx.tcx.type_of(assoc_def_id).kind() { - ty::Adt(adt, _) => Some(adt.did), - ty::Slice(_) => cx.tcx.get_diagnostic_item(sym::slice), // this isn't perfect but it works - _ => None, - }, - }) - .map_or(false, |assoc_def_id| cx.tcx.is_diagnostic_item(diag_item, assoc_def_id)) +/// Checks if a method is defined in an impl of a diagnostic item +pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool { + if let Some(impl_did) = cx.tcx.impl_of_method(def_id) { + if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() { + return cx.tcx.is_diagnostic_item(diag_item, adt.did); + } + } + false +} + +/// Checks if a method is in a diagnostic item trait +pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool { + if let Some(trait_did) = cx.tcx.trait_of_item(def_id) { + return cx.tcx.is_diagnostic_item(diag_item, trait_did); + } + false +} + +/// Checks if the method call given in `expr` belongs to the given trait. +pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool { + cx.typeck_results() + .type_dependent_def_id(expr.hir_id) + .map_or(false, |did| is_diag_trait_item(cx, did, diag_item)) } /// Checks if an expression references a variable of the given name. @@ -341,6 +367,10 @@ pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment } } +/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the +/// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from +/// `QPath::Resolved.1.res.opt_def_id()`. +/// /// Matches a `QPath` against a slice of segment string literals. /// /// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a @@ -368,6 +398,33 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool { } } +/// If the expression is a path, resolve it. Otherwise, return `Res::Err`. +pub fn expr_path_res(cx: &LateContext<'_>, expr: &Expr<'_>) -> Res { + if let ExprKind::Path(p) = &expr.kind { + cx.qpath_res(p, expr.hir_id) + } else { + Res::Err + } +} + +/// Resolves the path to a `DefId` and checks if it matches the given path. +pub fn is_qpath_def_path(cx: &LateContext<'_>, path: &QPath<'_>, hir_id: HirId, segments: &[&str]) -> bool { + cx.qpath_res(path, hir_id) + .opt_def_id() + .map_or(false, |id| match_def_path(cx, id, segments)) +} + +/// If the expression is a path, resolves it to a `DefId` and checks if it matches the given path. +pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool { + expr_path_res(cx, expr) + .opt_def_id() + .map_or(false, |id| match_def_path(cx, id, segments)) +} + +/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the +/// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from +/// `QPath::Resolved.1.res.opt_def_id()`. +/// /// Matches a `Path` against a slice of segment string literals. /// /// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a @@ -392,20 +449,6 @@ pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool { .all(|(a, b)| a.ident.name.as_str() == *b) } -/// Matches a `Path` against a slice of segment string literals, e.g. -/// -/// # Examples -/// ```rust,ignore -/// match_path_ast(path, &["std", "rt", "begin_unwind"]) -/// ``` -pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { - path.segments - .iter() - .rev() - .zip(segments.iter().rev()) - .all(|(a, b)| a.ident.name.as_str() == *b) -} - /// If the expression is a path to a local, returns the canonical `HirId` of the local. pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> { if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind { @@ -479,26 +522,6 @@ pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> { } } -/// Checks whether a type implements a trait. -/// See also `get_trait_def_id`. -pub fn implements_trait<'tcx>( - cx: &LateContext<'tcx>, - ty: Ty<'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; - } - 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)) -} - /// Gets the `hir::TraitRef` of the trait the given method is implemented for. /// /// Use this if you want to find the `TraitRef` of the `Add` trait in this example: @@ -526,24 +549,71 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio None } -/// Checks whether this type implements `Drop`. -pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.ty_adt_def() { - Some(def) => def.has_dtor(cx.tcx), - None => false, +/// Checks if the top level expression can be moved into a closure as is. +pub fn can_move_expr_to_closure_no_visit(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, jump_targets: &[HirId]) -> bool { + match expr.kind { + ExprKind::Break(Destination { target_id: Ok(id), .. }, _) + | ExprKind::Continue(Destination { target_id: Ok(id), .. }) + if jump_targets.contains(&id) => + { + true + }, + ExprKind::Break(..) + | ExprKind::Continue(_) + | ExprKind::Ret(_) + | ExprKind::Yield(..) + | ExprKind::InlineAsm(_) + | ExprKind::LlvmInlineAsm(_) => false, + // Accessing a field of a local value can only be done if the type isn't + // partially moved. + ExprKind::Field(base_expr, _) + if matches!( + base_expr.kind, + ExprKind::Path(QPath::Resolved(_, Path { res: Res::Local(_), .. })) + ) && can_partially_move_ty(cx, cx.typeck_results().expr_ty(base_expr)) => + { + // TODO: check if the local has been partially moved. Assume it has for now. + false + } + _ => true, } } -/// Checks whether a type can be partially moved. -pub fn can_partially_move_ty(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - if has_drop(cx, ty) || is_copy(cx, ty) { - return false; +/// Checks if the expression can be moved into a closure as is. +pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { + struct V<'cx, 'tcx> { + cx: &'cx LateContext<'tcx>, + loops: Vec<HirId>, + allow_closure: bool, } - match ty.kind() { - ty::Param(_) => false, - ty::Adt(def, subs) => def.all_fields().any(|f| !is_copy(cx, f.ty(cx.tcx, subs))), - _ => true, + impl Visitor<'tcx> for V<'_, 'tcx> { + type Map = ErasedMap<'tcx>; + fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { + NestedVisitorMap::None + } + + fn visit_expr(&mut self, e: &'tcx Expr<'_>) { + if !self.allow_closure { + return; + } + if let ExprKind::Loop(b, ..) = e.kind { + self.loops.push(e.hir_id); + self.visit_block(b); + self.loops.pop(); + } else { + self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops); + walk_expr(self, e); + } + } } + + let mut v = V { + cx, + allow_closure: true, + loops: Vec::new(), + }; + v.visit_expr(expr); + v.allow_closure } /// Returns the method names and argument list of nested method call expressions that make up @@ -608,7 +678,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool { cx.tcx .entry_fn(LOCAL_CRATE) - .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id.to_def_id()) + .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id) } /// Returns `true` if the expression is in the program's `#[panic_handler]`. @@ -641,9 +711,9 @@ pub fn get_pat_name(pat: &Pat<'_>) -> Option<Symbol> { } } -struct ContainsName { - name: Symbol, - result: bool, +pub struct ContainsName { + pub name: Symbol, + pub result: bool, } impl<'tcx> Visitor<'tcx> for ContainsName { @@ -727,206 +797,6 @@ pub fn find_macro_calls(names: &[&str], body: &Body<'_>) -> Vec<Span> { fmc.result } -/// Converts a span to a code snippet if available, otherwise use default. -/// -/// This is useful if you want to provide suggestions for your lint or more generally, if you want -/// to convert a given `Span` to a `str`. -/// -/// # Example -/// ```rust,ignore -/// snippet(cx, expr.span, "..") -/// ``` -pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from) -} - -/// Same as `snippet`, but it adapts the applicability level by following rules: -/// -/// - Applicability level `Unspecified` will never be changed. -/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. -/// - If the default value is used and the applicability level is `MachineApplicable`, change it to -/// `HasPlaceholders` -pub fn snippet_with_applicability<'a, T: LintContext>( - cx: &T, - span: Span, - default: &'a str, - applicability: &mut Applicability, -) -> Cow<'a, str> { - if *applicability != Applicability::Unspecified && span.from_expansion() { - *applicability = Applicability::MaybeIncorrect; - } - snippet_opt(cx, span).map_or_else( - || { - if *applicability == Applicability::MachineApplicable { - *applicability = Applicability::HasPlaceholders; - } - Cow::Borrowed(default) - }, - From::from, - ) -} - -/// Same as `snippet`, but should only be used when it's clear that the input span is -/// not a macro argument. -pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - snippet(cx, span.source_callsite(), default) -} - -/// Converts a span to a code snippet. Returns `None` if not available. -pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { - cx.sess().source_map().span_to_snippet(span).ok() -} - -/// Converts a span (from a block) to a code snippet if available, otherwise use default. -/// -/// This trims the code of indentation, except for the first line. Use it for blocks or block-like -/// things which need to be printed as such. -/// -/// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the -/// resulting snippet of the given span. -/// -/// # Example -/// -/// ```rust,ignore -/// snippet_block(cx, block.span, "..", None) -/// // where, `block` is the block of the if expr -/// if x { -/// y; -/// } -/// // will return the snippet -/// { -/// y; -/// } -/// ``` -/// -/// ```rust,ignore -/// snippet_block(cx, block.span, "..", Some(if_expr.span)) -/// // where, `block` is the block of the if expr -/// if x { -/// y; -/// } -/// // will return the snippet -/// { -/// y; -/// } // aligned with `if` -/// ``` -/// Note that the first line of the snippet always has 0 indentation. -pub fn snippet_block<'a, T: LintContext>( - cx: &T, - span: Span, - default: &'a str, - indent_relative_to: Option<Span>, -) -> Cow<'a, str> { - let snip = snippet(cx, span, default); - let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); - reindent_multiline(snip, true, indent) -} - -/// Same as `snippet_block`, but adapts the applicability level by the rules of -/// `snippet_with_applicability`. -pub fn snippet_block_with_applicability<'a, T: LintContext>( - cx: &T, - span: Span, - default: &'a str, - indent_relative_to: Option<Span>, - applicability: &mut Applicability, -) -> Cow<'a, str> { - let snip = snippet_with_applicability(cx, span, default, applicability); - let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); - reindent_multiline(snip, true, indent) -} - -/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This -/// will result in the macro call, rather then the expansion, if the span is from a child context. -/// If the span is not from a child context, it will be used directly instead. -/// -/// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node -/// would result in `box []`. If given the context of the address of expression, this function will -/// correctly get a snippet of `vec![]`. -pub fn snippet_with_context( - cx: &LateContext<'_>, - span: Span, - outer: SyntaxContext, - default: &'a str, - applicability: &mut Applicability, -) -> Cow<'a, str> { - let outer_span = hygiene::walk_chain(span, outer); - let span = if outer_span.ctxt() == outer { - outer_span - } else { - // The span is from a macro argument, and the outer context is the macro using the argument - if *applicability != Applicability::Unspecified { - *applicability = Applicability::MaybeIncorrect; - } - // TODO: get the argument span. - span - }; - - snippet_with_applicability(cx, span, default, applicability) -} - -/// Returns a new Span that extends the original Span to the first non-whitespace char of the first -/// line. -/// -/// ```rust,ignore -/// let x = (); -/// // ^^ -/// // will be converted to -/// let x = (); -/// // ^^^^^^^^^^ -/// ``` -pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span { - first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos)) -} - -fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> { - let line_span = line_span(cx, span); - snippet_opt(cx, line_span).and_then(|snip| { - snip.find(|c: char| !c.is_whitespace()) - .map(|pos| line_span.lo() + BytePos::from_usize(pos)) - }) -} - -/// Returns the indentation of the line of a span -/// -/// ```rust,ignore -/// let x = (); -/// // ^^ -- will return 0 -/// let x = (); -/// // ^^ -- will return 4 -/// ``` -pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> { - snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace())) -} - -/// Returns the positon just before rarrow -/// -/// ```rust,ignore -/// fn into(self) -> () {} -/// ^ -/// // in case of unformatted code -/// fn into2(self)-> () {} -/// ^ -/// fn into3(self) -> () {} -/// ^ -/// ``` -pub fn position_before_rarrow(s: &str) -> Option<usize> { - s.rfind("->").map(|rpos| { - let mut rpos = rpos; - let chars: Vec<char> = s.chars().collect(); - while rpos > 1 { - if let Some(c) = chars.get(rpos - 1) { - if c.is_whitespace() { - rpos -= 1; - continue; - } - } - break; - } - rpos - }) -} - /// Extends the span to the beginning of the spans line, incl. whitespaces. /// /// ```rust,ignore @@ -944,81 +814,17 @@ fn line_span<T: LintContext>(cx: &T, span: Span) -> Span { Span::new(line_start, span.hi(), span.ctxt()) } -/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`. -/// Also takes an `Option<String>` which can be put inside the braces. -pub fn expr_block<'a, T: LintContext>( - cx: &T, - expr: &Expr<'_>, - option: Option<String>, - default: &'a str, - indent_relative_to: Option<Span>, -) -> Cow<'a, str> { - let code = snippet_block(cx, expr.span, default, indent_relative_to); - let string = option.unwrap_or_default(); - if expr.span.from_expansion() { - Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default))) - } else if let ExprKind::Block(_, _) = expr.kind { - Cow::Owned(format!("{}{}", code, string)) - } else if string.is_empty() { - Cow::Owned(format!("{{ {} }}", code)) - } else { - Cow::Owned(format!("{{\n{};\n{}\n}}", code, string)) - } -} - -/// Reindent a multiline string with possibility of ignoring the first line. -#[allow(clippy::needless_pass_by_value)] -pub fn reindent_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> { - let s_space = reindent_multiline_inner(&s, ignore_first, indent, ' '); - let s_tab = reindent_multiline_inner(&s_space, ignore_first, indent, '\t'); - reindent_multiline_inner(&s_tab, ignore_first, indent, ' ').into() -} - -fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>, ch: char) -> String { - let x = s - .lines() - .skip(ignore_first as usize) - .filter_map(|l| { - if l.is_empty() { - None - } else { - // ignore empty lines - Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0) - } - }) - .min() - .unwrap_or(0); - let indent = indent.unwrap_or(0); - s.lines() - .enumerate() - .map(|(i, l)| { - if (ignore_first && i == 0) || l.is_empty() { - l.to_owned() - } else if x > indent { - l.split_at(x - indent).1.to_owned() - } else { - " ".repeat(indent - x) + l - } - }) - .collect::<Vec<String>>() - .join("\n") +/// Gets the parent node, if any. +pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> { + tcx.hir().parent_iter(id).next().map(|(_, node)| node) } /// Gets the parent expression, if any –- this is useful to constrain a lint. pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - let map = &cx.tcx.hir(); - let hir_id = e.hir_id; - let parent_id = map.get_parent_node(hir_id); - if hir_id == parent_id { - return None; - } - map.find(parent_id).and_then(|node| { - if let Node::Expr(parent) = node { - Some(parent) - } else { - None - } - }) + match get_parent_node(cx.tcx, e.hir_id) { + Some(Node::Expr(parent)) => Some(parent), + _ => None, + } } pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> { @@ -1058,24 +864,31 @@ pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> { } } -/// Returns the base type for HIR references and pointers. -pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { - match ty.kind { - TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), - _ => ty, - } -} - -/// Returns the base type for references and raw pointers, and count reference -/// depth. -pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) { - fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) { - match ty.kind() { - ty::Ref(_, ty, _) => inner(ty, depth + 1), - _ => (ty, depth), - } +/// Checks if the given expression is the else clause of either an `if` or `if let` expression. +pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { + let map = tcx.hir(); + let mut iter = map.parent_iter(expr.hir_id); + match iter.next() { + Some((arm_id, Node::Arm(..))) => matches!( + iter.next(), + Some(( + _, + Node::Expr(Expr { + kind: ExprKind::Match(_, [_, else_arm], MatchSource::IfLetDesugar { .. }), + .. + }) + )) + if else_arm.hir_id == arm_id + ), + Some(( + _, + Node::Expr(Expr { + kind: ExprKind::If(_, _, Some(else_expr)), + .. + }), + )) => else_expr.hir_id == expr.hir_id, + _ => false, } - inner(ty, 0) } /// Checks whether the given expression is a constant integer of the given value. @@ -1173,26 +986,6 @@ pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> cx.tcx.erase_late_bound_regions(ret_ty) } -/// Walks into `ty` and returns `true` if any inner type is the same as `other_ty` -pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool { - ty.walk().any(|inner| match inner.unpack() { - GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty), - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, - }) -} - -/// Returns `true` if the given type is an `unsafe` function. -pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, - _ => false, - } -} - -pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env) -} - /// Checks if an expression is constructing a tuple-like enum variant or struct pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let ExprKind::Call(ref fun, _) = expr.kind { @@ -1241,11 +1034,13 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { }, PatKind::Slice(ref head, ref middle, ref tail) => { match &cx.typeck_results().node_type(pat.hir_id).kind() { - ty::Slice(..) => { + rustc_ty::Slice(..) => { // [..] is the only irrefutable slice pattern. !head.is_empty() || middle.is_none() || !tail.is_empty() }, - 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()).map(|pat| &**pat)) + }, _ => { // unreachable!() true @@ -1255,6 +1050,16 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { } } +/// If the pattern is an `or` pattern, call the function once for each sub pattern. Otherwise, call +/// 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) + } else { + f(pat) + } +} + /// Checks for the `#[automatically_derived]` attribute all `#[derive]`d /// implementations have. pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool { @@ -1300,11 +1105,11 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl It /// Checks if a given expression is a match expression expanded from the `?` /// operator or the `try` macro. -pub fn is_try<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { - fn is_ok(arm: &Arm<'_>) -> bool { +pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { if_chain! { if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pat.kind; - if match_qpath(path, &paths::RESULT_OK[1..]); + if is_lang_ctor(cx, path, ResultOk); if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind; if path_to_local_id(arm.body, hir_id); then { @@ -1314,9 +1119,9 @@ pub fn is_try<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { false } - fn is_err(arm: &Arm<'_>) -> bool { + fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind { - match_qpath(path, &paths::RESULT_ERR[1..]) + is_lang_ctor(cx, path, ResultErr) } else { false } @@ -1332,8 +1137,8 @@ pub fn is_try<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if arms.len() == 2; if arms[0].guard.is_none(); if arms[1].guard.is_none(); - if (is_ok(&arms[0]) && is_err(&arms[1])) || - (is_ok(&arms[1]) && is_err(&arms[0])); + if (is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) || + (is_ok(cx, &arms[1]) && is_err(cx, &arms[0])); then { return Some(expr); } @@ -1357,64 +1162,31 @@ pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> { pat } -pub fn int_bits(tcx: TyCtxt<'_>, ity: ty::IntTy) -> u64 { +pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 { Integer::from_int_ty(&tcx, ity).size().bits() } #[allow(clippy::cast_possible_wrap)] /// Turn a constant int byte representation into an i128 -pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: ty::IntTy) -> i128 { +pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 { let amt = 128 - int_bits(tcx, ity); ((u as i128) << amt) >> amt } #[allow(clippy::cast_sign_loss)] /// clip unused bytes -pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: ty::IntTy) -> u128 { +pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 { let amt = 128 - int_bits(tcx, ity); ((u as u128) << amt) >> amt } /// clip unused bytes -pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: ty::UintTy) -> u128 { +pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 { let bits = Integer::from_uint_ty(&tcx, ity).size().bits(); let amt = 128 - bits; (u << amt) >> amt } -/// Removes block comments from the given `Vec` of lines. -/// -/// # Examples -/// -/// ```rust,ignore -/// without_block_comments(vec!["/*", "foo", "*/"]); -/// // => vec![] -/// -/// without_block_comments(vec!["bar", "/*", "foo", "*/"]); -/// // => vec!["bar"] -/// ``` -pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { - let mut without = vec![]; - - let mut nest_level = 0; - - for line in lines { - if line.contains("/*") { - nest_level += 1; - continue; - } else if line.contains("*/") { - nest_level -= 1; - continue; - } - - if nest_level == 0 { - without.push(line); - } - } - - without -} - pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool { let map = &tcx.hir(); let mut prev_enclosing_node = None; @@ -1429,47 +1201,6 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool false } -/// Returns true if ty has `iter` or `iter_mut` methods -pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> { - // FIXME: instead of this hard-coded list, we should check if `<adt>::iter` - // exists and has the desired signature. Unfortunately FnCtxt is not exported - // so we can't use its `lookup_method` method. - let into_iter_collections: &[Symbol] = &[ - sym::vec_type, - sym::option_type, - sym::result_type, - sym::BTreeMap, - sym::BTreeSet, - sym::vecdeque_type, - sym::LinkedList, - sym::BinaryHeap, - sym::hashset_type, - sym::hashmap_type, - sym::PathBuf, - sym::Path, - sym::Receiver, - ]; - - let ty_to_check = match probably_ref_ty.kind() { - ty::Ref(_, ty_to_check, _) => ty_to_check, - _ => probably_ref_ty, - }; - - let def_id = match ty_to_check.kind() { - ty::Array(..) => return Some(sym::array), - ty::Slice(..) => return Some(sym::slice), - ty::Adt(adt, _) => adt.did, - _ => return None, - }; - - for &name in into_iter_collections { - if cx.tcx.is_diagnostic_item(name, def_id) { - return Some(cx.tcx.item_name(def_id)); - } - } - None -} - /// Matches a function call with the given path and returns the arguments. /// /// Usage: @@ -1494,85 +1225,56 @@ pub fn match_function_call<'tcx>( None } -// FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize -// this function can be removed once the `normalizie` method does not panic when normalization does -// not succeed -/// Checks if `Ty` is normalizable. This function is useful -/// to avoid crashes on `layout_of`. -pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { - is_normalizable_helper(cx, param_env, ty, &mut HashMap::new()) -} - -fn is_normalizable_helper<'tcx>( - cx: &LateContext<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - cache: &mut HashMap<Ty<'tcx>, bool>, -) -> bool { - if let Some(&cached_result) = cache.get(ty) { - return cached_result; - } - // prevent recursive loops, false-negative is better than endless loop leading to stack overflow - cache.insert(ty, false); - let result = cx.tcx.infer_ctxt().enter(|infcx| { - let cause = rustc_middle::traits::ObligationCause::dummy(); - if infcx.at(&cause, param_env).normalize(ty).is_ok() { - match ty.kind() { - ty::Adt(def, substs) => def.variants.iter().all(|variant| { - variant - .fields - .iter() - .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache)) - }), - _ => ty.walk().all(|generic_arg| match generic_arg.unpack() { - GenericArgKind::Type(inner_ty) if inner_ty != ty => { - is_normalizable_helper(cx, param_env, inner_ty, cache) - }, - _ => true, // if inner_ty == ty, we've already checked it - }), - } - } else { - false - } - }); - cache.insert(ty, result); - result +/// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if +/// any. +pub fn match_any_def_paths(cx: &LateContext<'_>, did: DefId, paths: &[&[&str]]) -> Option<usize> { + let search_path = cx.get_def_path(did); + paths + .iter() + .position(|p| p.iter().map(|x| Symbol::intern(x)).eq(search_path.iter().copied())) } +/// Checks if the given `DefId` matches the path. pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) -> bool { - // We have to convert `syms` to `&[Symbol]` here because rustc's `match_def_path` - // accepts only that. We should probably move to Symbols in Clippy as well. - let syms = syms.iter().map(|p| Symbol::intern(p)).collect::<Vec<Symbol>>(); - cx.match_def_path(did, &syms) + // We should probably move to Symbols in Clippy as well rather than interning every time. + let path = cx.get_def_path(did); + syms.iter().map(|x| Symbol::intern(x)).eq(path.iter().copied()) } -pub fn match_panic_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx [Expr<'tcx>]> { - match_function_call(cx, expr, &paths::BEGIN_PANIC) - .or_else(|| match_function_call(cx, expr, &paths::BEGIN_PANIC_FMT)) - .or_else(|| match_function_call(cx, expr, &paths::PANIC_ANY)) - .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC)) - .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC_FMT)) - .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC_STR)) +pub fn match_panic_call(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::Call(func, [arg]) = expr.kind { + expr_path_res(cx, func) + .opt_def_id() + .map_or(false, |id| match_panic_def_id(cx, id)) + .then(|| arg) + } else { + None + } } pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool { - match_def_path(cx, did, &paths::BEGIN_PANIC) - || match_def_path(cx, did, &paths::BEGIN_PANIC_FMT) - || match_def_path(cx, did, &paths::PANIC_ANY) - || match_def_path(cx, did, &paths::PANICKING_PANIC) - || match_def_path(cx, did, &paths::PANICKING_PANIC_FMT) - || match_def_path(cx, did, &paths::PANICKING_PANIC_STR) + match_any_def_paths( + cx, + did, + &[ + &paths::BEGIN_PANIC, + &paths::BEGIN_PANIC_FMT, + &paths::PANIC_ANY, + &paths::PANICKING_PANIC, + &paths::PANICKING_PANIC_FMT, + &paths::PANICKING_PANIC_STR, + ], + ) + .is_some() } /// Returns the list of condition expressions and the list of blocks in a /// sequence of `if/else`. /// E.g., this returns `([a, b], [c, d, e])` for the expression /// `if a { c } else if b { d } else { e }`. -pub fn if_sequence<'tcx>( - mut expr: &'tcx Expr<'tcx>, -) -> (SmallVec<[&'tcx Expr<'tcx>; 1]>, SmallVec<[&'tcx Block<'tcx>; 1]>) { - let mut conds = SmallVec::new(); - let mut blocks: SmallVec<[&Block<'_>; 1]> = SmallVec::new(); +pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, Vec<&'tcx Block<'tcx>>) { + let mut conds = Vec::new(); + let mut blocks: Vec<&Block<'_>> = Vec::new(); while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind { conds.push(&**cond); @@ -1599,67 +1301,9 @@ pub fn if_sequence<'tcx>( (conds, blocks) } -pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool { - let map = cx.tcx.hir(); - let parent_id = map.get_parent_node(expr.hir_id); - let parent_node = map.get(parent_id); - matches!( - parent_node, - Node::Expr(Expr { - kind: ExprKind::If(_, _, _), - .. - }) - ) -} - -// Finds the attribute with the given name, if any -pub fn attr_by_name<'a>(attrs: &'a [Attribute], name: &'_ str) -> Option<&'a Attribute> { - attrs - .iter() - .find(|attr| attr.ident().map_or(false, |ident| ident.as_str() == name)) -} - // Finds the `#[must_use]` attribute, if any pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> { - attr_by_name(attrs, "must_use") -} - -// Returns whether the type has #[must_use] attribute -pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.kind() { - ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(), - ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(), - ty::Slice(ref ty) - | ty::Array(ref ty, _) - | ty::RawPtr(ty::TypeAndMut { ref ty, .. }) - | ty::Ref(_, ref ty, _) => { - // for the Array case we don't need to care for the len == 0 case - // because we don't want to lint functions returning empty arrays - is_must_use_ty(cx, *ty) - }, - ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), - ty::Opaque(ref def_id, _) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { - if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() { - if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() { - return true; - } - } - } - false - }, - ty::Dynamic(binder, _) => { - for predicate in binder.iter() { - if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { - if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() { - return true; - } - } - } - false - }, - _ => false, - } + attrs.iter().find(|a| a.has_name(sym::must_use)) } // check if expr is calling method or function with #[must_use] attribute @@ -1681,6 +1325,51 @@ 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()) } +/// 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(); + let mut child_id = expr.hir_id; + let mut iter = map.parent_iter(child_id); + loop { + match iter.next() { + None => break None, + Some((id, Node::Block(_))) => child_id = id, + Some((id, Node::Arm(arm))) if arm.body.hir_id == child_id => child_id = id, + Some((_, Node::Expr(expr))) => match expr.kind { + ExprKind::Match(_, [arm], _) if arm.hir_id == child_id => child_id = expr.hir_id, + ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = expr.hir_id, + ExprKind::If(_, then_expr, None) if then_expr.hir_id == child_id => break None, + _ => break Some(Node::Expr(expr)), + }, + Some((_, node)) => break Some(node), + } + } +} + +/// Checks if the result of an expression is used, or it's type is unified with another branch. +pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { + !matches!( + get_expr_use_or_unification_node(tcx, expr), + None | Some(Node::Stmt(Stmt { + kind: StmtKind::Expr(_) + | StmtKind::Semi(_) + | StmtKind::Local(Local { + pat: Pat { + kind: PatKind::Wild, + .. + }, + .. + }), + .. + })) + ) +} + +/// Checks if the expression is the final expression returned from a block. +pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { + matches!(get_parent_node(tcx, expr.hir_id), Some(Node::Block(..))) +} + pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool { cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| { if let ast::AttrKind::Normal(ref attr, _) = attr.kind { @@ -1747,6 +1436,16 @@ 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!( @@ -1756,18 +1455,6 @@ pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bo }) } -/// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point -/// number type, a str, or an array, slice, or tuple of those types). -pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool { - match ty.kind() { - ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true, - ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true, - ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type), - ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type), - _ => false, - } -} - /// 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. @@ -1775,9 +1462,9 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S let expr_type = cx.typeck_results().expr_ty_adjusted(expr); let expr_kind = expr_type.kind(); let is_primitive = match expr_kind { - ty::Slice(element_type) => is_recursively_primitive_type(element_type), - ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &ty::Slice(_)) => { - if let ty::Slice(element_type) = inner_ty.kind() { + rustc_ty::Slice(element_type) => is_recursively_primitive_type(element_type), + rustc_ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &rustc_ty::Slice(_)) => { + if let rustc_ty::Slice(element_type) = inner_ty.kind() { is_recursively_primitive_type(element_type) } else { unreachable!() @@ -1790,9 +1477,9 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S // if we have wrappers like Array, Slice or Tuple, print these // and get the type enclosed in the slice ref match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() { - ty::Slice(..) => return Some("slice".into()), - ty::Array(..) => return Some("array".into()), - ty::Tuple(..) => return Some("tuple".into()), + rustc_ty::Slice(..) => return Some("slice".into()), + rustc_ty::Array(..) => return Some("array".into()), + rustc_ty::Tuple(..) => return Some("tuple".into()), _ => { // is_recursively_primitive_type() should have taken care // of the rest and we can rely on the type that is found @@ -1852,54 +1539,43 @@ pub fn peel_hir_pat_refs(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) { peel(pat, 0) } +/// Peels of expressions while the given closure returns `Some`. +pub fn peel_hir_expr_while<'tcx>( + mut expr: &'tcx Expr<'tcx>, + mut f: impl FnMut(&'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>>, +) -> &'tcx Expr<'tcx> { + while let Some(e) = f(expr) { + expr = e; + } + expr +} + /// Peels off up to the given number of references on the expression. Returns the underlying /// expression and the number of references removed. pub fn peel_n_hir_expr_refs(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) { - fn f(expr: &'a Expr<'a>, count: usize, target: usize) -> (&'a Expr<'a>, usize) { - match expr.kind { - ExprKind::AddrOf(_, _, expr) if count != target => f(expr, count + 1, target), - _ => (expr, count), - } - } - f(expr, 0, count) + let mut remaining = count; + let e = peel_hir_expr_while(expr, |e| match e.kind { + ExprKind::AddrOf(BorrowKind::Ref, _, e) if remaining != 0 => { + remaining -= 1; + Some(e) + }, + _ => None, + }); + (e, count - remaining) } /// Peels off all references on the expression. Returns the underlying expression and the number of /// references removed. pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) { - fn f(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) { - match expr.kind { - ExprKind::AddrOf(BorrowKind::Ref, _, expr) => f(expr, count + 1), - _ => (expr, count), - } - } - f(expr, 0) -} - -/// Peels off all references on the type. Returns the underlying type and the number of references -/// removed. -pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) { - fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) { - if let ty::Ref(_, ty, _) = ty.kind() { - peel(ty, count + 1) - } else { - (ty, count) - } - } - peel(ty, 0) -} - -/// Peels off all references on the type.Returns the underlying type, the number of references -/// removed, and whether the pointer is ultimately mutable or not. -pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { - fn f(ty: Ty<'_>, count: usize, mutability: Mutability) -> (Ty<'_>, usize, Mutability) { - match ty.kind() { - ty::Ref(_, ty, Mutability::Mut) => f(ty, count + 1, mutability), - ty::Ref(_, ty, Mutability::Not) => f(ty, count + 1, Mutability::Not), - _ => (ty, count, mutability), - } - } - f(ty, 0, Mutability::Mut) + let mut count = 0; + let e = peel_hir_expr_while(expr, |e| match e.kind { + ExprKind::AddrOf(BorrowKind::Ref, _, e) => { + count += 1; + Some(e) + }, + _ => None, + }); + (e, count) } #[macro_export] @@ -1931,124 +1607,3 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { } } } - -/// Check if the resolution of a given path is an `Ok` variant of `Result`. -pub fn is_ok_ctor(cx: &LateContext<'_>, res: Res) -> bool { - if let Some(ok_id) = cx.tcx.lang_items().result_ok_variant() { - if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res { - if let Some(variant_id) = cx.tcx.parent(id) { - return variant_id == ok_id; - } - } - } - false -} - -/// Check if the resolution of a given path is a `Some` variant of `Option`. -pub fn is_some_ctor(cx: &LateContext<'_>, res: Res) -> bool { - if let Some(some_id) = cx.tcx.lang_items().option_some_variant() { - if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res { - if let Some(variant_id) = cx.tcx.parent(id) { - return variant_id == some_id; - } - } - } - false -} - -#[cfg(test)] -mod test { - use super::{reindent_multiline, without_block_comments}; - - #[test] - fn test_reindent_multiline_single_line() { - assert_eq!("", reindent_multiline("".into(), false, None)); - assert_eq!("...", reindent_multiline("...".into(), false, None)); - assert_eq!("...", reindent_multiline(" ...".into(), false, None)); - assert_eq!("...", reindent_multiline("\t...".into(), false, None)); - assert_eq!("...", reindent_multiline("\t\t...".into(), false, None)); - } - - #[test] - #[rustfmt::skip] - fn test_reindent_multiline_block() { - assert_eq!("\ - if x { - y - } else { - z - }", reindent_multiline(" if x { - y - } else { - z - }".into(), false, None)); - assert_eq!("\ - if x { - \ty - } else { - \tz - }", reindent_multiline(" if x { - \ty - } else { - \tz - }".into(), false, None)); - } - - #[test] - #[rustfmt::skip] - fn test_reindent_multiline_empty_line() { - assert_eq!("\ - if x { - y - - } else { - z - }", reindent_multiline(" if x { - y - - } else { - z - }".into(), false, None)); - } - - #[test] - #[rustfmt::skip] - fn test_reindent_multiline_lines_deeper() { - assert_eq!("\ - if x { - y - } else { - z - }", reindent_multiline("\ - if x { - y - } else { - z - }".into(), true, Some(8))); - } - - #[test] - fn test_without_block_comments_lines_without_block_comments() { - let result = without_block_comments(vec!["/*", "", "*/"]); - println!("result: {:?}", result); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); - assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); - - let result = without_block_comments(vec!["/* rust", "", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* one-line comment */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["foo", "bar", "baz"]); - assert_eq!(result, vec!["foo", "bar", "baz"]); - } -} diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs new file mode 100644 index 0000000000..00df04c014 --- /dev/null +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -0,0 +1,29 @@ +use rustc_semver::RustcVersion; + +macro_rules! msrv_aliases { + ($($major:literal,$minor:literal,$patch:literal { + $($name:ident),* $(,)? + })*) => { + $($( + pub const $name: RustcVersion = RustcVersion::new($major, $minor, $patch); + )*)* + }; +} + +// names may refer to stabilized feature flags or library items +msrv_aliases! { + 1,53,0 { OR_PATTERNS } + 1,50,0 { BOOL_THEN } + 1,46,0 { CONST_IF_MATCH } + 1,45,0 { STR_STRIP_PREFIX } + 1,42,0 { MATCHES_MACRO } + 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE } + 1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF } + 1,38,0 { POINTER_CAST } + 1,37,0 { TYPE_ALIAS_ENUM_VARIANTS } + 1,36,0 { ITERATOR_COPIED } + 1,35,0 { OPTION_COPIED, RANGE_CONTAINS } + 1,34,0 { TRY_FROM } + 1,30,0 { ITERATOR_FIND_MAP } + 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST } +} diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs index d02603d770..268bc5b320 100644 --- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs +++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs @@ -1,4 +1,5 @@ use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind}; +use std::iter; #[derive(Debug, PartialEq, Copy, Clone)] pub enum Radix { @@ -192,7 +193,7 @@ impl<'a> NumericLiteral<'a> { } } - for (c, i) in digits.zip((0..group_size).cycle()) { + for (c, i) in iter::zip(digits, (0..group_size).cycle()) { if i == 0 { output.push('_'); } diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index d884659dfb..0d4c2ae4ee 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -4,7 +4,7 @@ //! Whenever possible, please consider diagnostic items over hardcoded paths. //! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information. -pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"]; +pub const ANY_TRAIT: [&str; 3] = ["core", "any", "Any"]; pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; @@ -13,19 +13,20 @@ pub(super) const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_ pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"]; pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"]; +pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"]; pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "entry", "Entry"]; +pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"]; pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"]; pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"]; pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; -pub const COPY: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"]; -pub const COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["std", "ffi", "c_str", "CString", "as_c_str"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; 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"]; @@ -43,10 +44,14 @@ pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments 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"]; +pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"]; pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; pub const HASH: [&str; 3] = ["core", "hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; +pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; +pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"]; pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"]; #[cfg(feature = "internal-lints")] pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"]; @@ -59,9 +64,9 @@ pub const INTO: [&str; 3] = ["core", "convert", "Into"]; pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; -pub const IPADDR_V4: [&str; 4] = ["std", "net", "IpAddr", "V4"]; -pub const IPADDR_V6: [&str; 4] = ["std", "net", "IpAddr", "V6"]; -pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"]; +pub const IPADDR_V4: [&str; 5] = ["std", "net", "ip", "IpAddr", "V4"]; +pub const IPADDR_V6: [&str; 5] = ["std", "net", "ip", "IpAddr", "V6"]; +pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat"]; #[cfg(feature = "internal-lints")] pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"]; #[cfg(feature = "internal-lints")] @@ -93,18 +98,30 @@ pub(super) const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 2] = ["parking_lot", "MutexGuard"]; pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 2] = ["parking_lot", "RwLockReadGuard"]; pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 2] = ["parking_lot", "RwLockWriteGuard"]; -pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; +pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"]; +pub const PERMISSIONS_FROM_MODE: [&str; 7] = ["std", "sys", "unix", "ext", "fs", "PermissionsExt", "from_mode"]; pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"]; pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"]; +pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"]; +pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"]; pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; pub const PTR_NULL: [&str; 3] = ["core", "ptr", "null"]; pub const PTR_NULL_MUT: [&str; 3] = ["core", "ptr", "null_mut"]; pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"]; pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"]; pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"]; +pub const PTR_READ: [&str; 3] = ["core", "ptr", "read"]; +pub const PTR_READ_UNALIGNED: [&str; 3] = ["core", "ptr", "read_unaligned"]; +pub const PTR_READ_VOLATILE: [&str; 3] = ["core", "ptr", "read_volatile"]; +pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"]; +pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"]; +pub const PTR_WRITE: [&str; 3] = ["core", "ptr", "write"]; +pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"]; +pub const PTR_WRITE_UNALIGNED: [&str; 3] = ["core", "ptr", "write_unaligned"]; +pub const PTR_WRITE_VOLATILE: [&str; 3] = ["core", "ptr", "write_volatile"]; pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"]; @@ -116,7 +133,6 @@ pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"]; pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; -pub const REPEAT: [&str; 3] = ["core", "iter", "repeat"]; pub const RESULT: [&str; 3] = ["core", "result", "Result"]; pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"]; pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"]; @@ -130,10 +146,8 @@ pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"]; pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"]; pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"]; -pub const STD_CONVERT_IDENTITY: [&str; 3] = ["std", "convert", "identity"]; +pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"]; pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"]; -pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"]; -pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"]; pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"]; pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"]; pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"]; diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs index df6143edbc..5885cc8356 100644 --- a/src/tools/clippy/clippy_utils/src/ptr.rs +++ b/src/tools/clippy/clippy_utils/src/ptr.rs @@ -1,4 +1,5 @@ -use crate::{get_pat_name, match_var, snippet}; +use crate::source::snippet; +use crate::{get_pat_name, match_var}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Body, BodyId, Expr, ExprKind, Param}; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1391f7505e..a08dcf19e5 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -1,3 +1,8 @@ +// This code used to be a part of `rustc` but moved to Clippy as a result of +// https://github.com/rust-lang/rust/issues/76618. Because of that, it contains unused code and some +// of terminologies might not be relevant in the context of Clippy. Note that its behavior might +// differ from the time of `rustc` even if the name stays the same. + use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::mir::{ @@ -6,6 +11,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; +use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi::Abi::RustIntrinsic; @@ -13,7 +19,7 @@ use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; -pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>) -> McfResult { +pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<&RustcVersion>) -> McfResult { let def_id = body.source.def_id(); let mut current = def_id; loop { @@ -70,7 +76,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>) -> McfResult { )?; for bb in body.basic_blocks() { - check_terminator(tcx, body, bb.terminator())?; + check_terminator(tcx, body, bb.terminator(), msrv)?; for stmt in &bb.statements { check_statement(tcx, body, def_id, stmt)?; } @@ -210,21 +216,19 @@ fn check_statement(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, statemen StatementKind::Assign(box (place, rval)) => { check_place(tcx, *place, span, body)?; check_rvalue(tcx, body, def_id, rval, span) - } + }, - StatementKind::FakeRead(_, place) | + StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body), // just an assignment StatementKind::SetDiscriminant { place, .. } => check_place(tcx, **place, span, body), StatementKind::LlvmInlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), - StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping{ - dst, src, count, - }) => { - check_operand(tcx, dst, span, body)?; - check_operand(tcx, src, span, body)?; - check_operand(tcx, count, span, body) - } + StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => { + check_operand(tcx, dst, span, body)?; + check_operand(tcx, src, span, body)?; + check_operand(tcx, count, span, body) + }, // These are all NOPs StatementKind::StorageLive(_) | StatementKind::StorageDead(_) @@ -270,7 +274,12 @@ fn check_place(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'t Ok(()) } -fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Terminator<'tcx>) -> McfResult { +fn check_terminator( + tcx: TyCtxt<'tcx>, + body: &'a Body<'tcx>, + terminator: &Terminator<'tcx>, + msrv: Option<&RustcVersion>, +) -> McfResult { let span = terminator.source_info.span; match &terminator.kind { TerminatorKind::FalseEdge { .. } @@ -307,7 +316,7 @@ fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Termin } => { let fn_ty = func.ty(body, tcx); if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() { - if !rustc_mir::const_eval::is_min_const_fn(tcx, fn_def_id) { + if !is_const_fn(tcx, fn_def_id, msrv) { return Err(( span, format!( @@ -352,3 +361,22 @@ fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Termin TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), } } + +fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<&RustcVersion>) -> bool { + rustc_mir::const_eval::is_const_fn(tcx, def_id) + && tcx.lookup_const_stability(def_id).map_or(true, |const_stab| { + if let rustc_attr::StabilityLevel::Stable { since } = const_stab.level { + // Checking MSRV is manually necessary because `rustc` has no such concept. This entire + // function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`. + // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. + crate::meets_msrv( + msrv, + &RustcVersion::parse(&since.as_str()) + .expect("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted"), + ) + } else { + // Unstable const fn with the feature enabled. + msrv.is_none() + } + }) +} diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs new file mode 100644 index 0000000000..53180d1f9f --- /dev/null +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -0,0 +1,429 @@ +//! Utils for extracting, inspecting or transforming source code + +#![allow(clippy::module_name_repetitions)] + +use crate::line_span; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LintContext}; +use rustc_span::hygiene; +use rustc_span::{BytePos, Pos, Span, SyntaxContext}; +use std::borrow::Cow; + +/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`. +/// Also takes an `Option<String>` which can be put inside the braces. +pub fn expr_block<'a, T: LintContext>( + cx: &T, + expr: &Expr<'_>, + option: Option<String>, + default: &'a str, + indent_relative_to: Option<Span>, +) -> Cow<'a, str> { + let code = snippet_block(cx, expr.span, default, indent_relative_to); + let string = option.unwrap_or_default(); + if expr.span.from_expansion() { + Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default))) + } else if let ExprKind::Block(_, _) = expr.kind { + Cow::Owned(format!("{}{}", code, string)) + } else if string.is_empty() { + Cow::Owned(format!("{{ {} }}", code)) + } else { + Cow::Owned(format!("{{\n{};\n{}\n}}", code, string)) + } +} + +/// Returns a new Span that extends the original Span to the first non-whitespace char of the first +/// line. +/// +/// ```rust,ignore +/// let x = (); +/// // ^^ +/// // will be converted to +/// let x = (); +/// // ^^^^^^^^^^ +/// ``` +pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span { + first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos)) +} + +fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> { + let line_span = line_span(cx, span); + snippet_opt(cx, line_span).and_then(|snip| { + snip.find(|c: char| !c.is_whitespace()) + .map(|pos| line_span.lo() + BytePos::from_usize(pos)) + }) +} + +/// Returns the indentation of the line of a span +/// +/// ```rust,ignore +/// let x = (); +/// // ^^ -- will return 0 +/// let x = (); +/// // ^^ -- will return 4 +/// ``` +pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> { + snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace())) +} + +/// Gets a snippet of the indentation of the line of a span +pub fn snippet_indent<T: LintContext>(cx: &T, span: Span) -> Option<String> { + snippet_opt(cx, line_span(cx, span)).map(|mut s| { + let len = s.len() - s.trim_start().len(); + s.truncate(len); + s + }) +} + +// If the snippet is empty, it's an attribute that was inserted during macro +// expansion and we want to ignore those, because they could come from external +// sources that the user has no control over. +// For some reason these attributes don't have any expansion info on them, so +// we have to check it this way until there is a better way. +pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool { + if let Some(snippet) = snippet_opt(cx, span) { + if snippet.is_empty() { + return false; + } + } + true +} + +/// Returns the positon just before rarrow +/// +/// ```rust,ignore +/// fn into(self) -> () {} +/// ^ +/// // in case of unformatted code +/// fn into2(self)-> () {} +/// ^ +/// fn into3(self) -> () {} +/// ^ +/// ``` +pub fn position_before_rarrow(s: &str) -> Option<usize> { + s.rfind("->").map(|rpos| { + let mut rpos = rpos; + let chars: Vec<char> = s.chars().collect(); + while rpos > 1 { + if let Some(c) = chars.get(rpos - 1) { + if c.is_whitespace() { + rpos -= 1; + continue; + } + } + break; + } + rpos + }) +} + +/// Reindent a multiline string with possibility of ignoring the first line. +#[allow(clippy::needless_pass_by_value)] +pub fn reindent_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> { + let s_space = reindent_multiline_inner(&s, ignore_first, indent, ' '); + let s_tab = reindent_multiline_inner(&s_space, ignore_first, indent, '\t'); + reindent_multiline_inner(&s_tab, ignore_first, indent, ' ').into() +} + +fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>, ch: char) -> String { + let x = s + .lines() + .skip(ignore_first as usize) + .filter_map(|l| { + if l.is_empty() { + None + } else { + // ignore empty lines + Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0) + } + }) + .min() + .unwrap_or(0); + let indent = indent.unwrap_or(0); + s.lines() + .enumerate() + .map(|(i, l)| { + if (ignore_first && i == 0) || l.is_empty() { + l.to_owned() + } else if x > indent { + l.split_at(x - indent).1.to_owned() + } else { + " ".repeat(indent - x) + l + } + }) + .collect::<Vec<String>>() + .join("\n") +} + +/// Converts a span to a code snippet if available, otherwise use default. +/// +/// This is useful if you want to provide suggestions for your lint or more generally, if you want +/// to convert a given `Span` to a `str`. +/// +/// # Example +/// ```rust,ignore +/// snippet(cx, expr.span, "..") +/// ``` +pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { + snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from) +} + +/// Same as `snippet`, but it adapts the applicability level by following rules: +/// +/// - Applicability level `Unspecified` will never be changed. +/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. +/// - If the default value is used and the applicability level is `MachineApplicable`, change it to +/// `HasPlaceholders` +pub fn snippet_with_applicability<'a, T: LintContext>( + cx: &T, + span: Span, + default: &'a str, + applicability: &mut Applicability, +) -> Cow<'a, str> { + if *applicability != Applicability::Unspecified && span.from_expansion() { + *applicability = Applicability::MaybeIncorrect; + } + snippet_opt(cx, span).map_or_else( + || { + if *applicability == Applicability::MachineApplicable { + *applicability = Applicability::HasPlaceholders; + } + Cow::Borrowed(default) + }, + From::from, + ) +} + +/// Same as `snippet`, but should only be used when it's clear that the input span is +/// not a macro argument. +pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { + snippet(cx, span.source_callsite(), default) +} + +/// Converts a span to a code snippet. Returns `None` if not available. +pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> { + cx.sess().source_map().span_to_snippet(span).ok() +} + +/// Converts a span (from a block) to a code snippet if available, otherwise use default. +/// +/// This trims the code of indentation, except for the first line. Use it for blocks or block-like +/// things which need to be printed as such. +/// +/// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the +/// resulting snippet of the given span. +/// +/// # Example +/// +/// ```rust,ignore +/// snippet_block(cx, block.span, "..", None) +/// // where, `block` is the block of the if expr +/// if x { +/// y; +/// } +/// // will return the snippet +/// { +/// y; +/// } +/// ``` +/// +/// ```rust,ignore +/// snippet_block(cx, block.span, "..", Some(if_expr.span)) +/// // where, `block` is the block of the if expr +/// if x { +/// y; +/// } +/// // will return the snippet +/// { +/// y; +/// } // aligned with `if` +/// ``` +/// Note that the first line of the snippet always has 0 indentation. +pub fn snippet_block<'a, T: LintContext>( + cx: &T, + span: Span, + default: &'a str, + indent_relative_to: Option<Span>, +) -> Cow<'a, str> { + let snip = snippet(cx, span, default); + let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); + reindent_multiline(snip, true, indent) +} + +/// Same as `snippet_block`, but adapts the applicability level by the rules of +/// `snippet_with_applicability`. +pub fn snippet_block_with_applicability<'a, T: LintContext>( + cx: &T, + span: Span, + default: &'a str, + indent_relative_to: Option<Span>, + applicability: &mut Applicability, +) -> Cow<'a, str> { + let snip = snippet_with_applicability(cx, span, default, applicability); + let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); + reindent_multiline(snip, true, indent) +} + +/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This +/// will result in the macro call, rather then the expansion, if the span is from a child context. +/// If the span is not from a child context, it will be used directly instead. +/// +/// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node +/// would result in `box []`. If given the context of the address of expression, this function will +/// correctly get a snippet of `vec![]`. +/// +/// This will also return whether or not the snippet is a macro call. +pub fn snippet_with_context( + cx: &LateContext<'_>, + span: Span, + outer: SyntaxContext, + default: &'a str, + applicability: &mut Applicability, +) -> (Cow<'a, str>, bool) { + let outer_span = hygiene::walk_chain(span, outer); + let (span, is_macro_call) = if outer_span.ctxt() == outer { + (outer_span, span.ctxt() != outer) + } else { + // The span is from a macro argument, and the outer context is the macro using the argument + if *applicability != Applicability::Unspecified { + *applicability = Applicability::MaybeIncorrect; + } + // TODO: get the argument span. + (span, false) + }; + + ( + snippet_with_applicability(cx, span, default, applicability), + is_macro_call, + ) +} + +/// Removes block comments from the given `Vec` of lines. +/// +/// # Examples +/// +/// ```rust,ignore +/// without_block_comments(vec!["/*", "foo", "*/"]); +/// // => vec![] +/// +/// without_block_comments(vec!["bar", "/*", "foo", "*/"]); +/// // => vec!["bar"] +/// ``` +pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { + let mut without = vec![]; + + let mut nest_level = 0; + + for line in lines { + if line.contains("/*") { + nest_level += 1; + continue; + } else if line.contains("*/") { + nest_level -= 1; + continue; + } + + if nest_level == 0 { + without.push(line); + } + } + + without +} + +#[cfg(test)] +mod test { + use super::{reindent_multiline, without_block_comments}; + + #[test] + fn test_reindent_multiline_single_line() { + assert_eq!("", reindent_multiline("".into(), false, None)); + assert_eq!("...", reindent_multiline("...".into(), false, None)); + assert_eq!("...", reindent_multiline(" ...".into(), false, None)); + assert_eq!("...", reindent_multiline("\t...".into(), false, None)); + assert_eq!("...", reindent_multiline("\t\t...".into(), false, None)); + } + + #[test] + #[rustfmt::skip] + fn test_reindent_multiline_block() { + assert_eq!("\ + if x { + y + } else { + z + }", reindent_multiline(" if x { + y + } else { + z + }".into(), false, None)); + assert_eq!("\ + if x { + \ty + } else { + \tz + }", reindent_multiline(" if x { + \ty + } else { + \tz + }".into(), false, None)); + } + + #[test] + #[rustfmt::skip] + fn test_reindent_multiline_empty_line() { + assert_eq!("\ + if x { + y + + } else { + z + }", reindent_multiline(" if x { + y + + } else { + z + }".into(), false, None)); + } + + #[test] + #[rustfmt::skip] + fn test_reindent_multiline_lines_deeper() { + assert_eq!("\ + if x { + y + } else { + z + }", reindent_multiline("\ + if x { + y + } else { + z + }".into(), true, Some(8))); + } + + #[test] + fn test_without_block_comments_lines_without_block_comments() { + let result = without_block_comments(vec!["/*", "", "*/"]); + println!("result: {:?}", result); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); + assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); + + let result = without_block_comments(vec!["/* rust", "", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* one-line comment */"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["foo", "bar", "baz"]); + assert_eq!(result, vec!["foo", "bar", "baz"]); + } +} diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index d4f6f4281d..0633a19391 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -1,7 +1,8 @@ //! Contains utility functions to generate suggestions. #![deny(clippy::missing_docs_in_private_items)] -use crate::{higher, snippet, snippet_opt, snippet_with_macro_callsite}; +use crate::higher; +use crate::source::{snippet, snippet_opt, snippet_with_macro_callsite}; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ast, token}; use rustc_ast_pretty::pprust::token_kind_to_string; @@ -266,17 +267,44 @@ impl<'a> Sugg<'a> { Sugg::NonParen(..) => self, // `(x)` and `(x).y()` both don't need additional parens. Sugg::MaybeParen(sugg) => { - if sugg.starts_with('(') && sugg.ends_with(')') { + if has_enclosing_paren(&sugg) { Sugg::MaybeParen(sugg) } else { Sugg::NonParen(format!("({})", sugg).into()) } }, - Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()), + Sugg::BinOp(_, sugg) => { + if has_enclosing_paren(&sugg) { + Sugg::NonParen(sugg) + } else { + Sugg::NonParen(format!("({})", sugg).into()) + } + }, } } } +/// Return `true` if `sugg` is enclosed in parenthesis. +fn has_enclosing_paren(sugg: impl AsRef<str>) -> bool { + let mut chars = sugg.as_ref().chars(); + if let Some('(') = chars.next() { + let mut depth = 1; + while let Some(c) = chars.next() { + if c == '(' { + depth += 1; + } else if c == ')' { + depth -= 1; + } + if depth == 0 { + break; + } + } + chars.next().is_none() + } else { + false + } +} + // Copied from the rust standart library, and then edited macro_rules! forward_binop_impls_to_ref { (impl $imp:ident, $method:ident for $t:ty, type Output = $o:ty) => { @@ -667,6 +695,8 @@ impl<T: LintContext> DiagnosticBuilderExt<T> for rustc_errors::DiagnosticBuilder #[cfg(test)] mod test { use super::Sugg; + + use rustc_ast::util::parser::AssocOp; use std::borrow::Cow; const SUGGESTION: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("function_call()")); @@ -680,4 +710,13 @@ mod test { fn blockify_transforms_sugg_into_a_block() { assert_eq!("{ function_call() }", SUGGESTION.blockify().to_string()); } + + #[test] + fn binop_maybe_par() { + let sugg = Sugg::BinOp(AssocOp::Add, "(1 + 1)".into()); + assert_eq!("(1 + 1)", sugg.maybe_par().to_string()); + + let sugg = Sugg::BinOp(AssocOp::Add, "(1 + 1) + (1 + 1)".into()); + assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string()); + } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs new file mode 100644 index 0000000000..64a80f2554 --- /dev/null +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -0,0 +1,324 @@ +//! Util methods for [`rustc_middle::ty`] + +#![allow(clippy::module_name_repetitions)] + +use std::collections::HashMap; + +use rustc_ast::ast::Mutability; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_hir::{TyKind, Unsafety}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_lint::LateContext; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; +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::traits::query::normalize::AtExt; + +use crate::{match_def_path, must_use_attr}; + +pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env) +} + +/// Checks whether a type can be partially moved. +pub fn can_partially_move_ty(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + if has_drop(cx, ty) || is_copy(cx, ty) { + return false; + } + match ty.kind() { + ty::Param(_) => false, + ty::Adt(def, subs) => def.all_fields().any(|f| !is_copy(cx, f.ty(cx.tcx, subs))), + _ => true, + } +} + +/// Walks into `ty` and returns `true` if any inner type is the same as `other_ty` +pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool { + ty.walk().any(|inner| match inner.unpack() { + GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty), + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + }) +} + +/// Walks into `ty` and returns `true` if any inner type is an instance of the given adt +/// constructor. +pub fn contains_adt_constructor(ty: Ty<'_>, adt: &AdtDef) -> bool { + ty.walk().any(|inner| match inner.unpack() { + GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt), + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + }) +} + +/// Resolves `<T as Iterator>::Item` for `T` +/// Do not invoke without first verifying that the type implements `Iterator` +pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { + cx.tcx + .get_diagnostic_item(sym::Iterator) + .and_then(|iter_did| { + cx.tcx.associated_items(iter_did).find_by_name_and_kind( + cx.tcx, + Ident::from_str("Item"), + ty::AssocKind::Type, + iter_did, + ) + }) + .map(|assoc| { + let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, &[])); + cx.tcx.normalize_erasing_regions(cx.param_env, proj) + }) +} + +/// Returns true if ty has `iter` or `iter_mut` methods +pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> { + // FIXME: instead of this hard-coded list, we should check if `<adt>::iter` + // exists and has the desired signature. Unfortunately FnCtxt is not exported + // so we can't use its `lookup_method` method. + let into_iter_collections: &[Symbol] = &[ + sym::vec_type, + sym::option_type, + sym::result_type, + sym::BTreeMap, + sym::BTreeSet, + sym::vecdeque_type, + sym::LinkedList, + sym::BinaryHeap, + sym::hashset_type, + sym::hashmap_type, + sym::PathBuf, + sym::Path, + sym::Receiver, + ]; + + let ty_to_check = match probably_ref_ty.kind() { + ty::Ref(_, ty_to_check, _) => ty_to_check, + _ => probably_ref_ty, + }; + + let def_id = match ty_to_check.kind() { + ty::Array(..) => return Some(sym::array), + ty::Slice(..) => return Some(sym::slice), + ty::Adt(adt, _) => adt.did, + _ => return None, + }; + + for &name in into_iter_collections { + if cx.tcx.is_diagnostic_item(name, def_id) { + return Some(cx.tcx.item_name(def_id)); + } + } + None +} + +/// Checks whether a type implements a trait. +/// See also `get_trait_def_id`. +pub fn implements_trait<'tcx>( + cx: &LateContext<'tcx>, + ty: Ty<'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; + } + 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)) +} + +/// Checks whether this type implements `Drop`. +pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.ty_adt_def() { + Some(def) => def.has_dtor(cx.tcx), + None => false, + } +} + +// Returns whether the type has #[must_use] attribute +pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.kind() { + ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(), + ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(), + ty::Slice(ref ty) + | ty::Array(ref ty, _) + | ty::RawPtr(ty::TypeAndMut { ref ty, .. }) + | ty::Ref(_, ref ty, _) => { + // for the Array case we don't need to care for the len == 0 case + // because we don't want to lint functions returning empty arrays + is_must_use_ty(cx, *ty) + }, + ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), + ty::Opaque(ref def_id, _) => { + for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { + if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() { + if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() { + return true; + } + } + } + false + }, + ty::Dynamic(binder, _) => { + for predicate in binder.iter() { + if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { + if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() { + return true; + } + } + } + false + }, + _ => false, + } +} + +// FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize +// this function can be removed once the `normalizie` method does not panic when normalization does +// not succeed +/// Checks if `Ty` is normalizable. This function is useful +/// to avoid crashes on `layout_of`. +pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { + is_normalizable_helper(cx, param_env, ty, &mut HashMap::new()) +} + +fn is_normalizable_helper<'tcx>( + cx: &LateContext<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + cache: &mut HashMap<Ty<'tcx>, bool>, +) -> bool { + if let Some(&cached_result) = cache.get(ty) { + return cached_result; + } + // prevent recursive loops, false-negative is better than endless loop leading to stack overflow + cache.insert(ty, false); + let result = cx.tcx.infer_ctxt().enter(|infcx| { + let cause = rustc_middle::traits::ObligationCause::dummy(); + if infcx.at(&cause, param_env).normalize(ty).is_ok() { + match ty.kind() { + ty::Adt(def, substs) => def.variants.iter().all(|variant| { + variant + .fields + .iter() + .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache)) + }), + _ => ty.walk().all(|generic_arg| match generic_arg.unpack() { + GenericArgKind::Type(inner_ty) if inner_ty != ty => { + is_normalizable_helper(cx, param_env, inner_ty, cache) + }, + _ => true, // if inner_ty == ty, we've already checked it + }), + } + } else { + false + } + }); + cache.insert(ty, result); + result +} + +/// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point +/// number type, a str, or an array, slice, or tuple of those types). +pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool { + match ty.kind() { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true, + ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true, + ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type), + ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type), + _ => false, + } +} + +/// Checks if the type is equal to a diagnostic item +/// +/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem` +pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool { + match ty.kind() { + ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did), + _ => false, + } +} + +/// Checks if the type is equal to a lang item +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, + _ => false, + } +} + +/// Return `true` if the passed `typ` is `isize` or `usize`. +pub fn is_isize_or_usize(typ: Ty<'_>) -> bool { + matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize)) +} + +/// Checks if type is struct, enum or union type with the given def path. +/// +/// If the type is a diagnostic item, use `is_type_diagnostic_item` instead. +/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem` +pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool { + match ty.kind() { + ty::Adt(adt, _) => match_def_path(cx, adt.did, path), + _ => false, + } +} + +/// Peels off all references on the type. Returns the underlying type and the number of references +/// removed. +pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) { + fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) { + if let ty::Ref(_, ty, _) = ty.kind() { + peel(ty, count + 1) + } else { + (ty, count) + } + } + peel(ty, 0) +} + +/// Peels off all references on the type.Returns the underlying type, the number of references +/// removed, and whether the pointer is ultimately mutable or not. +pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { + fn f(ty: Ty<'_>, count: usize, mutability: Mutability) -> (Ty<'_>, usize, Mutability) { + match ty.kind() { + ty::Ref(_, ty, Mutability::Mut) => f(ty, count + 1, mutability), + ty::Ref(_, ty, Mutability::Not) => f(ty, count + 1, Mutability::Not), + _ => (ty, count, mutability), + } + } + f(ty, 0, Mutability::Mut) +} + +/// Returns `true` if the given type is an `unsafe` function. +pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.kind() { + ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, + _ => false, + } +} + +/// Returns the base type for HIR references and pointers. +pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { + match ty.kind { + TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), + _ => ty, + } +} + +/// Returns the base type for references and raw pointers, and count reference +/// depth. +pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) { + fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) { + match ty.kind() { + ty::Ref(_, ty, _) => inner(ty, depth + 1), + _ => (ty, depth), + } + } + inner(ty, 0) +} diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index 0b1ab6b7ea..650b70c63a 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -1,21 +1,21 @@ use crate as utils; -use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::intravisit; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc_hir::HirIdSet; use rustc_hir::{Expr, ExprKind, HirId, Path}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; -use rustc_middle::mir::FakeReadCause; 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}; /// 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<FxHashSet<HirId>> { +pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> Option<HirIdSet> { let mut delegate = MutVarsDelegate { - used_mutably: FxHashSet::default(), + used_mutably: HirIdSet::default(), skip: false, }; cx.tcx.infer_ctxt().enter(|infcx| { @@ -44,7 +44,7 @@ pub fn is_potentially_mutated<'tcx>(variable: &'tcx Path<'_>, expr: &'tcx Expr<' } struct MutVarsDelegate { - used_mutably: FxHashSet<HirId>, + used_mutably: HirIdSet, skip: bool, } @@ -79,7 +79,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { self.update(&cmt) } - fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _:HirId) { } + fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {} } pub struct ParamBindingIdCollector { diff --git a/src/tools/clippy/doc/adding_lints.md b/src/tools/clippy/doc/adding_lints.md index 575853996c..d6cc6d0c2c 100644 --- a/src/tools/clippy/doc/adding_lints.md +++ b/src/tools/clippy/doc/adding_lints.md @@ -18,7 +18,7 @@ because that's clearly a non-descriptive name. - [Lint passes](#lint-passes) - [Emitting a lint](#emitting-a-lint) - [Adding the lint logic](#adding-the-lint-logic) - - [Specifying the lint's minimum supported Rust version (msrv)](#specifying-the-lints-minimum-supported-rust-version-msrv) + - [Specifying the lint's minimum supported Rust version (MSRV)](#specifying-the-lints-minimum-supported-rust-version-msrv) - [Author lint](#author-lint) - [Documentation](#documentation) - [Running rustfmt](#running-rustfmt) @@ -388,18 +388,25 @@ pass. [`FnKind::Fn`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html#variant.Fn [ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html -## Specifying the lint's minimum supported Rust version (msrv) +## Specifying the lint's minimum supported Rust version (MSRV) -Projects supporting older versions of Rust would need to disable a lint if it targets features -present in later versions. Support for this can be added by specifying an msrv in your lint like so, +Sometimes a lint makes suggestions that require a certain version of Rust. For example, the `manual_strip` lint suggests +using `str::strip_prefix` and `str::strip_suffix` which is only available after Rust 1.45. In such cases, you need to +ensure that the MSRV configured for the project is >= the MSRV of the required Rust feature. If multiple features are +required, just use the one with a lower MSRV. + +First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`](/clippy_utils/src/msrvs.rs). This can be +accessed later as `msrvs::STR_STRIP_PREFIX`, for example. ```rust -const MANUAL_STRIP_MSRV: RustcVersion = RustcVersion::new(1, 45, 0); +msrv_aliases! { + .. + 1,45,0 { STR_STRIP_PREFIX } +} ``` -The project's msrv will also have to be an attribute in the lint so you'll have to add a struct -and constructor for your lint. The project's msrv needs to be passed when the lint is registered -in `lib.rs` +In order to access the project-configured MSRV, you need to have an `msrv` field in the LintPass struct, and a +constructor to initialize the field. The `msrv` value is passed to the constructor in `clippy_lints/lib.rs`. ```rust pub struct ManualStrip { @@ -414,18 +421,19 @@ impl ManualStrip { } ``` -The project's msrv can then be matched against the lint's msrv in the LintPass using the `meets_msrv` utility -function. +The project's MSRV can then be matched against the feature MSRV in the LintPass +using the `meets_msrv` utility function. ``` rust -if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) { +if !meets_msrv(self.msrv.as_ref(), &msrvs::STR_STRIP_PREFIX) { return; } ``` -The project's msrv can also be specified as an inner attribute, which overrides the value from -`clippy.toml`. This can be accounted for using the `extract_msrv_attr!(LintContext)` macro and passing -LateContext/EarlyContext. +The project's MSRV can also be specified as an inner attribute, which overrides +the value from `clippy.toml`. This can be accounted for using the +`extract_msrv_attr!(LintContext)` macro and passing +`LateContext`/`EarlyContext`. ```rust impl<'tcx> LateLintPass<'tcx> for ManualStrip { @@ -436,8 +444,20 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { } ``` -Once the msrv is added to the lint, a relevant test case should be added to `tests/ui/min_rust_version_attr.rs` -which verifies that the lint isn't emitted if the project's msrv is lower. +Once the `msrv` is added to the lint, a relevant test case should be added to +`tests/ui/min_rust_version_attr.rs` which verifies that the lint isn't emitted +if the project's MSRV is lower. + +As a last step, the lint should be added to the lint documentation. This is done +in `clippy_lints/src/utils/conf.rs`: + +```rust +define_Conf! { + /// Lint: LIST, OF, LINTS, <THE_NEWLY_ADDED_LINT>. The minimum rust version that the project supports + (msrv, "msrv": Option<String>, None), + ... +} +``` ## Author lint @@ -533,9 +553,9 @@ Before submitting your PR make sure you followed all of the basic requirements: ## Adding configuration to a lint -Clippy supports the configuration of lints values using a `clippy.toml` file in the workspace +Clippy supports the configuration of lints values using a `clippy.toml` file in the workspace directory. Adding a configuration to a lint can be useful for thresholds or to constrain some -behavior that can be seen as a false positive for some users. Adding a configuration is done +behavior that can be seen as a false positive for some users. Adding a configuration is done in the following steps: 1. Adding a new configuration entry to [clippy_utils::conf](/clippy_utils/src/conf.rs) @@ -544,10 +564,10 @@ in the following steps: /// Lint: LINT_NAME. <The configuration field doc comment> (configuration_ident, "configuration_value": Type, DefaultValue), ``` - The configuration value and identifier should usually be the same. The doc comment will be + The configuration value and identifier should usually be the same. The doc comment will be automatically added to the lint documentation. 2. Adding the configuration value to the lint impl struct: - 1. This first requires the definition of a lint impl struct. Lint impl structs are usually + 1. This first requires the definition of a lint impl struct. Lint impl structs are usually generated with the `declare_lint_pass!` macro. This struct needs to be defined manually to add some kind of metadata to it: ```rust @@ -564,7 +584,7 @@ in the following steps: LINT_NAME ]); ``` - + 2. Next add the configuration value and a corresponding creation method like this: ```rust #[derive(Copy, Clone)] @@ -584,7 +604,7 @@ in the following steps: ``` 3. Passing the configuration value to the lint impl struct: - First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs). + First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs). The configuration value is now cloned or copied into a local value that is then passed to the impl struct like this: ```rust @@ -601,9 +621,9 @@ in the following steps: 4. Adding tests: 1. The default configured value can be tested like any normal lint in [`tests/ui`](/tests/ui). - 2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml). - Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file - with the configuration value and a rust file that should be linted by Clippy. The test can + 2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml). + Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file + with the configuration value and a rust file that should be linted by Clippy. The test can otherwise be written as usual. ## Cheatsheet @@ -611,7 +631,7 @@ in the following steps: Here are some pointers to things you are likely going to need for every lint: * [Clippy utils][utils] - Various helper functions. Maybe the function you need - is already in here (`implements_trait`, `match_path`, `snippet`, etc) + is already in here (`implements_trait`, `match_def_path`, `snippet`, etc) * [Clippy diagnostics][diagnostics] * [The `if_chain` macro][if_chain] * [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] diff --git a/src/tools/clippy/doc/basics.md b/src/tools/clippy/doc/basics.md index c56e84e2e3..5226875cc2 100644 --- a/src/tools/clippy/doc/basics.md +++ b/src/tools/clippy/doc/basics.md @@ -88,8 +88,8 @@ cargo dev fmt cargo dev update_lints # create a new lint and register it cargo dev new_lint -# (experimental) Setup Clippy to work with rust-analyzer -cargo dev ra_setup +# (experimental) Setup Clippy to work with IntelliJ-Rust +cargo dev ide_setup ``` ## lintcheck diff --git a/src/tools/clippy/lintcheck-logs/lintcheck_crates_logs.txt b/src/tools/clippy/lintcheck-logs/lintcheck_crates_logs.txt index 3439b1e2c4..8f22bd6568 100644 --- a/src/tools/clippy/lintcheck-logs/lintcheck_crates_logs.txt +++ b/src/tools/clippy/lintcheck-logs/lintcheck_crates_logs.txt @@ -1,12 +1,12 @@ -clippy 0.1.52 (94d1c0a96 2021-03-11) +clippy 0.1.53 (0b7671963 2021-03-31) target/lintcheck/sources/anyhow-1.0.38/build.rs:1:null clippy::cargo_common_metadata "package `anyhow` is missing `package.keywords` metadata" target/lintcheck/sources/anyhow-1.0.38/src/error.rs:350:5 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" target/lintcheck/sources/anyhow-1.0.38/src/lib.rs:1:null clippy::cargo_common_metadata "package `anyhow` is missing `package.keywords` metadata" -target/lintcheck/sources/async-trait-0.1.42/registry/src/github.com-1ecc6299db9ec823/syn-1.0.63/src/custom_keyword.rs:201:9 clippy::expl_impl_clone_on_copy "you are implementing `Clone` explicitly on a `Copy` type" target/lintcheck/sources/async-trait-0.1.42/src/expand.rs:130:1 clippy::too_many_lines "this function has too many lines (104/100)" target/lintcheck/sources/async-trait-0.1.42/src/expand.rs:156:26 clippy::default_trait_access "calling `syn::token::Where::default()` is more clear than this expression" target/lintcheck/sources/async-trait-0.1.42/src/expand.rs:259:1 clippy::too_many_lines "this function has too many lines (204/100)" +target/lintcheck/sources/async-trait-0.1.42/src/expand.rs:387:17 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/async-trait-0.1.42/src/expand.rs:414:35 clippy::shadow_unrelated "`generics` is being shadowed" target/lintcheck/sources/async-trait-0.1.42/src/expand.rs:464:32 clippy::if_not_else "unnecessary `!=` operation" target/lintcheck/sources/async-trait-0.1.42/src/lib.rs:102:7 clippy::doc_markdown "you should put `async_trait` between ticks in the documentation" @@ -88,7 +88,6 @@ target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/commands/yank.rs:32:36 clipp target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/commands/yank.rs:33:35 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/commands/yank.rs:34:36 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/commands/yank.rs:35:36 clippy::redundant_closure_for_method_calls "redundant closure" -target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:100:17 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:118:41 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:137:43 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:148:19 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" @@ -101,7 +100,6 @@ target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:1:null clippy::multi target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:1:null clippy::multiple_crate_versions "multiple versions for dependency `humantime`: 1.3.0, 2.0.0" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:72:22 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:79:40 clippy::manual_map "manual implementation of `Option::map`" -target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:94:13 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/cargo-0.49.0/src/bin/cargo/main.rs:98:60 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_config.rs:155:13 clippy::enum_glob_use "usage of wildcard import for enum variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_config.rs:170:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" @@ -125,7 +123,7 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/targ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:469:58 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:603:19 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:665:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" -target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:697:12 clippy::inconsistent_struct_constructor "inconsistent struct constructor" +target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:697:12 clippy::inconsistent_struct_constructor "struct constructor field order is inconsistent with struct definition field order" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:82:31 clippy::doc_markdown "you should put `FileType` between ticks in the documentation" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:83:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/build_context/target_info.rs:84:9 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" @@ -255,6 +253,8 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/job_queue.rs:871:1 target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/job_queue.rs:890:9 clippy::unused_self "unused `self` argument" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/job_queue.rs:93:24 clippy::doc_markdown "you should put `JobQueue` between ticks in the documentation" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/links.rs:8:1 clippy::module_name_repetitions "item name ends with its containing module's name" +target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/lto.rs:130:13 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/lto.rs:135:13 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:1016:1 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:1094:19 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:1131:1 clippy::unnecessary_wraps "this function's return value is unnecessary" @@ -271,6 +271,7 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:392:45 clip target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:415:23 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:464:18 clippy::ptr_arg "writing `&PathBuf` instead of `&Path` involves a new object where a slice will do" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:488:61 clippy::ptr_arg "writing `&PathBuf` instead of `&Path` involves a new object where a slice will do" +target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:498:21 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:654:46 clippy::implicit_clone "implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenced type" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:667:15 clippy::similar_names "binding's name is too similar to existing binding" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:693:1 clippy::unnecessary_wraps "this function's return value is unnecessary" @@ -279,7 +280,6 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:736:1 clipp target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:73:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:777:12 clippy::if_not_else "unnecessary boolean `not` operation" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/mod.rs:873:5 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" -target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/output_depinfo.rs:41:13 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/rustdoc.rs:16:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/rustdoc.rs:57:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/compiler/rustdoc.rs:72:1 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" @@ -554,7 +554,6 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/context.rs:42:1 cl target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/context.rs:74:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/encode.rs:156:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/encode.rs:156:5 clippy::too_many_lines "this function has too many lines (164/100)" -target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/encode.rs:339:17 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/encode.rs:438:5 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/encode.rs:449:5 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/resolver/encode.rs:529:34 clippy::redundant_closure_for_method_calls "redundant closure" @@ -636,6 +635,7 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:130:9 clippy::sing target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:148:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:153:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:163:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" +target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:166:13 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:18:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:198:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/shell.rs:206:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" @@ -781,6 +781,7 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:267:5 clippy:: target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:317:5 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:329:37 clippy::doc_markdown "you should put `VirtualManifest` between ticks in the documentation" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:410:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" +target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:420:17 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:440:9 clippy::unnecessary_wraps "this function's return value is unnecessarily wrapped by `Result`" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:511:32 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" target/lintcheck/sources/cargo-0.49.0/src/cargo/core/workspace.rs:561:25 clippy::non_ascii_literal "literal non-ASCII character detected" @@ -964,6 +965,7 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:510:1 clippy::mi target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:529:5 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:53:1 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:53:1 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" +target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:573:17 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:573:22 clippy::match_same_arms "this `match` has identical arm bodies" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:608:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/registry.rs:621:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" @@ -990,7 +992,9 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/resolve.rs:58:1 clippy::modu target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/resolve.rs:602:5 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/resolve.rs:75:1 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/resolve.rs:75:1 clippy::module_name_repetitions "item name starts with its containing module's name" +target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/tree/format/mod.rs:103:21 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/tree/graph.rs:129:26 clippy::doc_markdown "you should put `PackageIds` between ticks in the documentation" +target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/tree/graph.rs:137:17 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/tree/graph.rs:152:15 clippy::match_on_vec_items "indexing into a vector may panic" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/tree/graph.rs:173:9 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/tree/graph.rs:234:46 clippy::filter_map "called `filter(..).flat_map(..)` on an `Iterator`" @@ -1010,10 +1014,10 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:14:1 clippy::modul target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:215:9 clippy::let_underscore_drop "non-binding `let` on a type that implements `Drop`" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:21:1 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:21:1 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" +target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:311:13 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:314:34 clippy::match_same_arms "this `match` has identical arm bodies" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:320:29 clippy::case_sensitive_file_extension_comparisons "case-sensitive file extension comparison" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:320:60 clippy::case_sensitive_file_extension_comparisons "case-sensitive file extension comparison" -target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:324:13 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/ops/vendor.rs:70:1 clippy::too_many_lines "this function has too many lines (175/100)" target/lintcheck/sources/cargo-0.49.0/src/cargo/sources/config.rs:102:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/sources/config.rs:111:28 clippy::needless_question_mark "question mark operator is useless here" @@ -1167,6 +1171,7 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1323:9 clippy target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1339:39 clippy::unused_self "unused `self` argument" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1344:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1420:1 clippy::module_name_repetitions "item name starts with its containing module's name" +target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1531:13 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1553:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1560:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1567:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" @@ -1187,7 +1192,6 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1778:1 clippy target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1804:1 clippy::module_name_repetitions "item name ends with its containing module's name" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1896:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:1901:5 clippy::doc_markdown "you should put `StringList` between ticks in the documentation" -target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:214:13 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:259:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:298:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/config/mod.rs:311:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" @@ -1242,6 +1246,8 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:150:5 clippy::mus target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:15:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:237:5 clippy::pub_enum_variant_names "variant name ends with the enum's name" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:245:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" +target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:289:21 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" +target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:293:13 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:321:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:328:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/errors.rs:356:1 clippy::must_use_candidate "this function could have a `#[must_use]` attribute" @@ -1348,7 +1354,7 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:185:5 cl target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:190:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:218:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:218:5 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" -target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:278:22 clippy::inconsistent_struct_constructor "inconsistent struct constructor" +target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:278:22 clippy::inconsistent_struct_constructor "struct constructor field order is inconsistent with struct definition field order" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:307:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/process_builder.rs:343:39 clippy::needless_pass_by_value "this argument is passed by value, but not consumed in the function body" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/progress.rs:122:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" @@ -1448,6 +1454,8 @@ target/lintcheck/sources/cargo-0.49.0/src/cargo/util/workspace.rs:56:1 clippy::m target/lintcheck/sources/cargo-0.49.0/src/cargo/util/workspace.rs:60:1 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cargo-0.49.0/src/cargo/util/workspace.rs:64:1 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cfg-expr-0.7.1/src/error.rs:107:13 clippy::enum_glob_use "usage of wildcard import for enum variants" +target/lintcheck/sources/cfg-expr-0.7.1/src/error.rs:55:13 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/error.rs:58:13 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cfg-expr-0.7.1/src/error.rs:5:1 clippy::module_name_repetitions "item name ends with its containing module's name" target/lintcheck/sources/cfg-expr-0.7.1/src/error.rs:74:13 clippy::enum_glob_use "usage of wildcard import for enum variants" target/lintcheck/sources/cfg-expr-0.7.1/src/error.rs:91:24 clippy::if_not_else "unnecessary boolean `not` operation" @@ -1458,6 +1466,7 @@ target/lintcheck/sources/cfg-expr-0.7.1/src/expr/lexer.rs:58:5 clippy::must_use_ target/lintcheck/sources/cfg-expr-0.7.1/src/expr/lexer.rs:76:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/lexer.rs:97:9 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/mod.rs:351:13 clippy::enum_glob_use "usage of wildcard import for enum variants" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/mod.rs:408:13 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/mod.rs:464:5 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/mod.rs:57:13 clippy::enum_glob_use "usage of wildcard import for enum variants" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/mod.rs:586:33 clippy::match_same_arms "this `match` has identical arm bodies" @@ -1467,12 +1476,25 @@ target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:116:31 clippy::simila target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:124:36 clippy::similar_names "binding's name is too similar to existing binding" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:17:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:17:5 clippy::too_many_lines "this function has too many lines (345/100)" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:211:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:211:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:211:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:211:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:211:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:211:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:211:21 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:22:13 clippy::shadow_unrelated "`original` is being shadowed" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:238:21 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:243:36 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:254:34 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:259:21 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:25:9 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:284:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:292:21 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:347:21 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:390:9 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:392:17 clippy::if_not_else "unnecessary `!=` operation" +target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:39:31 clippy::too_many_lines "this function has too many lines (136/100)" target/lintcheck/sources/cfg-expr-0.7.1/src/expr/parser.rs:67:13 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" target/lintcheck/sources/cfg-expr-0.7.1/src/lib.rs:1:null clippy::cargo_common_metadata "package `cfg-expr` is missing `package.categories` metadata" target/lintcheck/sources/cfg-expr-0.7.1/src/targets/builtins.rs:11:5 clippy::wildcard_imports "usage of wildcard import" @@ -2191,9 +2213,7 @@ target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:202:35 clippy::unnecessary_ target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:282:40 clippy::unreadable_literal "long literal lacking separators" target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:284:41 clippy::unreadable_literal "long literal lacking separators" target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:285:36 clippy::unreadable_literal "long literal lacking separators" -target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:34:10 clippy::upper_case_acronyms "name `DIR` contains a capitalized acronym" target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:36:1 clippy::expl_impl_clone_on_copy "you are implementing `Clone` explicitly on a `Copy` type" -target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:386:10 clippy::upper_case_acronyms "name `FILE` contains a capitalized acronym" target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:388:1 clippy::expl_impl_clone_on_copy "you are implementing `Clone` explicitly on a `Copy` type" target/lintcheck/sources/libc-0.2.81/src/unix/mod.rs:396:1 clippy::expl_impl_clone_on_copy "you are implementing `Clone` explicitly on a `Copy` type" target/lintcheck/sources/log-0.4.11/src/lib.rs:1047:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" @@ -2212,11 +2232,13 @@ target/lintcheck/sources/log-0.4.11/src/lib.rs:356:1 clippy::expl_impl_clone_on_ target/lintcheck/sources/log-0.4.11/src/lib.rs:448:12 clippy::manual_range_contains "manual `RangeInclusive::contains` implementation" target/lintcheck/sources/log-0.4.11/src/lib.rs:500:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/log-0.4.11/src/lib.rs:506:28 clippy::trivially_copy_pass_by_ref "this argument (8 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)" +target/lintcheck/sources/log-0.4.11/src/lib.rs:506:28 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/log-0.4.11/src/lib.rs:506:5 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" target/lintcheck/sources/log-0.4.11/src/lib.rs:506:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/log-0.4.11/src/lib.rs:538:1 clippy::expl_impl_clone_on_copy "you are implementing `Clone` explicitly on a `Copy` type" target/lintcheck/sources/log-0.4.11/src/lib.rs:653:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/log-0.4.11/src/lib.rs:661:21 clippy::trivially_copy_pass_by_ref "this argument (8 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)" +target/lintcheck/sources/log-0.4.11/src/lib.rs:661:21 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/log-0.4.11/src/lib.rs:661:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/log-0.4.11/src/lib.rs:677:44 clippy::match_same_arms "this `match` has identical arm bodies" target/lintcheck/sources/log-0.4.11/src/lib.rs:758:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" @@ -2233,13 +2255,14 @@ target/lintcheck/sources/log-0.4.11/src/lib.rs:908:5 clippy::must_use_candidate target/lintcheck/sources/log-0.4.11/src/lib.rs:908:5 clippy::new_without_default "you should consider adding a `Default` implementation for `RecordBuilder<'a>`" target/lintcheck/sources/log-0.4.11/src/lib.rs:995:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/proc-macro2-1.0.24/src/detection.rs:2:5 clippy::wildcard_imports "usage of wildcard import" -target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:108:17 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" +target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:108:17 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:269:20 clippy::unused_self "unused `self` argument" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:430:24 clippy::trivially_copy_pass_by_ref "this argument (0 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:437:23 clippy::trivially_copy_pass_by_ref "this argument (0 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:437:23 clippy::unused_self "unused `self` argument" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:471:17 clippy::trivially_copy_pass_by_ref "this argument (0 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:471:17 clippy::unused_self "unused `self` argument" +target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:50:9 clippy::mem_replace_with_default "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:654:5 clippy::manual_range_contains "manual `RangeInclusive::contains` implementation" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:655:12 clippy::manual_range_contains "manual `RangeInclusive::contains` implementation" target/lintcheck/sources/proc-macro2-1.0.24/src/fallback.rs:661:5 clippy::manual_range_contains "manual `RangeInclusive::contains` implementation" @@ -2286,6 +2309,12 @@ target/lintcheck/sources/proc-macro2-1.0.24/src/lib.rs:891:36 clippy::doc_markdo target/lintcheck/sources/proc-macro2-1.0.24/src/lib.rs:894:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/proc-macro2-1.0.24/src/lib.rs:911:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/proc-macro2-1.0.24/src/lib.rs:996:9 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" +target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:353:17 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:360:17 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:411:17 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:413:17 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:476:13 clippy::unnested_or_patterns "unnested or-patterns" +target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:500:13 clippy::unnested_or_patterns "unnested or-patterns" target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:552:5 clippy::while_let_on_iterator "this loop could be written as a `for` loop" target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:584:21 clippy::manual_range_contains "manual `RangeInclusive::contains` implementation" target/lintcheck/sources/proc-macro2-1.0.24/src/parse.rs:602:20 clippy::map_unwrap_or "called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead" @@ -2360,6 +2389,10 @@ target/lintcheck/sources/quote-1.0.7/src/runtime.rs:52:5 clippy::module_name_rep target/lintcheck/sources/quote-1.0.7/src/runtime.rs:63:5 clippy::module_name_repetitions "item name ends with its containing module's name" target/lintcheck/sources/quote-1.0.7/src/runtime.rs:66:33 clippy::doc_markdown "you should put `DoesNotHaveIter` between ticks in the documentation" target/lintcheck/sources/quote-1.0.7/src/runtime.rs:80:5 clippy::module_name_repetitions "item name ends with its containing module's name" +target/lintcheck/sources/quote-1.0.7/src/to_tokens.rs:132:26 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/quote-1.0.7/src/to_tokens.rs:159:18 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/quote-1.0.7/src/to_tokens.rs:165:18 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/quote-1.0.7/src/to_tokens.rs:80:18 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/rand-0.7.3/src/distributions/bernoulli.rs:103:20 clippy::cast_possible_truncation "casting `f64` to `u64` may truncate the value" target/lintcheck/sources/rand-0.7.3/src/distributions/bernoulli.rs:103:20 clippy::cast_sign_loss "casting `f64` to `u64` may lose the sign of the value" target/lintcheck/sources/rand-0.7.3/src/distributions/bernoulli.rs:116:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" @@ -2467,9 +2500,9 @@ target/lintcheck/sources/rand-0.7.3/src/distributions/uniform.rs:943:54 clippy:: target/lintcheck/sources/rand-0.7.3/src/distributions/unit_circle.rs:30:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" target/lintcheck/sources/rand-0.7.3/src/distributions/unit_sphere.rs:24:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/rand-0.7.3/src/distributions/unit_sphere.rs:29:5 clippy::must_use_candidate "this method could have a `#[must_use]` attribute" -target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:247:15 clippy::wrong_self_convention "methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name" -target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:248:20 clippy::wrong_self_convention "methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name" -target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:249:18 clippy::wrong_self_convention "methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name" +target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:247:15 clippy::wrong_self_convention "methods called `is_*` usually take `self` by reference or no `self`" +target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:248:20 clippy::wrong_self_convention "methods called `is_*` usually take `self` by reference or no `self`" +target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:249:18 clippy::wrong_self_convention "methods called `is_*` usually take `self` by reference or no `self`" target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:254:5 clippy::inline_always "you have declared `#[inline(always)]` on `lanes`. This is usually a bad idea" target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:258:5 clippy::inline_always "you have declared `#[inline(always)]` on `splat`. This is usually a bad idea" target/lintcheck/sources/rand-0.7.3/src/distributions/utils.rs:262:5 clippy::inline_always "you have declared `#[inline(always)]` on `extract`. This is usually a bad idea" @@ -2504,7 +2537,69 @@ target/lintcheck/sources/rand-0.7.3/src/distributions/weighted/mod.rs:169:16 cli target/lintcheck/sources/rand-0.7.3/src/distributions/weighted/mod.rs:386:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/rand-0.7.3/src/distributions/weighted/mod.rs:85:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/rand-0.7.3/src/lib.rs:333:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" -target/lintcheck/sources/rand-0.7.3/src/lib.rs:404:14 clippy::wrong_self_convention "methods called `to_*` usually take self by reference; consider choosing a less ambiguous name" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:412:14 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:435:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:459:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" +target/lintcheck/sources/rand-0.7.3/src/lib.rs:489:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" target/lintcheck/sources/rand-0.7.3/src/lib.rs:552:1 clippy::must_use_candidate "this function could have a `#[must_use]` attribute" target/lintcheck/sources/rand-0.7.3/src/rngs/adapter/read.rs:47:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/rand-0.7.3/src/rngs/adapter/read.rs:89:1 clippy::module_name_repetitions "item name starts with its containing module's name" @@ -2605,6 +2700,7 @@ target/lintcheck/sources/rayon-1.5.0/src/collections/hash_set.rs:9:5 clippy::wil target/lintcheck/sources/rayon-1.5.0/src/collections/linked_list.rs:7:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/collections/linked_list.rs:8:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/collections/mod.rs:59:32 clippy::mem_replace_with_default "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`" +target/lintcheck/sources/rayon-1.5.0/src/collections/mod.rs:68:40 clippy::mem_replace_with_default "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`" target/lintcheck/sources/rayon-1.5.0/src/collections/vec_deque.rs:8:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/collections/vec_deque.rs:9:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/compile_fail/cannot_collect_filtermap_data.rs:2:1 clippy::needless_doctest_main "needless `fn main` in doctest" @@ -2626,7 +2722,7 @@ target/lintcheck/sources/rayon-1.5.0/src/iter/chain.rs:58:17 clippy::shadow_unre target/lintcheck/sources/rayon-1.5.0/src/iter/chain.rs:78:14 clippy::shadow_unrelated "`a` is being shadowed" target/lintcheck/sources/rayon-1.5.0/src/iter/chain.rs:78:17 clippy::shadow_unrelated "`b` is being shadowed" target/lintcheck/sources/rayon-1.5.0/src/iter/chain.rs:97:9 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" -target/lintcheck/sources/rayon-1.5.0/src/iter/chunks.rs:29:9 clippy::inconsistent_struct_constructor "inconsistent struct constructor" +target/lintcheck/sources/rayon-1.5.0/src/iter/chunks.rs:29:9 clippy::inconsistent_struct_constructor "struct constructor field order is inconsistent with struct definition field order" target/lintcheck/sources/rayon-1.5.0/src/iter/chunks.rs:3:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/chunks.rs:4:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/chunks.rs:77:9 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" @@ -2704,8 +2800,6 @@ target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:200:23 clippy::doc_m target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:249:41 clippy::doc_markdown "you should put `DoubleEndedIterator` between ticks in the documentation" target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:250:5 clippy::doc_markdown "you should put `ExactSizeIterator` between ticks in the documentation" target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:263:33 clippy::doc_markdown "you should put `InterleaveSeq` between ticks in the documentation" -target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:280:17 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" -target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:285:17 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:2:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:313:9 clippy::comparison_chain "`if` chain can be rewritten with `match`" target/lintcheck/sources/rayon-1.5.0/src/iter/interleave.rs:82:9 clippy::items_after_statements "adding items after statements is confusing, since items exist from the start of the scope" @@ -2761,6 +2855,7 @@ target/lintcheck/sources/rayon-1.5.0/src/iter/positions.rs:1:5 clippy::wildcard_ target/lintcheck/sources/rayon-1.5.0/src/iter/positions.rs:2:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/product.rs:1:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/reduce.rs:1:5 clippy::wildcard_imports "usage of wildcard import" +target/lintcheck/sources/rayon-1.5.0/src/iter/reduce.rs:67:19 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/rayon-1.5.0/src/iter/repeat.rs:103:1 clippy::module_name_repetitions "item name starts with its containing module's name" target/lintcheck/sources/rayon-1.5.0/src/iter/repeat.rs:1:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/repeat.rs:2:5 clippy::wildcard_imports "usage of wildcard import" @@ -2787,7 +2882,9 @@ target/lintcheck/sources/rayon-1.5.0/src/iter/try_fold.rs:190:1 clippy::module_n target/lintcheck/sources/rayon-1.5.0/src/iter/try_fold.rs:1:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/try_fold.rs:2:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/try_reduce.rs:1:5 clippy::wildcard_imports "usage of wildcard import" +target/lintcheck/sources/rayon-1.5.0/src/iter/try_reduce.rs:74:19 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/rayon-1.5.0/src/iter/try_reduce_with.rs:1:5 clippy::wildcard_imports "usage of wildcard import" +target/lintcheck/sources/rayon-1.5.0/src/iter/try_reduce_with.rs:69:19 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/rayon-1.5.0/src/iter/unzip.rs:1:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/unzip.rs:2:5 clippy::wildcard_imports "usage of wildcard import" target/lintcheck/sources/rayon-1.5.0/src/iter/update.rs:1:5 clippy::wildcard_imports "usage of wildcard import" @@ -2960,6 +3057,7 @@ target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1129:13 clippy::doc_markdown "yo target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1134:13 clippy::doc_markdown "you should put `is_match` between ticks in the documentation" target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1185:68 clippy::doc_markdown "you should put `is_match` between ticks in the documentation" target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1193:13 clippy::enum_glob_use "usage of wildcard import for enum variants" +target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1205:13 clippy::mem_replace_with_default "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`" target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1244:50 clippy::doc_markdown "you should put `current_state` between ticks in the documentation" target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1338:58 clippy::doc_markdown "you should put `STATE_DEAD` between ticks in the documentation" target/lintcheck/sources/regex-1.3.2/src/dfa.rs:1339:9 clippy::doc_markdown "you should put `STATE_UNKNOWN` between ticks in the documentation" @@ -3365,7 +3463,7 @@ target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:369:5 clippy::upper_ target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:410:14 clippy::trivially_copy_pass_by_ref "this argument (2 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)" target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:475:18 clippy::match_same_arms "this `match` has identical arm bodies" target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:512:19 clippy::doc_markdown "you should put `ArgMatches` between ticks in the documentation" -target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:549:16 clippy::wrong_self_convention "methods called `to_*` usually take self by reference; consider choosing a less ambiguous name" +target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:549:16 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:76:18 clippy::trivially_copy_pass_by_ref "this argument (1 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)" target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:77:13 clippy::enum_glob_use "usage of wildcard import for enum variants" target/lintcheck/sources/ripgrep-12.1.1/crates/core/args.rs:923:42 clippy::doc_markdown "you should put `BinaryDetection::quit` between ticks in the documentation" @@ -3409,6 +3507,14 @@ target/lintcheck/sources/rpmalloc-0.2.0/src/lib.rs:71:73 clippy::doc_markdown "y target/lintcheck/sources/rpmalloc-0.2.0/src/lib.rs:72:50 clippy::doc_markdown "you should put bare URLs between `<`/`>` or make a proper Markdown link" target/lintcheck/sources/rpmalloc-0.2.0/src/lib.rs:92:9 clippy::ptr_as_ptr "`as` casting between raw pointers without changing its mutability" target/lintcheck/sources/rpmalloc-0.2.0/src/lib.rs:95:21 clippy::ptr_as_ptr "`as` casting between raw pointers without changing its mutability" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:103:24 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:107:25 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:111:25 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:115:25 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:48:24 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:52:25 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:56:25 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" +target/lintcheck/sources/serde-1.0.118/src/de/from_primitive.rs:60:25 clippy::wrong_self_convention "methods called `from_*` usually take no `self`" target/lintcheck/sources/serde-1.0.118/src/de/mod.rs:1592:9 clippy::let_underscore_drop "non-binding `let` on a type that implements `Drop`" target/lintcheck/sources/serde-1.0.118/src/de/mod.rs:1616:9 clippy::let_underscore_drop "non-binding `let` on a type that implements `Drop`" target/lintcheck/sources/serde-1.0.118/src/de/mod.rs:1627:9 clippy::let_underscore_drop "non-binding `let` on a type that implements `Drop`" @@ -3418,10 +3524,18 @@ target/lintcheck/sources/serde-1.0.118/src/de/mod.rs:952:13 clippy::let_undersco target/lintcheck/sources/serde-1.0.118/src/de/mod.rs:986:13 clippy::let_underscore_drop "non-binding `let` on a type that implements `Drop`" target/lintcheck/sources/serde_yaml-0.8.17/src/lib.rs:1:null clippy::cargo_common_metadata "package `serde_yaml` is missing `package.categories` metadata" target/lintcheck/sources/syn-1.0.54/build.rs:1:null clippy::cargo_common_metadata "package `syn` is missing `package.keywords` metadata" +target/lintcheck/sources/syn-1.0.54/src/custom_keyword.rs:177:26 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/syn-1.0.54/src/gen/clone.rs:1900:13 clippy::match_wildcard_for_single_variants "wildcard matches only a single variant and will also match any future added variants" +target/lintcheck/sources/syn-1.0.54/src/generics.rs:1227:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/syn-1.0.54/src/lib.rs:1:null clippy::cargo_common_metadata "package `syn` is missing `package.keywords` metadata" target/lintcheck/sources/syn-1.0.54/src/lit.rs:1397:40 clippy::redundant_else "redundant else block" target/lintcheck/sources/syn-1.0.54/src/lit.rs:1405:28 clippy::redundant_else "redundant else block" target/lintcheck/sources/syn-1.0.54/src/lit.rs:1485:32 clippy::redundant_else "redundant else block" +target/lintcheck/sources/syn-1.0.54/src/op.rs:190:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/syn-1.0.54/src/op.rs:226:22 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/syn-1.0.54/src/token.rs:311:30 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/syn-1.0.54/src/token.rs:446:30 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" +target/lintcheck/sources/syn-1.0.54/src/token.rs:563:18 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value" target/lintcheck/sources/syn-1.0.54/src/token.rs:974:5 clippy::missing_panics_doc "docs for function which may panic missing `# Panics` section" target/lintcheck/sources/tame-oidc-0.1.0/src/errors.rs:9:5 clippy::upper_case_acronyms "name `HTTP` contains a capitalized acronym" target/lintcheck/sources/tame-oidc-0.1.0/src/lib.rs:1:null clippy::cargo_common_metadata "package `tame-oidc` is missing `package.categories` metadata" @@ -3439,8 +3553,6 @@ target/lintcheck/sources/tame-oidc-0.1.0/src/provider.rs:26:5 clippy::missing_er target/lintcheck/sources/tame-oidc-0.1.0/src/provider.rs:38:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/tame-oidc-0.1.0/src/provider.rs:57:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/tame-oidc-0.1.0/src/provider.rs:71:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" -target/lintcheck/sources/tame-oidc-0.1.0/src/provider.rs:77:12 clippy::upper_case_acronyms "name `JWK` contains a capitalized acronym" -target/lintcheck/sources/tame-oidc-0.1.0/src/provider.rs:90:12 clippy::upper_case_acronyms "name `JWKS` contains a capitalized acronym" target/lintcheck/sources/tame-oidc-0.1.0/src/provider.rs:95:5 clippy::missing_errors_doc "docs for function returning `Result` missing `# Errors` section" target/lintcheck/sources/thiserror-1.0.24/src/lib.rs:1:null clippy::cargo_common_metadata "package `thiserror` is missing `package.keywords` metadata" target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:1:null clippy::cargo_common_metadata "package `unicode-xid` is missing `package.categories` metadata" @@ -3448,12 +3560,12 @@ target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:57:64 clippy::doc_markdown target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:60:10 clippy::doc_markdown "you should put `XID_Start` between ticks in the documentation" target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:62:27 clippy::doc_markdown "you should put `ID_Start` between ticks in the documentation" target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:62:67 clippy::doc_markdown "you should put `NFKx` between ticks in the documentation" -target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:63:21 clippy::wrong_self_convention "methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name" +target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:63:21 clippy::wrong_self_convention "methods called `is_*` usually take `self` by reference or no `self`" target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:65:61 clippy::doc_markdown "you should put `XID_Continue` between ticks in the documentation" target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:68:10 clippy::doc_markdown "you should put `XID_Continue` between ticks in the documentation" target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:70:28 clippy::doc_markdown "you should put `ID_Continue` between ticks in the documentation" target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:70:72 clippy::doc_markdown "you should put `NFKx` between ticks in the documentation" -target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:71:24 clippy::wrong_self_convention "methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name" +target/lintcheck/sources/unicode-xid-0.2.1/src/lib.rs:71:24 clippy::wrong_self_convention "methods called `is_*` usually take `self` by reference or no `self`" target/lintcheck/sources/xsv-0.13.0/src/cmd/cat.rs:101:34 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/xsv-0.13.0/src/cmd/cat.rs:42:1 clippy::struct_excessive_bools "more than 3 bools in a struct" target/lintcheck/sources/xsv-0.13.0/src/cmd/cat.rs:53:9 clippy::similar_names "binding's name is too similar to existing binding" @@ -3520,7 +3632,6 @@ target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:115:21 clippy::cast_possib target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:11:16 clippy::redundant_static_lifetimes "statics have by default a `'static` lifetime" target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:51:9 clippy::similar_names "binding's name is too similar to existing binding" target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:58:19 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" -target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:69:9 clippy::match_wildcard_for_single_variants "wildcard match will miss any future added variants" target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:75:16 clippy::explicit_into_iter_loop "it is more concise to loop over containers instead of using explicit iteration methods" target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:91:42 clippy::cast_possible_truncation "casting `u64` to `usize` may truncate the value on targets with 32-bit wide pointers" target/lintcheck/sources/xsv-0.13.0/src/cmd/sample.rs:92:43 clippy::cast_possible_truncation "casting `u64` to `usize` may truncate the value on targets with 32-bit wide pointers" @@ -3567,7 +3678,7 @@ target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:293:25 clippy::match_same_a target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:297:25 clippy::option_map_unit_fn "called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`" target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:301:21 clippy::option_map_unit_fn "called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`" target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:302:21 clippy::option_map_unit_fn "called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`" -target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:308:18 clippy::wrong_self_convention "methods called `to_*` usually take self by reference; consider choosing a less ambiguous name" +target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:308:18 clippy::wrong_self_convention "methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference" target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:318:9 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:322:45 clippy::redundant_closure_for_method_calls "redundant closure" target/lintcheck/sources/xsv-0.13.0/src/cmd/stats.rs:322:9 clippy::single_match_else "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`" @@ -3600,7 +3711,7 @@ target/lintcheck/sources/xsv-0.13.0/src/cmd/table.rs:50:9 clippy::similar_names target/lintcheck/sources/xsv-0.13.0/src/cmd/table.rs:54:9 clippy::similar_names "binding's name is too similar to existing binding" target/lintcheck/sources/xsv-0.13.0/src/config.rs:113:43 clippy::or_fun_call "use of `unwrap_or` followed by a function call" target/lintcheck/sources/xsv-0.13.0/src/config.rs:58:1 clippy::struct_excessive_bools "more than 3 bools in a struct" -target/lintcheck/sources/xsv-0.13.0/src/config.rs:77:28 clippy::explicit_deref_methods "explicit deref method call" +target/lintcheck/sources/xsv-0.13.0/src/config.rs:77:28 clippy::explicit_deref_methods "explicit `deref` method call" target/lintcheck/sources/xsv-0.13.0/src/config.rs:90:13 clippy::redundant_field_names "redundant field names in struct initialization" target/lintcheck/sources/xsv-0.13.0/src/index.rs:31:13 clippy::redundant_field_names "redundant field names in struct initialization" target/lintcheck/sources/xsv-0.13.0/src/main.rs:164:49 clippy::redundant_clone "redundant clone" @@ -3640,7 +3751,6 @@ clippy::from_iter_instead_of_collect 1 clippy::int_plus_one 1 clippy::manual_flatten 1 clippy::manual_saturating_arithmetic 1 -clippy::mem_replace_with_default 1 clippy::nonminimal_bool 1 clippy::or_fun_call 1 clippy::precedence 1 @@ -3677,7 +3787,9 @@ clippy::inconsistent_struct_constructor 3 clippy::manual_map 3 clippy::mut_mut 3 clippy::ptr_arg 3 +clippy::upper_case_acronyms 3 clippy::zero_ptr 3 +clippy::mem_replace_with_default 4 clippy::too_many_arguments 4 clippy::explicit_iter_loop 5 clippy::field_reassign_with_default 5 @@ -3695,16 +3807,14 @@ clippy::implicit_clone 7 clippy::map_clone 7 clippy::option_map_unit_fn 7 clippy::range_plus_one 7 -clippy::upper_case_acronyms 7 clippy::invalid_upcast_comparisons 8 clippy::needless_question_mark 8 -clippy::wrong_self_convention 8 clippy::len_without_is_empty 9 clippy::multiple_crate_versions 9 clippy::manual_range_contains 10 -clippy::match_wildcard_for_single_variants 10 clippy::missing_safety_doc 10 clippy::needless_doctest_main 10 +clippy::match_wildcard_for_single_variants 11 clippy::needless_lifetimes 12 clippy::linkedlist 14 clippy::single_char_add_str 14 @@ -3722,11 +3832,12 @@ clippy::cargo_common_metadata 21 clippy::ptr_as_ptr 21 clippy::redundant_static_lifetimes 21 clippy::cast_lossless 23 +clippy::unnested_or_patterns 25 clippy::default_trait_access 26 clippy::let_underscore_drop 26 clippy::trivially_copy_pass_by_ref 26 clippy::redundant_else 29 -clippy::too_many_lines 35 +clippy::too_many_lines 36 clippy::if_not_else 38 clippy::unseparated_literal_suffix 41 clippy::cast_precision_loss 44 @@ -3736,13 +3847,14 @@ clippy::inline_always 59 clippy::missing_panics_doc 59 clippy::match_same_arms 62 clippy::similar_names 83 +clippy::wrong_self_convention 94 clippy::cast_possible_truncation 95 clippy::redundant_field_names 111 clippy::redundant_closure_for_method_calls 131 clippy::items_after_statements 143 clippy::module_name_repetitions 146 +clippy::expl_impl_clone_on_copy 164 clippy::wildcard_imports 164 -clippy::expl_impl_clone_on_copy 165 clippy::doc_markdown 184 clippy::missing_errors_doc 356 clippy::unreadable_literal 365 diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs index 581b47647e..f6a75595c9 100644 --- a/src/tools/clippy/lintcheck/src/main.rs +++ b/src/tools/clippy/lintcheck/src/main.rs @@ -5,7 +5,7 @@ // When a new lint is introduced, we can search the results for new warnings and check for false // positives. -#![allow(clippy::filter_map, clippy::collapsible_else_if)] +#![allow(clippy::collapsible_else_if)] use std::ffi::OsStr; use std::process::Command; @@ -22,9 +22,16 @@ use rayon::prelude::*; use serde::{Deserialize, Serialize}; use serde_json::Value; +#[cfg(not(windows))] const CLIPPY_DRIVER_PATH: &str = "target/debug/clippy-driver"; +#[cfg(not(windows))] const CARGO_CLIPPY_PATH: &str = "target/debug/cargo-clippy"; +#[cfg(windows)] +const CLIPPY_DRIVER_PATH: &str = "target/debug/clippy-driver.exe"; +#[cfg(windows)] +const CARGO_CLIPPY_PATH: &str = "target/debug/cargo-clippy.exe"; + const LINTCHECK_DOWNLOADS: &str = "target/lintcheck/downloads"; const LINTCHECK_SOURCES: &str = "target/lintcheck/sources"; @@ -294,6 +301,14 @@ impl Crate { }); let stdout = String::from_utf8_lossy(&all_output.stdout); let stderr = String::from_utf8_lossy(&all_output.stderr); + let status = &all_output.status; + + if !status.success() { + eprintln!( + "\nWARNING: bad exit status after checking {} {} \n", + self.name, self.version + ); + } if fix { if let Some(stderr) = stderr diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index c52a7f2e74..cd39845178 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-03-11" +channel = "nightly-2021-04-22" components = ["llvm-tools-preview", "rustc-dev", "rust-src"] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index b6aed862e8..750a23e8c9 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -4,7 +4,7 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] // warn on rustc internal lints -#![deny(rustc::internal)] +#![warn(rustc::internal)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) @@ -99,17 +99,17 @@ impl rustc_driver::Callbacks for ClippyCallbacks { config.parse_sess_created = Some(Box::new(move |parse_sess| { track_clippy_args(parse_sess, &clippy_args_var); })); - config.register_lints = Some(Box::new(move |sess, mut lint_store| { + config.register_lints = Some(Box::new(move |sess, lint_store| { // technically we're ~guaranteed that this is none but might as well call anything that // is there already. Certainly it can't hurt. if let Some(previous) = &previous { (previous)(sess, lint_store); } - let conf = clippy_lints::read_conf(&[], &sess); - clippy_lints::register_plugins(&mut lint_store, &sess, &conf); - clippy_lints::register_pre_expansion_lints(&mut lint_store); - clippy_lints::register_renamed(&mut lint_store); + let conf = clippy_lints::read_conf(&[], sess); + clippy_lints::register_plugins(lint_store, sess, &conf); + clippy_lints::register_pre_expansion_lints(lint_store); + clippy_lints::register_renamed(lint_store); })); // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be @@ -191,7 +191,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { ]; for note in &xs { - handler.note_without_error(¬e); + handler.note_without_error(note); } // If backtraces are enabled, also print the query stack diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 0594663786..e1110721f6 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -83,14 +83,7 @@ fn default_config() -> compiletest::Config { third_party_crates(), )); - config.build_base = if cargo::is_rustc_test_suite() { - // This make the stderr files go to clippy OUT_DIR on rustc repo build dir - let mut path = PathBuf::from(env!("OUT_DIR")); - path.push("test_build_base"); - path - } else { - host_lib().join("test_build_base") - }; + config.build_base = host_lib().join("test_build_base"); config.rustc_path = clippy_driver_path(); config } @@ -98,7 +91,7 @@ fn default_config() -> compiletest::Config { fn run_mode(cfg: &mut compiletest::Config) { cfg.mode = TestMode::Ui; cfg.src_base = Path::new("tests").join("ui"); - compiletest::run_tests(&cfg); + compiletest::run_tests(cfg); } fn run_internal_tests(cfg: &mut compiletest::Config) { @@ -108,7 +101,7 @@ fn run_internal_tests(cfg: &mut compiletest::Config) { } cfg.mode = TestMode::Ui; cfg.src_base = Path::new("tests").join("ui-internal"); - compiletest::run_tests(&cfg); + compiletest::run_tests(cfg); } fn run_ui_toml(config: &mut compiletest::Config) { @@ -136,7 +129,7 @@ fn run_ui_toml(config: &mut compiletest::Config) { base: config.src_base.clone(), relative_dir: dir_path.file_name().unwrap().into(), }; - let test_name = compiletest::make_test_name(&config, &paths); + let test_name = compiletest::make_test_name(config, &paths); let index = tests .iter() .position(|test| test.desc.name == test_name) @@ -150,10 +143,10 @@ fn run_ui_toml(config: &mut compiletest::Config) { config.mode = TestMode::Ui; config.src_base = Path::new("tests").join("ui-toml").canonicalize().unwrap(); - let tests = compiletest::make_tests(&config); + let tests = compiletest::make_tests(config); let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap_or_default(); - let res = run_tests(&config, tests); + let res = run_tests(config, tests); set_var("CARGO_MANIFEST_DIR", &manifest_dir); match res { Ok(true) => {}, @@ -221,7 +214,7 @@ fn run_ui_cargo(config: &mut compiletest::Config) { base: config.src_base.clone(), relative_dir: src_path.strip_prefix(&config.src_base).unwrap().into(), }; - let test_name = compiletest::make_test_name(&config, &paths); + let test_name = compiletest::make_test_name(config, &paths); let index = tests .iter() .position(|test| test.desc.name == test_name) @@ -240,11 +233,11 @@ fn run_ui_cargo(config: &mut compiletest::Config) { config.mode = TestMode::Ui; config.src_base = Path::new("tests").join("ui-cargo").canonicalize().unwrap(); - let tests = compiletest::make_tests(&config); + let tests = compiletest::make_tests(config); let current_dir = env::current_dir().unwrap(); let conf_dir = var("CLIPPY_CONF_DIR").unwrap_or_default(); - let res = run_tests(&config, &config.filters, tests); + let res = run_tests(config, &config.filters, tests); env::set_current_dir(current_dir).unwrap(); set_var("CLIPPY_CONF_DIR", conf_dir); diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs index 3f754c255b..2f8989c8e1 100644 --- a/src/tools/clippy/tests/lint_message_convention.rs +++ b/src/tools/clippy/tests/lint_message_convention.rs @@ -89,14 +89,14 @@ fn lint_message_convention() { .filter(|message| !message.bad_lines.is_empty()) .collect(); - bad_tests.iter().for_each(|message| { + for message in &bad_tests { eprintln!( "error: the test '{}' contained the following nonconforming lines :", message.path.display() ); message.bad_lines.iter().for_each(|line| eprintln!("{}", line)); eprintln!("\n\n"); - }); + } eprintln!( "\n\n\nLint message should not start with a capital letter and should not have punctuation at the end of the message unless multiple sentences are needed." diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr index c8ae6c820d..5e9aa8dc36 100644 --- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr +++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr @@ -1,9 +1,7 @@ -error: package `cargo_common_metadata` is missing `package.authors` metadata +error: package `cargo_common_metadata` is missing `package.description` metadata | = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` -error: package `cargo_common_metadata` is missing `package.description` metadata - error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata error: package `cargo_common_metadata` is missing `package.repository` metadata @@ -14,5 +12,5 @@ error: package `cargo_common_metadata` is missing `package.keywords` metadata error: package `cargo_common_metadata` is missing `package.categories` metadata -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr index c8ae6c820d..5e9aa8dc36 100644 --- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr +++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr @@ -1,9 +1,7 @@ -error: package `cargo_common_metadata` is missing `package.authors` metadata +error: package `cargo_common_metadata` is missing `package.description` metadata | = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` -error: package `cargo_common_metadata` is missing `package.description` metadata - error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata error: package `cargo_common_metadata` is missing `package.repository` metadata @@ -14,5 +12,5 @@ error: package `cargo_common_metadata` is missing `package.keywords` metadata error: package `cargo_common_metadata` is missing `package.categories` metadata -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr index c8ae6c820d..5e9aa8dc36 100644 --- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr +++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr @@ -1,9 +1,7 @@ -error: package `cargo_common_metadata` is missing `package.authors` metadata +error: package `cargo_common_metadata` is missing `package.description` metadata | = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` -error: package `cargo_common_metadata` is missing `package.description` metadata - error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata error: package `cargo_common_metadata` is missing `package.repository` metadata @@ -14,5 +12,5 @@ error: package `cargo_common_metadata` is missing `package.keywords` metadata error: package `cargo_common_metadata` is missing `package.categories` metadata -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml index 737e84e963..cb4774d43a 100644 --- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml +++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml @@ -2,7 +2,6 @@ name = "cargo_common_metadata" version = "0.1.0" publish = false -authors = ["Random person from the Internet <someone@someplace.org>"] description = "A test package for the cargo_common_metadata lint" repository = "https://github.com/someone/cargo_common_metadata" readme = "README.md" diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed index e588c23345..7764cc8da7 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -2,58 +2,18 @@ #![deny(clippy::internal)] #![feature(rustc_private)] +extern crate clippy_utils; extern crate rustc_ast; extern crate rustc_errors; extern crate rustc_lint; extern crate rustc_session; extern crate rustc_span; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; use rustc_ast::ast::Expr; -use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; - -#[allow(unused_variables)] -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) -where - F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), -{ -} - -#[allow(unused_variables)] -fn span_lint_and_help<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - option_span: Option<Span>, - help: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_note<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - note_span: Option<Span>, - note: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_sugg<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - sp: Span, - msg: &str, - help: &str, - sugg: String, - applicability: Applicability, -) { -} declare_tool_lint! { pub clippy::TEST_LINT, diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs index d5dd3bb562..bdd296db83 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs @@ -2,58 +2,18 @@ #![deny(clippy::internal)] #![feature(rustc_private)] +extern crate clippy_utils; extern crate rustc_ast; extern crate rustc_errors; extern crate rustc_lint; extern crate rustc_session; extern crate rustc_span; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; use rustc_ast::ast::Expr; -use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; - -#[allow(unused_variables)] -pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) -where - F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), -{ -} - -#[allow(unused_variables)] -fn span_lint_and_help<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - option_span: Option<Span>, - help: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_note<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - span: Span, - msg: &str, - note_span: Option<Span>, - note: &str, -) { -} - -#[allow(unused_variables)] -fn span_lint_and_sugg<'a, T: LintContext>( - cx: &'a T, - lint: &'static Lint, - sp: Span, - msg: &str, - help: &str, - sugg: String, - applicability: Applicability, -) { -} declare_tool_lint! { pub clippy::TEST_LINT, diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr index 874d4a9f25..0632b03857 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -1,5 +1,5 @@ error: this call is collapsible - --> $DIR/collapsible_span_lint_calls.rs:75:9 + --> $DIR/collapsible_span_lint_calls.rs:35:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); @@ -14,7 +14,7 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]` error: this call is collapsible - --> $DIR/collapsible_span_lint_calls.rs:78:9 + --> $DIR/collapsible_span_lint_calls.rs:38:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | db.span_help(expr.span, help_msg); @@ -22,7 +22,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)` error: this call is collapsible - --> $DIR/collapsible_span_lint_calls.rs:81:9 + --> $DIR/collapsible_span_lint_calls.rs:41:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | db.help(help_msg); @@ -30,7 +30,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)` error: this call is collspible - --> $DIR/collapsible_span_lint_calls.rs:84:9 + --> $DIR/collapsible_span_lint_calls.rs:44:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | db.span_note(expr.span, note_msg); @@ -38,7 +38,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)` error: this call is collspible - --> $DIR/collapsible_span_lint_calls.rs:87:9 + --> $DIR/collapsible_span_lint_calls.rs:47:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | db.note(note_msg); diff --git a/src/tools/clippy/tests/ui-internal/if_chain_style.rs b/src/tools/clippy/tests/ui-internal/if_chain_style.rs new file mode 100644 index 0000000000..8e871707aa --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/if_chain_style.rs @@ -0,0 +1,92 @@ +#![warn(clippy::if_chain_style)] +#![allow(clippy::no_effect)] + +extern crate if_chain; + +use if_chain::if_chain; + +fn main() { + if true { + let x = ""; + // `if_chain!` inside `if` + if_chain! { + if true; + if true; + then {} + } + } + if_chain! { + if true + // multi-line AND'ed conditions + && false; + if let Some(1) = Some(1); + // `let` before `then` + let x = ""; + then { + (); + } + } + if_chain! { + // single `if` condition + if true; + then { + let x = ""; + // nested if + if true {} + } + } + if_chain! { + // starts with `let ..` + let x = ""; + if let Some(1) = Some(1); + then { + let x = ""; + let x = ""; + // nested if_chain! + if_chain! { + if true; + if true; + then {} + } + } + } +} + +fn negative() { + if true { + (); + if_chain! { + if true; + if true; + then { (); } + } + } + if_chain! { + if true; + let x = ""; + if true; + then { (); } + } + if_chain! { + if true; + if true; + then { + if true { 1 } else { 2 } + } else { + 3 + } + }; + if true { + if_chain! { + if true; + if true; + then {} + } + } else if false { + if_chain! { + if true; + if false; + then {} + } + } +} diff --git a/src/tools/clippy/tests/ui-internal/if_chain_style.stderr b/src/tools/clippy/tests/ui-internal/if_chain_style.stderr new file mode 100644 index 0000000000..b53c3ea05d --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/if_chain_style.stderr @@ -0,0 +1,85 @@ +error: this `if` can be part of the inner `if_chain!` + --> $DIR/if_chain_style.rs:9:5 + | +LL | / if true { +LL | | let x = ""; +LL | | // `if_chain!` inside `if` +LL | | if_chain! { +... | +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::if-chain-style` implied by `-D warnings` +help: this `let` statement can also be in the `if_chain!` + --> $DIR/if_chain_style.rs:10:9 + | +LL | let x = ""; + | ^^^^^^^^^^^ + +error: `if a && b;` should be `if a; if b;` + --> $DIR/if_chain_style.rs:19:12 + | +LL | if true + | ____________^ +LL | | // multi-line AND'ed conditions +LL | | && false; + | |____________________^ + +error: `let` expression should be inside `then { .. }` + --> $DIR/if_chain_style.rs:24:9 + | +LL | let x = ""; + | ^^^^^^^^^^^ + +error: this `if` can be part of the outer `if_chain!` + --> $DIR/if_chain_style.rs:35:13 + | +LL | if true {} + | ^^^^^^^^^^ + | +help: this `let` statement can also be in the `if_chain!` + --> $DIR/if_chain_style.rs:33:13 + | +LL | let x = ""; + | ^^^^^^^^^^^ + +error: `if_chain!` only has one `if` + --> $DIR/if_chain_style.rs:29:5 + | +LL | / if_chain! { +LL | | // single `if` condition +LL | | if true; +LL | | then { +... | +LL | | } +LL | | } + | |_____^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `let` expression should be above the `if_chain!` + --> $DIR/if_chain_style.rs:40:9 + | +LL | let x = ""; + | ^^^^^^^^^^^ + +error: this `if_chain!` can be merged with the outer `if_chain!` + --> $DIR/if_chain_style.rs:46:13 + | +LL | / if_chain! { +LL | | if true; +LL | | if true; +LL | | then {} +LL | | } + | |_____________^ + | +help: these `let` statements can also be in the `if_chain!` + --> $DIR/if_chain_style.rs:43:13 + | +LL | / let x = ""; +LL | | let x = ""; + | |_______________________^ + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs index fe950b0aa7..063f0c6460 100644 --- a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs +++ b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs @@ -1,29 +1,18 @@ #![deny(clippy::internal)] #![feature(rustc_private)] +extern crate clippy_utils; extern crate rustc_hir; extern crate rustc_lint; extern crate rustc_middle; + #[macro_use] extern crate rustc_session; +use clippy_utils::{paths, ty::match_type}; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -mod paths { - pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; -} - -mod utils { - use super::*; - - pub fn match_type(_cx: &LateContext<'_>, _ty: Ty<'_>, _path: &[&str]) -> bool { - false - } -} - -use utils::match_type; - declare_lint! { pub TEST_LINT, Warn, @@ -38,12 +27,12 @@ impl<'tcx> LateLintPass<'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr) { let ty = cx.typeck_results().expr_ty(expr); - let _ = match_type(cx, ty, &paths::VEC); + let _ = match_type(cx, ty, &paths::VEC); // FIXME: Doesn't lint external paths let _ = match_type(cx, ty, &OPTION); let _ = match_type(cx, ty, &["core", "result", "Result"]); let rc_path = &["alloc", "rc", "Rc"]; - let _ = utils::match_type(cx, ty, rc_path); + let _ = clippy_utils::ty::match_type(cx, ty, rc_path); } } diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr index 82465dbaf6..7147296056 100644 --- a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr +++ b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr @@ -1,8 +1,8 @@ -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:41:17 +error: usage of `clippy_utils::ty::match_type()` on a type diagnostic item + --> $DIR/match_type_on_diag_item.rs:31:17 | -LL | let _ = match_type(cx, ty, &paths::VEC); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::vec_type)` +LL | let _ = match_type(cx, ty, &OPTION); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clippy_utils::ty::is_type_diagnostic_item(cx, ty, sym::option_type)` | note: the lint level is defined here --> $DIR/match_type_on_diag_item.rs:1:9 @@ -11,23 +11,17 @@ LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::match_type_on_diagnostic_item)]` implied by `#[deny(clippy::internal)]` -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:42:17 - | -LL | let _ = match_type(cx, ty, &OPTION); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::option_type)` - -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:43:17 +error: usage of `clippy_utils::ty::match_type()` on a type diagnostic item + --> $DIR/match_type_on_diag_item.rs:32:17 | LL | let _ = match_type(cx, ty, &["core", "result", "Result"]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::result_type)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clippy_utils::ty::is_type_diagnostic_item(cx, ty, sym::result_type)` -error: usage of `utils::match_type()` on a type diagnostic item - --> $DIR/match_type_on_diag_item.rs:46:17 +error: usage of `clippy_utils::ty::match_type()` on a type diagnostic item + --> $DIR/match_type_on_diag_item.rs:35:17 | -LL | let _ = utils::match_type(cx, ty, rc_path); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::Rc)` +LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clippy_utils::ty::is_type_diagnostic_item(cx, ty, sym::Rc)` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs b/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs index 735909887a..1a5cf1b194 100644 --- a/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs +++ b/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs @@ -20,4 +20,25 @@ enum Flags { // `GccLlvmSomething` struct GCCLLVMSomething; +// don't warn on public items +pub struct MIXEDCapital; + +pub struct FULLCAPITAL; + +// enum variants should not be linted if the num is pub +pub enum ParseError<T> { + FULLCAPITAL(u8), + MIXEDCapital(String), + Utf8(std::string::FromUtf8Error), + Parse(T, String), +} + +// private, do lint here +enum ParseErrorPrivate<T> { + WASD(u8), + WASDMixed(String), + Utf8(std::string::FromUtf8Error), + Parse(T, String), +} + fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr b/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr index 38e30683d5..02f29bbefe 100644 --- a/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr +++ b/src/tools/clippy/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr @@ -66,5 +66,17 @@ error: name `GCCLLVMSomething` contains a capitalized acronym LL | struct GCCLLVMSomething; | ^^^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `GccllvmSomething` -error: aborting due to 11 previous errors +error: name `WASD` contains a capitalized acronym + --> $DIR/upper_case_acronyms.rs:38:5 + | +LL | WASD(u8), + | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Wasd` + +error: name `WASDMixed` contains a capitalized acronym + --> $DIR/upper_case_acronyms.rs:39:5 + | +LL | WASDMixed(String), + | ^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `WasdMixed` + +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/asm_syntax.rs b/src/tools/clippy/tests/ui/asm_syntax.rs index 658cae397e..4a62f6f290 100644 --- a/src/tools/clippy/tests/ui/asm_syntax.rs +++ b/src/tools/clippy/tests/ui/asm_syntax.rs @@ -1,5 +1,7 @@ -#![feature(asm)] // only-x86_64 +// ignore-aarch64 + +#![feature(asm)] #[warn(clippy::inline_asm_x86_intel_syntax)] mod warn_intel { @@ -23,6 +25,7 @@ mod warn_att { } } +#[cfg(target_arch = "x86_64")] fn main() { unsafe { warn_att::use_asm(); diff --git a/src/tools/clippy/tests/ui/asm_syntax.stderr b/src/tools/clippy/tests/ui/asm_syntax.stderr index 27b51166ea..e3abbe0865 100644 --- a/src/tools/clippy/tests/ui/asm_syntax.stderr +++ b/src/tools/clippy/tests/ui/asm_syntax.stderr @@ -1,5 +1,5 @@ error: Intel x86 assembly syntax used - --> $DIR/asm_syntax.rs:7:9 + --> $DIR/asm_syntax.rs:9:9 | LL | asm!(""); | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | asm!(""); = help: use AT&T x86 assembly syntax error: Intel x86 assembly syntax used - --> $DIR/asm_syntax.rs:8:9 + --> $DIR/asm_syntax.rs:10:9 | LL | asm!("", options()); | ^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | asm!("", options()); = help: use AT&T x86 assembly syntax error: Intel x86 assembly syntax used - --> $DIR/asm_syntax.rs:9:9 + --> $DIR/asm_syntax.rs:11:9 | LL | asm!("", options(nostack)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | asm!("", options(nostack)); = help: use AT&T x86 assembly syntax error: AT&T x86 assembly syntax used - --> $DIR/asm_syntax.rs:21:9 + --> $DIR/asm_syntax.rs:23:9 | LL | asm!("", options(att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | asm!("", options(att_syntax)); = help: use Intel x86 assembly syntax error: AT&T x86 assembly syntax used - --> $DIR/asm_syntax.rs:22:9 + --> $DIR/asm_syntax.rs:24:9 | LL | asm!("", options(nostack, att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.rs b/src/tools/clippy/tests/ui/bool_assert_comparison.rs new file mode 100644 index 0000000000..2de402fae8 --- /dev/null +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.rs @@ -0,0 +1,59 @@ +#![warn(clippy::bool_assert_comparison)] + +macro_rules! a { + () => { + true + }; +} +macro_rules! b { + () => { + true + }; +} + +fn main() { + assert_eq!("a".len(), 1); + assert_eq!("a".is_empty(), false); + assert_eq!("".is_empty(), true); + assert_eq!(true, "".is_empty()); + assert_eq!(a!(), b!()); + assert_eq!(a!(), "".is_empty()); + assert_eq!("".is_empty(), b!()); + + assert_ne!("a".len(), 1); + assert_ne!("a".is_empty(), false); + assert_ne!("".is_empty(), true); + assert_ne!(true, "".is_empty()); + assert_ne!(a!(), b!()); + assert_ne!(a!(), "".is_empty()); + assert_ne!("".is_empty(), b!()); + + debug_assert_eq!("a".len(), 1); + debug_assert_eq!("a".is_empty(), false); + debug_assert_eq!("".is_empty(), true); + debug_assert_eq!(true, "".is_empty()); + debug_assert_eq!(a!(), b!()); + debug_assert_eq!(a!(), "".is_empty()); + debug_assert_eq!("".is_empty(), b!()); + + debug_assert_ne!("a".len(), 1); + debug_assert_ne!("a".is_empty(), false); + debug_assert_ne!("".is_empty(), true); + debug_assert_ne!(true, "".is_empty()); + debug_assert_ne!(a!(), b!()); + debug_assert_ne!(a!(), "".is_empty()); + debug_assert_ne!("".is_empty(), b!()); + + // assert with error messages + assert_eq!("a".len(), 1, "tadam {}", 1); + assert_eq!("a".len(), 1, "tadam {}", true); + assert_eq!("a".is_empty(), false, "tadam {}", 1); + assert_eq!("a".is_empty(), false, "tadam {}", true); + assert_eq!(false, "a".is_empty(), "tadam {}", true); + + debug_assert_eq!("a".len(), 1, "tadam {}", 1); + debug_assert_eq!("a".len(), 1, "tadam {}", true); + debug_assert_eq!("a".is_empty(), false, "tadam {}", 1); + debug_assert_eq!("a".is_empty(), false, "tadam {}", true); + debug_assert_eq!(false, "a".is_empty(), "tadam {}", true); +} diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr new file mode 100644 index 0000000000..f57acf520d --- /dev/null +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr @@ -0,0 +1,112 @@ +error: used `assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:16:5 + | +LL | assert_eq!("a".is_empty(), false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + | + = note: `-D clippy::bool-assert-comparison` implied by `-D warnings` + +error: used `assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:17:5 + | +LL | assert_eq!("".is_empty(), true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:18:5 + | +LL | assert_eq!(true, "".is_empty()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `assert_ne!` with a literal bool + --> $DIR/bool_assert_comparison.rs:24:5 + | +LL | assert_ne!("a".is_empty(), false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `assert_ne!` with a literal bool + --> $DIR/bool_assert_comparison.rs:25:5 + | +LL | assert_ne!("".is_empty(), true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `assert_ne!` with a literal bool + --> $DIR/bool_assert_comparison.rs:26:5 + | +LL | assert_ne!(true, "".is_empty()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `debug_assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:32:5 + | +LL | debug_assert_eq!("a".is_empty(), false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `debug_assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:33:5 + | +LL | debug_assert_eq!("".is_empty(), true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `debug_assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:34:5 + | +LL | debug_assert_eq!(true, "".is_empty()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `debug_assert_ne!` with a literal bool + --> $DIR/bool_assert_comparison.rs:40:5 + | +LL | debug_assert_ne!("a".is_empty(), false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `debug_assert_ne!` with a literal bool + --> $DIR/bool_assert_comparison.rs:41:5 + | +LL | debug_assert_ne!("".is_empty(), true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `debug_assert_ne!` with a literal bool + --> $DIR/bool_assert_comparison.rs:42:5 + | +LL | debug_assert_ne!(true, "".is_empty()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:50:5 + | +LL | assert_eq!("a".is_empty(), false, "tadam {}", 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:51:5 + | +LL | assert_eq!("a".is_empty(), false, "tadam {}", true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:52:5 + | +LL | assert_eq!(false, "a".is_empty(), "tadam {}", true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)` + +error: used `debug_assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:56:5 + | +LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `debug_assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:57:5 + | +LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: used `debug_assert_eq!` with a literal bool + --> $DIR/bool_assert_comparison.rs:58:5 + | +LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)` + +error: aborting due to 18 previous errors + diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs index ea25729d11..4327f12c37 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs @@ -1,5 +1,9 @@ #![warn(clippy::borrow_interior_mutable_const)] -#![allow(clippy::declare_interior_mutable_const, clippy::ref_in_deref)] +#![allow( + clippy::declare_interior_mutable_const, + clippy::ref_in_deref, + clippy::needless_borrow +)] #![allow(const_item_mutation)] use std::borrow::Cow; diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr index 9a908cf30e..f146b97cf6 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr @@ -1,5 +1,5 @@ error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:54:5 + --> $DIR/others.rs:58:5 | LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^ @@ -8,7 +8,7 @@ LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:55:16 + --> $DIR/others.rs:59:16 | LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability | ^^^^^^ @@ -16,7 +16,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:58:22 + --> $DIR/others.rs:62:22 | LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:59:25 + --> $DIR/others.rs:63:25 | LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:60:27 + --> $DIR/others.rs:64:27 | LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:61:26 + --> $DIR/others.rs:65:26 | LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability | ^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:72:14 + --> $DIR/others.rs:76:14 | LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:73:14 + --> $DIR/others.rs:77:14 | LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:74:19 + --> $DIR/others.rs:78:19 | LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:75:14 + --> $DIR/others.rs:79:14 | LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:76:13 + --> $DIR/others.rs:80:13 | LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:82:13 + --> $DIR/others.rs:86:13 | LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability | ^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:87:5 + --> $DIR/others.rs:91:5 | LL | CELL.set(2); //~ ERROR interior mutability | ^^^^ @@ -104,7 +104,7 @@ LL | CELL.set(2); //~ ERROR interior mutability = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> $DIR/others.rs:88:16 + --> $DIR/others.rs:92:16 | LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability | ^^^^ diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs new file mode 100644 index 0000000000..ce2040bdeb --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs @@ -0,0 +1,223 @@ +#![allow(dead_code)] +#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + +// This tests the branches_sharing_code lint at the end of blocks + +fn simple_examples() { + let x = 1; + + let _ = if x == 7 { + println!("Branch I"); + let start_value = 0; + println!("=^.^="); + + // Same but not moveable due to `start_value` + let _ = start_value; + + // The rest is self contained and moveable => Only lint the rest + let result = false; + println!("Block end!"); + result + } else { + println!("Branch II"); + let start_value = 8; + println!("xD"); + + // Same but not moveable due to `start_value` + let _ = start_value; + + // The rest is self contained and moveable => Only lint the rest + let result = false; + println!("Block end!"); + result + }; + + // Else if block + if x == 9 { + println!("The index is: 6"); + + println!("Same end of block"); + } else if x == 8 { + println!("The index is: 4"); + + // We should only get a lint trigger for the last statement + println!("This is also eq with the else block"); + println!("Same end of block"); + } else { + println!("This is also eq with the else block"); + println!("Same end of block"); + } + + // Use of outer scope value + let outer_scope_value = "I'm outside the if block"; + if x < 99 { + let z = "How are you"; + println!("I'm a local because I use the value `z`: `{}`", z); + + println!( + "I'm moveable because I know: `outer_scope_value`: '{}'", + outer_scope_value + ); + } else { + let z = 45678000; + println!("I'm a local because I use the value `z`: `{}`", z); + + println!( + "I'm moveable because I know: `outer_scope_value`: '{}'", + outer_scope_value + ); + } + + if x == 9 { + if x == 8 { + // No parent!! + println!("---"); + println!("Hello World"); + } else { + println!("Hello World"); + } + } +} + +/// Simple examples where the move can cause some problems due to moved values +fn simple_but_suggestion_is_invalid() { + let x = 16; + + // Local value + let later_used_value = 17; + if x == 9 { + let _ = 9; + let later_used_value = "A string value"; + println!("{}", later_used_value); + } else { + let later_used_value = "A string value"; + println!("{}", later_used_value); + // I'm expecting a note about this + } + println!("{}", later_used_value); + + // outer function + if x == 78 { + let simple_examples = "I now identify as a &str :)"; + println!("This is the new simple_example: {}", simple_examples); + } else { + println!("Separator print statement"); + + let simple_examples = "I now identify as a &str :)"; + println!("This is the new simple_example: {}", simple_examples); + } + simple_examples(); +} + +/// Tests where the blocks are not linted due to the used value scope +fn not_moveable_due_to_value_scope() { + let x = 18; + + // Using a local value in the moved code + if x == 9 { + let y = 18; + println!("y is: `{}`", y); + } else { + let y = "A string"; + println!("y is: `{}`", y); + } + + // Using a local value in the expression + let _ = if x == 0 { + let mut result = x + 1; + + println!("1. Doing some calculations"); + println!("2. Some more calculations"); + println!("3. Setting result"); + + result + } else { + let mut result = x - 1; + + println!("1. Doing some calculations"); + println!("2. Some more calculations"); + println!("3. Setting result"); + + result + }; + + let _ = if x == 7 { + let z1 = 100; + println!("z1: {}", z1); + + let z2 = z1; + println!("z2: {}", z2); + + z2 + } else { + let z1 = 300; + println!("z1: {}", z1); + + let z2 = z1; + println!("z2: {}", z2); + + z2 + }; +} + +/// This should add a note to the lint msg since the moved expression is not `()` +fn added_note_for_expression_use() -> u32 { + let x = 9; + + let _ = if x == 7 { + x << 2 + } else { + let _ = 6; + x << 2 + }; + + if x == 9 { + x * 4 + } else { + let _ = 17; + x * 4 + } +} + +#[rustfmt::skip] +fn test_suggestion_with_weird_formatting() { + let x = 9; + let mut a = 0; + let mut b = 0; + + // The error message still looks weird tbh but this is the best I can do + // for weird formatting + if x == 17 { b = 1; a = 0x99; } else { a = 0x99; } +} + +fn fp_test() { + let x = 17; + + if x == 18 { + let y = 19; + if y < x { + println!("Trigger") + } + } else { + let z = 166; + if z < x { + println!("Trigger") + } + } +} + +fn fp_if_let_issue7054() { + // This shouldn't trigger the lint + let string; + let _x = if let true = true { + "" + } else if true { + string = "x".to_owned(); + &string + } else { + string = "y".to_owned(); + &string + }; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr new file mode 100644 index 0000000000..271fcd8b6c --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr @@ -0,0 +1,143 @@ +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:30:5 + | +LL | / let result = false; +LL | | println!("Block end!"); +LL | | result +LL | | }; + | |_____^ + | +note: the lint level is defined here + --> $DIR/shared_at_bottom.rs:2:36 + | +LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: The end suggestion probably needs some adjustments to use the expression result correctly +help: consider moving the end statements out like this + | +LL | } +LL | let result = false; +LL | println!("Block end!"); +LL | result; + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:48:5 + | +LL | / println!("Same end of block"); +LL | | } + | |_____^ + | +help: consider moving the end statements out like this + | +LL | } +LL | println!("Same end of block"); + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:65:5 + | +LL | / println!( +LL | | "I'm moveable because I know: `outer_scope_value`: '{}'", +LL | | outer_scope_value +LL | | ); +LL | | } + | |_____^ + | +help: consider moving the end statements out like this + | +LL | } +LL | println!( +LL | "I'm moveable because I know: `outer_scope_value`: '{}'", +LL | outer_scope_value +LL | ); + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:77:9 + | +LL | / println!("Hello World"); +LL | | } + | |_________^ + | +help: consider moving the end statements out like this + | +LL | } +LL | println!("Hello World"); + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:93:5 + | +LL | / let later_used_value = "A string value"; +LL | | println!("{}", later_used_value); +LL | | // I'm expecting a note about this +LL | | } + | |_____^ + | + = warning: Some moved values might need to be renamed to avoid wrong references +help: consider moving the end statements out like this + | +LL | } +LL | let later_used_value = "A string value"; +LL | println!("{}", later_used_value); + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:106:5 + | +LL | / let simple_examples = "I now identify as a &str :)"; +LL | | println!("This is the new simple_example: {}", simple_examples); +LL | | } + | |_____^ + | + = warning: Some moved values might need to be renamed to avoid wrong references +help: consider moving the end statements out like this + | +LL | } +LL | let simple_examples = "I now identify as a &str :)"; +LL | println!("This is the new simple_example: {}", simple_examples); + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:171:5 + | +LL | / x << 2 +LL | | }; + | |_____^ + | + = note: The end suggestion probably needs some adjustments to use the expression result correctly +help: consider moving the end statements out like this + | +LL | } +LL | x << 2; + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:178:5 + | +LL | / x * 4 +LL | | } + | |_____^ + | + = note: The end suggestion probably needs some adjustments to use the expression result correctly +help: consider moving the end statements out like this + | +LL | } +LL | x * 4 + | + +error: all if blocks contain the same code at the end + --> $DIR/shared_at_bottom.rs:190:44 + | +LL | if x == 17 { b = 1; a = 0x99; } else { a = 0x99; } + | ^^^^^^^^^^^ + | +help: consider moving the end statements out like this + | +LL | if x == 17 { b = 1; a = 0x99; } else { } +LL | a = 0x99; + | + +error: aborting due to 9 previous errors + diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs new file mode 100644 index 0000000000..51a4648139 --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs @@ -0,0 +1,114 @@ +#![allow(dead_code, clippy::eval_order_dependence)] +#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + +// This tests the branches_sharing_code lint at the start of blocks + +fn simple_examples() { + let x = 0; + + // Simple + if true { + println!("Hello World!"); + println!("I'm branch nr: 1"); + } else { + println!("Hello World!"); + println!("I'm branch nr: 2"); + } + + // Else if + if x == 0 { + let y = 9; + println!("The value y was set to: `{}`", y); + let _z = y; + + println!("I'm the true start index of arrays"); + } else if x == 1 { + let y = 9; + println!("The value y was set to: `{}`", y); + let _z = y; + + println!("I start counting from 1 so my array starts from `1`"); + } else { + let y = 9; + println!("The value y was set to: `{}`", y); + let _z = y; + + println!("Ha, Pascal allows you to start the array where you want") + } + + // Return a value + let _ = if x == 7 { + let y = 16; + println!("What can I say except: \"you're welcome?\""); + let _ = y; + x + } else { + let y = 16; + println!("Thank you"); + y + }; +} + +/// Simple examples where the move can cause some problems due to moved values +fn simple_but_suggestion_is_invalid() { + let x = 10; + + // Can't be automatically moved because used_value_name is getting used again + let used_value_name = 19; + if x == 10 { + let used_value_name = "Different type"; + println!("Str: {}", used_value_name); + let _ = 1; + } else { + let used_value_name = "Different type"; + println!("Str: {}", used_value_name); + let _ = 2; + } + let _ = used_value_name; + + // This can be automatically moved as `can_be_overridden` is not used again + let can_be_overridden = 8; + let _ = can_be_overridden; + if x == 11 { + let can_be_overridden = "Move me"; + println!("I'm also moveable"); + let _ = 111; + } else { + let can_be_overridden = "Move me"; + println!("I'm also moveable"); + let _ = 222; + } +} + +/// This function tests that the `IS_SAME_THAN_ELSE` only covers the lint if it's enabled. +fn check_if_same_than_else_mask() { + let x = 2021; + + #[allow(clippy::if_same_then_else)] + if x == 2020 { + println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint."); + println!("Because `IF_SAME_THEN_ELSE` is allowed here"); + } else { + println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint."); + println!("Because `IF_SAME_THEN_ELSE` is allowed here"); + } + + if x == 2019 { + println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); + } else { + println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); + } +} + +#[allow(clippy::vec_init_then_push)] +fn pf_local_with_inferred_type_issue7053() { + if true { + let mut v = Vec::new(); + v.push(0); + } else { + let mut v = Vec::new(); + v.push(""); + }; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr new file mode 100644 index 0000000000..15867e9ea0 --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr @@ -0,0 +1,121 @@ +error: all if blocks contain the same code at the start + --> $DIR/shared_at_top.rs:10:5 + | +LL | / if true { +LL | | println!("Hello World!"); + | |_________________________________^ + | +note: the lint level is defined here + --> $DIR/shared_at_top.rs:2:36 + | +LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider moving the start statements out like this + | +LL | println!("Hello World!"); +LL | if true { + | + +error: all if blocks contain the same code at the start + --> $DIR/shared_at_top.rs:19:5 + | +LL | / if x == 0 { +LL | | let y = 9; +LL | | println!("The value y was set to: `{}`", y); +LL | | let _z = y; + | |___________________^ + | + = warning: Some moved values might need to be renamed to avoid wrong references +help: consider moving the start statements out like this + | +LL | let y = 9; +LL | println!("The value y was set to: `{}`", y); +LL | let _z = y; +LL | if x == 0 { + | + +error: all if blocks contain the same code at the start + --> $DIR/shared_at_top.rs:40:5 + | +LL | / let _ = if x == 7 { +LL | | let y = 16; + | |___________________^ + | +help: consider moving the start statements out like this + | +LL | let y = 16; +LL | let _ = if x == 7 { + | + +error: all if blocks contain the same code at the start + --> $DIR/shared_at_top.rs:58:5 + | +LL | / if x == 10 { +LL | | let used_value_name = "Different type"; +LL | | println!("Str: {}", used_value_name); + | |_____________________________________________^ + | + = warning: Some moved values might need to be renamed to avoid wrong references +help: consider moving the start statements out like this + | +LL | let used_value_name = "Different type"; +LL | println!("Str: {}", used_value_name); +LL | if x == 10 { + | + +error: all if blocks contain the same code at the start + --> $DIR/shared_at_top.rs:72:5 + | +LL | / if x == 11 { +LL | | let can_be_overridden = "Move me"; +LL | | println!("I'm also moveable"); + | |______________________________________^ + | + = warning: Some moved values might need to be renamed to avoid wrong references +help: consider moving the start statements out like this + | +LL | let can_be_overridden = "Move me"; +LL | println!("I'm also moveable"); +LL | if x == 11 { + | + +error: all if blocks contain the same code at the start + --> $DIR/shared_at_top.rs:88:5 + | +LL | / if x == 2020 { +LL | | println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint."); +LL | | println!("Because `IF_SAME_THEN_ELSE` is allowed here"); + | |________________________________________________________________^ + | +help: consider moving the start statements out like this + | +LL | println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint."); +LL | println!("Because `IF_SAME_THEN_ELSE` is allowed here"); +LL | if x == 2020 { + | + +error: this `if` has identical blocks + --> $DIR/shared_at_top.rs:96:18 + | +LL | if x == 2019 { + | __________________^ +LL | | println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); +LL | | } else { + | |_____^ + | +note: the lint level is defined here + --> $DIR/shared_at_top.rs:2:9 + | +LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: same as this + --> $DIR/shared_at_top.rs:98:12 + | +LL | } else { + | ____________^ +LL | | println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); +LL | | } + | |_____^ + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs new file mode 100644 index 0000000000..deefdad32c --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs @@ -0,0 +1,119 @@ +#![allow(dead_code)] +#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + +// branches_sharing_code at the top and bottom of the if blocks + +struct DataPack { + id: u32, + name: String, + some_data: Vec<u8>, +} + +fn overlapping_eq_regions() { + let x = 9; + + // Overlap with separator + if x == 7 { + let t = 7; + let _overlap_start = t * 2; + let _overlap_end = 2 * t; + let _u = 9; + } else { + let t = 7; + let _overlap_start = t * 2; + let _overlap_end = 2 * t; + println!("Overlap separator"); + let _overlap_start = t * 2; + let _overlap_end = 2 * t; + let _u = 9; + } + + // Overlap with separator + if x == 99 { + let r = 7; + let _overlap_start = r; + let _overlap_middle = r * r; + let _overlap_end = r * r * r; + let z = "end"; + } else { + let r = 7; + let _overlap_start = r; + let _overlap_middle = r * r; + let _overlap_middle = r * r; + let _overlap_end = r * r * r; + let z = "end"; + } +} + +fn complexer_example() { + fn gen_id(x: u32, y: u32) -> u32 { + let x = x & 0x0000_ffff; + let y = (y & 0xffff_0000) << 16; + x | y + } + + fn process_data(data: DataPack) { + let _ = data; + } + + let x = 8; + let y = 9; + if (x > 7 && y < 13) || (x + y) % 2 == 1 { + let a = 0xcafe; + let b = 0xffff00ff; + let e_id = gen_id(a, b); + + println!("From the a `{}` to the b `{}`", a, b); + + let pack = DataPack { + id: e_id, + name: "Player 1".to_string(), + some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90], + }; + process_data(pack); + } else { + let a = 0xcafe; + let b = 0xffff00ff; + let e_id = gen_id(a, b); + + println!("The new ID is '{}'", e_id); + + let pack = DataPack { + id: e_id, + name: "Player 1".to_string(), + some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90], + }; + process_data(pack); + } +} + +/// This should add a note to the lint msg since the moved expression is not `()` +fn added_note_for_expression_use() -> u32 { + let x = 9; + + let _ = if x == 7 { + let _ = 19; + + let _splitter = 6; + + x << 2 + } else { + let _ = 19; + + x << 2 + }; + + if x == 9 { + let _ = 17; + + let _splitter = 6; + + x * 4 + } else { + let _ = 17; + + x * 4 + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr new file mode 100644 index 0000000000..212cfb2f1d --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr @@ -0,0 +1,154 @@ +error: all if blocks contain the same code at the start and the end. Here at the start + --> $DIR/shared_at_top_and_bottom.rs:16:5 + | +LL | / if x == 7 { +LL | | let t = 7; +LL | | let _overlap_start = t * 2; +LL | | let _overlap_end = 2 * t; + | |_________________________________^ + | +note: the lint level is defined here + --> $DIR/shared_at_top_and_bottom.rs:2:36 + | +LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: and here at the end + --> $DIR/shared_at_top_and_bottom.rs:28:5 + | +LL | / let _u = 9; +LL | | } + | |_____^ +help: consider moving the start statements out like this + | +LL | let t = 7; +LL | let _overlap_start = t * 2; +LL | let _overlap_end = 2 * t; +LL | if x == 7 { + | +help: and consider moving the end statements out like this + | +LL | } +LL | let _u = 9; + | + +error: all if blocks contain the same code at the start and the end. Here at the start + --> $DIR/shared_at_top_and_bottom.rs:32:5 + | +LL | / if x == 99 { +LL | | let r = 7; +LL | | let _overlap_start = r; +LL | | let _overlap_middle = r * r; + | |____________________________________^ + | +note: and here at the end + --> $DIR/shared_at_top_and_bottom.rs:43:5 + | +LL | / let _overlap_end = r * r * r; +LL | | let z = "end"; +LL | | } + | |_____^ + = warning: Some moved values might need to be renamed to avoid wrong references +help: consider moving the start statements out like this + | +LL | let r = 7; +LL | let _overlap_start = r; +LL | let _overlap_middle = r * r; +LL | if x == 99 { + | +help: and consider moving the end statements out like this + | +LL | } +LL | let _overlap_end = r * r * r; +LL | let z = "end"; + | + +error: all if blocks contain the same code at the start and the end. Here at the start + --> $DIR/shared_at_top_and_bottom.rs:61:5 + | +LL | / if (x > 7 && y < 13) || (x + y) % 2 == 1 { +LL | | let a = 0xcafe; +LL | | let b = 0xffff00ff; +LL | | let e_id = gen_id(a, b); + | |________________________________^ + | +note: and here at the end + --> $DIR/shared_at_top_and_bottom.rs:81:5 + | +LL | / let pack = DataPack { +LL | | id: e_id, +LL | | name: "Player 1".to_string(), +LL | | some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90], +LL | | }; +LL | | process_data(pack); +LL | | } + | |_____^ + = warning: Some moved values might need to be renamed to avoid wrong references +help: consider moving the start statements out like this + | +LL | let a = 0xcafe; +LL | let b = 0xffff00ff; +LL | let e_id = gen_id(a, b); +LL | if (x > 7 && y < 13) || (x + y) % 2 == 1 { + | +help: and consider moving the end statements out like this + | +LL | } +LL | let pack = DataPack { +LL | id: e_id, +LL | name: "Player 1".to_string(), +LL | some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90], +LL | }; + ... + +error: all if blocks contain the same code at the start and the end. Here at the start + --> $DIR/shared_at_top_and_bottom.rs:94:5 + | +LL | / let _ = if x == 7 { +LL | | let _ = 19; + | |___________________^ + | +note: and here at the end + --> $DIR/shared_at_top_and_bottom.rs:103:5 + | +LL | / x << 2 +LL | | }; + | |_____^ + = note: The end suggestion probably needs some adjustments to use the expression result correctly +help: consider moving the start statements out like this + | +LL | let _ = 19; +LL | let _ = if x == 7 { + | +help: and consider moving the end statements out like this + | +LL | } +LL | x << 2; + | + +error: all if blocks contain the same code at the start and the end. Here at the start + --> $DIR/shared_at_top_and_bottom.rs:106:5 + | +LL | / if x == 9 { +LL | | let _ = 17; + | |___________________^ + | +note: and here at the end + --> $DIR/shared_at_top_and_bottom.rs:115:5 + | +LL | / x * 4 +LL | | } + | |_____^ + = note: The end suggestion probably needs some adjustments to use the expression result correctly +help: consider moving the start statements out like this + | +LL | let _ = 17; +LL | if x == 9 { + | +help: and consider moving the end statements out like this + | +LL | } +LL | x * 4 + | + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs new file mode 100644 index 0000000000..0c70e3748e --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs @@ -0,0 +1,155 @@ +#![allow(dead_code, clippy::eval_order_dependence)] +#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + +// This tests valid if blocks that shouldn't trigger the lint + +// Tests with value references are includes in "shared_code_at_bottom.rs" + +fn valid_examples() { + let x = 2; + + // The edge statements are different + if x == 9 { + let y = 1 << 5; + + println!("This is the same: vvv"); + let _z = y; + println!("The block expression is different"); + + println!("Different end 1"); + } else { + let y = 1 << 7; + + println!("This is the same: vvv"); + let _z = y; + println!("The block expression is different"); + + println!("Different end 2"); + } + + // No else + if x == 2 { + println!("Hello world!"); + println!("Hello back, how are you?"); + + // This is different vvvv + println!("Howdy stranger =^.^="); + + println!("Bye Bye World"); + } else if x == 9 { + println!("Hello world!"); + println!("Hello back, how are you?"); + + // This is different vvvv + println!("Hello reviewer :D"); + + println!("Bye Bye World"); + } + + // Overlapping statements only in else if blocks -> Don't lint + if x == 0 { + println!("I'm important!") + } else if x == 17 { + println!("I share code in else if"); + + println!("x is 17"); + } else { + println!("I share code in else if"); + + println!("x is nether x nor 17"); + } + + // Mutability is different + if x == 13 { + let mut y = 9; + println!("Value y is: {}", y); + y += 16; + let _z1 = y; + } else { + let y = 9; + println!("Value y is: {}", y); + let _z2 = y; + } + + // Same blocks but at start and bottom so no `if_same_then_else` lint + if x == 418 { + let y = 9; + let z = 8; + let _ = (x, y, z); + // Don't tell the programmer, my code is also in the else block + } else if x == 419 { + println!("+-----------+"); + println!("| |"); + println!("| O O |"); + println!("| ° |"); + println!("| \\_____/ |"); + println!("| |"); + println!("+-----------+"); + } else { + let y = 9; + let z = 8; + let _ = (x, y, z); + // I'm so much better than the x == 418 block. Trust me + } + + let x = 1; + if true { + println!("{}", x); + } else { + let x = 2; + println!("{}", x); + } + + // Let's test empty blocks + if false { + } else { + } +} + +/// This makes sure that the `if_same_then_else` masks the `shared_code_in_if_blocks` lint +fn trigger_other_lint() { + let x = 0; + let y = 1; + + // Same block + if x == 0 { + let u = 19; + println!("How are u today?"); + let _ = "This is a string"; + } else { + let u = 19; + println!("How are u today?"); + let _ = "This is a string"; + } + + // Only same expression + let _ = if x == 6 { 7 } else { 7 }; + + // Same in else if block + let _ = if x == 67 { + println!("Well I'm the most important block"); + "I'm a pretty string" + } else if x == 68 { + println!("I'm a doppelgänger"); + // Don't listen to my clone below + + if y == 90 { "=^.^=" } else { ":D" } + } else { + // Don't listen to my clone above + println!("I'm a doppelgänger"); + + if y == 90 { "=^.^=" } else { ":D" } + }; + + if x == 0 { + println!("I'm single"); + } else if x == 68 { + println!("I'm a doppelgänger"); + // Don't listen to my clone below + } else { + // Don't listen to my clone above + println!("I'm a doppelgänger"); + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr new file mode 100644 index 0000000000..a815995e71 --- /dev/null +++ b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr @@ -0,0 +1,101 @@ +error: this `if` has identical blocks + --> $DIR/valid_if_blocks.rs:104:14 + | +LL | if false { + | ______________^ +LL | | } else { + | |_____^ + | +note: the lint level is defined here + --> $DIR/valid_if_blocks.rs:2:9 + | +LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: same as this + --> $DIR/valid_if_blocks.rs:105:12 + | +LL | } else { + | ____________^ +LL | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/valid_if_blocks.rs:115:15 + | +LL | if x == 0 { + | _______________^ +LL | | let u = 19; +LL | | println!("How are u today?"); +LL | | let _ = "This is a string"; +LL | | } else { + | |_____^ + | +note: same as this + --> $DIR/valid_if_blocks.rs:119:12 + | +LL | } else { + | ____________^ +LL | | let u = 19; +LL | | println!("How are u today?"); +LL | | let _ = "This is a string"; +LL | | } + | |_____^ + +error: this `if` has identical blocks + --> $DIR/valid_if_blocks.rs:126:23 + | +LL | let _ = if x == 6 { 7 } else { 7 }; + | ^^^^^ + | +note: same as this + --> $DIR/valid_if_blocks.rs:126:34 + | +LL | let _ = if x == 6 { 7 } else { 7 }; + | ^^^^^ + +error: this `if` has identical blocks + --> $DIR/valid_if_blocks.rs:132:23 + | +LL | } else if x == 68 { + | _______________________^ +LL | | println!("I'm a doppelgänger"); +LL | | // Don't listen to my clone below +LL | | +LL | | if y == 90 { "=^.^=" } else { ":D" } +LL | | } else { + | |_____^ + | +note: same as this + --> $DIR/valid_if_blocks.rs:137:12 + | +LL | } else { + | ____________^ +LL | | // Don't listen to my clone above +LL | | println!("I'm a doppelgänger"); +LL | | +LL | | if y == 90 { "=^.^=" } else { ":D" } +LL | | }; + | |_____^ + +error: this `if` has identical blocks + --> $DIR/valid_if_blocks.rs:146:23 + | +LL | } else if x == 68 { + | _______________________^ +LL | | println!("I'm a doppelgänger"); +LL | | // Don't listen to my clone below +LL | | } else { + | |_____^ + | +note: same as this + --> $DIR/valid_if_blocks.rs:149:12 + | +LL | } else { + | ____________^ +LL | | // Don't listen to my clone above +LL | | println!("I'm a doppelgänger"); +LL | | } + | |_____^ + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs index c986c992a0..ec082c73b4 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs +++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs @@ -1,5 +1,5 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else)] +#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] fn test_complex_conditions() { let x: Result<(), ()> = Ok(()); diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs index 2307996a48..043ea4148d 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs +++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs @@ -1,5 +1,5 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else)] +#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] fn test_nested() { fn nested() { diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs index 3696763083..8f23fb2882 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs @@ -1,5 +1,5 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else)] +#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] macro_rules! m { ($a:expr) => { diff --git a/src/tools/clippy/tests/ui/clone_on_copy.fixed b/src/tools/clippy/tests/ui/clone_on_copy.fixed index d924625132..8d43f64768 100644 --- a/src/tools/clippy/tests/ui/clone_on_copy.fixed +++ b/src/tools/clippy/tests/ui/clone_on_copy.fixed @@ -6,7 +6,8 @@ clippy::deref_addrof, clippy::no_effect, clippy::unnecessary_operation, - clippy::vec_init_then_push + clippy::vec_init_then_push, + clippy::toplevel_ref_arg )] use std::cell::RefCell; @@ -29,6 +30,37 @@ fn clone_on_copy() { let rc = RefCell::new(0); *rc.borrow(); + let x = 0u32; + x.rotate_left(1); + + #[derive(Clone, Copy)] + struct Foo; + impl Foo { + fn clone(&self) -> u32 { + 0 + } + } + Foo.clone(); // ok, this is not the clone trait + + macro_rules! m { + ($e:expr) => {{ $e }}; + } + m!(42); + + struct Wrap([u32; 2]); + impl core::ops::Deref for Wrap { + type Target = [u32; 2]; + fn deref(&self) -> &[u32; 2] { + &self.0 + } + } + let x = Wrap([0, 0]); + (*x)[0]; + + let x = 42; + let ref y = x.clone(); // ok, binds by reference + let ref mut y = x.clone(); // ok, binds by reference + // Issue #4348 let mut x = 43; let _ = &x.clone(); // ok, getting a ref diff --git a/src/tools/clippy/tests/ui/clone_on_copy.rs b/src/tools/clippy/tests/ui/clone_on_copy.rs index 97f4946724..f15501f718 100644 --- a/src/tools/clippy/tests/ui/clone_on_copy.rs +++ b/src/tools/clippy/tests/ui/clone_on_copy.rs @@ -6,7 +6,8 @@ clippy::deref_addrof, clippy::no_effect, clippy::unnecessary_operation, - clippy::vec_init_then_push + clippy::vec_init_then_push, + clippy::toplevel_ref_arg )] use std::cell::RefCell; @@ -29,6 +30,37 @@ fn clone_on_copy() { let rc = RefCell::new(0); rc.borrow().clone(); + let x = 0u32; + x.clone().rotate_left(1); + + #[derive(Clone, Copy)] + struct Foo; + impl Foo { + fn clone(&self) -> u32 { + 0 + } + } + Foo.clone(); // ok, this is not the clone trait + + macro_rules! m { + ($e:expr) => {{ $e }}; + } + m!(42).clone(); + + struct Wrap([u32; 2]); + impl core::ops::Deref for Wrap { + type Target = [u32; 2]; + fn deref(&self) -> &[u32; 2] { + &self.0 + } + } + let x = Wrap([0, 0]); + x.clone()[0]; + + let x = 42; + let ref y = x.clone(); // ok, binds by reference + let ref mut y = x.clone(); // ok, binds by reference + // Issue #4348 let mut x = 43; let _ = &x.clone(); // ok, getting a ref diff --git a/src/tools/clippy/tests/ui/clone_on_copy.stderr b/src/tools/clippy/tests/ui/clone_on_copy.stderr index 7a706884fb..e7d28b4320 100644 --- a/src/tools/clippy/tests/ui/clone_on_copy.stderr +++ b/src/tools/clippy/tests/ui/clone_on_copy.stderr @@ -1,5 +1,5 @@ error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:23:5 + --> $DIR/clone_on_copy.rs:24:5 | LL | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` @@ -7,28 +7,46 @@ LL | 42.clone(); = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:27:5 + --> $DIR/clone_on_copy.rs:28:5 | LL | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:30:5 + --> $DIR/clone_on_copy.rs:31:5 | LL | rc.borrow().clone(); | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` +error: using `clone` on type `u32` which implements the `Copy` trait + --> $DIR/clone_on_copy.rs:34:5 + | +LL | x.clone().rotate_left(1); + | ^^^^^^^^^ help: try removing the `clone` call: `x` + +error: using `clone` on type `i32` which implements the `Copy` trait + --> $DIR/clone_on_copy.rs:48:5 + | +LL | m!(42).clone(); + | ^^^^^^^^^^^^^^ help: try removing the `clone` call: `m!(42)` + +error: using `clone` on type `[u32; 2]` which implements the `Copy` trait + --> $DIR/clone_on_copy.rs:58:5 + | +LL | x.clone()[0]; + | ^^^^^^^^^ help: try dereferencing it: `(*x)` + error: using `clone` on type `char` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:36:14 + --> $DIR/clone_on_copy.rs:68:14 | LL | is_ascii('z'.clone()); | ^^^^^^^^^^^ help: try removing the `clone` call: `'z'` error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:40:14 + --> $DIR/clone_on_copy.rs:72:14 | LL | vec.push(42.clone()); | ^^^^^^^^^^ help: try removing the `clone` call: `42` -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/clone_on_copy_mut.rs b/src/tools/clippy/tests/ui/clone_on_copy_mut.rs deleted file mode 100644 index 5bfa256623..0000000000 --- a/src/tools/clippy/tests/ui/clone_on_copy_mut.rs +++ /dev/null @@ -1,18 +0,0 @@ -pub fn dec_read_dec(i: &mut i32) -> i32 { - *i -= 1; - let ret = *i; - *i -= 1; - ret -} - -pub fn minus_1(i: &i32) -> i32 { - dec_read_dec(&mut i.clone()) -} - -fn main() { - let mut i = 10; - assert_eq!(minus_1(&i), 9); - assert_eq!(i, 10); - assert_eq!(dec_read_dec(&mut i), 9); - assert_eq!(i, 8); -} diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed new file mode 100644 index 0000000000..4eb999e18e --- /dev/null +++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![warn(clippy::cloned_instead_of_copied)] + +fn main() { + // yay + let _ = [1].iter().copied(); + let _ = vec!["hi"].iter().copied(); + let _ = Some(&1).copied(); + let _ = Box::new([1].iter()).copied(); + let _ = Box::new(Some(&1)).copied(); + + // nay + let _ = [String::new()].iter().cloned(); + let _ = Some(&String::new()).cloned(); +} diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs new file mode 100644 index 0000000000..894496c0eb --- /dev/null +++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs @@ -0,0 +1,15 @@ +// run-rustfix +#![warn(clippy::cloned_instead_of_copied)] + +fn main() { + // yay + let _ = [1].iter().cloned(); + let _ = vec!["hi"].iter().cloned(); + let _ = Some(&1).cloned(); + let _ = Box::new([1].iter()).cloned(); + let _ = Box::new(Some(&1)).cloned(); + + // nay + let _ = [String::new()].iter().cloned(); + let _ = Some(&String::new()).cloned(); +} diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr b/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr new file mode 100644 index 0000000000..e0707d3214 --- /dev/null +++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr @@ -0,0 +1,34 @@ +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:6:24 + | +LL | let _ = [1].iter().cloned(); + | ^^^^^^ help: try: `copied` + | + = note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings` + +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:7:31 + | +LL | let _ = vec!["hi"].iter().cloned(); + | ^^^^^^ help: try: `copied` + +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:8:22 + | +LL | let _ = Some(&1).cloned(); + | ^^^^^^ help: try: `copied` + +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:9:34 + | +LL | let _ = Box::new([1].iter()).cloned(); + | ^^^^^^ help: try: `copied` + +error: used `cloned` where `copied` could be used instead + --> $DIR/cloned_instead_of_copied.rs:10:32 + | +LL | let _ = Box::new(Some(&1)).cloned(); + | ^^^^^^ help: try: `copied` + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/collapsible_match2.rs b/src/tools/clippy/tests/ui/collapsible_match2.rs index 8372a21247..542e694842 100644 --- a/src/tools/clippy/tests/ui/collapsible_match2.rs +++ b/src/tools/clippy/tests/ui/collapsible_match2.rs @@ -1,5 +1,10 @@ #![warn(clippy::collapsible_match)] -#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)] +#![allow( + clippy::needless_return, + clippy::no_effect, + clippy::single_match, + clippy::needless_borrow +)] fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) { // if guards on outer match diff --git a/src/tools/clippy/tests/ui/collapsible_match2.stderr b/src/tools/clippy/tests/ui/collapsible_match2.stderr index c8a445ef36..ffef32d1fd 100644 --- a/src/tools/clippy/tests/ui/collapsible_match2.stderr +++ b/src/tools/clippy/tests/ui/collapsible_match2.stderr @@ -1,5 +1,5 @@ error: unnecessary nested match - --> $DIR/collapsible_match2.rs:8:34 + --> $DIR/collapsible_match2.rs:13:34 | LL | Ok(val) if make() => match val { | __________________________________^ @@ -10,7 +10,7 @@ LL | | }, | = note: `-D clippy::collapsible-match` implied by `-D warnings` help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:8:16 + --> $DIR/collapsible_match2.rs:13:16 | LL | Ok(val) if make() => match val { | ^^^ replace this binding @@ -18,7 +18,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: unnecessary nested match - --> $DIR/collapsible_match2.rs:15:24 + --> $DIR/collapsible_match2.rs:20:24 | LL | Ok(val) => match val { | ________________________^ @@ -28,7 +28,7 @@ LL | | }, | |_____________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:15:16 + --> $DIR/collapsible_match2.rs:20:16 | LL | Ok(val) => match val { | ^^^ replace this binding @@ -36,7 +36,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: unnecessary nested match - --> $DIR/collapsible_match2.rs:29:29 + --> $DIR/collapsible_match2.rs:34:29 | LL | $pat => match $e { | _____________________________^ @@ -49,7 +49,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ------------------------------------------------- in this macro invocation | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:41:28 + --> $DIR/collapsible_match2.rs:46:28 | LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ^^^ ^^^^^^^ with this pattern @@ -58,7 +58,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary nested match - --> $DIR/collapsible_match2.rs:46:20 + --> $DIR/collapsible_match2.rs:51:20 | LL | Some(s) => match *s { | ____________________^ @@ -68,7 +68,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:46:14 + --> $DIR/collapsible_match2.rs:51:14 | LL | Some(s) => match *s { | ^ replace this binding @@ -76,7 +76,7 @@ LL | [n] => foo(n), | ^^^ with this pattern error: unnecessary nested match - --> $DIR/collapsible_match2.rs:55:24 + --> $DIR/collapsible_match2.rs:60:24 | LL | Some(ref s) => match &*s { | ________________________^ @@ -86,7 +86,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> $DIR/collapsible_match2.rs:55:14 + --> $DIR/collapsible_match2.rs:60:14 | LL | Some(ref s) => match &*s { | ^^^^^ replace this binding diff --git a/src/tools/clippy/tests/ui/crashes/ice-5835.rs b/src/tools/clippy/tests/ui/crashes/ice-5835.rs new file mode 100644 index 0000000000..5e99cb432b --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-5835.rs @@ -0,0 +1,9 @@ +#[rustfmt::skip] +pub struct Foo { + /// 位 + /// ^ Do not remove this tab character. + /// It was required to trigger the ICE. + pub bar: u8, +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-5835.stderr b/src/tools/clippy/tests/ui/crashes/ice-5835.stderr new file mode 100644 index 0000000000..c972bcb60a --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-5835.stderr @@ -0,0 +1,10 @@ +error: using tabs in doc comments is not recommended + --> $DIR/ice-5835.rs:3:10 + | +LL | /// 位 + | ^^^^ help: consider using four spaces per tab + | + = note: `-D clippy::tabs-in-doc-comments` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr index 9a7cf4b091..8498c04078 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr @@ -16,8 +16,8 @@ LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> { = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn bug<T>() -> impl Iterator<Item = [(); { |&x: [u8]| x }]> { - | ^ +LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: &[u8]| x }]> { + | ^ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/ice-6251.rs:4:54 diff --git a/src/tools/clippy/tests/ui/crashes/ice-7012.rs b/src/tools/clippy/tests/ui/crashes/ice-7012.rs new file mode 100644 index 0000000000..60bdbc4f12 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7012.rs @@ -0,0 +1,17 @@ +#![allow(clippy::all)] + +enum _MyOption { + None, + Some(()), +} + +impl _MyOption { + fn _foo(&self) { + match self { + &Self::Some(_) => {}, + _ => {}, + } + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-7126.rs b/src/tools/clippy/tests/ui/crashes/ice-7126.rs new file mode 100644 index 0000000000..ca563ba097 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7126.rs @@ -0,0 +1,14 @@ +// This test requires a feature gated const fn and will stop working in the future. + +#![feature(const_btree_new)] + +use std::collections::BTreeMap; + +struct Foo(BTreeMap<i32, i32>); +impl Foo { + fn new() -> Self { + Self(BTreeMap::new()) + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-7169.rs b/src/tools/clippy/tests/ui/crashes/ice-7169.rs new file mode 100644 index 0000000000..82095febc1 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7169.rs @@ -0,0 +1,9 @@ +#[derive(Default)] +struct A<T> { + a: Vec<A<T>>, + b: T, +} + +fn main() { + if let Ok(_) = Ok::<_, ()>(A::<String>::default()) {} +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-7169.stderr b/src/tools/clippy/tests/ui/crashes/ice-7169.stderr new file mode 100644 index 0000000000..5a9cd32380 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7169.stderr @@ -0,0 +1,10 @@ +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/ice-7169.rs:8:12 + | +LL | if let Ok(_) = Ok::<_, ()>(A::<String>::default()) {} + | -------^^^^^-------------------------------------- help: try this: `if Ok::<_, ()>(A::<String>::default()).is_ok()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs index 995787c533..7ff5a16ed8 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,11 +1,11 @@ // ignore-macos // ignore-windows -#![feature(main)] +#![feature(rustc_attrs)] #[warn(clippy::main_recursion)] #[allow(unconditional_recursion)] -#[main] +#[rustc_main] fn a() { println!("Hello, World!"); a(); diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs index 25b1417be9..be4348e2bb 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -1,8 +1,8 @@ +// compile-flags: -Clink-arg=-nostartfiles // ignore-macos // ignore-windows -#![feature(lang_items, link_args, start, libc)] -#![link_args = "-nostartfiles"] +#![feature(lang_items, start, libc)] #![no_std] use core::panic::PanicInfo; diff --git a/src/tools/clippy/tests/ui/def_id_nocore.stderr b/src/tools/clippy/tests/ui/def_id_nocore.stderr index ed87a50547..702684f6b4 100644 --- a/src/tools/clippy/tests/ui/def_id_nocore.stderr +++ b/src/tools/clippy/tests/ui/def_id_nocore.stderr @@ -1,10 +1,11 @@ -error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name +error: methods called `as_*` usually take `self` by reference or `self` by mutable reference --> $DIR/def_id_nocore.rs:26:19 | LL | pub fn as_ref(self) -> &'static str { | ^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` + = help: consider choosing a less ambiguous name error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback.rs b/src/tools/clippy/tests/ui/default_numeric_fallback.rs index 0b3758952a..43468872db 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback.rs +++ b/src/tools/clippy/tests/ui/default_numeric_fallback.rs @@ -3,6 +3,7 @@ #![allow(clippy::never_loop)] #![allow(clippy::no_effect)] #![allow(clippy::unnecessary_operation)] +#![allow(clippy::branches_sharing_code)] mod basic_expr { fn test() { diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback.stderr index b31aa4ebcf..d1c4c8203d 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback.stderr +++ b/src/tools/clippy/tests/ui/default_numeric_fallback.stderr @@ -1,5 +1,5 @@ error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:10:17 + --> $DIR/default_numeric_fallback.rs:11:17 | LL | let x = 22; | ^^ help: consider adding suffix: `22_i32` @@ -7,139 +7,139 @@ LL | let x = 22; = note: `-D clippy::default-numeric-fallback` implied by `-D warnings` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:11:18 + --> $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:11:21 + --> $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:11:24 + --> $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:12:28 + --> $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:12:31 + --> $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:12:44 + --> $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:12:47 + --> $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:13:23 + --> $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:14:13 + --> $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:14:18 + --> $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:15:18 + --> $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:19:17 + --> $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:37:21 + --> $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:45:21 + --> $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:51:21 + --> $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:63:9 + --> $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:69:27 + --> $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:73:29 + --> $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:87:21 + --> $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:90:32 + --> $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:108:28 + --> $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:111:36 + --> $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:131:23 + --> $DIR/default_numeric_fallback.rs:132:23 | LL | s.generic_arg(1); | ^ help: consider adding suffix: `1_i32` diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs index fc444c0bea..dbf0b03af7 100644 --- a/src/tools/clippy/tests/ui/deprecated.rs +++ b/src/tools/clippy/tests/ui/deprecated.rs @@ -11,5 +11,6 @@ #[warn(clippy::panic_params)] #[warn(clippy::unknown_clippy_lints)] #[warn(clippy::find_map)] +#[warn(clippy::filter_map)] fn main() {} diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr index 64efcd18f8..3e125c1dab 100644 --- a/src/tools/clippy/tests/ui/deprecated.stderr +++ b/src/tools/clippy/tests/ui/deprecated.stderr @@ -24,23 +24,23 @@ error: lint `clippy::unused_collect` has been removed: `collect` has been marked LL | #[warn(clippy::unused_collect)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::invalid_ref` has been removed: superseded by rustc lint `invalid_value` +error: lint `clippy::invalid_ref` has been renamed to `invalid_value` --> $DIR/deprecated.rs:5:8 | LL | #[warn(clippy::invalid_ref)] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` -error: lint `clippy::into_iter_on_array` has been removed: this lint has been uplifted to rustc and is now called `array_into_iter` +error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` --> $DIR/deprecated.rs:6:8 | LL | #[warn(clippy::into_iter_on_array)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` -error: lint `clippy::unused_label` has been removed: this lint has been uplifted to rustc and is now called `unused_labels` +error: lint `clippy::unused_label` has been renamed to `unused_labels` --> $DIR/deprecated.rs:7:8 | LL | #[warn(clippy::unused_label)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018 --> $DIR/deprecated.rs:8:8 @@ -48,29 +48,29 @@ error: lint `clippy::regex_macro` has been removed: the regex! macro has been re LL | #[warn(clippy::regex_macro)] | ^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::drop_bounds` has been removed: this lint has been uplifted to rustc and is now called `drop_bounds` +error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` --> $DIR/deprecated.rs:9:8 | LL | #[warn(clippy::drop_bounds)] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` -error: lint `clippy::temporary_cstring_as_ptr` has been removed: this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr` +error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` --> $DIR/deprecated.rs:10:8 | LL | #[warn(clippy::temporary_cstring_as_ptr)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` -error: lint `clippy::panic_params` has been removed: this lint has been uplifted to rustc and is now called `panic_fmt` +error: lint `clippy::panic_params` has been renamed to `non_fmt_panic` --> $DIR/deprecated.rs:11:8 | LL | #[warn(clippy::panic_params)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panic` -error: lint `clippy::unknown_clippy_lints` has been removed: this lint has been integrated into the `unknown_lints` rustc lint +error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` --> $DIR/deprecated.rs:12:8 | LL | #[warn(clippy::unknown_clippy_lints)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::find_map` has been removed: this lint has been replaced by `manual_find_map`, a more specific lint --> $DIR/deprecated.rs:13:8 @@ -78,11 +78,17 @@ error: lint `clippy::find_map` has been removed: this lint has been replaced by LL | #[warn(clippy::find_map)] | ^^^^^^^^^^^^^^^^ +error: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint + --> $DIR/deprecated.rs:14:8 + | +LL | #[warn(clippy::filter_map)] + | ^^^^^^^^^^^^^^^^^^ + error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7 --> $DIR/deprecated.rs:1:8 | LL | #[warn(clippy::unstable_as_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/dereference.stderr b/src/tools/clippy/tests/ui/dereference.stderr deleted file mode 100644 index d26b462a43..0000000000 --- a/src/tools/clippy/tests/ui/dereference.stderr +++ /dev/null @@ -1,70 +0,0 @@ -error: explicit deref method call - --> $DIR/dereference.rs:30:19 - | -LL | let b: &str = a.deref(); - | ^^^^^^^^^ help: try this: `&*a` - | - = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` - -error: explicit deref_mut method call - --> $DIR/dereference.rs:32:23 - | -LL | let b: &mut str = a.deref_mut(); - | ^^^^^^^^^^^^^ help: try this: `&mut *a` - -error: explicit deref method call - --> $DIR/dereference.rs:35:39 - | -LL | let b: String = format!("{}, {}", a.deref(), a.deref()); - | ^^^^^^^^^ help: try this: `&*a` - -error: explicit deref method call - --> $DIR/dereference.rs:35:50 - | -LL | let b: String = format!("{}, {}", a.deref(), a.deref()); - | ^^^^^^^^^ help: try this: `&*a` - -error: explicit deref method call - --> $DIR/dereference.rs:37:20 - | -LL | println!("{}", a.deref()); - | ^^^^^^^^^ help: try this: `&*a` - -error: explicit deref method call - --> $DIR/dereference.rs:40:11 - | -LL | match a.deref() { - | ^^^^^^^^^ help: try this: `&*a` - -error: explicit deref method call - --> $DIR/dereference.rs:44:28 - | -LL | let b: String = concat(a.deref()); - | ^^^^^^^^^ help: try this: `&*a` - -error: explicit deref method call - --> $DIR/dereference.rs:46:13 - | -LL | let b = just_return(a).deref(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)` - -error: explicit deref method call - --> $DIR/dereference.rs:48:28 - | -LL | let b: String = concat(just_return(a).deref()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)` - -error: explicit deref method call - --> $DIR/dereference.rs:50:19 - | -LL | let b: &str = a.deref().deref(); - | ^^^^^^^^^^^^^^^^^ help: try this: `&*a.deref()` - -error: explicit deref method call - --> $DIR/dereference.rs:53:13 - | -LL | let b = opt_a.unwrap().deref(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` - -error: aborting due to 11 previous errors - diff --git a/src/tools/clippy/tests/ui/derive.rs b/src/tools/clippy/tests/ui/derive.rs index 8fcb0e8b28..4e46bf1399 100644 --- a/src/tools/clippy/tests/ui/derive.rs +++ b/src/tools/clippy/tests/ui/derive.rs @@ -35,7 +35,6 @@ impl<'a> Clone for Lt<'a> { } } -// Ok, `Clone` cannot be derived because of the big array #[derive(Copy)] struct BigArray { a: [u8; 65], @@ -47,7 +46,6 @@ impl Clone for BigArray { } } -// Ok, function pointers are not always Clone #[derive(Copy)] struct FnPtr { a: fn() -> !, @@ -59,7 +57,7 @@ impl Clone for FnPtr { } } -// Ok, generics +// Ok, Clone trait impl doesn't have constrained generics. #[derive(Copy)] struct Generic<T> { a: T, @@ -71,4 +69,21 @@ impl<T> Clone for Generic<T> { } } +#[derive(Copy)] +struct Generic2<T>(T); +impl<T: Clone> Clone for Generic2<T> { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +// Ok, Clone trait impl doesn't have constrained generics. +#[derive(Copy)] +struct GenericRef<'a, T, U>(T, &'a U); +impl<T: Clone, U> Clone for GenericRef<'_, T, U> { + fn clone(&self) -> Self { + Self(self.0.clone(), self.1) + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/derive.stderr b/src/tools/clippy/tests/ui/derive.stderr index 1328a9b310..82a70ceecc 100644 --- a/src/tools/clippy/tests/ui/derive.stderr +++ b/src/tools/clippy/tests/ui/derive.stderr @@ -40,7 +40,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:44:1 + --> $DIR/derive.rs:43:1 | LL | / impl Clone for BigArray { LL | | fn clone(&self) -> Self { @@ -50,7 +50,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:44:1 + --> $DIR/derive.rs:43:1 | LL | / impl Clone for BigArray { LL | | fn clone(&self) -> Self { @@ -60,7 +60,7 @@ LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> $DIR/derive.rs:56:1 + --> $DIR/derive.rs:54:1 | LL | / impl Clone for FnPtr { LL | | fn clone(&self) -> Self { @@ -70,7 +70,7 @@ LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> $DIR/derive.rs:56:1 + --> $DIR/derive.rs:54:1 | LL | / impl Clone for FnPtr { LL | | fn clone(&self) -> Self { @@ -79,5 +79,25 @@ LL | | } LL | | } | |_^ -error: aborting due to 4 previous errors +error: you are implementing `Clone` explicitly on a `Copy` type + --> $DIR/derive.rs:74:1 + | +LL | / impl<T: Clone> Clone for Generic2<T> { +LL | | fn clone(&self) -> Self { +LL | | Self(self.0.clone()) +LL | | } +LL | | } + | |_^ + | +note: consider deriving `Clone` or removing `Copy` + --> $DIR/derive.rs:74:1 + | +LL | / impl<T: Clone> Clone for Generic2<T> { +LL | | fn clone(&self) -> Self { +LL | | Self(self.0.clone()) +LL | | } +LL | | } + | |_^ + +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/doc.rs b/src/tools/clippy/tests/ui/doc.rs index d2c666bd29..c946a047f1 100644 --- a/src/tools/clippy/tests/ui/doc.rs +++ b/src/tools/clippy/tests/ui/doc.rs @@ -1,8 +1,8 @@ //! This file tests for the `DOC_MARKDOWN` lint. -#![allow(dead_code)] +#![allow(dead_code, incomplete_features)] #![warn(clippy::doc_markdown)] -#![feature(custom_inner_attributes)] +#![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) @@ -202,3 +202,20 @@ 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/empty_loop_no_std.rs b/src/tools/clippy/tests/ui/empty_loop_no_std.rs index 4553d3ec50..235e0fc517 100644 --- a/src/tools/clippy/tests/ui/empty_loop_no_std.rs +++ b/src/tools/clippy/tests/ui/empty_loop_no_std.rs @@ -1,9 +1,9 @@ +// compile-flags: -Clink-arg=-nostartfiles // ignore-macos // ignore-windows #![warn(clippy::empty_loop)] -#![feature(lang_items, link_args, start, libc)] -#![link_args = "-nostartfiles"] +#![feature(lang_items, start, libc)] #![no_std] use core::panic::PanicInfo; diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed new file mode 100644 index 0000000000..cfad3090ba --- /dev/null +++ b/src/tools/clippy/tests/ui/entry.fixed @@ -0,0 +1,155 @@ +// run-rustfix + +#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] +#![warn(clippy::map_entry)] +#![feature(asm)] + +use std::collections::{BTreeMap, HashMap}; +use std::hash::Hash; + +macro_rules! m { + ($e:expr) => {{ $e }}; +} + +macro_rules! insert { + ($map:expr, $key:expr, $val:expr) => { + $map.insert($key, $val) + }; +} + +fn foo() {} + +fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMap<K, V>, k: K, k2: K, v: V, v2: V) { + // or_insert(v) + m.entry(k).or_insert(v); + + // semicolon on insert, use or_insert_with(..) + m.entry(k).or_insert_with(|| { + if true { + v + } else { + v2 + } + }); + + // semicolon on if, use or_insert_with(..) + m.entry(k).or_insert_with(|| { + if true { + v + } else { + v2 + } + }); + + // early return, use if let + if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { + if true { + e.insert(v); + } else { + e.insert(v2); + return; + } + } + + // use or_insert_with(..) + m.entry(k).or_insert_with(|| { + foo(); + v + }); + + // semicolon on insert and match, use or_insert_with(..) + m.entry(k).or_insert_with(|| { + match 0 { + 1 if true => { + v + }, + _ => { + v2 + }, + } + }); + + // one branch doesn't insert, use if let + if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { + match 0 { + 0 => foo(), + _ => { + e.insert(v2); + }, + }; + } + + // use or_insert_with + m.entry(k).or_insert_with(|| { + foo(); + match 0 { + 0 if false => { + v + }, + 1 => { + foo(); + v + }, + 2 | 3 => { + for _ in 0..2 { + foo(); + } + if true { + v + } else { + v2 + } + }, + _ => { + v2 + }, + } + }); + + // ok, insert in loop + if !m.contains_key(&k) { + for _ in 0..2 { + m.insert(k, v); + } + } + + // macro_expansion test, use or_insert(..) + m.entry(m!(k)).or_insert_with(|| m!(v)); + + // ok, map used before insertion + if !m.contains_key(&k) { + let _ = m.len(); + m.insert(k, v); + } + + // ok, inline asm + if !m.contains_key(&k) { + unsafe { asm!("nop") } + m.insert(k, v); + } + + // ok, different keys. + if !m.contains_key(&k) { + m.insert(k2, v); + } + + // ok, different maps + if !m.contains_key(&k) { + m2.insert(k, v); + } + + // ok, insert in macro + if !m.contains_key(&k) { + insert!(m, k, v); + } +} + +fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V, v2: V) { + // insert then do something, use if let + if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) { + e.insert(v); + foo(); + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs new file mode 100644 index 0000000000..fa9280b58d --- /dev/null +++ b/src/tools/clippy/tests/ui/entry.rs @@ -0,0 +1,159 @@ +// run-rustfix + +#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] +#![warn(clippy::map_entry)] +#![feature(asm)] + +use std::collections::{BTreeMap, HashMap}; +use std::hash::Hash; + +macro_rules! m { + ($e:expr) => {{ $e }}; +} + +macro_rules! insert { + ($map:expr, $key:expr, $val:expr) => { + $map.insert($key, $val) + }; +} + +fn foo() {} + +fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMap<K, V>, k: K, k2: K, v: V, v2: V) { + // or_insert(v) + if !m.contains_key(&k) { + m.insert(k, v); + } + + // semicolon on insert, use or_insert_with(..) + if !m.contains_key(&k) { + if true { + m.insert(k, v); + } else { + m.insert(k, v2); + } + } + + // semicolon on if, use or_insert_with(..) + if !m.contains_key(&k) { + if true { + m.insert(k, v) + } else { + m.insert(k, v2) + }; + } + + // early return, use if let + if !m.contains_key(&k) { + if true { + m.insert(k, v); + } else { + m.insert(k, v2); + return; + } + } + + // use or_insert_with(..) + if !m.contains_key(&k) { + foo(); + m.insert(k, v); + } + + // semicolon on insert and match, use or_insert_with(..) + if !m.contains_key(&k) { + match 0 { + 1 if true => { + m.insert(k, v); + }, + _ => { + m.insert(k, v2); + }, + }; + } + + // one branch doesn't insert, use if let + if !m.contains_key(&k) { + match 0 { + 0 => foo(), + _ => { + m.insert(k, v2); + }, + }; + } + + // use or_insert_with + if !m.contains_key(&k) { + foo(); + match 0 { + 0 if false => { + m.insert(k, v); + }, + 1 => { + foo(); + m.insert(k, v); + }, + 2 | 3 => { + for _ in 0..2 { + foo(); + } + if true { + m.insert(k, v); + } else { + m.insert(k, v2); + }; + }, + _ => { + m.insert(k, v2); + }, + } + } + + // ok, insert in loop + if !m.contains_key(&k) { + for _ in 0..2 { + m.insert(k, v); + } + } + + // macro_expansion test, use or_insert(..) + if !m.contains_key(&m!(k)) { + m.insert(m!(k), m!(v)); + } + + // ok, map used before insertion + if !m.contains_key(&k) { + let _ = m.len(); + m.insert(k, v); + } + + // ok, inline asm + if !m.contains_key(&k) { + unsafe { asm!("nop") } + m.insert(k, v); + } + + // ok, different keys. + if !m.contains_key(&k) { + m.insert(k2, v); + } + + // ok, different maps + if !m.contains_key(&k) { + m2.insert(k, v); + } + + // ok, insert in macro + if !m.contains_key(&k) { + insert!(m, k, v); + } +} + +fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V, v2: V) { + // insert then do something, use if let + if !m.contains_key(&k) { + m.insert(k, v); + foo(); + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/entry.stderr b/src/tools/clippy/tests/ui/entry.stderr new file mode 100644 index 0000000000..2f075a9701 --- /dev/null +++ b/src/tools/clippy/tests/ui/entry.stderr @@ -0,0 +1,186 @@ +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:24:5 + | +LL | / if !m.contains_key(&k) { +LL | | m.insert(k, v); +LL | | } + | |_____^ help: try this: `m.entry(k).or_insert(v);` + | + = note: `-D clippy::map-entry` implied by `-D warnings` + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:29:5 + | +LL | / if !m.contains_key(&k) { +LL | | if true { +LL | | m.insert(k, v); +LL | | } else { +LL | | m.insert(k, v2); +LL | | } +LL | | } + | |_____^ + | +help: try this + | +LL | m.entry(k).or_insert_with(|| { +LL | if true { +LL | v +LL | } else { +LL | v2 +LL | } + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:38:5 + | +LL | / if !m.contains_key(&k) { +LL | | if true { +LL | | m.insert(k, v) +LL | | } else { +LL | | m.insert(k, v2) +LL | | }; +LL | | } + | |_____^ + | +help: try this + | +LL | m.entry(k).or_insert_with(|| { +LL | if true { +LL | v +LL | } else { +LL | v2 +LL | } + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:47:5 + | +LL | / if !m.contains_key(&k) { +LL | | if true { +LL | | m.insert(k, v); +LL | | } else { +... | +LL | | } +LL | | } + | |_____^ + | +help: try this + | +LL | if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { +LL | if true { +LL | e.insert(v); +LL | } else { +LL | e.insert(v2); +LL | return; + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:57:5 + | +LL | / if !m.contains_key(&k) { +LL | | foo(); +LL | | m.insert(k, v); +LL | | } + | |_____^ + | +help: try this + | +LL | m.entry(k).or_insert_with(|| { +LL | foo(); +LL | v +LL | }); + | + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:63:5 + | +LL | / if !m.contains_key(&k) { +LL | | match 0 { +LL | | 1 if true => { +LL | | m.insert(k, v); +... | +LL | | }; +LL | | } + | |_____^ + | +help: try this + | +LL | m.entry(k).or_insert_with(|| { +LL | match 0 { +LL | 1 if true => { +LL | v +LL | }, +LL | _ => { + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:75:5 + | +LL | / if !m.contains_key(&k) { +LL | | match 0 { +LL | | 0 => foo(), +LL | | _ => { +... | +LL | | }; +LL | | } + | |_____^ + | +help: try this + | +LL | if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { +LL | match 0 { +LL | 0 => foo(), +LL | _ => { +LL | e.insert(v2); +LL | }, + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:85:5 + | +LL | / if !m.contains_key(&k) { +LL | | foo(); +LL | | match 0 { +LL | | 0 if false => { +... | +LL | | } +LL | | } + | |_____^ + | +help: try this + | +LL | m.entry(k).or_insert_with(|| { +LL | foo(); +LL | match 0 { +LL | 0 if false => { +LL | v +LL | }, + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry.rs:119:5 + | +LL | / if !m.contains_key(&m!(k)) { +LL | | m.insert(m!(k), m!(v)); +LL | | } + | |_____^ help: try this: `m.entry(m!(k)).or_insert_with(|| m!(v));` + +error: usage of `contains_key` followed by `insert` on a `BTreeMap` + --> $DIR/entry.rs:153:5 + | +LL | / if !m.contains_key(&k) { +LL | | m.insert(k, v); +LL | | foo(); +LL | | } + | |_____^ + | +help: try this + | +LL | if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) { +LL | e.insert(v); +LL | foo(); +LL | } + | + +error: aborting due to 10 previous errors + diff --git a/src/tools/clippy/tests/ui/entry_fixable.fixed b/src/tools/clippy/tests/ui/entry_fixable.fixed deleted file mode 100644 index dcdaae7e72..0000000000 --- a/src/tools/clippy/tests/ui/entry_fixable.fixed +++ /dev/null @@ -1,15 +0,0 @@ -// run-rustfix - -#![allow(unused, clippy::needless_pass_by_value)] -#![warn(clippy::map_entry)] - -use std::collections::{BTreeMap, HashMap}; -use std::hash::Hash; - -fn foo() {} - -fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - m.entry(k).or_insert(v); -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/entry_fixable.rs b/src/tools/clippy/tests/ui/entry_fixable.rs deleted file mode 100644 index 55d5b21568..0000000000 --- a/src/tools/clippy/tests/ui/entry_fixable.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-rustfix - -#![allow(unused, clippy::needless_pass_by_value)] -#![warn(clippy::map_entry)] - -use std::collections::{BTreeMap, HashMap}; -use std::hash::Hash; - -fn foo() {} - -fn insert_if_absent0<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { - m.insert(k, v); - } -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/entry_fixable.stderr b/src/tools/clippy/tests/ui/entry_fixable.stderr deleted file mode 100644 index 87403200ce..0000000000 --- a/src/tools/clippy/tests/ui/entry_fixable.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry_fixable.rs:12:5 - | -LL | / if !m.contains_key(&k) { -LL | | m.insert(k, v); -LL | | } - | |_____^ help: consider using: `m.entry(k).or_insert(v);` - | - = note: `-D clippy::map-entry` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/src/tools/clippy/tests/ui/entry_unfixable.rs b/src/tools/clippy/tests/ui/entry_unfixable.rs deleted file mode 100644 index f530fc023c..0000000000 --- a/src/tools/clippy/tests/ui/entry_unfixable.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![allow(unused, clippy::needless_pass_by_value)] -#![warn(clippy::map_entry)] - -use std::collections::{BTreeMap, HashMap}; -use std::hash::Hash; - -fn foo() {} - -fn insert_if_absent2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { - m.insert(k, v) - } else { - None - }; -} - -fn insert_if_present2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if m.contains_key(&k) { - None - } else { - m.insert(k, v) - }; -} - -fn insert_if_absent3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { - foo(); - m.insert(k, v) - } else { - None - }; -} - -fn insert_if_present3<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, v: V) { - if m.contains_key(&k) { - None - } else { - foo(); - m.insert(k, v) - }; -} - -fn insert_in_btreemap<K: Ord, V>(m: &mut BTreeMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { - foo(); - m.insert(k, v) - } else { - None - }; -} - -// should not trigger -fn insert_other_if_absent<K: Eq + Hash, V>(m: &mut HashMap<K, V>, k: K, o: K, v: V) { - if !m.contains_key(&k) { - m.insert(o, v); - } -} - -// should not trigger, because the one uses different HashMap from another one -fn insert_from_different_map<K: Eq + Hash, V>(m: HashMap<K, V>, n: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { - n.insert(k, v); - } -} - -// should not trigger, because the one uses different HashMap from another one -fn insert_from_different_map2<K: Eq + Hash, V>(m: &mut HashMap<K, V>, n: &mut HashMap<K, V>, k: K, v: V) { - if !m.contains_key(&k) { - n.insert(k, v); - } -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/entry_unfixable.stderr b/src/tools/clippy/tests/ui/entry_unfixable.stderr deleted file mode 100644 index e58c8d22dc..0000000000 --- a/src/tools/clippy/tests/ui/entry_unfixable.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry_unfixable.rs:10:5 - | -LL | / if !m.contains_key(&k) { -LL | | m.insert(k, v) -LL | | } else { -LL | | None -LL | | }; - | |_____^ consider using `m.entry(k)` - | - = note: `-D clippy::map-entry` implied by `-D warnings` - -error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry_unfixable.rs:18:5 - | -LL | / if m.contains_key(&k) { -LL | | None -LL | | } else { -LL | | m.insert(k, v) -LL | | }; - | |_____^ consider using `m.entry(k)` - -error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry_unfixable.rs:26:5 - | -LL | / if !m.contains_key(&k) { -LL | | foo(); -LL | | m.insert(k, v) -LL | | } else { -LL | | None -LL | | }; - | |_____^ consider using `m.entry(k)` - -error: usage of `contains_key` followed by `insert` on a `HashMap` - --> $DIR/entry_unfixable.rs:35:5 - | -LL | / if m.contains_key(&k) { -LL | | None -LL | | } else { -LL | | foo(); -LL | | m.insert(k, v) -LL | | }; - | |_____^ consider using `m.entry(k)` - -error: usage of `contains_key` followed by `insert` on a `BTreeMap` - --> $DIR/entry_unfixable.rs:44:5 - | -LL | / if !m.contains_key(&k) { -LL | | foo(); -LL | | m.insert(k, v) -LL | | } else { -LL | | None -LL | | }; - | |_____^ consider using `m.entry(k)` - -error: aborting due to 5 previous errors - diff --git a/src/tools/clippy/tests/ui/entry_with_else.fixed b/src/tools/clippy/tests/ui/entry_with_else.fixed new file mode 100644 index 0000000000..2332fa6313 --- /dev/null +++ b/src/tools/clippy/tests/ui/entry_with_else.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] +#![warn(clippy::map_entry)] + +use std::collections::{BTreeMap, HashMap}; +use std::hash::Hash; + +macro_rules! m { + ($e:expr) => {{ $e }}; +} + +fn foo() {} + +fn insert_if_absent0<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, k: K, v: V, v2: V) { + match m.entry(k) { + std::collections::hash_map::Entry::Vacant(e) => { + e.insert(v); + } + std::collections::hash_map::Entry::Occupied(mut e) => { + e.insert(v2); + } + } + + match m.entry(k) { + std::collections::hash_map::Entry::Occupied(mut e) => { + e.insert(v); + } + std::collections::hash_map::Entry::Vacant(e) => { + e.insert(v2); + } + } + + if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { + e.insert(v); + } else { + foo(); + } + + if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { + e.insert(v); + } else { + foo(); + } + + match m.entry(k) { + std::collections::hash_map::Entry::Vacant(e) => { + e.insert(v); + } + std::collections::hash_map::Entry::Occupied(mut e) => { + e.insert(v2); + } + } + + match m.entry(k) { + std::collections::hash_map::Entry::Occupied(mut e) => { + if true { Some(e.insert(v)) } else { Some(e.insert(v2)) } + } + std::collections::hash_map::Entry::Vacant(e) => { + e.insert(v); + None + } + }; + + if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { + foo(); + Some(e.insert(v)) + } else { + None + }; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/entry_with_else.rs b/src/tools/clippy/tests/ui/entry_with_else.rs new file mode 100644 index 0000000000..2ff0c038ef --- /dev/null +++ b/src/tools/clippy/tests/ui/entry_with_else.rs @@ -0,0 +1,60 @@ +// run-rustfix + +#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] +#![warn(clippy::map_entry)] + +use std::collections::{BTreeMap, HashMap}; +use std::hash::Hash; + +macro_rules! m { + ($e:expr) => {{ $e }}; +} + +fn foo() {} + +fn insert_if_absent0<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, k: K, v: V, v2: V) { + if !m.contains_key(&k) { + m.insert(k, v); + } else { + m.insert(k, v2); + } + + if m.contains_key(&k) { + m.insert(k, v); + } else { + m.insert(k, v2); + } + + if !m.contains_key(&k) { + m.insert(k, v); + } else { + foo(); + } + + if !m.contains_key(&k) { + foo(); + } else { + m.insert(k, v); + } + + if !m.contains_key(&k) { + m.insert(k, v); + } else { + m.insert(k, v2); + } + + if m.contains_key(&k) { + if true { m.insert(k, v) } else { m.insert(k, v2) } + } else { + m.insert(k, v) + }; + + if m.contains_key(&k) { + foo(); + m.insert(k, v) + } else { + None + }; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/entry_with_else.stderr b/src/tools/clippy/tests/ui/entry_with_else.stderr new file mode 100644 index 0000000000..6f62ff8d37 --- /dev/null +++ b/src/tools/clippy/tests/ui/entry_with_else.stderr @@ -0,0 +1,142 @@ +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry_with_else.rs:16:5 + | +LL | / if !m.contains_key(&k) { +LL | | m.insert(k, v); +LL | | } else { +LL | | m.insert(k, v2); +LL | | } + | |_____^ + | + = note: `-D clippy::map-entry` implied by `-D warnings` +help: try this + | +LL | match m.entry(k) { +LL | std::collections::hash_map::Entry::Vacant(e) => { +LL | e.insert(v); +LL | } +LL | std::collections::hash_map::Entry::Occupied(mut e) => { +LL | e.insert(v2); + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry_with_else.rs:22:5 + | +LL | / if m.contains_key(&k) { +LL | | m.insert(k, v); +LL | | } else { +LL | | m.insert(k, v2); +LL | | } + | |_____^ + | +help: try this + | +LL | match m.entry(k) { +LL | std::collections::hash_map::Entry::Occupied(mut e) => { +LL | e.insert(v); +LL | } +LL | std::collections::hash_map::Entry::Vacant(e) => { +LL | e.insert(v2); + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry_with_else.rs:28:5 + | +LL | / if !m.contains_key(&k) { +LL | | m.insert(k, v); +LL | | } else { +LL | | foo(); +LL | | } + | |_____^ + | +help: try this + | +LL | if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { +LL | e.insert(v); +LL | } else { +LL | foo(); +LL | } + | + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry_with_else.rs:34:5 + | +LL | / if !m.contains_key(&k) { +LL | | foo(); +LL | | } else { +LL | | m.insert(k, v); +LL | | } + | |_____^ + | +help: try this + | +LL | if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { +LL | e.insert(v); +LL | } else { +LL | foo(); +LL | } + | + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry_with_else.rs:40:5 + | +LL | / if !m.contains_key(&k) { +LL | | m.insert(k, v); +LL | | } else { +LL | | m.insert(k, v2); +LL | | } + | |_____^ + | +help: try this + | +LL | match m.entry(k) { +LL | std::collections::hash_map::Entry::Vacant(e) => { +LL | e.insert(v); +LL | } +LL | std::collections::hash_map::Entry::Occupied(mut e) => { +LL | e.insert(v2); + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry_with_else.rs:46:5 + | +LL | / if m.contains_key(&k) { +LL | | if true { m.insert(k, v) } else { m.insert(k, v2) } +LL | | } else { +LL | | m.insert(k, v) +LL | | }; + | |_____^ + | +help: try this + | +LL | match m.entry(k) { +LL | std::collections::hash_map::Entry::Occupied(mut e) => { +LL | if true { Some(e.insert(v)) } else { Some(e.insert(v2)) } +LL | } +LL | std::collections::hash_map::Entry::Vacant(e) => { +LL | e.insert(v); + ... + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> $DIR/entry_with_else.rs:52:5 + | +LL | / if m.contains_key(&k) { +LL | | foo(); +LL | | m.insert(k, v) +LL | | } else { +LL | | None +LL | | }; + | |_____^ + | +help: try this + | +LL | if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { +LL | foo(); +LL | Some(e.insert(v)) +LL | } else { +LL | None +LL | }; + | + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/escape_analysis.rs b/src/tools/clippy/tests/ui/escape_analysis.rs index d26f48fc68..13e2b6c7a2 100644 --- a/src/tools/clippy/tests/ui/escape_analysis.rs +++ b/src/tools/clippy/tests/ui/escape_analysis.rs @@ -101,7 +101,7 @@ fn warn_match() { let x = box A; match &x { // not moved - ref y => (), + y => (), } } @@ -111,7 +111,7 @@ fn nowarn_large_array() { let x = box [1; 10000]; match &x { // not moved - ref y => (), + y => (), } } diff --git a/src/tools/clippy/tests/ui/dereference.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed similarity index 91% rename from src/tools/clippy/tests/ui/dereference.fixed rename to src/tools/clippy/tests/ui/explicit_deref_methods.fixed index 459ca91b93..51d0468e47 100644 --- a/src/tools/clippy/tests/ui/dereference.fixed +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed @@ -29,7 +29,7 @@ fn main() { let b: &str = &*a; - let b: &mut str = &mut *a; + let b: &mut str = &mut **a; // both derefs should get linted here let b: String = format!("{}, {}", &*a, &*a); @@ -43,11 +43,11 @@ fn main() { let b: String = concat(&*a); - let b = &*just_return(a); + let b = just_return(a); - let b: String = concat(&*just_return(a)); + let b: String = concat(just_return(a)); - let b: &str = &*a.deref(); + let b: &str = &**a; let opt_a = Some(a.clone()); let b = &*opt_a.unwrap(); @@ -76,6 +76,8 @@ fn main() { } let b: &str = expr_deref!(a); + let b: &str = expr_deref!(&*a); + // The struct does not implement Deref trait #[derive(Copy, Clone)] struct NoLint(u32); diff --git a/src/tools/clippy/tests/ui/dereference.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs similarity index 97% rename from src/tools/clippy/tests/ui/dereference.rs rename to src/tools/clippy/tests/ui/explicit_deref_methods.rs index 8dc5272e67..680664bd4f 100644 --- a/src/tools/clippy/tests/ui/dereference.rs +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs @@ -76,6 +76,8 @@ fn main() { } let b: &str = expr_deref!(a); + let b: &str = expr_deref!(a.deref()); + // The struct does not implement Deref trait #[derive(Copy, Clone)] struct NoLint(u32); diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr new file mode 100644 index 0000000000..8035d77d18 --- /dev/null +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr @@ -0,0 +1,76 @@ +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:30:19 + | +LL | let b: &str = a.deref(); + | ^^^^^^^^^ help: try this: `&*a` + | + = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` + +error: explicit `deref_mut` method call + --> $DIR/explicit_deref_methods.rs:32:23 + | +LL | let b: &mut str = a.deref_mut(); + | ^^^^^^^^^^^^^ help: try this: `&mut **a` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:35:39 + | +LL | let b: String = format!("{}, {}", a.deref(), a.deref()); + | ^^^^^^^^^ help: try this: `&*a` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:35:50 + | +LL | let b: String = format!("{}, {}", a.deref(), a.deref()); + | ^^^^^^^^^ help: try this: `&*a` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:37:20 + | +LL | println!("{}", a.deref()); + | ^^^^^^^^^ help: try this: `&*a` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:40:11 + | +LL | match a.deref() { + | ^^^^^^^^^ help: try this: `&*a` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:44:28 + | +LL | let b: String = concat(a.deref()); + | ^^^^^^^^^ help: try this: `&*a` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:46:13 + | +LL | let b = just_return(a).deref(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:48:28 + | +LL | let b: String = concat(just_return(a).deref()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:50:19 + | +LL | let b: &str = a.deref().deref(); + | ^^^^^^^^^^^^^^^^^ help: try this: `&**a` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:53:13 + | +LL | let b = opt_a.unwrap().deref(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:79:31 + | +LL | let b: &str = expr_deref!(a.deref()); + | ^^^^^^^^^ help: try this: `&*a` + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs index 9fc208f533..1368c5d798 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs @@ -136,6 +136,13 @@ fn main() { // Don't lint in external macros field_reassign_with_default!(); + + // be sure suggestion is correct with generics + let mut a: Wrapper<bool> = Default::default(); + a.i = true; + + let mut a: WrapperMulti<i32, i64> = Default::default(); + a.i = 42; } mod m { @@ -145,3 +152,14 @@ mod m { b: u64, } } + +#[derive(Default)] +struct Wrapper<T> { + i: T, +} + +#[derive(Default)] +struct WrapperMulti<T, U> { + i: T, + j: U, +} diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr index 2f0f28f7bb..dd7c0360bb 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr @@ -83,5 +83,29 @@ note: consider initializing the variable with `C { i: vec![1], ..Default::defaul LL | let mut a: C = C::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: field assignment outside of initializer for an instance created with Default::default() + --> $DIR/field_reassign_with_default.rs:142: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 + | +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 + | +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 + | +LL | let mut a: WrapperMulti<i32, i64> = Default::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/filter_methods.rs b/src/tools/clippy/tests/ui/filter_methods.rs deleted file mode 100644 index 5145024161..0000000000 --- a/src/tools/clippy/tests/ui/filter_methods.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![warn(clippy::all, clippy::pedantic)] -#![allow(clippy::clippy::let_underscore_drop)] -#![allow(clippy::missing_docs_in_private_items)] - -fn main() { - let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect(); - - let _: Vec<_> = vec![5_i8; 6] - .into_iter() - .filter(|&x| x == 0) - .flat_map(|x| x.checked_mul(2)) - .collect(); - - let _: Vec<_> = vec![5_i8; 6] - .into_iter() - .filter_map(|x| x.checked_mul(2)) - .flat_map(|x| x.checked_mul(2)) - .collect(); - - let _: Vec<_> = vec![5_i8; 6] - .into_iter() - .filter_map(|x| x.checked_mul(2)) - .map(|x| x.checked_mul(2)) - .collect(); -} diff --git a/src/tools/clippy/tests/ui/filter_methods.stderr b/src/tools/clippy/tests/ui/filter_methods.stderr deleted file mode 100644 index c7b4f28be3..0000000000 --- a/src/tools/clippy/tests/ui/filter_methods.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error: called `filter(..).flat_map(..)` on an `Iterator` - --> $DIR/filter_methods.rs:8:21 - | -LL | let _: Vec<_> = vec![5_i8; 6] - | _____________________^ -LL | | .into_iter() -LL | | .filter(|&x| x == 0) -LL | | .flat_map(|x| x.checked_mul(2)) - | |_______________________________________^ - | - = note: `-D clippy::filter-map` implied by `-D warnings` - = help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()` - -error: called `filter_map(..).flat_map(..)` on an `Iterator` - --> $DIR/filter_methods.rs:14:21 - | -LL | let _: Vec<_> = vec![5_i8; 6] - | _____________________^ -LL | | .into_iter() -LL | | .filter_map(|x| x.checked_mul(2)) -LL | | .flat_map(|x| x.checked_mul(2)) - | |_______________________________________^ - | - = help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()` - -error: called `filter_map(..).map(..)` on an `Iterator` - --> $DIR/filter_methods.rs:20:21 - | -LL | let _: Vec<_> = vec![5_i8; 6] - | _____________________^ -LL | | .into_iter() -LL | | .filter_map(|x| x.checked_mul(2)) -LL | | .map(|x| x.checked_mul(2)) - | |__________________________________^ - | - = help: this is more succinctly expressed by only calling `.filter_map(..)` instead - -error: aborting due to 3 previous errors - diff --git a/src/tools/clippy/tests/ui/flat_map_option.fixed b/src/tools/clippy/tests/ui/flat_map_option.fixed new file mode 100644 index 0000000000..6a34f00899 --- /dev/null +++ b/src/tools/clippy/tests/ui/flat_map_option.fixed @@ -0,0 +1,13 @@ +// run-rustfix +#![warn(clippy::flat_map_option)] +#![allow(clippy::redundant_closure, clippy::unnecessary_filter_map)] + +fn main() { + // yay + let c = |x| Some(x); + let _ = [1].iter().filter_map(c); + let _ = [1].iter().filter_map(Some); + + // nay + let _ = [1].iter().flat_map(|_| &Some(1)); +} diff --git a/src/tools/clippy/tests/ui/flat_map_option.rs b/src/tools/clippy/tests/ui/flat_map_option.rs new file mode 100644 index 0000000000..2479abddbf --- /dev/null +++ b/src/tools/clippy/tests/ui/flat_map_option.rs @@ -0,0 +1,13 @@ +// run-rustfix +#![warn(clippy::flat_map_option)] +#![allow(clippy::redundant_closure, clippy::unnecessary_filter_map)] + +fn main() { + // yay + let c = |x| Some(x); + let _ = [1].iter().flat_map(c); + let _ = [1].iter().flat_map(Some); + + // nay + let _ = [1].iter().flat_map(|_| &Some(1)); +} diff --git a/src/tools/clippy/tests/ui/flat_map_option.stderr b/src/tools/clippy/tests/ui/flat_map_option.stderr new file mode 100644 index 0000000000..a9d8056dee --- /dev/null +++ b/src/tools/clippy/tests/ui/flat_map_option.stderr @@ -0,0 +1,16 @@ +error: used `flat_map` where `filter_map` could be used instead + --> $DIR/flat_map_option.rs:8:24 + | +LL | let _ = [1].iter().flat_map(c); + | ^^^^^^^^ help: try: `filter_map` + | + = note: `-D clippy::flat-map-option` implied by `-D warnings` + +error: used `flat_map` where `filter_map` could be used instead + --> $DIR/flat_map_option.rs:9:24 + | +LL | let _ = [1].iter().flat_map(Some); + | ^^^^^^^^ help: try: `filter_map` + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/floating_point_log.fixed b/src/tools/clippy/tests/ui/floating_point_log.fixed index 7dc7ee94af..5b487bb8fc 100644 --- a/src/tools/clippy/tests/ui/floating_point_log.fixed +++ b/src/tools/clippy/tests/ui/floating_point_log.fixed @@ -27,7 +27,7 @@ fn check_ln1p() { let _ = (x / 2.0).ln_1p(); let _ = x.powi(3).ln_1p(); let _ = (x.powi(3) / 2.0).ln_1p(); - let _ = ((std::f32::consts::E - 1.0)).ln_1p(); + let _ = (std::f32::consts::E - 1.0).ln_1p(); let _ = x.ln_1p(); let _ = x.powi(3).ln_1p(); let _ = (x + 2.0).ln_1p(); diff --git a/src/tools/clippy/tests/ui/floating_point_log.stderr b/src/tools/clippy/tests/ui/floating_point_log.stderr index 900dc2b793..96e5a15444 100644 --- a/src/tools/clippy/tests/ui/floating_point_log.stderr +++ b/src/tools/clippy/tests/ui/floating_point_log.stderr @@ -90,7 +90,7 @@ error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:30:13 | LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(std::f32::consts::E - 1.0).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:31:13 diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.fixed b/src/tools/clippy/tests/ui/for_loop_fixable.fixed index 249a88a0b3..f44928d408 100644 --- a/src/tools/clippy/tests/ui/for_loop_fixable.fixed +++ b/src/tools/clippy/tests/ui/for_loop_fixable.fixed @@ -281,3 +281,29 @@ mod issue_4958 { for _ in rr.into_iter() {} } } + +// explicit_into_iter_loop +#[warn(clippy::explicit_into_iter_loop)] +mod issue_6900 { + struct S; + impl S { + #[allow(clippy::should_implement_trait)] + pub fn into_iter<T>(self) -> I<T> { + unimplemented!() + } + } + + struct I<T>(T); + impl<T> Iterator for I<T> { + type Item = T; + fn next(&mut self) -> Option<Self::Item> { + unimplemented!() + } + } + + fn f() { + for _ in S.into_iter::<u32>() { + unimplemented!() + } + } +} diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.rs b/src/tools/clippy/tests/ui/for_loop_fixable.rs index 306d85a635..5b1eb3ee4d 100644 --- a/src/tools/clippy/tests/ui/for_loop_fixable.rs +++ b/src/tools/clippy/tests/ui/for_loop_fixable.rs @@ -281,3 +281,29 @@ mod issue_4958 { for _ in rr.into_iter() {} } } + +// explicit_into_iter_loop +#[warn(clippy::explicit_into_iter_loop)] +mod issue_6900 { + struct S; + impl S { + #[allow(clippy::should_implement_trait)] + pub fn into_iter<T>(self) -> I<T> { + unimplemented!() + } + } + + struct I<T>(T); + impl<T> Iterator for I<T> { + type Item = T; + fn next(&mut self) -> Option<Self::Item> { + unimplemented!() + } + } + + fn f() { + for _ in S.into_iter::<u32>() { + unimplemented!() + } + } +} diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed index 740a22a07d..e4cfb005fd 100644 --- a/src/tools/clippy/tests/ui/format.fixed +++ b/src/tools/clippy/tests/ui/format.fixed @@ -65,4 +65,8 @@ fn main() { // False positive let a = "foo".to_string(); let _ = Some(a + "bar"); + + // Wrap it with braces + let v: Vec<String> = vec!["foo".to_string(), "bar".to_string()]; + let _s: String = (&*v.join("\n")).to_string(); } diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs index b604d79cca..683957f0ff 100644 --- a/src/tools/clippy/tests/ui/format.rs +++ b/src/tools/clippy/tests/ui/format.rs @@ -67,4 +67,8 @@ fn main() { // False positive let a = "foo".to_string(); let _ = Some(format!("{}", a + "bar")); + + // Wrap it with braces + let v: Vec<String> = vec!["foo".to_string(), "bar".to_string()]; + let _s: String = format!("{}", &*v.join("\n")); } diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr index 96df7f37f7..2017eb2b38 100644 --- a/src/tools/clippy/tests/ui/format.stderr +++ b/src/tools/clippy/tests/ui/format.stderr @@ -87,5 +87,11 @@ error: useless use of `format!` LL | let _ = Some(format!("{}", a + "bar")); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"` -error: aborting due to 13 previous errors +error: useless use of `format!` + --> $DIR/format.rs:73:22 + | +LL | let _s: String = format!("{}", &*v.join("/n")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()` + +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr index b101d2704f..2951e6bdac 100644 --- a/src/tools/clippy/tests/ui/from_over_into.stderr +++ b/src/tools/clippy/tests/ui/from_over_into.stderr @@ -5,7 +5,7 @@ LL | impl Into<StringWrapper> for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::from-over-into` implied by `-D warnings` - = help: consider to implement `From` instead + = help: consider to implement `From<std::string::String>` instead error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/from_str_radix_10.stderr b/src/tools/clippy/tests/ui/from_str_radix_10.stderr index 471bf52a9a..da5c16f8d0 100644 --- a/src/tools/clippy/tests/ui/from_str_radix_10.stderr +++ b/src/tools/clippy/tests/ui/from_str_radix_10.stderr @@ -28,7 +28,7 @@ error: this call to `from_str_radix` can be replaced with a call to `str::parse` --> $DIR/from_str_radix_10.rs:32:5 | LL | u16::from_str_radix(&("10".to_owned() + "5"), 10)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(("10".to_owned() + "5")).parse::<u16>()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `("10".to_owned() + "5").parse::<u16>()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` --> $DIR/from_str_radix_10.rs:33:5 diff --git a/src/tools/clippy/tests/ui/if_same_then_else.rs b/src/tools/clippy/tests/ui/if_same_then_else.rs index 9c5fe02f75..ef95674550 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else.rs +++ b/src/tools/clippy/tests/ui/if_same_then_else.rs @@ -5,7 +5,8 @@ clippy::never_loop, clippy::no_effect, clippy::unused_unit, - clippy::zero_divided_by_zero + clippy::zero_divided_by_zero, + clippy::branches_sharing_code )] struct Foo { diff --git a/src/tools/clippy/tests/ui/if_same_then_else.stderr b/src/tools/clippy/tests/ui/if_same_then_else.stderr index d9fdf06fa8..2f38052fc2 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else.stderr +++ b/src/tools/clippy/tests/ui/if_same_then_else.stderr @@ -1,111 +1,111 @@ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:28:12 + --> $DIR/if_same_then_else.rs:21:13 | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block +LL | if true { + | _____________^ LL | | Foo { bar: 42 }; LL | | 0..10; +LL | | ..; ... | LL | | foo(); -LL | | } +LL | | } else { | |_____^ | = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/if_same_then_else.rs:20:13 + --> $DIR/if_same_then_else.rs:29:12 | -LL | if true { - | _____________^ +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block LL | | Foo { bar: 42 }; LL | | 0..10; -LL | | ..; ... | LL | | foo(); -LL | | } else { +LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:66:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | 0.0 -LL | | }; - | |_____^ - | -note: same as this - --> $DIR/if_same_then_else.rs:64:21 + --> $DIR/if_same_then_else.rs:65:21 | LL | let _ = if true { | _____________________^ LL | | 0.0 LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:73:12 + | +note: same as this + --> $DIR/if_same_then_else.rs:67:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | -0.0 +LL | | 0.0 LL | | }; | |_____^ - | -note: same as this - --> $DIR/if_same_then_else.rs:71:21 + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:72:21 | LL | let _ = if true { | _____________________^ LL | | -0.0 LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:89:12 + | +note: same as this + --> $DIR/if_same_then_else.rs:74:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | 42 +LL | | -0.0 LL | | }; | |_____^ - | -note: same as this - --> $DIR/if_same_then_else.rs:87:21 + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:88:21 | LL | let _ = if true { | _____________________^ LL | | 42 LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else.rs:101:12 + | +note: same as this + --> $DIR/if_same_then_else.rs:90:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block +LL | | 42 +LL | | }; + | |_____^ + +error: this `if` has identical blocks + --> $DIR/if_same_then_else.rs:95:13 + | +LL | if true { + | _____________^ LL | | let bar = if true { 42 } else { 43 }; LL | | +LL | | while foo() { ... | LL | | bar + 1; -LL | | } +LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:94:13 + --> $DIR/if_same_then_else.rs:102:12 | -LL | if true { - | _____________^ +LL | } else { + | ____________^ +LL | | //~ ERROR same body as `if` block LL | | let bar = if true { 42 } else { 43 }; LL | | -LL | | while foo() { ... | LL | | bar + 1; -LL | | } else { +LL | | } | |_____^ error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.rs b/src/tools/clippy/tests/ui/if_same_then_else2.rs index a2ff1b741c..e4dc5b647d 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else2.rs +++ b/src/tools/clippy/tests/ui/if_same_then_else2.rs @@ -5,7 +5,8 @@ clippy::collapsible_if, clippy::ifs_same_cond, clippy::needless_return, - clippy::single_element_loop + clippy::single_element_loop, + clippy::branches_sharing_code )] fn if_same_then_else2() -> Result<&'static str, ()> { diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr index 454322d8aa..6524be0af8 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr +++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr @@ -1,19 +1,5 @@ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:21:12 - | -LL | } else { - | ____________^ -LL | | //~ ERROR same body as `if` block -LL | | for _ in &[42] { -LL | | let bar: &Option<_> = &Some::<u8>(42); -... | -LL | | } -LL | | } - | |_____^ - | - = note: `-D clippy::if-same-then-else` implied by `-D warnings` -note: same as this - --> $DIR/if_same_then_else2.rs:12:13 + --> $DIR/if_same_then_else2.rs:13:13 | LL | if true { | _____________^ @@ -24,95 +10,99 @@ LL | | if foo.is_some() { LL | | } LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:35:12 + | + = note: `-D clippy::if-same-then-else` implied by `-D warnings` +note: same as this + --> $DIR/if_same_then_else2.rs:22:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | if let Some(a) = Some(42) {} +LL | | for _ in &[42] { +LL | | let bar: &Option<_> = &Some::<u8>(42); +... | +LL | | } LL | | } | |_____^ - | -note: same as this - --> $DIR/if_same_then_else2.rs:33:13 + +error: this `if` has identical blocks + --> $DIR/if_same_then_else2.rs:34:13 | LL | if true { | _____________^ LL | | if let Some(a) = Some(42) {} LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:42:12 + | +note: same as this + --> $DIR/if_same_then_else2.rs:36:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | if let (1, .., 3) = (1, 2, 3) {} +LL | | if let Some(a) = Some(42) {} LL | | } | |_____^ - | -note: same as this - --> $DIR/if_same_then_else2.rs:40:13 + +error: this `if` has identical blocks + --> $DIR/if_same_then_else2.rs:41:13 | LL | if true { | _____________^ LL | | if let (1, .., 3) = (1, 2, 3) {} LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:92:12 + | +note: same as this + --> $DIR/if_same_then_else2.rs:43:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | f32::NAN -LL | | }; +LL | | if let (1, .., 3) = (1, 2, 3) {} +LL | | } | |_____^ - | -note: same as this - --> $DIR/if_same_then_else2.rs:90:21 + +error: this `if` has identical blocks + --> $DIR/if_same_then_else2.rs:91:21 | LL | let _ = if true { | _____________________^ LL | | f32::NAN LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:99:12 + | +note: same as this + --> $DIR/if_same_then_else2.rs:93:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | Ok("foo")?; -LL | | } +LL | | f32::NAN +LL | | }; | |_____^ - | -note: same as this - --> $DIR/if_same_then_else2.rs:97:13 + +error: this `if` has identical blocks + --> $DIR/if_same_then_else2.rs:98:13 | LL | if true { | _____________^ LL | | Ok("foo")?; LL | | } else { | |_____^ - -error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:124:12 + | +note: same as this + --> $DIR/if_same_then_else2.rs:100:12 | LL | } else { | ____________^ -LL | | let foo = ""; -LL | | return Ok(&foo[0..]); +LL | | //~ ERROR same body as `if` block +LL | | Ok("foo")?; LL | | } | |_____^ - | -note: same as this - --> $DIR/if_same_then_else2.rs:121:20 + +error: this `if` has identical blocks + --> $DIR/if_same_then_else2.rs:122:20 | LL | } else if true { | ____________________^ @@ -120,6 +110,16 @@ LL | | let foo = ""; LL | | return Ok(&foo[0..]); LL | | } else { | |_____^ + | +note: same as this + --> $DIR/if_same_then_else2.rs:125:12 + | +LL | } else { + | ____________^ +LL | | let foo = ""; +LL | | return Ok(&foo[0..]); +LL | | } + | |_____^ error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.rs b/src/tools/clippy/tests/ui/if_then_some_else_none.rs new file mode 100644 index 0000000000..54789bf932 --- /dev/null +++ b/src/tools/clippy/tests/ui/if_then_some_else_none.rs @@ -0,0 +1,104 @@ +#![warn(clippy::if_then_some_else_none)] +#![feature(custom_inner_attributes)] + +fn main() { + // Should issue an error. + let _ = if foo() { + println!("true!"); + Some("foo") + } else { + None + }; + + // Should issue an error when macros are used. + let _ = if matches!(true, true) { + println!("true!"); + Some(matches!(true, false)) + } else { + None + }; + + // Should issue an error. Binary expression `o < 32` should be parenthesized. + let x = Some(5); + let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); + + // Should issue an error. Unary expression `!x` should be parenthesized. + let x = true; + let _ = if !x { Some(0) } else { None }; + + // Should not issue an error since the `else` block has a statement besides `None`. + let _ = if foo() { + println!("true!"); + Some("foo") + } else { + eprintln!("false..."); + None + }; + + // Should not issue an error since there are more than 2 blocks in the if-else chain. + let _ = if foo() { + println!("foo true!"); + Some("foo") + } else if bar() { + println!("bar true!"); + Some("bar") + } else { + None + }; + + let _ = if foo() { + println!("foo true!"); + Some("foo") + } else { + bar().then(|| { + println!("bar true!"); + "bar" + }) + }; + + // Should not issue an error since the `then` block has `None`, not `Some`. + let _ = if foo() { None } else { Some("foo is false") }; + + // Should not issue an error since the `else` block doesn't use `None` directly. + let _ = if foo() { Some("foo is true") } else { into_none() }; + + // Should not issue an error since the `then` block doesn't use `Some` directly. + let _ = if foo() { into_some("foo") } else { None }; +} + +fn _msrv_1_49() { + #![clippy::msrv = "1.49"] + // `bool::then` was stabilized in 1.50. Do not lint this + let _ = if foo() { + println!("true!"); + Some(149) + } else { + None + }; +} + +fn _msrv_1_50() { + #![clippy::msrv = "1.50"] + let _ = if foo() { + println!("true!"); + Some(150) + } else { + None + }; +} + +fn foo() -> bool { + unimplemented!() +} + +fn bar() -> bool { + unimplemented!() +} + +fn into_some<T>(v: T) -> Option<T> { + Some(v) +} + +fn into_none<T>() -> Option<T> { + None +} diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr new file mode 100644 index 0000000000..8cb22d569f --- /dev/null +++ b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr @@ -0,0 +1,61 @@ +error: this could be simplified with `bool::then` + --> $DIR/if_then_some_else_none.rs:6:13 + | +LL | let _ = if foo() { + | _____________^ +LL | | println!("true!"); +LL | | Some("foo") +LL | | } else { +LL | | None +LL | | }; + | |_____^ + | + = note: `-D clippy::if-then-some-else-none` implied by `-D warnings` + = help: consider using `bool::then` like: `foo().then(|| { /* snippet */ "foo" })` + +error: this could be simplified with `bool::then` + --> $DIR/if_then_some_else_none.rs:14:13 + | +LL | let _ = if matches!(true, true) { + | _____________^ +LL | | println!("true!"); +LL | | Some(matches!(true, false)) +LL | | } else { +LL | | None +LL | | }; + | |_____^ + | + = help: consider using `bool::then` like: `matches!(true, true).then(|| { /* snippet */ matches!(true, false) })` + +error: this could be simplified with `bool::then` + --> $DIR/if_then_some_else_none.rs:23:28 + | +LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `bool::then` like: `(o < 32).then(|| o)` + +error: this could be simplified with `bool::then` + --> $DIR/if_then_some_else_none.rs:27:13 + | +LL | let _ = if !x { Some(0) } else { None }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `bool::then` like: `(!x).then(|| 0)` + +error: this could be simplified with `bool::then` + --> $DIR/if_then_some_else_none.rs:82:13 + | +LL | let _ = if foo() { + | _____________^ +LL | | println!("true!"); +LL | | Some(150) +LL | | } else { +LL | | None +LL | | }; + | |_____^ + | + = help: consider using `bool::then` like: `foo().then(|| { /* snippet */ 150 })` + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/implicit_clone.rs b/src/tools/clippy/tests/ui/implicit_clone.rs index 1910152216..cef71cf79d 100644 --- a/src/tools/clippy/tests/ui/implicit_clone.rs +++ b/src/tools/clippy/tests/ui/implicit_clone.rs @@ -66,7 +66,7 @@ fn main() { let _ = vec.to_vec(); let vec_ref = &vec; - let _ = return_owned_from_slice(&vec_ref); + let _ = return_owned_from_slice(vec_ref); let _ = vec_ref.to_owned(); let _ = vec_ref.to_vec(); diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed index 8d9c311003..d102574379 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed @@ -13,6 +13,15 @@ struct Foo { z: i32, } +macro_rules! new_foo { + () => { + let x = 1; + let y = 1; + let z = 1; + Foo { y, x, z } + }; +} + mod without_base { use super::Foo; @@ -24,6 +33,10 @@ mod without_base { // Should lint. Foo { x, y, z }; + // Should NOT lint. + // issue #7069. + new_foo!(); + // Shoule NOT lint because the order is the same as in the definition. Foo { x, y, z }; diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs index 63fac91050..b095aa64a2 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs @@ -13,6 +13,15 @@ struct Foo { z: i32, } +macro_rules! new_foo { + () => { + let x = 1; + let y = 1; + let z = 1; + Foo { y, x, z } + }; +} + mod without_base { use super::Foo; @@ -24,6 +33,10 @@ mod without_base { // Should lint. Foo { y, x, z }; + // Should NOT lint. + // issue #7069. + new_foo!(); + // Shoule NOT lint because the order is the same as in the definition. Foo { x, y, z }; diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr index d7abe44f25..ef308dedb1 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr @@ -1,13 +1,13 @@ -error: inconsistent struct constructor - --> $DIR/inconsistent_struct_constructor.rs:25:9 +error: struct constructor field order is inconsistent with struct definition field order + --> $DIR/inconsistent_struct_constructor.rs:34:9 | LL | Foo { y, x, z }; | ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }` | = note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings` -error: inconsistent struct constructor - --> $DIR/inconsistent_struct_constructor.rs:43:9 +error: struct constructor field order is inconsistent with struct definition field order + --> $DIR/inconsistent_struct_constructor.rs:56:9 | LL | / Foo { LL | | z, diff --git a/src/tools/clippy/tests/ui/into_iter_on_ref.fixed b/src/tools/clippy/tests/ui/into_iter_on_ref.fixed index 7f92d0dbdc..b77f17944d 100644 --- a/src/tools/clippy/tests/ui/into_iter_on_ref.fixed +++ b/src/tools/clippy/tests/ui/into_iter_on_ref.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::useless_vec)] +#![allow(clippy::useless_vec, clippy::needless_borrow)] #![warn(clippy::into_iter_on_ref)] struct X; diff --git a/src/tools/clippy/tests/ui/into_iter_on_ref.rs b/src/tools/clippy/tests/ui/into_iter_on_ref.rs index 416056d3fd..3854bb05af 100644 --- a/src/tools/clippy/tests/ui/into_iter_on_ref.rs +++ b/src/tools/clippy/tests/ui/into_iter_on_ref.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::useless_vec)] +#![allow(clippy::useless_vec, clippy::needless_borrow)] #![warn(clippy::into_iter_on_ref)] struct X; diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed new file mode 100644 index 0000000000..4f5322ebf2 --- /dev/null +++ b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed @@ -0,0 +1,49 @@ +// run-rustfix + +fn main() { + unsafe { + let _slice: &[usize] = std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + let _slice: &[usize] = std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + + let _slice: &[usize] = std::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0); + + std::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); + + std::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); + + struct A; // zero sized struct + assert_eq!(std::mem::size_of::<A>(), 0); + + let _a: A = std::ptr::read(core::ptr::NonNull::dangling().as_ptr()); + let _a: A = std::ptr::read(core::ptr::NonNull::dangling().as_ptr()); + + let _a: A = std::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); + let _a: A = std::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); + + let _a: A = std::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); + let _a: A = std::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); + + let _a: A = std::ptr::replace(core::ptr::NonNull::dangling().as_ptr(), A); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0); + + std::ptr::swap::<A>(core::ptr::NonNull::dangling().as_ptr(), &mut A); + std::ptr::swap::<A>(&mut A, core::ptr::NonNull::dangling().as_ptr()); + + std::ptr::swap_nonoverlapping::<A>(core::ptr::NonNull::dangling().as_ptr(), &mut A, 0); + std::ptr::swap_nonoverlapping::<A>(&mut A, core::ptr::NonNull::dangling().as_ptr(), 0); + + std::ptr::write(core::ptr::NonNull::dangling().as_ptr(), A); + + std::ptr::write_unaligned(core::ptr::NonNull::dangling().as_ptr(), A); + + std::ptr::write_volatile(core::ptr::NonNull::dangling().as_ptr(), A); + + std::ptr::write_bytes::<usize>(core::ptr::NonNull::dangling().as_ptr(), 42, 0); + } +} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs new file mode 100644 index 0000000000..ae51c52d8a --- /dev/null +++ b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs @@ -0,0 +1,49 @@ +// run-rustfix + +fn main() { + unsafe { + let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); + let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); + + let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); + + std::ptr::copy::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + + std::ptr::copy_nonoverlapping::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + + struct A; // zero sized struct + assert_eq!(std::mem::size_of::<A>(), 0); + + let _a: A = std::ptr::read(std::ptr::null()); + let _a: A = std::ptr::read(std::ptr::null_mut()); + + let _a: A = std::ptr::read_unaligned(std::ptr::null()); + let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); + + let _a: A = std::ptr::read_volatile(std::ptr::null()); + let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); + + let _a: A = std::ptr::replace(std::ptr::null_mut(), A); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null(), 0); + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); + + std::ptr::swap::<A>(std::ptr::null_mut(), &mut A); + std::ptr::swap::<A>(&mut A, std::ptr::null_mut()); + + std::ptr::swap_nonoverlapping::<A>(std::ptr::null_mut(), &mut A, 0); + std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::null_mut(), 0); + + std::ptr::write(std::ptr::null_mut(), A); + + std::ptr::write_unaligned(std::ptr::null_mut(), A); + + std::ptr::write_volatile(std::ptr::null_mut(), A); + + std::ptr::write_bytes::<usize>(std::ptr::null_mut(), 42, 0); + } +} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr new file mode 100644 index 0000000000..532c36abe5 --- /dev/null +++ b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr @@ -0,0 +1,154 @@ +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:5:59 + | +LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + | + = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:6:59 + | +LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:8:63 + | +LL | let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:10:33 + | +LL | std::ptr::copy::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:11:73 + | +LL | std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:13:48 + | +LL | std::ptr::copy_nonoverlapping::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:14:88 + | +LL | std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:19:36 + | +LL | let _a: A = std::ptr::read(std::ptr::null()); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:20:36 + | +LL | let _a: A = std::ptr::read(std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:22:46 + | +LL | let _a: A = std::ptr::read_unaligned(std::ptr::null()); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:23:46 + | +LL | let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:25:45 + | +LL | let _a: A = std::ptr::read_volatile(std::ptr::null()); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:26:45 + | +LL | let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:28:39 + | +LL | let _a: A = std::ptr::replace(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:30:69 + | +LL | let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null(), 0); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:31:69 + | +LL | let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:33:73 + | +LL | let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:35:29 + | +LL | std::ptr::swap::<A>(std::ptr::null_mut(), &mut A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:36:37 + | +LL | std::ptr::swap::<A>(&mut A, std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:38:44 + | +LL | std::ptr::swap_nonoverlapping::<A>(std::ptr::null_mut(), &mut A, 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:39:52 + | +LL | std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:41:25 + | +LL | std::ptr::write(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:43:35 + | +LL | std::ptr::write_unaligned(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:45:34 + | +LL | std::ptr::write_volatile(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:47:40 + | +LL | std::ptr::write_bytes::<usize>(std::ptr::null_mut(), 42, 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: aborting due to 25 previous errors + diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed index 2773227e26..39cc58cd29 100644 --- a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed +++ b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed @@ -19,4 +19,8 @@ fn main() { let _: Vec<u8> = std::ffi::CStr::from_ptr(std::ptr::null()) .to_bytes().to_vec(); } + + // Issue #6808 + let arr: [u8; 64] = [0; 64]; + let _: Vec<_> = arr.to_vec(); } diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.rs b/src/tools/clippy/tests/ui/iter_cloned_collect.rs index 60a4eac23c..c2a036ec09 100644 --- a/src/tools/clippy/tests/ui/iter_cloned_collect.rs +++ b/src/tools/clippy/tests/ui/iter_cloned_collect.rs @@ -22,4 +22,8 @@ fn main() { .cloned() .collect(); } + + // Issue #6808 + let arr: [u8; 64] = [0; 64]; + let _: Vec<_> = arr.iter().cloned().collect(); } diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.stderr b/src/tools/clippy/tests/ui/iter_cloned_collect.stderr index b90a1e6c91..e1df61794c 100644 --- a/src/tools/clippy/tests/ui/iter_cloned_collect.stderr +++ b/src/tools/clippy/tests/ui/iter_cloned_collect.stderr @@ -22,5 +22,11 @@ LL | | .cloned() LL | | .collect(); | |______________________^ help: try: `.to_vec()` -error: aborting due to 3 previous errors +error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable + --> $DIR/iter_cloned_collect.rs:28:24 + | +LL | let _: Vec<_> = arr.iter().cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` + +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.rs b/src/tools/clippy/tests/ui/len_without_is_empty.rs index 6b3636a482..b9d66347c2 100644 --- a/src/tools/clippy/tests/ui/len_without_is_empty.rs +++ b/src/tools/clippy/tests/ui/len_without_is_empty.rs @@ -1,3 +1,5 @@ +// edition:2018 + #![warn(clippy::len_without_is_empty)] #![allow(dead_code, unused)] @@ -172,9 +174,9 @@ pub trait DependsOnFoo: Foo { fn len(&mut self) -> usize; } +// issue #1562 pub struct MultipleImpls; -// issue #1562 impl MultipleImpls { pub fn len(&self) -> usize { 1 @@ -187,4 +189,99 @@ impl MultipleImpls { } } +// issue #6958 +pub struct OptionalLen; + +impl OptionalLen { + pub fn len(&self) -> Option<usize> { + Some(0) + } + + pub fn is_empty(&self) -> Option<bool> { + Some(true) + } +} + +pub struct OptionalLen2; +impl OptionalLen2 { + pub fn len(&self) -> Option<usize> { + Some(0) + } + + pub fn is_empty(&self) -> bool { + true + } +} + +pub struct OptionalLen3; +impl OptionalLen3 { + pub fn len(&self) -> usize { + 0 + } + + // should lint, len is not an option + pub fn is_empty(&self) -> Option<bool> { + None + } +} + +pub struct ResultLen; +impl ResultLen { + pub fn len(&self) -> Result<usize, ()> { + Ok(0) + } + + // Differing result types + pub fn is_empty(&self) -> Option<bool> { + Some(true) + } +} + +pub struct ResultLen2; +impl ResultLen2 { + pub fn len(&self) -> Result<usize, ()> { + Ok(0) + } + + pub fn is_empty(&self) -> Result<bool, ()> { + Ok(true) + } +} + +pub struct ResultLen3; +impl ResultLen3 { + pub fn len(&self) -> Result<usize, ()> { + Ok(0) + } + + // Non-fallible result is ok. + pub fn is_empty(&self) -> bool { + true + } +} + +pub struct OddLenSig; +impl OddLenSig { + // don't lint + pub fn len(&self) -> bool { + true + } +} + +// issue #6958 +pub struct AsyncLen; +impl AsyncLen { + async fn async_task(&self) -> bool { + true + } + + pub async fn len(&self) -> usize { + if self.async_task().await { 0 } else { 1 } + } + + pub async fn is_empty(&self) -> bool { + self.len().await == 0 + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.stderr b/src/tools/clippy/tests/ui/len_without_is_empty.stderr index f106506faf..3282709bcd 100644 --- a/src/tools/clippy/tests/ui/len_without_is_empty.stderr +++ b/src/tools/clippy/tests/ui/len_without_is_empty.stderr @@ -1,5 +1,5 @@ error: struct `PubOne` has a public `len` method, but no `is_empty` method - --> $DIR/len_without_is_empty.rs:7:5 + --> $DIR/len_without_is_empty.rs:9:5 | LL | pub fn len(&self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pub fn len(&self) -> isize { = note: `-D clippy::len-without-is-empty` implied by `-D warnings` error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_without_is_empty.rs:55:1 + --> $DIR/len_without_is_empty.rs:57:1 | LL | / pub trait PubTraitsToo { LL | | fn len(&self) -> isize; @@ -15,50 +15,109 @@ LL | | } | |_^ error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method - --> $DIR/len_without_is_empty.rs:68:5 + --> $DIR/len_without_is_empty.rs:70:5 | LL | pub fn len(&self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:72:5 + --> $DIR/len_without_is_empty.rs:74:5 | LL | fn is_empty(&self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` method has an unexpected signature - --> $DIR/len_without_is_empty.rs:80:5 + --> $DIR/len_without_is_empty.rs:82:5 | LL | pub fn len(&self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:84:5 + --> $DIR/len_without_is_empty.rs:86:5 | LL | pub fn is_empty(&self, x: u32) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected signature: `(&self) -> bool` error: struct `MismatchedSelf` has a public `len` method, but the `is_empty` method has an unexpected signature - --> $DIR/len_without_is_empty.rs:92:5 + --> $DIR/len_without_is_empty.rs:94:5 | LL | pub fn len(self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> $DIR/len_without_is_empty.rs:96:5 + --> $DIR/len_without_is_empty.rs:98:5 | LL | pub fn is_empty(&self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected signature: `(self) -> bool` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> $DIR/len_without_is_empty.rs:171:1 + --> $DIR/len_without_is_empty.rs:173:1 | LL | / pub trait DependsOnFoo: Foo { LL | | fn len(&mut self) -> usize; LL | | } | |_^ -error: aborting due to 6 previous errors +error: struct `OptionalLen3` has a public `len` method, but the `is_empty` method has an unexpected signature + --> $DIR/len_without_is_empty.rs:218:5 + | +LL | pub fn len(&self) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `is_empty` defined here + --> $DIR/len_without_is_empty.rs:223:5 + | +LL | pub fn is_empty(&self) -> Option<bool> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature: `(&self) -> bool` + +error: struct `ResultLen` has a public `len` method, but the `is_empty` method has an unexpected signature + --> $DIR/len_without_is_empty.rs:230:5 + | +LL | pub fn len(&self) -> Result<usize, ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `is_empty` defined here + --> $DIR/len_without_is_empty.rs:235:5 + | +LL | pub fn is_empty(&self) -> Option<bool> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature: `(&self) -> bool` or `(&self) -> Result<bool> + +error: this returns a `Result<_, ()>` + --> $DIR/len_without_is_empty.rs:230:5 + | +LL | pub fn len(&self) -> Result<usize, ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::result-unit-err` implied by `-D warnings` + = help: use a custom `Error` type instead + +error: this returns a `Result<_, ()>` + --> $DIR/len_without_is_empty.rs:242:5 + | +LL | pub fn len(&self) -> Result<usize, ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a custom `Error` type instead + +error: this returns a `Result<_, ()>` + --> $DIR/len_without_is_empty.rs:246:5 + | +LL | pub fn is_empty(&self) -> Result<bool, ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a custom `Error` type instead + +error: this returns a `Result<_, ()>` + --> $DIR/len_without_is_empty.rs:253:5 + | +LL | pub fn len(&self) -> Result<usize, ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use a custom `Error` type instead + +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/let_if_seq.rs b/src/tools/clippy/tests/ui/let_if_seq.rs index 32a67f181d..2d8f3c2f0e 100644 --- a/src/tools/clippy/tests/ui/let_if_seq.rs +++ b/src/tools/clippy/tests/ui/let_if_seq.rs @@ -2,7 +2,8 @@ unused_variables, unused_assignments, clippy::similar_names, - clippy::blacklisted_name + clippy::blacklisted_name, + clippy::branches_sharing_code )] #![warn(clippy::useless_let_if_seq)] diff --git a/src/tools/clippy/tests/ui/let_if_seq.stderr b/src/tools/clippy/tests/ui/let_if_seq.stderr index 7de560c734..9cf2e10a5e 100644 --- a/src/tools/clippy/tests/ui/let_if_seq.stderr +++ b/src/tools/clippy/tests/ui/let_if_seq.stderr @@ -1,5 +1,5 @@ error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:64:5 + --> $DIR/let_if_seq.rs:65:5 | LL | / let mut foo = 0; LL | | if f() { @@ -11,7 +11,7 @@ LL | | } = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:69:5 + --> $DIR/let_if_seq.rs:70:5 | LL | / let mut bar = 0; LL | | if f() { @@ -25,7 +25,7 @@ LL | | } = note: you might not need `mut` at all error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:77:5 + --> $DIR/let_if_seq.rs:78:5 | LL | / let quz; LL | | if f() { @@ -36,7 +36,7 @@ LL | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> $DIR/let_if_seq.rs:106:5 + --> $DIR/let_if_seq.rs:107:5 | LL | / let mut baz = 0; LL | | if f() { diff --git a/src/tools/clippy/tests/ui/dlist.rs b/src/tools/clippy/tests/ui/linkedlist.rs similarity index 90% rename from src/tools/clippy/tests/ui/dlist.rs rename to src/tools/clippy/tests/ui/linkedlist.rs index 2940d2d290..2c3b25cd45 100644 --- a/src/tools/clippy/tests/ui/dlist.rs +++ b/src/tools/clippy/tests/ui/linkedlist.rs @@ -5,6 +5,9 @@ extern crate alloc; use alloc::collections::linked_list::LinkedList; +const C: LinkedList<i32> = LinkedList::new(); +static S: LinkedList<i32> = LinkedList::new(); + trait Foo { type Baz = LinkedList<u8>; fn foo(_: LinkedList<u8>); diff --git a/src/tools/clippy/tests/ui/dlist.stderr b/src/tools/clippy/tests/ui/linkedlist.stderr similarity index 65% rename from src/tools/clippy/tests/ui/dlist.stderr rename to src/tools/clippy/tests/ui/linkedlist.stderr index 234db33ba1..38ae71714d 100644 --- a/src/tools/clippy/tests/ui/dlist.stderr +++ b/src/tools/clippy/tests/ui/linkedlist.stderr @@ -1,14 +1,30 @@ error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:9:16 + --> $DIR/linkedlist.rs:8:10 + | +LL | const C: LinkedList<i32> = LinkedList::new(); + | ^^^^^^^^^^^^^^^ + | + = note: `-D clippy::linkedlist` implied by `-D warnings` + = help: a `VecDeque` might work + +error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? + --> $DIR/linkedlist.rs:9:11 + | +LL | static S: LinkedList<i32> = LinkedList::new(); + | ^^^^^^^^^^^^^^^ + | + = help: a `VecDeque` might work + +error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? + --> $DIR/linkedlist.rs:12:16 | LL | type Baz = LinkedList<u8>; | ^^^^^^^^^^^^^^ | - = note: `-D clippy::linkedlist` implied by `-D warnings` = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:10:15 + --> $DIR/linkedlist.rs:13:15 | LL | fn foo(_: LinkedList<u8>); | ^^^^^^^^^^^^^^ @@ -16,7 +32,7 @@ LL | fn foo(_: LinkedList<u8>); = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:11:23 + --> $DIR/linkedlist.rs:14:23 | LL | const BAR: Option<LinkedList<u8>>; | ^^^^^^^^^^^^^^ @@ -24,7 +40,7 @@ LL | const BAR: Option<LinkedList<u8>>; = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:22:15 + --> $DIR/linkedlist.rs:25:15 | LL | fn foo(_: LinkedList<u8>) {} | ^^^^^^^^^^^^^^ @@ -32,7 +48,7 @@ LL | fn foo(_: LinkedList<u8>) {} = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:25:39 + --> $DIR/linkedlist.rs:28:39 | LL | pub fn test(my_favourite_linked_list: LinkedList<u8>) { | ^^^^^^^^^^^^^^ @@ -40,12 +56,12 @@ LL | pub fn test(my_favourite_linked_list: LinkedList<u8>) { = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:29:29 + --> $DIR/linkedlist.rs:32:29 | LL | pub fn test_ret() -> Option<LinkedList<u8>> { | ^^^^^^^^^^^^^^ | = help: a `VecDeque` might work -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed index 91e34c6216..51c66a4636 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.fixed +++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed @@ -4,7 +4,7 @@ // run-rustfix // ignore-32bit -#![allow(unused_imports, unreachable_code, unused_variables, dead_code)] +#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] @@ -40,4 +40,8 @@ mod a { } } +// issue #7015, ICE due to calling `item_children` with local `DefId` +#[macro_use] +use a as b; + fn main() {} diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs index 9c3c50c5d4..2011129bc9 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.rs +++ b/src/tools/clippy/tests/ui/macro_use_imports.rs @@ -4,7 +4,7 @@ // run-rustfix // ignore-32bit -#![allow(unused_imports, unreachable_code, unused_variables, dead_code)] +#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] @@ -40,4 +40,8 @@ mod a { } } +// issue #7015, ICE due to calling `item_children` with local `DefId` +#[macro_use] +use a as b; + fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_flatten.rs b/src/tools/clippy/tests/ui/manual_flatten.rs index cff68eca93..b5bd35a687 100644 --- a/src/tools/clippy/tests/ui/manual_flatten.rs +++ b/src/tools/clippy/tests/ui/manual_flatten.rs @@ -1,4 +1,5 @@ #![warn(clippy::manual_flatten)] +#![allow(clippy::useless_vec)] fn main() { // Test for loop over implicitly adjusted `Iterator` with `if let` expression @@ -69,6 +70,27 @@ fn main() { } } + let vec_of_ref = vec![&Some(1)]; + for n in &vec_of_ref { + if let Some(n) = n { + println!("{:?}", n); + } + } + + let vec_of_ref = &vec_of_ref; + for n in vec_of_ref { + if let Some(n) = n { + println!("{:?}", n); + } + } + + let slice_of_ref = &[&Some(1)]; + for n in slice_of_ref { + if let Some(n) = n { + println!("{:?}", n); + } + } + // Using manual flatten should not trigger the lint for n in vec![Some(1), Some(2), Some(3)].iter().flatten() { println!("{}", n); diff --git a/src/tools/clippy/tests/ui/manual_flatten.stderr b/src/tools/clippy/tests/ui/manual_flatten.stderr index 855dd9130e..be5f8a1d81 100644 --- a/src/tools/clippy/tests/ui/manual_flatten.stderr +++ b/src/tools/clippy/tests/ui/manual_flatten.stderr @@ -1,5 +1,5 @@ error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> $DIR/manual_flatten.rs:6:5 + --> $DIR/manual_flatten.rs:7:5 | LL | for n in x { | ^ - help: try: `x.into_iter().flatten()` @@ -13,7 +13,7 @@ LL | | } | = note: `-D clippy::manual-flatten` implied by `-D warnings` help: ...and remove the `if let` statement in the for loop - --> $DIR/manual_flatten.rs:7:9 + --> $DIR/manual_flatten.rs:8:9 | LL | / if let Some(y) = n { LL | | println!("{}", y); @@ -21,7 +21,7 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Ok` variant of the iterator element is used - --> $DIR/manual_flatten.rs:14:5 + --> $DIR/manual_flatten.rs:15:5 | LL | for n in y.clone() { | ^ --------- help: try: `y.clone().into_iter().flatten()` @@ -34,7 +34,7 @@ LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> $DIR/manual_flatten.rs:15:9 + --> $DIR/manual_flatten.rs:16:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); @@ -42,7 +42,7 @@ LL | | }; | |_________^ error: unnecessary `if let` since only the `Ok` variant of the iterator element is used - --> $DIR/manual_flatten.rs:21:5 + --> $DIR/manual_flatten.rs:22:5 | LL | for n in &y { | ^ -- help: try: `y.iter().flatten()` @@ -55,7 +55,7 @@ LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> $DIR/manual_flatten.rs:22:9 + --> $DIR/manual_flatten.rs:23:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); @@ -63,7 +63,7 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Ok` variant of the iterator element is used - --> $DIR/manual_flatten.rs:31:5 + --> $DIR/manual_flatten.rs:32:5 | LL | for n in z { | ^ - help: try: `z.into_iter().flatten()` @@ -76,7 +76,7 @@ LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> $DIR/manual_flatten.rs:32:9 + --> $DIR/manual_flatten.rs:33:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); @@ -84,7 +84,7 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> $DIR/manual_flatten.rs:40:5 + --> $DIR/manual_flatten.rs:41:5 | LL | for n in z { | ^ - help: try: `z.flatten()` @@ -97,12 +97,75 @@ LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> $DIR/manual_flatten.rs:41:9 + --> $DIR/manual_flatten.rs:42:9 | LL | / if let Some(m) = n { LL | | println!("{}", m); LL | | } | |_________^ -error: aborting due to 5 previous errors +error: unnecessary `if let` since only the `Some` variant of the iterator element is used + --> $DIR/manual_flatten.rs:74:5 + | +LL | for n in &vec_of_ref { + | ^ ----------- help: try: `vec_of_ref.iter().copied().flatten()` + | _____| + | | +LL | | if let Some(n) = n { +LL | | println!("{:?}", n); +LL | | } +LL | | } + | |_____^ + | +help: ...and remove the `if let` statement in the for loop + --> $DIR/manual_flatten.rs:75:9 + | +LL | / if let Some(n) = n { +LL | | println!("{:?}", n); +LL | | } + | |_________^ + +error: unnecessary `if let` since only the `Some` variant of the iterator element is used + --> $DIR/manual_flatten.rs:81:5 + | +LL | for n in vec_of_ref { + | ^ ---------- help: try: `vec_of_ref.into_iter().copied().flatten()` + | _____| + | | +LL | | if let Some(n) = n { +LL | | println!("{:?}", n); +LL | | } +LL | | } + | |_____^ + | +help: ...and remove the `if let` statement in the for loop + --> $DIR/manual_flatten.rs:82:9 + | +LL | / if let Some(n) = n { +LL | | println!("{:?}", n); +LL | | } + | |_________^ + +error: unnecessary `if let` since only the `Some` variant of the iterator element is used + --> $DIR/manual_flatten.rs:88:5 + | +LL | for n in slice_of_ref { + | ^ ------------ help: try: `slice_of_ref.into_iter().copied().flatten()` + | _____| + | | +LL | | if let Some(n) = n { +LL | | println!("{:?}", n); +LL | | } +LL | | } + | |_____^ + | +help: ...and remove the `if let` statement in the for loop + --> $DIR/manual_flatten.rs:89:9 + | +LL | / if let Some(n) = n { +LL | | println!("{:?}", n); +LL | | } + | |_________^ + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed index 9222aaf6c7..40d01df637 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.fixed +++ b/src/tools/clippy/tests/ui/manual_map_option.fixed @@ -7,6 +7,7 @@ clippy::map_identity, clippy::unit_arg, clippy::match_ref_pats, + clippy::redundant_pattern_matching, dead_code )] @@ -128,4 +129,28 @@ fn main() { None => None, }; } + + // #6847 + if let Some(_) = Some(0) { + Some(0) + } else { Some(0).map(|x| x + 1) }; + + if true { + Some(0) + } else { Some(0).map(|x| x + 1) }; + + // #6967 + const fn f4() { + match Some(0) { + Some(x) => Some(x + 1), + None => None, + }; + } + + // #7077 + let s = &String::new(); + let _: Option<&str> = match Some(s) { + Some(s) => Some(s), + None => None, + }; } diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs index 1ccb450619..cfef0c5cc4 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.rs +++ b/src/tools/clippy/tests/ui/manual_map_option.rs @@ -7,6 +7,7 @@ clippy::map_identity, clippy::unit_arg, clippy::match_ref_pats, + clippy::redundant_pattern_matching, dead_code )] @@ -186,4 +187,36 @@ fn main() { None => None, }; } + + // #6847 + if let Some(_) = Some(0) { + Some(0) + } else if let Some(x) = Some(0) { + Some(x + 1) + } else { + None + }; + + if true { + Some(0) + } else if let Some(x) = Some(0) { + Some(x + 1) + } else { + None + }; + + // #6967 + const fn f4() { + match Some(0) { + Some(x) => Some(x + 1), + None => None, + }; + } + + // #7077 + let s = &String::new(); + let _: Option<&str> = match Some(s) { + Some(s) => Some(s), + None => None, + }; } diff --git a/src/tools/clippy/tests/ui/manual_map_option.stderr b/src/tools/clippy/tests/ui/manual_map_option.stderr index d9f86eecd9..cdc2c0e62a 100644 --- a/src/tools/clippy/tests/ui/manual_map_option.stderr +++ b/src/tools/clippy/tests/ui/manual_map_option.stderr @@ -1,5 +1,5 @@ error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:14:5 + --> $DIR/manual_map_option.rs:15:5 | LL | / match Some(0) { LL | | Some(_) => Some(2), @@ -10,7 +10,7 @@ LL | | }; = note: `-D clippy::manual-map` implied by `-D warnings` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:19:5 + --> $DIR/manual_map_option.rs:20:5 | LL | / match Some(0) { LL | | Some(x) => Some(x + 1), @@ -19,7 +19,7 @@ LL | | }; | |_____^ help: try this: `Some(0).map(|x| x + 1)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:24:5 + --> $DIR/manual_map_option.rs:25:5 | LL | / match Some("") { LL | | Some(x) => Some(x.is_empty()), @@ -28,7 +28,7 @@ LL | | }; | |_____^ help: try this: `Some("").map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:29:5 + --> $DIR/manual_map_option.rs:30:5 | LL | / if let Some(x) = Some(0) { LL | | Some(!x) @@ -38,7 +38,7 @@ LL | | }; | |_____^ help: try this: `Some(0).map(|x| !x)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:36:5 + --> $DIR/manual_map_option.rs:37:5 | LL | / match Some(0) { LL | | Some(x) => { Some(std::convert::identity(x)) } @@ -47,7 +47,7 @@ LL | | }; | |_____^ help: try this: `Some(0).map(std::convert::identity)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:41:5 + --> $DIR/manual_map_option.rs:42:5 | LL | / match Some(&String::new()) { LL | | Some(x) => Some(str::len(x)), @@ -56,7 +56,7 @@ LL | | }; | |_____^ help: try this: `Some(&String::new()).map(|x| str::len(x))` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:51:5 + --> $DIR/manual_map_option.rs:52:5 | LL | / match &Some([0, 1]) { LL | | Some(x) => Some(x[0]), @@ -65,7 +65,7 @@ LL | | }; | |_____^ help: try this: `Some([0, 1]).as_ref().map(|x| x[0])` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:56:5 + --> $DIR/manual_map_option.rs:57:5 | LL | / match &Some(0) { LL | | &Some(x) => Some(x * 2), @@ -74,7 +74,7 @@ LL | | }; | |_____^ help: try this: `Some(0).map(|x| x * 2)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:61:5 + --> $DIR/manual_map_option.rs:62:5 | LL | / match Some(String::new()) { LL | | Some(ref x) => Some(x.is_empty()), @@ -83,7 +83,7 @@ LL | | }; | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:66:5 + --> $DIR/manual_map_option.rs:67:5 | LL | / match &&Some(String::new()) { LL | | Some(x) => Some(x.len()), @@ -92,7 +92,7 @@ LL | | }; | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:71:5 + --> $DIR/manual_map_option.rs:72:5 | LL | / match &&Some(0) { LL | | &&Some(x) => Some(x + x), @@ -101,7 +101,7 @@ LL | | }; | |_____^ help: try this: `Some(0).map(|x| x + x)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:84:9 + --> $DIR/manual_map_option.rs:85:9 | LL | / match &mut Some(String::new()) { LL | | Some(x) => Some(x.push_str("")), @@ -110,7 +110,7 @@ LL | | }; | |_________^ help: try this: `Some(String::new()).as_mut().map(|x| x.push_str(""))` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:90:5 + --> $DIR/manual_map_option.rs:91:5 | LL | / match &mut Some(String::new()) { LL | | Some(ref x) => Some(x.len()), @@ -119,7 +119,7 @@ LL | | }; | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:95:5 + --> $DIR/manual_map_option.rs:96:5 | LL | / match &mut &Some(String::new()) { LL | | Some(x) => Some(x.is_empty()), @@ -128,7 +128,7 @@ LL | | }; | |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:100:5 + --> $DIR/manual_map_option.rs:101:5 | LL | / match Some((0, 1, 2)) { LL | | Some((x, y, z)) => Some(x + y + z), @@ -137,7 +137,7 @@ LL | | }; | |_____^ help: try this: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:105:5 + --> $DIR/manual_map_option.rs:106:5 | LL | / match Some([1, 2, 3]) { LL | | Some([first, ..]) => Some(first), @@ -146,7 +146,7 @@ LL | | }; | |_____^ help: try this: `Some([1, 2, 3]).map(|[first, ..]| first)` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:110:5 + --> $DIR/manual_map_option.rs:111:5 | LL | / match &Some((String::new(), "test")) { LL | | Some((x, y)) => Some((y, x)), @@ -155,7 +155,7 @@ LL | | }; | |_____^ help: try this: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:168:5 + --> $DIR/manual_map_option.rs:169:5 | LL | / match Some(0) { LL | | Some(x) => Some(vec![x]), @@ -164,7 +164,7 @@ LL | | }; | |_____^ help: try this: `Some(0).map(|x| vec![x])` error: manual implementation of `Option::map` - --> $DIR/manual_map_option.rs:173:5 + --> $DIR/manual_map_option.rs:174:5 | LL | / match option_env!("") { LL | | Some(x) => Some(String::from(x)), @@ -172,5 +172,27 @@ LL | | None => None, LL | | }; | |_____^ help: try this: `option_env!("").map(String::from)` -error: aborting due to 19 previous errors +error: manual implementation of `Option::map` + --> $DIR/manual_map_option.rs:194:12 + | +LL | } else if let Some(x) = Some(0) { + | ____________^ +LL | | Some(x + 1) +LL | | } else { +LL | | None +LL | | }; + | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }` + +error: manual implementation of `Option::map` + --> $DIR/manual_map_option.rs:202:12 + | +LL | } else if let Some(x) = Some(0) { + | ____________^ +LL | | Some(x + 1) +LL | | } else { +LL | | None +LL | | }; + | |_____^ help: try this: `{ Some(0).map(|x| x + 1) }` + +error: aborting due to 21 previous errors diff --git a/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.stderr index 2547b19f5d..a2f2dfce16 100644 --- a/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.stderr +++ b/src/tools/clippy/tests/ui/manual_memcpy/with_loop_counters.stderr @@ -43,7 +43,7 @@ LL | / for i in 3..(3 + src.len()) { LL | | dst[i] = src[count]; LL | | count += 1; LL | | } - | |_____^ help: try replacing the loop by: `dst[3..((3 + src.len()))].clone_from_slice(&src[..((3 + src.len()) - 3)]);` + | |_____^ help: try replacing the loop by: `dst[3..(3 + src.len())].clone_from_slice(&src[..((3 + src.len()) - 3)]);` error: it looks like you're manually copying between slices --> $DIR/with_loop_counters.rs:35:5 diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed index 81d903c15d..e7a29596b7 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed @@ -136,4 +136,31 @@ fn result_unwrap_or() { }; } +// don't lint in const fn +const fn const_fn_option_unwrap_or() { + match Some(1) { + Some(s) => s, + None => 0, + }; +} + +const fn const_fn_result_unwrap_or() { + match Ok::<&str, &str>("Alice") { + Ok(s) => s, + Err(_) => "Bob", + }; +} + +mod issue6965 { + macro_rules! some_macro { + () => { + if 1 > 2 { Some(1) } else { None } + }; + } + + fn test() { + let _ = some_macro!().unwrap_or(0); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs index 16105d379c..66006b6c61 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs @@ -175,4 +175,34 @@ fn result_unwrap_or() { }; } +// don't lint in const fn +const fn const_fn_option_unwrap_or() { + match Some(1) { + Some(s) => s, + None => 0, + }; +} + +const fn const_fn_result_unwrap_or() { + match Ok::<&str, &str>("Alice") { + Ok(s) => s, + Err(_) => "Bob", + }; +} + +mod issue6965 { + macro_rules! some_macro { + () => { + if 1 > 2 { Some(1) } else { None } + }; + } + + fn test() { + let _ = match some_macro!() { + Some(val) => val, + None => 0, + }; + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr index fc174c4c27..99625b789b 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr @@ -141,5 +141,15 @@ LL | | Err(_) => "Alice", LL | | }; | |_____^ help: replace with: `Ok::<&str, &str>("Bob").unwrap_or("Alice")` -error: aborting due to 13 previous errors +error: this pattern reimplements `Option::unwrap_or` + --> $DIR/manual_unwrap_or.rs:201:17 + | +LL | let _ = match some_macro!() { + | _________________^ +LL | | Some(val) => val, +LL | | None => 0, +LL | | }; + | |_________^ help: replace with: `some_macro!().unwrap_or(0)` + +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/match_ref_pats.stderr b/src/tools/clippy/tests/ui/match_ref_pats.stderr index 52cb4a14b7..67474e65cd 100644 --- a/src/tools/clippy/tests/ui/match_ref_pats.stderr +++ b/src/tools/clippy/tests/ui/match_ref_pats.stderr @@ -46,6 +46,14 @@ LL | Some(v) => println!("{:?}", v), LL | None => println!("none"), | +error: redundant pattern matching, consider using `is_none()` + --> $DIR/match_ref_pats.rs:35:12 + | +LL | if let &None = a { + | -------^^^^^---- help: try this: `if a.is_none()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + error: you don't need to add `&` to all patterns --> $DIR/match_ref_pats.rs:35:5 | @@ -59,6 +67,12 @@ help: instead of prefixing all patterns with `&`, you can dereference the expres LL | if let None = *a { | ^^^^ ^^ +error: redundant pattern matching, consider using `is_none()` + --> $DIR/match_ref_pats.rs:40:12 + | +LL | if let &None = &b { + | -------^^^^^----- help: try this: `if b.is_none()` + error: you don't need to add `&` to both the expression and the patterns --> $DIR/match_ref_pats.rs:40:5 | @@ -87,5 +101,5 @@ LL | match *foo_variant!(0) { LL | Foo::A => println!("A"), | -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/match_single_binding2.fixed b/src/tools/clippy/tests/ui/match_single_binding2.fixed new file mode 100644 index 0000000000..e73a85b73d --- /dev/null +++ b/src/tools/clippy/tests/ui/match_single_binding2.fixed @@ -0,0 +1,37 @@ +// run-rustfix + +#![warn(clippy::match_single_binding)] +#![allow(unused_variables)] + +fn main() { + // Lint (additional curly braces needed, see #6572) + struct AppendIter<I> + where + I: Iterator, + { + inner: Option<(I, <I as Iterator>::Item)>, + } + + #[allow(dead_code)] + fn size_hint<I: Iterator>(iter: &AppendIter<I>) -> (usize, Option<usize>) { + match &iter.inner { + Some((iter, _item)) => { + let (min, max) = iter.size_hint(); + (min.saturating_add(1), max.and_then(|max| max.checked_add(1))) + }, + None => (0, Some(0)), + } + } + + // Lint (no additional curly braces needed) + let opt = Some((5, 2)); + let get_tup = || -> (i32, i32) { (1, 2) }; + match opt { + #[rustfmt::skip] + Some((first, _second)) => { + let (a, b) = get_tup(); + println!("a {:?} and b {:?}", a, b); + }, + None => println!("nothing"), + } +} diff --git a/src/tools/clippy/tests/ui/match_single_binding2.rs b/src/tools/clippy/tests/ui/match_single_binding2.rs new file mode 100644 index 0000000000..7362cb390e --- /dev/null +++ b/src/tools/clippy/tests/ui/match_single_binding2.rs @@ -0,0 +1,37 @@ +// run-rustfix + +#![warn(clippy::match_single_binding)] +#![allow(unused_variables)] + +fn main() { + // Lint (additional curly braces needed, see #6572) + struct AppendIter<I> + where + I: Iterator, + { + inner: Option<(I, <I as Iterator>::Item)>, + } + + #[allow(dead_code)] + fn size_hint<I: Iterator>(iter: &AppendIter<I>) -> (usize, Option<usize>) { + match &iter.inner { + Some((iter, _item)) => match iter.size_hint() { + (min, max) => (min.saturating_add(1), max.and_then(|max| max.checked_add(1))), + }, + None => (0, Some(0)), + } + } + + // Lint (no additional curly braces needed) + let opt = Some((5, 2)); + let get_tup = || -> (i32, i32) { (1, 2) }; + match opt { + #[rustfmt::skip] + Some((first, _second)) => { + match get_tup() { + (a, b) => println!("a {:?} and b {:?}", a, b), + } + }, + None => println!("nothing"), + } +} diff --git a/src/tools/clippy/tests/ui/match_single_binding2.stderr b/src/tools/clippy/tests/ui/match_single_binding2.stderr new file mode 100644 index 0000000000..bc18d191aa --- /dev/null +++ b/src/tools/clippy/tests/ui/match_single_binding2.stderr @@ -0,0 +1,34 @@ +error: this match could be written as a `let` statement + --> $DIR/match_single_binding2.rs:18:36 + | +LL | Some((iter, _item)) => match iter.size_hint() { + | ____________________________________^ +LL | | (min, max) => (min.saturating_add(1), max.and_then(|max| max.checked_add(1))), +LL | | }, + | |_____________^ + | + = note: `-D clippy::match-single-binding` implied by `-D warnings` +help: consider using `let` statement + | +LL | Some((iter, _item)) => { +LL | let (min, max) = iter.size_hint(); +LL | (min.saturating_add(1), max.and_then(|max| max.checked_add(1))) +LL | }, + | + +error: this match could be written as a `let` statement + --> $DIR/match_single_binding2.rs:31:13 + | +LL | / match get_tup() { +LL | | (a, b) => println!("a {:?} and b {:?}", a, b), +LL | | } + | |_____________^ + | +help: consider using `let` statement + | +LL | let (a, b) = get_tup(); +LL | println!("a {:?} and b {:?}", a, b); + | + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed index 519200977a..31b743f7a1 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed @@ -15,6 +15,16 @@ enum Color { Blue, Rgb(u8, u8, u8), } +impl Color { + fn f(self) { + match self { + Self::Red => (), + Self::Green => (), + Self::Blue => (), + Self::Rgb(..) => (), + }; + } +} fn main() { let f = Foo::A; @@ -56,4 +66,62 @@ fn main() { Color::Rgb(255, _, _) => {}, _ => {}, } + + // References shouldn't change anything + match &color { + &Color::Red => (), + Color::Green => (), + &Color::Rgb(..) => (), + Color::Blue => (), + } + + use self::Color as C; + + match color { + C::Red => (), + C::Green => (), + C::Rgb(..) => (), + C::Blue => (), + } + + match color { + C::Red => (), + Color::Green => (), + Color::Rgb(..) => (), + Color::Blue => (), + } + + match Some(0) { + Some(0) => 0, + Some(_) => 1, + _ => 2, + }; + + #[non_exhaustive] + enum Bar { + A, + B, + C, + } + match Bar::A { + Bar::A => (), + Bar::B => (), + _ => (), + }; + + //#6984 + { + #![allow(clippy::manual_non_exhaustive)] + pub enum Enum { + A, + B, + #[doc(hidden)] + __Private, + } + match Enum::A { + Enum::A => (), + Enum::B => (), + _ => (), + } + } } diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs index 1df917e085..d19e6ab7eb 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs @@ -15,6 +15,16 @@ enum Color { Blue, Rgb(u8, u8, u8), } +impl Color { + fn f(self) { + match self { + Self::Red => (), + Self::Green => (), + Self::Blue => (), + _ => (), + }; + } +} fn main() { let f = Foo::A; @@ -56,4 +66,62 @@ fn main() { Color::Rgb(255, _, _) => {}, _ => {}, } + + // References shouldn't change anything + match &color { + &Color::Red => (), + Color::Green => (), + &Color::Rgb(..) => (), + &_ => (), + } + + use self::Color as C; + + match color { + C::Red => (), + C::Green => (), + C::Rgb(..) => (), + _ => (), + } + + match color { + C::Red => (), + Color::Green => (), + Color::Rgb(..) => (), + _ => (), + } + + match Some(0) { + Some(0) => 0, + Some(_) => 1, + _ => 2, + }; + + #[non_exhaustive] + enum Bar { + A, + B, + C, + } + match Bar::A { + Bar::A => (), + Bar::B => (), + _ => (), + }; + + //#6984 + { + #![allow(clippy::manual_non_exhaustive)] + pub enum Enum { + A, + B, + #[doc(hidden)] + __Private, + } + match Enum::A { + Enum::A => (), + Enum::B => (), + _ => (), + } + } } diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr index 82790aa9e8..34538dea8e 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr @@ -1,28 +1,52 @@ -error: wildcard match will miss any future added variants - --> $DIR/match_wildcard_for_single_variants.rs:24:9 +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:24:13 | -LL | _ => {}, - | ^ help: try this: `Foo::C` +LL | _ => (), + | ^ help: try this: `Self::Rgb(..)` | = note: `-D clippy::match-wildcard-for-single-variants` implied by `-D warnings` -error: wildcard match will miss any future added variants +error: wildcard matches only a single variant and will also match any future added variants --> $DIR/match_wildcard_for_single_variants.rs:34:9 | +LL | _ => {}, + | ^ help: try this: `Foo::C` + +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:44:9 + | LL | _ => {}, | ^ help: try this: `Color::Blue` -error: wildcard match will miss any future added variants - --> $DIR/match_wildcard_for_single_variants.rs:42:9 +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:52:9 | LL | _ => {}, | ^ help: try this: `Color::Blue` -error: wildcard match will miss any future added variants - --> $DIR/match_wildcard_for_single_variants.rs:48:9 +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:58:9 | LL | _ => {}, | ^ help: try this: `Color::Blue` -error: aborting due to 4 previous errors +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:75:9 + | +LL | &_ => (), + | ^^ help: try this: `Color::Blue` + +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:84:9 + | +LL | _ => (), + | ^ help: try this: `C::Blue` + +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:91:9 + | +LL | _ => (), + | ^ help: try this: `Color::Blue` + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/mem_replace.fixed b/src/tools/clippy/tests/ui/mem_replace.fixed index 54e962e711..3b6224254a 100644 --- a/src/tools/clippy/tests/ui/mem_replace.fixed +++ b/src/tools/clippy/tests/ui/mem_replace.fixed @@ -7,6 +7,7 @@ clippy::mem_replace_with_default )] +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; use std::mem; fn replace_option_with_none() { @@ -19,9 +20,37 @@ fn replace_option_with_none() { fn replace_with_default() { let mut s = String::from("foo"); let _ = std::mem::take(&mut s); + let s = &mut String::from("foo"); let _ = std::mem::take(s); let _ = std::mem::take(s); + + let mut v = vec![123]; + let _ = std::mem::take(&mut v); + let _ = std::mem::take(&mut v); + let _ = std::mem::take(&mut v); + let _ = std::mem::take(&mut v); + + let mut hash_map: HashMap<i32, i32> = HashMap::new(); + let _ = std::mem::take(&mut hash_map); + + let mut btree_map: BTreeMap<i32, i32> = BTreeMap::new(); + let _ = std::mem::take(&mut btree_map); + + let mut vd: VecDeque<i32> = VecDeque::new(); + let _ = std::mem::take(&mut vd); + + let mut hash_set: HashSet<&str> = HashSet::new(); + let _ = std::mem::take(&mut hash_set); + + let mut btree_set: BTreeSet<&str> = BTreeSet::new(); + let _ = std::mem::take(&mut btree_set); + + let mut list: LinkedList<i32> = LinkedList::new(); + let _ = std::mem::take(&mut list); + + let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new(); + let _ = std::mem::take(&mut binary_heap); } fn main() { diff --git a/src/tools/clippy/tests/ui/mem_replace.rs b/src/tools/clippy/tests/ui/mem_replace.rs index 60f5278107..0a36db9e92 100644 --- a/src/tools/clippy/tests/ui/mem_replace.rs +++ b/src/tools/clippy/tests/ui/mem_replace.rs @@ -7,6 +7,7 @@ clippy::mem_replace_with_default )] +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; use std::mem; fn replace_option_with_none() { @@ -19,9 +20,37 @@ fn replace_option_with_none() { fn replace_with_default() { let mut s = String::from("foo"); let _ = std::mem::replace(&mut s, String::default()); + let s = &mut String::from("foo"); let _ = std::mem::replace(s, String::default()); let _ = std::mem::replace(s, Default::default()); + + let mut v = vec![123]; + let _ = std::mem::replace(&mut v, Vec::default()); + let _ = std::mem::replace(&mut v, Default::default()); + let _ = std::mem::replace(&mut v, Vec::new()); + let _ = std::mem::replace(&mut v, vec![]); + + let mut hash_map: HashMap<i32, i32> = HashMap::new(); + let _ = std::mem::replace(&mut hash_map, HashMap::new()); + + let mut btree_map: BTreeMap<i32, i32> = BTreeMap::new(); + let _ = std::mem::replace(&mut btree_map, BTreeMap::new()); + + let mut vd: VecDeque<i32> = VecDeque::new(); + let _ = std::mem::replace(&mut vd, VecDeque::new()); + + let mut hash_set: HashSet<&str> = HashSet::new(); + let _ = std::mem::replace(&mut hash_set, HashSet::new()); + + let mut btree_set: BTreeSet<&str> = BTreeSet::new(); + let _ = std::mem::replace(&mut btree_set, BTreeSet::new()); + + let mut list: LinkedList<i32> = LinkedList::new(); + let _ = std::mem::replace(&mut list, LinkedList::new()); + + let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new(); + let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new()); } fn main() { diff --git a/src/tools/clippy/tests/ui/mem_replace.stderr b/src/tools/clippy/tests/ui/mem_replace.stderr index 245d33aa4f..f8aa1538bf 100644 --- a/src/tools/clippy/tests/ui/mem_replace.stderr +++ b/src/tools/clippy/tests/ui/mem_replace.stderr @@ -1,5 +1,5 @@ error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:14:13 + --> $DIR/mem_replace.rs:15:13 | LL | let _ = mem::replace(&mut an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` @@ -7,13 +7,13 @@ LL | let _ = mem::replace(&mut an_option, None); = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:16:13 + --> $DIR/mem_replace.rs:17:13 | LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:21:13 + --> $DIR/mem_replace.rs:22:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` @@ -21,16 +21,82 @@ LL | let _ = std::mem::replace(&mut s, String::default()); = note: `-D clippy::mem-replace-with-default` implied by `-D warnings` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:23:13 + --> $DIR/mem_replace.rs:25:13 | LL | let _ = std::mem::replace(s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:24:13 + --> $DIR/mem_replace.rs:26:13 | LL | let _ = std::mem::replace(s, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` -error: aborting due to 5 previous errors +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:29:13 + | +LL | let _ = std::mem::replace(&mut v, Vec::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:30:13 + | +LL | let _ = std::mem::replace(&mut v, Default::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:31:13 + | +LL | let _ = std::mem::replace(&mut v, Vec::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:32:13 + | +LL | let _ = std::mem::replace(&mut v, vec![]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:35:13 + | +LL | let _ = std::mem::replace(&mut hash_map, HashMap::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:38:13 + | +LL | let _ = std::mem::replace(&mut btree_map, BTreeMap::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:41:13 + | +LL | let _ = std::mem::replace(&mut vd, VecDeque::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:44:13 + | +LL | let _ = std::mem::replace(&mut hash_set, HashSet::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:47:13 + | +LL | let _ = std::mem::replace(&mut btree_set, BTreeSet::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:50:13 + | +LL | let _ = std::mem::replace(&mut list, LinkedList::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:53:13 + | +LL | let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)` + +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs index 0f47f1cbc4..7f9f7ddc53 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_attr.rs +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs @@ -4,6 +4,10 @@ use std::ops::{Deref, RangeFrom}; +fn cloned_instead_of_copied() { + let _ = [1].iter().cloned(); +} + fn option_as_ref_deref() { let mut opt = Some(String::from("123")); @@ -123,6 +127,11 @@ fn missing_const_for_fn() -> i32 { 1 } +fn unnest_or_patterns() { + struct TS(u8, u8); + if let TS(0, x) | TS(1, x) = TS(0, 0) {} +} + fn main() { filter_map_next(); checked_conversion(); @@ -138,6 +147,7 @@ fn main() { replace_with_default(); map_unwrap_or(); missing_const_for_fn(); + unnest_or_patterns(); } mod meets_msrv { diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr index e3e3b335cb..ddb1e1f372 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr +++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr @@ -1,12 +1,12 @@ error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:150:24 + --> $DIR/min_rust_version_attr.rs:160:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::manual-strip` implied by `-D warnings` note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:149:9 + --> $DIR/min_rust_version_attr.rs:159:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,13 +17,13 @@ LL | assert_eq!(<stripped>.to_uppercase(), "WORLD!"); | error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:162:24 + --> $DIR/min_rust_version_attr.rs:172:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:161:9 + --> $DIR/min_rust_version_attr.rs:171:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs new file mode 100644 index 0000000000..7b9dc76b8f --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs @@ -0,0 +1,8 @@ +// This file provides a const function that is unstably const forever. + +#![feature(staged_api)] +#![stable(feature = "1", since = "1.0.0")] + +#[stable(feature = "1", since = "1.0.0")] +#[rustc_const_unstable(feature = "foo", issue = "none")] +pub const fn unstably_const_fn() {} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs index ba352ef9ee..7cda1aaa3c 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -2,9 +2,14 @@ //! compilation error. //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. +// aux-build:helper.rs + #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features)] #![feature(start, const_generics)] +#![feature(custom_inner_attributes)] + +extern crate helper; struct Game; @@ -101,3 +106,17 @@ fn const_generic_return<T, const N: usize>(t: &[T]) -> &[T; N] { unsafe { &*p } } + +// Do not lint this because it calls a function whose constness is unstable. +fn unstably_const_fn() { + helper::unstably_const_fn() +} + +mod const_fn_stabilized_after_msrv { + #![clippy::msrv = "1.46.0"] + + // Do not lint this because `u8::is_ascii_digit` is stabilized as a const function in 1.47.0. + fn const_fn_stabilized_after_msrv(byte: u8) { + byte.is_ascii_digit(); + } +} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs index c6f44b7daa..0accb516f5 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,6 +1,7 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return)] #![feature(const_generics)] +#![feature(custom_inner_attributes)] use std::mem::transmute; @@ -70,5 +71,14 @@ mod with_drop { } } +mod const_fn_stabilized_before_msrv { + #![clippy::msrv = "1.47.0"] + + // This could be const because `u8::is_ascii_digit` is a stable const function in 1.47. + fn const_fn_stabilized_before_msrv(byte: u8) { + byte.is_ascii_digit(); + } +} + // Should not be const fn main() {} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr index 74d32b8a1a..63c211f39f 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> $DIR/could_be_const.rs:13:5 + --> $DIR/could_be_const.rs:14:5 | LL | / pub fn new() -> Self { LL | | Self { guess: 42 } @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` error: this could be a `const fn` - --> $DIR/could_be_const.rs:17:5 + --> $DIR/could_be_const.rs:18:5 | LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { LL | | b @@ -17,7 +17,7 @@ LL | | } | |_____^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:23:1 + --> $DIR/could_be_const.rs:24:1 | LL | / fn one() -> i32 { LL | | 1 @@ -25,7 +25,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:28:1 + --> $DIR/could_be_const.rs:29:1 | LL | / fn two() -> i32 { LL | | let abc = 2; @@ -34,7 +34,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:34:1 + --> $DIR/could_be_const.rs:35:1 | LL | / fn string() -> String { LL | | String::new() @@ -42,7 +42,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:39:1 + --> $DIR/could_be_const.rs:40:1 | LL | / unsafe fn four() -> i32 { LL | | 4 @@ -50,7 +50,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:44:1 + --> $DIR/could_be_const.rs:45:1 | LL | / fn generic<T>(t: T) -> T { LL | | t @@ -58,12 +58,20 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:67:9 + --> $DIR/could_be_const.rs:68:9 | LL | / pub fn b(self, a: &A) -> B { LL | | B LL | | } | |_________^ -error: aborting due to 8 previous errors +error: this could be a `const fn` + --> $DIR/could_be_const.rs:78:5 + | +LL | / fn const_fn_stabilized_before_msrv(byte: u8) { +LL | | byte.is_ascii_digit(); +LL | | } + | |_____^ + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/doc_panics.rs b/src/tools/clippy/tests/ui/missing_panics_doc.rs similarity index 74% rename from src/tools/clippy/tests/ui/doc_panics.rs rename to src/tools/clippy/tests/ui/missing_panics_doc.rs index 17e72353f8..2e1379a58a 100644 --- a/src/tools/clippy/tests/ui/doc_panics.rs +++ b/src/tools/clippy/tests/ui/missing_panics_doc.rs @@ -33,6 +33,18 @@ pub fn unreachable_and_panic() { if true { unreachable!() } else { panic!() } } +/// This needs to be documented +pub fn assert_eq() { + let x = 0; + assert_eq!(x, 0); +} + +/// This needs to be documented +pub fn assert_ne() { + let x = 0; + assert_ne!(x, 0); +} + /// This is documented /// /// # Panics @@ -83,6 +95,26 @@ pub fn unreachable_amd_panic_documented() { if true { unreachable!() } else { panic!() } } +/// This is documented +/// +/// # Panics +/// +/// Panics if `x` is not 0. +pub fn assert_eq_documented() { + let x = 0; + assert_eq!(x, 0); +} + +/// This is documented +/// +/// # Panics +/// +/// Panics if `x` is 0. +pub fn assert_ne_documented() { + let x = 0; + assert_ne!(x, 0); +} + /// This is okay because it is private fn unwrap_private() { let result = Err("Hi"); @@ -112,3 +144,11 @@ fn inner_body_private(opt: Option<u32>) { pub fn unreachable() { unreachable!("This function panics") } + +/// #6970. +/// This is okay because it is expansion of `debug_assert` family. +pub fn debug_assertions() { + debug_assert!(false); + debug_assert_eq!(1, 2); + debug_assert_ne!(1, 2); +} diff --git a/src/tools/clippy/tests/ui/doc_panics.stderr b/src/tools/clippy/tests/ui/missing_panics_doc.stderr similarity index 59% rename from src/tools/clippy/tests/ui/doc_panics.stderr rename to src/tools/clippy/tests/ui/missing_panics_doc.stderr index 2fa88a2f6e..ba96a6a12b 100644 --- a/src/tools/clippy/tests/ui/doc_panics.stderr +++ b/src/tools/clippy/tests/ui/missing_panics_doc.stderr @@ -1,5 +1,5 @@ error: docs for function which may panic missing `# Panics` section - --> $DIR/doc_panics.rs:7:1 + --> $DIR/missing_panics_doc.rs:7:1 | LL | / pub fn unwrap() { LL | | let result = Err("Hi"); @@ -9,13 +9,13 @@ LL | | } | = note: `-D clippy::missing-panics-doc` implied by `-D warnings` note: first possible panic found here - --> $DIR/doc_panics.rs:9:5 + --> $DIR/missing_panics_doc.rs:9:5 | LL | result.unwrap() | ^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/doc_panics.rs:13:1 + --> $DIR/missing_panics_doc.rs:13:1 | LL | / pub fn panic() { LL | | panic!("This function panics") @@ -23,14 +23,14 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/doc_panics.rs:14:5 + --> $DIR/missing_panics_doc.rs:14:5 | LL | panic!("This function panics") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: docs for function which may panic missing `# Panics` section - --> $DIR/doc_panics.rs:18:1 + --> $DIR/missing_panics_doc.rs:18:1 | LL | / pub fn todo() { LL | | todo!() @@ -38,14 +38,14 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/doc_panics.rs:19:5 + --> $DIR/missing_panics_doc.rs:19:5 | LL | todo!() | ^^^^^^^ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: docs for function which may panic missing `# Panics` section - --> $DIR/doc_panics.rs:23:1 + --> $DIR/missing_panics_doc.rs:23:1 | LL | / pub fn inner_body(opt: Option<u32>) { LL | | opt.map(|x| { @@ -57,14 +57,14 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/doc_panics.rs:26:13 + --> $DIR/missing_panics_doc.rs:26:13 | LL | panic!() | ^^^^^^^^ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: docs for function which may panic missing `# Panics` section - --> $DIR/doc_panics.rs:32:1 + --> $DIR/missing_panics_doc.rs:32:1 | LL | / pub fn unreachable_and_panic() { LL | | if true { unreachable!() } else { panic!() } @@ -72,11 +72,43 @@ LL | | } | |_^ | note: first possible panic found here - --> $DIR/doc_panics.rs:33:39 + --> $DIR/missing_panics_doc.rs:33:39 | LL | if true { unreachable!() } else { panic!() } | ^^^^^^^^ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:37:1 + | +LL | / pub fn assert_eq() { +LL | | let x = 0; +LL | | assert_eq!(x, 0); +LL | | } + | |_^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:39:5 + | +LL | assert_eq!(x, 0); + | ^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:43:1 + | +LL | / pub fn assert_ne() { +LL | | let x = 0; +LL | | assert_ne!(x, 0); +LL | | } + | |_^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:45:5 + | +LL | assert_ne!(x, 0); + | ^^^^^^^^^^^^^^^^^ + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/needless_bool/simple.rs b/src/tools/clippy/tests/ui/needless_bool/simple.rs index e9f1428fc3..588bb88f44 100644 --- a/src/tools/clippy/tests/ui/needless_bool/simple.rs +++ b/src/tools/clippy/tests/ui/needless_bool/simple.rs @@ -4,7 +4,8 @@ dead_code, clippy::no_effect, clippy::if_same_then_else, - clippy::needless_return + clippy::needless_return, + clippy::branches_sharing_code )] fn main() { diff --git a/src/tools/clippy/tests/ui/needless_bool/simple.stderr b/src/tools/clippy/tests/ui/needless_bool/simple.stderr index c57a8a042f..0ccc9416bc 100644 --- a/src/tools/clippy/tests/ui/needless_bool/simple.stderr +++ b/src/tools/clippy/tests/ui/needless_bool/simple.stderr @@ -1,5 +1,5 @@ error: this if-then-else expression will always return true - --> $DIR/simple.rs:13:5 + --> $DIR/simple.rs:14: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 will always return false - --> $DIR/simple.rs:18:5 + --> $DIR/simple.rs:19:5 | LL | / if x { LL | | false @@ -21,7 +21,7 @@ LL | | }; | |_____^ error: this if-then-else expression will always return true - --> $DIR/simple.rs:33:5 + --> $DIR/simple.rs:34:5 | LL | / if x { LL | | return true; @@ -31,7 +31,7 @@ LL | | }; | |_____^ error: this if-then-else expression will always return false - --> $DIR/simple.rs:41:5 + --> $DIR/simple.rs:42:5 | LL | / if x { LL | | return false; diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr index 76e789d905..c773b841f3 100644 --- a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr +++ b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr @@ -1,9 +1,10 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:5:5 + --> $DIR/needless_collect_indirect.rs:5:39 | -LL | / let indirect_iter = sample.iter().collect::<Vec<_>>(); -LL | | indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); - | |____^ +LL | let indirect_iter = sample.iter().collect::<Vec<_>>(); + | ^^^^^^^ +LL | indirect_iter.into_iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); + | ------------------------- the iterator could be used here instead | = note: `-D clippy::needless-collect` implied by `-D warnings` help: use the original Iterator instead of collecting it and then producing a new one @@ -13,11 +14,12 @@ LL | sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:7:5 + --> $DIR/needless_collect_indirect.rs:7:38 | -LL | / let indirect_len = sample.iter().collect::<VecDeque<_>>(); -LL | | indirect_len.len(); - | |____^ +LL | let indirect_len = sample.iter().collect::<VecDeque<_>>(); + | ^^^^^^^ +LL | indirect_len.len(); + | ------------------ the iterator could be used here instead | help: take the original Iterator's count instead of collecting it and finding the length | @@ -26,11 +28,12 @@ LL | sample.iter().count(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:9:5 + --> $DIR/needless_collect_indirect.rs:9:40 | -LL | / let indirect_empty = sample.iter().collect::<VecDeque<_>>(); -LL | | indirect_empty.is_empty(); - | |____^ +LL | let indirect_empty = sample.iter().collect::<VecDeque<_>>(); + | ^^^^^^^ +LL | indirect_empty.is_empty(); + | ------------------------- the iterator could be used here instead | help: check if the original Iterator has anything instead of collecting it and seeing if it's empty | @@ -39,11 +42,12 @@ LL | sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:11:5 + --> $DIR/needless_collect_indirect.rs:11:43 | -LL | / let indirect_contains = sample.iter().collect::<VecDeque<_>>(); -LL | | indirect_contains.contains(&&5); - | |____^ +LL | let indirect_contains = sample.iter().collect::<VecDeque<_>>(); + | ^^^^^^^ +LL | indirect_contains.contains(&&5); + | ------------------------------- the iterator could be used here instead | help: check if the original Iterator contains an element instead of collecting then checking | @@ -52,11 +56,12 @@ LL | sample.iter().any(|x| x == &5); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:23:5 + --> $DIR/needless_collect_indirect.rs:23:48 | -LL | / let non_copy_contains = sample.into_iter().collect::<Vec<_>>(); -LL | | non_copy_contains.contains(&a); - | |____^ +LL | let non_copy_contains = sample.into_iter().collect::<Vec<_>>(); + | ^^^^^^^ +LL | non_copy_contains.contains(&a); + | ------------------------------ the iterator could be used here instead | help: check if the original Iterator contains an element instead of collecting then checking | diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed new file mode 100644 index 0000000000..f00f9ee4c3 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed @@ -0,0 +1,113 @@ +// run-rustfix +#![warn(clippy::needless_for_each)] +#![allow(unused, clippy::needless_return, clippy::match_single_binding)] + +use std::collections::HashMap; + +fn should_lint() { + let v: Vec<i32> = Vec::new(); + let mut acc = 0; + for elem in v.iter() { + acc += elem; + } + for elem in v.into_iter() { + acc += elem; + } + + for elem in [1, 2, 3].iter() { + acc += elem; + } + + let mut hash_map: HashMap<i32, i32> = HashMap::new(); + for (k, v) in hash_map.iter() { + acc += k + v; + } + for (k, v) in hash_map.iter_mut() { + acc += *k + *v; + } + for k in hash_map.keys() { + acc += k; + } + for v in hash_map.values() { + acc += v; + } + + fn my_vec() -> Vec<i32> { + Vec::new() + } + for elem in my_vec().iter() { + acc += elem; + } +} + +fn should_not_lint() { + let v: Vec<i32> = Vec::new(); + let mut acc = 0; + + // `for_each` argument is not closure. + fn print(x: &i32) { + println!("{}", x); + } + v.iter().for_each(print); + + // User defined type. + struct MyStruct { + v: Vec<i32>, + } + impl MyStruct { + fn iter(&self) -> impl Iterator<Item = &i32> { + self.v.iter() + } + } + let s = MyStruct { v: Vec::new() }; + s.iter().for_each(|elem| { + acc += elem; + }); + + // `for_each` follows long iterator chain. + v.iter().chain(v.iter()).for_each(|v| { + acc += v; + }); + v.as_slice().iter().for_each(|v| { + acc += v; + }); + s.v.iter().for_each(|v| { + acc += v; + }); + + // `return` is used in `Loop` of the closure. + v.iter().for_each(|v| { + for i in 0..*v { + if i == 10 { + return; + } else { + println!("{}", v); + } + } + if *v == 20 { + return; + } else { + println!("{}", v); + } + }); + + // Previously transformed iterator variable. + let it = v.iter(); + it.chain(v.iter()).for_each(|elem| { + acc += elem; + }); + + // `for_each` is not directly in a statement. + match 1 { + _ => v.iter().for_each(|elem| { + acc += elem; + }), + } + + // `for_each` is in a let bingind. + let _ = v.iter().for_each(|elem| { + acc += elem; + }); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs new file mode 100644 index 0000000000..1bd400d348 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs @@ -0,0 +1,113 @@ +// run-rustfix +#![warn(clippy::needless_for_each)] +#![allow(unused, clippy::needless_return, clippy::match_single_binding)] + +use std::collections::HashMap; + +fn should_lint() { + let v: Vec<i32> = Vec::new(); + let mut acc = 0; + v.iter().for_each(|elem| { + acc += elem; + }); + v.into_iter().for_each(|elem| { + acc += elem; + }); + + [1, 2, 3].iter().for_each(|elem| { + acc += elem; + }); + + let mut hash_map: HashMap<i32, i32> = HashMap::new(); + hash_map.iter().for_each(|(k, v)| { + acc += k + v; + }); + hash_map.iter_mut().for_each(|(k, v)| { + acc += *k + *v; + }); + hash_map.keys().for_each(|k| { + acc += k; + }); + hash_map.values().for_each(|v| { + acc += v; + }); + + fn my_vec() -> Vec<i32> { + Vec::new() + } + my_vec().iter().for_each(|elem| { + acc += elem; + }); +} + +fn should_not_lint() { + let v: Vec<i32> = Vec::new(); + let mut acc = 0; + + // `for_each` argument is not closure. + fn print(x: &i32) { + println!("{}", x); + } + v.iter().for_each(print); + + // User defined type. + struct MyStruct { + v: Vec<i32>, + } + impl MyStruct { + fn iter(&self) -> impl Iterator<Item = &i32> { + self.v.iter() + } + } + let s = MyStruct { v: Vec::new() }; + s.iter().for_each(|elem| { + acc += elem; + }); + + // `for_each` follows long iterator chain. + v.iter().chain(v.iter()).for_each(|v| { + acc += v; + }); + v.as_slice().iter().for_each(|v| { + acc += v; + }); + s.v.iter().for_each(|v| { + acc += v; + }); + + // `return` is used in `Loop` of the closure. + v.iter().for_each(|v| { + for i in 0..*v { + if i == 10 { + return; + } else { + println!("{}", v); + } + } + if *v == 20 { + return; + } else { + println!("{}", v); + } + }); + + // Previously transformed iterator variable. + let it = v.iter(); + it.chain(v.iter()).for_each(|elem| { + acc += elem; + }); + + // `for_each` is not directly in a statement. + match 1 { + _ => v.iter().for_each(|elem| { + acc += elem; + }), + } + + // `for_each` is in a let bingind. + let _ = v.iter().for_each(|elem| { + acc += elem; + }); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr new file mode 100644 index 0000000000..483a5e6d61 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr @@ -0,0 +1,123 @@ +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:10:5 + | +LL | / v.iter().for_each(|elem| { +LL | | acc += elem; +LL | | }); + | |_______^ + | + = note: `-D clippy::needless-for-each` implied by `-D warnings` +help: try + | +LL | for elem in v.iter() { +LL | acc += elem; +LL | } + | + +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:13:5 + | +LL | / v.into_iter().for_each(|elem| { +LL | | acc += elem; +LL | | }); + | |_______^ + | +help: try + | +LL | for elem in v.into_iter() { +LL | acc += elem; +LL | } + | + +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:17:5 + | +LL | / [1, 2, 3].iter().for_each(|elem| { +LL | | acc += elem; +LL | | }); + | |_______^ + | +help: try + | +LL | for elem in [1, 2, 3].iter() { +LL | acc += elem; +LL | } + | + +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:22:5 + | +LL | / hash_map.iter().for_each(|(k, v)| { +LL | | acc += k + v; +LL | | }); + | |_______^ + | +help: try + | +LL | for (k, v) in hash_map.iter() { +LL | acc += k + v; +LL | } + | + +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:25:5 + | +LL | / hash_map.iter_mut().for_each(|(k, v)| { +LL | | acc += *k + *v; +LL | | }); + | |_______^ + | +help: try + | +LL | for (k, v) in hash_map.iter_mut() { +LL | acc += *k + *v; +LL | } + | + +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:28:5 + | +LL | / hash_map.keys().for_each(|k| { +LL | | acc += k; +LL | | }); + | |_______^ + | +help: try + | +LL | for k in hash_map.keys() { +LL | acc += k; +LL | } + | + +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:31:5 + | +LL | / hash_map.values().for_each(|v| { +LL | | acc += v; +LL | | }); + | |_______^ + | +help: try + | +LL | for v in hash_map.values() { +LL | acc += v; +LL | } + | + +error: needless use of `for_each` + --> $DIR/needless_for_each_fixable.rs:38:5 + | +LL | / my_vec().iter().for_each(|elem| { +LL | | acc += elem; +LL | | }); + | |_______^ + | +help: try + | +LL | for elem in my_vec().iter() { +LL | acc += elem; +LL | } + | + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui/needless_for_each_unfixable.rs b/src/tools/clippy/tests/ui/needless_for_each_unfixable.rs new file mode 100644 index 0000000000..d765d7dab6 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_for_each_unfixable.rs @@ -0,0 +1,14 @@ +#![warn(clippy::needless_for_each)] +#![allow(clippy::needless_return)] + +fn main() { + let v: Vec<i32> = Vec::new(); + // This is unfixable because the closure includes `return`. + v.iter().for_each(|v| { + if *v == 10 { + return; + } else { + println!("{}", v); + } + }); +} diff --git a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr new file mode 100644 index 0000000000..8c4507d232 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr @@ -0,0 +1,29 @@ +error: needless use of `for_each` + --> $DIR/needless_for_each_unfixable.rs:7:5 + | +LL | / v.iter().for_each(|v| { +LL | | if *v == 10 { +LL | | return; +LL | | } else { +LL | | println!("{}", v); +LL | | } +LL | | }); + | |_______^ + | + = note: `-D clippy::needless-for-each` implied by `-D warnings` +help: try + | +LL | for v in v.iter() { +LL | if *v == 10 { +LL | return; +LL | } else { +LL | println!("{}", v); +LL | } + ... +help: ...and replace `return` with `continue` + | +LL | continue; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/needless_question_mark.fixed b/src/tools/clippy/tests/ui/needless_question_mark.fixed index 71fb356522..52ddd9d2dc 100644 --- a/src/tools/clippy/tests/ui/needless_question_mark.fixed +++ b/src/tools/clippy/tests/ui/needless_question_mark.fixed @@ -96,74 +96,27 @@ where fn main() {} -mod question_mark_none { - #![clippy::msrv = "1.12.0"] - fn needless_question_mark_option() -> Option<usize> { - struct TO { - magic: Option<usize>, - } - let to = TO { magic: None }; - Some(to.magic?) // should not be triggered - } - - fn needless_question_mark_result() -> Result<usize, bool> { - struct TO { - magic: Result<usize, bool>, - } - let to = TO { magic: Ok(1_usize) }; - Ok(to.magic?) // should not be triggered - } - - fn main() { - needless_question_mark_option(); - needless_question_mark_result(); - } +// #6921 if a macro wraps an expr in Some( ) and the ? is in the macro use, +// the suggestion fails to apply; do not lint +macro_rules! some_in_macro { + ($expr:expr) => { + || -> _ { Some($expr) }() + }; } -mod question_mark_result { - #![clippy::msrv = "1.21.0"] - fn needless_question_mark_option() -> Option<usize> { - struct TO { - magic: Option<usize>, - } - let to = TO { magic: None }; - Some(to.magic?) // should not be triggered - } - - fn needless_question_mark_result() -> Result<usize, bool> { - struct TO { - magic: Result<usize, bool>, - } - let to = TO { magic: Ok(1_usize) }; - to.magic // should be triggered - } - - fn main() { - needless_question_mark_option(); - needless_question_mark_result(); - } +pub fn test1() { + let x = Some(3); + let _x = some_in_macro!(x?); } -mod question_mark_both { - #![clippy::msrv = "1.22.0"] - fn needless_question_mark_option() -> Option<usize> { - struct TO { - magic: Option<usize>, - } - let to = TO { magic: None }; - to.magic // should be triggered - } - - fn needless_question_mark_result() -> Result<usize, bool> { - struct TO { - magic: Result<usize, bool>, - } - let to = TO { magic: Ok(1_usize) }; - to.magic // should be triggered - } +// this one is ok because both the ? and the Some are both inside the macro def +macro_rules! some_and_qmark_in_macro { + ($expr:expr) => { + || -> Option<_> { Some($expr) }() + }; +} - fn main() { - needless_question_mark_option(); - needless_question_mark_result(); - } +pub fn test2() { + let x = Some(3); + let _x = some_and_qmark_in_macro!(x?); } diff --git a/src/tools/clippy/tests/ui/needless_question_mark.rs b/src/tools/clippy/tests/ui/needless_question_mark.rs index e31f6f48fa..1ea4ba0d83 100644 --- a/src/tools/clippy/tests/ui/needless_question_mark.rs +++ b/src/tools/clippy/tests/ui/needless_question_mark.rs @@ -96,74 +96,27 @@ where fn main() {} -mod question_mark_none { - #![clippy::msrv = "1.12.0"] - fn needless_question_mark_option() -> Option<usize> { - struct TO { - magic: Option<usize>, - } - let to = TO { magic: None }; - Some(to.magic?) // should not be triggered - } - - fn needless_question_mark_result() -> Result<usize, bool> { - struct TO { - magic: Result<usize, bool>, - } - let to = TO { magic: Ok(1_usize) }; - Ok(to.magic?) // should not be triggered - } - - fn main() { - needless_question_mark_option(); - needless_question_mark_result(); - } +// #6921 if a macro wraps an expr in Some( ) and the ? is in the macro use, +// the suggestion fails to apply; do not lint +macro_rules! some_in_macro { + ($expr:expr) => { + || -> _ { Some($expr) }() + }; } -mod question_mark_result { - #![clippy::msrv = "1.21.0"] - fn needless_question_mark_option() -> Option<usize> { - struct TO { - magic: Option<usize>, - } - let to = TO { magic: None }; - Some(to.magic?) // should not be triggered - } - - fn needless_question_mark_result() -> Result<usize, bool> { - struct TO { - magic: Result<usize, bool>, - } - let to = TO { magic: Ok(1_usize) }; - Ok(to.magic?) // should be triggered - } - - fn main() { - needless_question_mark_option(); - needless_question_mark_result(); - } +pub fn test1() { + let x = Some(3); + let _x = some_in_macro!(x?); } -mod question_mark_both { - #![clippy::msrv = "1.22.0"] - fn needless_question_mark_option() -> Option<usize> { - struct TO { - magic: Option<usize>, - } - let to = TO { magic: None }; - Some(to.magic?) // should be triggered - } - - fn needless_question_mark_result() -> Result<usize, bool> { - struct TO { - magic: Result<usize, bool>, - } - let to = TO { magic: Ok(1_usize) }; - Ok(to.magic?) // should be triggered - } +// this one is ok because both the ? and the Some are both inside the macro def +macro_rules! some_and_qmark_in_macro { + ($expr:expr) => { + || -> Option<_> { Some(Some($expr)?) }() + }; +} - fn main() { - needless_question_mark_option(); - needless_question_mark_result(); - } +pub fn test2() { + let x = Some(3); + let _x = some_and_qmark_in_macro!(x?); } diff --git a/src/tools/clippy/tests/ui/needless_question_mark.stderr b/src/tools/clippy/tests/ui/needless_question_mark.stderr index 983c56031d..afd68d91e5 100644 --- a/src/tools/clippy/tests/ui/needless_question_mark.stderr +++ b/src/tools/clippy/tests/ui/needless_question_mark.stderr @@ -67,22 +67,15 @@ LL | return Ok(t.magic?); | ^^^^^^^^^^^^ help: try: `t.magic` error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:138:9 + --> $DIR/needless_question_mark.rs:115:27 | -LL | Ok(to.magic?) // should be triggered - | ^^^^^^^^^^^^^ help: try: `to.magic` - -error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:154:9 - | -LL | Some(to.magic?) // should be triggered - | ^^^^^^^^^^^^^^^ help: try: `to.magic` - -error: question mark operator is useless here - --> $DIR/needless_question_mark.rs:162:9 +LL | || -> Option<_> { Some(Some($expr)?) }() + | ^^^^^^^^^^^^^^^^^^ help: try: `Some($expr)` +... +LL | let _x = some_and_qmark_in_macro!(x?); + | ---------------------------- in this macro invocation | -LL | Ok(to.magic?) // should be triggered - | ^^^^^^^^^^^^^ help: try: `to.magic` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 14 previous errors +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index 990475fcb5..5c4fd466c0 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,7 +1,13 @@ // run-rustfix - -#![allow(unused, clippy::needless_bool)] -#![allow(clippy::if_same_then_else, clippy::single_match)] +// edition:2018 + +#![allow(unused)] +#![allow( + clippy::if_same_then_else, + clippy::single_match, + clippy::branches_sharing_code, + clippy::needless_bool +)] #![warn(clippy::needless_return)] macro_rules! the_answer { @@ -120,10 +126,85 @@ mod issue6501 { } } -fn main() { - let _ = test_end_of_fn(); - let _ = test_no_semicolon(); - let _ = test_if_block(); - let _ = test_match(true); - test_closure(); +async fn async_test_end_of_fn() -> bool { + if true { + // no error! + return true; + } + true +} + +async fn async_test_no_semicolon() -> bool { + true +} + +async fn async_test_if_block() -> bool { + if true { + true + } else { + false + } } + +async fn async_test_match(x: bool) -> bool { + match x { + true => false, + false => { + true + }, + } +} + +async fn async_test_closure() { + let _ = || { + true + }; + let _ = || true; +} + +async fn async_test_macro_call() -> i32 { + return the_answer!(); +} + +async fn async_test_void_fun() { + +} + +async fn async_test_void_if_fun(b: bool) { + if b { + + } else { + + } +} + +async fn async_test_void_match(x: u32) { + match x { + 0 => (), + _ => {}, + } +} + +async fn async_read_line() -> String { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + return stdin.lock().lines().next().unwrap().unwrap(); +} + +async fn async_borrows_but_not_last(value: bool) -> String { + if value { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + let _a = stdin.lock().lines().next().unwrap().unwrap(); + String::from("test") + } else { + String::new() + } +} + +async fn async_test_return_in_macro() { + needed_return!(10); + needed_return!(0); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index dec3d84a02..34811db741 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,7 +1,13 @@ // run-rustfix - -#![allow(unused, clippy::needless_bool)] -#![allow(clippy::if_same_then_else, clippy::single_match)] +// edition:2018 + +#![allow(unused)] +#![allow( + clippy::if_same_then_else, + clippy::single_match, + clippy::branches_sharing_code, + clippy::needless_bool +)] #![warn(clippy::needless_return)] macro_rules! the_answer { @@ -120,10 +126,85 @@ mod issue6501 { } } -fn main() { - let _ = test_end_of_fn(); - let _ = test_no_semicolon(); - let _ = test_if_block(); - let _ = test_match(true); - test_closure(); +async fn async_test_end_of_fn() -> bool { + if true { + // no error! + return true; + } + return true; +} + +async fn async_test_no_semicolon() -> bool { + return true; +} + +async fn async_test_if_block() -> bool { + if true { + return true; + } else { + return false; + } } + +async fn async_test_match(x: bool) -> bool { + match x { + true => return false, + false => { + return true; + }, + } +} + +async fn async_test_closure() { + let _ = || { + return true; + }; + let _ = || return true; +} + +async fn async_test_macro_call() -> i32 { + return the_answer!(); +} + +async fn async_test_void_fun() { + return; +} + +async fn async_test_void_if_fun(b: bool) { + if b { + return; + } else { + return; + } +} + +async fn async_test_void_match(x: u32) { + match x { + 0 => (), + _ => return, + } +} + +async fn async_read_line() -> String { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + return stdin.lock().lines().next().unwrap().unwrap(); +} + +async fn async_borrows_but_not_last(value: bool) -> String { + if value { + use std::io::BufRead; + let stdin = ::std::io::stdin(); + let _a = stdin.lock().lines().next().unwrap().unwrap(); + return String::from("test"); + } else { + return String::new(); + } +} + +async fn async_test_return_in_macro() { + needed_return!(10); + needed_return!(0); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index ae31d60754..74dda971fd 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> $DIR/needless_return.rs:18:5 + --> $DIR/needless_return.rs:24:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` @@ -7,106 +7,190 @@ LL | return true; = note: `-D clippy::needless-return` implied by `-D warnings` error: unneeded `return` statement - --> $DIR/needless_return.rs:22:5 + --> $DIR/needless_return.rs:28:5 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:27:9 + --> $DIR/needless_return.rs:33:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:29:9 + --> $DIR/needless_return.rs:35:9 | LL | return false; | ^^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:35:17 + --> $DIR/needless_return.rs:41:17 | LL | true => return false, | ^^^^^^^^^^^^ help: remove `return`: `false` error: unneeded `return` statement - --> $DIR/needless_return.rs:37:13 + --> $DIR/needless_return.rs:43:13 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:44:9 + --> $DIR/needless_return.rs:50:9 | LL | return true; | ^^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:46:16 + --> $DIR/needless_return.rs:52:16 | LL | let _ = || return true; | ^^^^^^^^^^^ help: remove `return`: `true` error: unneeded `return` statement - --> $DIR/needless_return.rs:54:5 + --> $DIR/needless_return.rs:60:5 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:59:9 + --> $DIR/needless_return.rs:65:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:61:9 + --> $DIR/needless_return.rs:67:9 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:68:14 + --> $DIR/needless_return.rs:74:14 | LL | _ => return, | ^^^^^^ help: replace `return` with an empty block: `{}` error: unneeded `return` statement - --> $DIR/needless_return.rs:83:9 + --> $DIR/needless_return.rs:89:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")` error: unneeded `return` statement - --> $DIR/needless_return.rs:85:9 + --> $DIR/needless_return.rs:91:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` error: unneeded `return` statement - --> $DIR/needless_return.rs:106:32 + --> $DIR/needless_return.rs:112:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ help: replace `return` with an empty block: `{}` error: unneeded `return` statement - --> $DIR/needless_return.rs:111:13 + --> $DIR/needless_return.rs:117:13 | LL | return; | ^^^^^^^ help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:113:20 + --> $DIR/needless_return.rs:119:20 | LL | let _ = || return; | ^^^^^^ help: replace `return` with an empty block: `{}` error: unneeded `return` statement - --> $DIR/needless_return.rs:119:32 + --> $DIR/needless_return.rs:125:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ help: remove `return`: `Foo` -error: aborting due to 18 previous errors +error: unneeded `return` statement + --> $DIR/needless_return.rs:134:5 + | +LL | return true; + | ^^^^^^^^^^^^ help: remove `return`: `true` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:138:5 + | +LL | return true; + | ^^^^^^^^^^^^ help: remove `return`: `true` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:143:9 + | +LL | return true; + | ^^^^^^^^^^^^ help: remove `return`: `true` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:145:9 + | +LL | return false; + | ^^^^^^^^^^^^^ help: remove `return`: `false` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:151:17 + | +LL | true => return false, + | ^^^^^^^^^^^^ help: remove `return`: `false` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:153:13 + | +LL | return true; + | ^^^^^^^^^^^^ help: remove `return`: `true` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:160:9 + | +LL | return true; + | ^^^^^^^^^^^^ help: remove `return`: `true` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:162:16 + | +LL | let _ = || return true; + | ^^^^^^^^^^^ help: remove `return`: `true` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:170:5 + | +LL | return; + | ^^^^^^^ help: remove `return` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:175:9 + | +LL | return; + | ^^^^^^^ help: remove `return` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:177:9 + | +LL | return; + | ^^^^^^^ help: remove `return` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:184:14 + | +LL | _ => return, + | ^^^^^^ help: replace `return` with an empty block: `{}` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:199:9 + | +LL | return String::from("test"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")` + +error: unneeded `return` statement + --> $DIR/needless_return.rs:201:9 + | +LL | return String::new(); + | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()` + +error: aborting due to 32 previous errors diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.rs b/src/tools/clippy/tests/ui/new_ret_no_self.rs index e82873629a..2f315ffe29 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self.rs +++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs @@ -340,3 +340,13 @@ mod issue5435 { } } } + +// issue #1724 +struct RetOtherSelf<T>(T); +struct RetOtherSelfWrapper<T>(T); + +impl RetOtherSelf<T> { + fn new(t: T) -> RetOtherSelf<RetOtherSelfWrapper<T>> { + RetOtherSelf(RetOtherSelfWrapper(t)) + } +} diff --git a/src/tools/clippy/tests/ui/new_without_default.rs b/src/tools/clippy/tests/ui/new_without_default.rs index 3b6041823d..64659b63f4 100644 --- a/src/tools/clippy/tests/ui/new_without_default.rs +++ b/src/tools/clippy/tests/ui/new_without_default.rs @@ -159,4 +159,19 @@ impl NewNotEqualToDerive { } } +// see #6933 +pub struct FooGenerics<T>(std::marker::PhantomData<T>); +impl<T> FooGenerics<T> { + pub fn new() -> Self { + Self(Default::default()) + } +} + +pub struct BarGenerics<T>(std::marker::PhantomData<T>); +impl<T: Copy> BarGenerics<T> { + pub fn new() -> Self { + Self(Default::default()) + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/new_without_default.stderr b/src/tools/clippy/tests/ui/new_without_default.stderr index e529e441eb..973836f75a 100644 --- a/src/tools/clippy/tests/ui/new_without_default.stderr +++ b/src/tools/clippy/tests/ui/new_without_default.stderr @@ -43,7 +43,7 @@ LL | | } | help: try this | -LL | impl Default for LtKo<'c> { +LL | impl<'c> Default for LtKo<'c> { LL | fn default() -> Self { LL | Self::new() LL | } @@ -67,5 +67,39 @@ LL | } LL | } | -error: aborting due to 4 previous errors +error: you should consider adding a `Default` implementation for `FooGenerics<T>` + --> $DIR/new_without_default.rs:165:5 + | +LL | / pub fn new() -> Self { +LL | | Self(Default::default()) +LL | | } + | |_____^ + | +help: try this + | +LL | impl<T> Default for FooGenerics<T> { +LL | fn default() -> Self { +LL | Self::new() +LL | } +LL | } + | + +error: you should consider adding a `Default` implementation for `BarGenerics<T>` + --> $DIR/new_without_default.rs:172:5 + | +LL | / pub fn new() -> Self { +LL | | Self(Default::default()) +LL | | } + | |_____^ + | +help: try this + | +LL | impl<T: Copy> Default for BarGenerics<T> { +LL | fn default() -> Self { +LL | Self::new() +LL | } +LL | } + | + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed new file mode 100644 index 0000000000..a9b2dcfb08 --- /dev/null +++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed @@ -0,0 +1,33 @@ +// ignore-windows +// run-rustfix +#![warn(clippy::non_octal_unix_permissions)] +use std::fs::{DirBuilder, File, OpenOptions, Permissions}; +use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt}; + +fn main() { + let permissions = 0o760; + + // OpenOptionsExt::mode + let mut options = OpenOptions::new(); + options.mode(0o440); + options.mode(0o400); + options.mode(permissions); + + // PermissionsExt::from_mode + let _permissions = Permissions::from_mode(0o647); + let _permissions = Permissions::from_mode(0o000); + let _permissions = Permissions::from_mode(permissions); + + // PermissionsExt::set_mode + let f = File::create("foo.txt").unwrap(); + let metadata = f.metadata().unwrap(); + let mut permissions = metadata.permissions(); + + permissions.set_mode(0o644); + permissions.set_mode(0o704); + + // DirBuilderExt::mode + let mut builder = DirBuilder::new(); + builder.mode(0o755); + builder.mode(0o406); +} diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs new file mode 100644 index 0000000000..7d2922f494 --- /dev/null +++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs @@ -0,0 +1,33 @@ +// ignore-windows +// run-rustfix +#![warn(clippy::non_octal_unix_permissions)] +use std::fs::{DirBuilder, File, OpenOptions, Permissions}; +use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt}; + +fn main() { + let permissions = 0o760; + + // OpenOptionsExt::mode + let mut options = OpenOptions::new(); + options.mode(440); + options.mode(0o400); + options.mode(permissions); + + // PermissionsExt::from_mode + let _permissions = Permissions::from_mode(647); + let _permissions = Permissions::from_mode(0o000); + let _permissions = Permissions::from_mode(permissions); + + // PermissionsExt::set_mode + let f = File::create("foo.txt").unwrap(); + let metadata = f.metadata().unwrap(); + let mut permissions = metadata.permissions(); + + permissions.set_mode(644); + permissions.set_mode(0o704); + + // DirBuilderExt::mode + let mut builder = DirBuilder::new(); + builder.mode(755); + builder.mode(0o406); +} diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr b/src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr new file mode 100644 index 0000000000..32845d0659 --- /dev/null +++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr @@ -0,0 +1,28 @@ +error: using a non-octal value to set unix file permissions + --> $DIR/non_octal_unix_permissions.rs:12:18 + | +LL | options.mode(440); + | ^^^ help: consider using an octal literal instead: `0o440` + | + = note: `-D clippy::non-octal-unix-permissions` implied by `-D warnings` + +error: using a non-octal value to set unix file permissions + --> $DIR/non_octal_unix_permissions.rs:17:47 + | +LL | let _permissions = Permissions::from_mode(647); + | ^^^ help: consider using an octal literal instead: `0o647` + +error: using a non-octal value to set unix file permissions + --> $DIR/non_octal_unix_permissions.rs:26:26 + | +LL | permissions.set_mode(644); + | ^^^ help: consider using an octal literal instead: `0o644` + +error: using a non-octal value to set unix file permissions + --> $DIR/non_octal_unix_permissions.rs:31:18 + | +LL | builder.mode(755); + | ^^^ help: consider using an octal literal instead: `0o755` + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/option_filter_map.fixed b/src/tools/clippy/tests/ui/option_filter_map.fixed new file mode 100644 index 0000000000..f9d1825ade --- /dev/null +++ b/src/tools/clippy/tests/ui/option_filter_map.fixed @@ -0,0 +1,23 @@ +#![warn(clippy::option_filter_map)] +// run-rustfix +fn odds_out(x: i32) -> Option<i32> { + if x % 2 == 0 { Some(x) } else { None } +} + +fn main() { + let _ = Some(Some(1)).flatten(); + let _ = Some(Some(1)).flatten(); + let _ = Some(1).map(odds_out).flatten(); + let _ = Some(1).map(odds_out).flatten(); + + let _ = vec![Some(1)].into_iter().flatten(); + let _ = vec![Some(1)].into_iter().flatten(); + let _ = vec![1] + .into_iter() + .map(odds_out) + .flatten(); + let _ = vec![1] + .into_iter() + .map(odds_out) + .flatten(); +} diff --git a/src/tools/clippy/tests/ui/option_filter_map.rs b/src/tools/clippy/tests/ui/option_filter_map.rs new file mode 100644 index 0000000000..588e1ccccc --- /dev/null +++ b/src/tools/clippy/tests/ui/option_filter_map.rs @@ -0,0 +1,25 @@ +#![warn(clippy::option_filter_map)] +// run-rustfix +fn odds_out(x: i32) -> Option<i32> { + if x % 2 == 0 { Some(x) } else { None } +} + +fn main() { + let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); + let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap()); + let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap); + let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap()); + + let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap); + let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap()); + let _ = vec![1] + .into_iter() + .map(odds_out) + .filter(Option::is_some) + .map(Option::unwrap); + let _ = vec![1] + .into_iter() + .map(odds_out) + .filter(|o| o.is_some()) + .map(|o| o.unwrap()); +} diff --git a/src/tools/clippy/tests/ui/option_filter_map.stderr b/src/tools/clippy/tests/ui/option_filter_map.stderr new file mode 100644 index 0000000000..31a82969d5 --- /dev/null +++ b/src/tools/clippy/tests/ui/option_filter_map.stderr @@ -0,0 +1,56 @@ +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:8:27 + | +LL | let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + | + = note: `-D clippy::option-filter-map` implied by `-D warnings` + +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:9:27 + | +LL | let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:10:35 + | +LL | let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:11:35 + | +LL | let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:13:39 + | +LL | let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:14:39 + | +LL | let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:18:10 + | +LL | .filter(Option::is_some) + | __________^ +LL | | .map(Option::unwrap); + | |____________________________^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `Some` followed by `unwrap` + --> $DIR/option_filter_map.rs:23:10 + | +LL | .filter(|o| o.is_some()) + | __________^ +LL | | .map(|o| o.unwrap()); + | |____________________________^ help: consider using `flatten` instead: `flatten()` + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui/option_option.rs b/src/tools/clippy/tests/ui/option_option.rs index 6859ba8e5b..2faab9e035 100644 --- a/src/tools/clippy/tests/ui/option_option.rs +++ b/src/tools/clippy/tests/ui/option_option.rs @@ -1,6 +1,9 @@ #![deny(clippy::option_option)] #![allow(clippy::unnecessary_wraps)] +const C: Option<Option<i32>> = None; +static S: Option<Option<i32>> = None; + fn input(_: Option<Option<u8>>) {} fn output() -> Option<Option<u8>> { diff --git a/src/tools/clippy/tests/ui/option_option.stderr b/src/tools/clippy/tests/ui/option_option.stderr index ad7f081c71..a925bb35b0 100644 --- a/src/tools/clippy/tests/ui/option_option.stderr +++ b/src/tools/clippy/tests/ui/option_option.stderr @@ -1,8 +1,8 @@ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:4:13 + --> $DIR/option_option.rs:4:10 | -LL | fn input(_: Option<Option<u8>>) {} - | ^^^^^^^^^^^^^^^^^^ +LL | const C: Option<Option<i32>> = None; + | ^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/option_option.rs:1:9 @@ -11,58 +11,70 @@ LL | #![deny(clippy::option_option)] | ^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:6:16 + --> $DIR/option_option.rs:5:11 + | +LL | static S: Option<Option<i32>> = None; + | ^^^^^^^^^^^^^^^^^^^ + +error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases + --> $DIR/option_option.rs:7:13 + | +LL | fn input(_: Option<Option<u8>>) {} + | ^^^^^^^^^^^^^^^^^^ + +error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases + --> $DIR/option_option.rs:9:16 | LL | fn output() -> Option<Option<u8>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:10:27 + --> $DIR/option_option.rs:13:27 | LL | fn output_nested() -> Vec<Option<Option<u8>>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:15:30 + --> $DIR/option_option.rs:18:30 | LL | fn output_nested_nested() -> Option<Option<Option<u8>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:20:8 + --> $DIR/option_option.rs:23:8 | LL | x: Option<Option<u8>>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:24:23 + --> $DIR/option_option.rs:27:23 | LL | fn struct_fn() -> Option<Option<u8>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:30:22 + --> $DIR/option_option.rs:33:22 | LL | fn trait_fn() -> Option<Option<u8>>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:34:11 + --> $DIR/option_option.rs:37:11 | LL | Tuple(Option<Option<u8>>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:35:17 + --> $DIR/option_option.rs:38:17 | LL | Struct { x: Option<Option<u8>> }, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:76:14 + --> $DIR/option_option.rs:79:14 | LL | foo: Option<Option<Cow<'a, str>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed index 64347cae5d..4390ff7dc3 100644 --- a/src/tools/clippy/tests/ui/or_fun_call.fixed +++ b/src/tools/clippy/tests/ui/or_fun_call.fixed @@ -120,6 +120,9 @@ fn test_or_with_ctors() { let slice = &["foo"][..]; let _ = opt.ok_or(slice.len()); + + let string = "foo"; + let _ = opt.ok_or(string.len()); } // Issue 4514 - early return @@ -132,4 +135,18 @@ fn f() -> Option<()> { Some(()) } +mod issue6675 { + unsafe fn foo() { + let mut s = "test".to_owned(); + None.unwrap_or_else(|| s.as_mut_vec()); + } + + fn bar() { + let mut s = "test".to_owned(); + None.unwrap_or_else(|| unsafe { s.as_mut_vec() }); + #[rustfmt::skip] + None.unwrap_or_else(|| unsafe { s.as_mut_vec() }); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs index 7faab0017b..75908c974c 100644 --- a/src/tools/clippy/tests/ui/or_fun_call.rs +++ b/src/tools/clippy/tests/ui/or_fun_call.rs @@ -120,6 +120,9 @@ fn test_or_with_ctors() { let slice = &["foo"][..]; let _ = opt.ok_or(slice.len()); + + let string = "foo"; + let _ = opt.ok_or(string.len()); } // Issue 4514 - early return @@ -132,4 +135,18 @@ fn f() -> Option<()> { Some(()) } +mod issue6675 { + unsafe fn foo() { + let mut s = "test".to_owned(); + None.unwrap_or(s.as_mut_vec()); + } + + fn bar() { + let mut s = "test".to_owned(); + None.unwrap_or(unsafe { s.as_mut_vec() }); + #[rustfmt::skip] + None.unwrap_or( unsafe { s.as_mut_vec() } ); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr index 1e2bfd490e..9905029ce9 100644 --- a/src/tools/clippy/tests/ui/or_fun_call.stderr +++ b/src/tools/clippy/tests/ui/or_fun_call.stderr @@ -114,5 +114,23 @@ error: use of `or` followed by a function call LL | .or(Some(Bar(b, Duration::from_secs(2)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))` -error: aborting due to 19 previous errors +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:141:14 + | +LL | None.unwrap_or(s.as_mut_vec()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| s.as_mut_vec())` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:146:14 + | +LL | None.unwrap_or(unsafe { s.as_mut_vec() }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })` + +error: use of `unwrap_or` followed by a function call + --> $DIR/or_fun_call.rs:148:14 + | +LL | None.unwrap_or( unsafe { s.as_mut_vec() } ); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })` + +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs b/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs index b60c79f97c..c4fcd7e709 100644 --- a/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs +++ b/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs @@ -1,44 +1,39 @@ #![warn(clippy::panic_in_result_fn)] #![allow(clippy::unnecessary_wraps)] +// debug_assert should never trigger the `panic_in_result_fn` lint + struct A; impl A { - fn result_with_debug_assert_with_message(x: i32) -> Result<bool, String> // should emit lint - { + fn result_with_debug_assert_with_message(x: i32) -> Result<bool, String> { debug_assert!(x == 5, "wrong argument"); Ok(true) } - fn result_with_debug_assert_eq(x: i32) -> Result<bool, String> // should emit lint - { + fn result_with_debug_assert_eq(x: i32) -> Result<bool, String> { debug_assert_eq!(x, 5); Ok(true) } - fn result_with_debug_assert_ne(x: i32) -> Result<bool, String> // should emit lint - { + fn result_with_debug_assert_ne(x: i32) -> Result<bool, String> { debug_assert_ne!(x, 1); Ok(true) } - fn other_with_debug_assert_with_message(x: i32) // should not emit lint - { + fn other_with_debug_assert_with_message(x: i32) { debug_assert!(x == 5, "wrong argument"); } - fn other_with_debug_assert_eq(x: i32) // should not emit lint - { + fn other_with_debug_assert_eq(x: i32) { debug_assert_eq!(x, 5); } - fn other_with_debug_assert_ne(x: i32) // should not emit lint - { + fn other_with_debug_assert_ne(x: i32) { debug_assert_ne!(x, 1); } - fn result_without_banned_functions() -> Result<bool, String> // should not emit lint - { + fn result_without_banned_functions() -> Result<bool, String> { let debug_assert = "debug_assert!"; println!("No {}", debug_assert); Ok(true) diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.stderr deleted file mode 100644 index ec18e89698..0000000000 --- a/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn_debug_assertions.rs:7:5 - | -LL | / fn result_with_debug_assert_with_message(x: i32) -> Result<bool, String> // should emit lint -LL | | { -LL | | debug_assert!(x == 5, "wrong argument"); -LL | | Ok(true) -LL | | } - | |_____^ - | - = note: `-D clippy::panic-in-result-fn` implied by `-D warnings` - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing -note: return Err() instead of panicking - --> $DIR/panic_in_result_fn_debug_assertions.rs:9:9 - | -LL | debug_assert!(x == 5, "wrong argument"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn_debug_assertions.rs:13:5 - | -LL | / fn result_with_debug_assert_eq(x: i32) -> Result<bool, String> // should emit lint -LL | | { -LL | | debug_assert_eq!(x, 5); -LL | | Ok(true) -LL | | } - | |_____^ - | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing -note: return Err() instead of panicking - --> $DIR/panic_in_result_fn_debug_assertions.rs:15:9 - | -LL | debug_assert_eq!(x, 5); - | ^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result` - --> $DIR/panic_in_result_fn_debug_assertions.rs:19:5 - | -LL | / fn result_with_debug_assert_ne(x: i32) -> Result<bool, String> // should emit lint -LL | | { -LL | | debug_assert_ne!(x, 1); -LL | | Ok(true) -LL | | } - | |_____^ - | - = help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing -note: return Err() instead of panicking - --> $DIR/panic_in_result_fn_debug_assertions.rs:21:9 - | -LL | debug_assert_ne!(x, 1); - | ^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 3 previous errors - diff --git a/src/tools/clippy/tests/ui/panicking_macros.rs b/src/tools/clippy/tests/ui/panicking_macros.rs index 77fcb8dfd0..93b236f747 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.rs +++ b/src/tools/clippy/tests/ui/panicking_macros.rs @@ -1,5 +1,5 @@ #![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)] -#![allow(clippy::assertions_on_constants)] +#![allow(clippy::assertions_on_constants, clippy::eq_op)] extern crate core; @@ -43,6 +43,18 @@ fn core_versions() { unreachable!(); } +fn debug_assert() { + debug_assert!(true); + debug_assert_eq!(true, true); + debug_assert_ne!(true, false); +} + +fn debug_assert_msg() { + debug_assert!(true, "test"); + debug_assert_eq!(true, true, "test"); + debug_assert_ne!(true, false, "test"); +} + fn main() { panic(); todo(); diff --git a/src/tools/clippy/tests/ui/print.stderr b/src/tools/clippy/tests/ui/print.stderr index 208d953262..1754c41838 100644 --- a/src/tools/clippy/tests/ui/print.stderr +++ b/src/tools/clippy/tests/ui/print.stderr @@ -1,8 +1,8 @@ error: use of `Debug`-based formatting - --> $DIR/print.rs:11:19 + --> $DIR/print.rs:11:20 | LL | write!(f, "{:?}", 43.1415) - | ^^^^^^ + | ^^^^ | = note: `-D clippy::use-debug` implied by `-D warnings` @@ -33,10 +33,10 @@ LL | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:28:12 + --> $DIR/print.rs:28:19 | LL | print!("Hello {:?}", "World"); - | ^^^^^^^^^^^^ + | ^^^^ error: use of `print!` --> $DIR/print.rs:30:5 @@ -45,10 +45,10 @@ LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:30:12 + --> $DIR/print.rs:30:19 | LL | print!("Hello {:#?}", "#orld"); - | ^^^^^^^^^^^^^ + | ^^^^^ error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/print_literal.stderr b/src/tools/clippy/tests/ui/print_literal.stderr index e284aece23..54a4084c89 100644 --- a/src/tools/clippy/tests/ui/print_literal.stderr +++ b/src/tools/clippy/tests/ui/print_literal.stderr @@ -5,66 +5,120 @@ LL | print!("Hello {}", "world"); | ^^^^^^^ | = note: `-D clippy::print-literal` implied by `-D warnings` +help: try this + | +LL | print!("Hello world"); + | ^^^^^-- error: literal with an empty format string --> $DIR/print_literal.rs:26:36 | LL | println!("Hello {} {}", world, "world"); | ^^^^^^^ + | +help: try this + | +LL | println!("Hello {} world", world); + | ^^^^^ -- error: literal with an empty format string --> $DIR/print_literal.rs:27:26 | LL | println!("Hello {}", "world"); | ^^^^^^^ + | +help: try this + | +LL | println!("Hello world"); + | ^^^^^-- error: literal with an empty format string --> $DIR/print_literal.rs:32:25 | LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | println!("hello {1}", "world"); + | ^^^^^ -- error: literal with an empty format string --> $DIR/print_literal.rs:32:34 | LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | println!("{0} world", "hello"); + | ^^^^^ -- error: literal with an empty format string --> $DIR/print_literal.rs:33:25 | LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | println!("{1} hello", "world"); + | ^^^^^-- error: literal with an empty format string --> $DIR/print_literal.rs:33:34 | LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | println!("world {0}", "hello"); + | ^^^^^ -- error: literal with an empty format string - --> $DIR/print_literal.rs:36:35 + --> $DIR/print_literal.rs:36:29 | LL | println!("{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | println!("hello {bar}", bar = "world"); + | ^^^^^ -- error: literal with an empty format string - --> $DIR/print_literal.rs:36:50 + --> $DIR/print_literal.rs:36:44 | LL | println!("{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | println!("{foo} world", foo = "hello"); + | ^^^^^ -- error: literal with an empty format string - --> $DIR/print_literal.rs:37:35 + --> $DIR/print_literal.rs:37:29 | LL | println!("{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | println!("{bar} hello", bar = "world"); + | ^^^^^-- error: literal with an empty format string - --> $DIR/print_literal.rs:37:50 + --> $DIR/print_literal.rs:37:44 | LL | println!("{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | println!("world {foo}", foo = "hello"); + | ^^^^^ -- error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed index ec309109ed..f5da703cd1 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.fixed +++ b/src/tools/clippy/tests/ui/redundant_clone.fixed @@ -54,6 +54,7 @@ fn main() { not_consumed(); issue_5405(); manually_drop(); + clone_then_move_cloned(); } #[derive(Clone)] @@ -182,3 +183,26 @@ fn manually_drop() { Arc::from_raw(p); } } + +fn clone_then_move_cloned() { + // issue #5973 + let x = Some(String::new()); + // ok, x is moved while the clone is in use. + assert_eq!(x.clone(), None, "not equal {}", x.unwrap()); + + // issue #5595 + fn foo<F: Fn()>(_: &Alpha, _: F) {} + let x = Alpha; + // ok, data is moved while the clone is in use. + foo(&x.clone(), move || { + let _ = x; + }); + + // issue #6998 + struct S(String); + impl S { + fn m(&mut self) {} + } + let mut x = S(String::new()); + x.0.clone().chars().for_each(|_| x.m()); +} diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs index b57027456e..fd7f31a1cc 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.rs +++ b/src/tools/clippy/tests/ui/redundant_clone.rs @@ -54,6 +54,7 @@ fn main() { not_consumed(); issue_5405(); manually_drop(); + clone_then_move_cloned(); } #[derive(Clone)] @@ -182,3 +183,26 @@ fn manually_drop() { Arc::from_raw(p); } } + +fn clone_then_move_cloned() { + // issue #5973 + let x = Some(String::new()); + // ok, x is moved while the clone is in use. + assert_eq!(x.clone(), None, "not equal {}", x.unwrap()); + + // issue #5595 + fn foo<F: Fn()>(_: &Alpha, _: F) {} + let x = Alpha; + // ok, data is moved while the clone is in use. + foo(&x.clone(), move || { + let _ = x; + }); + + // issue #6998 + struct S(String); + impl S { + fn m(&mut self) {} + } + let mut x = S(String::new()); + x.0.clone().chars().for_each(|_| x.m()); +} diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr index 821e7934be..529a6de91e 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.stderr +++ b/src/tools/clippy/tests/ui/redundant_clone.stderr @@ -108,61 +108,61 @@ LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:62:25 + --> $DIR/redundant_clone.rs:63: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:62:24 + --> $DIR/redundant_clone.rs:63:24 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^ error: redundant clone - --> $DIR/redundant_clone.rs:119:15 + --> $DIR/redundant_clone.rs:120:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:119:14 + --> $DIR/redundant_clone.rs:120:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:120:15 + --> $DIR/redundant_clone.rs:121:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:120:14 + --> $DIR/redundant_clone.rs:121:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:130:19 + --> $DIR/redundant_clone.rs:131:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:130:18 + --> $DIR/redundant_clone.rs:131:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:142:14 + --> $DIR/redundant_clone.rs:143:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> $DIR/redundant_clone.rs:142:13 + --> $DIR/redundant_clone.rs:143:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed new file mode 100644 index 0000000000..794ed54243 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed @@ -0,0 +1,58 @@ +// run-rustfix + +// Issue #5746 +#![warn(clippy::redundant_pattern_matching)] +#![allow(clippy::if_same_then_else)] +use std::task::Poll::{Pending, Ready}; + +fn main() { + let m = std::sync::Mutex::new((0, 0)); + + // Result + if m.lock().is_ok() {} + if Err::<(), _>(m.lock().unwrap().0).is_err() {} + + { + if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() {} + } + if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() { + } else { + } + if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() {} + if Err::<std::sync::MutexGuard<()>, _>(()).is_err() {} + + if Ok::<_, ()>(String::new()).is_ok() {} + if Err::<(), _>((String::new(), ())).is_err() {} + + // Option + if Some(m.lock()).is_some() {} + if Some(m.lock().unwrap().0).is_some() {} + + { + if None::<std::sync::MutexGuard<()>>.is_none() {} + } + if None::<std::sync::MutexGuard<()>>.is_none() { + } else { + } + + if None::<std::sync::MutexGuard<()>>.is_none() {} + + if Some(String::new()).is_some() {} + if Some((String::new(), ())).is_some() {} + + // Poll + if Ready(m.lock()).is_ready() {} + if Ready(m.lock().unwrap().0).is_ready() {} + + { + if Pending::<std::sync::MutexGuard<()>>.is_pending() {} + } + if Pending::<std::sync::MutexGuard<()>>.is_pending() { + } else { + } + + if Pending::<std::sync::MutexGuard<()>>.is_pending() {} + + if Ready(String::new()).is_ready() {} + if Ready((String::new(), ())).is_ready() {} +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs new file mode 100644 index 0000000000..b9c82d86f6 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs @@ -0,0 +1,58 @@ +// run-rustfix + +// Issue #5746 +#![warn(clippy::redundant_pattern_matching)] +#![allow(clippy::if_same_then_else)] +use std::task::Poll::{Pending, Ready}; + +fn main() { + let m = std::sync::Mutex::new((0, 0)); + + // Result + if let Ok(_) = m.lock() {} + if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} + + { + if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} + } + if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { + } else { + } + if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} + if let Err(_) = Err::<std::sync::MutexGuard<()>, _>(()) {} + + if let Ok(_) = Ok::<_, ()>(String::new()) {} + if let Err(_) = Err::<(), _>((String::new(), ())) {} + + // Option + if let Some(_) = Some(m.lock()) {} + if let Some(_) = Some(m.lock().unwrap().0) {} + + { + if let None = None::<std::sync::MutexGuard<()>> {} + } + if let None = None::<std::sync::MutexGuard<()>> { + } else { + } + + if let None = None::<std::sync::MutexGuard<()>> {} + + if let Some(_) = Some(String::new()) {} + if let Some(_) = Some((String::new(), ())) {} + + // Poll + if let Ready(_) = Ready(m.lock()) {} + if let Ready(_) = Ready(m.lock().unwrap().0) {} + + { + if let Pending = Pending::<std::sync::MutexGuard<()>> {} + } + if let Pending = Pending::<std::sync::MutexGuard<()>> { + } else { + } + + if let Pending = Pending::<std::sync::MutexGuard<()>> {} + + if let Ready(_) = Ready(String::new()) {} + if let Ready(_) = Ready((String::new(), ())) {} +} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr new file mode 100644 index 0000000000..eb7aa70ee2 --- /dev/null +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr @@ -0,0 +1,171 @@ +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_drop_order.rs:12:12 + | +LL | if let Ok(_) = m.lock() {} + | -------^^^^^----------- help: try this: `if m.lock().is_ok()` + | + = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_drop_order.rs:13:12 + | +LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} + | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>(m.lock().unwrap().0).is_err()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_drop_order.rs:16:16 + | +LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} + | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_drop_order.rs:18:12 + | +LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { + | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_drop_order.rs:21:12 + | +LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} + | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_drop_order.rs:22:12 + | +LL | if let Err(_) = Err::<std::sync::MutexGuard<()>, _>(()) {} + | -------^^^^^^------------------------------------------ help: try this: `if Err::<std::sync::MutexGuard<()>, _>(()).is_err()` + +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_drop_order.rs:24:12 + | +LL | if let Ok(_) = Ok::<_, ()>(String::new()) {} + | -------^^^^^----------------------------- help: try this: `if Ok::<_, ()>(String::new()).is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_drop_order.rs:25:12 + | +LL | if let Err(_) = Err::<(), _>((String::new(), ())) {} + | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>((String::new(), ())).is_err()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_drop_order.rs:28:12 + | +LL | if let Some(_) = Some(m.lock()) {} + | -------^^^^^^^----------------- help: try this: `if Some(m.lock()).is_some()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_drop_order.rs:29:12 + | +LL | if let Some(_) = Some(m.lock().unwrap().0) {} + | -------^^^^^^^---------------------------- help: try this: `if Some(m.lock().unwrap().0).is_some()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/redundant_pattern_matching_drop_order.rs:32:16 + | +LL | if let None = None::<std::sync::MutexGuard<()>> {} + | -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/redundant_pattern_matching_drop_order.rs:34:12 + | +LL | if let None = None::<std::sync::MutexGuard<()>> { + | -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/redundant_pattern_matching_drop_order.rs:38:12 + | +LL | if let None = None::<std::sync::MutexGuard<()>> {} + | -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_drop_order.rs:40:12 + | +LL | if let Some(_) = Some(String::new()) {} + | -------^^^^^^^---------------------- help: try this: `if Some(String::new()).is_some()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_drop_order.rs:41:12 + | +LL | if let Some(_) = Some((String::new(), ())) {} + | -------^^^^^^^---------------------------- help: try this: `if Some((String::new(), ())).is_some()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_drop_order.rs:44:12 + | +LL | if let Ready(_) = Ready(m.lock()) {} + | -------^^^^^^^^------------------ help: try this: `if Ready(m.lock()).is_ready()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_drop_order.rs:45:12 + | +LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} + | -------^^^^^^^^----------------------------- help: try this: `if Ready(m.lock().unwrap().0).is_ready()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_drop_order.rs:48:16 + | +LL | if let Pending = Pending::<std::sync::MutexGuard<()>> {} + | -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_drop_order.rs:50:12 + | +LL | if let Pending = Pending::<std::sync::MutexGuard<()>> { + | -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important + +error: redundant pattern matching, consider using `is_pending()` + --> $DIR/redundant_pattern_matching_drop_order.rs:54:12 + | +LL | if let Pending = Pending::<std::sync::MutexGuard<()>> {} + | -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_drop_order.rs:56:12 + | +LL | if let Ready(_) = Ready(String::new()) {} + | -------^^^^^^^^----------------------- help: try this: `if Ready(String::new()).is_ready()` + +error: redundant pattern matching, consider using `is_ready()` + --> $DIR/redundant_pattern_matching_drop_order.rs:57:12 + | +LL | if let Ready(_) = Ready((String::new(), ())) {} + | -------^^^^^^^^----------------------------- help: try this: `if Ready((String::new(), ())).is_ready()` + +error: aborting due to 22 previous errors + diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed index 66f580a0a6..9971447726 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed @@ -2,7 +2,12 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] +#![allow( + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + clippy::if_same_then_else +)] fn main() { if None::<()>.is_none() {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs index f18b27b8b9..8309847e18 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs @@ -2,7 +2,12 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] +#![allow( + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + clippy::if_same_then_else +)] fn main() { if let None = None::<()> {} diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr index 58482a0ab7..613a30d4a4 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:8:12 + --> $DIR/redundant_pattern_matching_option.rs:13:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` @@ -7,43 +7,43 @@ LL | if let None = None::<()> {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:10:12 + --> $DIR/redundant_pattern_matching_option.rs:15:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:12:12 + --> $DIR/redundant_pattern_matching_option.rs:17:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:18:15 + --> $DIR/redundant_pattern_matching_option.rs:23:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:20:15 + --> $DIR/redundant_pattern_matching_option.rs:25:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try this: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:22:15 + --> $DIR/redundant_pattern_matching_option.rs:27:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:25:15 + --> $DIR/redundant_pattern_matching_option.rs:30:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:33:5 + --> $DIR/redundant_pattern_matching_option.rs:38:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -52,7 +52,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:38:5 + --> $DIR/redundant_pattern_matching_option.rs:43:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:43:13 + --> $DIR/redundant_pattern_matching_option.rs:48:13 | LL | let _ = match None::<()> { | _____________^ @@ -71,49 +71,49 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:49:20 + --> $DIR/redundant_pattern_matching_option.rs:54:20 | LL | let _ = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:53:20 + --> $DIR/redundant_pattern_matching_option.rs:58:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:55:19 + --> $DIR/redundant_pattern_matching_option.rs:60:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try this: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:74:12 + --> $DIR/redundant_pattern_matching_option.rs:79:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:76:12 + --> $DIR/redundant_pattern_matching_option.rs:81:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:78:15 + --> $DIR/redundant_pattern_matching_option.rs:83:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:80:15 + --> $DIR/redundant_pattern_matching_option.rs:85:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:82:5 + --> $DIR/redundant_pattern_matching_option.rs:87:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -122,7 +122,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:87:5 + --> $DIR/redundant_pattern_matching_option.rs:92:5 | LL | / match None::<()> { LL | | Some(_) => false, diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed index 465aa80dac..c297745380 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed @@ -2,7 +2,12 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] +#![allow( + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + clippy::if_same_then_else +)] use std::task::Poll::{self, Pending, Ready}; diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs index 7891ff353b..665c8c4175 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs @@ -2,7 +2,12 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)] +#![allow( + unused_must_use, + clippy::needless_bool, + clippy::match_like_matches_macro, + clippy::if_same_then_else +)] use std::task::Poll::{self, Pending, Ready}; diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr index 5ffc6c47c9..5ecf024a73 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:10:12 + --> $DIR/redundant_pattern_matching_poll.rs:15:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` @@ -7,37 +7,37 @@ LL | if let Pending = Pending::<()> {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:12:12 + --> $DIR/redundant_pattern_matching_poll.rs:17:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:14:12 + --> $DIR/redundant_pattern_matching_poll.rs:19:12 | LL | if let Ready(_) = Ready(42) { | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:20:15 + --> $DIR/redundant_pattern_matching_poll.rs:25:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:22:15 + --> $DIR/redundant_pattern_matching_poll.rs:27:15 | LL | while let Pending = Ready(42) {} | ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:24:15 + --> $DIR/redundant_pattern_matching_poll.rs:29:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:30:5 + --> $DIR/redundant_pattern_matching_poll.rs:35:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -46,7 +46,7 @@ LL | | }; | |_____^ help: try this: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:35:5 + --> $DIR/redundant_pattern_matching_poll.rs:40:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, @@ -55,7 +55,7 @@ LL | | }; | |_____^ help: try this: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:40:13 + --> $DIR/redundant_pattern_matching_poll.rs:45:13 | LL | let _ = match Pending::<()> { | _____________^ @@ -65,49 +65,49 @@ LL | | }; | |_____^ help: try this: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:46:20 + --> $DIR/redundant_pattern_matching_poll.rs:51:20 | LL | let _ = if let Ready(_) = poll { true } else { false }; | -------^^^^^^^^------- help: try this: `if poll.is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:50:20 + --> $DIR/redundant_pattern_matching_poll.rs:55:20 | LL | let _ = if let Ready(_) = gen_poll() { | -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:52:19 + --> $DIR/redundant_pattern_matching_poll.rs:57:19 | LL | } else if let Pending = gen_poll() { | -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:68:12 + --> $DIR/redundant_pattern_matching_poll.rs:73:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:70:12 + --> $DIR/redundant_pattern_matching_poll.rs:75:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:72:15 + --> $DIR/redundant_pattern_matching_poll.rs:77:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:74:15 + --> $DIR/redundant_pattern_matching_poll.rs:79:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:76:5 + --> $DIR/redundant_pattern_matching_poll.rs:81:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -116,7 +116,7 @@ LL | | }; | |_____^ help: try this: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:81:5 + --> $DIR/redundant_pattern_matching_poll.rs:86:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed index e94c5704b4..d7af5d762a 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed @@ -7,7 +7,8 @@ clippy::needless_bool, clippy::match_like_matches_macro, clippy::unnecessary_wraps, - deprecated + deprecated, + clippy::if_same_then_else )] fn main() { diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs index 5d17529423..e06d4485ae 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs @@ -7,7 +7,8 @@ clippy::needless_bool, clippy::match_like_matches_macro, clippy::unnecessary_wraps, - deprecated + deprecated, + clippy::if_same_then_else )] fn main() { diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr index d6a46babb7..e06f095da2 100644 --- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr +++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:15:12 + --> $DIR/redundant_pattern_matching_result.rs:16:12 | LL | if let Ok(_) = &result {} | -------^^^^^---------- help: try this: `if result.is_ok()` @@ -7,31 +7,31 @@ LL | if let Ok(_) = &result {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:17:12 + --> $DIR/redundant_pattern_matching_result.rs:18:12 | LL | if let Ok(_) = Ok::<i32, i32>(42) {} | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:19:12 + --> $DIR/redundant_pattern_matching_result.rs:20:12 | LL | if let Err(_) = Err::<i32, i32>(42) {} | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:21:15 + --> $DIR/redundant_pattern_matching_result.rs:22:15 | LL | while let Ok(_) = Ok::<i32, i32>(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:23:15 + --> $DIR/redundant_pattern_matching_result.rs:24:15 | LL | while let Err(_) = Ok::<i32, i32>(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:33:5 + --> $DIR/redundant_pattern_matching_result.rs:34:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => true, @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:38:5 + --> $DIR/redundant_pattern_matching_result.rs:39:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => false, @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:43:5 + --> $DIR/redundant_pattern_matching_result.rs:44:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => false, @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:48:5 + --> $DIR/redundant_pattern_matching_result.rs:49:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => true, @@ -67,73 +67,73 @@ LL | | }; | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:53:20 + --> $DIR/redundant_pattern_matching_result.rs:54:20 | LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false }; | -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:59:20 + --> $DIR/redundant_pattern_matching_result.rs:60:20 | LL | let _ = if let Ok(_) = gen_res() { | -------^^^^^------------ help: try this: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:61:19 + --> $DIR/redundant_pattern_matching_result.rs:62:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try this: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:84:19 + --> $DIR/redundant_pattern_matching_result.rs:85:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:85:16 + --> $DIR/redundant_pattern_matching_result.rs:86:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:91:12 + --> $DIR/redundant_pattern_matching_result.rs:92:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try this: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:92:15 + --> $DIR/redundant_pattern_matching_result.rs:93:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try this: `while m!().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:110:12 + --> $DIR/redundant_pattern_matching_result.rs:111:12 | LL | if let Ok(_) = Ok::<i32, i32>(42) {} | -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:112:12 + --> $DIR/redundant_pattern_matching_result.rs:113:12 | LL | if let Err(_) = Err::<i32, i32>(42) {} | -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:114:15 + --> $DIR/redundant_pattern_matching_result.rs:115:15 | LL | while let Ok(_) = Ok::<i32, i32>(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:116:15 + --> $DIR/redundant_pattern_matching_result.rs:117:15 | LL | while let Err(_) = Ok::<i32, i32>(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:118:5 + --> $DIR/redundant_pattern_matching_result.rs:119:5 | LL | / match Ok::<i32, i32>(42) { LL | | Ok(_) => true, @@ -142,7 +142,7 @@ LL | | }; | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:123:5 + --> $DIR/redundant_pattern_matching_result.rs:124:5 | LL | / match Err::<i32, i32>(42) { LL | | Ok(_) => false, diff --git a/src/tools/clippy/tests/ui/redundant_slicing.rs b/src/tools/clippy/tests/ui/redundant_slicing.rs index 922b8b4ce5..554b6ba36a 100644 --- a/src/tools/clippy/tests/ui/redundant_slicing.rs +++ b/src/tools/clippy/tests/ui/redundant_slicing.rs @@ -2,10 +2,31 @@ #![warn(clippy::redundant_slicing)] fn main() { - let x: &[u32] = &[0]; - let err = &x[..]; + let slice: &[u32] = &[0]; + let _ = &slice[..]; let v = vec![0]; - let ok = &v[..]; - let err = &(&v[..])[..]; + let _ = &v[..]; // Changes the type + let _ = &(&v[..])[..]; // Outer borrow is redundant + + static S: &[u8] = &[0, 1, 2]; + let err = &mut &S[..]; // Should reborrow instead of slice + + let mut vec = vec![0]; + let mut_slice = &mut *vec; + let _ = &mut mut_slice[..]; // Should reborrow instead of slice + + macro_rules! m { + ($e:expr) => { + $e + }; + } + let _ = &m!(slice)[..]; + + macro_rules! m2 { + ($e:expr) => { + &$e[..] + }; + } + let _ = m2!(slice); // Don't lint in a macro } diff --git a/src/tools/clippy/tests/ui/redundant_slicing.stderr b/src/tools/clippy/tests/ui/redundant_slicing.stderr index 9efd6484ad..bbd10eafbb 100644 --- a/src/tools/clippy/tests/ui/redundant_slicing.stderr +++ b/src/tools/clippy/tests/ui/redundant_slicing.stderr @@ -1,16 +1,34 @@ error: redundant slicing of the whole range - --> $DIR/redundant_slicing.rs:6:15 + --> $DIR/redundant_slicing.rs:6:13 | -LL | let err = &x[..]; - | ^^^^^^ help: use the original slice instead: `x` +LL | let _ = &slice[..]; + | ^^^^^^^^^^ help: use the original value instead: `slice` | = note: `-D clippy::redundant-slicing` implied by `-D warnings` error: redundant slicing of the whole range - --> $DIR/redundant_slicing.rs:10:15 + --> $DIR/redundant_slicing.rs:10:13 | -LL | let err = &(&v[..])[..]; - | ^^^^^^^^^^^^^ help: use the original slice instead: `(&v[..])` +LL | let _ = &(&v[..])[..]; // Outer borrow is redundant + | ^^^^^^^^^^^^^ help: use the original value instead: `(&v[..])` -error: aborting due to 2 previous errors +error: redundant slicing of the whole range + --> $DIR/redundant_slicing.rs:13:20 + | +LL | let err = &mut &S[..]; // Should reborrow instead of slice + | ^^^^^^ help: reborrow the original value instead: `&*S` + +error: redundant slicing of the whole range + --> $DIR/redundant_slicing.rs:17:13 + | +LL | let _ = &mut mut_slice[..]; // Should reborrow instead of slice + | ^^^^^^^^^^^^^^^^^^ help: reborrow the original value instead: `&mut *mut_slice` + +error: redundant slicing of the whole range + --> $DIR/redundant_slicing.rs:24:13 + | +LL | let _ = &m!(slice)[..]; + | ^^^^^^^^^^^^^^ help: use the original value instead: `slice` + +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/ref_option_ref.rs b/src/tools/clippy/tests/ui/ref_option_ref.rs index b2c275d68a..2df45c927d 100644 --- a/src/tools/clippy/tests/ui/ref_option_ref.rs +++ b/src/tools/clippy/tests/ui/ref_option_ref.rs @@ -9,7 +9,7 @@ static THRESHOLD: i32 = 10; static REF_THRESHOLD: &Option<&i32> = &Some(&THRESHOLD); const CONST_THRESHOLD: &i32 = &10; -const REF_CONST: &Option<&i32> = &Some(&CONST_THRESHOLD); +const REF_CONST: &Option<&i32> = &Some(CONST_THRESHOLD); type RefOptRefU32<'a> = &'a Option<&'a u32>; type RefOptRef<'a, T> = &'a Option<&'a T>; diff --git a/src/tools/clippy/tests/ui/ref_option_ref.stderr b/src/tools/clippy/tests/ui/ref_option_ref.stderr index 4e7fc80006..b61334758e 100644 --- a/src/tools/clippy/tests/ui/ref_option_ref.stderr +++ b/src/tools/clippy/tests/ui/ref_option_ref.stderr @@ -9,7 +9,7 @@ LL | static REF_THRESHOLD: &Option<&i32> = &Some(&THRESHOLD); error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` --> $DIR/ref_option_ref.rs:12:18 | -LL | const REF_CONST: &Option<&i32> = &Some(&CONST_THRESHOLD); +LL | const REF_CONST: &Option<&i32> = &Some(CONST_THRESHOLD); | ^^^^^^^^^^^^^ help: try: `Option<&i32>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` diff --git a/src/tools/clippy/tests/ui/repl_uninit.rs b/src/tools/clippy/tests/ui/repl_uninit.rs index ad5b8e4857..6c7e2b854d 100644 --- a/src/tools/clippy/tests/ui/repl_uninit.rs +++ b/src/tools/clippy/tests/ui/repl_uninit.rs @@ -1,5 +1,5 @@ -#![allow(deprecated, invalid_value)] -#![warn(clippy::all)] +#![allow(deprecated, invalid_value, clippy::uninit_assumed_init)] +#![warn(clippy::mem_replace_with_uninit)] use std::mem; diff --git a/src/tools/clippy/tests/ui/result_unit_error.stderr b/src/tools/clippy/tests/ui/result_unit_error.stderr index 41d8b0a7cb..8c7573eabd 100644 --- a/src/tools/clippy/tests/ui/result_unit_error.stderr +++ b/src/tools/clippy/tests/ui/result_unit_error.stderr @@ -1,43 +1,43 @@ -error: this returns a `Result<_, ()> +error: this returns a `Result<_, ()>` --> $DIR/result_unit_error.rs:3:1 | LL | pub fn returns_unit_error() -> Result<u32, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::result-unit-err` implied by `-D warnings` - = help: use a custom Error type instead + = help: use a custom `Error` type instead -error: this returns a `Result<_, ()> +error: this returns a `Result<_, ()>` --> $DIR/result_unit_error.rs:12:5 | LL | fn get_that_error(&self) -> Result<bool, ()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: use a custom Error type instead + = help: use a custom `Error` type instead -error: this returns a `Result<_, ()> +error: this returns a `Result<_, ()>` --> $DIR/result_unit_error.rs:14:5 | LL | fn get_this_one_too(&self) -> Result<bool, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: use a custom Error type instead + = help: use a custom `Error` type instead -error: this returns a `Result<_, ()> +error: this returns a `Result<_, ()>` --> $DIR/result_unit_error.rs:32:5 | LL | pub fn unit_error(&self) -> Result<usize, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: use a custom Error type instead + = help: use a custom `Error` type instead -error: this returns a `Result<_, ()> +error: this returns a `Result<_, ()>` --> $DIR/result_unit_error.rs:41:5 | LL | pub fn should_lint() -> ResInv<(), usize> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: use a custom Error type instead + = help: use a custom `Error` type instead error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/same_item_push.rs b/src/tools/clippy/tests/ui/same_item_push.rs index a37c8782ec..9d420ec672 100644 --- a/src/tools/clippy/tests/ui/same_item_push.rs +++ b/src/tools/clippy/tests/ui/same_item_push.rs @@ -148,4 +148,11 @@ fn main() { }; vec.push(item); } + + // Fix #6987 + let mut vec = Vec::new(); + for _ in 0..10 { + vec.push(1); + vec.extend(&[2]); + } } diff --git a/src/tools/clippy/tests/ui/search_is_some.rs b/src/tools/clippy/tests/ui/search_is_some.rs index f0dc3b3d06..72bc6ef35d 100644 --- a/src/tools/clippy/tests/ui/search_is_some.rs +++ b/src/tools/clippy/tests/ui/search_is_some.rs @@ -1,8 +1,9 @@ // aux-build:option_helpers.rs +#![warn(clippy::search_is_some)] +#![allow(dead_code)] extern crate option_helpers; use option_helpers::IteratorFalsePositives; -#[warn(clippy::search_is_some)] #[rustfmt::skip] fn main() { let v = vec![3, 2, 1, 0, -1, -2, -3]; @@ -36,3 +37,37 @@ fn main() { // `Pattern` that is not a string let _ = "hello world".find(|c: char| c == 'o' || c == 'l').is_some(); } + +#[rustfmt::skip] +fn is_none() { + let v = vec![3, 2, 1, 0, -1, -2, -3]; + let y = &&42; + + + // Check `find().is_none()`, multi-line case. + let _ = v.iter().find(|&x| { + *x < 0 + } + ).is_none(); + + // Check `position().is_none()`, multi-line case. + let _ = v.iter().position(|&x| { + x < 0 + } + ).is_none(); + + // Check `rposition().is_none()`, multi-line case. + let _ = v.iter().rposition(|&x| { + x < 0 + } + ).is_none(); + + // Check that we don't lint if the caller is not an `Iterator` or string + let falsepos = IteratorFalsePositives { foo: 0 }; + let _ = falsepos.find().is_none(); + let _ = falsepos.position().is_none(); + let _ = falsepos.rposition().is_none(); + // check that we don't lint if `find()` is called with + // `Pattern` that is not a string + let _ = "hello world".find(|c: char| c == 'o' || c == 'l').is_none(); +} diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr index c601f568c6..f3c758e451 100644 --- a/src/tools/clippy/tests/ui/search_is_some.stderr +++ b/src/tools/clippy/tests/ui/search_is_some.stderr @@ -1,5 +1,5 @@ error: called `is_some()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:13:13 + --> $DIR/search_is_some.rs:14:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -12,7 +12,7 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `position` - --> $DIR/search_is_some.rs:19:13 + --> $DIR/search_is_some.rs:20:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -24,7 +24,7 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `rposition` - --> $DIR/search_is_some.rs:25:13 + --> $DIR/search_is_some.rs:26:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -35,5 +35,41 @@ LL | | ).is_some(); | = help: this is more succinctly expressed by calling `any()` -error: aborting due to 3 previous errors +error: called `is_none()` after searching an `Iterator` with `find` + --> $DIR/search_is_some.rs:48:13 + | +LL | let _ = v.iter().find(|&x| { + | _____________^ +LL | | *x < 0 +LL | | } +LL | | ).is_none(); + | |______________________________^ + | + = help: this is more succinctly expressed by calling `any()` with negation + +error: called `is_none()` after searching an `Iterator` with `position` + --> $DIR/search_is_some.rs:54:13 + | +LL | let _ = v.iter().position(|&x| { + | _____________^ +LL | | x < 0 +LL | | } +LL | | ).is_none(); + | |______________________________^ + | + = help: this is more succinctly expressed by calling `any()` with negation + +error: called `is_none()` after searching an `Iterator` with `rposition` + --> $DIR/search_is_some.rs:60:13 + | +LL | let _ = v.iter().rposition(|&x| { + | _____________^ +LL | | x < 0 +LL | | } +LL | | ).is_none(); + | |______________________________^ + | + = help: this is more succinctly expressed by calling `any()` with negation + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable.fixed index dc3f290e56..62ff16f67f 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable.fixed +++ b/src/tools/clippy/tests/ui/search_is_some_fixable.fixed @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![warn(clippy::search_is_some)] fn main() { @@ -33,3 +33,36 @@ fn main() { let _ = s1[2..].contains(&s2); let _ = s1[2..].contains(&s2[2..]); } + +fn is_none() { + let v = vec![3, 2, 1, 0, -1, -2, -3]; + let y = &&42; + + // Check `find().is_none()`, single-line case. + let _ = !v.iter().any(|x| *x < 0); + let _ = !(0..1).any(|x| **y == x); // one dereference less + let _ = !(0..1).any(|x| x == 0); + let _ = !v.iter().any(|x| *x == 0); + + // Check `position().is_none()`, single-line case. + let _ = !v.iter().any(|&x| x < 0); + + // Check `rposition().is_none()`, single-line case. + let _ = !v.iter().any(|&x| x < 0); + + let s1 = String::from("hello world"); + let s2 = String::from("world"); + + // caller of `find()` is a `&`static str` + let _ = !"hello world".contains("world"); + let _ = !"hello world".contains(&s2); + let _ = !"hello world".contains(&s2[2..]); + // caller of `find()` is a `String` + let _ = !s1.contains("world"); + let _ = !s1.contains(&s2); + let _ = !s1.contains(&s2[2..]); + // caller of `find()` is slice of `String` + let _ = !s1[2..].contains("world"); + let _ = !s1[2..].contains(&s2); + let _ = !s1[2..].contains(&s2[2..]); +} diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.rs b/src/tools/clippy/tests/ui/search_is_some_fixable.rs index 146cf5adf1..8407f71664 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable.rs +++ b/src/tools/clippy/tests/ui/search_is_some_fixable.rs @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![warn(clippy::search_is_some)] fn main() { @@ -33,3 +33,36 @@ fn main() { let _ = s1[2..].find(&s2).is_some(); let _ = s1[2..].find(&s2[2..]).is_some(); } + +fn is_none() { + let v = vec![3, 2, 1, 0, -1, -2, -3]; + let y = &&42; + + // Check `find().is_none()`, single-line case. + let _ = v.iter().find(|&x| *x < 0).is_none(); + let _ = (0..1).find(|x| **y == *x).is_none(); // one dereference less + let _ = (0..1).find(|x| *x == 0).is_none(); + let _ = v.iter().find(|x| **x == 0).is_none(); + + // Check `position().is_none()`, single-line case. + let _ = v.iter().position(|&x| x < 0).is_none(); + + // Check `rposition().is_none()`, single-line case. + let _ = v.iter().rposition(|&x| x < 0).is_none(); + + let s1 = String::from("hello world"); + let s2 = String::from("world"); + + // caller of `find()` is a `&`static str` + let _ = "hello world".find("world").is_none(); + let _ = "hello world".find(&s2).is_none(); + let _ = "hello world".find(&s2[2..]).is_none(); + // caller of `find()` is a `String` + let _ = s1.find("world").is_none(); + let _ = s1.find(&s2).is_none(); + let _ = s1.find(&s2[2..]).is_none(); + // caller of `find()` is slice of `String` + let _ = s1[2..].find("world").is_none(); + let _ = s1[2..].find(&s2).is_none(); + let _ = s1[2..].find(&s2[2..]).is_none(); +} diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable.stderr index 23c1d9a901..bd1b6955a9 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable.stderr +++ b/src/tools/clippy/tests/ui/search_is_some_fixable.stderr @@ -90,5 +90,95 @@ error: called `is_some()` after calling `find()` on a string LL | let _ = s1[2..].find(&s2[2..]).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])` -error: aborting due to 15 previous errors +error: called `is_none()` after searching an `Iterator` with `find` + --> $DIR/search_is_some_fixable.rs:42:13 + | +LL | let _ = v.iter().find(|&x| *x < 0).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x < 0)` + +error: called `is_none()` after searching an `Iterator` with `find` + --> $DIR/search_is_some_fixable.rs:43:13 + | +LL | let _ = (0..1).find(|x| **y == *x).is_none(); // one dereference less + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(|x| **y == x)` + +error: called `is_none()` after searching an `Iterator` with `find` + --> $DIR/search_is_some_fixable.rs:44:13 + | +LL | let _ = (0..1).find(|x| *x == 0).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(|x| x == 0)` + +error: called `is_none()` after searching an `Iterator` with `find` + --> $DIR/search_is_some_fixable.rs:45:13 + | +LL | let _ = v.iter().find(|x| **x == 0).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x == 0)` + +error: called `is_none()` after searching an `Iterator` with `position` + --> $DIR/search_is_some_fixable.rs:48:13 + | +LL | let _ = v.iter().position(|&x| x < 0).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|&x| x < 0)` + +error: called `is_none()` after searching an `Iterator` with `rposition` + --> $DIR/search_is_some_fixable.rs:51:13 + | +LL | let _ = v.iter().rposition(|&x| x < 0).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|&x| x < 0)` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:57:13 + | +LL | let _ = "hello world".find("world").is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains("world")` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:58:13 + | +LL | let _ = "hello world".find(&s2).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains(&s2)` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:59:13 + | +LL | let _ = "hello world".find(&s2[2..]).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains(&s2[2..])` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:61:13 + | +LL | let _ = s1.find("world").is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains("world")` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:62:13 + | +LL | let _ = s1.find(&s2).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains(&s2)` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:63:13 + | +LL | let _ = s1.find(&s2[2..]).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains(&s2[2..])` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:65:13 + | +LL | let _ = s1[2..].find("world").is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains("world")` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:66:13 + | +LL | let _ = s1[2..].find(&s2).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains(&s2)` + +error: called `is_none()` after calling `find()` on a string + --> $DIR/search_is_some_fixable.rs:67:13 + | +LL | let _ = s1[2..].find(&s2[2..]).is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains(&s2[2..])` + +error: aborting due to 30 previous errors diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.fixed b/src/tools/clippy/tests/ui/single_component_path_imports.fixed index a7a8499b58..f66b445b7b 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports.fixed +++ b/src/tools/clippy/tests/ui/single_component_path_imports.fixed @@ -19,3 +19,16 @@ fn main() { // False positive #5154, shouldn't trigger lint. m!(); } + +mod hello_mod { + + #[allow(dead_code)] + fn hello_mod() {} +} + +mod hi_mod { + use self::regex::{Regex, RegexSet}; + use regex; + #[allow(dead_code)] + fn hi_mod() {} +} diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.rs b/src/tools/clippy/tests/ui/single_component_path_imports.rs index 9a427e90ad..09d4865859 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports.rs +++ b/src/tools/clippy/tests/ui/single_component_path_imports.rs @@ -19,3 +19,16 @@ fn main() { // False positive #5154, shouldn't trigger lint. m!(); } + +mod hello_mod { + use regex; + #[allow(dead_code)] + fn hello_mod() {} +} + +mod hi_mod { + use self::regex::{Regex, RegexSet}; + use regex; + #[allow(dead_code)] + fn hi_mod() {} +} diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.stderr b/src/tools/clippy/tests/ui/single_component_path_imports.stderr index 519ada0169..7005fa8f12 100644 --- a/src/tools/clippy/tests/ui/single_component_path_imports.stderr +++ b/src/tools/clippy/tests/ui/single_component_path_imports.stderr @@ -1,10 +1,16 @@ +error: this import is redundant + --> $DIR/single_component_path_imports.rs:24:5 + | +LL | use regex; + | ^^^^^^^^^^ help: remove it entirely + | + = note: `-D clippy::single-component-path-imports` implied by `-D warnings` + error: this import is redundant --> $DIR/single_component_path_imports.rs:6:1 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely - | - = note: `-D clippy::single-component-path-imports` implied by `-D warnings` -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed b/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed new file mode 100644 index 0000000000..05863f9a2b --- /dev/null +++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.fixed @@ -0,0 +1,21 @@ +// run-rustfix +// edition:2018 +#![warn(clippy::single_component_path_imports)] +#![allow(unused_imports)] + +// #7106: use statements exporting a macro within a crate should not trigger lint + +macro_rules! m1 { + () => {}; +} +pub(crate) use m1; // ok + +macro_rules! m2 { + () => {}; +} + // fail + +fn main() { + m1!(); + m2!(); +} diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs b/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs new file mode 100644 index 0000000000..633deea348 --- /dev/null +++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.rs @@ -0,0 +1,21 @@ +// run-rustfix +// edition:2018 +#![warn(clippy::single_component_path_imports)] +#![allow(unused_imports)] + +// #7106: use statements exporting a macro within a crate should not trigger lint + +macro_rules! m1 { + () => {}; +} +pub(crate) use m1; // ok + +macro_rules! m2 { + () => {}; +} +use m2; // fail + +fn main() { + m1!(); + m2!(); +} diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr b/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr new file mode 100644 index 0000000000..239efb393b --- /dev/null +++ b/src/tools/clippy/tests/ui/single_component_path_imports_macro.stderr @@ -0,0 +1,10 @@ +error: this import is redundant + --> $DIR/single_component_path_imports_macro.rs:16:1 + | +LL | use m2; // fail + | ^^^^^^^ help: remove it entirely + | + = note: `-D clippy::single-component-path-imports` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs new file mode 100644 index 0000000000..94117061b2 --- /dev/null +++ b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.rs @@ -0,0 +1,17 @@ +// edition:2018 +#![warn(clippy::single_component_path_imports)] +#![allow(unused_imports)] + +use regex; +use serde as edres; +pub use serde; + +fn main() { + regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); +} + +mod root_nested_use_mod { + use {regex, serde}; + #[allow(dead_code)] + fn root_nested_use_mod() {} +} diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr new file mode 100644 index 0000000000..0c3256c1ce --- /dev/null +++ b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr @@ -0,0 +1,25 @@ +error: this import is redundant + --> $DIR/single_component_path_imports_nested_first.rs:14:10 + | +LL | use {regex, serde}; + | ^^^^^ + | + = note: `-D clippy::single-component-path-imports` implied by `-D warnings` + = help: remove this import + +error: this import is redundant + --> $DIR/single_component_path_imports_nested_first.rs:14:17 + | +LL | use {regex, serde}; + | ^^^^^ + | + = help: remove this import + +error: this import is redundant + --> $DIR/single_component_path_imports_nested_first.rs:5:1 + | +LL | use regex; + | ^^^^^^^^^^ help: remove it entirely + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs b/src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs new file mode 100644 index 0000000000..94319ade0a --- /dev/null +++ b/src/tools/clippy/tests/ui/single_component_path_imports_self_after.rs @@ -0,0 +1,16 @@ +// edition:2018 +#![warn(clippy::single_component_path_imports)] +#![allow(unused_imports)] + +use self::regex::{Regex as xeger, RegexSet as tesxeger}; +pub use self::{ + regex::{Regex, RegexSet}, + some_mod::SomeType, +}; +use regex; + +mod some_mod { + pub struct SomeType; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs b/src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs new file mode 100644 index 0000000000..c7437b2345 --- /dev/null +++ b/src/tools/clippy/tests/ui/single_component_path_imports_self_before.rs @@ -0,0 +1,17 @@ +// edition:2018 +#![warn(clippy::single_component_path_imports)] +#![allow(unused_imports)] + +use regex; + +use self::regex::{Regex as xeger, RegexSet as tesxeger}; +pub use self::{ + regex::{Regex, RegexSet}, + some_mod::SomeType, +}; + +mod some_mod { + pub struct SomeType; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/single_element_loop.fixed b/src/tools/clippy/tests/ui/single_element_loop.fixed index 8ca068293a..c307afffcb 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.fixed +++ b/src/tools/clippy/tests/ui/single_element_loop.fixed @@ -8,4 +8,9 @@ fn main() { let item = &item1; println!("{}", item); } + + { + let item = &item1; + println!("{:?}", item); + } } diff --git a/src/tools/clippy/tests/ui/single_element_loop.rs b/src/tools/clippy/tests/ui/single_element_loop.rs index 57e9336a31..2c0c03b721 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.rs +++ b/src/tools/clippy/tests/ui/single_element_loop.rs @@ -7,4 +7,8 @@ fn main() { for item in &[item1] { println!("{}", item); } + + for item in [item1].iter() { + println!("{:?}", item); + } } diff --git a/src/tools/clippy/tests/ui/single_element_loop.stderr b/src/tools/clippy/tests/ui/single_element_loop.stderr index 90be1dc328..0e35a33ded 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.stderr +++ b/src/tools/clippy/tests/ui/single_element_loop.stderr @@ -15,5 +15,21 @@ LL | println!("{}", item); LL | } | -error: aborting due to previous error +error: for loop over a single element + --> $DIR/single_element_loop.rs:11:5 + | +LL | / for item in [item1].iter() { +LL | | println!("{:?}", item); +LL | | } + | |_____^ + | +help: try + | +LL | { +LL | let item = &item1; +LL | println!("{:?}", item); +LL | } + | + +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs index ca884b41c4..b1819e08d5 100644 --- a/src/tools/clippy/tests/ui/single_match.rs +++ b/src/tools/clippy/tests/ui/single_match.rs @@ -135,6 +135,14 @@ fn if_suggestion() { Bar::A => println!(), _ => (), } + + // issue #7038 + struct X; + let x = Some(X); + match x { + None => println!(), + _ => (), + }; } macro_rules! single_match { diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr index 7ea6955b74..9ef2a8668a 100644 --- a/src/tools/clippy/tests/ui/single_match.stderr +++ b/src/tools/clippy/tests/ui/single_match.stderr @@ -119,5 +119,14 @@ LL | | _ => (), LL | | } | |_____^ help: try this: `if let Bar::A = x { println!() }` -error: aborting due to 12 previous errors +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:142:5 + | +LL | / match x { +LL | | None => println!(), +LL | | _ => (), +LL | | }; + | |_____^ help: try this: `if let None = x { println!() }` + +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.fixed b/src/tools/clippy/tests/ui/stable_sort_primitive.fixed index 8f8f566593..f5f18169df 100644 --- a/src/tools/clippy/tests/ui/stable_sort_primitive.fixed +++ b/src/tools/clippy/tests/ui/stable_sort_primitive.fixed @@ -20,7 +20,7 @@ fn main() { // Negative examples: behavior changes if made unstable let mut vec = vec![1, 3, 2]; vec.sort_by_key(|i| i / 2); - vec.sort_by(|a, b| (a + b).cmp(&b)); + vec.sort_by(|&a, &b| (a + b).cmp(&b)); // negative examples - Not of a primitive type let mut vec_of_complex = vec![String::from("hello"), String::from("world!")]; vec_of_complex.sort(); diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.rs b/src/tools/clippy/tests/ui/stable_sort_primitive.rs index f9bd977906..8149c5638e 100644 --- a/src/tools/clippy/tests/ui/stable_sort_primitive.rs +++ b/src/tools/clippy/tests/ui/stable_sort_primitive.rs @@ -20,7 +20,7 @@ fn main() { // Negative examples: behavior changes if made unstable let mut vec = vec![1, 3, 2]; vec.sort_by_key(|i| i / 2); - vec.sort_by(|a, b| (a + b).cmp(&b)); + vec.sort_by(|&a, &b| (a + b).cmp(&b)); // negative examples - Not of a primitive type let mut vec_of_complex = vec![String::from("hello"), String::from("world!")]; vec_of_complex.sort(); diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed index ccf8f61c4a..df2256e4f9 100644 --- a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed +++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed @@ -8,15 +8,21 @@ fn str_lit_as_bytes() { let bs = br###"raw string with 3# plus " ""###; + let bs = b"lit to string".to_vec(); + let bs = b"lit to owned".to_vec(); + // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); let ubs = "hello there! this is a very long string".as_bytes(); + let ubs = "☃".to_string().into_bytes(); + let ubs = "this is also too long and shouldn't be fixed".to_string().into_bytes(); + let strify = stringify!(foobar).as_bytes(); let current_version = env!("CARGO_PKG_VERSION").as_bytes(); - let includestr = include_bytes!("entry_unfixable.rs"); + let includestr = include_bytes!("string_lit_as_bytes.rs"); let _ = b"string with newline\t\n"; } diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs index 178df08e24..c6bf8f732e 100644 --- a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs +++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs @@ -8,15 +8,21 @@ fn str_lit_as_bytes() { let bs = r###"raw string with 3# plus " ""###.as_bytes(); + let bs = "lit to string".to_string().into_bytes(); + let bs = "lit to owned".to_owned().into_bytes(); + // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); let ubs = "hello there! this is a very long string".as_bytes(); + let ubs = "☃".to_string().into_bytes(); + let ubs = "this is also too long and shouldn't be fixed".to_string().into_bytes(); + let strify = stringify!(foobar).as_bytes(); let current_version = env!("CARGO_PKG_VERSION").as_bytes(); - let includestr = include_str!("entry_unfixable.rs").as_bytes(); + let includestr = include_str!("string_lit_as_bytes.rs").as_bytes(); let _ = "string with newline\t\n".as_bytes(); } diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr index 99c512354d..f47d6161c6 100644 --- a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr +++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr @@ -12,17 +12,29 @@ error: calling `as_bytes()` on a string literal LL | let bs = r###"raw string with 3# plus " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###` +error: calling `into_bytes()` on a string literal + --> $DIR/string_lit_as_bytes.rs:11:14 + | +LL | let bs = "lit to string".to_string().into_bytes(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to string".to_vec()` + +error: calling `into_bytes()` on a string literal + --> $DIR/string_lit_as_bytes.rs:12:14 + | +LL | let bs = "lit to owned".to_owned().into_bytes(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to owned".to_vec()` + error: calling `as_bytes()` on `include_str!(..)` - --> $DIR/string_lit_as_bytes.rs:19:22 + --> $DIR/string_lit_as_bytes.rs:25:22 | -LL | let includestr = include_str!("entry_unfixable.rs").as_bytes(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry_unfixable.rs")` +LL | let includestr = include_str!("string_lit_as_bytes.rs").as_bytes(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("string_lit_as_bytes.rs")` error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:21:13 + --> $DIR/string_lit_as_bytes.rs:27:13 | LL | let _ = "string with newline/t/n".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline/t/n"` -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs index 226010ec6d..547615b10d 100644 --- a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs +++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs @@ -40,6 +40,7 @@ fn main() { { } + // This is fine, though weird. Allman style braces on the else. if foo() { } else @@ -76,4 +77,29 @@ fn main() { } if foo() { } + + // Almost Allman style braces. Lint these. + if foo() { + } + + else + { + + } + + if foo() { + } + else + + { + + } + + // #3864 - Allman style braces + if foo() + { + } + else + { + } } diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr index bbc036d376..d8d67b4138 100644 --- a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr +++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr @@ -41,37 +41,50 @@ LL | | { | = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` -error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:44:6 +error: this is an `else if` but the formatting might hide it + --> $DIR/suspicious_else_formatting.rs:51:6 | -LL | } +LL | } else | ______^ -LL | | else -LL | | { +LL | | if foo() { // the span of the above error should continue here | |____^ | - = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` + = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:50:6 + --> $DIR/suspicious_else_formatting.rs:56:6 | -LL | } else +LL | } | ______^ +LL | | else LL | | if foo() { // the span of the above error should continue here | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` -error: this is an `else if` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:55:6 +error: this is an `else {..}` but the formatting might hide it + --> $DIR/suspicious_else_formatting.rs:83:6 | LL | } | ______^ +LL | | LL | | else -LL | | if foo() { // the span of the above error should continue here +LL | | { | |____^ | - = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` + = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` + +error: this is an `else {..}` but the formatting might hide it + --> $DIR/suspicious_else_formatting.rs:91:6 + | +LL | } + | ______^ +LL | | else +LL | | +LL | | { + | |____^ + | + = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_map.rs b/src/tools/clippy/tests/ui/suspicious_map.rs index d838d8fde2..3a2a10cf09 100644 --- a/src/tools/clippy/tests/ui/suspicious_map.rs +++ b/src/tools/clippy/tests/ui/suspicious_map.rs @@ -2,4 +2,31 @@ fn main() { let _ = (0..3).map(|x| x + 2).count(); + + let f = |x| x + 1; + let _ = (0..3).map(f).count(); +} + +fn negative() { + // closure with side effects + let mut sum = 0; + let _ = (0..3).map(|x| sum += x).count(); + + // closure variable with side effects + let ext_closure = |x| sum += x; + let _ = (0..3).map(ext_closure).count(); + + // closure that returns unit + let _ = (0..3) + .map(|x| { + // do nothing + }) + .count(); + + // external function + let _ = (0..3).map(do_something).count(); +} + +fn do_something<T>(t: T) -> String { + unimplemented!() } diff --git a/src/tools/clippy/tests/ui/suspicious_map.stderr b/src/tools/clippy/tests/ui/suspicious_map.stderr index e1b4ba4037..8c3f36584a 100644 --- a/src/tools/clippy/tests/ui/suspicious_map.stderr +++ b/src/tools/clippy/tests/ui/suspicious_map.stderr @@ -7,5 +7,13 @@ LL | let _ = (0..3).map(|x| x + 2).count(); = note: `-D clippy::suspicious-map` implied by `-D warnings` = help: make sure you did not confuse `map` with `filter` or `for_each` -error: aborting due to previous error +error: this call to `map()` won't have an effect on the call to `count()` + --> $DIR/suspicious_map.rs:7:13 + | +LL | let _ = (0..3).map(f).count(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: make sure you did not confuse `map` with `filter` or `for_each` + +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/try_err.fixed b/src/tools/clippy/tests/ui/try_err.fixed index 5b96bb59c5..264194419c 100644 --- a/src/tools/clippy/tests/ui/try_err.fixed +++ b/src/tools/clippy/tests/ui/try_err.fixed @@ -160,3 +160,11 @@ pub fn poll_next(ready: bool) -> Poll<Option<io::Result<()>>> { Poll::Ready(None) } + +// Tests that `return` is not duplicated +pub fn try_return(x: bool) -> Result<i32, i32> { + if x { + return Err(42); + } + Ok(0) +} diff --git a/src/tools/clippy/tests/ui/try_err.rs b/src/tools/clippy/tests/ui/try_err.rs index f220d697d2..bc6979bf45 100644 --- a/src/tools/clippy/tests/ui/try_err.rs +++ b/src/tools/clippy/tests/ui/try_err.rs @@ -160,3 +160,11 @@ pub fn poll_next(ready: bool) -> Poll<Option<io::Result<()>>> { Poll::Ready(None) } + +// Tests that `return` is not duplicated +pub fn try_return(x: bool) -> Result<i32, i32> { + if x { + return Err(42)?; + } + Ok(0) +} diff --git a/src/tools/clippy/tests/ui/try_err.stderr b/src/tools/clippy/tests/ui/try_err.stderr index 2c01d37192..8f332a9b64 100644 --- a/src/tools/clippy/tests/ui/try_err.stderr +++ b/src/tools/clippy/tests/ui/try_err.stderr @@ -74,5 +74,11 @@ error: returning an `Err(_)` with the `?` operator LL | Err(io::ErrorKind::NotFound)? | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))` -error: aborting due to 10 previous errors +error: returning an `Err(_)` with the `?` operator + --> $DIR/try_err.rs:167:16 + | +LL | return Err(42)?; + | ^^^^^^^^ help: try this: `Err(42)` + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/complex_types.rs b/src/tools/clippy/tests/ui/type_complexity.rs similarity index 100% rename from src/tools/clippy/tests/ui/complex_types.rs rename to src/tools/clippy/tests/ui/type_complexity.rs diff --git a/src/tools/clippy/tests/ui/complex_types.stderr b/src/tools/clippy/tests/ui/type_complexity.stderr similarity index 85% rename from src/tools/clippy/tests/ui/complex_types.stderr rename to src/tools/clippy/tests/ui/type_complexity.stderr index 7fcbb4bce8..7879233fdf 100644 --- a/src/tools/clippy/tests/ui/complex_types.stderr +++ b/src/tools/clippy/tests/ui/type_complexity.stderr @@ -1,5 +1,5 @@ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:7:12 + --> $DIR/type_complexity.rs:7:12 | LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,85 +7,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); = note: `-D clippy::type-complexity` implied by `-D warnings` error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:8:12 + --> $DIR/type_complexity.rs:8:12 | LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:11:8 + --> $DIR/type_complexity.rs:11:8 | LL | f: Vec<Vec<Box<(u32, u32, u32, u32)>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:14:11 + --> $DIR/type_complexity.rs:14:11 | LL | struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:17:11 + --> $DIR/type_complexity.rs:17:11 | LL | Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:18:17 + --> $DIR/type_complexity.rs:18:17 | LL | Struct { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:22:14 + --> $DIR/type_complexity.rs:22:14 | LL | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:23:30 + --> $DIR/type_complexity.rs:23:30 | LL | fn impl_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:27:14 + --> $DIR/type_complexity.rs:27:14 | LL | const A: Vec<Vec<Box<(u32, u32, u32, u32)>>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:28:14 + --> $DIR/type_complexity.rs:28:14 | LL | type B = Vec<Vec<Box<(u32, u32, u32, u32)>>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:29:25 + --> $DIR/type_complexity.rs:29:25 | LL | fn method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:30:29 + --> $DIR/type_complexity.rs:30:29 | LL | fn def_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:33:15 + --> $DIR/type_complexity.rs:33:15 | LL | fn test1() -> Vec<Vec<Box<(u32, u32, u32, u32)>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:37:14 + --> $DIR/type_complexity.rs:37:14 | LL | fn test2(_x: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> $DIR/complex_types.rs:40:13 + --> $DIR/type_complexity.rs:40:13 | LL | let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/uninit.rs b/src/tools/clippy/tests/ui/uninit.rs index f42b884e0f..1ed3883c1f 100644 --- a/src/tools/clippy/tests/ui/uninit.rs +++ b/src/tools/clippy/tests/ui/uninit.rs @@ -1,6 +1,6 @@ #![feature(stmt_expr_attributes)] -use std::mem::MaybeUninit; +use std::mem::{self, MaybeUninit}; fn main() { let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; @@ -19,4 +19,7 @@ fn main() { // This is OK, because all constitutent types are uninit-compatible. let _: (MaybeUninit<usize>, [MaybeUninit<bool>; 2]) = unsafe { MaybeUninit::uninit().assume_init() }; + + // Was a false negative. + let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() }; } diff --git a/src/tools/clippy/tests/ui/uninit.stderr b/src/tools/clippy/tests/ui/uninit.stderr index a37233ecdd..85b64a8419 100644 --- a/src/tools/clippy/tests/ui/uninit.stderr +++ b/src/tools/clippy/tests/ui/uninit.stderr @@ -12,5 +12,11 @@ error: this call for this type may be undefined behavior LL | let _: [u8; 0] = unsafe { MaybeUninit::uninit().assume_init() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: this call for this type may be undefined behavior + --> $DIR/uninit.rs:24:29 + | +LL | let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr index 8981d13e8e..70aa448af6 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr @@ -1,22 +1,22 @@ -error: casting to the same type is unnecessary (`i32` -> `i32`) +error: casting integer literal to `i32` is unnecessary --> $DIR/unnecessary_cast.rs:6:5 | LL | 1i32 as i32; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ help: try: `1_i32` | = note: `-D clippy::unnecessary-cast` implied by `-D warnings` -error: casting to the same type is unnecessary (`f32` -> `f32`) +error: casting float literal to `f32` is unnecessary --> $DIR/unnecessary_cast.rs:7:5 | LL | 1f32 as f32; - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ help: try: `1_f32` error: casting to the same type is unnecessary (`bool` -> `bool`) --> $DIR/unnecessary_cast.rs:8:5 | LL | false as bool; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: try: `false` error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_self_imports.fixed b/src/tools/clippy/tests/ui/unnecessary_self_imports.fixed new file mode 100644 index 0000000000..1185eaa1d5 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_self_imports.fixed @@ -0,0 +1,10 @@ +// run-rustfix +#![warn(clippy::unnecessary_self_imports)] +#![allow(unused_imports, dead_code)] + +use std::collections::hash_map::{self, *}; +use std::fs as alias; +use std::io::{self, Read}; +use std::rc; + +fn main() {} diff --git a/src/tools/clippy/tests/ui/unnecessary_self_imports.rs b/src/tools/clippy/tests/ui/unnecessary_self_imports.rs new file mode 100644 index 0000000000..56bfbc0940 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_self_imports.rs @@ -0,0 +1,10 @@ +// run-rustfix +#![warn(clippy::unnecessary_self_imports)] +#![allow(unused_imports, dead_code)] + +use std::collections::hash_map::{self, *}; +use std::fs::{self as alias}; +use std::io::{self, Read}; +use std::rc::{self}; + +fn main() {} diff --git a/src/tools/clippy/tests/ui/unnecessary_self_imports.stderr b/src/tools/clippy/tests/ui/unnecessary_self_imports.stderr new file mode 100644 index 0000000000..83a5618c98 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_self_imports.stderr @@ -0,0 +1,23 @@ +error: import ending with `::{self}` + --> $DIR/unnecessary_self_imports.rs:6:1 + | +LL | use std::fs::{self as alias}; + | ^^^^^^^^^-------------------- + | | + | help: consider omitting `::{self}`: `fs as alias;` + | + = note: `-D clippy::unnecessary-self-imports` implied by `-D warnings` + = note: this will slightly change semantics; any non-module items at the same path will also be imported + +error: import ending with `::{self}` + --> $DIR/unnecessary_self_imports.rs:8:1 + | +LL | use std::rc::{self}; + | ^^^^^^^^^----------- + | | + | help: consider omitting `::{self}`: `rc;` + | + = note: this will slightly change semantics; any non-module items at the same path will also be imported + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed index 13a036cd80..46463a29e9 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed +++ b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(or_patterns)] #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.rs b/src/tools/clippy/tests/ui/unnested_or_patterns.rs index 4a10cc702c..8ce0738bfc 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns.rs +++ b/src/tools/clippy/tests/ui/unnested_or_patterns.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(or_patterns)] #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr index 1899dc657d..f7cb513c15 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr +++ b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:10:12 + --> $DIR/unnested_or_patterns.rs:9:12 | LL | if let box 0 | box 2 = Box::new(0) {} | ^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let box (0 | 2) = Box::new(0) {} | ^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:11:12 + --> $DIR/unnested_or_patterns.rs:10:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:13:12 + --> $DIR/unnested_or_patterns.rs:12:12 | LL | if let &0 | C0 | &2 = &0 {} | ^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let &(0 | 2) | C0 = &0 {} | ^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:14:12 + --> $DIR/unnested_or_patterns.rs:13:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let &mut (0 | 2) = &mut 0 {} | ^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:15:12 + --> $DIR/unnested_or_patterns.rs:14:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let x @ (0 | 2) = 0 {} | ^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:16:12 + --> $DIR/unnested_or_patterns.rs:15:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let (0, 1 | 2 | 3) = (0, 0) {} | ^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:17:12 + --> $DIR/unnested_or_patterns.rs:16:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let (1 | 2 | 3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:18:12 + --> $DIR/unnested_or_patterns.rs:17:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | if let (x, ..) | (x, 1 | 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:19:12 + --> $DIR/unnested_or_patterns.rs:18:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | if let [0 | 1] = [0] {} | ^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:20:12 + --> $DIR/unnested_or_patterns.rs:19:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL | if let [x, 0 | 1] = [0, 1] {} | ^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:21:12 + --> $DIR/unnested_or_patterns.rs:20:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | if let [x, 0 | 1 | 2] = [0, 1] {} | ^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:22:12 + --> $DIR/unnested_or_patterns.rs:21:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | if let [x, ..] | [x, 1 | 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:24:12 + --> $DIR/unnested_or_patterns.rs:23:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | if let TS(0 | 1, x) = TS(0, 0) {} | ^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:25:12 + --> $DIR/unnested_or_patterns.rs:24:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:26:12 + --> $DIR/unnested_or_patterns.rs:25:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:31:12 + --> $DIR/unnested_or_patterns.rs:30:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed index 02a129c55a..d3539d7981 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed +++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(or_patterns)] #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs index acf3158989..9cea5cdea6 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs +++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(or_patterns)] #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr index 1847fd8e09..9042c9c00b 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr +++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:10:12 + --> $DIR/unnested_or_patterns2.rs:9:12 | LL | if let Some(Some(0)) | Some(Some(1)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(Some(0 | 1)) = None {} | ^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:11:12 + --> $DIR/unnested_or_patterns2.rs:10:12 | LL | if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let Some(Some(0 | 1 | 2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:12:12 + --> $DIR/unnested_or_patterns2.rs:11:12 | LL | if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:13:12 + --> $DIR/unnested_or_patterns2.rs:12:12 | LL | if let Some(Some(0) | Some(1 | 2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let Some(Some(0 | 1 | 2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:14:12 + --> $DIR/unnested_or_patterns2.rs:13:12 | LL | if let ((0,),) | ((1,) | (2,),) = ((0,),) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let ((0 | 1 | 2,),) = ((0,),) {} | ^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:15:12 + --> $DIR/unnested_or_patterns2.rs:14:12 | LL | if let 0 | (1 | 2) = 0 {} | ^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let 0 | 1 | 2 = 0 {} | ^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:16:12 + --> $DIR/unnested_or_patterns2.rs:15:12 | LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:17:12 + --> $DIR/unnested_or_patterns2.rs:16:12 | LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns3.rs b/src/tools/clippy/tests/ui/unnested_or_patterns3.rs deleted file mode 100644 index 6bd35057bf..0000000000 --- a/src/tools/clippy/tests/ui/unnested_or_patterns3.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![warn(clippy::unnested_or_patterns)] - -// Test that `unnested_or_patterns` does not trigger without enabling `or_patterns` -fn main() { - if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} -} diff --git a/src/tools/clippy/tests/ui/unused_io_amount.rs b/src/tools/clippy/tests/ui/unused_io_amount.rs index ebaba9629d..8b141e2594 100644 --- a/src/tools/clippy/tests/ui/unused_io_amount.rs +++ b/src/tools/clippy/tests/ui/unused_io_amount.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![warn(clippy::unused_io_amount)] -use std::io; +use std::io::{self, Read}; fn question_mark<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> { s.write(b"test")?; @@ -22,4 +22,43 @@ fn vectored<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> { Ok(()) } +fn ok(file: &str) -> Option<()> { + let mut reader = std::fs::File::open(file).ok()?; + let mut result = [0u8; 0]; + reader.read(&mut result).ok()?; + Some(()) +} + +#[allow(clippy::redundant_closure)] +#[allow(clippy::bind_instead_of_map)] +fn or_else(file: &str) -> io::Result<()> { + let mut reader = std::fs::File::open(file)?; + let mut result = [0u8; 0]; + reader.read(&mut result).or_else(|err| Err(err))?; + Ok(()) +} + +#[derive(Debug)] +enum Error { + Kind, +} + +fn or(file: &str) -> Result<(), Error> { + let mut reader = std::fs::File::open(file).unwrap(); + let mut result = [0u8; 0]; + reader.read(&mut result).or(Err(Error::Kind))?; + Ok(()) +} + +fn combine_or(file: &str) -> Result<(), Error> { + let mut reader = std::fs::File::open(file).unwrap(); + let mut result = [0u8; 0]; + reader + .read(&mut result) + .or(Err(Error::Kind)) + .or(Err(Error::Kind)) + .expect("error"); + Ok(()) +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/unused_io_amount.stderr b/src/tools/clippy/tests/ui/unused_io_amount.stderr index 5219d63980..d8dfc0e5a7 100644 --- a/src/tools/clippy/tests/ui/unused_io_amount.stderr +++ b/src/tools/clippy/tests/ui/unused_io_amount.stderr @@ -36,5 +36,33 @@ error: written amount is not handled LL | s.write_vectored(&[io::IoSlice::new(&[])])?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: read amount is not handled. Use `Read::read_exact` instead + --> $DIR/unused_io_amount.rs:28:5 + | +LL | reader.read(&mut result).ok()?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: read amount is not handled. Use `Read::read_exact` instead + --> $DIR/unused_io_amount.rs:37:5 + | +LL | reader.read(&mut result).or_else(|err| Err(err))?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: read amount is not handled. Use `Read::read_exact` instead + --> $DIR/unused_io_amount.rs:49:5 + | +LL | reader.read(&mut result).or(Err(Error::Kind))?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: read amount is not handled. Use `Read::read_exact` instead + --> $DIR/unused_io_amount.rs:56:5 + | +LL | / reader +LL | | .read(&mut result) +LL | | .or(Err(Error::Kind)) +LL | | .or(Err(Error::Kind)) +LL | | .expect("error"); + | |________________________^ + +error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.rs b/src/tools/clippy/tests/ui/upper_case_acronyms.rs index 735909887a..48bb9e54b1 100644 --- a/src/tools/clippy/tests/ui/upper_case_acronyms.rs +++ b/src/tools/clippy/tests/ui/upper_case_acronyms.rs @@ -20,4 +20,22 @@ enum Flags { // `GccLlvmSomething` struct GCCLLVMSomething; +// public items must not be linted +pub struct NOWARNINGHERE; +pub struct ALSONoWarningHERE; + +// enum variants should not be linted if the num is pub +pub enum ParseError<T> { + YDB(u8), + Utf8(std::string::FromUtf8Error), + Parse(T, String), +} + +// private, do lint here +enum ParseErrorPrivate<T> { + WASD(u8), + Utf8(std::string::FromUtf8Error), + Parse(T, String), +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.stderr b/src/tools/clippy/tests/ui/upper_case_acronyms.stderr index bbe38991e5..250b196a99 100644 --- a/src/tools/clippy/tests/ui/upper_case_acronyms.stderr +++ b/src/tools/clippy/tests/ui/upper_case_acronyms.stderr @@ -48,5 +48,11 @@ error: name `FIN` contains a capitalized acronym LL | FIN, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Fin` -error: aborting due to 8 previous errors +error: name `WASD` contains a capitalized acronym + --> $DIR/upper_case_acronyms.rs:36:5 + | +LL | WASD(u8), + | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Wasd` + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed index b94d5448d9..1282befdfb 100644 --- a/src/tools/clippy/tests/ui/use_self.fixed +++ b/src/tools/clippy/tests/ui/use_self.fixed @@ -75,13 +75,13 @@ mod lifetimes { mod issue2894 { trait IntoBytes { - fn to_bytes(&self) -> Vec<u8>; + fn to_bytes(self) -> Vec<u8>; } // This should not be linted impl IntoBytes for u8 { - fn to_bytes(&self) -> Vec<u8> { - vec![*self] + fn to_bytes(self) -> Vec<u8> { + vec![self] } } } diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs index ac99c6d9d7..7aaac7b241 100644 --- a/src/tools/clippy/tests/ui/use_self.rs +++ b/src/tools/clippy/tests/ui/use_self.rs @@ -75,13 +75,13 @@ mod lifetimes { mod issue2894 { trait IntoBytes { - fn to_bytes(&self) -> Vec<u8>; + fn to_bytes(self) -> Vec<u8>; } // This should not be linted impl IntoBytes for u8 { - fn to_bytes(&self) -> Vec<u8> { - vec![*self] + fn to_bytes(self) -> Vec<u8> { + vec![self] } } } diff --git a/src/tools/clippy/tests/ui/vec.fixed b/src/tools/clippy/tests/ui/vec.fixed index 8567715962..da35f2e5c1 100644 --- a/src/tools/clippy/tests/ui/vec.fixed +++ b/src/tools/clippy/tests/ui/vec.fixed @@ -6,9 +6,14 @@ struct NonCopy; fn on_slice(_: &[u8]) {} + +fn on_mut_slice(_: &mut [u8]) {} + #[allow(clippy::ptr_arg)] fn on_vec(_: &Vec<u8>) {} +fn on_mut_vec(_: &mut Vec<u8>) {} + struct Line { length: usize, } @@ -22,28 +27,38 @@ impl Line { fn main() { on_slice(&[]); on_slice(&[]); + on_mut_slice(&mut []); on_slice(&[1, 2]); on_slice(&[1, 2]); + on_mut_slice(&mut [1, 2]); on_slice(&[1, 2]); on_slice(&[1, 2]); + on_mut_slice(&mut [1, 2]); #[rustfmt::skip] on_slice(&[1, 2]); on_slice(&[1, 2]); + on_mut_slice(&mut [1, 2]); on_slice(&[1; 2]); on_slice(&[1; 2]); + on_mut_slice(&mut [1; 2]); on_vec(&vec![]); on_vec(&vec![1, 2]); on_vec(&vec![1; 2]); + on_mut_vec(&mut vec![]); + on_mut_vec(&mut vec![1, 2]); + on_mut_vec(&mut vec![1; 2]); // Now with non-constant expressions let line = Line { length: 2 }; on_slice(&vec![2; line.length]); on_slice(&vec![2; line.length()]); + on_mut_slice(&mut vec![2; line.length]); + on_mut_slice(&mut vec![2; line.length()]); for a in &[1, 2, 3] { println!("{:?}", a); @@ -54,6 +69,7 @@ fn main() { } on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` + on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` // Ok for a in vec![1; 201] { diff --git a/src/tools/clippy/tests/ui/vec.rs b/src/tools/clippy/tests/ui/vec.rs index 03b8ee8166..e9ed83e5c5 100644 --- a/src/tools/clippy/tests/ui/vec.rs +++ b/src/tools/clippy/tests/ui/vec.rs @@ -6,9 +6,14 @@ struct NonCopy; fn on_slice(_: &[u8]) {} + +fn on_mut_slice(_: &mut [u8]) {} + #[allow(clippy::ptr_arg)] fn on_vec(_: &Vec<u8>) {} +fn on_mut_vec(_: &mut Vec<u8>) {} + struct Line { length: usize, } @@ -22,28 +27,38 @@ impl Line { fn main() { on_slice(&vec![]); on_slice(&[]); + on_mut_slice(&mut vec![]); on_slice(&vec![1, 2]); on_slice(&[1, 2]); + on_mut_slice(&mut vec![1, 2]); on_slice(&vec![1, 2]); on_slice(&[1, 2]); + on_mut_slice(&mut vec![1, 2]); #[rustfmt::skip] on_slice(&vec!(1, 2)); on_slice(&[1, 2]); + on_mut_slice(&mut vec![1, 2]); on_slice(&vec![1; 2]); on_slice(&[1; 2]); + on_mut_slice(&mut vec![1; 2]); on_vec(&vec![]); on_vec(&vec![1, 2]); on_vec(&vec![1; 2]); + on_mut_vec(&mut vec![]); + on_mut_vec(&mut vec![1, 2]); + on_mut_vec(&mut vec![1; 2]); // Now with non-constant expressions let line = Line { length: 2 }; on_slice(&vec![2; line.length]); on_slice(&vec![2; line.length()]); + on_mut_slice(&mut vec![2; line.length]); + on_mut_slice(&mut vec![2; line.length()]); for a in vec![1, 2, 3] { println!("{:?}", a); @@ -54,6 +69,7 @@ fn main() { } on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` + on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` // Ok for a in vec![1; 201] { diff --git a/src/tools/clippy/tests/ui/vec.stderr b/src/tools/clippy/tests/ui/vec.stderr index 37e28ebddb..7d1de05a5c 100644 --- a/src/tools/clippy/tests/ui/vec.stderr +++ b/src/tools/clippy/tests/ui/vec.stderr @@ -1,5 +1,5 @@ error: useless use of `vec!` - --> $DIR/vec.rs:23:14 + --> $DIR/vec.rs:28:14 | LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` @@ -7,34 +7,64 @@ LL | on_slice(&vec![]); = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:26:14 + --> $DIR/vec.rs:30:18 + | +LL | on_mut_slice(&mut vec![]); + | ^^^^^^^^^^^ help: you can use a slice directly: `&mut []` + +error: useless use of `vec!` + --> $DIR/vec.rs:32:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:29:14 + --> $DIR/vec.rs:34:18 + | +LL | on_mut_slice(&mut vec![1, 2]); + | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` + +error: useless use of `vec!` + --> $DIR/vec.rs:36:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:32:14 + --> $DIR/vec.rs:38:18 + | +LL | on_mut_slice(&mut vec![1, 2]); + | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` + +error: useless use of `vec!` + --> $DIR/vec.rs:40:14 | LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:35:14 + --> $DIR/vec.rs:42:18 + | +LL | on_mut_slice(&mut vec![1, 2]); + | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` + +error: useless use of `vec!` + --> $DIR/vec.rs:44:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:48:14 + --> $DIR/vec.rs:46:18 + | +LL | on_mut_slice(&mut vec![1; 2]); + | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]` + +error: useless use of `vec!` + --> $DIR/vec.rs:63:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` -error: aborting due to 6 previous errors +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/vec_box_sized.fixed b/src/tools/clippy/tests/ui/vec_box_sized.fixed index 4fa28b525c..a40d91fdb1 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.fixed +++ b/src/tools/clippy/tests/ui/vec_box_sized.fixed @@ -9,6 +9,8 @@ struct BigStruct([i32; 10000]); /// The following should trigger the lint mod should_trigger { use super::SizedStruct; + const C: Vec<i32> = Vec::new(); + static S: Vec<i32> = Vec::new(); struct StructWithVecBox { sized_type: Vec<SizedStruct>, diff --git a/src/tools/clippy/tests/ui/vec_box_sized.rs b/src/tools/clippy/tests/ui/vec_box_sized.rs index 7dc735cd90..843bbb64e7 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.rs +++ b/src/tools/clippy/tests/ui/vec_box_sized.rs @@ -9,6 +9,8 @@ struct BigStruct([i32; 10000]); /// The following should trigger the lint mod should_trigger { use super::SizedStruct; + const C: Vec<Box<i32>> = Vec::new(); + static S: Vec<Box<i32>> = Vec::new(); struct StructWithVecBox { sized_type: Vec<Box<SizedStruct>>, diff --git a/src/tools/clippy/tests/ui/vec_box_sized.stderr b/src/tools/clippy/tests/ui/vec_box_sized.stderr index 83435a40aa..c518267f04 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.stderr +++ b/src/tools/clippy/tests/ui/vec_box_sized.stderr @@ -1,28 +1,40 @@ error: `Vec<T>` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:14:21 + --> $DIR/vec_box_sized.rs:12:14 | -LL | sized_type: Vec<Box<SizedStruct>>, - | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>` +LL | const C: Vec<Box<i32>> = Vec::new(); + | ^^^^^^^^^^^^^ help: try: `Vec<i32>` | = note: `-D clippy::vec-box` implied by `-D warnings` error: `Vec<T>` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:17:14 + --> $DIR/vec_box_sized.rs:13:15 + | +LL | static S: Vec<Box<i32>> = Vec::new(); + | ^^^^^^^^^^^^^ help: try: `Vec<i32>` + +error: `Vec<T>` is already on the heap, the boxing is unnecessary + --> $DIR/vec_box_sized.rs:16:21 + | +LL | sized_type: Vec<Box<SizedStruct>>, + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>` + +error: `Vec<T>` is already on the heap, the boxing is unnecessary + --> $DIR/vec_box_sized.rs:19:14 | LL | struct A(Vec<Box<SizedStruct>>); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>` error: `Vec<T>` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:18:18 + --> $DIR/vec_box_sized.rs:20:18 | LL | struct B(Vec<Vec<Box<(u32)>>>); | ^^^^^^^^^^^^^^^ help: try: `Vec<u32>` error: `Vec<T>` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:46:23 + --> $DIR/vec_box_sized.rs:48:23 | LL | pub fn f() -> Vec<Box<S>> { | ^^^^^^^^^^^ help: try: `Vec<S>` -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed index e99c98ac79..749393db12 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed @@ -2,7 +2,6 @@ #![warn(clippy::while_let_on_iterator)] #![allow(clippy::never_loop, unreachable_code, unused_mut)] -#![feature(or_patterns)] fn base() { let mut iter = 1..20; diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs index ba13172428..30e3b82a7c 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs @@ -2,7 +2,6 @@ #![warn(clippy::while_let_on_iterator)] #![allow(clippy::never_loop, unreachable_code, unused_mut)] -#![feature(or_patterns)] fn base() { let mut iter = 1..20; diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr index aa980d9965..6554977c79 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:9:5 + --> $DIR/while_let_on_iterator.rs:8:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,37 +7,37 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:14:5 + --> $DIR/while_let_on_iterator.rs:13:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:19:5 + --> $DIR/while_let_on_iterator.rs:18:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:102:9 + --> $DIR/while_let_on_iterator.rs:101:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:109:9 + --> $DIR/while_let_on_iterator.rs:108:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:122:9 + --> $DIR/while_let_on_iterator.rs:121:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:154:9 + --> $DIR/while_let_on_iterator.rs:153:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed index c266f684a3..129d82652d 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed @@ -77,7 +77,7 @@ fn main() { let error_kind = ErrorKind::NotFound; match error_kind { ErrorKind::NotFound => {}, - std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _ => {}, + 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 | _ => {}, } match error_kind { ErrorKind::NotFound => {}, @@ -98,6 +98,7 @@ fn main() { ErrorKind::Interrupted => {}, ErrorKind::Other => {}, ErrorKind::UnexpectedEof => {}, + ErrorKind::Unsupported => {}, _ => {}, } } diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs index 2dbf726d5d..028ecb63e7 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs @@ -98,6 +98,7 @@ fn main() { ErrorKind::Interrupted => {}, ErrorKind::Other => {}, ErrorKind::UnexpectedEof => {}, + ErrorKind::Unsupported => {}, _ => {}, } } diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr index 0da2b68ba0..fd45cad00d 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr @@ -1,4 +1,4 @@ -error: wildcard match will miss any future added variants +error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:39:9 | LL | _ => eprintln!("Not red"), @@ -10,29 +10,29 @@ note: the lint level is defined here LL | #![deny(clippy::wildcard_enum_match_arm)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: wildcard match will miss any future added variants +error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:43: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 miss any future added variants +error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:47: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 miss any future added variants +error: wildcard match will also match any future added variants --> $DIR/wildcard_enum_match_arm.rs:63:9 | LL | _ => "No red", | ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` -error: match on non-exhaustive enum doesn't explicitly match all known variants +error: wildcard matches known variants and will also match future added variants --> $DIR/wildcard_enum_match_arm.rs:80:9 | LL | _ => {}, - | ^ help: try this: `std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _` + | ^ 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 | _` error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/write_literal.stderr b/src/tools/clippy/tests/ui/write_literal.stderr index e54d89ecf2..507a78e828 100644 --- a/src/tools/clippy/tests/ui/write_literal.stderr +++ b/src/tools/clippy/tests/ui/write_literal.stderr @@ -5,66 +5,120 @@ LL | write!(&mut v, "Hello {}", "world"); | ^^^^^^^ | = note: `-D clippy::write-literal` implied by `-D warnings` +help: try this + | +LL | write!(&mut v, "Hello world"); + | ^^^^^-- error: literal with an empty format string --> $DIR/write_literal.rs:31:44 | LL | writeln!(&mut v, "Hello {} {}", world, "world"); | ^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "Hello {} world", world); + | ^^^^^ -- error: literal with an empty format string --> $DIR/write_literal.rs:32:34 | LL | writeln!(&mut v, "Hello {}", "world"); | ^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "Hello world"); + | ^^^^^-- error: literal with an empty format string --> $DIR/write_literal.rs:37:33 | LL | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "hello {1}", "world"); + | ^^^^^ -- error: literal with an empty format string --> $DIR/write_literal.rs:37:42 | LL | writeln!(&mut v, "{0} {1}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "{0} world", "hello"); + | ^^^^^ -- error: literal with an empty format string --> $DIR/write_literal.rs:38:33 | LL | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "{1} hello", "world"); + | ^^^^^-- error: literal with an empty format string --> $DIR/write_literal.rs:38:42 | LL | writeln!(&mut v, "{1} {0}", "hello", "world"); | ^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "world {0}", "hello"); + | ^^^^^ -- error: literal with an empty format string - --> $DIR/write_literal.rs:41:43 + --> $DIR/write_literal.rs:41:37 | LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "hello {bar}", bar = "world"); + | ^^^^^ -- error: literal with an empty format string - --> $DIR/write_literal.rs:41:58 + --> $DIR/write_literal.rs:41:52 | LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "{foo} world", foo = "hello"); + | ^^^^^ -- error: literal with an empty format string - --> $DIR/write_literal.rs:42:43 + --> $DIR/write_literal.rs:42:37 | LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "{bar} hello", bar = "world"); + | ^^^^^-- error: literal with an empty format string - --> $DIR/write_literal.rs:42:58 + --> $DIR/write_literal.rs:42:52 | LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^ + | ^^^^^^^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, "world {foo}", foo = "hello"); + | ^^^^^ -- error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/write_literal_2.rs b/src/tools/clippy/tests/ui/write_literal_2.rs new file mode 100644 index 0000000000..f341e8215e --- /dev/null +++ b/src/tools/clippy/tests/ui/write_literal_2.rs @@ -0,0 +1,27 @@ +#![allow(unused_must_use)] +#![warn(clippy::write_literal)] + +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + writeln!(&mut v, "{}", "{hello}"); + writeln!(&mut v, r"{}", r"{hello}"); + writeln!(&mut v, "{}", '\''); + writeln!(&mut v, "{}", '"'); + writeln!(&mut v, r"{}", '"'); // don't lint + writeln!(&mut v, r"{}", '\''); + writeln!( + &mut v, + "some {}", + "hello \ + world!" + ); + writeln!( + &mut v, + "some {}\ + {} \\ {}", + "1", "2", "3", + ); +} diff --git a/src/tools/clippy/tests/ui/write_literal_2.stderr b/src/tools/clippy/tests/ui/write_literal_2.stderr new file mode 100644 index 0000000000..0aa1b55e58 --- /dev/null +++ b/src/tools/clippy/tests/ui/write_literal_2.stderr @@ -0,0 +1,107 @@ +error: literal with an empty format string + --> $DIR/write_literal_2.rs:9:28 + | +LL | writeln!(&mut v, "{}", "{hello}"); + | ^^^^^^^^^ + | + = note: `-D clippy::write-literal` implied by `-D warnings` +help: try this + | +LL | writeln!(&mut v, "{{hello}}"); + | ^^^^^^^^^-- + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:10:29 + | +LL | writeln!(&mut v, r"{}", r"{hello}"); + | ^^^^^^^^^^ + | +help: try this + | +LL | writeln!(&mut v, r"{{hello}}"); + | ^^^^^^^^^-- + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:11:28 + | +LL | writeln!(&mut v, "{}", '/''); + | ^^^^ + | +help: try this + | +LL | writeln!(&mut v, "'"); + | ^-- + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:12:28 + | +LL | writeln!(&mut v, "{}", '"'); + | ^^^ + | +help: try this + | +LL | writeln!(&mut v, "/""); + | ^^-- + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:14:29 + | +LL | writeln!(&mut v, r"{}", '/''); + | ^^^^ + | +help: try this + | +LL | writeln!(&mut v, r"'"); + | ^-- + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:18:9 + | +LL | / "hello / +LL | | world!" + | |_______________^ + | +help: try this + | +LL | "some hello / +LL | world!" + | + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:25:9 + | +LL | "1", "2", "3", + | ^^^ + | +help: try this + | +LL | "some 1/ +LL | {} / {}", "2", "3", + | + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:25:14 + | +LL | "1", "2", "3", + | ^^^ + | +help: try this + | +LL | 2 / {}", +LL | "1", "3", + | + +error: literal with an empty format string + --> $DIR/write_literal_2.rs:25:19 + | +LL | "1", "2", "3", + | ^^^ + | +help: try this + | +LL | {} / 3", +LL | "1", "2", + | + +error: aborting due to 9 previous errors + diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.rs b/src/tools/clippy/tests/ui/wrong_self_convention.rs index 6cfc0fcb4c..cdfbdb8b0d 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention.rs +++ b/src/tools/clippy/tests/ui/wrong_self_convention.rs @@ -163,3 +163,30 @@ mod issue6307 { fn to_mut(&mut self); } } + +mod issue6727 { + #[derive(Clone, Copy)] + struct FooCopy; + + impl FooCopy { + fn to_u64(self) -> u64 { + 1 + } + // trigger lint + fn to_u64_v2(&self) -> u64 { + 1 + } + } + + struct FooNoCopy; + + impl FooNoCopy { + // trigger lint + fn to_u64(self) -> u64 { + 2 + } + fn to_u64_v2(&self) -> u64 { + 2 + } + } +} diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.stderr b/src/tools/clippy/tests/ui/wrong_self_convention.stderr index 32bd9075bd..29f5ba8269 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention.stderr +++ b/src/tools/clippy/tests/ui/wrong_self_convention.stderr @@ -1,148 +1,195 @@ -error: methods called `from_*` usually take no self; consider choosing a less ambiguous name +error: methods called `from_*` usually take no `self` --> $DIR/wrong_self_convention.rs:18:17 | LL | fn from_i32(self) {} | ^^^^ | = note: `-D clippy::wrong-self-convention` implied by `-D warnings` + = help: consider choosing a less ambiguous name -error: methods called `from_*` usually take no self; consider choosing a less ambiguous name +error: methods called `from_*` usually take no `self` --> $DIR/wrong_self_convention.rs:24:21 | LL | pub fn from_i64(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name +error: methods called `as_*` usually take `self` by reference or `self` by mutable reference --> $DIR/wrong_self_convention.rs:36:15 | LL | fn as_i32(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name +error: methods called `into_*` usually take `self` by value --> $DIR/wrong_self_convention.rs:38:17 | LL | fn into_i32(&self) {} | ^^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name +error: methods called `is_*` usually take `self` by reference or no `self` --> $DIR/wrong_self_convention.rs:40:15 | LL | fn is_i32(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name +error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference --> $DIR/wrong_self_convention.rs:42:15 | LL | fn to_i32(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `from_*` usually take no self; consider choosing a less ambiguous name +error: methods called `from_*` usually take no `self` --> $DIR/wrong_self_convention.rs:44:17 | LL | fn from_i32(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name +error: methods called `as_*` usually take `self` by reference or `self` by mutable reference --> $DIR/wrong_self_convention.rs:46:19 | LL | pub fn as_i64(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name +error: methods called `into_*` usually take `self` by value --> $DIR/wrong_self_convention.rs:47:21 | LL | pub fn into_i64(&self) {} | ^^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name +error: methods called `is_*` usually take `self` by reference or no `self` --> $DIR/wrong_self_convention.rs:48:19 | LL | pub fn is_i64(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name +error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference --> $DIR/wrong_self_convention.rs:49:19 | LL | pub fn to_i64(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `from_*` usually take no self; consider choosing a less ambiguous name +error: methods called `from_*` usually take no `self` --> $DIR/wrong_self_convention.rs:50:21 | LL | pub fn from_i64(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name +error: methods called `as_*` usually take `self` by reference or `self` by mutable reference --> $DIR/wrong_self_convention.rs:95:19 | LL | fn as_i32(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name +error: methods called `into_*` usually take `self` by value --> $DIR/wrong_self_convention.rs:98:25 | LL | fn into_i32_ref(&self) {} | ^^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name +error: methods called `is_*` usually take `self` by reference or no `self` --> $DIR/wrong_self_convention.rs:100:19 | LL | fn is_i32(self) {} | ^^^^ - -error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:102:19 | -LL | fn to_i32(self) {} - | ^^^^ + = help: consider choosing a less ambiguous name -error: methods called `from_*` usually take no self; consider choosing a less ambiguous name +error: methods called `from_*` usually take no `self` --> $DIR/wrong_self_convention.rs:104:21 | LL | fn from_i32(self) {} | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name +error: methods called `as_*` usually take `self` by reference or `self` by mutable reference --> $DIR/wrong_self_convention.rs:119:19 | LL | fn as_i32(self); | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name +error: methods called `into_*` usually take `self` by value --> $DIR/wrong_self_convention.rs:122:25 | LL | fn into_i32_ref(&self); | ^^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name +error: methods called `is_*` usually take `self` by reference or no `self` --> $DIR/wrong_self_convention.rs:124:19 | LL | fn is_i32(self); | ^^^^ - -error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/wrong_self_convention.rs:126:19 | -LL | fn to_i32(self); - | ^^^^ + = help: consider choosing a less ambiguous name -error: methods called `from_*` usually take no self; consider choosing a less ambiguous name +error: methods called `from_*` usually take no `self` --> $DIR/wrong_self_convention.rs:128:21 | LL | fn from_i32(self); | ^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name +error: methods called `into_*` usually take `self` by value --> $DIR/wrong_self_convention.rs:146:25 | LL | fn into_i32_ref(&self); | ^^^^^ + | + = help: consider choosing a less ambiguous name -error: methods called `from_*` usually take no self; consider choosing a less ambiguous name +error: methods called `from_*` usually take no `self` --> $DIR/wrong_self_convention.rs:152:21 | LL | fn from_i32(self); | ^^^^ + | + = help: consider choosing a less ambiguous name + +error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value + --> $DIR/wrong_self_convention.rs:176:22 + | +LL | fn to_u64_v2(&self) -> u64 { + | ^^^^^ + | + = help: consider choosing a less ambiguous name + +error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference + --> $DIR/wrong_self_convention.rs:185:19 + | +LL | fn to_u64(self) -> u64 { + | ^^^^ + | + = help: consider choosing a less ambiguous name error: aborting due to 24 previous errors diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.rs b/src/tools/clippy/tests/ui/wrong_self_convention2.rs new file mode 100644 index 0000000000..ae3a740d40 --- /dev/null +++ b/src/tools/clippy/tests/ui/wrong_self_convention2.rs @@ -0,0 +1,44 @@ +// edition:2018 +#![warn(clippy::wrong_self_convention)] +#![warn(clippy::wrong_pub_self_convention)] +#![allow(dead_code)] + +fn main() {} + +mod issue6983 { + pub struct Thing; + pub trait Trait { + fn to_thing(&self) -> Thing; + } + + impl Trait for u8 { + // don't trigger, e.g. `ToString` from `std` requires `&self` + fn to_thing(&self) -> Thing { + Thing + } + } + + trait ToU64 { + fn to_u64(self) -> u64; + } + + struct FooNoCopy; + // trigger lint + impl ToU64 for FooNoCopy { + fn to_u64(self) -> u64 { + 2 + } + } +} + +mod issue7032 { + trait Foo { + fn from_usize(x: usize) -> Self; + } + // don't trigger + impl Foo for usize { + fn from_usize(x: usize) -> Self { + x + } + } +} diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr new file mode 100644 index 0000000000..0ca1a39097 --- /dev/null +++ b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr @@ -0,0 +1,11 @@ +error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference + --> $DIR/wrong_self_convention2.rs:28:19 + | +LL | fn to_u64(self) -> u64 { + | ^^^^ + | + = note: `-D clippy::wrong-self-convention` implied by `-D warnings` + = help: consider choosing a less ambiguous name + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs new file mode 100644 index 0000000000..486a0d7723 --- /dev/null +++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.rs @@ -0,0 +1,30 @@ +// edition:2018 +#![warn(clippy::wrong_self_convention)] +#![allow(dead_code)] + +fn main() {} + +mod issue6758 { + pub enum Test<T> { + One(T), + Many(Vec<T>), + } + + impl<T> Test<T> { + // If a method starts with `to_` and not ends with `_mut` it should expect `&self` + pub fn to_many(&mut self) -> Option<&mut [T]> { + match self { + Self::Many(data) => Some(data), + _ => None, + } + } + + // If a method starts with `to_` and ends with `_mut` it should expect `&mut self` + pub fn to_many_mut(&self) -> Option<&[T]> { + match self { + Self::Many(data) => Some(data), + _ => None, + } + } + } +} diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr new file mode 100644 index 0000000000..6ce37c5949 --- /dev/null +++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr @@ -0,0 +1,19 @@ +error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference + --> $DIR/wrong_self_conventions_mut.rs:15:24 + | +LL | pub fn to_many(&mut self) -> Option<&mut [T]> { + | ^^^^^^^^^ + | + = note: `-D clippy::wrong-self-convention` implied by `-D warnings` + = help: consider choosing a less ambiguous name + +error: methods with the following characteristics: (`to_*` and `*_mut`) usually take `self` by mutable reference + --> $DIR/wrong_self_conventions_mut.rs:23:28 + | +LL | pub fn to_many_mut(&self) -> Option<&[T]> { + | ^^^^^ + | + = help: consider choosing a less ambiguous name + +error: aborting due to 2 previous errors + diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 99cbcf316a..b7693a3cb1 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -376,12 +376,24 @@ pub fn expected_output_path( testpaths.file.with_extension(extension) } -pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT]; +pub const UI_EXTENSIONS: &[&str] = &[ + UI_STDERR, + UI_STDOUT, + UI_FIXED, + UI_RUN_STDERR, + UI_RUN_STDOUT, + UI_STDERR_64, + UI_STDERR_32, + UI_STDERR_16, +]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; pub const UI_FIXED: &str = "fixed"; pub const UI_RUN_STDERR: &str = "run.stderr"; pub const UI_RUN_STDOUT: &str = "run.stdout"; +pub const UI_STDERR_64: &str = "64bit.stderr"; +pub const UI_STDERR_32: &str = "32bit.stderr"; +pub const UI_STDERR_16: &str = "16bit.stderr"; /// Absolute path to the directory where all output for all tests in the given /// `relative_dir` group should reside. Example: diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ff0d845be9..f31a24738d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -44,6 +44,7 @@ impl EarlyProps { 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); @@ -76,6 +77,10 @@ impl EarlyProps { 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; } @@ -131,9 +136,7 @@ impl EarlyProps { props.aux_crate.push(ac); } - if let Some(r) = config.parse_revisions(ln) { - props.revisions.extend(r); - } + config.parse_and_update_revisions(ln, &mut props.revisions); props.should_fail = props.should_fail || config.parse_name_directive(ln, "should-fail"); }); @@ -427,9 +430,7 @@ impl TestProps { self.compile_flags.push(format!("--edition={}", edition)); } - if let Some(r) = config.parse_revisions(ln) { - self.revisions.extend(r); - } + config.parse_and_update_revisions(ln, &mut self.revisions); if self.run_flags.is_none() { self.run_flags = config.parse_run_flags(ln); @@ -708,8 +709,8 @@ impl Config { self.parse_name_value_directive(line, "aux-crate").map(|r| { let mut parts = r.trim().splitn(2, '='); ( - parts.next().expect("aux-crate name").to_string(), - parts.next().expect("aux-crate value").to_string(), + parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), + parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), ) }) } @@ -718,9 +719,16 @@ impl Config { self.parse_name_value_directive(line, "compile-flags") } - fn parse_revisions(&self, line: &str) -> Option<Vec<String>> { - self.parse_name_value_directive(line, "revisions") - .map(|r| r.split_whitespace().map(|t| t.to_string()).collect()) + fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec<String>) { + if let Some(raw) = self.parse_name_value_directive(line, "revisions") { + let mut duplicates: HashSet<_> = existing.iter().cloned().collect(); + for revision in raw.split_whitespace().map(|r| r.to_string()) { + if !duplicates.insert(revision.clone()) { + panic!("Duplicate revision: `{}` in line `{}`", revision, raw); + } + existing.push(revision); + } + } } fn parse_run_flags(&self, line: &str) -> Option<String> { @@ -973,7 +981,11 @@ fn parse_normalization_string(line: &mut &str) -> Option<String> { } pub fn extract_llvm_version(version: &str) -> Option<u32> { - let version_without_suffix = version.trim_end_matches("git").split('-').next().unwrap(); + let pat = |c: char| !c.is_ascii_digit() && c != '.'; + let version_without_suffix = match version.find(pat) { + Some(pos) => &version[..pos], + None => version, + }; let components: Vec<u32> = version_without_suffix .split('.') .map(|s| s.parse().expect("Malformed version component")) diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index ec99fde0df..ca7458d255 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -223,6 +223,17 @@ fn sanitizers() { assert!(parse_rs(&config, "// needs-sanitizer-thread").ignore); } +#[test] +fn asm_support() { + let mut config = config(); + + config.target = "avr-unknown-gnu-atmega328".to_owned(); + assert!(parse_rs(&config, "// needs-asm-support").ignore); + + config.target = "i686-unknown-netbsd".to_owned(); + assert!(!parse_rs(&config, "// needs-asm-support").ignore); +} + #[test] fn test_extract_version_range() { use super::{extract_llvm_version, extract_version_range}; @@ -237,3 +248,10 @@ fn test_extract_version_range() { assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None); assert_eq!(extract_version_range("0 -", extract_llvm_version), None); } + +#[test] +#[should_panic(expected = "Duplicate revision: `rpass1` in line ` rpass1 rpass1`")] +fn test_duplicate_revisions() { + let config = config(); + parse_rs(&config, "// revisions: rpass1 rpass1"); +} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 1d4b5e1247..d1798a52df 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -909,7 +909,8 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> { // This particular form is documented in the GNU coding standards: // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion - let mut splits = full_version_line.rsplit(' '); + let unbracketed_part = full_version_line.split('[').next().unwrap(); + let mut splits = unbracketed_part.trim_end().rsplit(' '); let version_string = splits.next().unwrap(); let mut splits = version_string.split('.'); @@ -974,7 +975,7 @@ fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> { } } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") { if let Some(idx) = lldb_ver.find(not_a_digit) { - let version: u32 = lldb_ver[..idx].parse().unwrap(); + let version: u32 = lldb_ver[..idx].parse().ok()?; return Some((version * 100, full_version_line.contains("rust-enabled"))); } } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 6aebf4b604..5125acb9b6 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1612,7 +1612,7 @@ impl<'test> TestCx<'test> { .args(&self.props.compile_flags); if self.config.mode == RustdocJson { - rustdoc.arg("--output-format").arg("json"); + rustdoc.arg("--output-format").arg("json").arg("-Zunstable-options"); } if let Some(ref linker) = self.config.linker { @@ -1784,7 +1784,9 @@ impl<'test> TestCx<'test> { /// Returns whether or not it is a dylib. fn build_auxiliary(&self, source_path: &str, aux_dir: &Path) -> bool { let aux_testpaths = self.compute_aux_test_paths(source_path); - let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + let mut aux_props = + self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + aux_props.rustc_env.push((String::from("RUSTC_FORCE_INCREMENTAL"), String::from("1"))); let aux_output = TargetLocation::ThisDirectory(self.aux_output_dir_name()); let aux_cx = TestCx { config: self.config, @@ -1921,8 +1923,7 @@ impl<'test> TestCx<'test> { } else { Command::new(&self.config.rustdoc_path.clone().expect("no rustdoc built yet")) }; - // FIXME Why is -L here? - rustc.arg(input_file); //.arg("-L").arg(&self.config.build_base); + rustc.arg(input_file); // Use a single thread for efficiency and a deterministic error message order rustc.arg("-Zthreads=1"); @@ -1964,6 +1965,7 @@ impl<'test> TestCx<'test> { if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) { rustc.args(&["--error-format", "json"]); } + rustc.arg("-Ccodegen-units=1"); rustc.arg("-Zui-testing"); rustc.arg("-Zdeduplicate-diagnostics=no"); rustc.arg("-Zemit-future-incompat-report"); @@ -3152,8 +3154,14 @@ impl<'test> TestCx<'test> { output_kind: TestOutput, explicit_format: bool, ) -> usize { + let stderr_bits = format!("{}.stderr", get_pointer_width(&self.config.target)); let (stderr_kind, stdout_kind) = match output_kind { - TestOutput::Compile => (UI_STDERR, UI_STDOUT), + TestOutput::Compile => ( + { + if self.props.stderr_per_bitwidth { &stderr_bits } else { UI_STDERR } + }, + UI_STDOUT, + ), TestOutput::Run => (UI_RUN_STDERR, UI_RUN_STDOUT), }; @@ -3193,15 +3201,12 @@ impl<'test> TestCx<'test> { match output_kind { TestOutput::Compile => { if !self.props.dont_check_compiler_stdout { - errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); + errors += + self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); } if !self.props.dont_check_compiler_stderr { - let kind = if self.props.stderr_per_bitwidth { - format!("{}bit.stderr", get_pointer_width(&self.config.target)) - } else { - String::from("stderr") - }; - errors += self.compare_output(&kind, &normalized_stderr, &expected_stderr); + errors += + self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); } } TestOutput::Run => { @@ -3659,6 +3664,8 @@ impl<'test> TestCx<'test> { // Remove test annotations like `//~ ERROR text` from the output, // since they duplicate actual errors and make the output hard to read. + // This mirrors the regex in src/tools/tidy/src/style.rs, please update + // both if either are changed. normalized = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap().replace_all(&normalized, "").into_owned(); diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index ea9bc1c1a5..e6725dba26 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -39,6 +39,9 @@ fn test_extract_gdb_version() { 7012000: "GNU gdb (GDB) 7.12", 7012000: "GNU gdb (GDB) 7.12.20161027-git", 7012050: "GNU gdb (GDB) 7.12.50.20161027-git", + + 9002000: "GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2", + 10001000: "GNU gdb (GDB) 10.1 [GDB v10.1 for FreeBSD]", } } @@ -68,4 +71,8 @@ fn test_extract_llvm_version() { assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001)); assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301)); assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000)); + assert_eq!(extract_llvm_version("11.1.0"), Some(110100)); + assert_eq!(extract_llvm_version("12.0.0libcxx"), Some(120000)); + assert_eq!(extract_llvm_version("12.0.0-rc3"), Some(120000)); + assert_eq!(extract_llvm_version("13.0.0git"), Some(130000)); } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index b302953708..7dbd70948b 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -128,6 +128,15 @@ const BIG_ENDIAN: &[&str] = &[ "sparcv9", ]; +static ASM_SUPPORTED_ARCHS: &[&str] = &[ + "x86", "x86_64", "arm", "aarch64", "riscv32", "riscv64", "nvptx64", "hexagon", "mips", + "mips64", "spirv", "wasm32", +]; + +pub fn has_asm_support(triple: &str) -> bool { + ASM_SUPPORTED_ARCHS.contains(&get_arch(triple)) +} + pub fn matches_os(triple: &str, name: &str) -> bool { // For the wasm32 bare target we ignore anything also ignored on emscripten // and then we also recognize `wasm32-bare` as the os for the target diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index 97052ef58d..a6efc4c9a6 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -12,3 +12,4 @@ lazy_static = "1.4" shlex = "0.1" serde = "1.0" serde_json = "1.0" +fs-err = "2.5.0" diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs index 8a6a911321..a188750c56 100644 --- a/src/tools/jsondocck/src/cache.rs +++ b/src/tools/jsondocck/src/cache.rs @@ -1,8 +1,10 @@ use crate::error::CkError; use serde_json::Value; use std::collections::HashMap; +use std::io; use std::path::{Path, PathBuf}; -use std::{fs, io}; + +use fs_err as fs; #[derive(Debug)] pub struct Cache { @@ -31,7 +33,11 @@ impl Cache { self.last_path = Some(resolve.clone()); resolve } else { - self.last_path.as_ref().unwrap().clone() + self.last_path + .as_ref() + // FIXME: Point to a line number + .expect("No last path set. Make sure to specify a full path before using `-`") + .clone() } } diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index bcb3f6922e..216890d59a 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -239,7 +239,20 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { let val = cache.get_value(&command.args[0])?; let results = select(&val, &command.args[1]).unwrap(); let pat = string_to_value(&command.args[2], cache); - results.len() == 1 && results[0] == pat.as_ref() + let is = results.len() == 1 && results[0] == pat.as_ref(); + if !command.negated && !is { + return Err(CkError::FailedCheck( + format!( + "{} matched to {:?}, but expected {:?}", + &command.args[1], + results, + pat.as_ref() + ), + command, + )); + } else { + is + } } CommandKind::Set => { // @set <name> = <path> <jsonpath> @@ -299,7 +312,10 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> { if s.starts_with("$") { - Cow::Borrowed(&cache.variables[&s[1..]]) + Cow::Borrowed(&cache.variables.get(&s[1..]).unwrap_or_else(|| { + // FIXME(adotinthevoid): Show line number + panic!("No variable: `{}`. Current state: `{:?}`", &s[1..], cache.variables) + })) } else { Cow::Owned(serde_json::from_str(s).unwrap()) } diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index f6875e0036..c677d04917 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -14,8 +14,6 @@ //! A few exceptions are allowed as there's known bugs in rustdoc, but this //! should catch the majority of "broken link" cases. -#![cfg_attr(bootstrap, feature(str_split_once))] - use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::env; diff --git a/src/tools/rust-demangler/Cargo.toml b/src/tools/rust-demangler/Cargo.toml index ac684a3c47..b7bc112531 100644 --- a/src/tools/rust-demangler/Cargo.toml +++ b/src/tools/rust-demangler/Cargo.toml @@ -8,6 +8,10 @@ edition = "2018" regex = "1.0" rustc-demangle = "0.1.17" +[lib] +name = "rust_demangler" +doctest = false + [[bin]] name = "rust-demangler" -path = "main.rs" +test = false diff --git a/src/tools/rust-demangler/README.md b/src/tools/rust-demangler/README.md new file mode 100644 index 0000000000..4e8a689a13 --- /dev/null +++ b/src/tools/rust-demangler/README.md @@ -0,0 +1,36 @@ +# rust-demangler + +_Demangles rustc mangled names._ + +`rust-demangler` supports the requirements of the [`llvm-cov show -Xdemangler` +option](https://llvm.org/docs/CommandGuide/llvm-cov.html#cmdoption-llvm-cov-show-xdemangler), +to perform Rust-specific symbol demangling: + +> _The demangler is expected to read a newline-separated list of symbols from +> stdin and write a newline-separated list of the same length to stdout._ + +To use `rust-demangler` with `llvm-cov` for example: + +```shell +$ TARGET="${PWD}/build/x86_64-unknown-linux-gnu" +$ "${TARGET}"/llvm/bin/llvm-cov show \ + --Xdemangler=path/to/rust-demangler \ + --instr-profile=main.profdata ./main --show-line-counts-or-regions +``` + +`rust-demangler` is a Rust "extended tool", used in Rust compiler tests, and +optionally included in Rust distributions that enable coverage profiling. Symbol +demangling is implemented using the +[rustc-demangle](https://crates.io/crates/rustc-demangle) crate. + +_(Note, for Rust developers, the third-party tool +[`rustfilt`](https://crates.io/crates/rustfilt) also supports `llvm-cov` symbol +demangling. `rustfilt` is a more generalized tool that searches any body of +text, using pattern matching, to find and demangle Rust symbols.)_ + +## License + +Rust-demangler is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](/LICENSE-APACHE) and [LICENSE-MIT](/LICENSE-MIT) for details. diff --git a/src/tools/rust-demangler/src/lib.rs b/src/tools/rust-demangler/src/lib.rs new file mode 100644 index 0000000000..1d972229d9 --- /dev/null +++ b/src/tools/rust-demangler/src/lib.rs @@ -0,0 +1,21 @@ +use regex::Regex; +use rustc_demangle::demangle; +use std::str::Lines; + +const REPLACE_COLONS: &str = "::"; + +pub fn create_disambiguator_re() -> Regex { + Regex::new(r"\[[a-f0-9]{5,16}\]::").unwrap() +} + +pub fn demangle_lines(lines: Lines<'_>, strip_crate_disambiguators: Option<Regex>) -> Vec<String> { + let mut demangled_lines = Vec::new(); + for mangled in lines { + let mut demangled = demangle(mangled).to_string(); + if let Some(re) = &strip_crate_disambiguators { + demangled = re.replace_all(&demangled, REPLACE_COLONS).to_string(); + } + demangled_lines.push(demangled); + } + demangled_lines +} diff --git a/src/tools/rust-demangler/main.rs b/src/tools/rust-demangler/src/main.rs similarity index 76% rename from src/tools/rust-demangler/main.rs rename to src/tools/rust-demangler/src/main.rs index fd031ccb25..1b5ef5d244 100644 --- a/src/tools/rust-demangler/main.rs +++ b/src/tools/rust-demangler/src/main.rs @@ -1,27 +1,5 @@ //! Demangles rustc mangled names. //! -//! This tool uses https://crates.io/crates/rustc-demangle to convert an input buffer of -//! newline-separated mangled names into their demangled translations. -//! -//! This tool can be leveraged by other applications that support third-party demanglers. -//! It takes a list of mangled names (one per line) on standard input, and prints a corresponding -//! list of demangled names. The tool is designed to support other programs that can leverage a -//! third-party demangler, such as `llvm-cov`, via the `-Xdemangler=<path-to-demangler>` option. -//! -//! To use `rust-demangler`, first build the tool with: -//! -//! ```shell -//! $ ./x.py build rust-demangler -//! ``` -//! -//! Then, with `llvm-cov` for example, add the `-Xdemangler=...` option: -//! -//! ```shell -//! $ TARGET="${PWD}/build/x86_64-unknown-linux-gnu" -//! $ "${TARGET}"/llvm/bin/llvm-cov show --Xdemangler="${TARGET}"/stage0-tools-bin/rust-demangler \ -//! --instr-profile=main.profdata ./main --show-line-counts-or-regions -//! ``` -//! //! Note regarding crate disambiguators: //! //! Some demangled symbol paths can include "crate disambiguator" suffixes, represented as a large @@ -57,12 +35,9 @@ //! These disambiguators seem to have more analytical value (for instance, in coverage analysis), so //! they are not removed. -use regex::Regex; -use rustc_demangle::demangle; +use rust_demangler::*; use std::io::{self, Read, Write}; -const REPLACE_COLONS: &str = "::"; - fn main() -> io::Result<()> { // FIXME(richkadel): In Issue #77615 discussed updating the `rustc-demangle` library, to provide // an option to generate demangled names without including crate disambiguators. If that @@ -82,7 +57,7 @@ fn main() -> io::Result<()> { // and more than three leading zeros should be extremely unlikely. Conversely, it should be // sufficient to assume the zero-based indexes for closures and anonymous scopes will never // exceed the value 9999. - let mut strip_crate_disambiguators = Some(Regex::new(r"\[[a-f0-9]{5,16}\]::").unwrap()); + let mut strip_crate_disambiguators = Some(create_disambiguator_re()); let mut args = std::env::args(); let progname = args.next().unwrap(); @@ -115,16 +90,8 @@ fn main() -> io::Result<()> { let mut buffer = String::new(); io::stdin().read_to_string(&mut buffer)?; - let lines = buffer.lines(); - let mut demangled_lines = Vec::new(); - for mangled in lines { - let mut demangled = demangle(mangled).to_string(); - if let Some(re) = &strip_crate_disambiguators { - demangled = re.replace_all(&demangled, REPLACE_COLONS).to_string(); - } - demangled_lines.push(demangled); - } - demangled_lines.push("".to_string()); + let mut demangled_lines = demangle_lines(buffer.lines(), strip_crate_disambiguators); + demangled_lines.push("".to_string()); // ensure a trailing newline io::stdout().write_all(demangled_lines.join("\n").as_bytes())?; Ok(()) } diff --git a/src/tools/rust-demangler/tests/lib.rs b/src/tools/rust-demangler/tests/lib.rs new file mode 100644 index 0000000000..5a67b42322 --- /dev/null +++ b/src/tools/rust-demangler/tests/lib.rs @@ -0,0 +1,84 @@ +use rust_demangler::*; + +const MANGLED_INPUT: &str = r" +_RNvC6_123foo3bar +_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y +_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_ +_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_ +_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std +INtC8arrayvec8ArrayVechKj7b_E +_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E +_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E +_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E +_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E +_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E +_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO +_RC3foo.llvm.9D1C9369 +_RC3foo.llvm.9D1C9369@@16 +_RNvC9backtrace3foo.llvm.A5310EB9 +_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0 +"; + +const DEMANGLED_OUTPUT: &str = r" +123foo[0]::bar +utf8_idents[317d481089b8c8fe]::საჭმელად_გემრიელი_სადილი +cc[4d6468d6c9fd4bb3]::spawn::{closure#0}::{closure#0} +<core[846817f741e54dfd]::slice::Iter<u8> as core[846817f741e54dfd]::iter::iterator::Iterator>::rposition::<core[846817f741e54dfd]::slice::memchr::memrchr::{closure#1}>::{closure#0} +alloc[f15a878b47eb696b]::alloc::box_free::<dyn alloc[f15a878b47eb696b]::boxed::FnBox<(), Output = ()>> +INtC8arrayvec8ArrayVechKj7b_E +<const_generic[317d481089b8c8fe]::Unsigned<11: u8>> +<const_generic[317d481089b8c8fe]::Signed<152: i16>> +<const_generic[317d481089b8c8fe]::Signed<-11: i8>> +<const_generic[317d481089b8c8fe]::Bool<false: bool>> +<const_generic[317d481089b8c8fe]::Bool<true: bool>> +<const_generic[317d481089b8c8fe]::Char<'v': char>> +<const_generic[317d481089b8c8fe]::Char<'\n': char>> +<const_generic[317d481089b8c8fe]::Char<'∂': char>> +<const_generic[317d481089b8c8fe]::Foo<_>>::foo::FOO +foo[0] +foo[0] +backtrace[0]::foo +rand[693ea8e72247470f]::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0 +"; + +const DEMANGLED_OUTPUT_NO_CRATE_DISAMBIGUATORS: &str = r" +123foo[0]::bar +utf8_idents::საჭმელად_გემრიელი_სადილი +cc::spawn::{closure#0}::{closure#0} +<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0} +alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>> +INtC8arrayvec8ArrayVechKj7b_E +<const_generic::Unsigned<11: u8>> +<const_generic::Signed<152: i16>> +<const_generic::Signed<-11: i8>> +<const_generic::Bool<false: bool>> +<const_generic::Bool<true: bool>> +<const_generic::Char<'v': char>> +<const_generic::Char<'\n': char>> +<const_generic::Char<'∂': char>> +<const_generic::Foo<_>>::foo::FOO +foo[0] +foo[0] +backtrace[0]::foo +rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0 +"; + +#[test] +fn test_demangle_lines() { + let demangled_lines = demangle_lines(MANGLED_INPUT.lines(), None); + for (expected, actual) in DEMANGLED_OUTPUT.lines().zip(demangled_lines) { + assert_eq!(expected, actual); + } +} + +#[test] +fn test_demangle_lines_no_crate_disambiguators() { + let demangled_lines = demangle_lines(MANGLED_INPUT.lines(), Some(create_disambiguator_re())); + for (expected, actual) in DEMANGLED_OUTPUT_NO_CRATE_DISAMBIGUATORS.lines().zip(demangled_lines) + { + assert_eq!(expected, actual); + } +} diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 8da7db2dfd..d39cb597b2 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -63,15 +63,15 @@ features = [ [dependencies] byteorder = { version = "1", features = ['default', 'std'] } curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } -crossbeam-utils = { version = "0.7.2", features = ["nightly"] } +crossbeam-utils = { version = "0.8.0", features = ["nightly"] } libc = { version = "0.2.79", features = ["align"] } # Ensure default features of libz-sys, which are disabled in some scenarios. libz-sys = { version = "1.1.2" } proc-macro2 = { version = "1", features = ["default"] } quote = { version = "1", features = ["default"] } +rand_core_0_5 = { package = "rand_core", version = "0.5.1", features = ["getrandom", "alloc", "std"] } serde = { version = "1.0.82", features = ['derive'] } serde_json = { version = "1.0.31", features = ["raw_value", "unbounded_depth"] } -smallvec-0_6 = { package = "smallvec", version = "0.6.14", features = ['union', 'may_dangle'] } smallvec = { version = "1.6.1", features = ['union', 'may_dangle'] } syn = { version = "1", features = ['fold', 'full', 'extra-traits', 'visit', 'visit-mut'] } url = { version = "2.0", features = ['serde'] } diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index c21277de33..e583bd225a 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -246,7 +246,7 @@ function lookForEntry(entry, data) { return null; } -function loadMainJsAndIndex(mainJs, searchIndex, storageJs, crate) { +function loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate) { if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -264,14 +264,15 @@ function loadMainJsAndIndex(mainJs, searchIndex, storageJs, crate) { // execQuery last parameter is built in buildIndex. // buildIndex requires the hashmap from search-index. var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", - "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch"]; + "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch", + "removeEmptyStringsFromArray"]; ALIASES = {}; finalJS += 'window = { "currentCrate": "' + crate + '", rootPath: "../" };\n'; finalJS += loadThings(["hasOwnProperty", "onEach"], 'function', extractFunction, storageJs); - finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); - finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); - finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); + finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, searchJs); + finalJS += loadThings(variablesToLoad, 'variable', extractVariable, searchJs); + finalJS += loadThings(functionsToLoad, 'function', extractFunction, searchJs); var loaded = loadContent(finalJS); var index = loaded.buildIndex(searchIndex.rawSearchIndex); @@ -381,12 +382,12 @@ function runChecks(testFile, loaded, index) { } function load_files(doc_folder, resource_suffix, crate) { - var mainJs = readFile(path.join(doc_folder, "main" + resource_suffix + ".js")); + var searchJs = readFile(path.join(doc_folder, "search" + resource_suffix + ".js")); var storageJs = readFile(path.join(doc_folder, "storage" + resource_suffix + ".js")); var searchIndex = readFile( path.join(doc_folder, "search-index" + resource_suffix + ".js")).split("\n"); - return loadMainJsAndIndex(mainJs, searchIndex, storageJs, crate); + return loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate); } function showHelp() { diff --git a/src/tools/rustdoc/Cargo.toml b/src/tools/rustdoc/Cargo.toml index 36aa5916da..d0c047ad6d 100644 --- a/src/tools/rustdoc/Cargo.toml +++ b/src/tools/rustdoc/Cargo.toml @@ -13,3 +13,6 @@ path = "main.rs" [dependencies] rustdoc = { path = "../../librustdoc" } + +[features] +jemalloc = ['rustdoc/jemalloc'] diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml index 2e832b6b62..b79221d054 100644 --- a/src/tools/rustfmt/.github/workflows/integration.yml +++ b/src/tools/rustfmt/.github/workflows/integration.yml @@ -72,14 +72,11 @@ jobs: uses: actions/checkout@v2 # Run build - - name: setup - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly-x86_64-unknown-linux-gnu - target: x86_64-unknown-linux-gnu - override: true - profile: minimal - default: true + - name: install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + - name: run integration tests env: INTEGRATION: ${{ matrix.integration }} diff --git a/src/tools/rustfmt/.github/workflows/linux.yml b/src/tools/rustfmt/.github/workflows/linux.yml index acbf666955..6eaae69c70 100644 --- a/src/tools/rustfmt/.github/workflows/linux.yml +++ b/src/tools/rustfmt/.github/workflows/linux.yml @@ -8,7 +8,7 @@ on: jobs: test: runs-on: ubuntu-latest - name: (${{ matrix.target }}, ${{ matrix.channel }}, ${{ matrix.cfg-release-channel }}) + name: (${{ matrix.target }}, nightly) strategy: # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization. @@ -20,29 +20,17 @@ jobs: target: [ x86_64-unknown-linux-gnu, ] - channel: [ nightly ] - cfg-release-channel: [ - beta, - nightly, - ] - - env: - CFG_RELEASE_CHANNEL: ${{ matrix.cfg-release-channel }} - CFG_RELEASE: ${{ matrix.cfg-release-channel }} steps: - name: checkout uses: actions/checkout@v2 # Run build - - name: setup - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.channel }}-${{ matrix.target }} - target: ${{ matrix.target }} - override: true - profile: minimal - default: true + - name: install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + rustup target add ${{ matrix.target }} - name: build run: | diff --git a/src/tools/rustfmt/.github/workflows/mac.yml b/src/tools/rustfmt/.github/workflows/mac.yml index afbc8a8d74..79e4f69163 100644 --- a/src/tools/rustfmt/.github/workflows/mac.yml +++ b/src/tools/rustfmt/.github/workflows/mac.yml @@ -10,32 +10,24 @@ jobs: # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources # macOS Catalina 10.15 runs-on: macos-latest - name: (${{ matrix.target }}, ${{ matrix.channel }}) + name: (${{ matrix.target }}, nightly) strategy: fail-fast: false matrix: target: [ x86_64-apple-darwin, ] - channel: [ nightly ] - - env: - CFG_RELEASE_CHANNEL: nightly - CFG_RELEASE: nightly steps: - name: checkout uses: actions/checkout@v2 # Run build - - name: setup - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.channel }}-${{ matrix.target }} - target: ${{ matrix.target }} - override: true - profile: minimal - default: true + - name: install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + rustup target add ${{ matrix.target }} - name: build run: | diff --git a/src/tools/rustfmt/.github/workflows/windows.yml b/src/tools/rustfmt/.github/workflows/windows.yml index 156848c165..08cb52eeda 100644 --- a/src/tools/rustfmt/.github/workflows/windows.yml +++ b/src/tools/rustfmt/.github/workflows/windows.yml @@ -8,7 +8,7 @@ on: jobs: test: runs-on: windows-latest - name: (${{ matrix.target }}, ${{ matrix.channel }}) + name: (${{ matrix.target }}, nightly) strategy: # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization. @@ -23,14 +23,6 @@ jobs: x86_64-pc-windows-gnu, x86_64-pc-windows-msvc, ] - channel: [ nightly ] - include: - - channel: nightly - target: i686-pc-windows-gnu - - env: - CFG_RELEASE_CHANNEL: nightly - CFG_RELEASE: nightly steps: # The Windows runners have autocrlf enabled by default @@ -41,14 +33,15 @@ jobs: uses: actions/checkout@v2 # Run build - - name: setup - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.channel }}-${{ matrix.target }} - target: ${{ matrix.target }} - override: true - profile: minimal - default: true + - name: Install Rustup using win.rustup.rs + run: | + # Disable the download progress bar which can cause perf issues + $ProgressPreference = "SilentlyContinue" + Invoke-WebRequest https://win.rustup.rs/ -OutFile rustup-init.exe + .\rustup-init.exe -y --default-host=x86_64-pc-windows-msvc --default-toolchain=none + del rustup-init.exe + rustup target add ${{ matrix.target }} + shell: powershell - name: Add mingw32 to path for i686-gnu run: | diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md index f52b45f7e5..0f23663d6c 100644 --- a/src/tools/rustfmt/CHANGELOG.md +++ b/src/tools/rustfmt/CHANGELOG.md @@ -2,6 +2,22 @@ ## [Unreleased] +## [1.4.37] 2021-04-03 + +### Changed + +- `rustc-ap-*` crates updated to v712.0.0 + +### Fixed +- Resolve idempotence issue related to indentation of macro defs that contain or-patterns with inner comments ([#4603](https://github.com/rust-lang/rustfmt/issues/4603)) +- Addressed various clippy and rustc warnings + +### Install/Download Options +- **crates.io package** - *pending* +- **rustup (nightly)** - *pending* +- **GitHub Release Binaries** - [Release v1.4.37](https://github.com/rust-lang/rustfmt/releases/tag/v1.4.37) +- **Build from source** - [Tag v1.4.37](https://github.com/rust-lang/rustfmt/tree/v1.4.37), see instructions for how to [install rustfmt from source][install-from-source] + ## [1.4.36] 2021-02-07 ### Changed diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock index ff23a4775d..0e12e81904 100644 --- a/src/tools/rustfmt/Cargo.lock +++ b/src/tools/rustfmt/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.6" @@ -9,20 +11,14 @@ dependencies = [ "memchr", ] -[[package]] -name = "annotate-snippets" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" -dependencies = [ - "ansi_term", -] - [[package]] name = "annotate-snippets" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" +dependencies = [ + "yansi-term", +] [[package]] name = "ansi_term" @@ -54,12 +50,6 @@ dependencies = [ "nodrop", ] -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - [[package]] name = "atty" version = "0.2.13" @@ -76,12 +66,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - [[package]] name = "backtrace" version = "0.3.40" @@ -89,7 +73,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" dependencies = [ "backtrace-sys", - "cfg-if 0.1.10", + "cfg-if", "libc", "rustc-demangle", ] @@ -126,19 +110,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" dependencies = [ "arrayref", - "arrayvec 0.4.12", + "arrayvec", "constant_time_eq", ] -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "bstr" version = "0.2.8" @@ -187,12 +162,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "clap" version = "2.33.0" @@ -217,27 +186,12 @@ dependencies = [ "bitflags", ] -[[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags", -] - [[package]] name = "constant_time_eq" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -[[package]] -name = "cpuid-bool" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" - [[package]] name = "crossbeam-channel" version = "0.4.0" @@ -247,46 +201,13 @@ dependencies = [ "crossbeam-utils 0.7.0", ] -[[package]] -name = "crossbeam-deque" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils 0.6.5", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -dependencies = [ - "arrayvec 0.4.12", - "cfg-if 0.1.10", - "crossbeam-utils 0.6.5", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -dependencies = [ - "crossbeam-utils 0.6.5", -] - [[package]] name = "crossbeam-utils" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "lazy_static", ] @@ -296,8 +217,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" dependencies = [ - "autocfg 0.1.7", - "cfg-if 0.1.10", + "autocfg", + "cfg-if", "lazy_static", ] @@ -318,22 +239,13 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "dirs" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "dirs-sys", ] @@ -343,7 +255,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "libc", "redox_users", "winapi", @@ -355,15 +267,6 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -[[package]] -name = "ena" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" -dependencies = [ - "log", -] - [[package]] name = "env_logger" version = "0.6.2" @@ -411,16 +314,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -[[package]] -name = "generic-array" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getopts" version = "0.2.21" @@ -430,17 +323,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "getrandom" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "wasi", -] - [[package]] name = "globset" version = "0.4.4" @@ -454,15 +336,6 @@ dependencies = [ "regex", ] -[[package]] -name = "hashbrown" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" -dependencies = [ - "autocfg 1.0.1", -] - [[package]] name = "heck" version = "0.3.1" @@ -499,25 +372,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "indexmap" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e47a3566dd4fd4eec714ae6ceabdee0caec795be835c223d92c2d40f1e8cf1c" -dependencies = [ - "autocfg 1.0.1", - "hashbrown", -] - -[[package]] -name = "instant" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" -dependencies = [ - "cfg-if 0.1.10", -] - [[package]] name = "itertools" version = "0.8.0" @@ -527,32 +381,12 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -[[package]] -name = "jobserver" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" -dependencies = [ - "getrandom", - "libc", - "log", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -565,44 +399,13 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" -[[package]] -name = "lock_api" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.10", -] - -[[package]] -name = "md-5" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer", - "digest", - "opaque-debug", -] - -[[package]] -name = "measureme" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22bf8d885d073610aee20e7fa205c4341ed32a761dbde96da5fd96301a8d3e82" -dependencies = [ - "parking_lot", - "rustc-hash", - "smallvec", + "cfg-if", ] [[package]] @@ -611,77 +414,21 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -[[package]] -name = "memoffset" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -dependencies = [ - "rustc_version", -] - [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -[[package]] -name = "num_cpus" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -dependencies = [ - "libc", -] - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "packed_simd" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", ] -[[package]] -name = "parking_lot" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi 0.1.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" - [[package]] name = "proc-macro-error" version = "0.4.11" @@ -717,15 +464,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "psm" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7" -dependencies = [ - "cc", -] - [[package]] name = "quick-error" version = "1.2.2" @@ -741,29 +479,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - [[package]] name = "rand_core" version = "0.3.1" @@ -779,31 +494,13 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rand_os" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3", + "cloudabi", "fuchsia-cprng", "libc", "rand_core 0.4.2", @@ -856,15 +553,6 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" -[[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 = "rust-argon2" version = "0.5.1" @@ -873,312 +561,7 @@ checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" dependencies = [ "base64", "blake2b_simd", - "crossbeam-utils 0.6.5", -] - -[[package]] -name = "rustc-ap-rustc_arena" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93575affa286089b92c8208aea4e60fe9fdd251a619a09b566d6e4e2cc123212" -dependencies = [ - "smallvec", -] - -[[package]] -name = "rustc-ap-rustc_ast" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c700f2d3b25aa8d6446dd2936048737b08b2d547bd86e2a70afa9fee4e9c522" -dependencies = [ - "bitflags", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "smallvec", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_ast_passes" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e01f63e5259ee397bbe2e395d34a2e6b6b24f10c184d30fbbee1dcd7117f4f3" -dependencies = [ - "itertools 0.9.0", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_ast_pretty" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d644c69c55deb24257cb0cb5261265fe5134f6f545e9062e1c18b07e422c68" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_span", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_attr" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "797fc68816d5396870f04e03d35164f5275d2502403239d4caec7ce063683f41" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", -] - -[[package]] -name = "rustc-ap-rustc_data_structures" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d840c4e6198b57982a54543ae604d634c7ceb7107f0c75970b88ebaff077ac5" -dependencies = [ - "arrayvec 0.5.1", - "bitflags", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.0", - "ena", - "indexmap", - "jobserver", - "libc", - "measureme", - "parking_lot", - "rustc-ap-rustc_graphviz", - "rustc-ap-rustc_index", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-hash", - "rustc-rayon", - "rustc-rayon-core", - "smallvec", - "stable_deref_trait", - "stacker", - "tempfile", - "tracing", - "winapi", -] - -[[package]] -name = "rustc-ap-rustc_errors" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f2f99bdc828ad417636d9016611dc9047b641fadcb7f533b8b0e9616d81f90b" -dependencies = [ - "annotate-snippets 0.8.0", - "atty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "termcolor", - "termize", - "tracing", - "unicode-width", - "winapi", -] - -[[package]] -name = "rustc-ap-rustc_expand" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27008b4c7ded287bf5cb20b84d6d5a6566329140f2e2bc8f6e68b37a34898595" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_passes", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "smallvec", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_feature" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb47b53670f1263ed1389dda932d5b5a6daf98579c1f076c2ee7d7f22709b7c" -dependencies = [ - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_span", -] - -[[package]] -name = "rustc-ap-rustc_fs_util" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdaddc4bae5ffab17037553e172f5014686db600050429aaa60aec14fe780e84" - -[[package]] -name = "rustc-ap-rustc_graphviz" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d73c72543311e88786f7380a3bfd946395579c1a0c0441a879a97fcdea79130" - -[[package]] -name = "rustc-ap-rustc_index" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bba8d74ed4bad44a5b4264cf2a51ad0bd458ed56caa5bb090e989b8002ec6327" -dependencies = [ - "arrayvec 0.5.1", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", -] - -[[package]] -name = "rustc-ap-rustc_lexer" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a030d00510966cd31e13dca5e6c1bd40d303a932c54eca40e854188bca8c49e" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "rustc-ap-rustc_lint_defs" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff95da1b5d979183ef5c285817ba6cc67a1ac11296ef1e87b1b5bbaf57213c" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "rustc-ap-rustc_target", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_macros" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3ed7401bf6f5a256d58cd0e1c1e2e77eec25e60a0d7ad75313962edcb4e396" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "rustc-ap-rustc_parse" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609a624baffa3f99847d57d30c96ee6732ce0912f8df4be239b6fd91533910d6" -dependencies = [ - "bitflags", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "smallvec", - "tracing", - "unicode-normalization", -] - -[[package]] -name = "rustc-ap-rustc_serialize" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc232e2a351d8131c8f1386ce372ee22ef7b1b0b897bbf817a8ce4792029a564" -dependencies = [ - "indexmap", - "smallvec", -] - -[[package]] -name = "rustc-ap-rustc_session" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18acf94c820cd0c64ee1cbd811fd1f4d5ba18987c457c88771359b90cb1a12f5" -dependencies = [ - "bitflags", - "getopts", - "num_cpus", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_fs_util", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "rustc-ap-rustc_target", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_span" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3479f453a38b6a5572938d035fc2b3cb6ec379c57f598b8682b512eb90c7858" -dependencies = [ - "cfg-if 0.1.10", - "md-5", - "rustc-ap-rustc_arena", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "scoped-tls", - "sha-1", - "sha2", - "tracing", - "unicode-width", -] - -[[package]] -name = "rustc-ap-rustc_target" -version = "705.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cacaf829778cf07bb97a9f4604896789de12392175f3743e74a30ed370f1c1" -dependencies = [ - "bitflags", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "tracing", + "crossbeam-utils 0.6.6", ] [[package]] @@ -1187,51 +570,12 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-rayon" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" -dependencies = [ - "crossbeam-deque", - "either", - "rustc-rayon-core", -] - -[[package]] -name = "rustc-rayon-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3" -dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils 0.6.5", - "lazy_static", - "num_cpus", -] - [[package]] name = "rustc-workspace-hack" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - [[package]] name = "rustfmt-config_proc_macro" version = "0.2.0" @@ -1243,9 +587,9 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.36" +version = "1.4.37" dependencies = [ - "annotate-snippets 0.6.1", + "annotate-snippets", "anyhow", "bytecount", "cargo_metadata", @@ -1255,19 +599,10 @@ dependencies = [ "env_logger", "getopts", "ignore", - "itertools 0.8.0", + "itertools", "lazy_static", "log", "regex", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_expand", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", @@ -1296,18 +631,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "semver" version = "0.9.0" @@ -1355,57 +678,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c" -dependencies = [ - "block-buffer", - "cfg-if 1.0.0", - "cpuid-bool", - "digest", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" -dependencies = [ - "block-buffer", - "cfg-if 1.0.0", - "cpuid-bool", - "digest", - "opaque-debug", -] - -[[package]] -name = "smallvec" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" - -[[package]] -name = "stable_deref_trait" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" - -[[package]] -name = "stacker" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ccb4c06ec57bc82d0f610f1a2963d7648700e43a6f513e564b9c89f7991786" -dependencies = [ - "cc", - "cfg-if 0.1.10", - "libc", - "psm", - "winapi", -] - [[package]] name = "strsim" version = "0.8.0" @@ -1470,20 +742,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi", -] - [[package]] name = "term" version = "0.6.1" @@ -1503,16 +761,6 @@ dependencies = [ "wincolor", ] -[[package]] -name = "termize" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -1569,52 +817,6 @@ dependencies = [ "serde", ] -[[package]] -name = "tracing" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" -dependencies = [ - "cfg-if 0.1.10", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f0e00789804e99b20f12bc7003ca416309d28a6f495d6af58d1e2c2842461b5" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - -[[package]] -name = "unicode-normalization" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" -dependencies = [ - "smallvec", -] - [[package]] name = "unicode-segmentation" version = "1.3.0" @@ -1662,12 +864,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" - [[package]] name = "winapi" version = "0.3.8" @@ -1708,3 +904,12 @@ dependencies = [ "winapi", "winapi-util", ] + +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi", +] diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml index 28696c5608..24b3b79343 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.36" +version = "1.4.37" authors = ["Nicholas Cameron <ncameron@mozilla.com>", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" @@ -52,7 +52,7 @@ unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "2.0.1" ignore = "0.4.11" -annotate-snippets = { version = "0.6", features = ["ansi_term"] } +annotate-snippets = { version = "0.8", features = ["color"] } structopt = "0.3" rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } lazy_static = "1.0.0" @@ -64,38 +64,4 @@ thiserror = "1.0" # for more information. rustc-workspace-hack = "1.0.0" -[dependencies.rustc_ast] -package = "rustc-ap-rustc_ast" -version = "705.0.0" - -[dependencies.rustc_ast_pretty] -package = "rustc-ap-rustc_ast_pretty" -version = "705.0.0" - -[dependencies.rustc_attr] -package = "rustc-ap-rustc_attr" -version = "705.0.0" - -[dependencies.rustc_data_structures] -package = "rustc-ap-rustc_data_structures" -version = "705.0.0" - -[dependencies.rustc_errors] -package = "rustc-ap-rustc_errors" -version = "705.0.0" - -[dependencies.rustc_expand] -package = "rustc-ap-rustc_expand" -version = "705.0.0" - -[dependencies.rustc_parse] -package = "rustc-ap-rustc_parse" -version = "705.0.0" - -[dependencies.rustc_session] -package = "rustc-ap-rustc_session" -version = "705.0.0" - -[dependencies.rustc_span] -package = "rustc-ap-rustc_span" -version = "705.0.0" +# Rustc dependencies are loaded from the sysroot, Cargo doesn't know about them. diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md index c92be5df01..37cb747413 100644 --- a/src/tools/rustfmt/Configurations.md +++ b/src/tools/rustfmt/Configurations.md @@ -17,6 +17,29 @@ 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` + +Maximum width of an array literal before falling back to vertical formatting. + +- **Default value**: `60` +- **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. + +See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) + +## `attr_fn_like_width` + +Maximum width of the args of a function-like attributes before falling back to vertical formatting. + +- **Default value**: `70` +- **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. + +See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) ## `binop_separator` @@ -272,6 +295,17 @@ where } ``` +## `chain_width` + +Maximum width of a chain to fit on one line. + +- **Default value**: `60` +- **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. + +See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) ## `color` @@ -717,6 +751,17 @@ trait Lorem { } ``` +## `fn_call_width` + +Maximum width of the args of a function call before falling back to vertical formatting. + +- **Default value**: `60` +- **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. + +See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) ## `fn_single_line` @@ -2079,6 +2124,18 @@ Don't reformat out of line modules - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: #3389) +## `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`. + +- **Default value**: `50` +- **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. + +See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) + ## `space_after_colon` Leave a space after the colon. @@ -2256,6 +2313,29 @@ fn main() { See also: [`indent_style`](#indent_style). +## `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`. + +- **Default value**: `18` +- **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. + +See also [`max_width`](#max_width), [`use_small_heuristics`](#use_small_heuristics), and [`struct_lit_single_line`](#struct_lit_single_line) + +## `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`. + +- **Default value**: `35` +- **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. + +See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics) ## `tab_spaces` @@ -2448,13 +2528,43 @@ fn main() { ## `use_small_heuristics` -Whether to use different formatting for items and expressions if they satisfy a heuristic notion of 'small'. +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`. - **Default value**: `"Default"` - **Possible values**: `"Default"`, `"Off"`, `"Max"` - **Stable**: Yes #### `Default` (default): +When `use_small_heuristics` is set to `Default`, the values for the granular width settings are calculated as a ratio of the value for `max_width`. + +The ratios are: +* [`fn_call_width`](#fn_call_width) - `60%` +* [`attr_fn_like_width`](#attr_fn_like_width) - `70%` +* [`struct_lit_width`](#struct_lit_width) - `18%` +* [`struct_variant_width`](#struct_variant_width) - `35%` +* [`array_width`](#array_width) - `60%` +* [`chain_width`](#chain_width) - `60%` +* [`single_line_if_else_max_width`](#single_line_if_else_max_width) - `50%` + +For example when `max_width` is set to `100`, the width settings are: +* `fn_call_width=60` +* `attr_fn_like_width=70` +* `struct_lit_width=18` +* `struct_variant_width=35` +* `array_width=60` +* `chain_width=60` +* `single_line_if_else_max_width=50` + +and when `max_width` is set to `200`: +* `fn_call_width=120` +* `attr_fn_like_width=140` +* `struct_lit_width=36` +* `struct_variant_width=70` +* `array_width=120` +* `chain_width=120` +* `single_line_if_else_max_width=100` ```rust enum Lorem { @@ -2485,6 +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. ```rust enum Lorem { @@ -2513,6 +2624,16 @@ fn main() { ``` #### `Max`: +When `use_small_heuristics` is set to `Max`, then each granular width setting is set to the same value as `max_width`. + +So if `max_width` is set to `200`, then all the width settings are also set to `200`. +* `fn_call_width=200` +* `attr_fn_like_width=200` +* `struct_lit_width=200` +* `struct_variant_width=200` +* `array_width=200` +* `chain_width=200` +* `single_line_if_else_max_width=200` ```rust enum Lorem { @@ -2530,6 +2651,17 @@ fn main() { } ``` + +See also: +* [`max_width`](#max_width) +* [`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) + ## `use_try_shorthand` Replace uses of the try! macro by the ? shorthand diff --git a/src/tools/rustfmt/config_proc_macro/src/lib.rs b/src/tools/rustfmt/config_proc_macro/src/lib.rs index 66cfd3c727..78e7e098ed 100644 --- a/src/tools/rustfmt/config_proc_macro/src/lib.rs +++ b/src/tools/rustfmt/config_proc_macro/src/lib.rs @@ -2,8 +2,6 @@ #![recursion_limit = "256"] -extern crate proc_macro; - mod attrs; mod config_type; mod item_enum; diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain index 09ed382937..b7d71e79b1 100644 --- a/src/tools/rustfmt/rust-toolchain +++ b/src/tools/rustfmt/rust-toolchain @@ -1 +1,3 @@ -nightly-2021-02-06 +[toolchain] +channel = "nightly-2021-05-04" +components = ["rustc-dev"] diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 2d25c26327..c5ffb074ba 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -1,7 +1,7 @@ //! Format attributes and meta items. use rustc_ast::ast; -use rustc_ast::attr::HasAttrs; +use rustc_ast::AstLike; use rustc_span::{symbol::sym, Span, Symbol}; use self::doc_comment::DocCommentFormatter; @@ -300,7 +300,7 @@ impl Rewrite for ast::MetaItem { // 1 = "]" shape.sub_width(1)?, self.span, - context.config.width_heuristics().attr_fn_like_width, + context.config.attr_fn_like_width(), Some(if has_trailing_comma { SeparatorTactic::Always } else { @@ -376,7 +376,7 @@ impl Rewrite for ast::Attribute { } } -impl<'a> Rewrite for [ast::Attribute] { +impl Rewrite for [ast::Attribute] { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { if self.is_empty() { return Some(String::new()); diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index 9101c015fb..56b0722221 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -1,5 +1,5 @@ use anyhow::{format_err, Result}; -use env_logger; + use io::Error as IoError; use thiserror::Error; @@ -233,7 +233,7 @@ fn execute(opts: &Options) -> Result<i32> { let file = PathBuf::from(path); let file = file.canonicalize().unwrap_or(file); - let (config, _) = load_config(Some(file.parent().unwrap()), Some(options.clone()))?; + let (config, _) = load_config(Some(file.parent().unwrap()), Some(options))?; let toml = config.all_options().to_toml()?; io::stdout().write_all(toml.as_bytes())?; @@ -565,7 +565,7 @@ impl GetOptsOptions { options.inline_config = matches .opt_strs("config") .iter() - .flat_map(|config| config.split(",")) + .flat_map(|config| config.split(',')) .map( |key_val| match key_val.char_indices().find(|(_, ch)| *ch == '=') { Some((middle, _)) => { @@ -681,7 +681,7 @@ impl CliOptions for GetOptsOptions { } fn config_path(&self) -> Option<&Path> { - self.config_path.as_ref().map(|p| &**p) + self.config_path.as_deref() } } diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs index 22aeceeb53..9062a2952e 100644 --- a/src/tools/rustfmt/src/cargo-fmt/main.rs +++ b/src/tools/rustfmt/src/cargo-fmt/main.rs @@ -2,8 +2,6 @@ #![deny(warnings)] -use cargo_metadata; - use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; use std::env; diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs index ac14ec9e11..8053f0e8fe 100644 --- a/src/tools/rustfmt/src/chains.rs +++ b/src/tools/rustfmt/src/chains.rs @@ -577,7 +577,7 @@ impl<'a> ChainFormatterShared<'a> { let one_line_budget = if self.child_count == 1 { shape.width } else { - min(shape.width, context.config.width_heuristics().chain_width) + min(shape.width, context.config.chain_width()) } .saturating_sub(almost_total); diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs index 9959ef7fd9..c71302fdd1 100644 --- a/src/tools/rustfmt/src/comment.rs +++ b/src/tools/rustfmt/src/comment.rs @@ -977,6 +977,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s pub(crate) trait FindUncommented { fn find_uncommented(&self, pat: &str) -> Option<usize>; + fn find_last_uncommented(&self, pat: &str) -> Option<usize>; } impl FindUncommented for str { @@ -1002,6 +1003,19 @@ impl FindUncommented for str { None => Some(self.len() - pat.len()), } } + + fn find_last_uncommented(&self, pat: &str) -> Option<usize> { + if let Some(left) = self.find_uncommented(pat) { + let mut result = left; + // add 1 to use find_last_uncommented for &str after pat + while let Some(next) = self[(result + 1)..].find_last_uncommented(pat) { + result += next + 1; + } + Some(result) + } else { + None + } + } } // Returns the first byte position after the first comment. The given string @@ -1297,6 +1311,9 @@ where char_kind = FullCodeCharKind::InStringCommented; if chr == '"' { CharClassesStatus::BlockComment(deepness) + } else if chr == '*' && self.base.peek().map(RichChar::get_char) == Some('/') { + char_kind = FullCodeCharKind::InComment; + CharClassesStatus::BlockCommentClosing(deepness - 1) } else { CharClassesStatus::StringInBlockComment(deepness) } @@ -1674,7 +1691,8 @@ fn remove_comment_header(comment: &str) -> &str { } else { assert!( comment.starts_with("/*"), - format!("string '{}' is not a comment", comment) + "string '{}' is not a comment", + comment ); &comment[2..comment.len() - 2] } diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs index bd4a847e0f..2f567b2552 100644 --- a/src/tools/rustfmt/src/config/config_type.rs +++ b/src/tools/rustfmt/src/config/config_type.rs @@ -95,7 +95,15 @@ macro_rules! create_config { pub fn $i(&mut self, value: $ty) { (self.0).$i.2 = value; match stringify!($i) { - "max_width" | "use_small_heuristics" => self.0.set_heuristics(), + "max_width" + | "use_small_heuristics" + | "fn_call_width" + | "single_line_if_else_max_width" + | "attr_fn_like_width" + | "struct_lit_width" + | "struct_variant_width" + | "array_width" + | "chain_width" => self.0.set_heuristics(), "license_template_path" => self.0.set_license_template(), "merge_imports" => self.0.set_merge_imports(), &_ => (), @@ -230,7 +238,15 @@ macro_rules! create_config { } match key { - "max_width" | "use_small_heuristics" => self.set_heuristics(), + "max_width" + | "use_small_heuristics" + | "fn_call_width" + | "single_line_if_else_max_width" + | "attr_fn_like_width" + | "struct_lit_width" + | "struct_variant_width" + | "array_width" + | "chain_width" => self.set_heuristics(), "license_template_path" => self.set_license_template(), "merge_imports" => self.set_merge_imports(), &_ => (), @@ -281,16 +297,93 @@ macro_rules! create_config { )+ } + fn set_width_heuristics(&mut self, heuristics: WidthHeuristics) { + let max_width = self.max_width.2; + let get_width_value = | + was_set: bool, + override_value: usize, + heuristic_value: usize, + config_key: &str, + | -> usize { + if !was_set { + return heuristic_value; + } + if override_value > max_width { + eprintln!( + "`{0}` cannot have a value that exceeds `max_width`. \ + `{0}` will be set to the same value as `max_width`", + config_key, + ); + return max_width; + } + override_value + }; + + let fn_call_width = get_width_value( + self.was_set().fn_call_width(), + self.fn_call_width.2, + heuristics.fn_call_width, + "fn_call_width", + ); + self.fn_call_width.2 = fn_call_width; + + let attr_fn_like_width = get_width_value( + self.was_set().attr_fn_like_width(), + self.attr_fn_like_width.2, + heuristics.attr_fn_like_width, + "attr_fn_like_width", + ); + self.attr_fn_like_width.2 = attr_fn_like_width; + + let struct_lit_width = get_width_value( + self.was_set().struct_lit_width(), + self.struct_lit_width.2, + heuristics.struct_lit_width, + "struct_lit_width", + ); + self.struct_lit_width.2 = struct_lit_width; + + let struct_variant_width = get_width_value( + self.was_set().struct_variant_width(), + self.struct_variant_width.2, + heuristics.struct_variant_width, + "struct_variant_width", + ); + self.struct_variant_width.2 = struct_variant_width; + + let array_width = get_width_value( + self.was_set().array_width(), + self.array_width.2, + heuristics.array_width, + "array_width", + ); + self.array_width.2 = array_width; + + let chain_width = get_width_value( + self.was_set().chain_width(), + self.chain_width.2, + heuristics.chain_width, + "chain_width", + ); + self.chain_width.2 = chain_width; + + let single_line_if_else_max_width = get_width_value( + self.was_set().single_line_if_else_max_width(), + self.single_line_if_else_max_width.2, + heuristics.single_line_if_else_max_width, + "single_line_if_else_max_width", + ); + self.single_line_if_else_max_width.2 = single_line_if_else_max_width; + } + fn set_heuristics(&mut self) { - if self.use_small_heuristics.2 == Heuristics::Default { - let max_width = self.max_width.2; - self.set().width_heuristics(WidthHeuristics::scaled(max_width)); - } else if self.use_small_heuristics.2 == Heuristics::Max { - let max_width = self.max_width.2; - self.set().width_heuristics(WidthHeuristics::set(max_width)); - } else { - self.set().width_heuristics(WidthHeuristics::null()); - } + let max_width = self.max_width.2; + match self.use_small_heuristics.2 { + Heuristics::Default => + self.set_width_heuristics(WidthHeuristics::scaled(max_width)), + Heuristics::Max => self.set_width_heuristics(WidthHeuristics::set(max_width)), + Heuristics::Off => self.set_width_heuristics(WidthHeuristics::null()), + }; } fn set_license_template(&mut self) { diff --git a/src/tools/rustfmt/src/config/file_lines.rs b/src/tools/rustfmt/src/config/file_lines.rs index 18ae2fd2c4..95e5d0c915 100644 --- a/src/tools/rustfmt/src/config/file_lines.rs +++ b/src/tools/rustfmt/src/config/file_lines.rs @@ -3,9 +3,9 @@ use itertools::Itertools; use std::collections::HashMap; use std::path::PathBuf; -use std::rc::Rc; use std::{cmp, fmt, iter, str}; +use rustc_data_structures::sync::Lrc; use rustc_span::{self, SourceFile}; use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; use serde_json as json; @@ -13,7 +13,7 @@ use thiserror::Error; /// A range of lines in a file, inclusive of both ends. pub struct LineRange { - pub file: Rc<SourceFile>, + pub file: Lrc<SourceFile>, pub lo: usize, pub hi: usize, } diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index dfce7977bf..8c04363b1f 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -35,9 +35,26 @@ create_config! { hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; tab_spaces: usize, 4, true, "Number of spaces per tab"; newline_style: NewlineStyle, NewlineStyle::Auto, true, "Unix or Windows line endings"; + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; + + // Width Heuristics use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ formatting for items and expressions if they satisfy a heuristic notion of 'small'"; - indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; + fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \ + falling back to vertical formatting."; + attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \ + attributes before falling back to vertical formatting."; + struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \ + falling back to vertical formatting."; + struct_variant_width: usize, 35, true, "Maximum width in the body of a struct variant before \ + falling back to vertical formatting."; + array_width: usize, 60, true, "Maximum width of an array literal before falling \ + back to vertical formatting."; + chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; + single_line_if_else_max_width: usize, 50, true, "Maximum line length for single line if-else \ + expressions. A value of zero means always break if-else expressions."; // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; @@ -154,8 +171,6 @@ create_config! { file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, - "'small' heuristic values"; emit_mode: EmitMode, EmitMode::Files, false, "What emit Mode to use when none is supplied"; make_backup: bool, false, false, "Backup changed files"; @@ -394,9 +409,6 @@ mod test { create_config! { // Options that are used by the generated functions max_width: usize, 100, true, "Maximum width of each line"; - use_small_heuristics: Heuristics, Heuristics::Default, true, - "Whether to use different formatting for items and \ - expressions if they satisfy a heuristic notion of 'small'."; license_template_path: String, String::default(), false, "Beginning of file must match license template"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, @@ -408,13 +420,33 @@ mod test { file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, - "'small' heuristic values"; + // merge_imports deprecation imports_granularity: ImportGranularity, ImportGranularity::Preserve, false, "Merge imports"; merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)"; + // Width Heuristics + use_small_heuristics: Heuristics, Heuristics::Default, true, + "Whether to use different formatting for items and \ + expressions if they satisfy a heuristic notion of 'small'."; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; + + fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \ + falling back to vertical formatting."; + attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \ + attributes before falling back to vertical formatting."; + struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \ + falling back to vertical formatting."; + struct_variant_width: usize, 35, true, "Maximum width in the body of a struct \ + variant before falling back to vertical formatting."; + array_width: usize, 60, true, "Maximum width of an array literal before falling \ + back to vertical formatting."; + chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; + single_line_if_else_max_width: usize, 50, true, "Maximum line length for single \ + line if-else expressions. A value of zero means always break if-else expressions."; + // Options that are used by the tests stable_option: bool, false, true, "A stable option"; unstable_option: bool, false, false, "An unstable option"; @@ -519,8 +551,15 @@ mod test { hard_tabs = false tab_spaces = 4 newline_style = "Auto" -use_small_heuristics = "Default" indent_style = "Block" +use_small_heuristics = "Default" +fn_call_width = 60 +attr_fn_like_width = 70 +struct_lit_width = 18 +struct_variant_width = 35 +array_width = 60 +chain_width = 60 +single_line_if_else_max_width = 50 wrap_comments = false format_code_in_doc_comments = false comment_width = 80 @@ -683,4 +722,242 @@ make_backup = false assert_eq!(config.imports_granularity(), ImportGranularity::Module); } } + + #[cfg(test)] + mod use_small_heuristics { + use super::*; + + #[test] + fn test_default_sets_correct_widths() { + let toml = r#" + use_small_heuristics = "Default" + max_width = 200 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 120); + assert_eq!(config.attr_fn_like_width(), 140); + assert_eq!(config.chain_width(), 120); + assert_eq!(config.fn_call_width(), 120); + assert_eq!(config.single_line_if_else_max_width(), 100); + assert_eq!(config.struct_lit_width(), 36); + assert_eq!(config.struct_variant_width(), 70); + } + + #[test] + fn test_max_sets_correct_widths() { + let toml = r#" + use_small_heuristics = "Max" + max_width = 120 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 120); + assert_eq!(config.attr_fn_like_width(), 120); + assert_eq!(config.chain_width(), 120); + assert_eq!(config.fn_call_width(), 120); + assert_eq!(config.single_line_if_else_max_width(), 120); + assert_eq!(config.struct_lit_width(), 120); + assert_eq!(config.struct_variant_width(), 120); + } + + #[test] + fn test_off_sets_correct_widths() { + let toml = r#" + use_small_heuristics = "Off" + max_width = 100 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), usize::max_value()); + assert_eq!(config.attr_fn_like_width(), usize::max_value()); + assert_eq!(config.chain_width(), usize::max_value()); + assert_eq!(config.fn_call_width(), usize::max_value()); + assert_eq!(config.single_line_if_else_max_width(), 0); + assert_eq!(config.struct_lit_width(), 0); + assert_eq!(config.struct_variant_width(), 0); + } + + #[test] + fn test_override_works_with_default() { + let toml = r#" + use_small_heuristics = "Default" + array_width = 20 + attr_fn_like_width = 40 + chain_width = 20 + fn_call_width = 90 + single_line_if_else_max_width = 40 + struct_lit_width = 30 + struct_variant_width = 34 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 20); + assert_eq!(config.attr_fn_like_width(), 40); + assert_eq!(config.chain_width(), 20); + assert_eq!(config.fn_call_width(), 90); + assert_eq!(config.single_line_if_else_max_width(), 40); + assert_eq!(config.struct_lit_width(), 30); + assert_eq!(config.struct_variant_width(), 34); + } + + #[test] + fn test_override_with_max() { + let toml = r#" + use_small_heuristics = "Max" + array_width = 20 + attr_fn_like_width = 40 + chain_width = 20 + fn_call_width = 90 + single_line_if_else_max_width = 40 + struct_lit_width = 30 + struct_variant_width = 34 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 20); + assert_eq!(config.attr_fn_like_width(), 40); + assert_eq!(config.chain_width(), 20); + assert_eq!(config.fn_call_width(), 90); + assert_eq!(config.single_line_if_else_max_width(), 40); + assert_eq!(config.struct_lit_width(), 30); + assert_eq!(config.struct_variant_width(), 34); + } + + #[test] + fn test_override_with_off() { + let toml = r#" + use_small_heuristics = "Off" + array_width = 20 + attr_fn_like_width = 40 + chain_width = 20 + fn_call_width = 90 + single_line_if_else_max_width = 40 + struct_lit_width = 30 + struct_variant_width = 34 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 20); + assert_eq!(config.attr_fn_like_width(), 40); + assert_eq!(config.chain_width(), 20); + assert_eq!(config.fn_call_width(), 90); + assert_eq!(config.single_line_if_else_max_width(), 40); + assert_eq!(config.struct_lit_width(), 30); + assert_eq!(config.struct_variant_width(), 34); + } + + #[test] + fn test_fn_call_width_config_exceeds_max_width() { + let toml = r#" + max_width = 90 + fn_call_width = 95 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.fn_call_width(), 90); + } + + #[test] + fn test_attr_fn_like_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + attr_fn_like_width = 90 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.attr_fn_like_width(), 80); + } + + #[test] + fn test_struct_lit_config_exceeds_max_width() { + let toml = r#" + max_width = 78 + struct_lit_width = 90 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.struct_lit_width(), 78); + } + + #[test] + fn test_struct_variant_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + struct_variant_width = 90 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.struct_variant_width(), 80); + } + + #[test] + fn test_array_width_config_exceeds_max_width() { + let toml = r#" + max_width = 60 + array_width = 80 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 60); + } + + #[test] + fn test_chain_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + chain_width = 90 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.chain_width(), 80); + } + + #[test] + fn test_single_line_if_else_max_width_config_exceeds_max_width() { + let toml = r#" + max_width = 70 + single_line_if_else_max_width = 90 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.single_line_if_else_max_width(), 70); + } + + #[test] + fn test_override_fn_call_width_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("fn_call_width", "101"); + assert_eq!(config.fn_call_width(), 100); + } + + #[test] + fn test_override_attr_fn_like_width_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("attr_fn_like_width", "101"); + assert_eq!(config.attr_fn_like_width(), 100); + } + + #[test] + fn test_override_struct_lit_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("struct_lit_width", "101"); + assert_eq!(config.struct_lit_width(), 100); + } + + #[test] + fn test_override_struct_variant_width_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("struct_variant_width", "101"); + assert_eq!(config.struct_variant_width(), 100); + } + + #[test] + fn test_override_array_width_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("array_width", "101"); + assert_eq!(config.array_width(), 100); + } + + #[test] + fn test_override_chain_width_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("chain_width", "101"); + assert_eq!(config.chain_width(), 100); + } + + #[test] + fn test_override_single_line_if_else_max_width_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("single_line_if_else_max_width", "101"); + assert_eq!(config.single_line_if_else_max_width(), 100); + } + } } diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs index c0491630c0..3b91021813 100644 --- a/src/tools/rustfmt/src/config/options.rs +++ b/src/tools/rustfmt/src/config/options.rs @@ -79,13 +79,15 @@ pub enum TypeDensity { } #[config_type] -/// To what extent does rustfmt pursue its heuristics? +/// Heuristic settings that can be used to simply +/// the configuration of the granular width configurations +/// like `struct_lit_width`, `array_width`, etc. pub enum Heuristics { /// Turn off any heuristics Off, /// Turn on max heuristics Max, - /// Use Rustfmt's defaults + /// Use scaled values based on the value of `max_width` Default, } diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 33add30c7c..ced382c491 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -9,8 +9,8 @@ use rustc_span::{BytePos, Span}; use crate::chains::rewrite_chain; use crate::closures; use crate::comment::{ - combine_strs_with_missing_comments, comment_style, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, + combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, + rewrite_missing_comment, CharClasses, FindUncommented, }; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; @@ -106,15 +106,10 @@ pub(crate) fn format_expr( }) } ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), - ast::ExprKind::Struct(ref path, ref fields, ref struct_rest) => rewrite_struct_lit( - context, - path, - fields, - struct_rest, - &expr.attrs, - expr.span, - shape, - ), + ast::ExprKind::Struct(ref struct_expr) => { + let ast::StructExpr { fields, path, rest } = &**struct_expr; + rewrite_struct_lit(context, path, fields, rest, &expr.attrs, expr.span, shape) + } ast::ExprKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) } @@ -829,38 +824,16 @@ impl<'a> ControlFlow<'a> { let comments_lo = context .snippet_provider .span_after(self.span, self.connector.trim()); - let missing_comments = if let Some(comment) = - rewrite_missing_comment(mk_sp(comments_lo, expr.span.lo()), cond_shape, context) - { - if !self.connector.is_empty() && !comment.is_empty() { - if comment_style(&comment, false).is_line_comment() || comment.contains("\n") { - let newline = &pat_shape - .indent - .block_indent(context.config) - .to_string_with_newline(context.config); - // An extra space is added when the lhs and rhs are joined - // so we need to remove one space from the end to ensure - // the comment and rhs are aligned. - let mut suffix = newline.as_ref().to_string(); - if !suffix.is_empty() { - suffix.truncate(suffix.len() - 1); - } - format!("{}{}{}", newline, comment, suffix) - } else { - format!(" {}", comment) - } - } else { - comment - } - } else { - "".to_owned() - }; - - let result = format!( - "{}{}{}{}", - matcher, pat_string, self.connector, missing_comments + let comments_span = mk_sp(comments_lo, expr.span.lo()); + return rewrite_assign_rhs_with_comments( + context, + &format!("{}{}{}", matcher, pat_string, self.connector), + expr, + cond_shape, + RhsTactics::Default, + comments_span, + true, ); - return rewrite_assign_rhs(context, result, expr, cond_shape); } let expr_rw = expr.rewrite(context, cond_shape); @@ -926,22 +899,11 @@ impl<'a> ControlFlow<'a> { || last_line_offsetted(shape.used_width(), &pat_expr_string)); // Try to format if-else on single line. - if self.allow_single_line - && context - .config - .width_heuristics() - .single_line_if_else_max_width - > 0 - { + if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if let Some(cond_str) = trial { - if cond_str.len() - <= context - .config - .width_heuristics() - .single_line_if_else_max_width - { + if cond_str.len() <= context.config.single_line_if_else_max_width() { return Some((cond_str, 0)); } } @@ -1273,7 +1235,7 @@ pub(crate) fn rewrite_call( args.iter(), shape, span, - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), choose_separator_tactic(context, span), ) } @@ -1518,14 +1480,14 @@ fn rewrite_index( } } -fn struct_lit_can_be_aligned(fields: &[ast::Field], has_base: bool) -> bool { +fn struct_lit_can_be_aligned(fields: &[ast::ExprField], has_base: bool) -> bool { !has_base && fields.iter().all(|field| !field.is_shorthand) } fn rewrite_struct_lit<'a>( context: &RewriteContext<'_>, path: &ast::Path, - fields: &'a [ast::Field], + fields: &'a [ast::ExprField], struct_rest: &ast::StructRest, attrs: &[ast::Attribute], span: Span, @@ -1534,7 +1496,7 @@ fn rewrite_struct_lit<'a>( debug!("rewrite_struct_lit: shape {:?}", shape); enum StructLitField<'a> { - Regular(&'a ast::Field), + Regular(&'a ast::ExprField), Base(&'a ast::Expr), Rest(&'a Span), } @@ -1690,7 +1652,7 @@ pub(crate) fn struct_lit_field_separator(config: &Config) -> &str { pub(crate) fn rewrite_field( context: &RewriteContext<'_>, - field: &ast::Field, + field: &ast::ExprField, shape: Shape, prefix_max_width: usize, ) -> Option<String> { @@ -1812,7 +1774,7 @@ pub(crate) fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( items, shape, span, - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), force_tactic, ) } else { @@ -1899,14 +1861,13 @@ pub(crate) fn rewrite_assign_rhs<S: Into<String>, R: Rewrite>( rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default) } -pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>( +pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>( context: &RewriteContext<'_>, - lhs: S, + lhs: &str, ex: &R, shape: Shape, rhs_tactics: RhsTactics, ) -> Option<String> { - let lhs = lhs.into(); let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') { shape.indent.width() } else { @@ -1918,22 +1879,67 @@ pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>( offset: shape.offset + last_line_width + 1, ..shape }); - let rhs = choose_rhs( + let has_rhs_comment = if let Some(offset) = lhs.find_last_uncommented("=") { + lhs.trim_end().len() > offset + 1 + } else { + false + }; + + choose_rhs( context, ex, orig_shape, ex.rewrite(context, orig_shape), rhs_tactics, - )?; + has_rhs_comment, + ) +} + +pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>( + context: &RewriteContext<'_>, + lhs: S, + ex: &R, + shape: Shape, + rhs_tactics: RhsTactics, +) -> Option<String> { + let lhs = lhs.into(); + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?; Some(lhs + &rhs) } +pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>( + context: &RewriteContext<'_>, + lhs: S, + ex: &R, + shape: Shape, + rhs_tactics: RhsTactics, + between_span: Span, + allow_extend: bool, +) -> Option<String> { + let lhs = lhs.into(); + let contains_comment = contains_comment(context.snippet(between_span)); + let shape = if contains_comment { + shape.block_left(context.config.tab_spaces())? + } else { + shape + }; + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?; + + if contains_comment { + let rhs = rhs.trim_start(); + combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend) + } else { + Some(lhs + &rhs) + } +} + fn choose_rhs<R: Rewrite>( context: &RewriteContext<'_>, expr: &R, shape: Shape, orig_rhs: Option<String>, rhs_tactics: RhsTactics, + has_rhs_comment: bool, ) -> Option<String> { match orig_rhs { Some(ref new_str) @@ -1950,13 +1956,14 @@ fn choose_rhs<R: Rewrite>( .indent .block_indent(context.config) .to_string_with_newline(context.config); + let before_space_str = if has_rhs_comment { "" } else { " " }; match (orig_rhs, new_rhs) { (Some(ref orig_rhs), Some(ref new_rhs)) if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) .is_none() => { - Some(format!(" {}", orig_rhs)) + Some(format!("{}{}", before_space_str, orig_rhs)) } (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) => @@ -1966,10 +1973,11 @@ fn choose_rhs<R: Rewrite>( (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), (None, None) if rhs_tactics == RhsTactics::AllowOverflow => { let shape = shape.infinite_width(); - expr.rewrite(context, shape).map(|s| format!(" {}", s)) + expr.rewrite(context, shape) + .map(|s| format!("{}{}", before_space_str, s)) } (None, None) => None, - (Some(orig_rhs), _) => Some(format!(" {}", orig_rhs)), + (Some(orig_rhs), _) => Some(format!("{}{}", before_space_str, orig_rhs)), } } } diff --git a/src/tools/rustfmt/src/format-diff/main.rs b/src/tools/rustfmt/src/format-diff/main.rs index 8a8bb9356c..c751932273 100644 --- a/src/tools/rustfmt/src/format-diff/main.rs +++ b/src/tools/rustfmt/src/format-diff/main.rs @@ -4,10 +4,9 @@ #![deny(warnings)] -use env_logger; #[macro_use] extern crate log; -use regex; + use serde::{Deserialize, Serialize}; use serde_json as json; use thiserror::Error; diff --git a/src/tools/rustfmt/src/format_report_formatter.rs b/src/tools/rustfmt/src/format_report_formatter.rs index 2fc6c4e895..c820259256 100644 --- a/src/tools/rustfmt/src/format_report_formatter.rs +++ b/src/tools/rustfmt/src/format_report_formatter.rs @@ -1,8 +1,6 @@ -use crate::config::FileName; use crate::formatting::FormattingError; use crate::{ErrorKind, FormatReport}; -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::display_list::{DisplayList, FormatOptions}; use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; use std::fmt::{self, Display}; @@ -48,91 +46,79 @@ pub struct FormatReportFormatter<'a> { impl<'a> Display for FormatReportFormatter<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let formatter = DisplayListFormatter::new(self.enable_colors, false); let errors_by_file = &self.report.internal.borrow().0; + let opt = FormatOptions { + color: self.enable_colors, + ..Default::default() + }; + for (file, errors) in errors_by_file { for error in errors { - let snippet = formatting_error_to_snippet(file, error); - writeln!(f, "{}\n", formatter.format(&DisplayList::from(snippet)))?; + let error_kind = error.kind.to_string(); + let title = Some(Annotation { + id: if error.is_internal() { + Some("internal") + } else { + None + }, + label: Some(&error_kind), + annotation_type: error_kind_to_snippet_annotation_type(&error.kind), + }); + + let message_suffix = error.msg_suffix(); + let footer = if !message_suffix.is_empty() { + Some(Annotation { + id: None, + label: Some(message_suffix), + annotation_type: AnnotationType::Note, + }) + } else { + None + }; + + let origin = format!("{}:{}", file, error.line); + let slice = Slice { + source: &error.line_buffer.clone(), + line_start: error.line, + origin: Some(origin.as_str()), + fold: false, + annotations: slice_annotation(error).into_iter().collect(), + }; + + let snippet = Snippet { + title, + footer: footer.into_iter().collect(), + slices: vec![slice], + opt, + }; + writeln!(f, "{}\n", DisplayList::from(snippet))?; } } if !errors_by_file.is_empty() { - let snippet = formatting_failure_snippet(self.report.warning_count()); - writeln!(f, "{}", formatter.format(&DisplayList::from(snippet)))?; + let label = format!( + "rustfmt has failed to format. See previous {} errors.", + self.report.warning_count() + ); + let snippet = Snippet { + title: Some(Annotation { + id: None, + label: Some(&label), + annotation_type: AnnotationType::Warning, + }), + footer: Vec::new(), + slices: Vec::new(), + opt, + }; + writeln!(f, "{}", DisplayList::from(snippet))?; } Ok(()) } } -fn formatting_failure_snippet(warning_count: usize) -> Snippet { - Snippet { - title: Some(Annotation { - id: None, - label: Some(format!( - "rustfmt has failed to format. See previous {} errors.", - warning_count - )), - annotation_type: AnnotationType::Warning, - }), - footer: Vec::new(), - slices: Vec::new(), - } -} - -fn formatting_error_to_snippet(file: &FileName, error: &FormattingError) -> Snippet { - let slices = vec![snippet_code_slice(file, error)]; - let title = Some(snippet_title(error)); - let footer = snippet_footer(error).into_iter().collect(); - - Snippet { - title, - footer, - slices, - } -} - -fn snippet_title(error: &FormattingError) -> Annotation { - let annotation_type = error_kind_to_snippet_annotation_type(&error.kind); - - Annotation { - id: title_annotation_id(error), - label: Some(error.kind.to_string()), - annotation_type, - } -} - -fn snippet_footer(error: &FormattingError) -> Option<Annotation> { - let message_suffix = error.msg_suffix(); - - if !message_suffix.is_empty() { - Some(Annotation { - id: None, - label: Some(message_suffix.to_string()), - annotation_type: AnnotationType::Note, - }) - } else { - None - } -} - -fn snippet_code_slice(file: &FileName, error: &FormattingError) -> Slice { - let annotations = slice_annotation(error).into_iter().collect(); - let origin = Some(format!("{}:{}", file, error.line)); - let source = error.line_buffer.clone(); - - Slice { - source, - line_start: error.line, - origin, - fold: false, - annotations, - } -} - -fn slice_annotation(error: &FormattingError) -> Option<SourceAnnotation> { +fn slice_annotation(error: &FormattingError) -> Option<SourceAnnotation<'_>> { let (range_start, range_length) = error.format_len(); let range_end = range_start + range_length; @@ -140,23 +126,13 @@ fn slice_annotation(error: &FormattingError) -> Option<SourceAnnotation> { Some(SourceAnnotation { annotation_type: AnnotationType::Error, range: (range_start, range_end), - label: String::new(), + label: "", }) } else { None } } -fn title_annotation_id(error: &FormattingError) -> Option<String> { - const INTERNAL_ERROR_ID: &str = "internal"; - - if error.is_internal() { - Some(INTERNAL_ERROR_ID.to_string()) - } else { - None - } -} - fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationType { match error_kind { ErrorKind::LineOverflow(..) diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs index 289e58cf69..b69ecdc5cb 100644 --- a/src/tools/rustfmt/src/formatting.rs +++ b/src/tools/rustfmt/src/formatting.rs @@ -76,7 +76,7 @@ fn format_project<T: FormatHandler>( // Parse the crate. let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); - let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { + let krate = match Parser::parse_crate(input, &parse_session) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) Err(e) => { @@ -92,7 +92,7 @@ fn format_project<T: FormatHandler>( let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( &context.parse_session, - directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), + directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock), !input_is_stdin && !config.skip_children(), ) .visit_crate(&krate)?; @@ -145,7 +145,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { module: &Module<'_>, is_macro_def: bool, ) -> Result<(), ErrorKind> { - let snippet_provider = self.parse_session.snippet_provider(module.as_ref().inner); + let snippet_provider = self.parse_session.snippet_provider(module.span); let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, &self.config, @@ -331,6 +331,9 @@ pub(crate) struct ReportedErrors { /// Formatted code differs from existing code (--check only). pub(crate) has_diff: bool, + + /// Formatted code missed something, like lost comments or extra trailing space + pub(crate) has_unformatted_code_errors: bool, } impl ReportedErrors { @@ -342,6 +345,7 @@ impl ReportedErrors { self.has_macro_format_failure |= other.has_macro_format_failure; self.has_check_errors |= other.has_check_errors; self.has_diff |= other.has_diff; + self.has_unformatted_code_errors |= other.has_unformatted_code_errors; } } diff --git a/src/tools/rustfmt/src/git-rustfmt/main.rs b/src/tools/rustfmt/src/git-rustfmt/main.rs index c90eae3e64..16f5d1dd4f 100644 --- a/src/tools/rustfmt/src/git-rustfmt/main.rs +++ b/src/tools/rustfmt/src/git-rustfmt/main.rs @@ -7,7 +7,6 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; -use env_logger; use getopts::{Matches, Options}; use rustfmt_nightly as rustfmt; @@ -127,7 +126,6 @@ fn make_opts() -> Options { struct Config { commits: String, uncommitted: bool, - check: bool, } impl Config { @@ -146,11 +144,9 @@ impl Config { let mut config = Config { commits: "1".to_owned(), uncommitted: false, - check: false, }; if matches.opt_present("c") { - config.check = true; unimplemented!(); } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 10654a2a5a..ecbd0bd12e 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -17,7 +17,8 @@ use crate::comment::{ use crate::config::lists::*; use crate::config::{BraceStyle, Config, IndentStyle, Version}; use crate::expr::{ - is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, RhsTactics, + is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, + rewrite_assign_rhs_with_comments, RhsTactics, }; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use crate::macros::{rewrite_macro, MacroPosition}; @@ -157,7 +158,7 @@ impl<'a> Item<'a> { #[derive(Debug)] enum BodyElement<'a> { // Stmt(&'a ast::Stmt), - // Field(&'a ast::Field), + // Field(&'a ast::ExprField), // Variant(&'a ast::Variant), // Item(&'a ast::Item), ForeignItem(&'a ast::ForeignItem), @@ -504,8 +505,8 @@ impl<'a> FmtVisitor<'a> { ) .collect() }; - let mut items: Vec<_> = - itemize_list_with(self.config.width_heuristics().struct_variant_width); + let mut items: Vec<_> = itemize_list_with(self.config.struct_variant_width()); + // If one of the variants use multiple lines, use multi-lined formatting for all variants. let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n')); let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n')); @@ -1273,7 +1274,7 @@ fn format_unit_struct( pub(crate) fn format_struct_struct( context: &RewriteContext<'_>, struct_parts: &StructParts<'_>, - fields: &[ast::StructField], + fields: &[ast::FieldDef], offset: Indent, one_line_width: Option<usize>, ) -> Option<String> { @@ -1410,7 +1411,7 @@ fn format_empty_struct_or_tuple( fn format_tuple_struct( context: &RewriteContext<'_>, struct_parts: &StructParts<'_>, - fields: &[ast::StructField], + fields: &[ast::FieldDef], offset: Indent, ) -> Option<String> { let mut result = String::with_capacity(1024); @@ -1478,7 +1479,7 @@ fn format_tuple_struct( fields.iter(), shape, span, - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), None, )?; } @@ -1630,7 +1631,7 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { pub(crate) fn rewrite_struct_field_prefix( context: &RewriteContext<'_>, - field: &ast::StructField, + field: &ast::FieldDef, ) -> Option<String> { let vis = format_visibility(context, &field.vis); let type_annotation_spacing = type_annotation_spacing(context.config); @@ -1645,7 +1646,7 @@ pub(crate) fn rewrite_struct_field_prefix( }) } -impl Rewrite for ast::StructField { +impl Rewrite for ast::FieldDef { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { rewrite_struct_field(context, self, shape, 0) } @@ -1653,7 +1654,7 @@ impl Rewrite for ast::StructField { pub(crate) fn rewrite_struct_field( context: &RewriteContext<'_>, - field: &ast::StructField, + field: &ast::FieldDef, shape: Shape, lhs_max_width: usize, ) -> Option<String> { @@ -1822,14 +1823,22 @@ fn rewrite_static( }; if let Some(expr) = static_parts.expr_opt { + let comments_lo = context.snippet_provider.span_after(static_parts.span, "="); + let expr_lo = expr.span.lo(); + let comments_span = mk_sp(comments_lo, expr_lo); + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; let remaining_width = context.budget(offset.block_indent + 1); - rewrite_assign_rhs( + rewrite_assign_rhs_with_comments( context, - lhs, + &lhs, &**expr, Shape::legacy(remaining_width, offset.block_only()), + RhsTactics::Default, + comments_span, + true, ) .and_then(|res| recover_comment_removed(res, static_parts.span, context)) .map(|s| if s.ends_with(';') { s } else { s + ";" }) @@ -3262,8 +3271,8 @@ pub(crate) fn rewrite_extern_crate( /// Returns `true` for `mod foo;`, false for `mod foo { .. }`. pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { match item.kind { - ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), - _ => false, + ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) => false, + _ => true, } } diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index 370b7eb6c4..8a798777e0 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(rustc_private)] #![deny(rust_2018_idioms)] #![warn(unreachable_pub)] @@ -9,6 +10,16 @@ extern crate lazy_static; #[macro_use] extern crate log; +// N.B. these crates are loaded from the sysroot, so they need extern crate. +extern crate rustc_ast; +extern crate rustc_ast_pretty; +extern crate rustc_data_structures; +extern crate rustc_errors; +extern crate rustc_expand; +extern crate rustc_parse; +extern crate rustc_session; +extern crate rustc_span; + use std::cell::RefCell; use std::collections::HashMap; use std::fmt; @@ -210,13 +221,21 @@ impl FormatReport { if !new_errors.is_empty() { errs.has_formatting_errors = true; } - if errs.has_operational_errors && errs.has_check_errors { + if errs.has_operational_errors && errs.has_check_errors && errs.has_unformatted_code_errors + { return; } for err in new_errors { match err.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => { + ErrorKind::LineOverflow(..) => { + errs.has_operational_errors = true; + } + ErrorKind::TrailingWhitespace => { errs.has_operational_errors = true; + errs.has_unformatted_code_errors = true; + } + ErrorKind::LostComment => { + errs.has_unformatted_code_errors = true; } ErrorKind::BadIssue(_) | ErrorKind::LicenseCheck @@ -294,6 +313,9 @@ fn format_snippet(snippet: &str, config: &Config, is_macro_def: bool) -> Option< config.set().emit_mode(config::EmitMode::Stdout); config.set().verbose(Verbosity::Quiet); config.set().hide_parse_errors(true); + if is_macro_def { + config.set().error_on_unformatted(true); + } let (formatting_error, result) = { let input = Input::Text(snippet.into()); @@ -302,7 +324,8 @@ fn format_snippet(snippet: &str, config: &Config, is_macro_def: bool) -> Option< ( session.errors.has_macro_format_failure || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty() - || result.is_err(), + || result.is_err() + || (is_macro_def && session.has_unformatted_code_errors()), result, ) }; @@ -477,13 +500,18 @@ impl<'b, T: Write + 'b> Session<'b, T> { self.errors.has_diff } + pub fn has_unformatted_code_errors(&self) -> bool { + self.errors.has_unformatted_code_errors + } + pub fn has_no_errors(&self) -> bool { !(self.has_operational_errors() || self.has_parsing_errors() || self.has_formatting_errors() || self.has_check_errors() - || self.has_diff()) - || self.errors.has_macro_format_failure + || self.has_diff() + || self.has_unformatted_code_errors() + || self.errors.has_macro_format_failure) } } diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs index bc55ef6686..ccf8f784c0 100644 --- a/src/tools/rustfmt/src/lists.rs +++ b/src/tools/rustfmt/src/lists.rs @@ -863,7 +863,7 @@ pub(crate) fn struct_lit_shape( }; let shape_width = shape.width.checked_sub(prefix_width + suffix_width); if let Some(w) = shape_width { - let shape_width = cmp::min(w, context.config.width_heuristics().struct_lit_width); + let shape_width = cmp::min(w, context.config.struct_lit_width()); Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) } else { Some((None, v_shape)) diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 1abb1cd9e1..bf4769b34a 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind}; -use rustc_ast::tokenstream::{Cursor, LazyTokenStream, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_parse::parser::{ForceCollect, Parser}; @@ -132,7 +132,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> { ); parse_macro_arg!( Pat, - |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat(None), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None), |x: ptr::P<ast::Pat>| Some(x) ); // `parse_item` returns `Option<ptr::P<ast::Item>>`. @@ -382,7 +382,7 @@ fn rewrite_macro_inner( arg_vec.iter(), shape, mac.span(), - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), if trailing_comma { Some(SeparatorTactic::Always) } else { @@ -1212,7 +1212,7 @@ pub(crate) fn convert_try_mac( kind: ast::ExprKind::Try(parser.parse_expr().ok()?), span: mac.span(), // incorrect span, but shouldn't matter too much attrs: ast::AttrVec::new(), - tokens: Some(LazyTokenStream::new(ts)), + tokens: None, }) } else { None @@ -1259,7 +1259,7 @@ impl MacroParser { TokenTree::Token(..) => return None, TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d), }; - let args = tok.joint(); + let args = TokenStream::new(vec![(tok, Spacing::Joint)]); match self.toks.next()? { TokenTree::Token(Token { kind: TokenKind::FatArrow, diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs index a43aed09ef..f33fedce92 100644 --- a/src/tools/rustfmt/src/matches.rs +++ b/src/tools/rustfmt/src/matches.rs @@ -19,7 +19,7 @@ use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - semicolon_for_expr, trimmed_last_line_width, unicode_str_width, + mk_sp_lo_plus_one, semicolon_for_expr, trimmed_last_line_width, unicode_str_width, }; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. @@ -163,17 +163,14 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { fn collect_beginning_verts( context: &RewriteContext<'_>, arms: &[ast::Arm], - span: Span, ) -> Vec<Option<BytePos>> { - let mut beginning_verts = Vec::with_capacity(arms.len()); - let mut lo = context.snippet_provider.span_after(span, "{"); - for arm in arms { - let hi = arm.pat.span.lo(); - let missing_span = mk_sp(lo, hi); - beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|")); - lo = arm.span().hi(); - } - beginning_verts + arms.iter() + .map(|a| { + context + .snippet_provider + .opt_span_before(mk_sp_lo_plus_one(a.pat.span.lo()), "|") + }) + .collect() } fn rewrite_match_arms( @@ -191,7 +188,7 @@ fn rewrite_match_arms( let is_last_iter = repeat(false) .take(arm_len.saturating_sub(1)) .chain(repeat(true)); - let beginning_verts = collect_beginning_verts(context, arms, span); + let beginning_verts = collect_beginning_verts(context, arms); let items = itemize_list( context.snippet_provider, arms.iter() diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index cadcd30a3d..c3f4406860 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -3,16 +3,17 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use rustc_ast::ast; -use rustc_ast::attr::HasAttrs; use rustc_ast::visit::Visitor; +use rustc_ast::AstLike; use rustc_span::symbol::{self, sym, Symbol}; +use rustc_span::Span; use thiserror::Error; use crate::attr::MetaVisitor; use crate::config::FileName; use crate::items::is_mod_decl; use crate::syntux::parser::{ - Directory, DirectoryOwnership, ModulePathSuccess, Parser, ParserError, + Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError, }; use crate::syntux::session::ParseSess; use crate::utils::contains_skip; @@ -24,36 +25,45 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>; /// Represents module with its inner attributes. #[derive(Debug, Clone)] pub(crate) struct Module<'a> { - ast_mod: Cow<'a, ast::Mod>, + ast_mod_kind: Option<Cow<'a, ast::ModKind>>, + pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>, + attrs: Cow<'a, Vec<ast::Attribute>>, inner_attr: Vec<ast::Attribute>, + pub(crate) span: Span, } impl<'a> Module<'a> { - pub(crate) fn new(ast_mod: Cow<'a, ast::Mod>, attrs: &[ast::Attribute]) -> Self { - let inner_attr = attrs + pub(crate) fn new( + mod_span: Span, + ast_mod_kind: Option<Cow<'a, ast::ModKind>>, + mod_items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>, + mod_attrs: Cow<'a, Vec<ast::Attribute>>, + ) -> Self { + let inner_attr = mod_attrs .iter() .filter(|attr| attr.style == ast::AttrStyle::Inner) .cloned() .collect(); Module { - ast_mod, + items: mod_items, + attrs: mod_attrs, inner_attr, + span: mod_span, + ast_mod_kind, } } } -impl<'a> HasAttrs for Module<'a> { +impl<'a> AstLike for Module<'a> { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; fn attrs(&self) -> &[ast::Attribute] { &self.inner_attr } fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<ast::Attribute>)) { f(&mut self.inner_attr) } -} - -impl<'a> AsRef<ast::Mod> for Module<'a> { - fn as_ref(&self) -> &ast::Mod { - &self.ast_mod + fn tokens_mut(&mut self) -> Option<&mut Option<rustc_ast::tokenstream::LazyTokenStream>> { + unimplemented!() } } @@ -66,8 +76,8 @@ pub(crate) struct ModResolver<'ast, 'sess> { } /// Represents errors while trying to resolve modules. -#[error("failed to resolve mod `{module}`: {kind}")] #[derive(Debug, Error)] +#[error("failed to resolve mod `{module}`: {kind}")] pub struct ModuleResolutionError { pub(crate) module: String, pub(crate) kind: ModuleResolutionErrorKind, @@ -124,12 +134,17 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { // Skip visiting sub modules when the input is from stdin. if self.recursive { - self.visit_mod_from_ast(&krate.module)?; + self.visit_mod_from_ast(&krate.items)?; } self.file_map.insert( root_filename, - Module::new(Cow::Borrowed(&krate.module), &krate.attrs), + Module::new( + krate.span, + None, + Cow::Borrowed(&krate.items), + Cow::Borrowed(&krate.attrs), + ), ); Ok(self.file_map) } @@ -139,10 +154,15 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess); visitor.visit_item(&item); for module_item in visitor.mods() { - if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind { self.visit_sub_mod( &module_item.item, - Module::new(Cow::Owned(sub_mod.clone()), &module_item.item.attrs), + Module::new( + module_item.item.span, + Some(Cow::Owned(sub_mod_kind.clone())), + Cow::Owned(vec![]), + Cow::Owned(vec![]), + ), )?; } } @@ -150,29 +170,53 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit modules defined inside macro calls. - fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), ModuleResolutionError> { - for item in module.items { + fn visit_mod_outside_ast( + &mut self, + items: Vec<rustc_ast::ptr::P<ast::Item>>, + ) -> Result<(), ModuleResolutionError> { + for item in items { if is_cfg_if(&item) { self.visit_cfg_if(Cow::Owned(item.into_inner()))?; continue; } - if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(&item, Module::new(Cow::Owned(sub_mod.clone()), &item.attrs))?; + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + let span = item.span; + self.visit_sub_mod( + &item, + Module::new( + span, + Some(Cow::Owned(sub_mod_kind.clone())), + Cow::Owned(vec![]), + Cow::Owned(vec![]), + ), + )?; } } Ok(()) } /// Visit modules from AST. - fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), ModuleResolutionError> { - for item in &module.items { + fn visit_mod_from_ast( + &mut self, + items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>, + ) -> Result<(), ModuleResolutionError> { + for item in items { if is_cfg_if(item) { self.visit_cfg_if(Cow::Borrowed(item))?; } - if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(item, Module::new(Cow::Borrowed(sub_mod), &item.attrs))?; + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + let span = item.span; + self.visit_sub_mod( + item, + Module::new( + span, + Some(Cow::Borrowed(sub_mod_kind)), + Cow::Owned(vec![]), + Cow::Borrowed(&item.attrs), + ), + )?; } } Ok(()) @@ -273,9 +317,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if let Some(directory) = directory { self.directory = directory; } - match sub_mod.ast_mod { - Cow::Borrowed(sub_mod) => self.visit_mod_from_ast(sub_mod), - Cow::Owned(sub_mod) => self.visit_mod_outside_ast(sub_mod), + match (sub_mod.ast_mod_kind, sub_mod.items) { + (Some(Cow::Borrowed(ast::ModKind::Loaded(items, ast::Inline::No, _))), _) => { + self.visit_mod_from_ast(&items) + } + (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items), + (_, _) => Ok(()), } } @@ -288,19 +335,23 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { ) -> Result<Option<SubModKind<'c, 'ast>>, ModuleResolutionError> { let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, + DirectoryOwnership::UnownedViaBlock => None, }; if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) { if self.parse_sess.is_file_parsed(&path) { return Ok(None); } - return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) - { - Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok(m) => Ok(Some(SubModKind::External( + return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), + Ok((attrs, items, span)) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), ))), Err(ParserError::ParseError) => Err(ModuleResolutionError { module: mod_name.to_string(), @@ -319,72 +370,84 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { match self .parse_sess .default_submod_path(mod_name, relative, &self.directory.path) - .result { Ok(ModulePathSuccess { - path, ownership, .. + file_path, + dir_ownership, + .. }) => { let outside_mods_empty = mods_outside_ast.is_empty(); let should_insert = !mods_outside_ast .iter() - .any(|(outside_path, _, _)| outside_path == &path); - if self.parse_sess.is_file_parsed(&path) { + .any(|(outside_path, _, _)| outside_path == &file_path); + if self.parse_sess.is_file_parsed(&file_path) { if outside_mods_empty { return Ok(None); } else { if should_insert { - mods_outside_ast.push((path, ownership, sub_mod.clone())); + mods_outside_ast.push((file_path, dir_ownership, sub_mod.clone())); } return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); } } - match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) { - Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok(m) if outside_mods_empty => Ok(Some(SubModKind::External( - path, - ownership, - Module::new(Cow::Owned(m.0), &m.1), - ))), - Ok(m) => { + match Parser::parse_file_as_module(self.parse_sess, &file_path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), + Ok((attrs, items, span)) if outside_mods_empty => { + Ok(Some(SubModKind::External( + file_path, + dir_ownership, + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), + ))) + } + Ok((attrs, items, span)) => { mods_outside_ast.push(( - path.clone(), - ownership, - Module::new(Cow::Owned(m.0), &m.1), + file_path.clone(), + dir_ownership, + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), )); if should_insert { - mods_outside_ast.push((path, ownership, sub_mod.clone())); + mods_outside_ast.push((file_path, dir_ownership, sub_mod.clone())); } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } Err(ParserError::ParseError) => Err(ModuleResolutionError { module: mod_name.to_string(), - kind: ModuleResolutionErrorKind::ParseError { file: path }, + kind: ModuleResolutionErrorKind::ParseError { file: file_path }, }), Err(..) if outside_mods_empty => Err(ModuleResolutionError { module: mod_name.to_string(), - kind: ModuleResolutionErrorKind::NotFound { file: path }, + kind: ModuleResolutionErrorKind::NotFound { file: file_path }, }), Err(..) => { if should_insert { - mods_outside_ast.push((path, ownership, sub_mod.clone())); + mods_outside_ast.push((file_path, dir_ownership, sub_mod.clone())); } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } } } - Err(mut e) if !mods_outside_ast.is_empty() => { - e.cancel(); + Err(mod_err) if !mods_outside_ast.is_empty() => { + if let ModError::ParserError(mut e) = mod_err { + e.cancel(); + } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } - Err(mut e) => { - e.cancel(); - Err(ModuleResolutionError { - module: mod_name.to_string(), - kind: ModuleResolutionErrorKind::NotFound { - file: self.directory.path.clone(), - }, - }) - } + Err(_) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { + file: self.directory.path.clone(), + }, + }), } } @@ -437,20 +500,22 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { )); continue; } - let m = match Parser::parse_file_as_module( - self.parse_sess, - &actual_path, - sub_mod.ast_mod.inner, - ) { - Ok((_, ref attrs)) if contains_skip(attrs) => continue, - Ok(m) => m, - Err(..) => continue, - }; + let (attrs, items, span) = + match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => continue, + Ok(m) => m, + Err(..) => continue, + }; result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), )) } result diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index 566f0e3663..d670b0a41e 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -74,7 +74,7 @@ pub(crate) enum OverflowableItem<'a> { MacroArg(&'a MacroArg), NestedMetaItem(&'a ast::NestedMetaItem), SegmentParam(&'a SegmentParam<'a>), - StructField(&'a ast::StructField), + FieldDef(&'a ast::FieldDef), TuplePatField(&'a TuplePatField<'a>), Ty(&'a ast::Ty), } @@ -96,7 +96,7 @@ impl<'a> OverflowableItem<'a> { match self { OverflowableItem::Expr(ast::Expr { attrs, .. }) | OverflowableItem::GenericParam(ast::GenericParam { attrs, .. }) => !attrs.is_empty(), - OverflowableItem::StructField(ast::StructField { attrs, .. }) => !attrs.is_empty(), + OverflowableItem::FieldDef(ast::FieldDef { attrs, .. }) => !attrs.is_empty(), OverflowableItem::MacroArg(MacroArg::Expr(expr)) => !expr.attrs.is_empty(), OverflowableItem::MacroArg(MacroArg::Item(item)) => !item.attrs.is_empty(), _ => false, @@ -113,7 +113,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::MacroArg(macro_arg) => f(*macro_arg), OverflowableItem::NestedMetaItem(nmi) => f(*nmi), OverflowableItem::SegmentParam(sp) => f(*sp), - OverflowableItem::StructField(sf) => f(*sf), + OverflowableItem::FieldDef(sf) => f(*sf), OverflowableItem::TuplePatField(pat) => f(*pat), OverflowableItem::Ty(ty) => f(*ty), } @@ -238,7 +238,7 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types { } } -impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, StructField, Ty); +impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty); impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); pub(crate) fn into_overflowable_list<'a, T>( @@ -318,7 +318,7 @@ pub(crate) fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>> span, lhs, rhs, - context.config.width_heuristics().array_width, + context.config.array_width(), force_separator_tactic, Some(("[", "]")), ) diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 5847bd08d8..6824fc661b 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -1,4 +1,4 @@ -use rustc_ast::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; +use rustc_ast::ast::{self, BindingMode, Pat, PatField, PatKind, RangeEnd, RangeSyntax}; use rustc_ast::ptr; use rustc_span::{BytePos, Span}; @@ -17,7 +17,7 @@ use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::types::{rewrite_path, PathContext}; -use crate::utils::{format_mutability, mk_sp, rewrite_ident}; +use crate::utils::{format_mutability, mk_sp, mk_sp_lo_plus_one, rewrite_ident}; /// Returns `true` if the given pattern is "short". /// A short pattern is defined by the following grammar: @@ -259,7 +259,7 @@ impl Rewrite for Pat { fn rewrite_struct_pat( path: &ast::Path, - fields: &[ast::FieldPat], + fields: &[ast::PatField], ellipsis: bool, span: Span, context: &RewriteContext<'_>, @@ -334,7 +334,7 @@ fn rewrite_struct_pat( Some(format!("{} {{{}}}", path_str, fields_str)) } -impl Rewrite for FieldPat { +impl Rewrite for PatField { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { let hi_pos = if let Some(last) = self.attrs.last() { last.span.hi() @@ -460,7 +460,7 @@ fn rewrite_tuple_pat( let sp = pat_vec[new_item_count - 1].span(); let snippet = context.snippet(sp); let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); - pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp_lo_plus_one(lo)); ( &pat_vec[..new_item_count], mk_sp(span.lo(), lo + BytePos(1)), diff --git a/src/tools/rustfmt/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs index 1d22c25d92..052b0f9c5d 100644 --- a/src/tools/rustfmt/src/source_file.rs +++ b/src/tools/rustfmt/src/source_file.rs @@ -13,7 +13,8 @@ use crate::config::Config; use crate::create_emitter; #[cfg(test)] use crate::formatting::FileRecord; -use std::rc::Rc; + +use rustc_data_structures::sync::Lrc; // Append a newline to the end of each file. pub(crate) fn append_newline(s: &mut String) { @@ -86,11 +87,11 @@ where // source map instead of hitting the file system. This also supports getting // original text for `FileName::Stdin`. let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { - Rc::new(fs::read_to_string(ensure_real_path(filename))?) + Lrc::new(fs::read_to_string(ensure_real_path(filename))?) } else { match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { Some(ori) => ori, - None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), + None => Lrc::new(fs::read_to_string(ensure_real_path(filename))?), } }; diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 1f6d0023e6..7e3786b7cd 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -53,7 +53,7 @@ macro_rules! implement_spanned { // Implement `Spanned` for structs with `attrs` field. implement_spanned!(ast::AssocItem); implement_spanned!(ast::Expr); -implement_spanned!(ast::Field); +implement_spanned!(ast::ExprField); implement_spanned!(ast::ForeignItem); implement_spanned!(ast::Item); implement_spanned!(ast::Local); @@ -143,7 +143,7 @@ impl Spanned for ast::GenericParam { } } -impl Spanned for ast::StructField { +impl Spanned for ast::FieldDef { fn span(&self) -> Span { span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) } diff --git a/src/tools/rustfmt/src/syntux/parser.rs b/src/tools/rustfmt/src/syntux/parser.rs index 6b70d83ceb..0b94749f3c 100644 --- a/src/tools/rustfmt/src/syntux/parser.rs +++ b/src/tools/rustfmt/src/syntux/parser.rs @@ -1,8 +1,8 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; -use rustc_ast::ast; use rustc_ast::token::{DelimToken, TokenKind}; +use rustc_ast::{ast, ptr}; use rustc_errors::Diagnostic; use rustc_parse::{ new_parser_from_file, @@ -12,10 +12,11 @@ use rustc_span::{sym, symbol::kw, Span}; use crate::attr::first_attr_value_str_by_name; use crate::syntux::session::ParseSess; -use crate::{Config, Input}; +use crate::Input; -pub(crate) type DirectoryOwnership = rustc_expand::module::DirectoryOwnership; +pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership; pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess; +pub(crate) type ModError<'a> = rustc_expand::module::ModError<'a>; #[derive(Clone)] pub(crate) struct Directory { @@ -31,10 +32,8 @@ pub(crate) struct Parser<'a> { /// A builder for the `Parser`. #[derive(Default)] pub(crate) struct ParserBuilder<'a> { - config: Option<&'a Config>, sess: Option<&'a ParseSess>, input: Option<Input>, - directory_ownership: Option<DirectoryOwnership>, } impl<'a> ParserBuilder<'a> { @@ -48,19 +47,6 @@ impl<'a> ParserBuilder<'a> { self } - pub(crate) fn config(mut self, config: &'a Config) -> ParserBuilder<'a> { - self.config = Some(config); - self - } - - pub(crate) fn directory_ownership( - mut self, - directory_ownership: Option<DirectoryOwnership>, - ) -> ParserBuilder<'a> { - self.directory_ownership = directory_ownership; - self - } - pub(crate) fn build(self) -> Result<Parser<'a>, ParserError> { let sess = self.sess.ok_or(ParserError::NoParseSess)?; let input = self.input.ok_or(ParserError::NoInput)?; @@ -124,10 +110,10 @@ impl<'a> Parser<'a> { sess: &'a ParseSess, path: &Path, span: Span, - ) -> Result<(ast::Mod, Vec<ast::Attribute>), ParserError> { + ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); - match parser.parse_mod(&TokenKind::Eof, ast::Unsafe::No) { + match parser.parse_mod(&TokenKind::Eof) { Ok(result) => Some(result), Err(mut e) => { sess.emit_or_cancel_diagnostic(&mut e); @@ -157,12 +143,10 @@ impl<'a> Parser<'a> { } pub(crate) fn parse_crate( - config: &'a Config, input: Input, - directory_ownership: Option<DirectoryOwnership>, sess: &'a ParseSess, ) -> Result<ast::Crate, ParserError> { - let krate = Parser::parse_crate_inner(config, input, directory_ownership, sess)?; + let krate = Parser::parse_crate_inner(input, sess)?; if !sess.has_errors() { return Ok(krate); } @@ -175,19 +159,12 @@ impl<'a> Parser<'a> { Err(ParserError::ParseError) } - fn parse_crate_inner( - config: &'a Config, - input: Input, - directory_ownership: Option<DirectoryOwnership>, - sess: &'a ParseSess, - ) -> Result<ast::Crate, ParserError> { - let mut parser = ParserBuilder::default() - .config(config) + fn parse_crate_inner(input: Input, sess: &'a ParseSess) -> Result<ast::Crate, ParserError> { + ParserBuilder::default() .input(input) - .directory_ownership(directory_ownership) .sess(sess) - .build()?; - parser.parse_crate_mod() + .build()? + .parse_crate_mod() } fn parse_crate_mod(&mut self) -> Result<ast::Crate, ParserError> { diff --git a/src/tools/rustfmt/src/syntux/session.rs b/src/tools/rustfmt/src/syntux/session.rs index ef5ad62674..b17a655c1c 100644 --- a/src/tools/rustfmt/src/syntux/session.rs +++ b/src/tools/rustfmt/src/syntux/session.rs @@ -1,6 +1,5 @@ -use std::cell::RefCell; use std::path::Path; -use std::rc::Rc; +use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; @@ -21,8 +20,8 @@ use crate::{Config, ErrorKind, FileName}; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { parse_sess: RawParseSess, - ignore_path_set: Rc<IgnorePathSet>, - can_reset_errors: Rc<RefCell<bool>>, + ignore_path_set: Lrc<IgnorePathSet>, + can_reset_errors: Lrc<AtomicBool>, } /// Emitter which discards every error. @@ -41,17 +40,17 @@ fn silent_emitter() -> Box<dyn Emitter + Send> { /// Emit errors against every files expect ones specified in the `ignore_path_set`. struct SilentOnIgnoredFilesEmitter { - ignore_path_set: Rc<IgnorePathSet>, - source_map: Rc<SourceMap>, + ignore_path_set: Lrc<IgnorePathSet>, + source_map: Lrc<SourceMap>, emitter: Box<dyn Emitter + Send>, has_non_ignorable_parser_errors: bool, - can_reset: Rc<RefCell<bool>>, + can_reset: Lrc<AtomicBool>, } impl SilentOnIgnoredFilesEmitter { fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { self.has_non_ignorable_parser_errors = true; - *self.can_reset.borrow_mut() = false; + self.can_reset.store(false, Ordering::Release); self.emitter.emit_diagnostic(db); } } @@ -73,7 +72,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter { .is_match(&FileName::Real(path.to_path_buf())) { if !self.has_non_ignorable_parser_errors { - *self.can_reset.borrow_mut() = true; + self.can_reset.store(true, Ordering::Release); } return; } @@ -84,9 +83,9 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } fn default_handler( - source_map: Rc<SourceMap>, - ignore_path_set: Rc<IgnorePathSet>, - can_reset: Rc<RefCell<bool>>, + source_map: Lrc<SourceMap>, + ignore_path_set: Lrc<IgnorePathSet>, + can_reset: Lrc<AtomicBool>, hide_parse_errors: bool, ) -> Handler { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); @@ -124,16 +123,16 @@ fn default_handler( impl ParseSess { pub(crate) fn new(config: &Config) -> Result<ParseSess, ErrorKind> { let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { - Ok(ignore_path_set) => Rc::new(ignore_path_set), + Ok(ignore_path_set) => Lrc::new(ignore_path_set), Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), }; - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let can_reset_errors = Rc::new(RefCell::new(false)); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); let handler = default_handler( - Rc::clone(&source_map), - Rc::clone(&ignore_path_set), - Rc::clone(&can_reset_errors), + Lrc::clone(&source_map), + Lrc::clone(&ignore_path_set), + Lrc::clone(&can_reset_errors), config.hide_parse_errors(), ); let parse_sess = RawParseSess::with_span_handler(handler, source_map); @@ -150,14 +149,8 @@ impl ParseSess { id: symbol::Ident, relative: Option<symbol::Ident>, dir_path: &Path, - ) -> rustc_expand::module::ModulePath<'_> { - rustc_expand::module::default_submod_path( - &self.parse_sess, - id, - rustc_span::DUMMY_SP, - relative, - dir_path, - ) + ) -> Result<rustc_expand::module::ModulePathSuccess, rustc_expand::module::ModError<'_>> { + rustc_expand::module::default_submod_path(&self.parse_sess, id, relative, dir_path) } pub(crate) fn is_file_parsed(&self, path: &Path) -> bool { @@ -210,11 +203,11 @@ impl ParseSess { SnippetProvider::new( source_file.start_pos, source_file.end_pos, - Rc::clone(source_file.src.as_ref().unwrap()), + Lrc::clone(source_file.src.as_ref().unwrap()), ) } - pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option<Rc<String>> { + pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option<Lrc<String>> { self.parse_sess .source_map() .get_source_file(&file_name.into()) @@ -242,7 +235,7 @@ impl ParseSess { } pub(super) fn can_reset_errors(&self) -> bool { - *self.can_reset_errors.borrow() + self.can_reset_errors.load(Ordering::Acquire) } pub(super) fn has_errors(&self) -> bool { @@ -293,9 +286,10 @@ mod tests { use crate::utils::mk_sp; use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP}; use std::path::PathBuf; + use std::sync::atomic::AtomicU32; struct TestEmitter { - num_emitted_errors: Rc<RefCell<u32>>, + num_emitted_errors: Lrc<AtomicU32>, } impl Emitter for TestEmitter { @@ -303,7 +297,7 @@ mod tests { None } fn emit_diagnostic(&mut self, _db: &Diagnostic) { - *self.num_emitted_errors.borrow_mut() += 1; + self.num_emitted_errors.fetch_add(1, Ordering::Release); } } @@ -320,16 +314,17 @@ mod tests { } fn build_emitter( - num_emitted_errors: Rc<RefCell<u32>>, - can_reset: Rc<RefCell<bool>>, - source_map: Option<Rc<SourceMap>>, + num_emitted_errors: Lrc<AtomicU32>, + can_reset: Lrc<AtomicBool>, + source_map: Option<Lrc<SourceMap>>, ignore_list: Option<IgnoreList>, ) -> SilentOnIgnoredFilesEmitter { let emitter_writer = TestEmitter { num_emitted_errors }; let source_map = - source_map.unwrap_or_else(|| Rc::new(SourceMap::new(FilePathMapping::empty()))); - let ignore_path_set = - Rc::new(IgnorePathSet::from_ignore_list(&ignore_list.unwrap_or_default()).unwrap()); + source_map.unwrap_or_else(|| Lrc::new(SourceMap::new(FilePathMapping::empty()))); + let ignore_path_set = Lrc::new( + IgnorePathSet::from_ignore_list(&ignore_list.unwrap_or_default()).unwrap(), + ); SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, source_map, @@ -345,10 +340,10 @@ mod tests { #[test] fn handles_fatal_parse_error_in_ignored_file() { - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); source_map.new_source_file( @@ -356,16 +351,16 @@ mod tests { source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), Some(ignore_list), ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); emitter.emit_diagnostic(&fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 1); - assert_eq!(*can_reset_errors.borrow(), false); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); + assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } #[test] @@ -373,26 +368,26 @@ mod tests { if !is_nightly_channel!() { return; } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file( SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), Some(ignore_list), ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); emitter.emit_diagnostic(&non_fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 0); - assert_eq!(*can_reset_errors.borrow(), true); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); + assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } #[test] @@ -400,25 +395,25 @@ mod tests { if !is_nightly_channel!() { return; } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file( SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), None, ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); emitter.emit_diagnostic(&non_fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 1); - assert_eq!(*can_reset_errors.borrow(), false); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); + assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } #[test] @@ -426,9 +421,9 @@ mod tests { if !is_nightly_channel!() { return; } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); let bar_source = String::from(r#"pub fn bar() { 1x; }"#); let foo_source = String::from(r#"pub fn foo() { 1x; }"#); @@ -447,9 +442,9 @@ mod tests { fatal_source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), Some(ignore_list), ); let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); @@ -460,8 +455,8 @@ mod tests { emitter.emit_diagnostic(&bar_diagnostic); emitter.emit_diagnostic(&foo_diagnostic); emitter.emit_diagnostic(&fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 2); - assert_eq!(*can_reset_errors.borrow(), false); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2); + assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } } } diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs index 142de28f33..ce56a223f2 100644 --- a/src/tools/rustfmt/src/test/mod.rs +++ b/src/tools/rustfmt/src/test/mod.rs @@ -133,10 +133,8 @@ fn verify_config_used(path: &Path, config_name: &str) { .map(Result::unwrap) .take_while(|l| l.starts_with("//")) .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), - format!( - "config option file {} does not contain expected config name", - path.display() - ) + "config option file {} does not contain expected config name", + path.display() ); } } @@ -884,6 +882,7 @@ fn rustfmt() -> PathBuf { me.push("rustfmt"); assert!( me.is_file() || me.with_extension("exe").is_file(), + "{}", if cfg!(release) { "no rustfmt bin, try running `cargo build --release` before testing" } else { diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index a3d0ed050e..d3c349fb70 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -360,6 +360,10 @@ pub(crate) fn mk_sp(lo: BytePos, hi: BytePos) -> Span { Span::new(lo, hi, SyntaxContext::root()) } +pub(crate) fn mk_sp_lo_plus_one(lo: BytePos) -> Span { + Span::new(lo, lo + BytePos(1), SyntaxContext::root()) +} + // Returns `true` if the given span does not intersect with file lines. macro_rules! out_of_file_lines_range { ($self:ident, $span:expr) => { diff --git a/src/tools/rustfmt/src/vertical.rs b/src/tools/rustfmt/src/vertical.rs index 95d1d5c2d7..c4208848c6 100644 --- a/src/tools/rustfmt/src/vertical.rs +++ b/src/tools/rustfmt/src/vertical.rs @@ -33,7 +33,7 @@ pub(crate) trait AlignedItem { ) -> Option<String>; } -impl AlignedItem for ast::StructField { +impl AlignedItem for ast::FieldDef { fn skip(&self) -> bool { contains_skip(&self.attrs) } @@ -72,7 +72,7 @@ impl AlignedItem for ast::StructField { } } -impl AlignedItem for ast::Field { +impl AlignedItem for ast::ExprField { fn skip(&self) -> bool { contains_skip(&self.attrs) } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 34e8536b7e..079568630c 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -1,7 +1,8 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_ast::{ast, attr::HasAttrs, token::DelimToken, visit}; +use rustc_ast::{ast, token::DelimToken, visit, AstLike}; +use rustc_data_structures::sync::Lrc; use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; use crate::attr::*; @@ -32,7 +33,7 @@ use crate::{ErrorKind, FormatReport, FormattingError}; /// Creates a string slice corresponding to the specified span. pub(crate) struct SnippetProvider { /// A pointer to the content of the file we are formatting. - big_snippet: Rc<String>, + big_snippet: Lrc<String>, /// A position of the start of `big_snippet`, used as an offset. start_pos: usize, /// A end position of the file that this snippet lives. @@ -46,7 +47,7 @@ impl SnippetProvider { Some(&self.big_snippet[start_index..end_index]) } - pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: Rc<String>) -> Self { + pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: Lrc<String>) -> Self { let start_pos = start_pos.to_usize(); let end_pos = end_pos.to_usize(); SnippetProvider { @@ -524,10 +525,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_enum(item.ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); } - ast::ItemKind::Mod(ref module) => { - let is_inline = !is_mod_decl(item); + ast::ItemKind::Mod(unsafety, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); + self.format_mod(mod_kind, unsafety, &item.vis, item.span, item.ident, attrs); } ast::ItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); @@ -921,8 +921,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { !is_skip_attr(segments) } - fn walk_mod_items(&mut self, m: &ast::Mod) { - self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); + fn walk_mod_items(&mut self, items: &Vec<rustc_ast::ptr::P<ast::Item>>) { + self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items)); } fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) { @@ -974,22 +974,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn format_mod( &mut self, - m: &ast::Mod, + mod_kind: &ast::ModKind, + unsafety: ast::Unsafe, vis: &ast::Visibility, s: Span, ident: symbol::Ident, attrs: &[ast::Attribute], - is_internal: bool, ) { let vis_str = utils::format_visibility(&self.get_context(), vis); self.push_str(&*vis_str); - self.push_str(format_unsafety(m.unsafety)); + self.push_str(format_unsafety(unsafety)); self.push_str("mod "); // Calling `to_owned()` to work around borrow checker. let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); self.push_str(&ident_str); - if is_internal { + if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, inner_span) = mod_kind { match self.config.brace_style() { BraceStyle::AlwaysNextLine => { let indent_str = self.block_indent.to_string_with_newline(self.config); @@ -1001,7 +1001,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Hackery to account for the closing }. let mod_lo = self.snippet_provider.span_after(source!(self, s), "{"); let body_snippet = - self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); + self.snippet(mk_sp(mod_lo, source!(self, inner_span).hi() - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { self.push_str("}"); @@ -1009,11 +1009,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = mod_lo; self.block_indent = self.block_indent.block_indent(self.config); self.visit_attrs(attrs, ast::AttrStyle::Inner); - self.walk_mod_items(m); - let missing_span = self.next_span(m.inner.hi() - BytePos(1)); + self.walk_mod_items(items); + let missing_span = self.next_span(inner_span.hi() - BytePos(1)); self.close_block(missing_span, false); } - self.last_pos = source!(self, m.inner).hi(); + self.last_pos = source!(self, inner_span).hi(); } else { self.push_str(";"); self.last_pos = source!(self, s).hi(); @@ -1023,9 +1023,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) { self.block_indent = Indent::empty(); if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) { - self.push_skipped_with_span(m.attrs(), m.as_ref().inner, m.as_ref().inner); + self.push_skipped_with_span(m.attrs(), m.span, m.span); } else { - self.walk_mod_items(m.as_ref()); + self.walk_mod_items(&m.items); self.format_missing_with_indent(end_pos); } } diff --git a/src/tools/rustfmt/tests/source/configs/chain_width/always.rs b/src/tools/rustfmt/tests/source/configs/chain_width/always.rs new file mode 100644 index 0000000000..2d16d66aec --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/chain_width/always.rs @@ -0,0 +1,23 @@ +// rustfmt-chain_width: 1 +// setting an unachievable chain_width to always get chains +// on separate lines + +struct Fluent {} + +impl Fluent { + fn blorp(&self) -> &Self { + self + } +} + +fn main() { + let test = Fluent {}; + + // should be left alone + test.blorp(); + + // should be wrapped + test.blorp().blorp(); + test.blorp().blorp().blorp(); + test.blorp().blorp().blorp().blorp(); +} diff --git a/src/tools/rustfmt/tests/source/configs/chain_width/small.rs b/src/tools/rustfmt/tests/source/configs/chain_width/small.rs new file mode 100644 index 0000000000..26f9354537 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/chain_width/small.rs @@ -0,0 +1,23 @@ +// rustfmt-chain_width: 40 + +struct Fluent {} + +impl Fluent { + fn blorp(&self) -> &Self { + self + } +} + +fn main() { + let test = Fluent {}; + + // should not be wrapped + test.blorp(); + test.blorp().blorp(); + test.blorp().blorp().blorp(); + test.blorp().blorp().blorp().blorp(); + + // should be wrapped + test.blorp().blorp().blorp().blorp().blorp(); + test.blorp().blorp().blorp().blorp().blorp().blorp(); +} diff --git a/src/tools/rustfmt/tests/source/configs/chain_width/tiny.rs b/src/tools/rustfmt/tests/source/configs/chain_width/tiny.rs new file mode 100644 index 0000000000..fffc81dd5d --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/chain_width/tiny.rs @@ -0,0 +1,21 @@ +// rustfmt-chain_width: 20 + +struct Fluent {} + +impl Fluent { + fn blorp(&self) -> &Self { + self + } +} + +fn main() { + let test = Fluent {}; + + // should not be wrapped + test.blorp(); + test.blorp().blorp(); + + // should be wrapped + test.blorp().blorp().blorp(); + test.blorp().blorp().blorp().blorp(); +} diff --git a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs new file mode 100644 index 0000000000..68bc40271a --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs @@ -0,0 +1,25 @@ +// rustfmt-use_small_heuristics: Default + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} diff --git a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs new file mode 100644 index 0000000000..f76392d240 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs @@ -0,0 +1,25 @@ +// rustfmt-use_small_heuristics: Off + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} diff --git a/src/tools/rustfmt/tests/source/issue-4312.rs b/src/tools/rustfmt/tests/source/issue-4312.rs new file mode 100644 index 0000000000..b36b0efdb9 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4312.rs @@ -0,0 +1,22 @@ +// issue 4312 +fn main() { + /* " */ + println!("Hello, world!"); + /* abc " */ + println!("Hello, world!"); + /* " abc */ + println!("Hello, world!"); + let y = 4; + let x = match 1 + y == 3 { + True => 3, + False => 4, + /* " unreachable */ + }; +} + +// issue 4806 +enum X { + A, + B, + /*"*/ +} diff --git a/src/tools/rustfmt/tests/source/issue-4427.rs b/src/tools/rustfmt/tests/source/issue-4427.rs new file mode 100644 index 0000000000..e14e039b98 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4427.rs @@ -0,0 +1,31 @@ +const A: usize = + // Some constant + 2; + +const B: usize = +/* constant */ +3; + +const C : usize + = /* foo */5; + +const D: usize = // baz +/* Some constant */ + /* ba */ + { 3 + // foo + }; +const E: usize= /* foo */5; +const F: usize = +{ + 7 + }; +const G: usize = /* foooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000xx00 */ 5; + const H: usize = /* asdfasdf */ match G > 1 { + true => 1, + false => 3, + }; + + pub static FOO_BAR: Vec<u8> = //f + { + vec![]}; diff --git a/src/tools/rustfmt/tests/source/issue-4603.rs b/src/tools/rustfmt/tests/source/issue-4603.rs new file mode 100644 index 0000000000..ba0803e0ec --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4603.rs @@ -0,0 +1,47 @@ +// Formatting when original macro snippet is used + +// Original issue #4603 code +#![feature(or_patterns)] +macro_rules! t_or_f { + () => { + (true // some comment + | false) + }; +} + +// Other test cases variations +macro_rules! RULES { + () => { + ( + xxxxxxx // COMMENT + | yyyyyyy + ) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; +} + +fn main() { + macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; + } +} + +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ | yyyyyyy) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ + | yyyyyyy) + }; +} diff --git a/src/tools/rustfmt/tests/source/match.rs b/src/tools/rustfmt/tests/source/match.rs index f54082f92e..da20517203 100644 --- a/src/tools/rustfmt/tests/source/match.rs +++ b/src/tools/rustfmt/tests/source/match.rs @@ -410,7 +410,7 @@ fn match_with_near_max_width() { fn match_with_trailing_spaces() { match x { - #![allow(simple_match)] + Some(..) => 0, None => 1, } diff --git a/src/tools/rustfmt/tests/target/configs/chain_width/always.rs b/src/tools/rustfmt/tests/target/configs/chain_width/always.rs new file mode 100644 index 0000000000..b16d25251f --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/chain_width/always.rs @@ -0,0 +1,29 @@ +// rustfmt-chain_width: 1 +// setting an unachievable chain_width to always get chains +// on separate lines + +struct Fluent {} + +impl Fluent { + fn blorp(&self) -> &Self { + self + } +} + +fn main() { + let test = Fluent {}; + + // should be left alone + test.blorp(); + + // should be wrapped + test.blorp() + .blorp(); + test.blorp() + .blorp() + .blorp(); + test.blorp() + .blorp() + .blorp() + .blorp(); +} diff --git a/src/tools/rustfmt/tests/target/configs/chain_width/small.rs b/src/tools/rustfmt/tests/target/configs/chain_width/small.rs new file mode 100644 index 0000000000..2f2f72777f --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/chain_width/small.rs @@ -0,0 +1,32 @@ +// rustfmt-chain_width: 40 + +struct Fluent {} + +impl Fluent { + fn blorp(&self) -> &Self { + self + } +} + +fn main() { + let test = Fluent {}; + + // should not be wrapped + test.blorp(); + test.blorp().blorp(); + test.blorp().blorp().blorp(); + test.blorp().blorp().blorp().blorp(); + + // should be wrapped + test.blorp() + .blorp() + .blorp() + .blorp() + .blorp(); + test.blorp() + .blorp() + .blorp() + .blorp() + .blorp() + .blorp(); +} diff --git a/src/tools/rustfmt/tests/target/configs/chain_width/tiny.rs b/src/tools/rustfmt/tests/target/configs/chain_width/tiny.rs new file mode 100644 index 0000000000..960d245f8a --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/chain_width/tiny.rs @@ -0,0 +1,26 @@ +// rustfmt-chain_width: 20 + +struct Fluent {} + +impl Fluent { + fn blorp(&self) -> &Self { + self + } +} + +fn main() { + let test = Fluent {}; + + // should not be wrapped + test.blorp(); + test.blorp().blorp(); + + // should be wrapped + test.blorp() + .blorp() + .blorp(); + test.blorp() + .blorp() + .blorp() + .blorp(); +} diff --git a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs new file mode 100644 index 0000000000..d67bd9aafa --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs @@ -0,0 +1,26 @@ +// rustfmt-use_small_heuristics: Default + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { amet: Consectetur, adipiscing: Elit }, +} + +fn main() { + lorem( + "lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + ); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { dolor } else { sit }; +} diff --git a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs new file mode 100644 index 0000000000..f76392d240 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs @@ -0,0 +1,25 @@ +// rustfmt-use_small_heuristics: Off + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-3592.rs b/src/tools/rustfmt/tests/target/issue-3592.rs deleted file mode 100644 index 3142268e08..0000000000 --- a/src/tools/rustfmt/tests/target/issue-3592.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn r() -> (Biz, ()) { - ( - Biz { - #![cfg(unix)] - field: 9 - }, - Biz { - #![cfg(not(unix))] - field: 200 - }, - (), - ) -} diff --git a/src/tools/rustfmt/tests/target/issue-4312.rs b/src/tools/rustfmt/tests/target/issue-4312.rs new file mode 100644 index 0000000000..b36b0efdb9 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4312.rs @@ -0,0 +1,22 @@ +// issue 4312 +fn main() { + /* " */ + println!("Hello, world!"); + /* abc " */ + println!("Hello, world!"); + /* " abc */ + println!("Hello, world!"); + let y = 4; + let x = match 1 + y == 3 { + True => 3, + False => 4, + /* " unreachable */ + }; +} + +// issue 4806 +enum X { + A, + B, + /*"*/ +} diff --git a/src/tools/rustfmt/tests/target/issue-4427.rs b/src/tools/rustfmt/tests/target/issue-4427.rs new file mode 100644 index 0000000000..c8a37ead8c --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4427.rs @@ -0,0 +1,30 @@ +const A: usize = + // Some constant + 2; + +const B: usize = + /* constant */ + 3; + +const C: usize = /* foo */ 5; + +const D: usize = // baz + /* Some constant */ + /* ba */ + { + 3 + // foo + }; +const E: usize = /* foo */ 5; +const F: usize = { 7 }; +const G: usize = + /* foooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000xx00 */ + 5; +const H: usize = /* asdfasdf */ + match G > 1 { + true => 1, + false => 3, + }; + +pub static FOO_BAR: Vec<u8> = //f + { vec![] }; diff --git a/src/tools/rustfmt/tests/target/issue-4603.rs b/src/tools/rustfmt/tests/target/issue-4603.rs new file mode 100644 index 0000000000..e8c368a247 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4603.rs @@ -0,0 +1,47 @@ +// Formatting when original macro snippet is used + +// Original issue #4603 code +#![feature(or_patterns)] +macro_rules! t_or_f { + () => { + (true // some comment + | false) + }; +} + +// Other test cases variations +macro_rules! RULES { + () => { + ( + xxxxxxx // COMMENT + | yyyyyyy + ) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; +} + +fn main() { + macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; + } +} + +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ | yyyyyyy) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ + | yyyyyyy) + }; +} diff --git a/src/tools/rustfmt/tests/target/issue_4049.rs b/src/tools/rustfmt/tests/target/issue_4049.rs new file mode 100644 index 0000000000..fe025a0f64 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4049.rs @@ -0,0 +1,26 @@ +// rustfmt-max_width: 110 +// rustfmt-use_small_heuristics: Max +// rustfmt-hard_tabs: true +// rustfmt-use_field_init_shorthand: true +// rustfmt-overflow_delimited_expr: true + +// https://github.com/rust-lang/rustfmt/issues/4049 +fn foo() { + { + { + if let Some(MpcEv::PlayDrum(pitch, vel)) = + // self.mpc.handle_input(e, /*btn_ctrl_down,*/ tx_launch_to_daw, state_view) + self.mpc.handle_input(e, &mut MyBorrowedState { tx_launch_to_daw, state_view }) + { + println!("bar"); + } + + if let Some(e) = + // self.note_input.handle_input(e, /*btn_ctrl_down,*/ tx_launch_to_daw, state_view) + self.note_input.handle_input(e, &mut MyBorrowedState { tx_launch_to_daw, state_view }) + { + println!("baz"); + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/match.rs b/src/tools/rustfmt/tests/target/match.rs index 123c4c55f6..e2c522bea1 100644 --- a/src/tools/rustfmt/tests/target/match.rs +++ b/src/tools/rustfmt/tests/target/match.rs @@ -441,7 +441,6 @@ fn match_with_near_max_width() { fn match_with_trailing_spaces() { match x { - #![allow(simple_match)] Some(..) => 0, None => 1, } diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 777d7be8fd..58c32993cb 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -10,6 +10,7 @@ cargo_metadata = "0.11" regex = "1" lazy_static = "1" walkdir = "2" +crossbeam-utils = "0.8.0" [[bin]] name = "rust-tidy" diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 62cfa85577..1d5ec5c31c 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -5,91 +5,126 @@ //! huge amount of bloat to the Git history, so it's good to just ensure we //! don't do that again. -use std::path::Path; +pub use os_impl::*; // All files are executable on Windows, so just check on Unix. #[cfg(windows)] -pub fn check(_path: &Path, _output: &Path, _bad: &mut bool) {} +mod os_impl { + use std::path::Path; + + pub fn check_filesystem_support(_sources: &[&Path], _output: &Path) -> bool { + return false; + } + + pub fn check(_path: &Path, _bad: &mut bool) {} +} #[cfg(unix)] -pub fn check(path: &Path, output: &Path, bad: &mut bool) { +mod os_impl { use std::fs; use std::os::unix::prelude::*; + use std::path::Path; use std::process::{Command, Stdio}; + enum FilesystemSupport { + Supported, + Unsupported, + ReadOnlyFs, + } + + use FilesystemSupport::*; + fn is_executable(path: &Path) -> std::io::Result<bool> { Ok(path.metadata()?.mode() & 0o111 != 0) } - // We want to avoid false positives on filesystems that do not support the - // executable bit. This occurs on some versions of Window's linux subsystem, - // for example. - // - // We try to create the temporary file first in the src directory, which is - // the preferred location as it's most likely to be on the same filesystem, - // and then in the output (`build`) directory if that fails. Sometimes we - // see the source directory mounted as read-only which means we can't - // readily create a file there to test. - // - // See #36706 and #74753 for context. - let mut temp_path = path.join("tidy-test-file"); - match fs::File::create(&temp_path).or_else(|_| { - temp_path = output.join("tidy-test-file"); - fs::File::create(&temp_path) - }) { - Ok(file) => { - let exec = is_executable(&temp_path).unwrap_or(false); - std::mem::drop(file); - std::fs::remove_file(&temp_path).expect("Deleted temp file"); - if exec { - // If the file is executable, then we assume that this - // filesystem does not track executability, so skip this check. - return; - } + pub fn check_filesystem_support(sources: &[&Path], output: &Path) -> bool { + // We want to avoid false positives on filesystems that do not support the + // executable bit. This occurs on some versions of Window's linux subsystem, + // for example. + // + // We try to create the temporary file first in the src directory, which is + // the preferred location as it's most likely to be on the same filesystem, + // and then in the output (`build`) directory if that fails. Sometimes we + // see the source directory mounted as read-only which means we can't + // readily create a file there to test. + // + // See #36706 and #74753 for context. + + fn check_dir(dir: &Path) -> FilesystemSupport { + let path = dir.join("tidy-test-file"); + match fs::File::create(&path) { + Ok(file) => { + let exec = is_executable(&path).unwrap_or(false); + std::mem::drop(file); + std::fs::remove_file(&path).expect("Deleted temp file"); + // If the file is executable, then we assume that this + // filesystem does not track executability, so skip this check. + return if exec { Unsupported } else { Supported }; + } + Err(e) => { + // If the directory is read-only or we otherwise don't have rights, + // just don't run this check. + // + // 30 is the "Read-only filesystem" code at least in one CI + // environment. + if e.raw_os_error() == Some(30) { + eprintln!("tidy: Skipping binary file check, read-only filesystem"); + return ReadOnlyFs; + } + + panic!("unable to create temporary file `{:?}`: {:?}", path, e); + } + }; } - Err(e) => { - // If the directory is read-only or we otherwise don't have rights, - // just don't run this check. - // - // 30 is the "Read-only filesystem" code at least in one CI - // environment. - if e.raw_os_error() == Some(30) { - eprintln!("tidy: Skipping binary file check, read-only filesystem"); - return; - } - panic!("unable to create temporary file `{:?}`: {:?}", temp_path, e); + for &source_dir in sources { + match check_dir(source_dir) { + Unsupported => return false, + ReadOnlyFs => { + return match check_dir(output) { + Supported => true, + _ => false, + }; + } + _ => {} + } } + + return true; } - super::walk_no_read( - path, - &mut |path| super::filter_dirs(path) || path.ends_with("src/etc"), - &mut |entry| { - let file = entry.path(); - let filename = file.file_name().unwrap().to_string_lossy(); - let extensions = [".py", ".sh"]; - if extensions.iter().any(|e| filename.ends_with(e)) { - return; - } + #[cfg(unix)] + pub fn check(path: &Path, bad: &mut bool) { + crate::walk_no_read( + path, + &mut |path| crate::filter_dirs(path) || path.ends_with("src/etc"), + &mut |entry| { + let file = entry.path(); + let filename = file.file_name().unwrap().to_string_lossy(); + let extensions = [".py", ".sh"]; + if extensions.iter().any(|e| filename.ends_with(e)) { + return; + } - if t!(is_executable(&file), file) { - let rel_path = file.strip_prefix(path).unwrap(); - let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/"); - let output = Command::new("git") - .arg("ls-files") - .arg(&git_friendly_path) - .current_dir(path) - .stderr(Stdio::null()) - .output() - .unwrap_or_else(|e| { - panic!("could not run git ls-files: {}", e); - }); - let path_bytes = rel_path.as_os_str().as_bytes(); - if output.status.success() && output.stdout.starts_with(path_bytes) { - tidy_error!(bad, "binary checked into source: {}", file.display()); + if t!(is_executable(&file), file) { + let rel_path = file.strip_prefix(path).unwrap(); + let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/"); + let output = Command::new("git") + .arg("ls-files") + .arg(&git_friendly_path) + .current_dir(path) + .stderr(Stdio::null()) + .output() + .unwrap_or_else(|e| { + panic!("could not run git ls-files: {}", e); + }); + let path_bytes = rel_path.as_os_str().as_bytes(); + if output.status.success() && output.stdout.starts_with(path_bytes) { + tidy_error!(bad, "binary checked into source: {}", file.display()); + } } - } - }, - ) + }, + ) + } } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 96a0203863..b604b39967 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -32,15 +32,12 @@ const EXCEPTIONS: &[(&str, &str)] = &[ ("fuchsia-zircon", "BSD-3-Clause"), // rustdoc, rustc, cargo (jobserver & tempdir) ("colored", "MPL-2.0"), // rustfmt ("ordslice", "Apache-2.0"), // rls - ("cloudabi", "BSD-2-Clause"), // (rls -> crossbeam-channel 0.2 -> rand 0.5) ("ryu", "Apache-2.0 OR BSL-1.0"), // rls/cargo/... (because of serde) ("bytesize", "Apache-2.0"), // cargo ("im-rc", "MPL-2.0+"), // cargo - ("constant_time_eq", "CC0-1.0"), // rustfmt ("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 - ("arrayref", "BSD-2-Clause"), // cargo-miri/directories/.../rust-argon2 (redox) ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("snap", "BSD-3-Clause"), // rustc // FIXME: this dependency violates the documentation comment above: @@ -76,7 +73,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "cfg-if", "chalk-derive", "chalk-ir", - "cloudabi", "cmake", "compiler_builtins", "cpuid-bool", @@ -193,6 +189,8 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "winapi-i686-pc-windows-gnu", "winapi-util", "winapi-x86_64-pc-windows-gnu", + // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well. + "yansi-term", ]; /// Dependency checks. diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index a7199fdfce..55f824b63f 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -48,6 +48,8 @@ fn check_error_code_explanation( } fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool { + let mut ignore_found = false; + for line in f.lines() { let s = line.trim(); if s.starts_with("#### Note: this error code is no longer emitted by the compiler") { @@ -56,13 +58,13 @@ fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool { if s.starts_with("```") { if s.contains("compile_fail") && s.contains(err_code) { return true; - } else if s.contains('(') { + } else if s.contains("ignore") { // It's very likely that we can't actually make it fail compilation... - return true; + ignore_found = true; } } } - false + ignore_found } macro_rules! some_or_continue { @@ -164,18 +166,32 @@ fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, boo } } -pub fn check(path: &Path, bad: &mut bool) { +pub fn check(paths: &[&Path], bad: &mut bool) { let mut errors = Vec::new(); + let mut found_explanations = 0; + let mut found_tests = 0; println!("Checking which error codes lack tests..."); let mut error_codes: HashMap<String, bool> = HashMap::new(); - super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| { - let file_name = entry.file_name(); - if file_name == "error_codes.rs" { - extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors); - } else if entry.path().extension() == Some(OsStr::new("stderr")) { - extract_error_codes_from_tests(contents, &mut error_codes); - } - }); + for path in paths { + super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| { + let file_name = entry.file_name(); + if file_name == "error_codes.rs" { + extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors); + found_explanations += 1; + } else if entry.path().extension() == Some(OsStr::new("stderr")) { + extract_error_codes_from_tests(contents, &mut error_codes); + found_tests += 1; + } + }); + } + if found_explanations == 0 { + eprintln!("No error code explanation was tested!"); + *bad = true; + } + if found_tests == 0 { + eprintln!("No error code was found in compilation errors!"); + *bad = true; + } if errors.is_empty() { println!("Found {} error codes", error_codes.len()); diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index cb84fd8be6..b14b5aeb57 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -423,6 +423,15 @@ fn map_lib_features( continue; }}; } + + lazy_static::lazy_static! { + static ref COMMENT_LINE: Regex = Regex::new(r"^\s*//").unwrap(); + } + // exclude commented out lines + if COMMENT_LINE.is_match(line) { + continue; + } + if let Some((ref name, ref mut f)) = becoming_feature { if f.tracking_issue.is_none() { f.tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none); diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 11d36751f6..fcb27dae9e 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -3,8 +3,6 @@ //! This library contains the tidy lints and exposes it //! to be used by tools. -#![cfg_attr(bootstrap, feature(str_split_once))] - use std::fs::File; use std::io::Read; use walkdir::{DirEntry, WalkDir}; @@ -55,6 +53,7 @@ pub mod unstable_book; fn filter_dirs(path: &Path) -> bool { let skip = [ + "tidy-test-file", "compiler/rustc_codegen_cranelift", "src/llvm-project", "library/backtrace", diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 2ac96e404a..10356a2fdc 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -6,15 +6,23 @@ use tidy::*; +use crossbeam_utils::thread::{scope, ScopedJoinHandle}; +use std::collections::VecDeque; use std::env; +use std::num::NonZeroUsize; use std::path::PathBuf; use std::process; +use std::str::FromStr; +use std::sync::atomic::{AtomicBool, Ordering}; fn main() { let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into(); let output_directory: PathBuf = env::args_os().nth(3).expect("need path to output directory").into(); + let concurrency: NonZeroUsize = + FromStr::from_str(&env::args().nth(4).expect("need concurrency")) + .expect("concurrency must be a number"); let src_path = root_path.join("src"); let library_path = root_path.join("library"); @@ -22,45 +30,84 @@ fn main() { let args: Vec<String> = env::args().skip(1).collect(); - let mut bad = false; let verbose = args.iter().any(|s| *s == "--verbose"); - // Checks over tests. - debug_artifacts::check(&src_path, &mut bad); - ui_tests::check(&src_path, &mut bad); - - // Checks that only make sense for the compiler. - errors::check(&compiler_path, &mut bad); - error_codes_check::check(&src_path, &mut bad); - - // Checks that only make sense for the std libs. - pal::check(&library_path, &mut bad); - - // Checks that need to be done for both the compiler and std libraries. - unit_tests::check(&src_path, &mut bad); - unit_tests::check(&compiler_path, &mut bad); - unit_tests::check(&library_path, &mut bad); - - bins::check(&src_path, &output_directory, &mut bad); - bins::check(&compiler_path, &output_directory, &mut bad); - bins::check(&library_path, &output_directory, &mut bad); - - style::check(&src_path, &mut bad); - style::check(&compiler_path, &mut bad); - style::check(&library_path, &mut bad); - - edition::check(&src_path, &mut bad); - edition::check(&compiler_path, &mut bad); - edition::check(&library_path, &mut bad); - - let collected = features::check(&src_path, &compiler_path, &library_path, &mut bad, verbose); - unstable_book::check(&src_path, collected, &mut bad); - - // Checks that are done on the cargo workspace. - deps::check(&root_path, &cargo, &mut bad); - extdeps::check(&root_path, &mut bad); - - if bad { + let bad = std::sync::Arc::new(AtomicBool::new(false)); + + scope(|s| { + let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> = + VecDeque::with_capacity(concurrency.get()); + + macro_rules! check { + ($p:ident $(, $args:expr)* ) => { + while handles.len() >= concurrency.get() { + handles.pop_front().unwrap().join().unwrap(); + } + + let handle = s.spawn(|_| { + let mut flag = false; + $p::check($($args),* , &mut flag); + if (flag) { + bad.store(true, Ordering::Relaxed); + } + }); + handles.push_back(handle); + } + } + + // Checks that are done on the cargo workspace. + check!(deps, &root_path, &cargo); + check!(extdeps, &root_path); + + // Checks over tests. + check!(debug_artifacts, &src_path); + check!(ui_tests, &src_path); + + // Checks that only make sense for the compiler. + check!(errors, &compiler_path); + check!(error_codes_check, &[&src_path, &compiler_path]); + + // Checks that only make sense for the std libs. + check!(pal, &library_path); + + // Checks that need to be done for both the compiler and std libraries. + check!(unit_tests, &src_path); + check!(unit_tests, &compiler_path); + check!(unit_tests, &library_path); + + if bins::check_filesystem_support( + &[&src_path, &compiler_path, &library_path], + &output_directory, + ) { + check!(bins, &src_path); + check!(bins, &compiler_path); + check!(bins, &library_path); + } + + check!(style, &src_path); + check!(style, &compiler_path); + check!(style, &library_path); + + check!(edition, &src_path); + check!(edition, &compiler_path); + check!(edition, &library_path); + + let collected = { + while handles.len() >= concurrency.get() { + handles.pop_front().unwrap().join().unwrap(); + } + let mut flag = false; + let r = features::check(&src_path, &compiler_path, &library_path, &mut flag, verbose); + if flag { + bad.store(true, Ordering::Relaxed); + } + r + }; + check!(unstable_book, &src_path, collected); + }) + .unwrap(); + + if bad.load(Ordering::Relaxed) { eprintln!("some tidy checks failed"); process::exit(1); } diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 1dba6b73b9..144529d864 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -40,35 +40,20 @@ const EXCEPTION_PATHS: &[&str] = &[ "library/panic_abort", "library/panic_unwind", "library/unwind", - // black_box implementation is LLVM-version specific and it uses - // target_os to tell targets with different LLVM-versions apart - // (e.g. `wasm32-unknown-emscripten` vs `wasm32-unknown-unknown`): - "library/core/src/hint.rs", "library/std/src/sys/", // Platform-specific code for std lives here. // This has the trailing slash so that sys_common is not excepted. "library/std/src/os", // Platform-specific public interfaces "library/rtstartup", // Not sure what to do about this. magic stuff for mingw - // temporary exceptions - "library/std/src/lib.rs", - "library/std/src/path.rs", - "library/std/src/f32.rs", - "library/std/src/f64.rs", // Integration test for platform-specific run-time feature detection: "library/std/tests/run-time-detect.rs", "library/std/src/net/test.rs", "library/std/src/net/addr", "library/std/src/net/udp", - "library/std/src/sys_common/mod.rs", - "library/std/src/sys_common/net.rs", - "library/std/src/sys_common/backtrace.rs", "library/std/src/sys_common/remutex.rs", "library/std/src/sync/mutex.rs", "library/std/src/sync/rwlock.rs", - // panic_unwind shims - "library/std/src/panicking.rs", "library/term", // Not sure how to make this crate portable, but test crate needs it. "library/test", // Probably should defer to unstable `std::sys` APIs. - "library/std/src/sync/mpsc", // some tests are only run on non-emscripten // std testing crates, okay for now at least "library/core/tests", "library/alloc/tests/lib.rs", @@ -79,13 +64,6 @@ const EXCEPTION_PATHS: &[&str] = &[ // we must use `#[cfg(windows)]` to conditionally compile the // correct `VaList` structure for windows. "library/core/src/ffi.rs", - // non-std crates - "src/test", - "src/tools", - "src/librustc", - "src/librustdoc", - "src/librustc_ast", - "src/bootstrap", ]; pub fn check(path: &Path, bad: &mut bool) { diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 75c4334302..3d5f39e8c9 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -16,6 +16,7 @@ //! A number of these checks can be opted-out of with various directives of the form: //! `// ignore-tidy-CHECK-NAME`. +use regex::Regex; use std::path::Path; /// Error code markdown is restricted to 80 columns because they can be @@ -41,6 +42,19 @@ C++ code used llvm_unreachable, which triggers undefined behavior when executed when assertions are disabled. Use llvm::report_fatal_error for increased robustness."; +const ANNOTATIONS_TO_IGNORE: &[&str] = &[ + "// @!has", + "// @has", + "// @matches", + "// CHECK", + "// EMIT_MIR", + "// compile-flags", + "// error-pattern", + "// gdb", + "// lldb", + "// normalize-stderr-test", +]; + /// Parser states for `line_is_url`. #[derive(Clone, Copy, PartialEq)] #[allow(non_camel_case_types)] @@ -92,12 +106,20 @@ fn line_is_url(is_error_code: bool, columns: usize, line: &str) -> bool { state == EXP_END } +/// Returns `true` if `line` can be ignored. This is the case when it contains +/// an annotation that is explicitly ignored. +fn should_ignore(line: &str) -> bool { + // Matches test annotations like `//~ ERROR text`. + // This mirrors the regex in src/tools/compiletest/src/runtest.rs, please + // update both if either are changed. + let re = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap(); + re.is_match(line) || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a)) +} + /// Returns `true` if `line` is allowed to be longer than the normal limit. -/// Currently there is only one exception, for long URLs, but more -/// may be added in the future. fn long_line_is_ok(extension: &str, is_error_code: bool, max_columns: usize, line: &str) -> bool { if extension != "md" || is_error_code { - if line_is_url(is_error_code, max_columns, line) { + if line_is_url(is_error_code, max_columns, line) || should_ignore(line) { return true; } } else if extension == "md" { diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 3374a8c9b7..8334bc68ae 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -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 = 1408; -const ISSUES_ENTRY_LIMIT: usize = 2565; +const ROOT_ENTRY_LIMIT: usize = 1388; +const ISSUES_ENTRY_LIMIT: usize = 2551; fn check_entries(path: &Path, bad: &mut bool) { let dirs = walkdir::WalkDir::new(&path.join("test/ui")) diff --git a/src/version b/src/version index 154cb93b2c..3f4830156c 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.52.1 +1.53.0 diff --git a/vendor/annotate-snippets-0.6.1/.cargo-checksum.json b/vendor/annotate-snippets-0.6.1/.cargo-checksum.json deleted file mode 100644 index 13074988fc..0000000000 --- a/vendor/annotate-snippets-0.6.1/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"230269942a7482e8a1c77dd30e22db58b4c7e3fa42dd5203e40e93d6bbcea175","Cargo.toml":"984545ef81f26c2d0087367044b65f9eb1f8c75c6a160c717d37caea5058452b","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-MIT":"49c0b000c03731d9e3970dc059ad4ca345d773681f4a612b0024435b663e0220","README.md":"8974c4d36d39dff6dabea6fcef6d04c001bd4fe46ac28e6cd18206a7d96ff9b1","examples/expected_type.rs":"cc8e81dcbdbe31cb1e3d2b2b951c8eeb975789c68c8511f1436b9464752396df","examples/footer.rs":"485dd393b03ad1958549db08b521be9f67ee61400e3181793353e927ec2aa414","examples/format.rs":"a6f1e6b51b13b883f0636aca177fa119db8095faaff58c3c5f2712537d9b08bc","examples/multislice.rs":"0afeed0bb0af412c2f1b5709e536a42186f492602d11869f4c058e8ccb30ceda","src/display_list/from_snippet.rs":"354ed2170db40e8324d3e2c28fe938623b45e4993d6124d3d4979a1546664d09","src/display_list/mod.rs":"e1810ba12bf48515d063075b9cdda3ede667d58bb33e75b1de27c392fbe11836","src/display_list/structs.rs":"d6a13ba21ced6032db262eca1aa50c0a6f738b9f0a778deb6b88a072fc54f335","src/formatter/mod.rs":"8b8414e7a0abc24c2d22d043d59b09da4f0f3cfdebed517e769de9e453765eac","src/formatter/style.rs":"6f3049e6d18fb9629a752f1bdc4ef720b1675ff69f07db55c3e7debb3885ad87","src/lib.rs":"fd655cb0518b4d11d5ff3a92eceefc0f45697c430197e95d3b8bed3bbf90325f","src/snippet.rs":"904d642357a4ed5d2a0387e7e9253ec4631ef852c7188507f98e474b16fd5adf","src/stylesheets/color.rs":"081f025ab42091dea42eda719d997e7fdf6a949885ead46e0d614dfa47c6a3a4","src/stylesheets/mod.rs":"ef8038360631561f53a4472cffe45e1fbde04f4aed8d4738426da88214b94576","src/stylesheets/no_color.rs":"0d25c1253658141b24fab1440b2b39a3fffe71952fc3667d2e2804a471766cf9","tests/diff/mod.rs":"44a8f8ef3b90db894227d6451b3bcbaa158c6daad5e8951456b979de6687b8e1","tests/dl_from_snippet.rs":"468eea5c1811b0578e923cdeaa6b7d8c159d4ac517c8802e332554e709df7038","tests/fixtures.rs":"25af2bd1891997b07bae8425e82a1ec89c04de29645188e83d6eb506948fb1b7","tests/fixtures/no-color/multiline_annotation.txt":"b8d36204f260d91e99672fe11839e1fe416f6a18b6de46c923d43c0430a97ee7","tests/fixtures/no-color/multiline_annotation.yaml":"fab49391fa0c53ffe3b997f70c5615c0b767c21de105b0a3805a692085e641ae","tests/fixtures/no-color/multiline_annotation2.txt":"391da0ef9bec5de45a30a0869ecc3227a1d3272872508af1d7a294fa431c8dd2","tests/fixtures/no-color/multiline_annotation2.yaml":"aa2fb2c8666f1c625c92dd1630dd643ba304617334c077b169e5a27be0c116af","tests/fixtures/no-color/multiple_annotations.txt":"b284ab83d9de3aa9d014d3d04ac199517967885bc064f0462c15d6a4d71554aa","tests/fixtures/no-color/multiple_annotations.yaml":"7892a2eb95a0442e3926c31482202410d867a87ef3d35c6c4599ebd6e5c33d31","tests/fixtures/no-color/simple.txt":"cb9b7fab003c58e03ce87cae4fd04a40983ff3f8ee329b494dcb3abcf576fccd","tests/fixtures/no-color/simple.yaml":"9650f0a4ff157c7daf6cc3fc33179173f1cd4c1ace298501efca3da134aec1e9","tests/formatter.rs":"9a6be74db49bb3d5d91d3c42430f7d0585911b6702fb017063ed02063c50507d","tests/snippet/mod.rs":"e2f2b073590ba2632196ea2bdc26832a9ab986e1955721a578db7a723e21a37e"},"package":"c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7"} \ No newline at end of file diff --git a/vendor/annotate-snippets-0.6.1/CHANGELOG.md b/vendor/annotate-snippets-0.6.1/CHANGELOG.md deleted file mode 100644 index a125e8fca3..0000000000 --- a/vendor/annotate-snippets-0.6.1/CHANGELOG.md +++ /dev/null @@ -1,15 +0,0 @@ -# Changelog - -## Unreleased - - - … - -## annotate-snippets 0.6.1 (July 23, 2019) - - - Fix too many anonymized line numbers (#5) - -## annotate-snippets 0.6.0 (June 26, 2019) - - - Add an option to anonymize line numbers (#3) - - Transition the crate to rust-lang org. - - Update the syntax to Rust 2018 idioms. (#4) diff --git a/vendor/annotate-snippets-0.6.1/Cargo.toml b/vendor/annotate-snippets-0.6.1/Cargo.toml deleted file mode 100644 index 1f157d28ca..0000000000 --- a/vendor/annotate-snippets-0.6.1/Cargo.toml +++ /dev/null @@ -1,55 +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 = "annotate-snippets" -version = "0.6.1" -authors = ["Zibi Braniecki <gandalf@mozilla.com>"] -description = "Library for building code annotations" -readme = "README.md" -keywords = ["code", "analysis", "ascii", "errors", "debug"] -license = "Apache-2.0/MIT" -repository = "https://github.com/rust-lang/annotate-snippets-rs" -[dependencies.ansi_term] -version = "0.11.0" -optional = true -[dev-dependencies.ansi_term] -version = "^0.12" - -[dev-dependencies.difference] -version = "^2.0" - -[dev-dependencies.glob] -version = "^0.3" - -[dev-dependencies.serde] -version = "^1.0" -features = ["derive"] - -[dev-dependencies.serde_yaml] -version = "^0.8" - -[features] -color = ["ansi_term"] -default = [] -[badges.coveralls] -branch = "master" -repository = "rust-lang/annotate-snippets-rs" -service = "github" - -[badges.maintenance] -status = "actively-developed" - -[badges.travis-ci] -branch = "master" -repository = "rust-lang/annotate-snippets-rs" diff --git a/vendor/annotate-snippets-0.6.1/LICENSE-APACHE b/vendor/annotate-snippets-0.6.1/LICENSE-APACHE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/vendor/annotate-snippets-0.6.1/LICENSE-APACHE +++ /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/annotate-snippets-0.6.1/LICENSE-MIT b/vendor/annotate-snippets-0.6.1/LICENSE-MIT deleted file mode 100644 index 5655fa311c..0000000000 --- a/vendor/annotate-snippets-0.6.1/LICENSE-MIT +++ /dev/null @@ -1,19 +0,0 @@ -Copyright 2017 Mozilla - -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/annotate-snippets-0.6.1/README.md b/vendor/annotate-snippets-0.6.1/README.md deleted file mode 100644 index a690007b0f..0000000000 --- a/vendor/annotate-snippets-0.6.1/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# annotate-snippets - -`annotate-snippets` is a Rust library for annotation of programming code slices. - -[![crates.io](http://meritbadge.herokuapp.com/annotate-snippets)](https://crates.io/crates/annotate-snippets) -[![Build Status](https://travis-ci.org/rust-lang/annotate-snippets-rs.svg?branch=master)](https://travis-ci.org/rust-lang/annotate-snippets-rs) -[![Coverage Status](https://coveralls.io/repos/github/rust-lang/annotate-snippets-rs/badge.svg?branch=master)](https://coveralls.io/github/rust-lang/annotate-snippets-rs?branch=master) - -The library helps visualize meta information annotating source code slices. -It takes a data structure called `Snippet` on the input and produces a `String` -which may look like this: - -```text -error[E0308]: mismatched types - --> src/format.rs:52:1 - | -51 | ) -> Option<String> { - | -------------- expected `Option<String>` because of return type -52 | / for ann in annotations { -53 | | match (ann.range.0, ann.range.1) { -54 | | (None, None) => continue, -55 | | (Some(start), Some(end)) if start > end_index => continue, -... | -71 | | } -72 | | } - | |_____^ expected enum `std::option::Option`, found () -``` - -[Documentation][] - -[Documentation]: https://docs.rs/annotate-snippets/ - -Usage ------ - -```rust -use annotate_snippets::snippet; - -fn main() { - let snippet = Snippet { - title: Some(Annotation { - label: Some("expected type, found `22`".to_string()), - id: None, - annotation_type: AnnotationType::Error, - }), - footer: vec![], - slices: vec![ - Slice { - source: r#" -This is an example -content of the slice -which will be annotated -with the list of annotations below. - "#.to_string(), - line_start: 26, - origin: Some("examples/example.txt".to_string()), - fold: false, - annotations: vec![ - SourceAnnotation { - label: "Example error annotation".to_string(), - annotation_type: AnnotationType::Error, - range: (13, 18), - }, - SourceAnnotation { - label: "and here's a warning".to_string(), - annotation_type: AnnotationType::Warning, - range: (34, 50), - }, - ], - }, - ], - }; - - let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true); - dlf.format(&dl); -} -``` - -Local Development ------------------ - - cargo build - cargo test - -When submitting a PR please use [`cargo fmt`][] (nightly). - -[`cargo fmt`]: https://github.com/rust-lang-nursery/rustfmt diff --git a/vendor/annotate-snippets-0.6.1/examples/expected_type.rs b/vendor/annotate-snippets-0.6.1/examples/expected_type.rs deleted file mode 100644 index 20cda66889..0000000000 --- a/vendor/annotate-snippets-0.6.1/examples/expected_type.rs +++ /dev/null @@ -1,40 +0,0 @@ -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; -use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; - -fn main() { - let snippet = Snippet { - title: Some(Annotation { - label: Some("expected type, found `22`".to_string()), - id: None, - annotation_type: AnnotationType::Error, - }), - footer: vec![], - slices: vec![Slice { - source: r#" annotations: vec![SourceAnnotation { - label: "expected struct `annotate_snippets::snippet::Slice`, found reference" - .to_string(), - range: <22, 25>,"# - .to_string(), - line_start: 26, - origin: Some("examples/footer.rs".to_string()), - fold: true, - annotations: vec![ - SourceAnnotation { - label: "".to_string(), - annotation_type: AnnotationType::Error, - range: (208, 210), - }, - SourceAnnotation { - label: "while parsing this struct".to_string(), - annotation_type: AnnotationType::Info, - range: (34, 50), - }, - ], - }], - }; - - let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true, false); - println!("{}", dlf.format(&dl)); -} diff --git a/vendor/annotate-snippets-0.6.1/examples/footer.rs b/vendor/annotate-snippets-0.6.1/examples/footer.rs deleted file mode 100644 index 1b03910fe6..0000000000 --- a/vendor/annotate-snippets-0.6.1/examples/footer.rs +++ /dev/null @@ -1,37 +0,0 @@ -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; -use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; - -fn main() { - let snippet = Snippet { - title: Some(Annotation { - label: Some("mismatched types".to_string()), - id: Some("E0308".to_string()), - annotation_type: AnnotationType::Error, - }), - footer: vec![Annotation { - label: Some( - "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`" - .to_string(), - ), - id: None, - annotation_type: AnnotationType::Note, - }], - slices: vec![Slice { - source: " slices: vec![\"A\",".to_string(), - line_start: 13, - origin: Some("src/multislice.rs".to_string()), - fold: false, - annotations: vec![SourceAnnotation { - label: "expected struct `annotate_snippets::snippet::Slice`, found reference" - .to_string(), - range: (21, 24), - annotation_type: AnnotationType::Error, - }], - }], - }; - - let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true, false); - println!("{}", dlf.format(&dl)); -} diff --git a/vendor/annotate-snippets-0.6.1/examples/format.rs b/vendor/annotate-snippets-0.6.1/examples/format.rs deleted file mode 100644 index 7e41802eb8..0000000000 --- a/vendor/annotate-snippets-0.6.1/examples/format.rs +++ /dev/null @@ -1,58 +0,0 @@ -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; -use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; - -fn main() { - let snippet = Snippet { - slices: vec![Slice { - source: r#") -> Option<String> { - for ann in annotations { - match (ann.range.0, ann.range.1) { - (None, None) => continue, - (Some(start), Some(end)) if start > end_index => continue, - (Some(start), Some(end)) if start >= start_index => { - let label = if let Some(ref label) = ann.label { - format!(" {}", label) - } else { - String::from("") - }; - - return Some(format!( - "{}{}{}", - " ".repeat(start - start_index), - "^".repeat(end - start), - label - )); - } - _ => continue, - } - }"# - .to_string(), - line_start: 51, - origin: Some("src/format.rs".to_string()), - fold: false, - annotations: vec![ - SourceAnnotation { - label: "expected `Option<String>` because of return type".to_string(), - annotation_type: AnnotationType::Warning, - range: (5, 19), - }, - SourceAnnotation { - label: "expected enum `std::option::Option`".to_string(), - annotation_type: AnnotationType::Error, - range: (23, 745), - }, - ], - }], - title: Some(Annotation { - label: Some("mismatched types".to_string()), - id: Some("E0308".to_string()), - annotation_type: AnnotationType::Error, - }), - footer: vec![], - }; - - let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true, false); - println!("{}", dlf.format(&dl)); -} diff --git a/vendor/annotate-snippets-0.6.1/examples/multislice.rs b/vendor/annotate-snippets-0.6.1/examples/multislice.rs deleted file mode 100644 index af1cb152bc..0000000000 --- a/vendor/annotate-snippets-0.6.1/examples/multislice.rs +++ /dev/null @@ -1,34 +0,0 @@ -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; -use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet}; - -fn main() { - let snippet = Snippet { - title: Some(Annotation { - label: Some("mismatched types".to_string()), - id: None, - annotation_type: AnnotationType::Error, - }), - footer: vec![], - slices: vec![ - Slice { - source: "Foo".to_string(), - line_start: 51, - origin: Some("src/format.rs".to_string()), - fold: false, - annotations: vec![], - }, - Slice { - source: "Faa".to_string(), - line_start: 129, - origin: Some("src/display.rs".to_string()), - fold: false, - annotations: vec![], - }, - ], - }; - - let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true, false); - println!("{}", dlf.format(&dl)); -} diff --git a/vendor/annotate-snippets-0.6.1/src/display_list/from_snippet.rs b/vendor/annotate-snippets-0.6.1/src/display_list/from_snippet.rs deleted file mode 100644 index e3d79ed4b1..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/display_list/from_snippet.rs +++ /dev/null @@ -1,403 +0,0 @@ -//! Trait for converting `Snippet` to `DisplayList`. -use super::*; -use crate::snippet; - -fn format_label(label: Option<&str>, style: Option<DisplayTextStyle>) -> Vec<DisplayTextFragment> { - let mut result = vec![]; - if let Some(label) = label { - let elements: Vec<&str> = label.split("__").collect(); - for (idx, element) in elements.iter().enumerate() { - let element_style = match style { - Some(s) => s, - None => { - if idx % 2 == 0 { - DisplayTextStyle::Regular - } else { - DisplayTextStyle::Emphasis - } - } - }; - result.push(DisplayTextFragment { - content: element.to_string(), - style: element_style, - }); - } - } - result -} - -fn format_title(annotation: &snippet::Annotation) -> DisplayLine { - let label = annotation.label.clone().unwrap_or_default(); - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::from(annotation.annotation_type), - id: annotation.id.clone(), - label: format_label(Some(&label), Some(DisplayTextStyle::Emphasis)), - }, - source_aligned: false, - continuation: false, - }) -} - -fn format_annotation(annotation: &snippet::Annotation) -> Vec<DisplayLine> { - let mut result = vec![]; - let label = annotation.label.clone().unwrap_or_default(); - for (i, line) in label.lines().enumerate() { - result.push(DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::from(annotation.annotation_type), - id: None, - label: format_label(Some(line), None), - }, - source_aligned: true, - continuation: i != 0, - })); - } - result -} - -fn format_slice(slice: &snippet::Slice, is_first: bool, has_footer: bool) -> Vec<DisplayLine> { - let mut body = format_body(slice, has_footer); - let mut result = vec![]; - - let header = format_header(slice, &body, is_first); - if let Some(header) = header { - result.push(header); - } - result.append(&mut body); - result -} - -fn format_header( - slice: &snippet::Slice, - body: &[DisplayLine], - is_first: bool, -) -> Option<DisplayLine> { - let main_annotation = slice.annotations.get(0); - - let display_header = if is_first { - DisplayHeaderType::Initial - } else { - DisplayHeaderType::Continuation - }; - - if let Some(annotation) = main_annotation { - let mut col = 1; - let mut row = slice.line_start; - - for item in body.iter() { - if let DisplayLine::Source { - line: DisplaySourceLine::Content { range, .. }, - .. - } = item - { - if annotation.range.0 >= range.0 && annotation.range.0 <= range.1 { - col = annotation.range.0 - range.0; - break; - } - row += 1; - } - } - if let Some(ref path) = slice.origin { - return Some(DisplayLine::Raw(DisplayRawLine::Origin { - path: path.to_string(), - pos: Some((row, col)), - header_type: display_header, - })); - } - } - if let Some(ref path) = slice.origin { - return Some(DisplayLine::Raw(DisplayRawLine::Origin { - path: path.to_string(), - pos: None, - header_type: display_header, - })); - } - None -} - -fn fold_body(body: &[DisplayLine]) -> Vec<DisplayLine> { - let mut new_body = vec![]; - - let mut no_annotation_lines_counter = 0; - let mut idx = 0; - - while idx < body.len() { - match body[idx] { - DisplayLine::Source { - line: DisplaySourceLine::Annotation { .. }, - ref inline_marks, - .. - } => { - if no_annotation_lines_counter > 2 { - let fold_start = idx - no_annotation_lines_counter; - let fold_end = idx; - let pre_len = if no_annotation_lines_counter > 8 { - 4 - } else { - 0 - }; - let post_len = if no_annotation_lines_counter > 8 { - 2 - } else { - 1 - }; - for item in body.iter().take(fold_start + pre_len).skip(fold_start) { - new_body.push(item.clone()); - } - new_body.push(DisplayLine::Fold { - inline_marks: inline_marks.clone(), - }); - for item in body.iter().take(fold_end).skip(fold_end - post_len) { - new_body.push(item.clone()); - } - } else { - let start = idx - no_annotation_lines_counter; - for item in body.iter().take(idx).skip(start) { - new_body.push(item.clone()); - } - } - no_annotation_lines_counter = 0; - } - DisplayLine::Source { .. } => { - no_annotation_lines_counter += 1; - idx += 1; - continue; - } - _ => { - no_annotation_lines_counter += 1; - } - } - new_body.push(body[idx].clone()); - idx += 1; - } - - new_body -} - -fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> { - let mut body = vec![]; - - let mut current_line = slice.line_start; - let mut current_index = 0; - let mut line_index_ranges = vec![]; - - for line in slice.source.lines() { - let line_length = line.chars().count() + 1; - let line_range = (current_index, current_index + line_length); - body.push(DisplayLine::Source { - lineno: Some(current_line), - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: line.to_string(), - range: line_range, - }, - }); - line_index_ranges.push(line_range); - current_line += 1; - current_index += line_length + 1; - } - - let mut annotation_line_count = 0; - let mut annotations = slice.annotations.clone(); - for idx in 0..body.len() { - let (line_start, line_end) = line_index_ranges[idx]; - // It would be nice to use filter_drain here once it's stable. - annotations = annotations - .into_iter() - .filter(|annotation| { - let body_idx = idx + annotation_line_count; - let annotation_type = match annotation.annotation_type { - snippet::AnnotationType::Error => DisplayAnnotationType::None, - snippet::AnnotationType::Warning => DisplayAnnotationType::None, - _ => DisplayAnnotationType::from(annotation.annotation_type), - }; - match annotation.range { - (start, _) if start > line_end => true, - (start, end) if start >= line_start && end <= line_end + 1 => { - let range = (start - line_start, end - line_start); - body.insert( - body_idx + 1, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - annotation: Annotation { - annotation_type, - id: None, - label: format_label(Some(&annotation.label), None), - }, - range, - annotation_type: DisplayAnnotationType::from( - annotation.annotation_type, - ), - annotation_part: DisplayAnnotationPart::Standalone, - }, - }, - ); - annotation_line_count += 1; - false - } - (start, end) if start >= line_start && start <= line_end && end > line_end => { - if start - line_start == 0 { - if let DisplayLine::Source { - ref mut inline_marks, - .. - } = body[body_idx] - { - inline_marks.push(DisplayMark { - mark_type: DisplayMarkType::AnnotationStart, - annotation_type: DisplayAnnotationType::from( - annotation.annotation_type, - ), - }); - } - } else { - let range = (start - line_start, start - line_start + 1); - body.insert( - body_idx + 1, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::None, - id: None, - label: vec![], - }, - range, - annotation_type: DisplayAnnotationType::from( - annotation.annotation_type, - ), - annotation_part: DisplayAnnotationPart::MultilineStart, - }, - }, - ); - annotation_line_count += 1; - } - true - } - (start, end) if start < line_start && end > line_end => { - if let DisplayLine::Source { - ref mut inline_marks, - .. - } = body[body_idx] - { - inline_marks.push(DisplayMark { - mark_type: DisplayMarkType::AnnotationThrough, - annotation_type: DisplayAnnotationType::from( - annotation.annotation_type, - ), - }); - } - true - } - (start, end) if start < line_start && end >= line_start && end <= line_end => { - if let DisplayLine::Source { - ref mut inline_marks, - .. - } = body[body_idx] - { - inline_marks.push(DisplayMark { - mark_type: DisplayMarkType::AnnotationThrough, - annotation_type: DisplayAnnotationType::from( - annotation.annotation_type, - ), - }); - } - let range = (end - line_start, end - line_start + 1); - body.insert( - body_idx + 1, - DisplayLine::Source { - lineno: None, - inline_marks: vec![DisplayMark { - mark_type: DisplayMarkType::AnnotationThrough, - annotation_type: DisplayAnnotationType::from( - annotation.annotation_type, - ), - }], - line: DisplaySourceLine::Annotation { - annotation: Annotation { - annotation_type, - id: None, - label: format_label(Some(&annotation.label), None), - }, - range, - annotation_type: DisplayAnnotationType::from( - annotation.annotation_type, - ), - annotation_part: DisplayAnnotationPart::MultilineEnd, - }, - }, - ); - annotation_line_count += 1; - false - } - _ => true, - } - }) - .collect(); - } - - if slice.fold { - body = fold_body(&body); - } - - body.insert( - 0, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Empty, - }, - ); - if has_footer { - body.push(DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Empty, - }); - } else if let Some(DisplayLine::Source { .. }) = body.last() { - body.push(DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Empty, - }); - } - body -} - -impl From<snippet::Snippet> for DisplayList { - fn from(snippet: snippet::Snippet) -> Self { - let mut body = vec![]; - if let Some(annotation) = snippet.title { - body.push(format_title(&annotation)); - } - - for (idx, slice) in snippet.slices.iter().enumerate() { - body.append(&mut format_slice( - &slice, - idx == 0, - !snippet.footer.is_empty(), - )); - } - - for annotation in snippet.footer { - body.append(&mut format_annotation(&annotation)); - } - - Self { body } - } -} - -impl From<snippet::AnnotationType> for DisplayAnnotationType { - fn from(at: snippet::AnnotationType) -> Self { - match at { - snippet::AnnotationType::Error => DisplayAnnotationType::Error, - snippet::AnnotationType::Warning => DisplayAnnotationType::Warning, - snippet::AnnotationType::Info => DisplayAnnotationType::Info, - snippet::AnnotationType::Note => DisplayAnnotationType::Note, - snippet::AnnotationType::Help => DisplayAnnotationType::Help, - } - } -} diff --git a/vendor/annotate-snippets-0.6.1/src/display_list/mod.rs b/vendor/annotate-snippets-0.6.1/src/display_list/mod.rs deleted file mode 100644 index 5e0b393d66..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/display_list/mod.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! display_list module stores the output model for the snippet. -//! -//! `DisplayList` is a central structure in the crate, which contains -//! the structured list of lines to be displayed. -//! -//! It is made of two types of lines: `Source` and `Raw`. All `Source` lines -//! are structured using four columns: -//! -//! ```text -//! /------------ (1) Line number column. -//! | /--------- (2) Line number column delimiter. -//! | | /------- (3) Inline marks column. -//! | | | /--- (4) Content column with the source and annotations for slices. -//! | | | | -//! ============================================================================= -//! error[E0308]: mismatched types -//! --> src/format.rs:51:5 -//! | -//! 151 | / fn test() -> String { -//! 152 | | return "test"; -//! 153 | | } -//! | |___^ error: expected `String`, for `&str`. -//! | -//! ``` -//! -//! The first two lines of the example above are `Raw` lines, while the rest -//! are `Source` lines. -//! -//! `DisplayList` does not store column alignment information, and those are -//! only calculated by the `DisplayListFormatter` using information such as -//! styling. -//! -//! The above snippet has been built out of the following structure: -//! -//! ``` -//! use annotate_snippets::display_list::*; -//! -//! let dl = DisplayList { -//! body: vec![ -//! DisplayLine::Raw(DisplayRawLine::Annotation { -//! annotation: Annotation { -//! annotation_type: DisplayAnnotationType::Error, -//! id: Some("E0308".to_string()), -//! label: vec![ -//! DisplayTextFragment { -//! content: "mismatched types".to_string(), -//! style: DisplayTextStyle::Regular, -//! } -//! ] -//! }, -//! source_aligned: false, -//! continuation: false, -//! }), -//! DisplayLine::Raw(DisplayRawLine::Origin { -//! path: "src/format.rs".to_string(), -//! pos: Some((51, 5)), -//! header_type: DisplayHeaderType::Initial, -//! }), -//! DisplayLine::Source { -//! lineno: Some(151), -//! inline_marks: vec![ -//! DisplayMark { -//! mark_type: DisplayMarkType::AnnotationStart, -//! annotation_type: DisplayAnnotationType::Error, -//! } -//! ], -//! line: DisplaySourceLine::Content { -//! text: " fn test() -> String {".to_string(), -//! range: (0, 24) -//! } -//! }, -//! DisplayLine::Source { -//! lineno: Some(152), -//! inline_marks: vec![ -//! DisplayMark { -//! mark_type: DisplayMarkType::AnnotationThrough, -//! annotation_type: DisplayAnnotationType::Error, -//! } -//! ], -//! line: DisplaySourceLine::Content { -//! text: " return \"test\";".to_string(), -//! range: (25, 46) -//! } -//! }, -//! DisplayLine::Source { -//! lineno: Some(153), -//! inline_marks: vec![ -//! DisplayMark { -//! mark_type: DisplayMarkType::AnnotationThrough, -//! annotation_type: DisplayAnnotationType::Error, -//! } -//! ], -//! line: DisplaySourceLine::Content { -//! text: " }".to_string(), -//! range: (47, 51) -//! } -//! }, -//! DisplayLine::Source { -//! lineno: None, -//! inline_marks: vec![], -//! line: DisplaySourceLine::Annotation { -//! annotation: Annotation { -//! annotation_type: DisplayAnnotationType::Error, -//! id: None, -//! label: vec![ -//! DisplayTextFragment { -//! content: "expected `String`, for `&str`.".to_string(), -//! style: DisplayTextStyle::Regular, -//! } -//! ] -//! }, -//! range: (3, 4), -//! annotation_type: DisplayAnnotationType::Error, -//! annotation_part: DisplayAnnotationPart::MultilineEnd, -//! } -//! -//! } -//! ] -//! }; -//! ``` -mod from_snippet; -mod structs; - -pub use self::structs::*; diff --git a/vendor/annotate-snippets-0.6.1/src/display_list/structs.rs b/vendor/annotate-snippets-0.6.1/src/display_list/structs.rs deleted file mode 100644 index 0d3e0bc5b6..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/display_list/structs.rs +++ /dev/null @@ -1,253 +0,0 @@ -/// List of lines to be displayed. -#[derive(Debug, Clone, PartialEq)] -pub struct DisplayList { - pub body: Vec<DisplayLine>, -} - -impl From<Vec<DisplayLine>> for DisplayList { - fn from(body: Vec<DisplayLine>) -> Self { - Self { body } - } -} - -/// Inline annotation which can be used in either Raw or Source line. -#[derive(Debug, Clone, PartialEq)] -pub struct Annotation { - pub annotation_type: DisplayAnnotationType, - pub id: Option<String>, - pub label: Vec<DisplayTextFragment>, -} - -/// A single line used in `DisplayList`. -#[derive(Debug, Clone, PartialEq)] -pub enum DisplayLine { - /// A line with `lineno` portion of the slice. - Source { - lineno: Option<usize>, - inline_marks: Vec<DisplayMark>, - line: DisplaySourceLine, - }, - - /// A line indicating a folded part of the slice. - Fold { inline_marks: Vec<DisplayMark> }, - - /// A line which is displayed outside of slices. - Raw(DisplayRawLine), -} - -/// A source line. -#[derive(Debug, Clone, PartialEq)] -pub enum DisplaySourceLine { - /// A line with the content of the Slice. - Content { - text: String, - range: (usize, usize), // meta information for annotation placement. - }, - - /// An annotation line which is displayed in context of the slice. - Annotation { - annotation: Annotation, - range: (usize, usize), - annotation_type: DisplayAnnotationType, - annotation_part: DisplayAnnotationPart, - }, - - /// An empty source line. - Empty, -} - -/// Raw line - a line which does not have the `lineno` part and is not considered -/// a part of the snippet. -#[derive(Debug, Clone, PartialEq)] -pub enum DisplayRawLine { - /// A line which provides information about the location of the given - /// slice in the project structure. - Origin { - path: String, - pos: Option<(usize, usize)>, - header_type: DisplayHeaderType, - }, - - /// An annotation line which is not part of any snippet. - Annotation { - annotation: Annotation, - - /// If set to `true`, the annotation will be aligned to the - /// lineno delimiter of the snippet. - source_aligned: bool, - /// If set to `true`, only the label of the `Annotation` will be - /// displayed. It allows for a multiline annotation to be aligned - /// without displaing the meta information (`type` and `id`) to be - /// displayed on each line. - continuation: bool, - }, -} - -/// An inline text fragment which any label is composed of. -#[derive(Debug, Clone, PartialEq)] -pub struct DisplayTextFragment { - pub content: String, - pub style: DisplayTextStyle, -} - -/// A style for the `DisplayTextFragment` which can be visually formatted. -/// -/// This information may be used to emphasis parts of the label. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum DisplayTextStyle { - Regular, - Emphasis, -} - -/// An indicator of what part of the annotation a given `Annotation` is. -#[derive(Debug, Clone, PartialEq)] -pub enum DisplayAnnotationPart { - /// A standalone, single-line annotation. - Standalone, - /// A continuation of a multi-line label of an annotation. - LabelContinuation, - /// A consequitive annotation in case multiple annotations annotate a single line. - Consequitive, - /// A line starting a multiline annotation. - MultilineStart, - /// A line ending a multiline annotation. - MultilineEnd, -} - -/// A visual mark used in `inline_marks` field of the `DisplaySourceLine`. -#[derive(Debug, Clone, PartialEq)] -pub struct DisplayMark { - pub mark_type: DisplayMarkType, - pub annotation_type: DisplayAnnotationType, -} - -/// A type of the `DisplayMark`. -#[derive(Debug, Clone, PartialEq)] -pub enum DisplayMarkType { - /// A mark indicating a multiline annotation going through the current line. - /// - /// Example: - /// ``` - /// use annotate_snippets::display_list::*; - /// use annotate_snippets::formatter::DisplayListFormatter; - /// - /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors - /// - /// let dl = DisplayList { - /// body: vec![ - /// DisplayLine::Source { - /// lineno: Some(51), - /// inline_marks: vec![ - /// DisplayMark { - /// mark_type: DisplayMarkType::AnnotationThrough, - /// annotation_type: DisplayAnnotationType::Error, - /// } - /// ], - /// line: DisplaySourceLine::Content { - /// text: "Example".to_string(), - /// range: (0, 7), - /// } - /// } - /// ] - /// }; - /// assert_eq!(dlf.format(&dl), "51 | | Example"); - /// ``` - AnnotationThrough, - - /// A mark indicating a multiline annotation starting on the given line. - /// - /// Example: - /// ``` - /// use annotate_snippets::display_list::*; - /// use annotate_snippets::formatter::DisplayListFormatter; - /// - /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors - /// - /// let dl = DisplayList { - /// body: vec![ - /// DisplayLine::Source { - /// lineno: Some(51), - /// inline_marks: vec![ - /// DisplayMark { - /// mark_type: DisplayMarkType::AnnotationStart, - /// annotation_type: DisplayAnnotationType::Error, - /// } - /// ], - /// line: DisplaySourceLine::Content { - /// text: "Example".to_string(), - /// range: (0, 7), - /// } - /// } - /// ] - /// }; - /// assert_eq!(dlf.format(&dl), "51 | / Example"); - /// ``` - AnnotationStart, -} - -/// A type of the `Annotation` which may impact the sigils, style or text displayed. -/// -/// There are several ways in which the `DisplayListFormatter` uses this information -/// when formatting the `DisplayList`: -/// -/// * An annotation may display the name of the type like `error` or `info`. -/// * An underline for `Error` may be `^^^` while for `Warning` it coule be `---`. -/// * `ColorStylesheet` may use different colors for different annotations. -#[derive(Debug, Clone, PartialEq)] -pub enum DisplayAnnotationType { - None, - Error, - Warning, - Info, - Note, - Help, -} - -/// Information whether the header is the initial one or a consequitive one -/// for multi-slice cases. -#[derive(Debug, Clone, PartialEq)] -pub enum DisplayHeaderType { - /// Initial header is the first header in the snippet. - /// - /// Example: - /// ``` - /// use annotate_snippets::display_list::*; - /// use annotate_snippets::formatter::DisplayListFormatter; - /// - /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors - /// - /// let dl = DisplayList { - /// body: vec![ - /// DisplayLine::Raw(DisplayRawLine::Origin { - /// path: "file1.rs".to_string(), - /// pos: Some((51, 5)), - /// header_type: DisplayHeaderType::Initial, - /// }) - /// ] - /// }; - /// assert_eq!(dlf.format(&dl), "--> file1.rs:51:5"); - /// ``` - Initial, - - /// Continuation marks all headers of following slices in the snippet. - /// - /// Example: - /// ``` - /// use annotate_snippets::display_list::*; - /// use annotate_snippets::formatter::DisplayListFormatter; - /// - /// let dlf = DisplayListFormatter::new(false, false); // Don't use colors - /// - /// let dl = DisplayList { - /// body: vec![ - /// DisplayLine::Raw(DisplayRawLine::Origin { - /// path: "file1.rs".to_string(), - /// pos: Some((51, 5)), - /// header_type: DisplayHeaderType::Continuation, - /// }) - /// ] - /// }; - /// assert_eq!(dlf.format(&dl), "::: file1.rs:51:5"); - /// ``` - Continuation, -} diff --git a/vendor/annotate-snippets-0.6.1/src/formatter/mod.rs b/vendor/annotate-snippets-0.6.1/src/formatter/mod.rs deleted file mode 100644 index 654b51893b..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/formatter/mod.rs +++ /dev/null @@ -1,367 +0,0 @@ -//! DisplayListFormatter is a module handling the formatting of a -//! `DisplayList` into a formatted string. -//! -//! Besides formatting into a string it also uses a `style::Stylesheet` to -//! provide additional styling like colors and emphasis to the text. - -pub mod style; - -use self::style::{Style, StyleClass, Stylesheet}; -use crate::display_list::*; -use std::cmp; - -use crate::stylesheets::no_color::NoColorStylesheet; -#[cfg(feature = "ansi_term")] -use crate::stylesheets::color::AnsiTermStylesheet; - -fn repeat_char(c: char, n: usize) -> String { - let mut s = String::with_capacity(c.len_utf8()); - s.push(c); - s.repeat(n) -} - -/// DisplayListFormatter' constructor accepts two arguments: -/// -/// * `color` allows the formatter to optionally apply colors and emphasis -/// using the `ansi_term` crate. -/// * `anonymized_line_numbers` will replace line numbers in the left column with the text `LL`. -/// -/// Example: -/// -/// ``` -/// use annotate_snippets::formatter::DisplayListFormatter; -/// use annotate_snippets::display_list::{DisplayList, DisplayLine, DisplaySourceLine}; -/// -/// let dlf = DisplayListFormatter::new(false, false); // Don't use colors, Don't anonymize line numbers -/// -/// let dl = DisplayList { -/// body: vec![ -/// DisplayLine::Source { -/// lineno: Some(192), -/// inline_marks: vec![], -/// line: DisplaySourceLine::Content { -/// text: "Example line of text".into(), -/// range: (0, 21) -/// } -/// } -/// ] -/// }; -/// assert_eq!(dlf.format(&dl), "192 | Example line of text"); -/// ``` -pub struct DisplayListFormatter { - stylesheet: Box<dyn Stylesheet>, - anonymized_line_numbers: bool, -} - -impl DisplayListFormatter { - const ANONYMIZED_LINE_NUM: &'static str = "LL"; - - /// Constructor for the struct. - /// - /// The argument `color` selects the stylesheet depending on the user preferences and - /// `ansi_term` crate availability. - /// - /// The argument `anonymized_line_numbers` will replace line numbers in the left column with - /// the text `LL`. This can be useful to enable when running UI tests, such as in the Rust - /// test suite. - pub fn new(color: bool, anonymized_line_numbers: bool) -> Self { - if color { - Self { - #[cfg(feature = "ansi_term")] - stylesheet: Box::new(AnsiTermStylesheet {}), - #[cfg(not(feature = "ansi_term"))] - stylesheet: Box::new(NoColorStylesheet {}), - anonymized_line_numbers, - } - } else { - Self { - stylesheet: Box::new(NoColorStylesheet {}), - anonymized_line_numbers, - } - } - } - - /// Formats a `DisplayList` into a String. - pub fn format(&self, dl: &DisplayList) -> String { - let lineno_width = dl.body.iter().fold(0, |max, line| match line { - DisplayLine::Source { - lineno: Some(lineno), - .. - } => { - if self.anonymized_line_numbers { - Self::ANONYMIZED_LINE_NUM.len() - } else { - cmp::max(lineno.to_string().len(), max) - } - }, - _ => max, - }); - let inline_marks_width = dl.body.iter().fold(0, |max, line| match line { - DisplayLine::Source { inline_marks, .. } => cmp::max(inline_marks.len(), max), - _ => max, - }); - - dl.body - .iter() - .map(|line| self.format_line(line, lineno_width, inline_marks_width)) - .collect::<Vec<String>>() - .join("\n") - } - - fn format_annotation_type(&self, annotation_type: &DisplayAnnotationType) -> &'static str { - match annotation_type { - DisplayAnnotationType::Error => "error", - DisplayAnnotationType::Warning => "warning", - DisplayAnnotationType::Info => "info", - DisplayAnnotationType::Note => "note", - DisplayAnnotationType::Help => "help", - DisplayAnnotationType::None => "", - } - } - - fn get_annotation_style(&self, annotation_type: &DisplayAnnotationType) -> Box<dyn Style> { - self.stylesheet.get_style(match annotation_type { - DisplayAnnotationType::Error => StyleClass::Error, - DisplayAnnotationType::Warning => StyleClass::Warning, - DisplayAnnotationType::Info => StyleClass::Info, - DisplayAnnotationType::Note => StyleClass::Note, - DisplayAnnotationType::Help => StyleClass::Help, - DisplayAnnotationType::None => StyleClass::None, - }) - } - - fn format_label(&self, label: &[DisplayTextFragment]) -> String { - let emphasis_style = self.stylesheet.get_style(StyleClass::Emphasis); - label - .iter() - .map(|fragment| match fragment.style { - DisplayTextStyle::Regular => fragment.content.clone(), - DisplayTextStyle::Emphasis => emphasis_style.paint(&fragment.content), - }) - .collect::<Vec<String>>() - .join("") - } - - fn format_annotation( - &self, - annotation: &Annotation, - continuation: bool, - in_source: bool, - ) -> String { - let color = self.get_annotation_style(&annotation.annotation_type); - let formatted_type = if let Some(ref id) = annotation.id { - format!( - "{}[{}]", - self.format_annotation_type(&annotation.annotation_type), - id - ) - } else { - self.format_annotation_type(&annotation.annotation_type) - .to_string() - }; - let label = self.format_label(&annotation.label); - - let label_part = if label.is_empty() { - "".to_string() - } else if in_source { - color.paint(&format!(": {}", self.format_label(&annotation.label))) - } else { - format!(": {}", self.format_label(&annotation.label)) - }; - if continuation { - let indent = formatted_type.len() + 2; - return format!("{}{}", repeat_char(' ', indent), label); - } - if !formatted_type.is_empty() { - format!("{}{}", color.paint(&formatted_type), label_part) - } else { - label - } - } - - fn format_source_line(&self, line: &DisplaySourceLine) -> Option<String> { - match line { - DisplaySourceLine::Empty => None, - DisplaySourceLine::Content { text, .. } => Some(format!(" {}", text)), - DisplaySourceLine::Annotation { - range, - annotation, - annotation_type, - annotation_part, - } => { - let indent_char = match annotation_part { - DisplayAnnotationPart::Standalone => ' ', - DisplayAnnotationPart::LabelContinuation => ' ', - DisplayAnnotationPart::Consequitive => ' ', - DisplayAnnotationPart::MultilineStart => '_', - DisplayAnnotationPart::MultilineEnd => '_', - }; - let mark = match annotation_type { - DisplayAnnotationType::Error => '^', - DisplayAnnotationType::Warning => '-', - DisplayAnnotationType::Info => '-', - DisplayAnnotationType::Note => '-', - DisplayAnnotationType::Help => '-', - DisplayAnnotationType::None => ' ', - }; - let color = self.get_annotation_style(annotation_type); - let indent_length = match annotation_part { - DisplayAnnotationPart::LabelContinuation => range.1, - DisplayAnnotationPart::Consequitive => range.1, - _ => range.0, - }; - let indent = color.paint(&repeat_char(indent_char, indent_length + 1)); - let marks = color.paint(&repeat_char(mark, range.1 - indent_length)); - let annotation = self.format_annotation( - annotation, - annotation_part == &DisplayAnnotationPart::LabelContinuation, - true, - ); - if annotation.is_empty() { - return Some(format!("{}{}", indent, marks)); - } - Some(format!("{}{} {}", indent, marks, color.paint(&annotation))) - } - } - } - - fn format_lineno(&self, lineno: Option<usize>, lineno_width: usize) -> String { - match lineno { - Some(n) => format!("{:>width$}", n, width = lineno_width), - None => repeat_char(' ', lineno_width), - } - } - - fn format_raw_line(&self, line: &DisplayRawLine, lineno_width: usize) -> String { - match line { - DisplayRawLine::Origin { - path, - pos, - header_type, - } => { - let header_sigil = match header_type { - DisplayHeaderType::Initial => "-->", - DisplayHeaderType::Continuation => ":::", - }; - let lineno_color = self.stylesheet.get_style(StyleClass::LineNo); - - if let Some((col, row)) = pos { - format!( - "{}{} {}:{}:{}", - repeat_char(' ', lineno_width), - lineno_color.paint(header_sigil), - path, - col, - row - ) - } else { - format!( - "{}{} {}", - repeat_char(' ', lineno_width), - lineno_color.paint(header_sigil), - path - ) - } - } - DisplayRawLine::Annotation { - annotation, - source_aligned, - continuation, - } => { - if *source_aligned { - if *continuation { - format!( - "{}{}", - repeat_char(' ', lineno_width + 3), - self.format_annotation(annotation, *continuation, false) - ) - } else { - let lineno_color = self.stylesheet.get_style(StyleClass::LineNo); - format!( - "{} {} {}", - repeat_char(' ', lineno_width), - lineno_color.paint("="), - self.format_annotation(annotation, *continuation, false) - ) - } - } else { - self.format_annotation(annotation, *continuation, false) - } - } - } - } - - fn format_line( - &self, - dl: &DisplayLine, - lineno_width: usize, - inline_marks_width: usize, - ) -> String { - match dl { - DisplayLine::Source { - lineno, - inline_marks, - line, - } => { - let lineno = if self.anonymized_line_numbers && lineno.is_some() { - Self::ANONYMIZED_LINE_NUM.to_string() - } else { - self.format_lineno(*lineno, lineno_width) - }; - let marks = self.format_inline_marks(inline_marks, inline_marks_width); - let lf = self.format_source_line(line); - let lineno_color = self.stylesheet.get_style(StyleClass::LineNo); - - let mut prefix = lineno_color.paint(&format!("{} |", lineno)); - - match lf { - Some(lf) => { - if !marks.is_empty() { - prefix.push_str(&format!(" {}", marks)); - } - format!("{}{}", prefix, lf) - } - None => { - if !marks.trim().is_empty() { - prefix.push_str(&format!(" {}", marks)); - } - prefix - } - } - } - DisplayLine::Fold { inline_marks } => { - let marks = self.format_inline_marks(inline_marks, inline_marks_width); - let indent = lineno_width; - if marks.trim().is_empty() { - String::from("...") - } else { - format!("...{}{}", repeat_char(' ', indent), marks) - } - } - DisplayLine::Raw(line) => self.format_raw_line(line, lineno_width), - } - } - - fn format_inline_marks( - &self, - inline_marks: &[DisplayMark], - inline_marks_width: usize, - ) -> String { - format!( - "{}{}", - " ".repeat(inline_marks_width - inline_marks.len()), - inline_marks - .iter() - .map(|mark| { - let sigil = match mark.mark_type { - DisplayMarkType::AnnotationThrough => "|", - DisplayMarkType::AnnotationStart => "/", - }; - let color = self.get_annotation_style(&mark.annotation_type); - color.paint(sigil) - }) - .collect::<Vec<String>>() - .join(""), - ) - } -} diff --git a/vendor/annotate-snippets-0.6.1/src/formatter/style.rs b/vendor/annotate-snippets-0.6.1/src/formatter/style.rs deleted file mode 100644 index c1b90467e3..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/formatter/style.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! Set of structures required to implement a stylesheet for -//! [DisplayListFormatter](super::DisplayListFormatter). -//! -//! In order to provide additional styling information for the -//! formatter, a structs can implement `Stylesheet` and `Style` -//! traits. -//! -//! Example: -//! -//! ``` -//! use annotate_snippets::formatter::style::{Stylesheet, StyleClass, Style}; -//! -//! struct HTMLStyle { -//! prefix: String, -//! postfix: String, -//! }; -//! -//! impl HTMLStyle { -//! fn new(prefix: &str, postfix: &str) -> Self { -//! HTMLStyle { -//! prefix: prefix.into(), -//! postfix: postfix.into() -//! } -//! } -//! }; -//! -//! impl Style for HTMLStyle { -//! fn paint(&self, text: &str) -> String { -//! format!("{}{}{}", self.prefix, text, self.postfix) -//! } -//! -//! fn bold(&self) -> Box<Style> { -//! Box::new(HTMLStyle { -//! prefix: format!("{}<b>", self.prefix), -//! postfix: format!("</b>{}", self.postfix), -//! }) -//! } -//! } -//! -//! struct HTMLStylesheet {}; -//! -//! -//! impl Stylesheet for HTMLStylesheet { -//! fn get_style(&self, class: StyleClass) -> Box<Style> { -//! let s = match class { -//! StyleClass::Error => HTMLStyle::new("<span style='color:red'>", "</span>"), -//! StyleClass::Warning => HTMLStyle::new("<span style='color:orange'>", "</span>"), -//! StyleClass::Info => HTMLStyle::new("<span style='color:yellow'>", "</span>"), -//! StyleClass::Note => HTMLStyle::new("<span style='color:blue'>", "</span>"), -//! StyleClass::Help => HTMLStyle::new("<span style='color:green'>", "</span>"), -//! StyleClass::LineNo => HTMLStyle::new("<strong>", "</strong>"), -//! StyleClass::Emphasis => HTMLStyle::new("<i>", "</i>"), -//! StyleClass::None => HTMLStyle::new("", ""), -//! }; -//! Box::new(s) -//! } -//! } -//! ``` - -/// StyleClass is a collection of named variants of style classes -/// that DisplayListFormatter uses. -pub enum StyleClass { - /// Message indicating an error. - Error, - /// Message indicating a warning. - Warning, - /// Message indicating an information. - Info, - /// Message indicating a note. - Note, - /// Message indicating a help. - Help, - - /// Style for line numbers. - LineNo, - - /// Parts of the text that are to be emphasised. - Emphasis, - - /// Parts of the text that are regular. Usually a no-op. - None, -} - -/// This trait implements a return value for the `Stylesheet::get_style`. -pub trait Style { - /// The method used by the DisplayListFormatter to style the message. - fn paint(&self, text: &str) -> String; - /// The method used by the DisplayListFormatter to display the message - /// in bold font. - fn bold(&self) -> Box<dyn Style>; -} - -/// Trait to annotate structs that can provide `Style` implementations for -/// every `StyleClass` variant. -pub trait Stylesheet { - /// Returns a `Style` implementer based on the requested `StyleClass` variant. - fn get_style(&self, class: StyleClass) -> Box<dyn Style>; -} diff --git a/vendor/annotate-snippets-0.6.1/src/lib.rs b/vendor/annotate-snippets-0.6.1/src/lib.rs deleted file mode 100644 index 46b25e1566..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -#![deny(rust_2018_idioms)] - -//! A library for formatting of text or programming code snippets. -//! -//! It's primary purpose is to build an ASCII-graphical representation of the snippet -//! with annotations. -//! -//! # Example -//! -//! ```text -//! error[E0308]: mismatched types -//! --> src/format.rs:52:1 -//! | -//! 51 | ) -> Option<String> { -//! | -------------- expected `Option<String>` because of return type -//! 52 | / for ann in annotations { -//! 53 | | match (ann.range.0, ann.range.1) { -//! 54 | | (None, None) => continue, -//! 55 | | (Some(start), Some(end)) if start > end_index => continue, -//! ... | -//! 71 | | } -//! 72 | | } -//! | |_____^ expected enum `std::option::Option`, found () -//! ``` -//! -//! The crate uses a three stage process with two conversions between states: -//! -//! ```text -//! Snippet --> DisplayList --> String -//! ``` -//! -//! The input type - [Snippet](self::snippet) is a structure designed -//! to align with likely output from any parser whose code snippet is to be -//! annotated. -//! -//! The middle structure - [DisplayList](self::display_list) is a -//! structure designed to store the snippet data converted into a vector -//! of lines containing semantic information about each line. -//! This structure is the easiest to manipulate and organize. -//! -//! Finally, [DisplayListFormatter](self::formatter::DisplayListFormatter) is -//! used to format the `DisplayList` using a `Stylesheet` into a final `String` output. -//! -//! A user of the crate may choose to provide their own equivalent of the input -//! structure with an `Into<DisplayList>` trait. -//! -//! A user of the crate may also choose to provide their own formatter logic, -//! to convert a `DisplayList` into a `String`, or just a `Stylesheet` to -//! use the crate's formatting logic, but with a custom stylesheet. - -pub mod display_list; -pub mod formatter; -pub mod snippet; -pub mod stylesheets; diff --git a/vendor/annotate-snippets-0.6.1/src/snippet.rs b/vendor/annotate-snippets-0.6.1/src/snippet.rs deleted file mode 100644 index 6566b0f6e1..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/snippet.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Structures used as an input for the library. -//! -//! Example: -//! -//! ``` -//! use annotate_snippets::snippet::*; -//! -//! Snippet { -//! title: Some(Annotation { -//! label: Some("mismatched types".to_string()), -//! id: None, -//! annotation_type: AnnotationType::Error, -//! }), -//! footer: vec![], -//! slices: vec![ -//! Slice { -//! source: "Foo".to_string(), -//! line_start: 51, -//! origin: Some("src/format.rs".to_string()), -//! fold: false, -//! annotations: vec![], -//! }, -//! Slice { -//! source: "Faa".to_string(), -//! line_start: 129, -//! origin: Some("src/display.rs".to_string()), -//! fold: false, -//! annotations: vec![], -//! }, -//! ], -//! }; -//! ``` -/// Primary structure provided for formatting -#[derive(Debug, Clone)] -pub struct Snippet { - pub title: Option<Annotation>, - pub footer: Vec<Annotation>, - pub slices: Vec<Slice>, -} - -/// Structure containing the slice of text to be annotated and -/// basic information about the location of the slice. -#[derive(Debug, Clone)] -pub struct Slice { - pub source: String, - pub line_start: usize, - pub origin: Option<String>, - pub annotations: Vec<SourceAnnotation>, - /// If set explicitly to `true`, the snippet will fold - /// parts of the slice that don't contain any annotations. - pub fold: bool, -} - -/// Types of annotations. -#[derive(Debug, Clone, Copy)] -pub enum AnnotationType { - /// Error annotations are displayed using red color and "^" character. - Error, - /// Warning annotations are displayed using blue color and "-" character. - Warning, - Info, - Note, - Help, -} - -/// An annotation for a `Slice`. -#[derive(Debug, Clone)] -pub struct SourceAnnotation { - pub range: (usize, usize), - pub label: String, - pub annotation_type: AnnotationType, -} - -/// An annotation for a `Snippet`. -#[derive(Debug, Clone)] -pub struct Annotation { - /// Identifier of the annotation. Usually error code like "E0308". - pub id: Option<String>, - pub label: Option<String>, - pub annotation_type: AnnotationType, -} diff --git a/vendor/annotate-snippets-0.6.1/src/stylesheets/color.rs b/vendor/annotate-snippets-0.6.1/src/stylesheets/color.rs deleted file mode 100644 index f0a5d9ce43..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/stylesheets/color.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::formatter::style::{Style, StyleClass, Stylesheet}; - -use ansi_term::Color::Fixed; -use ansi_term::Style as AnsiTermStyle; - -struct AnsiTermStyleWrapper { - style: AnsiTermStyle, -} - -impl Style for AnsiTermStyleWrapper { - fn paint(&self, text: &str) -> String { - format!("{}", self.style.paint(text)) - } - - fn bold(&self) -> Box<dyn Style> { - Box::new(AnsiTermStyleWrapper { - style: self.style.clone(), - }) - } -} - -pub struct AnsiTermStylesheet {} - -impl Stylesheet for AnsiTermStylesheet { - fn get_style(&self, class: StyleClass) -> Box<dyn Style> { - let ansi_term_style = match class { - StyleClass::Error => Fixed(9).bold(), - StyleClass::Warning => Fixed(11).bold(), - StyleClass::Info => Fixed(12).bold(), - StyleClass::Note => AnsiTermStyle::new().bold(), - StyleClass::Help => Fixed(14).bold(), - - StyleClass::LineNo => Fixed(12).bold(), - - StyleClass::Emphasis => AnsiTermStyle::new().bold(), - - StyleClass::None => AnsiTermStyle::new(), - }; - Box::new(AnsiTermStyleWrapper { - style: ansi_term_style, - }) - } -} diff --git a/vendor/annotate-snippets-0.6.1/src/stylesheets/mod.rs b/vendor/annotate-snippets-0.6.1/src/stylesheets/mod.rs deleted file mode 100644 index 40aef52342..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/stylesheets/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! List of stylesheets that can be used by the `DisplayListFormatter`. -//! -//! The list depends on what optional dependencies the crate has been -//! compiled with. -//! -//! By default the `no_color` is available. If the crate gets compiled -//! with `ansi_term`, the `color` stylesheet is added. - -#[cfg(feature = "ansi_term")] -pub mod color; -pub mod no_color; diff --git a/vendor/annotate-snippets-0.6.1/src/stylesheets/no_color.rs b/vendor/annotate-snippets-0.6.1/src/stylesheets/no_color.rs deleted file mode 100644 index 608e4e5c0e..0000000000 --- a/vendor/annotate-snippets-0.6.1/src/stylesheets/no_color.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::formatter::style::{Style, StyleClass, Stylesheet}; - -pub struct NoOpStyle {} - -impl Style for NoOpStyle { - fn paint(&self, text: &str) -> String { - text.to_string() - } - - fn bold(&self) -> Box<dyn Style> { - Box::new(NoOpStyle {}) - } -} - -pub struct NoColorStylesheet {} - -impl Stylesheet for NoColorStylesheet { - fn get_style(&self, _class: StyleClass) -> Box<dyn Style> { - Box::new(NoOpStyle {}) - } -} diff --git a/vendor/annotate-snippets-0.6.1/tests/diff/mod.rs b/vendor/annotate-snippets-0.6.1/tests/diff/mod.rs deleted file mode 100644 index 7032e71cc3..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/diff/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -use ansi_term::Color::{Black, Green, Red}; -use difference::{Changeset, Difference}; - -pub fn get_diff(left: &str, right: &str) -> String { - let mut output = String::new(); - - let Changeset { diffs, .. } = Changeset::new(left, right, "\n"); - - for i in 0..diffs.len() { - match diffs[i] { - Difference::Same(ref x) => { - output += &format!(" {}\n", x); - } - Difference::Add(ref x) => { - match diffs[i - 1] { - Difference::Rem(ref y) => { - output += &format!("{}", Green.paint("+")); - let Changeset { diffs, .. } = Changeset::new(y, x, " "); - for c in diffs { - match c { - Difference::Same(ref z) => { - output += &format!("{} ", Green.paint(z.as_str())); - } - Difference::Add(ref z) => { - output += &format!("{} ", Black.on(Green).paint(z.as_str())); - } - _ => (), - } - } - output += "\n"; - } - _ => { - output += &format!("+{}\n", Green.paint(x.as_str())); - } - }; - } - Difference::Rem(ref x) => { - output += &format!("-{}\n", Red.paint(x.as_str())); - } - } - } - return output; -} diff --git a/vendor/annotate-snippets-0.6.1/tests/dl_from_snippet.rs b/vendor/annotate-snippets-0.6.1/tests/dl_from_snippet.rs deleted file mode 100644 index 2eb03134a2..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/dl_from_snippet.rs +++ /dev/null @@ -1,256 +0,0 @@ -use annotate_snippets::display_list as dl; -use annotate_snippets::snippet; - -#[test] -fn test_format_title() { - let input = snippet::Snippet { - title: Some(snippet::Annotation { - id: Some("E0001".to_string()), - label: Some("This is a title".to_string()), - annotation_type: snippet::AnnotationType::Error, - }), - footer: vec![], - slices: vec![], - }; - let output = dl::DisplayList { - body: vec![dl::DisplayLine::Raw(dl::DisplayRawLine::Annotation { - annotation: dl::Annotation { - annotation_type: dl::DisplayAnnotationType::Error, - id: Some("E0001".to_string()), - label: vec![dl::DisplayTextFragment { - content: "This is a title".to_string(), - style: dl::DisplayTextStyle::Emphasis, - }], - }, - source_aligned: false, - continuation: false, - })], - }; - assert_eq!(dl::DisplayList::from(input), output); -} - -#[test] -fn test_format_slice() { - let input = snippet::Snippet { - title: None, - footer: vec![], - slices: vec![snippet::Slice { - source: "This is line 1\nThis is line 2".to_string(), - line_start: 5402, - origin: None, - annotations: vec![], - fold: false, - }], - }; - let output = dl::DisplayList { - body: vec![ - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - dl::DisplayLine::Source { - lineno: Some(5402), - inline_marks: vec![], - line: dl::DisplaySourceLine::Content { - text: "This is line 1".to_string(), - range: (0, 15), - }, - }, - dl::DisplayLine::Source { - lineno: Some(5403), - inline_marks: vec![], - line: dl::DisplaySourceLine::Content { - text: "This is line 2".to_string(), - range: (16, 31), - }, - }, - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - ], - }; - assert_eq!(dl::DisplayList::from(input), output); -} - -#[test] -fn test_format_slices_continuation() { - let input = snippet::Snippet { - title: None, - footer: vec![], - slices: vec![ - snippet::Slice { - source: "This is slice 1".to_string(), - line_start: 5402, - origin: Some("file1.rs".to_string()), - annotations: vec![], - fold: false, - }, - snippet::Slice { - source: "This is slice 2".to_string(), - line_start: 2, - origin: Some("file2.rs".to_string()), - annotations: vec![], - fold: false, - }, - ], - }; - let output = dl::DisplayList { - body: vec![ - dl::DisplayLine::Raw(dl::DisplayRawLine::Origin { - path: "file1.rs".to_string(), - pos: None, - header_type: dl::DisplayHeaderType::Initial, - }), - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - dl::DisplayLine::Source { - lineno: Some(5402), - inline_marks: vec![], - line: dl::DisplaySourceLine::Content { - text: "This is slice 1".to_string(), - range: (0, 16), - }, - }, - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - dl::DisplayLine::Raw(dl::DisplayRawLine::Origin { - path: "file2.rs".to_string(), - pos: None, - header_type: dl::DisplayHeaderType::Continuation, - }), - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - dl::DisplayLine::Source { - lineno: Some(2), - inline_marks: vec![], - line: dl::DisplaySourceLine::Content { - text: "This is slice 2".to_string(), - range: (0, 16), - }, - }, - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - ], - }; - assert_eq!(dl::DisplayList::from(input), output); -} - -#[test] -fn test_format_slice_annotation_standalone() { - let input = snippet::Snippet { - title: None, - footer: vec![], - slices: vec![snippet::Slice { - source: "This is line 1\nThis is line 2".to_string(), - line_start: 5402, - origin: None, - annotations: vec![snippet::SourceAnnotation { - range: (22, 24), - label: "Test annotation".to_string(), - annotation_type: snippet::AnnotationType::Info, - }], - fold: false, - }], - }; - let output = dl::DisplayList { - body: vec![ - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - dl::DisplayLine::Source { - lineno: Some(5402), - inline_marks: vec![], - line: dl::DisplaySourceLine::Content { - text: "This is line 1".to_string(), - range: (0, 15), - }, - }, - dl::DisplayLine::Source { - lineno: Some(5403), - inline_marks: vec![], - line: dl::DisplaySourceLine::Content { - text: "This is line 2".to_string(), - range: (16, 31), - }, - }, - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Annotation { - annotation: dl::Annotation { - annotation_type: dl::DisplayAnnotationType::Info, - id: None, - label: vec![dl::DisplayTextFragment { - content: "Test annotation".to_string(), - style: dl::DisplayTextStyle::Regular, - }], - }, - range: (6, 8), - annotation_type: dl::DisplayAnnotationType::Info, - annotation_part: dl::DisplayAnnotationPart::Standalone, - }, - }, - dl::DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: dl::DisplaySourceLine::Empty, - }, - ], - }; - assert_eq!(dl::DisplayList::from(input), output); -} - -#[test] -fn test_format_label() { - let input = snippet::Snippet { - title: None, - footer: vec![snippet::Annotation { - id: None, - label: Some("This __is__ a title".to_string()), - annotation_type: snippet::AnnotationType::Error, - }], - slices: vec![], - }; - let output = dl::DisplayList { - body: vec![dl::DisplayLine::Raw(dl::DisplayRawLine::Annotation { - annotation: dl::Annotation { - annotation_type: dl::DisplayAnnotationType::Error, - id: None, - label: vec![ - dl::DisplayTextFragment { - content: "This ".to_string(), - style: dl::DisplayTextStyle::Regular, - }, - dl::DisplayTextFragment { - content: "is".to_string(), - style: dl::DisplayTextStyle::Emphasis, - }, - dl::DisplayTextFragment { - content: " a title".to_string(), - style: dl::DisplayTextStyle::Regular, - }, - ], - }, - source_aligned: true, - continuation: false, - })], - }; - assert_eq!(dl::DisplayList::from(input), output); -} diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures.rs b/vendor/annotate-snippets-0.6.1/tests/fixtures.rs deleted file mode 100644 index e103b843ae..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures.rs +++ /dev/null @@ -1,57 +0,0 @@ -mod diff; -mod snippet; - -use crate::snippet::SnippetDef; -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; -use annotate_snippets::snippet::Snippet; -use glob::glob; -use std::error::Error; -use std::fs::File; -use std::io; -use std::io::prelude::*; -use std::path::Path; -use serde::Deserialize; - -fn read_file(path: &str) -> Result<String, io::Error> { - let mut f = File::open(path)?; - let mut s = String::new(); - (f.read_to_string(&mut s))?; - Ok(s.trim_end().to_string()) -} - -fn read_fixture<P: AsRef<Path>>(path: P) -> Result<Snippet, Box<Error>> { - #[derive(Deserialize)] - struct Wrapper(#[serde(with = "SnippetDef")] Snippet); - - let file = File::open(path)?; - let u = serde_yaml::from_reader(file).map(|Wrapper(a)| a)?; - Ok(u) -} - -#[test] -fn test_fixtures() { - for entry in glob("./tests/fixtures/no-color/**/*.yaml").expect("Failed to read glob pattern") { - let p = entry.expect("Error while getting an entry"); - let path_in = p.to_str().expect("Can't print path"); - - let path_out = path_in.replace(".yaml", ".txt"); - - let snippet = read_fixture(path_in).expect("Failed to read file"); - let expected_out = read_file(&path_out).expect("Failed to read file"); - - let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true, false); - let actual_out = dlf.format(&dl); - println!("{}", expected_out); - println!("{}", actual_out.trim_end()); - - assert_eq!( - expected_out, - actual_out.trim_end(), - "\n\n\nWhile parsing: {}\nThe diff is:\n\n\n{}\n\n\n", - path_in, - diff::get_diff(expected_out.as_str(), actual_out.as_str()) - ); - } -} diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.txt b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.txt deleted file mode 100644 index b90078470c..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.txt +++ /dev/null @@ -1,14 +0,0 @@ -error[E0308]: mismatched types - --> src/format.rs:51:5 - | -51 | ) -> Option<String> { - | -------------- expected `std::option::Option<std::string::String>` because of return type -52 | / for ann in annotations { -53 | | match (ann.range.0, ann.range.1) { -54 | | (None, None) => continue, -55 | | (Some(start), Some(end)) if start > end_index || end < start_index => continue, -... | -71 | | } -72 | | } - | |_____^ expected enum `std::option::Option`, found () - | diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.yaml b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.yaml deleted file mode 100644 index 6048e382b8..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation.yaml +++ /dev/null @@ -1,38 +0,0 @@ -slices: - - source: |- - ) -> Option<String> { - for ann in annotations { - match (ann.range.0, ann.range.1) { - (None, None) => continue, - (Some(start), Some(end)) if start > end_index || end < start_index => continue, - (Some(start), Some(end)) if start >= start_index && end <= end_index => { - let label = if let Some(ref label) = ann.label { - format!(" {}", label) - } else { - String::from("") - }; - - return Some(format!( - "{}{}{}", - " ".repeat(start - start_index), - "^".repeat(end - start), - label - )); - } - _ => continue, - } - } - line_start: 51 - origin: "src/format.rs" - fold: true - annotations: - - label: expected `std::option::Option<std::string::String>` because of return type - annotation_type: Warning - range: [5, 19] - - label: expected enum `std::option::Option`, found () - annotation_type: Error - range: [23, 786] -title: - label: mismatched types - id: E0308 - annotation_type: Error diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.txt b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.txt deleted file mode 100644 index 5234ee87ec..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.txt +++ /dev/null @@ -1,9 +0,0 @@ -error[E0027]: pattern does not mention fields `lineno`, `content` - --> src/display_list.rs:139:31 - | -139 | if let DisplayLine::Source { - | ________________________________^ -140 | | ref mut inline_marks, -141 | | } = body[body_idx] - | |_________________________^ missing fields `lineno`, `content` - | diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.yaml b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.yaml deleted file mode 100644 index bdbdb4c94c..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiline_annotation2.yaml +++ /dev/null @@ -1,16 +0,0 @@ -slices: - - source: |1 - if let DisplayLine::Source { - ref mut inline_marks, - } = body[body_idx] - line_start: 139 - origin: "src/display_list.rs" - fold: false - annotations: - - label: missing fields `lineno`, `content` - annotation_type: Error - range: [31, 129] -title: - label: pattern does not mention fields `lineno`, `content` - id: E0027 - annotation_type: Error diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.txt b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.txt deleted file mode 100644 index 26c677f7e0..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.txt +++ /dev/null @@ -1,14 +0,0 @@ - | - 96 | fn add_title_line(result: &mut Vec<String>, main_annotation: Option<&Annotation>) { - 97 | if let Some(annotation) = main_annotation { - | ^^^^^^^^^^ Variable defined here - 98 | result.push(format_title_line( - 99 | &annotation.annotation_type, - | ^^^^^^^^^^ Referenced here -100 | None, -101 | &annotation.label, - | ^^^^^^^^^^ Referenced again here -102 | )); -103 | } -104 | } - | diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.yaml b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.yaml deleted file mode 100644 index 5bc71bb752..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/multiple_annotations.yaml +++ /dev/null @@ -1,23 +0,0 @@ -slices: - - source: |- - fn add_title_line(result: &mut Vec<String>, main_annotation: Option<&Annotation>) { - if let Some(annotation) = main_annotation { - result.push(format_title_line( - &annotation.annotation_type, - None, - &annotation.label, - )); - } - } - line_start: 96 - annotations: - - label: Variable defined here - annotation_type: Error - range: [101, 111] - - label: Referenced here - annotation_type: Error - range: [187, 197] - - label: Referenced again here - annotation_type: Error - range: [248, 258] -title: null diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.txt b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.txt deleted file mode 100644 index a5a3136997..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.txt +++ /dev/null @@ -1,9 +0,0 @@ -error: expected one of `.`, `;`, `?`, or an operator, found `for` - --> src/format_color.rs:171:8 - | -169 | }) - | - expected one of `.`, `;`, `?`, or an operator here -170 | -171 | for line in &self.body { - | ^^^ unexpected token - | diff --git a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.yaml b/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.yaml deleted file mode 100644 index db3862cc8f..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/fixtures/no-color/simple.yaml +++ /dev/null @@ -1,17 +0,0 @@ -slices: - - source: |1 - }) - - for line in &self.body { - line_start: 169 - origin: src/format_color.rs - annotations: - - label: unexpected token - annotation_type: Error - range: [22, 25] - - label: expected one of `.`, `;`, `?`, or an operator here - annotation_type: Warning - range: [10, 11] -title: - label: expected one of `.`, `;`, `?`, or an operator, found `for` - annotation_type: Error diff --git a/vendor/annotate-snippets-0.6.1/tests/formatter.rs b/vendor/annotate-snippets-0.6.1/tests/formatter.rs deleted file mode 100644 index 9d224e9aad..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/formatter.rs +++ /dev/null @@ -1,551 +0,0 @@ -use annotate_snippets::display_list::*; -use annotate_snippets::formatter::DisplayListFormatter; - -#[test] -fn test_source_empty() { - let dl = DisplayList::from(vec![DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Empty, - }]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), " |"); -} - -#[test] -fn test_source_content() { - let dl = DisplayList::from(vec![ - DisplayLine::Source { - lineno: Some(56), - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: "This is an example".to_string(), - range: (0, 19), - }, - }, - DisplayLine::Source { - lineno: Some(57), - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: "of content lines".to_string(), - range: (0, 19), - }, - }, - ]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!( - dlf.format(&dl), - "56 | This is an example\n57 | of content lines" - ); -} - -#[test] -fn test_source_annotation_standalone_singleline() { - let dl = DisplayList::from(vec![DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::None, - id: None, - label: vec![DisplayTextFragment { - content: String::from("Example string"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Error, - annotation_part: DisplayAnnotationPart::Standalone, - }, - }]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), " | ^^^^^ Example string"); -} - -#[test] -fn test_source_annotation_standalone_multiline() { - let dl = DisplayList::from(vec![ - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Help, - id: None, - label: vec![DisplayTextFragment { - content: String::from("Example string"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Warning, - annotation_part: DisplayAnnotationPart::Standalone, - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Help, - id: None, - label: vec![DisplayTextFragment { - content: String::from("Second line"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Warning, - annotation_part: DisplayAnnotationPart::LabelContinuation, - }, - }, - ]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!( - dlf.format(&dl), - " | ----- help: Example string\n | Second line" - ); -} - -#[test] -fn test_source_annotation_standalone_multi_annotation() { - let dl = DisplayList::from(vec![ - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Info, - id: None, - label: vec![DisplayTextFragment { - content: String::from("Example string"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Note, - annotation_part: DisplayAnnotationPart::Standalone, - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Info, - id: None, - label: vec![DisplayTextFragment { - content: String::from("Second line"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Note, - annotation_part: DisplayAnnotationPart::LabelContinuation, - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Warning, - id: None, - label: vec![DisplayTextFragment { - content: String::from("This is a note"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Note, - annotation_part: DisplayAnnotationPart::Consequitive, - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Warning, - id: None, - label: vec![DisplayTextFragment { - content: String::from("Second line of the warning"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Note, - annotation_part: DisplayAnnotationPart::LabelContinuation, - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Info, - id: None, - label: vec![DisplayTextFragment { - content: String::from("This is an info"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Info, - annotation_part: DisplayAnnotationPart::Standalone, - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 5), - annotation: Annotation { - annotation_type: DisplayAnnotationType::Help, - id: None, - label: vec![DisplayTextFragment { - content: String::from("This is help"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::Help, - annotation_part: DisplayAnnotationPart::Standalone, - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Annotation { - range: (0, 0), - annotation: Annotation { - annotation_type: DisplayAnnotationType::None, - id: None, - label: vec![DisplayTextFragment { - content: String::from("This is an annotation of type none"), - style: DisplayTextStyle::Regular, - }], - }, - annotation_type: DisplayAnnotationType::None, - annotation_part: DisplayAnnotationPart::Standalone, - }, - }, - ]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), " | ----- info: Example string\n | Second line\n | warning: This is a note\n | Second line of the warning\n | ----- info: This is an info\n | ----- help: This is help\n | This is an annotation of type none"); -} - -#[test] -fn test_fold_line() { - let dl = DisplayList::from(vec![ - DisplayLine::Source { - lineno: Some(5), - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: "This is line 5".to_string(), - range: (0, 19), - }, - }, - DisplayLine::Fold { - inline_marks: vec![], - }, - DisplayLine::Source { - lineno: Some(10021), - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: "... and now we're at line 10021".to_string(), - range: (0, 19), - }, - }, - ]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!( - dlf.format(&dl), - " 5 | This is line 5\n...\n10021 | ... and now we're at line 10021" - ); -} - -#[test] -fn test_raw_origin_initial_nopos() { - let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { - path: "src/test.rs".to_string(), - pos: None, - header_type: DisplayHeaderType::Initial, - })]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), "--> src/test.rs"); -} - -#[test] -fn test_raw_origin_initial_pos() { - let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { - path: "src/test.rs".to_string(), - pos: Some((23, 15)), - header_type: DisplayHeaderType::Initial, - })]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), "--> src/test.rs:23:15"); -} - -#[test] -fn test_raw_origin_continuation() { - let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { - path: "src/test.rs".to_string(), - pos: Some((23, 15)), - header_type: DisplayHeaderType::Continuation, - })]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), "::: src/test.rs:23:15"); -} - -#[test] -fn test_raw_annotation_unaligned() { - let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::Error, - id: Some("E0001".to_string()), - label: vec![DisplayTextFragment { - content: String::from("This is an error"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: false, - continuation: false, - })]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), "error[E0001]: This is an error"); -} - -#[test] -fn test_raw_annotation_unaligned_multiline() { - let dl = DisplayList::from(vec![ - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::Warning, - id: Some("E0001".to_string()), - label: vec![DisplayTextFragment { - content: String::from("This is an error"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: false, - continuation: false, - }), - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::Warning, - id: Some("E0001".to_string()), - label: vec![DisplayTextFragment { - content: String::from("Second line of the error"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: false, - continuation: true, - }), - ]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!( - dlf.format(&dl), - "warning[E0001]: This is an error\n Second line of the error" - ); -} - -#[test] -fn test_raw_annotation_aligned() { - let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::Error, - id: Some("E0001".to_string()), - label: vec![DisplayTextFragment { - content: String::from("This is an error"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: true, - continuation: false, - })]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), " = error[E0001]: This is an error"); -} - -#[test] -fn test_raw_annotation_aligned_multiline() { - let dl = DisplayList::from(vec![ - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::Warning, - id: Some("E0001".to_string()), - label: vec![DisplayTextFragment { - content: String::from("This is an error"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: true, - continuation: false, - }), - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::Warning, - id: Some("E0001".to_string()), - label: vec![DisplayTextFragment { - content: String::from("Second line of the error"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: true, - continuation: true, - }), - ]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!( - dlf.format(&dl), - " = warning[E0001]: This is an error\n Second line of the error" - ); -} - -#[test] -fn test_different_annotation_types() { - let dl = DisplayList::from(vec![ - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::Note, - id: None, - label: vec![DisplayTextFragment { - content: String::from("This is a note"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: false, - continuation: false, - }), - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::None, - id: None, - label: vec![DisplayTextFragment { - content: String::from("This is just a string"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: false, - continuation: false, - }), - DisplayLine::Raw(DisplayRawLine::Annotation { - annotation: Annotation { - annotation_type: DisplayAnnotationType::None, - id: None, - label: vec![DisplayTextFragment { - content: String::from("Second line of none type annotation"), - style: DisplayTextStyle::Regular, - }], - }, - source_aligned: false, - continuation: true, - }), - ]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!( - dlf.format(&dl), - "note: This is a note\nThis is just a string\n Second line of none type annotation", - ); -} - -#[test] -fn test_inline_marks_empty_line() { - let dl = DisplayList::from(vec![DisplayLine::Source { - lineno: None, - inline_marks: vec![DisplayMark { - mark_type: DisplayMarkType::AnnotationThrough, - annotation_type: DisplayAnnotationType::Error, - }], - line: DisplaySourceLine::Empty, - }]); - - let dlf = DisplayListFormatter::new(false, false); - - assert_eq!(dlf.format(&dl), " | |",); -} - -#[test] -fn test_anon_lines() { - let dl = DisplayList::from(vec![ - DisplayLine::Source { - lineno: Some(56), - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: "This is an example".to_string(), - range: (0, 19), - }, - }, - DisplayLine::Source { - lineno: Some(57), - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: "of content lines".to_string(), - range: (0, 19), - }, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Empty, - }, - DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Content { - text: "abc".to_string(), - range: (0, 19), - }, - }, - ]); - - let dlf = DisplayListFormatter::new(false, true); - - assert_eq!( - dlf.format(&dl), - "LL | This is an example\nLL | of content lines\n |\n | abc" - ); -} - -#[test] -fn test_raw_origin_initial_pos_anon_lines() { - let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { - path: "src/test.rs".to_string(), - pos: Some((23, 15)), - header_type: DisplayHeaderType::Initial, - })]); - - let dlf = DisplayListFormatter::new(false, true); - - // Using anonymized_line_numbers should not affect the inital position - assert_eq!(dlf.format(&dl), "--> src/test.rs:23:15"); -} diff --git a/vendor/annotate-snippets-0.6.1/tests/snippet/mod.rs b/vendor/annotate-snippets-0.6.1/tests/snippet/mod.rs deleted file mode 100644 index a08e3fcc34..0000000000 --- a/vendor/annotate-snippets-0.6.1/tests/snippet/mod.rs +++ /dev/null @@ -1,105 +0,0 @@ -use serde::{Serialize, Deserialize, Deserializer}; - -use annotate_snippets::snippet::{ - Annotation, AnnotationType, Slice, Snippet, SourceAnnotation, -}; - -#[derive(Deserialize)] -#[serde(remote = "Snippet")] -pub struct SnippetDef { - #[serde(deserialize_with = "deserialize_annotation")] - #[serde(default)] - pub title: Option<Annotation>, - #[serde(deserialize_with = "deserialize_annotations")] - #[serde(default)] - pub footer: Vec<Annotation>, - #[serde(deserialize_with = "deserialize_slices")] - pub slices: Vec<Slice>, -} - -fn deserialize_slices<'de, D>(deserializer: D) -> Result<Vec<Slice>, D::Error> -where - D: Deserializer<'de>, -{ - #[derive(Deserialize)] - struct Wrapper(#[serde(with = "SliceDef")] Slice); - - let v = Vec::deserialize(deserializer)?; - Ok(v.into_iter().map(|Wrapper(a)| a).collect()) -} - -fn deserialize_annotation<'de, D>(deserializer: D) -> Result<Option<Annotation>, D::Error> -where - D: Deserializer<'de>, -{ - #[derive(Deserialize)] - struct Wrapper(#[serde(with = "AnnotationDef")] Annotation); - - Option::<Wrapper>::deserialize(deserializer) - .map(|opt_wrapped: Option<Wrapper>| opt_wrapped.map(|wrapped: Wrapper| wrapped.0)) -} - -fn deserialize_annotations<'de, D>(deserializer: D) -> Result<Vec<Annotation>, D::Error> -where - D: Deserializer<'de>, -{ - #[derive(Deserialize)] - struct Wrapper(#[serde(with = "AnnotationDef")] Annotation); - - let v = Vec::deserialize(deserializer)?; - Ok(v.into_iter().map(|Wrapper(a)| a).collect()) -} - -#[derive(Deserialize)] -#[serde(remote = "Slice")] -pub struct SliceDef { - pub source: String, - pub line_start: usize, - pub origin: Option<String>, - #[serde(deserialize_with = "deserialize_source_annotations")] - pub annotations: Vec<SourceAnnotation>, - #[serde(default)] - pub fold: bool, -} - -fn deserialize_source_annotations<'de, D>( - deserializer: D, -) -> Result<Vec<SourceAnnotation>, D::Error> -where - D: Deserializer<'de>, -{ - #[derive(Deserialize)] - struct Wrapper(#[serde(with = "SourceAnnotationDef")] SourceAnnotation); - - let v = Vec::deserialize(deserializer)?; - Ok(v.into_iter().map(|Wrapper(a)| a).collect()) -} - -#[derive(Serialize, Deserialize)] -#[serde(remote = "SourceAnnotation")] -pub struct SourceAnnotationDef { - pub range: (usize, usize), - pub label: String, - #[serde(with = "AnnotationTypeDef")] - pub annotation_type: AnnotationType, -} - -#[derive(Serialize, Deserialize)] -#[serde(remote = "Annotation")] -pub struct AnnotationDef { - pub id: Option<String>, - pub label: Option<String>, - #[serde(with = "AnnotationTypeDef")] - pub annotation_type: AnnotationType, -} - -#[allow(dead_code)] -#[derive(Serialize, Deserialize)] -#[serde(remote = "AnnotationType")] -enum AnnotationTypeDef { - Error, - Warning, - Info, - Note, - Help, -} diff --git a/vendor/anyhow/.cargo-checksum.json b/vendor/anyhow/.cargo-checksum.json index 1daaf9e673..a3a7c153e3 100644 --- a/vendor/anyhow/.cargo-checksum.json +++ b/vendor/anyhow/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"7b82bfe252749d8211792ba4a669c01f660ae3707acaa72e390812a85455198e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"5ae3beb5cb960dfe629cd02293a4ad678624b7ca1c104953912bd7606c2fd0c7","build.rs":"ffd5a7a8c9700328517abf11a3654c310c2da232f28841e0467c7e200fcd9221","src/backtrace.rs":"a82a8ffae2c68ee385dc78d8ec8cb6f3351234f0ad6af7e87df2371593e0f6aa","src/chain.rs":"1627608ce95c3484d26e1742a1b8b533b74c6159916b717bacffae3ae53731f9","src/context.rs":"559478ae785ce913523aa21358cc1561ef4b0b95c5c87675a77890364c0162fe","src/error.rs":"804481d6f89adfc518022e1e8f507d76e747c832f9a68d56dedd9df779fb393f","src/fmt.rs":"b825bc8b6e13fc565b42a159932081c79e72b4ac82307d0ac2c37738ce45ff72","src/kind.rs":"8481a8b7835eebb3859a8c32c217bf9c73543cfc62e3916b98d39af8b063125c","src/lib.rs":"5240f586154fcbadcadf88f4835cbe5969eadab668ff0f0fb686b58b9f898317","src/macros.rs":"88daf58370b2fcc93c43ebd5b9c1659bf5460c972681b63d89d51132126e5560","src/ptr.rs":"e0a57ec6d9f011a9c74cb3f484b976f025593389a80ca111fb5bfce714e858b1","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":"828964b889abbeabcbcbb0dd92147039804a52cae2635590142a184158375f91","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"4b0cceae9e9b27fe2594e6c02bb3e3fd9965ed04498738e5877934dab807b50f"},"package":"afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"} \ No newline at end of file +{"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 diff --git a/vendor/anyhow/Cargo.toml b/vendor/anyhow/Cargo.toml index c36e376d49..09c3dbf1e7 100644 --- a/vendor/anyhow/Cargo.toml +++ b/vendor/anyhow/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "anyhow" -version = "1.0.38" +version = "1.0.40" authors = ["David Tolnay <dtolnay@gmail.com>"] description = "Flexible concrete Error type built on std::error::Error" documentation = "https://docs.rs/anyhow" @@ -24,6 +24,9 @@ repository = "https://github.com/dtolnay/anyhow" [package.metadata.docs.rs] rustdoc-args = ["--cfg", "doc_cfg"] targets = ["x86_64-unknown-linux-gnu"] +[dependencies.backtrace] +version = "0.3" +optional = true [dev-dependencies.futures] version = "0.3" default-features = false diff --git a/vendor/anyhow/README.md b/vendor/anyhow/README.md index 336f879939..c6eb0f1a1d 100644 --- a/vendor/anyhow/README.md +++ b/vendor/anyhow/README.md @@ -1,5 +1,5 @@ -Anyhow ¯\\\_(ツ)\_/¯ -========================= +Anyhow ¯\\\_(°ペ)\_/¯ +========================== [<img alt="github" src="https://img.shields.io/badge/github-dtolnay/anyhow-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/anyhow) [<img alt="crates.io" src="https://img.shields.io/crates/v/anyhow.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/anyhow) diff --git a/vendor/anyhow/build.rs b/vendor/anyhow/build.rs index a7dc8f2d03..df2e73bd82 100644 --- a/vendor/anyhow/build.rs +++ b/vendor/anyhow/build.rs @@ -4,6 +4,11 @@ use std::path::Path; use std::process::{Command, ExitStatus, Stdio}; use std::str; +#[cfg(all(feature = "backtrace", not(feature = "std")))] +compile_error! { + "`backtrace` feature without `std` feature is not supported" +} + // This code exercises the surface area that we expect of the std Backtrace // type. If the current toolchain is able to compile it, we go ahead and use // backtrace in anyhow. @@ -51,6 +56,10 @@ fn main() { if rustc < 38 { println!("cargo:rustc-cfg=anyhow_no_macro_reexport"); } + + if rustc < 51 { + println!("cargo:rustc-cfg=anyhow_no_ptr_addr_of"); + } } fn compile_probe() -> Option<ExitStatus> { diff --git a/vendor/anyhow/src/backtrace.rs b/vendor/anyhow/src/backtrace.rs index 01e33cb237..1fa20a6a12 100644 --- a/vendor/anyhow/src/backtrace.rs +++ b/vendor/anyhow/src/backtrace.rs @@ -1,17 +1,34 @@ #[cfg(backtrace)] -pub(crate) use std::backtrace::Backtrace; +pub(crate) use std::backtrace::{Backtrace, BacktraceStatus}; -#[cfg(not(backtrace))] +#[cfg(all(not(backtrace), feature = "backtrace"))] +pub(crate) use self::capture::{Backtrace, BacktraceStatus}; + +#[cfg(not(any(backtrace, feature = "backtrace")))] pub(crate) enum Backtrace {} #[cfg(backtrace)] +macro_rules! impl_backtrace { + () => { + std::backtrace::Backtrace + }; +} + +#[cfg(all(not(backtrace), feature = "backtrace"))] +macro_rules! impl_backtrace { + () => { + impl core::fmt::Debug + core::fmt::Display + }; +} + +#[cfg(any(backtrace, feature = "backtrace"))] macro_rules! backtrace { () => { - Some(Backtrace::capture()) + Some(crate::backtrace::Backtrace::capture()) }; } -#[cfg(not(backtrace))] +#[cfg(not(any(backtrace, feature = "backtrace")))] macro_rules! backtrace { () => { None @@ -23,14 +40,362 @@ macro_rules! backtrace_if_absent { ($err:expr) => { match $err.backtrace() { Some(_) => None, - None => Some(Backtrace::capture()), + None => backtrace!(), } }; } -#[cfg(all(feature = "std", not(backtrace)))] +#[cfg(all(feature = "std", not(backtrace), feature = "backtrace"))] +macro_rules! backtrace_if_absent { + ($err:expr) => { + backtrace!() + }; +} + +#[cfg(all(feature = "std", not(backtrace), not(feature = "backtrace")))] macro_rules! backtrace_if_absent { ($err:expr) => { None }; } + +#[cfg(all(not(backtrace), feature = "backtrace"))] +mod capture { + use backtrace::{BacktraceFmt, BytesOrWideString, Frame, PrintFmt, SymbolName}; + use core::cell::UnsafeCell; + use core::fmt::{self, Debug, Display}; + use core::sync::atomic::{AtomicUsize, Ordering}; + use std::borrow::Cow; + use std::env; + use std::path::{self, Path, PathBuf}; + use std::sync::Once; + + pub(crate) struct Backtrace { + inner: Inner, + } + + pub(crate) enum BacktraceStatus { + Unsupported, + Disabled, + Captured, + } + + enum Inner { + Unsupported, + Disabled, + Captured(LazilyResolvedCapture), + } + + struct Capture { + actual_start: usize, + resolved: bool, + frames: Vec<BacktraceFrame>, + } + + struct BacktraceFrame { + frame: Frame, + symbols: Vec<BacktraceSymbol>, + } + + struct BacktraceSymbol { + name: Option<Vec<u8>>, + filename: Option<BytesOrWide>, + lineno: Option<u32>, + colno: Option<u32>, + } + + enum BytesOrWide { + Bytes(Vec<u8>), + Wide(Vec<u16>), + } + + impl Debug for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str("<unsupported>"), + Inner::Disabled => return fmt.write_str("<disabled>"), + Inner::Captured(c) => c.force(), + }; + + let frames = &capture.frames[capture.actual_start..]; + + write!(fmt, "Backtrace ")?; + + let mut dbg = fmt.debug_list(); + + for frame in frames { + if frame.frame.ip().is_null() { + continue; + } + + dbg.entries(&frame.symbols); + } + + dbg.finish() + } + } + + impl Debug for BacktraceFrame { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut dbg = fmt.debug_list(); + dbg.entries(&self.symbols); + dbg.finish() + } + } + + impl Debug for BacktraceSymbol { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{{ ")?; + + if let Some(fn_name) = self.name.as_ref().map(|b| SymbolName::new(b)) { + write!(fmt, "fn: \"{:#}\"", fn_name)?; + } else { + write!(fmt, "fn: <unknown>")?; + } + + if let Some(fname) = self.filename.as_ref() { + write!(fmt, ", file: \"{:?}\"", fname)?; + } + + if let Some(line) = self.lineno { + write!(fmt, ", line: {:?}", line)?; + } + + write!(fmt, " }}") + } + } + + impl Debug for BytesOrWide { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + output_filename( + fmt, + match self { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }, + PrintFmt::Short, + env::current_dir().as_ref().ok(), + ) + } + } + + impl Backtrace { + fn enabled() -> bool { + static ENABLED: AtomicUsize = AtomicUsize::new(0); + match ENABLED.load(Ordering::SeqCst) { + 0 => {} + 1 => return false, + _ => return true, + } + let enabled = match env::var_os("RUST_LIB_BACKTRACE") { + Some(s) => s != "0", + None => match env::var_os("RUST_BACKTRACE") { + Some(s) => s != "0", + None => false, + }, + }; + ENABLED.store(enabled as usize + 1, Ordering::SeqCst); + enabled + } + + #[inline(never)] // want to make sure there's a frame here to remove + pub(crate) fn capture() -> Backtrace { + if Backtrace::enabled() { + Backtrace::create(Backtrace::capture as usize) + } else { + let inner = Inner::Disabled; + Backtrace { inner } + } + } + + // Capture a backtrace which starts just before the function addressed + // by `ip` + fn create(ip: usize) -> Backtrace { + let mut frames = Vec::new(); + let mut actual_start = None; + backtrace::trace(|frame| { + frames.push(BacktraceFrame { + frame: frame.clone(), + symbols: Vec::new(), + }); + if frame.symbol_address() as usize == ip && actual_start.is_none() { + actual_start = Some(frames.len() + 1); + } + true + }); + + // If no frames came out assume that this is an unsupported platform + // since `backtrace` doesn't provide a way of learning this right + // now, and this should be a good enough approximation. + let inner = if frames.is_empty() { + Inner::Unsupported + } else { + Inner::Captured(LazilyResolvedCapture::new(Capture { + actual_start: actual_start.unwrap_or(0), + frames, + resolved: false, + })) + }; + + Backtrace { inner } + } + + pub(crate) fn status(&self) -> BacktraceStatus { + match self.inner { + Inner::Unsupported => BacktraceStatus::Unsupported, + Inner::Disabled => BacktraceStatus::Disabled, + Inner::Captured(_) => BacktraceStatus::Captured, + } + } + } + + impl Display for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str("unsupported backtrace"), + Inner::Disabled => return fmt.write_str("disabled backtrace"), + Inner::Captured(c) => c.force(), + }; + + let full = fmt.alternate(); + let (frames, style) = if full { + (&capture.frames[..], PrintFmt::Full) + } else { + (&capture.frames[capture.actual_start..], PrintFmt::Short) + }; + + // When printing paths we try to strip the cwd if it exists, + // otherwise we just print the path as-is. Note that we also only do + // this for the short format, because if it's full we presumably + // want to print everything. + let cwd = env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter, path: BytesOrWideString| { + output_filename(fmt, path, style, cwd.as_ref().ok()) + }; + + let mut f = 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)?; + } else { + for symbol in frame.symbols.iter() { + f.print_raw_with_column( + frame.frame.ip(), + symbol.name.as_ref().map(|b| SymbolName::new(b)), + symbol.filename.as_ref().map(|b| match b { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }), + symbol.lineno, + symbol.colno, + )?; + } + } + } + f.finish()?; + Ok(()) + } + } + + struct LazilyResolvedCapture { + sync: Once, + capture: UnsafeCell<Capture>, + } + + impl LazilyResolvedCapture { + fn new(capture: Capture) -> Self { + LazilyResolvedCapture { + sync: Once::new(), + capture: UnsafeCell::new(capture), + } + } + + fn force(&self) -> &Capture { + self.sync.call_once(|| { + // Safety: This exclusive reference can't overlap with any + // others. `Once` guarantees callers will block until this + // closure returns. `Once` also guarantees only a single caller + // will enter this closure. + unsafe { &mut *self.capture.get() }.resolve(); + }); + + // Safety: This shared reference can't overlap with the exclusive + // reference above. + unsafe { &*self.capture.get() } + } + } + + // Safety: Access to the inner value is synchronized using a thread-safe + // `Once`. So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too + unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {} + + impl Capture { + fn resolve(&mut self) { + // If we're already resolved, nothing to do! + if self.resolved { + return; + } + self.resolved = true; + + for frame in self.frames.iter_mut() { + let symbols = &mut frame.symbols; + let frame = &frame.frame; + backtrace::resolve_frame(frame, |symbol| { + symbols.push(BacktraceSymbol { + name: symbol.name().map(|m| m.as_bytes().to_vec()), + filename: symbol.filename_raw().map(|b| match b { + BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()), + BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()), + }), + lineno: symbol.lineno(), + colno: symbol.colno(), + }); + }); + } + } + } + + // Prints the filename of the backtrace frame. + fn output_filename( + fmt: &mut fmt::Formatter, + bows: BytesOrWideString, + print_fmt: PrintFmt, + cwd: Option<&PathBuf>, + ) -> fmt::Result { + let file: Cow<Path> = match bows { + #[cfg(unix)] + BytesOrWideString::Bytes(bytes) => { + use std::os::unix::ffi::OsStrExt; + Path::new(std::ffi::OsStr::from_bytes(bytes)).into() + } + #[cfg(not(unix))] + BytesOrWideString::Bytes(bytes) => { + Path::new(std::str::from_utf8(bytes).unwrap_or("<unknown>")).into() + } + #[cfg(windows)] + BytesOrWideString::Wide(wide) => { + use std::os::windows::ffi::OsStringExt; + Cow::Owned(std::ffi::OsString::from_wide(wide).into()) + } + #[cfg(not(windows))] + BytesOrWideString::Wide(_wide) => Path::new("<unknown>").into(), + }; + if print_fmt == PrintFmt::Short && file.is_absolute() { + if let Some(cwd) = cwd { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s); + } + } + } + } + Display::fmt(&file.display(), fmt) + } +} + +fn _assert_send_sync() { + fn _assert<T: Send + Sync>() {} + _assert::<Backtrace>(); +} diff --git a/vendor/anyhow/src/error.rs b/vendor/anyhow/src/error.rs index e7c086f662..f4f5bc28ce 100644 --- a/vendor/anyhow/src/error.rs +++ b/vendor/anyhow/src/error.rs @@ -1,11 +1,15 @@ use crate::alloc::Box; use crate::backtrace::Backtrace; use crate::chain::Chain; -use crate::ptr::{Mut, Own, Ref}; +#[cfg(any(feature = "std", anyhow_no_ptr_addr_of))] +use crate::ptr::Mut; +use crate::ptr::{Own, Ref}; use crate::{Error, StdError}; use core::any::TypeId; use core::fmt::{self, Debug, Display}; use core::mem::ManuallyDrop; +#[cfg(not(anyhow_no_ptr_addr_of))] +use core::ptr; use core::ptr::NonNull; #[cfg(feature = "std")] @@ -81,11 +85,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::<E>, object_ref: object_ref::<E>, + #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::<E>, object_boxed: object_boxed::<E>, object_downcast: object_downcast::<E>, + #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::<E>, object_drop_rest: object_drop_front::<E>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: passing vtable that operates on the right type E. @@ -101,12 +109,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::<MessageError<M>>, object_ref: object_ref::<MessageError<M>>, - #[cfg(feature = "std")] + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::<MessageError<M>>, object_boxed: object_boxed::<MessageError<M>>, object_downcast: object_downcast::<M>, + #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::<M>, object_drop_rest: object_drop_front::<M>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: MessageError is repr(transparent) so it is okay for the @@ -123,12 +134,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::<DisplayError<M>>, object_ref: object_ref::<DisplayError<M>>, - #[cfg(feature = "std")] + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::<DisplayError<M>>, object_boxed: object_boxed::<DisplayError<M>>, object_downcast: object_downcast::<M>, + #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::<M>, object_drop_rest: object_drop_front::<M>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: DisplayError is repr(transparent) so it is okay for the @@ -147,11 +161,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::<ContextError<C, E>>, object_ref: object_ref::<ContextError<C, E>>, + #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::<ContextError<C, E>>, object_boxed: object_boxed::<ContextError<C, E>>, object_downcast: context_downcast::<C, E>, + #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: context_downcast_mut::<C, E>, object_drop_rest: context_drop_rest::<C, E>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: passing vtable that operates on the right type. @@ -168,11 +186,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::<BoxedError>, object_ref: object_ref::<BoxedError>, + #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::<BoxedError>, object_boxed: object_boxed::<BoxedError>, object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>, + #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::<Box<dyn StdError + Send + Sync>>, object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: BoxedError is repr(transparent) so it is okay for the vtable @@ -274,12 +296,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::<ContextError<C, Error>>, object_ref: object_ref::<ContextError<C, Error>>, - #[cfg(feature = "std")] + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::<ContextError<C, Error>>, object_boxed: object_boxed::<ContextError<C, Error>>, object_downcast: context_chain_downcast::<C>, + #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: context_chain_downcast_mut::<C>, object_drop_rest: context_chain_drop_rest::<C>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: context_backtrace::<C>, }; // As the cause is anyhow::Error, we already have a backtrace for it. @@ -291,9 +316,6 @@ impl Error { /// Get the backtrace for this Error. /// - /// Backtraces are only available on the nightly channel. Tracking issue: - /// [rust-lang/rust#53487][tracking]. - /// /// In order for the backtrace to be meaningful, one of the two environment /// variables `RUST_LIB_BACKTRACE=1` or `RUST_BACKTRACE=1` must be defined /// and `RUST_LIB_BACKTRACE` must not be `0`. Backtraces are somewhat @@ -307,9 +329,24 @@ impl Error { /// - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and /// `RUST_LIB_BACKTRACE=0`. /// + /// # Stability + /// + /// Standard library backtraces are only available on the nightly channel. + /// Tracking issue: [rust-lang/rust#53487][tracking]. + /// + /// On stable compilers, this function is only available if the crate's + /// "backtrace" feature is enabled, and will use the `backtrace` crate as + /// the underlying backtrace implementation. + /// + /// ```toml + /// [dependencies] + /// anyhow = { version = "1.0", features = ["backtrace"] } + /// ``` + /// /// [tracking]: https://github.com/rust-lang/rust/issues/53487 - #[cfg(backtrace)] - pub fn backtrace(&self) -> &Backtrace { + #[cfg(any(backtrace, feature = "backtrace"))] + #[cfg_attr(doc_cfg, doc(cfg(any(nightly, feature = "backtrace"))))] + pub fn backtrace(&self) -> &impl_backtrace!() { unsafe { ErrorImpl::backtrace(self.inner.by_ref()) } } @@ -372,14 +409,20 @@ impl Error { E: Display + Debug + Send + Sync + 'static, { let target = TypeId::of::<E>(); + let inner = self.inner.by_mut(); unsafe { // Use vtable to find NonNull<()> which points to a value of type E // somewhere inside the data structure. - let addr = - match (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target) { - Some(addr) => addr.extend(), - None => return Err(self), - }; + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) { + Some(addr) => addr.by_mut().extend(), + None => return Err(self), + }; + #[cfg(anyhow_no_ptr_addr_of)] + let addr = match (vtable(inner.ptr).object_downcast_mut)(inner, target) { + Some(addr) => addr.extend(), + None => return Err(self), + }; // Prepare to read E out of the data structure. We'll drop the rest // of the data structure separately so that E is not dropped. @@ -453,7 +496,14 @@ impl Error { unsafe { // Use vtable to find NonNull<()> which points to a value of type E // somewhere inside the data structure. + + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = + (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut(); + + #[cfg(anyhow_no_ptr_addr_of)] let addr = (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target)?; + Some(addr.cast::<E>().deref_mut()) } } @@ -512,13 +562,16 @@ impl Drop for Error { struct ErrorVTable { object_drop: unsafe fn(Own<ErrorImpl>), - object_ref: unsafe fn(Ref<ErrorImpl>) -> &(dyn StdError + Send + Sync + 'static), - #[cfg(feature = "std")] + object_ref: unsafe fn(Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>, + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: unsafe fn(Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static), object_boxed: unsafe fn(Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>, object_downcast: unsafe fn(Ref<ErrorImpl>, TypeId) -> Option<Ref<()>>, + #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: unsafe fn(Mut<ErrorImpl>, TypeId) -> Option<Mut<()>>, object_drop_rest: unsafe fn(Own<ErrorImpl>, TypeId), + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: unsafe fn(Ref<ErrorImpl>) -> Option<&Backtrace>, } // Safety: requires layout of *e to match ErrorImpl<E>. @@ -540,17 +593,26 @@ unsafe fn object_drop_front<E>(e: Own<ErrorImpl>, target: TypeId) { } // Safety: requires layout of *e to match ErrorImpl<E>. -unsafe fn object_ref<E>(e: Ref<ErrorImpl>) -> &(dyn StdError + Send + Sync + 'static) +unsafe fn object_ref<E>(e: Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static> where E: StdError + Send + Sync + 'static, { // Attach E's native StdError vtable onto a pointer to self._object. - &e.cast::<ErrorImpl<E>>().deref()._object + + let unerased = e.cast::<ErrorImpl<E>>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )); + + #[cfg(anyhow_no_ptr_addr_of)] + return Ref::new(&unerased.deref()._object); } // Safety: requires layout of *e to match ErrorImpl<E>, and for `e` to be derived // from a `&mut` -#[cfg(feature = "std")] +#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] unsafe fn object_mut<E>(e: Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static) where E: StdError + Send + Sync + 'static, @@ -576,14 +638,26 @@ where if TypeId::of::<E>() == target { // Caller is looking for an E pointer and e is ErrorImpl<E>, take a // pointer to its E field. - let unerased = e.cast::<ErrorImpl<E>>().deref(); - Some(Ref::new(&unerased._object).cast::<()>()) + + let unerased = e.cast::<ErrorImpl<E>>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Some( + Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )) + .cast::<()>(), + ); + + #[cfg(anyhow_no_ptr_addr_of)] + return Some(Ref::new(&unerased.deref()._object).cast::<()>()); } else { None } } // Safety: requires layout of *e to match ErrorImpl<E>. +#[cfg(anyhow_no_ptr_addr_of)] unsafe fn object_downcast_mut<E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> where E: 'static, @@ -598,6 +672,12 @@ where } } +#[cfg(all(not(backtrace), feature = "backtrace"))] +fn no_backtrace(e: Ref<ErrorImpl>) -> Option<&Backtrace> { + let _ = e; + None +} + // Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. #[cfg(feature = "std")] unsafe fn context_downcast<C, E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>> @@ -617,7 +697,7 @@ where } // Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. -#[cfg(feature = "std")] +#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] unsafe fn context_downcast_mut<C, E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> where C: 'static, @@ -673,6 +753,7 @@ where } // Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. +#[cfg(anyhow_no_ptr_addr_of)] unsafe fn context_chain_downcast_mut<C>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> where C: 'static, @@ -714,6 +795,18 @@ where } } +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. +#[cfg(all(not(backtrace), feature = "backtrace"))] +#[allow(clippy::unnecessary_wraps)] +unsafe fn context_backtrace<C>(e: Ref<ErrorImpl>) -> Option<&Backtrace> +where + C: 'static, +{ + let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref(); + let backtrace = ErrorImpl::backtrace(unerased._object.error.inner.by_ref()); + Some(backtrace) +} + // NOTE: If working with `ErrorImpl<()>`, references should be avoided in favor // of raw pointers and `NonNull`. // repr C to ensure that E remains in the final position. @@ -754,17 +847,24 @@ impl ErrorImpl { pub(crate) unsafe fn error(this: Ref<Self>) -> &(dyn StdError + Send + Sync + 'static) { // Use vtable to attach E's native StdError vtable for the right // original type E. - (vtable(this.ptr).object_ref)(this) + (vtable(this.ptr).object_ref)(this).deref() } #[cfg(feature = "std")] pub(crate) unsafe fn error_mut(this: Mut<Self>) -> &mut (dyn StdError + Send + Sync + 'static) { // Use vtable to attach E's native StdError vtable for the right // original type E. - (vtable(this.ptr).object_mut)(this) + + #[cfg(not(anyhow_no_ptr_addr_of))] + return (vtable(this.ptr).object_ref)(this.by_ref()) + .by_mut() + .deref_mut(); + + #[cfg(anyhow_no_ptr_addr_of)] + return (vtable(this.ptr).object_mut)(this); } - #[cfg(backtrace)] + #[cfg(any(backtrace, feature = "backtrace"))] pub(crate) unsafe fn backtrace(this: Ref<Self>) -> &Backtrace { // This unwrap can only panic if the underlying error's backtrace method // is nondeterministic, which would only happen in maliciously @@ -772,7 +872,12 @@ impl ErrorImpl { this.deref() .backtrace .as_ref() - .or_else(|| Self::error(this).backtrace()) + .or_else(|| { + #[cfg(backtrace)] + return Self::error(this).backtrace(); + #[cfg(all(not(backtrace), feature = "backtrace"))] + return (vtable(this.ptr).object_backtrace)(this); + }) .expect("backtrace capture failed") } diff --git a/vendor/anyhow/src/fmt.rs b/vendor/anyhow/src/fmt.rs index 68f6755508..03d8fd3940 100644 --- a/vendor/anyhow/src/fmt.rs +++ b/vendor/anyhow/src/fmt.rs @@ -39,9 +39,9 @@ impl ErrorImpl { } } - #[cfg(backtrace)] + #[cfg(any(backtrace, feature = "backtrace"))] { - use std::backtrace::BacktraceStatus; + use crate::backtrace::BacktraceStatus; let backtrace = Self::backtrace(this); if let BacktraceStatus::Captured = backtrace.status() { diff --git a/vendor/anyhow/src/kind.rs b/vendor/anyhow/src/kind.rs index fdeb060ad8..eb8d604462 100644 --- a/vendor/anyhow/src/kind.rs +++ b/vendor/anyhow/src/kind.rs @@ -50,9 +50,6 @@ use core::fmt::{Debug, Display}; #[cfg(feature = "std")] use crate::StdError; -#[cfg(backtrace)] -use std::backtrace::Backtrace; - pub struct Adhoc; pub trait AdhocKind: Sized { diff --git a/vendor/anyhow/src/lib.rs b/vendor/anyhow/src/lib.rs index c8bc599676..d6d70cf874 100644 --- a/vendor/anyhow/src/lib.rs +++ b/vendor/anyhow/src/lib.rs @@ -209,18 +209,21 @@ //! 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.38")] +#![doc(html_root_url = "https://docs.rs/anyhow/1.0.40")] #![cfg_attr(backtrace, feature(backtrace))] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] +#![deny(dead_code, unused_imports, unused_mut)] #![allow( clippy::doc_markdown, clippy::enum_glob_use, clippy::missing_errors_doc, + clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::needless_doctest_main, clippy::new_ret_no_self, + clippy::redundant_else, clippy::unused_self, clippy::used_underscore_binding, clippy::wildcard_imports, @@ -612,9 +615,6 @@ pub mod private { use crate::Error; use core::fmt::{Debug, Display}; - #[cfg(backtrace)] - use std::backtrace::Backtrace; - pub use core::result::Result::Err; #[doc(hidden)] diff --git a/vendor/anyhow/src/ptr.rs b/vendor/anyhow/src/ptr.rs index bcfdc6d398..6840833896 100644 --- a/vendor/anyhow/src/ptr.rs +++ b/vendor/anyhow/src/ptr.rs @@ -3,27 +3,39 @@ use core::marker::PhantomData; use core::ptr::NonNull; #[repr(transparent)] -pub struct Own<T> { +pub struct Own<T> +where + T: ?Sized, +{ pub ptr: NonNull<T>, } -unsafe impl<T> Send for Own<T> {} -unsafe impl<T> Sync for Own<T> {} -impl<T> Copy for Own<T> {} -impl<T> Clone for Own<T> { +unsafe impl<T> Send for Own<T> where T: ?Sized {} + +unsafe impl<T> Sync for Own<T> where T: ?Sized {} + +impl<T> Copy for Own<T> where T: ?Sized {} + +impl<T> Clone for Own<T> +where + T: ?Sized, +{ fn clone(&self) -> Self { *self } } -impl<T> Own<T> { +impl<T> Own<T> +where + T: ?Sized, +{ pub fn new(ptr: Box<T>) -> Self { Own { ptr: unsafe { NonNull::new_unchecked(Box::into_raw(ptr)) }, } } - pub fn cast<U>(self) -> Own<U> { + pub fn cast<U: CastTo>(self) -> Own<U::Target> { Own { ptr: self.ptr.cast(), } @@ -49,19 +61,29 @@ impl<T> Own<T> { } #[repr(transparent)] -pub struct Ref<'a, T> { +pub struct Ref<'a, T> +where + T: ?Sized, +{ pub ptr: NonNull<T>, lifetime: PhantomData<&'a T>, } -impl<'a, T> Copy for Ref<'a, T> {} -impl<'a, T> Clone for Ref<'a, T> { +impl<'a, T> Copy for Ref<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Ref<'a, T> +where + T: ?Sized, +{ fn clone(&self) -> Self { *self } } -impl<'a, T> Ref<'a, T> { +impl<'a, T> Ref<'a, T> +where + T: ?Sized, +{ pub fn new(ptr: &'a T) -> Self { Ref { ptr: NonNull::from(ptr), @@ -69,32 +91,64 @@ impl<'a, T> Ref<'a, T> { } } - pub fn cast<U>(self) -> Ref<'a, U> { + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn from_raw(ptr: NonNull<T>) -> Self { + Ref { + ptr, + lifetime: PhantomData, + } + } + + pub fn cast<U: CastTo>(self) -> Ref<'a, U::Target> { Ref { ptr: self.ptr.cast(), lifetime: PhantomData, } } + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_mut(self) -> Mut<'a, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn as_ptr(self) -> *const T { + self.ptr.as_ptr() as *const T + } + pub unsafe fn deref(self) -> &'a T { &*self.ptr.as_ptr() } } #[repr(transparent)] -pub struct Mut<'a, T> { +pub struct Mut<'a, T> +where + T: ?Sized, +{ pub ptr: NonNull<T>, lifetime: PhantomData<&'a mut T>, } -impl<'a, T> Copy for Mut<'a, T> {} -impl<'a, T> Clone for Mut<'a, T> { +impl<'a, T> Copy for Mut<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Mut<'a, T> +where + T: ?Sized, +{ fn clone(&self) -> Self { *self } } -impl<'a, T> Mut<'a, T> { +impl<'a, T> Mut<'a, T> +where + T: ?Sized, +{ + #[cfg(anyhow_no_ptr_addr_of)] pub fn new(ptr: &'a mut T) -> Self { Mut { ptr: NonNull::from(ptr), @@ -102,13 +156,21 @@ impl<'a, T> Mut<'a, T> { } } - pub fn cast<U>(self) -> Mut<'a, U> { + pub fn cast<U: CastTo>(self) -> Mut<'a, U::Target> { Mut { ptr: self.ptr.cast(), lifetime: PhantomData, } } + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_ref(self) -> Ref<'a, T> { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + pub fn extend<'b>(self) -> Mut<'b, T> { Mut { ptr: self.ptr, @@ -119,8 +181,19 @@ impl<'a, T> Mut<'a, T> { pub unsafe fn deref_mut(self) -> &'a mut T { &mut *self.ptr.as_ptr() } +} +impl<'a, T> Mut<'a, T> { pub unsafe fn read(self) -> T { self.ptr.as_ptr().read() } } + +// Force turbofish on all calls of `.cast::<U>()`. +pub trait CastTo { + type Target; +} + +impl<T> CastTo for T { + type Target = T; +} diff --git a/vendor/anyhow/tests/ui/no-impl.stderr b/vendor/anyhow/tests/ui/no-impl.stderr index 0af29aff41..a4a829b660 100644 --- a/vendor/anyhow/tests/ui/no-impl.stderr +++ b/vendor/anyhow/tests/ui/no-impl.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `anyhow_kind` found for reference `&Error` in the current scope +error[E0599]: the method `anyhow_kind` exists for reference `&Error`, but its trait bounds were not satisfied --> $DIR/no-impl.rs:7:13 | 4 | struct Error; @@ -9,9 +9,9 @@ error[E0599]: no method named `anyhow_kind` found for reference `&Error` in the | doesn't satisfy `Error: std::fmt::Display` ... 7 | let _ = anyhow!(Error); - | ^^^^^^^^^^^^^^ method not found in `&Error` + | ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds | - = note: the method `anyhow_kind` exists but the following trait bounds were not satisfied: + = note: the following trait bounds were not satisfied: `Error: Into<anyhow::Error>` which is required by `Error: anyhow::private::kind::TraitKind` `Error: std::fmt::Display` diff --git a/vendor/arrayref/.cargo-checksum.json b/vendor/arrayref/.cargo-checksum.json deleted file mode 100644 index 5d57087e27..0000000000 --- a/vendor/arrayref/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.lock":"a089c4b179e72a02fac211ae23ff35cbb93703e975733b94eba13ac4b52fe5c4","Cargo.toml":"ff0e13c99f02212cb939518302c5110c6c5383fe4ddd3da01cea2fd656f0feee","LICENSE":"1bc7e6f475b3ec99b7e2643411950ae2368c250dd4c5c325f80f9811362a94a1","README.md":"f77d8910fa16f9f0ad2d72d039a7e8ac2979834e0acf435b7c84744c90cb21ec","examples/array_refs.rs":"336b52f6ab31d78766bd1653cea60b9f183d80369f3feec55e454ccbcb3adaaa","examples/array_refs_with_const.rs":"9e49959de714c611bc2e48bb0dd51c3023abc2b3e6b6e0428e7d7b30be8900e4","examples/simple-case.rs":"12a7c596db0d8e89415dfd75a8fe390a7141b24771ad70aee73286857a37b5fb","src/lib.rs":"193dcf7ba66294353b3173047606381f390552a94f1d0472bd9207273bd347c4"},"package":"a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"} \ No newline at end of file diff --git a/vendor/arrayref/Cargo.lock b/vendor/arrayref/Cargo.lock deleted file mode 100644 index 7b43782c24..0000000000 --- a/vendor/arrayref/Cargo.lock +++ /dev/null @@ -1,256 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "aho-corasick" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "arrayref" -version = "0.3.6" -dependencies = [ - "quickcheck 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "env_logger" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "humantime" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "log" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memchr" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quick-error" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quickcheck" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termcolor" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ucd-util" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "utf8-ranges" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.5" -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-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wincolor" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" -"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" -"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5" -"checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" -"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" -"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quickcheck 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c01babc5ffd48a2a83744b3024814bb46dfd4f2a4705ccb44b1b60e644fdcab7" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" -"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9dc3aa9dcda98b5a16150c54619c1ead22e3d3a5d458778ae914be760aa981a" diff --git a/vendor/arrayref/LICENSE b/vendor/arrayref/LICENSE deleted file mode 100644 index b9eb43a86c..0000000000 --- a/vendor/arrayref/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2015 David Roundy <roundyd@physics.oregonstate.edu> -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the - distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"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 THE COPYRIGHT -HOLDER OR CONTRIBUTORS 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/arrayref/README.md b/vendor/arrayref/README.md deleted file mode 100644 index 10603a089f..0000000000 --- a/vendor/arrayref/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# arrayref - -[![Build Status](https://travis-ci.org/droundy/arrayref.svg?branch=master)](https://travis-ci.org/droundy/arrayref) -[![Coverage Status](https://coveralls.io/repos/droundy/arrayref/badge.svg?branch=master&service=github)](https://coveralls.io/github/droundy/arrayref?branch=master) - -[Documentation](https://docs.rs/arrayref) - -This is a very small rust module, which contains just four macros, for -the taking of array references to slices of... sliceable things. -These macros (which are awkwardly named) should be perfectly safe, and -have seen just a tad of code review. - -## Why would I want this? - -The goal of arrayref is to enable the effective use of APIs that -involve array references rather than slices, for situations where -parameters must have a given size. As an example, consider the -`byteorder` crate. This is a very nice crate with a simple API -containing functions that look like: - -```rust -fn read_u16(buf: &[u8]) -> u16; -fn write_u16(buf: &mut [u8], n: u16); -``` - -Looking at this, you might wonder why they accept a slice reference as -input. After all, they always want just two bytes. These functions -must panic if given a slice that is too small, which means that unless -they are inlined, then a runtime bounds-check is forced, even if it -may be statically known that the input is the right size. - -Wouldn't it be nicer if we had functions more like - -```rust -fn read_u16_array(buf: &[u8; 2]) -> u16; -fn write_u16_array(buf: &mut [u8; 2], n: u16); -``` - -The type signature would tell users precisely what size of input is -required, and the compiler could check at compile time that the input -is of the appropriate size: this sounds like the zero-cost -abstractions rust is famous for! However, there is a catch, which -arises when you try to *use* these nicer functions, which is that -usually you are looking at two bytes in a stream. So, e.g. consider -that we are working with a hypothetical (and simplified) ipv6 address. - -Doing this with our array version (which looks so beautiful in terms -of accurately describing what we want!) looks terrible: - -```rust -let addr: &[u8; 16] = ...; -let mut segments = [0u16; 8]; -// array-based API -for i in 0 .. 8 { - let mut two_bytes = [addr[2*i], addr[2*i+1]]; - segments[i] = read_u16_array(&two_bytes); -} -// slice-based API -for i in 0 .. 8 { - segments[i] = read_u16(&addr[2*i..]); -} -``` - -The array-based approach looks way worse. We need to create a fresh -copy of the bytes, just so it will be in an array of the proper size! -Thus the whole "zero-cost abstraction" argument for using array -references fails. The trouble is that there is no (safe) way (until -[RFC 495][1] lands) to obtain an array reference to a portion of a -larger array or slice. Doing so is the equivalent of taking a slice -with a size known at compile time, and ought to be built into the -language. - -[1]: https://github.com/rust-lang/rfcs/blob/master/text/0495-array-pattern-changes.md - -The arrayref crate allows you to do this kind of slicing. So the -above (very contrived) example can be implemented with array -references as: - -```rust -let addr: &[u8; 16] = ...; -let mut segments = [0u16; 8]; -// array-based API with arrayref -for i in 0 .. 8 { - segments[i] = read_u16_array(array_ref![addr,2*i,2]); -} -``` - -Here the `array_ref![addr,2*i,2]` macro allows us to take an array -reference to a slice consisting of two bytes starting at `2*i`. Apart -from the syntax (less nice than slicing), it is essentially the same -as the slice approach. However, this code makes explicit the -need for precisely *two* bytes both in the caller, and in the function -signature. - -This module provides three other macros providing related -functionality, which you can read about in the -[documentation](https://droundy.github.io/arrayref). - -For an example of how these macros can be used in an actual program, -see [my rust translation of tweetnacl][2], which uses `arrayref` -to almost exclusively accept array references in functions, with the -only exception being those which truly expect data of arbitrary -length. In my opinion, the result is code that is far more legible -than the original C code, since the size of each argument is -explicit. Moreover (although I have not tested this), the use of -array references rather than slices *should* result in far fewer -bounds checks, since almost all sizes are known at compile time. - -[2]: https://github.com/droundy/onionsalt/blob/master/src/crypto.rs diff --git a/vendor/arrayref/examples/array_refs.rs b/vendor/arrayref/examples/array_refs.rs deleted file mode 100644 index a3ff081a11..0000000000 --- a/vendor/arrayref/examples/array_refs.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[macro_use] -extern crate arrayref; - -fn main() { - let x = [0,1,2,3,4,5,6,7,8,9]; - let (a,b,c) = array_refs!(&x, 2, 3, 5); - assert_eq!(2, a.len()); - assert_eq!(3, b.len()); - assert_eq!(5, c.len()); - assert_eq!(*a, [0,1]); - assert_eq!(*b, [2,3,4]); - assert_eq!(*c, [5,6,7,8,9]); -} diff --git a/vendor/arrayref/examples/array_refs_with_const.rs b/vendor/arrayref/examples/array_refs_with_const.rs deleted file mode 100644 index 734ef46270..0000000000 --- a/vendor/arrayref/examples/array_refs_with_const.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[macro_use] -extern crate arrayref; - -const SIZE: usize = 10; -const SIZE_A: usize = 2; -const SIZE_B: usize = 3; -const SIZE_C: usize = 5; - -fn main() { - let x: [u8; SIZE] = [0,1,2,3,4,5,6,7,8,9]; - let (a,b,c) = array_refs!(&x, SIZE_A, SIZE_B, SIZE_C); - assert_eq!(SIZE_A, a.len()); - assert_eq!(SIZE_B, b.len()); - assert_eq!(SIZE_C, c.len()); - assert_eq!(*a, [0,1]); - assert_eq!(*b, [2,3,4]); - assert_eq!(*c, [5,6,7,8,9]); -} diff --git a/vendor/arrayref/examples/simple-case.rs b/vendor/arrayref/examples/simple-case.rs deleted file mode 100644 index 434e253ae6..0000000000 --- a/vendor/arrayref/examples/simple-case.rs +++ /dev/null @@ -1,15 +0,0 @@ -#[macro_use] -extern crate arrayref; - -fn add_three(a: &[u8; 3]) -> u8 { - a[0] + a[1] + a[2] -} - -fn main() { - let mut x = [0u8; 30]; - x[20] = 1; - x[21] = 4; - x[24] = 3; - x[0] = add_three(array_mut_ref![x,20,3]); - assert_eq!(x[0], 8); -} diff --git a/vendor/arrayref/src/lib.rs b/vendor/arrayref/src/lib.rs deleted file mode 100644 index b59b2fcd9c..0000000000 --- a/vendor/arrayref/src/lib.rs +++ /dev/null @@ -1,476 +0,0 @@ -//! This package contains just four macros, which enable the creation -//! of array references to portions of arrays or slices (or things -//! that can be sliced). -//! -//! # Examples -//! -//! Here is a simple example of slicing and dicing a slice into array -//! references with these macros. Here we implement a simple -//! little-endian conversion from bytes to `u16`, and demonstrate code -//! that uses `array_ref!` to extract an array reference from a larger -//! array. Note that the documentation for each macro also has an -//! example of its use. -//! -//! ``` -//! #[macro_use] -//! extern crate arrayref; -//! -//! fn read_u16(bytes: &[u8; 2]) -> u16 { -//! bytes[0] as u16 + ((bytes[1] as u16) << 8) -//! } -//! // ... -//! # fn main() { -//! let data = [0,1,2,3,4,0,6,7,8,9]; -//! assert_eq!(256, read_u16(array_ref![data,0,2])); -//! assert_eq!(4, read_u16(array_ref![data,4,2])); -//! # } -//! ``` -#![deny(warnings)] -#![no_std] - -#[cfg(test)] -#[macro_use] -extern crate std; - -/// You can use `array_ref` to generate an array reference to a subset -/// of a sliceable bit of data (which could be an array, or a slice, -/// or a Vec). -/// -/// **Panics** if the slice is out of bounds. -/// -/// ``` -/// #[macro_use] -/// extern crate arrayref; -/// -/// fn read_u16(bytes: &[u8; 2]) -> u16 { -/// bytes[0] as u16 + ((bytes[1] as u16) << 8) -/// } -/// // ... -/// # fn main() { -/// let data = [0,1,2,3,4,0,6,7,8,9]; -/// assert_eq!(256, read_u16(array_ref![data,0,2])); -/// assert_eq!(4, read_u16(array_ref![data,4,2])); -/// # } -/// ``` - -#[macro_export] -macro_rules! array_ref { - ($arr:expr, $offset:expr, $len:expr) => {{ - { - #[inline] - unsafe fn as_array<T>(slice: &[T]) -> &[T; $len] { - &*(slice.as_ptr() as *const [_; $len]) - } - let offset = $offset; - let slice = & $arr[offset..offset + $len]; - #[allow(unused_unsafe)] - unsafe { - as_array(slice) - } - } - }} -} - -/// You can use `array_refs` to generate a series of array references -/// to an input array reference. The idea is if you want to break an -/// array into a series of contiguous and non-overlapping arrays. -/// `array_refs` is a bit funny in that it insists on slicing up the -/// *entire* array. This is intentional, as I find it handy to make -/// me ensure that my sub-arrays add up to the entire array. This -/// macro will *never* panic, since the sizes are all checked at -/// compile time. -/// -/// Note that unlike `array_ref!`, `array_refs` *requires* that the -/// first argument be an array reference. The following arguments are -/// the lengths of each subarray you wish a reference to. The total -/// of these arguments *must* equal the size of the array itself. -/// -/// ``` -/// #[macro_use] -/// extern crate arrayref; -/// -/// fn read_u16(bytes: &[u8; 2]) -> u16 { -/// bytes[0] as u16 + ((bytes[1] as u16) << 8) -/// } -/// // ... -/// # fn main() { -/// let data = [0,1,2,3,4,0,6,7]; -/// let (a,b,c) = array_refs![&data,2,2,4]; -/// assert_eq!(read_u16(a), 256); -/// assert_eq!(read_u16(b), 3*256+2); -/// assert_eq!(*c, [4,0,6,7]); -/// # } -/// ``` -#[macro_export] -macro_rules! array_refs { - ( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{ - { - use std::slice; - #[inline] - #[allow(unused_assignments)] - #[allow(eval_order_dependence)] - unsafe fn as_arrays<T>(a: &[T]) -> ( $( &[T; $pre], )* &[T], $( &[T; $post], )*) { - let min_len = $( $pre + )* $( $post + )* 0; - let var_len = a.len() - min_len; - assert!(a.len() >= min_len); - let mut p = a.as_ptr(); - ( $( { - let aref = & *(p as *const [T; $pre]); - p = p.offset($pre as isize); - aref - } ),* , { - let sl = slice::from_raw_parts(p as *const T, var_len); - p = p.offset(var_len as isize); - sl - }, $( { - let aref = & *(p as *const [T; $post]); - p = p.offset($post as isize); - aref - } ),*) - } - let input = $arr; - #[allow(unused_unsafe)] - unsafe { - as_arrays(input) - } - } - }}; - ( $arr:expr, $( $len:expr ),* ) => {{ - { - #[inline] - #[allow(unused_assignments)] - #[allow(eval_order_dependence)] - unsafe fn as_arrays<T>(a: &[T; $( $len + )* 0 ]) -> ( $( &[T; $len], )* ) { - let mut p = a.as_ptr(); - ( $( { - let aref = &*(p as *const [T; $len]); - p = p.offset($len as isize); - aref - } ),* ) - } - let input = $arr; - #[allow(unused_unsafe)] - unsafe { - as_arrays(input) - } - } - }} -} - - -/// You can use `mut_array_refs` to generate a series of mutable array -/// references to an input mutable array reference. The idea is if -/// you want to break an array into a series of contiguous and -/// non-overlapping mutable array references. Like `array_refs!`, -/// `mut_array_refs!` is a bit funny in that it insists on slicing up -/// the *entire* array. This is intentional, as I find it handy to -/// make me ensure that my sub-arrays add up to the entire array. -/// This macro will *never* panic, since the sizes are all checked at -/// compile time. -/// -/// Note that unlike `array_mut_ref!`, `mut_array_refs` *requires* -/// that the first argument be a mutable array reference. The -/// following arguments are the lengths of each subarray you wish a -/// reference to. The total of these arguments *must* equal the size -/// of the array itself. Also note that this macro allows you to take -/// out multiple mutable references to a single object, which is both -/// weird and powerful. -/// -/// ``` -/// #[macro_use] -/// extern crate arrayref; -/// -/// fn write_u16(bytes: &mut [u8; 2], num: u16) { -/// bytes[0] = num as u8; -/// bytes[1] = (num >> 8) as u8; -/// } -/// fn write_u32(bytes: &mut [u8; 4], num: u32) { -/// bytes[0] = num as u8; -/// bytes[1] = (num >> 8) as u8; // this is buggy to save space... -/// } -/// // ... -/// # fn main() { -/// let mut data = [0,1,2,3,4,0,6,7]; -/// let (a,b,c) = mut_array_refs![&mut data,2,2,4]; -/// // let's write out some nice prime numbers! -/// write_u16(a, 37); -/// write_u16(b, 73); -/// write_u32(c, 137); // approximate inverse of the fine structure constant! -/// # } -/// ``` -#[macro_export] -macro_rules! mut_array_refs { - ( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{ - { - use std::slice; - #[inline] - #[allow(unused_assignments)] - #[allow(eval_order_dependence)] - unsafe fn as_arrays<T>(a: &mut [T]) -> ( $( &mut [T; $pre], )* &mut [T], $( &mut [T; $post], )*) { - let min_len = $( $pre + )* $( $post + )* 0; - let var_len = a.len() - min_len; - assert!(a.len() >= min_len); - let mut p = a.as_mut_ptr(); - ( $( { - let aref = &mut *(p as *mut [T; $pre]); - p = p.offset($pre as isize); - aref - } ),* , { - let sl = slice::from_raw_parts_mut(p as *mut T, var_len); - p = p.offset(var_len as isize); - sl - }, $( { - let aref = &mut *(p as *mut [T; $post]); - p = p.offset($post as isize); - aref - } ),*) - } - let input = $arr; - #[allow(unused_unsafe)] - unsafe { - as_arrays(input) - } - } - }}; - ( $arr:expr, $( $len:expr ),* ) => {{ - { - #[inline] - #[allow(unused_assignments)] - #[allow(eval_order_dependence)] - unsafe fn as_arrays<T>(a: &mut [T; $( $len + )* 0 ]) -> ( $( &mut [T; $len], )* ) { - let mut p = a.as_mut_ptr(); - ( $( { - let aref = &mut *(p as *mut [T; $len]); - p = p.offset($len as isize); - aref - } ),* ) - } - let input = $arr; - #[allow(unused_unsafe)] - unsafe { - as_arrays(input) - } - } - }}; -} - -/// You can use `array_mut_ref` to generate a mutable array reference -/// to a subset of a sliceable bit of data (which could be an array, -/// or a slice, or a Vec). -/// -/// **Panics** if the slice is out of bounds. -/// -/// ``` -/// #[macro_use] -/// extern crate arrayref; -/// -/// fn write_u16(bytes: &mut [u8; 2], num: u16) { -/// bytes[0] = num as u8; -/// bytes[1] = (num >> 8) as u8; -/// } -/// // ... -/// # fn main() { -/// let mut data = [0,1,2,3,4,0,6,7,8,9]; -/// write_u16(array_mut_ref![data,0,2], 1); -/// write_u16(array_mut_ref![data,2,2], 5); -/// assert_eq!(*array_ref![data,0,4], [1,0,5,0]); -/// *array_mut_ref![data,4,5] = [4,3,2,1,0]; -/// assert_eq!(data, [1,0,5,0,4,3,2,1,0,9]); -/// # } -/// ``` -#[macro_export] -macro_rules! array_mut_ref { - ($arr:expr, $offset:expr, $len:expr) => {{ - { - #[inline] - unsafe fn as_array<T>(slice: &mut [T]) -> &mut [T; $len] { - &mut *(slice.as_mut_ptr() as *mut [_; $len]) - } - let offset = $offset; - let slice = &mut $arr[offset..offset + $len]; - #[allow(unused_unsafe)] - unsafe { - as_array(slice) - } - } - }} -} - - -#[cfg(test)] -mod test { - -extern crate quickcheck; - -use std::vec::Vec; - -// use super::*; - -#[test] -#[should_panic] -fn checks_bounds() { - let foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let bar = array_ref!(foo, 1, 11); - println!("I am checking that I can dereference bar[0] = {}", bar[0]); -} - -#[test] -fn simple_case_works() { - fn check(expected: [u8; 3], actual: &[u8; 3]) { - for (e, a) in (&expected).iter().zip(actual.iter()) { - assert_eq!(e, a) - } - } - let mut foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - { - let bar = array_ref!(foo, 2, 3); - check([2, 3, 4], bar); - } - check([0, 1, 2], array_ref!(foo, 0, 3)); - fn zero2(x: &mut [u8; 2]) { - x[0] = 0; - x[1] = 0; - } - zero2(array_mut_ref!(foo, 8, 2)); - check([0, 0, 10], array_ref!(foo, 8, 3)); -} - - -#[test] -fn check_array_ref_5() { - fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult { - if data.len() < offset + 5 { - return quickcheck::TestResult::discard(); - } - let out = array_ref!(data, offset, 5); - quickcheck::TestResult::from_bool(out.len() == 5) - } - quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult); -} - -#[test] -fn check_array_ref_out_of_bounds_5() { - fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult { - if data.len() >= offset + 5 { - return quickcheck::TestResult::discard(); - } - quickcheck::TestResult::must_fail(move || { - array_ref!(data, offset, 5); - }) - } - quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult); -} - -#[test] -fn check_array_mut_ref_7() { - fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult { - if data.len() < offset + 7 { - return quickcheck::TestResult::discard(); - } - let out = array_mut_ref!(data, offset, 7); - out[6] = 3; - quickcheck::TestResult::from_bool(out.len() == 7) - } - quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult); -} - - -#[test] -fn check_array_mut_ref_out_of_bounds_32() { - fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult { - if data.len() >= offset + 32 { - return quickcheck::TestResult::discard(); - } - quickcheck::TestResult::must_fail(move || { - array_mut_ref!(data, offset, 32); - }) - } - quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult); -} - - -#[test] -fn test_5_array_refs() { - let mut data: [usize; 128] = [0; 128]; - for i in 0..128 { - data[i] = i; - } - let data = data; - let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3, 100, 10); - assert_eq!(a.len(), 1 as usize); - assert_eq!(b.len(), 14 as usize); - assert_eq!(c.len(), 3 as usize); - assert_eq!(d.len(), 100 as usize); - assert_eq!(e.len(), 10 as usize); - assert_eq!(a, array_ref![data, 0, 1]); - assert_eq!(b, array_ref![data, 1, 14]); - assert_eq!(c, array_ref![data, 15, 3]); - assert_eq!(e, array_ref![data, 118, 10]); -} - -#[test] -fn test_5_array_refs_dotdot() { - let mut data: [usize; 128] = [0; 128]; - for i in 0..128 { - data[i] = i; - } - let data = data; - let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3; ..; 10); - assert_eq!(a.len(), 1 as usize); - assert_eq!(b.len(), 14 as usize); - assert_eq!(c.len(), 3 as usize); - assert_eq!(d.len(), 100 as usize); - assert_eq!(e.len(), 10 as usize); - assert_eq!(a, array_ref![data, 0, 1]); - assert_eq!(b, array_ref![data, 1, 14]); - assert_eq!(c, array_ref![data, 15, 3]); - assert_eq!(e, array_ref![data, 118, 10]); -} - - -#[test] -fn test_5_mut_xarray_refs() { - let mut data: [usize; 128] = [0; 128]; - { - // temporarily borrow the data to modify it. - let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3, 100, 10); - assert_eq!(a.len(), 1 as usize); - assert_eq!(b.len(), 14 as usize); - assert_eq!(c.len(), 3 as usize); - assert_eq!(d.len(), 100 as usize); - assert_eq!(e.len(), 10 as usize); - *a = [1; 1]; - *b = [14; 14]; - *c = [3; 3]; - *d = [100; 100]; - *e = [10; 10]; - } - assert_eq!(&[1;1], array_ref![data, 0, 1]); - assert_eq!(&[14;14], array_ref![data, 1, 14]); - assert_eq!(&[3;3], array_ref![data, 15, 3]); - assert_eq!(&[10;10], array_ref![data, 118, 10]); -} - -#[test] -fn test_5_mut_xarray_refs_with_dotdot() { - let mut data: [usize; 128] = [0; 128]; - { - // temporarily borrow the data to modify it. - let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3; ..; 10); - assert_eq!(a.len(), 1 as usize); - assert_eq!(b.len(), 14 as usize); - assert_eq!(c.len(), 3 as usize); - assert_eq!(d.len(), 100 as usize); - assert_eq!(e.len(), 10 as usize); - *a = [1; 1]; - *b = [14; 14]; - *c = [3; 3]; - *e = [10; 10]; - } - assert_eq!(&[1;1], array_ref![data, 0, 1]); - assert_eq!(&[14;14], array_ref![data, 1, 14]); - assert_eq!(&[3;3], array_ref![data, 15, 3]); - assert_eq!(&[10;10], array_ref![data, 118, 10]); -} - -} // mod test diff --git a/vendor/arrayvec/.cargo-checksum.json b/vendor/arrayvec/.cargo-checksum.json index f69428e400..893d948ba4 100644 --- a/vendor/arrayvec/.cargo-checksum.json +++ b/vendor/arrayvec/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"c9e49774ee89a3b7b533362d82060a14f2777ccefbe03b956f6f08057b6c3600","Cargo.toml":"c736151a4747b2c041404d730e17dec631393c5feea287edc8a3e482f83a8927","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0245ee104228a100ce5fceecf43e25faae450494d9173f43fd94c27d69fdac13","README.md":"f42eb73acbc7729825a836a532d1c8c6b71e006e0d87e549ea7a483da7472425","benches/arraystring.rs":"f12b890977117ebde4ca42bcd6b91f2a6a087f2b235aaca6d15e30d125ae9f67","benches/extend.rs":"c3d69cc488ec5341b019cfed545ebbfea252f98718037b413f6a349da9489d1b","ci/miri.sh":"59172afe080a3431f4e7dbd66d2040afa27ab9c0359532bd68f8f423261738de","custom.css":"e6f2cd299392337b4e2959c52f422e5b7be11920ea98d10db44d10ddef5ed47c","src/array.rs":"5fa75554ebdf595c918fe923a84678989fc420d800310ee19a21597f7d683b66","src/array_string.rs":"48c175371aed3372158a9331e939cffc2a11a09120253fa9d0521e5cbca7cfca","src/char.rs":"3fe9e9cc68fc7cedb238d53924b552b876a60c4fea85935d2f5d1ca0d41ffa3e","src/errors.rs":"ca44c0987f59ae57623088d80013e75129101caea93c278c8ebb0df898bc6b1b","src/lib.rs":"08270486d9e9d34e02e0edf227baf5e87b36d38d264da209d3b7f8962dce1b54","src/maybe_uninit.rs":"c81cf16f976bfaf7c1fe371aa2fba84872874fb0e43c96f63bef01cceb5e1d64","tests/serde.rs":"18c165cf6024f04a25b19aa139657d7c59f72d1541c9b24b44f9eaea01f507db","tests/tests.rs":"b9a3db8a0b957695d9ecc539a7ea2ded1eea3c6f76de8b5624c2b4eae95f1fdd"},"package":"23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"} \ No newline at end of file +{"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 diff --git a/vendor/arrayvec/CHANGELOG.md b/vendor/arrayvec/CHANGELOG.md index 9ee813cfce..fba82ab32d 100644 --- a/vendor/arrayvec/CHANGELOG.md +++ b/vendor/arrayvec/CHANGELOG.md @@ -1,56 +1,100 @@ Recent Changes (arrayvec) -------------------------- - -- 0.5.2 - - - Add `is_empty` methods for ArrayVec and ArrayString by @nicbn - - Implement `TryFrom<Slice>` for ArrayVec by @paulkernfeld - - Add `unstable-const-fn` to make `new` methods const by @m-ou-se - - Run miri in CI and a few related fixes by @RalfJung - - Fix outdated comment by @Phlosioneer - - Move changelog to a separate file by @Luro02 - - Remove deprecated `Error::description` by @AnderEnder - - Use pointer method `add` by @hbina - -- 0.5.1 - - - Add `as_ptr`, `as_mut_ptr` accessors directly on the `ArrayVec` by @tbu- - (matches the same addition to `Vec` which happened in Rust 1.37). - - Add method `ArrayString::len` (now available directly, not just through deref to str). - - Use raw pointers instead of `&mut [u8]` for encoding chars into `ArrayString` - (uninit best practice fix). - - Use raw pointers instead of `get_unchecked_mut` where the target may be - uninitialized everywhere relevant in the ArrayVec implementation - (uninit best practice fix). - - Changed inline hints on many methods, mainly removing inline hints - - `ArrayVec::dispose` is now deprecated (it has no purpose anymore) - -- 0.4.12 - - - Use raw pointers instead of `get_unchecked_mut` where the target may be - uninitialized everywhere relevant in the ArrayVec implementation. - -- 0.5.0 - - - Use `MaybeUninit` (now unconditionally) in the implementation of - `ArrayVec` - - Use `MaybeUninit` (now unconditionally) in the implementation of - `ArrayString` - - The crate feature for serde serialization is now named `serde`. - - Updated the `Array` trait interface, and it is now easier to use for - users outside the crate. - - Add `FromStr` impl for `ArrayString` by @despawnerer - - Add method `try_extend_from_slice` to `ArrayVec`, which is always - effecient by @Thomasdezeeuw. - - Add method `remaining_capacity` by @Thomasdezeeuw - - Improve performance of the `extend` method. - - The index type of zero capacity vectors is now itself zero size, by - @clarfon - - Use `drop_in_place` for truncate and clear methods. This affects drop order - and resume from panic during drop. - - Use Rust 2018 edition for the implementation - - Require Rust 1.36 or later, for the unconditional `MaybeUninit` - improvements. +========================= + +## 0.7.0 + +- `fn new_const` is now the way to const-construct arrayvec and arraystring, + and `fn new` has been reverted to a regular "non-const" function. + 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 + +## 0.6.1 + +- The ``ArrayVec::new`` and ``ArrayString::new`` constructors are properly + const fns on stable and the feature flag ``unstable-const-fn`` is now deprecated. + by @rodrimati1992 + +- Small fix to the capacity check macro by @Xaeroxe +- Typo fix in documentation by @cuviper +- Small code cleanup by @bluss + +## 0.6.0 + +- The **const generics** release 🎉. Arrayvec finally implements what it + wanted to implement, since its first version: a vector backed by an array, + with generic parameters for the arbitrary element type *and* backing array + capacity. + + The New type syntax is `ArrayVec<T, CAP>` where `CAP` is the arrayvec capacity. + For arraystring the syntax is `ArrayString<CAP>`. + + Length is stored internally as u32; this limits the maximum capacity. The size + of the `ArrayVec` or `ArrayString` structs for the same capacity may grow + slightly compared with the previous version (depending on padding requirements + for the element type). Change by @bluss. + +- Arrayvec's `.extend()` and `FromIterator`/`.collect()` to arrayvec now + **panic** if the capacity of the arrayvec is exceeded. Change by @bluss. + +- Arraystring now implements `TryFrom<&str>` and `TryFrom<fmt::Arguments>` by + @c410-f3r + +- Minimum supported rust version is Rust 1.51 + +## 0.5.2 + +- Add `is_empty` methods for ArrayVec and ArrayString by @nicbn +- Implement `TryFrom<Slice>` for ArrayVec by @paulkernfeld +- Add `unstable-const-fn` to make `new` methods const by @m-ou-se +- Run miri in CI and a few related fixes by @RalfJung +- Fix outdated comment by @Phlosioneer +- Move changelog to a separate file by @Luro02 +- Remove deprecated `Error::description` by @AnderEnder +- Use pointer method `add` by @hbina + +## 0.5.1 + +- Add `as_ptr`, `as_mut_ptr` accessors directly on the `ArrayVec` by @tbu- + (matches the same addition to `Vec` which happened in Rust 1.37). +- Add method `ArrayString::len` (now available directly, not just through deref to str). +- Use raw pointers instead of `&mut [u8]` for encoding chars into `ArrayString` + (uninit best practice fix). +- Use raw pointers instead of `get_unchecked_mut` where the target may be + uninitialized everywhere relevant in the ArrayVec implementation + (uninit best practice fix). +- Changed inline hints on many methods, mainly removing inline hints +- `ArrayVec::dispose` is now deprecated (it has no purpose anymore) + +## 0.4.12 + +- Use raw pointers instead of `get_unchecked_mut` where the target may be + uninitialized everywhere relevant in the ArrayVec implementation. + +## 0.5.0 + +- Use `MaybeUninit` (now unconditionally) in the implementation of + `ArrayVec` +- Use `MaybeUninit` (now unconditionally) in the implementation of + `ArrayString` +- The crate feature for serde serialization is now named `serde`. +- Updated the `Array` trait interface, and it is now easier to use for + users outside the crate. +- Add `FromStr` impl for `ArrayString` by @despawnerer +- Add method `try_extend_from_slice` to `ArrayVec`, which is always + effecient by @Thomasdezeeuw. +- Add method `remaining_capacity` by @Thomasdezeeuw +- Improve performance of the `extend` method. +- The index type of zero capacity vectors is now itself zero size, by + @clarfon +- Use `drop_in_place` for truncate and clear methods. This affects drop order + and resume from panic during drop. +- Use Rust 2018 edition for the implementation +- Require Rust 1.36 or later, for the unconditional `MaybeUninit` + improvements. + +## Older releases - 0.4.11 diff --git a/vendor/arrayvec/Cargo.toml b/vendor/arrayvec/Cargo.toml index 4fb37c1aa9..859ff3838b 100644 --- a/vendor/arrayvec/Cargo.toml +++ b/vendor/arrayvec/Cargo.toml @@ -13,13 +13,13 @@ [package] edition = "2018" name = "arrayvec" -version = "0.5.2" +version = "0.7.0" 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/" keywords = ["stack", "vector", "array", "data-structure", "no_std"] categories = ["data-structures", "no-std"] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/bluss/arrayvec" [package.metadata.docs.rs] features = ["serde"] @@ -56,8 +56,5 @@ version = "1.0" [build-dependencies] [features] -array-sizes-129-255 = [] -array-sizes-33-128 = [] default = ["std"] std = [] -unstable-const-fn = [] diff --git a/vendor/arrayvec/README.md b/vendor/arrayvec/README.md index bfac3b325f..85ccbd13bd 100644 --- a/vendor/arrayvec/README.md +++ b/vendor/arrayvec/README.md @@ -2,9 +2,12 @@ arrayvec ======== [![Crates.io: arrayvec](https://img.shields.io/crates/v/arrayvec.svg)](https://crates.io/crates/arrayvec) -[![Crates.io: nodrop](https://img.shields.io/crates/v/nodrop.svg)](https://crates.io/crates/nodrop) [![Documentation](https://docs.rs/arrayvec/badge.svg)](https://docs.rs/arrayvec) -[![Build Status](https://travis-ci.org/bluss/arrayvec.svg?branch=master)](https://travis-ci.org/bluss/arrayvec) +[![Build Status](https://github.com/bluss/arrayvec/workflows/Continuous%20integration/badge.svg?branch=master)](https://github.com/bluss/arrayvec/actions) + + + + [![License: Apache](https://img.shields.io/badge/License-Apache%202.0-red.svg)](LICENSE-APACHE) OR [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) diff --git a/vendor/arrayvec/benches/arraystring.rs b/vendor/arrayvec/benches/arraystring.rs index 9cff5875d8..5b986fa2ab 100644 --- a/vendor/arrayvec/benches/arraystring.rs +++ b/vendor/arrayvec/benches/arraystring.rs @@ -7,7 +7,7 @@ use arrayvec::ArrayString; use bencher::Bencher; fn try_push_c(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while v.try_push('c').is_ok() { @@ -18,7 +18,7 @@ fn try_push_c(b: &mut Bencher) { } fn try_push_alpha(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while v.try_push('α').is_ok() { @@ -30,7 +30,7 @@ fn try_push_alpha(b: &mut Bencher) { // Yes, pushing a string char-by-char is slow. Use .push_str. fn try_push_string(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); let input = "abcαβγ“”"; b.iter(|| { v.clear(); @@ -45,7 +45,7 @@ fn try_push_string(b: &mut Bencher) { } fn push_c(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while !v.is_full() { @@ -57,7 +57,7 @@ fn push_c(b: &mut Bencher) { } fn push_alpha(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while !v.is_full() { @@ -69,7 +69,7 @@ fn push_alpha(b: &mut Bencher) { } fn push_string(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); let input = "abcαβγ“”"; b.iter(|| { v.clear(); diff --git a/vendor/arrayvec/benches/extend.rs b/vendor/arrayvec/benches/extend.rs index 0579717696..ba33a93257 100644 --- a/vendor/arrayvec/benches/extend.rs +++ b/vendor/arrayvec/benches/extend.rs @@ -10,7 +10,7 @@ use bencher::Bencher; use bencher::black_box; fn extend_with_constant(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::<u8, 512>::new(); let cap = v.capacity(); b.iter(|| { v.clear(); @@ -22,7 +22,7 @@ fn extend_with_constant(b: &mut Bencher) { } fn extend_with_range(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::<u8, 512>::new(); let cap = v.capacity(); b.iter(|| { v.clear(); @@ -34,7 +34,7 @@ fn extend_with_range(b: &mut Bencher) { } fn extend_with_slice(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::<u8, 512>::new(); let data = [1; 512]; b.iter(|| { v.clear(); @@ -46,7 +46,7 @@ fn extend_with_slice(b: &mut Bencher) { } fn extend_with_write(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::<u8, 512>::new(); let data = [1; 512]; b.iter(|| { v.clear(); @@ -57,7 +57,7 @@ fn extend_with_write(b: &mut Bencher) { } fn extend_from_slice(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::<u8, 512>::new(); let data = [1; 512]; b.iter(|| { v.clear(); diff --git a/vendor/arrayvec/ci/miri.sh b/vendor/arrayvec/ci/miri.sh old mode 100644 new mode 100755 index 6b95c2d97b..272995ca86 --- a/vendor/arrayvec/ci/miri.sh +++ b/vendor/arrayvec/ci/miri.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/bin/sh set -ex diff --git a/vendor/arrayvec/custom.css b/vendor/arrayvec/custom.css deleted file mode 100644 index 8e0b7053ea..0000000000 --- a/vendor/arrayvec/custom.css +++ /dev/null @@ -1,25 +0,0 @@ - -.docblock pre.rust { background: #eeeeff; } -pre.trait, pre.fn, pre.struct, pre.enum, pre.typedef { background: #fcfefc; } - -/* Small “example” label for doc examples */ -.docblock pre.rust::before { - content: "example"; - float: right; - font-style: italic; - font-size: 0.8em; - margin-top: -10px; - margin-right: -5px; -} - - -/* Fixup where display in trait listing */ -pre.trait .where::before { -content: '\a '; -} - -.docblock code { - background-color: inherit; - font-weight: bold; - padding: 0 0.1em; -} diff --git a/vendor/arrayvec/src/array.rs b/vendor/arrayvec/src/array.rs deleted file mode 100644 index 2de5e77c7d..0000000000 --- a/vendor/arrayvec/src/array.rs +++ /dev/null @@ -1,151 +0,0 @@ - -/// Trait for fixed size arrays. -/// -/// This trait is implemented for some specific array sizes, see -/// the implementor list below. At the current state of Rust we can't -/// make this fully general for every array size. -/// -/// The following crate features add more array sizes (and they are not -/// enabled by default due to their impact on compliation speed). -/// -/// - `array-sizes-33-128`: All sizes 33 to 128 are implemented -/// (a few in this range are included by default). -/// - `array-sizes-129-255`: All sizes 129 to 255 are implemented -/// (a few in this range are included by default). -/// -/// ## Safety -/// -/// This trait can *only* be implemented by fixed-size arrays or types with -/// *exactly* the representation of a fixed size array (of the right element -/// type and capacity). -/// -/// Normally this trait is an implementation detail of arrayvec and doesn’t -/// need implementing. -pub unsafe trait Array { - /// The array’s element type - type Item; - /// The smallest type that can index and tell the length of the array. - #[doc(hidden)] - type Index: Index; - /// The array's element capacity - const CAPACITY: usize; - fn as_slice(&self) -> &[Self::Item]; - fn as_mut_slice(&mut self) -> &mut [Self::Item]; -} - -pub trait Index : PartialEq + Copy { - const ZERO: Self; - fn to_usize(self) -> usize; - fn from(_: usize) -> Self; -} - -impl Index for () { - const ZERO: Self = (); - #[inline(always)] - fn to_usize(self) -> usize { 0 } - #[inline(always)] - fn from(_ix: usize) -> Self { () } -} - -impl Index for bool { - const ZERO: Self = false; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix != 0 } -} - -impl Index for u8 { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix as u8 } -} - -impl Index for u16 { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix as u16 } -} - -impl Index for u32 { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix as u32 } -} - -impl Index for usize { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self } - #[inline(always)] - fn from(ix: usize) -> Self { ix } -} - -macro_rules! fix_array_impl { - ($index_type:ty, $len:expr ) => ( - unsafe impl<T> Array for [T; $len] { - type Item = T; - type Index = $index_type; - const CAPACITY: usize = $len; - #[doc(hidden)] - fn as_slice(&self) -> &[Self::Item] { self } - #[doc(hidden)] - fn as_mut_slice(&mut self) -> &mut [Self::Item] { self } - } - ) -} - -macro_rules! fix_array_impl_recursive { - ($index_type:ty, ) => (); - ($index_type:ty, $($len:expr,)*) => ( - $(fix_array_impl!($index_type, $len);)* - ); -} - - -fix_array_impl_recursive!((), 0,); -fix_array_impl_recursive!(bool, 1,); -fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, ); - -#[cfg(not(feature="array-sizes-33-128"))] -fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, ); - -#[cfg(feature="array-sizes-33-128")] -fix_array_impl_recursive!(u8, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, -72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, -92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, -109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, -125, 126, 127, 128, -); - -#[cfg(not(feature="array-sizes-129-255"))] -fix_array_impl_recursive!(u8, 160, 192, 200, 224,); - -#[cfg(feature="array-sizes-129-255")] -fix_array_impl_recursive!(u8, -129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, -141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, -157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, -173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, -189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, -205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, -221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, -237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, -253, 254, 255, -); - -fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,); -// This array size doesn't exist on 16-bit -#[cfg(any(target_pointer_width="32", target_pointer_width="64"))] -fix_array_impl_recursive!(u32, 1 << 16,); - diff --git a/vendor/arrayvec/src/array_string.rs b/vendor/arrayvec/src/array_string.rs index 1aae59ea71..fdce16a66a 100644 --- a/vendor/arrayvec/src/array_string.rs +++ b/vendor/arrayvec/src/array_string.rs @@ -1,50 +1,51 @@ use std::borrow::Borrow; use std::cmp; +use std::convert::TryFrom; use std::fmt; use std::hash::{Hash, Hasher}; -use std::ptr; +use std::mem::MaybeUninit; use std::ops::{Deref, DerefMut}; +use std::ptr; +use std::slice; use std::str; use std::str::FromStr; use std::str::Utf8Error; -use std::slice; -use crate::array::Array; -use crate::array::Index; use crate::CapacityError; +use crate::LenUint; use crate::char::encode_utf8; +use crate::utils::MakeMaybeUninit; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; -use super::MaybeUninit as MaybeUninitCopy; /// A string with a fixed capacity. /// /// The `ArrayString` is a string backed by a fixed size array. It keeps track -/// of its length. +/// of its length, and is parameterized by `CAP` for the maximum capacity. +/// +/// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger +/// arrayvecs with larger capacity will panic. /// /// The string is a contiguous value that you can store directly on the stack /// if needed. #[derive(Copy)] -pub struct ArrayString<A> - where A: Array<Item=u8> + Copy -{ - xs: MaybeUninitCopy<A>, - len: A::Index, +pub struct ArrayString<const CAP: usize> { + // the `len` first elements of the array are initialized + xs: [MaybeUninit<u8>; CAP], + len: LenUint, } -impl<A> Default for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Default for ArrayString<CAP> { /// Return an empty `ArrayString` - fn default() -> ArrayString<A> { + fn default() -> ArrayString<CAP> { ArrayString::new() } } -impl<A> ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> ArrayString<CAP> { /// Create a new empty `ArrayString`. /// @@ -53,34 +54,35 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 16]>::new(); + /// let mut string = ArrayString::<16>::new(); /// string.push_str("foo"); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` - #[cfg(not(feature="unstable-const-fn"))] - pub fn new() -> ArrayString<A> { + pub fn new() -> ArrayString<CAP> { + assert_capacity_limit!(CAP); unsafe { - ArrayString { - xs: MaybeUninitCopy::uninitialized(), - len: Index::ZERO, - } + ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } - #[cfg(feature="unstable-const-fn")] - pub const fn new() -> ArrayString<A> { - unsafe { - ArrayString { - xs: MaybeUninitCopy::uninitialized(), - len: Index::ZERO, - } - } + /// Create a new empty `ArrayString` (const fn). + /// + /// Capacity is inferred from the type parameter. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// static ARRAY: ArrayString<1024> = ArrayString::new_const(); + /// ``` + pub const fn new_const() -> ArrayString<CAP> { + assert_capacity_limit_const!(CAP); + ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 } } /// Return the length of the string. #[inline] - pub fn len(&self) -> usize { self.len.to_usize() } + pub fn len(&self) -> usize { self.len as usize } /// Returns whether the string is empty. #[inline] @@ -95,7 +97,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut string = ArrayString::<3>::from("foo").unwrap(); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.len(), 3); /// assert_eq!(string.capacity(), 3); @@ -115,13 +117,16 @@ impl<A> ArrayString<A> /// /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); /// ``` - pub fn from_byte_string(b: &A) -> Result<Self, Utf8Error> { - let len = str::from_utf8(b.as_slice())?.len(); - debug_assert_eq!(len, A::CAPACITY); - Ok(ArrayString { - xs: MaybeUninitCopy::from(*b), - len: Index::from(A::CAPACITY), - }) + pub fn from_byte_string(b: &[u8; CAP]) -> Result<Self, Utf8Error> { + let len = str::from_utf8(b)?.len(); + debug_assert_eq!(len, CAP); + let mut vec = Self::new(); + unsafe { + (b as *const [u8; CAP] as *const [MaybeUninit<u8>; CAP]) + .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit<u8>; CAP], 1); + vec.set_len(CAP); + } + Ok(vec) } /// Return the capacity of the `ArrayString`. @@ -129,18 +134,18 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let string = ArrayString::<[_; 3]>::new(); + /// let string = ArrayString::<3>::new(); /// assert_eq!(string.capacity(), 3); /// ``` #[inline(always)] - pub fn capacity(&self) -> usize { A::CAPACITY } + pub fn capacity(&self) -> usize { CAP } /// Return if the `ArrayString` is completely filled. /// /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 1]>::new(); + /// let mut string = ArrayString::<1>::new(); /// assert!(!string.is_full()); /// string.push_str("A"); /// assert!(string.is_full()); @@ -154,7 +159,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.push('a'); /// string.push('b'); @@ -174,7 +179,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.try_push('a').unwrap(); /// string.try_push('b').unwrap(); @@ -186,7 +191,7 @@ impl<A> ArrayString<A> pub fn try_push(&mut self, c: char) -> Result<(), CapacityError<char>> { let len = self.len(); unsafe { - let ptr = self.xs.ptr_mut().add(len); + let ptr = self.as_mut_ptr().add(len); let remaining_cap = self.capacity() - len; match encode_utf8(c, ptr, remaining_cap) { Ok(n) => { @@ -205,7 +210,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.push_str("a"); /// string.push_str("d"); @@ -225,7 +230,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.try_push_str("a").unwrap(); /// let overflow1 = string.try_push_str("bc"); @@ -241,7 +246,7 @@ impl<A> ArrayString<A> return Err(CapacityError::new(s)); } unsafe { - let dst = self.xs.ptr_mut().add(self.len()); + let dst = self.as_mut_ptr().add(self.len()); let src = s.as_ptr(); ptr::copy_nonoverlapping(src, dst, s.len()); let newl = self.len() + s.len(); @@ -257,7 +262,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('o')); @@ -287,7 +292,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 6]>::from("foobar").unwrap(); + /// let mut string = ArrayString::<6>::from("foobar").unwrap(); /// string.truncate(3); /// assert_eq!(&string[..], "foo"); /// string.truncate(4); @@ -317,7 +322,7 @@ impl<A> ArrayString<A> /// ``` /// use arrayvec::ArrayString; /// - /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); /// assert_eq!(s.remove(1), 'o'); @@ -332,8 +337,8 @@ impl<A> ArrayString<A> let next = idx + ch.len_utf8(); let len = self.len(); unsafe { - ptr::copy(self.xs.ptr().add(next), - self.xs.ptr_mut().add(idx), + ptr::copy(self.as_ptr().add(next), + self.as_mut_ptr().add(idx), len - next); self.set_len(len - (next - idx)); } @@ -355,104 +360,102 @@ impl<A> ArrayString<A> /// This method uses *debug assertions* to check the validity of `length` /// and may use other debug assertions. pub unsafe fn set_len(&mut self, length: usize) { + // type invariant that capacity always fits in LenUint debug_assert!(length <= self.capacity()); - self.len = Index::from(length); + self.len = length as LenUint; } /// Return a string slice of the whole `ArrayString`. pub fn as_str(&self) -> &str { self } + + fn as_ptr(&self) -> *const u8 { + self.xs.as_ptr() as *const u8 + } + + fn as_mut_ptr(&mut self) -> *mut u8 { + self.xs.as_mut_ptr() as *mut u8 + } } -impl<A> Deref for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Deref for ArrayString<CAP> { type Target = str; #[inline] fn deref(&self) -> &str { unsafe { - let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize()); + let sl = slice::from_raw_parts(self.as_ptr(), self.len()); str::from_utf8_unchecked(sl) } } } -impl<A> DerefMut for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> DerefMut for ArrayString<CAP> { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { - let sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize()); + let len = self.len(); + let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), len); str::from_utf8_unchecked_mut(sl) } } } -impl<A> PartialEq for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> PartialEq for ArrayString<CAP> { fn eq(&self, rhs: &Self) -> bool { **self == **rhs } } -impl<A> PartialEq<str> for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> PartialEq<str> for ArrayString<CAP> { fn eq(&self, rhs: &str) -> bool { &**self == rhs } } -impl<A> PartialEq<ArrayString<A>> for str - where A: Array<Item=u8> + Copy +impl<const CAP: usize> PartialEq<ArrayString<CAP>> for str { - fn eq(&self, rhs: &ArrayString<A>) -> bool { + fn eq(&self, rhs: &ArrayString<CAP>) -> bool { self == &**rhs } } -impl<A> Eq for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Eq for ArrayString<CAP> { } -impl<A> Hash for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Hash for ArrayString<CAP> { fn hash<H: Hasher>(&self, h: &mut H) { (**self).hash(h) } } -impl<A> Borrow<str> for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Borrow<str> for ArrayString<CAP> { fn borrow(&self) -> &str { self } } -impl<A> AsRef<str> for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> AsRef<str> for ArrayString<CAP> { fn as_ref(&self) -> &str { self } } -impl<A> fmt::Debug for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> fmt::Debug for ArrayString<CAP> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl<A> fmt::Display for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> fmt::Display for ArrayString<CAP> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } /// `Write` appends written data to the end of the string. -impl<A> fmt::Write for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> fmt::Write for ArrayString<CAP> { fn write_char(&mut self, c: char) -> fmt::Result { self.try_push(c).map_err(|_| fmt::Error) @@ -463,10 +466,9 @@ impl<A> fmt::Write for ArrayString<A> } } -impl<A> Clone for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Clone for ArrayString<CAP> { - fn clone(&self) -> ArrayString<A> { + fn clone(&self) -> ArrayString<CAP> { *self } fn clone_from(&mut self, rhs: &Self) { @@ -476,8 +478,7 @@ impl<A> Clone for ArrayString<A> } } -impl<A> PartialOrd for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> PartialOrd for ArrayString<CAP> { fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> { (**self).partial_cmp(&**rhs) @@ -488,8 +489,7 @@ impl<A> PartialOrd for ArrayString<A> fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } } -impl<A> PartialOrd<str> for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> PartialOrd<str> for ArrayString<CAP> { fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> { (**self).partial_cmp(rhs) @@ -500,28 +500,25 @@ impl<A> PartialOrd<str> for ArrayString<A> fn ge(&self, rhs: &str) -> bool { &**self >= rhs } } -impl<A> PartialOrd<ArrayString<A>> for str - where A: Array<Item=u8> + Copy +impl<const CAP: usize> PartialOrd<ArrayString<CAP>> for str { - fn partial_cmp(&self, rhs: &ArrayString<A>) -> Option<cmp::Ordering> { + fn partial_cmp(&self, rhs: &ArrayString<CAP>) -> Option<cmp::Ordering> { self.partial_cmp(&**rhs) } - fn lt(&self, rhs: &ArrayString<A>) -> bool { self < &**rhs } - fn le(&self, rhs: &ArrayString<A>) -> bool { self <= &**rhs } - fn gt(&self, rhs: &ArrayString<A>) -> bool { self > &**rhs } - fn ge(&self, rhs: &ArrayString<A>) -> bool { self >= &**rhs } + fn lt(&self, rhs: &ArrayString<CAP>) -> bool { self < &**rhs } + fn le(&self, rhs: &ArrayString<CAP>) -> bool { self <= &**rhs } + fn gt(&self, rhs: &ArrayString<CAP>) -> bool { self > &**rhs } + fn ge(&self, rhs: &ArrayString<CAP>) -> bool { self >= &**rhs } } -impl<A> Ord for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Ord for ArrayString<CAP> { fn cmp(&self, rhs: &Self) -> cmp::Ordering { (**self).cmp(&**rhs) } } -impl<A> FromStr for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> FromStr for ArrayString<CAP> { type Err = CapacityError; @@ -532,8 +529,7 @@ impl<A> FromStr for ArrayString<A> #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl<A> Serialize for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<const CAP: usize> Serialize for ArrayString<CAP> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer @@ -544,8 +540,7 @@ impl<A> Serialize for ArrayString<A> #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl<'de, A> Deserialize<'de> for ArrayString<A> - where A: Array<Item=u8> + Copy +impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP> { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> @@ -553,13 +548,13 @@ impl<'de, A> Deserialize<'de> for ArrayString<A> use serde::de::{self, Visitor}; use std::marker::PhantomData; - struct ArrayStringVisitor<A: Array<Item=u8>>(PhantomData<A>); + struct ArrayStringVisitor<const CAP: usize>(PhantomData<[u8; CAP]>); - impl<'de, A: Copy + Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> { - type Value = ArrayString<A>; + impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor<CAP> { + type Value = ArrayString<CAP>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a string no more than {} bytes long", A::CAPACITY) + write!(formatter, "a string no more than {} bytes long", CAP) } fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> @@ -577,6 +572,29 @@ impl<'de, A> Deserialize<'de> for ArrayString<A> } } - deserializer.deserialize_str(ArrayStringVisitor::<A>(PhantomData)) + deserializer.deserialize_str(ArrayStringVisitor(PhantomData)) + } +} + +impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString<CAP> +{ + type Error = CapacityError<&'a str>; + + fn try_from(f: &'a str) -> Result<Self, Self::Error> { + let mut v = Self::new(); + v.try_push_str(f)?; + Ok(v) + } +} + +impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP> +{ + type Error = CapacityError<fmt::Error>; + + fn try_from(f: fmt::Arguments<'a>) -> Result<Self, Self::Error> { + use fmt::Write; + let mut v = Self::new(); + v.write_fmt(f).map_err(|e| CapacityError::new(e))?; + Ok(v) } } diff --git a/vendor/arrayvec/src/arrayvec.rs b/vendor/arrayvec/src/arrayvec.rs new file mode 100644 index 0000000000..57002372fe --- /dev/null +++ b/vendor/arrayvec/src/arrayvec.rs @@ -0,0 +1,1232 @@ + +use std::cmp; +use std::iter; +use std::mem; +use std::ops::{Bound, Deref, DerefMut, RangeBounds}; +use std::ptr; +use std::slice; + +// extra traits +use std::borrow::{Borrow, BorrowMut}; +use std::hash::{Hash, Hasher}; +use std::fmt; + +#[cfg(feature="std")] +use std::io; + +use std::mem::ManuallyDrop; +use std::mem::MaybeUninit; + +#[cfg(feature="serde")] +use serde::{Serialize, Deserialize, Serializer, Deserializer}; + +use crate::LenUint; +use crate::errors::CapacityError; +use crate::arrayvec_impl::ArrayVecImpl; +use crate::utils::MakeMaybeUninit; + +/// A vector with a fixed capacity. +/// +/// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of +/// the number of initialized elements. The `ArrayVec<T, CAP>` is parameterized +/// by `T` for the element type and `CAP` for the maximum capacity. +/// +/// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger +/// arrayvecs with larger capacity will panic. +/// +/// The vector is a contiguous value (storing the elements inline) that you can store directly on +/// the stack if needed. +/// +/// It offers a simple API but also dereferences to a slice, so that the full slice API is +/// available. The ArrayVec can be converted into a by value iterator. +pub struct ArrayVec<T, const CAP: usize> { + // the `len` first elements of the array are initialized + xs: [MaybeUninit<T>; CAP], + len: LenUint, +} + +impl<T, const CAP: usize> Drop for ArrayVec<T, CAP> { + fn drop(&mut self) { + self.clear(); + + // MaybeUninit inhibits array's drop + } +} + +macro_rules! panic_oob { + ($method_name:expr, $index:expr, $len:expr) => { + panic!(concat!("ArrayVec::", $method_name, ": index {} is out of bounds in vector of length {}"), + $index, $len) + } +} + +impl<T, const CAP: usize> ArrayVec<T, CAP> { + /// Capacity + const CAPACITY: usize = CAP; + + /// Create a new empty `ArrayVec`. + /// + /// The maximum capacity is given by the generic parameter `CAP`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 16>::new(); + /// array.push(1); + /// array.push(2); + /// assert_eq!(&array[..], &[1, 2]); + /// assert_eq!(array.capacity(), 16); + /// ``` + pub fn new() -> ArrayVec<T, CAP> { + assert_capacity_limit!(CAP); + unsafe { + ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } + } + } + + /// Create a new empty `ArrayVec` (const fn). + /// + /// The maximum capacity is given by the generic parameter `CAP`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// static ARRAY: ArrayVec<u8, 1024> = ArrayVec::new_const(); + /// ``` + pub const fn new_const() -> ArrayVec<T, CAP> { + assert_capacity_limit_const!(CAP); + ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 } + } + + /// Return the number of elements in the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// array.pop(); + /// assert_eq!(array.len(), 2); + /// ``` + #[inline(always)] + pub fn len(&self) -> usize { self.len as usize } + + /// Returns whether the `ArrayVec` is empty. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1]); + /// array.pop(); + /// assert_eq!(array.is_empty(), true); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Return the capacity of the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let array = ArrayVec::from([1, 2, 3]); + /// assert_eq!(array.capacity(), 3); + /// ``` + #[inline(always)] + pub fn capacity(&self) -> usize { CAP } + + /// Return true if the `ArrayVec` is completely filled to its capacity, false otherwise. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 1>::new(); + /// assert!(!array.is_full()); + /// array.push(1); + /// assert!(array.is_full()); + /// ``` + pub fn is_full(&self) -> bool { self.len() == self.capacity() } + + /// Returns the capacity left in the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// array.pop(); + /// assert_eq!(array.remaining_capacity(), 1); + /// ``` + pub fn remaining_capacity(&self) -> usize { + self.capacity() - self.len() + } + + /// Push `element` to the end of the vector. + /// + /// ***Panics*** if the vector is already full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// array.push(1); + /// array.push(2); + /// + /// assert_eq!(&array[..], &[1, 2]); + /// ``` + pub fn push(&mut self, element: T) { + ArrayVecImpl::push(self, element) + } + + /// Push `element` to the end of the vector. + /// + /// Return `Ok` if the push succeeds, or return an error if the vector + /// is already full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// let push1 = array.try_push(1); + /// let push2 = array.try_push(2); + /// + /// assert!(push1.is_ok()); + /// assert!(push2.is_ok()); + /// + /// assert_eq!(&array[..], &[1, 2]); + /// + /// let overflow = array.try_push(3); + /// + /// assert!(overflow.is_err()); + /// ``` + pub fn try_push(&mut self, element: T) -> Result<(), CapacityError<T>> { + ArrayVecImpl::try_push(self, element) + } + + /// Push `element` to the end of the vector without checking the capacity. + /// + /// It is up to the caller to ensure the capacity of the vector is + /// sufficiently large. + /// + /// This method uses *debug assertions* to check that the arrayvec is not full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// if array.len() + 2 <= array.capacity() { + /// unsafe { + /// array.push_unchecked(1); + /// array.push_unchecked(2); + /// } + /// } + /// + /// assert_eq!(&array[..], &[1, 2]); + /// ``` + pub unsafe fn push_unchecked(&mut self, element: T) { + ArrayVecImpl::push_unchecked(self, element) + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector’s current length this has no + /// effect. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); + /// array.truncate(3); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// array.truncate(4); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// ``` + pub fn truncate(&mut self, new_len: usize) { + ArrayVecImpl::truncate(self, new_len) + } + + /// Remove all elements in the vector. + pub fn clear(&mut self) { + ArrayVecImpl::clear(self) + } + + + /// Get pointer to where element at `index` would be + unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T { + self.as_mut_ptr().add(index) + } + + /// Insert `element` at position `index`. + /// + /// Shift up all elements after `index`. + /// + /// It is an error if the index is greater than the length or if the + /// arrayvec is full. + /// + /// ***Panics*** if the array is full or the `index` is out of bounds. See + /// `try_insert` for fallible version. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// array.insert(0, "x"); + /// array.insert(0, "y"); + /// assert_eq!(&array[..], &["y", "x"]); + /// + /// ``` + pub fn insert(&mut self, index: usize, element: T) { + self.try_insert(index, element).unwrap() + } + + /// Insert `element` at position `index`. + /// + /// Shift up all elements after `index`; the `index` must be less than + /// or equal to the length. + /// + /// Returns an error if vector is already at full capacity. + /// + /// ***Panics*** `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// assert!(array.try_insert(0, "x").is_ok()); + /// assert!(array.try_insert(0, "y").is_ok()); + /// assert!(array.try_insert(0, "z").is_err()); + /// assert_eq!(&array[..], &["y", "x"]); + /// + /// ``` + pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), CapacityError<T>> { + if index > self.len() { + panic_oob!("try_insert", index, self.len()) + } + if self.len() == self.capacity() { + return Err(CapacityError::new(element)); + } + let len = self.len(); + + // follows is just like Vec<T> + unsafe { // infallible + // The spot to put the new value + { + let p: *mut _ = self.get_unchecked_ptr(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + Ok(()) + } + + /// Remove the last element in the vector and return it. + /// + /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<_, 2>::new(); + /// + /// array.push(1); + /// + /// assert_eq!(array.pop(), Some(1)); + /// assert_eq!(array.pop(), None); + /// ``` + pub fn pop(&mut self) -> Option<T> { + ArrayVecImpl::pop(self) + } + + /// Remove the element at `index` and swap the last element into its place. + /// + /// This operation is O(1). + /// + /// Return the *element* if the index is in bounds, else panic. + /// + /// ***Panics*** if the `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.swap_remove(0), 1); + /// assert_eq!(&array[..], &[3, 2]); + /// + /// assert_eq!(array.swap_remove(1), 2); + /// assert_eq!(&array[..], &[3]); + /// ``` + pub fn swap_remove(&mut self, index: usize) -> T { + self.swap_pop(index) + .unwrap_or_else(|| { + panic_oob!("swap_remove", index, self.len()) + }) + } + + /// Remove the element at `index` and swap the last element into its place. + /// + /// This is a checked version of `.swap_remove`. + /// This operation is O(1). + /// + /// Return `Some(` *element* `)` if the index is in bounds, else `None`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.swap_pop(0), Some(1)); + /// assert_eq!(&array[..], &[3, 2]); + /// + /// assert_eq!(array.swap_pop(10), None); + /// ``` + pub fn swap_pop(&mut self, index: usize) -> Option<T> { + let len = self.len(); + if index >= len { + return None; + } + self.swap(index, len - 1); + self.pop() + } + + /// Remove the element at `index` and shift down the following elements. + /// + /// The `index` must be strictly less than the length of the vector. + /// + /// ***Panics*** if the `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// let removed_elt = array.remove(0); + /// assert_eq!(removed_elt, 1); + /// assert_eq!(&array[..], &[2, 3]); + /// ``` + pub fn remove(&mut self, index: usize) -> T { + self.pop_at(index) + .unwrap_or_else(|| { + panic_oob!("remove", index, self.len()) + }) + } + + /// Remove the element at `index` and shift down the following elements. + /// + /// This is a checked version of `.remove(index)`. Returns `None` if there + /// is no element at `index`. Otherwise, return the element inside `Some`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert!(array.pop_at(0).is_some()); + /// assert_eq!(&array[..], &[2, 3]); + /// + /// assert!(array.pop_at(2).is_none()); + /// assert!(array.pop_at(10).is_none()); + /// ``` + pub fn pop_at(&mut self, index: usize) -> Option<T> { + if index >= self.len() { + None + } else { + self.drain(index..index + 1).next() + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns false. + /// This method operates in place and preserves the order of the retained + /// elements. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4]); + /// array.retain(|x| *x & 1 != 0 ); + /// assert_eq!(&array[..], &[1, 3]); + /// ``` + pub fn retain<F>(&mut self, mut f: F) + where F: FnMut(&mut T) -> bool + { + // Check the implementation of + // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.retain + // for safety arguments (especially regarding panics in f and when + // dropping elements). Implementation closely mirrored here. + + let original_len = self.len(); + unsafe { self.set_len(0) }; + + struct BackshiftOnDrop<'a, T, const CAP: usize> { + v: &'a mut ArrayVec<T, CAP>, + processed_len: usize, + deleted_cnt: usize, + original_len: usize, + } + + impl<T, const CAP: usize> Drop for BackshiftOnDrop<'_, T, CAP> { + fn drop(&mut self) { + if self.deleted_cnt > 0 { + unsafe { + ptr::copy( + self.v.as_ptr().add(self.processed_len), + self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), + self.original_len - self.processed_len + ); + } + } + unsafe { + self.v.set_len(self.original_len - self.deleted_cnt); + } + } + } + + let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; + + while g.processed_len < original_len { + let cur = unsafe { g.v.as_mut_ptr().add(g.processed_len) }; + if !f(unsafe { &mut *cur }) { + g.processed_len += 1; + g.deleted_cnt += 1; + unsafe { ptr::drop_in_place(cur) }; + continue; + } + if g.deleted_cnt > 0 { + unsafe { + let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt); + ptr::copy_nonoverlapping(cur, hole_slot, 1); + } + } + g.processed_len += 1; + } + + drop(g); + } + + /// Set the vector’s length without dropping or moving out elements + /// + /// This method is `unsafe` because it changes the notion of the + /// number of “valid” elements in the vector. Use with care. + /// + /// This method uses *debug assertions* to check that `length` is + /// not greater than the capacity. + pub unsafe fn set_len(&mut self, length: usize) { + // type invariant that capacity always fits in LenUint + debug_assert!(length <= self.capacity()); + self.len = length as LenUint; + } + + /// Copy all elements from the slice and append to the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut vec: ArrayVec<usize, 10> = ArrayVec::new(); + /// vec.push(1); + /// vec.try_extend_from_slice(&[2, 3]).unwrap(); + /// assert_eq!(&vec[..], &[1, 2, 3]); + /// ``` + /// + /// # Errors + /// + /// This method will return an error if the capacity left (see + /// [`remaining_capacity`]) is smaller then the length of the provided + /// slice. + /// + /// [`remaining_capacity`]: #method.remaining_capacity + pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError> + where T: Copy, + { + if self.remaining_capacity() < other.len() { + return Err(CapacityError::new(())); + } + + let self_len = self.len(); + let other_len = other.len(); + + unsafe { + let dst = self.get_unchecked_ptr(self_len); + ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); + self.set_len(self_len + other_len); + } + Ok(()) + } + + /// Create a draining iterator that removes the specified range in the vector + /// and yields the removed items from start to end. The element range is + /// removed even if the iterator is not consumed until the end. + /// + /// Note: It is unspecified how many elements are removed from the vector, + /// if the `Drain` value is leaked. + /// + /// **Panics** if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut v1 = ArrayVec::from([1, 2, 3]); + /// let v2: ArrayVec<_, 3> = v1.drain(0..2).collect(); + /// assert_eq!(&v1[..], &[3]); + /// assert_eq!(&v2[..], &[1, 2]); + /// ``` + pub fn drain<R>(&mut self, range: R) -> Drain<T, CAP> + where R: RangeBounds<usize> + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let start = match range.start_bound() { + Bound::Unbounded => 0, + Bound::Included(&i) => i, + Bound::Excluded(&i) => i.saturating_add(1), + }; + let end = match range.end_bound() { + Bound::Excluded(&j) => j, + Bound::Included(&j) => j.saturating_add(1), + Bound::Unbounded => len, + }; + self.drain_range(start, end) + } + + fn drain_range(&mut self, start: usize, end: usize) -> Drain<T, CAP> + { + let len = self.len(); + + // bounds check happens here (before length is changed!) + let range_slice: *const _ = &self[start..end]; + + // Calling `set_len` creates a fresh and thus unique mutable references, making all + // older aliases we created invalid. So we cannot call that function. + self.len = start as LenUint; + + unsafe { + Drain { + tail_start: end, + tail_len: len - end, + iter: (*range_slice).iter(), + vec: self as *mut _, + } + } + } + + /// Return the inner fixed size array, if it is full to its capacity. + /// + /// Return an `Ok` value with the array if length equals capacity, + /// return an `Err` with self otherwise. + pub fn into_inner(self) -> Result<[T; CAP], Self> { + 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) + } + } + } + + /// Return a slice containing all elements of the vector. + pub fn as_slice(&self) -> &[T] { + ArrayVecImpl::as_slice(self) + } + + /// Return a mutable slice containing all elements of the vector. + pub fn as_mut_slice(&mut self) -> &mut [T] { + ArrayVecImpl::as_mut_slice(self) + } + + /// Return a raw pointer to the vector's buffer. + pub fn as_ptr(&self) -> *const T { + ArrayVecImpl::as_ptr(self) + } + + /// Return a raw mutable pointer to the vector's buffer. + pub fn as_mut_ptr(&mut self) -> *mut T { + ArrayVecImpl::as_mut_ptr(self) + } +} + +impl<T, const CAP: usize> ArrayVecImpl for ArrayVec<T, CAP> { + type Item = T; + const CAPACITY: usize = CAP; + + fn len(&self) -> usize { self.len() } + + unsafe fn set_len(&mut self, length: usize) { + debug_assert!(length <= CAP); + self.len = length as LenUint; + } + + fn as_ptr(&self) -> *const Self::Item { + self.xs.as_ptr() as _ + } + + fn as_mut_ptr(&mut self) -> *mut Self::Item { + self.xs.as_mut_ptr() as _ + } +} + +impl<T, const CAP: usize> Deref for ArrayVec<T, CAP> { + type Target = [T]; + #[inline] + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl<T, const CAP: usize> DerefMut for ArrayVec<T, CAP> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() + } +} + + +/// Create an `ArrayVec` from an array. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// assert_eq!(array.len(), 3); +/// assert_eq!(array.capacity(), 3); +/// ``` +impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> { + fn from(array: [T; CAP]) -> Self { + let array = ManuallyDrop::new(array); + let mut vec = <ArrayVec<T, CAP>>::new(); + unsafe { + (&*array as *const [T; CAP] as *const [MaybeUninit<T>; CAP]) + .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit<T>; CAP], 1); + vec.set_len(CAP); + } + vec + } +} + + +/// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to +/// fit. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// use std::convert::TryInto as _; +/// +/// let array: ArrayVec<_, 4> = (&[1, 2, 3] as &[_]).try_into().unwrap(); +/// assert_eq!(array.len(), 3); +/// assert_eq!(array.capacity(), 4); +/// ``` +impl<T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP> + where T: Clone, +{ + type Error = CapacityError; + + fn try_from(slice: &[T]) -> Result<Self, Self::Error> { + if Self::CAPACITY < slice.len() { + Err(CapacityError::new(())) + } else { + let mut array = Self::new(); + array.extend_from_slice(slice); + Ok(array) + } + } +} + + +/// Iterate the `ArrayVec` with references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &array { +/// // ... +/// } +/// ``` +impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec<T, CAP> { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { self.iter() } +} + +/// Iterate the `ArrayVec` with mutable references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &mut array { +/// // ... +/// } +/// ``` +impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec<T, CAP> { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } +} + +/// Iterate the `ArrayVec` with each element by value. +/// +/// The vector is consumed by this operation. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// for elt in ArrayVec::from([1, 2, 3]) { +/// // ... +/// } +/// ``` +impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> { + type Item = T; + type IntoIter = IntoIter<T, CAP>; + fn into_iter(self) -> IntoIter<T, CAP> { + IntoIter { index: 0, v: self, } + } +} + + +/// By-value iterator for `ArrayVec`. +pub struct IntoIter<T, const CAP: usize> { + index: usize, + v: ArrayVec<T, CAP>, +} + +impl<T, const CAP: usize> Iterator for IntoIter<T, CAP> { + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + if self.index == self.v.len() { + None + } else { + unsafe { + let index = self.index; + self.index = index + 1; + Some(ptr::read(self.v.get_unchecked_ptr(index))) + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.v.len() - self.index; + (len, Some(len)) + } +} + +impl<T, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> { + fn next_back(&mut self) -> Option<Self::Item> { + if self.index == self.v.len() { + None + } else { + unsafe { + let new_len = self.v.len() - 1; + self.v.set_len(new_len); + Some(ptr::read(self.v.get_unchecked_ptr(new_len))) + } + } + } +} + +impl<T, const CAP: usize> ExactSizeIterator for IntoIter<T, CAP> { } + +impl<T, const CAP: usize> Drop for IntoIter<T, CAP> { + fn drop(&mut self) { + // panic safety: Set length to 0 before dropping elements. + let index = self.index; + let len = self.v.len(); + unsafe { + self.v.set_len(0); + let elements = slice::from_raw_parts_mut( + self.v.get_unchecked_ptr(index), + len - index); + ptr::drop_in_place(elements); + } + } +} + +impl<T, const CAP: usize> Clone for IntoIter<T, CAP> +where T: Clone, +{ + fn clone(&self) -> IntoIter<T, CAP> { + let mut v = ArrayVec::new(); + v.extend_from_slice(&self.v[self.index..]); + v.into_iter() + } +} + +impl<T, const CAP: usize> fmt::Debug for IntoIter<T, CAP> +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(&self.v[self.index..]) + .finish() + } +} + +/// A draining iterator for `ArrayVec`. +pub struct Drain<'a, T: 'a, const CAP: usize> { + /// Index of tail to preserve + tail_start: usize, + /// Length of tail + tail_len: usize, + /// Current remaining range to remove + iter: slice::Iter<'a, T>, + vec: *mut ArrayVec<T, CAP>, +} + +unsafe impl<'a, T: Sync, const CAP: usize> Sync for Drain<'a, T, CAP> {} +unsafe impl<'a, T: Send, const CAP: usize> Send for Drain<'a, T, CAP> {} + +impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP> +{ + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } +} + +impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {} + +impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> { + fn drop(&mut self) { + // len is currently 0 so panicking while dropping will not cause a double drop. + + // exhaust self first + while let Some(_) = self.next() { } + + if self.tail_len > 0 { + unsafe { + let source_vec = &mut *self.vec; + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.tail_start; + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.tail_len); + source_vec.set_len(start + self.tail_len); + } + } + } +} + +struct ScopeExitGuard<T, Data, F> + where F: FnMut(&Data, &mut T) +{ + value: T, + data: Data, + f: F, +} + +impl<T, Data, F> Drop for ScopeExitGuard<T, Data, F> + where F: FnMut(&Data, &mut T) +{ + fn drop(&mut self) { + (self.f)(&self.data, &mut self.value) + } +} + + + +/// Extend the `ArrayVec` with an iterator. +/// +/// ***Panics*** if extending the vector exceeds its capacity. +impl<T, const CAP: usize> Extend<T> for ArrayVec<T, CAP> { + /// Extend the `ArrayVec` with an iterator. + /// + /// ***Panics*** if extending the vector exceeds its capacity. + fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) { + unsafe { + self.extend_from_iter::<_, true>(iter) + } + } +} + +#[inline(never)] +#[cold] +fn extend_panic() { + panic!("ArrayVec: capacity exceeded in extend/from_iter"); +} + +impl<T, const CAP: usize> ArrayVec<T, CAP> { + /// Extend the arrayvec from the iterable. + /// + /// ## Safety + /// + /// Unsafe because if CHECK is false, the length of the input is not checked. + /// The caller must ensure the length of the input fits in the capacity. + pub(crate) unsafe fn extend_from_iter<I, const CHECK: bool>(&mut self, iterable: I) + where I: IntoIterator<Item = T> + { + let take = self.capacity() - self.len(); + let len = self.len(); + let mut ptr = raw_ptr_add(self.as_mut_ptr(), len); + let end_ptr = raw_ptr_add(ptr, take); + // Keep the length in a separate variable, write it back on scope + // exit. To help the compiler with alias analysis and stuff. + // We update the length to handle panic in the iteration of the + // user's iterator, without dropping any elements on the floor. + let mut guard = ScopeExitGuard { + value: &mut self.len, + data: len, + f: move |&len, self_len| { + **self_len = len as LenUint; + } + }; + let mut iter = iterable.into_iter(); + loop { + if let Some(elt) = iter.next() { + if ptr == end_ptr && CHECK { extend_panic(); } + debug_assert_ne!(ptr, end_ptr); + ptr.write(elt); + ptr = raw_ptr_add(ptr, 1); + guard.data += 1; + } else { + return; // success + } + } + } + + /// Extend the ArrayVec with clones of elements from the slice; + /// the length of the slice must be <= the remaining capacity in the arrayvec. + pub(crate) fn extend_from_slice(&mut self, slice: &[T]) + where T: Clone + { + let take = self.capacity() - self.len(); + debug_assert!(slice.len() <= take); + unsafe { + let slice = if take < slice.len() { &slice[..take] } else { slice }; + self.extend_from_iter::<_, false>(slice.iter().cloned()); + } + } +} + +/// Rawptr add but uses arithmetic distance for ZST +unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T { + if mem::size_of::<T>() == 0 { + // Special case for ZST + (ptr as usize).wrapping_add(offset) as _ + } else { + ptr.add(offset) + } +} + +/// Create an `ArrayVec` from an iterator. +/// +/// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. +impl<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> { + /// Create an `ArrayVec` from an iterator. + /// + /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. + fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self { + let mut array = ArrayVec::new(); + array.extend(iter); + array + } +} + +impl<T, const CAP: usize> Clone for ArrayVec<T, CAP> + where T: Clone +{ + fn clone(&self) -> Self { + self.iter().cloned().collect() + } + + fn clone_from(&mut self, rhs: &Self) { + // recursive case for the common prefix + let prefix = cmp::min(self.len(), rhs.len()); + self[..prefix].clone_from_slice(&rhs[..prefix]); + + if prefix < self.len() { + // rhs was shorter + for _ in 0..self.len() - prefix { + self.pop(); + } + } else { + let rhs_elems = &rhs[self.len()..]; + self.extend_from_slice(rhs_elems); + } + } +} + +impl<T, const CAP: usize> Hash for ArrayVec<T, CAP> + where T: Hash +{ + fn hash<H: Hasher>(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +impl<T, const CAP: usize> PartialEq for ArrayVec<T, CAP> + where T: PartialEq +{ + fn eq(&self, other: &Self) -> bool { + **self == **other + } +} + +impl<T, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP> + where T: PartialEq +{ + fn eq(&self, other: &[T]) -> bool { + **self == *other + } +} + +impl<T, const CAP: usize> Eq for ArrayVec<T, CAP> where T: Eq { } + +impl<T, const CAP: usize> Borrow<[T]> for ArrayVec<T, CAP> { + fn borrow(&self) -> &[T] { self } +} + +impl<T, const CAP: usize> BorrowMut<[T]> for ArrayVec<T, CAP> { + fn borrow_mut(&mut self) -> &mut [T] { self } +} + +impl<T, const CAP: usize> AsRef<[T]> for ArrayVec<T, CAP> { + fn as_ref(&self) -> &[T] { self } +} + +impl<T, const CAP: usize> AsMut<[T]> for ArrayVec<T, CAP> { + fn as_mut(&mut self) -> &mut [T] { self } +} + +impl<T, const CAP: usize> fmt::Debug for ArrayVec<T, CAP> where T: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +impl<T, const CAP: usize> Default for ArrayVec<T, CAP> { + /// Return an empty array + fn default() -> ArrayVec<T, CAP> { + ArrayVec::new() + } +} + +impl<T, const CAP: usize> PartialOrd for ArrayVec<T, CAP> where T: PartialOrd { + fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { + (**self).partial_cmp(other) + } + + fn lt(&self, other: &Self) -> bool { + (**self).lt(other) + } + + fn le(&self, other: &Self) -> bool { + (**self).le(other) + } + + fn ge(&self, other: &Self) -> bool { + (**self).ge(other) + } + + fn gt(&self, other: &Self) -> bool { + (**self).gt(other) + } +} + +impl<T, const CAP: usize> Ord for ArrayVec<T, CAP> where T: Ord { + fn cmp(&self, other: &Self) -> cmp::Ordering { + (**self).cmp(other) + } +} + +#[cfg(feature="std")] +/// `Write` appends written data to the end of the vector. +/// +/// Requires `features="std"`. +impl<const CAP: usize> io::Write for ArrayVec<u8, CAP> { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + let len = cmp::min(self.remaining_capacity(), data.len()); + let _result = self.try_extend_from_slice(&data[..len]); + debug_assert!(_result.is_ok()); + Ok(len) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<T: Serialize, const CAP: usize> Serialize for ArrayVec<T, CAP> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where S: Serializer + { + serializer.collect_seq(self) + } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T, CAP> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> + { + use serde::de::{Visitor, SeqAccess, Error}; + use std::marker::PhantomData; + + struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>); + + impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> { + type Value = ArrayVec<T, CAP>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "an array with no more than {} items", CAP) + } + + fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error> + where SA: SeqAccess<'de>, + { + let mut values = ArrayVec::<T, CAP>::new(); + + while let Some(value) = seq.next_element()? { + if let Err(_) = values.try_push(value) { + return Err(SA::Error::invalid_length(CAP + 1, &self)); + } + } + + Ok(values) + } + } + + deserializer.deserialize_seq(ArrayVecVisitor::<T, CAP>(PhantomData)) + } +} diff --git a/vendor/arrayvec/src/arrayvec_impl.rs b/vendor/arrayvec/src/arrayvec_impl.rs new file mode 100644 index 0000000000..6c09834add --- /dev/null +++ b/vendor/arrayvec/src/arrayvec_impl.rs @@ -0,0 +1,86 @@ +use std::ptr; +use std::slice; + +use crate::CapacityError; + +/// Implements basic arrayvec methods - based on a few required methods +/// for length and element access. +pub(crate) trait ArrayVecImpl { + type Item; + const CAPACITY: usize; + + fn len(&self) -> usize; + + unsafe fn set_len(&mut self, new_len: usize); + + /// Return a slice containing all elements of the vector. + fn as_slice(&self) -> &[Self::Item] { + let len = self.len(); + unsafe { + slice::from_raw_parts(self.as_ptr(), len) + } + } + + /// Return a mutable slice containing all elements of the vector. + fn as_mut_slice(&mut self) -> &mut [Self::Item] { + let len = self.len(); + unsafe { + std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } + } + + /// Return a raw pointer to the vector's buffer. + fn as_ptr(&self) -> *const Self::Item; + + /// Return a raw mutable pointer to the vector's buffer. + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + fn push(&mut self, element: Self::Item) { + self.try_push(element).unwrap() + } + + fn try_push(&mut self, element: Self::Item) -> Result<(), CapacityError<Self::Item>> { + if self.len() < Self::CAPACITY { + unsafe { + self.push_unchecked(element); + } + Ok(()) + } else { + Err(CapacityError::new(element)) + } + } + + unsafe fn push_unchecked(&mut self, element: Self::Item) { + let len = self.len(); + debug_assert!(len < Self::CAPACITY); + ptr::write(self.as_mut_ptr().add(len), element); + self.set_len(len + 1); + } + + fn pop(&mut self) -> Option<Self::Item> { + if self.len() == 0 { + return None; + } + unsafe { + let new_len = self.len() - 1; + self.set_len(new_len); + Some(ptr::read(self.as_ptr().add(new_len))) + } + } + + fn clear(&mut self) { + self.truncate(0) + } + + fn truncate(&mut self, new_len: usize) { + unsafe { + let len = self.len(); + if new_len < len { + self.set_len(new_len); + let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len); + ptr::drop_in_place(tail); + } + } + } +} + diff --git a/vendor/arrayvec/src/char.rs b/vendor/arrayvec/src/char.rs index 03d64fcd49..939b6b472a 100644 --- a/vendor/arrayvec/src/char.rs +++ b/vendor/arrayvec/src/char.rs @@ -10,8 +10,6 @@ // // Original authors: alexchrichton, bluss -use std::ptr; - // UTF-8 ranges and tags for encoding characters const TAG_CONT: u8 = 0b1000_0000; const TAG_TWO_B: u8 = 0b1100_0000; @@ -24,11 +22,6 @@ const MAX_THREE_B: u32 = 0x10000; /// Placeholder pub struct EncodeUtf8Error; -#[inline] -unsafe fn write(ptr: *mut u8, index: usize, byte: u8) { - ptr::write(ptr.add(index), byte) -} - /// Encode a char into buf using UTF-8. /// /// On success, return the byte length of the encoding (1, 2, 3 or 4).<br> @@ -40,22 +33,22 @@ pub unsafe fn encode_utf8(ch: char, ptr: *mut u8, len: usize) -> Result<usize, E { let code = ch as u32; if code < MAX_ONE_B && len >= 1 { - write(ptr, 0, code as u8); + ptr.add(0).write(code as u8); return Ok(1); } else if code < MAX_TWO_B && len >= 2 { - write(ptr, 0, (code >> 6 & 0x1F) as u8 | TAG_TWO_B); - write(ptr, 1, (code & 0x3F) as u8 | TAG_CONT); + ptr.add(0).write((code >> 6 & 0x1F) as u8 | TAG_TWO_B); + ptr.add(1).write((code & 0x3F) as u8 | TAG_CONT); return Ok(2); } else if code < MAX_THREE_B && len >= 3 { - write(ptr, 0, (code >> 12 & 0x0F) as u8 | TAG_THREE_B); - write(ptr, 1, (code >> 6 & 0x3F) as u8 | TAG_CONT); - write(ptr, 2, (code & 0x3F) as u8 | TAG_CONT); + ptr.add(0).write((code >> 12 & 0x0F) as u8 | TAG_THREE_B); + ptr.add(1).write((code >> 6 & 0x3F) as u8 | TAG_CONT); + ptr.add(2).write((code & 0x3F) as u8 | TAG_CONT); return Ok(3); } else if len >= 4 { - write(ptr, 0, (code >> 18 & 0x07) as u8 | TAG_FOUR_B); - write(ptr, 1, (code >> 12 & 0x3F) as u8 | TAG_CONT); - write(ptr, 2, (code >> 6 & 0x3F) as u8 | TAG_CONT); - write(ptr, 3, (code & 0x3F) as u8 | TAG_CONT); + ptr.add(0).write((code >> 18 & 0x07) as u8 | TAG_FOUR_B); + ptr.add(1).write((code >> 12 & 0x3F) as u8 | TAG_CONT); + ptr.add(2).write((code >> 6 & 0x3F) as u8 | TAG_CONT); + ptr.add(3).write((code & 0x3F) as u8 | TAG_CONT); return Ok(4); }; Err(EncodeUtf8Error) diff --git a/vendor/arrayvec/src/lib.rs b/vendor/arrayvec/src/lib.rs index a5d6c06068..d5a032014e 100644 --- a/vendor/arrayvec/src/lib.rs +++ b/vendor/arrayvec/src/lib.rs @@ -1,4 +1,4 @@ -//! **arrayvec** provides the types `ArrayVec` and `ArrayString`: +//! **arrayvec** provides the types [`ArrayVec`] and [`ArrayString`]: //! array-backed vector and string types, which store their contents inline. //! //! The arrayvec package has the following cargo features: @@ -10,23 +10,13 @@ //! - `serde` //! - Optional //! - Enable serialization for ArrayVec and ArrayString using serde 1.x -//! - `array-sizes-33-128`, `array-sizes-129-255` -//! - Optional -//! - Enable more array sizes (see [Array] for more information) -//! -//! - `unstable-const-fn` -//! - Optional -//! - Makes [`ArrayVec::new`] and [`ArrayString::new`] `const fn`s, -//! using the nightly `const_fn` feature. -//! - Unstable and requires nightly. //! //! ## Rust Version //! -//! This version of arrayvec requires Rust 1.36 or later. +//! This version of arrayvec requires Rust 1.51 or later. //! -#![doc(html_root_url="https://docs.rs/arrayvec/0.4/")] +#![doc(html_root_url="https://docs.rs/arrayvec/0.6/")] #![cfg_attr(not(feature="std"), no_std)] -#![cfg_attr(feature="unstable-const-fn", feature(const_fn))] #[cfg(feature="serde")] extern crate serde; @@ -34,1180 +24,36 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -use std::cmp; -use std::iter; -use std::mem; -use std::ops::{Bound, Deref, DerefMut, RangeBounds}; -use std::ptr; -use std::slice; - -// extra traits -use std::borrow::{Borrow, BorrowMut}; -use std::hash::{Hash, Hasher}; -use std::fmt; - -#[cfg(feature="std")] -use std::io; - - -mod maybe_uninit; -use crate::maybe_uninit::MaybeUninit; - -#[cfg(feature="serde")] -use serde::{Serialize, Deserialize, Serializer, Deserializer}; - -mod array; -mod array_string; -mod char; -mod errors; - -pub use crate::array::Array; -use crate::array::Index; -pub use crate::array_string::ArrayString; -pub use crate::errors::CapacityError; - - -/// A vector with a fixed capacity. -/// -/// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of -/// the number of initialized elements. -/// -/// The vector is a contiguous value that you can store directly on the stack -/// if needed. -/// -/// It offers a simple API but also dereferences to a slice, so -/// that the full slice API is available. -/// -/// ArrayVec can be converted into a by value iterator. -pub struct ArrayVec<A: Array> { - xs: MaybeUninit<A>, - len: A::Index, -} - -impl<A: Array> Drop for ArrayVec<A> { - fn drop(&mut self) { - self.clear(); - - // MaybeUninit inhibits array's drop - } -} - -macro_rules! panic_oob { - ($method_name:expr, $index:expr, $len:expr) => { - panic!(concat!("ArrayVec::", $method_name, ": index {} is out of bounds in vector of length {}"), - $index, $len) - } -} - -impl<A: Array> ArrayVec<A> { - /// Create a new empty `ArrayVec`. - /// - /// Capacity is inferred from the type parameter. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 16]>::new(); - /// array.push(1); - /// array.push(2); - /// assert_eq!(&array[..], &[1, 2]); - /// assert_eq!(array.capacity(), 16); - /// ``` - #[cfg(not(feature="unstable-const-fn"))] - pub fn new() -> ArrayVec<A> { - unsafe { - ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } - } - } - - #[cfg(feature="unstable-const-fn")] - pub const fn new() -> ArrayVec<A> { - unsafe { - ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } - } - } - - /// Return the number of elements in the `ArrayVec`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// array.pop(); - /// assert_eq!(array.len(), 2); - /// ``` - #[inline] - pub fn len(&self) -> usize { self.len.to_usize() } - - /// Returns whether the `ArrayVec` is empty. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1]); - /// array.pop(); - /// assert_eq!(array.is_empty(), true); - /// ``` - #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } +pub(crate) type LenUint = u32; - /// Return the capacity of the `ArrayVec`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let array = ArrayVec::from([1, 2, 3]); - /// assert_eq!(array.capacity(), 3); - /// ``` - #[inline(always)] - pub fn capacity(&self) -> usize { A::CAPACITY } - - /// Return if the `ArrayVec` is completely filled. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 1]>::new(); - /// assert!(!array.is_full()); - /// array.push(1); - /// assert!(array.is_full()); - /// ``` - pub fn is_full(&self) -> bool { self.len() == self.capacity() } - - /// Returns the capacity left in the `ArrayVec`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// array.pop(); - /// assert_eq!(array.remaining_capacity(), 1); - /// ``` - pub fn remaining_capacity(&self) -> usize { - self.capacity() - self.len() - } - - /// Push `element` to the end of the vector. - /// - /// ***Panics*** if the vector is already full. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// array.push(1); - /// array.push(2); - /// - /// assert_eq!(&array[..], &[1, 2]); - /// ``` - pub fn push(&mut self, element: A::Item) { - self.try_push(element).unwrap() - } - - /// Push `element` to the end of the vector. - /// - /// Return `Ok` if the push succeeds, or return an error if the vector - /// is already full. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// let push1 = array.try_push(1); - /// let push2 = array.try_push(2); - /// - /// assert!(push1.is_ok()); - /// assert!(push2.is_ok()); - /// - /// assert_eq!(&array[..], &[1, 2]); - /// - /// let overflow = array.try_push(3); - /// - /// assert!(overflow.is_err()); - /// ``` - pub fn try_push(&mut self, element: A::Item) -> Result<(), CapacityError<A::Item>> { - if self.len() < A::CAPACITY { - unsafe { - self.push_unchecked(element); - } - Ok(()) - } else { - Err(CapacityError::new(element)) - } - } - - - /// Push `element` to the end of the vector without checking the capacity. - /// - /// It is up to the caller to ensure the capacity of the vector is - /// sufficiently large. - /// - /// This method uses *debug assertions* to check that the arrayvec is not full. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// if array.len() + 2 <= array.capacity() { - /// unsafe { - /// array.push_unchecked(1); - /// array.push_unchecked(2); - /// } - /// } - /// - /// assert_eq!(&array[..], &[1, 2]); - /// ``` - pub unsafe fn push_unchecked(&mut self, element: A::Item) { - let len = self.len(); - debug_assert!(len < A::CAPACITY); - ptr::write(self.get_unchecked_ptr(len), element); - self.set_len(len + 1); - } - - /// Get pointer to where element at `index` would be - unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut A::Item { - self.xs.ptr_mut().add(index) - } - - /// Insert `element` at position `index`. - /// - /// Shift up all elements after `index`. - /// - /// It is an error if the index is greater than the length or if the - /// arrayvec is full. - /// - /// ***Panics*** if the array is full or the `index` is out of bounds. See - /// `try_insert` for fallible version. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// array.insert(0, "x"); - /// array.insert(0, "y"); - /// assert_eq!(&array[..], &["y", "x"]); - /// - /// ``` - pub fn insert(&mut self, index: usize, element: A::Item) { - self.try_insert(index, element).unwrap() - } - - /// Insert `element` at position `index`. - /// - /// Shift up all elements after `index`; the `index` must be less than - /// or equal to the length. - /// - /// Returns an error if vector is already at full capacity. - /// - /// ***Panics*** `index` is out of bounds. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// assert!(array.try_insert(0, "x").is_ok()); - /// assert!(array.try_insert(0, "y").is_ok()); - /// assert!(array.try_insert(0, "z").is_err()); - /// assert_eq!(&array[..], &["y", "x"]); - /// - /// ``` - pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityError<A::Item>> { - if index > self.len() { - panic_oob!("try_insert", index, self.len()) - } - if self.len() == self.capacity() { - return Err(CapacityError::new(element)); - } - let len = self.len(); - - // follows is just like Vec<T> - unsafe { // infallible - // The spot to put the new value - { - let p: *mut _ = self.get_unchecked_ptr(index); - // Shift everything over to make space. (Duplicating the - // `index`th element into two consecutive places.) - ptr::copy(p, p.offset(1), len - index); - // Write it in, overwriting the first copy of the `index`th - // element. - ptr::write(p, element); +macro_rules! assert_capacity_limit { + ($cap:expr) => { + if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() { + if $cap > LenUint::MAX as usize { + panic!("ArrayVec: largest supported capacity is u32::MAX") } - self.set_len(len + 1); - } - Ok(()) - } - - /// Remove the last element in the vector and return it. - /// - /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::<[_; 2]>::new(); - /// - /// array.push(1); - /// - /// assert_eq!(array.pop(), Some(1)); - /// assert_eq!(array.pop(), None); - /// ``` - pub fn pop(&mut self) -> Option<A::Item> { - if self.len() == 0 { - return None; - } - unsafe { - let new_len = self.len() - 1; - self.set_len(new_len); - Some(ptr::read(self.get_unchecked_ptr(new_len))) - } - } - - /// Remove the element at `index` and swap the last element into its place. - /// - /// This operation is O(1). - /// - /// Return the *element* if the index is in bounds, else panic. - /// - /// ***Panics*** if the `index` is out of bounds. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// - /// assert_eq!(array.swap_remove(0), 1); - /// assert_eq!(&array[..], &[3, 2]); - /// - /// assert_eq!(array.swap_remove(1), 2); - /// assert_eq!(&array[..], &[3]); - /// ``` - pub fn swap_remove(&mut self, index: usize) -> A::Item { - self.swap_pop(index) - .unwrap_or_else(|| { - panic_oob!("swap_remove", index, self.len()) - }) - } - - /// Remove the element at `index` and swap the last element into its place. - /// - /// This is a checked version of `.swap_remove`. - /// This operation is O(1). - /// - /// Return `Some(` *element* `)` if the index is in bounds, else `None`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// - /// assert_eq!(array.swap_pop(0), Some(1)); - /// assert_eq!(&array[..], &[3, 2]); - /// - /// assert_eq!(array.swap_pop(10), None); - /// ``` - pub fn swap_pop(&mut self, index: usize) -> Option<A::Item> { - let len = self.len(); - if index >= len { - return None; - } - self.swap(index, len - 1); - self.pop() - } - - /// Remove the element at `index` and shift down the following elements. - /// - /// The `index` must be strictly less than the length of the vector. - /// - /// ***Panics*** if the `index` is out of bounds. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// - /// let removed_elt = array.remove(0); - /// assert_eq!(removed_elt, 1); - /// assert_eq!(&array[..], &[2, 3]); - /// ``` - pub fn remove(&mut self, index: usize) -> A::Item { - self.pop_at(index) - .unwrap_or_else(|| { - panic_oob!("remove", index, self.len()) - }) - } - - /// Remove the element at `index` and shift down the following elements. - /// - /// This is a checked version of `.remove(index)`. Returns `None` if there - /// is no element at `index`. Otherwise, return the element inside `Some`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3]); - /// - /// assert!(array.pop_at(0).is_some()); - /// assert_eq!(&array[..], &[2, 3]); - /// - /// assert!(array.pop_at(2).is_none()); - /// assert!(array.pop_at(10).is_none()); - /// ``` - pub fn pop_at(&mut self, index: usize) -> Option<A::Item> { - if index >= self.len() { - None - } else { - self.drain(index..index + 1).next() - } - } - - /// Shortens the vector, keeping the first `len` elements and dropping - /// the rest. - /// - /// If `len` is greater than the vector’s current length this has no - /// effect. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); - /// array.truncate(3); - /// assert_eq!(&array[..], &[1, 2, 3]); - /// array.truncate(4); - /// assert_eq!(&array[..], &[1, 2, 3]); - /// ``` - pub fn truncate(&mut self, new_len: usize) { - unsafe { - if new_len < self.len() { - let tail: *mut [_] = &mut self[new_len..]; - self.len = Index::from(new_len); - ptr::drop_in_place(tail); - } - } - } - - /// Remove all elements in the vector. - pub fn clear(&mut self) { - self.truncate(0) - } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&mut e)` returns false. - /// This method operates in place and preserves the order of the retained - /// elements. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3, 4]); - /// array.retain(|x| *x & 1 != 0 ); - /// assert_eq!(&array[..], &[1, 3]); - /// ``` - pub fn retain<F>(&mut self, mut f: F) - where F: FnMut(&mut A::Item) -> bool - { - let len = self.len(); - let mut del = 0; - { - let v = &mut **self; - - for i in 0..len { - if !f(&mut v[i]) { - del += 1; - } else if del > 0 { - v.swap(i - del, i); - } - } - } - if del > 0 { - self.drain(len - del..); - } - } - - /// Set the vector’s length without dropping or moving out elements - /// - /// This method is `unsafe` because it changes the notion of the - /// number of “valid” elements in the vector. Use with care. - /// - /// This method uses *debug assertions* to check that `length` is - /// not greater than the capacity. - pub unsafe fn set_len(&mut self, length: usize) { - debug_assert!(length <= self.capacity()); - self.len = Index::from(length); - } - - /// Copy and appends all elements in a slice to the `ArrayVec`. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); - /// vec.push(1); - /// vec.try_extend_from_slice(&[2, 3]).unwrap(); - /// assert_eq!(&vec[..], &[1, 2, 3]); - /// ``` - /// - /// # Errors - /// - /// This method will return an error if the capacity left (see - /// [`remaining_capacity`]) is smaller then the length of the provided - /// slice. - /// - /// [`remaining_capacity`]: #method.remaining_capacity - pub fn try_extend_from_slice(&mut self, other: &[A::Item]) -> Result<(), CapacityError> - where A::Item: Copy, - { - if self.remaining_capacity() < other.len() { - return Err(CapacityError::new(())); - } - - let self_len = self.len(); - let other_len = other.len(); - - unsafe { - let dst = self.xs.ptr_mut().add(self_len); - ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); - self.set_len(self_len + other_len); - } - Ok(()) - } - - /// Create a draining iterator that removes the specified range in the vector - /// and yields the removed items from start to end. The element range is - /// removed even if the iterator is not consumed until the end. - /// - /// Note: It is unspecified how many elements are removed from the vector, - /// if the `Drain` value is leaked. - /// - /// **Panics** if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut v = ArrayVec::from([1, 2, 3]); - /// let u: ArrayVec<[_; 3]> = v.drain(0..2).collect(); - /// assert_eq!(&v[..], &[3]); - /// assert_eq!(&u[..], &[1, 2]); - /// ``` - pub fn drain<R>(&mut self, range: R) -> Drain<A> - where R: RangeBounds<usize> - { - // Memory safety - // - // When the Drain is first created, it shortens the length of - // the source vector to make sure no uninitialized or moved-from elements - // are accessible at all if the Drain's destructor never gets to run. - // - // Drain will ptr::read out the values to remove. - // When finished, remaining tail of the vec is copied back to cover - // the hole, and the vector length is restored to the new length. - // - let len = self.len(); - let start = match range.start_bound() { - Bound::Unbounded => 0, - Bound::Included(&i) => i, - Bound::Excluded(&i) => i.saturating_add(1), - }; - let end = match range.end_bound() { - Bound::Excluded(&j) => j, - Bound::Included(&j) => j.saturating_add(1), - Bound::Unbounded => len, - }; - self.drain_range(start, end) - } - - fn drain_range(&mut self, start: usize, end: usize) -> Drain<A> - { - let len = self.len(); - - // bounds check happens here (before length is changed!) - let range_slice: *const _ = &self[start..end]; - - // Calling `set_len` creates a fresh and thus unique mutable references, making all - // older aliases we created invalid. So we cannot call that function. - self.len = Index::from(start); - - unsafe { - Drain { - tail_start: end, - tail_len: len - end, - iter: (*range_slice).iter(), - vec: self as *mut _, - } - } - } - - /// Return the inner fixed size array, if it is full to its capacity. - /// - /// Return an `Ok` value with the array if length equals capacity, - /// return an `Err` with self otherwise. - pub fn into_inner(self) -> Result<A, Self> { - if self.len() < self.capacity() { - Err(self) - } else { - unsafe { - let array = ptr::read(self.xs.ptr() as *const A); - mem::forget(self); - Ok(array) - } - } - } - - /// Dispose of `self` (same as drop) - #[deprecated="Use std::mem::drop instead, if at all needed."] - pub fn dispose(mut self) { - self.clear(); - mem::forget(self); - } - - /// Return a slice containing all elements of the vector. - pub fn as_slice(&self) -> &[A::Item] { - self - } - - /// Return a mutable slice containing all elements of the vector. - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { - self - } - - /// Return a raw pointer to the vector's buffer. - pub fn as_ptr(&self) -> *const A::Item { - self.xs.ptr() - } - - /// Return a raw mutable pointer to the vector's buffer. - pub fn as_mut_ptr(&mut self) -> *mut A::Item { - self.xs.ptr_mut() - } -} - -impl<A: Array> Deref for ArrayVec<A> { - type Target = [A::Item]; - #[inline] - fn deref(&self) -> &[A::Item] { - unsafe { - slice::from_raw_parts(self.xs.ptr(), self.len()) - } - } -} - -impl<A: Array> DerefMut for ArrayVec<A> { - #[inline] - fn deref_mut(&mut self) -> &mut [A::Item] { - let len = self.len(); - unsafe { - slice::from_raw_parts_mut(self.xs.ptr_mut(), len) } } } -/// Create an `ArrayVec` from an array. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// let mut array = ArrayVec::from([1, 2, 3]); -/// assert_eq!(array.len(), 3); -/// assert_eq!(array.capacity(), 3); -/// ``` -impl<A: Array> From<A> for ArrayVec<A> { - fn from(array: A) -> Self { - ArrayVec { xs: MaybeUninit::from(array), len: Index::from(A::CAPACITY) } - } -} - - -/// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to -/// fit. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// use std::convert::TryInto as _; -/// -/// let array: ArrayVec<[_; 4]> = (&[1, 2, 3] as &[_]).try_into().unwrap(); -/// assert_eq!(array.len(), 3); -/// assert_eq!(array.capacity(), 4); -/// ``` -impl<A: Array> std::convert::TryFrom<&[A::Item]> for ArrayVec<A> - where - A::Item: Clone, -{ - type Error = CapacityError; - - fn try_from(slice: &[A::Item]) -> Result<Self, Self::Error> { - if A::CAPACITY < slice.len() { - Err(CapacityError::new(())) - } else { - let mut array = Self::new(); - array.extend(slice.iter().cloned()); - Ok(array) - } - } -} - - -/// Iterate the `ArrayVec` with references to each element. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// let array = ArrayVec::from([1, 2, 3]); -/// -/// for elt in &array { -/// // ... -/// } -/// ``` -impl<'a, A: Array> IntoIterator for &'a ArrayVec<A> { - type Item = &'a A::Item; - type IntoIter = slice::Iter<'a, A::Item>; - fn into_iter(self) -> Self::IntoIter { self.iter() } -} - -/// Iterate the `ArrayVec` with mutable references to each element. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// let mut array = ArrayVec::from([1, 2, 3]); -/// -/// for elt in &mut array { -/// // ... -/// } -/// ``` -impl<'a, A: Array> IntoIterator for &'a mut ArrayVec<A> { - type Item = &'a mut A::Item; - type IntoIter = slice::IterMut<'a, A::Item>; - fn into_iter(self) -> Self::IntoIter { self.iter_mut() } -} - -/// Iterate the `ArrayVec` with each element by value. -/// -/// The vector is consumed by this operation. -/// -/// ``` -/// use arrayvec::ArrayVec; -/// -/// for elt in ArrayVec::from([1, 2, 3]) { -/// // ... -/// } -/// ``` -impl<A: Array> IntoIterator for ArrayVec<A> { - type Item = A::Item; - type IntoIter = IntoIter<A>; - fn into_iter(self) -> IntoIter<A> { - IntoIter { index: Index::from(0), v: self, } - } -} - - -/// By-value iterator for `ArrayVec`. -pub struct IntoIter<A: Array> { - index: A::Index, - v: ArrayVec<A>, -} - -impl<A: Array> Iterator for IntoIter<A> { - type Item = A::Item; - - fn next(&mut self) -> Option<A::Item> { - if self.index == self.v.len { - None - } else { - unsafe { - let index = self.index.to_usize(); - self.index = Index::from(index + 1); - Some(ptr::read(self.v.get_unchecked_ptr(index))) - } - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - let len = self.v.len() - self.index.to_usize(); - (len, Some(len)) - } -} - -impl<A: Array> DoubleEndedIterator for IntoIter<A> { - fn next_back(&mut self) -> Option<A::Item> { - if self.index == self.v.len { - None - } else { - unsafe { - let new_len = self.v.len() - 1; - self.v.set_len(new_len); - Some(ptr::read(self.v.get_unchecked_ptr(new_len))) - } - } - } -} - -impl<A: Array> ExactSizeIterator for IntoIter<A> { } - -impl<A: Array> Drop for IntoIter<A> { - fn drop(&mut self) { - // panic safety: Set length to 0 before dropping elements. - let index = self.index.to_usize(); - let len = self.v.len(); - unsafe { - self.v.set_len(0); - let elements = slice::from_raw_parts_mut( - self.v.get_unchecked_ptr(index), - len - index); - ptr::drop_in_place(elements); - } - } -} - -impl<A: Array> Clone for IntoIter<A> -where - A::Item: Clone, -{ - fn clone(&self) -> IntoIter<A> { - self.v[self.index.to_usize()..] - .iter() - .cloned() - .collect::<ArrayVec<A>>() - .into_iter() - } -} - -impl<A: Array> fmt::Debug for IntoIter<A> -where - A::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_list() - .entries(&self.v[self.index.to_usize()..]) - .finish() - } -} - -/// A draining iterator for `ArrayVec`. -pub struct Drain<'a, A> - where A: Array, - A::Item: 'a, -{ - /// Index of tail to preserve - tail_start: usize, - /// Length of tail - tail_len: usize, - /// Current remaining range to remove - iter: slice::Iter<'a, A::Item>, - vec: *mut ArrayVec<A>, -} - -unsafe impl<'a, A: Array + Sync> Sync for Drain<'a, A> {} -unsafe impl<'a, A: Array + Send> Send for Drain<'a, A> {} - -impl<'a, A: Array> Iterator for Drain<'a, A> - where A::Item: 'a, -{ - type Item = A::Item; - - fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|elt| - unsafe { - ptr::read(elt as *const _) - } - ) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> - where A::Item: 'a, -{ - fn next_back(&mut self) -> Option<Self::Item> { - self.iter.next_back().map(|elt| - unsafe { - ptr::read(elt as *const _) - } - ) - } -} - -impl<'a, A: Array> ExactSizeIterator for Drain<'a, A> where A::Item: 'a {} - -impl<'a, A: Array> Drop for Drain<'a, A> - where A::Item: 'a -{ - fn drop(&mut self) { - // len is currently 0 so panicking while dropping will not cause a double drop. - - // exhaust self first - while let Some(_) = self.next() { } - - if self.tail_len > 0 { - unsafe { - let source_vec = &mut *self.vec; - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.tail_start; - let src = source_vec.as_ptr().add(tail); - let dst = source_vec.as_mut_ptr().add(start); - ptr::copy(src, dst, self.tail_len); - source_vec.set_len(start + self.tail_len); - } - } - } -} - -struct ScopeExitGuard<T, Data, F> - where F: FnMut(&Data, &mut T) -{ - value: T, - data: Data, - f: F, -} - -impl<T, Data, F> Drop for ScopeExitGuard<T, Data, F> - where F: FnMut(&Data, &mut T) -{ - fn drop(&mut self) { - (self.f)(&self.data, &mut self.value) - } -} - - - -/// Extend the `ArrayVec` with an iterator. -/// -/// Does not extract more items than there is space for. No error -/// occurs if there are more iterator elements. -impl<A: Array> Extend<A::Item> for ArrayVec<A> { - fn extend<T: IntoIterator<Item=A::Item>>(&mut self, iter: T) { - let take = self.capacity() - self.len(); - unsafe { - let len = self.len(); - let mut ptr = raw_ptr_add(self.as_mut_ptr(), len); - let end_ptr = raw_ptr_add(ptr, take); - // Keep the length in a separate variable, write it back on scope - // exit. To help the compiler with alias analysis and stuff. - // We update the length to handle panic in the iteration of the - // user's iterator, without dropping any elements on the floor. - let mut guard = ScopeExitGuard { - value: &mut self.len, - data: len, - f: move |&len, self_len| { - **self_len = Index::from(len); - } - }; - let mut iter = iter.into_iter(); - loop { - if ptr == end_ptr { break; } - if let Some(elt) = iter.next() { - raw_ptr_write(ptr, elt); - ptr = raw_ptr_add(ptr, 1); - guard.data += 1; - } else { - break; - } - } - } - } -} - -/// Rawptr add but uses arithmetic distance for ZST -unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T { - if mem::size_of::<T>() == 0 { - // Special case for ZST - (ptr as usize).wrapping_add(offset) as _ - } else { - ptr.add(offset) - } -} - -unsafe fn raw_ptr_write<T>(ptr: *mut T, value: T) { - if mem::size_of::<T>() == 0 { - /* nothing */ - } else { - ptr::write(ptr, value) - } -} - -/// Create an `ArrayVec` from an iterator. -/// -/// Does not extract more items than there is space for. No error -/// occurs if there are more iterator elements. -impl<A: Array> iter::FromIterator<A::Item> for ArrayVec<A> { - fn from_iter<T: IntoIterator<Item=A::Item>>(iter: T) -> Self { - let mut array = ArrayVec::new(); - array.extend(iter); - array - } -} - -impl<A: Array> Clone for ArrayVec<A> - where A::Item: Clone -{ - fn clone(&self) -> Self { - self.iter().cloned().collect() - } - - fn clone_from(&mut self, rhs: &Self) { - // recursive case for the common prefix - let prefix = cmp::min(self.len(), rhs.len()); - self[..prefix].clone_from_slice(&rhs[..prefix]); - - if prefix < self.len() { - // rhs was shorter - for _ in 0..self.len() - prefix { - self.pop(); +macro_rules! assert_capacity_limit_const { + ($cap:expr) => { + if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() { + if $cap > LenUint::MAX as usize { + [/*ArrayVec: largest supported capacity is u32::MAX*/][$cap] } - } else { - let rhs_elems = rhs[self.len()..].iter().cloned(); - self.extend(rhs_elems); } } } -impl<A: Array> Hash for ArrayVec<A> - where A::Item: Hash -{ - fn hash<H: Hasher>(&self, state: &mut H) { - Hash::hash(&**self, state) - } -} - -impl<A: Array> PartialEq for ArrayVec<A> - where A::Item: PartialEq -{ - fn eq(&self, other: &Self) -> bool { - **self == **other - } -} - -impl<A: Array> PartialEq<[A::Item]> for ArrayVec<A> - where A::Item: PartialEq -{ - fn eq(&self, other: &[A::Item]) -> bool { - **self == *other - } -} - -impl<A: Array> Eq for ArrayVec<A> where A::Item: Eq { } - -impl<A: Array> Borrow<[A::Item]> for ArrayVec<A> { - fn borrow(&self) -> &[A::Item] { self } -} - -impl<A: Array> BorrowMut<[A::Item]> for ArrayVec<A> { - fn borrow_mut(&mut self) -> &mut [A::Item] { self } -} - -impl<A: Array> AsRef<[A::Item]> for ArrayVec<A> { - fn as_ref(&self) -> &[A::Item] { self } -} - -impl<A: Array> AsMut<[A::Item]> for ArrayVec<A> { - fn as_mut(&mut self) -> &mut [A::Item] { self } -} - -impl<A: Array> fmt::Debug for ArrayVec<A> where A::Item: fmt::Debug { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } -} - -impl<A: Array> Default for ArrayVec<A> { - /// Return an empty array - fn default() -> ArrayVec<A> { - ArrayVec::new() - } -} - -impl<A: Array> PartialOrd for ArrayVec<A> where A::Item: PartialOrd { - fn partial_cmp(&self, other: &ArrayVec<A>) -> Option<cmp::Ordering> { - (**self).partial_cmp(other) - } - - fn lt(&self, other: &Self) -> bool { - (**self).lt(other) - } - - fn le(&self, other: &Self) -> bool { - (**self).le(other) - } - - fn ge(&self, other: &Self) -> bool { - (**self).ge(other) - } - - fn gt(&self, other: &Self) -> bool { - (**self).gt(other) - } -} - -impl<A: Array> Ord for ArrayVec<A> where A::Item: Ord { - fn cmp(&self, other: &ArrayVec<A>) -> cmp::Ordering { - (**self).cmp(other) - } -} - -#[cfg(feature="std")] -/// `Write` appends written data to the end of the vector. -/// -/// Requires `features="std"`. -impl<A: Array<Item=u8>> io::Write for ArrayVec<A> { - fn write(&mut self, data: &[u8]) -> io::Result<usize> { - let len = cmp::min(self.remaining_capacity(), data.len()); - let _result = self.try_extend_from_slice(&data[..len]); - debug_assert!(_result.is_ok()); - Ok(len) - } - fn flush(&mut self) -> io::Result<()> { Ok(()) } -} - -#[cfg(feature="serde")] -/// Requires crate feature `"serde"` -impl<T: Serialize, A: Array<Item=T>> Serialize for ArrayVec<A> { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where S: Serializer - { - serializer.collect_seq(self) - } -} - -#[cfg(feature="serde")] -/// Requires crate feature `"serde"` -impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Deserialize<'de> for ArrayVec<A> { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where D: Deserializer<'de> - { - use serde::de::{Visitor, SeqAccess, Error}; - use std::marker::PhantomData; - - struct ArrayVecVisitor<'de, T: Deserialize<'de>, A: Array<Item=T>>(PhantomData<(&'de (), T, A)>); - - impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Visitor<'de> for ArrayVecVisitor<'de, T, A> { - type Value = ArrayVec<A>; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "an array with no more than {} items", A::CAPACITY) - } - - fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error> - where SA: SeqAccess<'de>, - { - let mut values = ArrayVec::<A>::new(); - - while let Some(value) = seq.next_element()? { - if let Err(_) = values.try_push(value) { - return Err(SA::Error::invalid_length(A::CAPACITY + 1, &self)); - } - } +mod arrayvec_impl; +mod arrayvec; +mod array_string; +mod char; +mod errors; +mod utils; - Ok(values) - } - } +pub use crate::array_string::ArrayString; +pub use crate::errors::CapacityError; - deserializer.deserialize_seq(ArrayVecVisitor::<T, A>(PhantomData)) - } -} +pub use crate::arrayvec::{ArrayVec, IntoIter, Drain}; diff --git a/vendor/arrayvec/src/maybe_uninit.rs b/vendor/arrayvec/src/maybe_uninit.rs deleted file mode 100644 index e009abfc8e..0000000000 --- a/vendor/arrayvec/src/maybe_uninit.rs +++ /dev/null @@ -1,44 +0,0 @@ - - -use crate::array::Array; -use std::mem::MaybeUninit as StdMaybeUninit; - -#[derive(Copy)] -pub struct MaybeUninit<T> { - inner: StdMaybeUninit<T>, -} - -impl<T> Clone for MaybeUninit<T> - where T: Copy -{ - fn clone(&self) -> Self { *self } -} - -impl<T> MaybeUninit<T> { - /// Create a new MaybeUninit with uninitialized interior - pub const unsafe fn uninitialized() -> Self { - MaybeUninit { inner: StdMaybeUninit::uninit() } - } - - /// Create a new MaybeUninit from the value `v`. - pub fn from(v: T) -> Self { - MaybeUninit { inner: StdMaybeUninit::new(v) } - } - - // Raw pointer casts written so that we don't reference or access the - // uninitialized interior value - - /// Return a raw pointer to the start of the interior array - pub fn ptr(&self) -> *const T::Item - where T: Array - { - self.inner.as_ptr() as *const T::Item - } - - /// Return a mut raw pointer to the start of the interior array - pub fn ptr_mut(&mut self) -> *mut T::Item - where T: Array - { - self.inner.as_mut_ptr() as *mut T::Item - } -} diff --git a/vendor/arrayvec/src/utils.rs b/vendor/arrayvec/src/utils.rs new file mode 100644 index 0000000000..b8e5ddb323 --- /dev/null +++ b/vendor/arrayvec/src/utils.rs @@ -0,0 +1,11 @@ +use std::marker::PhantomData; +use std::mem::MaybeUninit; + +pub(crate) struct MakeMaybeUninit<T, const N: usize>(PhantomData<fn() -> T>); + +impl<T, const N: usize> MakeMaybeUninit<T, N> { + pub(crate) const VALUE: MaybeUninit<T> = MaybeUninit::uninit(); + + pub(crate) const ARRAY: [MaybeUninit<T>; N] = [Self::VALUE; N]; +} + diff --git a/vendor/arrayvec/tests/serde.rs b/vendor/arrayvec/tests/serde.rs index 3876d2a7cd..f02c693a0f 100644 --- a/vendor/arrayvec/tests/serde.rs +++ b/vendor/arrayvec/tests/serde.rs @@ -9,7 +9,7 @@ mod array_vec { #[test] fn test_ser_de_empty() { - let vec = ArrayVec::<[u32; 0]>::new(); + let vec = ArrayVec::<u32, 0>::new(); assert_tokens(&vec, &[ Token::Seq { len: Some(0) }, @@ -20,7 +20,7 @@ mod array_vec { #[test] fn test_ser_de() { - let mut vec = ArrayVec::<[u32; 3]>::new(); + let mut vec = ArrayVec::<u32, 3>::new(); vec.push(20); vec.push(55); vec.push(123); @@ -36,7 +36,7 @@ mod array_vec { #[test] fn test_de_too_large() { - assert_de_tokens_error::<ArrayVec<[u32; 2]>>(&[ + assert_de_tokens_error::<ArrayVec<u32, 2>>(&[ Token::Seq { len: Some(3) }, Token::U32(13), Token::U32(42), @@ -52,7 +52,7 @@ mod array_string { #[test] fn test_ser_de_empty() { - let string = ArrayString::<[u8; 0]>::new(); + let string = ArrayString::<0>::new(); assert_tokens(&string, &[ Token::Str(""), @@ -62,7 +62,7 @@ mod array_string { #[test] fn test_ser_de() { - let string = ArrayString::<[u8; 9]>::from("1234 abcd") + let string = ArrayString::<9>::from("1234 abcd") .expect("expected exact specified capacity to be enough"); assert_tokens(&string, &[ @@ -72,7 +72,7 @@ mod array_string { #[test] fn test_de_too_large() { - assert_de_tokens_error::<ArrayString<[u8; 2]>>(&[ + assert_de_tokens_error::<ArrayString<2>>(&[ Token::Str("afd") ], "invalid length 3, expected a string no more than 2 bytes long"); } diff --git a/vendor/arrayvec/tests/tests.rs b/vendor/arrayvec/tests/tests.rs index c7ebcd0c4b..ca42c74500 100644 --- a/vendor/arrayvec/tests/tests.rs +++ b/vendor/arrayvec/tests/tests.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; fn test_simple() { use std::ops::Add; - let mut vec: ArrayVec<[Vec<i32>; 3]> = ArrayVec::new(); + let mut vec: ArrayVec<Vec<i32>, 3> = ArrayVec::new(); vec.push(vec![1, 2, 3, 4]); vec.push(vec![10]); @@ -29,7 +29,7 @@ fn test_simple() { #[test] fn test_capacity_left() { - let mut vec: ArrayVec<[usize; 4]> = ArrayVec::new(); + let mut vec: ArrayVec<usize, 4> = ArrayVec::new(); assert_eq!(vec.remaining_capacity(), 4); vec.push(1); assert_eq!(vec.remaining_capacity(), 3); @@ -43,7 +43,7 @@ fn test_capacity_left() { #[test] fn test_extend_from_slice() { - let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + let mut vec: ArrayVec<usize, 10> = ArrayVec::new(); vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); assert_eq!(vec.len(), 3); @@ -54,13 +54,13 @@ fn test_extend_from_slice() { #[test] fn test_extend_from_slice_error() { - let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + let mut vec: ArrayVec<usize, 10> = ArrayVec::new(); vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); let res = vec.try_extend_from_slice(&[0; 8]); assert_matches!(res, Err(_)); - let mut vec: ArrayVec<[usize; 0]> = ArrayVec::new(); + let mut vec: ArrayVec<usize, 0> = ArrayVec::new(); let res = vec.try_extend_from_slice(&[0; 1]); assert_matches!(res, Err(_)); } @@ -70,14 +70,14 @@ fn test_try_from_slice_error() { use arrayvec::ArrayVec; use std::convert::TryInto as _; - let res: Result<ArrayVec<[_; 2]>, _> = (&[1, 2, 3] as &[_]).try_into(); + let res: Result<ArrayVec<_, 2>, _> = (&[1, 2, 3] as &[_]).try_into(); assert_matches!(res, Err(_)); } #[test] fn test_u16_index() { const N: usize = 4096; - let mut vec: ArrayVec<[_; N]> = ArrayVec::new(); + let mut vec: ArrayVec<_, N> = ArrayVec::new(); for _ in 0..N { assert!(vec.try_push(1u8).is_ok()); } @@ -113,7 +113,7 @@ fn test_drop() { } { - let mut array = ArrayVec::<[Bump; 128]>::new(); + let mut array = ArrayVec::<Bump, 128>::new(); array.push(Bump(flag)); array.push(Bump(flag)); } @@ -123,7 +123,7 @@ fn test_drop() { flag.set(0); { - let mut array = ArrayVec::<[_; 3]>::new(); + let mut array = ArrayVec::<_, 3>::new(); array.push(vec![Bump(flag)]); array.push(vec![Bump(flag), Bump(flag)]); array.push(vec![]); @@ -142,7 +142,7 @@ fn test_drop() { // test into_inner flag.set(0); { - let mut array = ArrayVec::<[_; 3]>::new(); + let mut array = ArrayVec::<_, 3>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -156,7 +156,7 @@ fn test_drop() { // test cloning into_iter flag.set(0); { - let mut array = ArrayVec::<[_; 3]>::new(); + let mut array = ArrayVec::<_, 3>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -210,7 +210,7 @@ fn test_drop_panics() { flag.set(0); { - let mut array = ArrayVec::<[Bump; 128]>::new(); + let mut array = ArrayVec::<Bump, 128>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -226,7 +226,7 @@ fn test_drop_panics() { flag.set(0); { - let mut array = ArrayVec::<[Bump; 16]>::new(); + let mut array = ArrayVec::<Bump, 16>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -251,48 +251,66 @@ fn test_drop_panics() { fn test_extend() { let mut range = 0..10; - let mut array: ArrayVec<[_; 5]> = range.by_ref().collect(); + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); assert_eq!(range.next(), Some(5)); - array.extend(range.by_ref()); + array.extend(range.by_ref().take(0)); assert_eq!(range.next(), Some(6)); - let mut array: ArrayVec<[_; 10]> = (0..3).collect(); + let mut array: ArrayVec<_, 10> = (0..3).collect(); assert_eq!(&array[..], &[0, 1, 2]); array.extend(3..5); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); } +#[should_panic] +#[test] +fn test_extend_capacity_panic_1() { + let mut range = 0..10; + + let _: ArrayVec<_, 5> = range.by_ref().collect(); +} + +#[should_panic] +#[test] +fn test_extend_capacity_panic_2() { + let mut range = 0..10; + + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); + assert_eq!(&array[..], &[0, 1, 2, 3, 4]); + assert_eq!(range.next(), Some(5)); + array.extend(range.by_ref().take(1)); +} + #[test] fn test_is_send_sync() { - let data = ArrayVec::<[Vec<i32>; 5]>::new(); + let data = ArrayVec::<Vec<i32>, 5>::new(); &data as &dyn Send; &data as &dyn Sync; } #[test] fn test_compact_size() { - // Future rust will kill these drop flags! - // 4 elements size + 1 len + 1 enum tag + [1 drop flag] - type ByteArray = ArrayVec<[u8; 4]>; + // 4 bytes + padding + length + type ByteArray = ArrayVec<u8, 4>; println!("{}", mem::size_of::<ByteArray>()); - assert!(mem::size_of::<ByteArray>() <= 8); + assert!(mem::size_of::<ByteArray>() <= 2 * mem::size_of::<u32>()); - // 1 enum tag + 1 drop flag - type EmptyArray = ArrayVec<[u8; 0]>; + // just length + type EmptyArray = ArrayVec<u8, 0>; println!("{}", mem::size_of::<EmptyArray>()); - assert!(mem::size_of::<EmptyArray>() <= 2); + assert!(mem::size_of::<EmptyArray>() <= mem::size_of::<u32>()); - // 12 element size + 1 enum tag + 3 padding + 1 len + 1 drop flag + 2 padding - type QuadArray = ArrayVec<[u32; 3]>; + // 3 elements + padding + length + type QuadArray = ArrayVec<u32, 3>; println!("{}", mem::size_of::<QuadArray>()); - assert!(mem::size_of::<QuadArray>() <= 24); + assert!(mem::size_of::<QuadArray>() <= 4 * 4 + mem::size_of::<u32>()); } #[test] fn test_still_works_with_option_arrayvec() { - type RefArray = ArrayVec<[&'static i32; 2]>; + type RefArray = ArrayVec<&'static i32, 2>; let array = Some(RefArray::new()); assert!(array.is_some()); println!("{:?}", array); @@ -305,10 +323,10 @@ fn test_drain() { v.drain(0..7); assert_eq!(&v[..], &[]); - v.extend(0..); + v.extend(0..8); v.drain(1..4); assert_eq!(&v[..], &[0, 4, 5, 6, 7]); - let u: ArrayVec<[_; 3]> = v.drain(1..4).rev().collect(); + let u: ArrayVec<_, 3> = v.drain(1..4).rev().collect(); assert_eq!(&u[..], &[6, 5, 4]); assert_eq!(&v[..], &[0, 7]); v.drain(..); @@ -321,10 +339,10 @@ fn test_drain_range_inclusive() { v.drain(0..=7); assert_eq!(&v[..], &[]); - v.extend(0..); + v.extend(0..8); v.drain(1..=4); assert_eq!(&v[..], &[0, 5, 6, 7]); - let u: ArrayVec<[_; 3]> = v.drain(1..=2).rev().collect(); + let u: ArrayVec<_, 3> = v.drain(1..=2).rev().collect(); assert_eq!(&u[..], &[6, 5]); assert_eq!(&v[..], &[0, 7]); v.drain(..); @@ -374,7 +392,7 @@ fn test_drop_panic() { } } - let mut array = ArrayVec::<[DropPanic; 1]>::new(); + let mut array = ArrayVec::<DropPanic, 1>::new(); array.push(DropPanic); } @@ -389,7 +407,7 @@ fn test_drop_panic_into_iter() { } } - let mut array = ArrayVec::<[DropPanic; 1]>::new(); + let mut array = ArrayVec::<DropPanic, 1>::new(); array.push(DropPanic); array.into_iter(); } @@ -399,7 +417,7 @@ fn test_insert() { let mut v = ArrayVec::from([]); assert_matches!(v.try_push(1), Err(_)); - let mut v = ArrayVec::<[_; 3]>::new(); + let mut v = ArrayVec::<_, 3>::new(); v.insert(0, 0); v.insert(1, 1); //let ret1 = v.try_insert(3, 3); @@ -428,7 +446,7 @@ fn test_into_inner_1() { #[test] fn test_into_inner_2() { - let mut v = ArrayVec::<[String; 4]>::new(); + let mut v = ArrayVec::<String, 4>::new(); v.push("a".into()); v.push("b".into()); v.push("c".into()); @@ -437,9 +455,9 @@ fn test_into_inner_2() { } #[test] -fn test_into_inner_3_() { - let mut v = ArrayVec::<[i32; 4]>::new(); - v.extend(1..); +fn test_into_inner_3() { + let mut v = ArrayVec::<i32, 4>::new(); + v.extend(1..=4); assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); } @@ -447,7 +465,7 @@ fn test_into_inner_3_() { #[test] fn test_write() { use std::io::Write; - let mut v = ArrayVec::<[_; 8]>::new(); + let mut v = ArrayVec::<_, 8>::new(); write!(&mut v, "\x01\x02\x03").unwrap(); assert_eq!(&v[..], &[1, 2, 3]); let r = v.write(&[9; 16]).unwrap(); @@ -457,16 +475,16 @@ fn test_write() { #[test] fn array_clone_from() { - let mut v = ArrayVec::<[_; 4]>::new(); + let mut v = ArrayVec::<_, 4>::new(); v.push(vec![1, 2]); v.push(vec![3, 4, 5]); v.push(vec![6]); let reference = v.to_vec(); - let mut u = ArrayVec::<[_; 4]>::new(); + let mut u = ArrayVec::<_, 4>::new(); u.clone_from(&v); assert_eq!(&u, &reference[..]); - let mut t = ArrayVec::<[_; 4]>::new(); + let mut t = ArrayVec::<_, 4>::new(); t.push(vec![97]); t.push(vec![]); t.push(vec![5, 6, 2]); @@ -484,7 +502,7 @@ fn test_string() { use std::error::Error; let text = "hello world"; - let mut s = ArrayString::<[_; 16]>::new(); + let mut s = ArrayString::<16>::new(); s.try_push_str(text).unwrap(); assert_eq!(&s, text); assert_eq!(text, &s); @@ -494,7 +512,7 @@ fn test_string() { map.insert(s, 1); assert_eq!(map[text], 1); - let mut t = ArrayString::<[_; 2]>::new(); + let mut t = ArrayString::<2>::new(); assert!(t.try_push_str(text).is_err()); assert_eq!(&t, ""); @@ -505,7 +523,7 @@ fn test_string() { // Test Error trait / try let t = || -> Result<(), Box<dyn Error>> { - let mut t = ArrayString::<[_; 2]>::new(); + let mut t = ArrayString::<2>::new(); t.try_push_str(text)?; Ok(()) }(); @@ -516,7 +534,7 @@ fn test_string() { fn test_string_from() { let text = "hello world"; // Test `from` constructor - let u = ArrayString::<[_; 11]>::from(text).unwrap(); + let u = ArrayString::<11>::from(text).unwrap(); assert_eq!(&u, text); assert_eq!(u.len(), text.len()); } @@ -524,7 +542,7 @@ fn test_string_from() { #[test] fn test_string_parse_from_str() { let text = "hello world"; - let u: ArrayString<[_; 11]> = text.parse().unwrap(); + let u: ArrayString<11> = text.parse().unwrap(); assert_eq!(&u, text); assert_eq!(u.len(), text.len()); } @@ -540,9 +558,9 @@ fn test_string_from_bytes() { #[test] fn test_string_clone() { let text = "hi"; - let mut s = ArrayString::<[_; 4]>::new(); + let mut s = ArrayString::<4>::new(); s.push_str("abcd"); - let t = ArrayString::<[_; 4]>::from(text).unwrap(); + let t = ArrayString::<4>::from(text).unwrap(); s.clone_from(&t); assert_eq!(&t, &s); } @@ -550,7 +568,7 @@ fn test_string_clone() { #[test] fn test_string_push() { let text = "abcαβγ"; - let mut s = ArrayString::<[_; 8]>::new(); + let mut s = ArrayString::<8>::new(); for c in text.chars() { if let Err(_) = s.try_push(c) { break; @@ -565,7 +583,7 @@ fn test_string_push() { #[test] fn test_insert_at_length() { - let mut v = ArrayVec::<[_; 8]>::new(); + let mut v = ArrayVec::<_, 8>::new(); let result1 = v.try_insert(0, "a"); let result2 = v.try_insert(1, "b"); assert!(result1.is_ok() && result2.is_ok()); @@ -575,7 +593,7 @@ fn test_insert_at_length() { #[should_panic] #[test] fn test_insert_out_of_bounds() { - let mut v = ArrayVec::<[_; 8]>::new(); + let mut v = ArrayVec::<_, 8>::new(); let _ = v.try_insert(1, "test"); } @@ -608,7 +626,7 @@ fn test_drop_in_insert() { flag.set(0); { - let mut array = ArrayVec::<[_; 2]>::new(); + let mut array = ArrayVec::<_, 2>::new(); array.push(Bump(flag)); array.insert(0, Bump(flag)); assert_eq!(flag.get(), 0); @@ -623,7 +641,7 @@ fn test_drop_in_insert() { #[test] fn test_pop_at() { - let mut v = ArrayVec::<[String; 4]>::new(); + let mut v = ArrayVec::<String, 4>::new(); let s = String::from; v.push(s("a")); v.push(s("b")); @@ -646,9 +664,9 @@ fn test_sizes() { #[test] fn test_default() { use std::net; - let s: ArrayString<[u8; 4]> = Default::default(); + let s: ArrayString<4> = Default::default(); // Something without `Default` implementation. - let v: ArrayVec<[net::TcpStream; 4]> = Default::default(); + let v: ArrayVec<net::TcpStream, 4> = Default::default(); assert_eq!(s.len(), 0); assert_eq!(v.len(), 0); } @@ -673,16 +691,74 @@ fn test_extend_zst() { #[derive(Copy, Clone, PartialEq, Debug)] struct Z; // Zero sized type - let mut array: ArrayVec<[_; 5]> = range.by_ref().map(|_| Z).collect(); + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 5]); assert_eq!(range.next(), Some(5)); - array.extend(range.by_ref().map(|_| Z)); + array.extend(range.by_ref().take(0).map(|_| Z)); assert_eq!(range.next(), Some(6)); - let mut array: ArrayVec<[_; 10]> = (0..3).map(|_| Z).collect(); + let mut array: ArrayVec<_, 10> = (0..3).map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 3]); array.extend((3..5).map(|_| Z)); assert_eq!(&array[..], &[Z; 5]); assert_eq!(array.len(), 5); } + +#[test] +fn test_try_from_argument() { + use core::convert::TryFrom; + let v = ArrayString::<16>::try_from(format_args!("Hello {}", 123)).unwrap(); + assert_eq!(&v, "Hello 123"); +} + +#[test] +fn allow_max_capacity_arrayvec_type() { + // this type is allowed to be used (but can't be constructed) + let _v: ArrayVec<(), {usize::MAX}>; +} + +#[should_panic(expected="largest supported capacity")] +#[test] +fn deny_max_capacity_arrayvec_value() { + if mem::size_of::<usize>() <= mem::size_of::<u32>() { + panic!("This test does not work on this platform. 'largest supported capacity'"); + } + // this type is allowed to be used (but can't be constructed) + let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new(); +} + +#[should_panic(expected="index out of bounds")] +#[test] +fn deny_max_capacity_arrayvec_value_const() { + if mem::size_of::<usize>() <= mem::size_of::<u32>() { + panic!("This test does not work on this platform. 'index out of bounds'"); + } + // this type is allowed to be used (but can't be constructed) + let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const(); +} + +#[test] +fn test_arrayvec_const_constructible() { + const OF_U8: ArrayVec<Vec<u8>, 10> = ArrayVec::new_const(); + + let mut var = OF_U8; + assert!(var.is_empty()); + assert_eq!(var, ArrayVec::new()); + var.push(vec![3, 5, 8]); + assert_eq!(var[..], [vec![3, 5, 8]]); +} + + +#[test] +fn test_arraystring_const_constructible() { + const AS: ArrayString<10> = ArrayString::new_const(); + + let mut var = AS; + assert!(var.is_empty()); + assert_eq!(var, ArrayString::new()); + var.push_str("hello"); + assert_eq!(var, *"hello"); +} + + diff --git a/vendor/base64/.cargo-checksum.json b/vendor/base64/.cargo-checksum.json deleted file mode 100644 index c778840372..0000000000 --- a/vendor/base64/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.lock":"65ebf1f4354afcd9b89cad6b7c49ae84967a8051b98f71c2f7e41ee00ec58761","Cargo.toml":"8fbadd28fb944722813e9eb87549e6f0b545ac0e324f972fec8d18d929fe50c7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0dd882e53de11566d50f8e8e2d5a651bcf3fabee4987d70f306233cf39094ba7","README.md":"1dbd70065db1015c6286859fa71c2a70d0e3f24ba117dde7322af78411338a8f","RELEASE-NOTES.md":"38a9d339c5d3d91014bededcd2882ed5606b62e4c08543659753b256197c013b","benches/benchmarks.rs":"7d1eb58b600b5ff349a560c663aadc6c75d8f75fe77d76fc2dbb8717256d0bf4","examples/make_tables.rs":"096b87deb404e6af6761a38ef0ba56fa89eca385a72a3cc54f410058a7794d35","icon_CLion.svg":"cffa044ba75cb998ee3306991dc4a3755ec2f39ab95ddd4b74bc21988389020f","src/chunked_encoder.rs":"0b7c502ead9a95a1c6f20b682294347a5114b2f2d0c1e387fe4c11b283506db7","src/decode.rs":"ae1bf6adecfd005d1810169894fe88d6e4aaa78ee74583776e193aa82e67ece9","src/display.rs":"55f9cd05ba037b77689e2558fa174055fad5273959d1edce3a2289f94244fd5d","src/encode.rs":"9f51eb63cbe318cd194297b0f5569d409cd7a6593db2e3fcf7adfd319106ca46","src/lib.rs":"c1c368eb81eebc7781fbfa702cf541b956664d917fbc5e051ebd42c223ee3ce8","src/tables.rs":"3f84fa4d86a4ad585d30926c756a29eeb707b2253ff7a6ce5d791b3dd9c21c7e","src/tests.rs":"ef9fb6f4ca37d2324f9748d54d2c59c5c901b850409647e7ee932a8775edccf1","src/write/encoder.rs":"f99b967f4347c44af8d0b8cb7ad29228a1b168a13738d7298dbe07b7411de30a","src/write/encoder_tests.rs":"7192e321a1c61afa0de5ecb3c07757777ea4bc2844789cdb93852467977d5969","src/write/mod.rs":"124b223f3effcb1d85671a4173a635cdfae480341b032217c77876647344176b","tests/decode.rs":"2b63c9e7f9dd48153e77206882684d3f99288bcfa2addda71b255e5d966c8b00","tests/encode.rs":"5efb6904c36c6f899a05078e5c9be756fc58af1ee9940edfa8dea1ee53675364","tests/helpers.rs":"a76015e4a4e8f98213bdbaa592cd9574ccdc95a28e1b1f835a2753e09fa6037f","tests/tests.rs":"05753e5f1d4a6c75015a5342f9b5dc3073c00bdfe0a829a962f8723321c75549"},"package":"b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"} \ No newline at end of file diff --git a/vendor/base64/Cargo.lock b/vendor/base64/Cargo.lock deleted file mode 100644 index 347821b619..0000000000 --- a/vendor/base64/Cargo.lock +++ /dev/null @@ -1,621 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "arrayvec" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "base64" -version = "0.11.0" -dependencies = [ - "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bstr" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "byteorder" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cast" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clap" -version = "2.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "criterion" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "criterion-plot" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "csv" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "csv-core" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "doc-comment" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "either" -version = "1.5.2" -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 = "getrandom" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itertools" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.65" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memoffset" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nodrop" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num-traits" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num_cpus" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_hc" -version = "0.1.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 = "rand_isaac" -version = "0.1.1" -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 = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (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.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -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 = "rand_xoshiro" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (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-automata" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ryu" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "same-file" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tinytemplate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-width" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "walkdir" -version = "2.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" -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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (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 arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" -"checksum atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ecaaea69f52b3b18633611ec0007d188517d0366f47ff703d400fa6879d6f8d5" -"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc0572e02f76cb335f309b19e0a0d585b4f62788f7d26de2a13a836a637385f" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" -"checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" -"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" -"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" -"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" -"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" -"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed09217220c272b29ef237a974ad58515bde75f194e3ffa7e6d0bf0f3b01f86" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "076a696fdea89c19d3baed462576b8f6d663064414b5c793642da8dfeb99475b" -"checksum serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "ef45eb79d6463b22f5f9e16d283798b7c0175ba6050bc25c1a946c122727fe7b" -"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" -"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c7904a7e2bb3cdf0cf5e783f44204a85a37a93151738fa349f06680f59a98b45" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/vendor/base64/Cargo.toml b/vendor/base64/Cargo.toml deleted file mode 100644 index 749243c340..0000000000 --- a/vendor/base64/Cargo.toml +++ /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] -edition = "2018" -name = "base64" -version = "0.11.0" -authors = ["Alice Maz <alice@alicemaz.com>", "Marshall Pierce <marshall@mpierce.org>"] -description = "encodes and decodes base64 as bytes or utf8" -documentation = "https://docs.rs/base64" -readme = "README.md" -keywords = ["base64", "utf8", "encode", "decode", "no_std"] -categories = ["encoding"] -license = "MIT/Apache-2.0" -repository = "https://github.com/marshallpierce/rust-base64" -[profile.bench] -debug = true - -[[bench]] -name = "benchmarks" -harness = false -[dev-dependencies.criterion] -version = "0.3" - -[dev-dependencies.doc-comment] -version = "0.3" - -[dev-dependencies.rand] -version = "0.6.1" - -[features] -alloc = [] -default = ["std"] -std = [] diff --git a/vendor/base64/LICENSE-MIT b/vendor/base64/LICENSE-MIT deleted file mode 100644 index 7bc10f80a0..0000000000 --- a/vendor/base64/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Alice Maz - -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/base64/README.md b/vendor/base64/README.md deleted file mode 100644 index 19f2feb26b..0000000000 --- a/vendor/base64/README.md +++ /dev/null @@ -1,114 +0,0 @@ -[base64](https://crates.io/crates/base64) -=== - -[![](https://img.shields.io/crates/v/base64.svg)](https://crates.io/crates/base64) [![Docs](https://docs.rs/base64/badge.svg)](https://docs.rs/base64) [![Build](https://travis-ci.org/marshallpierce/rust-base64.svg?branch=master)](https://travis-ci.org/marshallpierce/rust-base64) [![codecov](https://codecov.io/gh/marshallpierce/rust-base64/branch/master/graph/badge.svg)](https://codecov.io/gh/marshallpierce/rust-base64) [![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) - -<a href="https://www.jetbrains.com/?from=rust-base64"><img src="/icon_CLion.svg" height="40px"/></a> - -Made with CLion. Thanks to JetBrains for supporting open source! - -It's base64. What more could anyone want? - -This library's goals are to be *correct* and *fast*. It's thoroughly tested and widely used. It exposes functionality at multiple levels of abstraction so you can choose the level of convenience vs performance that you want, e.g. `decode_config_slice` decodes into an existing `&mut [u8]` and is pretty fast (2.6GiB/s for a 3 KiB input), whereas `decode_config` allocates a new `Vec<u8>` and returns it, which might be more convenient in some cases, but is slower (although still fast enough for most purposes) at 2.1 GiB/s. - -Example ---- - -```rust -extern crate base64; - -use base64::{encode, decode}; - -fn main() { - let a = b"hello world"; - let b = "aGVsbG8gd29ybGQ="; - - assert_eq!(encode(a), b); - assert_eq!(a, &decode(b).unwrap()[..]); -} -``` - -See the [docs](https://docs.rs/base64) for all the details. - -Rust version compatibility ---- - -The minimum required Rust version is 1.34.0. - -Developing ---- - -Benchmarks are in `benches/`. Running them requires nightly rust, but `rustup` makes it easy: - -```bash -rustup run nightly cargo bench -``` - -Decoding is aided by some pre-calculated tables, which are generated by: - -```bash -cargo run --example make_tables > src/tables.rs.tmp && mv src/tables.rs.tmp src/tables.rs -``` - -no_std ---- - -This crate supports no_std. By default the crate targets std via the `std` feature. You can deactivate the `default-features` to target core instead. In that case you lose out on all the functionality revolving around `std::io`, `std::error::Error` and heap allocations. There is an additional `alloc` feature that you can activate to bring back the support for heap allocations. - -Profiling ---- - -On Linux, you can use [perf](https://perf.wiki.kernel.org/index.php/Main_Page) for profiling. Then compile the benchmarks with `rustup nightly run cargo bench --no-run`. - -Run the benchmark binary with `perf` (shown here filtering to one particular benchmark, which will make the results easier to read). `perf` is only available to the root user on most systems as it fiddles with event counters in your CPU, so use `sudo`. We need to run the actual benchmark binary, hence the path into `target`. You can see the actual full path with `rustup run nightly cargo bench -v`; it will print out the commands it runs. If you use the exact path that `bench` outputs, make sure you get the one that's for the benchmarks, not the tests. You may also want to `cargo clean` so you have only one `benchmarks-` binary (they tend to accumulate). - -```bash -sudo perf record target/release/deps/benchmarks-* --bench decode_10mib_reuse -``` - -Then analyze the results, again with perf: - -```bash -sudo perf annotate -l -``` - -You'll see a bunch of interleaved rust source and assembly like this. The section with `lib.rs:327` is telling us that 4.02% of samples saw the `movzbl` aka bit shift as the active instruction. However, this percentage is not as exact as it seems due to a phenomenon called *skid*. Basically, a consequence of how fancy modern CPUs are is that this sort of instruction profiling is inherently inaccurate, especially in branch-heavy code. - -```text - lib.rs:322 0.70 : 10698: mov %rdi,%rax - 2.82 : 1069b: shr $0x38,%rax - : if morsel == decode_tables::INVALID_VALUE { - : bad_byte_index = input_index; - : break; - : }; - : accum = (morsel as u64) << 58; - lib.rs:327 4.02 : 1069f: movzbl (%r9,%rax,1),%r15d - : // fast loop of 8 bytes at a time - : while input_index < length_of_full_chunks { - : let mut accum: u64; - : - : let input_chunk = BigEndian::read_u64(&input_bytes[input_index..(input_index + 8)]); - : morsel = decode_table[(input_chunk >> 56) as usize]; - lib.rs:322 3.68 : 106a4: cmp $0xff,%r15 - : if morsel == decode_tables::INVALID_VALUE { - 0.00 : 106ab: je 1090e <base64::decode_config_buf::hbf68a45fefa299c1+0x46e> -``` - - -Fuzzing ---- - -This uses [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). See `fuzz/fuzzers` for the available fuzzing scripts. To run, use an invocation like these: - -```bash -cargo +nightly fuzz run roundtrip -cargo +nightly fuzz run roundtrip_no_pad -cargo +nightly fuzz run roundtrip_random_config -- -max_len=10240 -cargo +nightly fuzz run decode_random -``` - - -License ---- - -This project is dual-licensed under MIT and Apache 2.0. diff --git a/vendor/base64/RELEASE-NOTES.md b/vendor/base64/RELEASE-NOTES.md deleted file mode 100644 index 1a730dca88..0000000000 --- a/vendor/base64/RELEASE-NOTES.md +++ /dev/null @@ -1,84 +0,0 @@ -# Next - -- 0.11.0 -- Minimum rust version 1.34.0 -- `no_std` is now supported via the two new features `alloc` and `std`. - -# 0.10.1 - -- Minimum rust version 1.27.2 -- Fix bug in streaming encoding ([#90](https://github.com/marshallpierce/rust-base64/pull/90)): if the underlying writer didn't write all the bytes given to it, the remaining bytes would not be retried later. See the docs on `EncoderWriter::write`. -- Make it configurable whether or not to return an error when decoding detects excess trailing bits. - -# 0.10.0 - -- Remove line wrapping. Line wrapping was never a great conceptual fit in this library, and other features (streaming encoding, etc) either couldn't support it or could support only special cases of it with a great increase in complexity. Line wrapping has been pulled out into a [line-wrap](https://crates.io/crates/line-wrap) crate, so it's still available if you need it. - - `Base64Display` creation no longer uses a `Result` because it can't fail, which means its helper methods for common - configs that `unwrap()` for you are no longer needed -- Add a streaming encoder `Write` impl to transparently base64 as you write. -- Remove the remaining `unsafe` code. -- Remove whitespace stripping to simplify `no_std` support. No out of the box configs use it, and it's trivial to do yourself if needed: `filter(|b| !b" \n\t\r\x0b\x0c".contains(b)`. -- Detect invalid trailing symbols when decoding and return an error rather than silently ignoring them. - -# 0.9.3 - -- Update safemem - -# 0.9.2 - -- Derive `Clone` for `DecodeError`. - -# 0.9.1 - -- Add support for `crypt(3)`'s base64 variant. - -# 0.9.0 - -- `decode_config_slice` function for no-allocation decoding, analogous to `encode_config_slice` -- Decode performance optimization - -# 0.8.0 - -- `encode_config_slice` function for no-allocation encoding - -# 0.7.0 - -- `STANDARD_NO_PAD` config -- `Base64Display` heap-free wrapper for use in format strings, etc - -# 0.6.0 - -- Decode performance improvements -- Use `unsafe` in fewer places -- Added fuzzers - -# 0.5.2 - -- Avoid usize overflow when calculating length -- Better line wrapping performance - -# 0.5.1 - -- Temporarily disable line wrapping -- Add Apache 2.0 license - -# 0.5.0 - -- MIME support, including configurable line endings and line wrapping -- Removed `decode_ws` -- Renamed `Base64Error` to `DecodeError` - -# 0.4.1 - -- Allow decoding a `AsRef<[u8]>` instead of just a `&str` - -# 0.4.0 - -- Configurable padding -- Encode performance improvements - -# 0.3.0 - -- Added encode/decode functions that do not allocate their own storage -- Decode performance improvements -- Extraneous padding bytes are no longer ignored. Now, an error will be returned. diff --git a/vendor/base64/benches/benchmarks.rs b/vendor/base64/benches/benchmarks.rs deleted file mode 100644 index 475dfdb779..0000000000 --- a/vendor/base64/benches/benchmarks.rs +++ /dev/null @@ -1,160 +0,0 @@ -extern crate base64; -#[macro_use] -extern crate criterion; -extern crate rand; - -use base64::display; -use base64::{ - decode, decode_config_buf, decode_config_slice, encode, encode_config_buf, encode_config_slice, - write, Config, -}; - -use criterion::{black_box, Bencher, Criterion, ParameterizedBenchmark, Throughput}; -use rand::{FromEntropy, Rng}; -use std::io::Write; - -const TEST_CONFIG: Config = base64::STANDARD; - -fn do_decode_bench(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4); - fill(&mut v); - let encoded = encode(&v); - - b.iter(|| { - let orig = decode(&encoded); - black_box(&orig); - }); -} - -fn do_decode_bench_reuse_buf(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4); - fill(&mut v); - let encoded = encode(&v); - - let mut buf = Vec::new(); - b.iter(|| { - decode_config_buf(&encoded, TEST_CONFIG, &mut buf).unwrap(); - black_box(&buf); - buf.clear(); - }); -} - -fn do_decode_bench_slice(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4); - fill(&mut v); - let encoded = encode(&v); - - let mut buf = Vec::new(); - buf.resize(size, 0); - b.iter(|| { - decode_config_slice(&encoded, TEST_CONFIG, &mut buf).unwrap(); - black_box(&buf); - }); -} - -fn do_encode_bench(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size); - fill(&mut v); - b.iter(|| { - let e = encode(&v); - black_box(&e); - }); -} - -fn do_encode_bench_display(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size); - fill(&mut v); - b.iter(|| { - let e = format!("{}", display::Base64Display::with_config(&v, TEST_CONFIG)); - black_box(&e); - }); -} - -fn do_encode_bench_reuse_buf(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size); - fill(&mut v); - let mut buf = String::new(); - b.iter(|| { - encode_config_buf(&v, TEST_CONFIG, &mut buf); - buf.clear(); - }); -} - -fn do_encode_bench_slice(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size); - fill(&mut v); - let mut buf = Vec::new(); - // conservative estimate of encoded size - buf.resize(v.len() * 2, 0); - b.iter(|| { - encode_config_slice(&v, TEST_CONFIG, &mut buf); - }); -} - -fn do_encode_bench_stream(b: &mut Bencher, &size: &usize) { - let mut v: Vec<u8> = Vec::with_capacity(size); - fill(&mut v); - let mut buf = Vec::new(); - - buf.reserve(size * 2); - b.iter(|| { - buf.clear(); - let mut stream_enc = write::EncoderWriter::new(&mut buf, TEST_CONFIG); - stream_enc.write_all(&v).unwrap(); - stream_enc.flush().unwrap(); - }); -} - -fn fill(v: &mut Vec<u8>) { - let cap = v.capacity(); - // weak randomness is plenty; we just want to not be completely friendly to the branch predictor - let mut r = rand::rngs::SmallRng::from_entropy(); - while v.len() < cap { - v.push(r.gen::<u8>()); - } -} - -const BYTE_SIZES: [usize; 5] = [3, 50, 100, 500, 3 * 1024]; - -// Benchmarks over these byte sizes take longer so we will run fewer samples to -// keep the benchmark runtime reasonable. -const LARGE_BYTE_SIZES: [usize; 3] = [3 * 1024 * 1024, 10 * 1024 * 1024, 30 * 1024 * 1024]; - -fn encode_benchmarks(byte_sizes: &[usize]) -> ParameterizedBenchmark<usize> { - ParameterizedBenchmark::new("encode", do_encode_bench, byte_sizes.iter().cloned()) - .warm_up_time(std::time::Duration::from_millis(500)) - .measurement_time(std::time::Duration::from_secs(3)) - .throughput(|s| Throughput::Bytes(*s as u64)) - .with_function("encode_display", do_encode_bench_display) - .with_function("encode_reuse_buf", do_encode_bench_reuse_buf) - .with_function("encode_slice", do_encode_bench_slice) - .with_function("encode_reuse_buf_stream", do_encode_bench_stream) -} - -fn decode_benchmarks(byte_sizes: &[usize]) -> ParameterizedBenchmark<usize> { - ParameterizedBenchmark::new("decode", do_decode_bench, byte_sizes.iter().cloned()) - .warm_up_time(std::time::Duration::from_millis(500)) - .measurement_time(std::time::Duration::from_secs(3)) - .throughput(|s| Throughput::Bytes(*s as u64)) - .with_function("decode_reuse_buf", do_decode_bench_reuse_buf) - .with_function("decode_slice", do_decode_bench_slice) -} - -fn bench(c: &mut Criterion) { - c.bench("bench_small_input", encode_benchmarks(&BYTE_SIZES[..])); - - c.bench( - "bench_large_input", - encode_benchmarks(&LARGE_BYTE_SIZES[..]).sample_size(10), - ); - - c.bench("bench_small_input", decode_benchmarks(&BYTE_SIZES[..])); - - c.bench( - "bench_large_input", - decode_benchmarks(&LARGE_BYTE_SIZES[..]).sample_size(10), - ); -} - -criterion_group!(benches, bench); -criterion_main!(benches); diff --git a/vendor/base64/examples/make_tables.rs b/vendor/base64/examples/make_tables.rs deleted file mode 100644 index 77df0b4e93..0000000000 --- a/vendor/base64/examples/make_tables.rs +++ /dev/null @@ -1,116 +0,0 @@ -use std::collections::HashMap; -use std::iter::Iterator; - -fn main() { - println!("pub const INVALID_VALUE: u8 = 255;"); - - // A-Z - let standard_alphabet: Vec<u8> = (0x41..0x5B) - // a-z - .chain(0x61..0x7B) - // 0-9 - .chain(0x30..0x3A) - // + - .chain(0x2B..0x2C) - // / - .chain(0x2F..0x30) - .collect(); - print_encode_table(&standard_alphabet, "STANDARD_ENCODE", 0); - print_decode_table(&standard_alphabet, "STANDARD_DECODE", 0); - - // A-Z - let url_alphabet: Vec<u8> = (0x41..0x5B) - // a-z - .chain(0x61..0x7B) - // 0-9 - .chain(0x30..0x3A) - // - - .chain(0x2D..0x2E) - // _s - .chain(0x5F..0x60) - .collect(); - print_encode_table(&url_alphabet, "URL_SAFE_ENCODE", 0); - print_decode_table(&url_alphabet, "URL_SAFE_DECODE", 0); - - // ./0123456789 - let crypt_alphabet: Vec<u8> = (b'.'..(b'9' + 1)) - // A-Z - .chain(b'A'..(b'Z' + 1)) - // a-z - .chain(b'a'..(b'z' + 1)) - .collect(); - print_encode_table(&crypt_alphabet, "CRYPT_ENCODE", 0); - print_decode_table(&crypt_alphabet, "CRYPT_DECODE", 0); -} - -fn print_encode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) { - println!("#[rustfmt::skip]"); - println!( - "{:width$}pub const {}: &[u8; 64] = &[", - "", - const_name, - width = indent_depth - ); - - for (i, b) in alphabet.iter().enumerate() { - println!( - "{:width$}{}, // input {} (0x{:X}) => '{}' (0x{:X})", - "", - b, - i, - i, - String::from_utf8(vec![*b as u8]).unwrap(), - b, - width = indent_depth + 4 - ); - } - - println!("{:width$}];", "", width = indent_depth); -} - -fn print_decode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) { - // map of alphabet bytes to 6-bit morsels - let mut input_to_morsel = HashMap::<u8, u8>::new(); - - // standard base64 alphabet bytes, in order - for (morsel, ascii_byte) in alphabet.iter().enumerate() { - // truncation cast is fine here - let _ = input_to_morsel.insert(*ascii_byte, morsel as u8); - } - - println!("#[rustfmt::skip]"); - println!( - "{:width$}pub const {}: &[u8; 256] = &[", - "", - const_name, - width = indent_depth - ); - for ascii_byte in 0..256 { - let (value, comment) = match input_to_morsel.get(&(ascii_byte as u8)) { - None => ( - "INVALID_VALUE".to_string(), - format!("input {} (0x{:X})", ascii_byte, ascii_byte), - ), - Some(v) => ( - format!("{}", *v), - format!( - "input {} (0x{:X} char '{}') => {} (0x{:X})", - ascii_byte, - ascii_byte, - String::from_utf8(vec![ascii_byte as u8]).unwrap(), - *v, - *v - ), - ), - }; - - println!( - "{:width$}{}, // {}", - "", - value, - comment, - width = indent_depth + 4 - ); - } - println!("{:width$}];", "", width = indent_depth); -} diff --git a/vendor/base64/icon_CLion.svg b/vendor/base64/icon_CLion.svg deleted file mode 100644 index e9edb0445e..0000000000 --- a/vendor/base64/icon_CLion.svg +++ /dev/null @@ -1,34 +0,0 @@ -<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 128 128"> - <defs> - <linearGradient id="linear-gradient" x1="40.69" y1="-676.56" x2="83.48" y2="-676.56" gradientTransform="matrix(1, 0, 0, -1, 0, -648.86)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#ed358c"/> - <stop offset="0.16" stop-color="#e9388c"/> - <stop offset="0.3" stop-color="#de418c"/> - <stop offset="0.43" stop-color="#cc508c"/> - <stop offset="0.57" stop-color="#b2658d"/> - <stop offset="0.7" stop-color="#90808d"/> - <stop offset="0.83" stop-color="#67a18e"/> - <stop offset="0.95" stop-color="#37c78f"/> - <stop offset="1" stop-color="#22d88f"/> - </linearGradient> - <linearGradient id="linear-gradient-2" x1="32.58" y1="-665.27" x2="13.76" y2="-791.59" gradientTransform="matrix(1, 0, 0, -1, 0, -648.86)" gradientUnits="userSpaceOnUse"> - <stop offset="0.09" stop-color="#22d88f"/> - <stop offset="0.9" stop-color="#029de0"/> - </linearGradient> - <linearGradient id="linear-gradient-3" x1="116.68" y1="-660.66" x2="-12.09" y2="-796.66" xlink:href="#linear-gradient-2"/> - <linearGradient id="linear-gradient-4" x1="73.35" y1="-739.1" x2="122.29" y2="-746.06" xlink:href="#linear-gradient-2"/> - </defs> - <title>icon_CLion - - - - - - - - - - - - - diff --git a/vendor/base64/src/chunked_encoder.rs b/vendor/base64/src/chunked_encoder.rs deleted file mode 100644 index 7d405ace23..0000000000 --- a/vendor/base64/src/chunked_encoder.rs +++ /dev/null @@ -1,248 +0,0 @@ -use crate::{ - encode::{add_padding, encode_to_slice}, - Config, -}; -#[cfg(any(feature = "alloc", feature = "std", test))] -use alloc::string::String; -use core::cmp; -#[cfg(any(feature = "alloc", feature = "std", test))] -use core::str; - -/// The output mechanism for ChunkedEncoder's encoded bytes. -pub trait Sink { - type Error; - - /// Handle a chunk of encoded base64 data (as UTF-8 bytes) - fn write_encoded_bytes(&mut self, encoded: &[u8]) -> Result<(), Self::Error>; -} - -const BUF_SIZE: usize = 1024; - -/// A base64 encoder that emits encoded bytes in chunks without heap allocation. -pub struct ChunkedEncoder { - config: Config, - max_input_chunk_len: usize, -} - -impl ChunkedEncoder { - pub fn new(config: Config) -> ChunkedEncoder { - ChunkedEncoder { - config, - max_input_chunk_len: max_input_length(BUF_SIZE, config), - } - } - - pub fn encode(&self, bytes: &[u8], sink: &mut S) -> Result<(), S::Error> { - let mut encode_buf: [u8; BUF_SIZE] = [0; BUF_SIZE]; - let encode_table = self.config.char_set.encode_table(); - - let mut input_index = 0; - - while input_index < bytes.len() { - // either the full input chunk size, or it's the last iteration - let input_chunk_len = cmp::min(self.max_input_chunk_len, bytes.len() - input_index); - - let chunk = &bytes[input_index..(input_index + input_chunk_len)]; - - let mut b64_bytes_written = encode_to_slice(chunk, &mut encode_buf, encode_table); - - input_index += input_chunk_len; - let more_input_left = input_index < bytes.len(); - - if self.config.pad && !more_input_left { - // no more input, add padding if needed. Buffer will have room because - // max_input_length leaves room for it. - b64_bytes_written += add_padding(bytes.len(), &mut encode_buf[b64_bytes_written..]); - } - - sink.write_encoded_bytes(&encode_buf[0..b64_bytes_written])?; - } - - Ok(()) - } -} - -/// Calculate the longest input that can be encoded for the given output buffer size. -/// -/// If the config requires padding, two bytes of buffer space will be set aside so that the last -/// chunk of input can be encoded safely. -/// -/// The input length will always be a multiple of 3 so that no encoding state has to be carried over -/// between chunks. -fn max_input_length(encoded_buf_len: usize, config: Config) -> usize { - let effective_buf_len = if config.pad { - // make room for padding - encoded_buf_len - .checked_sub(2) - .expect("Don't use a tiny buffer") - } else { - encoded_buf_len - }; - - // No padding, so just normal base64 expansion. - (effective_buf_len / 4) * 3 -} - -// A really simple sink that just appends to a string -#[cfg(any(feature = "alloc", feature = "std", test))] -pub(crate) struct StringSink<'a> { - string: &'a mut String, -} - -#[cfg(any(feature = "alloc", feature = "std", test))] -impl<'a> StringSink<'a> { - pub(crate) fn new(s: &mut String) -> StringSink { - StringSink { string: s } - } -} - -#[cfg(any(feature = "alloc", feature = "std", test))] -impl<'a> Sink for StringSink<'a> { - type Error = (); - - fn write_encoded_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> { - self.string.push_str(str::from_utf8(s).unwrap()); - - Ok(()) - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - use crate::{encode_config_buf, tests::random_config, CharacterSet, STANDARD}; - - use rand::{ - distributions::{Distribution, Uniform}, - FromEntropy, Rng, - }; - - #[test] - fn chunked_encode_empty() { - assert_eq!("", chunked_encode_str(&[], STANDARD)); - } - - #[test] - fn chunked_encode_intermediate_fast_loop() { - // > 8 bytes input, will enter the pretty fast loop - assert_eq!( - "Zm9vYmFyYmF6cXV4", - chunked_encode_str(b"foobarbazqux", STANDARD) - ); - } - - #[test] - fn chunked_encode_fast_loop() { - // > 32 bytes input, will enter the uber fast loop - assert_eq!( - "Zm9vYmFyYmF6cXV4cXV1eGNvcmdlZ3JhdWx0Z2FycGx5eg==", - chunked_encode_str(b"foobarbazquxquuxcorgegraultgarplyz", STANDARD) - ); - } - - #[test] - fn chunked_encode_slow_loop_only() { - // < 8 bytes input, slow loop only - assert_eq!("Zm9vYmFy", chunked_encode_str(b"foobar", STANDARD)); - } - - #[test] - fn chunked_encode_matches_normal_encode_random_string_sink() { - let helper = StringSinkTestHelper; - chunked_encode_matches_normal_encode_random(&helper); - } - - #[test] - fn max_input_length_no_pad() { - let config = config_with_pad(false); - assert_eq!(768, max_input_length(1024, config)); - } - - #[test] - fn max_input_length_with_pad_decrements_one_triple() { - let config = config_with_pad(true); - assert_eq!(765, max_input_length(1024, config)); - } - - #[test] - fn max_input_length_with_pad_one_byte_short() { - let config = config_with_pad(true); - assert_eq!(765, max_input_length(1025, config)); - } - - #[test] - fn max_input_length_with_pad_fits_exactly() { - let config = config_with_pad(true); - assert_eq!(768, max_input_length(1026, config)); - } - - #[test] - fn max_input_length_cant_use_extra_single_encoded_byte() { - let config = Config::new(crate::CharacterSet::Standard, false); - assert_eq!(300, max_input_length(401, config)); - } - - pub fn chunked_encode_matches_normal_encode_random(sink_test_helper: &S) { - let mut input_buf: Vec = Vec::new(); - let mut output_buf = String::new(); - let mut rng = rand::rngs::SmallRng::from_entropy(); - let input_len_range = Uniform::new(1, 10_000); - - for _ in 0..5_000 { - input_buf.clear(); - output_buf.clear(); - - let buf_len = input_len_range.sample(&mut rng); - for _ in 0..buf_len { - input_buf.push(rng.gen()); - } - - let config = random_config(&mut rng); - - let chunk_encoded_string = sink_test_helper.encode_to_string(config, &input_buf); - encode_config_buf(&input_buf, config, &mut output_buf); - - assert_eq!( - output_buf, chunk_encoded_string, - "input len={}, config: pad={}", - buf_len, config.pad - ); - } - } - - fn chunked_encode_str(bytes: &[u8], config: Config) -> String { - let mut s = String::new(); - { - let mut sink = StringSink::new(&mut s); - let encoder = ChunkedEncoder::new(config); - encoder.encode(bytes, &mut sink).unwrap(); - } - - return s; - } - - fn config_with_pad(pad: bool) -> Config { - Config::new(CharacterSet::Standard, pad) - } - - // An abstraction around sinks so that we can have tests that easily to any sink implementation - pub trait SinkTestHelper { - fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String; - } - - struct StringSinkTestHelper; - - impl SinkTestHelper for StringSinkTestHelper { - fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String { - let encoder = ChunkedEncoder::new(config); - let mut s = String::new(); - { - let mut sink = StringSink::new(&mut s); - encoder.encode(bytes, &mut sink).unwrap(); - } - - s - } - } - -} diff --git a/vendor/base64/src/decode.rs b/vendor/base64/src/decode.rs deleted file mode 100644 index f9f19c82a3..0000000000 --- a/vendor/base64/src/decode.rs +++ /dev/null @@ -1,862 +0,0 @@ -use crate::{tables, Config}; - -#[cfg(any(feature = "alloc", feature = "std", test))] -use crate::STANDARD; -#[cfg(any(feature = "alloc", feature = "std", test))] -use alloc::vec::Vec; -#[cfg(any(feature = "std", test))] -use std::error; -use core::fmt; - -// decode logic operates on chunks of 8 input bytes without padding -const INPUT_CHUNK_LEN: usize = 8; -const DECODED_CHUNK_LEN: usize = 6; -// we read a u64 and write a u64, but a u64 of input only yields 6 bytes of output, so the last -// 2 bytes of any output u64 should not be counted as written to (but must be available in a -// slice). -const DECODED_CHUNK_SUFFIX: usize = 2; - -// how many u64's of input to handle at a time -const CHUNKS_PER_FAST_LOOP_BLOCK: usize = 4; -const INPUT_BLOCK_LEN: usize = CHUNKS_PER_FAST_LOOP_BLOCK * INPUT_CHUNK_LEN; -// includes the trailing 2 bytes for the final u64 write -const DECODED_BLOCK_LEN: usize = - CHUNKS_PER_FAST_LOOP_BLOCK * DECODED_CHUNK_LEN + DECODED_CHUNK_SUFFIX; - -/// Errors that can occur while decoding. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum DecodeError { - /// An invalid byte was found in the input. The offset and offending byte are provided. - InvalidByte(usize, u8), - /// The length of the input is invalid. - InvalidLength, - /// The last non-padding input symbol's encoded 6 bits have nonzero bits that will be discarded. - /// This is indicative of corrupted or truncated Base64. - /// Unlike InvalidByte, which reports symbols that aren't in the alphabet, this error is for - /// symbols that are in the alphabet but represent nonsensical encodings. - InvalidLastSymbol(usize, u8), -} - -impl fmt::Display for DecodeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - DecodeError::InvalidByte(index, byte) => { - write!(f, "Invalid byte {}, offset {}.", byte, index) - } - DecodeError::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."), - DecodeError::InvalidLastSymbol(index, byte) => { - write!(f, "Invalid last symbol {}, offset {}.", byte, index) - } - } - } -} - -#[cfg(any(feature = "std", test))] -impl error::Error for DecodeError { - fn description(&self) -> &str { - match *self { - DecodeError::InvalidByte(_, _) => "invalid byte", - DecodeError::InvalidLength => "invalid length", - DecodeError::InvalidLastSymbol(_, _) => "invalid last symbol", - } - } - - fn cause(&self) -> Option<&dyn error::Error> { - None - } -} - -///Decode from string reference as octets. -///Returns a Result containing a Vec. -///Convenience `decode_config(input, base64::STANDARD);`. -/// -///# Example -/// -///```rust -///extern crate base64; -/// -///fn main() { -/// let bytes = base64::decode("aGVsbG8gd29ybGQ=").unwrap(); -/// println!("{:?}", bytes); -///} -///``` -#[cfg(any(feature = "alloc", feature = "std", test))] -pub fn decode>(input: &T) -> Result, DecodeError> { - decode_config(input, STANDARD) -} - -///Decode from string reference as octets. -///Returns a Result containing a Vec. -/// -///# Example -/// -///```rust -///extern crate base64; -/// -///fn main() { -/// let bytes = base64::decode_config("aGVsbG8gd29ybGR+Cg==", base64::STANDARD).unwrap(); -/// println!("{:?}", bytes); -/// -/// let bytes_url = base64::decode_config("aGVsbG8gaW50ZXJuZXR-Cg==", base64::URL_SAFE).unwrap(); -/// println!("{:?}", bytes_url); -///} -///``` -#[cfg(any(feature = "alloc", feature = "std", test))] -pub fn decode_config>( - input: &T, - config: Config, -) -> Result, DecodeError> { - let mut buffer = Vec::::with_capacity(input.as_ref().len() * 4 / 3); - - decode_config_buf(input, config, &mut buffer).map(|_| buffer) -} - -///Decode from string reference as octets. -///Writes into the supplied buffer to avoid allocation. -///Returns a Result containing an empty tuple, aka (). -/// -///# Example -/// -///```rust -///extern crate base64; -/// -///fn main() { -/// let mut buffer = Vec::::new(); -/// base64::decode_config_buf("aGVsbG8gd29ybGR+Cg==", base64::STANDARD, &mut buffer).unwrap(); -/// println!("{:?}", buffer); -/// -/// buffer.clear(); -/// -/// base64::decode_config_buf("aGVsbG8gaW50ZXJuZXR-Cg==", base64::URL_SAFE, &mut buffer) -/// .unwrap(); -/// println!("{:?}", buffer); -///} -///``` -#[cfg(any(feature = "alloc", feature = "std", test))] -pub fn decode_config_buf>( - input: &T, - config: Config, - buffer: &mut Vec, -) -> Result<(), DecodeError> { - let input_bytes = input.as_ref(); - - let starting_output_len = buffer.len(); - - let num_chunks = num_chunks(input_bytes); - let decoded_len_estimate = num_chunks - .checked_mul(DECODED_CHUNK_LEN) - .and_then(|p| p.checked_add(starting_output_len)) - .expect("Overflow when calculating output buffer length"); - buffer.resize(decoded_len_estimate, 0); - - let bytes_written; - { - let buffer_slice = &mut buffer.as_mut_slice()[starting_output_len..]; - bytes_written = decode_helper(input_bytes, num_chunks, config, buffer_slice)?; - } - - buffer.truncate(starting_output_len + bytes_written); - - Ok(()) -} - -/// Decode the input into the provided output slice. -/// -/// This will not write any bytes past exactly what is decoded (no stray garbage bytes at the end). -/// -/// If you don't know ahead of time what the decoded length should be, size your buffer with a -/// conservative estimate for the decoded length of an input: 3 bytes of output for every 4 bytes of -/// input, rounded up, or in other words `(input_len + 3) / 4 * 3`. -/// -/// If the slice is not large enough, this will panic. -pub fn decode_config_slice>( - input: &T, - config: Config, - output: &mut [u8], -) -> Result { - let input_bytes = input.as_ref(); - - decode_helper(input_bytes, num_chunks(input_bytes), config, output) -} - -/// Return the number of input chunks (including a possibly partial final chunk) in the input -fn num_chunks(input: &[u8]) -> usize { - input - .len() - .checked_add(INPUT_CHUNK_LEN - 1) - .expect("Overflow when calculating number of chunks in input") - / INPUT_CHUNK_LEN -} - -/// Helper to avoid duplicating num_chunks calculation, which is costly on short inputs. -/// Returns the number of bytes written, or an error. -// We're on the fragile edge of compiler heuristics here. If this is not inlined, slow. If this is -// inlined(always), a different slow. plain ol' inline makes the benchmarks happiest at the moment, -// but this is fragile and the best setting changes with only minor code modifications. -#[inline] -fn decode_helper( - input: &[u8], - num_chunks: usize, - config: Config, - output: &mut [u8], -) -> Result { - let char_set = config.char_set; - let decode_table = char_set.decode_table(); - - let remainder_len = input.len() % INPUT_CHUNK_LEN; - - // Because the fast decode loop writes in groups of 8 bytes (unrolled to - // CHUNKS_PER_FAST_LOOP_BLOCK times 8 bytes, where possible) and outputs 8 bytes at a time (of - // which only 6 are valid data), we need to be sure that we stop using the fast decode loop - // soon enough that there will always be 2 more bytes of valid data written after that loop. - let trailing_bytes_to_skip = match remainder_len { - // if input is a multiple of the chunk size, ignore the last chunk as it may have padding, - // and the fast decode logic cannot handle padding - 0 => INPUT_CHUNK_LEN, - // 1 and 5 trailing bytes are illegal: can't decode 6 bits of input into a byte - 1 | 5 => return Err(DecodeError::InvalidLength), - // This will decode to one output byte, which isn't enough to overwrite the 2 extra bytes - // written by the fast decode loop. So, we have to ignore both these 2 bytes and the - // previous chunk. - 2 => INPUT_CHUNK_LEN + 2, - // If this is 3 unpadded chars, then it would actually decode to 2 bytes. However, if this - // is an erroneous 2 chars + 1 pad char that would decode to 1 byte, then it should fail - // with an error, not panic from going past the bounds of the output slice, so we let it - // use stage 3 + 4. - 3 => INPUT_CHUNK_LEN + 3, - // This can also decode to one output byte because it may be 2 input chars + 2 padding - // chars, which would decode to 1 byte. - 4 => INPUT_CHUNK_LEN + 4, - // Everything else is a legal decode len (given that we don't require padding), and will - // decode to at least 2 bytes of output. - _ => remainder_len, - }; - - // rounded up to include partial chunks - let mut remaining_chunks = num_chunks; - - let mut input_index = 0; - let mut output_index = 0; - - { - let length_of_fast_decode_chunks = input.len().saturating_sub(trailing_bytes_to_skip); - - // Fast loop, stage 1 - // manual unroll to CHUNKS_PER_FAST_LOOP_BLOCK of u64s to amortize slice bounds checks - if let Some(max_start_index) = length_of_fast_decode_chunks.checked_sub(INPUT_BLOCK_LEN) { - while input_index <= max_start_index { - let input_slice = &input[input_index..(input_index + INPUT_BLOCK_LEN)]; - let output_slice = &mut output[output_index..(output_index + DECODED_BLOCK_LEN)]; - - decode_chunk( - &input_slice[0..], - input_index, - decode_table, - &mut output_slice[0..], - )?; - decode_chunk( - &input_slice[8..], - input_index + 8, - decode_table, - &mut output_slice[6..], - )?; - decode_chunk( - &input_slice[16..], - input_index + 16, - decode_table, - &mut output_slice[12..], - )?; - decode_chunk( - &input_slice[24..], - input_index + 24, - decode_table, - &mut output_slice[18..], - )?; - - input_index += INPUT_BLOCK_LEN; - output_index += DECODED_BLOCK_LEN - DECODED_CHUNK_SUFFIX; - remaining_chunks -= CHUNKS_PER_FAST_LOOP_BLOCK; - } - } - - // Fast loop, stage 2 (aka still pretty fast loop) - // 8 bytes at a time for whatever we didn't do in stage 1. - if let Some(max_start_index) = length_of_fast_decode_chunks.checked_sub(INPUT_CHUNK_LEN) { - while input_index < max_start_index { - decode_chunk( - &input[input_index..(input_index + INPUT_CHUNK_LEN)], - input_index, - decode_table, - &mut output - [output_index..(output_index + DECODED_CHUNK_LEN + DECODED_CHUNK_SUFFIX)], - )?; - - output_index += DECODED_CHUNK_LEN; - input_index += INPUT_CHUNK_LEN; - remaining_chunks -= 1; - } - } - } - - // Stage 3 - // If input length was such that a chunk had to be deferred until after the fast loop - // because decoding it would have produced 2 trailing bytes that wouldn't then be - // overwritten, we decode that chunk here. This way is slower but doesn't write the 2 - // trailing bytes. - // However, we still need to avoid the last chunk (partial or complete) because it could - // have padding, so we always do 1 fewer to avoid the last chunk. - for _ in 1..remaining_chunks { - decode_chunk_precise( - &input[input_index..], - input_index, - decode_table, - &mut output[output_index..(output_index + DECODED_CHUNK_LEN)], - )?; - - input_index += INPUT_CHUNK_LEN; - output_index += DECODED_CHUNK_LEN; - } - - // always have one more (possibly partial) block of 8 input - debug_assert!(input.len() - input_index > 1 || input.is_empty()); - debug_assert!(input.len() - input_index <= 8); - - // Stage 4 - // Finally, decode any leftovers that aren't a complete input block of 8 bytes. - // Use a u64 as a stack-resident 8 byte buffer. - let mut leftover_bits: u64 = 0; - let mut morsels_in_leftover = 0; - let mut padding_bytes = 0; - let mut first_padding_index: usize = 0; - let mut last_symbol = 0_u8; - let start_of_leftovers = input_index; - for (i, b) in input[start_of_leftovers..].iter().enumerate() { - // '=' padding - if *b == 0x3D { - // There can be bad padding in a few ways: - // 1 - Padding with non-padding characters after it - // 2 - Padding after zero or one non-padding characters before it - // in the current quad. - // 3 - More than two characters of padding. If 3 or 4 padding chars - // are in the same quad, that implies it will be caught by #2. - // If it spreads from one quad to another, it will be caught by - // #2 in the second quad. - - if i % 4 < 2 { - // Check for case #2. - let bad_padding_index = start_of_leftovers - + if padding_bytes > 0 { - // If we've already seen padding, report the first padding index. - // This is to be consistent with the faster logic above: it will report an - // error on the first padding character (since it doesn't expect to see - // anything but actual encoded data). - first_padding_index - } else { - // haven't seen padding before, just use where we are now - i - }; - return Err(DecodeError::InvalidByte(bad_padding_index, *b)); - } - - if padding_bytes == 0 { - first_padding_index = i; - } - - padding_bytes += 1; - continue; - } - - // Check for case #1. - // To make '=' handling consistent with the main loop, don't allow - // non-suffix '=' in trailing chunk either. Report error as first - // erroneous padding. - if padding_bytes > 0 { - return Err(DecodeError::InvalidByte( - start_of_leftovers + first_padding_index, - 0x3D, - )); - } - last_symbol = *b; - - // can use up to 8 * 6 = 48 bits of the u64, if last chunk has no padding. - // To minimize shifts, pack the leftovers from left to right. - let shift = 64 - (morsels_in_leftover + 1) * 6; - // tables are all 256 elements, lookup with a u8 index always succeeds - let morsel = decode_table[*b as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte(start_of_leftovers + i, *b)); - } - - leftover_bits |= (morsel as u64) << shift; - morsels_in_leftover += 1; - } - - let leftover_bits_ready_to_append = match morsels_in_leftover { - 0 => 0, - 2 => 8, - 3 => 16, - 4 => 24, - 6 => 32, - 7 => 40, - 8 => 48, - _ => unreachable!( - "Impossible: must only have 0 to 8 input bytes in last chunk, with no invalid lengths" - ), - }; - - // if there are bits set outside the bits we care about, last symbol encodes trailing bits that - // will not be included in the output - let mask = !0 >> leftover_bits_ready_to_append; - if !config.decode_allow_trailing_bits && (leftover_bits & mask) != 0 { - // last morsel is at `morsels_in_leftover` - 1 - return Err(DecodeError::InvalidLastSymbol( - start_of_leftovers + morsels_in_leftover - 1, - last_symbol, - )); - } - - let mut leftover_bits_appended_to_buf = 0; - while leftover_bits_appended_to_buf < leftover_bits_ready_to_append { - // `as` simply truncates the higher bits, which is what we want here - let selected_bits = (leftover_bits >> (56 - leftover_bits_appended_to_buf)) as u8; - output[output_index] = selected_bits; - output_index += 1; - - leftover_bits_appended_to_buf += 8; - } - - Ok(output_index) -} - -#[inline] -fn write_u64(output: &mut [u8], value: u64) { - output[..8].copy_from_slice(&value.to_be_bytes()); -} - -/// Decode 8 bytes of input into 6 bytes of output. 8 bytes of output will be written, but only the -/// first 6 of those contain meaningful data. -/// -/// `input` is the bytes to decode, of which the first 8 bytes will be processed. -/// `index_at_start_of_input` is the offset in the overall input (used for reporting errors -/// accurately) -/// `decode_table` is the lookup table for the particular base64 alphabet. -/// `output` will have its first 8 bytes overwritten, of which only the first 6 are valid decoded -/// data. -// yes, really inline (worth 30-50% speedup) -#[inline(always)] -fn decode_chunk( - input: &[u8], - index_at_start_of_input: usize, - decode_table: &[u8; 256], - output: &mut [u8], -) -> Result<(), DecodeError> { - let mut accum: u64; - - let morsel = decode_table[input[0] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte(index_at_start_of_input, input[0])); - } - accum = (morsel as u64) << 58; - - let morsel = decode_table[input[1] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte( - index_at_start_of_input + 1, - input[1], - )); - } - accum |= (morsel as u64) << 52; - - let morsel = decode_table[input[2] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte( - index_at_start_of_input + 2, - input[2], - )); - } - accum |= (morsel as u64) << 46; - - let morsel = decode_table[input[3] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte( - index_at_start_of_input + 3, - input[3], - )); - } - accum |= (morsel as u64) << 40; - - let morsel = decode_table[input[4] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte( - index_at_start_of_input + 4, - input[4], - )); - } - accum |= (morsel as u64) << 34; - - let morsel = decode_table[input[5] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte( - index_at_start_of_input + 5, - input[5], - )); - } - accum |= (morsel as u64) << 28; - - let morsel = decode_table[input[6] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte( - index_at_start_of_input + 6, - input[6], - )); - } - accum |= (morsel as u64) << 22; - - let morsel = decode_table[input[7] as usize]; - if morsel == tables::INVALID_VALUE { - return Err(DecodeError::InvalidByte( - index_at_start_of_input + 7, - input[7], - )); - } - accum |= (morsel as u64) << 16; - - write_u64(output, accum); - - Ok(()) -} - -/// Decode an 8-byte chunk, but only write the 6 bytes actually decoded instead of including 2 -/// trailing garbage bytes. -#[inline] -fn decode_chunk_precise( - input: &[u8], - index_at_start_of_input: usize, - decode_table: &[u8; 256], - output: &mut [u8], -) -> Result<(), DecodeError> { - let mut tmp_buf = [0_u8; 8]; - - decode_chunk( - input, - index_at_start_of_input, - decode_table, - &mut tmp_buf[..], - )?; - - output[0..6].copy_from_slice(&tmp_buf[0..6]); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - encode::encode_config_buf, - encode::encode_config_slice, - tests::{assert_encode_sanity, random_config}, - }; - - use rand::{ - distributions::{Distribution, Uniform}, - FromEntropy, Rng, - }; - - #[test] - fn decode_chunk_precise_writes_only_6_bytes() { - let input = b"Zm9vYmFy"; // "foobar" - let mut output = [0_u8, 1, 2, 3, 4, 5, 6, 7]; - decode_chunk_precise(&input[..], 0, tables::STANDARD_DECODE, &mut output).unwrap(); - assert_eq!(&vec![b'f', b'o', b'o', b'b', b'a', b'r', 6, 7], &output); - } - - #[test] - fn decode_chunk_writes_8_bytes() { - let input = b"Zm9vYmFy"; // "foobar" - let mut output = [0_u8, 1, 2, 3, 4, 5, 6, 7]; - decode_chunk(&input[..], 0, tables::STANDARD_DECODE, &mut output).unwrap(); - assert_eq!(&vec![b'f', b'o', b'o', b'b', b'a', b'r', 0, 0], &output); - } - - #[test] - fn decode_into_nonempty_vec_doesnt_clobber_existing_prefix() { - let mut orig_data = Vec::new(); - let mut encoded_data = String::new(); - let mut decoded_with_prefix = Vec::new(); - let mut decoded_without_prefix = Vec::new(); - let mut prefix = Vec::new(); - - let prefix_len_range = Uniform::new(0, 1000); - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - orig_data.clear(); - encoded_data.clear(); - decoded_with_prefix.clear(); - decoded_without_prefix.clear(); - prefix.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - orig_data.push(rng.gen()); - } - - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut encoded_data); - assert_encode_sanity(&encoded_data, config, input_len); - - let prefix_len = prefix_len_range.sample(&mut rng); - - // fill the buf with a prefix - for _ in 0..prefix_len { - prefix.push(rng.gen()); - } - - decoded_with_prefix.resize(prefix_len, 0); - decoded_with_prefix.copy_from_slice(&prefix); - - // decode into the non-empty buf - decode_config_buf(&encoded_data, config, &mut decoded_with_prefix).unwrap(); - // also decode into the empty buf - decode_config_buf(&encoded_data, config, &mut decoded_without_prefix).unwrap(); - - assert_eq!( - prefix_len + decoded_without_prefix.len(), - decoded_with_prefix.len() - ); - assert_eq!(orig_data, decoded_without_prefix); - - // append plain decode onto prefix - prefix.append(&mut decoded_without_prefix); - - assert_eq!(prefix, decoded_with_prefix); - } - } - - #[test] - fn decode_into_slice_doesnt_clobber_existing_prefix_or_suffix() { - let mut orig_data = Vec::new(); - let mut encoded_data = String::new(); - let mut decode_buf = Vec::new(); - let mut decode_buf_copy: Vec = Vec::new(); - - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - orig_data.clear(); - encoded_data.clear(); - decode_buf.clear(); - decode_buf_copy.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - orig_data.push(rng.gen()); - } - - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut encoded_data); - assert_encode_sanity(&encoded_data, config, input_len); - - // fill the buffer with random garbage, long enough to have some room before and after - for _ in 0..5000 { - decode_buf.push(rng.gen()); - } - - // keep a copy for later comparison - decode_buf_copy.extend(decode_buf.iter()); - - let offset = 1000; - - // decode into the non-empty buf - let decode_bytes_written = - decode_config_slice(&encoded_data, config, &mut decode_buf[offset..]).unwrap(); - - assert_eq!(orig_data.len(), decode_bytes_written); - assert_eq!( - orig_data, - &decode_buf[offset..(offset + decode_bytes_written)] - ); - assert_eq!(&decode_buf_copy[0..offset], &decode_buf[0..offset]); - assert_eq!( - &decode_buf_copy[offset + decode_bytes_written..], - &decode_buf[offset + decode_bytes_written..] - ); - } - } - - #[test] - fn decode_into_slice_fits_in_precisely_sized_slice() { - let mut orig_data = Vec::new(); - let mut encoded_data = String::new(); - let mut decode_buf = Vec::new(); - - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - orig_data.clear(); - encoded_data.clear(); - decode_buf.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - orig_data.push(rng.gen()); - } - - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut encoded_data); - assert_encode_sanity(&encoded_data, config, input_len); - - decode_buf.resize(input_len, 0); - - // decode into the non-empty buf - let decode_bytes_written = - decode_config_slice(&encoded_data, config, &mut decode_buf[..]).unwrap(); - - assert_eq!(orig_data.len(), decode_bytes_written); - assert_eq!(orig_data, decode_buf); - } - } - - #[test] - fn detect_invalid_last_symbol_two_bytes() { - let decode = - |input, forgiving| decode_config(input, STANDARD.decode_allow_trailing_bits(forgiving)); - - // example from https://github.com/marshallpierce/rust-base64/issues/75 - assert!(decode("iYU=", false).is_ok()); - // trailing 01 - assert_eq!( - Err(DecodeError::InvalidLastSymbol(2, b'V')), - decode("iYV=", false) - ); - assert_eq!(Ok(vec![137, 133]), decode("iYV=", true)); - // trailing 10 - assert_eq!( - Err(DecodeError::InvalidLastSymbol(2, b'W')), - decode("iYW=", false) - ); - assert_eq!(Ok(vec![137, 133]), decode("iYV=", true)); - // trailing 11 - assert_eq!( - Err(DecodeError::InvalidLastSymbol(2, b'X')), - decode("iYX=", false) - ); - assert_eq!(Ok(vec![137, 133]), decode("iYV=", true)); - - // also works when there are 2 quads in the last block - assert_eq!( - Err(DecodeError::InvalidLastSymbol(6, b'X')), - decode("AAAAiYX=", false) - ); - assert_eq!(Ok(vec![0, 0, 0, 137, 133]), decode("AAAAiYX=", true)); - } - - #[test] - fn detect_invalid_last_symbol_one_byte() { - // 0xFF -> "/w==", so all letters > w, 0-9, and '+', '/' should get InvalidLastSymbol - - assert!(decode("/w==").is_ok()); - // trailing 01 - assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'x')), decode("/x==")); - assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'z')), decode("/z==")); - assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'0')), decode("/0==")); - assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'9')), decode("/9==")); - assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'+')), decode("/+==")); - assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'/')), decode("//==")); - - // also works when there are 2 quads in the last block - assert_eq!( - Err(DecodeError::InvalidLastSymbol(5, b'x')), - decode("AAAA/x==") - ); - } - - #[test] - fn detect_invalid_last_symbol_every_possible_three_symbols() { - let mut base64_to_bytes = ::std::collections::HashMap::new(); - - let mut bytes = [0_u8; 2]; - for b1 in 0_u16..256 { - bytes[0] = b1 as u8; - for b2 in 0_u16..256 { - bytes[1] = b2 as u8; - let mut b64 = vec![0_u8; 4]; - assert_eq!(4, encode_config_slice(&bytes, STANDARD, &mut b64[..])); - let mut v = ::std::vec::Vec::with_capacity(2); - v.extend_from_slice(&bytes[..]); - - assert!(base64_to_bytes.insert(b64, v).is_none()); - } - } - - // every possible combination of symbols must either decode to 2 bytes or get InvalidLastSymbol - - let mut symbols = [0_u8; 4]; - for &s1 in STANDARD.char_set.encode_table().iter() { - symbols[0] = s1; - for &s2 in STANDARD.char_set.encode_table().iter() { - symbols[1] = s2; - for &s3 in STANDARD.char_set.encode_table().iter() { - symbols[2] = s3; - symbols[3] = b'='; - - match base64_to_bytes.get(&symbols[..]) { - Some(bytes) => { - assert_eq!(Ok(bytes.to_vec()), decode_config(&symbols, STANDARD)) - } - None => assert_eq!( - Err(DecodeError::InvalidLastSymbol(2, s3)), - decode_config(&symbols[..], STANDARD) - ), - } - } - } - } - } - - #[test] - fn detect_invalid_last_symbol_every_possible_two_symbols() { - let mut base64_to_bytes = ::std::collections::HashMap::new(); - - for b in 0_u16..256 { - let mut b64 = vec![0_u8; 4]; - assert_eq!(4, encode_config_slice(&[b as u8], STANDARD, &mut b64[..])); - let mut v = ::std::vec::Vec::with_capacity(1); - v.push(b as u8); - - assert!(base64_to_bytes.insert(b64, v).is_none()); - } - - // every possible combination of symbols must either decode to 1 byte or get InvalidLastSymbol - - let mut symbols = [0_u8; 4]; - for &s1 in STANDARD.char_set.encode_table().iter() { - symbols[0] = s1; - for &s2 in STANDARD.char_set.encode_table().iter() { - symbols[1] = s2; - symbols[2] = b'='; - symbols[3] = b'='; - - match base64_to_bytes.get(&symbols[..]) { - Some(bytes) => { - assert_eq!(Ok(bytes.to_vec()), decode_config(&symbols, STANDARD)) - } - None => assert_eq!( - Err(DecodeError::InvalidLastSymbol(1, s2)), - decode_config(&symbols[..], STANDARD) - ), - } - } - } - } -} diff --git a/vendor/base64/src/display.rs b/vendor/base64/src/display.rs deleted file mode 100644 index cc70aac225..0000000000 --- a/vendor/base64/src/display.rs +++ /dev/null @@ -1,88 +0,0 @@ -//! Enables base64'd output anywhere you might use a `Display` implementation, like a format string. -//! -//! ``` -//! use base64::display::Base64Display; -//! -//! let data = vec![0x0, 0x1, 0x2, 0x3]; -//! let wrapper = Base64Display::with_config(&data, base64::STANDARD); -//! -//! assert_eq!("base64: AAECAw==", format!("base64: {}", wrapper)); -//! ``` - -use super::chunked_encoder::ChunkedEncoder; -use super::Config; -use core::fmt::{Display, Formatter}; -use core::{fmt, str}; - -/// A convenience wrapper for base64'ing bytes into a format string without heap allocation. -pub struct Base64Display<'a> { - bytes: &'a [u8], - chunked_encoder: ChunkedEncoder, -} - -impl<'a> Base64Display<'a> { - /// Create a `Base64Display` with the provided config. - pub fn with_config(bytes: &[u8], config: Config) -> Base64Display { - Base64Display { - bytes, - chunked_encoder: ChunkedEncoder::new(config), - } - } -} - -impl<'a> Display for Base64Display<'a> { - fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> { - let mut sink = FormatterSink { f: formatter }; - self.chunked_encoder.encode(self.bytes, &mut sink) - } -} - -struct FormatterSink<'a, 'b: 'a> { - f: &'a mut Formatter<'b>, -} - -impl<'a, 'b: 'a> super::chunked_encoder::Sink for FormatterSink<'a, 'b> { - type Error = fmt::Error; - - fn write_encoded_bytes(&mut self, encoded: &[u8]) -> Result<(), Self::Error> { - // Avoid unsafe. If max performance is needed, write your own display wrapper that uses - // unsafe here to gain about 10-15%. - self.f - .write_str(str::from_utf8(encoded).expect("base64 data was not utf8")) - } -} - -#[cfg(test)] -mod tests { - use super::super::chunked_encoder::tests::{ - chunked_encode_matches_normal_encode_random, SinkTestHelper, - }; - use super::super::*; - use super::*; - - #[test] - fn basic_display() { - assert_eq!( - "~$Zm9vYmFy#*", - format!("~${}#*", Base64Display::with_config(b"foobar", STANDARD)) - ); - assert_eq!( - "~$Zm9vYmFyZg==#*", - format!("~${}#*", Base64Display::with_config(b"foobarf", STANDARD)) - ); - } - - #[test] - fn display_encode_matches_normal_encode() { - let helper = DisplaySinkTestHelper; - chunked_encode_matches_normal_encode_random(&helper); - } - - struct DisplaySinkTestHelper; - - impl SinkTestHelper for DisplaySinkTestHelper { - fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String { - format!("{}", Base64Display::with_config(bytes, config)) - } - } -} diff --git a/vendor/base64/src/encode.rs b/vendor/base64/src/encode.rs deleted file mode 100644 index ad0aa6addb..0000000000 --- a/vendor/base64/src/encode.rs +++ /dev/null @@ -1,673 +0,0 @@ -use crate::Config; -#[cfg(any(feature = "alloc", feature = "std", test))] -use crate::{chunked_encoder, STANDARD}; -#[cfg(any(feature = "alloc", feature = "std", test))] -use alloc::{string::String, vec}; -use core::convert::TryInto; - -///Encode arbitrary octets as base64. -///Returns a String. -///Convenience for `encode_config(input, base64::STANDARD);`. -/// -///# Example -/// -///```rust -///extern crate base64; -/// -///fn main() { -/// let b64 = base64::encode(b"hello world"); -/// println!("{}", b64); -///} -///``` -#[cfg(any(feature = "alloc", feature = "std", test))] -pub fn encode>(input: &T) -> String { - encode_config(input, STANDARD) -} - -///Encode arbitrary octets as base64. -///Returns a String. -/// -///# Example -/// -///```rust -///extern crate base64; -/// -///fn main() { -/// let b64 = base64::encode_config(b"hello world~", base64::STANDARD); -/// println!("{}", b64); -/// -/// let b64_url = base64::encode_config(b"hello internet~", base64::URL_SAFE); -/// println!("{}", b64_url); -///} -///``` -#[cfg(any(feature = "alloc", feature = "std", test))] -pub fn encode_config>(input: &T, config: Config) -> String { - let mut buf = match encoded_size(input.as_ref().len(), config) { - Some(n) => vec![0; n], - None => panic!("integer overflow when calculating buffer size"), - }; - - let encoded_len = encode_config_slice(input.as_ref(), config, &mut buf[..]); - debug_assert_eq!(encoded_len, buf.len()); - - String::from_utf8(buf).expect("Invalid UTF8") -} - -///Encode arbitrary octets as base64. -///Writes into the supplied output buffer, which will grow the buffer if needed. -/// -///# Example -/// -///```rust -///extern crate base64; -/// -///fn main() { -/// let mut buf = String::new(); -/// base64::encode_config_buf(b"hello world~", base64::STANDARD, &mut buf); -/// println!("{}", buf); -/// -/// buf.clear(); -/// base64::encode_config_buf(b"hello internet~", base64::URL_SAFE, &mut buf); -/// println!("{}", buf); -///} -///``` -#[cfg(any(feature = "alloc", feature = "std", test))] -pub fn encode_config_buf>(input: &T, config: Config, buf: &mut String) { - let input_bytes = input.as_ref(); - - { - let mut sink = chunked_encoder::StringSink::new(buf); - let encoder = chunked_encoder::ChunkedEncoder::new(config); - - encoder - .encode(input_bytes, &mut sink) - .expect("Writing to a String shouldn't fail") - } -} - -/// Encode arbitrary octets as base64. -/// Writes into the supplied output buffer. -/// -/// This is useful if you wish to avoid allocation entirely (e.g. encoding into a stack-resident -/// or statically-allocated buffer). -/// -/// # Panics -/// -/// If `output` is too small to hold the encoded version of `input`, a panic will result. -/// -/// # Example -/// -/// ```rust -/// extern crate base64; -/// -/// fn main() { -/// let s = b"hello internet!"; -/// let mut buf = Vec::new(); -/// // make sure we'll have a slice big enough for base64 + padding -/// buf.resize(s.len() * 4 / 3 + 4, 0); -/// -/// let bytes_written = base64::encode_config_slice(s, -/// base64::STANDARD, &mut buf); -/// -/// // shorten our vec down to just what was written -/// buf.resize(bytes_written, 0); -/// -/// assert_eq!(s, base64::decode(&buf).unwrap().as_slice()); -/// } -/// ``` -pub fn encode_config_slice>( - input: &T, - config: Config, - output: &mut [u8], -) -> usize { - let input_bytes = input.as_ref(); - - let encoded_size = encoded_size(input_bytes.len(), config) - .expect("usize overflow when calculating buffer size"); - - let mut b64_output = &mut output[0..encoded_size]; - - encode_with_padding(&input_bytes, config, encoded_size, &mut b64_output); - - encoded_size -} - -/// B64-encode and pad (if configured). -/// -/// This helper exists to avoid recalculating encoded_size, which is relatively expensive on short -/// inputs. -/// -/// `encoded_size` is the encoded size calculated for `input`. -/// -/// `output` must be of size `encoded_size`. -/// -/// All bytes in `output` will be written to since it is exactly the size of the output. -fn encode_with_padding(input: &[u8], config: Config, encoded_size: usize, output: &mut [u8]) { - debug_assert_eq!(encoded_size, output.len()); - - let b64_bytes_written = encode_to_slice(input, output, config.char_set.encode_table()); - - let padding_bytes = if config.pad { - add_padding(input.len(), &mut output[b64_bytes_written..]) - } else { - 0 - }; - - let encoded_bytes = b64_bytes_written - .checked_add(padding_bytes) - .expect("usize overflow when calculating b64 length"); - - debug_assert_eq!(encoded_size, encoded_bytes); -} - -#[inline] -fn read_u64(s: &[u8]) -> u64 { - u64::from_be_bytes(s[..8].try_into().unwrap()) -} - -/// Encode input bytes to utf8 base64 bytes. Does not pad. -/// `output` must be long enough to hold the encoded `input` without padding. -/// Returns the number of bytes written. -#[inline] -pub fn encode_to_slice(input: &[u8], output: &mut [u8], encode_table: &[u8; 64]) -> usize { - let mut input_index: usize = 0; - - const BLOCKS_PER_FAST_LOOP: usize = 4; - const LOW_SIX_BITS: u64 = 0x3F; - - // we read 8 bytes at a time (u64) but only actually consume 6 of those bytes. Thus, we need - // 2 trailing bytes to be available to read.. - let last_fast_index = input.len().saturating_sub(BLOCKS_PER_FAST_LOOP * 6 + 2); - let mut output_index = 0; - - if last_fast_index > 0 { - while input_index <= last_fast_index { - // Major performance wins from letting the optimizer do the bounds check once, mostly - // on the output side - let input_chunk = &input[input_index..(input_index + (BLOCKS_PER_FAST_LOOP * 6 + 2))]; - let output_chunk = &mut output[output_index..(output_index + BLOCKS_PER_FAST_LOOP * 8)]; - - // Hand-unrolling for 32 vs 16 or 8 bytes produces yields performance about equivalent - // to unsafe pointer code on a Xeon E5-1650v3. 64 byte unrolling was slightly better for - // large inputs but significantly worse for 50-byte input, unsurprisingly. I suspect - // that it's a not uncommon use case to encode smallish chunks of data (e.g. a 64-byte - // SHA-512 digest), so it would be nice if that fit in the unrolled loop at least once. - // Plus, single-digit percentage performance differences might well be quite different - // on different hardware. - - let input_u64 = read_u64(&input_chunk[0..]); - - output_chunk[0] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; - output_chunk[1] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; - output_chunk[2] = encode_table[((input_u64 >> 46) & LOW_SIX_BITS) as usize]; - output_chunk[3] = encode_table[((input_u64 >> 40) & LOW_SIX_BITS) as usize]; - output_chunk[4] = encode_table[((input_u64 >> 34) & LOW_SIX_BITS) as usize]; - output_chunk[5] = encode_table[((input_u64 >> 28) & LOW_SIX_BITS) as usize]; - output_chunk[6] = encode_table[((input_u64 >> 22) & LOW_SIX_BITS) as usize]; - output_chunk[7] = encode_table[((input_u64 >> 16) & LOW_SIX_BITS) as usize]; - - let input_u64 = read_u64(&input_chunk[6..]); - - output_chunk[8] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; - output_chunk[9] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; - output_chunk[10] = encode_table[((input_u64 >> 46) & LOW_SIX_BITS) as usize]; - output_chunk[11] = encode_table[((input_u64 >> 40) & LOW_SIX_BITS) as usize]; - output_chunk[12] = encode_table[((input_u64 >> 34) & LOW_SIX_BITS) as usize]; - output_chunk[13] = encode_table[((input_u64 >> 28) & LOW_SIX_BITS) as usize]; - output_chunk[14] = encode_table[((input_u64 >> 22) & LOW_SIX_BITS) as usize]; - output_chunk[15] = encode_table[((input_u64 >> 16) & LOW_SIX_BITS) as usize]; - - let input_u64 = read_u64(&input_chunk[12..]); - - output_chunk[16] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; - output_chunk[17] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; - output_chunk[18] = encode_table[((input_u64 >> 46) & LOW_SIX_BITS) as usize]; - output_chunk[19] = encode_table[((input_u64 >> 40) & LOW_SIX_BITS) as usize]; - output_chunk[20] = encode_table[((input_u64 >> 34) & LOW_SIX_BITS) as usize]; - output_chunk[21] = encode_table[((input_u64 >> 28) & LOW_SIX_BITS) as usize]; - output_chunk[22] = encode_table[((input_u64 >> 22) & LOW_SIX_BITS) as usize]; - output_chunk[23] = encode_table[((input_u64 >> 16) & LOW_SIX_BITS) as usize]; - - let input_u64 = read_u64(&input_chunk[18..]); - - output_chunk[24] = encode_table[((input_u64 >> 58) & LOW_SIX_BITS) as usize]; - output_chunk[25] = encode_table[((input_u64 >> 52) & LOW_SIX_BITS) as usize]; - output_chunk[26] = encode_table[((input_u64 >> 46) & LOW_SIX_BITS) as usize]; - output_chunk[27] = encode_table[((input_u64 >> 40) & LOW_SIX_BITS) as usize]; - output_chunk[28] = encode_table[((input_u64 >> 34) & LOW_SIX_BITS) as usize]; - output_chunk[29] = encode_table[((input_u64 >> 28) & LOW_SIX_BITS) as usize]; - output_chunk[30] = encode_table[((input_u64 >> 22) & LOW_SIX_BITS) as usize]; - output_chunk[31] = encode_table[((input_u64 >> 16) & LOW_SIX_BITS) as usize]; - - output_index += BLOCKS_PER_FAST_LOOP * 8; - input_index += BLOCKS_PER_FAST_LOOP * 6; - } - } - - // Encode what's left after the fast loop. - - const LOW_SIX_BITS_U8: u8 = 0x3F; - - let rem = input.len() % 3; - let start_of_rem = input.len() - rem; - - // start at the first index not handled by fast loop, which may be 0. - - while input_index < start_of_rem { - let input_chunk = &input[input_index..(input_index + 3)]; - let output_chunk = &mut output[output_index..(output_index + 4)]; - - output_chunk[0] = encode_table[(input_chunk[0] >> 2) as usize]; - output_chunk[1] = - encode_table[((input_chunk[0] << 4 | input_chunk[1] >> 4) & LOW_SIX_BITS_U8) as usize]; - output_chunk[2] = - encode_table[((input_chunk[1] << 2 | input_chunk[2] >> 6) & LOW_SIX_BITS_U8) as usize]; - output_chunk[3] = encode_table[(input_chunk[2] & LOW_SIX_BITS_U8) as usize]; - - input_index += 3; - output_index += 4; - } - - if rem == 2 { - output[output_index] = encode_table[(input[start_of_rem] >> 2) as usize]; - output[output_index + 1] = encode_table[((input[start_of_rem] << 4 - | input[start_of_rem + 1] >> 4) - & LOW_SIX_BITS_U8) as usize]; - output[output_index + 2] = - encode_table[((input[start_of_rem + 1] << 2) & LOW_SIX_BITS_U8) as usize]; - output_index += 3; - } else if rem == 1 { - output[output_index] = encode_table[(input[start_of_rem] >> 2) as usize]; - output[output_index + 1] = - encode_table[((input[start_of_rem] << 4) & LOW_SIX_BITS_U8) as usize]; - output_index += 2; - } - - output_index -} - -/// calculate the base64 encoded string size, including padding if appropriate -pub fn encoded_size(bytes_len: usize, config: Config) -> Option { - let rem = bytes_len % 3; - - let complete_input_chunks = bytes_len / 3; - let complete_chunk_output = complete_input_chunks.checked_mul(4); - - if rem > 0 { - if config.pad { - complete_chunk_output.and_then(|c| c.checked_add(4)) - } else { - let encoded_rem = match rem { - 1 => 2, - 2 => 3, - _ => unreachable!("Impossible remainder"), - }; - complete_chunk_output.and_then(|c| c.checked_add(encoded_rem)) - } - } else { - complete_chunk_output - } -} - -/// Write padding characters. -/// `output` is the slice where padding should be written, of length at least 2. -/// -/// Returns the number of padding bytes written. -pub fn add_padding(input_len: usize, output: &mut [u8]) -> usize { - let rem = input_len % 3; - let mut bytes_written = 0; - for _ in 0..((3 - rem) % 3) { - output[bytes_written] = b'='; - bytes_written += 1; - } - - bytes_written -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - decode::decode_config_buf, - tests::{assert_encode_sanity, random_config}, - Config, STANDARD, URL_SAFE_NO_PAD, - }; - - use rand::{ - distributions::{Distribution, Uniform}, - FromEntropy, Rng, - }; - use std; - use std::str; - - #[test] - fn encoded_size_correct_standard() { - assert_encoded_length(0, 0, STANDARD); - - assert_encoded_length(1, 4, STANDARD); - assert_encoded_length(2, 4, STANDARD); - assert_encoded_length(3, 4, STANDARD); - - assert_encoded_length(4, 8, STANDARD); - assert_encoded_length(5, 8, STANDARD); - assert_encoded_length(6, 8, STANDARD); - - assert_encoded_length(7, 12, STANDARD); - assert_encoded_length(8, 12, STANDARD); - assert_encoded_length(9, 12, STANDARD); - - assert_encoded_length(54, 72, STANDARD); - - assert_encoded_length(55, 76, STANDARD); - assert_encoded_length(56, 76, STANDARD); - assert_encoded_length(57, 76, STANDARD); - - assert_encoded_length(58, 80, STANDARD); - } - - #[test] - fn encoded_size_correct_no_pad() { - assert_encoded_length(0, 0, URL_SAFE_NO_PAD); - - assert_encoded_length(1, 2, URL_SAFE_NO_PAD); - assert_encoded_length(2, 3, URL_SAFE_NO_PAD); - assert_encoded_length(3, 4, URL_SAFE_NO_PAD); - - assert_encoded_length(4, 6, URL_SAFE_NO_PAD); - assert_encoded_length(5, 7, URL_SAFE_NO_PAD); - assert_encoded_length(6, 8, URL_SAFE_NO_PAD); - - assert_encoded_length(7, 10, URL_SAFE_NO_PAD); - assert_encoded_length(8, 11, URL_SAFE_NO_PAD); - assert_encoded_length(9, 12, URL_SAFE_NO_PAD); - - assert_encoded_length(54, 72, URL_SAFE_NO_PAD); - - assert_encoded_length(55, 74, URL_SAFE_NO_PAD); - assert_encoded_length(56, 75, URL_SAFE_NO_PAD); - assert_encoded_length(57, 76, URL_SAFE_NO_PAD); - - assert_encoded_length(58, 78, URL_SAFE_NO_PAD); - } - - #[test] - fn encoded_size_overflow() { - assert_eq!(None, encoded_size(std::usize::MAX, STANDARD)); - } - - #[test] - fn encode_config_buf_into_nonempty_buffer_doesnt_clobber_prefix() { - let mut orig_data = Vec::new(); - let mut prefix = String::new(); - let mut encoded_data_no_prefix = String::new(); - let mut encoded_data_with_prefix = String::new(); - let mut decoded = Vec::new(); - - let prefix_len_range = Uniform::new(0, 1000); - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - orig_data.clear(); - prefix.clear(); - encoded_data_no_prefix.clear(); - encoded_data_with_prefix.clear(); - decoded.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - orig_data.push(rng.gen()); - } - - let prefix_len = prefix_len_range.sample(&mut rng); - for _ in 0..prefix_len { - // getting convenient random single-byte printable chars that aren't base64 is - // annoying - prefix.push('#'); - } - encoded_data_with_prefix.push_str(&prefix); - - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut encoded_data_no_prefix); - encode_config_buf(&orig_data, config, &mut encoded_data_with_prefix); - - assert_eq!( - encoded_data_no_prefix.len() + prefix_len, - encoded_data_with_prefix.len() - ); - assert_encode_sanity(&encoded_data_no_prefix, config, input_len); - assert_encode_sanity(&encoded_data_with_prefix[prefix_len..], config, input_len); - - // append plain encode onto prefix - prefix.push_str(&mut encoded_data_no_prefix); - - assert_eq!(prefix, encoded_data_with_prefix); - - decode_config_buf(&encoded_data_no_prefix, config, &mut decoded).unwrap(); - assert_eq!(orig_data, decoded); - } - } - - #[test] - fn encode_config_slice_into_nonempty_buffer_doesnt_clobber_suffix() { - let mut orig_data = Vec::new(); - let mut encoded_data = Vec::new(); - let mut encoded_data_original_state = Vec::new(); - let mut decoded = Vec::new(); - - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - orig_data.clear(); - encoded_data.clear(); - encoded_data_original_state.clear(); - decoded.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - orig_data.push(rng.gen()); - } - - // plenty of existing garbage in the encoded buffer - for _ in 0..10 * input_len { - encoded_data.push(rng.gen()); - } - - encoded_data_original_state.extend_from_slice(&encoded_data); - - let config = random_config(&mut rng); - - let encoded_size = encoded_size(input_len, config).unwrap(); - - assert_eq!( - encoded_size, - encode_config_slice(&orig_data, config, &mut encoded_data) - ); - - assert_encode_sanity( - std::str::from_utf8(&encoded_data[0..encoded_size]).unwrap(), - config, - input_len, - ); - - assert_eq!( - &encoded_data[encoded_size..], - &encoded_data_original_state[encoded_size..] - ); - - decode_config_buf(&encoded_data[0..encoded_size], config, &mut decoded).unwrap(); - assert_eq!(orig_data, decoded); - } - } - - #[test] - fn encode_config_slice_fits_into_precisely_sized_slice() { - let mut orig_data = Vec::new(); - let mut encoded_data = Vec::new(); - let mut decoded = Vec::new(); - - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - orig_data.clear(); - encoded_data.clear(); - decoded.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - orig_data.push(rng.gen()); - } - - let config = random_config(&mut rng); - - let encoded_size = encoded_size(input_len, config).unwrap(); - - encoded_data.resize(encoded_size, 0); - - assert_eq!( - encoded_size, - encode_config_slice(&orig_data, config, &mut encoded_data) - ); - - assert_encode_sanity( - std::str::from_utf8(&encoded_data[0..encoded_size]).unwrap(), - config, - input_len, - ); - - decode_config_buf(&encoded_data[0..encoded_size], config, &mut decoded).unwrap(); - assert_eq!(orig_data, decoded); - } - } - - #[test] - fn encode_to_slice_random_valid_utf8() { - let mut input = Vec::new(); - let mut output = Vec::new(); - - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - input.clear(); - output.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - input.push(rng.gen()); - } - - let config = random_config(&mut rng); - - // fill up the output buffer with garbage - let encoded_size = encoded_size(input_len, config).unwrap(); - for _ in 0..encoded_size { - output.push(rng.gen()); - } - - let orig_output_buf = output.to_vec(); - - let bytes_written = - encode_to_slice(&input, &mut output, config.char_set.encode_table()); - - // make sure the part beyond bytes_written is the same garbage it was before - assert_eq!(orig_output_buf[bytes_written..], output[bytes_written..]); - - // make sure the encoded bytes are UTF-8 - let _ = str::from_utf8(&output[0..bytes_written]).unwrap(); - } - } - - #[test] - fn encode_with_padding_random_valid_utf8() { - let mut input = Vec::new(); - let mut output = Vec::new(); - - let input_len_range = Uniform::new(0, 1000); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..10_000 { - input.clear(); - output.clear(); - - let input_len = input_len_range.sample(&mut rng); - - for _ in 0..input_len { - input.push(rng.gen()); - } - - let config = random_config(&mut rng); - - // fill up the output buffer with garbage - let encoded_size = encoded_size(input_len, config).unwrap(); - for _ in 0..encoded_size + 1000 { - output.push(rng.gen()); - } - - let orig_output_buf = output.to_vec(); - - encode_with_padding(&input, config, encoded_size, &mut output[0..encoded_size]); - - // make sure the part beyond b64 is the same garbage it was before - assert_eq!(orig_output_buf[encoded_size..], output[encoded_size..]); - - // make sure the encoded bytes are UTF-8 - let _ = str::from_utf8(&output[0..encoded_size]).unwrap(); - } - } - - #[test] - fn add_padding_random_valid_utf8() { - let mut output = Vec::new(); - - let mut rng = rand::rngs::SmallRng::from_entropy(); - - // cover our bases for length % 3 - for input_len in 0..10 { - output.clear(); - - // fill output with random - for _ in 0..10 { - output.push(rng.gen()); - } - - let orig_output_buf = output.to_vec(); - - let bytes_written = add_padding(input_len, &mut output); - - // make sure the part beyond bytes_written is the same garbage it was before - assert_eq!(orig_output_buf[bytes_written..], output[bytes_written..]); - - // make sure the encoded bytes are UTF-8 - let _ = str::from_utf8(&output[0..bytes_written]).unwrap(); - } - } - - fn assert_encoded_length(input_len: usize, encoded_len: usize, config: Config) { - assert_eq!(encoded_len, encoded_size(input_len, config).unwrap()); - - let mut bytes: Vec = Vec::new(); - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..input_len { - bytes.push(rng.gen()); - } - - let encoded = encode_config(&bytes, config); - assert_encode_sanity(&encoded, config, input_len); - - assert_eq!(encoded_len, encoded.len()); - } - -} diff --git a/vendor/base64/src/lib.rs b/vendor/base64/src/lib.rs deleted file mode 100644 index ce71e2c855..0000000000 --- a/vendor/base64/src/lib.rs +++ /dev/null @@ -1,203 +0,0 @@ -//! # Configs -//! -//! There isn't just one type of Base64; that would be too simple. You need to choose a character -//! set (standard, URL-safe, etc) and padding suffix (yes/no). -//! The `Config` struct encapsulates this info. There are some common configs included: `STANDARD`, -//! `URL_SAFE`, etc. You can also make your own `Config` if needed. -//! -//! The functions that don't have `config` in the name (e.g. `encode()` and `decode()`) use the -//! `STANDARD` config . -//! -//! The functions that write to a slice (the ones that end in `_slice`) are generally the fastest -//! because they don't need to resize anything. If it fits in your workflow and you care about -//! performance, keep using the same buffer (growing as need be) and use the `_slice` methods for -//! the best performance. -//! -//! # Encoding -//! -//! Several different encoding functions are available to you depending on your desire for -//! convenience vs performance. -//! -//! | Function | Output | Allocates | -//! | ----------------------- | ---------------------------- | ------------------------------ | -//! | `encode` | Returns a new `String` | Always | -//! | `encode_config` | Returns a new `String` | Always | -//! | `encode_config_buf` | Appends to provided `String` | Only if `String` needs to grow | -//! | `encode_config_slice` | Writes to provided `&[u8]` | Never | -//! -//! All of the encoding functions that take a `Config` will pad as per the config. -//! -//! # Decoding -//! -//! Just as for encoding, there are different decoding functions available. -//! -//! | Function | Output | Allocates | -//! | ----------------------- | ----------------------------- | ------------------------------ | -//! | `decode` | Returns a new `Vec` | Always | -//! | `decode_config` | Returns a new `Vec` | Always | -//! | `decode_config_buf` | Appends to provided `Vec` | Only if `Vec` needs to grow | -//! | `decode_config_slice` | Writes to provided `&[u8]` | Never | -//! -//! Unlike encoding, where all possible input is valid, decoding can fail (see `DecodeError`). -//! -//! Input can be invalid because it has invalid characters or invalid padding. (No padding at all is -//! valid, but excess padding is not.) Whitespace in the input is invalid. -//! -//! # Panics -//! -//! If length calculations result in overflowing `usize`, a panic will result. -//! -//! The `_slice` flavors of encode or decode will panic if the provided output slice is too small, - -#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))] -#![deny( - missing_docs, - trivial_casts, - trivial_numeric_casts, - unused_extern_crates, - unused_import_braces, - unused_results, - variant_size_differences, - warnings -)] -#![forbid(unsafe_code)] -#![cfg_attr(not(any(feature = "std", test)), no_std)] - -#[cfg(all(feature = "alloc", not(any(feature = "std", test))))] -extern crate alloc; -#[cfg(any(feature = "std", test))] -extern crate std as alloc; - -#[cfg(test)] -#[macro_use] -extern crate doc_comment; - -#[cfg(test)] -doctest!("../README.md"); - -mod chunked_encoder; -pub mod display; -mod tables; -#[cfg(any(feature = "std", test))] -pub mod write; - -mod encode; -pub use crate::encode::encode_config_slice; -#[cfg(any(feature = "alloc", feature = "std", test))] -pub use crate::encode::{encode, encode_config, encode_config_buf}; - -mod decode; -#[cfg(any(feature = "alloc", feature = "std", test))] -pub use crate::decode::{decode, decode_config, decode_config_buf}; -pub use crate::decode::{decode_config_slice, DecodeError}; - -#[cfg(test)] -mod tests; - -/// Available encoding character sets -#[derive(Clone, Copy, Debug)] -pub enum CharacterSet { - /// The standard character set (uses `+` and `/`). - /// - /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-3). - Standard, - /// The URL safe character set (uses `-` and `_`). - /// - /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-4). - UrlSafe, - /// The `crypt(3)` character set (uses `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`). - /// - /// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses. - Crypt, -} - -impl CharacterSet { - fn encode_table(self) -> &'static [u8; 64] { - match self { - CharacterSet::Standard => tables::STANDARD_ENCODE, - CharacterSet::UrlSafe => tables::URL_SAFE_ENCODE, - CharacterSet::Crypt => tables::CRYPT_ENCODE, - } - } - - fn decode_table(self) -> &'static [u8; 256] { - match self { - CharacterSet::Standard => tables::STANDARD_DECODE, - CharacterSet::UrlSafe => tables::URL_SAFE_DECODE, - CharacterSet::Crypt => tables::CRYPT_DECODE, - } - } -} - -/// Contains configuration parameters for base64 encoding -#[derive(Clone, Copy, Debug)] -pub struct Config { - /// Character set to use - char_set: CharacterSet, - /// True to pad output with `=` characters - pad: bool, - /// True to ignore excess nonzero bits in the last few symbols, otherwise an error is returned. - decode_allow_trailing_bits: bool, -} - -impl Config { - /// Create a new `Config`. - pub fn new(char_set: CharacterSet, pad: bool) -> Config { - Config { - char_set, - pad, - decode_allow_trailing_bits: false, - } - } - - /// Sets whether to pad output with `=` characters. - pub fn pad(self, pad: bool) -> Config { - Config { pad, ..self } - } - - /// Sets whether to emit errors for nonzero trailing bits. - /// - /// This is useful when implementing - /// [forgiving-base64 decode](https://infra.spec.whatwg.org/#forgiving-base64-decode). - pub fn decode_allow_trailing_bits(self, allow: bool) -> Config { - Config { - decode_allow_trailing_bits: allow, - ..self - } - } -} - -/// Standard character set with padding. -pub const STANDARD: Config = Config { - char_set: CharacterSet::Standard, - pad: true, - decode_allow_trailing_bits: false, -}; - -/// Standard character set without padding. -pub const STANDARD_NO_PAD: Config = Config { - char_set: CharacterSet::Standard, - pad: false, - decode_allow_trailing_bits: false, -}; - -/// URL-safe character set with padding -pub const URL_SAFE: Config = Config { - char_set: CharacterSet::UrlSafe, - pad: true, - decode_allow_trailing_bits: false, -}; - -/// URL-safe character set without padding -pub const URL_SAFE_NO_PAD: Config = Config { - char_set: CharacterSet::UrlSafe, - pad: false, - decode_allow_trailing_bits: false, -}; - -/// As per `crypt(3)` requirements -pub const CRYPT: Config = Config { - char_set: CharacterSet::Crypt, - pad: false, - decode_allow_trailing_bits: false, -}; diff --git a/vendor/base64/src/tables.rs b/vendor/base64/src/tables.rs deleted file mode 100644 index c68a0a88b1..0000000000 --- a/vendor/base64/src/tables.rs +++ /dev/null @@ -1,979 +0,0 @@ -pub const INVALID_VALUE: u8 = 255; -#[rustfmt::skip] -pub const STANDARD_ENCODE: &[u8; 64] = &[ - 65, // input 0 (0x0) => 'A' (0x41) - 66, // input 1 (0x1) => 'B' (0x42) - 67, // input 2 (0x2) => 'C' (0x43) - 68, // input 3 (0x3) => 'D' (0x44) - 69, // input 4 (0x4) => 'E' (0x45) - 70, // input 5 (0x5) => 'F' (0x46) - 71, // input 6 (0x6) => 'G' (0x47) - 72, // input 7 (0x7) => 'H' (0x48) - 73, // input 8 (0x8) => 'I' (0x49) - 74, // input 9 (0x9) => 'J' (0x4A) - 75, // input 10 (0xA) => 'K' (0x4B) - 76, // input 11 (0xB) => 'L' (0x4C) - 77, // input 12 (0xC) => 'M' (0x4D) - 78, // input 13 (0xD) => 'N' (0x4E) - 79, // input 14 (0xE) => 'O' (0x4F) - 80, // input 15 (0xF) => 'P' (0x50) - 81, // input 16 (0x10) => 'Q' (0x51) - 82, // input 17 (0x11) => 'R' (0x52) - 83, // input 18 (0x12) => 'S' (0x53) - 84, // input 19 (0x13) => 'T' (0x54) - 85, // input 20 (0x14) => 'U' (0x55) - 86, // input 21 (0x15) => 'V' (0x56) - 87, // input 22 (0x16) => 'W' (0x57) - 88, // input 23 (0x17) => 'X' (0x58) - 89, // input 24 (0x18) => 'Y' (0x59) - 90, // input 25 (0x19) => 'Z' (0x5A) - 97, // input 26 (0x1A) => 'a' (0x61) - 98, // input 27 (0x1B) => 'b' (0x62) - 99, // input 28 (0x1C) => 'c' (0x63) - 100, // input 29 (0x1D) => 'd' (0x64) - 101, // input 30 (0x1E) => 'e' (0x65) - 102, // input 31 (0x1F) => 'f' (0x66) - 103, // input 32 (0x20) => 'g' (0x67) - 104, // input 33 (0x21) => 'h' (0x68) - 105, // input 34 (0x22) => 'i' (0x69) - 106, // input 35 (0x23) => 'j' (0x6A) - 107, // input 36 (0x24) => 'k' (0x6B) - 108, // input 37 (0x25) => 'l' (0x6C) - 109, // input 38 (0x26) => 'm' (0x6D) - 110, // input 39 (0x27) => 'n' (0x6E) - 111, // input 40 (0x28) => 'o' (0x6F) - 112, // input 41 (0x29) => 'p' (0x70) - 113, // input 42 (0x2A) => 'q' (0x71) - 114, // input 43 (0x2B) => 'r' (0x72) - 115, // input 44 (0x2C) => 's' (0x73) - 116, // input 45 (0x2D) => 't' (0x74) - 117, // input 46 (0x2E) => 'u' (0x75) - 118, // input 47 (0x2F) => 'v' (0x76) - 119, // input 48 (0x30) => 'w' (0x77) - 120, // input 49 (0x31) => 'x' (0x78) - 121, // input 50 (0x32) => 'y' (0x79) - 122, // input 51 (0x33) => 'z' (0x7A) - 48, // input 52 (0x34) => '0' (0x30) - 49, // input 53 (0x35) => '1' (0x31) - 50, // input 54 (0x36) => '2' (0x32) - 51, // input 55 (0x37) => '3' (0x33) - 52, // input 56 (0x38) => '4' (0x34) - 53, // input 57 (0x39) => '5' (0x35) - 54, // input 58 (0x3A) => '6' (0x36) - 55, // input 59 (0x3B) => '7' (0x37) - 56, // input 60 (0x3C) => '8' (0x38) - 57, // input 61 (0x3D) => '9' (0x39) - 43, // input 62 (0x3E) => '+' (0x2B) - 47, // input 63 (0x3F) => '/' (0x2F) -]; -#[rustfmt::skip] -pub const STANDARD_DECODE: &[u8; 256] = &[ - INVALID_VALUE, // input 0 (0x0) - INVALID_VALUE, // input 1 (0x1) - INVALID_VALUE, // input 2 (0x2) - INVALID_VALUE, // input 3 (0x3) - INVALID_VALUE, // input 4 (0x4) - INVALID_VALUE, // input 5 (0x5) - INVALID_VALUE, // input 6 (0x6) - INVALID_VALUE, // input 7 (0x7) - INVALID_VALUE, // input 8 (0x8) - INVALID_VALUE, // input 9 (0x9) - INVALID_VALUE, // input 10 (0xA) - INVALID_VALUE, // input 11 (0xB) - INVALID_VALUE, // input 12 (0xC) - INVALID_VALUE, // input 13 (0xD) - INVALID_VALUE, // input 14 (0xE) - INVALID_VALUE, // input 15 (0xF) - INVALID_VALUE, // input 16 (0x10) - INVALID_VALUE, // input 17 (0x11) - INVALID_VALUE, // input 18 (0x12) - INVALID_VALUE, // input 19 (0x13) - INVALID_VALUE, // input 20 (0x14) - INVALID_VALUE, // input 21 (0x15) - INVALID_VALUE, // input 22 (0x16) - INVALID_VALUE, // input 23 (0x17) - INVALID_VALUE, // input 24 (0x18) - INVALID_VALUE, // input 25 (0x19) - INVALID_VALUE, // input 26 (0x1A) - INVALID_VALUE, // input 27 (0x1B) - INVALID_VALUE, // input 28 (0x1C) - INVALID_VALUE, // input 29 (0x1D) - INVALID_VALUE, // input 30 (0x1E) - INVALID_VALUE, // input 31 (0x1F) - INVALID_VALUE, // input 32 (0x20) - INVALID_VALUE, // input 33 (0x21) - INVALID_VALUE, // input 34 (0x22) - INVALID_VALUE, // input 35 (0x23) - INVALID_VALUE, // input 36 (0x24) - INVALID_VALUE, // input 37 (0x25) - INVALID_VALUE, // input 38 (0x26) - INVALID_VALUE, // input 39 (0x27) - INVALID_VALUE, // input 40 (0x28) - INVALID_VALUE, // input 41 (0x29) - INVALID_VALUE, // input 42 (0x2A) - 62, // input 43 (0x2B char '+') => 62 (0x3E) - INVALID_VALUE, // input 44 (0x2C) - INVALID_VALUE, // input 45 (0x2D) - INVALID_VALUE, // input 46 (0x2E) - 63, // input 47 (0x2F char '/') => 63 (0x3F) - 52, // input 48 (0x30 char '0') => 52 (0x34) - 53, // input 49 (0x31 char '1') => 53 (0x35) - 54, // input 50 (0x32 char '2') => 54 (0x36) - 55, // input 51 (0x33 char '3') => 55 (0x37) - 56, // input 52 (0x34 char '4') => 56 (0x38) - 57, // input 53 (0x35 char '5') => 57 (0x39) - 58, // input 54 (0x36 char '6') => 58 (0x3A) - 59, // input 55 (0x37 char '7') => 59 (0x3B) - 60, // input 56 (0x38 char '8') => 60 (0x3C) - 61, // input 57 (0x39 char '9') => 61 (0x3D) - INVALID_VALUE, // input 58 (0x3A) - INVALID_VALUE, // input 59 (0x3B) - INVALID_VALUE, // input 60 (0x3C) - INVALID_VALUE, // input 61 (0x3D) - INVALID_VALUE, // input 62 (0x3E) - INVALID_VALUE, // input 63 (0x3F) - INVALID_VALUE, // input 64 (0x40) - 0, // input 65 (0x41 char 'A') => 0 (0x0) - 1, // input 66 (0x42 char 'B') => 1 (0x1) - 2, // input 67 (0x43 char 'C') => 2 (0x2) - 3, // input 68 (0x44 char 'D') => 3 (0x3) - 4, // input 69 (0x45 char 'E') => 4 (0x4) - 5, // input 70 (0x46 char 'F') => 5 (0x5) - 6, // input 71 (0x47 char 'G') => 6 (0x6) - 7, // input 72 (0x48 char 'H') => 7 (0x7) - 8, // input 73 (0x49 char 'I') => 8 (0x8) - 9, // input 74 (0x4A char 'J') => 9 (0x9) - 10, // input 75 (0x4B char 'K') => 10 (0xA) - 11, // input 76 (0x4C char 'L') => 11 (0xB) - 12, // input 77 (0x4D char 'M') => 12 (0xC) - 13, // input 78 (0x4E char 'N') => 13 (0xD) - 14, // input 79 (0x4F char 'O') => 14 (0xE) - 15, // input 80 (0x50 char 'P') => 15 (0xF) - 16, // input 81 (0x51 char 'Q') => 16 (0x10) - 17, // input 82 (0x52 char 'R') => 17 (0x11) - 18, // input 83 (0x53 char 'S') => 18 (0x12) - 19, // input 84 (0x54 char 'T') => 19 (0x13) - 20, // input 85 (0x55 char 'U') => 20 (0x14) - 21, // input 86 (0x56 char 'V') => 21 (0x15) - 22, // input 87 (0x57 char 'W') => 22 (0x16) - 23, // input 88 (0x58 char 'X') => 23 (0x17) - 24, // input 89 (0x59 char 'Y') => 24 (0x18) - 25, // input 90 (0x5A char 'Z') => 25 (0x19) - INVALID_VALUE, // input 91 (0x5B) - INVALID_VALUE, // input 92 (0x5C) - INVALID_VALUE, // input 93 (0x5D) - INVALID_VALUE, // input 94 (0x5E) - INVALID_VALUE, // input 95 (0x5F) - INVALID_VALUE, // input 96 (0x60) - 26, // input 97 (0x61 char 'a') => 26 (0x1A) - 27, // input 98 (0x62 char 'b') => 27 (0x1B) - 28, // input 99 (0x63 char 'c') => 28 (0x1C) - 29, // input 100 (0x64 char 'd') => 29 (0x1D) - 30, // input 101 (0x65 char 'e') => 30 (0x1E) - 31, // input 102 (0x66 char 'f') => 31 (0x1F) - 32, // input 103 (0x67 char 'g') => 32 (0x20) - 33, // input 104 (0x68 char 'h') => 33 (0x21) - 34, // input 105 (0x69 char 'i') => 34 (0x22) - 35, // input 106 (0x6A char 'j') => 35 (0x23) - 36, // input 107 (0x6B char 'k') => 36 (0x24) - 37, // input 108 (0x6C char 'l') => 37 (0x25) - 38, // input 109 (0x6D char 'm') => 38 (0x26) - 39, // input 110 (0x6E char 'n') => 39 (0x27) - 40, // input 111 (0x6F char 'o') => 40 (0x28) - 41, // input 112 (0x70 char 'p') => 41 (0x29) - 42, // input 113 (0x71 char 'q') => 42 (0x2A) - 43, // input 114 (0x72 char 'r') => 43 (0x2B) - 44, // input 115 (0x73 char 's') => 44 (0x2C) - 45, // input 116 (0x74 char 't') => 45 (0x2D) - 46, // input 117 (0x75 char 'u') => 46 (0x2E) - 47, // input 118 (0x76 char 'v') => 47 (0x2F) - 48, // input 119 (0x77 char 'w') => 48 (0x30) - 49, // input 120 (0x78 char 'x') => 49 (0x31) - 50, // input 121 (0x79 char 'y') => 50 (0x32) - 51, // input 122 (0x7A char 'z') => 51 (0x33) - INVALID_VALUE, // input 123 (0x7B) - INVALID_VALUE, // input 124 (0x7C) - INVALID_VALUE, // input 125 (0x7D) - INVALID_VALUE, // input 126 (0x7E) - INVALID_VALUE, // input 127 (0x7F) - INVALID_VALUE, // input 128 (0x80) - INVALID_VALUE, // input 129 (0x81) - INVALID_VALUE, // input 130 (0x82) - INVALID_VALUE, // input 131 (0x83) - INVALID_VALUE, // input 132 (0x84) - INVALID_VALUE, // input 133 (0x85) - INVALID_VALUE, // input 134 (0x86) - INVALID_VALUE, // input 135 (0x87) - INVALID_VALUE, // input 136 (0x88) - INVALID_VALUE, // input 137 (0x89) - INVALID_VALUE, // input 138 (0x8A) - INVALID_VALUE, // input 139 (0x8B) - INVALID_VALUE, // input 140 (0x8C) - INVALID_VALUE, // input 141 (0x8D) - INVALID_VALUE, // input 142 (0x8E) - INVALID_VALUE, // input 143 (0x8F) - INVALID_VALUE, // input 144 (0x90) - INVALID_VALUE, // input 145 (0x91) - INVALID_VALUE, // input 146 (0x92) - INVALID_VALUE, // input 147 (0x93) - INVALID_VALUE, // input 148 (0x94) - INVALID_VALUE, // input 149 (0x95) - INVALID_VALUE, // input 150 (0x96) - INVALID_VALUE, // input 151 (0x97) - INVALID_VALUE, // input 152 (0x98) - INVALID_VALUE, // input 153 (0x99) - INVALID_VALUE, // input 154 (0x9A) - INVALID_VALUE, // input 155 (0x9B) - INVALID_VALUE, // input 156 (0x9C) - INVALID_VALUE, // input 157 (0x9D) - INVALID_VALUE, // input 158 (0x9E) - INVALID_VALUE, // input 159 (0x9F) - INVALID_VALUE, // input 160 (0xA0) - INVALID_VALUE, // input 161 (0xA1) - INVALID_VALUE, // input 162 (0xA2) - INVALID_VALUE, // input 163 (0xA3) - INVALID_VALUE, // input 164 (0xA4) - INVALID_VALUE, // input 165 (0xA5) - INVALID_VALUE, // input 166 (0xA6) - INVALID_VALUE, // input 167 (0xA7) - INVALID_VALUE, // input 168 (0xA8) - INVALID_VALUE, // input 169 (0xA9) - INVALID_VALUE, // input 170 (0xAA) - INVALID_VALUE, // input 171 (0xAB) - INVALID_VALUE, // input 172 (0xAC) - INVALID_VALUE, // input 173 (0xAD) - INVALID_VALUE, // input 174 (0xAE) - INVALID_VALUE, // input 175 (0xAF) - INVALID_VALUE, // input 176 (0xB0) - INVALID_VALUE, // input 177 (0xB1) - INVALID_VALUE, // input 178 (0xB2) - INVALID_VALUE, // input 179 (0xB3) - INVALID_VALUE, // input 180 (0xB4) - INVALID_VALUE, // input 181 (0xB5) - INVALID_VALUE, // input 182 (0xB6) - INVALID_VALUE, // input 183 (0xB7) - INVALID_VALUE, // input 184 (0xB8) - INVALID_VALUE, // input 185 (0xB9) - INVALID_VALUE, // input 186 (0xBA) - INVALID_VALUE, // input 187 (0xBB) - INVALID_VALUE, // input 188 (0xBC) - INVALID_VALUE, // input 189 (0xBD) - INVALID_VALUE, // input 190 (0xBE) - INVALID_VALUE, // input 191 (0xBF) - INVALID_VALUE, // input 192 (0xC0) - INVALID_VALUE, // input 193 (0xC1) - INVALID_VALUE, // input 194 (0xC2) - INVALID_VALUE, // input 195 (0xC3) - INVALID_VALUE, // input 196 (0xC4) - INVALID_VALUE, // input 197 (0xC5) - INVALID_VALUE, // input 198 (0xC6) - INVALID_VALUE, // input 199 (0xC7) - INVALID_VALUE, // input 200 (0xC8) - INVALID_VALUE, // input 201 (0xC9) - INVALID_VALUE, // input 202 (0xCA) - INVALID_VALUE, // input 203 (0xCB) - INVALID_VALUE, // input 204 (0xCC) - INVALID_VALUE, // input 205 (0xCD) - INVALID_VALUE, // input 206 (0xCE) - INVALID_VALUE, // input 207 (0xCF) - INVALID_VALUE, // input 208 (0xD0) - INVALID_VALUE, // input 209 (0xD1) - INVALID_VALUE, // input 210 (0xD2) - INVALID_VALUE, // input 211 (0xD3) - INVALID_VALUE, // input 212 (0xD4) - INVALID_VALUE, // input 213 (0xD5) - INVALID_VALUE, // input 214 (0xD6) - INVALID_VALUE, // input 215 (0xD7) - INVALID_VALUE, // input 216 (0xD8) - INVALID_VALUE, // input 217 (0xD9) - INVALID_VALUE, // input 218 (0xDA) - INVALID_VALUE, // input 219 (0xDB) - INVALID_VALUE, // input 220 (0xDC) - INVALID_VALUE, // input 221 (0xDD) - INVALID_VALUE, // input 222 (0xDE) - INVALID_VALUE, // input 223 (0xDF) - INVALID_VALUE, // input 224 (0xE0) - INVALID_VALUE, // input 225 (0xE1) - INVALID_VALUE, // input 226 (0xE2) - INVALID_VALUE, // input 227 (0xE3) - INVALID_VALUE, // input 228 (0xE4) - INVALID_VALUE, // input 229 (0xE5) - INVALID_VALUE, // input 230 (0xE6) - INVALID_VALUE, // input 231 (0xE7) - INVALID_VALUE, // input 232 (0xE8) - INVALID_VALUE, // input 233 (0xE9) - INVALID_VALUE, // input 234 (0xEA) - INVALID_VALUE, // input 235 (0xEB) - INVALID_VALUE, // input 236 (0xEC) - INVALID_VALUE, // input 237 (0xED) - INVALID_VALUE, // input 238 (0xEE) - INVALID_VALUE, // input 239 (0xEF) - INVALID_VALUE, // input 240 (0xF0) - INVALID_VALUE, // input 241 (0xF1) - INVALID_VALUE, // input 242 (0xF2) - INVALID_VALUE, // input 243 (0xF3) - INVALID_VALUE, // input 244 (0xF4) - INVALID_VALUE, // input 245 (0xF5) - INVALID_VALUE, // input 246 (0xF6) - INVALID_VALUE, // input 247 (0xF7) - INVALID_VALUE, // input 248 (0xF8) - INVALID_VALUE, // input 249 (0xF9) - INVALID_VALUE, // input 250 (0xFA) - INVALID_VALUE, // input 251 (0xFB) - INVALID_VALUE, // input 252 (0xFC) - INVALID_VALUE, // input 253 (0xFD) - INVALID_VALUE, // input 254 (0xFE) - INVALID_VALUE, // input 255 (0xFF) -]; -#[rustfmt::skip] -pub const URL_SAFE_ENCODE: &[u8; 64] = &[ - 65, // input 0 (0x0) => 'A' (0x41) - 66, // input 1 (0x1) => 'B' (0x42) - 67, // input 2 (0x2) => 'C' (0x43) - 68, // input 3 (0x3) => 'D' (0x44) - 69, // input 4 (0x4) => 'E' (0x45) - 70, // input 5 (0x5) => 'F' (0x46) - 71, // input 6 (0x6) => 'G' (0x47) - 72, // input 7 (0x7) => 'H' (0x48) - 73, // input 8 (0x8) => 'I' (0x49) - 74, // input 9 (0x9) => 'J' (0x4A) - 75, // input 10 (0xA) => 'K' (0x4B) - 76, // input 11 (0xB) => 'L' (0x4C) - 77, // input 12 (0xC) => 'M' (0x4D) - 78, // input 13 (0xD) => 'N' (0x4E) - 79, // input 14 (0xE) => 'O' (0x4F) - 80, // input 15 (0xF) => 'P' (0x50) - 81, // input 16 (0x10) => 'Q' (0x51) - 82, // input 17 (0x11) => 'R' (0x52) - 83, // input 18 (0x12) => 'S' (0x53) - 84, // input 19 (0x13) => 'T' (0x54) - 85, // input 20 (0x14) => 'U' (0x55) - 86, // input 21 (0x15) => 'V' (0x56) - 87, // input 22 (0x16) => 'W' (0x57) - 88, // input 23 (0x17) => 'X' (0x58) - 89, // input 24 (0x18) => 'Y' (0x59) - 90, // input 25 (0x19) => 'Z' (0x5A) - 97, // input 26 (0x1A) => 'a' (0x61) - 98, // input 27 (0x1B) => 'b' (0x62) - 99, // input 28 (0x1C) => 'c' (0x63) - 100, // input 29 (0x1D) => 'd' (0x64) - 101, // input 30 (0x1E) => 'e' (0x65) - 102, // input 31 (0x1F) => 'f' (0x66) - 103, // input 32 (0x20) => 'g' (0x67) - 104, // input 33 (0x21) => 'h' (0x68) - 105, // input 34 (0x22) => 'i' (0x69) - 106, // input 35 (0x23) => 'j' (0x6A) - 107, // input 36 (0x24) => 'k' (0x6B) - 108, // input 37 (0x25) => 'l' (0x6C) - 109, // input 38 (0x26) => 'm' (0x6D) - 110, // input 39 (0x27) => 'n' (0x6E) - 111, // input 40 (0x28) => 'o' (0x6F) - 112, // input 41 (0x29) => 'p' (0x70) - 113, // input 42 (0x2A) => 'q' (0x71) - 114, // input 43 (0x2B) => 'r' (0x72) - 115, // input 44 (0x2C) => 's' (0x73) - 116, // input 45 (0x2D) => 't' (0x74) - 117, // input 46 (0x2E) => 'u' (0x75) - 118, // input 47 (0x2F) => 'v' (0x76) - 119, // input 48 (0x30) => 'w' (0x77) - 120, // input 49 (0x31) => 'x' (0x78) - 121, // input 50 (0x32) => 'y' (0x79) - 122, // input 51 (0x33) => 'z' (0x7A) - 48, // input 52 (0x34) => '0' (0x30) - 49, // input 53 (0x35) => '1' (0x31) - 50, // input 54 (0x36) => '2' (0x32) - 51, // input 55 (0x37) => '3' (0x33) - 52, // input 56 (0x38) => '4' (0x34) - 53, // input 57 (0x39) => '5' (0x35) - 54, // input 58 (0x3A) => '6' (0x36) - 55, // input 59 (0x3B) => '7' (0x37) - 56, // input 60 (0x3C) => '8' (0x38) - 57, // input 61 (0x3D) => '9' (0x39) - 45, // input 62 (0x3E) => '-' (0x2D) - 95, // input 63 (0x3F) => '_' (0x5F) -]; -#[rustfmt::skip] -pub const URL_SAFE_DECODE: &[u8; 256] = &[ - INVALID_VALUE, // input 0 (0x0) - INVALID_VALUE, // input 1 (0x1) - INVALID_VALUE, // input 2 (0x2) - INVALID_VALUE, // input 3 (0x3) - INVALID_VALUE, // input 4 (0x4) - INVALID_VALUE, // input 5 (0x5) - INVALID_VALUE, // input 6 (0x6) - INVALID_VALUE, // input 7 (0x7) - INVALID_VALUE, // input 8 (0x8) - INVALID_VALUE, // input 9 (0x9) - INVALID_VALUE, // input 10 (0xA) - INVALID_VALUE, // input 11 (0xB) - INVALID_VALUE, // input 12 (0xC) - INVALID_VALUE, // input 13 (0xD) - INVALID_VALUE, // input 14 (0xE) - INVALID_VALUE, // input 15 (0xF) - INVALID_VALUE, // input 16 (0x10) - INVALID_VALUE, // input 17 (0x11) - INVALID_VALUE, // input 18 (0x12) - INVALID_VALUE, // input 19 (0x13) - INVALID_VALUE, // input 20 (0x14) - INVALID_VALUE, // input 21 (0x15) - INVALID_VALUE, // input 22 (0x16) - INVALID_VALUE, // input 23 (0x17) - INVALID_VALUE, // input 24 (0x18) - INVALID_VALUE, // input 25 (0x19) - INVALID_VALUE, // input 26 (0x1A) - INVALID_VALUE, // input 27 (0x1B) - INVALID_VALUE, // input 28 (0x1C) - INVALID_VALUE, // input 29 (0x1D) - INVALID_VALUE, // input 30 (0x1E) - INVALID_VALUE, // input 31 (0x1F) - INVALID_VALUE, // input 32 (0x20) - INVALID_VALUE, // input 33 (0x21) - INVALID_VALUE, // input 34 (0x22) - INVALID_VALUE, // input 35 (0x23) - INVALID_VALUE, // input 36 (0x24) - INVALID_VALUE, // input 37 (0x25) - INVALID_VALUE, // input 38 (0x26) - INVALID_VALUE, // input 39 (0x27) - INVALID_VALUE, // input 40 (0x28) - INVALID_VALUE, // input 41 (0x29) - INVALID_VALUE, // input 42 (0x2A) - INVALID_VALUE, // input 43 (0x2B) - INVALID_VALUE, // input 44 (0x2C) - 62, // input 45 (0x2D char '-') => 62 (0x3E) - INVALID_VALUE, // input 46 (0x2E) - INVALID_VALUE, // input 47 (0x2F) - 52, // input 48 (0x30 char '0') => 52 (0x34) - 53, // input 49 (0x31 char '1') => 53 (0x35) - 54, // input 50 (0x32 char '2') => 54 (0x36) - 55, // input 51 (0x33 char '3') => 55 (0x37) - 56, // input 52 (0x34 char '4') => 56 (0x38) - 57, // input 53 (0x35 char '5') => 57 (0x39) - 58, // input 54 (0x36 char '6') => 58 (0x3A) - 59, // input 55 (0x37 char '7') => 59 (0x3B) - 60, // input 56 (0x38 char '8') => 60 (0x3C) - 61, // input 57 (0x39 char '9') => 61 (0x3D) - INVALID_VALUE, // input 58 (0x3A) - INVALID_VALUE, // input 59 (0x3B) - INVALID_VALUE, // input 60 (0x3C) - INVALID_VALUE, // input 61 (0x3D) - INVALID_VALUE, // input 62 (0x3E) - INVALID_VALUE, // input 63 (0x3F) - INVALID_VALUE, // input 64 (0x40) - 0, // input 65 (0x41 char 'A') => 0 (0x0) - 1, // input 66 (0x42 char 'B') => 1 (0x1) - 2, // input 67 (0x43 char 'C') => 2 (0x2) - 3, // input 68 (0x44 char 'D') => 3 (0x3) - 4, // input 69 (0x45 char 'E') => 4 (0x4) - 5, // input 70 (0x46 char 'F') => 5 (0x5) - 6, // input 71 (0x47 char 'G') => 6 (0x6) - 7, // input 72 (0x48 char 'H') => 7 (0x7) - 8, // input 73 (0x49 char 'I') => 8 (0x8) - 9, // input 74 (0x4A char 'J') => 9 (0x9) - 10, // input 75 (0x4B char 'K') => 10 (0xA) - 11, // input 76 (0x4C char 'L') => 11 (0xB) - 12, // input 77 (0x4D char 'M') => 12 (0xC) - 13, // input 78 (0x4E char 'N') => 13 (0xD) - 14, // input 79 (0x4F char 'O') => 14 (0xE) - 15, // input 80 (0x50 char 'P') => 15 (0xF) - 16, // input 81 (0x51 char 'Q') => 16 (0x10) - 17, // input 82 (0x52 char 'R') => 17 (0x11) - 18, // input 83 (0x53 char 'S') => 18 (0x12) - 19, // input 84 (0x54 char 'T') => 19 (0x13) - 20, // input 85 (0x55 char 'U') => 20 (0x14) - 21, // input 86 (0x56 char 'V') => 21 (0x15) - 22, // input 87 (0x57 char 'W') => 22 (0x16) - 23, // input 88 (0x58 char 'X') => 23 (0x17) - 24, // input 89 (0x59 char 'Y') => 24 (0x18) - 25, // input 90 (0x5A char 'Z') => 25 (0x19) - INVALID_VALUE, // input 91 (0x5B) - INVALID_VALUE, // input 92 (0x5C) - INVALID_VALUE, // input 93 (0x5D) - INVALID_VALUE, // input 94 (0x5E) - 63, // input 95 (0x5F char '_') => 63 (0x3F) - INVALID_VALUE, // input 96 (0x60) - 26, // input 97 (0x61 char 'a') => 26 (0x1A) - 27, // input 98 (0x62 char 'b') => 27 (0x1B) - 28, // input 99 (0x63 char 'c') => 28 (0x1C) - 29, // input 100 (0x64 char 'd') => 29 (0x1D) - 30, // input 101 (0x65 char 'e') => 30 (0x1E) - 31, // input 102 (0x66 char 'f') => 31 (0x1F) - 32, // input 103 (0x67 char 'g') => 32 (0x20) - 33, // input 104 (0x68 char 'h') => 33 (0x21) - 34, // input 105 (0x69 char 'i') => 34 (0x22) - 35, // input 106 (0x6A char 'j') => 35 (0x23) - 36, // input 107 (0x6B char 'k') => 36 (0x24) - 37, // input 108 (0x6C char 'l') => 37 (0x25) - 38, // input 109 (0x6D char 'm') => 38 (0x26) - 39, // input 110 (0x6E char 'n') => 39 (0x27) - 40, // input 111 (0x6F char 'o') => 40 (0x28) - 41, // input 112 (0x70 char 'p') => 41 (0x29) - 42, // input 113 (0x71 char 'q') => 42 (0x2A) - 43, // input 114 (0x72 char 'r') => 43 (0x2B) - 44, // input 115 (0x73 char 's') => 44 (0x2C) - 45, // input 116 (0x74 char 't') => 45 (0x2D) - 46, // input 117 (0x75 char 'u') => 46 (0x2E) - 47, // input 118 (0x76 char 'v') => 47 (0x2F) - 48, // input 119 (0x77 char 'w') => 48 (0x30) - 49, // input 120 (0x78 char 'x') => 49 (0x31) - 50, // input 121 (0x79 char 'y') => 50 (0x32) - 51, // input 122 (0x7A char 'z') => 51 (0x33) - INVALID_VALUE, // input 123 (0x7B) - INVALID_VALUE, // input 124 (0x7C) - INVALID_VALUE, // input 125 (0x7D) - INVALID_VALUE, // input 126 (0x7E) - INVALID_VALUE, // input 127 (0x7F) - INVALID_VALUE, // input 128 (0x80) - INVALID_VALUE, // input 129 (0x81) - INVALID_VALUE, // input 130 (0x82) - INVALID_VALUE, // input 131 (0x83) - INVALID_VALUE, // input 132 (0x84) - INVALID_VALUE, // input 133 (0x85) - INVALID_VALUE, // input 134 (0x86) - INVALID_VALUE, // input 135 (0x87) - INVALID_VALUE, // input 136 (0x88) - INVALID_VALUE, // input 137 (0x89) - INVALID_VALUE, // input 138 (0x8A) - INVALID_VALUE, // input 139 (0x8B) - INVALID_VALUE, // input 140 (0x8C) - INVALID_VALUE, // input 141 (0x8D) - INVALID_VALUE, // input 142 (0x8E) - INVALID_VALUE, // input 143 (0x8F) - INVALID_VALUE, // input 144 (0x90) - INVALID_VALUE, // input 145 (0x91) - INVALID_VALUE, // input 146 (0x92) - INVALID_VALUE, // input 147 (0x93) - INVALID_VALUE, // input 148 (0x94) - INVALID_VALUE, // input 149 (0x95) - INVALID_VALUE, // input 150 (0x96) - INVALID_VALUE, // input 151 (0x97) - INVALID_VALUE, // input 152 (0x98) - INVALID_VALUE, // input 153 (0x99) - INVALID_VALUE, // input 154 (0x9A) - INVALID_VALUE, // input 155 (0x9B) - INVALID_VALUE, // input 156 (0x9C) - INVALID_VALUE, // input 157 (0x9D) - INVALID_VALUE, // input 158 (0x9E) - INVALID_VALUE, // input 159 (0x9F) - INVALID_VALUE, // input 160 (0xA0) - INVALID_VALUE, // input 161 (0xA1) - INVALID_VALUE, // input 162 (0xA2) - INVALID_VALUE, // input 163 (0xA3) - INVALID_VALUE, // input 164 (0xA4) - INVALID_VALUE, // input 165 (0xA5) - INVALID_VALUE, // input 166 (0xA6) - INVALID_VALUE, // input 167 (0xA7) - INVALID_VALUE, // input 168 (0xA8) - INVALID_VALUE, // input 169 (0xA9) - INVALID_VALUE, // input 170 (0xAA) - INVALID_VALUE, // input 171 (0xAB) - INVALID_VALUE, // input 172 (0xAC) - INVALID_VALUE, // input 173 (0xAD) - INVALID_VALUE, // input 174 (0xAE) - INVALID_VALUE, // input 175 (0xAF) - INVALID_VALUE, // input 176 (0xB0) - INVALID_VALUE, // input 177 (0xB1) - INVALID_VALUE, // input 178 (0xB2) - INVALID_VALUE, // input 179 (0xB3) - INVALID_VALUE, // input 180 (0xB4) - INVALID_VALUE, // input 181 (0xB5) - INVALID_VALUE, // input 182 (0xB6) - INVALID_VALUE, // input 183 (0xB7) - INVALID_VALUE, // input 184 (0xB8) - INVALID_VALUE, // input 185 (0xB9) - INVALID_VALUE, // input 186 (0xBA) - INVALID_VALUE, // input 187 (0xBB) - INVALID_VALUE, // input 188 (0xBC) - INVALID_VALUE, // input 189 (0xBD) - INVALID_VALUE, // input 190 (0xBE) - INVALID_VALUE, // input 191 (0xBF) - INVALID_VALUE, // input 192 (0xC0) - INVALID_VALUE, // input 193 (0xC1) - INVALID_VALUE, // input 194 (0xC2) - INVALID_VALUE, // input 195 (0xC3) - INVALID_VALUE, // input 196 (0xC4) - INVALID_VALUE, // input 197 (0xC5) - INVALID_VALUE, // input 198 (0xC6) - INVALID_VALUE, // input 199 (0xC7) - INVALID_VALUE, // input 200 (0xC8) - INVALID_VALUE, // input 201 (0xC9) - INVALID_VALUE, // input 202 (0xCA) - INVALID_VALUE, // input 203 (0xCB) - INVALID_VALUE, // input 204 (0xCC) - INVALID_VALUE, // input 205 (0xCD) - INVALID_VALUE, // input 206 (0xCE) - INVALID_VALUE, // input 207 (0xCF) - INVALID_VALUE, // input 208 (0xD0) - INVALID_VALUE, // input 209 (0xD1) - INVALID_VALUE, // input 210 (0xD2) - INVALID_VALUE, // input 211 (0xD3) - INVALID_VALUE, // input 212 (0xD4) - INVALID_VALUE, // input 213 (0xD5) - INVALID_VALUE, // input 214 (0xD6) - INVALID_VALUE, // input 215 (0xD7) - INVALID_VALUE, // input 216 (0xD8) - INVALID_VALUE, // input 217 (0xD9) - INVALID_VALUE, // input 218 (0xDA) - INVALID_VALUE, // input 219 (0xDB) - INVALID_VALUE, // input 220 (0xDC) - INVALID_VALUE, // input 221 (0xDD) - INVALID_VALUE, // input 222 (0xDE) - INVALID_VALUE, // input 223 (0xDF) - INVALID_VALUE, // input 224 (0xE0) - INVALID_VALUE, // input 225 (0xE1) - INVALID_VALUE, // input 226 (0xE2) - INVALID_VALUE, // input 227 (0xE3) - INVALID_VALUE, // input 228 (0xE4) - INVALID_VALUE, // input 229 (0xE5) - INVALID_VALUE, // input 230 (0xE6) - INVALID_VALUE, // input 231 (0xE7) - INVALID_VALUE, // input 232 (0xE8) - INVALID_VALUE, // input 233 (0xE9) - INVALID_VALUE, // input 234 (0xEA) - INVALID_VALUE, // input 235 (0xEB) - INVALID_VALUE, // input 236 (0xEC) - INVALID_VALUE, // input 237 (0xED) - INVALID_VALUE, // input 238 (0xEE) - INVALID_VALUE, // input 239 (0xEF) - INVALID_VALUE, // input 240 (0xF0) - INVALID_VALUE, // input 241 (0xF1) - INVALID_VALUE, // input 242 (0xF2) - INVALID_VALUE, // input 243 (0xF3) - INVALID_VALUE, // input 244 (0xF4) - INVALID_VALUE, // input 245 (0xF5) - INVALID_VALUE, // input 246 (0xF6) - INVALID_VALUE, // input 247 (0xF7) - INVALID_VALUE, // input 248 (0xF8) - INVALID_VALUE, // input 249 (0xF9) - INVALID_VALUE, // input 250 (0xFA) - INVALID_VALUE, // input 251 (0xFB) - INVALID_VALUE, // input 252 (0xFC) - INVALID_VALUE, // input 253 (0xFD) - INVALID_VALUE, // input 254 (0xFE) - INVALID_VALUE, // input 255 (0xFF) -]; -#[rustfmt::skip] -pub const CRYPT_ENCODE: &[u8; 64] = &[ - 46, // input 0 (0x0) => '.' (0x2E) - 47, // input 1 (0x1) => '/' (0x2F) - 48, // input 2 (0x2) => '0' (0x30) - 49, // input 3 (0x3) => '1' (0x31) - 50, // input 4 (0x4) => '2' (0x32) - 51, // input 5 (0x5) => '3' (0x33) - 52, // input 6 (0x6) => '4' (0x34) - 53, // input 7 (0x7) => '5' (0x35) - 54, // input 8 (0x8) => '6' (0x36) - 55, // input 9 (0x9) => '7' (0x37) - 56, // input 10 (0xA) => '8' (0x38) - 57, // input 11 (0xB) => '9' (0x39) - 65, // input 12 (0xC) => 'A' (0x41) - 66, // input 13 (0xD) => 'B' (0x42) - 67, // input 14 (0xE) => 'C' (0x43) - 68, // input 15 (0xF) => 'D' (0x44) - 69, // input 16 (0x10) => 'E' (0x45) - 70, // input 17 (0x11) => 'F' (0x46) - 71, // input 18 (0x12) => 'G' (0x47) - 72, // input 19 (0x13) => 'H' (0x48) - 73, // input 20 (0x14) => 'I' (0x49) - 74, // input 21 (0x15) => 'J' (0x4A) - 75, // input 22 (0x16) => 'K' (0x4B) - 76, // input 23 (0x17) => 'L' (0x4C) - 77, // input 24 (0x18) => 'M' (0x4D) - 78, // input 25 (0x19) => 'N' (0x4E) - 79, // input 26 (0x1A) => 'O' (0x4F) - 80, // input 27 (0x1B) => 'P' (0x50) - 81, // input 28 (0x1C) => 'Q' (0x51) - 82, // input 29 (0x1D) => 'R' (0x52) - 83, // input 30 (0x1E) => 'S' (0x53) - 84, // input 31 (0x1F) => 'T' (0x54) - 85, // input 32 (0x20) => 'U' (0x55) - 86, // input 33 (0x21) => 'V' (0x56) - 87, // input 34 (0x22) => 'W' (0x57) - 88, // input 35 (0x23) => 'X' (0x58) - 89, // input 36 (0x24) => 'Y' (0x59) - 90, // input 37 (0x25) => 'Z' (0x5A) - 97, // input 38 (0x26) => 'a' (0x61) - 98, // input 39 (0x27) => 'b' (0x62) - 99, // input 40 (0x28) => 'c' (0x63) - 100, // input 41 (0x29) => 'd' (0x64) - 101, // input 42 (0x2A) => 'e' (0x65) - 102, // input 43 (0x2B) => 'f' (0x66) - 103, // input 44 (0x2C) => 'g' (0x67) - 104, // input 45 (0x2D) => 'h' (0x68) - 105, // input 46 (0x2E) => 'i' (0x69) - 106, // input 47 (0x2F) => 'j' (0x6A) - 107, // input 48 (0x30) => 'k' (0x6B) - 108, // input 49 (0x31) => 'l' (0x6C) - 109, // input 50 (0x32) => 'm' (0x6D) - 110, // input 51 (0x33) => 'n' (0x6E) - 111, // input 52 (0x34) => 'o' (0x6F) - 112, // input 53 (0x35) => 'p' (0x70) - 113, // input 54 (0x36) => 'q' (0x71) - 114, // input 55 (0x37) => 'r' (0x72) - 115, // input 56 (0x38) => 's' (0x73) - 116, // input 57 (0x39) => 't' (0x74) - 117, // input 58 (0x3A) => 'u' (0x75) - 118, // input 59 (0x3B) => 'v' (0x76) - 119, // input 60 (0x3C) => 'w' (0x77) - 120, // input 61 (0x3D) => 'x' (0x78) - 121, // input 62 (0x3E) => 'y' (0x79) - 122, // input 63 (0x3F) => 'z' (0x7A) -]; -#[rustfmt::skip] -pub const CRYPT_DECODE: &[u8; 256] = &[ - INVALID_VALUE, // input 0 (0x0) - INVALID_VALUE, // input 1 (0x1) - INVALID_VALUE, // input 2 (0x2) - INVALID_VALUE, // input 3 (0x3) - INVALID_VALUE, // input 4 (0x4) - INVALID_VALUE, // input 5 (0x5) - INVALID_VALUE, // input 6 (0x6) - INVALID_VALUE, // input 7 (0x7) - INVALID_VALUE, // input 8 (0x8) - INVALID_VALUE, // input 9 (0x9) - INVALID_VALUE, // input 10 (0xA) - INVALID_VALUE, // input 11 (0xB) - INVALID_VALUE, // input 12 (0xC) - INVALID_VALUE, // input 13 (0xD) - INVALID_VALUE, // input 14 (0xE) - INVALID_VALUE, // input 15 (0xF) - INVALID_VALUE, // input 16 (0x10) - INVALID_VALUE, // input 17 (0x11) - INVALID_VALUE, // input 18 (0x12) - INVALID_VALUE, // input 19 (0x13) - INVALID_VALUE, // input 20 (0x14) - INVALID_VALUE, // input 21 (0x15) - INVALID_VALUE, // input 22 (0x16) - INVALID_VALUE, // input 23 (0x17) - INVALID_VALUE, // input 24 (0x18) - INVALID_VALUE, // input 25 (0x19) - INVALID_VALUE, // input 26 (0x1A) - INVALID_VALUE, // input 27 (0x1B) - INVALID_VALUE, // input 28 (0x1C) - INVALID_VALUE, // input 29 (0x1D) - INVALID_VALUE, // input 30 (0x1E) - INVALID_VALUE, // input 31 (0x1F) - INVALID_VALUE, // input 32 (0x20) - INVALID_VALUE, // input 33 (0x21) - INVALID_VALUE, // input 34 (0x22) - INVALID_VALUE, // input 35 (0x23) - INVALID_VALUE, // input 36 (0x24) - INVALID_VALUE, // input 37 (0x25) - INVALID_VALUE, // input 38 (0x26) - INVALID_VALUE, // input 39 (0x27) - INVALID_VALUE, // input 40 (0x28) - INVALID_VALUE, // input 41 (0x29) - INVALID_VALUE, // input 42 (0x2A) - INVALID_VALUE, // input 43 (0x2B) - INVALID_VALUE, // input 44 (0x2C) - INVALID_VALUE, // input 45 (0x2D) - 0, // input 46 (0x2E char '.') => 0 (0x0) - 1, // input 47 (0x2F char '/') => 1 (0x1) - 2, // input 48 (0x30 char '0') => 2 (0x2) - 3, // input 49 (0x31 char '1') => 3 (0x3) - 4, // input 50 (0x32 char '2') => 4 (0x4) - 5, // input 51 (0x33 char '3') => 5 (0x5) - 6, // input 52 (0x34 char '4') => 6 (0x6) - 7, // input 53 (0x35 char '5') => 7 (0x7) - 8, // input 54 (0x36 char '6') => 8 (0x8) - 9, // input 55 (0x37 char '7') => 9 (0x9) - 10, // input 56 (0x38 char '8') => 10 (0xA) - 11, // input 57 (0x39 char '9') => 11 (0xB) - INVALID_VALUE, // input 58 (0x3A) - INVALID_VALUE, // input 59 (0x3B) - INVALID_VALUE, // input 60 (0x3C) - INVALID_VALUE, // input 61 (0x3D) - INVALID_VALUE, // input 62 (0x3E) - INVALID_VALUE, // input 63 (0x3F) - INVALID_VALUE, // input 64 (0x40) - 12, // input 65 (0x41 char 'A') => 12 (0xC) - 13, // input 66 (0x42 char 'B') => 13 (0xD) - 14, // input 67 (0x43 char 'C') => 14 (0xE) - 15, // input 68 (0x44 char 'D') => 15 (0xF) - 16, // input 69 (0x45 char 'E') => 16 (0x10) - 17, // input 70 (0x46 char 'F') => 17 (0x11) - 18, // input 71 (0x47 char 'G') => 18 (0x12) - 19, // input 72 (0x48 char 'H') => 19 (0x13) - 20, // input 73 (0x49 char 'I') => 20 (0x14) - 21, // input 74 (0x4A char 'J') => 21 (0x15) - 22, // input 75 (0x4B char 'K') => 22 (0x16) - 23, // input 76 (0x4C char 'L') => 23 (0x17) - 24, // input 77 (0x4D char 'M') => 24 (0x18) - 25, // input 78 (0x4E char 'N') => 25 (0x19) - 26, // input 79 (0x4F char 'O') => 26 (0x1A) - 27, // input 80 (0x50 char 'P') => 27 (0x1B) - 28, // input 81 (0x51 char 'Q') => 28 (0x1C) - 29, // input 82 (0x52 char 'R') => 29 (0x1D) - 30, // input 83 (0x53 char 'S') => 30 (0x1E) - 31, // input 84 (0x54 char 'T') => 31 (0x1F) - 32, // input 85 (0x55 char 'U') => 32 (0x20) - 33, // input 86 (0x56 char 'V') => 33 (0x21) - 34, // input 87 (0x57 char 'W') => 34 (0x22) - 35, // input 88 (0x58 char 'X') => 35 (0x23) - 36, // input 89 (0x59 char 'Y') => 36 (0x24) - 37, // input 90 (0x5A char 'Z') => 37 (0x25) - INVALID_VALUE, // input 91 (0x5B) - INVALID_VALUE, // input 92 (0x5C) - INVALID_VALUE, // input 93 (0x5D) - INVALID_VALUE, // input 94 (0x5E) - INVALID_VALUE, // input 95 (0x5F) - INVALID_VALUE, // input 96 (0x60) - 38, // input 97 (0x61 char 'a') => 38 (0x26) - 39, // input 98 (0x62 char 'b') => 39 (0x27) - 40, // input 99 (0x63 char 'c') => 40 (0x28) - 41, // input 100 (0x64 char 'd') => 41 (0x29) - 42, // input 101 (0x65 char 'e') => 42 (0x2A) - 43, // input 102 (0x66 char 'f') => 43 (0x2B) - 44, // input 103 (0x67 char 'g') => 44 (0x2C) - 45, // input 104 (0x68 char 'h') => 45 (0x2D) - 46, // input 105 (0x69 char 'i') => 46 (0x2E) - 47, // input 106 (0x6A char 'j') => 47 (0x2F) - 48, // input 107 (0x6B char 'k') => 48 (0x30) - 49, // input 108 (0x6C char 'l') => 49 (0x31) - 50, // input 109 (0x6D char 'm') => 50 (0x32) - 51, // input 110 (0x6E char 'n') => 51 (0x33) - 52, // input 111 (0x6F char 'o') => 52 (0x34) - 53, // input 112 (0x70 char 'p') => 53 (0x35) - 54, // input 113 (0x71 char 'q') => 54 (0x36) - 55, // input 114 (0x72 char 'r') => 55 (0x37) - 56, // input 115 (0x73 char 's') => 56 (0x38) - 57, // input 116 (0x74 char 't') => 57 (0x39) - 58, // input 117 (0x75 char 'u') => 58 (0x3A) - 59, // input 118 (0x76 char 'v') => 59 (0x3B) - 60, // input 119 (0x77 char 'w') => 60 (0x3C) - 61, // input 120 (0x78 char 'x') => 61 (0x3D) - 62, // input 121 (0x79 char 'y') => 62 (0x3E) - 63, // input 122 (0x7A char 'z') => 63 (0x3F) - INVALID_VALUE, // input 123 (0x7B) - INVALID_VALUE, // input 124 (0x7C) - INVALID_VALUE, // input 125 (0x7D) - INVALID_VALUE, // input 126 (0x7E) - INVALID_VALUE, // input 127 (0x7F) - INVALID_VALUE, // input 128 (0x80) - INVALID_VALUE, // input 129 (0x81) - INVALID_VALUE, // input 130 (0x82) - INVALID_VALUE, // input 131 (0x83) - INVALID_VALUE, // input 132 (0x84) - INVALID_VALUE, // input 133 (0x85) - INVALID_VALUE, // input 134 (0x86) - INVALID_VALUE, // input 135 (0x87) - INVALID_VALUE, // input 136 (0x88) - INVALID_VALUE, // input 137 (0x89) - INVALID_VALUE, // input 138 (0x8A) - INVALID_VALUE, // input 139 (0x8B) - INVALID_VALUE, // input 140 (0x8C) - INVALID_VALUE, // input 141 (0x8D) - INVALID_VALUE, // input 142 (0x8E) - INVALID_VALUE, // input 143 (0x8F) - INVALID_VALUE, // input 144 (0x90) - INVALID_VALUE, // input 145 (0x91) - INVALID_VALUE, // input 146 (0x92) - INVALID_VALUE, // input 147 (0x93) - INVALID_VALUE, // input 148 (0x94) - INVALID_VALUE, // input 149 (0x95) - INVALID_VALUE, // input 150 (0x96) - INVALID_VALUE, // input 151 (0x97) - INVALID_VALUE, // input 152 (0x98) - INVALID_VALUE, // input 153 (0x99) - INVALID_VALUE, // input 154 (0x9A) - INVALID_VALUE, // input 155 (0x9B) - INVALID_VALUE, // input 156 (0x9C) - INVALID_VALUE, // input 157 (0x9D) - INVALID_VALUE, // input 158 (0x9E) - INVALID_VALUE, // input 159 (0x9F) - INVALID_VALUE, // input 160 (0xA0) - INVALID_VALUE, // input 161 (0xA1) - INVALID_VALUE, // input 162 (0xA2) - INVALID_VALUE, // input 163 (0xA3) - INVALID_VALUE, // input 164 (0xA4) - INVALID_VALUE, // input 165 (0xA5) - INVALID_VALUE, // input 166 (0xA6) - INVALID_VALUE, // input 167 (0xA7) - INVALID_VALUE, // input 168 (0xA8) - INVALID_VALUE, // input 169 (0xA9) - INVALID_VALUE, // input 170 (0xAA) - INVALID_VALUE, // input 171 (0xAB) - INVALID_VALUE, // input 172 (0xAC) - INVALID_VALUE, // input 173 (0xAD) - INVALID_VALUE, // input 174 (0xAE) - INVALID_VALUE, // input 175 (0xAF) - INVALID_VALUE, // input 176 (0xB0) - INVALID_VALUE, // input 177 (0xB1) - INVALID_VALUE, // input 178 (0xB2) - INVALID_VALUE, // input 179 (0xB3) - INVALID_VALUE, // input 180 (0xB4) - INVALID_VALUE, // input 181 (0xB5) - INVALID_VALUE, // input 182 (0xB6) - INVALID_VALUE, // input 183 (0xB7) - INVALID_VALUE, // input 184 (0xB8) - INVALID_VALUE, // input 185 (0xB9) - INVALID_VALUE, // input 186 (0xBA) - INVALID_VALUE, // input 187 (0xBB) - INVALID_VALUE, // input 188 (0xBC) - INVALID_VALUE, // input 189 (0xBD) - INVALID_VALUE, // input 190 (0xBE) - INVALID_VALUE, // input 191 (0xBF) - INVALID_VALUE, // input 192 (0xC0) - INVALID_VALUE, // input 193 (0xC1) - INVALID_VALUE, // input 194 (0xC2) - INVALID_VALUE, // input 195 (0xC3) - INVALID_VALUE, // input 196 (0xC4) - INVALID_VALUE, // input 197 (0xC5) - INVALID_VALUE, // input 198 (0xC6) - INVALID_VALUE, // input 199 (0xC7) - INVALID_VALUE, // input 200 (0xC8) - INVALID_VALUE, // input 201 (0xC9) - INVALID_VALUE, // input 202 (0xCA) - INVALID_VALUE, // input 203 (0xCB) - INVALID_VALUE, // input 204 (0xCC) - INVALID_VALUE, // input 205 (0xCD) - INVALID_VALUE, // input 206 (0xCE) - INVALID_VALUE, // input 207 (0xCF) - INVALID_VALUE, // input 208 (0xD0) - INVALID_VALUE, // input 209 (0xD1) - INVALID_VALUE, // input 210 (0xD2) - INVALID_VALUE, // input 211 (0xD3) - INVALID_VALUE, // input 212 (0xD4) - INVALID_VALUE, // input 213 (0xD5) - INVALID_VALUE, // input 214 (0xD6) - INVALID_VALUE, // input 215 (0xD7) - INVALID_VALUE, // input 216 (0xD8) - INVALID_VALUE, // input 217 (0xD9) - INVALID_VALUE, // input 218 (0xDA) - INVALID_VALUE, // input 219 (0xDB) - INVALID_VALUE, // input 220 (0xDC) - INVALID_VALUE, // input 221 (0xDD) - INVALID_VALUE, // input 222 (0xDE) - INVALID_VALUE, // input 223 (0xDF) - INVALID_VALUE, // input 224 (0xE0) - INVALID_VALUE, // input 225 (0xE1) - INVALID_VALUE, // input 226 (0xE2) - INVALID_VALUE, // input 227 (0xE3) - INVALID_VALUE, // input 228 (0xE4) - INVALID_VALUE, // input 229 (0xE5) - INVALID_VALUE, // input 230 (0xE6) - INVALID_VALUE, // input 231 (0xE7) - INVALID_VALUE, // input 232 (0xE8) - INVALID_VALUE, // input 233 (0xE9) - INVALID_VALUE, // input 234 (0xEA) - INVALID_VALUE, // input 235 (0xEB) - INVALID_VALUE, // input 236 (0xEC) - INVALID_VALUE, // input 237 (0xED) - INVALID_VALUE, // input 238 (0xEE) - INVALID_VALUE, // input 239 (0xEF) - INVALID_VALUE, // input 240 (0xF0) - INVALID_VALUE, // input 241 (0xF1) - INVALID_VALUE, // input 242 (0xF2) - INVALID_VALUE, // input 243 (0xF3) - INVALID_VALUE, // input 244 (0xF4) - INVALID_VALUE, // input 245 (0xF5) - INVALID_VALUE, // input 246 (0xF6) - INVALID_VALUE, // input 247 (0xF7) - INVALID_VALUE, // input 248 (0xF8) - INVALID_VALUE, // input 249 (0xF9) - INVALID_VALUE, // input 250 (0xFA) - INVALID_VALUE, // input 251 (0xFB) - INVALID_VALUE, // input 252 (0xFC) - INVALID_VALUE, // input 253 (0xFD) - INVALID_VALUE, // input 254 (0xFE) - INVALID_VALUE, // input 255 (0xFF) -]; diff --git a/vendor/base64/src/tests.rs b/vendor/base64/src/tests.rs deleted file mode 100644 index d0ed7daf45..0000000000 --- a/vendor/base64/src/tests.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::{decode_config, encode::encoded_size, encode_config_buf, CharacterSet, Config}; - -use std::str; - -use rand::{ - distributions::{Distribution, Uniform}, - seq::SliceRandom, - FromEntropy, Rng, -}; - -#[test] -fn roundtrip_random_config_short() { - // exercise the slower encode/decode routines that operate on shorter buffers more vigorously - roundtrip_random_config(Uniform::new(0, 50), 10_000); -} - -#[test] -fn roundtrip_random_config_long() { - roundtrip_random_config(Uniform::new(0, 1000), 10_000); -} - -pub fn assert_encode_sanity(encoded: &str, config: Config, input_len: usize) { - let input_rem = input_len % 3; - let expected_padding_len = if input_rem > 0 { - if config.pad { - 3 - input_rem - } else { - 0 - } - } else { - 0 - }; - - let expected_encoded_len = encoded_size(input_len, config).unwrap(); - - assert_eq!(expected_encoded_len, encoded.len()); - - let padding_len = encoded.chars().filter(|&c| c == '=').count(); - - assert_eq!(expected_padding_len, padding_len); - - let _ = str::from_utf8(encoded.as_bytes()).expect("Base64 should be valid utf8"); -} - -fn roundtrip_random_config(input_len_range: Uniform, iterations: u32) { - let mut input_buf: Vec = Vec::new(); - let mut encoded_buf = String::new(); - let mut rng = rand::rngs::SmallRng::from_entropy(); - - for _ in 0..iterations { - input_buf.clear(); - encoded_buf.clear(); - - let input_len = input_len_range.sample(&mut rng); - - let config = random_config(&mut rng); - - for _ in 0..input_len { - input_buf.push(rng.gen()); - } - - encode_config_buf(&input_buf, config, &mut encoded_buf); - - assert_encode_sanity(&encoded_buf, config, input_len); - - assert_eq!(input_buf, decode_config(&encoded_buf, config).unwrap()); - } -} - -pub fn random_config(rng: &mut R) -> Config { - const CHARSETS: &[CharacterSet] = &[ - CharacterSet::UrlSafe, - CharacterSet::Standard, - CharacterSet::Crypt, - ]; - let charset = *CHARSETS.choose(rng).unwrap(); - - Config::new(charset, rng.gen()) -} diff --git a/vendor/base64/src/write/encoder.rs b/vendor/base64/src/write/encoder.rs deleted file mode 100644 index bece69b36b..0000000000 --- a/vendor/base64/src/write/encoder.rs +++ /dev/null @@ -1,355 +0,0 @@ -use crate::encode::encode_to_slice; -use crate::{encode_config_slice, Config}; -use std::{ - cmp, fmt, - io::{ErrorKind, Result, Write}, -}; - -pub(crate) const BUF_SIZE: usize = 1024; -/// The most bytes whose encoding will fit in `BUF_SIZE` -const MAX_INPUT_LEN: usize = BUF_SIZE / 4 * 3; -// 3 bytes of input = 4 bytes of base64, always (because we don't allow line wrapping) -const MIN_ENCODE_CHUNK_SIZE: usize = 3; - -/// A `Write` implementation that base64 encodes data before delegating to the wrapped writer. -/// -/// Because base64 has special handling for the end of the input data (padding, etc), there's a -/// `finish()` method on this type that encodes any leftover input bytes and adds padding if -/// appropriate. It's called automatically when deallocated (see the `Drop` implementation), but -/// any error that occurs when invoking the underlying writer will be suppressed. If you want to -/// handle such errors, call `finish()` yourself. -/// -/// # Examples -/// -/// ``` -/// use std::io::Write; -/// -/// // use a vec as the simplest possible `Write` -- in real code this is probably a file, etc. -/// let mut wrapped_writer = Vec::new(); -/// { -/// let mut enc = base64::write::EncoderWriter::new( -/// &mut wrapped_writer, base64::STANDARD); -/// -/// // handle errors as you normally would -/// enc.write_all(b"asdf").unwrap(); -/// // could leave this out to be called by Drop, if you don't care -/// // about handling errors -/// enc.finish().unwrap(); -/// -/// } -/// -/// // base64 was written to the writer -/// assert_eq!(b"YXNkZg==", &wrapped_writer[..]); -/// -/// ``` -/// -/// # Panics -/// -/// Calling `write()` after `finish()` is invalid and will panic. -/// -/// # Errors -/// -/// Base64 encoding itself does not generate errors, but errors from the wrapped writer will be -/// returned as per the contract of `Write`. -/// -/// # Performance -/// -/// It has some minor performance loss compared to encoding slices (a couple percent). -/// It does not do any heap allocation. -pub struct EncoderWriter<'a, W: 'a + Write> { - config: Config, - /// Where encoded data is written to - w: &'a mut W, - /// Holds a partial chunk, if any, after the last `write()`, so that we may then fill the chunk - /// with the next `write()`, encode it, then proceed with the rest of the input normally. - extra_input: [u8; MIN_ENCODE_CHUNK_SIZE], - /// How much of `extra` is occupied, in `[0, MIN_ENCODE_CHUNK_SIZE]`. - extra_input_occupied_len: usize, - /// Buffer to encode into. May hold leftover encoded bytes from a previous write call that the underlying writer - /// did not write last time. - output: [u8; BUF_SIZE], - /// How much of `output` is occupied with encoded data that couldn't be written last time - output_occupied_len: usize, - /// True iff padding / partial last chunk has been written. - finished: bool, - /// panic safety: don't write again in destructor if writer panicked while we were writing to it - panicked: bool, -} - -impl<'a, W: Write> fmt::Debug for EncoderWriter<'a, W> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "extra_input: {:?} extra_input_occupied_len:{:?} output[..5]: {:?} output_occupied_len: {:?}", - self.extra_input, - self.extra_input_occupied_len, - &self.output[0..5], - self.output_occupied_len - ) - } -} - -impl<'a, W: Write> EncoderWriter<'a, W> { - /// Create a new encoder that will write to the provided delegate writer `w`. - pub fn new(w: &'a mut W, config: Config) -> EncoderWriter<'a, W> { - EncoderWriter { - config, - w, - extra_input: [0u8; MIN_ENCODE_CHUNK_SIZE], - extra_input_occupied_len: 0, - output: [0u8; BUF_SIZE], - output_occupied_len: 0, - finished: false, - panicked: false, - } - } - - /// Encode all remaining buffered data and write it, including any trailing incomplete input - /// triples and associated padding. - /// - /// Once this succeeds, no further writes can be performed, as that would produce invalid - /// base64. - /// - /// This may write to the delegate writer multiple times if the delegate writer does not accept all input provided - /// to its `write` each invocation. - /// - /// # Errors - /// - /// The first error that is not of [`ErrorKind::Interrupted`] will be returned. - pub fn finish(&mut self) -> Result<()> { - if self.finished { - return Ok(()); - }; - - self.write_all_encoded_output()?; - - if self.extra_input_occupied_len > 0 { - let encoded_len = encode_config_slice( - &self.extra_input[..self.extra_input_occupied_len], - self.config, - &mut self.output[..], - ); - - self.output_occupied_len = encoded_len; - - self.write_all_encoded_output()?; - - // write succeeded, do not write the encoding of extra again if finish() is retried - self.extra_input_occupied_len = 0; - } - - self.finished = true; - Ok(()) - } - - /// Write as much of the encoded output to the delegate writer as it will accept, and store the - /// leftovers to be attempted at the next write() call. Updates `self.output_occupied_len`. - /// - /// # Errors - /// - /// Errors from the delegate writer are returned. In the case of an error, - /// `self.output_occupied_len` will not be updated, as errors from `write` are specified to mean - /// that no write took place. - fn write_to_delegate(&mut self, current_output_len: usize) -> Result<()> { - self.panicked = true; - let res = self.w.write(&self.output[..current_output_len]); - self.panicked = false; - - res.map(|consumed| { - debug_assert!(consumed <= current_output_len); - - if consumed < current_output_len { - self.output_occupied_len = current_output_len.checked_sub(consumed).unwrap(); - // If we're blocking on I/O, the minor inefficiency of copying bytes to the - // start of the buffer is the least of our concerns... - // Rotate moves more than we need to, but copy_within isn't stabilized yet. - self.output.rotate_left(consumed); - } else { - self.output_occupied_len = 0; - } - }) - } - - /// Write all buffered encoded output. If this returns `Ok`, `self.output_occupied_len` is `0`. - /// - /// This is basically write_all for the remaining buffered data but without the undesirable - /// abort-on-`Ok(0)` behavior. - /// - /// # Errors - /// - /// Any error emitted by the delegate writer abort the write loop and is returned, unless it's - /// `Interrupted`, in which case the error is ignored and writes will continue. - fn write_all_encoded_output(&mut self) -> Result<()> { - while self.output_occupied_len > 0 { - let remaining_len = self.output_occupied_len; - match self.write_to_delegate(remaining_len) { - // try again on interrupts ala write_all - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} - // other errors return - Err(e) => return Err(e), - // success no-ops because remaining length is already updated - Ok(_) => {} - }; - } - - debug_assert_eq!(0, self.output_occupied_len); - Ok(()) - } -} - -impl<'a, W: Write> Write for EncoderWriter<'a, W> { - /// Encode input and then write to the delegate writer. - /// - /// Under non-error circumstances, this returns `Ok` with the value being the number of bytes - /// of `input` consumed. The value may be `0`, which interacts poorly with `write_all`, which - /// interprets `Ok(0)` as an error, despite it being allowed by the contract of `write`. See - /// https://github.com/rust-lang/rust/issues/56889 for more on that. - /// - /// If the previous call to `write` provided more (encoded) data than the delegate writer could - /// accept in a single call to its `write`, the remaining data is buffered. As long as buffered - /// data is present, subsequent calls to `write` will try to write the remaining buffered data - /// to the delegate and return either `Ok(0)` -- and therefore not consume any of `input` -- or - /// an error. - /// - /// # Errors - /// - /// Any errors emitted by the delegate writer are returned. - fn write(&mut self, input: &[u8]) -> Result { - if self.finished { - panic!("Cannot write more after calling finish()"); - } - - if input.is_empty() { - return Ok(0); - } - - // The contract of `Write::write` places some constraints on this implementation: - // - a call to `write()` represents at most one call to a wrapped `Write`, so we can't - // iterate over the input and encode multiple chunks. - // - Errors mean that "no bytes were written to this writer", so we need to reset the - // internal state to what it was before the error occurred - - // before reading any input, write any leftover encoded output from last time - if self.output_occupied_len > 0 { - let current_len = self.output_occupied_len; - return self - .write_to_delegate(current_len) - // did not read any input - .map(|_| 0); - } - - debug_assert_eq!(0, self.output_occupied_len); - - // how many bytes, if any, were read into `extra` to create a triple to encode - let mut extra_input_read_len = 0; - let mut input = input; - - let orig_extra_len = self.extra_input_occupied_len; - - let mut encoded_size = 0; - // always a multiple of MIN_ENCODE_CHUNK_SIZE - let mut max_input_len = MAX_INPUT_LEN; - - // process leftover un-encoded input from last write - if self.extra_input_occupied_len > 0 { - debug_assert!(self.extra_input_occupied_len < 3); - if input.len() + self.extra_input_occupied_len >= MIN_ENCODE_CHUNK_SIZE { - // Fill up `extra`, encode that into `output`, and consume as much of the rest of - // `input` as possible. - // We could write just the encoding of `extra` by itself but then we'd have to - // return after writing only 4 bytes, which is inefficient if the underlying writer - // would make a syscall. - extra_input_read_len = MIN_ENCODE_CHUNK_SIZE - self.extra_input_occupied_len; - debug_assert!(extra_input_read_len > 0); - // overwrite only bytes that weren't already used. If we need to rollback extra_len - // (when the subsequent write errors), the old leading bytes will still be there. - self.extra_input[self.extra_input_occupied_len..MIN_ENCODE_CHUNK_SIZE] - .copy_from_slice(&input[0..extra_input_read_len]); - - let len = encode_to_slice( - &self.extra_input[0..MIN_ENCODE_CHUNK_SIZE], - &mut self.output[..], - self.config.char_set.encode_table(), - ); - debug_assert_eq!(4, len); - - input = &input[extra_input_read_len..]; - - // consider extra to be used up, since we encoded it - self.extra_input_occupied_len = 0; - // don't clobber where we just encoded to - encoded_size = 4; - // and don't read more than can be encoded - max_input_len = MAX_INPUT_LEN - MIN_ENCODE_CHUNK_SIZE; - - // fall through to normal encoding - } else { - // `extra` and `input` are non empty, but `|extra| + |input| < 3`, so there must be - // 1 byte in each. - debug_assert_eq!(1, input.len()); - debug_assert_eq!(1, self.extra_input_occupied_len); - - self.extra_input[self.extra_input_occupied_len] = input[0]; - self.extra_input_occupied_len += 1; - return Ok(1); - }; - } else if input.len() < MIN_ENCODE_CHUNK_SIZE { - // `extra` is empty, and `input` fits inside it - self.extra_input[0..input.len()].copy_from_slice(input); - self.extra_input_occupied_len = input.len(); - return Ok(input.len()); - }; - - // either 0 or 1 complete chunks encoded from extra - debug_assert!(encoded_size == 0 || encoded_size == 4); - debug_assert!( - // didn't encode extra input - MAX_INPUT_LEN == max_input_len - // encoded one triple - || MAX_INPUT_LEN == max_input_len + MIN_ENCODE_CHUNK_SIZE - ); - - // encode complete triples only - let input_complete_chunks_len = input.len() - (input.len() % MIN_ENCODE_CHUNK_SIZE); - let input_chunks_to_encode_len = cmp::min(input_complete_chunks_len, max_input_len); - debug_assert_eq!(0, max_input_len % MIN_ENCODE_CHUNK_SIZE); - debug_assert_eq!(0, input_chunks_to_encode_len % MIN_ENCODE_CHUNK_SIZE); - - encoded_size += encode_to_slice( - &input[..(input_chunks_to_encode_len)], - &mut self.output[encoded_size..], - self.config.char_set.encode_table(), - ); - - // not updating `self.output_occupied_len` here because if the below write fails, it should - // "never take place" -- the buffer contents we encoded are ignored and perhaps retried - // later, if the consumer chooses. - - self.write_to_delegate(encoded_size) - // no matter whether we wrote the full encoded buffer or not, we consumed the same - // input - .map(|_| extra_input_read_len + input_chunks_to_encode_len) - .map_err(|e| { - // in case we filled and encoded `extra`, reset extra_len - self.extra_input_occupied_len = orig_extra_len; - - e - }) - } - - /// Because this is usually treated as OK to call multiple times, it will *not* flush any - /// incomplete chunks of input or write padding. - fn flush(&mut self) -> Result<()> { - self.write_all_encoded_output()?; - self.w.flush() - } -} - -impl<'a, W: Write> Drop for EncoderWriter<'a, W> { - fn drop(&mut self) { - if !self.panicked { - // like `BufWriter`, ignore errors during drop - let _ = self.finish(); - } - } -} diff --git a/vendor/base64/src/write/encoder_tests.rs b/vendor/base64/src/write/encoder_tests.rs deleted file mode 100644 index 59a6127a9d..0000000000 --- a/vendor/base64/src/write/encoder_tests.rs +++ /dev/null @@ -1,568 +0,0 @@ -use super::EncoderWriter; -use crate::tests::random_config; -use crate::{encode_config, encode_config_buf, STANDARD_NO_PAD, URL_SAFE}; - -use std::io::{Cursor, Write}; -use std::{cmp, io, str}; - -use rand::Rng; - -#[test] -fn encode_three_bytes() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - let sz = enc.write(b"abc").unwrap(); - assert_eq!(sz, 3); - } - assert_eq!(&c.get_ref()[..], encode_config("abc", URL_SAFE).as_bytes()); -} - -#[test] -fn encode_nine_bytes_two_writes() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - let sz = enc.write(b"abcdef").unwrap(); - assert_eq!(sz, 6); - let sz = enc.write(b"ghi").unwrap(); - assert_eq!(sz, 3); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abcdefghi", URL_SAFE).as_bytes() - ); -} - -#[test] -fn encode_one_then_two_bytes() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - let sz = enc.write(b"a").unwrap(); - assert_eq!(sz, 1); - let sz = enc.write(b"bc").unwrap(); - assert_eq!(sz, 2); - } - assert_eq!(&c.get_ref()[..], encode_config("abc", URL_SAFE).as_bytes()); -} - -#[test] -fn encode_one_then_five_bytes() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - let sz = enc.write(b"a").unwrap(); - assert_eq!(sz, 1); - let sz = enc.write(b"bcdef").unwrap(); - assert_eq!(sz, 5); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abcdef", URL_SAFE).as_bytes() - ); -} - -#[test] -fn encode_1_2_3_bytes() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - let sz = enc.write(b"a").unwrap(); - assert_eq!(sz, 1); - let sz = enc.write(b"bc").unwrap(); - assert_eq!(sz, 2); - let sz = enc.write(b"def").unwrap(); - assert_eq!(sz, 3); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abcdef", URL_SAFE).as_bytes() - ); -} - -#[test] -fn encode_with_padding() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - enc.write_all(b"abcd").unwrap(); - - enc.flush().unwrap(); - } - assert_eq!(&c.get_ref()[..], encode_config("abcd", URL_SAFE).as_bytes()); -} - -#[test] -fn encode_with_padding_multiple_writes() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - assert_eq!(1, enc.write(b"a").unwrap()); - assert_eq!(2, enc.write(b"bc").unwrap()); - assert_eq!(3, enc.write(b"def").unwrap()); - assert_eq!(1, enc.write(b"g").unwrap()); - - enc.flush().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abcdefg", URL_SAFE).as_bytes() - ); -} - -#[test] -fn finish_writes_extra_byte() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, URL_SAFE); - - assert_eq!(6, enc.write(b"abcdef").unwrap()); - - // will be in extra - assert_eq!(1, enc.write(b"g").unwrap()); - - // 1 trailing byte = 2 encoded chars - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abcdefg", URL_SAFE).as_bytes() - ); -} - -#[test] -fn write_partial_chunk_encodes_partial_chunk() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - - // nothing encoded yet - assert_eq!(2, enc.write(b"ab").unwrap()); - // encoded here - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("ab", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(3, c.get_ref().len()); -} - -#[test] -fn write_1_chunk_encodes_complete_chunk() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - - assert_eq!(3, enc.write(b"abc").unwrap()); - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abc", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(4, c.get_ref().len()); -} - -#[test] -fn write_1_chunk_and_partial_encodes_only_complete_chunk() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - - // "d" not written - assert_eq!(3, enc.write(b"abcd").unwrap()); - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abc", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(4, c.get_ref().len()); -} - -#[test] -fn write_2_partials_to_exactly_complete_chunk_encodes_complete_chunk() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - - assert_eq!(1, enc.write(b"a").unwrap()); - assert_eq!(2, enc.write(b"bc").unwrap()); - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abc", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(4, c.get_ref().len()); -} - -#[test] -fn write_partial_then_enough_to_complete_chunk_but_not_complete_another_chunk_encodes_complete_chunk_without_consuming_remaining( -) { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - - assert_eq!(1, enc.write(b"a").unwrap()); - // doesn't consume "d" - assert_eq!(2, enc.write(b"bcd").unwrap()); - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abc", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(4, c.get_ref().len()); -} - -#[test] -fn write_partial_then_enough_to_complete_chunk_and_another_chunk_encodes_complete_chunks() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - - assert_eq!(1, enc.write(b"a").unwrap()); - // completes partial chunk, and another chunk - assert_eq!(5, enc.write(b"bcdef").unwrap()); - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abcdef", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(8, c.get_ref().len()); -} - -#[test] -fn write_partial_then_enough_to_complete_chunk_and_another_chunk_and_another_partial_chunk_encodes_only_complete_chunks( -) { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - - assert_eq!(1, enc.write(b"a").unwrap()); - // completes partial chunk, and another chunk, with one more partial chunk that's not - // consumed - assert_eq!(5, enc.write(b"bcdefe").unwrap()); - let _ = enc.finish().unwrap(); - } - assert_eq!( - &c.get_ref()[..], - encode_config("abcdef", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(8, c.get_ref().len()); -} - -#[test] -fn drop_calls_finish_for_you() { - let mut c = Cursor::new(Vec::new()); - { - let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD); - assert_eq!(1, enc.write(b"a").unwrap()); - } - assert_eq!( - &c.get_ref()[..], - encode_config("a", STANDARD_NO_PAD).as_bytes() - ); - assert_eq!(2, c.get_ref().len()); -} - -#[test] -fn every_possible_split_of_input() { - let mut rng = rand::thread_rng(); - let mut orig_data = Vec::::new(); - let mut stream_encoded = Vec::::new(); - let mut normal_encoded = String::new(); - - let size = 5_000; - - for i in 0..size { - orig_data.clear(); - stream_encoded.clear(); - normal_encoded.clear(); - - for _ in 0..size { - orig_data.push(rng.gen()); - } - - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut normal_encoded); - - { - let mut stream_encoder = EncoderWriter::new(&mut stream_encoded, config); - // Write the first i bytes, then the rest - stream_encoder.write_all(&orig_data[0..i]).unwrap(); - stream_encoder.write_all(&orig_data[i..]).unwrap(); - } - - assert_eq!(normal_encoded, str::from_utf8(&stream_encoded).unwrap()); - } -} - -#[test] -fn encode_random_config_matches_normal_encode_reasonable_input_len() { - // choose up to 2 * buf size, so ~half the time it'll use a full buffer - do_encode_random_config_matches_normal_encode(super::encoder::BUF_SIZE * 2) -} - -#[test] -fn encode_random_config_matches_normal_encode_tiny_input_len() { - do_encode_random_config_matches_normal_encode(10) -} - -#[test] -fn retrying_writes_that_error_with_interrupted_works() { - let mut rng = rand::thread_rng(); - let mut orig_data = Vec::::new(); - let mut stream_encoded = Vec::::new(); - let mut normal_encoded = String::new(); - - for _ in 0..1_000 { - orig_data.clear(); - stream_encoded.clear(); - normal_encoded.clear(); - - let orig_len: usize = rng.gen_range(100, 20_000); - for _ in 0..orig_len { - orig_data.push(rng.gen()); - } - - // encode the normal way - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut normal_encoded); - - // encode via the stream encoder - { - let mut interrupt_rng = rand::thread_rng(); - let mut interrupting_writer = InterruptingWriter { - w: &mut stream_encoded, - rng: &mut interrupt_rng, - fraction: 0.8, - }; - - let mut stream_encoder = EncoderWriter::new(&mut interrupting_writer, config); - let mut bytes_consumed = 0; - while bytes_consumed < orig_len { - // use short inputs since we want to use `extra` a lot as that's what needs rollback - // when errors occur - let input_len: usize = cmp::min(rng.gen_range(0, 10), orig_len - bytes_consumed); - - retry_interrupted_write_all( - &mut stream_encoder, - &orig_data[bytes_consumed..bytes_consumed + input_len], - ) - .unwrap(); - - bytes_consumed += input_len; - } - - loop { - let res = stream_encoder.finish(); - match res { - Ok(_) => break, - Err(e) => match e.kind() { - io::ErrorKind::Interrupted => continue, - _ => Err(e).unwrap(), // bail - }, - } - } - - assert_eq!(orig_len, bytes_consumed); - } - - assert_eq!(normal_encoded, str::from_utf8(&stream_encoded).unwrap()); - } -} - -#[test] -fn writes_that_only_write_part_of_input_and_sometimes_interrupt_produce_correct_encoded_data() { - let mut rng = rand::thread_rng(); - let mut orig_data = Vec::::new(); - let mut stream_encoded = Vec::::new(); - let mut normal_encoded = String::new(); - - for _ in 0..1_000 { - orig_data.clear(); - stream_encoded.clear(); - normal_encoded.clear(); - - let orig_len: usize = rng.gen_range(100, 20_000); - for _ in 0..orig_len { - orig_data.push(rng.gen()); - } - - // encode the normal way - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut normal_encoded); - - // encode via the stream encoder - { - let mut partial_rng = rand::thread_rng(); - let mut partial_writer = PartialInterruptingWriter { - w: &mut stream_encoded, - rng: &mut partial_rng, - full_input_fraction: 0.1, - no_interrupt_fraction: 0.1, - }; - - let mut stream_encoder = EncoderWriter::new(&mut partial_writer, config); - let mut bytes_consumed = 0; - while bytes_consumed < orig_len { - // use at most medium-length inputs to exercise retry logic more aggressively - let input_len: usize = cmp::min(rng.gen_range(0, 100), orig_len - bytes_consumed); - - let res = - stream_encoder.write(&orig_data[bytes_consumed..bytes_consumed + input_len]); - - // retry on interrupt - match res { - Ok(len) => bytes_consumed += len, - Err(e) => match e.kind() { - io::ErrorKind::Interrupted => continue, - _ => { - panic!("should not see other errors"); - } - }, - } - } - - stream_encoder.finish().unwrap(); - - assert_eq!(orig_len, bytes_consumed); - } - - assert_eq!(normal_encoded, str::from_utf8(&stream_encoded).unwrap()); - } -} - -/// Retry writes until all the data is written or an error that isn't Interrupted is returned. -fn retry_interrupted_write_all(w: &mut W, buf: &[u8]) -> io::Result<()> { - let mut bytes_consumed = 0; - - while bytes_consumed < buf.len() { - let res = w.write(&buf[bytes_consumed..]); - - match res { - Ok(len) => bytes_consumed += len, - Err(e) => match e.kind() { - io::ErrorKind::Interrupted => continue, - _ => return Err(e), - }, - } - } - - Ok(()) -} - -fn do_encode_random_config_matches_normal_encode(max_input_len: usize) { - let mut rng = rand::thread_rng(); - let mut orig_data = Vec::::new(); - let mut stream_encoded = Vec::::new(); - let mut normal_encoded = String::new(); - - for _ in 0..1_000 { - orig_data.clear(); - stream_encoded.clear(); - normal_encoded.clear(); - - let orig_len: usize = rng.gen_range(100, 20_000); - for _ in 0..orig_len { - orig_data.push(rng.gen()); - } - - // encode the normal way - let config = random_config(&mut rng); - encode_config_buf(&orig_data, config, &mut normal_encoded); - - // encode via the stream encoder - { - let mut stream_encoder = EncoderWriter::new(&mut stream_encoded, config); - let mut bytes_consumed = 0; - while bytes_consumed < orig_len { - let input_len: usize = - cmp::min(rng.gen_range(0, max_input_len), orig_len - bytes_consumed); - - // write a little bit of the data - stream_encoder - .write_all(&orig_data[bytes_consumed..bytes_consumed + input_len]) - .unwrap(); - - bytes_consumed += input_len; - } - - stream_encoder.finish().unwrap(); - - assert_eq!(orig_len, bytes_consumed); - } - - assert_eq!(normal_encoded, str::from_utf8(&stream_encoded).unwrap()); - } -} - -/// A `Write` implementation that returns Interrupted some fraction of the time, randomly. -struct InterruptingWriter<'a, W: 'a + Write, R: 'a + Rng> { - w: &'a mut W, - rng: &'a mut R, - /// In [0, 1]. If a random number in [0, 1] is `<= threshold`, `Write` methods will return - /// an `Interrupted` error - fraction: f64, -} - -impl<'a, W: Write, R: Rng> Write for InterruptingWriter<'a, W, R> { - fn write(&mut self, buf: &[u8]) -> io::Result { - if self.rng.gen_range(0.0, 1.0) <= self.fraction { - return Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted")); - } - - self.w.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - if self.rng.gen_range(0.0, 1.0) <= self.fraction { - return Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted")); - } - - self.w.flush() - } -} - -/// A `Write` implementation that sometimes will only write part of its input. -struct PartialInterruptingWriter<'a, W: 'a + Write, R: 'a + Rng> { - w: &'a mut W, - rng: &'a mut R, - /// In [0, 1]. If a random number in [0, 1] is `<= threshold`, `write()` will write all its - /// input. Otherwise, it will write a random substring - full_input_fraction: f64, - no_interrupt_fraction: f64, -} - -impl<'a, W: Write, R: Rng> Write for PartialInterruptingWriter<'a, W, R> { - fn write(&mut self, buf: &[u8]) -> io::Result { - if self.rng.gen_range(0.0, 1.0) > self.no_interrupt_fraction { - return Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted")); - } - - if self.rng.gen_range(0.0, 1.0) <= self.full_input_fraction || buf.len() == 0 { - // pass through the buf untouched - self.w.write(buf) - } else { - // only use a prefix of it - self.w - .write(&buf[0..(self.rng.gen_range(0, buf.len() - 1))]) - } - } - - fn flush(&mut self) -> io::Result<()> { - self.w.flush() - } -} diff --git a/vendor/base64/src/write/mod.rs b/vendor/base64/src/write/mod.rs deleted file mode 100644 index f8ed70768c..0000000000 --- a/vendor/base64/src/write/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Implementations of `io::Write` to transparently handle base64. -mod encoder; -pub use self::encoder::EncoderWriter; - -#[cfg(test)] -mod encoder_tests; diff --git a/vendor/base64/tests/decode.rs b/vendor/base64/tests/decode.rs deleted file mode 100644 index fbe07691dc..0000000000 --- a/vendor/base64/tests/decode.rs +++ /dev/null @@ -1,310 +0,0 @@ -extern crate base64; - -use base64::*; - -mod helpers; - -use self::helpers::*; - -#[test] -fn decode_rfc4648_0() { - compare_decode("", ""); -} - -#[test] -fn decode_rfc4648_1() { - compare_decode("f", "Zg=="); -} - -#[test] -fn decode_rfc4648_1_just_a_bit_of_padding() { - // allows less padding than required - compare_decode("f", "Zg="); -} - -#[test] -fn decode_rfc4648_1_no_padding() { - compare_decode("f", "Zg"); -} - -#[test] -fn decode_rfc4648_2() { - compare_decode("fo", "Zm8="); -} - -#[test] -fn decode_rfc4648_2_no_padding() { - compare_decode("fo", "Zm8"); -} - -#[test] -fn decode_rfc4648_3() { - compare_decode("foo", "Zm9v"); -} - -#[test] -fn decode_rfc4648_4() { - compare_decode("foob", "Zm9vYg=="); -} - -#[test] -fn decode_rfc4648_4_no_padding() { - compare_decode("foob", "Zm9vYg"); -} - -#[test] -fn decode_rfc4648_5() { - compare_decode("fooba", "Zm9vYmE="); -} - -#[test] -fn decode_rfc4648_5_no_padding() { - compare_decode("fooba", "Zm9vYmE"); -} - -#[test] -fn decode_rfc4648_6() { - compare_decode("foobar", "Zm9vYmFy"); -} - -#[test] -fn decode_reject_null() { - assert_eq!( - DecodeError::InvalidByte(3, 0x0), - decode_config("YWx\0pY2U==", config_std_pad()).unwrap_err() - ); -} - -#[test] -fn decode_single_pad_byte_after_2_chars_in_trailing_quad_ok() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("Zg="); - - let input_len = num_quads * 3 + 1; - - // Since there are 3 bytes in the trailing quad, want to be sure this allows for the fact - // that it could be bad padding rather than assuming that it will decode to 2 bytes and - // therefore allow 1 extra round of fast decode logic (stage 1 / 2). - - let mut decoded = Vec::new(); - decoded.resize(input_len, 0); - - assert_eq!( - input_len, - decode_config_slice(&s, STANDARD, &mut decoded).unwrap() - ); - } -} - -//this is a MAY in the rfc: https://tools.ietf.org/html/rfc4648#section-3.3 -#[test] -fn decode_1_pad_byte_in_fast_loop_then_extra_padding_chunk_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("YWxpY2U====="); - - // since the first 8 bytes are handled in stage 1 or 2, the padding is detected as a - // generic invalid byte, not specifcally a padding issue. - // Could argue that the *next* padding byte (in the next quad) is technically the first - // erroneous one, but reporting that accurately is more complex and probably nobody cares - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 7, b'='), - decode(&s).unwrap_err() - ); - } -} - -#[test] -fn decode_2_pad_bytes_in_leftovers_then_extra_padding_chunk_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("YWxpY2UABB===="); - - // 6 bytes (4 padding) after last 8-byte chunk, so it's decoded by stage 4. - // First padding byte is invalid. - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 10, b'='), - decode(&s).unwrap_err() - ); - } -} - -#[test] -fn decode_valid_bytes_after_padding_in_leftovers_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("YWxpY2UABB=B"); - - // 4 bytes after last 8-byte chunk, so it's decoded by stage 4. - // First (and only) padding byte is invalid. - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 10, b'='), - decode(&s).unwrap_err() - ); - } -} - -#[test] -fn decode_absurd_pad_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("==Y=Wx===pY=2U====="); - - // Plenty of remaining bytes, so handled by stage 1 or 2. - // first padding byte - assert_eq!( - DecodeError::InvalidByte(num_quads * 4, b'='), - decode(&s).unwrap_err() - ); - } -} - -#[test] -fn decode_extra_padding_after_1_pad_bytes_in_trailing_quad_returns_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("EEE==="); - - // handled by stage 1, 2, or 4 depending on length - // first padding byte -- which would be legal if it was the only padding - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 3, b'='), - decode(&s).unwrap_err() - ); - } -} - -#[test] -fn decode_extra_padding_after_2_pad_bytes_in_trailing_quad_2_returns_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("EE===="); - - // handled by stage 1, 2, or 4 depending on length - // first padding byte -- which would be legal if it was by itself - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 2, b'='), - decode(&s).unwrap_err() - ); - } -} - -#[test] -fn decode_start_quad_with_padding_returns_error() { - for num_quads in 0..25 { - // add enough padding to ensure that we'll hit all 4 stages at the different lengths - for pad_bytes in 1..32 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - let padding: String = std::iter::repeat("=").take(pad_bytes).collect(); - s.push_str(&padding); - - if pad_bytes % 4 == 1 { - // detected in early length check - assert_eq!(DecodeError::InvalidLength, decode(&s).unwrap_err()); - } else { - // padding lengths 2 - 8 are handled by stage 4 - // padding length >= 8 will hit at least one chunk at stages 1, 2, 3 at different - // prefix lengths - assert_eq!( - DecodeError::InvalidByte(num_quads * 4, b'='), - decode(&s).unwrap_err() - ); - } - } - } -} - -#[test] -fn decode_padding_followed_by_non_padding_returns_error() { - for num_quads in 0..25 { - for pad_bytes in 0..31 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - let padding: String = std::iter::repeat("=").take(pad_bytes).collect(); - s.push_str(&padding); - s.push_str("E"); - - if pad_bytes % 4 == 0 { - assert_eq!(DecodeError::InvalidLength, decode(&s).unwrap_err()); - } else { - // pad len 1 - 8 will be handled by stage 4 - // pad len 9 (suffix len 10) will have 8 bytes of padding handled by stage 3 - // first padding byte - assert_eq!( - DecodeError::InvalidByte(num_quads * 4, b'='), - decode(&s).unwrap_err() - ); - } - } - } -} - -#[test] -fn decode_one_char_in_quad_with_padding_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("E="); - - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 1, b'='), - decode(&s).unwrap_err() - ); - - // more padding doesn't change the error - s.push_str("="); - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 1, b'='), - decode(&s).unwrap_err() - ); - - s.push_str("="); - assert_eq!( - DecodeError::InvalidByte(num_quads * 4 + 1, b'='), - decode(&s).unwrap_err() - ); - } -} - -#[test] -fn decode_one_char_in_quad_without_padding_error() { - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push('E'); - - assert_eq!(DecodeError::InvalidLength, decode(&s).unwrap_err()); - } -} - -#[test] -fn decode_reject_invalid_bytes_with_correct_error() { - for length in 1..100 { - for index in 0_usize..length { - for invalid_byte in " \t\n\r\x0C\x0B\x00%*.".bytes() { - let prefix: String = std::iter::repeat("A").take(index).collect(); - let suffix: String = std::iter::repeat("B").take(length - index - 1).collect(); - - let input = prefix + &String::from_utf8(vec![invalid_byte]).unwrap() + &suffix; - assert_eq!( - length, - input.len(), - "length {} error position {}", - length, - index - ); - - if length % 4 == 1 { - assert_eq!(DecodeError::InvalidLength, decode(&input).unwrap_err()); - } else { - assert_eq!( - DecodeError::InvalidByte(index, invalid_byte), - decode(&input).unwrap_err() - ); - } - } - } - } -} - -fn config_std_pad() -> Config { - Config::new(CharacterSet::Standard, true) -} diff --git a/vendor/base64/tests/encode.rs b/vendor/base64/tests/encode.rs deleted file mode 100644 index 0004be00fe..0000000000 --- a/vendor/base64/tests/encode.rs +++ /dev/null @@ -1,105 +0,0 @@ -extern crate base64; - -use base64::*; - -fn compare_encode(expected: &str, target: &[u8]) { - assert_eq!(expected, encode(target)); -} - -#[test] -fn encode_rfc4648_0() { - compare_encode("", b""); -} - -#[test] -fn encode_rfc4648_1() { - compare_encode("Zg==", b"f"); -} - -#[test] -fn encode_rfc4648_2() { - compare_encode("Zm8=", b"fo"); -} - -#[test] -fn encode_rfc4648_3() { - compare_encode("Zm9v", b"foo"); -} - -#[test] -fn encode_rfc4648_4() { - compare_encode("Zm9vYg==", b"foob"); -} - -#[test] -fn encode_rfc4648_5() { - compare_encode("Zm9vYmE=", b"fooba"); -} - -#[test] -fn encode_rfc4648_6() { - compare_encode("Zm9vYmFy", b"foobar"); -} - -#[test] -fn encode_all_ascii() { - let mut ascii = Vec::::with_capacity(128); - - for i in 0..128 { - ascii.push(i); - } - - compare_encode( - "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7P\ - D0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn8\ - =", - &ascii, - ); -} - -#[test] -fn encode_all_bytes() { - let mut bytes = Vec::::with_capacity(256); - - for i in 0..255 { - bytes.push(i); - } - bytes.push(255); //bug with "overflowing" ranges? - - compare_encode( - "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7P\ - D0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn\ - +AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6\ - /wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==", - &bytes, - ); -} - -#[test] -fn encode_all_bytes_url() { - let mut bytes = Vec::::with_capacity(256); - - for i in 0..255 { - bytes.push(i); - } - bytes.push(255); //bug with "overflowing" ranges? - - assert_eq!( - "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0\ - -P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn\ - -AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq\ - -wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy\ - 8_T19vf4-fr7_P3-_w==", - encode_config(&bytes, URL_SAFE) - ); -} - -#[test] -fn encode_url_safe_without_padding() { - let encoded = encode_config(b"alice", URL_SAFE_NO_PAD); - assert_eq!(&encoded, "YWxpY2U"); - assert_eq!( - String::from_utf8(decode(&encoded).unwrap()).unwrap(), - "alice" - ); -} diff --git a/vendor/base64/tests/helpers.rs b/vendor/base64/tests/helpers.rs deleted file mode 100644 index 5144988448..0000000000 --- a/vendor/base64/tests/helpers.rs +++ /dev/null @@ -1,14 +0,0 @@ -extern crate base64; - -use base64::*; - -pub fn compare_decode(expected: &str, target: &str) { - assert_eq!( - expected, - String::from_utf8(decode(target).unwrap()).unwrap() - ); - assert_eq!( - expected, - String::from_utf8(decode(target.as_bytes()).unwrap()).unwrap() - ); -} diff --git a/vendor/base64/tests/tests.rs b/vendor/base64/tests/tests.rs deleted file mode 100644 index 11fed960ff..0000000000 --- a/vendor/base64/tests/tests.rs +++ /dev/null @@ -1,194 +0,0 @@ -extern crate base64; -extern crate rand; - -use rand::{FromEntropy, Rng}; - -use base64::*; - -mod helpers; -use self::helpers::*; - -// generate random contents of the specified length and test encode/decode roundtrip -fn roundtrip_random( - byte_buf: &mut Vec, - str_buf: &mut String, - config: Config, - byte_len: usize, - approx_values_per_byte: u8, - max_rounds: u64, -) { - // let the short ones be short but don't let it get too crazy large - let num_rounds = calculate_number_of_rounds(byte_len, approx_values_per_byte, max_rounds); - let mut r = rand::rngs::SmallRng::from_entropy(); - let mut decode_buf = Vec::new(); - - for _ in 0..num_rounds { - byte_buf.clear(); - str_buf.clear(); - decode_buf.clear(); - while byte_buf.len() < byte_len { - byte_buf.push(r.gen::()); - } - - encode_config_buf(&byte_buf, config, str_buf); - decode_config_buf(&str_buf, config, &mut decode_buf).unwrap(); - - assert_eq!(byte_buf, &decode_buf); - } -} - -fn calculate_number_of_rounds(byte_len: usize, approx_values_per_byte: u8, max: u64) -> u64 { - // don't overflow - let mut prod = approx_values_per_byte as u64; - - for _ in 0..byte_len { - if prod > max { - return max; - } - - prod = prod.saturating_mul(prod); - } - - prod -} - -fn no_pad_config() -> Config { - Config::new(CharacterSet::Standard, false) -} - -#[test] -fn roundtrip_random_short_standard() { - let mut byte_buf: Vec = Vec::new(); - let mut str_buf = String::new(); - - for input_len in 0..40 { - roundtrip_random(&mut byte_buf, &mut str_buf, STANDARD, input_len, 4, 10000); - } -} - -#[test] -fn roundtrip_random_with_fast_loop_standard() { - let mut byte_buf: Vec = Vec::new(); - let mut str_buf = String::new(); - - for input_len in 40..100 { - roundtrip_random(&mut byte_buf, &mut str_buf, STANDARD, input_len, 4, 1000); - } -} - -#[test] -fn roundtrip_random_short_no_padding() { - let mut byte_buf: Vec = Vec::new(); - let mut str_buf = String::new(); - - for input_len in 0..40 { - roundtrip_random( - &mut byte_buf, - &mut str_buf, - no_pad_config(), - input_len, - 4, - 10000, - ); - } -} - -#[test] -fn roundtrip_random_no_padding() { - let mut byte_buf: Vec = Vec::new(); - let mut str_buf = String::new(); - - for input_len in 40..100 { - roundtrip_random( - &mut byte_buf, - &mut str_buf, - no_pad_config(), - input_len, - 4, - 1000, - ); - } -} - -#[test] -fn roundtrip_decode_trailing_10_bytes() { - // This is a special case because we decode 8 byte blocks of input at a time as much as we can, - // ideally unrolled to 32 bytes at a time, in stages 1 and 2. Since we also write a u64's worth - // of bytes (8) to the output, we always write 2 garbage bytes that then will be overwritten by - // the NEXT block. However, if the next block only contains 2 bytes, it will decode to 1 byte, - // and therefore be too short to cover up the trailing 2 garbage bytes. Thus, we have stage 3 - // to handle that case. - - for num_quads in 0..25 { - let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect(); - s.push_str("EFGHIJKLZg"); - - let decoded = decode(&s).unwrap(); - assert_eq!(num_quads * 3 + 7, decoded.len()); - - assert_eq!(s, encode_config(&decoded, STANDARD_NO_PAD)); - } -} - -#[test] -fn display_wrapper_matches_normal_encode() { - let mut bytes = Vec::::with_capacity(256); - - for i in 0..255 { - bytes.push(i); - } - bytes.push(255); - - assert_eq!( - encode(&bytes), - format!( - "{}", - base64::display::Base64Display::with_config(&bytes, STANDARD) - ) - ); -} - -#[test] -fn because_we_can() { - compare_decode("alice", "YWxpY2U="); - compare_decode("alice", &encode(b"alice")); - compare_decode("alice", &encode(&decode(&encode(b"alice")).unwrap())); -} - -#[test] -fn encode_config_slice_can_use_inline_buffer() { - let mut buf: [u8; 22] = [0; 22]; - let mut larger_buf: [u8; 24] = [0; 24]; - let mut input: [u8; 16] = [0; 16]; - - let mut rng = rand::rngs::SmallRng::from_entropy(); - for elt in &mut input { - *elt = rng.gen(); - } - - assert_eq!(22, encode_config_slice(&input, STANDARD_NO_PAD, &mut buf)); - let decoded = decode_config(&buf, STANDARD_NO_PAD).unwrap(); - - assert_eq!(decoded, input); - - // let's try it again with padding - - assert_eq!(24, encode_config_slice(&input, STANDARD, &mut larger_buf)); - let decoded = decode_config(&buf, STANDARD).unwrap(); - - assert_eq!(decoded, input); -} - -#[test] -#[should_panic(expected = "index 24 out of range for slice of length 22")] -fn encode_config_slice_panics_when_buffer_too_small() { - let mut buf: [u8; 22] = [0; 22]; - let mut input: [u8; 16] = [0; 16]; - - let mut rng = rand::rngs::SmallRng::from_entropy(); - for elt in &mut input { - *elt = rng.gen(); - } - - encode_config_slice(&input, STANDARD, &mut buf); -} diff --git a/vendor/blake2b_simd/.cargo-checksum.json b/vendor/blake2b_simd/.cargo-checksum.json deleted file mode 100644 index 2e265caab4..0000000000 --- a/vendor/blake2b_simd/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"2d5bffdbc397fd9e0ff49296716aab31957fd58576d624c0b1ab7f9f7058855e","README.md":"2253eba78d5af06642073c5dfd41253fb8be73d3a0e823bc3d7642c9d0ad0c6c","src/avx2.rs":"8e0c3932234c21ef0b016931b692a0449672b7ddd017d5b1fcc4faa50cc4a3b4","src/blake2bp.rs":"83577d4a22db3b92030d9bd4563aa9ad440f23c64a6ad5f10a9d709f22d50589","src/guts.rs":"1189cab87b18eaaf2abd5bcb3d7d799c75401a312cee6f1f65fdaad30203eb6f","src/lib.rs":"67723a3abc30dc7f3d488f434ced884b5ce962a807991c8f1cc9940df869c342","src/many.rs":"60d07e4d7ad63949fb5432ad05f7c6a525a3eee39d325f7d4e65e901b466be95","src/portable.rs":"a274acd298a394c014096a8214a0dc1db7439d1e920bd2ad75707fadcc501e10","src/sse41.rs":"a869541cac1acabb33c29d8721c44de84560f87ac47f8e11330392131641bb23","src/test.rs":"1685eec6fedc30fca1332cbb78c85e6c9b56eca962b6c6343c91ba69eefac754"},"package":"d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"} \ No newline at end of file diff --git a/vendor/blake2b_simd/README.md b/vendor/blake2b_simd/README.md deleted file mode 100644 index 54caef739d..0000000000 --- a/vendor/blake2b_simd/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# blake2b_simd [![GitHub](https://img.shields.io/github/tag/oconnor663/blake2_simd.svg?label=GitHub)](https://github.com/oconnor663/blake2_simd) [![crates.io](https://img.shields.io/crates/v/blake2b_simd.svg)](https://crates.io/crates/blake2b_simd) [![Build Status](https://travis-ci.org/oconnor663/blake2_simd.svg?branch=master)](https://travis-ci.org/oconnor663/blake2_simd) - -An implementation of the BLAKE2b and BLAKE2bp hash functions. See also -[`blake2s_simd`](../blake2s). - -This crate includes: - -- 100% stable Rust. -- SIMD implementations based on Samuel Neves' [`blake2-avx2`](https://github.com/sneves/blake2-avx2). - These are very fast. For benchmarks, see [the Performance section of the - README](https://github.com/oconnor663/blake2_simd#performance). -- Portable, safe implementations for other platforms. -- Dynamic CPU feature detection. Binaries include multiple implementations by default and - choose the fastest one the processor supports at runtime. -- All the features from the [the BLAKE2 spec](https://blake2.net/blake2.pdf), like adjustable - length, keying, and associated data for tree hashing. -- `no_std` support. The `std` Cargo feature is on by default, for CPU feature detection and - for implementing `std::io::Write`. -- Support for computing multiple BLAKE2b hashes in parallel, matching the efficiency of - BLAKE2bp. See the [`many`](many/index.html) module. - -# Example - -``` -use blake2b_simd::{blake2b, Params}; - -let expected = "ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6d\ - c1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d"; -let hash = blake2b(b"foo"); -assert_eq!(expected, &hash.to_hex()); - -let hash = Params::new() - .hash_length(16) - .key(b"The Magic Words are Squeamish Ossifrage") - .personal(b"L. P. Waterhouse") - .to_state() - .update(b"foo") - .update(b"bar") - .update(b"baz") - .finalize(); -assert_eq!("ee8ff4e9be887297cf79348dc35dab56", &hash.to_hex()); -``` diff --git a/vendor/blake2b_simd/src/avx2.rs b/vendor/blake2b_simd/src/avx2.rs deleted file mode 100644 index 7fbdec5bad..0000000000 --- a/vendor/blake2b_simd/src/avx2.rs +++ /dev/null @@ -1,928 +0,0 @@ -#[cfg(target_arch = "x86")] -use core::arch::x86::*; -#[cfg(target_arch = "x86_64")] -use core::arch::x86_64::*; - -use crate::guts::{ - assemble_count, count_high, count_low, final_block, flag_word, input_debug_asserts, Finalize, - Job, LastNode, Stride, -}; -use crate::{Count, Word, BLOCKBYTES, IV, SIGMA}; -use arrayref::{array_refs, mut_array_refs}; -use core::cmp; -use core::mem; - -pub const DEGREE: usize = 4; - -#[inline(always)] -unsafe fn loadu(src: *const [Word; DEGREE]) -> __m256i { - // This is an unaligned load, so the pointer cast is allowed. - _mm256_loadu_si256(src as *const __m256i) -} - -#[inline(always)] -unsafe fn storeu(src: __m256i, dest: *mut [Word; DEGREE]) { - // This is an unaligned store, so the pointer cast is allowed. - _mm256_storeu_si256(dest as *mut __m256i, src) -} - -#[inline(always)] -unsafe fn loadu_128(mem_addr: &[u8; 16]) -> __m128i { - _mm_loadu_si128(mem_addr.as_ptr() as *const __m128i) -} - -#[inline(always)] -unsafe fn add(a: __m256i, b: __m256i) -> __m256i { - _mm256_add_epi64(a, b) -} - -#[inline(always)] -unsafe fn eq(a: __m256i, b: __m256i) -> __m256i { - _mm256_cmpeq_epi64(a, b) -} - -#[inline(always)] -unsafe fn and(a: __m256i, b: __m256i) -> __m256i { - _mm256_and_si256(a, b) -} - -#[inline(always)] -unsafe fn negate_and(a: __m256i, b: __m256i) -> __m256i { - // Note that "and not" implies the reverse of the actual arg order. - _mm256_andnot_si256(a, b) -} - -#[inline(always)] -unsafe fn xor(a: __m256i, b: __m256i) -> __m256i { - _mm256_xor_si256(a, b) -} - -#[inline(always)] -unsafe fn set1(x: u64) -> __m256i { - _mm256_set1_epi64x(x as i64) -} - -#[inline(always)] -unsafe fn set4(a: u64, b: u64, c: u64, d: u64) -> __m256i { - _mm256_setr_epi64x(a as i64, b as i64, c as i64, d as i64) -} - -// Adapted from https://github.com/rust-lang-nursery/stdsimd/pull/479. -macro_rules! _MM_SHUFFLE { - ($z:expr, $y:expr, $x:expr, $w:expr) => { - ($z << 6) | ($y << 4) | ($x << 2) | $w - }; -} - -// These rotations are the "simple version". For the "complicated version", see -// https://github.com/sneves/blake2-avx2/blob/b3723921f668df09ece52dcd225a36d4a4eea1d9/blake2b-common.h#L43-L46. -// For a discussion of the tradeoffs, see -// https://github.com/sneves/blake2-avx2/pull/5. In short: -// - This version performs better on modern x86 chips, Skylake and later. -// - LLVM is able to optimize this version to AVX-512 rotation instructions -// when those are enabled. - -#[inline(always)] -unsafe fn rot32(x: __m256i) -> __m256i { - _mm256_or_si256(_mm256_srli_epi64(x, 32), _mm256_slli_epi64(x, 64 - 32)) -} - -#[inline(always)] -unsafe fn rot24(x: __m256i) -> __m256i { - _mm256_or_si256(_mm256_srli_epi64(x, 24), _mm256_slli_epi64(x, 64 - 24)) -} - -#[inline(always)] -unsafe fn rot16(x: __m256i) -> __m256i { - _mm256_or_si256(_mm256_srli_epi64(x, 16), _mm256_slli_epi64(x, 64 - 16)) -} - -#[inline(always)] -unsafe fn rot63(x: __m256i) -> __m256i { - _mm256_or_si256(_mm256_srli_epi64(x, 63), _mm256_slli_epi64(x, 64 - 63)) -} - -#[inline(always)] -unsafe fn g1(a: &mut __m256i, b: &mut __m256i, c: &mut __m256i, d: &mut __m256i, m: &mut __m256i) { - *a = add(*a, *m); - *a = add(*a, *b); - *d = xor(*d, *a); - *d = rot32(*d); - *c = add(*c, *d); - *b = xor(*b, *c); - *b = rot24(*b); -} - -#[inline(always)] -unsafe fn g2(a: &mut __m256i, b: &mut __m256i, c: &mut __m256i, d: &mut __m256i, m: &mut __m256i) { - *a = add(*a, *m); - *a = add(*a, *b); - *d = xor(*d, *a); - *d = rot16(*d); - *c = add(*c, *d); - *b = xor(*b, *c); - *b = rot63(*b); -} - -// Note the optimization here of leaving b as the unrotated row, rather than a. -// All the message loads below are adjusted to compensate for this. See -// discussion at https://github.com/sneves/blake2-avx2/pull/4 -#[inline(always)] -unsafe fn diagonalize(a: &mut __m256i, _b: &mut __m256i, c: &mut __m256i, d: &mut __m256i) { - *a = _mm256_permute4x64_epi64(*a, _MM_SHUFFLE!(2, 1, 0, 3)); - *d = _mm256_permute4x64_epi64(*d, _MM_SHUFFLE!(1, 0, 3, 2)); - *c = _mm256_permute4x64_epi64(*c, _MM_SHUFFLE!(0, 3, 2, 1)); -} - -#[inline(always)] -unsafe fn undiagonalize(a: &mut __m256i, _b: &mut __m256i, c: &mut __m256i, d: &mut __m256i) { - *a = _mm256_permute4x64_epi64(*a, _MM_SHUFFLE!(0, 3, 2, 1)); - *d = _mm256_permute4x64_epi64(*d, _MM_SHUFFLE!(1, 0, 3, 2)); - *c = _mm256_permute4x64_epi64(*c, _MM_SHUFFLE!(2, 1, 0, 3)); -} - -#[inline(always)] -unsafe fn compress_block( - block: &[u8; BLOCKBYTES], - words: &mut [Word; 8], - count: Count, - last_block: Word, - last_node: Word, -) { - let (words_low, words_high) = mut_array_refs!(words, DEGREE, DEGREE); - let (iv_low, iv_high) = array_refs!(&IV, DEGREE, DEGREE); - let mut a = loadu(words_low); - let mut b = loadu(words_high); - let mut c = loadu(iv_low); - let flags = set4(count_low(count), count_high(count), last_block, last_node); - let mut d = xor(loadu(iv_high), flags); - - let msg_chunks = array_refs!(block, 16, 16, 16, 16, 16, 16, 16, 16); - let m0 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.0)); - let m1 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.1)); - let m2 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.2)); - let m3 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.3)); - let m4 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.4)); - let m5 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.5)); - let m6 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.6)); - let m7 = _mm256_broadcastsi128_si256(loadu_128(msg_chunks.7)); - - let iv0 = a; - let iv1 = b; - let mut t0; - let mut t1; - let mut b0; - - // round 1 - t0 = _mm256_unpacklo_epi64(m0, m1); - t1 = _mm256_unpacklo_epi64(m2, m3); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m0, m1); - t1 = _mm256_unpackhi_epi64(m2, m3); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_unpacklo_epi64(m7, m4); - t1 = _mm256_unpacklo_epi64(m5, m6); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m7, m4); - t1 = _mm256_unpackhi_epi64(m5, m6); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 2 - t0 = _mm256_unpacklo_epi64(m7, m2); - t1 = _mm256_unpackhi_epi64(m4, m6); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m5, m4); - t1 = _mm256_alignr_epi8(m3, m7, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_unpackhi_epi64(m2, m0); - t1 = _mm256_blend_epi32(m5, m0, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_alignr_epi8(m6, m1, 8); - t1 = _mm256_blend_epi32(m3, m1, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 3 - t0 = _mm256_alignr_epi8(m6, m5, 8); - t1 = _mm256_unpackhi_epi64(m2, m7); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m4, m0); - t1 = _mm256_blend_epi32(m6, m1, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_alignr_epi8(m5, m4, 8); - t1 = _mm256_unpackhi_epi64(m1, m3); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m2, m7); - t1 = _mm256_blend_epi32(m0, m3, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 4 - t0 = _mm256_unpackhi_epi64(m3, m1); - t1 = _mm256_unpackhi_epi64(m6, m5); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m4, m0); - t1 = _mm256_unpacklo_epi64(m6, m7); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_alignr_epi8(m1, m7, 8); - t1 = _mm256_shuffle_epi32(m2, _MM_SHUFFLE!(1, 0, 3, 2)); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m4, m3); - t1 = _mm256_unpacklo_epi64(m5, m0); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 5 - t0 = _mm256_unpackhi_epi64(m4, m2); - t1 = _mm256_unpacklo_epi64(m1, m5); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_blend_epi32(m3, m0, 0x33); - t1 = _mm256_blend_epi32(m7, m2, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_alignr_epi8(m7, m1, 8); - t1 = _mm256_alignr_epi8(m3, m5, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m6, m0); - t1 = _mm256_unpacklo_epi64(m6, m4); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 6 - t0 = _mm256_unpacklo_epi64(m1, m3); - t1 = _mm256_unpacklo_epi64(m0, m4); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m6, m5); - t1 = _mm256_unpackhi_epi64(m5, m1); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_alignr_epi8(m2, m0, 8); - t1 = _mm256_unpackhi_epi64(m3, m7); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m4, m6); - t1 = _mm256_alignr_epi8(m7, m2, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 7 - t0 = _mm256_blend_epi32(m0, m6, 0x33); - t1 = _mm256_unpacklo_epi64(m7, m2); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m2, m7); - t1 = _mm256_alignr_epi8(m5, m6, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_unpacklo_epi64(m4, m0); - t1 = _mm256_blend_epi32(m4, m3, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m5, m3); - t1 = _mm256_shuffle_epi32(m1, _MM_SHUFFLE!(1, 0, 3, 2)); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 8 - t0 = _mm256_unpackhi_epi64(m6, m3); - t1 = _mm256_blend_epi32(m1, m6, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_alignr_epi8(m7, m5, 8); - t1 = _mm256_unpackhi_epi64(m0, m4); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_blend_epi32(m2, m1, 0x33); - t1 = _mm256_alignr_epi8(m4, m7, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m5, m0); - t1 = _mm256_unpacklo_epi64(m2, m3); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 9 - t0 = _mm256_unpacklo_epi64(m3, m7); - t1 = _mm256_alignr_epi8(m0, m5, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m7, m4); - t1 = _mm256_alignr_epi8(m4, m1, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_unpacklo_epi64(m5, m6); - t1 = _mm256_unpackhi_epi64(m6, m0); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_alignr_epi8(m1, m2, 8); - t1 = _mm256_alignr_epi8(m2, m3, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 10 - t0 = _mm256_unpacklo_epi64(m5, m4); - t1 = _mm256_unpackhi_epi64(m3, m0); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m1, m2); - t1 = _mm256_blend_epi32(m2, m3, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_unpackhi_epi64(m6, m7); - t1 = _mm256_unpackhi_epi64(m4, m1); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_blend_epi32(m5, m0, 0x33); - t1 = _mm256_unpacklo_epi64(m7, m6); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 11 - t0 = _mm256_unpacklo_epi64(m0, m1); - t1 = _mm256_unpacklo_epi64(m2, m3); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m0, m1); - t1 = _mm256_unpackhi_epi64(m2, m3); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_unpacklo_epi64(m7, m4); - t1 = _mm256_unpacklo_epi64(m5, m6); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpackhi_epi64(m7, m4); - t1 = _mm256_unpackhi_epi64(m5, m6); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - // round 12 - t0 = _mm256_unpacklo_epi64(m7, m2); - t1 = _mm256_unpackhi_epi64(m4, m6); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_unpacklo_epi64(m5, m4); - t1 = _mm256_alignr_epi8(m3, m7, 8); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - diagonalize(&mut a, &mut b, &mut c, &mut d); - t0 = _mm256_unpackhi_epi64(m2, m0); - t1 = _mm256_blend_epi32(m5, m0, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g1(&mut a, &mut b, &mut c, &mut d, &mut b0); - t0 = _mm256_alignr_epi8(m6, m1, 8); - t1 = _mm256_blend_epi32(m3, m1, 0x33); - b0 = _mm256_blend_epi32(t0, t1, 0xF0); - g2(&mut a, &mut b, &mut c, &mut d, &mut b0); - undiagonalize(&mut a, &mut b, &mut c, &mut d); - - a = xor(a, c); - b = xor(b, d); - a = xor(a, iv0); - b = xor(b, iv1); - - storeu(a, words_low); - storeu(b, words_high); -} - -#[target_feature(enable = "avx2")] -pub unsafe fn compress1_loop( - input: &[u8], - words: &mut [Word; 8], - mut count: Count, - last_node: LastNode, - finalize: Finalize, - stride: Stride, -) { - input_debug_asserts(input, finalize); - - let mut local_words = *words; - - let mut fin_offset = input.len().saturating_sub(1); - fin_offset -= fin_offset % stride.padded_blockbytes(); - let mut buf = [0; BLOCKBYTES]; - let (fin_block, fin_len, _) = final_block(input, fin_offset, &mut buf, stride); - let fin_last_block = flag_word(finalize.yes()); - let fin_last_node = flag_word(finalize.yes() && last_node.yes()); - - let mut offset = 0; - loop { - let block; - let count_delta; - let last_block; - let last_node; - if offset == fin_offset { - block = fin_block; - count_delta = fin_len; - last_block = fin_last_block; - last_node = fin_last_node; - } else { - // This unsafe cast avoids bounds checks. There's guaranteed to be - // enough input because `offset < fin_offset`. - block = &*(input.as_ptr().add(offset) as *const [u8; BLOCKBYTES]); - count_delta = BLOCKBYTES; - last_block = flag_word(false); - last_node = flag_word(false); - }; - - count = count.wrapping_add(count_delta as Count); - compress_block(block, &mut local_words, count, last_block, last_node); - - // Check for termination before bumping the offset, to avoid overflow. - if offset == fin_offset { - break; - } - - offset += stride.padded_blockbytes(); - } - - *words = local_words; -} - -// Performance note: Factoring out a G function here doesn't hurt performance, -// unlike in the case of BLAKE2s where it hurts substantially. In fact, on my -// machine, it helps a tiny bit. But the difference it tiny, so I'm going to -// stick to the approach used by https://github.com/sneves/blake2-avx2 -// until/unless I can be sure the (tiny) improvement is consistent across -// different Intel microarchitectures. Smaller code size is nice, but a -// divergence between the BLAKE2b and BLAKE2s implementations is less nice. -#[inline(always)] -unsafe fn round(v: &mut [__m256i; 16], m: &[__m256i; 16], r: usize) { - v[0] = add(v[0], m[SIGMA[r][0] as usize]); - v[1] = add(v[1], m[SIGMA[r][2] as usize]); - v[2] = add(v[2], m[SIGMA[r][4] as usize]); - v[3] = add(v[3], m[SIGMA[r][6] as usize]); - v[0] = add(v[0], v[4]); - v[1] = add(v[1], v[5]); - v[2] = add(v[2], v[6]); - v[3] = add(v[3], v[7]); - v[12] = xor(v[12], v[0]); - v[13] = xor(v[13], v[1]); - v[14] = xor(v[14], v[2]); - v[15] = xor(v[15], v[3]); - v[12] = rot32(v[12]); - v[13] = rot32(v[13]); - v[14] = rot32(v[14]); - v[15] = rot32(v[15]); - v[8] = add(v[8], v[12]); - v[9] = add(v[9], v[13]); - v[10] = add(v[10], v[14]); - v[11] = add(v[11], v[15]); - v[4] = xor(v[4], v[8]); - v[5] = xor(v[5], v[9]); - v[6] = xor(v[6], v[10]); - v[7] = xor(v[7], v[11]); - v[4] = rot24(v[4]); - v[5] = rot24(v[5]); - v[6] = rot24(v[6]); - v[7] = rot24(v[7]); - v[0] = add(v[0], m[SIGMA[r][1] as usize]); - v[1] = add(v[1], m[SIGMA[r][3] as usize]); - v[2] = add(v[2], m[SIGMA[r][5] as usize]); - v[3] = add(v[3], m[SIGMA[r][7] as usize]); - v[0] = add(v[0], v[4]); - v[1] = add(v[1], v[5]); - v[2] = add(v[2], v[6]); - v[3] = add(v[3], v[7]); - v[12] = xor(v[12], v[0]); - v[13] = xor(v[13], v[1]); - v[14] = xor(v[14], v[2]); - v[15] = xor(v[15], v[3]); - v[12] = rot16(v[12]); - v[13] = rot16(v[13]); - v[14] = rot16(v[14]); - v[15] = rot16(v[15]); - v[8] = add(v[8], v[12]); - v[9] = add(v[9], v[13]); - v[10] = add(v[10], v[14]); - v[11] = add(v[11], v[15]); - v[4] = xor(v[4], v[8]); - v[5] = xor(v[5], v[9]); - v[6] = xor(v[6], v[10]); - v[7] = xor(v[7], v[11]); - v[4] = rot63(v[4]); - v[5] = rot63(v[5]); - v[6] = rot63(v[6]); - v[7] = rot63(v[7]); - - v[0] = add(v[0], m[SIGMA[r][8] as usize]); - v[1] = add(v[1], m[SIGMA[r][10] as usize]); - v[2] = add(v[2], m[SIGMA[r][12] as usize]); - v[3] = add(v[3], m[SIGMA[r][14] as usize]); - v[0] = add(v[0], v[5]); - v[1] = add(v[1], v[6]); - v[2] = add(v[2], v[7]); - v[3] = add(v[3], v[4]); - v[15] = xor(v[15], v[0]); - v[12] = xor(v[12], v[1]); - v[13] = xor(v[13], v[2]); - v[14] = xor(v[14], v[3]); - v[15] = rot32(v[15]); - v[12] = rot32(v[12]); - v[13] = rot32(v[13]); - v[14] = rot32(v[14]); - v[10] = add(v[10], v[15]); - v[11] = add(v[11], v[12]); - v[8] = add(v[8], v[13]); - v[9] = add(v[9], v[14]); - v[5] = xor(v[5], v[10]); - v[6] = xor(v[6], v[11]); - v[7] = xor(v[7], v[8]); - v[4] = xor(v[4], v[9]); - v[5] = rot24(v[5]); - v[6] = rot24(v[6]); - v[7] = rot24(v[7]); - v[4] = rot24(v[4]); - v[0] = add(v[0], m[SIGMA[r][9] as usize]); - v[1] = add(v[1], m[SIGMA[r][11] as usize]); - v[2] = add(v[2], m[SIGMA[r][13] as usize]); - v[3] = add(v[3], m[SIGMA[r][15] as usize]); - v[0] = add(v[0], v[5]); - v[1] = add(v[1], v[6]); - v[2] = add(v[2], v[7]); - v[3] = add(v[3], v[4]); - v[15] = xor(v[15], v[0]); - v[12] = xor(v[12], v[1]); - v[13] = xor(v[13], v[2]); - v[14] = xor(v[14], v[3]); - v[15] = rot16(v[15]); - v[12] = rot16(v[12]); - v[13] = rot16(v[13]); - v[14] = rot16(v[14]); - v[10] = add(v[10], v[15]); - v[11] = add(v[11], v[12]); - v[8] = add(v[8], v[13]); - v[9] = add(v[9], v[14]); - v[5] = xor(v[5], v[10]); - v[6] = xor(v[6], v[11]); - v[7] = xor(v[7], v[8]); - v[4] = xor(v[4], v[9]); - v[5] = rot63(v[5]); - v[6] = rot63(v[6]); - v[7] = rot63(v[7]); - v[4] = rot63(v[4]); -} - -// We'd rather make this a regular function with #[inline(always)], but for -// some reason that blows up compile times by about 10 seconds, at least in -// some cases (BLAKE2b avx2.rs). This macro seems to get the same performance -// result, without the compile time issue. -macro_rules! compress4_transposed { - ( - $h_vecs:expr, - $msg_vecs:expr, - $count_low:expr, - $count_high:expr, - $lastblock:expr, - $lastnode:expr, - ) => { - let h_vecs: &mut [__m256i; 8] = $h_vecs; - let msg_vecs: &[__m256i; 16] = $msg_vecs; - let count_low: __m256i = $count_low; - let count_high: __m256i = $count_high; - let lastblock: __m256i = $lastblock; - let lastnode: __m256i = $lastnode; - - let mut v = [ - h_vecs[0], - h_vecs[1], - h_vecs[2], - h_vecs[3], - h_vecs[4], - h_vecs[5], - h_vecs[6], - h_vecs[7], - set1(IV[0]), - set1(IV[1]), - set1(IV[2]), - set1(IV[3]), - xor(set1(IV[4]), count_low), - xor(set1(IV[5]), count_high), - xor(set1(IV[6]), lastblock), - xor(set1(IV[7]), lastnode), - ]; - - round(&mut v, &msg_vecs, 0); - round(&mut v, &msg_vecs, 1); - round(&mut v, &msg_vecs, 2); - round(&mut v, &msg_vecs, 3); - round(&mut v, &msg_vecs, 4); - round(&mut v, &msg_vecs, 5); - round(&mut v, &msg_vecs, 6); - round(&mut v, &msg_vecs, 7); - round(&mut v, &msg_vecs, 8); - round(&mut v, &msg_vecs, 9); - round(&mut v, &msg_vecs, 10); - round(&mut v, &msg_vecs, 11); - - h_vecs[0] = xor(xor(h_vecs[0], v[0]), v[8]); - h_vecs[1] = xor(xor(h_vecs[1], v[1]), v[9]); - h_vecs[2] = xor(xor(h_vecs[2], v[2]), v[10]); - h_vecs[3] = xor(xor(h_vecs[3], v[3]), v[11]); - h_vecs[4] = xor(xor(h_vecs[4], v[4]), v[12]); - h_vecs[5] = xor(xor(h_vecs[5], v[5]), v[13]); - h_vecs[6] = xor(xor(h_vecs[6], v[6]), v[14]); - h_vecs[7] = xor(xor(h_vecs[7], v[7]), v[15]); - }; -} - -#[inline(always)] -unsafe fn interleave128(a: __m256i, b: __m256i) -> (__m256i, __m256i) { - ( - _mm256_permute2x128_si256(a, b, 0x20), - _mm256_permute2x128_si256(a, b, 0x31), - ) -} - -// There are several ways to do a transposition. We could do it naively, with 8 separate -// _mm256_set_epi64x instructions, referencing each of the 64 words explicitly. Or we could copy -// the vecs into contiguous storage and then use gather instructions. This third approach is to use -// a series of unpack instructions to interleave the vectors. In my benchmarks, interleaving is the -// fastest approach. To test this, run `cargo +nightly bench --bench libtest load_4` in the -// https://github.com/oconnor663/bao_experiments repo. -#[inline(always)] -unsafe fn transpose_vecs( - vec_a: __m256i, - vec_b: __m256i, - vec_c: __m256i, - vec_d: __m256i, -) -> [__m256i; DEGREE] { - // Interleave 64-bit lates. The low unpack is lanes 00/22 and the high is 11/33. - let ab_02 = _mm256_unpacklo_epi64(vec_a, vec_b); - let ab_13 = _mm256_unpackhi_epi64(vec_a, vec_b); - let cd_02 = _mm256_unpacklo_epi64(vec_c, vec_d); - let cd_13 = _mm256_unpackhi_epi64(vec_c, vec_d); - - // Interleave 128-bit lanes. - let (abcd_0, abcd_2) = interleave128(ab_02, cd_02); - let (abcd_1, abcd_3) = interleave128(ab_13, cd_13); - - [abcd_0, abcd_1, abcd_2, abcd_3] -} - -#[inline(always)] -unsafe fn transpose_state_vecs(jobs: &[Job; DEGREE]) -> [__m256i; 8] { - // Load all the state words into transposed vectors, where the first vector - // has the first word of each state, etc. Transposing once at the beginning - // and once at the end is more efficient that repeating it for each block. - let words0 = array_refs!(&jobs[0].words, DEGREE, DEGREE); - let words1 = array_refs!(&jobs[1].words, DEGREE, DEGREE); - let words2 = array_refs!(&jobs[2].words, DEGREE, DEGREE); - let words3 = array_refs!(&jobs[3].words, DEGREE, DEGREE); - let [h0, h1, h2, h3] = transpose_vecs( - loadu(words0.0), - loadu(words1.0), - loadu(words2.0), - loadu(words3.0), - ); - let [h4, h5, h6, h7] = transpose_vecs( - loadu(words0.1), - loadu(words1.1), - loadu(words2.1), - loadu(words3.1), - ); - [h0, h1, h2, h3, h4, h5, h6, h7] -} - -#[inline(always)] -unsafe fn untranspose_state_vecs(h_vecs: &[__m256i; 8], jobs: &mut [Job; DEGREE]) { - // Un-transpose the updated state vectors back into the caller's arrays. - let [job0, job1, job2, job3] = jobs; - let words0 = mut_array_refs!(&mut job0.words, DEGREE, DEGREE); - let words1 = mut_array_refs!(&mut job1.words, DEGREE, DEGREE); - let words2 = mut_array_refs!(&mut job2.words, DEGREE, DEGREE); - let words3 = mut_array_refs!(&mut job3.words, DEGREE, DEGREE); - let out = transpose_vecs(h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3]); - storeu(out[0], words0.0); - storeu(out[1], words1.0); - storeu(out[2], words2.0); - storeu(out[3], words3.0); - let out = transpose_vecs(h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7]); - storeu(out[0], words0.1); - storeu(out[1], words1.1); - storeu(out[2], words2.1); - storeu(out[3], words3.1); -} - -#[inline(always)] -unsafe fn transpose_msg_vecs(blocks: [*const [u8; BLOCKBYTES]; DEGREE]) -> [__m256i; 16] { - // These input arrays have no particular alignment, so we use unaligned - // loads to read from them. - let block0 = blocks[0] as *const [Word; DEGREE]; - let block1 = blocks[1] as *const [Word; DEGREE]; - let block2 = blocks[2] as *const [Word; DEGREE]; - let block3 = blocks[3] as *const [Word; DEGREE]; - let [m0, m1, m2, m3] = transpose_vecs( - loadu(block0.add(0)), - loadu(block1.add(0)), - loadu(block2.add(0)), - loadu(block3.add(0)), - ); - let [m4, m5, m6, m7] = transpose_vecs( - loadu(block0.add(1)), - loadu(block1.add(1)), - loadu(block2.add(1)), - loadu(block3.add(1)), - ); - let [m8, m9, m10, m11] = transpose_vecs( - loadu(block0.add(2)), - loadu(block1.add(2)), - loadu(block2.add(2)), - loadu(block3.add(2)), - ); - let [m12, m13, m14, m15] = transpose_vecs( - loadu(block0.add(3)), - loadu(block1.add(3)), - loadu(block2.add(3)), - loadu(block3.add(3)), - ); - [ - m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, - ] -} - -#[inline(always)] -unsafe fn load_counts(jobs: &[Job; DEGREE]) -> (__m256i, __m256i) { - ( - set4( - count_low(jobs[0].count), - count_low(jobs[1].count), - count_low(jobs[2].count), - count_low(jobs[3].count), - ), - set4( - count_high(jobs[0].count), - count_high(jobs[1].count), - count_high(jobs[2].count), - count_high(jobs[3].count), - ), - ) -} - -#[inline(always)] -unsafe fn store_counts(jobs: &mut [Job; DEGREE], low: __m256i, high: __m256i) { - let low_ints: [Word; DEGREE] = mem::transmute(low); - let high_ints: [Word; DEGREE] = mem::transmute(high); - for i in 0..DEGREE { - jobs[i].count = assemble_count(low_ints[i], high_ints[i]); - } -} - -#[inline(always)] -unsafe fn add_to_counts(lo: &mut __m256i, hi: &mut __m256i, delta: __m256i) { - // If the low counts reach zero, that means they wrapped, unless the delta - // was also zero. - *lo = add(*lo, delta); - let lo_reached_zero = eq(*lo, set1(0)); - let delta_was_zero = eq(delta, set1(0)); - let hi_inc = and(set1(1), negate_and(delta_was_zero, lo_reached_zero)); - *hi = add(*hi, hi_inc); -} - -#[inline(always)] -unsafe fn flags_vec(flags: [bool; DEGREE]) -> __m256i { - set4( - flag_word(flags[0]), - flag_word(flags[1]), - flag_word(flags[2]), - flag_word(flags[3]), - ) -} - -#[target_feature(enable = "avx2")] -pub unsafe fn compress4_loop(jobs: &mut [Job; DEGREE], finalize: Finalize, stride: Stride) { - // If we're not finalizing, there can't be a partial block at the end. - for job in jobs.iter() { - input_debug_asserts(job.input, finalize); - } - - let msg_ptrs = [ - jobs[0].input.as_ptr(), - jobs[1].input.as_ptr(), - jobs[2].input.as_ptr(), - jobs[3].input.as_ptr(), - ]; - let mut h_vecs = transpose_state_vecs(&jobs); - let (mut counts_lo, mut counts_hi) = load_counts(&jobs); - - // Prepare the final blocks (note, which could be empty if the input is - // empty). Do all this before entering the main loop. - let min_len = jobs.iter().map(|job| job.input.len()).min().unwrap(); - let mut fin_offset = min_len.saturating_sub(1); - fin_offset -= fin_offset % stride.padded_blockbytes(); - // Performance note, making these buffers mem::uninitialized() seems to - // cause problems in the optimizer. - let mut buf0: [u8; BLOCKBYTES] = [0; BLOCKBYTES]; - let mut buf1: [u8; BLOCKBYTES] = [0; BLOCKBYTES]; - let mut buf2: [u8; BLOCKBYTES] = [0; BLOCKBYTES]; - let mut buf3: [u8; BLOCKBYTES] = [0; BLOCKBYTES]; - let (block0, len0, finalize0) = final_block(jobs[0].input, fin_offset, &mut buf0, stride); - let (block1, len1, finalize1) = final_block(jobs[1].input, fin_offset, &mut buf1, stride); - let (block2, len2, finalize2) = final_block(jobs[2].input, fin_offset, &mut buf2, stride); - let (block3, len3, finalize3) = final_block(jobs[3].input, fin_offset, &mut buf3, stride); - let fin_blocks: [*const [u8; BLOCKBYTES]; DEGREE] = [block0, block1, block2, block3]; - let fin_counts_delta = set4(len0 as Word, len1 as Word, len2 as Word, len3 as Word); - let fin_last_block; - let fin_last_node; - if finalize.yes() { - fin_last_block = flags_vec([finalize0, finalize1, finalize2, finalize3]); - fin_last_node = flags_vec([ - finalize0 && jobs[0].last_node.yes(), - finalize1 && jobs[1].last_node.yes(), - finalize2 && jobs[2].last_node.yes(), - finalize3 && jobs[3].last_node.yes(), - ]); - } else { - fin_last_block = set1(0); - fin_last_node = set1(0); - } - - // The main loop. - let mut offset = 0; - loop { - let blocks; - let counts_delta; - let last_block; - let last_node; - if offset == fin_offset { - blocks = fin_blocks; - counts_delta = fin_counts_delta; - last_block = fin_last_block; - last_node = fin_last_node; - } else { - blocks = [ - msg_ptrs[0].add(offset) as *const [u8; BLOCKBYTES], - msg_ptrs[1].add(offset) as *const [u8; BLOCKBYTES], - msg_ptrs[2].add(offset) as *const [u8; BLOCKBYTES], - msg_ptrs[3].add(offset) as *const [u8; BLOCKBYTES], - ]; - counts_delta = set1(BLOCKBYTES as Word); - last_block = set1(0); - last_node = set1(0); - }; - - let m_vecs = transpose_msg_vecs(blocks); - add_to_counts(&mut counts_lo, &mut counts_hi, counts_delta); - compress4_transposed!( - &mut h_vecs, - &m_vecs, - counts_lo, - counts_hi, - last_block, - last_node, - ); - - // Check for termination before bumping the offset, to avoid overflow. - if offset == fin_offset { - break; - } - - offset += stride.padded_blockbytes(); - } - - // Write out the results. - untranspose_state_vecs(&h_vecs, &mut *jobs); - store_counts(&mut *jobs, counts_lo, counts_hi); - let max_consumed = offset.saturating_add(stride.padded_blockbytes()); - for job in jobs.iter_mut() { - let consumed = cmp::min(max_consumed, job.input.len()); - job.input = &job.input[consumed..]; - } -} diff --git a/vendor/blake2b_simd/src/blake2bp.rs b/vendor/blake2b_simd/src/blake2bp.rs deleted file mode 100644 index 7bdfad64f6..0000000000 --- a/vendor/blake2b_simd/src/blake2bp.rs +++ /dev/null @@ -1,570 +0,0 @@ -//! BLAKE2bp, a variant of BLAKE2b that uses SIMD more efficiently. -//! -//! The AVX2 implementation of BLAKE2bp is about twice as fast that of BLAKE2b. -//! However, note that it's a different hash function, and it gives a different -//! hash from BLAKE2b for the same input. -//! -//! # Example -//! -//! ``` -//! use blake2b_simd::blake2bp; -//! -//! let hash = blake2bp::Params::new() -//! .hash_length(16) -//! .key(b"The Magic Words are Squeamish Ossifrage") -//! .to_state() -//! .update(b"foo") -//! .update(b"bar") -//! .update(b"baz") -//! .finalize(); -//! assert_eq!("e69c7d2c42a5ac14948772231c68c552", &hash.to_hex()); -//! ``` - -use crate::guts::{Finalize, Implementation, Job, LastNode, Stride}; -use crate::many; -use crate::Count; -use crate::Hash; -use crate::Word; -use crate::BLOCKBYTES; -use crate::KEYBYTES; -use crate::OUTBYTES; -use core::cmp; -use core::fmt; -use core::mem::size_of; - -#[cfg(feature = "std")] -use std; - -pub(crate) const DEGREE: usize = 4; - -/// Compute the BLAKE2bp hash of a slice of bytes all at once, using default -/// parameters. -/// -/// # Example -/// -/// ``` -/// # use blake2b_simd::blake2bp::blake2bp; -/// let expected = "8ca9ccee7946afcb686fe7556628b5ba1bf9a691da37ca58cd049354d99f3704\ -/// 2c007427e5f219b9ab5063707ec6823872dee413ee014b4d02f2ebb6abb5f643"; -/// let hash = blake2bp(b"foo"); -/// assert_eq!(expected, &hash.to_hex()); -/// ``` -pub fn blake2bp(input: &[u8]) -> Hash { - Params::new().hash(input) -} - -/// A parameter builder for BLAKE2bp, just like the [`Params`](../struct.Params.html) type for -/// BLAKE2b. -/// -/// This builder only supports configuring the hash length and a secret key. This matches the -/// options provided by the [reference -/// implementation](https://github.com/BLAKE2/BLAKE2/blob/320c325437539ae91091ce62efec1913cd8093c2/ref/blake2.h#L162-L165). -/// -/// # Example -/// -/// ``` -/// use blake2b_simd::blake2bp; -/// let mut state = blake2bp::Params::new().hash_length(32).to_state(); -/// ``` -#[derive(Clone)] -pub struct Params { - hash_length: u8, - key_length: u8, - key: [u8; KEYBYTES], - implementation: Implementation, -} - -impl Params { - /// Equivalent to `Params::default()`. - pub fn new() -> Self { - Self { - hash_length: OUTBYTES as u8, - key_length: 0, - key: [0; KEYBYTES], - implementation: Implementation::detect(), - } - } - - fn to_words(&self) -> ([[Word; 8]; DEGREE], [Word; 8]) { - let mut base_params = crate::Params::new(); - base_params - .hash_length(self.hash_length as usize) - .key(&self.key[..self.key_length as usize]) - .fanout(DEGREE as u8) - .max_depth(2) - .max_leaf_length(0) - // Note that inner_hash_length is always OUTBYTES, regardless of the hash_length - // parameter. This isn't documented in the spec, but it matches the behavior of the - // reference implementation: https://github.com/BLAKE2/BLAKE2/blob/320c325437539ae91091ce62efec1913cd8093c2/ref/blake2bp-ref.c#L55 - .inner_hash_length(OUTBYTES); - let leaf_words = |worker_index| { - base_params - .clone() - .node_offset(worker_index) - .node_depth(0) - // Note that setting the last_node flag here has no effect, - // because it isn't included in the state words. - .to_words() - }; - let leaf_words = [leaf_words(0), leaf_words(1), leaf_words(2), leaf_words(3)]; - let root_words = base_params - .clone() - .node_offset(0) - .node_depth(1) - // Note that setting the last_node flag here has no effect, because - // it isn't included in the state words. Also note that because - // we're only preserving its state words, the root node won't hash - // any key bytes. - .to_words(); - (leaf_words, root_words) - } - - /// Hash an input all at once with these parameters. - pub fn hash(&self, input: &[u8]) -> Hash { - // If there's a key, just fall back to using the State. - if self.key_length > 0 { - return self.to_state().update(input).finalize(); - } - let (mut leaf_words, mut root_words) = self.to_words(); - // Hash each leaf in parallel. - let jobs = leaf_words.iter_mut().enumerate().map(|(i, words)| { - let input_start = cmp::min(input.len(), i * BLOCKBYTES); - Job { - input: &input[input_start..], - words, - count: 0, - last_node: if i == DEGREE - 1 { - LastNode::Yes - } else { - LastNode::No - }, - } - }); - many::compress_many(jobs, self.implementation, Finalize::Yes, Stride::Parallel); - // Hash each leaf into the root. - finalize_root_words( - &leaf_words, - &mut root_words, - self.hash_length, - self.implementation, - ) - } - - /// Construct a BLAKE2bp `State` object based on these parameters. - pub fn to_state(&self) -> State { - State::with_params(self) - } - - /// Set the length of the final hash, from 1 to `OUTBYTES` (64). Apart from controlling the - /// length of the final `Hash`, this is also associated data, and changing it will result in a - /// totally different hash. - pub fn hash_length(&mut self, length: usize) -> &mut Self { - assert!( - 1 <= length && length <= OUTBYTES, - "Bad hash length: {}", - length - ); - self.hash_length = length as u8; - self - } - - /// Use a secret key, so that BLAKE2bp acts as a MAC. The maximum key length is `KEYBYTES` - /// (64). An empty key is equivalent to having no key at all. - pub fn key(&mut self, key: &[u8]) -> &mut Self { - assert!(key.len() <= KEYBYTES, "Bad key length: {}", key.len()); - self.key_length = key.len() as u8; - self.key = [0; KEYBYTES]; - self.key[..key.len()].copy_from_slice(key); - self - } -} - -impl Default for Params { - fn default() -> Self { - Self::new() - } -} - -impl fmt::Debug for Params { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "Params {{ hash_length: {}, key_length: {} }}", - self.hash_length, - // NB: Don't print the key itself. Debug shouldn't leak secrets. - self.key_length, - ) - } -} - -/// An incremental hasher for BLAKE2bp, just like the [`State`](../struct.State.html) type for -/// BLAKE2b. -/// -/// # Example -/// -/// ``` -/// use blake2b_simd::blake2bp; -/// -/// let mut state = blake2bp::State::new(); -/// state.update(b"foo"); -/// state.update(b"bar"); -/// let hash = state.finalize(); -/// -/// let expected = "e654427b6ef02949471712263e59071abbb6aa94855674c1daeed6cfaf127c33\ -/// dfa3205f7f7f71e4f0673d25fa82a368488911f446bccd323af3ab03f53e56e5"; -/// assert_eq!(expected, &hash.to_hex()); -/// ``` -#[derive(Clone)] -pub struct State { - leaf_words: [[Word; 8]; DEGREE], - root_words: [Word; 8], - // Note that this buffer is twice as large as what compress4 needs. That guarantees that we - // have enough input when we compress to know we don't need to finalize any of the leaves. - buf: [u8; 2 * DEGREE * BLOCKBYTES], - buf_len: u16, - // Note that this is the *per-leaf* count. - count: Count, - hash_length: u8, - implementation: Implementation, - is_keyed: bool, -} - -impl State { - /// Equivalent to `State::default()` or `Params::default().to_state()`. - pub fn new() -> Self { - Self::with_params(&Params::default()) - } - - fn with_params(params: &Params) -> Self { - let (leaf_words, root_words) = params.to_words(); - - // If a key is set, initalize the buffer to contain the key bytes. Note - // that only the leaves hash key bytes. The root doesn't, even though - // the key length it still set in its parameters. Again this isn't - // documented in the spec, but it matches the behavior of the reference - // implementation: - // https://github.com/BLAKE2/BLAKE2/blob/320c325437539ae91091ce62efec1913cd8093c2/ref/blake2bp-ref.c#L128 - // This particular behavior (though not the inner hash length behavior - // above) is also corroborated by the official test vectors; see - // tests/vector_tests.rs. - let mut buf = [0; 2 * DEGREE * BLOCKBYTES]; - let mut buf_len = 0; - if params.key_length > 0 { - for i in 0..DEGREE { - let keybytes = ¶ms.key[..params.key_length as usize]; - buf[i * BLOCKBYTES..][..keybytes.len()].copy_from_slice(keybytes); - buf_len = BLOCKBYTES * DEGREE; - } - } - - Self { - leaf_words, - root_words, - buf, - buf_len: buf_len as u16, - count: 0, // count gets updated in self.compress() - hash_length: params.hash_length, - implementation: params.implementation, - is_keyed: params.key_length > 0, - } - } - - fn fill_buf(&mut self, input: &mut &[u8]) { - let take = cmp::min(self.buf.len() - self.buf_len as usize, input.len()); - self.buf[self.buf_len as usize..][..take].copy_from_slice(&input[..take]); - self.buf_len += take as u16; - *input = &input[take..]; - } - - fn compress_to_leaves( - leaves: &mut [[Word; 8]; DEGREE], - input: &[u8], - count: &mut Count, - implementation: Implementation, - ) { - // Input is assumed to be an even number of blocks for each leaf. Since - // we're not finilizing, debug asserts will fire otherwise. - let jobs = leaves.iter_mut().enumerate().map(|(i, words)| { - Job { - input: &input[i * BLOCKBYTES..], - words, - count: *count, - last_node: LastNode::No, // irrelevant when not finalizing - } - }); - many::compress_many(jobs, implementation, Finalize::No, Stride::Parallel); - // Note that count is the bytes input *per-leaf*. - *count = count.wrapping_add((input.len() / DEGREE) as Count); - } - - /// Add input to the hash. You can call `update` any number of times. - pub fn update(&mut self, mut input: &[u8]) -> &mut Self { - // If we have a partial buffer, try to complete it. If we complete it and there's more - // input waiting, we need to compress to make more room. However, because we need to be - // sure that *none* of the leaves would need to be finalized as part of this round of - // compression, we need to buffer more than we would for BLAKE2b. - if self.buf_len > 0 { - self.fill_buf(&mut input); - // The buffer is large enough for two compressions. If we've filled - // the buffer and there's still more input coming, then we have to - // do at least one compression. If there's enough input still - // coming that all the leaves are guaranteed to get more, do both - // compressions in the buffer. Otherwise, do just one and shift the - // back half of the buffer to the front. - if !input.is_empty() { - if input.len() > (DEGREE - 1) * BLOCKBYTES { - // Enough input coming to do both compressions. - Self::compress_to_leaves( - &mut self.leaf_words, - &self.buf, - &mut self.count, - self.implementation, - ); - self.buf_len = 0; - } else { - // Only enough input coming for one compression. - Self::compress_to_leaves( - &mut self.leaf_words, - &self.buf[..DEGREE * BLOCKBYTES], - &mut self.count, - self.implementation, - ); - self.buf_len = (DEGREE * BLOCKBYTES) as u16; - let (buf_front, buf_back) = self.buf.split_at_mut(DEGREE * BLOCKBYTES); - buf_front.copy_from_slice(buf_back); - } - } - } - - // Now we directly compress as much input as possible, without copying - // it into the buffer. We need to make sure we buffer at least one byte - // for each of the leaves, so that we know we don't need to finalize - // them. - let needed_tail = (DEGREE - 1) * BLOCKBYTES + 1; - let mut bulk_bytes = input.len().saturating_sub(needed_tail); - bulk_bytes -= bulk_bytes % (DEGREE * BLOCKBYTES); - if bulk_bytes > 0 { - Self::compress_to_leaves( - &mut self.leaf_words, - &input[..bulk_bytes], - &mut self.count, - self.implementation, - ); - input = &input[bulk_bytes..]; - } - - // Buffer any remaining input, to be either compressed or finalized in - // a subsequent call. - self.fill_buf(&mut input); - debug_assert_eq!(0, input.len()); - self - } - - /// Finalize the state and return a `Hash`. This method is idempotent, and calling it multiple - /// times will give the same result. It's also possible to `update` with more input in between. - pub fn finalize(&self) -> Hash { - // Hash whatever's remaining in the buffer and finalize the leaves. - let buf_len = self.buf_len as usize; - let mut leaves_copy = self.leaf_words; - let jobs = leaves_copy - .iter_mut() - .enumerate() - .map(|(leaf_index, leaf_words)| { - let input = &self.buf[cmp::min(leaf_index * BLOCKBYTES, buf_len)..buf_len]; - Job { - input, - words: leaf_words, - count: self.count, - last_node: if leaf_index == DEGREE - 1 { - LastNode::Yes - } else { - LastNode::No - }, - } - }); - many::compress_many(jobs, self.implementation, Finalize::Yes, Stride::Parallel); - - // Concatenate each leaf into the root and hash that. - let mut root_words_copy = self.root_words; - finalize_root_words( - &leaves_copy, - &mut root_words_copy, - self.hash_length, - self.implementation, - ) - } - - /// Return the total number of bytes input so far. - /// - /// Note that `count` doesn't include the bytes of the key block, if any. - /// It's exactly the total number of input bytes fed to `update`. - pub fn count(&self) -> Count { - // Remember that self.count is *per-leaf*. - let mut ret = self - .count - .wrapping_mul(DEGREE as Count) - .wrapping_add(self.buf_len as Count); - if self.is_keyed { - ret -= (DEGREE * BLOCKBYTES) as Count; - } - ret - } -} - -#[cfg(feature = "std")] -impl std::io::Write for State { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.update(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} - -impl fmt::Debug for State { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "State {{ count: {}, hash_length: {} }}", - self.count(), - self.hash_length, - ) - } -} - -impl Default for State { - fn default() -> Self { - Self::with_params(&Params::default()) - } -} - -// Compress each of the four finalized hashes into the root words as input, -// using two compressions. Note that even if a future version of this -// implementation supports the hash_length parameter and sets it as associated -// data for all nodes, this step must still use the untruncated output of each -// leaf. Note also that, as mentioned above, the root node doesn't hash any key -// bytes. -fn finalize_root_words( - leaf_words: &[[Word; 8]; DEGREE], - root_words: &mut [Word; 8], - hash_length: u8, - imp: Implementation, -) -> Hash { - debug_assert_eq!(OUTBYTES, 8 * size_of::()); - let mut block = [0; DEGREE * OUTBYTES]; - for (word, chunk) in leaf_words - .iter() - .flat_map(|words| words.iter()) - .zip(block.chunks_exact_mut(size_of::())) - { - chunk.copy_from_slice(&word.to_le_bytes()); - } - imp.compress1_loop( - &block, - root_words, - 0, - LastNode::Yes, - Finalize::Yes, - Stride::Serial, - ); - Hash { - bytes: crate::state_words_to_bytes(&root_words), - len: hash_length, - } -} - -pub(crate) fn force_portable(params: &mut Params) { - params.implementation = Implementation::portable(); -} - -#[cfg(test)] -pub(crate) mod test { - use super::*; - use crate::paint_test_input; - - // This is a simple reference implementation without the complicated buffering or parameter - // support of the real implementation. We need this because the official test vectors don't - // include any inputs large enough to exercise all the branches in the buffering logic. - fn blake2bp_reference(input: &[u8]) -> Hash { - let mut leaves = arrayvec::ArrayVec::<[_; DEGREE]>::new(); - for leaf_index in 0..DEGREE { - leaves.push( - crate::Params::new() - .fanout(DEGREE as u8) - .max_depth(2) - .node_offset(leaf_index as u64) - .inner_hash_length(OUTBYTES) - .to_state(), - ); - } - leaves[DEGREE - 1].set_last_node(true); - for (i, chunk) in input.chunks(BLOCKBYTES).enumerate() { - leaves[i % DEGREE].update(chunk); - } - let mut root = crate::Params::new() - .fanout(DEGREE as u8) - .max_depth(2) - .node_depth(1) - .inner_hash_length(OUTBYTES) - .last_node(true) - .to_state(); - for leaf in &mut leaves { - root.update(leaf.finalize().as_bytes()); - } - root.finalize() - } - - #[test] - fn test_against_reference() { - let mut buf = [0; 21 * BLOCKBYTES]; - paint_test_input(&mut buf); - // - 8 blocks is just enought to fill the double buffer. - // - 9 blocks triggers the "perform one compression on the double buffer" case. - // - 11 blocks is the largest input where only one compression may be performed, on the - // first half of the buffer, because there's not enough input to avoid needing to - // finalize the second half. - // - 12 blocks triggers the "perform both compressions in the double buffer" case. - // - 15 blocks is the largest input where, after compressing 8 blocks from the buffer, - // there's not enough input to hash directly from memory. - // - 16 blocks triggers "after emptying the buffer, hash directly from memory". - for num_blocks in 0..=20 { - for &extra in &[0, 1, BLOCKBYTES - 1] { - for &portable in &[false, true] { - // eprintln!("\ncase -----"); - // dbg!(num_blocks); - // dbg!(extra); - // dbg!(portable); - - // First hash the input all at once, as a sanity check. - let mut params = Params::new(); - if portable { - force_portable(&mut params); - } - let input = &buf[..num_blocks * BLOCKBYTES + extra]; - let expected = blake2bp_reference(&input); - let mut state = params.to_state(); - let found = state.update(input).finalize(); - assert_eq!(expected, found); - - // Then, do it again, but buffer 1 byte of input first. That causes the buffering - // branch to trigger. - let mut state = params.to_state(); - let maybe_one = cmp::min(1, input.len()); - state.update(&input[..maybe_one]); - assert_eq!(maybe_one as Count, state.count()); - // Do a throwaway finalize here to check for idempotency. - state.finalize(); - state.update(&input[maybe_one..]); - assert_eq!(input.len() as Count, state.count()); - let found = state.finalize(); - assert_eq!(expected, found); - - // Finally, do it again with the all-at-once interface. - assert_eq!(expected, blake2bp(input)); - } - } - } - } -} diff --git a/vendor/blake2b_simd/src/guts.rs b/vendor/blake2b_simd/src/guts.rs deleted file mode 100644 index 9fcacf319c..0000000000 --- a/vendor/blake2b_simd/src/guts.rs +++ /dev/null @@ -1,565 +0,0 @@ -use crate::*; -use arrayref::array_ref; -use core::cmp; - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -pub const MAX_DEGREE: usize = 4; - -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -pub const MAX_DEGREE: usize = 1; - -// Variants other than Portable are unreachable in no_std, unless CPU features -// are explicitly enabled for the build with e.g. RUSTFLAGS="-C target-feature=avx2". -// This might change in the future if is_x86_feature_detected moves into libcore. -#[allow(dead_code)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum Platform { - Portable, - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - SSE41, - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - AVX2, -} - -#[derive(Clone, Copy, Debug)] -pub struct Implementation(Platform); - -impl Implementation { - pub fn detect() -> Self { - // Try the different implementations in order of how fast/modern they - // are. Currently on non-x86, everything just uses portable. - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { - if let Some(avx2_impl) = Self::avx2_if_supported() { - return avx2_impl; - } - } - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { - if let Some(sse41_impl) = Self::sse41_if_supported() { - return sse41_impl; - } - } - Self::portable() - } - - pub fn portable() -> Self { - Implementation(Platform::Portable) - } - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - #[allow(unreachable_code)] - pub fn sse41_if_supported() -> Option { - // Check whether SSE4.1 support is assumed by the build. - #[cfg(target_feature = "sse4.1")] - { - return Some(Implementation(Platform::SSE41)); - } - // Otherwise dynamically check for support if we can. - #[cfg(feature = "std")] - { - if is_x86_feature_detected!("sse4.1") { - return Some(Implementation(Platform::SSE41)); - } - } - None - } - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - #[allow(unreachable_code)] - pub fn avx2_if_supported() -> Option { - // Check whether AVX2 support is assumed by the build. - #[cfg(target_feature = "avx2")] - { - return Some(Implementation(Platform::AVX2)); - } - // Otherwise dynamically check for support if we can. - #[cfg(feature = "std")] - { - if is_x86_feature_detected!("avx2") { - return Some(Implementation(Platform::AVX2)); - } - } - None - } - - pub fn degree(&self) -> usize { - match self.0 { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - Platform::AVX2 => avx2::DEGREE, - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - Platform::SSE41 => sse41::DEGREE, - Platform::Portable => 1, - } - } - - pub fn compress1_loop( - &self, - input: &[u8], - words: &mut [Word; 8], - count: Count, - last_node: LastNode, - finalize: Finalize, - stride: Stride, - ) { - match self.0 { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - Platform::AVX2 => unsafe { - avx2::compress1_loop(input, words, count, last_node, finalize, stride); - }, - // Note that there's an SSE version of compress1 in the official C - // implementation, but I haven't ported it yet. - _ => { - portable::compress1_loop(input, words, count, last_node, finalize, stride); - } - } - } - - pub fn compress2_loop(&self, jobs: &mut [Job; 2], finalize: Finalize, stride: Stride) { - match self.0 { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - Platform::AVX2 | Platform::SSE41 => unsafe { - sse41::compress2_loop(jobs, finalize, stride) - }, - _ => panic!("unsupported"), - } - } - - pub fn compress4_loop(&self, jobs: &mut [Job; 4], finalize: Finalize, stride: Stride) { - match self.0 { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - Platform::AVX2 => unsafe { avx2::compress4_loop(jobs, finalize, stride) }, - _ => panic!("unsupported"), - } - } -} - -pub struct Job<'a, 'b> { - pub input: &'a [u8], - pub words: &'b mut [Word; 8], - pub count: Count, - pub last_node: LastNode, -} - -impl<'a, 'b> core::fmt::Debug for Job<'a, 'b> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // NB: Don't print the words. Leaking them would allow length extension. - write!( - f, - "Job {{ input_len: {}, count: {}, last_node: {} }}", - self.input.len(), - self.count, - self.last_node.yes(), - ) - } -} - -// Finalize could just be a bool, but this is easier to read at callsites. -#[derive(Clone, Copy, Debug)] -pub enum Finalize { - Yes, - No, -} - -impl Finalize { - pub fn yes(&self) -> bool { - match self { - Finalize::Yes => true, - Finalize::No => false, - } - } -} - -// Like Finalize, this is easier to read at callsites. -#[derive(Clone, Copy, Debug)] -pub enum LastNode { - Yes, - No, -} - -impl LastNode { - pub fn yes(&self) -> bool { - match self { - LastNode::Yes => true, - LastNode::No => false, - } - } -} - -#[derive(Clone, Copy, Debug)] -pub enum Stride { - Serial, // BLAKE2b/BLAKE2s - Parallel, // BLAKE2bp/BLAKE2sp -} - -impl Stride { - pub fn padded_blockbytes(&self) -> usize { - match self { - Stride::Serial => BLOCKBYTES, - Stride::Parallel => blake2bp::DEGREE * BLOCKBYTES, - } - } -} - -pub(crate) fn count_low(count: Count) -> Word { - count as Word -} - -pub(crate) fn count_high(count: Count) -> Word { - (count >> 8 * size_of::()) as Word -} - -pub(crate) fn assemble_count(low: Word, high: Word) -> Count { - low as Count + ((high as Count) << 8 * size_of::()) -} - -pub(crate) fn flag_word(flag: bool) -> Word { - if flag { - !0 - } else { - 0 - } -} - -// Pull a array reference at the given offset straight from the input, if -// there's a full block of input available. If there's only a partial block, -// copy it into the provided buffer, and return an array reference that. Along -// with the array, return the number of bytes of real input, and whether the -// input can be finalized (i.e. whether there aren't any more bytes after this -// block). Note that this is written so that the optimizer can elide bounds -// checks, see: https://godbolt.org/z/0hH2bC -pub fn final_block<'a>( - input: &'a [u8], - offset: usize, - buffer: &'a mut [u8; BLOCKBYTES], - stride: Stride, -) -> (&'a [u8; BLOCKBYTES], usize, bool) { - let capped_offset = cmp::min(offset, input.len()); - let offset_slice = &input[capped_offset..]; - if offset_slice.len() >= BLOCKBYTES { - let block = array_ref!(offset_slice, 0, BLOCKBYTES); - let should_finalize = offset_slice.len() <= stride.padded_blockbytes(); - (block, BLOCKBYTES, should_finalize) - } else { - // Copy the final block to the front of the block buffer. The rest of - // the buffer is assumed to be initialized to zero. - buffer[..offset_slice.len()].copy_from_slice(offset_slice); - (buffer, offset_slice.len(), true) - } -} - -pub fn input_debug_asserts(input: &[u8], finalize: Finalize) { - // If we're not finalizing, the input must not be empty, and it must be an - // even multiple of the block size. - if !finalize.yes() { - debug_assert!(!input.is_empty()); - debug_assert_eq!(0, input.len() % BLOCKBYTES); - } -} - -#[cfg(test)] -mod test { - use super::*; - use arrayvec::ArrayVec; - use core::mem::size_of; - - #[test] - fn test_detection() { - assert_eq!(Platform::Portable, Implementation::portable().0); - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - #[cfg(feature = "std")] - { - if is_x86_feature_detected!("avx2") { - assert_eq!(Platform::AVX2, Implementation::detect().0); - assert_eq!( - Platform::AVX2, - Implementation::avx2_if_supported().unwrap().0 - ); - assert_eq!( - Platform::SSE41, - Implementation::sse41_if_supported().unwrap().0 - ); - } else if is_x86_feature_detected!("sse4.1") { - assert_eq!(Platform::SSE41, Implementation::detect().0); - assert!(Implementation::avx2_if_supported().is_none()); - assert_eq!( - Platform::SSE41, - Implementation::sse41_if_supported().unwrap().0 - ); - } else { - assert_eq!(Platform::Portable, Implementation::detect().0); - assert!(Implementation::avx2_if_supported().is_none()); - assert!(Implementation::sse41_if_supported().is_none()); - } - } - } - - // TODO: Move all of these case tests into the implementation files. - fn exercise_cases(mut f: F) - where - F: FnMut(Stride, usize, LastNode, Finalize, Count), - { - // Chose counts to hit the relevant overflow cases. - let counts = &[ - (0 as Count), - ((1 as Count) << (8 * size_of::())) - BLOCKBYTES as Count, - (0 as Count).wrapping_sub(BLOCKBYTES as Count), - ]; - for &stride in &[Stride::Serial, Stride::Parallel] { - let lengths = [ - 0, - 1, - BLOCKBYTES - 1, - BLOCKBYTES, - BLOCKBYTES + 1, - 2 * BLOCKBYTES - 1, - 2 * BLOCKBYTES, - 2 * BLOCKBYTES + 1, - stride.padded_blockbytes() - 1, - stride.padded_blockbytes(), - stride.padded_blockbytes() + 1, - 2 * stride.padded_blockbytes() - 1, - 2 * stride.padded_blockbytes(), - 2 * stride.padded_blockbytes() + 1, - ]; - for &length in &lengths { - for &last_node in &[LastNode::No, LastNode::Yes] { - for &finalize in &[Finalize::No, Finalize::Yes] { - if !finalize.yes() && (length == 0 || length % BLOCKBYTES != 0) { - // Skip these cases, they're invalid. - continue; - } - for &count in counts { - // eprintln!("\ncase -----"); - // dbg!(stride); - // dbg!(length); - // dbg!(last_node); - // dbg!(finalize); - // dbg!(count); - - f(stride, length, last_node, finalize, count); - } - } - } - } - } - } - - fn initial_test_words(input_index: usize) -> [Word; 8] { - crate::Params::new() - .node_offset(input_index as u64) - .to_words() - } - - // Use the portable implementation, one block at a time, to compute the - // final state words expected for a given test case. - fn reference_compression( - input: &[u8], - stride: Stride, - last_node: LastNode, - finalize: Finalize, - mut count: Count, - input_index: usize, - ) -> [Word; 8] { - let mut words = initial_test_words(input_index); - let mut offset = 0; - while offset == 0 || offset < input.len() { - let block_size = cmp::min(BLOCKBYTES, input.len() - offset); - let maybe_finalize = if offset + stride.padded_blockbytes() < input.len() { - Finalize::No - } else { - finalize - }; - portable::compress1_loop( - &input[offset..][..block_size], - &mut words, - count, - last_node, - maybe_finalize, - Stride::Serial, - ); - offset += stride.padded_blockbytes(); - count = count.wrapping_add(BLOCKBYTES as Count); - } - words - } - - // For various loop lengths and finalization parameters, make sure that the - // implementation gives the same answer as the portable implementation does - // when invoked one block at a time. (So even the portable implementation - // itself is being tested here, to make sure its loop is correct.) Note - // that this doesn't include any fixed test vectors; those are taken from - // the blake2-kat.json file (copied from upstream) and tested elsewhere. - fn exercise_compress1_loop(implementation: Implementation) { - let mut input = [0; 100 * BLOCKBYTES]; - paint_test_input(&mut input); - - exercise_cases(|stride, length, last_node, finalize, count| { - let reference_words = - reference_compression(&input[..length], stride, last_node, finalize, count, 0); - - let mut test_words = initial_test_words(0); - implementation.compress1_loop( - &input[..length], - &mut test_words, - count, - last_node, - finalize, - stride, - ); - assert_eq!(reference_words, test_words); - }); - } - - #[test] - fn test_compress1_loop_portable() { - exercise_compress1_loop(Implementation::portable()); - } - - #[test] - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn test_compress1_loop_sse41() { - // Currently this just falls back to portable, but we test it anyway. - if let Some(imp) = Implementation::sse41_if_supported() { - exercise_compress1_loop(imp); - } - } - - #[test] - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn test_compress1_loop_avx2() { - if let Some(imp) = Implementation::avx2_if_supported() { - exercise_compress1_loop(imp); - } - } - - // I use ArrayVec everywhere in here becuase currently these tests pass - // under no_std. I might decide that's not worth maintaining at some point, - // since really all we care about with no_std is that the library builds, - // but for now it's here. Everything is keyed off of this N constant so - // that it's easy to copy the code to exercise_compress4_loop. - fn exercise_compress2_loop(implementation: Implementation) { - const N: usize = 2; - - let mut input_buffer = [0; 100 * BLOCKBYTES]; - paint_test_input(&mut input_buffer); - let mut inputs = ArrayVec::<[_; N]>::new(); - for i in 0..N { - inputs.push(&input_buffer[i..]); - } - - exercise_cases(|stride, length, last_node, finalize, count| { - let mut reference_words = ArrayVec::<[_; N]>::new(); - for i in 0..N { - let words = reference_compression( - &inputs[i][..length], - stride, - last_node, - finalize, - count.wrapping_add((i * BLOCKBYTES) as Count), - i, - ); - reference_words.push(words); - } - - let mut test_words = ArrayVec::<[_; N]>::new(); - for i in 0..N { - test_words.push(initial_test_words(i)); - } - let mut jobs = ArrayVec::<[_; N]>::new(); - for (i, words) in test_words.iter_mut().enumerate() { - jobs.push(Job { - input: &inputs[i][..length], - words, - count: count.wrapping_add((i * BLOCKBYTES) as Count), - last_node, - }); - } - let mut jobs = jobs.into_inner().expect("full"); - implementation.compress2_loop(&mut jobs, finalize, stride); - - for i in 0..N { - assert_eq!(reference_words[i], test_words[i], "words {} unequal", i); - } - }); - } - - #[test] - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn test_compress2_loop_sse41() { - if let Some(imp) = Implementation::sse41_if_supported() { - exercise_compress2_loop(imp); - } - } - - #[test] - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn test_compress2_loop_avx2() { - // Currently this just falls back to SSE4.1, but we test it anyway. - if let Some(imp) = Implementation::avx2_if_supported() { - exercise_compress2_loop(imp); - } - } - - // Copied from exercise_compress2_loop, with a different value of N and an - // interior call to compress4_loop. - fn exercise_compress4_loop(implementation: Implementation) { - const N: usize = 4; - - let mut input_buffer = [0; 100 * BLOCKBYTES]; - paint_test_input(&mut input_buffer); - let mut inputs = ArrayVec::<[_; N]>::new(); - for i in 0..N { - inputs.push(&input_buffer[i..]); - } - - exercise_cases(|stride, length, last_node, finalize, count| { - let mut reference_words = ArrayVec::<[_; N]>::new(); - for i in 0..N { - let words = reference_compression( - &inputs[i][..length], - stride, - last_node, - finalize, - count.wrapping_add((i * BLOCKBYTES) as Count), - i, - ); - reference_words.push(words); - } - - let mut test_words = ArrayVec::<[_; N]>::new(); - for i in 0..N { - test_words.push(initial_test_words(i)); - } - let mut jobs = ArrayVec::<[_; N]>::new(); - for (i, words) in test_words.iter_mut().enumerate() { - jobs.push(Job { - input: &inputs[i][..length], - words, - count: count.wrapping_add((i * BLOCKBYTES) as Count), - last_node, - }); - } - let mut jobs = jobs.into_inner().expect("full"); - implementation.compress4_loop(&mut jobs, finalize, stride); - - for i in 0..N { - assert_eq!(reference_words[i], test_words[i], "words {} unequal", i); - } - }); - } - - #[test] - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn test_compress4_loop_avx2() { - if let Some(imp) = Implementation::avx2_if_supported() { - exercise_compress4_loop(imp); - } - } - - #[test] - fn sanity_check_count_size() { - assert_eq!(size_of::(), 2 * size_of::()); - } -} diff --git a/vendor/blake2b_simd/src/lib.rs b/vendor/blake2b_simd/src/lib.rs deleted file mode 100644 index cadef7f9a9..0000000000 --- a/vendor/blake2b_simd/src/lib.rs +++ /dev/null @@ -1,674 +0,0 @@ -//! [![GitHub](https://img.shields.io/github/tag/oconnor663/blake2_simd.svg?label=GitHub)](https://github.com/oconnor663/blake2_simd) [![crates.io](https://img.shields.io/crates/v/blake2b_simd.svg)](https://crates.io/crates/blake2b_simd) [![Build Status](https://travis-ci.org/oconnor663/blake2_simd.svg?branch=master)](https://travis-ci.org/oconnor663/blake2_simd) -//! -//! An implementation of the BLAKE2b and BLAKE2bp hash functions. See also -//! [`blake2s_simd`](https://docs.rs/blake2s_simd). -//! -//! This crate includes: -//! -//! - 100% stable Rust. -//! - SIMD implementations based on Samuel Neves' [`blake2-avx2`](https://github.com/sneves/blake2-avx2). -//! These are very fast. For benchmarks, see [the Performance section of the -//! README](https://github.com/oconnor663/blake2_simd#performance). -//! - Portable, safe implementations for other platforms. -//! - Dynamic CPU feature detection. Binaries include multiple implementations by default and -//! choose the fastest one the processor supports at runtime. -//! - All the features from the [the BLAKE2 spec](https://blake2.net/blake2.pdf), like adjustable -//! length, keying, and associated data for tree hashing. -//! - `no_std` support. The `std` Cargo feature is on by default, for CPU feature detection and -//! for implementing `std::io::Write`. -//! - Support for computing multiple BLAKE2b hashes in parallel, matching the efficiency of -//! BLAKE2bp. See the [`many`](many/index.html) module. -//! -//! # Example -//! -//! ``` -//! use blake2b_simd::{blake2b, Params}; -//! -//! let expected = "ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6d\ -//! c1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d"; -//! let hash = blake2b(b"foo"); -//! assert_eq!(expected, &hash.to_hex()); -//! -//! let hash = Params::new() -//! .hash_length(16) -//! .key(b"The Magic Words are Squeamish Ossifrage") -//! .personal(b"L. P. Waterhouse") -//! .to_state() -//! .update(b"foo") -//! .update(b"bar") -//! .update(b"baz") -//! .finalize(); -//! assert_eq!("ee8ff4e9be887297cf79348dc35dab56", &hash.to_hex()); -//! ``` - -#![cfg_attr(not(feature = "std"), no_std)] - -use arrayref::{array_refs, mut_array_refs}; -use core::cmp; -use core::fmt; -use core::mem::size_of; - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -mod avx2; -mod portable; -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -mod sse41; - -pub mod blake2bp; -mod guts; -pub mod many; - -#[cfg(test)] -mod test; - -type Word = u64; -type Count = u128; - -/// The max hash length. -pub const OUTBYTES: usize = 8 * size_of::(); -/// The max key length. -pub const KEYBYTES: usize = 8 * size_of::(); -/// The max salt length. -pub const SALTBYTES: usize = 2 * size_of::(); -/// The max personalization length. -pub const PERSONALBYTES: usize = 2 * size_of::(); -/// The number input bytes passed to each call to the compression function. Small benchmarks need -/// to use an even multiple of `BLOCKBYTES`, or else their apparent throughput will be low. -pub const BLOCKBYTES: usize = 16 * size_of::(); - -const IV: [Word; 8] = [ - 0x6A09E667F3BCC908, - 0xBB67AE8584CAA73B, - 0x3C6EF372FE94F82B, - 0xA54FF53A5F1D36F1, - 0x510E527FADE682D1, - 0x9B05688C2B3E6C1F, - 0x1F83D9ABFB41BD6B, - 0x5BE0CD19137E2179, -]; - -const SIGMA: [[u8; 16]; 12] = [ - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], - [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], - [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], - [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], - [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], - [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], - [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], - [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], -]; - -/// Compute the BLAKE2b hash of a slice of bytes all at once, using default -/// parameters. -/// -/// # Example -/// -/// ``` -/// # use blake2b_simd::{blake2b, Params}; -/// let expected = "ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6d\ -/// c1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d"; -/// let hash = blake2b(b"foo"); -/// assert_eq!(expected, &hash.to_hex()); -/// ``` -pub fn blake2b(input: &[u8]) -> Hash { - Params::new().hash(input) -} - -/// A parameter builder that exposes all the non-default BLAKE2 features. -/// -/// Apart from `hash_length`, which controls the length of the final `Hash`, -/// all of these parameters are just associated data that gets mixed with the -/// input. For more details, see [the BLAKE2 spec](https://blake2.net/blake2.pdf). -/// -/// Several of the parameters have a valid range defined in the spec and -/// documented below. Trying to set an invalid parameter will panic. -/// -/// # Example -/// -/// ``` -/// # use blake2b_simd::Params; -/// // Create a Params object with a secret key and a non-default length. -/// let mut params = Params::new(); -/// params.key(b"my secret key"); -/// params.hash_length(16); -/// -/// // Use those params to hash an input all at once. -/// let hash = params.hash(b"my input"); -/// -/// // Or use those params to build an incremental State. -/// let mut state = params.to_state(); -/// ``` -#[derive(Clone)] -pub struct Params { - hash_length: u8, - key_length: u8, - key_block: [u8; BLOCKBYTES], - salt: [u8; SALTBYTES], - personal: [u8; PERSONALBYTES], - fanout: u8, - max_depth: u8, - max_leaf_length: u32, - node_offset: u64, - node_depth: u8, - inner_hash_length: u8, - last_node: guts::LastNode, - implementation: guts::Implementation, -} - -impl Params { - /// Equivalent to `Params::default()`. - #[inline] - pub fn new() -> Self { - Self { - hash_length: OUTBYTES as u8, - key_length: 0, - key_block: [0; BLOCKBYTES], - salt: [0; SALTBYTES], - personal: [0; PERSONALBYTES], - // NOTE: fanout and max_depth don't default to zero! - fanout: 1, - max_depth: 1, - max_leaf_length: 0, - node_offset: 0, - node_depth: 0, - inner_hash_length: 0, - last_node: guts::LastNode::No, - implementation: guts::Implementation::detect(), - } - } - - #[inline(always)] - fn to_words(&self) -> [Word; 8] { - let (salt_left, salt_right) = array_refs!(&self.salt, SALTBYTES / 2, SALTBYTES / 2); - let (personal_left, personal_right) = - array_refs!(&self.personal, PERSONALBYTES / 2, PERSONALBYTES / 2); - [ - IV[0] - ^ self.hash_length as u64 - ^ (self.key_length as u64) << 8 - ^ (self.fanout as u64) << 16 - ^ (self.max_depth as u64) << 24 - ^ (self.max_leaf_length as u64) << 32, - IV[1] ^ self.node_offset, - IV[2] ^ self.node_depth as u64 ^ (self.inner_hash_length as u64) << 8, - IV[3], - IV[4] ^ Word::from_le_bytes(*salt_left), - IV[5] ^ Word::from_le_bytes(*salt_right), - IV[6] ^ Word::from_le_bytes(*personal_left), - IV[7] ^ Word::from_le_bytes(*personal_right), - ] - } - - /// Hash an input all at once with these parameters. - #[inline] - pub fn hash(&self, input: &[u8]) -> Hash { - // If there's a key, just fall back to using the State. - if self.key_length > 0 { - return self.to_state().update(input).finalize(); - } - let mut words = self.to_words(); - self.implementation.compress1_loop( - input, - &mut words, - 0, - self.last_node, - guts::Finalize::Yes, - guts::Stride::Serial, - ); - Hash { - bytes: state_words_to_bytes(&words), - len: self.hash_length, - } - } - - /// Construct a `State` object based on these parameters, for hashing input - /// incrementally. - pub fn to_state(&self) -> State { - State::with_params(self) - } - - /// Set the length of the final hash in bytes, from 1 to `OUTBYTES` (64). Apart from - /// controlling the length of the final `Hash`, this is also associated data, and changing it - /// will result in a totally different hash. - #[inline] - pub fn hash_length(&mut self, length: usize) -> &mut Self { - assert!( - 1 <= length && length <= OUTBYTES, - "Bad hash length: {}", - length - ); - self.hash_length = length as u8; - self - } - - /// Use a secret key, so that BLAKE2 acts as a MAC. The maximum key length is `KEYBYTES` (64). - /// An empty key is equivalent to having no key at all. - #[inline] - pub fn key(&mut self, key: &[u8]) -> &mut Self { - assert!(key.len() <= KEYBYTES, "Bad key length: {}", key.len()); - self.key_length = key.len() as u8; - self.key_block = [0; BLOCKBYTES]; - self.key_block[..key.len()].copy_from_slice(key); - self - } - - /// At most `SALTBYTES` (16). Shorter salts are padded with null bytes. An empty salt is - /// equivalent to having no salt at all. - #[inline] - pub fn salt(&mut self, salt: &[u8]) -> &mut Self { - assert!(salt.len() <= SALTBYTES, "Bad salt length: {}", salt.len()); - self.salt = [0; SALTBYTES]; - self.salt[..salt.len()].copy_from_slice(salt); - self - } - - /// At most `PERSONALBYTES` (16). Shorter personalizations are padded with null bytes. An empty - /// personalization is equivalent to having no personalization at all. - #[inline] - pub fn personal(&mut self, personalization: &[u8]) -> &mut Self { - assert!( - personalization.len() <= PERSONALBYTES, - "Bad personalization length: {}", - personalization.len() - ); - self.personal = [0; PERSONALBYTES]; - self.personal[..personalization.len()].copy_from_slice(personalization); - self - } - - /// From 0 (meaning unlimited) to 255. The default is 1 (meaning sequential). - #[inline] - pub fn fanout(&mut self, fanout: u8) -> &mut Self { - self.fanout = fanout; - self - } - - /// From 0 (meaning BLAKE2X B2 hashes), through 1 (the default, meaning sequential) to 255 (meaning unlimited). - #[inline] - pub fn max_depth(&mut self, depth: u8) -> &mut Self { - self.max_depth = depth; - self - } - - /// From 0 (the default, meaning unlimited or sequential) to `2^32 - 1`. - #[inline] - pub fn max_leaf_length(&mut self, length: u32) -> &mut Self { - self.max_leaf_length = length; - self - } - - /// From 0 (the default, meaning first, leftmost, leaf, or sequential) to `2^64 - 1`. - #[inline] - pub fn node_offset(&mut self, offset: u64) -> &mut Self { - self.node_offset = offset; - self - } - - /// From 0 (the default, meaning leaf or sequential) to 255. - #[inline] - pub fn node_depth(&mut self, depth: u8) -> &mut Self { - self.node_depth = depth; - self - } - - /// From 0 (the default, meaning sequential) to `OUTBYTES` (64). - #[inline] - pub fn inner_hash_length(&mut self, length: usize) -> &mut Self { - assert!(length <= OUTBYTES, "Bad inner hash length: {}", length); - self.inner_hash_length = length as u8; - self - } - - /// Indicates the rightmost node in a row. This can also be changed on the - /// `State` object, potentially after hashing has begun. See - /// [`State::set_last_node`]. - /// - /// [`State::set_last_node`]: struct.State.html#method.set_last_node - #[inline] - pub fn last_node(&mut self, last_node: bool) -> &mut Self { - self.last_node = if last_node { - guts::LastNode::Yes - } else { - guts::LastNode::No - }; - self - } -} - -impl Default for Params { - fn default() -> Self { - Self::new() - } -} - -impl fmt::Debug for Params { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "Params {{ hash_length: {}, key_length: {}, salt: {:?}, personal: {:?}, fanout: {}, \ - max_depth: {}, max_leaf_length: {}, node_offset: {}, node_depth: {}, \ - inner_hash_length: {}, last_node: {} }}", - self.hash_length, - // NB: Don't print the key itself. Debug shouldn't leak secrets. - self.key_length, - &self.salt, - &self.personal, - self.fanout, - self.max_depth, - self.max_leaf_length, - self.node_offset, - self.node_depth, - self.inner_hash_length, - self.last_node.yes(), - ) - } -} - -/// An incremental hasher for BLAKE2b. -/// -/// To construct a `State` with non-default parameters, see `Params::to_state`. -/// -/// # Example -/// -/// ``` -/// use blake2b_simd::{State, blake2b}; -/// -/// let mut state = blake2b_simd::State::new(); -/// -/// state.update(b"foo"); -/// assert_eq!(blake2b(b"foo"), state.finalize()); -/// -/// state.update(b"bar"); -/// assert_eq!(blake2b(b"foobar"), state.finalize()); -/// ``` -#[derive(Clone)] -pub struct State { - words: [Word; 8], - count: Count, - buf: [u8; BLOCKBYTES], - buflen: u8, - last_node: guts::LastNode, - hash_length: u8, - implementation: guts::Implementation, - is_keyed: bool, -} - -impl State { - /// Equivalent to `State::default()` or `Params::default().to_state()`. - pub fn new() -> Self { - Self::with_params(&Params::default()) - } - - fn with_params(params: &Params) -> Self { - let mut state = Self { - words: params.to_words(), - count: 0, - buf: [0; BLOCKBYTES], - buflen: 0, - last_node: params.last_node, - hash_length: params.hash_length, - implementation: params.implementation, - is_keyed: params.key_length > 0, - }; - if state.is_keyed { - state.buf = params.key_block; - state.buflen = state.buf.len() as u8; - } - state - } - - fn fill_buf(&mut self, input: &mut &[u8]) { - let take = cmp::min(BLOCKBYTES - self.buflen as usize, input.len()); - self.buf[self.buflen as usize..self.buflen as usize + take].copy_from_slice(&input[..take]); - self.buflen += take as u8; - *input = &input[take..]; - } - - // If the state already has some input in its buffer, try to fill the buffer and perform a - // compression. However, only do the compression if there's more input coming, otherwise it - // will give the wrong hash it the caller finalizes immediately after. - fn compress_buffer_if_possible(&mut self, input: &mut &[u8]) { - if self.buflen > 0 { - self.fill_buf(input); - if !input.is_empty() { - self.implementation.compress1_loop( - &self.buf, - &mut self.words, - self.count, - self.last_node, - guts::Finalize::No, - guts::Stride::Serial, - ); - self.count = self.count.wrapping_add(BLOCKBYTES as Count); - self.buflen = 0; - } - } - } - - /// Add input to the hash. You can call `update` any number of times. - pub fn update(&mut self, mut input: &[u8]) -> &mut Self { - // If we have a partial buffer, try to complete it. - self.compress_buffer_if_possible(&mut input); - // While there's more than a block of input left (which also means we cleared the buffer - // above), compress blocks directly without copying. - let mut end = input.len().saturating_sub(1); - end -= end % BLOCKBYTES; - if end > 0 { - self.implementation.compress1_loop( - &input[..end], - &mut self.words, - self.count, - self.last_node, - guts::Finalize::No, - guts::Stride::Serial, - ); - self.count = self.count.wrapping_add(end as Count); - input = &input[end..]; - } - // Buffer any remaining input, to be either compressed or finalized in a subsequent call. - // Note that this represents some copying overhead, which in theory we could avoid in - // all-at-once setting. A function hardcoded for exactly BLOCKSIZE input bytes is about 10% - // faster than using this implementation for the same input. - self.fill_buf(&mut input); - self - } - - /// Finalize the state and return a `Hash`. This method is idempotent, and calling it multiple - /// times will give the same result. It's also possible to `update` with more input in between. - pub fn finalize(&self) -> Hash { - let mut words_copy = self.words; - self.implementation.compress1_loop( - &self.buf[..self.buflen as usize], - &mut words_copy, - self.count, - self.last_node, - guts::Finalize::Yes, - guts::Stride::Serial, - ); - Hash { - bytes: state_words_to_bytes(&words_copy), - len: self.hash_length, - } - } - - /// Set a flag indicating that this is the last node of its level in a tree hash. This is - /// equivalent to [`Params::last_node`], except that it can be set at any time before calling - /// `finalize`. That allows callers to begin hashing a node without knowing ahead of time - /// whether it's the last in its level. For more details about the intended use of this flag - /// [the BLAKE2 spec]. - /// - /// [`Params::last_node`]: struct.Params.html#method.last_node - /// [the BLAKE2 spec]: https://blake2.net/blake2.pdf - pub fn set_last_node(&mut self, last_node: bool) -> &mut Self { - self.last_node = if last_node { - guts::LastNode::Yes - } else { - guts::LastNode::No - }; - self - } - - /// Return the total number of bytes input so far. - /// - /// Note that `count` doesn't include the bytes of the key block, if any. - /// It's exactly the total number of input bytes fed to `update`. - pub fn count(&self) -> Count { - let mut ret = self.count.wrapping_add(self.buflen as Count); - if self.is_keyed { - ret -= BLOCKBYTES as Count; - } - ret - } -} - -#[inline(always)] -fn state_words_to_bytes(state_words: &[Word; 8]) -> [u8; OUTBYTES] { - let mut bytes = [0; OUTBYTES]; - { - const W: usize = size_of::(); - let refs = mut_array_refs!(&mut bytes, W, W, W, W, W, W, W, W); - *refs.0 = state_words[0].to_le_bytes(); - *refs.1 = state_words[1].to_le_bytes(); - *refs.2 = state_words[2].to_le_bytes(); - *refs.3 = state_words[3].to_le_bytes(); - *refs.4 = state_words[4].to_le_bytes(); - *refs.5 = state_words[5].to_le_bytes(); - *refs.6 = state_words[6].to_le_bytes(); - *refs.7 = state_words[7].to_le_bytes(); - } - bytes -} - -#[cfg(feature = "std")] -impl std::io::Write for State { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.update(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} - -impl fmt::Debug for State { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // NB: Don't print the words. Leaking them would allow length extension. - write!( - f, - "State {{ count: {}, hash_length: {}, last_node: {} }}", - self.count(), - self.hash_length, - self.last_node.yes(), - ) - } -} - -impl Default for State { - fn default() -> Self { - Self::with_params(&Params::default()) - } -} - -type HexString = arrayvec::ArrayString<[u8; 2 * OUTBYTES]>; - -/// A finalized BLAKE2 hash, with constant-time equality. -#[derive(Clone, Copy)] -pub struct Hash { - bytes: [u8; OUTBYTES], - len: u8, -} - -impl Hash { - /// Convert the hash to a byte slice. Note that if you're using BLAKE2 as a MAC, you need - /// constant time equality, which `&[u8]` doesn't provide. - pub fn as_bytes(&self) -> &[u8] { - &self.bytes[..self.len as usize] - } - - /// Convert the hash to a byte array. Note that if you're using BLAKE2 as a - /// MAC, you need constant time equality, which arrays don't provide. This - /// panics in debug mode if the length of the hash isn't `OUTBYTES`. - #[inline] - pub fn as_array(&self) -> &[u8; OUTBYTES] { - debug_assert_eq!(self.len as usize, OUTBYTES); - &self.bytes - } - - /// Convert the hash to a lowercase hexadecimal - /// [`ArrayString`](https://docs.rs/arrayvec/0.4/arrayvec/struct.ArrayString.html). - pub fn to_hex(&self) -> HexString { - bytes_to_hex(self.as_bytes()) - } -} - -fn bytes_to_hex(bytes: &[u8]) -> HexString { - let mut s = arrayvec::ArrayString::new(); - let table = b"0123456789abcdef"; - for &b in bytes { - s.push(table[(b >> 4) as usize] as char); - s.push(table[(b & 0xf) as usize] as char); - } - s -} - -/// This implementation is constant time, if the two hashes are the same length. -impl PartialEq for Hash { - fn eq(&self, other: &Hash) -> bool { - constant_time_eq::constant_time_eq(&self.as_bytes(), &other.as_bytes()) - } -} - -/// This implementation is constant time, if the slice is the same length as the hash. -impl PartialEq<[u8]> for Hash { - fn eq(&self, other: &[u8]) -> bool { - constant_time_eq::constant_time_eq(&self.as_bytes(), other) - } -} - -impl Eq for Hash {} - -impl AsRef<[u8]> for Hash { - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - -impl fmt::Debug for Hash { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Hash(0x{})", self.to_hex()) - } -} - -// Paint a byte pattern that won't repeat, so that we don't accidentally miss -// buffer offset bugs. This is the same as what Bao uses in its tests. -#[cfg(test)] -fn paint_test_input(buf: &mut [u8]) { - let mut offset = 0; - let mut counter: u32 = 1; - while offset < buf.len() { - let bytes = counter.to_le_bytes(); - let take = cmp::min(bytes.len(), buf.len() - offset); - buf[offset..][..take].copy_from_slice(&bytes[..take]); - counter += 1; - offset += take; - } -} - -// This module is pub for internal benchmarks only. Please don't use it. -#[doc(hidden)] -pub mod benchmarks { - use super::*; - - pub fn force_portable(params: &mut Params) { - params.implementation = guts::Implementation::portable(); - } - - pub fn force_portable_blake2bp(params: &mut blake2bp::Params) { - blake2bp::force_portable(params); - } -} diff --git a/vendor/blake2b_simd/src/many.rs b/vendor/blake2b_simd/src/many.rs deleted file mode 100644 index 1588a3fb92..0000000000 --- a/vendor/blake2b_simd/src/many.rs +++ /dev/null @@ -1,529 +0,0 @@ -//! Interfaces for hashing multiple inputs at once, using SIMD more -//! efficiently. -//! -//! The throughput of these interfaces is comparable to BLAKE2bp, about twice -//! the throughput of regular BLAKE2b when AVX2 is available. -//! -//! These interfaces can accept any number of inputs, and the implementation -//! does its best to parallelize them. In general, the more inputs you can pass -//! in at once the better. If you need to batch your inputs in smaller groups, -//! see the [`degree`](fn.degree.html) function for a good batch size. -//! -//! The implementation keeps working in parallel even when inputs are of -//! different lengths, by managing a working set of jobs whose input isn't yet -//! exhausted. However, if one or two inputs are much longer than the others, -//! and they're encountered only at the end, there might not be any remaining -//! work to parallelize them with. In this case, sorting the inputs -//! longest-first can improve parallelism. -//! -//! # Example -//! -//! ``` -//! use blake2b_simd::{blake2b, State, many::update_many}; -//! -//! let mut states = [ -//! State::new(), -//! State::new(), -//! State::new(), -//! State::new(), -//! ]; -//! -//! let inputs = [ -//! &b"foo"[..], -//! &b"bar"[..], -//! &b"baz"[..], -//! &b"bing"[..], -//! ]; -//! -//! update_many(states.iter_mut().zip(inputs.iter())); -//! -//! for (state, input) in states.iter_mut().zip(inputs.iter()) { -//! assert_eq!(blake2b(input), state.finalize()); -//! } -//! ``` - -use crate::guts::{self, Finalize, Implementation, Job, LastNode, Stride}; -use crate::state_words_to_bytes; -use crate::Count; -use crate::Hash; -use crate::Params; -use crate::State; -use crate::Word; -use crate::BLOCKBYTES; -use arrayref::array_mut_ref; -use arrayvec::ArrayVec; -use core::fmt; - -/// The largest possible value of [`degree`](fn.degree.html) on the target -/// platform. -/// -/// Note that this constant reflects the parallelism degree supported by this -/// crate, so it will change over time as support is added or removed. For -/// example, when Rust stabilizes AVX-512 support and this crate adds an -/// AVX-512 implementation, this constant will double on x86 targets. If that -/// implementation is an optional feature (e.g. because it's nightly-only), the -/// value of this constant will depend on that optional feature also. -pub const MAX_DEGREE: usize = guts::MAX_DEGREE; - -/// The parallelism degree of the implementation, detected at runtime. If you -/// hash your inputs in small batches, making the batch size a multiple of -/// `degree` will generally give good performance. -/// -/// For example, an x86 processor that supports AVX2 can compute four BLAKE2b -/// hashes in parallel, so `degree` returns 4 on that machine. If you call -/// [`hash_many`] with only three inputs, that's not enough to use the AVX2 -/// implementation, and your average throughput will be lower. Likewise if you -/// call it with five inputs of equal length, the first four will be hashed in -/// parallel with AVX2, but the last one will have to be hashed by itself, and -/// again your average throughput will be lower. -/// -/// As noted in the module level docs, performance is more complicated if your -/// inputs are of different lengths. When parallelizing long and short inputs -/// together, the longer ones will have bytes left over, and the implementation -/// will try to parallelize those leftover bytes with subsequent inputs. The -/// more inputs available in that case, the more the implementation will be -/// able to parallelize. -/// -/// If you need a constant batch size, for example to collect inputs in an -/// array, see [`MAX_DEGREE`]. -/// -/// [`hash_many`]: fn.hash_many.html -/// [`MAX_DEGREE`]: constant.MAX_DEGREE.html -pub fn degree() -> usize { - guts::Implementation::detect().degree() -} - -type JobsVec<'a, 'b> = ArrayVec<[Job<'a, 'b>; guts::MAX_DEGREE]>; - -#[inline(always)] -fn fill_jobs_vec<'a, 'b>( - jobs_iter: &mut impl Iterator>, - vec: &mut JobsVec<'a, 'b>, - target_len: usize, -) { - while vec.len() < target_len { - if let Some(job) = jobs_iter.next() { - vec.push(job); - } else { - break; - } - } -} - -#[inline(always)] -fn evict_finished<'a, 'b>(vec: &mut JobsVec<'a, 'b>, num_jobs: usize) { - // Iterate backwards so that removal doesn't cause an out-of-bounds panic. - for i in (0..num_jobs).rev() { - // Note that is_empty() is only valid because we know all these jobs - // have been run at least once. Otherwise we could confuse the empty - // input for a finished job, which would be incorrect. - // - // Avoid a panic branch here in release mode. - debug_assert!(vec.len() > i); - if vec.len() > i && vec[i].input.is_empty() { - // Note that calling pop_at() repeatedly has some overhead, because - // later elements need to be shifted up. However, the JobsVec is - // small, and this approach guarantees that jobs are encountered in - // order. - vec.pop_at(i); - } - } -} - -pub(crate) fn compress_many<'a, 'b, I>( - jobs: I, - imp: Implementation, - finalize: Finalize, - stride: Stride, -) where - I: IntoIterator>, -{ - // Fuse is important for correctness, since each of these blocks tries to - // advance the iterator, even if a previous block emptied it. - let mut jobs_iter = jobs.into_iter().fuse(); - let mut jobs_vec = JobsVec::new(); - - if imp.degree() >= 4 { - loop { - fill_jobs_vec(&mut jobs_iter, &mut jobs_vec, 4); - if jobs_vec.len() < 4 { - break; - } - let jobs_array = array_mut_ref!(jobs_vec, 0, 4); - imp.compress4_loop(jobs_array, finalize, stride); - evict_finished(&mut jobs_vec, 4); - } - } - - if imp.degree() >= 2 { - loop { - fill_jobs_vec(&mut jobs_iter, &mut jobs_vec, 2); - if jobs_vec.len() < 2 { - break; - } - let jobs_array = array_mut_ref!(jobs_vec, 0, 2); - imp.compress2_loop(jobs_array, finalize, stride); - evict_finished(&mut jobs_vec, 2); - } - } - - for job in jobs_vec.into_iter().chain(jobs_iter) { - let Job { - input, - words, - count, - last_node, - } = job; - imp.compress1_loop(input, words, count, last_node, finalize, stride); - } -} - -/// Update any number of `State` objects at once. -/// -/// # Example -/// -/// ``` -/// use blake2b_simd::{blake2b, State, many::update_many}; -/// -/// let mut states = [ -/// State::new(), -/// State::new(), -/// State::new(), -/// State::new(), -/// ]; -/// -/// let inputs = [ -/// &b"foo"[..], -/// &b"bar"[..], -/// &b"baz"[..], -/// &b"bing"[..], -/// ]; -/// -/// update_many(states.iter_mut().zip(inputs.iter())); -/// -/// for (state, input) in states.iter_mut().zip(inputs.iter()) { -/// assert_eq!(blake2b(input), state.finalize()); -/// } -/// ``` -pub fn update_many<'a, 'b, I, T>(pairs: I) -where - I: IntoIterator, - T: 'b + AsRef<[u8]> + ?Sized, -{ - // Get the guts::Implementation from the first state, if any. - let mut peekable_pairs = pairs.into_iter().peekable(); - let implementation = if let Some((state, _)) = peekable_pairs.peek() { - state.implementation - } else { - // No work items, just short circuit. - return; - }; - - // Adapt the pairs iterator into a Jobs iterator, but skip over the Jobs - // where there's not actually any work to do (e.g. because there's not much - // input and it's all just going in the State buffer). - let jobs = peekable_pairs.flat_map(|(state, input_t)| { - let mut input = input_t.as_ref(); - // For each pair, if the State has some input in its buffer, try to - // finish that buffer. If there wasn't enough input to do that -- - // or if the input was empty to begin with -- skip this pair. - state.compress_buffer_if_possible(&mut input); - if input.is_empty() { - return None; - } - // Now we know the buffer is empty and there's more input. Make sure we - // buffer the final block, because update() doesn't finalize. - let mut last_block_start = input.len() - 1; - last_block_start -= last_block_start % BLOCKBYTES; - let (blocks, last_block) = input.split_at(last_block_start); - state.buf[..last_block.len()].copy_from_slice(last_block); - state.buflen = last_block.len() as u8; - // Finally, if the full blocks slice is non-empty, prepare that job for - // compression, and bump the State count. - if blocks.is_empty() { - None - } else { - let count = state.count; - state.count = state.count.wrapping_add(blocks.len() as Count); - Some(Job { - input: blocks, - words: &mut state.words, - count, - last_node: state.last_node, - }) - } - }); - - // Run all the Jobs in the iterator. - compress_many(jobs, implementation, Finalize::No, Stride::Serial); -} - -/// A job for the [`hash_many`] function. After calling [`hash_many`] on a -/// collection of `HashManyJob` objects, you can call [`to_hash`] on each job -/// to get the result. -/// -/// [`hash_many`]: fn.hash_many.html -/// [`to_hash`]: struct.HashManyJob.html#method.to_hash -#[derive(Clone)] -pub struct HashManyJob<'a> { - words: [Word; 8], - count: Count, - last_node: LastNode, - hash_length: u8, - input: &'a [u8], - finished: bool, - implementation: guts::Implementation, -} - -impl<'a> HashManyJob<'a> { - /// Construct a new `HashManyJob` from a set of hashing parameters and an - /// input. - #[inline] - pub fn new(params: &Params, input: &'a [u8]) -> Self { - let mut words = params.to_words(); - let mut count = 0; - let mut finished = false; - // If we have key bytes, compress them into the state words. If there's - // no additional input, this compression needs to finalize and set - // finished=true. - if params.key_length > 0 { - let mut finalization = Finalize::No; - if input.is_empty() { - finalization = Finalize::Yes; - finished = true; - } - params.implementation.compress1_loop( - ¶ms.key_block, - &mut words, - 0, - params.last_node, - finalization, - Stride::Serial, - ); - count = BLOCKBYTES as Count; - } - Self { - words, - count, - last_node: params.last_node, - hash_length: params.hash_length, - input, - finished, - implementation: params.implementation, - } - } - - /// Get the hash from a finished job. If you call this before calling - /// [`hash_many`], it will panic in debug mode. - /// - /// [`hash_many`]: fn.hash_many.html - #[inline] - pub fn to_hash(&self) -> Hash { - debug_assert!(self.finished, "job hasn't been run yet"); - Hash { - bytes: state_words_to_bytes(&self.words), - len: self.hash_length, - } - } -} - -impl<'a> fmt::Debug for HashManyJob<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // NB: Don't print the words. Leaking them would allow length extension. - write!( - f, - "HashManyJob {{ count: {}, hash_length: {}, last_node: {}, input_len: {} }}", - self.count, - self.hash_length, - self.last_node.yes(), - self.input.len(), - ) - } -} - -/// Hash any number of complete inputs all at once. -/// -/// This is slightly more efficient than using `update_many` with `State` -/// objects, because it doesn't need to do any buffering. -/// -/// Running `hash_many` on the same `HashManyJob` object more than once has no -/// effect. -/// -/// # Example -/// -/// ``` -/// use blake2b_simd::{blake2b, Params, many::{HashManyJob, hash_many}}; -/// -/// let inputs = [ -/// &b"foo"[..], -/// &b"bar"[..], -/// &b"baz"[..], -/// &b"bing"[..], -/// ]; -/// -/// let mut params = Params::new(); -/// params.hash_length(16); -/// -/// let mut jobs = [ -/// HashManyJob::new(¶ms, inputs[0]), -/// HashManyJob::new(¶ms, inputs[1]), -/// HashManyJob::new(¶ms, inputs[2]), -/// HashManyJob::new(¶ms, inputs[3]), -/// ]; -/// -/// hash_many(jobs.iter_mut()); -/// -/// for (input, job) in inputs.iter().zip(jobs.iter()) { -/// let expected = params.hash(input); -/// assert_eq!(expected, job.to_hash()); -/// } -/// ``` -pub fn hash_many<'a, 'b, I>(hash_many_jobs: I) -where - 'b: 'a, - I: IntoIterator>, -{ - // Get the guts::Implementation from the first job, if any. - let mut peekable_jobs = hash_many_jobs.into_iter().peekable(); - let implementation = if let Some(job) = peekable_jobs.peek() { - job.implementation - } else { - // No work items, just short circuit. - return; - }; - - // In the jobs iterator, skip HashManyJobs that have already been run. This - // is less because we actually expect callers to call hash_many twice - // (though they're allowed to if they want), and more because - // HashManyJob::new might need to finalize if there are key bytes but no - // input. Tying the job lifetime to the Params reference is an alternative, - // but I've found it too constraining in practice. We could also put key - // bytes in every HashManyJob, but that would add unnecessary storage and - // zeroing for all callers. - let unfinished_jobs = peekable_jobs.into_iter().filter(|j| !j.finished); - let jobs = unfinished_jobs.map(|j| { - j.finished = true; - Job { - input: j.input, - words: &mut j.words, - count: j.count, - last_node: j.last_node, - } - }); - compress_many(jobs, implementation, Finalize::Yes, Stride::Serial); -} - -#[cfg(test)] -mod test { - use super::*; - use crate::guts; - use crate::paint_test_input; - use crate::BLOCKBYTES; - use arrayvec::ArrayVec; - - #[test] - fn test_degree() { - assert!(degree() <= MAX_DEGREE); - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - #[cfg(feature = "std")] - { - if is_x86_feature_detected!("avx2") { - assert!(degree() >= 4); - } - if is_x86_feature_detected!("sse4.1") { - assert!(degree() >= 2); - } - } - } - - #[test] - fn test_hash_many() { - // Use a length of inputs that will exercise all of the power-of-two loops. - const LEN: usize = 2 * guts::MAX_DEGREE - 1; - - // Rerun LEN inputs LEN different times, with the empty input starting in a - // different spot each time. - let mut input = [0; LEN * BLOCKBYTES]; - paint_test_input(&mut input); - for start_offset in 0..LEN { - let mut inputs: [&[u8]; LEN] = [&[]; LEN]; - for i in 0..LEN { - let chunks = (i + start_offset) % LEN; - inputs[i] = &input[..chunks * BLOCKBYTES]; - } - - let mut params: ArrayVec<[Params; LEN]> = ArrayVec::new(); - for i in 0..LEN { - let mut p = Params::new(); - p.node_offset(i as u64); - if i % 2 == 1 { - p.last_node(true); - p.key(b"foo"); - } - params.push(p); - } - - let mut jobs: ArrayVec<[HashManyJob; LEN]> = ArrayVec::new(); - for i in 0..LEN { - jobs.push(HashManyJob::new(¶ms[i], inputs[i])); - } - - hash_many(&mut jobs); - - // Check the outputs. - for i in 0..LEN { - let expected = params[i].hash(inputs[i]); - assert_eq!(expected, jobs[i].to_hash()); - } - } - } - - #[test] - fn test_update_many() { - // Use a length of inputs that will exercise all of the power-of-two loops. - const LEN: usize = 2 * guts::MAX_DEGREE - 1; - - // Rerun LEN inputs LEN different times, with the empty input starting in a - // different spot each time. - let mut input = [0; LEN * BLOCKBYTES]; - paint_test_input(&mut input); - for start_offset in 0..LEN { - let mut inputs: [&[u8]; LEN] = [&[]; LEN]; - for i in 0..LEN { - let chunks = (i + start_offset) % LEN; - inputs[i] = &input[..chunks * BLOCKBYTES]; - } - - let mut params: ArrayVec<[Params; LEN]> = ArrayVec::new(); - for i in 0..LEN { - let mut p = Params::new(); - p.node_offset(i as u64); - if i % 2 == 1 { - p.last_node(true); - p.key(b"foo"); - } - params.push(p); - } - - let mut states: ArrayVec<[State; LEN]> = ArrayVec::new(); - for i in 0..LEN { - states.push(params[i].to_state()); - } - - // Run each input twice through, to exercise buffering. - update_many(states.iter_mut().zip(inputs.iter())); - update_many(states.iter_mut().zip(inputs.iter())); - - // Check the outputs. - for i in 0..LEN { - let mut reference_state = params[i].to_state(); - // Again, run the input twice. - reference_state.update(inputs[i]); - reference_state.update(inputs[i]); - assert_eq!(reference_state.finalize(), states[i].finalize()); - assert_eq!(2 * inputs[i].len() as Count, states[i].count()); - } - } - } -} diff --git a/vendor/blake2b_simd/src/portable.rs b/vendor/blake2b_simd/src/portable.rs deleted file mode 100644 index 216d2d39e5..0000000000 --- a/vendor/blake2b_simd/src/portable.rs +++ /dev/null @@ -1,168 +0,0 @@ -use arrayref::{array_ref, array_refs}; - -use super::*; -use crate::guts::{ - count_high, count_low, final_block, flag_word, input_debug_asserts, Finalize, LastNode, Stride, -}; - -// G is the mixing function, called eight times per round in the compression -// function. V is the 16-word state vector of the compression function, usually -// described as a 4x4 matrix. A, B, C, and D are the mixing indices, set by the -// caller first to the four columns of V, and then to its four diagonals. X and -// Y are words of input, chosen by the caller according to the message -// schedule, SIGMA. -#[inline(always)] -fn g(v: &mut [Word; 16], a: usize, b: usize, c: usize, d: usize, x: Word, y: Word) { - v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); - v[d] = (v[d] ^ v[a]).rotate_right(32); - v[c] = v[c].wrapping_add(v[d]); - v[b] = (v[b] ^ v[c]).rotate_right(24); - v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); - v[d] = (v[d] ^ v[a]).rotate_right(16); - v[c] = v[c].wrapping_add(v[d]); - v[b] = (v[b] ^ v[c]).rotate_right(63); -} - -// This is too much inlining for some small chips like ARM Cortex-M0, so the -// uninline_portable feature is provided to disable it. -#[cfg_attr(not(feature = "uninline_portable"), inline(always))] -fn round(r: usize, m: &[Word; 16], v: &mut [Word; 16]) { - // Select the message schedule based on the round. - let s = SIGMA[r]; - - // Mix the columns. - g(v, 0, 4, 8, 12, m[s[0] as usize], m[s[1] as usize]); - g(v, 1, 5, 9, 13, m[s[2] as usize], m[s[3] as usize]); - g(v, 2, 6, 10, 14, m[s[4] as usize], m[s[5] as usize]); - g(v, 3, 7, 11, 15, m[s[6] as usize], m[s[7] as usize]); - - // Mix the rows. - g(v, 0, 5, 10, 15, m[s[8] as usize], m[s[9] as usize]); - g(v, 1, 6, 11, 12, m[s[10] as usize], m[s[11] as usize]); - g(v, 2, 7, 8, 13, m[s[12] as usize], m[s[13] as usize]); - g(v, 3, 4, 9, 14, m[s[14] as usize], m[s[15] as usize]); -} - -#[inline(always)] -fn compress_block( - block: &[u8; BLOCKBYTES], - words: &mut [Word; 8], - count: Count, - last_block: Word, - last_node: Word, -) { - // Initialize the compression state. - let mut v = [ - words[0], - words[1], - words[2], - words[3], - words[4], - words[5], - words[6], - words[7], - IV[0], - IV[1], - IV[2], - IV[3], - IV[4] ^ count_low(count), - IV[5] ^ count_high(count), - IV[6] ^ last_block, - IV[7] ^ last_node, - ]; - - // Parse the message bytes as ints in little endian order. - const W: usize = size_of::(); - let msg_refs = array_refs!(block, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W, W); - let m = [ - Word::from_le_bytes(*msg_refs.0), - Word::from_le_bytes(*msg_refs.1), - Word::from_le_bytes(*msg_refs.2), - Word::from_le_bytes(*msg_refs.3), - Word::from_le_bytes(*msg_refs.4), - Word::from_le_bytes(*msg_refs.5), - Word::from_le_bytes(*msg_refs.6), - Word::from_le_bytes(*msg_refs.7), - Word::from_le_bytes(*msg_refs.8), - Word::from_le_bytes(*msg_refs.9), - Word::from_le_bytes(*msg_refs.10), - Word::from_le_bytes(*msg_refs.11), - Word::from_le_bytes(*msg_refs.12), - Word::from_le_bytes(*msg_refs.13), - Word::from_le_bytes(*msg_refs.14), - Word::from_le_bytes(*msg_refs.15), - ]; - - round(0, &m, &mut v); - round(1, &m, &mut v); - round(2, &m, &mut v); - round(3, &m, &mut v); - round(4, &m, &mut v); - round(5, &m, &mut v); - round(6, &m, &mut v); - round(7, &m, &mut v); - round(8, &m, &mut v); - round(9, &m, &mut v); - round(10, &m, &mut v); - round(11, &m, &mut v); - - words[0] ^= v[0] ^ v[8]; - words[1] ^= v[1] ^ v[9]; - words[2] ^= v[2] ^ v[10]; - words[3] ^= v[3] ^ v[11]; - words[4] ^= v[4] ^ v[12]; - words[5] ^= v[5] ^ v[13]; - words[6] ^= v[6] ^ v[14]; - words[7] ^= v[7] ^ v[15]; -} - -pub fn compress1_loop( - input: &[u8], - words: &mut [Word; 8], - mut count: Count, - last_node: LastNode, - finalize: Finalize, - stride: Stride, -) { - input_debug_asserts(input, finalize); - - let mut local_words = *words; - - let mut fin_offset = input.len().saturating_sub(1); - fin_offset -= fin_offset % stride.padded_blockbytes(); - let mut buf = [0; BLOCKBYTES]; - let (fin_block, fin_len, _) = final_block(input, fin_offset, &mut buf, stride); - let fin_last_block = flag_word(finalize.yes()); - let fin_last_node = flag_word(finalize.yes() && last_node.yes()); - - let mut offset = 0; - loop { - let block; - let count_delta; - let last_block; - let last_node; - if offset == fin_offset { - block = fin_block; - count_delta = fin_len; - last_block = fin_last_block; - last_node = fin_last_node; - } else { - block = array_ref!(input, offset, BLOCKBYTES); - count_delta = BLOCKBYTES; - last_block = flag_word(false); - last_node = flag_word(false); - }; - - count = count.wrapping_add(count_delta as Count); - compress_block(block, &mut local_words, count, last_block, last_node); - - // Check for termination before bumping the offset, to avoid overflow. - if offset == fin_offset { - break; - } - - offset += stride.padded_blockbytes(); - } - - *words = local_words; -} diff --git a/vendor/blake2b_simd/src/sse41.rs b/vendor/blake2b_simd/src/sse41.rs deleted file mode 100644 index e8f9e06f0d..0000000000 --- a/vendor/blake2b_simd/src/sse41.rs +++ /dev/null @@ -1,460 +0,0 @@ -#[cfg(target_arch = "x86")] -use core::arch::x86::*; -#[cfg(target_arch = "x86_64")] -use core::arch::x86_64::*; - -use crate::guts::{ - assemble_count, count_high, count_low, final_block, flag_word, input_debug_asserts, Finalize, - Job, Stride, -}; -use crate::{Word, BLOCKBYTES, IV, SIGMA}; -use arrayref::{array_refs, mut_array_refs}; -use core::cmp; -use core::mem; - -pub const DEGREE: usize = 2; - -#[inline(always)] -unsafe fn loadu(src: *const [Word; DEGREE]) -> __m128i { - // This is an unaligned load, so the pointer cast is allowed. - _mm_loadu_si128(src as *const __m128i) -} - -#[inline(always)] -unsafe fn storeu(src: __m128i, dest: *mut [Word; DEGREE]) { - // This is an unaligned store, so the pointer cast is allowed. - _mm_storeu_si128(dest as *mut __m128i, src) -} - -#[inline(always)] -unsafe fn add(a: __m128i, b: __m128i) -> __m128i { - _mm_add_epi64(a, b) -} - -#[inline(always)] -unsafe fn eq(a: __m128i, b: __m128i) -> __m128i { - _mm_cmpeq_epi64(a, b) -} - -#[inline(always)] -unsafe fn and(a: __m128i, b: __m128i) -> __m128i { - _mm_and_si128(a, b) -} - -#[inline(always)] -unsafe fn negate_and(a: __m128i, b: __m128i) -> __m128i { - // Note that "and not" implies the reverse of the actual arg order. - _mm_andnot_si128(a, b) -} - -#[inline(always)] -unsafe fn xor(a: __m128i, b: __m128i) -> __m128i { - _mm_xor_si128(a, b) -} - -#[inline(always)] -unsafe fn set1(x: u64) -> __m128i { - _mm_set1_epi64x(x as i64) -} - -#[inline(always)] -unsafe fn set2(a: u64, b: u64) -> __m128i { - // There's no _mm_setr_epi64x, so note the arg order is backwards. - _mm_set_epi64x(b as i64, a as i64) -} - -// Adapted from https://github.com/rust-lang-nursery/stdsimd/pull/479. -macro_rules! _MM_SHUFFLE { - ($z:expr, $y:expr, $x:expr, $w:expr) => { - ($z << 6) | ($y << 4) | ($x << 2) | $w - }; -} - -// These rotations are the "simple version". For the "complicated version", see -// https://github.com/sneves/blake2-avx2/blob/b3723921f668df09ece52dcd225a36d4a4eea1d9/blake2b-common.h#L43-L46. -// For a discussion of the tradeoffs, see -// https://github.com/sneves/blake2-avx2/pull/5. In short: -// - This version performs better on modern x86 chips, Skylake and later. -// - LLVM is able to optimize this version to AVX-512 rotation instructions -// when those are enabled. - -#[inline(always)] -unsafe fn rot32(x: __m128i) -> __m128i { - _mm_or_si128(_mm_srli_epi64(x, 32), _mm_slli_epi64(x, 64 - 32)) -} - -#[inline(always)] -unsafe fn rot24(x: __m128i) -> __m128i { - _mm_or_si128(_mm_srli_epi64(x, 24), _mm_slli_epi64(x, 64 - 24)) -} - -#[inline(always)] -unsafe fn rot16(x: __m128i) -> __m128i { - _mm_or_si128(_mm_srli_epi64(x, 16), _mm_slli_epi64(x, 64 - 16)) -} - -#[inline(always)] -unsafe fn rot63(x: __m128i) -> __m128i { - _mm_or_si128(_mm_srli_epi64(x, 63), _mm_slli_epi64(x, 64 - 63)) -} - -#[inline(always)] -unsafe fn round(v: &mut [__m128i; 16], m: &[__m128i; 16], r: usize) { - v[0] = add(v[0], m[SIGMA[r][0] as usize]); - v[1] = add(v[1], m[SIGMA[r][2] as usize]); - v[2] = add(v[2], m[SIGMA[r][4] as usize]); - v[3] = add(v[3], m[SIGMA[r][6] as usize]); - v[0] = add(v[0], v[4]); - v[1] = add(v[1], v[5]); - v[2] = add(v[2], v[6]); - v[3] = add(v[3], v[7]); - v[12] = xor(v[12], v[0]); - v[13] = xor(v[13], v[1]); - v[14] = xor(v[14], v[2]); - v[15] = xor(v[15], v[3]); - v[12] = rot32(v[12]); - v[13] = rot32(v[13]); - v[14] = rot32(v[14]); - v[15] = rot32(v[15]); - v[8] = add(v[8], v[12]); - v[9] = add(v[9], v[13]); - v[10] = add(v[10], v[14]); - v[11] = add(v[11], v[15]); - v[4] = xor(v[4], v[8]); - v[5] = xor(v[5], v[9]); - v[6] = xor(v[6], v[10]); - v[7] = xor(v[7], v[11]); - v[4] = rot24(v[4]); - v[5] = rot24(v[5]); - v[6] = rot24(v[6]); - v[7] = rot24(v[7]); - v[0] = add(v[0], m[SIGMA[r][1] as usize]); - v[1] = add(v[1], m[SIGMA[r][3] as usize]); - v[2] = add(v[2], m[SIGMA[r][5] as usize]); - v[3] = add(v[3], m[SIGMA[r][7] as usize]); - v[0] = add(v[0], v[4]); - v[1] = add(v[1], v[5]); - v[2] = add(v[2], v[6]); - v[3] = add(v[3], v[7]); - v[12] = xor(v[12], v[0]); - v[13] = xor(v[13], v[1]); - v[14] = xor(v[14], v[2]); - v[15] = xor(v[15], v[3]); - v[12] = rot16(v[12]); - v[13] = rot16(v[13]); - v[14] = rot16(v[14]); - v[15] = rot16(v[15]); - v[8] = add(v[8], v[12]); - v[9] = add(v[9], v[13]); - v[10] = add(v[10], v[14]); - v[11] = add(v[11], v[15]); - v[4] = xor(v[4], v[8]); - v[5] = xor(v[5], v[9]); - v[6] = xor(v[6], v[10]); - v[7] = xor(v[7], v[11]); - v[4] = rot63(v[4]); - v[5] = rot63(v[5]); - v[6] = rot63(v[6]); - v[7] = rot63(v[7]); - - v[0] = add(v[0], m[SIGMA[r][8] as usize]); - v[1] = add(v[1], m[SIGMA[r][10] as usize]); - v[2] = add(v[2], m[SIGMA[r][12] as usize]); - v[3] = add(v[3], m[SIGMA[r][14] as usize]); - v[0] = add(v[0], v[5]); - v[1] = add(v[1], v[6]); - v[2] = add(v[2], v[7]); - v[3] = add(v[3], v[4]); - v[15] = xor(v[15], v[0]); - v[12] = xor(v[12], v[1]); - v[13] = xor(v[13], v[2]); - v[14] = xor(v[14], v[3]); - v[15] = rot32(v[15]); - v[12] = rot32(v[12]); - v[13] = rot32(v[13]); - v[14] = rot32(v[14]); - v[10] = add(v[10], v[15]); - v[11] = add(v[11], v[12]); - v[8] = add(v[8], v[13]); - v[9] = add(v[9], v[14]); - v[5] = xor(v[5], v[10]); - v[6] = xor(v[6], v[11]); - v[7] = xor(v[7], v[8]); - v[4] = xor(v[4], v[9]); - v[5] = rot24(v[5]); - v[6] = rot24(v[6]); - v[7] = rot24(v[7]); - v[4] = rot24(v[4]); - v[0] = add(v[0], m[SIGMA[r][9] as usize]); - v[1] = add(v[1], m[SIGMA[r][11] as usize]); - v[2] = add(v[2], m[SIGMA[r][13] as usize]); - v[3] = add(v[3], m[SIGMA[r][15] as usize]); - v[0] = add(v[0], v[5]); - v[1] = add(v[1], v[6]); - v[2] = add(v[2], v[7]); - v[3] = add(v[3], v[4]); - v[15] = xor(v[15], v[0]); - v[12] = xor(v[12], v[1]); - v[13] = xor(v[13], v[2]); - v[14] = xor(v[14], v[3]); - v[15] = rot16(v[15]); - v[12] = rot16(v[12]); - v[13] = rot16(v[13]); - v[14] = rot16(v[14]); - v[10] = add(v[10], v[15]); - v[11] = add(v[11], v[12]); - v[8] = add(v[8], v[13]); - v[9] = add(v[9], v[14]); - v[5] = xor(v[5], v[10]); - v[6] = xor(v[6], v[11]); - v[7] = xor(v[7], v[8]); - v[4] = xor(v[4], v[9]); - v[5] = rot63(v[5]); - v[6] = rot63(v[6]); - v[7] = rot63(v[7]); - v[4] = rot63(v[4]); -} - -// We'd rather make this a regular function with #[inline(always)], but for -// some reason that blows up compile times by about 10 seconds, at least in -// some cases (BLAKE2b avx2.rs). This macro seems to get the same performance -// result, without the compile time issue. -macro_rules! compress2_transposed { - ( - $h_vecs:expr, - $msg_vecs:expr, - $count_low:expr, - $count_high:expr, - $lastblock:expr, - $lastnode:expr, - ) => { - let h_vecs: &mut [__m128i; 8] = $h_vecs; - let msg_vecs: &[__m128i; 16] = $msg_vecs; - let count_low: __m128i = $count_low; - let count_high: __m128i = $count_high; - let lastblock: __m128i = $lastblock; - let lastnode: __m128i = $lastnode; - let mut v = [ - h_vecs[0], - h_vecs[1], - h_vecs[2], - h_vecs[3], - h_vecs[4], - h_vecs[5], - h_vecs[6], - h_vecs[7], - set1(IV[0]), - set1(IV[1]), - set1(IV[2]), - set1(IV[3]), - xor(set1(IV[4]), count_low), - xor(set1(IV[5]), count_high), - xor(set1(IV[6]), lastblock), - xor(set1(IV[7]), lastnode), - ]; - - round(&mut v, &msg_vecs, 0); - round(&mut v, &msg_vecs, 1); - round(&mut v, &msg_vecs, 2); - round(&mut v, &msg_vecs, 3); - round(&mut v, &msg_vecs, 4); - round(&mut v, &msg_vecs, 5); - round(&mut v, &msg_vecs, 6); - round(&mut v, &msg_vecs, 7); - round(&mut v, &msg_vecs, 8); - round(&mut v, &msg_vecs, 9); - round(&mut v, &msg_vecs, 10); - round(&mut v, &msg_vecs, 11); - - h_vecs[0] = xor(xor(h_vecs[0], v[0]), v[8]); - h_vecs[1] = xor(xor(h_vecs[1], v[1]), v[9]); - h_vecs[2] = xor(xor(h_vecs[2], v[2]), v[10]); - h_vecs[3] = xor(xor(h_vecs[3], v[3]), v[11]); - h_vecs[4] = xor(xor(h_vecs[4], v[4]), v[12]); - h_vecs[5] = xor(xor(h_vecs[5], v[5]), v[13]); - h_vecs[6] = xor(xor(h_vecs[6], v[6]), v[14]); - h_vecs[7] = xor(xor(h_vecs[7], v[7]), v[15]); - }; -} - -#[inline(always)] -unsafe fn transpose_vecs(a: __m128i, b: __m128i) -> [__m128i; DEGREE] { - let a_words: [Word; DEGREE] = mem::transmute(a); - let b_words: [Word; DEGREE] = mem::transmute(b); - [set2(a_words[0], b_words[0]), set2(a_words[1], b_words[1])] -} - -#[inline(always)] -unsafe fn transpose_state_vecs(jobs: &[Job; DEGREE]) -> [__m128i; 8] { - // Load all the state words into transposed vectors, where the first vector - // has the first word of each state, etc. Transposing once at the beginning - // and once at the end is more efficient that repeating it for each block. - let words0 = array_refs!(&jobs[0].words, DEGREE, DEGREE, DEGREE, DEGREE); - let words1 = array_refs!(&jobs[1].words, DEGREE, DEGREE, DEGREE, DEGREE); - let [h0, h1] = transpose_vecs(loadu(words0.0), loadu(words1.0)); - let [h2, h3] = transpose_vecs(loadu(words0.1), loadu(words1.1)); - let [h4, h5] = transpose_vecs(loadu(words0.2), loadu(words1.2)); - let [h6, h7] = transpose_vecs(loadu(words0.3), loadu(words1.3)); - [h0, h1, h2, h3, h4, h5, h6, h7] -} - -#[inline(always)] -unsafe fn untranspose_state_vecs(h_vecs: &[__m128i; 8], jobs: &mut [Job; DEGREE]) { - // Un-transpose the updated state vectors back into the caller's arrays. - let [job0, job1] = jobs; - let words0 = mut_array_refs!(&mut job0.words, DEGREE, DEGREE, DEGREE, DEGREE); - let words1 = mut_array_refs!(&mut job1.words, DEGREE, DEGREE, DEGREE, DEGREE); - - let out = transpose_vecs(h_vecs[0], h_vecs[1]); - storeu(out[0], words0.0); - storeu(out[1], words1.0); - let out = transpose_vecs(h_vecs[2], h_vecs[3]); - storeu(out[0], words0.1); - storeu(out[1], words1.1); - let out = transpose_vecs(h_vecs[4], h_vecs[5]); - storeu(out[0], words0.2); - storeu(out[1], words1.2); - let out = transpose_vecs(h_vecs[6], h_vecs[7]); - storeu(out[0], words0.3); - storeu(out[1], words1.3); -} - -#[inline(always)] -unsafe fn transpose_msg_vecs(blocks: [*const [u8; BLOCKBYTES]; DEGREE]) -> [__m128i; 16] { - // These input arrays have no particular alignment, so we use unaligned - // loads to read from them. - let block0 = blocks[0] as *const [Word; DEGREE]; - let block1 = blocks[1] as *const [Word; DEGREE]; - let [m0, m1] = transpose_vecs(loadu(block0.add(0)), loadu(block1.add(0))); - let [m2, m3] = transpose_vecs(loadu(block0.add(1)), loadu(block1.add(1))); - let [m4, m5] = transpose_vecs(loadu(block0.add(2)), loadu(block1.add(2))); - let [m6, m7] = transpose_vecs(loadu(block0.add(3)), loadu(block1.add(3))); - let [m8, m9] = transpose_vecs(loadu(block0.add(4)), loadu(block1.add(4))); - let [m10, m11] = transpose_vecs(loadu(block0.add(5)), loadu(block1.add(5))); - let [m12, m13] = transpose_vecs(loadu(block0.add(6)), loadu(block1.add(6))); - let [m14, m15] = transpose_vecs(loadu(block0.add(7)), loadu(block1.add(7))); - [ - m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, - ] -} - -#[inline(always)] -unsafe fn load_counts(jobs: &[Job; DEGREE]) -> (__m128i, __m128i) { - ( - set2(count_low(jobs[0].count), count_low(jobs[1].count)), - set2(count_high(jobs[0].count), count_high(jobs[1].count)), - ) -} - -#[inline(always)] -unsafe fn store_counts(jobs: &mut [Job; DEGREE], low: __m128i, high: __m128i) { - let low_ints: [Word; DEGREE] = mem::transmute(low); - let high_ints: [Word; DEGREE] = mem::transmute(high); - for i in 0..DEGREE { - jobs[i].count = assemble_count(low_ints[i], high_ints[i]); - } -} - -#[inline(always)] -unsafe fn add_to_counts(lo: &mut __m128i, hi: &mut __m128i, delta: __m128i) { - // If the low counts reach zero, that means they wrapped, unless the delta - // was also zero. - *lo = add(*lo, delta); - let lo_reached_zero = eq(*lo, set1(0)); - let delta_was_zero = eq(delta, set1(0)); - let hi_inc = and(set1(1), negate_and(delta_was_zero, lo_reached_zero)); - *hi = add(*hi, hi_inc); -} - -#[inline(always)] -unsafe fn flags_vec(flags: [bool; DEGREE]) -> __m128i { - set2(flag_word(flags[0]), flag_word(flags[1])) -} - -#[target_feature(enable = "sse4.1")] -pub unsafe fn compress2_loop(jobs: &mut [Job; DEGREE], finalize: Finalize, stride: Stride) { - // If we're not finalizing, there can't be a partial block at the end. - for job in jobs.iter() { - input_debug_asserts(job.input, finalize); - } - - let msg_ptrs = [jobs[0].input.as_ptr(), jobs[1].input.as_ptr()]; - let mut h_vecs = transpose_state_vecs(&jobs); - let (mut counts_lo, mut counts_hi) = load_counts(&jobs); - - // Prepare the final blocks (note, which could be empty if the input is - // empty). Do all this before entering the main loop. - let min_len = jobs.iter().map(|job| job.input.len()).min().unwrap(); - let mut fin_offset = min_len.saturating_sub(1); - fin_offset -= fin_offset % stride.padded_blockbytes(); - // Performance note, making these buffers mem::uninitialized() seems to - // cause problems in the optimizer. - let mut buf0: [u8; BLOCKBYTES] = [0; BLOCKBYTES]; - let mut buf1: [u8; BLOCKBYTES] = [0; BLOCKBYTES]; - let (block0, len0, finalize0) = final_block(jobs[0].input, fin_offset, &mut buf0, stride); - let (block1, len1, finalize1) = final_block(jobs[1].input, fin_offset, &mut buf1, stride); - let fin_blocks: [*const [u8; BLOCKBYTES]; DEGREE] = [block0, block1]; - let fin_counts_delta = set2(len0 as Word, len1 as Word); - let fin_last_block; - let fin_last_node; - if finalize.yes() { - fin_last_block = flags_vec([finalize0, finalize1]); - fin_last_node = flags_vec([ - finalize0 && jobs[0].last_node.yes(), - finalize1 && jobs[1].last_node.yes(), - ]); - } else { - fin_last_block = set1(0); - fin_last_node = set1(0); - } - - // The main loop. - let mut offset = 0; - loop { - let blocks; - let counts_delta; - let last_block; - let last_node; - if offset == fin_offset { - blocks = fin_blocks; - counts_delta = fin_counts_delta; - last_block = fin_last_block; - last_node = fin_last_node; - } else { - blocks = [ - msg_ptrs[0].add(offset) as *const [u8; BLOCKBYTES], - msg_ptrs[1].add(offset) as *const [u8; BLOCKBYTES], - ]; - counts_delta = set1(BLOCKBYTES as Word); - last_block = set1(0); - last_node = set1(0); - }; - - let m_vecs = transpose_msg_vecs(blocks); - add_to_counts(&mut counts_lo, &mut counts_hi, counts_delta); - compress2_transposed!( - &mut h_vecs, - &m_vecs, - counts_lo, - counts_hi, - last_block, - last_node, - ); - - // Check for termination before bumping the offset, to avoid overflow. - if offset == fin_offset { - break; - } - - offset += stride.padded_blockbytes(); - } - - // Write out the results. - untranspose_state_vecs(&h_vecs, &mut *jobs); - store_counts(&mut *jobs, counts_lo, counts_hi); - let max_consumed = offset.saturating_add(stride.padded_blockbytes()); - for job in jobs.iter_mut() { - let consumed = cmp::min(max_consumed, job.input.len()); - job.input = &job.input[consumed..]; - } -} diff --git a/vendor/blake2b_simd/src/test.rs b/vendor/blake2b_simd/src/test.rs deleted file mode 100644 index 9ca8e87751..0000000000 --- a/vendor/blake2b_simd/src/test.rs +++ /dev/null @@ -1,201 +0,0 @@ -use super::*; - -const EMPTY_HASH: &str = "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419\ - d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"; -const ABC_HASH: &str = "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1\ - 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"; -const ONE_BLOCK_HASH: &str = "865939e120e6805438478841afb739ae4250cf372653078a065cdcfffca4caf7\ - 98e6d462b65d658fc165782640eded70963449ae1500fb0f24981d7727e22c41"; -const THOUSAND_HASH: &str = "1ee4e51ecab5210a518f26150e882627ec839967f19d763e1508b12cfefed148\ - 58f6a1c9d1f969bc224dc9440f5a6955277e755b9c513f9ba4421c5e50c8d787"; - -#[test] -fn test_update_state() { - let io = &[ - (&b""[..], EMPTY_HASH), - (&b"abc"[..], ABC_HASH), - (&[0; BLOCKBYTES], ONE_BLOCK_HASH), - (&[0; 1000], THOUSAND_HASH), - ]; - // Test each input all at once. - for &(input, output) in io { - let hash = blake2b(input); - assert_eq!(&hash.to_hex(), output, "hash mismatch"); - } - // Now in two chunks. This is especially important for the ONE_BLOCK case, because it would be - // a mistake for update() to call compress, even though the buffer is full. - for &(input, output) in io { - let mut state = State::new(); - let split = input.len() / 2; - state.update(&input[..split]); - assert_eq!(split as Count, state.count()); - state.update(&input[split..]); - assert_eq!(input.len() as Count, state.count()); - let hash = state.finalize(); - assert_eq!(&hash.to_hex(), output, "hash mismatch"); - } - // Now one byte at a time. - for &(input, output) in io { - let mut state = State::new(); - let mut count = 0; - for &b in input { - state.update(&[b]); - count += 1; - assert_eq!(count, state.count()); - } - let hash = state.finalize(); - assert_eq!(&hash.to_hex(), output, "hash mismatch"); - } -} - -#[test] -fn test_multiple_finalizes() { - let mut state = State::new(); - assert_eq!(&state.finalize().to_hex(), EMPTY_HASH, "hash mismatch"); - assert_eq!(&state.finalize().to_hex(), EMPTY_HASH, "hash mismatch"); - assert_eq!(&state.finalize().to_hex(), EMPTY_HASH, "hash mismatch"); - state.update(b"abc"); - assert_eq!(&state.finalize().to_hex(), ABC_HASH, "hash mismatch"); - assert_eq!(&state.finalize().to_hex(), ABC_HASH, "hash mismatch"); - assert_eq!(&state.finalize().to_hex(), ABC_HASH, "hash mismatch"); -} - -#[cfg(feature = "std")] -#[test] -fn test_write() { - use std::io::prelude::*; - - let mut state = State::new(); - state.write_all(&[0; 1000]).unwrap(); - let hash = state.finalize(); - assert_eq!(&hash.to_hex(), THOUSAND_HASH, "hash mismatch"); -} - -// You can check this case against the equivalent Python: -// -// import hashlib -// hashlib.blake2b( -// b'foo', -// digest_size=18, -// key=b"bar", -// salt=b"bazbazbazbazbazb", -// person=b"bing bing bing b", -// fanout=2, -// depth=3, -// leaf_size=0x04050607, -// node_offset=0x08090a0b0c0d0e0f, -// node_depth=16, -// inner_size=17, -// last_node=True, -// ).hexdigest() -#[test] -fn test_all_parameters() { - let mut params = Params::new(); - params - .hash_length(18) - // Make sure a shorter key properly overwrites a longer one. - .key(b"not the real key") - .key(b"bar") - .salt(b"bazbazbazbazbazb") - .personal(b"bing bing bing b") - .fanout(2) - .max_depth(3) - .max_leaf_length(0x04050607) - .node_offset(0x08090a0b0c0d0e0f) - .node_depth(16) - .inner_hash_length(17) - .last_node(true); - - // Check the State API. - assert_eq!( - "ec0f59cb65f92e7fcca1280ba859a6925ded", - ¶ms.to_state().update(b"foo").finalize().to_hex() - ); - - // Check the all-at-once API. - assert_eq!( - "ec0f59cb65f92e7fcca1280ba859a6925ded", - ¶ms.hash(b"foo").to_hex() - ); -} - -#[test] -fn test_all_parameters_blake2bp() { - let mut params = blake2bp::Params::new(); - params - .hash_length(18) - // Make sure a shorter key properly overwrites a longer one. - .key(b"not the real key") - .key(b"bar"); - - // Check the State API. - assert_eq!( - "8c54e888a8a01c63da6585c058fe54ea81df", - ¶ms.to_state().update(b"foo").finalize().to_hex() - ); - - // Check the all-at-once API. - assert_eq!( - "8c54e888a8a01c63da6585c058fe54ea81df", - ¶ms.hash(b"foo").to_hex() - ); -} - -#[test] -#[should_panic] -fn test_short_hash_length_panics() { - Params::new().hash_length(0); -} - -#[test] -#[should_panic] -fn test_long_hash_length_panics() { - Params::new().hash_length(OUTBYTES + 1); -} - -#[test] -#[should_panic] -fn test_long_key_panics() { - Params::new().key(&[0; KEYBYTES + 1]); -} - -#[test] -#[should_panic] -fn test_long_salt_panics() { - Params::new().salt(&[0; SALTBYTES + 1]); -} - -#[test] -#[should_panic] -fn test_long_personal_panics() { - Params::new().personal(&[0; PERSONALBYTES + 1]); -} - -#[test] -fn test_zero_max_depth_supported() { - Params::new().max_depth(0); -} - -#[test] -#[should_panic] -fn test_long_inner_hash_length_panics() { - Params::new().inner_hash_length(OUTBYTES + 1); -} - -#[test] -#[should_panic] -fn test_blake2bp_short_hash_length_panics() { - blake2bp::Params::new().hash_length(0); -} - -#[test] -#[should_panic] -fn test_blake2bp_long_hash_length_panics() { - blake2bp::Params::new().hash_length(OUTBYTES + 1); -} - -#[test] -#[should_panic] -fn test_blake2bp_long_key_panics() { - blake2bp::Params::new().key(&[0; KEYBYTES + 1]); -} diff --git a/vendor/bytecount/.cargo-checksum.json b/vendor/bytecount/.cargo-checksum.json index 86dfdfbfb1..700fc57f25 100644 --- a/vendor/bytecount/.cargo-checksum.json +++ b/vendor/bytecount/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"5feb30618cdc8d05391a18110e1968eed438931b5d2088372d97f27551e468b5","LICENSE.Apache2":"b40930bbcf80744c86c46a12bc9da056641d722716c378f5659b9e555ef833e1","LICENSE.MIT":"a5dea80c1f383cb5f80a6bb0da5e55a2beb9f24adb123ce6300af2cbaaa3bf65","README.md":"84e452fd64997865cf8f55790717703efb8efc7c43c82252a23545d50e73fa28","benches/bench.rs":"085734cc7b3c3f6da30eeab8bf98d95fc2a9c0886c63f93edd98df356674bf8e","src/integer_simd.rs":"5b6a3da54adfb8417d1035c3da4e14be38e86c0145b81ec407d537829e373cd3","src/lib.rs":"000a6591306852b9ec892995cd6ab4247b8a727f4befa9dd6a9851c20a5f6552","src/naive.rs":"068dae3fba7d721227bb7a9ed9bdfe4a12cfb373a9de4852d6a517630fabf0c8","src/simd/generic.rs":"7b8dcdca3a66351c89e95ee7c536336803fc7def6de270bc98edfb1d3894b3e4","src/simd/mod.rs":"8ce4aac79520bd0d49f6e48471bf32a2d6d3cd8a3a1c65e393f4f4fae6c7f502","src/simd/x86_avx2.rs":"e505ef3e522a0eab75535cf327f268a54de809e6816ab9b6b32498d7bf19e124","src/simd/x86_sse2.rs":"e7caab115d77118e6a7bca8daea4a9b6d2d318bd3e76ddc23dc4f023aced1f77","tests/check.rs":"623402690d6dd293a0c75f322c5aeacefb669eb61545ab3fbc4794a16490156c"},"package":"b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e"} \ No newline at end of file +{"files":{"Cargo.toml":"90f053e609e5ba2abe4f05ecca43423ed11efebf55d6070fd9983252a81c24a8","LICENSE.Apache2":"b40930bbcf80744c86c46a12bc9da056641d722716c378f5659b9e555ef833e1","LICENSE.MIT":"a5dea80c1f383cb5f80a6bb0da5e55a2beb9f24adb123ce6300af2cbaaa3bf65","README.md":"84e452fd64997865cf8f55790717703efb8efc7c43c82252a23545d50e73fa28","benches/bench.rs":"085734cc7b3c3f6da30eeab8bf98d95fc2a9c0886c63f93edd98df356674bf8e","ci/miri.sh":"fb8d52144352c6b09ac925fb089177d30f46ab8b17dd378d68e414c6b6b5b709","src/integer_simd.rs":"5cd97182cd5aea5c5eab1e1cb5d9d409f263de9083c8e69cd7f9d1dd379dfb52","src/lib.rs":"000a6591306852b9ec892995cd6ab4247b8a727f4befa9dd6a9851c20a5f6552","src/naive.rs":"068dae3fba7d721227bb7a9ed9bdfe4a12cfb373a9de4852d6a517630fabf0c8","src/simd/generic.rs":"2f01963147fa97b5dbd7a166975e6f6660d3197f4b6d0a78ed138da9f78a269e","src/simd/mod.rs":"8ce4aac79520bd0d49f6e48471bf32a2d6d3cd8a3a1c65e393f4f4fae6c7f502","src/simd/x86_avx2.rs":"0345d5fbb74d907e3e6cd0d361427ce75645e7abf4c6efa17ef20ee8a4d8fc18","src/simd/x86_sse2.rs":"e7caab115d77118e6a7bca8daea4a9b6d2d318bd3e76ddc23dc4f023aced1f77","tests/check.rs":"e5075559155a1aae6326932e68410996ca52e4140db4b26eb8b9f03a07241b87"},"package":"72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"} \ No newline at end of file diff --git a/vendor/bytecount/Cargo.toml b/vendor/bytecount/Cargo.toml index c9714031d3..e3571c5c11 100644 --- a/vendor/bytecount/Cargo.toml +++ b/vendor/bytecount/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "bytecount" -version = "0.6.0" +version = "0.6.2" authors = ["Andre Bogus ", "Joshua Landau "] exclude = ["/.travis.yml", "/appveyor.yml"] description = "count occurrences of a given byte, or the number of UTF-8 code points, in a byte slice, fast" @@ -29,8 +29,9 @@ bench = false name = "bench" harness = false [dependencies.packed_simd] -version = "0.3.1" +version = "0.3.4" optional = true +package = "packed_simd_2" [dev-dependencies.criterion] version = "0.3" default-features = false diff --git a/vendor/bytecount/ci/miri.sh b/vendor/bytecount/ci/miri.sh new file mode 100755 index 0000000000..8704ebc1dc --- /dev/null +++ b/vendor/bytecount/ci/miri.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -ex + +# Setup +MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) +echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" +rustup default "$MIRI_NIGHTLY" +rustup component add miri + +# Run tests +cargo miri test +cargo miri test --target=mips64-unknown-linux-gnuabi64 # big-endian architecture + +# Restore old state in case Travis uses this cache for other jobs. +rustup default nightly diff --git a/vendor/bytecount/src/integer_simd.rs b/vendor/bytecount/src/integer_simd.rs index 296ee5ef3e..48f2ee8d90 100644 --- a/vendor/bytecount/src/integer_simd.rs +++ b/vendor/bytecount/src/integer_simd.rs @@ -11,7 +11,7 @@ fn splat(byte: u8) -> usize { unsafe fn usize_load_unchecked(bytes: &[u8], offset: usize) -> usize { let mut output = 0; ptr::copy_nonoverlapping( - bytes.as_ptr().offset(offset as isize), + bytes.as_ptr().add(offset), &mut output as *mut usize as *mut u8, mem::size_of::() ); diff --git a/vendor/bytecount/src/simd/generic.rs b/vendor/bytecount/src/simd/generic.rs index 792d6d740a..2031e730e4 100644 --- a/vendor/bytecount/src/simd/generic.rs +++ b/vendor/bytecount/src/simd/generic.rs @@ -68,6 +68,10 @@ pub fn chunk_count(haystack: &[u8], needle: u8) -> usize { for i in 0..(haystack.len() - offset) / 32 { counts -= u8x32::from_cast(u8x32_from_offset(haystack, offset + i * 32).eq(needles_x32)); } + count += sum_x32(&counts); + + // Straggler; need to reset counts because prior loop can run 255 times + counts = u8x32::splat(0); if haystack.len() % 32 != 0 { counts -= u8x32::from_cast(u8x32_from_offset(haystack, haystack.len() - 32).eq(needles_x32)) & u8x32_from_offset(&MASK, haystack.len() % 32); @@ -95,7 +99,7 @@ pub fn chunk_num_chars(utf8_chars: &[u8]) -> usize { // 16320 while utf8_chars.len() >= offset + 64 * 255 { - let mut counts = u8x64::splat(0);; + let mut counts = u8x64::splat(0); for _ in 0..255 { counts -= is_leading_utf8_byte_x64(u8x64_from_offset(utf8_chars, offset)); offset += 64; @@ -105,7 +109,7 @@ pub fn chunk_num_chars(utf8_chars: &[u8]) -> usize { // 8192 if utf8_chars.len() >= offset + 64 * 128 { - let mut counts = u8x64::splat(0);; + let mut counts = u8x64::splat(0); for _ in 0..128 { counts -= is_leading_utf8_byte_x64(u8x64_from_offset(utf8_chars, offset)); offset += 64; @@ -118,6 +122,10 @@ pub fn chunk_num_chars(utf8_chars: &[u8]) -> usize { for i in 0..(utf8_chars.len() - offset) / 32 { counts -= is_leading_utf8_byte_x32(u8x32_from_offset(utf8_chars, offset + i * 32)); } + count += sum_x32(&counts); + + // Straggler; need to reset counts because prior loop can run 255 times + counts = u8x32::splat(0); if utf8_chars.len() % 32 != 0 { counts -= is_leading_utf8_byte_x32(u8x32_from_offset(utf8_chars, utf8_chars.len() - 32)) & u8x32_from_offset(&MASK, utf8_chars.len() % 32); diff --git a/vendor/bytecount/src/simd/x86_avx2.rs b/vendor/bytecount/src/simd/x86_avx2.rs index e6070812fd..90a55c0fb5 100644 --- a/vendor/bytecount/src/simd/x86_avx2.rs +++ b/vendor/bytecount/src/simd/x86_avx2.rs @@ -30,7 +30,7 @@ const MASK: [u8; 64] = [ #[target_feature(enable = "avx2")] unsafe fn mm256_from_offset(slice: &[u8], offset: usize) -> __m256i { - _mm256_loadu_si256(slice.as_ptr().offset(offset as isize) as *const _) + _mm256_loadu_si256(slice.as_ptr().add(offset) as *const _) } #[target_feature(enable = "avx2")] diff --git a/vendor/bytecount/tests/check.rs b/vendor/bytecount/tests/check.rs index e45e9a4859..147b466fc8 100644 --- a/vendor/bytecount/tests/check.rs +++ b/vendor/bytecount/tests/check.rs @@ -3,7 +3,6 @@ extern crate bytecount; extern crate quickcheck; extern crate rand; -use std::iter; use bytecount::{ count, naive_count, num_chars, naive_num_chars, @@ -25,15 +24,15 @@ quickcheck! { #[test] fn check_count_large() { - let haystack = vec![0u8; 10_000_000]; + let haystack = vec![0u8; if cfg!(miri) { 2_000 } else { 10_000_000 }]; assert_eq!(naive_count(&haystack, 0), count(&haystack, 0)); assert_eq!(naive_count(&haystack, 1), count(&haystack, 1)); } #[test] fn check_count_large_rand() { - let haystack = random_bytes(100_000); - for i in (0..255).chain(iter::once(255)) { + let haystack = random_bytes(if cfg!(miri) { 200 } else { 100_000 }); + for i in 0..=255 { assert_eq!(naive_count(&haystack, i), count(&haystack, i)); } } @@ -52,6 +51,16 @@ fn check_count_overflow() { assert_eq!(count(&haystack, needle), naive_count(&haystack, needle)); } +#[test] +fn check_count_overflow_many() { + let string = [b'x'; 20000]; + for i in 0..20000 { + assert_eq!(count(&string[..i], b'x'), i); + } +} + + + quickcheck! { fn check_num_chars_correct(haystack: Vec) -> bool { num_chars(&haystack) == naive_num_chars(&haystack) @@ -60,7 +69,7 @@ quickcheck! { #[test] fn check_num_chars_large() { - let haystack = vec![0u8; 10_000_000]; + let haystack = vec![0u8; if cfg!(miri) { 2_000 } else { 10_000_000 }]; assert_eq!(naive_num_chars(&haystack), num_chars(&haystack)); assert_eq!(naive_num_chars(&haystack), num_chars(&haystack)); } @@ -76,3 +85,11 @@ fn check_num_chars_overflow() { let haystack = vec![0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; assert_eq!(num_chars(&haystack), naive_num_chars(&haystack)); } + +#[test] +fn check_num_chars_overflow_many() { + let string = [b'x'; 20000]; + for i in 0..20000 { + assert_eq!(num_chars(&string[..i]), i); + } +} diff --git a/vendor/constant_time_eq/.cargo-checksum.json b/vendor/constant_time_eq/.cargo-checksum.json deleted file mode 100644 index 5eb6dd1755..0000000000 --- a/vendor/constant_time_eq/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"5039cc861ab84d85162dc1b3acf268a98d63d299a99b897ab21d390a9e9fb0f3","LICENSE.txt":"a2010f343487d3f7618affe54f789f5487602331c0a8d03f49e9a7c547cf0499","README":"4f0deec2ec32eeabaa065fef2ddd7816a32550b8395da5c47fc458bd45143bea","benches/bench.rs":"ffc599703d114cc4943db322f433b0819787db0c1ff41d7be3efc5c0940e0001","src/lib.rs":"ab735430ea1eaea0673a9a15d9437d591a718bc061c70f3499e42b65e4eb8ba4"},"package":"245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"} \ No newline at end of file diff --git a/vendor/constant_time_eq/Cargo.toml b/vendor/constant_time_eq/Cargo.toml deleted file mode 100644 index 20d49fb683..0000000000 --- a/vendor/constant_time_eq/Cargo.toml +++ /dev/null @@ -1,25 +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 = "constant_time_eq" -version = "0.1.5" -authors = ["Cesar Eduardo Barros "] -description = "Compares two equal-sized byte strings in constant time." -documentation = "https://docs.rs/constant_time_eq" -readme = "README" -keywords = ["constant_time"] -categories = ["cryptography", "no-std"] -license = "CC0-1.0" -repository = "https://github.com/cesarb/constant_time_eq" -[badges.travis-ci] -repository = "cesarb/constant_time_eq" diff --git a/vendor/constant_time_eq/LICENSE.txt b/vendor/constant_time_eq/LICENSE.txt deleted file mode 100644 index 0e259d42c9..0000000000 --- a/vendor/constant_time_eq/LICENSE.txt +++ /dev/null @@ -1,121 +0,0 @@ -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. diff --git a/vendor/constant_time_eq/README b/vendor/constant_time_eq/README deleted file mode 100644 index 98cdaf04ca..0000000000 --- a/vendor/constant_time_eq/README +++ /dev/null @@ -1,3 +0,0 @@ -Compares two equal-sized byte strings in constant time. - -Inspired by the Linux kernel's crypto_memneq. diff --git a/vendor/constant_time_eq/benches/bench.rs b/vendor/constant_time_eq/benches/bench.rs deleted file mode 100644 index 4b3b790a5d..0000000000 --- a/vendor/constant_time_eq/benches/bench.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![feature(test)] - -extern crate constant_time_eq; -extern crate test; - -use constant_time_eq::constant_time_eq; -use test::{Bencher, black_box}; - -fn bench(b: &mut Bencher, left: &[u8], right: &[u8]) { - b.bytes = (left.len() + right.len()) as u64; - b.iter(|| { - constant_time_eq(black_box(left), black_box(right)) - }) -} - -#[bench] -fn bench_16(b: &mut Bencher) { - bench(b, &[0; 16], &[0; 16]) -} - -#[bench] -fn bench_4096(b: &mut Bencher) { - bench(b, &[0; 4096], &[0; 4096]) -} - -#[bench] -fn bench_65536(b: &mut Bencher) { - bench(b, &[0; 65536], &[0; 65536]) -} diff --git a/vendor/constant_time_eq/src/lib.rs b/vendor/constant_time_eq/src/lib.rs deleted file mode 100644 index a37121acb6..0000000000 --- a/vendor/constant_time_eq/src/lib.rs +++ /dev/null @@ -1,105 +0,0 @@ -#![no_std] - -// This function is non-inline to prevent the optimizer from looking inside it. -#[inline(never)] -fn constant_time_ne(a: &[u8], b: &[u8]) -> u8 { - assert!(a.len() == b.len()); - - // These useless slices make the optimizer elide the bounds checks. - // See the comment in clone_from_slice() added on Rust commit 6a7bc47. - let len = a.len(); - let a = &a[..len]; - let b = &b[..len]; - - let mut tmp = 0; - for i in 0..len { - tmp |= a[i] ^ b[i]; - } - tmp // The compare with 0 must happen outside this function. -} - -/// Compares two equal-sized byte strings in constant time. -/// -/// # Examples -/// -/// ``` -/// use constant_time_eq::constant_time_eq; -/// -/// assert!(constant_time_eq(b"foo", b"foo")); -/// assert!(!constant_time_eq(b"foo", b"bar")); -/// assert!(!constant_time_eq(b"bar", b"baz")); -/// # assert!(constant_time_eq(b"", b"")); -/// -/// // Not equal-sized, so won't take constant time. -/// assert!(!constant_time_eq(b"foo", b"")); -/// assert!(!constant_time_eq(b"foo", b"quux")); -/// ``` -#[inline] -pub fn constant_time_eq(a: &[u8], b: &[u8]) -> bool { - a.len() == b.len() && constant_time_ne(a, b) == 0 -} - -// Fixed-size variants for the most common sizes. - -macro_rules! constant_time_ne_n { - ($ne:ident, $n:expr) => { - // This function is non-inline to prevent the optimizer from looking inside it. - #[inline(never)] - fn $ne(a: &[u8; $n], b: &[u8; $n]) -> u8 { - let mut tmp = 0; - for i in 0..$n { - tmp |= a[i] ^ b[i]; - } - tmp // The compare with 0 must happen outside this function. - } - }; -} - -constant_time_ne_n!(constant_time_ne_16, 16); -constant_time_ne_n!(constant_time_ne_32, 32); -constant_time_ne_n!(constant_time_ne_64, 64); - -/// Compares two 128-bit byte strings in constant time. -/// -/// # Examples -/// -/// ``` -/// use constant_time_eq::constant_time_eq_16; -/// -/// assert!(constant_time_eq_16(&[3; 16], &[3; 16])); -/// assert!(!constant_time_eq_16(&[3; 16], &[7; 16])); -/// ``` -#[inline] -pub fn constant_time_eq_16(a: &[u8; 16], b: &[u8; 16]) -> bool { - constant_time_ne_16(a, b) == 0 -} - -/// Compares two 256-bit byte strings in constant time. -/// -/// # Examples -/// -/// ``` -/// use constant_time_eq::constant_time_eq_32; -/// -/// assert!(constant_time_eq_32(&[3; 32], &[3; 32])); -/// assert!(!constant_time_eq_32(&[3; 32], &[7; 32])); -/// ``` -#[inline] -pub fn constant_time_eq_32(a: &[u8; 32], b: &[u8; 32]) -> bool { - constant_time_ne_32(a, b) == 0 -} - -/// Compares two 512-bit byte strings in constant time. -/// -/// # Examples -/// -/// ``` -/// use constant_time_eq::constant_time_eq_64; -/// -/// assert!(constant_time_eq_64(&[3; 64], &[3; 64])); -/// assert!(!constant_time_eq_64(&[3; 64], &[7; 64])); -/// ``` -#[inline] -pub fn constant_time_eq_64(a: &[u8; 64], b: &[u8; 64]) -> bool { - constant_time_ne_64(a, b) == 0 -} diff --git a/vendor/crossbeam-channel/.cargo-checksum.json b/vendor/crossbeam-channel/.cargo-checksum.json index e232bc9cbe..11d72285ce 100644 --- a/vendor/crossbeam-channel/.cargo-checksum.json +++ b/vendor/crossbeam-channel/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"0d433ba4c2a327604b582aa0cdbe7b841ee9dcca526f6cb368a07c389c485096","Cargo.lock":"97e544df9b9e169d315994dc220e7a274ac039a3a4f372f7cab333a2e93d9b96","Cargo.toml":"a493466e1330e58126818f0e46b82350ad9e6a7811ca6817159fcdd89c8c871a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","LICENSE-THIRD-PARTY":"924a49392dc8304def57586be4ebd69aaf51e16fd245b55b4b69ad2cce6b715a","README.md":"d2c041f6fa5da30a6f87377421a8de4010c0c002dbff777e18ad2f8b36a65378","benches/crossbeam.rs":"f5720508d3458f2451271b9887f7557823304bd38288c928b0d6aa1f459865e5","examples/fibonacci.rs":"6a26ecd74c7493d2c93f4280c0804afc19adc612b77b3d9fea433119ff472a44","examples/matching.rs":"63c250e164607a7a9f643d46f107bb5da846d49e89cf9069909562d20e530f71","examples/stopwatch.rs":"87e4613e24083e877d97aaefdc6c78ee0308c3a2994974b2cbc7df042a82d488","src/channel.rs":"de23e68e7fa16a1e3278bd69f22fd499724e21533b2b601a71dada9cdda97181","src/context.rs":"ad24cabfc50dd5e6ae84aa46a0246da12da1f1a6fa19043244ad25136075c6ca","src/counter.rs":"8b6d4d69db59bc992ddc7ed33f709788c3fab482521bb1adf985f77499506c09","src/err.rs":"fdbde7279a1e74973e5c7d3e835a97836229a357fe465c0ba1a37f2a012d1bef","src/flavors/array.rs":"59d43e7292f5e3f7f1bb7799fdf99d97aae763ac93d2c1c2e0e807cbbae1657b","src/flavors/at.rs":"e6a169d91ee1057080b0ef55f3e38471212b4ef225e2cdc2fd25b2262371f921","src/flavors/list.rs":"fa6667a33e30fad94a8432b78dd70d143e0809ebf80fa881bb6221aca55b4229","src/flavors/mod.rs":"6188db53712b10add58364e3031101833d9fb0e384f3a2894c38c8b11abe4cdf","src/flavors/never.rs":"59ac4a46b5e32780b2b2f338064544a8b4ec1bc8b78a8a9cd0a683bcd01d5d36","src/flavors/tick.rs":"667fcaacb07d7556350a7e59b5906956224c57b1f43b7b0018a5e2dad0d91ff8","src/flavors/zero.rs":"97c13c89bce0ffd4f761a5ecd73e3221bdd320817061ef7bc7d76010da021b77","src/lib.rs":"5873568968cfd92c6970ef9c3b2643a9d68c61f2fe4c724e52243f3b555de758","src/select.rs":"da9446e51bdcc51e878e71d7a97f0b718639ea065d7ddf4fa7b561efebc84a0e","src/select_macro.rs":"96bc9acb9a22588a4e733b0ab0761ad2be9a6b3e03744e8fc9c6de9ae433b696","src/utils.rs":"4ec0d30835f42dffc7614a18c8f005abb40dd33f2b127809b297959c6aa43004","src/waker.rs":"27eb84dcd0eb58f7d0d79d412bb293becc2740f6166d2fc64acb0ad94cfb523e","tests/after.rs":"324c7d773f72bef62d150171f74ba7b7ac1b06f6030b3d4d2b1a35d211956b21","tests/array.rs":"62290dfd66740a1d1017daea8048df09a11ee8ff8eb614a3a0aa5f4d456a7c39","tests/golang.rs":"751743529b0354d152916e0854a0387ca0b3a898a1771c46e1e7fa2b1660edf9","tests/iter.rs":"7563dc7fdf4c63e31dd74ee3fedecdd3aed490f7ef599b98f6f75f929cf79edb","tests/list.rs":"6a9645c00aed88c1ad07d2e416b4f137ccef2e50f389c71589c6ac7d57373e5a","tests/mpsc.rs":"0c4c6b056f5cec77ca19eca45f99b083632700a4b67133e88071a1d22a61d6fe","tests/never.rs":"665441a9fb004f7cd44047619637ebe6766cf2faf58e68e6481397bbfc682e11","tests/ready.rs":"3848ee8bb16cc83269a462d830659ff29f91834eaab0749bca7be02f43d7db51","tests/same_channel.rs":"2bab761443671e841e1b2476bd8082d75533a2f6be7946f5dbcee67cdc82dccb","tests/select.rs":"58aa5421475bd98b3adc02e4241fc77669ca910cf9cac7a8b0a212b2e92cb7c7","tests/select_macro.rs":"00dd7963f79b96abf30851fdab29e86c8424b502a8a7d34abf4bc1714f493ecf","tests/thread_locals.rs":"3611db5502e6af0a8d15187d09fd195381819795544208b946e9f99b04579a81","tests/tick.rs":"06f205ace5fc44daaf1b6900a2e05bb5bda1c6071c1a07524f45769d8855968b","tests/zero.rs":"368eac99c6d9fb679f8dfbe93cdb96b01d77d1b6f840aa4e156b06f1786bb882"},"package":"dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"} \ No newline at end of file +{"files":{"CHANGELOG.md":"74ac49b84461217698d4430f81b1cdcba0595bc4e57216ffc52b8296ac44cd41","Cargo.lock":"7956079bcac40cc40c894f0260266365ecdb1c01c48636ae4c4080977603e7b8","Cargo.toml":"6a7acaffaa30dab2b5ea1f5ab86b20bc97370314ed03472288745b3b969786dc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","LICENSE-THIRD-PARTY":"b16db96b93b1d7cf7bea533f572091ec6bca3234fbe0a83038be772ff391a44c","README.md":"415a71d4978cfd338a6ae1f1b41284652eccd277a815542c304647dc437a8274","benches/crossbeam.rs":"f5720508d3458f2451271b9887f7557823304bd38288c928b0d6aa1f459865e5","examples/fibonacci.rs":"6a26ecd74c7493d2c93f4280c0804afc19adc612b77b3d9fea433119ff472a44","examples/matching.rs":"63c250e164607a7a9f643d46f107bb5da846d49e89cf9069909562d20e530f71","examples/stopwatch.rs":"f9a00477b41823199e4af06bddeb0c6cfd22e272340eec1b98b333fc59ee6a1f","src/channel.rs":"a9baaad2f414c38cd324a60ac9375ca58462ce6662217683648e9b66cec43a8c","src/context.rs":"ad24cabfc50dd5e6ae84aa46a0246da12da1f1a6fa19043244ad25136075c6ca","src/counter.rs":"c49a9f44587888850edeb62f7c8ecd1acecb39c836834254ff3ac934c478440a","src/err.rs":"fdbde7279a1e74973e5c7d3e835a97836229a357fe465c0ba1a37f2a012d1bef","src/flavors/array.rs":"c125146771265058ac320226456b1e21667e93649531a3d20157f71cd715881d","src/flavors/at.rs":"65bf870b3ddb14738256706b0276f2656ad1fe9cd8eb91737489868edd088e92","src/flavors/list.rs":"50dbe59616c39b5aa184470023ce0cfb1cb0dbd92e1577375d299446981527c0","src/flavors/mod.rs":"3d9d43bc38b0adb18c96c995c2bd3421d8e33ab6c30b20c3c467d21d48e485dc","src/flavors/never.rs":"0e7921922d00c711552fb063c63c78192fa6ddc0762fb81c1713b847495ec39a","src/flavors/tick.rs":"38a479b9f4a72a5ccb9c407a1e7b44d36b6ad0f4e214e39266b12b9564c803dc","src/flavors/zero.rs":"1bda0c5483b04d53f36f9f4a6fe6f87b69f698068771e637e224c09400c6ce83","src/lib.rs":"3a65706d4124844ffc4c8cb1f8cc779631ec94f449f85cbb68364ad3619404f1","src/select.rs":"4eb4b1988c5dffff3e3d2138d14a1b86613bf62b78c45a5c70f65aaee92c11bb","src/select_macro.rs":"96bc9acb9a22588a4e733b0ab0761ad2be9a6b3e03744e8fc9c6de9ae433b696","src/utils.rs":"746fe315d6cfc832e3dda35e5055c0fd5c99907f1303b2ea7eacc4e37c8527e1","src/waker.rs":"9058cc441d467539c439ef88f0be1a187bf122d26fc116ce3e3a0265a693761f","tests/after.rs":"324c7d773f72bef62d150171f74ba7b7ac1b06f6030b3d4d2b1a35d211956b21","tests/array.rs":"574bff53aff0b0a8c365bf3f9ad77bb64675df9e6e0714be9c16eeeeac22e4d5","tests/golang.rs":"ec03806945fecd381cfce0634e2d776741423589c92e1bd4d8a431ac20f5d2d0","tests/iter.rs":"7563dc7fdf4c63e31dd74ee3fedecdd3aed490f7ef599b98f6f75f929cf79edb","tests/list.rs":"cc2971e69fd7f6a94b5463c9d4e9079df7955b37552e16dd66f4c6e65db60d96","tests/mpsc.rs":"0c4c6b056f5cec77ca19eca45f99b083632700a4b67133e88071a1d22a61d6fe","tests/never.rs":"665441a9fb004f7cd44047619637ebe6766cf2faf58e68e6481397bbfc682e11","tests/ready.rs":"eae3d7f16e817e63f3a6ceda062fece3de5e11c7a9631b32b02f23396a9d59c1","tests/same_channel.rs":"2bab761443671e841e1b2476bd8082d75533a2f6be7946f5dbcee67cdc82dccb","tests/select.rs":"3603f450b23f5e0d1e4014a167a9b23ab149b5f418c8b89636f1c02c90501569","tests/select_macro.rs":"00dd7963f79b96abf30851fdab29e86c8424b502a8a7d34abf4bc1714f493ecf","tests/thread_locals.rs":"3611db5502e6af0a8d15187d09fd195381819795544208b946e9f99b04579a81","tests/tick.rs":"dc4a7d3c8dd888ce135fe8a8c67f5dc8b5ab0c3fa57a48459f96d51fa0f1e6d5","tests/zero.rs":"0ff0587cc74569bfe389e0c619217799a960a0dfc5e6354603c88e6eea1b79a1"},"package":"06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"} \ No newline at end of file diff --git a/vendor/crossbeam-channel/CHANGELOG.md b/vendor/crossbeam-channel/CHANGELOG.md index 0a53e8a0b8..98fd9f66da 100644 --- a/vendor/crossbeam-channel/CHANGELOG.md +++ b/vendor/crossbeam-channel/CHANGELOG.md @@ -1,3 +1,7 @@ +# Version 0.5.1 + +- Fix memory leak in unbounded channel. (#669) + # Version 0.5.0 - Bump the minimum supported Rust version to 1.36. diff --git a/vendor/crossbeam-channel/Cargo.lock b/vendor/crossbeam-channel/Cargo.lock index 91cb58a0f7..1ae0d57c27 100644 --- a/vendor/crossbeam-channel/Cargo.lock +++ b/vendor/crossbeam-channel/Cargo.lock @@ -1,10 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "arc-swap" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" +version = 3 [[package]] name = "autocfg" @@ -12,29 +8,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "const_fn" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2" - [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", "num_cpus", "rand", @@ -43,32 +27,31 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", - "cfg-if 1.0.0", - "const_fn", + "cfg-if", "lazy_static", ] [[package]] name = "getrandom" -version = "0.1.15" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "libc", "wasi", ] [[package]] name = "hermit-abi" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] @@ -81,9 +64,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.79" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" [[package]] name = "num_cpus" @@ -97,17 +80,16 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" dependencies = [ - "getrandom", "libc", "rand_chacha", "rand_core", @@ -116,9 +98,9 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ "ppv-lite86", "rand_core", @@ -126,27 +108,27 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ "getrandom", ] [[package]] name = "rand_hc" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" dependencies = [ "rand_core", ] [[package]] name = "signal-hook" -version = "0.1.16" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604508c1418b99dfe1925ca9224829bb2a8a9a04dda655cc01fcad46f4ab05ed" +checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac" dependencies = [ "libc", "signal-hook-registry", @@ -154,16 +136,15 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" dependencies = [ - "arc-swap", "libc", ] [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/vendor/crossbeam-channel/Cargo.toml b/vendor/crossbeam-channel/Cargo.toml index a5c9964af3..abcc485aec 100644 --- a/vendor/crossbeam-channel/Cargo.toml +++ b/vendor/crossbeam-channel/Cargo.toml @@ -13,12 +13,11 @@ [package] edition = "2018" name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.1" authors = ["The Crossbeam Project Developers"] description = "Multi-producer multi-consumer channels for message passing" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel" documentation = "https://docs.rs/crossbeam-channel" -readme = "README.md" keywords = ["channel", "mpmc", "select", "golang", "message"] categories = ["algorithms", "concurrency", "data-structures"] license = "MIT OR Apache-2.0" @@ -34,10 +33,10 @@ default-features = false version = "1.13.0" [dev-dependencies.rand] -version = "0.7.3" +version = "0.8" [dev-dependencies.signal-hook] -version = "0.1.15" +version = "0.3" [features] default = ["std"] diff --git a/vendor/crossbeam-channel/LICENSE-THIRD-PARTY b/vendor/crossbeam-channel/LICENSE-THIRD-PARTY index d15e32bc71..ed4df76f4c 100644 --- a/vendor/crossbeam-channel/LICENSE-THIRD-PARTY +++ b/vendor/crossbeam-channel/LICENSE-THIRD-PARTY @@ -1,37 +1,5 @@ =============================================================================== -Bounded MPMC queue -http://www.1024cores.net/home/code-license - -Copyright (c) 2010-2011 Dmitry Vyukov. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "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 DMITRY VYUKOV OR CONTRIBUTORS 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. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of Dmitry Vyukov. - -=============================================================================== - matching.go https://creativecommons.org/licenses/by/3.0/legalcode diff --git a/vendor/crossbeam-channel/README.md b/vendor/crossbeam-channel/README.md index eab623a6a9..f5077c556c 100644 --- a/vendor/crossbeam-channel/README.md +++ b/vendor/crossbeam-channel/README.md @@ -2,7 +2,7 @@ [![Build Status](https://github.com/crossbeam-rs/crossbeam/workflows/CI/badge.svg)]( https://github.com/crossbeam-rs/crossbeam/actions) -[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)]( +[![License](https://img.shields.io/badge/license-MIT_OR_Apache--2.0-blue.svg)]( https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel#license) [![Cargo](https://img.shields.io/crates/v/crossbeam-channel.svg)]( https://crates.io/crates/crossbeam-channel) @@ -10,7 +10,7 @@ https://crates.io/crates/crossbeam-channel) https://docs.rs/crossbeam-channel) [![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-lightgray.svg)]( https://www.rust-lang.org) -[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.gg/BBYwKq) +[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) This crate provides multi-producer multi-consumer channels for message passing. It is an alternative to [`std::sync::mpsc`] with more features and better performance. @@ -41,7 +41,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -crossbeam-channel = "0.4" +crossbeam-channel = "0.5" ``` ## Compatibility @@ -73,10 +73,6 @@ This product includes copies and modifications of software developed by third pa [matching.go](http://www.nada.kth.se/~snilsson/concurrency/src/matching.go) by Stefan Nilsson, licensed under Creative Commons Attribution 3.0 Unported License. -* [src/flavors/array.rs](src/flavors/array.rs) is based on - [Bounded MPMC queue](http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue) - by Dmitry Vyukov, licensed under the Simplified BSD License and the Apache License, Version 2.0. - * [tests/mpsc.rs](tests/mpsc.rs) includes modifications of code from The Rust Programming Language, licensed under the MIT License and the Apache License, Version 2.0. diff --git a/vendor/crossbeam-channel/examples/stopwatch.rs b/vendor/crossbeam-channel/examples/stopwatch.rs index 6a67c9eefc..98895c5a3a 100644 --- a/vendor/crossbeam-channel/examples/stopwatch.rs +++ b/vendor/crossbeam-channel/examples/stopwatch.rs @@ -12,13 +12,13 @@ fn main() { use std::time::{Duration, Instant}; use crossbeam_channel::{bounded, select, tick, Receiver}; + use signal_hook::consts::SIGINT; use signal_hook::iterator::Signals; - use signal_hook::SIGINT; // Creates a channel that gets a message every time `SIGINT` is signalled. fn sigint_notifier() -> io::Result> { let (s, r) = bounded(100); - let signals = Signals::new(&[SIGINT])?; + let mut signals = Signals::new(&[SIGINT])?; thread::spawn(move || { for _ in signals.forever() { diff --git a/vendor/crossbeam-channel/src/channel.rs b/vendor/crossbeam-channel/src/channel.rs index ebcd652018..8988235db4 100644 --- a/vendor/crossbeam-channel/src/channel.rs +++ b/vendor/crossbeam-channel/src/channel.rs @@ -257,8 +257,6 @@ pub fn at(when: Instant) -> Receiver { /// recv(timeout) -> _ => println!("timed out"), /// } /// ``` -/// -/// [`select!`]: macro.select.html pub fn never() -> Receiver { Receiver { flavor: ReceiverFlavor::Never(flavors::never::Channel::new()), @@ -645,7 +643,7 @@ impl Drop for Sender { unsafe { match &self.flavor { SenderFlavor::Array(chan) => chan.release(|c| c.disconnect()), - SenderFlavor::List(chan) => chan.release(|c| c.disconnect()), + SenderFlavor::List(chan) => chan.release(|c| c.disconnect_senders()), SenderFlavor::Zero(chan) => chan.release(|c| c.disconnect()), } } @@ -1137,7 +1135,7 @@ impl Drop for Receiver { unsafe { match &self.flavor { ReceiverFlavor::Array(chan) => chan.release(|c| c.disconnect()), - ReceiverFlavor::List(chan) => chan.release(|c| c.disconnect()), + ReceiverFlavor::List(chan) => chan.release(|c| c.disconnect_receivers()), ReceiverFlavor::Zero(chan) => chan.release(|c| c.disconnect()), ReceiverFlavor::At(_) => {} ReceiverFlavor::Tick(_) => {} @@ -1485,7 +1483,7 @@ impl SelectHandle for Receiver { } /// Writes a message into the channel. -pub unsafe fn write(s: &Sender, token: &mut Token, msg: T) -> Result<(), T> { +pub(crate) unsafe fn write(s: &Sender, token: &mut Token, msg: T) -> Result<(), T> { match &s.flavor { SenderFlavor::Array(chan) => chan.write(token, msg), SenderFlavor::List(chan) => chan.write(token, msg), @@ -1494,7 +1492,7 @@ pub unsafe fn write(s: &Sender, token: &mut Token, msg: T) -> Result<(), T } /// Reads a message from the channel. -pub unsafe fn read(r: &Receiver, token: &mut Token) -> Result { +pub(crate) unsafe fn read(r: &Receiver, token: &mut Token) -> Result { match &r.flavor { ReceiverFlavor::Array(chan) => chan.read(token), ReceiverFlavor::List(chan) => chan.read(token), diff --git a/vendor/crossbeam-channel/src/counter.rs b/vendor/crossbeam-channel/src/counter.rs index 2eaf067820..2c27f7c6b2 100644 --- a/vendor/crossbeam-channel/src/counter.rs +++ b/vendor/crossbeam-channel/src/counter.rs @@ -21,7 +21,7 @@ struct Counter { } /// Wraps a channel into the reference counter. -pub fn new(chan: C) -> (Sender, Receiver) { +pub(crate) fn new(chan: C) -> (Sender, Receiver) { let counter = Box::into_raw(Box::new(Counter { senders: AtomicUsize::new(1), receivers: AtomicUsize::new(1), @@ -34,7 +34,7 @@ pub fn new(chan: C) -> (Sender, Receiver) { } /// The sending side. -pub struct Sender { +pub(crate) struct Sender { counter: *mut Counter, } @@ -45,7 +45,7 @@ impl Sender { } /// Acquires another sender reference. - pub fn acquire(&self) -> Sender { + pub(crate) fn acquire(&self) -> Sender { let count = self.counter().senders.fetch_add(1, Ordering::Relaxed); // Cloning senders and calling `mem::forget` on the clones could potentially overflow the @@ -63,7 +63,7 @@ impl Sender { /// Releases the sender reference. /// /// Function `disconnect` will be called if this is the last sender reference. - pub unsafe fn release bool>(&self, disconnect: F) { + pub(crate) unsafe fn release bool>(&self, disconnect: F) { if self.counter().senders.fetch_sub(1, Ordering::AcqRel) == 1 { disconnect(&self.counter().chan); @@ -89,7 +89,7 @@ impl PartialEq for Sender { } /// The receiving side. -pub struct Receiver { +pub(crate) struct Receiver { counter: *mut Counter, } @@ -100,7 +100,7 @@ impl Receiver { } /// Acquires another receiver reference. - pub fn acquire(&self) -> Receiver { + pub(crate) fn acquire(&self) -> Receiver { let count = self.counter().receivers.fetch_add(1, Ordering::Relaxed); // Cloning receivers and calling `mem::forget` on the clones could potentially overflow the @@ -118,7 +118,7 @@ impl Receiver { /// Releases the receiver reference. /// /// Function `disconnect` will be called if this is the last receiver reference. - pub unsafe fn release bool>(&self, disconnect: F) { + pub(crate) unsafe fn release bool>(&self, disconnect: F) { if self.counter().receivers.fetch_sub(1, Ordering::AcqRel) == 1 { disconnect(&self.counter().chan); diff --git a/vendor/crossbeam-channel/src/flavors/array.rs b/vendor/crossbeam-channel/src/flavors/array.rs index 323a200c25..c49eef1f04 100644 --- a/vendor/crossbeam-channel/src/flavors/array.rs +++ b/vendor/crossbeam-channel/src/flavors/array.rs @@ -5,13 +5,8 @@ //! The implementation is based on Dmitry Vyukov's bounded MPMC queue. //! //! Source: -//! - http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue -//! - https://docs.google.com/document/d/1yIAYmbvL3JxOKOjuCyon7JhW4cSv1wy5hC0ApeGMV9s/pub -//! -//! Copyright & License: -//! - Copyright (c) 2010-2011 Dmitry Vyukov -//! - Simplified BSD License and Apache License, Version 2.0 -//! - http://www.1024cores.net/home/code-license +//! - +//! - use std::cell::UnsafeCell; use std::marker::PhantomData; @@ -57,7 +52,7 @@ impl Default for ArrayToken { } /// Bounded channel based on a preallocated array. -pub struct Channel { +pub(crate) struct Channel { /// The head of the channel. /// /// This value is a "stamp" consisting of an index into the buffer, a mark bit, and a lap, but @@ -100,7 +95,7 @@ pub struct Channel { impl Channel { /// Creates a bounded channel of capacity `cap`. - pub fn with_capacity(cap: usize) -> Self { + pub(crate) fn with_capacity(cap: usize) -> Self { assert!(cap > 0, "capacity must be positive"); // Compute constants `mark_bit` and `one_lap`. @@ -143,12 +138,12 @@ impl Channel { } /// Returns a receiver handle to the channel. - pub fn receiver(&self) -> Receiver<'_, T> { + pub(crate) fn receiver(&self) -> Receiver<'_, T> { Receiver(self) } /// Returns a sender handle to the channel. - pub fn sender(&self) -> Sender<'_, T> { + pub(crate) fn sender(&self) -> Sender<'_, T> { Sender(self) } @@ -224,7 +219,7 @@ impl Channel { } /// Writes a message into the channel. - pub unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> { + pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> { // If there is no slot, the channel is disconnected. if token.array.slot.is_null() { return Err(msg); @@ -314,7 +309,7 @@ impl Channel { } /// Reads a message from the channel. - pub unsafe fn read(&self, token: &mut Token) -> Result { + pub(crate) unsafe fn read(&self, token: &mut Token) -> Result { if token.array.slot.is_null() { // The channel is disconnected. return Err(()); @@ -332,7 +327,7 @@ impl Channel { } /// Attempts to send a message into the channel. - pub fn try_send(&self, msg: T) -> Result<(), TrySendError> { + pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError> { let token = &mut Token::default(); if self.start_send(token) { unsafe { self.write(token, msg).map_err(TrySendError::Disconnected) } @@ -342,7 +337,11 @@ impl Channel { } /// Sends a message into the channel. - pub fn send(&self, msg: T, deadline: Option) -> Result<(), SendTimeoutError> { + pub(crate) fn send( + &self, + msg: T, + deadline: Option, + ) -> Result<(), SendTimeoutError> { let token = &mut Token::default(); loop { // Try sending a message several times. @@ -391,7 +390,7 @@ impl Channel { } /// Attempts to receive a message without blocking. - pub fn try_recv(&self) -> Result { + pub(crate) fn try_recv(&self) -> Result { let token = &mut Token::default(); if self.start_recv(token) { @@ -402,7 +401,7 @@ impl Channel { } /// Receives a message from the channel. - pub fn recv(&self, deadline: Option) -> Result { + pub(crate) fn recv(&self, deadline: Option) -> Result { let token = &mut Token::default(); loop { // Try receiving a message several times. @@ -453,7 +452,7 @@ impl Channel { } /// Returns the current number of messages inside the channel. - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { loop { // Load the tail, then load the head. let tail = self.tail.load(Ordering::SeqCst); @@ -478,14 +477,15 @@ impl Channel { } /// Returns the capacity of the channel. - pub fn capacity(&self) -> Option { + #[allow(clippy::unnecessary_wraps)] // This is intentional. + pub(crate) fn capacity(&self) -> Option { Some(self.cap) } /// Disconnects the channel and wakes up all blocked senders and receivers. /// /// Returns `true` if this call disconnected the channel. - pub fn disconnect(&self) -> bool { + pub(crate) fn disconnect(&self) -> bool { let tail = self.tail.fetch_or(self.mark_bit, Ordering::SeqCst); if tail & self.mark_bit == 0 { @@ -498,12 +498,12 @@ impl Channel { } /// Returns `true` if the channel is disconnected. - pub fn is_disconnected(&self) -> bool { + pub(crate) fn is_disconnected(&self) -> bool { self.tail.load(Ordering::SeqCst) & self.mark_bit != 0 } /// Returns `true` if the channel is empty. - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { let head = self.head.load(Ordering::SeqCst); let tail = self.tail.load(Ordering::SeqCst); @@ -515,7 +515,7 @@ impl Channel { } /// Returns `true` if the channel is full. - pub fn is_full(&self) -> bool { + pub(crate) fn is_full(&self) -> bool { let tail = self.tail.load(Ordering::SeqCst); let head = self.head.load(Ordering::SeqCst); @@ -563,10 +563,10 @@ impl Drop for Channel { } /// Receiver handle to a channel. -pub struct Receiver<'a, T>(&'a Channel); +pub(crate) struct Receiver<'a, T>(&'a Channel); /// Sender handle to a channel. -pub struct Sender<'a, T>(&'a Channel); +pub(crate) struct Sender<'a, T>(&'a Channel); impl SelectHandle for Receiver<'_, T> { fn try_select(&self, token: &mut Token) -> bool { diff --git a/vendor/crossbeam-channel/src/flavors/at.rs b/vendor/crossbeam-channel/src/flavors/at.rs index a2b1b578ec..4581edba12 100644 --- a/vendor/crossbeam-channel/src/flavors/at.rs +++ b/vendor/crossbeam-channel/src/flavors/at.rs @@ -12,10 +12,10 @@ use crate::select::{Operation, SelectHandle, Token}; use crate::utils; /// Result of a receive operation. -pub type AtToken = Option; +pub(crate) type AtToken = Option; /// Channel that delivers a message at a certain moment in time -pub struct Channel { +pub(crate) struct Channel { /// The instant at which the message will be delivered. delivery_time: Instant, @@ -26,7 +26,7 @@ pub struct Channel { impl Channel { /// Creates a channel that delivers a message at a certain instant in time. #[inline] - pub fn new_deadline(when: Instant) -> Self { + pub(crate) fn new_deadline(when: Instant) -> Self { Channel { delivery_time: when, received: AtomicBool::new(false), @@ -34,13 +34,13 @@ impl Channel { } /// Creates a channel that delivers a message after a certain duration of time. #[inline] - pub fn new_timeout(dur: Duration) -> Self { + pub(crate) fn new_timeout(dur: Duration) -> Self { Self::new_deadline(Instant::now() + dur) } /// Attempts to receive a message without blocking. #[inline] - pub fn try_recv(&self) -> Result { + pub(crate) fn try_recv(&self) -> Result { // We use relaxed ordering because this is just an optional optimistic check. if self.received.load(Ordering::Relaxed) { // The message has already been received. @@ -64,7 +64,7 @@ impl Channel { /// Receives a message from the channel. #[inline] - pub fn recv(&self, deadline: Option) -> Result { + pub(crate) fn recv(&self, deadline: Option) -> Result { // We use relaxed ordering because this is just an optional optimistic check. if self.received.load(Ordering::Relaxed) { // The message has already been received. @@ -103,13 +103,13 @@ impl Channel { /// Reads a message from the channel. #[inline] - pub unsafe fn read(&self, token: &mut Token) -> Result { + pub(crate) unsafe fn read(&self, token: &mut Token) -> Result { token.at.ok_or(()) } /// Returns `true` if the channel is empty. #[inline] - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { // We use relaxed ordering because this is just an optional optimistic check. if self.received.load(Ordering::Relaxed) { return true; @@ -127,13 +127,13 @@ impl Channel { /// Returns `true` if the channel is full. #[inline] - pub fn is_full(&self) -> bool { + pub(crate) fn is_full(&self) -> bool { !self.is_empty() } /// Returns the number of messages in the channel. #[inline] - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { if self.is_empty() { 0 } else { @@ -142,8 +142,9 @@ impl Channel { } /// Returns the capacity of the channel. + #[allow(clippy::unnecessary_wraps)] // This is intentional. #[inline] - pub fn capacity(&self) -> Option { + pub(crate) fn capacity(&self) -> Option { Some(1) } } diff --git a/vendor/crossbeam-channel/src/flavors/list.rs b/vendor/crossbeam-channel/src/flavors/list.rs index 532e8b6ad4..5056aa4313 100644 --- a/vendor/crossbeam-channel/src/flavors/list.rs +++ b/vendor/crossbeam-channel/src/flavors/list.rs @@ -151,7 +151,7 @@ impl Default for ListToken { /// /// Consecutive messages are grouped into blocks in order to put less pressure on the allocator and /// improve cache efficiency. -pub struct Channel { +pub(crate) struct Channel { /// The head of the channel. head: CachePadded>, @@ -167,7 +167,7 @@ pub struct Channel { impl Channel { /// Creates a new unbounded channel. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Channel { head: CachePadded::new(Position { block: AtomicPtr::new(ptr::null_mut()), @@ -183,12 +183,12 @@ impl Channel { } /// Returns a receiver handle to the channel. - pub fn receiver(&self) -> Receiver<'_, T> { + pub(crate) fn receiver(&self) -> Receiver<'_, T> { Receiver(self) } /// Returns a sender handle to the channel. - pub fn sender(&self) -> Sender<'_, T> { + pub(crate) fn sender(&self) -> Sender<'_, T> { Sender(self) } @@ -231,8 +231,8 @@ impl Channel { if self .tail .block - .compare_and_swap(block, new, Ordering::Release) - == block + .compare_exchange(block, new, Ordering::Release, Ordering::Relaxed) + .is_ok() { self.head.block.store(new, Ordering::Release); block = new; @@ -276,7 +276,7 @@ impl Channel { } /// Writes a message into the channel. - pub unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> { + pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> { // If there is no slot, the channel is disconnected. if token.list.block.is_null() { return Err(msg); @@ -380,7 +380,7 @@ impl Channel { } /// Reads a message from the channel. - pub unsafe fn read(&self, token: &mut Token) -> Result { + pub(crate) unsafe fn read(&self, token: &mut Token) -> Result { if token.list.block.is_null() { // The channel is disconnected. return Err(()); @@ -405,7 +405,7 @@ impl Channel { } /// Attempts to send a message into the channel. - pub fn try_send(&self, msg: T) -> Result<(), TrySendError> { + pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError> { self.send(msg, None).map_err(|err| match err { SendTimeoutError::Disconnected(msg) => TrySendError::Disconnected(msg), SendTimeoutError::Timeout(_) => unreachable!(), @@ -413,7 +413,11 @@ impl Channel { } /// Sends a message into the channel. - pub fn send(&self, msg: T, _deadline: Option) -> Result<(), SendTimeoutError> { + pub(crate) fn send( + &self, + msg: T, + _deadline: Option, + ) -> Result<(), SendTimeoutError> { let token = &mut Token::default(); assert!(self.start_send(token)); unsafe { @@ -423,7 +427,7 @@ impl Channel { } /// Attempts to receive a message without blocking. - pub fn try_recv(&self) -> Result { + pub(crate) fn try_recv(&self) -> Result { let token = &mut Token::default(); if self.start_recv(token) { @@ -434,7 +438,7 @@ impl Channel { } /// Receives a message from the channel. - pub fn recv(&self, deadline: Option) -> Result { + pub(crate) fn recv(&self, deadline: Option) -> Result { let token = &mut Token::default(); loop { // Try receiving a message several times. @@ -486,7 +490,7 @@ impl Channel { } /// Returns the current number of messages inside the channel. - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { loop { // Load the tail index, then load the head index. let mut tail = self.tail.index.load(Ordering::SeqCst); @@ -522,14 +526,14 @@ impl Channel { } /// Returns the capacity of the channel. - pub fn capacity(&self) -> Option { + pub(crate) fn capacity(&self) -> Option { None } - /// Disconnects the channel and wakes up all blocked receivers. + /// Disconnects senders and wakes up all blocked receivers. /// /// Returns `true` if this call disconnected the channel. - pub fn disconnect(&self) -> bool { + pub(crate) fn disconnect_senders(&self) -> bool { let tail = self.tail.index.fetch_or(MARK_BIT, Ordering::SeqCst); if tail & MARK_BIT == 0 { @@ -540,20 +544,90 @@ impl Channel { } } + /// Disconnects receivers. + /// + /// Returns `true` if this call disconnected the channel. + pub(crate) fn disconnect_receivers(&self) -> bool { + let tail = self.tail.index.fetch_or(MARK_BIT, Ordering::SeqCst); + + if tail & MARK_BIT == 0 { + // If receivers are dropped first, discard all messages to free + // memory eagerly. + self.discard_all_messages(); + true + } else { + false + } + } + + /// Discards all messages. + /// + /// This method should only be called when all receivers are dropped. + fn discard_all_messages(&self) { + let backoff = Backoff::new(); + let mut tail = self.tail.index.load(Ordering::Acquire); + loop { + let offset = (tail >> SHIFT) % LAP; + if offset != BLOCK_CAP { + break; + } + + // New updates to tail will be rejected by MARK_BIT and aborted unless it's + // at boundary. We need to wait for the updates take affect otherwise there + // can be memory leaks. + backoff.snooze(); + tail = self.tail.index.load(Ordering::Acquire); + } + + let mut head = self.head.index.load(Ordering::Acquire); + let mut block = self.head.block.load(Ordering::Acquire); + + unsafe { + // Drop all messages between head and tail and deallocate the heap-allocated blocks. + while head >> SHIFT != tail >> SHIFT { + let offset = (head >> SHIFT) % LAP; + + if offset < BLOCK_CAP { + // Drop the message in the slot. + let slot = (*block).slots.get_unchecked(offset); + slot.wait_write(); + let p = &mut *slot.msg.get(); + p.as_mut_ptr().drop_in_place(); + } else { + (*block).wait_next(); + // Deallocate the block and move to the next one. + let next = (*block).next.load(Ordering::Acquire); + drop(Box::from_raw(block)); + block = next; + } + + head = head.wrapping_add(1 << SHIFT); + } + + // Deallocate the last remaining block. + if !block.is_null() { + drop(Box::from_raw(block)); + } + } + head &= !MARK_BIT; + self.head.block.store(ptr::null_mut(), Ordering::Release); + self.head.index.store(head, Ordering::Release); + } + /// Returns `true` if the channel is disconnected. - pub fn is_disconnected(&self) -> bool { + pub(crate) fn is_disconnected(&self) -> bool { self.tail.index.load(Ordering::SeqCst) & MARK_BIT != 0 } /// Returns `true` if the channel is empty. - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { let head = self.head.index.load(Ordering::SeqCst); let tail = self.tail.index.load(Ordering::SeqCst); head >> SHIFT == tail >> SHIFT } /// Returns `true` if the channel is full. - pub fn is_full(&self) -> bool { + pub(crate) fn is_full(&self) -> bool { false } } @@ -597,10 +671,10 @@ impl Drop for Channel { } /// Receiver handle to a channel. -pub struct Receiver<'a, T>(&'a Channel); +pub(crate) struct Receiver<'a, T>(&'a Channel); /// Sender handle to a channel. -pub struct Sender<'a, T>(&'a Channel); +pub(crate) struct Sender<'a, T>(&'a Channel); impl SelectHandle for Receiver<'_, T> { fn try_select(&self, token: &mut Token) -> bool { diff --git a/vendor/crossbeam-channel/src/flavors/mod.rs b/vendor/crossbeam-channel/src/flavors/mod.rs index 299e78f696..0314bf4209 100644 --- a/vendor/crossbeam-channel/src/flavors/mod.rs +++ b/vendor/crossbeam-channel/src/flavors/mod.rs @@ -9,9 +9,9 @@ //! 5. `tick` - Channel that delivers messages periodically. //! 6. `zero` - Zero-capacity channel. -pub mod array; -pub mod at; -pub mod list; -pub mod never; -pub mod tick; -pub mod zero; +pub(crate) mod array; +pub(crate) mod at; +pub(crate) mod list; +pub(crate) mod never; +pub(crate) mod tick; +pub(crate) mod zero; diff --git a/vendor/crossbeam-channel/src/flavors/never.rs b/vendor/crossbeam-channel/src/flavors/never.rs index e49d2147c4..1951e963fa 100644 --- a/vendor/crossbeam-channel/src/flavors/never.rs +++ b/vendor/crossbeam-channel/src/flavors/never.rs @@ -11,17 +11,17 @@ use crate::select::{Operation, SelectHandle, Token}; use crate::utils; /// This flavor doesn't need a token. -pub type NeverToken = (); +pub(crate) type NeverToken = (); /// Channel that never delivers messages. -pub struct Channel { +pub(crate) struct Channel { _marker: PhantomData, } impl Channel { /// Creates a channel that never delivers messages. #[inline] - pub fn new() -> Self { + pub(crate) fn new() -> Self { Channel { _marker: PhantomData, } @@ -29,44 +29,45 @@ impl Channel { /// Attempts to receive a message without blocking. #[inline] - pub fn try_recv(&self) -> Result { + pub(crate) fn try_recv(&self) -> Result { Err(TryRecvError::Empty) } /// Receives a message from the channel. #[inline] - pub fn recv(&self, deadline: Option) -> Result { + pub(crate) fn recv(&self, deadline: Option) -> Result { utils::sleep_until(deadline); Err(RecvTimeoutError::Timeout) } /// Reads a message from the channel. #[inline] - pub unsafe fn read(&self, _token: &mut Token) -> Result { + pub(crate) unsafe fn read(&self, _token: &mut Token) -> Result { Err(()) } /// Returns `true` if the channel is empty. #[inline] - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { true } /// Returns `true` if the channel is full. #[inline] - pub fn is_full(&self) -> bool { + pub(crate) fn is_full(&self) -> bool { true } /// Returns the number of messages in the channel. #[inline] - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { 0 } /// Returns the capacity of the channel. + #[allow(clippy::unnecessary_wraps)] // This is intentional. #[inline] - pub fn capacity(&self) -> Option { + pub(crate) fn capacity(&self) -> Option { Some(0) } } diff --git a/vendor/crossbeam-channel/src/flavors/tick.rs b/vendor/crossbeam-channel/src/flavors/tick.rs index e8e7020ca8..d4b1f6c78d 100644 --- a/vendor/crossbeam-channel/src/flavors/tick.rs +++ b/vendor/crossbeam-channel/src/flavors/tick.rs @@ -12,10 +12,10 @@ use crate::err::{RecvTimeoutError, TryRecvError}; use crate::select::{Operation, SelectHandle, Token}; /// Result of a receive operation. -pub type TickToken = Option; +pub(crate) type TickToken = Option; /// Channel that delivers messages periodically. -pub struct Channel { +pub(crate) struct Channel { /// The instant at which the next message will be delivered. delivery_time: AtomicCell, @@ -26,7 +26,7 @@ pub struct Channel { impl Channel { /// Creates a channel that delivers messages periodically. #[inline] - pub fn new(dur: Duration) -> Self { + pub(crate) fn new(dur: Duration) -> Self { Channel { delivery_time: AtomicCell::new(Instant::now() + dur), duration: dur, @@ -35,7 +35,7 @@ impl Channel { /// Attempts to receive a message without blocking. #[inline] - pub fn try_recv(&self) -> Result { + pub(crate) fn try_recv(&self) -> Result { loop { let now = Instant::now(); let delivery_time = self.delivery_time.load(); @@ -56,7 +56,7 @@ impl Channel { /// Receives a message from the channel. #[inline] - pub fn recv(&self, deadline: Option) -> Result { + pub(crate) fn recv(&self, deadline: Option) -> Result { loop { let delivery_time = self.delivery_time.load(); let now = Instant::now(); @@ -85,25 +85,25 @@ impl Channel { /// Reads a message from the channel. #[inline] - pub unsafe fn read(&self, token: &mut Token) -> Result { + pub(crate) unsafe fn read(&self, token: &mut Token) -> Result { token.tick.ok_or(()) } /// Returns `true` if the channel is empty. #[inline] - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { Instant::now() < self.delivery_time.load() } /// Returns `true` if the channel is full. #[inline] - pub fn is_full(&self) -> bool { + pub(crate) fn is_full(&self) -> bool { !self.is_empty() } /// Returns the number of messages in the channel. #[inline] - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { if self.is_empty() { 0 } else { @@ -112,8 +112,9 @@ impl Channel { } /// Returns the capacity of the channel. + #[allow(clippy::unnecessary_wraps)] // This is intentional. #[inline] - pub fn capacity(&self) -> Option { + pub(crate) fn capacity(&self) -> Option { Some(1) } } diff --git a/vendor/crossbeam-channel/src/flavors/zero.rs b/vendor/crossbeam-channel/src/flavors/zero.rs index be647b55c8..9790b77c23 100644 --- a/vendor/crossbeam-channel/src/flavors/zero.rs +++ b/vendor/crossbeam-channel/src/flavors/zero.rs @@ -16,7 +16,7 @@ use crate::utils::Spinlock; use crate::waker::Waker; /// A pointer to a packet. -pub type ZeroToken = usize; +pub(crate) type ZeroToken = usize; /// A slot for passing one message from a sender to a receiver. struct Packet { @@ -80,7 +80,7 @@ struct Inner { } /// Zero-capacity channel. -pub struct Channel { +pub(crate) struct Channel { /// Inner representation of the channel. inner: Spinlock, @@ -90,7 +90,7 @@ pub struct Channel { impl Channel { /// Constructs a new zero-capacity channel. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Channel { inner: Spinlock::new(Inner { senders: Waker::new(), @@ -102,12 +102,12 @@ impl Channel { } /// Returns a receiver handle to the channel. - pub fn receiver(&self) -> Receiver<'_, T> { + pub(crate) fn receiver(&self) -> Receiver<'_, T> { Receiver(self) } /// Returns a sender handle to the channel. - pub fn sender(&self) -> Sender<'_, T> { + pub(crate) fn sender(&self) -> Sender<'_, T> { Sender(self) } @@ -128,7 +128,7 @@ impl Channel { } /// Writes a message into the packet. - pub unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> { + pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> { // If there is no packet, the channel is disconnected. if token.zero == 0 { return Err(msg); @@ -157,7 +157,7 @@ impl Channel { } /// Reads a message from the packet. - pub unsafe fn read(&self, token: &mut Token) -> Result { + pub(crate) unsafe fn read(&self, token: &mut Token) -> Result { // If there is no packet, the channel is disconnected. if token.zero == 0 { return Err(()); @@ -183,7 +183,7 @@ impl Channel { } /// Attempts to send a message into the channel. - pub fn try_send(&self, msg: T) -> Result<(), TrySendError> { + pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError> { let token = &mut Token::default(); let mut inner = self.inner.lock(); @@ -203,7 +203,11 @@ impl Channel { } /// Sends a message into the channel. - pub fn send(&self, msg: T, deadline: Option) -> Result<(), SendTimeoutError> { + pub(crate) fn send( + &self, + msg: T, + deadline: Option, + ) -> Result<(), SendTimeoutError> { let token = &mut Token::default(); let mut inner = self.inner.lock(); @@ -256,7 +260,7 @@ impl Channel { } /// Attempts to receive a message without blocking. - pub fn try_recv(&self) -> Result { + pub(crate) fn try_recv(&self) -> Result { let token = &mut Token::default(); let mut inner = self.inner.lock(); @@ -273,7 +277,7 @@ impl Channel { } /// Receives a message from the channel. - pub fn recv(&self, deadline: Option) -> Result { + pub(crate) fn recv(&self, deadline: Option) -> Result { let token = &mut Token::default(); let mut inner = self.inner.lock(); @@ -325,7 +329,7 @@ impl Channel { /// Disconnects the channel and wakes up all blocked senders and receivers. /// /// Returns `true` if this call disconnected the channel. - pub fn disconnect(&self) -> bool { + pub(crate) fn disconnect(&self) -> bool { let mut inner = self.inner.lock(); if !inner.is_disconnected { @@ -339,31 +343,32 @@ impl Channel { } /// Returns the current number of messages inside the channel. - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { 0 } /// Returns the capacity of the channel. - pub fn capacity(&self) -> Option { + #[allow(clippy::unnecessary_wraps)] // This is intentional. + pub(crate) fn capacity(&self) -> Option { Some(0) } /// Returns `true` if the channel is empty. - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { true } /// Returns `true` if the channel is full. - pub fn is_full(&self) -> bool { + pub(crate) fn is_full(&self) -> bool { true } } /// Receiver handle to a channel. -pub struct Receiver<'a, T>(&'a Channel); +pub(crate) struct Receiver<'a, T>(&'a Channel); /// Sender handle to a channel. -pub struct Sender<'a, T>(&'a Channel); +pub(crate) struct Sender<'a, T>(&'a Channel); impl SelectHandle for Receiver<'_, T> { fn try_select(&self, token: &mut Token) -> bool { diff --git a/vendor/crossbeam-channel/src/lib.rs b/vendor/crossbeam-channel/src/lib.rs index e08ac08f90..cc1ef112f9 100644 --- a/vendor/crossbeam-channel/src/lib.rs +++ b/vendor/crossbeam-channel/src/lib.rs @@ -294,7 +294,7 @@ //! //! * [`after`] creates a channel that delivers a single message after a certain duration of time. //! * [`tick`] creates a channel that delivers messages periodically. -//! * [`never`] creates a channel that never delivers messages. +//! * [`never`](never()) creates a channel that never delivers messages. //! //! These channels are very efficient because messages get lazily generated on receive operations. //! @@ -328,10 +328,13 @@ allow(dead_code, unused_assignments, unused_variables) ) ))] -#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] +#![warn( + missing_docs, + missing_debug_implementations, + rust_2018_idioms, + unreachable_pub +)] #![cfg_attr(not(feature = "std"), no_std)] -// matches! requires Rust 1.42 -#![allow(clippy::match_like_matches_macro)] use cfg_if::cfg_if; diff --git a/vendor/crossbeam-channel/src/select.rs b/vendor/crossbeam-channel/src/select.rs index 1488f80d5f..5259328b80 100644 --- a/vendor/crossbeam-channel/src/select.rs +++ b/vendor/crossbeam-channel/src/select.rs @@ -486,7 +486,7 @@ pub fn select_timeout<'a>( /// Blocks until a given deadline, or until one of the operations becomes ready and selects it. #[inline] -pub fn select_deadline<'a>( +pub(crate) fn select_deadline<'a>( handles: &mut [(&'a dyn SelectHandle, usize, *const u8)], deadline: Instant, ) -> Result, SelectTimeoutError> { @@ -864,9 +864,6 @@ impl<'a> Select<'a> { /// The selected operation must be completed with [`SelectedOperation::send`] /// or [`SelectedOperation::recv`]. /// - /// [`SelectedOperation::send`]: struct.SelectedOperation.html#method.send - /// [`SelectedOperation::recv`]: struct.SelectedOperation.html#method.recv - /// /// # Examples /// /// ``` diff --git a/vendor/crossbeam-channel/src/utils.rs b/vendor/crossbeam-channel/src/utils.rs index 3fe171b2e4..557b6a0d77 100644 --- a/vendor/crossbeam-channel/src/utils.rs +++ b/vendor/crossbeam-channel/src/utils.rs @@ -10,7 +10,7 @@ use std::time::{Duration, Instant}; use crossbeam_utils::Backoff; /// Randomly shuffles a slice. -pub fn shuffle(v: &mut [T]) { +pub(crate) fn shuffle(v: &mut [T]) { let len = v.len(); if len <= 1 { return; @@ -46,7 +46,7 @@ pub fn shuffle(v: &mut [T]) { } /// Sleeps until the deadline, or forever if the deadline isn't specified. -pub fn sleep_until(deadline: Option) { +pub(crate) fn sleep_until(deadline: Option) { loop { match deadline { None => thread::sleep(Duration::from_secs(1000)), @@ -62,14 +62,14 @@ pub fn sleep_until(deadline: Option) { } /// A simple spinlock. -pub struct Spinlock { +pub(crate) struct Spinlock { flag: AtomicBool, value: UnsafeCell, } impl Spinlock { /// Returns a new spinlock initialized with `value`. - pub fn new(value: T) -> Spinlock { + pub(crate) fn new(value: T) -> Spinlock { Spinlock { flag: AtomicBool::new(false), value: UnsafeCell::new(value), @@ -77,7 +77,7 @@ impl Spinlock { } /// Locks the spinlock. - pub fn lock(&self) -> SpinlockGuard<'_, T> { + pub(crate) fn lock(&self) -> SpinlockGuard<'_, T> { let backoff = Backoff::new(); while self.flag.swap(true, Ordering::Acquire) { backoff.snooze(); @@ -87,7 +87,7 @@ impl Spinlock { } /// A guard holding a spinlock locked. -pub struct SpinlockGuard<'a, T> { +pub(crate) struct SpinlockGuard<'a, T> { parent: &'a Spinlock, } diff --git a/vendor/crossbeam-channel/src/waker.rs b/vendor/crossbeam-channel/src/waker.rs index 3d0af2616c..62defa2e18 100644 --- a/vendor/crossbeam-channel/src/waker.rs +++ b/vendor/crossbeam-channel/src/waker.rs @@ -8,22 +8,22 @@ use crate::select::{Operation, Selected}; use crate::utils::Spinlock; /// Represents a thread blocked on a specific channel operation. -pub struct Entry { +pub(crate) struct Entry { /// The operation. - pub oper: Operation, + pub(crate) oper: Operation, /// Optional packet. - pub packet: usize, + pub(crate) packet: usize, /// Context associated with the thread owning this operation. - pub cx: Context, + pub(crate) cx: Context, } /// A queue of threads blocked on channel operations. /// /// This data structure is used by threads to register blocking operations and get woken up once /// an operation becomes ready. -pub struct Waker { +pub(crate) struct Waker { /// A list of select operations. selectors: Vec, @@ -34,7 +34,7 @@ pub struct Waker { impl Waker { /// Creates a new `Waker`. #[inline] - pub fn new() -> Self { + pub(crate) fn new() -> Self { Waker { selectors: Vec::new(), observers: Vec::new(), @@ -43,13 +43,13 @@ impl Waker { /// Registers a select operation. #[inline] - pub fn register(&mut self, oper: Operation, cx: &Context) { + pub(crate) fn register(&mut self, oper: Operation, cx: &Context) { self.register_with_packet(oper, 0, cx); } /// Registers a select operation and a packet. #[inline] - pub fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) { + pub(crate) fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) { self.selectors.push(Entry { oper, packet, @@ -59,7 +59,7 @@ impl Waker { /// Unregisters a select operation. #[inline] - pub fn unregister(&mut self, oper: Operation) -> Option { + pub(crate) fn unregister(&mut self, oper: Operation) -> Option { if let Some((i, _)) = self .selectors .iter() @@ -75,7 +75,7 @@ impl Waker { /// Attempts to find another thread's entry, select the operation, and wake it up. #[inline] - pub fn try_select(&mut self) -> Option { + pub(crate) fn try_select(&mut self) -> Option { let mut entry = None; if !self.selectors.is_empty() { @@ -108,7 +108,7 @@ impl Waker { /// Returns `true` if there is an entry which can be selected by the current thread. #[inline] - pub fn can_select(&self) -> bool { + pub(crate) fn can_select(&self) -> bool { if self.selectors.is_empty() { false } else { @@ -122,7 +122,7 @@ impl Waker { /// Registers an operation waiting to be ready. #[inline] - pub fn watch(&mut self, oper: Operation, cx: &Context) { + pub(crate) fn watch(&mut self, oper: Operation, cx: &Context) { self.observers.push(Entry { oper, packet: 0, @@ -132,13 +132,13 @@ impl Waker { /// Unregisters an operation waiting to be ready. #[inline] - pub fn unwatch(&mut self, oper: Operation) { + pub(crate) fn unwatch(&mut self, oper: Operation) { self.observers.retain(|e| e.oper != oper); } /// Notifies all operations waiting to be ready. #[inline] - pub fn notify(&mut self) { + pub(crate) fn notify(&mut self) { for entry in self.observers.drain(..) { if entry.cx.try_select(Selected::Operation(entry.oper)).is_ok() { entry.cx.unpark(); @@ -148,7 +148,7 @@ impl Waker { /// Notifies all registered operations that the channel is disconnected. #[inline] - pub fn disconnect(&mut self) { + pub(crate) fn disconnect(&mut self) { for entry in self.selectors.iter() { if entry.cx.try_select(Selected::Disconnected).is_ok() { // Wake the thread up. @@ -175,7 +175,7 @@ impl Drop for Waker { /// A waker that can be shared among threads without locking. /// /// This is a simple wrapper around `Waker` that internally uses a mutex for synchronization. -pub struct SyncWaker { +pub(crate) struct SyncWaker { /// The inner `Waker`. inner: Spinlock, @@ -186,7 +186,7 @@ pub struct SyncWaker { impl SyncWaker { /// Creates a new `SyncWaker`. #[inline] - pub fn new() -> Self { + pub(crate) fn new() -> Self { SyncWaker { inner: Spinlock::new(Waker::new()), is_empty: AtomicBool::new(true), @@ -195,7 +195,7 @@ impl SyncWaker { /// Registers the current thread with an operation. #[inline] - pub fn register(&self, oper: Operation, cx: &Context) { + pub(crate) fn register(&self, oper: Operation, cx: &Context) { let mut inner = self.inner.lock(); inner.register(oper, cx); self.is_empty.store( @@ -206,7 +206,7 @@ impl SyncWaker { /// Unregisters an operation previously registered by the current thread. #[inline] - pub fn unregister(&self, oper: Operation) -> Option { + pub(crate) fn unregister(&self, oper: Operation) -> Option { let mut inner = self.inner.lock(); let entry = inner.unregister(oper); self.is_empty.store( @@ -218,7 +218,7 @@ impl SyncWaker { /// Attempts to find one thread (not the current one), select its operation, and wake it up. #[inline] - pub fn notify(&self) { + pub(crate) fn notify(&self) { if !self.is_empty.load(Ordering::SeqCst) { let mut inner = self.inner.lock(); if !self.is_empty.load(Ordering::SeqCst) { @@ -234,7 +234,7 @@ impl SyncWaker { /// Registers an operation waiting to be ready. #[inline] - pub fn watch(&self, oper: Operation, cx: &Context) { + pub(crate) fn watch(&self, oper: Operation, cx: &Context) { let mut inner = self.inner.lock(); inner.watch(oper, cx); self.is_empty.store( @@ -245,7 +245,7 @@ impl SyncWaker { /// Unregisters an operation waiting to be ready. #[inline] - pub fn unwatch(&self, oper: Operation) { + pub(crate) fn unwatch(&self, oper: Operation) { let mut inner = self.inner.lock(); inner.unwatch(oper); self.is_empty.store( @@ -256,7 +256,7 @@ impl SyncWaker { /// Notifies all threads that the channel is disconnected. #[inline] - pub fn disconnect(&self) { + pub(crate) fn disconnect(&self) { let mut inner = self.inner.lock(); inner.disconnect(); self.is_empty.store( diff --git a/vendor/crossbeam-channel/tests/array.rs b/vendor/crossbeam-channel/tests/array.rs index a7ae323d91..15c30a50b1 100644 --- a/vendor/crossbeam-channel/tests/array.rs +++ b/vendor/crossbeam-channel/tests/array.rs @@ -497,8 +497,8 @@ fn drops() { let mut rng = thread_rng(); for _ in 0..RUNS { - let steps = rng.gen_range(0, 10_000); - let additional = rng.gen_range(0, 50); + let steps = rng.gen_range(0..10_000); + let additional = rng.gen_range(0..50); DROPS.store(0, Ordering::SeqCst); let (s, r) = bounded::(50); diff --git a/vendor/crossbeam-channel/tests/golang.rs b/vendor/crossbeam-channel/tests/golang.rs index 69a9315a0a..cd7001326f 100644 --- a/vendor/crossbeam-channel/tests/golang.rs +++ b/vendor/crossbeam-channel/tests/golang.rs @@ -315,7 +315,7 @@ mod fifo { fn chain(ch: Chan, val: i32, inp: Chan, out: Chan) { inp.recv(); if ch.recv() != Some(val) { - panic!(val); + panic!("{}", val); } out.send(1); } @@ -1507,5 +1507,58 @@ mod chan { // https://github.com/golang/go/blob/master/test/ken/chan1.go mod chan1 { - // TODO + use super::*; + + // sent messages + const N: usize = 1000; + // receiving "goroutines" + const M: usize = 10; + // channel buffering + const W: usize = 2; + + fn r(c: Chan, m: usize, h: Arc>) { + loop { + select! { + recv(c.rx()) -> rr => { + let r = rr.unwrap(); + let mut data = h.lock().unwrap(); + if data[r] != 1 { + println!("r\nm={}\nr={}\nh={}\n", m, r, data[r]); + panic!("fail") + } + data[r] = 2; + } + } + } + } + + fn s(c: Chan, h: Arc>) { + for n in 0..N { + let r = n; + let mut data = h.lock().unwrap(); + if data[r] != 0 { + println!("s"); + panic!("fail"); + } + data[r] = 1; + // https://github.com/crossbeam-rs/crossbeam/pull/615#discussion_r550281094 + drop(data); + c.send(r); + } + } + + #[test] + fn main() { + let h = Arc::new(Mutex::new([0usize; N])); + let c = make::(W); + for m in 0..M { + go!(c, h, { + r(c, m, h); + }); + thread::yield_now(); + } + thread::yield_now(); + thread::yield_now(); + s(c, h); + } } diff --git a/vendor/crossbeam-channel/tests/list.rs b/vendor/crossbeam-channel/tests/list.rs index 8b84105406..f166a19815 100644 --- a/vendor/crossbeam-channel/tests/list.rs +++ b/vendor/crossbeam-channel/tests/list.rs @@ -387,8 +387,8 @@ fn drops() { let mut rng = thread_rng(); for _ in 0..100 { - let steps = rng.gen_range(0, 10_000); - let additional = rng.gen_range(0, 1000); + let steps = rng.gen_range(0..10_000); + let additional = rng.gen_range(0..1000); DROPS.store(0, Ordering::SeqCst); let (s, r) = unbounded::(); diff --git a/vendor/crossbeam-channel/tests/ready.rs b/vendor/crossbeam-channel/tests/ready.rs index 700f487e04..6779694a97 100644 --- a/vendor/crossbeam-channel/tests/ready.rs +++ b/vendor/crossbeam-channel/tests/ready.rs @@ -606,8 +606,7 @@ fn stress_timeout_two_threads() { thread::sleep(ms(500)); } - let done = false; - while !done { + loop { let mut sel = Select::new(); sel.send(&s); match sel.ready_timeout(ms(100)) { @@ -628,15 +627,14 @@ fn stress_timeout_two_threads() { thread::sleep(ms(500)); } - let mut done = false; - while !done { + loop { let mut sel = Select::new(); sel.recv(&r); match sel.ready_timeout(ms(100)) { Err(_) => {} Ok(0) => { assert_eq!(r.try_recv(), Ok(i)); - done = true; + break; } Ok(_) => panic!(), } diff --git a/vendor/crossbeam-channel/tests/select.rs b/vendor/crossbeam-channel/tests/select.rs index 4cf08b6a62..fcc291ef38 100644 --- a/vendor/crossbeam-channel/tests/select.rs +++ b/vendor/crossbeam-channel/tests/select.rs @@ -809,8 +809,7 @@ fn stress_timeout_two_threads() { thread::sleep(ms(500)); } - let done = false; - while !done { + loop { let mut sel = Select::new(); let oper1 = sel.send(&s); let oper = sel.select_timeout(ms(100)); @@ -834,8 +833,7 @@ fn stress_timeout_two_threads() { thread::sleep(ms(500)); } - let mut done = false; - while !done { + loop { let mut sel = Select::new(); let oper1 = sel.recv(&r); let oper = sel.select_timeout(ms(100)); @@ -844,7 +842,7 @@ fn stress_timeout_two_threads() { Ok(oper) => match oper.index() { ix if ix == oper1 => { assert_eq!(oper.recv(&r), Ok(i)); - done = true; + break; } _ => unreachable!(), }, diff --git a/vendor/crossbeam-channel/tests/tick.rs b/vendor/crossbeam-channel/tests/tick.rs index 5dc87306ff..1273f64b5b 100644 --- a/vendor/crossbeam-channel/tests/tick.rs +++ b/vendor/crossbeam-channel/tests/tick.rs @@ -127,6 +127,7 @@ fn recv() { assert_eq!(r.try_recv(), Err(TryRecvError::Empty)); } +#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow #[test] fn recv_timeout() { let start = Instant::now(); @@ -251,6 +252,7 @@ fn select() { assert_eq!(hits.load(Ordering::SeqCst), 8); } +#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow #[test] fn ready() { const THREADS: usize = 4; diff --git a/vendor/crossbeam-channel/tests/zero.rs b/vendor/crossbeam-channel/tests/zero.rs index 66dcc1eeb6..1dd39e1817 100644 --- a/vendor/crossbeam-channel/tests/zero.rs +++ b/vendor/crossbeam-channel/tests/zero.rs @@ -399,7 +399,7 @@ fn drops() { let mut rng = thread_rng(); for _ in 0..100 { - let steps = rng.gen_range(0, 3_000); + let steps = rng.gen_range(0..3_000); DROPS.store(0, Ordering::SeqCst); let (s, r) = bounded::(0); diff --git a/vendor/dirs-sys/.cargo-checksum.json b/vendor/dirs-sys/.cargo-checksum.json index 37b8b33136..d095c8ac5c 100644 --- a/vendor/dirs-sys/.cargo-checksum.json +++ b/vendor/dirs-sys/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"e3275b30fa8db88cf0e0db5bd34fb1a46ea99c8f5dbe3a9882f096be8d9c5b24","LICENSE-APACHE":"d3174ad63e721d4c9dccb8ad4320848992d314369bc46319720b5802c9153fe9","LICENSE-MIT":"6a2e0ade09a7d5f816f11566fee2b151b32235a7fad52b41d49cce96f833c1a9","README.md":"1c818a4ea3bf85aaafe27421528a285db92c1f20ae9651c669379cb603495f37","src/lib.rs":"7641c8b0f3951e8ce233cc6dc428b3e4919b4959b25efb6e88d4ecdedc672fd2","src/xdg_user_dirs.rs":"225ae21a97b839330a8c3bc8e0a0b48e40580cbae25bfc47581dff724bb0ebec"},"package":"8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"} \ No newline at end of file +{"files":{"Cargo.toml":"141e80efbaefa9322513f4900a2ac4c5209b135bb36bf7ca347e3deebc75965f","LICENSE-APACHE":"d3174ad63e721d4c9dccb8ad4320848992d314369bc46319720b5802c9153fe9","LICENSE-MIT":"6a2e0ade09a7d5f816f11566fee2b151b32235a7fad52b41d49cce96f833c1a9","README.md":"1c818a4ea3bf85aaafe27421528a285db92c1f20ae9651c669379cb603495f37","src/lib.rs":"5c1aff249eb1f6abd52785f58318c1b0641ca810c15ce349e9c3797d86b1c8c5","src/xdg_user_dirs.rs":"225ae21a97b839330a8c3bc8e0a0b48e40580cbae25bfc47581dff724bb0ebec"},"package":"03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"} \ No newline at end of file diff --git a/vendor/dirs-sys/Cargo.toml b/vendor/dirs-sys/Cargo.toml index 4a4116d60b..6c4100798f 100644 --- a/vendor/dirs-sys/Cargo.toml +++ b/vendor/dirs-sys/Cargo.toml @@ -12,14 +12,15 @@ [package] name = "dirs-sys" -version = "0.3.5" +version = "0.3.6" authors = ["Simon Ochsenreither "] description = "System-level helper functions for the dirs and directories crates." readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/dirs-dev/dirs-sys-rs" [target."cfg(target_os = \"redox\")".dependencies.redox_users] -version = "0.3.0" +version = "0.4" +default-features = false [target."cfg(unix)".dependencies.libc] version = "0.2" [target."cfg(windows)".dependencies.winapi] diff --git a/vendor/dirs-sys/src/lib.rs b/vendor/dirs-sys/src/lib.rs index 9061def755..cd5bb4794b 100644 --- a/vendor/dirs-sys/src/lib.rs +++ b/vendor/dirs-sys/src/lib.rs @@ -158,6 +158,7 @@ pub fn known_folder(folder_id: shtypes::REFKNOWNFOLDERID) -> Option { combaseapi::CoTaskMemFree(path_ptr as *mut winapi::ctypes::c_void); Some(PathBuf::from(ostr)) } else { + combaseapi::CoTaskMemFree(path_ptr as *mut winapi::ctypes::c_void); None } } diff --git a/vendor/fs_extra/.cargo-checksum.json b/vendor/fs_extra/.cargo-checksum.json deleted file mode 100644 index d030154984..0000000000 --- a/vendor/fs_extra/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"5ffc0f40c4f9d9cdd3895f3fcaa8bf5262f89eb6750ab98dbaa784ea809f1059","LICENSE":"251ea8ccb1205ce5fa847d6e264d6b6753af62de2cecf2fd9abc0eb02c7c83fc","README.md":"e178fdaf57d699192aaf57ae625742a9489023895fd3645741a36873e2af5d22","src/dir.rs":"f778f1e14f4dc524050f4422fa4d9c245ba34e0f88eff41911b2eb1c7ce5835f","src/error.rs":"ff3a36b0496939f7d741a4966da0d0014e3a33d26ef1e5861a15823fa7f4c1da","src/file.rs":"34d0f62f3ce7d30e96f70a8587406dead6d568796656e9136951c72840e90e06","src/lib.rs":"e45129f6dd59da2d1ce5d0ab80f439d195068660298d96046a28f372778428a8","tests/dir.rs":"4e3ebe83f033588243754bbcd905e0e539cb3c7fe3b6864ddfa3dee44bf01ac1","tests/file.rs":"375f1230afd021051541490ab50b5f1a53563617236524cc3287f018dd89262a","tests/lib.rs":"4d573c8d93e790e2b409e1e7caeae9340760e9680ffafae0f0370684298eb6a7"},"package":"2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"} \ No newline at end of file diff --git a/vendor/fs_extra/Cargo.toml b/vendor/fs_extra/Cargo.toml deleted file mode 100644 index 49a40befb9..0000000000 --- a/vendor/fs_extra/Cargo.toml +++ /dev/null @@ -1,25 +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 = "fs_extra" -version = "1.2.0" -authors = ["Denis Kurilenko "] -include = ["**/*.rs", "Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md"] -description = "Expanding opportunities standard library std::fs and std::io. Recursively copy folders with recept information about process and much more." -homepage = "https://github.com/webdesus/fs_extra" -documentation = "https://docs.rs/fs_extra" -keywords = ["filesystem", "recursion", "copy", "dir", "file"] -license = "MIT" -repository = "https://github.com/webdesus/fs_extra" - -[dependencies] diff --git a/vendor/fs_extra/LICENSE b/vendor/fs_extra/LICENSE deleted file mode 100644 index 2f97c3d7dc..0000000000 --- a/vendor/fs_extra/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Denis Kurilenko - -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/fs_extra/README.md b/vendor/fs_extra/README.md deleted file mode 100644 index 2d7ca214a5..0000000000 --- a/vendor/fs_extra/README.md +++ /dev/null @@ -1,134 +0,0 @@ -# fs_extra - -A Rust library that provides additional functionality not present in [`std::fs`](https://doc.rust-lang.org/std/fs/index.html). - -[![Build Status](https://travis-ci.org/webdesus/fs_extra.svg)](https://travis-ci.org/webdesus/fs_extra) -[![Crates.io Status](https://img.shields.io/crates/v/fs_extra.svg)](https://crates.io/crates/fs_extra) -[![Docs](https://docs.rs/fs_extra/badge.svg)](https://docs.rs/fs_extra) - -[Documentation](https://docs.rs/fs_extra) - -[Migrations to 1.x.x version](https://github.com/webdesus/fs_extra/wiki/Migrations-to-1.x.x-version) - - -## Key features: - -* Copy files (optionally with information about the progress). - -* Copy directories recursively (optionally with information about the progress). - -* Move files (optionally with information about the progress). - -* Move directories recursively (optionally with information about the progress). - -* A single method for create and write `String` content in file. - -* A single method for open and read `String` content from file. - -* Get folder size - -* Get collection of directory entries - -## Functions: - -| Function | Description | -| ------------- | ------------- | -| [fs_extra::copy_items](https://docs.rs/fs_extra/*/fs_extra/fn.copy_items.html) | Recursively copies files and directories from one location to another | -| [fs_extra::copy_items_with_progress](https://docs.rs/fs_extra/*/fs_extra/fn.copy_items_with_progress.html) | Recursively copies files and directories from one location to another with information about progress | -| [fs_extra::move_items](https://docs.rs/fs_extra/*/fs_extra/fn.move_items.html) | Recursively moves files and directories from one location to another | -| [fs_extra::move_items_with_progress](https://docs.rs/fs_extra/*/fs_extra/fn.move_items_with_progress.html) | Recursively moves files and directories from one location to another with information about progress | -| [fs_extra::remove_items](https://docs.rs/fs_extra/*/fs_extra/fn.remove_items.html) | Removes files or directories | -| [fs_extra::file::copy](https://docs.rs/fs_extra/*/fs_extra/file/fn.copy.html) | Copies the contents of one file to another | -| [fs_extra::file::copy_with_progress](https://docs.rs/fs_extra/*/fs_extra/file/fn.copy_with_progress.html) | Copies the contents of one file to another with information about progress | -| [fs_extra::file::move_file](https://docs.rs/fs_extra/*/fs_extra/file/fn.move_file.html) | Moves a file from one location to another | -| [fs_extra::file::move_file_with_progress](https://docs.rs/fs_extra/*/fs_extra/file/fn.move_file_with_progress.html) | Moves a file from one location to another with information about progress | -| [fs_extra::file::remove](https://docs.rs/fs_extra/*/fs_extra/file/fn.remove.html) | Removes a file | -| [fs_extra::file::read_to_string](https://docs.rs/fs_extra/*/fs_extra/file/fn.read_to_string.html) | Reads file content into a `String` | -| [fs_extra::file::write_all](https://docs.rs/fs_extra/*/fs_extra/file/fn.write_all.html) | Writes `String` content to a file | -| [fs_extra::dir::create](https://docs.rs/fs_extra/*/fs_extra/dir/fn.create.html) | Creates a new, empty directory at the given path | -| [fs_extra::dir::create_all](https://docs.rs/fs_extra/*/fs_extra/dir/fn.create_all.html) | Recursively creates a directory and all of its parent components if they are missing | -| [fs_extra::dir::copy](https://docs.rs/fs_extra/*/fs_extra/dir/fn.copy.html) | Recursively copies the directory contents from one location to another | -| [fs_extra::dir::copy_with_progress](https://docs.rs/fs_extra/*/fs_extra/dir/fn.copy_with_progress.html) | Recursively copies the directory contents from one location to another with information about progress | -| [fs_extra::dir::move_dir](https://docs.rs/fs_extra/*/fs_extra/dir/fn.move_dir.html) | Moves directory contents from one location to another | -| [fs_extra::dir::move_dir_with_progress](https://docs.rs/fs_extra/*/fs_extra/dir/fn.move_dir_with_progress.html) | Moves directory contents from one location to another with information about progress | -| [fs_extra::dir::remove](https://docs.rs/fs_extra/*/fs_extra/dir/fn.remove.html) | Removes directory | -| [fs_extra::dir::get_size](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_size.html) | Returns the size of the file or directory | -| [fs_extra::dir::get_dir_content](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_dir_content.html) | Gets details such as the size and child items of a directory | -| [fs_extra::dir::get_dir_content2](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_dir_content2.html) | Gets details such as the size and child items of a directory using specified settings | -| [fs_extra::dir::get_details_entry](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_details_entry.html) | Gets attributes of a directory entry | -| [fs_extra::dir::ls](https://docs.rs/fs_extra/*/fs_extra/dir/fn.ls.html) | Gets attributes of directory entries in a directory | - -## Usage - -Add this to your `Cargo.toml`: -```toml -[dependencies] -fs_extra = "1.2.0" -``` -## Examples - -The following example shows how to copy a directory recursively and display progress. First a source directory `./temp/dir` containing file `test1.txt` and a subdirectory `sub` is createad with `sub` itself having a file `test2.txt`. `./temp/dir` and all contents are then copied out to `./out/dir`. - -```rust -use std::path::Path; -use std::{thread, time}; -use std::sync::mpsc::{self, TryRecvError}; - -extern crate fs_extra; -use fs_extra::dir::*; -use fs_extra::error::*; - -fn example_copy() -> Result<()> { - - let path_from = Path::new("./temp"); - let path_to = path_from.join("out"); - let test_folder = path_from.join("test_folder"); - let dir = test_folder.join("dir"); - let sub = dir.join("sub"); - let file1 = dir.join("file1.txt"); - let file2 = sub.join("file2.txt"); - - create_all(&sub, true)?; - create_all(&path_to, true)?; - fs_extra::file::write_all(&file1, "content1")?; - fs_extra::file::write_all(&file2, "content2")?; - - assert!(dir.exists()); - assert!(sub.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - - - let mut options = CopyOptions::new(); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - thread::spawn(move || { - let handler = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - thread::sleep(time::Duration::from_millis(500)); - fs_extra::dir::TransitProcessResult::ContinueOrAbort - }; - copy_with_progress(&test_folder, &path_to, &options, handler).unwrap(); - }); - - loop { - match rx.try_recv() { - Ok(process_info) => { - println!("{} of {} bytes", - process_info.copied_bytes, - process_info.total_bytes); - } - Err(TryRecvError::Disconnected) => { - println!("finished"); - break; - } - Err(TryRecvError::Empty) => {} - } - } - Ok(()) - -} -fn main() { - example_copy(); -} -``` diff --git a/vendor/fs_extra/src/dir.rs b/vendor/fs_extra/src/dir.rs deleted file mode 100644 index 905c88cb1e..0000000000 --- a/vendor/fs_extra/src/dir.rs +++ /dev/null @@ -1,1349 +0,0 @@ -use error::*; -use std::collections::{HashMap, HashSet}; -use std::fs::{create_dir, create_dir_all, read_dir, remove_dir_all, Metadata}; -use std::path::{Path, PathBuf}; -use std::time::SystemTime; - -/// Options and flags which can be used to configure how a file will be copied or moved. -#[derive(Clone)] -pub struct CopyOptions { - /// Sets the option true for overwrite existing files. - pub overwrite: bool, - /// Sets the option true for skipe existing files. - pub skip_exist: bool, - /// Sets buffer size for copy/move work only with receipt information about process work. - pub buffer_size: usize, - /// Sets the option true for recursively copying a directory with a new name or place it inside the destination.(same behaviors like cp -r in Unix) - pub copy_inside: bool, - /// Sets the option true, for copy only content without a created folder in the destination folder - pub content_only: bool, - /// Sets levels reading. Set 0 for read all directory folder. By default 0. - /// - /// Warrning: Work only for copy operations! - pub depth: u64, -} - -impl CopyOptions { - /// Initialize struct CopyOptions with default value. - /// - /// ```rust,ignore - /// overwrite: false - /// - /// skip_exist: false - /// - /// buffer_size: 64000 //64kb - /// - /// copy_inside: false - /// ``` - pub fn new() -> CopyOptions { - CopyOptions { - overwrite: false, - skip_exist: false, - buffer_size: 64000, //64kb - copy_inside: false, - content_only: false, - depth: 0, - } - } -} - -impl Default for CopyOptions { - fn default() -> Self { - CopyOptions::new() - } -} - -/// Options and flags which can be used to configure how read a directory. -#[derive(Clone, Default)] -pub struct DirOptions { - /// Sets levels reading. Set value 0 for read all directory folder. By default 0. - pub depth: u64, -} - -impl DirOptions { - /// Initialize struct DirOptions with default value. - pub fn new() -> DirOptions { - Default::default() - } -} - -/// A structure which imclude information about directory -pub struct DirContent { - /// Directory size. - pub dir_size: u64, - /// List all files directory and sub directories. - pub files: Vec, - /// List all folders and sub folders directory. - pub directories: Vec, -} - -/// A structure which include information about the current status of the copy or move directory. -pub struct TransitProcess { - /// Copied bytes on this time for folder - pub copied_bytes: u64, - /// All the bytes which should to copy or move (dir size). - pub total_bytes: u64, - /// Copied bytes on this time for file. - pub file_bytes_copied: u64, - /// Size current copied file. - pub file_total_bytes: u64, - /// Name current copied file. - pub file_name: String, - /// Transit state - pub state: TransitState, -} - -/// -#[derive(Hash, Eq, PartialEq, Clone)] -pub enum TransitState { - /// Standart state. - Normal, - /// Pause state when destination path is exist. - Exists, - /// Pause state when current process does not have the permission rights to acess from or to - /// path. - NoAccess, -} - -/// Available returns codes for user decide -pub enum TransitProcessResult { - /// Rewrite exist file or directory. - Overwrite, - /// Rewrite for all exist files or directories. - OverwriteAll, - /// Skip current problem file or directory. - Skip, - /// Skip for all problems file or directory. - SkipAll, - /// Retry current operation. - Retry, - /// Abort current operation. - Abort, - /// Continue execute process if process not have error and abort if process content error. - ContinueOrAbort, -} - -impl Clone for TransitProcess { - fn clone(&self) -> TransitProcess { - TransitProcess { - copied_bytes: self.copied_bytes, - total_bytes: self.total_bytes, - file_bytes_copied: self.file_bytes_copied, - file_total_bytes: self.file_total_bytes, - file_name: self.file_name.clone(), - state: self.state.clone(), - } - } -} - -/// Available attributes for get information about directory entry. -#[derive(Hash, Eq, PartialEq, Clone)] -pub enum DirEntryAttr { - /// Folder name or file name without extension. - Name, - /// File extension. - Ext, - /// Folder name or file name with extention. - FullName, - /// Path to file or directory. - Path, - /// Dos path to file or directory. - DosPath, - /// File size in bytes. - FileSize, - /// Size file or directory in bytes. - /// - /// `Attention!`: This operation very expensive and sometimes required additional rights. - Size, - /// Return whether entry is directory or not. - IsDir, - /// Return whether entry is file or not. - IsFile, - /// Last modification time for directory entry. - Modified, - /// Last access time for directory entry. - Accessed, - /// Created time for directory entry. - /// - /// `Attention!`: Not supported UNIX platform. - Created, - /// Return or not return base information target folder. - BaseInfo, -} - -/// Available types for directory entry. -pub enum DirEntryValue { - /// String type - String(String), - /// Boolean type - Boolean(bool), - /// SystemTime type - SystemTime(SystemTime), - /// u64 type - U64(u64), -} - -/// Result returned by the `ls` function. -pub struct LsResult { - /// Base folder target path - pub base: HashMap, - /// Collection directory entry with information. - pub items: Vec>, -} - -/// Returned information about directory entry with information which you choose in config. -/// -/// This function takes to arguments: -/// -/// * `path` - Path to directory. -/// -/// * `config` - Set attributes which you want see inside return data. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `path` does not exist. -/// * Invalid `path`. -/// * The current process does not have the permission rights to access `path`. -/// -/// #Examples -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::{get_details_entry, DirEntryAttr}; -/// use std::collections::{HashMap, HashSet}; -/// -/// let mut config = HashSet::new(); -/// config.insert(DirEntryAttr::Name); -/// config.insert(DirEntryAttr::Size); -/// -/// let entry_info = get_details_entry("test", &config); -/// assert_eq!(2, entry_info.len()); -/// ``` -pub fn get_details_entry

( - path: P, - config: &HashSet, -) -> Result> -where - P: AsRef, -{ - let path = path.as_ref(); - let metadata = path.metadata()?; - get_details_entry_with_meta(path, config, metadata) -} -fn get_details_entry_with_meta

( - path: P, - config: &HashSet, - metadata: Metadata, -) -> Result> -where - P: AsRef, -{ - let path = path.as_ref(); - let mut item = HashMap::new(); - if config.contains(&DirEntryAttr::Name) { - if metadata.is_dir() { - if let Some(file_name) = path.file_name() { - item.insert( - DirEntryAttr::Name, - DirEntryValue::String(file_name.to_os_string().into_string()?), - ); - } else { - item.insert(DirEntryAttr::Name, DirEntryValue::String(String::new())); - } - } else { - if let Some(file_stem) = path.file_stem() { - item.insert( - DirEntryAttr::Name, - DirEntryValue::String(file_stem.to_os_string().into_string()?), - ); - } else { - item.insert(DirEntryAttr::Name, DirEntryValue::String(String::new())); - } - } - } - if config.contains(&DirEntryAttr::Ext) { - if let Some(value) = path.extension() { - item.insert( - DirEntryAttr::Ext, - DirEntryValue::String(value.to_os_string().into_string()?), - ); - } else { - item.insert(DirEntryAttr::Ext, DirEntryValue::String(String::from(""))); - } - } - if config.contains(&DirEntryAttr::FullName) { - if let Some(file_name) = path.file_name() { - item.insert( - DirEntryAttr::FullName, - DirEntryValue::String(file_name.to_os_string().into_string()?), - ); - } else { - item.insert(DirEntryAttr::FullName, DirEntryValue::String(String::new())); - } - } - if config.contains(&DirEntryAttr::Path) { - let mut result_path: PathBuf; - match path.canonicalize() { - Ok(new_path) => { - result_path = new_path; - } - Err(_) => { - if let Some(parent_path) = path.parent() { - if let Some(name) = path.file_name() { - result_path = parent_path.canonicalize()?; - result_path.push(name); - } else { - err!("Error get part name path", ErrorKind::Other); - } - } else { - err!("Error get parent path", ErrorKind::Other); - } - } - } - let mut path = result_path.as_os_str().to_os_string().into_string()?; - if path.find("\\\\?\\") == Some(0) { - path = path[4..].to_string(); - } - item.insert(DirEntryAttr::Path, DirEntryValue::String(path)); - } - if config.contains(&DirEntryAttr::DosPath) { - let mut result_path: PathBuf; - match path.canonicalize() { - Ok(new_path) => { - result_path = new_path; - } - Err(_) => { - if let Some(parent_path) = path.parent() { - if let Some(name) = path.file_name() { - result_path = parent_path.canonicalize()?; - result_path.push(name); - } else { - err!("Error get part name path", ErrorKind::Other); - } - } else { - err!("Error get parent path", ErrorKind::Other); - } - } - } - let path = result_path.as_os_str().to_os_string().into_string()?; - item.insert(DirEntryAttr::DosPath, DirEntryValue::String(path)); - } - if config.contains(&DirEntryAttr::Size) { - item.insert(DirEntryAttr::Size, DirEntryValue::U64(get_size(&path)?)); - } - if config.contains(&DirEntryAttr::FileSize) { - item.insert(DirEntryAttr::FileSize, DirEntryValue::U64(metadata.len())); - } - if config.contains(&DirEntryAttr::IsDir) { - item.insert( - DirEntryAttr::IsDir, - DirEntryValue::Boolean(metadata.is_dir()), - ); - } - if config.contains(&DirEntryAttr::IsFile) { - item.insert( - DirEntryAttr::IsFile, - DirEntryValue::Boolean(metadata.is_file()), - ); - } - if config.contains(&DirEntryAttr::Modified) { - item.insert( - DirEntryAttr::Modified, - DirEntryValue::SystemTime(metadata.modified()?), - ); - } - if config.contains(&DirEntryAttr::Accessed) { - item.insert( - DirEntryAttr::Accessed, - DirEntryValue::SystemTime(metadata.accessed()?), - ); - } - if config.contains(&DirEntryAttr::Created) { - item.insert( - DirEntryAttr::Created, - DirEntryValue::SystemTime(metadata.created()?), - ); - } - Ok(item) -} - -/// Returned collection directory entries with information which you choose in config. -/// -/// This function takes to arguments: -/// -/// * `path` - Path to directory. -/// -/// * `config` - Set attributes which you want see inside return data. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `path` directory does not exist. -/// * Invalid `path`. -/// * The current process does not have the permission rights to access `path`. -/// -/// #Examples -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::{ls, DirEntryAttr, LsResult}; -/// use std::collections::HashSet; -/// -/// let mut config = HashSet::new(); -/// config.insert(DirEntryAttr::Name); -/// config.insert(DirEntryAttr::Size); -/// config.insert(DirEntryAttr::BaseInfo); -/// -/// let result = ls("test", &config); -/// assert_eq!(2, ls_result.items.len()); -/// assert_eq!(2, ls_result.base.len()); -/// ``` -pub fn ls

(path: P, config: &HashSet) -> Result -where - P: AsRef, -{ - let mut items = Vec::new(); - let path = path.as_ref(); - if !path.is_dir() { - err!("Path does not directory", ErrorKind::InvalidFolder); - } - for entry in read_dir(&path)? { - let entry = entry?; - let path = entry.path(); - let metadata = entry.metadata()?; - let item = get_details_entry_with_meta(path, &config, metadata)?; - items.push(item); - } - let mut base = HashMap::new(); - if config.contains(&DirEntryAttr::BaseInfo) { - base = get_details_entry(&path, &config)?; - } - Ok(LsResult { - items: items, - base: base, - }) -} - -/// Creates a new, empty directory at the provided path. -/// -/// This function takes to arguments: -/// -/// * `path` - Path to new directory. -/// -/// * `erase` - If set true and folder exist, then folder will be erased. -/// -/// #Errors -/// -/// This function will return an error in the following situations, -/// but is not limited to just these cases: -/// -/// * User lacks permissions to create directory at `path`. -/// -/// * `path` already exists if `erase` set false. -/// -/// #Examples -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::create; -/// -/// create("dir", false); // create directory -/// ``` -pub fn create

(path: P, erase: bool) -> Result<()> -where - P: AsRef, -{ - if erase && path.as_ref().exists() { - remove(&path)?; - } - Ok(create_dir(&path)?) -} - -/// Recursively create a directory and all of its parent components if they are missing. -/// -/// This function takes to arguments: -/// -/// * `path` - Path to new directory. -/// -/// * `erase` - If set true and folder exist, then folder will be erased. -/// -///#Errors -/// -/// This function will return an error in the following situations, -/// but is not limited to just these cases: -/// -/// * User lacks permissions to create directory at `path`. -/// -/// * `path` already exists if `erase` set false. -/// -/// #Examples -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::create_all; -/// -/// create_all("/some/dir", false); // create directory some and dir -pub fn create_all

(path: P, erase: bool) -> Result<()> -where - P: AsRef, -{ - if erase && path.as_ref().exists() { - remove(&path)?; - } - Ok(create_dir_all(&path)?) -} - -/// Copies the directory contents from one place to another using recursive method. -/// This function will also copy the permission bits of the original files to -/// destionation files (not for directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a directory. -/// * This `from` directory does not exist. -/// * Invalid folder name for `from` or `to`. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::copy; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// // options.mirror_copy = true; // To mirror copy the whole structure of the source directory -/// -/// -/// // copy source/dir1 to target/dir1 -/// copy("source/dir1", "target/dir1", &options)?; -/// -/// ``` -pub fn copy(from: P, to: Q, options: &CopyOptions) -> Result -where - P: AsRef, - Q: AsRef, -{ - let from = from.as_ref(); - - if !from.exists() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" does not exist or you don't have access!", msg); - err!(&msg, ErrorKind::NotFound); - } - err!( - "Path does not exist Or you don't have access!", - ErrorKind::NotFound - ); - } - if !from.is_dir() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" is not a directory!", msg); - err!(&msg, ErrorKind::InvalidFolder); - } - err!("Path is not a directory!", ErrorKind::InvalidFolder); - } - let dir_name; - if let Some(val) = from.components().last() { - dir_name = val.as_os_str(); - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - let mut to: PathBuf = to.as_ref().to_path_buf(); - if !options.content_only && ((options.copy_inside && to.exists()) || !options.copy_inside) { - to.push(dir_name); - } - - let mut read_options = DirOptions::new(); - if options.depth > 0 { - read_options.depth = options.depth; - } - - let dir_content = get_dir_content2(from, &read_options)?; - for directory in dir_content.directories { - let tmp_to = Path::new(&directory).strip_prefix(from)?; - let dir = to.join(&tmp_to); - if !dir.exists() { - if options.copy_inside { - create_all(dir, false)?; - } else { - create(dir, false)?; - } - } - } - let mut result: u64 = 0; - for file in dir_content.files { - let to = to.to_path_buf(); - let tp = Path::new(&file).strip_prefix(from)?; - let path = to.join(&tp); - - let file_options = super::file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - buffer_size: options.buffer_size, - }; - let mut result_copy: Result; - let mut work = true; - - while work { - result_copy = super::file::copy(&file, &path, &file_options); - match result_copy { - Ok(val) => { - result += val; - work = false; - } - Err(err) => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - } - Ok(result) -} - -/// Return DirContent which containt information about directory: -/// -/// * Size directory. -/// * List all files source directory(files subdirectories included too). -/// * List all directory and subdirectories source path. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `path` directory does not exist. -/// * Invalid `path`. -/// * The current process does not have the permission rights to access `path`. -/// -/// # Examples -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::get_dir_content; -/// -/// let dir_content = get_dir_content("dir")?; -/// for directory in dir_content.directories { -/// println!("{}", directory); // print directory path -/// } -/// ``` -/// -pub fn get_dir_content

(path: P) -> Result -where - P: AsRef, -{ - let options = DirOptions::new(); - get_dir_content2(path, &options) -} - -/// Return DirContent which containt information about directory: -/// -/// * Size directory. -/// * List all files source directory(files subdirectories included too). -/// * List all directory and subdirectories source path. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `path` directory does not exist. -/// * Invalid `path`. -/// * The current process does not have the permission rights to access `path`. -/// -/// # Examples -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::get_dir_content2; -/// -/// let options = DirOptions::new(); -/// options.depth = 3; // Get 3 levels of folder. -/// let dir_content = get_dir_content2("dir", &options)?; -/// for directory in dir_content.directories { -/// println!("{}", directory); // print directory path -/// } -/// ``` -/// -pub fn get_dir_content2

(path: P, options: &DirOptions) -> Result -where - P: AsRef, -{ - let mut depth = 0; - if options.depth != 0 { - depth = options.depth + 1; - } - _get_dir_content(path, depth) -} - -fn _get_dir_content

(path: P, mut depth: u64) -> Result -where - P: AsRef, -{ - let mut directories = Vec::new(); - let mut files = Vec::new(); - let mut dir_size = 0; - let item = path.as_ref().to_str(); - if !item.is_some() { - err!("Invalid path", ErrorKind::InvalidPath); - } - let item = item.unwrap().to_string(); - - if path.as_ref().is_dir() { - directories.push(item); - if depth == 0 || depth > 1 { - if depth > 1 { - depth -= 1; - } - for entry in read_dir(&path)? { - let _path = entry?.path(); - - match _get_dir_content(_path, depth) { - Ok(items) => { - let mut _files = items.files; - let mut _dirrectories = items.directories; - dir_size += items.dir_size; - files.append(&mut _files); - directories.append(&mut _dirrectories); - } - Err(err) => return Err(err), - } - } - } - } else { - dir_size = path.as_ref().metadata()?.len(); - files.push(item); - } - Ok(DirContent { - dir_size: dir_size, - files: files, - directories: directories, - }) -} - -/// Returns the size of the file or directory -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `path` directory does not exist. -/// * Invalid `path`. -/// * The current process does not have the permission rights to access `path`. -/// -/// # Examples -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::get_size; -/// -/// let folder_size = get_size("dir")?; -/// println!("{}", folder_size); // print directory sile in bytes -/// ``` -pub fn get_size

(path: P) -> Result -where - P: AsRef, -{ - let mut result = 0; - - if path.as_ref().is_dir() { - for entry in read_dir(&path)? { - let _path = entry?.path(); - if _path.is_file() { - result += _path.metadata()?.len(); - } else { - result += get_size(_path)?; - } - } - } else { - result = path.as_ref().metadata()?.len(); - } - Ok(result) -} - -/// Copies the directory contents from one place to another using recursive method, -/// with recept information about process. This function will also copy the -/// permission bits of the original files to destionation files (not for directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a directory. -/// * This `from` directory does not exist. -/// * Invalid folder name for `from` or `to`. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::copy; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// let handle = |process_info: TransitProcess| { -/// println!("{}", process_info.total_bytes); -/// fs_extra::dir::TransitProcessResult::ContinueOrAbort -/// } -/// // copy source/dir1 to target/dir1 -/// copy_with_progress("source/dir1", "target/dir1", &options, handle)?; -/// -/// ``` -pub fn copy_with_progress( - from: P, - to: Q, - options: &CopyOptions, - mut progress_handler: F, -) -> Result -where - P: AsRef, - Q: AsRef, - F: FnMut(TransitProcess) -> TransitProcessResult, -{ - let from = from.as_ref(); - - if !from.exists() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" does not exist or you don't have access!", msg); - err!(&msg, ErrorKind::NotFound); - } - err!( - "Path does not exist or you don't have access!", - ErrorKind::NotFound - ); - } - - let mut to: PathBuf = to.as_ref().to_path_buf(); - if !from.is_dir() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" is not a directory!", msg); - err!(&msg, ErrorKind::InvalidFolder); - } - err!("Path is not a directory!", ErrorKind::InvalidFolder); - } - - let dir_name; - if let Some(val) = from.components().last() { - dir_name = val.as_os_str(); - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - if !options.content_only && ((options.copy_inside && to.exists()) || !options.copy_inside) { - to.push(dir_name); - } - - let mut read_options = DirOptions::new(); - if options.depth > 0 { - read_options.depth = options.depth; - } - - let dir_content = get_dir_content2(from, &read_options)?; - for directory in dir_content.directories { - let tmp_to = Path::new(&directory).strip_prefix(from)?; - let dir = to.join(&tmp_to); - if !dir.exists() { - if options.copy_inside { - create_all(dir, false)?; - } else { - create(dir, false)?; - } - } - } - - let mut result: u64 = 0; - let mut info_process = TransitProcess { - copied_bytes: 0, - total_bytes: dir_content.dir_size, - file_bytes_copied: 0, - file_total_bytes: 0, - file_name: String::new(), - state: TransitState::Normal, - }; - - let mut options = options.clone(); - for file in dir_content.files { - let mut to = to.to_path_buf(); - let tp = Path::new(&file).strip_prefix(from)?; - let path = to.join(&tp); - - let file_name = path.file_name(); - if !file_name.is_some() { - err!("No file name"); - } - let file_name = file_name.unwrap(); - to.push(file_name); - - let mut file_options = super::file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - buffer_size: options.buffer_size, - }; - - if let Some(file_name) = file_name.to_str() { - info_process.file_name = file_name.to_string(); - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - - info_process.file_bytes_copied = 0; - info_process.file_total_bytes = Path::new(&file).metadata()?.len(); - - let mut result_copy: Result; - let mut work = true; - let copied_bytes = result; - while work { - { - let _progress_handler = |info: super::file::TransitProcess| { - info_process.copied_bytes = copied_bytes + info.copied_bytes; - info_process.file_bytes_copied = info.copied_bytes; - progress_handler(info_process.clone()); - }; - - result_copy = - super::file::copy_with_progress(&file, &path, &file_options, _progress_handler); - } - match result_copy { - Ok(val) => { - result += val; - work = false; - } - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - let mut info_process = info_process.clone(); - info_process.state = TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - TransitProcessResult::Overwrite => { - file_options.overwrite = true; - } - TransitProcessResult::OverwriteAll => { - file_options.overwrite = true; - options.overwrite = true; - } - TransitProcessResult::Skip => { - file_options.skip_exist = true; - } - TransitProcessResult::SkipAll => { - file_options.skip_exist = true; - options.skip_exist = true; - } - TransitProcessResult::Retry => {} - TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - ErrorKind::PermissionDenied => { - let mut info_process = info_process.clone(); - info_process.state = TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - TransitProcessResult::Overwrite => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - TransitProcessResult::OverwriteAll => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - TransitProcessResult::Skip => { - file_options.skip_exist = true; - } - TransitProcessResult::SkipAll => { - file_options.skip_exist = true; - options.skip_exist = true; - } - TransitProcessResult::Retry => {} - TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - _ => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - }, - } - } - } - - Ok(result) -} - -/// Moves the directory contents from one place to another. -/// This function will also copy the permission bits of the original files to -/// destionation files (not for directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a directory. -/// * This `from` directory does not exist. -/// * Invalid folder name for `from` or `to`. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::move_dir; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// -/// // move source/dir1 to target/dir1 -/// move_dir("source/dir1", "target/dir1", &options)?; -/// -/// ``` -pub fn move_dir(from: P, to: Q, options: &CopyOptions) -> Result -where - P: AsRef, - Q: AsRef, -{ - let mut is_remove = true; - if options.skip_exist && to.as_ref().exists() && !options.overwrite { - is_remove = false; - } - let from = from.as_ref(); - - if !from.exists() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" does not exist", msg); - err!(&msg, ErrorKind::NotFound); - } - err!( - "Path does not exist or you don't have access!", - ErrorKind::NotFound - ); - } - - let mut to: PathBuf = to.as_ref().to_path_buf(); - if !from.is_dir() { - if let Some(msg) = from.to_str() { - let msg = format!( - "Path \"{}\" is not a directory or you don't have access!", - msg - ); - err!(&msg, ErrorKind::InvalidFolder); - } - err!( - "Path is not a directory or you don't have access!", - ErrorKind::InvalidFolder - ); - } - let dir_name; - if let Some(val) = from.components().last() { - dir_name = val.as_os_str(); - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - - if !options.content_only && ((options.copy_inside && to.exists()) || !options.copy_inside) { - to.push(dir_name); - } - let dir_content = get_dir_content(from)?; - for directory in dir_content.directories { - let tmp_to = Path::new(&directory).strip_prefix(from)?; - let dir = to.join(&tmp_to); - if !dir.exists() { - if options.copy_inside { - create_all(dir, false)?; - } else { - create(dir, false)?; - } - } - } - let mut result: u64 = 0; - for file in dir_content.files { - let to = to.to_path_buf(); - let tp = Path::new(&file).strip_prefix(from)?; - let path = to.join(&tp); - - let file_options = super::file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - buffer_size: options.buffer_size, - }; - - let mut result_copy: Result; - let mut work = true; - while work { - { - result_copy = super::file::move_file(&file, &path, &file_options); - match result_copy { - Ok(val) => { - result += val; - work = false; - } - Err(err) => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - } - } - if is_remove { - remove(from)?; - } - - Ok(result) -} - -/// Moves the directory contents from one place to another with recept information about process. -/// This function will also copy the permission bits of the original files to -/// destionation files (not for directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a directory. -/// * This `from` directory does not exist. -/// * Invalid folder name for `from` or `to`. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::move_dir_with_progress; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// let handle = |process_info: TransitProcess| { -/// println!("{}", process_info.total_bytes); -/// fs_extra::dir::TransitProcessResult::ContinueOrAbort -/// } -/// -/// // move source/dir1 to target/dir1 -/// move_dir_with_progress("source/dir1", "target/dir1", &options, handle)?; -/// -/// ``` -pub fn move_dir_with_progress( - from: P, - to: Q, - options: &CopyOptions, - mut progress_handler: F, -) -> Result -where - P: AsRef, - Q: AsRef, - F: FnMut(TransitProcess) -> TransitProcessResult, -{ - let mut is_remove = true; - if options.skip_exist && to.as_ref().exists() && !options.overwrite { - is_remove = false; - } - let from = from.as_ref(); - - if !from.exists() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" does not exist or you don't have access!", msg); - err!(&msg, ErrorKind::NotFound); - } - err!( - "Path does not exist or you don't have access!", - ErrorKind::NotFound - ); - } - - let mut to: PathBuf = to.as_ref().to_path_buf(); - if !from.is_dir() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" is not a directory!", msg); - err!(&msg, ErrorKind::InvalidFolder); - } - err!("Path is not a directory!", ErrorKind::InvalidFolder); - } - let dir_name; - if let Some(val) = from.components().last() { - dir_name = val.as_os_str(); - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - if !options.content_only && ((options.copy_inside && to.exists()) || !options.copy_inside) { - to.push(dir_name); - } - - let dir_content = get_dir_content(from)?; - for directory in dir_content.directories { - let tmp_to = Path::new(&directory).strip_prefix(from)?; - let dir = to.join(&tmp_to); - if !dir.exists() { - if options.copy_inside { - create_all(dir, false)?; - } else { - create(dir, false)?; - } - } - } - - let mut result: u64 = 0; - let mut info_process = TransitProcess { - copied_bytes: 0, - total_bytes: dir_content.dir_size, - file_bytes_copied: 0, - file_total_bytes: 0, - file_name: String::new(), - state: TransitState::Normal, - }; - - let mut options = options.clone(); - for file in dir_content.files { - let mut to = to.to_path_buf(); - let tp = Path::new(&file).strip_prefix(from)?; - let path = to.join(&tp); - - let file_name = path.file_name(); - if !file_name.is_some() { - err!("No file name"); - } - let file_name = file_name.unwrap(); - to.push(file_name); - - let mut file_options = super::file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - buffer_size: options.buffer_size, - }; - - if let Some(file_name) = file_name.to_str() { - info_process.file_name = file_name.to_string(); - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - - info_process.file_bytes_copied = 0; - info_process.file_total_bytes = Path::new(&file).metadata()?.len(); - - let mut result_copy: Result; - let mut work = true; - let copied_bytes = result; - while work { - { - let _progress_handler = |info: super::file::TransitProcess| { - info_process.copied_bytes = copied_bytes + info.copied_bytes; - info_process.file_bytes_copied = info.copied_bytes; - progress_handler(info_process.clone()); - }; - - result_copy = super::file::move_file_with_progress( - &file, - &path, - &file_options, - _progress_handler, - ); - } - match result_copy { - Ok(val) => { - result += val; - work = false; - } - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - let mut info_process = info_process.clone(); - info_process.state = TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - TransitProcessResult::Overwrite => { - file_options.overwrite = true; - } - TransitProcessResult::OverwriteAll => { - file_options.overwrite = true; - options.overwrite = true; - } - TransitProcessResult::Skip => { - is_remove = false; - file_options.skip_exist = true; - } - TransitProcessResult::SkipAll => { - is_remove = false; - file_options.skip_exist = true; - options.skip_exist = true; - } - TransitProcessResult::Retry => {} - TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - ErrorKind::PermissionDenied => { - let mut info_process = info_process.clone(); - info_process.state = TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - TransitProcessResult::Overwrite => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - TransitProcessResult::OverwriteAll => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - TransitProcessResult::Skip => { - is_remove = false; - file_options.skip_exist = true; - } - TransitProcessResult::SkipAll => { - file_options.skip_exist = true; - options.skip_exist = true; - } - TransitProcessResult::Retry => {} - TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - _ => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - }, - } - } - } - if is_remove { - remove(from)?; - } - - Ok(result) -} - -/// Removes directory. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::remove; -/// -/// remove("source/dir1"); // remove dir1 -/// ``` -pub fn remove>(path: P) -> Result<()> { - if path.as_ref().exists() { - Ok(remove_dir_all(path)?) - } else { - Ok(()) - } -} diff --git a/vendor/fs_extra/src/error.rs b/vendor/fs_extra/src/error.rs deleted file mode 100644 index 5e4bce8d37..0000000000 --- a/vendor/fs_extra/src/error.rs +++ /dev/null @@ -1,158 +0,0 @@ -use std::error::Error as StdError; -use std::ffi::OsString; -use std::fmt; -use std::io::Error as IoError; -use std::io::ErrorKind as IoErrorKind; -use std::path::StripPrefixError; - -/// A list specifying general categories of fs_extra error. -#[derive(Debug)] -pub enum ErrorKind { - /// An entity was not found. - NotFound, - /// The operation lacked the necessary privileges to complete. - PermissionDenied, - /// An entity already exists. - AlreadyExists, - /// This operation was interrupted. - Interrupted, - /// Path does not a directory. - InvalidFolder, - /// Path does not a file. - InvalidFile, - /// Invalid file name. - InvalidFileName, - /// Invalid path. - InvalidPath, - /// Any I/O error. - Io(IoError), - /// Any StripPrefix error. - StripPrefix(StripPrefixError), - /// Any OsString error. - OsString(OsString), - /// Any fs_extra error not part of this list. - Other, -} - -impl ErrorKind { - fn as_str(&self) -> &str { - match *self { - ErrorKind::NotFound => "entity not found", - ErrorKind::PermissionDenied => "permission denied", - ErrorKind::AlreadyExists => "entity already exists", - ErrorKind::Interrupted => "operation interrupted", - ErrorKind::Other => "other os error", - ErrorKind::InvalidFolder => "invalid folder error", - ErrorKind::InvalidFile => "invalid file error", - ErrorKind::InvalidFileName => "invalid file name error", - ErrorKind::InvalidPath => "invalid path error", - ErrorKind::Io(_) => "Io error", - ErrorKind::StripPrefix(_) => "Strip prefix error", - ErrorKind::OsString(_) => "OsString error", - } - } -} - -/// A specialized Result type for fs_extra operations. -/// -/// This typedef is generally used to avoid writing out fs_extra::Error directly -/// and is otherwise a direct mapping to Result. -/// -///#Examples -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::create; -/// -///fn get_string() -> io::Result<()> { -/// -/// create("test_dir")?; -/// -/// Ok(()) -/// } -/// ``` -pub type Result = ::std::result::Result; - -/// The error type for fs_extra operations with files and folder. -/// -/// Errors mostly originate from the underlying OS, but custom instances of -/// `Error` can be created with crafted error messages and a particular value of -/// [`ErrorKind`]. -/// -/// [`ErrorKind`]: enum.ErrorKind.html -#[derive(Debug)] -pub struct Error { - /// Type error - pub kind: ErrorKind, - message: String, -} - -impl Error { - /// Create a new fs_extra error from a kind of error error as well as an arbitrary error payload. - /// - ///#Examples - /// ```rust,ignore - /// - /// extern crate fs_extra; - /// use fs_extra::error::{Error, ErrorKind}; - /// - /// errors can be created from strings - /// let custom_error = Error::new(ErrorKind::Other, "Other Error!"); - /// // errors can also be created from other errors - /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); - /// - /// ``` - pub fn new(kind: ErrorKind, message: &str) -> Error { - Error { - kind: kind, - message: message.to_string(), - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.message) - } -} - -impl StdError for Error { - fn description(&self) -> &str { - self.kind.as_str() - } -} -impl From for Error { - fn from(err: StripPrefixError) -> Error { - Error::new( - ErrorKind::StripPrefix(err), - "StripPrefixError. Look inside for more details", - ) - } -} - -impl From for Error { - fn from(err: OsString) -> Error { - Error::new( - ErrorKind::OsString(err), - "OsString. Look inside for more details", - ) - } -} - -impl From for Error { - fn from(err: IoError) -> Error { - let err_kind: ErrorKind; - match err.kind() { - IoErrorKind::NotFound => err_kind = ErrorKind::NotFound, - IoErrorKind::PermissionDenied => err_kind = ErrorKind::PermissionDenied, - IoErrorKind::AlreadyExists => err_kind = ErrorKind::AlreadyExists, - IoErrorKind::Interrupted => err_kind = ErrorKind::Interrupted, - IoErrorKind::Other => err_kind = ErrorKind::Other, - _ => { - err_kind = ErrorKind::Io(err); - return Error::new(err_kind, "Io error. Look inside err_kind for more details."); - } - } - Error::new(err_kind, &err.to_string()) - } -} diff --git a/vendor/fs_extra/src/file.rs b/vendor/fs_extra/src/file.rs deleted file mode 100644 index 673f1fd9a6..0000000000 --- a/vendor/fs_extra/src/file.rs +++ /dev/null @@ -1,392 +0,0 @@ -use error::{Error, ErrorKind, Result}; -use std; -use std::fs::{remove_file, File}; -use std::io::{Read, Write}; -use std::path::Path; - -/// Options and flags which can be used to configure how a file will be copied or moved. -pub struct CopyOptions { - /// Sets the option true for overwrite existing files. - pub overwrite: bool, - /// Sets the option true for skipe existing files. - pub skip_exist: bool, - /// Sets buffer size for copy/move work only with receipt information about process work. - pub buffer_size: usize, -} - -impl CopyOptions { - /// Initialize struct CopyOptions with default value. - /// - /// ```rust,ignore - /// - /// overwrite: false - /// - /// skip_exist: false - /// - /// buffer_size: 64000 //64kb - /// ``` - pub fn new() -> CopyOptions { - CopyOptions { - overwrite: false, - skip_exist: false, - buffer_size: 64000, //64kb - } - } -} - -impl Default for CopyOptions { - fn default() -> Self { - CopyOptions::new() - } -} - -/// A structure which include information about the current status of the copy or move file. -pub struct TransitProcess { - /// Copied bytes on this time. - pub copied_bytes: u64, - /// All the bytes which should to copy or move. - pub total_bytes: u64, -} - -/// Copies the contents of one file to another. This function will also copy the permission -/// bits of the original file to the destination file. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a file. -/// * This `from` file does not exist. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::file::copy; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// copy("dir1/foo.txt", "dir2/bar.txt", &options)?; // Copy dir1/foo.txt to dir2/bar.txt -/// -/// ``` -pub fn copy(from: P, to: Q, options: &CopyOptions) -> Result -where - P: AsRef, - Q: AsRef, -{ - let from = from.as_ref(); - if !from.exists() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" does not exist or you don't have access!", msg); - err!(&msg, ErrorKind::NotFound); - } - err!( - "Path does not exist or you don't have access!", - ErrorKind::NotFound - ); - } - - if !from.is_file() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" is not a file!", msg); - err!(&msg, ErrorKind::InvalidFile); - } - err!("Path is not a file!", ErrorKind::InvalidFile); - } - - if !options.overwrite && to.as_ref().exists() { - if options.skip_exist { - return Ok(0); - } - - if let Some(msg) = to.as_ref().to_str() { - let msg = format!("Path \"{}\" is exist", msg); - err!(&msg, ErrorKind::AlreadyExists); - } - } - - Ok(std::fs::copy(from, to)?) -} - -/// Copies the contents of one file to another with recept information about process. -/// This function will also copy the permission bits of the original file to the -/// destination file. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a file. -/// * This `from` file does not exist. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::file::copy_with_progress; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// let handle = |process_info: TransitProcess| println!("{}", process_info.total_bytes); -/// -/// // Copy dir1/foo.txt to dir2/foo.txt -/// copy_with_progress("dir1/foo.txt", "dir2/foo.txt", &options, handle)?; -/// -/// ``` -pub fn copy_with_progress( - from: P, - to: Q, - options: &CopyOptions, - mut progress_handler: F, -) -> Result -where - P: AsRef, - Q: AsRef, - F: FnMut(TransitProcess) -> (), -{ - let from = from.as_ref(); - if !from.exists() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" does not exist or you don't have access!", msg); - err!(&msg, ErrorKind::NotFound); - } - err!( - "Path does not exist or you don't have access!", - ErrorKind::NotFound - ); - } - - if !from.is_file() { - if let Some(msg) = from.to_str() { - let msg = format!("Path \"{}\" is not a file!", msg); - err!(&msg, ErrorKind::InvalidFile); - } - err!("Path is not a file!", ErrorKind::InvalidFile); - } - - if !options.overwrite && to.as_ref().exists() { - if options.skip_exist { - return Ok(0); - } - - if let Some(msg) = to.as_ref().to_str() { - let msg = format!("Path \"{}\" is exist", msg); - err!(&msg, ErrorKind::AlreadyExists); - } - } - let mut file_from = File::open(from)?; - let mut buf = vec![0; options.buffer_size]; - let file_size = file_from.metadata()?.len(); - let mut copied_bytes: u64 = 0; - - let mut file_to = File::create(to)?; - while !buf.is_empty() { - match file_from.read(&mut buf) { - Ok(0) => break, - Ok(n) => { - file_to.write(&mut buf[..n])?; - copied_bytes = copied_bytes + n as u64; - let data = TransitProcess { - copied_bytes: copied_bytes, - total_bytes: file_size, - }; - progress_handler(data); - } - Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => {} - Err(e) => return Err(::std::convert::From::from(e)), - } - } - Ok(file_size) -} - -/// Moves file from one place to another. This function will also copy the permission -/// bits of the original file to the destination file. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a file. -/// * This `from` file does not exist. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::file::move_file; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// move_file("dir1/foo.txt", "dir2/foo.txt", &options)?; // Move dir1/foo.txt to dir2/foo.txt -/// -/// ``` -pub fn move_file(from: P, to: Q, options: &CopyOptions) -> Result -where - P: AsRef, - Q: AsRef, -{ - let mut is_remove = true; - if options.skip_exist && to.as_ref().exists() && !options.overwrite { - is_remove = false; - } - let result = copy(&from, to, options)?; - if is_remove { - remove(from)?; - } - - Ok(result) -} - -/// Moves file from one place to another with recept information about process. -/// This function will also copy the permission bits of the original file to the -/// destination file. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `from` path is not a file. -/// * This `from` file does not exist. -/// * The current process does not have the permission rights to access `from` or write `to`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::file::move_file; -/// -/// let options = CopyOptions::new(); //Initialize default values for CopyOptions -/// let handle = |process_info: TransitProcess| println!("{}", process_info.total_bytes); -/// -/// // Move dir1/foo.txt to dir2/foo.txt -/// move_file("dir1/foo.txt", "dir2/foo.txt", &options, handle)?; -/// -/// ``` -pub fn move_file_with_progress( - from: P, - to: Q, - options: &CopyOptions, - progress_handler: F, -) -> Result -where - P: AsRef, - Q: AsRef, - F: FnMut(TransitProcess) -> (), -{ - let mut is_remove = true; - if options.skip_exist && to.as_ref().exists() && !options.overwrite { - is_remove = false; - } - let result = copy_with_progress(&from, to, options, progress_handler)?; - if is_remove { - remove(from)?; - } - - Ok(result) -} - -/// Removes a file from the filesystem. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * The current process does not have the permission rights to access `path`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::file::remove; -/// -/// remove("foo.txt" )?; // Remove foo.txt -/// -/// ``` -pub fn remove

(path: P) -> Result<()> -where - P: AsRef, -{ - if path.as_ref().exists() { - Ok(remove_file(path)?) - } else { - Ok(()) - } -} - -/// Read file content, placing him into `String`. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `path` is not a file. -/// * This `path` file does not exist. -/// * The current process does not have the permission rights to access `path`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::file::read_to_string; -/// -/// let file_content = read_to_string("foo.txt" )?; // Get file conent from foo.txt -/// println!("{}", file_content); -/// -/// ``` -pub fn read_to_string

(path: P) -> Result -where - P: AsRef, -{ - let path = path.as_ref(); - if path.exists() && !path.is_file() { - if let Some(msg) = path.to_str() { - let msg = format!("Path \"{}\" is not a file!", msg); - err!(&msg, ErrorKind::InvalidFile); - } - err!("Path is not a file!", ErrorKind::InvalidFile); - } - - let mut file = File::open(path)?; - let mut result = String::new(); - file.read_to_string(&mut result)?; - - Ok(result) -} - -/// Write `String` content into inside target file. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these cases: -/// -/// * This `path` is not a file. -/// * This `path` file does not exist. -/// * The current process does not have the permission rights to access `path`. -/// -/// # Example -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::file::read_to_string; -/// -/// write_all("foo.txt", "conents" )?; // Create file foo.txt and send content inside -/// -/// ``` -pub fn write_all

(path: P, content: &str) -> Result<()> -where - P: AsRef, -{ - let path = path.as_ref(); - if path.exists() && !path.is_file() { - if let Some(msg) = path.to_str() { - let msg = format!("Path \"{}\" is not a file!", msg); - err!(&msg, ErrorKind::InvalidFile); - } - err!("Path is not a file!", ErrorKind::InvalidFile); - } - - let mut f = File::create(path)?; - - Ok(f.write_all(content.as_bytes())?) -} diff --git a/vendor/fs_extra/src/lib.rs b/vendor/fs_extra/src/lib.rs deleted file mode 100644 index 434b90d3f4..0000000000 --- a/vendor/fs_extra/src/lib.rs +++ /dev/null @@ -1,807 +0,0 @@ -macro_rules! err { - ($text:expr, $kind:expr) => { - return Err(Error::new($kind, $text)); - }; - - ($text:expr) => { - err!($text, ErrorKind::Other) - }; -} - -/// The error type for fs_extra operations with files and folder. -pub mod error; -/// This module include extra methods for works with files. -/// -/// One of the distinguishing features is receipt information -/// about process work with files. -/// -/// # Example -/// ```rust,ignore -/// use std::path::Path; -/// use std::{thread, time}; -/// use std::sync::mpsc::{self, TryRecvError}; -/// -/// extern crate fs_extra; -/// use fs_extra::file::*; -/// use fs_extra::error::*; -/// -/// fn example_copy() -> Result<()> { -/// let path_from = Path::new("./temp"); -/// let path_to = path_from.join("out"); -/// let test_file = (path_from.join("test_file.txt"), path_to.join("test_file.txt")); -/// -/// -/// fs_extra::dir::create_all(&path_from, true)?; -/// fs_extra::dir::create_all(&path_to, true)?; -/// -/// write_all(&test_file.0, "test_data")?; -/// assert!(test_file.0.exists()); -/// assert!(!test_file.1.exists()); -/// -/// -/// let options = CopyOptions { -/// buffer_size: 1, -/// ..Default::default() -/// } -/// let (tx, rx) = mpsc::channel(); -/// thread::spawn(move || { -/// let handler = |process_info: TransitProcess| { -/// tx.send(process_info).unwrap(); -/// thread::sleep(time::Duration::from_millis(500)); -/// }; -/// copy_with_progress(&test_file.0, &test_file.1, &options, handler).unwrap(); -/// assert!(test_file.0.exists()); -/// assert!(test_file.1.exists()); -/// -/// }); -/// loop { -/// match rx.try_recv() { -/// Ok(process_info) => { -/// println!("{} of {} bytes", -/// process_info.copied_bytes, -/// process_info.total_bytes); -/// } -/// Err(TryRecvError::Disconnected) => { -/// println!("finished"); -/// break; -/// } -/// Err(TryRecvError::Empty) => {} -/// } -/// } -/// Ok(()) -/// -/// } -/// -/// -/// fn main() { -/// example_copy(); -/// -/// -/// ``` -pub mod file; - -/// This module include extra methods for works with directories. -/// -/// One of the distinguishing features is receipt information -/// about process work with directories and recursion operations. -/// -/// # Example -/// ```rust,ignore -/// use std::path::Path; -/// use std::{thread, time}; -/// use std::sync::mpsc::{self, TryRecvError}; -/// -/// extern crate fs_extra; -/// use fs_extra::dir::*; -/// use fs_extra::error::*; -/// -/// fn example_copy() -> Result<()> { -/// -/// let path_from = Path::new("./temp"); -/// let path_to = path_from.join("out"); -/// let test_folder = path_from.join("test_folder"); -/// let dir = test_folder.join("dir"); -/// let sub = dir.join("sub"); -/// let file1 = dir.join("file1.txt"); -/// let file2 = sub.join("file2.txt"); -/// -/// create_all(&sub, true)?; -/// create_all(&path_to, true)?; -/// fs_extra::file::write_all(&file1, "content1")?; -/// fs_extra::file::write_all(&file2, "content2")?; -/// -/// assert!(dir.exists()); -/// assert!(sub.exists()); -/// assert!(file1.exists()); -/// assert!(file2.exists()); -/// -/// -/// let options = CopyOptions { -/// buffer_size: 1, -/// ..Default::default(), -/// }; -/// let (tx, rx) = mpsc::channel(); -/// thread::spawn(move || { -/// let handler = |process_info: TransitProcess| { -/// tx.send(process_info).unwrap(); -/// thread::sleep(time::Duration::from_millis(500)); -/// }; -/// copy_with_progress(&test_folder, &path_to, &options, handler).unwrap(); -/// }); -/// -/// loop { -/// match rx.try_recv() { -/// Ok(process_info) => { -/// println!("{} of {} bytes", -/// process_info.copied_bytes, -/// process_info.total_bytes); -/// } -/// Err(TryRecvError::Disconnected) => { -/// println!("finished"); -/// break; -/// } -/// Err(TryRecvError::Empty) => {} -/// } -/// } -/// Ok(()) -/// -/// } -/// fn main() { -/// example_copy(); -/// } -/// ``` -/// -pub mod dir; - -use error::*; -use std::path::Path; - -/// Copies list directories and files to another place using recursive method. This function will -/// also copy the permission bits of the original files to destionation files (not for -/// directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these case: -/// -/// * List `from` contains file or directory does not exist. -/// -/// * List `from` contains file or directory with invalid name. -/// -/// * The current process does not have the permission rights to access to file from `lists from` or -/// `to`. -/// -/// # Example -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::copy; -/// -/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions -/// -/// // copy dir1 and file1.txt to target/dir1 and target/file1.txt -/// let mut from_paths = Vec::new(); -/// from_paths.push("source/dir1"); -/// from_paths.push("source/file.txt"); -/// copy_items(&from_paths, "target", &options)?; -/// ``` -/// -pub fn copy_items(from: &[P], to: Q, options: &dir::CopyOptions) -> Result -where - P: AsRef, - Q: AsRef, -{ - let mut result: u64 = 0; - if options.content_only { - err!( - "Options 'content_only' not acccess for copy_items function", - ErrorKind::Other - ); - } - for item in from { - let item = item.as_ref(); - if item.is_dir() { - result += dir::copy(item, &to, options)?; - } else { - if let Some(file_name) = item.file_name() { - if let Some(file_name) = file_name.to_str() { - let file_options = file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - ..Default::default() - }; - result += file::copy(item, to.as_ref().join(file_name), &file_options)?; - } - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - } - } - - Ok(result) -} - -/// A structure which include information about the current status of the copy or move directory. -pub struct TransitProcess { - /// Copied bytes on this time for folder - pub copied_bytes: u64, - /// All the bytes which should to copy or move (dir size). - pub total_bytes: u64, - /// Copied bytes on this time for file. - pub file_bytes_copied: u64, - /// Size current copied file. - pub file_total_bytes: u64, - /// Name current copied file. - pub file_name: String, - /// Name current copied folder. - pub dir_name: String, - /// Transit state - pub state: dir::TransitState, -} - -impl Clone for TransitProcess { - fn clone(&self) -> TransitProcess { - TransitProcess { - copied_bytes: self.copied_bytes, - total_bytes: self.total_bytes, - file_bytes_copied: self.file_bytes_copied, - file_total_bytes: self.file_total_bytes, - file_name: self.file_name.clone(), - dir_name: self.dir_name.clone(), - state: self.state.clone(), - } - } -} - -/// Copies list directories and files to another place using recursive method, with recept -/// information about process. This function will also copy the permission bits of the -/// original files to destionation files (not for directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these case: -/// -/// * List `from` contains file or directory does not exist. -/// -/// * List `from` contains file or directory with invalid name. -/// -/// * The current process does not have the permission rights to access to file from `lists from` or -/// `to`. -/// -/// # Example -/// ```rust,ignore -/// -/// extern crate fs_extra; -/// use fs_extra::dir::copy; -/// -/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions -/// let handle = |process_info: TransitProcess| { -/// println!("{}", process_info.total_bytes); -/// fs_extra::dir::TransitProcessResult::ContinueOrAbort -/// } -/// // copy dir1 and file1.txt to target/dir1 and target/file1.txt -/// let mut from_paths = Vec::new(); -/// from_paths.push("source/dir1"); -/// from_paths.push("source/file.txt"); -/// copy_items_with_progress(&from_paths, "target", &options, handle)?; -/// ``` -/// -pub fn copy_items_with_progress( - from: &[P], - to: Q, - options: &dir::CopyOptions, - mut progress_handler: F, -) -> Result -where - P: AsRef, - Q: AsRef, - F: FnMut(TransitProcess) -> dir::TransitProcessResult, -{ - if options.content_only { - err!( - "Options 'content_only' not acccess for copy_items_with_progress function", - ErrorKind::Other - ); - } - let mut total_size = 0; - let mut list_paths = Vec::new(); - for item in from { - let item = item.as_ref(); - total_size += dir::get_size(item)?; - list_paths.push(item); - } - - let mut result: u64 = 0; - let mut info_process = TransitProcess { - copied_bytes: 0, - total_bytes: total_size, - file_bytes_copied: 0, - file_total_bytes: 0, - file_name: String::new(), - dir_name: String::new(), - state: dir::TransitState::Normal, - }; - - let mut options = options.clone(); - for item in list_paths { - if item.is_dir() { - if let Some(dir_name) = item.components().last() { - if let Ok(dir_name) = dir_name.as_os_str().to_os_string().into_string() { - info_process.dir_name = dir_name; - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - - let copied_bytes = result; - let dir_options = options.clone(); - let handler = |info: dir::TransitProcess| { - info_process.copied_bytes = copied_bytes + info.copied_bytes; - info_process.state = info.state; - let result = progress_handler(info_process.clone()); - match result { - dir::TransitProcessResult::OverwriteAll => options.overwrite = true, - dir::TransitProcessResult::SkipAll => options.skip_exist = true, - _ => {} - } - result - }; - result += dir::copy_with_progress(item, &to, &dir_options, handler)?; - } else { - let mut file_options = file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - buffer_size: options.buffer_size, - ..Default::default() - }; - - if let Some(file_name) = item.file_name() { - if let Some(file_name) = file_name.to_str() { - info_process.file_name = file_name.to_string(); - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - - info_process.file_bytes_copied = 0; - info_process.file_total_bytes = item.metadata()?.len(); - - let copied_bytes = result; - let file_name = to.as_ref().join(info_process.file_name.clone()); - let mut work = true; - - let mut result_copy: Result; - while work { - { - let handler = |info: file::TransitProcess| { - info_process.copied_bytes = copied_bytes + info.copied_bytes; - info_process.file_bytes_copied = info.copied_bytes; - progress_handler(info_process.clone()); - }; - result_copy = - file::copy_with_progress(item, &file_name, &file_options, handler); - } - match result_copy { - Ok(val) => { - result += val; - work = false; - } - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - let mut info_process = info_process.clone(); - info_process.state = dir::TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - dir::TransitProcessResult::Overwrite => { - file_options.overwrite = true; - } - dir::TransitProcessResult::OverwriteAll => { - file_options.overwrite = true; - options.overwrite = true; - } - dir::TransitProcessResult::Skip => { - file_options.skip_exist = true; - } - dir::TransitProcessResult::SkipAll => { - file_options.skip_exist = true; - options.skip_exist = true; - } - dir::TransitProcessResult::Retry => {} - dir::TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - dir::TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - ErrorKind::PermissionDenied => { - let mut info_process = info_process.clone(); - info_process.state = dir::TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - dir::TransitProcessResult::Overwrite => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - dir::TransitProcessResult::OverwriteAll => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - dir::TransitProcessResult::Skip => { - file_options.skip_exist = true; - } - dir::TransitProcessResult::SkipAll => { - file_options.skip_exist = true; - options.skip_exist = true; - } - dir::TransitProcessResult::Retry => {} - dir::TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - dir::TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - _ => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - }, - } - } - } - } - - Ok(result) -} - -/// Moves list directories and files to another place using recursive method. This function will -/// also copy the permission bits of the original files to destionation files (not for -/// directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these case: -/// -/// * List `from` contains file or directory does not exist. -/// -/// * List `from` contains file or directory with invalid name. -/// -/// * The current process does not have the permission rights to access to file from `lists from` or -/// `to`. -/// -/// # Example -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::copy; -/// -/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions -/// -/// // move dir1 and file1.txt to target/dir1 and target/file1.txt -/// let mut from_paths = Vec::new(); -/// from_paths.push("source/dir1"); -/// from_paths.push("source/file.txt"); -/// move_items(&from_paths, "target", &options)?; -/// ``` -/// -pub fn move_items(from_items: &[P], to: Q, options: &dir::CopyOptions) -> Result -where - P: AsRef, - Q: AsRef, -{ - if options.content_only { - err!( - "Options 'content_only' not acccess for move_items function", - ErrorKind::Other - ); - } - let mut total_size = 0; - let mut list_paths = Vec::new(); - for item in from_items { - let item = item.as_ref(); - total_size += dir::get_size(item)?; - list_paths.push(item); - } - - let mut result = 0; - let mut info_process = TransitProcess { - copied_bytes: 0, - total_bytes: total_size, - file_bytes_copied: 0, - file_total_bytes: 0, - file_name: String::new(), - dir_name: String::new(), - state: dir::TransitState::Normal, - }; - - for item in list_paths { - if item.is_dir() { - if let Some(dir_name) = item.components().last() { - if let Ok(dir_name) = dir_name.as_os_str().to_os_string().into_string() { - info_process.dir_name = dir_name; - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - - result += dir::move_dir(item, &to, options)?; - } else { - let file_options = file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - buffer_size: options.buffer_size, - ..Default::default() - }; - - if let Some(file_name) = item.file_name() { - if let Some(file_name) = file_name.to_str() { - info_process.file_name = file_name.to_string(); - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - - info_process.file_bytes_copied = 0; - info_process.file_total_bytes = item.metadata()?.len(); - - let file_name = to.as_ref().join(info_process.file_name.clone()); - result += file::move_file(item, &file_name, &file_options)?; - } - } - - Ok(result) -} - -/// Moves list directories and files to another place using recursive method, with recept -/// information about process. This function will also copy the permission bits of the -/// original files to destionation files (not for directories). -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not limited to just -/// these case: -/// -/// * List `from` contains file or directory does not exist. -/// -/// * List `from` contains file or directory with invalid name. -/// -/// * The current process does not have the permission rights to access to file from `lists from` or -/// `to`. -/// -/// # Example -/// -/// ```rust,ignore -/// extern crate fs_extra; -/// use fs_extra::dir::copy; -/// -/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions -/// let handle = |process_info: TransitProcess| { -/// println!("{}", process_info.total_bytes); -/// fs_extra::dir::TransitProcessResult::ContinueOrAbort -/// } -/// // move dir1 and file1.txt to target/dir1 and target/file1.txt -/// let mut from_paths = Vec::new(); -/// from_paths.push("source/dir1"); -/// from_paths.push("source/file.txt"); -/// move_items_with_progress(&from_paths, "target", &options, handle)?; -/// ``` -/// -pub fn move_items_with_progress( - from_items: &[P], - to: Q, - options: &dir::CopyOptions, - mut progress_handler: F, -) -> Result -where - P: AsRef, - Q: AsRef, - F: FnMut(TransitProcess) -> dir::TransitProcessResult, -{ - if options.content_only { - err!( - "Options 'content_only' not acccess for move_items_with_progress function", - ErrorKind::Other - ); - } - let mut total_size = 0; - let mut list_paths = Vec::new(); - for item in from_items { - let item = item.as_ref(); - total_size += dir::get_size(item)?; - list_paths.push(item); - } - - let mut result = 0; - let mut info_process = TransitProcess { - copied_bytes: 0, - total_bytes: total_size, - file_bytes_copied: 0, - file_total_bytes: 0, - file_name: String::new(), - dir_name: String::new(), - state: dir::TransitState::Normal, - }; - let mut options = options.clone(); - - for item in list_paths { - if item.is_dir() { - if let Some(dir_name) = item.components().last() { - if let Ok(dir_name) = dir_name.as_os_str().to_os_string().into_string() { - info_process.dir_name = dir_name; - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - } else { - err!("Invalid folder from", ErrorKind::InvalidFolder); - } - - let copied_bytes = result; - let dir_options = options.clone(); - let handler = |info: dir::TransitProcess| { - info_process.copied_bytes = copied_bytes + info.copied_bytes; - info_process.state = info.state; - let result = progress_handler(info_process.clone()); - match result { - dir::TransitProcessResult::OverwriteAll => options.overwrite = true, - dir::TransitProcessResult::SkipAll => options.skip_exist = true, - _ => {} - } - result - }; - result += dir::move_dir_with_progress(item, &to, &dir_options, handler)?; - } else { - let mut file_options = file::CopyOptions { - overwrite: options.overwrite, - skip_exist: options.skip_exist, - buffer_size: options.buffer_size, - ..Default::default() - }; - - if let Some(file_name) = item.file_name() { - if let Some(file_name) = file_name.to_str() { - info_process.file_name = file_name.to_string(); - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - } else { - err!("Invalid file name", ErrorKind::InvalidFileName); - } - - info_process.file_bytes_copied = 0; - info_process.file_total_bytes = item.metadata()?.len(); - - let copied_bytes = result; - let file_name = to.as_ref().join(info_process.file_name.clone()); - let mut work = true; - - let mut result_copy: Result; - while work { - { - let handler = |info: file::TransitProcess| { - info_process.copied_bytes = copied_bytes + info.copied_bytes; - info_process.file_bytes_copied = info.copied_bytes; - progress_handler(info_process.clone()); - }; - result_copy = - file::move_file_with_progress(item, &file_name, &file_options, handler); - } - match result_copy { - Ok(val) => { - result += val; - work = false; - } - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - let mut info_process = info_process.clone(); - info_process.state = dir::TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - dir::TransitProcessResult::Overwrite => { - file_options.overwrite = true; - } - dir::TransitProcessResult::OverwriteAll => { - file_options.overwrite = true; - options.overwrite = true; - } - dir::TransitProcessResult::Skip => { - file_options.skip_exist = true; - } - dir::TransitProcessResult::SkipAll => { - file_options.skip_exist = true; - options.skip_exist = true; - } - dir::TransitProcessResult::Retry => {} - dir::TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - dir::TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - ErrorKind::PermissionDenied => { - let mut info_process = info_process.clone(); - info_process.state = dir::TransitState::Exists; - let user_decide = progress_handler(info_process); - match user_decide { - dir::TransitProcessResult::Overwrite => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - dir::TransitProcessResult::OverwriteAll => { - err!("Overwrite denied for this situation!", ErrorKind::Other); - } - dir::TransitProcessResult::Skip => { - file_options.skip_exist = true; - } - dir::TransitProcessResult::SkipAll => { - file_options.skip_exist = true; - options.skip_exist = true; - } - dir::TransitProcessResult::Retry => {} - dir::TransitProcessResult::ContinueOrAbort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - dir::TransitProcessResult::Abort => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - } - } - _ => { - let err_msg = err.to_string(); - err!(err_msg.as_str(), err.kind) - } - }, - } - } - } - } - Ok(result) -} - -/// Removes list files or directories. -/// -/// # Example -/// -/// ```rust,ignore -/// let mut from_paths = Vec::new(); -/// from_paths.push("source/dir1"); -/// from_paths.push("source/file.txt"); -/// -/// remove_items(&from_paths).unwrap(); -/// ``` -/// -pub fn remove_items

(from_items: &[P]) -> Result<()> -where - P: AsRef, -{ - for item in from_items { - let item = item.as_ref(); - if item.is_dir() { - dir::remove(item)?; - } else { - file::remove(item)? - } - } - - Ok(()) -} diff --git a/vendor/fs_extra/tests/dir.rs b/vendor/fs_extra/tests/dir.rs deleted file mode 100644 index bf0dfab04e..0000000000 --- a/vendor/fs_extra/tests/dir.rs +++ /dev/null @@ -1,4753 +0,0 @@ -use std::collections::HashSet; -use std::fs::read_dir; -use std::path::{Path, PathBuf}; -use std::sync::mpsc::{self, TryRecvError}; -use std::thread; - -extern crate fs_extra; -use fs_extra::dir::*; -use fs_extra::error::*; - -fn files_eq(file1: P, file2: Q) -> bool -where - P: AsRef, - Q: AsRef, -{ - let content1 = fs_extra::file::read_to_string(file1).unwrap(); - let content2 = fs_extra::file::read_to_string(file2).unwrap(); - content1 == content2 -} - -fn compare_dir(path_from: P, path_to: Q) -> bool -where - P: AsRef, - Q: AsRef, -{ - let mut path_to = path_to.as_ref().to_path_buf(); - match path_from.as_ref().components().last() { - None => panic!("Invalid folder from"), - Some(dir_name) => { - path_to.push(dir_name.as_os_str()); - if !path_to.exists() { - return false; - } - } - } - - for entry in read_dir(&path_from).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - if path.is_dir() { - if !compare_dir(path, &path_to) { - return false; - } - } else { - let mut path_to = path_to.to_path_buf(); - match path.file_name() { - None => panic!("No file name"), - Some(file_name) => { - path_to.push(file_name); - if !path_to.exists() { - return false; - } else if !files_eq(&path, path_to.clone()) { - return false; - } - } - } - } - } - - true -} - -const TEST_FOLDER: &'static str = "./tests/temp/dir"; - -#[test] -fn it_create_all_work() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_create_all_work"); - test_dir.push("sub_dir"); - if test_dir.exists() { - remove(&test_dir).unwrap(); - } - assert!(!test_dir.exists()); - create_all(&test_dir, false).unwrap(); - assert!(test_dir.exists()); -} - -#[test] -fn it_create_work() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_create_work"); - if !test_dir.exists() { - create_all(&test_dir, false).unwrap(); - } - assert!(test_dir.exists()); - test_dir.push("sub_dir"); - if test_dir.exists() { - remove(&test_dir).unwrap(); - } - create(&test_dir, false).unwrap(); - assert!(test_dir.exists()); -} - -#[test] -fn it_create_exist_folder() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_create_exist_folder"); - test_dir.push("sub"); - if test_dir.exists() { - remove(&test_dir).unwrap(); - } - assert!(!test_dir.exists()); - create_all(&test_dir, false).unwrap(); - assert!(test_dir.exists()); - let mut file_path = test_dir.clone(); - file_path.push("test.txt"); - assert!(!file_path.exists()); - let content = "test_content"; - fs_extra::file::write_all(&file_path, &content).unwrap(); - assert!(file_path.exists()); - - match create(&test_dir, false) { - Ok(_) => panic!("Should be error!"), - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - assert!(test_dir.exists()); - assert!(file_path.exists()); - let new_content = fs_extra::file::read_to_string(file_path).unwrap(); - assert_eq!(new_content, content); - } - _ => panic!("Wrong error"), - }, - } -} - -#[test] -fn it_create_erase_exist_folder() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_create_erase_exist_folder"); - test_dir.push("sub"); - if test_dir.exists() { - remove(&test_dir).unwrap(); - } - assert!(!test_dir.exists()); - create_all(&test_dir, true).unwrap(); - assert!(test_dir.exists()); - let mut file_path = test_dir.clone(); - file_path.push("test.txt"); - assert!(!file_path.exists()); - fs_extra::file::write_all(&file_path, "test_content").unwrap(); - assert!(file_path.exists()); - - create(&test_dir, true).unwrap(); - assert!(test_dir.exists()); - assert!(!file_path.exists()); -} - -#[test] -fn it_create_all_exist_folder() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_create_all_exist_folder"); - test_dir.push("sub"); - if test_dir.exists() { - remove(&test_dir).unwrap(); - } - assert!(!test_dir.exists()); - create_all(&test_dir, false).unwrap(); - assert!(test_dir.exists()); - let mut file_path = test_dir.clone(); - file_path.push("test.txt"); - assert!(!file_path.exists()); - let content = "test_content"; - fs_extra::file::write_all(&file_path, &content).unwrap(); - assert!(file_path.exists()); - - create_all(&test_dir, false).unwrap(); - assert!(test_dir.exists()); - assert!(file_path.exists()); - let new_content = fs_extra::file::read_to_string(file_path).unwrap(); - assert_eq!(new_content, content); -} - -#[test] -fn it_create_all_erase_exist_folder() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_create_all_erase_exist_folder"); - test_dir.push("sub"); - if test_dir.exists() { - remove(&test_dir).unwrap(); - } - assert!(!test_dir.exists()); - create_all(&test_dir, true).unwrap(); - assert!(test_dir.exists()); - let mut file_path = test_dir.clone(); - file_path.push("test.txt"); - assert!(!file_path.exists()); - fs_extra::file::write_all(&file_path, "test_content").unwrap(); - assert!(file_path.exists()); - - create_all(&test_dir, true).unwrap(); - assert!(test_dir.exists()); - assert!(!file_path.exists()); -} - -#[test] -fn it_remove_work() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_remove_work"); - test_dir.push("sub"); - test_dir.push("second_sub"); - create_all(&test_dir, true).unwrap(); - assert!(test_dir.exists()); - test_dir.pop(); - test_dir.pop(); - remove(&test_dir).unwrap(); - assert!(!test_dir.exists()); -} - -#[test] -fn it_remove_not_exist() { - let mut test_dir = PathBuf::from(TEST_FOLDER); - test_dir.push("it_remove_not_exist"); - test_dir.push("sub"); - assert!(!test_dir.exists()); - match remove(&test_dir) { - Ok(_) => { - assert!(!test_dir.exists()); - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_copy_work() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_work"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let options = CopyOptions::new(); - let result = copy(&path_from, &path_to, &options).unwrap(); - - assert_eq!(16, result); - assert!(path_to.exists()); - assert!(path_from.exists()); - assert!(compare_dir(&path_from, &path_to)); -} - -#[test] -fn it_copy_not_folder() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_copy_not_folder"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - path_from.push("test.txt"); - fs_extra::file::write_all(&path_from, "test").unwrap(); - - match copy(&path_from, &path_to, &options) { - Err(err) => match err.kind { - ErrorKind::InvalidFolder => { - let wrong_path = format!( - "Path \"{}\" is not a directory!", - path_from.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_copy_source_not_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_copy_source_not_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - assert!(!path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - match copy(&path_from, &path_to, &options) { - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!( - "Path \"{}\" does not exist or you don't have \ - access!", - path_from.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_copy_exist_overwrite() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_exist_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let mut options = CopyOptions::new(); - options.overwrite = true; - copy(&path_from, &path_to, &options).unwrap(); - - assert!(exist_path.exists()); - assert!(files_eq(file1_path, exist_path)); - assert!(path_to.exists()); - assert!(compare_dir(&path_from, &path_to)); -} - -#[test] -fn it_copy_exist_not_overwrite() { - let test_name = "sub"; - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_copy_exist_not_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let options = CopyOptions::new(); - match copy(&path_from, &path_to, &options) { - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - let wrong_path = format!("Path \"{}\" is exist", exist_path.to_str().unwrap()); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_copy_exist_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_exist_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let mut options = CopyOptions::new(); - options.skip_exist = true; - copy(&path_from, &path_to, &options).unwrap(); - - assert!(exist_path.exists()); - assert!(!files_eq(file1_path, &exist_path)); - assert_eq!( - fs_extra::file::read_to_string(exist_path).unwrap(), - exist_content - ); - - assert!(path_to.exists()); - assert!(!compare_dir(&path_from, &path_to)); -} - -#[test] -fn it_copy_exist_overwrite_and_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_exist_overwrite_and_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let mut options = CopyOptions::new(); - options.overwrite = true; - options.skip_exist = true; - copy(&path_from, &path_to, &options).unwrap(); - - assert!(exist_path.exists()); - assert!(files_eq(file1_path, exist_path)); - assert!(path_to.exists()); - assert!(compare_dir(&path_from, &path_to)); -} - -#[test] -fn it_copy_using_first_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_first_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&d_level_4.0, true).unwrap(); - create_all(&d_level_5.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = CopyOptions::new(); - options.depth = 1; - let result = copy(&d_level_1.0, path_to, &options).unwrap(); - - assert_eq!(8, result); - - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); -} - -#[test] -fn it_copy_using_four_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_four_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&d_level_4.0, true).unwrap(); - create_all(&d_level_5.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = CopyOptions::new(); - options.depth = 4; - let result = copy(&d_level_1.0, path_to, &options).unwrap(); - - assert_eq!(32, result); - - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(d_level_3.1.exists()); - assert!(d_level_4.1.exists()); - assert!(d_level_5.1.exists()); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - assert!(files_eq(&file3.0, &file3.1)); - assert!(files_eq(&file4.0, &file4.1)); -} -#[test] -fn it_copy_content_only_option() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_content_only_option"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.clone()); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - - let mut options = CopyOptions::new(); - options.content_only = true; - let result = copy(&d_level_1.0, path_to, &options).unwrap(); - - assert_eq!(24, result); - - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(d_level_3.1.exists()); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - assert!(files_eq(&file3.0, &file3.1)); -} - -#[test] -fn it_copy_progress_work() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_progress_work"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(15, result); - assert!(path_to.exists()); - assert!(compare_dir(&path_from, &path_to)); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "test2.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else if process_info.file_name == "test1.txt" { - assert_eq!(7, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_copy_with_progress_not_folder() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_copy_with_progress_not_folder"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - path_from.push("test.txt"); - fs_extra::file::write_all(&path_from, "test").unwrap(); - let func_test = |process_info: TransitProcess| { - match process_info.state { - TransitState::NoAccess => {} - _ => panic!("Error not should be!"), - }; - TransitProcessResult::ContinueOrAbort - }; - match copy_with_progress(&path_from, &path_to, &options, func_test) { - Err(err) => match err.kind { - ErrorKind::InvalidFolder => { - let wrong_path = format!( - "Path \"{}\" is not a directory!", - path_from.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_copy_with_progress_work_dif_buf_size() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_with_progress_work_dif_buf_size"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(16, result); - assert!(path_to.exists()); - assert!(compare_dir(&path_from, &path_to)); - - let mut options = CopyOptions::new(); - options.buffer_size = 2; - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(16, result); - assert!(path_to.exists()); - assert!(compare_dir(&path_from, &path_to)); - }).join(); - for i in 1..5 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2, process_info.file_bytes_copied); - assert_eq!(i * 2, process_info.copied_bytes); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - for i in 1..5 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2 + 8, process_info.copied_bytes); - assert_eq!(i * 2, process_info.file_bytes_copied); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - }).join(); - - for i in 1..9 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i, process_info.file_bytes_copied); - assert_eq!(i, process_info.copied_bytes); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - for i in 1..9 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i + 8, process_info.copied_bytes); - assert_eq!(i, process_info.file_bytes_copied); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} -#[test] -fn it_copy_with_progress_source_not_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_copy_with_progress_source_not_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - assert!(!path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - match copy_with_progress(&path_from, &path_to, &options, func_test) { - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!( - "Path \"{}\" does not exist or you don't \ - have access!", - path_from.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } - }).join(); - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => {} - _ => panic!("should be error"), - } -} - -#[test] -fn it_copy_with_progress_exist_overwrite() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_with_progress_exist_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - fs_extra::file::write_all(&file2_path, "another conntent").unwrap(); - - options.buffer_size = 1; - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(23, result); - assert!(path_to.exists()); - assert!(compare_dir(&path_from, &path_to)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_with_progress_exist_not_overwrite() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_with_progress_exist_not_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - - options.buffer_size = 1; - let func_test = |process_info: TransitProcess| { - match process_info.state { - TransitState::Exists => {} - _ => panic!("Error not should be!"), - }; - TransitProcessResult::ContinueOrAbort - }; - let result = copy_with_progress(&path_from, &path_to, &options, func_test); - match result { - Ok(_) => panic!("Should be error!"), - Err(err) => match err.kind { - ErrorKind::AlreadyExists => {} - _ => panic!("Wrong wrror"), - }, - } -} - -#[test] -fn it_copy_with_progress_exist_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_with_progress_exist_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - - fs_extra::file::write_all(&file2_path, "another conntent").unwrap(); - options.buffer_size = 1; - options.skip_exist = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(0, result); - assert!(path_to.exists()); - assert!(!compare_dir(&path_from, &path_to)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => {} - _ => panic!("should be error"), - } -} - -#[test] -fn it_copy_with_progress_exist_overwrite_and_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_copy_with_progress_exist_overwrite_and_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - fs_extra::file::write_all(&file2_path, "another conntent").unwrap(); - - options.buffer_size = 1; - options.overwrite = true; - options.skip_exist = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(23, result); - assert!(path_to.exists()); - assert!(compare_dir(&path_from, &path_to)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_using_first_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_first_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&d_level_4.0, true).unwrap(); - create_all(&d_level_5.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = CopyOptions::new(); - options.depth = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = copy_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap(); - - assert_eq!(8, result); - - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_with_progress_using_four_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_four_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&d_level_4.0, true).unwrap(); - create_all(&d_level_5.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = CopyOptions::new(); - options.depth = 4; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = copy_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap(); - - assert_eq!(32, result); - - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(d_level_3.1.exists()); - assert!(d_level_4.1.exists()); - assert!(d_level_5.1.exists()); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - assert!(files_eq(&file3.0, &file3.1)); - assert!(files_eq(&file4.0, &file4.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} -#[test] -fn it_copy_with_progress_content_only_option() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_content_only_option"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.clone()); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - - let mut options = CopyOptions::new(); - options.content_only = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = copy_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap(); - - assert_eq!(24, result); - - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(d_level_3.1.exists()); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - assert!(files_eq(&file3.0, &file3.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_inside_work_target_dir_not_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join("it_copy_inside_work_target_dir_not_exist"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - - if root_dir2.exists() { - remove(&root_dir2).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(!root_dir2.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - let result = copy(&root_dir1, &root_dir2, &options).unwrap(); - - assert_eq!(16, result); - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(compare_dir_recursively(&root_dir1, &root_dir2)); -} - -#[test] -fn it_copy_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() { - let path_root = Path::new(TEST_FOLDER); - let root = - path_root.join("it_copy_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - fs_extra::file::write_all(&file3, "content3").unwrap(); - - if root_dir2_dir1.exists() { - remove(&root_dir2_dir1).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(!root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - let result = copy(&root_dir1, &root_dir2, &options).unwrap(); - - assert_eq!(16, result); - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - assert!(compare_dir(&root_dir1, &root_dir2)); -} - -#[test] -fn it_copy_inside_work_target_dir_exist_with_source_dir_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join("it_copy_inside_work_target_dir_exist_with_source_dir_exist"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - let old_file1 = root_dir2_dir1.join("file1.txt"); - let old_file2 = root_dir2_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - create_all(&root_dir2_dir1, true).unwrap(); - create_all(&root_dir2_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - fs_extra::file::write_all(&file3, "content3").unwrap(); - fs_extra::file::write_all(&old_file1, "old_content1").unwrap(); - fs_extra::file::write_all(&old_file2, "old_content2").unwrap(); - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - assert!(old_file1.exists()); - assert!(old_file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - match copy(&root_dir1, &root_dir2, &options) { - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - assert_eq!(1, 1); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } - options.overwrite = true; - - let result = copy(&root_dir1, &root_dir2, &options).unwrap(); - - assert_eq!(16, result); - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(compare_dir(&root_dir1, &root_dir2)); -} - -// The compare_dir method assumes that the folder `path_to` must have a sub folder named the last component of the `path_from`. -// In order to compare two folders with different name but share the same structure, rewrite a new compare method to do that! -fn compare_dir_recursively(path_from: P, path_to: Q) -> bool -where - P: AsRef, - Q: AsRef, -{ - let path_to = path_to.as_ref().to_path_buf(); - - for entry in read_dir(&path_from).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - if path.is_dir() { - match path.components().last() { - None => panic!("Invalid folder from"), - Some(dir_name) => { - let mut target_dir = path_to.to_path_buf(); - target_dir.push(dir_name.as_os_str()); - if !compare_dir_recursively(path.clone(), &target_dir) { - return false; - } - } - } - } else { - let mut target_file = path_to.to_path_buf(); - match path.file_name() { - None => panic!("No file name"), - Some(file_name) => { - target_file.push(file_name); - if !target_file.exists() { - return false; - } else if !files_eq(&path, target_file.clone()) { - return false; - } - } - } - } - } - - true -} - -#[test] -fn it_move_work() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_work"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let options = CopyOptions::new(); - let result = move_dir(&path_from, &path_to, &options).unwrap(); - - assert_eq!(16, result); - assert!(path_to.exists()); - assert!(!path_from.exists()); -} - -#[test] -fn it_move_not_folder() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_move_not_folder"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - path_from.push("test.txt"); - fs_extra::file::write_all(&path_from, "test").unwrap(); - - match move_dir(&path_from, &path_to, &options) { - Err(err) => match err.kind { - ErrorKind::InvalidFolder => { - let wrong_path = format!( - "Path \"{}\" is not a directory or you don't have \ - access!", - path_from.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_move_source_not_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_move_source_not_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - assert!(!path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - match move_dir(&path_from, &path_to, &options) { - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!("Path \"{}\" does not exist", path_from.to_str().unwrap()); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_move_exist_overwrite() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_exist_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let mut options = CopyOptions::new(); - options.overwrite = true; - move_dir(&path_from, &path_to, &options).unwrap(); - - assert!(exist_path.exists()); - assert!(path_to.exists()); - assert!(!path_from.exists()); -} - -#[test] -fn it_move_exist_not_overwrite() { - let test_name = "sub"; - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_move_exist_not_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let options = CopyOptions::new(); - match move_dir(&path_from, &path_to, &options) { - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - let wrong_path = format!("Path \"{}\" is exist", exist_path.to_str().unwrap()); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_move_exist_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_exist_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let mut options = CopyOptions::new(); - options.skip_exist = true; - move_dir(&path_from, &path_to, &options).unwrap(); - - assert!(exist_path.exists()); - assert_eq!( - fs_extra::file::read_to_string(exist_path).unwrap(), - exist_content - ); - - assert!(path_to.exists()); -} - -#[test] -fn it_move_exist_overwrite_and_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_exist_overwrite_and_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - let same_file = "test.txt"; - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push(same_file); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut exist_path = path_to.clone(); - exist_path.push(&test_name); - create(&exist_path, true).unwrap(); - assert!(exist_path.exists()); - exist_path.push(same_file); - let exist_content = "exist content"; - assert_ne!(exist_content, content1); - fs_extra::file::write_all(&exist_path, exist_content).unwrap(); - assert!(exist_path.exists()); - - let mut options = CopyOptions::new(); - options.overwrite = true; - options.skip_exist = true; - move_dir(&path_from, &path_to, &options).unwrap(); - - assert!(exist_path.exists()); - assert!(path_to.exists()); - assert!(!path_from.exists()); -} - -#[test] -fn it_move_inside_work_target_dir_not_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join("it_move_inside_work_target_dir_not_exist"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - - if root_dir2.exists() { - remove(&root_dir2).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(!root_dir2.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - let result = move_dir(&root_dir1, &root_dir2, &options).unwrap(); - - assert_eq!(16, result); - assert!(!root_dir1.exists()); - let root_dir2_sub = root_dir2.join("sub"); - let root_dir2_file1 = root_dir2.join("file1.txt"); - let root_dir2_sub_file2 = root_dir2_sub.join("file2.txt"); - assert!(root_dir2.exists()); - assert!(root_dir2_sub.exists()); - assert!(root_dir2_file1.exists()); - assert!(root_dir2_sub_file2.exists()); -} - -#[test] -fn it_move_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() { - let path_root = Path::new(TEST_FOLDER); - let root = - path_root.join("it_move_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - fs_extra::file::write_all(&file3, "content3").unwrap(); - - if root_dir2_dir1.exists() { - remove(&root_dir2_dir1).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(!root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - let result = move_dir(&root_dir1, &root_dir2, &options).unwrap(); - - assert_eq!(16, result); - assert!(!root_dir1.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt"); - let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt"); - assert!(root_dir2_dir1_file1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir1_sub_file2.exists()); - assert!(root_dir2_dir3_file3.exists()); -} - -#[test] -fn it_move_inside_work_target_dir_exist_with_source_dir_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join("it_move_inside_work_target_dir_exist_with_source_dir_exist"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - let old_file1 = root_dir2_dir1.join("file1.txt"); - let old_file2 = root_dir2_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - create_all(&root_dir2_dir1, true).unwrap(); - create_all(&root_dir2_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - fs_extra::file::write_all(&file3, "content3").unwrap(); - fs_extra::file::write_all(&old_file1, "old_content1").unwrap(); - fs_extra::file::write_all(&old_file2, "old_content2").unwrap(); - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - assert!(old_file1.exists()); - assert!(old_file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - match copy(&root_dir1, &root_dir2, &options) { - Err(err) => match err.kind { - ErrorKind::AlreadyExists => { - assert_eq!(1, 1); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } - options.overwrite = true; - let result = move_dir(&root_dir1, &root_dir2, &options).unwrap(); - - assert_eq!(16, result); - assert!(!root_dir1.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt"); - let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt"); - let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt"); - assert!(root_dir2_dir1_file1.exists()); - assert!(root_dir2_dir1_sub_file2.exists()); - assert!(root_dir2_dir3_file3.exists()); -} -#[test] -fn it_move_content_only_option() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_content_only_option"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.clone()); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - - let mut options = CopyOptions::new(); - options.content_only = true; - let result = move_dir(&d_level_1.0, path_to, &options).unwrap(); - - assert_eq!(24, result); - - assert!(!d_level_1.0.exists()); - assert!(!d_level_2.0.exists()); - assert!(!d_level_3.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(d_level_3.1.exists()); - - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); -} -#[test] -fn it_move_progress_work() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_progress_work"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(15, result); - assert!(path_to.exists()); - assert!(!path_from.exists()); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "test2.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else if process_info.file_name == "test1.txt" { - assert_eq!(7, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_move_with_progress_not_folder() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_move_with_progress_not_folder"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - path_from.push("test.txt"); - fs_extra::file::write_all(&path_from, "test").unwrap(); - let func_test = |process_info: TransitProcess| { - match process_info.state { - TransitState::NoAccess => {} - _ => panic!("Error not should be!"), - }; - TransitProcessResult::ContinueOrAbort - }; - - match move_dir_with_progress(&path_from, &path_to, &options, func_test) { - Err(err) => match err.kind { - ErrorKind::InvalidFolder => { - let wrong_path = format!( - "Path \"{}\" is not a directory!", - path_from.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_move_with_progress_work_dif_buf_size() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_with_progress_work_dif_buf_size"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(16, result); - assert!(path_to.exists()); - assert!(!path_from.exists()); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content1"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - options.buffer_size = 2; - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(16, result); - assert!(path_to.exists()); - assert!(!path_from.exists()); - }).join(); - for i in 1..5 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2, process_info.file_bytes_copied); - assert_eq!(i * 2, process_info.copied_bytes); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - for i in 1..5 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2 + 8, process_info.copied_bytes); - assert_eq!(i * 2, process_info.file_bytes_copied); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - }).join(); - - for i in 1..9 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i, process_info.file_bytes_copied); - assert_eq!(i, process_info.copied_bytes); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - for i in 1..9 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i + 8, process_info.copied_bytes); - assert_eq!(i, process_info.file_bytes_copied); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(16, process_info.total_bytes); - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} -#[test] -fn it_move_with_progress_source_not_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - path_from.push("it_move_with_progress_source_not_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push("sub"); - - assert!(!path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let options = CopyOptions::new(); - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - match move_dir_with_progress(&path_from, &path_to, &options, func_test) { - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!( - "Path \"{}\" does not exist or you don't \ - have access!", - path_from.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } - }).join(); - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => {} - _ => panic!("should be error"), - } -} - -#[test] -fn it_move_with_progress_exist_overwrite() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_with_progress_exist_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - fs_extra::file::write_all(&file2_path, "another conntent").unwrap(); - - options.buffer_size = 1; - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(23, result); - assert!(path_to.exists()); - assert!(!path_from.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_not_overwrite() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_with_progress_exist_not_overwrite"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = move_dir_with_progress(&path_from, &path_to, &options, func_test); - match result { - Ok(_) => panic!("Should be error!"), - Err(err) => match err.kind { - ErrorKind::AlreadyExists => {} - _ => panic!("Wrong wrror"), - }, - } - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => { - panic!("Error not should be!"); - } - _ => {} - } -} - -#[test] -fn it_move_with_progress_exist_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_with_progress_exist_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - - fs_extra::file::write_all(&file2_path, "another conntent").unwrap(); - options.buffer_size = 1; - options.skip_exist = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(0, result); - assert!(path_from.exists()); - assert!(path_to.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => {} - _ => panic!("should be error"), - } -} - -#[test] -fn it_move_with_progress_exist_overwrite_and_skip_exist() { - let mut path_from = PathBuf::from(TEST_FOLDER); - let test_name = "sub"; - path_from.push("it_move_with_progress_exist_overwrite_and_skip_exist"); - let mut path_to = path_from.clone(); - path_to.push("out"); - path_from.push(&test_name); - - create_all(&path_from, true).unwrap(); - assert!(path_from.exists()); - create_all(&path_to, true).unwrap(); - assert!(path_to.exists()); - - let mut file1_path = path_from.clone(); - file1_path.push("test1.txt"); - let content1 = "content"; - fs_extra::file::write_all(&file1_path, &content1).unwrap(); - assert!(file1_path.exists()); - - let mut sub_dir_path = path_from.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2_path = sub_dir_path.clone(); - file2_path.push("test2.txt"); - let content2 = "content2"; - fs_extra::file::write_all(&file2_path, &content2).unwrap(); - assert!(file2_path.exists()); - - let mut options = CopyOptions::new(); - copy(&path_from, &path_to, &options).unwrap(); - fs_extra::file::write_all(&file2_path, "another conntent").unwrap(); - - options.buffer_size = 1; - options.overwrite = true; - options.skip_exist = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap(); - - assert_eq!(23, result); - assert!(path_to.exists()); - assert!(!path_from.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.recv().unwrap(); -} - -#[test] -fn it_get_folder_size() { - let mut path = PathBuf::from(TEST_FOLDER); - path.push("it_get_folder_size"); - path.push("dir"); - - create_all(&path, true).unwrap(); - assert!(path.exists()); - - let mut file1 = path.clone(); - file1.push("test1.txt"); - fs_extra::file::write_all(&file1, "content1").unwrap(); - assert!(file1.exists()); - - let mut sub_dir_path = path.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2 = sub_dir_path.clone(); - file2.push("test2.txt"); - fs_extra::file::write_all(&file2, "content2").unwrap(); - assert!(file2.exists()); - - let result = get_size(&path).unwrap(); - - assert_eq!(16, result); -} - -#[test] -fn it_get_file_size() { - let mut path = PathBuf::from(TEST_FOLDER); - path.push("it_get_file_size"); - - create_all(&path, true).unwrap(); - assert!(path.exists()); - - let mut file = path.clone(); - file.push("test1.txt"); - fs_extra::file::write_all(&file, "content").unwrap(); - assert!(file.exists()); - - let result = get_size(&path).unwrap(); - - assert_eq!(7, result); -} - -#[test] -fn it_get_size_not_found() { - let mut path = PathBuf::from(TEST_FOLDER); - path.push("it_get_size_not_found"); - - assert!(!path.exists()); - - match get_size(&path) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::NotFound => {} - _ => panic!("Wrong error!"), - }, - }; -} - -#[test] -fn it_get_dir_content() { - let mut path = PathBuf::from(TEST_FOLDER); - path.push("it_get_dir_content"); - path.push("dir"); - - create_all(&path, true).unwrap(); - assert!(path.exists()); - - let mut file1 = path.clone(); - file1.push("test1.txt"); - fs_extra::file::write_all(&file1, "content1").unwrap(); - assert!(file1.exists()); - - let mut sub_dir_path = path.clone(); - sub_dir_path.push("sub"); - create(&sub_dir_path, true).unwrap(); - let mut file2 = sub_dir_path.clone(); - file2.push("test2.txt"); - fs_extra::file::write_all(&file2, "content2").unwrap(); - assert!(file2.exists()); - - let result = get_dir_content(&path).unwrap(); - - assert_eq!(16, result.dir_size); - assert_eq!(2, result.files.len()); - assert_eq!(2, result.directories.len()); - - let dir1 = file1.parent().unwrap().to_str().unwrap().to_string(); - let dir2 = file2.parent().unwrap().to_str().unwrap().to_string(); - let file1 = file1.to_str().unwrap().to_string(); - let file2 = file2.to_str().unwrap().to_string(); - - let mut files_correct = true; - for file in result.files { - if file != file1 && file != file2 { - files_correct = false; - } - } - assert!(files_correct); - - let mut directories_correct = true; - for dir in result.directories { - if dir != dir1 && dir != dir2 { - directories_correct = false; - } - } - assert!(directories_correct); -} - -#[test] -fn it_get_dir_content_many_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_get_dir_content_many_levels"); - let d_level_1 = test_dir.join("d_level_1"); - let d_level_2 = d_level_1.join("d_level_2"); - let d_level_3 = d_level_2.join("d_level_3"); - let d_level_4 = d_level_3.join("d_level_4"); - let d_level_5 = d_level_4.join("d_level_5"); - - let file1 = d_level_1.join("file1.txt"); - let file2 = d_level_2.join("file2.txt"); - let file3 = d_level_3.join("file3.txt"); - let file4 = d_level_4.join("file4.txt"); - let file5 = d_level_5.join("file5.txt"); - - create_all(&d_level_1, true).unwrap(); - create_all(&d_level_2, true).unwrap(); - create_all(&d_level_3, true).unwrap(); - create_all(&d_level_4, true).unwrap(); - create_all(&d_level_5, true).unwrap(); - - assert!(&d_level_1.exists()); - assert!(&d_level_2.exists()); - assert!(&d_level_3.exists()); - assert!(&d_level_4.exists()); - assert!(&d_level_5.exists()); - - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - fs_extra::file::write_all(&file3, "content3").unwrap(); - fs_extra::file::write_all(&file4, "content4").unwrap(); - fs_extra::file::write_all(&file5, "content5").unwrap(); - - let mut options = DirOptions::new(); - let result = get_dir_content2(&d_level_1, &options).unwrap(); - - assert_eq!(40, result.dir_size); - assert_eq!(5, result.files.len()); - assert_eq!(5, result.directories.len()); - - let mut directories = Vec::new(); - directories.push(file1.parent().unwrap().to_str().unwrap().to_string()); - directories.push(file2.parent().unwrap().to_str().unwrap().to_string()); - directories.push(file3.parent().unwrap().to_str().unwrap().to_string()); - directories.push(file4.parent().unwrap().to_str().unwrap().to_string()); - directories.push(file5.parent().unwrap().to_str().unwrap().to_string()); - - let mut files = Vec::new(); - files.push(file1.to_str().unwrap().to_string()); - files.push(file2.to_str().unwrap().to_string()); - files.push(file3.to_str().unwrap().to_string()); - files.push(file4.to_str().unwrap().to_string()); - files.push(file5.to_str().unwrap().to_string()); - - let mut files_correct = true; - for file in result.files { - if !files.contains(&file) { - files_correct = false; - } - } - assert!(files_correct); - - let mut directories_correct = true; - for dir in result.directories { - if !directories.contains(&dir) { - directories_correct = false; - } - } - assert!(directories_correct); - - // first level - options.depth = 1; - let result = get_dir_content2(&d_level_1, &options).unwrap(); - - assert_eq!(8, result.dir_size); - assert_eq!(1, result.files.len()); - assert_eq!(2, result.directories.len()); - files_correct = true; - for file in &result.files { - if !files.contains(&file) { - files_correct = false; - } - } - assert!(files_correct); - assert!(result.files.contains(&file1.to_str().unwrap().to_string())); - - directories_correct = true; - for dir in &result.directories { - if !directories.contains(&dir) { - directories_correct = false; - } - } - assert!(directories_correct); - assert!( - result - .directories - .contains(&file1.parent().unwrap().to_str().unwrap().to_string(),) - ); - assert!( - result - .directories - .contains(&file2.parent().unwrap().to_str().unwrap().to_string(),) - ); - - // fourth level - options.depth = 4; - let result = get_dir_content2(&d_level_1, &options).unwrap(); - - assert_eq!(32, result.dir_size); - assert_eq!(4, result.files.len()); - assert_eq!(5, result.directories.len()); - files_correct = true; - for file in &result.files { - if !files.contains(&file) { - files_correct = false; - } - } - assert!(files_correct); - assert!(result.files.contains(&file1.to_str().unwrap().to_string())); - assert!(result.files.contains(&file2.to_str().unwrap().to_string())); - assert!(result.files.contains(&file3.to_str().unwrap().to_string())); - assert!(result.files.contains(&file4.to_str().unwrap().to_string())); - - directories_correct = true; - for dir in &result.directories { - if !directories.contains(&dir) { - directories_correct = false; - } - } - assert!(directories_correct); - assert!( - result - .directories - .contains(&file1.parent().unwrap().to_str().unwrap().to_string(),) - ); - assert!( - result - .directories - .contains(&file2.parent().unwrap().to_str().unwrap().to_string(),) - ); - assert!( - result - .directories - .contains(&file3.parent().unwrap().to_str().unwrap().to_string(),) - ); - assert!( - result - .directories - .contains(&file4.parent().unwrap().to_str().unwrap().to_string(),) - ); - assert!( - result - .directories - .contains(&file5.parent().unwrap().to_str().unwrap().to_string(),) - ); -} - -#[test] -fn it_get_dir_content_path_file() { - let mut path = PathBuf::from(TEST_FOLDER); - path.push("it_get_dir_content_path_file"); - - create_all(&path, true).unwrap(); - assert!(path.exists()); - - let mut file = path.clone(); - file.push("test1.txt"); - fs_extra::file::write_all(&file, "content1").unwrap(); - assert!(file.exists()); - - let result = get_dir_content(&file).unwrap(); - - assert_eq!(8, result.dir_size); - assert_eq!(1, result.files.len()); - assert_eq!(0, result.directories.len()); - assert_eq!(file.to_str().unwrap().to_string(), result.files[0]); -} - -#[test] -fn it_get_dir_content_not_found() { - let mut path = PathBuf::from(TEST_FOLDER); - path.push("it_get_dir_content_not_found"); - - assert!(!path.exists()); - - match get_dir_content(&path) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::NotFound => {} - _ => panic!("Wrong error!"), - }, - } -} - -#[test] -fn it_details_item_dir() { - let test_dir = Path::new(TEST_FOLDER).join("it_details_item_dir"); - create_all(&test_dir, true).unwrap(); - assert!(test_dir.exists()); - let mut config = HashSet::new(); - config.insert(DirEntryAttr::Name); - config.insert(DirEntryAttr::Ext); - config.insert(DirEntryAttr::FullName); - config.insert(DirEntryAttr::Path); - config.insert(DirEntryAttr::DosPath); - config.insert(DirEntryAttr::Size); - config.insert(DirEntryAttr::IsDir); - config.insert(DirEntryAttr::IsFile); - config.insert(DirEntryAttr::Modified); - config.insert(DirEntryAttr::Accessed); - let item = get_details_entry(test_dir, &config).unwrap(); - assert_eq!(10, item.len()); - - let mut fields = 0; - if let Some(name) = item.get(&DirEntryAttr::Name) { - if let &DirEntryValue::String(ref name) = name { - assert_eq!("it_details_item_dir", name); - fields += 1; - } - } - if let Some(ext) = item.get(&DirEntryAttr::Ext) { - if let &DirEntryValue::String(ref ext) = ext { - assert_eq!("", ext); - fields += 1; - } - } - if let Some(fname) = item.get(&DirEntryAttr::FullName) { - if let &DirEntryValue::String(ref fname) = fname { - assert_eq!("it_details_item_dir", fname); - fields += 1; - } - } - if let Some(path) = item.get(&DirEntryAttr::Path) { - if let &DirEntryValue::String(ref path) = path { - if !path.is_empty() { - fields += 1; - } - } - } - if let Some(path) = item.get(&DirEntryAttr::DosPath) { - if let &DirEntryValue::String(ref path) = path { - if !path.is_empty() { - fields += 1; - } - } - } - if let Some(size) = item.get(&DirEntryAttr::Size) { - if let &DirEntryValue::U64(size) = size { - assert_eq!(0, size); - fields += 1; - } - } - if let Some(is_dir) = item.get(&DirEntryAttr::IsDir) { - if let &DirEntryValue::Boolean(is_dir) = is_dir { - assert_eq!(true, is_dir); - fields += 1; - } - } - - if let Some(is_file) = item.get(&DirEntryAttr::IsFile) { - if let &DirEntryValue::Boolean(is_file) = is_file { - assert_eq!(false, is_file); - fields += 1; - } - } - - if let Some(modified) = item.get(&DirEntryAttr::Modified) { - if let &DirEntryValue::SystemTime(modified) = modified { - if modified.elapsed().unwrap().as_secs() == 0 { - fields += 1; - } - } - } - if let Some(accessed) = item.get(&DirEntryAttr::Accessed) { - if let &DirEntryValue::SystemTime(accessed) = accessed { - if accessed.elapsed().unwrap().as_secs() == 0 { - fields += 1; - } - } - } - - assert_eq!(10, fields); -} - -#[test] -fn it_details_file_item() { - let test_dir = Path::new(TEST_FOLDER).join("it_details_file_item"); - create_all(&test_dir, true).unwrap(); - let file = test_dir.join("file.txt"); - fs_extra::file::write_all(&file, "content").unwrap(); - assert!(file.exists()); - let mut config = HashSet::new(); - config.insert(DirEntryAttr::Name); - config.insert(DirEntryAttr::Ext); - config.insert(DirEntryAttr::FullName); - config.insert(DirEntryAttr::Path); - config.insert(DirEntryAttr::DosPath); - config.insert(DirEntryAttr::Size); - config.insert(DirEntryAttr::FileSize); - config.insert(DirEntryAttr::IsDir); - config.insert(DirEntryAttr::IsFile); - config.insert(DirEntryAttr::Modified); - config.insert(DirEntryAttr::Accessed); - let item = get_details_entry(file, &config).unwrap(); - assert_eq!(11, item.len()); - - let mut fields = 0; - if let Some(name) = item.get(&DirEntryAttr::Name) { - if let &DirEntryValue::String(ref name) = name { - assert_eq!("file", name); - fields += 1; - } - } - if let Some(ext) = item.get(&DirEntryAttr::Ext) { - if let &DirEntryValue::String(ref ext) = ext { - assert_eq!("txt", ext); - fields += 1; - } - } - if let Some(fname) = item.get(&DirEntryAttr::FullName) { - if let &DirEntryValue::String(ref fname) = fname { - assert_eq!("file.txt", fname); - fields += 1; - } - } - if let Some(path) = item.get(&DirEntryAttr::Path) { - if let &DirEntryValue::String(ref path) = path { - if !path.is_empty() { - fields += 1; - } - } - } - if let Some(path) = item.get(&DirEntryAttr::DosPath) { - if let &DirEntryValue::String(ref path) = path { - if !path.is_empty() { - fields += 1; - } - } - } - if let Some(size) = item.get(&DirEntryAttr::Size) { - if let &DirEntryValue::U64(size) = size { - assert_eq!(7, size); - fields += 1; - } - } - if let Some(size) = item.get(&DirEntryAttr::FileSize) { - if let &DirEntryValue::U64(size) = size { - assert_eq!(7, size); - fields += 1; - } - } - if let Some(is_dir) = item.get(&DirEntryAttr::IsDir) { - if let &DirEntryValue::Boolean(is_dir) = is_dir { - assert_eq!(false, is_dir); - fields += 1; - } - } - - if let Some(is_file) = item.get(&DirEntryAttr::IsFile) { - if let &DirEntryValue::Boolean(is_file) = is_file { - assert_eq!(true, is_file); - fields += 1; - } - } - - if let Some(modified) = item.get(&DirEntryAttr::Modified) { - if let &DirEntryValue::SystemTime(modified) = modified { - if modified.elapsed().unwrap().as_secs() == 0 { - fields += 1; - } - } - } - if let Some(accessed) = item.get(&DirEntryAttr::Accessed) { - if let &DirEntryValue::SystemTime(accessed) = accessed { - if accessed.elapsed().unwrap().as_secs() == 0 { - fields += 1; - } - } - } - - assert_eq!(11, fields); -} - -#[test] -fn it_details_item_dir_short() { - let test_dir = Path::new(TEST_FOLDER).join("it_details_item_dir_short"); - create_all(&test_dir, true).unwrap(); - assert!(test_dir.exists()); - let mut config = HashSet::new(); - config.insert(DirEntryAttr::Name); - config.insert(DirEntryAttr::Size); - let item = get_details_entry(test_dir, &config).unwrap(); - assert_eq!(2, item.len()); - - if let Some(name) = item.get(&DirEntryAttr::Name) { - if let &DirEntryValue::String(ref name) = name { - assert_eq!("it_details_item_dir_short", name); - } - } - if let Some(size) = item.get(&DirEntryAttr::Size) { - if let &DirEntryValue::U64(size) = size { - assert_eq!(0, size); - } - } -} - -#[test] -fn it_details_item_file_short() { - let test_dir = Path::new(TEST_FOLDER).join("it_details_item_short"); - create_all(&test_dir, true).unwrap(); - let file = test_dir.join("file.txt"); - fs_extra::file::write_all(&file, "content").unwrap(); - assert!(file.exists()); - let mut config = HashSet::new(); - config.insert(DirEntryAttr::Name); - config.insert(DirEntryAttr::Size); - let item = get_details_entry(file, &config).unwrap(); - assert_eq!(2, item.len()); - - if let Some(name) = item.get(&DirEntryAttr::Name) { - if let &DirEntryValue::String(ref name) = name { - assert_eq!("file", name); - } - } - if let Some(size) = item.get(&DirEntryAttr::Size) { - if let &DirEntryValue::U64(size) = size { - assert_eq!(7, size); - } - } -} - -#[test] -fn it_ls() { - let test_dir = Path::new(TEST_FOLDER).join("it_ls"); - create_all(&test_dir, true).unwrap(); - let file1 = test_dir.join("file1.txt"); - let file2 = test_dir.join("file2.txt"); - fs_extra::file::write_all(&file1, "content").unwrap(); - fs_extra::file::write_all(&file2, "content").unwrap(); - assert!(file1.exists()); - assert!(file2.exists()); - let mut config = HashSet::new(); - config.insert(DirEntryAttr::Name); - config.insert(DirEntryAttr::Size); - config.insert(DirEntryAttr::IsDir); - config.insert(DirEntryAttr::BaseInfo); - let ls_result = ls(&test_dir, &config).unwrap(); - assert_eq!(2, ls_result.items.len()); - assert_eq!(3, ls_result.base.len()); - - if let Some(name) = ls_result.base.get(&DirEntryAttr::Name) { - if let &DirEntryValue::String(ref name) = name { - assert_eq!("it_ls", name); - } - } - if let Some(size) = ls_result.base.get(&DirEntryAttr::Size) { - if let &DirEntryValue::U64(size) = size { - assert_eq!(14, size); - } - } - if let Some(is_dir) = ls_result.base.get(&DirEntryAttr::IsDir) { - if let &DirEntryValue::Boolean(is_dir) = is_dir { - assert_eq!(true, is_dir); - } - } - for item in ls_result.items { - if let Some(name) = item.get(&DirEntryAttr::Name) { - if let &DirEntryValue::String(ref name) = name { - assert_eq!(String::from("file"), name[..4]); - } - } - if let Some(size) = item.get(&DirEntryAttr::Size) { - if let &DirEntryValue::U64(size) = size { - assert_eq!(7, size); - } - } - if let Some(is_dir) = item.get(&DirEntryAttr::IsDir) { - if let &DirEntryValue::Boolean(is_dir) = is_dir { - assert_eq!(false, is_dir); - } - } - } -} - -#[test] -fn it_copy_with_progress_exist_user_decide_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::Overwrite; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(2, count_exist_files); - - assert_eq!(16, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - assert!(compare_dir(&dir.0, &out)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_overwrite_all() { - let test_dir = - Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite_all"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::OverwriteAll; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(16, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - assert!(compare_dir(&dir.0, &out)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_skip() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::Skip; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(2, count_exist_files); - - assert_eq!(0, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - assert!(!compare_dir(&dir.0, &out)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_skip_all() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip_all"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::SkipAll; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(0, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - assert!(!compare_dir(&dir.0, &out)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_retry() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_retry"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - if count_exist_files == 3 || count_exist_files == 6 { - result = TransitProcessResult::Skip; - } else { - result = TransitProcessResult::Retry; - } - count_exist_files += 1; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(7, count_exist_files); - - assert_eq!(0, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - assert!(!compare_dir(&dir.0, &out)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_inside_work_target_dir_not_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join("it_copy_with_progress_inside_work_target_dir_not_exist"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - - if root_dir2.exists() { - remove(&root_dir2).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(!root_dir2.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(15, result); - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(compare_dir_recursively(&root_dir1, &root_dir2)); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(7, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_copy_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join( - "it_copy_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir", - ); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content22").unwrap(); - fs_extra::file::write_all(&file3, "content333").unwrap(); - - if root_dir2_dir1.exists() { - remove(&root_dir2_dir1).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(!root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(17, result); - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - assert!(compare_dir(&root_dir1, &root_dir2)); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_copy_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join( - "it_copy_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist", - ); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - let old_file1 = root_dir2_dir1.join("file1.txt"); - let old_file2 = root_dir2_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - create_all(&root_dir2_dir1, true).unwrap(); - create_all(&root_dir2_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content22").unwrap(); - fs_extra::file::write_all(&file3, "content333").unwrap(); - fs_extra::file::write_all(&old_file1, "old_content1").unwrap(); - fs_extra::file::write_all(&old_file2, "old_content22").unwrap(); - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - assert!(old_file1.exists()); - assert!(old_file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::Skip - }; - let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(0, result); - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(!files_eq(file1, old_file1)); - assert!(!files_eq(file2, old_file2)); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_copy_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root - .join("it_copy_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - let old_file1 = root_dir2_dir1.join("file1.txt"); - let old_file2 = root_dir2_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - create_all(&root_dir2_dir1, true).unwrap(); - create_all(&root_dir2_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content22").unwrap(); - fs_extra::file::write_all(&file3, "content333").unwrap(); - fs_extra::file::write_all(&old_file1, "old_content1").unwrap(); - fs_extra::file::write_all(&old_file2, "old_content22").unwrap(); - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - assert!(old_file1.exists()); - assert!(old_file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - options.overwrite = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(17, result); - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(compare_dir(&root_dir1, &root_dir2)); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_move_with_progress_exist_user_decide_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::Overwrite; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(2, count_exist_files); - - assert_eq!(16, result); - assert!(!dir.0.exists()); - assert!(dir.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_overwrite_all() { - let test_dir = - Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite_all"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::OverwriteAll; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(16, result); - assert!(!dir.0.exists()); - assert!(dir.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_skip() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::Skip; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(2, count_exist_files); - - assert_eq!(0, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_skip_all() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip_all"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - count_exist_files += 1; - result = TransitProcessResult::SkipAll; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(0, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_retry() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_retry"); - let out = test_dir.join("out"); - let dir = (test_dir.join("dir"), out.join("dir")); - let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt")); - let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt")); - - create_all(&dir.0, true).unwrap(); - create_all(&dir.1, true).unwrap(); - - assert!(&dir.0.exists()); - assert!(&dir.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content7").unwrap(); - fs_extra::file::write_all(&file2.1, "old content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - - let mut options = CopyOptions::new(); - assert!(!compare_dir(&dir.0, &out)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: TransitProcessResult; - match process_info.state { - TransitState::Exists => { - if count_exist_files == 3 || count_exist_files == 6 { - result = TransitProcessResult::Skip; - } else { - result = TransitProcessResult::Retry; - } - count_exist_files += 1; - tx.send(process_info).unwrap(); - } - _ => result = TransitProcessResult::Abort, - }; - result - }; - result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap(); - } - assert_eq!(7, count_exist_files); - - assert_eq!(0, result); - assert!(dir.0.exists()); - assert!(dir.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_dir_with_progress_inside_work_target_dir_not_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join("it_move_dir_with_progress_inside_work_target_dir_not_exist"); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content").unwrap(); - fs_extra::file::write_all(&file2, "content2").unwrap(); - - if root_dir2.exists() { - remove(&root_dir2).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(!root_dir2.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(15, result); - assert!(!root_dir1.exists()); - let root_dir2_sub = root_dir2.join("sub"); - let root_dir2_file1 = root_dir2.join("file1.txt"); - let root_dir2_sub_file2 = root_dir2_sub.join("file2.txt"); - assert!(root_dir2.exists()); - assert!(root_dir2_sub.exists()); - assert!(root_dir2_file1.exists()); - assert!(root_dir2_sub_file2.exists()); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(7, process_info.file_total_bytes); - assert_eq!(15, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_move_dir_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join( - "it_move_dir_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir", - ); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content22").unwrap(); - fs_extra::file::write_all(&file3, "content333").unwrap(); - - if root_dir2_dir1.exists() { - remove(&root_dir2_dir1).unwrap(); - } - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(!root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(17, result); - assert!(!root_dir1.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir3.exists()); - let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt"); - let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt"); - assert!(root_dir2_dir1_file1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir1_sub_file2.exists()); - assert!(root_dir2_dir3_file3.exists()); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_move_dir_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join( - "it_move_dir_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist", - ); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - let old_file1 = root_dir2_dir1.join("file1.txt"); - let old_file2 = root_dir2_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - create_all(&root_dir2_dir1, true).unwrap(); - create_all(&root_dir2_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content22").unwrap(); - fs_extra::file::write_all(&file3, "content333").unwrap(); - fs_extra::file::write_all(&old_file1, "old_content1").unwrap(); - fs_extra::file::write_all(&old_file2, "old_content22").unwrap(); - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - assert!(old_file1.exists()); - assert!(old_file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::Skip - }; - let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(0, result); - - assert!(root_dir1.exists()); - assert!(file1.exists()); - assert!(root_dir1_sub.exists()); - assert!(file2.exists()); - - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt"); - let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt"); - let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt"); - assert!(root_dir2_dir1_file1.exists()); - assert!(root_dir2_dir1_sub_file2.exists()); - assert!(root_dir2_dir3_file3.exists()); - assert!(!files_eq(file1, old_file1)); - assert!(!files_eq(file2, old_file2)); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_move_dir_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist() { - let path_root = Path::new(TEST_FOLDER); - let root = path_root.join( - "it_move_dir_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist", - ); - let root_dir1 = root.join("dir1"); - let root_dir1_sub = root_dir1.join("sub"); - let root_dir2 = root.join("dir2"); - let root_dir2_dir1 = root_dir2.join("dir1"); - let root_dir2_dir1_sub = root_dir2_dir1.join("sub"); - let root_dir2_dir3 = root_dir2.join("dir3"); - let file1 = root_dir1.join("file1.txt"); - let file2 = root_dir1_sub.join("file2.txt"); - let file3 = root_dir2_dir3.join("file3.txt"); - let old_file1 = root_dir2_dir1.join("file1.txt"); - let old_file2 = root_dir2_dir1_sub.join("file2.txt"); - - create_all(&root_dir1_sub, true).unwrap(); - create_all(&root_dir2_dir3, true).unwrap(); - create_all(&root_dir2_dir1, true).unwrap(); - create_all(&root_dir2_dir1_sub, true).unwrap(); - fs_extra::file::write_all(&file1, "content1").unwrap(); - fs_extra::file::write_all(&file2, "content22").unwrap(); - fs_extra::file::write_all(&file3, "content333").unwrap(); - fs_extra::file::write_all(&old_file1, "old_content1").unwrap(); - fs_extra::file::write_all(&old_file2, "old_content22").unwrap(); - - assert!(root_dir1.exists()); - assert!(root_dir1_sub.exists()); - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - assert!(old_file1.exists()); - assert!(old_file2.exists()); - - let mut options = CopyOptions::new(); - options.copy_inside = true; - options.overwrite = true; - - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap(); - - assert_eq!(17, result); - - assert!(!root_dir1.exists()); - - assert!(root_dir2.exists()); - assert!(root_dir2_dir1.exists()); - assert!(root_dir2_dir1_sub.exists()); - assert!(root_dir2_dir3.exists()); - let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt"); - let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt"); - let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt"); - assert!(root_dir2_dir1_file1.exists()); - assert!(root_dir2_dir1_sub_file2.exists()); - assert!(root_dir2_dir3_file3.exists()); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(17, process_info.total_bytes); - } else { - panic!("Unknow file name!"); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} -#[test] -fn it_move_with_progress_content_only_option() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_content_only_option"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.clone()); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - - create_all(&d_level_1.0, true).unwrap(); - create_all(&d_level_2.0, true).unwrap(); - create_all(&d_level_3.0, true).unwrap(); - create_all(&path_to, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - - let mut options = CopyOptions::new(); - options.content_only = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - TransitProcessResult::ContinueOrAbort - }; - - let result = move_dir_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap(); - - assert_eq!(24, result); - - assert!(!d_level_1.0.exists()); - assert!(!d_level_2.0.exists()); - assert!(!d_level_3.0.exists()); - - assert!(d_level_1.1.exists()); - assert!(d_level_2.1.exists()); - assert!(d_level_3.1.exists()); - - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} diff --git a/vendor/fs_extra/tests/file.rs b/vendor/fs_extra/tests/file.rs deleted file mode 100644 index c7fdb36f82..0000000000 --- a/vendor/fs_extra/tests/file.rs +++ /dev/null @@ -1,1036 +0,0 @@ -// use std::io::{ErrorKind, Result}; -use std::path::{Path, PathBuf}; -use std::thread; -use std::sync::mpsc; - -extern crate fs_extra; -use fs_extra::file::*; -use fs_extra::error::*; - -const TEST_FOLDER: &'static str = "./tests/temp/file"; - -fn files_eq(file1: P, file2: Q) -> Result -where - P: AsRef, - Q: AsRef, -{ - let content1 = read_to_string(file1)?; - let content2 = read_to_string(file2)?; - Ok(content1 == content2) -} - -#[test] -fn it_read_and_write_work() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_read_and_write_work"); - test_file.push("test.txt"); - fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap(); - let content1 = "test_1"; - let content2 = "test_2"; - write_all(&test_file, &content1).unwrap(); - assert!(test_file.exists()); - let read1 = read_to_string(&test_file).unwrap(); - assert_eq!(content1, read1); - write_all(&test_file, &content2).unwrap(); - let read2 = read_to_string(&test_file).unwrap(); - assert_eq!(content2, read2); -} - -#[test] -fn it_read_not_exist_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_read_not_exist_file"); - test_file.push("test.txt"); - fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap(); - assert!(!test_file.exists()); - match read_to_string(&test_file) { - Ok(_) => panic!("should be error"), - Err(err) => match err.kind { - ErrorKind::NotFound => {} - _ => panic!("wrong error"), - }, - } -} - -#[test] -fn it_read_not_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_read_not_file"); - fs_extra::dir::create_all(&test_file, true).unwrap(); - match read_to_string(&test_file) { - Ok(_) => panic!("should be error"), - Err(err) => match err.kind { - ErrorKind::InvalidFile => {} - _ => panic!("wrong error"), - }, - } -} - -#[test] -fn it_write_not_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_write_not_file"); - test_file.push("test.txt"); - fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap(); - assert!(!test_file.exists()); - test_file.pop(); - match write_all(test_file, "content") { - Ok(_) => panic!("should be error"), - Err(err) => match err.kind { - ErrorKind::InvalidFile => {} - _ => panic!("wrong error"), - }, - } -} - -#[test] -fn it_remove_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_remove_file"); - test_file.push("test.txt"); - fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap(); - write_all(&test_file, "test").unwrap(); - assert!(test_file.exists()); - remove(&test_file).unwrap(); - assert!(!test_file.exists()); -} - -#[test] -fn it_copy_work() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_work"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - let options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(test_file_out.exists()); - assert_eq!(test_file.file_name(), test_file_out.file_name()); - assert!(files_eq(test_file, test_file_out).unwrap()); -} - -#[test] -fn it_copy_not_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_work"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - test_file.pop(); - let options = CopyOptions::new(); - - match copy(&test_file, &test_file_out, &options) { - Err(err) => match err.kind { - ErrorKind::InvalidFile => { - let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap()); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_copy_source_not_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_source_not_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test1.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - assert!(!test_file.exists()); - let options = CopyOptions::new(); - match copy(&test_file, test_file_out, &options) { - Ok(_) => panic!("should be error"), - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!( - "Path \"{}\" does not exist or you don't have \ - access!", - test_file.to_str().unwrap() - ); - assert_eq!(wrong_path, err.to_string()); - () - } - _ => panic!("wrong error"), - }, - } -} - -#[test] -fn it_copy_exist_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_exist_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - write_all(&test_file, "test_data2").unwrap(); - match copy(&test_file, &test_file_out, &options) { - Ok(_) => { - assert!(test_file.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_copy_exist_not_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_exist_not_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.overwrite = false; - write_all(&test_file, "test_data2").unwrap(); - match copy(&test_file, &test_file_out, &options) { - Ok(_) => panic!("should be error"), - Err(err) => { - let file_path = format!("Path \"{}\" is exist", test_file_out.to_str().unwrap()); - assert_eq!(file_path, err.to_string()); - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - } -} - -#[test] -fn it_copy_exist_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_exist_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - match copy(&test_file, &test_file_out, &options) { - Ok(_) => { - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - Err(_) => panic!("should be error"), - } -} - -#[test] -fn it_copy_exist_overwrite_and_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_exist_overwrite_and_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - match copy(&test_file, &test_file_out, &options) { - Ok(_) => { - assert!(test_file.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_copy_with_progress_work() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_with_progress_work"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - let mut options = CopyOptions::new(); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - }; - copy_with_progress(&test_file, &test_file_out, &options, func_test).unwrap(); - assert!(test_file.exists()); - assert!(test_file_out.exists()); - assert_eq!(test_file.file_name(), test_file_out.file_name()); - assert!(files_eq(test_file, test_file_out).unwrap()); - }); - for i in 1..10 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i, process_info.copied_bytes); - assert_eq!(9, process_info.total_bytes); - } -} - -#[test] -fn it_copy_progress_not_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_progress_not_file"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - test_file.pop(); - let options = CopyOptions::new(); - let func_test = |process_info: TransitProcess| println!("{}", process_info.total_bytes); - - match copy_with_progress(&test_file, &test_file_out, &options, func_test) { - Err(err) => match err.kind { - ErrorKind::InvalidFile => { - let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap()); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_copy_with_progress_work_dif_buf_size() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_with_progress_work_dif_buf_size"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data_").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - let mut options = CopyOptions::new(); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - }; - copy_with_progress(&test_file, &test_file_out, &options, func_test).unwrap(); - assert!(test_file.exists()); - assert!(test_file_out.exists()); - assert_eq!(test_file.file_name(), test_file_out.file_name()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - - let mut options = CopyOptions::new(); - options.buffer_size = 2; - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - }; - copy_with_progress(&test_file, &test_file_out, &options, func_test).unwrap(); - }); - for i in 1..6 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2, process_info.copied_bytes); - assert_eq!(10, process_info.total_bytes); - } - }); - for i in 1..11 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i, process_info.copied_bytes); - assert_eq!(10, process_info.total_bytes); - } -} - -#[test] -fn it_copy_with_progress_source_not_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_with_progress_source_not_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test1.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - assert!(!test_file.exists()); - let options = CopyOptions::new(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match copy_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => panic!("should be error"), - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!( - "Path \"{}\" does not exist or you don't have \ - access!", - test_file.to_str().unwrap() - ); - - assert_eq!(wrong_path, err.to_string()); - () - } - _ => panic!("wrong error"), - }, - } -} - -#[test] -fn it_copy_with_progress_exist_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_with_progress_exist_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match copy_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => { - assert!(test_file.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_copy_with_progress_exist_not_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_with_progress_exist_not_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.overwrite = false; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match copy_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => panic!("should be error"), - Err(err) => { - let file_path = format!("Path \"{}\" is exist", test_file_out.to_str().unwrap()); - - assert_eq!(file_path, err.to_string()); - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - } -} - -#[test] -fn it_copy_with_progress_exist_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_with_progress_exist_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match copy_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => { - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - Err(_) => panic!("should be error"), - } -} - -#[test] -fn it_copy_with_progress_exist_overwrite_and_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_copy_with_progress_exist_overwrite_and_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match copy_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => { - assert!(test_file.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_move_work() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_work"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - let options = CopyOptions::new(); - let old_name = test_file.file_name(); - let old_content = read_to_string(&test_file).unwrap(); - move_file(&test_file, &test_file_out, &options).unwrap(); - assert!(!test_file.exists()); - assert!(test_file_out.exists()); - assert_eq!(old_name, test_file_out.file_name()); - let new_content = read_to_string(&test_file_out).unwrap(); - assert_eq!(old_content, new_content); -} - -#[test] -fn it_move_not_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_work"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - test_file.pop(); - let options = CopyOptions::new(); - - match move_file(&test_file, &test_file_out, &options) { - Err(err) => match err.kind { - ErrorKind::InvalidFile => { - let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap()); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_move_source_not_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_source_not_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test1.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - assert!(!test_file.exists()); - let options = CopyOptions::new(); - match move_file(&test_file, &test_file_out, &options) { - Ok(_) => panic!("should be error"), - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!( - "Path \"{}\" does not exist or you don't have \ - access!", - test_file.to_str().unwrap() - ); - - assert_eq!(wrong_path, err.to_string()); - () - } - _ => panic!("wrong error"), - }, - } -} - -#[test] -fn it_move_exist_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_exist_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - write_all(&test_file, "test_data2").unwrap(); - match move_file(&test_file, &test_file_out, &options) { - Ok(_) => { - assert!(!test_file.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_move_exist_not_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_exist_not_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.overwrite = false; - write_all(&test_file, "test_data2").unwrap(); - match move_file(&test_file, &test_file_out, &options) { - Ok(_) => panic!("should be error"), - Err(err) => { - let file_path = format!("Path \"{}\" is exist", test_file_out.to_str().unwrap()); - - assert_eq!(file_path, err.to_string()); - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - } -} - -#[test] -fn it_move_exist_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_exist_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - match move_file(&test_file, &test_file_out, &options) { - Ok(_) => { - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - Err(_) => panic!("should be error"), - } -} - -#[test] -fn it_move_exist_overwrite_and_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_exist_overwrite_and_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - match move_file(&test_file, &test_file_out, &options) { - Ok(_) => { - assert!(!test_file.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_move_with_progress_work() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_with_progress_work"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - let mut options = CopyOptions::new(); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - thread::spawn(move || { - let old_name = test_file.file_name(); - let old_content = read_to_string(&test_file).unwrap(); - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - }; - move_file_with_progress(&test_file, &test_file_out, &options, func_test).unwrap(); - assert!(!test_file.exists()); - assert!(test_file_out.exists()); - assert_eq!(old_name, test_file_out.file_name()); - let new_content = read_to_string(&test_file_out).unwrap(); - assert_eq!(old_content, new_content); - }); - for i in 1..10 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i, process_info.copied_bytes); - assert_eq!(9, process_info.total_bytes); - } -} - -#[test] -fn it_move_progress_not_file() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_progress_not_file"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - test_file.pop(); - let options = CopyOptions::new(); - let func_test = |process_info: TransitProcess| println!("{}", process_info.total_bytes); - - match move_file_with_progress(&test_file, &test_file_out, &options, func_test) { - Err(err) => match err.kind { - ErrorKind::InvalidFile => { - let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap()); - assert_eq!(wrong_path, err.to_string()); - } - _ => { - panic!("wrong error"); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_move_with_progress_work_dif_buf_size() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_with_progress_work_dif_buf_size"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data_").unwrap(); - assert!(test_file.exists()); - assert!(!test_file_out.exists()); - let mut options = CopyOptions::new(); - options.buffer_size = 2; - let (tx, rx) = mpsc::channel(); - thread::spawn(move || { - let old_name = test_file.file_name(); - let old_content = read_to_string(&test_file).unwrap(); - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - }; - move_file_with_progress(&test_file, &test_file_out, &options, func_test).unwrap(); - assert!(!test_file.exists()); - assert!(test_file_out.exists()); - assert_eq!(old_name, test_file_out.file_name()); - let new_content = read_to_string(&test_file_out).unwrap(); - assert_eq!(old_content, new_content); - }); - for i in 1..6 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2, process_info.copied_bytes); - assert_eq!(10, process_info.total_bytes); - } -} - -#[test] -fn it_move_with_progress_source_not_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_with_progress_source_not_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test1.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - assert!(!test_file.exists()); - let options = CopyOptions::new(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match move_file_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => panic!("should be error"), - Err(err) => match err.kind { - ErrorKind::NotFound => { - let wrong_path = format!( - "Path \"{}\" does not exist or you don't have \ - access!", - test_file.to_str().unwrap() - ); - - assert_eq!(wrong_path, err.to_string()); - () - } - _ => panic!("wrong error"), - }, - } -} - -#[test] -fn it_move_with_progress_exist_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_with_progress_exist_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match move_file_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => { - assert!(!test_file.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} - -#[test] -fn it_move_with_progress_exist_not_overwrite() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_with_progress_exist_not_overwrite"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.overwrite = false; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match move_file_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => panic!("should be error"), - Err(err) => { - let file_path = format!("Path \"{}\" is exist", test_file_out.to_str().unwrap()); - - assert_eq!(file_path, err.to_string()); - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - } -} - -#[test] -fn it_move_with_progress_exist_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_with_progress_exist_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match move_file_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => { - assert!(!files_eq(test_file, test_file_out).unwrap()); - () - } - Err(_) => panic!("should be error"), - } -} - -#[test] -fn it_move_with_progress_exist_overwrite_and_skip_exist() { - let mut test_file = PathBuf::from(TEST_FOLDER); - test_file.push("it_move_with_progress_exist_overwrite_and_skip_exist"); - let mut test_file_out = test_file.clone(); - test_file.push("test.txt"); - test_file_out.push("out"); - test_file_out.push("test.txt"); - fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap(); - fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap(); - - write_all(&test_file, "test_data").unwrap(); - let mut options = CopyOptions::new(); - copy(&test_file, &test_file_out, &options).unwrap(); - assert!(test_file.exists()); - assert!(files_eq(&test_file, &test_file_out).unwrap()); - options.overwrite = true; - options.skip_exist = true; - write_all(&test_file, "test_data2").unwrap(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - }; - match move_file_with_progress(&test_file, &test_file_out, &options, func_test) { - Ok(_) => { - assert!(!test_file.exists()); - assert!(test_file_out.exists()); - assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2"); - () - } - Err(err) => panic!(err.to_string()), - } -} diff --git a/vendor/fs_extra/tests/lib.rs b/vendor/fs_extra/tests/lib.rs deleted file mode 100644 index c11e2fa415..0000000000 --- a/vendor/fs_extra/tests/lib.rs +++ /dev/null @@ -1,3861 +0,0 @@ -use std::fs::read_dir; -use std::path::Path; -use std::sync::mpsc::{self, TryRecvError}; -use std::thread; - -extern crate fs_extra; -use fs_extra::error::*; -use fs_extra::*; - -fn files_eq(file1: P, file2: Q) -> bool -where - P: AsRef, - Q: AsRef, -{ - let content1 = fs_extra::file::read_to_string(file1).unwrap(); - let content2 = fs_extra::file::read_to_string(file2).unwrap(); - content1 == content2 -} - -fn compare_dir(path_from: P, path_to: Q) -> bool -where - P: AsRef, - Q: AsRef, -{ - let mut path_to = path_to.as_ref().to_path_buf(); - match path_from.as_ref().components().last() { - None => panic!("Invalid folder from"), - Some(dir_name) => { - path_to.push(dir_name.as_os_str()); - if !path_to.exists() { - return false; - } - } - } - - for entry in read_dir(&path_from).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - if path.is_dir() { - if !compare_dir(path, &path_to) { - return false; - } - } else { - let mut path_to = path_to.to_path_buf(); - match path.file_name() { - None => panic!("No file name"), - Some(file_name) => { - path_to.push(file_name); - if !path_to.exists() { - return false; - } else if !files_eq(&path, path_to.clone()) { - return false; - } - } - } - } - } - - true -} - -const TEST_FOLDER: &'static str = "./tests/temp/lib"; - -#[test] -fn it_copy_work() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_work"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(!sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let options = dir::CopyOptions::new(); - let result = copy_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(40, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); -} - -#[test] -fn it_copy_source_not_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_source_not_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - assert!(!dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(!dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(!sub.0.exists()); - assert!(!sub.1.exists()); - - assert!(!file1.0.exists()); - assert!(!file1.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - - let options = dir::CopyOptions::new(); - match copy_items(&from_paths, &path_to, &options) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::NotFound => {} - _ => {} - }, - }; -} - -#[test] -fn it_copy_exist_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - let result = copy_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(40, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); -} - -#[test] -fn it_copy_exist_not_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_not_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let options = dir::CopyOptions::new(); - match copy_items(&from_paths, &path_to, &options) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::AlreadyExists => {} - _ => panic!(format!("{}", err.to_string())), - }, - }; -} - -#[test] -fn it_copy_exist_skip() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_skip"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.skip_exist = true; - let result = copy_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(16, result); - assert!(!compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); -} - -#[test] -fn it_copy_exist_overwrite_and_skip_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_overwrite_and_skip_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - options.skip_exist = true; - let result = copy_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(40, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); -} - -#[test] -fn it_copy_using_first_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_first_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1")); - let d2_level_2 = ( - d_level_1.0.join("d2_level_2"), - d_level_1.1.join("d2_level_2"), - ); - let d2_level_3 = ( - d_level_2.0.join("d2_level_3"), - d_level_2.1.join("d2_level_3"), - ); - let d2_level_4 = ( - d_level_3.0.join("d2_level_4"), - d_level_3.1.join("d2_level_4"), - ); - let d2_level_5 = ( - d_level_4.0.join("d2_level_5"), - d_level_4.1.join("d2_level_5"), - ); - - let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - let file21 = ( - d2_level_1.0.join("file21.txt"), - d2_level_1.1.join("file21.txt"), - ); - let file22 = ( - d2_level_2.0.join("file22.txt"), - d2_level_2.1.join("file22.txt"), - ); - let file23 = ( - d2_level_3.0.join("file23.txt"), - d2_level_3.1.join("file23.txt"), - ); - let file24 = ( - d2_level_4.0.join("file24.txt"), - d2_level_4.1.join("file24.txt"), - ); - let file25 = ( - d2_level_5.0.join("file25.txt"), - d2_level_5.1.join("file25.txt"), - ); - - let file31 = ( - d3_level_1.0.join("file31.txt"), - d3_level_1.1.join("file31.txt"), - ); - - dir::create_all(&d_level_1.0, true).unwrap(); - dir::create_all(&d_level_2.0, true).unwrap(); - dir::create_all(&d_level_3.0, true).unwrap(); - dir::create_all(&d_level_4.0, true).unwrap(); - dir::create_all(&d_level_5.0, true).unwrap(); - dir::create_all(&path_to, true).unwrap(); - - dir::create_all(&d2_level_1.0, true).unwrap(); - dir::create_all(&d2_level_2.0, true).unwrap(); - dir::create_all(&d2_level_3.0, true).unwrap(); - dir::create_all(&d2_level_4.0, true).unwrap(); - dir::create_all(&d2_level_5.0, true).unwrap(); - - dir::create_all(&d3_level_1.0, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d2_level_1.0.exists()); - assert!(d2_level_2.0.exists()); - assert!(d2_level_3.0.exists()); - assert!(d2_level_4.0.exists()); - assert!(d2_level_5.0.exists()); - - assert!(d3_level_1.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - assert!(!d2_level_1.1.exists()); - assert!(!d2_level_2.1.exists()); - assert!(!d2_level_3.1.exists()); - assert!(!d2_level_4.1.exists()); - assert!(!d2_level_5.1.exists()); - - assert!(!d3_level_1.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file21.0, "2content1").unwrap(); - fs_extra::file::write_all(&file22.0, "2content2").unwrap(); - fs_extra::file::write_all(&file23.0, "2content3").unwrap(); - fs_extra::file::write_all(&file24.0, "2content4").unwrap(); - fs_extra::file::write_all(&file25.0, "2content5").unwrap(); - - fs_extra::file::write_all(&file31.0, "3content1").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(!file21.1.exists()); - assert!(!file22.1.exists()); - assert!(!file23.1.exists()); - assert!(!file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(!file31.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(d_level_1.0.as_path()); - from_paths.push(d2_level_1.0.as_path()); - from_paths.push(d3_level_1.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.depth = 1; - let result = copy_items(&from_paths, path_to, &options).unwrap(); - - assert_eq!(26, result); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(file21.1.exists()); - assert!(!file22.1.exists()); - assert!(!file23.1.exists()); - assert!(!file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(file31.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file21.0, &file21.1)); - assert!(files_eq(&file31.0, &file31.1)); -} - -#[test] -fn it_copy_using_four_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_four_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1")); - let d2_level_2 = ( - d_level_1.0.join("d2_level_2"), - d_level_1.1.join("d2_level_2"), - ); - let d2_level_3 = ( - d_level_2.0.join("d2_level_3"), - d_level_2.1.join("d2_level_3"), - ); - let d2_level_4 = ( - d_level_3.0.join("d2_level_4"), - d_level_3.1.join("d2_level_4"), - ); - let d2_level_5 = ( - d_level_4.0.join("d2_level_5"), - d_level_4.1.join("d2_level_5"), - ); - - let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - let file21 = ( - d2_level_1.0.join("file21.txt"), - d2_level_1.1.join("file21.txt"), - ); - let file22 = ( - d2_level_2.0.join("file22.txt"), - d2_level_2.1.join("file22.txt"), - ); - let file23 = ( - d2_level_3.0.join("file23.txt"), - d2_level_3.1.join("file23.txt"), - ); - let file24 = ( - d2_level_4.0.join("file24.txt"), - d2_level_4.1.join("file24.txt"), - ); - let file25 = ( - d2_level_5.0.join("file25.txt"), - d2_level_5.1.join("file25.txt"), - ); - - let file31 = ( - d3_level_1.0.join("file31.txt"), - d3_level_1.1.join("file31.txt"), - ); - - dir::create_all(&d_level_1.0, true).unwrap(); - dir::create_all(&d_level_2.0, true).unwrap(); - dir::create_all(&d_level_3.0, true).unwrap(); - dir::create_all(&d_level_4.0, true).unwrap(); - dir::create_all(&d_level_5.0, true).unwrap(); - dir::create_all(&path_to, true).unwrap(); - - dir::create_all(&d2_level_1.0, true).unwrap(); - dir::create_all(&d2_level_2.0, true).unwrap(); - dir::create_all(&d2_level_3.0, true).unwrap(); - dir::create_all(&d2_level_4.0, true).unwrap(); - dir::create_all(&d2_level_5.0, true).unwrap(); - - dir::create_all(&d3_level_1.0, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d2_level_1.0.exists()); - assert!(d2_level_2.0.exists()); - assert!(d2_level_3.0.exists()); - assert!(d2_level_4.0.exists()); - assert!(d2_level_5.0.exists()); - - assert!(d3_level_1.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - assert!(!d2_level_1.1.exists()); - assert!(!d2_level_2.1.exists()); - assert!(!d2_level_3.1.exists()); - assert!(!d2_level_4.1.exists()); - assert!(!d2_level_5.1.exists()); - - assert!(!d3_level_1.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file21.0, "2content1").unwrap(); - fs_extra::file::write_all(&file22.0, "2content2").unwrap(); - fs_extra::file::write_all(&file23.0, "2content3").unwrap(); - fs_extra::file::write_all(&file24.0, "2content4").unwrap(); - fs_extra::file::write_all(&file25.0, "2content5").unwrap(); - - fs_extra::file::write_all(&file31.0, "3content1").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(!file21.1.exists()); - assert!(!file22.1.exists()); - assert!(!file23.1.exists()); - assert!(!file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(!file31.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(d_level_1.0.as_path()); - from_paths.push(d2_level_1.0.as_path()); - from_paths.push(d3_level_1.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.depth = 4; - let result = copy_items(&from_paths, path_to, &options).unwrap(); - - assert_eq!(77, result); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(file21.1.exists()); - assert!(file22.1.exists()); - assert!(file23.1.exists()); - assert!(file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(file31.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file21.0, &file21.1)); - assert!(files_eq(&file31.0, &file31.1)); -} -#[test] - -fn it_copy_content_only_opton() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_content_only_opton"); - let path_to = test_dir.join("out"); - - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - let mut options = dir::CopyOptions::new(); - options.content_only = true; - match copy_items(&vec![&file1.0], &file1.1, &options) { - Err(err) => match err.kind { - ErrorKind::Other => { - assert_eq!(1, 1); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_copy_progress_work() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_progress_work"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(!sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content22").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let options = dir::CopyOptions::new(); - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(41, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(41, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(41, process_info.total_bytes); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_copy_with_progress_work_dif_buf_size() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_work_dif_buf_size"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(!sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(file1.0.as_path().to_str().unwrap().to_string()); - from_paths.push(file2.0.as_path().to_str().unwrap().to_string()); - from_paths.push(dir1.0.as_path().to_str().unwrap().to_string()); - from_paths.push(dir2.0.as_path().to_str().unwrap().to_string()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - - let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(40, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - - let mut options = dir::CopyOptions::new(); - options.buffer_size = 2; - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - let result = - copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(40, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - }).join(); - for i in 1..5 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2, process_info.file_bytes_copied); - assert_eq!(i * 2, process_info.copied_bytes); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(40, process_info.total_bytes); - } - for i in 1..5 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i * 2 + 8, process_info.copied_bytes); - assert_eq!(i * 2, process_info.file_bytes_copied); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(40, process_info.total_bytes); - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - }).join(); - - for i in 1..9 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i, process_info.file_bytes_copied); - assert_eq!(i, process_info.copied_bytes); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(40, process_info.total_bytes); - } - for i in 1..9 { - let process_info: TransitProcess = rx.recv().unwrap(); - assert_eq!(i + 8, process_info.copied_bytes); - assert_eq!(i, process_info.file_bytes_copied); - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(40, process_info.total_bytes); - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_copy_with_progress_source_not_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_source_not_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - assert!(!dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(!dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(!sub.0.exists()); - assert!(!sub.1.exists()); - - assert!(!file1.0.exists()); - assert!(!file1.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - dir::TransitProcessResult::ContinueOrAbort - }; - - let options = dir::CopyOptions::new(); - match copy_items_with_progress(&from_paths, &path_to, &options, func_test) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::NotFound => {} - _ => {} - }, - }; -} - -#[test] -fn it_copy_with_progress_exist_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - - let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(40, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_with_progress_exist_not_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_not_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let options = dir::CopyOptions::new(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - dir::TransitProcessResult::ContinueOrAbort - }; - - match copy_items_with_progress(&from_paths, &path_to, &options, func_test) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::AlreadyExists => {} - _ => panic!(format!("{}", err.to_string())), - }, - }; -} - -#[test] -fn it_copy_with_progress_exist_skip_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_skip_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.skip_exist = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - - let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(16, result); - assert!(!compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_with_progress_exist_overwrite_and_skip_exist() { - let test_dir = - Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_overwrite_and_skip_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - options.skip_exist = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - - let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(40, result); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_with_progress_using_first_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_first_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1")); - let d2_level_2 = ( - d_level_1.0.join("d2_level_2"), - d_level_1.1.join("d2_level_2"), - ); - let d2_level_3 = ( - d_level_2.0.join("d2_level_3"), - d_level_2.1.join("d2_level_3"), - ); - let d2_level_4 = ( - d_level_3.0.join("d2_level_4"), - d_level_3.1.join("d2_level_4"), - ); - let d2_level_5 = ( - d_level_4.0.join("d2_level_5"), - d_level_4.1.join("d2_level_5"), - ); - - let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - let file21 = ( - d2_level_1.0.join("file21.txt"), - d2_level_1.1.join("file21.txt"), - ); - let file22 = ( - d2_level_2.0.join("file22.txt"), - d2_level_2.1.join("file22.txt"), - ); - let file23 = ( - d2_level_3.0.join("file23.txt"), - d2_level_3.1.join("file23.txt"), - ); - let file24 = ( - d2_level_4.0.join("file24.txt"), - d2_level_4.1.join("file24.txt"), - ); - let file25 = ( - d2_level_5.0.join("file25.txt"), - d2_level_5.1.join("file25.txt"), - ); - - let file31 = ( - d3_level_1.0.join("file31.txt"), - d3_level_1.1.join("file31.txt"), - ); - - dir::create_all(&d_level_1.0, true).unwrap(); - dir::create_all(&d_level_2.0, true).unwrap(); - dir::create_all(&d_level_3.0, true).unwrap(); - dir::create_all(&d_level_4.0, true).unwrap(); - dir::create_all(&d_level_5.0, true).unwrap(); - dir::create_all(&path_to, true).unwrap(); - - dir::create_all(&d2_level_1.0, true).unwrap(); - dir::create_all(&d2_level_2.0, true).unwrap(); - dir::create_all(&d2_level_3.0, true).unwrap(); - dir::create_all(&d2_level_4.0, true).unwrap(); - dir::create_all(&d2_level_5.0, true).unwrap(); - - dir::create_all(&d3_level_1.0, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d2_level_1.0.exists()); - assert!(d2_level_2.0.exists()); - assert!(d2_level_3.0.exists()); - assert!(d2_level_4.0.exists()); - assert!(d2_level_5.0.exists()); - - assert!(d3_level_1.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - assert!(!d2_level_1.1.exists()); - assert!(!d2_level_2.1.exists()); - assert!(!d2_level_3.1.exists()); - assert!(!d2_level_4.1.exists()); - assert!(!d2_level_5.1.exists()); - - assert!(!d3_level_1.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file21.0, "2content1").unwrap(); - fs_extra::file::write_all(&file22.0, "2content2").unwrap(); - fs_extra::file::write_all(&file23.0, "2content3").unwrap(); - fs_extra::file::write_all(&file24.0, "2content4").unwrap(); - fs_extra::file::write_all(&file25.0, "2content5").unwrap(); - - fs_extra::file::write_all(&file31.0, "3content1").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(!file21.1.exists()); - assert!(!file22.1.exists()); - assert!(!file23.1.exists()); - assert!(!file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(!file31.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.depth = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(d_level_1.0.as_path()); - from_paths.push(d2_level_1.0.as_path()); - from_paths.push(d3_level_1.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - - let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(26, result); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(file21.1.exists()); - assert!(!file22.1.exists()); - assert!(!file23.1.exists()); - assert!(!file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(file31.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file21.0, &file21.1)); - assert!(files_eq(&file31.0, &file31.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_with_progress_using_four_levels() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_four_levels"); - let path_to = test_dir.join("out"); - let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1")); - let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2")); - let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3")); - let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4")); - let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5")); - - let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1")); - let d2_level_2 = ( - d_level_1.0.join("d2_level_2"), - d_level_1.1.join("d2_level_2"), - ); - let d2_level_3 = ( - d_level_2.0.join("d2_level_3"), - d_level_2.1.join("d2_level_3"), - ); - let d2_level_4 = ( - d_level_3.0.join("d2_level_4"), - d_level_3.1.join("d2_level_4"), - ); - let d2_level_5 = ( - d_level_4.0.join("d2_level_5"), - d_level_4.1.join("d2_level_5"), - ); - - let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1")); - - let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt")); - let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt")); - let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt")); - let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt")); - let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt")); - - let file21 = ( - d2_level_1.0.join("file21.txt"), - d2_level_1.1.join("file21.txt"), - ); - let file22 = ( - d2_level_2.0.join("file22.txt"), - d2_level_2.1.join("file22.txt"), - ); - let file23 = ( - d2_level_3.0.join("file23.txt"), - d2_level_3.1.join("file23.txt"), - ); - let file24 = ( - d2_level_4.0.join("file24.txt"), - d2_level_4.1.join("file24.txt"), - ); - let file25 = ( - d2_level_5.0.join("file25.txt"), - d2_level_5.1.join("file25.txt"), - ); - - let file31 = ( - d3_level_1.0.join("file31.txt"), - d3_level_1.1.join("file31.txt"), - ); - - dir::create_all(&d_level_1.0, true).unwrap(); - dir::create_all(&d_level_2.0, true).unwrap(); - dir::create_all(&d_level_3.0, true).unwrap(); - dir::create_all(&d_level_4.0, true).unwrap(); - dir::create_all(&d_level_5.0, true).unwrap(); - dir::create_all(&path_to, true).unwrap(); - - dir::create_all(&d2_level_1.0, true).unwrap(); - dir::create_all(&d2_level_2.0, true).unwrap(); - dir::create_all(&d2_level_3.0, true).unwrap(); - dir::create_all(&d2_level_4.0, true).unwrap(); - dir::create_all(&d2_level_5.0, true).unwrap(); - - dir::create_all(&d3_level_1.0, true).unwrap(); - - assert!(path_to.exists()); - assert!(d_level_1.0.exists()); - assert!(d_level_2.0.exists()); - assert!(d_level_3.0.exists()); - assert!(d_level_4.0.exists()); - assert!(d_level_5.0.exists()); - - assert!(d2_level_1.0.exists()); - assert!(d2_level_2.0.exists()); - assert!(d2_level_3.0.exists()); - assert!(d2_level_4.0.exists()); - assert!(d2_level_5.0.exists()); - - assert!(d3_level_1.0.exists()); - - assert!(!d_level_1.1.exists()); - assert!(!d_level_2.1.exists()); - assert!(!d_level_3.1.exists()); - assert!(!d_level_4.1.exists()); - assert!(!d_level_5.1.exists()); - - assert!(!d2_level_1.1.exists()); - assert!(!d2_level_2.1.exists()); - assert!(!d2_level_3.1.exists()); - assert!(!d2_level_4.1.exists()); - assert!(!d2_level_5.1.exists()); - - assert!(!d3_level_1.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file21.0, "2content1").unwrap(); - fs_extra::file::write_all(&file22.0, "2content2").unwrap(); - fs_extra::file::write_all(&file23.0, "2content3").unwrap(); - fs_extra::file::write_all(&file24.0, "2content4").unwrap(); - fs_extra::file::write_all(&file25.0, "2content5").unwrap(); - - fs_extra::file::write_all(&file31.0, "3content1").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(!file21.1.exists()); - assert!(!file22.1.exists()); - assert!(!file23.1.exists()); - assert!(!file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(!file31.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.depth = 4; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(d_level_1.0.as_path()); - from_paths.push(d2_level_1.0.as_path()); - from_paths.push(d3_level_1.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - - let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(77, result); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - - assert!(file21.0.exists()); - assert!(file22.0.exists()); - assert!(file23.0.exists()); - assert!(file24.0.exists()); - assert!(file25.0.exists()); - - assert!(file31.0.exists()); - - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - assert!(file21.1.exists()); - assert!(file22.1.exists()); - assert!(file23.1.exists()); - assert!(file24.1.exists()); - assert!(!file25.1.exists()); - - assert!(file31.1.exists()); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file21.0, &file21.1)); - assert!(files_eq(&file31.0, &file31.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_copy_with_progress_content_only_opton() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_content_only_opton"); - let path_to = test_dir.join("out"); - - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - let mut options = dir::CopyOptions::new(); - options.content_only = true; - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - dir::TransitProcessResult::ContinueOrAbort - }; - match copy_items_with_progress(&vec![&file1.0], &file1.1, &options, func_test) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::Other => {} - _ => panic!(format!("wrong error {}", err.to_string())), - }, - }; -} - -#[test] -fn it_move_work() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_work"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(!sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let options = dir::CopyOptions::new(); - let result = move_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(40, result); - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - assert!(!file4.0.exists()); - assert!(!file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); -} - -#[test] -fn it_move_source_not_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_source_not_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - assert!(!dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(!dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(!sub.0.exists()); - assert!(!sub.1.exists()); - - assert!(!file1.0.exists()); - assert!(!file1.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - - let options = dir::CopyOptions::new(); - match move_items(&from_paths, &path_to, &options) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::NotFound => {} - _ => {} - }, - }; -} - -#[test] -fn it_move_exist_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - let result = move_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(40, result); - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - assert!(!file4.0.exists()); - assert!(!file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); -} - -#[test] -fn it_move_exist_not_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_not_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let options = dir::CopyOptions::new(); - match move_items(&from_paths, &path_to, &options) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::AlreadyExists => {} - _ => panic!(format!("{}", err.to_string())), - }, - }; -} - -#[test] -fn it_move_exist_skip() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_skip"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.skip_exist = true; - let result = move_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(16, result); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!file2.0.exists()); - assert!(!files_eq(&file3.0, &file3.1)); - assert!(!files_eq(&file4.0, &file4.1)); - assert!(!file5.0.exists()); -} - -#[test] -fn it_move_exist_overwrite_and_skip_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_overwrite_and_skip_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - options.skip_exist = true; - let result = move_items(&from_paths, &path_to, &options).unwrap(); - - assert_eq!(40, result); - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - assert!(!file4.0.exists()); - assert!(!file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); -} -#[test] -fn it_move_content_only_option() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_content_only_option"); - let path_to = test_dir.join("out"); - - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - let mut options = dir::CopyOptions::new(); - options.content_only = true; - match move_items(&vec![&file1.0], &file1.1, &options) { - Err(err) => match err.kind { - ErrorKind::Other => { - assert_eq!(1, 1); - } - _ => { - panic!(format!("wrong error {}", err.to_string())); - } - }, - Ok(_) => { - panic!("should be error"); - } - } -} - -#[test] -fn it_move_progress_work() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_progress_work"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(!sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content22").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(!file1.1.exists()); - assert!(!file2.1.exists()); - assert!(!file3.1.exists()); - assert!(!file4.1.exists()); - assert!(!file5.1.exists()); - - let options = dir::CopyOptions::new(); - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(41, result); - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - assert!(!file4.0.exists()); - assert!(!file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - }).join(); - - loop { - match rx.try_recv() { - Ok(process_info) => { - if process_info.file_name == "file2.txt" { - assert_eq!(9, process_info.file_total_bytes); - assert_eq!(41, process_info.total_bytes); - } else if process_info.file_name == "file1.txt" { - assert_eq!(8, process_info.file_total_bytes); - assert_eq!(41, process_info.total_bytes); - } - } - Err(TryRecvError::Disconnected) => { - break; - } - Err(TryRecvError::Empty) => {} - } - } - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } -} - -#[test] -fn it_move_with_progress_source_not_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_source_not_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - assert!(!dir1.0.exists()); - assert!(!dir1.1.exists()); - assert!(!dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(!sub.0.exists()); - assert!(!sub.1.exists()); - - assert!(!file1.0.exists()); - assert!(!file1.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - dir::TransitProcessResult::ContinueOrAbort - }; - let options = dir::CopyOptions::new(); - match move_items_with_progress(&from_paths, &path_to, &options, func_test) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::NotFound => {} - _ => {} - }, - }; -} - -#[test] -fn it_move_with_progress_exist_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(40, result); - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - assert!(!file4.0.exists()); - assert!(!file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_move_with_progress_exist_not_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_not_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let options = dir::CopyOptions::new(); - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - dir::TransitProcessResult::ContinueOrAbort - }; - match move_items_with_progress(&from_paths, &path_to, &options, func_test) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::AlreadyExists => {} - _ => panic!(format!("{}", err.to_string())), - }, - }; -} - -#[test] -fn it_move_with_progress_exist_skip_exist() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_skip_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - file::write_all(&file5.1, "old content5").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.skip_exist = true; - options.overwrite = false; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(8, result); - assert!(file1.0.exists()); - assert!(!file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - assert!(!files_eq(&file1.0, &file1.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_move_with_progress_exist_overwrite_and_skip_exist() { - let test_dir = - Path::new(TEST_FOLDER).join("it_move_with_progress_exist_overwrite_and_skip_exist"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - match dir::create_all(&path_to, true) { - Ok(_) => {} - Err(_) => {} - }; - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(!dir2.1.exists()); - assert!(sub.0.exists()); - assert!(sub.1.exists()); - - file::write_all(&file1.0, "content1").unwrap(); - file::write_all(&file2.0, "content2").unwrap(); - file::write_all(&file3.0, "content3").unwrap(); - file::write_all(&file4.0, "content4").unwrap(); - file::write_all(&file5.0, "content5").unwrap(); - - file::write_all(&file1.1, "old content1").unwrap(); - file::write_all(&file3.1, "old content3").unwrap(); - file::write_all(&file4.1, "old content4").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(!file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(!file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - options.overwrite = true; - options.skip_exist = true; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let func_test = |process_info: TransitProcess| { - tx.send(process_info).unwrap(); - dir::TransitProcessResult::ContinueOrAbort - }; - let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - - assert_eq!(40, result); - assert!(!file1.0.exists()); - assert!(!file2.0.exists()); - assert!(!file3.0.exists()); - assert!(!file4.0.exists()); - assert!(!file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - - match rx.recv() { - Err(_) => panic!("Errors should not be!"), - _ => {} - } -} - -#[test] -fn it_move_with_progress_content_only_option() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_content_only_option"); - let path_to = test_dir.join("out"); - - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - - let mut options = dir::CopyOptions::new(); - options.content_only = true; - let func_test = |process_info: TransitProcess| { - println!("{}", process_info.total_bytes); - dir::TransitProcessResult::ContinueOrAbort - }; - match move_items_with_progress(&vec![&file1.0], &file1.1, &options, func_test) { - Ok(_) => panic!("Should be a error!"), - Err(err) => match err.kind { - ErrorKind::Other => {} - _ => panic!(format!("wrong error {}", err.to_string())), - }, - }; -} - -#[test] -fn it_remove_work() { - let test_dir = Path::new(TEST_FOLDER).join("it_remove_work"); - let dir1 = test_dir.join("dir1"); - let dir2 = test_dir.join("dir2"); - let sub = dir1.join("sub"); - let file1 = test_dir.join("file1.txt"); - let file2 = test_dir.join("file2.txt"); - let file3 = dir1.join("file3.txt"); - let file4 = sub.join("file4.txt"); - let file5 = dir2.join("file5.txt"); - - dir::create_all(&dir1, true).unwrap(); - dir::create_all(&dir2, true).unwrap(); - dir::create_all(&sub, true).unwrap(); - - assert!(dir1.exists()); - assert!(dir2.exists()); - assert!(sub.exists()); - - file::write_all(&file1, "content1").unwrap(); - file::write_all(&file2, "content2").unwrap(); - file::write_all(&file3, "content3").unwrap(); - file::write_all(&file4, "content4").unwrap(); - file::write_all(&file5, "content5").unwrap(); - - assert!(file1.exists()); - assert!(file2.exists()); - assert!(file3.exists()); - assert!(file4.exists()); - assert!(file5.exists()); - - let mut from_paths = Vec::new(); - from_paths.push(dir1.as_path()); - from_paths.push(dir2.as_path()); - from_paths.push(file1.as_path()); - from_paths.push(file2.as_path()); - - remove_items(&from_paths).unwrap(); - assert!(!file1.exists()); - assert!(!file2.exists()); - assert!(!file3.exists()); - assert!(!file4.exists()); - assert!(!file5.exists()); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::Overwrite; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(5, count_exist_files); - - assert_eq!(40, result); - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(dir2.1.exists()); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_overwrite_all() { - let test_dir = - Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite_all"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::OverwriteAll; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(40, result); - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(dir2.1.exists()); - assert!(compare_dir(&dir1.0, &path_to)); - assert!(compare_dir(&dir2.0, &path_to)); - assert!(files_eq(&file1.0, &file1.1)); - assert!(files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_skip() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::Skip; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(5, count_exist_files); - - assert_eq!(0, result); - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(dir2.1.exists()); - assert!(!compare_dir(&dir1.0, &path_to)); - assert!(!compare_dir(&dir2.0, &path_to)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_skip_all() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip_all"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::SkipAll; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(0, result); - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(dir2.1.exists()); - assert!(!compare_dir(&dir1.0, &path_to)); - assert!(!compare_dir(&dir2.0, &path_to)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_copy_with_progress_exist_user_decide_retry() { - let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_retry"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - if count_exist_files == 3 || count_exist_files > 6 { - result = dir::TransitProcessResult::Skip; - } else { - result = dir::TransitProcessResult::Retry; - } - - count_exist_files += 1; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(11, count_exist_files); - - assert_eq!(0, result); - assert!(dir1.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.0.exists()); - assert!(dir2.1.exists()); - assert!(!compare_dir(&dir1.0, &path_to)); - assert!(!compare_dir(&dir2.0, &path_to)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_overwrite() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::Overwrite; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(5, count_exist_files); - - assert_eq!(40, result); - assert!(!dir1.0.exists()); - assert!(!dir2.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_overwrite_all() { - let test_dir = - Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite_all"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::OverwriteAll; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(40, result); - assert!(!dir1.0.exists()); - assert!(!dir2.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_skip() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::Skip; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(5, count_exist_files); - - assert_eq!(0, result); - assert!(dir1.0.exists()); - assert!(dir2.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_skip_all() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip_all"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - count_exist_files += 1; - result = dir::TransitProcessResult::SkipAll; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(1, count_exist_files); - - assert_eq!(0, result); - assert!(dir1.0.exists()); - assert!(dir2.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.1.exists()); - assert!(file1.0.exists()); - assert!(file2.0.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} - -#[test] -fn it_move_with_progress_exist_user_decide_retry() { - let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_retry"); - let path_to = test_dir.join("out"); - let dir1 = (test_dir.join("dir1"), path_to.join("dir1")); - let dir2 = (test_dir.join("dir2"), path_to.join("dir2")); - let sub = (dir1.0.join("sub"), dir1.1.join("sub")); - let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt")); - let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt")); - let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt")); - let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt")); - let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt")); - - dir::create_all(&dir1.0, true).unwrap(); - dir::create_all(&dir1.1, true).unwrap(); - dir::create_all(&dir2.0, true).unwrap(); - dir::create_all(&dir2.1, true).unwrap(); - dir::create_all(&sub.0, true).unwrap(); - dir::create_all(&sub.1, true).unwrap(); - - assert!(&dir1.0.exists()); - assert!(&dir1.1.exists()); - assert!(&dir2.0.exists()); - assert!(&dir2.1.exists()); - assert!(&sub.0.exists()); - assert!(&sub.1.exists()); - - fs_extra::file::write_all(&file1.0, "content1").unwrap(); - fs_extra::file::write_all(&file2.0, "content2").unwrap(); - fs_extra::file::write_all(&file3.0, "content3").unwrap(); - fs_extra::file::write_all(&file4.0, "content4").unwrap(); - fs_extra::file::write_all(&file5.0, "content5").unwrap(); - - fs_extra::file::write_all(&file1.1, "old content11").unwrap(); - fs_extra::file::write_all(&file2.1, "old content12").unwrap(); - fs_extra::file::write_all(&file3.1, "old content13").unwrap(); - fs_extra::file::write_all(&file4.1, "old content14").unwrap(); - fs_extra::file::write_all(&file5.1, "old content15").unwrap(); - - assert!(file1.0.exists()); - assert!(file2.0.exists()); - assert!(file3.0.exists()); - assert!(file4.0.exists()); - assert!(file5.0.exists()); - assert!(file1.1.exists()); - assert!(file2.1.exists()); - assert!(file3.1.exists()); - assert!(file4.1.exists()); - assert!(file5.1.exists()); - - let mut options = dir::CopyOptions::new(); - assert!(!compare_dir(&dir1.0, &dir1.1)); - assert!(!compare_dir(&dir2.0, &dir2.1)); - assert!(!files_eq(&file1.0, &file1.1)); - assert!(!files_eq(&file2.0, &file2.1)); - options.buffer_size = 1; - let (tx, rx) = mpsc::channel(); - let result = thread::spawn(move || { - let mut count_exist_files = 0; - let mut from_paths = Vec::new(); - from_paths.push(dir1.0.as_path()); - from_paths.push(dir2.0.as_path()); - from_paths.push(file1.0.as_path()); - from_paths.push(file2.0.as_path()); - - let result: u64; - { - let func_test = |process_info: TransitProcess| { - let result: dir::TransitProcessResult; - match process_info.state { - dir::TransitState::Exists => { - if count_exist_files == 3 || count_exist_files > 6 { - result = dir::TransitProcessResult::Skip; - } else { - result = dir::TransitProcessResult::Retry; - } - - count_exist_files += 1; - tx.send(process_info).unwrap(); - } - _ => result = dir::TransitProcessResult::Abort, - }; - result - }; - - result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap(); - } - assert_eq!(11, count_exist_files); - - assert_eq!(0, result); - assert!(dir1.0.exists()); - assert!(dir2.0.exists()); - assert!(dir1.1.exists()); - assert!(dir2.1.exists()); - }).join(); - - match result { - Ok(_) => {} - Err(err) => panic!(err), - } - rx.try_recv().unwrap(); -} diff --git a/vendor/idna/.cargo-checksum.json b/vendor/idna/.cargo-checksum.json index 8a9c776f2f..01c1655f1b 100644 --- a/vendor/idna/.cargo-checksum.json +++ b/vendor/idna/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"f06264f03f56352df5d6119c3916c611793a76e860f56f479d6541d5472954f0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","benches/all.rs":"e734b9c9092ed66986725f86cfe90f3756cfddb058af308b796ba494f9beefc2","src/IdnaMappingTable.txt":"87d6553a4b86bc49dcade38bf26b745cd81800eb8af295dc3fb99b4729eaea38","src/lib.rs":"d61b2bfcf4265b9a41eedd1de33ab49ea615e3c06df944321b30c57950a85342","src/make_uts46_mapping_table.py":"917055fa841f813de2bcf79cc79b595da3d5551559ee768db8660ab77cb26c34","src/punycode.rs":"dceeb0467197f892d2c777711b3c6647238f52f3976dfca5a8f8957500fd3599","src/uts46.rs":"c3e23fa4e3666ad48a8f79ddcfb64111405d510bb1f2f64baf4158f2331ef58b","src/uts46_mapping_table.rs":"942fff78147c61da942f5f3a7ff4e90f9d7a00a29285733ac3fc3357eb2ed06f","tests/IdnaTestV2.txt":"c6f3778b0545fd150c8063286c7f5adc901e16557eddccc3751213646d07593d","tests/punycode.rs":"e6fb978f48445d1525a6b97351c41c5393a1612a35f85b9a7f45b8794fce9aba","tests/punycode_tests.json":"3d4ac0cf25984c37b9ce197f5df680a0136f728fb8ec82bc76624e42139eb3a8","tests/tests.rs":"de7425a3e4e6e871255721107803704d1431246601fa9c87105224d88dfe60d6","tests/unit.rs":"a53756af9f3f9fe0906f19e4e062477e02e83a76b17676acf1e829dcd288fbc7","tests/uts46.rs":"ca91d48811d366fb9e32d7aa79cfda1261b93c271b6ed7fb5535de9a2500205b"},"package":"89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"} \ No newline at end of file +{"files":{"Cargo.toml":"fa141dcb135262e5fda9f680671699045326d96779bb1acf38d48c70c712bcdf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","benches/all.rs":"e734b9c9092ed66986725f86cfe90f3756cfddb058af308b796ba494f9beefc2","src/IdnaMappingTable.txt":"87d6553a4b86bc49dcade38bf26b745cd81800eb8af295dc3fb99b4729eaea38","src/lib.rs":"d61b2bfcf4265b9a41eedd1de33ab49ea615e3c06df944321b30c57950a85342","src/make_uts46_mapping_table.py":"917055fa841f813de2bcf79cc79b595da3d5551559ee768db8660ab77cb26c34","src/punycode.rs":"07edf5293bc384a164eebb01bc18fe3d4b2d009b4565a36b74a3030978ea6e04","src/uts46.rs":"40521a01e5b8c38667252d5b1e0141c5a71f63aeae2f451b986792984e633b09","src/uts46_mapping_table.rs":"942fff78147c61da942f5f3a7ff4e90f9d7a00a29285733ac3fc3357eb2ed06f","tests/IdnaTestV2.txt":"c6f3778b0545fd150c8063286c7f5adc901e16557eddccc3751213646d07593d","tests/punycode.rs":"e6fb978f48445d1525a6b97351c41c5393a1612a35f85b9a7f45b8794fce9aba","tests/punycode_tests.json":"3d4ac0cf25984c37b9ce197f5df680a0136f728fb8ec82bc76624e42139eb3a8","tests/tests.rs":"de7425a3e4e6e871255721107803704d1431246601fa9c87105224d88dfe60d6","tests/unit.rs":"be025a7d9bab3bd1ce134c87f9d848269e157b31ca5ba0ea03426c1ac736b69e","tests/uts46.rs":"ca91d48811d366fb9e32d7aa79cfda1261b93c271b6ed7fb5535de9a2500205b"},"package":"418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"} \ No newline at end of file diff --git a/vendor/idna/Cargo.toml b/vendor/idna/Cargo.toml index 566689278d..138a27162a 100644 --- a/vendor/idna/Cargo.toml +++ b/vendor/idna/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "idna" -version = "0.2.2" +version = "0.2.3" authors = ["The rust-url developers"] autotests = false description = "IDNA (Internationalizing Domain Names in Applications) and Punycode." diff --git a/vendor/idna/src/punycode.rs b/vendor/idna/src/punycode.rs index a237504e22..21955f3596 100644 --- a/vendor/idna/src/punycode.rs +++ b/vendor/idna/src/punycode.rs @@ -78,6 +78,10 @@ impl Decoder { ), }; + if !base.is_ascii() { + return Err(()); + } + let base_len = base.len(); let mut length = base_len as u32; let mut code_point = INITIAL_N; diff --git a/vendor/idna/src/uts46.rs b/vendor/idna/src/uts46.rs index 0b7d27af54..ad798055fc 100644 --- a/vendor/idna/src/uts46.rs +++ b/vendor/idna/src/uts46.rs @@ -309,7 +309,6 @@ fn check_validity(label: &str, config: Config, errors: &mut Errors) { _ => true, }) { errors.invalid_mapping = true; - return; } // V7: ContextJ rules diff --git a/vendor/idna/tests/unit.rs b/vendor/idna/tests/unit.rs index 84a9d54031..297c8cfce2 100644 --- a/vendor/idna/tests/unit.rs +++ b/vendor/idna/tests/unit.rs @@ -131,3 +131,9 @@ fn emoji_domains() { let error = format!("{:?}", config.to_ascii("☕.com").unwrap_err()); assert!(error.contains("disallowed_in_idna_2008")); } + +#[test] +fn unicode_before_delimiter() { + let config = idna::Config::default(); + assert!(config.to_ascii("xn--f\u{34a}-PTP").is_err()); +} diff --git a/vendor/ignore/.cargo-checksum.json b/vendor/ignore/.cargo-checksum.json index e601bc79a0..42770100a3 100644 --- a/vendor/ignore/.cargo-checksum.json +++ b/vendor/ignore/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.lock":"6314d7e1703fa0a2173819d41f815a608a92a05cd65a10137e9aab505660aa83","Cargo.toml":"0efda4dd62f72c056dfd96fd46b0a390523dcb3d472b4342f79eabb9bd035fb9","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"c0af54e110652d9519a0bbb92cebdab956cac1b6638fee313a38c346022f292f","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","examples/walk.rs":"d93675825e3ef9dd45e1a514c69e73aaad6b3803514b074a0b34f22776bed7f7","src/default_types.rs":"4ca600a4ee51562ba3af8a52bf29376e48266f6513595bde8b5863511fedb9b7","src/dir.rs":"cfde74c8ba5aab92d6d15d2b3127775639640f24eda677e6f0d8228303686b83","src/gitignore.rs":"c13f713f2f1fcb19171e6c515647067a2c61b006b9d0a5c03a1045c28d2bd323","src/lib.rs":"2c2271c943bc9e65fe1a42e4df4dddee2ccc99b4045fdf57bcd4fcf91df3d157","src/overrides.rs":"ef5d124fd317b0911986352d8e6c85145fd9fe3878a52faa9267f5b3745e9719","src/pathutil.rs":"b12295b5eb166635d2fe5c681d2180a3dab3c8c8380cf5c5649c3c3a2cfec200","src/types.rs":"85100a73b08d55456bf1dfb33747695aa5de25263a40b83fbd5424c1958610ea","src/walk.rs":"109b8580a0fd481a81f5c6ae3ba4be590e1b3ee722a1eddb3b9c405a1a5af6c0","tests/gitignore_matched_path_or_any_parents_tests.gitignore":"3895c935f76a57928cc12284dfff406693b7666c0ffce9b8676c6c1976debe2d","tests/gitignore_matched_path_or_any_parents_tests.rs":"d5d9c88ed7783a88519e19b2205cce4548f0952b148a3f835185e706b22a1225"},"package":"22dcbf2a4a289528dbef21686354904e1c694ac642610a9bff9e7df730d9ec72"} \ No newline at end of file +{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.lock":"85cec0a0c2936488fffed98cb61f66bb9b85bfabbdacec907bb948b9e3417431","Cargo.toml":"db5450ee5447b8698a4904216a64ca32d6dc16dc6eaab6f427346a01639be531","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"10e77aba2ccebc593d25fb607e2bafb03eab2a42dc40bc0cc76aef7e8e4a08aa","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","examples/walk.rs":"d93675825e3ef9dd45e1a514c69e73aaad6b3803514b074a0b34f22776bed7f7","src/default_types.rs":"be529f4d9bc4316c1cc70dbf5456f2beaf8823082bc633799d4c2953d85d4af1","src/dir.rs":"cfde74c8ba5aab92d6d15d2b3127775639640f24eda677e6f0d8228303686b83","src/gitignore.rs":"c13f713f2f1fcb19171e6c515647067a2c61b006b9d0a5c03a1045c28d2bd323","src/lib.rs":"aa1115a35b9e8ce7386c2fef984e885aee6935248576a2916ac353ae97c01b40","src/overrides.rs":"ef5d124fd317b0911986352d8e6c85145fd9fe3878a52faa9267f5b3745e9719","src/pathutil.rs":"b12295b5eb166635d2fe5c681d2180a3dab3c8c8380cf5c5649c3c3a2cfec200","src/types.rs":"023b44c036d8e923d47d5fc0fb3a12ea670043a7188ea540a6bb638ac5bcd7ce","src/walk.rs":"109b8580a0fd481a81f5c6ae3ba4be590e1b3ee722a1eddb3b9c405a1a5af6c0","tests/gitignore_matched_path_or_any_parents_tests.gitignore":"3895c935f76a57928cc12284dfff406693b7666c0ffce9b8676c6c1976debe2d","tests/gitignore_matched_path_or_any_parents_tests.rs":"d5d9c88ed7783a88519e19b2205cce4548f0952b148a3f835185e706b22a1225"},"package":"b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"} \ No newline at end of file diff --git a/vendor/ignore/Cargo.lock b/vendor/ignore/Cargo.lock index adcbf8b902..26bbb0999a 100644 --- a/vendor/ignore/Cargo.lock +++ b/vendor/ignore/Cargo.lock @@ -2,24 +2,24 @@ # It is not intended for manual editing. [[package]] name = "aho-corasick" -version = "0.7.10" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bstr" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" +checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" dependencies = [ "memchr", ] @@ -30,24 +30,37 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const_fn" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" + [[package]] name = "crossbeam-channel" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ + "cfg-if 1.0.0", "crossbeam-utils", - "maybe-uninit", ] [[package]] name = "crossbeam-utils" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 1.0.0", + "const_fn", "lazy_static", ] @@ -59,9 +72,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "globset" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" +checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a" dependencies = [ "aho-corasick", "bstr", @@ -72,7 +85,7 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.16" +version = "0.4.17" dependencies = [ "crossbeam-channel", "crossbeam-utils", @@ -95,30 +108,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "log" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "regex" -version = "1.3.9" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ "aho-corasick", "memchr", @@ -128,9 +135,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" [[package]] name = "same-file" @@ -163,9 +170,9 @@ dependencies = [ [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/vendor/ignore/Cargo.toml b/vendor/ignore/Cargo.toml index 1d56b87293..c3a7fdca54 100644 --- a/vendor/ignore/Cargo.toml +++ b/vendor/ignore/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "ignore" -version = "0.4.16" +version = "0.4.17" authors = ["Andrew Gallant "] description = "A fast library for efficiently matching ignore files such as `.gitignore`\nagainst file paths.\n" homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore" @@ -26,7 +26,7 @@ repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore" name = "ignore" bench = false [dependencies.crossbeam-utils] -version = "0.7.0" +version = "0.8.0" [dependencies.globset] version = "0.4.5" @@ -52,7 +52,7 @@ version = "1" [dependencies.walkdir] version = "2.2.7" [dev-dependencies.crossbeam-channel] -version = "0.4.0" +version = "0.5.0" [features] simd-accel = ["globset/simd-accel"] diff --git a/vendor/ignore/README.md b/vendor/ignore/README.md index b0e659a9c3..d9213ec627 100644 --- a/vendor/ignore/README.md +++ b/vendor/ignore/README.md @@ -4,11 +4,10 @@ The ignore crate provides a fast recursive directory iterator that respects various filters such as globs, file types and `.gitignore` files. This crate also provides lower level direct access to gitignore and file type matchers. -[![Linux build status](https://api.travis-ci.org/BurntSushi/ripgrep.svg)](https://travis-ci.org/BurntSushi/ripgrep) -[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/ripgrep?svg=true)](https://ci.appveyor.com/project/BurntSushi/ripgrep) +[![Build status](https://github.com/BurntSushi/ripgrep/workflows/ci/badge.svg)](https://github.com/BurntSushi/ripgrep/actions) [![](https://img.shields.io/crates/v/ignore.svg)](https://crates.io/crates/ignore) -Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). +Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/). ### Documentation diff --git a/vendor/ignore/src/default_types.rs b/vendor/ignore/src/default_types.rs index a0c5bf761f..54fe5cb778 100644 --- a/vendor/ignore/src/default_types.rs +++ b/vendor/ignore/src/default_types.rs @@ -21,7 +21,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]), ("avro", &["*.avdl", "*.avpr", "*.avsc"]), ("awk", &["*.awk"]), - ("bazel", &["*.bzl", "WORKSPACE", "BUILD", "BUILD.bazel"]), + ("bazel", &["*.bazel", "*.bzl", "BUILD", "WORKSPACE"]), ("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]), ("brotli", &["*.br"]), ("buildstream", &["*.bst"]), @@ -52,6 +52,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ("dhall", &["*.dhall"]), ("diff", &["*.patch", "*.diff"]), ("docker", &["*Dockerfile*"]), + ("dvc", &["Dvcfile", "*.dvc"]), ("ebuild", &["*.ebuild"]), ("edn", &["*.edn"]), ("elisp", &["*.el"]), @@ -61,11 +62,13 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ("erlang", &["*.erl", "*.hrl"]), ("fidl", &["*.fidl"]), ("fish", &["*.fish"]), + ("flatbuffers", &["*.fbs"]), ("fortran", &[ "*.f", "*.F", "*.f77", "*.F77", "*.pfo", "*.f90", "*.F90", "*.f95", "*.F95", ]), ("fsharp", &["*.fs", "*.fsx", "*.fsi"]), + ("fut", &[".fut"]), ("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]), ("gn", &["*.gn", "*.gni"]), ("go", &["*.go"]), @@ -136,6 +139,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ("matlab", &["*.m"]), ("md", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]), ("meson", &["meson.build", "meson_options.txt"]), + ("minified", &["*.min.html", "*.min.css", "*.min.js"]), ("mk", &["mkfile"]), ("ml", &["*.ml"]), ("msbuild", &[ @@ -161,6 +165,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ("qmake", &["*.pro", "*.pri", "*.prf"]), ("qml", &["*.qml"]), ("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]), + ("racket", &["*.rkt"]), ("rdoc", &["*.rdoc"]), ("readme", &["README*", "*README"]), ("robot", &["*.robot"]), @@ -222,6 +227,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ("typoscript", &["*.typoscript", "*.ts"]), ("vala", &["*.vala"]), ("vb", &["*.vb"]), + ("vcl", &["*.vcl"]), ("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]), ("vhdl", &["*.vhd", "*.vhdl"]), ("vim", &["*.vim"]), @@ -235,6 +241,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[ ("xz", &["*.xz", "*.txz"]), ("yacc", &["*.y"]), ("yaml", &["*.yaml", "*.yml"]), + ("yang", &["*.yang"]), ("z", &["*.Z"]), ("zig", &["*.zig"]), ("zsh", &[ diff --git a/vendor/ignore/src/lib.rs b/vendor/ignore/src/lib.rs index bcf0ef495b..e58fa36a1d 100644 --- a/vendor/ignore/src/lib.rs +++ b/vendor/ignore/src/lib.rs @@ -196,6 +196,71 @@ impl Error { } } + /// Inspect the original [`io::Error`] if there is one. + /// + /// [`None`] is returned if the [`Error`] doesn't correspond to an + /// [`io::Error`]. This might happen, for example, when the error was + /// produced because a cycle was found in the directory tree while + /// following symbolic links. + /// + /// This method returns a borrowed value that is bound to the lifetime of the [`Error`]. To + /// obtain an owned value, the [`into_io_error`] can be used instead. + /// + /// > This is the original [`io::Error`] and is _not_ the same as + /// > [`impl From for std::io::Error`][impl] which contains additional context about the + /// error. + /// + /// [`None`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#variant.None + /// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html + /// [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html + /// [`Error`]: struct.Error.html + /// [`into_io_error`]: struct.Error.html#method.into_io_error + /// [impl]: struct.Error.html#impl-From%3CError%3E + pub fn io_error(&self) -> Option<&std::io::Error> { + match *self { + Error::Partial(ref errs) => { + if errs.len() == 1 { + errs[0].io_error() + } else { + None + } + } + Error::WithLineNumber { ref err, .. } => err.io_error(), + Error::WithPath { ref err, .. } => err.io_error(), + Error::WithDepth { ref err, .. } => err.io_error(), + Error::Loop { .. } => None, + Error::Io(ref err) => Some(err), + Error::Glob { .. } => None, + Error::UnrecognizedFileType(_) => None, + Error::InvalidDefinition => None, + } + } + + /// Similar to [`io_error`] except consumes self to convert to the original + /// [`io::Error`] if one exists. + /// + /// [`io_error`]: struct.Error.html#method.io_error + /// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html + pub fn into_io_error(self) -> Option { + match self { + Error::Partial(mut errs) => { + if errs.len() == 1 { + errs.remove(0).into_io_error() + } else { + None + } + } + Error::WithLineNumber { err, .. } => err.into_io_error(), + Error::WithPath { err, .. } => err.into_io_error(), + Error::WithDepth { err, .. } => err.into_io_error(), + Error::Loop { .. } => None, + Error::Io(err) => Some(err), + Error::Glob { .. } => None, + Error::UnrecognizedFileType(_) => None, + Error::InvalidDefinition => None, + } + } + /// Returns a depth associated with recursively walking a directory (if /// this error was generated from a recursive directory iterator). pub fn depth(&self) -> Option { diff --git a/vendor/ignore/src/types.rs b/vendor/ignore/src/types.rs index d77e54ebe4..4edf56de45 100644 --- a/vendor/ignore/src/types.rs +++ b/vendor/ignore/src/types.rs @@ -134,7 +134,7 @@ impl<'a> Glob<'a> { Glob(GlobInner::UnmatchedIgnore) } - /// Return the file type defintion that matched, if one exists. A file type + /// Return the file type definition that matched, if one exists. A file type /// definition always exists when a specific definition matches a file /// path. pub fn file_type_def(&self) -> Option<&FileTypeDef> { diff --git a/vendor/jobserver/.cargo-checksum.json b/vendor/jobserver/.cargo-checksum.json index 42f01c1be1..e8150097ec 100644 --- a/vendor/jobserver/.cargo-checksum.json +++ b/vendor/jobserver/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"649c3364426ce43e5e3984b5d7ad1d162ab570d4f0933693b732fc8bed4ed996","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"a9adb9dd4cfca03543232305d4ffab615795e7c04e82c67880fc3802eb1531d5","src/lib.rs":"a11a35e242a379fa1bad686dbe329cbc0cf003d38976c5c3cc999a5ff1478229","src/unix.rs":"aba4305675501da5f14231d836c065c4b2102ba27919fd9eeda6623fddc07ff3","src/wasm.rs":"bb67f97bccd0b0c1762917de342d721e319a3a204604ab1517285c59b5e2a369","src/windows.rs":"f886175abbf75ff45ea3fc09396bbcc3048e7daf732ed78149377f7b8e9148b2","tests/client-of-myself.rs":"09aa82b78b33c09c98fa4eb011af58455972b6a32fa40a2c6631af53e08a1d99","tests/client.rs":"8b0e2cd7ec0cf0de3e7f06342d8cdbd482a29351e8bf3181030e03e76a4c175d","tests/helper.rs":"802ae3eb69c3d787acef2930f9eebe16ad4fc5a2a67b39bb4482d84e2315287a","tests/make-as-a-client.rs":"d8358590a86e6b725a86d0f1b8917f0b051839630a9557d820e4fdcbf99985ec","tests/server.rs":"8f08fe8ed6b3a260de9bf8ee1a7820fadfce8e54ff4fb7bec18e628d092adafb"},"package":"5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"} \ No newline at end of file +{"files":{"Cargo.toml":"b71c5f191edbef61a118e40ebf711045736700b5645de52a02d210b463940444","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"07d8d79f8f6b6a94321fe8db78d26ed409de47cee49290947bd6bbfa29d05e9c","src/lib.rs":"891d9c9cf2d75eee30c02ffa8ae7fa8fb1f7675dccddb0cc79a067e1a87a9850","src/unix.rs":"5802f031e80295c5498a2ddb95b5ee6e39b7294f25b35075302fb978b8d4c409","src/wasm.rs":"bb67f97bccd0b0c1762917de342d721e319a3a204604ab1517285c59b5e2a369","src/windows.rs":"f886175abbf75ff45ea3fc09396bbcc3048e7daf732ed78149377f7b8e9148b2","tests/client-of-myself.rs":"ca09bf398f69df4bac1730999e954dbbc3faf3c6512678c136e0938e7e9cd0ab","tests/client.rs":"64547b780edce5ebcd397db1160fd86baab030c530c6976fa013bca9f07a85ff","tests/helper.rs":"c0e6c00eaf849295d8ec23e374690b6645c0f7d993e91abf7ad53ac960f71762","tests/make-as-a-client.rs":"ec09a7cdbf78d6c3b16f26de15766c4bd62d44a913ada6b86b66e067e6c484ba","tests/server.rs":"9a260f1302ae4908479df0bd34b46edb9d2b8b9b3dbc3e2b6666296d9e1b2b84"},"package":"972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd"} \ No newline at end of file diff --git a/vendor/jobserver/Cargo.toml b/vendor/jobserver/Cargo.toml index 16455b0461..5df95ebf3e 100644 --- a/vendor/jobserver/Cargo.toml +++ b/vendor/jobserver/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "jobserver" -version = "0.1.21" +version = "0.1.22" authors = ["Alex Crichton "] description = "An implementation of the GNU make jobserver for Rust\n" homepage = "https://github.com/alexcrichton/jobserver-rs" diff --git a/vendor/jobserver/README.md b/vendor/jobserver/README.md index 06a6a5450f..7b06c3eb0a 100644 --- a/vendor/jobserver/README.md +++ b/vendor/jobserver/README.md @@ -35,5 +35,5 @@ at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be +for inclusion in jobserver-rs 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/jobserver/src/lib.rs b/vendor/jobserver/src/lib.rs index d61c70c594..72c02c1200 100644 --- a/vendor/jobserver/src/lib.rs +++ b/vendor/jobserver/src/lib.rs @@ -226,8 +226,8 @@ impl Client { /// any number of times. pub unsafe fn from_env() -> Option { let var = match env::var("CARGO_MAKEFLAGS") - .or(env::var("MAKEFLAGS")) - .or(env::var("MFLAGS")) + .or_else(|_| env::var("MAKEFLAGS")) + .or_else(|_| env::var("MFLAGS")) { Ok(s) => s, Err(_) => return None, @@ -268,7 +268,7 @@ impl Client { let data = self.inner.acquire()?; Ok(Acquired { client: self.inner.clone(), - data: data, + data, disabled: false, }) } @@ -294,7 +294,7 @@ impl Client { // Older implementations of make use `--jobserver-fds` and newer // implementations use `--jobserver-auth`, pass both to try to catch // both implementations. - let value = format!("--jobserver-fds={0} --jobserver-auth={0}", arg); + let value = format!("-j --jobserver-fds={0} --jobserver-auth={0}", arg); cmd.env("CARGO_MAKEFLAGS", &value); self.inner.configure(cmd); } diff --git a/vendor/jobserver/src/unix.rs b/vendor/jobserver/src/unix.rs index 7b969ee0ea..d69ae88e30 100644 --- a/vendor/jobserver/src/unix.rs +++ b/vendor/jobserver/src/unix.rs @@ -26,7 +26,7 @@ impl Client { // I don't think the character written here matters, but I could be // wrong! for _ in 0..limit { - (&client.write).write(&[b'|'])?; + (&client.write).write_all(&[b'|'])?; } Ok(client) } @@ -122,10 +122,11 @@ impl Client { // fds are set to nonblocking and combined with `pselect` // internally. // - // Here we try to be compatible with both strategies. We - // unconditionally expect the file descriptor to be in nonblocking - // mode and if it happens to be in blocking mode then most of this - // won't end up actually being necessary! + // Here we try to be compatible with both strategies. We optimistically + // try to read from the file descriptor which then may block, return + // a token or indicate that polling is needed. + // Blocking reads (if possible) allows the kernel to be more selective + // about which readers to wake up when a token is written to the pipe. // // We use `poll` here to block this thread waiting for read // readiness, and then afterwards we perform the `read` itself. If @@ -139,17 +140,6 @@ impl Client { fd.fd = self.read.as_raw_fd(); fd.events = libc::POLLIN; loop { - fd.revents = 0; - if libc::poll(&mut fd, 1, -1) == -1 { - let e = io::Error::last_os_error(); - match e.kind() { - io::ErrorKind::Interrupted => return Ok(None), - _ => return Err(e), - } - } - if fd.revents == 0 { - continue; - } let mut buf = [0]; match (&self.read).read(&mut buf) { Ok(1) => return Ok(Some(Acquired { byte: buf[0] })), @@ -160,10 +150,25 @@ impl Client { )) } Err(e) => match e.kind() { - io::ErrorKind::WouldBlock | io::ErrorKind::Interrupted => return Ok(None), + io::ErrorKind::WouldBlock => { /* fall through to polling */ } + io::ErrorKind::Interrupted => return Ok(None), _ => return Err(e), }, } + + loop { + fd.revents = 0; + if libc::poll(&mut fd, 1, -1) == -1 { + let e = io::Error::last_os_error(); + return match e.kind() { + io::ErrorKind::Interrupted => Ok(None), + _ => Err(e), + }; + } + if fd.revents != 0 { + break; + } + } } } } @@ -184,7 +189,7 @@ impl Client { } pub fn string_arg(&self) -> String { - format!("{},{} -j", self.read.as_raw_fd(), self.write.as_raw_fd()) + format!("{},{}", self.read.as_raw_fd(), self.write.as_raw_fd()) } pub fn configure(&self, cmd: &mut Command) { @@ -299,9 +304,7 @@ impl Helper { } fn is_valid_fd(fd: c_int) -> bool { - unsafe { - return libc::fcntl(fd, libc::F_GETFD) != -1; - } + unsafe { libc::fcntl(fd, libc::F_GETFD) != -1 } } fn set_cloexec(fd: c_int, set: bool) -> io::Result<()> { diff --git a/vendor/jobserver/tests/client-of-myself.rs b/vendor/jobserver/tests/client-of-myself.rs index b89a2f7b54..45d57b0b58 100644 --- a/vendor/jobserver/tests/client-of-myself.rs +++ b/vendor/jobserver/tests/client-of-myself.rs @@ -1,5 +1,3 @@ -extern crate jobserver; - use std::env; use std::io::prelude::*; use std::io::BufReader; diff --git a/vendor/jobserver/tests/client.rs b/vendor/jobserver/tests/client.rs index 042afaa818..7f319c09ce 100644 --- a/vendor/jobserver/tests/client.rs +++ b/vendor/jobserver/tests/client.rs @@ -1,10 +1,3 @@ -extern crate futures; -extern crate jobserver; -extern crate num_cpus; -extern crate tempdir; -extern crate tokio_core; -extern crate tokio_process; - use std::env; use std::fs::File; use std::io::Write; @@ -41,7 +34,7 @@ const TESTS: &[Test] = &[ Test { name: "no j args", make_args: &[], - rule: &|me| format!("{}", me), + rule: &|me| me.to_string(), f: &|| { assert!(unsafe { Client::from_env().is_none() }); }, @@ -124,7 +117,7 @@ fn main() { let me = t!(env::current_exe()); let me = me.to_str().unwrap(); - let filter = env::args().skip(1).next(); + let filter = env::args().nth(1); let mut core = t!(Core::new()); @@ -146,7 +139,7 @@ all: (test.rule)(me) ); t!(t!(File::create(td.path().join("Makefile"))).write_all(makefile.as_bytes())); - let prog = env::var("MAKE").unwrap_or("make".to_string()); + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); let mut cmd = Command::new(prog); cmd.args(test.make_args); cmd.current_dir(td.path()); @@ -174,7 +167,7 @@ all: Ok(()) }))); - if failures.len() == 0 { + if failures.is_empty() { println!("\ntest result: ok\n"); return; } diff --git a/vendor/jobserver/tests/helper.rs b/vendor/jobserver/tests/helper.rs index 093a504ebe..0b3ba88a70 100644 --- a/vendor/jobserver/tests/helper.rs +++ b/vendor/jobserver/tests/helper.rs @@ -20,7 +20,7 @@ fn helper_smoke() { drop(client.clone().into_helper_thread(|_| ()).unwrap()); drop(client.clone().into_helper_thread(|_| ()).unwrap()); drop(client.clone().into_helper_thread(|_| ()).unwrap()); - drop(client.clone().into_helper_thread(|_| ()).unwrap()); + drop(client.into_helper_thread(|_| ()).unwrap()); } #[test] diff --git a/vendor/jobserver/tests/make-as-a-client.rs b/vendor/jobserver/tests/make-as-a-client.rs index 070d3464fc..e530211b05 100644 --- a/vendor/jobserver/tests/make-as-a-client.rs +++ b/vendor/jobserver/tests/make-as-a-client.rs @@ -1,6 +1,3 @@ -extern crate jobserver; -extern crate tempdir; - use std::env; use std::fs::File; use std::io::prelude::*; @@ -42,7 +39,7 @@ fn main() { let c = t!(Client::new(1)); let td = TempDir::new("foo").unwrap(); - let prog = env::var("MAKE").unwrap_or("make".to_string()); + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); let me = t!(env::current_exe()); let me = me.to_str().unwrap(); diff --git a/vendor/jobserver/tests/server.rs b/vendor/jobserver/tests/server.rs index efdda013ba..fcdd12ca2a 100644 --- a/vendor/jobserver/tests/server.rs +++ b/vendor/jobserver/tests/server.rs @@ -1,6 +1,3 @@ -extern crate jobserver; -extern crate tempdir; - use std::env; use std::fs::File; use std::io::prelude::*; @@ -61,7 +58,7 @@ fn make_as_a_single_thread_client() { let c = t!(Client::new(1)); let td = TempDir::new("foo").unwrap(); - let prog = env::var("MAKE").unwrap_or("make".to_string()); + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); let mut cmd = Command::new(prog); cmd.current_dir(td.path()); @@ -115,7 +112,7 @@ fn make_as_a_multi_thread_client() { let c = t!(Client::new(1)); let td = TempDir::new("foo").unwrap(); - let prog = env::var("MAKE").unwrap_or("make".to_string()); + let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string()); let mut cmd = Command::new(prog); cmd.current_dir(td.path()); diff --git a/vendor/libc/.cargo-checksum.json b/vendor/libc/.cargo-checksum.json index 20c894d82d..104eaa0ea1 100644 --- a/vendor/libc/.cargo-checksum.json +++ b/vendor/libc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CONTRIBUTING.md":"50547f85785c64798a3bb93515b795603a78fa131fb92c7e2d1e4d7b463eb829","Cargo.toml":"fb6bb6cbdf66b031372de59ed831b8c90124d96a966072d7cff5d6acee7a6657","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"da312dbe6ad942063ec1e92509c672639aea86b4d73b28bbb9e5e78ca3a897e1","rustfmt.toml":"8a654d5787585ca8f2c20580737336fc327f411a07b0dbd4870adf6e9bdf624f","src/fixed_width_ints.rs":"34c60f12ec5eeb90f13ec3b954427532111c2446e69617616a97aefc1086a9f1","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"0bc9db9863eca7e6254c9bf150812e8ad1c1460b3228126e4a12f26b9d7a03da","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":"017fdd719cc85352a1c062d40edd96a821e19d25abe23b55e40ed6e7ac2892e1","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":"1f4596b7a6e2317e57167e6a9e02fcac1052c201c0f61280b246a19147359a79","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"aceb12eb54b198ae04a64f6308eeb6ec1bf9132c9d98427134292c79f1a61c38","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":"2e9b8f8af44eb75539c7688c2723745a5f10079a7faac99e43ae7534bd111f48","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"09a2441852a6dfb7e7fce28d5115ce243109deab1c569d80c67c5b634ac4bb23","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"72a87d191189486d44bc19a3296817fcf828087ce1286bca20d474a3b2602602","src/unix/bsd/freebsdlike/freebsd/mod.rs":"c12a475eed4a2ebc7f2261f82875dc6dfa33649cbb176073c03183bf26c5f5b9","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":"393d03b6c46c23b727a3de1d7644bca18c9fb68d0e91f175ac4880f64dcf37e8","src/unix/bsd/mod.rs":"26160c60a33cec65ccc3b28277d40bd95f7f62ee857f931ada76cbc7c2694858","src/unix/bsd/netbsdlike/mod.rs":"48dd60524119c1e09b255d5472d091e7e7b2b29eab04be51b4b1e740bd022859","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"b38fc046f9a40fea28bd26328b96629f4d5d63d7524936bd6af1865d401a8716","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"ef048d255a598691217edd86ca9b3edd90ce5f96fc57b1a479214141c9a36ec4","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":"135509edeaf3fb3f102d89d51ff1a8f82323497336a8dc7e1f0f23b5c2434b73","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/mod.rs":"253888b365d4f0dd86d3eae1a63662248514b132031d4bf5434d8a63144ce296","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":"980793af95e9ce82796c8ef487aca2003a1e62f9b23dba84b81331b24f971612","src/unix/haiku/native.rs":"a35b5df389dab4dcff10c758a6714cb69263cf5f3465285d0632ea336a2a617b","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"2d8d3ce0299931199011bb73136bebbddf88edf7d263cc39d26dbfaaa1a14228","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"d611801c875a1066ff596ba813a80c1689aa54489bbd5bd8af4610c786d97a36","src/unix/linux_like/android/b32/mod.rs":"6b3fd3e1eb21e50d000f496729b40968b1c728f5f10d4fb18a9aef44bff383ff","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":"db23f94bc3ed46a0967dde748f0d4566fc885cc6171d0555007f3398ff99a708","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":"87ab84d45d989a98d99975d1d153ad0292eb33e84beb4fac1e79b417b5bfaf11","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"0770f13ce30b98752d5e868332bf5a55bee8389108fe9d91cf2c2bf71c237093","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"213e70ebed2703e14a9cf17666b21ecbf180b7bff7fa22fdbb36dbbd52df326d","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":"4932bb1e4d6b00e3eea211f241a29d08a7a6cb310633d4cb585194ac088e19b7","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"5cf043f5342c37b1cf50bc09de9baaa8d120a8827640f328a74ebbff1fe5aca0","src/unix/linux_like/linux/gnu/b32/mod.rs":"3d282f97f171ce235e687169e7a494e65c21bdc4e59c28360dae60b6c2ffa80c","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"527284eff16dbbed819a12f169a4f957e1ece913a6756be32b2938610c25fc73","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"b16636eff9bcd1b6e23b4a915606f230a01cd8f2752e9331eb576cb023ad27f5","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"98cb96fb979947a2d141d298739649e241168ba7047e6cd1928abdd722281c1b","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"43ddb3fc0e8a9d4b32f929bdbd7dbf3e18167409a6f8e8f12aa694ce34a8d7dc","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":"d2bc7110c0ea616471474957cb16ef54fac9567a569d90ca82961a4eda3fadda","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"ca99bae93eb60138c698ec6b0e78f87cb1dd7181ed3c42c3281c8037c7468921","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":"facd49a8dfcd9e27c8dac6ebaefb07f801a1b8aa21b8d5f477ccf654a14b9d20","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"aa980f78651165fff4db9c9ff33966b3345b682a3600827b91c8141e86f0ff1e","src/unix/linux_like/linux/gnu/b64/s390x.rs":"86562ad9e0468597b13eb8a606f3df456097ad7a9df11ee8dc77c215fc2fc5fc","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"5eaf057e149846b07af6ccc17c6c1b7abf0b4a50ee4fbb100c7c81880c235398","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"f047199e4267bcb63a831379c72884ccf2189b5f2879479436342b2c5b58671e","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"74deaf2135168fd8a8fe3382a443d3800b95ea833e94150b265cc59a24872166","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"60ff6e9aca19226714cf0c7f58f4388f5f046cf099cc4f61f9a2913d94d7e846","src/unix/linux_like/linux/gnu/mod.rs":"a175368149ba4a0f42f0b5aa59faf4fdfd332adfe643d4ef8161609c02c210e1","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"cafa7a6b25c54451f5a72aa31833b6804e88dde7713abfe2859cafb57ab7e5ed","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"5f65fb836de0f5d84dfb78894a045548dab3f62af5241319ec5da46686261a90","src/unix/linux_like/linux/musl/b32/hexagon.rs":"7c6c481f70da1fe6ca759f363784e130041f3d87906c45910fc1142b5ef17970","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"f7adecc4a36b4eb484c168b6c21e73f02ee23f607c0a0351f773f9d9c83b8400","src/unix/linux_like/linux/musl/b32/mod.rs":"8ede3985e6243882814ce91e8ce543e7edbafc0cee5932816072b6f14207a671","src/unix/linux_like/linux/musl/b32/powerpc.rs":"cf286cbf4d2076aaa82662ace2b5c333480410fa59af5cb4542d59f04da84b31","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"ecb903211cb7a956ad1dab4dbef3a0344d9e4df4bd7b4a49ab5cc591df114dc2","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"9870fd9a953c98b775c9e17a29a66bbe8019a6236eb69a0272f42232a226521d","src/unix/linux_like/linux/musl/b64/mips64.rs":"848c8f7ba23b2bab2b070f0d37b42854605dc0bbd660a6728a3aea9a23d9f9e8","src/unix/linux_like/linux/musl/b64/mod.rs":"cf615e1d34fd657f4dffff528de2291750cd0ccceb737018022f31b10fe0d16f","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"8992be6cb56e403e9a712c0ca4761934f873cf89f3e6d3cc4483f43e5a192351","src/unix/linux_like/linux/musl/b64/s390x.rs":"ad940de8bb6cd6a8efa266274dbe96045d071d90700b620949970a033236aad7","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"d6d98b6e5af5d9b1caa7e67fe18c3c4d76fdb92603b42efed83719a41c53defe","src/unix/linux_like/linux/musl/mod.rs":"e0145896cb14dcd2507cfff420aec20a53b4b1dda1f32b34007ff154d0b9b63d","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":"dacb13a12c4abae440c7a600580d84c590b6b420f79b24d5a0b57e04894b45fc","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":"bc8833cb438c252f43801dbecc339c9527f4ca0d197563bc4cfa53093ddd7af0","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":"18623e880c79e10dd1e556860460323c4d06d3b9f2db5a71fbf5ac038cf9923a","src/unix/linux_like/linux/uclibc/mod.rs":"ac2fcd42bc21b854de629730288738bb95c9d652aaa6e652f486ff935b0addbd","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":"634a669cef55569498ef4bf9f86a894d795442a3c445510dec91183f6f897dac","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"7801de13d23b89f80f4f3ff8cebaf7a92887d4ed25da2c943a159f3eca9496e8","src/unix/mod.rs":"5a4c42b444abab61f8adf0410f2a3fba94c53261d1d050372f4498f70a84931f","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":"35ea283f645afbc7ddebba90d46875c9dc5edc8d215d4becc9e2681a909c5aa1","src/unix/newlib/no_align.rs":"7123dcec13604a11b7765c380ff3a4d0da19c39f4b03919de7857723c0cf1502","src/unix/newlib/powerpc/mod.rs":"2d0f7af28b47f7a2a6c210ebd1c1f33ed8eac62e56b5af2b856de2ad3fdc5187","src/unix/newlib/xtensa/mod.rs":"4c72003c5e692e648c7e798358c49af6901e68850dbba0624af84c40baf208f5","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"b865c65438e102403708fa8a299d02ea635bda0879a256d99fadd0092d42f224","src/unix/solarish/compat.rs":"3f13657fc072462b85b5f937f0db1427c41acb2a714cc4f78fefba1ea8036846","src/unix/solarish/illumos.rs":"100845235d27978725d7ff71d58c1b1eb7b360be489056b2758c6cc7244e252e","src/unix/solarish/mod.rs":"ed57a5ad4c715a9038055fe3a57ea12f5ef97c55c3f603596e721a5cbb90ed73","src/unix/solarish/solaris.rs":"3d3cc14b47839da1e4ec117bce1395e22ef86d8d1eb1fdcc6464d2fd8267efb4","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"ce8eb593241f7ac0c9d5e91d535457cd169ddcb3d061d3982ba5bcf6b8d63876","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"bbdfbffd96969f9028d13ad61e08db88769d47a33e45ecc683d9ae203d94130a","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"c7ab9793baaa3b6854d25fdf44266b7953533009e4fa722ca717b71d3e5d2c9d","src/windows/mod.rs":"7b74bf885712d16a3557df33ef02799dc03d4a1af953c7e6b4648954ce7a20fc","src/windows/msvc.rs":"2c2bfce66027d88021e7289139ebf5b0db258a7b6443f18872c84dbd4ef57131","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a"} \ No newline at end of file +{"files":{"CONTRIBUTING.md":"752eea5a703d11b485c6b5f195f51bd2c79aa5159b619ce09555c779e1fb586b","Cargo.toml":"c65ce090d2ce0144faeb8d9ed9039d698ab19d92eee1121ef234238041ec6153","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"8228847944f1332882fbb00275b6f30e4a8aad08a13569c25d52cac012cc2a47","build.rs":"770bf9c7c799dd3536b1e716cb42e7b5569cb4721f02e1d67dd2b932718dea2c","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"34c60f12ec5eeb90f13ec3b954427532111c2446e69617616a97aefc1086a9f1","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"e992965c141308f1ab38c9646b6197b308143dedd2771b6df2f12eb5909ce663","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":"3fe42dd50ccc476255ebe7c1f5bf65950f3d1b5a62fbf8ac91c8c29c945781bc","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"06e3e4a8972f367275c7d1226a47cf86db13afad74a22344d91d1ec2ab043bd9","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":"e777354db19a183fba4c616cb8c72ac88839528c5e2095bbdf7e47e8e5d2148e","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"f3dc5dc3ca3e9cf999ee73222c4fc2200a06f92ce6e9dd6fc357d019bb4999a5","src/unix/bsd/freebsdlike/freebsd/mod.rs":"154dfc0825d39fb19fcf87ccc43bb3923d7faec1eac7b50464a6106dc44a32a8","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":"52a793977374d138c46e62b967e97dc5df06ef143701ffd8f4563658cbe77cf2","src/unix/bsd/mod.rs":"33df9bc4e6f92f78842defe59d9ac2c2afa0942ba990134ec0bf57aa76faa798","src/unix/bsd/netbsdlike/mod.rs":"c640eb7106c8af2ffee0644ea715528da3a8124fd2c9ca6ac617ab9eebc88787","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"b38fc046f9a40fea28bd26328b96629f4d5d63d7524936bd6af1865d401a8716","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"ff10f80b8182dc3a8fa5739bddd5362a2280f396b09d2da6c8adbf596d9643b0","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":"135509edeaf3fb3f102d89d51ff1a8f82323497336a8dc7e1f0f23b5c2434b73","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/mod.rs":"04372b08f57319b08002c1a5e1b200723ed1293754ea5b7d12beafa735c0c2db","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":"7f43160df105a83a8527c59ad99b2578f479837a7c7d8bcdd5ee6607803e49f4","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":"87c46d1ce6899df80b5eea1ca4fd30bc437028e281ea16b658209c2a9b4edbec","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":"db23f94bc3ed46a0967dde748f0d4566fc885cc6171d0555007f3398ff99a708","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":"ead1d5880fa288e11470e560e119c29b16198a0a1bbd853c51e10b1bf4db7583","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"d4c59585ca4802029a41e269092ccfa20f982b352a74abc54d3e7edc3102fb05","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":"08c8e94116dd5bc3e78bd9118647169d6decfbab4b15c6d4f2fc378c2d802cd1","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"8fbd8e1d91f9e748755e11be5c385d9ba2c03acff741b4f75100d679cbcc44bf","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"273f58d7483c7b562725fba71ff0b1f9685258c040f7f4830032aa5f42eced23","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":"33dfff5266bbc50c36d93e7b15381b9b9245031aa49e3db811b8984dd81851c0","src/unix/linux_like/linux/musl/b32/mod.rs":"8ede3985e6243882814ce91e8ce543e7edbafc0cee5932816072b6f14207a671","src/unix/linux_like/linux/musl/b32/powerpc.rs":"bdfed99eb8beb541cc026a86eb99622687eecf603deb35204fee70f5464ad225","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"c34c06d1a2f02a761825a49ad6b37393c4f31afb9a3347de0a0c61979634b9b2","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"798a9229d70ce235394f2dd625f6c4c1e10519a94382dc5b091952b638ae2928","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"3f01dbb2155877208ba58908396f75c7d3f57015662acb46cb19be6b2e81310b","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":"028d235cb9d5af1b80e287b52373640532752ddce4812dee831948c6db4d434b","src/unix/linux_like/linux/musl/b64/s390x.rs":"38bbf839c22a07a46fd5b195812cf8a4d2966611a62213a5b4972422a7e5b8cc","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"aeb436f2575e4e34eb88b597923e480e1e8214b1c8be7f1e41d63c8a0dd9c78b","src/unix/linux_like/linux/musl/mod.rs":"1a8ff52e8f3c52ad53a0d423fae3d79a8f7e07a0b83d5ff9b759eb2a421bda9a","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":"4320e8731666e30f850d45d51cd59311e23cd22dad5d04b3be98a6419e70e0a1","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":"35e17aa16019a82bb1667c43a97ecef151c16ecb5f489793adac918e704e21de","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":"aa2fdf95ead6cde2937f2f0e7e0c72fdf2a6827d8b1bac647d3ca79e4d409348","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":"a0752b528fe6239536b9e915806326b20dc06183f078592b7394a10f5f56a621","src/windows/msvc.rs":"ea6d87a6a9cd668261b1c043e7c36cf599e80b5d09f6e4502e85daa4797c7927","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"} \ No newline at end of file diff --git a/vendor/libc/CONTRIBUTING.md b/vendor/libc/CONTRIBUTING.md index 1acc71d9ca..5be6eb9be4 100644 --- a/vendor/libc/CONTRIBUTING.md +++ b/vendor/libc/CONTRIBUTING.md @@ -28,14 +28,24 @@ at, fear not! This crate has CI support which tests any binding against all platforms supported, so you'll see failures if an API is added at the wrong level or has different signatures across platforms. +New symbol(s) (i.e. functions, constants etc.) should also be added to the +symbols list(s) found in the `libc-test/semver` directory. These lists keep +track of what symbols are public in the libc crate and ensures they remain +available between changes to the crate. If the new symbol(s) are available on +all supported Unixes it should be added to `unix.txt` list1, +otherwise they should be added to the OS specific list(s). + With that in mind, the steps for adding a new API are: 1. Determine where in the module hierarchy your API should be added. -2. Add the API. +2. Add the API, including adding new symbol(s) to the semver lists. 3. Send a PR to this repo. 4. Wait for CI to pass, fixing errors. 5. Wait for a merge! +1: Note that this list has nothing to do with any Unix or Posix +standard, it's just a list shared between all OSs that declare `#[cfg(unix)]`. + ## Test before you commit We have two automated tests running on [GitHub Actions](https://github.com/rust-lang/libc/actions): @@ -69,11 +79,11 @@ platform in this crate, the next step is to get that sweet, sweet usage from crates.io! The only next step is to bump the version of libc and then publish it. If you'd like to get a release out ASAP you can follow these steps: -1. Increment the patch version number in `Cargo.toml`. -1. Send a PR to this repository. It should [look like this][example], but it'd +1. Increment the patch version number in `Cargo.toml` and `libc-test/Cargo.toml`. +1. Send a PR to this repository. It should [look like this][example-pr], but it'd also be nice to fill out the description with a small rationale for the release (any rationale is ok though!) 1. Once merged, the release will be tagged and published by one of the libc crate maintainers. -[example]: https://github.com/rust-lang/libc/pull/583 +[example-pr]: https://github.com/rust-lang/libc/pull/2120 diff --git a/vendor/libc/Cargo.toml b/vendor/libc/Cargo.toml index 34854e1780..20b6db46d7 100644 --- a/vendor/libc/Cargo.toml +++ b/vendor/libc/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "libc" -version = "0.2.88" +version = "0.2.93" authors = ["The Rust Project Developers"] build = "build.rs" exclude = ["/ci/*", "/.github/*", "/.cirrus.yml", "/triagebot.toml"] diff --git a/vendor/libc/build.rs b/vendor/libc/build.rs index ef43dfb788..9ebb67a80c 100644 --- a/vendor/libc/build.rs +++ b/vendor/libc/build.rs @@ -3,12 +3,13 @@ use std::process::Command; use std::str; fn main() { - let (rustc_minor_ver, is_nightly) = - rustc_minor_nightly().expect("Failed to get rustc version"); + // Avoid unnecessary re-building. + println!("cargo:rerun-if-changed=build.rs"); + + let (rustc_minor_ver, is_nightly) = rustc_minor_nightly().expect("Failed to get rustc version"); let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok(); let align_cargo_feature = env::var("CARGO_FEATURE_ALIGN").is_ok(); - let const_extern_fn_cargo_feature = - env::var("CARGO_FEATURE_CONST_EXTERN_FN").is_ok(); + let const_extern_fn_cargo_feature = env::var("CARGO_FEATURE_CONST_EXTERN_FN").is_ok(); let libc_ci = env::var("LIBC_CI").is_ok(); let target = env::var("TARGET").unwrap(); diff --git a/vendor/libc/rustfmt.toml b/vendor/libc/rustfmt.toml index 7ecc610f33..dc85c99467 100644 --- a/vendor/libc/rustfmt.toml +++ b/vendor/libc/rustfmt.toml @@ -1,3 +1 @@ -max_width = 79 -comment_width = 79 -error_on_line_overflow = true \ No newline at end of file +error_on_line_overflow = true diff --git a/vendor/libc/src/fuchsia/mod.rs b/vendor/libc/src/fuchsia/mod.rs index f179923ac4..616655a073 100644 --- a/vendor/libc/src/fuchsia/mod.rs +++ b/vendor/libc/src/fuchsia/mod.rs @@ -3256,12 +3256,12 @@ f! { } } - pub fn CMSG_ALIGN(len: ::size_t) -> ::size_t { + pub {const} fn CMSG_ALIGN(len: ::size_t) -> ::size_t { (len + ::mem::size_of::<::size_t>() - 1) & !(::mem::size_of::<::size_t>() - 1) } - pub fn CMSG_SPACE(len: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(len: ::c_uint) -> ::c_uint { (CMSG_ALIGN(len as ::size_t) + CMSG_ALIGN(::mem::size_of::())) as ::c_uint } @@ -3310,8 +3310,7 @@ safe_f! { } fn __CMSG_LEN(cmsg: *const cmsghdr) -> ::ssize_t { - ((unsafe { (*cmsg).cmsg_len as ::size_t } + ::mem::size_of::<::c_long>() - - 1) + ((unsafe { (*cmsg).cmsg_len as ::size_t } + ::mem::size_of::<::c_long>() - 1) & !(::mem::size_of::<::c_long>() - 1)) as ::ssize_t } @@ -3320,8 +3319,7 @@ fn __CMSG_NEXT(cmsg: *const cmsghdr) -> *mut c_uchar { } fn __MHDR_END(mhdr: *const msghdr) -> *mut c_uchar { - unsafe { (*mhdr).msg_control.offset((*mhdr).msg_controllen as isize) } - .cast() + unsafe { (*mhdr).msg_control.offset((*mhdr).msg_controllen as isize) }.cast() } // EXTERN_FN @@ -3363,44 +3361,24 @@ extern "C" { pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - file: *mut FILE, - ) -> *mut FILE; + pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; - pub fn setvbuf( - stream: *mut FILE, - buffer: *mut c_char, - mode: c_int, - size: size_t, - ) -> c_int; + pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; - pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) - -> *mut c_char; + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; - pub fn fread( - ptr: *mut c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; - pub fn fwrite( - ptr: *const c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; + pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; + pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); @@ -3411,16 +3389,8 @@ extern "C" { pub fn perror(s: *const c_char); pub fn atoi(s: *const c_char) -> c_int; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; - pub fn strtol( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_long; - pub fn strtoul( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_ulong; + pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; + pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; @@ -3433,17 +3403,9 @@ extern "C" { pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; - pub fn strncpy( - dst: *mut c_char, - src: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; - pub fn strncat( - s: *mut c_char, - ct: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; @@ -3460,25 +3422,13 @@ extern "C" { pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; - pub fn wcstombs( - dest: *mut c_char, - src: *const wchar_t, - n: size_t, - ) -> ::size_t; + pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; - pub fn memcpy( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; - pub fn memmove( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; + pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; + pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn abs(i: c_int) -> c_int; @@ -3490,42 +3440,20 @@ extern "C" { pub fn getpwnam(name: *const ::c_char) -> *mut passwd; pub fn getpwuid(uid: ::uid_t) -> *mut passwd; - pub fn fprintf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; - pub fn snprintf( - s: *mut ::c_char, - n: ::size_t, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; - pub fn fscanf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn scanf(format: *const ::c_char, ...) -> ::c_int; - pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) - -> ::c_int; + pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; pub fn socket(domain: ::c_int, ty: ::c_int, protocol: ::c_int) -> ::c_int; - pub fn connect( - socket: ::c_int, - address: *const sockaddr, - len: socklen_t, - ) -> ::c_int; + pub fn connect(socket: ::c_int, address: *const sockaddr, len: socklen_t) -> ::c_int; pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int; - pub fn accept( - socket: ::c_int, - address: *mut sockaddr, - address_len: *mut socklen_t, - ) -> ::c_int; + pub fn accept(socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> ::c_int; pub fn getpeername( socket: ::c_int, address: *mut sockaddr, @@ -3578,20 +3506,12 @@ extern "C" { pub fn opendir(dirname: *const c_char) -> *mut ::DIR; pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent; - pub fn readdir_r( - dirp: *mut ::DIR, - entry: *mut ::dirent, - result: *mut *mut ::dirent, - ) -> ::c_int; + pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) + -> ::c_int; pub fn closedir(dirp: *mut ::DIR) -> ::c_int; pub fn rewinddir(dirp: *mut ::DIR); - pub fn openat( - dirfd: ::c_int, - pathname: *const ::c_char, - flags: ::c_int, - ... - ) -> ::c_int; + pub fn openat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int, ...) -> ::c_int; pub fn fchmodat( dirfd: ::c_int, pathname: *const ::c_char, @@ -3619,11 +3539,7 @@ extern "C" { newpath: *const ::c_char, flags: ::c_int, ) -> ::c_int; - pub fn mkdirat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; + pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn readlinkat( dirfd: ::c_int, pathname: *const ::c_char, @@ -3641,11 +3557,7 @@ extern "C" { newdirfd: ::c_int, linkpath: *const ::c_char, ) -> ::c_int; - pub fn unlinkat( - dirfd: ::c_int, - pathname: *const ::c_char, - flags: ::c_int, - ) -> ::c_int; + pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; pub fn alarm(seconds: ::c_uint) -> ::c_uint; @@ -3656,16 +3568,8 @@ extern "C" { pub fn dup(fd: ::c_int) -> ::c_int; pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> ::c_int; - pub fn execle( - path: *const ::c_char, - arg0: *const ::c_char, - ... - ) -> ::c_int; - pub fn execlp( - file: *const ::c_char, - arg0: *const ::c_char, - ... - ) -> ::c_int; + pub fn execle(path: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; + pub fn execlp(file: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::c_int; pub fn execve( prog: *const c_char, @@ -3681,11 +3585,7 @@ extern "C" { pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t) -> ::c_int; pub fn getlogin() -> *mut c_char; - pub fn getopt( - argc: ::c_int, - argv: *const *mut c_char, - optstr: *const c_char, - ) -> ::c_int; + pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn getpgid(pid: pid_t) -> pid_t; pub fn getpgrp() -> pid_t; pub fn getpid() -> pid_t; @@ -3697,13 +3597,8 @@ extern "C" { pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; pub fn pause() -> ::c_int; pub fn pipe(fds: *mut ::c_int) -> ::c_int; - pub fn posix_memalign( - memptr: *mut *mut ::c_void, - align: ::size_t, - size: ::size_t, - ) -> ::c_int; - pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) - -> ::ssize_t; + pub fn posix_memalign(memptr: *mut *mut ::c_void, align: ::size_t, size: ::size_t) -> ::c_int; + pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; pub fn rmdir(path: *const c_char) -> ::c_int; pub fn seteuid(uid: uid_t) -> ::c_int; pub fn setegid(gid: gid_t) -> ::c_int; @@ -3718,28 +3613,10 @@ extern "C" { pub fn ttyname(fd: ::c_int) -> *mut c_char; pub fn unlink(c: *const c_char) -> ::c_int; pub fn wait(status: *mut ::c_int) -> pid_t; - pub fn waitpid( - pid: pid_t, - status: *mut ::c_int, - options: ::c_int, - ) -> pid_t; - pub fn write( - fd: ::c_int, - buf: *const ::c_void, - count: ::size_t, - ) -> ::ssize_t; - pub fn pread( - fd: ::c_int, - buf: *mut ::c_void, - count: ::size_t, - offset: off_t, - ) -> ::ssize_t; - pub fn pwrite( - fd: ::c_int, - buf: *const ::c_void, - count: ::size_t, - offset: off_t, - ) -> ::ssize_t; + pub fn waitpid(pid: pid_t, status: *mut ::c_int, options: ::c_int) -> pid_t; + pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t; + pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; + pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn umask(mask: mode_t) -> mode_t; pub fn utime(file: *const c_char, buf: *const utimbuf) -> ::c_int; @@ -3762,20 +3639,13 @@ extern "C" { pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int; pub fn if_nametoindex(ifname: *const c_char) -> ::c_uint; - pub fn if_indextoname( - ifindex: ::c_uint, - ifname: *mut ::c_char, - ) -> *mut ::c_char; + pub fn if_indextoname(ifindex: ::c_uint, ifname: *mut ::c_char) -> *mut ::c_char; pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn fsync(fd: ::c_int) -> ::c_int; - pub fn setenv( - name: *const c_char, - val: *const c_char, - overwrite: ::c_int, - ) -> ::c_int; + pub fn setenv(name: *const c_char, val: *const c_char, overwrite: ::c_int) -> ::c_int; pub fn unsetenv(name: *const c_char) -> ::c_int; pub fn symlink(path1: *const c_char, path2: *const c_char) -> ::c_int; @@ -3784,10 +3654,7 @@ extern "C" { pub fn signal(signum: ::c_int, handler: sighandler_t) -> sighandler_t; - pub fn realpath( - pathname: *const ::c_char, - resolved: *mut ::c_char, - ) -> *mut ::c_char; + pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char) -> *mut ::c_char; pub fn flock(fd: ::c_int, operation: ::c_int) -> ::c_int; @@ -3795,21 +3662,12 @@ extern "C" { pub fn times(buf: *mut ::tms) -> ::clock_t; pub fn pthread_self() -> ::pthread_t; - pub fn pthread_join( - native: ::pthread_t, - value: *mut *mut ::c_void, - ) -> ::c_int; + pub fn pthread_join(native: ::pthread_t, value: *mut *mut ::c_void) -> ::c_int; pub fn pthread_exit(value: *mut ::c_void) -> !; pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int; - pub fn pthread_attr_setstacksize( - attr: *mut ::pthread_attr_t, - stack_size: ::size_t, - ) -> ::c_int; - pub fn pthread_attr_setdetachstate( - attr: *mut ::pthread_attr_t, - state: ::c_int, - ) -> ::c_int; + pub fn pthread_attr_setstacksize(attr: *mut ::pthread_attr_t, stack_size: ::size_t) -> ::c_int; + pub fn pthread_attr_setdetachstate(attr: *mut ::pthread_attr_t, state: ::c_int) -> ::c_int; pub fn pthread_detach(thread: ::pthread_t) -> ::c_int; pub fn sched_yield() -> ::c_int; pub fn pthread_key_create( @@ -3818,10 +3676,7 @@ extern "C" { ) -> ::c_int; pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void; - pub fn pthread_setspecific( - key: pthread_key_t, - value: *const ::c_void, - ) -> ::c_int; + pub fn pthread_setspecific(key: pthread_key_t, value: *const ::c_void) -> ::c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, @@ -3832,22 +3687,12 @@ extern "C" { pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> ::c_int; - pub fn pthread_mutexattr_destroy( - attr: *mut pthread_mutexattr_t, - ) -> ::c_int; - pub fn pthread_mutexattr_settype( - attr: *mut pthread_mutexattr_t, - _type: ::c_int, - ) -> ::c_int; + pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> ::c_int; + pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: ::c_int) -> ::c_int; - pub fn pthread_cond_init( - cond: *mut pthread_cond_t, - attr: *const pthread_condattr_t, - ) -> ::c_int; - pub fn pthread_cond_wait( - cond: *mut pthread_cond_t, - lock: *mut pthread_mutex_t, - ) -> ::c_int; + pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) + -> ::c_int; + pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_cond_timedwait( cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t, @@ -3868,16 +3713,9 @@ extern "C" { pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> ::c_int; - pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) - -> ::c_int; - pub fn pthread_rwlockattr_destroy( - attr: *mut pthread_rwlockattr_t, - ) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> ::c_int; + pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn getsockopt( sockfd: ::c_int, @@ -3887,22 +3725,12 @@ extern "C" { optlen: *mut ::socklen_t, ) -> ::c_int; pub fn raise(signum: ::c_int) -> ::c_int; - pub fn sigaction( - signum: ::c_int, - act: *const sigaction, - oldact: *mut sigaction, - ) -> ::c_int; + pub fn sigaction(signum: ::c_int, act: *const sigaction, oldact: *mut sigaction) -> ::c_int; - pub fn utimes( - filename: *const ::c_char, - times: *const ::timeval, - ) -> ::c_int; + pub fn utimes(filename: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn dlopen(filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; pub fn dlerror() -> *mut ::c_char; - pub fn dlsym( - handle: *mut ::c_void, - symbol: *const ::c_char, - ) -> *mut ::c_void; + pub fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void; pub fn dlclose(handle: *mut ::c_void) -> ::c_int; pub fn dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int; @@ -3923,32 +3751,15 @@ extern "C" { pub fn gmtime(time_p: *const time_t) -> *mut tm; pub fn localtime(time_p: *const time_t) -> *mut tm; - pub fn mknod( - pathname: *const ::c_char, - mode: ::mode_t, - dev: ::dev_t, - ) -> ::c_int; + pub fn mknod(pathname: *const ::c_char, mode: ::mode_t, dev: ::dev_t) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int; - pub fn getservbyname( - name: *const ::c_char, - proto: *const ::c_char, - ) -> *mut servent; + pub fn getservbyname(name: *const ::c_char, proto: *const ::c_char) -> *mut servent; pub fn getprotobyname(name: *const ::c_char) -> *mut protoent; pub fn getprotobynumber(proto: ::c_int) -> *mut protoent; pub fn usleep(secs: ::c_uint) -> ::c_int; - pub fn send( - socket: ::c_int, - buf: *const ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; - pub fn recv( - socket: ::c_int, - buf: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; + pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; + pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; pub fn putenv(string: *mut c_char) -> ::c_int; pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; pub fn select( @@ -3958,29 +3769,18 @@ extern "C" { errorfds: *mut fd_set, timeout: *mut timeval, ) -> ::c_int; - pub fn setlocale( - category: ::c_int, - locale: *const ::c_char, - ) -> *mut ::c_char; + pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; pub fn localeconv() -> *mut lconv; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_wait(sem: *mut sem_t) -> ::c_int; pub fn sem_trywait(sem: *mut sem_t) -> ::c_int; pub fn sem_post(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> ::c_int; pub fn fstatvfs(fd: ::c_int, buf: *mut statvfs) -> ::c_int; - pub fn readlink( - path: *const c_char, - buf: *mut c_char, - bufsz: ::size_t, - ) -> ::ssize_t; + pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t; pub fn sigemptyset(set: *mut sigset_t) -> ::c_int; pub fn sigaddset(set: *mut sigset_t, signum: ::c_int) -> ::c_int; @@ -3988,11 +3788,7 @@ extern "C" { pub fn sigdelset(set: *mut sigset_t, signum: ::c_int) -> ::c_int; pub fn sigismember(set: *const sigset_t, signum: ::c_int) -> ::c_int; - pub fn sigprocmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn sigprocmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sigpending(set: *mut sigset_t) -> ::c_int; pub fn timegm(tm: *mut ::tm) -> time_t; @@ -4011,11 +3807,7 @@ extern "C" { timeout: *const timespec, sigmask: *const sigset_t, ) -> ::c_int; - pub fn fseeko( - stream: *mut ::FILE, - offset: ::off_t, - whence: ::c_int, - ) -> ::c_int; + pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; pub fn tcdrain(fd: ::c_int) -> ::c_int; pub fn cfgetispeed(termios: *const ::termios) -> ::speed_t; @@ -4025,11 +3817,7 @@ extern "C" { pub fn cfsetospeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn cfsetspeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn tcgetattr(fd: ::c_int, termios: *mut ::termios) -> ::c_int; - pub fn tcsetattr( - fd: ::c_int, - optional_actions: ::c_int, - termios: *const ::termios, - ) -> ::c_int; + pub fn tcsetattr(fd: ::c_int, optional_actions: ::c_int, termios: *const ::termios) -> ::c_int; pub fn tcflow(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcflush(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcgetsid(fd: ::c_int) -> ::pid_t; @@ -4052,16 +3840,10 @@ extern "C" { pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; - pub fn clock_settime( - clk_id: ::clockid_t, - tp: *const ::timespec, - ) -> ::c_int; + pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; - pub fn pthread_getattr_np( - native: ::pthread_t, - attr: *mut ::pthread_attr_t, - ) -> ::c_int; + pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, @@ -4072,18 +3854,9 @@ extern "C" { pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; - pub fn memrchr( - cx: *const ::c_void, - c: ::c_int, - n: ::size_t, - ) -> *mut ::c_void; + pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; - pub fn posix_fadvise( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - advise: ::c_int, - ) -> ::c_int; + pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, @@ -4093,11 +3866,7 @@ extern "C" { ) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); - pub fn newlocale( - mask: ::c_int, - locale: *const ::c_char, - base: ::locale_t, - ) -> ::locale_t; + pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; @@ -4122,30 +3891,14 @@ extern "C" { len: *mut ::socklen_t, flg: ::c_int, ) -> ::c_int; - pub fn ptsname_r( - fd: ::c_int, - buf: *mut ::c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; pub fn clearenv() -> ::c_int; - pub fn waitid( - idtype: idtype_t, - id: id_t, - infop: *mut ::siginfo_t, - options: ::c_int, - ) -> ::c_int; + pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) + -> ::c_int; pub fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int; pub fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int; - pub fn getresuid( - ruid: *mut ::uid_t, - euid: *mut ::uid_t, - suid: *mut ::uid_t, - ) -> ::c_int; - pub fn getresgid( - rgid: *mut ::gid_t, - egid: *mut ::gid_t, - sgid: *mut ::gid_t, - ) -> ::c_int; + pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, suid: *mut ::uid_t) -> ::c_int; + pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, sgid: *mut ::gid_t) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; pub fn brk(addr: *mut ::c_void) -> ::c_int; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; @@ -4176,40 +3929,18 @@ extern "C" { pub fn endpwent(); pub fn getpwent() -> *mut passwd; - pub fn shm_open( - name: *const c_char, - oflag: ::c_int, - mode: mode_t, - ) -> ::c_int; + pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; // System V IPC pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; - pub fn shmat( - shmid: ::c_int, - shmaddr: *const ::c_void, - shmflg: ::c_int, - ) -> *mut ::c_void; + pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; - pub fn shmctl( - shmid: ::c_int, - cmd: ::c_int, - buf: *mut ::shmid_ds, - ) -> ::c_int; + pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int; - pub fn semop( - semid: ::c_int, - sops: *mut ::sembuf, - nsops: ::size_t, - ) -> ::c_int; - pub fn semctl( - semid: ::c_int, - semnum: ::c_int, - cmd: ::c_int, - ... - ) -> ::c_int; - pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) - -> ::c_int; + pub fn semop(semid: ::c_int, sops: *mut ::sembuf, nsops: ::size_t) -> ::c_int; + pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; + pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv( msqid: ::c_int, @@ -4225,57 +3956,24 @@ extern "C" { msgflg: ::c_int, ) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn __errno_location() -> *mut ::c_int; - pub fn fallocate( - fd: ::c_int, - mode: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn posix_fallocate( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn readahead( - fd: ::c_int, - offset: ::off64_t, - count: ::size_t, - ) -> ::ssize_t; - pub fn signalfd( - fd: ::c_int, - mask: *const ::sigset_t, - flags: ::c_int, - ) -> ::c_int; + pub fn fallocate(fd: ::c_int, mode: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn readahead(fd: ::c_int, offset: ::off64_t, count: ::size_t) -> ::ssize_t; + 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_gettime( - fd: ::c_int, - curr_value: *mut itimerspec, - ) -> ::c_int; + pub fn timerfd_gettime(fd: ::c_int, curr_value: *mut itimerspec) -> ::c_int; pub fn timerfd_settime( fd: ::c_int, flags: ::c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> ::c_int; - pub fn pwritev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn preadv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; + pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) + -> ::ssize_t; + pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn quotactl( cmd: ::c_int, special: *const ::c_char, @@ -4284,19 +3982,14 @@ extern "C" { ) -> ::c_int; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; - pub fn mkostemps( - template: *mut ::c_char, - suffixlen: ::c_int, - flags: ::c_int, - ) -> ::c_int; + pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; - pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) - -> *mut ::c_char; + pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, @@ -4311,11 +4004,7 @@ extern "C" { pub fn setfsuid(uid: ::uid_t) -> ::c_int; // Not available now on Android - pub fn mkfifoat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn sync_file_range( @@ -4330,35 +4019,21 @@ extern "C" { pub fn glob( pattern: *const c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); - pub fn posix_madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, @@ -4372,33 +4047,13 @@ extern "C" { pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; - pub fn bind( - socket: ::c_int, - address: *const ::sockaddr, - address_len: ::socklen_t, - ) -> ::c_int; + pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; - pub fn sendmsg( - fd: ::c_int, - msg: *const ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; - pub fn recvmsg( - fd: ::c_int, - msg: *mut ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; + pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn vhangup() -> ::c_int; @@ -4417,11 +4072,8 @@ extern "C" { ) -> ::c_int; pub fn sync(); pub fn syscall(num: ::c_long, ...) -> ::c_long; - pub fn sched_getaffinity( - pid: ::pid_t, - cpusetsize: ::size_t, - cpuset: *mut cpu_set_t, - ) -> ::c_int; + pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) + -> ::c_int; pub fn sched_setaffinity( pid: ::pid_t, cpusetsize: ::size_t, @@ -4429,16 +4081,8 @@ extern "C" { ) -> ::c_int; pub fn umount(target: *const ::c_char) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; - pub fn tee( - fd_in: ::c_int, - fd_out: ::c_int, - len: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; - pub fn settimeofday( - tv: *const ::timeval, - tz: *const ::timezone, - ) -> ::c_int; + pub fn tee(fd_in: ::c_int, fd_out: ::c_int, len: ::size_t, flags: ::c_uint) -> ::ssize_t; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn splice( fd_in: ::c_int, off_in: *mut ::loff_t, @@ -4448,17 +4092,10 @@ extern "C" { flags: ::c_uint, ) -> ::ssize_t; pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; - pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) - -> ::c_int; - pub fn sem_timedwait( - sem: *mut sem_t, - abstime: *const ::timespec, - ) -> ::c_int; + pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; - pub fn sched_setparam( - pid: ::pid_t, - param: *const ::sched_param, - ) -> ::c_int; + pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn swapoff(puath: *const ::c_char) -> ::c_int; pub fn vmsplice( fd: ::c_int, @@ -4531,11 +4168,7 @@ extern "C" { result: *mut *mut ::group, ) -> ::c_int; pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; - pub fn pthread_sigmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; diff --git a/vendor/libc/src/psp.rs b/vendor/libc/src/psp.rs index 9babe1c0ec..575232dad1 100644 --- a/vendor/libc/src/psp.rs +++ b/vendor/libc/src/psp.rs @@ -54,24 +54,18 @@ pub type SceKernelVTimerHandler = unsafe extern "C" fn( arg3: *mut c_void, ) -> u32; -pub type SceKernelVTimerHandlerWide = unsafe extern "C" fn( - uid: SceUid, - arg1: i64, - arg2: i64, - arg3: *mut c_void, -) -> u32; +pub type SceKernelVTimerHandlerWide = + unsafe extern "C" fn(uid: SceUid, arg1: i64, arg2: i64, arg3: *mut c_void) -> u32; pub type SceKernelThreadEventHandler = unsafe extern "C" fn(mask: i32, thid: SceUid, common: *mut c_void) -> i32; -pub type SceKernelAlarmHandler = - unsafe extern "C" fn(common: *mut c_void) -> u32; +pub type SceKernelAlarmHandler = unsafe extern "C" fn(common: *mut c_void) -> u32; pub type SceKernelCallbackFunction = unsafe extern "C" fn(arg1: i32, arg2: i32, arg: *mut c_void) -> i32; -pub type SceKernelThreadEntry = - unsafe extern "C" fn(args: usize, argp: *mut c_void) -> i32; +pub type SceKernelThreadEntry = unsafe extern "C" fn(args: usize, argp: *mut c_void) -> i32; pub type PowerCallback = extern "C" fn(unknown: i32, power_info: i32); @@ -79,22 +73,15 @@ pub type IoPermissions = i32; pub type UmdCallback = fn(unknown: i32, event: i32) -> i32; -pub type SceMpegRingbufferCb = ::Option< - unsafe extern "C" fn( - data: *mut c_void, - num_packets: i32, - param: *mut c_void, - ) -> i32, ->; +pub type SceMpegRingbufferCb = + ::Option i32>; pub type GuCallback = ::Option; -pub type GuSwapBuffersCallback = ::Option< - extern "C" fn(display: *mut *mut c_void, render: *mut *mut c_void), ->; +pub type GuSwapBuffersCallback = + ::Option; -pub type SceNetAdhocctlHandler = ::Option< - unsafe extern "C" fn(flag: i32, error: i32, unknown: *mut c_void), ->; +pub type SceNetAdhocctlHandler = + ::Option; pub type AdhocMatchingCallback = ::Option< unsafe extern "C" fn( @@ -107,17 +94,10 @@ pub type AdhocMatchingCallback = ::Option< >; pub type SceNetApctlHandler = ::Option< - unsafe extern "C" fn( - oldState: i32, - newState: i32, - event: i32, - error: i32, - pArg: *mut c_void, - ), + unsafe extern "C" fn(oldState: i32, newState: i32, event: i32, error: i32, pArg: *mut c_void), >; -pub type HttpMallocFunction = - ::Option *mut c_void>; +pub type HttpMallocFunction = ::Option *mut c_void>; pub type HttpReallocFunction = ::Option *mut c_void>; pub type HttpFreeFunction = ::Option; @@ -2613,8 +2593,7 @@ pub const UTILITY_HTMLVIEWER_DISABLE_EXIT_DIALOG: i32 = 0x000004; pub const UTILITY_HTMLVIEWER_DISABLE_CURSOR: i32 = 0x000008; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_COMPLETE_DIALOG: i32 = 0x000010; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_START_DIALOG: i32 = 0x000020; -pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_DESTINATION_DIALOG: i32 = - 0x000040; +pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_DESTINATION_DIALOG: i32 = 0x000040; pub const UTILITY_HTMLVIEWER_LOCK_DOWNLOAD_DESTINATION_DIALOG: i32 = 0x000080; pub const UTILITY_HTMLVIEWER_DISABLE_TAB_DISPLAY: i32 = 0x000100; pub const UTILITY_HTMLVIEWER_ENABLE_ANALOG_HOLD: i32 = 0x000200; @@ -2622,18 +2601,10 @@ pub const UTILITY_HTMLVIEWER_ENABLE_FLASH: i32 = 0x000400; pub const UTILITY_HTMLVIEWER_DISABLE_LRTRIGGER: i32 = 0x000800; extern "C" { - pub fn sceAudioChReserve( - channel: i32, - sample_count: i32, - format: AudioFormat, - ) -> i32; + pub fn sceAudioChReserve(channel: i32, sample_count: i32, format: AudioFormat) -> i32; pub fn sceAudioChRelease(channel: i32) -> i32; pub fn sceAudioOutput(channel: i32, vol: i32, buf: *mut c_void) -> i32; - pub fn sceAudioOutputBlocking( - channel: i32, - vol: i32, - buf: *mut c_void, - ) -> i32; + pub fn sceAudioOutputBlocking(channel: i32, vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioOutputPanned( channel: i32, left_vol: i32, @@ -2649,15 +2620,8 @@ extern "C" { pub fn sceAudioGetChannelRestLen(channel: i32) -> i32; pub fn sceAudioGetChannelRestLength(channel: i32) -> i32; pub fn sceAudioSetChannelDataLen(channel: i32, sample_count: i32) -> i32; - pub fn sceAudioChangeChannelConfig( - channel: i32, - format: AudioFormat, - ) -> i32; - pub fn sceAudioChangeChannelVolume( - channel: i32, - left_vol: i32, - right_vol: i32, - ) -> i32; + pub fn sceAudioChangeChannelConfig(channel: i32, format: AudioFormat) -> i32; + pub fn sceAudioChangeChannelVolume(channel: i32, left_vol: i32, right_vol: i32) -> i32; pub fn sceAudioOutput2Reserve(sample_count: i32) -> i32; pub fn sceAudioOutput2Release() -> i32; pub fn sceAudioOutput2ChangeLength(sample_count: i32) -> i32; @@ -2672,16 +2636,8 @@ extern "C" { pub fn sceAudioSRCOutputBlocking(vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioInputInit(unknown1: i32, gain: i32, unknown2: i32) -> i32; pub fn sceAudioInputInitEx(params: *mut AudioInputParams) -> i32; - pub fn sceAudioInputBlocking( - sample_count: i32, - freq: AudioInputFrequency, - buf: *mut c_void, - ); - pub fn sceAudioInput( - sample_count: i32, - freq: AudioInputFrequency, - buf: *mut c_void, - ); + pub fn sceAudioInputBlocking(sample_count: i32, freq: AudioInputFrequency, buf: *mut c_void); + pub fn sceAudioInput(sample_count: i32, freq: AudioInputFrequency, buf: *mut c_void); pub fn sceAudioGetInputLength() -> i32; pub fn sceAudioWaitInputEnd() -> i32; pub fn sceAudioPollInputEnd() -> i32; @@ -2695,10 +2651,7 @@ extern "C" { out_end: *mut i32, out_remain_frame: *mut i32, ) -> i32; - pub fn sceAtracGetRemainFrame( - atrac_id: i32, - out_remain_frame: *mut i32, - ) -> i32; + pub fn sceAtracGetRemainFrame(atrac_id: i32, out_remain_frame: *mut i32) -> i32; pub fn sceAtracGetStreamDataInfo( atrac_id: i32, write_pointer: *mut *mut u8, @@ -2717,19 +2670,13 @@ extern "C" { pbuffer_info: *mut Atrac3BufferInfo, ) -> i32; pub fn sceAtracGetChannel(atrac_id: i32, pui_channel: *mut u32) -> i32; - pub fn sceAtracGetInternalErrorInfo( - atrac_id: i32, - pi_result: *mut i32, - ) -> i32; + pub fn sceAtracGetInternalErrorInfo(atrac_id: i32, pi_result: *mut i32) -> i32; pub fn sceAtracGetLoopStatus( atrac_id: i32, pi_loop_num: *mut i32, pui_loop_status: *mut u32, ) -> i32; - pub fn sceAtracGetNextDecodePosition( - atrac_id: i32, - pui_sample_position: *mut u32, - ) -> i32; + pub fn sceAtracGetNextDecodePosition(atrac_id: i32, pui_sample_position: *mut u32) -> i32; pub fn sceAtracGetSecondBufferInfo( atrac_id: i32, pui_position: *mut u32, @@ -2747,11 +2694,7 @@ extern "C" { ui_write_byte_first_buf: u32, ui_write_byte_second_buf: u32, ) -> i32; - pub fn sceAtracSetData( - atrac_id: i32, - puc_buffer_addr: *mut u8, - ui_buffer_byte: u32, - ) -> i32; + pub fn sceAtracSetData(atrac_id: i32, puc_buffer_addr: *mut u8, ui_buffer_byte: u32) -> i32; pub fn sceAtracSetHalfwayBuffer( atrac_id: i32, puc_buffer_addr: *mut u8, @@ -2773,41 +2716,17 @@ extern "C" { pub fn sceCtrlGetSamplingCycle(pcycle: *mut i32) -> i32; pub fn sceCtrlSetSamplingMode(mode: CtrlMode) -> i32; pub fn sceCtrlGetSamplingMode(pmode: *mut i32) -> i32; - pub fn sceCtrlPeekBufferPositive( - pad_data: *mut SceCtrlData, - count: i32, - ) -> i32; - pub fn sceCtrlPeekBufferNegative( - pad_data: *mut SceCtrlData, - count: i32, - ) -> i32; - pub fn sceCtrlReadBufferPositive( - pad_data: *mut SceCtrlData, - count: i32, - ) -> i32; - pub fn sceCtrlReadBufferNegative( - pad_data: *mut SceCtrlData, - count: i32, - ) -> i32; + pub fn sceCtrlPeekBufferPositive(pad_data: *mut SceCtrlData, count: i32) -> i32; + pub fn sceCtrlPeekBufferNegative(pad_data: *mut SceCtrlData, count: i32) -> i32; + pub fn sceCtrlReadBufferPositive(pad_data: *mut SceCtrlData, count: i32) -> i32; + pub fn sceCtrlReadBufferNegative(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlPeekLatch(latch_data: *mut SceCtrlLatch) -> i32; pub fn sceCtrlReadLatch(latch_data: *mut SceCtrlLatch) -> i32; - pub fn sceCtrlSetIdleCancelThreshold(idlereset: i32, idleback: i32) - -> i32; - pub fn sceCtrlGetIdleCancelThreshold( - idlereset: *mut i32, - idleback: *mut i32, - ) -> i32; + pub fn sceCtrlSetIdleCancelThreshold(idlereset: i32, idleback: i32) -> i32; + pub fn sceCtrlGetIdleCancelThreshold(idlereset: *mut i32, idleback: *mut i32) -> i32; - pub fn sceDisplaySetMode( - mode: DisplayMode, - width: usize, - height: usize, - ) -> u32; - pub fn sceDisplayGetMode( - pmode: *mut i32, - pwidth: *mut i32, - pheight: *mut i32, - ) -> i32; + pub fn sceDisplaySetMode(mode: DisplayMode, width: usize, height: usize) -> u32; + pub fn sceDisplayGetMode(pmode: *mut i32, pwidth: *mut i32, pheight: *mut i32) -> i32; pub fn sceDisplaySetFrameBuf( top_addr: *const u8, buffer_width: usize, @@ -2862,10 +2781,7 @@ extern "C" { pub fn sceKernelExitGame(); pub fn sceKernelRegisterExitCallback(id: SceUid) -> i32; - pub fn sceKernelLoadExec( - file: *const u8, - param: *mut SceKernelLoadExecParam, - ) -> i32; + pub fn sceKernelLoadExec(file: *const u8, param: *mut SceKernelLoadExecParam) -> i32; pub fn sceKernelAllocPartitionMemory( partition: SceSysMemPartitionId, @@ -2884,52 +2800,27 @@ extern "C" { pub fn sceKernelLibcTime(t: *mut i32) -> i32; pub fn sceKernelLibcClock() -> u32; - pub fn sceKernelLibcGettimeofday( - tp: *mut timeval, - tzp: *mut timezone, - ) -> i32; + pub fn sceKernelLibcGettimeofday(tp: *mut timeval, tzp: *mut timezone) -> i32; pub fn sceKernelDcacheWritebackAll(); pub fn sceKernelDcacheWritebackInvalidateAll(); pub fn sceKernelDcacheWritebackRange(p: *const c_void, size: u32); - pub fn sceKernelDcacheWritebackInvalidateRange( - p: *const c_void, - size: u32, - ); + pub fn sceKernelDcacheWritebackInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelDcacheInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelIcacheInvalidateAll(); pub fn sceKernelIcacheInvalidateRange(p: *const c_void, size: u32); - pub fn sceKernelUtilsMt19937Init( - ctx: *mut SceKernelUtilsMt19937Context, - seed: u32, - ) -> i32; - pub fn sceKernelUtilsMt19937UInt( - ctx: *mut SceKernelUtilsMt19937Context, - ) -> u32; - pub fn sceKernelUtilsMd5Digest( - data: *mut u8, - size: u32, - digest: *mut u8, - ) -> i32; - pub fn sceKernelUtilsMd5BlockInit( - ctx: *mut SceKernelUtilsMd5Context, - ) -> i32; + pub fn sceKernelUtilsMt19937Init(ctx: *mut SceKernelUtilsMt19937Context, seed: u32) -> i32; + pub fn sceKernelUtilsMt19937UInt(ctx: *mut SceKernelUtilsMt19937Context) -> u32; + pub fn sceKernelUtilsMd5Digest(data: *mut u8, size: u32, digest: *mut u8) -> i32; + pub fn sceKernelUtilsMd5BlockInit(ctx: *mut SceKernelUtilsMd5Context) -> i32; pub fn sceKernelUtilsMd5BlockUpdate( ctx: *mut SceKernelUtilsMd5Context, data: *mut u8, size: u32, ) -> i32; - pub fn sceKernelUtilsMd5BlockResult( - ctx: *mut SceKernelUtilsMd5Context, - digest: *mut u8, - ) -> i32; - pub fn sceKernelUtilsSha1Digest( - data: *mut u8, - size: u32, - digest: *mut u8, - ) -> i32; - pub fn sceKernelUtilsSha1BlockInit( - ctx: *mut SceKernelUtilsSha1Context, - ) -> i32; + pub fn sceKernelUtilsMd5BlockResult(ctx: *mut SceKernelUtilsMd5Context, digest: *mut u8) + -> i32; + pub fn sceKernelUtilsSha1Digest(data: *mut u8, size: u32, digest: *mut u8) -> i32; + pub fn sceKernelUtilsSha1BlockInit(ctx: *mut SceKernelUtilsSha1Context) -> i32; pub fn sceKernelUtilsSha1BlockUpdate( ctx: *mut SceKernelUtilsSha1Context, data: *mut u8, @@ -2997,37 +2888,22 @@ extern "C" { option: *mut SceKernelSMOption, ) -> i32; pub fn sceKernelUnloadModule(mod_id: SceUid) -> i32; - pub fn sceKernelSelfStopUnloadModule( - unknown: i32, - arg_size: usize, - argp: *mut c_void, - ) -> i32; + pub fn sceKernelSelfStopUnloadModule(unknown: i32, arg_size: usize, argp: *mut c_void) -> i32; pub fn sceKernelStopUnloadSelfModule( arg_size: usize, argp: *mut c_void, status: *mut i32, option: *mut SceKernelSMOption, ) -> i32; - pub fn sceKernelQueryModuleInfo( - mod_id: SceUid, - info: *mut SceKernelModuleInfo, - ) -> i32; + pub fn sceKernelQueryModuleInfo(mod_id: SceUid, info: *mut SceKernelModuleInfo) -> i32; pub fn sceKernelGetModuleIdList( read_buf: *mut SceUid, read_buf_size: i32, id_count: *mut i32, ) -> i32; - pub fn sceKernelVolatileMemLock( - unk: i32, - ptr: *mut *mut c_void, - size: *mut i32, - ) -> i32; - pub fn sceKernelVolatileMemTryLock( - unk: i32, - ptr: *mut *mut c_void, - size: *mut i32, - ) -> i32; + pub fn sceKernelVolatileMemLock(unk: i32, ptr: *mut *mut c_void, size: *mut i32) -> i32; + pub fn sceKernelVolatileMemTryLock(unk: i32, ptr: *mut *mut c_void, size: *mut i32) -> i32; pub fn sceKernelVolatileMemUnlock(unk: i32) -> i32; pub fn sceKernelStdin() -> SceUid; @@ -3044,11 +2920,7 @@ extern "C" { option: *mut SceKernelThreadOptParam, ) -> SceUid; pub fn sceKernelDeleteThread(thid: SceUid) -> i32; - pub fn sceKernelStartThread( - id: SceUid, - arg_len: usize, - arg_p: *mut c_void, - ) -> i32; + pub fn sceKernelStartThread(id: SceUid, arg_len: usize, arg_p: *mut c_void) -> i32; pub fn sceKernelExitThread(status: i32) -> i32; pub fn sceKernelExitDeleteThread(status: i32) -> i32; pub fn sceKernelTerminateThread(thid: SceUid) -> i32; @@ -3066,9 +2938,7 @@ extern "C" { pub fn sceKernelDelayThread(delay: u32) -> i32; pub fn sceKernelDelayThreadCB(delay: u32) -> i32; pub fn sceKernelDelaySysClockThread(delay: *mut SceKernelSysClock) -> i32; - pub fn sceKernelDelaySysClockThreadCB( - delay: *mut SceKernelSysClock, - ) -> i32; + pub fn sceKernelDelaySysClockThreadCB(delay: *mut SceKernelSysClock) -> i32; pub fn sceKernelChangeCurrentThreadAttr(unknown: i32, attr: i32) -> i32; pub fn sceKernelChangeThreadPriority(thid: SceUid, priority: i32) -> i32; pub fn sceKernelRotateThreadReadyQueue(priority: i32) -> i32; @@ -3078,10 +2948,7 @@ extern "C" { pub fn sceKernelGetThreadExitStatus(thid: SceUid) -> i32; pub fn sceKernelCheckThreadStack() -> i32; pub fn sceKernelGetThreadStackFreeSize(thid: SceUid) -> i32; - pub fn sceKernelReferThreadStatus( - thid: SceUid, - info: *mut SceKernelThreadInfo, - ) -> i32; + pub fn sceKernelReferThreadStatus(thid: SceUid, info: *mut SceKernelThreadInfo) -> i32; pub fn sceKernelReferThreadRunStatus( thid: SceUid, status: *mut SceKernelThreadRunStatus, @@ -3095,21 +2962,10 @@ extern "C" { ) -> SceUid; pub fn sceKernelDeleteSema(sema_id: SceUid) -> i32; pub fn sceKernelSignalSema(sema_id: SceUid, signal: i32) -> i32; - pub fn sceKernelWaitSema( - sema_id: SceUid, - signal: i32, - timeout: *mut u32, - ) -> i32; - pub fn sceKernelWaitSemaCB( - sema_id: SceUid, - signal: i32, - timeout: *mut u32, - ) -> i32; + pub fn sceKernelWaitSema(sema_id: SceUid, signal: i32, timeout: *mut u32) -> i32; + pub fn sceKernelWaitSemaCB(sema_id: SceUid, signal: i32, timeout: *mut u32) -> i32; pub fn sceKernelPollSema(sema_id: SceUid, signal: i32) -> i32; - pub fn sceKernelReferSemaStatus( - sema_id: SceUid, - info: *mut SceKernelSemaInfo, - ) -> i32; + pub fn sceKernelReferSemaStatus(sema_id: SceUid, info: *mut SceKernelSemaInfo) -> i32; pub fn sceKernelCreateEventFlag( name: *const u8, attr: i32, @@ -3118,12 +2974,7 @@ extern "C" { ) -> SceUid; pub fn sceKernelSetEventFlag(ev_id: SceUid, bits: u32) -> i32; pub fn sceKernelClearEventFlag(ev_id: SceUid, bits: u32) -> i32; - pub fn sceKernelPollEventFlag( - ev_id: SceUid, - bits: u32, - wait: i32, - out_bits: *mut u32, - ) -> i32; + pub fn sceKernelPollEventFlag(ev_id: SceUid, bits: u32, wait: i32, out_bits: *mut u32) -> i32; pub fn sceKernelWaitEventFlag( ev_id: SceUid, bits: u32, @@ -3139,10 +2990,8 @@ extern "C" { timeout: *mut u32, ) -> i32; pub fn sceKernelDeleteEventFlag(ev_id: SceUid) -> i32; - pub fn sceKernelReferEventFlagStatus( - event: SceUid, - status: *mut SceKernelEventFlagInfo, - ) -> i32; + pub fn sceKernelReferEventFlagStatus(event: SceUid, status: *mut SceKernelEventFlagInfo) + -> i32; pub fn sceKernelCreateMbx( name: *const u8, attr: u32, @@ -3150,23 +2999,16 @@ extern "C" { ) -> SceUid; pub fn sceKernelDeleteMbx(mbx_id: SceUid) -> i32; pub fn sceKernelSendMbx(mbx_id: SceUid, message: *mut c_void) -> i32; - pub fn sceKernelReceiveMbx( - mbx_id: SceUid, - message: *mut *mut c_void, - timeout: *mut u32, - ) -> i32; + pub fn sceKernelReceiveMbx(mbx_id: SceUid, message: *mut *mut c_void, timeout: *mut u32) + -> i32; pub fn sceKernelReceiveMbxCB( mbx_id: SceUid, message: *mut *mut c_void, timeout: *mut u32, ) -> i32; - pub fn sceKernelPollMbx(mbx_id: SceUid, pmessage: *mut *mut c_void) - -> i32; + pub fn sceKernelPollMbx(mbx_id: SceUid, pmessage: *mut *mut c_void) -> i32; pub fn sceKernelCancelReceiveMbx(mbx_id: SceUid, num: *mut i32) -> i32; - pub fn sceKernelReferMbxStatus( - mbx_id: SceUid, - info: *mut SceKernelMbxInfo, - ) -> i32; + pub fn sceKernelReferMbxStatus(mbx_id: SceUid, info: *mut SceKernelMbxInfo) -> i32; pub fn sceKernelSetAlarm( clock: u32, handler: SceKernelAlarmHandler, @@ -3178,19 +3020,13 @@ extern "C" { common: *mut c_void, ) -> SceUid; pub fn sceKernelCancelAlarm(alarm_id: SceUid) -> i32; - pub fn sceKernelReferAlarmStatus( - alarm_id: SceUid, - info: *mut SceKernelAlarmInfo, - ) -> i32; + pub fn sceKernelReferAlarmStatus(alarm_id: SceUid, info: *mut SceKernelAlarmInfo) -> i32; pub fn sceKernelCreateCallback( name: *const u8, func: SceKernelCallbackFunction, arg: *mut c_void, ) -> SceUid; - pub fn sceKernelReferCallbackStatus( - cb: SceUid, - status: *mut SceKernelCallbackInfo, - ) -> i32; + pub fn sceKernelReferCallbackStatus(cb: SceUid, status: *mut SceKernelCallbackInfo) -> i32; pub fn sceKernelDeleteCallback(cb: SceUid) -> i32; pub fn sceKernelNotifyCallback(cb: SceUid, arg2: i32) -> i32; pub fn sceKernelCancelCallback(cb: SceUid) -> i32; @@ -3202,9 +3038,7 @@ extern "C" { read_buf_size: i32, id_count: *mut i32, ) -> i32; - pub fn sceKernelReferSystemStatus( - status: *mut SceKernelSystemStatus, - ) -> i32; + pub fn sceKernelReferSystemStatus(status: *mut SceKernelSystemStatus) -> i32; pub fn sceKernelCreateMsgPipe( name: *const u8, part: i32, @@ -3259,15 +3093,8 @@ extern "C" { unk1: i32, unk2: *mut c_void, ) -> i32; - pub fn sceKernelCancelMsgPipe( - uid: SceUid, - send: *mut i32, - recv: *mut i32, - ) -> i32; - pub fn sceKernelReferMsgPipeStatus( - uid: SceUid, - info: *mut SceKernelMppInfo, - ) -> i32; + pub fn sceKernelCancelMsgPipe(uid: SceUid, send: *mut i32, recv: *mut i32) -> i32; + pub fn sceKernelReferMsgPipeStatus(uid: SceUid, info: *mut SceKernelMppInfo) -> i32; pub fn sceKernelCreateVpl( name: *const u8, part: i32, @@ -3288,17 +3115,10 @@ extern "C" { data: *mut *mut c_void, timeout: *mut u32, ) -> i32; - pub fn sceKernelTryAllocateVpl( - uid: SceUid, - size: u32, - data: *mut *mut c_void, - ) -> i32; + pub fn sceKernelTryAllocateVpl(uid: SceUid, size: u32, data: *mut *mut c_void) -> i32; pub fn sceKernelFreeVpl(uid: SceUid, data: *mut c_void) -> i32; pub fn sceKernelCancelVpl(uid: SceUid, num: *mut i32) -> i32; - pub fn sceKernelReferVplStatus( - uid: SceUid, - info: *mut SceKernelVplInfo, - ) -> i32; + pub fn sceKernelReferVplStatus(uid: SceUid, info: *mut SceKernelVplInfo) -> i32; pub fn sceKernelCreateFpl( name: *const u8, part: i32, @@ -3308,61 +3128,30 @@ extern "C" { opt: *mut SceKernelFplOptParam, ) -> i32; pub fn sceKernelDeleteFpl(uid: SceUid) -> i32; - pub fn sceKernelAllocateFpl( - uid: SceUid, - data: *mut *mut c_void, - timeout: *mut u32, - ) -> i32; - pub fn sceKernelAllocateFplCB( - uid: SceUid, - data: *mut *mut c_void, - timeout: *mut u32, - ) -> i32; - pub fn sceKernelTryAllocateFpl(uid: SceUid, data: *mut *mut c_void) - -> i32; + pub fn sceKernelAllocateFpl(uid: SceUid, data: *mut *mut c_void, timeout: *mut u32) -> i32; + pub fn sceKernelAllocateFplCB(uid: SceUid, data: *mut *mut c_void, timeout: *mut u32) -> i32; + pub fn sceKernelTryAllocateFpl(uid: SceUid, data: *mut *mut c_void) -> i32; pub fn sceKernelFreeFpl(uid: SceUid, data: *mut c_void) -> i32; pub fn sceKernelCancelFpl(uid: SceUid, pnum: *mut i32) -> i32; - pub fn sceKernelReferFplStatus( - uid: SceUid, - info: *mut SceKernelFplInfo, - ) -> i32; - pub fn sceKernelUSec2SysClock( - usec: u32, - clock: *mut SceKernelSysClock, - ) -> i32; + pub fn sceKernelReferFplStatus(uid: SceUid, info: *mut SceKernelFplInfo) -> i32; + pub fn sceKernelUSec2SysClock(usec: u32, clock: *mut SceKernelSysClock) -> i32; pub fn sceKernelUSec2SysClockWide(usec: u32) -> i64; pub fn sceKernelSysClock2USec( clock: *mut SceKernelSysClock, low: *mut u32, high: *mut u32, ) -> i32; - pub fn sceKernelSysClock2USecWide( - clock: i64, - low: *mut u32, - high: *mut u32, - ) -> i32; + pub fn sceKernelSysClock2USecWide(clock: i64, low: *mut u32, high: *mut u32) -> i32; pub fn sceKernelGetSystemTime(time: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetSystemTimeWide() -> i64; pub fn sceKernelGetSystemTimeLow() -> u32; - pub fn sceKernelCreateVTimer( - name: *const u8, - opt: *mut SceKernelVTimerOptParam, - ) -> SceUid; + pub fn sceKernelCreateVTimer(name: *const u8, opt: *mut SceKernelVTimerOptParam) -> SceUid; pub fn sceKernelDeleteVTimer(uid: SceUid) -> i32; - pub fn sceKernelGetVTimerBase( - uid: SceUid, - base: *mut SceKernelSysClock, - ) -> i32; + pub fn sceKernelGetVTimerBase(uid: SceUid, base: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetVTimerBaseWide(uid: SceUid) -> i64; - pub fn sceKernelGetVTimerTime( - uid: SceUid, - time: *mut SceKernelSysClock, - ) -> i32; + pub fn sceKernelGetVTimerTime(uid: SceUid, time: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetVTimerTimeWide(uid: SceUid) -> i64; - pub fn sceKernelSetVTimerTime( - uid: SceUid, - time: *mut SceKernelSysClock, - ) -> i32; + pub fn sceKernelSetVTimerTime(uid: SceUid, time: *mut SceKernelSysClock) -> i32; pub fn sceKernelSetVTimerTimeWide(uid: SceUid, time: i64) -> i64; pub fn sceKernelStartVTimer(uid: SceUid) -> i32; pub fn sceKernelStopVTimer(uid: SceUid) -> i32; @@ -3379,10 +3168,7 @@ extern "C" { common: *mut c_void, ) -> i32; pub fn sceKernelCancelVTimerHandler(uid: SceUid) -> i32; - pub fn sceKernelReferVTimerStatus( - uid: SceUid, - info: *mut SceKernelVTimerInfo, - ) -> i32; + pub fn sceKernelReferVTimerStatus(uid: SceUid, info: *mut SceKernelVTimerInfo) -> i32; pub fn sceKernelRegisterThreadEventHandler( name: *const u8, thread_id: SceUid, @@ -3398,16 +3184,8 @@ extern "C" { pub fn sceKernelReferThreadProfiler() -> *mut DebugProfilerRegs; pub fn sceKernelReferGlobalProfiler() -> *mut DebugProfilerRegs; - pub fn sceUsbStart( - driver_name: *const u8, - size: i32, - args: *mut c_void, - ) -> i32; - pub fn sceUsbStop( - driver_name: *const u8, - size: i32, - args: *mut c_void, - ) -> i32; + pub fn sceUsbStart(driver_name: *const u8, size: i32, args: *mut c_void) -> i32; + pub fn sceUsbStop(driver_name: *const u8, size: i32, args: *mut c_void) -> i32; pub fn sceUsbActivate(pid: u32) -> i32; pub fn sceUsbDeactivate(pid: u32) -> i32; pub fn sceUsbGetState() -> i32; @@ -3452,9 +3230,7 @@ extern "C" { pub fn sceUsbCamGetBrightness(brightness: *mut i32) -> i32; pub fn sceUsbCamGetContrast(contrast: *mut i32) -> i32; pub fn sceUsbCamGetSharpness(sharpness: *mut i32) -> i32; - pub fn sceUsbCamGetImageEffectMode( - effect_mode: *mut UsbCamEffectMode, - ) -> i32; + pub fn sceUsbCamGetImageEffectMode(effect_mode: *mut UsbCamEffectMode) -> i32; pub fn sceUsbCamGetEvLevel(exposure_level: *mut UsbCamEvLevel) -> i32; pub fn sceUsbCamGetReverseMode(reverse_flags: *mut i32) -> i32; pub fn sceUsbCamGetZoom(zoom: *mut i32) -> i32; @@ -3486,11 +3262,7 @@ extern "C" { pub fn scePowerGetBusClockFrequency() -> i32; pub fn scePowerGetBusClockFrequencyInt() -> i32; pub fn scePowerGetBusClockFrequencyFloat() -> f32; - pub fn scePowerSetClockFrequency( - pllfreq: i32, - cpufreq: i32, - busfreq: i32, - ) -> i32; + pub fn scePowerSetClockFrequency(pllfreq: i32, cpufreq: i32, busfreq: i32) -> i32; pub fn scePowerLock(unknown: i32) -> i32; pub fn scePowerUnlock(unknown: i32) -> i32; pub fn scePowerTick(t: PowerTick) -> i32; @@ -3511,14 +3283,8 @@ extern "C" { pub fn sceRtcGetCurrentTick(tick: *mut u64) -> i32; pub fn sceRtcGetCurrentClock(tm: *mut ScePspDateTime, tz: i32) -> i32; pub fn sceRtcGetCurrentClockLocalTime(tm: *mut ScePspDateTime) -> i32; - pub fn sceRtcConvertUtcToLocalTime( - tick_utc: *const u64, - tick_local: *mut u64, - ) -> i32; - pub fn sceRtcConvertLocalTimeToUTC( - tick_local: *const u64, - tick_utc: *mut u64, - ) -> i32; + pub fn sceRtcConvertUtcToLocalTime(tick_utc: *const u64, tick_local: *mut u64) -> i32; + pub fn sceRtcConvertLocalTimeToUTC(tick_local: *const u64, tick_utc: *mut u64) -> i32; pub fn sceRtcIsLeapYear(year: i32) -> i32; pub fn sceRtcGetDaysInMonth(year: i32, month: i32) -> i32; pub fn sceRtcGetDayOfWeek(year: i32, month: i32, day: i32) -> i32; @@ -3526,106 +3292,43 @@ extern "C" { pub fn sceRtcSetTick(date: *mut ScePspDateTime, tick: *const u64) -> i32; pub fn sceRtcGetTick(date: *const ScePspDateTime, tick: *mut u64) -> i32; pub fn sceRtcCompareTick(tick1: *const u64, tick2: *const u64) -> i32; - pub fn sceRtcTickAddTicks( - dest_tick: *mut u64, - src_tick: *const u64, - num_ticks: u64, - ) -> i32; - pub fn sceRtcTickAddMicroseconds( - dest_tick: *mut u64, - src_tick: *const u64, - num_ms: u64, - ) -> i32; - pub fn sceRtcTickAddSeconds( - dest_tick: *mut u64, - src_tick: *const u64, - num_seconds: u64, - ) -> i32; - pub fn sceRtcTickAddMinutes( - dest_tick: *mut u64, - src_tick: *const u64, - num_minutes: u64, - ) -> i32; - pub fn sceRtcTickAddHours( - dest_tick: *mut u64, - src_tick: *const u64, - num_hours: u64, - ) -> i32; - pub fn sceRtcTickAddDays( - dest_tick: *mut u64, - src_tick: *const u64, - num_days: u64, - ) -> i32; - pub fn sceRtcTickAddWeeks( - dest_tick: *mut u64, - src_tick: *const u64, - num_weeks: u64, - ) -> i32; - pub fn sceRtcTickAddMonths( - dest_tick: *mut u64, - src_tick: *const u64, - num_months: u64, - ) -> i32; - pub fn sceRtcTickAddYears( - dest_tick: *mut u64, - src_tick: *const u64, - num_years: u64, - ) -> i32; - pub fn sceRtcSetTime_t(date: *mut ScePspDateTime, time: u32) -> i32; - pub fn sceRtcGetTime_t(date: *const ScePspDateTime, time: *mut u32) + pub fn sceRtcTickAddTicks(dest_tick: *mut u64, src_tick: *const u64, num_ticks: u64) -> i32; + pub fn sceRtcTickAddMicroseconds(dest_tick: *mut u64, src_tick: *const u64, num_ms: u64) + -> i32; + pub fn sceRtcTickAddSeconds(dest_tick: *mut u64, src_tick: *const u64, num_seconds: u64) + -> i32; + pub fn sceRtcTickAddMinutes(dest_tick: *mut u64, src_tick: *const u64, num_minutes: u64) -> i32; + pub fn sceRtcTickAddHours(dest_tick: *mut u64, src_tick: *const u64, num_hours: u64) -> i32; + pub fn sceRtcTickAddDays(dest_tick: *mut u64, src_tick: *const u64, num_days: u64) -> i32; + pub fn sceRtcTickAddWeeks(dest_tick: *mut u64, src_tick: *const u64, num_weeks: u64) -> i32; + pub fn sceRtcTickAddMonths(dest_tick: *mut u64, src_tick: *const u64, num_months: u64) -> i32; + pub fn sceRtcTickAddYears(dest_tick: *mut u64, src_tick: *const u64, num_years: u64) -> i32; + pub fn sceRtcSetTime_t(date: *mut ScePspDateTime, time: u32) -> i32; + pub fn sceRtcGetTime_t(date: *const ScePspDateTime, time: *mut u32) -> i32; pub fn sceRtcSetTime64_t(date: *mut ScePspDateTime, time: u64) -> i32; - pub fn sceRtcGetTime64_t( - date: *const ScePspDateTime, - time: *mut u64, - ) -> i32; + pub fn sceRtcGetTime64_t(date: *const ScePspDateTime, time: *mut u64) -> i32; pub fn sceRtcSetDosTime(date: *mut ScePspDateTime, dos_time: u32) -> i32; pub fn sceRtcGetDosTime(date: *mut ScePspDateTime, dos_time: u32) -> i32; - pub fn sceRtcSetWin32FileTime( - date: *mut ScePspDateTime, - time: *mut u64, - ) -> i32; - pub fn sceRtcGetWin32FileTime( - date: *mut ScePspDateTime, - time: *mut u64, - ) -> i32; - pub fn sceRtcParseDateTime( - dest_tick: *mut u64, - date_string: *const u8, - ) -> i32; + pub fn sceRtcSetWin32FileTime(date: *mut ScePspDateTime, time: *mut u64) -> i32; + pub fn sceRtcGetWin32FileTime(date: *mut ScePspDateTime, time: *mut u64) -> i32; + pub fn sceRtcParseDateTime(dest_tick: *mut u64, date_string: *const u8) -> i32; pub fn sceRtcFormatRFC3339( psz_date_time: *mut char, p_utc: *const u64, time_zone_minutes: i32, ) -> i32; - pub fn sceRtcFormatRFC3339LocalTime( - psz_date_time: *mut char, - p_utc: *const u64, - ) -> i32; - pub fn sceRtcParseRFC3339( - p_utc: *mut u64, - psz_date_time: *const u8, - ) -> i32; + pub fn sceRtcFormatRFC3339LocalTime(psz_date_time: *mut char, p_utc: *const u64) -> i32; + pub fn sceRtcParseRFC3339(p_utc: *mut u64, psz_date_time: *const u8) -> i32; pub fn sceRtcFormatRFC2822( psz_date_time: *mut char, p_utc: *const u64, time_zone_minutes: i32, ) -> i32; - pub fn sceRtcFormatRFC2822LocalTime( - psz_date_time: *mut char, - p_utc: *const u64, - ) -> i32; + pub fn sceRtcFormatRFC2822LocalTime(psz_date_time: *mut char, p_utc: *const u64) -> i32; - pub fn sceIoOpen( - file: *const u8, - flags: i32, - permissions: IoPermissions, - ) -> SceUid; - pub fn sceIoOpenAsync( - file: *const u8, - flags: i32, - permissions: IoPermissions, - ) -> SceUid; + pub fn sceIoOpen(file: *const u8, flags: i32, permissions: IoPermissions) -> SceUid; + pub fn sceIoOpenAsync(file: *const u8, flags: i32, permissions: IoPermissions) -> SceUid; pub fn sceIoClose(fd: SceUid) -> i32; pub fn sceIoCloseAsync(fd: SceUid) -> i32; pub fn sceIoRead(fd: SceUid, data: *mut c_void, size: u32) -> i32; @@ -3635,8 +3338,7 @@ extern "C" { pub fn sceIoLseek(fd: SceUid, offset: i64, whence: IoWhence) -> i64; pub fn sceIoLseekAsync(fd: SceUid, offset: i64, whence: IoWhence) -> i32; pub fn sceIoLseek32(fd: SceUid, offset: i32, whence: IoWhence) -> i32; - pub fn sceIoLseek32Async(fd: SceUid, offset: i32, whence: IoWhence) - -> i32; + pub fn sceIoLseek32Async(fd: SceUid, offset: i32, whence: IoWhence) -> i32; pub fn sceIoRemove(file: *const u8) -> i32; pub fn sceIoMkdir(dir: *const u8, mode: IoPermissions) -> i32; pub fn sceIoRmdir(path: *const u8) -> i32; @@ -3663,11 +3365,7 @@ extern "C" { ) -> i32; pub fn sceIoUnassign(dev: *const u8) -> i32; pub fn sceIoGetstat(file: *const u8, stat: *mut SceIoStat) -> i32; - pub fn sceIoChstat( - file: *const u8, - stat: *mut SceIoStat, - bits: i32, - ) -> i32; + pub fn sceIoChstat(file: *const u8, stat: *mut SceIoStat, bits: i32) -> i32; pub fn sceIoIoctl( fd: SceUid, cmd: u32, @@ -3692,22 +3390,13 @@ extern "C" { pub fn sceIoCancel(fd: SceUid) -> i32; pub fn sceIoGetDevType(fd: SceUid) -> i32; pub fn sceIoChangeAsyncPriority(fd: SceUid, pri: i32) -> i32; - pub fn sceIoSetAsyncCallback( - fd: SceUid, - cb: SceUid, - argp: *mut c_void, - ) -> i32; + pub fn sceIoSetAsyncCallback(fd: SceUid, cb: SceUid, argp: *mut c_void) -> i32; pub fn sceJpegInitMJpeg() -> i32; pub fn sceJpegFinishMJpeg() -> i32; pub fn sceJpegCreateMJpeg(width: i32, height: i32) -> i32; pub fn sceJpegDeleteMJpeg() -> i32; - pub fn sceJpegDecodeMJpeg( - jpeg_buf: *mut u8, - size: usize, - rgba: *mut c_void, - unk: u32, - ) -> i32; + pub fn sceJpegDecodeMJpeg(jpeg_buf: *mut u8, size: usize, rgba: *mut c_void, unk: u32) -> i32; pub fn sceUmdCheckMedium() -> i32; pub fn sceUmdGetDiscInfo(info: *mut UmdInfo) -> i32; @@ -3736,9 +3425,7 @@ extern "C" { cb_param: *mut c_void, ) -> i32; pub fn sceMpegRingbufferDestruct(ringbuffer: *mut SceMpegRingbuffer); - pub fn sceMpegRingbufferAvailableSize( - ringbuffer: *mut SceMpegRingbuffer, - ) -> i32; + pub fn sceMpegRingbufferAvailableSize(ringbuffer: *mut SceMpegRingbuffer) -> i32; pub fn sceMpegRingbufferPut( ringbuffer: *mut SceMpegRingbuffer, num_packets: i32, @@ -3755,41 +3442,22 @@ extern "C" { unk2: i32, ) -> i32; pub fn sceMpegDelete(handle: SceMpeg); - pub fn sceMpegQueryStreamOffset( - handle: SceMpeg, - buffer: *mut c_void, - offset: *mut i32, - ) -> i32; + pub fn sceMpegQueryStreamOffset(handle: SceMpeg, buffer: *mut c_void, offset: *mut i32) -> i32; pub fn sceMpegQueryStreamSize(buffer: *mut c_void, size: *mut i32) -> i32; - pub fn sceMpegRegistStream( - handle: SceMpeg, - stream_id: i32, - unk: i32, - ) -> SceMpegStream; + pub fn sceMpegRegistStream(handle: SceMpeg, stream_id: i32, unk: i32) -> SceMpegStream; pub fn sceMpegUnRegistStream(handle: SceMpeg, stream: SceMpegStream); pub fn sceMpegFlushAllStream(handle: SceMpeg) -> i32; pub fn sceMpegMallocAvcEsBuf(handle: SceMpeg) -> *mut c_void; pub fn sceMpegFreeAvcEsBuf(handle: SceMpeg, buf: *mut c_void); - pub fn sceMpegQueryAtracEsSize( - handle: SceMpeg, - es_size: *mut i32, - out_size: *mut i32, - ) -> i32; - pub fn sceMpegInitAu( - handle: SceMpeg, - es_buffer: *mut c_void, - au: *mut SceMpegAu, - ) -> i32; + pub fn sceMpegQueryAtracEsSize(handle: SceMpeg, es_size: *mut i32, out_size: *mut i32) -> i32; + pub fn sceMpegInitAu(handle: SceMpeg, es_buffer: *mut c_void, au: *mut SceMpegAu) -> i32; pub fn sceMpegGetAvcAu( handle: SceMpeg, stream: SceMpegStream, au: *mut SceMpegAu, unk: *mut i32, ) -> i32; - pub fn sceMpegAvcDecodeMode( - handle: SceMpeg, - mode: *mut SceMpegAvcMode, - ) -> i32; + pub fn sceMpegAvcDecodeMode(handle: SceMpeg, mode: *mut SceMpegAvcMode) -> i32; pub fn sceMpegAvcDecode( handle: SceMpeg, au: *mut SceMpegAu, @@ -3816,11 +3484,7 @@ extern "C" { init: i32, ) -> i32; - pub fn sceMpegBaseYCrCbCopyVme( - yuv_buffer: *mut c_void, - buffer: *mut i32, - type_: i32, - ) -> i32; + pub fn sceMpegBaseYCrCbCopyVme(yuv_buffer: *mut c_void, buffer: *mut i32, type_: i32) -> i32; pub fn sceMpegBaseCscInit(width: i32) -> i32; pub fn sceMpegBaseCscVme( rgb_buffer: *mut c_void, @@ -3838,22 +3502,9 @@ extern "C" { pub fn sceHprmIsMicrophoneExist() -> i32; pub fn sceGuDepthBuffer(zbp: *mut c_void, zbw: i32); - pub fn sceGuDispBuffer( - width: i32, - height: i32, - dispbp: *mut c_void, - dispbw: i32, - ); - pub fn sceGuDrawBuffer( - psm: DisplayPixelFormat, - fbp: *mut c_void, - fbw: i32, - ); - pub fn sceGuDrawBufferList( - psm: DisplayPixelFormat, - fbp: *mut c_void, - fbw: i32, - ); + pub fn sceGuDispBuffer(width: i32, height: i32, dispbp: *mut c_void, dispbw: i32); + pub fn sceGuDrawBuffer(psm: DisplayPixelFormat, fbp: *mut c_void, fbw: i32); + pub fn sceGuDrawBufferList(psm: DisplayPixelFormat, fbp: *mut c_void, fbw: i32); pub fn sceGuDisplay(state: bool) -> bool; pub fn sceGuDepthFunc(function: DepthFunc); pub fn sceGuDepthMask(mask: i32); @@ -3864,10 +3515,7 @@ extern "C" { pub fn sceGuTerm(); pub fn sceGuBreak(mode: i32); pub fn sceGuContinue(); - pub fn sceGuSetCallback( - signal: GuCallbackId, - callback: GuCallback, - ) -> GuCallback; + pub fn sceGuSetCallback(signal: GuCallbackId, callback: GuCallback) -> GuCallback; pub fn sceGuSignal(behavior: SignalBehavior, signal: i32); pub fn sceGuSendCommandf(cmd: GeCommand, argument: f32); pub fn sceGuSendCommandi(cmd: GeCommand, argument: i32); @@ -3878,16 +3526,9 @@ extern "C" { pub fn sceGuCallList(list: *const c_void); pub fn sceGuCallMode(mode: i32); pub fn sceGuCheckList() -> i32; - pub fn sceGuSendList( - mode: GuQueueMode, - list: *const c_void, - context: *mut GeContext, - ); + pub fn sceGuSendList(mode: GuQueueMode, list: *const c_void, context: *mut GeContext); pub fn sceGuSwapBuffers() -> *mut c_void; - pub fn sceGuSync( - mode: GuSyncMode, - behavior: GuSyncBehavior, - ) -> GeListState; + pub fn sceGuSync(mode: GuSyncMode, behavior: GuSyncBehavior) -> GeListState; pub fn sceGuDrawArray( prim: GuPrimitive, vtype: i32, @@ -3908,21 +3549,11 @@ extern "C" { pub fn sceGuGetAllStatus() -> i32; pub fn sceGuEnable(state: GuState); pub fn sceGuDisable(state: GuState); - pub fn sceGuLight( - light: i32, - type_: LightType, - components: i32, - position: &ScePspFVector3, - ); + pub fn sceGuLight(light: i32, type_: LightType, components: i32, position: &ScePspFVector3); pub fn sceGuLightAtt(light: i32, atten0: f32, atten1: f32, atten2: f32); pub fn sceGuLightColor(light: i32, component: i32, color: u32); pub fn sceGuLightMode(mode: LightMode); - pub fn sceGuLightSpot( - light: i32, - direction: &ScePspFVector3, - exponent: f32, - cutoff: f32, - ); + pub fn sceGuLightSpot(light: i32, direction: &ScePspFVector3, exponent: f32, cutoff: f32); pub fn sceGuClear(flags: i32); pub fn sceGuClearColor(color: u32); pub fn sceGuClearDepth(depth: u32); @@ -3934,26 +3565,11 @@ extern "C" { pub fn sceGuAlphaFunc(func: AlphaFunc, value: i32, mask: i32); pub fn sceGuAmbient(color: u32); pub fn sceGuAmbientColor(color: u32); - pub fn sceGuBlendFunc( - op: BlendOp, - src: BlendSrc, - dest: BlendDst, - src_fix: u32, - dest_fix: u32, - ); + pub fn sceGuBlendFunc(op: BlendOp, src: BlendSrc, dest: BlendDst, src_fix: u32, dest_fix: u32); pub fn sceGuMaterial(components: i32, color: u32); - pub fn sceGuModelColor( - emissive: u32, - ambient: u32, - diffuse: u32, - specular: u32, - ); + pub fn sceGuModelColor(emissive: u32, ambient: u32, diffuse: u32, specular: u32); pub fn sceGuStencilFunc(func: StencilFunc, ref_: i32, mask: i32); - pub fn sceGuStencilOp( - fail: StencilOperation, - zfail: StencilOperation, - zpass: StencilOperation, - ); + pub fn sceGuStencilOp(fail: StencilOperation, zfail: StencilOperation, zpass: StencilOperation); pub fn sceGuSpecular(power: f32); pub fn sceGuFrontFace(order: FrontFaceDirection); pub fn sceGuLogicalOp(op: LogicalOperation); @@ -3985,12 +3601,7 @@ extern "C" { ); pub fn sceGuTexLevelMode(mode: TextureLevelMode, bias: f32); pub fn sceGuTexMapMode(mode: TextureMapMode, a1: u32, a2: u32); - pub fn sceGuTexMode( - tpsm: TexturePixelFormat, - maxmips: i32, - a2: i32, - swizzle: i32, - ); + pub fn sceGuTexMode(tpsm: TexturePixelFormat, maxmips: i32, a2: i32, swizzle: i32); pub fn sceGuTexOffset(u: f32, v: f32); pub fn sceGuTexProjMapMode(mode: TextureProjectionMapMode); pub fn sceGuTexScale(u: f32, v: f32); @@ -3998,12 +3609,7 @@ extern "C" { pub fn sceGuTexSync(); pub fn sceGuTexWrap(u: GuTexWrapMode, v: GuTexWrapMode); pub fn sceGuClutLoad(num_blocks: i32, cbp: *const c_void); - pub fn sceGuClutMode( - cpsm: ClutPixelFormat, - shift: u32, - mask: u32, - a3: u32, - ); + pub fn sceGuClutMode(cpsm: ClutPixelFormat, shift: u32, mask: u32, a3: u32); pub fn sceGuOffset(x: u32, y: u32); pub fn sceGuScissor(x: i32, y: i32, w: i32, h: i32); pub fn sceGuViewport(cx: i32, cy: i32, width: i32, height: i32); @@ -4073,21 +3679,10 @@ extern "C" { pub fn sceGumFullInverse(); pub fn sceGumLoadIdentity(); pub fn sceGumLoadMatrix(m: &ScePspFMatrix4); - pub fn sceGumLookAt( - eye: &ScePspFVector3, - center: &ScePspFVector3, - up: &ScePspFVector3, - ); + pub fn sceGumLookAt(eye: &ScePspFVector3, center: &ScePspFVector3, up: &ScePspFVector3); pub fn sceGumMatrixMode(mode: MatrixMode); pub fn sceGumMultMatrix(m: &ScePspFMatrix4); - pub fn sceGumOrtho( - left: f32, - right: f32, - bottom: f32, - top: f32, - near: f32, - far: f32, - ); + pub fn sceGumOrtho(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32); pub fn sceGumPerspective(fovy: f32, aspect: f32, near: f32, far: f32); pub fn sceGumPopMatrix(); pub fn sceGumPushMatrix(); @@ -4124,11 +3719,7 @@ extern "C" { pub fn sceMp3GetMp3ChannelNum(handle: Mp3Handle) -> i32; pub fn sceMp3ResetPlayPosition(handle: Mp3Handle) -> i32; - pub fn sceRegOpenRegistry( - reg: *mut Key, - mode: i32, - handle: *mut RegHandle, - ) -> i32; + pub fn sceRegOpenRegistry(reg: *mut Key, mode: i32, handle: *mut RegHandle) -> i32; pub fn sceRegFlushRegistry(handle: RegHandle) -> i32; pub fn sceRegCloseRegistry(handle: RegHandle) -> i32; pub fn sceRegOpenCategory( @@ -4172,21 +3763,13 @@ extern "C" { size: usize, ) -> i32; pub fn sceRegGetKeysNum(dir_handle: RegHandle, num: *mut i32) -> i32; - pub fn sceRegGetKeys(dir_handle: RegHandle, buf: *mut u8, num: i32) - -> i32; - pub fn sceRegCreateKey( - dir_handle: RegHandle, - name: *const u8, - type_: i32, - size: usize, - ) -> i32; + pub fn sceRegGetKeys(dir_handle: RegHandle, buf: *mut u8, num: i32) -> i32; + pub fn sceRegCreateKey(dir_handle: RegHandle, name: *const u8, type_: i32, size: usize) -> i32; pub fn sceRegRemoveRegistry(key: *mut Key) -> i32; pub fn sceOpenPSIDGetOpenPSID(openpsid: *mut OpenPSID) -> i32; - pub fn sceUtilityMsgDialogInitStart( - params: *mut UtilityMsgDialogParams, - ) -> i32; + pub fn sceUtilityMsgDialogInitStart(params: *mut UtilityMsgDialogParams) -> i32; pub fn sceUtilityMsgDialogShutdownStart(); pub fn sceUtilityMsgDialogGetStatus() -> i32; pub fn sceUtilityMsgDialogUpdate(n: i32); @@ -4196,43 +3779,23 @@ extern "C" { pub fn sceUtilityNetconfUpdate(unknown: i32) -> i32; pub fn sceUtilityNetconfGetStatus() -> i32; pub fn sceUtilityCheckNetParam(id: i32) -> i32; - pub fn sceUtilityGetNetParam( - conf: i32, - param: NetParam, - data: *mut UtilityNetData, - ) -> i32; - pub fn sceUtilitySavedataInitStart( - params: *mut SceUtilitySavedataParam, - ) -> i32; + pub fn sceUtilityGetNetParam(conf: i32, param: NetParam, data: *mut UtilityNetData) -> i32; + pub fn sceUtilitySavedataInitStart(params: *mut SceUtilitySavedataParam) -> i32; pub fn sceUtilitySavedataGetStatus() -> i32; pub fn sceUtilitySavedataShutdownStart() -> i32; pub fn sceUtilitySavedataUpdate(unknown: i32); - pub fn sceUtilityGameSharingInitStart( - params: *mut UtilityGameSharingParams, - ) -> i32; + pub fn sceUtilityGameSharingInitStart(params: *mut UtilityGameSharingParams) -> i32; pub fn sceUtilityGameSharingShutdownStart(); pub fn sceUtilityGameSharingGetStatus() -> i32; pub fn sceUtilityGameSharingUpdate(n: i32); - pub fn sceUtilityHtmlViewerInitStart( - params: *mut UtilityHtmlViewerParam, - ) -> i32; + pub fn sceUtilityHtmlViewerInitStart(params: *mut UtilityHtmlViewerParam) -> i32; pub fn sceUtilityHtmlViewerShutdownStart() -> i32; pub fn sceUtilityHtmlViewerUpdate(n: i32) -> i32; pub fn sceUtilityHtmlViewerGetStatus() -> i32; pub fn sceUtilitySetSystemParamInt(id: SystemParamId, value: i32) -> i32; - pub fn sceUtilitySetSystemParamString( - id: SystemParamId, - str: *const u8, - ) -> i32; - pub fn sceUtilityGetSystemParamInt( - id: SystemParamId, - value: *mut i32, - ) -> i32; - pub fn sceUtilityGetSystemParamString( - id: SystemParamId, - str: *mut u8, - len: i32, - ) -> i32; + pub fn sceUtilitySetSystemParamString(id: SystemParamId, str: *const u8) -> i32; + pub fn sceUtilityGetSystemParamInt(id: SystemParamId, value: *mut i32) -> i32; + pub fn sceUtilityGetSystemParamString(id: SystemParamId, str: *mut u8, len: i32) -> i32; pub fn sceUtilityOskInitStart(params: *mut SceUtilityOskParams) -> i32; pub fn sceUtilityOskShutdownStart() -> i32; pub fn sceUtilityOskUpdate(n: i32) -> i32; @@ -4291,48 +3854,29 @@ extern "C" { timeout: u32, unknown: i32, ) -> i32; - pub fn sceNetAdhocctlGetGameModeInfo( - gamemodeinfo: *mut SceNetAdhocctlGameModeInfo, - ) -> i32; + pub fn sceNetAdhocctlGetGameModeInfo(gamemodeinfo: *mut SceNetAdhocctlGameModeInfo) -> i32; pub fn sceNetAdhocctlExitGameMode() -> i32; - pub fn sceNetAdhocctlGetPeerList( - length: *mut i32, - buf: *mut c_void, - ) -> i32; + pub fn sceNetAdhocctlGetPeerList(length: *mut i32, buf: *mut c_void) -> i32; pub fn sceNetAdhocctlGetPeerInfo( mac: *mut u8, size: i32, peerinfo: *mut SceNetAdhocctlPeerInfo, ) -> i32; pub fn sceNetAdhocctlScan() -> i32; - pub fn sceNetAdhocctlGetScanInfo( - length: *mut i32, - buf: *mut c_void, - ) -> i32; - pub fn sceNetAdhocctlAddHandler( - handler: SceNetAdhocctlHandler, - unknown: *mut c_void, - ) -> i32; + pub fn sceNetAdhocctlGetScanInfo(length: *mut i32, buf: *mut c_void) -> i32; + pub fn sceNetAdhocctlAddHandler(handler: SceNetAdhocctlHandler, unknown: *mut c_void) -> i32; pub fn sceNetAdhocctlDelHandler(id: i32) -> i32; - pub fn sceNetAdhocctlGetNameByAddr(mac: *mut u8, nickname: *mut u8) - -> i32; + pub fn sceNetAdhocctlGetNameByAddr(mac: *mut u8, nickname: *mut u8) -> i32; pub fn sceNetAdhocctlGetAddrByName( nickname: *mut u8, length: *mut i32, buf: *mut c_void, ) -> i32; - pub fn sceNetAdhocctlGetParameter( - params: *mut SceNetAdhocctlParams, - ) -> i32; + pub fn sceNetAdhocctlGetParameter(params: *mut SceNetAdhocctlParams) -> i32; pub fn sceNetAdhocInit() -> i32; pub fn sceNetAdhocTerm() -> i32; - pub fn sceNetAdhocPdpCreate( - mac: *mut u8, - port: u16, - buf_size: u32, - unk1: i32, - ) -> i32; + pub fn sceNetAdhocPdpCreate(mac: *mut u8, port: u16, buf_size: u32, unk1: i32) -> i32; pub fn sceNetAdhocPdpDelete(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocPdpSend( id: i32, @@ -4352,19 +3896,9 @@ extern "C" { timeout: u32, nonblock: i32, ) -> i32; - pub fn sceNetAdhocGetPdpStat( - size: *mut i32, - stat: *mut SceNetAdhocPdpStat, - ) -> i32; - pub fn sceNetAdhocGameModeCreateMaster( - data: *mut c_void, - size: i32, - ) -> i32; - pub fn sceNetAdhocGameModeCreateReplica( - mac: *mut u8, - data: *mut c_void, - size: i32, - ) -> i32; + pub fn sceNetAdhocGetPdpStat(size: *mut i32, stat: *mut SceNetAdhocPdpStat) -> i32; + pub fn sceNetAdhocGameModeCreateMaster(data: *mut c_void, size: i32) -> i32; + pub fn sceNetAdhocGameModeCreateReplica(mac: *mut u8, data: *mut c_void, size: i32) -> i32; pub fn sceNetAdhocGameModeUpdateMaster() -> i32; pub fn sceNetAdhocGameModeUpdateReplica(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocGameModeDeleteMaster() -> i32; @@ -4412,10 +3946,7 @@ extern "C" { ) -> i32; pub fn sceNetAdhocPtpFlush(id: i32, timeout: u32, nonblock: i32) -> i32; pub fn sceNetAdhocPtpClose(id: i32, unk1: i32) -> i32; - pub fn sceNetAdhocGetPtpStat( - size: *mut i32, - stat: *mut SceNetAdhocPtpStat, - ) -> i32; + pub fn sceNetAdhocGetPtpStat(size: *mut i32, stat: *mut SceNetAdhocPtpStat) -> i32; } extern "C" { @@ -4449,10 +3980,7 @@ extern "C" { opt_len: i32, opt_data: *mut c_void, ) -> i32; - pub fn sceNetAdhocMatchingCancelTarget( - matching_id: i32, - mac: *mut u8, - ) -> i32; + pub fn sceNetAdhocMatchingCancelTarget(matching_id: i32, mac: *mut u8) -> i32; pub fn sceNetAdhocMatchingCancelTargetWithOpt( matching_id: i32, mac: *mut u8, @@ -4465,10 +3993,7 @@ extern "C" { data_len: i32, data: *mut c_void, ) -> i32; - pub fn sceNetAdhocMatchingAbortSendData( - matching_id: i32, - mac: *mut u8, - ) -> i32; + pub fn sceNetAdhocMatchingAbortSendData(matching_id: i32, mac: *mut u8) -> i32; pub fn sceNetAdhocMatchingSetHelloOpt( matching_id: i32, opt_len: i32, @@ -4485,21 +4010,14 @@ extern "C" { buf: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingGetPoolMaxAlloc() -> i32; - pub fn sceNetAdhocMatchingGetPoolStat(poolstat: *mut AdhocPoolStat) - -> i32; + pub fn sceNetAdhocMatchingGetPoolStat(poolstat: *mut AdhocPoolStat) -> i32; } extern "C" { pub fn sceNetApctlInit(stack_size: i32, init_priority: i32) -> i32; pub fn sceNetApctlTerm() -> i32; - pub fn sceNetApctlGetInfo( - code: ApctlInfo, - pinfo: *mut SceNetApctlInfo, - ) -> i32; - pub fn sceNetApctlAddHandler( - handler: SceNetApctlHandler, - parg: *mut c_void, - ) -> i32; + pub fn sceNetApctlGetInfo(code: ApctlInfo, pinfo: *mut SceNetApctlInfo) -> i32; + pub fn sceNetApctlAddHandler(handler: SceNetApctlHandler, parg: *mut c_void) -> i32; pub fn sceNetApctlDelHandler(handler_id: i32) -> i32; pub fn sceNetApctlConnect(conn_index: i32) -> i32; pub fn sceNetApctlDisconnect() -> i32; @@ -4507,21 +4025,9 @@ extern "C" { pub fn sceNetInetInit() -> i32; pub fn sceNetInetTerm() -> i32; - pub fn sceNetInetAccept( - s: i32, - addr: *mut sockaddr, - addr_len: *mut socklen_t, - ) -> i32; - pub fn sceNetInetBind( - s: i32, - my_addr: *const sockaddr, - addr_len: socklen_t, - ) -> i32; - pub fn sceNetInetConnect( - s: i32, - serv_addr: *const sockaddr, - addr_len: socklen_t, - ) -> i32; + pub fn sceNetInetAccept(s: i32, addr: *mut sockaddr, addr_len: *mut socklen_t) -> i32; + pub fn sceNetInetBind(s: i32, my_addr: *const sockaddr, addr_len: socklen_t) -> i32; + pub fn sceNetInetConnect(s: i32, serv_addr: *const sockaddr, addr_len: socklen_t) -> i32; pub fn sceNetInetGetsockopt( s: i32, level: i32, @@ -4530,12 +4036,7 @@ extern "C" { optl_en: *mut socklen_t, ) -> i32; pub fn sceNetInetListen(s: i32, backlog: i32) -> i32; - pub fn sceNetInetRecv( - s: i32, - buf: *mut c_void, - len: usize, - flags: i32, - ) -> usize; + pub fn sceNetInetRecv(s: i32, buf: *mut c_void, len: usize, flags: i32) -> usize; pub fn sceNetInetRecvfrom( s: i32, buf: *mut c_void, @@ -4544,12 +4045,7 @@ extern "C" { from: *mut sockaddr, from_len: *mut socklen_t, ) -> usize; - pub fn sceNetInetSend( - s: i32, - buf: *const c_void, - len: usize, - flags: i32, - ) -> usize; + pub fn sceNetInetSend(s: i32, buf: *const c_void, len: usize, flags: i32) -> usize; pub fn sceNetInetSendto( s: i32, buf: *const c_void, @@ -4577,11 +4073,7 @@ extern "C" { pub fn sceHttpInit(unknown1: u32) -> i32; pub fn sceHttpEnd() -> i32; - pub fn sceHttpCreateTemplate( - agent: *mut u8, - unknown1: i32, - unknown2: i32, - ) -> i32; + pub fn sceHttpCreateTemplate(agent: *mut u8, unknown1: i32, unknown2: i32) -> i32; pub fn sceHttpDeleteTemplate(templateid: i32) -> i32; pub fn sceHttpCreateConnection( templateid: i32, @@ -4590,11 +4082,7 @@ extern "C" { port: u16, unknown2: i32, ) -> i32; - pub fn sceHttpCreateConnectionWithURL( - templateid: i32, - url: *const u8, - unknown1: i32, - ) -> i32; + pub fn sceHttpCreateConnectionWithURL(templateid: i32, url: *const u8, unknown1: i32) -> i32; pub fn sceHttpDeleteConnection(connection_id: i32) -> i32; pub fn sceHttpCreateRequest( connection_id: i32, @@ -4609,23 +4097,11 @@ extern "C" { content_length: u64, ) -> i32; pub fn sceHttpDeleteRequest(request_id: i32) -> i32; - pub fn sceHttpSendRequest( - request_id: i32, - data: *mut c_void, - data_size: u32, - ) -> i32; + pub fn sceHttpSendRequest(request_id: i32, data: *mut c_void, data_size: u32) -> i32; pub fn sceHttpAbortRequest(request_id: i32) -> i32; - pub fn sceHttpReadData( - request_id: i32, - data: *mut c_void, - data_size: u32, - ) -> i32; - pub fn sceHttpGetContentLength( - request_id: i32, - content_length: *mut u64, - ) -> i32; - pub fn sceHttpGetStatusCode(request_id: i32, status_code: *mut i32) - -> i32; + pub fn sceHttpReadData(request_id: i32, data: *mut c_void, data_size: u32) -> i32; + pub fn sceHttpGetContentLength(request_id: i32, content_length: *mut u64) -> i32; + pub fn sceHttpGetStatusCode(request_id: i32, status_code: *mut i32) -> i32; pub fn sceHttpSetResolveTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpSetResolveRetry(id: i32, count: i32) -> i32; pub fn sceHttpSetConnectTimeOut(id: i32, timeout: u32) -> i32; @@ -4639,19 +4115,9 @@ extern "C" { pub fn sceHttpDisableCookie(id: i32) -> i32; pub fn sceHttpSaveSystemCookie() -> i32; pub fn sceHttpLoadSystemCookie() -> i32; - pub fn sceHttpAddExtraHeader( - id: i32, - name: *mut u8, - value: *mut u8, - unknown1: i32, - ) -> i32; + pub fn sceHttpAddExtraHeader(id: i32, name: *mut u8, value: *mut u8, unknown1: i32) -> i32; pub fn sceHttpDeleteHeader(id: i32, name: *const u8) -> i32; - pub fn sceHttpsInit( - unknown1: i32, - unknown2: i32, - unknown3: i32, - unknown4: i32, - ) -> i32; + pub fn sceHttpsInit(unknown1: i32, unknown2: i32, unknown3: i32, unknown4: i32) -> i32; pub fn sceHttpsEnd() -> i32; pub fn sceHttpsLoadDefaultCert(unknown1: i32, unknown2: i32) -> i32; pub fn sceHttpDisableAuth(id: i32) -> i32; @@ -4659,11 +4125,7 @@ extern "C" { pub fn sceHttpEnableAuth(id: i32) -> i32; pub fn sceHttpEnableCache(id: i32) -> i32; pub fn sceHttpEndCache() -> i32; - pub fn sceHttpGetAllHeader( - request: i32, - header: *mut *mut u8, - header_size: *mut u32, - ) -> i32; + pub fn sceHttpGetAllHeader(request: i32, header: *mut *mut u8, header_size: *mut u32) -> i32; pub fn sceHttpGetNetworkErrno(request: i32, err_num: *mut i32) -> i32; pub fn sceHttpGetProxy( id: i32, @@ -4690,11 +4152,7 @@ extern "C" { ) -> i32; pub fn sceNetResolverInit() -> i32; - pub fn sceNetResolverCreate( - rid: *mut i32, - buf: *mut c_void, - buf_length: u32, - ) -> i32; + pub fn sceNetResolverCreate(rid: *mut i32, buf: *mut c_void, buf_length: u32) -> i32; pub fn sceNetResolverDelete(rid: i32) -> i32; pub fn sceNetResolverStartNtoA( rid: i32, diff --git a/vendor/libc/src/unix/bsd/apple/mod.rs b/vendor/libc/src/unix/bsd/apple/mod.rs index 7f321eab46..6d77692480 100644 --- a/vendor/libc/src/unix/bsd/apple/mod.rs +++ b/vendor/libc/src/unix/bsd/apple/mod.rs @@ -26,6 +26,8 @@ pub type idtype_t = ::c_uint; pub type integer_t = ::c_int; pub type cpu_type_t = integer_t; pub type cpu_subtype_t = integer_t; +pub type natural_t = u32; +pub type mach_msg_type_number_t = natural_t; pub type posix_spawnattr_t = *mut ::c_void; pub type posix_spawn_file_actions_t = *mut ::c_void; @@ -36,9 +38,21 @@ pub type sae_associd_t = u32; pub type sae_connid_t = u32; pub type mach_port_t = ::c_uint; +pub type processor_flavor_t = ::c_int; pub type iconv_t = *mut ::c_void; +pub type processor_cpu_load_info_t = *mut processor_cpu_load_info; +pub type processor_cpu_load_info_data_t = processor_cpu_load_info; +pub type processor_basic_info_t = *mut processor_basic_info; +pub type processor_basic_info_data_t = processor_basic_info; +pub type processor_set_basic_info_data_t = processor_set_basic_info; +pub type processor_set_basic_info_t = *mut processor_set_basic_info; +pub type processor_set_load_info_data_t = processor_set_load_info; +pub type processor_set_load_info_t = *mut processor_set_load_info; +pub type processor_info_t = *mut integer_t; +pub type processor_info_array_t = *mut integer_t; + deprecated_mach! { pub type vm_prot_t = ::c_int; pub type vm_size_t = ::uintptr_t; @@ -662,6 +676,30 @@ s_no_extra_traits! { __unused1: *mut ::c_void, //actually a function pointer pub sigev_notify_attributes: *mut ::pthread_attr_t } + + pub struct processor_cpu_load_info { + pub cpu_ticks: [::c_uint; CPU_STATE_MAX as usize], + } + + pub struct processor_basic_info { + pub cpu_type: cpu_type_t, + pub cpu_subtype: cpu_subtype_t, + pub running: ::boolean_t, + pub slot_num: ::c_int, + pub is_master: ::boolean_t, + } + + pub struct processor_set_basic_info { + pub processor_count: ::c_int, + pub default_policy: ::c_int, + } + + pub struct processor_set_load_info { + pub task_count: ::c_int, + pub thread_count: ::c_int, + pub load_average: integer_t, + pub mach_factor: integer_t, + } } impl siginfo_t { @@ -1276,6 +1314,106 @@ cfg_if! { self.sigev_notify_attributes.hash(state); } } + + impl PartialEq for processor_cpu_load_info { + fn eq(&self, other: &processor_cpu_load_info) -> bool { + self.cpu_ticks == other.cpu_ticks + } + } + impl Eq for processor_cpu_load_info {} + impl ::fmt::Debug for processor_cpu_load_info { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("processor_cpu_load_info") + .field("cpu_ticks", &self.cpu_ticks) + .finish() + } + } + impl ::hash::Hash for processor_cpu_load_info { + fn hash(&self, state: &mut H) { + self.cpu_ticks.hash(state); + } + } + + impl PartialEq for processor_basic_info { + fn eq(&self, other: &processor_basic_info) -> bool { + self.cpu_type == other.cpu_type + && self.cpu_subtype == other.cpu_subtype + && self.running == other.running + && self.slot_num == other.slot_num + && self.is_master == other.is_master + } + } + impl Eq for processor_basic_info {} + impl ::fmt::Debug for processor_basic_info { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("processor_basic_info") + .field("cpu_type", &self.cpu_type) + .field("cpu_subtype", &self.cpu_subtype) + .field("running", &self.running) + .field("slot_num", &self.slot_num) + .field("is_master", &self.is_master) + .finish() + } + } + impl ::hash::Hash for processor_basic_info { + fn hash(&self, state: &mut H) { + self.cpu_type.hash(state); + self.cpu_subtype.hash(state); + self.running.hash(state); + self.slot_num.hash(state); + self.is_master.hash(state); + } + } + + impl PartialEq for processor_set_basic_info { + fn eq(&self, other: &processor_set_basic_info) -> bool { + self.processor_count == other.processor_count + && self.default_policy == other.default_policy + } + } + impl Eq for processor_set_basic_info {} + impl ::fmt::Debug for processor_set_basic_info { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("processor_set_basic_info") + .field("processor_count", &self.processor_count) + .field("default_policy", &self.default_policy) + .finish() + } + } + impl ::hash::Hash for processor_set_basic_info { + fn hash(&self, state: &mut H) { + self.processor_count.hash(state); + self.default_policy.hash(state); + } + } + + impl PartialEq for processor_set_load_info { + fn eq(&self, other: &processor_set_load_info) -> bool { + self.task_count == other.task_count + && self.thread_count == other.thread_count + && self.load_average == other.load_average + && self.mach_factor == other.mach_factor + } + } + impl Eq for processor_set_load_info {} + impl ::fmt::Debug for processor_set_load_info { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("processor_set_load_info") + .field("task_count", &self.task_count) + .field("thread_count", &self.thread_count) + .field("load_average", &self.load_average) + .field("mach_factor", &self.mach_factor) + .finish() + } + } + impl ::hash::Hash for processor_set_load_info { + fn hash(&self, state: &mut H) { + self.task_count.hash(state); + self.thread_count.hash(state); + self.load_average.hash(state); + self.mach_factor.hash(state); + } + } } } @@ -1495,6 +1633,19 @@ pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_ANON: ::c_int = 0x1000; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; +pub const CPU_STATE_USER: ::c_int = 0; +pub const CPU_STATE_SYSTEM: ::c_int = 1; +pub const CPU_STATE_IDLE: ::c_int = 2; +pub const CPU_STATE_NICE: ::c_int = 3; +pub const CPU_STATE_MAX: ::c_int = 4; + +pub const PROCESSOR_BASIC_INFO: ::c_int = 1; +pub const PROCESSOR_CPU_LOAD_INFO: ::c_int = 2; +pub const PROCESSOR_PM_REGS_INFO: ::c_int = 0x10000001; +pub const PROCESSOR_TEMPERATURE: ::c_int = 0x10000002; +pub const PROCESSOR_SET_LOAD_INFO: ::c_int = 4; +pub const PROCESSOR_SET_BASIC_INFO: ::c_int = 5; + deprecated_mach! { pub const VM_FLAGS_FIXED: ::c_int = 0x0000; pub const VM_FLAGS_ANYWHERE: ::c_int = 0x0001; @@ -2888,11 +3039,8 @@ pub const AI_PASSIVE: ::c_int = 0x00000001; pub const AI_CANONNAME: ::c_int = 0x00000002; pub const AI_NUMERICHOST: ::c_int = 0x00000004; pub const AI_NUMERICSERV: ::c_int = 0x00001000; -pub const AI_MASK: ::c_int = AI_PASSIVE - | AI_CANONNAME - | AI_NUMERICHOST - | AI_NUMERICSERV - | AI_ADDRCONFIG; +pub const AI_MASK: ::c_int = + AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG; pub const AI_ALL: ::c_int = 0x00000100; pub const AI_V4MAPPED_CFG: ::c_int = 0x00000200; pub const AI_ADDRCONFIG: ::c_int = 0x00000400; @@ -3215,7 +3363,12 @@ pub const MNT_WAIT: ::c_int = 1; pub const MNT_NOWAIT: ::c_int = 2; cfg_if! { - if #[cfg(libc_const_size_of)] { + if #[cfg(libc_const_extern_fn)] { + const fn __DARWIN_ALIGN32(p: usize) -> usize { + const __DARWIN_ALIGNBYTES32: usize = ::mem::size_of::() - 1; + p + __DARWIN_ALIGNBYTES32 & !__DARWIN_ALIGNBYTES32 + } + } else if #[cfg(libc_const_size_of)] { fn __DARWIN_ALIGN32(p: usize) -> usize { const __DARWIN_ALIGNBYTES32: usize = ::mem::size_of::() - 1; p + __DARWIN_ALIGNBYTES32 & !__DARWIN_ALIGNBYTES32 @@ -3237,7 +3390,7 @@ f! { let cmsg_len = (*cmsg).cmsg_len as usize; let next = cmsg as usize + __DARWIN_ALIGN32(cmsg_len as usize); let max = (*mhdr).msg_control as usize - + (*mhdr).msg_controllen as usize; + + (*mhdr).msg_controllen as usize; if next + __DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) > max { 0 as *mut ::cmsghdr } else { @@ -3250,7 +3403,7 @@ f! { .offset(__DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) as isize) } - pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (__DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) + __DARWIN_ALIGN32(length as usize)) as ::c_uint @@ -3295,11 +3448,7 @@ extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated in MacOSX 10.10")] - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int; @@ -3348,11 +3497,7 @@ extern "C" { sevlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; - pub fn mincore( - addr: *const ::c_void, - len: ::size_t, - vec: *mut ::c_char, - ) -> ::c_int; + pub fn mincore(addr: *const ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; pub fn sysctlnametomib( name: *const ::c_char, mibp: *mut ::c_int, @@ -3362,44 +3507,23 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "mprotect$UNIX2003" )] - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn semget(key: key_t, nsems: ::c_int, semflg: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "semctl$UNIX2003" )] - pub fn semctl( - semid: ::c_int, - semnum: ::c_int, - cmd: ::c_int, - ... - ) -> ::c_int; - pub fn semop( - semid: ::c_int, - sops: *mut sembuf, - nsops: ::size_t, - ) -> ::c_int; + pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; + pub fn semop(semid: ::c_int, sops: *mut sembuf, nsops: ::size_t) -> ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::c_int; pub fn ftok(pathname: *const c_char, proj_id: ::c_int) -> key_t; - pub fn shmat( - shmid: ::c_int, - shmaddr: *const ::c_void, - shmflg: ::c_int, - ) -> *mut ::c_void; + pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "shmctl$UNIX2003" )] - pub fn shmctl( - shmid: ::c_int, - cmd: ::c_int, - buf: *mut ::shmid_ds, - ) -> ::c_int; + pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn shmget(key: key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn sysctl( name: *mut ::c_int, @@ -3422,18 +3546,11 @@ extern "C" { #[allow(deprecated)] pub fn mach_timebase_info(info: *mut ::mach_timebase_info) -> ::c_int; pub fn pthread_setname_np(name: *const ::c_char) -> ::c_int; - pub fn pthread_getname_np( - thread: ::pthread_t, - name: *mut ::c_char, - len: ::size_t, - ) -> ::c_int; + pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_from_mach_thread_np(port: ::mach_port_t) -> ::pthread_t; pub fn pthread_get_stackaddr_np(thread: ::pthread_t) -> *mut ::c_void; pub fn pthread_get_stacksize_np(thread: ::pthread_t) -> ::size_t; - pub fn pthread_condattr_setpshared( - attr: *mut pthread_condattr_t, - pshared: ::c_int, - ) -> ::c_int; + pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, @@ -3450,10 +3567,7 @@ extern "C" { attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; - pub fn pthread_rwlockattr_setpshared( - attr: *mut pthread_rwlockattr_t, - val: ::c_int, - ) -> ::c_int; + pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; pub fn __error() -> *mut ::c_int; pub fn backtrace(buf: *mut *mut ::c_void, sz: ::c_int) -> ::c_int; #[cfg_attr( @@ -3489,12 +3603,7 @@ extern "C" { flags: ::c_int, data: *mut ::c_void, ) -> ::c_int; - pub fn ptrace( - request: ::c_int, - pid: ::pid_t, - addr: *mut ::c_char, - data: ::c_int, - ) -> ::c_int; + pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: *mut ::c_char, data: ::c_int) -> ::c_int; pub fn quotactl( special: *const ::c_char, cmd: ::c_int, @@ -3534,29 +3643,16 @@ extern "C" { pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t) -> ::c_int; pub fn localeconv_l(loc: ::locale_t) -> *mut lconv; - pub fn newlocale( - mask: ::c_int, - locale: *const ::c_char, - base: ::locale_t, - ) -> ::locale_t; + pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn querylocale(mask: ::c_int, loc: ::locale_t) -> *const ::c_char; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::c_int) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::c_int) -> ::c_int; - pub fn preadv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn pwritev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; + pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; + pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) + -> ::ssize_t; pub fn getxattr( path: *const ::c_char, name: *const ::c_char, @@ -3601,16 +3697,8 @@ extern "C" { size: ::size_t, flags: ::c_int, ) -> ::ssize_t; - pub fn removexattr( - path: *const ::c_char, - name: *const ::c_char, - flags: ::c_int, - ) -> ::c_int; - pub fn renamex_np( - from: *const ::c_char, - to: *const ::c_char, - flags: ::c_uint, - ) -> ::c_int; + pub fn removexattr(path: *const ::c_char, name: *const ::c_char, flags: ::c_int) -> ::c_int; + pub fn renamex_np(from: *const ::c_char, to: *const ::c_char, flags: ::c_uint) -> ::c_int; pub fn renameatx_np( fromfd: ::c_int, from: *const ::c_char, @@ -3618,11 +3706,7 @@ extern "C" { to: *const ::c_char, flags: ::c_uint, ) -> ::c_int; - pub fn fremovexattr( - filedes: ::c_int, - name: *const ::c_char, - flags: ::c_int, - ) -> ::c_int; + pub fn fremovexattr(filedes: ::c_int, name: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn getgrouplist( name: *const ::c_char, @@ -3636,18 +3720,11 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "waitid$UNIX2003" )] - pub fn waitid( - idtype: idtype_t, - id: id_t, - infop: *mut ::siginfo_t, - options: ::c_int, - ) -> ::c_int; + pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) + -> ::c_int; pub fn brk(addr: *const ::c_void) -> *mut ::c_void; pub fn sbrk(increment: ::c_int) -> *mut ::c_void; - pub fn settimeofday( - tv: *const ::timeval, - tz: *const ::timezone, - ) -> ::c_int; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; #[deprecated(since = "0.2.55", note = "Use the mach crate")] pub fn _dyld_image_count() -> u32; #[deprecated(since = "0.2.55", note = "Use the mach crate")] @@ -3696,25 +3773,15 @@ extern "C" { attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; - pub fn posix_spawnattr_setflags( - attr: *mut posix_spawnattr_t, - flags: ::c_short, - ) -> ::c_int; + pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; - pub fn posix_spawnattr_setpgroup( - attr: *mut posix_spawnattr_t, - flags: ::pid_t, - ) -> ::c_int; + pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; - pub fn posix_spawn_file_actions_init( - actions: *mut posix_spawn_file_actions_t, - ) -> ::c_int; - pub fn posix_spawn_file_actions_destroy( - actions: *mut posix_spawn_file_actions_t, - ) -> ::c_int; + pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; + pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, @@ -3743,11 +3810,7 @@ extern "C" { len: *mut ::size_t, connid: *mut sae_connid_t, ) -> ::c_int; - pub fn disconnectx( - socket: ::c_int, - associd: sae_associd_t, - connid: sae_connid_t, - ) -> ::c_int; + pub fn disconnectx(socket: ::c_int, associd: sae_associd_t, connid: sae_connid_t) -> ::c_int; pub fn ntp_adjtime(buf: *mut timex) -> ::c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int; @@ -3761,16 +3824,9 @@ extern "C" { all(target_os = "macos", not(target_arch = "aarch64")), link_name = "getfsstat$INODE64" )] - pub fn getfsstat( - mntbufp: *mut statfs, - bufsize: ::c_int, - flags: ::c_int, - ) -> ::c_int; + pub fn getfsstat(mntbufp: *mut statfs, bufsize: ::c_int, flags: ::c_int) -> ::c_int; - pub fn iconv_open( - tocode: *const ::c_char, - fromcode: *const ::c_char, - ) -> iconv_t; + pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, diff --git a/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs index 0330183d3f..60ab2188c4 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs @@ -171,6 +171,14 @@ s! { pub sdl_route: [::c_ushort; 16], } + pub struct xucred { + pub cr_version: ::c_uint, + pub cr_uid: ::uid_t, + pub cr_ngroups: ::c_short, + pub cr_groups: [::gid_t; 16], + __cr_unused1: *mut ::c_void, + } + pub struct stack_t { pub ss_sp: *mut ::c_char, pub ss_size: ::size_t, @@ -238,7 +246,6 @@ s_no_extra_traits! { pub sigev_value: ::sigval, __unused3: *mut ::c_void //actually a function pointer } - } cfg_if! { @@ -1013,8 +1020,10 @@ pub const SF_XLINK: ::c_ulong = 0x01000000; pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; -fn _CMSG_ALIGN(n: usize) -> usize { - (n + 3) & !3 +const_fn! { + {const} fn _CMSG_ALIGN(n: usize) -> usize { + (n + 3) & !3 + } } f! { @@ -1043,7 +1052,7 @@ f! { } } - pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) + _CMSG_ALIGN(length as usize)) as ::c_uint } @@ -1058,18 +1067,11 @@ safe_f! { extern "C" { pub fn __errno_location() -> *mut ::c_int; pub fn setgrent(); - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn setutxdb(_type: ::c_uint, file: *mut ::c_char) -> ::c_int; - pub fn aio_waitcomplete( - iocbp: *mut *mut aiocb, - timeout: *mut ::timespec, - ) -> ::c_int; + pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, timeout: *mut ::timespec) -> ::c_int; pub fn waitid( idtype: idtype_t, diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs index a88e56cc6e..a0b510514f 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs @@ -198,11 +198,7 @@ extern "C" { // Type of `addr` argument changed from `const void*` to `void*` // in FreeBSD 12 - pub fn mprotect( - addr: *const ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; // Return type ::c_int was removed in FreeBSD 12 pub fn freelocale(loc: ::locale_t) -> ::c_int; diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs index 647e11e6b7..30fc886949 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs @@ -208,11 +208,7 @@ pub const ELAST: ::c_int = 96; extern "C" { pub fn setgrent(); - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn freelocale(loc: ::locale_t); pub fn msgrcv( msqid: ::c_int, @@ -230,11 +226,7 @@ extern "C" { pub fn fdatasync(fd: ::c_int) -> ::c_int; - pub fn getrandom( - buf: *mut ::c_void, - buflen: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; + pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs index a974146d69..1753583b46 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs @@ -212,11 +212,7 @@ extern "C" { pub fn aio_readv(aiocbp: *mut ::aiocb) -> ::c_int; pub fn aio_writev(aiocbp: *mut ::aiocb) -> ::c_int; pub fn setgrent(); - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn freelocale(loc: ::locale_t); pub fn msgrcv( msqid: ::c_int, @@ -234,11 +230,7 @@ extern "C" { pub fn fdatasync(fd: ::c_int) -> ::c_int; - pub fn getrandom( - buf: *mut ::c_void, - buflen: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; + pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs index 04bc48dcd6..db495e4817 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs @@ -89,14 +89,6 @@ s! { pub msg_ctime: ::time_t, } - pub struct xucred { - pub cr_version: ::c_uint, - pub cr_uid: ::uid_t, - pub cr_ngroups: ::c_short, - pub cr_groups: [::gid_t;16], - __cr_unused1: *mut ::c_void, - } - pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, @@ -143,6 +135,23 @@ s_no_extra_traits! { pub __ut_spare: [::c_char; 64], } + #[cfg(libc_union)] + pub union __c_anonymous_cr_pid { + __cr_unused: *mut ::c_void, + pub cr_pid: ::pid_t, + } + + pub struct xucred { + pub cr_version: ::c_uint, + pub cr_uid: ::uid_t, + pub cr_ngroups: ::c_short, + pub cr_groups: [::gid_t; 16], + #[cfg(libc_union)] + pub cr_pid__c_anonymous_union: __c_anonymous_cr_pid, + #[cfg(not(libc_union))] + __cr_unused1: *mut ::c_void, + } + pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, @@ -225,6 +234,73 @@ cfg_if! { } } + #[cfg(libc_union)] + impl PartialEq for __c_anonymous_cr_pid { + fn eq(&self, other: &__c_anonymous_cr_pid) -> bool { + unsafe { self.cr_pid == other.cr_pid} + } + } + #[cfg(libc_union)] + impl Eq for __c_anonymous_cr_pid {} + #[cfg(libc_union)] + impl ::fmt::Debug for __c_anonymous_cr_pid { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("cr_pid") + .field("cr_pid", unsafe { &self.cr_pid }) + .finish() + } + } + #[cfg(libc_union)] + impl ::hash::Hash for __c_anonymous_cr_pid { + fn hash(&self, state: &mut H) { + unsafe { self.cr_pid.hash(state) }; + } + } + + impl PartialEq for xucred { + fn eq(&self, other: &xucred) -> bool { + #[cfg(libc_union)] + let equal_cr_pid = self.cr_pid__c_anonymous_union + == other.cr_pid__c_anonymous_union; + #[cfg(not(libc_union))] + let equal_cr_pid = self.__cr_unused1 == other.__cr_unused1; + + self.cr_version == other.cr_version + && self.cr_uid == other.cr_uid + && self.cr_ngroups == other.cr_ngroups + && self.cr_groups == other.cr_groups + && equal_cr_pid + } + } + impl Eq for xucred {} + impl ::fmt::Debug for xucred { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + let mut struct_formatter = f.debug_struct("xucred"); + struct_formatter.field("cr_version", &self.cr_version); + struct_formatter.field("cr_uid", &self.cr_uid); + struct_formatter.field("cr_ngroups", &self.cr_ngroups); + struct_formatter.field("cr_groups", &self.cr_groups); + #[cfg(libc_union)] + struct_formatter.field( + "cr_pid__c_anonymous_union", + &self.cr_pid__c_anonymous_union + ); + struct_formatter.finish() + } + } + impl ::hash::Hash for xucred { + fn hash(&self, state: &mut H) { + self.cr_version.hash(state); + self.cr_uid.hash(state); + self.cr_ngroups.hash(state); + self.cr_groups.hash(state); + #[cfg(libc_union)] + self.cr_pid__c_anonymous_union.hash(state); + #[cfg(not(libc_union))] + self.__cr_unused1.hash(state); + } + } + impl PartialEq for sockaddr_dl { fn eq(&self, other: &sockaddr_dl) -> bool { self.sdl_len == other.sdl_len @@ -371,6 +447,8 @@ pub const NI_NUMERICSCOPE: ::c_int = 0x00000020; pub const Q_GETQUOTA: ::c_int = 0x700; pub const Q_SETQUOTA: ::c_int = 0x800; +pub const MAP_GUARD: ::c_int = 0x00002000; + pub const POSIX_FADV_NORMAL: ::c_int = 0; pub const POSIX_FADV_RANDOM: ::c_int = 1; pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; @@ -629,7 +707,6 @@ pub const SO_PROTOCOL: ::c_int = 0x1016; pub const SO_PROTOTYPE: ::c_int = SO_PROTOCOL; pub const SO_VENDOR: ::c_int = 0x80000000; -pub const LOCAL_PEERCRED: ::c_int = 1; pub const LOCAL_CREDS: ::c_int = 2; pub const LOCAL_CONNWAIT: ::c_int = 4; pub const LOCAL_VENDOR: ::c_int = SO_VENDOR; @@ -694,10 +771,7 @@ pub const IFF_PROMISC: ::c_int = 0x100; // (n) receive all packets pub const IFF_ALLMULTI: ::c_int = 0x200; // (n) receive all multicast packets pub const IFF_OACTIVE: ::c_int = 0x400; // (d) tx hardware queue is full #[doc(hidden)] -#[deprecated( - since = "0.2.54", - note = "Use the portable `IFF_OACTIVE` instead" -)] +#[deprecated(since = "0.2.54", note = "Use the portable `IFF_OACTIVE` instead")] pub const IFF_DRV_OACTIVE: ::c_int = 0x400; pub const IFF_SIMPLEX: ::c_int = 0x800; // (i) can't hear own transmissions pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit @@ -1103,9 +1177,6 @@ pub const _PC_ACL_NFS4: ::c_int = 64; pub const _SC_CPUSET_SIZE: ::c_int = 122; -pub const XU_NGROUPS: ::c_int = 16; -pub const XUCRED_VERSION: ::c_uint = 0; - // Flags which can be passed to pdfork(2) pub const PD_DAEMON: ::c_int = 0x00000001; pub const PD_CLOEXEC: ::c_int = 0x00000002; @@ -1142,8 +1213,10 @@ pub const F_READAHEAD: ::c_int = 15; pub const F_RDAHEAD: ::c_int = 16; pub const F_DUP2FD_CLOEXEC: ::c_int = 18; -fn _ALIGN(p: usize) -> usize { - (p + _ALIGNBYTES) & !_ALIGNBYTES +const_fn! { + {const} fn _ALIGN(p: usize) -> usize { + (p + _ALIGNBYTES) & !_ALIGNBYTES + } } f! { @@ -1174,7 +1247,7 @@ f! { } } - pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_ALIGN(::mem::size_of::<::cmsghdr>()) + _ALIGN(length as usize)) as ::c_uint } @@ -1293,16 +1366,8 @@ extern "C" { pub fn jail(jail: *mut ::jail) -> ::c_int; pub fn jail_attach(jid: ::c_int) -> ::c_int; pub fn jail_remove(jid: ::c_int) -> ::c_int; - pub fn jail_get( - iov: *mut ::iovec, - niov: ::c_uint, - flags: ::c_int, - ) -> ::c_int; - pub fn jail_set( - iov: *mut ::iovec, - niov: ::c_uint, - flags: ::c_int, - ) -> ::c_int; + pub fn jail_get(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int) -> ::c_int; + pub fn jail_set(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int) -> ::c_int; pub fn lio_listio( mode: ::c_int, @@ -1311,31 +1376,15 @@ extern "C" { sevp: *mut sigevent, ) -> ::c_int; - pub fn posix_fallocate( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn posix_fadvise( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - advise: ::c_int, - ) -> ::c_int; + pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; - pub fn mkostemps( - template: *mut ::c_char, - suffixlen: ::c_int, - flags: ::c_int, - ) -> ::c_int; + pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn getutxuser(user: *const ::c_char) -> *mut utmpx; pub fn setutxdb(_type: ::c_int, file: *const ::c_char) -> ::c_int; - pub fn aio_waitcomplete( - iocbp: *mut *mut aiocb, - timeout: *mut ::timespec, - ) -> ::ssize_t; + pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, timeout: *mut ::timespec) -> ::ssize_t; pub fn mq_getfd_np(mqd: ::mqd_t) -> ::c_int; pub fn waitid( @@ -1347,22 +1396,10 @@ extern "C" { pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; - pub fn shmat( - shmid: ::c_int, - shmaddr: *const ::c_void, - shmflg: ::c_int, - ) -> *mut ::c_void; + pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; - pub fn shmctl( - shmid: ::c_int, - cmd: ::c_int, - buf: *mut ::shmid_ds, - ) -> ::c_int; - pub fn msgctl( - msqid: ::c_int, - cmd: ::c_int, - buf: *mut ::msqid_ds, - ) -> ::c_int; + pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; + pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut ::msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgsnd( msqid: ::c_int, @@ -1381,11 +1418,7 @@ extern "C" { pub fn pdgetpid(fd: ::c_int, pidp: *mut ::pid_t) -> ::c_int; pub fn pdkill(fd: ::c_int, signum: ::c_int) -> ::c_int; - pub fn rtprio_thread( - function: ::c_int, - lwpid: ::lwpid_t, - rtp: *mut super::rtprio, - ) -> ::c_int; + pub fn rtprio_thread(function: ::c_int, lwpid: ::lwpid_t, rtp: *mut super::rtprio) -> ::c_int; pub fn posix_spawn( pid: *mut ::pid_t, @@ -1425,26 +1458,17 @@ extern "C" { attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; - pub fn posix_spawnattr_setflags( - attr: *mut posix_spawnattr_t, - flags: ::c_short, - ) -> ::c_int; + pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; - pub fn posix_spawnattr_setpgroup( - attr: *mut posix_spawnattr_t, - flags: ::pid_t, - ) -> ::c_int; + pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; - pub fn posix_spawnattr_setschedpolicy( - attr: *mut posix_spawnattr_t, - flags: ::c_int, - ) -> ::c_int; + pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, @@ -1454,12 +1478,8 @@ extern "C" { param: *const ::sched_param, ) -> ::c_int; - pub fn posix_spawn_file_actions_init( - actions: *mut posix_spawn_file_actions_t, - ) -> ::c_int; - pub fn posix_spawn_file_actions_destroy( - actions: *mut posix_spawn_file_actions_t, - ) -> ::c_int; + pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; + pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, @@ -1477,15 +1497,9 @@ extern "C" { newfd: ::c_int, ) -> ::c_int; - #[cfg_attr( - all(target_os = "freebsd", freebsd11), - link_name = "statfs@FBSD_1.0" - )] + #[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" - )] + #[cfg_attr(all(target_os = "freebsd", freebsd11), link_name = "fstatfs@FBSD_1.0")] pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn dup3(src: ::c_int, dst: ::c_int, flags: ::c_int) -> ::c_int; @@ -1511,11 +1525,7 @@ extern "C" { needlelen: ::size_t, ) -> *mut ::c_void; - pub fn nmount( - iov: *mut ::iovec, - niov: ::c_uint, - flags: ::c_int, - ) -> ::c_int; + pub fn nmount(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int) -> ::c_int; } #[link(name = "util")] diff --git a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs index 94d30972e8..a40bb3dca5 100644 --- a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs +++ b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs @@ -396,12 +396,15 @@ cfg_if! { } // Non-public helper constant -#[cfg(all(not(libc_const_size_of), target_pointer_width = "32"))] -const SIZEOF_LONG: usize = 4; -#[cfg(all(not(libc_const_size_of), target_pointer_width = "64"))] -const SIZEOF_LONG: usize = 8; -#[cfg(libc_const_size_of)] -const SIZEOF_LONG: usize = ::mem::size_of::<::c_long>(); +cfg_if! { + if #[cfg(all(not(libc_const_size_of), target_pointer_width = "32"))] { + const SIZEOF_LONG: usize = 4; + } else if #[cfg(all(not(libc_const_size_of), target_pointer_width = "64"))] { + const SIZEOF_LONG: usize = 8; + } else if #[cfg(libc_const_size_of)] { + const SIZEOF_LONG: usize = ::mem::size_of::<::c_long>(); + } +} #[deprecated( since = "0.2.64", @@ -947,6 +950,8 @@ pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; +pub const LOCAL_PEERCRED: ::c_int = 1; + pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; @@ -1133,6 +1138,9 @@ pub const ST_NOSUID: ::c_ulong = 2; pub const NI_MAXHOST: ::size_t = 1025; +pub const XU_NGROUPS: ::c_int = 16; +pub const XUCRED_VERSION: ::c_uint = 0; + pub const RTLD_LOCAL: ::c_int = 0; pub const RTLD_NODELETE: ::c_int = 0x1000; pub const RTLD_NOLOAD: ::c_int = 0x2000; @@ -1354,11 +1362,7 @@ safe_f! { extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; @@ -1378,14 +1382,8 @@ extern "C" { pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; - pub fn clock_settime( - clk_id: ::clockid_t, - tp: *const ::timespec, - ) -> ::c_int; - pub fn clock_getcpuclockid( - pid: ::pid_t, - clk_id: *mut ::clockid_t, - ) -> ::c_int; + pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; + pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; @@ -1439,16 +1437,8 @@ extern "C" { ) -> ::c_int; pub fn lchflags(path: *const ::c_char, flags: ::c_ulong) -> ::c_int; pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; - pub fn memrchr( - cx: *const ::c_void, - c: ::c_int, - n: ::size_t, - ) -> *mut ::c_void; - pub fn mkfifoat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; + pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "mknodat@FBSD_1.1" @@ -1459,18 +1449,9 @@ extern "C" { mode: ::mode_t, dev: dev_t, ) -> ::c_int; - pub fn mincore( - addr: *const ::c_void, - len: ::size_t, - vec: *mut ::c_char, - ) -> ::c_int; - pub fn newlocale( - mask: ::c_int, - locale: *const ::c_char, - base: ::locale_t, - ) -> ::locale_t; - pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) - -> *mut ::c_char; + pub fn mincore(addr: *const ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; + pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; + pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn ppoll( fds: *mut ::pollfd, @@ -1478,16 +1459,8 @@ extern "C" { timeout: *const ::timespec, sigmask: *const sigset_t, ) -> ::c_int; - pub fn preadv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn pthread_attr_get_np( - tid: ::pthread_t, - attr: *mut ::pthread_attr_t, - ) -> ::c_int; + pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; + pub fn pthread_attr_get_np(tid: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, @@ -1509,10 +1482,7 @@ extern "C" { attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; - pub fn pthread_condattr_setpshared( - attr: *mut pthread_condattr_t, - pshared: ::c_int, - ) -> ::c_int; + pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_main_np() -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, @@ -1530,30 +1500,14 @@ extern "C" { attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; - pub fn pthread_rwlockattr_setpshared( - attr: *mut pthread_rwlockattr_t, - val: ::c_int, - ) -> ::c_int; + pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::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 ptrace(request: ::c_int, pid: ::pid_t, addr: *mut ::c_char, data: ::c_int) -> ::c_int; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; - pub fn pwritev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; + pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) + -> ::ssize_t; pub fn querylocale(mask: ::c_int, loc: ::locale_t) -> *const ::c_char; - pub fn rtprio( - function: ::c_int, - pid: ::pid_t, - rtp: *mut rtprio, - ) -> ::c_int; + pub fn rtprio(function: ::c_int, pid: ::pid_t, rtp: *mut rtprio) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, @@ -1561,10 +1515,7 @@ extern "C" { param: *const ::sched_param, ) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; - pub fn sem_timedwait( - sem: *mut sem_t, - abstime: *const ::timespec, - ) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sendfile( fd: ::c_int, s: ::c_int, @@ -1576,20 +1527,12 @@ extern "C" { ) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::c_int) -> ::c_int; - pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) - -> ::c_int; + pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) -> ::c_int; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; - pub fn settimeofday( - tv: *const ::timeval, - tz: *const ::timezone, - ) -> ::c_int; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn setutxent(); - pub fn shm_open( - name: *const ::c_char, - oflag: ::c_int, - mode: ::mode_t, - ) -> ::c_int; + pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, @@ -1639,10 +1582,7 @@ extern "C" { data: *mut ::c_void, ) -> ::c_int; - pub fn iconv_open( - tocode: *const ::c_char, - fromcode: *const ::c_char, - ) -> iconv_t; + pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, @@ -1657,8 +1597,7 @@ extern "C" { extern "C" { pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; - pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) - -> ::c_int; + pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) -> ::c_int; pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_receive( mqd: ::mqd_t, @@ -1672,11 +1611,7 @@ extern "C" { msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; - pub fn mq_setattr( - mqd: ::mqd_t, - newattr: *const ::mq_attr, - oldattr: *mut ::mq_attr, - ) -> ::c_int; + pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, diff --git a/vendor/libc/src/unix/bsd/mod.rs b/vendor/libc/src/unix/bsd/mod.rs index 725f5cbf22..f86a0080e6 100644 --- a/vendor/libc/src/unix/bsd/mod.rs +++ b/vendor/libc/src/unix/bsd/mod.rs @@ -587,11 +587,7 @@ extern "C" { )] pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn atof(s: *const ::c_char) -> ::c_double; pub fn labs(i: ::c_long) -> ::c_long; @@ -626,11 +622,7 @@ extern "C" { pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); - pub fn getpeereid( - socket: ::c_int, - euid: *mut ::uid_t, - egid: *mut ::gid_t, - ) -> ::c_int; + pub fn getpeereid(socket: ::c_int, euid: *mut ::uid_t, egid: *mut ::gid_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), @@ -644,9 +636,7 @@ extern "C" { pub fn glob( pattern: *const ::c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const ::c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__globfree30")] @@ -656,11 +646,7 @@ extern "C" { )] pub fn globfree(pglob: *mut ::glob_t); - pub fn posix_madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; @@ -683,22 +669,14 @@ extern "C" { link_name = "telldir$INODE64$UNIX2003" )] pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "msync$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__msync13")] - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), @@ -721,49 +699,29 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "bind$UNIX2003" )] - pub fn bind( - socket: ::c_int, - address: *const ::sockaddr, - address_len: ::socklen_t, - ) -> ::c_int; + pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "writev$UNIX2003" )] - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "readv$UNIX2003" )] - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sendmsg$UNIX2003" )] - pub fn sendmsg( - fd: ::c_int, - msg: *const ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recvmsg$UNIX2003" )] - pub fn recvmsg( - fd: ::c_int, - msg: *mut ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn sync(); pub fn getgrgid_r( @@ -792,11 +750,7 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "pthread_sigmask$UNIX2003" )] - pub fn pthread_sigmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; #[cfg_attr( @@ -880,11 +834,7 @@ extern "C" { old_value: *mut ::itimerval, ) -> ::c_int; - pub fn regcomp( - preg: *mut regex_t, - pattern: *const ::c_char, - cflags: ::c_int, - ) -> ::c_int; + pub fn regcomp(preg: *mut regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regexec( preg: *const regex_t, diff --git a/vendor/libc/src/unix/bsd/netbsdlike/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/mod.rs index 720f10be82..0eab40c0bc 100644 --- a/vendor/libc/src/unix/bsd/netbsdlike/mod.rs +++ b/vendor/libc/src/unix/bsd/netbsdlike/mod.rs @@ -639,11 +639,7 @@ pub const TIMER_ABSTIME: ::c_int = 1; extern "C" { pub fn setgrent(); pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn accept4( @@ -652,49 +648,21 @@ extern "C" { addrlen: *mut ::socklen_t, flags: ::c_int, ) -> ::c_int; - pub fn mincore( - addr: *mut ::c_void, - len: ::size_t, - vec: *mut ::c_char, - ) -> ::c_int; + pub fn mincore(addr: *mut ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_getres50")] pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_gettime50")] pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_settime50")] - pub fn clock_settime( - clk_id: ::clockid_t, - tp: *const ::timespec, - ) -> ::c_int; + pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn __errno() -> *mut ::c_int; - pub fn shm_open( - name: *const ::c_char, - oflag: ::c_int, - mode: ::mode_t, - ) -> ::c_int; - pub fn memrchr( - cx: *const ::c_void, - c: ::c_int, - n: ::size_t, - ) -> *mut ::c_void; + pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; + pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; - pub fn mkostemps( - template: *mut ::c_char, - suffixlen: ::c_int, - flags: ::c_int, - ) -> ::c_int; - pub fn pwritev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn preadv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; + pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; + pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) + -> ::ssize_t; + pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, @@ -726,15 +694,8 @@ extern "C" { mode: ::mode_t, dev: dev_t, ) -> ::c_int; - pub fn mkfifoat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; - pub fn sem_timedwait( - sem: *mut sem_t, - abstime: *const ::timespec, - ) -> ::c_int; + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, @@ -759,17 +720,9 @@ extern "C" { pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; - pub fn shmat( - shmid: ::c_int, - shmaddr: *const ::c_void, - shmflg: ::c_int, - ) -> *mut ::c_void; + pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; - pub fn shmctl( - shmid: ::c_int, - cmd: ::c_int, - buf: *mut ::shmid_ds, - ) -> ::c_int; + pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; } cfg_if! { diff --git a/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs index 7833138798..ad7381b27c 100644 --- a/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs +++ b/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs @@ -299,6 +299,12 @@ s! { pub sc_groups: [::gid_t; 1], } + pub struct unpcbid { + pub unp_pid: ::pid_t, + pub unp_euid: ::uid_t, + pub unp_egid: ::gid_t, + } + pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, @@ -439,7 +445,6 @@ s_no_extra_traits! { pub ipi_ifindex: ::c_uint, } - #[repr(packed)] pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, @@ -448,7 +453,6 @@ s_no_extra_traits! { pub ar_op: u16, } - #[repr(packed)] pub struct in_addr { pub s_addr: ::in_addr_t, } @@ -1047,6 +1051,12 @@ pub const SO_TIMESTAMP: ::c_int = 0x2000; pub const SO_OVERFLOWED: ::c_int = 0x1009; pub const SO_NOHEADER: ::c_int = 0x100a; +// http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/un.h?annotate +pub const LOCAL_OCREDS: ::c_int = 0x0001; // pass credentials to receiver +pub const LOCAL_CONNWAIT: ::c_int = 0x0002; // connects block until accepted +pub const LOCAL_PEEREID: ::c_int = 0x0003; // get peer identification +pub const LOCAL_CREDS: ::c_int = 0x0004; // pass credentials to receiver + // https://github.com/NetBSD/src/blob/trunk/sys/net/if.h#L373 pub const IFF_UP: ::c_int = 0x0001; // interface is up pub const IFF_BROADCAST: ::c_int = 0x0002; // broadcast address valid @@ -1736,8 +1746,10 @@ pub const SF_SNAPSHOT: ::c_ulong = 0x00200000; pub const SF_LOG: ::c_ulong = 0x00400000; pub const SF_SNAPINVAL: ::c_ulong = 0x00800000; -fn _ALIGN(p: usize) -> usize { - (p + _ALIGNBYTES) & !_ALIGNBYTES +const_fn! { + {const} fn _ALIGN(p: usize) -> usize { + (p + _ALIGNBYTES) & !_ALIGNBYTES + } } f! { @@ -1768,7 +1780,7 @@ f! { } } - pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_ALIGN(::mem::size_of::<::cmsghdr>()) + _ALIGN(length as usize)) as ::c_uint } @@ -1925,11 +1937,7 @@ extern "C" { sevlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn sysctl( name: *const ::c_int, namelen: ::c_uint, @@ -1965,8 +1973,7 @@ extern "C" { pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; - pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) - -> ::c_int; + pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) -> ::c_int; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, @@ -1979,11 +1986,7 @@ extern "C" { msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; - pub fn mq_setattr( - mqd: ::mqd_t, - newattr: *const ::mq_attr, - oldattr: *mut ::mq_attr, - ) -> ::c_int; + pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; #[link_name = "__mq_timedreceive50"] pub fn mq_timedreceive( mqd: ::mqd_t, @@ -2001,25 +2004,14 @@ extern "C" { abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; - pub fn ptrace( - request: ::c_int, - pid: ::pid_t, - addr: *mut ::c_void, - data: ::c_int, - ) -> ::c_int; + pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: *mut ::c_void, data: ::c_int) -> ::c_int; pub fn pthread_setname_np( t: ::pthread_t, name: *const ::c_char, arg: *const ::c_void, ) -> ::c_int; - pub fn pthread_attr_get_np( - thread: ::pthread_t, - attr: *mut ::pthread_attr_t, - ) -> ::c_int; - pub fn pthread_getattr_np( - native: ::pthread_t, - attr: *mut ::pthread_attr_t, - ) -> ::c_int; + pub fn pthread_attr_get_np(thread: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; + pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, @@ -2039,11 +2031,7 @@ extern "C" { pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn localeconv_l(loc: ::locale_t) -> *mut lconv; - pub fn newlocale( - mask: ::c_int, - locale: *const ::c_char, - base: ::locale_t, - ) -> ::locale_t; + pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; #[link_name = "__settimeofday50"] pub fn settimeofday(tv: *const ::timeval, tz: *const ::c_void) -> ::c_int; @@ -2084,10 +2072,7 @@ extern "C" { data: *mut ::c_void, ) -> ::c_int; - pub fn iconv_open( - tocode: *const ::c_char, - fromcode: *const ::c_char, - ) -> iconv_t; + pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, @@ -2115,16 +2100,8 @@ extern "C" { ) -> ::c_int; pub fn updwtmpx(file: *const ::c_char, ut: *const utmpx) -> ::c_int; - pub fn getlastlogx( - fname: *const ::c_char, - uid: ::uid_t, - ll: *mut lastlogx, - ) -> *mut lastlogx; - pub fn updlastlogx( - fname: *const ::c_char, - uid: ::uid_t, - ll: *mut lastlogx, - ) -> ::c_int; + pub fn getlastlogx(fname: *const ::c_char, uid: ::uid_t, ll: *mut lastlogx) -> *mut lastlogx; + pub fn updlastlogx(fname: *const ::c_char, uid: ::uid_t, ll: *mut lastlogx) -> ::c_int; pub fn utmpxname(file: *const ::c_char) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; diff --git a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs index 06068115f8..c7a25e2865 100644 --- a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs +++ b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs @@ -1397,8 +1397,10 @@ pub const PTRACE_FORK: ::c_int = 0x0002; pub const WCONTINUED: ::c_int = 8; -fn _ALIGN(p: usize) -> usize { - (p + _ALIGNBYTES) & !_ALIGNBYTES +const_fn! { + {const} fn _ALIGN(p: usize) -> usize { + (p + _ALIGNBYTES) & !_ALIGNBYTES + } } f! { @@ -1429,7 +1431,7 @@ f! { } } - pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_ALIGN(::mem::size_of::<::cmsghdr>()) + _ALIGN(length as usize)) as ::c_uint } @@ -1455,19 +1457,13 @@ safe_f! { extern "C" { pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; - pub fn settimeofday( - tp: *const ::timeval, - tz: *const ::timezone, - ) -> ::c_int; + pub fn settimeofday(tp: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; - pub fn pledge( - promises: *const ::c_char, - execpromises: *const ::c_char, - ) -> ::c_int; + pub fn pledge(promises: *const ::c_char, execpromises: *const ::c_char) -> ::c_int; pub fn strtonum( nptr: *const ::c_char, minval: ::c_longlong, @@ -1501,11 +1497,7 @@ extern "C" { nevents: ::c_int, timeout: *const ::timespec, ) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, @@ -1517,10 +1509,7 @@ extern "C" { ) -> ::c_int; 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 pthread_stackseg_np(thread: ::pthread_t, sinfo: *mut ::stack_t) -> ::c_int; pub fn sysctl( name: *const ::c_int, namelen: ::c_uint, @@ -1532,12 +1521,7 @@ extern "C" { pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; - pub fn ptrace( - request: ::c_int, - pid: ::pid_t, - addr: caddr_t, - data: ::c_int, - ) -> ::c_int; + pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: caddr_t, data: ::c_int) -> ::c_int; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, diff --git a/vendor/libc/src/unix/haiku/mod.rs b/vendor/libc/src/unix/haiku/mod.rs index e834a13866..d88baec69a 100644 --- a/vendor/libc/src/unix/haiku/mod.rs +++ b/vendor/libc/src/unix/haiku/mod.rs @@ -874,6 +874,7 @@ pub const LOCK_UN: ::c_int = 0x08; pub const SIGSTKSZ: ::size_t = 16384; +pub const IOV_MAX: ::c_int = 1024; pub const PATH_MAX: ::c_int = 1024; pub const SA_NOCLDSTOP: ::c_int = 0x01; @@ -924,7 +925,10 @@ pub const _PC_2_SYMLINKS: ::c_int = 37; pub const _PC_XATTR_EXISTS: ::c_int = 38; pub const _PC_XATTR_ENABLED: ::c_int = 39; -pub const FIONBIO: ::c_int = 0xbe000000; +pub const FIONBIO: ::c_ulong = 0xbe000000; +pub const FIONREAD: ::c_ulong = 0xbe000001; +pub const FIOSEEKDATA: ::c_ulong = 0xbe000002; +pub const FIOSEEKHOLE: ::c_ulong = 0xbe000003; pub const _SC_ARG_MAX: ::c_int = 15; pub const _SC_CHILD_MAX: ::c_int = 16; @@ -1201,30 +1205,30 @@ pub const TCIFLUSH: ::c_int = 0x01; pub const TCOFLUSH: ::c_int = 0x02; pub const TCIOFLUSH: ::c_int = 0x03; -pub const TCGETA: ::c_int = 0x8000; -pub const TCSETA: ::c_int = TCGETA + 1; -pub const TCSETAF: ::c_int = TCGETA + 2; -pub const TCSETAW: ::c_int = TCGETA + 3; -pub const TCWAITEVENT: ::c_int = TCGETA + 4; -pub const TCSBRK: ::c_int = TCGETA + 5; -pub const TCFLSH: ::c_int = TCGETA + 6; -pub const TCXONC: ::c_int = TCGETA + 7; -pub const TCQUERYCONNECTED: ::c_int = TCGETA + 8; -pub const TCGETBITS: ::c_int = TCGETA + 9; -pub const TCSETDTR: ::c_int = TCGETA + 10; -pub const TCSETRTS: ::c_int = TCGETA + 11; -pub const TIOCGWINSZ: ::c_int = TCGETA + 12; -pub const TIOCSWINSZ: ::c_int = TCGETA + 13; -pub const TCVTIME: ::c_int = TCGETA + 14; -pub const TIOCGPGRP: ::c_int = TCGETA + 15; -pub const TIOCSPGRP: ::c_int = TCGETA + 16; -pub const TIOCSCTTY: ::c_int = TCGETA + 17; -pub const TIOCMGET: ::c_int = TCGETA + 18; -pub const TIOCMSET: ::c_int = TCGETA + 19; -pub const TIOCSBRK: ::c_int = TCGETA + 20; -pub const TIOCCBRK: ::c_int = TCGETA + 21; -pub const TIOCMBIS: ::c_int = TCGETA + 22; -pub const TIOCMBIC: ::c_int = TCGETA + 23; +pub const TCGETA: ::c_ulong = 0x8000; +pub const TCSETA: ::c_ulong = TCGETA + 1; +pub const TCSETAF: ::c_ulong = TCGETA + 2; +pub const TCSETAW: ::c_ulong = TCGETA + 3; +pub const TCWAITEVENT: ::c_ulong = TCGETA + 4; +pub const TCSBRK: ::c_ulong = TCGETA + 5; +pub const TCFLSH: ::c_ulong = TCGETA + 6; +pub const TCXONC: ::c_ulong = TCGETA + 7; +pub const TCQUERYCONNECTED: ::c_ulong = TCGETA + 8; +pub const TCGETBITS: ::c_ulong = TCGETA + 9; +pub const TCSETDTR: ::c_ulong = TCGETA + 10; +pub const TCSETRTS: ::c_ulong = TCGETA + 11; +pub const TIOCGWINSZ: ::c_ulong = TCGETA + 12; +pub const TIOCSWINSZ: ::c_ulong = TCGETA + 13; +pub const TCVTIME: ::c_ulong = TCGETA + 14; +pub const TIOCGPGRP: ::c_ulong = TCGETA + 15; +pub const TIOCSPGRP: ::c_ulong = TCGETA + 16; +pub const TIOCSCTTY: ::c_ulong = TCGETA + 17; +pub const TIOCMGET: ::c_ulong = TCGETA + 18; +pub const TIOCMSET: ::c_ulong = TCGETA + 19; +pub const TIOCSBRK: ::c_ulong = TCGETA + 20; +pub const TIOCCBRK: ::c_ulong = TCGETA + 21; +pub const TIOCMBIS: ::c_ulong = TCGETA + 22; +pub const TIOCMBIC: ::c_ulong = TCGETA + 23; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; @@ -1350,11 +1354,7 @@ extern "C" { pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn getpriority(which: ::c_int, who: id_t) -> ::c_int; - pub fn setpriority( - which: ::c_int, - who: id_t, - priority: ::c_int, - ) -> ::c_int; + pub fn setpriority(which: ::c_int, who: id_t, priority: ::c_int) -> ::c_int; pub fn utimensat( fd: ::c_int, @@ -1363,11 +1363,7 @@ extern "C" { flag: ::c_int, ) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn _errnop() -> *mut ::c_int; pub fn abs(i: ::c_int) -> ::c_int; @@ -1380,11 +1376,7 @@ extern "C" { #[link(name = "bsd")] extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn clock_gettime(clk_id: ::c_int, tp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: ::c_int, tp: *const ::timespec) -> ::c_int; @@ -1414,11 +1406,7 @@ extern "C" { pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, @@ -1433,50 +1421,28 @@ extern "C" { lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; - pub fn waitid( - idtype: idtype_t, - id: id_t, - infop: *mut ::siginfo_t, - options: ::c_int, - ) -> ::c_int; + pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) + -> ::c_int; pub fn glob( pattern: *const ::c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const ::c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; - pub fn posix_madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; - pub fn shm_open( - name: *const ::c_char, - oflag: ::c_int, - mode: ::mode_t, - ) -> ::c_int; + pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, @@ -1490,33 +1456,13 @@ extern "C" { pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; - pub fn bind( - socket: ::c_int, - address: *const ::sockaddr, - address_len: ::socklen_t, - ) -> ::c_int; + pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - count: ::size_t, - ) -> ::ssize_t; - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - count: ::size_t, - ) -> ::ssize_t; + pub fn writev(fd: ::c_int, iov: *const ::iovec, count: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, count: ::c_int) -> ::ssize_t; - pub fn sendmsg( - fd: ::c_int, - msg: *const ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; - pub fn recvmsg( - fd: ::c_int, - msg: *mut ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; + pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, @@ -1539,11 +1485,7 @@ extern "C" { buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; - pub fn pthread_sigmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; diff --git a/vendor/libc/src/unix/haiku/native.rs b/vendor/libc/src/unix/haiku/native.rs index c5ae21a823..7d2a60d93b 100644 --- a/vendor/libc/src/unix/haiku/native.rs +++ b/vendor/libc/src/unix/haiku/native.rs @@ -20,10 +20,7 @@ macro_rules! haiku_constant { ($a:tt, $b:tt, $c:tt, $d:tt) => { - (($a as u32) << 24) - + (($b as u32) << 16) - + (($c as u32) << 8) - + ($d as u32) + (($a as u32) << 24) + (($b as u32) << 16) + (($c as u32) << 8) + ($d as u32) }; } @@ -236,8 +233,7 @@ pub const B_INFINITE_TIMEOUT: usize = 9223372036854775807; pub const B_RELATIVE_TIMEOUT: u32 = 0x8; pub const B_ABSOLUTE_TIMEOUT: u32 = 0x10; pub const B_TIMEOUT_REAL_TIME_BASE: u32 = 0x40; -pub const B_ABSOLUTE_REAL_TIME_TIMEOUT: u32 = - B_ABSOLUTE_TIMEOUT | B_TIMEOUT_REAL_TIME_BASE; +pub const B_ABSOLUTE_REAL_TIME_TIMEOUT: u32 = B_ABSOLUTE_TIMEOUT | B_TIMEOUT_REAL_TIME_BASE; pub const B_NO_LOCK: u32 = 0; pub const B_LAZY_LOCK: u32 = 1; @@ -440,8 +436,7 @@ pub const B_LAUNCH_FAILED_EXECUTABLE: status_t = B_APP_ERROR_BASE + 10; pub const B_LAUNCH_FAILED_APP_NOT_FOUND: status_t = B_APP_ERROR_BASE + 11; pub const B_LAUNCH_FAILED_APP_IN_TRASH: status_t = B_APP_ERROR_BASE + 12; pub const B_LAUNCH_FAILED_NO_PREFERRED_APP: status_t = B_APP_ERROR_BASE + 13; -pub const B_LAUNCH_FAILED_FILES_APP_NOT_FOUND: status_t = - B_APP_ERROR_BASE + 14; +pub const B_LAUNCH_FAILED_FILES_APP_NOT_FOUND: status_t = B_APP_ERROR_BASE + 14; pub const B_BAD_MIME_SNIFFER_RULE: status_t = B_APP_ERROR_BASE + 15; pub const B_NOT_A_MESSAGE: status_t = B_APP_ERROR_BASE + 16; pub const B_SHUTDOWN_CANCELLED: status_t = B_APP_ERROR_BASE + 17; @@ -586,11 +581,9 @@ pub const B_INT32_TYPE: u32 = haiku_constant!('L', 'O', 'N', 'G'); pub const B_INT64_TYPE: u32 = haiku_constant!('L', 'L', 'N', 'G'); pub const B_INT8_TYPE: u32 = haiku_constant!('B', 'Y', 'T', 'E'); pub const B_LARGE_ICON_TYPE: u32 = haiku_constant!('I', 'C', 'O', 'N'); -pub const B_MEDIA_PARAMETER_GROUP_TYPE: u32 = - haiku_constant!('B', 'M', 'C', 'G'); +pub const B_MEDIA_PARAMETER_GROUP_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'G'); pub const B_MEDIA_PARAMETER_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'T'); -pub const B_MEDIA_PARAMETER_WEB_TYPE: u32 = - haiku_constant!('B', 'M', 'C', 'W'); +pub const B_MEDIA_PARAMETER_WEB_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'W'); pub const B_MESSAGE_TYPE: u32 = haiku_constant!('M', 'S', 'G', 'G'); pub const B_MESSENGER_TYPE: u32 = haiku_constant!('M', 'S', 'N', 'G'); pub const B_MIME_TYPE: u32 = haiku_constant!('M', 'I', 'M', 'E'); @@ -645,11 +638,7 @@ extern "C" { pub fn delete_area(id: area_id) -> status_t; pub fn resize_area(id: area_id, newSize: usize) -> status_t; pub fn set_area_protection(id: area_id, newProtection: u32) -> status_t; - pub fn _get_area_info( - id: area_id, - areaInfo: *mut area_info, - size: usize, - ) -> status_t; + pub fn _get_area_info(id: area_id, areaInfo: *mut area_info, size: usize) -> status_t; pub fn _get_next_area_info( team: team_id, cookie: *mut isize, @@ -690,19 +679,11 @@ extern "C" { pub fn close_port(port: port_id) -> status_t; pub fn delete_port(port: port_id) -> status_t; pub fn port_buffer_size(port: port_id) -> ::ssize_t; - pub fn port_buffer_size_etc( - port: port_id, - flags: u32, - timeout: bigtime_t, - ) -> ::ssize_t; + pub fn port_buffer_size_etc(port: port_id, flags: u32, timeout: bigtime_t) -> ::ssize_t; pub fn port_count(port: port_id) -> ::ssize_t; pub fn set_port_owner(port: port_id, team: team_id) -> status_t; - pub fn _get_port_info( - port: port_id, - buf: *mut port_info, - portInfoSize: ::size_t, - ) -> status_t; + pub fn _get_port_info(port: port_id, buf: *mut port_info, portInfoSize: ::size_t) -> status_t; pub fn _get_next_port_info( port: port_id, cookie: *mut i32, @@ -720,12 +701,7 @@ extern "C" { pub fn create_sem(count: i32, name: *const ::c_char) -> sem_id; pub fn delete_sem(id: sem_id) -> status_t; pub fn acquire_sem(id: sem_id) -> status_t; - pub fn acquire_sem_etc( - id: sem_id, - count: i32, - flags: u32, - timeout: bigtime_t, - ) -> status_t; + pub fn acquire_sem_etc(id: sem_id, count: i32, flags: u32, timeout: bigtime_t) -> status_t; pub fn release_sem(id: sem_id) -> status_t; pub fn release_sem_etc(id: sem_id, count: i32, flags: u32) -> status_t; pub fn switch_sem(semToBeReleased: sem_id, id: sem_id) -> status_t; @@ -738,11 +714,7 @@ extern "C" { ) -> status_t; pub fn get_sem_count(id: sem_id, threadCount: *mut i32) -> status_t; pub fn set_sem_owner(id: sem_id, team: team_id) -> status_t; - pub fn _get_sem_info( - id: sem_id, - info: *mut sem_info, - infoSize: ::size_t, - ) -> status_t; + pub fn _get_sem_info(id: sem_id, info: *mut sem_info, infoSize: ::size_t) -> status_t; pub fn _get_next_sem_info( team: team_id, cookie: *mut i32, @@ -751,16 +723,8 @@ extern "C" { ) -> status_t; pub fn kill_team(team: team_id) -> status_t; - pub fn _get_team_info( - team: team_id, - info: *mut team_info, - size: ::size_t, - ) -> status_t; - pub fn _get_next_team_info( - cookie: *mut i32, - info: *mut team_info, - size: ::size_t, - ) -> status_t; + pub fn _get_team_info(team: team_id, info: *mut team_info, size: ::size_t) -> status_t; + pub fn _get_next_team_info(cookie: *mut i32, info: *mut team_info, size: ::size_t) -> status_t; pub fn spawn_thread( func: thread_func, @@ -772,23 +736,11 @@ extern "C" { pub fn resume_thread(thread: thread_id) -> status_t; pub fn suspend_thread(thread: thread_id) -> status_t; - pub fn rename_thread( - thread: thread_id, - newName: *const ::c_char, - ) -> status_t; - pub fn set_thread_priority( - thread: thread_id, - newPriority: i32, - ) -> status_t; + pub fn rename_thread(thread: thread_id, newName: *const ::c_char) -> status_t; + pub fn set_thread_priority(thread: thread_id, newPriority: i32) -> status_t; pub fn exit_thread(status: status_t); - pub fn wait_for_thread( - thread: thread_id, - returnValue: *mut status_t, - ) -> status_t; - pub fn on_exit_thread( - callback: extern "C" fn(*mut ::c_void), - data: *mut ::c_void, - ) -> status_t; + pub fn wait_for_thread(thread: thread_id, returnValue: *mut status_t) -> status_t; + pub fn on_exit_thread(callback: extern "C" fn(*mut ::c_void), data: *mut ::c_void) -> status_t; pub fn find_thread(name: *const ::c_char) -> thread_id; @@ -798,26 +750,15 @@ extern "C" { buffer: *const ::c_void, bufferSize: ::size_t, ) -> status_t; - pub fn receive_data( - sender: *mut thread_id, - buffer: *mut ::c_void, - bufferSize: ::size_t, - ) -> i32; + pub fn receive_data(sender: *mut thread_id, buffer: *mut ::c_void, bufferSize: ::size_t) + -> i32; pub fn has_data(thread: thread_id) -> bool; pub fn snooze(amount: bigtime_t) -> status_t; - pub fn snooze_etc( - amount: bigtime_t, - timeBase: ::c_int, - flags: u32, - ) -> status_t; + pub fn snooze_etc(amount: bigtime_t, timeBase: ::c_int, flags: u32) -> status_t; pub fn snooze_until(time: bigtime_t, timeBase: ::c_int) -> status_t; - pub fn _get_thread_info( - id: thread_id, - info: *mut thread_info, - size: ::size_t, - ) -> status_t; + pub fn _get_thread_info(id: thread_id, info: *mut thread_info, size: ::size_t) -> status_t; pub fn _get_next_thread_info( team: team_id, cookie: *mut i32, @@ -848,20 +789,13 @@ extern "C" { // TODO: cpuid_info struct and the get_cpuid() function pub fn get_system_info(info: *mut system_info) -> status_t; - pub fn get_cpu_info( - firstCPU: u32, - cpuCount: u32, - info: *mut cpu_info, - ) -> status_t; + pub fn get_cpu_info(firstCPU: u32, cpuCount: u32, info: *mut cpu_info) -> status_t; pub fn is_computer_on() -> i32; pub fn is_computer_on_fire() -> ::c_double; pub fn send_signal(threadID: thread_id, signal: ::c_uint) -> ::c_int; pub fn set_signal_stack(base: *mut ::c_void, size: ::size_t); - pub fn wait_for_objects( - infos: *mut object_wait_info, - numInfos: ::c_int, - ) -> ::ssize_t; + pub fn wait_for_objects(infos: *mut object_wait_info, numInfos: ::c_int) -> ::ssize_t; pub fn wait_for_objects_etc( infos: *mut object_wait_info, numInfos: ::c_int, @@ -939,11 +873,7 @@ extern "C" { pub fn fs_stat_dev(dev: ::dev_t, info: *mut fs_info) -> ::c_int; // kernel/fs_query.h - pub fn fs_open_query( - device: ::dev_t, - query: *const ::c_char, - flags: u32, - ) -> *mut ::DIR; + pub fn fs_open_query(device: ::dev_t, query: *const ::c_char, flags: u32) -> *mut ::DIR; pub fn fs_open_live_query( device: ::dev_t, query: *const ::c_char, @@ -953,11 +883,7 @@ extern "C" { ) -> *mut ::DIR; pub fn fs_close_query(d: *mut ::DIR) -> ::c_int; pub fn fs_read_query(d: *mut ::DIR) -> *mut ::dirent; - pub fn get_path_for_dirent( - dent: *mut ::dirent, - buf: *mut ::c_char, - len: ::size_t, - ) -> status_t; + pub fn get_path_for_dirent(dent: *mut ::dirent, buf: *mut ::c_char, len: ::size_t) -> status_t; // kernel/fs_volume.h pub fn fs_mount_volume( @@ -992,11 +918,7 @@ extern "C" { symbolLocation: *mut *mut ::c_void, ) -> status_t; pub fn clear_caches(address: *mut ::c_void, length: ::size_t, flags: u32); - pub fn _get_image_info( - image: image_id, - info: *mut image_info, - size: ::size_t, - ) -> status_t; + pub fn _get_image_info(image: image_id, info: *mut image_info, size: ::size_t) -> status_t; pub fn _get_next_image_info( team: team_id, cookie: *mut i32, @@ -1059,11 +981,7 @@ pub unsafe fn get_sem_info(id: sem_id, info: *mut sem_info) -> status_t { _get_sem_info(id, info, core::mem::size_of::() as ::size_t) } -pub unsafe fn get_next_sem_info( - team: team_id, - cookie: *mut i32, - info: *mut sem_info, -) -> status_t { +pub unsafe fn get_next_sem_info(team: team_id, cookie: *mut i32, info: *mut sem_info) -> status_t { _get_next_sem_info( team, cookie, @@ -1076,22 +994,11 @@ pub unsafe fn get_team_info(team: team_id, info: *mut team_info) -> status_t { _get_team_info(team, info, core::mem::size_of::() as ::size_t) } -pub unsafe fn get_next_team_info( - cookie: *mut i32, - info: *mut team_info, -) -> status_t { - _get_next_team_info( - cookie, - info, - core::mem::size_of::() as ::size_t, - ) +pub unsafe fn get_next_team_info(cookie: *mut i32, info: *mut team_info) -> status_t { + _get_next_team_info(cookie, info, core::mem::size_of::() as ::size_t) } -pub unsafe fn get_team_usage_info( - team: team_id, - who: i32, - info: *mut team_usage_info, -) -> status_t { +pub unsafe fn get_team_usage_info(team: team_id, who: i32, info: *mut team_usage_info) -> status_t { _get_team_usage_info( team, who, @@ -1100,10 +1007,7 @@ pub unsafe fn get_team_usage_info( ) } -pub unsafe fn get_thread_info( - id: thread_id, - info: *mut thread_info, -) -> status_t { +pub unsafe fn get_thread_info(id: thread_id, info: *mut thread_info) -> status_t { _get_thread_info(id, info, core::mem::size_of::() as ::size_t) } @@ -1121,15 +1025,8 @@ pub unsafe fn get_next_thread_info( } // kernel/image.h -pub unsafe fn get_image_info( - image: image_id, - info: *mut image_info, -) -> status_t { - _get_image_info( - image, - info, - core::mem::size_of::() as ::size_t, - ) +pub unsafe fn get_image_info(image: image_id, info: *mut image_info) -> status_t { + _get_image_info(image, info, core::mem::size_of::() as ::size_t) } pub unsafe fn get_next_image_info( diff --git a/vendor/libc/src/unix/hermit/mod.rs b/vendor/libc/src/unix/hermit/mod.rs index ad0fd14dcc..eedfd28a49 100644 --- a/vendor/libc/src/unix/hermit/mod.rs +++ b/vendor/libc/src/unix/hermit/mod.rs @@ -960,18 +960,10 @@ safe_f! { extern "C" { pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn atof(s: *const ::c_char) -> ::c_double; @@ -979,16 +971,9 @@ extern "C" { pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); - pub fn bind( - s: ::c_int, - name: *const ::sockaddr, - namelen: ::socklen_t, - ) -> ::c_int; + pub fn bind(s: ::c_int, name: *const ::sockaddr, namelen: ::socklen_t) -> ::c_int; - pub fn clock_gettime( - clock_id: ::clockid_t, - tp: *mut ::timespec, - ) -> ::c_int; + pub fn clock_gettime(clock_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn getpwuid_r( @@ -1011,11 +996,7 @@ extern "C" { arg: *mut ::c_void, ) -> ::c_int; - pub fn pthread_sigmask( - how: ::c_int, - set: *const ::sigset_t, - oset: *mut ::sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const ::sigset_t, oset: *mut ::sigset_t) -> ::c_int; pub fn recvfrom( s: ::c_int, diff --git a/vendor/libc/src/unix/linux_like/android/b32/mod.rs b/vendor/libc/src/unix/linux_like/android/b32/mod.rs index e686da60b5..774690704e 100644 --- a/vendor/libc/src/unix/linux_like/android/b32/mod.rs +++ b/vendor/libc/src/unix/linux_like/android/b32/mod.rs @@ -197,10 +197,8 @@ pub const PTRACE_SETFPREGS: ::c_int = 15; pub const PTRACE_GETREGS: ::c_int = 12; pub const PTRACE_SETREGS: ::c_int = 13; -pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = - pthread_mutex_t { value: 0 }; -pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = - pthread_cond_t { value: 0 }; +pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { value: 0 }; +pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { value: 0 }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { lock: PTHREAD_MUTEX_INITIALIZER, cond: PTHREAD_COND_INITIALIZER, diff --git a/vendor/libc/src/unix/linux_like/android/mod.rs b/vendor/libc/src/unix/linux_like/android/mod.rs index f1d6ef4b2b..d64a365edd 100644 --- a/vendor/libc/src/unix/linux_like/android/mod.rs +++ b/vendor/libc/src/unix/linux_like/android/mod.rs @@ -1078,8 +1078,10 @@ pub const SO_SNDTIMEO: ::c_int = 21; pub const SO_BINDTODEVICE: ::c_int = 25; pub const SO_TIMESTAMP: ::c_int = 29; pub const SO_ACCEPTCONN: ::c_int = 30; +pub const SO_PEERSEC: ::c_int = 31; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_PASSSEC: ::c_int = 34; pub const SO_MARK: ::c_int = 36; pub const SO_PROTOCOL: ::c_int = 38; pub const SO_DOMAIN: ::c_int = 39; @@ -1257,11 +1259,8 @@ pub const AI_PASSIVE: ::c_int = 0x00000001; pub const AI_CANONNAME: ::c_int = 0x00000002; pub const AI_NUMERICHOST: ::c_int = 0x00000004; pub const AI_NUMERICSERV: ::c_int = 0x00000008; -pub const AI_MASK: ::c_int = AI_PASSIVE - | AI_CANONNAME - | AI_NUMERICHOST - | AI_NUMERICSERV - | AI_ADDRCONFIG; +pub const AI_MASK: ::c_int = + AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG; pub const AI_ALL: ::c_int = 0x00000100; pub const AI_V4MAPPED_CFG: ::c_int = 0x00000200; pub const AI_ADDRCONFIG: ::c_int = 0x00000400; @@ -2217,8 +2216,7 @@ pub const FUTEX_CMP_REQUEUE_PI: ::c_int = 12; pub const FUTEX_PRIVATE_FLAG: ::c_int = 128; pub const FUTEX_CLOCK_REALTIME: ::c_int = 256; -pub const FUTEX_CMD_MASK: ::c_int = - !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); +pub const FUTEX_CMD_MASK: ::c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); // linux/errqueue.h pub const SO_EE_ORIGIN_NONE: u8 = 0; @@ -2369,29 +2367,13 @@ extern "C" { new_limit: *const ::rlimit64, old_limit: *mut ::rlimit64, ) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; - pub fn madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, @@ -2409,18 +2391,8 @@ extern "C" { sevlen: ::size_t, flags: ::c_int, ) -> ::c_int; - pub fn preadv( - fd: ::c_int, - iov: *const ::iovec, - count: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn pwritev( - fd: ::c_int, - iov: *const ::iovec, - count: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; + pub fn preadv(fd: ::c_int, iov: *const ::iovec, count: ::c_int, offset: ::off_t) -> ::ssize_t; + pub fn pwritev(fd: ::c_int, iov: *const ::iovec, count: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn process_vm_readv( pid: ::pid_t, local_iov: *const ::iovec, @@ -2442,10 +2414,7 @@ extern "C" { pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn __sched_cpualloc(count: ::size_t) -> *mut ::cpu_set_t; 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_cpucount(setsize: ::size_t, set: *const cpu_set_t) -> ::c_int; pub fn sched_getcpu() -> ::c_int; pub fn utmpname(name: *const ::c_char) -> ::c_int; @@ -2454,28 +2423,10 @@ extern "C" { pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn fallocate( - fd: ::c_int, - mode: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn fallocate64( - fd: ::c_int, - mode: ::c_int, - offset: ::off64_t, - len: ::off64_t, - ) -> ::c_int; - pub fn posix_fallocate( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn posix_fallocate64( - fd: ::c_int, - offset: ::off64_t, - len: ::off64_t, - ) -> ::c_int; + pub fn fallocate(fd: ::c_int, mode: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn fallocate64(fd: ::c_int, mode: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; + pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn posix_fallocate64(fd: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; pub fn getxattr( path: *const c_char, name: *const c_char, @@ -2515,34 +2466,15 @@ extern "C" { size: ::size_t, flags: ::c_int, ) -> ::c_int; - pub fn listxattr( - path: *const c_char, - list: *mut c_char, - size: ::size_t, - ) -> ::ssize_t; - pub fn llistxattr( - path: *const c_char, - list: *mut c_char, - size: ::size_t, - ) -> ::ssize_t; - pub fn flistxattr( - filedes: ::c_int, - list: *mut c_char, - size: ::size_t, - ) -> ::ssize_t; + pub fn listxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; + pub fn llistxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; + pub fn flistxattr(filedes: ::c_int, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int; 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 signalfd(fd: ::c_int, mask: *const ::sigset_t, flags: ::c_int) -> ::c_int; pub fn timerfd_create(clock: ::clockid_t, flags: ::c_int) -> ::c_int; - pub fn timerfd_gettime( - fd: ::c_int, - current_value: *mut itimerspec, - ) -> ::c_int; + pub fn timerfd_gettime(fd: ::c_int, current_value: *mut itimerspec) -> ::c_int; pub fn timerfd_settime( fd: ::c_int, flags: ::c_int, @@ -2550,11 +2482,8 @@ extern "C" { old_value: *mut itimerspec, ) -> ::c_int; pub fn syscall(num: ::c_long, ...) -> ::c_long; - pub fn sched_getaffinity( - pid: ::pid_t, - cpusetsize: ::size_t, - cpuset: *mut cpu_set_t, - ) -> ::c_int; + pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) + -> ::c_int; pub fn sched_setaffinity( pid: ::pid_t, cpusetsize: ::size_t, @@ -2568,12 +2497,8 @@ extern "C" { maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; - pub fn epoll_ctl( - epfd: ::c_int, - op: ::c_int, - fd: ::c_int, - event: *mut ::epoll_event, - ) -> ::c_int; + pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) + -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, @@ -2582,16 +2507,8 @@ extern "C" { pub fn unshare(flags: ::c_int) -> ::c_int; pub fn umount(target: *const ::c_char) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; - pub fn tee( - fd_in: ::c_int, - fd_out: ::c_int, - len: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; - pub fn settimeofday( - tv: *const ::timeval, - tz: *const ::timezone, - ) -> ::c_int; + pub fn tee(fd_in: ::c_int, fd_out: ::c_int, len: ::size_t, flags: ::c_uint) -> ::ssize_t; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn splice( fd_in: ::c_int, off_in: *mut ::loff_t, @@ -2601,17 +2518,10 @@ extern "C" { flags: ::c_uint, ) -> ::ssize_t; pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; - pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) - -> ::c_int; - pub fn sem_timedwait( - sem: *mut sem_t, - abstime: *const ::timespec, - ) -> ::c_int; + pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; - pub fn sched_setparam( - pid: ::pid_t, - param: *const ::sched_param, - ) -> ::c_int; + pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn setns(fd: ::c_int, nstype: ::c_int) -> ::c_int; pub fn swapoff(puath: *const ::c_char) -> ::c_int; pub fn vmsplice( @@ -2702,11 +2612,7 @@ extern "C" { buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; - pub fn pthread_sigmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; @@ -2779,17 +2685,9 @@ extern "C" { ) -> ::c_int; pub fn inotify_init() -> ::c_int; pub fn inotify_init1(flags: ::c_int) -> ::c_int; - pub fn inotify_add_watch( - fd: ::c_int, - path: *const ::c_char, - mask: u32, - ) -> ::c_int; + pub fn inotify_add_watch(fd: ::c_int, path: *const ::c_char, mask: u32) -> ::c_int; - pub fn regcomp( - preg: *mut ::regex_t, - pattern: *const ::c_char, - cflags: ::c_int, - ) -> ::c_int; + pub fn regcomp(preg: *mut ::regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regexec( preg: *const ::regex_t, diff --git a/vendor/libc/src/unix/linux_like/emscripten/mod.rs b/vendor/libc/src/unix/linux_like/emscripten/mod.rs index 9599e1992f..ee9d4d4dca 100644 --- a/vendor/libc/src/unix/linux_like/emscripten/mod.rs +++ b/vendor/libc/src/unix/linux_like/emscripten/mod.rs @@ -1776,11 +1776,7 @@ extern "C" { pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int; pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn atof(s: *const ::c_char) -> ::c_double; @@ -1794,23 +1790,12 @@ extern "C" { pub fn endpwent(); pub fn getpwent() -> *mut passwd; - pub fn shm_open( - name: *const c_char, - oflag: ::c_int, - mode: mode_t, - ) -> ::c_int; + pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn __errno_location() -> *mut ::c_int; - pub fn fopen64( - filename: *const c_char, - mode: *const c_char, - ) -> *mut ::FILE; + pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn freopen64( filename: *const c_char, mode: *const c_char, @@ -1819,38 +1804,16 @@ extern "C" { pub fn tmpfile64() -> *mut ::FILE; pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int; pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int; - pub fn fseeko64( - stream: *mut ::FILE, - offset: ::off64_t, - whence: ::c_int, - ) -> ::c_int; + pub fn fseeko64(stream: *mut ::FILE, offset: ::off64_t, whence: ::c_int) -> ::c_int; pub fn ftello64(stream: *mut ::FILE) -> ::off64_t; - pub fn posix_fallocate( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn pwritev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn preadv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; + pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) + -> ::ssize_t; + pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; - pub fn mkostemps( - template: *mut ::c_char, - suffixlen: ::c_int, - flags: ::c_int, - ) -> ::c_int; - pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) - -> *mut ::c_char; + pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; + pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, @@ -1869,11 +1832,7 @@ extern "C" { pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; // Not available now on Android - pub fn mkfifoat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); @@ -1888,35 +1847,21 @@ extern "C" { pub fn glob( pattern: *const c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); - pub fn posix_madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, diff --git a/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs b/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs new file mode 100644 index 0000000000..e3401d4b72 --- /dev/null +++ b/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs @@ -0,0 +1,100 @@ +// include/uapi/asm-generic/socket.h +// arch/alpha/include/uapi/asm/socket.h +// tools/include/uapi/asm-generic/socket.h +// arch/mips/include/uapi/asm/socket.h +pub const SOL_SOCKET: ::c_int = 1; + +// Defined in unix/linux_like/mod.rs +// pub const SO_DEBUG: ::c_int = 1; +pub const SO_REUSEADDR: ::c_int = 2; +pub const SO_TYPE: ::c_int = 3; +pub const SO_ERROR: ::c_int = 4; +pub const SO_DONTROUTE: ::c_int = 5; +pub const SO_BROADCAST: ::c_int = 6; +pub const SO_SNDBUF: ::c_int = 7; +pub const SO_RCVBUF: ::c_int = 8; +pub const SO_KEEPALIVE: ::c_int = 9; +pub const SO_OOBINLINE: ::c_int = 10; +pub const SO_NO_CHECK: ::c_int = 11; +pub const SO_PRIORITY: ::c_int = 12; +pub const SO_LINGER: ::c_int = 13; +pub const SO_BSDCOMPAT: ::c_int = 14; +pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_PASSCRED: ::c_int = 16; +pub const SO_PEERCRED: ::c_int = 17; +pub const SO_RCVLOWAT: ::c_int = 18; +pub const SO_SNDLOWAT: ::c_int = 19; +pub const SO_RCVTIMEO: ::c_int = 20; +pub const SO_SNDTIMEO: ::c_int = 21; +// pub const SO_RCVTIMEO_OLD: ::c_int = 20; +// pub const SO_SNDTIMEO_OLD: ::c_int = 21; +pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; +pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; +pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_ATTACH_FILTER: ::c_int = 26; +pub const SO_DETACH_FILTER: ::c_int = 27; +pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; +pub const SO_PEERNAME: ::c_int = 28; +pub const SO_TIMESTAMP: ::c_int = 29; +// pub const SO_TIMESTAMP_OLD: ::c_int = 29; +pub const SO_ACCEPTCONN: ::c_int = 30; +pub const SO_PEERSEC: ::c_int = 31; +pub const SO_SNDBUFFORCE: ::c_int = 32; +pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_PASSSEC: ::c_int = 34; +pub const SO_TIMESTAMPNS: ::c_int = 35; +// pub const SO_TIMESTAMPNS_OLD: ::c_int = 35; +pub const SO_MARK: ::c_int = 36; +pub const SO_TIMESTAMPING: ::c_int = 37; +// pub const SO_TIMESTAMPING_OLD: ::c_int = 37; +pub const SO_PROTOCOL: ::c_int = 38; +pub const SO_DOMAIN: ::c_int = 39; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_WIFI_STATUS: ::c_int = 41; +pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_NOFCS: ::c_int = 43; +pub const SO_LOCK_FILTER: ::c_int = 44; +pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; +pub const SO_BUSY_POLL: ::c_int = 46; +pub const SO_MAX_PACING_RATE: ::c_int = 47; +pub const SO_BPF_EXTENSIONS: ::c_int = 48; +pub const SO_INCOMING_CPU: ::c_int = 49; +pub const SO_ATTACH_BPF: ::c_int = 50; +pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; +pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; +pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; +pub const SO_CNX_ADVICE: ::c_int = 53; +pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; +pub const SO_MEMINFO: ::c_int = 55; +pub const SO_INCOMING_NAPI_ID: ::c_int = 56; +pub const SO_COOKIE: ::c_int = 57; +pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; +pub const SO_PEERGROUPS: ::c_int = 59; +pub const SO_ZEROCOPY: ::c_int = 60; +pub const SO_TXTIME: ::c_int = 61; +pub const SCM_TXTIME: ::c_int = SO_TXTIME; +pub const SO_BINDTOIFINDEX: ::c_int = 62; +cfg_if! { + // Some of these platforms in CI already have these constants. + // But they may still not have those _OLD ones. + if #[cfg(all(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "aarch64"), + not(target_env = "musl")))] { + pub const SO_TIMESTAMP_NEW: ::c_int = 63; + pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; + pub const SO_TIMESTAMPING_NEW: ::c_int = 65; + pub const SO_RCVTIMEO_NEW: ::c_int = 66; + pub const SO_SNDTIMEO_NEW: ::c_int = 67; + pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; + } +} +// pub const SO_PREFER_BUSY_POLL: ::c_int = 69; +// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70; + +// Defined in unix/linux_like/mod.rs +// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; +pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; +pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; diff --git a/vendor/libc/src/unix/linux_like/linux/arch/mips/mod.rs b/vendor/libc/src/unix/linux_like/linux/arch/mips/mod.rs new file mode 100644 index 0000000000..cdbdca2bbf --- /dev/null +++ b/vendor/libc/src/unix/linux_like/linux/arch/mips/mod.rs @@ -0,0 +1,96 @@ +// arch/mips/include/uapi/asm/socket.h +pub const SOL_SOCKET: ::c_int = 0xffff; + +// Defined in unix/linux_like/mod.rs +// pub const SO_DEBUG: ::c_int = 0x0001; +pub const SO_REUSEADDR: ::c_int = 0x0004; +pub const SO_KEEPALIVE: ::c_int = 0x0008; +pub const SO_DONTROUTE: ::c_int = 0x0010; +pub const SO_BROADCAST: ::c_int = 0x0020; +pub const SO_LINGER: ::c_int = 0x0080; +pub const SO_OOBINLINE: ::c_int = 0x0100; +pub const SO_REUSEPORT: ::c_int = 0x0200; +pub const SO_TYPE: ::c_int = 0x1008; +// pub const SO_STYLE: ::c_int = SO_TYPE; +pub const SO_ERROR: ::c_int = 0x1007; +pub const SO_SNDBUF: ::c_int = 0x1001; +pub const SO_RCVBUF: ::c_int = 0x1002; +pub const SO_SNDLOWAT: ::c_int = 0x1003; +pub const SO_RCVLOWAT: ::c_int = 0x1004; +// NOTE: These definitions are now being renamed with _OLD postfix, +// but CI haven't support them yet. +// Some related consts could be found in b32.rs and b64.rs +pub const SO_SNDTIMEO: ::c_int = 0x1005; +pub const SO_RCVTIMEO: ::c_int = 0x1006; +// pub const SO_SNDTIMEO_OLD: ::c_int = 0x1005; +// pub const SO_RCVTIMEO_OLD: ::c_int = 0x1006; +pub const SO_ACCEPTCONN: ::c_int = 0x1009; +pub const SO_PROTOCOL: ::c_int = 0x1028; +pub const SO_DOMAIN: ::c_int = 0x1029; + +pub const SO_NO_CHECK: ::c_int = 11; +pub const SO_PRIORITY: ::c_int = 12; +pub const SO_BSDCOMPAT: ::c_int = 14; +pub const SO_PASSCRED: ::c_int = 17; +pub const SO_PEERCRED: ::c_int = 18; +pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; +pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; +pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_ATTACH_FILTER: ::c_int = 26; +pub const SO_DETACH_FILTER: ::c_int = 27; +pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; +pub const SO_PEERNAME: ::c_int = 28; +pub const SO_PEERSEC: ::c_int = 30; +pub const SO_SNDBUFFORCE: ::c_int = 31; +pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_PASSSEC: ::c_int = 34; +pub const SO_MARK: ::c_int = 36; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_WIFI_STATUS: ::c_int = 41; +pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_NOFCS: ::c_int = 43; +pub const SO_LOCK_FILTER: ::c_int = 44; +pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; +pub const SO_BUSY_POLL: ::c_int = 46; +pub const SO_MAX_PACING_RATE: ::c_int = 47; +pub const SO_BPF_EXTENSIONS: ::c_int = 48; +pub const SO_INCOMING_CPU: ::c_int = 49; +pub const SO_ATTACH_BPF: ::c_int = 50; +pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; +pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; +pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; +pub const SO_CNX_ADVICE: ::c_int = 53; +pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; +pub const SO_MEMINFO: ::c_int = 55; +pub const SO_INCOMING_NAPI_ID: ::c_int = 56; +pub const SO_COOKIE: ::c_int = 57; +pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; +pub const SO_PEERGROUPS: ::c_int = 59; +pub const SO_ZEROCOPY: ::c_int = 60; +pub const SO_TXTIME: ::c_int = 61; +pub const SCM_TXTIME: ::c_int = SO_TXTIME; +pub const SO_BINDTOIFINDEX: ::c_int = 62; +// NOTE: These definitions are now being renamed with _OLD postfix, +// but CI haven't support them yet. +// Some related consts could be found in b32.rs and b64.rs +pub const SO_TIMESTAMP: ::c_int = 29; +pub const SO_TIMESTAMPNS: ::c_int = 35; +pub const SO_TIMESTAMPING: ::c_int = 37; +// pub const SO_TIMESTAMP_OLD: ::c_int = 29; +// pub const SO_TIMESTAMPNS_OLD: ::c_int = 35; +// pub const SO_TIMESTAMPING_OLD: ::c_int = 37; +// pub const SO_TIMESTAMP_NEW: ::c_int = 63; +// pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; +// pub const SO_TIMESTAMPING_NEW: ::c_int = 65; +// pub const SO_RCVTIMEO_NEW: ::c_int = 66; +// pub const SO_SNDTIMEO_NEW: ::c_int = 67; +// pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; +// pub const SO_PREFER_BUSY_POLL: ::c_int = 69; +// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70; + +// Defined in unix/linux_like/mod.rs +// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; +pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; +pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; diff --git a/vendor/libc/src/unix/linux_like/linux/arch/mod.rs b/vendor/libc/src/unix/linux_like/linux/arch/mod.rs new file mode 100644 index 0000000000..c1528f593f --- /dev/null +++ b/vendor/libc/src/unix/linux_like/linux/arch/mod.rs @@ -0,0 +1,15 @@ +cfg_if! { + if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { + mod mips; + pub use self::mips::*; + } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { + mod powerpc; + pub use self::powerpc::*; + } else if #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] { + mod sparc; + pub use self::sparc::*; + } else { + mod generic; + pub use self::generic::*; + } +} diff --git a/vendor/libc/src/unix/linux_like/linux/arch/powerpc/mod.rs b/vendor/libc/src/unix/linux_like/linux/arch/powerpc/mod.rs new file mode 100644 index 0000000000..89cc09e3f0 --- /dev/null +++ b/vendor/libc/src/unix/linux_like/linux/arch/powerpc/mod.rs @@ -0,0 +1,91 @@ +// arch/powerpc/include/uapi/asm/socket.h + +pub const SOL_SOCKET: ::c_int = 1; + +// Defined in unix/linux_like/mod.rs +// pub const SO_DEBUG: ::c_int = 1; +pub const SO_REUSEADDR: ::c_int = 2; +pub const SO_TYPE: ::c_int = 3; +pub const SO_ERROR: ::c_int = 4; +pub const SO_DONTROUTE: ::c_int = 5; +pub const SO_BROADCAST: ::c_int = 6; +pub const SO_SNDBUF: ::c_int = 7; +pub const SO_RCVBUF: ::c_int = 8; +pub const SO_KEEPALIVE: ::c_int = 9; +pub const SO_OOBINLINE: ::c_int = 10; +pub const SO_NO_CHECK: ::c_int = 11; +pub const SO_PRIORITY: ::c_int = 12; +pub const SO_LINGER: ::c_int = 13; +pub const SO_BSDCOMPAT: ::c_int = 14; +pub const SO_REUSEPORT: ::c_int = 15; +// powerpc only differs in these +pub const SO_RCVLOWAT: ::c_int = 16; +pub const SO_SNDLOWAT: ::c_int = 17; +pub const SO_RCVTIMEO: ::c_int = 18; +pub const SO_SNDTIMEO: ::c_int = 19; +// pub const SO_RCVTIMEO_OLD: ::c_int = 18; +// pub const SO_SNDTIMEO_OLD: ::c_int = 19; +pub const SO_PASSCRED: ::c_int = 20; +pub const SO_PEERCRED: ::c_int = 21; +// end +pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; +pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; +pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; +pub const SO_BINDTODEVICE: ::c_int = 25; +pub const SO_ATTACH_FILTER: ::c_int = 26; +pub const SO_DETACH_FILTER: ::c_int = 27; +pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; +pub const SO_PEERNAME: ::c_int = 28; +pub const SO_TIMESTAMP: ::c_int = 29; +// pub const SO_TIMESTAMP_OLD: ::c_int = 29; +pub const SO_ACCEPTCONN: ::c_int = 30; +pub const SO_PEERSEC: ::c_int = 31; +pub const SO_SNDBUFFORCE: ::c_int = 32; +pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_PASSSEC: ::c_int = 34; +pub const SO_TIMESTAMPNS: ::c_int = 35; +// pub const SO_TIMESTAMPNS_OLD: ::c_int = 35; +pub const SO_MARK: ::c_int = 36; +pub const SO_TIMESTAMPING: ::c_int = 37; +// pub const SO_TIMESTAMPING_OLD: ::c_int = 37; +pub const SO_PROTOCOL: ::c_int = 38; +pub const SO_DOMAIN: ::c_int = 39; +pub const SO_RXQ_OVFL: ::c_int = 40; +pub const SO_WIFI_STATUS: ::c_int = 41; +pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; +pub const SO_PEEK_OFF: ::c_int = 42; +pub const SO_NOFCS: ::c_int = 43; +pub const SO_LOCK_FILTER: ::c_int = 44; +pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; +pub const SO_BUSY_POLL: ::c_int = 46; +pub const SO_MAX_PACING_RATE: ::c_int = 47; +pub const SO_BPF_EXTENSIONS: ::c_int = 48; +pub const SO_INCOMING_CPU: ::c_int = 49; +pub const SO_ATTACH_BPF: ::c_int = 50; +pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; +pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; +pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; +pub const SO_CNX_ADVICE: ::c_int = 53; +pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; +pub const SO_MEMINFO: ::c_int = 55; +pub const SO_INCOMING_NAPI_ID: ::c_int = 56; +pub const SO_COOKIE: ::c_int = 57; +pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; +pub const SO_PEERGROUPS: ::c_int = 59; +pub const SO_ZEROCOPY: ::c_int = 60; +pub const SO_TXTIME: ::c_int = 61; +pub const SCM_TXTIME: ::c_int = SO_TXTIME; +pub const SO_BINDTOIFINDEX: ::c_int = 62; +// pub const SO_TIMESTAMP_NEW: ::c_int = 63; +// pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; +// pub const SO_TIMESTAMPING_NEW: ::c_int = 65; +// pub const SO_RCVTIMEO_NEW: ::c_int = 66; +// pub const SO_SNDTIMEO_NEW: ::c_int = 67; +// pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; +// pub const SO_PREFER_BUSY_POLL: ::c_int = 69; +// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70; + +// Defined in unix/linux_like/mod.rs +// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; +pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; +pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; diff --git a/vendor/libc/src/unix/linux_like/linux/arch/sparc/mod.rs b/vendor/libc/src/unix/linux_like/linux/arch/sparc/mod.rs new file mode 100644 index 0000000000..d4f9bb0ebc --- /dev/null +++ b/vendor/libc/src/unix/linux_like/linux/arch/sparc/mod.rs @@ -0,0 +1,88 @@ +// arch/sparc/include/uapi/asm/socket.h +pub const SOL_SOCKET: ::c_int = 0xffff; + +// Defined in unix/linux_like/mod.rs +// pub const SO_DEBUG: ::c_int = 0x0001; +pub const SO_PASSCRED: ::c_int = 0x0002; +pub const SO_REUSEADDR: ::c_int = 0x0004; +pub const SO_KEEPALIVE: ::c_int = 0x0008; +pub const SO_DONTROUTE: ::c_int = 0x0010; +pub const SO_BROADCAST: ::c_int = 0x0020; +pub const SO_PEERCRED: ::c_int = 0x0040; +pub const SO_LINGER: ::c_int = 0x0080; +pub const SO_OOBINLINE: ::c_int = 0x0100; +pub const SO_REUSEPORT: ::c_int = 0x0200; +pub const SO_BSDCOMPAT: ::c_int = 0x0400; +pub const SO_RCVLOWAT: ::c_int = 0x0800; +pub const SO_SNDLOWAT: ::c_int = 0x1000; +pub const SO_RCVTIMEO: ::c_int = 0x2000; +pub const SO_SNDTIMEO: ::c_int = 0x4000; +// pub const SO_RCVTIMEO_OLD: ::c_int = 0x2000; +// pub const SO_SNDTIMEO_OLD: ::c_int = 0x4000; +pub const SO_ACCEPTCONN: ::c_int = 0x8000; +pub const SO_SNDBUF: ::c_int = 0x1001; +pub const SO_RCVBUF: ::c_int = 0x1002; +pub const SO_SNDBUFFORCE: ::c_int = 0x100a; +pub const SO_RCVBUFFORCE: ::c_int = 0x100b; +pub const SO_ERROR: ::c_int = 0x1007; +pub const SO_TYPE: ::c_int = 0x1008; +pub const SO_PROTOCOL: ::c_int = 0x1028; +pub const SO_DOMAIN: ::c_int = 0x1029; +pub const SO_NO_CHECK: ::c_int = 0x000b; +pub const SO_PRIORITY: ::c_int = 0x000c; +pub const SO_BINDTODEVICE: ::c_int = 0x000d; +pub const SO_ATTACH_FILTER: ::c_int = 0x001a; +pub const SO_DETACH_FILTER: ::c_int = 0x001b; +pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; +pub const SO_PEERNAME: ::c_int = 0x001c; +pub const SO_PEERSEC: ::c_int = 0x001e; +pub const SO_PASSSEC: ::c_int = 0x001f; +pub const SO_MARK: ::c_int = 0x0022; +pub const SO_RXQ_OVFL: ::c_int = 0x0024; +pub const SO_WIFI_STATUS: ::c_int = 0x0025; +pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; +pub const SO_PEEK_OFF: ::c_int = 0x0026; +pub const SO_NOFCS: ::c_int = 0x0027; +pub const SO_LOCK_FILTER: ::c_int = 0x0028; +pub const SO_SELECT_ERR_QUEUE: ::c_int = 0x0029; +pub const SO_BUSY_POLL: ::c_int = 0x0030; +pub const SO_MAX_PACING_RATE: ::c_int = 0x0031; +pub const SO_BPF_EXTENSIONS: ::c_int = 0x0032; +pub const SO_INCOMING_CPU: ::c_int = 0x0033; +pub const SO_ATTACH_BPF: ::c_int = 0x0034; +pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; +pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 0x0035; +pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 0x0036; +pub const SO_CNX_ADVICE: ::c_int = 0x0037; +pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 0x0038; +pub const SO_MEMINFO: ::c_int = 0x0039; +pub const SO_INCOMING_NAPI_ID: ::c_int = 0x003a; +pub const SO_COOKIE: ::c_int = 0x003b; +pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 0x003c; +pub const SO_PEERGROUPS: ::c_int = 0x003d; +pub const SO_ZEROCOPY: ::c_int = 0x003e; +pub const SO_TXTIME: ::c_int = 0x003f; +pub const SCM_TXTIME: ::c_int = SO_TXTIME; +pub const SO_BINDTOIFINDEX: ::c_int = 0x0041; +pub const SO_SECURITY_AUTHENTICATION: ::c_int = 0x5001; +pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 0x5002; +pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 0x5004; +pub const SO_TIMESTAMP: ::c_int = 0x001d; +pub const SO_TIMESTAMPNS: ::c_int = 0x0021; +pub const SO_TIMESTAMPING: ::c_int = 0x0023; +// pub const SO_TIMESTAMP_OLD: ::c_int = 0x001d; +// pub const SO_TIMESTAMPNS_OLD: ::c_int = 0x0021; +// pub const SO_TIMESTAMPING_OLD: ::c_int = 0x0023; +// pub const SO_TIMESTAMP_NEW: ::c_int = 0x0046; +// pub const SO_TIMESTAMPNS_NEW: ::c_int = 0x0042; +// pub const SO_TIMESTAMPING_NEW: ::c_int = 0x0043; +// pub const SO_RCVTIMEO_NEW: ::c_int = 0x0044; +// pub const SO_SNDTIMEO_NEW: ::c_int = 0x0045; +// pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 0x0047; +// pub const SO_PREFER_BUSY_POLL: ::c_int = 0x0048; +// pub const SO_BUSY_POLL_BUDGET: ::c_int = 0x0049; + +// Defined in unix/linux_like/mod.rs +// pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; +pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; +pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs index d084450b9f..0e7fb70f6e 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs @@ -214,8 +214,6 @@ pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_SYNC: ::c_int = 0x080000; -pub const SOL_SOCKET: ::c_int = 1; - pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; @@ -301,29 +299,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_LINGER: ::c_int = 13; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; - pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; @@ -868,8 +843,25 @@ pub const SYS_pkey_mprotect: ::c_long = 394; pub const SYS_pkey_alloc: ::c_long = 395; pub const SYS_pkey_free: ::c_long = 396; pub const SYS_statx: ::c_long = 397; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; cfg_if! { if #[cfg(libc_align)] { diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs index 0903eaee75..4ded201fb4 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs @@ -527,8 +527,25 @@ pub const SYS_pkey_mprotect: ::c_long = 4000 + 363; pub const SYS_pkey_alloc: ::c_long = 4000 + 364; pub const SYS_pkey_free: ::c_long = 4000 + 365; pub const SYS_statx: ::c_long = 4000 + 366; +pub const SYS_pidfd_send_signal: ::c_long = 4000 + 424; +pub const SYS_io_uring_setup: ::c_long = 4000 + 425; +pub const SYS_io_uring_enter: ::c_long = 4000 + 426; +pub const SYS_io_uring_register: ::c_long = 4000 + 427; +pub const SYS_open_tree: ::c_long = 4000 + 428; +pub const SYS_move_mount: ::c_long = 4000 + 429; +pub const SYS_fsopen: ::c_long = 4000 + 430; +pub const SYS_fsconfig: ::c_long = 4000 + 431; +pub const SYS_fsmount: ::c_long = 4000 + 432; +pub const SYS_fspick: ::c_long = 4000 + 433; pub const SYS_pidfd_open: ::c_long = 4000 + 434; pub const SYS_clone3: ::c_long = 4000 + 435; +pub const SYS_close_range: ::c_long = 4000 + 436; +pub const SYS_openat2: ::c_long = 4000 + 437; +pub const SYS_pidfd_getfd: ::c_long = 4000 + 438; +pub const SYS_faccessat2: ::c_long = 4000 + 439; +pub const SYS_process_madvise: ::c_long = 4000 + 440; +pub const SYS_epoll_pwait2: ::c_long = 4000 + 441; +pub const SYS_mount_setattr: ::c_long = 4000 + 442; pub const O_DIRECT: ::c_int = 0x8000; pub const O_DIRECTORY: ::c_int = 0x10000; @@ -651,55 +668,6 @@ pub const MAP_STACK: ::c_int = 0x40000; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; -pub const SOL_SOCKET: ::c_int = 0xffff; - -pub const SO_REUSEADDR: ::c_int = 0x0004; -pub const SO_KEEPALIVE: ::c_int = 0x0008; -pub const SO_DONTROUTE: ::c_int = 0x0010; -pub const SO_BROADCAST: ::c_int = 0x0020; -pub const SO_LINGER: ::c_int = 0x0080; -pub const SO_OOBINLINE: ::c_int = 0x0100; -pub const SO_REUSEPORT: ::c_int = 0x0200; -pub const SO_TYPE: ::c_int = 0x1008; -pub const SO_STYLE: ::c_int = SO_TYPE; -pub const SO_ERROR: ::c_int = 0x1007; -pub const SO_SNDBUF: ::c_int = 0x1001; -pub const SO_RCVBUF: ::c_int = 0x1002; -pub const SO_SNDLOWAT: ::c_int = 0x1003; -pub const SO_RCVLOWAT: ::c_int = 0x1004; -pub const SO_SNDTIMEO: ::c_int = 0x1005; -pub const SO_RCVTIMEO: ::c_int = 0x1006; -pub const SO_ACCEPTCONN: ::c_int = 0x1009; -pub const SO_PROTOCOL: ::c_int = 0x1028; -pub const SO_DOMAIN: ::c_int = 0x1029; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PASSCRED: ::c_int = 17; -pub const SO_PEERCRED: ::c_int = 18; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_PEERSEC: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 31; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; - -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; - pub const FIOCLEX: ::c_ulong = 0x6601; pub const FIONCLEX: ::c_ulong = 0x6602; pub const FIONBIO: ::c_ulong = 0x667e; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/mod.rs index c7fa1a8a28..239492b1c9 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/mod.rs @@ -140,10 +140,6 @@ s! { } } -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_TIMESTAMP: ::c_int = 29; - pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; @@ -162,11 +158,6 @@ cfg_if! { pub const O_NOATIME: ::c_int = 0x200000; pub const O_PATH: ::c_int = 0x1000000; pub const O_TMPFILE: ::c_int = 0x2000000 | O_DIRECTORY; - pub const SO_BINDTODEVICE: ::c_int = 0x000d; - pub const SO_MARK: ::c_int = 0x0022; - pub const SO_RXQ_OVFL: ::c_int = 0x0024; - pub const SO_PEEK_OFF: ::c_int = 0x0026; - pub const SO_BUSY_POLL: ::c_int = 0x0030; pub const SA_ONSTACK: ::c_int = 1; @@ -213,11 +204,6 @@ cfg_if! { pub const O_NOATIME: ::c_int = 0o1000000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; - pub const SO_BINDTODEVICE: ::c_int = 25; - pub const SO_MARK: ::c_int = 36; - pub const SO_RXQ_OVFL: ::c_int = 40; - pub const SO_PEEK_OFF: ::c_int = 42; - pub const SO_BUSY_POLL: ::c_int = 46; pub const SA_ONSTACK: ::c_int = 0x08000000; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs index c22b792402..59c1e1c8da 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs @@ -215,8 +215,6 @@ pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_SYNC: ::c_int = 0x080000; -pub const SOL_SOCKET: ::c_int = 1; - pub const EDEADLOCK: ::c_int = 58; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; @@ -302,30 +300,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_LINGER: ::c_int = 13; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_RCVLOWAT: ::c_int = 16; -pub const SO_SNDLOWAT: ::c_int = 17; -pub const SO_RCVTIMEO: ::c_int = 18; -pub const SO_SNDTIMEO: ::c_int = 19; -pub const SO_PASSCRED: ::c_int = 20; -pub const SO_PEERCRED: ::c_int = 21; - pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; @@ -872,5 +846,22 @@ pub const SYS_preadv2: ::c_long = 380; pub const SYS_pwritev2: ::c_long = 381; pub const SYS_kexec_file_load: ::c_long = 382; pub const SYS_statx: ::c_long = 383; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs index 1732c23104..96ee5a3bf2 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs @@ -300,51 +300,7 @@ pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_LINGER: ::c_int = 13; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = 26; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PEERSEC: ::c_int = 31; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = 35; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = 41; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = 27; + pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_SIGINFO: ::c_int = 4; @@ -818,3 +774,22 @@ pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; +pub const SYS_pidfd_open: ::c_long = 434; +pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs index 33400b3a72..4364814094 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs @@ -320,25 +320,6 @@ pub const ENOTRECOVERABLE: ::c_int = 133; pub const EHWPOISON: ::c_int = 135; pub const ERFKILL: ::c_int = 134; -pub const SOL_SOCKET: ::c_int = 0xffff; - -pub const SO_PASSCRED: ::c_int = 2; -pub const SO_REUSEADDR: ::c_int = 4; -pub const SO_TYPE: ::c_int = 0x1008; -pub const SO_ERROR: ::c_int = 0x1007; -pub const SO_DONTROUTE: ::c_int = 16; -pub const SO_BROADCAST: ::c_int = 32; -pub const SO_SNDBUF: ::c_int = 0x1001; -pub const SO_RCVBUF: ::c_int = 0x1002; -pub const SO_SNDBUFFORCE: ::c_int = 0x100a; -pub const SO_RCVBUFFORCE: ::c_int = 0x100b; -pub const SO_DOMAIN: ::c_int = 0x1029; -pub const SO_KEEPALIVE: ::c_int = 8; -pub const SO_OOBINLINE: ::c_int = 0x100; -pub const SO_LINGER: ::c_int = 128; -pub const SO_REUSEPORT: ::c_int = 0x200; -pub const SO_ACCEPTCONN: ::c_int = 0x8000; - pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; @@ -420,12 +401,6 @@ pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; -pub const SO_PEERCRED: ::c_int = 0x40; -pub const SO_RCVLOWAT: ::c_int = 0x800; -pub const SO_SNDLOWAT: ::c_int = 0x1000; -pub const SO_RCVTIMEO: ::c_int = 0x2000; -pub const SO_SNDTIMEO: ::c_int = 0x4000; - pub const FIOCLEX: ::c_ulong = 0x20006601; pub const FIONCLEX: ::c_ulong = 0x20006602; pub const FIONBIO: ::c_ulong = 0x8004667e; @@ -906,9 +881,26 @@ pub const SYS_copy_file_range: ::c_long = 357; pub const SYS_preadv2: ::c_long = 358; pub const SYS_pwritev2: ::c_long = 359; pub const SYS_statx: ::c_long = 360; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; // Reserved in the kernel, but not actually implemented yet pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; cfg_if! { if #[cfg(libc_align)] { diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs index 130ed85095..75edd27885 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs @@ -401,8 +401,6 @@ pub const RLIMIT_RSS: ::__rlimit_resource_t = 5; pub const RLIMIT_AS: ::__rlimit_resource_t = 9; pub const RLIMIT_MEMLOCK: ::__rlimit_resource_t = 8; -pub const SOL_SOCKET: ::c_int = 1; - pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; @@ -503,30 +501,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_LINGER: ::c_int = 13; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; - pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; @@ -1103,8 +1077,25 @@ pub const SYS_pkey_mprotect: ::c_long = 380; pub const SYS_pkey_alloc: ::c_long = 381; pub const SYS_pkey_free: ::c_long = 382; pub const SYS_statx: ::c_long = 383; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; // offsets in user_regs_structs, from sys/reg.h pub const EBX: ::c_int = 0; @@ -1149,16 +1140,8 @@ pub const REG_SS: ::c_int = 18; extern "C" { pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int; pub fn setcontext(ucp: *const ucontext_t) -> ::c_int; - pub fn makecontext( - ucp: *mut ucontext_t, - func: extern "C" fn(), - argc: ::c_int, - ... - ); - pub fn swapcontext( - uocp: *mut ucontext_t, - ucp: *const ucontext_t, - ) -> ::c_int; + pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); + pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs index e9a06c7718..35fe306122 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs @@ -322,80 +322,6 @@ pub const ERFKILL: ::c_int = 132; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; -pub const SOL_SOCKET: ::c_int = 1; - -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PEERSEC: ::c_int = 31; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; -pub const SO_MARK: ::c_int = 36; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_BUSY_POLL: ::c_int = 46; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; -pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; -pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; -pub const SO_CNX_ADVICE: ::c_int = 53; -pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; -pub const SO_MEMINFO: ::c_int = 55; -pub const SO_INCOMING_NAPI_ID: ::c_int = 56; -pub const SO_COOKIE: ::c_int = 57; -pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; -pub const SO_PEERGROUPS: ::c_int = 59; -pub const SO_ZEROCOPY: ::c_int = 60; -pub const SO_TXTIME: ::c_int = 61; -pub const SCM_TXTIME: ::c_int = SO_TXTIME; -pub const SO_BINDTOIFINDEX: ::c_int = 62; -pub const SO_TIMESTAMP_NEW: ::c_int = 63; -pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; -pub const SO_TIMESTAMPING_NEW: ::c_int = 65; -pub const SO_RCVTIMEO_NEW: ::c_int = 66; -pub const SO_SNDTIMEO_NEW: ::c_int = 67; -pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; - pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; @@ -976,8 +902,25 @@ pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; extern "C" { pub fn sysctl( diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs index ca82528935..87939566f7 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs @@ -577,8 +577,25 @@ pub const SYS_pkey_mprotect: ::c_long = 5000 + 323; pub const SYS_pkey_alloc: ::c_long = 5000 + 324; pub const SYS_pkey_free: ::c_long = 5000 + 325; pub const SYS_statx: ::c_long = 5000 + 326; +pub const SYS_pidfd_send_signal: ::c_long = 5000 + 424; +pub const SYS_io_uring_setup: ::c_long = 5000 + 425; +pub const SYS_io_uring_enter: ::c_long = 5000 + 426; +pub const SYS_io_uring_register: ::c_long = 5000 + 427; +pub const SYS_open_tree: ::c_long = 5000 + 428; +pub const SYS_move_mount: ::c_long = 5000 + 429; +pub const SYS_fsopen: ::c_long = 5000 + 430; +pub const SYS_fsconfig: ::c_long = 5000 + 431; +pub const SYS_fsmount: ::c_long = 5000 + 432; +pub const SYS_fspick: ::c_long = 5000 + 433; pub const SYS_pidfd_open: ::c_long = 5000 + 434; pub const SYS_clone3: ::c_long = 5000 + 435; +pub const SYS_close_range: ::c_long = 5000 + 436; +pub const SYS_openat2: ::c_long = 5000 + 437; +pub const SYS_pidfd_getfd: ::c_long = 5000 + 438; +pub const SYS_faccessat2: ::c_long = 5000 + 439; +pub const SYS_process_madvise: ::c_long = 5000 + 440; +pub const SYS_epoll_pwait2: ::c_long = 5000 + 441; +pub const SYS_mount_setattr: ::c_long = 5000 + 442; pub const SFD_CLOEXEC: ::c_int = 0x080000; @@ -739,62 +756,6 @@ pub const MAP_HUGETLB: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; -pub const SOL_SOCKET: ::c_int = 0xffff; - -pub const SO_REUSEADDR: ::c_int = 0x0004; -pub const SO_KEEPALIVE: ::c_int = 0x0008; -pub const SO_DONTROUTE: ::c_int = 0x0010; -pub const SO_BROADCAST: ::c_int = 0x0020; -pub const SO_LINGER: ::c_int = 0x0080; -pub const SO_OOBINLINE: ::c_int = 0x0100; -pub const SO_REUSEPORT: ::c_int = 0x0200; -pub const SO_TYPE: ::c_int = 0x1008; -pub const SO_STYLE: ::c_int = SO_TYPE; -pub const SO_ERROR: ::c_int = 0x1007; -pub const SO_SNDBUF: ::c_int = 0x1001; -pub const SO_RCVBUF: ::c_int = 0x1002; -pub const SO_SNDLOWAT: ::c_int = 0x1003; -pub const SO_RCVLOWAT: ::c_int = 0x1004; -pub const SO_SNDTIMEO: ::c_int = 0x1005; -pub const SO_RCVTIMEO: ::c_int = 0x1006; -pub const SO_ACCEPTCONN: ::c_int = 0x1009; -pub const SO_PROTOCOL: ::c_int = 0x1028; -pub const SO_DOMAIN: ::c_int = 0x1029; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_PASSCRED: ::c_int = 17; -pub const SO_PEERCRED: ::c_int = 18; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_PEERSEC: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 31; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; -pub const SO_MARK: ::c_int = 36; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_BUSY_POLL: ::c_int = 46; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; - pub const FIOCLEX: ::c_ulong = 0x6601; pub const FIONCLEX: ::c_ulong = 0x6602; pub const FIONBIO: ::c_ulong = 0x667e; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs index e5e4262c9d..dcaeaf5248 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs @@ -319,61 +319,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SOL_SOCKET: ::c_int = 1; - -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 20; -pub const SO_PEERCRED: ::c_int = 21; -pub const SO_RCVLOWAT: ::c_int = 16; -pub const SO_SNDLOWAT: ::c_int = 17; -pub const SO_RCVTIMEO: ::c_int = 18; -pub const SO_SNDTIMEO: ::c_int = 19; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PEERSEC: ::c_int = 31; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; -pub const SO_MARK: ::c_int = 36; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_BUSY_POLL: ::c_int = 46; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; - pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; @@ -1043,8 +988,25 @@ pub const SYS_preadv2: ::c_long = 380; pub const SYS_pwritev2: ::c_long = 381; pub const SYS_kexec_file_load: ::c_long = 382; pub const SYS_statx: ::c_long = 383; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; extern "C" { pub fn sysctl( diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs index a297ac7f22..c656189c43 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs @@ -305,59 +305,7 @@ pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = 26; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PEERSEC: ::c_int = 31; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = 35; -pub const SO_MARK: ::c_int = 36; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = 41; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_BUSY_POLL: ::c_int = 46; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = 27; + pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 134217728; @@ -863,5 +811,22 @@ pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs index fcd1f7b16f..7685a34f80 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs @@ -354,20 +354,6 @@ pub const SIGBUS: ::c_int = 7; pub const SIGSTKSZ: ::size_t = 0x2000; pub const MINSIGSTKSZ: ::size_t = 2048; pub const SIG_SETMASK: ::c_int = 2; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_ERROR: ::c_int = 4; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_MARK: ::c_int = 36; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_BUSY_POLL: ::c_int = 46; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; @@ -471,24 +457,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SO_TYPE: ::c_int = 3; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; - pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; @@ -1007,8 +975,25 @@ pub const SYS_setfsuid: ::c_long = 215; pub const SYS_setfsgid: ::c_long = 216; pub const SYS_newfstatat: ::c_long = 293; pub const SYS_statx: ::c_long = 379; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; extern "C" { @@ -1022,14 +1007,6 @@ extern "C" { ) -> ::c_int; pub fn getcontext(ucp: *mut ::ucontext_t) -> ::c_int; pub fn setcontext(ucp: *const ::ucontext_t) -> ::c_int; - pub fn makecontext( - ucp: *mut ::ucontext_t, - func: extern "C" fn(), - argc: ::c_int, - ... - ); - pub fn swapcontext( - uocp: *mut ::ucontext_t, - ucp: *const ::ucontext_t, - ) -> ::c_int; + pub fn makecontext(ucp: *mut ::ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); + pub fn swapcontext(uocp: *mut ::ucontext_t, ucp: *const ::ucontext_t) -> ::c_int; } diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs index bcf0fd6222..5ed83ab8ed 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs @@ -328,31 +328,6 @@ pub const ENOTRECOVERABLE: ::c_int = 133; pub const EHWPOISON: ::c_int = 135; pub const ERFKILL: ::c_int = 134; -pub const SOL_SOCKET: ::c_int = 0xffff; - -pub const SO_PASSCRED: ::c_int = 2; -pub const SO_REUSEADDR: ::c_int = 4; -pub const SO_BINDTODEVICE: ::c_int = 0x000d; -pub const SO_TIMESTAMP: ::c_int = 0x001d; -pub const SO_MARK: ::c_int = 0x0022; -pub const SO_RXQ_OVFL: ::c_int = 0x0024; -pub const SO_PEEK_OFF: ::c_int = 0x0026; -pub const SO_BUSY_POLL: ::c_int = 0x0030; -pub const SO_TYPE: ::c_int = 0x1008; -pub const SO_ERROR: ::c_int = 0x1007; -pub const SO_DONTROUTE: ::c_int = 16; -pub const SO_BROADCAST: ::c_int = 32; -pub const SO_SNDBUF: ::c_int = 0x1001; -pub const SO_RCVBUF: ::c_int = 0x1002; -pub const SO_SNDBUFFORCE: ::c_int = 0x100a; -pub const SO_RCVBUFFORCE: ::c_int = 0x100b; -pub const SO_DOMAIN: ::c_int = 0x1029; -pub const SO_KEEPALIVE: ::c_int = 8; -pub const SO_OOBINLINE: ::c_int = 0x100; -pub const SO_LINGER: ::c_int = 128; -pub const SO_REUSEPORT: ::c_int = 0x200; -pub const SO_ACCEPTCONN: ::c_int = 0x8000; - pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; @@ -505,12 +480,6 @@ pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; -pub const SO_PEERCRED: ::c_int = 0x40; -pub const SO_RCVLOWAT: ::c_int = 0x800; -pub const SO_SNDLOWAT: ::c_int = 0x1000; -pub const SO_RCVTIMEO: ::c_int = 0x2000; -pub const SO_SNDTIMEO: ::c_int = 0x4000; - pub const FIOCLEX: ::c_ulong = 0x20006601; pub const FIONCLEX: ::c_ulong = 0x20006602; pub const FIONBIO: ::c_ulong = 0x8004667e; @@ -973,9 +942,26 @@ pub const SYS_copy_file_range: ::c_long = 357; pub const SYS_preadv2: ::c_long = 358; pub const SYS_pwritev2: ::c_long = 359; pub const SYS_statx: ::c_long = 360; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; // Reserved in the kernel, but not actually implemented yet pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; extern "C" { pub fn sysctl( diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs index faad040ef9..99937dfabd 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs @@ -515,80 +515,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SOL_SOCKET: ::c_int = 1; - -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_PEERSEC: ::c_int = 31; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; -pub const SO_MARK: ::c_int = 36; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_BUSY_POLL: ::c_int = 46; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; -pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; -pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; -pub const SO_CNX_ADVICE: ::c_int = 53; -pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; -pub const SO_MEMINFO: ::c_int = 55; -pub const SO_INCOMING_NAPI_ID: ::c_int = 56; -pub const SO_COOKIE: ::c_int = 57; -pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; -pub const SO_PEERGROUPS: ::c_int = 59; -pub const SO_ZEROCOPY: ::c_int = 60; -pub const SO_TXTIME: ::c_int = 61; -pub const SCM_TXTIME: ::c_int = SO_TXTIME; -pub const SO_BINDTOIFINDEX: ::c_int = 62; -pub const SO_TIMESTAMP_NEW: ::c_int = 63; -pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; -pub const SO_TIMESTAMPING_NEW: ::c_int = 65; -pub const SO_RCVTIMEO_NEW: ::c_int = 66; -pub const SO_SNDTIMEO_NEW: ::c_int = 67; -pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; - pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; @@ -920,22 +846,10 @@ pub const REG_CR2: ::c_int = 22; extern "C" { pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int; pub fn setcontext(ucp: *const ucontext_t) -> ::c_int; - pub fn makecontext( - ucp: *mut ucontext_t, - func: extern "C" fn(), - argc: ::c_int, - ... - ); - pub fn swapcontext( - uocp: *mut ucontext_t, - ucp: *const ucontext_t, - ) -> ::c_int; + pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); + pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; pub fn iopl(level: ::c_int) -> ::c_int; - pub fn ioperm( - from: ::c_ulong, - num: ::c_ulong, - turn_on: ::c_int, - ) -> ::c_int; + pub fn ioperm(from: ::c_ulong, num: ::c_ulong, turn_on: ::c_int) -> ::c_int; } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs index ab9b76ae0c..e126984268 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs @@ -409,8 +409,25 @@ pub const SYS_pkey_mprotect: ::c_long = 329; pub const SYS_pkey_alloc: ::c_long = 330; pub const SYS_pkey_free: ::c_long = 331; pub const SYS_statx: ::c_long = 332; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; extern "C" { pub fn sysctl( diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs index 82b71c1a8e..dcbc3472f0 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs @@ -337,8 +337,25 @@ pub const SYS_pkey_mprotect: ::c_long = __X32_SYSCALL_BIT + 329; pub const SYS_pkey_alloc: ::c_long = __X32_SYSCALL_BIT + 330; pub const SYS_pkey_free: ::c_long = __X32_SYSCALL_BIT + 331; pub const SYS_statx: ::c_long = __X32_SYSCALL_BIT + 332; +pub const SYS_pidfd_send_signal: ::c_long = __X32_SYSCALL_BIT + 424; +pub const SYS_io_uring_setup: ::c_long = __X32_SYSCALL_BIT + 425; +pub const SYS_io_uring_enter: ::c_long = __X32_SYSCALL_BIT + 426; +pub const SYS_io_uring_register: ::c_long = __X32_SYSCALL_BIT + 427; +pub const SYS_open_tree: ::c_long = __X32_SYSCALL_BIT + 428; +pub const SYS_move_mount: ::c_long = __X32_SYSCALL_BIT + 429; +pub const SYS_fsopen: ::c_long = __X32_SYSCALL_BIT + 430; +pub const SYS_fsconfig: ::c_long = __X32_SYSCALL_BIT + 431; +pub const SYS_fsmount: ::c_long = __X32_SYSCALL_BIT + 432; +pub const SYS_fspick: ::c_long = __X32_SYSCALL_BIT + 433; pub const SYS_pidfd_open: ::c_long = __X32_SYSCALL_BIT + 434; pub const SYS_clone3: ::c_long = __X32_SYSCALL_BIT + 435; +pub const SYS_close_range: ::c_long = __X32_SYSCALL_BIT + 436; +pub const SYS_openat2: ::c_long = __X32_SYSCALL_BIT + 437; +pub const SYS_pidfd_getfd: ::c_long = __X32_SYSCALL_BIT + 438; +pub const SYS_faccessat2: ::c_long = __X32_SYSCALL_BIT + 439; +pub const SYS_process_madvise: ::c_long = __X32_SYSCALL_BIT + 440; +pub const SYS_epoll_pwait2: ::c_long = __X32_SYSCALL_BIT + 441; +pub const SYS_mount_setattr: ::c_long = __X32_SYSCALL_BIT + 442; pub const SYS_rt_sigaction: ::c_long = __X32_SYSCALL_BIT + 512; pub const SYS_rt_sigreturn: ::c_long = __X32_SYSCALL_BIT + 513; pub const SYS_ioctl: ::c_long = __X32_SYSCALL_BIT + 514; diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs index 600257ac03..09cddb9fa7 100644 --- a/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs @@ -1223,33 +1223,6 @@ pub const STATX_ATTR_NODUMP: ::c_int = 0x0040; pub const STATX_ATTR_ENCRYPTED: ::c_int = 0x0800; pub const STATX_ATTR_AUTOMOUNT: ::c_int = 0x1000; -// sys/auxv.h -pub const AT_NULL: ::c_ulong = 0; -pub const AT_IGNORE: ::c_ulong = 1; -pub const AT_EXECFD: ::c_ulong = 2; -pub const AT_PHDR: ::c_ulong = 3; -pub const AT_PHENT: ::c_ulong = 4; -pub const AT_PHNUM: ::c_ulong = 5; -pub const AT_PAGESZ: ::c_ulong = 6; -pub const AT_BASE: ::c_ulong = 7; -pub const AT_FLAGS: ::c_ulong = 8; -pub const AT_ENTRY: ::c_ulong = 9; -pub const AT_NOTELF: ::c_ulong = 10; -pub const AT_UID: ::c_ulong = 11; -pub const AT_EUID: ::c_ulong = 12; -pub const AT_GID: ::c_ulong = 13; -pub const AT_EGID: ::c_ulong = 14; -pub const AT_PLATFORM: ::c_ulong = 15; -pub const AT_HWCAP: ::c_ulong = 16; -pub const AT_CLKTCK: ::c_ulong = 17; -// AT_* values 18 through 22 are reserved -pub const AT_SECURE: ::c_ulong = 23; -pub const AT_BASE_PLATFORM: ::c_ulong = 24; -pub const AT_RANDOM: ::c_ulong = 25; -pub const AT_HWCAP2: ::c_ulong = 26; - -pub const AT_EXECFN: ::c_ulong = 31; - //sys/timex.h pub const ADJ_OFFSET: ::c_uint = 0x0001; pub const ADJ_FREQUENCY: ::c_uint = 0x0002; @@ -1362,11 +1335,7 @@ extern "C" { num: ::size_t, size: ::size_t, compar: ::Option< - unsafe extern "C" fn( - *const ::c_void, - *const ::c_void, - *mut ::c_void, - ) -> ::c_int, + unsafe extern "C" fn(*const ::c_void, *const ::c_void, *mut ::c_void) -> ::c_int, >, arg: *mut ::c_void, ); @@ -1384,22 +1353,10 @@ extern "C" { timeout: *mut ::timespec, ) -> ::c_int; - pub fn getrlimit64( - resource: ::__rlimit_resource_t, - rlim: *mut ::rlimit64, - ) -> ::c_int; - pub fn setrlimit64( - resource: ::__rlimit_resource_t, - rlim: *const ::rlimit64, - ) -> ::c_int; - pub fn getrlimit( - resource: ::__rlimit_resource_t, - rlim: *mut ::rlimit, - ) -> ::c_int; - pub fn setrlimit( - resource: ::__rlimit_resource_t, - rlim: *const ::rlimit, - ) -> ::c_int; + pub fn getrlimit64(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit64) -> ::c_int; + pub fn setrlimit64(resource: ::__rlimit_resource_t, rlim: *const ::rlimit64) -> ::c_int; + pub fn getrlimit(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit) -> ::c_int; + pub fn setrlimit(resource: ::__rlimit_resource_t, rlim: *const ::rlimit) -> ::c_int; pub fn prlimit( pid: ::pid_t, resource: ::__rlimit_resource_t, @@ -1430,11 +1387,7 @@ extern "C" { mask: ::c_uint, statxbuf: *mut statx, ) -> ::c_int; - pub fn getrandom( - buf: *mut ::c_void, - buflen: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; + pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn memmem( haystack: *const ::c_void, @@ -1477,6 +1430,13 @@ extern "C" { offset: ::off_t, flags: ::c_int, ) -> ::ssize_t; + pub fn renameat2( + olddirfd: ::c_int, + oldpath: *const ::c_char, + newdirfd: ::c_int, + newpath: *const ::c_char, + flags: ::c_uint, + ) -> ::c_int; } extern "C" { @@ -1485,9 +1445,7 @@ extern "C" { pub fn glob64( pattern: *const ::c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const ::c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut glob64_t, ) -> ::c_int; pub fn globfree64(pglob: *mut glob64_t); @@ -1503,11 +1461,7 @@ extern "C" { cpuset: *const ::cpu_set_t, ) -> ::c_int; pub fn getpriority(which: ::__priority_which_t, who: ::id_t) -> ::c_int; - pub fn setpriority( - which: ::__priority_which_t, - who: ::id_t, - prio: ::c_int, - ) -> ::c_int; + pub fn setpriority(which: ::__priority_which_t, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn pthread_getaffinity_np( thread: ::pthread_t, cpusetsize: ::size_t, @@ -1541,28 +1495,13 @@ extern "C" { buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; - pub fn pthread_getname_np( - thread: ::pthread_t, - name: *mut ::c_char, - len: ::size_t, - ) -> ::c_int; - pub fn pthread_setname_np( - thread: ::pthread_t, - name: *const ::c_char, - ) -> ::c_int; + pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; + pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int; } 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 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; } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/linux/mod.rs b/vendor/libc/src/unix/linux_like/linux/mod.rs index ce71f1c7ef..38e89d3e2b 100644 --- a/vendor/libc/src/unix/linux_like/linux/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/mod.rs @@ -284,6 +284,24 @@ s! { pub u: [u32; 7], } + pub struct uinput_ff_upload { + pub request_id: ::__u32, + pub retval: ::__s32, + pub effect: ff_effect, + pub old: ff_effect, + } + + pub struct uinput_ff_erase { + pub request_id: ::__u32, + pub retval: ::__s32, + pub effect_id: ::__u32, + } + + pub struct uinput_abs_setup { + pub code: ::__u16, + pub absinfo: input_absinfo, + } + pub struct dl_phdr_info { #[cfg(target_pointer_width = "64")] pub dlpi_addr: Elf64_Addr, @@ -557,6 +575,22 @@ s_no_extra_traits! { pub salg_name: [::c_uchar; 64], } + pub struct uinput_setup { + pub id: input_id, + pub name: [::c_char; UINPUT_MAX_NAME_SIZE], + pub ff_effects_max: ::__u32, + } + + pub struct uinput_user_dev { + pub name: [::c_char; UINPUT_MAX_NAME_SIZE], + pub id: input_id, + pub ff_effects_max: ::__u32, + pub absmax: [::__s32; ABS_CNT], + pub absmin: [::__s32; ABS_CNT], + pub absfuzz: [::__s32; ABS_CNT], + pub absflat: [::__s32; ABS_CNT], + } + /// WARNING: The `PartialEq`, `Eq` and `Hash` implementations of this /// type are unsound and will be removed in the future. #[deprecated( @@ -827,6 +861,72 @@ cfg_if! { } } + impl PartialEq for uinput_setup { + fn eq(&self, other: &uinput_setup) -> bool { + self.id == other.id + && self.name[..] == other.name[..] + && self.ff_effects_max == other.ff_effects_max + } + } + impl Eq for uinput_setup {} + + impl ::fmt::Debug for uinput_setup { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("uinput_setup") + .field("id", &self.id) + .field("name", &&self.name[..]) + .field("ff_effects_max", &self.ff_effects_max) + .finish() + } + } + + impl ::hash::Hash for uinput_setup { + fn hash(&self, state: &mut H) { + self.id.hash(state); + self.name.hash(state); + self.ff_effects_max.hash(state); + } + } + + impl PartialEq for uinput_user_dev { + fn eq(&self, other: &uinput_user_dev) -> bool { + self.name[..] == other.name[..] + && self.id == other.id + && self.ff_effects_max == other.ff_effects_max + && self.absmax[..] == other.absmax[..] + && self.absmin[..] == other.absmin[..] + && self.absfuzz[..] == other.absfuzz[..] + && self.absflat[..] == other.absflat[..] + } + } + impl Eq for uinput_user_dev {} + + impl ::fmt::Debug for uinput_user_dev { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + f.debug_struct("uinput_setup") + .field("name", &&self.name[..]) + .field("id", &self.id) + .field("ff_effects_max", &self.ff_effects_max) + .field("absmax", &&self.absmax[..]) + .field("absmin", &&self.absmin[..]) + .field("absfuzz", &&self.absfuzz[..]) + .field("absflat", &&self.absflat[..]) + .finish() + } + } + + impl ::hash::Hash for uinput_user_dev { + fn hash(&self, state: &mut H) { + self.name.hash(state); + self.id.hash(state); + self.ff_effects_max.hash(state); + self.absmax.hash(state); + self.absmin.hash(state); + self.absfuzz.hash(state); + self.absflat.hash(state); + } + } + #[allow(deprecated)] impl af_alg_iv { fn as_slice(&self) -> &[u8] { @@ -1135,6 +1235,32 @@ pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248; pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; +pub const AT_NULL: ::c_ulong = 0; +pub const AT_IGNORE: ::c_ulong = 1; +pub const AT_EXECFD: ::c_ulong = 2; +pub const AT_PHDR: ::c_ulong = 3; +pub const AT_PHENT: ::c_ulong = 4; +pub const AT_PHNUM: ::c_ulong = 5; +pub const AT_PAGESZ: ::c_ulong = 6; +pub const AT_BASE: ::c_ulong = 7; +pub const AT_FLAGS: ::c_ulong = 8; +pub const AT_ENTRY: ::c_ulong = 9; +pub const AT_NOTELF: ::c_ulong = 10; +pub const AT_UID: ::c_ulong = 11; +pub const AT_EUID: ::c_ulong = 12; +pub const AT_GID: ::c_ulong = 13; +pub const AT_EGID: ::c_ulong = 14; +pub const AT_PLATFORM: ::c_ulong = 15; +pub const AT_HWCAP: ::c_ulong = 16; +pub const AT_CLKTCK: ::c_ulong = 17; + +pub const AT_SECURE: ::c_ulong = 23; +pub const AT_BASE_PLATFORM: ::c_ulong = 24; +pub const AT_RANDOM: ::c_ulong = 25; +pub const AT_HWCAP2: ::c_ulong = 26; + +pub const AT_EXECFN: ::c_ulong = 31; + pub const GLOB_ERR: ::c_int = 1 << 0; pub const GLOB_MARK: ::c_int = 1 << 1; pub const GLOB_NOSORT: ::c_int = 1 << 2; @@ -1318,9 +1444,9 @@ pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; -pub const RENAME_NOREPLACE: ::c_int = 1; -pub const RENAME_EXCHANGE: ::c_int = 2; -pub const RENAME_WHITEOUT: ::c_int = 4; +pub const RENAME_NOREPLACE: ::c_uint = 1; +pub const RENAME_EXCHANGE: ::c_uint = 2; +pub const RENAME_WHITEOUT: ::c_uint = 4; pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; @@ -2330,12 +2456,6 @@ pub const ARPD_LOOKUP: ::c_ushort = 0x02; pub const ARPD_FLUSH: ::c_ushort = 0x03; pub const ATF_MAGIC: ::c_int = 0x80; -#[cfg(not(target_arch = "sparc64"))] -pub const SO_TIMESTAMPING: ::c_int = 37; -#[cfg(target_arch = "sparc64")] -pub const SO_TIMESTAMPING: ::c_int = 35; -pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; - // linux/module.h pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001; pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002; @@ -2471,6 +2591,38 @@ pub const IN_ALL_EVENTS: u32 = IN_ACCESS pub const IN_CLOEXEC: ::c_int = O_CLOEXEC; pub const IN_NONBLOCK: ::c_int = O_NONBLOCK; +// linux/input.h +pub const FF_MAX: ::__u16 = 0x7f; +pub const FF_CNT: usize = FF_MAX as usize + 1; + +// linux/input-event-codes.h +pub const INPUT_PROP_MAX: ::__u16 = 0x1f; +pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1; +pub const EV_MAX: ::__u16 = 0x1f; +pub const EV_CNT: usize = EV_MAX as usize + 1; +pub const SYN_MAX: ::__u16 = 0xf; +pub const SYN_CNT: usize = SYN_MAX as usize + 1; +pub const KEY_MAX: ::__u16 = 0x2ff; +pub const KEY_CNT: usize = KEY_MAX as usize + 1; +pub const REL_MAX: ::__u16 = 0x0f; +pub const REL_CNT: usize = REL_MAX as usize + 1; +pub const ABS_MAX: ::__u16 = 0x3f; +pub const ABS_CNT: usize = ABS_MAX as usize + 1; +pub const SW_MAX: ::__u16 = 0x10; +pub const SW_CNT: usize = SW_MAX as usize + 1; +pub const MSC_MAX: ::__u16 = 0x07; +pub const MSC_CNT: usize = MSC_MAX as usize + 1; +pub const LED_MAX: ::__u16 = 0x0f; +pub const LED_CNT: usize = LED_MAX as usize + 1; +pub const REP_MAX: ::__u16 = 0x01; +pub const REP_CNT: usize = REP_MAX as usize + 1; +pub const SND_MAX: ::__u16 = 0x07; +pub const SND_CNT: usize = SND_MAX as usize + 1; + +// linux/uinput.h +pub const UINPUT_VERSION: ::c_uint = 5; +pub const UINPUT_MAX_NAME_SIZE: usize = 80; + // uapi/linux/fanotify.h pub const FAN_ACCESS: u64 = 0x0000_0001; pub const FAN_MODIFY: u64 = 0x0000_0002; @@ -2530,8 +2682,7 @@ pub const FUTEX_CMP_REQUEUE_PI: ::c_int = 12; pub const FUTEX_PRIVATE_FLAG: ::c_int = 128; pub const FUTEX_CLOCK_REALTIME: ::c_int = 256; -pub const FUTEX_CMD_MASK: ::c_int = - !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); +pub const FUTEX_CMD_MASK: ::c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); // linux/reboot.h pub const LINUX_REBOOT_MAGIC1: ::c_int = 0xfee1dead; @@ -2853,11 +3004,7 @@ cfg_if! { extern "C" { #[cfg_attr(not(target_env = "musl"), link_name = "__xpg_strerror_r")] - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn atof(s: *const ::c_char) -> ::c_double; @@ -2889,40 +3036,18 @@ extern "C" { spbufp: *mut *mut spwd, ) -> ::c_int; - pub fn shm_open( - name: *const c_char, - oflag: ::c_int, - mode: mode_t, - ) -> ::c_int; + pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; // System V IPC pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; - pub fn shmat( - shmid: ::c_int, - shmaddr: *const ::c_void, - shmflg: ::c_int, - ) -> *mut ::c_void; + pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; - pub fn shmctl( - shmid: ::c_int, - cmd: ::c_int, - buf: *mut ::shmid_ds, - ) -> ::c_int; + pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int; - pub fn semop( - semid: ::c_int, - sops: *mut ::sembuf, - nsops: ::size_t, - ) -> ::c_int; - pub fn semctl( - semid: ::c_int, - semnum: ::c_int, - cmd: ::c_int, - ... - ) -> ::c_int; - pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) - -> ::c_int; + pub fn semop(semid: ::c_int, sops: *mut ::sembuf, nsops: ::size_t) -> ::c_int; + pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; + pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv( msqid: ::c_int, @@ -2938,17 +3063,10 @@ extern "C" { msgflg: ::c_int, ) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn __errno_location() -> *mut ::c_int; - pub fn fopen64( - filename: *const c_char, - mode: *const c_char, - ) -> *mut ::FILE; + pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn freopen64( filename: *const c_char, mode: *const c_char, @@ -2957,39 +3075,13 @@ extern "C" { pub fn tmpfile64() -> *mut ::FILE; pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int; pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int; - pub fn fseeko64( - stream: *mut ::FILE, - offset: ::off64_t, - whence: ::c_int, - ) -> ::c_int; + pub fn fseeko64(stream: *mut ::FILE, offset: ::off64_t, whence: ::c_int) -> ::c_int; pub fn ftello64(stream: *mut ::FILE) -> ::off64_t; - pub fn fallocate( - fd: ::c_int, - mode: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn fallocate64( - fd: ::c_int, - mode: ::c_int, - offset: ::off64_t, - len: ::off64_t, - ) -> ::c_int; - pub fn posix_fallocate( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; - pub fn posix_fallocate64( - fd: ::c_int, - offset: ::off64_t, - len: ::off64_t, - ) -> ::c_int; - pub fn readahead( - fd: ::c_int, - offset: ::off64_t, - count: ::size_t, - ) -> ::ssize_t; + pub fn fallocate(fd: ::c_int, mode: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn fallocate64(fd: ::c_int, mode: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; + pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; + pub fn posix_fallocate64(fd: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; + pub fn readahead(fd: ::c_int, offset: ::off64_t, count: ::size_t) -> ::ssize_t; pub fn getxattr( path: *const c_char, name: *const c_char, @@ -3029,34 +3121,15 @@ extern "C" { size: ::size_t, flags: ::c_int, ) -> ::c_int; - pub fn listxattr( - path: *const c_char, - list: *mut c_char, - size: ::size_t, - ) -> ::ssize_t; - pub fn llistxattr( - path: *const c_char, - list: *mut c_char, - size: ::size_t, - ) -> ::ssize_t; - pub fn flistxattr( - filedes: ::c_int, - list: *mut c_char, - size: ::size_t, - ) -> ::ssize_t; + pub fn listxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; + pub fn llistxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; + pub fn flistxattr(filedes: ::c_int, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int; 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 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_gettime( - fd: ::c_int, - curr_value: *mut itimerspec, - ) -> ::c_int; + pub fn timerfd_gettime(fd: ::c_int, curr_value: *mut itimerspec) -> ::c_int; pub fn timerfd_settime( fd: ::c_int, flags: ::c_int, @@ -3099,11 +3172,7 @@ extern "C" { abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; - pub fn mq_setattr( - mqd: ::mqd_t, - newattr: *const ::mq_attr, - oldattr: *mut ::mq_attr, - ) -> ::c_int; + pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; pub fn epoll_pwait( epfd: ::c_int, events: *mut ::epoll_event, @@ -3113,39 +3182,27 @@ extern "C" { ) -> ::c_int; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; - pub fn mkostemps( - template: *mut ::c_char, - suffixlen: ::c_int, - flags: ::c_int, - ) -> ::c_int; + pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; - pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) - -> *mut ::c_char; + pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int, ) -> ::c_int; - pub fn pthread_setschedprio( - native: ::pthread_t, - priority: ::c_int, - ) -> ::c_int; + pub fn pthread_setschedprio(native: ::pthread_t, priority: ::c_int) -> ::c_int; pub fn reboot(how_to: ::c_int) -> ::c_int; pub fn setfsgid(gid: ::gid_t) -> ::c_int; pub fn setfsuid(uid: ::uid_t) -> ::c_int; // Not available now on Android - pub fn mkfifoat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn sync_file_range( @@ -3165,35 +3222,21 @@ extern "C" { pub fn glob( pattern: *const c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); - pub fn posix_madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn remap_file_pages( addr: *mut ::c_void, size: ::size_t, @@ -3218,11 +3261,8 @@ extern "C" { pub fn vhangup() -> ::c_int; pub fn sync(); pub fn syscall(num: ::c_long, ...) -> ::c_long; - pub fn sched_getaffinity( - pid: ::pid_t, - cpusetsize: ::size_t, - cpuset: *mut cpu_set_t, - ) -> ::c_int; + pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) + -> ::c_int; pub fn sched_setaffinity( pid: ::pid_t, cpusetsize: ::size_t, @@ -3236,12 +3276,8 @@ extern "C" { maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; - pub fn epoll_ctl( - epfd: ::c_int, - op: ::c_int, - fd: ::c_int, - event: *mut ::epoll_event, - ) -> ::c_int; + pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) + -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, @@ -3250,16 +3286,8 @@ extern "C" { pub fn unshare(flags: ::c_int) -> ::c_int; pub fn umount(target: *const ::c_char) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; - pub fn tee( - fd_in: ::c_int, - fd_out: ::c_int, - len: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; - pub fn settimeofday( - tv: *const ::timeval, - tz: *const ::timezone, - ) -> ::c_int; + pub fn tee(fd_in: ::c_int, fd_out: ::c_int, len: ::size_t, flags: ::c_uint) -> ::ssize_t; + pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn splice( fd_in: ::c_int, off_in: *mut ::loff_t, @@ -3269,19 +3297,12 @@ extern "C" { flags: ::c_uint, ) -> ::ssize_t; pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; - pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) - -> ::c_int; - pub fn sem_timedwait( - sem: *mut sem_t, - abstime: *const ::timespec, - ) -> ::c_int; + pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; - pub fn sched_setparam( - pid: ::pid_t, - param: *const ::sched_param, - ) -> ::c_int; + pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn setns(fd: ::c_int, nstype: ::c_int) -> ::c_int; - pub fn swapoff(puath: *const ::c_char) -> ::c_int; + pub fn swapoff(path: *const ::c_char) -> ::c_int; pub fn vmsplice( fd: ::c_int, iov: *const ::iovec, @@ -3376,11 +3397,7 @@ extern "C" { result: *mut *mut ::group, ) -> ::c_int; pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; - pub fn pthread_sigmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; @@ -3442,17 +3459,11 @@ extern "C" { data: *mut ::c_void, ) -> ::c_int; - pub fn setmntent( - filename: *const ::c_char, - ty: *const ::c_char, - ) -> *mut ::FILE; + pub fn setmntent(filename: *const ::c_char, ty: *const ::c_char) -> *mut ::FILE; pub fn getmntent(stream: *mut ::FILE) -> *mut ::mntent; pub fn addmntent(stream: *mut ::FILE, mnt: *const ::mntent) -> ::c_int; pub fn endmntent(streamp: *mut ::FILE) -> ::c_int; - pub fn hasmntopt( - mnt: *const ::mntent, - opt: *const ::c_char, - ) -> *mut ::c_char; + pub fn hasmntopt(mnt: *const ::mntent, opt: *const ::c_char) -> *mut ::c_char; pub fn posix_spawn( pid: *mut ::pid_t, @@ -3492,26 +3503,17 @@ extern "C" { attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; - pub fn posix_spawnattr_setflags( - attr: *mut posix_spawnattr_t, - flags: ::c_short, - ) -> ::c_int; + pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; - pub fn posix_spawnattr_setpgroup( - attr: *mut posix_spawnattr_t, - flags: ::pid_t, - ) -> ::c_int; + pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; - pub fn posix_spawnattr_setschedpolicy( - attr: *mut posix_spawnattr_t, - flags: ::c_int, - ) -> ::c_int; + pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, @@ -3521,12 +3523,8 @@ extern "C" { param: *const ::sched_param, ) -> ::c_int; - pub fn posix_spawn_file_actions_init( - actions: *mut posix_spawn_file_actions_t, - ) -> ::c_int; - pub fn posix_spawn_file_actions_destroy( - actions: *mut posix_spawn_file_actions_t, - ) -> ::c_int; + pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; + pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, @@ -3552,18 +3550,10 @@ extern "C" { pub fn inotify_rm_watch(fd: ::c_int, wd: ::c_int) -> ::c_int; pub fn inotify_init() -> ::c_int; pub fn inotify_init1(flags: ::c_int) -> ::c_int; - pub fn inotify_add_watch( - fd: ::c_int, - path: *const ::c_char, - mask: u32, - ) -> ::c_int; + pub fn inotify_add_watch(fd: ::c_int, path: *const ::c_char, mask: u32) -> ::c_int; pub fn fanotify_init(flags: ::c_uint, event_f_flags: ::c_uint) -> ::c_int; - pub fn regcomp( - preg: *mut ::regex_t, - pattern: *const ::c_char, - cflags: ::c_int, - ) -> ::c_int; + pub fn regcomp(preg: *mut ::regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regexec( preg: *const ::regex_t, @@ -3582,10 +3572,7 @@ extern "C" { pub fn regfree(preg: *mut ::regex_t); - pub fn iconv_open( - tocode: *const ::c_char, - fromcode: *const ::c_char, - ) -> iconv_t; + pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, @@ -3611,6 +3598,9 @@ cfg_if! { } } +mod arch; +pub use self::arch::*; + cfg_if! { if #[cfg(libc_align)] { #[macro_use] diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs index 88e8d56b99..1f952c310f 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs @@ -268,8 +268,6 @@ pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_SEQPACKET: ::c_int = 5; -pub const SOL_SOCKET: ::c_int = 1; - pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; @@ -356,32 +354,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; - pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; @@ -832,13 +804,28 @@ pub const SYS_pkey_mprotect: ::c_long = 394; pub const SYS_pkey_alloc: ::c_long = 395; pub const SYS_pkey_free: ::c_long = 396; pub const SYS_statx: ::c_long = 397; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; +pub const SYS_pidfd_open: ::c_long = 434; +pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; extern "C" { - pub fn getrandom( - buf: *mut ::c_void, - buflen: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; + pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs index 0006197625..a94ebb6afc 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/hexagon.rs @@ -317,65 +317,19 @@ pub const SIGXFSZ: ::c_int = 25; pub const SIG_SETMASK: ::c_int = 2; // FIXME check these pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; -pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_BSDCOMPAT: ::c_int = 14; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_NONBLOCK: ::c_int = 2048; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_STREAM: ::c_int = 1; -pub const SO_CNX_ADVICE: ::c_int = 53; -pub const SO_DETACH_BPF: ::c_int = 27; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_DOMAIN: ::c_int = 39; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_ERROR: ::c_int = 4; -pub const SO_GET_FILTER: ::c_int = 26; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_KEEPALIVE: ::c_int = 9; pub const SOL_CAIF: ::c_int = 278; -pub const SO_LINGER: ::c_int = 13; pub const SOL_IUCV: ::c_int = 277; pub const SOL_KCM: ::c_int = 281; pub const SOL_NFC: ::c_int = 280; -pub const SO_LOCK_FILTER: ::c_int = 44; pub const SOL_PNPIPE: ::c_int = 275; pub const SOL_PPPOL2TP: ::c_int = 273; pub const SOL_RDS: ::c_int = 276; pub const SOL_RXRPC: ::c_int = 272; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_PEERSEC: ::c_int = 31; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_TYPE: ::c_int = 3; -pub const SO_WIFI_STATUS: ::c_int = 41; + pub const SYS3264_fadvise64: ::c_int = 223; pub const SYS3264_fcntl: ::c_int = 25; pub const SYS3264_fstatat: ::c_int = 79; diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs index 2e17ccc637..115ba53d15 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs @@ -363,34 +363,6 @@ pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; pub const SOCK_SEQPACKET: ::c_int = 5; -pub const SOL_SOCKET: ::c_int = 65535; - -pub const SO_REUSEADDR: ::c_int = 0x0004; -pub const SO_KEEPALIVE: ::c_int = 0x0008; -pub const SO_DONTROUTE: ::c_int = 0x0010; -pub const SO_BROADCAST: ::c_int = 0x0020; -pub const SO_LINGER: ::c_int = 0x0080; -pub const SO_OOBINLINE: ::c_int = 0x0100; -pub const SO_REUSEPORT: ::c_int = 0x0200; -pub const SO_SNDBUF: ::c_int = 0x1001; -pub const SO_RCVBUF: ::c_int = 0x1002; -pub const SO_SNDLOWAT: ::c_int = 0x1003; -pub const SO_RCVLOWAT: ::c_int = 0x1004; -pub const SO_RCVTIMEO: ::c_int = 0x1006; -pub const SO_SNDTIMEO: ::c_int = 0x1005; -pub const SO_ERROR: ::c_int = 0x1007; -pub const SO_TYPE: ::c_int = 0x1008; -pub const SO_ACCEPTCONN: ::c_int = 0x1009; -pub const SO_PROTOCOL: ::c_int = 0x1028; -pub const SO_DOMAIN: ::c_int = 0x1029; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_PASSCRED: ::c_int = 17; -pub const SO_PEERCRED: ::c_int = 18; -pub const SO_SNDBUFFORCE: ::c_int = 31; -pub const SO_RCVBUFFORCE: ::c_int = 33; - pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 8; pub const SA_NOCLDWAIT: ::c_int = 0x10000; @@ -843,6 +815,25 @@ pub const SYS_pkey_mprotect: ::c_long = 4000 + 363; pub const SYS_pkey_alloc: ::c_long = 4000 + 364; pub const SYS_pkey_free: ::c_long = 4000 + 365; pub const SYS_statx: ::c_long = 4000 + 366; +pub const SYS_pidfd_send_signal: ::c_long = 4000 + 424; +pub const SYS_io_uring_setup: ::c_long = 4000 + 425; +pub const SYS_io_uring_enter: ::c_long = 4000 + 426; +pub const SYS_io_uring_register: ::c_long = 4000 + 427; +pub const SYS_open_tree: ::c_long = 4000 + 428; +pub const SYS_move_mount: ::c_long = 4000 + 429; +pub const SYS_fsopen: ::c_long = 4000 + 430; +pub const SYS_fsconfig: ::c_long = 4000 + 431; +pub const SYS_fsmount: ::c_long = 4000 + 432; +pub const SYS_fspick: ::c_long = 4000 + 433; +pub const SYS_pidfd_open: ::c_long = 4000 + 434; +pub const SYS_clone3: ::c_long = 4000 + 435; +pub const SYS_close_range: ::c_long = 4000 + 436; +pub const SYS_openat2: ::c_long = 4000 + 437; +pub const SYS_pidfd_getfd: ::c_long = 4000 + 438; +pub const SYS_faccessat2: ::c_long = 4000 + 439; +pub const SYS_process_madvise: ::c_long = 4000 + 440; +pub const SYS_epoll_pwait2: ::c_long = 4000 + 441; +pub const SYS_mount_setattr: ::c_long = 4000 + 442; cfg_if! { if #[cfg(libc_align)] { diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs index b94bb7b15e..848d2d550e 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs @@ -270,8 +270,6 @@ pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_SEQPACKET: ::c_int = 5; -pub const SOL_SOCKET: ::c_int = 1; - pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; @@ -358,32 +356,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_RCVLOWAT: ::c_int = 16; -pub const SO_SNDLOWAT: ::c_int = 17; -pub const SO_RCVTIMEO: ::c_int = 18; -pub const SO_SNDTIMEO: ::c_int = 19; -pub const SO_PASSCRED: ::c_int = 20; -pub const SO_PEERCRED: ::c_int = 21; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; - pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; @@ -856,11 +828,26 @@ pub const SYS_statx: ::c_long = 383; pub const SYS_pkey_alloc: ::c_long = 384; pub const SYS_pkey_free: ::c_long = 385; pub const SYS_pkey_mprotect: ::c_long = 386; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; +pub const SYS_pidfd_open: ::c_long = 434; +pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; extern "C" { - pub fn getrandom( - buf: *mut ::c_void, - buflen: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; + pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs index 82ef84a96e..d4cedbc50a 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs @@ -328,8 +328,6 @@ pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_SEQPACKET: ::c_int = 5; -pub const SOL_SOCKET: ::c_int = 1; - pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; @@ -416,32 +414,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; - pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; @@ -922,6 +894,25 @@ pub const SYS_pkey_mprotect: ::c_long = 380; pub const SYS_pkey_alloc: ::c_long = 381; pub const SYS_pkey_free: ::c_long = 382; pub const SYS_statx: ::c_long = 383; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; +pub const SYS_pidfd_open: ::c_long = 434; +pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; // offsets in user_regs_structs, from sys/reg.h pub const EBX: ::c_int = 0; @@ -943,11 +934,7 @@ pub const UESP: ::c_int = 15; pub const SS: ::c_int = 16; extern "C" { - pub fn getrandom( - buf: *mut ::c_void, - buflen: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; + pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs index 88c252ea6c..6aab650a17 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs @@ -174,26 +174,6 @@ pub const MAP_SYNC: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; @@ -515,6 +495,25 @@ pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; +pub const SYS_pidfd_open: ::c_long = 434; +pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; pub const RLIMIT_NLIMITS: ::c_int = 15; pub const TIOCINQ: ::c_int = ::FIONREAD; @@ -592,12 +591,7 @@ pub const FIONCLEX: ::c_int = 0x5450; pub const FIONBIO: ::c_int = 0x5421; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = EDEADLK; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; + pub const EXTPROC: ::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs index 21ddc9c0e5..4605a07e8c 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs @@ -425,6 +425,25 @@ pub const SYS_pkey_mprotect: ::c_long = 5000 + 323; pub const SYS_pkey_alloc: ::c_long = 5000 + 324; pub const SYS_pkey_free: ::c_long = 5000 + 325; pub const SYS_statx: ::c_long = 5000 + 326; +pub const SYS_pidfd_send_signal: ::c_long = 5000 + 424; +pub const SYS_io_uring_setup: ::c_long = 5000 + 425; +pub const SYS_io_uring_enter: ::c_long = 5000 + 426; +pub const SYS_io_uring_register: ::c_long = 5000 + 427; +pub const SYS_open_tree: ::c_long = 5000 + 428; +pub const SYS_move_mount: ::c_long = 5000 + 429; +pub const SYS_fsopen: ::c_long = 5000 + 430; +pub const SYS_fsconfig: ::c_long = 5000 + 431; +pub const SYS_fsmount: ::c_long = 5000 + 432; +pub const SYS_fspick: ::c_long = 5000 + 433; +pub const SYS_pidfd_open: ::c_long = 5000 + 434; +pub const SYS_clone3: ::c_long = 5000 + 435; +pub const SYS_close_range: ::c_long = 5000 + 436; +pub const SYS_openat2: ::c_long = 5000 + 437; +pub const SYS_pidfd_getfd: ::c_long = 5000 + 438; +pub const SYS_faccessat2: ::c_long = 5000 + 439; +pub const SYS_process_madvise: ::c_long = 5000 + 440; +pub const SYS_epoll_pwait2: ::c_long = 5000 + 441; +pub const SYS_mount_setattr: ::c_long = 5000 + 442; pub const O_DIRECT: ::c_int = 0x8000; pub const O_DIRECTORY: ::c_int = 0x10000; @@ -538,55 +557,6 @@ pub const MAP_HUGETLB: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; -pub const SOL_SOCKET: ::c_int = 0xffff; - -pub const SO_REUSEADDR: ::c_int = 0x0004; -pub const SO_KEEPALIVE: ::c_int = 0x0008; -pub const SO_DONTROUTE: ::c_int = 0x0010; -pub const SO_BROADCAST: ::c_int = 0x0020; -pub const SO_LINGER: ::c_int = 0x0080; -pub const SO_OOBINLINE: ::c_int = 0x0100; -pub const SO_REUSEPORT: ::c_int = 0x0200; -pub const SO_TYPE: ::c_int = 0x1008; -pub const SO_ERROR: ::c_int = 0x1007; -pub const SO_SNDBUF: ::c_int = 0x1001; -pub const SO_RCVBUF: ::c_int = 0x1002; -pub const SO_SNDLOWAT: ::c_int = 0x1003; -pub const SO_RCVLOWAT: ::c_int = 0x1004; -pub const SO_SNDTIMEO: ::c_int = 0x1005; -pub const SO_RCVTIMEO: ::c_int = 0x1006; -pub const SO_ACCEPTCONN: ::c_int = 0x1009; -pub const SO_PROTOCOL: ::c_int = 0x1028; -pub const SO_DOMAIN: ::c_int = 0x1029; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_PASSCRED: ::c_int = 17; -pub const SO_PEERCRED: ::c_int = 18; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_PEERSEC: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 31; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; -pub const SO_INCOMING_CPU: ::c_int = 49; -pub const SO_ATTACH_BPF: ::c_int = 50; -pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; - pub const FIOCLEX: ::c_int = 0x6601; pub const FIONCLEX: ::c_int = 0x6602; pub const FIONBIO: ::c_int = 0x667e; diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/mod.rs index b3c79b06a9..cfcdaaecf4 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/mod.rs @@ -144,11 +144,7 @@ pub const SOCK_NONBLOCK: ::c_int = 2048; pub const SOCK_SEQPACKET: ::c_int = 5; extern "C" { - pub fn getrandom( - buf: *mut ::c_void, - buflen: ::size_t, - flags: ::c_uint, - ) -> ::ssize_t; + pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs index 2533ffd6d3..daa5b11f16 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs @@ -174,26 +174,6 @@ pub const MAP_SYNC: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; @@ -601,18 +581,32 @@ pub const SYS_preadv2: ::c_long = 380; pub const SYS_pwritev2: ::c_long = 381; pub const SYS_kexec_file_load: ::c_long = 382; pub const SYS_statx: ::c_long = 383; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; +pub const SYS_pidfd_open: ::c_long = 434; +pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; pub const FIOCLEX: ::c_int = 0x20006601; pub const FIONCLEX: ::c_int = 0x20006602; pub const FIONBIO: ::c_int = 0x8004667e; pub const EDEADLK: ::c_int = 58; pub const EDEADLOCK: ::c_int = EDEADLK; -pub const SO_PASSCRED: ::c_int = 20; -pub const SO_PEERCRED: ::c_int = 21; -pub const SO_RCVLOWAT: ::c_int = 16; -pub const SO_SNDLOWAT: ::c_int = 17; -pub const SO_RCVTIMEO: ::c_int = 18; -pub const SO_SNDTIMEO: ::c_int = 19; + pub const EXTPROC: ::tcflag_t = 0x10000000; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs index c81517689d..bd33bdbb8f 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs @@ -155,14 +155,6 @@ pub const SIGBUS: ::c_int = 7; pub const SIGSTKSZ: ::size_t = 0x2000; pub const MINSIGSTKSZ: ::size_t = 2048; pub const SIG_SETMASK: ::c_int = 2; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_ERROR: ::c_int = 4; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; @@ -259,24 +251,6 @@ pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; -pub const SO_TYPE: ::c_int = 3; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; - pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; @@ -759,5 +733,22 @@ pub const SYS_setfsuid: ::c_long = 215; pub const SYS_setfsgid: ::c_long = 216; pub const SYS_newfstatat: ::c_long = 293; pub const SYS_statx: ::c_long = 379; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs index 1229bec172..5c4b6bbb41 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs @@ -580,6 +580,25 @@ pub const SYS_pkey_mprotect: ::c_long = 329; pub const SYS_pkey_alloc: ::c_long = 330; pub const SYS_pkey_free: ::c_long = 331; pub const SYS_statx: ::c_long = 332; +pub const SYS_pidfd_send_signal: ::c_long = 424; +pub const SYS_io_uring_setup: ::c_long = 425; +pub const SYS_io_uring_enter: ::c_long = 426; +pub const SYS_io_uring_register: ::c_long = 427; +pub const SYS_open_tree: ::c_long = 428; +pub const SYS_move_mount: ::c_long = 429; +pub const SYS_fsopen: ::c_long = 430; +pub const SYS_fsconfig: ::c_long = 431; +pub const SYS_fsmount: ::c_long = 432; +pub const SYS_fspick: ::c_long = 433; +pub const SYS_pidfd_open: ::c_long = 434; +pub const SYS_clone3: ::c_long = 435; +pub const SYS_close_range: ::c_long = 436; +pub const SYS_openat2: ::c_long = 437; +pub const SYS_pidfd_getfd: ::c_long = 438; +pub const SYS_faccessat2: ::c_long = 439; +pub const SYS_process_madvise: ::c_long = 440; +pub const SYS_epoll_pwait2: ::c_long = 441; +pub const SYS_mount_setattr: ::c_long = 442; // offsets in user_regs_structs, from sys/reg.h pub const R15: ::c_int = 0; @@ -788,26 +807,6 @@ pub const POLLWRBAND: ::c_short = 0x200; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_TYPE: ::c_int = 3; -pub const SO_ERROR: ::c_int = 4; -pub const SO_DONTROUTE: ::c_int = 5; -pub const SO_BROADCAST: ::c_int = 6; -pub const SO_SNDBUF: ::c_int = 7; -pub const SO_RCVBUF: ::c_int = 8; -pub const SO_KEEPALIVE: ::c_int = 9; -pub const SO_OOBINLINE: ::c_int = 10; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_LINGER: ::c_int = 13; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_ACCEPTCONN: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 32; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PROTOCOL: ::c_int = 38; -pub const SO_DOMAIN: ::c_int = 39; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; @@ -897,12 +896,7 @@ pub const FIONCLEX: ::c_int = 0x5450; pub const FIONBIO: ::c_int = 0x5421; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = EDEADLK; -pub const SO_PASSCRED: ::c_int = 16; -pub const SO_PEERCRED: ::c_int = 17; -pub const SO_RCVLOWAT: ::c_int = 18; -pub const SO_SNDLOWAT: ::c_int = 19; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_SNDTIMEO: ::c_int = 21; + pub const EXTPROC: ::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; diff --git a/vendor/libc/src/unix/linux_like/linux/musl/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/mod.rs index 44f7680e08..00f26475df 100644 --- a/vendor/libc/src/unix/linux_like/linux/musl/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/musl/mod.rs @@ -615,13 +615,6 @@ pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_MARK: ::c_int = 36; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_BUSY_POLL: ::c_int = 46; - pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; @@ -715,6 +708,7 @@ extern "C" { dirfd: ::c_int, path: *const ::c_char, ) -> ::c_int; + pub fn getauxval(type_: ::c_ulong) -> ::c_ulong; } cfg_if! { diff --git a/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs b/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs index 1cafdb61c4..dc6518c0da 100644 --- a/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs @@ -259,9 +259,6 @@ pub const NCCS: usize = 32; // I wasn't able to find those constants // in uclibc build environment for armv7 pub const MAP_HUGETLB: ::c_int = 0x040000; // from linux/other/mod.rs -pub const SO_BUSY_POLL: ::c_int = 46; // from src/unix/linux_like/mod.rs -pub const SO_PEEK_OFF: ::c_int = 42; // from src/unix/linux_like/mod.rs -pub const SO_REUSEPORT: ::c_int = 15; // from src/unix/linux_like/mod.rs // autogenerated constants with hand tuned types pub const B0: ::speed_t = 0; @@ -511,34 +508,7 @@ pub const SOCK_DGRAM: ::c_int = 0x2; pub const SOCK_NONBLOCK: ::c_int = 0o0004000; pub const SOCK_SEQPACKET: ::c_int = 0x5; pub const SOCK_STREAM: ::c_int = 0x1; -pub const SOL_SOCKET: ::c_int = 0x1; -pub const SO_ACCEPTCONN: ::c_int = 0x1e; -pub const SO_BINDTODEVICE: ::c_int = 0x19; -pub const SO_BROADCAST: ::c_int = 0x6; -pub const SO_BSDCOMPAT: ::c_int = 0xe; -pub const SO_DOMAIN: ::c_int = 0x27; -pub const SO_DONTROUTE: ::c_int = 0x5; -pub const SO_ERROR: ::c_int = 0x4; -pub const SO_KEEPALIVE: ::c_int = 0x9; -pub const SO_LINGER: ::c_int = 0xd; -pub const SO_MARK: ::c_int = 0x24; -pub const SO_OOBINLINE: ::c_int = 0xa; -pub const SO_PASSCRED: ::c_int = 0x10; -pub const SO_PEERCRED: ::c_int = 0x11; -pub const SO_PRIORITY: ::c_int = 0xc; -pub const SO_PROTOCOL: ::c_int = 0x26; -pub const SO_RCVBUF: ::c_int = 0x8; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_RCVLOWAT: ::c_int = 0x12; -pub const SO_RCVTIMEO: ::c_int = 0x14; -pub const SO_REUSEADDR: ::c_int = 0x2; -pub const SO_RXQ_OVFL: ::c_int = 0x28; -pub const SO_SNDBUF: ::c_int = 0x7; -pub const SO_SNDBUFFORCE: ::c_int = 0x20; -pub const SO_SNDLOWAT: ::c_int = 0x13; -pub const SO_SNDTIMEO: ::c_int = 0x15; -pub const SO_TIMESTAMP: ::c_int = 0x1d; -pub const SO_TYPE: ::c_int = 0x3; + pub const TAB1: ::c_int = 0x800; pub const TAB2: ::c_int = 0x1000; pub const TAB3: ::c_int = 0x1800; diff --git a/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs b/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs index 6b34faeade..8edde11aad 100644 --- a/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs @@ -640,9 +640,7 @@ extern "C" { pub fn glob64( pattern: *const ::c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const ::c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut glob64_t, ) -> ::c_int; pub fn globfree64(pglob: *mut glob64_t); diff --git a/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mod.rs b/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mod.rs index 26408ff82a..d3f6bb2712 100644 --- a/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/uclibc/mips/mod.rs @@ -163,59 +163,6 @@ pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; pub const SOCK_SEQPACKET: ::c_int = 5; -pub const SOL_SOCKET: ::c_int = 0xffff; - -pub const SO_REUSEADDR: ::c_int = 0x0004; -pub const SO_KEEPALIVE: ::c_int = 0x0008; -pub const SO_DONTROUTE: ::c_int = 0x0010; -pub const SO_BROADCAST: ::c_int = 0x0020; -pub const SO_LINGER: ::c_int = 0x0080; -pub const SO_OOBINLINE: ::c_int = 0x0100; -pub const SO_REUSEPORT: ::c_int = 0x0200; -pub const SO_TYPE: ::c_int = 0x1008; -pub const SO_STYLE: ::c_int = SO_TYPE; -pub const SO_ERROR: ::c_int = 0x1007; -pub const SO_SNDBUF: ::c_int = 0x1001; -pub const SO_RCVBUF: ::c_int = 0x1002; -pub const SO_SNDLOWAT: ::c_int = 0x1003; -pub const SO_RCVLOWAT: ::c_int = 0x1004; -pub const SO_SNDTIMEO: ::c_int = 0x1005; -pub const SO_RCVTIMEO: ::c_int = 0x1006; -pub const SO_ACCEPTCONN: ::c_int = 0x1009; -pub const SO_PROTOCOL: ::c_int = 0x1028; -pub const SO_DOMAIN: ::c_int = 0x1029; -pub const SO_NO_CHECK: ::c_int = 11; -pub const SO_PRIORITY: ::c_int = 12; -pub const SO_BSDCOMPAT: ::c_int = 14; -pub const SO_PASSCRED: ::c_int = 17; -pub const SO_PEERCRED: ::c_int = 18; -pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; -pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; -pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; -pub const SO_BINDTODEVICE: ::c_int = 25; -pub const SO_ATTACH_FILTER: ::c_int = 26; -pub const SO_DETACH_FILTER: ::c_int = 27; -pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; -pub const SO_PEERNAME: ::c_int = 28; -pub const SO_TIMESTAMP: ::c_int = 29; -pub const SO_PEERSEC: ::c_int = 30; -pub const SO_SNDBUFFORCE: ::c_int = 31; -pub const SO_RCVBUFFORCE: ::c_int = 33; -pub const SO_PASSSEC: ::c_int = 34; -pub const SO_TIMESTAMPNS: ::c_int = 35; -pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; -pub const SO_MARK: ::c_int = 36; -pub const SO_RXQ_OVFL: ::c_int = 40; -pub const SO_WIFI_STATUS: ::c_int = 41; -pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; -pub const SO_PEEK_OFF: ::c_int = 42; -pub const SO_NOFCS: ::c_int = 43; -pub const SO_LOCK_FILTER: ::c_int = 44; -pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; -pub const SO_BUSY_POLL: ::c_int = 46; -pub const SO_MAX_PACING_RATE: ::c_int = 47; -pub const SO_BPF_EXTENSIONS: ::c_int = 48; - pub const FIOCLEX: ::c_ulong = 0x6601; pub const FIONCLEX: ::c_ulong = 0x6602; pub const FIONBIO: ::c_ulong = 0x667e; diff --git a/vendor/libc/src/unix/linux_like/linux/uclibc/mod.rs b/vendor/libc/src/unix/linux_like/linux/uclibc/mod.rs index cc5d5cdce9..9c79f99980 100644 --- a/vendor/libc/src/unix/linux_like/linux/uclibc/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/uclibc/mod.rs @@ -147,8 +147,7 @@ pub const LC_ALL: ::c_int = 6; // end different section // MS_ flags for mount(2) -pub const MS_RMT_MASK: ::c_ulong = - ::MS_RDONLY | ::MS_SYNCHRONOUS | ::MS_MANDLOCK | ::MS_I_VERSION; +pub const MS_RMT_MASK: ::c_ulong = ::MS_RDONLY | ::MS_SYNCHRONOUS | ::MS_MANDLOCK | ::MS_I_VERSION; pub const ENOTSUP: ::c_int = EOPNOTSUPP; diff --git a/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs b/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs index 80c9583372..4f7974c5e9 100644 --- a/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs +++ b/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs @@ -315,15 +315,8 @@ pub const NCCS: usize = 32; pub const SIG_SETMASK: ::c_int = 2; // Set the set of blocked signals pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; -pub const SO_BROADCAST: ::c_int = 6; pub const SOCK_DGRAM: ::c_int = 2; // connectionless, unreliable datagrams pub const SOCK_STREAM: ::c_int = 1; // …/common/bits/socket_type.h -pub const SO_ERROR: ::c_int = 4; -pub const SOL_SOCKET: ::c_int = 1; -pub const SO_RCVTIMEO: ::c_int = 20; -pub const SO_REUSEADDR: ::c_int = 2; -pub const SO_SNDTIMEO: ::c_int = 21; -pub const SO_TIMESTAMP: ::c_int = 0x1d; pub const RLIM_INFINITY: u64 = 0xffffffffffffffff; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; diff --git a/vendor/libc/src/unix/linux_like/mod.rs b/vendor/libc/src/unix/linux_like/mod.rs index 2a1b95f10a..1cfc910a17 100644 --- a/vendor/libc/src/unix/linux_like/mod.rs +++ b/vendor/libc/src/unix/linux_like/mod.rs @@ -1438,35 +1438,18 @@ safe_f! { extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; - pub fn mincore( - addr: *mut ::c_void, - len: ::size_t, - vec: *mut ::c_uchar, - ) -> ::c_int; + pub fn mincore(addr: *mut ::c_void, len: ::size_t, vec: *mut ::c_uchar) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; - pub fn clock_settime( - clk_id: ::clockid_t, - tp: *const ::timespec, - ) -> ::c_int; - pub fn clock_getcpuclockid( - pid: ::pid_t, - clk_id: *mut ::clockid_t, - ) -> ::c_int; + pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; + pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; - pub fn pthread_getattr_np( - native: ::pthread_t, - attr: *mut ::pthread_attr_t, - ) -> ::c_int; + pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, @@ -1481,18 +1464,9 @@ extern "C" { pub fn fstatfs64(fd: ::c_int, buf: *mut statfs64) -> ::c_int; pub fn statvfs64(path: *const ::c_char, buf: *mut statvfs64) -> ::c_int; pub fn fstatvfs64(fd: ::c_int, buf: *mut statvfs64) -> ::c_int; - pub fn memrchr( - cx: *const ::c_void, - c: ::c_int, - n: ::size_t, - ) -> *mut ::c_void; + pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; - pub fn posix_fadvise( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - advise: ::c_int, - ) -> ::c_int; + pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn posix_fadvise64( fd: ::c_int, offset: ::off64_t, @@ -1508,11 +1482,7 @@ extern "C" { ) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); - pub fn newlocale( - mask: ::c_int, - locale: *const ::c_char, - base: ::locale_t, - ) -> ::locale_t; + pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn creat64(path: *const c_char, mode: mode_t) -> ::c_int; pub fn fstat64(fildes: ::c_int, buf: *mut stat64) -> ::c_int; @@ -1534,15 +1504,11 @@ extern "C" { offset: off64_t, ) -> *mut ::c_void; pub fn open64(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; - pub fn openat64( - fd: ::c_int, - path: *const c_char, - oflag: ::c_int, - ... - ) -> ::c_int; - pub fn pread64( + pub fn openat64(fd: ::c_int, path: *const c_char, oflag: ::c_int, ...) -> ::c_int; + pub fn pread64(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off64_t) -> ::ssize_t; + pub fn pwrite64( fd: ::c_int, - buf: *mut ::c_void, + buf: *const ::c_void, count: ::size_t, offset: off64_t, ) -> ::ssize_t; @@ -1569,10 +1535,7 @@ extern "C" { attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; - pub fn pthread_condattr_setpshared( - attr: *mut pthread_condattr_t, - pshared: ::c_int, - ) -> ::c_int; + pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_mutexattr_setpshared( attr: *mut pthread_mutexattr_t, pshared: ::c_int, @@ -1581,34 +1544,15 @@ extern "C" { attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; - pub fn pthread_rwlockattr_setpshared( - attr: *mut pthread_rwlockattr_t, - val: ::c_int, - ) -> ::c_int; - pub fn ptsname_r( - fd: ::c_int, - buf: *mut ::c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; + pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; pub fn clearenv() -> ::c_int; - pub fn waitid( - idtype: idtype_t, - id: id_t, - infop: *mut ::siginfo_t, - options: ::c_int, - ) -> ::c_int; + pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) + -> ::c_int; pub fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int; pub fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int; - pub fn getresuid( - ruid: *mut ::uid_t, - euid: *mut ::uid_t, - suid: *mut ::uid_t, - ) -> ::c_int; - pub fn getresgid( - rgid: *mut ::gid_t, - egid: *mut ::gid_t, - sgid: *mut ::gid_t, - ) -> ::c_int; + pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, suid: *mut ::uid_t) -> ::c_int; + pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, sgid: *mut ::gid_t) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; pub fn brk(addr: *mut ::c_void) -> ::c_int; pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; @@ -1638,33 +1582,13 @@ extern "C" { ) -> ::c_int; pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); - pub fn bind( - socket: ::c_int, - address: *const ::sockaddr, - address_len: ::socklen_t, - ) -> ::c_int; + pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; - pub fn sendmsg( - fd: ::c_int, - msg: *const ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; - pub fn recvmsg( - fd: ::c_int, - msg: *mut ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; + pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn uname(buf: *mut ::utsname) -> ::c_int; } @@ -1677,12 +1601,6 @@ cfg_if! { iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t; - pub fn pwrite64( - fd: ::c_int, - buf: *const ::c_void, - count: ::size_t, - offset: off64_t, - ) -> ::ssize_t; pub fn pwritev64( fd: ::c_int, iov: *const ::iovec, diff --git a/vendor/libc/src/unix/mod.rs b/vendor/libc/src/unix/mod.rs index b3c0b47141..be7b6e73e8 100644 --- a/vendor/libc/src/unix/mod.rs +++ b/vendor/libc/src/unix/mod.rs @@ -422,18 +422,14 @@ extern "C" { base: *mut c_void, num: size_t, size: size_t, - compar: ::Option< - unsafe extern "C" fn(*const c_void, *const c_void) -> c_int, - >, + compar: ::Option c_int>, ); pub fn bsearch( key: *const c_void, base: *const c_void, num: size_t, size: size_t, - compar: ::Option< - unsafe extern "C" fn(*const c_void, *const c_void) -> c_int, - >, + compar: ::Option c_int>, ) -> *mut c_void; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), @@ -444,38 +440,21 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "freopen$UNIX2003" )] - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - file: *mut FILE, - ) -> *mut FILE; - pub fn fmemopen( - buf: *mut c_void, - size: size_t, - mode: *const c_char, - ) -> *mut FILE; - pub fn open_memstream( - ptr: *mut *mut c_char, - sizeloc: *mut size_t, - ) -> *mut FILE; + pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; + pub fn fmemopen(buf: *mut c_void, size: size_t, mode: *const c_char) -> *mut FILE; + pub fn open_memstream(ptr: *mut *mut c_char, sizeloc: *mut size_t) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; - pub fn setvbuf( - stream: *mut FILE, - buffer: *mut c_char, - mode: c_int, - size: size_t, - ) -> c_int; + pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; - pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) - -> *mut c_char; + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), @@ -484,22 +463,12 @@ extern "C" { pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; - pub fn fread( - ptr: *mut c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; + pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fwrite$UNIX2003" )] - pub fn fwrite( - ptr: *const c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; + pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); @@ -517,16 +486,8 @@ extern "C" { link_name = "strtod$UNIX2003" )] pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; - pub fn strtol( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_long; - pub fn strtoul( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_ulong; + pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; + pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; @@ -543,17 +504,9 @@ extern "C" { pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; - pub fn strncpy( - dst: *mut c_char, - src: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; - pub fn strncat( - s: *mut c_char, - ct: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; @@ -566,11 +519,7 @@ extern "C" { pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; - pub fn strncasecmp( - s1: *const c_char, - s2: *const c_char, - n: size_t, - ) -> c_int; + pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; #[cfg_attr( @@ -582,25 +531,13 @@ extern "C" { pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn strsignal(sig: c_int) -> *mut c_char; pub fn wcslen(buf: *const wchar_t) -> size_t; - pub fn wcstombs( - dest: *mut c_char, - src: *const wchar_t, - n: size_t, - ) -> ::size_t; + pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; - pub fn memcpy( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; - pub fn memmove( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; + pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; + pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; } @@ -610,28 +547,15 @@ extern "C" { #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid50")] pub fn getpwuid(uid: ::uid_t) -> *mut passwd; - pub fn fprintf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; - pub fn snprintf( - s: *mut ::c_char, - n: ::size_t, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_fscanf" )] - pub fn fscanf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_scanf" @@ -641,8 +565,7 @@ extern "C" { all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_sscanf" )] - pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) - -> ::c_int; + pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; @@ -664,11 +587,7 @@ extern "C" { link_name = "connect$UNIX2003" )] #[cfg_attr(target_os = "illumos", link_name = "__xnet_connect")] - pub fn connect( - socket: ::c_int, - address: *const sockaddr, - len: socklen_t, - ) -> ::c_int; + pub fn connect(socket: ::c_int, address: *const sockaddr, len: socklen_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "listen$UNIX2003" @@ -683,11 +602,7 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "accept$UNIX2003" )] - pub fn accept( - socket: ::c_int, - address: *mut sockaddr, - address_len: *mut socklen_t, - ) -> ::c_int; + pub fn accept(socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", @@ -895,11 +810,7 @@ extern "C" { newdirfd: ::c_int, linkpath: *const ::c_char, ) -> ::c_int; - pub fn unlinkat( - dirfd: ::c_int, - pathname: *const ::c_char, - flags: ::c_int, - ) -> ::c_int; + pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; pub fn alarm(seconds: ::c_uint) -> ::c_uint; @@ -923,16 +834,8 @@ extern "C" { pub fn dup(fd: ::c_int) -> ::c_int; pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> ::c_int; - pub fn execle( - path: *const ::c_char, - arg0: *const ::c_char, - ... - ) -> ::c_int; - pub fn execlp( - file: *const ::c_char, - arg0: *const ::c_char, - ... - ) -> ::c_int; + pub fn execle(path: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; + pub fn execlp(file: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::c_int; pub fn execve( prog: *const c_char, @@ -953,11 +856,7 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "getopt$UNIX2003" )] - pub fn getopt( - argc: ::c_int, - argv: *const *mut c_char, - optstr: *const c_char, - ) -> ::c_int; + pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn getpgid(pid: pid_t) -> pid_t; pub fn getpgrp() -> pid_t; pub fn getpid() -> pid_t; @@ -968,17 +867,12 @@ extern "C" { pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; pub fn pipe(fds: *mut ::c_int) -> ::c_int; - pub fn posix_memalign( - memptr: *mut *mut ::c_void, - align: ::size_t, - size: ::size_t, - ) -> ::c_int; + pub fn posix_memalign(memptr: *mut *mut ::c_void, align: ::size_t, size: ::size_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "read$UNIX2003" )] - pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) - -> ::ssize_t; + pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; pub fn rmdir(path: *const c_char) -> ::c_int; pub fn seteuid(uid: uid_t) -> ::c_int; pub fn setegid(gid: gid_t) -> ::c_int; @@ -1005,11 +899,7 @@ extern "C" { link_name = "ttyname_r$UNIX2003" )] #[cfg_attr(target_os = "illumos", link_name = "__posix_ttyname_r")] - pub fn ttyname_r( - fd: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn ttyname_r(fd: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn unlink(c: *const c_char) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), @@ -1020,40 +910,22 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "waitpid$UNIX2003" )] - pub fn waitpid( - pid: pid_t, - status: *mut ::c_int, - options: ::c_int, - ) -> pid_t; + pub fn waitpid(pid: pid_t, status: *mut ::c_int, options: ::c_int) -> pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "write$UNIX2003" )] - pub fn write( - fd: ::c_int, - buf: *const ::c_void, - count: ::size_t, - ) -> ::ssize_t; + pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pread$UNIX2003" )] - pub fn pread( - fd: ::c_int, - buf: *mut ::c_void, - count: ::size_t, - offset: off_t, - ) -> ::ssize_t; + pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pwrite$UNIX2003" )] - pub fn pwrite( - fd: ::c_int, - buf: *const ::c_void, - count: ::size_t, - offset: off_t, - ) -> ::ssize_t; + pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn umask(mask: mode_t) -> mode_t; #[cfg_attr(target_os = "netbsd", link_name = "__utime50")] @@ -1094,10 +966,7 @@ extern "C" { pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int; pub fn if_nametoindex(ifname: *const c_char) -> ::c_uint; - pub fn if_indextoname( - ifindex: ::c_uint, - ifname: *mut ::c_char, - ) -> *mut ::c_char; + pub fn if_indextoname(ifindex: ::c_uint, ifname: *mut ::c_char) -> *mut ::c_char; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), @@ -1120,11 +989,7 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "setenv$UNIX2003" )] - pub fn setenv( - name: *const c_char, - val: *const c_char, - overwrite: ::c_int, - ) -> ::c_int; + pub fn setenv(name: *const c_char, val: *const c_char, overwrite: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "unsetenv$UNIX2003" @@ -1145,10 +1010,7 @@ extern "C" { any(target_os = "macos", target_os = "ios"), link_name = "realpath$DARWIN_EXTSN" )] - pub fn realpath( - pathname: *const ::c_char, - resolved: *mut ::c_char, - ) -> *mut ::c_char; + pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char) -> *mut ::c_char; pub fn flock(fd: ::c_int, operation: ::c_int) -> ::c_int; @@ -1160,21 +1022,12 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "pthread_join$UNIX2003" )] - pub fn pthread_join( - native: ::pthread_t, - value: *mut *mut ::c_void, - ) -> ::c_int; + pub fn pthread_join(native: ::pthread_t, value: *mut *mut ::c_void) -> ::c_int; pub fn pthread_exit(value: *mut ::c_void) -> !; pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int; - pub fn pthread_attr_setstacksize( - attr: *mut ::pthread_attr_t, - stack_size: ::size_t, - ) -> ::c_int; - pub fn pthread_attr_setdetachstate( - attr: *mut ::pthread_attr_t, - state: ::c_int, - ) -> ::c_int; + pub fn pthread_attr_setstacksize(attr: *mut ::pthread_attr_t, stack_size: ::size_t) -> ::c_int; + pub fn pthread_attr_setdetachstate(attr: *mut ::pthread_attr_t, state: ::c_int) -> ::c_int; pub fn pthread_detach(thread: ::pthread_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__libc_thr_yield")] pub fn sched_yield() -> ::c_int; @@ -1184,10 +1037,7 @@ extern "C" { ) -> ::c_int; pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void; - pub fn pthread_setspecific( - key: pthread_key_t, - value: *const ::c_void, - ) -> ::c_int; + pub fn pthread_setspecific(key: pthread_key_t, value: *const ::c_void) -> ::c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, @@ -1202,30 +1052,20 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "pthread_mutexattr_destroy$UNIX2003" )] - pub fn pthread_mutexattr_destroy( - attr: *mut pthread_mutexattr_t, - ) -> ::c_int; - pub fn pthread_mutexattr_settype( - attr: *mut pthread_mutexattr_t, - _type: ::c_int, - ) -> ::c_int; + pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> ::c_int; + pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_init$UNIX2003" )] - pub fn pthread_cond_init( - cond: *mut pthread_cond_t, - attr: *const pthread_condattr_t, - ) -> ::c_int; + pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) + -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_wait$UNIX2003" )] - pub fn pthread_cond_wait( - cond: *mut pthread_cond_t, - lock: *mut pthread_mutex_t, - ) -> ::c_int; + pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_timedwait$UNIX2003" @@ -1278,11 +1118,8 @@ extern "C" { link_name = "pthread_rwlock_unlock$UNIX2003" )] pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> ::c_int; - pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) - -> ::c_int; - pub fn pthread_rwlockattr_destroy( - attr: *mut pthread_rwlockattr_t, - ) -> ::c_int; + pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> ::c_int; + pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> ::c_int; #[cfg_attr(target_os = "illumos", link_name = "__xnet_getsockopt")] pub fn getsockopt( @@ -1294,23 +1131,13 @@ extern "C" { ) -> ::c_int; pub fn raise(signum: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")] - pub fn sigaction( - signum: ::c_int, - act: *const sigaction, - oldact: *mut sigaction, - ) -> ::c_int; + pub fn sigaction(signum: ::c_int, act: *const sigaction, oldact: *mut sigaction) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__utimes50")] - pub fn utimes( - filename: *const ::c_char, - times: *const ::timeval, - ) -> ::c_int; + pub fn utimes(filename: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn dlopen(filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; pub fn dlerror() -> *mut ::c_char; - pub fn dlsym( - handle: *mut ::c_void, - symbol: *const ::c_char, - ) -> *mut ::c_void; + pub fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void; pub fn dlclose(handle: *mut ::c_void) -> ::c_int; pub fn dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int; @@ -1342,10 +1169,7 @@ extern "C" { ), link_name = "__res_init" )] - #[cfg_attr( - any(target_os = "macos", target_os = "ios"), - link_name = "res_9_init" - )] + #[cfg_attr(any(target_os = "macos", target_os = "ios"), link_name = "res_9_init")] pub fn res_init() -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__gmtime_r50")] @@ -1390,21 +1214,11 @@ extern "C" { all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "mknod@FBSD_1.0" )] - pub fn mknod( - pathname: *const ::c_char, - mode: ::mode_t, - dev: ::dev_t, - ) -> ::c_int; + pub fn mknod(pathname: *const ::c_char, mode: ::mode_t, dev: ::dev_t) -> ::c_int; pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn endservent(); - pub fn getservbyname( - name: *const ::c_char, - proto: *const ::c_char, - ) -> *mut servent; - pub fn getservbyport( - port: ::c_int, - proto: *const ::c_char, - ) -> *mut servent; + pub fn getservbyname(name: *const ::c_char, proto: *const ::c_char) -> *mut servent; + pub fn getservbyport(port: ::c_int, proto: *const ::c_char) -> *mut servent; pub fn getservent() -> *mut servent; pub fn setservent(stayopen: ::c_int); pub fn getprotobyname(name: *const ::c_char) -> *mut protoent; @@ -1419,22 +1233,12 @@ extern "C" { all(target_os = "macos", target_arch = "x86"), link_name = "send$UNIX2003" )] - pub fn send( - socket: ::c_int, - buf: *const ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; + pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recv$UNIX2003" )] - pub fn recv( - socket: ::c_int, - buf: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; + pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "putenv$UNIX2003" @@ -1463,10 +1267,7 @@ extern "C" { timeout: *mut timeval, ) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__setlocale50")] - pub fn setlocale( - category: ::c_int, - locale: *const ::c_char, - ) -> *mut ::c_char; + pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; pub fn localeconv() -> *mut lconv; #[cfg_attr( @@ -1479,11 +1280,7 @@ extern "C" { pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> ::c_int; pub fn fstatvfs(fd: ::c_int, buf: *mut statvfs) -> ::c_int; - pub fn readlink( - path: *const c_char, - buf: *mut c_char, - bufsz: ::size_t, - ) -> ::ssize_t; + pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t; #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] pub fn sigemptyset(set: *mut sigset_t) -> ::c_int; @@ -1497,11 +1294,7 @@ extern "C" { pub fn sigismember(set: *const sigset_t, signum: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigprocmask14")] - pub fn sigprocmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn sigprocmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigpending14")] pub fn sigpending(set: *mut sigset_t) -> ::c_int; @@ -1526,11 +1319,7 @@ extern "C" { timeout: *const timespec, sigmask: *const sigset_t, ) -> ::c_int; - pub fn fseeko( - stream: *mut ::FILE, - offset: ::off_t, - whence: ::c_int, - ) -> ::c_int; + pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), @@ -1542,11 +1331,7 @@ extern "C" { pub fn cfsetispeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn cfsetospeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn tcgetattr(fd: ::c_int, termios: *mut ::termios) -> ::c_int; - pub fn tcsetattr( - fd: ::c_int, - optional_actions: ::c_int, - termios: *const ::termios, - ) -> ::c_int; + pub fn tcsetattr(fd: ::c_int, optional_actions: ::c_int, termios: *const ::termios) -> ::c_int; pub fn tcflow(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcflush(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcgetsid(fd: ::c_int) -> ::pid_t; @@ -1573,11 +1358,7 @@ extern "C" { pub fn unlockpt(fd: ::c_int) -> ::c_int; pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; - pub fn getline( - lineptr: *mut *mut c_char, - n: *mut size_t, - stream: *mut FILE, - ) -> ssize_t; + pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; pub fn lockf(fd: ::c_int, cmd: ::c_int, len: ::off_t) -> ::c_int; } diff --git a/vendor/libc/src/unix/newlib/mod.rs b/vendor/libc/src/unix/newlib/mod.rs index 270dd7b92f..6e87983fe5 100644 --- a/vendor/libc/src/unix/newlib/mod.rs +++ b/vendor/libc/src/unix/newlib/mod.rs @@ -583,18 +583,10 @@ extern "C" { pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; #[cfg_attr(target_os = "linux", link_name = "__xpg_strerror_r")] - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn atof(s: *const ::c_char) -> ::c_double; @@ -607,20 +599,10 @@ extern "C" { target_arch = "powerpc", target_vendor = "nintendo" )))] - pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) - -> ::c_int; - pub fn clock_settime( - clock_id: ::clockid_t, - tp: *const ::timespec, - ) -> ::c_int; - pub fn clock_gettime( - clock_id: ::clockid_t, - tp: *mut ::timespec, - ) -> ::c_int; - pub fn clock_getres( - clock_id: ::clockid_t, - res: *mut ::timespec, - ) -> ::c_int; + pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) -> ::c_int; + pub fn clock_settime(clock_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; + pub fn clock_gettime(clock_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; + pub fn clock_getres(clock_id: ::clockid_t, res: *mut ::timespec) -> ::c_int; pub fn closesocket(sockfd: ::c_int) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; #[cfg(not(all( @@ -674,11 +656,7 @@ extern "C" { buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; - pub fn pthread_sigmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; diff --git a/vendor/libc/src/unix/newlib/no_align.rs b/vendor/libc/src/unix/newlib/no_align.rs index 316c464ed5..ce3aca4ed5 100644 --- a/vendor/libc/src/unix/newlib/no_align.rs +++ b/vendor/libc/src/unix/newlib/no_align.rs @@ -47,5 +47,5 @@ macro_rules! expand_align { size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } - } + }; } diff --git a/vendor/libc/src/unix/newlib/xtensa/mod.rs b/vendor/libc/src/unix/newlib/xtensa/mod.rs index bc31506b5d..f520f7a1ee 100644 --- a/vendor/libc/src/unix/newlib/xtensa/mod.rs +++ b/vendor/libc/src/unix/newlib/xtensa/mod.rs @@ -85,22 +85,9 @@ pub const MSG_MORE: ::c_int = 0x10; pub const MSG_NOSIGNAL: ::c_int = 0x20; extern "C" { - pub fn sendmsg( - s: ::c_int, - msg: *const ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; - pub fn recvmsg( - s: ::c_int, - msg: *mut ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn sendmsg(s: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; + pub fn recvmsg(s: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; - pub fn writev(s: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) - -> ::c_int; - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn writev(s: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::c_int; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; } diff --git a/vendor/libc/src/unix/redox/mod.rs b/vendor/libc/src/unix/redox/mod.rs index faf8f0bf75..45615a5498 100644 --- a/vendor/libc/src/unix/redox/mod.rs +++ b/vendor/libc/src/unix/redox/mod.rs @@ -937,11 +937,7 @@ safe_f! { extern "C" { // errno.h pub fn __errno_location() -> *mut ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; // unistd.h pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; @@ -991,32 +987,16 @@ extern "C" { maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; - pub fn epoll_ctl( - epfd: ::c_int, - op: ::c_int, - fd: ::c_int, - event: *mut ::epoll_event, - ) -> ::c_int; + pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) + -> ::c_int; // sys/ioctl.h pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; // sys/mman.h - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; - pub fn mprotect( - addr: *mut ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; - pub fn shm_open( - name: *const c_char, - oflag: ::c_int, - mode: mode_t, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; + pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; + pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; // sys/resource.h @@ -1024,11 +1004,7 @@ extern "C" { pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; // sys/socket.h - pub fn bind( - socket: ::c_int, - address: *const ::sockaddr, - address_len: ::socklen_t, - ) -> ::c_int; + pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, @@ -1042,16 +1018,8 @@ extern "C" { pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; // sys/uio.h - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; + pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; // sys/utsname.h pub fn uname(utsname: *mut utsname) -> ::c_int; diff --git a/vendor/libc/src/unix/solarish/compat.rs b/vendor/libc/src/unix/solarish/compat.rs index 6ada067550..4a232f0d83 100644 --- a/vendor/libc/src/unix/solarish/compat.rs +++ b/vendor/libc/src/unix/solarish/compat.rs @@ -7,15 +7,8 @@ const PTEM: &[u8] = b"ptem\0"; const LDTERM: &[u8] = b"ldterm\0"; pub unsafe fn cfmakeraw(termios: *mut ::termios) { - (*termios).c_iflag &= !(IMAXBEL - | IGNBRK - | BRKINT - | PARMRK - | ISTRIP - | INLCR - | IGNCR - | ICRNL - | IXON); + (*termios).c_iflag &= + !(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); (*termios).c_oflag &= !OPOST; (*termios).c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN); (*termios).c_cflag &= !(CSIZE | PARENB); @@ -38,10 +31,7 @@ pub unsafe fn cfmakeraw(termios: *mut ::termios) { (*termios).c_cc[VTIME] = 0; } -pub unsafe fn cfsetspeed( - termios: *mut ::termios, - speed: ::speed_t, -) -> ::c_int { +pub unsafe fn cfsetspeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int { // Neither of these functions on illumos or Solaris actually ever // return an error ::cfsetispeed(termios, speed); @@ -100,9 +90,7 @@ pub unsafe fn openpty( } else if setup == 0 { // The line discipline is not present, so push the appropriate STREAMS // modules for the subordinate device: - if ::ioctl(fds, I_PUSH, PTEM.as_ptr()) < 0 - || ::ioctl(fds, I_PUSH, LDTERM.as_ptr()) < 0 - { + if ::ioctl(fds, I_PUSH, PTEM.as_ptr()) < 0 || ::ioctl(fds, I_PUSH, LDTERM.as_ptr()) < 0 { return bail(fdm, fds); } } diff --git a/vendor/libc/src/unix/solarish/illumos.rs b/vendor/libc/src/unix/solarish/illumos.rs index 184f73b522..730bb690c4 100644 --- a/vendor/libc/src/unix/solarish/illumos.rs +++ b/vendor/libc/src/unix/solarish/illumos.rs @@ -36,9 +36,5 @@ pub const F_FLOCKW: ::c_int = 56; 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 mincore(addr: ::caddr_t, len: ::size_t, vec: *mut ::c_char) -> ::c_int; } diff --git a/vendor/libc/src/unix/solarish/mod.rs b/vendor/libc/src/unix/solarish/mod.rs index 2db4916a52..6166da5d9e 100644 --- a/vendor/libc/src/unix/solarish/mod.rs +++ b/vendor/libc/src/unix/solarish/mod.rs @@ -2078,11 +2078,8 @@ pub const STA_PPSJITTER: i32 = 0x0200; pub const STA_PPSWANDER: i32 = 0x0400; pub const STA_PPSERROR: i32 = 0x0800; pub const STA_CLOCKERR: i32 = 0x1000; -pub const STA_RONLY: i32 = STA_PPSSIGNAL - | STA_PPSJITTER - | STA_PPSWANDER - | STA_PPSERROR - | STA_CLOCKERR; +pub const STA_RONLY: i32 = + STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR; pub const TIME_OK: i32 = 0; pub const TIME_INS: i32 = 1; pub const TIME_DEL: i32 = 2; @@ -2103,12 +2100,14 @@ const _CMSG_HDR_ALIGNMENT: usize = 4; const _CMSG_DATA_ALIGNMENT: usize = ::mem::size_of::<::c_int>(); -fn _CMSG_HDR_ALIGN(p: usize) -> usize { - (p + _CMSG_HDR_ALIGNMENT - 1) & !(_CMSG_HDR_ALIGNMENT - 1) -} +const_fn! { + {const} fn _CMSG_HDR_ALIGN(p: usize) -> usize { + (p + _CMSG_HDR_ALIGNMENT - 1) & !(_CMSG_HDR_ALIGNMENT - 1) + } -fn _CMSG_DATA_ALIGN(p: usize) -> usize { - (p + _CMSG_DATA_ALIGNMENT - 1) & !(_CMSG_DATA_ALIGNMENT - 1) + {const} fn _CMSG_DATA_ALIGN(p: usize) -> usize { + (p + _CMSG_DATA_ALIGNMENT - 1) & !(_CMSG_DATA_ALIGNMENT - 1) + } } f! { @@ -2146,7 +2145,7 @@ f! { } } - pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { _CMSG_HDR_ALIGN(::mem::size_of::<::cmsghdr>() as usize + length as usize) as ::c_uint } @@ -2216,18 +2215,10 @@ extern "C" { pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; - pub fn sem_init( - sem: *mut sem_t, - pshared: ::c_int, - value: ::c_uint, - ) -> ::c_int; + pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; @@ -2246,11 +2237,7 @@ extern "C" { pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn ioctl(fildes: ::c_int, request: ::c_int, ...) -> ::c_int; - pub fn mprotect( - addr: *const ::c_void, - len: ::size_t, - prot: ::c_int, - ) -> ::c_int; + pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn ___errno() -> *mut ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; @@ -2260,10 +2247,7 @@ extern "C" { rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; - pub fn clock_settime( - clk_id: ::clockid_t, - tp: *const ::timespec, - ) -> ::c_int; + pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, @@ -2277,22 +2261,16 @@ extern "C" { pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn fdatasync(fd: ::c_int) -> ::c_int; - pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) - -> *mut ::c_char; + pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); - pub fn newlocale( - mask: ::c_int, - locale: *const ::c_char, - base: ::locale_t, - ) -> ::locale_t; + pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn getprogname() -> *const ::c_char; pub fn setprogname(name: *const ::c_char); pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::c_int) -> ::c_int; - pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) - -> ::c_int; + pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) -> ::c_int; pub fn mknodat( dirfd: ::c_int, @@ -2300,11 +2278,7 @@ extern "C" { mode: ::mode_t, dev: dev_t, ) -> ::c_int; - pub fn mkfifoat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; + pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); @@ -2327,78 +2301,45 @@ extern "C" { attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; - pub fn sem_timedwait( - sem: *mut sem_t, - abstime: *const ::timespec, - ) -> ::c_int; + pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; - pub fn waitid( - idtype: idtype_t, - id: id_t, - infop: *mut ::siginfo_t, - options: ::c_int, - ) -> ::c_int; + pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) + -> ::c_int; #[cfg_attr(target_os = "illumos", link_name = "_glob_ext")] pub fn glob( pattern: *const ::c_char, flags: ::c_int, - errfunc: ::Option< - extern "C" fn(epath: *const ::c_char, errno: ::c_int) -> ::c_int, - >, + errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; #[cfg_attr(target_os = "illumos", link_name = "_globfree_ext")] pub fn globfree(pglob: *mut ::glob_t); - pub fn posix_madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; - pub fn shmat( - shmid: ::c_int, - shmaddr: *const ::c_void, - shmflg: ::c_int, - ) -> *mut ::c_void; + pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; - pub fn shmctl( - shmid: ::c_int, - cmd: ::c_int, - buf: *mut ::shmid_ds, - ) -> ::c_int; + pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmget(key: key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; - pub fn shm_open( - name: *const ::c_char, - oflag: ::c_int, - mode: ::mode_t, - ) -> ::c_int; + pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn madvise( - addr: *mut ::c_void, - len: ::size_t, - advice: ::c_int, - ) -> ::c_int; + pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; - pub fn msync( - addr: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::c_int; + pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; @@ -2411,11 +2352,7 @@ extern "C" { addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; - pub fn futimesat( - fd: ::c_int, - path: *const ::c_char, - times: *const ::timeval, - ) -> ::c_int; + pub fn futimesat(fd: ::c_int, path: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn futimens(dirfd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, @@ -2426,35 +2363,15 @@ extern "C" { pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; #[cfg_attr(target_os = "illumos", link_name = "__xnet_bind")] - pub fn bind( - socket: ::c_int, - address: *const ::sockaddr, - address_len: ::socklen_t, - ) -> ::c_int; + pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; #[cfg_attr(target_os = "illumos", link_name = "__xnet_sendmsg")] - pub fn sendmsg( - fd: ::c_int, - msg: *const ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; #[cfg_attr(target_os = "illumos", link_name = "__xnet_recvmsg")] - pub fn recvmsg( - fd: ::c_int, - msg: *mut ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn accept4( fd: ::c_int, address: *mut sockaddr, @@ -2492,11 +2409,7 @@ extern "C" { abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; - pub fn mq_setattr( - mqd: ::mqd_t, - newattr: *const ::mq_attr, - oldattr: *mut ::mq_attr, - ) -> ::c_int; + pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; pub fn port_create() -> ::c_int; pub fn port_associate( port: ::c_int, @@ -2505,16 +2418,8 @@ extern "C" { events: ::c_int, user: *mut ::c_void, ) -> ::c_int; - pub fn port_dissociate( - port: ::c_int, - source: ::c_int, - object: ::uintptr_t, - ) -> ::c_int; - pub fn port_get( - port: ::c_int, - pe: *mut port_event, - timeout: *mut ::timespec, - ) -> ::c_int; + pub fn port_dissociate(port: ::c_int, source: ::c_int, object: ::uintptr_t) -> ::c_int; + pub fn port_get(port: ::c_int, pe: *mut port_event, timeout: *mut ::timespec) -> ::c_int; pub fn port_getn( port: ::c_int, pe_list: *mut port_event, @@ -2522,11 +2427,7 @@ extern "C" { nget: *mut ::c_uint, timeout: *mut ::timespec, ) -> ::c_int; - pub fn port_send( - port: ::c_int, - events: ::c_int, - user: *mut ::c_void, - ) -> ::c_int; + pub fn port_send(port: ::c_int, events: ::c_int, user: *mut ::c_void) -> ::c_int; pub fn port_sendn( port_list: *mut ::c_int, error_list: *mut ::c_int, @@ -2569,12 +2470,8 @@ extern "C" { maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; - pub fn epoll_ctl( - epfd: ::c_int, - op: ::c_int, - fd: ::c_int, - event: *mut ::epoll_event, - ) -> ::c_int; + pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) + -> ::c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), @@ -2587,11 +2484,7 @@ extern "C" { buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; - pub fn pthread_sigmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; @@ -2685,11 +2578,7 @@ extern "C" { pub fn ntp_adjtime(buf: *mut timex) -> ::c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int; - pub fn timer_create( - clock_id: clockid_t, - evp: *mut sigevent, - timerid: *mut timer_t, - ) -> ::c_int; + pub fn timer_create(clock_id: clockid_t, evp: *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, value: *mut itimerspec) -> ::c_int; @@ -2711,15 +2600,11 @@ extern "C" { pub fn ucred_getegid(ucred: *const ucred_t) -> ::gid_t; pub fn ucred_getrgid(ucred: *const ucred_t) -> ::gid_t; pub fn ucred_getsgid(ucred: *const ucred_t) -> ::gid_t; - pub fn ucred_getgroups( - ucred: *const ucred_t, - groups: *mut *const ::gid_t, - ) -> ::c_int; + pub fn ucred_getgroups(ucred: *const ucred_t, groups: *mut *const ::gid_t) -> ::c_int; pub fn ucred_getpid(ucred: *const ucred_t) -> ::pid_t; pub fn ucred_getprojid(ucred: *const ucred_t) -> projid_t; pub fn ucred_getzoneid(ucred: *const ucred_t) -> zoneid_t; - pub fn ucred_getpflags(ucred: *const ucred_t, flags: ::c_uint) - -> ::c_uint; + pub fn ucred_getpflags(ucred: *const ucred_t, flags: ::c_uint) -> ::c_uint; pub fn ucred_size() -> ::size_t; } diff --git a/vendor/libc/src/unix/solarish/solaris.rs b/vendor/libc/src/unix/solarish/solaris.rs index a07bc88a49..8ea070c6db 100644 --- a/vendor/libc/src/unix/solarish/solaris.rs +++ b/vendor/libc/src/unix/solarish/solaris.rs @@ -43,11 +43,7 @@ extern "C" { envp: *const *const ::c_char, ) -> ::c_int; - pub fn mincore( - addr: *const ::c_void, - len: ::size_t, - vec: *mut ::c_char, - ) -> ::c_int; + pub fn mincore(addr: *const ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; pub fn door_call(d: ::c_int, params: *const door_arg_t) -> ::c_int; pub fn door_return( @@ -70,10 +66,7 @@ extern "C" { pub fn fattach(fildes: ::c_int, path: *const ::c_char) -> ::c_int; - pub fn pthread_getattr_np( - thread: ::pthread_t, - attr: *mut ::pthread_attr_t, - ) -> ::c_int; + pub fn pthread_getattr_np(thread: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; } s_no_extra_traits! { diff --git a/vendor/libc/src/vxworks/mod.rs b/vendor/libc/src/vxworks/mod.rs old mode 100644 new mode 100755 index 668a7fcc96..1e4deb71bb --- a/vendor/libc/src/vxworks/mod.rs +++ b/vendor/libc/src/vxworks/mod.rs @@ -702,24 +702,16 @@ pub const S_nfsLib_NFSERR_NAMETOOLONG: ::c_int = ENAMETOOLONG; pub const S_nfsLib_NFSERR_NOTEMPTY: ::c_int = ENOTEMPTY; pub const S_nfsLib_NFSERR_DQUOT: ::c_int = EDQUOT; pub const S_nfsLib_NFSERR_STALE: ::c_int = ESTALE; -pub const S_nfsLib_NFSERR_WFLUSH: ::c_int = - M_nfsStat | nfsstat::NFSERR_WFLUSH as ::c_int; -pub const S_nfsLib_NFSERR_REMOTE: ::c_int = - M_nfsStat | nfsstat::NFSERR_REMOTE as ::c_int; -pub const S_nfsLib_NFSERR_BADHANDLE: ::c_int = - M_nfsStat | nfsstat::NFSERR_BADHANDLE as ::c_int; -pub const S_nfsLib_NFSERR_NOT_SYNC: ::c_int = - M_nfsStat | nfsstat::NFSERR_NOT_SYNC as ::c_int; -pub const S_nfsLib_NFSERR_BAD_COOKIE: ::c_int = - M_nfsStat | nfsstat::NFSERR_BAD_COOKIE as ::c_int; +pub const S_nfsLib_NFSERR_WFLUSH: ::c_int = M_nfsStat | nfsstat::NFSERR_WFLUSH as ::c_int; +pub const S_nfsLib_NFSERR_REMOTE: ::c_int = M_nfsStat | nfsstat::NFSERR_REMOTE as ::c_int; +pub const S_nfsLib_NFSERR_BADHANDLE: ::c_int = M_nfsStat | nfsstat::NFSERR_BADHANDLE as ::c_int; +pub const S_nfsLib_NFSERR_NOT_SYNC: ::c_int = M_nfsStat | nfsstat::NFSERR_NOT_SYNC as ::c_int; +pub const S_nfsLib_NFSERR_BAD_COOKIE: ::c_int = M_nfsStat | nfsstat::NFSERR_BAD_COOKIE as ::c_int; pub const S_nfsLib_NFSERR_NOTSUPP: ::c_int = EOPNOTSUPP; -pub const S_nfsLib_NFSERR_TOOSMALL: ::c_int = - M_nfsStat | nfsstat::NFSERR_TOOSMALL as ::c_int; +pub const S_nfsLib_NFSERR_TOOSMALL: ::c_int = M_nfsStat | nfsstat::NFSERR_TOOSMALL as ::c_int; pub const S_nfsLib_NFSERR_SERVERFAULT: ::c_int = EIO; -pub const S_nfsLib_NFSERR_BADTYPE: ::c_int = - M_nfsStat | nfsstat::NFSERR_BADTYPE as ::c_int; -pub const S_nfsLib_NFSERR_JUKEBOX: ::c_int = - M_nfsStat | nfsstat::NFSERR_JUKEBOX as ::c_int; +pub const S_nfsLib_NFSERR_BADTYPE: ::c_int = M_nfsStat | nfsstat::NFSERR_BADTYPE as ::c_int; +pub const S_nfsLib_NFSERR_JUKEBOX: ::c_int = M_nfsStat | nfsstat::NFSERR_JUKEBOX as ::c_int; // in.h pub const IPPROTO_IP: ::c_int = 0; @@ -803,8 +795,7 @@ pub const SOCK_PACKET: ::c_int = 10; pub const _SS_MAXSIZE: usize = 128; pub const _SS_ALIGNSIZE: usize = size_of::(); -pub const _SS_PAD1SIZE: usize = - _SS_ALIGNSIZE - size_of::<::c_uchar>() - size_of::<::sa_family_t>(); +pub const _SS_PAD1SIZE: usize = _SS_ALIGNSIZE - size_of::<::c_uchar>() - size_of::<::sa_family_t>(); pub const _SS_PAD2SIZE: usize = _SS_MAXSIZE - size_of::<::c_uchar>() - size_of::<::sa_family_t>() @@ -951,14 +942,13 @@ pub const _PARM_PATH_MAX: ::c_int = 1024; pub const WNOHANG: ::c_int = 0x01; pub const WUNTRACED: ::c_int = 0x02; -const PTHREAD_MUTEXATTR_INITIALIZER: pthread_mutexattr_t = - pthread_mutexattr_t { - mutexAttrStatus: PTHREAD_INITIALIZED_OBJ, - mutexAttrProtocol: PTHREAD_PRIO_NONE, - mutexAttrPrioceiling: 0, - mutexAttrType: PTHREAD_MUTEX_DEFAULT, - mutexAttrPshared: 1, - }; +const PTHREAD_MUTEXATTR_INITIALIZER: pthread_mutexattr_t = pthread_mutexattr_t { + mutexAttrStatus: PTHREAD_INITIALIZED_OBJ, + mutexAttrProtocol: PTHREAD_PRIO_NONE, + mutexAttrPrioceiling: 0, + mutexAttrType: PTHREAD_MUTEX_DEFAULT, + mutexAttrPshared: 1, +}; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { mutexSemId: null_mut(), mutexValid: PTHREAD_VALID_OBJ, @@ -984,13 +974,12 @@ pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { condSemName: [0; _PTHREAD_SHARED_SEM_NAME_MAX], }; -const PTHREAD_RWLOCKATTR_INITIALIZER: pthread_rwlockattr_t = - pthread_rwlockattr_t { - rwlockAttrStatus: PTHREAD_INITIALIZED_OBJ, - rwlockAttrPshared: 1, - rwlockAttrMaxReaders: 0, - rwlockAttrConformOpt: 1, - }; +const PTHREAD_RWLOCKATTR_INITIALIZER: pthread_rwlockattr_t = pthread_rwlockattr_t { + rwlockAttrStatus: PTHREAD_INITIALIZED_OBJ, + rwlockAttrPshared: 1, + rwlockAttrMaxReaders: 0, + rwlockAttrConformOpt: 1, +}; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { rwlockSemId: null_mut(), rwlockReadersRefCount: 0, @@ -1040,7 +1029,7 @@ impl ::Clone for fpos_t { } f! { - pub fn CMSG_ALIGN(len: usize) -> usize { + pub {const} fn CMSG_ALIGN(len: usize) -> usize { len + ::mem::size_of::() - 1 & !(::mem::size_of::() - 1) } @@ -1071,7 +1060,7 @@ f! { .offset(CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } - pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { + pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(::mem::size_of::())) as ::c_uint } @@ -1097,44 +1086,24 @@ extern "C" { pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - file: *mut FILE, - ) -> *mut FILE; + pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; - pub fn setvbuf( - stream: *mut FILE, - buffer: *mut c_char, - mode: c_int, - size: size_t, - ) -> c_int; + pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; - pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) - -> *mut c_char; + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; - pub fn fread( - ptr: *mut c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; - pub fn fwrite( - ptr: *const c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; + pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; + pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); @@ -1145,16 +1114,8 @@ extern "C" { pub fn perror(s: *const c_char); pub fn atoi(s: *const c_char) -> c_int; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; - pub fn strtol( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_long; - pub fn strtoul( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_ulong; + pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; + pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; @@ -1166,17 +1127,9 @@ extern "C" { pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; - pub fn strncpy( - dst: *mut c_char, - src: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; - pub fn strncat( - s: *mut c_char, - ct: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; @@ -1188,60 +1141,30 @@ extern "C" { pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; - pub fn strncasecmp( - s1: *const c_char, - s2: *const c_char, - n: size_t, - ) -> c_int; + pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; - pub fn wcstombs( - dest: *mut c_char, - src: *const wchar_t, - n: size_t, - ) -> ::size_t; + pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; - pub fn memcpy( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; - pub fn memmove( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; + pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; + pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; } extern "C" { - pub fn fprintf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; - pub fn snprintf( - s: *mut ::c_char, - n: ::size_t, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; - pub fn fscanf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn scanf(format: *const ::c_char, ...) -> ::c_int; - pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) - -> ::c_int; + pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; @@ -1259,11 +1182,7 @@ extern "C" { pub fn geteuid() -> uid_t; pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t) -> ::c_int; pub fn getlogin() -> *mut c_char; - pub fn getopt( - argc: ::c_int, - argv: *const *mut c_char, - optstr: *const c_char, - ) -> ::c_int; + pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; pub fn pause() -> ::c_int; pub fn seteuid(uid: uid_t) -> ::c_int; @@ -1289,27 +1208,13 @@ extern "C" { pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn pthread_exit(value: *mut ::c_void) -> !; - pub fn pthread_attr_setdetachstate( - attr: *mut ::pthread_attr_t, - state: ::c_int, - ) -> ::c_int; + pub fn pthread_attr_setdetachstate(attr: *mut ::pthread_attr_t, state: ::c_int) -> ::c_int; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; - pub fn sigaction( - signum: ::c_int, - act: *const sigaction, - oldact: *mut sigaction, - ) -> ::c_int; + pub fn sigaction(signum: ::c_int, act: *const sigaction, oldact: *mut sigaction) -> ::c_int; - pub fn utimes( - filename: *const ::c_char, - times: *const ::timeval, - ) -> ::c_int; + pub fn utimes(filename: *const ::c_char, times: *const ::timeval) -> ::c_int; #[link_name = "_rtld_dlopen"] pub fn dlopen(filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; @@ -1318,10 +1223,7 @@ extern "C" { pub fn dlerror() -> *mut ::c_char; #[link_name = "_rtld_dlsym"] - pub fn dlsym( - handle: *mut ::c_void, - symbol: *const ::c_char, - ) -> *mut ::c_void; + pub fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void; #[link_name = "_rtld_dlclose"] pub fn dlclose(handle: *mut ::c_void) -> ::c_int; @@ -1341,25 +1243,14 @@ extern "C" { pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn usleep(secs: ::useconds_t) -> ::c_int; pub fn putenv(string: *mut c_char) -> ::c_int; - pub fn setlocale( - category: ::c_int, - locale: *const ::c_char, - ) -> *mut ::c_char; - - pub fn sigprocmask( - how: ::c_int, - set: *const sigset_t, - oldset: *mut sigset_t, - ) -> ::c_int; + pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; + + pub fn sigprocmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sigpending(set: *mut sigset_t) -> ::c_int; pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int; - pub fn fseeko( - stream: *mut ::FILE, - offset: ::off_t, - whence: ::c_int, - ) -> ::c_int; + pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; pub fn mkstemp(template: *mut ::c_char) -> ::c_int; @@ -1369,18 +1260,13 @@ extern "C" { pub fn closelog(); pub fn setlogmask(maskpri: ::c_int) -> ::c_int; pub fn syslog(priority: ::c_int, message: *const ::c_char, ...); - pub fn getline( - lineptr: *mut *mut c_char, - n: *mut size_t, - stream: *mut FILE, - ) -> ssize_t; + pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; } extern "C" { // stdlib.h - pub fn memalign(block_size: ::size_t, size_arg: ::size_t) - -> *mut ::c_void; + pub fn memalign(block_size: ::size_t, size_arg: ::size_t) -> *mut ::c_void; // ioLib.h pub fn getcwd(buf: *mut ::c_char, size: ::size_t) -> *mut ::c_char; @@ -1392,15 +1278,10 @@ extern "C" { pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> ::c_int; // pthread.h - pub fn pthread_mutexattr_destroy( - attr: *mut pthread_mutexattr_t, - ) -> ::c_int; + pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> ::c_int; // pthread.h - pub fn pthread_mutexattr_settype( - pAttr: *mut ::pthread_mutexattr_t, - pType: ::c_int, - ) -> ::c_int; + pub fn pthread_mutexattr_settype(pAttr: *mut ::pthread_mutexattr_t, pType: ::c_int) -> ::c_int; // pthread.h pub fn pthread_mutex_init( @@ -1418,31 +1299,20 @@ extern "C" { pub fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> ::c_int; // pthread.h - pub fn pthread_mutex_timedlock( - attr: *mut pthread_mutex_t, - spec: *const timespec, - ) -> ::c_int; + pub fn pthread_mutex_timedlock(attr: *mut pthread_mutex_t, spec: *const timespec) -> ::c_int; // pthread.h pub fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> ::c_int; // pthread.h - pub fn pthread_attr_setname( - pAttr: *mut ::pthread_attr_t, - name: *mut ::c_char, - ) -> ::c_int; + pub fn pthread_attr_setname(pAttr: *mut ::pthread_attr_t, name: *mut ::c_char) -> ::c_int; // pthread.h - pub fn pthread_attr_setstacksize( - attr: *mut ::pthread_attr_t, - stacksize: ::size_t, - ) -> ::c_int; + pub fn pthread_attr_setstacksize(attr: *mut ::pthread_attr_t, stacksize: ::size_t) -> ::c_int; // pthread.h - pub fn pthread_attr_getstacksize( - attr: *const ::pthread_attr_t, - size: *mut ::size_t, - ) -> ::c_int; + pub fn pthread_attr_getstacksize(attr: *const ::pthread_attr_t, size: *mut ::size_t) + -> ::c_int; // pthread.h pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int; @@ -1477,11 +1347,8 @@ extern "C" { pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; // dirent.h - pub fn readdir_r( - pDir: *mut ::DIR, - entry: *mut ::dirent, - result: *mut *mut ::dirent, - ) -> ::c_int; + pub fn readdir_r(pDir: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) + -> ::c_int; // dirent.h pub fn readdir(pDir: *mut ::DIR) -> *mut ::dirent; @@ -1497,9 +1364,7 @@ extern "C" { pub fn pthread_condattr_init(attr: *mut ::pthread_condattr_t) -> ::c_int; // pthread.h - pub fn pthread_condattr_destroy( - attr: *mut ::pthread_condattr_t, - ) -> ::c_int; + pub fn pthread_condattr_destroy(attr: *mut ::pthread_condattr_t) -> ::c_int; // pthread.h pub fn pthread_condattr_getclock( @@ -1529,20 +1394,14 @@ extern "C" { pub fn pthread_cond_broadcast(cond: *mut ::pthread_cond_t) -> ::c_int; // pthread.h - pub fn pthread_cond_wait( - cond: *mut ::pthread_cond_t, - mutex: *mut ::pthread_mutex_t, - ) -> ::c_int; + pub fn pthread_cond_wait(cond: *mut ::pthread_cond_t, mutex: *mut ::pthread_mutex_t) + -> ::c_int; // pthread.h - pub fn pthread_rwlockattr_init( - attr: *mut ::pthread_rwlockattr_t, - ) -> ::c_int; + pub fn pthread_rwlockattr_init(attr: *mut ::pthread_rwlockattr_t) -> ::c_int; // pthread.h - pub fn pthread_rwlockattr_destroy( - attr: *mut ::pthread_rwlockattr_t, - ) -> ::c_int; + pub fn pthread_rwlockattr_destroy(attr: *mut ::pthread_rwlockattr_t) -> ::c_int; // pthread.h pub fn pthread_rwlockattr_setmaxreaders( @@ -1596,10 +1455,7 @@ extern "C" { pub fn pthread_key_delete(key: ::pthread_key_t) -> ::c_int; // pthread.h - pub fn pthread_setspecific( - key: ::pthread_key_t, - value: *const ::c_void, - ) -> ::c_int; + pub fn pthread_setspecific(key: ::pthread_key_t, value: *const ::c_void) -> ::c_int; // pthread.h pub fn pthread_getspecific(key: ::pthread_key_t) -> *mut ::c_void; @@ -1612,37 +1468,22 @@ extern "C" { ) -> ::c_int; // pthread.h - pub fn pthread_attr_getname( - attr: *mut ::pthread_attr_t, - name: *mut *mut ::c_char, - ) -> ::c_int; + pub fn pthread_attr_getname(attr: *mut ::pthread_attr_t, name: *mut *mut ::c_char) -> ::c_int; // pthread.h - pub fn pthread_join( - thread: ::pthread_t, - status: *mut *mut ::c_void, - ) -> ::c_int; + pub fn pthread_join(thread: ::pthread_t, status: *mut *mut ::c_void) -> ::c_int; // pthread.h pub fn pthread_self() -> ::pthread_t; // clockLib.h - pub fn clock_gettime( - clock_id: ::clockid_t, - tp: *mut ::timespec, - ) -> ::c_int; + pub fn clock_gettime(clock_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; // clockLib.h - pub fn clock_settime( - clock_id: ::clockid_t, - tp: *const ::timespec, - ) -> ::c_int; + pub fn clock_settime(clock_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; // clockLib.h - pub fn clock_getres( - clock_id: ::clockid_t, - res: *mut ::timespec, - ) -> ::c_int; + pub fn clock_getres(clock_id: ::clockid_t, res: *mut ::timespec) -> ::c_int; // clockLib.h pub fn clock_nanosleep( @@ -1653,35 +1494,19 @@ extern "C" { ) -> ::c_int; // timerLib.h - pub fn nanosleep( - rqtp: *const ::timespec, - rmtp: *mut ::timespec, - ) -> ::c_int; + pub fn nanosleep(rqtp: *const ::timespec, rmtp: *mut ::timespec) -> ::c_int; // socket.h - pub fn accept( - s: ::c_int, - addr: *mut ::sockaddr, - addrlen: *mut ::socklen_t, - ) -> ::c_int; + pub fn accept(s: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t) -> ::c_int; // socket.h - pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) - -> ::c_int; + pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) -> ::c_int; // socket.h - pub fn connect( - s: ::c_int, - name: *const ::sockaddr, - namelen: ::socklen_t, - ) -> ::c_int; + pub fn connect(s: ::c_int, name: *const ::sockaddr, namelen: ::socklen_t) -> ::c_int; // socket.h - pub fn getpeername( - s: ::c_int, - name: *mut ::sockaddr, - namelen: *mut ::socklen_t, - ) -> ::c_int; + pub fn getpeername(s: ::c_int, name: *mut ::sockaddr, namelen: *mut ::socklen_t) -> ::c_int; // socket.h pub fn getsockname( @@ -1703,12 +1528,7 @@ extern "C" { pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int; // socket.h - pub fn recv( - s: ::c_int, - buf: *mut ::c_void, - bufLen: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; + pub fn recv(s: ::c_int, buf: *mut ::c_void, bufLen: ::size_t, flags: ::c_int) -> ::ssize_t; // socket.h pub fn recvfrom( @@ -1720,25 +1540,12 @@ extern "C" { pFromLen: *mut ::socklen_t, ) -> ::ssize_t; - pub fn recvmsg( - socket: ::c_int, - mp: *mut ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn recvmsg(socket: ::c_int, mp: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; // socket.h - pub fn send( - socket: ::c_int, - buf: *const ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; + pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; - pub fn sendmsg( - socket: ::c_int, - mp: *const ::msghdr, - flags: ::c_int, - ) -> ::ssize_t; + pub fn sendmsg(socket: ::c_int, mp: *const ::msghdr, flags: ::c_int) -> ::ssize_t; // socket.h pub fn sendto( @@ -1763,11 +1570,7 @@ extern "C" { pub fn shutdown(s: ::c_int, how: ::c_int) -> ::c_int; // socket.h - pub fn socket( - domain: ::c_int, - _type: ::c_int, - protocol: ::c_int, - ) -> ::c_int; + pub fn socket(domain: ::c_int, _type: ::c_int, protocol: ::c_int) -> ::c_int; // icotl.h pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; @@ -1785,16 +1588,11 @@ extern "C" { // ioLib.h or // unistd.h - pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) - -> ::ssize_t; + pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; // ioLib.h or // unistd.h - pub fn write( - fd: ::c_int, - buf: *const ::c_void, - count: ::size_t, - ) -> ::ssize_t; + pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t; // ioLib.h or // unistd.h @@ -1841,8 +1639,7 @@ extern "C" { pub fn getppid() -> pid_t; // wait.h - pub fn waitpid(pid: pid_t, status: *mut ::c_int, optons: ::c_int) - -> pid_t; + pub fn waitpid(pid: pid_t, status: *mut ::c_int, optons: ::c_int) -> pid_t; // unistd.h pub fn sysconf(attr: ::c_int) -> ::c_long; @@ -1862,20 +1659,13 @@ extern "C" { ) -> ::c_int; // stdlib.h - pub fn realpath( - fileName: *const ::c_char, - resolvedName: *mut ::c_char, - ) -> *mut ::c_char; + pub fn realpath(fileName: *const ::c_char, resolvedName: *mut ::c_char) -> *mut ::c_char; // unistd.h pub fn link(src: *const ::c_char, dst: *const ::c_char) -> ::c_int; // unistd.h - pub fn readlink( - path: *const ::c_char, - buf: *mut ::c_char, - bufsize: ::size_t, - ) -> ::ssize_t; + pub fn readlink(path: *const ::c_char, buf: *mut ::c_char, bufsize: ::size_t) -> ::ssize_t; // unistd.h pub fn symlink(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int; @@ -1940,11 +1730,7 @@ extern "C" { pub fn kill(__pid: pid_t, __signo: ::c_int) -> ::c_int; // signal.h for user - pub fn sigqueue( - __pid: pid_t, - __signo: ::c_int, - __value: ::sigval, - ) -> ::c_int; + pub fn sigqueue(__pid: pid_t, __signo: ::c_int, __value: ::sigval) -> ::c_int; // signal.h for user pub fn _sigqueue( @@ -1977,27 +1763,13 @@ extern "C" { ) -> RTP_ID; // ioLib.h - pub fn _realpath( - fileName: *const ::c_char, - resolvedName: *mut ::c_char, - ) -> *mut ::c_char; + pub fn _realpath(fileName: *const ::c_char, resolvedName: *mut ::c_char) -> *mut ::c_char; // pathLib.h - pub fn _pathIsAbsolute( - filepath: *const ::c_char, - pNameTail: *mut *const ::c_char, - ) -> BOOL; + pub fn _pathIsAbsolute(filepath: *const ::c_char, pNameTail: *mut *const ::c_char) -> BOOL; - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; + pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; // randomNumGen.h pub fn randBytes(buf: *mut c_uchar, length: c_int) -> c_int; @@ -2036,11 +1808,7 @@ extern "C" { abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; - pub fn mq_setattr( - mqd: ::mqd_t, - newattr: *const ::mq_attr, - oldattr: *mut ::mq_attr, - ) -> ::c_int; + pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; } //Dummy functions, these don't really exist in VxWorks. @@ -2067,12 +1835,7 @@ safe_f! { } } -pub fn pread( - _fd: ::c_int, - _buf: *mut ::c_void, - _count: ::size_t, - _offset: off64_t, -) -> ::ssize_t { +pub fn pread(_fd: ::c_int, _buf: *mut ::c_void, _count: ::size_t, _offset: off64_t) -> ::ssize_t { -1 } @@ -2084,16 +1847,10 @@ pub fn pwrite( ) -> ::ssize_t { -1 } -pub fn posix_memalign( - memptr: *mut *mut ::c_void, - align: ::size_t, - size: ::size_t, -) -> ::c_int { +pub fn posix_memalign(memptr: *mut *mut ::c_void, align: ::size_t, size: ::size_t) -> ::c_int { // check to see if align is a power of 2 and if align is a multiple // of sizeof(void *) - if (align & align - 1 != 0) - || (align as usize % size_of::<::size_t>() != 0) - { + if (align & align - 1 != 0) || (align as usize % size_of::<::size_t>() != 0) { return ::EINVAL; } diff --git a/vendor/libc/src/wasi.rs b/vendor/libc/src/wasi.rs index 9aef01a5f4..6aefff8a2f 100644 --- a/vendor/libc/src/wasi.rs +++ b/vendor/libc/src/wasi.rs @@ -358,11 +358,7 @@ extern "C" { pub fn write(fd: c_int, ptr: *const c_void, size: size_t) -> ssize_t; pub static mut environ: *mut *mut c_char; pub fn fopen(a: *const c_char, b: *const c_char) -> *mut FILE; - pub fn freopen( - a: *const c_char, - b: *const c_char, - f: *mut FILE, - ) -> *mut FILE; + pub fn freopen(a: *const c_char, b: *const c_char, f: *mut FILE) -> *mut FILE; pub fn fclose(f: *mut FILE) -> c_int; pub fn remove(a: *const c_char) -> c_int; pub fn rename(a: *const c_char, b: *const c_char) -> c_int; @@ -375,18 +371,8 @@ extern "C" { pub fn rewind(f: *mut FILE); pub fn fgetpos(f: *mut FILE, pos: *mut fpos_t) -> c_int; pub fn fsetpos(f: *mut FILE, pos: *const fpos_t) -> c_int; - pub fn fread( - buf: *mut c_void, - a: size_t, - b: size_t, - f: *mut FILE, - ) -> size_t; - pub fn fwrite( - buf: *const c_void, - a: size_t, - b: size_t, - f: *mut FILE, - ) -> size_t; + pub fn fread(buf: *mut c_void, a: size_t, b: size_t, f: *mut FILE) -> size_t; + pub fn fwrite(buf: *const c_void, a: size_t, b: size_t, f: *mut FILE) -> size_t; pub fn fgetc(f: *mut FILE) -> c_int; pub fn getc(f: *mut FILE) -> c_int; pub fn getchar() -> c_int; @@ -410,12 +396,7 @@ extern "C" { pub fn time(a: *mut time_t) -> time_t; pub fn difftime(a: time_t, b: time_t) -> c_double; pub fn mktime(a: *mut tm) -> time_t; - pub fn strftime( - a: *mut c_char, - b: size_t, - c: *const c_char, - d: *const tm, - ) -> size_t; + pub fn strftime(a: *mut c_char, b: size_t, c: *const c_char, d: *const tm) -> size_t; pub fn gmtime(a: *const time_t) -> *mut tm; pub fn gmtime_r(a: *const time_t, b: *mut tm) -> *mut tm; pub fn localtime(a: *const time_t) -> *mut tm; @@ -447,41 +428,19 @@ extern "C" { pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; - pub fn setvbuf( - stream: *mut FILE, - buffer: *mut c_char, - mode: c_int, - size: size_t, - ) -> c_int; + pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); - pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) - -> *mut c_char; + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn atoi(s: *const c_char) -> c_int; pub fn atof(s: *const c_char) -> c_double; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; - pub fn strtol( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_long; - pub fn strtoul( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_ulong; + pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; + pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; - pub fn strncpy( - dst: *mut c_char, - src: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; - pub fn strncat( - s: *mut c_char, - ct: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; @@ -494,11 +453,7 @@ extern "C" { pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; - pub fn strncasecmp( - s1: *const c_char, - s2: *const c_char, - n: size_t, - ) -> c_int; + pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; @@ -507,39 +462,17 @@ extern "C" { pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; - pub fn memcpy( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; - pub fn memmove( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; + pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; + pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; - pub fn fprintf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; - pub fn snprintf( - s: *mut ::c_char, - n: ::size_t, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; - pub fn fscanf( - stream: *mut ::FILE, - format: *const ::c_char, - ... - ) -> ::c_int; + pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn scanf(format: *const ::c_char, ...) -> ::c_int; - pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) - -> ::c_int; + pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; @@ -561,12 +494,7 @@ extern "C" { pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; - pub fn openat( - dirfd: ::c_int, - pathname: *const ::c_char, - flags: ::c_int, - ... - ) -> ::c_int; + pub fn openat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int, ...) -> ::c_int; pub fn fstatat( dirfd: ::c_int, pathname: *const ::c_char, @@ -580,11 +508,7 @@ extern "C" { newpath: *const ::c_char, flags: ::c_int, ) -> ::c_int; - pub fn mkdirat( - dirfd: ::c_int, - pathname: *const ::c_char, - mode: ::mode_t, - ) -> ::c_int; + pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn readlinkat( dirfd: ::c_int, pathname: *const ::c_char, @@ -602,20 +526,12 @@ extern "C" { newdirfd: ::c_int, linkpath: *const ::c_char, ) -> ::c_int; - pub fn unlinkat( - dirfd: ::c_int, - pathname: *const ::c_char, - flags: ::c_int, - ) -> ::c_int; + pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; pub fn close(fd: ::c_int) -> ::c_int; pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long; - pub fn getopt( - argc: ::c_int, - argv: *const *mut c_char, - optstr: *const c_char, - ) -> ::c_int; + pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn isatty(fd: ::c_int) -> ::c_int; pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int; pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; @@ -623,18 +539,8 @@ extern "C" { pub fn rmdir(path: *const c_char) -> ::c_int; pub fn sleep(secs: ::c_uint) -> ::c_uint; pub fn unlink(c: *const c_char) -> ::c_int; - pub fn pread( - fd: ::c_int, - buf: *mut ::c_void, - count: ::size_t, - offset: off_t, - ) -> ::ssize_t; - pub fn pwrite( - fd: ::c_int, - buf: *const ::c_void, - count: ::size_t, - offset: off_t, - ) -> ::ssize_t; + pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; + pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; @@ -651,37 +557,16 @@ extern "C" { pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn times(buf: *mut ::tms) -> ::clock_t; - pub fn strerror_r( - errnum: ::c_int, - buf: *mut c_char, - buflen: ::size_t, - ) -> ::c_int; + pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn usleep(secs: ::c_uint) -> ::c_int; - pub fn send( - socket: ::c_int, - buf: *const ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; - pub fn recv( - socket: ::c_int, - buf: *mut ::c_void, - len: ::size_t, - flags: ::c_int, - ) -> ::ssize_t; + pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; + pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; - pub fn setlocale( - category: ::c_int, - locale: *const ::c_char, - ) -> *mut ::c_char; + pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; pub fn localeconv() -> *mut lconv; - pub fn readlink( - path: *const c_char, - buf: *mut c_char, - bufsz: ::size_t, - ) -> ::ssize_t; + pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t; pub fn timegm(tm: *mut ::tm) -> time_t; @@ -689,24 +574,12 @@ extern "C" { pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; - pub fn fseeko( - stream: *mut ::FILE, - offset: ::off_t, - whence: ::c_int, - ) -> ::c_int; + pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; - pub fn posix_fallocate( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - ) -> ::c_int; + pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; - pub fn getline( - lineptr: *mut *mut c_char, - n: *mut size_t, - stream: *mut FILE, - ) -> ssize_t; + pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; pub fn faccessat( dirfd: ::c_int, @@ -714,34 +587,12 @@ extern "C" { mode: ::c_int, flags: ::c_int, ) -> ::c_int; - pub fn writev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; - pub fn readv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - ) -> ::ssize_t; - pub fn pwritev( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn preadv( - fd: ::c_int, - iov: *const ::iovec, - iovcnt: ::c_int, - offset: ::off_t, - ) -> ::ssize_t; - pub fn posix_fadvise( - fd: ::c_int, - offset: ::off_t, - len: ::off_t, - advise: ::c_int, - ) -> ::c_int; + pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; + pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; + pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) + -> ::ssize_t; + pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; + pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, @@ -750,27 +601,16 @@ extern "C" { flag: ::c_int, ) -> ::c_int; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; - pub fn memrchr( - cx: *const ::c_void, - c: ::c_int, - n: ::size_t, - ) -> *mut ::c_void; + pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); - pub fn newlocale( - mask: ::c_int, - locale: *const ::c_char, - base: ::locale_t, - ) -> ::locale_t; + pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn sched_yield() -> ::c_int; - pub fn __wasilibc_register_preopened_fd( - fd: c_int, - path: *const c_char, - ) -> c_int; + pub fn __wasilibc_register_preopened_fd(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_fd_renumber(fd: c_int, newfd: c_int) -> c_int; pub fn __wasilibc_unlinkat(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_rmdirat(fd: c_int, path: *const c_char) -> c_int; @@ -781,14 +621,8 @@ extern "C" { relative_path_len: usize, ) -> c_int; pub fn __wasilibc_tell(fd: c_int) -> ::off_t; - pub fn __wasilibc_nocwd___wasilibc_unlinkat( - dirfd: c_int, - path: *const c_char, - ) -> c_int; - pub fn __wasilibc_nocwd___wasilibc_rmdirat( - dirfd: c_int, - path: *const c_char, - ) -> c_int; + pub fn __wasilibc_nocwd___wasilibc_unlinkat(dirfd: c_int, path: *const c_char) -> c_int; + pub fn __wasilibc_nocwd___wasilibc_rmdirat(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd_linkat( olddirfd: c_int, oldpath: *const c_char, @@ -819,51 +653,30 @@ extern "C" { newdirfd: c_int, newpath: *const c_char, ) -> c_int; - pub fn __wasilibc_nocwd_openat_nomode( - dirfd: c_int, - path: *const c_char, - flags: c_int, - ) -> c_int; + pub fn __wasilibc_nocwd_openat_nomode(dirfd: c_int, path: *const c_char, flags: c_int) + -> c_int; pub fn __wasilibc_nocwd_fstatat( dirfd: c_int, path: *const c_char, buf: *mut stat, flags: c_int, ) -> c_int; - pub fn __wasilibc_nocwd_mkdirat_nomode( - dirfd: c_int, - path: *const c_char, - ) -> c_int; + pub fn __wasilibc_nocwd_mkdirat_nomode(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd_utimensat( dirfd: c_int, path: *const c_char, times: *const ::timespec, flags: c_int, ) -> c_int; - pub fn __wasilibc_nocwd_opendirat( - dirfd: c_int, - path: *const c_char, - ) -> *mut ::DIR; - pub fn __wasilibc_access( - pathname: *const c_char, - mode: c_int, - flags: c_int, - ) -> c_int; - pub fn __wasilibc_stat( - pathname: *const c_char, - buf: *mut stat, - flags: c_int, - ) -> c_int; + pub fn __wasilibc_nocwd_opendirat(dirfd: c_int, path: *const c_char) -> *mut ::DIR; + pub fn __wasilibc_access(pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; + pub fn __wasilibc_stat(pathname: *const c_char, buf: *mut stat, flags: c_int) -> c_int; pub fn __wasilibc_utimens( pathname: *const c_char, times: *const ::timespec, flags: c_int, ) -> c_int; - pub fn __wasilibc_link( - oldpath: *const c_char, - newpath: *const c_char, - flags: c_int, - ) -> c_int; + pub fn __wasilibc_link(oldpath: *const c_char, newpath: *const c_char, flags: c_int) -> c_int; pub fn __wasilibc_link_oldat( olddirfd: c_int, oldpath: *const c_char, diff --git a/vendor/libc/src/windows/gnu/mod.rs b/vendor/libc/src/windows/gnu/mod.rs index 3e906967f6..3e7d38b8e8 100644 --- a/vendor/libc/src/windows/gnu/mod.rs +++ b/vendor/libc/src/windows/gnu/mod.rs @@ -8,19 +8,11 @@ pub const STDERR_FILENO: ::c_int = 2; extern "C" { pub fn strcasecmp(s1: *const ::c_char, s2: *const ::c_char) -> ::c_int; - pub fn strncasecmp( - s1: *const ::c_char, - s2: *const ::c_char, - n: ::size_t, - ) -> ::c_int; + pub fn strncasecmp(s1: *const ::c_char, s2: *const ::c_char, n: ::size_t) -> ::c_int; // NOTE: For MSVC target, `wmemchr` is only a inline function in `` // header file. We cannot find a way to link to that symbol from Rust. - pub fn wmemchr( - cx: *const ::wchar_t, - c: ::wchar_t, - n: ::size_t, - ) -> *mut ::wchar_t; + pub fn wmemchr(cx: *const ::wchar_t, c: ::wchar_t, n: ::size_t) -> *mut ::wchar_t; } cfg_if! { diff --git a/vendor/libc/src/windows/mod.rs b/vendor/libc/src/windows/mod.rs index a2cd8574ab..f64aa2f971 100644 --- a/vendor/libc/src/windows/mod.rs +++ b/vendor/libc/src/windows/mod.rs @@ -274,44 +274,24 @@ extern "C" { pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - file: *mut FILE, - ) -> *mut FILE; + pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; - pub fn setvbuf( - stream: *mut FILE, - buffer: *mut c_char, - mode: c_int, - size: size_t, - ) -> c_int; + pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; - pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) - -> *mut c_char; + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; - pub fn fread( - ptr: *mut c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; - pub fn fwrite( - ptr: *const c_void, - size: size_t, - nobj: size_t, - stream: *mut FILE, - ) -> size_t; + pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; + pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); @@ -322,16 +302,8 @@ extern "C" { pub fn perror(s: *const c_char); pub fn atoi(s: *const c_char) -> c_int; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; - pub fn strtol( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_long; - pub fn strtoul( - s: *const c_char, - endp: *mut *mut c_char, - base: c_int, - ) -> c_ulong; + pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; + pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; @@ -344,17 +316,9 @@ extern "C" { pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; - pub fn strncpy( - dst: *mut c_char, - src: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; - pub fn strncat( - s: *mut c_char, - ct: *const c_char, - n: size_t, - ) -> *mut c_char; + pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; @@ -371,24 +335,12 @@ extern "C" { pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; - pub fn wcstombs( - dest: *mut c_char, - src: *const wchar_t, - n: size_t, - ) -> ::size_t; + pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; - pub fn memcpy( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; - pub fn memmove( - dest: *mut c_void, - src: *const c_void, - n: size_t, - ) -> *mut c_void; + pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; + pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn abs(i: c_int) -> c_int; @@ -447,37 +399,21 @@ extern "C" { #[link_name = "_execl"] pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexecl"] - pub fn wexecl(path: *const wchar_t, arg0: *const wchar_t, ...) - -> intptr_t; + pub fn wexecl(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execle"] pub fn execle(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexecle"] - pub fn wexecle( - path: *const wchar_t, - arg0: *const wchar_t, - ... - ) -> intptr_t; + pub fn wexecle(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execlp"] pub fn execlp(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexeclp"] - pub fn wexeclp( - path: *const wchar_t, - arg0: *const wchar_t, - ... - ) -> intptr_t; + pub fn wexeclp(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execlpe"] pub fn execlpe(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexeclpe"] - pub fn wexeclpe( - path: *const wchar_t, - arg0: *const wchar_t, - ... - ) -> intptr_t; + pub fn wexeclpe(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execv"] - pub fn execv( - prog: *const c_char, - argv: *const *const c_char, - ) -> ::intptr_t; + pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::intptr_t; #[link_name = "_execve"] pub fn execve( prog: *const c_char, @@ -493,10 +429,7 @@ extern "C" { envp: *const *const c_char, ) -> ::c_int; #[link_name = "_wexecv"] - pub fn wexecv( - prog: *const wchar_t, - argv: *const *const wchar_t, - ) -> ::intptr_t; + pub fn wexecv(prog: *const wchar_t, argv: *const *const wchar_t) -> ::intptr_t; #[link_name = "_wexecve"] pub fn wexecve( prog: *const wchar_t, @@ -504,10 +437,7 @@ extern "C" { envp: *const *const wchar_t, ) -> ::intptr_t; #[link_name = "_wexecvp"] - pub fn wexecvp( - c: *const wchar_t, - argv: *const *const wchar_t, - ) -> ::intptr_t; + pub fn wexecvp(c: *const wchar_t, argv: *const *const wchar_t) -> ::intptr_t; #[link_name = "_wexecvpe"] pub fn wexecvpe( c: *const wchar_t, @@ -523,17 +453,9 @@ extern "C" { #[link_name = "_lseek"] pub fn lseek(fd: ::c_int, offset: c_long, origin: ::c_int) -> c_long; #[link_name = "_lseeki64"] - pub fn lseek64( - fd: ::c_int, - offset: c_longlong, - origin: ::c_int, - ) -> c_longlong; + pub fn lseek64(fd: ::c_int, offset: c_longlong, origin: ::c_int) -> c_longlong; #[link_name = "_pipe"] - pub fn pipe( - fds: *mut ::c_int, - psize: ::c_uint, - textmode: ::c_int, - ) -> ::c_int; + pub fn pipe(fds: *mut ::c_int, psize: ::c_uint, textmode: ::c_int) -> ::c_int; #[link_name = "_read"] pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::c_uint) -> ::c_int; #[link_name = "_rmdir"] @@ -541,11 +463,7 @@ extern "C" { #[link_name = "_unlink"] pub fn unlink(c: *const c_char) -> ::c_int; #[link_name = "_write"] - pub fn write( - fd: ::c_int, - buf: *const ::c_void, - count: ::c_uint, - ) -> ::c_int; + pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::c_uint) -> ::c_int; #[link_name = "_commit"] pub fn commit(fd: ::c_int) -> ::c_int; #[link_name = "_get_osfhandle"] @@ -554,41 +472,18 @@ extern "C" { pub fn open_osfhandle(osfhandle: ::intptr_t, flags: ::c_int) -> ::c_int; pub fn setlocale(category: ::c_int, locale: *const c_char) -> *mut c_char; #[link_name = "_wsetlocale"] - pub fn wsetlocale( - category: ::c_int, - locale: *const wchar_t, - ) -> *mut wchar_t; + pub fn wsetlocale(category: ::c_int, locale: *const wchar_t) -> *mut wchar_t; #[link_name = "_aligned_malloc"] pub fn aligned_malloc(size: size_t, alignment: size_t) -> *mut c_void; } extern "system" { pub fn listen(s: SOCKET, backlog: ::c_int) -> ::c_int; - pub fn accept( - s: SOCKET, - addr: *mut ::sockaddr, - addrlen: *mut ::c_int, - ) -> SOCKET; - pub fn bind( - s: SOCKET, - name: *const ::sockaddr, - namelen: ::c_int, - ) -> ::c_int; - pub fn connect( - s: SOCKET, - name: *const ::sockaddr, - namelen: ::c_int, - ) -> ::c_int; - pub fn getpeername( - s: SOCKET, - name: *mut ::sockaddr, - nameln: *mut ::c_int, - ) -> ::c_int; - pub fn getsockname( - s: SOCKET, - name: *mut ::sockaddr, - nameln: *mut ::c_int, - ) -> ::c_int; + pub fn accept(s: SOCKET, addr: *mut ::sockaddr, addrlen: *mut ::c_int) -> SOCKET; + pub fn bind(s: SOCKET, name: *const ::sockaddr, namelen: ::c_int) -> ::c_int; + pub fn connect(s: SOCKET, name: *const ::sockaddr, namelen: ::c_int) -> ::c_int; + pub fn getpeername(s: SOCKET, name: *mut ::sockaddr, nameln: *mut ::c_int) -> ::c_int; + pub fn getsockname(s: SOCKET, name: *mut ::sockaddr, nameln: *mut ::c_int) -> ::c_int; pub fn getsockopt( s: SOCKET, level: ::c_int, @@ -619,11 +514,7 @@ extern "system" { optval: *const ::c_char, optlen: ::c_int, ) -> ::c_int; - pub fn socket( - af: ::c_int, - socket_type: ::c_int, - protocol: ::c_int, - ) -> SOCKET; + pub fn socket(af: ::c_int, socket_type: ::c_int, protocol: ::c_int) -> SOCKET; } cfg_if! { diff --git a/vendor/libc/src/windows/msvc.rs b/vendor/libc/src/windows/msvc.rs index 8f20deb5df..b4c98a8496 100644 --- a/vendor/libc/src/windows/msvc.rs +++ b/vendor/libc/src/windows/msvc.rs @@ -9,9 +9,5 @@ extern "C" { #[link_name = "_stricmp"] pub fn stricmp(s1: *const ::c_char, s2: *const ::c_char) -> ::c_int; #[link_name = "_strnicmp"] - pub fn strnicmp( - s1: *const ::c_char, - s2: *const ::c_char, - n: ::size_t, - ) -> ::c_int; + pub fn strnicmp(s1: *const ::c_char, s2: *const ::c_char, n: ::size_t) -> ::c_int; } diff --git a/vendor/libm/.cargo-checksum.json b/vendor/libm/.cargo-checksum.json new file mode 100644 index 0000000000..1b77bc77fd --- /dev/null +++ b/vendor/libm/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"dddcff92c74e853aad03e68ba32853caa5547e31ef17f7a72ee61816e4857d88","CONTRIBUTING.md":"9e8ed260af182c49c57e8e657e6b07648640a43e25e822fd0c75d3beddf5d4e0","Cargo.toml":"beb4d2c919d44be05314edb1b98940eebc8e8ace483029fa9f68cbc5749b4e51","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c986bcdb83103d4ddf58aeb7b5302359782e54dc4eea14a0cc27c62dcbd50729","README.md":"795376eae284995ff080671c37911e0143425885e329e487c5e9978cadd83321","azure-pipelines.yml":"43c33bf91e455322ace2037a33c318bb309ab7c6fadb78f11ff2faead19f1d36","build.rs":"d5e9e396c7b7387bdf7298cf805c59eeb2a9dae5354a4b42368be1e6f03e1291","ci/azure-install-rust.yml":"249e765f8c29cf8952b3c92698885536d37c87bf83070677afa7669519fa323f","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"5cf75ef952cc482076116ff8d40474b9105509700223d5269dbf077a72dae316","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"54811a30242a9c2ec218ec7328781e70753962792ae5b59ba1475ff2e3ce7601","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"4025b0e787ef05c92f6993d3df119adc1e86c24b0879a5e76647727505f0c6cf","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"87b30019c2eb7ce13aeeb00e453861a5274a0979ba29485221b3298d59ed9d01","ci/docker/i686-unknown-linux-gnu/Dockerfile":"4297d3e169c208e425b9af62100e5e5febb68924b5e47055e16c502c99b49f49","ci/docker/mips-unknown-linux-gnu/Dockerfile":"caa48dd56c8d3ec335600cc364e19bad4090b77521e35cb0fc544bec962e1a68","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"e965e72776de58150c686180f1aefe60c6851b27ed2c85880b2c01a77e128f64","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"1d4c9a45fa5578629902dfdfca1966f83673ba44cc5a566b528847b0a1ddd997","ci/docker/mipsel-unknown-linux-gnu/Dockerfile":"12945077fc0b846dcd3b9778fba397b07b6a1c3beeb5e1583934af028ff6e10a","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"77d53959b518bb6c0f08505d157b035fa63e51f323d63e743b8772aebdb6f15d","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"7b279ad6f05b806dc8df002babf1f3a5fded1ff6b66c7a4c07792881d4c3e70c","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"fee2d038252e31e77b69b735cd3724527dfe1f928f6dfd7a75e28d5303db0ead","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"1c4f3e9fdcfa58f8e406a6bdb377424f73e3bf030f3b962ea653fa3e3de25c23","ci/run-docker.sh":"d9c76e2acbaa2fb9d8646d394a4d097f967ea63373990a09c6ea1453d8345313","ci/run.sh":"292b5622bffda94a4b59e9dab847c8775e3d1d9b65d086b8280c0ee5bccf9111","src/lib.rs":"b3a187899179de261ba23b138969cdc2d3a1c7102e31858ce7ae55c294f59194","src/math/acos.rs":"97b929339071ffed2d2fb67aaa1bcb008386b06300582f4c35c26330b119c463","src/math/acosf.rs":"908325810aa4b6f667140de7b332dc14548542b1a95167d4f2b06d121be4a301","src/math/acosh.rs":"56dac8538e4350cd7cf001327c89f087b68abb2e6aaad58edba8a094b09f6b0f","src/math/acoshf.rs":"df5b0c4d8e37e64cf5ff2d8328b28bc35c78e84060ff769e64523ea9ff9065c1","src/math/asin.rs":"dceae678f9c74c9be4b36a7bbb5fe138662e4bf3d6224da01c450ab486945f0c","src/math/asinf.rs":"c4429db1742623154dc7421823f1ff65f7d3bed6d4a8dfb9ea0cacf4f8765dbc","src/math/asinh.rs":"e8fc94031015fddf35e9c26b94da9f6431ee17c81cd7bd37da8ffc98f7e0b32c","src/math/asinhf.rs":"8a0b8933a98a17617a66fef4c7b89eba645fdf05302000babf4a5a5f45328430","src/math/atan.rs":"a580e215ce20296ca36efe567b5f3caadf7d48d753d92f3a36069f566bc5293a","src/math/atan2.rs":"59708e1a010d3f3020419abfdacc0ed0f57530d25330b05c85fa93c252807fac","src/math/atan2f.rs":"13cfe5b1e1ea4f562867d983cc75f3875292f6eda8f8c3934bb1e1138e522114","src/math/atanf.rs":"412b8b6248d80da6453e04a0d42f05a22766b84e057e5ba4a8fab804ad449df1","src/math/atanh.rs":"5934dbd6b7395ca4f103ace7598da723a9270e1cf6b47e7f786debe4bb3651ff","src/math/atanhf.rs":"8ba4711dda19ef2dc33622be65c1483902868083543198c6bbd040d4026293de","src/math/cbrt.rs":"1ada8c0ce28f04cf2210641a3a3c888b8e89e132e64ff0a4c7b81e9fc8d24ea6","src/math/cbrtf.rs":"7a4177e996626b945f741fd182bb077e09cdaeda33fe742c6b6c71ce3642603d","src/math/ceil.rs":"7cc3c1a45c620939b1bda9b4a7bd1212663956e725cecb6abce196463e1841b9","src/math/ceilf.rs":"27a262e152285be8a62421d23951fb8d7dc8aed784592caefc43e3f05d09c88d","src/math/copysign.rs":"d80c880efaf0cdf2ce0a4d4f5a68dd6c36c88d46fa997ec8ac8604bfdb26fa33","src/math/copysignf.rs":"1547116071e68a42b1605eb2fc722db6466a34517dc96b92de1f29a274c3d8e3","src/math/cos.rs":"a66010c2364f30da987637786d508cf2ac5980e68be1891321a6f352ac04c948","src/math/cosf.rs":"73d7a9fa6afbc02add6819f119768bea7d55d88512fe5481c3459a35fe6d290b","src/math/cosh.rs":"bb588c9acb045d5ba642de543a743fe52fec49f208c775168e5967becfe707db","src/math/coshf.rs":"7daf35753d7e38aa109fe1cd4ef9839930c2b04336cf7e89d3dca3bc5df49653","src/math/erf.rs":"9c55fc6756ba816996f0b585e07ccfa4cd87575ad525cd30c4a968b30acffda3","src/math/erff.rs":"cb020e8bada9a54573a11fe3271750d73f14fed3092a881a9ceaf98fe32fd5a6","src/math/exp.rs":"6a5e7e4138ecd85ad6ffe53e1998ec6027d5299b16213544832edc5ba9de04ca","src/math/exp10.rs":"2deb037f88feac87a0e924b69dd496f0dd3b5d35f2a58e09d4c5166b207e517b","src/math/exp10f.rs":"6979464dfe3f4f2da1f9afc909646499c4bfaef15e10a039384750e2f1586fea","src/math/exp2.rs":"b97264684fbad0c6a413a4de26238f96a6a5cba70af1fb45857b00f83dab8bb1","src/math/exp2f.rs":"0053f3048e065799f2c0c04b57671a850f11f86eb7a476ffb089dbac78381574","src/math/expf.rs":"a55f5e25a19499d9ab6d4a9c42630c2528f69dbf965d9bca92e794958e6e1a20","src/math/expm1.rs":"72c97e3c90b197437ee7f2f1f07afc5e66b4de9ee5a9d5aa5cca038cd5371e71","src/math/expm1f.rs":"1b7a5f79037bc53f11b5a1b1a53e561883e3095c9db0b2faf2a334ed2dd509e4","src/math/expo2.rs":"2ae905e1fd8d475308e4ea3fd4607045041fe1770024e0b2a07aed00778e0ec7","src/math/fabs.rs":"90f99274001168b64444421480b7e1df27d60566a9f1f2f37e510f549860cb06","src/math/fabsf.rs":"afb23e4c6e14353d594247e7f1fbe9f0b205eafdbab98152138fdab6d197f9a2","src/math/fdim.rs":"e2b004cc6b0cbd8dac8b116bc6bb10914c8e3bf8f180fbfbe2f41c32f07d6c93","src/math/fdimf.rs":"d775fd720079c9e3a3202e20e910ba6868279da5a0b5dda713fffe8f8b5d8b4a","src/math/fenv.rs":"a8a835b195f880094bd9fb46762aef869e5f5925569ebbf71cceeafa2524a909","src/math/floor.rs":"ab122f713c882fec8db0939caf6082890acef8fd54189094b6424513e961a4e7","src/math/floorf.rs":"959349a094ee976a47f4cb9c25368098df57739190ff1d4350abe502479a3002","src/math/fma.rs":"0c4c519c7db91dc147ec625185c62e3a10280216ed75fa922442e6ce5a966b73","src/math/fmaf.rs":"ebc765aa52fc75d4ae29ee33574832eb1282faae882cccdccc52accd5615977c","src/math/fmax.rs":"15f3b99769ada1534369bf2be44bb8ee526ac4ddae322e0be976410bb7e90577","src/math/fmaxf.rs":"af19f98694335ecef1d046b125cc2a1629d9711b12c94c49100ccb60e3f14329","src/math/fmin.rs":"ed58ec8d403af6ebec8a0c0e8b9540d2ca6b0efb73ddd4317f4f71ea9da6a9c0","src/math/fminf.rs":"9cb486769b41f391ff6421d47cc01061be3ac0f628c71ec45586bcbe0b94c4cf","src/math/fmod.rs":"6dab52901947137392310250a42937514a165793f20a10ffa268902f9e0a5782","src/math/fmodf.rs":"17b1cf1e6c93b3af5d91266080d70e096f862f45dc599ebb8c041a0adf9abebc","src/math/frexp.rs":"28af70026922a8ab979744c7ad4d8faba6079c4743b7eeb6d14c983a982fbbcc","src/math/frexpf.rs":"2e2593ae8002ba420809ebfaf737ef001cdc912354be3d978a8c0cb930350d4d","src/math/hypot.rs":"8db4a26ff29fce64a3ca25ddc241822409e83a06ff76ff01aad61b489e34acee","src/math/hypotf.rs":"09df5a9cb7550d472640eff949e111ce4d275c7874de3dccf370fff28a0896ec","src/math/ilogb.rs":"813413bf6266d4fc40db9c5921af3cef4f892ba93e8f6d9efe62a449d1234532","src/math/ilogbf.rs":"dec462780f46682e16cfaa733238bed3b692729e951f53a44726100b6c73a716","src/math/j0.rs":"9572b6396c489927d332d0e717920e61ec0618e5e9c31f7eeeec70f5e4abab06","src/math/j0f.rs":"802c8254bded9b3afb6eea8b9af240038a5a4a5d811396729f69ca509e3e7d87","src/math/j1.rs":"97b1af1611fa3d110c2b349ee8e4176100132ea1391b619086b47ac063b81803","src/math/j1f.rs":"ccee0261db1cca175ac23a939f1dd41840b9f2caa131eb9cca5af2ca596735a9","src/math/jn.rs":"847d122334e5707ad9627146cddccc082a1f2f5bcd3e5ef54399013a7007ce88","src/math/jnf.rs":"4045076f7d1a1b89882ed60d4dd60a4cbbc66b85cfb90491378c8015effcc476","src/math/k_cos.rs":"5d2f24a11bf2ce52f3a80a76e320a752000548b77d47bb3d2aa759a85aa4f486","src/math/k_cosf.rs":"077b9dfd826df4d985434b48c383252f75e4b79a3a48e3e612750907a992d6a5","src/math/k_expo2.rs":"ae0017a84086b93708888a93d294216843d419562cdfd8dd17a49a09ec4e5e05","src/math/k_expo2f.rs":"285f3eee66504741c5e895d51b162bb21cfb88b34de49f9c19bd1c32326089b5","src/math/k_sin.rs":"7381988fa81f4788de6a4f6658b0057fdd535298a2997d63ef4b36cf4473e707","src/math/k_sinf.rs":"cd067bd2d917efdc8e89c02d8af6f67b0a4c92bbd01223fb695527050163d9ab","src/math/k_tan.rs":"a648fbb023afec2826ce10a2dd5d7ac51eaf9c3e9b8b24f4aa867d54203fe17c","src/math/k_tanf.rs":"53a886377aead553b2bba5e02a76d24f6d8c3df80fa0b80251bbfd98323c83fd","src/math/ldexp.rs":"ec4627b6b10d0bdba39cd3dc24cb4d72f6ed140db2da0b6447a0ebb159992ff2","src/math/ldexpf.rs":"45eb23a0f93fbfa5b6cccf1a42ce18f25499a71ab5a93342cb10966901d011da","src/math/lgamma.rs":"498552658cc8106d7754f85ae8dbc3306ac2f0a9f7eb5a796be70c5beac92c41","src/math/lgamma_r.rs":"7906850ab2dd77a27a19e11ec284d7ecf6bf275228854893807a4ba77ba31bed","src/math/lgammaf.rs":"457105f53a4c8717e8f5a117d261dcf94e222e83981337fe23602abe883fe3f7","src/math/lgammaf_r.rs":"7e2eae7cac9e7ea72cf3819de2b260c17a2cd51f2cbfd093c6ab2d60ea11925f","src/math/log.rs":"f381301cf6adde3af15b153c5f8923cf955ec3470d2d510614028a033f7def60","src/math/log10.rs":"b98abbb6255ef9ad3726876e62d75ecfdd6ca0d91374d3e1a4c7043460b6f64d","src/math/log10f.rs":"6724ab87137c1014f7d6387e0b51c8abff759a8e90619de7ce4f8ef58931e47b","src/math/log1p.rs":"bfca5da128fa12a862e7e0f0be27f9e04d1fe4a08f74016558ba91d49bcb125c","src/math/log1pf.rs":"8a2bc51ccc89933df450b9a8aa8e2e137db217550720543a3ce309ac82d2bee7","src/math/log2.rs":"252fc08c78b30e0a05ec305d5978a8badf1514d559d19cc9a200221c1014436e","src/math/log2f.rs":"a7705e2a55398674b4ac211f04f92941f42b93c33e24a6712de7403d85bdd50a","src/math/logf.rs":"6c042d2e5957b464ee5edfc2d14d5af9a8df817a170a67a0932ed4ca29010621","src/math/mod.rs":"e2d45e42a0ef4a45740d34467234a4de509481af53333cf269cbf2d88d5d097c","src/math/modf.rs":"d012ed5a708ef52b6d1313c22a46cadaf5764dde1220816e3df2f03a0fcc60ae","src/math/modff.rs":"f8f1e4c27a85d2cdb3c8e74439d59ef64aa543b948f22c23227d02d8388d61c2","src/math/pow.rs":"9c80d74aee21e4a82ced3d329381ee5fd2e8ebd80d4f938bd5ca1cf76640dac3","src/math/powf.rs":"70a8ef7924d39e0483a29916e83ccbbde8cae41fed3194a2836240e4c7b59916","src/math/rem_pio2.rs":"11799c886c07c752396f9bc9f54d03b30d342c5e920799d624854ae937287f0b","src/math/rem_pio2_large.rs":"a3a613e68609cf738f99d21e05dd5702f72405524b2f0f8ef7708f8baab1c3e1","src/math/rem_pio2f.rs":"66a914409c0a25820864c4be4039cb1544c106b6fa7b99ad8e160257d2d1c905","src/math/remquo.rs":"7e192e07956d10eb9739343f9bb19835fa0b47bad8618c7276891505a142872a","src/math/remquof.rs":"875ec1e3086dfe996e0e8923b0dd2ed5bfd30a9b98bedd1d163fd4ed338645c9","src/math/round.rs":"a8f541ace0d5cfa4f169d861fb971b82ef703071465e2aeacfac25799655bad7","src/math/roundf.rs":"a873f25f6d1707c559a1b0641e12f52c6e9a96e3c3aafc09bb92c0642b557424","src/math/scalbn.rs":"a96558226381e4491c7c8ca6c2566b268d4dfefb31bf2ba76b75dbfdbf9dfa01","src/math/scalbnf.rs":"770c0bd1edb1d8f45f287f8c806bb07378c7b575a280df7eb5521e639df60274","src/math/sin.rs":"0d84550a88c50f6bce6b23741d91ea86f0f650db4f286285384a8d80d1c290df","src/math/sincos.rs":"cc27cfcbcd5942f478e7e7e1a20fc3b273bad61393627d8a2adc4b3d41ba9b06","src/math/sincosf.rs":"cd93ce44f8f69636aeb33b1bb1fd17714a3e9bf4dd29f5e894f1a7f00ba3055e","src/math/sinf.rs":"57a7d233c5d6f400273ce50ea9a8a43384c3cccf5628c463c1bb7738d5940600","src/math/sinh.rs":"cc42172da41b926f0c2ca8a5ce007404d2a065b240c82032aaf896ae1e850ebb","src/math/sinhf.rs":"2fdb3863db18aa910b65f40392d0578b6234207b91e8b1c58c66410b99129e6b","src/math/sqrt.rs":"cc8ff45b78b52f22e40d5b45ea5582eb41f14bafadc291dc0e24b780611272ee","src/math/sqrtf.rs":"9580760c2d1c6ae76b55073da0fe56d0ebd398cb37385d4ec17f48ca7b0de73a","src/math/tan.rs":"49524a388958b54c5bb9360bcbe1ab2a8656c4e172f481969df51fce51eaeedd","src/math/tanf.rs":"9c416fe8e0e2e03cc61cfefc5d913e8523ce359909df499d2aa7f2cf79abbdca","src/math/tanh.rs":"8fc5edf4669ba3bf35f9773ebcccca5c19868628971581217a5f9f95811489fb","src/math/tanhf.rs":"a8367cbc5a43f6b00d77a07d2ef0a7e392ebfa46062a19b97901b7c993800dd4","src/math/tgamma.rs":"a6aabb8365410af6611f19f58694ccb74e82bb9ba9e1cdec7e1af787cfa44815","src/math/tgammaf.rs":"c95bd69957387533853532164f7e2251d2b04f5e775406b9e647226ae2bdd5ad","src/math/trunc.rs":"16cae799dc1c16c2eed92c9a194c89a6abc94adbd06e83630dafa7dad89abdec","src/math/truncf.rs":"2302a045af823ac076102d5d0c11f985253f0eb32265855d7ee0d56ded75930e"},"package":"7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"} \ No newline at end of file diff --git a/vendor/libm/CHANGELOG.md b/vendor/libm/CHANGELOG.md new file mode 100644 index 0000000000..28e27055df --- /dev/null +++ b/vendor/libm/CHANGELOG.md @@ -0,0 +1,97 @@ +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +... + +## [v0.1.4] - 2019-06-12 + +### Fixed +- Restored compatibility with Rust 1.31.0 + +## [v0.1.3] - 2019-05-14 + +### Added + +- minf +- fmin +- fmaxf +- fmax + +## [v0.1.2] - 2018-07-18 + +### Added + +- acosf +- asin +- asinf +- atan +- atan2 +- atan2f +- atanf +- cos +- cosf +- cosh +- coshf +- exp2 +- expm1 +- expm1f +- expo2 +- fmaf +- pow +- sin +- sinf +- sinh +- sinhf +- tan +- tanf +- tanh +- tanhf + +## [v0.1.1] - 2018-07-14 + +### Added + +- acos +- acosf +- asin +- asinf +- atanf +- cbrt +- cbrtf +- ceil +- ceilf +- cosf +- exp +- exp2 +- exp2f +- expm1 +- expm1f +- fdim +- fdimf +- floorf +- fma +- fmod +- log +- log2 +- log10 +- log10f +- log1p +- log1pf +- log2f +- roundf +- sinf +- tanf + +## v0.1.0 - 2018-07-13 + +- Initial release + +[Unreleased]: https://github.com/japaric/libm/compare/v0.1.4...HEAD +[v0.1.4]: https://github.com/japaric/libm/compare/0.1.3...v0.1.4 +[v0.1.3]: https://github.com/japaric/libm/compare/v0.1.2...0.1.3 +[v0.1.2]: https://github.com/japaric/libm/compare/v0.1.1...v0.1.2 +[v0.1.1]: https://github.com/japaric/libm/compare/v0.1.0...v0.1.1 diff --git a/vendor/libm/CONTRIBUTING.md b/vendor/libm/CONTRIBUTING.md new file mode 100644 index 0000000000..a7e817e13e --- /dev/null +++ b/vendor/libm/CONTRIBUTING.md @@ -0,0 +1,95 @@ +# How to contribute + +- Pick your favorite math function from the [issue tracker]. +- Look for the C implementation of the function in the [MUSL source code][src]. +- Copy paste the C code into a Rust file in the `src/math` directory and adjust + `src/math/mod.rs` accordingly. Also, uncomment the corresponding trait method + in `src/lib.rs`. +- Write some simple tests in your module (using `#[test]`) +- Run `cargo test` to make sure it works +- Run `cargo test --features musl-reference-tests` to compare your + implementation against musl's +- Send us a pull request! Make sure to run `cargo fmt` on your code before + sending the PR. Also include "closes #42" in the PR description to close the + corresponding issue. +- :tada: + +[issue tracker]: https://github.com/rust-lang-nursery/libm/issues +[src]: https://git.musl-libc.org/cgit/musl/tree/src/math +[`src/math/truncf.rs`]: https://github.com/rust-lang-nursery/libm/blob/master/src/math/truncf.rs + +Check [PR #65] for an example. + +[PR #65]: https://github.com/rust-lang-nursery/libm/pull/65 + +## Tips and tricks + +- *IMPORTANT* The code in this crate will end up being used in the `core` crate so it can **not** + have any external dependencies (other than `core` itself). + +- Only use relative imports within the `math` directory / module, e.g. `use self::fabs::fabs` or +`use super::k_cos`. Absolute imports from core are OK, e.g. `use core::u64`. + +- To reinterpret a float as an integer use the `to_bits` method. The MUSL code uses the + `GET_FLOAT_WORD` macro, or a union, to do this operation. + +- To reinterpret an integer as a float use the `f32::from_bits` constructor. The MUSL code uses the + `SET_FLOAT_WORD` macro, or a union, to do this operation. + +- You may use other methods from core like `f64::is_nan`, etc. as appropriate. + +- If you're implementing one of the private double-underscore functions, take a look at the + "source" name in the comment at the top for an idea for alternate naming. For example, `__sin` + was renamed to `k_sin` after the FreeBSD source code naming. Do `use` these private functions in + `mod.rs`. + +- You may encounter weird literals like `0x1p127f` in the MUSL code. These are hexadecimal floating + point literals. Rust (the language) doesn't support these kind of literals. The best way I have + found to deal with these literals is to turn them into their integer representation using the + [`hexf!`] macro and then turn them back into floats. See below: + +[`hexf!`]: https://crates.io/crates/hexf + +``` rust +// Step 1: write a program to convert the float into its integer representation +#[macro_use] +extern crate hexf; + +fn main() { + println!("{:#x}", hexf32!("0x1.0p127").to_bits()); +} +``` + +``` console +$ # Step 2: run the program +$ cargo run +0x7f000000 +``` + +``` rust +// Step 3: copy paste the output into libm +let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 12 +``` + +- Rust code panics on arithmetic overflows when not optimized. You may need to use the [`Wrapping`] + newtype to avoid this problem. + +[`Wrapping`]: https://doc.rust-lang.org/std/num/struct.Wrapping.html + +## Testing + +Normal tests can be executed with: + +``` +cargo test +``` + +If you'd like to run tests with randomized inputs that get compared against musl +itself, you'll need to be on a Linux system and then you can execute: + +``` +cargo test --features musl-reference-tests +``` + +Note that you may need to pass `--release` to Cargo if there are errors related +to integer overflow. diff --git a/vendor/blake2b_simd/Cargo.toml b/vendor/libm/Cargo.toml similarity index 53% rename from vendor/blake2b_simd/Cargo.toml rename to vendor/libm/Cargo.toml index 8dbb8308e8..802a7f0aa7 100644 --- a/vendor/blake2b_simd/Cargo.toml +++ b/vendor/libm/Cargo.toml @@ -12,25 +12,23 @@ [package] edition = "2018" -name = "blake2b_simd" -version = "0.5.10" -authors = ["Jack O'Connor"] -description = "a pure Rust BLAKE2b implementation with dynamic SIMD" -documentation = "https://docs.rs/blake2b_simd" -readme = "README.md" -license = "MIT" -repository = "https://github.com/oconnor663/blake2_simd" -[dependencies.arrayref] -version = "0.3.5" - -[dependencies.arrayvec] -version = "0.5.0" -default-features = false - -[dependencies.constant_time_eq] -version = "0.1.3" +name = "libm" +version = "0.1.4" +authors = ["Jorge Aparicio "] +description = "libm in pure Rust" +documentation = "https://docs.rs/libm" +keywords = ["libm", "math"] +categories = ["no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang-nursery/libm" +[dev-dependencies.no-panic] +version = "0.1.8" +[build-dependencies.rand] +version = "0.6.5" +optional = true [features] -default = ["std"] -std = [] -uninline_portable = [] +checked = [] +default = ["stable"] +musl-reference-tests = ["rand"] +stable = [] diff --git a/vendor/base64/LICENSE-APACHE b/vendor/libm/LICENSE-APACHE similarity index 100% rename from vendor/base64/LICENSE-APACHE rename to vendor/libm/LICENSE-APACHE diff --git a/vendor/socket2/LICENSE-MIT b/vendor/libm/LICENSE-MIT similarity index 96% rename from vendor/socket2/LICENSE-MIT rename to vendor/libm/LICENSE-MIT index 39e0ed6602..432fbea04d 100644 --- a/vendor/socket2/LICENSE-MIT +++ b/vendor/libm/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2014 Alex Crichton +Copyright (c) 2018 Jorge Aparicio Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/vendor/libm/README.md b/vendor/libm/README.md new file mode 100644 index 0000000000..3df5b65ea3 --- /dev/null +++ b/vendor/libm/README.md @@ -0,0 +1,58 @@ +# `libm` + +[![Build Status](https://dev.azure.com/rust-lang/libm/_apis/build/status/rust-lang-nursery.libm?branchName=master)](https://dev.azure.com/rust-lang/libm/_build/latest?definitionId=7&branchName=master) + +A port of [MUSL]'s libm to Rust. + +[MUSL]: https://www.musl-libc.org/ + +## Goals + +The short term goal of this library is to [enable math support (e.g. `sin`, `atan2`) for the +`wasm32-unknown-unknown` target][wasm] (cf. [rust-lang-nursery/compiler-builtins][pr]). The longer +term goal is to enable [math support in the `core` crate][core]. + +[wasm]: https://github.com/rust-lang-nursery/libm/milestone/1 +[pr]: https://github.com/rust-lang-nursery/compiler-builtins/pull/248 +[core]: https://github.com/rust-lang-nursery/libm/milestone/2 + +## Already usable + +This crate is [on crates.io] and can be used today in stable `#![no_std]` programs like this: + +[on crates.io]: https://crates.io/crates/libm + +``` rust +#![no_std] + +extern crate libm; + +use libm::F32Ext; // adds methods to `f32` + +fn foo(x: f32) { + let y = x.sqrt(); + let z = libm::truncf(x); +} +``` + +The API documentation can be found [here](https://docs.rs/libm). + +## Contributing + +Please check [CONTRIBUTING.md](CONTRIBUTING.md) + +## 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/libm/azure-pipelines.yml b/vendor/libm/azure-pipelines.yml new file mode 100644 index 0000000000..d8068e023b --- /dev/null +++ b/vendor/libm/azure-pipelines.yml @@ -0,0 +1,73 @@ +trigger: + - master + +jobs: + - job: Docker + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-install-rust.yml + - bash: rustup target add $TARGET + displayName: "add cross target" + - bash: rustup target add x86_64-unknown-linux-musl + displayName: "add musl target" + - bash: cargo generate-lockfile && ./ci/run-docker.sh $TARGET + displayName: "run tests" + strategy: + matrix: + aarch64: + TARGET: aarch64-unknown-linux-gnu + arm: + TARGET: arm-unknown-linux-gnueabi + armhf: + TARGET: arm-unknown-linux-gnueabihf + armv7: + TARGET: armv7-unknown-linux-gnueabihf + i686: + TARGET: i686-unknown-linux-gnu + mips: + TARGET: mips-unknown-linux-gnu + mips64: + TARGET: mips64-unknown-linux-gnuabi64 + mips64el: + TARGET: mips64el-unknown-linux-gnuabi64 + powerpc: + TARGET: powerpc-unknown-linux-gnu + powerpc64: + TARGET: powerpc64-unknown-linux-gnu + powerpc64le: + TARGET: powerpc64le-unknown-linux-gnu + x86_64: + TARGET: x86_64-unknown-linux-gnu + + - job: wasm + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-install-rust.yml + - script: rustup target add wasm32-unknown-unknown + displayName: "Install rust wasm target" + - script: cargo build --target wasm32-unknown-unknown + displayName: "Build for wasm" + - script: cargo build --target wasm32-unknown-unknown --no-default-features + displayName: "Build for wasm (no default features)" + variables: + TOOLCHAIN: nightly + + - job: rustfmt + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-install-rust.yml + - bash: rustup component add rustfmt + displayName: "install rustfmt" + - bash: cargo fmt --all -- --check + displayName: "check formatting" + + - job: compiler_builtins_works + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-install-rust.yml + - bash: cargo build -p cb + displayName: "Check compiler-builtins still probably builds" diff --git a/vendor/libm/build.rs b/vendor/libm/build.rs new file mode 100644 index 0000000000..9af6dec938 --- /dev/null +++ b/vendor/libm/build.rs @@ -0,0 +1,444 @@ +use std::env; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + + #[cfg(feature = "musl-reference-tests")] + musl_reference_tests::generate(); + + if !cfg!(feature = "checked") { + let lvl = env::var("OPT_LEVEL").unwrap(); + if lvl != "0" { + println!("cargo:rustc-cfg=assert_no_panic"); + } + } +} + +#[cfg(feature = "musl-reference-tests")] +mod musl_reference_tests { + use rand::seq::SliceRandom; + use rand::Rng; + use std::fs; + use std::process::Command; + + // Number of tests to generate for each function + const NTESTS: usize = 500; + + // These files are all internal functions or otherwise miscellaneous, not + // defining a function we want to test. + const IGNORED_FILES: &[&str] = &["fenv.rs"]; + + struct Function { + name: String, + args: Vec, + ret: Vec, + tests: Vec, + } + + enum Ty { + F32, + F64, + I32, + Bool, + } + + struct Test { + inputs: Vec, + outputs: Vec, + } + + pub fn generate() { + let files = fs::read_dir("src/math") + .unwrap() + .map(|f| f.unwrap().path()) + .collect::>(); + + let mut math = Vec::new(); + for file in files { + if IGNORED_FILES.iter().any(|f| file.ends_with(f)) { + continue; + } + + println!("generating musl reference tests in {:?}", file); + + let contents = fs::read_to_string(file).unwrap(); + let mut functions = contents.lines().filter(|f| f.starts_with("pub fn")); + while let Some(function_to_test) = functions.next() { + math.push(parse(function_to_test)); + } + } + + // Generate a bunch of random inputs for each function. This will + // attempt to generate a good set of uniform test cases for exercising + // all the various functionality. + generate_random_tests(&mut math, &mut rand::thread_rng()); + + // After we have all our inputs, use the x86_64-unknown-linux-musl + // target to generate the expected output. + generate_test_outputs(&mut math); + //panic!("Boo"); + // ... and now that we have both inputs and expected outputs, do a bunch + // of codegen to create the unit tests which we'll actually execute. + generate_unit_tests(&math); + } + + /// A "poor man's" parser for the signature of a function + fn parse(s: &str) -> Function { + let s = eat(s, "pub fn "); + let pos = s.find('(').unwrap(); + let name = &s[..pos]; + let s = &s[pos + 1..]; + let end = s.find(')').unwrap(); + let args = s[..end] + .split(',') + .map(|arg| { + let colon = arg.find(':').unwrap(); + parse_ty(arg[colon + 1..].trim()) + }) + .collect::>(); + let tail = &s[end + 1..]; + let tail = eat(tail, " -> "); + let ret = parse_retty(tail.replace("{", "").trim()); + + return Function { + name: name.to_string(), + args, + ret, + tests: Vec::new(), + }; + + fn parse_ty(s: &str) -> Ty { + match s { + "f32" => Ty::F32, + "f64" => Ty::F64, + "i32" => Ty::I32, + "bool" => Ty::Bool, + other => panic!("unknown type `{}`", other), + } + } + + fn parse_retty(s: &str) -> Vec { + match s { + "(f32, f32)" => vec![Ty::F32, Ty::F32], + "(f32, i32)" => vec![Ty::F32, Ty::I32], + "(f64, f64)" => vec![Ty::F64, Ty::F64], + "(f64, i32)" => vec![Ty::F64, Ty::I32], + other => vec![parse_ty(other)], + } + } + + fn eat<'a>(s: &'a str, prefix: &str) -> &'a str { + if s.starts_with(prefix) { + &s[prefix.len()..] + } else { + panic!("{:?} didn't start with {:?}", s, prefix) + } + } + } + + fn generate_random_tests(functions: &mut [Function], rng: &mut R) { + for function in functions { + for _ in 0..NTESTS { + function.tests.push(generate_test(function, rng)); + } + } + + fn generate_test(function: &Function, rng: &mut R) -> Test { + let mut inputs = function + .args + .iter() + .map(|ty| ty.gen_i64(rng)) + .collect::>(); + + // First argument to this function appears to be a number of + // iterations, so passing in massive random numbers causes it to + // take forever to execute, so make sure we're not running random + // math code until the heat death of the universe. + if function.name == "jn" || function.name == "jnf" { + inputs[0] &= 0xffff; + } + + Test { + inputs, + // zero output for now since we'll generate it later + outputs: vec![], + } + } + } + + impl Ty { + fn gen_i64(&self, r: &mut R) -> i64 { + use std::f32; + use std::f64; + + return match self { + Ty::F32 => { + if r.gen_range(0, 20) < 1 { + let i = *[f32::NAN, f32::INFINITY, f32::NEG_INFINITY] + .choose(r) + .unwrap(); + i.to_bits().into() + } else { + r.gen::().to_bits().into() + } + } + Ty::F64 => { + if r.gen_range(0, 20) < 1 { + let i = *[f64::NAN, f64::INFINITY, f64::NEG_INFINITY] + .choose(r) + .unwrap(); + i.to_bits() as i64 + } else { + r.gen::().to_bits() as i64 + } + } + Ty::I32 => { + if r.gen_range(0, 10) < 1 { + let i = *[i32::max_value(), 0, i32::min_value()].choose(r).unwrap(); + i.into() + } else { + r.gen::().into() + } + } + Ty::Bool => r.gen::() as i64, + }; + } + + fn libc_ty(&self) -> &'static str { + match self { + Ty::F32 => "f32", + Ty::F64 => "f64", + Ty::I32 => "i32", + Ty::Bool => "i32", + } + } + + fn libc_pty(&self) -> &'static str { + match self { + Ty::F32 => "*mut f32", + Ty::F64 => "*mut f64", + Ty::I32 => "*mut i32", + Ty::Bool => "*mut i32", + } + } + + fn default(&self) -> &'static str { + match self { + Ty::F32 => "0_f32", + Ty::F64 => "0_f64", + Ty::I32 => "0_i32", + Ty::Bool => "false", + } + } + + fn to_i64(&self) -> &'static str { + match self { + Ty::F32 => ".to_bits() as i64", + Ty::F64 => ".to_bits() as i64", + Ty::I32 => " as i64", + Ty::Bool => " as i64", + } + } + } + + fn generate_test_outputs(functions: &mut [Function]) { + let mut src = String::new(); + let dst = std::env::var("OUT_DIR").unwrap(); + + // Generate a program which will run all tests with all inputs in + // `functions`. This program will write all outputs to stdout (in a + // binary format). + src.push_str("use std::io::Write;"); + src.push_str("fn main() {"); + src.push_str("let mut result = Vec::new();"); + for function in functions.iter_mut() { + src.push_str("unsafe {"); + src.push_str("extern { fn "); + src.push_str(&function.name); + src.push_str("("); + + let (ret, retptr) = match function.name.as_str() { + "sincos" | "sincosf" => (None, &function.ret[..]), + _ => (Some(&function.ret[0]), &function.ret[1..]), + }; + for (i, arg) in function.args.iter().enumerate() { + src.push_str(&format!("arg{}: {},", i, arg.libc_ty())); + } + for (i, ret) in retptr.iter().enumerate() { + src.push_str(&format!("argret{}: {},", i, ret.libc_pty())); + } + src.push_str(")"); + if let Some(ty) = ret { + src.push_str(" -> "); + src.push_str(ty.libc_ty()); + } + src.push_str("; }"); + + src.push_str(&format!("static TESTS: &[[i64; {}]]", function.args.len())); + src.push_str(" = &["); + for test in function.tests.iter() { + src.push_str("["); + for val in test.inputs.iter() { + src.push_str(&val.to_string()); + src.push_str(","); + } + src.push_str("],"); + } + src.push_str("];"); + + src.push_str("for test in TESTS {"); + for (i, arg) in retptr.iter().enumerate() { + src.push_str(&format!("let mut argret{} = {};", i, arg.default())); + } + src.push_str("let output = "); + src.push_str(&function.name); + src.push_str("("); + for (i, arg) in function.args.iter().enumerate() { + src.push_str(&match arg { + Ty::F32 => format!("f32::from_bits(test[{}] as u32)", i), + Ty::F64 => format!("f64::from_bits(test[{}] as u64)", i), + Ty::I32 => format!("test[{}] as i32", i), + Ty::Bool => format!("test[{}] as i32", i), + }); + src.push_str(","); + } + for (i, _) in retptr.iter().enumerate() { + src.push_str(&format!("&mut argret{},", i)); + } + src.push_str(");"); + if let Some(ty) = &ret { + src.push_str(&format!("let output = output{};", ty.to_i64())); + src.push_str("result.extend_from_slice(&output.to_le_bytes());"); + } + + for (i, ret) in retptr.iter().enumerate() { + src.push_str(&format!( + "result.extend_from_slice(&(argret{}{}).to_le_bytes());", + i, + ret.to_i64(), + )); + } + src.push_str("}"); + + src.push_str("}"); + } + + src.push_str("std::io::stdout().write_all(&result).unwrap();"); + + src.push_str("}"); + + let path = format!("{}/gen.rs", dst); + fs::write(&path, src).unwrap(); + + // Make it somewhat pretty if something goes wrong + drop(Command::new("rustfmt").arg(&path).status()); + + // Compile and execute this tests for the musl target, assuming we're an + // x86_64 host effectively. + let status = Command::new("rustc") + .current_dir(&dst) + .arg(&path) + .arg("--target=x86_64-unknown-linux-musl") + .status() + .unwrap(); + assert!(status.success()); + let output = Command::new("./gen").current_dir(&dst).output().unwrap(); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + + // Map all the output bytes back to an `i64` and then shove it all into + // the expected results. + let mut results = output.stdout.chunks_exact(8).map(|buf| { + let mut exact = [0; 8]; + exact.copy_from_slice(buf); + i64::from_le_bytes(exact) + }); + + for f in functions.iter_mut() { + for test in f.tests.iter_mut() { + test.outputs = (0..f.ret.len()).map(|_| results.next().unwrap()).collect(); + } + } + assert!(results.next().is_none()); + } + + /// Codegens a file which has a ton of `#[test]` annotations for all the + /// tests that we generated above. + fn generate_unit_tests(functions: &[Function]) { + let mut src = String::new(); + let dst = std::env::var("OUT_DIR").unwrap(); + + for function in functions { + src.push_str("#[test]"); + src.push_str("fn "); + src.push_str(&function.name); + src.push_str("_matches_musl() {"); + src.push_str(&format!( + "static TESTS: &[([i64; {}], [i64; {}])]", + function.args.len(), + function.ret.len(), + )); + src.push_str(" = &["); + for test in function.tests.iter() { + src.push_str("(["); + for val in test.inputs.iter() { + src.push_str(&val.to_string()); + src.push_str(","); + } + src.push_str("],"); + src.push_str("["); + for val in test.outputs.iter() { + src.push_str(&val.to_string()); + src.push_str(","); + } + src.push_str("],"); + src.push_str("),"); + } + src.push_str("];"); + + src.push_str("for (test, expected) in TESTS {"); + src.push_str("let output = "); + src.push_str(&function.name); + src.push_str("("); + for (i, arg) in function.args.iter().enumerate() { + src.push_str(&match arg { + Ty::F32 => format!("f32::from_bits(test[{}] as u32)", i), + Ty::F64 => format!("f64::from_bits(test[{}] as u64)", i), + Ty::I32 => format!("test[{}] as i32", i), + Ty::Bool => format!("test[{}] as i32", i), + }); + src.push_str(","); + } + src.push_str(");"); + + for (i, ret) in function.ret.iter().enumerate() { + let get = if function.ret.len() == 1 { + String::new() + } else { + format!(".{}", i) + }; + src.push_str(&(match ret { + Ty::F32 => format!("if _eqf(output{}, f32::from_bits(expected[{}] as u32)).is_ok() {{ continue }}", get, i), + Ty::F64 => format!("if _eq(output{}, f64::from_bits(expected[{}] as u64)).is_ok() {{ continue }}", get, i), + Ty::I32 => format!("if output{} as i64 == expected[{}] {{ continue }}", get, i), + Ty::Bool => unreachable!(), + })); + } + + src.push_str( + r#" + panic!("INPUT: {:?} EXPECTED: {:?} ACTUAL {:?}", test, expected, output); + "#, + ); + src.push_str("}"); + + src.push_str("}"); + } + + let path = format!("{}/musl-tests.rs", dst); + fs::write(&path, src).unwrap(); + + // Try to make it somewhat pretty + drop(Command::new("rustfmt").arg(&path).status()); + } +} diff --git a/vendor/libm/ci/azure-install-rust.yml b/vendor/libm/ci/azure-install-rust.yml new file mode 100644 index 0000000000..c5a53122f8 --- /dev/null +++ b/vendor/libm/ci/azure-install-rust.yml @@ -0,0 +1,25 @@ +steps: + - bash: | + set -e + toolchain=$TOOLCHAIN + if [ "$toolchain" = "" ]; then + toolchain=stable + fi + if command -v rustup; then + rustup update $toolchain + rustup default $toolchain + else + curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $toolchain + echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin" + fi + displayName: Install rust (unix) + condition: ne( variables['Agent.OS'], 'Windows_NT' ) + + - bash: rustup update stable-$TOOLCHAIN && rustup default stable-$TOOLCHAIN + displayName: Install rust (windows) + condition: eq( variables['Agent.OS'], 'Windows_NT' ) + + - script: | + rustc -Vv + cargo -V + displayName: Query rust and cargo versions diff --git a/vendor/libm/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/aarch64-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..9e2559f4ab --- /dev/null +++ b/vendor/libm/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -0,0 +1,10 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ + qemu-user-static +ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-aarch64-static \ + QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/arm-unknown-linux-gnueabi/Dockerfile b/vendor/libm/ci/docker/arm-unknown-linux-gnueabi/Dockerfile new file mode 100644 index 0000000000..afab874bc2 --- /dev/null +++ b/vendor/libm/ci/docker/arm-unknown-linux-gnueabi/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-arm-linux-gnueabi libc6-dev-armel-cross qemu-user-static +ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_LINKER=arm-linux-gnueabi-gcc \ + CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_RUNNER=qemu-arm-static \ + QEMU_LD_PREFIX=/usr/arm-linux-gnueabi \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/vendor/libm/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile new file mode 100644 index 0000000000..3ed3602b0d --- /dev/null +++ b/vendor/libm/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static +ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \ + CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm-static \ + QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/vendor/libm/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile new file mode 100644 index 0000000000..6617af1558 --- /dev/null +++ b/vendor/libm/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static +ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \ + CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm-static \ + QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/i686-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/i686-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..5783e28e12 --- /dev/null +++ b/vendor/libm/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc-multilib libc6-dev ca-certificates diff --git a/vendor/libm/ci/docker/mips-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/mips-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..f47e8f5227 --- /dev/null +++ b/vendor/libm/ci/docker/mips-unknown-linux-gnu/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:18.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-mips-linux-gnu libc6-dev-mips-cross \ + binfmt-support qemu-user-static qemu-system-mips + +ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER=mips-linux-gnu-gcc \ + CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER=qemu-mips-static \ + QEMU_LD_PREFIX=/usr/mips-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/vendor/libm/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile new file mode 100644 index 0000000000..8fa77c7bd0 --- /dev/null +++ b/vendor/libm/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile @@ -0,0 +1,15 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-mips64-linux-gnuabi64 \ + libc6-dev \ + libc6-dev-mips64-cross \ + qemu-user-static \ + qemu-system-mips +ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_LINKER=mips64-linux-gnuabi64-gcc \ + CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64-static \ + CC_mips64_unknown_linux_gnuabi64=mips64-linux-gnuabi64-gcc \ + QEMU_LD_PREFIX=/usr/mips64-linux-gnuabi64 \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile b/vendor/libm/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile new file mode 100644 index 0000000000..c6611d9ac8 --- /dev/null +++ b/vendor/libm/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile @@ -0,0 +1,14 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-mips64el-linux-gnuabi64 \ + libc6-dev \ + libc6-dev-mips64el-cross \ + qemu-user-static +ENV CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_LINKER=mips64el-linux-gnuabi64-gcc \ + CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64el-static \ + CC_mips64el_unknown_linux_gnuabi64=mips64el-linux-gnuabi64-gcc \ + QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/mipsel-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/mipsel-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..0bc6956246 --- /dev/null +++ b/vendor/libm/ci/docker/mipsel-unknown-linux-gnu/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:18.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-mipsel-linux-gnu libc6-dev-mipsel-cross \ + binfmt-support qemu-user-static + +ENV CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_LINKER=mipsel-linux-gnu-gcc \ + CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_RUNNER=qemu-mipsel-static \ + QEMU_LD_PREFIX=/usr/mipsel-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/powerpc-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..2d39fef614 --- /dev/null +++ b/vendor/libm/ci/docker/powerpc-unknown-linux-gnu/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:18.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev qemu-user-static ca-certificates \ + gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \ + qemu-system-ppc + +ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER=powerpc-linux-gnu-gcc \ + CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc-static \ + QEMU_LD_PREFIX=/usr/powerpc-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..653cd35115 --- /dev/null +++ b/vendor/libm/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:18.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates \ + gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \ + binfmt-support qemu-user-static qemu-system-ppc + +ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER=powerpc64-linux-gnu-gcc \ + CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64-static \ + CC_powerpc64_unknown_linux_gnu=powerpc64-linux-gnu-gcc \ + QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..63ea9af9d2 --- /dev/null +++ b/vendor/libm/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:18.04 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev qemu-user-static ca-certificates \ + gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \ + qemu-system-ppc + +ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER=powerpc64le-linux-gnu-gcc \ + CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64le-static \ + QEMU_CPU=POWER8 \ + QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \ + RUST_TEST_THREADS=1 diff --git a/vendor/libm/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/vendor/libm/ci/docker/x86_64-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..98000f4eb8 --- /dev/null +++ b/vendor/libm/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:18.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc libc6-dev ca-certificates diff --git a/vendor/libm/ci/run-docker.sh b/vendor/libm/ci/run-docker.sh new file mode 100755 index 0000000000..e7b80c719e --- /dev/null +++ b/vendor/libm/ci/run-docker.sh @@ -0,0 +1,37 @@ +# Small script to run tests for a target (or all targets) inside all the +# respective docker images. + +set -ex + +run() { + local target=$1 + + echo $target + + # This directory needs to exist before calling docker, otherwise docker will create it but it + # will be owned by root + mkdir -p target + + docker build -t $target ci/docker/$target + docker run \ + --rm \ + --user $(id -u):$(id -g) \ + -e CARGO_HOME=/cargo \ + -e CARGO_TARGET_DIR=/target \ + -v $(dirname $(dirname `which cargo`)):/cargo \ + -v `pwd`/target:/target \ + -v `pwd`:/checkout:ro \ + -v `rustc --print sysroot`:/rust:ro \ + --init \ + -w /checkout \ + $target \ + sh -c "HOME=/tmp PATH=\$PATH:/rust/bin exec ci/run.sh $target" +} + +if [ -z "$1" ]; then + for d in `ls ci/docker/`; do + run $d + done +else + run $1 +fi diff --git a/vendor/libm/ci/run.sh b/vendor/libm/ci/run.sh new file mode 100755 index 0000000000..42c2416455 --- /dev/null +++ b/vendor/libm/ci/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -ex +TARGET=$1 + +cargo test --target $TARGET +cargo test --target $TARGET --release + +cargo test --features 'checked musl-reference-tests' --target $TARGET + +cargo test --features 'checked musl-reference-tests' --target $TARGET --release diff --git a/vendor/libm/src/lib.rs b/vendor/libm/src/lib.rs new file mode 100644 index 0000000000..a47883d81b --- /dev/null +++ b/vendor/libm/src/lib.rs @@ -0,0 +1,642 @@ +//! libm in pure Rust +//! +//! # Usage +//! +//! You can use this crate in two ways: +//! +//! - By directly using its free functions, e.g. `libm::powf`. +//! +//! - By importing the `F32Ext` and / or `F64Ext` extension traits to add methods like `powf` to the +//! `f32` and `f64` types. Then you'll be able to invoke math functions as methods, e.g. `x.sqrt()`. + +#![deny(warnings)] +#![no_std] +#![cfg_attr( + all(target_arch = "wasm32", not(feature = "stable")), + feature(core_intrinsics) +)] + +mod math; + +use core::{f32, f64}; + +pub use self::math::*; + +/// Approximate equality with 1 ULP of tolerance +#[doc(hidden)] +#[inline] +pub fn _eqf(a: f32, b: f32) -> Result<(), u32> { + if a.is_nan() && b.is_nan() { + Ok(()) + } else { + let err = (a.to_bits() as i32).wrapping_sub(b.to_bits() as i32).abs(); + + if err <= 1 { + Ok(()) + } else { + Err(err as u32) + } + } +} + +#[doc(hidden)] +#[inline] +pub fn _eq(a: f64, b: f64) -> Result<(), u64> { + if a.is_nan() && b.is_nan() { + Ok(()) + } else { + let err = (a.to_bits() as i64).wrapping_sub(b.to_bits() as i64).abs(); + + if err <= 1 { + Ok(()) + } else { + Err(err as u64) + } + } +} + +/// Math support for `f32` +/// +/// This trait is sealed and cannot be implemented outside of `libm`. +pub trait F32Ext: private::Sealed + Sized { + fn floor(self) -> Self; + + fn ceil(self) -> Self; + + fn round(self) -> Self; + + fn trunc(self) -> Self; + + fn fdim(self, rhs: Self) -> Self; + + fn fract(self) -> Self; + + fn abs(self) -> Self; + + // NOTE depends on unstable intrinsics::copysignf32 + // fn signum(self) -> Self; + + fn mul_add(self, a: Self, b: Self) -> Self; + + fn div_euc(self, rhs: Self) -> Self; + + fn mod_euc(self, rhs: Self) -> Self; + + // NOTE depends on unstable intrinsics::powif32 + // fn powi(self, n: i32) -> Self; + + fn powf(self, n: Self) -> Self; + + fn sqrt(self) -> Self; + + fn exp(self) -> Self; + + fn exp2(self) -> Self; + + fn ln(self) -> Self; + + fn log(self, base: Self) -> Self; + + fn log2(self) -> Self; + + fn log10(self) -> Self; + + fn cbrt(self) -> Self; + + fn hypot(self, other: Self) -> Self; + + fn sin(self) -> Self; + + fn cos(self) -> Self; + + fn tan(self) -> Self; + + fn asin(self) -> Self; + + fn acos(self) -> Self; + + fn atan(self) -> Self; + + fn atan2(self, other: Self) -> Self; + + fn sin_cos(self) -> (Self, Self); + + fn exp_m1(self) -> Self; + + fn ln_1p(self) -> Self; + + fn sinh(self) -> Self; + + fn cosh(self) -> Self; + + fn tanh(self) -> Self; + + fn asinh(self) -> Self; + + fn acosh(self) -> Self; + + fn atanh(self) -> Self; + + fn min(self, other: Self) -> Self; + + fn max(self, other: Self) -> Self; +} + +impl F32Ext for f32 { + #[inline] + fn floor(self) -> Self { + floorf(self) + } + + #[inline] + fn ceil(self) -> Self { + ceilf(self) + } + + #[inline] + fn round(self) -> Self { + roundf(self) + } + + #[inline] + fn trunc(self) -> Self { + truncf(self) + } + + #[inline] + fn fdim(self, rhs: Self) -> Self { + fdimf(self, rhs) + } + + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } + + #[inline] + fn abs(self) -> Self { + fabsf(self) + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + fmaf(self, a, b) + } + + #[inline] + fn div_euc(self, rhs: Self) -> Self { + let q = (self / rhs).trunc(); + if self % rhs < 0.0 { + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn mod_euc(self, rhs: f32) -> f32 { + let r = self % rhs; + if r < 0.0 { + r + rhs.abs() + } else { + r + } + } + + #[inline] + fn powf(self, n: Self) -> Self { + powf(self, n) + } + + #[inline] + fn sqrt(self) -> Self { + sqrtf(self) + } + + #[inline] + fn exp(self) -> Self { + expf(self) + } + + #[inline] + fn exp2(self) -> Self { + exp2f(self) + } + + #[inline] + fn ln(self) -> Self { + logf(self) + } + + #[inline] + fn log(self, base: Self) -> Self { + self.ln() / base.ln() + } + + #[inline] + fn log2(self) -> Self { + log2f(self) + } + + #[inline] + fn log10(self) -> Self { + log10f(self) + } + + #[inline] + fn cbrt(self) -> Self { + cbrtf(self) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + hypotf(self, other) + } + + #[inline] + fn sin(self) -> Self { + sinf(self) + } + + #[inline] + fn cos(self) -> Self { + cosf(self) + } + + #[inline] + fn tan(self) -> Self { + tanf(self) + } + + #[inline] + fn asin(self) -> Self { + asinf(self) + } + + #[inline] + fn acos(self) -> Self { + acosf(self) + } + + #[inline] + fn atan(self) -> Self { + atanf(self) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + atan2f(self, other) + } + + #[inline] + fn sin_cos(self) -> (Self, Self) { + sincosf(self) + } + + #[inline] + fn exp_m1(self) -> Self { + expm1f(self) + } + + #[inline] + fn ln_1p(self) -> Self { + log1pf(self) + } + + #[inline] + fn sinh(self) -> Self { + sinhf(self) + } + + #[inline] + fn cosh(self) -> Self { + coshf(self) + } + + #[inline] + fn tanh(self) -> Self { + tanhf(self) + } + + #[inline] + fn asinh(self) -> Self { + asinhf(self) + } + + #[inline] + fn acosh(self) -> Self { + acoshf(self) + } + + #[inline] + fn atanh(self) -> Self { + atanhf(self) + } + + #[inline] + fn min(self, other: Self) -> Self { + fminf(self, other) + } + + #[inline] + fn max(self, other: Self) -> Self { + fmaxf(self, other) + } +} + +/// Math support for `f64` +/// +/// This trait is sealed and cannot be implemented outside of `libm`. +pub trait F64Ext: private::Sealed + Sized { + fn floor(self) -> Self; + + fn ceil(self) -> Self; + + fn round(self) -> Self; + + fn trunc(self) -> Self; + + fn fdim(self, rhs: Self) -> Self; + + fn fract(self) -> Self; + + fn abs(self) -> Self; + + // NOTE depends on unstable intrinsics::copysignf64 + // fn signum(self) -> Self; + + fn mul_add(self, a: Self, b: Self) -> Self; + + fn div_euc(self, rhs: Self) -> Self; + + fn mod_euc(self, rhs: Self) -> Self; + + // NOTE depends on unstable intrinsics::powif64 + // fn powi(self, n: i32) -> Self; + + fn powf(self, n: Self) -> Self; + + fn sqrt(self) -> Self; + + fn exp(self) -> Self; + + fn exp2(self) -> Self; + + fn ln(self) -> Self; + + fn log(self, base: Self) -> Self; + + fn log2(self) -> Self; + + fn log10(self) -> Self; + + fn cbrt(self) -> Self; + + fn hypot(self, other: Self) -> Self; + + fn sin(self) -> Self; + + fn cos(self) -> Self; + + fn tan(self) -> Self; + + fn asin(self) -> Self; + + fn acos(self) -> Self; + + fn atan(self) -> Self; + + fn atan2(self, other: Self) -> Self; + + fn sin_cos(self) -> (Self, Self); + + fn exp_m1(self) -> Self; + + fn ln_1p(self) -> Self; + + fn sinh(self) -> Self; + + fn cosh(self) -> Self; + + fn tanh(self) -> Self; + + fn asinh(self) -> Self; + + fn acosh(self) -> Self; + + fn atanh(self) -> Self; + + fn min(self, other: Self) -> Self; + + fn max(self, other: Self) -> Self; +} + +impl F64Ext for f64 { + #[inline] + fn floor(self) -> Self { + floor(self) + } + + #[inline] + fn ceil(self) -> Self { + ceil(self) + } + + #[inline] + fn round(self) -> Self { + round(self) + } + + #[inline] + fn trunc(self) -> Self { + trunc(self) + } + + #[inline] + fn fdim(self, rhs: Self) -> Self { + fdim(self, rhs) + } + + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } + + #[inline] + fn abs(self) -> Self { + fabs(self) + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + fma(self, a, b) + } + + #[inline] + fn div_euc(self, rhs: Self) -> Self { + let q = (self / rhs).trunc(); + if self % rhs < 0.0 { + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn mod_euc(self, rhs: f64) -> f64 { + let r = self % rhs; + if r < 0.0 { + r + rhs.abs() + } else { + r + } + } + + #[inline] + fn powf(self, n: Self) -> Self { + pow(self, n) + } + + #[inline] + fn sqrt(self) -> Self { + sqrt(self) + } + + #[inline] + fn exp(self) -> Self { + exp(self) + } + + #[inline] + fn exp2(self) -> Self { + exp2(self) + } + + #[inline] + fn ln(self) -> Self { + log(self) + } + + #[inline] + fn log(self, base: Self) -> Self { + self.ln() / base.ln() + } + + #[inline] + fn log2(self) -> Self { + log2(self) + } + + #[inline] + fn log10(self) -> Self { + log10(self) + } + + #[inline] + fn cbrt(self) -> Self { + cbrt(self) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + hypot(self, other) + } + + #[inline] + fn sin(self) -> Self { + sin(self) + } + + #[inline] + fn cos(self) -> Self { + cos(self) + } + + #[inline] + fn tan(self) -> Self { + tan(self) + } + + #[inline] + fn asin(self) -> Self { + asin(self) + } + + #[inline] + fn acos(self) -> Self { + acos(self) + } + + #[inline] + fn atan(self) -> Self { + atan(self) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + atan2(self, other) + } + + #[inline] + fn sin_cos(self) -> (Self, Self) { + sincos(self) + } + + #[inline] + fn exp_m1(self) -> Self { + expm1(self) + } + + #[inline] + fn ln_1p(self) -> Self { + log1p(self) + } + + #[inline] + fn sinh(self) -> Self { + sinh(self) + } + + #[inline] + fn cosh(self) -> Self { + cosh(self) + } + + #[inline] + fn tanh(self) -> Self { + tanh(self) + } + + #[inline] + fn asinh(self) -> Self { + asinh(self) + } + + #[inline] + fn acosh(self) -> Self { + acosh(self) + } + + #[inline] + fn atanh(self) -> Self { + atanh(self) + } + + #[inline] + fn min(self, other: Self) -> Self { + fmin(self, other) + } + + #[inline] + fn max(self, other: Self) -> Self { + fmax(self, other) + } +} + +mod private { + pub trait Sealed {} + + impl Sealed for f32 {} + impl Sealed for f64 {} +} + +#[cfg(all(test, feature = "musl-reference-tests"))] +include!(concat!(env!("OUT_DIR"), "/musl-tests.rs")); diff --git a/vendor/libm/src/math/acos.rs b/vendor/libm/src/math/acos.rs new file mode 100644 index 0000000000..d5e1f6865a --- /dev/null +++ b/vendor/libm/src/math/acos.rs @@ -0,0 +1,114 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_acos.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* acos(x) + * Method : + * acos(x) = pi/2 - asin(x) + * acos(-x) = pi/2 + asin(x) + * For |x|<=0.5 + * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) + * For x>0.5 + * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) + * = 2asin(sqrt((1-x)/2)) + * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) + * = 2f + (2c + 2s*z*R(z)) + * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term + * for f so that f+c ~ sqrt(z). + * For x<-0.5 + * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) + * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + * Function needed: sqrt + */ + +use super::sqrt; + +const PIO2_HI: f64 = 1.57079632679489655800e+00; /* 0x3FF921FB, 0x54442D18 */ +const PIO2_LO: f64 = 6.12323399573676603587e-17; /* 0x3C91A626, 0x33145C07 */ +const PS0: f64 = 1.66666666666666657415e-01; /* 0x3FC55555, 0x55555555 */ +const PS1: f64 = -3.25565818622400915405e-01; /* 0xBFD4D612, 0x03EB6F7D */ +const PS2: f64 = 2.01212532134862925881e-01; /* 0x3FC9C155, 0x0E884455 */ +const PS3: f64 = -4.00555345006794114027e-02; /* 0xBFA48228, 0xB5688F3B */ +const PS4: f64 = 7.91534994289814532176e-04; /* 0x3F49EFE0, 0x7501B288 */ +const PS5: f64 = 3.47933107596021167570e-05; /* 0x3F023DE1, 0x0DFDF709 */ +const QS1: f64 = -2.40339491173441421878e+00; /* 0xC0033A27, 0x1C8A2D4B */ +const QS2: f64 = 2.02094576023350569471e+00; /* 0x40002AE5, 0x9C598AC8 */ +const QS3: f64 = -6.88283971605453293030e-01; /* 0xBFE6066C, 0x1B8D0159 */ +const QS4: f64 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +#[inline] +fn r(z: f64) -> f64 { + let p: f64 = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5))))); + let q: f64 = 1.0 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4))); + p / q +} + +/// Arccosine (f64) +/// +/// Computes the inverse cosine (arc cosine) of the input value. +/// Arguments must be in the range -1 to 1. +/// Returns values in radians, in the range of 0 to pi. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn acos(x: f64) -> f64 { + let x1p_120f = f64::from_bits(0x3870000000000000); // 0x1p-120 === 2 ^ -120 + let z: f64; + let w: f64; + let s: f64; + let c: f64; + let df: f64; + let hx: u32; + let ix: u32; + + hx = (x.to_bits() >> 32) as u32; + ix = hx & 0x7fffffff; + /* |x| >= 1 or nan */ + if ix >= 0x3ff00000 { + let lx: u32 = x.to_bits() as u32; + + if ((ix - 0x3ff00000) | lx) == 0 { + /* acos(1)=0, acos(-1)=pi */ + if (hx >> 31) != 0 { + return 2. * PIO2_HI + x1p_120f; + } + return 0.; + } + return 0. / (x - x); + } + /* |x| < 0.5 */ + if ix < 0x3fe00000 { + if ix <= 0x3c600000 { + /* |x| < 2**-57 */ + return PIO2_HI + x1p_120f; + } + return PIO2_HI - (x - (PIO2_LO - x * r(x * x))); + } + /* x < -0.5 */ + if (hx >> 31) != 0 { + z = (1.0 + x) * 0.5; + s = sqrt(z); + w = r(z) * s - PIO2_LO; + return 2. * (PIO2_HI - (s + w)); + } + /* x > 0.5 */ + z = (1.0 - x) * 0.5; + s = sqrt(z); + // Set the low 4 bytes to zero + df = f64::from_bits(s.to_bits() & 0xff_ff_ff_ff_00_00_00_00); + + c = (z - df * df) / (s + df); + w = r(z) * s + c; + 2. * (df + w) +} diff --git a/vendor/libm/src/math/acosf.rs b/vendor/libm/src/math/acosf.rs new file mode 100644 index 0000000000..d0598e8119 --- /dev/null +++ b/vendor/libm/src/math/acosf.rs @@ -0,0 +1,81 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_acosf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::sqrtf::sqrtf; + +const PIO2_HI: f32 = 1.5707962513e+00; /* 0x3fc90fda */ +const PIO2_LO: f32 = 7.5497894159e-08; /* 0x33a22168 */ +const P_S0: f32 = 1.6666586697e-01; +const P_S1: f32 = -4.2743422091e-02; +const P_S2: f32 = -8.6563630030e-03; +const Q_S1: f32 = -7.0662963390e-01; + +#[inline] +fn r(z: f32) -> f32 { + let p = z * (P_S0 + z * (P_S1 + z * P_S2)); + let q = 1. + z * Q_S1; + p / q +} + +/// Arccosine (f32) +/// +/// Computes the inverse cosine (arc cosine) of the input value. +/// Arguments must be in the range -1 to 1. +/// Returns values in radians, in the range of 0 to pi. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn acosf(x: f32) -> f32 { + let x1p_120 = f32::from_bits(0x03800000); // 0x1p-120 === 2 ^ (-120) + + let z: f32; + let w: f32; + let s: f32; + + let mut hx = x.to_bits(); + let ix = hx & 0x7fffffff; + /* |x| >= 1 or nan */ + if ix >= 0x3f800000 { + if ix == 0x3f800000 { + if (hx >> 31) != 0 { + return 2. * PIO2_HI + x1p_120; + } + return 0.; + } + return 0. / (x - x); + } + /* |x| < 0.5 */ + if ix < 0x3f000000 { + if ix <= 0x32800000 { + /* |x| < 2**-26 */ + return PIO2_HI + x1p_120; + } + return PIO2_HI - (x - (PIO2_LO - x * r(x * x))); + } + /* x < -0.5 */ + if (hx >> 31) != 0 { + z = (1. + x) * 0.5; + s = sqrtf(z); + w = r(z) * s - PIO2_LO; + return 2. * (PIO2_HI - (s + w)); + } + /* x > 0.5 */ + z = (1. - x) * 0.5; + s = sqrtf(z); + hx = s.to_bits(); + let df = f32::from_bits(hx & 0xfffff000); + let c = (z - df * df) / (s + df); + w = r(z) * s + c; + 2. * (df + w) +} diff --git a/vendor/libm/src/math/acosh.rs b/vendor/libm/src/math/acosh.rs new file mode 100644 index 0000000000..ac7a5f1c62 --- /dev/null +++ b/vendor/libm/src/math/acosh.rs @@ -0,0 +1,26 @@ +use super::{log, log1p, sqrt}; + +const LN2: f64 = 0.693147180559945309417232121458176568; /* 0x3fe62e42, 0xfefa39ef*/ + +/// Inverse hyperbolic cosine (f64) +/// +/// Calculates the inverse hyperbolic cosine of `x`. +/// Is defined as `log(x + sqrt(x*x-1))`. +/// `x` must be a number greater than or equal to 1. +pub fn acosh(x: f64) -> f64 { + let u = x.to_bits(); + let e = ((u >> 52) as usize) & 0x7ff; + + /* x < 1 domain error is handled in the called functions */ + + if e < 0x3ff + 1 { + /* |x| < 2, up to 2ulp error in [1,1.125] */ + return log1p(x - 1.0 + sqrt((x - 1.0) * (x - 1.0) + 2.0 * (x - 1.0))); + } + if e < 0x3ff + 26 { + /* |x| < 0x1p26 */ + return log(2.0 * x - 1.0 / (x + sqrt(x * x - 1.0))); + } + /* |x| >= 0x1p26 or nan */ + return log(x) + LN2; +} diff --git a/vendor/libm/src/math/acoshf.rs b/vendor/libm/src/math/acoshf.rs new file mode 100644 index 0000000000..0879e1edb0 --- /dev/null +++ b/vendor/libm/src/math/acoshf.rs @@ -0,0 +1,25 @@ +use super::{log1pf, logf, sqrtf}; + +const LN2: f32 = 0.693147180559945309417232121458176568; + +/// Inverse hyperbolic cosine (f32) +/// +/// Calculates the inverse hyperbolic cosine of `x`. +/// Is defined as `log(x + sqrt(x*x-1))`. +/// `x` must be a number greater than or equal to 1. +pub fn acoshf(x: f32) -> f32 { + let u = x.to_bits(); + let a = u & 0x7fffffff; + + if a < 0x3f800000 + (1 << 23) { + /* |x| < 2, invalid if x < 1 or nan */ + /* up to 2ulp error in [1,1.125] */ + return log1pf(x - 1.0 + sqrtf((x - 1.0) * (x - 1.0) + 2.0 * (x - 1.0))); + } + if a < 0x3f800000 + (12 << 23) { + /* |x| < 0x1p12 */ + return logf(2.0 * x - 1.0 / (x + sqrtf(x * x - 1.0))); + } + /* x >= 0x1p12 */ + return logf(x) + LN2; +} diff --git a/vendor/libm/src/math/asin.rs b/vendor/libm/src/math/asin.rs new file mode 100644 index 0000000000..774475e519 --- /dev/null +++ b/vendor/libm/src/math/asin.rs @@ -0,0 +1,121 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_asin.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* asin(x) + * Method : + * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... + * we approximate asin(x) on [0,0.5] by + * asin(x) = x + x*x^2*R(x^2) + * where + * R(x^2) is a rational approximation of (asin(x)-x)/x^3 + * and its remez error is bounded by + * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75) + * + * For x in [0.5,1] + * asin(x) = pi/2-2*asin(sqrt((1-x)/2)) + * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2; + * then for x>0.98 + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) + * For x<=0.98, let pio4_hi = pio2_hi/2, then + * f = hi part of s; + * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) + * and + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) + * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + */ + +use super::{fabs, get_high_word, get_low_word, sqrt, with_set_low_word}; + +const PIO2_HI: f64 = 1.57079632679489655800e+00; /* 0x3FF921FB, 0x54442D18 */ +const PIO2_LO: f64 = 6.12323399573676603587e-17; /* 0x3C91A626, 0x33145C07 */ +/* coefficients for R(x^2) */ +const P_S0: f64 = 1.66666666666666657415e-01; /* 0x3FC55555, 0x55555555 */ +const P_S1: f64 = -3.25565818622400915405e-01; /* 0xBFD4D612, 0x03EB6F7D */ +const P_S2: f64 = 2.01212532134862925881e-01; /* 0x3FC9C155, 0x0E884455 */ +const P_S3: f64 = -4.00555345006794114027e-02; /* 0xBFA48228, 0xB5688F3B */ +const P_S4: f64 = 7.91534994289814532176e-04; /* 0x3F49EFE0, 0x7501B288 */ +const P_S5: f64 = 3.47933107596021167570e-05; /* 0x3F023DE1, 0x0DFDF709 */ +const Q_S1: f64 = -2.40339491173441421878e+00; /* 0xC0033A27, 0x1C8A2D4B */ +const Q_S2: f64 = 2.02094576023350569471e+00; /* 0x40002AE5, 0x9C598AC8 */ +const Q_S3: f64 = -6.88283971605453293030e-01; /* 0xBFE6066C, 0x1B8D0159 */ +const Q_S4: f64 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +#[inline] +fn comp_r(z: f64) -> f64 { + let p = z * (P_S0 + z * (P_S1 + z * (P_S2 + z * (P_S3 + z * (P_S4 + z * P_S5))))); + let q = 1.0 + z * (Q_S1 + z * (Q_S2 + z * (Q_S3 + z * Q_S4))); + p / q +} + +/// Arcsine (f64) +/// +/// Computes the inverse sine (arc sine) of the argument `x`. +/// Arguments to asin must be in the range -1 to 1. +/// Returns values in radians, in the range of -pi/2 to pi/2. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn asin(mut x: f64) -> f64 { + let z: f64; + let r: f64; + let s: f64; + let hx: u32; + let ix: u32; + + hx = get_high_word(x); + ix = hx & 0x7fffffff; + /* |x| >= 1 or nan */ + if ix >= 0x3ff00000 { + let lx: u32; + lx = get_low_word(x); + if ((ix - 0x3ff00000) | lx) == 0 { + /* asin(1) = +-pi/2 with inexact */ + return x * PIO2_HI + f64::from_bits(0x3870000000000000); + } else { + return 0.0 / (x - x); + } + } + /* |x| < 0.5 */ + if ix < 0x3fe00000 { + /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */ + if ix < 0x3e500000 && ix >= 0x00100000 { + return x; + } else { + return x + x * comp_r(x * x); + } + } + /* 1 > |x| >= 0.5 */ + z = (1.0 - fabs(x)) * 0.5; + s = sqrt(z); + r = comp_r(z); + if ix >= 0x3fef3333 { + /* if |x| > 0.975 */ + x = PIO2_HI - (2. * (s + s * r) - PIO2_LO); + } else { + let f: f64; + let c: f64; + /* f+c = sqrt(z) */ + f = with_set_low_word(s, 0); + c = (z - f * f) / (s + f); + x = 0.5 * PIO2_HI - (2.0 * s * r - (PIO2_LO - 2.0 * c) - (0.5 * PIO2_HI - 2.0 * f)); + } + if hx >> 31 != 0 { + -x + } else { + x + } +} diff --git a/vendor/libm/src/math/asinf.rs b/vendor/libm/src/math/asinf.rs new file mode 100644 index 0000000000..ce0f4a997e --- /dev/null +++ b/vendor/libm/src/math/asinf.rs @@ -0,0 +1,74 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_asinf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::fabsf::fabsf; +use super::sqrt::sqrt; + +const PIO2: f64 = 1.570796326794896558e+00; + +/* coefficients for R(x^2) */ +const P_S0: f32 = 1.6666586697e-01; +const P_S1: f32 = -4.2743422091e-02; +const P_S2: f32 = -8.6563630030e-03; +const Q_S1: f32 = -7.0662963390e-01; + +#[inline] +fn r(z: f32) -> f32 { + let p = z * (P_S0 + z * (P_S1 + z * P_S2)); + let q = 1. + z * Q_S1; + p / q +} + +/// Arcsine (f32) +/// +/// Computes the inverse sine (arc sine) of the argument `x`. +/// Arguments to asin must be in the range -1 to 1. +/// Returns values in radians, in the range of -pi/2 to pi/2. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn asinf(mut x: f32) -> f32 { + let x1p_120 = f64::from_bits(0x3870000000000000); // 0x1p-120 === 2 ^ (-120) + + let hx = x.to_bits(); + let ix = hx & 0x7fffffff; + + if ix >= 0x3f800000 { + /* |x| >= 1 */ + if ix == 0x3f800000 { + /* |x| == 1 */ + return ((x as f64) * PIO2 + x1p_120) as f32; /* asin(+-1) = +-pi/2 with inexact */ + } + return 0. / (x - x); /* asin(|x|>1) is NaN */ + } + + if ix < 0x3f000000 { + /* |x| < 0.5 */ + /* if 0x1p-126 <= |x| < 0x1p-12, avoid raising underflow */ + if (ix < 0x39800000) && (ix >= 0x00800000) { + return x; + } + return x + x * r(x * x); + } + + /* 1 > |x| >= 0.5 */ + let z = (1. - fabsf(x)) * 0.5; + let s = sqrt(z as f64); + x = (PIO2 - 2. * (s + s * (r(z) as f64))) as f32; + if (hx >> 31) != 0 { + -x + } else { + x + } +} diff --git a/vendor/libm/src/math/asinh.rs b/vendor/libm/src/math/asinh.rs new file mode 100644 index 0000000000..14295357a5 --- /dev/null +++ b/vendor/libm/src/math/asinh.rs @@ -0,0 +1,39 @@ +use super::{log, log1p, sqrt}; + +const LN2: f64 = 0.693147180559945309417232121458176568; /* 0x3fe62e42, 0xfefa39ef*/ + +/* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */ +/// Inverse hyperbolic sine (f64) +/// +/// Calculates the inverse hyperbolic sine of `x`. +/// Is defined as `sgn(x)*log(|x|+sqrt(x*x+1))`. +pub fn asinh(mut x: f64) -> f64 { + let mut u = x.to_bits(); + let e = ((u >> 52) as usize) & 0x7ff; + let sign = (u >> 63) != 0; + + /* |x| */ + u &= (!0) >> 1; + x = f64::from_bits(u); + + if e >= 0x3ff + 26 { + /* |x| >= 0x1p26 or inf or nan */ + x = log(x) + LN2; + } else if e >= 0x3ff + 1 { + /* |x| >= 2 */ + x = log(2.0 * x + 1.0 / (sqrt(x * x + 1.0) + x)); + } else if e >= 0x3ff - 26 { + /* |x| >= 0x1p-26, up to 1.6ulp error in [0.125,0.5] */ + x = log1p(x + x * x / (sqrt(x * x + 1.0) + 1.0)); + } else { + /* |x| < 0x1p-26, raise inexact if x != 0 */ + let x1p120 = f64::from_bits(0x4770000000000000); + force_eval!(x + x1p120); + } + + if sign { + -x + } else { + x + } +} diff --git a/vendor/libm/src/math/asinhf.rs b/vendor/libm/src/math/asinhf.rs new file mode 100644 index 0000000000..e22a291323 --- /dev/null +++ b/vendor/libm/src/math/asinhf.rs @@ -0,0 +1,38 @@ +use super::{log1pf, logf, sqrtf}; + +const LN2: f32 = 0.693147180559945309417232121458176568; + +/* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */ +/// Inverse hyperbolic sine (f32) +/// +/// Calculates the inverse hyperbolic sine of `x`. +/// Is defined as `sgn(x)*log(|x|+sqrt(x*x+1))`. +pub fn asinhf(mut x: f32) -> f32 { + let u = x.to_bits(); + let i = u & 0x7fffffff; + let sign = (u >> 31) != 0; + + /* |x| */ + x = f32::from_bits(i); + + if i >= 0x3f800000 + (12 << 23) { + /* |x| >= 0x1p12 or inf or nan */ + x = logf(x) + LN2; + } else if i >= 0x3f800000 + (1 << 23) { + /* |x| >= 2 */ + x = logf(2.0 * x + 1.0 / (sqrtf(x * x + 1.0) + x)); + } else if i >= 0x3f800000 - (12 << 23) { + /* |x| >= 0x1p-12, up to 1.6ulp error in [0.125,0.5] */ + x = log1pf(x + x * x / (sqrtf(x * x + 1.0) + 1.0)); + } else { + /* |x| < 0x1p-12, raise inexact if x!=0 */ + let x1p120 = f32::from_bits(0x7b800000); + force_eval!(x + x1p120); + } + + if sign { + -x + } else { + x + } +} diff --git a/vendor/libm/src/math/atan.rs b/vendor/libm/src/math/atan.rs new file mode 100644 index 0000000000..d2684ece8e --- /dev/null +++ b/vendor/libm/src/math/atan.rs @@ -0,0 +1,185 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_atan.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* atan(x) + * Method + * 1. Reduce x to positive by atan(x) = -atan(-x). + * 2. According to the integer k=4t+0.25 chopped, t=x, the argument + * is further reduced to one of the following intervals and the + * arctangent of t is evaluated by the corresponding formula: + * + * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) + * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) + * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) + * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) + * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +use super::fabs; +use core::f64; + +const ATANHI: [f64; 4] = [ + 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ + 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ + 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ + 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ +]; + +const ATANLO: [f64; 4] = [ + 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ + 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ + 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ + 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ +]; + +const AT: [f64; 11] = [ + 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ + -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ + 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ + -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ + 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ + -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ + 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ + -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ + 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ + -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ + 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ +]; + +/// Arctangent (f64) +/// +/// Computes the inverse tangent (arc tangent) of the input value. +/// Returns a value in radians, in the range of -pi/2 to pi/2. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn atan(x: f64) -> f64 { + let mut x = x; + let mut ix = (x.to_bits() >> 32) as u32; + let sign = ix >> 31; + ix &= 0x7fff_ffff; + if ix >= 0x4410_0000 { + if x.is_nan() { + return x; + } + + let z = ATANHI[3] + f64::from_bits(0x0380_0000); // 0x1p-120f + return if sign != 0 { -z } else { z }; + } + + let id = if ix < 0x3fdc_0000 { + /* |x| < 0.4375 */ + if ix < 0x3e40_0000 { + /* |x| < 2^-27 */ + if ix < 0x0010_0000 { + /* raise underflow for subnormal x */ + force_eval!(x as f32); + } + + return x; + } + + -1 + } else { + x = fabs(x); + if ix < 0x3ff30000 { + /* |x| < 1.1875 */ + if ix < 0x3fe60000 { + /* 7/16 <= |x| < 11/16 */ + x = (2. * x - 1.) / (2. + x); + 0 + } else { + /* 11/16 <= |x| < 19/16 */ + x = (x - 1.) / (x + 1.); + 1 + } + } else if ix < 0x40038000 { + /* |x| < 2.4375 */ + x = (x - 1.5) / (1. + 1.5 * x); + 2 + } else { + /* 2.4375 <= |x| < 2^66 */ + x = -1. / x; + 3 + } + }; + + let z = x * x; + let w = z * z; + /* break sum from i=0 to 10 AT[i]z**(i+1) into odd and even poly */ + let s1 = z * (AT[0] + w * (AT[2] + w * (AT[4] + w * (AT[6] + w * (AT[8] + w * AT[10]))))); + let s2 = w * (AT[1] + w * (AT[3] + w * (AT[5] + w * (AT[7] + w * AT[9])))); + + if id < 0 { + return x - x * (s1 + s2); + } + + let z = i!(ATANHI, id as usize) - (x * (s1 + s2) - i!(ATANLO, id as usize) - x); + + if sign != 0 { + -z + } else { + z + } +} + +#[cfg(test)] +mod tests { + use super::atan; + use core::f64; + + #[test] + fn sanity_check() { + for (input, answer) in [ + (3.0_f64.sqrt() / 3.0, f64::consts::FRAC_PI_6), + (1.0, f64::consts::FRAC_PI_4), + (3.0_f64.sqrt(), f64::consts::FRAC_PI_3), + (-3.0_f64.sqrt() / 3.0, -f64::consts::FRAC_PI_6), + (-1.0, -f64::consts::FRAC_PI_4), + (-3.0_f64.sqrt(), -f64::consts::FRAC_PI_3), + ] + .iter() + { + assert!( + (atan(*input) - answer) / answer < 1e-5, + "\natan({:.4}/16) = {:.4}, actual: {}", + input * 16.0, + answer, + atan(*input) + ); + } + } + + #[test] + fn zero() { + assert_eq!(atan(0.0), 0.0); + } + + #[test] + fn infinity() { + assert_eq!(atan(f64::INFINITY), f64::consts::FRAC_PI_2); + } + + #[test] + fn minus_infinity() { + assert_eq!(atan(f64::NEG_INFINITY), -f64::consts::FRAC_PI_2); + } + + #[test] + fn nan() { + assert!(atan(f64::NAN).is_nan()); + } +} diff --git a/vendor/libm/src/math/atan2.rs b/vendor/libm/src/math/atan2.rs new file mode 100644 index 0000000000..08385cd100 --- /dev/null +++ b/vendor/libm/src/math/atan2.rs @@ -0,0 +1,127 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_atan2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ +/* atan2(y,x) + * Method : + * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). + * 2. Reduce x to positive by (if x and y are unexceptional): + * ARG (x+iy) = arctan(y/x) ... if x > 0, + * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, + * + * Special cases: + * + * ATAN2((anything), NaN ) is NaN; + * ATAN2(NAN , (anything) ) is NaN; + * ATAN2(+-0, +(anything but NaN)) is +-0 ; + * ATAN2(+-0, -(anything but NaN)) is +-pi ; + * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; + * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; + * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; + * ATAN2(+-INF,+INF ) is +-pi/4 ; + * ATAN2(+-INF,-INF ) is +-3pi/4; + * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +use super::atan; +use super::fabs; + +const PI: f64 = 3.1415926535897931160E+00; /* 0x400921FB, 0x54442D18 */ +const PI_LO: f64 = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ + +/// Arctangent of y/x (f64) +/// +/// Computes the inverse tangent (arc tangent) of `y/x`. +/// Produces the correct result even for angles near pi/2 or -pi/2 (that is, when `x` is near 0). +/// Returns a value in radians, in the range of -pi to pi. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn atan2(y: f64, x: f64) -> f64 { + if x.is_nan() || y.is_nan() { + return x + y; + } + let mut ix = (x.to_bits() >> 32) as u32; + let lx = x.to_bits() as u32; + let mut iy = (y.to_bits() >> 32) as u32; + let ly = y.to_bits() as u32; + if ((ix.wrapping_sub(0x3ff00000)) | lx) == 0 { + /* x = 1.0 */ + return atan(y); + } + let m = ((iy >> 31) & 1) | ((ix >> 30) & 2); /* 2*sign(x)+sign(y) */ + ix &= 0x7fffffff; + iy &= 0x7fffffff; + + /* when y = 0 */ + if (iy | ly) == 0 { + return match m { + 0 | 1 => y, /* atan(+-0,+anything)=+-0 */ + 2 => PI, /* atan(+0,-anything) = PI */ + _ => -PI, /* atan(-0,-anything) =-PI */ + }; + } + /* when x = 0 */ + if (ix | lx) == 0 { + return if m & 1 != 0 { -PI / 2.0 } else { PI / 2.0 }; + } + /* when x is INF */ + if ix == 0x7ff00000 { + if iy == 0x7ff00000 { + return match m { + 0 => PI / 4.0, /* atan(+INF,+INF) */ + 1 => -PI / 4.0, /* atan(-INF,+INF) */ + 2 => 3.0 * PI / 4.0, /* atan(+INF,-INF) */ + _ => -3.0 * PI / 4.0, /* atan(-INF,-INF) */ + }; + } else { + return match m { + 0 => 0.0, /* atan(+...,+INF) */ + 1 => -0.0, /* atan(-...,+INF) */ + 2 => PI, /* atan(+...,-INF) */ + _ => -PI, /* atan(-...,-INF) */ + }; + } + } + /* |y/x| > 0x1p64 */ + if ix.wrapping_add(64 << 20) < iy || iy == 0x7ff00000 { + return if m & 1 != 0 { -PI / 2.0 } else { PI / 2.0 }; + } + + /* z = atan(|y/x|) without spurious underflow */ + let z = if (m & 2 != 0) && iy.wrapping_add(64 << 20) < ix { + /* |y/x| < 0x1p-64, x<0 */ + 0.0 + } else { + atan(fabs(y / x)) + }; + match m { + 0 => z, /* atan(+,+) */ + 1 => -z, /* atan(-,+) */ + 2 => PI - (z - PI_LO), /* atan(+,-) */ + _ => (z - PI_LO) - PI, /* atan(-,-) */ + } +} + +#[test] +fn sanity_check() { + assert_eq!(atan2(0.0, 1.0), 0.0); + assert_eq!(atan2(0.0, -1.0), PI); + assert_eq!(atan2(-0.0, -1.0), -PI); + assert_eq!(atan2(3.0, 2.0), atan(3.0 / 2.0)); + assert_eq!(atan2(2.0, -1.0), atan(2.0 / -1.0) + PI); + assert_eq!(atan2(-2.0, -1.0), atan(-2.0 / -1.0) - PI); +} diff --git a/vendor/libm/src/math/atan2f.rs b/vendor/libm/src/math/atan2f.rs new file mode 100644 index 0000000000..7bbe5f1d47 --- /dev/null +++ b/vendor/libm/src/math/atan2f.rs @@ -0,0 +1,92 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_atan2f.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::atanf; +use super::fabsf; + +const PI: f32 = 3.1415927410e+00; /* 0x40490fdb */ +const PI_LO: f32 = -8.7422776573e-08; /* 0xb3bbbd2e */ + +/// Arctangent of y/x (f32) +/// +/// Computes the inverse tangent (arc tangent) of `y/x`. +/// Produces the correct result even for angles near pi/2 or -pi/2 (that is, when `x` is near 0). +/// Returns a value in radians, in the range of -pi to pi. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn atan2f(y: f32, x: f32) -> f32 { + if x.is_nan() || y.is_nan() { + return x + y; + } + let mut ix = x.to_bits(); + let mut iy = y.to_bits(); + + if ix == 0x3f800000 { + /* x=1.0 */ + return atanf(y); + } + let m = ((iy >> 31) & 1) | ((ix >> 30) & 2); /* 2*sign(x)+sign(y) */ + ix &= 0x7fffffff; + iy &= 0x7fffffff; + + /* when y = 0 */ + if iy == 0 { + return match m { + 0 | 1 => y, /* atan(+-0,+anything)=+-0 */ + 2 => PI, /* atan(+0,-anything) = pi */ + 3 | _ => -PI, /* atan(-0,-anything) =-pi */ + }; + } + /* when x = 0 */ + if ix == 0 { + return if m & 1 != 0 { -PI / 2. } else { PI / 2. }; + } + /* when x is INF */ + if ix == 0x7f800000 { + return if iy == 0x7f800000 { + match m { + 0 => PI / 4., /* atan(+INF,+INF) */ + 1 => -PI / 4., /* atan(-INF,+INF) */ + 2 => 3. * PI / 4., /* atan(+INF,-INF)*/ + 3 | _ => -3. * PI / 4., /* atan(-INF,-INF)*/ + } + } else { + match m { + 0 => 0., /* atan(+...,+INF) */ + 1 => -0., /* atan(-...,+INF) */ + 2 => PI, /* atan(+...,-INF) */ + 3 | _ => -PI, /* atan(-...,-INF) */ + } + }; + } + /* |y/x| > 0x1p26 */ + if (ix + (26 << 23) < iy) || (iy == 0x7f800000) { + return if m & 1 != 0 { -PI / 2. } else { PI / 2. }; + } + + /* z = atan(|y/x|) with correct underflow */ + let z = if (m & 2 != 0) && (iy + (26 << 23) < ix) { + /*|y/x| < 0x1p-26, x < 0 */ + 0. + } else { + atanf(fabsf(y / x)) + }; + match m { + 0 => z, /* atan(+,+) */ + 1 => -z, /* atan(-,+) */ + 2 => PI - (z - PI_LO), /* atan(+,-) */ + _ => (z - PI_LO) - PI, /* case 3 */ /* atan(-,-) */ + } +} diff --git a/vendor/libm/src/math/atanf.rs b/vendor/libm/src/math/atanf.rs new file mode 100644 index 0000000000..363e11d647 --- /dev/null +++ b/vendor/libm/src/math/atanf.rs @@ -0,0 +1,113 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_atanf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::fabsf; + +const ATAN_HI: [f32; 4] = [ + 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */ + 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */ + 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */ + 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */ +]; + +const ATAN_LO: [f32; 4] = [ + 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */ + 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */ + 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */ + 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */ +]; + +const A_T: [f32; 5] = [ + 3.3333328366e-01, + -1.9999158382e-01, + 1.4253635705e-01, + -1.0648017377e-01, + 6.1687607318e-02, +]; + +/// Arctangent (f32) +/// +/// Computes the inverse tangent (arc tangent) of the input value. +/// Returns a value in radians, in the range of -pi/2 to pi/2. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn atanf(mut x: f32) -> f32 { + let x1p_120 = f32::from_bits(0x03800000); // 0x1p-120 === 2 ^ (-120) + + let z: f32; + + let mut ix = x.to_bits(); + let sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + + if ix >= 0x4c800000 { + /* if |x| >= 2**26 */ + if x.is_nan() { + return x; + } + z = ATAN_HI[3] + x1p_120; + return if sign { -z } else { z }; + } + let id = if ix < 0x3ee00000 { + /* |x| < 0.4375 */ + if ix < 0x39800000 { + /* |x| < 2**-12 */ + if ix < 0x00800000 { + /* raise underflow for subnormal x */ + force_eval!(x * x); + } + return x; + } + -1 + } else { + x = fabsf(x); + if ix < 0x3f980000 { + /* |x| < 1.1875 */ + if ix < 0x3f300000 { + /* 7/16 <= |x| < 11/16 */ + x = (2. * x - 1.) / (2. + x); + 0 + } else { + /* 11/16 <= |x| < 19/16 */ + x = (x - 1.) / (x + 1.); + 1 + } + } else if ix < 0x401c0000 { + /* |x| < 2.4375 */ + x = (x - 1.5) / (1. + 1.5 * x); + 2 + } else { + /* 2.4375 <= |x| < 2**26 */ + x = -1. / x; + 3 + } + }; + /* end of argument reduction */ + z = x * x; + let w = z * z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + let s1 = z * (A_T[0] + w * (A_T[2] + w * A_T[4])); + let s2 = w * (A_T[1] + w * A_T[3]); + if id < 0 { + return x - x * (s1 + s2); + } + let id = id as usize; + let z = ATAN_HI[id] - ((x * (s1 + s2) - ATAN_LO[id]) - x); + if sign { + -z + } else { + z + } +} diff --git a/vendor/libm/src/math/atanh.rs b/vendor/libm/src/math/atanh.rs new file mode 100644 index 0000000000..79a989c42d --- /dev/null +++ b/vendor/libm/src/math/atanh.rs @@ -0,0 +1,36 @@ +use super::log1p; + +/* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ +/// Inverse hyperbolic tangent (f64) +/// +/// Calculates the inverse hyperbolic tangent of `x`. +/// Is defined as `log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2`. +pub fn atanh(x: f64) -> f64 { + let u = x.to_bits(); + let e = ((u >> 52) as usize) & 0x7ff; + let sign = (u >> 63) != 0; + + /* |x| */ + let mut y = f64::from_bits(u & 0x7fff_ffff_ffff_ffff); + + if e < 0x3ff - 1 { + if e < 0x3ff - 32 { + /* handle underflow */ + if e == 0 { + force_eval!(y as f32); + } + } else { + /* |x| < 0.5, up to 1.7ulp error */ + y = 0.5 * log1p(2.0 * y + 2.0 * y * y / (1.0 - y)); + } + } else { + /* avoid overflow */ + y = 0.5 * log1p(2.0 * (y / (1.0 - y))); + } + + if sign { + -y + } else { + y + } +} diff --git a/vendor/libm/src/math/atanhf.rs b/vendor/libm/src/math/atanhf.rs new file mode 100644 index 0000000000..7b2f34d97d --- /dev/null +++ b/vendor/libm/src/math/atanhf.rs @@ -0,0 +1,36 @@ +use super::log1pf; + +/* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ +/// Inverse hyperbolic tangent (f32) +/// +/// Calculates the inverse hyperbolic tangent of `x`. +/// Is defined as `log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2`. +pub fn atanhf(mut x: f32) -> f32 { + let mut u = x.to_bits(); + let sign = (u >> 31) != 0; + + /* |x| */ + u &= 0x7fffffff; + x = f32::from_bits(u); + + if u < 0x3f800000 - (1 << 23) { + if u < 0x3f800000 - (32 << 23) { + /* handle underflow */ + if u < (1 << 23) { + force_eval!((x * x) as f32); + } + } else { + /* |x| < 0.5, up to 1.7ulp error */ + x = 0.5 * log1pf(2.0 * x + 2.0 * x * x / (1.0 - x)); + } + } else { + /* avoid overflow */ + x = 0.5 * log1pf(2.0 * (x / (1.0 - x))); + } + + if sign { + -x + } else { + x + } +} diff --git a/vendor/libm/src/math/cbrt.rs b/vendor/libm/src/math/cbrt.rs new file mode 100644 index 0000000000..04469b1598 --- /dev/null +++ b/vendor/libm/src/math/cbrt.rs @@ -0,0 +1,114 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_cbrt.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + * Optimized by Bruce D. Evans. + */ +/* cbrt(x) + * Return cube root of x + */ + +use core::f64; + +const B1: u32 = 715094163; /* B1 = (1023-1023/3-0.03306235651)*2**20 */ +const B2: u32 = 696219795; /* B2 = (1023-1023/3-54/3-0.03306235651)*2**20 */ + +/* |1/cbrt(x) - p(x)| < 2**-23.5 (~[-7.93e-8, 7.929e-8]). */ +const P0: f64 = 1.87595182427177009643; /* 0x3ffe03e6, 0x0f61e692 */ +const P1: f64 = -1.88497979543377169875; /* 0xbffe28e0, 0x92f02420 */ +const P2: f64 = 1.621429720105354466140; /* 0x3ff9f160, 0x4a49d6c2 */ +const P3: f64 = -0.758397934778766047437; /* 0xbfe844cb, 0xbee751d9 */ +const P4: f64 = 0.145996192886612446982; /* 0x3fc2b000, 0xd4e4edd7 */ + +// Cube root (f64) +/// +/// Computes the cube root of the argument. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn cbrt(x: f64) -> f64 { + let x1p54 = f64::from_bits(0x4350000000000000); // 0x1p54 === 2 ^ 54 + + let mut ui: u64 = x.to_bits(); + let mut r: f64; + let s: f64; + let mut t: f64; + let w: f64; + let mut hx: u32 = (ui >> 32) as u32 & 0x7fffffff; + + if hx >= 0x7ff00000 { + /* cbrt(NaN,INF) is itself */ + return x + x; + } + + /* + * Rough cbrt to 5 bits: + * cbrt(2**e*(1+m) ~= 2**(e/3)*(1+(e%3+m)/3) + * where e is integral and >= 0, m is real and in [0, 1), and "/" and + * "%" are integer division and modulus with rounding towards minus + * infinity. The RHS is always >= the LHS and has a maximum relative + * error of about 1 in 16. Adding a bias of -0.03306235651 to the + * (e%3+m)/3 term reduces the error to about 1 in 32. With the IEEE + * floating point representation, for finite positive normal values, + * ordinary integer divison of the value in bits magically gives + * almost exactly the RHS of the above provided we first subtract the + * exponent bias (1023 for doubles) and later add it back. We do the + * subtraction virtually to keep e >= 0 so that ordinary integer + * division rounds towards minus infinity; this is also efficient. + */ + if hx < 0x00100000 { + /* zero or subnormal? */ + ui = (x * x1p54).to_bits(); + hx = (ui >> 32) as u32 & 0x7fffffff; + if hx == 0 { + return x; /* cbrt(0) is itself */ + } + hx = hx / 3 + B2; + } else { + hx = hx / 3 + B1; + } + ui &= 1 << 63; + ui |= (hx as u64) << 32; + t = f64::from_bits(ui); + + /* + * New cbrt to 23 bits: + * cbrt(x) = t*cbrt(x/t**3) ~= t*P(t**3/x) + * where P(r) is a polynomial of degree 4 that approximates 1/cbrt(r) + * to within 2**-23.5 when |r - 1| < 1/10. The rough approximation + * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this + * gives us bounds for r = t**3/x. + * + * Try to optimize for parallel evaluation as in __tanf.c. + */ + r = (t * t) * (t / x); + t = t * ((P0 + r * (P1 + r * P2)) + ((r * r) * r) * (P3 + r * P4)); + + /* + * Round t away from zero to 23 bits (sloppily except for ensuring that + * the result is larger in magnitude than cbrt(x) but not much more than + * 2 23-bit ulps larger). With rounding towards zero, the error bound + * would be ~5/6 instead of ~4/6. With a maximum error of 2 23-bit ulps + * in the rounded t, the infinite-precision error in the Newton + * approximation barely affects third digit in the final error + * 0.667; the error in the rounded t can be up to about 3 23-bit ulps + * before the final error is larger than 0.667 ulps. + */ + ui = t.to_bits(); + ui = (ui + 0x80000000) & 0xffffffffc0000000; + t = f64::from_bits(ui); + + /* one step Newton iteration to 53 bits with error < 0.667 ulps */ + s = t * t; /* t*t is exact */ + r = x / s; /* error <= 0.5 ulps; |r| < |t| */ + w = t + t; /* t+t is exact */ + r = (r - t) / (w + r); /* r-t is exact; w+r ~= 3*t */ + t = t + t * r; /* error <= 0.5 + 0.5/3 + epsilon */ + t +} diff --git a/vendor/libm/src/math/cbrtf.rs b/vendor/libm/src/math/cbrtf.rs new file mode 100644 index 0000000000..6e589c0994 --- /dev/null +++ b/vendor/libm/src/math/cbrtf.rs @@ -0,0 +1,76 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_cbrtf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Debugged and optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* cbrtf(x) + * Return cube root of x + */ + +use core::f32; + +const B1: u32 = 709958130; /* B1 = (127-127.0/3-0.03306235651)*2**23 */ +const B2: u32 = 642849266; /* B2 = (127-127.0/3-24/3-0.03306235651)*2**23 */ + +/// Cube root (f32) +/// +/// Computes the cube root of the argument. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn cbrtf(x: f32) -> f32 { + let x1p24 = f32::from_bits(0x4b800000); // 0x1p24f === 2 ^ 24 + + let mut r: f64; + let mut t: f64; + let mut ui: u32 = x.to_bits(); + let mut hx: u32 = ui & 0x7fffffff; + + if hx >= 0x7f800000 { + /* cbrt(NaN,INF) is itself */ + return x + x; + } + + /* rough cbrt to 5 bits */ + if hx < 0x00800000 { + /* zero or subnormal? */ + if hx == 0 { + return x; /* cbrt(+-0) is itself */ + } + ui = (x * x1p24).to_bits(); + hx = ui & 0x7fffffff; + hx = hx / 3 + B2; + } else { + hx = hx / 3 + B1; + } + ui &= 0x80000000; + ui |= hx; + + /* + * First step Newton iteration (solving t*t-x/t == 0) to 16 bits. In + * double precision so that its terms can be arranged for efficiency + * without causing overflow or underflow. + */ + t = f32::from_bits(ui) as f64; + r = t * t * t; + t = t * (x as f64 + x as f64 + r) / (x as f64 + r + r); + + /* + * Second step Newton iteration to 47 bits. In double precision for + * efficiency and accuracy. + */ + r = t * t * t; + t = t * (x as f64 + x as f64 + r) / (x as f64 + r + r); + + /* rounding to 24 bits is perfect in round-to-nearest mode */ + t as f32 +} diff --git a/vendor/libm/src/math/ceil.rs b/vendor/libm/src/math/ceil.rs new file mode 100644 index 0000000000..59883a8a7b --- /dev/null +++ b/vendor/libm/src/math/ceil.rs @@ -0,0 +1,51 @@ +use core::f64; + +const TOINT: f64 = 1. / f64::EPSILON; + +/// Ceil (f64) +/// +/// Finds the nearest integer greater than or equal to `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn ceil(x: f64) -> f64 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f64.ceil` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::ceilf64(x) } + } + } + let u: u64 = x.to_bits(); + let e: i64 = (u >> 52 & 0x7ff) as i64; + let y: f64; + + if e >= 0x3ff + 52 || x == 0. { + return x; + } + // y = int(x) - x, where int(x) is an integer neighbor of x + y = if (u >> 63) != 0 { + x - TOINT + TOINT - x + } else { + x + TOINT - TOINT - x + }; + // special case because of non-nearest rounding modes + if e < 0x3ff { + force_eval!(y); + return if (u >> 63) != 0 { -0. } else { 1. }; + } + if y < 0. { + x + y + 1. + } else { + x + y + } +} + +#[cfg(test)] +mod tests { + #[test] + fn sanity_check() { + assert_eq!(super::ceil(1.1), 2.0); + assert_eq!(super::ceil(2.9), 3.0); + } +} diff --git a/vendor/libm/src/math/ceilf.rs b/vendor/libm/src/math/ceilf.rs new file mode 100644 index 0000000000..151a4f2104 --- /dev/null +++ b/vendor/libm/src/math/ceilf.rs @@ -0,0 +1,42 @@ +use core::f32; + +/// Ceil (f32) +/// +/// Finds the nearest integer greater than or equal to `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn ceilf(x: f32) -> f32 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f32.ceil` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::ceilf32(x) } + } + } + let mut ui = x.to_bits(); + let e = (((ui >> 23) & 0xff).wrapping_sub(0x7f)) as i32; + + if e >= 23 { + return x; + } + if e >= 0 { + let m = 0x007fffff >> e; + if (ui & m) == 0 { + return x; + } + force_eval!(x + f32::from_bits(0x7b800000)); + if ui >> 31 == 0 { + ui += m; + } + ui &= !m; + } else { + force_eval!(x + f32::from_bits(0x7b800000)); + if ui >> 31 != 0 { + return -0.0; + } else if ui << 1 != 0 { + return 1.0; + } + } + f32::from_bits(ui) +} diff --git a/vendor/libm/src/math/copysign.rs b/vendor/libm/src/math/copysign.rs new file mode 100644 index 0000000000..1527fb6ea8 --- /dev/null +++ b/vendor/libm/src/math/copysign.rs @@ -0,0 +1,11 @@ +/// Sign of Y, magnitude of X (f64) +/// +/// Constructs a number with the magnitude (absolute value) of its +/// first argument, `x`, and the sign of its second argument, `y`. +pub fn copysign(x: f64, y: f64) -> f64 { + let mut ux = x.to_bits(); + let uy = y.to_bits(); + ux &= (!0) >> 1; + ux |= uy & (1 << 63); + f64::from_bits(ux) +} diff --git a/vendor/libm/src/math/copysignf.rs b/vendor/libm/src/math/copysignf.rs new file mode 100644 index 0000000000..35148561a8 --- /dev/null +++ b/vendor/libm/src/math/copysignf.rs @@ -0,0 +1,11 @@ +/// Sign of Y, magnitude of X (f32) +/// +/// Constructs a number with the magnitude (absolute value) of its +/// first argument, `x`, and the sign of its second argument, `y`. +pub fn copysignf(x: f32, y: f32) -> f32 { + let mut ux = x.to_bits(); + let uy = y.to_bits(); + ux &= 0x7fffffff; + ux |= uy & 0x80000000; + f32::from_bits(ux) +} diff --git a/vendor/libm/src/math/cos.rs b/vendor/libm/src/math/cos.rs new file mode 100644 index 0000000000..fe5a89919b --- /dev/null +++ b/vendor/libm/src/math/cos.rs @@ -0,0 +1,74 @@ +// origin: FreeBSD /usr/src/lib/msun/src/s_cos.c */ +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunPro, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== + +use super::{k_cos, k_sin, rem_pio2}; + +// cos(x) +// Return cosine function of x. +// +// kernel function: +// k_sin ... sine function on [-pi/4,pi/4] +// k_cos ... cosine function on [-pi/4,pi/4] +// rem_pio2 ... argument reduction routine +// +// Method. +// Let S,C and T denote the sin, cos and tan respectively on +// [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 +// in [-pi/4 , +pi/4], and let n = k mod 4. +// We have +// +// n sin(x) cos(x) tan(x) +// ---------------------------------------------------------- +// 0 S C T +// 1 C -S -1/T +// 2 -S -C T +// 3 -C S -1/T +// ---------------------------------------------------------- +// +// Special cases: +// Let trig be any of sin, cos, or tan. +// trig(+-INF) is NaN, with signals; +// trig(NaN) is that NaN; +// +// Accuracy: +// TRIG(x) returns trig(x) nearly rounded +// +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn cos(x: f64) -> f64 { + let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff; + + /* |x| ~< pi/4 */ + if ix <= 0x3fe921fb { + if ix < 0x3e46a09e { + /* if x < 2**-27 * sqrt(2) */ + /* raise inexact if x != 0 */ + if x as i32 == 0 { + return 1.0; + } + } + return k_cos(x, 0.0); + } + + /* cos(Inf or NaN) is NaN */ + if ix >= 0x7ff00000 { + return x - x; + } + + /* argument reduction needed */ + let (n, y0, y1) = rem_pio2(x); + match n & 3 { + 0 => k_cos(y0, y1), + 1 => -k_sin(y0, y1, 1), + 2 => -k_cos(y0, y1), + _ => k_sin(y0, y1, 1), + } +} diff --git a/vendor/libm/src/math/cosf.rs b/vendor/libm/src/math/cosf.rs new file mode 100644 index 0000000000..48d76c8ee0 --- /dev/null +++ b/vendor/libm/src/math/cosf.rs @@ -0,0 +1,84 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_cosf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{k_cosf, k_sinf, rem_pio2f}; + +use core::f64::consts::FRAC_PI_2; + +/* Small multiples of pi/2 rounded to double precision. */ +const C1_PIO2: f64 = 1. * FRAC_PI_2; /* 0x3FF921FB, 0x54442D18 */ +const C2_PIO2: f64 = 2. * FRAC_PI_2; /* 0x400921FB, 0x54442D18 */ +const C3_PIO2: f64 = 3. * FRAC_PI_2; /* 0x4012D97C, 0x7F3321D2 */ +const C4_PIO2: f64 = 4. * FRAC_PI_2; /* 0x401921FB, 0x54442D18 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn cosf(x: f32) -> f32 { + let x64 = x as f64; + + let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120 + + let mut ix = x.to_bits(); + let sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + + if ix <= 0x3f490fda { + /* |x| ~<= pi/4 */ + if ix < 0x39800000 { + /* |x| < 2**-12 */ + /* raise inexact if x != 0 */ + force_eval!(x + x1p120); + return 1.; + } + return k_cosf(x64); + } + if ix <= 0x407b53d1 { + /* |x| ~<= 5*pi/4 */ + if ix > 0x4016cbe3 { + /* |x| ~> 3*pi/4 */ + return -k_cosf(if sign { x64 + C2_PIO2 } else { x64 - C2_PIO2 }); + } else if sign { + return k_sinf(x64 + C1_PIO2); + } else { + return k_sinf(C1_PIO2 - x64); + } + } + if ix <= 0x40e231d5 { + /* |x| ~<= 9*pi/4 */ + if ix > 0x40afeddf { + /* |x| ~> 7*pi/4 */ + return k_cosf(if sign { x64 + C4_PIO2 } else { x64 - C4_PIO2 }); + } else if sign { + return k_sinf(-x64 - C3_PIO2); + } else { + return k_sinf(x64 - C3_PIO2); + } + } + + /* cos(Inf or NaN) is NaN */ + if ix >= 0x7f800000 { + return x - x; + } + + /* general argument reduction needed */ + let (n, y) = rem_pio2f(x); + match n & 3 { + 0 => k_cosf(y), + 1 => k_sinf(-y), + 2 => -k_cosf(y), + _ => k_sinf(y), + } +} diff --git a/vendor/libm/src/math/cosh.rs b/vendor/libm/src/math/cosh.rs new file mode 100644 index 0000000000..bac8755668 --- /dev/null +++ b/vendor/libm/src/math/cosh.rs @@ -0,0 +1,39 @@ +use super::exp; +use super::expm1; +use super::k_expo2; + +/// Hyperbolic cosine (f64) +/// +/// Computes the hyperbolic cosine of the argument x. +/// Is defined as `(exp(x) + exp(-x))/2` +/// Angles are specified in radians. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn cosh(mut x: f64) -> f64 { + /* |x| */ + let mut ix = x.to_bits(); + ix &= 0x7fffffffffffffff; + x = f64::from_bits(ix); + let w = ix >> 32; + + /* |x| < log(2) */ + if w < 0x3fe62e42 { + if w < 0x3ff00000 - (26 << 20) { + let x1p120 = f64::from_bits(0x4770000000000000); + force_eval!(x + x1p120); + return 1.; + } + let t = expm1(x); // exponential minus 1 + return 1. + t * t / (2. * (1. + t)); + } + + /* |x| < log(DBL_MAX) */ + if w < 0x40862e42 { + let t = exp(x); + /* note: if x>log(0x1p26) then the 1/t is not needed */ + return 0.5 * (t + 1. / t); + } + + /* |x| > log(DBL_MAX) or nan */ + k_expo2(x) +} diff --git a/vendor/libm/src/math/coshf.rs b/vendor/libm/src/math/coshf.rs new file mode 100644 index 0000000000..bf99e42f09 --- /dev/null +++ b/vendor/libm/src/math/coshf.rs @@ -0,0 +1,39 @@ +use super::expf; +use super::expm1f; +use super::k_expo2f; + +/// Hyperbolic cosine (f64) +/// +/// Computes the hyperbolic cosine of the argument x. +/// Is defined as `(exp(x) + exp(-x))/2` +/// Angles are specified in radians. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn coshf(mut x: f32) -> f32 { + let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120 + + /* |x| */ + let mut ix = x.to_bits(); + ix &= 0x7fffffff; + x = f32::from_bits(ix); + let w = ix; + + /* |x| < log(2) */ + if w < 0x3f317217 { + if w < (0x3f800000 - (12 << 23)) { + force_eval!(x + x1p120); + return 1.; + } + let t = expm1f(x); + return 1. + t * t / (2. * (1. + t)); + } + + /* |x| < log(FLT_MAX) */ + if w < 0x42b17217 { + let t = expf(x); + return 0.5 * (t + 1. / t); + } + + /* |x| > log(FLT_MAX) or nan */ + k_expo2f(x) +} diff --git a/vendor/libm/src/math/erf.rs b/vendor/libm/src/math/erf.rs new file mode 100644 index 0000000000..a2c617d341 --- /dev/null +++ b/vendor/libm/src/math/erf.rs @@ -0,0 +1,317 @@ +use super::{exp, fabs, get_high_word, with_set_low_word}; +/* origin: FreeBSD /usr/src/lib/msun/src/s_erf.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* double erf(double x) + * double erfc(double x) + * x + * 2 |\ + * erf(x) = --------- | exp(-t*t)dt + * sqrt(pi) \| + * 0 + * + * erfc(x) = 1-erf(x) + * Note that + * erf(-x) = -erf(x) + * erfc(-x) = 2 - erfc(x) + * + * Method: + * 1. For |x| in [0, 0.84375] + * erf(x) = x + x*R(x^2) + * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] + * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] + * where R = P/Q where P is an odd poly of degree 8 and + * Q is an odd poly of degree 10. + * -57.90 + * | R - (erf(x)-x)/x | <= 2 + * + * + * Remark. The formula is derived by noting + * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) + * and that + * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 + * is close to one. The interval is chosen because the fix + * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is + * near 0.6174), and by some experiment, 0.84375 is chosen to + * guarantee the error is less than one ulp for erf. + * + * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and + * c = 0.84506291151 rounded to single (24 bits) + * erf(x) = sign(x) * (c + P1(s)/Q1(s)) + * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 + * 1+(c+P1(s)/Q1(s)) if x < 0 + * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 + * Remark: here we use the taylor series expansion at x=1. + * erf(1+s) = erf(1) + s*Poly(s) + * = 0.845.. + P1(s)/Q1(s) + * That is, we use rational approximation to approximate + * erf(1+s) - (c = (single)0.84506291151) + * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] + * where + * P1(s) = degree 6 poly in s + * Q1(s) = degree 6 poly in s + * + * 3. For x in [1.25,1/0.35(~2.857143)], + * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) + * erf(x) = 1 - erfc(x) + * where + * R1(z) = degree 7 poly in z, (z=1/x^2) + * S1(z) = degree 8 poly in z + * + * 4. For x in [1/0.35,28] + * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 + * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 + * erf(x) = sign(x) *(1 - tiny) (raise inexact) + * erfc(x) = tiny*tiny (raise underflow) if x > 0 + * = 2 - tiny if x<0 + * + * 7. Special case: + * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, + * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, + * erfc/erf(NaN) is NaN + */ + +const ERX: f64 = 8.45062911510467529297e-01; /* 0x3FEB0AC1, 0x60000000 */ +/* + * Coefficients for approximation to erf on [0,0.84375] + */ +const EFX8: f64 = 1.02703333676410069053e+00; /* 0x3FF06EBA, 0x8214DB69 */ +const PP0: f64 = 1.28379167095512558561e-01; /* 0x3FC06EBA, 0x8214DB68 */ +const PP1: f64 = -3.25042107247001499370e-01; /* 0xBFD4CD7D, 0x691CB913 */ +const PP2: f64 = -2.84817495755985104766e-02; /* 0xBF9D2A51, 0xDBD7194F */ +const PP3: f64 = -5.77027029648944159157e-03; /* 0xBF77A291, 0x236668E4 */ +const PP4: f64 = -2.37630166566501626084e-05; /* 0xBEF8EAD6, 0x120016AC */ +const QQ1: f64 = 3.97917223959155352819e-01; /* 0x3FD97779, 0xCDDADC09 */ +const QQ2: f64 = 6.50222499887672944485e-02; /* 0x3FB0A54C, 0x5536CEBA */ +const QQ3: f64 = 5.08130628187576562776e-03; /* 0x3F74D022, 0xC4D36B0F */ +const QQ4: f64 = 1.32494738004321644526e-04; /* 0x3F215DC9, 0x221C1A10 */ +const QQ5: f64 = -3.96022827877536812320e-06; /* 0xBED09C43, 0x42A26120 */ +/* + * Coefficients for approximation to erf in [0.84375,1.25] + */ +const PA0: f64 = -2.36211856075265944077e-03; /* 0xBF6359B8, 0xBEF77538 */ +const PA1: f64 = 4.14856118683748331666e-01; /* 0x3FDA8D00, 0xAD92B34D */ +const PA2: f64 = -3.72207876035701323847e-01; /* 0xBFD7D240, 0xFBB8C3F1 */ +const PA3: f64 = 3.18346619901161753674e-01; /* 0x3FD45FCA, 0x805120E4 */ +const PA4: f64 = -1.10894694282396677476e-01; /* 0xBFBC6398, 0x3D3E28EC */ +const PA5: f64 = 3.54783043256182359371e-02; /* 0x3FA22A36, 0x599795EB */ +const PA6: f64 = -2.16637559486879084300e-03; /* 0xBF61BF38, 0x0A96073F */ +const QA1: f64 = 1.06420880400844228286e-01; /* 0x3FBB3E66, 0x18EEE323 */ +const QA2: f64 = 5.40397917702171048937e-01; /* 0x3FE14AF0, 0x92EB6F33 */ +const QA3: f64 = 7.18286544141962662868e-02; /* 0x3FB2635C, 0xD99FE9A7 */ +const QA4: f64 = 1.26171219808761642112e-01; /* 0x3FC02660, 0xE763351F */ +const QA5: f64 = 1.36370839120290507362e-02; /* 0x3F8BEDC2, 0x6B51DD1C */ +const QA6: f64 = 1.19844998467991074170e-02; /* 0x3F888B54, 0x5735151D */ +/* + * Coefficients for approximation to erfc in [1.25,1/0.35] + */ +const RA0: f64 = -9.86494403484714822705e-03; /* 0xBF843412, 0x600D6435 */ +const RA1: f64 = -6.93858572707181764372e-01; /* 0xBFE63416, 0xE4BA7360 */ +const RA2: f64 = -1.05586262253232909814e+01; /* 0xC0251E04, 0x41B0E726 */ +const RA3: f64 = -6.23753324503260060396e+01; /* 0xC04F300A, 0xE4CBA38D */ +const RA4: f64 = -1.62396669462573470355e+02; /* 0xC0644CB1, 0x84282266 */ +const RA5: f64 = -1.84605092906711035994e+02; /* 0xC067135C, 0xEBCCABB2 */ +const RA6: f64 = -8.12874355063065934246e+01; /* 0xC0545265, 0x57E4D2F2 */ +const RA7: f64 = -9.81432934416914548592e+00; /* 0xC023A0EF, 0xC69AC25C */ +const SA1: f64 = 1.96512716674392571292e+01; /* 0x4033A6B9, 0xBD707687 */ +const SA2: f64 = 1.37657754143519042600e+02; /* 0x4061350C, 0x526AE721 */ +const SA3: f64 = 4.34565877475229228821e+02; /* 0x407B290D, 0xD58A1A71 */ +const SA4: f64 = 6.45387271733267880336e+02; /* 0x40842B19, 0x21EC2868 */ +const SA5: f64 = 4.29008140027567833386e+02; /* 0x407AD021, 0x57700314 */ +const SA6: f64 = 1.08635005541779435134e+02; /* 0x405B28A3, 0xEE48AE2C */ +const SA7: f64 = 6.57024977031928170135e+00; /* 0x401A47EF, 0x8E484A93 */ +const SA8: f64 = -6.04244152148580987438e-02; /* 0xBFAEEFF2, 0xEE749A62 */ +/* + * Coefficients for approximation to erfc in [1/.35,28] + */ +const RB0: f64 = -9.86494292470009928597e-03; /* 0xBF843412, 0x39E86F4A */ +const RB1: f64 = -7.99283237680523006574e-01; /* 0xBFE993BA, 0x70C285DE */ +const RB2: f64 = -1.77579549177547519889e+01; /* 0xC031C209, 0x555F995A */ +const RB3: f64 = -1.60636384855821916062e+02; /* 0xC064145D, 0x43C5ED98 */ +const RB4: f64 = -6.37566443368389627722e+02; /* 0xC083EC88, 0x1375F228 */ +const RB5: f64 = -1.02509513161107724954e+03; /* 0xC0900461, 0x6A2E5992 */ +const RB6: f64 = -4.83519191608651397019e+02; /* 0xC07E384E, 0x9BDC383F */ +const SB1: f64 = 3.03380607434824582924e+01; /* 0x403E568B, 0x261D5190 */ +const SB2: f64 = 3.25792512996573918826e+02; /* 0x40745CAE, 0x221B9F0A */ +const SB3: f64 = 1.53672958608443695994e+03; /* 0x409802EB, 0x189D5118 */ +const SB4: f64 = 3.19985821950859553908e+03; /* 0x40A8FFB7, 0x688C246A */ +const SB5: f64 = 2.55305040643316442583e+03; /* 0x40A3F219, 0xCEDF3BE6 */ +const SB6: f64 = 4.74528541206955367215e+02; /* 0x407DA874, 0xE79FE763 */ +const SB7: f64 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ + +fn erfc1(x: f64) -> f64 { + let s: f64; + let p: f64; + let q: f64; + + s = fabs(x) - 1.0; + p = PA0 + s * (PA1 + s * (PA2 + s * (PA3 + s * (PA4 + s * (PA5 + s * PA6))))); + q = 1.0 + s * (QA1 + s * (QA2 + s * (QA3 + s * (QA4 + s * (QA5 + s * QA6))))); + + 1.0 - ERX - p / q +} + +fn erfc2(ix: u32, mut x: f64) -> f64 { + let s: f64; + let r: f64; + let big_s: f64; + let z: f64; + + if ix < 0x3ff40000 { + /* |x| < 1.25 */ + return erfc1(x); + } + + x = fabs(x); + s = 1.0 / (x * x); + if ix < 0x4006db6d { + /* |x| < 1/.35 ~ 2.85714 */ + r = RA0 + s * (RA1 + s * (RA2 + s * (RA3 + s * (RA4 + s * (RA5 + s * (RA6 + s * RA7)))))); + big_s = 1.0 + + s * (SA1 + + s * (SA2 + s * (SA3 + s * (SA4 + s * (SA5 + s * (SA6 + s * (SA7 + s * SA8))))))); + } else { + /* |x| > 1/.35 */ + r = RB0 + s * (RB1 + s * (RB2 + s * (RB3 + s * (RB4 + s * (RB5 + s * RB6))))); + big_s = + 1.0 + s * (SB1 + s * (SB2 + s * (SB3 + s * (SB4 + s * (SB5 + s * (SB6 + s * SB7)))))); + } + z = with_set_low_word(x, 0); + + exp(-z * z - 0.5625) * exp((z - x) * (z + x) + r / big_s) / x +} + +/// Error function (f64) +/// +/// Calculates an approximation to the “error function”, which estimates +/// the probability that an observation will fall within x standard +/// deviations of the mean (assuming a normal distribution). +pub fn erf(x: f64) -> f64 { + let r: f64; + let s: f64; + let z: f64; + let y: f64; + let mut ix: u32; + let sign: usize; + + ix = get_high_word(x); + sign = (ix >> 31) as usize; + ix &= 0x7fffffff; + if ix >= 0x7ff00000 { + /* erf(nan)=nan, erf(+-inf)=+-1 */ + return 1.0 - 2.0 * (sign as f64) + 1.0 / x; + } + if ix < 0x3feb0000 { + /* |x| < 0.84375 */ + if ix < 0x3e300000 { + /* |x| < 2**-28 */ + /* avoid underflow */ + return 0.125 * (8.0 * x + EFX8 * x); + } + z = x * x; + r = PP0 + z * (PP1 + z * (PP2 + z * (PP3 + z * PP4))); + s = 1.0 + z * (QQ1 + z * (QQ2 + z * (QQ3 + z * (QQ4 + z * QQ5)))); + y = r / s; + return x + x * y; + } + if ix < 0x40180000 { + /* 0.84375 <= |x| < 6 */ + y = 1.0 - erfc2(ix, x); + } else { + let x1p_1022 = f64::from_bits(0x0010000000000000); + y = 1.0 - x1p_1022; + } + + if sign != 0 { + -y + } else { + y + } +} + +/// Error function (f64) +/// +/// Calculates the complementary probability. +/// Is `1 - erf(x)`. Is computed directly, so that you can use it to avoid +/// the loss of precision that would result from subtracting +/// large probabilities (on large `x`) from 1. +pub fn erfc(x: f64) -> f64 { + let r: f64; + let s: f64; + let z: f64; + let y: f64; + let mut ix: u32; + let sign: usize; + + ix = get_high_word(x); + sign = (ix >> 31) as usize; + ix &= 0x7fffffff; + if ix >= 0x7ff00000 { + /* erfc(nan)=nan, erfc(+-inf)=0,2 */ + return 2.0 * (sign as f64) + 1.0 / x; + } + if ix < 0x3feb0000 { + /* |x| < 0.84375 */ + if ix < 0x3c700000 { + /* |x| < 2**-56 */ + return 1.0 - x; + } + z = x * x; + r = PP0 + z * (PP1 + z * (PP2 + z * (PP3 + z * PP4))); + s = 1.0 + z * (QQ1 + z * (QQ2 + z * (QQ3 + z * (QQ4 + z * QQ5)))); + y = r / s; + if sign != 0 || ix < 0x3fd00000 { + /* x < 1/4 */ + return 1.0 - (x + x * y); + } + return 0.5 - (x - 0.5 + x * y); + } + if ix < 0x403c0000 { + /* 0.84375 <= |x| < 28 */ + if sign != 0 { + return 2.0 - erfc2(ix, x); + } else { + return erfc2(ix, x); + } + } + + let x1p_1022 = f64::from_bits(0x0010000000000000); + if sign != 0 { + 2.0 - x1p_1022 + } else { + x1p_1022 * x1p_1022 + } +} diff --git a/vendor/libm/src/math/erff.rs b/vendor/libm/src/math/erff.rs new file mode 100644 index 0000000000..384052293f --- /dev/null +++ b/vendor/libm/src/math/erff.rs @@ -0,0 +1,229 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_erff.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{expf, fabsf}; + +const ERX: f32 = 8.4506291151e-01; /* 0x3f58560b */ +/* + * Coefficients for approximation to erf on [0,0.84375] + */ +const EFX8: f32 = 1.0270333290e+00; /* 0x3f8375d4 */ +const PP0: f32 = 1.2837916613e-01; /* 0x3e0375d4 */ +const PP1: f32 = -3.2504209876e-01; /* 0xbea66beb */ +const PP2: f32 = -2.8481749818e-02; /* 0xbce9528f */ +const PP3: f32 = -5.7702702470e-03; /* 0xbbbd1489 */ +const PP4: f32 = -2.3763017452e-05; /* 0xb7c756b1 */ +const QQ1: f32 = 3.9791721106e-01; /* 0x3ecbbbce */ +const QQ2: f32 = 6.5022252500e-02; /* 0x3d852a63 */ +const QQ3: f32 = 5.0813062117e-03; /* 0x3ba68116 */ +const QQ4: f32 = 1.3249473704e-04; /* 0x390aee49 */ +const QQ5: f32 = -3.9602282413e-06; /* 0xb684e21a */ +/* + * Coefficients for approximation to erf in [0.84375,1.25] + */ +const PA0: f32 = -2.3621185683e-03; /* 0xbb1acdc6 */ +const PA1: f32 = 4.1485610604e-01; /* 0x3ed46805 */ +const PA2: f32 = -3.7220788002e-01; /* 0xbebe9208 */ +const PA3: f32 = 3.1834661961e-01; /* 0x3ea2fe54 */ +const PA4: f32 = -1.1089469492e-01; /* 0xbde31cc2 */ +const PA5: f32 = 3.5478305072e-02; /* 0x3d1151b3 */ +const PA6: f32 = -2.1663755178e-03; /* 0xbb0df9c0 */ +const QA1: f32 = 1.0642088205e-01; /* 0x3dd9f331 */ +const QA2: f32 = 5.4039794207e-01; /* 0x3f0a5785 */ +const QA3: f32 = 7.1828655899e-02; /* 0x3d931ae7 */ +const QA4: f32 = 1.2617121637e-01; /* 0x3e013307 */ +const QA5: f32 = 1.3637083583e-02; /* 0x3c5f6e13 */ +const QA6: f32 = 1.1984500103e-02; /* 0x3c445aa3 */ +/* + * Coefficients for approximation to erfc in [1.25,1/0.35] + */ +const RA0: f32 = -9.8649440333e-03; /* 0xbc21a093 */ +const RA1: f32 = -6.9385856390e-01; /* 0xbf31a0b7 */ +const RA2: f32 = -1.0558626175e+01; /* 0xc128f022 */ +const RA3: f32 = -6.2375331879e+01; /* 0xc2798057 */ +const RA4: f32 = -1.6239666748e+02; /* 0xc322658c */ +const RA5: f32 = -1.8460508728e+02; /* 0xc3389ae7 */ +const RA6: f32 = -8.1287437439e+01; /* 0xc2a2932b */ +const RA7: f32 = -9.8143291473e+00; /* 0xc11d077e */ +const SA1: f32 = 1.9651271820e+01; /* 0x419d35ce */ +const SA2: f32 = 1.3765776062e+02; /* 0x4309a863 */ +const SA3: f32 = 4.3456588745e+02; /* 0x43d9486f */ +const SA4: f32 = 6.4538726807e+02; /* 0x442158c9 */ +const SA5: f32 = 4.2900814819e+02; /* 0x43d6810b */ +const SA6: f32 = 1.0863500214e+02; /* 0x42d9451f */ +const SA7: f32 = 6.5702495575e+00; /* 0x40d23f7c */ +const SA8: f32 = -6.0424413532e-02; /* 0xbd777f97 */ +/* + * Coefficients for approximation to erfc in [1/.35,28] + */ +const RB0: f32 = -9.8649431020e-03; /* 0xbc21a092 */ +const RB1: f32 = -7.9928326607e-01; /* 0xbf4c9dd4 */ +const RB2: f32 = -1.7757955551e+01; /* 0xc18e104b */ +const RB3: f32 = -1.6063638306e+02; /* 0xc320a2ea */ +const RB4: f32 = -6.3756646729e+02; /* 0xc41f6441 */ +const RB5: f32 = -1.0250950928e+03; /* 0xc480230b */ +const RB6: f32 = -4.8351919556e+02; /* 0xc3f1c275 */ +const SB1: f32 = 3.0338060379e+01; /* 0x41f2b459 */ +const SB2: f32 = 3.2579251099e+02; /* 0x43a2e571 */ +const SB3: f32 = 1.5367296143e+03; /* 0x44c01759 */ +const SB4: f32 = 3.1998581543e+03; /* 0x4547fdbb */ +const SB5: f32 = 2.5530502930e+03; /* 0x451f90ce */ +const SB6: f32 = 4.7452853394e+02; /* 0x43ed43a7 */ +const SB7: f32 = -2.2440952301e+01; /* 0xc1b38712 */ + +fn erfc1(x: f32) -> f32 { + let s: f32; + let p: f32; + let q: f32; + + s = fabsf(x) - 1.0; + p = PA0 + s * (PA1 + s * (PA2 + s * (PA3 + s * (PA4 + s * (PA5 + s * PA6))))); + q = 1.0 + s * (QA1 + s * (QA2 + s * (QA3 + s * (QA4 + s * (QA5 + s * QA6))))); + return 1.0 - ERX - p / q; +} + +fn erfc2(mut ix: u32, mut x: f32) -> f32 { + let s: f32; + let r: f32; + let big_s: f32; + let z: f32; + + if ix < 0x3fa00000 { + /* |x| < 1.25 */ + return erfc1(x); + } + + x = fabsf(x); + s = 1.0 / (x * x); + if ix < 0x4036db6d { + /* |x| < 1/0.35 */ + r = RA0 + s * (RA1 + s * (RA2 + s * (RA3 + s * (RA4 + s * (RA5 + s * (RA6 + s * RA7)))))); + big_s = 1.0 + + s * (SA1 + + s * (SA2 + s * (SA3 + s * (SA4 + s * (SA5 + s * (SA6 + s * (SA7 + s * SA8))))))); + } else { + /* |x| >= 1/0.35 */ + r = RB0 + s * (RB1 + s * (RB2 + s * (RB3 + s * (RB4 + s * (RB5 + s * RB6))))); + big_s = + 1.0 + s * (SB1 + s * (SB2 + s * (SB3 + s * (SB4 + s * (SB5 + s * (SB6 + s * SB7)))))); + } + ix = x.to_bits(); + z = f32::from_bits(ix & 0xffffe000); + + expf(-z * z - 0.5625) * expf((z - x) * (z + x) + r / big_s) / x +} + +/// Error function (f32) +/// +/// Calculates an approximation to the “error function”, which estimates +/// the probability that an observation will fall within x standard +/// deviations of the mean (assuming a normal distribution). +pub fn erff(x: f32) -> f32 { + let r: f32; + let s: f32; + let z: f32; + let y: f32; + let mut ix: u32; + let sign: usize; + + ix = x.to_bits(); + sign = (ix >> 31) as usize; + ix &= 0x7fffffff; + if ix >= 0x7f800000 { + /* erf(nan)=nan, erf(+-inf)=+-1 */ + return 1.0 - 2.0 * (sign as f32) + 1.0 / x; + } + if ix < 0x3f580000 { + /* |x| < 0.84375 */ + if ix < 0x31800000 { + /* |x| < 2**-28 */ + /*avoid underflow */ + return 0.125 * (8.0 * x + EFX8 * x); + } + z = x * x; + r = PP0 + z * (PP1 + z * (PP2 + z * (PP3 + z * PP4))); + s = 1.0 + z * (QQ1 + z * (QQ2 + z * (QQ3 + z * (QQ4 + z * QQ5)))); + y = r / s; + return x + x * y; + } + if ix < 0x40c00000 { + /* |x| < 6 */ + y = 1.0 - erfc2(ix, x); + } else { + let x1p_120 = f32::from_bits(0x03800000); + y = 1.0 - x1p_120; + } + + if sign != 0 { + -y + } else { + y + } +} + +/// Error function (f32) +/// +/// Calculates the complementary probability. +/// Is `1 - erf(x)`. Is computed directly, so that you can use it to avoid +/// the loss of precision that would result from subtracting +/// large probabilities (on large `x`) from 1. +pub fn erfcf(x: f32) -> f32 { + let r: f32; + let s: f32; + let z: f32; + let y: f32; + let mut ix: u32; + let sign: usize; + + ix = x.to_bits(); + sign = (ix >> 31) as usize; + ix &= 0x7fffffff; + if ix >= 0x7f800000 { + /* erfc(nan)=nan, erfc(+-inf)=0,2 */ + return 2.0 * (sign as f32) + 1.0 / x; + } + + if ix < 0x3f580000 { + /* |x| < 0.84375 */ + if ix < 0x23800000 { + /* |x| < 2**-56 */ + return 1.0 - x; + } + z = x * x; + r = PP0 + z * (PP1 + z * (PP2 + z * (PP3 + z * PP4))); + s = 1.0 + z * (QQ1 + z * (QQ2 + z * (QQ3 + z * (QQ4 + z * QQ5)))); + y = r / s; + if sign != 0 || ix < 0x3e800000 { + /* x < 1/4 */ + return 1.0 - (x + x * y); + } + return 0.5 - (x - 0.5 + x * y); + } + if ix < 0x41e00000 { + /* |x| < 28 */ + if sign != 0 { + return 2.0 - erfc2(ix, x); + } else { + return erfc2(ix, x); + } + } + + let x1p_120 = f32::from_bits(0x03800000); + if sign != 0 { + 2.0 - x1p_120 + } else { + x1p_120 * x1p_120 + } +} diff --git a/vendor/libm/src/math/exp.rs b/vendor/libm/src/math/exp.rs new file mode 100644 index 0000000000..5465b56934 --- /dev/null +++ b/vendor/libm/src/math/exp.rs @@ -0,0 +1,155 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_exp.c */ +/* + * ==================================================== + * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. + * + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* exp(x) + * Returns the exponential of x. + * + * Method + * 1. Argument reduction: + * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. + * Given x, find r and integer k such that + * + * x = k*ln2 + r, |r| <= 0.5*ln2. + * + * Here r will be represented as r = hi-lo for better + * accuracy. + * + * 2. Approximation of exp(r) by a special rational function on + * the interval [0,0.34658]: + * Write + * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... + * We use a special Remez algorithm on [0,0.34658] to generate + * a polynomial of degree 5 to approximate R. The maximum error + * of this polynomial approximation is bounded by 2**-59. In + * other words, + * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 + * (where z=r*r, and the values of P1 to P5 are listed below) + * and + * | 5 | -59 + * | 2.0+P1*z+...+P5*z - R(z) | <= 2 + * | | + * The computation of exp(r) thus becomes + * 2*r + * exp(r) = 1 + ---------- + * R(r) - r + * r*c(r) + * = 1 + r + ----------- (for better accuracy) + * 2 - c(r) + * where + * 2 4 10 + * c(r) = r - (P1*r + P2*r + ... + P5*r ). + * + * 3. Scale back to obtain exp(x): + * From step 1, we have + * exp(x) = 2^k * exp(r) + * + * Special cases: + * exp(INF) is INF, exp(NaN) is NaN; + * exp(-INF) is 0, and + * for finite argument, only exp(0)=1 is exact. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Misc. info. + * For IEEE double + * if x > 709.782712893383973096 then exp(x) overflows + * if x < -745.133219101941108420 then exp(x) underflows + */ + +use super::scalbn; + +const HALF: [f64; 2] = [0.5, -0.5]; +const LN2HI: f64 = 6.93147180369123816490e-01; /* 0x3fe62e42, 0xfee00000 */ +const LN2LO: f64 = 1.90821492927058770002e-10; /* 0x3dea39ef, 0x35793c76 */ +const INVLN2: f64 = 1.44269504088896338700e+00; /* 0x3ff71547, 0x652b82fe */ +const P1: f64 = 1.66666666666666019037e-01; /* 0x3FC55555, 0x5555553E */ +const P2: f64 = -2.77777777770155933842e-03; /* 0xBF66C16C, 0x16BEBD93 */ +const P3: f64 = 6.61375632143793436117e-05; /* 0x3F11566A, 0xAF25DE2C */ +const P4: f64 = -1.65339022054652515390e-06; /* 0xBEBBBD41, 0xC5D26BF1 */ +const P5: f64 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ + +/// Exponential, base *e* (f64) +/// +/// Calculate the exponential of `x`, that is, *e* raised to the power `x` +/// (where *e* is the base of the natural system of logarithms, approximately 2.71828). +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn exp(mut x: f64) -> f64 { + let x1p1023 = f64::from_bits(0x7fe0000000000000); // 0x1p1023 === 2 ^ 1023 + let x1p_149 = f64::from_bits(0x36a0000000000000); // 0x1p-149 === 2 ^ -149 + + let hi: f64; + let lo: f64; + let c: f64; + let xx: f64; + let y: f64; + let k: i32; + let sign: i32; + let mut hx: u32; + + hx = (x.to_bits() >> 32) as u32; + sign = (hx >> 31) as i32; + hx &= 0x7fffffff; /* high word of |x| */ + + /* special cases */ + if hx >= 0x4086232b { + /* if |x| >= 708.39... */ + if x.is_nan() { + return x; + } + if x > 709.782712893383973096 { + /* overflow if x!=inf */ + x *= x1p1023; + return x; + } + if x < -708.39641853226410622 { + /* underflow if x!=-inf */ + force_eval!((-x1p_149 / x) as f32); + if x < -745.13321910194110842 { + return 0.; + } + } + } + + /* argument reduction */ + if hx > 0x3fd62e42 { + /* if |x| > 0.5 ln2 */ + if hx >= 0x3ff0a2b2 { + /* if |x| >= 1.5 ln2 */ + k = (INVLN2 * x + HALF[sign as usize]) as i32; + } else { + k = 1 - sign - sign; + } + hi = x - k as f64 * LN2HI; /* k*ln2hi is exact here */ + lo = k as f64 * LN2LO; + x = hi - lo; + } else if hx > 0x3e300000 { + /* if |x| > 2**-28 */ + k = 0; + hi = x; + lo = 0.; + } else { + /* inexact if x!=0 */ + force_eval!(x1p1023 + x); + return 1. + x; + } + + /* x is now in primary range */ + xx = x * x; + c = x - xx * (P1 + xx * (P2 + xx * (P3 + xx * (P4 + xx * P5)))); + y = 1. + (x * c / (2. - c) - lo + hi); + if k == 0 { + y + } else { + scalbn(y, k) + } +} diff --git a/vendor/libm/src/math/exp10.rs b/vendor/libm/src/math/exp10.rs new file mode 100644 index 0000000000..9537f76f13 --- /dev/null +++ b/vendor/libm/src/math/exp10.rs @@ -0,0 +1,21 @@ +use super::{exp2, modf, pow}; + +const LN10: f64 = 3.32192809488736234787031942948939; +const P10: &[f64] = &[ + 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, +]; + +pub fn exp10(x: f64) -> f64 { + let (mut y, n) = modf(x); + let u: u64 = n.to_bits(); + /* fabs(n) < 16 without raising invalid on nan */ + if (u >> 52 & 0x7ff) < 0x3ff + 4 { + if y == 0.0 { + return P10[((n as isize) + 15) as usize]; + } + y = exp2(LN10 * y); + return y * P10[((n as isize) + 15) as usize]; + } + return pow(10.0, x); +} diff --git a/vendor/libm/src/math/exp10f.rs b/vendor/libm/src/math/exp10f.rs new file mode 100644 index 0000000000..d45fff36ea --- /dev/null +++ b/vendor/libm/src/math/exp10f.rs @@ -0,0 +1,21 @@ +use super::{exp2, exp2f, modff}; + +const LN10_F32: f32 = 3.32192809488736234787031942948939; +const LN10_F64: f64 = 3.32192809488736234787031942948939; +const P10: &[f32] = &[ + 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, +]; + +pub fn exp10f(x: f32) -> f32 { + let (mut y, n) = modff(x); + let u = n.to_bits(); + /* fabsf(n) < 8 without raising invalid on nan */ + if (u >> 23 & 0xff) < 0x7f + 3 { + if y == 0.0 { + return P10[((n as isize) + 7) as usize]; + } + y = exp2f(LN10_F32 * y); + return y * P10[((n as isize) + 7) as usize]; + } + return exp2(LN10_F64 * (x as f64)) as f32; +} diff --git a/vendor/libm/src/math/exp2.rs b/vendor/libm/src/math/exp2.rs new file mode 100644 index 0000000000..c2192fde5a --- /dev/null +++ b/vendor/libm/src/math/exp2.rs @@ -0,0 +1,395 @@ +// origin: FreeBSD /usr/src/lib/msun/src/s_exp2.c */ +//- +// Copyright (c) 2005 David Schultz +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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. + +use super::scalbn; + +const TBLSIZE: usize = 256; + +#[cfg_attr(rustfmt, rustfmt_skip)] +static TBL: [u64; TBLSIZE * 2] = [ + // exp2(z + eps) eps + 0x3fe6a09e667f3d5d, 0x3d39880000000000, + 0x3fe6b052fa751744, 0x3cd8000000000000, + 0x3fe6c012750bd9fe, 0xbd28780000000000, + 0x3fe6cfdcddd476bf, 0x3d1ec00000000000, + 0x3fe6dfb23c651a29, 0xbcd8000000000000, + 0x3fe6ef9298593ae3, 0xbcbc000000000000, + 0x3fe6ff7df9519386, 0xbd2fd80000000000, + 0x3fe70f7466f42da3, 0xbd2c880000000000, + 0x3fe71f75e8ec5fc3, 0x3d13c00000000000, + 0x3fe72f8286eacf05, 0xbd38300000000000, + 0x3fe73f9a48a58152, 0xbd00c00000000000, + 0x3fe74fbd35d7ccfc, 0x3d2f880000000000, + 0x3fe75feb564267f1, 0x3d03e00000000000, + 0x3fe77024b1ab6d48, 0xbd27d00000000000, + 0x3fe780694fde5d38, 0xbcdd000000000000, + 0x3fe790b938ac1d00, 0x3ce3000000000000, + 0x3fe7a11473eb0178, 0xbced000000000000, + 0x3fe7b17b0976d060, 0x3d20400000000000, + 0x3fe7c1ed0130c133, 0x3ca0000000000000, + 0x3fe7d26a62ff8636, 0xbd26900000000000, + 0x3fe7e2f336cf4e3b, 0xbd02e00000000000, + 0x3fe7f3878491c3e8, 0xbd24580000000000, + 0x3fe80427543e1b4e, 0x3d33000000000000, + 0x3fe814d2add1071a, 0x3d0f000000000000, + 0x3fe82589994ccd7e, 0xbd21c00000000000, + 0x3fe8364c1eb942d0, 0x3d29d00000000000, + 0x3fe8471a4623cab5, 0x3d47100000000000, + 0x3fe857f4179f5bbc, 0x3d22600000000000, + 0x3fe868d99b4491af, 0xbd32c40000000000, + 0x3fe879cad931a395, 0xbd23000000000000, + 0x3fe88ac7d98a65b8, 0xbd2a800000000000, + 0x3fe89bd0a4785800, 0xbced000000000000, + 0x3fe8ace5422aa223, 0x3d33280000000000, + 0x3fe8be05bad619fa, 0x3d42b40000000000, + 0x3fe8cf3216b54383, 0xbd2ed00000000000, + 0x3fe8e06a5e08664c, 0xbd20500000000000, + 0x3fe8f1ae99157807, 0x3d28280000000000, + 0x3fe902fed0282c0e, 0xbd1cb00000000000, + 0x3fe9145b0b91ff96, 0xbd05e00000000000, + 0x3fe925c353aa2ff9, 0x3cf5400000000000, + 0x3fe93737b0cdc64a, 0x3d17200000000000, + 0x3fe948b82b5f98ae, 0xbd09000000000000, + 0x3fe95a44cbc852cb, 0x3d25680000000000, + 0x3fe96bdd9a766f21, 0xbd36d00000000000, + 0x3fe97d829fde4e2a, 0xbd01000000000000, + 0x3fe98f33e47a23a3, 0x3d2d000000000000, + 0x3fe9a0f170ca0604, 0xbd38a40000000000, + 0x3fe9b2bb4d53ff89, 0x3d355c0000000000, + 0x3fe9c49182a3f15b, 0x3d26b80000000000, + 0x3fe9d674194bb8c5, 0xbcec000000000000, + 0x3fe9e86319e3238e, 0x3d17d00000000000, + 0x3fe9fa5e8d07f302, 0x3d16400000000000, + 0x3fea0c667b5de54d, 0xbcf5000000000000, + 0x3fea1e7aed8eb8f6, 0x3d09e00000000000, + 0x3fea309bec4a2e27, 0x3d2ad80000000000, + 0x3fea42c980460a5d, 0xbd1af00000000000, + 0x3fea5503b23e259b, 0x3d0b600000000000, + 0x3fea674a8af46213, 0x3d38880000000000, + 0x3fea799e1330b3a7, 0x3d11200000000000, + 0x3fea8bfe53c12e8d, 0x3d06c00000000000, + 0x3fea9e6b5579fcd2, 0xbd29b80000000000, + 0x3feab0e521356fb8, 0x3d2b700000000000, + 0x3feac36bbfd3f381, 0x3cd9000000000000, + 0x3fead5ff3a3c2780, 0x3ce4000000000000, + 0x3feae89f995ad2a3, 0xbd2c900000000000, + 0x3feafb4ce622f367, 0x3d16500000000000, + 0x3feb0e07298db790, 0x3d2fd40000000000, + 0x3feb20ce6c9a89a9, 0x3d12700000000000, + 0x3feb33a2b84f1a4b, 0x3d4d470000000000, + 0x3feb468415b747e7, 0xbd38380000000000, + 0x3feb59728de5593a, 0x3c98000000000000, + 0x3feb6c6e29f1c56a, 0x3d0ad00000000000, + 0x3feb7f76f2fb5e50, 0x3cde800000000000, + 0x3feb928cf22749b2, 0xbd04c00000000000, + 0x3feba5b030a10603, 0xbd0d700000000000, + 0x3febb8e0b79a6f66, 0x3d0d900000000000, + 0x3febcc1e904bc1ff, 0x3d02a00000000000, + 0x3febdf69c3f3a16f, 0xbd1f780000000000, + 0x3febf2c25bd71db8, 0xbd10a00000000000, + 0x3fec06286141b2e9, 0xbd11400000000000, + 0x3fec199bdd8552e0, 0x3d0be00000000000, + 0x3fec2d1cd9fa64ee, 0xbd09400000000000, + 0x3fec40ab5fffd02f, 0xbd0ed00000000000, + 0x3fec544778fafd15, 0x3d39660000000000, + 0x3fec67f12e57d0cb, 0xbd1a100000000000, + 0x3fec7ba88988c1b6, 0xbd58458000000000, + 0x3fec8f6d9406e733, 0xbd1a480000000000, + 0x3feca3405751c4df, 0x3ccb000000000000, + 0x3fecb720dcef9094, 0x3d01400000000000, + 0x3feccb0f2e6d1689, 0x3cf0200000000000, + 0x3fecdf0b555dc412, 0x3cf3600000000000, + 0x3fecf3155b5bab3b, 0xbd06900000000000, + 0x3fed072d4a0789bc, 0x3d09a00000000000, + 0x3fed1b532b08c8fa, 0xbd15e00000000000, + 0x3fed2f87080d8a85, 0x3d1d280000000000, + 0x3fed43c8eacaa203, 0x3d01a00000000000, + 0x3fed5818dcfba491, 0x3cdf000000000000, + 0x3fed6c76e862e6a1, 0xbd03a00000000000, + 0x3fed80e316c9834e, 0xbd0cd80000000000, + 0x3fed955d71ff6090, 0x3cf4c00000000000, + 0x3feda9e603db32ae, 0x3cff900000000000, + 0x3fedbe7cd63a8325, 0x3ce9800000000000, + 0x3fedd321f301b445, 0xbcf5200000000000, + 0x3fede7d5641c05bf, 0xbd1d700000000000, + 0x3fedfc97337b9aec, 0xbd16140000000000, + 0x3fee11676b197d5e, 0x3d0b480000000000, + 0x3fee264614f5a3e7, 0x3d40ce0000000000, + 0x3fee3b333b16ee5c, 0x3d0c680000000000, + 0x3fee502ee78b3fb4, 0xbd09300000000000, + 0x3fee653924676d68, 0xbce5000000000000, + 0x3fee7a51fbc74c44, 0xbd07f80000000000, + 0x3fee8f7977cdb726, 0xbcf3700000000000, + 0x3feea4afa2a490e8, 0x3ce5d00000000000, + 0x3feeb9f4867ccae4, 0x3d161a0000000000, + 0x3feecf482d8e680d, 0x3cf5500000000000, + 0x3feee4aaa2188514, 0x3cc6400000000000, + 0x3feefa1bee615a13, 0xbcee800000000000, + 0x3fef0f9c1cb64106, 0xbcfa880000000000, + 0x3fef252b376bb963, 0xbd2c900000000000, + 0x3fef3ac948dd7275, 0x3caa000000000000, + 0x3fef50765b6e4524, 0xbcf4f00000000000, + 0x3fef6632798844fd, 0x3cca800000000000, + 0x3fef7bfdad9cbe38, 0x3cfabc0000000000, + 0x3fef91d802243c82, 0xbcd4600000000000, + 0x3fefa7c1819e908e, 0xbd0b0c0000000000, + 0x3fefbdba3692d511, 0xbcc0e00000000000, + 0x3fefd3c22b8f7194, 0xbd10de8000000000, + 0x3fefe9d96b2a23ee, 0x3cee430000000000, + 0x3ff0000000000000, 0x0, + 0x3ff00b1afa5abcbe, 0xbcb3400000000000, + 0x3ff0163da9fb3303, 0xbd12170000000000, + 0x3ff02168143b0282, 0x3cba400000000000, + 0x3ff02c9a3e77806c, 0x3cef980000000000, + 0x3ff037d42e11bbca, 0xbcc7400000000000, + 0x3ff04315e86e7f89, 0x3cd8300000000000, + 0x3ff04e5f72f65467, 0xbd1a3f0000000000, + 0x3ff059b0d315855a, 0xbd02840000000000, + 0x3ff0650a0e3c1f95, 0x3cf1600000000000, + 0x3ff0706b29ddf71a, 0x3d15240000000000, + 0x3ff07bd42b72a82d, 0xbce9a00000000000, + 0x3ff0874518759bd0, 0x3ce6400000000000, + 0x3ff092bdf66607c8, 0xbd00780000000000, + 0x3ff09e3ecac6f383, 0xbc98000000000000, + 0x3ff0a9c79b1f3930, 0x3cffa00000000000, + 0x3ff0b5586cf988fc, 0xbcfac80000000000, + 0x3ff0c0f145e46c8a, 0x3cd9c00000000000, + 0x3ff0cc922b724816, 0x3d05200000000000, + 0x3ff0d83b23395dd8, 0xbcfad00000000000, + 0x3ff0e3ec32d3d1f3, 0x3d1bac0000000000, + 0x3ff0efa55fdfa9a6, 0xbd04e80000000000, + 0x3ff0fb66affed2f0, 0xbd0d300000000000, + 0x3ff1073028d7234b, 0x3cf1500000000000, + 0x3ff11301d0125b5b, 0x3cec000000000000, + 0x3ff11edbab5e2af9, 0x3d16bc0000000000, + 0x3ff12abdc06c31d5, 0x3ce8400000000000, + 0x3ff136a814f2047d, 0xbd0ed00000000000, + 0x3ff1429aaea92de9, 0x3ce8e00000000000, + 0x3ff14e95934f3138, 0x3ceb400000000000, + 0x3ff15a98c8a58e71, 0x3d05300000000000, + 0x3ff166a45471c3df, 0x3d03380000000000, + 0x3ff172b83c7d5211, 0x3d28d40000000000, + 0x3ff17ed48695bb9f, 0xbd05d00000000000, + 0x3ff18af9388c8d93, 0xbd1c880000000000, + 0x3ff1972658375d66, 0x3d11f00000000000, + 0x3ff1a35beb6fcba7, 0x3d10480000000000, + 0x3ff1af99f81387e3, 0xbd47390000000000, + 0x3ff1bbe084045d54, 0x3d24e40000000000, + 0x3ff1c82f95281c43, 0xbd0a200000000000, + 0x3ff1d4873168b9b2, 0x3ce3800000000000, + 0x3ff1e0e75eb44031, 0x3ceac00000000000, + 0x3ff1ed5022fcd938, 0x3d01900000000000, + 0x3ff1f9c18438cdf7, 0xbd1b780000000000, + 0x3ff2063b88628d8f, 0x3d2d940000000000, + 0x3ff212be3578a81e, 0x3cd8000000000000, + 0x3ff21f49917ddd41, 0x3d2b340000000000, + 0x3ff22bdda2791323, 0x3d19f80000000000, + 0x3ff2387a6e7561e7, 0xbd19c80000000000, + 0x3ff2451ffb821427, 0x3d02300000000000, + 0x3ff251ce4fb2a602, 0xbd13480000000000, + 0x3ff25e85711eceb0, 0x3d12700000000000, + 0x3ff26b4565e27d16, 0x3d11d00000000000, + 0x3ff2780e341de00f, 0x3d31ee0000000000, + 0x3ff284dfe1f5633e, 0xbd14c00000000000, + 0x3ff291ba7591bb30, 0xbd13d80000000000, + 0x3ff29e9df51fdf09, 0x3d08b00000000000, + 0x3ff2ab8a66d10e9b, 0xbd227c0000000000, + 0x3ff2b87fd0dada3a, 0x3d2a340000000000, + 0x3ff2c57e39771af9, 0xbd10800000000000, + 0x3ff2d285a6e402d9, 0xbd0ed00000000000, + 0x3ff2df961f641579, 0xbcf4200000000000, + 0x3ff2ecafa93e2ecf, 0xbd24980000000000, + 0x3ff2f9d24abd8822, 0xbd16300000000000, + 0x3ff306fe0a31b625, 0xbd32360000000000, + 0x3ff31432edeea50b, 0xbd70df8000000000, + 0x3ff32170fc4cd7b8, 0xbd22480000000000, + 0x3ff32eb83ba8e9a2, 0xbd25980000000000, + 0x3ff33c08b2641766, 0x3d1ed00000000000, + 0x3ff3496266e3fa27, 0xbcdc000000000000, + 0x3ff356c55f929f0f, 0xbd30d80000000000, + 0x3ff36431a2de88b9, 0x3d22c80000000000, + 0x3ff371a7373aaa39, 0x3d20600000000000, + 0x3ff37f26231e74fe, 0xbd16600000000000, + 0x3ff38cae6d05d838, 0xbd0ae00000000000, + 0x3ff39a401b713ec3, 0xbd44720000000000, + 0x3ff3a7db34e5a020, 0x3d08200000000000, + 0x3ff3b57fbfec6e95, 0x3d3e800000000000, + 0x3ff3c32dc313a8f2, 0x3cef800000000000, + 0x3ff3d0e544ede122, 0xbd17a00000000000, + 0x3ff3dea64c1234bb, 0x3d26300000000000, + 0x3ff3ec70df1c4ecc, 0xbd48a60000000000, + 0x3ff3fa4504ac7e8c, 0xbd3cdc0000000000, + 0x3ff40822c367a0bb, 0x3d25b80000000000, + 0x3ff4160a21f72e95, 0x3d1ec00000000000, + 0x3ff423fb27094646, 0xbd13600000000000, + 0x3ff431f5d950a920, 0x3d23980000000000, + 0x3ff43ffa3f84b9eb, 0x3cfa000000000000, + 0x3ff44e0860618919, 0xbcf6c00000000000, + 0x3ff45c2042a7d201, 0xbd0bc00000000000, + 0x3ff46a41ed1d0016, 0xbd12800000000000, + 0x3ff4786d668b3326, 0x3d30e00000000000, + 0x3ff486a2b5c13c00, 0xbd2d400000000000, + 0x3ff494e1e192af04, 0x3d0c200000000000, + 0x3ff4a32af0d7d372, 0xbd1e500000000000, + 0x3ff4b17dea6db801, 0x3d07800000000000, + 0x3ff4bfdad53629e1, 0xbd13800000000000, + 0x3ff4ce41b817c132, 0x3d00800000000000, + 0x3ff4dcb299fddddb, 0x3d2c700000000000, + 0x3ff4eb2d81d8ab96, 0xbd1ce00000000000, + 0x3ff4f9b2769d2d02, 0x3d19200000000000, + 0x3ff508417f4531c1, 0xbd08c00000000000, + 0x3ff516daa2cf662a, 0xbcfa000000000000, + 0x3ff5257de83f51ea, 0x3d4a080000000000, + 0x3ff5342b569d4eda, 0xbd26d80000000000, + 0x3ff542e2f4f6ac1a, 0xbd32440000000000, + 0x3ff551a4ca5d94db, 0x3d483c0000000000, + 0x3ff56070dde9116b, 0x3d24b00000000000, + 0x3ff56f4736b529de, 0x3d415a0000000000, + 0x3ff57e27dbe2c40e, 0xbd29e00000000000, + 0x3ff58d12d497c76f, 0xbd23080000000000, + 0x3ff59c0827ff0b4c, 0x3d4dec0000000000, + 0x3ff5ab07dd485427, 0xbcc4000000000000, + 0x3ff5ba11fba87af4, 0x3d30080000000000, + 0x3ff5c9268a59460b, 0xbd26c80000000000, + 0x3ff5d84590998e3f, 0x3d469a0000000000, + 0x3ff5e76f15ad20e1, 0xbd1b400000000000, + 0x3ff5f6a320dcebca, 0x3d17700000000000, + 0x3ff605e1b976dcb8, 0x3d26f80000000000, + 0x3ff6152ae6cdf715, 0x3d01000000000000, + 0x3ff6247eb03a5531, 0xbd15d00000000000, + 0x3ff633dd1d1929b5, 0xbd12d00000000000, + 0x3ff6434634ccc313, 0xbcea800000000000, + 0x3ff652b9febc8efa, 0xbd28600000000000, + 0x3ff6623882553397, 0x3d71fe0000000000, + 0x3ff671c1c708328e, 0xbd37200000000000, + 0x3ff68155d44ca97e, 0x3ce6800000000000, + 0x3ff690f4b19e9471, 0xbd29780000000000, +]; + +// exp2(x): compute the base 2 exponential of x +// +// Accuracy: Peak error < 0.503 ulp for normalized results. +// +// Method: (accurate tables) +// +// Reduce x: +// x = k + y, for integer k and |y| <= 1/2. +// Thus we have exp2(x) = 2**k * exp2(y). +// +// Reduce y: +// y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE. +// Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]), +// with |z - eps[i]| <= 2**-9 + 2**-39 for the table used. +// +// We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via +// a degree-5 minimax polynomial with maximum error under 1.3 * 2**-61. +// The values in exp2t[] and eps[] are chosen such that +// exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such +// that exp2t[i] is accurate to 2**-64. +// +// Note that the range of i is +-TBLSIZE/2, so we actually index the tables +// by i0 = i + TBLSIZE/2. For cache efficiency, exp2t[] and eps[] are +// virtual tables, interleaved in the real table tbl[]. +// +// This method is due to Gal, with many details due to Gal and Bachelis: +// +// Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library +// for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991). + +/// Exponential, base 2 (f64) +/// +/// Calculate `2^x`, that is, 2 raised to the power `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn exp2(mut x: f64) -> f64 { + let redux = f64::from_bits(0x4338000000000000) / TBLSIZE as f64; + let p1 = f64::from_bits(0x3fe62e42fefa39ef); + let p2 = f64::from_bits(0x3fcebfbdff82c575); + let p3 = f64::from_bits(0x3fac6b08d704a0a6); + let p4 = f64::from_bits(0x3f83b2ab88f70400); + let p5 = f64::from_bits(0x3f55d88003875c74); + + // double_t r, t, z; + // uint32_t ix, i0; + // union {double f; uint64_t i;} u = {x}; + // union {uint32_t u; int32_t i;} k; + let x1p1023 = f64::from_bits(0x7fe0000000000000); + let x1p52 = f64::from_bits(0x4330000000000000); + let _0x1p_149 = f64::from_bits(0xb6a0000000000000); + + /* Filter out exceptional cases. */ + let ui = f64::to_bits(x); + let ix = ui >> 32 & 0x7fffffff; + if ix >= 0x408ff000 { + /* |x| >= 1022 or nan */ + if ix >= 0x40900000 && ui >> 63 == 0 { + /* x >= 1024 or nan */ + /* overflow */ + x *= x1p1023; + return x; + } + if ix >= 0x7ff00000 { + /* -inf or -nan */ + return -1.0 / x; + } + if ui >> 63 != 0 { + /* x <= -1022 */ + /* underflow */ + if x <= -1075.0 || x - x1p52 + x1p52 != x { + force_eval!((_0x1p_149 / x) as f32); + } + if x <= -1075.0 { + return 0.0; + } + } + } else if ix < 0x3c900000 { + /* |x| < 0x1p-54 */ + return 1.0 + x; + } + + /* Reduce x, computing z, i0, and k. */ + let ui = f64::to_bits(x + redux); + let mut i0 = ui as u32; + i0 = i0.wrapping_add(TBLSIZE as u32 / 2); + let ku = i0 / TBLSIZE as u32 * TBLSIZE as u32; + let ki = ku as i32 / TBLSIZE as i32; + i0 %= TBLSIZE as u32; + let uf = f64::from_bits(ui) - redux; + let mut z = x - uf; + + /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */ + let t = f64::from_bits(TBL[2 * i0 as usize]); /* exp2t[i0] */ + z -= f64::from_bits(TBL[2 * i0 as usize + 1]); /* eps[i0] */ + let r = t + t * z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * p5)))); + + scalbn(r, ki) +} + +#[test] +fn i0_wrap_test() { + let x = -3.0 / 256.0; + assert_eq!(exp2(x), f64::from_bits(0x3fefbdba3692d514)); +} diff --git a/vendor/libm/src/math/exp2f.rs b/vendor/libm/src/math/exp2f.rs new file mode 100644 index 0000000000..12c9e76a4c --- /dev/null +++ b/vendor/libm/src/math/exp2f.rs @@ -0,0 +1,136 @@ +// origin: FreeBSD /usr/src/lib/msun/src/s_exp2f.c +//- +// Copyright (c) 2005 David Schultz +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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. + +const TBLSIZE: usize = 16; + +static EXP2FT: [u64; TBLSIZE] = [ + 0x3fe6a09e667f3bcd, + 0x3fe7a11473eb0187, + 0x3fe8ace5422aa0db, + 0x3fe9c49182a3f090, + 0x3feae89f995ad3ad, + 0x3fec199bdd85529c, + 0x3fed5818dcfba487, + 0x3feea4afa2a490da, + 0x3ff0000000000000, + 0x3ff0b5586cf9890f, + 0x3ff172b83c7d517b, + 0x3ff2387a6e756238, + 0x3ff306fe0a31b715, + 0x3ff3dea64c123422, + 0x3ff4bfdad5362a27, + 0x3ff5ab07dd485429, +]; + +// exp2f(x): compute the base 2 exponential of x +// +// Accuracy: Peak error < 0.501 ulp; location of peak: -0.030110927. +// +// Method: (equally-spaced tables) +// +// Reduce x: +// x = k + y, for integer k and |y| <= 1/2. +// Thus we have exp2f(x) = 2**k * exp2(y). +// +// Reduce y: +// y = i/TBLSIZE + z for integer i near y * TBLSIZE. +// Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z), +// with |z| <= 2**-(TBLSIZE+1). +// +// We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a +// degree-4 minimax polynomial with maximum error under 1.4 * 2**-33. +// Using double precision for everything except the reduction makes +// roundoff error insignificant and simplifies the scaling step. +// +// This method is due to Tang, but I do not use his suggested parameters: +// +// Tang, P. Table-driven Implementation of the Exponential Function +// in IEEE Floating-Point Arithmetic. TOMS 15(2), 144-157 (1989). + +/// Exponential, base 2 (f32) +/// +/// Calculate `2^x`, that is, 2 raised to the power `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn exp2f(mut x: f32) -> f32 { + let redux = f32::from_bits(0x4b400000) / TBLSIZE as f32; + let p1 = f32::from_bits(0x3f317218); + let p2 = f32::from_bits(0x3e75fdf0); + let p3 = f32::from_bits(0x3d6359a4); + let p4 = f32::from_bits(0x3c1d964e); + + // double_t t, r, z; + // uint32_t ix, i0, k; + + let x1p127 = f32::from_bits(0x7f000000); + + /* Filter out exceptional cases. */ + let ui = f32::to_bits(x); + let ix = ui & 0x7fffffff; + if ix > 0x42fc0000 { + /* |x| > 126 */ + if ix > 0x7f800000 { + /* NaN */ + return x; + } + if ui >= 0x43000000 && ui < 0x80000000 { + /* x >= 128 */ + x *= x1p127; + return x; + } + if ui >= 0x80000000 { + /* x < -126 */ + if ui >= 0xc3160000 || (ui & 0x0000ffff != 0) { + force_eval!(f32::from_bits(0x80000001) / x); + } + if ui >= 0xc3160000 { + /* x <= -150 */ + return 0.0; + } + } + } else if ix <= 0x33000000 { + /* |x| <= 0x1p-25 */ + return 1.0 + x; + } + + /* Reduce x, computing z, i0, and k. */ + let ui = f32::to_bits(x + redux); + let mut i0 = ui; + i0 += TBLSIZE as u32 / 2; + let k = i0 / TBLSIZE as u32; + let ukf = f64::from_bits(((0x3ff + k) as u64) << 52); + i0 &= TBLSIZE as u32 - 1; + let mut uf = f32::from_bits(ui); + uf -= redux; + let z: f64 = (x - uf) as f64; + /* Compute r = exp2(y) = exp2ft[i0] * p(z). */ + let r: f64 = f64::from_bits(EXP2FT[i0 as usize]); + let t: f64 = r as f64 * z; + let r: f64 = r + t * (p1 as f64 + z * p2 as f64) + t * (z * z) * (p3 as f64 + z * p4 as f64); + + /* Scale by 2**k */ + (r * ukf) as f32 +} diff --git a/vendor/libm/src/math/expf.rs b/vendor/libm/src/math/expf.rs new file mode 100644 index 0000000000..09323ec8de --- /dev/null +++ b/vendor/libm/src/math/expf.rs @@ -0,0 +1,102 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_expf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::scalbnf; + +const HALF: [f32; 2] = [0.5, -0.5]; +const LN2_HI: f32 = 6.9314575195e-01; /* 0x3f317200 */ +const LN2_LO: f32 = 1.4286067653e-06; /* 0x35bfbe8e */ +const INV_LN2: f32 = 1.4426950216e+00; /* 0x3fb8aa3b */ +/* + * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]: + * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74 + */ +const P1: f32 = 1.6666625440e-1; /* 0xaaaa8f.0p-26 */ +const P2: f32 = -2.7667332906e-3; /* -0xb55215.0p-32 */ + +/// Exponential, base *e* (f32) +/// +/// Calculate the exponential of `x`, that is, *e* raised to the power `x` +/// (where *e* is the base of the natural system of logarithms, approximately 2.71828). +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn expf(mut x: f32) -> f32 { + let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127 + let x1p_126 = f32::from_bits(0x800000); // 0x1p-126f === 2 ^ -126 /*original 0x1p-149f ??????????? */ + let mut hx = x.to_bits(); + let sign = (hx >> 31) as i32; /* sign bit of x */ + let signb: bool = sign != 0; + hx &= 0x7fffffff; /* high word of |x| */ + + /* special cases */ + if hx >= 0x42aeac50 { + /* if |x| >= -87.33655f or NaN */ + if hx > 0x7f800000 { + /* NaN */ + return x; + } + if (hx >= 0x42b17218) && (!signb) { + /* x >= 88.722839f */ + /* overflow */ + x *= x1p127; + return x; + } + if signb { + /* underflow */ + force_eval!(-x1p_126 / x); + if hx >= 0x42cff1b5 { + /* x <= -103.972084f */ + return 0.; + } + } + } + + /* argument reduction */ + let k: i32; + let hi: f32; + let lo: f32; + if hx > 0x3eb17218 { + /* if |x| > 0.5 ln2 */ + if hx > 0x3f851592 { + /* if |x| > 1.5 ln2 */ + k = (INV_LN2 * x + HALF[sign as usize]) as i32; + } else { + k = 1 - sign - sign; + } + let kf = k as f32; + hi = x - kf * LN2_HI; /* k*ln2hi is exact here */ + lo = kf * LN2_LO; + x = hi - lo; + } else if hx > 0x39000000 { + /* |x| > 2**-14 */ + k = 0; + hi = x; + lo = 0.; + } else { + /* raise inexact */ + force_eval!(x1p127 + x); + return 1. + x; + } + + /* x is now in primary range */ + let xx = x * x; + let c = x - xx * (P1 + xx * P2); + let y = 1. + (x * c / (2. - c) - lo + hi); + if k == 0 { + y + } else { + scalbnf(y, k) + } +} diff --git a/vendor/libm/src/math/expm1.rs b/vendor/libm/src/math/expm1.rs new file mode 100644 index 0000000000..0d43b4e103 --- /dev/null +++ b/vendor/libm/src/math/expm1.rs @@ -0,0 +1,145 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_expm1.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use core::f64; + +const O_THRESHOLD: f64 = 7.09782712893383973096e+02; /* 0x40862E42, 0xFEFA39EF */ +const LN2_HI: f64 = 6.93147180369123816490e-01; /* 0x3fe62e42, 0xfee00000 */ +const LN2_LO: f64 = 1.90821492927058770002e-10; /* 0x3dea39ef, 0x35793c76 */ +const INVLN2: f64 = 1.44269504088896338700e+00; /* 0x3ff71547, 0x652b82fe */ +/* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs = x*x/2: */ +const Q1: f64 = -3.33333333333331316428e-02; /* BFA11111 111110F4 */ +const Q2: f64 = 1.58730158725481460165e-03; /* 3F5A01A0 19FE5585 */ +const Q3: f64 = -7.93650757867487942473e-05; /* BF14CE19 9EAADBB7 */ +const Q4: f64 = 4.00821782732936239552e-06; /* 3ED0CFCA 86E65239 */ +const Q5: f64 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ + +/// Exponential, base *e*, of x-1 (f64) +/// +/// Calculates the exponential of `x` and subtract 1, that is, *e* raised +/// to the power `x` minus 1 (where *e* is the base of the natural +/// system of logarithms, approximately 2.71828). +/// The result is accurate even for small values of `x`, +/// where using `exp(x)-1` would lose many significant digits. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn expm1(mut x: f64) -> f64 { + let hi: f64; + let lo: f64; + let k: i32; + let c: f64; + let mut t: f64; + let mut y: f64; + + let mut ui = x.to_bits(); + let hx = ((ui >> 32) & 0x7fffffff) as u32; + let sign = (ui >> 63) as i32; + + /* filter out huge and non-finite argument */ + if hx >= 0x4043687A { + /* if |x|>=56*ln2 */ + if x.is_nan() { + return x; + } + if sign != 0 { + return -1.0; + } + if x > O_THRESHOLD { + x *= f64::from_bits(0x7fe0000000000000); + return x; + } + } + + /* argument reduction */ + if hx > 0x3fd62e42 { + /* if |x| > 0.5 ln2 */ + if hx < 0x3FF0A2B2 { + /* and |x| < 1.5 ln2 */ + if sign == 0 { + hi = x - LN2_HI; + lo = LN2_LO; + k = 1; + } else { + hi = x + LN2_HI; + lo = -LN2_LO; + k = -1; + } + } else { + k = (INVLN2 * x + if sign != 0 { -0.5 } else { 0.5 }) as i32; + t = k as f64; + hi = x - t * LN2_HI; /* t*ln2_hi is exact here */ + lo = t * LN2_LO; + } + x = hi - lo; + c = (hi - x) - lo; + } else if hx < 0x3c900000 { + /* |x| < 2**-54, return x */ + if hx < 0x00100000 { + force_eval!(x); + } + return x; + } else { + c = 0.0; + k = 0; + } + + /* x is now in primary range */ + let hfx = 0.5 * x; + let hxs = x * hfx; + let r1 = 1.0 + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5)))); + t = 3.0 - r1 * hfx; + let mut e = hxs * ((r1 - t) / (6.0 - x * t)); + if k == 0 { + /* c is 0 */ + return x - (x * e - hxs); + } + e = x * (e - c) - c; + e -= hxs; + /* exp(x) ~ 2^k (x_reduced - e + 1) */ + if k == -1 { + return 0.5 * (x - e) - 0.5; + } + if k == 1 { + if x < -0.25 { + return -2.0 * (e - (x + 0.5)); + } + return 1.0 + 2.0 * (x - e); + } + ui = ((0x3ff + k) as u64) << 52; /* 2^k */ + let twopk = f64::from_bits(ui); + if k < 0 || k > 56 { + /* suffice to return exp(x)-1 */ + y = x - e + 1.0; + if k == 1024 { + y = y * 2.0 * f64::from_bits(0x7fe0000000000000); + } else { + y = y * twopk; + } + return y - 1.0; + } + ui = ((0x3ff - k) as u64) << 52; /* 2^-k */ + let uf = f64::from_bits(ui); + if k < 20 { + y = (x - e + (1.0 - uf)) * twopk; + } else { + y = (x - (e + uf) + 1.0) * twopk; + } + y +} + +#[cfg(test)] +mod tests { + #[test] + fn sanity_check() { + assert_eq!(super::expm1(1.1), 2.0041660239464334); + } +} diff --git a/vendor/libm/src/math/expm1f.rs b/vendor/libm/src/math/expm1f.rs new file mode 100644 index 0000000000..9bb2234488 --- /dev/null +++ b/vendor/libm/src/math/expm1f.rs @@ -0,0 +1,135 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_expm1f.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +const O_THRESHOLD: f32 = 8.8721679688e+01; /* 0x42b17180 */ +const LN2_HI: f32 = 6.9313812256e-01; /* 0x3f317180 */ +const LN2_LO: f32 = 9.0580006145e-06; /* 0x3717f7d1 */ +const INV_LN2: f32 = 1.4426950216e+00; /* 0x3fb8aa3b */ +/* + * Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]: + * |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04 + * Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c): + */ +const Q1: f32 = -3.3333212137e-2; /* -0x888868.0p-28 */ +const Q2: f32 = 1.5807170421e-3; /* 0xcf3010.0p-33 */ + +/// Exponential, base *e*, of x-1 (f32) +/// +/// Calculates the exponential of `x` and subtract 1, that is, *e* raised +/// to the power `x` minus 1 (where *e* is the base of the natural +/// system of logarithms, approximately 2.71828). +/// The result is accurate even for small values of `x`, +/// where using `exp(x)-1` would lose many significant digits. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn expm1f(mut x: f32) -> f32 { + let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127 + + let mut hx = x.to_bits(); + let sign = (hx >> 31) != 0; + hx &= 0x7fffffff; + + /* filter out huge and non-finite argument */ + if hx >= 0x4195b844 { + /* if |x|>=27*ln2 */ + if hx > 0x7f800000 { + /* NaN */ + return x; + } + if sign { + return -1.; + } + if x > O_THRESHOLD { + x *= x1p127; + return x; + } + } + + let k: i32; + let hi: f32; + let lo: f32; + let mut c = 0f32; + /* argument reduction */ + if hx > 0x3eb17218 { + /* if |x| > 0.5 ln2 */ + if hx < 0x3F851592 { + /* and |x| < 1.5 ln2 */ + if !sign { + hi = x - LN2_HI; + lo = LN2_LO; + k = 1; + } else { + hi = x + LN2_HI; + lo = -LN2_LO; + k = -1; + } + } else { + k = (INV_LN2 * x + (if sign { -0.5 } else { 0.5 })) as i32; + let t = k as f32; + hi = x - t * LN2_HI; /* t*ln2_hi is exact here */ + lo = t * LN2_LO; + } + x = hi - lo; + c = (hi - x) - lo; + } else if hx < 0x33000000 { + /* when |x|<2**-25, return x */ + if hx < 0x00800000 { + force_eval!(x * x); + } + return x; + } else { + k = 0; + } + + /* x is now in primary range */ + let hfx = 0.5 * x; + let hxs = x * hfx; + let r1 = 1. + hxs * (Q1 + hxs * Q2); + let t = 3. - r1 * hfx; + let mut e = hxs * ((r1 - t) / (6. - x * t)); + if k == 0 { + /* c is 0 */ + return x - (x * e - hxs); + } + e = x * (e - c) - c; + e -= hxs; + /* exp(x) ~ 2^k (x_reduced - e + 1) */ + if k == -1 { + return 0.5 * (x - e) - 0.5; + } + if k == 1 { + if x < -0.25 { + return -2. * (e - (x + 0.5)); + } + return 1. + 2. * (x - e); + } + let twopk = f32::from_bits(((0x7f + k) << 23) as u32); /* 2^k */ + if (k < 0) || (k > 56) { + /* suffice to return exp(x)-1 */ + let mut y = x - e + 1.; + if k == 128 { + y = y * 2. * x1p127; + } else { + y = y * twopk; + } + return y - 1.; + } + let uf = f32::from_bits(((0x7f - k) << 23) as u32); /* 2^-k */ + if k < 23 { + (x - e + (1. - uf)) * twopk + } else { + (x - (e + uf) + 1.) * twopk + } +} diff --git a/vendor/libm/src/math/expo2.rs b/vendor/libm/src/math/expo2.rs new file mode 100644 index 0000000000..ae6cc8121e --- /dev/null +++ b/vendor/libm/src/math/expo2.rs @@ -0,0 +1,15 @@ +use super::{combine_words, exp}; + +/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn expo2(x: f64) -> f64 { + /* k is such that k*ln2 has minimal relative error and x - kln2 > log(DBL_MIN) */ + const K: i32 = 2043; + let kln2 = f64::from_bits(0x40962066151add8b); + + /* note that k is odd and scale*scale overflows */ + let scale = combine_words(((0x3ff + K / 2) as u32) << 20, 0); + /* exp(x - k ln2) * 2**(k-1) */ + exp(x - kln2) * scale * scale +} diff --git a/vendor/libm/src/math/fabs.rs b/vendor/libm/src/math/fabs.rs new file mode 100644 index 0000000000..52a9adcbff --- /dev/null +++ b/vendor/libm/src/math/fabs.rs @@ -0,0 +1,18 @@ +use core::u64; + +/// Absolute value (magnitude) (f64) +/// Calculates the absolute value (magnitude) of the argument `x`, +/// by direct manipulation of the bit representation of `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fabs(x: f64) -> f64 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f64.abs` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::fabsf64(x) } + } + } + f64::from_bits(x.to_bits() & (u64::MAX / 2)) +} diff --git a/vendor/libm/src/math/fabsf.rs b/vendor/libm/src/math/fabsf.rs new file mode 100644 index 0000000000..5942d983a4 --- /dev/null +++ b/vendor/libm/src/math/fabsf.rs @@ -0,0 +1,16 @@ +/// Absolute value (magnitude) (f32) +/// Calculates the absolute value (magnitude) of the argument `x`, +/// by direct manipulation of the bit representation of `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fabsf(x: f32) -> f32 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f32.abs` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::fabsf32(x) } + } + } + f32::from_bits(x.to_bits() & 0x7fffffff) +} diff --git a/vendor/libm/src/math/fdim.rs b/vendor/libm/src/math/fdim.rs new file mode 100644 index 0000000000..06edc99603 --- /dev/null +++ b/vendor/libm/src/math/fdim.rs @@ -0,0 +1,23 @@ +use core::f64; + +/// Positive difference (f64) +/// +/// Determines the positive difference between arguments, returning: +/// * x - y if x > y, or +/// * +0 if x <= y, or +/// * NAN if either argument is NAN. +/// +/// A range error may occur. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fdim(x: f64, y: f64) -> f64 { + if x.is_nan() { + x + } else if y.is_nan() { + y + } else if x > y { + x - y + } else { + 0.0 + } +} diff --git a/vendor/libm/src/math/fdimf.rs b/vendor/libm/src/math/fdimf.rs new file mode 100644 index 0000000000..f1ad5896bf --- /dev/null +++ b/vendor/libm/src/math/fdimf.rs @@ -0,0 +1,23 @@ +use core::f32; + +/// Positive difference (f32) +/// +/// Determines the positive difference between arguments, returning: +/// * x - y if x > y, or +/// * +0 if x <= y, or +/// * NAN if either argument is NAN. +/// +/// A range error may occur. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fdimf(x: f32, y: f32) -> f32 { + if x.is_nan() { + x + } else if y.is_nan() { + y + } else if x > y { + x - y + } else { + 0.0 + } +} diff --git a/vendor/libm/src/math/fenv.rs b/vendor/libm/src/math/fenv.rs new file mode 100644 index 0000000000..63bb203682 --- /dev/null +++ b/vendor/libm/src/math/fenv.rs @@ -0,0 +1,33 @@ +// src: musl/src/fenv/fenv.c +/* Dummy functions for archs lacking fenv implementation */ + +pub const FE_UNDERFLOW: i32 = 0; +pub const FE_INEXACT: i32 = 0; + +pub const FE_TONEAREST: i32 = 0; +pub const FE_TOWARDZERO: i32 = 0; + +#[inline] +pub fn feclearexcept(_mask: i32) -> i32 { + 0 +} + +#[inline] +pub fn feraiseexcept(_mask: i32) -> i32 { + 0 +} + +#[inline] +pub fn fetestexcept(_mask: i32) -> i32 { + 0 +} + +#[inline] +pub fn fegetround() -> i32 { + FE_TONEAREST +} + +#[inline] +pub fn fesetround(_r: i32) -> i32 { + 0 +} diff --git a/vendor/libm/src/math/floor.rs b/vendor/libm/src/math/floor.rs new file mode 100644 index 0000000000..f6068c697a --- /dev/null +++ b/vendor/libm/src/math/floor.rs @@ -0,0 +1,41 @@ +use core::f64; + +const TOINT: f64 = 1. / f64::EPSILON; + +/// Floor (f64) +/// +/// Finds the nearest integer less than or equal to `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn floor(x: f64) -> f64 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f64.floor` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::floorf64(x) } + } + } + let ui = x.to_bits(); + let e = ((ui >> 52) & 0x7ff) as i32; + + if (e >= 0x3ff + 52) || (x == 0.) { + return x; + } + /* y = int(x) - x, where int(x) is an integer neighbor of x */ + let y = if (ui >> 63) != 0 { + x - TOINT + TOINT - x + } else { + x + TOINT - TOINT - x + }; + /* special case because of non-nearest rounding modes */ + if e < 0x3ff { + force_eval!(y); + return if (ui >> 63) != 0 { -1. } else { 0. }; + } + if y > 0. { + x + y - 1. + } else { + x + y + } +} diff --git a/vendor/libm/src/math/floorf.rs b/vendor/libm/src/math/floorf.rs new file mode 100644 index 0000000000..ae605e1918 --- /dev/null +++ b/vendor/libm/src/math/floorf.rs @@ -0,0 +1,50 @@ +use core::f32; + +/// Floor (f64) +/// +/// Finds the nearest integer less than or equal to `x`. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn floorf(x: f32) -> f32 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f32.floor` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::floorf32(x) } + } + } + let mut ui = x.to_bits(); + let e = (((ui >> 23) as i32) & 0xff) - 0x7f; + + if e >= 23 { + return x; + } + if e >= 0 { + let m: u32 = 0x007fffff >> e; + if (ui & m) == 0 { + return x; + } + force_eval!(x + f32::from_bits(0x7b800000)); + if ui >> 31 != 0 { + ui += m; + } + ui &= !m; + } else { + force_eval!(x + f32::from_bits(0x7b800000)); + if ui >> 31 == 0 { + ui = 0; + } else if ui << 1 != 0 { + return -1.0; + } + } + f32::from_bits(ui) +} + +#[cfg(test)] +mod tests { + #[test] + fn no_overflow() { + assert_eq!(super::floorf(0.5), 0.0); + } +} diff --git a/vendor/libm/src/math/fma.rs b/vendor/libm/src/math/fma.rs new file mode 100644 index 0000000000..07d90f8b72 --- /dev/null +++ b/vendor/libm/src/math/fma.rs @@ -0,0 +1,207 @@ +use core::{f32, f64}; + +use super::scalbn; + +const ZEROINFNAN: i32 = 0x7ff - 0x3ff - 52 - 1; + +struct Num { + m: u64, + e: i32, + sign: i32, +} + +#[inline] +fn normalize(x: f64) -> Num { + let x1p63: f64 = f64::from_bits(0x43e0000000000000); // 0x1p63 === 2 ^ 63 + + let mut ix: u64 = x.to_bits(); + let mut e: i32 = (ix >> 52) as i32; + let sign: i32 = e & 0x800; + e &= 0x7ff; + if e == 0 { + ix = (x * x1p63).to_bits(); + e = (ix >> 52) as i32 & 0x7ff; + e = if e != 0 { e - 63 } else { 0x800 }; + } + ix &= (1 << 52) - 1; + ix |= 1 << 52; + ix <<= 1; + e -= 0x3ff + 52 + 1; + Num { m: ix, e, sign } +} + +#[inline] +fn mul(x: u64, y: u64) -> (u64, u64) { + let t1: u64; + let t2: u64; + let t3: u64; + let xlo: u64 = x as u32 as u64; + let xhi: u64 = x >> 32; + let ylo: u64 = y as u32 as u64; + let yhi: u64 = y >> 32; + + t1 = xlo * ylo; + t2 = xlo * yhi + xhi * ylo; + t3 = xhi * yhi; + let lo = t1.wrapping_add(t2 << 32); + let hi = t3 + (t2 >> 32) + (t1 > lo) as u64; + (hi, lo) +} + +/// Floating multiply add (f64) +/// +/// Computes `(x*y)+z`, rounded as one ternary operation: +/// Computes the value (as if) to infinite precision and rounds once to the result format, +/// according to the rounding mode characterized by the value of FLT_ROUNDS. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fma(x: f64, y: f64, z: f64) -> f64 { + let x1p63: f64 = f64::from_bits(0x43e0000000000000); // 0x1p63 === 2 ^ 63 + let x0_ffffff8p_63 = f64::from_bits(0x3bfffffff0000000); // 0x0.ffffff8p-63 + + /* normalize so top 10bits and last bit are 0 */ + let nx = normalize(x); + let ny = normalize(y); + let nz = normalize(z); + + if nx.e >= ZEROINFNAN || ny.e >= ZEROINFNAN { + return x * y + z; + } + if nz.e >= ZEROINFNAN { + if nz.e > ZEROINFNAN { + /* z==0 */ + return x * y + z; + } + return z; + } + + /* mul: r = x*y */ + let zhi: u64; + let zlo: u64; + let (mut rhi, mut rlo) = mul(nx.m, ny.m); + /* either top 20 or 21 bits of rhi and last 2 bits of rlo are 0 */ + + /* align exponents */ + let mut e: i32 = nx.e + ny.e; + let mut d: i32 = nz.e - e; + /* shift bits z<<=kz, r>>=kr, so kz+kr == d, set e = e+kr (== ez-kz) */ + if d > 0 { + if d < 64 { + zlo = nz.m << d; + zhi = nz.m >> (64 - d); + } else { + zlo = 0; + zhi = nz.m; + e = nz.e - 64; + d -= 64; + if d == 0 { + } else if d < 64 { + rlo = rhi << (64 - d) | rlo >> d | ((rlo << (64 - d)) != 0) as u64; + rhi = rhi >> d; + } else { + rlo = 1; + rhi = 0; + } + } + } else { + zhi = 0; + d = -d; + if d == 0 { + zlo = nz.m; + } else if d < 64 { + zlo = nz.m >> d | ((nz.m << (64 - d)) != 0) as u64; + } else { + zlo = 1; + } + } + + /* add */ + let mut sign: i32 = nx.sign ^ ny.sign; + let samesign: bool = (sign ^ nz.sign) == 0; + let mut nonzero: i32 = 1; + if samesign { + /* r += z */ + rlo = rlo.wrapping_add(zlo); + rhi += zhi + (rlo < zlo) as u64; + } else { + /* r -= z */ + let t = rlo; + rlo -= zlo; + rhi = rhi - zhi - (t < rlo) as u64; + if (rhi >> 63) != 0 { + rlo = (-(rlo as i64)) as u64; + rhi = (-(rhi as i64)) as u64 - (rlo != 0) as u64; + sign = (sign == 0) as i32; + } + nonzero = (rhi != 0) as i32; + } + + /* set rhi to top 63bit of the result (last bit is sticky) */ + if nonzero != 0 { + e += 64; + d = rhi.leading_zeros() as i32 - 1; + /* note: d > 0 */ + rhi = rhi << d | rlo >> (64 - d) | ((rlo << d) != 0) as u64; + } else if rlo != 0 { + d = rlo.leading_zeros() as i32 - 1; + if d < 0 { + rhi = rlo >> 1 | (rlo & 1); + } else { + rhi = rlo << d; + } + } else { + /* exact +-0 */ + return x * y + z; + } + e -= d; + + /* convert to double */ + let mut i: i64 = rhi as i64; /* i is in [1<<62,(1<<63)-1] */ + if sign != 0 { + i = -i; + } + let mut r: f64 = i as f64; /* |r| is in [0x1p62,0x1p63] */ + + if e < -1022 - 62 { + /* result is subnormal before rounding */ + if e == -1022 - 63 { + let mut c: f64 = x1p63; + if sign != 0 { + c = -c; + } + if r == c { + /* min normal after rounding, underflow depends + on arch behaviour which can be imitated by + a double to float conversion */ + let fltmin: f32 = (x0_ffffff8p_63 * f32::MIN_POSITIVE as f64 * r) as f32; + return f64::MIN_POSITIVE / f32::MIN_POSITIVE as f64 * fltmin as f64; + } + /* one bit is lost when scaled, add another top bit to + only round once at conversion if it is inexact */ + if (rhi << 53) != 0 { + i = (rhi >> 1 | (rhi & 1) | 1 << 62) as i64; + if sign != 0 { + i = -i; + } + r = i as f64; + r = 2. * r - c; /* remove top bit */ + + /* raise underflow portably, such that it + cannot be optimized away */ + { + let tiny: f64 = f64::MIN_POSITIVE / f32::MIN_POSITIVE as f64 * r; + r += (tiny * tiny) * (r - r); + } + } + } else { + /* only round once when scaled */ + d = 10; + i = ((rhi >> d | ((rhi << (64 - d)) != 0) as u64) << d) as i64; + if sign != 0 { + i = -i; + } + r = i as f64; + } + } + scalbn(r, e) +} diff --git a/vendor/libm/src/math/fmaf.rs b/vendor/libm/src/math/fmaf.rs new file mode 100644 index 0000000000..e77e0fa4a2 --- /dev/null +++ b/vendor/libm/src/math/fmaf.rs @@ -0,0 +1,107 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_fmaf.c */ +/*- + * Copyright (c) 2005-2011 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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. + */ + +use core::f32; +use core::ptr::read_volatile; + +use super::fenv::{ + feclearexcept, fegetround, feraiseexcept, fesetround, fetestexcept, FE_INEXACT, FE_TONEAREST, + FE_TOWARDZERO, FE_UNDERFLOW, +}; + +/* + * Fused multiply-add: Compute x * y + z with a single rounding error. + * + * A double has more than twice as much precision than a float, so + * direct double-precision arithmetic suffices, except where double + * rounding occurs. + */ + +/// Floating multiply add (f32) +/// +/// Computes `(x*y)+z`, rounded as one ternary operation: +/// Computes the value (as if) to infinite precision and rounds once to the result format, +/// according to the rounding mode characterized by the value of FLT_ROUNDS. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmaf(x: f32, y: f32, mut z: f32) -> f32 { + let xy: f64; + let mut result: f64; + let mut ui: u64; + let e: i32; + + xy = x as f64 * y as f64; + result = xy + z as f64; + ui = result.to_bits(); + e = (ui >> 52) as i32 & 0x7ff; + /* Common case: The double precision result is fine. */ + if ( + /* not a halfway case */ + ui & 0x1fffffff) != 0x10000000 || + /* NaN */ + e == 0x7ff || + /* exact */ + (result - xy == z as f64 && result - z as f64 == xy) || + /* not round-to-nearest */ + fegetround() != FE_TONEAREST + { + /* + underflow may not be raised correctly, example: + fmaf(0x1p-120f, 0x1p-120f, 0x1p-149f) + */ + if e < 0x3ff - 126 && e >= 0x3ff - 149 && fetestexcept(FE_INEXACT) != 0 { + feclearexcept(FE_INEXACT); + // prevent `xy + vz` from being CSE'd with `xy + z` above + let vz: f32 = unsafe { read_volatile(&z) }; + result = xy + vz as f64; + if fetestexcept(FE_INEXACT) != 0 { + feraiseexcept(FE_UNDERFLOW); + } else { + feraiseexcept(FE_INEXACT); + } + } + z = result as f32; + return z; + } + + /* + * If result is inexact, and exactly halfway between two float values, + * we need to adjust the low-order bit in the direction of the error. + */ + fesetround(FE_TOWARDZERO); + // prevent `vxy + z` from being CSE'd with `xy + z` above + let vxy: f64 = unsafe { read_volatile(&xy) }; + let mut adjusted_result: f64 = vxy + z as f64; + fesetround(FE_TONEAREST); + if result == adjusted_result { + ui = adjusted_result.to_bits(); + ui += 1; + adjusted_result = f64::from_bits(ui); + } + z = adjusted_result as f32; + z +} diff --git a/vendor/libm/src/math/fmax.rs b/vendor/libm/src/math/fmax.rs new file mode 100644 index 0000000000..22016d11cc --- /dev/null +++ b/vendor/libm/src/math/fmax.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmax(x: f64, y: f64) -> f64 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if x.is_nan() || x < y { y } else { x }) * 1.0 +} diff --git a/vendor/libm/src/math/fmaxf.rs b/vendor/libm/src/math/fmaxf.rs new file mode 100644 index 0000000000..a883fdaef5 --- /dev/null +++ b/vendor/libm/src/math/fmaxf.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmaxf(x: f32, y: f32) -> f32 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if x.is_nan() || x < y { y } else { x }) * 1.0 +} diff --git a/vendor/libm/src/math/fmin.rs b/vendor/libm/src/math/fmin.rs new file mode 100644 index 0000000000..d1ccc3a468 --- /dev/null +++ b/vendor/libm/src/math/fmin.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmin(x: f64, y: f64) -> f64 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if y.is_nan() || x < y { x } else { y }) * 1.0 +} diff --git a/vendor/libm/src/math/fminf.rs b/vendor/libm/src/math/fminf.rs new file mode 100644 index 0000000000..43ec97cb5b --- /dev/null +++ b/vendor/libm/src/math/fminf.rs @@ -0,0 +1,13 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fminf(x: f32, y: f32) -> f32 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if y.is_nan() || x < y { x } else { y }) * 1.0 +} diff --git a/vendor/libm/src/math/fmod.rs b/vendor/libm/src/math/fmod.rs new file mode 100644 index 0000000000..2cdd8a9ba3 --- /dev/null +++ b/vendor/libm/src/math/fmod.rs @@ -0,0 +1,81 @@ +use core::u64; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmod(x: f64, y: f64) -> f64 { + let mut uxi = x.to_bits(); + let mut uyi = y.to_bits(); + let mut ex = (uxi >> 52 & 0x7ff) as i64; + let mut ey = (uyi >> 52 & 0x7ff) as i64; + let sx = uxi >> 63; + let mut i; + + if uyi << 1 == 0 || y.is_nan() || ex == 0x7ff { + return (x * y) / (x * y); + } + if uxi << 1 <= uyi << 1 { + if uxi << 1 == uyi << 1 { + return 0.0 * x; + } + return x; + } + + /* normalize x and y */ + if ex == 0 { + i = uxi << 12; + while i >> 63 == 0 { + ex -= 1; + i <<= 1; + } + uxi <<= -ex + 1; + } else { + uxi &= u64::MAX >> 12; + uxi |= 1 << 52; + } + if ey == 0 { + i = uyi << 12; + while i >> 63 == 0 { + ey -= 1; + i <<= 1; + } + uyi <<= -ey + 1; + } else { + uyi &= u64::MAX >> 12; + uyi |= 1 << 52; + } + + /* x mod y */ + while ex > ey { + i = uxi.wrapping_sub(uyi); + if i >> 63 == 0 { + if i == 0 { + return 0.0 * x; + } + uxi = i; + } + uxi <<= 1; + ex -= 1; + } + i = uxi.wrapping_sub(uyi); + if i >> 63 == 0 { + if i == 0 { + return 0.0 * x; + } + uxi = i; + } + while uxi >> 52 == 0 { + uxi <<= 1; + ex -= 1; + } + + /* scale result */ + if ex > 0 { + uxi -= 1 << 52; + uxi |= (ex as u64) << 52; + } else { + uxi >>= -ex + 1; + } + uxi |= (sx as u64) << 63; + + f64::from_bits(uxi) +} diff --git a/vendor/libm/src/math/fmodf.rs b/vendor/libm/src/math/fmodf.rs new file mode 100644 index 0000000000..3e6779a930 --- /dev/null +++ b/vendor/libm/src/math/fmodf.rs @@ -0,0 +1,90 @@ +use core::f32; +use core::u32; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn fmodf(x: f32, y: f32) -> f32 { + let mut uxi = x.to_bits(); + let mut uyi = y.to_bits(); + let mut ex = (uxi >> 23 & 0xff) as i32; + let mut ey = (uyi >> 23 & 0xff) as i32; + let sx = uxi & 0x80000000; + let mut i; + + if uyi << 1 == 0 || y.is_nan() || ex == 0xff { + return (x * y) / (x * y); + } + + if uxi << 1 <= uyi << 1 { + if uxi << 1 == uyi << 1 { + return 0.0 * x; + } + + return x; + } + + /* normalize x and y */ + if ex == 0 { + i = uxi << 9; + while i >> 31 == 0 { + ex -= 1; + i <<= 1; + } + + uxi <<= -ex + 1; + } else { + uxi &= u32::MAX >> 9; + uxi |= 1 << 23; + } + + if ey == 0 { + i = uyi << 9; + while i >> 31 == 0 { + ey -= 1; + i <<= 1; + } + + uyi <<= -ey + 1; + } else { + uyi &= u32::MAX >> 9; + uyi |= 1 << 23; + } + + /* x mod y */ + while ex > ey { + i = uxi.wrapping_sub(uyi); + if i >> 31 == 0 { + if i == 0 { + return 0.0 * x; + } + uxi = i; + } + uxi <<= 1; + + ex -= 1; + } + + i = uxi.wrapping_sub(uyi); + if i >> 31 == 0 { + if i == 0 { + return 0.0 * x; + } + uxi = i; + } + + while uxi >> 23 == 0 { + uxi <<= 1; + ex -= 1; + } + + /* scale result up */ + if ex > 0 { + uxi -= 1 << 23; + uxi |= (ex as u32) << 23; + } else { + uxi >>= -ex + 1; + } + uxi |= sx; + + f32::from_bits(uxi) +} diff --git a/vendor/libm/src/math/frexp.rs b/vendor/libm/src/math/frexp.rs new file mode 100644 index 0000000000..badad786aa --- /dev/null +++ b/vendor/libm/src/math/frexp.rs @@ -0,0 +1,20 @@ +pub fn frexp(x: f64) -> (f64, i32) { + let mut y = x.to_bits(); + let ee = ((y >> 52) & 0x7ff) as i32; + + if ee == 0 { + if x != 0.0 { + let x1p64 = f64::from_bits(0x43f0000000000000); + let (x, e) = frexp(x * x1p64); + return (x, e - 64); + } + return (x, 0); + } else if ee == 0x7ff { + return (x, 0); + } + + let e = ee - 0x3fe; + y &= 0x800fffffffffffff; + y |= 0x3fe0000000000000; + return (f64::from_bits(y), e); +} diff --git a/vendor/libm/src/math/frexpf.rs b/vendor/libm/src/math/frexpf.rs new file mode 100644 index 0000000000..2919c0ab02 --- /dev/null +++ b/vendor/libm/src/math/frexpf.rs @@ -0,0 +1,21 @@ +pub fn frexpf(x: f32) -> (f32, i32) { + let mut y = x.to_bits(); + let ee: i32 = ((y >> 23) & 0xff) as i32; + + if ee == 0 { + if x != 0.0 { + let x1p64 = f32::from_bits(0x5f800000); + let (x, e) = frexpf(x * x1p64); + return (x, e - 64); + } else { + return (x, 0); + } + } else if ee == 0xff { + return (x, 0); + } + + let e = ee - 0x7e; + y &= 0x807fffff; + y |= 0x3f000000; + (f32::from_bits(y), e) +} diff --git a/vendor/libm/src/math/hypot.rs b/vendor/libm/src/math/hypot.rs new file mode 100644 index 0000000000..e53baf5399 --- /dev/null +++ b/vendor/libm/src/math/hypot.rs @@ -0,0 +1,76 @@ +use core::f64; + +use super::sqrt; + +const SPLIT: f64 = 134217728. + 1.; // 0x1p27 + 1 === (2 ^ 27) + 1 + +#[inline] +fn sq(x: f64) -> (f64, f64) { + let xh: f64; + let xl: f64; + let xc: f64; + + xc = x * SPLIT; + xh = x - xc + xc; + xl = x - xh; + let hi = x * x; + let lo = xh * xh - hi + 2. * xh * xl + xl * xl; + (hi, lo) +} + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn hypot(mut x: f64, mut y: f64) -> f64 { + let x1p700 = f64::from_bits(0x6bb0000000000000); // 0x1p700 === 2 ^ 700 + let x1p_700 = f64::from_bits(0x1430000000000000); // 0x1p-700 === 2 ^ -700 + + let mut uxi = x.to_bits(); + let mut uyi = y.to_bits(); + let uti; + let ex: i64; + let ey: i64; + let mut z: f64; + + /* arrange |x| >= |y| */ + uxi &= -1i64 as u64 >> 1; + uyi &= -1i64 as u64 >> 1; + if uxi < uyi { + uti = uxi; + uxi = uyi; + uyi = uti; + } + + /* special cases */ + ex = (uxi >> 52) as i64; + ey = (uyi >> 52) as i64; + x = f64::from_bits(uxi); + y = f64::from_bits(uyi); + /* note: hypot(inf,nan) == inf */ + if ey == 0x7ff { + return y; + } + if ex == 0x7ff || uyi == 0 { + return x; + } + /* note: hypot(x,y) ~= x + y*y/x/2 with inexact for small y/x */ + /* 64 difference is enough for ld80 double_t */ + if ex - ey > 64 { + return x + y; + } + + /* precise sqrt argument in nearest rounding mode without overflow */ + /* xh*xh must not overflow and xl*xl must not underflow in sq */ + z = 1.; + if ex > 0x3ff + 510 { + z = x1p700; + x *= x1p_700; + y *= x1p_700; + } else if ey < 0x3ff - 450 { + z = x1p_700; + x *= x1p700; + y *= x1p700; + } + let (hx, lx) = sq(x); + let (hy, ly) = sq(y); + z * sqrt(ly + lx + hy + hx) +} diff --git a/vendor/libm/src/math/hypotf.rs b/vendor/libm/src/math/hypotf.rs new file mode 100644 index 0000000000..4636b8f1d8 --- /dev/null +++ b/vendor/libm/src/math/hypotf.rs @@ -0,0 +1,44 @@ +use core::f32; + +use super::sqrtf; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn hypotf(mut x: f32, mut y: f32) -> f32 { + let x1p90 = f32::from_bits(0x6c800000); // 0x1p90f === 2 ^ 90 + let x1p_90 = f32::from_bits(0x12800000); // 0x1p-90f === 2 ^ -90 + + let mut uxi = x.to_bits(); + let mut uyi = y.to_bits(); + let uti; + let mut z: f32; + + uxi &= -1i32 as u32 >> 1; + uyi &= -1i32 as u32 >> 1; + if uxi < uyi { + uti = uxi; + uxi = uyi; + uyi = uti; + } + + x = f32::from_bits(uxi); + y = f32::from_bits(uyi); + if uyi == 0xff << 23 { + return y; + } + if uxi >= 0xff << 23 || uyi == 0 || uxi - uyi >= 25 << 23 { + return x + y; + } + + z = 1.; + if uxi >= (0x7f + 60) << 23 { + z = x1p90; + x *= x1p_90; + y *= x1p_90; + } else if uyi < (0x7f - 60) << 23 { + z = x1p_90; + x *= x1p90; + y *= x1p90; + } + z * sqrtf((x as f64 * x as f64 + y as f64 * y as f64) as f32) +} diff --git a/vendor/libm/src/math/ilogb.rs b/vendor/libm/src/math/ilogb.rs new file mode 100644 index 0000000000..0a380b7efd --- /dev/null +++ b/vendor/libm/src/math/ilogb.rs @@ -0,0 +1,31 @@ +const FP_ILOGBNAN: i32 = -1 - 0x7fffffff; +const FP_ILOGB0: i32 = FP_ILOGBNAN; + +pub fn ilogb(x: f64) -> i32 { + let mut i: u64 = x.to_bits(); + let e = ((i >> 52) & 0x7ff) as i32; + + if e == 0 { + i <<= 12; + if i == 0 { + force_eval!(0.0 / 0.0); + return FP_ILOGB0; + } + /* subnormal x */ + let mut e = -0x3ff; + while (i >> 63) == 0 { + e -= 1; + i <<= 1; + } + e + } else if e == 0x7ff { + force_eval!(0.0 / 0.0); + if (i << 12) != 0 { + FP_ILOGBNAN + } else { + i32::max_value() + } + } else { + e - 0x3ff + } +} diff --git a/vendor/libm/src/math/ilogbf.rs b/vendor/libm/src/math/ilogbf.rs new file mode 100644 index 0000000000..b384fa4b20 --- /dev/null +++ b/vendor/libm/src/math/ilogbf.rs @@ -0,0 +1,31 @@ +const FP_ILOGBNAN: i32 = -1 - 0x7fffffff; +const FP_ILOGB0: i32 = FP_ILOGBNAN; + +pub fn ilogbf(x: f32) -> i32 { + let mut i = x.to_bits(); + let e = ((i >> 23) & 0xff) as i32; + + if e == 0 { + i <<= 9; + if i == 0 { + force_eval!(0.0 / 0.0); + return FP_ILOGB0; + } + /* subnormal x */ + let mut e = -0x7f; + while (i >> 31) == 0 { + e -= 1; + i <<= 1; + } + e + } else if e == 0xff { + force_eval!(0.0 / 0.0); + if (i << 9) != 0 { + FP_ILOGBNAN + } else { + i32::max_value() + } + } else { + e - 0x7f + } +} diff --git a/vendor/libm/src/math/j0.rs b/vendor/libm/src/math/j0.rs new file mode 100644 index 0000000000..c4258ccca1 --- /dev/null +++ b/vendor/libm/src/math/j0.rs @@ -0,0 +1,422 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_j0.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* j0(x), y0(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j0(x): + * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... + * 2. Reduce x to |x| since j0(x)=j0(-x), and + * for x in (0,2) + * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; + * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) + * for x in (2,inf) + * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * as follow: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (cos(x) + sin(x)) + * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j0(nan)= nan + * j0(0) = 1 + * j0(inf) = 0 + * + * Method -- y0(x): + * 1. For x<2. + * Since + * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) + * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. + * We use the following function to approximate y0, + * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 + * where + * U(z) = u00 + u01*z + ... + u06*z^6 + * V(z) = 1 + v01*z + ... + v04*z^4 + * with absolute approximation error bounded by 2**-72. + * Note: For tiny x, U/V = u0 and j0(x)~1, hence + * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) + * 2. For x>=2. + * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * by the method mentioned above. + * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. + */ + +use super::{cos, fabs, get_high_word, get_low_word, log, sin, sqrt}; +const INVSQRTPI: f64 = 5.64189583547756279280e-01; /* 0x3FE20DD7, 0x50429B6D */ +const TPI: f64 = 6.36619772367581382433e-01; /* 0x3FE45F30, 0x6DC9C883 */ + +/* common method when |x|>=2 */ +fn common(ix: u32, x: f64, y0: bool) -> f64 { + let s: f64; + let mut c: f64; + let mut ss: f64; + let mut cc: f64; + let z: f64; + + /* + * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x-pi/4)-q0(x)*sin(x-pi/4)) + * y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x-pi/4)+q0(x)*cos(x-pi/4)) + * + * sin(x-pi/4) = (sin(x) - cos(x))/sqrt(2) + * cos(x-pi/4) = (sin(x) + cos(x))/sqrt(2) + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + */ + s = sin(x); + c = cos(x); + if y0 { + c = -c; + } + cc = s + c; + /* avoid overflow in 2*x, big ulp error when x>=0x1p1023 */ + if ix < 0x7fe00000 { + ss = s - c; + z = -cos(2.0 * x); + if s * c < 0.0 { + cc = z / ss; + } else { + ss = z / cc; + } + if ix < 0x48000000 { + if y0 { + ss = -ss; + } + cc = pzero(x) * cc - qzero(x) * ss; + } + } + return INVSQRTPI * cc / sqrt(x); +} + +/* R0/S0 on [0, 2.00] */ +const R02: f64 = 1.56249999999999947958e-02; /* 0x3F8FFFFF, 0xFFFFFFFD */ +const R03: f64 = -1.89979294238854721751e-04; /* 0xBF28E6A5, 0xB61AC6E9 */ +const R04: f64 = 1.82954049532700665670e-06; /* 0x3EBEB1D1, 0x0C503919 */ +const R05: f64 = -4.61832688532103189199e-09; /* 0xBE33D5E7, 0x73D63FCE */ +const S01: f64 = 1.56191029464890010492e-02; /* 0x3F8FFCE8, 0x82C8C2A4 */ +const S02: f64 = 1.16926784663337450260e-04; /* 0x3F1EA6D2, 0xDD57DBF4 */ +const S03: f64 = 5.13546550207318111446e-07; /* 0x3EA13B54, 0xCE84D5A9 */ +const S04: f64 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ + +pub fn j0(mut x: f64) -> f64 { + let z: f64; + let r: f64; + let s: f64; + let mut ix: u32; + + ix = get_high_word(x); + ix &= 0x7fffffff; + + /* j0(+-inf)=0, j0(nan)=nan */ + if ix >= 0x7ff00000 { + return 1.0 / (x * x); + } + x = fabs(x); + + if ix >= 0x40000000 { + /* |x| >= 2 */ + /* large ulp error near zeros: 2.4, 5.52, 8.6537,.. */ + return common(ix, x, false); + } + + /* 1 - x*x/4 + x*x*R(x^2)/S(x^2) */ + if ix >= 0x3f200000 { + /* |x| >= 2**-13 */ + /* up to 4ulp error close to 2 */ + z = x * x; + r = z * (R02 + z * (R03 + z * (R04 + z * R05))); + s = 1.0 + z * (S01 + z * (S02 + z * (S03 + z * S04))); + return (1.0 + x / 2.0) * (1.0 - x / 2.0) + z * (r / s); + } + + /* 1 - x*x/4 */ + /* prevent underflow */ + /* inexact should be raised when x!=0, this is not done correctly */ + if ix >= 0x38000000 { + /* |x| >= 2**-127 */ + x = 0.25 * x * x; + } + return 1.0 - x; +} + +const U00: f64 = -7.38042951086872317523e-02; /* 0xBFB2E4D6, 0x99CBD01F */ +const U01: f64 = 1.76666452509181115538e-01; /* 0x3FC69D01, 0x9DE9E3FC */ +const U02: f64 = -1.38185671945596898896e-02; /* 0xBF8C4CE8, 0xB16CFA97 */ +const U03: f64 = 3.47453432093683650238e-04; /* 0x3F36C54D, 0x20B29B6B */ +const U04: f64 = -3.81407053724364161125e-06; /* 0xBECFFEA7, 0x73D25CAD */ +const U05: f64 = 1.95590137035022920206e-08; /* 0x3E550057, 0x3B4EABD4 */ +const U06: f64 = -3.98205194132103398453e-11; /* 0xBDC5E43D, 0x693FB3C8 */ +const V01: f64 = 1.27304834834123699328e-02; /* 0x3F8A1270, 0x91C9C71A */ +const V02: f64 = 7.60068627350353253702e-05; /* 0x3F13ECBB, 0xF578C6C1 */ +const V03: f64 = 2.59150851840457805467e-07; /* 0x3E91642D, 0x7FF202FD */ +const V04: f64 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ + +pub fn y0(x: f64) -> f64 { + let z: f64; + let u: f64; + let v: f64; + let ix: u32; + let lx: u32; + + ix = get_high_word(x); + lx = get_low_word(x); + + /* y0(nan)=nan, y0(<0)=nan, y0(0)=-inf, y0(inf)=0 */ + if ((ix << 1) | lx) == 0 { + return -1.0 / 0.0; + } + if (ix >> 31) != 0 { + return 0.0 / 0.0; + } + if ix >= 0x7ff00000 { + return 1.0 / x; + } + + if ix >= 0x40000000 { + /* x >= 2 */ + /* large ulp errors near zeros: 3.958, 7.086,.. */ + return common(ix, x, true); + } + + /* U(x^2)/V(x^2) + (2/pi)*j0(x)*log(x) */ + if ix >= 0x3e400000 { + /* x >= 2**-27 */ + /* large ulp error near the first zero, x ~= 0.89 */ + z = x * x; + u = U00 + z * (U01 + z * (U02 + z * (U03 + z * (U04 + z * (U05 + z * U06))))); + v = 1.0 + z * (V01 + z * (V02 + z * (V03 + z * V04))); + return u / v + TPI * (j0(x) * log(x)); + } + return U00 + TPI * log(x); +} + +/* The asymptotic expansions of pzero is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate pzero by + * pzero(x) = 1 + (R/S) + * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 + * S = 1 + pS0*s^2 + ... + pS4*s^10 + * and + * | pzero(x)-1-R/S | <= 2 ** ( -60.26) + */ +const PR8: [f64; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ + -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ + -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ + -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ + -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ +]; +const PS8: [f64; 5] = [ + 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ + 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ + 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ + 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ + 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ +]; + +const PR5: [f64; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ + -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ + -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ + -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ + -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ + -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ +]; +const PS5: [f64; 5] = [ + 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ + 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ + 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ + 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ + 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ +]; + +const PR3: [f64; 6] = [ + /* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ + -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ + -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ + -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ + -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ + -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ +]; +const PS3: [f64; 5] = [ + 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ + 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ + 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ + 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ + 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ +]; + +const PR2: [f64; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ + -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ + -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ + -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ + -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ + -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ +]; +const PS2: [f64; 5] = [ + 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ + 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ + 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ + 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ + 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ +]; + +fn pzero(x: f64) -> f64 { + let p: &[f64; 6]; + let q: &[f64; 5]; + let z: f64; + let r: f64; + let s: f64; + let mut ix: u32; + + ix = get_high_word(x); + ix &= 0x7fffffff; + if ix >= 0x40200000 { + p = &PR8; + q = &PS8; + } else if ix >= 0x40122E8B { + p = &PR5; + q = &PS5; + } else if ix >= 0x4006DB6D { + p = &PR3; + q = &PS3; + } else + /*ix >= 0x40000000*/ + { + p = &PR2; + q = &PS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4])))); + return 1.0 + r / s; +} + +/* For x >= 8, the asymptotic expansions of qzero is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate pzero by + * qzero(x) = s*(-1.25 + (R/S)) + * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 + * S = 1 + qS0*s^2 + ... + qS5*s^12 + * and + * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) + */ +const QR8: [f64; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ + 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ + 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ + 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ + 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ +]; +const QS8: [f64; 6] = [ + 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ + 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ + 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ + 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ + 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ + -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ +]; + +const QR5: [f64; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ + 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ + 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ + 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ + 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ + 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ +]; +const QS5: [f64; 6] = [ + 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ + 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ + 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ + 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ + 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ + -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ +]; + +const QR3: [f64; 6] = [ + /* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ + 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ + 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ + 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ + 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ + 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ +]; +const QS3: [f64; 6] = [ + 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ + 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ + 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ + 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ + 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ + -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ +]; + +const QR2: [f64; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ + 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ + 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ + 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ + 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ + 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ +]; +const QS2: [f64; 6] = [ + 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ + 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ + 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ + 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ + 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ + -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ +]; + +fn qzero(x: f64) -> f64 { + let p: &[f64; 6]; + let q: &[f64; 6]; + let s: f64; + let r: f64; + let z: f64; + let mut ix: u32; + + ix = get_high_word(x); + ix &= 0x7fffffff; + if ix >= 0x40200000 { + p = &QR8; + q = &QS8; + } else if ix >= 0x40122E8B { + p = &QR5; + q = &QS5; + } else if ix >= 0x4006DB6D { + p = &QR3; + q = &QS3; + } else + /*ix >= 0x40000000*/ + { + p = &QR2; + q = &QS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5]))))); + return (-0.125 + r / s) / x; +} diff --git a/vendor/libm/src/math/j0f.rs b/vendor/libm/src/math/j0f.rs new file mode 100644 index 0000000000..91c03dbbcd --- /dev/null +++ b/vendor/libm/src/math/j0f.rs @@ -0,0 +1,359 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_j0f.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{cosf, fabsf, logf, sinf, sqrtf}; + +const INVSQRTPI: f32 = 5.6418961287e-01; /* 0x3f106ebb */ +const TPI: f32 = 6.3661974669e-01; /* 0x3f22f983 */ + +fn common(ix: u32, x: f32, y0: bool) -> f32 { + let z: f32; + let s: f32; + let mut c: f32; + let mut ss: f32; + let mut cc: f32; + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + s = sinf(x); + c = cosf(x); + if y0 { + c = -c; + } + cc = s + c; + if ix < 0x7f000000 { + ss = s - c; + z = -cosf(2.0 * x); + if s * c < 0.0 { + cc = z / ss; + } else { + ss = z / cc; + } + if ix < 0x58800000 { + if y0 { + ss = -ss; + } + cc = pzerof(x) * cc - qzerof(x) * ss; + } + } + return INVSQRTPI * cc / sqrtf(x); +} + +/* R0/S0 on [0, 2.00] */ +const R02: f32 = 1.5625000000e-02; /* 0x3c800000 */ +const R03: f32 = -1.8997929874e-04; /* 0xb947352e */ +const R04: f32 = 1.8295404516e-06; /* 0x35f58e88 */ +const R05: f32 = -4.6183270541e-09; /* 0xb19eaf3c */ +const S01: f32 = 1.5619102865e-02; /* 0x3c7fe744 */ +const S02: f32 = 1.1692678527e-04; /* 0x38f53697 */ +const S03: f32 = 5.1354652442e-07; /* 0x3509daa6 */ +const S04: f32 = 1.1661400734e-09; /* 0x30a045e8 */ + +pub fn j0f(mut x: f32) -> f32 { + let z: f32; + let r: f32; + let s: f32; + let mut ix: u32; + + ix = x.to_bits(); + ix &= 0x7fffffff; + if ix >= 0x7f800000 { + return 1.0 / (x * x); + } + x = fabsf(x); + + if ix >= 0x40000000 { + /* |x| >= 2 */ + /* large ulp error near zeros */ + return common(ix, x, false); + } + if ix >= 0x3a000000 { + /* |x| >= 2**-11 */ + /* up to 4ulp error near 2 */ + z = x * x; + r = z * (R02 + z * (R03 + z * (R04 + z * R05))); + s = 1.0 + z * (S01 + z * (S02 + z * (S03 + z * S04))); + return (1.0 + x / 2.0) * (1.0 - x / 2.0) + z * (r / s); + } + if ix >= 0x21800000 { + /* |x| >= 2**-60 */ + x = 0.25 * x * x; + } + return 1.0 - x; +} + +const U00: f32 = -7.3804296553e-02; /* 0xbd9726b5 */ +const U01: f32 = 1.7666645348e-01; /* 0x3e34e80d */ +const U02: f32 = -1.3818567619e-02; /* 0xbc626746 */ +const U03: f32 = 3.4745343146e-04; /* 0x39b62a69 */ +const U04: f32 = -3.8140706238e-06; /* 0xb67ff53c */ +const U05: f32 = 1.9559013964e-08; /* 0x32a802ba */ +const U06: f32 = -3.9820518410e-11; /* 0xae2f21eb */ +const V01: f32 = 1.2730483897e-02; /* 0x3c509385 */ +const V02: f32 = 7.6006865129e-05; /* 0x389f65e0 */ +const V03: f32 = 2.5915085189e-07; /* 0x348b216c */ +const V04: f32 = 4.4111031494e-10; /* 0x2ff280c2 */ + +pub fn y0f(x: f32) -> f32 { + let z: f32; + let u: f32; + let v: f32; + let ix: u32; + + ix = x.to_bits(); + if (ix & 0x7fffffff) == 0 { + return -1.0 / 0.0; + } + if (ix >> 31) != 0 { + return 0.0 / 0.0; + } + if ix >= 0x7f800000 { + return 1.0 / x; + } + if ix >= 0x40000000 { + /* |x| >= 2.0 */ + /* large ulp error near zeros */ + return common(ix, x, true); + } + if ix >= 0x39000000 { + /* x >= 2**-13 */ + /* large ulp error at x ~= 0.89 */ + z = x * x; + u = U00 + z * (U01 + z * (U02 + z * (U03 + z * (U04 + z * (U05 + z * U06))))); + v = 1.0 + z * (V01 + z * (V02 + z * (V03 + z * V04))); + return u / v + TPI * (j0f(x) * logf(x)); + } + return U00 + TPI * logf(x); +} + +/* The asymptotic expansions of pzero is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate pzero by + * pzero(x) = 1 + (R/S) + * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 + * S = 1 + pS0*s^2 + ... + pS4*s^10 + * and + * | pzero(x)-1-R/S | <= 2 ** ( -60.26) + */ +const PR8: [f32; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.0000000000e+00, /* 0x00000000 */ + -7.0312500000e-02, /* 0xbd900000 */ + -8.0816707611e+00, /* 0xc1014e86 */ + -2.5706311035e+02, /* 0xc3808814 */ + -2.4852163086e+03, /* 0xc51b5376 */ + -5.2530439453e+03, /* 0xc5a4285a */ +]; +const PS8: [f32; 5] = [ + 1.1653436279e+02, /* 0x42e91198 */ + 3.8337448730e+03, /* 0x456f9beb */ + 4.0597855469e+04, /* 0x471e95db */ + 1.1675296875e+05, /* 0x47e4087c */ + 4.7627726562e+04, /* 0x473a0bba */ +]; +const PR5: [f32; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -1.1412546255e-11, /* 0xad48c58a */ + -7.0312492549e-02, /* 0xbd8fffff */ + -4.1596107483e+00, /* 0xc0851b88 */ + -6.7674766541e+01, /* 0xc287597b */ + -3.3123129272e+02, /* 0xc3a59d9b */ + -3.4643338013e+02, /* 0xc3ad3779 */ +]; +const PS5: [f32; 5] = [ + 6.0753936768e+01, /* 0x42730408 */ + 1.0512523193e+03, /* 0x44836813 */ + 5.9789707031e+03, /* 0x45bad7c4 */ + 9.6254453125e+03, /* 0x461665c8 */ + 2.4060581055e+03, /* 0x451660ee */ +]; + +const PR3: [f32; 6] = [ + /* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + -2.5470459075e-09, /* 0xb12f081b */ + -7.0311963558e-02, /* 0xbd8fffb8 */ + -2.4090321064e+00, /* 0xc01a2d95 */ + -2.1965976715e+01, /* 0xc1afba52 */ + -5.8079170227e+01, /* 0xc2685112 */ + -3.1447946548e+01, /* 0xc1fb9565 */ +]; +const PS3: [f32; 5] = [ + 3.5856033325e+01, /* 0x420f6c94 */ + 3.6151397705e+02, /* 0x43b4c1ca */ + 1.1936077881e+03, /* 0x44953373 */ + 1.1279968262e+03, /* 0x448cffe6 */ + 1.7358093262e+02, /* 0x432d94b8 */ +]; + +const PR2: [f32; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + -8.8753431271e-08, /* 0xb3be98b7 */ + -7.0303097367e-02, /* 0xbd8ffb12 */ + -1.4507384300e+00, /* 0xbfb9b1cc */ + -7.6356959343e+00, /* 0xc0f4579f */ + -1.1193166733e+01, /* 0xc1331736 */ + -3.2336456776e+00, /* 0xc04ef40d */ +]; +const PS2: [f32; 5] = [ + 2.2220300674e+01, /* 0x41b1c32d */ + 1.3620678711e+02, /* 0x430834f0 */ + 2.7047027588e+02, /* 0x43873c32 */ + 1.5387539673e+02, /* 0x4319e01a */ + 1.4657617569e+01, /* 0x416a859a */ +]; + +fn pzerof(x: f32) -> f32 { + let p: &[f32; 6]; + let q: &[f32; 5]; + let z: f32; + let r: f32; + let s: f32; + let mut ix: u32; + + ix = x.to_bits(); + ix &= 0x7fffffff; + if ix >= 0x41000000 { + p = &PR8; + q = &PS8; + } else if ix >= 0x409173eb { + p = &PR5; + q = &PS5; + } else if ix >= 0x4036d917 { + p = &PR3; + q = &PS3; + } else + /*ix >= 0x40000000*/ + { + p = &PR2; + q = &PS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4])))); + return 1.0 + r / s; +} + +/* For x >= 8, the asymptotic expansions of qzero is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate pzero by + * qzero(x) = s*(-1.25 + (R/S)) + * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 + * S = 1 + qS0*s^2 + ... + qS5*s^12 + * and + * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) + */ +const QR8: [f32; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.0000000000e+00, /* 0x00000000 */ + 7.3242187500e-02, /* 0x3d960000 */ + 1.1768206596e+01, /* 0x413c4a93 */ + 5.5767340088e+02, /* 0x440b6b19 */ + 8.8591972656e+03, /* 0x460a6cca */ + 3.7014625000e+04, /* 0x471096a0 */ +]; +const QS8: [f32; 6] = [ + 1.6377603149e+02, /* 0x4323c6aa */ + 8.0983447266e+03, /* 0x45fd12c2 */ + 1.4253829688e+05, /* 0x480b3293 */ + 8.0330925000e+05, /* 0x49441ed4 */ + 8.4050156250e+05, /* 0x494d3359 */ + -3.4389928125e+05, /* 0xc8a7eb69 */ +]; + +const QR5: [f32; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.8408595828e-11, /* 0x2da1ec79 */ + 7.3242180049e-02, /* 0x3d95ffff */ + 5.8356351852e+00, /* 0x40babd86 */ + 1.3511157227e+02, /* 0x43071c90 */ + 1.0272437744e+03, /* 0x448067cd */ + 1.9899779053e+03, /* 0x44f8bf4b */ +]; +const QS5: [f32; 6] = [ + 8.2776611328e+01, /* 0x42a58da0 */ + 2.0778142090e+03, /* 0x4501dd07 */ + 1.8847289062e+04, /* 0x46933e94 */ + 5.6751113281e+04, /* 0x475daf1d */ + 3.5976753906e+04, /* 0x470c88c1 */ + -5.3543427734e+03, /* 0xc5a752be */ +]; + +const QR3: [f32; 6] = [ + /* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + 4.3774099900e-09, /* 0x3196681b */ + 7.3241114616e-02, /* 0x3d95ff70 */ + 3.3442313671e+00, /* 0x405607e3 */ + 4.2621845245e+01, /* 0x422a7cc5 */ + 1.7080809021e+02, /* 0x432acedf */ + 1.6673394775e+02, /* 0x4326bbe4 */ +]; +const QS3: [f32; 6] = [ + 4.8758872986e+01, /* 0x42430916 */ + 7.0968920898e+02, /* 0x44316c1c */ + 3.7041481934e+03, /* 0x4567825f */ + 6.4604252930e+03, /* 0x45c9e367 */ + 2.5163337402e+03, /* 0x451d4557 */ + -1.4924745178e+02, /* 0xc3153f59 */ +]; + +const QR2: [f32; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.5044444979e-07, /* 0x342189db */ + 7.3223426938e-02, /* 0x3d95f62a */ + 1.9981917143e+00, /* 0x3fffc4bf */ + 1.4495602608e+01, /* 0x4167edfd */ + 3.1666231155e+01, /* 0x41fd5471 */ + 1.6252708435e+01, /* 0x4182058c */ +]; +const QS2: [f32; 6] = [ + 3.0365585327e+01, /* 0x41f2ecb8 */ + 2.6934811401e+02, /* 0x4386ac8f */ + 8.4478375244e+02, /* 0x44533229 */ + 8.8293585205e+02, /* 0x445cbbe5 */ + 2.1266638184e+02, /* 0x4354aa98 */ + -5.3109550476e+00, /* 0xc0a9f358 */ +]; + +fn qzerof(x: f32) -> f32 { + let p: &[f32; 6]; + let q: &[f32; 6]; + let s: f32; + let r: f32; + let z: f32; + let mut ix: u32; + + ix = x.to_bits(); + ix &= 0x7fffffff; + if ix >= 0x41000000 { + p = &QR8; + q = &QS8; + } else if ix >= 0x409173eb { + p = &QR5; + q = &QS5; + } else if ix >= 0x4036d917 { + p = &QR3; + q = &QS3; + } else + /*ix >= 0x40000000*/ + { + p = &QR2; + q = &QS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5]))))); + return (-0.125 + r / s) / x; +} diff --git a/vendor/libm/src/math/j1.rs b/vendor/libm/src/math/j1.rs new file mode 100644 index 0000000000..02a65ca5a2 --- /dev/null +++ b/vendor/libm/src/math/j1.rs @@ -0,0 +1,414 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_j1.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* j1(x), y1(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j1(x): + * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... + * 2. Reduce x to |x| since j1(x)=-j1(-x), and + * for x in (0,2) + * j1(x) = x/2 + x*z*R0/S0, where z = x*x; + * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) + * for x in (2,inf) + * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * as follow: + * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (sin(x) + cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j1(nan)= nan + * j1(0) = 0 + * j1(inf) = 0 + * + * Method -- y1(x): + * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN + * 2. For x<2. + * Since + * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) + * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. + * We use the following function to approximate y1, + * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 + * where for x in [0,2] (abs err less than 2**-65.89) + * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 + * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 + * Note: For tiny x, 1/x dominate y1 and hence + * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) + * 3. For x>=2. + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * by method mentioned above. + */ + +use super::{cos, fabs, get_high_word, get_low_word, log, sin, sqrt}; + +const INVSQRTPI: f64 = 5.64189583547756279280e-01; /* 0x3FE20DD7, 0x50429B6D */ +const TPI: f64 = 6.36619772367581382433e-01; /* 0x3FE45F30, 0x6DC9C883 */ + +fn common(ix: u32, x: f64, y1: bool, sign: bool) -> f64 { + let z: f64; + let mut s: f64; + let c: f64; + let mut ss: f64; + let mut cc: f64; + + /* + * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x-3pi/4)-q1(x)*sin(x-3pi/4)) + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x-3pi/4)+q1(x)*cos(x-3pi/4)) + * + * sin(x-3pi/4) = -(sin(x) + cos(x))/sqrt(2) + * cos(x-3pi/4) = (sin(x) - cos(x))/sqrt(2) + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + */ + s = sin(x); + if y1 { + s = -s; + } + c = cos(x); + cc = s - c; + if ix < 0x7fe00000 { + /* avoid overflow in 2*x */ + ss = -s - c; + z = cos(2.0 * x); + if s * c > 0.0 { + cc = z / ss; + } else { + ss = z / cc; + } + if ix < 0x48000000 { + if y1 { + ss = -ss; + } + cc = pone(x) * cc - qone(x) * ss; + } + } + if sign { + cc = -cc; + } + return INVSQRTPI * cc / sqrt(x); +} + +/* R0/S0 on [0,2] */ +const R00: f64 = -6.25000000000000000000e-02; /* 0xBFB00000, 0x00000000 */ +const R01: f64 = 1.40705666955189706048e-03; /* 0x3F570D9F, 0x98472C61 */ +const R02: f64 = -1.59955631084035597520e-05; /* 0xBEF0C5C6, 0xBA169668 */ +const R03: f64 = 4.96727999609584448412e-08; /* 0x3E6AAAFA, 0x46CA0BD9 */ +const S01: f64 = 1.91537599538363460805e-02; /* 0x3F939D0B, 0x12637E53 */ +const S02: f64 = 1.85946785588630915560e-04; /* 0x3F285F56, 0xB9CDF664 */ +const S03: f64 = 1.17718464042623683263e-06; /* 0x3EB3BFF8, 0x333F8498 */ +const S04: f64 = 5.04636257076217042715e-09; /* 0x3E35AC88, 0xC97DFF2C */ +const S05: f64 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ + +pub fn j1(x: f64) -> f64 { + let mut z: f64; + let r: f64; + let s: f64; + let mut ix: u32; + let sign: bool; + + ix = get_high_word(x); + sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + if ix >= 0x7ff00000 { + return 1.0 / (x * x); + } + if ix >= 0x40000000 { + /* |x| >= 2 */ + return common(ix, fabs(x), false, sign); + } + if ix >= 0x38000000 { + /* |x| >= 2**-127 */ + z = x * x; + r = z * (R00 + z * (R01 + z * (R02 + z * R03))); + s = 1.0 + z * (S01 + z * (S02 + z * (S03 + z * (S04 + z * S05)))); + z = r / s; + } else { + /* avoid underflow, raise inexact if x!=0 */ + z = x; + } + return (0.5 + z) * x; +} + +const U0: [f64; 5] = [ + -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ + 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ + -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ + 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ + -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ +]; +const V0: [f64; 5] = [ + 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ + 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ + 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ + 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ + 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ +]; + +pub fn y1(x: f64) -> f64 { + let z: f64; + let u: f64; + let v: f64; + let ix: u32; + let lx: u32; + + ix = get_high_word(x); + lx = get_low_word(x); + + /* y1(nan)=nan, y1(<0)=nan, y1(0)=-inf, y1(inf)=0 */ + if (ix << 1 | lx) == 0 { + return -1.0 / 0.0; + } + if (ix >> 31) != 0 { + return 0.0 / 0.0; + } + if ix >= 0x7ff00000 { + return 1.0 / x; + } + + if ix >= 0x40000000 { + /* x >= 2 */ + return common(ix, x, true, false); + } + if ix < 0x3c900000 { + /* x < 2**-54 */ + return -TPI / x; + } + z = x * x; + u = U0[0] + z * (U0[1] + z * (U0[2] + z * (U0[3] + z * U0[4]))); + v = 1.0 + z * (V0[0] + z * (V0[1] + z * (V0[2] + z * (V0[3] + z * V0[4])))); + return x * (u / v) + TPI * (j1(x) * log(x) - 1.0 / x); +} + +/* For x >= 8, the asymptotic expansions of pone is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate pone by + * pone(x) = 1 + (R/S) + * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 + * S = 1 + ps0*s^2 + ... + ps4*s^10 + * and + * | pone(x)-1-R/S | <= 2 ** ( -60.06) + */ + +const PR8: [f64; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ + 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ + 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ + 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ + 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ +]; +const PS8: [f64; 5] = [ + 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ + 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ + 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ + 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ + 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ +]; + +const PR5: [f64; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ + 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ + 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ + 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ + 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ + 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ +]; +const PS5: [f64; 5] = [ + 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ + 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ + 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ + 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ + 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ +]; + +const PR3: [f64; 6] = [ + 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ + 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ + 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ + 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ + 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ + 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ +]; +const PS3: [f64; 5] = [ + 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ + 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ + 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ + 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ + 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ +]; + +const PR2: [f64; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ + 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ + 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ + 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ + 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ + 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ +]; +const PS2: [f64; 5] = [ + 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ + 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ + 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ + 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ + 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ +]; + +fn pone(x: f64) -> f64 { + let p: &[f64; 6]; + let q: &[f64; 5]; + let z: f64; + let r: f64; + let s: f64; + let mut ix: u32; + + ix = get_high_word(x); + ix &= 0x7fffffff; + if ix >= 0x40200000 { + p = &PR8; + q = &PS8; + } else if ix >= 0x40122E8B { + p = &PR5; + q = &PS5; + } else if ix >= 0x4006DB6D { + p = &PR3; + q = &PS3; + } else + /*ix >= 0x40000000*/ + { + p = &PR2; + q = &PS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4])))); + return 1.0 + r / s; +} + +/* For x >= 8, the asymptotic expansions of qone is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate pone by + * qone(x) = s*(0.375 + (R/S)) + * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 + * S = 1 + qs1*s^2 + ... + qs6*s^12 + * and + * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) + */ + +const QR8: [f64; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ + -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ + -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ + -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ + -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ +]; +const QS8: [f64; 6] = [ + 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ + 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ + 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ + 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ + 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ + -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ +]; + +const QR5: [f64; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ + -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ + -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ + -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ + -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ + -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ +]; +const QS5: [f64; 6] = [ + 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ + 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ + 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ + 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ + 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ + -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ +]; + +const QR3: [f64; 6] = [ + -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ + -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ + -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ + -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ + -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ + -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ +]; +const QS3: [f64; 6] = [ + 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ + 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ + 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ + 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ + 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ + -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ +]; + +const QR2: [f64; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ + -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ + -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ + -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ + -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ + -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ +]; +const QS2: [f64; 6] = [ + 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ + 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ + 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ + 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ + 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ + -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ +]; + +fn qone(x: f64) -> f64 { + let p: &[f64; 6]; + let q: &[f64; 6]; + let s: f64; + let r: f64; + let z: f64; + let mut ix: u32; + + ix = get_high_word(x); + ix &= 0x7fffffff; + if ix >= 0x40200000 { + p = &QR8; + q = &QS8; + } else if ix >= 0x40122E8B { + p = &QR5; + q = &QS5; + } else if ix >= 0x4006DB6D { + p = &QR3; + q = &QS3; + } else + /*ix >= 0x40000000*/ + { + p = &QR2; + q = &QS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5]))))); + return (0.375 + r / s) / x; +} diff --git a/vendor/libm/src/math/j1f.rs b/vendor/libm/src/math/j1f.rs new file mode 100644 index 0000000000..83ac1acffd --- /dev/null +++ b/vendor/libm/src/math/j1f.rs @@ -0,0 +1,358 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_j1f.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{cosf, fabsf, logf, sinf, sqrtf}; + +const INVSQRTPI: f32 = 5.6418961287e-01; /* 0x3f106ebb */ +const TPI: f32 = 6.3661974669e-01; /* 0x3f22f983 */ + +fn common(ix: u32, x: f32, y1: bool, sign: bool) -> f32 { + let z: f64; + let mut s: f64; + let c: f64; + let mut ss: f64; + let mut cc: f64; + + s = sinf(x) as f64; + if y1 { + s = -s; + } + c = cosf(x) as f64; + cc = s - c; + if ix < 0x7f000000 { + ss = -s - c; + z = cosf(2.0 * x) as f64; + if s * c > 0.0 { + cc = z / ss; + } else { + ss = z / cc; + } + if ix < 0x58800000 { + if y1 { + ss = -ss; + } + cc = (ponef(x) as f64) * cc - (qonef(x) as f64) * ss; + } + } + if sign { + cc = -cc; + } + return INVSQRTPI * (cc as f32) / sqrtf(x); +} + +/* R0/S0 on [0,2] */ +const R00: f32 = -6.2500000000e-02; /* 0xbd800000 */ +const R01: f32 = 1.4070566976e-03; /* 0x3ab86cfd */ +const R02: f32 = -1.5995563444e-05; /* 0xb7862e36 */ +const R03: f32 = 4.9672799207e-08; /* 0x335557d2 */ +const S01: f32 = 1.9153760746e-02; /* 0x3c9ce859 */ +const S02: f32 = 1.8594678841e-04; /* 0x3942fab6 */ +const S03: f32 = 1.1771846857e-06; /* 0x359dffc2 */ +const S04: f32 = 5.0463624390e-09; /* 0x31ad6446 */ +const S05: f32 = 1.2354227016e-11; /* 0x2d59567e */ + +pub fn j1f(x: f32) -> f32 { + let mut z: f32; + let r: f32; + let s: f32; + let mut ix: u32; + let sign: bool; + + ix = x.to_bits(); + sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + if ix >= 0x7f800000 { + return 1.0 / (x * x); + } + if ix >= 0x40000000 { + /* |x| >= 2 */ + return common(ix, fabsf(x), false, sign); + } + if ix >= 0x39000000 { + /* |x| >= 2**-13 */ + z = x * x; + r = z * (R00 + z * (R01 + z * (R02 + z * R03))); + s = 1.0 + z * (S01 + z * (S02 + z * (S03 + z * (S04 + z * S05)))); + z = 0.5 + r / s; + } else { + z = 0.5; + } + return z * x; +} + +const U0: [f32; 5] = [ + -1.9605709612e-01, /* 0xbe48c331 */ + 5.0443872809e-02, /* 0x3d4e9e3c */ + -1.9125689287e-03, /* 0xbafaaf2a */ + 2.3525259166e-05, /* 0x37c5581c */ + -9.1909917899e-08, /* 0xb3c56003 */ +]; +const V0: [f32; 5] = [ + 1.9916731864e-02, /* 0x3ca3286a */ + 2.0255257550e-04, /* 0x3954644b */ + 1.3560879779e-06, /* 0x35b602d4 */ + 6.2274145840e-09, /* 0x31d5f8eb */ + 1.6655924903e-11, /* 0x2d9281cf */ +]; + +pub fn y1f(x: f32) -> f32 { + let z: f32; + let u: f32; + let v: f32; + let ix: u32; + + ix = x.to_bits(); + if (ix & 0x7fffffff) == 0 { + return -1.0 / 0.0; + } + if (ix >> 31) != 0 { + return 0.0 / 0.0; + } + if ix >= 0x7f800000 { + return 1.0 / x; + } + if ix >= 0x40000000 { + /* |x| >= 2.0 */ + return common(ix, x, true, false); + } + if ix < 0x33000000 { + /* x < 2**-25 */ + return -TPI / x; + } + z = x * x; + u = U0[0] + z * (U0[1] + z * (U0[2] + z * (U0[3] + z * U0[4]))); + v = 1.0 + z * (V0[0] + z * (V0[1] + z * (V0[2] + z * (V0[3] + z * V0[4])))); + return x * (u / v) + TPI * (j1f(x) * logf(x) - 1.0 / x); +} + +/* For x >= 8, the asymptotic expansions of pone is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate pone by + * pone(x) = 1 + (R/S) + * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 + * S = 1 + ps0*s^2 + ... + ps4*s^10 + * and + * | pone(x)-1-R/S | <= 2 ** ( -60.06) + */ + +const PR8: [f32; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.0000000000e+00, /* 0x00000000 */ + 1.1718750000e-01, /* 0x3df00000 */ + 1.3239480972e+01, /* 0x4153d4ea */ + 4.1205184937e+02, /* 0x43ce06a3 */ + 3.8747453613e+03, /* 0x45722bed */ + 7.9144794922e+03, /* 0x45f753d6 */ +]; +const PS8: [f32; 5] = [ + 1.1420736694e+02, /* 0x42e46a2c */ + 3.6509309082e+03, /* 0x45642ee5 */ + 3.6956207031e+04, /* 0x47105c35 */ + 9.7602796875e+04, /* 0x47bea166 */ + 3.0804271484e+04, /* 0x46f0a88b */ +]; + +const PR5: [f32; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.3199052094e-11, /* 0x2d68333f */ + 1.1718749255e-01, /* 0x3defffff */ + 6.8027510643e+00, /* 0x40d9b023 */ + 1.0830818176e+02, /* 0x42d89dca */ + 5.1763616943e+02, /* 0x440168b7 */ + 5.2871520996e+02, /* 0x44042dc6 */ +]; +const PS5: [f32; 5] = [ + 5.9280597687e+01, /* 0x426d1f55 */ + 9.9140142822e+02, /* 0x4477d9b1 */ + 5.3532670898e+03, /* 0x45a74a23 */ + 7.8446904297e+03, /* 0x45f52586 */ + 1.5040468750e+03, /* 0x44bc0180 */ +]; + +const PR3: [f32; 6] = [ + 3.0250391081e-09, /* 0x314fe10d */ + 1.1718686670e-01, /* 0x3defffab */ + 3.9329774380e+00, /* 0x407bb5e7 */ + 3.5119403839e+01, /* 0x420c7a45 */ + 9.1055007935e+01, /* 0x42b61c2a */ + 4.8559066772e+01, /* 0x42423c7c */ +]; +const PS3: [f32; 5] = [ + 3.4791309357e+01, /* 0x420b2a4d */ + 3.3676245117e+02, /* 0x43a86198 */ + 1.0468714600e+03, /* 0x4482dbe3 */ + 8.9081134033e+02, /* 0x445eb3ed */ + 1.0378793335e+02, /* 0x42cf936c */ +]; + +const PR2: [f32; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.0771083225e-07, /* 0x33e74ea8 */ + 1.1717621982e-01, /* 0x3deffa16 */ + 2.3685150146e+00, /* 0x401795c0 */ + 1.2242610931e+01, /* 0x4143e1bc */ + 1.7693971634e+01, /* 0x418d8d41 */ + 5.0735230446e+00, /* 0x40a25a4d */ +]; +const PS2: [f32; 5] = [ + 2.1436485291e+01, /* 0x41ab7dec */ + 1.2529022980e+02, /* 0x42fa9499 */ + 2.3227647400e+02, /* 0x436846c7 */ + 1.1767937469e+02, /* 0x42eb5bd7 */ + 8.3646392822e+00, /* 0x4105d590 */ +]; + +fn ponef(x: f32) -> f32 { + let p: &[f32; 6]; + let q: &[f32; 5]; + let z: f32; + let r: f32; + let s: f32; + let mut ix: u32; + + ix = x.to_bits(); + ix &= 0x7fffffff; + if ix >= 0x41000000 { + p = &PR8; + q = &PS8; + } else if ix >= 0x409173eb { + p = &PR5; + q = &PS5; + } else if ix >= 0x4036d917 { + p = &PR3; + q = &PS3; + } else + /*ix >= 0x40000000*/ + { + p = &PR2; + q = &PS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4])))); + return 1.0 + r / s; +} + +/* For x >= 8, the asymptotic expansions of qone is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate pone by + * qone(x) = s*(0.375 + (R/S)) + * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 + * S = 1 + qs1*s^2 + ... + qs6*s^12 + * and + * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) + */ + +const QR8: [f32; 6] = [ + /* for x in [inf, 8]=1/[0,0.125] */ + 0.0000000000e+00, /* 0x00000000 */ + -1.0253906250e-01, /* 0xbdd20000 */ + -1.6271753311e+01, /* 0xc1822c8d */ + -7.5960174561e+02, /* 0xc43de683 */ + -1.1849806641e+04, /* 0xc639273a */ + -4.8438511719e+04, /* 0xc73d3683 */ +]; +const QS8: [f32; 6] = [ + 1.6139537048e+02, /* 0x43216537 */ + 7.8253862305e+03, /* 0x45f48b17 */ + 1.3387534375e+05, /* 0x4802bcd6 */ + 7.1965775000e+05, /* 0x492fb29c */ + 6.6660125000e+05, /* 0x4922be94 */ + -2.9449025000e+05, /* 0xc88fcb48 */ +]; + +const QR5: [f32; 6] = [ + /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -2.0897993405e-11, /* 0xadb7d219 */ + -1.0253904760e-01, /* 0xbdd1fffe */ + -8.0564479828e+00, /* 0xc100e736 */ + -1.8366960144e+02, /* 0xc337ab6b */ + -1.3731937256e+03, /* 0xc4aba633 */ + -2.6124443359e+03, /* 0xc523471c */ +]; +const QS5: [f32; 6] = [ + 8.1276550293e+01, /* 0x42a28d98 */ + 1.9917987061e+03, /* 0x44f8f98f */ + 1.7468484375e+04, /* 0x468878f8 */ + 4.9851425781e+04, /* 0x4742bb6d */ + 2.7948074219e+04, /* 0x46da5826 */ + -4.7191835938e+03, /* 0xc5937978 */ +]; + +const QR3: [f32; 6] = [ + -5.0783124372e-09, /* 0xb1ae7d4f */ + -1.0253783315e-01, /* 0xbdd1ff5b */ + -4.6101160049e+00, /* 0xc0938612 */ + -5.7847221375e+01, /* 0xc267638e */ + -2.2824453735e+02, /* 0xc3643e9a */ + -2.1921012878e+02, /* 0xc35b35cb */ +]; +const QS3: [f32; 6] = [ + 4.7665153503e+01, /* 0x423ea91e */ + 6.7386511230e+02, /* 0x4428775e */ + 3.3801528320e+03, /* 0x45534272 */ + 5.5477290039e+03, /* 0x45ad5dd5 */ + 1.9031191406e+03, /* 0x44ede3d0 */ + -1.3520118713e+02, /* 0xc3073381 */ +]; + +const QR2: [f32; 6] = [ + /* for x in [2.8570,2]=1/[0.3499,0.5] */ + -1.7838172539e-07, /* 0xb43f8932 */ + -1.0251704603e-01, /* 0xbdd1f475 */ + -2.7522056103e+00, /* 0xc0302423 */ + -1.9663616180e+01, /* 0xc19d4f16 */ + -4.2325313568e+01, /* 0xc2294d1f */ + -2.1371921539e+01, /* 0xc1aaf9b2 */ +]; +const QS2: [f32; 6] = [ + 2.9533363342e+01, /* 0x41ec4454 */ + 2.5298155212e+02, /* 0x437cfb47 */ + 7.5750280762e+02, /* 0x443d602e */ + 7.3939318848e+02, /* 0x4438d92a */ + 1.5594900513e+02, /* 0x431bf2f2 */ + -4.9594988823e+00, /* 0xc09eb437 */ +]; + +fn qonef(x: f32) -> f32 { + let p: &[f32; 6]; + let q: &[f32; 6]; + let s: f32; + let r: f32; + let z: f32; + let mut ix: u32; + + ix = x.to_bits(); + ix &= 0x7fffffff; + if ix >= 0x41000000 { + p = &QR8; + q = &QS8; + } else if ix >= 0x409173eb { + p = &QR5; + q = &QS5; + } else if ix >= 0x4036d917 { + p = &QR3; + q = &QS3; + } else + /*ix >= 0x40000000*/ + { + p = &QR2; + q = &QS2; + } + z = 1.0 / (x * x); + r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5])))); + s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5]))))); + return (0.375 + r / s) / x; +} diff --git a/vendor/libm/src/math/jn.rs b/vendor/libm/src/math/jn.rs new file mode 100644 index 0000000000..1be167f846 --- /dev/null +++ b/vendor/libm/src/math/jn.rs @@ -0,0 +1,343 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_jn.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * jn(n, x), yn(n, x) + * floating point Bessel's function of the 1st and 2nd kind + * of order n + * + * Special cases: + * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; + * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. + * Note 2. About jn(n,x), yn(n,x) + * For n=0, j0(x) is called, + * for n=1, j1(x) is called, + * for n<=x, forward recursion is used starting + * from values of j0(x) and j1(x). + * for n>x, a continued fraction approximation to + * j(n,x)/j(n-1,x) is evaluated and then backward + * recursion is used starting from a supposed value + * for j(n,x). The resulting value of j(0,x) is + * compared with the actual value to correct the + * supposed value of j(n,x). + * + * yn(n,x) is similar in all respects, except + * that forward recursion is used for all + * values of n>1. + */ + +use super::{cos, fabs, get_high_word, get_low_word, j0, j1, log, sin, sqrt, y0, y1}; + +const INVSQRTPI: f64 = 5.64189583547756279280e-01; /* 0x3FE20DD7, 0x50429B6D */ + +pub fn jn(n: i32, mut x: f64) -> f64 { + let mut ix: u32; + let lx: u32; + let nm1: i32; + let mut i: i32; + let mut sign: bool; + let mut a: f64; + let mut b: f64; + let mut temp: f64; + + ix = get_high_word(x); + lx = get_low_word(x); + sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + + // -lx == !lx + 1 + if (ix | (lx | ((!lx).wrapping_add(1))) >> 31) > 0x7ff00000 { + /* nan */ + return x; + } + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + /* nm1 = |n|-1 is used instead of |n| to handle n==INT_MIN */ + if n == 0 { + return j0(x); + } + if n < 0 { + nm1 = -(n + 1); + x = -x; + sign = !sign; + } else { + nm1 = n - 1; + } + if nm1 == 0 { + return j1(x); + } + + sign &= (n & 1) != 0; /* even n: 0, odd n: signbit(x) */ + x = fabs(x); + if (ix | lx) == 0 || ix == 0x7ff00000 { + /* if x is 0 or inf */ + b = 0.0; + } else if (nm1 as f64) < x { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + if ix >= 0x52d00000 { + /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + temp = match nm1 & 3 { + 0 => -cos(x) + sin(x), + 1 => -cos(x) - sin(x), + 2 => cos(x) - sin(x), + 3 | _ => cos(x) + sin(x), + }; + b = INVSQRTPI * temp / sqrt(x); + } else { + a = j0(x); + b = j1(x); + i = 0; + while i < nm1 { + i += 1; + temp = b; + b = b * (2.0 * (i as f64) / x) - a; /* avoid underflow */ + a = temp; + } + } + } else { + if ix < 0x3e100000 { + /* x < 2**-29 */ + /* x is tiny, return the first Taylor expansion of J(n,x) + * J(n,x) = 1/n!*(x/2)^n - ... + */ + if nm1 > 32 { + /* underflow */ + b = 0.0; + } else { + temp = x * 0.5; + b = temp; + a = 1.0; + i = 2; + while i <= nm1 + 1 { + a *= i as f64; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + i += 1; + } + b = b / a; + } + } else { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + let mut t: f64; + let mut q0: f64; + let mut q1: f64; + let mut w: f64; + let h: f64; + let mut z: f64; + let mut tmp: f64; + let nf: f64; + + let mut k: i32; + + nf = (nm1 as f64) + 1.0; + w = 2.0 * nf / x; + h = 2.0 / x; + z = w + h; + q0 = w; + q1 = w * z - 1.0; + k = 1; + while q1 < 1.0e9 { + k += 1; + z += h; + tmp = z * q1 - q0; + q0 = q1; + q1 = tmp; + } + t = 0.0; + i = k; + while i >= 0 { + t = 1.0 / (2.0 * ((i as f64) + nf) / x - t); + i -= 1; + } + a = t; + b = 1.0; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result is + * likely underflow to zero + */ + tmp = nf * log(fabs(w)); + if tmp < 7.09782712893383973096e+02 { + i = nm1; + while i > 0 { + temp = b; + b = b * (2.0 * (i as f64)) / x - a; + a = temp; + i -= 1; + } + } else { + i = nm1; + while i > 0 { + temp = b; + b = b * (2.0 * (i as f64)) / x - a; + a = temp; + /* scale b to avoid spurious overflow */ + let x1p500 = f64::from_bits(0x5f30000000000000); // 0x1p500 == 2^500 + if b > x1p500 { + a /= b; + t /= b; + b = 1.0; + } + i -= 1; + } + } + z = j0(x); + w = j1(x); + if fabs(z) >= fabs(w) { + b = t * z / b; + } else { + b = t * w / a; + } + } + } + + if sign { + -b + } else { + b + } +} + +pub fn yn(n: i32, x: f64) -> f64 { + let mut ix: u32; + let lx: u32; + let mut ib: u32; + let nm1: i32; + let mut sign: bool; + let mut i: i32; + let mut a: f64; + let mut b: f64; + let mut temp: f64; + + ix = get_high_word(x); + lx = get_low_word(x); + sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + + // -lx == !lx + 1 + if (ix | (lx | ((!lx).wrapping_add(1))) >> 31) > 0x7ff00000 { + /* nan */ + return x; + } + if sign && (ix | lx) != 0 { + /* x < 0 */ + return 0.0 / 0.0; + } + if ix == 0x7ff00000 { + return 0.0; + } + + if n == 0 { + return y0(x); + } + if n < 0 { + nm1 = -(n + 1); + sign = (n & 1) != 0; + } else { + nm1 = n - 1; + sign = false; + } + if nm1 == 0 { + if sign { + return -y1(x); + } else { + return y1(x); + } + } + + if ix >= 0x52d00000 { + /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + temp = match nm1 & 3 { + 0 => -sin(x) - cos(x), + 1 => -sin(x) + cos(x), + 2 => sin(x) + cos(x), + 3 | _ => sin(x) - cos(x), + }; + b = INVSQRTPI * temp / sqrt(x); + } else { + a = y0(x); + b = y1(x); + /* quit if b is -inf */ + ib = get_high_word(b); + i = 0; + while i < nm1 && ib != 0xfff00000 { + i += 1; + temp = b; + b = (2.0 * (i as f64) / x) * b - a; + ib = get_high_word(b); + a = temp; + } + } + + if sign { + -b + } else { + b + } +} diff --git a/vendor/libm/src/math/jnf.rs b/vendor/libm/src/math/jnf.rs new file mode 100644 index 0000000000..360f62e201 --- /dev/null +++ b/vendor/libm/src/math/jnf.rs @@ -0,0 +1,259 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_jnf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{fabsf, j0f, j1f, logf, y0f, y1f}; + +pub fn jnf(n: i32, mut x: f32) -> f32 { + let mut ix: u32; + let mut nm1: i32; + let mut sign: bool; + let mut i: i32; + let mut a: f32; + let mut b: f32; + let mut temp: f32; + + ix = x.to_bits(); + sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + if ix > 0x7f800000 { + /* nan */ + return x; + } + + /* J(-n,x) = J(n,-x), use |n|-1 to avoid overflow in -n */ + if n == 0 { + return j0f(x); + } + if n < 0 { + nm1 = -(n + 1); + x = -x; + sign = !sign; + } else { + nm1 = n - 1; + } + if nm1 == 0 { + return j1f(x); + } + + sign &= (n & 1) != 0; /* even n: 0, odd n: signbit(x) */ + x = fabsf(x); + if ix == 0 || ix == 0x7f800000 { + /* if x is 0 or inf */ + b = 0.0; + } else if (nm1 as f32) < x { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + a = j0f(x); + b = j1f(x); + i = 0; + while i < nm1 { + i += 1; + temp = b; + b = b * (2.0 * (i as f32) / x) - a; + a = temp; + } + } else { + if ix < 0x35800000 { + /* x < 2**-20 */ + /* x is tiny, return the first Taylor expansion of J(n,x) + * J(n,x) = 1/n!*(x/2)^n - ... + */ + if nm1 > 8 { + /* underflow */ + nm1 = 8; + } + temp = 0.5 * x; + b = temp; + a = 1.0; + i = 2; + while i <= nm1 + 1 { + a *= i as f32; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + i += 1; + } + b = b / a; + } else { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + let mut t: f32; + let mut q0: f32; + let mut q1: f32; + let mut w: f32; + let h: f32; + let mut z: f32; + let mut tmp: f32; + let nf: f32; + let mut k: i32; + + nf = (nm1 as f32) + 1.0; + w = 2.0 * (nf as f32) / x; + h = 2.0 / x; + z = w + h; + q0 = w; + q1 = w * z - 1.0; + k = 1; + while q1 < 1.0e4 { + k += 1; + z += h; + tmp = z * q1 - q0; + q0 = q1; + q1 = tmp; + } + t = 0.0; + i = k; + while i >= 0 { + t = 1.0 / (2.0 * ((i as f32) + nf) / x - t); + i -= 1; + } + a = t; + b = 1.0; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result is + * likely underflow to zero + */ + tmp = nf * logf(fabsf(w)); + if tmp < 88.721679688 { + i = nm1; + while i > 0 { + temp = b; + b = 2.0 * (i as f32) * b / x - a; + a = temp; + i -= 1; + } + } else { + i = nm1; + while i > 0 { + temp = b; + b = 2.0 * (i as f32) * b / x - a; + a = temp; + /* scale b to avoid spurious overflow */ + let x1p60 = f32::from_bits(0x5d800000); // 0x1p60 == 2^60 + if b > x1p60 { + a /= b; + t /= b; + b = 1.0; + } + i -= 1; + } + } + z = j0f(x); + w = j1f(x); + if fabsf(z) >= fabsf(w) { + b = t * z / b; + } else { + b = t * w / a; + } + } + } + + if sign { + -b + } else { + b + } +} + +pub fn ynf(n: i32, x: f32) -> f32 { + let mut ix: u32; + let mut ib: u32; + let nm1: i32; + let mut sign: bool; + let mut i: i32; + let mut a: f32; + let mut b: f32; + let mut temp: f32; + + ix = x.to_bits(); + sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + if ix > 0x7f800000 { + /* nan */ + return x; + } + if sign && ix != 0 { + /* x < 0 */ + return 0.0 / 0.0; + } + if ix == 0x7f800000 { + return 0.0; + } + + if n == 0 { + return y0f(x); + } + if n < 0 { + nm1 = -(n + 1); + sign = (n & 1) != 0; + } else { + nm1 = n - 1; + sign = false; + } + if nm1 == 0 { + if sign { + return -y1f(x); + } else { + return y1f(x); + } + } + + a = y0f(x); + b = y1f(x); + /* quit if b is -inf */ + ib = b.to_bits(); + i = 0; + while i < nm1 && ib != 0xff800000 { + i += 1; + temp = b; + b = (2.0 * (i as f32) / x) * b - a; + ib = b.to_bits(); + a = temp; + } + + if sign { + -b + } else { + b + } +} diff --git a/vendor/libm/src/math/k_cos.rs b/vendor/libm/src/math/k_cos.rs new file mode 100644 index 0000000000..4687b369a6 --- /dev/null +++ b/vendor/libm/src/math/k_cos.rs @@ -0,0 +1,63 @@ +// origin: FreeBSD /usr/src/lib/msun/src/k_cos.c +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunSoft, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== + +const C1: f64 = 4.16666666666666019037e-02; /* 0x3FA55555, 0x5555554C */ +const C2: f64 = -1.38888888888741095749e-03; /* 0xBF56C16C, 0x16C15177 */ +const C3: f64 = 2.48015872894767294178e-05; /* 0x3EFA01A0, 0x19CB1590 */ +const C4: f64 = -2.75573143513906633035e-07; /* 0xBE927E4F, 0x809C52AD */ +const C5: f64 = 2.08757232129817482790e-09; /* 0x3E21EE9E, 0xBDB4B1C4 */ +const C6: f64 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +// kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 +// Input x is assumed to be bounded by ~pi/4 in magnitude. +// Input y is the tail of x. +// +// Algorithm +// 1. Since cos(-x) = cos(x), we need only to consider positive x. +// 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. +// 3. cos(x) is approximated by a polynomial of degree 14 on +// [0,pi/4] +// 4 14 +// cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x +// where the remez error is +// +// | 2 4 6 8 10 12 14 | -58 +// |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 +// | | +// +// 4 6 8 10 12 14 +// 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then +// cos(x) ~ 1 - x*x/2 + r +// since cos(x+y) ~ cos(x) - sin(x)*y +// ~ cos(x) - x*y, +// a correction term is necessary in cos(x) and hence +// cos(x+y) = 1 - (x*x/2 - (r - x*y)) +// For better accuracy, rearrange to +// cos(x+y) ~ w + (tmp + (r-x*y)) +// where w = 1 - x*x/2 and tmp is a tiny correction term +// (1 - x*x/2 == w + tmp exactly in infinite precision). +// The exactness of w + tmp in infinite precision depends on w +// and tmp having the same precision as x. If they have extra +// precision due to compiler bugs, then the extra precision is +// only good provided it is retained in all terms of the final +// expression for cos(). Retention happens in all cases tested +// under FreeBSD, so don't pessimize things by forcibly clipping +// any extra precision in w. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_cos(x: f64, y: f64) -> f64 { + let z = x * x; + let w = z * z; + let r = z * (C1 + z * (C2 + z * C3)) + w * w * (C4 + z * (C5 + z * C6)); + let hz = 0.5 * z; + let w = 1.0 - hz; + w + (((1.0 - w) - hz) + (z * r - x * y)) +} diff --git a/vendor/libm/src/math/k_cosf.rs b/vendor/libm/src/math/k_cosf.rs new file mode 100644 index 0000000000..79d0f238fc --- /dev/null +++ b/vendor/libm/src/math/k_cosf.rs @@ -0,0 +1,30 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_cosf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Debugged and optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */ +const C0: f64 = -0.499999997251031003120; /* -0x1ffffffd0c5e81.0p-54 */ +const C1: f64 = 0.0416666233237390631894; /* 0x155553e1053a42.0p-57 */ +const C2: f64 = -0.00138867637746099294692; /* -0x16c087e80f1e27.0p-62 */ +const C3: f64 = 0.0000243904487962774090654; /* 0x199342e0ee5069.0p-68 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_cosf(x: f64) -> f32 { + let z = x * x; + let w = z * z; + let r = C2 + z * C3; + (((1.0 + z * C0) + w * C1) + (w * z) * r) as f32 +} diff --git a/vendor/libm/src/math/k_expo2.rs b/vendor/libm/src/math/k_expo2.rs new file mode 100644 index 0000000000..0a9562eaea --- /dev/null +++ b/vendor/libm/src/math/k_expo2.rs @@ -0,0 +1,15 @@ +use super::exp; + +/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */ +const K: i32 = 2043; + +/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_expo2(x: f64) -> f64 { + let k_ln2 = f64::from_bits(0x40962066151add8b); + /* note that k is odd and scale*scale overflows */ + let scale = f64::from_bits(((((0x3ff + K / 2) as u32) << 20) as u64) << 32); + /* exp(x - k ln2) * 2**(k-1) */ + exp(x - k_ln2) * scale * scale +} diff --git a/vendor/libm/src/math/k_expo2f.rs b/vendor/libm/src/math/k_expo2f.rs new file mode 100644 index 0000000000..de85077725 --- /dev/null +++ b/vendor/libm/src/math/k_expo2f.rs @@ -0,0 +1,15 @@ +use super::expf; + +/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */ +const K: i32 = 235; + +/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_expo2f(x: f32) -> f32 { + let k_ln2 = f32::from_bits(0x4322e3bc); + /* note that k is odd and scale*scale overflows */ + let scale = f32::from_bits(((0x7f + K / 2) as u32) << 23); + /* exp(x - k ln2) * 2**(k-1) */ + expf(x - k_ln2) * scale * scale +} diff --git a/vendor/libm/src/math/k_sin.rs b/vendor/libm/src/math/k_sin.rs new file mode 100644 index 0000000000..5d2bd68aa9 --- /dev/null +++ b/vendor/libm/src/math/k_sin.rs @@ -0,0 +1,58 @@ +// origin: FreeBSD /usr/src/lib/msun/src/k_sin.c +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunSoft, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== + +const S1: f64 = -1.66666666666666324348e-01; /* 0xBFC55555, 0x55555549 */ +const S2: f64 = 8.33333333332248946124e-03; /* 0x3F811111, 0x1110F8A6 */ +const S3: f64 = -1.98412698298579493134e-04; /* 0xBF2A01A0, 0x19C161D5 */ +const S4: f64 = 2.75573137070700676789e-06; /* 0x3EC71DE3, 0x57B1FE7D */ +const S5: f64 = -2.50507602534068634195e-08; /* 0xBE5AE5E6, 0x8A2B9CEB */ +const S6: f64 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +// kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 +// Input x is assumed to be bounded by ~pi/4 in magnitude. +// Input y is the tail of x. +// Input iy indicates whether y is 0. (if iy=0, y assume to be 0). +// +// Algorithm +// 1. Since sin(-x) = -sin(x), we need only to consider positive x. +// 2. Callers must return sin(-0) = -0 without calling here since our +// odd polynomial is not evaluated in a way that preserves -0. +// Callers may do the optimization sin(x) ~ x for tiny x. +// 3. sin(x) is approximated by a polynomial of degree 13 on +// [0,pi/4] +// 3 13 +// sin(x) ~ x + S1*x + ... + S6*x +// where +// +// |sin(x) 2 4 6 8 10 12 | -58 +// |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 +// | x | +// +// 4. sin(x+y) = sin(x) + sin'(x')*y +// ~ sin(x) + (1-x*x/2)*y +// For better accuracy, let +// 3 2 2 2 2 +// r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) +// then 3 2 +// sin(x) = x + (S1*x + (x *(r-y/2)+y)) +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_sin(x: f64, y: f64, iy: i32) -> f64 { + let z = x * x; + let w = z * z; + let r = S2 + z * (S3 + z * S4) + z * w * (S5 + z * S6); + let v = z * x; + if iy == 0 { + x + v * (S1 + z * r) + } else { + x - ((z * (0.5 * y - v * r) - y) - v * S1) + } +} diff --git a/vendor/libm/src/math/k_sinf.rs b/vendor/libm/src/math/k_sinf.rs new file mode 100644 index 0000000000..68fe926c21 --- /dev/null +++ b/vendor/libm/src/math/k_sinf.rs @@ -0,0 +1,31 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_sinf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */ +const S1: f64 = -0.166666666416265235595; /* -0x15555554cbac77.0p-55 */ +const S2: f64 = 0.0083333293858894631756; /* 0x111110896efbb2.0p-59 */ +const S3: f64 = -0.000198393348360966317347; /* -0x1a00f9e2cae774.0p-65 */ +const S4: f64 = 0.0000027183114939898219064; /* 0x16cd878c3b46a7.0p-71 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_sinf(x: f64) -> f32 { + let z = x * x; + let w = z * z; + let r = S3 + z * S4; + let s = z * x; + ((x + s * (S1 + z * S2)) + s * w * r) as f32 +} diff --git a/vendor/libm/src/math/k_tan.rs b/vendor/libm/src/math/k_tan.rs new file mode 100644 index 0000000000..ea3c386b00 --- /dev/null +++ b/vendor/libm/src/math/k_tan.rs @@ -0,0 +1,107 @@ +// origin: FreeBSD /usr/src/lib/msun/src/k_tan.c */ +// +// ==================================================== +// Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. +// +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== + +// kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 +// Input x is assumed to be bounded by ~pi/4 in magnitude. +// Input y is the tail of x. +// Input odd indicates whether tan (if odd = 0) or -1/tan (if odd = 1) is returned. +// +// Algorithm +// 1. Since tan(-x) = -tan(x), we need only to consider positive x. +// 2. Callers must return tan(-0) = -0 without calling here since our +// odd polynomial is not evaluated in a way that preserves -0. +// Callers may do the optimization tan(x) ~ x for tiny x. +// 3. tan(x) is approximated by a odd polynomial of degree 27 on +// [0,0.67434] +// 3 27 +// tan(x) ~ x + T1*x + ... + T13*x +// where +// +// |tan(x) 2 4 26 | -59.2 +// |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 +// | x | +// +// Note: tan(x+y) = tan(x) + tan'(x)*y +// ~ tan(x) + (1+x*x)*y +// Therefore, for better accuracy in computing tan(x+y), let +// 3 2 2 2 2 +// r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) +// then +// 3 2 +// tan(x+y) = x + (T1*x + (x *(r+y)+y)) +// +// 4. For x in [0.67434,pi/4], let y = pi/4 - x, then +// tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) +// = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) +static T: [f64; 13] = [ + 3.33333333333334091986e-01, /* 3FD55555, 55555563 */ + 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */ + 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */ + 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */ + 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */ + 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */ + 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */ + 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */ + 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */ + 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */ + 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */ + -1.85586374855275456654e-05, /* BEF375CB, DB605373 */ + 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */ +]; +const PIO4: f64 = 7.85398163397448278999e-01; /* 3FE921FB, 54442D18 */ +const PIO4_LO: f64 = 3.06161699786838301793e-17; /* 3C81A626, 33145C07 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_tan(mut x: f64, mut y: f64, odd: i32) -> f64 { + let hx = (f64::to_bits(x) >> 32) as u32; + let big = (hx & 0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */ + if big { + let sign = hx >> 31; + if sign != 0 { + x = -x; + y = -y; + } + x = (PIO4 - x) + (PIO4_LO - y); + y = 0.0; + } + let z = x * x; + let w = z * z; + /* + * Break x^5*(T[1]+x^2*T[2]+...) into + * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) + */ + let r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11])))); + let v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12]))))); + let s = z * x; + let r = y + z * (s * (r + v) + y) + s * T[0]; + let w = x + r; + if big { + let sign = hx >> 31; + let s = 1.0 - 2.0 * odd as f64; + let v = s - 2.0 * (x + (r - w * w / (w + s))); + return if sign != 0 { -v } else { v }; + } + if odd == 0 { + return w; + } + /* -1.0/(x+r) has up to 2ulp error, so compute it accurately */ + let w0 = zero_low_word(w); + let v = r - (w0 - x); /* w0+v = r+x */ + let a = -1.0 / w; + let a0 = zero_low_word(a); + a0 + a * (1.0 + a0 * w0 + a0 * v) +} + +#[inline] +fn zero_low_word(x: f64) -> f64 { + f64::from_bits(f64::to_bits(x) & 0xFFFF_FFFF_0000_0000) +} diff --git a/vendor/libm/src/math/k_tanf.rs b/vendor/libm/src/math/k_tanf.rs new file mode 100644 index 0000000000..52651378db --- /dev/null +++ b/vendor/libm/src/math/k_tanf.rs @@ -0,0 +1,47 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_tan.c */ +/* + * ==================================================== + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* |tan(x)/x - t(x)| < 2**-25.5 (~[-2e-08, 2e-08]). */ +const T: [f64; 6] = [ + 0.333331395030791399758, /* 0x15554d3418c99f.0p-54 */ + 0.133392002712976742718, /* 0x1112fd38999f72.0p-55 */ + 0.0533812378445670393523, /* 0x1b54c91d865afe.0p-57 */ + 0.0245283181166547278873, /* 0x191df3908c33ce.0p-58 */ + 0.00297435743359967304927, /* 0x185dadfcecf44e.0p-61 */ + 0.00946564784943673166728, /* 0x1362b9bf971bcd.0p-59 */ +]; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn k_tanf(x: f64, odd: bool) -> f32 { + let z = x * x; + /* + * Split up the polynomial into small independent terms to give + * opportunities for parallel evaluation. The chosen splitting is + * micro-optimized for Athlons (XP, X64). It costs 2 multiplications + * relative to Horner's method on sequential machines. + * + * We add the small terms from lowest degree up for efficiency on + * non-sequential machines (the lowest degree terms tend to be ready + * earlier). Apart from this, we don't care about order of + * operations, and don't need to to care since we have precision to + * spare. However, the chosen splitting is good for accuracy too, + * and would give results as accurate as Horner's method if the + * small terms were added from highest degree down. + */ + let mut r = T[4] + z * T[5]; + let t = T[2] + z * T[3]; + let w = z * z; + let s = z * x; + let u = T[0] + z * T[1]; + r = (x + s * u) + (s * w) * (t + w * r); + (if odd { -1. / r } else { r }) as f32 +} diff --git a/vendor/libm/src/math/ldexp.rs b/vendor/libm/src/math/ldexp.rs new file mode 100644 index 0000000000..780ddfc116 --- /dev/null +++ b/vendor/libm/src/math/ldexp.rs @@ -0,0 +1,5 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn ldexp(x: f64, n: i32) -> f64 { + super::scalbn(x, n) +} diff --git a/vendor/libm/src/math/ldexpf.rs b/vendor/libm/src/math/ldexpf.rs new file mode 100644 index 0000000000..70935a0024 --- /dev/null +++ b/vendor/libm/src/math/ldexpf.rs @@ -0,0 +1,5 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn ldexpf(x: f32, n: i32) -> f32 { + super::scalbnf(x, n) +} diff --git a/vendor/libm/src/math/lgamma.rs b/vendor/libm/src/math/lgamma.rs new file mode 100644 index 0000000000..5bc87e85e8 --- /dev/null +++ b/vendor/libm/src/math/lgamma.rs @@ -0,0 +1,5 @@ +use super::lgamma_r; + +pub fn lgamma(x: f64) -> f64 { + lgamma_r(x).0 +} diff --git a/vendor/libm/src/math/lgamma_r.rs b/vendor/libm/src/math/lgamma_r.rs new file mode 100644 index 0000000000..382a501fc3 --- /dev/null +++ b/vendor/libm/src/math/lgamma_r.rs @@ -0,0 +1,319 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_lgamma_r.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ +/* lgamma_r(x, signgamp) + * Reentrant version of the logarithm of the Gamma function + * with user provide pointer for the sign of Gamma(x). + * + * Method: + * 1. Argument Reduction for 0 < x <= 8 + * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may + * reduce x to a number in [1.5,2.5] by + * lgamma(1+s) = log(s) + lgamma(s) + * for example, + * lgamma(7.3) = log(6.3) + lgamma(6.3) + * = log(6.3*5.3) + lgamma(5.3) + * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) + * 2. Polynomial approximation of lgamma around its + * minimun ymin=1.461632144968362245 to maintain monotonicity. + * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use + * Let z = x-ymin; + * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) + * where + * poly(z) is a 14 degree polynomial. + * 2. Rational approximation in the primary interval [2,3] + * We use the following approximation: + * s = x-2.0; + * lgamma(x) = 0.5*s + s*P(s)/Q(s) + * with accuracy + * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 + * Our algorithms are based on the following observation + * + * zeta(2)-1 2 zeta(3)-1 3 + * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... + * 2 3 + * + * where Euler = 0.5771... is the Euler constant, which is very + * close to 0.5. + * + * 3. For x>=8, we have + * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... + * (better formula: + * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) + * Let z = 1/x, then we approximation + * f(z) = lgamma(x) - (x-0.5)(log(x)-1) + * by + * 3 5 11 + * w = w0 + w1*z + w2*z + w3*z + ... + w6*z + * where + * |w - f(z)| < 2**-58.74 + * + * 4. For negative x, since (G is gamma function) + * -x*G(-x)*G(x) = PI/sin(PI*x), + * we have + * G(x) = PI/(sin(PI*x)*(-x)*G(-x)) + * since G(-x) is positive, sign(G(x)) = sign(sin(PI*x)) for x<0 + * Hence, for x<0, signgam = sign(sin(PI*x)) and + * lgamma(x) = log(|Gamma(x)|) + * = log(PI/(|x*sin(PI*x)|)) - lgamma(-x); + * Note: one should avoid compute PI*(-x) directly in the + * computation of sin(PI*(-x)). + * + * 5. Special Cases + * lgamma(2+s) ~ s*(1-Euler) for tiny s + * lgamma(1) = lgamma(2) = 0 + * lgamma(x) ~ -log(|x|) for tiny x + * lgamma(0) = lgamma(neg.integer) = inf and raise divide-by-zero + * lgamma(inf) = inf + * lgamma(-inf) = inf (bug for bug compatible with C99!?) + * + */ + +use super::{floor, k_cos, k_sin, log}; + +const PI: f64 = 3.14159265358979311600e+00; /* 0x400921FB, 0x54442D18 */ +const A0: f64 = 7.72156649015328655494e-02; /* 0x3FB3C467, 0xE37DB0C8 */ +const A1: f64 = 3.22467033424113591611e-01; /* 0x3FD4A34C, 0xC4A60FAD */ +const A2: f64 = 6.73523010531292681824e-02; /* 0x3FB13E00, 0x1A5562A7 */ +const A3: f64 = 2.05808084325167332806e-02; /* 0x3F951322, 0xAC92547B */ +const A4: f64 = 7.38555086081402883957e-03; /* 0x3F7E404F, 0xB68FEFE8 */ +const A5: f64 = 2.89051383673415629091e-03; /* 0x3F67ADD8, 0xCCB7926B */ +const A6: f64 = 1.19270763183362067845e-03; /* 0x3F538A94, 0x116F3F5D */ +const A7: f64 = 5.10069792153511336608e-04; /* 0x3F40B6C6, 0x89B99C00 */ +const A8: f64 = 2.20862790713908385557e-04; /* 0x3F2CF2EC, 0xED10E54D */ +const A9: f64 = 1.08011567247583939954e-04; /* 0x3F1C5088, 0x987DFB07 */ +const A10: f64 = 2.52144565451257326939e-05; /* 0x3EFA7074, 0x428CFA52 */ +const A11: f64 = 4.48640949618915160150e-05; /* 0x3F07858E, 0x90A45837 */ +const TC: f64 = 1.46163214496836224576e+00; /* 0x3FF762D8, 0x6356BE3F */ +const TF: f64 = -1.21486290535849611461e-01; /* 0xBFBF19B9, 0xBCC38A42 */ +/* tt = -(tail of TF) */ +const TT: f64 = -3.63867699703950536541e-18; /* 0xBC50C7CA, 0xA48A971F */ +const T0: f64 = 4.83836122723810047042e-01; /* 0x3FDEF72B, 0xC8EE38A2 */ +const T1: f64 = -1.47587722994593911752e-01; /* 0xBFC2E427, 0x8DC6C509 */ +const T2: f64 = 6.46249402391333854778e-02; /* 0x3FB08B42, 0x94D5419B */ +const T3: f64 = -3.27885410759859649565e-02; /* 0xBFA0C9A8, 0xDF35B713 */ +const T4: f64 = 1.79706750811820387126e-02; /* 0x3F9266E7, 0x970AF9EC */ +const T5: f64 = -1.03142241298341437450e-02; /* 0xBF851F9F, 0xBA91EC6A */ +const T6: f64 = 6.10053870246291332635e-03; /* 0x3F78FCE0, 0xE370E344 */ +const T7: f64 = -3.68452016781138256760e-03; /* 0xBF6E2EFF, 0xB3E914D7 */ +const T8: f64 = 2.25964780900612472250e-03; /* 0x3F6282D3, 0x2E15C915 */ +const T9: f64 = -1.40346469989232843813e-03; /* 0xBF56FE8E, 0xBF2D1AF1 */ +const T10: f64 = 8.81081882437654011382e-04; /* 0x3F4CDF0C, 0xEF61A8E9 */ +const T11: f64 = -5.38595305356740546715e-04; /* 0xBF41A610, 0x9C73E0EC */ +const T12: f64 = 3.15632070903625950361e-04; /* 0x3F34AF6D, 0x6C0EBBF7 */ +const T13: f64 = -3.12754168375120860518e-04; /* 0xBF347F24, 0xECC38C38 */ +const T14: f64 = 3.35529192635519073543e-04; /* 0x3F35FD3E, 0xE8C2D3F4 */ +const U0: f64 = -7.72156649015328655494e-02; /* 0xBFB3C467, 0xE37DB0C8 */ +const U1: f64 = 6.32827064025093366517e-01; /* 0x3FE4401E, 0x8B005DFF */ +const U2: f64 = 1.45492250137234768737e+00; /* 0x3FF7475C, 0xD119BD6F */ +const U3: f64 = 9.77717527963372745603e-01; /* 0x3FEF4976, 0x44EA8450 */ +const U4: f64 = 2.28963728064692451092e-01; /* 0x3FCD4EAE, 0xF6010924 */ +const U5: f64 = 1.33810918536787660377e-02; /* 0x3F8B678B, 0xBF2BAB09 */ +const V1: f64 = 2.45597793713041134822e+00; /* 0x4003A5D7, 0xC2BD619C */ +const V2: f64 = 2.12848976379893395361e+00; /* 0x40010725, 0xA42B18F5 */ +const V3: f64 = 7.69285150456672783825e-01; /* 0x3FE89DFB, 0xE45050AF */ +const V4: f64 = 1.04222645593369134254e-01; /* 0x3FBAAE55, 0xD6537C88 */ +const V5: f64 = 3.21709242282423911810e-03; /* 0x3F6A5ABB, 0x57D0CF61 */ +const S0: f64 = -7.72156649015328655494e-02; /* 0xBFB3C467, 0xE37DB0C8 */ +const S1: f64 = 2.14982415960608852501e-01; /* 0x3FCB848B, 0x36E20878 */ +const S2: f64 = 3.25778796408930981787e-01; /* 0x3FD4D98F, 0x4F139F59 */ +const S3: f64 = 1.46350472652464452805e-01; /* 0x3FC2BB9C, 0xBEE5F2F7 */ +const S4: f64 = 2.66422703033638609560e-02; /* 0x3F9B481C, 0x7E939961 */ +const S5: f64 = 1.84028451407337715652e-03; /* 0x3F5E26B6, 0x7368F239 */ +const S6: f64 = 3.19475326584100867617e-05; /* 0x3F00BFEC, 0xDD17E945 */ +const R1: f64 = 1.39200533467621045958e+00; /* 0x3FF645A7, 0x62C4AB74 */ +const R2: f64 = 7.21935547567138069525e-01; /* 0x3FE71A18, 0x93D3DCDC */ +const R3: f64 = 1.71933865632803078993e-01; /* 0x3FC601ED, 0xCCFBDF27 */ +const R4: f64 = 1.86459191715652901344e-02; /* 0x3F9317EA, 0x742ED475 */ +const R5: f64 = 7.77942496381893596434e-04; /* 0x3F497DDA, 0xCA41A95B */ +const R6: f64 = 7.32668430744625636189e-06; /* 0x3EDEBAF7, 0xA5B38140 */ +const W0: f64 = 4.18938533204672725052e-01; /* 0x3FDACFE3, 0x90C97D69 */ +const W1: f64 = 8.33333333333329678849e-02; /* 0x3FB55555, 0x5555553B */ +const W2: f64 = -2.77777777728775536470e-03; /* 0xBF66C16C, 0x16B02E5C */ +const W3: f64 = 7.93650558643019558500e-04; /* 0x3F4A019F, 0x98CF38B6 */ +const W4: f64 = -5.95187557450339963135e-04; /* 0xBF4380CB, 0x8C0FE741 */ +const W5: f64 = 8.36339918996282139126e-04; /* 0x3F4B67BA, 0x4CDAD5D1 */ +const W6: f64 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ + +/* sin(PI*x) assuming x > 2^-100, if sin(PI*x)==0 the sign is arbitrary */ +fn sin_pi(mut x: f64) -> f64 { + let mut n: i32; + + /* spurious inexact if odd int */ + x = 2.0 * (x * 0.5 - floor(x * 0.5)); /* x mod 2.0 */ + + n = (x * 4.0) as i32; + n = (n + 1) / 2; + x -= (n as f64) * 0.5; + x *= PI; + + match n { + 1 => k_cos(x, 0.0), + 2 => k_sin(-x, 0.0, 0), + 3 => -k_cos(x, 0.0), + 0 | _ => k_sin(x, 0.0, 0), + } +} + +pub fn lgamma_r(mut x: f64) -> (f64, i32) { + let u: u64 = x.to_bits(); + let mut t: f64; + let y: f64; + let mut z: f64; + let nadj: f64; + let p: f64; + let p1: f64; + let p2: f64; + let p3: f64; + let q: f64; + let mut r: f64; + let w: f64; + let ix: u32; + let sign: bool; + let i: i32; + let mut signgam: i32; + + /* purge off +-inf, NaN, +-0, tiny and negative arguments */ + signgam = 1; + sign = (u >> 63) != 0; + ix = ((u >> 32) as u32) & 0x7fffffff; + if ix >= 0x7ff00000 { + return (x * x, signgam); + } + if ix < (0x3ff - 70) << 20 { + /* |x|<2**-70, return -log(|x|) */ + if sign { + x = -x; + signgam = -1; + } + return (-log(x), signgam); + } + if sign { + x = -x; + t = sin_pi(x); + if t == 0.0 { + /* -integer */ + return (1.0 / (x - x), signgam); + } + if t > 0.0 { + signgam = -1; + } else { + t = -t; + } + nadj = log(PI / (t * x)); + } else { + nadj = 0.0; + } + + /* purge off 1 and 2 */ + if (ix == 0x3ff00000 || ix == 0x40000000) && (u & 0xffffffff) == 0 { + r = 0.0; + } + /* for x < 2.0 */ + else if ix < 0x40000000 { + if ix <= 0x3feccccc { + /* lgamma(x) = lgamma(x+1)-log(x) */ + r = -log(x); + if ix >= 0x3FE76944 { + y = 1.0 - x; + i = 0; + } else if ix >= 0x3FCDA661 { + y = x - (TC - 1.0); + i = 1; + } else { + y = x; + i = 2; + } + } else { + r = 0.0; + if ix >= 0x3FFBB4C3 { + /* [1.7316,2] */ + y = 2.0 - x; + i = 0; + } else if ix >= 0x3FF3B4C4 { + /* [1.23,1.73] */ + y = x - TC; + i = 1; + } else { + y = x - 1.0; + i = 2; + } + } + match i { + 0 => { + z = y * y; + p1 = A0 + z * (A2 + z * (A4 + z * (A6 + z * (A8 + z * A10)))); + p2 = z * (A1 + z * (A3 + z * (A5 + z * (A7 + z * (A9 + z * A11))))); + p = y * p1 + p2; + r += p - 0.5 * y; + } + 1 => { + z = y * y; + w = z * y; + p1 = T0 + w * (T3 + w * (T6 + w * (T9 + w * T12))); /* parallel comp */ + p2 = T1 + w * (T4 + w * (T7 + w * (T10 + w * T13))); + p3 = T2 + w * (T5 + w * (T8 + w * (T11 + w * T14))); + p = z * p1 - (TT - w * (p2 + y * p3)); + r += TF + p; + } + 2 => { + p1 = y * (U0 + y * (U1 + y * (U2 + y * (U3 + y * (U4 + y * U5))))); + p2 = 1.0 + y * (V1 + y * (V2 + y * (V3 + y * (V4 + y * V5)))); + r += -0.5 * y + p1 / p2; + } + #[cfg(feature = "checked")] + _ => unreachable!(), + #[cfg(not(feature = "checked"))] + _ => {} + } + } else if ix < 0x40200000 { + /* x < 8.0 */ + i = x as i32; + y = x - (i as f64); + p = y * (S0 + y * (S1 + y * (S2 + y * (S3 + y * (S4 + y * (S5 + y * S6)))))); + q = 1.0 + y * (R1 + y * (R2 + y * (R3 + y * (R4 + y * (R5 + y * R6))))); + r = 0.5 * y + p / q; + z = 1.0; /* lgamma(1+s) = log(s) + lgamma(s) */ + // TODO: In C, this was implemented using switch jumps with fallthrough. + // Does this implementation have performance problems? + if i >= 7 { + z *= y + 6.0; + } + if i >= 6 { + z *= y + 5.0; + } + if i >= 5 { + z *= y + 4.0; + } + if i >= 4 { + z *= y + 3.0; + } + if i >= 3 { + z *= y + 2.0; + r += log(z); + } + } else if ix < 0x43900000 { + /* 8.0 <= x < 2**58 */ + t = log(x); + z = 1.0 / x; + y = z * z; + w = W0 + z * (W1 + y * (W2 + y * (W3 + y * (W4 + y * (W5 + y * W6))))); + r = (x - 0.5) * (t - 1.0) + w; + } else { + /* 2**58 <= x <= inf */ + r = x * (log(x) - 1.0); + } + if sign { + r = nadj - r; + } + return (r, signgam); +} diff --git a/vendor/libm/src/math/lgammaf.rs b/vendor/libm/src/math/lgammaf.rs new file mode 100644 index 0000000000..dfdc87f962 --- /dev/null +++ b/vendor/libm/src/math/lgammaf.rs @@ -0,0 +1,5 @@ +use super::lgammaf_r; + +pub fn lgammaf(x: f32) -> f32 { + lgammaf_r(x).0 +} diff --git a/vendor/libm/src/math/lgammaf_r.rs b/vendor/libm/src/math/lgammaf_r.rs new file mode 100644 index 0000000000..0745359a25 --- /dev/null +++ b/vendor/libm/src/math/lgammaf_r.rs @@ -0,0 +1,254 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_lgammaf_r.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{floorf, k_cosf, k_sinf, logf}; + +const PI: f32 = 3.1415927410e+00; /* 0x40490fdb */ +const A0: f32 = 7.7215664089e-02; /* 0x3d9e233f */ +const A1: f32 = 3.2246702909e-01; /* 0x3ea51a66 */ +const A2: f32 = 6.7352302372e-02; /* 0x3d89f001 */ +const A3: f32 = 2.0580807701e-02; /* 0x3ca89915 */ +const A4: f32 = 7.3855509982e-03; /* 0x3bf2027e */ +const A5: f32 = 2.8905137442e-03; /* 0x3b3d6ec6 */ +const A6: f32 = 1.1927076848e-03; /* 0x3a9c54a1 */ +const A7: f32 = 5.1006977446e-04; /* 0x3a05b634 */ +const A8: f32 = 2.2086278477e-04; /* 0x39679767 */ +const A9: f32 = 1.0801156895e-04; /* 0x38e28445 */ +const A10: f32 = 2.5214456400e-05; /* 0x37d383a2 */ +const A11: f32 = 4.4864096708e-05; /* 0x383c2c75 */ +const TC: f32 = 1.4616321325e+00; /* 0x3fbb16c3 */ +const TF: f32 = -1.2148628384e-01; /* 0xbdf8cdcd */ +/* TT = -(tail of TF) */ +const TT: f32 = 6.6971006518e-09; /* 0x31e61c52 */ +const T0: f32 = 4.8383611441e-01; /* 0x3ef7b95e */ +const T1: f32 = -1.4758771658e-01; /* 0xbe17213c */ +const T2: f32 = 6.4624942839e-02; /* 0x3d845a15 */ +const T3: f32 = -3.2788541168e-02; /* 0xbd064d47 */ +const T4: f32 = 1.7970675603e-02; /* 0x3c93373d */ +const T5: f32 = -1.0314224288e-02; /* 0xbc28fcfe */ +const T6: f32 = 6.1005386524e-03; /* 0x3bc7e707 */ +const T7: f32 = -3.6845202558e-03; /* 0xbb7177fe */ +const T8: f32 = 2.2596477065e-03; /* 0x3b141699 */ +const T9: f32 = -1.4034647029e-03; /* 0xbab7f476 */ +const T10: f32 = 8.8108185446e-04; /* 0x3a66f867 */ +const T11: f32 = -5.3859531181e-04; /* 0xba0d3085 */ +const T12: f32 = 3.1563205994e-04; /* 0x39a57b6b */ +const T13: f32 = -3.1275415677e-04; /* 0xb9a3f927 */ +const T14: f32 = 3.3552918467e-04; /* 0x39afe9f7 */ +const U0: f32 = -7.7215664089e-02; /* 0xbd9e233f */ +const U1: f32 = 6.3282704353e-01; /* 0x3f2200f4 */ +const U2: f32 = 1.4549225569e+00; /* 0x3fba3ae7 */ +const U3: f32 = 9.7771751881e-01; /* 0x3f7a4bb2 */ +const U4: f32 = 2.2896373272e-01; /* 0x3e6a7578 */ +const U5: f32 = 1.3381091878e-02; /* 0x3c5b3c5e */ +const V1: f32 = 2.4559779167e+00; /* 0x401d2ebe */ +const V2: f32 = 2.1284897327e+00; /* 0x4008392d */ +const V3: f32 = 7.6928514242e-01; /* 0x3f44efdf */ +const V4: f32 = 1.0422264785e-01; /* 0x3dd572af */ +const V5: f32 = 3.2170924824e-03; /* 0x3b52d5db */ +const S0: f32 = -7.7215664089e-02; /* 0xbd9e233f */ +const S1: f32 = 2.1498242021e-01; /* 0x3e5c245a */ +const S2: f32 = 3.2577878237e-01; /* 0x3ea6cc7a */ +const S3: f32 = 1.4635047317e-01; /* 0x3e15dce6 */ +const S4: f32 = 2.6642270386e-02; /* 0x3cda40e4 */ +const S5: f32 = 1.8402845599e-03; /* 0x3af135b4 */ +const S6: f32 = 3.1947532989e-05; /* 0x3805ff67 */ +const R1: f32 = 1.3920053244e+00; /* 0x3fb22d3b */ +const R2: f32 = 7.2193557024e-01; /* 0x3f38d0c5 */ +const R3: f32 = 1.7193385959e-01; /* 0x3e300f6e */ +const R4: f32 = 1.8645919859e-02; /* 0x3c98bf54 */ +const R5: f32 = 7.7794247773e-04; /* 0x3a4beed6 */ +const R6: f32 = 7.3266842264e-06; /* 0x36f5d7bd */ +const W0: f32 = 4.1893854737e-01; /* 0x3ed67f1d */ +const W1: f32 = 8.3333335817e-02; /* 0x3daaaaab */ +const W2: f32 = -2.7777778450e-03; /* 0xbb360b61 */ +const W3: f32 = 7.9365057172e-04; /* 0x3a500cfd */ +const W4: f32 = -5.9518753551e-04; /* 0xba1c065c */ +const W5: f32 = 8.3633989561e-04; /* 0x3a5b3dd2 */ +const W6: f32 = -1.6309292987e-03; /* 0xbad5c4e8 */ + +/* sin(PI*x) assuming x > 2^-100, if sin(PI*x)==0 the sign is arbitrary */ +fn sin_pi(mut x: f32) -> f32 { + let mut y: f64; + let mut n: isize; + + /* spurious inexact if odd int */ + x = 2.0 * (x * 0.5 - floorf(x * 0.5)); /* x mod 2.0 */ + + n = (x * 4.0) as isize; + n = (n + 1) / 2; + y = (x as f64) - (n as f64) * 0.5; + y *= 3.14159265358979323846; + match n { + 1 => k_cosf(y), + 2 => k_sinf(-y), + 3 => -k_cosf(y), + 0 | _ => k_sinf(y), + } +} + +pub fn lgammaf_r(mut x: f32) -> (f32, i32) { + let u = x.to_bits(); + let mut t: f32; + let y: f32; + let mut z: f32; + let nadj: f32; + let p: f32; + let p1: f32; + let p2: f32; + let p3: f32; + let q: f32; + let mut r: f32; + let w: f32; + let ix: u32; + let i: i32; + let sign: bool; + let mut signgam: i32; + + /* purge off +-inf, NaN, +-0, tiny and negative arguments */ + signgam = 1; + sign = (u >> 31) != 0; + ix = u & 0x7fffffff; + if ix >= 0x7f800000 { + return (x * x, signgam); + } + if ix < 0x35000000 { + /* |x| < 2**-21, return -log(|x|) */ + if sign { + signgam = -1; + x = -x; + } + return (-logf(x), signgam); + } + if sign { + x = -x; + t = sin_pi(x); + if t == 0.0 { + /* -integer */ + return (1.0 / (x - x), signgam); + } + if t > 0.0 { + signgam = -1; + } else { + t = -t; + } + nadj = logf(PI / (t * x)); + } else { + nadj = 0.0; + } + + /* purge off 1 and 2 */ + if ix == 0x3f800000 || ix == 0x40000000 { + r = 0.0; + } + /* for x < 2.0 */ + else if ix < 0x40000000 { + if ix <= 0x3f666666 { + /* lgamma(x) = lgamma(x+1)-log(x) */ + r = -logf(x); + if ix >= 0x3f3b4a20 { + y = 1.0 - x; + i = 0; + } else if ix >= 0x3e6d3308 { + y = x - (TC - 1.0); + i = 1; + } else { + y = x; + i = 2; + } + } else { + r = 0.0; + if ix >= 0x3fdda618 { + /* [1.7316,2] */ + y = 2.0 - x; + i = 0; + } else if ix >= 0x3F9da620 { + /* [1.23,1.73] */ + y = x - TC; + i = 1; + } else { + y = x - 1.0; + i = 2; + } + } + match i { + 0 => { + z = y * y; + p1 = A0 + z * (A2 + z * (A4 + z * (A6 + z * (A8 + z * A10)))); + p2 = z * (A1 + z * (A3 + z * (A5 + z * (A7 + z * (A9 + z * A11))))); + p = y * p1 + p2; + r += p - 0.5 * y; + } + 1 => { + z = y * y; + w = z * y; + p1 = T0 + w * (T3 + w * (T6 + w * (T9 + w * T12))); /* parallel comp */ + p2 = T1 + w * (T4 + w * (T7 + w * (T10 + w * T13))); + p3 = T2 + w * (T5 + w * (T8 + w * (T11 + w * T14))); + p = z * p1 - (TT - w * (p2 + y * p3)); + r += TF + p; + } + 2 => { + p1 = y * (U0 + y * (U1 + y * (U2 + y * (U3 + y * (U4 + y * U5))))); + p2 = 1.0 + y * (V1 + y * (V2 + y * (V3 + y * (V4 + y * V5)))); + r += -0.5 * y + p1 / p2; + } + #[cfg(feature = "checked")] + _ => unreachable!(), + #[cfg(not(feature = "checked"))] + _ => {} + } + } else if ix < 0x41000000 { + /* x < 8.0 */ + i = x as i32; + y = x - (i as f32); + p = y * (S0 + y * (S1 + y * (S2 + y * (S3 + y * (S4 + y * (S5 + y * S6)))))); + q = 1.0 + y * (R1 + y * (R2 + y * (R3 + y * (R4 + y * (R5 + y * R6))))); + r = 0.5 * y + p / q; + z = 1.0; /* lgamma(1+s) = log(s) + lgamma(s) */ + // TODO: In C, this was implemented using switch jumps with fallthrough. + // Does this implementation have performance problems? + if i >= 7 { + z *= y + 6.0; + } + if i >= 6 { + z *= y + 5.0; + } + if i >= 5 { + z *= y + 4.0; + } + if i >= 4 { + z *= y + 3.0; + } + if i >= 3 { + z *= y + 2.0; + r += logf(z); + } + } else if ix < 0x5c800000 { + /* 8.0 <= x < 2**58 */ + t = logf(x); + z = 1.0 / x; + y = z * z; + w = W0 + z * (W1 + y * (W2 + y * (W3 + y * (W4 + y * (W5 + y * W6))))); + r = (x - 0.5) * (t - 1.0) + w; + } else { + /* 2**58 <= x <= inf */ + r = x * (logf(x) - 1.0); + } + if sign { + r = nadj - r; + } + return (r, signgam); +} diff --git a/vendor/libm/src/math/log.rs b/vendor/libm/src/math/log.rs new file mode 100644 index 0000000000..4126e413b7 --- /dev/null +++ b/vendor/libm/src/math/log.rs @@ -0,0 +1,118 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_log.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* log(x) + * Return the logarithm of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Remez algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +const LN2_HI: f64 = 6.93147180369123816490e-01; /* 3fe62e42 fee00000 */ +const LN2_LO: f64 = 1.90821492927058770002e-10; /* 3dea39ef 35793c76 */ +const LG1: f64 = 6.666666666666735130e-01; /* 3FE55555 55555593 */ +const LG2: f64 = 3.999999999940941908e-01; /* 3FD99999 9997FA04 */ +const LG3: f64 = 2.857142874366239149e-01; /* 3FD24924 94229359 */ +const LG4: f64 = 2.222219843214978396e-01; /* 3FCC71C5 1D8E78AF */ +const LG5: f64 = 1.818357216161805012e-01; /* 3FC74664 96CB03DE */ +const LG6: f64 = 1.531383769920937332e-01; /* 3FC39A09 D078C69F */ +const LG7: f64 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log(mut x: f64) -> f64 { + let x1p54 = f64::from_bits(0x4350000000000000); // 0x1p54 === 2 ^ 54 + + let mut ui = x.to_bits(); + let mut hx: u32 = (ui >> 32) as u32; + let mut k: i32 = 0; + + if (hx < 0x00100000) || ((hx >> 31) != 0) { + /* x < 2**-126 */ + if ui << 1 == 0 { + return -1. / (x * x); /* log(+-0)=-inf */ + } + if hx >> 31 != 0 { + return (x - x) / 0.0; /* log(-#) = NaN */ + } + /* subnormal number, scale x up */ + k -= 54; + x *= x1p54; + ui = x.to_bits(); + hx = (ui >> 32) as u32; + } else if hx >= 0x7ff00000 { + return x; + } else if hx == 0x3ff00000 && ui << 32 == 0 { + return 0.; + } + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + hx += 0x3ff00000 - 0x3fe6a09e; + k += ((hx >> 20) as i32) - 0x3ff; + hx = (hx & 0x000fffff) + 0x3fe6a09e; + ui = ((hx as u64) << 32) | (ui & 0xffffffff); + x = f64::from_bits(ui); + + let f: f64 = x - 1.0; + let hfsq: f64 = 0.5 * f * f; + let s: f64 = f / (2.0 + f); + let z: f64 = s * s; + let w: f64 = z * z; + let t1: f64 = w * (LG2 + w * (LG4 + w * LG6)); + let t2: f64 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7))); + let r: f64 = t2 + t1; + let dk: f64 = k as f64; + s * (hfsq + r) + dk * LN2_LO - hfsq + f + dk * LN2_HI +} diff --git a/vendor/libm/src/math/log10.rs b/vendor/libm/src/math/log10.rs new file mode 100644 index 0000000000..c99696040a --- /dev/null +++ b/vendor/libm/src/math/log10.rs @@ -0,0 +1,118 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_log10.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * Return the base 10 logarithm of x. See log.c for most comments. + * + * Reduce x to 2^k (1+f) and calculate r = log(1+f) - f + f*f/2 + * as in log.c, then combine and scale in extra precision: + * log10(x) = (f - f*f/2 + r)/log(10) + k*log10(2) + */ + +use core::f64; + +const IVLN10HI: f64 = 4.34294481878168880939e-01; /* 0x3fdbcb7b, 0x15200000 */ +const IVLN10LO: f64 = 2.50829467116452752298e-11; /* 0x3dbb9438, 0xca9aadd5 */ +const LOG10_2HI: f64 = 3.01029995663611771306e-01; /* 0x3FD34413, 0x509F6000 */ +const LOG10_2LO: f64 = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ +const LG1: f64 = 6.666666666666735130e-01; /* 3FE55555 55555593 */ +const LG2: f64 = 3.999999999940941908e-01; /* 3FD99999 9997FA04 */ +const LG3: f64 = 2.857142874366239149e-01; /* 3FD24924 94229359 */ +const LG4: f64 = 2.222219843214978396e-01; /* 3FCC71C5 1D8E78AF */ +const LG5: f64 = 1.818357216161805012e-01; /* 3FC74664 96CB03DE */ +const LG6: f64 = 1.531383769920937332e-01; /* 3FC39A09 D078C69F */ +const LG7: f64 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log10(mut x: f64) -> f64 { + let x1p54 = f64::from_bits(0x4350000000000000); // 0x1p54 === 2 ^ 54 + + let mut ui: u64 = x.to_bits(); + let hfsq: f64; + let f: f64; + let s: f64; + let z: f64; + let r: f64; + let mut w: f64; + let t1: f64; + let t2: f64; + let dk: f64; + let y: f64; + let mut hi: f64; + let lo: f64; + let mut val_hi: f64; + let mut val_lo: f64; + let mut hx: u32; + let mut k: i32; + + hx = (ui >> 32) as u32; + k = 0; + if hx < 0x00100000 || (hx >> 31) > 0 { + if ui << 1 == 0 { + return -1. / (x * x); /* log(+-0)=-inf */ + } + if (hx >> 31) > 0 { + return (x - x) / 0.0; /* log(-#) = NaN */ + } + /* subnormal number, scale x up */ + k -= 54; + x *= x1p54; + ui = x.to_bits(); + hx = (ui >> 32) as u32; + } else if hx >= 0x7ff00000 { + return x; + } else if hx == 0x3ff00000 && ui << 32 == 0 { + return 0.; + } + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + hx += 0x3ff00000 - 0x3fe6a09e; + k += (hx >> 20) as i32 - 0x3ff; + hx = (hx & 0x000fffff) + 0x3fe6a09e; + ui = (hx as u64) << 32 | (ui & 0xffffffff); + x = f64::from_bits(ui); + + f = x - 1.0; + hfsq = 0.5 * f * f; + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (LG2 + w * (LG4 + w * LG6)); + t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7))); + r = t2 + t1; + + /* See log2.c for details. */ + /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */ + hi = f - hfsq; + ui = hi.to_bits(); + ui &= (-1i64 as u64) << 32; + hi = f64::from_bits(ui); + lo = f - hi - hfsq + s * (hfsq + r); + + /* val_hi+val_lo ~ log10(1+f) + k*log10(2) */ + val_hi = hi * IVLN10HI; + dk = k as f64; + y = dk * LOG10_2HI; + val_lo = dk * LOG10_2LO + (lo + hi) * IVLN10LO + lo * IVLN10HI; + + /* + * Extra precision in for adding y is not strictly needed + * since there is no very large cancellation near x = sqrt(2) or + * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs + * with some parallelism and it reduces the error for many args. + */ + w = y + val_hi; + val_lo += (y - w) + val_hi; + val_hi = w; + + val_lo + val_hi +} diff --git a/vendor/libm/src/math/log10f.rs b/vendor/libm/src/math/log10f.rs new file mode 100644 index 0000000000..9845cda5d9 --- /dev/null +++ b/vendor/libm/src/math/log10f.rs @@ -0,0 +1,92 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_log10f.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * See comments in log10.c. + */ + +use core::f32; + +const IVLN10HI: f32 = 4.3432617188e-01; /* 0x3ede6000 */ +const IVLN10LO: f32 = -3.1689971365e-05; /* 0xb804ead9 */ +const LOG10_2HI: f32 = 3.0102920532e-01; /* 0x3e9a2080 */ +const LOG10_2LO: f32 = 7.9034151668e-07; /* 0x355427db */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +const LG1: f32 = 0.66666662693; /* 0xaaaaaa.0p-24 */ +const LG2: f32 = 0.40000972152; /* 0xccce13.0p-25 */ +const LG3: f32 = 0.28498786688; /* 0x91e9ee.0p-25 */ +const LG4: f32 = 0.24279078841; /* 0xf89e26.0p-26 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log10f(mut x: f32) -> f32 { + let x1p25f = f32::from_bits(0x4c000000); // 0x1p25f === 2 ^ 25 + + let mut ui: u32 = x.to_bits(); + let hfsq: f32; + let f: f32; + let s: f32; + let z: f32; + let r: f32; + let w: f32; + let t1: f32; + let t2: f32; + let dk: f32; + let mut hi: f32; + let lo: f32; + let mut ix: u32; + let mut k: i32; + + ix = ui; + k = 0; + if ix < 0x00800000 || (ix >> 31) > 0 { + /* x < 2**-126 */ + if ix << 1 == 0 { + return -1. / (x * x); /* log(+-0)=-inf */ + } + if (ix >> 31) > 0 { + return (x - x) / 0.0; /* log(-#) = NaN */ + } + /* subnormal number, scale up x */ + k -= 25; + x *= x1p25f; + ui = x.to_bits(); + ix = ui; + } else if ix >= 0x7f800000 { + return x; + } else if ix == 0x3f800000 { + return 0.; + } + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + k += (ix >> 23) as i32 - 0x7f; + ix = (ix & 0x007fffff) + 0x3f3504f3; + ui = ix; + x = f32::from_bits(ui); + + f = x - 1.0; + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (LG2 + w * LG4); + t2 = z * (LG1 + w * LG3); + r = t2 + t1; + hfsq = 0.5 * f * f; + + hi = f - hfsq; + ui = hi.to_bits(); + ui &= 0xfffff000; + hi = f32::from_bits(ui); + lo = f - hi - hfsq + s * (hfsq + r); + dk = k as f32; + dk * LOG10_2LO + (lo + hi) * IVLN10LO + lo * IVLN10HI + hi * IVLN10HI + dk * LOG10_2HI +} diff --git a/vendor/libm/src/math/log1p.rs b/vendor/libm/src/math/log1p.rs new file mode 100644 index 0000000000..cd7045ac97 --- /dev/null +++ b/vendor/libm/src/math/log1p.rs @@ -0,0 +1,144 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_log1p.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* double log1p(double x) + * Return the natural logarithm of 1+x. + * + * Method : + * 1. Argument Reduction: find k and f such that + * 1+x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * Note. If k=0, then f=x is exact. However, if k!=0, then f + * may not be representable exactly. In that case, a correction + * term is need. Let u=1+x rounded. Let c = (1+x)-u, then + * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), + * and add back the correction term c/u. + * (Note: when x > 2**53, one can simply return log(x)) + * + * 2. Approximation of log(1+f): See log.c + * + * 3. Finally, log1p(x) = k*ln2 + log(1+f) + c/u. See log.c + * + * Special cases: + * log1p(x) is NaN with signal if x < -1 (including -INF) ; + * log1p(+INF) is +INF; log1p(-1) is -INF with signal; + * log1p(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + * + * Note: Assuming log() return accurate answer, the following + * algorithm can be used to compute log1p(x) to within a few ULP: + * + * u = 1+x; + * if(u==1.0) return x ; else + * return log(u)*(x/(u-1.0)); + * + * See HP-15C Advanced Functions Handbook, p.193. + */ + +use core::f64; + +const LN2_HI: f64 = 6.93147180369123816490e-01; /* 3fe62e42 fee00000 */ +const LN2_LO: f64 = 1.90821492927058770002e-10; /* 3dea39ef 35793c76 */ +const LG1: f64 = 6.666666666666735130e-01; /* 3FE55555 55555593 */ +const LG2: f64 = 3.999999999940941908e-01; /* 3FD99999 9997FA04 */ +const LG3: f64 = 2.857142874366239149e-01; /* 3FD24924 94229359 */ +const LG4: f64 = 2.222219843214978396e-01; /* 3FCC71C5 1D8E78AF */ +const LG5: f64 = 1.818357216161805012e-01; /* 3FC74664 96CB03DE */ +const LG6: f64 = 1.531383769920937332e-01; /* 3FC39A09 D078C69F */ +const LG7: f64 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log1p(x: f64) -> f64 { + let mut ui: u64 = x.to_bits(); + let hfsq: f64; + let mut f: f64 = 0.; + let mut c: f64 = 0.; + let s: f64; + let z: f64; + let r: f64; + let w: f64; + let t1: f64; + let t2: f64; + let dk: f64; + let hx: u32; + let mut hu: u32; + let mut k: i32; + + hx = (ui >> 32) as u32; + k = 1; + if hx < 0x3fda827a || (hx >> 31) > 0 { + /* 1+x < sqrt(2)+ */ + if hx >= 0xbff00000 { + /* x <= -1.0 */ + if x == -1. { + return x / 0.0; /* log1p(-1) = -inf */ + } + return (x - x) / 0.0; /* log1p(x<-1) = NaN */ + } + if hx << 1 < 0x3ca00000 << 1 { + /* |x| < 2**-53 */ + /* underflow if subnormal */ + if (hx & 0x7ff00000) == 0 { + force_eval!(x as f32); + } + return x; + } + if hx <= 0xbfd2bec4 { + /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ + k = 0; + c = 0.; + f = x; + } + } else if hx >= 0x7ff00000 { + return x; + } + if k > 0 { + ui = (1. + x).to_bits(); + hu = (ui >> 32) as u32; + hu += 0x3ff00000 - 0x3fe6a09e; + k = (hu >> 20) as i32 - 0x3ff; + /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ + if k < 54 { + c = if k >= 2 { + 1. - (f64::from_bits(ui) - x) + } else { + x - (f64::from_bits(ui) - 1.) + }; + c /= f64::from_bits(ui); + } else { + c = 0.; + } + /* reduce u into [sqrt(2)/2, sqrt(2)] */ + hu = (hu & 0x000fffff) + 0x3fe6a09e; + ui = (hu as u64) << 32 | (ui & 0xffffffff); + f = f64::from_bits(ui) - 1.; + } + hfsq = 0.5 * f * f; + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (LG2 + w * (LG4 + w * LG6)); + t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7))); + r = t2 + t1; + dk = k as f64; + s * (hfsq + r) + (dk * LN2_LO + c) - hfsq + f + dk * LN2_HI +} diff --git a/vendor/libm/src/math/log1pf.rs b/vendor/libm/src/math/log1pf.rs new file mode 100644 index 0000000000..8e9651357d --- /dev/null +++ b/vendor/libm/src/math/log1pf.rs @@ -0,0 +1,99 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_log1pf.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use core::f32; + +const LN2_HI: f32 = 6.9313812256e-01; /* 0x3f317180 */ +const LN2_LO: f32 = 9.0580006145e-06; /* 0x3717f7d1 */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +const LG1: f32 = 0.66666662693; /* 0xaaaaaa.0p-24 */ +const LG2: f32 = 0.40000972152; /* 0xccce13.0p-25 */ +const LG3: f32 = 0.28498786688; /* 0x91e9ee.0p-25 */ +const LG4: f32 = 0.24279078841; /* 0xf89e26.0p-26 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log1pf(x: f32) -> f32 { + let mut ui: u32 = x.to_bits(); + let hfsq: f32; + let mut f: f32 = 0.; + let mut c: f32 = 0.; + let s: f32; + let z: f32; + let r: f32; + let w: f32; + let t1: f32; + let t2: f32; + let dk: f32; + let ix: u32; + let mut iu: u32; + let mut k: i32; + + ix = ui; + k = 1; + if ix < 0x3ed413d0 || (ix >> 31) > 0 { + /* 1+x < sqrt(2)+ */ + if ix >= 0xbf800000 { + /* x <= -1.0 */ + if x == -1. { + return x / 0.0; /* log1p(-1)=+inf */ + } + return (x - x) / 0.0; /* log1p(x<-1)=NaN */ + } + if ix << 1 < 0x33800000 << 1 { + /* |x| < 2**-24 */ + /* underflow if subnormal */ + if (ix & 0x7f800000) == 0 { + force_eval!(x * x); + } + return x; + } + if ix <= 0xbe95f619 { + /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ + k = 0; + c = 0.; + f = x; + } + } else if ix >= 0x7f800000 { + return x; + } + if k > 0 { + ui = (1. + x).to_bits(); + iu = ui; + iu += 0x3f800000 - 0x3f3504f3; + k = (iu >> 23) as i32 - 0x7f; + /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ + if k < 25 { + c = if k >= 2 { + 1. - (f32::from_bits(ui) - x) + } else { + x - (f32::from_bits(ui) - 1.) + }; + c /= f32::from_bits(ui); + } else { + c = 0.; + } + /* reduce u into [sqrt(2)/2, sqrt(2)] */ + iu = (iu & 0x007fffff) + 0x3f3504f3; + ui = iu; + f = f32::from_bits(ui) - 1.; + } + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (LG2 + w * LG4); + t2 = z * (LG1 + w * LG3); + r = t2 + t1; + hfsq = 0.5 * f * f; + dk = k as f32; + s * (hfsq + r) + (dk * LN2_LO + c) - hfsq + f + dk * LN2_HI +} diff --git a/vendor/libm/src/math/log2.rs b/vendor/libm/src/math/log2.rs new file mode 100644 index 0000000000..a3d43e55c2 --- /dev/null +++ b/vendor/libm/src/math/log2.rs @@ -0,0 +1,107 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_log2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * Return the base 2 logarithm of x. See log.c for most comments. + * + * Reduce x to 2^k (1+f) and calculate r = log(1+f) - f + f*f/2 + * as in log.c, then combine and scale in extra precision: + * log2(x) = (f - f*f/2 + r)/log(2) + k + */ + +use core::f64; + +const IVLN2HI: f64 = 1.44269504072144627571e+00; /* 0x3ff71547, 0x65200000 */ +const IVLN2LO: f64 = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */ +const LG1: f64 = 6.666666666666735130e-01; /* 3FE55555 55555593 */ +const LG2: f64 = 3.999999999940941908e-01; /* 3FD99999 9997FA04 */ +const LG3: f64 = 2.857142874366239149e-01; /* 3FD24924 94229359 */ +const LG4: f64 = 2.222219843214978396e-01; /* 3FCC71C5 1D8E78AF */ +const LG5: f64 = 1.818357216161805012e-01; /* 3FC74664 96CB03DE */ +const LG6: f64 = 1.531383769920937332e-01; /* 3FC39A09 D078C69F */ +const LG7: f64 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log2(mut x: f64) -> f64 { + let x1p54 = f64::from_bits(0x4350000000000000); // 0x1p54 === 2 ^ 54 + + let mut ui: u64 = x.to_bits(); + let hfsq: f64; + let f: f64; + let s: f64; + let z: f64; + let r: f64; + let mut w: f64; + let t1: f64; + let t2: f64; + let y: f64; + let mut hi: f64; + let lo: f64; + let mut val_hi: f64; + let mut val_lo: f64; + let mut hx: u32; + let mut k: i32; + + hx = (ui >> 32) as u32; + k = 0; + if hx < 0x00100000 || (hx >> 31) > 0 { + if ui << 1 == 0 { + return -1. / (x * x); /* log(+-0)=-inf */ + } + if (hx >> 31) > 0 { + return (x - x) / 0.0; /* log(-#) = NaN */ + } + /* subnormal number, scale x up */ + k -= 54; + x *= x1p54; + ui = x.to_bits(); + hx = (ui >> 32) as u32; + } else if hx >= 0x7ff00000 { + return x; + } else if hx == 0x3ff00000 && ui << 32 == 0 { + return 0.; + } + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + hx += 0x3ff00000 - 0x3fe6a09e; + k += (hx >> 20) as i32 - 0x3ff; + hx = (hx & 0x000fffff) + 0x3fe6a09e; + ui = (hx as u64) << 32 | (ui & 0xffffffff); + x = f64::from_bits(ui); + + f = x - 1.0; + hfsq = 0.5 * f * f; + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (LG2 + w * (LG4 + w * LG6)); + t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7))); + r = t2 + t1; + + /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */ + hi = f - hfsq; + ui = hi.to_bits(); + ui &= (-1i64 as u64) << 32; + hi = f64::from_bits(ui); + lo = f - hi - hfsq + s * (hfsq + r); + + val_hi = hi * IVLN2HI; + val_lo = (lo + hi) * IVLN2LO + lo * IVLN2HI; + + /* spadd(val_hi, val_lo, y), except for not using double_t: */ + y = k.into(); + w = y + val_hi; + val_lo += (y - w) + val_hi; + val_hi = w; + + val_lo + val_hi +} diff --git a/vendor/libm/src/math/log2f.rs b/vendor/libm/src/math/log2f.rs new file mode 100644 index 0000000000..53a37e5033 --- /dev/null +++ b/vendor/libm/src/math/log2f.rs @@ -0,0 +1,88 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_log2f.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * See comments in log2.c. + */ + +use core::f32; + +const IVLN2HI: f32 = 1.4428710938e+00; /* 0x3fb8b000 */ +const IVLN2LO: f32 = -1.7605285393e-04; /* 0xb9389ad4 */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +const LG1: f32 = 0.66666662693; /* 0xaaaaaa.0p-24 */ +const LG2: f32 = 0.40000972152; /* 0xccce13.0p-25 */ +const LG3: f32 = 0.28498786688; /* 0x91e9ee.0p-25 */ +const LG4: f32 = 0.24279078841; /* 0xf89e26.0p-26 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log2f(mut x: f32) -> f32 { + let x1p25f = f32::from_bits(0x4c000000); // 0x1p25f === 2 ^ 25 + + let mut ui: u32 = x.to_bits(); + let hfsq: f32; + let f: f32; + let s: f32; + let z: f32; + let r: f32; + let w: f32; + let t1: f32; + let t2: f32; + let mut hi: f32; + let lo: f32; + let mut ix: u32; + let mut k: i32; + + ix = ui; + k = 0; + if ix < 0x00800000 || (ix >> 31) > 0 { + /* x < 2**-126 */ + if ix << 1 == 0 { + return -1. / (x * x); /* log(+-0)=-inf */ + } + if (ix >> 31) > 0 { + return (x - x) / 0.0; /* log(-#) = NaN */ + } + /* subnormal number, scale up x */ + k -= 25; + x *= x1p25f; + ui = x.to_bits(); + ix = ui; + } else if ix >= 0x7f800000 { + return x; + } else if ix == 0x3f800000 { + return 0.; + } + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + k += (ix >> 23) as i32 - 0x7f; + ix = (ix & 0x007fffff) + 0x3f3504f3; + ui = ix; + x = f32::from_bits(ui); + + f = x - 1.0; + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (LG2 + w * LG4); + t2 = z * (LG1 + w * LG3); + r = t2 + t1; + hfsq = 0.5 * f * f; + + hi = f - hfsq; + ui = hi.to_bits(); + ui &= 0xfffff000; + hi = f32::from_bits(ui); + lo = f - hi - hfsq + s * (hfsq + r); + (lo + hi) * IVLN2LO + lo * IVLN2HI + hi * IVLN2HI + k as f32 +} diff --git a/vendor/libm/src/math/logf.rs b/vendor/libm/src/math/logf.rs new file mode 100644 index 0000000000..95195601c2 --- /dev/null +++ b/vendor/libm/src/math/logf.rs @@ -0,0 +1,66 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_logf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +const LN2_HI: f32 = 6.9313812256e-01; /* 0x3f317180 */ +const LN2_LO: f32 = 9.0580006145e-06; /* 0x3717f7d1 */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +const LG1: f32 = 0.66666662693; /* 0xaaaaaa.0p-24*/ +const LG2: f32 = 0.40000972152; /* 0xccce13.0p-25 */ +const LG3: f32 = 0.28498786688; /* 0x91e9ee.0p-25 */ +const LG4: f32 = 0.24279078841; /* 0xf89e26.0p-26 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn logf(mut x: f32) -> f32 { + let x1p25 = f32::from_bits(0x4c000000); // 0x1p25f === 2 ^ 25 + + let mut ix = x.to_bits(); + let mut k = 0i32; + + if (ix < 0x00800000) || ((ix >> 31) != 0) { + /* x < 2**-126 */ + if ix << 1 == 0 { + return -1. / (x * x); /* log(+-0)=-inf */ + } + if (ix >> 31) != 0 { + return (x - x) / 0.; /* log(-#) = NaN */ + } + /* subnormal number, scale up x */ + k -= 25; + x *= x1p25; + ix = x.to_bits(); + } else if ix >= 0x7f800000 { + return x; + } else if ix == 0x3f800000 { + return 0.; + } + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + k += ((ix >> 23) as i32) - 0x7f; + ix = (ix & 0x007fffff) + 0x3f3504f3; + x = f32::from_bits(ix); + + let f = x - 1.; + let s = f / (2. + f); + let z = s * s; + let w = z * z; + let t1 = w * (LG2 + w * LG4); + let t2 = z * (LG1 + w * LG3); + let r = t2 + t1; + let hfsq = 0.5 * f * f; + let dk = k as f32; + s * (hfsq + r) + dk * LN2_LO - hfsq + f + dk * LN2_HI +} diff --git a/vendor/libm/src/math/mod.rs b/vendor/libm/src/math/mod.rs new file mode 100644 index 0000000000..35ffe1a2cb --- /dev/null +++ b/vendor/libm/src/math/mod.rs @@ -0,0 +1,342 @@ +macro_rules! force_eval { + ($e:expr) => { + unsafe { + ::core::ptr::read_volatile(&$e); + } + }; +} + +#[cfg(not(feature = "checked"))] +macro_rules! i { + ($array:expr, $index:expr) => { + unsafe { *$array.get_unchecked($index) } + }; + ($array:expr, $index:expr, = , $rhs:expr) => { + unsafe { + *$array.get_unchecked_mut($index) = $rhs; + } + }; + ($array:expr, $index:expr, += , $rhs:expr) => { + unsafe { + *$array.get_unchecked_mut($index) += $rhs; + } + }; + ($array:expr, $index:expr, -= , $rhs:expr) => { + unsafe { + *$array.get_unchecked_mut($index) -= $rhs; + } + }; + ($array:expr, $index:expr, &= , $rhs:expr) => { + unsafe { + *$array.get_unchecked_mut($index) &= $rhs; + } + }; + ($array:expr, $index:expr, == , $rhs:expr) => { + unsafe { *$array.get_unchecked_mut($index) == $rhs } + }; +} + +#[cfg(feature = "checked")] +macro_rules! i { + ($array:expr, $index:expr) => { + *$array.get($index).unwrap() + }; + ($array:expr, $index:expr, = , $rhs:expr) => { + *$array.get_mut($index).unwrap() = $rhs; + }; + ($array:expr, $index:expr, -= , $rhs:expr) => { + *$array.get_mut($index).unwrap() -= $rhs; + }; + ($array:expr, $index:expr, += , $rhs:expr) => { + *$array.get_mut($index).unwrap() += $rhs; + }; + ($array:expr, $index:expr, &= , $rhs:expr) => { + *$array.get_mut($index).unwrap() &= $rhs; + }; + ($array:expr, $index:expr, == , $rhs:expr) => { + *$array.get_mut($index).unwrap() == $rhs + }; +} + +macro_rules! llvm_intrinsically_optimized { + (#[cfg($($clause:tt)*)] $e:expr) => { + #[cfg(all(not(feature = "stable"), $($clause)*))] + { + if true { // thwart the dead code lint + $e + } + } + }; +} + +// Public modules +mod acos; +mod acosf; +mod acosh; +mod acoshf; +mod asin; +mod asinf; +mod asinh; +mod asinhf; +mod atan; +mod atan2; +mod atan2f; +mod atanf; +mod atanh; +mod atanhf; +mod cbrt; +mod cbrtf; +mod ceil; +mod ceilf; +mod copysign; +mod copysignf; +mod cos; +mod cosf; +mod cosh; +mod coshf; +mod erf; +mod erff; +mod exp; +mod exp10; +mod exp10f; +mod exp2; +mod exp2f; +mod expf; +mod expm1; +mod expm1f; +mod fabs; +mod fabsf; +mod fdim; +mod fdimf; +mod floor; +mod floorf; +mod fma; +mod fmaf; +mod fmax; +mod fmaxf; +mod fmin; +mod fminf; +mod fmod; +mod fmodf; +mod frexp; +mod frexpf; +mod hypot; +mod hypotf; +mod ilogb; +mod ilogbf; +mod j0; +mod j0f; +mod j1; +mod j1f; +mod jn; +mod jnf; +mod ldexp; +mod ldexpf; +mod lgamma; +mod lgamma_r; +mod lgammaf; +mod lgammaf_r; +mod log; +mod log10; +mod log10f; +mod log1p; +mod log1pf; +mod log2; +mod log2f; +mod logf; +mod modf; +mod modff; +mod pow; +mod powf; +mod remquo; +mod remquof; +mod round; +mod roundf; +mod scalbn; +mod scalbnf; +mod sin; +mod sincos; +mod sincosf; +mod sinf; +mod sinh; +mod sinhf; +mod sqrt; +mod sqrtf; +mod tan; +mod tanf; +mod tanh; +mod tanhf; +mod tgamma; +mod tgammaf; +mod trunc; +mod truncf; + +// Use separated imports instead of {}-grouped imports for easier merging. +pub use self::acos::acos; +pub use self::acosf::acosf; +pub use self::acosh::acosh; +pub use self::acoshf::acoshf; +pub use self::asin::asin; +pub use self::asinf::asinf; +pub use self::asinh::asinh; +pub use self::asinhf::asinhf; +pub use self::atan::atan; +pub use self::atan2::atan2; +pub use self::atan2f::atan2f; +pub use self::atanf::atanf; +pub use self::atanh::atanh; +pub use self::atanhf::atanhf; +pub use self::cbrt::cbrt; +pub use self::cbrtf::cbrtf; +pub use self::ceil::ceil; +pub use self::ceilf::ceilf; +pub use self::copysign::copysign; +pub use self::copysignf::copysignf; +pub use self::cos::cos; +pub use self::cosf::cosf; +pub use self::cosh::cosh; +pub use self::coshf::coshf; +pub use self::erf::erf; +pub use self::erf::erfc; +pub use self::erff::erfcf; +pub use self::erff::erff; +pub use self::exp::exp; +pub use self::exp10::exp10; +pub use self::exp10f::exp10f; +pub use self::exp2::exp2; +pub use self::exp2f::exp2f; +pub use self::expf::expf; +pub use self::expm1::expm1; +pub use self::expm1f::expm1f; +pub use self::fabs::fabs; +pub use self::fabsf::fabsf; +pub use self::fdim::fdim; +pub use self::fdimf::fdimf; +pub use self::floor::floor; +pub use self::floorf::floorf; +pub use self::fma::fma; +pub use self::fmaf::fmaf; +pub use self::fmax::fmax; +pub use self::fmaxf::fmaxf; +pub use self::fmin::fmin; +pub use self::fminf::fminf; +pub use self::fmod::fmod; +pub use self::fmodf::fmodf; +pub use self::frexp::frexp; +pub use self::frexpf::frexpf; +pub use self::hypot::hypot; +pub use self::hypotf::hypotf; +pub use self::ilogb::ilogb; +pub use self::ilogbf::ilogbf; +pub use self::j0::j0; +pub use self::j0::y0; +pub use self::j0f::j0f; +pub use self::j0f::y0f; +pub use self::j1::j1; +pub use self::j1::y1; +pub use self::j1f::j1f; +pub use self::j1f::y1f; +pub use self::jn::jn; +pub use self::jn::yn; +pub use self::jnf::jnf; +pub use self::jnf::ynf; +pub use self::ldexp::ldexp; +pub use self::ldexpf::ldexpf; +pub use self::lgamma::lgamma; +pub use self::lgamma_r::lgamma_r; +pub use self::lgammaf::lgammaf; +pub use self::lgammaf_r::lgammaf_r; +pub use self::log::log; +pub use self::log10::log10; +pub use self::log10f::log10f; +pub use self::log1p::log1p; +pub use self::log1pf::log1pf; +pub use self::log2::log2; +pub use self::log2f::log2f; +pub use self::logf::logf; +pub use self::modf::modf; +pub use self::modff::modff; +pub use self::pow::pow; +pub use self::powf::powf; +pub use self::remquo::remquo; +pub use self::remquof::remquof; +pub use self::round::round; +pub use self::roundf::roundf; +pub use self::scalbn::scalbn; +pub use self::scalbnf::scalbnf; +pub use self::sin::sin; +pub use self::sincos::sincos; +pub use self::sincosf::sincosf; +pub use self::sinf::sinf; +pub use self::sinh::sinh; +pub use self::sinhf::sinhf; +pub use self::sqrt::sqrt; +pub use self::sqrtf::sqrtf; +pub use self::tan::tan; +pub use self::tanf::tanf; +pub use self::tanh::tanh; +pub use self::tanhf::tanhf; +pub use self::tgamma::tgamma; +pub use self::tgammaf::tgammaf; +pub use self::trunc::trunc; +pub use self::truncf::truncf; + +// Private modules +mod expo2; +mod fenv; +mod k_cos; +mod k_cosf; +mod k_expo2; +mod k_expo2f; +mod k_sin; +mod k_sinf; +mod k_tan; +mod k_tanf; +mod rem_pio2; +mod rem_pio2_large; +mod rem_pio2f; + +// Private re-imports +use self::expo2::expo2; +use self::k_cos::k_cos; +use self::k_cosf::k_cosf; +use self::k_expo2::k_expo2; +use self::k_expo2f::k_expo2f; +use self::k_sin::k_sin; +use self::k_sinf::k_sinf; +use self::k_tan::k_tan; +use self::k_tanf::k_tanf; +use self::rem_pio2::rem_pio2; +use self::rem_pio2_large::rem_pio2_large; +use self::rem_pio2f::rem_pio2f; + +#[inline] +fn get_high_word(x: f64) -> u32 { + (x.to_bits() >> 32) as u32 +} + +#[inline] +fn get_low_word(x: f64) -> u32 { + x.to_bits() as u32 +} + +#[inline] +fn with_set_high_word(f: f64, hi: u32) -> f64 { + let mut tmp = f.to_bits(); + tmp &= 0x00000000_ffffffff; + tmp |= (hi as u64) << 32; + f64::from_bits(tmp) +} + +#[inline] +fn with_set_low_word(f: f64, lo: u32) -> f64 { + let mut tmp = f.to_bits(); + tmp &= 0xffffffff_00000000; + tmp |= lo as u64; + f64::from_bits(tmp) +} + +#[inline] +fn combine_words(hi: u32, lo: u32) -> f64 { + f64::from_bits((hi as u64) << 32 | lo as u64) +} diff --git a/vendor/libm/src/math/modf.rs b/vendor/libm/src/math/modf.rs new file mode 100644 index 0000000000..bcab33a810 --- /dev/null +++ b/vendor/libm/src/math/modf.rs @@ -0,0 +1,34 @@ +pub fn modf(x: f64) -> (f64, f64) { + let rv2: f64; + let mut u = x.to_bits(); + let mask: u64; + let e = ((u >> 52 & 0x7ff) as i32) - 0x3ff; + + /* no fractional part */ + if e >= 52 { + rv2 = x; + if e == 0x400 && (u << 12) != 0 { + /* nan */ + return (x, rv2); + } + u &= 1 << 63; + return (f64::from_bits(u), rv2); + } + + /* no integral part*/ + if e < 0 { + u &= 1 << 63; + rv2 = f64::from_bits(u); + return (x, rv2); + } + + mask = ((!0) >> 12) >> e; + if (u & mask) == 0 { + rv2 = x; + u &= 1 << 63; + return (f64::from_bits(u), rv2); + } + u &= !mask; + rv2 = f64::from_bits(u); + return (x - rv2, rv2); +} diff --git a/vendor/libm/src/math/modff.rs b/vendor/libm/src/math/modff.rs new file mode 100644 index 0000000000..56ece12e3c --- /dev/null +++ b/vendor/libm/src/math/modff.rs @@ -0,0 +1,33 @@ +pub fn modff(x: f32) -> (f32, f32) { + let rv2: f32; + let mut u: u32 = x.to_bits(); + let mask: u32; + let e = ((u >> 23 & 0xff) as i32) - 0x7f; + + /* no fractional part */ + if e >= 23 { + rv2 = x; + if e == 0x80 && (u << 9) != 0 { + /* nan */ + return (x, rv2); + } + u &= 0x80000000; + return (f32::from_bits(u), rv2); + } + /* no integral part */ + if e < 0 { + u &= 0x80000000; + rv2 = f32::from_bits(u); + return (x, rv2); + } + + mask = 0x007fffff >> e; + if (u & mask) == 0 { + rv2 = x; + u &= 0x80000000; + return (f32::from_bits(u), rv2); + } + u &= !mask; + rv2 = f32::from_bits(u); + return (x - rv2, rv2); +} diff --git a/vendor/libm/src/math/pow.rs b/vendor/libm/src/math/pow.rs new file mode 100644 index 0000000000..111d712ffc --- /dev/null +++ b/vendor/libm/src/math/pow.rs @@ -0,0 +1,634 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_pow.c */ +/* + * ==================================================== + * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. + * + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +// pow(x,y) return x**y +// +// n +// Method: Let x = 2 * (1+f) +// 1. Compute and return log2(x) in two pieces: +// log2(x) = w1 + w2, +// where w1 has 53-24 = 29 bit trailing zeros. +// 2. Perform y*log2(x) = n+y' by simulating muti-precision +// arithmetic, where |y'|<=0.5. +// 3. Return x**y = 2**n*exp(y'*log2) +// +// Special cases: +// 1. (anything) ** 0 is 1 +// 2. 1 ** (anything) is 1 +// 3. (anything except 1) ** NAN is NAN +// 4. NAN ** (anything except 0) is NAN +// 5. +-(|x| > 1) ** +INF is +INF +// 6. +-(|x| > 1) ** -INF is +0 +// 7. +-(|x| < 1) ** +INF is +0 +// 8. +-(|x| < 1) ** -INF is +INF +// 9. -1 ** +-INF is 1 +// 10. +0 ** (+anything except 0, NAN) is +0 +// 11. -0 ** (+anything except 0, NAN, odd integer) is +0 +// 12. +0 ** (-anything except 0, NAN) is +INF, raise divbyzero +// 13. -0 ** (-anything except 0, NAN, odd integer) is +INF, raise divbyzero +// 14. -0 ** (+odd integer) is -0 +// 15. -0 ** (-odd integer) is -INF, raise divbyzero +// 16. +INF ** (+anything except 0,NAN) is +INF +// 17. +INF ** (-anything except 0,NAN) is +0 +// 18. -INF ** (+odd integer) is -INF +// 19. -INF ** (anything) = -0 ** (-anything), (anything except odd integer) +// 20. (anything) ** 1 is (anything) +// 21. (anything) ** -1 is 1/(anything) +// 22. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) +// 23. (-anything except 0 and inf) ** (non-integer) is NAN +// +// Accuracy: +// pow(x,y) returns x**y nearly rounded. In particular +// pow(integer,integer) +// always returns the correct integer provided it is +// representable. +// +// Constants : +// The hexadecimal values are the intended ones for the following +// constants. The decimal values may be used, provided that the +// compiler will convert from decimal to binary accurately enough +// to produce the hexadecimal values shown. +// +use super::{fabs, get_high_word, scalbn, sqrt, with_set_high_word, with_set_low_word}; + +const BP: [f64; 2] = [1.0, 1.5]; +const DP_H: [f64; 2] = [0.0, 5.84962487220764160156e-01]; /* 0x3fe2b803_40000000 */ +const DP_L: [f64; 2] = [0.0, 1.35003920212974897128e-08]; /* 0x3E4CFDEB, 0x43CFD006 */ +const TWO53: f64 = 9007199254740992.0; /* 0x43400000_00000000 */ +const HUGE: f64 = 1.0e300; +const TINY: f64 = 1.0e-300; + +// poly coefs for (3/2)*(log(x)-2s-2/3*s**3: +const L1: f64 = 5.99999999999994648725e-01; /* 0x3fe33333_33333303 */ +const L2: f64 = 4.28571428578550184252e-01; /* 0x3fdb6db6_db6fabff */ +const L3: f64 = 3.33333329818377432918e-01; /* 0x3fd55555_518f264d */ +const L4: f64 = 2.72728123808534006489e-01; /* 0x3fd17460_a91d4101 */ +const L5: f64 = 2.30660745775561754067e-01; /* 0x3fcd864a_93c9db65 */ +const L6: f64 = 2.06975017800338417784e-01; /* 0x3fca7e28_4a454eef */ +const P1: f64 = 1.66666666666666019037e-01; /* 0x3fc55555_5555553e */ +const P2: f64 = -2.77777777770155933842e-03; /* 0xbf66c16c_16bebd93 */ +const P3: f64 = 6.61375632143793436117e-05; /* 0x3f11566a_af25de2c */ +const P4: f64 = -1.65339022054652515390e-06; /* 0xbebbbd41_c5d26bf1 */ +const P5: f64 = 4.13813679705723846039e-08; /* 0x3e663769_72bea4d0 */ +const LG2: f64 = 6.93147180559945286227e-01; /* 0x3fe62e42_fefa39ef */ +const LG2_H: f64 = 6.93147182464599609375e-01; /* 0x3fe62e43_00000000 */ +const LG2_L: f64 = -1.90465429995776804525e-09; /* 0xbe205c61_0ca86c39 */ +const OVT: f64 = 8.0085662595372944372e-017; /* -(1024-log2(ovfl+.5ulp)) */ +const CP: f64 = 9.61796693925975554329e-01; /* 0x3feec709_dc3a03fd =2/(3ln2) */ +const CP_H: f64 = 9.61796700954437255859e-01; /* 0x3feec709_e0000000 =(float)cp */ +const CP_L: f64 = -7.02846165095275826516e-09; /* 0xbe3e2fe0_145b01f5 =tail of cp_h*/ +const IVLN2: f64 = 1.44269504088896338700e+00; /* 0x3ff71547_652b82fe =1/ln2 */ +const IVLN2_H: f64 = 1.44269502162933349609e+00; /* 0x3ff71547_60000000 =24b 1/ln2*/ +const IVLN2_L: f64 = 1.92596299112661746887e-08; /* 0x3e54ae0b_f85ddf44 =1/ln2 tail*/ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn pow(x: f64, y: f64) -> f64 { + let t1: f64; + let t2: f64; + + let (hx, lx): (i32, u32) = ((x.to_bits() >> 32) as i32, x.to_bits() as u32); + let (hy, ly): (i32, u32) = ((y.to_bits() >> 32) as i32, y.to_bits() as u32); + + let mut ix: i32 = (hx & 0x7fffffff) as i32; + let iy: i32 = (hy & 0x7fffffff) as i32; + + /* x**0 = 1, even if x is NaN */ + if ((iy as u32) | ly) == 0 { + return 1.0; + } + + /* 1**y = 1, even if y is NaN */ + if hx == 0x3ff00000 && lx == 0 { + return 1.0; + } + + /* NaN if either arg is NaN */ + if ix > 0x7ff00000 + || (ix == 0x7ff00000 && lx != 0) + || iy > 0x7ff00000 + || (iy == 0x7ff00000 && ly != 0) + { + return x + y; + } + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + let mut yisint: i32 = 0; + let mut k: i32; + let mut j: i32; + if hx < 0 { + if iy >= 0x43400000 { + yisint = 2; /* even integer y */ + } else if iy >= 0x3ff00000 { + k = (iy >> 20) - 0x3ff; /* exponent */ + + if k > 20 { + j = (ly >> (52 - k)) as i32; + + if (j << (52 - k)) == (ly as i32) { + yisint = 2 - (j & 1); + } + } else if ly == 0 { + j = iy >> (20 - k); + + if (j << (20 - k)) == iy { + yisint = 2 - (j & 1); + } + } + } + } + + if ly == 0 { + /* special value of y */ + if iy == 0x7ff00000 { + /* y is +-inf */ + + return if ((ix - 0x3ff00000) | (lx as i32)) == 0 { + /* (-1)**+-inf is 1 */ + 1.0 + } else if ix >= 0x3ff00000 { + /* (|x|>1)**+-inf = inf,0 */ + if hy >= 0 { + y + } else { + 0.0 + } + } else { + /* (|x|<1)**+-inf = 0,inf */ + if hy >= 0 { + 0.0 + } else { + -y + } + }; + } + + if iy == 0x3ff00000 { + /* y is +-1 */ + return if hy >= 0 { x } else { 1.0 / x }; + } + + if hy == 0x40000000 { + /* y is 2 */ + return x * x; + } + + if hy == 0x3fe00000 { + /* y is 0.5 */ + if hx >= 0 { + /* x >= +0 */ + return sqrt(x); + } + } + } + + let mut ax: f64 = fabs(x); + if lx == 0 { + /* special value of x */ + if ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000 { + /* x is +-0,+-inf,+-1 */ + let mut z: f64 = ax; + + if hy < 0 { + /* z = (1/|x|) */ + z = 1.0 / z; + } + + if hx < 0 { + if ((ix - 0x3ff00000) | yisint) == 0 { + z = (z - z) / (z - z); /* (-1)**non-int is NaN */ + } else if yisint == 1 { + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + } + + return z; + } + } + + let mut s: f64 = 1.0; /* sign of result */ + if hx < 0 { + if yisint == 0 { + /* (x<0)**(non-int) is NaN */ + return (x - x) / (x - x); + } + + if yisint == 1 { + /* (x<0)**(odd int) */ + s = -1.0; + } + } + + /* |y| is HUGE */ + if iy > 0x41e00000 { + /* if |y| > 2**31 */ + if iy > 0x43f00000 { + /* if |y| > 2**64, must o/uflow */ + if ix <= 0x3fefffff { + return if hy < 0 { HUGE * HUGE } else { TINY * TINY }; + } + + if ix >= 0x3ff00000 { + return if hy > 0 { HUGE * HUGE } else { TINY * TINY }; + } + } + + /* over/underflow if x is not close to one */ + if ix < 0x3fefffff { + return if hy < 0 { + s * HUGE * HUGE + } else { + s * TINY * TINY + }; + } + if ix > 0x3ff00000 { + return if hy > 0 { + s * HUGE * HUGE + } else { + s * TINY * TINY + }; + } + + /* now |1-x| is TINY <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + let t: f64 = ax - 1.0; /* t has 20 trailing zeros */ + let w: f64 = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); + let u: f64 = IVLN2_H * t; /* ivln2_h has 21 sig. bits */ + let v: f64 = t * IVLN2_L - w * IVLN2; + t1 = with_set_low_word(u + v, 0); + t2 = v - (t1 - u); + } else { + // double ss,s2,s_h,s_l,t_h,t_l; + let mut n: i32 = 0; + + if ix < 0x00100000 { + /* take care subnormal number */ + ax *= TWO53; + n -= 53; + ix = get_high_word(ax) as i32; + } + + n += (ix >> 20) - 0x3ff; + j = ix & 0x000fffff; + + /* determine interval */ + let k: i32; + ix = j | 0x3ff00000; /* normalize ix */ + if j <= 0x3988E { + /* |x|> 1) | 0x20000000) + 0x00080000 + ((k as u32) << 18), + ); + let t_l: f64 = ax - (t_h - BP[k as usize]); + let s_l: f64 = v * ((u - s_h * t_h) - s_h * t_l); + + /* compute log(ax) */ + let s2: f64 = ss * ss; + let mut r: f64 = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); + r += s_l * (s_h + ss); + let s2: f64 = s_h * s_h; + let t_h: f64 = with_set_low_word(3.0 + s2 + r, 0); + let t_l: f64 = r - ((t_h - 3.0) - s2); + + /* u+v = ss*(1+...) */ + let u: f64 = s_h * t_h; + let v: f64 = s_l * t_h + t_l * ss; + + /* 2/(3log2)*(ss+...) */ + let p_h: f64 = with_set_low_word(u + v, 0); + let p_l = v - (p_h - u); + let z_h: f64 = CP_H * p_h; /* cp_h+cp_l = 2/(3*log2) */ + let z_l: f64 = CP_L * p_h + p_l * CP + DP_L[k as usize]; + + /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + let t: f64 = n as f64; + t1 = with_set_low_word(((z_h + z_l) + DP_H[k as usize]) + t, 0); + t2 = z_l - (((t1 - t) - DP_H[k as usize]) - z_h); + } + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + let y1: f64 = with_set_low_word(y, 0); + let p_l: f64 = (y - y1) * t1 + y * t2; + let mut p_h: f64 = y1 * t1; + let z: f64 = p_l + p_h; + let mut j: i32 = (z.to_bits() >> 32) as i32; + let i: i32 = z.to_bits() as i32; + // let (j, i): (i32, i32) = ((z.to_bits() >> 32) as i32, z.to_bits() as i32); + + if j >= 0x40900000 { + /* z >= 1024 */ + if (j - 0x40900000) | i != 0 { + /* if z > 1024 */ + return s * HUGE * HUGE; /* overflow */ + } + + if p_l + OVT > z - p_h { + return s * HUGE * HUGE; /* overflow */ + } + } else if (j & 0x7fffffff) >= 0x4090cc00 { + /* z <= -1075 */ + // FIXME: instead of abs(j) use unsigned j + + if (((j as u32) - 0xc090cc00) | (i as u32)) != 0 { + /* z < -1075 */ + return s * TINY * TINY; /* underflow */ + } + + if p_l <= z - p_h { + return s * TINY * TINY; /* underflow */ + } + } + + /* compute 2**(p_h+p_l) */ + let i: i32 = j & (0x7fffffff as i32); + k = (i >> 20) - 0x3ff; + let mut n: i32 = 0; + + if i > 0x3fe00000 { + /* if |z| > 0.5, set n = [z+0.5] */ + n = j + (0x00100000 >> (k + 1)); + k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ + let t: f64 = with_set_high_word(0.0, (n & !(0x000fffff >> k)) as u32); + n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); + if j < 0 { + n = -n; + } + p_h -= t; + } + + let t: f64 = with_set_low_word(p_l + p_h, 0); + let u: f64 = t * LG2_H; + let v: f64 = (p_l - (t - p_h)) * LG2 + t * LG2_L; + let mut z: f64 = u + v; + let w: f64 = v - (z - u); + let t: f64 = z * z; + let t1: f64 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + let r: f64 = (z * t1) / (t1 - 2.0) - (w + z * w); + z = 1.0 - (r - z); + j = get_high_word(z) as i32; + j += n << 20; + + if (j >> 20) <= 0 { + /* subnormal output */ + z = scalbn(z, n); + } else { + z = with_set_high_word(z, j as u32); + } + + s * z +} + +#[cfg(test)] +mod tests { + extern crate core; + + use self::core::f64::consts::{E, PI}; + use self::core::f64::{EPSILON, INFINITY, MAX, MIN, MIN_POSITIVE, NAN, NEG_INFINITY}; + use super::pow; + + const POS_ZERO: &[f64] = &[0.0]; + const NEG_ZERO: &[f64] = &[-0.0]; + const POS_ONE: &[f64] = &[1.0]; + const NEG_ONE: &[f64] = &[-1.0]; + const POS_FLOATS: &[f64] = &[99.0 / 70.0, E, PI]; + const NEG_FLOATS: &[f64] = &[-99.0 / 70.0, -E, -PI]; + const POS_SMALL_FLOATS: &[f64] = &[(1.0 / 2.0), MIN_POSITIVE, EPSILON]; + const NEG_SMALL_FLOATS: &[f64] = &[-(1.0 / 2.0), -MIN_POSITIVE, -EPSILON]; + const POS_EVENS: &[f64] = &[2.0, 6.0, 8.0, 10.0, 22.0, 100.0, MAX]; + const NEG_EVENS: &[f64] = &[MIN, -100.0, -22.0, -10.0, -8.0, -6.0, -2.0]; + const POS_ODDS: &[f64] = &[3.0, 7.0]; + const NEG_ODDS: &[f64] = &[-7.0, -3.0]; + const NANS: &[f64] = &[NAN]; + const POS_INF: &[f64] = &[INFINITY]; + const NEG_INF: &[f64] = &[NEG_INFINITY]; + + const ALL: &[&[f64]] = &[ + POS_ZERO, + NEG_ZERO, + NANS, + NEG_SMALL_FLOATS, + POS_SMALL_FLOATS, + NEG_FLOATS, + POS_FLOATS, + NEG_EVENS, + POS_EVENS, + NEG_ODDS, + POS_ODDS, + NEG_INF, + POS_INF, + NEG_ONE, + POS_ONE, + ]; + const POS: &[&[f64]] = &[POS_ZERO, POS_ODDS, POS_ONE, POS_FLOATS, POS_EVENS, POS_INF]; + const NEG: &[&[f64]] = &[NEG_ZERO, NEG_ODDS, NEG_ONE, NEG_FLOATS, NEG_EVENS, NEG_INF]; + + fn pow_test(base: f64, exponent: f64, expected: f64) { + let res = pow(base, exponent); + assert!( + if expected.is_nan() { + res.is_nan() + } else { + pow(base, exponent) == expected + }, + "{} ** {} was {} instead of {}", + base, + exponent, + res, + expected + ); + } + + fn test_sets_as_base(sets: &[&[f64]], exponent: f64, expected: f64) { + sets.iter() + .for_each(|s| s.iter().for_each(|val| pow_test(*val, exponent, expected))); + } + + fn test_sets_as_exponent(base: f64, sets: &[&[f64]], expected: f64) { + sets.iter() + .for_each(|s| s.iter().for_each(|val| pow_test(base, *val, expected))); + } + + fn test_sets(sets: &[&[f64]], computed: &Fn(f64) -> f64, expected: &Fn(f64) -> f64) { + sets.iter().for_each(|s| { + s.iter().for_each(|val| { + let exp = expected(*val); + let res = computed(*val); + + assert!( + if exp.is_nan() { + res.is_nan() + } else { + exp == res + }, + "test for {} was {} instead of {}", + val, + res, + exp + ); + }) + }); + } + + #[test] + fn zero_as_exponent() { + test_sets_as_base(ALL, 0.0, 1.0); + test_sets_as_base(ALL, -0.0, 1.0); + } + + #[test] + fn one_as_base() { + test_sets_as_exponent(1.0, ALL, 1.0); + } + + #[test] + fn nan_inputs() { + // NAN as the base: + // (NAN ^ anything *but 0* should be NAN) + test_sets_as_exponent(NAN, &ALL[2..], NAN); + + // NAN as the exponent: + // (anything *but 1* ^ NAN should be NAN) + test_sets_as_base(&ALL[..(ALL.len() - 2)], NAN, NAN); + } + + #[test] + fn infinity_as_base() { + // Positive Infinity as the base: + // (+Infinity ^ positive anything but 0 and NAN should be +Infinity) + test_sets_as_exponent(INFINITY, &POS[1..], INFINITY); + + // (+Infinity ^ negative anything except 0 and NAN should be 0.0) + test_sets_as_exponent(INFINITY, &NEG[1..], 0.0); + + // Negative Infinity as the base: + // (-Infinity ^ positive odd ints should be -Infinity) + test_sets_as_exponent(NEG_INFINITY, &[POS_ODDS], NEG_INFINITY); + + // (-Infinity ^ anything but odd ints should be == -0 ^ (-anything)) + // We can lump in pos/neg odd ints here because they don't seem to + // cause panics (div by zero) in release mode (I think). + test_sets(ALL, &|v: f64| pow(NEG_INFINITY, v), &|v: f64| pow(-0.0, -v)); + } + + #[test] + fn infinity_as_exponent() { + // Positive/Negative base greater than 1: + // (pos/neg > 1 ^ Infinity should be Infinity - note this excludes NAN as the base) + test_sets_as_base(&ALL[5..(ALL.len() - 2)], INFINITY, INFINITY); + + // (pos/neg > 1 ^ -Infinity should be 0.0) + test_sets_as_base(&ALL[5..ALL.len() - 2], NEG_INFINITY, 0.0); + + // Positive/Negative base less than 1: + let base_below_one = &[POS_ZERO, NEG_ZERO, NEG_SMALL_FLOATS, POS_SMALL_FLOATS]; + + // (pos/neg < 1 ^ Infinity should be 0.0 - this also excludes NAN as the base) + test_sets_as_base(base_below_one, INFINITY, 0.0); + + // (pos/neg < 1 ^ -Infinity should be Infinity) + test_sets_as_base(base_below_one, NEG_INFINITY, INFINITY); + + // Positive/Negative 1 as the base: + // (pos/neg 1 ^ Infinity should be 1) + test_sets_as_base(&[NEG_ONE, POS_ONE], INFINITY, 1.0); + + // (pos/neg 1 ^ -Infinity should be 1) + test_sets_as_base(&[NEG_ONE, POS_ONE], NEG_INFINITY, 1.0); + } + + #[test] + fn zero_as_base() { + // Positive Zero as the base: + // (+0 ^ anything positive but 0 and NAN should be +0) + test_sets_as_exponent(0.0, &POS[1..], 0.0); + + // (+0 ^ anything negative but 0 and NAN should be Infinity) + // (this should panic because we're dividing by zero) + test_sets_as_exponent(0.0, &NEG[1..], INFINITY); + + // Negative Zero as the base: + // (-0 ^ anything positive but 0, NAN, and odd ints should be +0) + test_sets_as_exponent(-0.0, &POS[3..], 0.0); + + // (-0 ^ anything negative but 0, NAN, and odd ints should be Infinity) + // (should panic because of divide by zero) + test_sets_as_exponent(-0.0, &NEG[3..], INFINITY); + + // (-0 ^ positive odd ints should be -0) + test_sets_as_exponent(-0.0, &[POS_ODDS], -0.0); + + // (-0 ^ negative odd ints should be -Infinity) + // (should panic because of divide by zero) + test_sets_as_exponent(-0.0, &[NEG_ODDS], NEG_INFINITY); + } + + #[test] + fn special_cases() { + // One as the exponent: + // (anything ^ 1 should be anything - i.e. the base) + test_sets(ALL, &|v: f64| pow(v, 1.0), &|v: f64| v); + + // Negative One as the exponent: + // (anything ^ -1 should be 1/anything) + test_sets(ALL, &|v: f64| pow(v, -1.0), &|v: f64| 1.0 / v); + + // 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] + .iter() + .for_each(|int_set| { + int_set.iter().for_each(|int| { + test_sets(ALL, &|v: f64| pow(-v, *int), &|v: f64| { + pow(-1.0, *int) * pow(v, *int) + }); + }) + }); + + // Negative base (imaginary results): + // (-anything except 0 and Infinity ^ non-integer should be NAN) + &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); + }) + }); + } + + #[test] + fn normal_cases() { + assert_eq!(pow(2.0, 20.0), (1 << 20) as f64); + assert_eq!(pow(-1.0, 9.0), -1.0); + assert!(pow(-1.0, 2.2).is_nan()); + assert!(pow(-1.0, -1.14).is_nan()); + } +} diff --git a/vendor/libm/src/math/powf.rs b/vendor/libm/src/math/powf.rs new file mode 100644 index 0000000000..015bade86c --- /dev/null +++ b/vendor/libm/src/math/powf.rs @@ -0,0 +1,343 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_powf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{fabsf, scalbnf, sqrtf}; + +const BP: [f32; 2] = [1.0, 1.5]; +const DP_H: [f32; 2] = [0.0, 5.84960938e-01]; /* 0x3f15c000 */ +const DP_L: [f32; 2] = [0.0, 1.56322085e-06]; /* 0x35d1cfdc */ +const TWO24: f32 = 16777216.0; /* 0x4b800000 */ +const HUGE: f32 = 1.0e30; +const TINY: f32 = 1.0e-30; +const L1: f32 = 6.0000002384e-01; /* 0x3f19999a */ +const L2: f32 = 4.2857143283e-01; /* 0x3edb6db7 */ +const L3: f32 = 3.3333334327e-01; /* 0x3eaaaaab */ +const L4: f32 = 2.7272811532e-01; /* 0x3e8ba305 */ +const L5: f32 = 2.3066075146e-01; /* 0x3e6c3255 */ +const L6: f32 = 2.0697501302e-01; /* 0x3e53f142 */ +const P1: f32 = 1.6666667163e-01; /* 0x3e2aaaab */ +const P2: f32 = -2.7777778450e-03; /* 0xbb360b61 */ +const P3: f32 = 6.6137559770e-05; /* 0x388ab355 */ +const P4: f32 = -1.6533901999e-06; /* 0xb5ddea0e */ +const P5: f32 = 4.1381369442e-08; /* 0x3331bb4c */ +const LG2: f32 = 6.9314718246e-01; /* 0x3f317218 */ +const LG2_H: f32 = 6.93145752e-01; /* 0x3f317200 */ +const LG2_L: f32 = 1.42860654e-06; /* 0x35bfbe8c */ +const OVT: f32 = 4.2995665694e-08; /* -(128-log2(ovfl+.5ulp)) */ +const CP: f32 = 9.6179670095e-01; /* 0x3f76384f =2/(3ln2) */ +const CP_H: f32 = 9.6191406250e-01; /* 0x3f764000 =12b cp */ +const CP_L: f32 = -1.1736857402e-04; /* 0xb8f623c6 =tail of cp_h */ +const IVLN2: f32 = 1.4426950216e+00; +const IVLN2_H: f32 = 1.4426879883e+00; +const IVLN2_L: f32 = 7.0526075433e-06; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn powf(x: f32, y: f32) -> f32 { + let mut z: f32; + let mut ax: f32; + let z_h: f32; + let z_l: f32; + let mut p_h: f32; + let mut p_l: f32; + let y1: f32; + let mut t1: f32; + let t2: f32; + let mut r: f32; + let s: f32; + let mut sn: f32; + let mut t: f32; + let mut u: f32; + let mut v: f32; + let mut w: f32; + let i: i32; + let mut j: i32; + let mut k: i32; + let mut yisint: i32; + let mut n: i32; + let hx: i32; + let hy: i32; + let mut ix: i32; + let iy: i32; + let mut is: i32; + + hx = x.to_bits() as i32; + hy = y.to_bits() as i32; + + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + + /* x**0 = 1, even if x is NaN */ + if iy == 0 { + return 1.0; + } + + /* 1**y = 1, even if y is NaN */ + if hx == 0x3f800000 { + return 1.0; + } + + /* NaN if either arg is NaN */ + if ix > 0x7f800000 || iy > 0x7f800000 { + return x + y; + } + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if hx < 0 { + if iy >= 0x4b800000 { + yisint = 2; /* even integer y */ + } else if iy >= 0x3f800000 { + k = (iy >> 23) - 0x7f; /* exponent */ + j = iy >> (23 - k); + if (j << (23 - k)) == iy { + yisint = 2 - (j & 1); + } + } + } + + /* special value of y */ + if iy == 0x7f800000 { + /* y is +-inf */ + if ix == 0x3f800000 { + /* (-1)**+-inf is 1 */ + return 1.0; + } else if ix > 0x3f800000 { + /* (|x|>1)**+-inf = inf,0 */ + return if hy >= 0 { y } else { 0.0 }; + } else { + /* (|x|<1)**+-inf = 0,inf */ + return if hy >= 0 { 0.0 } else { -y }; + } + } + if iy == 0x3f800000 { + /* y is +-1 */ + return if hy >= 0 { x } else { 1.0 / x }; + } + + if hy == 0x40000000 { + /* y is 2 */ + return x * x; + } + + if hy == 0x3f000000 + /* y is 0.5 */ + && hx >= 0 + { + /* x >= +0 */ + return sqrtf(x); + } + + ax = fabsf(x); + /* special value of x */ + if ix == 0x7f800000 || ix == 0 || ix == 0x3f800000 { + /* x is +-0,+-inf,+-1 */ + z = ax; + if hy < 0 { + /* z = (1/|x|) */ + z = 1.0 / z; + } + + if hx < 0 { + if ((ix - 0x3f800000) | yisint) == 0 { + z = (z - z) / (z - z); /* (-1)**non-int is NaN */ + } else if yisint == 1 { + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + } + return z; + } + + sn = 1.0; /* sign of result */ + if hx < 0 { + if yisint == 0 { + /* (x<0)**(non-int) is NaN */ + return (x - x) / (x - x); + } + + if yisint == 1 { + /* (x<0)**(odd int) */ + sn = -1.0; + } + } + + /* |y| is HUGE */ + if iy > 0x4d000000 { + /* if |y| > 2**27 */ + /* over/underflow if x is not close to one */ + if ix < 0x3f7ffff8 { + return if hy < 0 { + sn * HUGE * HUGE + } else { + sn * TINY * TINY + }; + } + + if ix > 0x3f800007 { + return if hy > 0 { + sn * HUGE * HUGE + } else { + sn * TINY * TINY + }; + } + + /* now |1-x| is TINY <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = ax - 1.; /* t has 20 trailing zeros */ + w = (t * t) * (0.5 - t * (0.333333333333 - t * 0.25)); + u = IVLN2_H * t; /* IVLN2_H has 16 sig. bits */ + v = t * IVLN2_L - w * IVLN2; + t1 = u + v; + is = t1.to_bits() as i32; + t1 = f32::from_bits(is as u32 & 0xfffff000); + t2 = v - (t1 - u); + } else { + let mut s2: f32; + let mut s_h: f32; + let s_l: f32; + let mut t_h: f32; + let mut t_l: f32; + + n = 0; + /* take care subnormal number */ + if ix < 0x00800000 { + ax *= TWO24; + n -= 24; + ix = ax.to_bits() as i32; + } + n += ((ix) >> 23) - 0x7f; + j = ix & 0x007fffff; + /* determine interval */ + ix = j | 0x3f800000; /* normalize ix */ + if j <= 0x1cc471 { + /* |x|> 1) & 0xfffff000) | 0x20000000) as i32; + t_h = f32::from_bits(is as u32 + 0x00400000 + ((k as u32) << 21)); + t_l = ax - (t_h - BP[k as usize]); + s_l = v * ((u - s_h * t_h) - s_h * t_l); + /* compute log(ax) */ + s2 = s * s; + r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); + r += s_l * (s_h + s); + s2 = s_h * s_h; + t_h = 3.0 + s2 + r; + is = t_h.to_bits() as i32; + t_h = f32::from_bits(is as u32 & 0xfffff000); + t_l = r - ((t_h - 3.0) - s2); + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = s_l * t_h + t_l * s; + /* 2/(3log2)*(s+...) */ + p_h = u + v; + is = p_h.to_bits() as i32; + p_h = f32::from_bits(is as u32 & 0xfffff000); + p_l = v - (p_h - u); + z_h = CP_H * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = CP_L * p_h + p_l * CP + DP_L[k as usize]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = n as f32; + t1 = ((z_h + z_l) + DP_H[k as usize]) + t; + is = t1.to_bits() as i32; + t1 = f32::from_bits(is as u32 & 0xfffff000); + t2 = z_l - (((t1 - t) - DP_H[k as usize]) - z_h); + }; + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + is = y.to_bits() as i32; + y1 = f32::from_bits(is as u32 & 0xfffff000); + p_l = (y - y1) * t1 + y * t2; + p_h = y1 * t1; + z = p_l + p_h; + j = z.to_bits() as i32; + if j > 0x43000000 { + /* if z > 128 */ + return sn * HUGE * HUGE; /* overflow */ + } else if j == 0x43000000 { + /* if z == 128 */ + if p_l + OVT > z - p_h { + return sn * HUGE * HUGE; /* overflow */ + } + } else if (j & 0x7fffffff) > 0x43160000 { + /* z < -150 */ + // FIXME: check should be (uint32_t)j > 0xc3160000 + return sn * TINY * TINY; /* underflow */ + } else if j as u32 == 0xc3160000 + /* z == -150 */ + && p_l <= z - p_h + { + return sn * TINY * TINY; /* underflow */ + } + + /* + * compute 2**(p_h+p_l) + */ + i = j & 0x7fffffff; + k = (i >> 23) - 0x7f; + n = 0; + if i > 0x3f000000 { + /* if |z| > 0.5, set n = [z+0.5] */ + n = j + (0x00800000 >> (k + 1)); + k = ((n & 0x7fffffff) >> 23) - 0x7f; /* new k for n */ + t = f32::from_bits(n as u32 & !(0x007fffff >> k)); + n = ((n & 0x007fffff) | 0x00800000) >> (23 - k); + if j < 0 { + n = -n; + } + p_h -= t; + } + t = p_l + p_h; + is = t.to_bits() as i32; + t = f32::from_bits(is as u32 & 0xffff8000); + u = t * LG2_H; + v = (p_l - (t - p_h)) * LG2 + t * LG2_L; + z = u + v; + w = v - (z - u); + t = z * z; + t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + r = (z * t1) / (t1 - 2.0) - (w + z * w); + z = 1.0 - (r - z); + j = z.to_bits() as i32; + j += n << 23; + if (j >> 23) <= 0 { + /* subnormal output */ + z = scalbnf(z, n); + } else { + z = f32::from_bits(j as u32); + } + sn * z +} diff --git a/vendor/libm/src/math/rem_pio2.rs b/vendor/libm/src/math/rem_pio2.rs new file mode 100644 index 0000000000..536dfac3c4 --- /dev/null +++ b/vendor/libm/src/math/rem_pio2.rs @@ -0,0 +1,207 @@ +// origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunPro, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== +// +// Optimized by Bruce D. Evans. */ +use super::rem_pio2_large; + +// #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 +// #define EPS DBL_EPSILON +const EPS: f64 = 2.2204460492503131e-16; +// #elif FLT_EVAL_METHOD==2 +// #define EPS LDBL_EPSILON +// #endif + +// TODO: Support FLT_EVAL_METHOD? + +const TO_INT: f64 = 1.5 / EPS; +/// 53 bits of 2/pi +const INV_PIO2: f64 = 6.36619772367581382433e-01; /* 0x3FE45F30, 0x6DC9C883 */ +/// first 33 bits of pi/2 +const PIO2_1: f64 = 1.57079632673412561417e+00; /* 0x3FF921FB, 0x54400000 */ +/// pi/2 - PIO2_1 +const PIO2_1T: f64 = 6.07710050650619224932e-11; /* 0x3DD0B461, 0x1A626331 */ +/// second 33 bits of pi/2 +const PIO2_2: f64 = 6.07710050630396597660e-11; /* 0x3DD0B461, 0x1A600000 */ +/// pi/2 - (PIO2_1+PIO2_2) +const PIO2_2T: f64 = 2.02226624879595063154e-21; /* 0x3BA3198A, 0x2E037073 */ +/// third 33 bits of pi/2 +const PIO2_3: f64 = 2.02226624871116645580e-21; /* 0x3BA3198A, 0x2E000000 */ +/// pi/2 - (PIO2_1+PIO2_2+PIO2_3) +const PIO2_3T: f64 = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +// return the remainder of x rem pi/2 in y[0]+y[1] +// use rem_pio2_large() for large x +// +// caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn rem_pio2(x: f64) -> (i32, f64, f64) { + let x1p24 = f64::from_bits(0x4170000000000000); + + let sign = (f64::to_bits(x) >> 63) as i32; + let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff; + + #[inline] + fn medium(x: f64, ix: u32) -> (i32, f64, f64) { + /* rint(x/(pi/2)), Assume round-to-nearest. */ + let f_n = x as f64 * INV_PIO2 + TO_INT - TO_INT; + let n = f_n as i32; + let mut r = x - f_n * PIO2_1; + let mut w = f_n * PIO2_1T; /* 1st round, good to 85 bits */ + let mut y0 = r - w; + let ui = f64::to_bits(y0); + let ey = (ui >> 52) as i32 & 0x7ff; + let ex = (ix >> 20) as i32; + if ex - ey > 16 { + /* 2nd round, good to 118 bits */ + let t = r; + w = f_n * PIO2_2; + r = t - w; + w = f_n * PIO2_2T - ((t - r) - w); + y0 = r - w; + let ey = (f64::to_bits(y0) >> 52) as i32 & 0x7ff; + if ex - ey > 49 { + /* 3rd round, good to 151 bits, covers all cases */ + let t = r; + w = f_n * PIO2_3; + r = t - w; + w = f_n * PIO2_3T - ((t - r) - w); + y0 = r - w; + } + } + let y1 = (r - y0) - w; + (n, y0, y1) + } + + if ix <= 0x400f6a7a { + /* |x| ~<= 5pi/4 */ + if (ix & 0xfffff) == 0x921fb { + /* |x| ~= pi/2 or 2pi/2 */ + return medium(x, ix); /* cancellation -- use medium case */ + } + if ix <= 0x4002d97c { + /* |x| ~<= 3pi/4 */ + if sign == 0 { + let z = x - PIO2_1; /* one round good to 85 bits */ + let y0 = z - PIO2_1T; + let y1 = (z - y0) - PIO2_1T; + return (1, y0, y1); + } else { + let z = x + PIO2_1; + let y0 = z + PIO2_1T; + let y1 = (z - y0) + PIO2_1T; + return (-1, y0, y1); + } + } else if sign == 0 { + let z = x - 2.0 * PIO2_1; + let y0 = z - 2.0 * PIO2_1T; + let y1 = (z - y0) - 2.0 * PIO2_1T; + return (2, y0, y1); + } else { + let z = x + 2.0 * PIO2_1; + let y0 = z + 2.0 * PIO2_1T; + let y1 = (z - y0) + 2.0 * PIO2_1T; + return (-2, y0, y1); + } + } + if ix <= 0x401c463b { + /* |x| ~<= 9pi/4 */ + if ix <= 0x4015fdbc { + /* |x| ~<= 7pi/4 */ + if ix == 0x4012d97c { + /* |x| ~= 3pi/2 */ + return medium(x, ix); + } + if sign == 0 { + let z = x - 3.0 * PIO2_1; + let y0 = z - 3.0 * PIO2_1T; + let y1 = (z - y0) - 3.0 * PIO2_1T; + return (3, y0, y1); + } else { + let z = x + 3.0 * PIO2_1; + let y0 = z + 3.0 * PIO2_1T; + let y1 = (z - y0) + 3.0 * PIO2_1T; + return (-3, y0, y1); + } + } else { + if ix == 0x401921fb { + /* |x| ~= 4pi/2 */ + return medium(x, ix); + } + if sign == 0 { + let z = x - 4.0 * PIO2_1; + let y0 = z - 4.0 * PIO2_1T; + let y1 = (z - y0) - 4.0 * PIO2_1T; + return (4, y0, y1); + } else { + let z = x + 4.0 * PIO2_1; + let y0 = z + 4.0 * PIO2_1T; + let y1 = (z - y0) + 4.0 * PIO2_1T; + return (-4, y0, y1); + } + } + } + if ix < 0x413921fb { + /* |x| ~< 2^20*(pi/2), medium size */ + return medium(x, ix); + } + /* + * all other (large) arguments + */ + if ix >= 0x7ff00000 { + /* x is inf or NaN */ + let y0 = x - x; + let y1 = y0; + return (0, y0, y1); + } + /* set z = scalbn(|x|,-ilogb(x)+23) */ + let mut ui = f64::to_bits(x); + ui &= (!1) >> 12; + ui |= (0x3ff + 23) << 52; + let mut z = f64::from_bits(ui); + let mut tx = [0.0; 3]; + for i in 0..2 { + tx[i] = z as i32 as f64; + z = (z - tx[i]) * x1p24; + } + tx[2] = z; + /* skip zero terms, first term is non-zero */ + let mut i = 2; + while i != 0 && tx[i] == 0.0 { + i -= 1; + } + let mut ty = [0.0; 3]; + let n = rem_pio2_large(&tx[..=i], &mut ty, ((ix >> 20) - (0x3ff + 23)) as i32, 1); + if sign != 0 { + return (-n, -ty[0], -ty[1]); + } + (n, ty[0], ty[1]) +} + +#[test] +fn test_near_pi() { + assert_eq!( + rem_pio2(3.141592025756836), + (2, -6.278329573009626e-7, -2.1125998133974653e-23) + ); + assert_eq!( + rem_pio2(3.141592033207416), + (2, -6.20382377148128e-7, -2.1125998133974653e-23) + ); + assert_eq!( + rem_pio2(3.141592144966125), + (2, -5.086236681942706e-7, -2.1125998133974653e-23) + ); + assert_eq!( + rem_pio2(3.141592979431152), + (2, 3.2584135866119817e-7, -2.1125998133974653e-23) + ); +} diff --git a/vendor/libm/src/math/rem_pio2_large.rs b/vendor/libm/src/math/rem_pio2_large.rs new file mode 100644 index 0000000000..006d3e153d --- /dev/null +++ b/vendor/libm/src/math/rem_pio2_large.rs @@ -0,0 +1,471 @@ +#![allow(unused_unsafe)] +/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::floor; +use super::scalbn; + +// initial value for jk +const INIT_JK: [usize; 4] = [3, 4, 4, 6]; + +// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi +// +// integer array, contains the (24*i)-th to (24*i+23)-th +// bit of 2/pi after binary point. The corresponding +// floating value is +// +// ipio2[i] * 2^(-24(i+1)). +// +// NB: This table must have at least (e0-3)/24 + jk terms. +// For quad precision (e0 <= 16360, jk = 6), this is 686. +#[cfg(target_pointer_width = "32")] +const IPIO2: [i32; 66] = [ + 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, + 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, + 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, + 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, + 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, + 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, + 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, + 0x73A8C9, 0x60E27B, 0xC08C6B, +]; + +#[cfg(target_pointer_width = "64")] +const IPIO2: [i32; 690] = [ + 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, + 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, + 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, + 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, + 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, + 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, + 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, + 0x73A8C9, 0x60E27B, 0xC08C6B, 0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6, + 0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, 0xDE4F98, 0x327DBB, 0xC33D26, + 0xEF6B1E, 0x5EF89F, 0x3A1F35, 0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30, + 0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, 0x467D86, 0x2D71E3, 0x9AC69B, + 0x006233, 0x7CD2B4, 0x97A7B4, 0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770, + 0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, 0xCB2324, 0x778AD6, 0x23545A, + 0xB91F00, 0x1B0AF1, 0xDFCE19, 0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522, + 0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, 0xDE3B58, 0x929BDE, 0x2822D2, + 0xE88628, 0x4D58E2, 0x32CAC6, 0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E, + 0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, 0xD36710, 0xD8DDAA, 0x425FAE, + 0xCE616A, 0xA4280A, 0xB499D3, 0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF, + 0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, 0x36D9CA, 0xD2A828, 0x8D61C2, + 0x77C912, 0x142604, 0x9B4612, 0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929, + 0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, 0xC3E7B3, 0x28F8C7, 0x940593, + 0x3E71C1, 0xB3092E, 0xF3450B, 0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C, + 0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, 0x9794E8, 0x84E6E2, 0x973199, + 0x6BED88, 0x365F5F, 0x0EFDBB, 0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC, + 0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, 0x90AA47, 0x02E774, 0x24D6BD, + 0xA67DF7, 0x72486E, 0xEF169F, 0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5, + 0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, 0x10D86D, 0x324832, 0x754C5B, + 0xD4714E, 0x6E5445, 0xC1090B, 0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA, + 0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, 0x6AE290, 0x89D988, 0x50722C, + 0xBEA404, 0x940777, 0x7030F3, 0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3, + 0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, 0x3BDF08, 0x2B3715, 0xA0805C, + 0x93805A, 0x921110, 0xD8E80F, 0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61, + 0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, 0xAA140A, 0x2F2689, 0x768364, + 0x333B09, 0x1A940E, 0xAA3A51, 0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0, + 0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, 0x5BC3D8, 0xC492F5, 0x4BADC6, + 0xA5CA4E, 0xCD37A7, 0x36A9E6, 0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC, + 0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, 0x306529, 0xBF5657, 0x3AFF47, + 0xB9F96A, 0xF3BE75, 0xDF9328, 0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D, + 0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, 0xA8654F, 0xA5C1D2, 0x0F3F0B, + 0xCD785B, 0x76F923, 0x048B7B, 0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4, + 0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, 0xDA4886, 0xA05DF7, 0xF480C6, + 0x2FF0AC, 0x9AECDD, 0xBC5C3F, 0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD, + 0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, 0x2A1216, 0x2DB7DC, 0xFDE5FA, + 0xFEDB89, 0xFDBE89, 0x6C76E4, 0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761, + 0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, 0x48D784, 0x16DF30, 0x432DC7, + 0x356125, 0xCE70C9, 0xB8CB30, 0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262, + 0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, 0xC4F133, 0x5F6E13, 0xE4305D, + 0xA92E85, 0xC3B21D, 0x3632A1, 0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C, + 0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, 0xCBDA11, 0xD0BE7D, 0xC1DB9B, + 0xBD17AB, 0x81A2CA, 0x5C6A08, 0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196, + 0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, 0x4F6A68, 0xA82A4A, 0x5AC44F, + 0xBCF82D, 0x985AD7, 0x95C7F4, 0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC, + 0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, 0xD0C0B2, 0x485551, 0x0EFB1E, + 0xC37295, 0x3B06A3, 0x3540C0, 0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C, + 0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, 0x3C3ABA, 0x461846, 0x5F7555, + 0xF5BDD2, 0xC6926E, 0x5D2EAC, 0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22, + 0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, 0x745D7C, 0xB2AD6B, 0x9D6ECD, + 0x7B723E, 0x6A11C6, 0xA9CFF7, 0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5, + 0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, 0xBEFDFD, 0xEF4556, 0x367ED9, + 0x13D9EC, 0xB9BA8B, 0xFC97C4, 0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF, + 0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, 0x9C2A3E, 0xCC5F11, 0x4A0BFD, + 0xFBF4E1, 0x6D3B8E, 0x2C86E2, 0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138, + 0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, 0xCC2254, 0xDC552A, 0xD6C6C0, + 0x96190B, 0xB8701A, 0x649569, 0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34, + 0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, 0x9B5861, 0xBC57E1, 0xC68351, + 0x103ED8, 0x4871DD, 0xDD1C2D, 0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F, + 0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, 0x382682, 0x9BE7CA, 0xA40D51, + 0xB13399, 0x0ED7A9, 0x480569, 0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B, + 0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, 0x5FD45E, 0xA4677B, 0x7AACBA, + 0xA2F655, 0x23882B, 0x55BA41, 0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49, + 0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, 0xAE5ADB, 0x86C547, 0x624385, + 0x3B8621, 0x94792C, 0x876110, 0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8, + 0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, 0xB1933D, 0x0B7CBD, 0xDC51A4, + 0x63DD27, 0xDDE169, 0x19949A, 0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270, + 0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, 0x4D7E6F, 0x5119A5, 0xABF9B5, + 0xD6DF82, 0x61DD96, 0x023616, 0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B, + 0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0, +]; + +const PIO2: [f64; 8] = [ + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +]; + +// fn rem_pio2_large(x : &[f64], y : &mut [f64], e0 : i32, prec : usize) -> i32 +// +// Input parameters: +// x[] The input value (must be positive) is broken into nx +// pieces of 24-bit integers in double precision format. +// x[i] will be the i-th 24 bit of x. The scaled exponent +// of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 +// match x's up to 24 bits. +// +// Example of breaking a double positive z into x[0]+x[1]+x[2]: +// e0 = ilogb(z)-23 +// z = scalbn(z,-e0) +// for i = 0,1,2 +// x[i] = floor(z) +// z = (z-x[i])*2**24 +// +// y[] ouput result in an array of double precision numbers. +// The dimension of y[] is: +// 24-bit precision 1 +// 53-bit precision 2 +// 64-bit precision 2 +// 113-bit precision 3 +// The actual value is the sum of them. Thus for 113-bit +// precison, one may have to do something like: +// +// long double t,w,r_head, r_tail; +// t = (long double)y[2] + (long double)y[1]; +// w = (long double)y[0]; +// r_head = t+w; +// r_tail = w - (r_head - t); +// +// e0 The exponent of x[0]. Must be <= 16360 or you need to +// expand the ipio2 table. +// +// prec an integer indicating the precision: +// 0 24 bits (single) +// 1 53 bits (double) +// 2 64 bits (extended) +// 3 113 bits (quad) +// +// Here is the description of some local variables: +// +// jk jk+1 is the initial number of terms of ipio2[] needed +// in the computation. The minimum and recommended value +// for jk is 3,4,4,6 for single, double, extended, and quad. +// jk+1 must be 2 larger than you might expect so that our +// recomputation test works. (Up to 24 bits in the integer +// part (the 24 bits of it that we compute) and 23 bits in +// the fraction part may be lost to cancelation before we +// recompute.) +// +// jz local integer variable indicating the number of +// terms of ipio2[] used. +// +// jx nx - 1 +// +// jv index for pointing to the suitable ipio2[] for the +// computation. In general, we want +// ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 +// is an integer. Thus +// e0-3-24*jv >= 0 or (e0-3)/24 >= jv +// Hence jv = max(0,(e0-3)/24). +// +// jp jp+1 is the number of terms in PIo2[] needed, jp = jk. +// +// q[] double array with integral value, representing the +// 24-bits chunk of the product of x and 2/pi. +// +// q0 the corresponding exponent of q[0]. Note that the +// exponent for q[i] would be q0-24*i. +// +// PIo2[] double precision array, obtained by cutting pi/2 +// into 24 bits chunks. +// +// f[] ipio2[] in floating point +// +// iq[] integer array by breaking up q[] in 24-bits chunk. +// +// fq[] final product of x*(2/pi) in fq[0],..,fq[jk] +// +// ih integer. If >0 it indicates q[] is >= 0.5, hence +// it also indicates the *sign* of the result. + +/// Return the last three digits of N with y = x - N*pi/2 +/// so that |y| < pi/2. +/// +/// The method is to compute the integer (mod 8) and fraction parts of +/// (2/pi)*x without doing the full multiplication. In general we +/// skip the part of the product that are known to be a huge integer ( +/// more accurately, = 0 mod 8 ). Thus the number of operations are +/// independent of the exponent of the input. +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn rem_pio2_large(x: &[f64], y: &mut [f64], e0: i32, prec: usize) -> i32 { + let x1p24 = f64::from_bits(0x4170000000000000); // 0x1p24 === 2 ^ 24 + let x1p_24 = f64::from_bits(0x3e70000000000000); // 0x1p_24 === 2 ^ (-24) + + #[cfg(all(target_pointer_width = "64", feature = "checked"))] + assert!(e0 <= 16360); + + let nx = x.len(); + + let mut fw: f64; + let mut n: i32; + let mut ih: i32; + let mut z: f64; + let mut f: [f64; 20] = [0.; 20]; + let mut fq: [f64; 20] = [0.; 20]; + let mut q: [f64; 20] = [0.; 20]; + let mut iq: [i32; 20] = [0; 20]; + + /* initialize jk*/ + let jk = INIT_JK[prec]; + let jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + let jx = nx - 1; + let mut jv = (e0 - 3) / 24; + if jv < 0 { + jv = 0; + } + let mut q0 = e0 - 24 * (jv + 1); + let jv = jv as usize; + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + let mut j = (jv - jx) as i32; + let m = jx + jk; + for i in 0..=m { + i!(f, i, =, if j < 0 { + 0. + } else { + i!(IPIO2, j as usize) as f64 + }); + j += 1; + } + + /* compute q[0],q[1],...q[jk] */ + for i in 0..=jk { + fw = 0f64; + for j in 0..=jx { + fw += i!(x, j) * i!(f, jx + i - j); + } + i!(q, i, =, fw); + } + + let mut jz = jk; + + 'recompute: loop { + /* distill q[] into iq[] reversingly */ + let mut i = 0i32; + z = i!(q, jz); + for j in (1..=jz).rev() { + fw = (x1p_24 * z) as i32 as f64; + i!(iq, i as usize, =, (z - x1p24 * fw) as i32); + z = i!(q, j - 1) + fw; + i += 1; + } + + /* compute n */ + z = scalbn(z, q0); /* actual value of z */ + z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */ + n = z as i32; + z -= n as f64; + ih = 0; + if q0 > 0 { + /* need iq[jz-1] to determine n */ + i = i!(iq, jz - 1) >> (24 - q0); + n += i; + i!(iq, jz - 1, -=, i << (24 - q0)); + ih = i!(iq, jz - 1) >> (23 - q0); + } else if q0 == 0 { + ih = i!(iq, jz - 1) >> 23; + } else if z >= 0.5 { + ih = 2; + } + + if ih > 0 { + /* q > 0.5 */ + n += 1; + let mut carry = 0i32; + for i in 0..jz { + /* compute 1-q */ + let j = i!(iq, i); + if carry == 0 { + if j != 0 { + carry = 1; + i!(iq, i, =, 0x1000000 - j); + } + } else { + i!(iq, i, =, 0xffffff - j); + } + } + if q0 > 0 { + /* rare case: chance is 1 in 12 */ + match q0 { + 1 => { + i!(iq, jz - 1, &=, 0x7fffff); + } + 2 => { + i!(iq, jz - 1, &=, 0x3fffff); + } + _ => {} + } + } + if ih == 2 { + z = 1. - z; + if carry != 0 { + z -= scalbn(1., q0); + } + } + } + + /* check if recomputation is needed */ + if z == 0. { + let mut j = 0; + for i in (jk..=jz - 1).rev() { + j |= i!(iq, i); + } + if j == 0 { + /* need recomputation */ + let mut k = 1; + while i!(iq, jk - k, ==, 0) { + k += 1; /* k = no. of terms needed */ + } + + for i in (jz + 1)..=(jz + k) { + /* add q[jz+1] to q[jz+k] */ + i!(f, jx + i, =, i!(IPIO2, jv + i) as f64); + fw = 0f64; + for j in 0..=jx { + fw += i!(x, j) * i!(f, jx + i - j); + } + i!(q, i, =, fw); + } + jz += k; + continue 'recompute; + } + } + + break; + } + + /* chop off zero terms */ + if z == 0. { + jz -= 1; + q0 -= 24; + while i!(iq, jz) == 0 { + jz -= 1; + q0 -= 24; + } + } else { + /* break z into 24-bit if necessary */ + z = scalbn(z, -q0); + if z >= x1p24 { + fw = (x1p_24 * z) as i32 as f64; + i!(iq, jz, =, (z - x1p24 * fw) as i32); + jz += 1; + q0 += 24; + i!(iq, jz, =, fw as i32); + } else { + i!(iq, jz, =, z as i32); + } + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(1., q0); + for i in (0..=jz).rev() { + i!(q, i, =, fw * (i!(iq, i) as f64)); + fw *= x1p_24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for i in (0..=jz).rev() { + fw = 0f64; + let mut k = 0; + while (k <= jp) && (k <= jz - i) { + fw += i!(PIO2, k) * i!(q, i + k); + k += 1; + } + i!(fq, jz - i, =, fw); + } + + /* compress fq[] into y[] */ + match prec { + 0 => { + fw = 0f64; + for i in (0..=jz).rev() { + fw += i!(fq, i); + } + i!(y, 0, =, if ih == 0 { fw } else { -fw }); + } + 1 | 2 => { + fw = 0f64; + for i in (0..=jz).rev() { + fw += i!(fq, i); + } + // TODO: drop excess precision here once double_t is used + fw = fw as f64; + i!(y, 0, =, if ih == 0 { fw } else { -fw }); + fw = i!(fq, 0) - fw; + for i in 1..=jz { + fw += i!(fq, i); + } + i!(y, 1, =, if ih == 0 { fw } else { -fw }); + } + 3 => { + /* painful */ + for i in (1..=jz).rev() { + fw = i!(fq, i - 1) + i!(fq, i); + i!(fq, i, +=, i!(fq, i - 1) - fw); + i!(fq, i - 1, =, fw); + } + for i in (2..=jz).rev() { + fw = i!(fq, i - 1) + i!(fq, i); + i!(fq, i, +=, i!(fq, i - 1) - fw); + i!(fq, i - 1, =, fw); + } + fw = 0f64; + for i in (2..=jz).rev() { + fw += i!(fq, i); + } + if ih == 0 { + i!(y, 0, =, i!(fq, 0)); + i!(y, 1, =, i!(fq, 1)); + i!(y, 2, =, fw); + } else { + i!(y, 0, =, -i!(fq, 0)); + i!(y, 1, =, -i!(fq, 1)); + i!(y, 2, =, -fw); + } + } + #[cfg(feature = "checked")] + _ => unreachable!(), + #[cfg(not(feature = "checked"))] + _ => {} + } + n & 7 +} diff --git a/vendor/libm/src/math/rem_pio2f.rs b/vendor/libm/src/math/rem_pio2f.rs new file mode 100644 index 0000000000..af2745d1be --- /dev/null +++ b/vendor/libm/src/math/rem_pio2f.rs @@ -0,0 +1,63 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2f.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Debugged and optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::rem_pio2_large; + +use core::f64; + +const TOINT: f64 = 1.5 / f64::EPSILON; + +/// 53 bits of 2/pi +const INV_PIO2: f64 = 6.36619772367581382433e-01; /* 0x3FE45F30, 0x6DC9C883 */ +/// first 25 bits of pi/2 +const PIO2_1: f64 = 1.57079631090164184570e+00; /* 0x3FF921FB, 0x50000000 */ +/// pi/2 - pio2_1 +const PIO2_1T: f64 = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */ + +/// Return the remainder of x rem pi/2 in *y +/// +/// use double precision for everything except passing x +/// use __rem_pio2_large() for large x +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub(crate) fn rem_pio2f(x: f32) -> (i32, f64) { + let x64 = x as f64; + + let mut tx: [f64; 1] = [0.]; + let mut ty: [f64; 1] = [0.]; + + let ix = x.to_bits() & 0x7fffffff; + /* 25+53 bit pi is good enough for medium size */ + if ix < 0x4dc90fdb { + /* |x| ~< 2^28*(pi/2), medium size */ + /* Use a specialized rint() to get fn. Assume round-to-nearest. */ + let f_n = x64 * INV_PIO2 + TOINT - TOINT; + return (f_n as i32, x64 - f_n * PIO2_1 - f_n * PIO2_1T); + } + if ix >= 0x7f800000 { + /* x is inf or NaN */ + return (0, x64 - x64); + } + /* scale x into [2^23, 2^24-1] */ + let sign = (x.to_bits() >> 31) != 0; + let e0 = ((ix >> 23) - (0x7f + 23)) as i32; /* e0 = ilogb(|x|)-23, positive */ + tx[0] = f32::from_bits(ix - (e0 << 23) as u32) as f64; + let n = rem_pio2_large(&tx, &mut ty, e0, 0); + if sign { + return (-n, -ty[0]); + } + (n, ty[0]) +} diff --git a/vendor/libm/src/math/remquo.rs b/vendor/libm/src/math/remquo.rs new file mode 100644 index 0000000000..1c2ba8918c --- /dev/null +++ b/vendor/libm/src/math/remquo.rs @@ -0,0 +1,97 @@ +pub fn remquo(mut x: f64, mut y: f64) -> (f64, i32) { + let ux: u64 = x.to_bits(); + let mut uy: u64 = y.to_bits(); + let mut ex = ((ux >> 52) & 0x7ff) as i32; + let mut ey = ((uy >> 52) & 0x7ff) as i32; + let sx = (ux >> 63) != 0; + let sy = (uy >> 63) != 0; + let mut q: u32; + let mut i: u64; + let mut uxi: u64 = ux; + + if (uy << 1) == 0 || y.is_nan() || ex == 0x7ff { + return ((x * y) / (x * y), 0); + } + if (ux << 1) == 0 { + return (x, 0); + } + + /* normalize x and y */ + if ex == 0 { + i = uxi << 12; + while (i >> 63) == 0 { + ex -= 1; + i <<= 1; + } + uxi <<= -ex + 1; + } else { + uxi &= (!0) >> 12; + uxi |= 1 << 52; + } + if ey == 0 { + i = uy << 12; + while (i >> 63) == 0 { + ey -= 1; + i <<= 1; + } + uy <<= -ey + 1; + } else { + uy &= (!0) >> 12; + uy |= 1 << 52; + } + + q = 0; + + if ex + 1 != ey { + if ex < ey { + return (x, 0); + } + /* x mod y */ + while ex > ey { + i = uxi.wrapping_sub(uy); + if (i >> 63) == 0 { + uxi = i; + q += 1; + } + uxi <<= 1; + q <<= 1; + ex -= 1; + } + i = uxi.wrapping_sub(uy); + if (i >> 63) == 0 { + uxi = i; + q += 1; + } + if uxi == 0 { + ex = -60; + } else { + while (uxi >> 52) == 0 { + uxi <<= 1; + ex -= 1; + } + } + } + + /* scale result and decide between |x| and |x|-|y| */ + if ex > 0 { + uxi -= 1 << 52; + uxi |= (ex as u64) << 52; + } else { + uxi >>= -ex + 1; + } + x = f64::from_bits(uxi); + if sy { + y = -y; + } + if ex == ey || (ex + 1 == ey && (2.0 * x > y || (2.0 * x == y && (q % 2) != 0))) { + x -= y; + q += 1; + } + q &= 0x7fffffff; + let quo = if sx ^ sy { -(q as i32) } else { q as i32 }; + if sx { + (-x, quo) + } else { + (x, quo) + } +} diff --git a/vendor/libm/src/math/remquof.rs b/vendor/libm/src/math/remquof.rs new file mode 100644 index 0000000000..871d0c7d69 --- /dev/null +++ b/vendor/libm/src/math/remquof.rs @@ -0,0 +1,96 @@ +pub fn remquof(mut x: f32, mut y: f32) -> (f32, i32) { + let ux: u32 = x.to_bits(); + let mut uy: u32 = y.to_bits(); + let mut ex = ((ux >> 23) & 0xff) as i32; + let mut ey = ((uy >> 23) & 0xff) as i32; + let sx = (ux >> 31) != 0; + let sy = (uy >> 31) != 0; + let mut q: u32; + let mut i: u32; + let mut uxi: u32 = ux; + + if (uy << 1) == 0 || y.is_nan() || ex == 0xff { + return ((x * y) / (x * y), 0); + } + if (ux << 1) == 0 { + return (x, 0); + } + + /* normalize x and y */ + if ex == 0 { + i = uxi << 9; + while (i >> 31) == 0 { + ex -= 1; + i <<= 1; + } + uxi <<= -ex + 1; + } else { + uxi &= (!0) >> 9; + uxi |= 1 << 23; + } + if ey == 0 { + i = uy << 9; + while (i >> 31) == 0 { + ey -= 1; + i <<= 1; + } + uy <<= -ey + 1; + } else { + uy &= (!0) >> 9; + uy |= 1 << 23; + } + + q = 0; + if ex + 1 != ey { + if ex < ey { + return (x, 0); + } + /* x mod y */ + while ex > ey { + i = uxi.wrapping_sub(uy); + if (i >> 31) == 0 { + uxi = i; + q += 1; + } + uxi <<= 1; + q <<= 1; + ex -= 1; + } + i = uxi.wrapping_sub(uy); + if (i >> 31) == 0 { + uxi = i; + q += 1; + } + if uxi == 0 { + ex = -30; + } else { + while (uxi >> 23) == 0 { + uxi <<= 1; + ex -= 1; + } + } + } + + /* scale result and decide between |x| and |x|-|y| */ + if ex > 0 { + uxi -= 1 << 23; + uxi |= (ex as u32) << 23; + } else { + uxi >>= -ex + 1; + } + x = f32::from_bits(uxi); + if sy { + y = -y; + } + if ex == ey || (ex + 1 == ey && (2.0 * x > y || (2.0 * x == y && (q % 2) != 0))) { + x -= y; + q += 1; + } + q &= 0x7fffffff; + let quo = if sx ^ sy { -(q as i32) } else { q as i32 }; + if sx { + (-x, quo) + } else { + (x, quo) + } +} diff --git a/vendor/libm/src/math/round.rs b/vendor/libm/src/math/round.rs new file mode 100644 index 0000000000..9a9723cfbb --- /dev/null +++ b/vendor/libm/src/math/round.rs @@ -0,0 +1,37 @@ +use core::f64; + +const TOINT: f64 = 1.0 / f64::EPSILON; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn round(mut x: f64) -> f64 { + let (f, i) = (x, x.to_bits()); + let e: u64 = i >> 52 & 0x7ff; + let mut y: f64; + + if e >= 0x3ff + 52 { + return x; + } + if i >> 63 != 0 { + x = -x; + } + if e < 0x3ff - 1 { + // raise inexact if x!=0 + force_eval!(x + TOINT); + return 0.0 * f; + } + y = x + TOINT - TOINT - x; + if y > 0.5 { + y = y + x - 1.0; + } else if y <= -0.5 { + y = y + x + 1.0; + } else { + y = y + x; + } + + if i >> 63 != 0 { + -y + } else { + y + } +} diff --git a/vendor/libm/src/math/roundf.rs b/vendor/libm/src/math/roundf.rs new file mode 100644 index 0000000000..839d9469a4 --- /dev/null +++ b/vendor/libm/src/math/roundf.rs @@ -0,0 +1,35 @@ +use core::f32; + +const TOINT: f32 = 1.0 / f32::EPSILON; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn roundf(mut x: f32) -> f32 { + let i = x.to_bits(); + let e: u32 = i >> 23 & 0xff; + let mut y: f32; + + if e >= 0x7f + 23 { + return x; + } + if i >> 31 != 0 { + x = -x; + } + if e < 0x7f - 1 { + force_eval!(x + TOINT); + return 0.0 * x; + } + y = x + TOINT - TOINT - x; + if y > 0.5f32 { + y = y + x - 1.0; + } else if y <= -0.5f32 { + y = y + x + 1.0; + } else { + y = y + x; + } + if i >> 31 != 0 { + -y + } else { + y + } +} diff --git a/vendor/libm/src/math/scalbn.rs b/vendor/libm/src/math/scalbn.rs new file mode 100644 index 0000000000..d8c8409ac1 --- /dev/null +++ b/vendor/libm/src/math/scalbn.rs @@ -0,0 +1,34 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn scalbn(x: f64, mut n: i32) -> f64 { + let x1p1023 = f64::from_bits(0x7fe0000000000000); // 0x1p1023 === 2 ^ 1023 + let x1p53 = f64::from_bits(0x4340000000000000); // 0x1p53 === 2 ^ 53 + let x1p_1022 = f64::from_bits(0x0010000000000000); // 0x1p-1022 === 2 ^ (-1022) + + let mut y = x; + + if n > 1023 { + y *= x1p1023; + n -= 1023; + if n > 1023 { + y *= x1p1023; + n -= 1023; + if n > 1023 { + n = 1023; + } + } + } else if n < -1022 { + /* make sure final n < -53 to avoid double + rounding in the subnormal range */ + y *= x1p_1022 * x1p53; + n += 1022 - 53; + if n < -1022 { + y *= x1p_1022 * x1p53; + n += 1022 - 53; + if n < -1022 { + n = -1022; + } + } + } + y * f64::from_bits(((0x3ff + n) as u64) << 52) +} diff --git a/vendor/libm/src/math/scalbnf.rs b/vendor/libm/src/math/scalbnf.rs new file mode 100644 index 0000000000..4e9771175d --- /dev/null +++ b/vendor/libm/src/math/scalbnf.rs @@ -0,0 +1,30 @@ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn scalbnf(mut x: f32, mut n: i32) -> f32 { + let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127 + let x1p_126 = f32::from_bits(0x800000); // 0x1p-126f === 2 ^ -126 + let x1p24 = f32::from_bits(0x4b800000); // 0x1p24f === 2 ^ 24 + + if n > 127 { + x *= x1p127; + n -= 127; + if n > 127 { + x *= x1p127; + n -= 127; + if n > 127 { + n = 127; + } + } + } else if n < -126 { + x *= x1p_126 * x1p24; + n += 126 - 24; + if n < -126 { + x *= x1p_126 * x1p24; + n += 126 - 24; + if n < -126 { + n = -126; + } + } + } + x * f32::from_bits(((0x7f + n) as u32) << 23) +} diff --git a/vendor/libm/src/math/sin.rs b/vendor/libm/src/math/sin.rs new file mode 100644 index 0000000000..51aed88a8d --- /dev/null +++ b/vendor/libm/src/math/sin.rs @@ -0,0 +1,86 @@ +// origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */ +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunPro, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== + +use super::{k_cos, k_sin, rem_pio2}; + +// sin(x) +// Return sine function of x. +// +// kernel function: +// k_sin ... sine function on [-pi/4,pi/4] +// k_cos ... cose function on [-pi/4,pi/4] +// rem_pio2 ... argument reduction routine +// +// Method. +// Let S,C and T denote the sin, cos and tan respectively on +// [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 +// in [-pi/4 , +pi/4], and let n = k mod 4. +// We have +// +// n sin(x) cos(x) tan(x) +// ---------------------------------------------------------- +// 0 S C T +// 1 C -S -1/T +// 2 -S -C T +// 3 -C S -1/T +// ---------------------------------------------------------- +// +// Special cases: +// Let trig be any of sin, cos, or tan. +// trig(+-INF) is NaN, with signals; +// trig(NaN) is that NaN; +// +// Accuracy: +// TRIG(x) returns trig(x) nearly rounded +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn sin(x: f64) -> f64 { + let x1p120 = f64::from_bits(0x4770000000000000); // 0x1p120f === 2 ^ 120 + + /* High word of x. */ + let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff; + + /* |x| ~< pi/4 */ + if ix <= 0x3fe921fb { + if ix < 0x3e500000 { + /* |x| < 2**-26 */ + /* raise inexact if x != 0 and underflow if subnormal*/ + if ix < 0x00100000 { + force_eval!(x / x1p120); + } else { + force_eval!(x + x1p120); + } + return x; + } + return k_sin(x, 0.0, 0); + } + + /* sin(Inf or NaN) is NaN */ + if ix >= 0x7ff00000 { + return x - x; + } + + /* argument reduction needed */ + let (n, y0, y1) = rem_pio2(x); + match n & 3 { + 0 => k_sin(y0, y1, 1), + 1 => k_cos(y0, y1), + 2 => -k_sin(y0, y1, 1), + _ => -k_cos(y0, y1), + } +} + +#[test] +fn test_near_pi() { + let x = f64::from_bits(0x400921fb000FD5DD); // 3.141592026217707 + let sx = f64::from_bits(0x3ea50d15ced1a4a2); // 6.273720864039205e-7 + assert_eq!(sin(x), sx); +} diff --git a/vendor/libm/src/math/sincos.rs b/vendor/libm/src/math/sincos.rs new file mode 100644 index 0000000000..750908df4f --- /dev/null +++ b/vendor/libm/src/math/sincos.rs @@ -0,0 +1,59 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{get_high_word, k_cos, k_sin, rem_pio2}; + +pub fn sincos(x: f64) -> (f64, f64) { + let s: f64; + let c: f64; + let mut ix: u32; + + ix = get_high_word(x); + ix &= 0x7fffffff; + + /* |x| ~< pi/4 */ + if ix <= 0x3fe921fb { + /* if |x| < 2**-27 * sqrt(2) */ + if ix < 0x3e46a09e { + /* raise inexact if x!=0 and underflow if subnormal */ + let x1p120 = f64::from_bits(0x4770000000000000); // 0x1p120 == 2^120 + if ix < 0x00100000 { + force_eval!(x / x1p120); + } else { + force_eval!(x + x1p120); + } + return (x, 1.0); + } + return (k_sin(x, 0.0, 0), k_cos(x, 0.0)); + } + + /* sincos(Inf or NaN) is NaN */ + if ix >= 0x7ff00000 { + let rv = x - x; + return (rv, rv); + } + + /* argument reduction needed */ + let (n, y0, y1) = rem_pio2(x); + s = k_sin(y0, y1, 1); + c = k_cos(y0, y1); + match n & 3 { + 0 => (s, c), + 1 => (c, -s), + 2 => (-s, -c), + 3 => (-c, s), + #[cfg(feature = "checked")] + _ => unreachable!(), + #[cfg(not(feature = "checked"))] + _ => (0.0, 1.0), + } +} diff --git a/vendor/libm/src/math/sincosf.rs b/vendor/libm/src/math/sincosf.rs new file mode 100644 index 0000000000..bb9a003920 --- /dev/null +++ b/vendor/libm/src/math/sincosf.rs @@ -0,0 +1,123 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{k_cosf, k_sinf, rem_pio2f}; + +/* Small multiples of pi/2 rounded to double precision. */ +const PI_2: f32 = 0.5 * 3.1415926535897931160E+00; +const S1PIO2: f32 = 1.0 * PI_2; /* 0x3FF921FB, 0x54442D18 */ +const S2PIO2: f32 = 2.0 * PI_2; /* 0x400921FB, 0x54442D18 */ +const S3PIO2: f32 = 3.0 * PI_2; /* 0x4012D97C, 0x7F3321D2 */ +const S4PIO2: f32 = 4.0 * PI_2; /* 0x401921FB, 0x54442D18 */ + +pub fn sincosf(x: f32) -> (f32, f32) { + let s: f32; + let c: f32; + let mut ix: u32; + let sign: bool; + + ix = x.to_bits(); + sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + + /* |x| ~<= pi/4 */ + if ix <= 0x3f490fda { + /* |x| < 2**-12 */ + if ix < 0x39800000 { + /* raise inexact if x!=0 and underflow if subnormal */ + + let x1p120 = f32::from_bits(0x7b800000); // 0x1p120 == 2^120 + if ix < 0x00100000 { + force_eval!(x / x1p120); + } else { + force_eval!(x + x1p120); + } + return (x, 1.0); + } + return (k_sinf(x as f64), k_cosf(x as f64)); + } + + /* |x| ~<= 5*pi/4 */ + if ix <= 0x407b53d1 { + if ix <= 0x4016cbe3 { + /* |x| ~<= 3pi/4 */ + if sign { + s = -k_cosf((x + S1PIO2) as f64); + c = k_sinf((x + S1PIO2) as f64); + } else { + s = k_cosf((S1PIO2 - x) as f64); + c = k_sinf((S1PIO2 - x) as f64); + } + } + /* -sin(x+c) is not correct if x+c could be 0: -0 vs +0 */ + else { + if sign { + s = k_sinf((x + S2PIO2) as f64); + c = k_cosf((x + S2PIO2) as f64); + } else { + s = k_sinf((x - S2PIO2) as f64); + c = k_cosf((x - S2PIO2) as f64); + } + } + + return (s, c); + } + + /* |x| ~<= 9*pi/4 */ + if ix <= 0x40e231d5 { + if ix <= 0x40afeddf { + /* |x| ~<= 7*pi/4 */ + if sign { + s = k_cosf((x + S3PIO2) as f64); + c = -k_sinf((x + S3PIO2) as f64); + } else { + s = -k_cosf((x - S3PIO2) as f64); + c = k_sinf((x - S3PIO2) as f64); + } + } else { + if sign { + s = k_cosf((x + S4PIO2) as f64); + c = k_sinf((x + S4PIO2) as f64); + } else { + s = k_cosf((x - S4PIO2) as f64); + c = k_sinf((x - S4PIO2) as f64); + } + } + + return (s, c); + } + + /* sin(Inf or NaN) is NaN */ + if ix >= 0x7f800000 { + let rv = x - x; + return (rv, rv); + } + + /* general argument reduction needed */ + let (n, y) = rem_pio2f(x); + s = k_sinf(y); + c = k_cosf(y); + match n & 3 { + 0 => (s, c), + 1 => (c, -s), + 2 => (-s, -c), + 3 => (-c, s), + #[cfg(feature = "checked")] + _ => unreachable!(), + #[cfg(not(feature = "checked"))] + _ => (0.0, 1.0), + } +} diff --git a/vendor/libm/src/math/sinf.rs b/vendor/libm/src/math/sinf.rs new file mode 100644 index 0000000000..0c31099edd --- /dev/null +++ b/vendor/libm/src/math/sinf.rs @@ -0,0 +1,94 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{k_cosf, k_sinf, rem_pio2f}; + +use core::f64::consts::FRAC_PI_2; + +/* Small multiples of pi/2 rounded to double precision. */ +const S1_PIO2: f64 = 1. * FRAC_PI_2; /* 0x3FF921FB, 0x54442D18 */ +const S2_PIO2: f64 = 2. * FRAC_PI_2; /* 0x400921FB, 0x54442D18 */ +const S3_PIO2: f64 = 3. * FRAC_PI_2; /* 0x4012D97C, 0x7F3321D2 */ +const S4_PIO2: f64 = 4. * FRAC_PI_2; /* 0x401921FB, 0x54442D18 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn sinf(x: f32) -> f32 { + let x64 = x as f64; + + let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120 + + let mut ix = x.to_bits(); + let sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + + if ix <= 0x3f490fda { + /* |x| ~<= pi/4 */ + if ix < 0x39800000 { + /* |x| < 2**-12 */ + /* raise inexact if x!=0 and underflow if subnormal */ + force_eval!(if ix < 0x00800000 { + x / x1p120 + } else { + x + x1p120 + }); + return x; + } + return k_sinf(x64); + } + if ix <= 0x407b53d1 { + /* |x| ~<= 5*pi/4 */ + if ix <= 0x4016cbe3 { + /* |x| ~<= 3pi/4 */ + if sign { + return -k_cosf(x64 + S1_PIO2); + } else { + return k_cosf(x64 - S1_PIO2); + } + } + return k_sinf(if sign { + -(x64 + S2_PIO2) + } else { + -(x64 - S2_PIO2) + }); + } + if ix <= 0x40e231d5 { + /* |x| ~<= 9*pi/4 */ + if ix <= 0x40afeddf { + /* |x| ~<= 7*pi/4 */ + if sign { + return k_cosf(x64 + S3_PIO2); + } else { + return -k_cosf(x64 - S3_PIO2); + } + } + return k_sinf(if sign { x64 + S4_PIO2 } else { x64 - S4_PIO2 }); + } + + /* sin(Inf or NaN) is NaN */ + if ix >= 0x7f800000 { + return x - x; + } + + /* general argument reduction needed */ + let (n, y) = rem_pio2f(x); + match n & 3 { + 0 => k_sinf(y), + 1 => k_cosf(y), + 2 => k_sinf(-y), + _ => -k_cosf(y), + } +} diff --git a/vendor/libm/src/math/sinh.rs b/vendor/libm/src/math/sinh.rs new file mode 100644 index 0000000000..d36de66c1c --- /dev/null +++ b/vendor/libm/src/math/sinh.rs @@ -0,0 +1,50 @@ +use super::{expm1, expo2}; + +// sinh(x) = (exp(x) - 1/exp(x))/2 +// = (exp(x)-1 + (exp(x)-1)/exp(x))/2 +// = x + x^3/6 + o(x^5) +// +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn sinh(x: f64) -> f64 { + // union {double f; uint64_t i;} u = {.f = x}; + // uint32_t w; + // double t, h, absx; + + let mut uf: f64 = x; + let mut ui: u64 = f64::to_bits(uf); + let w: u32; + let t: f64; + let mut h: f64; + let absx: f64; + + h = 0.5; + if ui >> 63 != 0 { + h = -h; + } + /* |x| */ + ui &= !1 / 2; + uf = f64::from_bits(ui); + absx = uf; + w = (ui >> 32) as u32; + + /* |x| < log(DBL_MAX) */ + if w < 0x40862e42 { + t = expm1(absx); + if w < 0x3ff00000 { + if w < 0x3ff00000 - (26 << 20) { + /* note: inexact and underflow are raised by expm1 */ + /* note: this branch avoids spurious underflow */ + return x; + } + return h * (2.0 * t - t * t / (t + 1.0)); + } + /* note: |x|>log(0x1p26)+eps could be just h*exp(x) */ + return h * (t + t / (t + 1.0)); + } + + /* |x| > log(DBL_MAX) or nan */ + /* note: the result is stored to handle overflow */ + t = 2.0 * h * expo2(absx); + t +} diff --git a/vendor/libm/src/math/sinhf.rs b/vendor/libm/src/math/sinhf.rs new file mode 100644 index 0000000000..fd0b2bfc89 --- /dev/null +++ b/vendor/libm/src/math/sinhf.rs @@ -0,0 +1,31 @@ +use super::expm1f; +use super::k_expo2f; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn sinhf(x: f32) -> f32 { + let mut h = 0.5f32; + let mut ix = x.to_bits(); + if (ix >> 31) != 0 { + h = -h; + } + /* |x| */ + ix &= 0x7fffffff; + let absx = f32::from_bits(ix); + let w = ix; + + /* |x| < log(FLT_MAX) */ + if w < 0x42b17217 { + let t = expm1f(absx); + if w < 0x3f800000 { + if w < (0x3f800000 - (12 << 23)) { + return x; + } + return h * (2. * t - t * t / (t + 1.)); + } + return h * (t + t / (t + 1.)); + } + + /* |x| > logf(FLT_MAX) or nan */ + 2. * h * k_expo2f(absx) +} diff --git a/vendor/libm/src/math/sqrt.rs b/vendor/libm/src/math/sqrt.rs new file mode 100644 index 0000000000..14404d4eb1 --- /dev/null +++ b/vendor/libm/src/math/sqrt.rs @@ -0,0 +1,223 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + */ + +use core::f64; +use core::num::Wrapping; + +const TINY: f64 = 1.0e-300; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn sqrt(x: f64) -> f64 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f64.sqrt` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return if x < 0.0 { + f64::NAN + } else { + unsafe { ::core::intrinsics::sqrtf64(x) } + } + } + } + let mut z: f64; + let sign: Wrapping = Wrapping(0x80000000); + let mut ix0: i32; + let mut s0: i32; + let mut q: i32; + let mut m: i32; + let mut t: i32; + let mut i: i32; + let mut r: Wrapping; + let mut t1: Wrapping; + let mut s1: Wrapping; + let mut ix1: Wrapping; + let mut q1: Wrapping; + + ix0 = (x.to_bits() >> 32) as i32; + ix1 = Wrapping(x.to_bits() as u32); + + /* take care of Inf and NaN */ + if (ix0 & 0x7ff00000) == 0x7ff00000 { + return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if ix0 <= 0 { + if ((ix0 & !(sign.0 as i32)) | ix1.0 as i32) == 0 { + return x; /* sqrt(+-0) = +-0 */ + } + if ix0 < 0 { + return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ + } + } + /* normalize x */ + m = ix0 >> 20; + if m == 0 { + /* subnormal x */ + while ix0 == 0 { + m -= 21; + ix0 |= (ix1 >> 11).0 as i32; + ix1 <<= 21; + } + i = 0; + while (ix0 & 0x00100000) == 0 { + i += 1; + ix0 <<= 1; + } + m -= i - 1; + ix0 |= (ix1 >> (32 - i) as usize).0 as i32; + ix1 = ix1 << i as usize; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0 & 0x000fffff) | 0x00100000; + if (m & 1) == 1 { + /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; + ix1 += ix1; + q = 0; /* [q,q1] = sqrt(x) */ + q1 = Wrapping(0); + s0 = 0; + s1 = Wrapping(0); + r = Wrapping(0x00200000); /* r = moving bit from right to left */ + + while r != Wrapping(0) { + t = s0 + r.0 as i32; + if t <= ix0 { + s0 = t + r.0 as i32; + ix0 -= t; + q += r.0 as i32; + } + ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; + ix1 += ix1; + r >>= 1; + } + + r = sign; + while r != Wrapping(0) { + t1 = s1 + r; + t = s0; + if t < ix0 || (t == ix0 && t1 <= ix1) { + s1 = t1 + r; + if (t1 & sign) == sign && (s1 & sign) == Wrapping(0) { + s0 += 1; + } + ix0 -= t; + if ix1 < t1 { + ix0 -= 1; + } + ix1 -= t1; + q1 += r; + } + ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; + ix1 += ix1; + r >>= 1; + } + + /* use floating add to find out rounding direction */ + if (ix0 as u32 | ix1.0) != 0 { + z = 1.0 - TINY; /* raise inexact flag */ + if z >= 1.0 { + z = 1.0 + TINY; + if q1.0 == 0xffffffff { + q1 = Wrapping(0); + q += 1; + } else if z > 1.0 { + if q1.0 == 0xfffffffe { + q += 1; + } + q1 += Wrapping(2); + } else { + q1 += q1 & Wrapping(1); + } + } + } + ix0 = (q >> 1) + 0x3fe00000; + ix1 = q1 >> 1; + if (q & 1) == 1 { + ix1 |= sign; + } + ix0 += m << 20; + f64::from_bits((ix0 as u64) << 32 | ix1.0 as u64) +} diff --git a/vendor/libm/src/math/sqrtf.rs b/vendor/libm/src/math/sqrtf.rs new file mode 100644 index 0000000000..b9365c6171 --- /dev/null +++ b/vendor/libm/src/math/sqrtf.rs @@ -0,0 +1,112 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrtf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +const TINY: f32 = 1.0e-30; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn sqrtf(x: f32) -> f32 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f32.sqrt` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return if x < 0.0 { + ::core::f32::NAN + } else { + unsafe { ::core::intrinsics::sqrtf32(x) } + } + } + } + let mut z: f32; + let sign: i32 = 0x80000000u32 as i32; + let mut ix: i32; + let mut s: i32; + let mut q: i32; + let mut m: i32; + let mut t: i32; + let mut i: i32; + let mut r: u32; + + ix = x.to_bits() as i32; + + /* take care of Inf and NaN */ + if (ix as u32 & 0x7f800000) == 0x7f800000 { + return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ + } + + /* take care of zero */ + if ix <= 0 { + if (ix & !sign) == 0 { + return x; /* sqrt(+-0) = +-0 */ + } + if ix < 0 { + return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ + } + } + + /* normalize x */ + m = ix >> 23; + if m == 0 { + /* subnormal x */ + i = 0; + while ix & 0x00800000 == 0 { + ix <<= 1; + i = i + 1; + } + m -= i - 1; + } + m -= 127; /* unbias exponent */ + ix = (ix & 0x007fffff) | 0x00800000; + if m & 1 == 1 { + /* odd m, double x to make it even */ + ix += ix; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix += ix; + q = 0; + s = 0; + r = 0x01000000; /* r = moving bit from right to left */ + + while r != 0 { + t = s + r as i32; + if t <= ix { + s = t + r as i32; + ix -= t; + q += r as i32; + } + ix += ix; + r >>= 1; + } + + /* use floating add to find out rounding direction */ + if ix != 0 { + z = 1.0 - TINY; /* raise inexact flag */ + if z >= 1.0 { + z = 1.0 + TINY; + if z > 1.0 { + q += 2; + } else { + q += q & 1; + } + } + } + + ix = (q >> 1) + 0x3f000000; + ix += m << 23; + f32::from_bits(ix as u32) +} diff --git a/vendor/libm/src/math/tan.rs b/vendor/libm/src/math/tan.rs new file mode 100644 index 0000000000..e5c94cbb15 --- /dev/null +++ b/vendor/libm/src/math/tan.rs @@ -0,0 +1,71 @@ +// origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */ +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunPro, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== + +use super::{k_tan, rem_pio2}; + +// tan(x) +// Return tangent function of x. +// +// kernel function: +// k_tan ... tangent function on [-pi/4,pi/4] +// rem_pio2 ... argument reduction routine +// +// Method. +// Let S,C and T denote the sin, cos and tan respectively on +// [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 +// in [-pi/4 , +pi/4], and let n = k mod 4. +// We have +// +// n sin(x) cos(x) tan(x) +// ---------------------------------------------------------- +// 0 S C T +// 1 C -S -1/T +// 2 -S -C T +// 3 -C S -1/T +// ---------------------------------------------------------- +// +// Special cases: +// Let trig be any of sin, cos, or tan. +// trig(+-INF) is NaN, with signals; +// trig(NaN) is that NaN; +// +// Accuracy: +// TRIG(x) returns trig(x) nearly rounded +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn tan(x: f64) -> f64 { + let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120 + + let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff; + /* |x| ~< pi/4 */ + if ix <= 0x3fe921fb { + if ix < 0x3e400000 { + /* |x| < 2**-27 */ + /* raise inexact if x!=0 and underflow if subnormal */ + force_eval!(if ix < 0x00100000 { + x / x1p120 as f64 + } else { + x + x1p120 as f64 + }); + return x; + } + return k_tan(x, 0.0, 0); + } + + /* tan(Inf or NaN) is NaN */ + if ix >= 0x7ff00000 { + return x - x; + } + + /* argument reduction */ + let (n, y0, y1) = rem_pio2(x); + k_tan(y0, y1, n & 1) +} diff --git a/vendor/libm/src/math/tanf.rs b/vendor/libm/src/math/tanf.rs new file mode 100644 index 0000000000..c286cdeb41 --- /dev/null +++ b/vendor/libm/src/math/tanf.rs @@ -0,0 +1,79 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_tanf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +use super::{k_tanf, rem_pio2f}; + +use core::f64::consts::FRAC_PI_2; + +/* Small multiples of pi/2 rounded to double precision. */ +const T1_PIO2: f64 = 1. * FRAC_PI_2; /* 0x3FF921FB, 0x54442D18 */ +const T2_PIO2: f64 = 2. * FRAC_PI_2; /* 0x400921FB, 0x54442D18 */ +const T3_PIO2: f64 = 3. * FRAC_PI_2; /* 0x4012D97C, 0x7F3321D2 */ +const T4_PIO2: f64 = 4. * FRAC_PI_2; /* 0x401921FB, 0x54442D18 */ + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn tanf(x: f32) -> f32 { + let x64 = x as f64; + + let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120 + + let mut ix = x.to_bits(); + let sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + + if ix <= 0x3f490fda { + /* |x| ~<= pi/4 */ + if ix < 0x39800000 { + /* |x| < 2**-12 */ + /* raise inexact if x!=0 and underflow if subnormal */ + force_eval!(if ix < 0x00800000 { + x / x1p120 + } else { + x + x1p120 + }); + return x; + } + return k_tanf(x64, false); + } + if ix <= 0x407b53d1 { + /* |x| ~<= 5*pi/4 */ + if ix <= 0x4016cbe3 { + /* |x| ~<= 3pi/4 */ + return k_tanf(if sign { x64 + T1_PIO2 } else { x64 - T1_PIO2 }, true); + } else { + return k_tanf(if sign { x64 + T2_PIO2 } else { x64 - T2_PIO2 }, false); + } + } + if ix <= 0x40e231d5 { + /* |x| ~<= 9*pi/4 */ + if ix <= 0x40afeddf { + /* |x| ~<= 7*pi/4 */ + return k_tanf(if sign { x64 + T3_PIO2 } else { x64 - T3_PIO2 }, true); + } else { + return k_tanf(if sign { x64 + T4_PIO2 } else { x64 - T4_PIO2 }, false); + } + } + + /* tan(Inf or NaN) is NaN */ + if ix >= 0x7f800000 { + return x - x; + } + + /* argument reduction */ + let (n, y) = rem_pio2f(x); + k_tanf(y, n & 1 != 0) +} diff --git a/vendor/libm/src/math/tanh.rs b/vendor/libm/src/math/tanh.rs new file mode 100644 index 0000000000..75d695cf7e --- /dev/null +++ b/vendor/libm/src/math/tanh.rs @@ -0,0 +1,54 @@ +use super::expm1; + +/* tanh(x) = (exp(x) - exp(-x))/(exp(x) + exp(-x)) + * = (exp(2*x) - 1)/(exp(2*x) - 1 + 2) + * = (1 - exp(-2*x))/(exp(-2*x) - 1 + 2) + */ +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn tanh(mut x: f64) -> f64 { + let mut uf: f64 = x; + let mut ui: u64 = f64::to_bits(uf); + + let w: u32; + let sign: bool; + let mut t: f64; + + /* x = |x| */ + sign = ui >> 63 != 0; + ui &= !1 / 2; + uf = f64::from_bits(ui); + x = uf; + w = (ui >> 32) as u32; + + if w > 0x3fe193ea { + /* |x| > log(3)/2 ~= 0.5493 or nan */ + if w > 0x40340000 { + /* |x| > 20 or nan */ + /* note: this branch avoids raising overflow */ + t = 1.0 - 0.0 / x; + } else { + t = expm1(2.0 * x); + t = 1.0 - 2.0 / (t + 2.0); + } + } else if w > 0x3fd058ae { + /* |x| > log(5/3)/2 ~= 0.2554 */ + t = expm1(2.0 * x); + t = t / (t + 2.0); + } else if w >= 0x00100000 { + /* |x| >= 0x1p-1022, up to 2ulp error in [0.1,0.2554] */ + t = expm1(-2.0 * x); + t = -t / (t + 2.0); + } else { + /* |x| is subnormal */ + /* note: the branch above would not raise underflow in [0x1p-1023,0x1p-1022) */ + force_eval!(x as f32); + t = x; + } + + if sign { + -t + } else { + t + } +} diff --git a/vendor/libm/src/math/tanhf.rs b/vendor/libm/src/math/tanhf.rs new file mode 100644 index 0000000000..ac4657b5ab --- /dev/null +++ b/vendor/libm/src/math/tanhf.rs @@ -0,0 +1,40 @@ +use super::expm1f; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn tanhf(mut x: f32) -> f32 { + /* x = |x| */ + let mut ix = x.to_bits(); + let sign = (ix >> 31) != 0; + ix &= 0x7fffffff; + x = f32::from_bits(ix); + let w = ix; + + let tt = if w > 0x3f0c9f54 { + /* |x| > log(3)/2 ~= 0.5493 or nan */ + if w > 0x41200000 { + /* |x| > 10 */ + 1. + 0. / x + } else { + let t = expm1f(2. * x); + 1. - 2. / (t + 2.) + } + } else if w > 0x3e82c578 { + /* |x| > log(5/3)/2 ~= 0.2554 */ + let t = expm1f(2. * x); + t / (t + 2.) + } else if w >= 0x00800000 { + /* |x| >= 0x1p-126 */ + let t = expm1f(-2. * x); + -t / (t + 2.) + } else { + /* |x| is subnormal */ + force_eval!(x * x); + x + }; + if sign { + -tt + } else { + tt + } +} diff --git a/vendor/libm/src/math/tgamma.rs b/vendor/libm/src/math/tgamma.rs new file mode 100644 index 0000000000..f8ccf669a2 --- /dev/null +++ b/vendor/libm/src/math/tgamma.rs @@ -0,0 +1,207 @@ +/* +"A Precision Approximation of the Gamma Function" - Cornelius Lanczos (1964) +"Lanczos Implementation of the Gamma Function" - Paul Godfrey (2001) +"An Analysis of the Lanczos Gamma Approximation" - Glendon Ralph Pugh (2004) + +approximation method: + + (x - 0.5) S(x) +Gamma(x) = (x + g - 0.5) * ---------------- + exp(x + g - 0.5) + +with + a1 a2 a3 aN +S(x) ~= [ a0 + ----- + ----- + ----- + ... + ----- ] + x + 1 x + 2 x + 3 x + N + +with a0, a1, a2, a3,.. aN constants which depend on g. + +for x < 0 the following reflection formula is used: + +Gamma(x)*Gamma(-x) = -pi/(x sin(pi x)) + +most ideas and constants are from boost and python +*/ +extern crate core; +use super::{exp, floor, k_cos, k_sin, pow}; + +const PI: f64 = 3.141592653589793238462643383279502884; + +/* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */ +fn sinpi(mut x: f64) -> f64 { + let mut n: isize; + + /* argument reduction: x = |x| mod 2 */ + /* spurious inexact when x is odd int */ + x = x * 0.5; + x = 2.0 * (x - floor(x)); + + /* reduce x into [-.25,.25] */ + n = (4.0 * x) as isize; + n = (n + 1) / 2; + x -= (n as f64) * 0.5; + + x *= PI; + match n { + 1 => k_cos(x, 0.0), + 2 => k_sin(-x, 0.0, 0), + 3 => -k_cos(x, 0.0), + 0 | _ => k_sin(x, 0.0, 0), + } +} + +const N: usize = 12; +//static const double g = 6.024680040776729583740234375; +const GMHALF: f64 = 5.524680040776729583740234375; +const SNUM: [f64; N + 1] = [ + 23531376880.410759688572007674451636754734846804940, + 42919803642.649098768957899047001988850926355848959, + 35711959237.355668049440185451547166705960488635843, + 17921034426.037209699919755754458931112671403265390, + 6039542586.3520280050642916443072979210699388420708, + 1439720407.3117216736632230727949123939715485786772, + 248874557.86205415651146038641322942321632125127801, + 31426415.585400194380614231628318205362874684987640, + 2876370.6289353724412254090516208496135991145378768, + 186056.26539522349504029498971604569928220784236328, + 8071.6720023658162106380029022722506138218516325024, + 210.82427775157934587250973392071336271166969580291, + 2.5066282746310002701649081771338373386264310793408, +]; +const SDEN: [f64; N + 1] = [ + 0.0, + 39916800.0, + 120543840.0, + 150917976.0, + 105258076.0, + 45995730.0, + 13339535.0, + 2637558.0, + 357423.0, + 32670.0, + 1925.0, + 66.0, + 1.0, +]; +/* n! for small integer n */ +const FACT: [f64; 23] = [ + 1.0, + 1.0, + 2.0, + 6.0, + 24.0, + 120.0, + 720.0, + 5040.0, + 40320.0, + 362880.0, + 3628800.0, + 39916800.0, + 479001600.0, + 6227020800.0, + 87178291200.0, + 1307674368000.0, + 20922789888000.0, + 355687428096000.0, + 6402373705728000.0, + 121645100408832000.0, + 2432902008176640000.0, + 51090942171709440000.0, + 1124000727777607680000.0, +]; + +/* S(x) rational function for positive x */ +fn s(x: f64) -> f64 { + let mut num: f64 = 0.0; + let mut den: f64 = 0.0; + + /* to avoid overflow handle large x differently */ + if x < 8.0 { + for i in (0..=N).rev() { + num = num * x + SNUM[i]; + den = den * x + SDEN[i]; + } + } else { + for i in 0..=N { + num = num / x + SNUM[i]; + den = den / x + SDEN[i]; + } + } + return num / den; +} + +pub fn tgamma(mut x: f64) -> f64 { + let u: u64 = x.to_bits(); + let absx: f64; + let mut y: f64; + let mut dy: f64; + let mut z: f64; + let mut r: f64; + let ix: u32 = ((u >> 32) as u32) & 0x7fffffff; + let sign: bool = (u >> 63) != 0; + + /* special cases */ + if ix >= 0x7ff00000 { + /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */ + return x + core::f64::INFINITY; + } + if ix < ((0x3ff - 54) << 20) { + /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */ + return 1.0 / x; + } + + /* integer arguments */ + /* raise inexact when non-integer */ + if x == floor(x) { + if sign { + return 0.0 / 0.0; + } + if x <= FACT.len() as f64 { + return FACT[(x as usize) - 1]; + } + } + + /* x >= 172: tgamma(x)=inf with overflow */ + /* x =< -184: tgamma(x)=+-0 with underflow */ + if ix >= 0x40670000 { + /* |x| >= 184 */ + if sign { + let x1p_126 = f64::from_bits(0x3810000000000000); // 0x1p-126 == 2^-126 + force_eval!((x1p_126 / x) as f32); + if floor(x) * 0.5 == floor(x * 0.5) { + return 0.0; + } else { + return -0.0; + } + } + let x1p1023 = f64::from_bits(0x7fe0000000000000); // 0x1p1023 == 2^1023 + x *= x1p1023; + return x; + } + + absx = if sign { -x } else { x }; + + /* handle the error of x + g - 0.5 */ + y = absx + GMHALF; + if absx > GMHALF { + dy = y - absx; + dy -= GMHALF; + } else { + dy = y - GMHALF; + dy -= absx; + } + + z = absx - 0.5; + r = s(absx) * exp(-y); + if x < 0.0 { + /* reflection formula for negative x */ + /* sinpi(absx) is not 0, integers are already handled */ + r = -PI / (sinpi(absx) * absx * r); + dy = -dy; + z = -z; + } + r += dy * (GMHALF + 0.5) * r / y; + z = pow(y, 0.5 * z); + y = r * z * z; + return y; +} diff --git a/vendor/libm/src/math/tgammaf.rs b/vendor/libm/src/math/tgammaf.rs new file mode 100644 index 0000000000..a8f161f0c1 --- /dev/null +++ b/vendor/libm/src/math/tgammaf.rs @@ -0,0 +1,5 @@ +use super::tgamma; + +pub fn tgammaf(x: f32) -> f32 { + tgamma(x as f64) as f32 +} diff --git a/vendor/libm/src/math/trunc.rs b/vendor/libm/src/math/trunc.rs new file mode 100644 index 0000000000..1ee46fc7da --- /dev/null +++ b/vendor/libm/src/math/trunc.rs @@ -0,0 +1,41 @@ +use core::f64; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn trunc(x: f64) -> f64 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f64.trunc` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::truncf64(x) } + } + } + let x1p120 = f64::from_bits(0x4770000000000000); // 0x1p120f === 2 ^ 120 + + let mut i: u64 = x.to_bits(); + let mut e: i64 = (i >> 52 & 0x7ff) as i64 - 0x3ff + 12; + let m: u64; + + if e >= 52 + 12 { + return x; + } + if e < 12 { + e = 1; + } + m = -1i64 as u64 >> e; + if (i & m) == 0 { + return x; + } + force_eval!(x + x1p120); + i &= !m; + f64::from_bits(i) +} + +#[cfg(test)] +mod tests { + #[test] + fn sanity_check() { + assert_eq!(super::trunc(1.1), 1.0); + } +} diff --git a/vendor/libm/src/math/truncf.rs b/vendor/libm/src/math/truncf.rs new file mode 100644 index 0000000000..f933832690 --- /dev/null +++ b/vendor/libm/src/math/truncf.rs @@ -0,0 +1,41 @@ +use core::f32; + +#[inline] +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn truncf(x: f32) -> f32 { + // On wasm32 we know that LLVM's intrinsic will compile to an optimized + // `f32.trunc` native instruction, so we can leverage this for both code size + // and speed. + llvm_intrinsically_optimized! { + #[cfg(target_arch = "wasm32")] { + return unsafe { ::core::intrinsics::truncf32(x) } + } + } + let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120 + + let mut i: u32 = x.to_bits(); + let mut e: i32 = (i >> 23 & 0xff) as i32 - 0x7f + 9; + let m: u32; + + if e >= 23 + 9 { + return x; + } + if e < 9 { + e = 1; + } + m = -1i32 as u32 >> e; + if (i & m) == 0 { + return x; + } + force_eval!(x + x1p120); + i &= !m; + f32::from_bits(i) +} + +#[cfg(test)] +mod tests { + #[test] + fn sanity_check() { + assert_eq!(super::truncf(1.1), 1.0); + } +} diff --git a/vendor/lock_api/.cargo-checksum.json b/vendor/lock_api/.cargo-checksum.json index f22814ff2a..b8e13f18bb 100644 --- a/vendor/lock_api/.cargo-checksum.json +++ b/vendor/lock_api/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"0b7ec1020d4c5b58310956b970789207f7e257062d4045786773b4a34338161f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","src/lib.rs":"e30eee3009000171f340316683699e7a6bcbb63e241fc29f836acf3be5544fb7","src/mutex.rs":"db7f0dcb09fc5aaab2b04d6eac7b80b799da8fdb669fa43ddbb7007663760782","src/remutex.rs":"1049b5c824a1f2df4e0ed348fbe8a9d5697f9ad4779b174ad7a02610d23bcf7c","src/rwlock.rs":"6639e140c50ee81e212647e5a2596c0e247a0a062ee8471c79d268c1280c7330"},"package":"dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"} \ No newline at end of file +{"files":{"Cargo.toml":"06563e3dc0450ad2719f696feca64c1d037d23a20bb488ee06748fac3a843513","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","src/lib.rs":"e30eee3009000171f340316683699e7a6bcbb63e241fc29f836acf3be5544fb7","src/mutex.rs":"db7f0dcb09fc5aaab2b04d6eac7b80b799da8fdb669fa43ddbb7007663760782","src/remutex.rs":"83f6704348eb5052364c98aea2c5eaa621b22e3f4b03c4c130069496f7825595","src/rwlock.rs":"6639e140c50ee81e212647e5a2596c0e247a0a062ee8471c79d268c1280c7330"},"package":"5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"} \ No newline at end of file diff --git a/vendor/lock_api/Cargo.toml b/vendor/lock_api/Cargo.toml index cdc5b164f6..5f5c4398ce 100644 --- a/vendor/lock_api/Cargo.toml +++ b/vendor/lock_api/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "lock_api" -version = "0.4.2" +version = "0.4.3" authors = ["Amanieu d'Antras "] description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std." keywords = ["mutex", "rwlock", "lock", "no_std"] diff --git a/vendor/lock_api/src/remutex.rs b/vendor/lock_api/src/remutex.rs index 09833b06d6..b49ec6c0e5 100644 --- a/vendor/lock_api/src/remutex.rs +++ b/vendor/lock_api/src/remutex.rs @@ -135,6 +135,13 @@ impl RawReentrantMutex { pub fn is_locked(&self) -> bool { self.mutex.is_locked() } + + /// Checks whether the mutex is currently held by the current thread. + #[inline] + pub fn is_owned_by_current_thread(&self) -> bool { + let id = self.get_thread_id.nonzero_thread_id().get(); + self.owner.load(Ordering::Relaxed) == id + } } impl RawReentrantMutex { @@ -333,6 +340,12 @@ impl ReentrantMutex { self.raw.is_locked() } + /// Checks whether the mutex is currently held by the current thread. + #[inline] + pub fn is_owned_by_current_thread(&self) -> bool { + self.raw.is_owned_by_current_thread() + } + /// Forcibly unlocks the mutex. /// /// This is useful when combined with `mem::forget` to hold a lock without diff --git a/vendor/memmap2/.cargo-checksum.json b/vendor/memmap2/.cargo-checksum.json index 19a48c7a58..0fa2854ee7 100644 --- a/vendor/memmap2/.cargo-checksum.json +++ b/vendor/memmap2/.cargo-checksum.json @@ -1 +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 +{"files":{"CHANGELOG.md":"2a9557f020325204147619969ff08fe97ef795297737a8bde58822daddde69dd","Cargo.lock":"a6c8e45c0166b1319bd14f5f268039034f47d898ce4812ea69e30cdc9a499715","Cargo.toml":"efe624d0a6519d0e49ddfc6242a9fa162c1c6e6c625f44219f05e2553348c67a","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"e9116f7228fce981d81aa680ae1add0cfb8122c35d801c4664d3d674ad0beda8","README.md":"4e70c39451ff48d9b60e2a0db4754fefc2fe349149b4baf4747ca3556ac7ae15","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/lib.rs":"312a5779c22072fbfc2b2ba62230ee982e853e80fe152080dd44aaeac894bf36","src/unix.rs":"11f1f7c628827ad4d84564586b2718b046b5aae8d6b70bed3a2b715f1bb39ef4","src/windows.rs":"bca08b6db9a81ebb22517f92b9c38660d5ec3f8681cd9322f723ce2d715c1886"},"package":"397d1a6d6d0563c0f5462bbdae662cf6c784edf5e828e40c7257f85d82bf56dd"} \ No newline at end of file diff --git a/vendor/memmap2/CHANGELOG.md b/vendor/memmap2/CHANGELOG.md index 258be14c25..5c33ee55d5 100644 --- a/vendor/memmap2/CHANGELOG.md +++ b/vendor/memmap2/CHANGELOG.md @@ -6,15 +6,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## 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). +- `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). +- 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 diff --git a/vendor/memmap2/Cargo.lock b/vendor/memmap2/Cargo.lock index 76c7131c13..cfdb3eb19e 100644 --- a/vendor/memmap2/Cargo.lock +++ b/vendor/memmap2/Cargo.lock @@ -14,7 +14,7 @@ checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" [[package]] name = "memmap2" -version = "0.2.1" +version = "0.2.2" dependencies = [ "libc", "tempdir", diff --git a/vendor/memmap2/Cargo.toml b/vendor/memmap2/Cargo.toml index 1765b84cc8..c02a24d78d 100644 --- a/vendor/memmap2/Cargo.toml +++ b/vendor/memmap2/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "memmap2" -version = "0.2.1" +version = "0.2.2" authors = ["Dan Burkert ", "Evgeniy Reizner "] description = "Cross-platform Rust API for memory-mapped file IO" documentation = "https://docs.rs/memmap2" diff --git a/vendor/memmap2/src/lib.rs b/vendor/memmap2/src/lib.rs index b408ba8a22..942f02a139 100644 --- a/vendor/memmap2/src/lib.rs +++ b/vendor/memmap2/src/lib.rs @@ -1,6 +1,6 @@ //! A cross-platform Rust API for memory mapped buffers. -#![doc(html_root_url = "https://docs.rs/memmap2/0.2.1")] +#![doc(html_root_url = "https://docs.rs/memmap2/0.2.2")] #[cfg(windows)] mod windows; @@ -10,7 +10,7 @@ use windows::MmapInner; #[cfg(unix)] mod unix; #[cfg(unix)] -use crate::unix::MmapInner; +use unix::MmapInner; use std::fmt; use std::fs::File; @@ -44,6 +44,7 @@ pub struct MmapOptions { offset: u64, len: Option, stack: bool, + populate: bool, } impl MmapOptions { @@ -144,7 +145,7 @@ impl MmapOptions { /// 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 corresponds to the `MAP_STACK` flag on Linux. It has no effect on Windows. /// /// This option has no effect on file-backed memory maps. /// @@ -163,6 +164,34 @@ impl MmapOptions { 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 @@ -192,7 +221,8 @@ impl MmapOptions { /// # } /// ``` pub unsafe fn map(&self, file: &File) -> Result { - MmapInner::map(self.get_len(file)?, file, self.offset).map(|inner| Mmap { inner: inner }) + 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. @@ -202,8 +232,8 @@ impl MmapOptions { /// 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 { - MmapInner::map_exec(self.get_len(file)?, file, self.offset) - .map(|inner| Mmap { inner: inner }) + 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. @@ -240,8 +270,8 @@ impl MmapOptions { /// # } /// ``` pub unsafe fn map_mut(&self, file: &File) -> Result { - MmapInner::map_mut(self.get_len(file)?, file, self.offset) - .map(|inner| MmapMut { inner: inner }) + 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. @@ -269,8 +299,8 @@ impl MmapOptions { /// # } /// ``` pub unsafe fn map_copy(&self, file: &File) -> Result { - MmapInner::map_copy(self.get_len(file)?, file, self.offset) - .map(|inner| MmapMut { inner: inner }) + 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. @@ -302,8 +332,8 @@ impl MmapOptions { /// # } /// ``` pub unsafe fn map_copy_read_only(&self, file: &File) -> Result { - MmapInner::map_copy_read_only(self.get_len(file)?, file, self.offset) - .map(|inner| Mmap { inner: inner }) + MmapInner::map_copy_read_only(self.get_len(file)?, file, self.offset, self.populate) + .map(|inner| Mmap { inner }) } /// Creates an anonymous memory map. @@ -315,7 +345,7 @@ impl MmapOptions { /// /// This method returns an error when the underlying system call fails. pub fn map_anon(&self) -> Result { - MmapInner::map_anon(self.len.unwrap_or(0), self.stack).map(|inner| MmapMut { inner: inner }) + MmapInner::map_anon(self.len.unwrap_or(0), self.stack).map(|inner| MmapMut { inner }) } /// Creates a raw memory map. @@ -325,8 +355,8 @@ impl MmapOptions { /// 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 { - MmapInner::map_mut(self.get_len(file)?, file, self.offset) - .map(|inner| MmapRaw { inner: inner }) + MmapInner::map_mut(self.get_len(file)?, file, self.offset, self.populate) + .map(|inner| MmapRaw { inner }) } } @@ -507,7 +537,9 @@ impl MmapRaw { /// 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() } + pub fn as_ptr(&self) -> *const u8 { + self.inner.ptr() + } /// Returns an unsafe mutable pointer to the memory mapped file. /// @@ -516,13 +548,17 @@ impl MmapRaw { /// 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 _ } + 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() } + pub fn len(&self) -> usize { + self.inner.len() + } } impl fmt::Debug for MmapRaw { @@ -785,8 +821,6 @@ mod test { 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; @@ -886,7 +920,7 @@ mod test { (&mut mmap[..]).write_all(write).unwrap(); mmap.flush().unwrap(); - file.read(&mut read).unwrap(); + file.read_exact(&mut read).unwrap(); assert_eq!(write, &read); } @@ -912,6 +946,7 @@ mod test { .unwrap() }; (&mut mmap[..]).write_all(write).unwrap(); + mmap.flush_async_range(0, write.len()).unwrap(); mmap.flush_range(0, write.len()).unwrap(); } @@ -934,20 +969,20 @@ mod test { let mut mmap = unsafe { MmapOptions::new().map_copy(&file).unwrap() }; - (&mut mmap[..]).write(write).unwrap(); + (&mut mmap[..]).write_all(write).unwrap(); mmap.flush().unwrap(); // The mmap contains the write - (&mmap[..]).read(&mut read).unwrap(); + (&mmap[..]).read_exact(&mut read).unwrap(); assert_eq!(write, &read); // The file does not contain the write - file.read(&mut read).unwrap(); + 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(&mut read).unwrap(); + (&mmap2[..]).read_exact(&mut read).unwrap(); assert_eq!(nulls, &read); } @@ -968,11 +1003,11 @@ mod test { let mut read = [0u8; 6]; let mmap = unsafe { MmapOptions::new().map_copy_read_only(&file).unwrap() }; - (&mmap[..]).read(&mut read).unwrap(); + (&mmap[..]).read_exact(&mut read).unwrap(); assert_eq!(nulls, &read); let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() }; - (&mmap2[..]).read(&mut read).unwrap(); + (&mmap2[..]).read_exact(&mut read).unwrap(); assert_eq!(nulls, &read); } @@ -1028,10 +1063,15 @@ mod test { #[test] fn sync_send() { - let mmap = Arc::new(MmapMut::map_anon(129).unwrap()); - thread::spawn(move || { - &mmap[..]; - }); + let mmap = MmapMut::map_anon(129).unwrap(); + + fn is_sync_send(_val: T) + where + T: Sync + Send, + { + } + + is_sync_send(mmap); } #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] @@ -1090,7 +1130,7 @@ mod test { .create(true) .open(&path) .expect("open"); - file.set_len(256 as u64).expect("set_len"); + file.set_len(256_u64).expect("set_len"); let mmap = unsafe { MmapMut::map_mut(&file).expect("map_mut") }; @@ -1100,20 +1140,20 @@ mod test { let write = b"abc123"; let mut read = [0u8; 6]; - (&mut mmap[..]).write(write).unwrap(); + (&mut mmap[..]).write_all(write).unwrap(); mmap.flush().unwrap(); // The mmap contains the write - (&mmap[..]).read(&mut read).unwrap(); + (&mmap[..]).read_exact(&mut read).unwrap(); assert_eq!(write, &read); // The file should contain the write - file.read(&mut read).unwrap(); + 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(&mut read).unwrap(); + (&mmap2[..]).read_exact(&mut read).unwrap(); assert_eq!(write, &read); let mmap = mmap.make_exec().expect("make_exec"); @@ -1136,7 +1176,7 @@ mod test { .create(true) .open(&path) .expect("open"); - file.set_len(256 as u64).expect("set_len"); + file.set_len(256_u64).expect("set_len"); let mmap = unsafe { MmapOptions::new().map_copy(&file).expect("map_mut") }; @@ -1147,20 +1187,20 @@ mod test { let write = b"abc123"; let mut read = [0u8; 6]; - (&mut mmap[..]).write(write).unwrap(); + (&mut mmap[..]).write_all(write).unwrap(); mmap.flush().unwrap(); // The mmap contains the write - (&mmap[..]).read(&mut read).unwrap(); + (&mmap[..]).read_exact(&mut read).unwrap(); assert_eq!(write, &read); // The file does not contain the write - file.read(&mut read).unwrap(); + 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(&mut read).unwrap(); + (&mmap2[..]).read_exact(&mut read).unwrap(); assert_eq!(nulls, &read); let mmap = mmap.make_exec().expect("make_exec"); @@ -1190,7 +1230,7 @@ mod test { .create(true) .open(&path) .expect("open"); - file.write(b"abc123").unwrap(); + 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()); diff --git a/vendor/memmap2/src/unix.rs b/vendor/memmap2/src/unix.rs index d8437a9212..2d45e68d65 100644 --- a/vendor/memmap2/src/unix.rs +++ b/vendor/memmap2/src/unix.rs @@ -18,6 +18,12 @@ const MAP_STACK: libc::c_int = libc::MAP_STACK; )))] 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, @@ -60,57 +66,67 @@ impl MmapInner { } else { Ok(MmapInner { ptr: ptr.offset(alignment as isize), - len: len, + len, }) } } } - pub fn map(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map(len: usize, file: &File, offset: u64, populate: bool) -> io::Result { + let populate = if populate { MAP_POPULATE } else { 0 }; MmapInner::new( len, libc::PROT_READ, - libc::MAP_SHARED, + libc::MAP_SHARED | populate, file.as_raw_fd(), offset, ) } - pub fn map_exec(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_exec(len: usize, file: &File, offset: u64, populate: bool) -> io::Result { + let populate = if populate { MAP_POPULATE } else { 0 }; MmapInner::new( len, libc::PROT_READ | libc::PROT_EXEC, - libc::MAP_SHARED, + libc::MAP_SHARED | populate, file.as_raw_fd(), offset, ) } - pub fn map_mut(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_mut(len: usize, file: &File, offset: u64, populate: bool) -> io::Result { + let populate = if populate { MAP_POPULATE } else { 0 }; MmapInner::new( len, libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_SHARED, + libc::MAP_SHARED | populate, file.as_raw_fd(), offset, ) } - pub fn map_copy(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_copy(len: usize, file: &File, offset: u64, populate: bool) -> io::Result { + let populate = if populate { MAP_POPULATE } else { 0 }; MmapInner::new( len, libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_PRIVATE, + libc::MAP_PRIVATE | populate, file.as_raw_fd(), offset, ) } - pub fn map_copy_read_only(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_copy_read_only( + len: usize, + file: &File, + offset: u64, + populate: bool, + ) -> io::Result { + let populate = if populate { MAP_POPULATE } else { 0 }; MmapInner::new( len, libc::PROT_READ, - libc::MAP_PRIVATE, + libc::MAP_PRIVATE | populate, file.as_raw_fd(), offset, ) @@ -142,16 +158,11 @@ impl MmapInner { } 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, - ) - }; + 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 { diff --git a/vendor/memmap2/src/windows.rs b/vendor/memmap2/src/windows.rs index a0f3d552a4..df8d479c20 100644 --- a/vendor/memmap2/src/windows.rs +++ b/vendor/memmap2/src/windows.rs @@ -31,8 +31,12 @@ 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 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; @@ -82,9 +86,7 @@ struct SYSTEM_INFO { } extern "system" { - fn CloseHandle( - hObject: HANDLE, - ) -> BOOL; + fn CloseHandle(hObject: HANDLE) -> BOOL; fn CreateFileMappingW( hFile: HANDLE, @@ -95,14 +97,9 @@ extern "system" { lpName: LPCWSTR, ) -> HANDLE; - fn FlushViewOfFile( - lpBaseAddress: LPCVOID, - dwNumberOfBytesToFlush: SIZE_T, - ) -> BOOL; + fn FlushViewOfFile(lpBaseAddress: LPCVOID, dwNumberOfBytesToFlush: SIZE_T) -> BOOL; - fn UnmapViewOfFile( - lpBaseAddress: LPCVOID, - ) -> BOOL; + fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL; fn MapViewOfFile( hFileMappingObject: HANDLE, @@ -119,9 +116,7 @@ extern "system" { lpflOldProtect: PDWORD, ) -> BOOL; - fn GetSystemInfo( - lpSystemInfo: LPSYSTEM_INFO, - ); + fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); } pub struct MmapInner { @@ -156,7 +151,7 @@ impl MmapInner { 0, ptr::null(), ); - if handle == ptr::null_mut() { + if handle.is_null() { return Err(io::Error::last_os_error()); } @@ -169,20 +164,20 @@ impl MmapInner { ); CloseHandle(handle); - if ptr == ptr::null_mut() { + 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: copy, + copy, }) } } } - pub fn map(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map(len: usize, file: &File, offset: u64, _populate: bool) -> io::Result { 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; @@ -209,7 +204,12 @@ impl MmapInner { Ok(inner) } - pub fn map_exec(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_exec( + len: usize, + file: &File, + offset: u64, + _populate: bool, + ) -> io::Result { let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE); let mut access = FILE_MAP_READ | FILE_MAP_EXECUTE; let protection = if write { @@ -226,7 +226,7 @@ impl MmapInner { Ok(inner) } - pub fn map_mut(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_mut(len: usize, file: &File, offset: u64, _populate: bool) -> io::Result { let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ); let mut access = FILE_MAP_READ | FILE_MAP_WRITE; let protection = if exec { @@ -243,7 +243,12 @@ impl MmapInner { Ok(inner) } - pub fn map_copy(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_copy( + len: usize, + file: &File, + offset: u64, + _populate: bool, + ) -> io::Result { let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READWRITE); let mut access = FILE_MAP_COPY; let protection = if exec { @@ -260,7 +265,12 @@ impl MmapInner { Ok(inner) } - pub fn map_copy_read_only(len: usize, file: &File, offset: u64) -> io::Result { + pub fn map_copy_read_only( + len: usize, + file: &File, + offset: u64, + _populate: bool, + ) -> io::Result { 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; @@ -293,14 +303,14 @@ impl MmapInner { (len & 0xffffffff) as DWORD, ptr::null(), ); - if handle == ptr::null_mut() { + 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 == ptr::null_mut() { + if ptr.is_null() { return Err(io::Error::last_os_error()); } @@ -309,7 +319,7 @@ impl MmapInner { if result != 0 { Ok(MmapInner { file: None, - ptr: ptr, + ptr, len: len as usize, copy: false, }) @@ -328,7 +338,7 @@ impl MmapInner { } 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) }; + let result = unsafe { FlushViewOfFile(self.ptr.add(offset), len as SIZE_T) }; if result != 0 { Ok(()) } else { @@ -409,7 +419,7 @@ 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() { + if handle.is_null() { return false; } CloseHandle(handle); @@ -421,6 +431,6 @@ fn allocation_granularity() -> usize { unsafe { let mut info = mem::zeroed(); GetSystemInfo(&mut info); - return info.dwAllocationGranularity as usize; + info.dwAllocationGranularity as usize } } diff --git a/vendor/memoffset/.cargo-checksum.json b/vendor/memoffset/.cargo-checksum.json index 7c8590ab4e..ac0ad963b4 100644 --- a/vendor/memoffset/.cargo-checksum.json +++ b/vendor/memoffset/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"333c7595740d7640056444df0ecc255393a198098f4a464902e2ec5fc6579086","LICENSE":"3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1","README.md":"ab1f5d43646dda8a433f5b39e176007d6d3a19348cdb1e6a525e9d3f287223cf","build.rs":"35fa2f5fabdaba3ad8ad311bf4c402530e01b3103b6376c0a7249d9635be3c54","ci/miri.sh":"ad7410b0a5bd6e346f55e9d96ec0719a085a2d1ce266bddfe6fe73333a1eb8ec","src/lib.rs":"0621a03c51702403e46846f871bab0f576c9557f33b94c37431a57ce81c665d1","src/offset_of.rs":"e1836cde12a430c7639630efb1635a43321ec0a4d8cdeb6d0d9080b75e607fb7","src/raw_field.rs":"c19ff6ccbe40f9c1e2fa62e39bb4e4ac1b9a1c020a1ffdbc790c47615b37c010","src/span_of.rs":"2d9216b794327e95f55bad04ba7d8e76ff5313713c187b319348d8e5620aa0a9"},"package":"157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"} \ No newline at end of file +{"files":{"Cargo.toml":"045622efd2d70f644e5a250d9354e7f2e754d4f16c82ea193e8bf41ee20504a8","LICENSE":"3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1","README.md":"5fa2d8db2b91d1dab87a67545a4e6b5a5f06a42ab1d4f4fdf068641094f4bca4","build.rs":"6d677e33a1c98d588c97ec7985d4d5c3b954683e0a73c3dc53d79db4fbb5e638","ci/miri.sh":"ad7410b0a5bd6e346f55e9d96ec0719a085a2d1ce266bddfe6fe73333a1eb8ec","src/lib.rs":"14b7574dbb690c3c3e3b633b5db6c77b4fd12e092269ec4a9d8702a37207293b","src/offset_of.rs":"c62f87015758a7c85bafe312f77dda0199f120b894527453c2ed82ba67d0f24c","src/raw_field.rs":"295cc971d64e51f3d053e56c692ae6ef3bb58915298f1ec49bb695b767daff46","src/span_of.rs":"e9e8eb985f51de0915351365f451d9b9e45385dc1d374f3d59373fa774939fe5"},"package":"f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"} \ No newline at end of file diff --git a/vendor/memoffset/Cargo.toml b/vendor/memoffset/Cargo.toml index 9e2874f381..e2737575ad 100644 --- a/vendor/memoffset/Cargo.toml +++ b/vendor/memoffset/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "memoffset" -version = "0.6.1" +version = "0.6.3" authors = ["Gilad Naaman "] description = "offset_of functionality for Rust structs." readme = "README.md" @@ -28,4 +28,3 @@ version = "1" [features] default = [] unstable_const = [] -unstable_raw = [] diff --git a/vendor/memoffset/README.md b/vendor/memoffset/README.md index 67ce9ebe69..a60f288bf1 100644 --- a/vendor/memoffset/README.md +++ b/vendor/memoffset/README.md @@ -73,8 +73,3 @@ Your crate root: (`lib.rs`/`main.rs`) ``` If you intend to use `offset_of!` inside a `const fn`, also add the `const_fn` compiler feature. - -### Raw references ### -Recent nightlies support [a way to create raw pointers](https://github.com/rust-lang/rust/issues/73394) that avoids creating intermediate safe references. -`memoffset` can make use of that feature to avoid what is technically Undefined Behavior. -Use the `unstable_raw` feature to enable this. diff --git a/vendor/memoffset/build.rs b/vendor/memoffset/build.rs index c83bff2b55..0604c1954e 100644 --- a/vendor/memoffset/build.rs +++ b/vendor/memoffset/build.rs @@ -16,4 +16,7 @@ fn main() { if ac.probe_rustc_version(1, 40) { println!("cargo:rustc-cfg=doctests"); } + if ac.probe_rustc_version(1, 51) { + println!("cargo:rustc-cfg=raw_ref_macros"); + } } diff --git a/vendor/memoffset/src/lib.rs b/vendor/memoffset/src/lib.rs index c85fb01418..454759eb2c 100644 --- a/vendor/memoffset/src/lib.rs +++ b/vendor/memoffset/src/lib.rs @@ -67,7 +67,6 @@ const_raw_ptr_deref, ) )] -#![cfg_attr(feature = "unstable_raw", feature(raw_ref_macros))] #[macro_use] #[cfg(doctests)] @@ -77,12 +76,20 @@ extern crate doc_comment; #[cfg(doctest)] doctest!("../README.md"); -// This `use` statement enables the macros to use `$crate::mem`. -// Doing this enables this crate to function under both std and no-std crates. +/// Hiden module for things the macros need to access. #[doc(hidden)] -pub use core::mem; -#[doc(hidden)] -pub use core::ptr; +pub mod __priv { + #[doc(hidden)] + pub use core::mem; + #[doc(hidden)] + pub use core::ptr; + + /// Use type inference to obtain the size of the pointee (without actually using the pointer). + #[doc(hidden)] + pub fn size_of_pointee(_ptr: *const T) -> usize { + mem::size_of::() + } +} #[macro_use] mod raw_field; diff --git a/vendor/memoffset/src/offset_of.rs b/vendor/memoffset/src/offset_of.rs index 2ffb79c17a..a363d303e9 100644 --- a/vendor/memoffset/src/offset_of.rs +++ b/vendor/memoffset/src/offset_of.rs @@ -30,7 +30,7 @@ macro_rules! _memoffset__let_base_ptr { // so it has to be in the same scope as `$name`. That's why // `let_base_ptr` declares a variable (several, actually) // instead of returning one. - let uninit = $crate::mem::MaybeUninit::<$type>::uninit(); + let uninit = $crate::__priv::mem::MaybeUninit::<$type>::uninit(); let $name: *const $type = uninit.as_ptr(); }; } @@ -41,7 +41,7 @@ macro_rules! _memoffset__let_base_ptr { ($name:ident, $type:ty) => { // No UB right here, but we will later dereference this pointer to // offset into a field, and that is UB because the pointer is dangling. - let $name = $crate::mem::align_of::<$type>() as *const $type; + let $name = $crate::__priv::mem::align_of::<$type>() as *const $type; }; } @@ -49,17 +49,19 @@ macro_rules! _memoffset__let_base_ptr { #[cfg(feature = "unstable_const")] #[macro_export] #[doc(hidden)] -macro_rules! _memoffset_offset_from { - ($field:expr, $base:expr) => { +macro_rules! _memoffset_offset_from_unsafe { + ($field:expr, $base:expr) => {{ + let field = $field; // evaluate $field outside the `unsafe` block + let base = $base; // evaluate $base outside the `unsafe` block // Compute offset, with unstable `offset_from` for const-compatibility. // (Requires the pointers to not dangle, but we already need that for `raw_field!` anyway.) - unsafe { ($field as *const u8).offset_from($base as *const u8) as usize } - }; + unsafe { (field as *const u8).offset_from(base as *const u8) as usize } + }}; } #[cfg(not(feature = "unstable_const"))] #[macro_export] #[doc(hidden)] -macro_rules! _memoffset_offset_from { +macro_rules! _memoffset_offset_from_unsafe { ($field:expr, $base:expr) => { // Compute offset. ($field as usize) - ($base as usize) @@ -93,7 +95,7 @@ macro_rules! offset_of { // Get field pointer. let field_ptr = raw_field!(base_ptr, $parent, $field); // Compute offset. - _memoffset_offset_from!(field_ptr, base_ptr) + _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } @@ -117,7 +119,7 @@ macro_rules! offset_of_tuple { // Get field pointer. let field_ptr = raw_field_tuple!(base_ptr, $parent, $field); // Compute offset. - _memoffset_offset_from!(field_ptr, base_ptr) + _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } diff --git a/vendor/memoffset/src/raw_field.rs b/vendor/memoffset/src/raw_field.rs index 16d01bb68d..a8dd2b3594 100644 --- a/vendor/memoffset/src/raw_field.rs +++ b/vendor/memoffset/src/raw_field.rs @@ -18,22 +18,22 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -/// `raw_const!`, or just ref-then-cast when that is not available. -#[cfg(feature = "unstable_raw")] +/// `addr_of!`, or just ref-then-cast when that is not available. +#[cfg(raw_ref_macros)] #[macro_export] #[doc(hidden)] -macro_rules! _memoffset__raw_const { +macro_rules! _memoffset__addr_of { ($path:expr) => {{ - $crate::ptr::raw_const!($path) + $crate::__priv::ptr::addr_of!($path) }}; } -#[cfg(not(feature = "unstable_raw"))] +#[cfg(not(raw_ref_macros))] #[macro_export] #[doc(hidden)] -macro_rules! _memoffset__raw_const { +macro_rules! _memoffset__addr_of { ($path:expr) => {{ // This is UB because we create an intermediate reference to uninitialized memory. - // Nothing we can do about that without `raw_const!` though. + // Nothing we can do about that without `addr_of!` though. &$path as *const _ }}; } @@ -82,13 +82,14 @@ macro_rules! _memoffset__field_check_tuple { macro_rules! raw_field { ($base:expr, $parent:path, $field:tt) => {{ _memoffset__field_check!($parent, $field); + let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { - _memoffset__raw_const!((*($base as *const $parent)).$field) + _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } @@ -103,13 +104,14 @@ macro_rules! raw_field { macro_rules! raw_field_tuple { ($base:expr, $parent:ty, $field:tt) => {{ _memoffset__field_check_tuple!($parent, $field); + let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { - _memoffset__raw_const!((*($base as *const $parent)).$field) + _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } diff --git a/vendor/memoffset/src/span_of.rs b/vendor/memoffset/src/span_of.rs index 0592dbd11a..fe69e1e94b 100644 --- a/vendor/memoffset/src/span_of.rs +++ b/vendor/memoffset/src/span_of.rs @@ -95,23 +95,21 @@ macro_rules! span_of { }; // No explicit begin for range. (@helper $root:ident, $parent:path, [] ..) => {{ - // UB due to taking references to uninitialized fields for `size_of_val`. ($root as usize, - $root as usize + $crate::mem::size_of_val(&(*$root))) + $root as usize + $crate::__priv::size_of_pointee($root)) }}; - (@helper $root:ident, $parent:path, [] ..= $field:tt) => {{ - // UB due to taking references to uninitialized fields for `size_of_val`. - ($root as usize, - raw_field!($root, $parent, $field) as usize + $crate::mem::size_of_val(&(*$root).$field)) + (@helper $root:ident, $parent:path, [] ..= $end:tt) => {{ + let end = raw_field!($root, $parent, $end); + ($root as usize, end as usize + $crate::__priv::size_of_pointee(end)) }}; - (@helper $root:ident, $parent:path, [] .. $field:tt) => {{ - ($root as usize, raw_field!($root, $parent, $field) as usize) + (@helper $root:ident, $parent:path, [] .. $end:tt) => {{ + ($root as usize, raw_field!($root, $parent, $end) as usize) }}; // Explicit begin and end for range. (@helper $root:ident, $parent:path, # $begin:tt [] ..= $end:tt) => {{ - // UB due to taking references to uninitialized fields for `size_of_val`. - (raw_field!($root, $parent, $begin) as usize, - raw_field!($root, $parent, $end) as usize + $crate::mem::size_of_val(&(*$root).$end)) + let begin = raw_field!($root, $parent, $begin); + let end = raw_field!($root, $parent, $end); + (begin as usize, end as usize + $crate::__priv::size_of_pointee(end)) }}; (@helper $root:ident, $parent:path, # $begin:tt [] .. $end:tt) => {{ (raw_field!($root, $parent, $begin) as usize, @@ -119,19 +117,17 @@ macro_rules! span_of { }}; // No explicit end for range. (@helper $root:ident, $parent:path, # $begin:tt [] ..) => {{ - // UB due to taking references to uninitialized fields for `size_of_val`. (raw_field!($root, $parent, $begin) as usize, - $root as usize + $crate::mem::size_of_val(&*$root)) + $root as usize + $crate::__priv::size_of_pointee($root)) }}; (@helper $root:ident, $parent:path, # $begin:tt [] ..=) => {{ _memoffset__compile_error!( "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?") }}; // Just one field. - (@helper $root:ident, $parent:path, # $begin:tt []) => {{ - // UB due to taking references to uninitialized fields for `size_of_val`. - (raw_field!($root, $parent, $begin) as usize, - raw_field!($root, $parent, $begin) as usize + $crate::mem::size_of_val(&(*$root).$begin)) + (@helper $root:ident, $parent:path, # $field:tt []) => {{ + let field = raw_field!($root, $parent, $field); + (field as usize, field as usize + $crate::__priv::size_of_pointee(field)) }}; // Parsing. (@helper $root:ident, $parent:path, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {{ @@ -143,13 +139,11 @@ macro_rules! span_of { // Entry point. ($sty:path, $($exp:tt)+) => ({ - unsafe { - // Get a base pointer. - _memoffset__let_base_ptr!(root, $sty); - let base = root as usize; - let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*); - begin-base..end-base - } + // Get a base pointer. + _memoffset__let_base_ptr!(root, $sty); + let base = root as usize; + let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*); + begin-base..end-base }); } diff --git a/vendor/miow/.cargo-checksum.json b/vendor/miow/.cargo-checksum.json index 8b333c1784..1b3575ee7e 100644 --- a/vendor/miow/.cargo-checksum.json +++ b/vendor/miow/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"0fe59ead1468db233456bb3f46436c5a62bcc85ce89258a3de706ba9ae17afcf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3ea75d353de268b9dbec44e2e9f56c12cd391579ec4ac5855a4eb68dea216ef2","appveyor.yml":"ffdfb9572a6362866bea6787a726b0d4e43f6bb6516f3a38ebdd561859531602","src/handle.rs":"683af650dcd2975e066891bcd570454e14958f9fb291e0d6ee1d563d2ac1e4ce","src/iocp.rs":"7d11b2269ec05288f0ad693142186f90da60a11dcda264aca3f4ff2f2f78fc57","src/lib.rs":"88aac05a61313b02cf69653392d70c725a805477cb897416d31a02ce7b26d1f1","src/net.rs":"dbb48873bed9921ebbd5227cce9e853d711719972503608d9892da90435881c9","src/overlapped.rs":"90c65c36dbeb95fb1b402b06e97f957c01be2ebb9d43b612bd735ca6e60d3c14","src/pipe.rs":"2a205f04302c3209ba90e6336635525f2fd3ceecad2687f7321a1b2c0188427b"},"package":"5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"} \ No newline at end of file +{"files":{"CHANGELOG.md":"588aa2a1146d5f0a0fe15b633a07b047f0dd333c8beb6fd9eb959a7493f3fdbc","Cargo.toml":"4ef0d55cf903edac87248410e260dfb8fef8fe19322e2917053a1fd757448876","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3ea75d353de268b9dbec44e2e9f56c12cd391579ec4ac5855a4eb68dea216ef2","appveyor.yml":"ffdfb9572a6362866bea6787a726b0d4e43f6bb6516f3a38ebdd561859531602","src/handle.rs":"683af650dcd2975e066891bcd570454e14958f9fb291e0d6ee1d563d2ac1e4ce","src/iocp.rs":"7d11b2269ec05288f0ad693142186f90da60a11dcda264aca3f4ff2f2f78fc57","src/lib.rs":"816e6b1806daa5bf6c354829b974f3ec8bf021fa82e1dd11ef8a4030d6868163","src/net.rs":"a3477bf3f4da11dd062d2f1a482588c9f85d7c9218554516a6a0d64aba66bc03","src/overlapped.rs":"90c65c36dbeb95fb1b402b06e97f957c01be2ebb9d43b612bd735ca6e60d3c14","src/pipe.rs":"ee1aecf7114919cec801465a9ce355b18a5cfddeb9cde3a7ad3153ebe717675d"},"package":"b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"} \ No newline at end of file diff --git a/vendor/miow/CHANGELOG.md b/vendor/miow/CHANGELOG.md new file mode 100644 index 0000000000..e16937d5e1 --- /dev/null +++ b/vendor/miow/CHANGELOG.md @@ -0,0 +1,5 @@ + +## [v0.3.7] - 2021-03-22 +### Changed +- Upgrade `rand` dev-dependency from 0.4 -> 0.8 +- Upgrade `socket2` dependency from 0.3 to 0.4 and make it a dev-dependency diff --git a/vendor/miow/Cargo.toml b/vendor/miow/Cargo.toml index b0b39494b1..c32cc3cc40 100644 --- a/vendor/miow/Cargo.toml +++ b/vendor/miow/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "miow" -version = "0.3.6" +version = "0.3.7" authors = ["Alex Crichton "] description = "A zero overhead I/O library for Windows, focusing on IOCP and Async I/O\nabstractions.\n" homepage = "https://github.com/yoshuawuyts/miow" @@ -25,11 +25,11 @@ repository = "https://github.com/yoshuawuyts/miow" [package.metadata.docs.rs] default-target = "x86_64-pc-windows-msvc" targets = ["aarch64-pc-windows-msvc", "i686-pc-windows-msvc", "x86_64-pc-windows-msvc"] -[dependencies.socket2] -version = "0.3.16" - [dependencies.winapi] version = "0.3.3" features = ["std", "fileapi", "handleapi", "ioapiset", "minwindef", "namedpipeapi", "ntdef", "synchapi", "winerror", "winsock2", "ws2def", "ws2ipdef"] [dev-dependencies.rand] -version = "0.4" +version = "0.8.0" + +[dev-dependencies.socket2] +version = "0.4.0" diff --git a/vendor/miow/src/lib.rs b/vendor/miow/src/lib.rs index e1139a3f4f..53c01aeeae 100644 --- a/vendor/miow/src/lib.rs +++ b/vendor/miow/src/lib.rs @@ -5,12 +5,6 @@ #![allow(bad_style)] #![doc(html_root_url = "https://docs.rs/miow/0.3/x86_64-pc-windows-msvc/")] -extern crate socket2; -extern crate winapi; - -#[cfg(test)] -extern crate rand; - use std::cmp; use std::io; use std::time::Duration; diff --git a/vendor/miow/src/net.rs b/vendor/miow/src/net.rs index def109c0a4..e30bc2d2bf 100644 --- a/vendor/miow/src/net.rs +++ b/vendor/miow/src/net.rs @@ -1108,13 +1108,10 @@ mod tests { }); let cp = t!(CompletionPort::new(1)); - let domain = match addr { - SocketAddr::V4(..) => Domain::ipv4(), - SocketAddr::V6(..) => Domain::ipv6(), - }; - let socket = t!(Socket::new(domain, Type::stream(), None)); + let domain = Domain::for_address(addr); + let socket = t!(Socket::new(domain, Type::STREAM, None)); t!(socket.bind(&addr_template.into())); - let socket = socket.into_tcp_stream(); + let socket = TcpStream::from(socket); t!(cp.add_socket(1, &socket)); let a = Overlapped::zero(); @@ -1268,11 +1265,8 @@ mod tests { }); let cp = t!(CompletionPort::new(1)); - let domain = match addr { - SocketAddr::V4(..) => Domain::ipv4(), - SocketAddr::V6(..) => Domain::ipv6(), - }; - let socket = t!(Socket::new(domain, Type::stream(), None)).into_tcp_stream(); + let domain = Domain::for_address(addr); + let socket = TcpStream::from(t!(Socket::new(domain, Type::STREAM, None))); t!(cp.add_socket(1, &l)); let a = Overlapped::zero(); diff --git a/vendor/miow/src/pipe.rs b/vendor/miow/src/pipe.rs index 6192dd250e..5088021a86 100644 --- a/vendor/miow/src/pipe.rs +++ b/vendor/miow/src/pipe.rs @@ -569,14 +569,18 @@ mod tests { use std::thread; use std::time::Duration; - use rand::{thread_rng, Rng}; + use rand::{distributions::Alphanumeric, thread_rng, Rng}; use super::{anonymous, NamedPipe, NamedPipeBuilder}; use crate::iocp::CompletionPort; use crate::Overlapped; fn name() -> String { - let name = thread_rng().gen_ascii_chars().take(30).collect::(); + let name = thread_rng() + .sample_iter(Alphanumeric) + .take(30) + .map(char::from) + .collect::(); format!(r"\\.\pipe\{}", name) } diff --git a/vendor/packed_simd/.cargo-checksum.json b/vendor/packed_simd/.cargo-checksum.json deleted file mode 100644 index 490b1f06b2..0000000000 --- a/vendor/packed_simd/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"0015448819f4af9ef6bb3b24428a2ed5d014c7aecdcd15015f231f268aa41e2c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","bors.toml":"dee881dc69b9b7834e4eba5d95c3ed5a416d4628815a167d6a22d4cb4fb064b8","build.rs":"eb12357e953205b699ea2fd355a777af25de76ac0181cce40d3fce43547fb161","ci/all.sh":"6f1d5d9c19093c385c58f9fbccd3579e423e1abc7142387fed1f9afc226a3ea6","ci/android-install-ndk.sh":"0f1746108cc30bf9b9ba45bcde7b19fc1a8bdf5b0258035b4eb8dc69b75efac4","ci/android-install-sdk.sh":"3490432022c5c8f5a115c084f7a9aca1626f96c0c87ffb62019228c4346b47e4","ci/android-sysimage.sh":"ebf4e5daa1f0fe1b2092b79f0f3f161c4c4275cb744e52352c4d81ab451e4c5a","ci/benchmark.sh":"b61d19ef6b90deba8fb79dee74c8b062d94844676293da346da87bb78a9a49a4","ci/deploy_and_run_on_ios_simulator.rs":"ec8ecf82d92072676aa47f0d1a3d021b60a7ae3531153ef12d2ff4541fc294dc","ci/docker/aarch64-linux-android/Dockerfile":"ace2e7d33c87bc0f6d3962a4a3408c04557646f7f51ab99cfbf574906796b016","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"1ecdac757101d951794fb2ab0deaa278199cf25f2e08a15c7d40ff31a8556184","ci/docker/arm-linux-androideabi/Dockerfile":"370e55d3330a413a3ccf677b3afb3e0ef9018a5fab263faa97ae8ac017fc2286","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"e25d88f6c0c94aada3d2e3f08243f755feb7e869dc5dc505b3799719cb1af591","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"f126f4c7bae8c11ab8b16df06ad997863f0838825a9c08c9899a3eedb6d570bd","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"b647545c158ee480a4c581dbdc1f57833aef056c8d498acc04b573e842bf803c","ci/docker/i586-unknown-linux-gnu/Dockerfile":"0d492759017307ccf74dc2aa4a8cf6623daf3dc728c708dc2b18fa7940800cba","ci/docker/i686-unknown-linux-gnu/Dockerfile":"0d492759017307ccf74dc2aa4a8cf6623daf3dc728c708dc2b18fa7940800cba","ci/docker/mips-unknown-linux-gnu/Dockerfile":"323776469bb7b160385f3621d66e3ee14c75242f8180f916e65af048a29d4ea0","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"c647f6948a9a43b0be695cbed4eac752120d0faf28e5e69c718cb10406921dab","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"77bfd00cc8639509be381b394f077e39b45a00158ad61b4e1656714c714665d1","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"ec5bea6c98a3b626731fdb95f9ff2d1182639c76e8fb16d3271d0fc884901524","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"4f2b662de66e83d1354f650b7077692309637f786c2ea5516c31b5c2ee10af2d","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"a9595402b772bc365982e22a0096a8988825d90b09b5faa97ab192e76072f71d","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"df3c381c157439695ae8cd10ab71664702c061e3b4ab22906a5ad6c2680acfed","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"93fb44df3d7fd31ead158570667c97b5076a05c3d968af4a84bc13819a8f2db8","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"da1c39a3ff1fe22e41395fa7c8934e90b4c1788e551b9aec6e38bfd94effc437","ci/docker/thumbv7neon-linux-androideabi/Dockerfile":"c2decd5591bd7a09378901bef629cd944acf052eb55e4f35b79eb9cb4d62246a","ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile":"75c0c56161c7382b439de74c00de1c0e3dc9d59560cd6720976a751034b78714","ci/docker/wasm32-unknown-unknown/Dockerfile":"3e5f294bc1e004aa599086c2af49d6f3e7459fa250f5fbdd60cf67d53db78758","ci/docker/x86_64-linux-android/Dockerfile":"685040273cf350d5509e580ac451555efa19790c8723ca2af066adadc6880ad2","ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile":"44b6203d9290bfdc53d81219f0937e1110847a23dd982ec8c4de388354f01536","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"d253c86803b22da428fa9cc671a05f18d3318eca7733b8dccb4f7be1ddf524c5","ci/dox.sh":"5b61711be47a4e3dde0ddd15ba73d256ea95fd75af3897732c24db1dc7e66366","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab7ad3b7a344833ee726aba6b647cf5952e56f0ad1ba420b13325","ci/lld-shim.rs":"3d7f71ec23a49e2b67f694a0168786f9a954dda15f5a138815d966643fd3fcc3","ci/max_line_width.sh":"0a1518bba4c9ecaa55694cb2e9930d0e19c265baabf73143f17f9cf285aaa5bb","ci/run-docker.sh":"92e036390ad9b0d16f109579df1b5ced2e72e9afea40c7d011400ebd3a2a90de","ci/run.sh":"63259e22a96ba539f53c06b1b39f53e3a78a71171652e7afc170836110ccd913","ci/run_examples.sh":"d1a23c6c35374a0678ba5114b9b8fefd8be0a79e774872a8bf0898d1baca18d0","ci/runtest-android.rs":"145a8e9799a5223975061fe7e586ade5669ee4877a7d7a4cf6b4ab48e8e36c7c","ci/setup_benchmarks.sh":"73fb981a8fdb1dcd54409d3c0fbbfb8f77a3ceabf8626a6b9bf9d21d6bc8ce72","ci/test-runner-linux":"c8aa6025cff5306f4f31d0c61dc5f9d4dd5a1d189ab613ef8d4c367c694d9ccd","contributing.md":"2cc8c9c560ae17867e69b06d09b758dbf7bc39eb774ada50a743724b10acc0a2","perf-guide/book.toml":"115a98284126c6b180178b44713314cc494f08a71662ee2ce15cf67f17a51064","perf-guide/src/SUMMARY.md":"3e03bffc991fdc2050f3d51842d72d9d21ea6abab56a3baf3b2d5973a78b89e1","perf-guide/src/ascii.css":"29afb08833b2fe2250f0412e1fa1161a2432a0820a14953c87124407417c741a","perf-guide/src/bound_checks.md":"5e4991ff58a183ef0cd9fdc1feb4cd12d083b44bdf87393bbb0927808ef3ce7d","perf-guide/src/float-math/approx.md":"8c09032fa2d795a0c5db1775826c850d28eb2627846d0965c60ee72de63735ad","perf-guide/src/float-math/fma.md":"311076ba4b741d604a82e74b83a8d7e8c318fcbd7f64c4392d1cf5af95c60243","perf-guide/src/float-math/fp.md":"04153e775ab6e4f0d7837bcc515230d327b04edfa34c84ce9c9e10ebaeef2be8","perf-guide/src/float-math/svml.md":"0798873b8eedaeda5fed62dc91645b57c20775a02d3cd74d8bd06958f1516506","perf-guide/src/introduction.md":"9f5a19e9e6751f25d2daad39891a0cc600974527ec4c8305843f9618910671bd","perf-guide/src/prof/linux.md":"447731eb5de7d69166728fdbc5ecb0c0c9db678ea493b45a592d67dd002184c0","perf-guide/src/prof/mca.md":"f56d54f3d20e7aa4d32052186e8237b03d65971eb5d112802b442570ff11d344","perf-guide/src/prof/profiling.md":"8a650c0fd6ede0964789bb6577557eeef1d8226a896788602ce61528e260e43c","perf-guide/src/target-feature/attribute.md":"615f88dca0a707b6c416fa605435dd6e1fb5361cc639429cbf68cd87624bd78b","perf-guide/src/target-feature/features.md":"17077760ff24c006b606dd21889c53d87228f4311f3ba3a574f9afdeacd86165","perf-guide/src/target-feature/inlining.md":"7ed1d7068d8173a00d84c16cfe5871cd68b9f04f8d0cca2d01ebc84957ebf2f6","perf-guide/src/target-feature/practice.md":"c4b371842e0086df178488fec97f20def8f0c62ee588bcd25fd948b9b1fa227e","perf-guide/src/target-feature/runtime.md":"835425f5ee597fb3e51d36e725a81ebee29f4561231d19563cd4da81dbb1cfcb","perf-guide/src/target-feature/rustflags.md":"ab49712e9293a65d74d540ba4784fcb57ff1119ec05a575d895c071f1a620f64","perf-guide/src/vert-hor-ops.md":"c6211c0ee91e60552ec592d89d9d957eedc21dee3cbd89e1ad6765ea06a27471","readme.md":"c0cfbcb55a21d5707dbca61c38adcfe77fd276541328399d2477695537ebae3b","rust-toolchain":"2a3b62b53ddb9f167b63d22202a360811ba78df015021f704d01ee9abad4169c","rustfmt.toml":"de6101d0670bad65fb3b337d56957d2a024e017e5ab146ec784d77312daaf8ff","src/api.rs":"f6e92f056565e6fd93f98829a408aee9e790251e0cbd8a8bc30c8662b4d6fabb","src/api/bit_manip.rs":"e68290ee679cc5abc9c73afbe635c1035f8cbfe849e5c751a1680e459244c39e","src/api/bitmask.rs":"6d2beefd62ee5d9c8eb060bee6abc641616bf828c99f82abf97b21bf004e894b","src/api/cast.rs":"b37e872e1b344544ebc30405fc214eaa4861f1711546e63c06ab7ec7b5c6597e","src/api/cast/macros.rs":"b0a14d0c83ad2ebb7a275180f6d9e3f2bc312ba57a7d3d6c39fad4e0f20f9408","src/api/cast/v128.rs":"63e28c6a3edf1a7a635f51b8d3c6adbb1d46f884d92a196b3d4a6e743d809416","src/api/cast/v16.rs":"2a584eeb57fd47baad6f3533764301b04aaaac23702b7a8db12598ac02899262","src/api/cast/v256.rs":"b91c15ed8d1536ecd97b4eb79ff9d5aba0552cd9b6f0ea6435b05f2273e23b3a","src/api/cast/v32.rs":"62ec89fcce7fa7f28497ee5770adc8f81d2d3a6b2925b02f7dc06504c40e8f38","src/api/cast/v512.rs":"d855cb943ae7106e9599ef38e30a3afb1c6bd5433178baca54cb128fd9a7d143","src/api/cast/v64.rs":"fe0f7dfaf4fc0c0c1a78c96fcfcdfdc2a1e2845843b11aa797a0c6fb52a8f774","src/api/cmp.rs":"357c3a2a09c6d4611c32dd7fa95be2fae933d513e229026ec9b44451a77b884e","src/api/cmp/eq.rs":"60f70f355bae4cb5b17db53204cacc3890f70670611c17df638d4c04f7cc8075","src/api/cmp/ord.rs":"589f7234761c294fa5df8f525bc4acd5a47cdb602207d524a0d4e19804cd9695","src/api/cmp/partial_eq.rs":"b574d95fca8c2e3da1dd88085a7c501fad798aa63a65be8536405cf97eb23e5f","src/api/cmp/partial_ord.rs":"e16b11805c94048acd058c93994b5bc74bb187f8d7e3b86a87df60e1601467f9","src/api/cmp/vertical.rs":"de3d62f38eba817299aa16f1e1939954c9a447e316509397465c2830852ba053","src/api/default.rs":"b61f92fc0e33a2633b3375eb405beba480da071cde03df4d437d8a6058afcd97","src/api/fmt.rs":"67fb804bb86b6cd77cf8cd492b5733ce437071b66fe3297278b8a6552c325dda","src/api/fmt/binary.rs":"649fcb1b7d7ca37fe0bf924f70a73864736cf9a2ebb3e935e2a275cc658592bd","src/api/fmt/debug.rs":"41161f979ce5ba09fef3d584cc318d6820761486ed8a6f0e93ab108e0e174bbf","src/api/fmt/lower_hex.rs":"9a0f19774a9083cb3399f63e8d0fed70a1fcf281a149b50364b684a3870b8c7a","src/api/fmt/octal.rs":"5fe82d1a8d2d7aa65078ae2b269ea74ad81650931761e4493394c3292bf85f50","src/api/fmt/upper_hex.rs":"e949cb4a691f77f88f773d7a8a89f5c1ecbd94e005bf964724b10cc123da5a86","src/api/from.rs":"2e599d8329cb05eaf06224cc441355c4b7b51254fc19256619333be8c149d444","src/api/from/from_array.rs":"4151593c7bba7455821fffa5b59867005a77c95d32f1f0cc3fd87294000157d9","src/api/from/from_vector.rs":"9764371aa9e6005aace74dea14f59e5611a095b7cf42707940924749282c52f0","src/api/hash.rs":"562cfa3f1d8eb9a733c035a3665a599c2f1e341ee820d8fbdd102a4398a441bc","src/api/into_bits.rs":"82297f0697d67b5a015e904e7e6e7b2a7066ba825bc54b94b4ff3e22d7a1eefb","src/api/into_bits/arch_specific.rs":"1f925390b0ce7132587d95f2419c6e2ad3e1a9d17eb1d9c120a1c1c4bdf4277e","src/api/into_bits/macros.rs":"d762406de25aedff88d460dec7a80dc8e825a2a419d53218ce007efa6a1d3e04","src/api/into_bits/v128.rs":"ecdc5893664c71d7ab1ff3697c3fbe490d20d8748b9b76881d05e7625e40d74c","src/api/into_bits/v16.rs":"5459ec7dad1ad7bd30dc7e48374580b993abf23701d9c3cb22203fa0a9aabb6d","src/api/into_bits/v256.rs":"90ea351da0380ead1bf0f63b620afd40d01d638d09f7e7be31840bd2c1d9c663","src/api/into_bits/v32.rs":"ee1dc5a430050e16f51154b5fe85b1536f5feddf2ea23dd1d3859b67c4afc6fc","src/api/into_bits/v512.rs":"f72098ed1c9a23944f3d01abaf5e0f2d0e81d35a06fdadd2183e896d41b59867","src/api/into_bits/v64.rs":"6394462facdfe7827349c742b7801f1291e75a720dfb8c0b52100df46f371c98","src/api/math.rs":"8b2a2fc651917a850539f993aa0b9e5bf4da67b11685285b8de8cdca311719ec","src/api/math/float.rs":"61d2794d68262a1090ae473bd30793b5f65cf732f32a6694a3af2ce5d9225616","src/api/math/float/abs.rs":"5b6b2701e2e11135b7ce58a05052ea8120e10e4702c95d046b9d21b827b26bf8","src/api/math/float/consts.rs":"78acba000d3fa527111300b6327c1932de9c4c1e02d4174e1a5615c01463d38c","src/api/math/float/cos.rs":"4c2dd7173728ef189314f1576c9486e03be21b7da98843b2f9011282a7979e31","src/api/math/float/exp.rs":"7c6d5f1e304f498a01cfa23b92380c815d7da0ad94eae3483783bc377d287eef","src/api/math/float/ln.rs":"54c7583f3df793b39ff57534fade27b41bb992439e5dc178252f5ca3190a3e54","src/api/math/float/mul_add.rs":"62cac77660d20159276d4c9ef066eb90c81cbddb808e8e157182c607625ad2eb","src/api/math/float/mul_adde.rs":"bae056ee9f3a70df39ec3c3b2f6437c65303888a7b843ef1a5bcf1f5aca0e602","src/api/math/float/powf.rs":"9ddb938984b36d39d82a82f862f80df8f7fb013f1d222d45698d41d88472f568","src/api/math/float/recpre.rs":"589225794ff1dbf31158dff660e6d4509ecc8befbb57c633900dea5ac0b840d6","src/api/math/float/rsqrte.rs":"a32abdcc318d7ccc8448231f54d75b884b7cbeb03a7d595713ab6243036f4dbf","src/api/math/float/sin.rs":"cbd3622b7df74f19691743001c8cf747a201f8977ad90542fee915f37dcd1e49","src/api/math/float/sqrt.rs":"0c66d5d63fb08e4d99c6b82a8828e41173aff1ac9fa1a2764a11fac217ccf2ac","src/api/math/float/sqrte.rs":"731e1c9f321b662accdd27dacb3aac2e8043b7aecb2f2161dde733bd9f025362","src/api/minimal.rs":"1f22bcc528555444e76de569ec0ae2029b9ae9d04805efeafa93369c8098036b","src/api/minimal/iuf.rs":"c38667a77b72f71b6be3fbb5d5f3690278223f58bc5fb83222f8a8e03d5f78f9","src/api/minimal/mask.rs":"75ecde186b47ba12c3bd4cf50fc6763f66fa81ef2450d9ce8cd0f63f7f94ae30","src/api/minimal/ptr.rs":"3f4affc618a08fde8fe2f86486045d3b993d845f2b28af5e4a902f1614e745a2","src/api/ops.rs":"3e273b277a0f3019d42c3c59ca94a5afd4885d5ae6d2182e5089bbeec9de42ee","src/api/ops/scalar_arithmetic.rs":"d2d5ad897a59dd0787544f927e0e7ca4072c3e58b0f4a2324083312b0d5a21d7","src/api/ops/scalar_bitwise.rs":"482204e459ca6be79568e1c9f70adbe2d2151412ddf122fb2161be8ebb51c40c","src/api/ops/scalar_mask_bitwise.rs":"c250f52042e37b22d57256c80d4604104cfd2fbe2a2e127c676267270ca5d350","src/api/ops/scalar_shifts.rs":"987f8fdebeedc16e3d77c1b732e7826ef70633c541d16dfa290845d5c6289150","src/api/ops/vector_arithmetic.rs":"ddca15d09ddeef502c2ed66117a62300ca65d87e959e8b622d767bdf1c307910","src/api/ops/vector_bitwise.rs":"b3968f7005b649edcc22a54e2379b14d5ee19045f2e784029805781ae043b5ee","src/api/ops/vector_float_min_max.rs":"f5155dce75219f4ba11275b1f295d2fdcddd49d174a6f1fb2ace7ea42813ce41","src/api/ops/vector_int_min_max.rs":"a378789c6ff9b32a51fbd0a97ffd36ed102cd1fe6a067d2b02017c1df342def6","src/api/ops/vector_mask_bitwise.rs":"5052d18517d765415d40327e6e8e55a312daaca0a5e2aec959bfa54b1675f9c8","src/api/ops/vector_neg.rs":"5c62f6b0221983cdbd23cd0a3af3672e6ba1255f0dfe8b19aae6fbd6503e231b","src/api/ops/vector_rotates.rs":"03cbe8a400fd7c688e4ee771a990a6754f2031b1a59b19ae81158b21471167e5","src/api/ops/vector_shifts.rs":"9bf69d0087268f61009e39aea52e03a90f378910206b6a28e8393178b6a5d0e0","src/api/ptr.rs":"8a793251bed6130dcfb2f1519ceaa18b751bbb15875928d0fb6deb5a5e07523a","src/api/ptr/gather_scatter.rs":"9ddd960365e050674b25b2fd3116e24d94669b4375d74e71c03e3f1469576066","src/api/reductions.rs":"ae5baca81352ecd44526d6c30c0a1feeda475ec73ddd3c3ec6b14e944e5448ee","src/api/reductions/bitwise.rs":"8bf910ae226188bd15fc7e125f058cd2566b6186fcd0cd8fd020f352c39ce139","src/api/reductions/float_arithmetic.rs":"e58c8c87806a95df2b2b5b48ac5991036df024096d9d7c171a480fe9282896a4","src/api/reductions/integer_arithmetic.rs":"47471da1c5f859489680bb5d34ced3d3aa20081c16053a3af121a4496fcb57bf","src/api/reductions/mask.rs":"fcc21a0301545212d61800da65684a4ef1cb4fcc8671ee2effc30fa3e93760f7","src/api/reductions/min_max.rs":"f27be3aa28e1c1f46de7890198db6e12f00c207085e89ef2de7e57ee443cdb98","src/api/select.rs":"a98e2ccf9fc6bdeed32d337c8675bc96c2fbe2cc34fbf149ad6047fb8e749774","src/api/shuffle.rs":"da58200790868c09659819322a489929a5b6e56c596ed07e6a44293ea02e7d09","src/api/shuffle1_dyn.rs":"bfea5a91905b31444e9ef7ca6eddb7a9606b7e22d3f71bb842eb2795a0346620","src/api/slice.rs":"ee87484e8af329547b9a5d4f2a69e8bed6ea10bbd96270d706083843d4eea2ac","src/api/slice/from_slice.rs":"619deaf6d01c53c2ae3817a7b8ab592dceecd425b0959890a3a87fec2dcaba48","src/api/slice/write_to_slice.rs":"2bf74f490fdf0ae8d23af442a0411fe91c57c6e824368ca378f3cd9b20504d31","src/api/swap_bytes.rs":"4a6792a2e49a77475e1b237592b4b2804dbddb79c474331acd0dd71b36934259","src/codegen.rs":"c6eebc3d3665420aa6a2f317977e3c41a4f43e0550ac630cdbe8e4bbed5e2031","src/codegen/bit_manip.rs":"5559e095105a80003e0de35af1d19b0c65c9ab04eb743c7e01c5442d882eb34e","src/codegen/llvm.rs":"6cc1962f434e68d13049d37a095f0723518cefaae6abdd4cd29d0bf57006e43a","src/codegen/math.rs":"35f96e37a78fcf0cdb02146b7f27a45108fe06a37fc2a54d8851ce131a326178","src/codegen/math/float.rs":"fb6e74d65c3b50cabcd77c5f83ab19eaca7e17883193e61ad9c26e01a3a76a1a","src/codegen/math/float/abs.rs":"f56e2b4b8055ea861c1f5cbc6b6e1d8e7e5af163b62c13574ddee4e09513bfbc","src/codegen/math/float/cos.rs":"ef3b511a24d23045b310315e80348a9b7fedb576fc2de52d74290616a0abeb2a","src/codegen/math/float/cos_pi.rs":"4e7631a5d73dac21531e09ef1802d1180f8997509c2c8fa9f67f322194263a97","src/codegen/math/float/exp.rs":"61b691598c41b5622f24e4320c1bdd08701e612a516438bdddcc728fc3405c8c","src/codegen/math/float/ln.rs":"46b718b1ba8c9d99e1ad40f53d20dfde08a3063ca7bd2a9fdd6698e060da687e","src/codegen/math/float/macros.rs":"dd42135fff13f9aca4fd3a1a4e14c7e6c31aadc6d817d63b0d2fb9e62e062744","src/codegen/math/float/mul_add.rs":"a37bf764345d4b1714f97e83897b7cf0855fc2811704bcbc0012db91825339e1","src/codegen/math/float/mul_adde.rs":"c75702bfcb361de45964a93caf959a695ef2376bd069227600b8c6872665c755","src/codegen/math/float/powf.rs":"642346e982bc4c39203de0864d2149c4179cd7b21cf67a2951687932b4675872","src/codegen/math/float/sin.rs":"9d68164c90cdca6a85155040cdac42e27342ebe0b925273ef1593df721af4258","src/codegen/math/float/sin_cos_pi.rs":"9be02ad48585a1e8d99129382fbffbaed47852f15459256a708850b6b7a75405","src/codegen/math/float/sin_pi.rs":"9890347905b4d4a3c7341c3eb06406e46e60582bcf6960688bd727e5dadc6c57","src/codegen/math/float/sqrt.rs":"e3c60dcfb0c6d2fc62adabcc931b2d4040b83cab294dea36443fb4b89eb79e34","src/codegen/math/float/sqrte.rs":"f0f4ef9eb475ae41bcc7ec6a95ad744ba6b36925faa8b2c2814004396d196b63","src/codegen/pointer_sized_int.rs":"a70697169c28218b56fd2e8d5353f2e00671d1150d0c8cef77d613bdfacd84cb","src/codegen/reductions.rs":"645e2514746d01387ddd07f0aa4ffd8430cc9ab428d4fb13773ea319fa25dd95","src/codegen/reductions/mask.rs":"8f1afe6aabf096a3278e1fc3a30f736e04aa8b9ce96373cee22162d18cfe2702","src/codegen/reductions/mask/aarch64.rs":"cba6e17603d39795dcfe8339b6b7d8714c3e162a1f0a635979f037aa24fe4206","src/codegen/reductions/mask/arm.rs":"9447904818aa2c7c25d0963eead452a639a11ca7dbd6d21eedbfcaade07a0f33","src/codegen/reductions/mask/fallback.rs":"7a0ef9f7fd03ae318b495b95e121350cd61caffc5cc6ee17fabf130d5d933453","src/codegen/reductions/mask/fallback_impl.rs":"76547f396e55ef403327c77c314cf8db8c7a5c9b9819bfb925abeacf130249e5","src/codegen/reductions/mask/x86.rs":"14bd2c482071f2355beebcf7b7ecf950ff2dfcdb08c3ca50993092434a9de717","src/codegen/reductions/mask/x86/avx.rs":"b4913d87844c522903641cbbf10db4551addb1ce5e9e78278e21612fa65c733b","src/codegen/reductions/mask/x86/avx2.rs":"677aed3f056285285daa3adff8bc65e739630b4424defa6d9665e160f027507e","src/codegen/reductions/mask/x86/sse.rs":"226610b4ff88c676d5187114dd57b4a8800de6ce40884675e9198445b1ed0306","src/codegen/reductions/mask/x86/sse2.rs":"bc38e6c31cb4b3d62147eba6cac264e519e2a48e0f7ce9010cfa9ef0cf0ec9fd","src/codegen/shuffle.rs":"0abca97e92cdce49a58a39cc447eb09dc7d7715ef256c8dbd2181a186e61bb64","src/codegen/shuffle1_dyn.rs":"04523e9338133bdedb012dd076c2c564b79ce5593b0fc56d0fb6910e04190a81","src/codegen/swap_bytes.rs":"983fa0cc2960e7823e5850fb863db3207caea78709abdca2400cd1cf99f51100","src/codegen/v128.rs":"94226b31ec403d18d9d2fe06713f147c9c79e9b5f9105089088266313f843185","src/codegen/v16.rs":"ddec4ffb66b6f7aaffb9a1780c5ddba82557abd74f45073d335047e04cf74924","src/codegen/v256.rs":"6b63917f0444118d6b1595bff2045e59b97c4d24012bd575f69f1f0efc5a0241","src/codegen/v32.rs":"3477b3c5540aed86e61e2f5807dd31db947413cec9181c587d93ed6ec74f0eba","src/codegen/v512.rs":"5854f99d3aabc4cd42b28a20d9ce447756dc2ba024a409a69b6a8ae1f1842fc5","src/codegen/v64.rs":"e9e89caebfe63d10c0cbca61e4dfdba3b7e02ee0989170f80beed23237ddd950","src/codegen/vPtr.rs":"96d609a9eece4dcbbcc01ba0b8744d7f5958be12774176a2945bc676f4e6b5cb","src/codegen/vSize.rs":"eeee9858749aa82142b27bc120d1989bb74a6b82e1e4efbbeaccc9634dc9acfc","src/lib.rs":"ed6b6ef4a60833a32b6e5d99fdb69a9981174e2451fdb4111731da8734c94308","src/masks.rs":"d99df2d2b16d21560b4e92864a45356e4cc9bcc8c6f54ed90f32ba1e6056498c","src/sealed.rs":"ff7f0324276408ae8249941cfa32c90b8835a54d750896b683efea857af19db2","src/testing.rs":"1d3a7862ef625e235a5734ad7204e68d350f902c0695182b1f08a0552432416e","src/testing/macros.rs":"6378856d7a40ba5ec5c7c0dad6327d79f0c77266921c24296d10aed6c68e9b98","src/testing/utils.rs":"d6fd5a5017f1f85d9d99585754f8f6ad06fc3d683b34083543e67a7cc6c1772c","src/v128.rs":"ad7ab5c22ecda7821da73d20c3cbb9d654e58bec567a0ecd6c4c79be72c55499","src/v16.rs":"cb6465cf1e00bf530183af1819b9fe3d7eec978f8765d5e85d9b58a39a4b4045","src/v256.rs":"f98d395cb1ea16c97ebd2ee6d5b57d11cd3f52ef909e3542f52206f93b556923","src/v32.rs":"145d347855bac59b2de6508f9e594654e6c330423af9edc0e2ac8f4d1abdf45e","src/v512.rs":"0ca5956f0e4b6c36a160ea175e92ebc6d32fd2a91d75f7de0c29b6987d771ffb","src/v64.rs":"308b0298a695b58ff2e3441fa700b215105681576a07c11d49ec2821ad690833","src/vPtr.rs":"c9a53f41f466e17b6648a4ce390fd8f4d3a848d440eb8a9a803a11608d76eb05","src/vSize.rs":"7142f5da3c8099f53634c57329e86d220da40d426803bb7ab6a66fba9653c922","tests/endianness.rs":"541a144be017e3dd7da7c8ea49d907dc02538245e8c5f3deb5bd43da92c929e1"},"package":"a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220"} \ No newline at end of file diff --git a/vendor/packed_simd/src/codegen/shuffle.rs b/vendor/packed_simd/src/codegen/shuffle.rs deleted file mode 100644 index 35a9db9053..0000000000 --- a/vendor/packed_simd/src/codegen/shuffle.rs +++ /dev/null @@ -1,302 +0,0 @@ -//! Implementations of the `ShuffleResult` trait for the different numbers of -//! lanes and vector element types. - -use crate::masks::*; -use crate::sealed::Shuffle; - -impl Shuffle<[u32; 2]> for i8 { - type Output = crate::codegen::i8x2; -} -impl Shuffle<[u32; 4]> for i8 { - type Output = crate::codegen::i8x4; -} -impl Shuffle<[u32; 8]> for i8 { - type Output = crate::codegen::i8x8; -} -impl Shuffle<[u32; 16]> for i8 { - type Output = crate::codegen::i8x16; -} -impl Shuffle<[u32; 32]> for i8 { - type Output = crate::codegen::i8x32; -} -impl Shuffle<[u32; 64]> for i8 { - type Output = crate::codegen::i8x64; -} - -impl Shuffle<[u32; 2]> for u8 { - type Output = crate::codegen::u8x2; -} -impl Shuffle<[u32; 4]> for u8 { - type Output = crate::codegen::u8x4; -} -impl Shuffle<[u32; 8]> for u8 { - type Output = crate::codegen::u8x8; -} -impl Shuffle<[u32; 16]> for u8 { - type Output = crate::codegen::u8x16; -} -impl Shuffle<[u32; 32]> for u8 { - type Output = crate::codegen::u8x32; -} -impl Shuffle<[u32; 64]> for u8 { - type Output = crate::codegen::u8x64; -} - -impl Shuffle<[u32; 2]> for m8 { - type Output = crate::codegen::m8x2; -} -impl Shuffle<[u32; 4]> for m8 { - type Output = crate::codegen::m8x4; -} -impl Shuffle<[u32; 8]> for m8 { - type Output = crate::codegen::m8x8; -} -impl Shuffle<[u32; 16]> for m8 { - type Output = crate::codegen::m8x16; -} -impl Shuffle<[u32; 32]> for m8 { - type Output = crate::codegen::m8x32; -} -impl Shuffle<[u32; 64]> for m8 { - type Output = crate::codegen::m8x64; -} - -impl Shuffle<[u32; 2]> for i16 { - type Output = crate::codegen::i16x2; -} -impl Shuffle<[u32; 4]> for i16 { - type Output = crate::codegen::i16x4; -} -impl Shuffle<[u32; 8]> for i16 { - type Output = crate::codegen::i16x8; -} -impl Shuffle<[u32; 16]> for i16 { - type Output = crate::codegen::i16x16; -} -impl Shuffle<[u32; 32]> for i16 { - type Output = crate::codegen::i16x32; -} - -impl Shuffle<[u32; 2]> for u16 { - type Output = crate::codegen::u16x2; -} -impl Shuffle<[u32; 4]> for u16 { - type Output = crate::codegen::u16x4; -} -impl Shuffle<[u32; 8]> for u16 { - type Output = crate::codegen::u16x8; -} -impl Shuffle<[u32; 16]> for u16 { - type Output = crate::codegen::u16x16; -} -impl Shuffle<[u32; 32]> for u16 { - type Output = crate::codegen::u16x32; -} - -impl Shuffle<[u32; 2]> for m16 { - type Output = crate::codegen::m16x2; -} -impl Shuffle<[u32; 4]> for m16 { - type Output = crate::codegen::m16x4; -} -impl Shuffle<[u32; 8]> for m16 { - type Output = crate::codegen::m16x8; -} -impl Shuffle<[u32; 16]> for m16 { - type Output = crate::codegen::m16x16; -} -impl Shuffle<[u32; 32]> for m16 { - type Output = crate::codegen::m16x32; -} - -impl Shuffle<[u32; 2]> for i32 { - type Output = crate::codegen::i32x2; -} -impl Shuffle<[u32; 4]> for i32 { - type Output = crate::codegen::i32x4; -} -impl Shuffle<[u32; 8]> for i32 { - type Output = crate::codegen::i32x8; -} -impl Shuffle<[u32; 16]> for i32 { - type Output = crate::codegen::i32x16; -} - -impl Shuffle<[u32; 2]> for u32 { - type Output = crate::codegen::u32x2; -} -impl Shuffle<[u32; 4]> for u32 { - type Output = crate::codegen::u32x4; -} -impl Shuffle<[u32; 8]> for u32 { - type Output = crate::codegen::u32x8; -} -impl Shuffle<[u32; 16]> for u32 { - type Output = crate::codegen::u32x16; -} - -impl Shuffle<[u32; 2]> for f32 { - type Output = crate::codegen::f32x2; -} -impl Shuffle<[u32; 4]> for f32 { - type Output = crate::codegen::f32x4; -} -impl Shuffle<[u32; 8]> for f32 { - type Output = crate::codegen::f32x8; -} -impl Shuffle<[u32; 16]> for f32 { - type Output = crate::codegen::f32x16; -} - -impl Shuffle<[u32; 2]> for m32 { - type Output = crate::codegen::m32x2; -} -impl Shuffle<[u32; 4]> for m32 { - type Output = crate::codegen::m32x4; -} -impl Shuffle<[u32; 8]> for m32 { - type Output = crate::codegen::m32x8; -} -impl Shuffle<[u32; 16]> for m32 { - type Output = crate::codegen::m32x16; -} - -/* FIXME: 64-bit single element vector -impl Shuffle<[u32; 1]> for i64 { - type Output = crate::codegen::i64x1; -} -*/ -impl Shuffle<[u32; 2]> for i64 { - type Output = crate::codegen::i64x2; -} -impl Shuffle<[u32; 4]> for i64 { - type Output = crate::codegen::i64x4; -} -impl Shuffle<[u32; 8]> for i64 { - type Output = crate::codegen::i64x8; -} - -/* FIXME: 64-bit single element vector -impl Shuffle<[u32; 1]> for u64 { - type Output = crate::codegen::u64x1; -} -*/ -impl Shuffle<[u32; 2]> for u64 { - type Output = crate::codegen::u64x2; -} -impl Shuffle<[u32; 4]> for u64 { - type Output = crate::codegen::u64x4; -} -impl Shuffle<[u32; 8]> for u64 { - type Output = crate::codegen::u64x8; -} - -/* FIXME: 64-bit single element vector -impl Shuffle<[u32; 1]> for f64 { - type Output = crate::codegen::f64x1; -} -*/ -impl Shuffle<[u32; 2]> for f64 { - type Output = crate::codegen::f64x2; -} -impl Shuffle<[u32; 4]> for f64 { - type Output = crate::codegen::f64x4; -} -impl Shuffle<[u32; 8]> for f64 { - type Output = crate::codegen::f64x8; -} - -/* FIXME: 64-bit single element vector -impl Shuffle<[u32; 1]> for m64 { - type Output = crate::codegen::m64x1; -} -*/ -impl Shuffle<[u32; 2]> for m64 { - type Output = crate::codegen::m64x2; -} -impl Shuffle<[u32; 4]> for m64 { - type Output = crate::codegen::m64x4; -} -impl Shuffle<[u32; 8]> for m64 { - type Output = crate::codegen::m64x8; -} - -impl Shuffle<[u32; 2]> for isize { - type Output = crate::codegen::isizex2; -} -impl Shuffle<[u32; 4]> for isize { - type Output = crate::codegen::isizex4; -} -impl Shuffle<[u32; 8]> for isize { - type Output = crate::codegen::isizex8; -} - -impl Shuffle<[u32; 2]> for usize { - type Output = crate::codegen::usizex2; -} -impl Shuffle<[u32; 4]> for usize { - type Output = crate::codegen::usizex4; -} -impl Shuffle<[u32; 8]> for usize { - type Output = crate::codegen::usizex8; -} - -impl Shuffle<[u32; 2]> for *const T { - type Output = crate::codegen::cptrx2; -} -impl Shuffle<[u32; 4]> for *const T { - type Output = crate::codegen::cptrx4; -} -impl Shuffle<[u32; 8]> for *const T { - type Output = crate::codegen::cptrx8; -} - -impl Shuffle<[u32; 2]> for *mut T { - type Output = crate::codegen::mptrx2; -} -impl Shuffle<[u32; 4]> for *mut T { - type Output = crate::codegen::mptrx4; -} -impl Shuffle<[u32; 8]> for *mut T { - type Output = crate::codegen::mptrx8; -} - -impl Shuffle<[u32; 2]> for msize { - type Output = crate::codegen::msizex2; -} -impl Shuffle<[u32; 4]> for msize { - type Output = crate::codegen::msizex4; -} -impl Shuffle<[u32; 8]> for msize { - type Output = crate::codegen::msizex8; -} - -impl Shuffle<[u32; 1]> for i128 { - type Output = crate::codegen::i128x1; -} -impl Shuffle<[u32; 2]> for i128 { - type Output = crate::codegen::i128x2; -} -impl Shuffle<[u32; 4]> for i128 { - type Output = crate::codegen::i128x4; -} - -impl Shuffle<[u32; 1]> for u128 { - type Output = crate::codegen::u128x1; -} -impl Shuffle<[u32; 2]> for u128 { - type Output = crate::codegen::u128x2; -} -impl Shuffle<[u32; 4]> for u128 { - type Output = crate::codegen::u128x4; -} - -impl Shuffle<[u32; 1]> for m128 { - type Output = crate::codegen::m128x1; -} -impl Shuffle<[u32; 2]> for m128 { - type Output = crate::codegen::m128x2; -} -impl Shuffle<[u32; 4]> for m128 { - type Output = crate::codegen::m128x4; -} diff --git a/vendor/packed_simd_2/.cargo-checksum.json b/vendor/packed_simd_2/.cargo-checksum.json new file mode 100644 index 0000000000..1ffff3edb8 --- /dev/null +++ b/vendor/packed_simd_2/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"9c95d2e7918abbed602d4bddd3e68b793c436a2e9503350575526e36b03c6195","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"eda9ee8b97b83f0b3f29a2ec8b717cdcd3297a79f0163be7d9b6e1fc64359a71","bors.toml":"dee881dc69b9b7834e4eba5d95c3ed5a416d4628815a167d6a22d4cb4fb064b8","build.rs":"eb12357e953205b699ea2fd355a777af25de76ac0181cce40d3fce43547fb161","ci/all.sh":"2ae6b2445b4db83833e40b37efd0016c6b9879ee988b9b3ef94db5439a3e1606","ci/android-install-ndk.sh":"0f1746108cc30bf9b9ba45bcde7b19fc1a8bdf5b0258035b4eb8dc69b75efac4","ci/android-install-sdk.sh":"3490432022c5c8f5a115c084f7a9aca1626f96c0c87ffb62019228c4346b47e4","ci/android-sysimage.sh":"ebf4e5daa1f0fe1b2092b79f0f3f161c4c4275cb744e52352c4d81ab451e4c5a","ci/benchmark.sh":"b61d19ef6b90deba8fb79dee74c8b062d94844676293da346da87bb78a9a49a4","ci/deploy_and_run_on_ios_simulator.rs":"ec8ecf82d92072676aa47f0d1a3d021b60a7ae3531153ef12d2ff4541fc294dc","ci/docker/aarch64-linux-android/Dockerfile":"ace2e7d33c87bc0f6d3962a4a3408c04557646f7f51ab99cfbf574906796b016","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"da88c0d50f16dc08448c7fdf1fa5ed2cbe576acf9e7dd85b5b818621b2a8c702","ci/docker/arm-linux-androideabi/Dockerfile":"370e55d3330a413a3ccf677b3afb3e0ef9018a5fab263faa97ae8ac017fc2286","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"bb5f8ae890707c128652290ffc544447643bf12037ddd73c6ad6989f848cb380","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"1afaefcbc05b740859acd4e067bc92439be6bcbe8f2e9678474fb434bcd398d9","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"8282ea707a94109beed47a57574755e2d58401735904a03f85fb64c578c53b4f","ci/docker/i586-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/i686-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/mips-unknown-linux-gnu/Dockerfile":"b2ebc25797612c4f8395fe9d407725156044955bfbcf442036b7f55b43a5f9da","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"b0c1692ac65bc56dd30494b1993d8e929c48cc9c4b92029b7c7592af6d4f9220","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"4e9249c179300138141d0b2b7401b11897f64aed69f541f078c1db4594df2827","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"3164c52b0dcbb01afa78292b15b5c43503ccf0491cf6eb801ec2bf22ae274e52","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"786f799d0b56eb54d7b6c4b00e1aed4ce81776e14e44767e083c89d014b72004","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"e8bc363837cd9c2d8b22402acb8c1c329efc11ba5d12170603d2fe2eae9da059","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"47998d45b781d797b9e6085ebe898d90de0c952b54537a8db4e8d7503eb032d9","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"93fb44df3d7fd31ead158570667c97b5076a05c3d968af4a84bc13819a8f2db8","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"da1c39a3ff1fe22e41395fa7c8934e90b4c1788e551b9aec6e38bfd94effc437","ci/docker/thumbv7neon-linux-androideabi/Dockerfile":"c2decd5591bd7a09378901bef629cd944acf052eb55e4f35b79eb9cb4d62246a","ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile":"51955a8bf3c4d440f47382af6f5426ebff94ab01a04da36175babda9a057740f","ci/docker/wasm32-unknown-unknown/Dockerfile":"3e5f294bc1e004aa599086c2af49d6f3e7459fa250f5fbdd60cf67d53db78758","ci/docker/x86_64-linux-android/Dockerfile":"685040273cf350d5509e580ac451555efa19790c8723ca2af066adadc6880ad2","ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile":"44b6203d9290bfdc53d81219f0937e1110847a23dd982ec8c4de388354f01536","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"7f4e3ca5fa288ea70edb4d1f75309708cd30b192e2e4444e61c4d5b3b58f89cf","ci/dox.sh":"434e9611c52e389312d2b03564adf09429f10cc76fe66a8644adb104903b87b7","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab7ad3b7a344833ee726aba6b647cf5952e56f0ad1ba420b13325","ci/lld-shim.rs":"3d7f71ec23a49e2b67f694a0168786f9a954dda15f5a138815d966643fd3fcc3","ci/max_line_width.sh":"0a1518bba4c9ecaa55694cb2e9930d0e19c265baabf73143f17f9cf285aaa5bb","ci/run-docker.sh":"92e036390ad9b0d16f109579df1b5ced2e72e9afea40c7d011400ebd3a2a90de","ci/run.sh":"41dd6a60efaaeae9661a01370cce98b631f78392859a0cf68c946c0a16edf5f7","ci/run_examples.sh":"d1a23c6c35374a0678ba5114b9b8fefd8be0a79e774872a8bf0898d1baca18d0","ci/runtest-android.rs":"145a8e9799a5223975061fe7e586ade5669ee4877a7d7a4cf6b4ab48e8e36c7c","ci/setup_benchmarks.sh":"fae3960023f6f3d1388cd2ad22fdbab4b075f1f29dd4292d7994a20783beb6cf","ci/test-runner-linux":"c8aa6025cff5306f4f31d0c61dc5f9d4dd5a1d189ab613ef8d4c367c694d9ccd","contributing.md":"2cc8c9c560ae17867e69b06d09b758dbf7bc39eb774ada50a743724b10acc0a2","perf-guide/book.toml":"115a98284126c6b180178b44713314cc494f08a71662ee2ce15cf67f17a51064","perf-guide/src/SUMMARY.md":"3e03bffc991fdc2050f3d51842d72d9d21ea6abab56a3baf3b2d5973a78b89e1","perf-guide/src/ascii.css":"29afb08833b2fe2250f0412e1fa1161a2432a0820a14953c87124407417c741a","perf-guide/src/bound_checks.md":"5e4991ff58a183ef0cd9fdc1feb4cd12d083b44bdf87393bbb0927808ef3ce7d","perf-guide/src/float-math/approx.md":"8c09032fa2d795a0c5db1775826c850d28eb2627846d0965c60ee72de63735ad","perf-guide/src/float-math/fma.md":"311076ba4b741d604a82e74b83a8d7e8c318fcbd7f64c4392d1cf5af95c60243","perf-guide/src/float-math/fp.md":"04153e775ab6e4f0d7837bcc515230d327b04edfa34c84ce9c9e10ebaeef2be8","perf-guide/src/float-math/svml.md":"0798873b8eedaeda5fed62dc91645b57c20775a02d3cd74d8bd06958f1516506","perf-guide/src/introduction.md":"9f5a19e9e6751f25d2daad39891a0cc600974527ec4c8305843f9618910671bd","perf-guide/src/prof/linux.md":"447731eb5de7d69166728fdbc5ecb0c0c9db678ea493b45a592d67dd002184c0","perf-guide/src/prof/mca.md":"f56d54f3d20e7aa4d32052186e8237b03d65971eb5d112802b442570ff11d344","perf-guide/src/prof/profiling.md":"8a650c0fd6ede0964789bb6577557eeef1d8226a896788602ce61528e260e43c","perf-guide/src/target-feature/attribute.md":"615f88dca0a707b6c416fa605435dd6e1fb5361cc639429cbf68cd87624bd78b","perf-guide/src/target-feature/features.md":"17077760ff24c006b606dd21889c53d87228f4311f3ba3a574f9afdeacd86165","perf-guide/src/target-feature/inlining.md":"7ed1d7068d8173a00d84c16cfe5871cd68b9f04f8d0cca2d01ebc84957ebf2f6","perf-guide/src/target-feature/practice.md":"c4b371842e0086df178488fec97f20def8f0c62ee588bcd25fd948b9b1fa227e","perf-guide/src/target-feature/runtime.md":"835425f5ee597fb3e51d36e725a81ebee29f4561231d19563cd4da81dbb1cfcb","perf-guide/src/target-feature/rustflags.md":"ab49712e9293a65d74d540ba4784fcb57ff1119ec05a575d895c071f1a620f64","perf-guide/src/vert-hor-ops.md":"c6211c0ee91e60552ec592d89d9d957eedc21dee3cbd89e1ad6765ea06a27471","rust-toolchain":"2a3b62b53ddb9f167b63d22202a360811ba78df015021f704d01ee9abad4169c","rustfmt.toml":"de6101d0670bad65fb3b337d56957d2a024e017e5ab146ec784d77312daaf8ff","src/api.rs":"9de8e5f6f3f2874a184f918b5d281d1e8a1965525d3fff432c9bcba01b94ebe5","src/api/bit_manip.rs":"c47a4d0f7451f7e35d07715e4f39a472e07457fd456fdb726864a4f6887252a3","src/api/bitmask.rs":"6d2beefd62ee5d9c8eb060bee6abc641616bf828c99f82abf97b21bf004e894b","src/api/cast.rs":"03b94a3d316ac7b7be7068810044911e965e889a0ace7bae762749ca74a92747","src/api/cast/macros.rs":"b0a14d0c83ad2ebb7a275180f6d9e3f2bc312ba57a7d3d6c39fad4e0f20f9408","src/api/cast/v128.rs":"2107ea6a426a0fe37a0aa6a03a579ff0bdeb5a1599ea76e2d81734a82f41276d","src/api/cast/v16.rs":"d785cf93b8e61200c9ae1c32b9f5e9d9518e87c261c56bcaf92f2e47b0009eb4","src/api/cast/v256.rs":"b81fcfd367a5de532d922dedf18579e53666facef7957c0e1bc827825e500ae6","src/api/cast/v32.rs":"2aac9ec0a67a97328ba908b13a1ff98da3dcd7781910d592d31f9207cbd9a7d2","src/api/cast/v512.rs":"33b33de818f8d4eccc982bc2f3951a8b3d03e9762ec02789b3df82e3f5ed3fc3","src/api/cast/v64.rs":"ec878917d52a8c952633251b3a938a2cbe0a63fee6d12c15840d9f1343d1f394","src/api/cmp.rs":"357c3a2a09c6d4611c32dd7fa95be2fae933d513e229026ec9b44451a77b884e","src/api/cmp/eq.rs":"60f70f355bae4cb5b17db53204cacc3890f70670611c17df638d4c04f7cc8075","src/api/cmp/ord.rs":"589f7234761c294fa5df8f525bc4acd5a47cdb602207d524a0d4e19804cd9695","src/api/cmp/partial_eq.rs":"3ed23d2a930b0f9750c3a5309da766b03dc4f9c4d375b42ad3c50fe732693d15","src/api/cmp/partial_ord.rs":"e16b11805c94048acd058c93994b5bc74bb187f8d7e3b86a87df60e1601467f9","src/api/cmp/vertical.rs":"de3d62f38eba817299aa16f1e1939954c9a447e316509397465c2830852ba053","src/api/default.rs":"67bf21c134127d12a7028c8b88a57f0ceee8ccbd74976da8ca74eb9f16a174d5","src/api/fmt.rs":"67fb804bb86b6cd77cf8cd492b5733ce437071b66fe3297278b8a6552c325dda","src/api/fmt/binary.rs":"35cb5c266197d6224d598fb3d286e5fe48ef0c01ed356c2ff6fe9ba946f96a92","src/api/fmt/debug.rs":"aa18eea443bf353fea3db8b1a025132bbcaf91e747ecfa43b8d9fce9af395a0c","src/api/fmt/lower_hex.rs":"69d5be366631af309f214e8031c8c20267fcc27a695eac6f45c6bc1df72a67e6","src/api/fmt/octal.rs":"9eb11ba3d990213f3c7f1ec25edba7ce997cb1320e16d308c83498ba6b9bfbd9","src/api/fmt/upper_hex.rs":"a4637d085b7bb20e759ce58e08435b510a563ba3dd468af2b03560fdc5511562","src/api/from.rs":"2e599d8329cb05eaf06224cc441355c4b7b51254fc19256619333be8c149d444","src/api/from/from_array.rs":"dd3fc64fb17d6184bb60343f8da26a05edf0e5f3c14caf55d49fa15e21d948dc","src/api/from/from_vector.rs":"9764371aa9e6005aace74dea14f59e5611a095b7cf42707940924749282c52f0","src/api/hash.rs":"5076ece87969592c876486f5b1ea8affbeaec379d1a14a30859e0aa5592019de","src/api/into_bits.rs":"82297f0697d67b5a015e904e7e6e7b2a7066ba825bc54b94b4ff3e22d7a1eefb","src/api/into_bits/arch_specific.rs":"4acab22af90112072a2608fafc66fccf18cbf2e641b72af28404d30833cfe5c6","src/api/into_bits/macros.rs":"d762406de25aedff88d460dec7a80dc8e825a2a419d53218ce007efa6a1d3e04","src/api/into_bits/v128.rs":"3c502b9ce85bfcc727d6f053d49030b0ba9f46bd8e9fa5aa109382a2033f9f87","src/api/into_bits/v16.rs":"f4f4f61ba88aa51b158ec56ca3dce234349aea0daf2b3029a14ab5125d1e41e5","src/api/into_bits/v256.rs":"c24c3676707a0feb868dabe00766d74deab176794f905f79056337198c7cf790","src/api/into_bits/v32.rs":"905ba683d342fa32f4202b80bb46530807bd0a5b588f6c2e8c9f475223c47775","src/api/into_bits/v512.rs":"7cd89005215a9326eed8a742125dcbf981cba1aca72a313478eabf3df71b1160","src/api/into_bits/v64.rs":"d6238022ccff7b92e55b3f6017fc269acb6f36330a6d7e8fb389853a0f1b6478","src/api/math.rs":"8b2a2fc651917a850539f993aa0b9e5bf4da67b11685285b8de8cdca311719ec","src/api/math/float.rs":"969a75cdb3743c5ac7cde653d1a7f659ac65f2a5afb004c9928a7b34b79c3e39","src/api/math/float/abs.rs":"5b6b2701e2e11135b7ce58a05052ea8120e10e4702c95d046b9d21b827b26bf8","src/api/math/float/consts.rs":"78acba000d3fa527111300b6327c1932de9c4c1e02d4174e1a5615c01463d38c","src/api/math/float/cos.rs":"4c2dd7173728ef189314f1576c9486e03be21b7da98843b2f9011282a7979e31","src/api/math/float/exp.rs":"7c6d5f1e304f498a01cfa23b92380c815d7da0ad94eae3483783bc377d287eef","src/api/math/float/ln.rs":"54c7583f3df793b39ff57534fade27b41bb992439e5dc178252f5ca3190a3e54","src/api/math/float/mul_add.rs":"62cac77660d20159276d4c9ef066eb90c81cbddb808e8e157182c607625ad2eb","src/api/math/float/mul_adde.rs":"bae056ee9f3a70df39ec3c3b2f6437c65303888a7b843ef1a5bcf1f5aca0e602","src/api/math/float/powf.rs":"9ddb938984b36d39d82a82f862f80df8f7fb013f1d222d45698d41d88472f568","src/api/math/float/recpre.rs":"589225794ff1dbf31158dff660e6d4509ecc8befbb57c633900dea5ac0b840d6","src/api/math/float/rsqrte.rs":"a32abdcc318d7ccc8448231f54d75b884b7cbeb03a7d595713ab6243036f4dbf","src/api/math/float/sin.rs":"cbd3622b7df74f19691743001c8cf747a201f8977ad90542fee915f37dcd1e49","src/api/math/float/sqrt.rs":"0c66d5d63fb08e4d99c6b82a8828e41173aff1ac9fa1a2764a11fac217ccf2ac","src/api/math/float/sqrte.rs":"731e1c9f321b662accdd27dacb3aac2e8043b7aecb2f2161dde733bd9f025362","src/api/math/float/tanh.rs":"e57940434cc05981b086f0f3b92d32caceb38d67b90aebce5d3ed8e07c80538f","src/api/minimal.rs":"1f22bcc528555444e76de569ec0ae2029b9ae9d04805efeafa93369c8098036b","src/api/minimal/iuf.rs":"819cff26d3e196f807645bcc1d79eb27d9f175edb89910f2274d52a1e913cd11","src/api/minimal/mask.rs":"0cae10ae1fc65f5070e686c0c79bfba27b86b33d6c399367bd4848fb367dcec4","src/api/minimal/ptr.rs":"f65ebf21866a863485344432d9a7a9b7418f7fad5fdf841a4e2fa56ec0766ad0","src/api/ops.rs":"3e273b277a0f3019d42c3c59ca94a5afd4885d5ae6d2182e5089bbeec9de42ee","src/api/ops/scalar_arithmetic.rs":"d2d5ad897a59dd0787544f927e0e7ca4072c3e58b0f4a2324083312b0d5a21d7","src/api/ops/scalar_bitwise.rs":"482204e459ca6be79568e1c9f70adbe2d2151412ddf122fb2161be8ebb51c40c","src/api/ops/scalar_mask_bitwise.rs":"c250f52042e37b22d57256c80d4604104cfd2fbe2a2e127c676267270ca5d350","src/api/ops/scalar_shifts.rs":"987f8fdebeedc16e3d77c1b732e7826ef70633c541d16dfa290845d5c6289150","src/api/ops/vector_arithmetic.rs":"ddca15d09ddeef502c2ed66117a62300ca65d87e959e8b622d767bdf1c307910","src/api/ops/vector_bitwise.rs":"b3968f7005b649edcc22a54e2379b14d5ee19045f2e784029805781ae043b5ee","src/api/ops/vector_float_min_max.rs":"76bf8cb607e2c442923c1da1061a6b80d742d607408033c2a3761161114cf2a0","src/api/ops/vector_int_min_max.rs":"a378789c6ff9b32a51fbd0a97ffd36ed102cd1fe6a067d2b02017c1df342def6","src/api/ops/vector_mask_bitwise.rs":"5052d18517d765415d40327e6e8e55a312daaca0a5e2aec959bfa54b1675f9c8","src/api/ops/vector_neg.rs":"5c62f6b0221983cdbd23cd0a3af3672e6ba1255f0dfe8b19aae6fbd6503e231b","src/api/ops/vector_rotates.rs":"03cbe8a400fd7c688e4ee771a990a6754f2031b1a59b19ae81158b21471167e5","src/api/ops/vector_shifts.rs":"9bf69d0087268f61009e39aea52e03a90f378910206b6a28e8393178b6a5d0e0","src/api/ptr.rs":"8a793251bed6130dcfb2f1519ceaa18b751bbb15875928d0fb6deb5a5e07523a","src/api/ptr/gather_scatter.rs":"138b02b0fa1fdd785b95fc7048488be7e3ef277e0bc6ac5affb26af6a11d41a6","src/api/reductions.rs":"ae5baca81352ecd44526d6c30c0a1feeda475ec73ddd3c3ec6b14e944e5448ee","src/api/reductions/bitwise.rs":"8bf910ae226188bd15fc7e125f058cd2566b6186fcd0cd8fd020f352c39ce139","src/api/reductions/float_arithmetic.rs":"3997125f87c7bac07fffda3a1d814e0e6c77ca83099546a9e2fb8dc92231129f","src/api/reductions/integer_arithmetic.rs":"47471da1c5f859489680bb5d34ced3d3aa20081c16053a3af121a4496fcb57bf","src/api/reductions/mask.rs":"db83327a950e33a317f37fd33ca4e20c347fb415975ec024f3e23da8509425af","src/api/reductions/min_max.rs":"d40ccad10220ae5982785015bef92e4b0749583c2b060cad0aa4f92d99491c3b","src/api/select.rs":"a98e2ccf9fc6bdeed32d337c8675bc96c2fbe2cc34fbf149ad6047fb8e749774","src/api/shuffle.rs":"da58200790868c09659819322a489929a5b6e56c596ed07e6a44293ea02e7d09","src/api/shuffle1_dyn.rs":"bfea5a91905b31444e9ef7ca6eddb7a9606b7e22d3f71bb842eb2795a0346620","src/api/slice.rs":"ee87484e8af329547b9a5d4f2a69e8bed6ea10bbd96270d706083843d4eea2ac","src/api/slice/from_slice.rs":"53691dc9958dec4180004a42d140552b405e8cd875caa282e89af378dd63c8bc","src/api/slice/write_to_slice.rs":"3dd2e511af43dc6fa911dd0b12f6f00323e0acd1202a01365db400557d52a89b","src/api/swap_bytes.rs":"4a6792a2e49a77475e1b237592b4b2804dbddb79c474331acd0dd71b36934259","src/codegen.rs":"a29d38fa0a85eaf787fb49989e625bf64effd5f39c126fbb2a24be206d2a3917","src/codegen/bit_manip.rs":"17ecebcff1f080e712fea5eb51602a73f4201ed56a198220342c8eb55bb92692","src/codegen/llvm.rs":"b1f24237f61b7c5ddb8d47f3943aab79a95ce0e75af87ab2d1c88d842faffd39","src/codegen/math.rs":"35f96e37a78fcf0cdb02146b7f27a45108fe06a37fc2a54d8851ce131a326178","src/codegen/math/float.rs":"843b06adc2467377bd1184fd7bacb0fc10714918d29e433a9a7bffe46ed3c9d9","src/codegen/math/float/abs.rs":"f56e2b4b8055ea861c1f5cbc6b6e1d8e7e5af163b62c13574ddee4e09513bfbc","src/codegen/math/float/cos.rs":"ef3b511a24d23045b310315e80348a9b7fedb576fc2de52d74290616a0abeb2a","src/codegen/math/float/cos_pi.rs":"4e7631a5d73dac21531e09ef1802d1180f8997509c2c8fa9f67f322194263a97","src/codegen/math/float/exp.rs":"61b691598c41b5622f24e4320c1bdd08701e612a516438bdddcc728fc3405c8c","src/codegen/math/float/ln.rs":"46b718b1ba8c9d99e1ad40f53d20dfde08a3063ca7bd2a9fdd6698e060da687e","src/codegen/math/float/macros.rs":"dd42135fff13f9aca4fd3a1a4e14c7e6c31aadc6d817d63b0d2fb9e62e062744","src/codegen/math/float/mul_add.rs":"a37bf764345d4b1714f97e83897b7cf0855fc2811704bcbc0012db91825339e1","src/codegen/math/float/mul_adde.rs":"c75702bfcb361de45964a93caf959a695ef2376bd069227600b8c6872665c755","src/codegen/math/float/powf.rs":"642346e982bc4c39203de0864d2149c4179cd7b21cf67a2951687932b4675872","src/codegen/math/float/sin.rs":"9d68164c90cdca6a85155040cdac42e27342ebe0b925273ef1593df721af4258","src/codegen/math/float/sin_cos_pi.rs":"9be02ad48585a1e8d99129382fbffbaed47852f15459256a708850b6b7a75405","src/codegen/math/float/sin_pi.rs":"9890347905b4d4a3c7341c3eb06406e46e60582bcf6960688bd727e5dadc6c57","src/codegen/math/float/sqrt.rs":"e3c60dcfb0c6d2fc62adabcc931b2d4040b83cab294dea36443fb4b89eb79e34","src/codegen/math/float/sqrte.rs":"f0f4ef9eb475ae41bcc7ec6a95ad744ba6b36925faa8b2c2814004396d196b63","src/codegen/math/float/tanh.rs":"1c2c7431162ab248ee23e557e92c8b401875fb7b597ccfbba8f37b48f724de20","src/codegen/pointer_sized_int.rs":"a70697169c28218b56fd2e8d5353f2e00671d1150d0c8cef77d613bdfacd84cb","src/codegen/reductions.rs":"645e2514746d01387ddd07f0aa4ffd8430cc9ab428d4fb13773ea319fa25dd95","src/codegen/reductions/mask.rs":"8f1afe6aabf096a3278e1fc3a30f736e04aa8b9ce96373cee22162d18cfe2702","src/codegen/reductions/mask/aarch64.rs":"cba6e17603d39795dcfe8339b6b7d8714c3e162a1f0a635979f037aa24fe4206","src/codegen/reductions/mask/arm.rs":"9447904818aa2c7c25d0963eead452a639a11ca7dbd6d21eedbfcaade07a0f33","src/codegen/reductions/mask/fallback.rs":"7a0ef9f7fd03ae318b495b95e121350cd61caffc5cc6ee17fabf130d5d933453","src/codegen/reductions/mask/fallback_impl.rs":"76547f396e55ef403327c77c314cf8db8c7a5c9b9819bfb925abeacf130249e5","src/codegen/reductions/mask/x86.rs":"4c0457b6276f9809223590092a4c77e73812330326cdabd28df06820de10a310","src/codegen/reductions/mask/x86/avx.rs":"b4913d87844c522903641cbbf10db4551addb1ce5e9e78278e21612fa65c733b","src/codegen/reductions/mask/x86/avx2.rs":"677aed3f056285285daa3adff8bc65e739630b4424defa6d9665e160f027507e","src/codegen/reductions/mask/x86/sse.rs":"5a827c6f8e1074e324f6e4c778942badb6c09d747a7142de01cadec1240b3428","src/codegen/reductions/mask/x86/sse2.rs":"bc38e6c31cb4b3d62147eba6cac264e519e2a48e0f7ce9010cfa9ef0cf0ec9fd","src/codegen/shuffle.rs":"99a0b52c2470097b028af134221099baba383446a01c7dc3ae560209880bcdb7","src/codegen/shuffle1_dyn.rs":"fbc7d3d2e287543ab476a9a9314a5fbabdddd33bc463fc4bd22aa95631fcb996","src/codegen/swap_bytes.rs":"1d6cdc716eadddc92b4fd506b2445a821caa8dc00860447de09d7ebd69c2087f","src/codegen/v128.rs":"94226b31ec403d18d9d2fe06713f147c9c79e9b5f9105089088266313f843185","src/codegen/v16.rs":"ddec4ffb66b6f7aaffb9a1780c5ddba82557abd74f45073d335047e04cf74924","src/codegen/v256.rs":"6b63917f0444118d6b1595bff2045e59b97c4d24012bd575f69f1f0efc5a0241","src/codegen/v32.rs":"3477b3c5540aed86e61e2f5807dd31db947413cec9181c587d93ed6ec74f0eba","src/codegen/v512.rs":"5854f99d3aabc4cd42b28a20d9ce447756dc2ba024a409a69b6a8ae1f1842fc5","src/codegen/v64.rs":"e9e89caebfe63d10c0cbca61e4dfdba3b7e02ee0989170f80beed23237ddd950","src/codegen/vPtr.rs":"711c753a08d53a2879c4fb87a0762c46ce4e34c22f0ca88d2e4c557a0f679969","src/codegen/vSize.rs":"eeee9858749aa82142b27bc120d1989bb74a6b82e1e4efbbeaccc9634dc9acfc","src/lib.rs":"891d5369911c53caf422f3dbff2b413907ca11365baa5ed5828a7f0601270dac","src/masks.rs":"be05e923ac58fe6eb61311561b5583cd306574f206dc09fe8e3c7de3dd0c1433","src/sealed.rs":"ae7fdeaf5d84cd7710ed730ca72ca7eaba93df6cb0acb183e5c0a7327acf197f","src/testing.rs":"1d3a7862ef625e235a5734ad7204e68d350f902c0695182b1f08a0552432416e","src/testing/macros.rs":"6378856d7a40ba5ec5c7c0dad6327d79f0c77266921c24296d10aed6c68e9b98","src/testing/utils.rs":"5ec6a47b836f364ec6dede19750a19eaac704162327d03041eb0f007d5f8d75c","src/v128.rs":"16cf9a8e7156b899ee9b9cd3f2dba9d13ec63289bea8c3ee9ae2e43ad9510288","src/v16.rs":"cb6465cf1e00bf530183af1819b9fe3d7eec978f8765d5e85d9b58a39a4b4045","src/v256.rs":"fe235017da18c7f3c361831c60e3173ad304d8ea1e95d64ebebc79da2d708511","src/v32.rs":"145d347855bac59b2de6508f9e594654e6c330423af9edc0e2ac8f4d1abdf45e","src/v512.rs":"f372f277f3e62eb5c945bb1c460333fdb17b6974fcc876633788ff53bded9599","src/v64.rs":"0b8079881b71575e3414be0b7f8f7eaba65281ba6732f2b2f61f73e95b6f48f7","src/vPtr.rs":"8b3e433d487180bb4304ff71245ecad90f0010f43e139a72027b672abe58facc","src/vSize.rs":"eda5aa020706cbf94d15bada41a0c2a35fc8f3f37cb7c2cd6f34d201399a495e","tests/endianness.rs":"7db22078f31fe1421fc2d21f2e6b9df5eb0bdc99c10f6985d3a74c0df8f205dc"},"package":"3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"} \ No newline at end of file diff --git a/vendor/packed_simd/Cargo.toml b/vendor/packed_simd_2/Cargo.toml similarity index 74% rename from vendor/packed_simd/Cargo.toml rename to vendor/packed_simd_2/Cargo.toml index 7a2fb10c7f..61fbb47fc2 100644 --- a/vendor/packed_simd/Cargo.toml +++ b/vendor/packed_simd_2/Cargo.toml @@ -3,7 +3,7 @@ # 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 @@ -12,9 +12,9 @@ [package] edition = "2018" -name = "packed_simd" -version = "0.3.3" -authors = ["Gonzalo Brito Gadeschi "] +name = "packed_simd_2" +version = "0.3.4" +authors = ["Gonzalo Brito Gadeschi ", "Jubilee Young "] build = "build.rs" description = "Portable Packed SIMD vectors" homepage = "https://github.com/rust-lang-nursery/packed_simd" @@ -24,13 +24,16 @@ categories = ["hardware-support", "concurrency", "no-std", "data-structures"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang-nursery/packed_simd" [dependencies.cfg-if] -version = "^0.1" +version = "0.1.10" [dependencies.core_arch] -version = "^0.1.3" +version = "0.1.5" optional = true + +[dependencies.libm] +version = "0.1.4" [dev-dependencies.arrayvec] -version = "^0.4" +version = "^0.5" default-features = false [dev-dependencies.paste] @@ -41,27 +44,27 @@ default = [] into_bits = [] libcore_neon = [] [target."cfg(target_arch = \"x86_64\")".dependencies.sleef-sys] -version = "^0.1.2" +version = "0.1.2" optional = true [target.wasm32-unknown-unknown.dev-dependencies.wasm-bindgen] -version = "=0.2.19" +version = "=0.2.52" [target.wasm32-unknown-unknown.dev-dependencies.wasm-bindgen-test] -version = "=0.2.19" +version = "=0.3.2" [badges.appveyor] -repository = "rust-lang-nursery/packed_simd" +repository = "rust-lang/packed_simd" [badges.codecov] -repository = "rust-lang-nursery/packed_simd" +repository = "rust-lang/packed_simd" [badges.is-it-maintained-issue-resolution] -repository = "rust-lang-nursery/packed_simd" +repository = "rust-lang/packed_simd" [badges.is-it-maintained-open-issues] -repository = "rust-lang-nursery/packed_simd" +repository = "rust-lang/packed_simd" [badges.maintenance] status = "experimental" [badges.travis-ci] -repository = "rust-lang-nursery/packed_simd" +repository = "rust-lang/packed_simd" diff --git a/vendor/packed_simd/LICENSE-APACHE b/vendor/packed_simd_2/LICENSE-APACHE similarity index 100% rename from vendor/packed_simd/LICENSE-APACHE rename to vendor/packed_simd_2/LICENSE-APACHE diff --git a/vendor/packed_simd/LICENSE-MIT b/vendor/packed_simd_2/LICENSE-MIT similarity index 100% rename from vendor/packed_simd/LICENSE-MIT rename to vendor/packed_simd_2/LICENSE-MIT diff --git a/vendor/packed_simd/readme.md b/vendor/packed_simd_2/README.md similarity index 53% rename from vendor/packed_simd/readme.md rename to vendor/packed_simd_2/README.md index 29a4c4fdd2..138dad85cd 100644 --- a/vendor/packed_simd/readme.md +++ b/vendor/packed_simd_2/README.md @@ -2,18 +2,16 @@ ## Implementation of [Rust RFC #2366: `std::simd`][rfc2366] -[![Travis-CI Status]][travis] [![Appveyor Status]][appveyor] [![Latest Version]][crates.io] [![docs]][master_docs] +[![Travis-CI Status]][travis] [![Latest Version]][crates.io] [![docs]][master_docs] -> This aims to be a 100% conforming implementation of Rust RFC 2366 for stabilization. - -**WARNING**: this crate only supports the most recent nightly Rust toolchain. +**WARNING**: this crate only supports the most recent nightly Rust toolchain +and will be superceded by [stdsimd](https://github.com/rust-lang/stdsimd). ## Documentation * [API docs (`master` branch)][master_docs] * [Performance guide][perf_guide] -* [API docs (`docs.rs`)][docs.rs]: **CURRENTLY DOWN** due to - https://github.com/rust-lang-nursery/packed_simd/issues/110 +* [API docs (`docs.rs`)][docs.rs] * [RFC2366 `std::simd`][rfc2366]: - contains motivation, design rationale, discussion, etc. @@ -39,17 +37,6 @@ Most of the examples come with both a scalar and a vectorized implementation. vector type as those of another vector type safely by just using the `.into_bits()` method. -* `core_arch` (default: disabled): enable this feature to recompile `core::arch` - for the target-features enabled. `packed_simd` includes optimizations for some - target feature combinations that are enabled by this feature. Note, however, - that this is an unstable dependency, that rustc might break at any time. - -* `sleef-sys` (default: disabled - `x86_64` only): internally uses the [SLEEF] - short-vector math library when profitable via the [`sleef-sys`][sleef_sys] - crate. [SLEEF] is licensed under the [Boost Software License - v1.0][boost_license], an extremely permissive license, and can be statically - linked without issues. - ## Performance The following [ISPC] examples are also part of `packed_simd`'s @@ -75,58 +62,40 @@ slowdown: ## Platform support -The following table describes the supported platforms: `build` shows whether the -library compiles without issues for a given target, while `run` shows whether -the full testsuite passes on the target. - -| Linux targets: | build | run | -|-----------------------------------|-----------|---------| -| `i586-unknown-linux-gnu` | ✓ | ✓ | -| `i686-unknown-linux-gnu` | ✓ | ✓ | -| `x86_64-unknown-linux-gnu` | ✓ | ✓ | -| `arm-unknown-linux-gnueabi` | ✗ | ✗ | -| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | -| `armv7-unknown-linux-gnueabi` | ✓ | ✓ | -| `aarch64-unknown-linux-gnu` | ✓ | ✓ | -| `mips-unknown-linux-gnu` | ✓ | ✓ | -| `mipsel-unknown-linux-musl` | ✓ | ✓ | -| `mips64-unknown-linux-gnuabi64` | ✓ | ✓ | -| `mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | -| `powerpc-unknown-linux-gnu` | ✗ | ✗ | -| `powerpc64-unknown-linux-gnu` | ✗ | ✗ | -| `powerpc64le-unknown-linux-gnu` | ✗ | ✗ | -| `s390x-unknown-linux-gnu` | ✓ | ✓* | -| `sparc64-unknown-linux-gnu` | ✓ | ✓* | -| **MacOSX targets:** | **build** | **run** | -| `x86_64-apple-darwin` | ✓ | ✓ | -| `i686-apple-darwin` | ✓ | ✓ | -| **Windows targets:** | **build** | **run** | -| `x86_64-pc-windows-msvc` | ✓ | ✓ | -| `i686-pc-windows-msvc` | ✓ | ✓ | -| `x86_64-pc-windows-gnu` | ✗ | ✗ | -| `i686-pc-windows-gnu` | ✗ | ✗ | -| **WebAssembly targets:** | **build** | **run** | -| `wasm32-unknown-unknown` | ✓ | ✓ | -| **Android targets:** | **build** | **run** | -| `x86_64-linux-android` | ✓ | ✓ | -| `arm-linux-androideabi` | ✓ | ✓ | -| `aarch64-linux-android` | ✓ | ✗ | -| **iOS targets:** | **build** | **run** | -| `i386-apple-ios` | ✓ | ✗ | -| `x86_64-apple-ios` | ✓ | ✗ | -| `armv7-apple-ios` | ✓ | ✗** | -| `aarch64-apple-ios` | ✓ | ✗** | -| **xBSD targets:** | **build** | **run** | -| `i686-unknown-freebsd` | ✗ | ✗** | -| `x86_64-unknown-freebsd` | ✗ | ✗** | -| `x86_64-unknown-netbsd` | ✗ | ✗** | -| **Solaris targets:** | **build** | **run** | -| `x86_64-sun-solaris` | ✗ | ✗** | - -[*] most of the test suite passes correctly on these platform but -there are correctness bugs open in the issue tracker. - -[**] it is currently not easily possible to run these platforms on CI. +The following table describes the supported platforms: `build` shows whether +the library compiles without issues for a given target, while `run` shows +whether the test suite passes for a given target. + +| **Linux** | **build** | **run** | +|---------------------------------------|-----------|---------| +| `i586-unknown-linux-gnu` | ✓ | ✗ | +| `i686-unknown-linux-gnu` | ✓ | ✗ | +| `x86_64-unknown-linux-gnu` | ✓ | ✓ | +| `arm-unknown-linux-gnueabi` | ✗ | ✗ | +| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | +| `armv7-unknown-linux-gnueabi` | ✓ | ✓ | +| `aarch64-unknown-linux-gnu` | ✓ | ✓ | +| `mips-unknown-linux-gnu` | ✓ | ✗ | +| `mipsel-unknown-linux-musl` | ✓ | ✗ | +| `mips64-unknown-linux-gnuabi64` | ✓ | ✗ | +| `mips64el-unknown-linux-gnuabi64` | ✓ | ✗ | +| `powerpc-unknown-linux-gnu` | ✗ | ✗ | +| `powerpc64-unknown-linux-gnu` | ✗ | ✗ | +| `powerpc64le-unknown-linux-gnu` | ✓ | ✓ | +| `s390x-unknown-linux-gnu` | ✗ | ✗ | +| `sparc64-unknown-linux-gnu` | ✓ | ✗ | +| `thumbv7neon-unknown-linux-gnueabihf` | ✓ | ✓ | +| **MacOSX** | **build** | **run** | +| `x86_64-apple-darwin` | ✓ | ✓ | +| **Android** | **build** | **run** | +| `x86_64-linux-android` | ✓ | ✓ | +| `arm-linux-androideabi` | ✓ | ✓ | +| `aarch64-linux-android` | ✓ | ✓ | +| `thumbv7neon-linux-androideabi` | ✗ | ✗ | +| **iOS** | **build** | **run** | +| `x86_64-apple-ios` | ✓ | ✗ | +| `aarch64-apple-ios` | ✓ | ✗ | + ## Machine code verification @@ -160,8 +129,8 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `packed_simd` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -[travis]: https://travis-ci.org/rust-lang-nursery/packed_simd -[Travis-CI Status]: https://travis-ci.org/rust-lang-nursery/packed_simd.svg?branch=master +[travis]: https://travis-ci.com/rust-lang/packed_simd +[Travis-CI Status]: https://travis-ci.com/rust-lang/packed_simd.svg?branch=master [appveyor]: https://ci.appveyor.com/project/gnzlbg/packed-simd [Appveyor Status]: https://ci.appveyor.com/api/projects/status/hd7v9dvr442hgdix?svg=true [Latest Version]: https://img.shields.io/crates/v/packed_simd.svg diff --git a/vendor/packed_simd/bors.toml b/vendor/packed_simd_2/bors.toml similarity index 100% rename from vendor/packed_simd/bors.toml rename to vendor/packed_simd_2/bors.toml diff --git a/vendor/packed_simd/build.rs b/vendor/packed_simd_2/build.rs similarity index 100% rename from vendor/packed_simd/build.rs rename to vendor/packed_simd_2/build.rs diff --git a/vendor/packed_simd/ci/all.sh b/vendor/packed_simd_2/ci/all.sh similarity index 76% rename from vendor/packed_simd/ci/all.sh rename to vendor/packed_simd_2/ci/all.sh index 9f327afc60..55a1fa2efe 100755 --- a/vendor/packed_simd/ci/all.sh +++ b/vendor/packed_simd_2/ci/all.sh @@ -4,7 +4,7 @@ set -ex -: ${1?"The all.sh script requires one argument."} +: "${1?The all.sh script requires one argument.}" op=$1 @@ -21,7 +21,7 @@ cargo_fmt() { } cargo_clippy() { - cargo clippy --all -- -D clippy::pedantic + cargo clippy --all -- -D clippy::perf } CMD="-1" @@ -54,11 +54,18 @@ $CMD for dir in examples/*/ do dir=${dir%*/} - cd ${dir%*/} - $CMD - cd - + ( + cd "${dir%*/}" + $CMD + ) done -cd verify/verify -$CMD -cd - +( + cd verify/verify + $CMD +) + +( + cd micro_benchmarks + $CMD +) diff --git a/vendor/packed_simd/ci/android-install-ndk.sh b/vendor/packed_simd_2/ci/android-install-ndk.sh similarity index 100% rename from vendor/packed_simd/ci/android-install-ndk.sh rename to vendor/packed_simd_2/ci/android-install-ndk.sh diff --git a/vendor/packed_simd/ci/android-install-sdk.sh b/vendor/packed_simd_2/ci/android-install-sdk.sh similarity index 100% rename from vendor/packed_simd/ci/android-install-sdk.sh rename to vendor/packed_simd_2/ci/android-install-sdk.sh diff --git a/vendor/packed_simd/ci/android-sysimage.sh b/vendor/packed_simd_2/ci/android-sysimage.sh similarity index 100% rename from vendor/packed_simd/ci/android-sysimage.sh rename to vendor/packed_simd_2/ci/android-sysimage.sh diff --git a/vendor/packed_simd/ci/benchmark.sh b/vendor/packed_simd_2/ci/benchmark.sh similarity index 100% rename from vendor/packed_simd/ci/benchmark.sh rename to vendor/packed_simd_2/ci/benchmark.sh diff --git a/vendor/packed_simd/ci/deploy_and_run_on_ios_simulator.rs b/vendor/packed_simd_2/ci/deploy_and_run_on_ios_simulator.rs similarity index 100% rename from vendor/packed_simd/ci/deploy_and_run_on_ios_simulator.rs rename to vendor/packed_simd_2/ci/deploy_and_run_on_ios_simulator.rs diff --git a/vendor/packed_simd/ci/docker/aarch64-linux-android/Dockerfile b/vendor/packed_simd_2/ci/docker/aarch64-linux-android/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/aarch64-linux-android/Dockerfile rename to vendor/packed_simd_2/ci/docker/aarch64-linux-android/Dockerfile diff --git a/vendor/packed_simd/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/aarch64-unknown-linux-gnu/Dockerfile similarity index 95% rename from vendor/packed_simd/ci/docker/aarch64-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/aarch64-unknown-linux-gnu/Dockerfile index 68261a2f03..41ff4729ac 100644 --- a/vendor/packed_simd/ci/docker/aarch64-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/arm-linux-androideabi/Dockerfile b/vendor/packed_simd_2/ci/docker/arm-linux-androideabi/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/arm-linux-androideabi/Dockerfile rename to vendor/packed_simd_2/ci/docker/arm-linux-androideabi/Dockerfile diff --git a/vendor/packed_simd/ci/docker/arm-unknown-linux-gnueabi/Dockerfile b/vendor/packed_simd_2/ci/docker/arm-unknown-linux-gnueabi/Dockerfile similarity index 96% rename from vendor/packed_simd/ci/docker/arm-unknown-linux-gnueabi/Dockerfile rename to vendor/packed_simd_2/ci/docker/arm-unknown-linux-gnueabi/Dockerfile index cb4de6a57e..e1c591dd97 100644 --- a/vendor/packed_simd/ci/docker/arm-unknown-linux-gnueabi/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/arm-unknown-linux-gnueabi/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/vendor/packed_simd_2/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile similarity index 95% rename from vendor/packed_simd/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile rename to vendor/packed_simd_2/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile index c7bd61f0a7..757b79e7ec 100644 --- a/vendor/packed_simd/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/vendor/packed_simd_2/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile similarity index 95% rename from vendor/packed_simd/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile rename to vendor/packed_simd_2/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile index e01b87afdf..2539062933 100644 --- a/vendor/packed_simd/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/i586-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/i586-unknown-linux-gnu/Dockerfile similarity index 88% rename from vendor/packed_simd/ci/docker/i586-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/i586-unknown-linux-gnu/Dockerfile index 857974a858..01093698f6 100644 --- a/vendor/packed_simd/ci/docker/i586-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/i586-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-multilib \ libc6-dev \ diff --git a/vendor/packed_simd/ci/docker/i686-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/i686-unknown-linux-gnu/Dockerfile similarity index 88% rename from vendor/packed_simd/ci/docker/i686-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/i686-unknown-linux-gnu/Dockerfile index 857974a858..01093698f6 100644 --- a/vendor/packed_simd/ci/docker/i686-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-multilib \ libc6-dev \ diff --git a/vendor/packed_simd/ci/docker/mips-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/mips-unknown-linux-gnu/Dockerfile similarity index 88% rename from vendor/packed_simd/ci/docker/mips-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/mips-unknown-linux-gnu/Dockerfile index 4711cead37..3bd471e87d 100644 --- a/vendor/packed_simd/ci/docker/mips-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/mips-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc libc6-dev qemu-user ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/vendor/packed_simd_2/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile similarity index 87% rename from vendor/packed_simd/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile rename to vendor/packed_simd_2/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile index 1422e8c809..f26f1f38eb 100644 --- a/vendor/packed_simd/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc libc6-dev qemu-user ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile b/vendor/packed_simd_2/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile similarity index 86% rename from vendor/packed_simd/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile rename to vendor/packed_simd_2/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile index d94deb5b20..7d9f0bd992 100644 --- a/vendor/packed_simd/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc libc6-dev qemu-user ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/mipsel-unknown-linux-musl/Dockerfile b/vendor/packed_simd_2/ci/docker/mipsel-unknown-linux-musl/Dockerfile similarity index 82% rename from vendor/packed_simd/ci/docker/mipsel-unknown-linux-musl/Dockerfile rename to vendor/packed_simd_2/ci/docker/mipsel-unknown-linux-musl/Dockerfile index 40ac50675b..7488662ef2 100644 --- a/vendor/packed_simd/ci/docker/mipsel-unknown-linux-musl/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/mipsel-unknown-linux-musl/Dockerfile @@ -16,10 +16,10 @@ RUN mkdir /toolchain # Note that this originally came from: # https://downloads.openwrt.org/snapshots/trunk/malta/generic/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 -RUN curl -L https://s3-us-west-1.amazonaws.com/rust-lang-ci2/libc/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \ +RUN curl -L https://ci-mirrors.rust-lang.org/libc/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \ tar xjf - -C /toolchain --strip-components=2 ENV PATH=$PATH:/rust/bin:/toolchain/bin \ CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER=mipsel-openwrt-linux-gcc \ - CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_RUNNER="qemu-mipsel -L /toolchain" \ No newline at end of file + CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_RUNNER="qemu-mipsel -L /toolchain" diff --git a/vendor/packed_simd/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/powerpc-unknown-linux-gnu/Dockerfile similarity index 89% rename from vendor/packed_simd/ci/docker/powerpc-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/powerpc-unknown-linux-gnu/Dockerfile index 43b174ed87..80cfee8ab5 100644 --- a/vendor/packed_simd/ci/docker/powerpc-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/powerpc-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc libc6-dev qemu-user ca-certificates \ @@ -9,4 +9,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER=powerpc-linux-gnu-gcc \ CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER="qemu-ppc -cpu Vger -L /usr/powerpc-linux-gnu" \ + CC=powerpc-linux-gnu-gcc \ OBJDUMP=powerpc-linux-gnu-objdump diff --git a/vendor/packed_simd/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile similarity index 96% rename from vendor/packed_simd/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile index 7757ad28a4..74031a2a3e 100644 --- a/vendor/packed_simd/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ diff --git a/vendor/packed_simd/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile similarity index 96% rename from vendor/packed_simd/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile index 0b0c214fdf..471a7d9651 100644 --- a/vendor/packed_simd/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc libc6-dev qemu-user ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/s390x-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/s390x-unknown-linux-gnu/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/s390x-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/s390x-unknown-linux-gnu/Dockerfile diff --git a/vendor/packed_simd/ci/docker/sparc64-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/sparc64-unknown-linux-gnu/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/sparc64-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/sparc64-unknown-linux-gnu/Dockerfile diff --git a/vendor/packed_simd/ci/docker/thumbv7neon-linux-androideabi/Dockerfile b/vendor/packed_simd_2/ci/docker/thumbv7neon-linux-androideabi/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/thumbv7neon-linux-androideabi/Dockerfile rename to vendor/packed_simd_2/ci/docker/thumbv7neon-linux-androideabi/Dockerfile diff --git a/vendor/packed_simd/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile b/vendor/packed_simd_2/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile similarity index 95% rename from vendor/packed_simd/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile rename to vendor/packed_simd_2/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile index 696cb6c3fb..588d23c65a 100644 --- a/vendor/packed_simd/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ ca-certificates \ diff --git a/vendor/packed_simd/ci/docker/wasm32-unknown-unknown/Dockerfile b/vendor/packed_simd_2/ci/docker/wasm32-unknown-unknown/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/wasm32-unknown-unknown/Dockerfile rename to vendor/packed_simd_2/ci/docker/wasm32-unknown-unknown/Dockerfile diff --git a/vendor/packed_simd/ci/docker/x86_64-linux-android/Dockerfile b/vendor/packed_simd_2/ci/docker/x86_64-linux-android/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/x86_64-linux-android/Dockerfile rename to vendor/packed_simd_2/ci/docker/x86_64-linux-android/Dockerfile diff --git a/vendor/packed_simd/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile b/vendor/packed_simd_2/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile similarity index 100% rename from vendor/packed_simd/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile rename to vendor/packed_simd_2/ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile diff --git a/vendor/packed_simd/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/vendor/packed_simd_2/ci/docker/x86_64-unknown-linux-gnu/Dockerfile similarity index 90% rename from vendor/packed_simd/ci/docker/x86_64-unknown-linux-gnu/Dockerfile rename to vendor/packed_simd_2/ci/docker/x86_64-unknown-linux-gnu/Dockerfile index e6b000d051..ce5bb88e62 100644 --- a/vendor/packed_simd/ci/docker/x86_64-unknown-linux-gnu/Dockerfile +++ b/vendor/packed_simd_2/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libc6-dev \ diff --git a/vendor/packed_simd/ci/dox.sh b/vendor/packed_simd_2/ci/dox.sh similarity index 83% rename from vendor/packed_simd/ci/dox.sh rename to vendor/packed_simd_2/ci/dox.sh index 1743366407..560eaadcc8 100755 --- a/vendor/packed_simd/ci/dox.sh +++ b/vendor/packed_simd_2/ci/dox.sh @@ -18,7 +18,10 @@ cp -r perf-guide/book target/doc/perf-guide # If we're on travis, not a PR, and on the right branch, publish! if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then - pip install ghp_import --install-option="--prefix=$HOME/.local" - $HOME/.local/bin/ghp-import -n target/doc + python3 -vV + pip -vV + python3.9 -vV + pip install ghp_import --user + ghp-import -n target/doc git push -qf https://${GH_PAGES}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages fi diff --git a/vendor/packed_simd/ci/linux-s390x.sh b/vendor/packed_simd_2/ci/linux-s390x.sh similarity index 100% rename from vendor/packed_simd/ci/linux-s390x.sh rename to vendor/packed_simd_2/ci/linux-s390x.sh diff --git a/vendor/packed_simd/ci/linux-sparc64.sh b/vendor/packed_simd_2/ci/linux-sparc64.sh similarity index 100% rename from vendor/packed_simd/ci/linux-sparc64.sh rename to vendor/packed_simd_2/ci/linux-sparc64.sh diff --git a/vendor/packed_simd/ci/lld-shim.rs b/vendor/packed_simd_2/ci/lld-shim.rs similarity index 100% rename from vendor/packed_simd/ci/lld-shim.rs rename to vendor/packed_simd_2/ci/lld-shim.rs diff --git a/vendor/packed_simd/ci/max_line_width.sh b/vendor/packed_simd_2/ci/max_line_width.sh similarity index 100% rename from vendor/packed_simd/ci/max_line_width.sh rename to vendor/packed_simd_2/ci/max_line_width.sh diff --git a/vendor/packed_simd/ci/run-docker.sh b/vendor/packed_simd_2/ci/run-docker.sh similarity index 100% rename from vendor/packed_simd/ci/run-docker.sh rename to vendor/packed_simd_2/ci/run-docker.sh diff --git a/vendor/packed_simd/ci/run.sh b/vendor/packed_simd_2/ci/run.sh similarity index 92% rename from vendor/packed_simd/ci/run.sh rename to vendor/packed_simd_2/ci/run.sh index 7bb8258836..428a5d8902 100755 --- a/vendor/packed_simd/ci/run.sh +++ b/vendor/packed_simd_2/ci/run.sh @@ -78,9 +78,11 @@ fi if [[ "${TARGET}" == "x86_64-unknown-linux-gnu" ]] || [[ "${TARGET}" == "x86_64-pc-windows-msvc" ]]; then # use sleef on linux and windows x86_64 builds - cargo_test_impl --release --features=into_bits,core_arch,sleef-sys + # FIXME: Use `core_arch,sleef-sys` features once they works again + cargo_test_impl --release --features=into_bits else - cargo_test_impl --release --features=into_bits,core_arch + # FIXME: Use `core_arch` feature once it works again + cargo_test_impl --release --features=into_bits fi # Verify code generation diff --git a/vendor/packed_simd/ci/run_examples.sh b/vendor/packed_simd_2/ci/run_examples.sh similarity index 100% rename from vendor/packed_simd/ci/run_examples.sh rename to vendor/packed_simd_2/ci/run_examples.sh diff --git a/vendor/packed_simd/ci/runtest-android.rs b/vendor/packed_simd_2/ci/runtest-android.rs similarity index 100% rename from vendor/packed_simd/ci/runtest-android.rs rename to vendor/packed_simd_2/ci/runtest-android.rs diff --git a/vendor/packed_simd/ci/setup_benchmarks.sh b/vendor/packed_simd_2/ci/setup_benchmarks.sh similarity index 72% rename from vendor/packed_simd/ci/setup_benchmarks.sh rename to vendor/packed_simd_2/ci/setup_benchmarks.sh index ddc4765d5c..cd41a78513 100755 --- a/vendor/packed_simd/ci/setup_benchmarks.sh +++ b/vendor/packed_simd_2/ci/setup_benchmarks.sh @@ -5,6 +5,3 @@ set -ex # Get latest ISPC binary for the target and put it in the path git clone https://github.com/gnzlbg/ispc-binaries cp ispc-binaries/ispc-${TARGET} ispc - -# Rust-bindgen requires RUSTFMT -rustup component add rustfmt-preview diff --git a/vendor/packed_simd/ci/test-runner-linux b/vendor/packed_simd_2/ci/test-runner-linux similarity index 100% rename from vendor/packed_simd/ci/test-runner-linux rename to vendor/packed_simd_2/ci/test-runner-linux diff --git a/vendor/packed_simd/contributing.md b/vendor/packed_simd_2/contributing.md similarity index 100% rename from vendor/packed_simd/contributing.md rename to vendor/packed_simd_2/contributing.md diff --git a/vendor/packed_simd/perf-guide/book.toml b/vendor/packed_simd_2/perf-guide/book.toml similarity index 100% rename from vendor/packed_simd/perf-guide/book.toml rename to vendor/packed_simd_2/perf-guide/book.toml diff --git a/vendor/packed_simd/perf-guide/src/SUMMARY.md b/vendor/packed_simd_2/perf-guide/src/SUMMARY.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/SUMMARY.md rename to vendor/packed_simd_2/perf-guide/src/SUMMARY.md diff --git a/vendor/packed_simd/perf-guide/src/ascii.css b/vendor/packed_simd_2/perf-guide/src/ascii.css similarity index 100% rename from vendor/packed_simd/perf-guide/src/ascii.css rename to vendor/packed_simd_2/perf-guide/src/ascii.css diff --git a/vendor/packed_simd/perf-guide/src/bound_checks.md b/vendor/packed_simd_2/perf-guide/src/bound_checks.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/bound_checks.md rename to vendor/packed_simd_2/perf-guide/src/bound_checks.md diff --git a/vendor/packed_simd/perf-guide/src/float-math/approx.md b/vendor/packed_simd_2/perf-guide/src/float-math/approx.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/float-math/approx.md rename to vendor/packed_simd_2/perf-guide/src/float-math/approx.md diff --git a/vendor/packed_simd/perf-guide/src/float-math/fma.md b/vendor/packed_simd_2/perf-guide/src/float-math/fma.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/float-math/fma.md rename to vendor/packed_simd_2/perf-guide/src/float-math/fma.md diff --git a/vendor/packed_simd/perf-guide/src/float-math/fp.md b/vendor/packed_simd_2/perf-guide/src/float-math/fp.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/float-math/fp.md rename to vendor/packed_simd_2/perf-guide/src/float-math/fp.md diff --git a/vendor/packed_simd/perf-guide/src/float-math/svml.md b/vendor/packed_simd_2/perf-guide/src/float-math/svml.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/float-math/svml.md rename to vendor/packed_simd_2/perf-guide/src/float-math/svml.md diff --git a/vendor/packed_simd/perf-guide/src/introduction.md b/vendor/packed_simd_2/perf-guide/src/introduction.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/introduction.md rename to vendor/packed_simd_2/perf-guide/src/introduction.md diff --git a/vendor/packed_simd/perf-guide/src/prof/linux.md b/vendor/packed_simd_2/perf-guide/src/prof/linux.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/prof/linux.md rename to vendor/packed_simd_2/perf-guide/src/prof/linux.md diff --git a/vendor/packed_simd/perf-guide/src/prof/mca.md b/vendor/packed_simd_2/perf-guide/src/prof/mca.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/prof/mca.md rename to vendor/packed_simd_2/perf-guide/src/prof/mca.md diff --git a/vendor/packed_simd/perf-guide/src/prof/profiling.md b/vendor/packed_simd_2/perf-guide/src/prof/profiling.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/prof/profiling.md rename to vendor/packed_simd_2/perf-guide/src/prof/profiling.md diff --git a/vendor/packed_simd/perf-guide/src/target-feature/attribute.md b/vendor/packed_simd_2/perf-guide/src/target-feature/attribute.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/target-feature/attribute.md rename to vendor/packed_simd_2/perf-guide/src/target-feature/attribute.md diff --git a/vendor/packed_simd/perf-guide/src/target-feature/features.md b/vendor/packed_simd_2/perf-guide/src/target-feature/features.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/target-feature/features.md rename to vendor/packed_simd_2/perf-guide/src/target-feature/features.md diff --git a/vendor/packed_simd/perf-guide/src/target-feature/inlining.md b/vendor/packed_simd_2/perf-guide/src/target-feature/inlining.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/target-feature/inlining.md rename to vendor/packed_simd_2/perf-guide/src/target-feature/inlining.md diff --git a/vendor/packed_simd/perf-guide/src/target-feature/practice.md b/vendor/packed_simd_2/perf-guide/src/target-feature/practice.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/target-feature/practice.md rename to vendor/packed_simd_2/perf-guide/src/target-feature/practice.md diff --git a/vendor/packed_simd/perf-guide/src/target-feature/runtime.md b/vendor/packed_simd_2/perf-guide/src/target-feature/runtime.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/target-feature/runtime.md rename to vendor/packed_simd_2/perf-guide/src/target-feature/runtime.md diff --git a/vendor/packed_simd/perf-guide/src/target-feature/rustflags.md b/vendor/packed_simd_2/perf-guide/src/target-feature/rustflags.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/target-feature/rustflags.md rename to vendor/packed_simd_2/perf-guide/src/target-feature/rustflags.md diff --git a/vendor/packed_simd/perf-guide/src/vert-hor-ops.md b/vendor/packed_simd_2/perf-guide/src/vert-hor-ops.md similarity index 100% rename from vendor/packed_simd/perf-guide/src/vert-hor-ops.md rename to vendor/packed_simd_2/perf-guide/src/vert-hor-ops.md diff --git a/vendor/packed_simd/rust-toolchain b/vendor/packed_simd_2/rust-toolchain similarity index 100% rename from vendor/packed_simd/rust-toolchain rename to vendor/packed_simd_2/rust-toolchain diff --git a/vendor/packed_simd/rustfmt.toml b/vendor/packed_simd_2/rustfmt.toml similarity index 100% rename from vendor/packed_simd/rustfmt.toml rename to vendor/packed_simd_2/rustfmt.toml diff --git a/vendor/packed_simd/src/api.rs b/vendor/packed_simd_2/src/api.rs similarity index 99% rename from vendor/packed_simd/src/api.rs rename to vendor/packed_simd_2/src/api.rs index 4e9c4292e0..9536859256 100644 --- a/vendor/packed_simd/src/api.rs +++ b/vendor/packed_simd_2/src/api.rs @@ -213,6 +213,7 @@ macro_rules! impl_f { impl_math_float_sin!([$elem_ty; $elem_n]: $tuple_id | $test_tt); impl_math_float_sqrt!([$elem_ty; $elem_n]: $tuple_id | $test_tt); impl_math_float_sqrte!([$elem_ty; $elem_n]: $tuple_id | $test_tt); + impl_math_float_tanh!([$elem_ty; $elem_n]: $tuple_id | $test_tt); impl_cmp_vertical!( [$elem_ty; $elem_n]: $tuple_id, $mask_ty, false, (1., 0.) | $test_tt diff --git a/vendor/packed_simd/src/api/bit_manip.rs b/vendor/packed_simd_2/src/api/bit_manip.rs similarity index 99% rename from vendor/packed_simd/src/api/bit_manip.rs rename to vendor/packed_simd_2/src/api/bit_manip.rs index 3d3c4eb885..6d8865706d 100644 --- a/vendor/packed_simd/src/api/bit_manip.rs +++ b/vendor/packed_simd_2/src/api/bit_manip.rs @@ -37,6 +37,7 @@ macro_rules! impl_bit_manip { paste::item_with_macros! { #[allow(overflowing_literals)] pub mod [<$id _bit_manip>] { + #![allow(const_item_mutation)] use super::*; const LANE_WIDTH: usize = mem::size_of::<$elem_ty>() * 8; diff --git a/vendor/packed_simd/src/api/bitmask.rs b/vendor/packed_simd_2/src/api/bitmask.rs similarity index 100% rename from vendor/packed_simd/src/api/bitmask.rs rename to vendor/packed_simd_2/src/api/bitmask.rs diff --git a/vendor/packed_simd/src/api/cast.rs b/vendor/packed_simd_2/src/api/cast.rs similarity index 95% rename from vendor/packed_simd/src/api/cast.rs rename to vendor/packed_simd_2/src/api/cast.rs index 70ce4615a3..f1c32ca1a3 100644 --- a/vendor/packed_simd/src/api/cast.rs +++ b/vendor/packed_simd_2/src/api/cast.rs @@ -1,11 +1,5 @@ //! Implementation of `FromCast` and `IntoCast`. -#![cfg_attr( - feature = "cargo-clippy", - allow( - clippy::module_name_repetitions, - clippy::stutter - ) -)] +#![allow(clippy::module_name_repetitions)] /// Numeric cast from `T` to `Self`. /// diff --git a/vendor/packed_simd/src/api/cast/macros.rs b/vendor/packed_simd_2/src/api/cast/macros.rs similarity index 100% rename from vendor/packed_simd/src/api/cast/macros.rs rename to vendor/packed_simd_2/src/api/cast/macros.rs diff --git a/vendor/packed_simd/src/api/cast/v128.rs b/vendor/packed_simd_2/src/api/cast/v128.rs similarity index 99% rename from vendor/packed_simd/src/api/cast/v128.rs rename to vendor/packed_simd_2/src/api/cast/v128.rs index 78c07f3a55..ab47ddc006 100644 --- a/vendor/packed_simd/src/api/cast/v128.rs +++ b/vendor/packed_simd_2/src/api/cast/v128.rs @@ -1,5 +1,5 @@ //! `FromCast` and `IntoCast` implementations for portable 128-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/api/cast/v16.rs b/vendor/packed_simd_2/src/api/cast/v16.rs similarity index 97% rename from vendor/packed_simd/src/api/cast/v16.rs rename to vendor/packed_simd_2/src/api/cast/v16.rs index d292936baa..cf974bb08e 100644 --- a/vendor/packed_simd/src/api/cast/v16.rs +++ b/vendor/packed_simd_2/src/api/cast/v16.rs @@ -1,5 +1,5 @@ //! `FromCast` and `IntoCast` implementations for portable 16-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/api/cast/v256.rs b/vendor/packed_simd_2/src/api/cast/v256.rs similarity index 99% rename from vendor/packed_simd/src/api/cast/v256.rs rename to vendor/packed_simd_2/src/api/cast/v256.rs index 0a669e0bee..9389dcb4c7 100644 --- a/vendor/packed_simd/src/api/cast/v256.rs +++ b/vendor/packed_simd_2/src/api/cast/v256.rs @@ -1,5 +1,5 @@ //! `FromCast` and `IntoCast` implementations for portable 256-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/api/cast/v32.rs b/vendor/packed_simd_2/src/api/cast/v32.rs similarity index 98% rename from vendor/packed_simd/src/api/cast/v32.rs rename to vendor/packed_simd_2/src/api/cast/v32.rs index 65050cdacb..2b254ba0cf 100644 --- a/vendor/packed_simd/src/api/cast/v32.rs +++ b/vendor/packed_simd_2/src/api/cast/v32.rs @@ -1,5 +1,5 @@ //! `FromCast` and `IntoCast` implementations for portable 32-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/api/cast/v512.rs b/vendor/packed_simd_2/src/api/cast/v512.rs similarity index 99% rename from vendor/packed_simd/src/api/cast/v512.rs rename to vendor/packed_simd_2/src/api/cast/v512.rs index 9ae1caed35..5a10ab0666 100644 --- a/vendor/packed_simd/src/api/cast/v512.rs +++ b/vendor/packed_simd_2/src/api/cast/v512.rs @@ -1,5 +1,5 @@ //! `FromCast` and `IntoCast` implementations for portable 512-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/api/cast/v64.rs b/vendor/packed_simd_2/src/api/cast/v64.rs similarity index 99% rename from vendor/packed_simd/src/api/cast/v64.rs rename to vendor/packed_simd_2/src/api/cast/v64.rs index 0e2f78f733..192a4638a3 100644 --- a/vendor/packed_simd/src/api/cast/v64.rs +++ b/vendor/packed_simd_2/src/api/cast/v64.rs @@ -1,5 +1,5 @@ //! `FromCast` and `IntoCast` implementations for portable 64-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/api/cmp.rs b/vendor/packed_simd_2/src/api/cmp.rs similarity index 100% rename from vendor/packed_simd/src/api/cmp.rs rename to vendor/packed_simd_2/src/api/cmp.rs diff --git a/vendor/packed_simd/src/api/cmp/eq.rs b/vendor/packed_simd_2/src/api/cmp/eq.rs similarity index 100% rename from vendor/packed_simd/src/api/cmp/eq.rs rename to vendor/packed_simd_2/src/api/cmp/eq.rs diff --git a/vendor/packed_simd/src/api/cmp/ord.rs b/vendor/packed_simd_2/src/api/cmp/ord.rs similarity index 100% rename from vendor/packed_simd/src/api/cmp/ord.rs rename to vendor/packed_simd_2/src/api/cmp/ord.rs diff --git a/vendor/packed_simd/src/api/cmp/partial_eq.rs b/vendor/packed_simd_2/src/api/cmp/partial_eq.rs similarity index 89% rename from vendor/packed_simd/src/api/cmp/partial_eq.rs rename to vendor/packed_simd_2/src/api/cmp/partial_eq.rs index 7e2782f0fc..1712a0de56 100644 --- a/vendor/packed_simd/src/api/cmp/partial_eq.rs +++ b/vendor/packed_simd_2/src/api/cmp/partial_eq.rs @@ -7,7 +7,7 @@ macro_rules! impl_cmp_partial_eq { ($true:expr, $false:expr) ) => { // FIXME: https://github.com/rust-lang-nursery/rust-clippy/issues/2892 - #[cfg_attr(feature = "cargo-clippy", allow(clippy::partialeq_ne_impl))] + #[allow(clippy::partialeq_ne_impl)] impl crate::cmp::PartialEq<$id> for $id { #[inline] fn eq(&self, other: &Self) -> bool { @@ -20,7 +20,7 @@ macro_rules! impl_cmp_partial_eq { } // FIXME: https://github.com/rust-lang-nursery/rust-clippy/issues/2892 - #[cfg_attr(feature = "cargo-clippy", allow(clippy::partialeq_ne_impl))] + #[allow(clippy::partialeq_ne_impl)] impl crate::cmp::PartialEq> for LexicographicallyOrdered<$id> { @@ -34,12 +34,13 @@ macro_rules! impl_cmp_partial_eq { } } - test_if!{ + test_if! { $test_tt: paste::item! { pub mod [<$id _cmp_PartialEq>] { use super::*; - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn partial_eq() { let a = $id::splat($false); let b = $id::splat($true); diff --git a/vendor/packed_simd/src/api/cmp/partial_ord.rs b/vendor/packed_simd_2/src/api/cmp/partial_ord.rs similarity index 100% rename from vendor/packed_simd/src/api/cmp/partial_ord.rs rename to vendor/packed_simd_2/src/api/cmp/partial_ord.rs diff --git a/vendor/packed_simd/src/api/cmp/vertical.rs b/vendor/packed_simd_2/src/api/cmp/vertical.rs similarity index 100% rename from vendor/packed_simd/src/api/cmp/vertical.rs rename to vendor/packed_simd_2/src/api/cmp/vertical.rs diff --git a/vendor/packed_simd/src/api/default.rs b/vendor/packed_simd_2/src/api/default.rs similarity index 88% rename from vendor/packed_simd/src/api/default.rs rename to vendor/packed_simd_2/src/api/default.rs index 843d51bcc4..7af55ea77a 100644 --- a/vendor/packed_simd/src/api/default.rs +++ b/vendor/packed_simd_2/src/api/default.rs @@ -12,6 +12,8 @@ macro_rules! impl_default { test_if!{ $test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] pub mod [<$id _default>] { use super::*; #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] diff --git a/vendor/packed_simd/src/api/fmt.rs b/vendor/packed_simd_2/src/api/fmt.rs similarity index 100% rename from vendor/packed_simd/src/api/fmt.rs rename to vendor/packed_simd_2/src/api/fmt.rs diff --git a/vendor/packed_simd/src/api/fmt/binary.rs b/vendor/packed_simd_2/src/api/fmt/binary.rs similarity index 86% rename from vendor/packed_simd/src/api/fmt/binary.rs rename to vendor/packed_simd_2/src/api/fmt/binary.rs index c758dadcc4..b60769082d 100644 --- a/vendor/packed_simd/src/api/fmt/binary.rs +++ b/vendor/packed_simd_2/src/api/fmt/binary.rs @@ -3,11 +3,10 @@ macro_rules! impl_fmt_binary { ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => { impl crate::fmt::Binary for $id { - #[cfg_attr( - feature = "cargo-clippy", allow(clippy::missing_inline_in_public_items) - )] - fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) - -> crate::fmt::Result { + #[allow(clippy::missing_inline_in_public_items)] + fn fmt( + &self, f: &mut crate::fmt::Formatter<'_>, + ) -> crate::fmt::Result { write!(f, "{}(", stringify!($id))?; for i in 0..$elem_count { if i > 0 { @@ -18,12 +17,13 @@ macro_rules! impl_fmt_binary { write!(f, ")") } } - test_if!{ + test_if! { $test_tt: paste::item! { pub mod [<$id _fmt_binary>] { use super::*; - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn binary() { use arrayvec::{ArrayString,ArrayVec}; type TinyString = ArrayString<[u8; 512]>; diff --git a/vendor/packed_simd/src/api/fmt/debug.rs b/vendor/packed_simd_2/src/api/fmt/debug.rs similarity index 91% rename from vendor/packed_simd/src/api/fmt/debug.rs rename to vendor/packed_simd_2/src/api/fmt/debug.rs index f34a237d96..ad0b8a59a1 100644 --- a/vendor/packed_simd/src/api/fmt/debug.rs +++ b/vendor/packed_simd_2/src/api/fmt/debug.rs @@ -2,12 +2,13 @@ macro_rules! impl_fmt_debug_tests { ([$elem_ty:ty; $elem_count:expr]: $id:ident | $test_tt:tt) => { - test_if!{ + test_if! { $test_tt: paste::item! { pub mod [<$id _fmt_debug>] { use super::*; - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn debug() { use arrayvec::{ArrayString,ArrayVec}; type TinyString = ArrayString<[u8; 512]>; @@ -42,10 +43,7 @@ macro_rules! impl_fmt_debug_tests { macro_rules! impl_fmt_debug { ([$elem_ty:ty; $elem_count:expr]: $id:ident | $test_tt:tt) => { impl crate::fmt::Debug for $id { - #[cfg_attr( - feature = "cargo-clippy", - allow(clippy::missing_inline_in_public_items) - )] + #[allow(clippy::missing_inline_in_public_items)] fn fmt( &self, f: &mut crate::fmt::Formatter<'_>, ) -> crate::fmt::Result { diff --git a/vendor/packed_simd/src/api/fmt/lower_hex.rs b/vendor/packed_simd_2/src/api/fmt/lower_hex.rs similarity index 86% rename from vendor/packed_simd/src/api/fmt/lower_hex.rs rename to vendor/packed_simd_2/src/api/fmt/lower_hex.rs index ac6ea95934..5a7aa14b5b 100644 --- a/vendor/packed_simd/src/api/fmt/lower_hex.rs +++ b/vendor/packed_simd_2/src/api/fmt/lower_hex.rs @@ -3,11 +3,10 @@ macro_rules! impl_fmt_lower_hex { ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => { impl crate::fmt::LowerHex for $id { - #[cfg_attr( - feature = "cargo-clippy", allow(clippy::missing_inline_in_public_items) - )] - fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) - -> crate::fmt::Result { + #[allow(clippy::missing_inline_in_public_items)] + fn fmt( + &self, f: &mut crate::fmt::Formatter<'_>, + ) -> crate::fmt::Result { write!(f, "{}(", stringify!($id))?; for i in 0..$elem_count { if i > 0 { @@ -18,12 +17,13 @@ macro_rules! impl_fmt_lower_hex { write!(f, ")") } } - test_if!{ + test_if! { $test_tt: paste::item! { pub mod [<$id _fmt_lower_hex>] { use super::*; - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn lower_hex() { use arrayvec::{ArrayString,ArrayVec}; type TinyString = ArrayString<[u8; 512]>; diff --git a/vendor/packed_simd/src/api/fmt/octal.rs b/vendor/packed_simd_2/src/api/fmt/octal.rs similarity index 86% rename from vendor/packed_simd/src/api/fmt/octal.rs rename to vendor/packed_simd_2/src/api/fmt/octal.rs index ff78a332b8..83ac8abc7d 100644 --- a/vendor/packed_simd/src/api/fmt/octal.rs +++ b/vendor/packed_simd_2/src/api/fmt/octal.rs @@ -3,11 +3,10 @@ macro_rules! impl_fmt_octal { ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => { impl crate::fmt::Octal for $id { - #[cfg_attr( - feature = "cargo-clippy", allow(clippy::missing_inline_in_public_items) - )] - fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) - -> crate::fmt::Result { + #[allow(clippy::missing_inline_in_public_items)] + fn fmt( + &self, f: &mut crate::fmt::Formatter<'_>, + ) -> crate::fmt::Result { write!(f, "{}(", stringify!($id))?; for i in 0..$elem_count { if i > 0 { @@ -18,12 +17,13 @@ macro_rules! impl_fmt_octal { write!(f, ")") } } - test_if!{ + test_if! { $test_tt: paste::item! { pub mod [<$id _fmt_octal>] { use super::*; - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn octal_hex() { use arrayvec::{ArrayString,ArrayVec}; type TinyString = ArrayString<[u8; 512]>; diff --git a/vendor/packed_simd/src/api/fmt/upper_hex.rs b/vendor/packed_simd_2/src/api/fmt/upper_hex.rs similarity index 86% rename from vendor/packed_simd/src/api/fmt/upper_hex.rs rename to vendor/packed_simd_2/src/api/fmt/upper_hex.rs index ab60c7e22b..aa88f673ab 100644 --- a/vendor/packed_simd/src/api/fmt/upper_hex.rs +++ b/vendor/packed_simd_2/src/api/fmt/upper_hex.rs @@ -3,11 +3,10 @@ macro_rules! impl_fmt_upper_hex { ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => { impl crate::fmt::UpperHex for $id { - #[cfg_attr( - feature = "cargo-clippy", allow(clippy::missing_inline_in_public_items) - )] - fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) - -> crate::fmt::Result { + #[allow(clippy::missing_inline_in_public_items)] + fn fmt( + &self, f: &mut crate::fmt::Formatter<'_>, + ) -> crate::fmt::Result { write!(f, "{}(", stringify!($id))?; for i in 0..$elem_count { if i > 0 { @@ -18,12 +17,13 @@ macro_rules! impl_fmt_upper_hex { write!(f, ")") } } - test_if!{ + test_if! { $test_tt: paste::item! { pub mod [<$id _fmt_upper_hex>] { use super::*; - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn upper_hex() { use arrayvec::{ArrayString,ArrayVec}; type TinyString = ArrayString<[u8; 512]>; diff --git a/vendor/packed_simd/src/api/from.rs b/vendor/packed_simd_2/src/api/from.rs similarity index 100% rename from vendor/packed_simd/src/api/from.rs rename to vendor/packed_simd_2/src/api/from.rs diff --git a/vendor/packed_simd/src/api/from/from_array.rs b/vendor/packed_simd_2/src/api/from/from_array.rs similarity index 97% rename from vendor/packed_simd/src/api/from/from_array.rs rename to vendor/packed_simd_2/src/api/from/from_array.rs index 964d1501df..b83f938162 100644 --- a/vendor/packed_simd/src/api/from/from_array.rs +++ b/vendor/packed_simd_2/src/api/from/from_array.rs @@ -56,6 +56,8 @@ macro_rules! impl_from_array { test_if! { $test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] mod [<$id _from>] { use super::*; #[test] diff --git a/vendor/packed_simd/src/api/from/from_vector.rs b/vendor/packed_simd_2/src/api/from/from_vector.rs similarity index 100% rename from vendor/packed_simd/src/api/from/from_vector.rs rename to vendor/packed_simd_2/src/api/from/from_vector.rs diff --git a/vendor/packed_simd/src/api/hash.rs b/vendor/packed_simd_2/src/api/hash.rs similarity index 93% rename from vendor/packed_simd/src/api/hash.rs rename to vendor/packed_simd_2/src/api/hash.rs index 08d42496ea..ee80eff939 100644 --- a/vendor/packed_simd/src/api/hash.rs +++ b/vendor/packed_simd_2/src/api/hash.rs @@ -36,6 +36,8 @@ macro_rules! impl_hash { let mut v_hash = a_hash.clone(); a.hash(&mut a_hash); + // Integer within mantissa^1 range. + #[allow(clippy::float_cmp)] let v = $id::splat(42 as $elem_ty); v.hash(&mut v_hash); assert_eq!(a_hash.finish(), v_hash.finish()); diff --git a/vendor/packed_simd/src/api/into_bits.rs b/vendor/packed_simd_2/src/api/into_bits.rs similarity index 100% rename from vendor/packed_simd/src/api/into_bits.rs rename to vendor/packed_simd_2/src/api/into_bits.rs diff --git a/vendor/packed_simd/src/api/into_bits/arch_specific.rs b/vendor/packed_simd_2/src/api/into_bits/arch_specific.rs similarity index 99% rename from vendor/packed_simd/src/api/into_bits/arch_specific.rs rename to vendor/packed_simd_2/src/api/into_bits/arch_specific.rs index 6cc2fa37b7..fee6140052 100644 --- a/vendor/packed_simd/src/api/into_bits/arch_specific.rs +++ b/vendor/packed_simd_2/src/api/into_bits/arch_specific.rs @@ -1,6 +1,6 @@ //! `FromBits` and `IntoBits` between portable vector types and the //! architecture-specific vector types. -#![rustfmt::skip] +#[rustfmt::skip] // FIXME: MIPS FromBits/IntoBits @@ -84,7 +84,6 @@ macro_rules! impl_arch { // FIXME: 64-bit single element types // FIXME: arm/aarch float16x4_t missing impl_arch!( - [x86["x86"]: __m64], [x86_64["x86_64"]: __m64], [arm["arm"]: int8x8_t, uint8x8_t, poly8x8_t, int16x4_t, uint16x4_t, poly16x4_t, int32x2_t, uint32x2_t, float32x2_t, int64x1_t, uint64x1_t], diff --git a/vendor/packed_simd/src/api/into_bits/macros.rs b/vendor/packed_simd_2/src/api/into_bits/macros.rs similarity index 100% rename from vendor/packed_simd/src/api/into_bits/macros.rs rename to vendor/packed_simd_2/src/api/into_bits/macros.rs diff --git a/vendor/packed_simd/src/api/into_bits/v128.rs b/vendor/packed_simd_2/src/api/into_bits/v128.rs similarity index 99% rename from vendor/packed_simd/src/api/into_bits/v128.rs rename to vendor/packed_simd_2/src/api/into_bits/v128.rs index 804dbf282d..e32cd7f9f0 100644 --- a/vendor/packed_simd/src/api/into_bits/v128.rs +++ b/vendor/packed_simd_2/src/api/into_bits/v128.rs @@ -1,5 +1,5 @@ //! `FromBits` and `IntoBits` implementations for portable 128-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] #[allow(unused)] // wasm_bindgen_test use crate::*; diff --git a/vendor/packed_simd/src/api/into_bits/v16.rs b/vendor/packed_simd_2/src/api/into_bits/v16.rs similarity index 94% rename from vendor/packed_simd/src/api/into_bits/v16.rs rename to vendor/packed_simd_2/src/api/into_bits/v16.rs index 1162a62e5b..e44d0e7f9a 100644 --- a/vendor/packed_simd/src/api/into_bits/v16.rs +++ b/vendor/packed_simd_2/src/api/into_bits/v16.rs @@ -1,5 +1,5 @@ //! `FromBits` and `IntoBits` implementations for portable 16-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] #[allow(unused)] // wasm_bindgen_test use crate::*; diff --git a/vendor/packed_simd/src/api/into_bits/v256.rs b/vendor/packed_simd_2/src/api/into_bits/v256.rs similarity index 99% rename from vendor/packed_simd/src/api/into_bits/v256.rs rename to vendor/packed_simd_2/src/api/into_bits/v256.rs index cc7a6646b5..c4c373e0d0 100644 --- a/vendor/packed_simd/src/api/into_bits/v256.rs +++ b/vendor/packed_simd_2/src/api/into_bits/v256.rs @@ -1,5 +1,5 @@ //! `FromBits` and `IntoBits` implementations for portable 256-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] #[allow(unused)] // wasm_bindgen_test use crate::*; diff --git a/vendor/packed_simd/src/api/into_bits/v32.rs b/vendor/packed_simd_2/src/api/into_bits/v32.rs similarity index 96% rename from vendor/packed_simd/src/api/into_bits/v32.rs rename to vendor/packed_simd_2/src/api/into_bits/v32.rs index 2c183ecf1c..5dba38a179 100644 --- a/vendor/packed_simd/src/api/into_bits/v32.rs +++ b/vendor/packed_simd_2/src/api/into_bits/v32.rs @@ -1,5 +1,5 @@ //! `FromBits` and `IntoBits` implementations for portable 32-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] #[allow(unused)] // wasm_bindgen_test use crate::*; diff --git a/vendor/packed_simd/src/api/into_bits/v512.rs b/vendor/packed_simd_2/src/api/into_bits/v512.rs similarity index 99% rename from vendor/packed_simd/src/api/into_bits/v512.rs rename to vendor/packed_simd_2/src/api/into_bits/v512.rs index 8dec6a7f63..4a771962c3 100644 --- a/vendor/packed_simd/src/api/into_bits/v512.rs +++ b/vendor/packed_simd_2/src/api/into_bits/v512.rs @@ -1,5 +1,5 @@ //! `FromBits` and `IntoBits` implementations for portable 512-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] #[allow(unused)] // wasm_bindgen_test use crate::*; diff --git a/vendor/packed_simd/src/api/into_bits/v64.rs b/vendor/packed_simd_2/src/api/into_bits/v64.rs similarity index 98% rename from vendor/packed_simd/src/api/into_bits/v64.rs rename to vendor/packed_simd_2/src/api/into_bits/v64.rs index 8999d98e13..5b065f1bd5 100644 --- a/vendor/packed_simd/src/api/into_bits/v64.rs +++ b/vendor/packed_simd_2/src/api/into_bits/v64.rs @@ -1,5 +1,5 @@ //! `FromBits` and `IntoBits` implementations for portable 64-bit wide vectors -#![rustfmt::skip] +#[rustfmt::skip] #[allow(unused)] // wasm_bindgen_test use crate::*; diff --git a/vendor/packed_simd/src/api/math.rs b/vendor/packed_simd_2/src/api/math.rs similarity index 100% rename from vendor/packed_simd/src/api/math.rs rename to vendor/packed_simd_2/src/api/math.rs diff --git a/vendor/packed_simd/src/api/math/float.rs b/vendor/packed_simd_2/src/api/math/float.rs similarity index 97% rename from vendor/packed_simd/src/api/math/float.rs rename to vendor/packed_simd_2/src/api/math/float.rs index c0ec46e917..d5d2bee2eb 100644 --- a/vendor/packed_simd/src/api/math/float.rs +++ b/vendor/packed_simd_2/src/api/math/float.rs @@ -39,6 +39,9 @@ mod sqrt; #[macro_use] mod sqrte; +#[macro_use] +mod tanh; + macro_rules! impl_float_category { ([$elem_ty:ident; $elem_count:expr]: $id:ident, $mask_ty:ident) => { impl $id { diff --git a/vendor/packed_simd/src/api/math/float/abs.rs b/vendor/packed_simd_2/src/api/math/float/abs.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/abs.rs rename to vendor/packed_simd_2/src/api/math/float/abs.rs diff --git a/vendor/packed_simd/src/api/math/float/consts.rs b/vendor/packed_simd_2/src/api/math/float/consts.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/consts.rs rename to vendor/packed_simd_2/src/api/math/float/consts.rs diff --git a/vendor/packed_simd/src/api/math/float/cos.rs b/vendor/packed_simd_2/src/api/math/float/cos.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/cos.rs rename to vendor/packed_simd_2/src/api/math/float/cos.rs diff --git a/vendor/packed_simd/src/api/math/float/exp.rs b/vendor/packed_simd_2/src/api/math/float/exp.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/exp.rs rename to vendor/packed_simd_2/src/api/math/float/exp.rs diff --git a/vendor/packed_simd/src/api/math/float/ln.rs b/vendor/packed_simd_2/src/api/math/float/ln.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/ln.rs rename to vendor/packed_simd_2/src/api/math/float/ln.rs diff --git a/vendor/packed_simd/src/api/math/float/mul_add.rs b/vendor/packed_simd_2/src/api/math/float/mul_add.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/mul_add.rs rename to vendor/packed_simd_2/src/api/math/float/mul_add.rs diff --git a/vendor/packed_simd/src/api/math/float/mul_adde.rs b/vendor/packed_simd_2/src/api/math/float/mul_adde.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/mul_adde.rs rename to vendor/packed_simd_2/src/api/math/float/mul_adde.rs diff --git a/vendor/packed_simd/src/api/math/float/powf.rs b/vendor/packed_simd_2/src/api/math/float/powf.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/powf.rs rename to vendor/packed_simd_2/src/api/math/float/powf.rs diff --git a/vendor/packed_simd/src/api/math/float/recpre.rs b/vendor/packed_simd_2/src/api/math/float/recpre.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/recpre.rs rename to vendor/packed_simd_2/src/api/math/float/recpre.rs diff --git a/vendor/packed_simd/src/api/math/float/rsqrte.rs b/vendor/packed_simd_2/src/api/math/float/rsqrte.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/rsqrte.rs rename to vendor/packed_simd_2/src/api/math/float/rsqrte.rs diff --git a/vendor/packed_simd/src/api/math/float/sin.rs b/vendor/packed_simd_2/src/api/math/float/sin.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/sin.rs rename to vendor/packed_simd_2/src/api/math/float/sin.rs diff --git a/vendor/packed_simd/src/api/math/float/sqrt.rs b/vendor/packed_simd_2/src/api/math/float/sqrt.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/sqrt.rs rename to vendor/packed_simd_2/src/api/math/float/sqrt.rs diff --git a/vendor/packed_simd/src/api/math/float/sqrte.rs b/vendor/packed_simd_2/src/api/math/float/sqrte.rs similarity index 100% rename from vendor/packed_simd/src/api/math/float/sqrte.rs rename to vendor/packed_simd_2/src/api/math/float/sqrte.rs diff --git a/vendor/packed_simd_2/src/api/math/float/tanh.rs b/vendor/packed_simd_2/src/api/math/float/tanh.rs new file mode 100644 index 0000000000..acfd93caaa --- /dev/null +++ b/vendor/packed_simd_2/src/api/math/float/tanh.rs @@ -0,0 +1,29 @@ +//! Implements vertical (lane-wise) floating-point `tanh`. + +macro_rules! impl_math_float_tanh { + ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => { + impl $id { + /// Tanh. + #[inline] + pub fn tanh(self) -> Self { + use crate::codegen::math::float::tanh::Tanh; + Tanh::tanh(self) + } + } + + test_if!{ + $test_tt: + paste::item! { + pub mod [<$id _math_tanh>] { + use super::*; + #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn tanh() { + let z = $id::splat(0 as $elem_ty); + + assert_eq!(z, z.tanh()); + } + } + } + } + }; +} diff --git a/vendor/packed_simd/src/api/minimal.rs b/vendor/packed_simd_2/src/api/minimal.rs similarity index 100% rename from vendor/packed_simd/src/api/minimal.rs rename to vendor/packed_simd_2/src/api/minimal.rs diff --git a/vendor/packed_simd/src/api/minimal/iuf.rs b/vendor/packed_simd_2/src/api/minimal/iuf.rs similarity index 96% rename from vendor/packed_simd/src/api/minimal/iuf.rs rename to vendor/packed_simd_2/src/api/minimal/iuf.rs index ed85cf7694..a155ac178a 100644 --- a/vendor/packed_simd/src/api/minimal/iuf.rs +++ b/vendor/packed_simd_2/src/api/minimal/iuf.rs @@ -18,8 +18,7 @@ macro_rules! impl_minimal_iuf { /// Creates a new instance with each vector elements initialized /// with the provided values. #[inline] - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::too_many_arguments))] + #[allow(clippy::too_many_arguments)] pub const fn new($($elem_name: $elem_ty),*) -> Self { Simd(codegen::$id($($elem_name as $ielem_ty),*)) } @@ -54,7 +53,7 @@ macro_rules! impl_minimal_iuf { /// Extracts the value at `index`. /// - /// # Precondition + /// # Safety /// /// If `index >= Self::lanes()` the behavior is undefined. #[inline] @@ -81,7 +80,7 @@ macro_rules! impl_minimal_iuf { /// Returns a new vector where the value at `index` is replaced by `new_value`. /// - /// # Precondition + /// # Safety /// /// If `index >= Self::lanes()` the behavior is undefined. #[inline] @@ -102,6 +101,8 @@ macro_rules! impl_minimal_iuf { test_if!{ $test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] pub mod [<$id _minimal>] { use super::*; #[cfg_attr(not(target_arch = "wasm32"), test)] diff --git a/vendor/packed_simd/src/api/minimal/mask.rs b/vendor/packed_simd_2/src/api/minimal/mask.rs similarity index 95% rename from vendor/packed_simd/src/api/minimal/mask.rs rename to vendor/packed_simd_2/src/api/minimal/mask.rs index 18ca5b24f9..a420060b42 100644 --- a/vendor/packed_simd/src/api/minimal/mask.rs +++ b/vendor/packed_simd_2/src/api/minimal/mask.rs @@ -16,16 +16,14 @@ macro_rules! impl_minimal_mask { /// Creates a new instance with each vector elements initialized /// with the provided values. #[inline] - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::too_many_arguments))] + #[allow(clippy::too_many_arguments)] pub const fn new($($elem_name: bool),*) -> Self { Simd(codegen::$id($(Self::bool_to_internal($elem_name)),*)) } /// Converts a boolean type into the type of the vector lanes. #[inline] - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::indexing_slicing))] + #[allow(clippy::indexing_slicing)] const fn bool_to_internal(x: bool) -> $ielem_ty { [0 as $ielem_ty, !(0 as $ielem_ty)][x as usize] } @@ -60,6 +58,8 @@ macro_rules! impl_minimal_mask { /// Extracts the value at `index`. /// + /// # Safety + /// /// If `index >= Self::lanes()` the behavior is undefined. #[inline] pub unsafe fn extract_unchecked(self, index: usize) -> bool { @@ -87,9 +87,9 @@ macro_rules! impl_minimal_mask { /// Returns a new vector where the value at `index` is replaced by /// `new_value`. /// - /// # Panics + /// # Safety /// - /// If `index >= Self::lanes()`. + /// If `index >= Self::lanes()` the behavior is undefined. #[inline] #[must_use = "replace_unchecked does not modify the original value - \ it returns a new vector with the value at `index` \ diff --git a/vendor/packed_simd/src/api/minimal/ptr.rs b/vendor/packed_simd_2/src/api/minimal/ptr.rs similarity index 97% rename from vendor/packed_simd/src/api/minimal/ptr.rs rename to vendor/packed_simd_2/src/api/minimal/ptr.rs index 38b8a73c91..c3d61fbf6d 100644 --- a/vendor/packed_simd/src/api/minimal/ptr.rs +++ b/vendor/packed_simd_2/src/api/minimal/ptr.rs @@ -19,8 +19,7 @@ macro_rules! impl_minimal_p { /// Creates a new instance with each vector elements initialized /// with the provided values. #[inline] - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::too_many_arguments))] + #[allow(clippy::too_many_arguments)] pub const fn new($($elem_name: $elem_ty),*) -> Self { Simd(codegen::$id($($elem_name),*)) } @@ -69,7 +68,7 @@ macro_rules! impl_minimal_p { /// Extracts the value at `index`. /// - /// # Precondition + /// # Safety /// /// If `index >= Self::lanes()` the behavior is undefined. #[inline] @@ -89,8 +88,7 @@ macro_rules! impl_minimal_p { it returns a new vector with the value at `index` \ replaced by `new_value`d" ] - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::not_unsafe_ptr_arg_deref))] + #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn replace(self, index: usize, new_value: $elem_ty) -> Self { assert!(index < $elem_count); unsafe { self.replace_unchecked(index, new_value) } @@ -98,7 +96,7 @@ macro_rules! impl_minimal_p { /// Returns a new vector where the value at `index` is replaced by `new_value`. /// - /// # Precondition + /// # Safety /// /// If `index >= Self::lanes()` the behavior is undefined. #[inline] @@ -210,15 +208,14 @@ macro_rules! impl_minimal_p { } impl crate::fmt::Debug for $id { - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::missing_inline_in_public_items))] + #[allow(clippy::missing_inline_in_public_items)] fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { write!( f, "{}<{}>(", stringify!($id), - unsafe { crate::intrinsics::type_name::() } + crate::intrinsics::type_name::() )?; for i in 0..$elem_count { if i > 0 { @@ -424,7 +421,7 @@ macro_rules! impl_minimal_p { } } - #[cfg_attr(feature = "cargo-clippy", allow(clippy::partialeq_ne_impl))] + #[allow(clippy::partialeq_ne_impl)] impl crate::cmp::PartialEq<$id> for $id { #[inline] fn eq(&self, other: &Self) -> bool { @@ -437,7 +434,7 @@ macro_rules! impl_minimal_p { } // FIXME: https://github.com/rust-lang-nursery/rust-clippy/issues/2892 - #[cfg_attr(feature = "cargo-clippy", allow(clippy::partialeq_ne_impl))] + #[allow(clippy::partialeq_ne_impl)] impl crate::cmp::PartialEq>> for LexicographicallyOrdered<$id> { @@ -553,11 +550,7 @@ macro_rules! impl_minimal_p { ]; for i in 0..$elem_count { - let ptr = unsafe { - crate::mem::transmute( - &values[i] as *const i32 - ) - }; + let ptr = &values[i] as *const i32 as *mut i32; vec = vec.replace(i, ptr); array[i] = ptr; } @@ -614,21 +607,20 @@ macro_rules! impl_minimal_p { /// Instantiates a new vector with the values of the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned /// to an `align_of::()` boundary, the behavior is undefined. #[inline] pub unsafe fn from_slice_aligned_unchecked(slice: &[$elem_ty]) -> Self { - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::cast_ptr_alignment))] + #[allow(clippy::cast_ptr_alignment)] *(slice.get_unchecked(0) as *const $elem_ty as *const Self) } /// Instantiates a new vector with the values of the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` the behavior is undefined. #[inline] @@ -831,7 +823,7 @@ macro_rules! impl_minimal_p { /// Writes the values of the vector to the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` or `&slice[0]` is not /// aligned to an `align_of::()` boundary, the behavior is @@ -840,15 +832,14 @@ macro_rules! impl_minimal_p { pub unsafe fn write_to_slice_aligned_unchecked( self, slice: &mut [$elem_ty], ) { - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::cast_ptr_alignment))] + #[allow(clippy::cast_ptr_alignment)] *(slice.get_unchecked_mut(0) as *mut $elem_ty as *mut Self) = self; } /// Writes the values of the vector to the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` the behavior is undefined. #[inline] @@ -1030,11 +1021,7 @@ macro_rules! impl_minimal_p { ]; for i in 0..$elem_count { - let ptr = unsafe { - crate::mem::transmute( - &values[i] as *const i32 - ) - }; + let ptr = &values[i] as *const i32 as *mut i32; vec = vec.replace(i, ptr); array[i] = ptr; } @@ -1156,7 +1143,7 @@ macro_rules! impl_minimal_p { /// As such, memory acquired directly from allocators or memory /// mapped files may be too large to handle with this function. /// - /// Consider using wrapping_offset_from instead if these constraints + /// Consider using `wrapping_offset_from` instead if these constraints /// are difficult to satisfy. The only advantage of this method is /// that it enables more aggressive compiler optimizations. #[inline] @@ -1225,8 +1212,7 @@ macro_rules! impl_minimal_p { /// are difficult to satisfy. The only advantage of this method is /// that it enables more aggressive compiler optimizations. #[inline] - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::should_implement_trait))] + #[allow(clippy::should_implement_trait)] pub unsafe fn add(self, count: $usize_ty) -> Self { self.offset(count.cast()) } @@ -1271,8 +1257,7 @@ macro_rules! impl_minimal_p { /// are difficult to satisfy. The only advantage of this method is /// that it enables more aggressive compiler optimizations. #[inline] - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::should_implement_trait))] + #[allow(clippy::should_implement_trait)] pub unsafe fn sub(self, count: $usize_ty) -> Self { let x: $isize_ty = count.cast(); // note: - is currently wrapping_neg diff --git a/vendor/packed_simd/src/api/ops.rs b/vendor/packed_simd_2/src/api/ops.rs similarity index 100% rename from vendor/packed_simd/src/api/ops.rs rename to vendor/packed_simd_2/src/api/ops.rs diff --git a/vendor/packed_simd/src/api/ops/scalar_arithmetic.rs b/vendor/packed_simd_2/src/api/ops/scalar_arithmetic.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/scalar_arithmetic.rs rename to vendor/packed_simd_2/src/api/ops/scalar_arithmetic.rs diff --git a/vendor/packed_simd/src/api/ops/scalar_bitwise.rs b/vendor/packed_simd_2/src/api/ops/scalar_bitwise.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/scalar_bitwise.rs rename to vendor/packed_simd_2/src/api/ops/scalar_bitwise.rs diff --git a/vendor/packed_simd/src/api/ops/scalar_mask_bitwise.rs b/vendor/packed_simd_2/src/api/ops/scalar_mask_bitwise.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/scalar_mask_bitwise.rs rename to vendor/packed_simd_2/src/api/ops/scalar_mask_bitwise.rs diff --git a/vendor/packed_simd/src/api/ops/scalar_shifts.rs b/vendor/packed_simd_2/src/api/ops/scalar_shifts.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/scalar_shifts.rs rename to vendor/packed_simd_2/src/api/ops/scalar_shifts.rs diff --git a/vendor/packed_simd/src/api/ops/vector_arithmetic.rs b/vendor/packed_simd_2/src/api/ops/vector_arithmetic.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/vector_arithmetic.rs rename to vendor/packed_simd_2/src/api/ops/vector_arithmetic.rs diff --git a/vendor/packed_simd/src/api/ops/vector_bitwise.rs b/vendor/packed_simd_2/src/api/ops/vector_bitwise.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/vector_bitwise.rs rename to vendor/packed_simd_2/src/api/ops/vector_bitwise.rs diff --git a/vendor/packed_simd/src/api/ops/vector_float_min_max.rs b/vendor/packed_simd_2/src/api/ops/vector_float_min_max.rs similarity index 91% rename from vendor/packed_simd/src/api/ops/vector_float_min_max.rs rename to vendor/packed_simd_2/src/api/ops/vector_float_min_max.rs index 4126e87042..8310667b7a 100644 --- a/vendor/packed_simd/src/api/ops/vector_float_min_max.rs +++ b/vendor/packed_simd_2/src/api/ops/vector_float_min_max.rs @@ -26,6 +26,11 @@ macro_rules! impl_ops_vector_float_min_max { test_if!{ $test_tt: paste::item! { + #[cfg(not(any( + // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/223 + all(target_arch = "mips", target_endian = "big"), + target_arch = "mips64", + )))] pub mod [<$id _ops_vector_min_max>] { use super::*; #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] diff --git a/vendor/packed_simd/src/api/ops/vector_int_min_max.rs b/vendor/packed_simd_2/src/api/ops/vector_int_min_max.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/vector_int_min_max.rs rename to vendor/packed_simd_2/src/api/ops/vector_int_min_max.rs diff --git a/vendor/packed_simd/src/api/ops/vector_mask_bitwise.rs b/vendor/packed_simd_2/src/api/ops/vector_mask_bitwise.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/vector_mask_bitwise.rs rename to vendor/packed_simd_2/src/api/ops/vector_mask_bitwise.rs diff --git a/vendor/packed_simd/src/api/ops/vector_neg.rs b/vendor/packed_simd_2/src/api/ops/vector_neg.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/vector_neg.rs rename to vendor/packed_simd_2/src/api/ops/vector_neg.rs diff --git a/vendor/packed_simd/src/api/ops/vector_rotates.rs b/vendor/packed_simd_2/src/api/ops/vector_rotates.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/vector_rotates.rs rename to vendor/packed_simd_2/src/api/ops/vector_rotates.rs diff --git a/vendor/packed_simd/src/api/ops/vector_shifts.rs b/vendor/packed_simd_2/src/api/ops/vector_shifts.rs similarity index 100% rename from vendor/packed_simd/src/api/ops/vector_shifts.rs rename to vendor/packed_simd_2/src/api/ops/vector_shifts.rs diff --git a/vendor/packed_simd/src/api/ptr.rs b/vendor/packed_simd_2/src/api/ptr.rs similarity index 100% rename from vendor/packed_simd/src/api/ptr.rs rename to vendor/packed_simd_2/src/api/ptr.rs diff --git a/vendor/packed_simd/src/api/ptr/gather_scatter.rs b/vendor/packed_simd_2/src/api/ptr/gather_scatter.rs similarity index 85% rename from vendor/packed_simd/src/api/ptr/gather_scatter.rs rename to vendor/packed_simd_2/src/api/ptr/gather_scatter.rs index 9d8e113bb4..4304356209 100644 --- a/vendor/packed_simd/src/api/ptr/gather_scatter.rs +++ b/vendor/packed_simd_2/src/api/ptr/gather_scatter.rs @@ -49,9 +49,9 @@ macro_rules! impl_ptr_read { let mut ptr = $id::::null(); for i in 0..$elem_count { - ptr = ptr.replace(i, unsafe { - crate::mem::transmute(&v[i] as *const i32) - }); + ptr = ptr.replace(i, + &v[i] as *const i32 as *mut i32 + ); } // all mask elements are true: @@ -135,32 +135,8 @@ macro_rules! impl_ptr_write { M: sealed::Mask, [M; $elem_count]: sealed::SimdArray, { - // FIXME: - // https://github.com/rust-lang-nursery/packed_simd/issues/85 - #[cfg(not(target_arch = "mips"))] - { - use crate::llvm::simd_scatter; - simd_scatter(value.0, self.0, mask.0) - } - #[cfg(target_arch = "mips")] - { - let m_ptr = - &mask as *const Simd<[M; $elem_count]> as *const M; - for i in 0..$elem_count { - let m = ptr::read(m_ptr.add(i)); - if m.test() { - let t_ptr = &self - as *const Simd<[*mut T; $elem_count]> - as *mut *mut T; - let v_ptr = &value as *const Simd<[T; $elem_count]> - as *const T; - ptr::write( - ptr::read(t_ptr.add(i)), - ptr::read(v_ptr.add(i)), - ); - } - } - } + use crate::llvm::simd_scatter; + simd_scatter(value.0, self.0, mask.0) } } @@ -185,7 +161,7 @@ macro_rules! impl_ptr_write { let mut ptr = $id::::null(); for i in 0..$elem_count { ptr = ptr.replace(i, unsafe { - crate::mem::transmute(arr.as_ptr().add(i)) + arr.as_ptr().add(i) as *mut i32 }); } // ptr = [&arr[0], &arr[1], ...] diff --git a/vendor/packed_simd/src/api/reductions.rs b/vendor/packed_simd_2/src/api/reductions.rs similarity index 100% rename from vendor/packed_simd/src/api/reductions.rs rename to vendor/packed_simd_2/src/api/reductions.rs diff --git a/vendor/packed_simd/src/api/reductions/bitwise.rs b/vendor/packed_simd_2/src/api/reductions/bitwise.rs similarity index 100% rename from vendor/packed_simd/src/api/reductions/bitwise.rs rename to vendor/packed_simd_2/src/api/reductions/bitwise.rs diff --git a/vendor/packed_simd/src/api/reductions/float_arithmetic.rs b/vendor/packed_simd_2/src/api/reductions/float_arithmetic.rs similarity index 95% rename from vendor/packed_simd/src/api/reductions/float_arithmetic.rs rename to vendor/packed_simd_2/src/api/reductions/float_arithmetic.rs index dd722ae25f..4a47452e50 100644 --- a/vendor/packed_simd/src/api/reductions/float_arithmetic.rs +++ b/vendor/packed_simd_2/src/api/reductions/float_arithmetic.rs @@ -93,6 +93,8 @@ macro_rules! impl_reduction_float_arithmetic { test_if! { $test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] pub mod [<$id _reduction_float_arith>] { use super::*; fn alternating(x: usize) -> $id { @@ -225,7 +227,7 @@ macro_rules! impl_reduction_float_arithmetic { let mut v = $id::splat(0. as $elem_ty); for i in 0..$id::lanes() { let c = if i % 2 == 0 { 1e3 } else { -1. }; - start *= 3.14 * c; + start *= ::core::$elem_ty::consts::PI * c; scalar_reduction += start; v = v.replace(i, start); } @@ -257,6 +259,7 @@ macro_rules! impl_reduction_float_arithmetic { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] #[allow(unused, dead_code)] fn product_roundoff() { + use ::core::convert::TryInto; // Performs a tree-reduction fn tree_reduce_product(a: &[$elem_ty]) -> $elem_ty { assert!(!a.is_empty()); @@ -278,7 +281,7 @@ macro_rules! impl_reduction_float_arithmetic { let mut v = $id::splat(0. as $elem_ty); for i in 0..$id::lanes() { let c = if i % 2 == 0 { 1e3 } else { -1. }; - start *= 3.14 * c; + start *= ::core::$elem_ty::consts::PI * c; scalar_reduction *= start; v = v.replace(i, start); } @@ -288,7 +291,9 @@ macro_rules! impl_reduction_float_arithmetic { v.write_to_slice_unaligned(&mut a); let tree_reduction = tree_reduce_product(&a); - // tolerate 1 ULP difference: + // FIXME: Too imprecise, even only for product(f32x8). + // Figure out how to narrow this down. + let ulp_limit = $id::lanes() / 2; let red_bits = simd_reduction.to_bits(); let tree_bits = tree_reduction.to_bits(); assert!( @@ -296,7 +301,7 @@ macro_rules! impl_reduction_float_arithmetic { red_bits - tree_bits } else { tree_bits - red_bits - } < 2, + } < ulp_limit.try_into().unwrap(), "vector: {:?} | simd_reduction: {:?} | \ tree_reduction: {} | scalar_reduction: {}", v, diff --git a/vendor/packed_simd/src/api/reductions/integer_arithmetic.rs b/vendor/packed_simd_2/src/api/reductions/integer_arithmetic.rs similarity index 100% rename from vendor/packed_simd/src/api/reductions/integer_arithmetic.rs rename to vendor/packed_simd_2/src/api/reductions/integer_arithmetic.rs diff --git a/vendor/packed_simd/src/api/reductions/mask.rs b/vendor/packed_simd_2/src/api/reductions/mask.rs similarity index 92% rename from vendor/packed_simd/src/api/reductions/mask.rs rename to vendor/packed_simd_2/src/api/reductions/mask.rs index 13d7130670..0dd6a84e7e 100644 --- a/vendor/packed_simd/src/api/reductions/mask.rs +++ b/vendor/packed_simd_2/src/api/reductions/mask.rs @@ -20,12 +20,13 @@ macro_rules! impl_reduction_mask { } } - test_if!{ + test_if! { $test_tt: paste::item! { pub mod [<$id _reduction>] { use super::*; - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn all() { let a = $id::splat(true); assert!(a.all()); @@ -43,7 +44,8 @@ macro_rules! impl_reduction_mask { } } } - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn any() { let a = $id::splat(true); assert!(a.any()); @@ -61,7 +63,8 @@ macro_rules! impl_reduction_mask { } } } - #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg_attr(not(target_arch = "wasm32"), test)] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn none() { let a = $id::splat(true); assert!(!a.none()); diff --git a/vendor/packed_simd/src/api/reductions/min_max.rs b/vendor/packed_simd_2/src/api/reductions/min_max.rs similarity index 98% rename from vendor/packed_simd/src/api/reductions/min_max.rs rename to vendor/packed_simd_2/src/api/reductions/min_max.rs index c4d3aa10f1..c4c1400a8f 100644 --- a/vendor/packed_simd/src/api/reductions/min_max.rs +++ b/vendor/packed_simd_2/src/api/reductions/min_max.rs @@ -76,6 +76,8 @@ macro_rules! impl_reduction_min_max { } test_if! {$test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] pub mod [<$id _reduction_min_max>] { use super::*; #[cfg_attr(not(target_arch = "wasm32"), test)] @@ -124,6 +126,8 @@ macro_rules! test_reduction_float_min_max { test_if!{ $test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] pub mod [<$id _reduction_min_max_nan>] { use super::*; #[cfg_attr(not(target_arch = "wasm32"), test)] diff --git a/vendor/packed_simd/src/api/select.rs b/vendor/packed_simd_2/src/api/select.rs similarity index 100% rename from vendor/packed_simd/src/api/select.rs rename to vendor/packed_simd_2/src/api/select.rs diff --git a/vendor/packed_simd/src/api/shuffle.rs b/vendor/packed_simd_2/src/api/shuffle.rs similarity index 100% rename from vendor/packed_simd/src/api/shuffle.rs rename to vendor/packed_simd_2/src/api/shuffle.rs diff --git a/vendor/packed_simd/src/api/shuffle1_dyn.rs b/vendor/packed_simd_2/src/api/shuffle1_dyn.rs similarity index 100% rename from vendor/packed_simd/src/api/shuffle1_dyn.rs rename to vendor/packed_simd_2/src/api/shuffle1_dyn.rs diff --git a/vendor/packed_simd/src/api/slice.rs b/vendor/packed_simd_2/src/api/slice.rs similarity index 100% rename from vendor/packed_simd/src/api/slice.rs rename to vendor/packed_simd_2/src/api/slice.rs diff --git a/vendor/packed_simd/src/api/slice/from_slice.rs b/vendor/packed_simd_2/src/api/slice/from_slice.rs similarity index 97% rename from vendor/packed_simd/src/api/slice/from_slice.rs rename to vendor/packed_simd_2/src/api/slice/from_slice.rs index ca83c7df75..25082d1e68 100644 --- a/vendor/packed_simd/src/api/slice/from_slice.rs +++ b/vendor/packed_simd_2/src/api/slice/from_slice.rs @@ -38,7 +38,7 @@ macro_rules! impl_slice_from_slice { /// Instantiates a new vector with the values of the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned /// to an `align_of::()` boundary, the behavior is undefined. @@ -53,16 +53,13 @@ macro_rules! impl_slice_from_slice { 0 ); - #[cfg_attr( - feature = "cargo-clippy", - allow(clippy::cast_ptr_alignment) - )] + #[allow(clippy::cast_ptr_alignment)] *(target_ptr as *const Self) } /// Instantiates a new vector with the values of the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` the behavior is undefined. #[inline] @@ -87,6 +84,8 @@ macro_rules! impl_slice_from_slice { test_if! { $test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] pub mod [<$id _slice_from_slice>] { use super::*; use crate::iter::Iterator; diff --git a/vendor/packed_simd/src/api/slice/write_to_slice.rs b/vendor/packed_simd_2/src/api/slice/write_to_slice.rs similarity index 92% rename from vendor/packed_simd/src/api/slice/write_to_slice.rs rename to vendor/packed_simd_2/src/api/slice/write_to_slice.rs index becb564d41..b634d98b99 100644 --- a/vendor/packed_simd/src/api/slice/write_to_slice.rs +++ b/vendor/packed_simd_2/src/api/slice/write_to_slice.rs @@ -39,7 +39,7 @@ macro_rules! impl_slice_write_to_slice { /// Writes the values of the vector to the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` or `&slice[0]` is not /// aligned to an `align_of::()` boundary, the behavior is @@ -55,26 +55,16 @@ macro_rules! impl_slice_write_to_slice { 0 ); - #[cfg_attr(feature = "cargo-clippy", - allow(clippy::cast_ptr_alignment))] - #[cfg_attr( - feature = "cargo-clippy", - allow(clippy::cast_ptr_alignment) - )] - #[cfg_attr( - feature = "cargo-clippy", - allow(clippy::cast_ptr_alignment) - )] - #[cfg_attr( - feature = "cargo-clippy", - allow(clippy::cast_ptr_alignment) - )] + #[allow(clippy::cast_ptr_alignment)] + #[allow(clippy::cast_ptr_alignment)] + #[allow(clippy::cast_ptr_alignment)] + #[allow(clippy::cast_ptr_alignment)] *(target_ptr as *mut Self) = self; } /// Writes the values of the vector to the `slice`. /// - /// # Precondition + /// # Safety /// /// If `slice.len() < Self::lanes()` the behavior is undefined. #[inline] @@ -96,6 +86,8 @@ macro_rules! impl_slice_write_to_slice { test_if! { $test_tt: paste::item! { + // Comparisons use integer casts within mantissa^1 range. + #[allow(clippy::float_cmp)] pub mod [<$id _slice_write_to_slice>] { use super::*; use crate::iter::Iterator; diff --git a/vendor/packed_simd/src/api/swap_bytes.rs b/vendor/packed_simd_2/src/api/swap_bytes.rs similarity index 100% rename from vendor/packed_simd/src/api/swap_bytes.rs rename to vendor/packed_simd_2/src/api/swap_bytes.rs diff --git a/vendor/packed_simd/src/codegen.rs b/vendor/packed_simd_2/src/codegen.rs similarity index 91% rename from vendor/packed_simd/src/codegen.rs rename to vendor/packed_simd_2/src/codegen.rs index b7ccd83860..9d1517e203 100644 --- a/vendor/packed_simd/src/codegen.rs +++ b/vendor/packed_simd_2/src/codegen.rs @@ -16,6 +16,8 @@ macro_rules! impl_simd_array { pub struct $tuple_id($(crate $elem_tys),*); //^^^^^^^ leaked through SimdArray + impl crate::sealed::Seal for [$elem_ty; $elem_count] {} + impl crate::sealed::SimdArray for [$elem_ty; $elem_count] { type Tuple = $tuple_id; type T = $elem_ty; @@ -23,6 +25,7 @@ macro_rules! impl_simd_array { type NT = [u32; $elem_count]; } + impl crate::sealed::Seal for $tuple_id {} impl crate::sealed::Simd for $tuple_id { type Element = $elem_ty; const LANES: usize = $elem_count; diff --git a/vendor/packed_simd/src/codegen/bit_manip.rs b/vendor/packed_simd_2/src/codegen/bit_manip.rs similarity index 99% rename from vendor/packed_simd/src/codegen/bit_manip.rs rename to vendor/packed_simd_2/src/codegen/bit_manip.rs index 947266f5bc..83c7d1987c 100644 --- a/vendor/packed_simd/src/codegen/bit_manip.rs +++ b/vendor/packed_simd_2/src/codegen/bit_manip.rs @@ -1,5 +1,5 @@ //! LLVM bit manipulation intrinsics. -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/codegen/llvm.rs b/vendor/packed_simd_2/src/codegen/llvm.rs similarity index 94% rename from vendor/packed_simd/src/codegen/llvm.rs rename to vendor/packed_simd_2/src/codegen/llvm.rs index 6ee30c590f..93c6ce6b77 100644 --- a/vendor/packed_simd/src/codegen/llvm.rs +++ b/vendor/packed_simd_2/src/codegen/llvm.rs @@ -10,31 +10,37 @@ extern "platform-intrinsic" { // FIXME: Passing this intrinsics an `idx` array with an index that is // out-of-bounds will produce a monomorphization-time error. // https://github.com/rust-lang-nursery/packed_simd/issues/21 + #[rustc_args_required_const(2)] pub fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U where T: Simd, ::Element: Shuffle<[u32; 2], Output = U>; + #[rustc_args_required_const(2)] pub fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U where T: Simd, ::Element: Shuffle<[u32; 4], Output = U>; + #[rustc_args_required_const(2)] pub fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U where T: Simd, ::Element: Shuffle<[u32; 8], Output = U>; + #[rustc_args_required_const(2)] pub fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U where T: Simd, ::Element: Shuffle<[u32; 16], Output = U>; + #[rustc_args_required_const(2)] pub fn simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U where T: Simd, ::Element: Shuffle<[u32; 32], Output = U>; + #[rustc_args_required_const(2)] pub fn simd_shuffle64(x: T, y: T, idx: [u32; 64]) -> U where T: Simd, diff --git a/vendor/packed_simd/src/codegen/math.rs b/vendor/packed_simd_2/src/codegen/math.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math.rs rename to vendor/packed_simd_2/src/codegen/math.rs diff --git a/vendor/packed_simd/src/codegen/math/float.rs b/vendor/packed_simd_2/src/codegen/math/float.rs similarity index 80% rename from vendor/packed_simd/src/codegen/math/float.rs rename to vendor/packed_simd_2/src/codegen/math/float.rs index 02a2bea08e..3743b49908 100644 --- a/vendor/packed_simd/src/codegen/math/float.rs +++ b/vendor/packed_simd_2/src/codegen/math/float.rs @@ -1,5 +1,5 @@ //! Vertical floating-point math operations. -#![cfg_attr(feature = "cargo-clippy", allow(clippy::useless_transmute))] +#![allow(clippy::useless_transmute)] #[macro_use] crate mod macros; @@ -16,3 +16,4 @@ crate mod sin_cos_pi; crate mod sin_pi; crate mod sqrt; crate mod sqrte; +crate mod tanh; diff --git a/vendor/packed_simd/src/codegen/math/float/abs.rs b/vendor/packed_simd_2/src/codegen/math/float/abs.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/abs.rs rename to vendor/packed_simd_2/src/codegen/math/float/abs.rs diff --git a/vendor/packed_simd/src/codegen/math/float/cos.rs b/vendor/packed_simd_2/src/codegen/math/float/cos.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/cos.rs rename to vendor/packed_simd_2/src/codegen/math/float/cos.rs diff --git a/vendor/packed_simd/src/codegen/math/float/cos_pi.rs b/vendor/packed_simd_2/src/codegen/math/float/cos_pi.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/cos_pi.rs rename to vendor/packed_simd_2/src/codegen/math/float/cos_pi.rs diff --git a/vendor/packed_simd/src/codegen/math/float/exp.rs b/vendor/packed_simd_2/src/codegen/math/float/exp.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/exp.rs rename to vendor/packed_simd_2/src/codegen/math/float/exp.rs diff --git a/vendor/packed_simd/src/codegen/math/float/ln.rs b/vendor/packed_simd_2/src/codegen/math/float/ln.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/ln.rs rename to vendor/packed_simd_2/src/codegen/math/float/ln.rs diff --git a/vendor/packed_simd/src/codegen/math/float/macros.rs b/vendor/packed_simd_2/src/codegen/math/float/macros.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/macros.rs rename to vendor/packed_simd_2/src/codegen/math/float/macros.rs diff --git a/vendor/packed_simd/src/codegen/math/float/mul_add.rs b/vendor/packed_simd_2/src/codegen/math/float/mul_add.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/mul_add.rs rename to vendor/packed_simd_2/src/codegen/math/float/mul_add.rs diff --git a/vendor/packed_simd/src/codegen/math/float/mul_adde.rs b/vendor/packed_simd_2/src/codegen/math/float/mul_adde.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/mul_adde.rs rename to vendor/packed_simd_2/src/codegen/math/float/mul_adde.rs diff --git a/vendor/packed_simd/src/codegen/math/float/powf.rs b/vendor/packed_simd_2/src/codegen/math/float/powf.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/powf.rs rename to vendor/packed_simd_2/src/codegen/math/float/powf.rs diff --git a/vendor/packed_simd/src/codegen/math/float/sin.rs b/vendor/packed_simd_2/src/codegen/math/float/sin.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/sin.rs rename to vendor/packed_simd_2/src/codegen/math/float/sin.rs diff --git a/vendor/packed_simd/src/codegen/math/float/sin_cos_pi.rs b/vendor/packed_simd_2/src/codegen/math/float/sin_cos_pi.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/sin_cos_pi.rs rename to vendor/packed_simd_2/src/codegen/math/float/sin_cos_pi.rs diff --git a/vendor/packed_simd/src/codegen/math/float/sin_pi.rs b/vendor/packed_simd_2/src/codegen/math/float/sin_pi.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/sin_pi.rs rename to vendor/packed_simd_2/src/codegen/math/float/sin_pi.rs diff --git a/vendor/packed_simd/src/codegen/math/float/sqrt.rs b/vendor/packed_simd_2/src/codegen/math/float/sqrt.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/sqrt.rs rename to vendor/packed_simd_2/src/codegen/math/float/sqrt.rs diff --git a/vendor/packed_simd/src/codegen/math/float/sqrte.rs b/vendor/packed_simd_2/src/codegen/math/float/sqrte.rs similarity index 100% rename from vendor/packed_simd/src/codegen/math/float/sqrte.rs rename to vendor/packed_simd_2/src/codegen/math/float/sqrte.rs diff --git a/vendor/packed_simd_2/src/codegen/math/float/tanh.rs b/vendor/packed_simd_2/src/codegen/math/float/tanh.rs new file mode 100644 index 0000000000..5220c7d10a --- /dev/null +++ b/vendor/packed_simd_2/src/codegen/math/float/tanh.rs @@ -0,0 +1,117 @@ +//! Vertical floating-point `tanh` +#![allow(unused)] + +// FIXME 64-bit 1 elem vectors tanh + +use crate::*; + +crate trait Tanh { + fn tanh(self) -> Self; +} + +macro_rules! define_tanh { + + ($name:ident, $basetype:ty, $simdtype:ty, $lanes:expr, $trait:path) => { + fn $name(x: $simdtype) -> $simdtype { + use core::intrinsics::transmute; + let mut buf: [$basetype; $lanes] = unsafe { transmute(x) }; + for elem in &mut buf { + *elem = <$basetype as $trait>::tanh(*elem); + } + unsafe { transmute(buf) } + } + }; + + (f32 => $name:ident, $type:ty, $lanes:expr) => { + define_tanh!($name, f32, $type, $lanes, libm::F32Ext); + }; + + (f64 => $name:ident, $type:ty, $lanes:expr) => { + define_tanh!($name, f64, $type, $lanes, libm::F64Ext); + }; +} + +// llvm does not seem to expose the hyperbolic versions of trigonometric functions; +// we thus call the classical rust versions on all of them (which stem from cmath). +define_tanh!(f32 => tanh_v2f32, f32x2, 2); +define_tanh!(f32 => tanh_v4f32, f32x4, 4); +define_tanh!(f32 => tanh_v8f32, f32x8, 8); +define_tanh!(f32 => tanh_v16f32, f32x16, 16); + +define_tanh!(f64 => tanh_v2f64, f64x2, 2); +define_tanh!(f64 => tanh_v4f64, f64x4, 4); +define_tanh!(f64 => tanh_v8f64, f64x8, 8); + +fn tanh_f32(x: f32) -> f32 { + libm::F32Ext::tanh(x) +} + +fn tanh_f64(x: f64) -> f64 { + libm::F64Ext::tanh(x) +} + +gen_unary_impl_table!(Tanh, tanh); + +cfg_if! { + if #[cfg(target_arch = "s390x")] { + // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14 + impl_unary!(f32x2[f32; 2]: tanh_f32); + impl_unary!(f32x4[f32; 4]: tanh_f32); + impl_unary!(f32x8[f32; 8]: tanh_f32); + impl_unary!(f32x16[f32; 16]: tanh_f32); + + impl_unary!(f64x2[f64; 2]: tanh_f64); + impl_unary!(f64x4[f64; 4]: tanh_f64); + impl_unary!(f64x8[f64; 8]: tanh_f64); + } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] { + use sleef_sys::*; + cfg_if! { + if #[cfg(target_feature = "avx2")] { + impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10avx2128); + impl_unary!(f32x16[h => f32x8]: Sleef_tanhf8_u10avx2); + impl_unary!(f64x8[h => f64x4]: Sleef_tanhd4_u10avx2); + + impl_unary!(f32x4: Sleef_tanhf4_u10avx2128); + impl_unary!(f32x8: Sleef_tanhf8_u10avx2); + impl_unary!(f64x2: Sleef_tanhd2_u10avx2128); + impl_unary!(f64x4: Sleef_tanhd4_u10avx2); + } else if #[cfg(target_feature = "avx")] { + impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10sse4); + impl_unary!(f32x16[h => f32x8]: Sleef_tanhf8_u10avx); + impl_unary!(f64x8[h => f64x4]: Sleef_tanhd4_u10avx); + + impl_unary!(f32x4: Sleef_tanhf4_u10sse4); + impl_unary!(f32x8: Sleef_tanhf8_u10avx); + impl_unary!(f64x2: Sleef_tanhd2_u10sse4); + impl_unary!(f64x4: Sleef_tanhd4_u10avx); + } else if #[cfg(target_feature = "sse4.2")] { + impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10sse4); + impl_unary!(f32x16[q => f32x4]: Sleef_tanhf4_u10sse4); + impl_unary!(f64x8[q => f64x2]: Sleef_tanhd2_u10sse4); + + impl_unary!(f32x4: Sleef_tanhf4_u10sse4); + impl_unary!(f32x8[h => f32x4]: Sleef_tanhf4_u10sse4); + impl_unary!(f64x2: Sleef_tanhd2_u10sse4); + impl_unary!(f64x4[h => f64x2]: Sleef_tanhd2_u10sse4); + } else { + impl_unary!(f32x2[f32; 2]: tanh_f32); + impl_unary!(f32x16: tanh_v16f32); + impl_unary!(f64x8: tanh_v8f64); + + impl_unary!(f32x4: tanh_v4f32); + impl_unary!(f32x8: tanh_v8f32); + impl_unary!(f64x2: tanh_v2f64); + impl_unary!(f64x4: tanh_v4f64); + } + } + } else { + impl_unary!(f32x2[f32; 2]: tanh_f32); + impl_unary!(f32x4: tanh_v4f32); + impl_unary!(f32x8: tanh_v8f32); + impl_unary!(f32x16: tanh_v16f32); + + impl_unary!(f64x2: tanh_v2f64); + impl_unary!(f64x4: tanh_v4f64); + impl_unary!(f64x8: tanh_v8f64); + } +} diff --git a/vendor/packed_simd/src/codegen/pointer_sized_int.rs b/vendor/packed_simd_2/src/codegen/pointer_sized_int.rs similarity index 100% rename from vendor/packed_simd/src/codegen/pointer_sized_int.rs rename to vendor/packed_simd_2/src/codegen/pointer_sized_int.rs diff --git a/vendor/packed_simd/src/codegen/reductions.rs b/vendor/packed_simd_2/src/codegen/reductions.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions.rs rename to vendor/packed_simd_2/src/codegen/reductions.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask.rs b/vendor/packed_simd_2/src/codegen/reductions/mask.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask/aarch64.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/aarch64.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask/aarch64.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/aarch64.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask/arm.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/arm.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask/arm.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/arm.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask/fallback.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/fallback.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask/fallback.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/fallback.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask/fallback_impl.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/fallback_impl.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask/fallback_impl.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/fallback_impl.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask/x86.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/x86.rs similarity index 95% rename from vendor/packed_simd/src/codegen/reductions/mask/x86.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/x86.rs index 2ae4ed81c4..bcfb1a6e17 100644 --- a/vendor/packed_simd/src/codegen/reductions/mask/x86.rs +++ b/vendor/packed_simd_2/src/codegen/reductions/mask/x86.rs @@ -19,13 +19,7 @@ mod avx2; /// x86 64-bit m8x8 implementation macro_rules! x86_m8x8_impl { ($id:ident) => { - cfg_if! { - if #[cfg(all(target_arch = "x86_64", target_feature = "sse"))] { - x86_m8x8_sse_impl!($id); - } else { - fallback_impl!($id); - } - } + fallback_impl!($id); }; } diff --git a/vendor/packed_simd/src/codegen/reductions/mask/x86/avx.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/x86/avx.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask/x86/avx.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/x86/avx.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask/x86/avx2.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/x86/avx2.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask/x86/avx2.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/x86/avx2.rs diff --git a/vendor/packed_simd/src/codegen/reductions/mask/x86/sse.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/x86/sse.rs similarity index 53% rename from vendor/packed_simd/src/codegen/reductions/mask/x86/sse.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/x86/sse.rs index 7482f9430a..eb1ef7fac9 100644 --- a/vendor/packed_simd/src/codegen/reductions/mask/x86/sse.rs +++ b/vendor/packed_simd_2/src/codegen/reductions/mask/x86/sse.rs @@ -34,35 +34,3 @@ macro_rules! x86_m32x4_sse_impl { } }; } - -macro_rules! x86_m8x8_sse_impl { - ($id:ident) => { - impl All for $id { - #[inline] - #[target_feature(enable = "sse")] - unsafe fn all(self) -> bool { - #[cfg(target_arch = "x86")] - use crate::arch::x86::_mm_movemask_pi8; - #[cfg(target_arch = "x86_64")] - use crate::arch::x86_64::_mm_movemask_pi8; - // _mm_movemask_pi8(a) creates an 8bit mask containing the most - // significant bit of each byte of `a`. If all bits are set, - // then all 8 lanes of the mask are true. - _mm_movemask_pi8(crate::mem::transmute(self)) - == u8::max_value() as i32 - } - } - impl Any for $id { - #[inline] - #[target_feature(enable = "sse")] - unsafe fn any(self) -> bool { - #[cfg(target_arch = "x86")] - use crate::arch::x86::_mm_movemask_pi8; - #[cfg(target_arch = "x86_64")] - use crate::arch::x86_64::_mm_movemask_pi8; - - _mm_movemask_pi8(crate::mem::transmute(self)) != 0 - } - } - }; -} diff --git a/vendor/packed_simd/src/codegen/reductions/mask/x86/sse2.rs b/vendor/packed_simd_2/src/codegen/reductions/mask/x86/sse2.rs similarity index 100% rename from vendor/packed_simd/src/codegen/reductions/mask/x86/sse2.rs rename to vendor/packed_simd_2/src/codegen/reductions/mask/x86/sse2.rs diff --git a/vendor/packed_simd_2/src/codegen/shuffle.rs b/vendor/packed_simd_2/src/codegen/shuffle.rs new file mode 100644 index 0000000000..d92c9ee224 --- /dev/null +++ b/vendor/packed_simd_2/src/codegen/shuffle.rs @@ -0,0 +1,150 @@ +//! Implementations of the `ShuffleResult` trait for the different numbers of +//! lanes and vector element types. + +use crate::masks::*; +use crate::sealed::{Shuffle, Seal}; + +macro_rules! impl_shuffle { + ($array:ty, $base:ty, $out:ty) => { + impl Seal<$array> for $base {} + impl Shuffle<$array> for $base { + type Output = $out; + } + } +} + +impl_shuffle! { [u32; 2], i8, crate::codegen::i8x2 } +impl_shuffle! { [u32; 4], i8, crate::codegen::i8x4 } +impl_shuffle! { [u32; 8], i8, crate::codegen::i8x8 } +impl_shuffle! { [u32; 16], i8, crate::codegen::i8x16 } +impl_shuffle! { [u32; 32], i8, crate::codegen::i8x32 } +impl_shuffle! { [u32; 64], i8, crate::codegen::i8x64 } + +impl_shuffle! { [u32; 2], u8, crate::codegen::u8x2 } +impl_shuffle! { [u32; 4], u8, crate::codegen::u8x4 } +impl_shuffle! { [u32; 8], u8, crate::codegen::u8x8 } +impl_shuffle! { [u32; 16], u8, crate::codegen::u8x16 } +impl_shuffle! { [u32; 32], u8, crate::codegen::u8x32 } +impl_shuffle! { [u32; 64], u8, crate::codegen::u8x64 } + +impl_shuffle! { [u32; 2], m8, crate::codegen::m8x2 } +impl_shuffle! { [u32; 4], m8, crate::codegen::m8x4 } +impl_shuffle! { [u32; 8], m8, crate::codegen::m8x8 } +impl_shuffle! { [u32; 16], m8, crate::codegen::m8x16 } +impl_shuffle! { [u32; 32], m8, crate::codegen::m8x32 } +impl_shuffle! { [u32; 64], m8, crate::codegen::m8x64 } + +impl_shuffle! { [u32; 2], i16, crate::codegen::i16x2 } +impl_shuffle! { [u32; 4], i16, crate::codegen::i16x4 } +impl_shuffle! { [u32; 8], i16, crate::codegen::i16x8 } +impl_shuffle! { [u32; 16], i16, crate::codegen::i16x16 } +impl_shuffle! { [u32; 32], i16, crate::codegen::i16x32 } + +impl_shuffle! { [u32; 2], u16, crate::codegen::u16x2 } +impl_shuffle! { [u32; 4], u16, crate::codegen::u16x4 } +impl_shuffle! { [u32; 8], u16, crate::codegen::u16x8 } +impl_shuffle! { [u32; 16], u16, crate::codegen::u16x16 } +impl_shuffle! { [u32; 32], u16, crate::codegen::u16x32 } + +impl_shuffle! { [u32; 2], m16, crate::codegen::m16x2 } +impl_shuffle! { [u32; 4], m16, crate::codegen::m16x4 } +impl_shuffle! { [u32; 8], m16, crate::codegen::m16x8 } +impl_shuffle! { [u32; 16], m16, crate::codegen::m16x16 } + +impl_shuffle! { [u32; 2], i32, crate::codegen::i32x2 } +impl_shuffle! { [u32; 4], i32, crate::codegen::i32x4 } +impl_shuffle! { [u32; 8], i32, crate::codegen::i32x8 } +impl_shuffle! { [u32; 16], i32, crate::codegen::i32x16 } + +impl_shuffle! { [u32; 2], u32, crate::codegen::u32x2 } +impl_shuffle! { [u32; 4], u32, crate::codegen::u32x4 } +impl_shuffle! { [u32; 8], u32, crate::codegen::u32x8 } +impl_shuffle! { [u32; 16], u32, crate::codegen::u32x16 } + +impl_shuffle! { [u32; 2], f32, crate::codegen::f32x2 } +impl_shuffle! { [u32; 4], f32, crate::codegen::f32x4 } +impl_shuffle! { [u32; 8], f32, crate::codegen::f32x8 } +impl_shuffle! { [u32; 16], f32, crate::codegen::f32x16 } + +impl_shuffle! { [u32; 2], m32, crate::codegen::m32x2 } +impl_shuffle! { [u32; 4], m32, crate::codegen::m32x4 } +impl_shuffle! { [u32; 8], m32, crate::codegen::m32x8 } +impl_shuffle! { [u32; 16], m32, crate::codegen::m32x16 } + +/* FIXME: 64-bit single element vector +impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 } +*/ +impl_shuffle! { [u32; 2], i64, crate::codegen::i64x2 } +impl_shuffle! { [u32; 4], i64, crate::codegen::i64x4 } +impl_shuffle! { [u32; 8], i64, crate::codegen::i64x8 } + +/* FIXME: 64-bit single element vector +impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 } +*/ +impl_shuffle! { [u32; 2], u64, crate::codegen::u64x2 } +impl_shuffle! { [u32; 4], u64, crate::codegen::u64x4 } +impl_shuffle! { [u32; 8], u64, crate::codegen::u64x8 } + +/* FIXME: 64-bit single element vector +impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 } +*/ +impl_shuffle! { [u32; 2], f64, crate::codegen::f64x2 } +impl_shuffle! { [u32; 4], f64, crate::codegen::f64x4 } +impl_shuffle! { [u32; 8], f64, crate::codegen::f64x8 } + +/* FIXME: 64-bit single element vector +impl_shuffle! { [u32; 1], i64, crate::codegen::i64x1 } +*/ +impl_shuffle! { [u32; 2], m64, crate::codegen::m64x2 } +impl_shuffle! { [u32; 4], m64, crate::codegen::m64x4 } +impl_shuffle! { [u32; 8], m64, crate::codegen::m64x8 } + +impl_shuffle! { [u32; 2], isize, crate::codegen::isizex2 } +impl_shuffle! { [u32; 4], isize, crate::codegen::isizex4 } +impl_shuffle! { [u32; 8], isize, crate::codegen::isizex8 } + +impl_shuffle! { [u32; 2], usize, crate::codegen::usizex2 } +impl_shuffle! { [u32; 4], usize, crate::codegen::usizex4 } +impl_shuffle! { [u32; 8], usize, crate::codegen::usizex8 } + +impl_shuffle! { [u32; 2], msize, crate::codegen::msizex2 } +impl_shuffle! { [u32; 4], msize, crate::codegen::msizex4 } +impl_shuffle! { [u32; 8], msize, crate::codegen::msizex8 } + +impl Seal<[u32; 2]> for *const T {} +impl Shuffle<[u32; 2]> for *const T { + type Output = crate::codegen::cptrx2; +} +impl Seal<[u32; 4]> for *const T {} +impl Shuffle<[u32; 4]> for *const T { + type Output = crate::codegen::cptrx4; +} +impl Seal<[u32; 8]> for *const T {} +impl Shuffle<[u32; 8]> for *const T { + type Output = crate::codegen::cptrx8; +} + +impl Seal<[u32; 2]> for *mut T {} +impl Shuffle<[u32; 2]> for *mut T { + type Output = crate::codegen::mptrx2; +} +impl Seal<[u32; 4]> for *mut T {} +impl Shuffle<[u32; 4]> for *mut T { + type Output = crate::codegen::mptrx4; +} +impl Seal<[u32; 8]> for *mut T {} +impl Shuffle<[u32; 8]> for *mut T { + type Output = crate::codegen::mptrx8; +} + +impl_shuffle! { [u32; 1], i128, crate::codegen::i128x1 } +impl_shuffle! { [u32; 2], i128, crate::codegen::i128x2 } +impl_shuffle! { [u32; 4], i128, crate::codegen::i128x4 } + +impl_shuffle! { [u32; 1], u128, crate::codegen::u128x1 } +impl_shuffle! { [u32; 2], u128, crate::codegen::u128x2 } +impl_shuffle! { [u32; 4], u128, crate::codegen::u128x4 } + +impl_shuffle! { [u32; 1], m128, crate::codegen::m128x1 } +impl_shuffle! { [u32; 2], m128, crate::codegen::m128x2 } +impl_shuffle! { [u32; 4], m128, crate::codegen::m128x4 } diff --git a/vendor/packed_simd/src/codegen/shuffle1_dyn.rs b/vendor/packed_simd_2/src/codegen/shuffle1_dyn.rs similarity index 91% rename from vendor/packed_simd/src/codegen/shuffle1_dyn.rs rename to vendor/packed_simd_2/src/codegen/shuffle1_dyn.rs index 1e9f581637..8d9577b26e 100644 --- a/vendor/packed_simd/src/codegen/shuffle1_dyn.rs +++ b/vendor/packed_simd_2/src/codegen/shuffle1_dyn.rs @@ -28,31 +28,10 @@ macro_rules! impl_fallback { macro_rules! impl_shuffle1_dyn { (u8x8) => { cfg_if! { - if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), - target_feature = "ssse3"))] { - impl Shuffle1Dyn for u8x8 { - type Indices = Self; - #[inline] - fn shuffle1_dyn(self, indices: Self::Indices) -> Self { - #[cfg(target_arch = "x86")] - use crate::arch::x86::_mm_shuffle_pi8; - #[cfg(target_arch = "x86_64")] - use crate::arch::x86_64::_mm_shuffle_pi8; - - unsafe { - crate::mem::transmute( - _mm_shuffle_pi8( - crate::mem::transmute(self.0), - crate::mem::transmute(indices.0) - ) - ) - } - } - } - } else if #[cfg(all( + if #[cfg(all( any( - all(target_aarch = "aarch64", target_feature = "neon"), - all(target_aarch = "arm", target_feature = "v7", + all(target_arch = "aarch64", target_feature = "neon"), + all(target_arch = "arm", target_feature = "v7", target_feature = "neon") ), any(feature = "core_arch", libcore_neon) @@ -62,9 +41,9 @@ macro_rules! impl_shuffle1_dyn { type Indices = Self; #[inline] fn shuffle1_dyn(self, indices: Self::Indices) -> Self { - #[cfg(targt_arch = "aarch64")] + #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::vtbl1_u8; - #[cfg(targt_arch = "arm")] + #[cfg(target_arch = "arm")] use crate::arch::arm::vtbl1_u8; // This is safe because the binary is compiled with @@ -106,7 +85,7 @@ macro_rules! impl_shuffle1_dyn { } } } - } else if #[cfg(all(target_aarch = "aarch64", target_feature = "neon", + } else if #[cfg(all(target_arch = "aarch64", target_feature = "neon", any(feature = "core_arch", libcore_neon)))] { impl Shuffle1Dyn for u8x16 { type Indices = Self; @@ -125,7 +104,7 @@ macro_rules! impl_shuffle1_dyn { } } } - } else if #[cfg(all(target_aarch = "arm", target_feature = "v7", + } else if #[cfg(all(target_arch = "arm", target_feature = "v7", target_feature = "neon", any(feature = "core_arch", libcore_neon)))] { impl Shuffle1Dyn for u8x16 { diff --git a/vendor/packed_simd/src/codegen/swap_bytes.rs b/vendor/packed_simd_2/src/codegen/swap_bytes.rs similarity index 92% rename from vendor/packed_simd/src/codegen/swap_bytes.rs rename to vendor/packed_simd_2/src/codegen/swap_bytes.rs index 15d47f68ef..b435fb5da1 100644 --- a/vendor/packed_simd/src/codegen/swap_bytes.rs +++ b/vendor/packed_simd_2/src/codegen/swap_bytes.rs @@ -24,7 +24,7 @@ macro_rules! impl_swap_bytes { $( impl SwapBytes for $id { #[inline] - #[cfg_attr(feature = "cargo-clippy", allow(clippy::useless_transmute))] + #[allow(clippy::useless_transmute)] fn swap_bytes(self) -> Self { unsafe { let bytes: u8x4 = crate::mem::transmute(self); @@ -39,7 +39,7 @@ macro_rules! impl_swap_bytes { $( impl SwapBytes for $id { #[inline] - #[cfg_attr(feature = "cargo-clippy", allow(clippy::useless_transmute))] + #[allow(clippy::useless_transmute)] fn swap_bytes(self) -> Self { unsafe { let bytes: u8x8 = crate::mem::transmute(self); @@ -56,7 +56,7 @@ macro_rules! impl_swap_bytes { $( impl SwapBytes for $id { #[inline] - #[cfg_attr(feature = "cargo-clippy", allow(clippy::useless_transmute))] + #[allow(clippy::useless_transmute)] fn swap_bytes(self) -> Self { unsafe { let bytes: u8x16 = crate::mem::transmute(self); @@ -74,7 +74,7 @@ macro_rules! impl_swap_bytes { $( impl SwapBytes for $id { #[inline] - #[cfg_attr(feature = "cargo-clippy", allow(clippy::useless_transmute))] + #[allow(clippy::useless_transmute)] fn swap_bytes(self) -> Self { unsafe { let bytes: u8x32 = crate::mem::transmute(self); @@ -94,7 +94,7 @@ macro_rules! impl_swap_bytes { $( impl SwapBytes for $id { #[inline] - #[cfg_attr(feature = "cargo-clippy", allow(clippy::useless_transmute))] + #[allow(clippy::useless_transmute)] fn swap_bytes(self) -> Self { unsafe { let bytes: u8x64 = crate::mem::transmute(self); diff --git a/vendor/packed_simd/src/codegen/v128.rs b/vendor/packed_simd_2/src/codegen/v128.rs similarity index 100% rename from vendor/packed_simd/src/codegen/v128.rs rename to vendor/packed_simd_2/src/codegen/v128.rs diff --git a/vendor/packed_simd/src/codegen/v16.rs b/vendor/packed_simd_2/src/codegen/v16.rs similarity index 100% rename from vendor/packed_simd/src/codegen/v16.rs rename to vendor/packed_simd_2/src/codegen/v16.rs diff --git a/vendor/packed_simd/src/codegen/v256.rs b/vendor/packed_simd_2/src/codegen/v256.rs similarity index 100% rename from vendor/packed_simd/src/codegen/v256.rs rename to vendor/packed_simd_2/src/codegen/v256.rs diff --git a/vendor/packed_simd/src/codegen/v32.rs b/vendor/packed_simd_2/src/codegen/v32.rs similarity index 100% rename from vendor/packed_simd/src/codegen/v32.rs rename to vendor/packed_simd_2/src/codegen/v32.rs diff --git a/vendor/packed_simd/src/codegen/v512.rs b/vendor/packed_simd_2/src/codegen/v512.rs similarity index 100% rename from vendor/packed_simd/src/codegen/v512.rs rename to vendor/packed_simd_2/src/codegen/v512.rs diff --git a/vendor/packed_simd/src/codegen/v64.rs b/vendor/packed_simd_2/src/codegen/v64.rs similarity index 100% rename from vendor/packed_simd/src/codegen/v64.rs rename to vendor/packed_simd_2/src/codegen/v64.rs diff --git a/vendor/packed_simd/src/codegen/vPtr.rs b/vendor/packed_simd_2/src/codegen/vPtr.rs similarity index 89% rename from vendor/packed_simd/src/codegen/vPtr.rs rename to vendor/packed_simd_2/src/codegen/vPtr.rs index 1f2bc7714d..cf47655381 100644 --- a/vendor/packed_simd/src/codegen/vPtr.rs +++ b/vendor/packed_simd_2/src/codegen/vPtr.rs @@ -8,6 +8,7 @@ macro_rules! impl_simd_ptr { pub struct $tuple_id<$ty>($(crate $tys),*); //^^^^^^^ leaked through SimdArray + impl<$ty> crate::sealed::Seal for [$ptr_ty; $elem_count] {} impl<$ty> crate::sealed::SimdArray for [$ptr_ty; $elem_count] { type Tuple = $tuple_id<$ptr_ty>; type T = $ptr_ty; @@ -15,6 +16,7 @@ macro_rules! impl_simd_ptr { type NT = [u32; $elem_count]; } + impl<$ty> crate::sealed::Seal for $tuple_id<$ptr_ty> {} impl<$ty> crate::sealed::Simd for $tuple_id<$ptr_ty> { type Element = $ptr_ty; const LANES: usize = $elem_count; diff --git a/vendor/packed_simd/src/codegen/vSize.rs b/vendor/packed_simd_2/src/codegen/vSize.rs similarity index 100% rename from vendor/packed_simd/src/codegen/vSize.rs rename to vendor/packed_simd_2/src/codegen/vSize.rs diff --git a/vendor/packed_simd/src/lib.rs b/vendor/packed_simd_2/src/lib.rs similarity index 93% rename from vendor/packed_simd/src/lib.rs rename to vendor/packed_simd_2/src/lib.rs index b27e9ace2a..4d12c9cd94 100644 --- a/vendor/packed_simd/src/lib.rs +++ b/vendor/packed_simd_2/src/lib.rs @@ -201,6 +201,7 @@ #![feature( repr_simd, + rustc_attrs, const_fn, platform_intrinsics, stdsimd, @@ -209,30 +210,27 @@ link_llvm_intrinsics, core_intrinsics, stmt_expr_attributes, - align_offset, - mmx_target_feature, crate_visibility_modifier, - custom_inner_attributes + custom_inner_attributes, + llvm_asm )] -#![allow(non_camel_case_types, non_snake_case)] -#![cfg_attr(test, feature(hashmap_internals))] -#![cfg_attr( - feature = "cargo-clippy", - allow( +#![allow(non_camel_case_types, non_snake_case, + // FIXME: these types are unsound in C FFI already + // See https://github.com/rust-lang/rust/issues/53346 + improper_ctypes_definitions, clippy::cast_possible_truncation, clippy::cast_lossless, clippy::cast_possible_wrap, clippy::cast_precision_loss, + // TODO: manually add the `#[must_use]` attribute where appropriate + clippy::must_use_candidate, // This lint is currently broken for generic code // See https://github.com/rust-lang/rust-clippy/issues/3410 - clippy::use_self - ) -)] -#![cfg_attr( - feature = "cargo-clippy", - deny(clippy::missing_inline_in_public_items) + clippy::use_self, + clippy::wrong_self_convention, )] -#![deny(warnings, rust_2018_idioms)] +#![cfg_attr(test, feature(hashmap_internals))] +#![deny(rust_2018_idioms, clippy::missing_inline_in_public_items)] #![no_std] use cfg_if::cfg_if; @@ -264,6 +262,8 @@ mod api; mod codegen; mod sealed; +pub use crate::sealed::{Simd as SimdVector, Shuffle, SimdArray, Mask}; + /// Packed SIMD vector type. /// /// # Examples @@ -284,14 +284,13 @@ pub struct Simd( #[doc(hidden)] pub ::Tuple, ); +impl sealed::Seal for Simd {} + /// Wrapper over `T` implementing a lexicoraphical order via the `PartialOrd` /// and/or `Ord` traits. #[repr(transparent)] #[derive(Copy, Clone, Debug)] -#[cfg_attr( - feature = "cargo-clippy", - allow(clippy::missing_inline_in_public_items) -)] +#[allow(clippy::missing_inline_in_public_items)] pub struct LexicographicallyOrdered(T); mod masks; diff --git a/vendor/packed_simd/src/masks.rs b/vendor/packed_simd_2/src/masks.rs similarity index 96% rename from vendor/packed_simd/src/masks.rs rename to vendor/packed_simd_2/src/masks.rs index 65c15cc5d8..aeb36d2328 100644 --- a/vendor/packed_simd/src/masks.rs +++ b/vendor/packed_simd_2/src/masks.rs @@ -6,7 +6,9 @@ macro_rules! impl_mask_ty { #[derive(Copy, Clone)] pub struct $id($elem_ty); + impl crate::sealed::Seal for $id {} impl crate::sealed::Mask for $id { + #[inline] fn test(&self) -> bool { $id::test(self) } @@ -36,7 +38,7 @@ macro_rules! impl_mask_ty { } } - #[cfg_attr(feature = "cargo-clippy", allow(clippy::partialeq_ne_impl))] + #[allow(clippy::partialeq_ne_impl)] impl PartialEq<$id> for $id { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/vendor/packed_simd/src/sealed.rs b/vendor/packed_simd_2/src/sealed.rs similarity index 77% rename from vendor/packed_simd/src/sealed.rs rename to vendor/packed_simd_2/src/sealed.rs index 832acd3f1d..0ec20300fd 100644 --- a/vendor/packed_simd/src/sealed.rs +++ b/vendor/packed_simd_2/src/sealed.rs @@ -1,8 +1,11 @@ //! Sealed traits +/// A sealed trait, this is logically private to the crate +/// and will prevent implementations from outside the crate +pub trait Seal {} + /// Trait implemented by arrays that can be SIMD types. -#[doc(hidden)] -pub trait SimdArray { +pub trait SimdArray: Seal { /// The type of the #[repr(simd)] type. type Tuple: Copy + Clone; /// The element type of the vector. @@ -16,7 +19,7 @@ pub trait SimdArray { /// This traits is used to constraint the arguments /// and result type of the portable shuffles. #[doc(hidden)] -pub trait Shuffle { +pub trait Shuffle: Seal { // Lanes is a `[u32; N]` where `N` is the number of vector lanes /// The result type of the shuffle. @@ -24,8 +27,7 @@ pub trait Shuffle { } /// This trait is implemented by all SIMD vector types. -#[doc(hidden)] -pub trait Simd { +pub trait Simd: Seal { /// Element type of the SIMD vector type Element; /// The number of elements in the SIMD vector. @@ -35,7 +37,6 @@ pub trait Simd { } /// This trait is implemented by all mask types -#[doc(hidden)] -pub trait Mask { +pub trait Mask: Seal { fn test(&self) -> bool; } diff --git a/vendor/packed_simd/src/testing.rs b/vendor/packed_simd_2/src/testing.rs similarity index 100% rename from vendor/packed_simd/src/testing.rs rename to vendor/packed_simd_2/src/testing.rs diff --git a/vendor/packed_simd/src/testing/macros.rs b/vendor/packed_simd_2/src/testing/macros.rs similarity index 100% rename from vendor/packed_simd/src/testing/macros.rs rename to vendor/packed_simd_2/src/testing/macros.rs diff --git a/vendor/packed_simd/src/testing/utils.rs b/vendor/packed_simd_2/src/testing/utils.rs similarity index 86% rename from vendor/packed_simd/src/testing/utils.rs rename to vendor/packed_simd_2/src/testing/utils.rs index 7b8f21ac1c..21f27aae54 100644 --- a/vendor/packed_simd/src/testing/utils.rs +++ b/vendor/packed_simd_2/src/testing/utils.rs @@ -1,6 +1,8 @@ //! Testing utilities #![allow(dead_code)] +// FIXME: Or don't. But it's true this is a problematic comparison. +#![allow(clippy::neg_cmp_op_on_partial_ord)] use crate::{cmp::PartialOrd, fmt::Debug, LexicographicallyOrdered}; @@ -19,14 +21,19 @@ pub fn test_lt( assert!(a <= b, "{:?}, {:?}", a, b); assert!(b >= a, "{:?}, {:?}", a, b); - // Irreflexivity - assert!(!(a < a), "{:?}, {:?}", a, b); - assert!(!(b < b), "{:?}, {:?}", a, b); - assert!(!(a > a), "{:?}, {:?}", a, b); - assert!(!(b > b), "{:?}, {:?}", a, b); + // The elegance of the mathematical expression of irreflexivity is more + // than clippy can handle. + #[allow(clippy::eq_op)] + { + // Irreflexivity + assert!(!(a < a), "{:?}, {:?}", a, b); + assert!(!(b < b), "{:?}, {:?}", a, b); + assert!(!(a > a), "{:?}, {:?}", a, b); + assert!(!(b > b), "{:?}, {:?}", a, b); - assert!(a <= a, "{:?}, {:?}", a, b); - assert!(b <= b, "{:?}, {:?}", a, b); + assert!(a <= a, "{:?}, {:?}", a, b); + assert!(b <= b, "{:?}, {:?}", a, b); + } } /// Tests PartialOrd for `a` and `b` where `a <= b` is true. @@ -38,8 +45,8 @@ pub fn test_le( assert!(a <= b, "{:?}, {:?}", a, b); assert!(b >= a, "{:?}, {:?}", a, b); - assert!(a == b || a < b, "{:?}, {:?}", a, b); - assert!(a == b || b > a, "{:?}, {:?}", a, b); + assert!(a <= b, "{:?}, {:?}", a, b); + assert!(b >= a, "{:?}, {:?}", a, b); if a == b { assert!(!(a < b), "{:?}, {:?}", a, b); diff --git a/vendor/packed_simd/src/v128.rs b/vendor/packed_simd_2/src/v128.rs similarity index 99% rename from vendor/packed_simd/src/v128.rs rename to vendor/packed_simd_2/src/v128.rs index 03dc246cd2..7949f6619a 100644 --- a/vendor/packed_simd/src/v128.rs +++ b/vendor/packed_simd_2/src/v128.rs @@ -1,5 +1,5 @@ //! 128-bit wide vector types -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/v16.rs b/vendor/packed_simd_2/src/v16.rs similarity index 100% rename from vendor/packed_simd/src/v16.rs rename to vendor/packed_simd_2/src/v16.rs diff --git a/vendor/packed_simd/src/v256.rs b/vendor/packed_simd_2/src/v256.rs similarity index 99% rename from vendor/packed_simd/src/v256.rs rename to vendor/packed_simd_2/src/v256.rs index 78523a5ba6..f0c3bc2813 100644 --- a/vendor/packed_simd/src/v256.rs +++ b/vendor/packed_simd_2/src/v256.rs @@ -1,5 +1,5 @@ //! 256-bit wide vector types -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/v32.rs b/vendor/packed_simd_2/src/v32.rs similarity index 100% rename from vendor/packed_simd/src/v32.rs rename to vendor/packed_simd_2/src/v32.rs diff --git a/vendor/packed_simd/src/v512.rs b/vendor/packed_simd_2/src/v512.rs similarity index 99% rename from vendor/packed_simd/src/v512.rs rename to vendor/packed_simd_2/src/v512.rs index 8fe4d8351a..4c8c71338a 100644 --- a/vendor/packed_simd/src/v512.rs +++ b/vendor/packed_simd_2/src/v512.rs @@ -1,5 +1,5 @@ //! 512-bit wide vector types -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/v64.rs b/vendor/packed_simd_2/src/v64.rs similarity index 99% rename from vendor/packed_simd/src/v64.rs rename to vendor/packed_simd_2/src/v64.rs index 92c2d103e8..bf6b9de610 100644 --- a/vendor/packed_simd/src/v64.rs +++ b/vendor/packed_simd_2/src/v64.rs @@ -1,5 +1,5 @@ //! 64-bit wide vector types -#![rustfmt::skip] +#[rustfmt::skip] use super::*; diff --git a/vendor/packed_simd/src/vPtr.rs b/vendor/packed_simd_2/src/vPtr.rs similarity index 98% rename from vendor/packed_simd/src/vPtr.rs rename to vendor/packed_simd_2/src/vPtr.rs index fe9fb28ffa..e34cb170eb 100644 --- a/vendor/packed_simd/src/vPtr.rs +++ b/vendor/packed_simd_2/src/vPtr.rs @@ -1,5 +1,5 @@ //! Vectors of pointers -#![rustfmt::skip] +#[rustfmt::skip] use crate::*; diff --git a/vendor/packed_simd/src/vSize.rs b/vendor/packed_simd_2/src/vSize.rs similarity index 97% rename from vendor/packed_simd/src/vSize.rs rename to vendor/packed_simd_2/src/vSize.rs index 0e3d8a84b7..b5d8910061 100644 --- a/vendor/packed_simd/src/vSize.rs +++ b/vendor/packed_simd_2/src/vSize.rs @@ -39,7 +39,7 @@ impl_m!([msize; 4]: msizex4 | isize_, u8 | test_v256 | impl_i!([isize; 8]: isizex8, msizex8 | isize_, u8 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 | From: | - /// A vector with 4 `isize` lanes. + /// A vector with 8 `isize` lanes. ); impl_u!([usize; 8]: usizex8, msizex8 | usize_, u8 | test_v512 | x0, x1, x2, x3, x4, x5, x6, x7 | diff --git a/vendor/packed_simd/tests/endianness.rs b/vendor/packed_simd_2/tests/endianness.rs similarity index 85% rename from vendor/packed_simd/tests/endianness.rs rename to vendor/packed_simd_2/tests/endianness.rs index 1e6b4f3543..31fb7073af 100644 --- a/vendor/packed_simd/tests/endianness.rs +++ b/vendor/packed_simd_2/tests/endianness.rs @@ -17,7 +17,7 @@ fn endian_indexing() { #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn endian_bitcasts() { - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -34,13 +34,13 @@ fn endian_bitcasts() { #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn endian_casts() { - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ); let t: i16x16 = x.into(); // simd_cast - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let e = i16x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -51,7 +51,7 @@ fn endian_casts() { #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn endian_load_and_stores() { - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -82,10 +82,15 @@ fn endian_array_union() { vec: f32x4, } let x: [f32; 4] = unsafe { A { vec: f32x4::new(0., 1., 2., 3.) }.data }; - assert_eq!(x[0], 0_f32); - assert_eq!(x[1], 1_f32); - assert_eq!(x[2], 2_f32); - assert_eq!(x[3], 3_f32); + // As all of these are integer values within the mantissa^1 range, it + // would be very unusual for them to actually fail to compare. + #[allow(clippy::float_cmp)] + { + assert_eq!(x[0], 0_f32); + assert_eq!(x[1], 1_f32); + assert_eq!(x[2], 2_f32); + assert_eq!(x[3], 3_f32); + } let y: f32x4 = unsafe { A { data: [3., 2., 1., 0.] }.vec }; assert_eq!(y, f32x4::new(3., 2., 1., 0.)); @@ -93,23 +98,23 @@ fn endian_array_union() { data: [i8; 16], vec: i8x16, } - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ); let x: [i8; 16] = unsafe { B { vec: x }.data }; - for i in 0..16 { - assert_eq!(x[i], i as i8); + for (i, v) in x.iter().enumerate() { + assert_eq!(i as i8, *v); } - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let y = [ 15, 14, 13, 12, 11, 19, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]; - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let e = i8x16::new( 15, 14, 13, 12, 11, 19, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 @@ -121,7 +126,7 @@ fn endian_array_union() { data: [i16; 8], vec: i8x16, } - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -145,21 +150,26 @@ fn endian_tuple_access() { vec: f32x4, } let x: F32x4T = unsafe { A { vec: f32x4::new(0., 1., 2., 3.) }.data }; - assert_eq!(x.0, 0_f32); - assert_eq!(x.1, 1_f32); - assert_eq!(x.2, 2_f32); - assert_eq!(x.3, 3_f32); + // As all of these are integer values within the mantissa^1 range, it + // would be very unusual for them to actually fail to compare. + #[allow(clippy::float_cmp)] + { + assert_eq!(x.0, 0_f32); + assert_eq!(x.1, 1_f32); + assert_eq!(x.2, 2_f32); + assert_eq!(x.3, 3_f32); + } let y: f32x4 = unsafe { A { data: (3., 2., 1., 0.) }.vec }; assert_eq!(y, f32x4::new(3., 2., 1., 0.)); - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] type I8x16T = (i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); union B { data: I8x16T, vec: i8x16, } - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -183,27 +193,27 @@ fn endian_tuple_access() { assert_eq!(x.14, 14); assert_eq!(x.15, 15); - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let y = ( 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ); let z: i8x16 = unsafe { B { data: y }.vec }; - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let e = i8x16::new( 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ); assert_eq!(e, z); - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] type I16x8T = (i16, i16, i16, i16, i16, i16, i16, i16); union C { data: I16x8T, vec: i8x16, } - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -224,7 +234,7 @@ fn endian_tuple_access() { assert_eq!(x.6, e[6]); assert_eq!(x.7, e[7]); - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] #[repr(C)] #[derive(Copy ,Clone)] pub struct Tup(pub i8, pub i8, pub i16, pub i8, pub i8, pub i16, @@ -235,7 +245,7 @@ fn endian_tuple_access() { vec: i8x16, } - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] let x = i8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, diff --git a/vendor/proc-macro2/.cargo-checksum.json b/vendor/proc-macro2/.cargo-checksum.json index e7849f2896..7f9ea4306e 100644 --- a/vendor/proc-macro2/.cargo-checksum.json +++ b/vendor/proc-macro2/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"302d447d62c8d091d6241cf62bdad607c0d4ed8ff9f43d9b254c9d99c253ee8e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e1f9d4fc22cff2c049f166a403b41458632a94357890d31cf0e3ad83807fb430","build.rs":"a71283fbc495095eebbbf46753df3fe2c19505c745b508dea157f65796b64dd7","src/detection.rs":"9d25d896889e65330858f2d6f6223c1b98cd1dad189813ad4161ff189fbda2b8","src/fallback.rs":"b114e013695260f6066395c8712cea112ec2a386010397a80f15a60f8b986444","src/lib.rs":"7f528764a958587f007f0c2a330a6a414bae2c8e73d5ed9fb64ff1b42b1805b1","src/marker.rs":"87fce2d0357f5b7998b6d9dfb064f4a0cbc9dabb19e33d4b514a446243ebe2e8","src/parse.rs":"1d2253eacbd40eb3a2a933be2adcee356af922bdb48cc89ff266252a41fd98a1","src/wrapper.rs":"f52646ce1705c1f6265516f30d4c43297b5f529dd31fb91f4c806be89d5a4122","tests/comments.rs":"ea6cbe6f4c8852e6a0612893c7d4f2c144a2e6a134a6c3db641a320cbfc3c800","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"652db9f25c69ffc65baa60cdca8f195aa2e254d4de0a9ddc85de4dc2470544b6","tests/test.rs":"5f30a704eeb2b9198b57f416d622da72d25cb9bf8d8b12e6d0e90aa2cb0e43fc","tests/test_fmt.rs":"745dfdc41d09c5308c221395eb43f2041f0a1413d2927a813bc2ad4554438fe2"},"package":"1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"} \ No newline at end of file +{"files":{"Cargo.toml":"d790bd30ab27a368d01e6eaab90ef990a9bc446ff0e0a0fac71e69c725259714","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e1f9d4fc22cff2c049f166a403b41458632a94357890d31cf0e3ad83807fb430","build.rs":"a71283fbc495095eebbbf46753df3fe2c19505c745b508dea157f65796b64dd7","src/detection.rs":"9d25d896889e65330858f2d6f6223c1b98cd1dad189813ad4161ff189fbda2b8","src/fallback.rs":"528a5859f4e11efaf1f4c58ec8551d369cddc0a5bdb4d5f2408f1319988a4c82","src/lib.rs":"83a4a8ec284ebe4cfa4f4889569344acfd0541a6d477f0ec4f5a8ea6b0c0909e","src/marker.rs":"87fce2d0357f5b7998b6d9dfb064f4a0cbc9dabb19e33d4b514a446243ebe2e8","src/parse.rs":"b6179432a3919da02d486b1dd1789af504e765c1e2e5b92b5f2868107b96fc41","src/wrapper.rs":"85bc6edd37e7a1bea89cadfc17011ece7b51456402799598dc86a52f633de32b","tests/comments.rs":"ea6cbe6f4c8852e6a0612893c7d4f2c144a2e6a134a6c3db641a320cbfc3c800","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"652db9f25c69ffc65baa60cdca8f195aa2e254d4de0a9ddc85de4dc2470544b6","tests/test.rs":"9ec99517d324532801e93a76ae6e4e07b98218aa61d901ee45d250ee93bac417","tests/test_fmt.rs":"745dfdc41d09c5308c221395eb43f2041f0a1413d2927a813bc2ad4554438fe2"},"package":"a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"} \ No newline at end of file diff --git a/vendor/proc-macro2/Cargo.toml b/vendor/proc-macro2/Cargo.toml index 22150c516a..3bb4b8e91b 100644 --- a/vendor/proc-macro2/Cargo.toml +++ b/vendor/proc-macro2/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "proc-macro2" -version = "1.0.24" +version = "1.0.26" authors = ["Alex Crichton ", "David Tolnay "] description = "A substitute implementation of the compiler's `proc_macro` API to decouple\ntoken-based libraries from the procedural macro use case.\n" documentation = "https://docs.rs/proc-macro2" @@ -24,7 +24,7 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/alexcrichton/proc-macro2" [package.metadata.docs.rs] rustc-args = ["--cfg", "procmacro2_semver_exempt"] -rustdoc-args = ["--cfg", "procmacro2_semver_exempt"] +rustdoc-args = ["--cfg", "procmacro2_semver_exempt", "--cfg", "doc_cfg"] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.playground] diff --git a/vendor/proc-macro2/src/fallback.rs b/vendor/proc-macro2/src/fallback.rs index 8900c5ff0f..50d10db3eb 100644 --- a/vendor/proc-macro2/src/fallback.rs +++ b/vendor/proc-macro2/src/fallback.rs @@ -1,4 +1,4 @@ -use crate::parse::{token_stream, Cursor}; +use crate::parse::{self, Cursor}; use crate::{Delimiter, Spacing, TokenTree}; #[cfg(span_locations)] use std::cell::RefCell; @@ -35,7 +35,15 @@ pub(crate) struct TokenStream { } #[derive(Debug)] -pub(crate) struct LexError; +pub(crate) struct LexError { + pub(crate) span: Span, +} + +impl LexError { + pub(crate) fn span(&self) -> Span { + self.span + } +} impl TokenStream { pub fn new() -> TokenStream { @@ -139,12 +147,7 @@ impl FromStr for TokenStream { // Create a dummy file & add it to the source map let cursor = get_cursor(src); - let (rest, tokens) = token_stream(cursor)?; - if rest.is_empty() { - Ok(tokens) - } else { - Err(LexError) - } + parse::token_stream(cursor) } } diff --git a/vendor/proc-macro2/src/lib.rs b/vendor/proc-macro2/src/lib.rs index c20fb50d4a..9dec30964e 100644 --- a/vendor/proc-macro2/src/lib.rs +++ b/vendor/proc-macro2/src/lib.rs @@ -78,10 +78,11 @@ //! a different thread. // Proc-macro2 types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.24")] +#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.26")] #![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] #![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))] -#![allow(clippy::needless_doctest_main)] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![allow(clippy::needless_doctest_main, clippy::vec_init_then_push)] #[cfg(use_proc_macro)] extern crate proc_macro; @@ -249,6 +250,12 @@ impl Debug for TokenStream { } } +impl LexError { + pub fn span(&self) -> Span { + Span::_new(self.inner.span()) + } +} + impl Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) @@ -267,6 +274,7 @@ impl Error for LexError {} /// /// This type is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] +#[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] #[derive(Clone, PartialEq, Eq)] pub struct SourceFile { inner: imp::SourceFile, @@ -317,6 +325,7 @@ impl Debug for SourceFile { /// /// This type is semver exempt and not exposed by default. #[cfg(span_locations)] +#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct LineColumn { /// The 1-indexed line in the source file on which the span starts or ends @@ -388,6 +397,7 @@ impl Span { /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] + #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] pub fn def_site() -> Span { Span::_new(imp::Span::def_site()) } @@ -430,6 +440,7 @@ impl Span { /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] + #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] pub fn source_file(&self) -> SourceFile { SourceFile::_new(self.inner.source_file()) } @@ -437,7 +448,14 @@ impl Span { /// Get the starting line/column in the source file for this span. /// /// This method requires the `"span-locations"` feature to be enabled. + /// + /// When executing in a procedural macro context, the returned line/column + /// are only meaningful if compiled with a nightly toolchain. The stable + /// toolchain does not have this information available. When executing + /// outside of a procedural macro, such as main.rs or build.rs, the + /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] + #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] pub fn start(&self) -> LineColumn { let imp::LineColumn { line, column } = self.inner.start(); LineColumn { line, column } @@ -446,7 +464,14 @@ impl Span { /// Get the ending line/column in the source file for this span. /// /// This method requires the `"span-locations"` feature to be enabled. + /// + /// When executing in a procedural macro context, the returned line/column + /// are only meaningful if compiled with a nightly toolchain. The stable + /// toolchain does not have this information available. When executing + /// outside of a procedural macro, such as main.rs or build.rs, the + /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] + #[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))] pub fn end(&self) -> LineColumn { let imp::LineColumn { line, column } = self.inner.end(); LineColumn { line, column } @@ -469,6 +494,7 @@ impl Span { /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] + #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] pub fn eq(&self, other: &Span) -> bool { self.inner.eq(&other.inner) } @@ -699,7 +725,7 @@ impl Debug for Group { } } -/// An `Punct` is an single punctuation character like `+`, `-` or `#`. +/// A `Punct` is a single punctuation character like `+`, `-` or `#`. /// /// Multicharacter operators like `+=` are represented as two instances of /// `Punct` with different forms of `Spacing` returned. @@ -710,7 +736,7 @@ pub struct Punct { span: Span, } -/// Whether an `Punct` is followed immediately by another `Punct` or followed by +/// Whether a `Punct` is followed immediately by another `Punct` or followed by /// another token or whitespace. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Spacing { @@ -899,6 +925,7 @@ impl Ident { /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] + #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] pub fn new_raw(string: &str, span: Span) -> Ident { Ident::_new_raw(string, span) } @@ -987,7 +1014,7 @@ macro_rules! suffixed_int_literals { /// This function will create an integer like `1u32` where the integer /// value specified is the first part of the token and the integral is /// also suffixed at the end. Literals created from negative numbers may - /// not survive rountrips through `TokenStream` or strings and may be + /// not survive roundtrips through `TokenStream` or strings and may be /// broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` @@ -1008,7 +1035,7 @@ macro_rules! unsuffixed_int_literals { /// specified on this token, meaning that invocations like /// `Literal::i8_unsuffixed(1)` are equivalent to /// `Literal::u32_unsuffixed(1)`. Literals created from negative numbers - /// may not survive rountrips through `TokenStream` or strings and may + /// may not survive roundtrips through `TokenStream` or strings and may /// be broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` diff --git a/vendor/proc-macro2/src/parse.rs b/vendor/proc-macro2/src/parse.rs index 365fe0484d..e5caed837e 100644 --- a/vendor/proc-macro2/src/parse.rs +++ b/vendor/proc-macro2/src/parse.rs @@ -26,7 +26,7 @@ impl<'a> Cursor<'a> { self.rest.starts_with(s) } - pub(crate) fn is_empty(&self) -> bool { + fn is_empty(&self) -> bool { self.rest.is_empty() } @@ -50,16 +50,17 @@ impl<'a> Cursor<'a> { self.rest.char_indices() } - fn parse(&self, tag: &str) -> Result, LexError> { + fn parse(&self, tag: &str) -> Result, Reject> { if self.starts_with(tag) { Ok(self.advance(tag.len())) } else { - Err(LexError) + Err(Reject) } } } -type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>; +struct Reject; +type PResult<'a, O> = Result<(Cursor<'a>, O), Reject>; fn skip_whitespace(input: Cursor) -> Cursor { let mut s = input; @@ -86,7 +87,7 @@ fn skip_whitespace(input: Cursor) -> Cursor { s = rest; continue; } - Err(LexError) => return s, + Err(Reject) => return s, } } } @@ -111,7 +112,7 @@ fn skip_whitespace(input: Cursor) -> Cursor { fn block_comment(input: Cursor) -> PResult<&str> { if !input.starts_with("/*") { - return Err(LexError); + return Err(Reject); } let mut depth = 0; @@ -133,7 +134,7 @@ fn block_comment(input: Cursor) -> PResult<&str> { i += 1; } - Err(LexError) + Err(Reject) } fn is_whitespace(ch: char) -> bool { @@ -141,14 +142,14 @@ fn is_whitespace(ch: char) -> bool { ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' } -fn word_break(input: Cursor) -> Result { +fn word_break(input: Cursor) -> Result { match input.chars().next() { - Some(ch) if is_ident_continue(ch) => Err(LexError), + Some(ch) if is_ident_continue(ch) => Err(Reject), Some(_) | None => Ok(input), } } -pub(crate) fn token_stream(mut input: Cursor) -> PResult { +pub(crate) fn token_stream(mut input: Cursor) -> Result { let mut trees = Vec::new(); let mut stack = Vec::new(); @@ -166,7 +167,17 @@ pub(crate) fn token_stream(mut input: Cursor) -> PResult { let first = match input.bytes().next() { Some(first) => first, - None => break, + None => match stack.last() { + None => return Ok(TokenStream { inner: trees }), + #[cfg(span_locations)] + Some((lo, _frame)) => { + return Err(LexError { + span: Span { lo: *lo, hi: *lo }, + }) + } + #[cfg(not(span_locations))] + Some(_frame) => return Err(LexError { span: Span {} }), + }, }; if let Some(open_delimiter) = match first { @@ -187,14 +198,17 @@ pub(crate) fn token_stream(mut input: Cursor) -> PResult { b'}' => Some(Delimiter::Brace), _ => None, } { - input = input.advance(1); - let frame = stack.pop().ok_or(LexError)?; + let frame = match stack.pop() { + Some(frame) => frame, + None => return Err(lex_error(input)), + }; #[cfg(span_locations)] let (lo, frame) = frame; let (open_delimiter, outer) = frame; if open_delimiter != close_delimiter { - return Err(LexError); + return Err(lex_error(input)); } + input = input.advance(1); let mut g = Group::new(open_delimiter, TokenStream { inner: trees }); g.set_span(Span { #[cfg(span_locations)] @@ -205,7 +219,10 @@ pub(crate) fn token_stream(mut input: Cursor) -> PResult { trees = outer; trees.push(TokenTree::Group(crate::Group::_new_stable(g))); } else { - let (rest, mut tt) = leaf_token(input)?; + let (rest, mut tt) = match leaf_token(input) { + Ok((rest, tt)) => (rest, tt), + Err(Reject) => return Err(lex_error(input)), + }; tt.set_span(crate::Span::_new_stable(Span { #[cfg(span_locations)] lo, @@ -216,11 +233,18 @@ pub(crate) fn token_stream(mut input: Cursor) -> PResult { input = rest; } } +} - if stack.is_empty() { - Ok((input, TokenStream { inner: trees })) - } else { - Err(LexError) +fn lex_error(cursor: Cursor) -> LexError { + #[cfg(not(span_locations))] + let _ = cursor; + LexError { + span: Span { + #[cfg(span_locations)] + lo: cursor.off, + #[cfg(span_locations)] + hi: cursor.off, + }, } } @@ -233,7 +257,7 @@ fn leaf_token(input: Cursor) -> PResult { } else if let Ok((input, i)) = ident(input) { Ok((input, TokenTree::Ident(i))) } else { - Err(LexError) + Err(Reject) } } @@ -242,7 +266,7 @@ fn ident(input: Cursor) -> PResult { .iter() .any(|prefix| input.starts_with(prefix)) { - Err(LexError) + Err(Reject) } else { ident_any(input) } @@ -260,7 +284,7 @@ fn ident_any(input: Cursor) -> PResult { } if sym == "_" { - return Err(LexError); + return Err(Reject); } let ident = crate::Ident::_new_raw(sym, crate::Span::call_site()); @@ -272,7 +296,7 @@ fn ident_not_raw(input: Cursor) -> PResult<&str> { match chars.next() { Some((_, ch)) if is_ident_start(ch) => {} - _ => return Err(LexError), + _ => return Err(Reject), } let mut end = input.len(); @@ -287,16 +311,12 @@ fn ident_not_raw(input: Cursor) -> PResult<&str> { } fn literal(input: Cursor) -> PResult { - match literal_nocapture(input) { - Ok(a) => { - let end = input.len() - a.len(); - Ok((a, Literal::_new(input.rest[..end].to_string()))) - } - Err(LexError) => Err(LexError), - } + let rest = literal_nocapture(input)?; + let end = input.len() - rest.len(); + Ok((rest, Literal::_new(input.rest[..end].to_string()))) } -fn literal_nocapture(input: Cursor) -> Result { +fn literal_nocapture(input: Cursor) -> Result { if let Ok(ok) = string(input) { Ok(ok) } else if let Ok(ok) = byte_string(input) { @@ -310,28 +330,28 @@ fn literal_nocapture(input: Cursor) -> Result { } else if let Ok(ok) = int(input) { Ok(ok) } else { - Err(LexError) + Err(Reject) } } fn literal_suffix(input: Cursor) -> Cursor { match ident_not_raw(input) { Ok((input, _)) => input, - Err(LexError) => input, + Err(Reject) => input, } } -fn string(input: Cursor) -> Result { +fn string(input: Cursor) -> Result { if let Ok(input) = input.parse("\"") { cooked_string(input) } else if let Ok(input) = input.parse("r") { raw_string(input) } else { - Err(LexError) + Err(Reject) } } -fn cooked_string(input: Cursor) -> Result { +fn cooked_string(input: Cursor) -> Result { let mut chars = input.char_indices().peekable(); while let Some((i, ch)) = chars.next() { @@ -361,7 +381,7 @@ fn cooked_string(input: Cursor) -> Result { let mut last = ch; loop { if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') { - return Err(LexError); + return Err(Reject); } match chars.peek() { Some((_, ch)) if ch.is_whitespace() => { @@ -377,20 +397,20 @@ fn cooked_string(input: Cursor) -> Result { _ch => {} } } - Err(LexError) + Err(Reject) } -fn byte_string(input: Cursor) -> Result { +fn byte_string(input: Cursor) -> Result { if let Ok(input) = input.parse("b\"") { cooked_byte_string(input) } else if let Ok(input) = input.parse("br") { raw_string(input) } else { - Err(LexError) + Err(Reject) } } -fn cooked_byte_string(mut input: Cursor) -> Result { +fn cooked_byte_string(mut input: Cursor) -> Result { let mut bytes = input.bytes().enumerate(); while let Some((offset, b)) = bytes.next() { match b { @@ -416,7 +436,7 @@ fn cooked_byte_string(mut input: Cursor) -> Result { let mut chars = rest.char_indices(); loop { if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') { - return Err(LexError); + return Err(Reject); } match chars.next() { Some((_, ch)) if ch.is_whitespace() => last = ch, @@ -425,7 +445,7 @@ fn cooked_byte_string(mut input: Cursor) -> Result { bytes = input.bytes().enumerate(); break; } - None => return Err(LexError), + None => return Err(Reject), } } } @@ -435,10 +455,10 @@ fn cooked_byte_string(mut input: Cursor) -> Result { _ => break, } } - Err(LexError) + Err(Reject) } -fn raw_string(input: Cursor) -> Result { +fn raw_string(input: Cursor) -> Result { let mut chars = input.char_indices(); let mut n = 0; while let Some((i, ch)) = chars.next() { @@ -448,7 +468,7 @@ fn raw_string(input: Cursor) -> Result { break; } '#' => {} - _ => return Err(LexError), + _ => return Err(Reject), } } while let Some((i, ch)) = chars.next() { @@ -464,10 +484,10 @@ fn raw_string(input: Cursor) -> Result { _ => {} } } - Err(LexError) + Err(Reject) } -fn byte(input: Cursor) -> Result { +fn byte(input: Cursor) -> Result { let input = input.parse("b'")?; let mut bytes = input.bytes().enumerate(); let ok = match bytes.next().map(|(_, b)| b) { @@ -480,17 +500,17 @@ fn byte(input: Cursor) -> Result { b => b.is_some(), }; if !ok { - return Err(LexError); + return Err(Reject); } - let (offset, _) = bytes.next().ok_or(LexError)?; + let (offset, _) = bytes.next().ok_or(Reject)?; if !input.chars().as_str().is_char_boundary(offset) { - return Err(LexError); + return Err(Reject); } let input = input.advance(offset).parse("'")?; Ok(literal_suffix(input)) } -fn character(input: Cursor) -> Result { +fn character(input: Cursor) -> Result { let input = input.parse("'")?; let mut chars = input.char_indices(); let ok = match chars.next().map(|(_, ch)| ch) { @@ -505,9 +525,9 @@ fn character(input: Cursor) -> Result { ch => ch.is_some(), }; if !ok { - return Err(LexError); + return Err(Reject); } - let (idx, _) = chars.next().ok_or(LexError)?; + let (idx, _) = chars.next().ok_or(Reject)?; let input = input.advance(idx).parse("'")?; Ok(literal_suffix(input)) } @@ -549,7 +569,7 @@ where next_ch!(chars @ '{'); let mut value = 0; let mut len = 0; - while let Some((_, ch)) = chars.next() { + for (_, ch) in chars { let digit = match ch { '0'..='9' => ch as u8 - b'0', 'a'..='f' => 10 + ch as u8 - b'a', @@ -568,7 +588,7 @@ where false } -fn float(input: Cursor) -> Result { +fn float(input: Cursor) -> Result { let mut rest = float_digits(input)?; if let Some(ch) = rest.chars().next() { if is_ident_start(ch) { @@ -578,11 +598,11 @@ fn float(input: Cursor) -> Result { word_break(rest) } -fn float_digits(input: Cursor) -> Result { +fn float_digits(input: Cursor) -> Result { let mut chars = input.chars().peekable(); match chars.next() { Some(ch) if ch >= '0' && ch <= '9' => {} - _ => return Err(LexError), + _ => return Err(Reject), } let mut len = 1; @@ -604,7 +624,7 @@ fn float_digits(input: Cursor) -> Result { .map(|&ch| ch == '.' || is_ident_start(ch)) .unwrap_or(false) { - return Err(LexError); + return Err(Reject); } len += 1; has_dot = true; @@ -620,14 +640,14 @@ fn float_digits(input: Cursor) -> Result { } if !(has_dot || has_exp) { - return Err(LexError); + return Err(Reject); } if has_exp { let token_before_exp = if has_dot { Ok(input.advance(len - 1)) } else { - Err(LexError) + Err(Reject) }; let mut has_sign = false; let mut has_exp_value = false; @@ -664,7 +684,7 @@ fn float_digits(input: Cursor) -> Result { Ok(input.advance(len)) } -fn int(input: Cursor) -> Result { +fn int(input: Cursor) -> Result { let mut rest = digits(input)?; if let Some(ch) = rest.chars().next() { if is_ident_start(ch) { @@ -674,7 +694,7 @@ fn int(input: Cursor) -> Result { word_break(rest) } -fn digits(mut input: Cursor) -> Result { +fn digits(mut input: Cursor) -> Result { let base = if input.starts_with("0x") { input = input.advance(2); 16 @@ -695,7 +715,7 @@ fn digits(mut input: Cursor) -> Result { b'0'..=b'9' => { let digit = (b - b'0') as u64; if digit >= base { - return Err(LexError); + return Err(Reject); } } b'a'..=b'f' => { @@ -712,7 +732,7 @@ fn digits(mut input: Cursor) -> Result { } b'_' => { if empty && base == 10 { - return Err(LexError); + return Err(Reject); } len += 1; continue; @@ -723,50 +743,47 @@ fn digits(mut input: Cursor) -> Result { empty = false; } if empty { - Err(LexError) + Err(Reject) } else { Ok(input.advance(len)) } } fn punct(input: Cursor) -> PResult { - match punct_char(input) { - Ok((rest, '\'')) => { - if ident_any(rest)?.0.starts_with("'") { - Err(LexError) - } else { - Ok((rest, Punct::new('\'', Spacing::Joint))) - } - } - Ok((rest, ch)) => { - let kind = match punct_char(rest) { - Ok(_) => Spacing::Joint, - Err(LexError) => Spacing::Alone, - }; - Ok((rest, Punct::new(ch, kind))) + let (rest, ch) = punct_char(input)?; + if ch == '\'' { + if ident_any(rest)?.0.starts_with("'") { + Err(Reject) + } else { + Ok((rest, Punct::new('\'', Spacing::Joint))) } - Err(LexError) => Err(LexError), + } else { + let kind = match punct_char(rest) { + Ok(_) => Spacing::Joint, + Err(Reject) => Spacing::Alone, + }; + Ok((rest, Punct::new(ch, kind))) } } fn punct_char(input: Cursor) -> PResult { if input.starts_with("//") || input.starts_with("/*") { // Do not accept `/` of a comment as a punct. - return Err(LexError); + return Err(Reject); } let mut chars = input.chars(); let first = match chars.next() { Some(ch) => ch, None => { - return Err(LexError); + return Err(Reject); } }; let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; if recognized.contains(first) { Ok((input.advance(first.len_utf8()), first)) } else { - Err(LexError) + Err(Reject) } } @@ -785,7 +802,7 @@ fn doc_comment(input: Cursor) -> PResult> { while let Some(cr) = scan_for_bare_cr.find('\r') { let rest = &scan_for_bare_cr[cr + 1..]; if !rest.starts_with('\n') { - return Err(LexError); + return Err(Reject); } scan_for_bare_cr = rest; } @@ -822,7 +839,7 @@ fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> { } else if input.starts_with("///") { let input = input.advance(3); if input.starts_with("/") { - return Err(LexError); + return Err(Reject); } let (input, s) = take_until_newline_or_eof(input); Ok((input, (s, false))) @@ -830,7 +847,7 @@ fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> { let (input, s) = block_comment(input)?; Ok((input, (&s[3..s.len() - 2], false))) } else { - Err(LexError) + Err(Reject) } } diff --git a/vendor/proc-macro2/src/wrapper.rs b/vendor/proc-macro2/src/wrapper.rs index 3df044af17..24d86e870b 100644 --- a/vendor/proc-macro2/src/wrapper.rs +++ b/vendor/proc-macro2/src/wrapper.rs @@ -107,8 +107,12 @@ impl FromStr for TokenStream { // Work around https://github.com/rust-lang/rust/issues/58736. fn proc_macro_parse(src: &str) -> Result { - panic::catch_unwind(|| src.parse().map_err(LexError::Compiler)) - .unwrap_or(Err(LexError::Fallback(fallback::LexError))) + let result = panic::catch_unwind(|| src.parse().map_err(LexError::Compiler)); + result.unwrap_or_else(|_| { + Err(LexError::Fallback(fallback::LexError { + span: fallback::Span::call_site(), + })) + }) } impl Display for TokenStream { @@ -243,6 +247,15 @@ impl Debug for TokenStream { } } +impl LexError { + pub(crate) fn span(&self) -> Span { + match self { + LexError::Compiler(_) => Span::call_site(), + LexError::Fallback(e) => Span::Fallback(e.span()), + } + } +} + impl From for LexError { fn from(e: proc_macro::LexError) -> LexError { LexError::Compiler(e) @@ -270,7 +283,12 @@ impl Display for LexError { #[cfg(lexerror_display)] LexError::Compiler(e) => Display::fmt(e, f), #[cfg(not(lexerror_display))] - LexError::Compiler(_e) => Display::fmt(&fallback::LexError, f), + LexError::Compiler(_e) => Display::fmt( + &fallback::LexError { + span: fallback::Span::call_site(), + }, + f, + ), LexError::Fallback(e) => Display::fmt(e, f), } } diff --git a/vendor/proc-macro2/tests/test.rs b/vendor/proc-macro2/tests/test.rs index 1e9f633944..6d0a93eb78 100644 --- a/vendor/proc-macro2/tests/test.rs +++ b/vendor/proc-macro2/tests/test.rs @@ -1,4 +1,5 @@ use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::panic; use std::str::{self, FromStr}; #[test] @@ -71,9 +72,24 @@ fn lifetime_number() { } #[test] -#[should_panic(expected = r#""\'a#" is not a valid Ident"#)] fn lifetime_invalid() { - Ident::new("'a#", Span::call_site()); + let result = panic::catch_unwind(|| Ident::new("'a#", Span::call_site())); + match result { + Err(box_any) => { + let message = box_any.downcast_ref::().unwrap(); + let expected1 = r#""\'a#" is not a valid Ident"#; // 1.31.0 .. 1.53.0 + let expected2 = r#""'a#" is not a valid Ident"#; // 1.53.0 .. + assert!( + message == expected1 || message == expected2, + "panic message does not match expected string\n\ + \x20 panic message: `{:?}`\n\ + \x20expected message: `{:?}`", + message, + expected2, + ); + } + Ok(_) => panic!("test did not panic as expected"), + } } #[test] diff --git a/vendor/rand/.cargo-checksum.json b/vendor/rand/.cargo-checksum.json new file mode 100644 index 0000000000..cd75f4d98b --- /dev/null +++ b/vendor/rand/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"163f660fdd260ee2aade895b64c86f6cecf1974d4c46f67496828095876f30a3","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.toml":"001ce77abe9a414eb711cbe40932b9ee88822e63613798ca3976909951bf4c5f","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"779a810c27e3b55bcb1341228340590515851052906c2af288780b8702016deb","src/distributions/bernoulli.rs":"ceaefa810de9e65de9b9bb98985092f01c76166f83c48476b2d2261ed612f49e","src/distributions/float.rs":"e5c22bb31a2297ed554553b671084d9a41f110d414b52eaa24fd6e7759bccfc7","src/distributions/integer.rs":"16948664d86a506ed8a401d602238e08ae6f74744b4a656167f8c2a70f7455bb","src/distributions/mod.rs":"8fcee0cf3434343a7cb3a6b0be03191d202cbc6375e8516700411513831c5775","src/distributions/other.rs":"e99827bdfe6da505b837dcd6dfb831a02d8b57e0c5cdaacbd086184c07f6ebc1","src/distributions/uniform.rs":"ab6bfd4a4e7df146d501fa56dffaf9f91cfe10e1f4ac4cbc8920b583a1005da1","src/distributions/utils.rs":"97bd9e385c3aa24acb2765f0190983c46f34dcd436eec6ced69a7124d1faf41f","src/distributions/weighted.rs":"049ed1ce8dcb66ebfa34bdfebea6c355732b099c564e047c7151e0c4e8fb3114","src/distributions/weighted_index.rs":"f44fe6231c192205515797a759456b5add0b8edd687e89186dcdc200028a965b","src/lib.rs":"4a1daba8371978292f85c52aba3cb357e68c46ef9b56b33e6e7e33d62308bb28","src/prelude.rs":"2f2132d74ce9f70513224baad3b161b1585a639f9136a254cdb0e7f8ffceb25b","src/rng.rs":"50196ee1cad553e7793537de033eb7745a75aafec65e06a46594a4bcadf1a85b","src/rngs/adapter/mod.rs":"1f21d310f3626c7f2d94770e47782db0e71995e1c15363a6d5623f5785b5f14f","src/rngs/adapter/read.rs":"f67300fb9d855355d138a198af70438618335ec39d5d0a4973afbdb54c0cbba6","src/rngs/adapter/reseeding.rs":"59ce72e2a5586ab06c4f29792d46edb4d22de462c5a77476d3492ac3c9a7195e","src/rngs/mock.rs":"0074abe04cf84b1263218f50140931fa4188f4e0a43fe3205556a00e4c36d1e9","src/rngs/mod.rs":"a6dec3d19e1726ba05f130ab9b20719d79177b8c1584cdd7b5f37b9996315ed3","src/rngs/small.rs":"a8e61c6e0bad62f06db1325e3b93eff1d4aa9e82cf0316fbfd02da2ef5b85b83","src/rngs/std.rs":"0fe31f4a9b3f440801965d777b455b066516044b0c83cb69547c17cbd21bf57e","src/rngs/thread.rs":"3249717e00a4cc944829c6ffde289053ae08bc6159dc90a2d397bf583c2cd8ad","src/rngs/xoshiro128plusplus.rs":"deca2450a2d5ea826ca6f47cccb9ee06daeac38799a30a107b78c5dae78ae30c","src/rngs/xoshiro256plusplus.rs":"429c1fdf5013589e253932198352ac9ce72870b32b08402a8f5d8d6aec31b6cb","src/seq/index.rs":"04ecf55d9ddc19df16f140107828855061798f9ad2833b1c033c9018b8109f7c","src/seq/mod.rs":"44ff77a2a31ac578ca36b825624f3cff1a48557e84967ee602bc7bc557a3ea31"},"package":"0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"} \ No newline at end of file diff --git a/vendor/rand/CHANGELOG.md b/vendor/rand/CHANGELOG.md new file mode 100644 index 0000000000..536c510af8 --- /dev/null +++ b/vendor/rand/CHANGELOG.md @@ -0,0 +1,667 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). + +You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. + +## [0.8.3] - 2021-01-25 +### Fixes +- Fix `no-std` + `alloc` build by gating `choose_multiple_weighted` on `std` (#1088) + +## [0.8.2] - 2021-01-12 +### Fixes +- Fix panic in `UniformInt::sample_single_inclusive` and `Rng::gen_range` when + providing a full integer range (eg `0..=MAX`) (#1087) + +## [0.8.1] - 2020-12-31 +### Other +- Enable all stable features in the playground (#1081) + +## [0.8.0] - 2020-12-18 +### Platform support +- The minimum supported Rust version is now 1.36 (#1011) +- `getrandom` updated to v0.2 (#1041) +- Remove `wasm-bindgen` and `stdweb` feature flags. For details of WASM support, + see the [getrandom documentation](https://docs.rs/getrandom/latest). (#948) +- `ReadRng::next_u32` and `next_u64` now use little-Endian conversion instead + of native-Endian, affecting results on Big-Endian platforms (#1061) +- The `nightly` feature no longer implies the `simd_support` feature (#1048) +- Fix `simd_support` feature to work on current nightlies (#1056) + +### Rngs +- `ThreadRng` is no longer `Copy` to enable safe usage within thread-local destructors (#1035) +- `gen_range(a, b)` was replaced with `gen_range(a..b)`. `gen_range(a..=b)` is + also supported. Note that `a` and `b` can no longer be references or SIMD types. (#744, #1003) +- Replace `AsByteSliceMut` with `Fill` and add support for `[bool], [char], [f32], [f64]` (#940) +- Restrict `rand::rngs::adapter` to `std` (#1027; see also #928) +- `StdRng`: add new `std_rng` feature flag (enabled by default, but might need + to be used if disabling default crate features) (#948) +- `StdRng`: Switch from ChaCha20 to ChaCha12 for better performance (#1028) +- `SmallRng`: Replace PCG algorithm with xoshiro{128,256}++ (#1038) + +### Sequences +- Add `IteratorRandom::choose_stable` as an alternative to `choose` which does + not depend on size hints (#1057) +- Improve accuracy and performance of `IteratorRandom::choose` (#1059) +- Implement `IntoIterator` for `IndexVec`, replacing the `into_iter` method (#1007) +- Add value stability tests for `seq` module (#933) + +### Misc +- Support `PartialEq` and `Eq` for `StdRng`, `SmallRng` and `StepRng` (#979) +- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex` (#974) +- Drop some unsafe code (#962, #963, #1011) +- Reduce packaged crate size (#983) +- Migrate to GitHub Actions from Travis+AppVeyor (#1073) + +### Distributions +- `Alphanumeric` samples bytes instead of chars (#935) +- `Uniform` now supports `char`, enabling `rng.gen_range('A'..='Z')` (#1068) +- Add `UniformSampler::sample_single_inclusive` (#1003) + +#### Weighted sampling +- Implement weighted sampling without replacement (#976, #1013) +- `rand::distributions::alias_method::WeightedIndex` was moved to `rand_distr::WeightedAliasIndex`. + The simpler alternative `rand::distribution::WeightedIndex` remains. (#945) +- Improve treatment of rounding errors in `WeightedIndex::update_weights` (#956) +- `WeightedIndex`: return error on NaN instead of panic (#1005) + +### Documentation +- Document types supported by `random` (#994) +- Document notes on password generation (#995) +- Note that `SmallRng` may not be the best choice for performance and in some + other cases (#1038) +- Use `doc(cfg)` to annotate feature-gated items (#1019) +- Adjust README (#1065) + +## [0.7.3] - 2020-01-10 +### Fixes +- The `Bernoulli` distribution constructors now reports an error on NaN and on + `denominator == 0`. (#925) +- Use `std::sync::Once` to register fork handler, avoiding possible atomicity violation (#928) +- Fix documentation on the precision of generated floating-point values + +### Changes +- Unix: make libc dependency optional; only use fork protection with std feature (#928) + +### Additions +- Implement `std::error::Error` for `BernoulliError` (#919) + +## [0.7.2] - 2019-09-16 +### Fixes +- Fix dependency on `rand_core` 0.5.1 (#890) + +### Additions +- Unit tests for value stability of distributions added (#888) + +## [0.7.1] - 2019-09-13 +### Yanked +This release was yanked since it depends on `rand_core::OsRng` added in 0.5.1 +but specifies a dependency on version 0.5.0 (#890), causing a broken builds +when updating from `rand 0.7.0` without also updating `rand_core`. + +### Fixes +- Fix `no_std` behaviour, appropriately enable c2-chacha's `std` feature (#844) +- `alloc` feature in `no_std` is available since Rust 1.36 (#856) +- Fix or squelch issues from Clippy lints (#840) + +### Additions +- Add a `no_std` target to CI to continuously evaluate `no_std` status (#844) +- `WeightedIndex`: allow adjusting a sub-set of weights (#866) + +## [0.7.0] - 2019-06-28 + +### Fixes +- Fix incorrect pointer usages revealed by Miri testing (#780, #781) +- Fix (tiny!) bias in `Uniform` for 8- and 16-bit ints (#809) + +### Crate +- Bumped MSRV (min supported Rust version) to 1.32.0 +- Updated to Rust Edition 2018 (#823, #824) +- Removed dependence on `rand_xorshift`, `rand_isaac`, `rand_jitter` crates (#759, #765) +- Remove dependency on `winapi` (#724) +- Removed all `build.rs` files (#824) +- Removed code already deprecated in version 0.6 (#757) +- Removed the serde1 feature (It's still available for backwards compatibility, but it does not do anything. #830) +- Many documentation changes + +### rand_core +- Updated to `rand_core` 0.5.0 +- `Error` type redesigned with new API (#800) +- Move `from_entropy` method to `SeedableRng` and remove `FromEntropy` (#800) +- `SeedableRng::from_rng` is now expected to be value-stable (#815) + +### Standard RNGs +- OS interface moved from `rand_os` to new `getrandom` crate (#765, [getrandom](https://github.com/rust-random/getrandom)) +- Use ChaCha for `StdRng` and `ThreadRng` (#792) +- Feature-gate `SmallRng` (#792) +- `ThreadRng` now supports `Copy` (#758) +- Deprecated `EntropyRng` (#765) +- Enable fork protection of ReseedingRng without `std` (#724) + +### Distributions +- Many distributions have been moved to `rand_distr` (#761) +- `Bernoulli::new` constructor now returns a `Result` (#803) +- `Distribution::sample_iter` adjusted for more flexibility (#758) +- Added `distributions::weighted::alias_method::WeightedIndex` for `O(1)` sampling (#692) +- Support sampling `NonZeroU*` types with the `Standard` distribution (#728) +- Optimised `Binomial` distribution sampling (#735, #740, #752) +- Optimised SIMD float sampling (#739) + +### Sequences +- Make results portable across 32- and 64-bit by using `u32` samples for `usize` where possible (#809) + +## [0.6.5] - 2019-01-28 +### Crates +- Update `rand_core` to 0.4 (#703) +- Move `JitterRng` to its own crate (#685) +- Add a wasm-bindgen test crate (#696) + +### Platforms +- Fuchsia: Replaced fuchsia-zircon with fuchsia-cprng + +### Doc +- Use RFC 1946 for doc links (#691) +- Fix some doc links and notes (#711) + +## [0.6.4] - 2019-01-08 +### Fixes +- Move wasm-bindgen shims to correct crate (#686) +- Make `wasm32-unknown-unknown` compile but fail at run-time if missing bindingsg (#686) + +## [0.6.3] - 2019-01-04 +### Fixes +- Make the `std` feature require the optional `rand_os` dependency (#675) +- Re-export the optional WASM dependencies of `rand_os` from `rand` to avoid breakage (#674) + +## [0.6.2] - 2019-01-04 +### Additions +- Add `Default` for `ThreadRng` (#657) +- Move `rngs::OsRng` to `rand_os` sub-crate; clean up code; use as dependency (#643) ##BLOCKER## +- Add `rand_xoshiro` sub-crate, plus benchmarks (#642, #668) + +### Fixes +- Fix bias in `UniformInt::sample_single` (#662) +- Use `autocfg` instead of `rustc_version` for rustc version detection (#664) +- Disable `i128` and `u128` if the `target_os` is `emscripten` (#671: work-around Emscripten limitation) +- CI fixes (#660, #671) + +### Optimisations +- Optimise memory usage of `UnitCircle` and `UnitSphereSurface` distributions (no PR) + +## [0.6.1] - 2018-11-22 +- Support sampling `Duration` also for `no_std` (only since Rust 1.25) (#649) +- Disable default features of `libc` (#647) + +## [0.6.0] - 2018-11-14 + +### Project organisation +- Rand has moved from [rust-lang-nursery](https://github.com/rust-lang-nursery/rand) + to [rust-random](https://github.com/rust-random/rand)! (#578) +- Created [The Rust Random Book](https://rust-random.github.io/book/) + ([source](https://github.com/rust-random/book)) +- Update copyright and licence notices (#591, #611) +- Migrate policy documentation from the wiki (#544) + +### Platforms +- Add fork protection on Unix (#466) +- Added support for wasm-bindgen. (#541, #559, #562, #600) +- Enable `OsRng` for powerpc64, sparc and sparc64 (#609) +- Use `syscall` from `libc` on Linux instead of redefining it (#629) + +### RNGs +- Switch `SmallRng` to use PCG (#623) +- Implement `Pcg32` and `Pcg64Mcg` generators (#632) +- Move ISAAC RNGs to a dedicated crate (#551) +- Move Xorshift RNG to its own crate (#557) +- Move ChaCha and HC128 RNGs to dedicated crates (#607, #636) +- Remove usage of `Rc` from `ThreadRng` (#615) + +### Sampling and distributions +- Implement `Rng.gen_ratio()` and `Bernoulli::new_ratio()` (#491) +- Make `Uniform` strictly respect `f32` / `f64` high/low bounds (#477) +- Allow `gen_range` and `Uniform` to work on non-`Copy` types (#506) +- `Uniform` supports inclusive ranges: `Uniform::from(a..=b)`. This is + automatically enabled for Rust >= 1.27. (#566) +- Implement `TrustedLen` and `FusedIterator` for `DistIter` (#620) + +#### New distributions +- Add the `Dirichlet` distribution (#485) +- Added sampling from the unit sphere and circle. (#567) +- Implement the triangular distribution (#575) +- Implement the Weibull distribution (#576) +- Implement the Beta distribution (#574) + +#### Optimisations + +- Optimise `Bernoulli::new` (#500) +- Optimise `char` sampling (#519) +- Optimise sampling of `std::time::Duration` (#583) + +### Sequences +- Redesign the `seq` module (#483, #515) +- Add `WeightedIndex` and `choose_weighted` (#518, #547) +- Optimised and changed return type of the `sample_indices` function. (#479) +- Use `Iterator::size_hint()` to speed up `IteratorRandom::choose` (#593) + +### SIMD +- Support for generating SIMD types (#523, #542, #561, #630) + +### Other +- Revise CI scripts (#632, #635) +- Remove functionality already deprecated in 0.5 (#499) +- Support for `i128` and `u128` is automatically enabled for Rust >= 1.26. This + renders the `i128_support` feature obsolete. It still exists for backwards + compatibility but does not have any effect. This breaks programs using Rand + with `i128_support` on nightlies older than Rust 1.26. (#571) + + +## [0.5.5] - 2018-08-07 +### Documentation +- Fix links in documentation (#582) + + +## [0.5.4] - 2018-07-11 +### Platform support +- Make `OsRng` work via WASM/stdweb for WebWorkers + + +## [0.5.3] - 2018-06-26 +### Platform support +- OpenBSD, Bitrig: fix compilation (broken in 0.5.1) (#530) + + +## [0.5.2] - 2018-06-18 +### Platform support +- Hide `OsRng` and `JitterRng` on unsupported platforms (#512; fixes #503). + + +## [0.5.1] - 2018-06-08 + +### New distributions +- Added Cauchy distribution. (#474, #486) +- Added Pareto distribution. (#495) + +### Platform support and `OsRng` +- Remove blanket Unix implementation. (#484) +- Remove Wasm unimplemented stub. (#484) +- Dragonfly BSD: read from `/dev/random`. (#484) +- Bitrig: use `getentropy` like OpenBSD. (#484) +- Solaris: (untested) use `getrandom` if available, otherwise `/dev/random`. (#484) +- Emscripten, `stdweb`: split the read up in chunks. (#484) +- Emscripten, Haiku: don't do an extra blocking read from `/dev/random`. (#484) +- Linux, NetBSD, Solaris: read in blocking mode on first use in `fill_bytes`. (#484) +- Fuchsia, CloudABI: fix compilation (broken in Rand 0.5). (#484) + + +## [0.5.0] - 2018-05-21 + +### Crate features and organisation +- Minimum Rust version update: 1.22.0. (#239) +- Create a separate `rand_core` crate. (#288) +- Deprecate `rand_derive`. (#256) +- Add `prelude` (and module reorganisation). (#435) +- Add `log` feature. Logging is now available in `JitterRng`, `OsRng`, `EntropyRng` and `ReseedingRng`. (#246) +- Add `serde1` feature for some PRNGs. (#189) +- `stdweb` feature for `OsRng` support on WASM via stdweb. (#272, #336) + +### `Rng` trait +- Split `Rng` in `RngCore` and `Rng` extension trait. + `next_u32`, `next_u64` and `fill_bytes` are now part of `RngCore`. (#265) +- Add `Rng::sample`. (#256) +- Deprecate `Rng::gen_weighted_bool`. (#308) +- Add `Rng::gen_bool`. (#308) +- Remove `Rng::next_f32` and `Rng::next_f64`. (#273) +- Add optimized `Rng::fill` and `Rng::try_fill` methods. (#247) +- Deprecate `Rng::gen_iter`. (#286) +- Deprecate `Rng::gen_ascii_chars`. (#279) + +### `rand_core` crate +- `rand` now depends on new `rand_core` crate (#288) +- `RngCore` and `SeedableRng` are now part of `rand_core`. (#288) +- Add modules to help implementing RNGs `impl` and `le`. (#209, #228) +- Add `Error` and `ErrorKind`. (#225) +- Add `CryptoRng` marker trait. (#273) +- Add `BlockRngCore` trait. (#281) +- Add `BlockRng` and `BlockRng64` wrappers to help implementations. (#281, #325) +- Revise the `SeedableRng` trait. (#233) +- Remove default implementations for `RngCore::next_u64` and `RngCore::fill_bytes`. (#288) +- Add `RngCore::try_fill_bytes`. (#225) + +### Other traits and types +- Add `FromEntropy` trait. (#233, #375) +- Add `SmallRng` wrapper. (#296) +- Rewrite `ReseedingRng` to only work with `BlockRngCore` (substantial performance improvement). (#281) +- Deprecate `weak_rng`. Use `SmallRng` instead. (#296) +- Deprecate `AsciiGenerator`. (#279) + +### Random number generators +- Switch `StdRng` and `thread_rng` to HC-128. (#277) +- `StdRng` must now be created with `from_entropy` instead of `new` +- Change `thread_rng` reseeding threshold to 32 MiB. (#277) +- PRNGs no longer implement `Copy`. (#209) +- `Debug` implementations no longer show internals. (#209) +- Implement `Clone` for `ReseedingRng`, `JitterRng`, OsRng`. (#383, #384) +- Implement serialization for `XorShiftRng`, `IsaacRng` and `Isaac64Rng` under the `serde1` feature. (#189) +- Implement `BlockRngCore` for `ChaChaCore` and `Hc128Core`. (#281) +- All PRNGs are now portable across big- and little-endian architectures. (#209) +- `Isaac64Rng::next_u32` no longer throws away half the results. (#209) +- Add `IsaacRng::new_from_u64` and `Isaac64Rng::new_from_u64`. (#209) +- Add the HC-128 CSPRNG `Hc128Rng`. (#210) +- Change ChaCha20 to have 64-bit counter and 64-bit stream. (#349) +- Changes to `JitterRng` to get its size down from 2112 to 24 bytes. (#251) +- Various performance improvements to all PRNGs. + +### Platform support and `OsRng` +- Add support for CloudABI. (#224) +- Remove support for NaCl. (#225) +- WASM support for `OsRng` via stdweb, behind the `stdweb` feature. (#272, #336) +- Use `getrandom` on more platforms for Linux, and on Android. (#338) +- Use the `SecRandomCopyBytes` interface on macOS. (#322) +- On systems that do not have a syscall interface, only keep a single file descriptor open for `OsRng`. (#239) +- On Unix, first try a single read from `/dev/random`, then `/dev/urandom`. (#338) +- Better error handling and reporting in `OsRng` (using new error type). (#225) +- `OsRng` now uses non-blocking when available. (#225) +- Add `EntropyRng`, which provides `OsRng`, but has `JitterRng` as a fallback. (#235) + +### Distributions +- New `Distribution` trait. (#256) +- Add `Distribution::sample_iter` and `Rng::::sample_iter`. (#361) +- Deprecate `Rand`, `Sample` and `IndependentSample` traits. (#256) +- Add a `Standard` distribution (replaces most `Rand` implementations). (#256) +- Add `Binomial` and `Poisson` distributions. (#96) +- Add `Bernoulli` dsitribution. (#411) +- Add `Alphanumeric` distribution. (#279) +- Remove `Closed01` distribution, add `OpenClosed01`. (#274, #420) +- Rework `Range` type, making it possible to implement it for user types. (#274) +- Rename `Range` to `Uniform`. (#395) +- Add `Uniform::new_inclusive` for inclusive ranges. (#274) +- Use widening multiply method for much faster integer range reduction. (#274) +- `Standard` distribution for `char` uses `Uniform` internally. (#274) +- `Standard` distribution for `bool` uses sign test. (#274) +- Implement `Standard` distribution for `Wrapping`. (#436) +- Implement `Uniform` distribution for `Duration`. (#427) + + +## [0.4.3] - 2018-08-16 +### Fixed +- Use correct syscall number for PowerPC (#589) + + +## [0.4.2] - 2018-01-06 +### Changed +- Use `winapi` on Windows +- Update for Fuchsia OS +- Remove dev-dependency on `log` + + +## [0.4.1] - 2017-12-17 +### Added +- `no_std` support + + +## [0.4.0-pre.0] - 2017-12-11 +### Added +- `JitterRng` added as a high-quality alternative entropy source using the + system timer +- new `seq` module with `sample_iter`, `sample_slice`, etc. +- WASM support via dummy implementations (fail at run-time) +- Additional benchmarks, covering generators and new seq code + +### Changed +- `thread_rng` uses `JitterRng` if seeding from system time fails + (slower but more secure than previous method) + +### Deprecated + - `sample` function deprecated (replaced by `sample_iter`) + + +## [0.3.20] - 2018-01-06 +### Changed +- Remove dev-dependency on `log` +- Update `fuchsia-zircon` dependency to 0.3.2 + + +## [0.3.19] - 2017-12-27 +### Changed +- Require `log <= 0.3.8` for dev builds +- Update `fuchsia-zircon` dependency to 0.3 +- Fix broken links in docs (to unblock compiler docs testing CI) + + +## [0.3.18] - 2017-11-06 +### Changed +- `thread_rng` is seeded from the system time if `OsRng` fails +- `weak_rng` now uses `thread_rng` internally + + +## [0.3.17] - 2017-10-07 +### Changed + - Fuchsia: Magenta was renamed Zircon + +## [0.3.16] - 2017-07-27 +### Added +- Implement Debug for mote non-public types +- implement `Rand` for (i|u)i128 +- Support for Fuchsia + +### Changed +- Add inline attribute to SampleRange::construct_range. + This improves the benchmark for sample in 11% and for shuffle in 16%. +- Use `RtlGenRandom` instead of `CryptGenRandom` + + +## [0.3.15] - 2016-11-26 +### Added +- Add `Rng` trait method `choose_mut` +- Redox support + +### Changed +- Use `arc4rand` for `OsRng` on FreeBSD. +- Use `arc4random(3)` for `OsRng` on OpenBSD. + +### Fixed +- Fix filling buffers 4 GiB or larger with `OsRng::fill_bytes` on Windows + + +## [0.3.14] - 2016-02-13 +### Fixed +- Inline definitions from winapi/advapi32, which decreases build times + + +## [0.3.13] - 2016-01-09 +### Fixed +- Compatible with Rust 1.7.0-nightly (needed some extra type annotations) + + +## [0.3.12] - 2015-11-09 +### Changed +- Replaced the methods in `next_f32` and `next_f64` with the technique described + Saito & Matsumoto at MCQMC'08. The new method should exhibit a slightly more + uniform distribution. +- Depend on libc 0.2 + +### Fixed +- Fix iterator protocol issue in `rand::sample` + + +## [0.3.11] - 2015-08-31 +### Added +- Implement `Rand` for arrays with n <= 32 + + +## [0.3.10] - 2015-08-17 +### Added +- Support for NaCl platforms + +### Changed +- Allow `Rng` to be `?Sized`, impl for `&mut R` and `Box` where `R: ?Sized + Rng` + + +## [0.3.9] - 2015-06-18 +### Changed +- Use `winapi` for Windows API things + +### Fixed +- Fixed test on stable/nightly +- Fix `getrandom` syscall number for aarch64-unknown-linux-gnu + + +## [0.3.8] - 2015-04-23 +### Changed +- `log` is a dev dependency + +### Fixed +- Fix race condition of atomics in `is_getrandom_available` + + +## [0.3.7] - 2015-04-03 +### Fixed +- Derive Copy/Clone changes + + +## [0.3.6] - 2015-04-02 +### Changed +- Move to stable Rust! + + +## [0.3.5] - 2015-04-01 +### Fixed +- Compatible with Rust master + + +## [0.3.4] - 2015-03-31 +### Added +- Implement Clone for `Weighted` + +### Fixed +- Compatible with Rust master + + +## [0.3.3] - 2015-03-26 +### Fixed +- Fix compile on Windows + + +## [0.3.2] - 2015-03-26 + + +## [0.3.1] - 2015-03-26 +### Fixed +- Fix compile on Windows + + +## [0.3.0] - 2015-03-25 +### Changed +- Update to use log version 0.3.x + + +## [0.2.1] - 2015-03-22 +### Fixed +- Compatible with Rust master +- Fixed iOS compilation + + +## [0.2.0] - 2015-03-06 +### Fixed +- Compatible with Rust master (move from `old_io` to `std::io`) + + +## [0.1.4] - 2015-03-04 +### Fixed +- Compatible with Rust master (use wrapping ops) + + +## [0.1.3] - 2015-02-20 +### Fixed +- Compatible with Rust master + +### Removed +- Removed Copy implementations from RNGs + + +## [0.1.2] - 2015-02-03 +### Added +- Imported functionality from `std::rand`, including: + - `StdRng`, `SeedableRng`, `TreadRng`, `weak_rng()` + - `ReaderRng`: A wrapper around any Reader to treat it as an RNG. +- Imported documentation from `std::rand` +- Imported tests from `std::rand` + + +## [0.1.1] - 2015-02-03 +### Added +- Migrate to a cargo-compatible directory structure. + +### Fixed +- Do not use entropy during `gen_weighted_bool(1)` + + +## [Rust 0.12.0] - 2014-10-09 +### Added +- Impl Rand for tuples of arity 11 and 12 +- Include ChaCha pseudorandom generator +- Add `next_f64` and `next_f32` to Rng +- Implement Clone for PRNGs + +### Changed +- Rename `TaskRng` to `ThreadRng` and `task_rng` to `thread_rng` (since a + runtime is removed from Rust). + +### Fixed +- Improved performance of ISAAC and ISAAC64 by 30% and 12 % respectively, by + informing the optimiser that indexing is never out-of-bounds. + +### Removed +- Removed the Deprecated `choose_option` + + +## [Rust 0.11.0] - 2014-07-02 +### Added +- document when to use `OSRng` in cryptographic context, and explain why we use `/dev/urandom` instead of `/dev/random` +- `Rng::gen_iter()` which will return an infinite stream of random values +- `Rng::gen_ascii_chars()` which will return an infinite stream of random ascii characters + +### Changed +- Now only depends on libcore! +- Remove `Rng.choose()`, rename `Rng.choose_option()` to `.choose()` +- Rename OSRng to OsRng +- The WeightedChoice structure is no longer built with a `Vec>`, + but rather a `&mut [Weighted]`. This means that the WeightedChoice + structure now has a lifetime associated with it. +- The `sample` method on `Rng` has been moved to a top-level function in the + `rand` module due to its dependence on `Vec`. + +### Removed +- `Rng::gen_vec()` was removed. Previous behavior can be regained with + `rng.gen_iter().take(n).collect()` +- `Rng::gen_ascii_str()` was removed. Previous behavior can be regained with + `rng.gen_ascii_chars().take(n).collect()` +- {IsaacRng, Isaac64Rng, XorShiftRng}::new() have all been removed. These all + relied on being able to use an OSRng for seeding, but this is no longer + available in librand (where these types are defined). To retain the same + functionality, these types now implement the `Rand` trait so they can be + generated with a random seed from another random number generator. This allows + the stdlib to use an OSRng to create seeded instances of these RNGs. +- Rand implementations for `Box` and `@T` were removed. These seemed to be + pretty rare in the codebase, and it allows for librand to not depend on + liballoc. Additionally, other pointer types like Rc and Arc were not + supported. +- Remove a slew of old deprecated functions + + +## [Rust 0.10] - 2014-04-03 +### Changed +- replace `Rng.shuffle's` functionality with `.shuffle_mut` +- bubble up IO errors when creating an OSRng + +### Fixed +- Use `fill()` instead of `read()` +- Rewrite OsRng in Rust for windows + +## [0.10-pre] - 2014-03-02 +### Added +- Seperate `rand` out of the standard library diff --git a/vendor/rand/COPYRIGHT b/vendor/rand/COPYRIGHT new file mode 100644 index 0000000000..468d907caf --- /dev/null +++ b/vendor/rand/COPYRIGHT @@ -0,0 +1,12 @@ +Copyrights in the Rand project are retained by their contributors. No +copyright assignment is required to contribute to the Rand project. + +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), Rand is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + +The Rand project includes code from the Rust project +published under these same licenses. diff --git a/vendor/rand/Cargo.toml b/vendor/rand/Cargo.toml new file mode 100644 index 0000000000..108633517e --- /dev/null +++ b/vendor/rand/Cargo.toml @@ -0,0 +1,80 @@ +# 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 = "rand" +version = "0.8.3" +authors = ["The Rand Project Developers", "The Rust Project Developers"] +include = ["src/", "LICENSE-*", "README.md", "CHANGELOG.md", "COPYRIGHT"] +autobenches = true +description = "Random number generators and other randomness functionality.\n" +homepage = "https://rust-random.github.io/book" +documentation = "https://docs.rs/rand" +readme = "README.md" +keywords = ["random", "rng"] +categories = ["algorithms", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/rand" +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "doc_cfg"] + +[package.metadata.playground] +features = ["small_rng", "serde1"] +[dependencies.log] +version = "0.4.4" +optional = true + +[dependencies.packed_simd] +version = "0.3.4" +features = ["into_bits"] +optional = true +package = "packed_simd_2" + +[dependencies.rand_core] +version = "0.6.0" + +[dependencies.serde] +version = "1.0.103" +features = ["derive"] +optional = true +[dev-dependencies.bincode] +version = "1.2.1" + +[dev-dependencies.rand_hc] +version = "0.3.0" + +[dev-dependencies.rand_pcg] +version = "0.3.0" + +[features] +alloc = ["rand_core/alloc"] +default = ["std", "std_rng"] +getrandom = ["rand_core/getrandom"] +nightly = [] +serde1 = ["serde"] +simd_support = ["packed_simd"] +small_rng = [] +std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom", "libc"] +std_rng = ["rand_chacha", "rand_hc"] +[target."cfg(not(target_os = \"emscripten\"))".dependencies.rand_chacha] +version = "0.3.0" +optional = true +default-features = false +[target."cfg(target_os = \"emscripten\")".dependencies.rand_hc] +version = "0.3.0" +optional = true +[target."cfg(unix)".dependencies.libc] +version = "0.2.22" +optional = true +default-features = false diff --git a/vendor/socket2/LICENSE-APACHE b/vendor/rand/LICENSE-APACHE similarity index 99% rename from vendor/socket2/LICENSE-APACHE rename to vendor/rand/LICENSE-APACHE index 16fe87b06e..17d74680f8 100644 --- a/vendor/socket2/LICENSE-APACHE +++ b/vendor/rand/LICENSE-APACHE @@ -1,6 +1,6 @@ Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -192,7 +192,7 @@ 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 + https://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, diff --git a/vendor/rand/LICENSE-MIT b/vendor/rand/LICENSE-MIT new file mode 100644 index 0000000000..d93b5baf34 --- /dev/null +++ b/vendor/rand/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright 2018 Developers of the Rand project +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/rand/README.md b/vendor/rand/README.md new file mode 100644 index 0000000000..aaf6df1d58 --- /dev/null +++ b/vendor/rand/README.md @@ -0,0 +1,148 @@ +# Rand + +[![Test Status](https://github.com/rust-random/rand/workflows/Tests/badge.svg?event=push)](https://github.com/rust-random/rand/actions) +[![Crate](https://img.shields.io/crates/v/rand.svg)](https://crates.io/crates/rand) +[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) +[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand) +[![API](https://docs.rs/rand/badge.svg)](https://docs.rs/rand) +[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements) + +A Rust library for random number generation, featuring: + +- Easy random value generation and usage via the [`Rng`](https://docs.rs/rand/*/rand/trait.Rng.html), + [`SliceRandom`](https://docs.rs/rand/*/rand/seq/trait.SliceRandom.html) and + [`IteratorRandom`](https://docs.rs/rand/*/rand/seq/trait.IteratorRandom.html) traits +- Secure seeding via the [`getrandom` crate](https://crates.io/crates/getrandom) + and fast, convenient generation via [`thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html) +- A modular design built over [`rand_core`](https://crates.io/crates/rand_core) + ([see the book](https://rust-random.github.io/book/crates.html)) +- Fast implementations of the best-in-class [cryptographic](https://rust-random.github.io/book/guide-rngs.html#cryptographically-secure-pseudo-random-number-generators-csprngs) and + [non-cryptographic](https://rust-random.github.io/book/guide-rngs.html#basic-pseudo-random-number-generators-prngs) generators +- A flexible [`distributions`](https://docs.rs/rand/*/rand/distributions/index.html) module +- Samplers for a large number of random number distributions via our own + [`rand_distr`](https://docs.rs/rand_distr) and via + the [`statrs`](https://docs.rs/statrs/0.13.0/statrs/) +- [Portably reproducible output](https://rust-random.github.io/book/portability.html) +- `#[no_std]` compatibility (partial) +- *Many* performance optimisations + +It's also worth pointing out what `rand` *is not*: + +- Small. Most low-level crates are small, but the higher-level `rand` and + `rand_distr` each contain a lot of functionality. +- Simple (implementation). We have a strong focus on correctness, speed and flexibility, but + not simplicity. If you prefer a small-and-simple library, there are + alternatives including [fastrand](https://crates.io/crates/fastrand) + and [oorandom](https://crates.io/crates/oorandom). +- Slow. We take performance seriously, with considerations also for set-up + time of new distributions, commonly-used parameters, and parameters of the + current sampler. + +Documentation: + +- [The Rust Rand Book](https://rust-random.github.io/book) +- [API reference (master branch)](https://rust-random.github.io/rand) +- [API reference (docs.rs)](https://docs.rs/rand) + + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +rand = "0.8.0" +``` + +To get started using Rand, see [The Book](https://rust-random.github.io/book). + + +## Versions + +Rand is *mature* (suitable for general usage, with infrequent breaking releases +which minimise breakage) but not yet at 1.0. We maintain compatibility with +pinned versions of the Rust compiler (see below). + +Current Rand versions are: + +- Version 0.7 was released in June 2019, moving most non-uniform distributions + to an external crate, moving `from_entropy` to `SeedableRng`, and many small + changes and fixes. +- Version 0.8 was released in December 2020 with many small changes. + +A detailed [changelog](CHANGELOG.md) is available for releases. + +When upgrading to the next minor series (especially 0.4 → 0.5), we recommend +reading the [Upgrade Guide](https://rust-random.github.io/book/update.html). + +Rand has not yet reached 1.0 implying some breaking changes may arrive in the +future ([SemVer](https://semver.org/) allows each 0.x.0 release to include +breaking changes), but is considered *mature*: breaking changes are minimised +and breaking releases are infrequent. + +Rand libs have inter-dependencies and make use of the +[semver trick](https://github.com/dtolnay/semver-trick/) in order to make traits +compatible across crate versions. (This is especially important for `RngCore` +and `SeedableRng`.) A few crate releases are thus compatibility shims, +depending on the *next* lib version (e.g. `rand_core` versions `0.2.2` and +`0.3.1`). This means, for example, that `rand_core_0_4_0::SeedableRng` and +`rand_core_0_3_0::SeedableRng` are distinct, incompatible traits, which can +cause build errors. Usually, running `cargo update` is enough to fix any issues. + +### Yanked versions + +Some versions of Rand crates have been yanked ("unreleased"). Where this occurs, +the crate's CHANGELOG *should* be updated with a rationale, and a search on the +issue tracker with the keyword `yank` *should* uncover the motivation. + +### Rust version requirements + +Since version 0.8, Rand requires **Rustc version 1.36 or greater**. +Rand 0.7 requires Rustc 1.32 or greater while versions 0.5 require Rustc 1.22 or +greater, and 0.4 and 0.3 (since approx. June 2017) require Rustc version 1.15 or +greater. Subsets of the Rand code may work with older Rust versions, but this is +not supported. + +Continuous Integration (CI) will always test the minimum supported Rustc version +(the MSRV). The current policy is that this can be updated in any +Rand release if required, but the change must be noted in the changelog. + +## Crate Features + +Rand is built with these features enabled by default: + +- `std` enables functionality dependent on the `std` lib +- `alloc` (implied by `std`) enables functionality requiring an allocator +- `getrandom` (implied by `std`) is an optional dependency providing the code + behind `rngs::OsRng` +- `std_rng` enables inclusion of `StdRng`, `thread_rng` and `random` + (the latter two *also* require that `std` be enabled) + +Optionally, the following dependencies can be enabled: + +- `log` enables logging via the `log` crate` crate + +Additionally, these features configure Rand: + +- `small_rng` enables inclusion of the `SmallRng` PRNG +- `nightly` enables some optimizations requiring nightly Rust +- `simd_support` (experimental) enables sampling of SIMD values + (uniformly random SIMD integers and floats), requiring nightly Rust + +Note that nightly features are not stable and therefore not all library and +compiler versions will be compatible. This is especially true of Rand's +experimental `simd_support` feature. + +Rand supports limited functionality in `no_std` mode (enabled via +`default-features = false`). In this case, `OsRng` and `from_entropy` are +unavailable (unless `getrandom` is enabled), large parts of `seq` are +unavailable (unless `alloc` is enabled), and `thread_rng` and `random` are +unavailable. + +# License + +Rand is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and +[COPYRIGHT](COPYRIGHT) for details. diff --git a/vendor/rand/src/distributions/bernoulli.rs b/vendor/rand/src/distributions/bernoulli.rs new file mode 100644 index 0000000000..b968ca046e --- /dev/null +++ b/vendor/rand/src/distributions/bernoulli.rs @@ -0,0 +1,211 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The Bernoulli distribution. + +use crate::distributions::Distribution; +use crate::Rng; +use core::{fmt, u64}; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; +/// The Bernoulli distribution. +/// +/// This is a special case of the Binomial distribution where `n = 1`. +/// +/// # Example +/// +/// ```rust +/// use rand::distributions::{Bernoulli, Distribution}; +/// +/// let d = Bernoulli::new(0.3).unwrap(); +/// let v = d.sample(&mut rand::thread_rng()); +/// println!("{} is from a Bernoulli distribution", v); +/// ``` +/// +/// # Precision +/// +/// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`), +/// so only probabilities that are multiples of 2-64 can be +/// represented. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct Bernoulli { + /// Probability of success, relative to the maximal integer. + p_int: u64, +} + +// To sample from the Bernoulli distribution we use a method that compares a +// random `u64` value `v < (p * 2^64)`. +// +// If `p == 1.0`, the integer `v` to compare against can not represented as a +// `u64`. We manually set it to `u64::MAX` instead (2^64 - 1 instead of 2^64). +// Note that value of `p < 1.0` can never result in `u64::MAX`, because an +// `f64` only has 53 bits of precision, and the next largest value of `p` will +// result in `2^64 - 2048`. +// +// Also there is a 100% theoretical concern: if someone consistenly wants to +// generate `true` using the Bernoulli distribution (i.e. by using a probability +// of `1.0`), just using `u64::MAX` is not enough. On average it would return +// false once every 2^64 iterations. Some people apparently care about this +// case. +// +// That is why we special-case `u64::MAX` to always return `true`, without using +// the RNG, and pay the performance price for all uses that *are* reasonable. +// Luckily, if `new()` and `sample` are close, the compiler can optimize out the +// extra check. +const ALWAYS_TRUE: u64 = u64::MAX; + +// This is just `2.0.powi(64)`, but written this way because it is not available +// in `no_std` mode. +const SCALE: f64 = 2.0 * (1u64 << 63) as f64; + +/// Error type returned from `Bernoulli::new`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BernoulliError { + /// `p < 0` or `p > 1`. + InvalidProbability, +} + +impl fmt::Display for BernoulliError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + BernoulliError::InvalidProbability => "p is outside [0, 1] in Bernoulli distribution", + }) + } +} + +#[cfg(feature = "std")] +impl ::std::error::Error for BernoulliError {} + +impl Bernoulli { + /// Construct a new `Bernoulli` with the given probability of success `p`. + /// + /// # Precision + /// + /// For `p = 1.0`, the resulting distribution will always generate true. + /// For `p = 0.0`, the resulting distribution will always generate false. + /// + /// This method is accurate for any input `p` in the range `[0, 1]` which is + /// a multiple of 2-64. (Note that not all multiples of + /// 2-64 in `[0, 1]` can be represented as a `f64`.) + #[inline] + pub fn new(p: f64) -> Result { + if !(p >= 0.0 && p < 1.0) { + if p == 1.0 { + return Ok(Bernoulli { p_int: ALWAYS_TRUE }); + } + return Err(BernoulliError::InvalidProbability); + } + Ok(Bernoulli { + p_int: (p * SCALE) as u64, + }) + } + + /// Construct a new `Bernoulli` with the probability of success of + /// `numerator`-in-`denominator`. I.e. `new_ratio(2, 3)` will return + /// a `Bernoulli` with a 2-in-3 chance, or about 67%, of returning `true`. + /// + /// return `true`. If `numerator == 0` it will always return `false`. + /// For `numerator > denominator` and `denominator == 0`, this returns an + /// error. Otherwise, for `numerator == denominator`, samples are always + /// true; for `numerator == 0` samples are always false. + #[inline] + pub fn from_ratio(numerator: u32, denominator: u32) -> Result { + if numerator > denominator || denominator == 0 { + return Err(BernoulliError::InvalidProbability); + } + if numerator == denominator { + return Ok(Bernoulli { p_int: ALWAYS_TRUE }); + } + let p_int = ((f64::from(numerator) / f64::from(denominator)) * SCALE) as u64; + Ok(Bernoulli { p_int }) + } +} + +impl Distribution for Bernoulli { + #[inline] + fn sample(&self, rng: &mut R) -> bool { + // Make sure to always return true for p = 1.0. + if self.p_int == ALWAYS_TRUE { + return true; + } + let v: u64 = rng.gen(); + v < self.p_int + } +} + +#[cfg(test)] +mod test { + use super::Bernoulli; + use crate::distributions::Distribution; + use crate::Rng; + + #[test] + #[cfg(feature="serde1")] + fn test_serializing_deserializing_bernoulli() { + let coin_flip = Bernoulli::new(0.5).unwrap(); + let de_coin_flip : Bernoulli = bincode::deserialize(&bincode::serialize(&coin_flip).unwrap()).unwrap(); + + assert_eq!(coin_flip.p_int, de_coin_flip.p_int); + } + + #[test] + fn test_trivial() { + let mut r = crate::test::rng(1); + let always_false = Bernoulli::new(0.0).unwrap(); + let always_true = Bernoulli::new(1.0).unwrap(); + for _ in 0..5 { + assert_eq!(r.sample::(&always_false), false); + assert_eq!(r.sample::(&always_true), true); + assert_eq!(Distribution::::sample(&always_false, &mut r), false); + assert_eq!(Distribution::::sample(&always_true, &mut r), true); + } + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_average() { + const P: f64 = 0.3; + const NUM: u32 = 3; + const DENOM: u32 = 10; + let d1 = Bernoulli::new(P).unwrap(); + let d2 = Bernoulli::from_ratio(NUM, DENOM).unwrap(); + const N: u32 = 100_000; + + let mut sum1: u32 = 0; + let mut sum2: u32 = 0; + let mut rng = crate::test::rng(2); + for _ in 0..N { + if d1.sample(&mut rng) { + sum1 += 1; + } + if d2.sample(&mut rng) { + sum2 += 1; + } + } + let avg1 = (sum1 as f64) / (N as f64); + assert!((avg1 - P).abs() < 5e-3); + + let avg2 = (sum2 as f64) / (N as f64); + assert!((avg2 - (NUM as f64) / (DENOM as f64)).abs() < 5e-3); + } + + #[test] + fn value_stability() { + let mut rng = crate::test::rng(3); + let distr = Bernoulli::new(0.4532).unwrap(); + let mut buf = [false; 10]; + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(buf, [ + true, false, false, true, false, false, true, true, true, true + ]); + } +} diff --git a/vendor/rand/src/distributions/float.rs b/vendor/rand/src/distributions/float.rs new file mode 100644 index 0000000000..733a40394d --- /dev/null +++ b/vendor/rand/src/distributions/float.rs @@ -0,0 +1,312 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Basic floating-point number distributions + +use crate::distributions::utils::FloatSIMDUtils; +use crate::distributions::{Distribution, Standard}; +use crate::Rng; +use core::mem; +#[cfg(feature = "simd_support")] use packed_simd::*; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + +/// A distribution to sample floating point numbers uniformly in the half-open +/// interval `(0, 1]`, i.e. including 1 but not 0. +/// +/// All values that can be generated are of the form `n * ε/2`. For `f32` +/// the 24 most significant random bits of a `u32` are used and for `f64` the +/// 53 most significant bits of a `u64` are used. The conversion uses the +/// multiplicative method. +/// +/// See also: [`Standard`] which samples from `[0, 1)`, [`Open01`] +/// which samples from `(0, 1)` and [`Uniform`] which samples from arbitrary +/// ranges. +/// +/// # Example +/// ``` +/// use rand::{thread_rng, Rng}; +/// use rand::distributions::OpenClosed01; +/// +/// let val: f32 = thread_rng().sample(OpenClosed01); +/// println!("f32 from (0, 1): {}", val); +/// ``` +/// +/// [`Standard`]: crate::distributions::Standard +/// [`Open01`]: crate::distributions::Open01 +/// [`Uniform`]: crate::distributions::uniform::Uniform +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct OpenClosed01; + +/// A distribution to sample floating point numbers uniformly in the open +/// interval `(0, 1)`, i.e. not including either endpoint. +/// +/// All values that can be generated are of the form `n * ε + ε/2`. For `f32` +/// the 23 most significant random bits of an `u32` are used, for `f64` 52 from +/// an `u64`. The conversion uses a transmute-based method. +/// +/// See also: [`Standard`] which samples from `[0, 1)`, [`OpenClosed01`] +/// which samples from `(0, 1]` and [`Uniform`] which samples from arbitrary +/// ranges. +/// +/// # Example +/// ``` +/// use rand::{thread_rng, Rng}; +/// use rand::distributions::Open01; +/// +/// let val: f32 = thread_rng().sample(Open01); +/// println!("f32 from (0, 1): {}", val); +/// ``` +/// +/// [`Standard`]: crate::distributions::Standard +/// [`OpenClosed01`]: crate::distributions::OpenClosed01 +/// [`Uniform`]: crate::distributions::uniform::Uniform +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct Open01; + + +// This trait is needed by both this lib and rand_distr hence is a hidden export +#[doc(hidden)] +pub trait IntoFloat { + type F; + + /// Helper method to combine the fraction and a contant exponent into a + /// float. + /// + /// Only the least significant bits of `self` may be set, 23 for `f32` and + /// 52 for `f64`. + /// The resulting value will fall in a range that depends on the exponent. + /// As an example the range with exponent 0 will be + /// [20..21), which is [1..2). + fn into_float_with_exponent(self, exponent: i32) -> Self::F; +} + +macro_rules! float_impls { + ($ty:ident, $uty:ident, $f_scalar:ident, $u_scalar:ty, + $fraction_bits:expr, $exponent_bias:expr) => { + impl IntoFloat for $uty { + type F = $ty; + #[inline(always)] + fn into_float_with_exponent(self, exponent: i32) -> $ty { + // The exponent is encoded using an offset-binary representation + let exponent_bits: $u_scalar = + (($exponent_bias + exponent) as $u_scalar) << $fraction_bits; + $ty::from_bits(self | exponent_bits) + } + } + + impl Distribution<$ty> for Standard { + fn sample(&self, rng: &mut R) -> $ty { + // Multiply-based method; 24/53 random bits; [0, 1) interval. + // We use the most significant bits because for simple RNGs + // those are usually more random. + let float_size = mem::size_of::<$f_scalar>() as u32 * 8; + let precision = $fraction_bits + 1; + let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar); + + let value: $uty = rng.gen(); + let value = value >> (float_size - precision); + scale * $ty::cast_from_int(value) + } + } + + impl Distribution<$ty> for OpenClosed01 { + fn sample(&self, rng: &mut R) -> $ty { + // Multiply-based method; 24/53 random bits; (0, 1] interval. + // We use the most significant bits because for simple RNGs + // those are usually more random. + let float_size = mem::size_of::<$f_scalar>() as u32 * 8; + let precision = $fraction_bits + 1; + let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar); + + let value: $uty = rng.gen(); + let value = value >> (float_size - precision); + // Add 1 to shift up; will not overflow because of right-shift: + scale * $ty::cast_from_int(value + 1) + } + } + + impl Distribution<$ty> for Open01 { + fn sample(&self, rng: &mut R) -> $ty { + // Transmute-based method; 23/52 random bits; (0, 1) interval. + // We use the most significant bits because for simple RNGs + // those are usually more random. + use core::$f_scalar::EPSILON; + let float_size = mem::size_of::<$f_scalar>() as u32 * 8; + + let value: $uty = rng.gen(); + let fraction = value >> (float_size - $fraction_bits); + fraction.into_float_with_exponent(0) - (1.0 - EPSILON / 2.0) + } + } + } +} + +float_impls! { f32, u32, f32, u32, 23, 127 } +float_impls! { f64, u64, f64, u64, 52, 1023 } + +#[cfg(feature = "simd_support")] +float_impls! { f32x2, u32x2, f32, u32, 23, 127 } +#[cfg(feature = "simd_support")] +float_impls! { f32x4, u32x4, f32, u32, 23, 127 } +#[cfg(feature = "simd_support")] +float_impls! { f32x8, u32x8, f32, u32, 23, 127 } +#[cfg(feature = "simd_support")] +float_impls! { f32x16, u32x16, f32, u32, 23, 127 } + +#[cfg(feature = "simd_support")] +float_impls! { f64x2, u64x2, f64, u64, 52, 1023 } +#[cfg(feature = "simd_support")] +float_impls! { f64x4, u64x4, f64, u64, 52, 1023 } +#[cfg(feature = "simd_support")] +float_impls! { f64x8, u64x8, f64, u64, 52, 1023 } + + +#[cfg(test)] +mod tests { + use super::*; + use crate::rngs::mock::StepRng; + + const EPSILON32: f32 = ::core::f32::EPSILON; + const EPSILON64: f64 = ::core::f64::EPSILON; + + macro_rules! test_f32 { + ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => { + #[test] + fn $fnn() { + // Standard + let mut zeros = StepRng::new(0, 0); + assert_eq!(zeros.gen::<$ty>(), $ZERO); + let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0); + assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0); + let mut max = StepRng::new(!0, 0); + assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0); + + // OpenClosed01 + let mut zeros = StepRng::new(0, 0); + assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0); + let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0); + assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); + let mut max = StepRng::new(!0, 0); + assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0); + + // Open01 + let mut zeros = StepRng::new(0, 0); + assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0); + let mut one = StepRng::new(1 << 9 | 1 << (9 + 32), 0); + assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0); + let mut max = StepRng::new(!0, 0); + assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0); + } + }; + } + test_f32! { f32_edge_cases, f32, 0.0, EPSILON32 } + #[cfg(feature = "simd_support")] + test_f32! { f32x2_edge_cases, f32x2, f32x2::splat(0.0), f32x2::splat(EPSILON32) } + #[cfg(feature = "simd_support")] + test_f32! { f32x4_edge_cases, f32x4, f32x4::splat(0.0), f32x4::splat(EPSILON32) } + #[cfg(feature = "simd_support")] + test_f32! { f32x8_edge_cases, f32x8, f32x8::splat(0.0), f32x8::splat(EPSILON32) } + #[cfg(feature = "simd_support")] + test_f32! { f32x16_edge_cases, f32x16, f32x16::splat(0.0), f32x16::splat(EPSILON32) } + + macro_rules! test_f64 { + ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => { + #[test] + fn $fnn() { + // Standard + let mut zeros = StepRng::new(0, 0); + assert_eq!(zeros.gen::<$ty>(), $ZERO); + let mut one = StepRng::new(1 << 11, 0); + assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0); + let mut max = StepRng::new(!0, 0); + assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0); + + // OpenClosed01 + let mut zeros = StepRng::new(0, 0); + assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0); + let mut one = StepRng::new(1 << 11, 0); + assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); + let mut max = StepRng::new(!0, 0); + assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0); + + // Open01 + let mut zeros = StepRng::new(0, 0); + assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0); + let mut one = StepRng::new(1 << 12, 0); + assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0); + let mut max = StepRng::new(!0, 0); + assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0); + } + }; + } + test_f64! { f64_edge_cases, f64, 0.0, EPSILON64 } + #[cfg(feature = "simd_support")] + test_f64! { f64x2_edge_cases, f64x2, f64x2::splat(0.0), f64x2::splat(EPSILON64) } + #[cfg(feature = "simd_support")] + test_f64! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64) } + #[cfg(feature = "simd_support")] + test_f64! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64) } + + #[test] + fn value_stability() { + fn test_samples>( + distr: &D, zero: T, expected: &[T], + ) { + let mut rng = crate::test::rng(0x6f44f5646c2a7334); + let mut buf = [zero; 3]; + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected); + } + + test_samples(&Standard, 0f32, &[0.0035963655, 0.7346052, 0.09778172]); + test_samples(&Standard, 0f64, &[ + 0.7346051961657583, + 0.20298547462974248, + 0.8166436635290655, + ]); + + test_samples(&OpenClosed01, 0f32, &[0.003596425, 0.73460525, 0.09778178]); + test_samples(&OpenClosed01, 0f64, &[ + 0.7346051961657584, + 0.2029854746297426, + 0.8166436635290656, + ]); + + test_samples(&Open01, 0f32, &[0.0035963655, 0.73460525, 0.09778172]); + test_samples(&Open01, 0f64, &[ + 0.7346051961657584, + 0.20298547462974248, + 0.8166436635290656, + ]); + + #[cfg(feature = "simd_support")] + { + // We only test a sub-set of types here. Values are identical to + // non-SIMD types; we assume this pattern continues across all + // SIMD types. + + test_samples(&Standard, f32x2::new(0.0, 0.0), &[ + f32x2::new(0.0035963655, 0.7346052), + f32x2::new(0.09778172, 0.20298547), + f32x2::new(0.34296435, 0.81664366), + ]); + + test_samples(&Standard, f64x2::new(0.0, 0.0), &[ + f64x2::new(0.7346051961657583, 0.20298547462974248), + f64x2::new(0.8166436635290655, 0.7423708925400552), + f64x2::new(0.16387782224016323, 0.9087068770169618), + ]); + } + } +} diff --git a/vendor/rand/src/distributions/integer.rs b/vendor/rand/src/distributions/integer.rs new file mode 100644 index 0000000000..8a2ce4cf1e --- /dev/null +++ b/vendor/rand/src/distributions/integer.rs @@ -0,0 +1,279 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The implementations of the `Standard` distribution for integer types. + +use crate::distributions::{Distribution, Standard}; +use crate::Rng; +#[cfg(all(target_arch = "x86", feature = "simd_support"))] +use core::arch::x86::{__m128i, __m256i}; +#[cfg(all(target_arch = "x86_64", feature = "simd_support"))] +use core::arch::x86_64::{__m128i, __m256i}; +#[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128; +use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; +#[cfg(feature = "simd_support")] use packed_simd::*; + +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> u8 { + rng.next_u32() as u8 + } +} + +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> u16 { + rng.next_u32() as u16 + } +} + +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> u32 { + rng.next_u32() + } +} + +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> u64 { + rng.next_u64() + } +} + +#[cfg(not(target_os = "emscripten"))] +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> u128 { + // Use LE; we explicitly generate one value before the next. + let x = u128::from(rng.next_u64()); + let y = u128::from(rng.next_u64()); + (y << 64) | x + } +} + +impl Distribution for Standard { + #[inline] + #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] + fn sample(&self, rng: &mut R) -> usize { + rng.next_u32() as usize + } + + #[inline] + #[cfg(target_pointer_width = "64")] + fn sample(&self, rng: &mut R) -> usize { + rng.next_u64() as usize + } +} + +macro_rules! impl_int_from_uint { + ($ty:ty, $uty:ty) => { + impl Distribution<$ty> for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> $ty { + rng.gen::<$uty>() as $ty + } + } + }; +} + +impl_int_from_uint! { i8, u8 } +impl_int_from_uint! { i16, u16 } +impl_int_from_uint! { i32, u32 } +impl_int_from_uint! { i64, u64 } +#[cfg(not(target_os = "emscripten"))] +impl_int_from_uint! { i128, u128 } +impl_int_from_uint! { isize, usize } + +macro_rules! impl_nzint { + ($ty:ty, $new:path) => { + impl Distribution<$ty> for Standard { + fn sample(&self, rng: &mut R) -> $ty { + loop { + if let Some(nz) = $new(rng.gen()) { + break nz; + } + } + } + } + }; +} + +impl_nzint!(NonZeroU8, NonZeroU8::new); +impl_nzint!(NonZeroU16, NonZeroU16::new); +impl_nzint!(NonZeroU32, NonZeroU32::new); +impl_nzint!(NonZeroU64, NonZeroU64::new); +#[cfg(not(target_os = "emscripten"))] +impl_nzint!(NonZeroU128, NonZeroU128::new); +impl_nzint!(NonZeroUsize, NonZeroUsize::new); + +#[cfg(feature = "simd_support")] +macro_rules! simd_impl { + ($(($intrinsic:ident, $vec:ty),)+) => {$( + impl Distribution<$intrinsic> for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> $intrinsic { + $intrinsic::from_bits(rng.gen::<$vec>()) + } + } + )+}; + + ($bits:expr,) => {}; + ($bits:expr, $ty:ty, $($ty_more:ty,)*) => { + simd_impl!($bits, $($ty_more,)*); + + impl Distribution<$ty> for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> $ty { + let mut vec: $ty = Default::default(); + unsafe { + let ptr = &mut vec; + let b_ptr = &mut *(ptr as *mut $ty as *mut [u8; $bits/8]); + rng.fill_bytes(b_ptr); + } + vec.to_le() + } + } + }; +} + +#[cfg(feature = "simd_support")] +simd_impl!(16, u8x2, i8x2,); +#[cfg(feature = "simd_support")] +simd_impl!(32, u8x4, i8x4, u16x2, i16x2,); +#[cfg(feature = "simd_support")] +simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,); +#[cfg(feature = "simd_support")] +simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,); +#[cfg(feature = "simd_support")] +simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,); +#[cfg(feature = "simd_support")] +simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,); +#[cfg(all( + feature = "simd_support", + any(target_arch = "x86", target_arch = "x86_64") +))] +simd_impl!((__m128i, u8x16), (__m256i, u8x32),); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_integers() { + let mut rng = crate::test::rng(806); + + rng.sample::(Standard); + rng.sample::(Standard); + rng.sample::(Standard); + rng.sample::(Standard); + rng.sample::(Standard); + #[cfg(not(target_os = "emscripten"))] + rng.sample::(Standard); + + rng.sample::(Standard); + rng.sample::(Standard); + rng.sample::(Standard); + rng.sample::(Standard); + rng.sample::(Standard); + #[cfg(not(target_os = "emscripten"))] + rng.sample::(Standard); + } + + #[test] + fn value_stability() { + fn test_samples(zero: T, expected: &[T]) + where Standard: Distribution { + let mut rng = crate::test::rng(807); + let mut buf = [zero; 3]; + for x in &mut buf { + *x = rng.sample(Standard); + } + assert_eq!(&buf, expected); + } + + test_samples(0u8, &[9, 247, 111]); + test_samples(0u16, &[32265, 42999, 38255]); + test_samples(0u32, &[2220326409, 2575017975, 2018088303]); + test_samples(0u64, &[ + 11059617991457472009, + 16096616328739788143, + 1487364411147516184, + ]); + test_samples(0u128, &[ + 296930161868957086625409848350820761097, + 145644820879247630242265036535529306392, + 111087889832015897993126088499035356354, + ]); + #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] + test_samples(0usize, &[2220326409, 2575017975, 2018088303]); + #[cfg(target_pointer_width = "64")] + test_samples(0usize, &[ + 11059617991457472009, + 16096616328739788143, + 1487364411147516184, + ]); + + test_samples(0i8, &[9, -9, 111]); + // Skip further i* types: they are simple reinterpretation of u* samples + + #[cfg(feature = "simd_support")] + { + // We only test a sub-set of types here and make assumptions about the rest. + + test_samples(u8x2::default(), &[ + u8x2::new(9, 126), + u8x2::new(247, 167), + u8x2::new(111, 149), + ]); + test_samples(u8x4::default(), &[ + u8x4::new(9, 126, 87, 132), + u8x4::new(247, 167, 123, 153), + u8x4::new(111, 149, 73, 120), + ]); + test_samples(u8x8::default(), &[ + u8x8::new(9, 126, 87, 132, 247, 167, 123, 153), + u8x8::new(111, 149, 73, 120, 68, 171, 98, 223), + u8x8::new(24, 121, 1, 50, 13, 46, 164, 20), + ]); + + test_samples(i64x8::default(), &[ + i64x8::new( + -7387126082252079607, + -2350127744969763473, + 1487364411147516184, + 7895421560427121838, + 602190064936008898, + 6022086574635100741, + -5080089175222015595, + -4066367846667249123, + ), + i64x8::new( + 9180885022207963908, + 3095981199532211089, + 6586075293021332726, + 419343203796414657, + 3186951873057035255, + 5287129228749947252, + 444726432079249540, + -1587028029513790706, + ), + i64x8::new( + 6075236523189346388, + 1351763722368165432, + -6192309979959753740, + -7697775502176768592, + -4482022114172078123, + 7522501477800909500, + -1837258847956201231, + -586926753024886735, + ), + ]); + } + } +} diff --git a/vendor/rand/src/distributions/mod.rs b/vendor/rand/src/distributions/mod.rs new file mode 100644 index 0000000000..652f52a183 --- /dev/null +++ b/vendor/rand/src/distributions/mod.rs @@ -0,0 +1,372 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013-2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Generating random samples from probability distributions +//! +//! This module is the home of the [`Distribution`] trait and several of its +//! implementations. It is the workhorse behind some of the convenient +//! functionality of the [`Rng`] trait, e.g. [`Rng::gen`] and of course +//! [`Rng::sample`]. +//! +//! Abstractly, a [probability distribution] describes the probability of +//! occurrence of each value in its sample space. +//! +//! More concretely, an implementation of `Distribution` for type `X` is an +//! algorithm for choosing values from the sample space (a subset of `T`) +//! according to the distribution `X` represents, using an external source of +//! randomness (an RNG supplied to the `sample` function). +//! +//! A type `X` may implement `Distribution` for multiple types `T`. +//! Any type implementing [`Distribution`] is stateless (i.e. immutable), +//! but it may have internal parameters set at construction time (for example, +//! [`Uniform`] allows specification of its sample space as a range within `T`). +//! +//! +//! # The `Standard` distribution +//! +//! The [`Standard`] distribution is important to mention. This is the +//! distribution used by [`Rng::gen`] and represents the "default" way to +//! produce a random value for many different types, including most primitive +//! types, tuples, arrays, and a few derived types. See the documentation of +//! [`Standard`] for more details. +//! +//! Implementing `Distribution` for [`Standard`] for user types `T` makes it +//! possible to generate type `T` with [`Rng::gen`], and by extension also +//! with the [`random`] function. +//! +//! ## Random characters +//! +//! [`Alphanumeric`] is a simple distribution to sample random letters and +//! numbers of the `char` type; in contrast [`Standard`] may sample any valid +//! `char`. +//! +//! +//! # Uniform numeric ranges +//! +//! The [`Uniform`] distribution is more flexible than [`Standard`], but also +//! more specialised: it supports fewer target types, but allows the sample +//! space to be specified as an arbitrary range within its target type `T`. +//! Both [`Standard`] and [`Uniform`] are in some sense uniform distributions. +//! +//! Values may be sampled from this distribution using [`Rng::sample(Range)`] or +//! by creating a distribution object with [`Uniform::new`], +//! [`Uniform::new_inclusive`] or `From`. When the range limits are not +//! known at compile time it is typically faster to reuse an existing +//! `Uniform` object than to call [`Rng::sample(Range)`]. +//! +//! User types `T` may also implement `Distribution` for [`Uniform`], +//! although this is less straightforward than for [`Standard`] (see the +//! documentation in the [`uniform`] module). Doing so enables generation of +//! values of type `T` with [`Rng::sample(Range)`]. +//! +//! ## Open and half-open ranges +//! +//! There are surprisingly many ways to uniformly generate random floats. A +//! range between 0 and 1 is standard, but the exact bounds (open vs closed) +//! and accuracy differ. In addition to the [`Standard`] distribution Rand offers +//! [`Open01`] and [`OpenClosed01`]. See "Floating point implementation" section of +//! [`Standard`] documentation for more details. +//! +//! # Non-uniform sampling +//! +//! Sampling a simple true/false outcome with a given probability has a name: +//! the [`Bernoulli`] distribution (this is used by [`Rng::gen_bool`]). +//! +//! For weighted sampling from a sequence of discrete values, use the +//! [`WeightedIndex`] distribution. +//! +//! This crate no longer includes other non-uniform distributions; instead +//! it is recommended that you use either [`rand_distr`] or [`statrs`]. +//! +//! +//! [probability distribution]: https://en.wikipedia.org/wiki/Probability_distribution +//! [`rand_distr`]: https://crates.io/crates/rand_distr +//! [`statrs`]: https://crates.io/crates/statrs + +//! [`random`]: crate::random +//! [`rand_distr`]: https://crates.io/crates/rand_distr +//! [`statrs`]: https://crates.io/crates/statrs + +use crate::Rng; +use core::iter; + +pub use self::bernoulli::{Bernoulli, BernoulliError}; +pub use self::float::{Open01, OpenClosed01}; +pub use self::other::Alphanumeric; +#[doc(inline)] pub use self::uniform::Uniform; + +#[cfg(feature = "alloc")] +pub use self::weighted_index::{WeightedError, WeightedIndex}; + +mod bernoulli; +pub mod uniform; + +#[deprecated(since = "0.8.0", note = "use rand::distributions::{WeightedIndex, WeightedError} instead")] +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +pub mod weighted; +#[cfg(feature = "alloc")] mod weighted_index; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + +mod float; +#[doc(hidden)] +pub mod hidden_export { + pub use super::float::IntoFloat; // used by rand_distr +} +mod integer; +mod other; +mod utils; + +/// Types (distributions) that can be used to create a random instance of `T`. +/// +/// It is possible to sample from a distribution through both the +/// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and +/// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which +/// produces an iterator that samples from the distribution. +/// +/// All implementations are expected to be immutable; this has the significant +/// advantage of not needing to consider thread safety, and for most +/// distributions efficient state-less sampling algorithms are available. +/// +/// Implementations are typically expected to be portable with reproducible +/// results when used with a PRNG with fixed seed; see the +/// [portability chapter](https://rust-random.github.io/book/portability.html) +/// of The Rust Rand Book. In some cases this does not apply, e.g. the `usize` +/// type requires different sampling on 32-bit and 64-bit machines. +/// +/// [`sample_iter`]: Distribution::method.sample_iter +pub trait Distribution { + /// Generate a random value of `T`, using `rng` as the source of randomness. + fn sample(&self, rng: &mut R) -> T; + + /// Create an iterator that generates random values of `T`, using `rng` as + /// the source of randomness. + /// + /// Note that this function takes `self` by value. This works since + /// `Distribution` is impl'd for `&D` where `D: Distribution`, + /// however borrowing is not automatic hence `distr.sample_iter(...)` may + /// need to be replaced with `(&distr).sample_iter(...)` to borrow or + /// `(&*distr).sample_iter(...)` to reborrow an existing reference. + /// + /// # Example + /// + /// ``` + /// use rand::thread_rng; + /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard}; + /// + /// let mut rng = thread_rng(); + /// + /// // Vec of 16 x f32: + /// let v: Vec = Standard.sample_iter(&mut rng).take(16).collect(); + /// + /// // String: + /// let s: String = Alphanumeric + /// .sample_iter(&mut rng) + /// .take(7) + /// .map(char::from) + /// .collect(); + /// + /// // Dice-rolling: + /// let die_range = Uniform::new_inclusive(1, 6); + /// let mut roll_die = die_range.sample_iter(&mut rng); + /// while roll_die.next().unwrap() != 6 { + /// println!("Not a 6; rolling again!"); + /// } + /// ``` + fn sample_iter(self, rng: R) -> DistIter + where + R: Rng, + Self: Sized, + { + DistIter { + distr: self, + rng, + phantom: ::core::marker::PhantomData, + } + } +} + +impl<'a, T, D: Distribution> Distribution for &'a D { + fn sample(&self, rng: &mut R) -> T { + (*self).sample(rng) + } +} + + +/// An iterator that generates random values of `T` with distribution `D`, +/// using `R` as the source of randomness. +/// +/// This `struct` is created by the [`sample_iter`] method on [`Distribution`]. +/// See its documentation for more. +/// +/// [`sample_iter`]: Distribution::sample_iter +#[derive(Debug)] +pub struct DistIter { + distr: D, + rng: R, + phantom: ::core::marker::PhantomData, +} + +impl Iterator for DistIter +where + D: Distribution, + R: Rng, +{ + type Item = T; + + #[inline(always)] + fn next(&mut self) -> Option { + // Here, self.rng may be a reference, but we must take &mut anyway. + // Even if sample could take an R: Rng by value, we would need to do this + // since Rng is not copyable and we cannot enforce that this is "reborrowable". + Some(self.distr.sample(&mut self.rng)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} + +impl iter::FusedIterator for DistIter +where + D: Distribution, + R: Rng, +{ +} + +#[cfg(features = "nightly")] +impl iter::TrustedLen for DistIter +where + D: Distribution, + R: Rng, +{ +} + + +/// A generic random value distribution, implemented for many primitive types. +/// Usually generates values with a numerically uniform distribution, and with a +/// range appropriate to the type. +/// +/// ## Provided implementations +/// +/// Assuming the provided `Rng` is well-behaved, these implementations +/// generate values with the following ranges and distributions: +/// +/// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed +/// over all values of the type. +/// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all +/// code points in the range `0...0x10_FFFF`, except for the range +/// `0xD800...0xDFFF` (the surrogate code points). This includes +/// unassigned/reserved code points. +/// * `bool`: Generates `false` or `true`, each with probability 0.5. +/// * Floating point types (`f32` and `f64`): Uniformly distributed in the +/// half-open range `[0, 1)`. See notes below. +/// * Wrapping integers (`Wrapping`), besides the type identical to their +/// normal integer variants. +/// +/// The `Standard` distribution also supports generation of the following +/// compound types where all component types are supported: +/// +/// * Tuples (up to 12 elements): each element is generated sequentially. +/// * Arrays (up to 32 elements): each element is generated sequentially; +/// see also [`Rng::fill`] which supports arbitrary array length for integer +/// types and tends to be faster for `u32` and smaller types. +/// * `Option` first generates a `bool`, and if true generates and returns +/// `Some(value)` where `value: T`, otherwise returning `None`. +/// +/// ## Custom implementations +/// +/// The [`Standard`] distribution may be implemented for user types as follows: +/// +/// ``` +/// # #![allow(dead_code)] +/// use rand::Rng; +/// use rand::distributions::{Distribution, Standard}; +/// +/// struct MyF32 { +/// x: f32, +/// } +/// +/// impl Distribution for Standard { +/// fn sample(&self, rng: &mut R) -> MyF32 { +/// MyF32 { x: rng.gen() } +/// } +/// } +/// ``` +/// +/// ## Example usage +/// ``` +/// use rand::prelude::*; +/// use rand::distributions::Standard; +/// +/// let val: f32 = StdRng::from_entropy().sample(Standard); +/// println!("f32 from [0, 1): {}", val); +/// ``` +/// +/// # Floating point implementation +/// The floating point implementations for `Standard` generate a random value in +/// the half-open interval `[0, 1)`, i.e. including 0 but not 1. +/// +/// All values that can be generated are of the form `n * ε/2`. For `f32` +/// the 24 most significant random bits of a `u32` are used and for `f64` the +/// 53 most significant bits of a `u64` are used. The conversion uses the +/// multiplicative method: `(rng.gen::<$uty>() >> N) as $ty * (ε/2)`. +/// +/// See also: [`Open01`] which samples from `(0, 1)`, [`OpenClosed01`] which +/// samples from `(0, 1]` and `Rng::gen_range(0..1)` which also samples from +/// `[0, 1)`. Note that `Open01` uses transmute-based methods which yield 1 bit +/// less precision but may perform faster on some architectures (on modern Intel +/// CPUs all methods have approximately equal performance). +/// +/// [`Uniform`]: uniform::Uniform +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct Standard; + + +#[cfg(test)] +mod tests { + use super::{Distribution, Uniform}; + use crate::Rng; + + #[test] + fn test_distributions_iter() { + use crate::distributions::Open01; + let mut rng = crate::test::rng(210); + let distr = Open01; + let mut iter = Distribution::::sample_iter(distr, &mut rng); + let mut sum: f32 = 0.; + for _ in 0..100 { + sum += iter.next().unwrap(); + } + assert!(0. < sum && sum < 100.); + } + + #[test] + fn test_make_an_iter() { + fn ten_dice_rolls_other_than_five<'a, R: Rng>( + rng: &'a mut R, + ) -> impl Iterator + 'a { + Uniform::new_inclusive(1, 6) + .sample_iter(rng) + .filter(|x| *x != 5) + .take(10) + } + + let mut rng = crate::test::rng(211); + let mut count = 0; + for val in ten_dice_rolls_other_than_five(&mut rng) { + assert!(val >= 1 && val <= 6 && val != 5); + count += 1; + } + assert_eq!(count, 10); + } +} diff --git a/vendor/rand/src/distributions/other.rs b/vendor/rand/src/distributions/other.rs new file mode 100644 index 0000000000..f62fe59aa7 --- /dev/null +++ b/vendor/rand/src/distributions/other.rs @@ -0,0 +1,313 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The implementations of the `Standard` distribution for other built-in types. + +use core::char; +use core::num::Wrapping; + +use crate::distributions::{Distribution, Standard, Uniform}; +use crate::Rng; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + +// ----- Sampling distributions ----- + +/// Sample a `u8`, uniformly distributed over ASCII letters and numbers: +/// a-z, A-Z and 0-9. +/// +/// # Example +/// +/// ``` +/// use std::iter; +/// use rand::{Rng, thread_rng}; +/// use rand::distributions::Alphanumeric; +/// +/// let mut rng = thread_rng(); +/// let chars: String = iter::repeat(()) +/// .map(|()| rng.sample(Alphanumeric)) +/// .map(char::from) +/// .take(7) +/// .collect(); +/// println!("Random chars: {}", chars); +/// ``` +/// +/// # Passwords +/// +/// Users sometimes ask whether it is safe to use a string of random characters +/// as a password. In principle, all RNGs in Rand implementing `CryptoRng` are +/// suitable as a source of randomness for generating passwords (if they are +/// properly seeded), but it is more conservative to only use randomness +/// directly from the operating system via the `getrandom` crate, or the +/// corresponding bindings of a crypto library. +/// +/// When generating passwords or keys, it is important to consider the threat +/// model and in some cases the memorability of the password. This is out of +/// scope of the Rand project, and therefore we defer to the following +/// references: +/// +/// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength) +/// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware) +#[derive(Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct Alphanumeric; + + +// ----- Implementations of distributions ----- + +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> char { + // A valid `char` is either in the interval `[0, 0xD800)` or + // `(0xDFFF, 0x11_0000)`. All `char`s must therefore be in + // `[0, 0x11_0000)` but not in the "gap" `[0xD800, 0xDFFF]` which is + // reserved for surrogates. This is the size of that gap. + const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1; + + // Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used but it + // seemed slower. + let range = Uniform::new(GAP_SIZE, 0x11_0000); + + let mut n = range.sample(rng); + if n <= 0xDFFF { + n -= GAP_SIZE; + } + unsafe { char::from_u32_unchecked(n) } + } +} + +impl Distribution for Alphanumeric { + fn sample(&self, rng: &mut R) -> u8 { + const RANGE: u32 = 26 + 26 + 10; + const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; + // We can pick from 62 characters. This is so close to a power of 2, 64, + // that we can do better than `Uniform`. Use a simple bitshift and + // rejection sampling. We do not use a bitmask, because for small RNGs + // the most significant bits are usually of higher quality. + loop { + let var = rng.next_u32() >> (32 - 6); + if var < RANGE { + return GEN_ASCII_STR_CHARSET[var as usize]; + } + } + } +} + +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> bool { + // We can compare against an arbitrary bit of an u32 to get a bool. + // Because the least significant bits of a lower quality RNG can have + // simple patterns, we compare against the most significant bit. This is + // easiest done using a sign test. + (rng.next_u32() as i32) < 0 + } +} + +macro_rules! tuple_impl { + // use variables to indicate the arity of the tuple + ($($tyvar:ident),* ) => { + // the trailing commas are for the 1 tuple + impl< $( $tyvar ),* > + Distribution<( $( $tyvar ),* , )> + for Standard + where $( Standard: Distribution<$tyvar> ),* + { + #[inline] + fn sample(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) { + ( + // use the $tyvar's to get the appropriate number of + // repeats (they're not actually needed) + $( + _rng.gen::<$tyvar>() + ),* + , + ) + } + } + } +} + +impl Distribution<()> for Standard { + #[allow(clippy::unused_unit)] + #[inline] + fn sample(&self, _: &mut R) -> () { + () + } +} +tuple_impl! {A} +tuple_impl! {A, B} +tuple_impl! {A, B, C} +tuple_impl! {A, B, C, D} +tuple_impl! {A, B, C, D, E} +tuple_impl! {A, B, C, D, E, F} +tuple_impl! {A, B, C, D, E, F, G} +tuple_impl! {A, B, C, D, E, F, G, H} +tuple_impl! {A, B, C, D, E, F, G, H, I} +tuple_impl! {A, B, C, D, E, F, G, H, I, J} +tuple_impl! {A, B, C, D, E, F, G, H, I, J, K} +tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L} + +macro_rules! array_impl { + // recursive, given at least one type parameter: + {$n:expr, $t:ident, $($ts:ident,)*} => { + array_impl!{($n - 1), $($ts,)*} + + impl Distribution<[T; $n]> for Standard where Standard: Distribution { + #[inline] + fn sample(&self, _rng: &mut R) -> [T; $n] { + [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*] + } + } + }; + // empty case: + {$n:expr,} => { + impl Distribution<[T; $n]> for Standard { + fn sample(&self, _rng: &mut R) -> [T; $n] { [] } + } + }; +} + +array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,} + +impl Distribution> for Standard +where Standard: Distribution +{ + #[inline] + fn sample(&self, rng: &mut R) -> Option { + // UFCS is needed here: https://github.com/rust-lang/rust/issues/24066 + if rng.gen::() { + Some(rng.gen()) + } else { + None + } + } +} + +impl Distribution> for Standard +where Standard: Distribution +{ + #[inline] + fn sample(&self, rng: &mut R) -> Wrapping { + Wrapping(rng.gen()) + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use crate::RngCore; + #[cfg(feature = "alloc")] use alloc::string::String; + + #[test] + fn test_misc() { + let rng: &mut dyn RngCore = &mut crate::test::rng(820); + + rng.sample::(Standard); + rng.sample::(Standard); + } + + #[cfg(feature = "alloc")] + #[test] + fn test_chars() { + use core::iter; + let mut rng = crate::test::rng(805); + + // Test by generating a relatively large number of chars, so we also + // take the rejection sampling path. + let word: String = iter::repeat(()) + .map(|()| rng.gen::()) + .take(1000) + .collect(); + assert!(word.len() != 0); + } + + #[test] + fn test_alphanumeric() { + let mut rng = crate::test::rng(806); + + // Test by generating a relatively large number of chars, so we also + // take the rejection sampling path. + let mut incorrect = false; + for _ in 0..100 { + let c: char = rng.sample(Alphanumeric).into(); + incorrect |= !((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') ); + } + assert!(incorrect == false); + } + + #[test] + fn value_stability() { + fn test_samples>( + distr: &D, zero: T, expected: &[T], + ) { + let mut rng = crate::test::rng(807); + let mut buf = [zero; 5]; + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected); + } + + test_samples(&Standard, 'a', &[ + '\u{8cdac}', + '\u{a346a}', + '\u{80120}', + '\u{ed692}', + '\u{35888}', + ]); + test_samples(&Alphanumeric, 0, &[104, 109, 101, 51, 77]); + test_samples(&Standard, false, &[true, true, false, true, false]); + test_samples(&Standard, None as Option, &[ + Some(true), + None, + Some(false), + None, + Some(false), + ]); + test_samples(&Standard, Wrapping(0i32), &[ + Wrapping(-2074640887), + Wrapping(-1719949321), + Wrapping(2018088303), + Wrapping(-547181756), + Wrapping(838957336), + ]); + + // We test only sub-sets of tuple and array impls + test_samples(&Standard, (), &[(), (), (), (), ()]); + test_samples(&Standard, (false,), &[ + (true,), + (true,), + (false,), + (true,), + (false,), + ]); + test_samples(&Standard, (false, false), &[ + (true, true), + (false, true), + (false, false), + (true, false), + (false, false), + ]); + + test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]); + test_samples(&Standard, [0u8; 3], &[ + [9, 247, 111], + [68, 24, 13], + [174, 19, 194], + [172, 69, 213], + [149, 207, 29], + ]); + } +} diff --git a/vendor/rand/src/distributions/uniform.rs b/vendor/rand/src/distributions/uniform.rs new file mode 100644 index 0000000000..e4a6407fd6 --- /dev/null +++ b/vendor/rand/src/distributions/uniform.rs @@ -0,0 +1,1625 @@ +// Copyright 2018-2020 Developers of the Rand project. +// Copyright 2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A distribution uniformly sampling numbers within a given range. +//! +//! [`Uniform`] is the standard distribution to sample uniformly from a range; +//! e.g. `Uniform::new_inclusive(1, 6)` can sample integers from 1 to 6, like a +//! standard die. [`Rng::gen_range`] supports any type supported by +//! [`Uniform`]. +//! +//! This distribution is provided with support for several primitive types +//! (all integer and floating-point types) as well as [`std::time::Duration`], +//! and supports extension to user-defined types via a type-specific *back-end* +//! implementation. +//! +//! The types [`UniformInt`], [`UniformFloat`] and [`UniformDuration`] are the +//! back-ends supporting sampling from primitive integer and floating-point +//! ranges as well as from [`std::time::Duration`]; these types do not normally +//! need to be used directly (unless implementing a derived back-end). +//! +//! # Example usage +//! +//! ``` +//! use rand::{Rng, thread_rng}; +//! use rand::distributions::Uniform; +//! +//! let mut rng = thread_rng(); +//! let side = Uniform::new(-10.0, 10.0); +//! +//! // sample between 1 and 10 points +//! for _ in 0..rng.gen_range(1..=10) { +//! // sample a point from the square with sides -10 - 10 in two dimensions +//! let (x, y) = (rng.sample(side), rng.sample(side)); +//! println!("Point: {}, {}", x, y); +//! } +//! ``` +//! +//! # Extending `Uniform` to support a custom type +//! +//! To extend [`Uniform`] to support your own types, write a back-end which +//! implements the [`UniformSampler`] trait, then implement the [`SampleUniform`] +//! helper trait to "register" your back-end. See the `MyF32` example below. +//! +//! At a minimum, the back-end needs to store any parameters needed for sampling +//! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`. +//! Those methods should include an assert to check the range is valid (i.e. +//! `low < high`). The example below merely wraps another back-end. +//! +//! The `new`, `new_inclusive` and `sample_single` functions use arguments of +//! type SampleBorrow in order to support passing in values by reference or +//! by value. In the implementation of these functions, you can choose to +//! simply use the reference returned by [`SampleBorrow::borrow`], or you can choose +//! to copy or clone the value, whatever is appropriate for your type. +//! +//! ``` +//! use rand::prelude::*; +//! use rand::distributions::uniform::{Uniform, SampleUniform, +//! UniformSampler, UniformFloat, SampleBorrow}; +//! +//! struct MyF32(f32); +//! +//! #[derive(Clone, Copy, Debug)] +//! struct UniformMyF32(UniformFloat); +//! +//! impl UniformSampler for UniformMyF32 { +//! type X = MyF32; +//! fn new(low: B1, high: B2) -> Self +//! where B1: SampleBorrow + Sized, +//! B2: SampleBorrow + Sized +//! { +//! UniformMyF32(UniformFloat::::new(low.borrow().0, high.borrow().0)) +//! } +//! fn new_inclusive(low: B1, high: B2) -> Self +//! where B1: SampleBorrow + Sized, +//! B2: SampleBorrow + Sized +//! { +//! UniformSampler::new(low, high) +//! } +//! fn sample(&self, rng: &mut R) -> Self::X { +//! MyF32(self.0.sample(rng)) +//! } +//! } +//! +//! impl SampleUniform for MyF32 { +//! type Sampler = UniformMyF32; +//! } +//! +//! let (low, high) = (MyF32(17.0f32), MyF32(22.0f32)); +//! let uniform = Uniform::new(low, high); +//! let x = uniform.sample(&mut thread_rng()); +//! ``` +//! +//! [`SampleUniform`]: crate::distributions::uniform::SampleUniform +//! [`UniformSampler`]: crate::distributions::uniform::UniformSampler +//! [`UniformInt`]: crate::distributions::uniform::UniformInt +//! [`UniformFloat`]: crate::distributions::uniform::UniformFloat +//! [`UniformDuration`]: crate::distributions::uniform::UniformDuration +//! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow + +#[cfg(not(feature = "std"))] use core::time::Duration; +#[cfg(feature = "std")] use std::time::Duration; +use core::ops::{Range, RangeInclusive}; + +use crate::distributions::float::IntoFloat; +use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply}; +use crate::distributions::Distribution; +use crate::{Rng, RngCore}; + +#[cfg(not(feature = "std"))] +#[allow(unused_imports)] // rustc doesn't detect that this is actually used +use crate::distributions::utils::Float; + +#[cfg(feature = "simd_support")] use packed_simd::*; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + +/// Sample values uniformly between two bounds. +/// +/// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform +/// distribution sampling from the given range; these functions may do extra +/// work up front to make sampling of multiple values faster. If only one sample +/// from the range is required, [`Rng::gen_range`] can be more efficient. +/// +/// When sampling from a constant range, many calculations can happen at +/// compile-time and all methods should be fast; for floating-point ranges and +/// the full range of integer types this should have comparable performance to +/// the `Standard` distribution. +/// +/// Steps are taken to avoid bias which might be present in naive +/// implementations; for example `rng.gen::() % 170` samples from the range +/// `[0, 169]` but is twice as likely to select numbers less than 85 than other +/// values. Further, the implementations here give more weight to the high-bits +/// generated by the RNG than the low bits, since with some RNGs the low-bits +/// are of lower quality than the high bits. +/// +/// Implementations must sample in `[low, high)` range for +/// `Uniform::new(low, high)`, i.e., excluding `high`. In particular, care must +/// be taken to ensure that rounding never results values `< low` or `>= high`. +/// +/// # Example +/// +/// ``` +/// use rand::distributions::{Distribution, Uniform}; +/// +/// let between = Uniform::from(10..10000); +/// let mut rng = rand::thread_rng(); +/// let mut sum = 0; +/// for _ in 0..1000 { +/// sum += between.sample(&mut rng); +/// } +/// println!("{}", sum); +/// ``` +/// +/// For a single sample, [`Rng::gen_range`] may be prefered: +/// +/// ``` +/// use rand::Rng; +/// +/// let mut rng = rand::thread_rng(); +/// println!("{}", rng.gen_range(0..10)); +/// ``` +/// +/// [`new`]: Uniform::new +/// [`new_inclusive`]: Uniform::new_inclusive +/// [`Rng::gen_range`]: Rng::gen_range +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct Uniform(X::Sampler); + +impl Uniform { + /// Create a new `Uniform` instance which samples uniformly from the half + /// open range `[low, high)` (excluding `high`). Panics if `low >= high`. + pub fn new(low: B1, high: B2) -> Uniform + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + Uniform(X::Sampler::new(low, high)) + } + + /// Create a new `Uniform` instance which samples uniformly from the closed + /// range `[low, high]` (inclusive). Panics if `low > high`. + pub fn new_inclusive(low: B1, high: B2) -> Uniform + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + Uniform(X::Sampler::new_inclusive(low, high)) + } +} + +impl Distribution for Uniform { + fn sample(&self, rng: &mut R) -> X { + self.0.sample(rng) + } +} + +/// Helper trait for creating objects using the correct implementation of +/// [`UniformSampler`] for the sampling type. +/// +/// See the [module documentation] on how to implement [`Uniform`] range +/// sampling for a custom type. +/// +/// [module documentation]: crate::distributions::uniform +pub trait SampleUniform: Sized { + /// The `UniformSampler` implementation supporting type `X`. + type Sampler: UniformSampler; +} + +/// Helper trait handling actual uniform sampling. +/// +/// See the [module documentation] on how to implement [`Uniform`] range +/// sampling for a custom type. +/// +/// Implementation of [`sample_single`] is optional, and is only useful when +/// the implementation can be faster than `Self::new(low, high).sample(rng)`. +/// +/// [module documentation]: crate::distributions::uniform +/// [`sample_single`]: UniformSampler::sample_single +pub trait UniformSampler: Sized { + /// The type sampled by this implementation. + type X; + + /// Construct self, with inclusive lower bound and exclusive upper bound + /// `[low, high)`. + /// + /// Usually users should not call this directly but instead use + /// `Uniform::new`, which asserts that `low < high` before calling this. + fn new(low: B1, high: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized; + + /// Construct self, with inclusive bounds `[low, high]`. + /// + /// Usually users should not call this directly but instead use + /// `Uniform::new_inclusive`, which asserts that `low <= high` before + /// calling this. + fn new_inclusive(low: B1, high: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized; + + /// Sample a value. + fn sample(&self, rng: &mut R) -> Self::X; + + /// Sample a single value uniformly from a range with inclusive lower bound + /// and exclusive upper bound `[low, high)`. + /// + /// By default this is implemented using + /// `UniformSampler::new(low, high).sample(rng)`. However, for some types + /// more optimal implementations for single usage may be provided via this + /// method (which is the case for integers and floats). + /// Results may not be identical. + /// + /// Note that to use this method in a generic context, the type needs to be + /// retrieved via `SampleUniform::Sampler` as follows: + /// ``` + /// use rand::{thread_rng, distributions::uniform::{SampleUniform, UniformSampler}}; + /// # #[allow(unused)] + /// fn sample_from_range(lb: T, ub: T) -> T { + /// let mut rng = thread_rng(); + /// ::Sampler::sample_single(lb, ub, &mut rng) + /// } + /// ``` + fn sample_single(low: B1, high: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let uniform: Self = UniformSampler::new(low, high); + uniform.sample(rng) + } + + /// Sample a single value uniformly from a range with inclusive lower bound + /// and inclusive upper bound `[low, high]`. + /// + /// By default this is implemented using + /// `UniformSampler::new_inclusive(low, high).sample(rng)`. However, for + /// some types more optimal implementations for single usage may be provided + /// via this method. + /// Results may not be identical. + fn sample_single_inclusive(low: B1, high: B2, rng: &mut R) + -> Self::X + where B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized + { + let uniform: Self = UniformSampler::new_inclusive(low, high); + uniform.sample(rng) + } +} + +impl From> for Uniform { + fn from(r: ::core::ops::Range) -> Uniform { + Uniform::new(r.start, r.end) + } +} + +impl From> for Uniform { + fn from(r: ::core::ops::RangeInclusive) -> Uniform { + Uniform::new_inclusive(r.start(), r.end()) + } +} + + +/// Helper trait similar to [`Borrow`] but implemented +/// only for SampleUniform and references to SampleUniform in +/// order to resolve ambiguity issues. +/// +/// [`Borrow`]: std::borrow::Borrow +pub trait SampleBorrow { + /// Immutably borrows from an owned value. See [`Borrow::borrow`] + /// + /// [`Borrow::borrow`]: std::borrow::Borrow::borrow + fn borrow(&self) -> &Borrowed; +} +impl SampleBorrow for Borrowed +where Borrowed: SampleUniform +{ + #[inline(always)] + fn borrow(&self) -> &Borrowed { + self + } +} +impl<'a, Borrowed> SampleBorrow for &'a Borrowed +where Borrowed: SampleUniform +{ + #[inline(always)] + fn borrow(&self) -> &Borrowed { + *self + } +} + +/// Range that supports generating a single sample efficiently. +/// +/// Any type implementing this trait can be used to specify the sampled range +/// for `Rng::gen_range`. +pub trait SampleRange { + /// Generate a sample from the given range. + fn sample_single(self, rng: &mut R) -> T; + + /// Check whether the range is empty. + fn is_empty(&self) -> bool; +} + +impl SampleRange for Range { + #[inline] + fn sample_single(self, rng: &mut R) -> T { + T::Sampler::sample_single(self.start, self.end, rng) + } + + #[inline] + fn is_empty(&self) -> bool { + !(self.start < self.end) + } +} + +impl SampleRange for RangeInclusive { + #[inline] + fn sample_single(self, rng: &mut R) -> T { + T::Sampler::sample_single_inclusive(self.start(), self.end(), rng) + } + + #[inline] + fn is_empty(&self) -> bool { + !(self.start() <= self.end()) + } +} + + +//////////////////////////////////////////////////////////////////////////////// + +// What follows are all back-ends. + + +/// The back-end implementing [`UniformSampler`] for integer types. +/// +/// Unless you are implementing [`UniformSampler`] for your own type, this type +/// should not be used directly, use [`Uniform`] instead. +/// +/// # Implementation notes +/// +/// For simplicity, we use the same generic struct `UniformInt` for all +/// integer types `X`. This gives us only one field type, `X`; to store unsigned +/// values of this size, we take use the fact that these conversions are no-ops. +/// +/// For a closed range, the number of possible numbers we should generate is +/// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of +/// our sample space, `zone`, is a multiple of `range`; other values must be +/// rejected (by replacing with a new random sample). +/// +/// As a special case, we use `range = 0` to represent the full range of the +/// result type (i.e. for `new_inclusive($ty::MIN, $ty::MAX)`). +/// +/// The optimum `zone` is the largest product of `range` which fits in our +/// (unsigned) target type. We calculate this by calculating how many numbers we +/// must reject: `reject = (MAX + 1) % range = (MAX - range + 1) % range`. Any (large) +/// product of `range` will suffice, thus in `sample_single` we multiply by a +/// power of 2 via bit-shifting (faster but may cause more rejections). +/// +/// The smallest integer PRNGs generate is `u32`. For 8- and 16-bit outputs we +/// use `u32` for our `zone` and samples (because it's not slower and because +/// it reduces the chance of having to reject a sample). In this case we cannot +/// store `zone` in the target type since it is too large, however we know +/// `ints_to_reject < range <= $unsigned::MAX`. +/// +/// An alternative to using a modulus is widening multiply: After a widening +/// multiply by `range`, the result is in the high word. Then comparing the low +/// word against `zone` makes sure our distribution is uniform. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct UniformInt { + low: X, + range: X, + z: X, // either ints_to_reject or zone depending on implementation +} + +macro_rules! uniform_int_impl { + ($ty:ty, $unsigned:ident, $u_large:ident) => { + impl SampleUniform for $ty { + type Sampler = UniformInt<$ty>; + } + + impl UniformSampler for UniformInt<$ty> { + // We play free and fast with unsigned vs signed here + // (when $ty is signed), but that's fine, since the + // contract of this macro is for $ty and $unsigned to be + // "bit-equal", so casting between them is a no-op. + + type X = $ty; + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!(low < high, "Uniform::new called with `low >= high`"); + UniformSampler::new_inclusive(low, high - 1) + } + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new_inclusive(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!( + low <= high, + "Uniform::new_inclusive called with `low > high`" + ); + let unsigned_max = ::core::$u_large::MAX; + + let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned; + let ints_to_reject = if range > 0 { + let range = $u_large::from(range); + (unsigned_max - range + 1) % range + } else { + 0 + }; + + UniformInt { + low, + // These are really $unsigned values, but store as $ty: + range: range as $ty, + z: ints_to_reject as $unsigned as $ty, + } + } + + #[inline] + fn sample(&self, rng: &mut R) -> Self::X { + let range = self.range as $unsigned as $u_large; + if range > 0 { + let unsigned_max = ::core::$u_large::MAX; + let zone = unsigned_max - (self.z as $unsigned as $u_large); + loop { + let v: $u_large = rng.gen(); + let (hi, lo) = v.wmul(range); + if lo <= zone { + return self.low.wrapping_add(hi as $ty); + } + } + } else { + // Sample from the entire integer range. + rng.gen() + } + } + + #[inline] + fn sample_single(low_b: B1, high_b: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!(low < high, "UniformSampler::sample_single: low >= high"); + Self::sample_single_inclusive(low, high - 1, rng) + } + + #[inline] + fn sample_single_inclusive(low_b: B1, high_b: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!(low <= high, "UniformSampler::sample_single_inclusive: low > high"); + let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned as $u_large; + // If the above resulted in wrap-around to 0, the range is $ty::MIN..=$ty::MAX, + // and any integer will do. + if range == 0 { + return rng.gen(); + } + + let zone = if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned { + // Using a modulus is faster than the approximation for + // i8 and i16. I suppose we trade the cost of one + // modulus for near-perfect branch prediction. + let unsigned_max: $u_large = ::core::$u_large::MAX; + let ints_to_reject = (unsigned_max - range + 1) % range; + unsigned_max - ints_to_reject + } else { + // conservative but fast approximation. `- 1` is necessary to allow the + // same comparison without bias. + (range << range.leading_zeros()).wrapping_sub(1) + }; + + loop { + let v: $u_large = rng.gen(); + let (hi, lo) = v.wmul(range); + if lo <= zone { + return low.wrapping_add(hi as $ty); + } + } + } + } + }; +} + +uniform_int_impl! { i8, u8, u32 } +uniform_int_impl! { i16, u16, u32 } +uniform_int_impl! { i32, u32, u32 } +uniform_int_impl! { i64, u64, u64 } +#[cfg(not(target_os = "emscripten"))] +uniform_int_impl! { i128, u128, u128 } +uniform_int_impl! { isize, usize, usize } +uniform_int_impl! { u8, u8, u32 } +uniform_int_impl! { u16, u16, u32 } +uniform_int_impl! { u32, u32, u32 } +uniform_int_impl! { u64, u64, u64 } +uniform_int_impl! { usize, usize, usize } +#[cfg(not(target_os = "emscripten"))] +uniform_int_impl! { u128, u128, u128 } + +#[cfg(feature = "simd_support")] +macro_rules! uniform_simd_int_impl { + ($ty:ident, $unsigned:ident, $u_scalar:ident) => { + // The "pick the largest zone that can fit in an `u32`" optimization + // is less useful here. Multiple lanes complicate things, we don't + // know the PRNG's minimal output size, and casting to a larger vector + // is generally a bad idea for SIMD performance. The user can still + // implement it manually. + + // TODO: look into `Uniform::::new(0u32, 100)` functionality + // perhaps `impl SampleUniform for $u_scalar`? + impl SampleUniform for $ty { + type Sampler = UniformInt<$ty>; + } + + impl UniformSampler for UniformInt<$ty> { + type X = $ty; + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new(low_b: B1, high_b: B2) -> Self + where B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!(low.lt(high).all(), "Uniform::new called with `low >= high`"); + UniformSampler::new_inclusive(low, high - 1) + } + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new_inclusive(low_b: B1, high_b: B2) -> Self + where B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!(low.le(high).all(), + "Uniform::new_inclusive called with `low > high`"); + let unsigned_max = ::core::$u_scalar::MAX; + + // NOTE: these may need to be replaced with explicitly + // wrapping operations if `packed_simd` changes + let range: $unsigned = ((high - low) + 1).cast(); + // `% 0` will panic at runtime. + let not_full_range = range.gt($unsigned::splat(0)); + // replacing 0 with `unsigned_max` allows a faster `select` + // with bitwise OR + let modulo = not_full_range.select(range, $unsigned::splat(unsigned_max)); + // wrapping addition + let ints_to_reject = (unsigned_max - range + 1) % modulo; + // When `range` is 0, `lo` of `v.wmul(range)` will always be + // zero which means only one sample is needed. + let zone = unsigned_max - ints_to_reject; + + UniformInt { + low, + // These are really $unsigned values, but store as $ty: + range: range.cast(), + z: zone.cast(), + } + } + + fn sample(&self, rng: &mut R) -> Self::X { + let range: $unsigned = self.range.cast(); + let zone: $unsigned = self.z.cast(); + + // This might seem very slow, generating a whole new + // SIMD vector for every sample rejection. For most uses + // though, the chance of rejection is small and provides good + // general performance. With multiple lanes, that chance is + // multiplied. To mitigate this, we replace only the lanes of + // the vector which fail, iteratively reducing the chance of + // rejection. The replacement method does however add a little + // overhead. Benchmarking or calculating probabilities might + // reveal contexts where this replacement method is slower. + let mut v: $unsigned = rng.gen(); + loop { + let (hi, lo) = v.wmul(range); + let mask = lo.le(zone); + if mask.all() { + let hi: $ty = hi.cast(); + // wrapping addition + let result = self.low + hi; + // `select` here compiles to a blend operation + // When `range.eq(0).none()` the compare and blend + // operations are avoided. + let v: $ty = v.cast(); + return range.gt($unsigned::splat(0)).select(result, v); + } + // Replace only the failing lanes + v = mask.select(v, rng.gen()); + } + } + } + }; + + // bulk implementation + ($(($unsigned:ident, $signed:ident),)+ $u_scalar:ident) => { + $( + uniform_simd_int_impl!($unsigned, $unsigned, $u_scalar); + uniform_simd_int_impl!($signed, $unsigned, $u_scalar); + )+ + }; +} + +#[cfg(feature = "simd_support")] +uniform_simd_int_impl! { + (u64x2, i64x2), + (u64x4, i64x4), + (u64x8, i64x8), + u64 +} + +#[cfg(feature = "simd_support")] +uniform_simd_int_impl! { + (u32x2, i32x2), + (u32x4, i32x4), + (u32x8, i32x8), + (u32x16, i32x16), + u32 +} + +#[cfg(feature = "simd_support")] +uniform_simd_int_impl! { + (u16x2, i16x2), + (u16x4, i16x4), + (u16x8, i16x8), + (u16x16, i16x16), + (u16x32, i16x32), + u16 +} + +#[cfg(feature = "simd_support")] +uniform_simd_int_impl! { + (u8x2, i8x2), + (u8x4, i8x4), + (u8x8, i8x8), + (u8x16, i8x16), + (u8x32, i8x32), + (u8x64, i8x64), + u8 +} + +impl SampleUniform for char { + type Sampler = UniformChar; +} + +/// The back-end implementing [`UniformSampler`] for `char`. +/// +/// Unless you are implementing [`UniformSampler`] for your own type, this type +/// should not be used directly, use [`Uniform`] instead. +/// +/// This differs from integer range sampling since the range `0xD800..=0xDFFF` +/// are used for surrogate pairs in UCS and UTF-16, and consequently are not +/// valid Unicode code points. We must therefore avoid sampling values in this +/// range. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct UniformChar { + sampler: UniformInt, +} + +/// UTF-16 surrogate range start +const CHAR_SURROGATE_START: u32 = 0xD800; +/// UTF-16 surrogate range size +const CHAR_SURROGATE_LEN: u32 = 0xE000 - CHAR_SURROGATE_START; + +/// Convert `char` to compressed `u32` +fn char_to_comp_u32(c: char) -> u32 { + match c as u32 { + c if c >= CHAR_SURROGATE_START => c - CHAR_SURROGATE_LEN, + c => c, + } +} + +impl UniformSampler for UniformChar { + type X = char; + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = char_to_comp_u32(*low_b.borrow()); + let high = char_to_comp_u32(*high_b.borrow()); + let sampler = UniformInt::::new(low, high); + UniformChar { sampler } + } + + #[inline] // if the range is constant, this helps LLVM to do the + // calculations at compile-time. + fn new_inclusive(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = char_to_comp_u32(*low_b.borrow()); + let high = char_to_comp_u32(*high_b.borrow()); + let sampler = UniformInt::::new_inclusive(low, high); + UniformChar { sampler } + } + + fn sample(&self, rng: &mut R) -> Self::X { + let mut x = self.sampler.sample(rng); + if x >= CHAR_SURROGATE_START { + x += CHAR_SURROGATE_LEN; + } + // SAFETY: x must not be in surrogate range or greater than char::MAX. + // This relies on range constructors which accept char arguments. + // Validity of input char values is assumed. + unsafe { core::char::from_u32_unchecked(x) } + } +} + +/// The back-end implementing [`UniformSampler`] for floating-point types. +/// +/// Unless you are implementing [`UniformSampler`] for your own type, this type +/// should not be used directly, use [`Uniform`] instead. +/// +/// # Implementation notes +/// +/// Instead of generating a float in the `[0, 1)` range using [`Standard`], the +/// `UniformFloat` implementation converts the output of an PRNG itself. This +/// way one or two steps can be optimized out. +/// +/// The floats are first converted to a value in the `[1, 2)` interval using a +/// transmute-based method, and then mapped to the expected range with a +/// multiply and addition. Values produced this way have what equals 23 bits of +/// random digits for an `f32`, and 52 for an `f64`. +/// +/// [`new`]: UniformSampler::new +/// [`new_inclusive`]: UniformSampler::new_inclusive +/// [`Standard`]: crate::distributions::Standard +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct UniformFloat { + low: X, + scale: X, +} + +macro_rules! uniform_float_impl { + ($ty:ty, $uty:ident, $f_scalar:ident, $u_scalar:ident, $bits_to_discard:expr) => { + impl SampleUniform for $ty { + type Sampler = UniformFloat<$ty>; + } + + impl UniformSampler for UniformFloat<$ty> { + type X = $ty; + + fn new(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!(low.all_lt(high), "Uniform::new called with `low >= high`"); + assert!( + low.all_finite() && high.all_finite(), + "Uniform::new called with non-finite boundaries" + ); + let max_rand = <$ty>::splat( + (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, + ); + + let mut scale = high - low; + + loop { + let mask = (scale * max_rand + low).ge_mask(high); + if mask.none() { + break; + } + scale = scale.decrease_masked(mask); + } + + debug_assert!(<$ty>::splat(0.0).all_le(scale)); + + UniformFloat { low, scale } + } + + fn new_inclusive(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!( + low.all_le(high), + "Uniform::new_inclusive called with `low > high`" + ); + assert!( + low.all_finite() && high.all_finite(), + "Uniform::new_inclusive called with non-finite boundaries" + ); + let max_rand = <$ty>::splat( + (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, + ); + + let mut scale = (high - low) / max_rand; + + loop { + let mask = (scale * max_rand + low).gt_mask(high); + if mask.none() { + break; + } + scale = scale.decrease_masked(mask); + } + + debug_assert!(<$ty>::splat(0.0).all_le(scale)); + + UniformFloat { low, scale } + } + + fn sample(&self, rng: &mut R) -> Self::X { + // Generate a value in the range [1, 2) + let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); + + // Get a value in the range [0, 1) in order to avoid + // overflowing into infinity when multiplying with scale + let value0_1 = value1_2 - 1.0; + + // We don't use `f64::mul_add`, because it is not available with + // `no_std`. Furthermore, it is slower for some targets (but + // faster for others). However, the order of multiplication and + // addition is important, because on some platforms (e.g. ARM) + // it will be optimized to a single (non-FMA) instruction. + value0_1 * self.scale + self.low + } + + #[inline] + fn sample_single(low_b: B1, high_b: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!( + low.all_lt(high), + "UniformSampler::sample_single: low >= high" + ); + let mut scale = high - low; + + loop { + // Generate a value in the range [1, 2) + let value1_2 = + (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); + + // Get a value in the range [0, 1) in order to avoid + // overflowing into infinity when multiplying with scale + let value0_1 = value1_2 - 1.0; + + // Doing multiply before addition allows some architectures + // to use a single instruction. + let res = value0_1 * scale + low; + + debug_assert!(low.all_le(res) || !scale.all_finite()); + if res.all_lt(high) { + return res; + } + + // This handles a number of edge cases. + // * `low` or `high` is NaN. In this case `scale` and + // `res` are going to end up as NaN. + // * `low` is negative infinity and `high` is finite. + // `scale` is going to be infinite and `res` will be + // NaN. + // * `high` is positive infinity and `low` is finite. + // `scale` is going to be infinite and `res` will + // be infinite or NaN (if value0_1 is 0). + // * `low` is negative infinity and `high` is positive + // infinity. `scale` will be infinite and `res` will + // be NaN. + // * `low` and `high` are finite, but `high - low` + // overflows to infinite. `scale` will be infinite + // and `res` will be infinite or NaN (if value0_1 is 0). + // So if `high` or `low` are non-finite, we are guaranteed + // to fail the `res < high` check above and end up here. + // + // While we technically should check for non-finite `low` + // and `high` before entering the loop, by doing the checks + // here instead, we allow the common case to avoid these + // checks. But we are still guaranteed that if `low` or + // `high` are non-finite we'll end up here and can do the + // appropriate checks. + // + // Likewise `high - low` overflowing to infinity is also + // rare, so handle it here after the common case. + let mask = !scale.finite_mask(); + if mask.any() { + assert!( + low.all_finite() && high.all_finite(), + "Uniform::sample_single: low and high must be finite" + ); + scale = scale.decrease_masked(mask); + } + } + } + } + }; +} + +uniform_float_impl! { f32, u32, f32, u32, 32 - 23 } +uniform_float_impl! { f64, u64, f64, u64, 64 - 52 } + +#[cfg(feature = "simd_support")] +uniform_float_impl! { f32x2, u32x2, f32, u32, 32 - 23 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { f32x4, u32x4, f32, u32, 32 - 23 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { f32x8, u32x8, f32, u32, 32 - 23 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { f32x16, u32x16, f32, u32, 32 - 23 } + +#[cfg(feature = "simd_support")] +uniform_float_impl! { f64x2, u64x2, f64, u64, 64 - 52 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 } +#[cfg(feature = "simd_support")] +uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 } + + +/// The back-end implementing [`UniformSampler`] for `Duration`. +/// +/// Unless you are implementing [`UniformSampler`] for your own types, this type +/// should not be used directly, use [`Uniform`] instead. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct UniformDuration { + mode: UniformDurationMode, + offset: u32, +} + +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +enum UniformDurationMode { + Small { + secs: u64, + nanos: Uniform, + }, + Medium { + nanos: Uniform, + }, + Large { + max_secs: u64, + max_nanos: u32, + secs: Uniform, + }, +} + +impl SampleUniform for Duration { + type Sampler = UniformDuration; +} + +impl UniformSampler for UniformDuration { + type X = Duration; + + #[inline] + fn new(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!(low < high, "Uniform::new called with `low >= high`"); + UniformDuration::new_inclusive(low, high - Duration::new(0, 1)) + } + + #[inline] + fn new_inclusive(low_b: B1, high_b: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + let low = *low_b.borrow(); + let high = *high_b.borrow(); + assert!( + low <= high, + "Uniform::new_inclusive called with `low > high`" + ); + + let low_s = low.as_secs(); + let low_n = low.subsec_nanos(); + let mut high_s = high.as_secs(); + let mut high_n = high.subsec_nanos(); + + if high_n < low_n { + high_s -= 1; + high_n += 1_000_000_000; + } + + let mode = if low_s == high_s { + UniformDurationMode::Small { + secs: low_s, + nanos: Uniform::new_inclusive(low_n, high_n), + } + } else { + let max = high_s + .checked_mul(1_000_000_000) + .and_then(|n| n.checked_add(u64::from(high_n))); + + if let Some(higher_bound) = max { + let lower_bound = low_s * 1_000_000_000 + u64::from(low_n); + UniformDurationMode::Medium { + nanos: Uniform::new_inclusive(lower_bound, higher_bound), + } + } else { + // An offset is applied to simplify generation of nanoseconds + let max_nanos = high_n - low_n; + UniformDurationMode::Large { + max_secs: high_s, + max_nanos, + secs: Uniform::new_inclusive(low_s, high_s), + } + } + }; + UniformDuration { + mode, + offset: low_n, + } + } + + #[inline] + fn sample(&self, rng: &mut R) -> Duration { + match self.mode { + UniformDurationMode::Small { secs, nanos } => { + let n = nanos.sample(rng); + Duration::new(secs, n) + } + UniformDurationMode::Medium { nanos } => { + let nanos = nanos.sample(rng); + Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32) + } + UniformDurationMode::Large { + max_secs, + max_nanos, + secs, + } => { + // constant folding means this is at least as fast as `Rng::sample(Range)` + let nano_range = Uniform::new(0, 1_000_000_000); + loop { + let s = secs.sample(rng); + let n = nano_range.sample(rng); + if !(s == max_secs && n > max_nanos) { + let sum = n + self.offset; + break Duration::new(s, sum); + } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::rngs::mock::StepRng; + + #[test] + #[cfg(feature = "serde1")] + fn test_serialization_uniform_duration() { + let distr = UniformDuration::new(std::time::Duration::from_secs(10), std::time::Duration::from_secs(60)); + let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); + assert_eq!( + distr.offset, de_distr.offset + ); + match (distr.mode, de_distr.mode) { + (UniformDurationMode::Small {secs: a_secs, nanos: a_nanos}, UniformDurationMode::Small {secs, nanos}) => { + assert_eq!(a_secs, secs); + + assert_eq!(a_nanos.0.low, nanos.0.low); + assert_eq!(a_nanos.0.range, nanos.0.range); + assert_eq!(a_nanos.0.z, nanos.0.z); + } + (UniformDurationMode::Medium {nanos: a_nanos} , UniformDurationMode::Medium {nanos}) => { + assert_eq!(a_nanos.0.low, nanos.0.low); + assert_eq!(a_nanos.0.range, nanos.0.range); + assert_eq!(a_nanos.0.z, nanos.0.z); + } + (UniformDurationMode::Large {max_secs:a_max_secs, max_nanos:a_max_nanos, secs:a_secs}, UniformDurationMode::Large {max_secs, max_nanos, secs} ) => { + assert_eq!(a_max_secs, max_secs); + assert_eq!(a_max_nanos, max_nanos); + + assert_eq!(a_secs.0.low, secs.0.low); + assert_eq!(a_secs.0.range, secs.0.range); + assert_eq!(a_secs.0.z, secs.0.z); + } + _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly") + } + } + + #[test] + #[cfg(feature = "serde1")] + fn test_uniform_serialization() { + let unit_box: Uniform = Uniform::new(-1, 1); + let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + + assert_eq!(unit_box.0.low, de_unit_box.0.low); + assert_eq!(unit_box.0.range, de_unit_box.0.range); + assert_eq!(unit_box.0.z, de_unit_box.0.z); + + let unit_box: Uniform = Uniform::new(-1., 1.); + let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + + assert_eq!(unit_box.0.low, de_unit_box.0.low); + assert_eq!(unit_box.0.scale, de_unit_box.0.scale); + } + + #[should_panic] + #[test] + fn test_uniform_bad_limits_equal_int() { + Uniform::new(10, 10); + } + + #[test] + fn test_uniform_good_limits_equal_int() { + let mut rng = crate::test::rng(804); + let dist = Uniform::new_inclusive(10, 10); + for _ in 0..20 { + assert_eq!(rng.sample(dist), 10); + } + } + + #[should_panic] + #[test] + fn test_uniform_bad_limits_flipped_int() { + Uniform::new(10, 5); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_integers() { + #[cfg(not(target_os = "emscripten"))] use core::{i128, u128}; + use core::{i16, i32, i64, i8, isize}; + use core::{u16, u32, u64, u8, usize}; + + let mut rng = crate::test::rng(251); + macro_rules! t { + ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{ + for &(low, high) in $v.iter() { + let my_uniform = Uniform::new(low, high); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $lt(v, high)); + } + + let my_uniform = Uniform::new_inclusive(low, high); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $le(v, high)); + } + + let my_uniform = Uniform::new(&low, high); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $lt(v, high)); + } + + let my_uniform = Uniform::new_inclusive(&low, &high); + for _ in 0..1000 { + let v: $ty = rng.sample(my_uniform); + assert!($le(low, v) && $le(v, high)); + } + + for _ in 0..1000 { + let v = <$ty as SampleUniform>::Sampler::sample_single(low, high, &mut rng); + assert!($le(low, v) && $lt(v, high)); + } + + for _ in 0..1000 { + let v = <$ty as SampleUniform>::Sampler::sample_single_inclusive(low, high, &mut rng); + assert!($le(low, v) && $le(v, high)); + } + } + }}; + + // scalar bulk + ($($ty:ident),*) => {{ + $(t!( + $ty, + [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)], + |x, y| x <= y, + |x, y| x < y + );)* + }}; + + // simd bulk + ($($ty:ident),* => $scalar:ident) => {{ + $(t!( + $ty, + [ + ($ty::splat(0), $ty::splat(10)), + ($ty::splat(10), $ty::splat(127)), + ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)), + ], + |x: $ty, y| x.le(y).all(), + |x: $ty, y| x.lt(y).all() + );)* + }}; + } + t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); + #[cfg(not(target_os = "emscripten"))] + t!(i128, u128); + + #[cfg(feature = "simd_support")] + { + t!(u8x2, u8x4, u8x8, u8x16, u8x32, u8x64 => u8); + t!(i8x2, i8x4, i8x8, i8x16, i8x32, i8x64 => i8); + t!(u16x2, u16x4, u16x8, u16x16, u16x32 => u16); + t!(i16x2, i16x4, i16x8, i16x16, i16x32 => i16); + t!(u32x2, u32x4, u32x8, u32x16 => u32); + t!(i32x2, i32x4, i32x8, i32x16 => i32); + t!(u64x2, u64x4, u64x8 => u64); + t!(i64x2, i64x4, i64x8 => i64); + } + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_char() { + let mut rng = crate::test::rng(891); + let mut max = core::char::from_u32(0).unwrap(); + for _ in 0..100 { + let c = rng.gen_range('A'..='Z'); + assert!('A' <= c && c <= 'Z'); + max = max.max(c); + } + assert_eq!(max, 'Z'); + let d = Uniform::new( + core::char::from_u32(0xD7F0).unwrap(), + core::char::from_u32(0xE010).unwrap(), + ); + for _ in 0..100 { + let c = d.sample(&mut rng); + assert!((c as u32) < 0xD800 || (c as u32) > 0xDFFF); + } + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_floats() { + let mut rng = crate::test::rng(252); + let mut zero_rng = StepRng::new(0, 0); + let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0); + macro_rules! t { + ($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{ + let v: &[($f_scalar, $f_scalar)] = &[ + (0.0, 100.0), + (-1e35, -1e25), + (1e-35, 1e-25), + (-1e35, 1e35), + (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)), + (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), + (-<$f_scalar>::from_bits(5), 0.0), + (-<$f_scalar>::from_bits(7), -0.0), + (10.0, ::core::$f_scalar::MAX), + (-100.0, ::core::$f_scalar::MAX), + (-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX), + (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0), + (-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7), + (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX), + ]; + for &(low_scalar, high_scalar) in v.iter() { + for lane in 0..<$ty>::lanes() { + let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); + let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); + let my_uniform = Uniform::new(low, high); + let my_incl_uniform = Uniform::new_inclusive(low, high); + for _ in 0..100 { + let v = rng.sample(my_uniform).extract(lane); + assert!(low_scalar <= v && v < high_scalar); + let v = rng.sample(my_incl_uniform).extract(lane); + assert!(low_scalar <= v && v <= high_scalar); + let v = <$ty as SampleUniform>::Sampler + ::sample_single(low, high, &mut rng).extract(lane); + assert!(low_scalar <= v && v < high_scalar); + } + + assert_eq!( + rng.sample(Uniform::new_inclusive(low, low)).extract(lane), + low_scalar + ); + + assert_eq!(zero_rng.sample(my_uniform).extract(lane), low_scalar); + assert_eq!(zero_rng.sample(my_incl_uniform).extract(lane), low_scalar); + assert_eq!(<$ty as SampleUniform>::Sampler + ::sample_single(low, high, &mut zero_rng) + .extract(lane), low_scalar); + assert!(max_rng.sample(my_uniform).extract(lane) < high_scalar); + assert!(max_rng.sample(my_incl_uniform).extract(lane) <= high_scalar); + + // Don't run this test for really tiny differences between high and low + // since for those rounding might result in selecting high for a very + // long time. + if (high_scalar - low_scalar) > 0.0001 { + let mut lowering_max_rng = StepRng::new( + 0xffff_ffff_ffff_ffff, + (-1i64 << $bits_shifted) as u64, + ); + assert!( + <$ty as SampleUniform>::Sampler + ::sample_single(low, high, &mut lowering_max_rng) + .extract(lane) < high_scalar + ); + } + } + } + + assert_eq!( + rng.sample(Uniform::new_inclusive( + ::core::$f_scalar::MAX, + ::core::$f_scalar::MAX + )), + ::core::$f_scalar::MAX + ); + assert_eq!( + rng.sample(Uniform::new_inclusive( + -::core::$f_scalar::MAX, + -::core::$f_scalar::MAX + )), + -::core::$f_scalar::MAX + ); + }}; + } + + t!(f32, f32, 32 - 23); + t!(f64, f64, 64 - 52); + #[cfg(feature = "simd_support")] + { + t!(f32x2, f32, 32 - 23); + t!(f32x4, f32, 32 - 23); + t!(f32x8, f32, 32 - 23); + t!(f32x16, f32, 32 - 23); + t!(f64x2, f64, 64 - 52); + t!(f64x4, f64, 64 - 52); + t!(f64x8, f64, 64 - 52); + } + } + + #[test] + #[cfg(all( + feature = "std", + not(target_arch = "wasm32"), + not(target_arch = "asmjs") + ))] + fn test_float_assertions() { + use super::SampleUniform; + use std::panic::catch_unwind; + fn range(low: T, high: T) { + let mut rng = crate::test::rng(253); + T::Sampler::sample_single(low, high, &mut rng); + } + + macro_rules! t { + ($ty:ident, $f_scalar:ident) => {{ + let v: &[($f_scalar, $f_scalar)] = &[ + (::std::$f_scalar::NAN, 0.0), + (1.0, ::std::$f_scalar::NAN), + (::std::$f_scalar::NAN, ::std::$f_scalar::NAN), + (1.0, 0.5), + (::std::$f_scalar::MAX, -::std::$f_scalar::MAX), + (::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY), + ( + ::std::$f_scalar::NEG_INFINITY, + ::std::$f_scalar::NEG_INFINITY, + ), + (::std::$f_scalar::NEG_INFINITY, 5.0), + (5.0, ::std::$f_scalar::INFINITY), + (::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY), + (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN), + (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY), + ]; + for &(low_scalar, high_scalar) in v.iter() { + for lane in 0..<$ty>::lanes() { + let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); + let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); + assert!(catch_unwind(|| range(low, high)).is_err()); + assert!(catch_unwind(|| Uniform::new(low, high)).is_err()); + assert!(catch_unwind(|| Uniform::new_inclusive(low, high)).is_err()); + assert!(catch_unwind(|| range(low, low)).is_err()); + assert!(catch_unwind(|| Uniform::new(low, low)).is_err()); + } + } + }}; + } + + t!(f32, f32); + t!(f64, f64); + #[cfg(feature = "simd_support")] + { + t!(f32x2, f32); + t!(f32x4, f32); + t!(f32x8, f32); + t!(f32x16, f32); + t!(f64x2, f64); + t!(f64x4, f64); + t!(f64x8, f64); + } + } + + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_durations() { + #[cfg(not(feature = "std"))] use core::time::Duration; + #[cfg(feature = "std")] use std::time::Duration; + + let mut rng = crate::test::rng(253); + + let v = &[ + (Duration::new(10, 50000), Duration::new(100, 1234)), + (Duration::new(0, 100), Duration::new(1, 50)), + ( + Duration::new(0, 0), + Duration::new(u64::max_value(), 999_999_999), + ), + ]; + for &(low, high) in v.iter() { + let my_uniform = Uniform::new(low, high); + for _ in 0..1000 { + let v = rng.sample(my_uniform); + assert!(low <= v && v < high); + } + } + } + + #[test] + fn test_custom_uniform() { + use crate::distributions::uniform::{ + SampleBorrow, SampleUniform, UniformFloat, UniformSampler, + }; + #[derive(Clone, Copy, PartialEq, PartialOrd)] + struct MyF32 { + x: f32, + } + #[derive(Clone, Copy, Debug)] + struct UniformMyF32(UniformFloat); + impl UniformSampler for UniformMyF32 { + type X = MyF32; + + fn new(low: B1, high: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + UniformMyF32(UniformFloat::::new(low.borrow().x, high.borrow().x)) + } + + fn new_inclusive(low: B1, high: B2) -> Self + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { + UniformSampler::new(low, high) + } + + fn sample(&self, rng: &mut R) -> Self::X { + MyF32 { + x: self.0.sample(rng), + } + } + } + impl SampleUniform for MyF32 { + type Sampler = UniformMyF32; + } + + let (low, high) = (MyF32 { x: 17.0f32 }, MyF32 { x: 22.0f32 }); + let uniform = Uniform::new(low, high); + let mut rng = crate::test::rng(804); + for _ in 0..100 { + let x: MyF32 = rng.sample(uniform); + assert!(low <= x && x < high); + } + } + + #[test] + fn test_uniform_from_std_range() { + let r = Uniform::from(2u32..7); + assert_eq!(r.0.low, 2); + assert_eq!(r.0.range, 5); + let r = Uniform::from(2.0f64..7.0); + assert_eq!(r.0.low, 2.0); + assert_eq!(r.0.scale, 5.0); + } + + #[test] + fn test_uniform_from_std_range_inclusive() { + let r = Uniform::from(2u32..=6); + assert_eq!(r.0.low, 2); + assert_eq!(r.0.range, 5); + let r = Uniform::from(2.0f64..=7.0); + assert_eq!(r.0.low, 2.0); + assert!(r.0.scale > 5.0); + assert!(r.0.scale < 5.0 + 1e-14); + } + + #[test] + fn value_stability() { + fn test_samples( + lb: T, ub: T, expected_single: &[T], expected_multiple: &[T], + ) where Uniform: Distribution { + let mut rng = crate::test::rng(897); + let mut buf = [lb; 3]; + + for x in &mut buf { + *x = T::Sampler::sample_single(lb, ub, &mut rng); + } + assert_eq!(&buf, expected_single); + + let distr = Uniform::new(lb, ub); + for x in &mut buf { + *x = rng.sample(&distr); + } + assert_eq!(&buf, expected_multiple); + } + + // We test on a sub-set of types; possibly we should do more. + // TODO: SIMD types + + test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]); + test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]); + + test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[ + 0.008194133, + 0.00398172, + 0.007428536, + ]); + test_samples( + -1e10f64, + 1e10f64, + &[-4673848682.871551, 6388267422.932352, 4857075081.198343], + &[1173375212.1808167, 1917642852.109581, 2365076174.3153973], + ); + + test_samples( + Duration::new(2, 0), + Duration::new(4, 0), + &[ + Duration::new(2, 532615131), + Duration::new(3, 638826742), + Duration::new(3, 485707508), + ], + &[ + Duration::new(3, 117337521), + Duration::new(3, 191764285), + Duration::new(3, 236507617), + ], + ); + } +} diff --git a/vendor/rand/src/distributions/utils.rs b/vendor/rand/src/distributions/utils.rs new file mode 100644 index 0000000000..e3bceb8a96 --- /dev/null +++ b/vendor/rand/src/distributions/utils.rs @@ -0,0 +1,429 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Math helper functions + +#[cfg(feature = "simd_support")] use packed_simd::*; + + +pub(crate) trait WideningMultiply { + type Output; + + fn wmul(self, x: RHS) -> Self::Output; +} + +macro_rules! wmul_impl { + ($ty:ty, $wide:ty, $shift:expr) => { + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, x: $ty) -> Self::Output { + let tmp = (self as $wide) * (x as $wide); + ((tmp >> $shift) as $ty, tmp as $ty) + } + } + }; + + // simd bulk implementation + ($(($ty:ident, $wide:ident),)+, $shift:expr) => { + $( + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, x: $ty) -> Self::Output { + // For supported vectors, this should compile to a couple + // supported multiply & swizzle instructions (no actual + // casting). + // TODO: optimize + let y: $wide = self.cast(); + let x: $wide = x.cast(); + let tmp = y * x; + let hi: $ty = (tmp >> $shift).cast(); + let lo: $ty = tmp.cast(); + (hi, lo) + } + } + )+ + }; +} +wmul_impl! { u8, u16, 8 } +wmul_impl! { u16, u32, 16 } +wmul_impl! { u32, u64, 32 } +#[cfg(not(target_os = "emscripten"))] +wmul_impl! { u64, u128, 64 } + +// This code is a translation of the __mulddi3 function in LLVM's +// compiler-rt. It is an optimised variant of the common method +// `(a + b) * (c + d) = ac + ad + bc + bd`. +// +// For some reason LLVM can optimise the C version very well, but +// keeps shuffling registers in this Rust translation. +macro_rules! wmul_impl_large { + ($ty:ty, $half:expr) => { + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, b: $ty) -> Self::Output { + const LOWER_MASK: $ty = !0 >> $half; + let mut low = (self & LOWER_MASK).wrapping_mul(b & LOWER_MASK); + let mut t = low >> $half; + low &= LOWER_MASK; + t += (self >> $half).wrapping_mul(b & LOWER_MASK); + low += (t & LOWER_MASK) << $half; + let mut high = t >> $half; + t = low >> $half; + low &= LOWER_MASK; + t += (b >> $half).wrapping_mul(self & LOWER_MASK); + low += (t & LOWER_MASK) << $half; + high += t >> $half; + high += (self >> $half).wrapping_mul(b >> $half); + + (high, low) + } + } + }; + + // simd bulk implementation + (($($ty:ty,)+) $scalar:ty, $half:expr) => { + $( + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, b: $ty) -> Self::Output { + // needs wrapping multiplication + const LOWER_MASK: $scalar = !0 >> $half; + let mut low = (self & LOWER_MASK) * (b & LOWER_MASK); + let mut t = low >> $half; + low &= LOWER_MASK; + t += (self >> $half) * (b & LOWER_MASK); + low += (t & LOWER_MASK) << $half; + let mut high = t >> $half; + t = low >> $half; + low &= LOWER_MASK; + t += (b >> $half) * (self & LOWER_MASK); + low += (t & LOWER_MASK) << $half; + high += t >> $half; + high += (self >> $half) * (b >> $half); + + (high, low) + } + } + )+ + }; +} +#[cfg(target_os = "emscripten")] +wmul_impl_large! { u64, 32 } +#[cfg(not(target_os = "emscripten"))] +wmul_impl_large! { u128, 64 } + +macro_rules! wmul_impl_usize { + ($ty:ty) => { + impl WideningMultiply for usize { + type Output = (usize, usize); + + #[inline(always)] + fn wmul(self, x: usize) -> Self::Output { + let (high, low) = (self as $ty).wmul(x as $ty); + (high as usize, low as usize) + } + } + }; +} +#[cfg(target_pointer_width = "32")] +wmul_impl_usize! { u32 } +#[cfg(target_pointer_width = "64")] +wmul_impl_usize! { u64 } + +#[cfg(feature = "simd_support")] +mod simd_wmul { + use super::*; + #[cfg(target_arch = "x86")] use core::arch::x86::*; + #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; + + wmul_impl! { + (u8x2, u16x2), + (u8x4, u16x4), + (u8x8, u16x8), + (u8x16, u16x16), + (u8x32, u16x32),, + 8 + } + + wmul_impl! { (u16x2, u32x2),, 16 } + wmul_impl! { (u16x4, u32x4),, 16 } + #[cfg(not(target_feature = "sse2"))] + wmul_impl! { (u16x8, u32x8),, 16 } + #[cfg(not(target_feature = "avx2"))] + wmul_impl! { (u16x16, u32x16),, 16 } + + // 16-bit lane widths allow use of the x86 `mulhi` instructions, which + // means `wmul` can be implemented with only two instructions. + #[allow(unused_macros)] + macro_rules! wmul_impl_16 { + ($ty:ident, $intrinsic:ident, $mulhi:ident, $mullo:ident) => { + impl WideningMultiply for $ty { + type Output = ($ty, $ty); + + #[inline(always)] + fn wmul(self, x: $ty) -> Self::Output { + let b = $intrinsic::from_bits(x); + let a = $intrinsic::from_bits(self); + let hi = $ty::from_bits(unsafe { $mulhi(a, b) }); + let lo = $ty::from_bits(unsafe { $mullo(a, b) }); + (hi, lo) + } + } + }; + } + + #[cfg(target_feature = "sse2")] + wmul_impl_16! { u16x8, __m128i, _mm_mulhi_epu16, _mm_mullo_epi16 } + #[cfg(target_feature = "avx2")] + wmul_impl_16! { u16x16, __m256i, _mm256_mulhi_epu16, _mm256_mullo_epi16 } + // FIXME: there are no `__m512i` types in stdsimd yet, so `wmul::` + // cannot use the same implementation. + + wmul_impl! { + (u32x2, u64x2), + (u32x4, u64x4), + (u32x8, u64x8),, + 32 + } + + // TODO: optimize, this seems to seriously slow things down + wmul_impl_large! { (u8x64,) u8, 4 } + wmul_impl_large! { (u16x32,) u16, 8 } + wmul_impl_large! { (u32x16,) u32, 16 } + wmul_impl_large! { (u64x2, u64x4, u64x8,) u64, 32 } +} + +/// Helper trait when dealing with scalar and SIMD floating point types. +pub(crate) trait FloatSIMDUtils { + // `PartialOrd` for vectors compares lexicographically. We want to compare all + // the individual SIMD lanes instead, and get the combined result over all + // lanes. This is possible using something like `a.lt(b).all()`, but we + // implement it as a trait so we can write the same code for `f32` and `f64`. + // Only the comparison functions we need are implemented. + fn all_lt(self, other: Self) -> bool; + fn all_le(self, other: Self) -> bool; + fn all_finite(self) -> bool; + + type Mask; + fn finite_mask(self) -> Self::Mask; + fn gt_mask(self, other: Self) -> Self::Mask; + fn ge_mask(self, other: Self) -> Self::Mask; + + // Decrease all lanes where the mask is `true` to the next lower value + // representable by the floating-point type. At least one of the lanes + // must be set. + fn decrease_masked(self, mask: Self::Mask) -> Self; + + // Convert from int value. Conversion is done while retaining the numerical + // value, not by retaining the binary representation. + type UInt; + fn cast_from_int(i: Self::UInt) -> Self; +} + +/// Implement functions available in std builds but missing from core primitives +#[cfg(not(std))] +pub(crate) trait Float: Sized { + fn is_nan(self) -> bool; + fn is_infinite(self) -> bool; + fn is_finite(self) -> bool; +} + +/// Implement functions on f32/f64 to give them APIs similar to SIMD types +pub(crate) trait FloatAsSIMD: Sized { + #[inline(always)] + fn lanes() -> usize { + 1 + } + #[inline(always)] + fn splat(scalar: Self) -> Self { + scalar + } + #[inline(always)] + fn extract(self, index: usize) -> Self { + debug_assert_eq!(index, 0); + self + } + #[inline(always)] + fn replace(self, index: usize, new_value: Self) -> Self { + debug_assert_eq!(index, 0); + new_value + } +} + +pub(crate) trait BoolAsSIMD: Sized { + fn any(self) -> bool; + fn all(self) -> bool; + fn none(self) -> bool; +} + +impl BoolAsSIMD for bool { + #[inline(always)] + fn any(self) -> bool { + self + } + + #[inline(always)] + fn all(self) -> bool { + self + } + + #[inline(always)] + fn none(self) -> bool { + !self + } +} + +macro_rules! scalar_float_impl { + ($ty:ident, $uty:ident) => { + #[cfg(not(std))] + impl Float for $ty { + #[inline] + fn is_nan(self) -> bool { + self != self + } + + #[inline] + fn is_infinite(self) -> bool { + self == ::core::$ty::INFINITY || self == ::core::$ty::NEG_INFINITY + } + + #[inline] + fn is_finite(self) -> bool { + !(self.is_nan() || self.is_infinite()) + } + } + + impl FloatSIMDUtils for $ty { + type Mask = bool; + type UInt = $uty; + + #[inline(always)] + fn all_lt(self, other: Self) -> bool { + self < other + } + + #[inline(always)] + fn all_le(self, other: Self) -> bool { + self <= other + } + + #[inline(always)] + fn all_finite(self) -> bool { + self.is_finite() + } + + #[inline(always)] + fn finite_mask(self) -> Self::Mask { + self.is_finite() + } + + #[inline(always)] + fn gt_mask(self, other: Self) -> Self::Mask { + self > other + } + + #[inline(always)] + fn ge_mask(self, other: Self) -> Self::Mask { + self >= other + } + + #[inline(always)] + fn decrease_masked(self, mask: Self::Mask) -> Self { + debug_assert!(mask, "At least one lane must be set"); + <$ty>::from_bits(self.to_bits() - 1) + } + + #[inline] + fn cast_from_int(i: Self::UInt) -> Self { + i as $ty + } + } + + impl FloatAsSIMD for $ty {} + }; +} + +scalar_float_impl!(f32, u32); +scalar_float_impl!(f64, u64); + + +#[cfg(feature = "simd_support")] +macro_rules! simd_impl { + ($ty:ident, $f_scalar:ident, $mty:ident, $uty:ident) => { + impl FloatSIMDUtils for $ty { + type Mask = $mty; + type UInt = $uty; + + #[inline(always)] + fn all_lt(self, other: Self) -> bool { + self.lt(other).all() + } + + #[inline(always)] + fn all_le(self, other: Self) -> bool { + self.le(other).all() + } + + #[inline(always)] + fn all_finite(self) -> bool { + self.finite_mask().all() + } + + #[inline(always)] + fn finite_mask(self) -> Self::Mask { + // This can possibly be done faster by checking bit patterns + let neg_inf = $ty::splat(::core::$f_scalar::NEG_INFINITY); + let pos_inf = $ty::splat(::core::$f_scalar::INFINITY); + self.gt(neg_inf) & self.lt(pos_inf) + } + + #[inline(always)] + fn gt_mask(self, other: Self) -> Self::Mask { + self.gt(other) + } + + #[inline(always)] + fn ge_mask(self, other: Self) -> Self::Mask { + self.ge(other) + } + + #[inline(always)] + fn decrease_masked(self, mask: Self::Mask) -> Self { + // Casting a mask into ints will produce all bits set for + // true, and 0 for false. Adding that to the binary + // representation of a float means subtracting one from + // the binary representation, resulting in the next lower + // value representable by $ty. This works even when the + // current value is infinity. + debug_assert!(mask.any(), "At least one lane must be set"); + <$ty>::from_bits(<$uty>::from_bits(self) + <$uty>::from_bits(mask)) + } + + #[inline] + fn cast_from_int(i: Self::UInt) -> Self { + i.cast() + } + } + }; +} + +#[cfg(feature="simd_support")] simd_impl! { f32x2, f32, m32x2, u32x2 } +#[cfg(feature="simd_support")] simd_impl! { f32x4, f32, m32x4, u32x4 } +#[cfg(feature="simd_support")] simd_impl! { f32x8, f32, m32x8, u32x8 } +#[cfg(feature="simd_support")] simd_impl! { f32x16, f32, m32x16, u32x16 } +#[cfg(feature="simd_support")] simd_impl! { f64x2, f64, m64x2, u64x2 } +#[cfg(feature="simd_support")] simd_impl! { f64x4, f64, m64x4, u64x4 } +#[cfg(feature="simd_support")] simd_impl! { f64x8, f64, m64x8, u64x8 } diff --git a/vendor/rand/src/distributions/weighted.rs b/vendor/rand/src/distributions/weighted.rs new file mode 100644 index 0000000000..6dd9273a50 --- /dev/null +++ b/vendor/rand/src/distributions/weighted.rs @@ -0,0 +1,48 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Weighted index sampling +//! +//! This module is deprecated. Use [`crate::distributions::WeightedIndex`] and +//! [`crate::distributions::WeightedError`] instead. + +pub use super::{WeightedIndex, WeightedError}; + +#[allow(missing_docs)] +#[deprecated(since = "0.8.0", note = "moved to rand_distr crate")] +pub mod alias_method { + // This module exists to provide a deprecation warning which minimises + // compile errors, but still fails to compile if ever used. + use core::marker::PhantomData; + use alloc::vec::Vec; + use super::WeightedError; + + #[derive(Debug)] + pub struct WeightedIndex { + _phantom: PhantomData, + } + impl WeightedIndex { + pub fn new(_weights: Vec) -> Result { + Err(WeightedError::NoItem) + } + } + + pub trait Weight {} + macro_rules! impl_weight { + () => {}; + ($T:ident, $($more:ident,)*) => { + impl Weight for $T {} + impl_weight!($($more,)*); + }; + } + impl_weight!(f64, f32,); + impl_weight!(u8, u16, u32, u64, usize,); + impl_weight!(i8, i16, i32, i64, isize,); + #[cfg(not(target_os = "emscripten"))] + impl_weight!(u128, i128,); +} diff --git a/vendor/rand/src/distributions/weighted_index.rs b/vendor/rand/src/distributions/weighted_index.rs new file mode 100644 index 0000000000..07ba53ec02 --- /dev/null +++ b/vendor/rand/src/distributions/weighted_index.rs @@ -0,0 +1,453 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Weighted index sampling + +use crate::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler}; +use crate::distributions::Distribution; +use crate::Rng; +use core::cmp::PartialOrd; +use core::fmt; + +// Note that this whole module is only imported if feature="alloc" is enabled. +use alloc::vec::Vec; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + +/// A distribution using weighted sampling of discrete items +/// +/// Sampling a `WeightedIndex` distribution returns the index of a randomly +/// selected element from the iterator used when the `WeightedIndex` was +/// created. The chance of a given element being picked is proportional to the +/// value of the element. The weights can use any type `X` for which an +/// implementation of [`Uniform`] exists. +/// +/// # Performance +/// +/// Time complexity of sampling from `WeightedIndex` is `O(log N)` where +/// `N` is the number of weights. As an alternative, +/// [`rand_distr::weighted_alias`](https://docs.rs/rand_distr/*/rand_distr/weighted_alias/index.html) +/// supports `O(1)` sampling, but with much higher initialisation cost. +/// +/// A `WeightedIndex` contains a `Vec` and a [`Uniform`] and so its +/// size is the sum of the size of those objects, possibly plus some alignment. +/// +/// Creating a `WeightedIndex` will allocate enough space to hold `N - 1` +/// weights of type `X`, where `N` is the number of weights. However, since +/// `Vec` doesn't guarantee a particular growth strategy, additional memory +/// might be allocated but not used. Since the `WeightedIndex` object also +/// contains, this might cause additional allocations, though for primitive +/// types, [`Uniform`] doesn't allocate any memory. +/// +/// Sampling from `WeightedIndex` will result in a single call to +/// `Uniform::sample` (method of the [`Distribution`] trait), which typically +/// will request a single value from the underlying [`RngCore`], though the +/// exact number depends on the implementation of `Uniform::sample`. +/// +/// # Example +/// +/// ``` +/// use rand::prelude::*; +/// use rand::distributions::WeightedIndex; +/// +/// let choices = ['a', 'b', 'c']; +/// let weights = [2, 1, 1]; +/// let dist = WeightedIndex::new(&weights).unwrap(); +/// let mut rng = thread_rng(); +/// for _ in 0..100 { +/// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c' +/// println!("{}", choices[dist.sample(&mut rng)]); +/// } +/// +/// let items = [('a', 0), ('b', 3), ('c', 7)]; +/// let dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap(); +/// for _ in 0..100 { +/// // 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c' +/// println!("{}", items[dist2.sample(&mut rng)].0); +/// } +/// ``` +/// +/// [`Uniform`]: crate::distributions::Uniform +/// [`RngCore`]: crate::RngCore +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +pub struct WeightedIndex { + cumulative_weights: Vec, + total_weight: X, + weight_distribution: X::Sampler, +} + +impl WeightedIndex { + /// Creates a new a `WeightedIndex` [`Distribution`] using the values + /// in `weights`. The weights can use any type `X` for which an + /// implementation of [`Uniform`] exists. + /// + /// Returns an error if the iterator is empty, if any weight is `< 0`, or + /// if its total value is 0. + /// + /// [`Uniform`]: crate::distributions::uniform::Uniform + pub fn new(weights: I) -> Result, WeightedError> + where + I: IntoIterator, + I::Item: SampleBorrow, + X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default, + { + let mut iter = weights.into_iter(); + let mut total_weight: X = iter.next().ok_or(WeightedError::NoItem)?.borrow().clone(); + + let zero = ::default(); + if !(total_weight >= zero) { + return Err(WeightedError::InvalidWeight); + } + + let mut weights = Vec::::with_capacity(iter.size_hint().0); + for w in iter { + // Note that `!(w >= x)` is not equivalent to `w < x` for partially + // ordered types due to NaNs which are equal to nothing. + if !(w.borrow() >= &zero) { + return Err(WeightedError::InvalidWeight); + } + weights.push(total_weight.clone()); + total_weight += w.borrow(); + } + + if total_weight == zero { + return Err(WeightedError::AllWeightsZero); + } + let distr = X::Sampler::new(zero, total_weight.clone()); + + Ok(WeightedIndex { + cumulative_weights: weights, + total_weight, + weight_distribution: distr, + }) + } + + /// Update a subset of weights, without changing the number of weights. + /// + /// `new_weights` must be sorted by the index. + /// + /// Using this method instead of `new` might be more efficient if only a small number of + /// weights is modified. No allocations are performed, unless the weight type `X` uses + /// allocation internally. + /// + /// In case of error, `self` is not modified. + pub fn update_weights(&mut self, new_weights: &[(usize, &X)]) -> Result<(), WeightedError> + where X: for<'a> ::core::ops::AddAssign<&'a X> + + for<'a> ::core::ops::SubAssign<&'a X> + + Clone + + Default { + if new_weights.is_empty() { + return Ok(()); + } + + let zero = ::default(); + + let mut total_weight = self.total_weight.clone(); + + // Check for errors first, so we don't modify `self` in case something + // goes wrong. + let mut prev_i = None; + for &(i, w) in new_weights { + if let Some(old_i) = prev_i { + if old_i >= i { + return Err(WeightedError::InvalidWeight); + } + } + if !(*w >= zero) { + return Err(WeightedError::InvalidWeight); + } + if i > self.cumulative_weights.len() { + return Err(WeightedError::TooMany); + } + + let mut old_w = if i < self.cumulative_weights.len() { + self.cumulative_weights[i].clone() + } else { + self.total_weight.clone() + }; + if i > 0 { + old_w -= &self.cumulative_weights[i - 1]; + } + + total_weight -= &old_w; + total_weight += w; + prev_i = Some(i); + } + if total_weight <= zero { + return Err(WeightedError::AllWeightsZero); + } + + // Update the weights. Because we checked all the preconditions in the + // previous loop, this should never panic. + let mut iter = new_weights.iter(); + + let mut prev_weight = zero.clone(); + let mut next_new_weight = iter.next(); + let &(first_new_index, _) = next_new_weight.unwrap(); + let mut cumulative_weight = if first_new_index > 0 { + self.cumulative_weights[first_new_index - 1].clone() + } else { + zero.clone() + }; + for i in first_new_index..self.cumulative_weights.len() { + match next_new_weight { + Some(&(j, w)) if i == j => { + cumulative_weight += w; + next_new_weight = iter.next(); + } + _ => { + let mut tmp = self.cumulative_weights[i].clone(); + tmp -= &prev_weight; // We know this is positive. + cumulative_weight += &tmp; + } + } + prev_weight = cumulative_weight.clone(); + core::mem::swap(&mut prev_weight, &mut self.cumulative_weights[i]); + } + + self.total_weight = total_weight; + self.weight_distribution = X::Sampler::new(zero, self.total_weight.clone()); + + Ok(()) + } +} + +impl Distribution for WeightedIndex +where X: SampleUniform + PartialOrd +{ + fn sample(&self, rng: &mut R) -> usize { + use ::core::cmp::Ordering; + let chosen_weight = self.weight_distribution.sample(rng); + // Find the first item which has a weight *higher* than the chosen weight. + self.cumulative_weights + .binary_search_by(|w| { + if *w <= chosen_weight { + Ordering::Less + } else { + Ordering::Greater + } + }) + .unwrap_err() + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[cfg(feature = "serde1")] + #[test] + fn test_weightedindex_serde1() { + let weighted_index = WeightedIndex::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap(); + + let ser_weighted_index = bincode::serialize(&weighted_index).unwrap(); + let de_weighted_index: WeightedIndex = + bincode::deserialize(&ser_weighted_index).unwrap(); + + assert_eq!( + de_weighted_index.cumulative_weights, + weighted_index.cumulative_weights + ); + assert_eq!(de_weighted_index.total_weight, weighted_index.total_weight); + } + + #[test] + fn test_accepting_nan(){ + assert_eq!( + WeightedIndex::new(&[core::f32::NAN, 0.5]).unwrap_err(), + WeightedError::InvalidWeight, + ); + assert_eq!( + WeightedIndex::new(&[core::f32::NAN]).unwrap_err(), + WeightedError::InvalidWeight, + ); + assert_eq!( + WeightedIndex::new(&[0.5, core::f32::NAN]).unwrap_err(), + WeightedError::InvalidWeight, + ); + + assert_eq!( + WeightedIndex::new(&[0.5, 7.0]) + .unwrap() + .update_weights(&[(0, &core::f32::NAN)]) + .unwrap_err(), + WeightedError::InvalidWeight, + ) + } + + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_weightedindex() { + let mut r = crate::test::rng(700); + const N_REPS: u32 = 5000; + let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]; + let total_weight = weights.iter().sum::() as f32; + + let verify = |result: [i32; 14]| { + for (i, count) in result.iter().enumerate() { + let exp = (weights[i] * N_REPS) as f32 / total_weight; + let mut err = (*count as f32 - exp).abs(); + if err != 0.0 { + err /= exp; + } + assert!(err <= 0.25); + } + }; + + // WeightedIndex from vec + let mut chosen = [0i32; 14]; + let distr = WeightedIndex::new(weights.to_vec()).unwrap(); + for _ in 0..N_REPS { + chosen[distr.sample(&mut r)] += 1; + } + verify(chosen); + + // WeightedIndex from slice + chosen = [0i32; 14]; + let distr = WeightedIndex::new(&weights[..]).unwrap(); + for _ in 0..N_REPS { + chosen[distr.sample(&mut r)] += 1; + } + verify(chosen); + + // WeightedIndex from iterator + chosen = [0i32; 14]; + let distr = WeightedIndex::new(weights.iter()).unwrap(); + for _ in 0..N_REPS { + chosen[distr.sample(&mut r)] += 1; + } + verify(chosen); + + for _ in 0..5 { + assert_eq!(WeightedIndex::new(&[0, 1]).unwrap().sample(&mut r), 1); + assert_eq!(WeightedIndex::new(&[1, 0]).unwrap().sample(&mut r), 0); + assert_eq!( + WeightedIndex::new(&[0, 0, 0, 0, 10, 0]) + .unwrap() + .sample(&mut r), + 4 + ); + } + + assert_eq!( + WeightedIndex::new(&[10][0..0]).unwrap_err(), + WeightedError::NoItem + ); + assert_eq!( + WeightedIndex::new(&[0]).unwrap_err(), + WeightedError::AllWeightsZero + ); + assert_eq!( + WeightedIndex::new(&[10, 20, -1, 30]).unwrap_err(), + WeightedError::InvalidWeight + ); + assert_eq!( + WeightedIndex::new(&[-10, 20, 1, 30]).unwrap_err(), + WeightedError::InvalidWeight + ); + assert_eq!( + WeightedIndex::new(&[-10]).unwrap_err(), + WeightedError::InvalidWeight + ); + } + + #[test] + fn test_update_weights() { + let data = [ + ( + &[10u32, 2, 3, 4][..], + &[(1, &100), (2, &4)][..], // positive change + &[10, 100, 4, 4][..], + ), + ( + &[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..], + &[(2, &1), (5, &1), (13, &100)][..], // negative change and last element + &[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..], + ), + ]; + + for (weights, update, expected_weights) in data.iter() { + let total_weight = weights.iter().sum::(); + let mut distr = WeightedIndex::new(weights.to_vec()).unwrap(); + assert_eq!(distr.total_weight, total_weight); + + distr.update_weights(update).unwrap(); + let expected_total_weight = expected_weights.iter().sum::(); + let expected_distr = WeightedIndex::new(expected_weights.to_vec()).unwrap(); + assert_eq!(distr.total_weight, expected_total_weight); + assert_eq!(distr.total_weight, expected_distr.total_weight); + assert_eq!(distr.cumulative_weights, expected_distr.cumulative_weights); + } + } + + #[test] + fn value_stability() { + fn test_samples( + weights: I, buf: &mut [usize], expected: &[usize], + ) where + I: IntoIterator, + I::Item: SampleBorrow, + X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default, + { + assert_eq!(buf.len(), expected.len()); + let distr = WeightedIndex::new(weights).unwrap(); + let mut rng = crate::test::rng(701); + for r in buf.iter_mut() { + *r = rng.sample(&distr); + } + assert_eq!(buf, expected); + } + + let mut buf = [0; 10]; + test_samples(&[1i32, 1, 1, 1, 1, 1, 1, 1, 1], &mut buf, &[ + 0, 6, 2, 6, 3, 4, 7, 8, 2, 5, + ]); + test_samples(&[0.7f32, 0.1, 0.1, 0.1], &mut buf, &[ + 0, 0, 0, 1, 0, 0, 2, 3, 0, 0, + ]); + test_samples(&[1.0f64, 0.999, 0.998, 0.997], &mut buf, &[ + 2, 2, 1, 3, 2, 1, 3, 3, 2, 1, + ]); + } +} + +/// Error type returned from `WeightedIndex::new`. +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum WeightedError { + /// The provided weight collection contains no items. + NoItem, + + /// A weight is either less than zero, greater than the supported maximum, + /// NaN, or otherwise invalid. + InvalidWeight, + + /// All items in the provided weight collection are zero. + AllWeightsZero, + + /// Too many weights are provided (length greater than `u32::MAX`) + TooMany, +} + +#[cfg(feature = "std")] +impl ::std::error::Error for WeightedError {} + +impl fmt::Display for WeightedError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + WeightedError::NoItem => write!(f, "No weights provided."), + WeightedError::InvalidWeight => write!(f, "A weight is invalid."), + WeightedError::AllWeightsZero => write!(f, "All weights are zero."), + WeightedError::TooMany => write!(f, "Too many weights (hit u32::MAX)"), + } + } +} diff --git a/vendor/rand/src/lib.rs b/vendor/rand/src/lib.rs new file mode 100644 index 0000000000..8bf7a9df12 --- /dev/null +++ b/vendor/rand/src/lib.rs @@ -0,0 +1,215 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013-2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Utilities for random number generation +//! +//! Rand provides utilities to generate random numbers, to convert them to +//! useful types and distributions, and some randomness-related algorithms. +//! +//! # Quick Start +//! +//! To get you started quickly, the easiest and highest-level way to get +//! a random value is to use [`random()`]; alternatively you can use +//! [`thread_rng()`]. The [`Rng`] trait provides a useful API on all RNGs, while +//! the [`distributions`] and [`seq`] modules provide further +//! functionality on top of RNGs. +//! +//! ``` +//! use rand::prelude::*; +//! +//! if rand::random() { // generates a boolean +//! // Try printing a random unicode code point (probably a bad idea)! +//! println!("char: {}", rand::random::()); +//! } +//! +//! let mut rng = rand::thread_rng(); +//! let y: f64 = rng.gen(); // generates a float between 0 and 1 +//! +//! let mut nums: Vec = (1..100).collect(); +//! nums.shuffle(&mut rng); +//! ``` +//! +//! # The Book +//! +//! For the user guide and further documentation, please read +//! [The Rust Rand Book](https://rust-random.github.io/book). + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![no_std] +#![cfg_attr(feature = "simd_support", feature(stdsimd))] +#![cfg_attr(feature = "nightly", feature(slice_partition_at_index))] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![allow( + clippy::float_cmp, + clippy::neg_cmp_op_on_partial_ord, +)] + +#[cfg(feature = "std")] extern crate std; +#[cfg(feature = "alloc")] extern crate alloc; + +#[allow(unused)] +macro_rules! trace { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::trace!($($x)*) + } +) } +#[allow(unused)] +macro_rules! debug { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::debug!($($x)*) + } +) } +#[allow(unused)] +macro_rules! info { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::info!($($x)*) + } +) } +#[allow(unused)] +macro_rules! warn { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::warn!($($x)*) + } +) } +#[allow(unused)] +macro_rules! error { ($($x:tt)*) => ( + #[cfg(feature = "log")] { + log::error!($($x)*) + } +) } + +// Re-exports from rand_core +pub use rand_core::{CryptoRng, Error, RngCore, SeedableRng}; + +// Public modules +pub mod distributions; +pub mod prelude; +mod rng; +pub mod rngs; +pub mod seq; + +// Public exports +#[cfg(all(feature = "std", feature = "std_rng"))] +pub use crate::rngs::thread::thread_rng; +pub use rng::{Fill, Rng}; + +#[cfg(all(feature = "std", feature = "std_rng"))] +use crate::distributions::{Distribution, Standard}; + +/// Generates a random value using the thread-local random number generator. +/// +/// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for +/// documentation of the entropy source and [`Standard`] for documentation of +/// distributions and type-specific generation. +/// +/// # Provided implementations +/// +/// The following types have provided implementations that +/// generate values with the following ranges and distributions: +/// +/// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed +/// over all values of the type. +/// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all +/// code points in the range `0...0x10_FFFF`, except for the range +/// `0xD800...0xDFFF` (the surrogate code points). This includes +/// unassigned/reserved code points. +/// * `bool`: Generates `false` or `true`, each with probability 0.5. +/// * Floating point types (`f32` and `f64`): Uniformly distributed in the +/// half-open range `[0, 1)`. See notes below. +/// * Wrapping integers (`Wrapping`), besides the type identical to their +/// normal integer variants. +/// +/// Also supported is the generation of the following +/// compound types where all component types are supported: +/// +/// * Tuples (up to 12 elements): each element is generated sequentially. +/// * Arrays (up to 32 elements): each element is generated sequentially; +/// see also [`Rng::fill`] which supports arbitrary array length for integer +/// types and tends to be faster for `u32` and smaller types. +/// * `Option` first generates a `bool`, and if true generates and returns +/// `Some(value)` where `value: T`, otherwise returning `None`. +/// +/// # Examples +/// +/// ``` +/// let x = rand::random::(); +/// println!("{}", x); +/// +/// let y = rand::random::(); +/// println!("{}", y); +/// +/// if rand::random() { // generates a boolean +/// println!("Better lucky than good!"); +/// } +/// ``` +/// +/// If you're calling `random()` in a loop, caching the generator as in the +/// following example can increase performance. +/// +/// ``` +/// use rand::Rng; +/// +/// let mut v = vec![1, 2, 3]; +/// +/// for x in v.iter_mut() { +/// *x = rand::random() +/// } +/// +/// // can be made faster by caching thread_rng +/// +/// let mut rng = rand::thread_rng(); +/// +/// for x in v.iter_mut() { +/// *x = rng.gen(); +/// } +/// ``` +/// +/// [`Standard`]: distributions::Standard +#[cfg(all(feature = "std", feature = "std_rng"))] +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))] +#[inline] +pub fn random() -> T +where Standard: Distribution { + thread_rng().gen() +} + +#[cfg(test)] +mod test { + use super::*; + + /// Construct a deterministic RNG with the given seed + pub fn rng(seed: u64) -> impl RngCore { + // For tests, we want a statistically good, fast, reproducible RNG. + // PCG32 will do fine, and will be easy to embed if we ever need to. + const INC: u64 = 11634580027462260723; + rand_pcg::Pcg32::new(seed, INC) + } + + #[test] + #[cfg(all(feature = "std", feature = "std_rng"))] + fn test_random() { + // not sure how to test this aside from just getting some values + let _n: usize = random(); + let _f: f32 = random(); + let _o: Option> = random(); + let _many: ( + (), + (usize, isize, Option<(u32, (bool,))>), + (u8, i8, u16, i16, u32, i32, u64, i64), + (f32, (f64, (f64,))), + ) = random(); + } +} diff --git a/vendor/rand/src/prelude.rs b/vendor/rand/src/prelude.rs new file mode 100644 index 0000000000..51c457e3f9 --- /dev/null +++ b/vendor/rand/src/prelude.rs @@ -0,0 +1,34 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Convenience re-export of common members +//! +//! Like the standard library's prelude, this module simplifies importing of +//! common items. Unlike the standard prelude, the contents of this module must +//! be imported manually: +//! +//! ``` +//! use rand::prelude::*; +//! # let mut r = StdRng::from_rng(thread_rng()).unwrap(); +//! # let _: f32 = r.gen(); +//! ``` + +#[doc(no_inline)] pub use crate::distributions::Distribution; +#[cfg(feature = "small_rng")] +#[doc(no_inline)] +pub use crate::rngs::SmallRng; +#[cfg(feature = "std_rng")] +#[doc(no_inline)] pub use crate::rngs::StdRng; +#[doc(no_inline)] +#[cfg(all(feature = "std", feature = "std_rng"))] +pub use crate::rngs::ThreadRng; +#[doc(no_inline)] pub use crate::seq::{IteratorRandom, SliceRandom}; +#[doc(no_inline)] +#[cfg(all(feature = "std", feature = "std_rng"))] +pub use crate::{random, thread_rng}; +#[doc(no_inline)] pub use crate::{CryptoRng, Rng, RngCore, SeedableRng}; diff --git a/vendor/rand/src/rng.rs b/vendor/rand/src/rng.rs new file mode 100644 index 0000000000..bb977a5437 --- /dev/null +++ b/vendor/rand/src/rng.rs @@ -0,0 +1,585 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013-2017 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! [`Rng`] trait + +use rand_core::{Error, RngCore}; +use crate::distributions::uniform::{SampleRange, SampleUniform}; +use crate::distributions::{self, Distribution, Standard}; +use core::num::Wrapping; +use core::{mem, slice}; + +/// An automatically-implemented extension trait on [`RngCore`] providing high-level +/// generic methods for sampling values and other convenience methods. +/// +/// This is the primary trait to use when generating random values. +/// +/// # Generic usage +/// +/// The basic pattern is `fn foo(rng: &mut R)`. Some +/// things are worth noting here: +/// +/// - Since `Rng: RngCore` and every `RngCore` implements `Rng`, it makes no +/// difference whether we use `R: Rng` or `R: RngCore`. +/// - The `+ ?Sized` un-bounding allows functions to be called directly on +/// type-erased references; i.e. `foo(r)` where `r: &mut RngCore`. Without +/// this it would be necessary to write `foo(&mut r)`. +/// +/// An alternative pattern is possible: `fn foo(rng: R)`. This has some +/// trade-offs. It allows the argument to be consumed directly without a `&mut` +/// (which is how `from_rng(thread_rng())` works); also it still works directly +/// on references (including type-erased references). Unfortunately within the +/// function `foo` it is not known whether `rng` is a reference type or not, +/// hence many uses of `rng` require an extra reference, either explicitly +/// (`distr.sample(&mut rng)`) or implicitly (`rng.gen()`); one may hope the +/// optimiser can remove redundant references later. +/// +/// Example: +/// +/// ``` +/// # use rand::thread_rng; +/// use rand::Rng; +/// +/// fn foo(rng: &mut R) -> f32 { +/// rng.gen() +/// } +/// +/// # let v = foo(&mut thread_rng()); +/// ``` +pub trait Rng: RngCore { + /// Return a random value supporting the [`Standard`] distribution. + /// + /// # Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// + /// let mut rng = thread_rng(); + /// let x: u32 = rng.gen(); + /// println!("{}", x); + /// println!("{:?}", rng.gen::<(f64, bool)>()); + /// ``` + /// + /// # Arrays and tuples + /// + /// The `rng.gen()` method is able to generate arrays (up to 32 elements) + /// and tuples (up to 12 elements), so long as all element types can be + /// generated. + /// + /// For arrays of integers, especially for those with small element types + /// (< 64 bit), it will likely be faster to instead use [`Rng::fill`]. + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// + /// let mut rng = thread_rng(); + /// let tuple: (u8, i32, char) = rng.gen(); // arbitrary tuple support + /// + /// let arr1: [f32; 32] = rng.gen(); // array construction + /// let mut arr2 = [0u8; 128]; + /// rng.fill(&mut arr2); // array fill + /// ``` + /// + /// [`Standard`]: distributions::Standard + #[inline] + fn gen(&mut self) -> T + where Standard: Distribution { + Standard.sample(self) + } + + /// Generate a random value in the given range. + /// + /// This function is optimised for the case that only a single sample is + /// made from the given range. See also the [`Uniform`] distribution + /// type which may be faster if sampling from the same range repeatedly. + /// + /// Only `gen_range(low..high)` and `gen_range(low..=high)` are supported. + /// + /// # Panics + /// + /// Panics if the range is empty. + /// + /// # Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// + /// let mut rng = thread_rng(); + /// + /// // Exclusive range + /// let n: u32 = rng.gen_range(0..10); + /// println!("{}", n); + /// let m: f64 = rng.gen_range(-40.0..1.3e5); + /// println!("{}", m); + /// + /// // Inclusive range + /// let n: u32 = rng.gen_range(0..=10); + /// println!("{}", n); + /// ``` + /// + /// [`Uniform`]: distributions::uniform::Uniform + fn gen_range(&mut self, range: R) -> T + where + T: SampleUniform, + R: SampleRange + { + assert!(!range.is_empty(), "cannot sample empty range"); + range.sample_single(self) + } + + /// Sample a new value, using the given distribution. + /// + /// ### Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// use rand::distributions::Uniform; + /// + /// let mut rng = thread_rng(); + /// let x = rng.sample(Uniform::new(10u32, 15)); + /// // Type annotation requires two types, the type and distribution; the + /// // distribution can be inferred. + /// let y = rng.sample::(Uniform::new(10, 15)); + /// ``` + fn sample>(&mut self, distr: D) -> T { + distr.sample(self) + } + + /// Create an iterator that generates values using the given distribution. + /// + /// Note that this function takes its arguments by value. This works since + /// `(&mut R): Rng where R: Rng` and + /// `(&D): Distribution where D: Distribution`, + /// however borrowing is not automatic hence `rng.sample_iter(...)` may + /// need to be replaced with `(&mut rng).sample_iter(...)`. + /// + /// # Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// use rand::distributions::{Alphanumeric, Uniform, Standard}; + /// + /// let mut rng = thread_rng(); + /// + /// // Vec of 16 x f32: + /// let v: Vec = (&mut rng).sample_iter(Standard).take(16).collect(); + /// + /// // String: + /// let s: String = (&mut rng).sample_iter(Alphanumeric) + /// .take(7) + /// .map(char::from) + /// .collect(); + /// + /// // Combined values + /// println!("{:?}", (&mut rng).sample_iter(Standard).take(5) + /// .collect::>()); + /// + /// // Dice-rolling: + /// let die_range = Uniform::new_inclusive(1, 6); + /// let mut roll_die = (&mut rng).sample_iter(die_range); + /// while roll_die.next().unwrap() != 6 { + /// println!("Not a 6; rolling again!"); + /// } + /// ``` + fn sample_iter(self, distr: D) -> distributions::DistIter + where + D: Distribution, + Self: Sized, + { + distr.sample_iter(self) + } + + /// Fill any type implementing [`Fill`] with random data + /// + /// The distribution is expected to be uniform with portable results, but + /// this cannot be guaranteed for third-party implementations. + /// + /// This is identical to [`try_fill`] except that it panics on error. + /// + /// # Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// + /// let mut arr = [0i8; 20]; + /// thread_rng().fill(&mut arr[..]); + /// ``` + /// + /// [`fill_bytes`]: RngCore::fill_bytes + /// [`try_fill`]: Rng::try_fill + fn fill(&mut self, dest: &mut T) { + dest.try_fill(self).unwrap_or_else(|_| panic!("Rng::fill failed")) + } + + /// Fill any type implementing [`Fill`] with random data + /// + /// The distribution is expected to be uniform with portable results, but + /// this cannot be guaranteed for third-party implementations. + /// + /// This is identical to [`fill`] except that it forwards errors. + /// + /// # Example + /// + /// ``` + /// # use rand::Error; + /// use rand::{thread_rng, Rng}; + /// + /// # fn try_inner() -> Result<(), Error> { + /// let mut arr = [0u64; 4]; + /// thread_rng().try_fill(&mut arr[..])?; + /// # Ok(()) + /// # } + /// + /// # try_inner().unwrap() + /// ``` + /// + /// [`try_fill_bytes`]: RngCore::try_fill_bytes + /// [`fill`]: Rng::fill + fn try_fill(&mut self, dest: &mut T) -> Result<(), Error> { + dest.try_fill(self) + } + + /// Return a bool with a probability `p` of being true. + /// + /// See also the [`Bernoulli`] distribution, which may be faster if + /// sampling from the same probability repeatedly. + /// + /// # Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// + /// let mut rng = thread_rng(); + /// println!("{}", rng.gen_bool(1.0 / 3.0)); + /// ``` + /// + /// # Panics + /// + /// If `p < 0` or `p > 1`. + /// + /// [`Bernoulli`]: distributions::Bernoulli + #[inline] + fn gen_bool(&mut self, p: f64) -> bool { + let d = distributions::Bernoulli::new(p).unwrap(); + self.sample(d) + } + + /// Return a bool with a probability of `numerator/denominator` of being + /// true. I.e. `gen_ratio(2, 3)` has chance of 2 in 3, or about 67%, of + /// returning true. If `numerator == denominator`, then the returned value + /// is guaranteed to be `true`. If `numerator == 0`, then the returned + /// value is guaranteed to be `false`. + /// + /// See also the [`Bernoulli`] distribution, which may be faster if + /// sampling from the same `numerator` and `denominator` repeatedly. + /// + /// # Panics + /// + /// If `denominator == 0` or `numerator > denominator`. + /// + /// # Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// + /// let mut rng = thread_rng(); + /// println!("{}", rng.gen_ratio(2, 3)); + /// ``` + /// + /// [`Bernoulli`]: distributions::Bernoulli + #[inline] + fn gen_ratio(&mut self, numerator: u32, denominator: u32) -> bool { + let d = distributions::Bernoulli::from_ratio(numerator, denominator).unwrap(); + self.sample(d) + } +} + +impl Rng for R {} + +/// Types which may be filled with random data +/// +/// This trait allows arrays to be efficiently filled with random data. +/// +/// Implementations are expected to be portable across machines unless +/// clearly documented otherwise (see the +/// [Chapter on Portability](https://rust-random.github.io/book/portability.html)). +pub trait Fill { + /// Fill self with random data + fn try_fill(&mut self, rng: &mut R) -> Result<(), Error>; +} + +macro_rules! impl_fill_each { + () => {}; + ($t:ty) => { + impl Fill for [$t] { + fn try_fill(&mut self, rng: &mut R) -> Result<(), Error> { + for elt in self.iter_mut() { + *elt = rng.gen(); + } + Ok(()) + } + } + }; + ($t:ty, $($tt:ty,)*) => { + impl_fill_each!($t); + impl_fill_each!($($tt,)*); + }; +} + +impl_fill_each!(bool, char, f32, f64,); + +impl Fill for [u8] { + fn try_fill(&mut self, rng: &mut R) -> Result<(), Error> { + rng.try_fill_bytes(self) + } +} + +macro_rules! impl_fill { + () => {}; + ($t:ty) => { + impl Fill for [$t] { + #[inline(never)] // in micro benchmarks, this improves performance + fn try_fill(&mut self, rng: &mut R) -> Result<(), Error> { + if self.len() > 0 { + rng.try_fill_bytes(unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr() + as *mut u8, + self.len() * mem::size_of::<$t>() + ) + })?; + for x in self { + *x = x.to_le(); + } + } + Ok(()) + } + } + + impl Fill for [Wrapping<$t>] { + #[inline(never)] + fn try_fill(&mut self, rng: &mut R) -> Result<(), Error> { + if self.len() > 0 { + rng.try_fill_bytes(unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr() + as *mut u8, + self.len() * mem::size_of::<$t>() + ) + })?; + for x in self { + *x = Wrapping(x.0.to_le()); + } + } + Ok(()) + } + } + }; + ($t:ty, $($tt:ty,)*) => { + impl_fill!($t); + // TODO: this could replace above impl once Rust #32463 is fixed + // impl_fill!(Wrapping<$t>); + impl_fill!($($tt,)*); + } +} + +impl_fill!(u16, u32, u64, usize,); +#[cfg(not(target_os = "emscripten"))] +impl_fill!(u128); +impl_fill!(i8, i16, i32, i64, isize,); +#[cfg(not(target_os = "emscripten"))] +impl_fill!(i128); + +macro_rules! impl_fill_arrays { + ($n:expr,) => {}; + ($n:expr, $N:ident) => { + impl Fill for [T; $n] where [T]: Fill { + fn try_fill(&mut self, rng: &mut R) -> Result<(), Error> { + self[..].try_fill(rng) + } + } + }; + ($n:expr, $N:ident, $($NN:ident,)*) => { + impl_fill_arrays!($n, $N); + impl_fill_arrays!($n - 1, $($NN,)*); + }; + (!div $n:expr,) => {}; + (!div $n:expr, $N:ident, $($NN:ident,)*) => { + impl_fill_arrays!($n, $N); + impl_fill_arrays!(!div $n / 2, $($NN,)*); + }; +} +#[rustfmt::skip] +impl_fill_arrays!(32, N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,); +impl_fill_arrays!(!div 4096, N,N,N,N,N,N,N,); + +#[cfg(test)] +mod test { + use super::*; + use crate::test::rng; + use crate::rngs::mock::StepRng; + #[cfg(feature = "alloc")] use alloc::boxed::Box; + + #[test] + fn test_fill_bytes_default() { + let mut r = StepRng::new(0x11_22_33_44_55_66_77_88, 0); + + // check every remainder mod 8, both in small and big vectors. + let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87]; + for &n in lengths.iter() { + let mut buffer = [0u8; 87]; + let v = &mut buffer[0..n]; + r.fill_bytes(v); + + // use this to get nicer error messages. + for (i, &byte) in v.iter().enumerate() { + if byte == 0 { + panic!("byte {} of {} is zero", i, n) + } + } + } + } + + #[test] + fn test_fill() { + let x = 9041086907909331047; // a random u64 + let mut rng = StepRng::new(x, 0); + + // Convert to byte sequence and back to u64; byte-swap twice if BE. + let mut array = [0u64; 2]; + rng.fill(&mut array[..]); + assert_eq!(array, [x, x]); + assert_eq!(rng.next_u64(), x); + + // Convert to bytes then u32 in LE order + let mut array = [0u32; 2]; + rng.fill(&mut array[..]); + assert_eq!(array, [x as u32, (x >> 32) as u32]); + assert_eq!(rng.next_u32(), x as u32); + + // Check equivalence using wrapped arrays + let mut warray = [Wrapping(0u32); 2]; + rng.fill(&mut warray[..]); + assert_eq!(array[0], warray[0].0); + assert_eq!(array[1], warray[1].0); + + // Check equivalence for generated floats + let mut array = [0f32; 2]; + rng.fill(&mut array); + let gen: [f32; 2] = rng.gen(); + assert_eq!(array, gen); + } + + #[test] + fn test_fill_empty() { + let mut array = [0u32; 0]; + let mut rng = StepRng::new(0, 1); + rng.fill(&mut array); + rng.fill(&mut array[..]); + } + + #[test] + fn test_gen_range_int() { + let mut r = rng(101); + for _ in 0..1000 { + let a = r.gen_range(-4711..17); + assert!(a >= -4711 && a < 17); + let a = r.gen_range(-3i8..42); + assert!(a >= -3i8 && a < 42i8); + let a: u16 = r.gen_range(10..99); + assert!(a >= 10u16 && a < 99u16); + let a = r.gen_range(-100i32..2000); + assert!(a >= -100i32 && a < 2000i32); + let a: u32 = r.gen_range(12..=24); + assert!(a >= 12u32 && a <= 24u32); + + assert_eq!(r.gen_range(0u32..1), 0u32); + assert_eq!(r.gen_range(-12i64..-11), -12i64); + assert_eq!(r.gen_range(3_000_000..3_000_001), 3_000_000); + } + } + + #[test] + fn test_gen_range_float() { + let mut r = rng(101); + for _ in 0..1000 { + let a = r.gen_range(-4.5..1.7); + assert!(a >= -4.5 && a < 1.7); + let a = r.gen_range(-1.1..=-0.3); + assert!(a >= -1.1 && a <= -0.3); + + assert_eq!(r.gen_range(0.0f32..=0.0), 0.); + assert_eq!(r.gen_range(-11.0..=-11.0), -11.); + assert_eq!(r.gen_range(3_000_000.0..=3_000_000.0), 3_000_000.); + } + } + + #[test] + #[should_panic] + fn test_gen_range_panic_int() { + let mut r = rng(102); + r.gen_range(5..-2); + } + + #[test] + #[should_panic] + fn test_gen_range_panic_usize() { + let mut r = rng(103); + r.gen_range(5..2); + } + + #[test] + fn test_gen_bool() { + let mut r = rng(105); + for _ in 0..5 { + assert_eq!(r.gen_bool(0.0), false); + assert_eq!(r.gen_bool(1.0), true); + } + } + + #[test] + fn test_rng_trait_object() { + use crate::distributions::{Distribution, Standard}; + let mut rng = rng(109); + let mut r = &mut rng as &mut dyn RngCore; + r.next_u32(); + r.gen::(); + assert_eq!(r.gen_range(0..1), 0); + let _c: u8 = Standard.sample(&mut r); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_rng_boxed_trait() { + use crate::distributions::{Distribution, Standard}; + let rng = rng(110); + let mut r = Box::new(rng) as Box; + r.next_u32(); + r.gen::(); + assert_eq!(r.gen_range(0..1), 0); + let _c: u8 = Standard.sample(&mut r); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_gen_ratio_average() { + const NUM: u32 = 3; + const DENOM: u32 = 10; + const N: u32 = 100_000; + + let mut sum: u32 = 0; + let mut rng = rng(111); + for _ in 0..N { + if rng.gen_ratio(NUM, DENOM) { + sum += 1; + } + } + // Have Binomial(N, NUM/DENOM) distribution + let expected = (NUM * N) / DENOM; // exact integer + assert!(((sum - expected) as i32).abs() < 500); + } +} diff --git a/vendor/rand/src/rngs/adapter/mod.rs b/vendor/rand/src/rngs/adapter/mod.rs new file mode 100644 index 0000000000..22b7158d40 --- /dev/null +++ b/vendor/rand/src/rngs/adapter/mod.rs @@ -0,0 +1,15 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Wrappers / adapters forming RNGs + +mod read; +mod reseeding; + +pub use self::read::{ReadError, ReadRng}; +pub use self::reseeding::ReseedingRng; diff --git a/vendor/rand/src/rngs/adapter/read.rs b/vendor/rand/src/rngs/adapter/read.rs new file mode 100644 index 0000000000..63b0dd0c0f --- /dev/null +++ b/vendor/rand/src/rngs/adapter/read.rs @@ -0,0 +1,157 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A wrapper around any Read to treat it as an RNG. + +use std::fmt; +use std::io::Read; + +use rand_core::{impls, Error, RngCore}; + + +/// An RNG that reads random bytes straight from any type supporting +/// [`std::io::Read`], for example files. +/// +/// This will work best with an infinite reader, but that is not required. +/// +/// This can be used with `/dev/urandom` on Unix but it is recommended to use +/// [`OsRng`] instead. +/// +/// # Panics +/// +/// `ReadRng` uses [`std::io::Read::read_exact`], which retries on interrupts. +/// All other errors from the underlying reader, including when it does not +/// have enough data, will only be reported through [`try_fill_bytes`]. +/// The other [`RngCore`] methods will panic in case of an error. +/// +/// # Example +/// +/// ``` +/// use rand::Rng; +/// use rand::rngs::adapter::ReadRng; +/// +/// let data = vec![1, 2, 3, 4, 5, 6, 7, 8]; +/// let mut rng = ReadRng::new(&data[..]); +/// println!("{:x}", rng.gen::()); +/// ``` +/// +/// [`OsRng`]: crate::rngs::OsRng +/// [`try_fill_bytes`]: RngCore::try_fill_bytes +#[derive(Debug)] +pub struct ReadRng { + reader: R, +} + +impl ReadRng { + /// Create a new `ReadRng` from a `Read`. + pub fn new(r: R) -> ReadRng { + ReadRng { reader: r } + } +} + +impl RngCore for ReadRng { + fn next_u32(&mut self) -> u32 { + impls::next_u32_via_fill(self) + } + + fn next_u64(&mut self) -> u64 { + impls::next_u64_via_fill(self) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.try_fill_bytes(dest).unwrap_or_else(|err| { + panic!( + "reading random bytes from Read implementation failed; error: {}", + err + ) + }); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + if dest.is_empty() { + return Ok(()); + } + // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`. + self.reader + .read_exact(dest) + .map_err(|e| Error::new(ReadError(e))) + } +} + +/// `ReadRng` error type +#[derive(Debug)] +pub struct ReadError(std::io::Error); + +impl fmt::Display for ReadError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ReadError: {}", self.0) + } +} + +impl std::error::Error for ReadError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&self.0) + } +} + + +#[cfg(test)] +mod test { + use std::println; + + use super::ReadRng; + use crate::RngCore; + + #[test] + fn test_reader_rng_u64() { + // transmute from the target to avoid endianness concerns. + #[rustfmt::skip] + let v = [0u8, 0, 0, 0, 0, 0, 0, 1, + 0, 4, 0, 0, 3, 0, 0, 2, + 5, 0, 0, 0, 0, 0, 0, 0]; + let mut rng = ReadRng::new(&v[..]); + + assert_eq!(rng.next_u64(), 1 << 56); + assert_eq!(rng.next_u64(), (2 << 56) + (3 << 32) + (4 << 8)); + assert_eq!(rng.next_u64(), 5); + } + + #[test] + fn test_reader_rng_u32() { + let v = [0u8, 0, 0, 1, 0, 0, 2, 0, 3, 0, 0, 0]; + let mut rng = ReadRng::new(&v[..]); + + assert_eq!(rng.next_u32(), 1 << 24); + assert_eq!(rng.next_u32(), 2 << 16); + assert_eq!(rng.next_u32(), 3); + } + + #[test] + fn test_reader_rng_fill_bytes() { + let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; + let mut w = [0u8; 8]; + + let mut rng = ReadRng::new(&v[..]); + rng.fill_bytes(&mut w); + + assert!(v == w); + } + + #[test] + fn test_reader_rng_insufficient_bytes() { + let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; + let mut w = [0u8; 9]; + + let mut rng = ReadRng::new(&v[..]); + + let result = rng.try_fill_bytes(&mut w); + assert!(result.is_err()); + println!("Error: {}", result.unwrap_err()); + } +} diff --git a/vendor/rand/src/rngs/adapter/reseeding.rs b/vendor/rand/src/rngs/adapter/reseeding.rs new file mode 100644 index 0000000000..1977cb3190 --- /dev/null +++ b/vendor/rand/src/rngs/adapter/reseeding.rs @@ -0,0 +1,370 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2013 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A wrapper around another PRNG that reseeds it after it +//! generates a certain number of random bytes. + +use core::mem::size_of; + +use rand_core::block::{BlockRng, BlockRngCore}; +use rand_core::{CryptoRng, Error, RngCore, SeedableRng}; + +/// A wrapper around any PRNG that implements [`BlockRngCore`], that adds the +/// ability to reseed it. +/// +/// `ReseedingRng` reseeds the underlying PRNG in the following cases: +/// +/// - On a manual call to [`reseed()`]. +/// - After `clone()`, the clone will be reseeded on first use. +/// - After a process is forked, the RNG in the child process is reseeded within +/// the next few generated values, depending on the block size of the +/// underlying PRNG. For ChaCha and Hc128 this is a maximum of +/// 15 `u32` values before reseeding. +/// - After the PRNG has generated a configurable number of random bytes. +/// +/// # When should reseeding after a fixed number of generated bytes be used? +/// +/// Reseeding after a fixed number of generated bytes is never strictly +/// *necessary*. Cryptographic PRNGs don't have a limited number of bytes they +/// can output, or at least not a limit reachable in any practical way. There is +/// no such thing as 'running out of entropy'. +/// +/// Occasionally reseeding can be seen as some form of 'security in depth'. Even +/// if in the future a cryptographic weakness is found in the CSPRNG being used, +/// or a flaw in the implementation, occasionally reseeding should make +/// exploiting it much more difficult or even impossible. +/// +/// Use [`ReseedingRng::new`] with a `threshold` of `0` to disable reseeding +/// after a fixed number of generated bytes. +/// +/// # Error handling +/// +/// Although unlikely, reseeding the wrapped PRNG can fail. `ReseedingRng` will +/// never panic but try to handle the error intelligently through some +/// combination of retrying and delaying reseeding until later. +/// If handling the source error fails `ReseedingRng` will continue generating +/// data from the wrapped PRNG without reseeding. +/// +/// Manually calling [`reseed()`] will not have this retry or delay logic, but +/// reports the error. +/// +/// # Example +/// +/// ``` +/// use rand::prelude::*; +/// use rand_chacha::ChaCha20Core; // Internal part of ChaChaRng that +/// // implements BlockRngCore +/// use rand::rngs::OsRng; +/// use rand::rngs::adapter::ReseedingRng; +/// +/// let prng = ChaCha20Core::from_entropy(); +/// let mut reseeding_rng = ReseedingRng::new(prng, 0, OsRng); +/// +/// println!("{}", reseeding_rng.gen::()); +/// +/// let mut cloned_rng = reseeding_rng.clone(); +/// assert!(reseeding_rng.gen::() != cloned_rng.gen::()); +/// ``` +/// +/// [`BlockRngCore`]: rand_core::block::BlockRngCore +/// [`ReseedingRng::new`]: ReseedingRng::new +/// [`reseed()`]: ReseedingRng::reseed +#[derive(Debug)] +pub struct ReseedingRng(BlockRng>) +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore; + +impl ReseedingRng +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore, +{ + /// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG + /// to use as reseeder. + /// + /// `threshold` sets the number of generated bytes after which to reseed the + /// PRNG. Set it to zero to never reseed based on the number of generated + /// values. + pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self { + ReseedingRng(BlockRng::new(ReseedingCore::new(rng, threshold, reseeder))) + } + + /// Reseed the internal PRNG. + pub fn reseed(&mut self) -> Result<(), Error> { + self.0.core.reseed() + } +} + +// TODO: this should be implemented for any type where the inner type +// implements RngCore, but we can't specify that because ReseedingCore is private +impl RngCore for ReseedingRng +where + R: BlockRngCore + SeedableRng, + ::Results: AsRef<[u32]> + AsMut<[u32]>, +{ + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest) + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl Clone for ReseedingRng +where + R: BlockRngCore + SeedableRng + Clone, + Rsdr: RngCore + Clone, +{ + fn clone(&self) -> ReseedingRng { + // Recreating `BlockRng` seems easier than cloning it and resetting + // the index. + ReseedingRng(BlockRng::new(self.0.core.clone())) + } +} + +impl CryptoRng for ReseedingRng +where + R: BlockRngCore + SeedableRng + CryptoRng, + Rsdr: RngCore + CryptoRng, +{ +} + +#[derive(Debug)] +struct ReseedingCore { + inner: R, + reseeder: Rsdr, + threshold: i64, + bytes_until_reseed: i64, + fork_counter: usize, +} + +impl BlockRngCore for ReseedingCore +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore, +{ + type Item = ::Item; + type Results = ::Results; + + fn generate(&mut self, results: &mut Self::Results) { + let global_fork_counter = fork::get_fork_counter(); + if self.bytes_until_reseed <= 0 || self.is_forked(global_fork_counter) { + // We get better performance by not calling only `reseed` here + // and continuing with the rest of the function, but by directly + // returning from a non-inlined function. + return self.reseed_and_generate(results, global_fork_counter); + } + let num_bytes = results.as_ref().len() * size_of::(); + self.bytes_until_reseed -= num_bytes as i64; + self.inner.generate(results); + } +} + +impl ReseedingCore +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore, +{ + /// Create a new `ReseedingCore`. + fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self { + use ::core::i64::MAX; + fork::register_fork_handler(); + + // Because generating more values than `i64::MAX` takes centuries on + // current hardware, we just clamp to that value. + // Also we set a threshold of 0, which indicates no limit, to that + // value. + let threshold = if threshold == 0 { + MAX + } else if threshold <= MAX as u64 { + threshold as i64 + } else { + MAX + }; + + ReseedingCore { + inner: rng, + reseeder, + threshold: threshold as i64, + bytes_until_reseed: threshold as i64, + fork_counter: 0, + } + } + + /// Reseed the internal PRNG. + fn reseed(&mut self) -> Result<(), Error> { + R::from_rng(&mut self.reseeder).map(|result| { + self.bytes_until_reseed = self.threshold; + self.inner = result + }) + } + + fn is_forked(&self, global_fork_counter: usize) -> bool { + // In theory, on 32-bit platforms, it is possible for + // `global_fork_counter` to wrap around after ~4e9 forks. + // + // This check will detect a fork in the normal case where + // `fork_counter < global_fork_counter`, and also when the difference + // between both is greater than `isize::MAX` (wrapped around). + // + // It will still fail to detect a fork if there have been more than + // `isize::MAX` forks, without any reseed in between. Seems unlikely + // enough. + (self.fork_counter.wrapping_sub(global_fork_counter) as isize) < 0 + } + + #[inline(never)] + fn reseed_and_generate( + &mut self, results: &mut ::Results, global_fork_counter: usize, + ) { + #![allow(clippy::if_same_then_else)] // false positive + if self.is_forked(global_fork_counter) { + info!("Fork detected, reseeding RNG"); + } else { + trace!("Reseeding RNG (periodic reseed)"); + } + + let num_bytes = results.as_ref().len() * size_of::<::Item>(); + + if let Err(e) = self.reseed() { + warn!("Reseeding RNG failed: {}", e); + let _ = e; + } + self.fork_counter = global_fork_counter; + + self.bytes_until_reseed = self.threshold - num_bytes as i64; + self.inner.generate(results); + } +} + +impl Clone for ReseedingCore +where + R: BlockRngCore + SeedableRng + Clone, + Rsdr: RngCore + Clone, +{ + fn clone(&self) -> ReseedingCore { + ReseedingCore { + inner: self.inner.clone(), + reseeder: self.reseeder.clone(), + threshold: self.threshold, + bytes_until_reseed: 0, // reseed clone on first use + fork_counter: self.fork_counter, + } + } +} + +impl CryptoRng for ReseedingCore +where + R: BlockRngCore + SeedableRng + CryptoRng, + Rsdr: RngCore + CryptoRng, +{ +} + + +#[cfg(all(unix, not(target_os = "emscripten")))] +mod fork { + use core::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::Once; + + // Fork protection + // + // We implement fork protection on Unix using `pthread_atfork`. + // When the process is forked, we increment `RESEEDING_RNG_FORK_COUNTER`. + // Every `ReseedingRng` stores the last known value of the static in + // `fork_counter`. If the cached `fork_counter` is less than + // `RESEEDING_RNG_FORK_COUNTER`, it is time to reseed this RNG. + // + // If reseeding fails, we don't deal with this by setting a delay, but just + // don't update `fork_counter`, so a reseed is attempted as soon as + // possible. + + static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = AtomicUsize::new(0); + + pub fn get_fork_counter() -> usize { + RESEEDING_RNG_FORK_COUNTER.load(Ordering::Relaxed) + } + + extern "C" fn fork_handler() { + // Note: fetch_add is defined to wrap on overflow + // (which is what we want). + RESEEDING_RNG_FORK_COUNTER.fetch_add(1, Ordering::Relaxed); + } + + pub fn register_fork_handler() { + static REGISTER: Once = Once::new(); + REGISTER.call_once(|| unsafe { + libc::pthread_atfork(None, None, Some(fork_handler)); + }); + } +} + +#[cfg(not(all(unix, not(target_os = "emscripten"))))] +mod fork { + pub fn get_fork_counter() -> usize { + 0 + } + pub fn register_fork_handler() {} +} + + +#[cfg(feature = "std_rng")] +#[cfg(test)] +mod test { + use super::ReseedingRng; + use crate::rngs::mock::StepRng; + use crate::rngs::std::Core; + use crate::{Rng, SeedableRng}; + + #[test] + fn test_reseeding() { + let mut zero = StepRng::new(0, 0); + let rng = Core::from_rng(&mut zero).unwrap(); + let thresh = 1; // reseed every time the buffer is exhausted + let mut reseeding = ReseedingRng::new(rng, thresh, zero); + + // RNG buffer size is [u32; 64] + // Debug is only implemented up to length 32 so use two arrays + let mut buf = ([0u32; 32], [0u32; 32]); + reseeding.fill(&mut buf.0); + reseeding.fill(&mut buf.1); + let seq = buf; + for _ in 0..10 { + reseeding.fill(&mut buf.0); + reseeding.fill(&mut buf.1); + assert_eq!(buf, seq); + } + } + + #[test] + fn test_clone_reseeding() { + let mut zero = StepRng::new(0, 0); + let rng = Core::from_rng(&mut zero).unwrap(); + let mut rng1 = ReseedingRng::new(rng, 32 * 4, zero); + + let first: u32 = rng1.gen(); + for _ in 0..10 { + let _ = rng1.gen::(); + } + + let mut rng2 = rng1.clone(); + assert_eq!(first, rng2.gen::()); + } +} diff --git a/vendor/rand/src/rngs/mock.rs b/vendor/rand/src/rngs/mock.rs new file mode 100644 index 0000000000..a1745a490d --- /dev/null +++ b/vendor/rand/src/rngs/mock.rs @@ -0,0 +1,87 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Mock random number generator + +use rand_core::{impls, Error, RngCore}; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + +/// A simple implementation of `RngCore` for testing purposes. +/// +/// This generates an arithmetic sequence (i.e. adds a constant each step) +/// over a `u64` number, using wrapping arithmetic. If the increment is 0 +/// the generator yields a constant. +/// +/// ``` +/// use rand::Rng; +/// use rand::rngs::mock::StepRng; +/// +/// let mut my_rng = StepRng::new(2, 1); +/// let sample: [u64; 3] = my_rng.gen(); +/// assert_eq!(sample, [2, 3, 4]); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct StepRng { + v: u64, + a: u64, +} + +impl StepRng { + /// Create a `StepRng`, yielding an arithmetic sequence starting with + /// `initial` and incremented by `increment` each time. + pub fn new(initial: u64, increment: u64) -> Self { + StepRng { + v: initial, + a: increment, + } + } +} + +impl RngCore for StepRng { + #[inline] + fn next_u32(&mut self) -> u32 { + self.next_u64() as u32 + } + + #[inline] + fn next_u64(&mut self) -> u64 { + let result = self.v; + self.v = self.v.wrapping_add(self.a); + result + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + impls::fill_bytes_via_next(self, dest); + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde1")] + fn test_serialization_step_rng() { + use super::StepRng; + + let some_rng = StepRng::new(42, 7); + let de_some_rng: StepRng = + bincode::deserialize(&bincode::serialize(&some_rng).unwrap()).unwrap(); + assert_eq!(some_rng.v, de_some_rng.v); + assert_eq!(some_rng.a, de_some_rng.a); + + } +} diff --git a/vendor/rand/src/rngs/mod.rs b/vendor/rand/src/rngs/mod.rs new file mode 100644 index 0000000000..ac3c2c595d --- /dev/null +++ b/vendor/rand/src/rngs/mod.rs @@ -0,0 +1,119 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Random number generators and adapters +//! +//! ## Background: Random number generators (RNGs) +//! +//! Computers cannot produce random numbers from nowhere. We classify +//! random number generators as follows: +//! +//! - "True" random number generators (TRNGs) use hard-to-predict data sources +//! (e.g. the high-resolution parts of event timings and sensor jitter) to +//! harvest random bit-sequences, apply algorithms to remove bias and +//! estimate available entropy, then combine these bits into a byte-sequence +//! or an entropy pool. This job is usually done by the operating system or +//! a hardware generator (HRNG). +//! - "Pseudo"-random number generators (PRNGs) use algorithms to transform a +//! seed into a sequence of pseudo-random numbers. These generators can be +//! fast and produce well-distributed unpredictable random numbers (or not). +//! They are usually deterministic: given algorithm and seed, the output +//! sequence can be reproduced. They have finite period and eventually loop; +//! with many algorithms this period is fixed and can be proven sufficiently +//! long, while others are chaotic and the period depends on the seed. +//! - "Cryptographically secure" pseudo-random number generators (CSPRNGs) +//! are the sub-set of PRNGs which are secure. Security of the generator +//! relies both on hiding the internal state and using a strong algorithm. +//! +//! ## Traits and functionality +//! +//! All RNGs implement the [`RngCore`] trait, as a consequence of which the +//! [`Rng`] extension trait is automatically implemented. Secure RNGs may +//! additionally implement the [`CryptoRng`] trait. +//! +//! All PRNGs require a seed to produce their random number sequence. The +//! [`SeedableRng`] trait provides three ways of constructing PRNGs: +//! +//! - `from_seed` accepts a type specific to the PRNG +//! - `from_rng` allows a PRNG to be seeded from any other RNG +//! - `seed_from_u64` allows any PRNG to be seeded from a `u64` insecurely +//! - `from_entropy` securely seeds a PRNG from fresh entropy +//! +//! Use the [`rand_core`] crate when implementing your own RNGs. +//! +//! ## Our generators +//! +//! This crate provides several random number generators: +//! +//! - [`OsRng`] is an interface to the operating system's random number +//! source. Typically the operating system uses a CSPRNG with entropy +//! provided by a TRNG and some type of on-going re-seeding. +//! - [`ThreadRng`], provided by the [`thread_rng`] function, is a handle to a +//! thread-local CSPRNG with periodic seeding from [`OsRng`]. Because this +//! is local, it is typically much faster than [`OsRng`]. It should be +//! secure, though the paranoid may prefer [`OsRng`]. +//! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security +//! (based on reviews, maturity and usage). The current algorithm is ChaCha12, +//! which is well established and rigorously analysed. +//! [`StdRng`] provides the algorithm used by [`ThreadRng`] but without +//! periodic reseeding. +//! - [`SmallRng`] is an **insecure** PRNG designed to be fast, simple, require +//! little memory, and have good output quality. +//! +//! The algorithms selected for [`StdRng`] and [`SmallRng`] may change in any +//! release and may be platform-dependent, therefore they should be considered +//! **not reproducible**. +//! +//! ## Additional generators +//! +//! **TRNGs**: The [`rdrand`] crate provides an interface to the RDRAND and +//! RDSEED instructions available in modern Intel and AMD CPUs. +//! The [`rand_jitter`] crate provides a user-space implementation of +//! entropy harvesting from CPU timer jitter, but is very slow and has +//! [security issues](https://github.com/rust-random/rand/issues/699). +//! +//! **PRNGs**: Several companion crates are available, providing individual or +//! families of PRNG algorithms. These provide the implementations behind +//! [`StdRng`] and [`SmallRng`] but can also be used directly, indeed *should* +//! be used directly when **reproducibility** matters. +//! Some suggestions are: [`rand_chacha`], [`rand_pcg`], [`rand_xoshiro`]. +//! A full list can be found by searching for crates with the [`rng` tag]. +//! +//! [`Rng`]: crate::Rng +//! [`RngCore`]: crate::RngCore +//! [`CryptoRng`]: crate::CryptoRng +//! [`SeedableRng`]: crate::SeedableRng +//! [`thread_rng`]: crate::thread_rng +//! [`rdrand`]: https://crates.io/crates/rdrand +//! [`rand_jitter`]: https://crates.io/crates/rand_jitter +//! [`rand_chacha`]: https://crates.io/crates/rand_chacha +//! [`rand_pcg`]: https://crates.io/crates/rand_pcg +//! [`rand_xoshiro`]: https://crates.io/crates/rand_xoshiro +//! [`rng` tag]: https://crates.io/keywords/rng + +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg(feature = "std")] pub mod adapter; + +pub mod mock; // Public so we don't export `StepRng` directly, making it a bit + // more clear it is intended for testing. + +#[cfg(all(feature = "small_rng", target_pointer_width = "64"))] +mod xoshiro256plusplus; +#[cfg(all(feature = "small_rng", not(target_pointer_width = "64")))] +mod xoshiro128plusplus; +#[cfg(feature = "small_rng")] mod small; + +#[cfg(feature = "std_rng")] mod std; +#[cfg(all(feature = "std", feature = "std_rng"))] pub(crate) mod thread; + +#[cfg(feature = "small_rng")] pub use self::small::SmallRng; +#[cfg(feature = "std_rng")] pub use self::std::StdRng; +#[cfg(all(feature = "std", feature = "std_rng"))] pub use self::thread::ThreadRng; + +#[cfg_attr(doc_cfg, doc(cfg(feature = "getrandom")))] +#[cfg(feature = "getrandom")] pub use rand_core::OsRng; diff --git a/vendor/rand/src/rngs/small.rs b/vendor/rand/src/rngs/small.rs new file mode 100644 index 0000000000..fb0e0d119b --- /dev/null +++ b/vendor/rand/src/rngs/small.rs @@ -0,0 +1,117 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A small fast RNG + +use rand_core::{Error, RngCore, SeedableRng}; + +#[cfg(target_pointer_width = "64")] +type Rng = super::xoshiro256plusplus::Xoshiro256PlusPlus; +#[cfg(not(target_pointer_width = "64"))] +type Rng = super::xoshiro128plusplus::Xoshiro128PlusPlus; + +/// A small-state, fast non-crypto PRNG +/// +/// `SmallRng` may be a good choice when a PRNG with small state, cheap +/// initialization, good statistical quality and good performance are required. +/// Note that depending on the application, [`StdRng`] may be faster on many +/// modern platforms while providing higher-quality randomness. Furthermore, +/// `SmallRng` is **not** a good choice when: +/// - Security against prediction is important. Use [`StdRng`] instead. +/// - Seeds with many zeros are provided. In such cases, it takes `SmallRng` +/// about 10 samples to produce 0 and 1 bits with equal probability. Either +/// provide seeds with an approximately equal number of 0 and 1 (for example +/// by using [`SeedableRng::from_entropy`] or [`SeedableRng::seed_from_u64`]), +/// or use [`StdRng`] instead. +/// +/// The algorithm is deterministic but should not be considered reproducible +/// due to dependence on platform and possible replacement in future +/// library versions. For a reproducible generator, use a named PRNG from an +/// external crate, e.g. [rand_xoshiro] or [rand_chacha]. +/// Refer also to [The Book](https://rust-random.github.io/book/guide-rngs.html). +/// +/// The PRNG algorithm in `SmallRng` is chosen to be efficient on the current +/// platform, without consideration for cryptography or security. The size of +/// its state is much smaller than [`StdRng`]. The current algorithm is +/// `Xoshiro256PlusPlus` on 64-bit platforms and `Xoshiro128PlusPlus` on 32-bit +/// platforms. Both are also implemented by the [rand_xoshiro] crate. +/// +/// # Examples +/// +/// Initializing `SmallRng` with a random seed can be done using [`SeedableRng::from_entropy`]: +/// +/// ``` +/// use rand::{Rng, SeedableRng}; +/// use rand::rngs::SmallRng; +/// +/// // Create small, cheap to initialize and fast RNG with a random seed. +/// // The randomness is supplied by the operating system. +/// let mut small_rng = SmallRng::from_entropy(); +/// # let v: u32 = small_rng.gen(); +/// ``` +/// +/// When initializing a lot of `SmallRng`'s, using [`thread_rng`] can be more +/// efficient: +/// +/// ``` +/// use rand::{SeedableRng, thread_rng}; +/// use rand::rngs::SmallRng; +/// +/// // Create a big, expensive to initialize and slower, but unpredictable RNG. +/// // This is cached and done only once per thread. +/// let mut thread_rng = thread_rng(); +/// // Create small, cheap to initialize and fast RNGs with random seeds. +/// // One can generally assume this won't fail. +/// let rngs: Vec = (0..10) +/// .map(|_| SmallRng::from_rng(&mut thread_rng).unwrap()) +/// .collect(); +/// ``` +/// +/// [`StdRng`]: crate::rngs::StdRng +/// [`thread_rng`]: crate::thread_rng +/// [rand_chacha]: https://crates.io/crates/rand_chacha +/// [rand_xoshiro]: https://crates.io/crates/rand_xoshiro +#[cfg_attr(doc_cfg, doc(cfg(feature = "small_rng")))] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SmallRng(Rng); + +impl RngCore for SmallRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for SmallRng { + type Seed = ::Seed; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + SmallRng(Rng::from_seed(seed)) + } + + #[inline(always)] + fn from_rng(rng: R) -> Result { + Rng::from_rng(rng).map(SmallRng) + } +} diff --git a/vendor/rand/src/rngs/std.rs b/vendor/rand/src/rngs/std.rs new file mode 100644 index 0000000000..80f8433698 --- /dev/null +++ b/vendor/rand/src/rngs/std.rs @@ -0,0 +1,102 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The standard RNG + +use crate::{CryptoRng, Error, RngCore, SeedableRng}; + +#[cfg(all(any(test, feature = "std"), not(target_os = "emscripten")))] +pub(crate) use rand_chacha::ChaCha12Core as Core; +#[cfg(all(any(test, feature = "std"), target_os = "emscripten"))] +pub(crate) use rand_hc::Hc128Core as Core; + +#[cfg(not(target_os = "emscripten"))] use rand_chacha::ChaCha12Rng as Rng; +#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng; + +/// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient +/// on the current platform, to be statistically strong and unpredictable +/// (meaning a cryptographically secure PRNG). +/// +/// The current algorithm used is the ChaCha block cipher with 12 rounds. Please +/// see this relevant [rand issue] for the discussion. This may change as new +/// evidence of cipher security and performance becomes available. +/// +/// The algorithm is deterministic but should not be considered reproducible +/// due to dependence on configuration and possible replacement in future +/// library versions. For a secure reproducible generator, we recommend use of +/// the [rand_chacha] crate directly. +/// +/// [rand_chacha]: https://crates.io/crates/rand_chacha +/// [rand issue]: https://github.com/rust-random/rand/issues/932 +#[cfg_attr(doc_cfg, doc(cfg(feature = "std_rng")))] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct StdRng(Rng); + +impl RngCore for StdRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for StdRng { + type Seed = ::Seed; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + StdRng(Rng::from_seed(seed)) + } + + #[inline(always)] + fn from_rng(rng: R) -> Result { + Rng::from_rng(rng).map(StdRng) + } +} + +impl CryptoRng for StdRng {} + + +#[cfg(test)] +mod test { + use crate::rngs::StdRng; + use crate::{RngCore, SeedableRng}; + + #[test] + fn test_stdrng_construction() { + // Test value-stability of StdRng. This is expected to break any time + // the algorithm is changed. + #[rustfmt::skip] + let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; + + let target = [10719222850664546238, 14064965282130556830]; + + let mut rng0 = StdRng::from_seed(seed); + let x0 = rng0.next_u64(); + + let mut rng1 = StdRng::from_rng(rng0).unwrap(); + let x1 = rng1.next_u64(); + + assert_eq!([x0, x1], target); + } +} diff --git a/vendor/rand/src/rngs/thread.rs b/vendor/rand/src/rngs/thread.rs new file mode 100644 index 0000000000..552851f1ec --- /dev/null +++ b/vendor/rand/src/rngs/thread.rs @@ -0,0 +1,142 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Thread-local random number generator + +use core::cell::UnsafeCell; +use std::rc::Rc; +use std::thread_local; + +use super::std::Core; +use crate::rngs::adapter::ReseedingRng; +use crate::rngs::OsRng; +use crate::{CryptoRng, Error, RngCore, SeedableRng}; + +// Rationale for using `UnsafeCell` in `ThreadRng`: +// +// Previously we used a `RefCell`, with an overhead of ~15%. There will only +// ever be one mutable reference to the interior of the `UnsafeCell`, because +// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a +// single thread (which is the definition of `ThreadRng`), there will only ever +// be one of these methods active at a time. +// +// A possible scenario where there could be multiple mutable references is if +// `ThreadRng` is used inside `next_u32` and co. But the implementation is +// completely under our control. We just have to ensure none of them use +// `ThreadRng` internally, which is nonsensical anyway. We should also never run +// `ThreadRng` in destructors of its implementation, which is also nonsensical. + + +// Number of generated bytes after which to reseed `ThreadRng`. +// According to benchmarks, reseeding has a noticable impact with thresholds +// of 32 kB and less. We choose 64 kB to avoid significant overhead. +const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64; + +/// A reference to the thread-local generator +/// +/// An instance can be obtained via [`thread_rng`] or via `ThreadRng::default()`. +/// This handle is safe to use everywhere (including thread-local destructors) +/// but cannot be passed between threads (is not `Send` or `Sync`). +/// +/// `ThreadRng` uses the same PRNG as [`StdRng`] for security and performance +/// and is automatically seeded from [`OsRng`]. +/// +/// Unlike `StdRng`, `ThreadRng` uses the [`ReseedingRng`] wrapper to reseed +/// the PRNG from fresh entropy every 64 kiB of random data as well as after a +/// fork on Unix (though not quite immediately; see documentation of +/// [`ReseedingRng`]). +/// Note that the reseeding is done as an extra precaution against side-channel +/// attacks and mis-use (e.g. if somehow weak entropy were supplied initially). +/// The PRNG algorithms used are assumed to be secure. +/// +/// [`ReseedingRng`]: crate::rngs::adapter::ReseedingRng +/// [`StdRng`]: crate::rngs::StdRng +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))] +#[derive(Clone, Debug)] +pub struct ThreadRng { + // Rc is explictly !Send and !Sync + rng: Rc>>, +} + +thread_local!( + // We require Rc<..> to avoid premature freeing when thread_rng is used + // within thread-local destructors. See #968. + static THREAD_RNG_KEY: Rc>> = { + let r = Core::from_rng(OsRng).unwrap_or_else(|err| + panic!("could not initialize thread_rng: {}", err)); + let rng = ReseedingRng::new(r, + THREAD_RNG_RESEED_THRESHOLD, + OsRng); + Rc::new(UnsafeCell::new(rng)) + } +); + +/// Retrieve the lazily-initialized thread-local random number generator, +/// seeded by the system. Intended to be used in method chaining style, +/// e.g. `thread_rng().gen::()`, or cached locally, e.g. +/// `let mut rng = thread_rng();`. Invoked by the `Default` trait, making +/// `ThreadRng::default()` equivalent. +/// +/// For more information see [`ThreadRng`]. +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))] +pub fn thread_rng() -> ThreadRng { + let rng = THREAD_RNG_KEY.with(|t| t.clone()); + ThreadRng { rng } +} + +impl Default for ThreadRng { + fn default() -> ThreadRng { + crate::prelude::thread_rng() + } +} + +impl RngCore for ThreadRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.fill_bytes(dest) + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + // SAFETY: We must make sure to stop using `rng` before anyone else + // creates another mutable reference + let rng = unsafe { &mut *self.rng.get() }; + rng.try_fill_bytes(dest) + } +} + +impl CryptoRng for ThreadRng {} + + +#[cfg(test)] +mod test { + #[test] + fn test_thread_rng() { + use crate::Rng; + let mut r = crate::thread_rng(); + r.gen::(); + assert_eq!(r.gen_range(0..1), 0); + } +} diff --git a/vendor/rand/src/rngs/xoshiro128plusplus.rs b/vendor/rand/src/rngs/xoshiro128plusplus.rs new file mode 100644 index 0000000000..ece98fafd6 --- /dev/null +++ b/vendor/rand/src/rngs/xoshiro128plusplus.rs @@ -0,0 +1,118 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[cfg(feature="serde1")] use serde::{Serialize, Deserialize}; +use rand_core::impls::{next_u64_via_u32, fill_bytes_via_next}; +use rand_core::le::read_u32_into; +use rand_core::{SeedableRng, RngCore, Error}; + +/// A xoshiro128++ random number generator. +/// +/// The xoshiro128++ algorithm is not suitable for cryptographic purposes, but +/// is very fast and has excellent statistical properties. +/// +/// The algorithm used here is translated from [the `xoshiro128plusplus.c` +/// reference source code](http://xoshiro.di.unimi.it/xoshiro128plusplus.c) by +/// David Blackman and Sebastiano Vigna. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] +pub struct Xoshiro128PlusPlus { + s: [u32; 4], +} + +impl SeedableRng for Xoshiro128PlusPlus { + type Seed = [u8; 16]; + + /// Create a new `Xoshiro128PlusPlus`. If `seed` is entirely 0, it will be + /// mapped to a different seed. + #[inline] + fn from_seed(seed: [u8; 16]) -> Xoshiro128PlusPlus { + if seed.iter().all(|&x| x == 0) { + return Self::seed_from_u64(0); + } + let mut state = [0; 4]; + read_u32_into(&seed, &mut state); + Xoshiro128PlusPlus { s: state } + } + + /// Create a new `Xoshiro128PlusPlus` from a `u64` seed. + /// + /// This uses the SplitMix64 generator internally. + fn seed_from_u64(mut state: u64) -> Self { + const PHI: u64 = 0x9e3779b97f4a7c15; + let mut seed = Self::Seed::default(); + for chunk in seed.as_mut().chunks_mut(8) { + state = state.wrapping_add(PHI); + let mut z = state; + z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9); + z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb); + z = z ^ (z >> 31); + chunk.copy_from_slice(&z.to_le_bytes()); + } + Self::from_seed(seed) + } +} + +impl RngCore for Xoshiro128PlusPlus { + #[inline] + fn next_u32(&mut self) -> u32 { + let result_starstar = self.s[0] + .wrapping_add(self.s[3]) + .rotate_left(7) + .wrapping_add(self.s[0]); + + let t = self.s[1] << 9; + + self.s[2] ^= self.s[0]; + self.s[3] ^= self.s[1]; + self.s[1] ^= self.s[2]; + self.s[0] ^= self.s[3]; + + self.s[2] ^= t; + + self.s[3] = self.s[3].rotate_left(11); + + result_starstar + } + + #[inline] + fn next_u64(&mut self) -> u64 { + next_u64_via_u32(self) + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + fill_bytes_via_next(self, dest); + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn reference() { + let mut rng = Xoshiro128PlusPlus::from_seed( + [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]); + // These values were produced with the reference implementation: + // http://xoshiro.di.unimi.it/xoshiro128plusplus.c + let expected = [ + 641, 1573767, 3222811527, 3517856514, 836907274, 4247214768, + 3867114732, 1355841295, 495546011, 621204420, + ]; + for &e in &expected { + assert_eq!(rng.next_u32(), e); + } + } +} diff --git a/vendor/rand/src/rngs/xoshiro256plusplus.rs b/vendor/rand/src/rngs/xoshiro256plusplus.rs new file mode 100644 index 0000000000..cd373c3066 --- /dev/null +++ b/vendor/rand/src/rngs/xoshiro256plusplus.rs @@ -0,0 +1,122 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[cfg(feature="serde1")] use serde::{Serialize, Deserialize}; +use rand_core::impls::fill_bytes_via_next; +use rand_core::le::read_u64_into; +use rand_core::{SeedableRng, RngCore, Error}; + +/// A xoshiro256** random number generator. +/// +/// The xoshiro256** algorithm is not suitable for cryptographic purposes, but +/// is very fast and has excellent statistical properties. +/// +/// The algorithm used here is translated from [the `xoshiro256plusplus.c` +/// reference source code](http://xoshiro.di.unimi.it/xoshiro256plusplus.c) by +/// David Blackman and Sebastiano Vigna. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] +pub struct Xoshiro256PlusPlus { + s: [u64; 4], +} + +impl SeedableRng for Xoshiro256PlusPlus { + type Seed = [u8; 32]; + + /// Create a new `Xoshiro256PlusPlus`. If `seed` is entirely 0, it will be + /// mapped to a different seed. + #[inline] + fn from_seed(seed: [u8; 32]) -> Xoshiro256PlusPlus { + if seed.iter().all(|&x| x == 0) { + return Self::seed_from_u64(0); + } + let mut state = [0; 4]; + read_u64_into(&seed, &mut state); + Xoshiro256PlusPlus { s: state } + } + + /// Create a new `Xoshiro256PlusPlus` from a `u64` seed. + /// + /// This uses the SplitMix64 generator internally. + fn seed_from_u64(mut state: u64) -> Self { + const PHI: u64 = 0x9e3779b97f4a7c15; + let mut seed = Self::Seed::default(); + for chunk in seed.as_mut().chunks_mut(8) { + state = state.wrapping_add(PHI); + let mut z = state; + z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9); + z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb); + z = z ^ (z >> 31); + chunk.copy_from_slice(&z.to_le_bytes()); + } + Self::from_seed(seed) + } +} + +impl RngCore for Xoshiro256PlusPlus { + #[inline] + fn next_u32(&mut self) -> u32 { + // The lowest bits have some linear dependencies, so we use the + // upper bits instead. + (self.next_u64() >> 32) as u32 + } + + #[inline] + fn next_u64(&mut self) -> u64 { + let result_plusplus = self.s[0] + .wrapping_add(self.s[3]) + .rotate_left(23) + .wrapping_add(self.s[0]); + + let t = self.s[1] << 17; + + self.s[2] ^= self.s[0]; + self.s[3] ^= self.s[1]; + self.s[1] ^= self.s[2]; + self.s[0] ^= self.s[3]; + + self.s[2] ^= t; + + self.s[3] = self.s[3].rotate_left(45); + + result_plusplus + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + fill_bytes_via_next(self, dest); + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn reference() { + let mut rng = Xoshiro256PlusPlus::from_seed( + [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0]); + // These values were produced with the reference implementation: + // http://xoshiro.di.unimi.it/xoshiro256plusplus.c + let expected = [ + 41943041, 58720359, 3588806011781223, 3591011842654386, + 9228616714210784205, 9973669472204895162, 14011001112246962877, + 12406186145184390807, 15849039046786891736, 10450023813501588000, + ]; + for &e in &expected { + assert_eq!(rng.next_u64(), e); + } + } +} diff --git a/vendor/rand/src/seq/index.rs b/vendor/rand/src/seq/index.rs new file mode 100644 index 0000000000..8b155e1f1e --- /dev/null +++ b/vendor/rand/src/seq/index.rs @@ -0,0 +1,678 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Low-level API for sampling indices + +#[cfg(feature = "alloc")] use core::slice; + +#[cfg(feature = "alloc")] use alloc::vec::{self, Vec}; +// BTreeMap is not as fast in tests, but better than nothing. +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::collections::BTreeSet; +#[cfg(feature = "std")] use std::collections::HashSet; + +#[cfg(feature = "alloc")] +use crate::distributions::{uniform::SampleUniform, Distribution, Uniform}; +#[cfg(feature = "std")] +use crate::distributions::WeightedError; +use crate::Rng; + +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + +/// A vector of indices. +/// +/// Multiple internal representations are possible. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub enum IndexVec { + #[doc(hidden)] + U32(Vec), + #[doc(hidden)] + USize(Vec), +} + +impl IndexVec { + /// Returns the number of indices + #[inline] + pub fn len(&self) -> usize { + match *self { + IndexVec::U32(ref v) => v.len(), + IndexVec::USize(ref v) => v.len(), + } + } + + /// Returns `true` if the length is 0. + #[inline] + pub fn is_empty(&self) -> bool { + match *self { + IndexVec::U32(ref v) => v.is_empty(), + IndexVec::USize(ref v) => v.is_empty(), + } + } + + /// Return the value at the given `index`. + /// + /// (Note: we cannot implement [`std::ops::Index`] because of lifetime + /// restrictions.) + #[inline] + pub fn index(&self, index: usize) -> usize { + match *self { + IndexVec::U32(ref v) => v[index] as usize, + IndexVec::USize(ref v) => v[index], + } + } + + /// Return result as a `Vec`. Conversion may or may not be trivial. + #[inline] + pub fn into_vec(self) -> Vec { + match self { + IndexVec::U32(v) => v.into_iter().map(|i| i as usize).collect(), + IndexVec::USize(v) => v, + } + } + + /// Iterate over the indices as a sequence of `usize` values + #[inline] + pub fn iter(&self) -> IndexVecIter<'_> { + match *self { + IndexVec::U32(ref v) => IndexVecIter::U32(v.iter()), + IndexVec::USize(ref v) => IndexVecIter::USize(v.iter()), + } + } +} + +impl IntoIterator for IndexVec { + type Item = usize; + type IntoIter = IndexVecIntoIter; + + /// Convert into an iterator over the indices as a sequence of `usize` values + #[inline] + fn into_iter(self) -> IndexVecIntoIter { + match self { + IndexVec::U32(v) => IndexVecIntoIter::U32(v.into_iter()), + IndexVec::USize(v) => IndexVecIntoIter::USize(v.into_iter()), + } + } +} + +impl PartialEq for IndexVec { + fn eq(&self, other: &IndexVec) -> bool { + use self::IndexVec::*; + match (self, other) { + (&U32(ref v1), &U32(ref v2)) => v1 == v2, + (&USize(ref v1), &USize(ref v2)) => v1 == v2, + (&U32(ref v1), &USize(ref v2)) => { + (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x as usize == *y)) + } + (&USize(ref v1), &U32(ref v2)) => { + (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x == *y as usize)) + } + } + } +} + +impl From> for IndexVec { + #[inline] + fn from(v: Vec) -> Self { + IndexVec::U32(v) + } +} + +impl From> for IndexVec { + #[inline] + fn from(v: Vec) -> Self { + IndexVec::USize(v) + } +} + +/// Return type of `IndexVec::iter`. +#[derive(Debug)] +pub enum IndexVecIter<'a> { + #[doc(hidden)] + U32(slice::Iter<'a, u32>), + #[doc(hidden)] + USize(slice::Iter<'a, usize>), +} + +impl<'a> Iterator for IndexVecIter<'a> { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + use self::IndexVecIter::*; + match *self { + U32(ref mut iter) => iter.next().map(|i| *i as usize), + USize(ref mut iter) => iter.next().cloned(), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + match *self { + IndexVecIter::U32(ref v) => v.size_hint(), + IndexVecIter::USize(ref v) => v.size_hint(), + } + } +} + +impl<'a> ExactSizeIterator for IndexVecIter<'a> {} + +/// Return type of `IndexVec::into_iter`. +#[derive(Clone, Debug)] +pub enum IndexVecIntoIter { + #[doc(hidden)] + U32(vec::IntoIter), + #[doc(hidden)] + USize(vec::IntoIter), +} + +impl Iterator for IndexVecIntoIter { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + use self::IndexVecIntoIter::*; + match *self { + U32(ref mut v) => v.next().map(|i| i as usize), + USize(ref mut v) => v.next(), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + use self::IndexVecIntoIter::*; + match *self { + U32(ref v) => v.size_hint(), + USize(ref v) => v.size_hint(), + } + } +} + +impl ExactSizeIterator for IndexVecIntoIter {} + + +/// Randomly sample exactly `amount` distinct indices from `0..length`, and +/// return them in random order (fully shuffled). +/// +/// This method is used internally by the slice sampling methods, but it can +/// sometimes be useful to have the indices themselves so this is provided as +/// an alternative. +/// +/// The implementation used is not specified; we automatically select the +/// fastest available algorithm for the `length` and `amount` parameters +/// (based on detailed profiling on an Intel Haswell CPU). Roughly speaking, +/// complexity is `O(amount)`, except that when `amount` is small, performance +/// is closer to `O(amount^2)`, and when `length` is close to `amount` then +/// `O(length)`. +/// +/// Note that performance is significantly better over `u32` indices than over +/// `u64` indices. Because of this we hide the underlying type behind an +/// abstraction, `IndexVec`. +/// +/// If an allocation-free `no_std` function is required, it is suggested +/// to adapt the internal `sample_floyd` implementation. +/// +/// Panics if `amount > length`. +pub fn sample(rng: &mut R, length: usize, amount: usize) -> IndexVec +where R: Rng + ?Sized { + if amount > length { + panic!("`amount` of samples must be less than or equal to `length`"); + } + if length > (::core::u32::MAX as usize) { + // We never want to use inplace here, but could use floyd's alg + // Lazy version: always use the cache alg. + return sample_rejection(rng, length, amount); + } + let amount = amount as u32; + let length = length as u32; + + // Choice of algorithm here depends on both length and amount. See: + // https://github.com/rust-random/rand/pull/479 + // We do some calculations with f32. Accuracy is not very important. + + if amount < 163 { + const C: [[f32; 2]; 2] = [[1.6, 8.0 / 45.0], [10.0, 70.0 / 9.0]]; + let j = if length < 500_000 { 0 } else { 1 }; + let amount_fp = amount as f32; + let m4 = C[0][j] * amount_fp; + // Short-cut: when amount < 12, floyd's is always faster + if amount > 11 && (length as f32) < (C[1][j] + m4) * amount_fp { + sample_inplace(rng, length, amount) + } else { + sample_floyd(rng, length, amount) + } + } else { + const C: [f32; 2] = [270.0, 330.0 / 9.0]; + let j = if length < 500_000 { 0 } else { 1 }; + if (length as f32) < C[j] * (amount as f32) { + sample_inplace(rng, length, amount) + } else { + sample_rejection(rng, length, amount) + } + } +} + +/// Randomly sample exactly `amount` distinct indices from `0..length`, and +/// return them in an arbitrary order (there is no guarantee of shuffling or +/// ordering). The weights are to be provided by the input function `weights`, +/// which will be called once for each index. +/// +/// This method is used internally by the slice sampling methods, but it can +/// sometimes be useful to have the indices themselves so this is provided as +/// an alternative. +/// +/// This implementation uses `O(length + amount)` space and `O(length)` time +/// if the "nightly" feature is enabled, or `O(length)` space and +/// `O(length + amount * log length)` time otherwise. +/// +/// Panics if `amount > length`. +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +pub fn sample_weighted( + rng: &mut R, length: usize, weight: F, amount: usize, +) -> Result +where + R: Rng + ?Sized, + F: Fn(usize) -> X, + X: Into, +{ + if length > (core::u32::MAX as usize) { + sample_efraimidis_spirakis(rng, length, weight, amount) + } else { + assert!(amount <= core::u32::MAX as usize); + let amount = amount as u32; + let length = length as u32; + sample_efraimidis_spirakis(rng, length, weight, amount) + } +} + + +/// Randomly sample exactly `amount` distinct indices from `0..length`, and +/// return them in an arbitrary order (there is no guarantee of shuffling or +/// ordering). The weights are to be provided by the input function `weights`, +/// which will be called once for each index. +/// +/// This implementation uses the algorithm described by Efraimidis and Spirakis +/// in this paper: https://doi.org/10.1016/j.ipl.2005.11.003 +/// It uses `O(length + amount)` space and `O(length)` time if the +/// "nightly" feature is enabled, or `O(length)` space and `O(length +/// + amount * log length)` time otherwise. +/// +/// Panics if `amount > length`. +#[cfg(feature = "std")] +fn sample_efraimidis_spirakis( + rng: &mut R, length: N, weight: F, amount: N, +) -> Result +where + R: Rng + ?Sized, + F: Fn(usize) -> X, + X: Into, + N: UInt, + IndexVec: From>, +{ + if amount == N::zero() { + return Ok(IndexVec::U32(Vec::new())); + } + + if amount > length { + panic!("`amount` of samples must be less than or equal to `length`"); + } + + struct Element { + index: N, + key: f64, + } + impl PartialOrd for Element { + fn partial_cmp(&self, other: &Self) -> Option { + self.key.partial_cmp(&other.key) + } + } + impl Ord for Element { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + // partial_cmp will always produce a value, + // because we check that the weights are not nan + self.partial_cmp(other).unwrap() + } + } + impl PartialEq for Element { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } + } + impl Eq for Element {} + + #[cfg(feature = "nightly")] + { + let mut candidates = Vec::with_capacity(length.as_usize()); + let mut index = N::zero(); + while index < length { + let weight = weight(index.as_usize()).into(); + if !(weight >= 0.) { + return Err(WeightedError::InvalidWeight); + } + + let key = rng.gen::().powf(1.0 / weight); + candidates.push(Element { index, key }); + + index += N::one(); + } + + // Partially sort the array to find the `amount` elements with the greatest + // keys. Do this by using `select_nth_unstable` to put the elements with + // the *smallest* keys at the beginning of the list in `O(n)` time, which + // provides equivalent information about the elements with the *greatest* keys. + let (_, mid, greater) + = candidates.select_nth_unstable(length.as_usize() - amount.as_usize()); + + let mut result: Vec = Vec::with_capacity(amount.as_usize()); + result.push(mid.index); + for element in greater { + result.push(element.index); + } + Ok(IndexVec::from(result)) + } + + #[cfg(not(feature = "nightly"))] + { + use std::collections::BinaryHeap; + + // Partially sort the array such that the `amount` elements with the largest + // keys are first using a binary max heap. + let mut candidates = BinaryHeap::with_capacity(length.as_usize()); + let mut index = N::zero(); + while index < length { + let weight = weight(index.as_usize()).into(); + if !(weight >= 0.) { + return Err(WeightedError::InvalidWeight); + } + + let key = rng.gen::().powf(1.0 / weight); + candidates.push(Element { index, key }); + + index += N::one(); + } + + let mut result: Vec = Vec::with_capacity(amount.as_usize()); + while result.len() < amount.as_usize() { + result.push(candidates.pop().unwrap().index); + } + Ok(IndexVec::from(result)) + } +} + +/// Randomly sample exactly `amount` indices from `0..length`, using Floyd's +/// combination algorithm. +/// +/// The output values are fully shuffled. (Overhead is under 50%.) +/// +/// This implementation uses `O(amount)` memory and `O(amount^2)` time. +fn sample_floyd(rng: &mut R, length: u32, amount: u32) -> IndexVec +where R: Rng + ?Sized { + // For small amount we use Floyd's fully-shuffled variant. For larger + // amounts this is slow due to Vec::insert performance, so we shuffle + // afterwards. Benchmarks show little overhead from extra logic. + let floyd_shuffle = amount < 50; + + debug_assert!(amount <= length); + let mut indices = Vec::with_capacity(amount as usize); + for j in length - amount..length { + let t = rng.gen_range(0..=j); + if floyd_shuffle { + if let Some(pos) = indices.iter().position(|&x| x == t) { + indices.insert(pos, j); + continue; + } + } else if indices.contains(&t) { + indices.push(j); + continue; + } + indices.push(t); + } + if !floyd_shuffle { + // Reimplement SliceRandom::shuffle with smaller indices + for i in (1..amount).rev() { + // invariant: elements with index > i have been locked in place. + indices.swap(i as usize, rng.gen_range(0..=i) as usize); + } + } + IndexVec::from(indices) +} + +/// Randomly sample exactly `amount` indices from `0..length`, using an inplace +/// partial Fisher-Yates method. +/// Sample an amount of indices using an inplace partial fisher yates method. +/// +/// This allocates the entire `length` of indices and randomizes only the first `amount`. +/// It then truncates to `amount` and returns. +/// +/// This method is not appropriate for large `length` and potentially uses a lot +/// of memory; because of this we only implement for `u32` index (which improves +/// performance in all cases). +/// +/// Set-up is `O(length)` time and memory and shuffling is `O(amount)` time. +fn sample_inplace(rng: &mut R, length: u32, amount: u32) -> IndexVec +where R: Rng + ?Sized { + debug_assert!(amount <= length); + let mut indices: Vec = Vec::with_capacity(length as usize); + indices.extend(0..length); + for i in 0..amount { + let j: u32 = rng.gen_range(i..length); + indices.swap(i as usize, j as usize); + } + indices.truncate(amount as usize); + debug_assert_eq!(indices.len(), amount as usize); + IndexVec::from(indices) +} + +trait UInt: Copy + PartialOrd + Ord + PartialEq + Eq + SampleUniform + + core::hash::Hash + core::ops::AddAssign { + fn zero() -> Self; + fn one() -> Self; + fn as_usize(self) -> usize; +} +impl UInt for u32 { + #[inline] + fn zero() -> Self { + 0 + } + + #[inline] + fn one() -> Self { + 1 + } + + #[inline] + fn as_usize(self) -> usize { + self as usize + } +} +impl UInt for usize { + #[inline] + fn zero() -> Self { + 0 + } + + #[inline] + fn one() -> Self { + 1 + } + + #[inline] + fn as_usize(self) -> usize { + self + } +} + +/// Randomly sample exactly `amount` indices from `0..length`, using rejection +/// sampling. +/// +/// Since `amount <<< length` there is a low chance of a random sample in +/// `0..length` being a duplicate. We test for duplicates and resample where +/// necessary. The algorithm is `O(amount)` time and memory. +/// +/// This function is generic over X primarily so that results are value-stable +/// over 32-bit and 64-bit platforms. +fn sample_rejection(rng: &mut R, length: X, amount: X) -> IndexVec +where + R: Rng + ?Sized, + IndexVec: From>, +{ + debug_assert!(amount < length); + #[cfg(feature = "std")] + let mut cache = HashSet::with_capacity(amount.as_usize()); + #[cfg(not(feature = "std"))] + let mut cache = BTreeSet::new(); + let distr = Uniform::new(X::zero(), length); + let mut indices = Vec::with_capacity(amount.as_usize()); + for _ in 0..amount.as_usize() { + let mut pos = distr.sample(rng); + while !cache.insert(pos) { + pos = distr.sample(rng); + } + indices.push(pos); + } + + debug_assert_eq!(indices.len(), amount.as_usize()); + IndexVec::from(indices) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "serde1")] + fn test_serialization_index_vec() { + let some_index_vec = IndexVec::from(vec![254_usize, 234, 2, 1]); + let de_some_index_vec: IndexVec = bincode::deserialize(&bincode::serialize(&some_index_vec).unwrap()).unwrap(); + match (some_index_vec, de_some_index_vec) { + (IndexVec::U32(a), IndexVec::U32(b)) => { + assert_eq!(a, b); + }, + (IndexVec::USize(a), IndexVec::USize(b)) => { + assert_eq!(a, b); + }, + _ => {panic!("failed to seralize/deserialize `IndexVec`")} + } + } + + #[cfg(feature = "alloc")] use alloc::vec; + + #[test] + fn test_sample_boundaries() { + let mut r = crate::test::rng(404); + + assert_eq!(sample_inplace(&mut r, 0, 0).len(), 0); + assert_eq!(sample_inplace(&mut r, 1, 0).len(), 0); + assert_eq!(sample_inplace(&mut r, 1, 1).into_vec(), vec![0]); + + assert_eq!(sample_rejection(&mut r, 1u32, 0).len(), 0); + + assert_eq!(sample_floyd(&mut r, 0, 0).len(), 0); + assert_eq!(sample_floyd(&mut r, 1, 0).len(), 0); + assert_eq!(sample_floyd(&mut r, 1, 1).into_vec(), vec![0]); + + // These algorithms should be fast with big numbers. Test average. + let sum: usize = sample_rejection(&mut r, 1 << 25, 10u32).into_iter().sum(); + assert!(1 << 25 < sum && sum < (1 << 25) * 25); + + let sum: usize = sample_floyd(&mut r, 1 << 25, 10).into_iter().sum(); + assert!(1 << 25 < sum && sum < (1 << 25) * 25); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_sample_alg() { + let seed_rng = crate::test::rng; + + // We can't test which algorithm is used directly, but Floyd's alg + // should produce different results from the others. (Also, `inplace` + // and `cached` currently use different sizes thus produce different results.) + + // A small length and relatively large amount should use inplace + let (length, amount): (usize, usize) = (100, 50); + let v1 = sample(&mut seed_rng(420), length, amount); + let v2 = sample_inplace(&mut seed_rng(420), length as u32, amount as u32); + assert!(v1.iter().all(|e| e < length)); + assert_eq!(v1, v2); + + // Test Floyd's alg does produce different results + let v3 = sample_floyd(&mut seed_rng(420), length as u32, amount as u32); + assert!(v1 != v3); + + // A large length and small amount should use Floyd + let (length, amount): (usize, usize) = (1 << 20, 50); + let v1 = sample(&mut seed_rng(421), length, amount); + let v2 = sample_floyd(&mut seed_rng(421), length as u32, amount as u32); + assert!(v1.iter().all(|e| e < length)); + assert_eq!(v1, v2); + + // A large length and larger amount should use cache + let (length, amount): (usize, usize) = (1 << 20, 600); + let v1 = sample(&mut seed_rng(422), length, amount); + let v2 = sample_rejection(&mut seed_rng(422), length as u32, amount as u32); + assert!(v1.iter().all(|e| e < length)); + assert_eq!(v1, v2); + } + + #[cfg(feature = "std")] + #[test] + fn test_sample_weighted() { + let seed_rng = crate::test::rng; + for &(amount, len) in &[(0, 10), (5, 10), (10, 10)] { + let v = sample_weighted(&mut seed_rng(423), len, |i| i as f64, amount).unwrap(); + match v { + IndexVec::U32(mut indices) => { + assert_eq!(indices.len(), amount); + indices.sort(); + indices.dedup(); + assert_eq!(indices.len(), amount); + for &i in &indices { + assert!((i as usize) < len); + } + }, + IndexVec::USize(_) => panic!("expected `IndexVec::U32`"), + } + } + } + + #[test] + fn value_stability_sample() { + let do_test = |length, amount, values: &[u32]| { + let mut buf = [0u32; 8]; + let mut rng = crate::test::rng(410); + + let res = sample(&mut rng, length, amount); + let len = res.len().min(buf.len()); + for (x, y) in res.into_iter().zip(buf.iter_mut()) { + *y = x as u32; + } + assert_eq!( + &buf[0..len], + values, + "failed sampling {}, {}", + length, + amount + ); + }; + + do_test(10, 6, &[8, 0, 3, 5, 9, 6]); // floyd + do_test(25, 10, &[18, 15, 14, 9, 0, 13, 5, 24]); // floyd + do_test(300, 8, &[30, 283, 150, 1, 73, 13, 285, 35]); // floyd + do_test(300, 80, &[31, 289, 248, 154, 5, 78, 19, 286]); // inplace + do_test(300, 180, &[31, 289, 248, 154, 5, 78, 19, 286]); // inplace + + do_test(1000_000, 8, &[ + 103717, 963485, 826422, 509101, 736394, 807035, 5327, 632573, + ]); // floyd + do_test(1000_000, 180, &[ + 103718, 963490, 826426, 509103, 736396, 807036, 5327, 632573, + ]); // rejection + } +} diff --git a/vendor/rand/src/seq/mod.rs b/vendor/rand/src/seq/mod.rs new file mode 100644 index 0000000000..4375fa1ccc --- /dev/null +++ b/vendor/rand/src/seq/mod.rs @@ -0,0 +1,1359 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Sequence-related functionality +//! +//! This module provides: +//! +//! * [`SliceRandom`] slice sampling and mutation +//! * [`IteratorRandom`] iterator sampling +//! * [`index::sample`] low-level API to choose multiple indices from +//! `0..length` +//! +//! Also see: +//! +//! * [`crate::distributions::WeightedIndex`] distribution which provides +//! weighted index sampling. +//! +//! In order to make results reproducible across 32-64 bit architectures, all +//! `usize` indices are sampled as a `u32` where possible (also providing a +//! small performance boost in some cases). + + +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +pub mod index; + +#[cfg(feature = "alloc")] use core::ops::Index; + +#[cfg(feature = "alloc")] use alloc::vec::Vec; + +#[cfg(feature = "alloc")] +use crate::distributions::uniform::{SampleBorrow, SampleUniform}; +#[cfg(feature = "alloc")] use crate::distributions::WeightedError; +use crate::Rng; + +/// Extension trait on slices, providing random mutation and sampling methods. +/// +/// This trait is implemented on all `[T]` slice types, providing several +/// methods for choosing and shuffling elements. You must `use` this trait: +/// +/// ``` +/// use rand::seq::SliceRandom; +/// +/// let mut rng = rand::thread_rng(); +/// let mut bytes = "Hello, random!".to_string().into_bytes(); +/// bytes.shuffle(&mut rng); +/// let str = String::from_utf8(bytes).unwrap(); +/// println!("{}", str); +/// ``` +/// Example output (non-deterministic): +/// ```none +/// l,nmroHado !le +/// ``` +pub trait SliceRandom { + /// The element type. + type Item; + + /// Returns a reference to one random element of the slice, or `None` if the + /// slice is empty. + /// + /// For slices, complexity is `O(1)`. + /// + /// # Example + /// + /// ``` + /// use rand::thread_rng; + /// use rand::seq::SliceRandom; + /// + /// let choices = [1, 2, 4, 8, 16, 32]; + /// let mut rng = thread_rng(); + /// println!("{:?}", choices.choose(&mut rng)); + /// assert_eq!(choices[..0].choose(&mut rng), None); + /// ``` + fn choose(&self, rng: &mut R) -> Option<&Self::Item> + where R: Rng + ?Sized; + + /// Returns a mutable reference to one random element of the slice, or + /// `None` if the slice is empty. + /// + /// For slices, complexity is `O(1)`. + fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Item> + where R: Rng + ?Sized; + + /// Chooses `amount` elements from the slice at random, without repetition, + /// and in random order. The returned iterator is appropriate both for + /// collection into a `Vec` and filling an existing buffer (see example). + /// + /// In case this API is not sufficiently flexible, use [`index::sample`]. + /// + /// For slices, complexity is the same as [`index::sample`]. + /// + /// # Example + /// ``` + /// use rand::seq::SliceRandom; + /// + /// let mut rng = &mut rand::thread_rng(); + /// let sample = "Hello, audience!".as_bytes(); + /// + /// // collect the results into a vector: + /// let v: Vec = sample.choose_multiple(&mut rng, 3).cloned().collect(); + /// + /// // store in a buffer: + /// let mut buf = [0u8; 5]; + /// for (b, slot) in sample.choose_multiple(&mut rng, buf.len()).zip(buf.iter_mut()) { + /// *slot = *b; + /// } + /// ``` + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + fn choose_multiple(&self, rng: &mut R, amount: usize) -> SliceChooseIter + where R: Rng + ?Sized; + + /// Similar to [`choose`], but where the likelihood of each outcome may be + /// specified. + /// + /// The specified function `weight` maps each item `x` to a relative + /// likelihood `weight(x)`. The probability of each item being selected is + /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. + /// + /// For slices of length `n`, complexity is `O(n)`. + /// See also [`choose_weighted_mut`], [`distributions::weighted`]. + /// + /// # Example + /// + /// ``` + /// use rand::prelude::*; + /// + /// let choices = [('a', 2), ('b', 1), ('c', 1)]; + /// let mut rng = thread_rng(); + /// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c' + /// println!("{:?}", choices.choose_weighted(&mut rng, |item| item.1).unwrap().0); + /// ``` + /// [`choose`]: SliceRandom::choose + /// [`choose_weighted_mut`]: SliceRandom::choose_weighted_mut + /// [`distributions::weighted`]: crate::distributions::weighted + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + fn choose_weighted( + &self, rng: &mut R, weight: F, + ) -> Result<&Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default; + + /// Similar to [`choose_mut`], but where the likelihood of each outcome may + /// be specified. + /// + /// The specified function `weight` maps each item `x` to a relative + /// likelihood `weight(x)`. The probability of each item being selected is + /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. + /// + /// For slices of length `n`, complexity is `O(n)`. + /// See also [`choose_weighted`], [`distributions::weighted`]. + /// + /// [`choose_mut`]: SliceRandom::choose_mut + /// [`choose_weighted`]: SliceRandom::choose_weighted + /// [`distributions::weighted`]: crate::distributions::weighted + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + fn choose_weighted_mut( + &mut self, rng: &mut R, weight: F, + ) -> Result<&mut Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default; + + /// Similar to [`choose_multiple`], but where the likelihood of each element's + /// inclusion in the output may be specified. The elements are returned in an + /// arbitrary, unspecified order. + /// + /// The specified function `weight` maps each item `x` to a relative + /// likelihood `weight(x)`. The probability of each item being selected is + /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. + /// + /// If all of the weights are equal, even if they are all zero, each element has + /// an equal likelihood of being selected. + /// + /// The complexity of this method depends on the feature `partition_at_index`. + /// If the feature is enabled, then for slices of length `n`, the complexity + /// is `O(n)` space and `O(n)` time. Otherwise, the complexity is `O(n)` space and + /// `O(n * log amount)` time. + /// + /// # Example + /// + /// ``` + /// use rand::prelude::*; + /// + /// let choices = [('a', 2), ('b', 1), ('c', 1)]; + /// let mut rng = thread_rng(); + /// // First Draw * Second Draw = total odds + /// // ----------------------- + /// // (50% * 50%) + (25% * 67%) = 41.7% chance that the output is `['a', 'b']` in some order. + /// // (50% * 50%) + (25% * 67%) = 41.7% chance that the output is `['a', 'c']` in some order. + /// // (25% * 33%) + (25% * 33%) = 16.6% chance that the output is `['b', 'c']` in some order. + /// println!("{:?}", choices.choose_multiple_weighted(&mut rng, 2, |item| item.1).unwrap().collect::>()); + /// ``` + /// [`choose_multiple`]: SliceRandom::choose_multiple + // + // Note: this is feature-gated on std due to usage of f64::powf. + // If necessary, we may use alloc+libm as an alternative (see PR #1089). + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + fn choose_multiple_weighted( + &self, rng: &mut R, amount: usize, weight: F, + ) -> Result, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> X, + X: Into; + + /// Shuffle a mutable slice in place. + /// + /// For slices of length `n`, complexity is `O(n)`. + /// + /// # Example + /// + /// ``` + /// use rand::seq::SliceRandom; + /// use rand::thread_rng; + /// + /// let mut rng = thread_rng(); + /// let mut y = [1, 2, 3, 4, 5]; + /// println!("Unshuffled: {:?}", y); + /// y.shuffle(&mut rng); + /// println!("Shuffled: {:?}", y); + /// ``` + fn shuffle(&mut self, rng: &mut R) + where R: Rng + ?Sized; + + /// Shuffle a slice in place, but exit early. + /// + /// Returns two mutable slices from the source slice. The first contains + /// `amount` elements randomly permuted. The second has the remaining + /// elements that are not fully shuffled. + /// + /// This is an efficient method to select `amount` elements at random from + /// the slice, provided the slice may be mutated. + /// + /// If you only need to choose elements randomly and `amount > self.len()/2` + /// then you may improve performance by taking + /// `amount = values.len() - amount` and using only the second slice. + /// + /// If `amount` is greater than the number of elements in the slice, this + /// will perform a full shuffle. + /// + /// For slices, complexity is `O(m)` where `m = amount`. + fn partial_shuffle( + &mut self, rng: &mut R, amount: usize, + ) -> (&mut [Self::Item], &mut [Self::Item]) + where R: Rng + ?Sized; +} + +/// Extension trait on iterators, providing random sampling methods. +/// +/// This trait is implemented on all iterators `I` where `I: Iterator + Sized` +/// and provides methods for +/// choosing one or more elements. You must `use` this trait: +/// +/// ``` +/// use rand::seq::IteratorRandom; +/// +/// let mut rng = rand::thread_rng(); +/// +/// let faces = "😀😎😐😕😠😢"; +/// println!("I am {}!", faces.chars().choose(&mut rng).unwrap()); +/// ``` +/// Example output (non-deterministic): +/// ```none +/// I am 😀! +/// ``` +pub trait IteratorRandom: Iterator + Sized { + /// Choose one element at random from the iterator. + /// + /// Returns `None` if and only if the iterator is empty. + /// + /// This method uses [`Iterator::size_hint`] for optimisation. With an + /// accurate hint and where [`Iterator::nth`] is a constant-time operation + /// this method can offer `O(1)` performance. Where no size hint is + /// available, complexity is `O(n)` where `n` is the iterator length. + /// Partial hints (where `lower > 0`) also improve performance. + /// + /// Note that the output values and the number of RNG samples used + /// depends on size hints. In particular, `Iterator` combinators that don't + /// change the values yielded but change the size hints may result in + /// `choose` returning different elements. If you want consistent results + /// and RNG usage consider using [`IteratorRandom::choose_stable`]. + fn choose(mut self, rng: &mut R) -> Option + where R: Rng + ?Sized { + let (mut lower, mut upper) = self.size_hint(); + let mut consumed = 0; + let mut result = None; + + // Handling for this condition outside the loop allows the optimizer to eliminate the loop + // when the Iterator is an ExactSizeIterator. This has a large performance impact on e.g. + // seq_iter_choose_from_1000. + if upper == Some(lower) { + return if lower == 0 { + None + } else { + self.nth(gen_index(rng, lower)) + }; + } + + // Continue until the iterator is exhausted + loop { + if lower > 1 { + let ix = gen_index(rng, lower + consumed); + let skip = if ix < lower { + result = self.nth(ix); + lower - (ix + 1) + } else { + lower + }; + if upper == Some(lower) { + return result; + } + consumed += lower; + if skip > 0 { + self.nth(skip - 1); + } + } else { + let elem = self.next(); + if elem.is_none() { + return result; + } + consumed += 1; + if gen_index(rng, consumed) == 0 { + result = elem; + } + } + + let hint = self.size_hint(); + lower = hint.0; + upper = hint.1; + } + } + + /// Choose one element at random from the iterator. + /// + /// Returns `None` if and only if the iterator is empty. + /// + /// This method is very similar to [`choose`] except that the result + /// only depends on the length of the iterator and the values produced by + /// `rng`. Notably for any iterator of a given length this will make the + /// same requests to `rng` and if the same sequence of values are produced + /// the same index will be selected from `self`. This may be useful if you + /// need consistent results no matter what type of iterator you are working + /// with. If you do not need this stability prefer [`choose`]. + /// + /// Note that this method still uses [`Iterator::size_hint`] to skip + /// constructing elements where possible, however the selection and `rng` + /// calls are the same in the face of this optimization. If you want to + /// force every element to be created regardless call `.inspect(|e| ())`. + /// + /// [`choose`]: IteratorRandom::choose + fn choose_stable(mut self, rng: &mut R) -> Option + where R: Rng + ?Sized { + let mut consumed = 0; + let mut result = None; + + loop { + // Currently the only way to skip elements is `nth()`. So we need to + // store what index to access next here. + // This should be replaced by `advance_by()` once it is stable: + // https://github.com/rust-lang/rust/issues/77404 + let mut next = 0; + + let (lower, _) = self.size_hint(); + if lower >= 2 { + let highest_selected = (0..lower) + .filter(|ix| gen_index(rng, consumed+ix+1) == 0) + .last(); + + consumed += lower; + next = lower; + + if let Some(ix) = highest_selected { + result = self.nth(ix); + next -= ix + 1; + debug_assert!(result.is_some(), "iterator shorter than size_hint().0"); + } + } + + let elem = self.nth(next); + if elem.is_none() { + return result + } + + if gen_index(rng, consumed+1) == 0 { + result = elem; + } + consumed += 1; + } + } + + /// Collects values at random from the iterator into a supplied buffer + /// until that buffer is filled. + /// + /// Although the elements are selected randomly, the order of elements in + /// the buffer is neither stable nor fully random. If random ordering is + /// desired, shuffle the result. + /// + /// Returns the number of elements added to the buffer. This equals the length + /// of the buffer unless the iterator contains insufficient elements, in which + /// case this equals the number of elements available. + /// + /// Complexity is `O(n)` where `n` is the length of the iterator. + /// For slices, prefer [`SliceRandom::choose_multiple`]. + fn choose_multiple_fill(mut self, rng: &mut R, buf: &mut [Self::Item]) -> usize + where R: Rng + ?Sized { + let amount = buf.len(); + let mut len = 0; + while len < amount { + if let Some(elem) = self.next() { + buf[len] = elem; + len += 1; + } else { + // Iterator exhausted; stop early + return len; + } + } + + // Continue, since the iterator was not exhausted + for (i, elem) in self.enumerate() { + let k = gen_index(rng, i + 1 + amount); + if let Some(slot) = buf.get_mut(k) { + *slot = elem; + } + } + len + } + + /// Collects `amount` values at random from the iterator into a vector. + /// + /// This is equivalent to `choose_multiple_fill` except for the result type. + /// + /// Although the elements are selected randomly, the order of elements in + /// the buffer is neither stable nor fully random. If random ordering is + /// desired, shuffle the result. + /// + /// The length of the returned vector equals `amount` unless the iterator + /// contains insufficient elements, in which case it equals the number of + /// elements available. + /// + /// Complexity is `O(n)` where `n` is the length of the iterator. + /// For slices, prefer [`SliceRandom::choose_multiple`]. + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + fn choose_multiple(mut self, rng: &mut R, amount: usize) -> Vec + where R: Rng + ?Sized { + let mut reservoir = Vec::with_capacity(amount); + reservoir.extend(self.by_ref().take(amount)); + + // Continue unless the iterator was exhausted + // + // note: this prevents iterators that "restart" from causing problems. + // If the iterator stops once, then so do we. + if reservoir.len() == amount { + for (i, elem) in self.enumerate() { + let k = gen_index(rng, i + 1 + amount); + if let Some(slot) = reservoir.get_mut(k) { + *slot = elem; + } + } + } else { + // Don't hang onto extra memory. There is a corner case where + // `amount` was much less than `self.len()`. + reservoir.shrink_to_fit(); + } + reservoir + } +} + + +impl SliceRandom for [T] { + type Item = T; + + fn choose(&self, rng: &mut R) -> Option<&Self::Item> + where R: Rng + ?Sized { + if self.is_empty() { + None + } else { + Some(&self[gen_index(rng, self.len())]) + } + } + + fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Item> + where R: Rng + ?Sized { + if self.is_empty() { + None + } else { + let len = self.len(); + Some(&mut self[gen_index(rng, len)]) + } + } + + #[cfg(feature = "alloc")] + fn choose_multiple(&self, rng: &mut R, amount: usize) -> SliceChooseIter + where R: Rng + ?Sized { + let amount = ::core::cmp::min(amount, self.len()); + SliceChooseIter { + slice: self, + _phantom: Default::default(), + indices: index::sample(rng, self.len(), amount).into_iter(), + } + } + + #[cfg(feature = "alloc")] + fn choose_weighted( + &self, rng: &mut R, weight: F, + ) -> Result<&Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default, + { + use crate::distributions::{Distribution, WeightedIndex}; + let distr = WeightedIndex::new(self.iter().map(weight))?; + Ok(&self[distr.sample(rng)]) + } + + #[cfg(feature = "alloc")] + fn choose_weighted_mut( + &mut self, rng: &mut R, weight: F, + ) -> Result<&mut Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default, + { + use crate::distributions::{Distribution, WeightedIndex}; + let distr = WeightedIndex::new(self.iter().map(weight))?; + Ok(&mut self[distr.sample(rng)]) + } + + #[cfg(feature = "std")] + fn choose_multiple_weighted( + &self, rng: &mut R, amount: usize, weight: F, + ) -> Result, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> X, + X: Into, + { + let amount = ::core::cmp::min(amount, self.len()); + Ok(SliceChooseIter { + slice: self, + _phantom: Default::default(), + indices: index::sample_weighted( + rng, + self.len(), + |idx| weight(&self[idx]).into(), + amount, + )? + .into_iter(), + }) + } + + fn shuffle(&mut self, rng: &mut R) + where R: Rng + ?Sized { + for i in (1..self.len()).rev() { + // invariant: elements with index > i have been locked in place. + self.swap(i, gen_index(rng, i + 1)); + } + } + + fn partial_shuffle( + &mut self, rng: &mut R, amount: usize, + ) -> (&mut [Self::Item], &mut [Self::Item]) + where R: Rng + ?Sized { + // This applies Durstenfeld's algorithm for the + // [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm) + // for an unbiased permutation, but exits early after choosing `amount` + // elements. + + let len = self.len(); + let end = if amount >= len { 0 } else { len - amount }; + + for i in (end..len).rev() { + // invariant: elements with index > i have been locked in place. + self.swap(i, gen_index(rng, i + 1)); + } + let r = self.split_at_mut(end); + (r.1, r.0) + } +} + +impl IteratorRandom for I where I: Iterator + Sized {} + + +/// An iterator over multiple slice elements. +/// +/// This struct is created by +/// [`SliceRandom::choose_multiple`](trait.SliceRandom.html#tymethod.choose_multiple). +#[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +#[derive(Debug)] +pub struct SliceChooseIter<'a, S: ?Sized + 'a, T: 'a> { + slice: &'a S, + _phantom: ::core::marker::PhantomData, + indices: index::IndexVecIntoIter, +} + +#[cfg(feature = "alloc")] +impl<'a, S: Index + ?Sized + 'a, T: 'a> Iterator for SliceChooseIter<'a, S, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + // TODO: investigate using SliceIndex::get_unchecked when stable + self.indices.next().map(|i| &self.slice[i as usize]) + } + + fn size_hint(&self) -> (usize, Option) { + (self.indices.len(), Some(self.indices.len())) + } +} + +#[cfg(feature = "alloc")] +impl<'a, S: Index + ?Sized + 'a, T: 'a> ExactSizeIterator + for SliceChooseIter<'a, S, T> +{ + fn len(&self) -> usize { + self.indices.len() + } +} + + +// Sample a number uniformly between 0 and `ubound`. Uses 32-bit sampling where +// possible, primarily in order to produce the same output on 32-bit and 64-bit +// platforms. +#[inline] +fn gen_index(rng: &mut R, ubound: usize) -> usize { + if ubound <= (core::u32::MAX as usize) { + rng.gen_range(0..ubound as u32) as usize + } else { + rng.gen_range(0..ubound) + } +} + + +#[cfg(test)] +mod test { + use super::*; + #[cfg(feature = "alloc")] use crate::Rng; + #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec; + + #[test] + fn test_slice_choose() { + let mut r = crate::test::rng(107); + let chars = [ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + ]; + let mut chosen = [0i32; 14]; + // The below all use a binomial distribution with n=1000, p=1/14. + // binocdf(40, 1000, 1/14) ~= 2e-5; 1-binocdf(106, ..) ~= 2e-5 + for _ in 0..1000 { + let picked = *chars.choose(&mut r).unwrap(); + chosen[(picked as usize) - ('a' as usize)] += 1; + } + for count in chosen.iter() { + assert!(40 < *count && *count < 106); + } + + chosen.iter_mut().for_each(|x| *x = 0); + for _ in 0..1000 { + *chosen.choose_mut(&mut r).unwrap() += 1; + } + for count in chosen.iter() { + assert!(40 < *count && *count < 106); + } + + let mut v: [isize; 0] = []; + assert_eq!(v.choose(&mut r), None); + assert_eq!(v.choose_mut(&mut r), None); + } + + #[test] + fn value_stability_slice() { + let mut r = crate::test::rng(413); + let chars = [ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + ]; + let mut nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + + assert_eq!(chars.choose(&mut r), Some(&'l')); + assert_eq!(nums.choose_mut(&mut r), Some(&mut 10)); + + #[cfg(feature = "alloc")] + assert_eq!( + &chars + .choose_multiple(&mut r, 8) + .cloned() + .collect::>(), + &['d', 'm', 'b', 'n', 'c', 'k', 'h', 'e'] + ); + + #[cfg(feature = "alloc")] + assert_eq!(chars.choose_weighted(&mut r, |_| 1), Ok(&'f')); + #[cfg(feature = "alloc")] + assert_eq!(nums.choose_weighted_mut(&mut r, |_| 1), Ok(&mut 5)); + + let mut r = crate::test::rng(414); + nums.shuffle(&mut r); + assert_eq!(nums, [9, 5, 3, 10, 7, 12, 8, 11, 6, 4, 0, 2, 1]); + nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + let res = nums.partial_shuffle(&mut r, 6); + assert_eq!(res.0, &mut [7, 4, 8, 6, 9, 3]); + assert_eq!(res.1, &mut [0, 1, 2, 12, 11, 5, 10]); + } + + #[derive(Clone)] + struct UnhintedIterator { + iter: I, + } + impl Iterator for UnhintedIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.iter.next() + } + } + + #[derive(Clone)] + struct ChunkHintedIterator { + iter: I, + chunk_remaining: usize, + chunk_size: usize, + hint_total_size: bool, + } + impl Iterator for ChunkHintedIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + if self.chunk_remaining == 0 { + self.chunk_remaining = ::core::cmp::min(self.chunk_size, self.iter.len()); + } + self.chunk_remaining = self.chunk_remaining.saturating_sub(1); + + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + ( + self.chunk_remaining, + if self.hint_total_size { + Some(self.iter.len()) + } else { + None + }, + ) + } + } + + #[derive(Clone)] + struct WindowHintedIterator { + iter: I, + window_size: usize, + hint_total_size: bool, + } + impl Iterator for WindowHintedIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + ( + ::core::cmp::min(self.iter.len(), self.window_size), + if self.hint_total_size { + Some(self.iter.len()) + } else { + None + }, + ) + } + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_iterator_choose() { + let r = &mut crate::test::rng(109); + fn test_iter + Clone>(r: &mut R, iter: Iter) { + let mut chosen = [0i32; 9]; + for _ in 0..1000 { + let picked = iter.clone().choose(r).unwrap(); + chosen[picked] += 1; + } + for count in chosen.iter() { + // Samples should follow Binomial(1000, 1/9) + // Octave: binopdf(x, 1000, 1/9) gives the prob of *count == x + // Note: have seen 153, which is unlikely but not impossible. + assert!( + 72 < *count && *count < 154, + "count not close to 1000/9: {}", + count + ); + } + } + + test_iter(r, 0..9); + test_iter(r, [0, 1, 2, 3, 4, 5, 6, 7, 8].iter().cloned()); + #[cfg(feature = "alloc")] + test_iter(r, (0..9).collect::>().into_iter()); + test_iter(r, UnhintedIterator { iter: 0..9 }); + test_iter(r, ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: false, + }); + test_iter(r, ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: true, + }); + test_iter(r, WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: false, + }); + test_iter(r, WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: true, + }); + + assert_eq!((0..0).choose(r), None); + assert_eq!(UnhintedIterator { iter: 0..0 }.choose(r), None); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_iterator_choose_stable() { + let r = &mut crate::test::rng(109); + fn test_iter + Clone>(r: &mut R, iter: Iter) { + let mut chosen = [0i32; 9]; + for _ in 0..1000 { + let picked = iter.clone().choose_stable(r).unwrap(); + chosen[picked] += 1; + } + for count in chosen.iter() { + // Samples should follow Binomial(1000, 1/9) + // Octave: binopdf(x, 1000, 1/9) gives the prob of *count == x + // Note: have seen 153, which is unlikely but not impossible. + assert!( + 72 < *count && *count < 154, + "count not close to 1000/9: {}", + count + ); + } + } + + test_iter(r, 0..9); + test_iter(r, [0, 1, 2, 3, 4, 5, 6, 7, 8].iter().cloned()); + #[cfg(feature = "alloc")] + test_iter(r, (0..9).collect::>().into_iter()); + test_iter(r, UnhintedIterator { iter: 0..9 }); + test_iter(r, ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: false, + }); + test_iter(r, ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: true, + }); + test_iter(r, WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: false, + }); + test_iter(r, WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: true, + }); + + assert_eq!((0..0).choose(r), None); + assert_eq!(UnhintedIterator { iter: 0..0 }.choose(r), None); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_iterator_choose_stable_stability() { + fn test_iter(iter: impl Iterator + Clone) -> [i32; 9] { + let r = &mut crate::test::rng(109); + let mut chosen = [0i32; 9]; + for _ in 0..1000 { + let picked = iter.clone().choose_stable(r).unwrap(); + chosen[picked] += 1; + } + chosen + } + + let reference = test_iter(0..9); + assert_eq!(test_iter([0, 1, 2, 3, 4, 5, 6, 7, 8].iter().cloned()), reference); + + #[cfg(feature = "alloc")] + assert_eq!(test_iter((0..9).collect::>().into_iter()), reference); + assert_eq!(test_iter(UnhintedIterator { iter: 0..9 }), reference); + assert_eq!(test_iter(ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: false, + }), reference); + assert_eq!(test_iter(ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: true, + }), reference); + assert_eq!(test_iter(WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: false, + }), reference); + assert_eq!(test_iter(WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: true, + }), reference); + } + + #[test] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_shuffle() { + let mut r = crate::test::rng(108); + let empty: &mut [isize] = &mut []; + empty.shuffle(&mut r); + let mut one = [1]; + one.shuffle(&mut r); + let b: &[_] = &[1]; + assert_eq!(one, b); + + let mut two = [1, 2]; + two.shuffle(&mut r); + assert!(two == [1, 2] || two == [2, 1]); + + fn move_last(slice: &mut [usize], pos: usize) { + // use slice[pos..].rotate_left(1); once we can use that + let last_val = slice[pos]; + for i in pos..slice.len() - 1 { + slice[i] = slice[i + 1]; + } + *slice.last_mut().unwrap() = last_val; + } + let mut counts = [0i32; 24]; + for _ in 0..10000 { + let mut arr: [usize; 4] = [0, 1, 2, 3]; + arr.shuffle(&mut r); + let mut permutation = 0usize; + let mut pos_value = counts.len(); + for i in 0..4 { + pos_value /= 4 - i; + let pos = arr.iter().position(|&x| x == i).unwrap(); + assert!(pos < (4 - i)); + permutation += pos * pos_value; + move_last(&mut arr, pos); + assert_eq!(arr[3], i); + } + for i in 0..4 { + assert_eq!(arr[i], i); + } + counts[permutation] += 1; + } + for count in counts.iter() { + // Binomial(10000, 1/24) with average 416.667 + // Octave: binocdf(n, 10000, 1/24) + // 99.9% chance samples lie within this range: + assert!(352 <= *count && *count <= 483, "count: {}", count); + } + } + + #[test] + fn test_partial_shuffle() { + let mut r = crate::test::rng(118); + + let mut empty: [u32; 0] = []; + let res = empty.partial_shuffle(&mut r, 10); + assert_eq!((res.0.len(), res.1.len()), (0, 0)); + + let mut v = [1, 2, 3, 4, 5]; + let res = v.partial_shuffle(&mut r, 2); + assert_eq!((res.0.len(), res.1.len()), (2, 3)); + assert!(res.0[0] != res.0[1]); + // First elements are only modified if selected, so at least one isn't modified: + assert!(res.1[0] == 1 || res.1[1] == 2 || res.1[2] == 3); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_sample_iter() { + let min_val = 1; + let max_val = 100; + + let mut r = crate::test::rng(401); + let vals = (min_val..max_val).collect::>(); + let small_sample = vals.iter().choose_multiple(&mut r, 5); + let large_sample = vals.iter().choose_multiple(&mut r, vals.len() + 5); + + assert_eq!(small_sample.len(), 5); + assert_eq!(large_sample.len(), vals.len()); + // no randomization happens when amount >= len + assert_eq!(large_sample, vals.iter().collect::>()); + + assert!(small_sample + .iter() + .all(|e| { **e >= min_val && **e <= max_val })); + } + + #[test] + #[cfg(feature = "alloc")] + #[cfg_attr(miri, ignore)] // Miri is too slow + fn test_weighted() { + let mut r = crate::test::rng(406); + const N_REPS: u32 = 3000; + let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]; + let total_weight = weights.iter().sum::() as f32; + + let verify = |result: [i32; 14]| { + for (i, count) in result.iter().enumerate() { + let exp = (weights[i] * N_REPS) as f32 / total_weight; + let mut err = (*count as f32 - exp).abs(); + if err != 0.0 { + err /= exp; + } + assert!(err <= 0.25); + } + }; + + // choose_weighted + fn get_weight(item: &(u32, T)) -> u32 { + item.0 + } + let mut chosen = [0i32; 14]; + let mut items = [(0u32, 0usize); 14]; // (weight, index) + for (i, item) in items.iter_mut().enumerate() { + *item = (weights[i], i); + } + for _ in 0..N_REPS { + let item = items.choose_weighted(&mut r, get_weight).unwrap(); + chosen[item.1] += 1; + } + verify(chosen); + + // choose_weighted_mut + let mut items = [(0u32, 0i32); 14]; // (weight, count) + for (i, item) in items.iter_mut().enumerate() { + *item = (weights[i], 0); + } + for _ in 0..N_REPS { + items.choose_weighted_mut(&mut r, get_weight).unwrap().1 += 1; + } + for (ch, item) in chosen.iter_mut().zip(items.iter()) { + *ch = item.1; + } + verify(chosen); + + // Check error cases + let empty_slice = &mut [10][0..0]; + assert_eq!( + empty_slice.choose_weighted(&mut r, |_| 1), + Err(WeightedError::NoItem) + ); + assert_eq!( + empty_slice.choose_weighted_mut(&mut r, |_| 1), + Err(WeightedError::NoItem) + ); + assert_eq!( + ['x'].choose_weighted_mut(&mut r, |_| 0), + Err(WeightedError::AllWeightsZero) + ); + assert_eq!( + [0, -1].choose_weighted_mut(&mut r, |x| *x), + Err(WeightedError::InvalidWeight) + ); + assert_eq!( + [-1, 0].choose_weighted_mut(&mut r, |x| *x), + Err(WeightedError::InvalidWeight) + ); + } + + #[test] + fn value_stability_choose() { + fn choose>(iter: I) -> Option { + let mut rng = crate::test::rng(411); + iter.choose(&mut rng) + } + + assert_eq!(choose([].iter().cloned()), None); + assert_eq!(choose(0..100), Some(33)); + assert_eq!(choose(UnhintedIterator { iter: 0..100 }), Some(40)); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: false, + }), + Some(39) + ); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: true, + }), + Some(39) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: false, + }), + Some(90) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: true, + }), + Some(90) + ); + } + + #[test] + fn value_stability_choose_stable() { + fn choose>(iter: I) -> Option { + let mut rng = crate::test::rng(411); + iter.choose_stable(&mut rng) + } + + assert_eq!(choose([].iter().cloned()), None); + assert_eq!(choose(0..100), Some(40)); + assert_eq!(choose(UnhintedIterator { iter: 0..100 }), Some(40)); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: false, + }), + Some(40) + ); + assert_eq!( + choose(ChunkHintedIterator { + iter: 0..100, + chunk_size: 32, + chunk_remaining: 32, + hint_total_size: true, + }), + Some(40) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: false, + }), + Some(40) + ); + assert_eq!( + choose(WindowHintedIterator { + iter: 0..100, + window_size: 32, + hint_total_size: true, + }), + Some(40) + ); + } + + #[test] + fn value_stability_choose_multiple() { + fn do_test>(iter: I, v: &[u32]) { + let mut rng = crate::test::rng(412); + let mut buf = [0u32; 8]; + assert_eq!(iter.choose_multiple_fill(&mut rng, &mut buf), v.len()); + assert_eq!(&buf[0..v.len()], v); + } + + do_test(0..4, &[0, 1, 2, 3]); + do_test(0..8, &[0, 1, 2, 3, 4, 5, 6, 7]); + do_test(0..100, &[58, 78, 80, 92, 43, 8, 96, 7]); + + #[cfg(feature = "alloc")] + { + fn do_test>(iter: I, v: &[u32]) { + let mut rng = crate::test::rng(412); + assert_eq!(iter.choose_multiple(&mut rng, v.len()), v); + } + + do_test(0..4, &[0, 1, 2, 3]); + do_test(0..8, &[0, 1, 2, 3, 4, 5, 6, 7]); + do_test(0..100, &[58, 78, 80, 92, 43, 8, 96, 7]); + } + } + + #[test] + #[cfg(feature = "std")] + fn test_multiple_weighted_edge_cases() { + use super::*; + + let mut rng = crate::test::rng(413); + + // Case 1: One of the weights is 0 + let choices = [('a', 2), ('b', 1), ('c', 0)]; + for _ in 0..100 { + let result = choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap() + .collect::>(); + + assert_eq!(result.len(), 2); + assert!(!result.iter().any(|val| val.0 == 'c')); + } + + // Case 2: All of the weights are 0 + let choices = [('a', 0), ('b', 0), ('c', 0)]; + let result = choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap() + .collect::>(); + assert_eq!(result.len(), 2); + + // Case 3: Negative weights + let choices = [('a', -1), ('b', 1), ('c', 1)]; + assert_eq!( + choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap_err(), + WeightedError::InvalidWeight + ); + + // Case 4: Empty list + let choices = []; + let result = choices + .choose_multiple_weighted(&mut rng, 0, |_: &()| 0) + .unwrap() + .collect::>(); + assert_eq!(result.len(), 0); + + // Case 5: NaN weights + let choices = [('a', core::f64::NAN), ('b', 1.0), ('c', 1.0)]; + assert_eq!( + choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap_err(), + WeightedError::InvalidWeight + ); + + // Case 6: +infinity weights + let choices = [('a', core::f64::INFINITY), ('b', 1.0), ('c', 1.0)]; + for _ in 0..100 { + let result = choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap() + .collect::>(); + assert_eq!(result.len(), 2); + assert!(result.iter().any(|val| val.0 == 'a')); + } + + // Case 7: -infinity weights + let choices = [('a', core::f64::NEG_INFINITY), ('b', 1.0), ('c', 1.0)]; + assert_eq!( + choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap_err(), + WeightedError::InvalidWeight + ); + + // Case 8: -0 weights + let choices = [('a', -0.0), ('b', 1.0), ('c', 1.0)]; + assert!(choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .is_ok()); + } + + #[test] + #[cfg(feature = "std")] + fn test_multiple_weighted_distributions() { + use super::*; + + // The theoretical probabilities of the different outcomes are: + // AB: 0.5 * 0.5 = 0.250 + // AC: 0.5 * 0.5 = 0.250 + // BA: 0.25 * 0.67 = 0.167 + // BC: 0.25 * 0.33 = 0.082 + // CA: 0.25 * 0.67 = 0.167 + // CB: 0.25 * 0.33 = 0.082 + let choices = [('a', 2), ('b', 1), ('c', 1)]; + let mut rng = crate::test::rng(414); + + let mut results = [0i32; 3]; + let expected_results = [4167, 4167, 1666]; + for _ in 0..10000 { + let result = choices + .choose_multiple_weighted(&mut rng, 2, |item| item.1) + .unwrap() + .collect::>(); + + assert_eq!(result.len(), 2); + + match (result[0].0, result[1].0) { + ('a', 'b') | ('b', 'a') => { + results[0] += 1; + } + ('a', 'c') | ('c', 'a') => { + results[1] += 1; + } + ('b', 'c') | ('c', 'b') => { + results[2] += 1; + } + (_, _) => panic!("unexpected result"), + } + } + + let mut diffs = results + .iter() + .zip(&expected_results) + .map(|(a, b)| (a - b).abs()); + assert!(!diffs.any(|deviation| deviation > 100)); + } +} diff --git a/vendor/rand_chacha/.cargo-checksum.json b/vendor/rand_chacha/.cargo-checksum.json new file mode 100644 index 0000000000..293de38d64 --- /dev/null +++ b/vendor/rand_chacha/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"ad5ed93d0f6e7c9adad7ce346b05ba5585275f689a1ae1aa176baab5f95266c7","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.toml":"1ea33201f9d2687c4a7201073efe3ddd9c7fe4ffef1307b22ccbf8e4a7537488","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"f4221f35b7086649fa77807e826af020b57eb65b19cb693482d4a7e1e4d80537","src/chacha.rs":"c48699c02df8e8fb654e9cb9feddaf432e367539da40bbfe2b8a0f4189797dee","src/guts.rs":"b378faf7648a510653cec160bd4a01dca65790e530a8a9bdebc6e5c9e1faf70a","src/lib.rs":"a27fe2bff676a764d43d604a20cf30a41dc1c5ef4053eb41129d2479f5ae83fe"},"package":"e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"} \ No newline at end of file diff --git a/vendor/rand_chacha/CHANGELOG.md b/vendor/rand_chacha/CHANGELOG.md new file mode 100644 index 0000000000..8a07390076 --- /dev/null +++ b/vendor/rand_chacha/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.3.0] - 2020-12-08 +- Bump `rand_core` version to 0.6.0 +- Bump MSRV to 1.36 (#1011) +- Remove usage of deprecated feature "simd" of `ppv-lite86` (#979), then revert + this change (#1023) since SIMD is only enabled by default from `ppv-lite86 v0.2.10` +- impl PartialEq+Eq for ChaChaXRng and ChaChaXCore (#979) +- Fix panic on block counter wrap that was occurring in debug builds (#980) + +## [0.2.2] - 2020-03-09 +- Integrate `c2-chacha`, reducing dependency count (#931) +- Add CryptoRng to ChaChaXCore (#944) + +## [0.2.1] - 2019-07-22 +- Force enable the `simd` feature of `c2-chacha` (#845) + +## [0.2.0] - 2019-06-06 +- Rewrite based on the much faster `c2-chacha` crate (#789) + +## [0.1.1] - 2019-01-04 +- Disable `i128` and `u128` if the `target_os` is `emscripten` (#671: work-around Emscripten limitation) +- Update readme and doc links + +## [0.1.0] - 2018-10-17 +- Pulled out of the Rand crate diff --git a/vendor/rand_chacha/COPYRIGHT b/vendor/rand_chacha/COPYRIGHT new file mode 100644 index 0000000000..468d907caf --- /dev/null +++ b/vendor/rand_chacha/COPYRIGHT @@ -0,0 +1,12 @@ +Copyrights in the Rand project are retained by their contributors. No +copyright assignment is required to contribute to the Rand project. + +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), Rand is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + +The Rand project includes code from the Rust project +published under these same licenses. diff --git a/vendor/rand_chacha/Cargo.toml b/vendor/rand_chacha/Cargo.toml new file mode 100644 index 0000000000..0f371b3c3f --- /dev/null +++ b/vendor/rand_chacha/Cargo.toml @@ -0,0 +1,37 @@ +# 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 = "rand_chacha" +version = "0.3.0" +authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"] +description = "ChaCha random number generator\n" +homepage = "https://crates.io/crates/rand_chacha" +documentation = "https://rust-random.github.io/rand/rand_chacha/" +readme = "README.md" +keywords = ["random", "rng", "chacha"] +categories = ["algorithms", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/rand" +[dependencies.ppv-lite86] +version = "0.2.8" +features = ["simd"] +default-features = false + +[dependencies.rand_core] +version = "0.6.0" + +[features] +default = ["std"] +simd = [] +std = ["ppv-lite86/std"] diff --git a/vendor/rand_chacha/LICENSE-APACHE b/vendor/rand_chacha/LICENSE-APACHE new file mode 100644 index 0000000000..17d74680f8 --- /dev/null +++ b/vendor/rand_chacha/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://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 + + https://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/rand_chacha/LICENSE-MIT b/vendor/rand_chacha/LICENSE-MIT new file mode 100644 index 0000000000..d93b5baf34 --- /dev/null +++ b/vendor/rand_chacha/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright 2018 Developers of the Rand project +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/rand_chacha/README.md b/vendor/rand_chacha/README.md new file mode 100644 index 0000000000..edd754d791 --- /dev/null +++ b/vendor/rand_chacha/README.md @@ -0,0 +1,48 @@ +# rand_chacha + +[![Test Status](https://github.com/rust-random/rand/workflows/Tests/badge.svg?event=push)](https://github.com/rust-random/rand/actions) +[![Latest version](https://img.shields.io/crates/v/rand_chacha.svg)](https://crates.io/crates/rand_chacha) +[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) +[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_chacha) +[![API](https://docs.rs/rand_chacha/badge.svg)](https://docs.rs/rand_chacha) +[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements) + +A cryptographically secure random number generator that uses the ChaCha +algorithm. + +ChaCha is a stream cipher designed by Daniel J. Bernstein[^1], that we use +as an RNG. It is an improved variant of the Salsa20 cipher family, which was +selected as one of the "stream ciphers suitable for widespread adoption" by +eSTREAM[^2]. + +The RNGs provided by this crate are implemented via the fast stream ciphers of +the [`c2-chacha`](https://crates.io/crates/c2-chacha) crate. + +Links: + +- [API documentation (master)](https://rust-random.github.io/rand/rand_chacha) +- [API documentation (docs.rs)](https://docs.rs/rand_chacha) +- [Changelog](https://github.com/rust-random/rand/blob/master/rand_chacha/CHANGELOG.md) + +[rand]: https://crates.io/crates/rand +[^1]: D. J. Bernstein, [*ChaCha, a variant of Salsa20*]( + https://cr.yp.to/chacha.html) + +[^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( + http://www.ecrypt.eu.org/stream/) + + +## Crate Features + +`rand_chacha` is `no_std` compatible when disabling default features; the `std` +feature can be explicitly required to re-enable `std` support. Using `std` +allows detection of CPU features and thus better optimisation. + + +# License + +`rand_chacha` is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and +[COPYRIGHT](COPYRIGHT) for details. diff --git a/vendor/rand_chacha/src/chacha.rs b/vendor/rand_chacha/src/chacha.rs new file mode 100644 index 0000000000..17bcc5528d --- /dev/null +++ b/vendor/rand_chacha/src/chacha.rs @@ -0,0 +1,509 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The ChaCha random number generator. + +#[cfg(not(feature = "std"))] use core; +#[cfg(feature = "std")] use std as core; + +use self::core::fmt; +use crate::guts::ChaCha; +use rand_core::block::{BlockRng, BlockRngCore}; +use rand_core::{CryptoRng, Error, RngCore, SeedableRng}; + +const STREAM_PARAM_NONCE: u32 = 1; +const STREAM_PARAM_BLOCK: u32 = 0; + +// NB. this must remain consistent with some currently hard-coded numbers in this module +const BUF_BLOCKS: u8 = 4; +// number of 32-bit words per ChaCha block (fixed by algorithm definition) +const BLOCK_WORDS: u8 = 16; + +pub struct Array64([T; 64]); +impl Default for Array64 +where T: Default +{ + #[rustfmt::skip] + fn default() -> Self { + Self([ + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + ]) + } +} +impl AsRef<[T]> for Array64 { + fn as_ref(&self) -> &[T] { + &self.0 + } +} +impl AsMut<[T]> for Array64 { + fn as_mut(&mut self) -> &mut [T] { + &mut self.0 + } +} +impl Clone for Array64 +where T: Copy + Default +{ + fn clone(&self) -> Self { + let mut new = Self::default(); + new.0.copy_from_slice(&self.0); + new + } +} +impl fmt::Debug for Array64 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Array64 {{}}") + } +} + +macro_rules! chacha_impl { + ($ChaChaXCore:ident, $ChaChaXRng:ident, $rounds:expr, $doc:expr) => { + #[doc=$doc] + #[derive(Clone, PartialEq, Eq)] + pub struct $ChaChaXCore { + state: ChaCha, + } + + // Custom Debug implementation that does not expose the internal state + impl fmt::Debug for $ChaChaXCore { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ChaChaXCore {{}}") + } + } + + impl BlockRngCore for $ChaChaXCore { + type Item = u32; + type Results = Array64; + #[inline] + fn generate(&mut self, r: &mut Self::Results) { + // Fill slice of words by writing to equivalent slice of bytes, then fixing endianness. + self.state.refill4($rounds, unsafe { + &mut *(&mut *r as *mut Array64 as *mut [u8; 256]) + }); + for x in r.as_mut() { + *x = x.to_le(); + } + } + } + + impl SeedableRng for $ChaChaXCore { + type Seed = [u8; 32]; + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + $ChaChaXCore { state: ChaCha::new(&seed, &[0u8; 8]) } + } + } + + impl CryptoRng for $ChaChaXCore {} + + /// A cryptographically secure random number generator that uses the ChaCha algorithm. + /// + /// ChaCha is a stream cipher designed by Daniel J. Bernstein[^1], that we use as an RNG. It is + /// an improved variant of the Salsa20 cipher family, which was selected as one of the "stream + /// ciphers suitable for widespread adoption" by eSTREAM[^2]. + /// + /// ChaCha uses add-rotate-xor (ARX) operations as its basis. These are safe against timing + /// attacks, although that is mostly a concern for ciphers and not for RNGs. We provide a SIMD + /// implementation to support high throughput on a variety of common hardware platforms. + /// + /// With the ChaCha algorithm it is possible to choose the number of rounds the core algorithm + /// should run. The number of rounds is a tradeoff between performance and security, where 8 + /// rounds is the minimum potentially secure configuration, and 20 rounds is widely used as a + /// conservative choice. + /// + /// We use a 64-bit counter and 64-bit stream identifier as in Bernstein's implementation[^1] + /// except that we use a stream identifier in place of a nonce. A 64-bit counter over 64-byte + /// (16 word) blocks allows 1 ZiB of output before cycling, and the stream identifier allows + /// 264 unique streams of output per seed. Both counter and stream are initialized + /// to zero but may be set via the `set_word_pos` and `set_stream` methods. + /// + /// The word layout is: + /// + /// ```text + /// constant constant constant constant + /// seed seed seed seed + /// seed seed seed seed + /// counter counter stream_id stream_id + /// ``` + /// + /// This implementation uses an output buffer of sixteen `u32` words, and uses + /// [`BlockRng`] to implement the [`RngCore`] methods. + /// + /// [^1]: D. J. Bernstein, [*ChaCha, a variant of Salsa20*]( + /// https://cr.yp.to/chacha.html) + /// + /// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( + /// http://www.ecrypt.eu.org/stream/) + #[derive(Clone, Debug)] + pub struct $ChaChaXRng { + rng: BlockRng<$ChaChaXCore>, + } + + impl SeedableRng for $ChaChaXRng { + type Seed = [u8; 32]; + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + let core = $ChaChaXCore::from_seed(seed); + Self { + rng: BlockRng::new(core), + } + } + } + + impl RngCore for $ChaChaXRng { + #[inline] + fn next_u32(&mut self) -> u32 { + self.rng.next_u32() + } + #[inline] + fn next_u64(&mut self) -> u64 { + self.rng.next_u64() + } + #[inline] + fn fill_bytes(&mut self, bytes: &mut [u8]) { + self.rng.fill_bytes(bytes) + } + #[inline] + fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Error> { + self.rng.try_fill_bytes(bytes) + } + } + + impl $ChaChaXRng { + // The buffer is a 4-block window, i.e. it is always at a block-aligned position in the + // stream but if the stream has been seeked it may not be self-aligned. + + /// Get the offset from the start of the stream, in 32-bit words. + /// + /// Since the generated blocks are 16 words (24) long and the + /// counter is 64-bits, the offset is a 68-bit number. Sub-word offsets are + /// not supported, hence the result can simply be multiplied by 4 to get a + /// byte-offset. + #[inline] + pub fn get_word_pos(&self) -> u128 { + let buf_start_block = { + let buf_end_block = self.rng.core.state.get_stream_param(STREAM_PARAM_BLOCK); + u64::wrapping_sub(buf_end_block, BUF_BLOCKS.into()) + }; + let (buf_offset_blocks, block_offset_words) = { + let buf_offset_words = self.rng.index() as u64; + let blocks_part = buf_offset_words / u64::from(BLOCK_WORDS); + let words_part = buf_offset_words % u64::from(BLOCK_WORDS); + (blocks_part, words_part) + }; + let pos_block = u64::wrapping_add(buf_start_block, buf_offset_blocks); + let pos_block_words = u128::from(pos_block) * u128::from(BLOCK_WORDS); + pos_block_words + u128::from(block_offset_words) + } + + /// Set the offset from the start of the stream, in 32-bit words. + /// + /// As with `get_word_pos`, we use a 68-bit number. Since the generator + /// simply cycles at the end of its period (1 ZiB), we ignore the upper + /// 60 bits. + #[inline] + pub fn set_word_pos(&mut self, word_offset: u128) { + let block = (word_offset / u128::from(BLOCK_WORDS)) as u64; + self.rng + .core + .state + .set_stream_param(STREAM_PARAM_BLOCK, block); + self.rng.generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize); + } + + /// Set the stream number. + /// + /// This is initialized to zero; 264 unique streams of output + /// are available per seed/key. + /// + /// Note that in order to reproduce ChaCha output with a specific 64-bit + /// nonce, one can convert that nonce to a `u64` in little-endian fashion + /// and pass to this function. In theory a 96-bit nonce can be used by + /// passing the last 64-bits to this function and using the first 32-bits as + /// the most significant half of the 64-bit counter (which may be set + /// indirectly via `set_word_pos`), but this is not directly supported. + #[inline] + pub fn set_stream(&mut self, stream: u64) { + self.rng + .core + .state + .set_stream_param(STREAM_PARAM_NONCE, stream); + if self.rng.index() != 64 { + let wp = self.get_word_pos(); + self.set_word_pos(wp); + } + } + } + + impl CryptoRng for $ChaChaXRng {} + + impl From<$ChaChaXCore> for $ChaChaXRng { + fn from(core: $ChaChaXCore) -> Self { + $ChaChaXRng { + rng: BlockRng::new(core), + } + } + } + + impl PartialEq<$ChaChaXRng> for $ChaChaXRng { + fn eq(&self, rhs: &$ChaChaXRng) -> bool { + self.rng.core.state.stream64_eq(&rhs.rng.core.state) + && self.get_word_pos() == rhs.get_word_pos() + } + } + impl Eq for $ChaChaXRng {} + } +} + +chacha_impl!(ChaCha20Core, ChaCha20Rng, 10, "ChaCha with 20 rounds"); +chacha_impl!(ChaCha12Core, ChaCha12Rng, 6, "ChaCha with 12 rounds"); +chacha_impl!(ChaCha8Core, ChaCha8Rng, 4, "ChaCha with 8 rounds"); + +#[cfg(test)] +mod test { + use rand_core::{RngCore, SeedableRng}; + + type ChaChaRng = super::ChaCha20Rng; + + #[test] + fn test_chacha_construction() { + let seed = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, + ]; + let mut rng1 = ChaChaRng::from_seed(seed); + assert_eq!(rng1.next_u32(), 137206642); + + let mut rng2 = ChaChaRng::from_rng(rng1).unwrap(); + assert_eq!(rng2.next_u32(), 1325750369); + } + + #[test] + fn test_chacha_true_values_a() { + // Test vectors 1 and 2 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + let seed = [0u8; 32]; + let mut rng = ChaChaRng::from_seed(seed); + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, 0xb819d2bd, 0x1aed8da0, 0xccef36a8, + 0xc70d778b, 0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8, 0xf4b8436a, 0x1ca11815, + 0x69b687c3, 0x8665eeb2, + ]; + assert_eq!(results, expected); + + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, 0xa0290fcb, 0x6965e348, 0x3e53c612, + 0xed7aee32, 0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874, 0x281fed31, 0x45fb0a51, + 0x1f0ae1ac, 0x6f4d794b, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_true_values_b() { + // Test vector 3 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + let seed = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, + ]; + let mut rng = ChaChaRng::from_seed(seed); + + // Skip block 0 + for _ in 0..16 { + rng.next_u32(); + } + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0x2452eb3a, 0x9249f8ec, 0x8d829d9b, 0xddd4ceb1, 0xe8252083, 0x60818b01, 0xf38422b8, + 0x5aaa49c9, 0xbb00ca8e, 0xda3ba7b4, 0xc4b592d1, 0xfdf2732f, 0x4436274e, 0x2561b3c8, + 0xebdd4aa6, 0xa0136c00, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_true_values_c() { + // Test vector 4 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + let seed = [ + 0, 0xff, 0, 0, 0, 0, 0, 0, 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 expected = [ + 0xfb4dd572, 0x4bc42ef1, 0xdf922636, 0x327f1394, 0xa78dea8f, 0x5e269039, 0xa1bebbc1, + 0xcaf09aae, 0xa25ab213, 0x48a6b46c, 0x1b9d9bcb, 0x092c5be6, 0x546ca624, 0x1bec45d5, + 0x87f47473, 0x96f0992e, + ]; + let expected_end = 3 * 16; + let mut results = [0u32; 16]; + + // Test block 2 by skipping block 0 and 1 + let mut rng1 = ChaChaRng::from_seed(seed); + for _ in 0..32 { + rng1.next_u32(); + } + for i in results.iter_mut() { + *i = rng1.next_u32(); + } + assert_eq!(results, expected); + assert_eq!(rng1.get_word_pos(), expected_end); + + // Test block 2 by using `set_word_pos` + let mut rng2 = ChaChaRng::from_seed(seed); + rng2.set_word_pos(2 * 16); + for i in results.iter_mut() { + *i = rng2.next_u32(); + } + assert_eq!(results, expected); + assert_eq!(rng2.get_word_pos(), expected_end); + + // Test skipping behaviour with other types + let mut buf = [0u8; 32]; + rng2.fill_bytes(&mut buf[..]); + assert_eq!(rng2.get_word_pos(), expected_end + 8); + rng2.fill_bytes(&mut buf[0..25]); + assert_eq!(rng2.get_word_pos(), expected_end + 15); + rng2.next_u64(); + assert_eq!(rng2.get_word_pos(), expected_end + 17); + rng2.next_u32(); + rng2.next_u64(); + assert_eq!(rng2.get_word_pos(), expected_end + 20); + rng2.fill_bytes(&mut buf[0..1]); + assert_eq!(rng2.get_word_pos(), expected_end + 21); + } + + #[test] + fn test_chacha_multiple_blocks() { + let seed = [ + 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 0, 0, + ]; + let mut rng = ChaChaRng::from_seed(seed); + + // Store the 17*i-th 32-bit word, + // i.e., the i-th word of the i-th 16-word block + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + for _ in 0..16 { + rng.next_u32(); + } + } + let expected = [ + 0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036, 0x49884684, 0x64efec72, 0x4be2d186, + 0x3615b384, 0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530, 0x2c5bad8f, 0x898881dc, + 0x5f1c86d9, 0xc1f8e7f4, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_true_bytes() { + let seed = [0u8; 32]; + let mut rng = ChaChaRng::from_seed(seed); + let mut results = [0u8; 32]; + rng.fill_bytes(&mut results); + let expected = [ + 118, 184, 224, 173, 160, 241, 61, 144, 64, 93, 106, 229, 83, 134, 189, 40, 189, 210, + 25, 184, 160, 141, 237, 26, 168, 54, 239, 204, 139, 119, 13, 199, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_nonce() { + // Test vector 5 from + // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 + // Although we do not support setting a nonce, we try it here anyway so + // we can use this test vector. + let seed = [0u8; 32]; + let mut rng = ChaChaRng::from_seed(seed); + // 96-bit nonce in LE order is: 0,0,0,0, 0,0,0,0, 0,0,0,2 + rng.set_stream(2u64 << (24 + 32)); + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected = [ + 0x374dc6c2, 0x3736d58c, 0xb904e24a, 0xcd3f93ef, 0x88228b1a, 0x96a4dfb3, 0x5b76ab72, + 0xc727ee54, 0x0e0e978a, 0xf3145c95, 0x1b748ea8, 0xf786c297, 0x99c28f5f, 0x628314e8, + 0x398a19fa, 0x6ded1b53, + ]; + assert_eq!(results, expected); + } + + #[test] + fn test_chacha_clone_streams() { + let seed = [ + 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 0, 0, + ]; + let mut rng = ChaChaRng::from_seed(seed); + let mut clone = rng.clone(); + for _ in 0..16 { + assert_eq!(rng.next_u64(), clone.next_u64()); + } + + rng.set_stream(51); + for _ in 0..7 { + assert!(rng.next_u32() != clone.next_u32()); + } + clone.set_stream(51); // switch part way through block + for _ in 7..16 { + assert_eq!(rng.next_u32(), clone.next_u32()); + } + } + + #[test] + fn test_chacha_word_pos_wrap_exact() { + use super::{BUF_BLOCKS, BLOCK_WORDS}; + let mut rng = ChaChaRng::from_seed(Default::default()); + // refilling the buffer in set_word_pos will wrap the block counter to 0 + let last_block = (1 << 68) - u128::from(BUF_BLOCKS * BLOCK_WORDS); + rng.set_word_pos(last_block); + assert_eq!(rng.get_word_pos(), last_block); + } + + #[test] + fn test_chacha_word_pos_wrap_excess() { + use super::BLOCK_WORDS; + let mut rng = ChaChaRng::from_seed(Default::default()); + // refilling the buffer in set_word_pos will wrap the block counter past 0 + let last_block = (1 << 68) - u128::from(BLOCK_WORDS); + rng.set_word_pos(last_block); + assert_eq!(rng.get_word_pos(), last_block); + } + + #[test] + fn test_chacha_word_pos_zero() { + let mut rng = ChaChaRng::from_seed(Default::default()); + assert_eq!(rng.get_word_pos(), 0); + rng.set_word_pos(0); + assert_eq!(rng.get_word_pos(), 0); + } +} diff --git a/vendor/rand_chacha/src/guts.rs b/vendor/rand_chacha/src/guts.rs new file mode 100644 index 0000000000..27ff957a92 --- /dev/null +++ b/vendor/rand_chacha/src/guts.rs @@ -0,0 +1,252 @@ +// Copyright 2019 The CryptoCorrosion Contributors +// Copyright 2020 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The ChaCha random number generator. + +use ppv_lite86::{dispatch, dispatch_light128}; + +pub use ppv_lite86::Machine; +use ppv_lite86::{vec128_storage, ArithOps, BitOps32, LaneWords4, MultiLane, StoreBytes, Vec4}; + +pub(crate) const BLOCK: usize = 64; +pub(crate) const BLOCK64: u64 = BLOCK as u64; +const LOG2_BUFBLOCKS: u64 = 2; +const BUFBLOCKS: u64 = 1 << LOG2_BUFBLOCKS; +pub(crate) const BUFSZ64: u64 = BLOCK64 * BUFBLOCKS; +pub(crate) const BUFSZ: usize = BUFSZ64 as usize; + +#[derive(Clone, PartialEq, Eq)] +pub struct ChaCha { + pub(crate) b: vec128_storage, + pub(crate) c: vec128_storage, + pub(crate) d: vec128_storage, +} + +#[derive(Clone)] +pub struct State { + pub(crate) a: V, + pub(crate) b: V, + pub(crate) c: V, + pub(crate) d: V, +} + +#[inline(always)] +pub(crate) fn round(mut x: State) -> State { + x.a += x.b; + x.d = (x.d ^ x.a).rotate_each_word_right16(); + x.c += x.d; + x.b = (x.b ^ x.c).rotate_each_word_right20(); + x.a += x.b; + x.d = (x.d ^ x.a).rotate_each_word_right24(); + x.c += x.d; + x.b = (x.b ^ x.c).rotate_each_word_right25(); + x +} + +#[inline(always)] +pub(crate) fn diagonalize(mut x: State) -> State { + x.b = x.b.shuffle_lane_words3012(); + x.c = x.c.shuffle_lane_words2301(); + x.d = x.d.shuffle_lane_words1230(); + x +} +#[inline(always)] +pub(crate) fn undiagonalize(mut x: State) -> State { + x.b = x.b.shuffle_lane_words1230(); + x.c = x.c.shuffle_lane_words2301(); + x.d = x.d.shuffle_lane_words3012(); + x +} + +impl ChaCha { + #[inline(always)] + pub fn new(key: &[u8; 32], nonce: &[u8]) -> Self { + init_chacha(key, nonce) + } + + #[inline(always)] + fn pos64(&self, m: M) -> u64 { + let d: M::u32x4 = m.unpack(self.d); + ((d.extract(1) as u64) << 32) | d.extract(0) as u64 + } + + /// Produce 4 blocks of output, advancing the state + #[inline(always)] + pub fn refill4(&mut self, drounds: u32, out: &mut [u8; BUFSZ]) { + refill_wide(self, drounds, out) + } + + #[inline(always)] + pub fn set_stream_param(&mut self, param: u32, value: u64) { + set_stream_param(self, param, value) + } + + #[inline(always)] + pub fn get_stream_param(&self, param: u32) -> u64 { + get_stream_param(self, param) + } + + /// Return whether rhs is equal in all parameters except current 64-bit position. + #[inline] + pub fn stream64_eq(&self, rhs: &Self) -> bool { + let self_d: [u32; 4] = self.d.into(); + let rhs_d: [u32; 4] = rhs.d.into(); + self.b == rhs.b && self.c == rhs.c && self_d[3] == rhs_d[3] && self_d[2] == rhs_d[2] + } +} + +#[allow(clippy::many_single_char_names)] +#[inline(always)] +fn refill_wide_impl( + m: Mach, state: &mut ChaCha, drounds: u32, out: &mut [u8; BUFSZ], +) { + let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]); + let mut pos = state.pos64(m); + let d0: Mach::u32x4 = m.unpack(state.d); + pos = pos.wrapping_add(1); + let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + pos = pos.wrapping_add(1); + let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + pos = pos.wrapping_add(1); + let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + + let b = m.unpack(state.b); + let c = m.unpack(state.c); + let mut x = State { + a: Mach::u32x4x4::from_lanes([k, k, k, k]), + b: Mach::u32x4x4::from_lanes([b, b, b, b]), + c: Mach::u32x4x4::from_lanes([c, c, c, c]), + d: m.unpack(Mach::u32x4x4::from_lanes([d0, d1, d2, d3]).into()), + }; + for _ in 0..drounds { + x = round(x); + x = undiagonalize(round(diagonalize(x))); + } + let mut pos = state.pos64(m); + let d0: Mach::u32x4 = m.unpack(state.d); + pos = pos.wrapping_add(1); + let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + pos = pos.wrapping_add(1); + let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + pos = pos.wrapping_add(1); + let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + pos = pos.wrapping_add(1); + let d4 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0); + + let (a, b, c, d) = ( + x.a.to_lanes(), + x.b.to_lanes(), + x.c.to_lanes(), + x.d.to_lanes(), + ); + let sb = m.unpack(state.b); + let sc = m.unpack(state.c); + let sd = [m.unpack(state.d), d1, d2, d3]; + state.d = d4.into(); + let mut words = out.chunks_exact_mut(16); + for ((((&a, &b), &c), &d), &sd) in a.iter().zip(&b).zip(&c).zip(&d).zip(&sd) { + (a + k).write_le(words.next().unwrap()); + (b + sb).write_le(words.next().unwrap()); + (c + sc).write_le(words.next().unwrap()); + (d + sd).write_le(words.next().unwrap()); + } +} + +dispatch!(m, Mach, { + fn refill_wide(state: &mut ChaCha, drounds: u32, out: &mut [u8; BUFSZ]) { + refill_wide_impl(m, state, drounds, out); + } +}); + +// Single-block, rounds-only; shared by try_apply_keystream for tails shorter than BUFSZ +// and XChaCha's setup step. +dispatch!(m, Mach, { + fn refill_narrow_rounds(state: &mut ChaCha, drounds: u32) -> State { + let k: Mach::u32x4 = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]); + let mut x = State { + a: k, + b: m.unpack(state.b), + c: m.unpack(state.c), + d: m.unpack(state.d), + }; + for _ in 0..drounds { + x = round(x); + x = undiagonalize(round(diagonalize(x))); + } + State { + a: x.a.into(), + b: x.b.into(), + c: x.c.into(), + d: x.d.into(), + } + } +}); + +dispatch_light128!(m, Mach, { + fn set_stream_param(state: &mut ChaCha, param: u32, value: u64) { + let d: Mach::u32x4 = m.unpack(state.d); + state.d = d + .insert((value >> 32) as u32, (param << 1) | 1) + .insert(value as u32, param << 1) + .into(); + } +}); + +dispatch_light128!(m, Mach, { + fn get_stream_param(state: &ChaCha, param: u32) -> u64 { + let d: Mach::u32x4 = m.unpack(state.d); + ((d.extract((param << 1) | 1) as u64) << 32) | d.extract(param << 1) as u64 + } +}); + +fn read_u32le(xs: &[u8]) -> u32 { + assert_eq!(xs.len(), 4); + u32::from(xs[0]) | (u32::from(xs[1]) << 8) | (u32::from(xs[2]) << 16) | (u32::from(xs[3]) << 24) +} + +dispatch_light128!(m, Mach, { + fn init_chacha(key: &[u8; 32], nonce: &[u8]) -> ChaCha { + let ctr_nonce = [ + 0, + if nonce.len() == 12 { + read_u32le(&nonce[0..4]) + } else { + 0 + }, + read_u32le(&nonce[nonce.len() - 8..nonce.len() - 4]), + read_u32le(&nonce[nonce.len() - 4..]), + ]; + let key0: Mach::u32x4 = m.read_le(&key[..16]); + let key1: Mach::u32x4 = m.read_le(&key[16..]); + ChaCha { + b: key0.into(), + c: key1.into(), + d: ctr_nonce.into(), + } + } +}); + +dispatch_light128!(m, Mach, { + fn init_chacha_x(key: &[u8; 32], nonce: &[u8; 24], rounds: u32) -> ChaCha { + let key0: Mach::u32x4 = m.read_le(&key[..16]); + let key1: Mach::u32x4 = m.read_le(&key[16..]); + let nonce0: Mach::u32x4 = m.read_le(&nonce[..16]); + let mut state = ChaCha { + b: key0.into(), + c: key1.into(), + d: nonce0.into(), + }; + let x = refill_narrow_rounds(&mut state, rounds); + let ctr_nonce1 = [0, 0, read_u32le(&nonce[16..20]), read_u32le(&nonce[20..24])]; + state.b = x.a; + state.c = x.d; + state.d = ctr_nonce1.into(); + state + } +}); diff --git a/vendor/rand_chacha/src/lib.rs b/vendor/rand_chacha/src/lib.rs new file mode 100644 index 0000000000..24125b45e1 --- /dev/null +++ b/vendor/rand_chacha/src/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The ChaCha random number generator. + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![cfg_attr(not(feature = "std"), no_std)] + +pub use rand_core; + +mod chacha; +mod guts; + +pub use crate::chacha::{ + ChaCha12Core, ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Core, ChaCha8Rng, +}; + +/// ChaCha with 20 rounds +pub type ChaChaRng = ChaCha20Rng; +/// ChaCha with 20 rounds, low-level interface +pub type ChaChaCore = ChaCha20Core; diff --git a/vendor/rand_core/.cargo-checksum.json b/vendor/rand_core/.cargo-checksum.json new file mode 100644 index 0000000000..140f5b6ca7 --- /dev/null +++ b/vendor/rand_core/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"bf45fe5169dfbec63635b1fc4b6d51f3ec06fbc034ede0791c16a5878db2444f","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.toml":"a319b64f513a62f2250165a4f4d578d04b6af127ce067328f0a9373b0ff5a1aa","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"bb3bd3831adc9eaabbcea108ab7f02f5837e9d2f81e872ffd7d340ad466df4de","src/block.rs":"09c479be71069f757e7a03d20078d26ac6acfe922a3207359a9c6ff48ccbcc65","src/error.rs":"0b6d5a188a256fa367dfa368e7dd846b58977a957489c03902307eb78ce4c9e8","src/impls.rs":"d6a97255d92c06bdd1a54590648bbe4cfb41111ac9e761496baf6b7eb5e92f6a","src/le.rs":"f302239d09cc8d915aa8d4fe46c32c8981900cb20d42b12eef9c34e2e820bc88","src/lib.rs":"40476377ed3da9e3589f058aaf8ec27ffeb12b0b179240a31259dc7f816fce5f","src/os.rs":"47849479e19c43dd01259eb14be7b4daf8474d23567dc32a1547c10b108b7069"},"package":"34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"} \ No newline at end of file diff --git a/vendor/rand_core/CHANGELOG.md b/vendor/rand_core/CHANGELOG.md new file mode 100644 index 0000000000..23d1fa5a1d --- /dev/null +++ b/vendor/rand_core/CHANGELOG.md @@ -0,0 +1,84 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.6.2] - 2021-02-12 +### Fixed +- Fixed assertions in `le::read_u32_into` and `le::read_u64_into` which could + have allowed buffers not to be fully populated (#1096) + +## [0.6.1] - 2021-01-03 +### Fixed +- Avoid panic when using `RngCore::seed_from_u64` with a seed which is not a + multiple of four (#1082) +### Other +- Enable all stable features in the playground (#1081) + +## [0.6.0] - 2020-12-08 +### Breaking changes +- Bump MSRV to 1.36, various code improvements (#1011) +- Update to getrandom v0.2 (#1041) +- Fix: `next_u32_via_fill` and `next_u64_via_fill` now use LE as documented (#1061) + +### Other +- Reduce usage of `unsafe` (#962, #963, #1011) +- Annotate feature-gates in documentation (#1019) +- Document available error codes (#1061) +- Various documentation tweaks +- Fix some clippy warnings (#1036) +- Apply rustfmt (#926) + +## [0.5.1] - 2019-08-28 +- `OsRng` added to `rand_core` (#863) +- `Error::INTERNAL_START` and `Error::CUSTOM_START` constants (#864) +- `Error::raw_os_error` method (#864) +- `Debug` and `Display` formatting for `getrandom` error codes without `std` (#864) +### Changed +- `alloc` feature in `no_std` is available since Rust 1.36 (#856) +- Added `#[inline]` to `Error` conversion methods (#864) + +## [0.5.0] - 2019-06-06 +### Changed +- Enable testing with Miri and fix incorrect pointer usages (#779, #780, #781, #783, #784) +- Rewrite `Error` type and adjust API (#800) +- Adjust usage of `#[inline]` for `BlockRng` and `BlockRng64` + +## [0.4.0] - 2019-01-24 +### Changed +- Disable the `std` feature by default (#702) + +## [0.3.0] - 2018-09-24 +### Added +- Add `SeedableRng::seed_from_u64` for convenient seeding. (#537) + +## [0.2.1] - 2018-06-08 +### Added +- References to a `CryptoRng` now also implement `CryptoRng`. (#470) + +## [0.2.0] - 2018-05-21 +### Changed +- Enable the `std` feature by default. (#409) +- Remove `BlockRng{64}::inner` and `BlockRng::inner_mut`; instead making `core` public +- Change `BlockRngCore::Results` bound to also require `AsMut<[Self::Item]>`. (#419) +### Added +- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419) +- Implement `std::io::Read` for RngCore. (#434) + +## [0.1.0] - 2018-04-17 +(Split out of the Rand crate, changes here are relative to rand 0.4.2.) +### Added +- `RngCore` and `SeedableRng` are now part of `rand_core`. (#288) +- Add modules to help implementing RNGs `impl` and `le`. (#209, #228) +- Add `Error` and `ErrorKind`. (#225) +- Add `CryptoRng` marker trait. (#273) +- Add `BlockRngCore` trait. (#281) +- Add `BlockRng` and `BlockRng64` wrappers to help implementations. (#281, #325) +- Add `RngCore::try_fill_bytes`. (#225) +### Changed +- Revise the `SeedableRng` trait. (#233) +- Remove default implementations for `RngCore::next_u64` and `RngCore::fill_bytes`. (#288) + +## [0.0.1] - 2017-09-14 (yanked) +Experimental version as part of the rand crate refactor. diff --git a/vendor/rand_core/COPYRIGHT b/vendor/rand_core/COPYRIGHT new file mode 100644 index 0000000000..468d907caf --- /dev/null +++ b/vendor/rand_core/COPYRIGHT @@ -0,0 +1,12 @@ +Copyrights in the Rand project are retained by their contributors. No +copyright assignment is required to contribute to the Rand project. + +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), Rand is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + +The Rand project includes code from the Rust project +published under these same licenses. diff --git a/vendor/rand_core/Cargo.toml b/vendor/rand_core/Cargo.toml new file mode 100644 index 0000000000..51b8385ead --- /dev/null +++ b/vendor/rand_core/Cargo.toml @@ -0,0 +1,44 @@ +# 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 = "rand_core" +version = "0.6.2" +authors = ["The Rand Project Developers", "The Rust Project Developers"] +description = "Core random number generator traits and tools for implementation.\n" +homepage = "https://rust-random.github.io/book" +documentation = "https://docs.rs/rand_core" +readme = "README.md" +keywords = ["random", "rng"] +categories = ["algorithms", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/rand" +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "doc_cfg"] + +[package.metadata.playground] +all-features = true +[dependencies.getrandom] +version = "0.2" +optional = true + +[dependencies.serde] +version = "1" +features = ["derive"] +optional = true + +[features] +alloc = [] +serde1 = ["serde"] +std = ["alloc", "getrandom", "getrandom/std"] diff --git a/vendor/rand_core/LICENSE-APACHE b/vendor/rand_core/LICENSE-APACHE new file mode 100644 index 0000000000..17d74680f8 --- /dev/null +++ b/vendor/rand_core/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://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 + + https://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/rand_core/LICENSE-MIT b/vendor/rand_core/LICENSE-MIT new file mode 100644 index 0000000000..d93b5baf34 --- /dev/null +++ b/vendor/rand_core/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright 2018 Developers of the Rand project +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/rand_core/README.md b/vendor/rand_core/README.md new file mode 100644 index 0000000000..d32dd6853d --- /dev/null +++ b/vendor/rand_core/README.md @@ -0,0 +1,81 @@ +# rand_core + +[![Test Status](https://github.com/rust-random/rand/workflows/Tests/badge.svg?event=push)](https://github.com/rust-random/rand/actions) +[![Latest version](https://img.shields.io/crates/v/rand_core.svg)](https://crates.io/crates/rand_core) +[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) +[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_core) +[![API](https://docs.rs/rand_core/badge.svg)](https://docs.rs/rand_core) +[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements) + +Core traits and error types of the [rand] library, plus tools for implementing +RNGs. + +This crate is intended for use when implementing the core trait, `RngCore`; it +defines the core traits to be implemented as well as several small functions to +aid in their implementation and types required for error handling. + +The main [rand] crate re-exports most items defined in this crate, along with +tools to convert the integer samples generated by `RngCore` to many different +applications (including sampling from restricted ranges, conversion to floating +point, list permutations and secure initialisation of RNGs). Most users should +prefer to use the main [rand] crate. + +Links: + +- [API documentation (master)](https://rust-random.github.io/rand/rand_core) +- [API documentation (docs.rs)](https://docs.rs/rand_core) +- [Changelog](https://github.com/rust-random/rand/blob/master/rand_core/CHANGELOG.md) + +[rand]: https://crates.io/crates/rand + + +## Functionality + +The `rand_core` crate provides: + +- base random number generator traits +- error-reporting types +- functionality to aid implementation of RNGs + +The traits and error types are also available via `rand`. + +## Versions + +The current version is: +``` +rand_core = "0.6.0" +``` + +Rand libs have inter-dependencies and make use of the +[semver trick](https://github.com/dtolnay/semver-trick/) in order to make traits +compatible across crate versions. (This is especially important for `RngCore` +and `SeedableRng`.) A few crate releases are thus compatibility shims, +depending on the *next* lib version (e.g. `rand_core` versions `0.2.2` and +`0.3.1`). This means, for example, that `rand_core_0_4_0::SeedableRng` and +`rand_core_0_3_0::SeedableRng` are distinct, incompatible traits, which can +cause build errors. Usually, running `cargo update` is enough to fix any issues. + +## Crate Features + +`rand_core` supports `no_std` and `alloc`-only configurations, as well as full +`std` functionality. The differences between `no_std` and full `std` are small, +comprising `RngCore` support for `Box` types where `R: RngCore`, +`std::io::Read` support for types supporting `RngCore`, and +extensions to the `Error` type's functionality. + +The `std` feature is *not enabled by default*. This is primarily to avoid build +problems where one crate implicitly requires `rand_core` with `std` support and +another crate requires `rand` *without* `std` support. However, the `rand` crate +continues to enable `std` support by default, both for itself and `rand_core`. + +The `serde1` feature can be used to derive `Serialize` and `Deserialize` for RNG +implementations that use the `BlockRng` or `BlockRng64` wrappers. + + +# License + +`rand_core` is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and +[COPYRIGHT](COPYRIGHT) for details. diff --git a/vendor/rand_core/src/block.rs b/vendor/rand_core/src/block.rs new file mode 100644 index 0000000000..005d071fbb --- /dev/null +++ b/vendor/rand_core/src/block.rs @@ -0,0 +1,431 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The `BlockRngCore` trait and implementation helpers +//! +//! The [`BlockRngCore`] trait exists to assist in the implementation of RNGs +//! which generate a block of data in a cache instead of returning generated +//! values directly. +//! +//! Usage of this trait is optional, but provides two advantages: +//! implementations only need to concern themselves with generation of the +//! block, not the various [`RngCore`] methods (especially [`fill_bytes`], where +//! the optimal implementations are not trivial), and this allows +//! `ReseedingRng` (see [`rand`](https://docs.rs/rand) crate) perform periodic +//! reseeding with very low overhead. +//! +//! # Example +//! +//! ```no_run +//! use rand_core::{RngCore, SeedableRng}; +//! use rand_core::block::{BlockRngCore, BlockRng}; +//! +//! struct MyRngCore; +//! +//! impl BlockRngCore for MyRngCore { +//! type Item = u32; +//! type Results = [u32; 16]; +//! +//! fn generate(&mut self, results: &mut Self::Results) { +//! unimplemented!() +//! } +//! } +//! +//! impl SeedableRng for MyRngCore { +//! type Seed = [u8; 32]; +//! fn from_seed(seed: Self::Seed) -> Self { +//! unimplemented!() +//! } +//! } +//! +//! // optionally, also implement CryptoRng for MyRngCore +//! +//! // Final RNG. +//! let mut rng = BlockRng::::seed_from_u64(0); +//! println!("First value: {}", rng.next_u32()); +//! ``` +//! +//! [`BlockRngCore`]: crate::block::BlockRngCore +//! [`fill_bytes`]: RngCore::fill_bytes + +use crate::impls::{fill_via_u32_chunks, fill_via_u64_chunks}; +use crate::{CryptoRng, Error, RngCore, SeedableRng}; +use core::convert::AsRef; +use core::fmt; +#[cfg(feature = "serde1")] +use serde::{Deserialize, Serialize}; + +/// A trait for RNGs which do not generate random numbers individually, but in +/// blocks (typically `[u32; N]`). This technique is commonly used by +/// cryptographic RNGs to improve performance. +/// +/// See the [module][crate::block] documentation for details. +pub trait BlockRngCore { + /// Results element type, e.g. `u32`. + type Item; + + /// Results type. This is the 'block' an RNG implementing `BlockRngCore` + /// generates, which will usually be an array like `[u32; 16]`. + type Results: AsRef<[Self::Item]> + AsMut<[Self::Item]> + Default; + + /// Generate a new block of results. + fn generate(&mut self, results: &mut Self::Results); +} + +/// A wrapper type implementing [`RngCore`] for some type implementing +/// [`BlockRngCore`] with `u32` array buffer; i.e. this can be used to implement +/// a full RNG from just a `generate` function. +/// +/// The `core` field may be accessed directly but the results buffer may not. +/// PRNG implementations can simply use a type alias +/// (`pub type MyRng = BlockRng;`) but might prefer to use a +/// wrapper type (`pub struct MyRng(BlockRng);`); the latter must +/// re-implement `RngCore` but hides the implementation details and allows +/// extra functionality to be defined on the RNG +/// (e.g. `impl MyRng { fn set_stream(...){...} }`). +/// +/// `BlockRng` has heavily optimized implementations of the [`RngCore`] methods +/// reading values from the results buffer, as well as +/// calling [`BlockRngCore::generate`] directly on the output array when +/// [`fill_bytes`] / [`try_fill_bytes`] is called on a large array. These methods +/// also handle the bookkeeping of when to generate a new batch of values. +/// +/// No whole generated `u32` values are thown away and all values are consumed +/// in-order. [`next_u32`] simply takes the next available `u32` value. +/// [`next_u64`] is implemented by combining two `u32` values, least +/// significant first. [`fill_bytes`] and [`try_fill_bytes`] consume a whole +/// number of `u32` values, converting each `u32` to a byte slice in +/// little-endian order. If the requested byte length is not a multiple of 4, +/// some bytes will be discarded. +/// +/// See also [`BlockRng64`] which uses `u64` array buffers. Currently there is +/// no direct support for other buffer types. +/// +/// For easy initialization `BlockRng` also implements [`SeedableRng`]. +/// +/// [`next_u32`]: RngCore::next_u32 +/// [`next_u64`]: RngCore::next_u64 +/// [`fill_bytes`]: RngCore::fill_bytes +/// [`try_fill_bytes`]: RngCore::try_fill_bytes +#[derive(Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct BlockRng { + results: R::Results, + index: usize, + /// The *core* part of the RNG, implementing the `generate` function. + pub core: R, +} + +// Custom Debug implementation that does not expose the contents of `results`. +impl fmt::Debug for BlockRng { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BlockRng") + .field("core", &self.core) + .field("result_len", &self.results.as_ref().len()) + .field("index", &self.index) + .finish() + } +} + +impl BlockRng { + /// Create a new `BlockRng` from an existing RNG implementing + /// `BlockRngCore`. Results will be generated on first use. + #[inline] + pub fn new(core: R) -> BlockRng { + let results_empty = R::Results::default(); + BlockRng { + core, + index: results_empty.as_ref().len(), + results: results_empty, + } + } + + /// Get the index into the result buffer. + /// + /// If this is equal to or larger than the size of the result buffer then + /// the buffer is "empty" and `generate()` must be called to produce new + /// results. + #[inline(always)] + pub fn index(&self) -> usize { + self.index + } + + /// Reset the number of available results. + /// This will force a new set of results to be generated on next use. + #[inline] + pub fn reset(&mut self) { + self.index = self.results.as_ref().len(); + } + + /// Generate a new set of results immediately, setting the index to the + /// given value. + #[inline] + pub fn generate_and_set(&mut self, index: usize) { + assert!(index < self.results.as_ref().len()); + self.core.generate(&mut self.results); + self.index = index; + } +} + +impl> RngCore for BlockRng +where + ::Results: AsRef<[u32]> + AsMut<[u32]>, +{ + #[inline] + fn next_u32(&mut self) -> u32 { + if self.index >= self.results.as_ref().len() { + self.generate_and_set(0); + } + + let value = self.results.as_ref()[self.index]; + self.index += 1; + value + } + + #[inline] + fn next_u64(&mut self) -> u64 { + let read_u64 = |results: &[u32], index| { + let data = &results[index..=index + 1]; + u64::from(data[1]) << 32 | u64::from(data[0]) + }; + + let len = self.results.as_ref().len(); + + let index = self.index; + if index < len - 1 { + self.index += 2; + // Read an u64 from the current index + read_u64(self.results.as_ref(), index) + } else if index >= len { + self.generate_and_set(2); + read_u64(self.results.as_ref(), 0) + } else { + let x = u64::from(self.results.as_ref()[len - 1]); + self.generate_and_set(1); + let y = u64::from(self.results.as_ref()[0]); + (y << 32) | x + } + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + let mut read_len = 0; + while read_len < dest.len() { + if self.index >= self.results.as_ref().len() { + self.generate_and_set(0); + } + let (consumed_u32, filled_u8) = + fill_via_u32_chunks(&self.results.as_ref()[self.index..], &mut dest[read_len..]); + + self.index += consumed_u32; + read_len += filled_u8; + } + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +impl SeedableRng for BlockRng { + type Seed = R::Seed; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + Self::new(R::from_seed(seed)) + } + + #[inline(always)] + fn seed_from_u64(seed: u64) -> Self { + Self::new(R::seed_from_u64(seed)) + } + + #[inline(always)] + fn from_rng(rng: S) -> Result { + Ok(Self::new(R::from_rng(rng)?)) + } +} + +/// A wrapper type implementing [`RngCore`] for some type implementing +/// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement +/// a full RNG from just a `generate` function. +/// +/// This is similar to [`BlockRng`], but specialized for algorithms that operate +/// on `u64` values. +/// +/// No whole generated `u64` values are thrown away and all values are consumed +/// in-order. [`next_u64`] simply takes the next available `u64` value. +/// [`next_u32`] is however a bit special: half of a `u64` is consumed, leaving +/// the other half in the buffer. If the next function called is [`next_u32`] +/// then the other half is then consumed, however both [`next_u64`] and +/// [`fill_bytes`] discard the rest of any half-consumed `u64`s when called. +/// +/// [`fill_bytes`] and [`try_fill_bytes`] consume a whole number of `u64` +/// values. If the requested length is not a multiple of 8, some bytes will be +/// discarded. +/// +/// [`next_u32`]: RngCore::next_u32 +/// [`next_u64`]: RngCore::next_u64 +/// [`fill_bytes`]: RngCore::fill_bytes +/// [`try_fill_bytes`]: RngCore::try_fill_bytes +#[derive(Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] +pub struct BlockRng64 { + results: R::Results, + index: usize, + half_used: bool, // true if only half of the previous result is used + /// The *core* part of the RNG, implementing the `generate` function. + pub core: R, +} + +// Custom Debug implementation that does not expose the contents of `results`. +impl fmt::Debug for BlockRng64 { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BlockRng64") + .field("core", &self.core) + .field("result_len", &self.results.as_ref().len()) + .field("index", &self.index) + .field("half_used", &self.half_used) + .finish() + } +} + +impl BlockRng64 { + /// Create a new `BlockRng` from an existing RNG implementing + /// `BlockRngCore`. Results will be generated on first use. + #[inline] + pub fn new(core: R) -> BlockRng64 { + let results_empty = R::Results::default(); + BlockRng64 { + core, + index: results_empty.as_ref().len(), + half_used: false, + results: results_empty, + } + } + + /// Get the index into the result buffer. + /// + /// If this is equal to or larger than the size of the result buffer then + /// the buffer is "empty" and `generate()` must be called to produce new + /// results. + #[inline(always)] + pub fn index(&self) -> usize { + self.index + } + + /// Reset the number of available results. + /// This will force a new set of results to be generated on next use. + #[inline] + pub fn reset(&mut self) { + self.index = self.results.as_ref().len(); + self.half_used = false; + } + + /// Generate a new set of results immediately, setting the index to the + /// given value. + #[inline] + pub fn generate_and_set(&mut self, index: usize) { + assert!(index < self.results.as_ref().len()); + self.core.generate(&mut self.results); + self.index = index; + self.half_used = false; + } +} + +impl> RngCore for BlockRng64 +where + ::Results: AsRef<[u64]> + AsMut<[u64]>, +{ + #[inline] + fn next_u32(&mut self) -> u32 { + let mut index = self.index * 2 - self.half_used as usize; + if index >= self.results.as_ref().len() * 2 { + self.core.generate(&mut self.results); + self.index = 0; + // `self.half_used` is by definition `false` + self.half_used = false; + index = 0; + } + + self.half_used = !self.half_used; + self.index += self.half_used as usize; + + // Index as if this is a u32 slice. + unsafe { + let results = &*(self.results.as_ref() as *const [u64] as *const [u32]); + if cfg!(target_endian = "little") { + *results.get_unchecked(index) + } else { + *results.get_unchecked(index ^ 1) + } + } + } + + #[inline] + fn next_u64(&mut self) -> u64 { + if self.index >= self.results.as_ref().len() { + self.core.generate(&mut self.results); + self.index = 0; + } + + let value = self.results.as_ref()[self.index]; + self.index += 1; + self.half_used = false; + value + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + let mut read_len = 0; + self.half_used = false; + while read_len < dest.len() { + if self.index as usize >= self.results.as_ref().len() { + self.core.generate(&mut self.results); + self.index = 0; + } + + let (consumed_u64, filled_u8) = fill_via_u64_chunks( + &self.results.as_ref()[self.index as usize..], + &mut dest[read_len..], + ); + + self.index += consumed_u64; + read_len += filled_u8; + } + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +impl SeedableRng for BlockRng64 { + type Seed = R::Seed; + + #[inline(always)] + fn from_seed(seed: Self::Seed) -> Self { + Self::new(R::from_seed(seed)) + } + + #[inline(always)] + fn seed_from_u64(seed: u64) -> Self { + Self::new(R::seed_from_u64(seed)) + } + + #[inline(always)] + fn from_rng(rng: S) -> Result { + Ok(Self::new(R::from_rng(rng)?)) + } +} + +impl CryptoRng for BlockRng {} diff --git a/vendor/rand_core/src/error.rs b/vendor/rand_core/src/error.rs new file mode 100644 index 0000000000..a64c430da8 --- /dev/null +++ b/vendor/rand_core/src/error.rs @@ -0,0 +1,228 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Error types + +use core::fmt; +use core::num::NonZeroU32; + +#[cfg(feature = "std")] use std::boxed::Box; + +/// Error type of random number generators +/// +/// In order to be compatible with `std` and `no_std`, this type has two +/// possible implementations: with `std` a boxed `Error` trait object is stored, +/// while with `no_std` we merely store an error code. +pub struct Error { + #[cfg(feature = "std")] + inner: Box, + #[cfg(not(feature = "std"))] + code: NonZeroU32, +} + +impl Error { + /// Codes at or above this point can be used by users to define their own + /// custom errors. + /// + /// This has a fixed value of `(1 << 31) + (1 << 30) = 0xC000_0000`, + /// therefore the number of values available for custom codes is `1 << 30`. + /// + /// This is identical to [`getrandom::Error::CUSTOM_START`](https://docs.rs/getrandom/latest/getrandom/struct.Error.html#associatedconstant.CUSTOM_START). + pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30); + /// Codes below this point represent OS Errors (i.e. positive i32 values). + /// Codes at or above this point, but below [`Error::CUSTOM_START`] are + /// reserved for use by the `rand` and `getrandom` crates. + /// + /// This is identical to [`getrandom::Error::INTERNAL_START`](https://docs.rs/getrandom/latest/getrandom/struct.Error.html#associatedconstant.INTERNAL_START). + pub const INTERNAL_START: u32 = 1 << 31; + + /// Construct from any type supporting `std::error::Error` + /// + /// Available only when configured with `std`. + /// + /// See also `From`, which is available with and without `std`. + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[inline] + pub fn new(err: E) -> Self + where + E: Into>, + { + Error { inner: err.into() } + } + + /// Reference the inner error (`std` only) + /// + /// When configured with `std`, this is a trivial operation and never + /// panics. Without `std`, this method is simply unavailable. + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[inline] + pub fn inner(&self) -> &(dyn std::error::Error + Send + Sync + 'static) { + &*self.inner + } + + /// Unwrap the inner error (`std` only) + /// + /// When configured with `std`, this is a trivial operation and never + /// panics. Without `std`, this method is simply unavailable. + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[inline] + pub fn take_inner(self) -> Box { + self.inner + } + + /// Extract the raw OS error code (if this error came from the OS) + /// + /// This method is identical to `std::io::Error::raw_os_error()`, except + /// that it works in `no_std` contexts. If this method returns `None`, the + /// error value can still be formatted via the `Diplay` implementation. + #[inline] + pub fn raw_os_error(&self) -> Option { + #[cfg(feature = "std")] + { + if let Some(e) = self.inner.downcast_ref::() { + return e.raw_os_error(); + } + } + match self.code() { + Some(code) if u32::from(code) < Self::INTERNAL_START => Some(u32::from(code) as i32), + _ => None, + } + } + + /// Retrieve the error code, if any. + /// + /// If this `Error` was constructed via `From`, then this method + /// will return this `NonZeroU32` code (for `no_std` this is always the + /// case). Otherwise, this method will return `None`. + #[inline] + pub fn code(&self) -> Option { + #[cfg(feature = "std")] + { + self.inner.downcast_ref::().map(|c| c.0) + } + #[cfg(not(feature = "std"))] + { + Some(self.code) + } + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + #[cfg(feature = "std")] + { + write!(f, "Error {{ inner: {:?} }}", self.inner) + } + #[cfg(all(feature = "getrandom", not(feature = "std")))] + { + getrandom::Error::from(self.code).fmt(f) + } + #[cfg(not(feature = "getrandom"))] + { + write!(f, "Error {{ code: {} }}", self.code) + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + #[cfg(feature = "std")] + { + write!(f, "{}", self.inner) + } + #[cfg(all(feature = "getrandom", not(feature = "std")))] + { + getrandom::Error::from(self.code).fmt(f) + } + #[cfg(not(feature = "getrandom"))] + { + write!(f, "error code {}", self.code) + } + } +} + +impl From for Error { + #[inline] + fn from(code: NonZeroU32) -> Self { + #[cfg(feature = "std")] + { + Error { + inner: Box::new(ErrorCode(code)), + } + } + #[cfg(not(feature = "std"))] + { + Error { code } + } + } +} + +#[cfg(feature = "getrandom")] +impl From for Error { + #[inline] + fn from(error: getrandom::Error) -> Self { + #[cfg(feature = "std")] + { + Error { + inner: Box::new(error), + } + } + #[cfg(not(feature = "std"))] + { + Error { code: error.code() } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + #[inline] + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.inner.source() + } +} + +#[cfg(feature = "std")] +impl From for std::io::Error { + #[inline] + fn from(error: Error) -> Self { + if let Some(code) = error.raw_os_error() { + std::io::Error::from_raw_os_error(code) + } else { + std::io::Error::new(std::io::ErrorKind::Other, error) + } + } +} + +#[cfg(feature = "std")] +#[derive(Debug, Copy, Clone)] +struct ErrorCode(NonZeroU32); + +#[cfg(feature = "std")] +impl fmt::Display for ErrorCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "error code {}", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ErrorCode {} + +#[cfg(test)] +mod test { + #[cfg(feature = "getrandom")] + #[test] + fn test_error_codes() { + // Make sure the values are the same as in `getrandom`. + assert_eq!(super::Error::CUSTOM_START, getrandom::Error::CUSTOM_START); + assert_eq!(super::Error::INTERNAL_START, getrandom::Error::INTERNAL_START); + } +} diff --git a/vendor/rand_core/src/impls.rs b/vendor/rand_core/src/impls.rs new file mode 100644 index 0000000000..2588a72ea3 --- /dev/null +++ b/vendor/rand_core/src/impls.rs @@ -0,0 +1,184 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Helper functions for implementing `RngCore` functions. +//! +//! For cross-platform reproducibility, these functions all use Little Endian: +//! least-significant part first. For example, `next_u64_via_u32` takes `u32` +//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32` +//! from `next_u64` in little-endian order, one should use `next_u64() as u32`. +//! +//! Byte-swapping (like the std `to_le` functions) is only needed to convert +//! to/from byte sequences, and since its purpose is reproducibility, +//! non-reproducible sources (e.g. `OsRng`) need not bother with it. + +use crate::RngCore; +use core::cmp::min; + +/// Implement `next_u64` via `next_u32`, little-endian order. +pub fn next_u64_via_u32(rng: &mut R) -> u64 { + // Use LE; we explicitly generate one value before the next. + let x = u64::from(rng.next_u32()); + let y = u64::from(rng.next_u32()); + (y << 32) | x +} + +/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order. +/// +/// The fastest way to fill a slice is usually to work as long as possible with +/// integers. That is why this method mostly uses `next_u64`, and only when +/// there are 4 or less bytes remaining at the end of the slice it uses +/// `next_u32` once. +pub fn fill_bytes_via_next(rng: &mut R, dest: &mut [u8]) { + let mut left = dest; + while left.len() >= 8 { + let (l, r) = { left }.split_at_mut(8); + left = r; + let chunk: [u8; 8] = rng.next_u64().to_le_bytes(); + l.copy_from_slice(&chunk); + } + let n = left.len(); + if n > 4 { + let chunk: [u8; 8] = rng.next_u64().to_le_bytes(); + left.copy_from_slice(&chunk[..n]); + } else if n > 0 { + let chunk: [u8; 4] = rng.next_u32().to_le_bytes(); + left.copy_from_slice(&chunk[..n]); + } +} + +macro_rules! fill_via_chunks { + ($src:expr, $dst:expr, $ty:ty) => {{ + const SIZE: usize = core::mem::size_of::<$ty>(); + let chunk_size_u8 = min($src.len() * SIZE, $dst.len()); + let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE; + + // The following can be replaced with safe code, but unfortunately it's + // ca. 8% slower. + if cfg!(target_endian = "little") { + unsafe { + core::ptr::copy_nonoverlapping( + $src.as_ptr() as *const u8, + $dst.as_mut_ptr(), + chunk_size_u8); + } + } else { + for (&n, chunk) in $src.iter().zip($dst.chunks_mut(SIZE)) { + let tmp = n.to_le(); + let src_ptr = &tmp as *const $ty as *const u8; + unsafe { + core::ptr::copy_nonoverlapping( + src_ptr, + chunk.as_mut_ptr(), + chunk.len()); + } + } + } + + (chunk_size, chunk_size_u8) + }}; +} + +/// Implement `fill_bytes` by reading chunks from the output buffer of a block +/// based RNG. +/// +/// The return values are `(consumed_u32, filled_u8)`. +/// +/// `filled_u8` is the number of filled bytes in `dest`, which may be less than +/// the length of `dest`. +/// `consumed_u32` is the number of words consumed from `src`, which is the same +/// as `filled_u8 / 4` rounded up. +/// +/// # Example +/// (from `IsaacRng`) +/// +/// ```ignore +/// fn fill_bytes(&mut self, dest: &mut [u8]) { +/// let mut read_len = 0; +/// while read_len < dest.len() { +/// if self.index >= self.rsl.len() { +/// self.isaac(); +/// } +/// +/// let (consumed_u32, filled_u8) = +/// impls::fill_via_u32_chunks(&mut self.rsl[self.index..], +/// &mut dest[read_len..]); +/// +/// self.index += consumed_u32; +/// read_len += filled_u8; +/// } +/// } +/// ``` +pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) { + fill_via_chunks!(src, dest, u32) +} + +/// Implement `fill_bytes` by reading chunks from the output buffer of a block +/// based RNG. +/// +/// The return values are `(consumed_u64, filled_u8)`. +/// `filled_u8` is the number of filled bytes in `dest`, which may be less than +/// the length of `dest`. +/// `consumed_u64` is the number of words consumed from `src`, which is the same +/// as `filled_u8 / 8` rounded up. +/// +/// See `fill_via_u32_chunks` for an example. +pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) { + fill_via_chunks!(src, dest, u64) +} + +/// Implement `next_u32` via `fill_bytes`, little-endian order. +pub fn next_u32_via_fill(rng: &mut R) -> u32 { + let mut buf = [0; 4]; + rng.fill_bytes(&mut buf); + u32::from_le_bytes(buf) +} + +/// Implement `next_u64` via `fill_bytes`, little-endian order. +pub fn next_u64_via_fill(rng: &mut R) -> u64 { + let mut buf = [0; 8]; + rng.fill_bytes(&mut buf); + u64::from_le_bytes(buf) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_fill_via_u32_chunks() { + let src = [1, 2, 3]; + let mut dst = [0u8; 11]; + assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11)); + assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]); + + let mut dst = [0u8; 13]; + assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12)); + assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]); + + let mut dst = [0u8; 5]; + assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5)); + assert_eq!(dst, [1, 0, 0, 0, 2]); + } + + #[test] + fn test_fill_via_u64_chunks() { + let src = [1, 2]; + let mut dst = [0u8; 11]; + assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11)); + assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]); + + let mut dst = [0u8; 17]; + assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16)); + assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]); + + let mut dst = [0u8; 5]; + assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5)); + assert_eq!(dst, [1, 0, 0, 0, 0]); + } +} diff --git a/vendor/rand_core/src/le.rs b/vendor/rand_core/src/le.rs new file mode 100644 index 0000000000..ed42e57f47 --- /dev/null +++ b/vendor/rand_core/src/le.rs @@ -0,0 +1,56 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Little-Endian utilities +//! +//! Little-Endian order has been chosen for internal usage; this makes some +//! useful functions available. + +use core::convert::TryInto; + +/// Reads unsigned 32 bit integers from `src` into `dst`. +#[inline] +pub fn read_u32_into(src: &[u8], dst: &mut [u32]) { + assert!(src.len() >= 4 * dst.len()); + for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(4)) { + *out = u32::from_le_bytes(chunk.try_into().unwrap()); + } +} + +/// Reads unsigned 64 bit integers from `src` into `dst`. +#[inline] +pub fn read_u64_into(src: &[u8], dst: &mut [u64]) { + assert!(src.len() >= 8 * dst.len()); + for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(8)) { + *out = u64::from_le_bytes(chunk.try_into().unwrap()); + } +} + +#[test] +fn test_read() { + let bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + + let mut buf = [0u32; 4]; + read_u32_into(&bytes, &mut buf); + assert_eq!(buf[0], 0x04030201); + assert_eq!(buf[3], 0x100F0E0D); + + let mut buf = [0u32; 3]; + read_u32_into(&bytes[1..13], &mut buf); // unaligned + assert_eq!(buf[0], 0x05040302); + assert_eq!(buf[2], 0x0D0C0B0A); + + let mut buf = [0u64; 2]; + read_u64_into(&bytes, &mut buf); + assert_eq!(buf[0], 0x0807060504030201); + assert_eq!(buf[1], 0x100F0E0D0C0B0A09); + + let mut buf = [0u64; 1]; + read_u64_into(&bytes[7..15], &mut buf); // unaligned + assert_eq!(buf[0], 0x0F0E0D0C0B0A0908); +} diff --git a/vendor/rand_core/src/lib.rs b/vendor/rand_core/src/lib.rs new file mode 100644 index 0000000000..7e847ae499 --- /dev/null +++ b/vendor/rand_core/src/lib.rs @@ -0,0 +1,497 @@ +// Copyright 2018 Developers of the Rand project. +// Copyright 2017-2018 The Rust Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Random number generation traits +//! +//! This crate is mainly of interest to crates publishing implementations of +//! [`RngCore`]. Other users are encouraged to use the [`rand`] crate instead +//! which re-exports the main traits and error types. +//! +//! [`RngCore`] is the core trait implemented by algorithmic pseudo-random number +//! generators and external random-number sources. +//! +//! [`SeedableRng`] is an extension trait for construction from fixed seeds and +//! other random number generators. +//! +//! [`Error`] is provided for error-handling. It is safe to use in `no_std` +//! environments. +//! +//! The [`impls`] and [`le`] sub-modules include a few small functions to assist +//! implementation of [`RngCore`]. +//! +//! [`rand`]: https://docs.rs/rand + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![no_std] + +use core::convert::AsMut; +use core::default::Default; + +#[cfg(feature = "std")] extern crate std; +#[cfg(feature = "alloc")] extern crate alloc; +#[cfg(feature = "alloc")] use alloc::boxed::Box; + +pub use error::Error; +#[cfg(feature = "getrandom")] pub use os::OsRng; + + +pub mod block; +mod error; +pub mod impls; +pub mod le; +#[cfg(feature = "getrandom")] mod os; + + +/// The core of a random number generator. +/// +/// This trait encapsulates the low-level functionality common to all +/// generators, and is the "back end", to be implemented by generators. +/// End users should normally use the `Rng` trait from the [`rand`] crate, +/// which is automatically implemented for every type implementing `RngCore`. +/// +/// Three different methods for generating random data are provided since the +/// optimal implementation of each is dependent on the type of generator. There +/// is no required relationship between the output of each; e.g. many +/// implementations of [`fill_bytes`] consume a whole number of `u32` or `u64` +/// values and drop any remaining unused bytes. The same can happen with the +/// [`next_u32`] and [`next_u64`] methods, implementations may discard some +/// random bits for efficiency. +/// +/// The [`try_fill_bytes`] method is a variant of [`fill_bytes`] allowing error +/// handling; it is not deemed sufficiently useful to add equivalents for +/// [`next_u32`] or [`next_u64`] since the latter methods are almost always used +/// with algorithmic generators (PRNGs), which are normally infallible. +/// +/// Algorithmic generators implementing [`SeedableRng`] should normally have +/// *portable, reproducible* output, i.e. fix Endianness when converting values +/// to avoid platform differences, and avoid making any changes which affect +/// output (except by communicating that the release has breaking changes). +/// +/// Typically implementators will implement only one of the methods available +/// in this trait directly, then use the helper functions from the +/// [`impls`] module to implement the other methods. +/// +/// It is recommended that implementations also implement: +/// +/// - `Debug` with a custom implementation which *does not* print any internal +/// state (at least, [`CryptoRng`]s should not risk leaking state through +/// `Debug`). +/// - `Serialize` and `Deserialize` (from Serde), preferably making Serde +/// support optional at the crate level in PRNG libs. +/// - `Clone`, if possible. +/// - *never* implement `Copy` (accidental copies may cause repeated values). +/// - *do not* implement `Default` for pseudorandom generators, but instead +/// implement [`SeedableRng`], to guide users towards proper seeding. +/// External / hardware RNGs can choose to implement `Default`. +/// - `Eq` and `PartialEq` could be implemented, but are probably not useful. +/// +/// # Example +/// +/// A simple example, obviously not generating very *random* output: +/// +/// ``` +/// #![allow(dead_code)] +/// use rand_core::{RngCore, Error, impls}; +/// +/// struct CountingRng(u64); +/// +/// impl RngCore for CountingRng { +/// fn next_u32(&mut self) -> u32 { +/// self.next_u64() as u32 +/// } +/// +/// fn next_u64(&mut self) -> u64 { +/// self.0 += 1; +/// self.0 +/// } +/// +/// fn fill_bytes(&mut self, dest: &mut [u8]) { +/// impls::fill_bytes_via_next(self, dest) +/// } +/// +/// fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { +/// Ok(self.fill_bytes(dest)) +/// } +/// } +/// ``` +/// +/// [`rand`]: https://docs.rs/rand +/// [`try_fill_bytes`]: RngCore::try_fill_bytes +/// [`fill_bytes`]: RngCore::fill_bytes +/// [`next_u32`]: RngCore::next_u32 +/// [`next_u64`]: RngCore::next_u64 +pub trait RngCore { + /// Return the next random `u32`. + /// + /// RNGs must implement at least one method from this trait directly. In + /// the case this method is not implemented directly, it can be implemented + /// using `self.next_u64() as u32` or via [`impls::next_u32_via_fill`]. + fn next_u32(&mut self) -> u32; + + /// Return the next random `u64`. + /// + /// RNGs must implement at least one method from this trait directly. In + /// the case this method is not implemented directly, it can be implemented + /// via [`impls::next_u64_via_u32`] or via [`impls::next_u64_via_fill`]. + fn next_u64(&mut self) -> u64; + + /// Fill `dest` with random data. + /// + /// RNGs must implement at least one method from this trait directly. In + /// the case this method is not implemented directly, it can be implemented + /// via [`impls::fill_bytes_via_next`] or + /// via [`RngCore::try_fill_bytes`]; if this generator can + /// fail the implementation must choose how best to handle errors here + /// (e.g. panic with a descriptive message or log a warning and retry a few + /// times). + /// + /// This method should guarantee that `dest` is entirely filled + /// with new data, and may panic if this is impossible + /// (e.g. reading past the end of a file that is being used as the + /// source of randomness). + fn fill_bytes(&mut self, dest: &mut [u8]); + + /// Fill `dest` entirely with random data. + /// + /// This is the only method which allows an RNG to report errors while + /// generating random data thus making this the primary method implemented + /// by external (true) RNGs (e.g. `OsRng`) which can fail. It may be used + /// directly to generate keys and to seed (infallible) PRNGs. + /// + /// Other than error handling, this method is identical to [`RngCore::fill_bytes`]; + /// thus this may be implemented using `Ok(self.fill_bytes(dest))` or + /// `fill_bytes` may be implemented with + /// `self.try_fill_bytes(dest).unwrap()` or more specific error handling. + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>; +} + +/// A marker trait used to indicate that an [`RngCore`] or [`BlockRngCore`] +/// implementation is supposed to be cryptographically secure. +/// +/// *Cryptographically secure generators*, also known as *CSPRNGs*, should +/// satisfy an additional properties over other generators: given the first +/// *k* bits of an algorithm's output +/// sequence, it should not be possible using polynomial-time algorithms to +/// predict the next bit with probability significantly greater than 50%. +/// +/// Some generators may satisfy an additional property, however this is not +/// required by this trait: if the CSPRNG's state is revealed, it should not be +/// computationally-feasible to reconstruct output prior to this. Some other +/// generators allow backwards-computation and are consided *reversible*. +/// +/// Note that this trait is provided for guidance only and cannot guarantee +/// suitability for cryptographic applications. In general it should only be +/// implemented for well-reviewed code implementing well-regarded algorithms. +/// +/// Note also that use of a `CryptoRng` does not protect against other +/// weaknesses such as seeding from a weak entropy source or leaking state. +/// +/// [`BlockRngCore`]: block::BlockRngCore +pub trait CryptoRng {} + +/// A random number generator that can be explicitly seeded. +/// +/// This trait encapsulates the low-level functionality common to all +/// pseudo-random number generators (PRNGs, or algorithmic generators). +/// +/// [`rand`]: https://docs.rs/rand +pub trait SeedableRng: Sized { + /// Seed type, which is restricted to types mutably-dereferencable as `u8` + /// arrays (we recommend `[u8; N]` for some `N`). + /// + /// It is recommended to seed PRNGs with a seed of at least circa 100 bits, + /// which means an array of `[u8; 12]` or greater to avoid picking RNGs with + /// partially overlapping periods. + /// + /// For cryptographic RNG's a seed of 256 bits is recommended, `[u8; 32]`. + /// + /// + /// # Implementing `SeedableRng` for RNGs with large seeds + /// + /// Note that the required traits `core::default::Default` and + /// `core::convert::AsMut` are not implemented for large arrays + /// `[u8; N]` with `N` > 32. To be able to implement the traits required by + /// `SeedableRng` for RNGs with such large seeds, the newtype pattern can be + /// used: + /// + /// ``` + /// use rand_core::SeedableRng; + /// + /// const N: usize = 64; + /// pub struct MyRngSeed(pub [u8; N]); + /// pub struct MyRng(MyRngSeed); + /// + /// impl Default for MyRngSeed { + /// fn default() -> MyRngSeed { + /// MyRngSeed([0; N]) + /// } + /// } + /// + /// impl AsMut<[u8]> for MyRngSeed { + /// fn as_mut(&mut self) -> &mut [u8] { + /// &mut self.0 + /// } + /// } + /// + /// impl SeedableRng for MyRng { + /// type Seed = MyRngSeed; + /// + /// fn from_seed(seed: MyRngSeed) -> MyRng { + /// MyRng(seed) + /// } + /// } + /// ``` + type Seed: Sized + Default + AsMut<[u8]>; + + /// Create a new PRNG using the given seed. + /// + /// PRNG implementations are allowed to assume that bits in the seed are + /// well distributed. That means usually that the number of one and zero + /// bits are roughly equal, and values like 0, 1 and (size - 1) are unlikely. + /// Note that many non-cryptographic PRNGs will show poor quality output + /// if this is not adhered to. If you wish to seed from simple numbers, use + /// `seed_from_u64` instead. + /// + /// All PRNG implementations should be reproducible unless otherwise noted: + /// given a fixed `seed`, the same sequence of output should be produced + /// on all runs, library versions and architectures (e.g. check endianness). + /// Any "value-breaking" changes to the generator should require bumping at + /// least the minor version and documentation of the change. + /// + /// It is not required that this function yield the same state as a + /// reference implementation of the PRNG given equivalent seed; if necessary + /// another constructor replicating behaviour from a reference + /// implementation can be added. + /// + /// PRNG implementations should make sure `from_seed` never panics. In the + /// case that some special values (like an all zero seed) are not viable + /// seeds it is preferable to map these to alternative constant value(s), + /// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad + /// seed"). This is assuming only a small number of values must be rejected. + fn from_seed(seed: Self::Seed) -> Self; + + /// Create a new PRNG using a `u64` seed. + /// + /// This is a convenience-wrapper around `from_seed` to allow construction + /// of any `SeedableRng` from a simple `u64` value. It is designed such that + /// low Hamming Weight numbers like 0 and 1 can be used and should still + /// result in good, independent seeds to the PRNG which is returned. + /// + /// This **is not suitable for cryptography**, as should be clear given that + /// the input size is only 64 bits. + /// + /// Implementations for PRNGs *may* provide their own implementations of + /// this function, but the default implementation should be good enough for + /// all purposes. *Changing* the implementation of this function should be + /// considered a value-breaking change. + fn seed_from_u64(mut state: u64) -> Self { + // We use PCG32 to generate a u32 sequence, and copy to the seed + fn pcg32(state: &mut u64) -> [u8; 4] { + const MUL: u64 = 6364136223846793005; + const INC: u64 = 11634580027462260723; + + // We advance the state first (to get away from the input value, + // in case it has low Hamming Weight). + *state = state.wrapping_mul(MUL).wrapping_add(INC); + let state = *state; + + // Use PCG output function with to_le to generate x: + let xorshifted = (((state >> 18) ^ state) >> 27) as u32; + let rot = (state >> 59) as u32; + let x = xorshifted.rotate_right(rot); + x.to_le_bytes() + } + + let mut seed = Self::Seed::default(); + let mut iter = seed.as_mut().chunks_exact_mut(4); + for chunk in &mut iter { + chunk.copy_from_slice(&pcg32(&mut state)); + } + let rem = iter.into_remainder(); + if !rem.is_empty() { + rem.copy_from_slice(&pcg32(&mut state)[..rem.len()]); + } + + Self::from_seed(seed) + } + + /// Create a new PRNG seeded from another `Rng`. + /// + /// This may be useful when needing to rapidly seed many PRNGs from a master + /// PRNG, and to allow forking of PRNGs. It may be considered deterministic. + /// + /// The master PRNG should be at least as high quality as the child PRNGs. + /// When seeding non-cryptographic child PRNGs, we recommend using a + /// different algorithm for the master PRNG (ideally a CSPRNG) to avoid + /// correlations between the child PRNGs. If this is not possible (e.g. + /// forking using small non-crypto PRNGs) ensure that your PRNG has a good + /// mixing function on the output or consider use of a hash function with + /// `from_seed`. + /// + /// Note that seeding `XorShiftRng` from another `XorShiftRng` provides an + /// extreme example of what can go wrong: the new PRNG will be a clone + /// of the parent. + /// + /// PRNG implementations are allowed to assume that a good RNG is provided + /// for seeding, and that it is cryptographically secure when appropriate. + /// As of `rand` 0.7 / `rand_core` 0.5, implementations overriding this + /// method should ensure the implementation satisfies reproducibility + /// (in prior versions this was not required). + /// + /// [`rand`]: https://docs.rs/rand + fn from_rng(mut rng: R) -> Result { + let mut seed = Self::Seed::default(); + rng.try_fill_bytes(seed.as_mut())?; + Ok(Self::from_seed(seed)) + } + + /// Creates a new instance of the RNG seeded via [`getrandom`]. + /// + /// This method is the recommended way to construct non-deterministic PRNGs + /// since it is convenient and secure. + /// + /// In case the overhead of using [`getrandom`] to seed *many* PRNGs is an + /// issue, one may prefer to seed from a local PRNG, e.g. + /// `from_rng(thread_rng()).unwrap()`. + /// + /// # Panics + /// + /// If [`getrandom`] is unable to provide secure entropy this method will panic. + /// + /// [`getrandom`]: https://docs.rs/getrandom + #[cfg(feature = "getrandom")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "getrandom")))] + fn from_entropy() -> Self { + let mut seed = Self::Seed::default(); + if let Err(err) = getrandom::getrandom(seed.as_mut()) { + panic!("from_entropy failed: {}", err); + } + Self::from_seed(seed) + } +} + +// Implement `RngCore` for references to an `RngCore`. +// Force inlining all functions, so that it is up to the `RngCore` +// implementation and the optimizer to decide on inlining. +impl<'a, R: RngCore + ?Sized> RngCore for &'a mut R { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + (**self).next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + (**self).next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + (**self).fill_bytes(dest) + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + (**self).try_fill_bytes(dest) + } +} + +// Implement `RngCore` for boxed references to an `RngCore`. +// Force inlining all functions, so that it is up to the `RngCore` +// implementation and the optimizer to decide on inlining. +#[cfg(feature = "alloc")] +impl RngCore for Box { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + (**self).next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + (**self).next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + (**self).fill_bytes(dest) + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + (**self).try_fill_bytes(dest) + } +} + +#[cfg(feature = "std")] +impl std::io::Read for dyn RngCore { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.try_fill_bytes(buf)?; + Ok(buf.len()) + } +} + +// Implement `CryptoRng` for references to an `CryptoRng`. +impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {} + +// Implement `CryptoRng` for boxed references to an `CryptoRng`. +#[cfg(feature = "alloc")] +impl CryptoRng for Box {} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_seed_from_u64() { + struct SeedableNum(u64); + impl SeedableRng for SeedableNum { + type Seed = [u8; 8]; + + fn from_seed(seed: Self::Seed) -> Self { + let mut x = [0u64; 1]; + le::read_u64_into(&seed, &mut x); + SeedableNum(x[0]) + } + } + + const N: usize = 8; + const SEEDS: [u64; N] = [0u64, 1, 2, 3, 4, 8, 16, -1i64 as u64]; + let mut results = [0u64; N]; + for (i, seed) in SEEDS.iter().enumerate() { + let SeedableNum(x) = SeedableNum::seed_from_u64(*seed); + results[i] = x; + } + + for (i1, r1) in results.iter().enumerate() { + let weight = r1.count_ones(); + // This is the binomial distribution B(64, 0.5), so chance of + // weight < 20 is binocdf(19, 64, 0.5) = 7.8e-4, and same for + // weight > 44. + assert!(weight >= 20 && weight <= 44); + + for (i2, r2) in results.iter().enumerate() { + if i1 == i2 { + continue; + } + let diff_weight = (r1 ^ r2).count_ones(); + assert!(diff_weight >= 20); + } + } + + // value-breakage test: + assert_eq!(results[0], 5029875928683246316); + } +} diff --git a/vendor/rand_core/src/os.rs b/vendor/rand_core/src/os.rs new file mode 100644 index 0000000000..6cd1b9cf5d --- /dev/null +++ b/vendor/rand_core/src/os.rs @@ -0,0 +1,85 @@ +// Copyright 2019 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Interface to the random number generator of the operating system. + +use crate::{impls, CryptoRng, Error, RngCore}; +use getrandom::getrandom; + +/// A random number generator that retrieves randomness from the +/// operating system. +/// +/// This is a zero-sized struct. It can be freely constructed with `OsRng`. +/// +/// The implementation is provided by the [getrandom] crate. Refer to +/// [getrandom] documentation for details. +/// +/// This struct is only available when specifying the crate feature `getrandom` +/// or `std`. When using the `rand` lib, it is also available as `rand::rngs::OsRng`. +/// +/// # Blocking and error handling +/// +/// It is possible that when used during early boot the first call to `OsRng` +/// will block until the system's RNG is initialised. It is also possible +/// (though highly unlikely) for `OsRng` to fail on some platforms, most +/// likely due to system mis-configuration. +/// +/// After the first successful call, it is highly unlikely that failures or +/// significant delays will occur (although performance should be expected to +/// be much slower than a user-space PRNG). +/// +/// # Usage example +/// ``` +/// use rand_core::{RngCore, OsRng}; +/// +/// let mut key = [0u8; 16]; +/// OsRng.fill_bytes(&mut key); +/// let random_u64 = OsRng.next_u64(); +/// ``` +/// +/// [getrandom]: https://crates.io/crates/getrandom +#[cfg_attr(doc_cfg, doc(cfg(feature = "getrandom")))] +#[derive(Clone, Copy, Debug, Default)] +pub struct OsRng; + +impl CryptoRng for OsRng {} + +impl RngCore for OsRng { + fn next_u32(&mut self) -> u32 { + impls::next_u32_via_fill(self) + } + + fn next_u64(&mut self) -> u64 { + impls::next_u64_via_fill(self) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + if let Err(e) = self.try_fill_bytes(dest) { + panic!("Error: {}", e); + } + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + getrandom(dest)?; + Ok(()) + } +} + +#[test] +fn test_os_rng() { + let x = OsRng.next_u64(); + let y = OsRng.next_u64(); + assert!(x != 0); + assert!(x != y); +} + +#[test] +fn test_construction() { + let mut rng = OsRng::default(); + assert!(rng.next_u64() != 0); +} diff --git a/vendor/rand_hc/.cargo-checksum.json b/vendor/rand_hc/.cargo-checksum.json new file mode 100644 index 0000000000..23b495b1ee --- /dev/null +++ b/vendor/rand_hc/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"45d421637c0cab53e5f6f18ffdb40b53dfa7fbef7b4cfa96de3450a3c8b03702","COPYRIGHT":"90eb64f0279b0d9432accfa6023ff803bc4965212383697eee27a0f426d5f8d5","Cargo.toml":"3ce23ba486460921b9159972c0fa2f48aa7593e4afdb9257b344c413e08808db","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"a771e4354f6b3ad4c92da1a5c9a239b6c291527db869632ecea4f20e24ca1135","README.md":"ff733a3325c745af3a4372578ef59a5d953cc5d1454139f490d73270bbc637bb","src/hc128.rs":"8e3bc13f0d1be8eba7dc7f56acf340c316d5eed81d5d0f09e4e778ff1d392141","src/lib.rs":"5bd63b49d1a0f4f8db05e910a0a376a863d028a0a6a18364e983d99eb7440c77"},"package":"3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"} \ No newline at end of file diff --git a/vendor/rand_hc/CHANGELOG.md b/vendor/rand_hc/CHANGELOG.md new file mode 100644 index 0000000000..ad9fe4dfb4 --- /dev/null +++ b/vendor/rand_hc/CHANGELOG.md @@ -0,0 +1,22 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.3.0] - 2020-12-08 +- Bump `rand_core` version to 0.6.0 +- Bump MSRV to 1.36 (#1011) +- impl PartialEq+Eq for Hc128Rng and Hc128Core (#979) +- Drop some unsafe code, fixing an unsound internal function (#960) + +## [0.2.0] - 2019-06-12 +- Bump minor crate version since rand_core bump is a breaking change +- Switch to Edition 2018 + +## [0.1.1] - 2019-06-06 - yanked +- Bump `rand_core` version +- Adjust usage of `#[inline]` + +## [0.1.0] - 2018-10-17 +- Pulled out of the Rand crate diff --git a/vendor/rand_hc/COPYRIGHT b/vendor/rand_hc/COPYRIGHT new file mode 100644 index 0000000000..468d907caf --- /dev/null +++ b/vendor/rand_hc/COPYRIGHT @@ -0,0 +1,12 @@ +Copyrights in the Rand project are retained by their contributors. No +copyright assignment is required to contribute to the Rand project. + +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), Rand is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + +The Rand project includes code from the Rust project +published under these same licenses. diff --git a/vendor/rustc-ap-rustc_graphviz/Cargo.toml b/vendor/rand_hc/Cargo.toml similarity index 54% rename from vendor/rustc-ap-rustc_graphviz/Cargo.toml rename to vendor/rand_hc/Cargo.toml index 318a288dff..bbc87a15ef 100644 --- a/vendor/rustc-ap-rustc_graphviz/Cargo.toml +++ b/vendor/rand_hc/Cargo.toml @@ -12,9 +12,16 @@ [package] edition = "2018" -name = "rustc-ap-rustc_graphviz" -version = "705.0.0" -authors = ["The Rust Project Developers"] -description = "Automatically published version of the package `rustc_graphviz` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n " -license = "MIT / Apache-2.0" -repository = "https://github.com/rust-lang/rust" +name = "rand_hc" +version = "0.3.0" +authors = ["The Rand Project Developers"] +description = "HC128 random number generator\n" +homepage = "https://crates.io/crates/rand_hc" +documentation = "https://rust-random.github.io/rand/rand_hc/" +readme = "README.md" +keywords = ["random", "rng", "hc128"] +categories = ["algorithms", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/rand" +[dependencies.rand_core] +version = "0.6.0" diff --git a/vendor/rand_hc/LICENSE-APACHE b/vendor/rand_hc/LICENSE-APACHE new file mode 100644 index 0000000000..17d74680f8 --- /dev/null +++ b/vendor/rand_hc/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://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 + + https://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/rand_hc/LICENSE-MIT b/vendor/rand_hc/LICENSE-MIT new file mode 100644 index 0000000000..cf656074cb --- /dev/null +++ b/vendor/rand_hc/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright 2018 Developers of the Rand project + +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/rand_hc/README.md b/vendor/rand_hc/README.md new file mode 100644 index 0000000000..87f1c8915c --- /dev/null +++ b/vendor/rand_hc/README.md @@ -0,0 +1,44 @@ +# rand_hc + +[![Test Status](https://github.com/rust-random/rand/workflows/Tests/badge.svg?event=push)](https://github.com/rust-random/rand/actions) +[![Latest version](https://img.shields.io/crates/v/rand_hc.svg)](https://crates.io/crates/rand_hc) +[[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/) +[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_hc) +[![API](https://docs.rs/rand_hc/badge.svg)](https://docs.rs/rand_hc) +[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements) + +A cryptographically secure random number generator that uses the HC-128 +algorithm. + +HC-128 is a stream cipher designed by Hongjun Wu[^1], that we use as an +RNG. It is selected as one of the "stream ciphers suitable for widespread +adoption" by eSTREAM[^2]. + +Links: + +- [API documentation (master)](https://rust-random.github.io/rand/rand_hc) +- [API documentation (docs.rs)](https://docs.rs/rand_hc) +- [Changelog](https://github.com/rust-random/rand/blob/master/rand_hc/CHANGELOG.md) + +[rand]: https://crates.io/crates/rand +[^1]: Hongjun Wu (2008). ["The Stream Cipher HC-128"]( + http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf). + *The eSTREAM Finalists*, LNCS 4986, pp. 39–47, Springer-Verlag. + +[^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( + http://www.ecrypt.eu.org/stream/) + + +## Crate Features + +`rand_hc` is `no_std` compatible. It does not require any functionality +outside of the `core` lib, thus there are no features to configure. + + +# License + +`rand_hc` is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and +[COPYRIGHT](COPYRIGHT) for details. diff --git a/vendor/rand_hc/src/hc128.rs b/vendor/rand_hc/src/hc128.rs new file mode 100644 index 0000000000..94d75778f7 --- /dev/null +++ b/vendor/rand_hc/src/hc128.rs @@ -0,0 +1,513 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The HC-128 random number generator. + +use core::fmt; +use rand_core::block::{BlockRng, BlockRngCore}; +use rand_core::{le, CryptoRng, Error, RngCore, SeedableRng}; + +const SEED_WORDS: usize = 8; // 128 bit key followed by 128 bit iv + +/// A cryptographically secure random number generator that uses the HC-128 +/// algorithm. +/// +/// HC-128 is a stream cipher designed by Hongjun Wu[^1], that we use as an +/// RNG. It is selected as one of the "stream ciphers suitable for widespread +/// adoption" by eSTREAM[^2]. +/// +/// HC-128 is an array based RNG. In this it is similar to RC-4 and ISAAC before +/// it, but those have never been proven cryptographically secure (or have even +/// been significantly compromised, as in the case of RC-4[^5]). +/// +/// Because HC-128 works with simple indexing into a large array and with a few +/// operations that parallelize well, it has very good performance. The size of +/// the array it needs, 4kb, can however be a disadvantage. +/// +/// This implementation is not based on the version of HC-128 submitted to the +/// eSTREAM contest, but on a later version by the author with a few small +/// improvements from December 15, 2009[^3]. +/// +/// HC-128 has no known weaknesses that are easier to exploit than doing a +/// brute-force search of 2128. A very comprehensive analysis of the +/// current state of known attacks / weaknesses of HC-128 is given in *Some +/// Results On Analysis And Implementation Of HC-128 Stream Cipher*[^4]. +/// +/// The average cycle length is expected to be +/// 21024*32+10-1 = 232777. +/// We support seeding with a 256-bit array, which matches the 128-bit key +/// concatenated with a 128-bit IV from the stream cipher. +/// +/// This implementation uses an output buffer of sixteen `u32` words, and uses +/// [`BlockRng`] to implement the [`RngCore`] methods. +/// +/// ## References +/// [^1]: Hongjun Wu (2008). ["The Stream Cipher HC-128"]( +/// http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf). +/// *The eSTREAM Finalists*, LNCS 4986, pp. 39–47, Springer-Verlag. +/// +/// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( +/// http://www.ecrypt.eu.org/stream/) +/// +/// [^3]: Hongjun Wu, [Stream Ciphers HC-128 and HC-256]( +/// https://www.ntu.edu.sg/home/wuhj/research/hc/index.html) +/// +/// [^4]: Shashwat Raizada (January 2015),["Some Results On Analysis And +/// Implementation Of HC-128 Stream Cipher"]( +/// http://library.isical.ac.in:8080/jspui/bitstream/123456789/6636/1/TH431.pdf). +/// +/// [^5]: Internet Engineering Task Force (February 2015), +/// ["Prohibiting RC4 Cipher Suites"](https://tools.ietf.org/html/rfc7465). +#[derive(Clone, Debug)] +pub struct Hc128Rng(BlockRng); + +impl RngCore for Hc128Rng { + #[inline] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest) + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for Hc128Rng { + type Seed = ::Seed; + + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + Hc128Rng(BlockRng::::from_seed(seed)) + } + + #[inline] + fn from_rng(rng: R) -> Result { + BlockRng::::from_rng(rng).map(Hc128Rng) + } +} + +impl CryptoRng for Hc128Rng {} + +impl PartialEq for Hc128Rng { + fn eq(&self, rhs: &Self) -> bool { + self.0.core == rhs.0.core && self.0.index() == rhs.0.index() + } +} +impl Eq for Hc128Rng {} + +/// The core of `Hc128Rng`, used with `BlockRng`. +#[derive(Clone)] +pub struct Hc128Core { + t: [u32; 1024], + counter1024: usize, +} + +// Custom Debug implementation that does not expose the internal state +impl fmt::Debug for Hc128Core { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Hc128Core {{}}") + } +} + +impl BlockRngCore for Hc128Core { + type Item = u32; + type Results = [u32; 16]; + + fn generate(&mut self, results: &mut Self::Results) { + assert!(self.counter1024 % 16 == 0); + + let cc = self.counter1024 % 512; + let dd = (cc + 16) % 512; + let ee = cc.wrapping_sub(16) % 512; + // These asserts let the compiler optimize out the bounds checks. + // Some of them may be superflous, and that's fine: + // they'll be optimized out if that's the case. + assert!(ee + 15 < 512); + assert!(cc + 15 < 512); + assert!(dd < 512); + + if self.counter1024 & 512 == 0 { + // P block + results[0] = self.step_p(cc+0, cc+1, ee+13, ee+6, ee+4); + results[1] = self.step_p(cc+1, cc+2, ee+14, ee+7, ee+5); + results[2] = self.step_p(cc+2, cc+3, ee+15, ee+8, ee+6); + results[3] = self.step_p(cc+3, cc+4, cc+0, ee+9, ee+7); + results[4] = self.step_p(cc+4, cc+5, cc+1, ee+10, ee+8); + results[5] = self.step_p(cc+5, cc+6, cc+2, ee+11, ee+9); + results[6] = self.step_p(cc+6, cc+7, cc+3, ee+12, ee+10); + results[7] = self.step_p(cc+7, cc+8, cc+4, ee+13, ee+11); + results[8] = self.step_p(cc+8, cc+9, cc+5, ee+14, ee+12); + results[9] = self.step_p(cc+9, cc+10, cc+6, ee+15, ee+13); + results[10] = self.step_p(cc+10, cc+11, cc+7, cc+0, ee+14); + results[11] = self.step_p(cc+11, cc+12, cc+8, cc+1, ee+15); + results[12] = self.step_p(cc+12, cc+13, cc+9, cc+2, cc+0); + results[13] = self.step_p(cc+13, cc+14, cc+10, cc+3, cc+1); + results[14] = self.step_p(cc+14, cc+15, cc+11, cc+4, cc+2); + results[15] = self.step_p(cc+15, dd+0, cc+12, cc+5, cc+3); + } else { + // Q block + results[0] = self.step_q(cc+0, cc+1, ee+13, ee+6, ee+4); + results[1] = self.step_q(cc+1, cc+2, ee+14, ee+7, ee+5); + results[2] = self.step_q(cc+2, cc+3, ee+15, ee+8, ee+6); + results[3] = self.step_q(cc+3, cc+4, cc+0, ee+9, ee+7); + results[4] = self.step_q(cc+4, cc+5, cc+1, ee+10, ee+8); + results[5] = self.step_q(cc+5, cc+6, cc+2, ee+11, ee+9); + results[6] = self.step_q(cc+6, cc+7, cc+3, ee+12, ee+10); + results[7] = self.step_q(cc+7, cc+8, cc+4, ee+13, ee+11); + results[8] = self.step_q(cc+8, cc+9, cc+5, ee+14, ee+12); + results[9] = self.step_q(cc+9, cc+10, cc+6, ee+15, ee+13); + results[10] = self.step_q(cc+10, cc+11, cc+7, cc+0, ee+14); + results[11] = self.step_q(cc+11, cc+12, cc+8, cc+1, ee+15); + results[12] = self.step_q(cc+12, cc+13, cc+9, cc+2, cc+0); + results[13] = self.step_q(cc+13, cc+14, cc+10, cc+3, cc+1); + results[14] = self.step_q(cc+14, cc+15, cc+11, cc+4, cc+2); + results[15] = self.step_q(cc+15, dd+0, cc+12, cc+5, cc+3); + } + self.counter1024 = self.counter1024.wrapping_add(16); + } +} + +impl Hc128Core { + // One step of HC-128, update P and generate 32 bits keystream + #[inline(always)] + fn step_p(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) -> u32 { + let (p, q) = self.t.split_at_mut(512); + let temp0 = p[i511].rotate_right(23); + let temp1 = p[i3].rotate_right(10); + let temp2 = p[i10].rotate_right(8); + p[i] = p[i] + .wrapping_add(temp2) + .wrapping_add(temp0 ^ temp1); + let temp3 = { + // The h1 function in HC-128 + let a = p[i12] as u8; + let c = (p[i12] >> 16) as u8; + q[a as usize].wrapping_add(q[256 + c as usize]) + }; + temp3 ^ p[i] + } + + // One step of HC-128, update Q and generate 32 bits keystream + // Similar to `step_p`, but `p` and `q` are swapped, and the rotates are to + // the left instead of to the right. + #[inline(always)] + fn step_q(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) -> u32 { + let (p, q) = self.t.split_at_mut(512); + let temp0 = q[i511].rotate_left(23); + let temp1 = q[i3].rotate_left(10); + let temp2 = q[i10].rotate_left(8); + q[i] = q + [i] + .wrapping_add(temp2) + .wrapping_add(temp0 ^ temp1); + let temp3 = { + // The h2 function in HC-128 + let a = q[i12] as u8; + let c = (q[i12] >> 16) as u8; + p[a as usize].wrapping_add(p[256 + c as usize]) + }; + temp3 ^ q[i] + } + + fn sixteen_steps(&mut self) { + assert!(self.counter1024 % 16 == 0); + + let cc = self.counter1024 % 512; + let dd = (cc + 16) % 512; + let ee = cc.wrapping_sub(16) % 512; + // These asserts let the compiler optimize out the bounds checks. + // Some of them may be superflous, and that's fine: + // they'll be optimized out if that's the case. + assert!(ee + 15 < 512); + assert!(cc + 15 < 512); + assert!(dd < 512); + + if self.counter1024 < 512 { + // P block + self.t[cc+0] = self.step_p(cc+0, cc+1, ee+13, ee+6, ee+4); + self.t[cc+1] = self.step_p(cc+1, cc+2, ee+14, ee+7, ee+5); + self.t[cc+2] = self.step_p(cc+2, cc+3, ee+15, ee+8, ee+6); + self.t[cc+3] = self.step_p(cc+3, cc+4, cc+0, ee+9, ee+7); + self.t[cc+4] = self.step_p(cc+4, cc+5, cc+1, ee+10, ee+8); + self.t[cc+5] = self.step_p(cc+5, cc+6, cc+2, ee+11, ee+9); + self.t[cc+6] = self.step_p(cc+6, cc+7, cc+3, ee+12, ee+10); + self.t[cc+7] = self.step_p(cc+7, cc+8, cc+4, ee+13, ee+11); + self.t[cc+8] = self.step_p(cc+8, cc+9, cc+5, ee+14, ee+12); + self.t[cc+9] = self.step_p(cc+9, cc+10, cc+6, ee+15, ee+13); + self.t[cc+10] = self.step_p(cc+10, cc+11, cc+7, cc+0, ee+14); + self.t[cc+11] = self.step_p(cc+11, cc+12, cc+8, cc+1, ee+15); + self.t[cc+12] = self.step_p(cc+12, cc+13, cc+9, cc+2, cc+0); + self.t[cc+13] = self.step_p(cc+13, cc+14, cc+10, cc+3, cc+1); + self.t[cc+14] = self.step_p(cc+14, cc+15, cc+11, cc+4, cc+2); + self.t[cc+15] = self.step_p(cc+15, dd+0, cc+12, cc+5, cc+3); + } else { + // Q block + self.t[cc+512+0] = self.step_q(cc+0, cc+1, ee+13, ee+6, ee+4); + self.t[cc+512+1] = self.step_q(cc+1, cc+2, ee+14, ee+7, ee+5); + self.t[cc+512+2] = self.step_q(cc+2, cc+3, ee+15, ee+8, ee+6); + self.t[cc+512+3] = self.step_q(cc+3, cc+4, cc+0, ee+9, ee+7); + self.t[cc+512+4] = self.step_q(cc+4, cc+5, cc+1, ee+10, ee+8); + self.t[cc+512+5] = self.step_q(cc+5, cc+6, cc+2, ee+11, ee+9); + self.t[cc+512+6] = self.step_q(cc+6, cc+7, cc+3, ee+12, ee+10); + self.t[cc+512+7] = self.step_q(cc+7, cc+8, cc+4, ee+13, ee+11); + self.t[cc+512+8] = self.step_q(cc+8, cc+9, cc+5, ee+14, ee+12); + self.t[cc+512+9] = self.step_q(cc+9, cc+10, cc+6, ee+15, ee+13); + self.t[cc+512+10] = self.step_q(cc+10, cc+11, cc+7, cc+0, ee+14); + self.t[cc+512+11] = self.step_q(cc+11, cc+12, cc+8, cc+1, ee+15); + self.t[cc+512+12] = self.step_q(cc+12, cc+13, cc+9, cc+2, cc+0); + self.t[cc+512+13] = self.step_q(cc+13, cc+14, cc+10, cc+3, cc+1); + self.t[cc+512+14] = self.step_q(cc+14, cc+15, cc+11, cc+4, cc+2); + self.t[cc+512+15] = self.step_q(cc+15, dd+0, cc+12, cc+5, cc+3); + } + self.counter1024 += 16; + } + + // Initialize an HC-128 random number generator. The seed has to be + // 256 bits in length (`[u32; 8]`), matching the 128 bit `key` followed by + // 128 bit `iv` when HC-128 where to be used as a stream cipher. + #[inline(always)] // single use: SeedableRng::from_seed + fn init(seed: [u32; SEED_WORDS]) -> Self { + #[inline] + fn f1(x: u32) -> u32 { + x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) + } + + #[inline] + fn f2(x: u32) -> u32 { + x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) + } + + let mut t = [0u32; 1024]; + + // Expand the key and iv into P and Q + let (key, iv) = seed.split_at(4); + t[..4].copy_from_slice(key); + t[4..8].copy_from_slice(key); + t[8..12].copy_from_slice(iv); + t[12..16].copy_from_slice(iv); + + // Generate the 256 intermediate values W[16] ... W[256+16-1], and + // copy the last 16 generated values to the start op P. + for i in 16..256 + 16 { + t[i] = f2(t[i - 2]) + .wrapping_add(t[i - 7]) + .wrapping_add(f1(t[i - 15])) + .wrapping_add(t[i - 16]) + .wrapping_add(i as u32); + } + { + let (p1, p2) = t.split_at_mut(256); + p1[0..16].copy_from_slice(&p2[0..16]); + } + + // Generate both the P and Q tables + for i in 16..1024 { + t[i] = f2(t[i - 2]) + .wrapping_add(t[i - 7]) + .wrapping_add(f1(t[i - 15])) + .wrapping_add(t[i - 16]) + .wrapping_add(256 + i as u32); + } + + let mut core = Self { t, counter1024: 0 }; + + // run the cipher 1024 steps + for _ in 0..64 { + core.sixteen_steps() + } + core.counter1024 = 0; + core + } +} + +impl SeedableRng for Hc128Core { + type Seed = [u8; SEED_WORDS * 4]; + + /// Create an HC-128 random number generator with a seed. The seed has to be + /// 256 bits in length, matching the 128 bit `key` followed by 128 bit `iv` + /// when HC-128 where to be used as a stream cipher. + fn from_seed(seed: Self::Seed) -> Self { + let mut seed_u32 = [0u32; SEED_WORDS]; + le::read_u32_into(&seed, &mut seed_u32); + Self::init(seed_u32) + } +} + +impl CryptoRng for Hc128Core {} + +// Custom PartialEq implementation as it can't currently be derived from an array of size 1024 +impl PartialEq for Hc128Core { + fn eq(&self, rhs: &Self) -> bool { + &self.t[..] == &rhs.t[..] && self.counter1024 == rhs.counter1024 + } +} +impl Eq for Hc128Core {} + +#[cfg(test)] +mod test { + use super::Hc128Rng; + use ::rand_core::{RngCore, SeedableRng}; + + #[test] + // Test vector 1 from the paper "The Stream Cipher HC-128" + fn test_hc128_true_values_a() { + #[rustfmt::skip] + let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv + let mut rng = Hc128Rng::from_seed(seed); + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + #[rustfmt::skip] + let expected = [0x73150082, 0x3bfd03a0, 0xfb2fd77f, 0xaa63af0e, + 0xde122fc6, 0xa7dc29b6, 0x62a68527, 0x8b75ec68, + 0x9036db1e, 0x81896005, 0x00ade078, 0x491fbf9a, + 0x1cdc3013, 0x6c3d6e24, 0x90f664b2, 0x9cd57102]; + assert_eq!(results, expected); + } + + #[test] + // Test vector 2 from the paper "The Stream Cipher HC-128" + fn test_hc128_true_values_b() { + #[rustfmt::skip] + let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key + 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv + let mut rng = Hc128Rng::from_seed(seed); + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + #[rustfmt::skip] + let expected = [0xc01893d5, 0xb7dbe958, 0x8f65ec98, 0x64176604, + 0x36fc6724, 0xc82c6eec, 0x1b1c38a7, 0xc9b42a95, + 0x323ef123, 0x0a6a908b, 0xce757b68, 0x9f14f7bb, + 0xe4cde011, 0xaeb5173f, 0x89608c94, 0xb5cf46ca]; + assert_eq!(results, expected); + } + + #[test] + // Test vector 3 from the paper "The Stream Cipher HC-128" + fn test_hc128_true_values_c() { + #[rustfmt::skip] + let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv + let mut rng = Hc128Rng::from_seed(seed); + + let mut results = [0u32; 16]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + #[rustfmt::skip] + let expected = [0x518251a4, 0x04b4930a, 0xb02af931, 0x0639f032, + 0xbcb4a47a, 0x5722480b, 0x2bf99f72, 0xcdc0e566, + 0x310f0c56, 0xd3cc83e8, 0x663db8ef, 0x62dfe07f, + 0x593e1790, 0xc5ceaa9c, 0xab03806f, 0xc9a6e5a0]; + assert_eq!(results, expected); + } + + #[test] + fn test_hc128_true_values_u64() { + #[rustfmt::skip] + let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv + let mut rng = Hc128Rng::from_seed(seed); + + let mut results = [0u64; 8]; + for i in results.iter_mut() { + *i = rng.next_u64(); + } + #[rustfmt::skip] + let expected = [0x3bfd03a073150082, 0xaa63af0efb2fd77f, + 0xa7dc29b6de122fc6, 0x8b75ec6862a68527, + 0x818960059036db1e, 0x491fbf9a00ade078, + 0x6c3d6e241cdc3013, 0x9cd5710290f664b2]; + assert_eq!(results, expected); + + // The RNG operates in a P block of 512 results and next a Q block. + // After skipping 2*800 u32 results we end up somewhere in the Q block + // of the second round + for _ in 0..800 { + rng.next_u64(); + } + + for i in results.iter_mut() { + *i = rng.next_u64(); + } + #[rustfmt::skip] + let expected = [0xd8c4d6ca84d0fc10, 0xf16a5d91dc66e8e7, + 0xd800de5bc37a8653, 0x7bae1f88c0dfbb4c, + 0x3bfe1f374e6d4d14, 0x424b55676be3fa06, + 0xe3a1e8758cbff579, 0x417f7198c5652bcd]; + assert_eq!(results, expected); + } + + #[test] + fn test_hc128_true_values_bytes() { + #[rustfmt::skip] + let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv + let mut rng = Hc128Rng::from_seed(seed); + #[rustfmt::skip] + let expected = [0x31, 0xf9, 0x2a, 0xb0, 0x32, 0xf0, 0x39, 0x06, + 0x7a, 0xa4, 0xb4, 0xbc, 0x0b, 0x48, 0x22, 0x57, + 0x72, 0x9f, 0xf9, 0x2b, 0x66, 0xe5, 0xc0, 0xcd, + 0x56, 0x0c, 0x0f, 0x31, 0xe8, 0x83, 0xcc, 0xd3, + 0xef, 0xb8, 0x3d, 0x66, 0x7f, 0xe0, 0xdf, 0x62, + 0x90, 0x17, 0x3e, 0x59, 0x9c, 0xaa, 0xce, 0xc5, + 0x6f, 0x80, 0x03, 0xab, 0xa0, 0xe5, 0xa6, 0xc9, + 0x60, 0x95, 0x84, 0x7a, 0xa5, 0x68, 0x5a, 0x84, + 0xea, 0xd5, 0xf3, 0xea, 0x73, 0xa9, 0xad, 0x01, + 0x79, 0x7d, 0xbe, 0x9f, 0xea, 0xe3, 0xf9, 0x74, + 0x0e, 0xda, 0x2f, 0xa0, 0xe4, 0x7b, 0x4b, 0x1b, + 0xdd, 0x17, 0x69, 0x4a, 0xfe, 0x9f, 0x56, 0x95, + 0xad, 0x83, 0x6b, 0x9d, 0x60, 0xa1, 0x99, 0x96, + 0x90, 0x00, 0x66, 0x7f, 0xfa, 0x7e, 0x65, 0xe9, + 0xac, 0x8b, 0x92, 0x34, 0x77, 0xb4, 0x23, 0xd0, + 0xb9, 0xab, 0xb1, 0x47, 0x7d, 0x4a, 0x13, 0x0a]; + + // Pick a somewhat large buffer so we can test filling with the + // remainder from `state.results`, directly filling the buffer, and + // filling the remainder of the buffer. + let mut buffer = [0u8; 16 * 4 * 2]; + // Consume a value so that we have a remainder. + assert!(rng.next_u64() == 0x04b4930a518251a4); + rng.fill_bytes(&mut buffer); + + // [u8; 128] doesn't implement PartialEq + assert_eq!(buffer.len(), expected.len()); + for (b, e) in buffer.iter().zip(expected.iter()) { + assert_eq!(b, e); + } + } + + #[test] + fn test_hc128_clone() { + #[rustfmt::skip] + let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv + let mut rng1 = Hc128Rng::from_seed(seed); + let mut rng2 = rng1.clone(); + for _ in 0..16 { + assert_eq!(rng1.next_u32(), rng2.next_u32()); + } + } +} diff --git a/vendor/rand_hc/src/lib.rs b/vendor/rand_hc/src/lib.rs new file mode 100644 index 0000000000..995cb1d043 --- /dev/null +++ b/vendor/rand_hc/src/lib.rs @@ -0,0 +1,23 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The HC128 random number generator. + +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![no_std] + +mod hc128; + +pub use hc128::{Hc128Core, Hc128Rng}; diff --git a/vendor/redox_syscall/.cargo-checksum.json b/vendor/redox_syscall/.cargo-checksum.json index afd55c0f2b..e6bba2a6e1 100644 --- a/vendor/redox_syscall/.cargo-checksum.json +++ b/vendor/redox_syscall/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"fa6c6b799f96f2dc4a8bb00dfcdbe55b1a50e012b4f4cc8218ff190f3433d974","LICENSE":"efcfee7981ff72431fffb06925cad00a23dce079ed4354f61030ad5abdb78829","README.md":"9161f18ba7f69b4ca51e844aee8ffb8237513a468c5c3b1f3a5f989044f895ac","src/arch/aarch64.rs":"7dade48302d4fc691cae48499cf91d7676ef8c82efe2270f17aee0fe2611f3ec","src/arch/arm.rs":"abc547bd2be32ff15f35032452e645668ec5050d2540e2dca073fc5670ca1a75","src/arch/nonredox.rs":"9eac0fa2cf9eae07f0cafa2dd63c4a820791897a3de9ad1a933ab4f53458dbd8","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":"8fbacb97f56059fbd32067d6c065f95189d2eb11bc9913f98609430ec94bf9fa","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":"ea460f580116575890031a48fbfa101db75b191ef6b2aebfeab11dbb866091c3"},"package":"94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"} \ No newline at end of file +{"files":{"Cargo.toml":"14780ec6f76b0753d649953e270af04c347b677b9ae7092ec753d79080579830","LICENSE":"efcfee7981ff72431fffb06925cad00a23dce079ed4354f61030ad5abdb78829","README.md":"9161f18ba7f69b4ca51e844aee8ffb8237513a468c5c3b1f3a5f989044f895ac","src/arch/aarch64.rs":"58ffa2a6413c04717437d955e8e59a209e28c7fd5cc26822801844b8d3c9f092","src/arch/arm.rs":"abc547bd2be32ff15f35032452e645668ec5050d2540e2dca073fc5670ca1a75","src/arch/nonredox.rs":"9eac0fa2cf9eae07f0cafa2dd63c4a820791897a3de9ad1a933ab4f53458dbd8","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":"8fbacb97f56059fbd32067d6c065f95189d2eb11bc9913f98609430ec94bf9fa","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":"8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041"} \ No newline at end of file diff --git a/vendor/redox_syscall/Cargo.toml b/vendor/redox_syscall/Cargo.toml index 43317fd9a0..12ecf58069 100644 --- a/vendor/redox_syscall/Cargo.toml +++ b/vendor/redox_syscall/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "redox_syscall" -version = "0.2.5" +version = "0.2.6" authors = ["Jeremy Soller "] description = "A Rust library to access raw Redox system calls" documentation = "https://docs.rs/redox_syscall" diff --git a/vendor/redox_syscall/src/arch/aarch64.rs b/vendor/redox_syscall/src/arch/aarch64.rs index 23abe49a0d..60e22386fe 100644 --- a/vendor/redox_syscall/src/arch/aarch64.rs +++ b/vendor/redox_syscall/src/arch/aarch64.rs @@ -1,62 +1,129 @@ +use core::{mem, slice}; +use core::ops::{Deref, DerefMut}; + use super::error::{Error, Result}; -pub unsafe fn syscall0(mut a: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a) - : "x0", "x8" - : "volatile"); +macro_rules! syscall { + ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => { + $( + pub unsafe fn $name(mut $a: usize, $(mut $b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result { + asm!( + "svc 0", + in("x8") $a, + $( + inout("x0") $b, + $( + in("x1") $c, + $( + in("x2") $d, + $( + in("x3") $e, + $( + in("x4") $f, + )? + )? + )? + )? + )? + options(nostack), + ); - Error::demux(a) + Error::demux($a) + } + )+ + }; } -pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b) - : "x0", "x8" - : "volatile"); - - Error::demux(a) +syscall! { + syscall0(a,); + syscall1(a, b,); + syscall2(a, b, c,); + syscall3(a, b, c, d,); + syscall4(a, b, c, d, e,); + syscall5(a, b, c, d, e, f,); } -pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c) - : "x0", "x1", "x8" - : "volatile"); - - Error::demux(a) +#[derive(Copy, Clone, Debug, Default)] +#[repr(C)] +pub struct IntRegisters { + pub elr_el1: usize, + pub tpidr_el0: usize, + pub tpidrro_el0: usize, + pub spsr_el1: usize, + pub esr_el1: usize, + pub sp_el0: usize, // Shouldn't be used if interrupt occurred at EL1 + pub padding: usize, // To keep the struct even number aligned + pub x30: usize, + pub x29: usize, + pub x28: usize, + pub x27: usize, + pub x26: usize, + pub x25: usize, + pub x24: usize, + pub x23: usize, + pub x22: usize, + pub x21: usize, + pub x20: usize, + pub x19: usize, + pub x18: usize, + pub x17: usize, + pub x16: usize, + pub x15: usize, + pub x14: usize, + pub x13: usize, + pub x12: usize, + pub x11: usize, + pub x10: usize, + pub x9: usize, + pub x8: usize, + pub x7: usize, + pub x6: usize, + pub x5: usize, + pub x4: usize, + pub x3: usize, + pub x2: usize, + pub x1: usize, + pub x0: usize } -pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d) - : "x0", "x1", "x2", "x8" - : "volatile"); - - Error::demux(a) +impl Deref for IntRegisters { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const IntRegisters as *const u8, mem::size_of::()) + } + } } -pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d), "{x3}"(e) - : "x0", "x1", "x2", "x3", "x8" - : "volatile"); +impl DerefMut for IntRegisters { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut IntRegisters as *mut u8, mem::size_of::()) + } + } +} - Error::demux(a) +#[derive(Clone, Copy, Debug, Default)] +#[repr(packed)] +pub struct FloatRegisters { + pub fp_simd_regs: [u128; 32], + pub fpsr: u32, + pub fpcr: u32 } -pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d), "{x3}"(e), "{x4}"(f) - : "x0", "x1", "x2", "x3", "x4", "x8" - : "volatile"); +impl Deref for FloatRegisters { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const FloatRegisters as *const u8, mem::size_of::()) + } + } +} - Error::demux(a) +impl DerefMut for FloatRegisters { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut FloatRegisters as *mut u8, mem::size_of::()) + } + } } diff --git a/vendor/redox_syscall/src/tests.rs b/vendor/redox_syscall/src/tests.rs index 49a5f1b4dd..c5e1f8df07 100644 --- a/vendor/redox_syscall/src/tests.rs +++ b/vendor/redox_syscall/src/tests.rs @@ -107,12 +107,15 @@ fn fmap() { ) ).unwrap(); + let size = 128; + let map = unsafe { slice::from_raw_parts_mut( dbg!( crate::fmap(fd, &crate::Map { + address: 0, offset: 0, - size: 128, + size, flags: crate::PROT_READ | crate::PROT_WRITE }) ).unwrap() as *mut u8, @@ -131,7 +134,7 @@ fn fmap() { //TODO: add msync unsafe { assert_eq!(dbg!( - crate::funmap(map.as_mut_ptr() as usize) + crate::funmap(map.as_mut_ptr() as usize, size) ), Ok(0)); } } diff --git a/vendor/redox_users-0.3.4/.cargo-checksum.json b/vendor/redox_users-0.3.4/.cargo-checksum.json deleted file mode 100644 index f8621976c3..0000000000 --- a/vendor/redox_users-0.3.4/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"7f5c1210ec03b11cfbc903cff2a930d6b3bfaff90d665f1fefc000603c933ef0","LICENSE":"e6a8ae2d796083783efc94b1e66271aa2929dc4dfb231d34239aa9c7db8396db","README.md":"9c3a6fd2a798bd1e105c5ee72f7b475471e3a9abec89b5be2b5263d654085d22","src/lib.rs":"3af9f7cc0c9da8afb6c7b9c7f4d36a7650d478e9b6bdfb899a968dea4b33e122","tests/etc/group":"175d89e8d03e2976d3f37110050372163fcafd07a20c899ade3a9690b2cb4526","tests/etc/passwd":"aee0d4bd2abf55846683cc2e5daaa03641636a262519623d59b1ab8e1eb1db32","tests/etc/shadow":"ca7c1a6f96eaef3bd26da4faeae55e78cad04822c191e3263b539ee687de4d0a"},"package":"09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"} \ No newline at end of file diff --git a/vendor/redox_users-0.3.4/Cargo.toml b/vendor/redox_users-0.3.4/Cargo.toml deleted file mode 100644 index 4b3b71e493..0000000000 --- a/vendor/redox_users-0.3.4/Cargo.toml +++ /dev/null @@ -1,30 +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 = "redox_users" -version = "0.3.4" -authors = ["Jose Narvaez ", "Wesley Hershberger "] -description = "A Rust library to access Redox users and groups functionality" -documentation = "https://docs.rs/redox_users" -readme = "README.md" -keywords = ["redox", "auth"] -license = "MIT" -repository = "https://gitlab.redox-os.org/redox-os/users" -[dependencies.getrandom] -version = "0.1" - -[dependencies.redox_syscall] -version = "0.1" - -[dependencies.rust-argon2] -version = "0.7" diff --git a/vendor/redox_users-0.3.4/LICENSE b/vendor/redox_users-0.3.4/LICENSE deleted file mode 100644 index 643ad0518e..0000000000 --- a/vendor/redox_users-0.3.4/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Jose Narvaez - -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/redox_users-0.3.4/README.md b/vendor/redox_users-0.3.4/README.md deleted file mode 100644 index ccb5d7965c..0000000000 --- a/vendor/redox_users-0.3.4/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# redox_users - -Redox OS APIs for accessing users and groups information. [Documentation](https://docs.rs/redox_users/0.1.0/redox_users/) - -High level APIs for: - -- Getting the current process effective user ID. -- Getting the current process user ID. -- Getting the current process effective group ID. -- Getting the current process group ID. -- Manipulating User and Group information (including adding, removing, and modifying groups and users, in addition to other functionality, see docs) - -We recommend to use these APIs instead of directly manipulating the -`/etc/group` and `/etc/passwd` as this is an implementation detail and -might change in the future. - -Note that redox_users is an API designed only for use on Redox. It compiles on other platforms (for testing), but it will not work and might produce unexpected behavior. - -## Hashing -redox_users uses the Argon2 hashing algorithm. The default hashing parameters are as follows: -```Rust -Argon2::new(10, 1, 4096, Variant::Argon2i) -``` diff --git a/vendor/redox_users-0.3.4/src/lib.rs b/vendor/redox_users-0.3.4/src/lib.rs deleted file mode 100644 index 6c77f127df..0000000000 --- a/vendor/redox_users-0.3.4/src/lib.rs +++ /dev/null @@ -1,1349 +0,0 @@ -//! `redox-users` is designed to be a small, low-ish level interface -//! to system user and group information, as well as user password -//! authentication. -//! -//! # Permissions -//! Because this is a system level tool dealing with password -//! authentication, programs are often required to run with -//! escalated priveleges. The implementation of the crate is -//! privelege unaware. The only privelege requirements are those -//! laid down by the system administrator over these files: -//! - `/etc/group` -//! - Read: Required to access group information -//! - Write: Required to change group information -//! - `/etc/passwd` -//! - Read: Required to access user information -//! - Write: Required to change user information -//! - `/etc/shadow` -//! - Read: Required to authenticate users -//! - Write: Required to set user passwords -//! -//! # Reimplementation -//! This crate is designed to be as small as possible without -//! sacrificing critical functionality. The idea is that a small -//! enough redox-users will allow easy re-implementation based on -//! the same flexible API. This would allow more complicated authentication -//! schemes for redox in future without breakage of existing -//! software. - -extern crate argon2; -extern crate getrandom; -extern crate syscall; - -use std::convert::From; -use std::error::Error; -use std::fmt::{self, Debug, Display}; -use std::fs::OpenOptions; -use std::io::{Read, Write}; -#[cfg(target_os = "redox")] -use std::os::unix::fs::OpenOptionsExt; -use std::os::unix::process::CommandExt; -use std::path::{Path, PathBuf}; -use std::process::Command; -use std::slice::{Iter, IterMut}; -use std::str::FromStr; -#[cfg(not(test))] -use std::thread; -use std::time::Duration; - -#[cfg(target_os = "redox")] -use syscall::flag::{O_EXLOCK, O_SHLOCK}; -use syscall::Error as SyscallError; - -const PASSWD_FILE: &'static str = "/etc/passwd"; -const GROUP_FILE: &'static str = "/etc/group"; -const SHADOW_FILE: &'static str = "/etc/shadow"; - -#[cfg(target_os = "redox")] -const DEFAULT_SCHEME: &'static str = "file:"; -#[cfg(not(target_os = "redox"))] -const DEFAULT_SCHEME: &'static str = ""; - -const MIN_ID: usize = 1000; -const MAX_ID: usize = 6000; -const DEFAULT_TIMEOUT: u64 = 3; - -pub type Result = std::result::Result>; - -/// Errors that might happen while using this crate -#[derive(Debug, PartialEq)] -pub enum UsersError { - Os { reason: String }, - Parsing { reason: String }, - NotFound, - AlreadyExists -} - -impl fmt::Display for UsersError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - UsersError::Os { reason } => write!(f, "os error: code {}", reason), - UsersError::Parsing { reason } => { - write!(f, "parse error: {}", reason) - }, - UsersError::NotFound => write!(f, "user/group not found"), - UsersError::AlreadyExists => write!(f, "user/group already exists") - } - } -} - -impl Error for UsersError { - fn description(&self) -> &str { "UsersError" } - - fn cause(&self) -> Option<&dyn Error> { None } -} - -#[inline] -fn parse_error(reason: &str) -> UsersError { - UsersError::Parsing { - reason: reason.into() - } -} - -#[inline] -fn os_error(reason: &str) -> UsersError { - UsersError::Os { - reason: reason.into() - } -} - -impl From for UsersError { - fn from(syscall_error: SyscallError) -> UsersError { - UsersError::Os { - reason: format!("{}", syscall_error) - } - } -} - -fn read_locked_file(file: impl AsRef) -> Result { - #[cfg(test)] - println!("Reading file: {}", file.as_ref().display()); - - #[cfg(target_os = "redox")] - let mut file = OpenOptions::new() - .read(true) - .custom_flags(O_SHLOCK as i32) - .open(file)?; - #[cfg(not(target_os = "redox"))] - #[cfg_attr(rustfmt, rustfmt_skip)] - let mut file = OpenOptions::new() - .read(true) - .open(file)?; - - let len = file.metadata()?.len(); - let mut file_data = String::with_capacity(len as usize); - file.read_to_string(&mut file_data)?; - Ok(file_data) -} - -fn write_locked_file(file: impl AsRef, data: String) -> Result<()> { - #[cfg(test)] - println!("Writing file: {}", file.as_ref().display()); - - #[cfg(target_os = "redox")] - let mut file = OpenOptions::new() - .write(true) - .truncate(true) - .custom_flags(O_EXLOCK as i32) - .open(file)?; - #[cfg(not(target_os = "redox"))] - #[cfg_attr(rustfmt, rustfmt_skip)] - let mut file = OpenOptions::new() - .write(true) - .truncate(true) - .open(file)?; - - file.write(data.as_bytes())?; - Ok(()) -} - -/// A struct representing a Redox user. -/// Currently maps to an entry in the `/etc/passwd` file. -/// -/// # Unset vs. Blank Passwords -/// A note on unset passwords vs. blank passwords. A blank password -/// is a hash field that is completely blank (aka, `""`). According -/// to this crate, successful login is only allowed if the input -/// password is blank as well. -/// -/// An unset password is one whose hash is not empty (`""`), but -/// also not a valid serialized argon2rs hashing session. This -/// hash always returns `false` upon attempted verification. The -/// most commonly used hash for an unset password is `"!"`, but -/// this crate makes no distinction. The most common way to unset -/// the password is to use [`unset_passwd`](struct.User.html#method.unset_passwd). -pub struct User { - /// Username (login name) - pub user: String, - // Hashed password and Argon2 indicator, stored to simplify API - hash: Option<(String, bool)>, - /// User id - pub uid: usize, - /// Group id - pub gid: usize, - /// Real name (GECOS field) - pub name: String, - /// Home directory path - pub home: String, - /// Shell path - pub shell: String, - /// Failed login delay duration - auth_delay: Duration -} - -impl User { - /// Set the password for a user. Make sure the password you have - /// received is actually what the user wants as their password (this doesn't). - /// - /// To set the password blank, use `""` as the password parameter. - /// - /// # Panics - /// If the User's hash fields are unpopulated, this function will `panic!` - /// (see [`AllUsers`](struct.AllUsers.html#shadowfile-handling) for more info). - pub fn set_passwd(&mut self, password: impl AsRef) -> Result<()> { - self.panic_if_unpopulated(); - let password = password.as_ref(); - - self.hash = if password != "" { - let mut buf = [0u8; 8]; - getrandom::getrandom(&mut buf)?; - let salt = format!("{:X}", u64::from_ne_bytes(buf)); - let config = argon2::Config::default(); - let hash = argon2::hash_encoded( - password.as_bytes(), - salt.as_bytes(), - &config - )?; - Some((hash, true)) - } else { - Some(("".into(), false)) - }; - Ok(()) - } - - /// Unset the password (do not allow logins). - /// - /// # Panics - /// If the User's hash fields are unpopulated, this function will `panic!` - /// (see [`AllUsers`](struct.AllUsers.html#shadowfile-handling) for more info). - pub fn unset_passwd(&mut self) { - self.panic_if_unpopulated(); - self.hash = Some(("!".into(), false)); - } - - /// Verify the password. If the hash is empty, this only - /// returns `true` if the password field is also empty. - /// Note that this is a blocking operation if the password - /// is incorrect. See [`Config::auth_delay`](struct.Config.html#method.auth_delay) - /// to set the wait time. Default is 3 seconds. - /// - /// # Panics - /// If the User's hash fields are unpopulated, this function will `panic!` - /// (see [`AllUsers`](struct.AllUsers.html#shadowfile-handling) for more info). - pub fn verify_passwd(&self, password: impl AsRef) -> bool { - self.panic_if_unpopulated(); - // Safe because it will have panicked already if self.hash.is_none() - let &(ref hash, ref encoded) = self.hash.as_ref().unwrap(); - let password = password.as_ref(); - - let verified = if *encoded { - argon2::verify_encoded(&hash, password.as_bytes()).unwrap() - } else { - hash == "" && password == "" - }; - - if !verified { - #[cfg(not(test))] // Make tests run faster - thread::sleep(self.auth_delay); - } - verified - } - - /// Determine if the hash for the password is blank - /// (any user can log in as this user with no password). - /// - /// # Panics - /// If the User's hash fields are unpopulated, this function will `panic!` - /// (see [`AllUsers`](struct.AllUsers.html#shadowfile-handling) for more info). - pub fn is_passwd_blank(&self) -> bool { - self.panic_if_unpopulated(); - let &(ref hash, ref encoded) = self.hash.as_ref().unwrap(); - hash == "" && ! encoded - } - - /// Determine if the hash for the password is unset - /// ([`verify_passwd`](struct.User.html#method.verify_passwd) - /// returns `false` regardless of input). - /// - /// # Panics - /// If the User's hash fields are unpopulated, this function will `panic!` - /// (see [`AllUsers`](struct.AllUsers.html#shadowfile-handling) for more info). - pub fn is_passwd_unset(&self) -> bool { - self.panic_if_unpopulated(); - let &(ref hash, ref encoded) = self.hash.as_ref().unwrap(); - hash != "" && ! encoded - } - - /// Get a Command to run the user's default shell - /// (see [`login_cmd`](struct.User.html#method.login_cmd) for more docs). - pub fn shell_cmd(&self) -> Command { self.login_cmd(&self.shell) } - - /// Provide a login command for the user, which is any - /// entry point for starting a user's session, whether - /// a shell (use [`shell_cmd`](struct.User.html#method.shell_cmd) instead) or a graphical init. - /// - /// The `Command` will use the user's `uid` and `gid`, its `current_dir` will be - /// set to the user's home directory, and the follwing enviroment variables will - /// be populated: - /// - /// - `USER` set to the user's `user` field. - /// - `UID` set to the user's `uid` field. - /// - `GROUPS` set the user's `gid` field. - /// - `HOME` set to the user's `home` field. - /// - `SHELL` set to the user's `shell` field. - pub fn login_cmd(&self, cmd: T) -> Command - where T: std::convert::AsRef + AsRef - { - let mut command = Command::new(cmd); - command - .uid(self.uid as u32) - .gid(self.gid as u32) - .current_dir(&self.home) - .env("USER", &self.user) - .env("UID", format!("{}", self.uid)) - .env("GROUPS", format!("{}", self.gid)) - .env("HOME", &self.home) - .env("SHELL", &self.shell); - command - } - - /// This returns an entry for `/etc/shadow` - /// Will panic! - fn shadowstring(&self) -> String { - self.panic_if_unpopulated(); - let hashstring = match self.hash { - Some((ref hash, _)) => hash, - None => panic!("Shadowfile not read!") - }; - format!("{};{}", self.user, hashstring) - } - - /// Give this a hash string (not a shadowfile entry!!!) - fn populate_hash(&mut self, hash: &str) -> Result<()> { - let encoded = match hash { - "" => false, - "!" => false, - _ => true, - }; - self.hash = Some((hash.to_string(), encoded)); - Ok(()) - } - - #[inline] - fn panic_if_unpopulated(&self) { - if self.hash.is_none() { - panic!("Hash not populated!"); - } - } -} - -impl Name for User { - fn name(&self) -> &str { - &self.user - } -} - -impl Id for User { - fn id(&self) -> usize { - self.uid - } -} - -impl Debug for User { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "User {{\n\tuser: {:?}\n\tuid: {:?}\n\tgid: {:?}\n\tname: {:?} - home: {:?}\n\tshell: {:?}\n\tauth_delay: {:?}\n}}", - self.user, self.uid, self.gid, self.name, self.home, self.shell, self.auth_delay - ) - } -} - -impl Display for User { - /// Format this user as an entry in `/etc/passwd`. This - /// is an implementation detail, do NOT rely on this trait - /// being implemented in future. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - #[cfg_attr(rustfmt, rustfmt_skip)] - write!(f, "{};{};{};{};{};{}", - self.user, self.uid, self.gid, self.name, self.home, self.shell - ) - } -} - -impl FromStr for User { - type Err = Box; - - /// Parse an entry from `/etc/passwd`. This - /// is an implementation detail, do NOT rely on this trait - /// being implemented in future. - fn from_str(s: &str) -> Result { - let mut parts = s.split(';'); - - let user = parts - .next() - .ok_or(parse_error("expected user"))?; - let uid = parts - .next() - .ok_or(parse_error("expected uid"))? - .parse::()?; - let gid = parts - .next() - .ok_or(parse_error("expected uid"))? - .parse::()?; - let name = parts - .next() - .ok_or(parse_error("expected real name"))?; - let home = parts - .next() - .ok_or(parse_error("expected home dir path"))?; - let shell = parts - .next() - .ok_or(parse_error("expected shell path"))?; - - Ok(User { - user: user.into(), - hash: None, - uid, - gid, - name: name.into(), - home: home.into(), - shell: shell.into(), - auth_delay: Duration::default(), - }) - } -} - -/// A struct representing a Redox user group. -/// Currently maps to an `/etc/group` file entry. -#[derive(Debug)] -pub struct Group { - /// Group name - pub group: String, - /// Unique group id - pub gid: usize, - /// Group members usernames - pub users: Vec, -} - -impl Name for Group { - fn name(&self) -> &str { - &self.group - } -} - -impl Id for Group { - fn id(&self) -> usize { - self.gid - } -} - -impl Display for Group { - /// Format this group as an entry in `/etc/group`. This - /// is an implementation detail, do NOT rely on this trait - /// being implemented in future. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - #[cfg_attr(rustfmt, rustfmt_skip)] - write!(f, "{};{};{}", - self.group, - self.gid, - self.users.join(",").trim_matches(',') - ) - } -} - -impl FromStr for Group { - type Err = Box; - - /// Parse an entry from `/etc/group`. This - /// is an implementation detail, do NOT rely on this trait - /// being implemented in future. - fn from_str(s: &str) -> Result { - let mut parts = s.split(';'); - - let group = parts - .next() - .ok_or(parse_error("expected group"))?; - let gid = parts - .next() - .ok_or(parse_error("expected gid"))? - .parse::()?; - //Allow for an empty users field. If there is a better way to do this, do it - let users_str = parts.next().unwrap_or(" "); - let users = users_str.split(',').map(|u| u.into()).collect(); - - Ok(Group { - group: group.into(), - gid, - users, - }) - } -} - -/// Gets the current process effective user ID. -/// -/// This function issues the `geteuid` system call returning the process effective -/// user id. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ```no_run -/// # use redox_users::get_euid; -/// let euid = get_euid().unwrap(); -/// ``` -pub fn get_euid() -> Result { - match syscall::geteuid() { - Ok(euid) => Ok(euid), - Err(syscall_error) => Err(From::from(os_error(syscall_error.text()))) - } -} - -/// Gets the current process real user ID. -/// -/// This function issues the `getuid` system call returning the process real -/// user id. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ```no_run -/// # use redox_users::get_uid; -/// let uid = get_uid().unwrap(); -/// ``` -pub fn get_uid() -> Result { - match syscall::getuid() { - Ok(uid) => Ok(uid), - Err(syscall_error) => Err(From::from(os_error(syscall_error.text()))) - } -} - -/// Gets the current process effective group ID. -/// -/// This function issues the `getegid` system call returning the process effective -/// group id. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ```no_run -/// # use redox_users::get_egid; -/// let egid = get_egid().unwrap(); -/// ``` -pub fn get_egid() -> Result { - match syscall::getegid() { - Ok(egid) => Ok(egid), - Err(syscall_error) => Err(From::from(os_error(syscall_error.text()))) - } -} - -/// Gets the current process real group ID. -/// -/// This function issues the `getegid` system call returning the process real -/// group id. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ```no_run -/// # use redox_users::get_gid; -/// let gid = get_gid().unwrap(); -/// ``` -pub fn get_gid() -> Result { - match syscall::getgid() { - Ok(gid) => Ok(gid), - Err(syscall_error) => Err(From::from(os_error(syscall_error.text()))) - } -} - -/// A generic configuration that allows better control of -/// `AllUsers` or `AllGroups` than might otherwise be possible. -/// -/// The use of the fields of this struct is completely optional -/// depending on what constructor it is passed to. For example, -/// `AllGroups` doesn't care if auth is enabled or not, or what -/// the duration is. -/// -/// In most situations, `Config::default()` will work just fine. -/// The other methods on this struct are usually for finer control -/// of an `AllUsers` or `AllGroups` if it is required. -#[derive(Clone)] -pub struct Config { - auth_enabled: bool, - scheme: String, - auth_delay: Duration, - min_id: usize, - max_id: usize, -} - -impl Config { - /// An alternative to the default constructor, this indicates that - /// authentication should be enabled. - pub fn with_auth() -> Config { - Config { - auth_enabled: true, - ..Default::default() - } - } - - /// Builder pattern version of `Self::with_auth`. - pub fn auth(mut self, auth: bool) -> Config { - self.auth_enabled = auth; - self - } - - /// Set the delay for a failed authentication. Default is 3 seconds. - pub fn auth_delay(mut self, delay: Duration) -> Config { - self.auth_delay = delay; - self - } - - /// Set the smallest ID possible to use when finding an unused ID. - pub fn min_id(mut self, id: usize) -> Config { - self.min_id = id; - self - } - - /// Set the largest possible ID to use when finding an unused ID. - pub fn max_id(mut self, id: usize) -> Config { - self.max_id = id; - self - } - - /// Set the scheme relative to which the `AllUsers` or `AllGroups` - /// should be looking for its data files. This is a compromise between - /// exposing implementation details and providing fine enough - /// control over the behavior of this API. - pub fn scheme(mut self, scheme: String) -> Config { - self.scheme = scheme; - self - } - - // Prepend a path with the scheme in this Config - fn in_scheme(&self, path: impl AsRef) -> PathBuf { - let mut canonical_path = PathBuf::from(&self.scheme); - // Should be a little careful here, not sure I want this behavior - if path.as_ref().is_absolute() { - // This is nasty - canonical_path.push(path.as_ref().to_string_lossy()[1..].to_string()); - } else { - canonical_path.push(path); - } - canonical_path - } -} - -impl Default for Config { - /// Authentication is not enabled; The default base scheme is `file`. - fn default() -> Config { - Config { - auth_enabled: false, - scheme: String::from(DEFAULT_SCHEME), - auth_delay: Duration::new(DEFAULT_TIMEOUT, 0), - min_id: MIN_ID, - max_id: MAX_ID, - } - } -} - -// Nasty hack to prevent the compiler complaining about -// "leaking" `AllInner` -mod sealed { - use Config; - - pub trait Name { - fn name(&self) -> &str; - } - - pub trait Id { - fn id(&self) -> usize; - } - - pub trait AllInner { - // Group+User, thanks Dad - type Gruser: Name + Id; - - /// These functions grab internal elements so that the other - /// methods of `All` can manipulate them. - fn list(&self) -> &Vec; - fn list_mut(&mut self) -> &mut Vec; - fn config(&self) -> &Config; - } -} - -use sealed::{AllInner, Id, Name}; - -/// This trait is used to remove repetitive API items from -/// [`AllGroups`] and [`AllUsers`]. It uses a hidden trait -/// so that the implementations of functions can be implemented -/// at the trait level. Do not try to implement this trait. -pub trait All: AllInner { - /// Get an iterator borrowing all [`User`](struct.User.html)'s - /// or [`Group`](struct.Group.html)'s on the system. - fn iter(&self) -> Iter<::Gruser> { - self.list().iter() - } - - /// Get an iterator mutably borrowing all [`User`](struct.User.html)'s - /// or [`Group`](struct.Group.html)'s on the system. - fn iter_mut(&mut self) -> IterMut<::Gruser> { - self.list_mut().iter_mut() - } - - /// Borrow the [`User`](struct.User.html) or [`Group`](struct.Group.html) - /// with a given name. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ```no_run - /// # use redox_users::{All, AllUsers, Config}; - /// let users = AllUsers::new(Config::default()).unwrap(); - /// let user = users.get_by_name("root").unwrap(); - /// ``` - fn get_by_name(&self, name: impl AsRef) -> Option<&::Gruser> { - self.iter() - .find(|gruser| gruser.name() == name.as_ref() ) - } - - /// Mutable version of [`get_by_name`](trait.All.html#method.get_by_name). - fn get_mut_by_name(&mut self, name: impl AsRef) -> Option<&mut ::Gruser> { - self.iter_mut() - .find(|gruser| gruser.name() == name.as_ref() ) - } - - /// Borrow the [`User`](struct.User.html) or [`Group`](struct.Group.html) - /// with the given ID. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ```no_run - /// # use redox_users::{All, AllUsers, Config}; - /// let users = AllUsers::new(Config::default()).unwrap(); - /// let user = users.get_by_id(0).unwrap(); - /// ``` - fn get_by_id(&self, id: usize) -> Option<&::Gruser> { - self.iter() - .find(|gruser| gruser.id() == id ) - } - - /// Mutable version of [`get_by_id`](trait.All.html#method.get_by_id). - fn get_mut_by_id(&mut self, id: usize) -> Option<&mut ::Gruser> { - self.iter_mut() - .find(|gruser| gruser.id() == id ) - } - - /// Provides an unused id based on the min and max values in - /// the [`Config`](struct.Config.html) passed to the `All`'s constructor. - /// - /// # Examples - /// - /// ```no_run - /// # use redox_users::{All, AllUsers, Config}; - /// let users = AllUsers::new(Config::default()).unwrap(); - /// let uid = users.get_unique_id().expect("no available uid"); - /// ``` - fn get_unique_id(&self) -> Option { - for id in self.config().min_id..self.config().max_id { - if !self.iter().any(|gruser| gruser.id() == id ) { - return Some(id) - } - } - None - } - - /// Remove a [`User`](struct.User.html) or [`Group`](struct.Group.html) - /// from this `All` given it's name. This won't provide an indication - /// of whether the user was removed or not, but is guaranteed to work - /// if a user with the specified name exists. - fn remove_by_name(&mut self, name: impl AsRef) { - // Significantly more elegant than other possible solutions. - // I wish it could indicate if it removed anything. - self.list_mut() - .retain(|gruser| gruser.name() != name.as_ref() ); - } - - /// Id version of [`remove_by_name`](trait.All.html#method.remove_by_name). - fn remove_by_id(&mut self, id: usize) { - self.list_mut() - .retain(|gruser| gruser.id() != id ); - } -} - -/// [`AllUsers`](struct.AllUsers.html) provides -/// (borrowed) access to all the users on the system. -/// Note that this struct implements [`All`](trait.All.html) for -/// a bunch of convenient access functions. -/// -/// # Notes -/// Note that everything in this section also applies to -/// [`AllGroups`](struct.AllGroups.html) -/// -/// * If you mutate anything owned by an `AllUsers`, -/// you must call the [`save`](struct.AllUsers.html#method.save) -/// method in order for those changes to be applied to the system. -/// * The API here is kept small on purpose in order to reduce the -/// surface area for security exploitation. Most mutating actions -/// can be accomplished via the [`get_mut_by_id`](struct.AllUsers.html#method.get_mut_by_id) -/// and [`get_mut_by_name`](struct.AllUsers.html#method.get_mut_by_name) -/// functions. -/// -/// # Shadowfile handling -/// This implementation of redox-users uses a shadowfile implemented primarily -/// by this struct. `AllUsers` respects the `auth_enabled` status of the `Config` -/// that is was passed. If auth is enabled, it populates the -/// hash fields of each user struct that it parses from `/etc/passwd` with -/// info from `/et/shadow`. If a caller attempts to perform an action that -/// requires this info with an `AllUsers` config that does not have auth enabled, -/// the `User` handling action will panic. -pub struct AllUsers { - users: Vec, - config: Config, -} - -impl AllUsers { - /// See [Shadowfile Handling](struct.AllUsers.html#shadowfile-handling) for - /// configuration information regarding this constructor. - //TODO: Indicate if parsing an individual line failed or not - pub fn new(config: Config) -> Result { - let passwd_cntnt = read_locked_file(config.in_scheme(PASSWD_FILE))?; - - let mut passwd_entries: Vec = Vec::new(); - for line in passwd_cntnt.lines() { - if let Ok(mut user) = User::from_str(line) { - user.auth_delay = config.auth_delay; - passwd_entries.push(user); - } - } - - if config.auth_enabled { - let shadow_cntnt = read_locked_file(config.in_scheme(SHADOW_FILE))?; - let shadow_entries: Vec<&str> = shadow_cntnt.lines().collect(); - for entry in shadow_entries.iter() { - let mut entry = entry.split(';'); - let name = entry.next().ok_or(parse_error( - "error parsing shadowfile: expected username" - ))?; - let hash = entry.next().ok_or(parse_error( - "error parsing shadowfile: expected hash" - ))?; - passwd_entries - .iter_mut() - .find(|user| user.user == name) - .ok_or(parse_error( - "error parsing shadowfile: unkown user" - ))? - .populate_hash(hash)?; - } - } - - Ok(AllUsers { - users: passwd_entries, - config - }) - } - - /// Adds a user with the specified attributes to the `AllUsers` - /// instance. Note that the user's password is set unset (see - /// [Unset vs Blank Passwords](struct.User.html#unset-vs-blank-passwords)) - /// during this call. - /// - /// This function is classified as a mutating operation, - /// and users must therefore call [`save`](struct.AllUsers.html#method.save) - /// in order for the new user to be applied to the system. - /// - /// # Panics - /// This function will `panic!` if the [`Config`](struct.Config.html) - /// passed to [`AllUsers::new`](struct.AllUsers.html#method.new) - /// does not have authentication enabled (see - /// [`Shadowfile handling`](struct.AllUsers.html#shadowfile-handling)). - //TODO: Take uid/gid as Option and if none, find an unused ID. - pub fn add_user( - &mut self, - login: &str, - uid: usize, - gid: usize, - name: &str, - home: &str, - shell: &str - ) -> Result<()> { - if self.iter() - .any(|user| user.user == login || user.uid == uid) - { - return Err(From::from(UsersError::AlreadyExists)) - } - - if !self.config.auth_enabled { - panic!("Attempt to create user without access to the shadowfile"); - } - - self.users.push(User { - user: login.into(), - hash: Some(("!".into(), false)), - uid, - gid, - name: name.into(), - home: home.into(), - shell: shell.into(), - auth_delay: self.config.auth_delay - }); - Ok(()) - } - - /// Syncs the data stored in the `AllUsers` instance to the filesystem. - /// To apply changes to the system from an `AllUsers`, you MUST call this function! - pub fn save(&self) -> Result<()> { - let mut userstring = String::new(); - let mut shadowstring = String::new(); - for user in &self.users { - userstring.push_str(&format!("{}\n", user.to_string().as_str())); - if self.config.auth_enabled { - shadowstring.push_str(&format!("{}\n", user.shadowstring())); - } - } - - write_locked_file(self.config.in_scheme(PASSWD_FILE), userstring)?; - if self.config.auth_enabled { - write_locked_file(self.config.in_scheme(SHADOW_FILE), shadowstring)?; - } - Ok(()) - } -} - -impl AllInner for AllUsers { - type Gruser = User; - - fn list(&self) -> &Vec { - &self.users - } - - fn list_mut(&mut self) -> &mut Vec { - &mut self.users - } - - fn config(&self) -> &Config { - &self.config - } -} - -impl All for AllUsers {} - -impl Debug for AllUsers { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "AllUsers {{\nusers: {:?}\n}}", self.users) - } -} - -/// [`AllGroups`](struct.AllGroups.html) provides -/// (borrowed) access to all groups on the system. Note that this -/// struct implements [`All`](trait.All.html), for a bunch of convenience -/// functions. -/// -/// General notes that also apply to this struct may be found with -/// [`AllUsers`](struct.AllUsers.html). -pub struct AllGroups { - groups: Vec, - config: Config, -} - -impl AllGroups { - /// Create a new `AllGroups`. - //TODO: Indicate if parsing an individual line failed or not - pub fn new(config: Config) -> Result { - let group_cntnt = read_locked_file(config.in_scheme(GROUP_FILE))?; - - let mut entries: Vec = Vec::new(); - for line in group_cntnt.lines() { - if let Ok(group) = Group::from_str(line) { - entries.push(group); - } - } - - Ok(AllGroups { - groups: entries, - config, - }) - } - - /// Adds a group with the specified attributes to this `AllGroups`. - /// - /// This function is classified as a mutating operation, - /// and users must therefore call [`save`](struct.AllGroups.html#method.save) - /// in order for the new group to be applied to the system. - //TODO: Take Option for gid and find unused ID if None - pub fn add_group( - &mut self, - name: &str, - gid: usize, - users: &[&str] - ) -> Result<()> { - if self.iter() - .any(|group| group.group == name || group.gid == gid) - { - return Err(From::from(UsersError::AlreadyExists)) - } - - //Might be cleaner... Also breaks... - //users: users.iter().map(String::to_string).collect() - self.groups.push(Group { - group: name.into(), - gid, - users: users - .iter() - .map(|user| user.to_string()) - .collect() - }); - - Ok(()) - } - - /// Syncs the data stored in this `AllGroups` instance to the filesystem. - /// To apply changes from an `AllGroups`, you MUST call this function! - pub fn save(&self) -> Result<()> { - let mut groupstring = String::new(); - for group in &self.groups { - groupstring.push_str(&format!("{}\n", group.to_string().as_str())); - } - - write_locked_file(self.config.in_scheme(GROUP_FILE), groupstring) - } -} - -impl AllInner for AllGroups { - type Gruser = Group; - - fn list(&self) -> &Vec { - &self.groups - } - - fn list_mut(&mut self) -> &mut Vec { - &mut self.groups - } - - fn config(&self) -> &Config { - &self.config - } -} - -impl All for AllGroups {} - -#[cfg(test)] -mod test { - use super::*; - - const TEST_PREFIX: &'static str = "tests"; - - /// Needed for the file checks, this is done by the library - fn test_prefix(filename: &str) -> String { - let mut complete = String::from(TEST_PREFIX); - complete.push_str(filename); - complete - } - - fn test_cfg() -> Config { - Config::default() - // Since all this really does is prepend `sheme` to the consts - .scheme(TEST_PREFIX.to_string()) - } - - fn test_auth_cfg() -> Config { - test_cfg().auth(true) - } - - // *** struct.User *** - #[test] - #[should_panic(expected = "Hash not populated!")] - fn wrong_attempt_set_password() { - let mut users = AllUsers::new(test_cfg()).unwrap(); - let user = users.get_mut_by_id(1000).unwrap(); - user.set_passwd("").unwrap(); - } - - #[test] - #[should_panic(expected = "Hash not populated!")] - fn wrong_attempt_unset_password() { - let mut users = AllUsers::new(test_cfg()).unwrap(); - let user = users.get_mut_by_id(1000).unwrap(); - user.unset_passwd(); - } - - #[test] - #[should_panic(expected = "Hash not populated!")] - fn wrong_attempt_verify_password() { - let mut users = AllUsers::new(test_cfg()).unwrap(); - let user = users.get_mut_by_id(1000).unwrap(); - user.verify_passwd("hi folks"); - } - - #[test] - #[should_panic(expected = "Hash not populated!")] - fn wrong_attempt_is_password_blank() { - let mut users = AllUsers::new(test_cfg()).unwrap(); - let user = users.get_mut_by_id(1000).unwrap(); - user.is_passwd_blank(); - } - - #[test] - #[should_panic(expected = "Hash not populated!")] - fn wrong_attempt_is_password_unset() { - let mut users = AllUsers::new(test_cfg()).unwrap(); - let user = users.get_mut_by_id(1000).unwrap(); - user.is_passwd_unset(); - } - - #[test] - fn attempt_user_api() { - let mut users = AllUsers::new(test_auth_cfg()).unwrap(); - let user = users.get_mut_by_id(1000).unwrap(); - - assert_eq!(user.is_passwd_blank(), true); - assert_eq!(user.is_passwd_unset(), false); - assert_eq!(user.verify_passwd(""), true); - assert_eq!(user.verify_passwd("Something"), false); - - user.set_passwd("hi,i_am_passwd").unwrap(); - - assert_eq!(user.is_passwd_blank(), false); - assert_eq!(user.is_passwd_unset(), false); - assert_eq!(user.verify_passwd(""), false); - assert_eq!(user.verify_passwd("Something"), false); - assert_eq!(user.verify_passwd("hi,i_am_passwd"), true); - - user.unset_passwd(); - - assert_eq!(user.is_passwd_blank(), false); - assert_eq!(user.is_passwd_unset(), true); - assert_eq!(user.verify_passwd(""), false); - assert_eq!(user.verify_passwd("Something"), false); - assert_eq!(user.verify_passwd("hi,i_am_passwd"), false); - - user.set_passwd("").unwrap(); - - assert_eq!(user.is_passwd_blank(), true); - assert_eq!(user.is_passwd_unset(), false); - assert_eq!(user.verify_passwd(""), true); - assert_eq!(user.verify_passwd("Something"), false); - } - - // *** struct.AllUsers *** - #[test] - fn get_user() { - let users = AllUsers::new(test_auth_cfg()).unwrap(); - - let root = users.get_by_id(0).expect("'root' user missing"); - assert_eq!(root.user, "root".to_string()); - let &(ref hashstring, ref encoded) = root.hash.as_ref().expect("'root' hash is None"); - assert_eq!(hashstring, - &"$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk".to_string()); - assert_eq!(root.uid, 0); - assert_eq!(root.gid, 0); - assert_eq!(root.name, "root".to_string()); - assert_eq!(root.home, "file:/root".to_string()); - assert_eq!(root.shell, "file:/bin/ion".to_string()); - match encoded { - true => (), - false => panic!("Expected encoded argon hash!") - } - - let user = users.get_by_name("user").expect("'user' user missing"); - assert_eq!(user.user, "user".to_string()); - let &(ref hashstring, ref encoded) = user.hash.as_ref().expect("'user' hash is None"); - assert_eq!(hashstring, &"".to_string()); - assert_eq!(user.uid, 1000); - assert_eq!(user.gid, 1000); - assert_eq!(user.name, "user".to_string()); - assert_eq!(user.home, "file:/home/user".to_string()); - assert_eq!(user.shell, "file:/bin/ion".to_string()); - match encoded { - true => panic!("Should not be an argon hash!"), - false => () - } - println!("{:?}", users); - - let li = users.get_by_name("li").expect("'li' user missing"); - println!("got li"); - assert_eq!(li.user, "li"); - let &(ref hashstring, ref encoded) = li.hash.as_ref().expect("'li' hash is None"); - assert_eq!(hashstring, &"!".to_string()); - assert_eq!(li.uid, 1007); - assert_eq!(li.gid, 1007); - assert_eq!(li.name, "Lorem".to_string()); - assert_eq!(li.home, "file:/home/lorem".to_string()); - assert_eq!(li.shell, "file:/bin/ion".to_string()); - match encoded { - true => panic!("Should not be an argon hash!"), - false => () - } - } - - #[test] - fn manip_user() { - let mut users = AllUsers::new(test_auth_cfg()).unwrap(); - // NOT testing `get_unique_id` - let id = 7099; - users - .add_user("fb", id, id, "FooBar", "/home/foob", "/bin/zsh") - .expect("failed to add user 'fb'"); - // weirdo ^^^^^^^^ :P - users.save().unwrap(); - let p_file_content = read_locked_file(test_prefix(PASSWD_FILE)).unwrap(); - assert_eq!( - p_file_content, - concat!( - "root;0;0;root;file:/root;file:/bin/ion\n", - "user;1000;1000;user;file:/home/user;file:/bin/ion\n", - "li;1007;1007;Lorem;file:/home/lorem;file:/bin/ion\n", - "fb;7099;7099;FooBar;/home/foob;/bin/zsh\n" - ) - ); - let s_file_content = read_locked_file(test_prefix(SHADOW_FILE)).unwrap(); - assert_eq!(s_file_content, concat!( - "root;$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk\n", - "user;\n", - "li;!\n", - "fb;!\n" - )); - - { - println!("{:?}", users); - let fb = users.get_mut_by_name("fb").expect("'fb' user missing"); - fb.shell = "/bin/fish".to_string(); // That's better - fb.set_passwd("").unwrap(); - } - users.save().unwrap(); - let p_file_content = read_locked_file(test_prefix(PASSWD_FILE)).unwrap(); - assert_eq!( - p_file_content, - concat!( - "root;0;0;root;file:/root;file:/bin/ion\n", - "user;1000;1000;user;file:/home/user;file:/bin/ion\n", - "li;1007;1007;Lorem;file:/home/lorem;file:/bin/ion\n", - "fb;7099;7099;FooBar;/home/foob;/bin/fish\n" - ) - ); - let s_file_content = read_locked_file(test_prefix(SHADOW_FILE)).unwrap(); - assert_eq!(s_file_content, concat!( - "root;$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk\n", - "user;\n", - "li;!\n", - "fb;\n" - )); - - users.remove_by_id(id); - users.save().unwrap(); - let file_content = read_locked_file(test_prefix(PASSWD_FILE)).unwrap(); - assert_eq!( - file_content, - concat!( - "root;0;0;root;file:/root;file:/bin/ion\n", - "user;1000;1000;user;file:/home/user;file:/bin/ion\n", - "li;1007;1007;Lorem;file:/home/lorem;file:/bin/ion\n" - ) - ); - } - - #[test] - fn get_group() { - let groups = AllGroups::new(test_cfg()).unwrap(); - let user = groups.get_by_name("user").unwrap(); - assert_eq!(user.group, "user"); - assert_eq!(user.gid, 1000); - assert_eq!(user.users, vec!["user"]); - - let wheel = groups.get_by_id(1).unwrap(); - assert_eq!(wheel.group, "wheel"); - assert_eq!(wheel.gid, 1); - assert_eq!(wheel.users, vec!["user", "root"]); - } - - #[test] - fn manip_group() { - let mut groups = AllGroups::new(test_cfg()).unwrap(); - // NOT testing `get_unique_id` - let id = 7099; - - groups.add_group("fb", id, &["fb"]).unwrap(); - groups.save().unwrap(); - let file_content = read_locked_file(test_prefix(GROUP_FILE)).unwrap(); - assert_eq!( - file_content, - concat!( - "root;0;root\n", - "user;1000;user\n", - "wheel;1;user,root\n", - "li;1007;li\n", - "fb;7099;fb\n" - ) - ); - - { - let fb = groups.get_mut_by_name("fb").unwrap(); - fb.users.push("user".to_string()); - } - groups.save().unwrap(); - let file_content = read_locked_file(test_prefix(GROUP_FILE)).unwrap(); - assert_eq!( - file_content, - concat!( - "root;0;root\n", - "user;1000;user\n", - "wheel;1;user,root\n", - "li;1007;li\n", - "fb;7099;fb,user\n" - ) - ); - - groups.remove_by_id(id); - groups.save().unwrap(); - let file_content = read_locked_file(test_prefix(GROUP_FILE)).unwrap(); - assert_eq!( - file_content, - concat!( - "root;0;root\n", - "user;1000;user\n", - "wheel;1;user,root\n", - "li;1007;li\n" - ) - ); - } - - // *** Misc *** - #[test] - fn users_get_unused_ids() { - let users = AllUsers::new(test_cfg()).unwrap(); - let id = users.get_unique_id().unwrap(); - if id < users.config.min_id || id > users.config.max_id { - panic!("User ID is not between allowed margins") - } else if let Some(_) = users.get_by_id(id) { - panic!("User ID is used!"); - } - } - - #[test] - fn groups_get_unused_ids() { - let groups = AllGroups::new(test_cfg()).unwrap(); - let id = groups.get_unique_id().unwrap(); - if id < groups.config.min_id || id > groups.config.max_id { - panic!("Group ID is not between allowed margins") - } else if let Some(_) = groups.get_by_id(id) { - panic!("Group ID is used!"); - } - } -} diff --git a/vendor/redox_users-0.3.4/tests/etc/group b/vendor/redox_users-0.3.4/tests/etc/group deleted file mode 100644 index 89cb5e61bb..0000000000 --- a/vendor/redox_users-0.3.4/tests/etc/group +++ /dev/null @@ -1,4 +0,0 @@ -root;0;root -user;1000;user -wheel;1;user,root -li;1007;li diff --git a/vendor/redox_users-0.3.4/tests/etc/passwd b/vendor/redox_users-0.3.4/tests/etc/passwd deleted file mode 100644 index 0679ecfdc1..0000000000 --- a/vendor/redox_users-0.3.4/tests/etc/passwd +++ /dev/null @@ -1,3 +0,0 @@ -root;0;0;root;file:/root;file:/bin/ion -user;1000;1000;user;file:/home/user;file:/bin/ion -li;1007;1007;Lorem;file:/home/lorem;file:/bin/ion diff --git a/vendor/redox_users-0.3.4/tests/etc/shadow b/vendor/redox_users-0.3.4/tests/etc/shadow deleted file mode 100644 index e0bab42a8d..0000000000 --- a/vendor/redox_users-0.3.4/tests/etc/shadow +++ /dev/null @@ -1,3 +0,0 @@ -root;$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk -user; -li;! diff --git a/vendor/regex-syntax/.cargo-checksum.json b/vendor/regex-syntax/.cargo-checksum.json index 27222f8f42..1afbd746fb 100644 --- a/vendor/regex-syntax/.cargo-checksum.json +++ b/vendor/regex-syntax/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"5e00dd78ac913f94b4b03bece4bb4201e5a0a0915f6b700d4427021d31d7d1b2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7e9a134c72b09540e6f81f02133c5ae7d35067ea6fec44a94a1ebd20af47b151","benches/bench.rs":"f04160a876ee69bc9938bf51227513d6dbf3608643bc8ae422200f7ffc5ca85f","src/ast/mod.rs":"ff7e81186be4f7dea848363622bcd13cd8bf5b0826ea0fd7784a46547d9cf7c0","src/ast/parse.rs":"39fae33ce40c051086811861cec4df912da91c40b74f09e478592e770cf2edee","src/ast/print.rs":"b075392a6d5b48713e09aa510199bb7380aca2cf09fa4bc0efb5c49782630dda","src/ast/visitor.rs":"fb1489ed5ce019091dde244acd8b027e391be442aef3a9033c785c81a4c251fb","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"dd937a59d5caed6ca430b884ca4d26116a57ba4c74e4f11797b255d1ac6ace51","src/hir/interval.rs":"fcd0babe3bddbe411e04adff7f4d8855db1d6aaa7d8e2180bba819abad576736","src/hir/literal/mod.rs":"b0a01a3d7e524277ada88d5b58efcced498a53addfac69355fcc368c4c4dfb0f","src/hir/mod.rs":"384d44974c90b3520f0ce1426749e6b3abaf29d7031504fd57e22a3c2e7ab3d0","src/hir/print.rs":"1bd12a70e5876d85eb2188d83c4b71c9533dc6fff0c1ab5c2b0e4701de7e7a90","src/hir/translate.rs":"1cf3f0822faeb45134e31d7dfa70ef873a92febfeabd64b694ae7c64c839ddb2","src/hir/visitor.rs":"203dbe93e4a8cde395c6ff5a0eb98c9c3737bc5ea11fe7163f5e7bf1babc1f69","src/lib.rs":"8282e9bf1babcd423a90215a7701f6fe2e3259e4a129c847c6a84d7a3ffc2c48","src/parser.rs":"10cc145d79c275c7e19b8cc9078754f23fc1da9a2c3a2e56041a8616d5f85dea","src/unicode.rs":"f1cd662a1df564be951a1df80560f1486dfe471ee9ea04d713fc6c5faf310642","src/unicode_tables/LICENSE-UNICODE":"74db5baf44a41b1000312c673544b3374e4198af5605c7f9080a402cec42cfa3","src/unicode_tables/age.rs":"b0932a020d3386478dd2f4839c59e30c525e8591735052b9e791e1ce3a2e2b72","src/unicode_tables/case_folding_simple.rs":"6d1f3d095132639228faf4806d05308c70ce2baa68cce69dca01ea159c4eaa15","src/unicode_tables/general_category.rs":"d21877600d387b8a0c5fbb0942458d0330c69aad6565e28134b8a1a371d2f4f4","src/unicode_tables/grapheme_cluster_break.rs":"f03a8be4a00265b568ca2a41d99f66a5d0f5fb423cb4113494153423a1123cda","src/unicode_tables/mod.rs":"26c837099cd934c8062e24bc9a0aaecf15fe1de03f9c6da3f3e1e5ac3ca24bee","src/unicode_tables/perl_decimal.rs":"e39a5934b504eb3282ccb26bbf50ecd764e720120eb7cf6c43662a2321665ab5","src/unicode_tables/perl_space.rs":"014e5d92b66730557e408c2d5c9b2f46d3d288aa85400ab9193c218c7b98ad21","src/unicode_tables/perl_word.rs":"ddf126f39171776ef83151d7a0dbc41da8dd09186723211fb966c4b304247a5e","src/unicode_tables/property_bool.rs":"21f72bd9f3955e3443549ef6609418817ae6df3c81fb5be90a0ceee9d7d3002d","src/unicode_tables/property_names.rs":"504ea44604cd15a7e827a89066bb81a847dd5c57cef360d9f4a914cf22afcf36","src/unicode_tables/property_values.rs":"4d793ad1b664c1913db146897c8eb4fa29d181b821f096de90dc889b738edb88","src/unicode_tables/script.rs":"5a7d2a958b93056081b8b2eb87c3a5609579ad791ad5b0c42959362ce6ea5b31","src/unicode_tables/script_extension.rs":"1d5f1985f7dcae833e78c3858231666b535bf60e032cfacc09d014c22bda6690","src/unicode_tables/sentence_break.rs":"cd5f0eb7ab6b0ec1c1fb4d78496dfecd691d0d0b76495538b9f376645a753deb","src/unicode_tables/word_break.rs":"eabeacfde7558cfe7b1556b0221f09c65f049de0b08c7cd464c1669040610a6b","src/utf8.rs":"57a37660a7fe5698ea4721cdd91f0f7117bc12616a7ddf3f215bf22c620692b8","test":"9d0bc68616c249f317e783e5083102d2645a6ade3de735e8d8a414e97eaa76d0"},"package":"b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"} \ No newline at end of file +{"files":{"Cargo.toml":"bef24f541acc980aee14f67481d0ec8e5d7eee82341841c394d2c9a83db1743f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7e9a134c72b09540e6f81f02133c5ae7d35067ea6fec44a94a1ebd20af47b151","benches/bench.rs":"f04160a876ee69bc9938bf51227513d6dbf3608643bc8ae422200f7ffc5ca85f","src/ast/mod.rs":"ff7e81186be4f7dea848363622bcd13cd8bf5b0826ea0fd7784a46547d9cf7c0","src/ast/parse.rs":"39fae33ce40c051086811861cec4df912da91c40b74f09e478592e770cf2edee","src/ast/print.rs":"b075392a6d5b48713e09aa510199bb7380aca2cf09fa4bc0efb5c49782630dda","src/ast/visitor.rs":"fb1489ed5ce019091dde244acd8b027e391be442aef3a9033c785c81a4c251fb","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"dd937a59d5caed6ca430b884ca4d26116a57ba4c74e4f11797b255d1ac6ace51","src/hir/interval.rs":"fcd0babe3bddbe411e04adff7f4d8855db1d6aaa7d8e2180bba819abad576736","src/hir/literal/mod.rs":"b0a01a3d7e524277ada88d5b58efcced498a53addfac69355fcc368c4c4dfb0f","src/hir/mod.rs":"384d44974c90b3520f0ce1426749e6b3abaf29d7031504fd57e22a3c2e7ab3d0","src/hir/print.rs":"1bd12a70e5876d85eb2188d83c4b71c9533dc6fff0c1ab5c2b0e4701de7e7a90","src/hir/translate.rs":"1cf3f0822faeb45134e31d7dfa70ef873a92febfeabd64b694ae7c64c839ddb2","src/hir/visitor.rs":"203dbe93e4a8cde395c6ff5a0eb98c9c3737bc5ea11fe7163f5e7bf1babc1f69","src/lib.rs":"92d0173c5b36354724b356786523416bc652cbb02dbcdd62ecb8e4b3381e2c5d","src/parser.rs":"10cc145d79c275c7e19b8cc9078754f23fc1da9a2c3a2e56041a8616d5f85dea","src/unicode.rs":"22e52c7548a59283ef46b4ce27d35aa91d018c9d6f04ccf16ab88d3afd3a41d3","src/unicode_tables/LICENSE-UNICODE":"74db5baf44a41b1000312c673544b3374e4198af5605c7f9080a402cec42cfa3","src/unicode_tables/age.rs":"b0932a020d3386478dd2f4839c59e30c525e8591735052b9e791e1ce3a2e2b72","src/unicode_tables/case_folding_simple.rs":"6d1f3d095132639228faf4806d05308c70ce2baa68cce69dca01ea159c4eaa15","src/unicode_tables/general_category.rs":"d21877600d387b8a0c5fbb0942458d0330c69aad6565e28134b8a1a371d2f4f4","src/unicode_tables/grapheme_cluster_break.rs":"f03a8be4a00265b568ca2a41d99f66a5d0f5fb423cb4113494153423a1123cda","src/unicode_tables/mod.rs":"26c837099cd934c8062e24bc9a0aaecf15fe1de03f9c6da3f3e1e5ac3ca24bee","src/unicode_tables/perl_decimal.rs":"e39a5934b504eb3282ccb26bbf50ecd764e720120eb7cf6c43662a2321665ab5","src/unicode_tables/perl_space.rs":"014e5d92b66730557e408c2d5c9b2f46d3d288aa85400ab9193c218c7b98ad21","src/unicode_tables/perl_word.rs":"ddf126f39171776ef83151d7a0dbc41da8dd09186723211fb966c4b304247a5e","src/unicode_tables/property_bool.rs":"21f72bd9f3955e3443549ef6609418817ae6df3c81fb5be90a0ceee9d7d3002d","src/unicode_tables/property_names.rs":"504ea44604cd15a7e827a89066bb81a847dd5c57cef360d9f4a914cf22afcf36","src/unicode_tables/property_values.rs":"4d793ad1b664c1913db146897c8eb4fa29d181b821f096de90dc889b738edb88","src/unicode_tables/script.rs":"5a7d2a958b93056081b8b2eb87c3a5609579ad791ad5b0c42959362ce6ea5b31","src/unicode_tables/script_extension.rs":"1d5f1985f7dcae833e78c3858231666b535bf60e032cfacc09d014c22bda6690","src/unicode_tables/sentence_break.rs":"cd5f0eb7ab6b0ec1c1fb4d78496dfecd691d0d0b76495538b9f376645a753deb","src/unicode_tables/word_break.rs":"eabeacfde7558cfe7b1556b0221f09c65f049de0b08c7cd464c1669040610a6b","src/utf8.rs":"a42486af691ca686673b85df5661cd5b1ee793368d5571abd81893ec04094e3f","test":"9d0bc68616c249f317e783e5083102d2645a6ade3de735e8d8a414e97eaa76d0"},"package":"24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"} \ No newline at end of file diff --git a/vendor/regex-syntax/Cargo.toml b/vendor/regex-syntax/Cargo.toml index 0420a2f3b8..877b230d7e 100644 --- a/vendor/regex-syntax/Cargo.toml +++ b/vendor/regex-syntax/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "regex-syntax" -version = "0.6.22" +version = "0.6.23" authors = ["The Rust Project Developers"] description = "A regular expression parser." homepage = "https://github.com/rust-lang/regex" diff --git a/vendor/regex-syntax/src/lib.rs b/vendor/regex-syntax/src/lib.rs index edf1b993db..6be634a9db 100644 --- a/vendor/regex-syntax/src/lib.rs +++ b/vendor/regex-syntax/src/lib.rs @@ -216,7 +216,7 @@ pub fn is_meta_character(c: char) -> bool { /// character. /// /// A Unicode word character is defined by -/// [UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties). +/// [UTS#18 Annex C](https://unicode.org/reports/tr18/#Compatibility_Properties). /// In particular, a character /// is considered a word character if it is in either of the `Alphabetic` or /// `Join_Control` properties, or is in one of the `Decimal_Number`, `Mark` @@ -236,7 +236,7 @@ pub fn is_word_character(c: char) -> bool { /// character. /// /// A Unicode word character is defined by -/// [UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties). +/// [UTS#18 Annex C](https://unicode.org/reports/tr18/#Compatibility_Properties). /// In particular, a character /// is considered a word character if it is in either of the `Alphabetic` or /// `Join_Control` properties, or is in one of the `Decimal_Number`, `Mark` diff --git a/vendor/regex-syntax/src/unicode.rs b/vendor/regex-syntax/src/unicode.rs index a78362b2fb..73df6987b5 100644 --- a/vendor/regex-syntax/src/unicode.rs +++ b/vendor/regex-syntax/src/unicode.rs @@ -823,7 +823,7 @@ fn symbolic_name_normalize(x: &str) -> String { /// The slice returned is guaranteed to be valid UTF-8 for all possible values /// of `slice`. /// -/// See: http://unicode.org/reports/tr44/#UAX44-LM3 +/// See: https://unicode.org/reports/tr44/#UAX44-LM3 fn symbolic_name_normalize_bytes(slice: &mut [u8]) -> &mut [u8] { // I couldn't find a place in the standard that specified that property // names/aliases had a particular structure (unlike character names), but diff --git a/vendor/regex-syntax/src/utf8.rs b/vendor/regex-syntax/src/utf8.rs index 89862afb61..947ba7c5fe 100644 --- a/vendor/regex-syntax/src/utf8.rs +++ b/vendor/regex-syntax/src/utf8.rs @@ -15,7 +15,7 @@ whether a particular byte sequence was a Cyrillic character. One possible scalar value range is `[0400-04FF]`. The set of allowed bytes for this range can be expressed as a sequence of byte ranges: -```ignore +```text [D0-D3][80-BF] ``` @@ -32,7 +32,7 @@ for example, `04FF` (because its last byte, `BF` isn't in the range `80-AF`). Instead, you need multiple sequences of byte ranges: -```ignore +```text [D0-D3][80-BF] # matches codepoints 0400-04FF [D4][80-AF] # matches codepoints 0500-052F ``` @@ -41,7 +41,7 @@ This gets even more complicated if you want bigger ranges, particularly if they naively contain surrogate codepoints. For example, the sequence of byte ranges for the basic multilingual plane (`[0000-FFFF]`) look like this: -```ignore +```text [0-7F] [C2-DF][80-BF] [E0][A0-BF][80-BF] @@ -55,7 +55,7 @@ UTF-8, including encodings of surrogate codepoints. And, of course, for all of Unicode (`[000000-10FFFF]`): -```ignore +```text [0-7F] [C2-DF][80-BF] [E0][A0-BF][80-BF] @@ -157,13 +157,13 @@ impl Utf8Sequence { /// /// For example, if this corresponds to the following sequence: /// - /// ```ignore + /// ```text /// [D0-D3][80-BF] /// ``` /// /// Then after reversal, it will be /// - /// ```ignore + /// ```text /// [80-BF][D0-D3] /// ``` /// diff --git a/vendor/regex/.cargo-checksum.json b/vendor/regex/.cargo-checksum.json index 502707a75a..37c81b548c 100644 --- a/vendor/regex/.cargo-checksum.json +++ b/vendor/regex/.cargo-checksum.json @@ -1 +1 @@ -{"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 +{"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/CHANGELOG.md b/vendor/regex/CHANGELOG.md index cf020d228d..b9256786f6 100644 --- a/vendor/regex/CHANGELOG.md +++ b/vendor/regex/CHANGELOG.md @@ -1,3 +1,44 @@ +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`, `String`, `Cow`, etc. + + 1.4.3 (2021-01-08) ================== This is a small patch release that adds some missing standard trait diff --git a/vendor/regex/Cargo.lock b/vendor/regex/Cargo.lock index eeaac4a3ea..1921931c25 100644 --- a/vendor/regex/Cargo.lock +++ b/vendor/regex/Cargo.lock @@ -1,41 +1,33 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" -version = "0.7.6" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d" dependencies = [ "memchr", ] [[package]] -name = "autocfg" -version = "0.1.7" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "bitflags" -version = "1.2.1" +name = "getrandom" +version = "0.2.2" 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" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "bitflags", + "cfg-if", + "libc", + "wasi", ] -[[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" @@ -44,144 +36,46 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "memchr" -version = "2.3.0" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "quickcheck" -version = "0.8.5" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c35d9c36a562f37eca96e79f66d5fd56eefbc22560dacc4a864cabd2d277456" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" 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" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" dependencies = [ - "autocfg", - "rand_core 0.3.1", + "rand_core", ] [[package]] name = "rand_core" -version = "0.3.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" 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", + "getrandom", ] [[package]] name = "regex" -version = "1.4.3" +version = "1.4.6" dependencies = [ "aho-corasick", "lazy_static", @@ -189,42 +83,16 @@ dependencies = [ "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" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/vendor/regex/Cargo.toml b/vendor/regex/Cargo.toml index e43a1baf7e..bc4e58ff5f 100644 --- a/vendor/regex/Cargo.toml +++ b/vendor/regex/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "regex" -version = "1.4.3" +version = "1.4.6" authors = ["The Rust Project Developers"] exclude = ["/scripts/*", "/.github/*"] autotests = false @@ -82,25 +82,23 @@ 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" +version = "1.0.3" default-features = false [dev-dependencies.rand] -version = "0.6.5" +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 = ["thread_local"] +perf-cache = [] perf-dfa = [] perf-inline = [] perf-literal = ["aho-corasick", "memchr"] diff --git a/vendor/regex/README.md b/vendor/regex/README.md index 8c05a902d8..f7a2554555 100644 --- a/vendor/regex/README.md +++ b/vendor/regex/README.md @@ -245,12 +245,12 @@ supported version of Rust. 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) + https://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) + 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](http://www.unicode.org/copyright.html#License)). +([LICENSE-UNICODE](https://www.unicode.org/copyright.html#License)). diff --git a/vendor/regex/UNICODE.md b/vendor/regex/UNICODE.md index 18fa9b1038..df7d21ed97 100644 --- a/vendor/regex/UNICODE.md +++ b/vendor/regex/UNICODE.md @@ -1,7 +1,7 @@ # Unicode conformance This document describes the regex crate's conformance to Unicode's -[UTS#18](http://unicode.org/reports/tr18/) +[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 @@ -10,7 +10,7 @@ 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) + [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 @@ -61,18 +61,18 @@ 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) +* [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](http://unicode.org/reports/tr18/#RL1.2) explicitly. + [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`](http://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt) +[`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`](http://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt) +[`PropertyValueAliases.txt`](https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt) file. The syntax supported is also consistent with the UTS#18 recommendation: @@ -149,10 +149,10 @@ properties correspond to properties required by RL1.2): ## RL1.2a Compatibility Properties -[UTS#18 RL1.2a](http://unicode.org/reports/tr18/#RL1.2a) +[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](http://unicode.org/reports/tr18/#Compatibility_Properties) +[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 @@ -165,7 +165,7 @@ Their traditional ASCII definition can be used by disabling Unicode. That is, ## RL1.3 Subtraction and Intersection -[UTS#18 RL1.3](http://unicode.org/reports/tr18/#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 (`~~`) @@ -178,7 +178,7 @@ For example, to match all non-ASCII letters, you could use either ## RL1.4 Simple Word Boundaries -[UTS#18 RL1.4](http://unicode.org/reports/tr18/#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 @@ -196,9 +196,9 @@ the following classes: * `\p{gc:Connector_Punctuation}` In particular, this differs slightly from the -[prescription given in RL1.4](http://unicode.org/reports/tr18/#Simple_Word_Boundaries) +[prescription given in RL1.4](https://unicode.org/reports/tr18/#Simple_Word_Boundaries) but is permissible according to -[UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties). +[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. @@ -211,7 +211,7 @@ 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) +[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 @@ -226,7 +226,7 @@ then all characters classes are case folded as well. ## RL1.6 Line Boundaries -[UTS#18 RL1.6](http://unicode.org/reports/tr18/#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 @@ -239,7 +239,7 @@ well, and in theory, this could be done efficiently. ## RL1.7 Code Points -[UTS#18 RL1.7](http://unicode.org/reports/tr18/#Supplementary_Characters) +[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. diff --git a/vendor/regex/src/backtrack.rs b/vendor/regex/src/backtrack.rs index 2eaeb72e55..6100c1730d 100644 --- a/vendor/regex/src/backtrack.rs +++ b/vendor/regex/src/backtrack.rs @@ -115,8 +115,8 @@ impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> { // 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. + // 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 = diff --git a/vendor/regex/src/cache.rs b/vendor/regex/src/cache.rs deleted file mode 100644 index dbb7e64eb8..0000000000 --- a/vendor/regex/src/cache.rs +++ /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(CachedThreadLocal); - - #[derive(Debug)] - pub struct CachedGuard<'a, T: 'a>(&'a T); - - impl Cached { - pub fn new() -> Cached { - Cached(CachedThreadLocal::new()) - } - - pub fn get_or(&self, create: impl FnOnce() -> T) -> CachedGuard { - 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 { - stack: Mutex>, - /// 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>, - } - - #[derive(Debug)] - pub struct CachedGuard<'a, T: 'a + Send> { - cache: &'a Cached, - value: Option, - } - - impl Cached { - pub fn new() -> Cached { - Cached { stack: Mutex::new(vec![]), _phantom: PhantomData } - } - - pub fn get_or(&self, create: impl FnOnce() -> T) -> CachedGuard { - 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/src/compile.rs b/vendor/regex/src/compile.rs index 9ffd347044..9bbd464e0f 100644 --- a/vendor/regex/src/compile.rs +++ b/vendor/regex/src/compile.rs @@ -38,6 +38,7 @@ pub struct Compiler { suffix_cache: SuffixCache, utf8_seqs: Option, byte_classes: ByteClassSet, + extra_inst_bytes: usize, } impl Compiler { @@ -54,6 +55,7 @@ impl Compiler { suffix_cache: SuffixCache::new(1000), utf8_seqs: Some(Utf8Sequences::new('\x00', '\x00')), byte_classes: ByteClassSet::new(), + extra_inst_bytes: 0, } } @@ -420,6 +422,8 @@ impl Compiler { } 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()?)) @@ -429,6 +433,8 @@ impl Compiler { 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::() * 2); self.push_hole(InstHole::Ranges { ranges: ranges }) }; Ok(Some(Patch { hole: hole, entry: self.insts.len() - 1 })) @@ -795,7 +801,9 @@ impl Compiler { fn check_size(&self) -> result::Result<(), Error> { use std::mem::size_of; - if self.insts.len() * size_of::() > self.size_limit { + let size = + self.extra_inst_bytes + (self.insts.len() * size_of::()); + if size > self.size_limit { Err(Error::CompiledTooBig(self.size_limit)) } else { Ok(()) @@ -927,9 +935,10 @@ impl InstHole { 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::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 }) } diff --git a/vendor/regex/src/dfa.rs b/vendor/regex/src/dfa.rs index 2a365ee721..9ac0c2c393 100644 --- a/vendor/regex/src/dfa.rs +++ b/vendor/regex/src/dfa.rs @@ -848,7 +848,7 @@ impl<'a> Fsm<'a> { /// next_si transitions to the next state, where the transition input /// corresponds to text[i]. /// - /// This elides bounds checks, and is therefore unsafe. + /// 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? @@ -1688,7 +1688,7 @@ impl Transitions { self.num_byte_classes * mem::size_of::() } - /// Like `next`, but uses unchecked access and is therefore unsafe. + /// 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); @@ -1895,12 +1895,22 @@ mod tests { push_inst_ptr, read_vari32, read_varu32, write_vari32, write_varu32, State, StateFlags, }; - use quickcheck::{quickcheck, QuickCheck, StdGen}; + use quickcheck::{quickcheck, Gen, QuickCheck}; use std::sync::Arc; #[test] fn prop_state_encode_decode() { - fn p(ips: Vec, flags: u8) -> bool { + fn p(mut ips: Vec, 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() { @@ -1914,7 +1924,7 @@ mod tests { expected == got && state.flags() == StateFlags(flags) } QuickCheck::new() - .gen(StdGen::new(self::rand::thread_rng(), 10_000)) + .gen(Gen::new(10_000)) .quickcheck(p as fn(Vec, u8) -> bool); } diff --git a/vendor/regex/src/exec.rs b/vendor/regex/src/exec.rs index e1aae87088..3d5a52bead 100644 --- a/vendor/regex/src/exec.rs +++ b/vendor/regex/src/exec.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::collections::HashMap; +use std::panic::AssertUnwindSafe; use std::sync::Arc; #[cfg(feature = "perf-literal")] @@ -9,7 +10,6 @@ use syntax::hir::Hir; use syntax::ParserBuilder; use backtrack; -use cache::{Cached, CachedGuard}; use compile::Compiler; #[cfg(feature = "perf-dfa")] use dfa; @@ -17,6 +17,7 @@ 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; @@ -34,8 +35,15 @@ use utf8::next_utf8; pub struct Exec { /// All read only state. ro: Arc, - /// Caches for the various matching engines. - cache: Cached, + /// 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>, } /// `ExecNoSync` is like `Exec`, except it embeds a reference to a cache. This @@ -46,7 +54,7 @@ pub struct ExecNoSync<'c> { /// All read only state. ro: &'c Arc, /// Caches for the various matching engines. - cache: CachedGuard<'c, ProgramCache>, + cache: PoolGuard<'c, ProgramCache>, } /// `ExecNoSyncStr` is like `ExecNoSync`, but matches on &str instead of &[u8]. @@ -302,7 +310,8 @@ impl ExecBuilder { ac: None, match_type: MatchType::Nothing, }); - return Ok(Exec { ro: ro, cache: Cached::new() }); + let pool = ExecReadOnly::new_pool(&ro); + return Ok(Exec { ro: ro, pool }); } let parsed = self.parse()?; let mut nfa = Compiler::new() @@ -342,7 +351,8 @@ impl ExecBuilder { ro.match_type = ro.choose_match_type(self.match_type); let ro = Arc::new(ro); - Ok(Exec { ro: ro, cache: Cached::new() }) + let pool = ExecReadOnly::new_pool(&ro); + Ok(Exec { ro, pool }) } #[cfg(feature = "perf-literal")] @@ -1254,10 +1264,9 @@ 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), + cache: self.pool.get(), } } @@ -1309,7 +1318,8 @@ impl Exec { impl Clone for Exec { fn clone(&self) -> Exec { - Exec { ro: self.ro.clone(), cache: Cached::new() } + let pool = ExecReadOnly::new_pool(&self.ro); + Exec { ro: self.ro.clone(), pool } } } @@ -1442,6 +1452,13 @@ impl ExecReadOnly { let lcs_len = self.suffixes.lcs().char_len(); lcs_len >= 3 && lcs_len > self.dfa.prefixes.lcp().char_len() } + + fn new_pool(ro: &Arc) -> Box> { + let ro = ro.clone(); + Box::new(Pool::new(Box::new(move || { + AssertUnwindSafe(RefCell::new(ProgramCacheInner::new(&ro))) + }))) + } } #[derive(Clone, Copy, Debug)] @@ -1500,7 +1517,11 @@ enum MatchNfaType { /// `ProgramCache` maintains reusable allocations for each matching engine /// available to a particular program. -pub type ProgramCache = RefCell; +/// +/// 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>; #[derive(Debug)] pub struct ProgramCacheInner { diff --git a/vendor/regex/src/expand.rs b/vendor/regex/src/expand.rs index fd2ab03acb..70dbf91f42 100644 --- a/vendor/regex/src/expand.rs +++ b/vendor/regex/src/expand.rs @@ -144,7 +144,8 @@ fn find_cap_ref(replacement: &[u8]) -> Option { } // 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]. + // 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 { diff --git a/vendor/regex/src/lib.rs b/vendor/regex/src/lib.rs index d3dc58d66f..357ac0dd02 100644 --- a/vendor/regex/src/lib.rs +++ b/vendor/regex/src/lib.rs @@ -253,7 +253,7 @@ 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/), +[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. @@ -455,7 +455,7 @@ assert_eq!(&cap[0], "abc"); ## Perl character classes (Unicode friendly) These classes are based on the definitions provided in -[UTS#18](http://www.unicode.org/reports/tr18/#Compatibility_Properties): +[UTS#18](https://www.unicode.org/reports/tr18/#Compatibility_Properties):

 \d     digit (\p{Nd})
@@ -523,11 +523,6 @@ All features below are enabled by default.
   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
@@ -542,6 +537,11 @@ All features below are enabled by default.
   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
 
@@ -631,8 +631,6 @@ extern crate memchr;
 #[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");
@@ -749,7 +747,6 @@ pub mod bytes {
 }
 
 mod backtrack;
-mod cache;
 mod compile;
 #[cfg(feature = "perf-dfa")]
 mod dfa;
@@ -764,6 +761,7 @@ mod literal;
 #[cfg(feature = "pattern")]
 mod pattern;
 mod pikevm;
+mod pool;
 mod prog;
 mod re_builder;
 mod re_bytes;
diff --git a/vendor/regex/src/pool.rs b/vendor/regex/src/pool.rs
new file mode 100644
index 0000000000..a506ee9fab
--- /dev/null
+++ b/vendor/regex/src/pool.rs
@@ -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>. 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>. There
+// is no special trick for bypassing the mutex.
+//
+// (3) is the same as (2), except it uses Mutex>>. It is twice as
+// fast because a Box is much smaller than the T we use with a Pool in this
+// crate. So pushing and popping a Box 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 =
+    Box 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 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 {
+    /// 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>>,
+    /// A function to create more T values when stack is empty and a caller
+    /// has requested a T.
+    create: CreateFn,
+    /// 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
+// 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 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 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 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 Sync for Pool {}
+
+impl ::std::fmt::Debug for Pool {
+    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,
+    /// This is None when the guard represents the special "owned" value. In
+    /// which case, the value is retrieved from 'pool.owner_val'.
+    value: Option>,
+}
+
+impl Pool {
+    /// Create a new pool. The given closure is used to create values in the
+    /// pool when necessary.
+    pub fn new(create: CreateFn) -> Pool {
+        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 {
+        // 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 {
+        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) {
+        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) -> 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() {}
+        has_oibits::>();
+    }
+
+    // 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>>> =
+            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/src/prog.rs b/vendor/regex/src/prog.rs
index 74e5f2f6f8..a2b89c99eb 100644
--- a/vendor/regex/src/prog.rs
+++ b/vendor/regex/src/prog.rs
@@ -259,8 +259,8 @@ impl<'a> IntoIterator for &'a Program {
 ///
 /// 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`
+/// 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.
@@ -374,7 +374,7 @@ pub struct InstRanges {
     /// succeeds.
     pub goto: InstPtr,
     /// The set of Unicode scalar value ranges to test.
-    pub ranges: Vec<(char, char)>,
+    pub ranges: Box<[(char, char)]>,
 }
 
 impl InstRanges {
@@ -432,3 +432,16 @@ impl InstBytes {
         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::());
+    }
+}
diff --git a/vendor/regex/src/re_bytes.rs b/vendor/regex/src/re_bytes.rs
index a091436f14..204a70ad3e 100644
--- a/vendor/regex/src/re_bytes.rs
+++ b/vendor/regex/src/re_bytes.rs
@@ -1105,9 +1105,9 @@ impl<'c, 't> FusedIterator for SubCaptureMatches<'c, 't> {}
 /// 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` (or any `FnMut(&Captures) -> T`
-/// where `T: AsRef<[u8]>`), which covers most use cases.
+/// since implementations are already provided for `&[u8]` along with other
+/// variants of bytes types and `FnMut(&Captures) -> Vec` (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.
     ///
@@ -1176,10 +1176,55 @@ impl<'a> Replacer for &'a [u8] {
     }
 
     fn no_expansion(&mut self) -> Option> {
-        match find_byte(b'$', *self) {
-            Some(_) => None,
-            None => Some(Cow::Borrowed(*self)),
-        }
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for &'a Vec {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) {
+        caps.expand(*self, dst);
+    }
+
+    fn no_expansion(&mut self) -> Option> {
+        no_expansion(self)
+    }
+}
+
+impl Replacer for Vec {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) {
+        caps.expand(self, dst);
+    }
+
+    fn no_expansion(&mut self) -> Option> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for Cow<'a, [u8]> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) {
+        caps.expand(self.as_ref(), dst);
+    }
+
+    fn no_expansion(&mut self) -> Option> {
+        no_expansion(self)
+    }
+}
+
+impl<'a> Replacer for &'a Cow<'a, [u8]> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) {
+        caps.expand(self.as_ref(), dst);
+    }
+
+    fn no_expansion(&mut self) -> Option> {
+        no_expansion(self)
+    }
+}
+
+fn no_expansion>(t: &T) -> Option> {
+    let s = t.as_ref();
+    match find_byte(b'$', s) {
+        Some(_) => None,
+        None => Some(Cow::Borrowed(s)),
     }
 }
 
diff --git a/vendor/regex/src/re_set.rs b/vendor/regex/src/re_set.rs
index 0a00229de7..5cb47addb1 100644
--- a/vendor/regex/src/re_set.rs
+++ b/vendor/regex/src/re_set.rs
@@ -43,7 +43,7 @@ $(#[$doc_regexset_example])*
 /// Note that it would be possible to adapt the above example to using `Regex`
 /// with an expression like:
 ///
-/// ```ignore
+/// ```text
 /// (?P[a-z]+@(?P[a-z]+[.](com|org|net)))|(?P[a-z]+[.](com|org|net))
 /// ```
 ///
diff --git a/vendor/regex/src/re_unicode.rs b/vendor/regex/src/re_unicode.rs
index df87c3421a..1b478cdbad 100644
--- a/vendor/regex/src/re_unicode.rs
+++ b/vendor/regex/src/re_unicode.rs
@@ -1147,9 +1147,9 @@ 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`), which covers most use cases.
+/// 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`), which covers most use cases.
 pub trait Replacer {
     /// Appends text to `dst` to replace the current match.
     ///
@@ -1218,10 +1218,55 @@ impl<'a> Replacer for &'a str {
     }
 
     fn no_expansion(&mut self) -> Option> {
-        match find_byte(b'$', self.as_bytes()) {
-            Some(_) => None,
-            None => Some(Cow::Borrowed(*self)),
-        }
+        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> {
+        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> {
+        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> {
+        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> {
+        no_expansion(self)
+    }
+}
+
+fn no_expansion>(t: &T) -> Option> {
+    let s = t.as_ref();
+    match find_byte(b'$', s.as_bytes()) {
+        Some(_) => None,
+        None => Some(Cow::Borrowed(s)),
     }
 }
 
diff --git a/vendor/regex/src/sparse.rs b/vendor/regex/src/sparse.rs
index bc1b2b577c..421d6b6f1e 100644
--- a/vendor/regex/src/sparse.rs
+++ b/vendor/regex/src/sparse.rs
@@ -8,7 +8,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 allocations, so the initial allocation cost is bareable. However,
 /// its other properties listed above are extremely useful.
diff --git a/vendor/regex/tests/consistent.rs b/vendor/regex/tests/consistent.rs
index 0f9ea53f35..722f2a51a0 100644
--- a/vendor/regex/tests/consistent.rs
+++ b/vendor/regex/tests/consistent.rs
@@ -157,10 +157,7 @@ macro_rules! checker {
             }
 
             impl quickcheck::Testable for RegexEqualityTest {
-                fn result(
-                    &self,
-                    gen: &mut G,
-                ) -> TestResult {
+                fn result(&self, gen: &mut quickcheck::Gen) -> TestResult {
                     let input = $mk_input(gen);
                     let input = &input;
 
diff --git a/vendor/regex/tests/crazy.rs b/vendor/regex/tests/crazy.rs
index 56f6cadb90..293ac1ae72 100644
--- a/vendor/regex/tests/crazy.rs
+++ b/vendor/regex/tests/crazy.rs
@@ -137,9 +137,10 @@ matiter!(match_empty23, r"a(?:)|b", "abc", (0, 1), (1, 2));
 #[test]
 fn dfa_handles_pathological_case() {
     fn ones_and_zeroes(count: usize) -> String {
-        use rand::{thread_rng, Rng};
+        use rand::rngs::SmallRng;
+        use rand::{Rng, SeedableRng};
 
-        let mut rng = thread_rng();
+        let mut rng = SmallRng::from_entropy();
         let mut s = String::new();
         for _ in 0..count {
             if rng.gen() {
diff --git a/vendor/regex/tests/macros_bytes.rs b/vendor/regex/tests/macros_bytes.rs
index 03c370d698..3d6c8c3ac8 100644
--- a/vendor/regex/tests/macros_bytes.rs
+++ b/vendor/regex/tests/macros_bytes.rs
@@ -4,7 +4,6 @@ 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 { () => { >::new() } }
-
 macro_rules! bytes { ($text:expr) => { $text } }
 
 macro_rules! no_expand {
diff --git a/vendor/regex/tests/macros_str.rs b/vendor/regex/tests/macros_str.rs
index 9b996b33b9..7b7eb110c2 100644
--- a/vendor/regex/tests/macros_str.rs
+++ b/vendor/regex/tests/macros_str.rs
@@ -4,6 +4,7 @@ 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 { () => { >::new() } }
+macro_rules! bytes { ($text:expr) => { std::str::from_utf8($text.as_ref()).unwrap() } }
 
 macro_rules! no_expand {
     ($text:expr) => {{
diff --git a/vendor/regex/tests/regression_fuzz.rs b/vendor/regex/tests/regression_fuzz.rs
index 5f92ed046c..4e76704d2a 100644
--- a/vendor/regex/tests/regression_fuzz.rs
+++ b/vendor/regex/tests/regression_fuzz.rs
@@ -17,3 +17,15 @@ fn fuzz1() {
 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/tests/replace.rs b/vendor/regex/tests/replace.rs
index c156a399ff..700aff2430 100644
--- a/vendor/regex/tests/replace.rs
+++ b/vendor/regex/tests/replace.rs
@@ -130,3 +130,101 @@ replace!(
     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/tests/test_default.rs b/vendor/regex/tests/test_default.rs
index 241e5804ca..af634a0c57 100644
--- a/vendor/regex/tests/test_default.rs
+++ b/vendor/regex/tests/test_default.rs
@@ -83,26 +83,49 @@ fn allow_octal() {
 #[test]
 fn oibits() {
     use regex::bytes;
-    use regex::{Regex, RegexBuilder};
-    use std::panic::UnwindSafe;
+    use regex::{Regex, RegexBuilder, RegexSet, RegexSetBuilder};
+    use std::panic::{RefUnwindSafe, UnwindSafe};
 
     fn assert_send() {}
     fn assert_sync() {}
     fn assert_unwind_safe() {}
+    fn assert_ref_unwind_safe() {}
 
     assert_send::();
     assert_sync::();
     assert_unwind_safe::();
+    assert_ref_unwind_safe::();
     assert_send::();
     assert_sync::();
     assert_unwind_safe::();
+    assert_ref_unwind_safe::();
 
     assert_send::();
     assert_sync::();
     assert_unwind_safe::();
+    assert_ref_unwind_safe::();
     assert_send::();
     assert_sync::();
     assert_unwind_safe::();
+    assert_ref_unwind_safe::();
+
+    assert_send::();
+    assert_sync::();
+    assert_unwind_safe::();
+    assert_ref_unwind_safe::();
+    assert_send::();
+    assert_sync::();
+    assert_unwind_safe::();
+    assert_ref_unwind_safe::();
+
+    assert_send::();
+    assert_sync::();
+    assert_unwind_safe::();
+    assert_ref_unwind_safe::();
+    assert_send::();
+    assert_sync::();
+    assert_unwind_safe::();
+    assert_ref_unwind_safe::();
 }
 
 // See: https://github.com/rust-lang/regex/issues/568
@@ -113,3 +136,18 @@ fn oibits_regression() {
 
     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::());
+    assert_eq!(16, size_of::());
+    assert_eq!(16, size_of::());
+    assert_eq!(16, size_of::());
+}
diff --git a/vendor/rust-argon2/.cargo-checksum.json b/vendor/rust-argon2/.cargo-checksum.json
deleted file mode 100644
index 18d59dcb9e..0000000000
--- a/vendor/rust-argon2/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"be3184d61ddd56f819ab0f4a2efd0dac96c6f80064e786a738a9c50ee11aba40","Cargo.toml":"59dc265a9095129a085b4734b5a70fd75920ac96f8b1e44d549301a11b1be73e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"26b997d1a1496df49cb1ad2cbe024714cd9126543c18e1bc6c7bbca1b3dc42b6","README.md":"32018a582e25c198dd736e14ac7f998050e71c1a78841f4757544d9bf9fa22c3","src/argon2.rs":"7c40d403a9a25394f41871e69295662b160246bdcc3322d5fea2da6bd3f8ea46","src/block.rs":"52bb31ab5d788d792d7ab2b1979f770cc13e0fdeba29005eee62b9a5d9696726","src/common.rs":"ff3d031e058e65cc03247008c61ba702e08d2d2545536c86aa208bbc05e7e8e2","src/config.rs":"e091c12789ae40a73736494eb6ee96db7eae418219a855da15049d43843b852f","src/context.rs":"9968592b3550314ce9522b5fed89f120f660751b69d9b7689c139d380b9bc751","src/core.rs":"8de9d3ca4d0e834cd1b9bd47ea45564f0306052fc4e25219c8db54df2249e1f4","src/decoded.rs":"446c4f23b2ebbfe69f26f37459367829f1c5c2f33d19cea763212a5d2f96add8","src/encoding.rs":"f5a63e14bf69ed62411463454fbb1fd2428a19c3f00cf5b73dc5d1975ab87b93","src/error.rs":"72ee3a00e7f0eca82efc4bb37ab5919da090f1e9265104f13db1eed2d66847df","src/lib.rs":"83754dc3f2e13fa4f4c928173a3d1c361a34372642c33dda10c7270c0b1ec57a","src/memory.rs":"4be344f0a3b4e88391ce2bd74f2249a0b95fed4be6284aefd89715041d459d76","src/result.rs":"1931d9d4a644d32b8ba4ed7d5761b8ea5a1144234e60b32cc184b35b0ddb9c62","src/thread_mode.rs":"97d1fe2c6607d5b0e2ddd796fd68a1b2aa9f0cb7ed95c8eccbba53a719354af7","src/variant.rs":"a46e0a164b428e379bd357e4c3f84b7347ecc23231707b9d76a2a5017499bce2","src/version.rs":"d131ecf75b6d0fe79283d60bcdb7e6453cfa736b7c9de6603655803eeeacda57","tests/integration_test.rs":"f8ed1ff0ff8e595a1155cfd786368ebfba4fb9d55c73d0d48f80021edd92aad5"},"package":"2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"}
\ No newline at end of file
diff --git a/vendor/rust-argon2/CHANGELOG.md b/vendor/rust-argon2/CHANGELOG.md
deleted file mode 100644
index a1bd2336af..0000000000
--- a/vendor/rust-argon2/CHANGELOG.md
+++ /dev/null
@@ -1,64 +0,0 @@
-ChangeLog for rust-argon2
-=========================
-
-This documents all notable changes to
-[rust-argon2](https://github.com/sru-systems/rust-argon2).
-
-
-## 0.7.0
-
-- Update crossbeam-utils dependency to 0.7.
-
-
-## 0.6.1
-
-- Use constant time equals to compare hashes.
-
-
-## 0.6.0
-
-- Use 2018 edition or Rust
-- Use &dyn error::Error instead of &error::Error
-- Fix clippy lints
-- Allow callers of encode_string to pass any &[u8]
-- Update base64 dependency.
-
-
-## 0.5.1
-
-- Use crossbeam utils 0.6 instead of crossbeam 0.5
-
-
-## 0.5.0
-
-- Replace blake2-rfc with blake2b_simd.
-
-
-## 0.4.0
-
-- Replace rustc-serialize dependency with base64 and hex.
-- Update base64 dependency.
-- Update crossbeam dependency.
-- Update hex dependency.
-- Allow updating to minor versions of blake2-rfc.
-
-
-## 0.3.0
-
-- Embed Config struct in Context struct.
-
-
-## 0.2.0
-
-- Use ThreadMode enum instead of explicit thread number.
-- Use a Config struct instead of explicit configuration arguments.
-- Use references instead of vectors for byte data in the Context struct.
-- Deprecate the following functions:
-  - hash_encoded_defaults
-  - hash_encoded_old
-  - hash_encoded_std
-  - hash_raw_defaults
-  - hash_raw_old
-  - hash_raw_std
-  - verify_raw_old
-  - verify_raw_std
diff --git a/vendor/rust-argon2/Cargo.toml b/vendor/rust-argon2/Cargo.toml
deleted file mode 100644
index fa7985ca93..0000000000
--- a/vendor/rust-argon2/Cargo.toml
+++ /dev/null
@@ -1,40 +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 = "rust-argon2"
-version = "0.7.0"
-authors = ["Martijn Rijkeboer "]
-description = "Rust implementation of the Argon2 password hashing function."
-homepage = "https://github.com/sru-systems/rust-argon2"
-documentation = "https://docs.sru-systems.com/rust-argon2/0.7.0/argon2/"
-readme = "README.md"
-keywords = ["argon2", "argon2d", "argon2i", "hash", "password"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/sru-systems/rust-argon2"
-
-[lib]
-name = "argon2"
-[dependencies.base64]
-version = "0.11"
-
-[dependencies.blake2b_simd]
-version = "0.5"
-
-[dependencies.constant_time_eq]
-version = "0.1.4"
-
-[dependencies.crossbeam-utils]
-version = "0.7"
-[dev-dependencies.hex]
-version = "0.3"
diff --git a/vendor/rust-argon2/LICENSE-MIT b/vendor/rust-argon2/LICENSE-MIT
deleted file mode 100644
index 96cd88f451..0000000000
--- a/vendor/rust-argon2/LICENSE-MIT
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT license.
-
-Copyright (c) 2017 Martijn Rijkeboer 
-
-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/rust-argon2/README.md b/vendor/rust-argon2/README.md
deleted file mode 100644
index f427d59ef7..0000000000
--- a/vendor/rust-argon2/README.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Rust-argon2
-
-Rust library for hashing passwords using
-[Argon2](https://github.com/P-H-C/phc-winner-argon2), the password-hashing
-function that won the
-[Password Hashing Competition (PHC)](https://password-hashing.net).
-
-## Usage
-
-To use `rust-argon2`, add the following to your Cargo.toml:
-
-```toml
-[dependencies]
-rust-argon2 = "0.7"
-```
-
-And the following to your crate root:
-
-```rust
-extern crate argon2;
-```
-
-
-## Examples
-
-Create a password hash using the defaults and verify it:
-
-```rust
-use argon2::{self, Config};
-
-let password = b"password";
-let salt = b"randomsalt";
-let config = Config::default();
-let hash = argon2::hash_encoded(password, salt, &config).unwrap();
-let matches = argon2::verify_encoded(&hash, password).unwrap();
-assert!(matches);
-```
-
-Create a password hash with custom settings and verify it:
-
-```rust
-use argon2::{self, Config, ThreadMode, Variant, Version};
-
-let password = b"password";
-let salt = b"othersalt";
-let config = Config {
-    variant: Variant::Argon2i,
-    version: Version::Version13,
-    mem_cost: 65536,
-    time_cost: 10,
-    lanes: 4,
-    thread_mode: ThreadMode::Parallel,
-    secret: &[],
-    ad: &[],
-    hash_length: 32
-};
-let hash = argon2::hash_encoded(password, salt, &config).unwrap();
-let matches = argon2::verify_encoded(&hash, password).unwrap();
-assert!(matches);
-```
-
-
-## Limitations
-
-This crate has the same limitation as the `blake2-rfc` crate that it uses.
-It does not attempt to clear potentially sensitive data from its work
-memory. To do so correctly without a heavy performance penalty would
-require help from the compiler. It's better to not attempt to do so than to
-present a false assurance.
-
-This version uses the standard implementation and does not yet implement
-optimizations. Therefore, it is not the fastest implementation available.
-
-
-## License
-
-Rust-argon2 is dual licensed under the [MIT](LICENSE-MIT) and
-[Apache 2.0](LICENSE-APACHE) licenses, the same licenses as the Rust compiler.
-
-
-## Contributions
-
-Contributions are welcome. By submitting a pull request you are agreeing to
-make you work available under the license terms of the Rust-argon2 project.
-
diff --git a/vendor/rust-argon2/src/argon2.rs b/vendor/rust-argon2/src/argon2.rs
deleted file mode 100644
index 47eafc41eb..0000000000
--- a/vendor/rust-argon2/src/argon2.rs
+++ /dev/null
@@ -1,720 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use crate::context::Context;
-use crate::config::Config;
-use crate::core;
-use crate::encoding;
-use crate::memory::Memory;
-use crate::result::Result;
-use crate::thread_mode::ThreadMode;
-use crate::variant::Variant;
-use crate::version::Version;
-
-use constant_time_eq::constant_time_eq;
-
-/// Returns the length of the encoded string.
-///
-/// # Remarks
-///
-/// The length is **one** less that the original C version, since no null
-/// terminator is used.
-///
-/// # Examples
-///
-/// ```rust
-/// use argon2::{self, Variant};
-///
-/// let variant = Variant::Argon2i;
-/// let mem = 4096;
-/// let time = 10;
-/// let parallelism = 10;
-/// let salt_len = 8;
-/// let hash_len = 32;
-/// let enc_len = argon2::encoded_len(variant, mem, time, parallelism, salt_len, hash_len);
-/// assert_eq!(enc_len, 86);
-/// ```
-#[rustfmt::skip]
-pub fn encoded_len(
-    variant: Variant,
-    mem_cost: u32,
-    time_cost: u32,
-    parallelism: u32,
-    salt_len: u32,
-    hash_len: u32
-) -> u32 {
-    ("$$v=$m=,t=,p=$$".len() as u32)  +
-    (variant.as_lowercase_str().len() as u32) +
-    encoding::num_len(Version::default().as_u32()) +
-    encoding::num_len(mem_cost) +
-    encoding::num_len(time_cost) +
-    encoding::num_len(parallelism) +
-    encoding::base64_len(salt_len) +
-    encoding::base64_len(hash_len)
-}
-
-/// Hashes the password and returns the encoded hash.
-///
-/// # Examples
-///
-/// Create an encoded hash with the default configuration:
-///
-/// ```
-/// use argon2::{self, Config};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config::default();
-/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
-/// ```
-///
-///
-/// Create an Argon2d encoded hash with 4 lanes and parallel execution:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let mut config = Config::default();
-/// config.variant = Variant::Argon2d;
-/// config.lanes = 4;
-/// config.thread_mode = ThreadMode::Parallel;
-/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
-/// ```
-pub fn hash_encoded(pwd: &[u8], salt: &[u8], config: &Config) -> Result {
-    let context = Context::new(config.clone(), pwd, salt)?;
-    let hash = run(&context);
-    let encoded = encoding::encode_string(&context, &hash);
-    Ok(encoded)
-}
-
-/// Hashes the password using default settings and returns the encoded hash.
-///
-/// # Examples
-///
-/// ```
-/// use argon2;
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let encoded = argon2::hash_encoded_defaults(pwd, salt).unwrap();
-/// ```
-///
-/// The above rewritten using `hash_encoded`:
-///
-/// ```
-/// use argon2::{self, Config};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config::default();
-/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
-/// ```
-#[deprecated(since = "0.2.0", note = "please use `hash_encoded` instead")]
-pub fn hash_encoded_defaults(pwd: &[u8], salt: &[u8]) -> Result {
-    hash_encoded(pwd, salt, &Config::default())
-}
-
-/// Hashes the password and returns the encoded hash (pre 0.2.0 `hash_encoded`).
-///
-/// # Examples
-///
-///
-/// ```
-/// use argon2::{self, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let mem_cost = 4096;
-/// let time_cost = 10;
-/// let lanes = 1;
-/// let threads = 1;
-/// let secret = b"secret value";
-/// let ad = b"associated data";
-/// let hash_len = 32;
-/// let encoded = argon2::hash_encoded_old(Variant::Argon2i,
-///                                        Version::Version13,
-///                                        mem_cost,
-///                                        time_cost,
-///                                        lanes,
-///                                        threads,
-///                                        pwd,
-///                                        salt,
-///                                        secret,
-///                                        ad,
-///                                        hash_len).unwrap();
-/// ```
-///
-/// The above rewritten using the new `hash_encoded`:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config {
-///     variant: Variant::Argon2i,
-///     version: Version::Version13,
-///     mem_cost: 4096,
-///     time_cost: 10,
-///     lanes: 1,
-///     thread_mode: ThreadMode::Sequential,
-///     secret: b"secret value",
-///     ad: b"associated data",
-///     hash_length: 32,
-/// };
-/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
-/// ```
-#[deprecated(since = "0.2.0", note = "please use new `hash_encoded` instead")]
-pub fn hash_encoded_old(
-    variant: Variant,
-    version: Version,
-    mem_cost: u32,
-    time_cost: u32,
-    lanes: u32,
-    threads: u32,
-    pwd: &[u8],
-    salt: &[u8],
-    secret: &[u8],
-    ad: &[u8],
-    hash_len: u32,
-) -> Result {
-    let config = Config {
-        variant,
-        version,
-        mem_cost,
-        time_cost,
-        lanes,
-        thread_mode: ThreadMode::from_threads(threads),
-        secret,
-        ad,
-        hash_length: hash_len,
-    };
-    hash_encoded(pwd, salt, &config)
-}
-
-/// Hashes the password and returns the encoded hash (standard).
-///
-/// # Examples
-///
-///
-/// ```
-/// use argon2::{self, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let mem_cost = 4096;
-/// let time_cost = 10;
-/// let parallelism = 1;
-/// let hash_len = 32;
-/// let encoded = argon2::hash_encoded_std(Variant::Argon2i,
-///                                        Version::Version13,
-///                                        mem_cost,
-///                                        time_cost,
-///                                        parallelism,
-///                                        pwd,
-///                                        salt,
-///                                        hash_len).unwrap();
-/// ```
-///
-/// The above rewritten using `hash_encoded`:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config {
-///     variant: Variant::Argon2i,
-///     version: Version::Version13,
-///     mem_cost: 4096,
-///     time_cost: 10,
-///     lanes: 1,
-///     thread_mode: ThreadMode::Sequential,
-///     secret: &[],
-///     ad: &[],
-///     hash_length: 32,
-/// };
-/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
-/// ```
-#[deprecated(since = "0.2.0", note = "please use `hash_encoded` instead")]
-pub fn hash_encoded_std(
-    variant: Variant,
-    version: Version,
-    mem_cost: u32,
-    time_cost: u32,
-    parallelism: u32,
-    pwd: &[u8],
-    salt: &[u8],
-    hash_len: u32,
-) -> Result {
-    let config = Config {
-        variant,
-        version,
-        mem_cost,
-        time_cost,
-        lanes: parallelism,
-        thread_mode: ThreadMode::from_threads(parallelism),
-        secret: &[],
-        ad: &[],
-        hash_length: hash_len,
-    };
-    hash_encoded(pwd, salt, &config)
-}
-
-/// Hashes the password and returns the hash as a vector.
-///
-/// # Examples
-///
-/// Create a hash with the default configuration:
-///
-/// ```
-/// use argon2::{self, Config};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config::default();
-/// let vec = argon2::hash_raw(pwd, salt, &config).unwrap();
-/// ```
-///
-///
-/// Create an Argon2d hash with 4 lanes and parallel execution:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let mut config = Config::default();
-/// config.variant = Variant::Argon2d;
-/// config.lanes = 4;
-/// config.thread_mode = ThreadMode::Parallel;
-/// let vec = argon2::hash_raw(pwd, salt, &config).unwrap();
-/// ```
-pub fn hash_raw(pwd: &[u8], salt: &[u8], config: &Config) -> Result> {
-    let context = Context::new(config.clone(), pwd, salt)?;
-    let hash = run(&context);
-    Ok(hash)
-}
-
-/// Hashes the password using default settings and returns the hash as a vector.
-///
-/// # Examples
-///
-/// ```
-/// use argon2;
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let vec = argon2::hash_raw_defaults(pwd, salt).unwrap();
-/// ```
-///
-/// The above rewritten using `hash_raw`:
-///
-/// ```
-/// use argon2::{self, Config};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config::default();
-/// let vec = argon2::hash_raw(pwd, salt, &config).unwrap();
-/// ```
-#[deprecated(since = "0.2.0", note = "please use `hash_raw` instead")]
-pub fn hash_raw_defaults(pwd: &[u8], salt: &[u8]) -> Result> {
-    hash_raw(pwd, salt, &Config::default())
-}
-
-/// Hashes the password and returns the hash as a vector (pre 0.2.0 `hash_raw`).
-///
-/// # Examples
-///
-///
-/// ```
-/// use argon2::{self, Variant, Version};
-///
-/// let mem_cost = 4096;
-/// let time_cost = 10;
-/// let lanes = 1;
-/// let threads = 1;
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let secret = b"secret value";
-/// let ad = b"associated data";
-/// let hash_len = 32;
-/// let vec = argon2::hash_raw_old(Variant::Argon2i,
-///                                Version::Version13,
-///                                mem_cost,
-///                                time_cost,
-///                                lanes,
-///                                threads,
-///                                pwd,
-///                                salt,
-///                                secret,
-///                                ad,
-///                                hash_len).unwrap();
-/// ```
-///
-/// The above rewritten using the new `hash_raw`:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config {
-///     variant: Variant::Argon2i,
-///     version: Version::Version13,
-///     mem_cost: 4096,
-///     time_cost: 10,
-///     lanes: 1,
-///     thread_mode: ThreadMode::Sequential,
-///     secret: b"secret value",
-///     ad: b"associated data",
-///     hash_length: 32,
-/// };
-/// let vec = argon2::hash_raw(pwd, salt, &config);
-/// ```
-#[deprecated(since = "0.2.0", note = "please use new `hash_raw` instead")]
-pub fn hash_raw_old(
-    variant: Variant,
-    version: Version,
-    mem_cost: u32,
-    time_cost: u32,
-    lanes: u32,
-    threads: u32,
-    pwd: &[u8],
-    salt: &[u8],
-    secret: &[u8],
-    ad: &[u8],
-    hash_len: u32,
-) -> Result> {
-    let config = Config {
-        variant,
-        version,
-        mem_cost,
-        time_cost,
-        lanes,
-        thread_mode: ThreadMode::from_threads(threads),
-        secret,
-        ad,
-        hash_length: hash_len,
-    };
-    hash_raw(pwd, salt, &config)
-}
-
-/// Hashes the password and returns the hash as a vector (standard).
-///
-/// # Examples
-///
-///
-/// ```
-/// use argon2::{self, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let mem_cost = 4096;
-/// let time_cost = 10;
-/// let parallelism = 1;
-/// let hash_len = 32;
-/// let vec = argon2::hash_raw_std(Variant::Argon2i,
-///                                Version::Version13,
-///                                mem_cost,
-///                                time_cost,
-///                                parallelism,
-///                                pwd,
-///                                salt,
-///                                hash_len).unwrap();
-/// ```
-///
-/// The above rewritten using `hash_raw`:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let config = Config {
-///     variant: Variant::Argon2i,
-///     version: Version::Version13,
-///     mem_cost: 4096,
-///     time_cost: 10,
-///     lanes: 1,
-///     thread_mode: ThreadMode::Sequential,
-///     secret: &[],
-///     ad: &[],
-///     hash_length: 32,
-/// };
-/// let vec = argon2::hash_raw(pwd, salt, &config);
-/// ```
-#[deprecated(since = "0.2.0", note = "please use `hash_raw` instead")]
-pub fn hash_raw_std(
-    variant: Variant,
-    version: Version,
-    mem_cost: u32,
-    time_cost: u32,
-    parallelism: u32,
-    pwd: &[u8],
-    salt: &[u8],
-    hash_len: u32,
-) -> Result> {
-    let config = Config {
-        variant,
-        version,
-        mem_cost,
-        time_cost,
-        lanes: parallelism,
-        thread_mode: ThreadMode::from_threads(parallelism),
-        secret: &[],
-        ad: &[],
-        hash_length: hash_len,
-    };
-    hash_raw(pwd, salt, &config)
-}
-
-/// Verifies the password with the encoded hash.
-///
-/// # Examples
-///
-/// ```
-/// use argon2;
-///
-/// let enc = "$argon2i$v=19$m=4096,t=3,p=1$c29tZXNhbHQ\
-///            $iWh06vD8Fy27wf9npn6FXWiCX4K6pW6Ue1Bnzz07Z8A";
-/// let pwd = b"password";
-/// let res = argon2::verify_encoded(enc, pwd).unwrap();
-/// assert!(res);
-/// ```
-pub fn verify_encoded(encoded: &str, pwd: &[u8]) -> Result {
-    verify_encoded_ext(encoded, pwd, &[], &[])
-}
-
-/// Verifies the password with the encoded hash, secret and associated data.
-///
-/// # Examples
-///
-/// ```
-/// use argon2;
-///
-/// let enc = "$argon2i$v=19$m=4096,t=3,p=1$c29tZXNhbHQ\
-///            $OlcSvlN20Lz43sK3jhCJ9K04oejhiY0AmI+ck6nuETo";
-/// let pwd = b"password";
-/// let secret = b"secret";
-/// let ad = b"ad";
-/// let res = argon2::verify_encoded_ext(enc, pwd, secret, ad).unwrap();
-/// assert!(res);
-/// ```
-pub fn verify_encoded_ext(encoded: &str, pwd: &[u8], secret: &[u8], ad: &[u8]) -> Result {
-    let decoded = encoding::decode_string(encoded)?;
-    let config = Config {
-        variant: decoded.variant,
-        version: decoded.version,
-        mem_cost: decoded.mem_cost,
-        time_cost: decoded.time_cost,
-        lanes: decoded.parallelism,
-        thread_mode: ThreadMode::from_threads(decoded.parallelism),
-        secret,
-        ad,
-        hash_length: decoded.hash.len() as u32,
-    };
-    verify_raw(pwd, &decoded.salt, &decoded.hash, &config)
-}
-
-/// Verifies the password with the supplied configuration.
-///
-/// # Examples
-///
-///
-/// ```
-/// use argon2::{self, Config};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
-///              126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
-///              103, 207, 61, 59, 103, 192];
-/// let config = Config::default();
-/// let res = argon2::verify_raw(pwd, salt, hash, &config).unwrap();
-/// assert!(res);
-/// ```
-pub fn verify_raw(pwd: &[u8], salt: &[u8], hash: &[u8], config: &Config) -> Result {
-    let config = Config {
-        hash_length: hash.len() as u32,
-        ..config.clone()
-    };
-    let context = Context::new(config, pwd, salt)?;
-    let calculated_hash = run(&context);
-    Ok(constant_time_eq(hash, &calculated_hash))
-}
-
-/// Verifies the password with the supplied settings (pre 0.2.0 `verify_raw`).
-///
-/// # Examples
-///
-/// ```
-/// use argon2::{self, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
-///              126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
-///              103, 207, 61, 59, 103, 192];
-/// let mem_cost = 4096;
-/// let time_cost = 3;
-/// let lanes = 1;
-/// let threads = 1;
-/// let secret = &[];
-/// let ad = &[];
-/// let res = argon2::verify_raw_old(Variant::Argon2i,
-///                                  Version::Version13,
-///                                  mem_cost,
-///                                  time_cost,
-///                                  lanes,
-///                                  threads,
-///                                  pwd,
-///                                  salt,
-///                                  secret,
-///                                  ad,
-///                                  hash).unwrap();
-/// assert!(res);
-/// ```
-///
-/// The above rewritten using the new `verify_raw`:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
-///              126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
-///              103, 207, 61, 59, 103, 192];
-/// let config = Config {
-///     variant: Variant::Argon2i,
-///     version: Version::Version13,
-///     mem_cost: 4096,
-///     time_cost: 3,
-///     lanes: 1,
-///     thread_mode: ThreadMode::Sequential,
-///     secret: &[],
-///     ad: &[],
-///     hash_length: hash.len() as u32,
-/// };
-/// let res = argon2::verify_raw(pwd, salt, hash, &config).unwrap();
-/// assert!(res);
-/// ```
-#[deprecated(since = "0.2.0", note = "please use new `verify_raw` instead")]
-pub fn verify_raw_old(
-    variant: Variant,
-    version: Version,
-    mem_cost: u32,
-    time_cost: u32,
-    lanes: u32,
-    threads: u32,
-    pwd: &[u8],
-    salt: &[u8],
-    secret: &[u8],
-    ad: &[u8],
-    hash: &[u8],
-) -> Result {
-    let config = Config {
-        variant,
-        version,
-        mem_cost,
-        time_cost,
-        lanes,
-        thread_mode: ThreadMode::from_threads(threads),
-        secret,
-        ad,
-        hash_length: hash.len() as u32,
-    };
-    verify_raw(pwd, salt, hash, &config)
-}
-
-/// Verifies the password with the supplied settings (standard).
-///
-/// # Examples
-///
-///
-/// ```
-/// use argon2::{self, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
-///              126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
-///              103, 207, 61, 59, 103, 192];
-/// let mem_cost = 4096;
-/// let time_cost = 3;
-/// let parallelism = 1;
-/// let res = argon2::verify_raw_std(Variant::Argon2i,
-///                                  Version::Version13,
-///                                  mem_cost,
-///                                  time_cost,
-///                                  parallelism,
-///                                  pwd,
-///                                  salt,
-///                                  hash).unwrap();
-/// assert!(res);
-/// ```
-///
-/// The above rewritten using `verify_raw`:
-///
-/// ```
-/// use argon2::{self, Config, ThreadMode, Variant, Version};
-///
-/// let pwd = b"password";
-/// let salt = b"somesalt";
-/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
-///              126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
-///              103, 207, 61, 59, 103, 192];
-/// let config = Config {
-///     variant: Variant::Argon2i,
-///     version: Version::Version13,
-///     mem_cost: 4096,
-///     time_cost: 3,
-///     lanes: 1,
-///     thread_mode: ThreadMode::Sequential,
-///     secret: &[],
-///     ad: &[],
-///     hash_length: hash.len() as u32,
-/// };
-/// let res = argon2::verify_raw(pwd, salt, hash, &config).unwrap();
-/// assert!(res);
-/// ```
-#[deprecated(since = "0.2.0", note = "please use `verify_raw` instead")]
-pub fn verify_raw_std(
-    variant: Variant,
-    version: Version,
-    mem_cost: u32,
-    time_cost: u32,
-    parallelism: u32,
-    pwd: &[u8],
-    salt: &[u8],
-    hash: &[u8],
-) -> Result {
-    let config = Config {
-        variant,
-        version,
-        mem_cost,
-        time_cost,
-        lanes: parallelism,
-        thread_mode: ThreadMode::from_threads(parallelism),
-        secret: &[],
-        ad: &[],
-        hash_length: hash.len() as u32,
-    };
-    verify_raw(pwd, salt, hash, &config)
-}
-
-fn run(context: &Context) -> Vec {
-    let mut memory = Memory::new(context.config.lanes, context.lane_length);
-    core::initialize(context, &mut memory);
-    core::fill_memory_blocks(context, &mut memory);
-    core::finalize(context, &memory)
-}
diff --git a/vendor/rust-argon2/src/block.rs b/vendor/rust-argon2/src/block.rs
deleted file mode 100644
index c773528908..0000000000
--- a/vendor/rust-argon2/src/block.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt;
-use std::fmt::Debug;
-use std::ops::{BitXorAssign, Index, IndexMut};
-use crate::common;
-
-/// Structure for the (1KB) memory block implemented as 128 64-bit words.
-pub struct Block([u64; common::QWORDS_IN_BLOCK]);
-
-impl Block {
-    /// Gets the byte slice representation of the block.
-    pub fn as_u8(&self) -> &[u8] {
-        let bytes: &[u8; common::BLOCK_SIZE] = unsafe { &*(&self.0 as *const [u64; common::QWORDS_IN_BLOCK] as *const [u8; common::BLOCK_SIZE]) };
-        bytes
-    }
-
-    /// Gets the mutable byte slice representation of the block.
-    pub fn as_u8_mut(&mut self) -> &mut [u8] {
-        let bytes: &mut [u8; common::BLOCK_SIZE] = unsafe { &mut *(&mut self.0 as *mut [u64; common::QWORDS_IN_BLOCK] as *mut [u8; common::BLOCK_SIZE]) };
-        bytes
-    }
-
-    /// Copies self to destination.
-    pub fn copy_to(&self, dst: &mut Block) {
-        for (d, s) in dst.0.iter_mut().zip(self.0.iter()) {
-            *d = *s
-        }
-    }
-
-    /// Creates a new block filled with zeros.
-    pub fn zero() -> Block {
-        Block([0u64; common::QWORDS_IN_BLOCK])
-    }
-}
-
-impl<'a> BitXorAssign<&'a Block> for Block {
-    fn bitxor_assign(&mut self, rhs: &Block) {
-        for (s, r) in self.0.iter_mut().zip(rhs.0.iter()) {
-            *s ^= *r
-        }
-    }
-}
-
-impl Clone for Block {
-    fn clone(&self) -> Block {
-        Block(self.0)
-    }
-}
-
-impl Debug for Block {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        fmt.debug_list().entries(self.0.iter()).finish()
-    }
-}
-
-impl Eq for Block {}
-
-impl Index for Block {
-    type Output = u64;
-    fn index(&self, index: usize) -> &u64 {
-        &self.0[index]
-    }
-}
-
-impl IndexMut for Block {
-    fn index_mut(&mut self, index: usize) -> &mut u64 {
-        &mut self.0[index]
-    }
-}
-
-impl PartialEq for Block {
-    fn eq(&self, other: &Block) -> bool {
-        let mut equal = true;
-        for (s, o) in self.0.iter().zip(other.0.iter()) {
-            if s != o {
-                equal = false;
-            }
-        }
-        equal
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::block::Block;
-    use crate::common;
-
-    #[test]
-    fn as_u8_returns_correct_slice() {
-        let block = Block::zero();
-        let expected = vec![0u8; 1024];
-        let actual = block.as_u8();
-        assert_eq!(actual, expected.as_slice());
-    }
-
-    #[test]
-    fn as_u8_mut_returns_correct_slice() {
-        let mut block = Block::zero();
-        let mut expected = vec![0u8; 1024];
-        let actual = block.as_u8_mut();
-        assert_eq!(actual, expected.as_mut_slice());
-    }
-
-    #[test]
-    fn bitxor_assign_updates_lhs() {
-        let mut lhs = Block([0u64; common::QWORDS_IN_BLOCK]);
-        let rhs = Block([1u64; common::QWORDS_IN_BLOCK]);
-        lhs ^= &rhs;
-        assert_eq!(lhs, rhs);
-    }
-
-    #[test]
-    fn copy_to_copies_block() {
-        let src = Block([1u64; common::QWORDS_IN_BLOCK]);
-        let mut dst = Block([0u64; common::QWORDS_IN_BLOCK]);
-        src.copy_to(&mut dst);
-        assert_eq!(dst, src);
-    }
-
-    #[test]
-    fn clone_clones_block() {
-        let orig = Block([1u64; common::QWORDS_IN_BLOCK]);
-        let copy = orig.clone();
-        assert_eq!(copy, orig);
-    }
-
-    #[test]
-    fn zero_creates_block_will_all_zeros() {
-        let expected = Block([0u64; common::QWORDS_IN_BLOCK]);
-        let actual = Block::zero();
-        assert_eq!(actual, expected);
-    }
-}
diff --git a/vendor/rust-argon2/src/common.rs b/vendor/rust-argon2/src/common.rs
deleted file mode 100644
index f03eed9555..0000000000
--- a/vendor/rust-argon2/src/common.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// Default number of lanes (degree of parallelism).
-pub const DEF_LANES: u32 = 1;
-
-/// Minimum number of lanes (degree of parallelism).
-pub const MIN_LANES: u32 = 1;
-
-/// Maximum number of lanes (degree of parallelism).
-pub const MAX_LANES: u32 = 0x00FF_FFFF;
-
-/// Number of synchronization points between lanes per pass.
-pub const SYNC_POINTS: u32 = 4;
-
-/// Default digest size in bytes.
-pub const DEF_HASH_LENGTH: u32 = 32;
-
-/// Minimum digest size in bytes.
-pub const MIN_HASH_LENGTH: u32 = 4;
-
-/// Maximum digest size in bytes.
-pub const MAX_HASH_LENGTH: u32 = 0xFFFF_FFFF;
-
-/// Default number of memory blocks (2^12).
-pub const DEF_MEMORY: u32 = 4096;
-
-/// Minimum number of memory blocks (each of BLOCK_SIZE bytes).
-pub const MIN_MEMORY: u32 = 2 * SYNC_POINTS;
-
-/// Maximum number of memory blocks (each of BLOCK_SIZE bytes).
-#[cfg(target_pointer_width = "32")]
-pub const MAX_MEMORY: u32 = 0x200000;
-#[cfg(target_pointer_width = "64")]
-pub const MAX_MEMORY: u32 = 0xFFFF_FFFF;
-
-/// Default number of passes.
-pub const DEF_TIME: u32 = 3;
-
-/// Minimum number of passes
-pub const MIN_TIME: u32 = 1;
-
-/// Maximum number of passes.
-pub const MAX_TIME: u32 = 0xFFFF_FFFF;
-
-/// Minimum password length in bytes.
-pub const MIN_PWD_LENGTH: u32 = 0;
-
-/// Maximum password length in bytes.
-pub const MAX_PWD_LENGTH: u32 = 0xFFFF_FFFF;
-
-/// Minimum associated data length in bytes.
-pub const MIN_AD_LENGTH: u32 = 0;
-
-/// Maximum associated data length in bytes.
-pub const MAX_AD_LENGTH: u32 = 0xFFFF_FFFF;
-
-/// Minimum salt length in bytes.
-pub const MIN_SALT_LENGTH: u32 = 8;
-
-/// Maximum salt length in bytes.
-pub const MAX_SALT_LENGTH: u32 = 0xFFFF_FFFF;
-
-/// Minimum key length in bytes.
-pub const MIN_SECRET_LENGTH: u32 = 0;
-
-/// Maximum key length in bytes.
-pub const MAX_SECRET_LENGTH: u32 = 0xFFFF_FFFF;
-
-/// Memory block size in bytes.
-pub const BLOCK_SIZE: usize = 1024;
-
-/// Number of quad words in a block.
-pub const QWORDS_IN_BLOCK: usize = BLOCK_SIZE / 8;
-
-/// Number of pseudo-random values generated by one call to Blake in Argon2i
-/// to generate reference block positions.
-pub const ADDRESSES_IN_BLOCK: u32 = 128;
-
-/// Pre-hashing digest length.
-pub const PREHASH_DIGEST_LENGTH: usize = 64;
-
-/// Pre-hashing digest length with extension.
-pub const PREHASH_SEED_LENGTH: usize = 72;
-
-/// Blake2b output length in bytes.
-pub const BLAKE2B_OUT_LENGTH: usize = 64;
diff --git a/vendor/rust-argon2/src/config.rs b/vendor/rust-argon2/src/config.rs
deleted file mode 100644
index 8eabe5defb..0000000000
--- a/vendor/rust-argon2/src/config.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use crate::common;
-use crate::thread_mode::ThreadMode;
-use crate::variant::Variant;
-use crate::version::Version;
-
-/// Structure containing configuration settings.
-///
-/// # Examples
-///
-/// ```
-/// use argon2::{Config, ThreadMode, Variant, Version};
-///
-/// let config = Config::default();
-/// assert_eq!(config.ad, &[]);
-/// assert_eq!(config.hash_length, 32);
-/// assert_eq!(config.lanes, 1);
-/// assert_eq!(config.mem_cost, 4096);
-/// assert_eq!(config.secret, &[]);
-/// assert_eq!(config.thread_mode, ThreadMode::Sequential);
-/// assert_eq!(config.time_cost, 3);
-/// assert_eq!(config.variant, Variant::Argon2i);
-/// assert_eq!(config.version, Version::Version13);
-/// ```
-#[derive(Clone, Debug, PartialEq)]
-pub struct Config<'a> {
-    /// The associated data.
-    pub ad: &'a [u8],
-
-    /// The length of the resulting hash.
-    pub hash_length: u32,
-
-    /// The number of lanes.
-    pub lanes: u32,
-
-    /// The amount of memory requested (KB).
-    pub mem_cost: u32,
-
-    /// The key.
-    pub secret: &'a [u8],
-
-    /// The thread mode.
-    pub thread_mode: ThreadMode,
-
-    /// The number of passes.
-    pub time_cost: u32,
-
-    /// The variant.
-    pub variant: Variant,
-
-    /// The version number.
-    pub version: Version,
-}
-
-impl<'a> Config<'a> {
-    pub fn uses_sequential(&self) -> bool {
-        self.thread_mode == ThreadMode::Sequential || self.lanes == 1
-    }
-}
-
-impl<'a> Default for Config<'a> {
-    fn default() -> Config<'a> {
-        Config {
-            ad: &[],
-            hash_length: common::DEF_HASH_LENGTH,
-            lanes: common::DEF_LANES,
-            mem_cost: common::DEF_MEMORY,
-            secret: &[],
-            thread_mode: ThreadMode::default(),
-            time_cost: common::DEF_TIME,
-            variant: Variant::default(),
-            version: Version::default(),
-        }
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::config::Config;
-    use crate::thread_mode::ThreadMode;
-    use crate::variant::Variant;
-    use crate::version::Version;
-
-    #[test]
-    fn default_returns_correct_instance() {
-        let config = Config::default();
-        assert_eq!(config.ad, &[]);
-        assert_eq!(config.hash_length, 32);
-        assert_eq!(config.lanes, 1);
-        assert_eq!(config.mem_cost, 4096);
-        assert_eq!(config.secret, &[]);
-        assert_eq!(config.thread_mode, ThreadMode::Sequential);
-        assert_eq!(config.time_cost, 3);
-        assert_eq!(config.variant, Variant::Argon2i);
-        assert_eq!(config.version, Version::Version13);
-    }
-}
diff --git a/vendor/rust-argon2/src/context.rs b/vendor/rust-argon2/src/context.rs
deleted file mode 100644
index ca258c1d46..0000000000
--- a/vendor/rust-argon2/src/context.rs
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use crate::common;
-use crate::config::Config;
-use crate::error::Error;
-use crate::result::Result;
-
-/// Structure containing settings for the Argon2 algorithm. A combination of
-/// the original argon2_context and argon2_instance_t.
-#[derive(Debug, PartialEq)]
-pub struct Context<'a> {
-    /// The config for this context.
-    pub config: Config<'a>,
-
-    /// The length of a lane.
-    pub lane_length: u32,
-
-    /// The number of memory blocks.
-    pub memory_blocks: u32,
-
-    /// The password.
-    pub pwd: &'a [u8],
-
-    /// The salt.
-    pub salt: &'a [u8],
-
-    /// The length of a segment.
-    pub segment_length: u32,
-}
-
-impl<'a> Context<'a> {
-    /// Attempts to create a new context.
-    pub fn new(config: Config<'a>, pwd: &'a [u8], salt: &'a [u8]) -> Result> {
-        if config.lanes < common::MIN_LANES {
-            return Err(Error::LanesTooFew);
-        } else if config.lanes > common::MAX_LANES {
-            return Err(Error::LanesTooMany);
-        }
-
-        let lanes = config.lanes;
-        if config.mem_cost < common::MIN_MEMORY {
-            return Err(Error::MemoryTooLittle);
-        } else if config.mem_cost > common::MAX_MEMORY {
-            return Err(Error::MemoryTooMuch);
-        } else if config.mem_cost < 8 * lanes {
-            return Err(Error::MemoryTooLittle);
-        }
-
-        if config.time_cost < common::MIN_TIME {
-            return Err(Error::TimeTooSmall);
-        } else if config.time_cost > common::MAX_TIME {
-            return Err(Error::TimeTooLarge);
-        }
-
-        let pwd_len = pwd.len();
-        if pwd_len < common::MIN_PWD_LENGTH as usize {
-            return Err(Error::PwdTooShort);
-        } else if pwd_len > common::MAX_PWD_LENGTH as usize {
-            return Err(Error::PwdTooLong);
-        }
-
-        let salt_len = salt.len();
-        if salt_len < common::MIN_SALT_LENGTH as usize {
-            return Err(Error::SaltTooShort);
-        } else if salt_len > common::MAX_SALT_LENGTH as usize {
-            return Err(Error::SaltTooLong);
-        }
-
-        let secret_len = config.secret.len();
-        if secret_len < common::MIN_SECRET_LENGTH as usize {
-            return Err(Error::SecretTooShort);
-        } else if secret_len > common::MAX_SECRET_LENGTH as usize {
-            return Err(Error::SecretTooLong);
-        }
-
-        let ad_len = config.ad.len();
-        if ad_len < common::MIN_AD_LENGTH as usize {
-            return Err(Error::AdTooShort);
-        } else if ad_len > common::MAX_AD_LENGTH as usize {
-            return Err(Error::AdTooLong);
-        }
-
-        if config.hash_length < common::MIN_HASH_LENGTH {
-            return Err(Error::OutputTooShort);
-        } else if config.hash_length > common::MAX_HASH_LENGTH {
-            return Err(Error::OutputTooLong);
-        }
-
-        let mut memory_blocks = config.mem_cost;
-        if memory_blocks < 2 * common::SYNC_POINTS * lanes {
-            memory_blocks = 2 * common::SYNC_POINTS * lanes;
-        }
-
-        let segment_length = memory_blocks / (lanes * common::SYNC_POINTS);
-        let memory_blocks = segment_length * (lanes * common::SYNC_POINTS);
-        let lane_length = segment_length * common::SYNC_POINTS;
-
-        Ok(Context {
-            config,
-            lane_length,
-            memory_blocks,
-            pwd,
-            salt,
-            segment_length,
-        })
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::config::Config;
-    use crate::context::Context;
-    use crate::error::Error;
-    use crate::thread_mode::ThreadMode;
-    use crate::variant::Variant;
-    use crate::version::Version;
-
-    #[test]
-    fn new_returns_correct_instance() {
-        let config = Config {
-            ad: b"additionaldata",
-            hash_length: 32,
-            lanes: 4,
-            mem_cost: 4096,
-            secret: b"secret",
-            thread_mode: ThreadMode::Sequential,
-            time_cost: 3,
-            variant: Variant::Argon2i,
-            version: Version::Version13,
-        };
-        let pwd = b"password";
-        let salt = b"somesalt";
-        let result = Context::new(config.clone(), pwd, salt);
-        assert!(result.is_ok());
-
-        let context = result.unwrap();
-        assert_eq!(context.config, config);
-        assert_eq!(context.pwd, pwd);
-        assert_eq!(context.salt, salt);
-        assert_eq!(context.memory_blocks, 4096);
-        assert_eq!(context.segment_length, 256);
-        assert_eq!(context.lane_length, 1024);
-    }
-
-    #[test]
-    fn new_with_too_little_mem_cost_returns_correct_error() {
-        let config = Config {
-            mem_cost: 7,
-            ..Default::default()
-        };
-        assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::MemoryTooLittle));
-    }
-
-    #[test]
-    fn new_with_less_than_8_x_lanes_mem_cost_returns_correct_error() {
-        let config = Config {
-            lanes: 4,
-            mem_cost: 31,
-            ..Default::default()
-        };
-        assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::MemoryTooLittle));
-    }
-
-    #[test]
-    fn new_with_too_small_time_cost_returns_correct_error() {
-        let config = Config {
-            time_cost: 0,
-            ..Default::default()
-        };
-        assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::TimeTooSmall));
-    }
-
-    #[test]
-    fn new_with_too_few_lanes_returns_correct_error() {
-        let config = Config {
-            lanes: 0,
-            ..Default::default()
-        };
-        assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::LanesTooFew));
-    }
-
-    #[test]
-    fn new_with_too_many_lanes_returns_correct_error() {
-        let config = Config {
-            lanes: 1 << 24,
-            ..Default::default()
-        };
-        assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::LanesTooMany));
-    }
-
-    #[test]
-    fn new_with_too_short_salt_returns_correct_error() {
-        let config = Default::default();
-        let salt = [0u8; 7];
-        assert_eq!(Context::new(config, &[0u8; 8], &salt), Err(Error::SaltTooShort));
-    }
-
-    #[test]
-    fn new_with_too_short_hash_length_returns_correct_error() {
-        let config = Config {
-            hash_length: 3,
-            ..Default::default()
-        };
-        assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::OutputTooShort));
-    }
-}
diff --git a/vendor/rust-argon2/src/core.rs b/vendor/rust-argon2/src/core.rs
deleted file mode 100644
index a93211de61..0000000000
--- a/vendor/rust-argon2/src/core.rs
+++ /dev/null
@@ -1,461 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use crate::block::Block;
-use crate::common;
-use crate::context::Context;
-use crate::memory::Memory;
-use crate::variant::Variant;
-use crate::version::Version;
-use blake2b_simd::Params;
-use crossbeam_utils::thread::scope;
-use std::mem;
-
-/// Position of the block currently being operated on.
-#[derive(Clone, Debug)]
-struct Position {
-    pass: u32,
-    lane: u32,
-    slice: u32,
-    index: u32,
-}
-
-/// Initializes the memory.
-pub fn initialize(context: &Context, memory: &mut Memory) {
-    fill_first_blocks(context, memory, &mut h0(context));
-}
-
-/// Fills all the memory blocks.
-pub fn fill_memory_blocks(context: &Context, memory: &mut Memory) {
-    if context.config.uses_sequential() {
-        fill_memory_blocks_st(context, memory);
-    } else {
-        fill_memory_blocks_mt(context, memory);
-    }
-}
-
-/// Calculates the final hash and returns it.
-pub fn finalize(context: &Context, memory: &Memory) -> Vec {
-    let mut blockhash = memory[context.lane_length - 1].clone();
-    for l in 1..context.config.lanes {
-        let last_block_in_lane = l * context.lane_length + (context.lane_length - 1);
-        blockhash ^= &memory[last_block_in_lane];
-    }
-
-    let mut hash = vec![0u8; context.config.hash_length as usize];
-    hprime(hash.as_mut_slice(), blockhash.as_u8());
-    hash
-}
-
-fn blake2b(out: &mut [u8], input: &[&[u8]]) {
-    let mut blake = Params::new().hash_length(out.len()).to_state();
-    for slice in input {
-        blake.update(slice);
-    }
-    out.copy_from_slice(blake.finalize().as_bytes());
-}
-
-fn f_bla_mka(x: u64, y: u64) -> u64 {
-    let m = 0xFFFF_FFFFu64;
-    let xy = (x & m) * (y & m);
-    x.wrapping_add(y.wrapping_add(xy.wrapping_add(xy)))
-}
-
-fn fill_block(prev_block: &Block, ref_block: &Block, next_block: &mut Block, with_xor: bool) {
-    let mut block_r = ref_block.clone();
-    block_r ^= prev_block;
-    let mut block_tmp = block_r.clone();
-
-    // Now block_r = ref_block + prev_block and block_tmp = ref_block + prev_block
-    if with_xor {
-        // Saving the next block contents for XOR over
-        block_tmp ^= next_block;
-        // Now block_r = ref_block + prev_block and
-        // block_tmp = ref_block + prev_block + next_block
-    }
-
-    // Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
-    // (16,17,..31)... finally (112,113,...127)
-    for i in 0..8 {
-        let mut v0 = block_r[16 * i];
-        let mut v1 = block_r[16 * i + 1];
-        let mut v2 = block_r[16 * i + 2];
-        let mut v3 = block_r[16 * i + 3];
-        let mut v4 = block_r[16 * i + 4];
-        let mut v5 = block_r[16 * i + 5];
-        let mut v6 = block_r[16 * i + 6];
-        let mut v7 = block_r[16 * i + 7];
-        let mut v8 = block_r[16 * i + 8];
-        let mut v9 = block_r[16 * i + 9];
-        let mut v10 = block_r[16 * i + 10];
-        let mut v11 = block_r[16 * i + 11];
-        let mut v12 = block_r[16 * i + 12];
-        let mut v13 = block_r[16 * i + 13];
-        let mut v14 = block_r[16 * i + 14];
-        let mut v15 = block_r[16 * i + 15];
-
-        p(
-            &mut v0, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6, &mut v7, &mut v8,
-            &mut v9, &mut v10, &mut v11, &mut v12, &mut v13, &mut v14, &mut v15,
-        );
-
-        block_r[16 * i] = v0;
-        block_r[16 * i + 1] = v1;
-        block_r[16 * i + 2] = v2;
-        block_r[16 * i + 3] = v3;
-        block_r[16 * i + 4] = v4;
-        block_r[16 * i + 5] = v5;
-        block_r[16 * i + 6] = v6;
-        block_r[16 * i + 7] = v7;
-        block_r[16 * i + 8] = v8;
-        block_r[16 * i + 9] = v9;
-        block_r[16 * i + 10] = v10;
-        block_r[16 * i + 11] = v11;
-        block_r[16 * i + 12] = v12;
-        block_r[16 * i + 13] = v13;
-        block_r[16 * i + 14] = v14;
-        block_r[16 * i + 15] = v15;
-    }
-
-    // Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
-    // (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127)
-    for i in 0..8 {
-        let mut v0 = block_r[2 * i];
-        let mut v1 = block_r[2 * i + 1];
-        let mut v2 = block_r[2 * i + 16];
-        let mut v3 = block_r[2 * i + 17];
-        let mut v4 = block_r[2 * i + 32];
-        let mut v5 = block_r[2 * i + 33];
-        let mut v6 = block_r[2 * i + 48];
-        let mut v7 = block_r[2 * i + 49];
-        let mut v8 = block_r[2 * i + 64];
-        let mut v9 = block_r[2 * i + 65];
-        let mut v10 = block_r[2 * i + 80];
-        let mut v11 = block_r[2 * i + 81];
-        let mut v12 = block_r[2 * i + 96];
-        let mut v13 = block_r[2 * i + 97];
-        let mut v14 = block_r[2 * i + 112];
-        let mut v15 = block_r[2 * i + 113];
-
-        p(
-            &mut v0, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6, &mut v7, &mut v8,
-            &mut v9, &mut v10, &mut v11, &mut v12, &mut v13, &mut v14, &mut v15,
-        );
-
-        block_r[2 * i] = v0;
-        block_r[2 * i + 1] = v1;
-        block_r[2 * i + 16] = v2;
-        block_r[2 * i + 17] = v3;
-        block_r[2 * i + 32] = v4;
-        block_r[2 * i + 33] = v5;
-        block_r[2 * i + 48] = v6;
-        block_r[2 * i + 49] = v7;
-        block_r[2 * i + 64] = v8;
-        block_r[2 * i + 65] = v9;
-        block_r[2 * i + 80] = v10;
-        block_r[2 * i + 81] = v11;
-        block_r[2 * i + 96] = v12;
-        block_r[2 * i + 97] = v13;
-        block_r[2 * i + 112] = v14;
-        block_r[2 * i + 113] = v15;
-    }
-
-    block_tmp.copy_to(next_block);
-    *next_block ^= &block_r;
-}
-
-fn fill_first_blocks(context: &Context, memory: &mut Memory, h0: &mut [u8]) {
-    for lane in 0..context.config.lanes {
-        let start = common::PREHASH_DIGEST_LENGTH;
-        // H'(H0||0||i)
-        h0[start..(start + 4)].clone_from_slice(&u32_as_32le(0));
-        h0[(start + 4)..(start + 8)].clone_from_slice(&u32_as_32le(lane));
-        hprime(memory[(lane, 0)].as_u8_mut(), &h0);
-
-        // H'(H0||1||i)
-        h0[start..(start + 4)].clone_from_slice(&u32_as_32le(1));
-        hprime(memory[(lane, 1)].as_u8_mut(), &h0);
-    }
-}
-
-fn fill_memory_blocks_mt(context: &Context, memory: &mut Memory) {
-    for p in 0..context.config.time_cost {
-        for s in 0..common::SYNC_POINTS {
-            let _ = scope(|scoped| {
-                for (l, mem) in (0..context.config.lanes).zip(memory.as_lanes_mut()) {
-                    let position = Position {
-                        pass: p,
-                        lane: l,
-                        slice: s,
-                        index: 0,
-                    };
-                    scoped.spawn(move |_| {
-                        fill_segment(context, &position, mem);
-                    });
-                }
-            });
-        }
-    }
-}
-
-fn fill_memory_blocks_st(context: &Context, memory: &mut Memory) {
-    for p in 0..context.config.time_cost {
-        for s in 0..common::SYNC_POINTS {
-            for l in 0..context.config.lanes {
-                let position = Position {
-                    pass: p,
-                    lane: l,
-                    slice: s,
-                    index: 0,
-                };
-                fill_segment(context, &position, memory);
-            }
-        }
-    }
-}
-
-fn fill_segment(context: &Context, position: &Position, memory: &mut Memory) {
-    let mut position = position.clone();
-    let data_independent_addressing = (context.config.variant == Variant::Argon2i)
-        || (context.config.variant == Variant::Argon2id && position.pass == 0)
-            && (position.slice < (common::SYNC_POINTS / 2));
-    let zero_block = Block::zero();
-    let mut input_block = Block::zero();
-    let mut address_block = Block::zero();
-
-    if data_independent_addressing {
-        input_block[0] = position.pass as u64;
-        input_block[1] = position.lane as u64;
-        input_block[2] = position.slice as u64;
-        input_block[3] = context.memory_blocks as u64;
-        input_block[4] = context.config.time_cost as u64;
-        input_block[5] = context.config.variant.as_u64();
-    }
-
-    let mut starting_index = 0u32;
-
-    if position.pass == 0 && position.slice == 0 {
-        starting_index = 2;
-
-        // Don't forget to generate the first block of addresses:
-        if data_independent_addressing {
-            next_addresses(&mut address_block, &mut input_block, &zero_block);
-        }
-    }
-
-    let mut curr_offset = (position.lane * context.lane_length)
-        + (position.slice * context.segment_length)
-        + starting_index;
-
-    let mut prev_offset = if curr_offset % context.lane_length == 0 {
-        // Last block in this lane
-        curr_offset + context.lane_length - 1
-    } else {
-        curr_offset - 1
-    };
-
-    let mut pseudo_rand;
-    for i in starting_index..context.segment_length {
-        // 1.1 Rotating prev_offset if needed
-        if curr_offset % context.lane_length == 1 {
-            prev_offset = curr_offset - 1;
-        }
-
-        // 1.2 Computing the index of the reference block
-        // 1.2.1 Taking pseudo-random value from the previous block
-        if data_independent_addressing {
-            if i % common::ADDRESSES_IN_BLOCK == 0 {
-                next_addresses(&mut address_block, &mut input_block, &zero_block);
-            }
-            pseudo_rand = address_block[(i % common::ADDRESSES_IN_BLOCK) as usize];
-        } else {
-            pseudo_rand = memory[(prev_offset)][0];
-        }
-
-        // 1.2.2 Computing the lane of the reference block
-        // If (position.pass == 0) && (position.slice == 0): can not reference other lanes yet
-        let ref_lane = if (position.pass == 0) && (position.slice == 0) { position.lane as u64 } else { (pseudo_rand >> 32) % context.config.lanes as u64 };
-
-        // 1.2.3 Computing the number of possible reference block within the lane.
-        position.index = i;
-        let pseudo_rand_u32 = (pseudo_rand & 0xFFFF_FFFF) as u32;
-        let same_lane = ref_lane == (position.lane as u64);
-        let ref_index = index_alpha(context, &position, pseudo_rand_u32, same_lane);
-
-        // 2 Creating a new block
-        let index = context.lane_length as u64 * ref_lane + ref_index as u64;
-        let mut curr_block = memory[curr_offset].clone();
-        {
-            let prev_block = &memory[prev_offset];
-            let ref_block = &memory[index];
-            if context.config.version == Version::Version10 || position.pass == 0 {
-                fill_block(prev_block, ref_block, &mut curr_block, false);
-            } else {
-                fill_block(prev_block, ref_block, &mut curr_block, true);
-            }
-        }
-
-        memory[curr_offset] = curr_block;
-        curr_offset += 1;
-        prev_offset += 1;
-    }
-}
-
-fn g(a: &mut u64, b: &mut u64, c: &mut u64, d: &mut u64) {
-    *a = f_bla_mka(*a, *b);
-    *d = rotr64(*d ^ *a, 32);
-    *c = f_bla_mka(*c, *d);
-    *b = rotr64(*b ^ *c, 24);
-    *a = f_bla_mka(*a, *b);
-    *d = rotr64(*d ^ *a, 16);
-    *c = f_bla_mka(*c, *d);
-    *b = rotr64(*b ^ *c, 63);
-}
-
-fn h0(context: &Context) -> [u8; common::PREHASH_SEED_LENGTH] {
-    let input = [
-        &u32_as_32le(context.config.lanes),
-        &u32_as_32le(context.config.hash_length),
-        &u32_as_32le(context.config.mem_cost),
-        &u32_as_32le(context.config.time_cost),
-        &u32_as_32le(context.config.version.as_u32()),
-        &u32_as_32le(context.config.variant.as_u32()),
-        &len_as_32le(context.pwd),
-        context.pwd,
-        &len_as_32le(context.salt),
-        context.salt,
-        &len_as_32le(context.config.secret),
-        context.config.secret,
-        &len_as_32le(context.config.ad),
-        context.config.ad,
-    ];
-    let mut out = [0u8; common::PREHASH_SEED_LENGTH];
-    blake2b(&mut out[0..common::PREHASH_DIGEST_LENGTH], &input);
-    out
-}
-
-fn hprime(out: &mut [u8], input: &[u8]) {
-    let out_len = out.len();
-    if out_len <= common::BLAKE2B_OUT_LENGTH {
-        blake2b(out, &[&u32_as_32le(out_len as u32), input]);
-    } else {
-        let ai_len = 32;
-        let mut out_buffer = [0u8; common::BLAKE2B_OUT_LENGTH];
-        let mut in_buffer = [0u8; common::BLAKE2B_OUT_LENGTH];
-        blake2b(&mut out_buffer, &[&u32_as_32le(out_len as u32), input]);
-        out[0..ai_len].clone_from_slice(&out_buffer[0..ai_len]);
-        let mut out_pos = ai_len;
-        let mut to_produce = out_len - ai_len;
-
-        while to_produce > common::BLAKE2B_OUT_LENGTH {
-            in_buffer.clone_from_slice(&out_buffer);
-            blake2b(&mut out_buffer, &[&in_buffer]);
-            out[out_pos..out_pos + ai_len].clone_from_slice(&out_buffer[0..ai_len]);
-            out_pos += ai_len;
-            to_produce -= ai_len;
-        }
-        blake2b(&mut out[out_pos..out_len], &[&out_buffer]);
-    }
-}
-
-fn index_alpha(context: &Context, position: &Position, pseudo_rand: u32, same_lane: bool) -> u32 {
-    // Pass 0:
-    // - This lane: all already finished segments plus already constructed blocks in this segment
-    // - Other lanes: all already finished segments
-    // Pass 1+:
-    // - This lane: (SYNC_POINTS - 1) last segments plus already constructed blocks in this segment
-    // - Other lanes : (SYNC_POINTS - 1) last segments
-    let reference_area_size: u32 = if position.pass == 0 {
-        // First pass
-        if position.slice == 0 {
-            // First slice
-            position.index - 1
-        } else if same_lane {
-            // The same lane => add current segment
-            position.slice * context.segment_length + position.index - 1
-        } else if position.index == 0 {
-            position.slice * context.segment_length - 1
-        } else {
-            position.slice * context.segment_length
-        }
-    } else {
-        // Second pass
-        if same_lane {
-            context.lane_length - context.segment_length + position.index - 1
-        } else if position.index == 0 {
-            context.lane_length - context.segment_length - 1
-        } else {
-            context.lane_length - context.segment_length
-        }
-    };
-    let reference_area_size = reference_area_size as u64;
-    let mut relative_position = pseudo_rand as u64;
-    relative_position = (relative_position * relative_position) >> 32;
-    relative_position = reference_area_size - 1 - ((reference_area_size * relative_position) >> 32);
-
-    // 1.2.5 Computing starting position
-    let start_position: u32 = if position.pass != 0 {
-        if position.slice == common::SYNC_POINTS - 1 {
-            0u32
-        } else {
-            (position.slice + 1) * context.segment_length
-        }
-    } else {
-        0u32
-    };
-    let start_position = start_position as u64;
-
-    // 1.2.6. Computing absolute position
-    ((start_position + relative_position) % context.lane_length as u64) as u32
-}
-
-fn len_as_32le(slice: &[u8]) -> [u8; 4] {
-    u32_as_32le(slice.len() as u32)
-}
-
-fn next_addresses(address_block: &mut Block, input_block: &mut Block, zero_block: &Block) {
-    input_block[6] += 1;
-    fill_block(zero_block, input_block, address_block, false);
-    fill_block(zero_block, &address_block.clone(), address_block, false);
-}
-
-fn p(
-    v0: &mut u64,
-    v1: &mut u64,
-    v2: &mut u64,
-    v3: &mut u64,
-    v4: &mut u64,
-    v5: &mut u64,
-    v6: &mut u64,
-    v7: &mut u64,
-    v8: &mut u64,
-    v9: &mut u64,
-    v10: &mut u64,
-    v11: &mut u64,
-    v12: &mut u64,
-    v13: &mut u64,
-    v14: &mut u64,
-    v15: &mut u64,
-) {
-    g(v0, v4, v8, v12);
-    g(v1, v5, v9, v13);
-    g(v2, v6, v10, v14);
-    g(v3, v7, v11, v15);
-    g(v0, v5, v10, v15);
-    g(v1, v6, v11, v12);
-    g(v2, v7, v8, v13);
-    g(v3, v4, v9, v14);
-}
-
-fn rotr64(w: u64, c: u32) -> u64 {
-    (w >> c) | (w << (64 - c))
-}
-
-fn u32_as_32le(val: u32) -> [u8; 4] {
-    unsafe { mem::transmute(val.to_le()) }
-}
diff --git a/vendor/rust-argon2/src/decoded.rs b/vendor/rust-argon2/src/decoded.rs
deleted file mode 100644
index 2055183062..0000000000
--- a/vendor/rust-argon2/src/decoded.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use crate::version::Version;
-use crate::variant::Variant;
-
-/// Structure that contains the decoded data.
-#[derive(Debug, Eq, PartialEq)]
-pub struct Decoded {
-    /// The variant.
-    pub variant: Variant,
-
-    /// The version.
-    pub version: Version,
-
-    /// The amount of memory requested (KiB).
-    pub mem_cost: u32,
-
-    /// The number of passes.
-    pub time_cost: u32,
-
-    /// The parallelism.
-    pub parallelism: u32,
-
-    /// The salt.
-    pub salt: Vec,
-
-    /// The hash.
-    pub hash: Vec,
-}
diff --git a/vendor/rust-argon2/src/encoding.rs b/vendor/rust-argon2/src/encoding.rs
deleted file mode 100644
index ded637dda0..0000000000
--- a/vendor/rust-argon2/src/encoding.rs
+++ /dev/null
@@ -1,400 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use base64;
-use crate::context::Context;
-use crate::decoded::Decoded;
-use crate::error::Error;
-use crate::result::Result;
-use crate::variant::Variant;
-use crate::version::Version;
-
-/// Structure containing the options.
-struct Options {
-    mem_cost: u32,
-    time_cost: u32,
-    parallelism: u32,
-}
-
-/// Gets the base64 encoded length of a byte slice with the specified length.
-pub fn base64_len(length: u32) -> u32 {
-    let olen = (length / 3) << 2;
-    match length % 3 {
-        2 => olen + 3,
-        1 => olen + 2,
-        _ => olen,
-    }
-}
-
-/// Attempts to decode the encoded string slice.
-pub fn decode_string(encoded: &str) -> Result {
-    let items: Vec<&str> = encoded.split('$').collect();
-    if items.len() == 6 {
-        decode_empty(items[0])?;
-        let variant = decode_variant(items[1])?;
-        let version = decode_version(items[2])?;
-        let options = decode_options(items[3])?;
-        let salt = base64::decode(items[4])?;
-        let hash = base64::decode(items[5])?;
-
-        Ok(Decoded {
-            variant,
-            version,
-            mem_cost: options.mem_cost,
-            time_cost: options.time_cost,
-            parallelism: options.parallelism,
-            salt,
-            hash,
-        })
-    } else if items.len() == 5 {
-        decode_empty(items[0])?;
-        let variant = decode_variant(items[1])?;
-        let options = decode_options(items[2])?;
-        let salt = base64::decode(items[3])?;
-        let hash = base64::decode(items[4])?;
-
-        Ok(Decoded {
-            variant,
-            version: Version::Version10,
-            mem_cost: options.mem_cost,
-            time_cost: options.time_cost,
-            parallelism: options.parallelism,
-            salt,
-            hash,
-        })
-    } else {
-        Err(Error::DecodingFail)
-    }
-}
-
-fn decode_empty(str: &str) -> Result<()> {
-    if str == "" {
-        Ok(())
-    } else {
-        Err(Error::DecodingFail)
-    }
-}
-
-fn decode_options(str: &str) -> Result {
-    let items: Vec<&str> = str.split(',').collect();
-    if items.len() == 3 {
-        Ok(Options {
-            mem_cost: decode_option(items[0], "m")?,
-            time_cost: decode_option(items[1], "t")?,
-            parallelism: decode_option(items[2], "p")?,
-        })
-    } else {
-        Err(Error::DecodingFail)
-    }
-}
-
-fn decode_option(str: &str, name: &str) -> Result {
-    let items: Vec<&str> = str.split('=').collect();
-    if items.len() == 2 {
-        if items[0] == name {
-            decode_u32(items[1])
-        } else {
-            Err(Error::DecodingFail)
-        }
-    } else {
-        Err(Error::DecodingFail)
-    }
-}
-
-fn decode_u32(str: &str) -> Result {
-    match str.parse() {
-        Ok(i) => Ok(i),
-        Err(_) => Err(Error::DecodingFail),
-    }
-}
-
-fn decode_variant(str: &str) -> Result {
-    Variant::from_str(str)
-}
-
-fn decode_version(str: &str) -> Result {
-    let items: Vec<&str> = str.split('=').collect();
-    if items.len() == 2 {
-        if items[0] == "v" {
-            Version::from_str(items[1])
-        } else {
-            Err(Error::DecodingFail)
-        }
-    } else {
-        Err(Error::DecodingFail)
-    }
-}
-
-/// Encodes the hash and context.
-pub fn encode_string(context: &Context, hash: &[u8]) -> String {
-    format!(
-        "${}$v={}$m={},t={},p={}${}${}",
-        context.config.variant,
-        context.config.version,
-        context.config.mem_cost,
-        context.config.time_cost,
-        context.config.lanes,
-        base64::encode_config(context.salt, base64::STANDARD_NO_PAD),
-        base64::encode_config(hash, base64::STANDARD_NO_PAD),
-    )
-}
-
-/// Gets the string length of the specified number.
-pub fn num_len(number: u32) -> u32 {
-    let mut len = 1;
-    let mut num = number;
-    while num >= 10 {
-        len += 1;
-        num /= 10;
-    }
-    len
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::config::Config;
-    use crate::context::Context;
-    use crate::decoded::Decoded;
-    use crate::encoding::{base64_len, decode_string, encode_string, num_len};
-    use crate::error::Error;
-    use crate::thread_mode::ThreadMode;
-    use crate::variant::Variant;
-    use crate::version::Version;
-
-    #[test]
-    fn base64_len_returns_correct_length() {
-        let tests = vec![
-            (1, 2),
-            (2, 3),
-            (3, 4),
-            (4, 6),
-            (5, 7),
-            (6, 8),
-            (7, 10),
-            (8, 11),
-            (9, 12),
-            (10, 14),
-        ];
-        for (len, expected) in tests {
-            let actual = base64_len(len);
-            assert_eq!(actual, expected);
-        }
-    }
-
-    #[test]
-    fn decode_string_with_version10_returns_correct_result() {
-        let encoded = "$argon2i$v=16$m=4096,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let expected = Decoded {
-            variant: Variant::Argon2i,
-            version: Version::Version10,
-            mem_cost: 4096,
-            time_cost: 3,
-            parallelism: 1,
-            salt: b"salt1234".to_vec(),
-            hash: b"12345678901234567890123456789012".to_vec(),
-        };
-        let actual = decode_string(encoded).unwrap();
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn decode_string_with_version13_returns_correct_result() {
-        let encoded = "$argon2i$v=19$m=4096,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let expected = Decoded {
-            variant: Variant::Argon2i,
-            version: Version::Version13,
-            mem_cost: 4096,
-            time_cost: 3,
-            parallelism: 1,
-            salt: b"salt1234".to_vec(),
-            hash: b"12345678901234567890123456789012".to_vec(),
-        };
-        let actual = decode_string(encoded).unwrap();
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn decode_string_without_version_returns_correct_result() {
-        let encoded = "$argon2i$m=4096,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let expected = Decoded {
-            variant: Variant::Argon2i,
-            version: Version::Version10,
-            mem_cost: 4096,
-            time_cost: 3,
-            parallelism: 1,
-            salt: b"salt1234".to_vec(),
-            hash: b"12345678901234567890123456789012".to_vec(),
-        };
-        let actual = decode_string(encoded).unwrap();
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn decode_string_without_variant_returns_error_result() {
-        let encoded = "$m=4096,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_empty_variant_returns_error_result() {
-        let encoded = "$$m=4096,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_invalid_variant_returns_error_result() {
-        let encoded = "$argon$m=4096,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_without_mem_cost_returns_error_result() {
-        let encoded = "$argon2i$t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_empty_mem_cost_returns_error_result() {
-        let encoded = "$argon2i$m=,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_non_numeric_mem_cost_returns_error_result() {
-        let encoded = "$argon2i$m=a,t=3,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_without_time_cost_returns_error_result() {
-        let encoded = "$argon2i$m=4096,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_empty_time_cost_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_non_numeric_time_cost_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=a,p=1\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_without_parallelism_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=3\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_empty_parallelism_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=3,p=\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_non_numeric_parallelism_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=3,p=a\
-                       $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_without_salt_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=3,p=1\
-                       $MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_without_hash_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=3,p=a\
-                       $c2FsdDEyMzQ=";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn decode_string_with_empty_hash_returns_error_result() {
-        let encoded = "$argon2i$m=4096,t=3,p=a\
-                       $c2FsdDEyMzQ=$";
-        let result = decode_string(encoded);
-        assert_eq!(result, Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn encode_string_returns_correct_string() {
-        let hash = b"12345678901234567890123456789012".to_vec();
-        let config = Config {
-            ad: &[],
-            hash_length: hash.len() as u32,
-            lanes: 1,
-            mem_cost: 4096,
-            secret: &[],
-            thread_mode: ThreadMode::Parallel,
-            time_cost: 3,
-            variant: Variant::Argon2i,
-            version: Version::Version13,
-        };
-        let pwd = b"password".to_vec();
-        let salt = b"salt1234".to_vec();
-        let context = Context::new(config, &pwd, &salt).unwrap();
-        let expected = "$argon2i$v=19$m=4096,t=3,p=1\
-                        $c2FsdDEyMzQ$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI";
-        let actual = encode_string(&context, &hash);
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn num_len_returns_correct_length() {
-        let tests = vec![
-            (1, 1),
-            (10, 2),
-            (110, 3),
-            (1230, 4),
-            (12340, 5),
-            (123457, 6),
-        ];
-        for (num, expected) in tests {
-            let actual = num_len(num);
-            assert_eq!(actual, expected);
-        }
-    }
-}
diff --git a/vendor/rust-argon2/src/error.rs b/vendor/rust-argon2/src/error.rs
deleted file mode 100644
index 4832a422f9..0000000000
--- a/vendor/rust-argon2/src/error.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::{error, fmt};
-
-/// Error type for Argon2 errors.
-#[derive(Debug, PartialEq)]
-pub enum Error {
-    /// The output (hash) is too short (minimum is 4).
-    OutputTooShort,
-
-    /// The output (hash) is too long (maximum is 2^32 - 1).
-    OutputTooLong,
-
-    /// The password is too short (minimum is 0).
-    PwdTooShort,
-
-    /// The password is too long (maximum is 2^32 - 1).
-    PwdTooLong,
-
-    /// The salt is too short (minimum is 8).
-    SaltTooShort,
-
-    /// The salt is too long (maximum is 2^32 - 1).
-    SaltTooLong,
-
-    /// The associated data is too short (minimum is 0).
-    AdTooShort,
-
-    /// The associated data is too long (maximum is 2^32 - 1).
-    AdTooLong,
-
-    /// The secret value is too short (minimum is 0).
-    SecretTooShort,
-
-    /// The secret value is too long (maximum is 2^32 - 1).
-    SecretTooLong,
-
-    /// The time cost (passes) is too small (minimum is 1).
-    TimeTooSmall,
-
-    /// The time cost (passes) is too large (maximum is 2^32 - 1).
-    TimeTooLarge,
-
-    /// The memory cost is too small (minimum is 8 x parallelism).
-    MemoryTooLittle,
-
-    /// The memory cost is too large (maximum 2GiB on 32-bit or 4TiB on 64-bit).
-    MemoryTooMuch,
-
-    /// The number of lanes (parallelism) is too small (minimum is 1).
-    LanesTooFew,
-
-    /// The number of lanes (parallelism) is too large (maximum is 2^24 - 1).
-    LanesTooMany,
-
-    /// Incorrect Argon2 variant.
-    IncorrectType,
-
-    /// Incorrect Argon2 version.
-    IncorrectVersion,
-
-    /// The decoding of the encoded data has failed.
-    DecodingFail,
-}
-
-impl Error {
-    fn msg(&self) -> &str {
-        match *self {
-            Error::OutputTooShort => "Output is too short",
-            Error::OutputTooLong => "Output is too long",
-            Error::PwdTooShort => "Password is too short",
-            Error::PwdTooLong => "Password is too long",
-            Error::SaltTooShort => "Salt is too short",
-            Error::SaltTooLong => "Salt is too long",
-            Error::AdTooShort => "Associated data is too short",
-            Error::AdTooLong => "Associated data is too long",
-            Error::SecretTooShort => "Secret is too short",
-            Error::SecretTooLong => "Secret is too long",
-            Error::TimeTooSmall => "Time cost is too small",
-            Error::TimeTooLarge => "Time cost is too large",
-            Error::MemoryTooLittle => "Memory cost is too small",
-            Error::MemoryTooMuch => "Memory cost is too large",
-            Error::LanesTooFew => "Too few lanes",
-            Error::LanesTooMany => "Too many lanes",
-            Error::IncorrectType => "There is no such type of Argon2",
-            Error::IncorrectVersion => "There is no such version of Argon2",
-            Error::DecodingFail => "Decoding failed",
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.msg())
-    }
-}
-
-impl error::Error for Error {
-    fn description(&self) -> &str {
-        self.msg()
-    }
-
-    fn cause(&self) -> Option<&dyn error::Error> {
-        None
-    }
-}
-
-impl From for Error {
-    fn from(_: base64::DecodeError) -> Self {
-        Error::DecodingFail
-    }
-}
diff --git a/vendor/rust-argon2/src/lib.rs b/vendor/rust-argon2/src/lib.rs
deleted file mode 100644
index 795526863d..0000000000
--- a/vendor/rust-argon2/src/lib.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Library for hashing passwords using
-//! [Argon2](https://github.com/P-H-C/phc-winner-argon2), the password-hashing
-//! function that won the
-//! [Password Hashing Competition (PHC)](https://password-hashing.net).
-//!
-//! # Usage
-//!
-//! To use this crate, add the following to your Cargo.toml:
-//!
-//! ```toml
-//! [dependencies]
-//! rust-argon2 = "0.7"
-//! ```
-//!
-//! And the following to your crate root:
-//!
-//! ```rust
-//! extern crate argon2;
-//! ```
-//!
-//! # Examples
-//!
-//! Create a password hash using the defaults and verify it:
-//!
-//! ```rust
-//! use argon2::{self, Config};
-//!
-//! let password = b"password";
-//! let salt = b"randomsalt";
-//! let config = Config::default();
-//! let hash = argon2::hash_encoded(password, salt, &config).unwrap();
-//! let matches = argon2::verify_encoded(&hash, password).unwrap();
-//! assert!(matches);
-//! ```
-//!
-//! Create a password hash with custom settings and verify it:
-//!
-//! ```rust
-//! use argon2::{self, Config, ThreadMode, Variant, Version};
-//!
-//! let password = b"password";
-//! let salt = b"othersalt";
-//! let config = Config {
-//!     variant: Variant::Argon2i,
-//!     version: Version::Version13,
-//!     mem_cost: 65536,
-//!     time_cost: 10,
-//!     lanes: 4,
-//!     thread_mode: ThreadMode::Parallel,
-//!     secret: &[],
-//!     ad: &[],
-//!     hash_length: 32
-//! };
-//! let hash = argon2::hash_encoded(password, salt, &config).unwrap();
-//! let matches = argon2::verify_encoded(&hash, password).unwrap();
-//! assert!(matches);
-//! ```
-//!
-//! # Limitations
-//!
-//! This crate has the same limitation as the `blake2-rfc` crate that it uses.
-//! It does not attempt to clear potentially sensitive data from its work
-//! memory. To do so correctly without a heavy performance penalty would
-//! require help from the compiler. It's better to not attempt to do so than to
-//! present a false assurance.
-//!
-//! This version uses the standard implementation and does not yet implement
-//! optimizations. Therefore, it is not the fastest implementation available.
-
-mod argon2;
-mod block;
-mod common;
-mod config;
-mod context;
-mod core;
-mod decoded;
-mod encoding;
-mod error;
-mod memory;
-mod result;
-mod thread_mode;
-mod variant;
-mod version;
-
-pub use crate::argon2::*;
-pub use crate::config::Config;
-pub use crate::error::Error;
-pub use crate::result::Result;
-pub use crate::thread_mode::ThreadMode;
-pub use crate::variant::Variant;
-pub use crate::version::Version;
diff --git a/vendor/rust-argon2/src/memory.rs b/vendor/rust-argon2/src/memory.rs
deleted file mode 100644
index 86270201b7..0000000000
--- a/vendor/rust-argon2/src/memory.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt;
-use std::fmt::Debug;
-use std::ops::{Index, IndexMut};
-use crate::block::Block;
-
-/// Structure representing the memory matrix.
-pub struct Memory {
-    /// The number of rows.
-    rows: usize,
-
-    /// The number of columns.
-    cols: usize,
-
-    /// The flat array of blocks representing the memory matrix.
-    blocks: Box<[Block]>,
-}
-
-impl Memory {
-    /// Creates a new memory matrix.
-    pub fn new(lanes: u32, lane_length: u32) -> Memory {
-        let rows = lanes as usize;
-        let cols = lane_length as usize;
-        let total = rows * cols;
-        let blocks = vec![Block::zero(); total].into_boxed_slice();
-        Memory {
-            rows,
-            cols,
-            blocks,
-        }
-    }
-
-    /// Gets the mutable lanes representation of the memory matrix.
-    pub fn as_lanes_mut(&mut self) -> Vec<&mut Memory> {
-        let ptr: *mut Memory = self;
-        let mut vec = Vec::with_capacity(self.rows);
-        for _ in 0..self.rows {
-            vec.push(unsafe { &mut (*ptr) });
-        }
-        vec
-    }
-}
-
-impl Debug for Memory {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "Memory {{ rows: {}, cols: {} }}", self.rows, self.cols)
-    }
-}
-
-impl Index for Memory {
-    type Output = Block;
-    fn index(&self, index: u32) -> &Block {
-        &self.blocks[index as usize]
-    }
-}
-
-impl Index for Memory {
-    type Output = Block;
-    fn index(&self, index: u64) -> &Block {
-        &self.blocks[index as usize]
-    }
-}
-
-impl Index<(u32, u32)> for Memory {
-    type Output = Block;
-    fn index(&self, index: (u32, u32)) -> &Block {
-        let pos = ((index.0 as usize) * self.cols) + (index.1 as usize);
-        &self.blocks[pos]
-    }
-}
-
-impl IndexMut for Memory {
-    fn index_mut(&mut self, index: u32) -> &mut Block {
-        &mut self.blocks[index as usize]
-    }
-}
-
-impl IndexMut for Memory {
-    fn index_mut(&mut self, index: u64) -> &mut Block {
-        &mut self.blocks[index as usize]
-    }
-}
-
-impl IndexMut<(u32, u32)> for Memory {
-    fn index_mut(&mut self, index: (u32, u32)) -> &mut Block {
-        let pos = ((index.0 as usize) * self.cols) + (index.1 as usize);
-        &mut self.blocks[pos]
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::memory::Memory;
-
-    #[test]
-    fn new_returns_correct_instance() {
-        let lanes = 4;
-        let lane_length = 128;
-        let memory = Memory::new(lanes, lane_length);
-        assert_eq!(memory.rows, lanes as usize);
-        assert_eq!(memory.cols, lane_length as usize);
-        assert_eq!(memory.blocks.len(), 512);
-    }
-
-    #[test]
-    fn as_lanes_mut_returns_correct_vec() {
-        let mut memory = Memory::new(4, 128);
-        let lanes = memory.as_lanes_mut();
-        assert_eq!(lanes.len(), 4);
-    }
-}
diff --git a/vendor/rust-argon2/src/result.rs b/vendor/rust-argon2/src/result.rs
deleted file mode 100644
index d921bfcf21..0000000000
--- a/vendor/rust-argon2/src/result.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::result;
-use crate::error::Error;
-
-/// A specialized result type for Argon2 operations.
-pub type Result = result::Result;
diff --git a/vendor/rust-argon2/src/thread_mode.rs b/vendor/rust-argon2/src/thread_mode.rs
deleted file mode 100644
index d02c787cf9..0000000000
--- a/vendor/rust-argon2/src/thread_mode.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2017 Xidorn Quan 
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// The thread mode used to perform the hashing.
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum ThreadMode {
-    /// Run in one thread.
-    Sequential,
-
-    /// Run in the same number of threads as the number of lanes.
-    Parallel,
-}
-
-impl ThreadMode {
-    /// Create a thread mode from the threads count.
-    pub fn from_threads(threads: u32) -> ThreadMode {
-        if threads > 1 {
-            ThreadMode::Parallel
-        } else {
-            ThreadMode::Sequential
-        }
-    }
-}
-
-impl Default for ThreadMode {
-    fn default() -> ThreadMode {
-        ThreadMode::Sequential
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::thread_mode::ThreadMode;
-
-    #[test]
-    fn default_returns_correct_thread_mode() {
-        assert_eq!(ThreadMode::default(), ThreadMode::Sequential);
-    }
-
-    #[test]
-    fn from_threads_returns_correct_thread_mode() {
-        assert_eq!(ThreadMode::from_threads(0), ThreadMode::Sequential);
-        assert_eq!(ThreadMode::from_threads(1), ThreadMode::Sequential);
-        assert_eq!(ThreadMode::from_threads(2), ThreadMode::Parallel);
-        assert_eq!(ThreadMode::from_threads(10), ThreadMode::Parallel);
-        assert_eq!(ThreadMode::from_threads(100), ThreadMode::Parallel);
-    }
-}
diff --git a/vendor/rust-argon2/src/variant.rs b/vendor/rust-argon2/src/variant.rs
deleted file mode 100644
index 54126734c9..0000000000
--- a/vendor/rust-argon2/src/variant.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt;
-use crate::error::Error;
-use crate::result::Result;
-
-/// The Argon2 variant.
-#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
-pub enum Variant {
-    /// Argon2 using data-dependent memory access to thwart tradeoff attacks.
-    /// Recommended for cryptocurrencies and backend servers.
-    Argon2d = 0,
-
-    /// Argon2 using data-independent memory access to thwart side-channel
-    /// attacks. Recommended for password hashing and password-based key
-    /// derivation.
-    Argon2i = 1,
-
-    /// Argon2 using hybrid construction.
-    Argon2id = 2,
-}
-
-impl Variant {
-    /// Gets the lowercase string slice representation of the variant.
-    pub fn as_lowercase_str(&self) -> &'static str {
-        match *self {
-            Variant::Argon2d => "argon2d",
-            Variant::Argon2i => "argon2i",
-            Variant::Argon2id => "argon2id",
-        }
-    }
-
-    /// Gets the u32 representation of the variant.
-    pub fn as_u32(&self) -> u32 {
-        *self as u32
-    }
-
-    /// Gets the u64 representation of the variant.
-    pub fn as_u64(&self) -> u64 {
-        *self as u64
-    }
-
-    /// Gets the uppercase string slice representation of the variant.
-    pub fn as_uppercase_str(&self) -> &'static str {
-        match *self {
-            Variant::Argon2d => "Argon2d",
-            Variant::Argon2i => "Argon2i",
-            Variant::Argon2id => "Argon2id",
-        }
-    }
-
-    /// Attempts to create a variant from a string slice.
-    pub fn from_str(str: &str) -> Result {
-        match str {
-            "Argon2d" => Ok(Variant::Argon2d),
-            "Argon2i" => Ok(Variant::Argon2i),
-            "Argon2id" => Ok(Variant::Argon2id),
-            "argon2d" => Ok(Variant::Argon2d),
-            "argon2i" => Ok(Variant::Argon2i),
-            "argon2id" => Ok(Variant::Argon2id),
-            _ => Err(Error::DecodingFail),
-        }
-    }
-
-    /// Attempts to create a variant from an u32.
-    pub fn from_u32(val: u32) -> Result {
-        match val {
-            0 => Ok(Variant::Argon2d),
-            1 => Ok(Variant::Argon2i),
-            2 => Ok(Variant::Argon2id),
-            _ => Err(Error::IncorrectType),
-        }
-    }
-}
-
-impl Default for Variant {
-    fn default() -> Variant {
-        Variant::Argon2i
-    }
-}
-
-impl fmt::Display for Variant {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.as_lowercase_str())
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::error::Error;
-    use crate::variant::Variant;
-
-    #[test]
-    fn as_lowercase_str_returns_correct_str() {
-        assert_eq!(Variant::Argon2d.as_lowercase_str(), "argon2d");
-        assert_eq!(Variant::Argon2i.as_lowercase_str(), "argon2i");
-        assert_eq!(Variant::Argon2id.as_lowercase_str(), "argon2id");
-    }
-
-    #[test]
-    fn as_u32_returns_correct_u32() {
-        assert_eq!(Variant::Argon2d.as_u32(), 0);
-        assert_eq!(Variant::Argon2i.as_u32(), 1);
-        assert_eq!(Variant::Argon2id.as_u32(), 2);
-    }
-
-    #[test]
-    fn as_u64_returns_correct_u64() {
-        assert_eq!(Variant::Argon2d.as_u64(), 0);
-        assert_eq!(Variant::Argon2i.as_u64(), 1);
-        assert_eq!(Variant::Argon2id.as_u64(), 2);
-    }
-
-    #[test]
-    fn as_uppercase_str_returns_correct_str() {
-        assert_eq!(Variant::Argon2d.as_uppercase_str(), "Argon2d");
-        assert_eq!(Variant::Argon2i.as_uppercase_str(), "Argon2i");
-        assert_eq!(Variant::Argon2id.as_uppercase_str(), "Argon2id");
-    }
-
-    #[test]
-    fn default_returns_correct_variant() {
-        assert_eq!(Variant::default(), Variant::Argon2i);
-    }
-
-    #[test]
-    fn display_returns_correct_string() {
-        assert_eq!(format!("{}", Variant::Argon2d), "argon2d");
-        assert_eq!(format!("{}", Variant::Argon2i), "argon2i");
-        assert_eq!(format!("{}", Variant::Argon2id), "argon2id");
-    }
-
-    #[test]
-    fn from_str_returns_correct_result() {
-        assert_eq!(Variant::from_str("Argon2d"), Ok(Variant::Argon2d));
-        assert_eq!(Variant::from_str("Argon2i"), Ok(Variant::Argon2i));
-        assert_eq!(Variant::from_str("Argon2id"), Ok(Variant::Argon2id));
-        assert_eq!(Variant::from_str("argon2d"), Ok(Variant::Argon2d));
-        assert_eq!(Variant::from_str("argon2i"), Ok(Variant::Argon2i));
-        assert_eq!(Variant::from_str("argon2id"), Ok(Variant::Argon2id));
-        assert_eq!(Variant::from_str("foobar"), Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn from_u32_returns_correct_result() {
-        assert_eq!(Variant::from_u32(0), Ok(Variant::Argon2d));
-        assert_eq!(Variant::from_u32(1), Ok(Variant::Argon2i));
-        assert_eq!(Variant::from_u32(2), Ok(Variant::Argon2id));
-        assert_eq!(Variant::from_u32(3), Err(Error::IncorrectType));
-    }
-}
diff --git a/vendor/rust-argon2/src/version.rs b/vendor/rust-argon2/src/version.rs
deleted file mode 100644
index 08cdbc6d90..0000000000
--- a/vendor/rust-argon2/src/version.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt;
-use crate::error::Error;
-use crate::result::Result;
-
-/// The Argon2 version.
-#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
-pub enum Version {
-    /// Version 0x10.
-    Version10 = 0x10,
-
-    /// Version 0x13 (Recommended).
-    Version13 = 0x13,
-}
-
-impl Version {
-    /// Gets the u32 representation of the version.
-    pub fn as_u32(&self) -> u32 {
-        *self as u32
-    }
-
-    /// Attempts to create a version from a string slice.
-    pub fn from_str(str: &str) -> Result {
-        match str {
-            "16" => Ok(Version::Version10),
-            "19" => Ok(Version::Version13),
-            _ => Err(Error::DecodingFail),
-        }
-    }
-
-    /// Attempts to create a version from an u32.
-    pub fn from_u32(val: u32) -> Result {
-        match val {
-            0x10 => Ok(Version::Version10),
-            0x13 => Ok(Version::Version13),
-            _ => Err(Error::IncorrectVersion),
-        }
-    }
-}
-
-impl Default for Version {
-    fn default() -> Version {
-        Version::Version13
-    }
-}
-
-impl fmt::Display for Version {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.as_u32())
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-
-    use crate::error::Error;
-    use crate::version::Version;
-
-    #[test]
-    fn as_u32_returns_correct_u32() {
-        assert_eq!(Version::Version10.as_u32(), 0x10);
-        assert_eq!(Version::Version13.as_u32(), 0x13);
-    }
-
-    #[test]
-    fn default_returns_correct_version() {
-        assert_eq!(Version::default(), Version::Version13);
-    }
-
-    #[test]
-    fn display_returns_correct_string() {
-        assert_eq!(format!("{}", Version::Version10), "16");
-        assert_eq!(format!("{}", Version::Version13), "19");
-    }
-
-    #[test]
-    fn from_str_returns_correct_result() {
-        assert_eq!(Version::from_str("16"), Ok(Version::Version10));
-        assert_eq!(Version::from_str("19"), Ok(Version::Version13));
-        assert_eq!(Version::from_str("11"), Err(Error::DecodingFail));
-    }
-
-    #[test]
-    fn from_u32_returns_correct_result() {
-        assert_eq!(Version::from_u32(0x10), Ok(Version::Version10));
-        assert_eq!(Version::from_u32(0x13), Ok(Version::Version13));
-        assert_eq!(Version::from_u32(0), Err(Error::IncorrectVersion));
-    }
-}
diff --git a/vendor/rust-argon2/tests/integration_test.rs b/vendor/rust-argon2/tests/integration_test.rs
deleted file mode 100644
index edd1c94eee..0000000000
--- a/vendor/rust-argon2/tests/integration_test.rs
+++ /dev/null
@@ -1,1073 +0,0 @@
-// Copyright (c) 2017 Martijn Rijkeboer 
-//
-// Licensed under the Apache License, Version 2.0  or the MIT license
-// , at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// These tests are based on Argon's test.c test suite.
-
-use argon2::{Error, Config, ThreadMode, Variant, Version};
-use hex::ToHex;
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version10_1() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "2ec0d925358f5830caf0c1cc8a3ee58b34505759428b859c79b72415f51f9221",
-        "$argon2d$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $LsDZJTWPWDDK8MHMij7lizRQV1lCi4WcebckFfUfkiE",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version10_2() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        2,
-        1048576,
-        1,
-        b"password",
-        b"somesalt",
-        "28ae0d1037991b55faec18425274d5f9169b2f44bee19b45b7a561d489d6019a",
-        "$argon2d$m=1048576,t=2,p=1$c29tZXNhbHQ\
-               $KK4NEDeZG1X67BhCUnTV+RabL0S+4ZtFt6Vh1InWAZo",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version10_3() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        2,
-        262144,
-        1,
-        b"password",
-        b"somesalt",
-        "41c89760d85b80ba1be7e959ebd16390bfb4176db9466d70f670457ccade4ec8",
-        "$argon2d$m=262144,t=2,p=1$c29tZXNhbHQ\
-               $QciXYNhbgLob5+lZ69FjkL+0F225Rm1w9nBFfMreTsg",
-    );
-}
-
-#[test]
-fn test_argon2d_version10_4() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        2,
-        256,
-        1,
-        b"password",
-        b"somesalt",
-        "bd404868ff00c52e7543c8332e6a772a5724892d7e328d5cf253bbc8e726b371",
-        "$argon2d$m=256,t=2,p=1$c29tZXNhbHQ\
-               $vUBIaP8AxS51Q8gzLmp3KlckiS1+Mo1c8lO7yOcms3E",
-    );
-}
-
-#[test]
-fn test_argon2d_version10_5() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        2,
-        256,
-        2,
-        b"password",
-        b"somesalt",
-        "6a91d02b9f8854ba0841f04aa6e53c1d3374c0a0c646b8e431b03de805b91ec3",
-        "$argon2d$m=256,t=2,p=2$c29tZXNhbHQ\
-               $apHQK5+IVLoIQfBKpuU8HTN0wKDGRrjkMbA96AW5HsM",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version10_6() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        1,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "05d1d0a85f499e9397b9c1c936b20f366a7273ccf259e2edfdb44ca8f86dd11f",
-        "$argon2d$m=65536,t=1,p=1$c29tZXNhbHQ\
-               $BdHQqF9JnpOXucHJNrIPNmpyc8zyWeLt/bRMqPht0R8",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version10_7() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        4,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "99e787faced20949df5a3b9c8620712b45cfea061716adf8b13efb7feee44084",
-        "$argon2d$m=65536,t=4,p=1$c29tZXNhbHQ\
-               $meeH+s7SCUnfWjuchiBxK0XP6gYXFq34sT77f+7kQIQ",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version10_8() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"differentpassword",
-        b"somesalt",
-        "b9c2e4a4ec9a6db99ca4e2b549dd64256305b95754b0a70ad757cd1ff7eed4a4",
-        "$argon2d$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $ucLkpOyabbmcpOK1Sd1kJWMFuVdUsKcK11fNH/fu1KQ",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version10_9() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"password",
-        b"diffsalt",
-        "d1da14196c233e0a3cb687aa6e6c465cb50669ffdb891158c2b75722395f14d5",
-        "$argon2d$m=65536,t=2,p=1$ZGlmZnNhbHQ\
-               $0doUGWwjPgo8toeqbmxGXLUGaf/biRFYwrdXIjlfFNU",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version13_1() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "955e5d5b163a1b60bba35fc36d0496474fba4f6b59ad53628666f07fb2f93eaf",
-        "$argon2d$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $lV5dWxY6G2C7o1/DbQSWR0+6T2tZrVNihmbwf7L5Pq8",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version13_2() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        2,
-        1048576,
-        1,
-        b"password",
-        b"somesalt",
-        "c2d680a6e7ac1b75e2c2b1e5e71b1701584869492efea4a76ccc91fec622d1ae",
-        "$argon2d$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ\
-               $wtaApuesG3XiwrHl5xsXAVhIaUku/qSnbMyR/sYi0a4",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version13_3() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        2,
-        262144,
-        1,
-        b"password",
-        b"somesalt",
-        "9678b3379ce20ddc96fa38f045c8cdc96282287ff2848efd867582b9528a2155",
-        "$argon2d$v=19$m=262144,t=2,p=1$c29tZXNhbHQ\
-               $lnizN5ziDdyW+jjwRcjNyWKCKH/yhI79hnWCuVKKIVU",
-    );
-}
-
-#[test]
-fn test_argon2d_version13_4() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        2,
-        256,
-        1,
-        b"password",
-        b"somesalt",
-        "25c4ee8ba448054b49efc804e478b9d823be1f9bd2e99f51d6ec4007a3a1501f",
-        "$argon2d$v=19$m=256,t=2,p=1$c29tZXNhbHQ\
-               $JcTui6RIBUtJ78gE5Hi52CO+H5vS6Z9R1uxAB6OhUB8",
-    );
-}
-
-#[test]
-fn test_argon2d_version13_5() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        2,
-        256,
-        2,
-        b"password",
-        b"somesalt",
-        "7b69c92d7c3889aad1281dbc8baefc12cc37c80f1c75e33ef2c2d40c28ebc573",
-        "$argon2d$v=19$m=256,t=2,p=2$c29tZXNhbHQ\
-               $e2nJLXw4iarRKB28i678Esw3yA8cdeM+8sLUDCjrxXM",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version13_6() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        1,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "8193708c030f09b121526b0efdffce738fef0ddb13937a65d43f3f1eab9aa802",
-        "$argon2d$v=19$m=65536,t=1,p=1$c29tZXNhbHQ\
-               $gZNwjAMPCbEhUmsO/f/Oc4/vDdsTk3pl1D8/HquaqAI",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version13_7() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        4,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "cd1e2816cf8895fffe535b87b7a0aa3612f73c6ce063de83b1e7b4621ca0afe6",
-        "$argon2d$v=19$m=65536,t=4,p=1$c29tZXNhbHQ\
-               $zR4oFs+Ilf/+U1uHt6CqNhL3PGzgY96Dsee0Yhygr+Y",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version13_8() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"differentpassword",
-        b"somesalt",
-        "a34dafc893182d521ae467bbfdce60f973a1223c4615654efeb0bfef8a930e25",
-        "$argon2d$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $o02vyJMYLVIa5Ge7/c5g+XOhIjxGFWVO/rC/74qTDiU",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2d_version13_9() {
-    hash_test(
-        Variant::Argon2d,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"password",
-        b"diffsalt",
-        "f00eb8a999a1c6949c61fbbee3c3cece5066e3ff5c79aed421266055e2bf4dd7",
-        "$argon2d$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ\
-               $8A64qZmhxpScYfu+48POzlBm4/9cea7UISZgVeK/Tdc",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version10_1() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "f6c4db4a54e2a370627aff3db6176b94a2a209a62c8e36152711802f7b30c694",
-        "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version10_2() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        2,
-        1048576,
-        1,
-        b"password",
-        b"somesalt",
-        "9690ec55d28d3ed32562f2e73ea62b02b018757643a2ae6e79528459de8106e9",
-        "$argon2i$m=1048576,t=2,p=1$c29tZXNhbHQ\
-               $lpDsVdKNPtMlYvLnPqYrArAYdXZDoq5ueVKEWd6BBuk",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version10_3() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        2,
-        262144,
-        1,
-        b"password",
-        b"somesalt",
-        "3e689aaa3d28a77cf2bc72a51ac53166761751182f1ee292e3f677a7da4c2467",
-        "$argon2i$m=262144,t=2,p=1$c29tZXNhbHQ\
-               $Pmiaqj0op3zyvHKlGsUxZnYXURgvHuKS4/Z3p9pMJGc",
-    );
-}
-
-#[test]
-fn test_argon2i_version10_4() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        2,
-        256,
-        1,
-        b"password",
-        b"somesalt",
-        "fd4dd83d762c49bdeaf57c47bdcd0c2f1babf863fdeb490df63ede9975fccf06",
-        "$argon2i$m=256,t=2,p=1$c29tZXNhbHQ\
-               $/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY",
-    );
-}
-
-#[test]
-fn test_argon2i_version10_5() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        2,
-        256,
-        2,
-        b"password",
-        b"somesalt",
-        "b6c11560a6a9d61eac706b79a2f97d68b4463aa3ad87e00c07e2b01e90c564fb",
-        "$argon2i$m=256,t=2,p=2$c29tZXNhbHQ\
-               $tsEVYKap1h6scGt5ovl9aLRGOqOth+AMB+KwHpDFZPs",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version10_6() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        1,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "81630552b8f3b1f48cdb1992c4c678643d490b2b5eb4ff6c4b3438b5621724b2",
-        "$argon2i$m=65536,t=1,p=1$c29tZXNhbHQ\
-               $gWMFUrjzsfSM2xmSxMZ4ZD1JCytetP9sSzQ4tWIXJLI",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version10_7() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        4,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "f212f01615e6eb5d74734dc3ef40ade2d51d052468d8c69440a3a1f2c1c2847b",
-        "$argon2i$m=65536,t=4,p=1$c29tZXNhbHQ\
-               $8hLwFhXm6110c03D70Ct4tUdBSRo2MaUQKOh8sHChHs",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version10_8() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"differentpassword",
-        b"somesalt",
-        "e9c902074b6754531a3a0be519e5baf404b30ce69b3f01ac3bf21229960109a3",
-        "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $6ckCB0tnVFMaOgvlGeW69ASzDOabPwGsO/ISKZYBCaM",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version10_9() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"password",
-        b"diffsalt",
-        "79a103b90fe8aef8570cb31fc8b22259778916f8336b7bdac3892569d4f1c497",
-        "$argon2i$m=65536,t=2,p=1$ZGlmZnNhbHQ\
-               $eaEDuQ/orvhXDLMfyLIiWXeJFvgza3vaw4kladTxxJc",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version13_1() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "c1628832147d9720c5bd1cfd61367078729f6dfb6f8fea9ff98158e0d7816ed0",
-        "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version13_2() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        2,
-        1048576,
-        1,
-        b"password",
-        b"somesalt",
-        "d1587aca0922c3b5d6a83edab31bee3c4ebaef342ed6127a55d19b2351ad1f41",
-        "$argon2i$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ\
-               $0Vh6ygkiw7XWqD7asxvuPE667zQu1hJ6VdGbI1GtH0E",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version13_3() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        2,
-        262144,
-        1,
-        b"password",
-        b"somesalt",
-        "296dbae80b807cdceaad44ae741b506f14db0959267b183b118f9b24229bc7cb",
-        "$argon2i$v=19$m=262144,t=2,p=1$c29tZXNhbHQ\
-               $KW266AuAfNzqrUSudBtQbxTbCVkmexg7EY+bJCKbx8s",
-    );
-}
-
-#[test]
-fn test_argon2i_version13_4() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        2,
-        256,
-        1,
-        b"password",
-        b"somesalt",
-        "89e9029f4637b295beb027056a7336c414fadd43f6b208645281cb214a56452f",
-        "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ\
-               $iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8",
-    );
-}
-
-#[test]
-fn test_argon2i_version13_5() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        2,
-        256,
-        2,
-        b"password",
-        b"somesalt",
-        "4ff5ce2769a1d7f4c8a491df09d41a9fbe90e5eb02155a13e4c01e20cd4eab61",
-        "$argon2i$v=19$m=256,t=2,p=2$c29tZXNhbHQ\
-               $T/XOJ2mh1/TIpJHfCdQan76Q5esCFVoT5MAeIM1Oq2E",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version13_6() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        1,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "d168075c4d985e13ebeae560cf8b94c3b5d8a16c51916b6f4ac2da3ac11bbecf",
-        "$argon2i$v=19$m=65536,t=1,p=1$c29tZXNhbHQ\
-               $0WgHXE2YXhPr6uVgz4uUw7XYoWxRkWtvSsLaOsEbvs8",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version13_7() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        4,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "aaa953d58af3706ce3df1aefd4a64a84e31d7f54175231f1285259f88174ce5b",
-        "$argon2i$v=19$m=65536,t=4,p=1$c29tZXNhbHQ\
-               $qqlT1YrzcGzj3xrv1KZKhOMdf1QXUjHxKFJZ+IF0zls",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version13_8() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"differentpassword",
-        b"somesalt",
-        "14ae8da01afea8700c2358dcef7c5358d9021282bd88663a4562f59fb74d22ee",
-        "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $FK6NoBr+qHAMI1jc73xTWNkCEoK9iGY6RWL1n7dNIu4",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2i_version13_9() {
-    hash_test(
-        Variant::Argon2i,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"password",
-        b"diffsalt",
-        "b0357cccfbef91f3860b0dba447b2348cbefecadaf990abfe9cc40726c521271",
-        "$argon2i$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ\
-               $sDV8zPvvkfOGCw26RHsjSMvv7K2vmQq/6cxAcmxSEnE",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version10_1() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "980ebd24a4e667f16346f9d4a78b175728783613e0cc6fb17c2ec884b16435df",
-        "$argon2id$v=16$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $mA69JKTmZ/FjRvnUp4sXVyh4NhPgzG+xfC7IhLFkNd8",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version10_2() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        2,
-        1048576,
-        1,
-        b"password",
-        b"somesalt",
-        "ce622fc2053acd224c06e7be122f9e9554b62b8a414b032056b46123422e32ab",
-        "$argon2id$v=16$m=1048576,t=2,p=1$c29tZXNhbHQ\
-               $zmIvwgU6zSJMBue+Ei+elVS2K4pBSwMgVrRhI0IuMqs",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version10_3() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        2,
-        262144,
-        1,
-        b"password",
-        b"somesalt",
-        "01cbafb58f2dc764adced1ab9a90fcb62f6ed8a066023b6ba0c204db6c9b90cd",
-        "$argon2id$v=16$m=262144,t=2,p=1$c29tZXNhbHQ\
-               $AcuvtY8tx2StztGrmpD8ti9u2KBmAjtroMIE22ybkM0",
-    );
-}
-
-#[test]
-fn test_argon2id_version10_4() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        2,
-        256,
-        1,
-        b"password",
-        b"somesalt",
-        "da070e576e50f2f38a3c897cbddc6c7fb4028e870971ff9eae7b4e1879295e6e",
-        "$argon2id$v=16$m=256,t=2,p=1$c29tZXNhbHQ\
-               $2gcOV25Q8vOKPIl8vdxsf7QCjocJcf+erntOGHkpXm4",
-    );
-}
-
-#[test]
-fn test_argon2id_version10_5() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        2,
-        256,
-        2,
-        b"password",
-        b"somesalt",
-        "f8aabb5315c63cddcdb3b4a021550928e525699da8fcbd1c2b0b1ccd35cc87a7",
-        "$argon2id$v=16$m=256,t=2,p=2$c29tZXNhbHQ\
-               $+Kq7UxXGPN3Ns7SgIVUJKOUlaZ2o/L0cKwsczTXMh6c",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version10_6() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        1,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "8e0f310407a989013a823defbd6cbae54d86b35d1ac16e4f88eb4645e1357956",
-        "$argon2id$v=16$m=65536,t=1,p=1$c29tZXNhbHQ\
-               $jg8xBAepiQE6gj3vvWy65U2Gs10awW5PiOtGReE1eVY",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version10_7() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        4,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "16653426e582143da6a0ff75daac9fa94c21ac2c221c96bd3645a5c15c2d962a",
-        "$argon2id$v=16$m=65536,t=4,p=1$c29tZXNhbHQ\
-               $FmU0JuWCFD2moP912qyfqUwhrCwiHJa9NkWlwVwtlio",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version10_8() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"differentpassword",
-        b"somesalt",
-        "75709d4c96a2c235696a77eefeecf33e64221f470b26177c19e5e27642612dbb",
-        "$argon2id$v=16$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $dXCdTJaiwjVpanfu/uzzPmQiH0cLJhd8GeXidkJhLbs",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version10_9() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version10,
-        2,
-        65536,
-        1,
-        b"password",
-        b"diffsalt",
-        "f0b57cfe03a9d78c4700e2fe802002343660a56b1b5d21ead788e6bb44ef48d3",
-        "$argon2id$v=16$m=65536,t=2,p=1$ZGlmZnNhbHQ\
-               $8LV8/gOp14xHAOL+gCACNDZgpWsbXSHq14jmu0TvSNM",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version13_1() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "09316115d5cf24ed5a15a31a3ba326e5cf32edc24702987c02b6566f61913cf7",
-        "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $CTFhFdXPJO1aFaMaO6Mm5c8y7cJHAph8ArZWb2GRPPc",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version13_2() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        2,
-        1048576,
-        1,
-        b"password",
-        b"somesalt",
-        "16a1cb8a061cf1f8b16fb195fe559fa6d1435e43dded2f4fb07293176be892fa",
-        "$argon2id$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ\
-               $FqHLigYc8fixb7GV/lWfptFDXkPd7S9PsHKTF2vokvo",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version13_3() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        2,
-        262144,
-        1,
-        b"password",
-        b"somesalt",
-        "78fe1ec91fb3aa5657d72e710854e4c3d9b9198c742f9616c2f085bed95b2e8c",
-        "$argon2id$v=19$m=262144,t=2,p=1$c29tZXNhbHQ\
-               $eP4eyR+zqlZX1y5xCFTkw9m5GYx0L5YWwvCFvtlbLow",
-    );
-}
-
-#[test]
-fn test_argon2id_version13_4() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        2,
-        256,
-        1,
-        b"password",
-        b"somesalt",
-        "9dfeb910e80bad0311fee20f9c0e2b12c17987b4cac90c2ef54d5b3021c68bfe",
-        "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ\
-               $nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4",
-    );
-}
-
-#[test]
-fn test_argon2id_version13_5() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        2,
-        256,
-        2,
-        b"password",
-        b"somesalt",
-        "6d093c501fd5999645e0ea3bf620d7b8be7fd2db59c20d9fff9539da2bf57037",
-        "$argon2id$v=19$m=256,t=2,p=2$c29tZXNhbHQ\
-               $bQk8UB/VmZZF4Oo79iDXuL5/0ttZwg2f/5U52iv1cDc",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version13_6() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        1,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "f6a5adc1ba723dddef9b5ac1d464e180fcd9dffc9d1cbf76cca2fed795d9ca98",
-        "$argon2id$v=19$m=65536,t=1,p=1$c29tZXNhbHQ\
-               $9qWtwbpyPd3vm1rB1GThgPzZ3/ydHL92zKL+15XZypg",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version13_7() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        4,
-        65536,
-        1,
-        b"password",
-        b"somesalt",
-        "9025d48e68ef7395cca9079da4c4ec3affb3c8911fe4f86d1a2520856f63172c",
-        "$argon2id$v=19$m=65536,t=4,p=1$c29tZXNhbHQ\
-               $kCXUjmjvc5XMqQedpMTsOv+zyJEf5PhtGiUghW9jFyw",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version13_8() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"differentpassword",
-        b"somesalt",
-        "0b84d652cf6b0c4beaef0dfe278ba6a80df6696281d7e0d2891b817d8c458fde",
-        "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-               $C4TWUs9rDEvq7w3+J4umqA32aWKB1+DSiRuBfYxFj94",
-    );
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_argon2id_version13_9() {
-    hash_test(
-        Variant::Argon2id,
-        Version::Version13,
-        2,
-        65536,
-        1,
-        b"password",
-        b"diffsalt",
-        "bdf32b05ccc42eb15d58fd19b1f856b113da1e9a5874fdcc544308565aa8141c",
-        "$argon2id$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ\
-               $vfMrBczELrFdWP0ZsfhWsRPaHppYdP3MVEMIVlqoFBw",
-    );
-}
-
-#[test]
-fn test_verify_encoded_with_missing_dollar_before_salt_version10() {
-    let encoded = "$argon2i$m=65536,t=2,p=1c29tZXNhbHQ\
-                   $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
-    let password = b"password";
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Err(Error::DecodingFail));
-}
-
-#[test]
-fn test_verify_encoded_with_missing_dollar_before_salt_version13() {
-    let encoded = "$argon2i$v=19$m=65536,t=2,p=1c29tZXNhbHQ\
-                   $wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA";
-    let password = b"password";
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Err(Error::DecodingFail));
-}
-
-#[test]
-fn test_verify_encoded_with_missing_dollar_before_hash_version10() {
-    let encoded = "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
-                   9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
-    let password = b"password";
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Err(Error::DecodingFail));
-}
-
-#[test]
-fn test_verify_encoded_with_missing_dollar_before_hash_version13() {
-    let encoded = "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-                   wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA";
-    let password = b"password";
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Err(Error::DecodingFail));
-}
-
-#[test]
-fn test_verify_encoded_with_too_short_salt_version10() {
-    let encoded = "$argon2i$m=65536,t=2,p=1$\
-                   $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
-    let password = b"password";
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Err(Error::SaltTooShort));
-}
-
-#[test]
-fn test_verify_encoded_with_too_short_salt_version13() {
-    let encoded = "$argon2i$v=19$m=65536,t=2,p=1$\
-                   $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
-    let password = b"password";
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Err(Error::SaltTooShort));
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_verify_encoded_with_wrong_password_version10() {
-    let encoded = "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
-                   $b2G3seW+uPzerwQQC+/E1K50CLLO7YXy0JRcaTuswRo";
-    let password = b"password"; // should be passwore
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Ok(false));
-}
-
-#[cfg(not(debug_assertions))]
-#[test]
-fn test_verify_encoded_with_wrong_password_version13() {
-    let encoded = "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
-                   $8iIuixkI73Js3G1uMbezQXD0b8LG4SXGsOwoQkdAQIM";
-    let password = b"password"; // should be passwore
-    let res = argon2::verify_encoded(encoded, password);
-    assert_eq!(res, Ok(false));
-}
-
-#[test]
-fn test_encoded_len_returns_correct_length() {
-    assert_eq!(argon2::encoded_len(Variant::Argon2d, 256, 1, 1, 8, 32), 83);
-    assert_eq!(argon2::encoded_len(Variant::Argon2i, 4096, 10, 10, 8, 32), 86);
-    assert_eq!(argon2::encoded_len(Variant::Argon2id, 65536, 100, 10, 8, 32), 89);
-}
-
-#[test]
-fn test_hash_raw_with_not_enough_memory() {
-    let pwd = b"password";
-    let salt = b"diffsalt";
-    let config = Config {
-        variant: Variant::Argon2i,
-        version: Version::Version13,
-        mem_cost: 2,
-        time_cost: 2,
-        lanes: 1,
-        thread_mode: ThreadMode::Sequential,
-        secret: &[],
-        ad: &[],
-        hash_length: 32,
-    };
-    let res = argon2::hash_raw(pwd, salt, &config);
-    assert_eq!(res, Err(Error::MemoryTooLittle));
-}
-
-#[test]
-fn test_hash_raw_with_too_short_salt() {
-    let pwd = b"password";
-    let salt = b"s";
-    let config = Config {
-        variant: Variant::Argon2i,
-        version: Version::Version13,
-        mem_cost: 2048,
-        time_cost: 2,
-        lanes: 1,
-        thread_mode: ThreadMode::Sequential,
-        secret: &[],
-        ad: &[],
-        hash_length: 32,
-    };
-    let res = argon2::hash_raw(pwd, salt, &config);
-    assert_eq!(res, Err(Error::SaltTooShort));
-}
-
-fn hash_test(
-    var: Variant,
-    ver: Version,
-    t: u32,
-    m: u32,
-    p: u32,
-    pwd: &[u8],
-    salt: &[u8],
-    hex: &str,
-    enc: &str,
-) {
-    let config = Config {
-        variant: var,
-        version: ver,
-        mem_cost: m,
-        time_cost: t,
-        lanes: p,
-        thread_mode: ThreadMode::from_threads(p),
-        secret: &[],
-        ad: &[],
-        hash_length: 32,
-    };
-    let hash = argon2::hash_raw(pwd, salt, &config).unwrap();
-    let mut hex_str = String::new();
-    let res = hash.write_hex(&mut hex_str);
-    assert_eq!(res, Ok(()));
-    assert_eq!(hex_str.as_str(), hex);
-
-    let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
-    let result = argon2::verify_encoded(encoded.as_str(), pwd).unwrap();
-    assert!(result);
-
-    let result = argon2::verify_encoded(enc, pwd).unwrap();
-    assert!(result);
-}
diff --git a/vendor/rustc-ap-rustc_arena/.cargo-checksum.json b/vendor/rustc-ap-rustc_arena/.cargo-checksum.json
deleted file mode 100644
index f9dabad911..0000000000
--- a/vendor/rustc-ap-rustc_arena/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"fed14cdbf1359fec1cb48c69aa8dd92b1d156a878ad91b01d41d807e6fc49c41","src/lib.rs":"7f45897f9758143205488b536dd9518da7d1a9101cab8d69f77a80bc32c19d93","src/tests.rs":"73ea19627c37e54ee3e3728e7e9179db93a55ad9232a6e32a89db8e0af4c3e37"},"package":"93575affa286089b92c8208aea4e60fe9fdd251a619a09b566d6e4e2cc123212"}
\ No newline at end of file
diff --git a/vendor/rustc-ap-rustc_arena/Cargo.toml b/vendor/rustc-ap-rustc_arena/Cargo.toml
deleted file mode 100644
index f731afc5e7..0000000000
--- a/vendor/rustc-ap-rustc_arena/Cargo.toml
+++ /dev/null
@@ -1,23 +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 = "rustc-ap-rustc_arena"
-version = "705.0.0"
-authors = ["The Rust Project Developers"]
-description = "Automatically published version of the package `rustc_arena` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n            "
-license = "MIT / Apache-2.0"
-repository = "https://github.com/rust-lang/rust"
-[dependencies.smallvec]
-version = "1.0"
-features = ["union", "may_dangle"]
diff --git a/vendor/rustc-ap-rustc_arena/src/lib.rs b/vendor/rustc-ap-rustc_arena/src/lib.rs
deleted file mode 100644
index 651f4c6fab..0000000000
--- a/vendor/rustc-ap-rustc_arena/src/lib.rs
+++ /dev/null
@@ -1,745 +0,0 @@
-//! The arena, a fast but limited type of allocator.
-//!
-//! Arenas are a type of allocator that destroy the objects within, all at
-//! once, once the arena itself is destroyed. They do not support deallocation
-//! of individual objects while the arena itself is still alive. The benefit
-//! of an arena is very fast allocation; just a pointer bump.
-//!
-//! This crate implements several kinds of arena.
-
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
-    test(no_crate_inject, attr(deny(warnings)))
-)]
-#![feature(dropck_eyepatch)]
-#![feature(new_uninit)]
-#![feature(maybe_uninit_slice)]
-#![cfg_attr(bootstrap, feature(min_const_generics))]
-#![feature(min_specialization)]
-#![cfg_attr(test, feature(test))]
-
-use smallvec::SmallVec;
-
-use std::alloc::Layout;
-use std::cell::{Cell, RefCell};
-use std::cmp;
-use std::marker::{PhantomData, Send};
-use std::mem::{self, MaybeUninit};
-use std::ptr;
-use std::slice;
-
-#[inline(never)]
-#[cold]
-fn cold_path R, R>(f: F) -> R {
-    f()
-}
-
-/// An arena that can hold objects of only one type.
-pub struct TypedArena {
-    /// A pointer to the next object to be allocated.
-    ptr: Cell<*mut T>,
-
-    /// A pointer to the end of the allocated area. When this pointer is
-    /// reached, a new chunk is allocated.
-    end: Cell<*mut T>,
-
-    /// A vector of arena chunks.
-    chunks: RefCell>>,
-
-    /// Marker indicating that dropping the arena causes its owned
-    /// instances of `T` to be dropped.
-    _own: PhantomData,
-}
-
-struct TypedArenaChunk {
-    /// The raw storage for the arena chunk.
-    storage: Box<[MaybeUninit]>,
-    /// The number of valid entries in the chunk.
-    entries: usize,
-}
-
-impl TypedArenaChunk {
-    #[inline]
-    unsafe fn new(capacity: usize) -> TypedArenaChunk {
-        TypedArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
-    }
-
-    /// Destroys this arena chunk.
-    #[inline]
-    unsafe fn destroy(&mut self, len: usize) {
-        // The branch on needs_drop() is an -O1 performance optimization.
-        // Without the branch, dropping TypedArena takes linear time.
-        if mem::needs_drop::() {
-            ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut self.storage[..len]));
-        }
-    }
-
-    // Returns a pointer to the first allocated object.
-    #[inline]
-    fn start(&mut self) -> *mut T {
-        MaybeUninit::slice_as_mut_ptr(&mut self.storage)
-    }
-
-    // Returns a pointer to the end of the allocated space.
-    #[inline]
-    fn end(&mut self) -> *mut T {
-        unsafe {
-            if mem::size_of::() == 0 {
-                // A pointer as large as possible for zero-sized elements.
-                !0 as *mut T
-            } else {
-                self.start().add(self.storage.len())
-            }
-        }
-    }
-}
-
-// The arenas start with PAGE-sized chunks, and then each new chunk is twice as
-// big as its predecessor, up until we reach HUGE_PAGE-sized chunks, whereupon
-// we stop growing. This scales well, from arenas that are barely used up to
-// arenas that are used for 100s of MiBs. Note also that the chosen sizes match
-// the usual sizes of pages and huge pages on Linux.
-const PAGE: usize = 4096;
-const HUGE_PAGE: usize = 2 * 1024 * 1024;
-
-impl Default for TypedArena {
-    /// Creates a new `TypedArena`.
-    fn default() -> TypedArena {
-        TypedArena {
-            // We set both `ptr` and `end` to 0 so that the first call to
-            // alloc() will trigger a grow().
-            ptr: Cell::new(ptr::null_mut()),
-            end: Cell::new(ptr::null_mut()),
-            chunks: RefCell::new(vec![]),
-            _own: PhantomData,
-        }
-    }
-}
-
-trait IterExt {
-    fn alloc_from_iter(self, arena: &TypedArena) -> &mut [T];
-}
-
-impl IterExt for I
-where
-    I: IntoIterator,
-{
-    #[inline]
-    default fn alloc_from_iter(self, arena: &TypedArena) -> &mut [T] {
-        let vec: SmallVec<[_; 8]> = self.into_iter().collect();
-        vec.alloc_from_iter(arena)
-    }
-}
-
-impl IterExt for std::array::IntoIter {
-    #[inline]
-    fn alloc_from_iter(self, arena: &TypedArena) -> &mut [T] {
-        let len = self.len();
-        if len == 0 {
-            return &mut [];
-        }
-        // Move the content to the arena by copying and then forgetting it
-        unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
-            self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            mem::forget(self);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
-    }
-}
-
-impl IterExt for Vec {
-    #[inline]
-    fn alloc_from_iter(mut self, arena: &TypedArena) -> &mut [T] {
-        let len = self.len();
-        if len == 0 {
-            return &mut [];
-        }
-        // Move the content to the arena by copying and then forgetting it
-        unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
-            self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            self.set_len(0);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
-    }
-}
-
-impl IterExt for SmallVec {
-    #[inline]
-    fn alloc_from_iter(mut self, arena: &TypedArena) -> &mut [A::Item] {
-        let len = self.len();
-        if len == 0 {
-            return &mut [];
-        }
-        // Move the content to the arena by copying and then forgetting it
-        unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
-            self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            self.set_len(0);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
-    }
-}
-
-impl TypedArena {
-    /// Allocates an object in the `TypedArena`, returning a reference to it.
-    #[inline]
-    pub fn alloc(&self, object: T) -> &mut T {
-        if self.ptr == self.end {
-            self.grow(1)
-        }
-
-        unsafe {
-            if mem::size_of::() == 0 {
-                self.ptr.set((self.ptr.get() as *mut u8).wrapping_offset(1) as *mut T);
-                let ptr = mem::align_of::() as *mut T;
-                // Don't drop the object. This `write` is equivalent to `forget`.
-                ptr::write(ptr, object);
-                &mut *ptr
-            } else {
-                let ptr = self.ptr.get();
-                // Advance the pointer.
-                self.ptr.set(self.ptr.get().offset(1));
-                // Write into uninitialized memory.
-                ptr::write(ptr, object);
-                &mut *ptr
-            }
-        }
-    }
-
-    #[inline]
-    fn can_allocate(&self, additional: usize) -> bool {
-        let available_bytes = self.end.get() as usize - self.ptr.get() as usize;
-        let additional_bytes = additional.checked_mul(mem::size_of::()).unwrap();
-        available_bytes >= additional_bytes
-    }
-
-    /// Ensures there's enough space in the current chunk to fit `len` objects.
-    #[inline]
-    fn ensure_capacity(&self, additional: usize) {
-        if !self.can_allocate(additional) {
-            self.grow(additional);
-            debug_assert!(self.can_allocate(additional));
-        }
-    }
-
-    #[inline]
-    unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T {
-        assert!(mem::size_of::() != 0);
-        assert!(len != 0);
-
-        self.ensure_capacity(len);
-
-        let start_ptr = self.ptr.get();
-        self.ptr.set(start_ptr.add(len));
-        start_ptr
-    }
-
-    /// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable
-    /// reference to it. Will panic if passed a zero-sized types.
-    ///
-    /// Panics:
-    ///
-    ///  - Zero-sized types
-    ///  - Zero-length slices
-    #[inline]
-    pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
-    where
-        T: Copy,
-    {
-        unsafe {
-            let len = slice.len();
-            let start_ptr = self.alloc_raw_slice(len);
-            slice.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
-    }
-
-    #[inline]
-    pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] {
-        assert!(mem::size_of::() != 0);
-        iter.alloc_from_iter(self)
-    }
-
-    /// Grows the arena.
-    #[inline(never)]
-    #[cold]
-    fn grow(&self, additional: usize) {
-        unsafe {
-            // We need the element size to convert chunk sizes (ranging from
-            // PAGE to HUGE_PAGE bytes) to element counts.
-            let elem_size = cmp::max(1, mem::size_of::());
-            let mut chunks = self.chunks.borrow_mut();
-            let mut new_cap;
-            if let Some(last_chunk) = chunks.last_mut() {
-                // If a type is `!needs_drop`, we don't need to keep track of how many elements
-                // the chunk stores - the field will be ignored anyway.
-                if mem::needs_drop::() {
-                    let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
-                    last_chunk.entries = used_bytes / mem::size_of::();
-                }
-
-                // If the previous chunk's len is less than HUGE_PAGE
-                // bytes, then this chunk will be least double the previous
-                // chunk's size.
-                new_cap = last_chunk.storage.len().min(HUGE_PAGE / elem_size / 2);
-                new_cap *= 2;
-            } else {
-                new_cap = PAGE / elem_size;
-            }
-            // Also ensure that this chunk can fit `additional`.
-            new_cap = cmp::max(additional, new_cap);
-
-            let mut chunk = TypedArenaChunk::::new(new_cap);
-            self.ptr.set(chunk.start());
-            self.end.set(chunk.end());
-            chunks.push(chunk);
-        }
-    }
-
-    /// Clears the arena. Deallocates all but the longest chunk which may be reused.
-    pub fn clear(&mut self) {
-        unsafe {
-            // Clear the last chunk, which is partially filled.
-            let mut chunks_borrow = self.chunks.borrow_mut();
-            if let Some(mut last_chunk) = chunks_borrow.last_mut() {
-                self.clear_last_chunk(&mut last_chunk);
-                let len = chunks_borrow.len();
-                // If `T` is ZST, code below has no effect.
-                for mut chunk in chunks_borrow.drain(..len - 1) {
-                    chunk.destroy(chunk.entries);
-                }
-            }
-        }
-    }
-
-    // Drops the contents of the last chunk. The last chunk is partially empty, unlike all other
-    // chunks.
-    fn clear_last_chunk(&self, last_chunk: &mut TypedArenaChunk) {
-        // Determine how much was filled.
-        let start = last_chunk.start() as usize;
-        // We obtain the value of the pointer to the first uninitialized element.
-        let end = self.ptr.get() as usize;
-        // We then calculate the number of elements to be dropped in the last chunk,
-        // which is the filled area's length.
-        let diff = if mem::size_of::() == 0 {
-            // `T` is ZST. It can't have a drop flag, so the value here doesn't matter. We get
-            // the number of zero-sized values in the last and only chunk, just out of caution.
-            // Recall that `end` was incremented for each allocated value.
-            end - start
-        } else {
-            (end - start) / mem::size_of::()
-        };
-        // Pass that to the `destroy` method.
-        unsafe {
-            last_chunk.destroy(diff);
-        }
-        // Reset the chunk.
-        self.ptr.set(last_chunk.start());
-    }
-}
-
-unsafe impl<#[may_dangle] T> Drop for TypedArena {
-    fn drop(&mut self) {
-        unsafe {
-            // Determine how much was filled.
-            let mut chunks_borrow = self.chunks.borrow_mut();
-            if let Some(mut last_chunk) = chunks_borrow.pop() {
-                // Drop the contents of the last chunk.
-                self.clear_last_chunk(&mut last_chunk);
-                // The last chunk will be dropped. Destroy all other chunks.
-                for chunk in chunks_borrow.iter_mut() {
-                    chunk.destroy(chunk.entries);
-                }
-            }
-            // Box handles deallocation of `last_chunk` and `self.chunks`.
-        }
-    }
-}
-
-unsafe impl Send for TypedArena {}
-
-pub struct DroplessArena {
-    /// A pointer to the start of the free space.
-    start: Cell<*mut u8>,
-
-    /// A pointer to the end of free space.
-    ///
-    /// The allocation proceeds from the end of the chunk towards the start.
-    /// When this pointer crosses the start pointer, a new chunk is allocated.
-    end: Cell<*mut u8>,
-
-    /// A vector of arena chunks.
-    chunks: RefCell>>,
-}
-
-unsafe impl Send for DroplessArena {}
-
-impl Default for DroplessArena {
-    #[inline]
-    fn default() -> DroplessArena {
-        DroplessArena {
-            start: Cell::new(ptr::null_mut()),
-            end: Cell::new(ptr::null_mut()),
-            chunks: Default::default(),
-        }
-    }
-}
-
-impl DroplessArena {
-    #[inline(never)]
-    #[cold]
-    fn grow(&self, additional: usize) {
-        unsafe {
-            let mut chunks = self.chunks.borrow_mut();
-            let mut new_cap;
-            if let Some(last_chunk) = chunks.last_mut() {
-                // There is no need to update `last_chunk.entries` because that
-                // field isn't used by `DroplessArena`.
-
-                // If the previous chunk's len is less than HUGE_PAGE
-                // bytes, then this chunk will be least double the previous
-                // chunk's size.
-                new_cap = last_chunk.storage.len().min(HUGE_PAGE / 2);
-                new_cap *= 2;
-            } else {
-                new_cap = PAGE;
-            }
-            // Also ensure that this chunk can fit `additional`.
-            new_cap = cmp::max(additional, new_cap);
-
-            let mut chunk = TypedArenaChunk::::new(new_cap);
-            self.start.set(chunk.start());
-            self.end.set(chunk.end());
-            chunks.push(chunk);
-        }
-    }
-
-    /// Allocates a byte slice with specified layout from the current memory
-    /// chunk. Returns `None` if there is no free space left to satisfy the
-    /// request.
-    #[inline]
-    fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> {
-        let start = self.start.get() as usize;
-        let end = self.end.get() as usize;
-
-        let align = layout.align();
-        let bytes = layout.size();
-
-        let new_end = end.checked_sub(bytes)? & !(align - 1);
-        if start <= new_end {
-            let new_end = new_end as *mut u8;
-            self.end.set(new_end);
-            Some(new_end)
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
-        assert!(layout.size() != 0);
-        loop {
-            if let Some(a) = self.alloc_raw_without_grow(layout) {
-                break a;
-            }
-            // No free space left. Allocate a new chunk to satisfy the request.
-            // On failure the grow will panic or abort.
-            self.grow(layout.size());
-        }
-    }
-
-    #[inline]
-    pub fn alloc(&self, object: T) -> &mut T {
-        assert!(!mem::needs_drop::());
-
-        let mem = self.alloc_raw(Layout::for_value::(&object)) as *mut T;
-
-        unsafe {
-            // Write into uninitialized memory.
-            ptr::write(mem, object);
-            &mut *mem
-        }
-    }
-
-    /// Allocates a slice of objects that are copied into the `DroplessArena`, returning a mutable
-    /// reference to it. Will panic if passed a zero-sized type.
-    ///
-    /// Panics:
-    ///
-    ///  - Zero-sized types
-    ///  - Zero-length slices
-    #[inline]
-    pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
-    where
-        T: Copy,
-    {
-        assert!(!mem::needs_drop::());
-        assert!(mem::size_of::() != 0);
-        assert!(!slice.is_empty());
-
-        let mem = self.alloc_raw(Layout::for_value::<[T]>(slice)) as *mut T;
-
-        unsafe {
-            mem.copy_from_nonoverlapping(slice.as_ptr(), slice.len());
-            slice::from_raw_parts_mut(mem, slice.len())
-        }
-    }
-
-    #[inline]
-    unsafe fn write_from_iter>(
-        &self,
-        mut iter: I,
-        len: usize,
-        mem: *mut T,
-    ) -> &mut [T] {
-        let mut i = 0;
-        // Use a manual loop since LLVM manages to optimize it better for
-        // slice iterators
-        loop {
-            let value = iter.next();
-            if i >= len || value.is_none() {
-                // We only return as many items as the iterator gave us, even
-                // though it was supposed to give us `len`
-                return slice::from_raw_parts_mut(mem, i);
-            }
-            ptr::write(mem.add(i), value.unwrap());
-            i += 1;
-        }
-    }
-
-    #[inline]
-    pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] {
-        let iter = iter.into_iter();
-        assert!(mem::size_of::() != 0);
-        assert!(!mem::needs_drop::());
-
-        let size_hint = iter.size_hint();
-
-        match size_hint {
-            (min, Some(max)) if min == max => {
-                // We know the exact number of elements the iterator will produce here
-                let len = min;
-
-                if len == 0 {
-                    return &mut [];
-                }
-
-                let mem = self.alloc_raw(Layout::array::(len).unwrap()) as *mut T;
-                unsafe { self.write_from_iter(iter, len, mem) }
-            }
-            (_, _) => {
-                cold_path(move || -> &mut [T] {
-                    let mut vec: SmallVec<[_; 8]> = iter.collect();
-                    if vec.is_empty() {
-                        return &mut [];
-                    }
-                    // Move the content to the arena by copying it and then forgetting
-                    // the content of the SmallVec
-                    unsafe {
-                        let len = vec.len();
-                        let start_ptr =
-                            self.alloc_raw(Layout::for_value::<[T]>(vec.as_slice())) as *mut T;
-                        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-                        vec.set_len(0);
-                        slice::from_raw_parts_mut(start_ptr, len)
-                    }
-                })
-            }
-        }
-    }
-}
-
-/// Calls the destructor for an object when dropped.
-struct DropType {
-    drop_fn: unsafe fn(*mut u8),
-    obj: *mut u8,
-}
-
-unsafe fn drop_for_type(to_drop: *mut u8) {
-    std::ptr::drop_in_place(to_drop as *mut T)
-}
-
-impl Drop for DropType {
-    fn drop(&mut self) {
-        unsafe { (self.drop_fn)(self.obj) }
-    }
-}
-
-/// An arena which can be used to allocate any type.
-/// Allocating in this arena is unsafe since the type system
-/// doesn't know which types it contains. In order to
-/// allocate safely, you must store a PhantomData
-/// alongside this arena for each type T you allocate.
-#[derive(Default)]
-pub struct DropArena {
-    /// A list of destructors to run when the arena drops.
-    /// Ordered so `destructors` gets dropped before the arena
-    /// since its destructor can reference memory in the arena.
-    destructors: RefCell>,
-    arena: DroplessArena,
-}
-
-impl DropArena {
-    #[inline]
-    pub unsafe fn alloc(&self, object: T) -> &mut T {
-        let mem = self.arena.alloc_raw(Layout::new::()) as *mut T;
-        // Write into uninitialized memory.
-        ptr::write(mem, object);
-        let result = &mut *mem;
-        // Record the destructor after doing the allocation as that may panic
-        // and would cause `object`'s destructor to run twice if it was recorded before
-        self.destructors
-            .borrow_mut()
-            .push(DropType { drop_fn: drop_for_type::, obj: result as *mut T as *mut u8 });
-        result
-    }
-
-    #[inline]
-    pub unsafe fn alloc_from_iter>(&self, iter: I) -> &mut [T] {
-        let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
-        if vec.is_empty() {
-            return &mut [];
-        }
-        let len = vec.len();
-
-        let start_ptr = self.arena.alloc_raw(Layout::array::(len).unwrap()) as *mut T;
-
-        let mut destructors = self.destructors.borrow_mut();
-        // Reserve space for the destructors so we can't panic while adding them
-        destructors.reserve(len);
-
-        // Move the content to the arena by copying it and then forgetting
-        // the content of the SmallVec
-        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-        mem::forget(vec.drain(..));
-
-        // Record the destructors after doing the allocation as that may panic
-        // and would cause `object`'s destructor to run twice if it was recorded before
-        for i in 0..len {
-            destructors
-                .push(DropType { drop_fn: drop_for_type::, obj: start_ptr.add(i) as *mut u8 });
-        }
-
-        slice::from_raw_parts_mut(start_ptr, len)
-    }
-}
-
-#[macro_export]
-macro_rules! arena_for_type {
-    ([][$ty:ty]) => {
-        $crate::TypedArena<$ty>
-    };
-    ([few $(, $attrs:ident)*][$ty:ty]) => {
-        ::std::marker::PhantomData<$ty>
-    };
-    ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
-        $crate::arena_for_type!([$($attrs),*]$args)
-    };
-}
-
-#[macro_export]
-macro_rules! which_arena_for_type {
-    ([][$arena:expr]) => {
-        ::std::option::Option::Some($arena)
-    };
-    ([few$(, $attrs:ident)*][$arena:expr]) => {
-        ::std::option::Option::None
-    };
-    ([$ignore:ident$(, $attrs:ident)*]$args:tt) => {
-        $crate::which_arena_for_type!([$($attrs),*]$args)
-    };
-}
-
-#[macro_export]
-macro_rules! declare_arena {
-    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
-        #[derive(Default)]
-        pub struct Arena<$tcx> {
-            pub dropless: $crate::DroplessArena,
-            drop: $crate::DropArena,
-            $($name: $crate::arena_for_type!($a[$ty]),)*
-        }
-
-        pub trait ArenaAllocatable<'tcx, T = Self>: Sized {
-            fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self;
-            fn allocate_from_iter<'a>(
-                arena: &'a Arena<'tcx>,
-                iter: impl ::std::iter::IntoIterator,
-            ) -> &'a mut [Self];
-        }
-
-        impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
-            #[inline]
-            fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
-                arena.dropless.alloc(self)
-            }
-            #[inline]
-            fn allocate_from_iter<'a>(
-                arena: &'a Arena<'tcx>,
-                iter: impl ::std::iter::IntoIterator,
-            ) -> &'a mut [Self] {
-                arena.dropless.alloc_from_iter(iter)
-            }
-
-        }
-        $(
-            impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty {
-                #[inline]
-                fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self {
-                    if !::std::mem::needs_drop::() {
-                        return arena.dropless.alloc(self);
-                    }
-                    match $crate::which_arena_for_type!($a[&arena.$name]) {
-                        ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => {
-                            ty_arena.alloc(self)
-                        }
-                        ::std::option::Option::None => unsafe { arena.drop.alloc(self) },
-                    }
-                }
-
-                #[inline]
-                fn allocate_from_iter<'a>(
-                    arena: &'a Arena<$tcx>,
-                    iter: impl ::std::iter::IntoIterator,
-                ) -> &'a mut [Self] {
-                    if !::std::mem::needs_drop::() {
-                        return arena.dropless.alloc_from_iter(iter);
-                    }
-                    match $crate::which_arena_for_type!($a[&arena.$name]) {
-                        ::std::option::Option::<&$crate::TypedArena>::Some(ty_arena) => {
-                            ty_arena.alloc_from_iter(iter)
-                        }
-                        ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) },
-                    }
-                }
-            }
-        )*
-
-        impl<'tcx> Arena<'tcx> {
-            #[inline]
-            pub fn alloc, U>(&self, value: T) -> &mut T {
-                value.allocate_on(self)
-            }
-
-            #[inline]
-            pub fn alloc_slice(&self, value: &[T]) -> &mut [T] {
-                if value.is_empty() {
-                    return &mut [];
-                }
-                self.dropless.alloc_slice(value)
-            }
-
-            pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>(
-                &'a self,
-                iter: impl ::std::iter::IntoIterator,
-            ) -> &'a mut [T] {
-                T::allocate_from_iter(self, iter)
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests;
diff --git a/vendor/rustc-ap-rustc_arena/src/tests.rs b/vendor/rustc-ap-rustc_arena/src/tests.rs
deleted file mode 100644
index e8a1f2db1a..0000000000
--- a/vendor/rustc-ap-rustc_arena/src/tests.rs
+++ /dev/null
@@ -1,214 +0,0 @@
-extern crate test;
-use super::TypedArena;
-use std::cell::Cell;
-use test::Bencher;
-
-#[allow(dead_code)]
-#[derive(Debug, Eq, PartialEq)]
-struct Point {
-    x: i32,
-    y: i32,
-    z: i32,
-}
-
-#[test]
-pub fn test_unused() {
-    let arena: TypedArena = TypedArena::default();
-    assert!(arena.chunks.borrow().is_empty());
-}
-
-#[test]
-fn test_arena_alloc_nested() {
-    struct Inner {
-        value: u8,
-    }
-    struct Outer<'a> {
-        inner: &'a Inner,
-    }
-    enum EI<'e> {
-        I(Inner),
-        O(Outer<'e>),
-    }
-
-    struct Wrap<'a>(TypedArena>);
-
-    impl<'a> Wrap<'a> {
-        fn alloc_inner Inner>(&self, f: F) -> &Inner {
-            let r: &EI<'_> = self.0.alloc(EI::I(f()));
-            if let &EI::I(ref i) = r {
-                i
-            } else {
-                panic!("mismatch");
-            }
-        }
-        fn alloc_outer Outer<'a>>(&self, f: F) -> &Outer<'_> {
-            let r: &EI<'_> = self.0.alloc(EI::O(f()));
-            if let &EI::O(ref o) = r {
-                o
-            } else {
-                panic!("mismatch");
-            }
-        }
-    }
-
-    let arena = Wrap(TypedArena::default());
-
-    let result = arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
-
-    assert_eq!(result.inner.value, 10);
-}
-
-#[test]
-pub fn test_copy() {
-    let arena = TypedArena::default();
-    for _ in 0..100000 {
-        arena.alloc(Point { x: 1, y: 2, z: 3 });
-    }
-}
-
-#[bench]
-pub fn bench_copy(b: &mut Bencher) {
-    let arena = TypedArena::default();
-    b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 }))
-}
-
-#[bench]
-pub fn bench_copy_nonarena(b: &mut Bencher) {
-    b.iter(|| {
-        let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 });
-    })
-}
-
-#[allow(dead_code)]
-struct Noncopy {
-    string: String,
-    array: Vec,
-}
-
-#[test]
-pub fn test_noncopy() {
-    let arena = TypedArena::default();
-    for _ in 0..100000 {
-        arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
-    }
-}
-
-#[test]
-pub fn test_typed_arena_zero_sized() {
-    let arena = TypedArena::default();
-    for _ in 0..100000 {
-        arena.alloc(());
-    }
-}
-
-#[test]
-pub fn test_typed_arena_clear() {
-    let mut arena = TypedArena::default();
-    for _ in 0..10 {
-        arena.clear();
-        for _ in 0..10000 {
-            arena.alloc(Point { x: 1, y: 2, z: 3 });
-        }
-    }
-}
-
-#[bench]
-pub fn bench_typed_arena_clear(b: &mut Bencher) {
-    let mut arena = TypedArena::default();
-    b.iter(|| {
-        arena.alloc(Point { x: 1, y: 2, z: 3 });
-        arena.clear();
-    })
-}
-
-#[bench]
-pub fn bench_typed_arena_clear_100(b: &mut Bencher) {
-    let mut arena = TypedArena::default();
-    b.iter(|| {
-        for _ in 0..100 {
-            arena.alloc(Point { x: 1, y: 2, z: 3 });
-        }
-        arena.clear();
-    })
-}
-
-// Drop tests
-
-struct DropCounter<'a> {
-    count: &'a Cell,
-}
-
-impl Drop for DropCounter<'_> {
-    fn drop(&mut self) {
-        self.count.set(self.count.get() + 1);
-    }
-}
-
-#[test]
-fn test_typed_arena_drop_count() {
-    let counter = Cell::new(0);
-    {
-        let arena: TypedArena> = TypedArena::default();
-        for _ in 0..100 {
-            // Allocate something with drop glue to make sure it doesn't leak.
-            arena.alloc(DropCounter { count: &counter });
-        }
-    };
-    assert_eq!(counter.get(), 100);
-}
-
-#[test]
-fn test_typed_arena_drop_on_clear() {
-    let counter = Cell::new(0);
-    let mut arena: TypedArena> = TypedArena::default();
-    for i in 0..10 {
-        for _ in 0..100 {
-            // Allocate something with drop glue to make sure it doesn't leak.
-            arena.alloc(DropCounter { count: &counter });
-        }
-        arena.clear();
-        assert_eq!(counter.get(), i * 100 + 100);
-    }
-}
-
-thread_local! {
-    static DROP_COUNTER: Cell = Cell::new(0)
-}
-
-struct SmallDroppable;
-
-impl Drop for SmallDroppable {
-    fn drop(&mut self) {
-        DROP_COUNTER.with(|c| c.set(c.get() + 1));
-    }
-}
-
-#[test]
-fn test_typed_arena_drop_small_count() {
-    DROP_COUNTER.with(|c| c.set(0));
-    {
-        let arena: TypedArena = TypedArena::default();
-        for _ in 0..100 {
-            // Allocate something with drop glue to make sure it doesn't leak.
-            arena.alloc(SmallDroppable);
-        }
-        // dropping
-    };
-    assert_eq!(DROP_COUNTER.with(|c| c.get()), 100);
-}
-
-#[bench]
-pub fn bench_noncopy(b: &mut Bencher) {
-    let arena = TypedArena::default();
-    b.iter(|| {
-        arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] })
-    })
-}
-
-#[bench]
-pub fn bench_noncopy_nonarena(b: &mut Bencher) {
-    b.iter(|| {
-        let _: Box<_> =
-            Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
-    })
-}
diff --git a/vendor/rustc-ap-rustc_ast/.cargo-checksum.json b/vendor/rustc-ap-rustc_ast/.cargo-checksum.json
deleted file mode 100644
index 454572a0e5..0000000000
--- a/vendor/rustc-ap-rustc_ast/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"1cc6660aa271f9d9dfe77c85a9ba49bf33658d4edbbc212a85947014018cba2e","README.md":"9f9896a40edac79b0d51e0e67d7f6f6c0d189a57d251cc06cea382d2fdd328ab","src/ast.rs":"c38e93bd820b306208ca40adf9b158d5083f85e84c86eb3662ec74d2b2738245","src/ast/tests.rs":"3636dac900209f66e3481b0675ce855d6db9bb7c185c08872fab52fb1214dc31","src/attr/mod.rs":"d7ba50485d4b6fe31e3d47b43da0b4ac699a2863961883d6e9d6a38ef8fce2fb","src/crate_disambiguator.rs":"3b5f38c0e9bb54e65cc4f85ef25f8c301c42e57c57f9b822776fe81b4e9e7560","src/entry.rs":"1cbb6069418aedd87c97e9b472cdef75bdd7bbae445ecc4e33126007fe9309a2","src/expand/allocator.rs":"63ce99d79273e1b3a7e72ce32caffc2735fd2abc59ae1cbfa65f8bb5b0ce519b","src/expand/mod.rs":"06c772bc43b091060366991b8e07d381d8079a0c84003f90827498e923196ad6","src/lib.rs":"369502c7daf61a455fda69f356a61ab3daa9b0b319dd54f556137ce98758e8d3","src/mut_visit.rs":"ae24159016d86b0aa7b191d67c27287d00a31117c0e447ac63e3eada74867e6d","src/node_id.rs":"e62ed5488ee582247a15174e449b3a77a577c450f4fda0d1d0322e3e8c6c00f5","src/ptr.rs":"c91df1826e55f6a47a0a472d788bda9893e9f1266471c5749af6ab07c5eaec8b","src/token.rs":"0b1f6d3f4f7602fb51d03e4066ecacd6a8df54eb68603f232dcbfeef83c0cd81","src/tokenstream.rs":"43f8e752eef377f070fbb6dc384ea916501867b6824df74cbb1594145ee86b8c","src/util/classify.rs":"09f1ef7152841292e87657d07d03823256a2fdfa7f90563beebb5304c09762c0","src/util/comments.rs":"7c8d696f6acb29ca163cfbb1cfdda04e88e0665a04c9c8f0cc1043b7c02256d7","src/util/comments/tests.rs":"292eb85f4886e2acaa3299a308aa90d0c9a62796d9298b2164918c576761f28b","src/util/literal.rs":"ab1a26915994fe0cf9c4bc0e8fa579ae1af673abd170d6388ad202821af9fe2e","src/util/parser.rs":"b4e3a9c20db35c34ed8f5149e1797380a026cc6545d5364e74b83d8ae38926e4","src/visit.rs":"2b75874806bb150211c99343a7652f640352ecb1a618ad5fe1acd815a8518af6"},"package":"4c700f2d3b25aa8d6446dd2936048737b08b2d547bd86e2a70afa9fee4e9c522"}
\ No newline at end of file
diff --git a/vendor/rustc-ap-rustc_ast/Cargo.toml b/vendor/rustc-ap-rustc_ast/Cargo.toml
deleted file mode 100644
index bfcd242d8a..0000000000
--- a/vendor/rustc-ap-rustc_ast/Cargo.toml
+++ /dev/null
@@ -1,56 +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 = "rustc-ap-rustc_ast"
-version = "705.0.0"
-authors = ["The Rust Project Developers"]
-description = "Automatically published version of the package `rustc_ast` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n            "
-license = "MIT / Apache-2.0"
-repository = "https://github.com/rust-lang/rust"
-
-[lib]
-doctest = false
-[dependencies.bitflags]
-version = "1.2.1"
-
-[dependencies.rustc_data_structures]
-version = "705.0.0"
-package = "rustc-ap-rustc_data_structures"
-
-[dependencies.rustc_index]
-version = "705.0.0"
-package = "rustc-ap-rustc_index"
-
-[dependencies.rustc_lexer]
-version = "705.0.0"
-package = "rustc-ap-rustc_lexer"
-
-[dependencies.rustc_macros]
-version = "705.0.0"
-package = "rustc-ap-rustc_macros"
-
-[dependencies.rustc_serialize]
-version = "705.0.0"
-package = "rustc-ap-rustc_serialize"
-
-[dependencies.rustc_span]
-version = "705.0.0"
-package = "rustc-ap-rustc_span"
-
-[dependencies.smallvec]
-version = "1.0"
-features = ["union", "may_dangle"]
-
-[dependencies.tracing]
-version = "0.1"
diff --git a/vendor/rustc-ap-rustc_ast/README.md b/vendor/rustc-ap-rustc_ast/README.md
deleted file mode 100644
index dd407dba1f..0000000000
--- a/vendor/rustc-ap-rustc_ast/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-The `rustc_ast` crate contains those things concerned purely with syntax
-– that is, the AST ("abstract syntax tree"), parser, pretty-printer,
-lexer, macro expander, and utilities for traversing ASTs.
-
-For more information about how these things work in rustc, see the
-rustc dev guide:
-
-- [Parsing](https://rustc-dev-guide.rust-lang.org/the-parser.html)
-- [Macro Expansion](https://rustc-dev-guide.rust-lang.org/macro-expansion.html)
diff --git a/vendor/rustc-ap-rustc_ast/src/ast.rs b/vendor/rustc-ap-rustc_ast/src/ast.rs
deleted file mode 100644
index 2ddcb9ef84..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/ast.rs
+++ /dev/null
@@ -1,2977 +0,0 @@
-//! The Rust abstract syntax tree module.
-//!
-//! This module contains common structures forming the language AST.
-//! Two main entities in the module are [`Item`] (which represents an AST element with
-//! additional metadata), and [`ItemKind`] (which represents a concrete type and contains
-//! information specific to the type of the item).
-//!
-//! Other module items worth mentioning:
-//! - [`Ty`] and [`TyKind`]: A parsed Rust type.
-//! - [`Expr`] and [`ExprKind`]: A parsed Rust expression.
-//! - [`Pat`] and [`PatKind`]: A parsed Rust pattern. Patterns are often dual to expressions.
-//! - [`Stmt`] and [`StmtKind`]: An executable action that does not return a value.
-//! - [`FnDecl`], [`FnHeader`] and [`Param`]: Metadata associated with a function declaration.
-//! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters.
-//! - [`EnumDef`] and [`Variant`]: Enum declaration.
-//! - [`Lit`] and [`LitKind`]: Literal expressions.
-//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimiter`]: Macro definition and invocation.
-//! - [`Attribute`]: Metadata associated with item.
-//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
-
-pub use crate::util::parser::ExprPrecedence;
-pub use GenericArgs::*;
-pub use UnsafeSource::*;
-
-use crate::ptr::P;
-use crate::token::{self, CommentKind, DelimToken, Token};
-use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree};
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::thin_vec::ThinVec;
-use rustc_macros::HashStable_Generic;
-use rustc_serialize::{self, Decoder, Encoder};
-use rustc_span::source_map::{respan, Spanned};
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
-
-use std::cmp::Ordering;
-use std::convert::TryFrom;
-use std::fmt;
-
-#[cfg(test)]
-mod tests;
-
-/// A "Label" is an identifier of some point in sources,
-/// e.g. in the following code:
-///
-/// ```rust
-/// 'outer: loop {
-///     break 'outer;
-/// }
-/// ```
-///
-/// `'outer` is a label.
-#[derive(Clone, Encodable, Decodable, Copy, HashStable_Generic)]
-pub struct Label {
-    pub ident: Ident,
-}
-
-impl fmt::Debug for Label {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "label({:?})", self.ident)
-    }
-}
-
-/// A "Lifetime" is an annotation of the scope in which variable
-/// can be used, e.g. `'a` in `&'a i32`.
-#[derive(Clone, Encodable, Decodable, Copy)]
-pub struct Lifetime {
-    pub id: NodeId,
-    pub ident: Ident,
-}
-
-impl fmt::Debug for Lifetime {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "lifetime({}: {})", self.id, self)
-    }
-}
-
-impl fmt::Display for Lifetime {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.ident.name)
-    }
-}
-
-/// A "Path" is essentially Rust's notion of a name.
-///
-/// It's represented as a sequence of identifiers,
-/// along with a bunch of supporting information.
-///
-/// E.g., `std::cmp::PartialEq`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Path {
-    pub span: Span,
-    /// The segments in the path: the things separated by `::`.
-    /// Global paths begin with `kw::PathRoot`.
-    pub segments: Vec,
-    pub tokens: Option,
-}
-
-impl PartialEq for Path {
-    fn eq(&self, symbol: &Symbol) -> bool {
-        self.segments.len() == 1 && { self.segments[0].ident.name == *symbol }
-    }
-}
-
-impl HashStable for Path {
-    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        self.segments.len().hash_stable(hcx, hasher);
-        for segment in &self.segments {
-            segment.ident.name.hash_stable(hcx, hasher);
-        }
-    }
-}
-
-impl Path {
-    // Convert a span and an identifier to the corresponding
-    // one-segment path.
-    pub fn from_ident(ident: Ident) -> Path {
-        Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
-    }
-
-    pub fn is_global(&self) -> bool {
-        !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
-    }
-}
-
-/// A segment of a path: an identifier, an optional lifetime, and a set of types.
-///
-/// E.g., `std`, `String` or `Box`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct PathSegment {
-    /// The identifier portion of this path segment.
-    pub ident: Ident,
-
-    pub id: NodeId,
-
-    /// Type/lifetime parameters attached to this path. They come in
-    /// two flavors: `Path` and `Path(A,B) -> C`.
-    /// `None` means that no parameter list is supplied (`Path`),
-    /// `Some` means that parameter list is supplied (`Path`)
-    /// but it can be empty (`Path<>`).
-    /// `P` is used as a size optimization for the common case with no parameters.
-    pub args: Option>,
-}
-
-impl PathSegment {
-    pub fn from_ident(ident: Ident) -> Self {
-        PathSegment { ident, id: DUMMY_NODE_ID, args: None }
-    }
-    pub fn path_root(span: Span) -> Self {
-        PathSegment::from_ident(Ident::new(kw::PathRoot, span))
-    }
-}
-
-/// The arguments of a path segment.
-///
-/// E.g., `` as in `Foo` or `(A, B)` as in `Foo(A, B)`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum GenericArgs {
-    /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`.
-    AngleBracketed(AngleBracketedArgs),
-    /// The `(A, B)` and `C` in `Foo(A, B) -> C`.
-    Parenthesized(ParenthesizedArgs),
-}
-
-impl GenericArgs {
-    pub fn is_angle_bracketed(&self) -> bool {
-        matches!(self, AngleBracketed(..))
-    }
-
-    pub fn span(&self) -> Span {
-        match *self {
-            AngleBracketed(ref data) => data.span,
-            Parenthesized(ref data) => data.span,
-        }
-    }
-}
-
-/// Concrete argument in the sequence of generic args.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum GenericArg {
-    /// `'a` in `Foo<'a>`
-    Lifetime(Lifetime),
-    /// `Bar` in `Foo`
-    Type(P),
-    /// `1` in `Foo<1>`
-    Const(AnonConst),
-}
-
-impl GenericArg {
-    pub fn span(&self) -> Span {
-        match self {
-            GenericArg::Lifetime(lt) => lt.ident.span,
-            GenericArg::Type(ty) => ty.span,
-            GenericArg::Const(ct) => ct.value.span,
-        }
-    }
-}
-
-/// A path like `Foo<'a, T>`.
-#[derive(Clone, Encodable, Decodable, Debug, Default)]
-pub struct AngleBracketedArgs {
-    /// The overall span.
-    pub span: Span,
-    /// The comma separated parts in the `<...>`.
-    pub args: Vec,
-}
-
-/// Either an argument for a parameter e.g., `'a`, `Vec`, `0`,
-/// or a constraint on an associated item, e.g., `Item = String` or `Item: Bound`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum AngleBracketedArg {
-    /// Argument for a generic parameter.
-    Arg(GenericArg),
-    /// Constraint for an associated item.
-    Constraint(AssocTyConstraint),
-}
-
-impl AngleBracketedArg {
-    pub fn span(&self) -> Span {
-        match self {
-            AngleBracketedArg::Arg(arg) => arg.span(),
-            AngleBracketedArg::Constraint(constraint) => constraint.span,
-        }
-    }
-}
-
-impl Into>> for AngleBracketedArgs {
-    fn into(self) -> Option> {
-        Some(P(GenericArgs::AngleBracketed(self)))
-    }
-}
-
-impl Into>> for ParenthesizedArgs {
-    fn into(self) -> Option> {
-        Some(P(GenericArgs::Parenthesized(self)))
-    }
-}
-
-/// A path like `Foo(A, B) -> C`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct ParenthesizedArgs {
-    /// ```text
-    /// Foo(A, B) -> C
-    /// ^^^^^^^^^^^^^^
-    /// ```
-    pub span: Span,
-
-    /// `(A, B)`
-    pub inputs: Vec>,
-
-    /// ```text
-    /// Foo(A, B) -> C
-    ///    ^^^^^^
-    /// ```
-    pub inputs_span: Span,
-
-    /// `C`
-    pub output: FnRetTy,
-}
-
-impl ParenthesizedArgs {
-    pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
-        let args = self
-            .inputs
-            .iter()
-            .cloned()
-            .map(|input| AngleBracketedArg::Arg(GenericArg::Type(input)))
-            .collect();
-        AngleBracketedArgs { span: self.span, args }
-    }
-}
-
-pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
-
-/// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
-///
-/// Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
-pub enum TraitBoundModifier {
-    /// No modifiers
-    None,
-
-    /// `?Trait`
-    Maybe,
-
-    /// `?const Trait`
-    MaybeConst,
-
-    /// `?const ?Trait`
-    //
-    // This parses but will be rejected during AST validation.
-    MaybeConstMaybe,
-}
-
-/// The AST represents all type param bounds as types.
-/// `typeck::collect::compute_bounds` matches these against
-/// the "special" built-in traits (see `middle::lang_items`) and
-/// detects `Copy`, `Send` and `Sync`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum GenericBound {
-    Trait(PolyTraitRef, TraitBoundModifier),
-    Outlives(Lifetime),
-}
-
-impl GenericBound {
-    pub fn span(&self) -> Span {
-        match self {
-            GenericBound::Trait(ref t, ..) => t.span,
-            GenericBound::Outlives(ref l) => l.ident.span,
-        }
-    }
-}
-
-pub type GenericBounds = Vec;
-
-/// Specifies the enforced ordering for generic parameters. In the future,
-/// if we wanted to relax this order, we could override `PartialEq` and
-/// `PartialOrd`, to allow the kinds to be unordered.
-#[derive(Hash, Clone, Copy)]
-pub enum ParamKindOrd {
-    Lifetime,
-    Type,
-    // `unordered` is only `true` if `sess.has_features().const_generics`
-    // is active. Specifically, if it's only `min_const_generics`, it will still require
-    // ordering consts after types.
-    Const { unordered: bool },
-}
-
-impl Ord for ParamKindOrd {
-    fn cmp(&self, other: &Self) -> Ordering {
-        use ParamKindOrd::*;
-        let to_int = |v| match v {
-            Lifetime => 0,
-            Type | Const { unordered: true } => 1,
-            // technically both consts should be ordered equally,
-            // but only one is ever encountered at a time, so this is
-            // fine.
-            Const { unordered: false } => 2,
-        };
-
-        to_int(*self).cmp(&to_int(*other))
-    }
-}
-impl PartialOrd for ParamKindOrd {
-    fn partial_cmp(&self, other: &Self) -> Option {
-        Some(self.cmp(other))
-    }
-}
-impl PartialEq for ParamKindOrd {
-    fn eq(&self, other: &Self) -> bool {
-        self.cmp(other) == Ordering::Equal
-    }
-}
-impl Eq for ParamKindOrd {}
-
-impl fmt::Display for ParamKindOrd {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            ParamKindOrd::Lifetime => "lifetime".fmt(f),
-            ParamKindOrd::Type => "type".fmt(f),
-            ParamKindOrd::Const { .. } => "const".fmt(f),
-        }
-    }
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum GenericParamKind {
-    /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
-    Lifetime,
-    Type {
-        default: Option>,
-    },
-    Const {
-        ty: P,
-        /// Span of the `const` keyword.
-        kw_span: Span,
-        /// Optional default value for the const generic param
-        default: Option,
-    },
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct GenericParam {
-    pub id: NodeId,
-    pub ident: Ident,
-    pub attrs: AttrVec,
-    pub bounds: GenericBounds,
-    pub is_placeholder: bool,
-    pub kind: GenericParamKind,
-}
-
-/// Represents lifetime, type and const parameters attached to a declaration of
-/// a function, enum, trait, etc.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Generics {
-    pub params: Vec,
-    pub where_clause: WhereClause,
-    pub span: Span,
-}
-
-impl Default for Generics {
-    /// Creates an instance of `Generics`.
-    fn default() -> Generics {
-        Generics {
-            params: Vec::new(),
-            where_clause: WhereClause {
-                has_where_token: false,
-                predicates: Vec::new(),
-                span: DUMMY_SP,
-            },
-            span: DUMMY_SP,
-        }
-    }
-}
-
-/// A where-clause in a definition.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct WhereClause {
-    /// `true` if we ate a `where` token: this can happen
-    /// if we parsed no predicates (e.g. `struct Foo where {}`).
-    /// This allows us to accurately pretty-print
-    /// in `nt_to_tokenstream`
-    pub has_where_token: bool,
-    pub predicates: Vec,
-    pub span: Span,
-}
-
-/// A single predicate in a where-clause.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum WherePredicate {
-    /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
-    BoundPredicate(WhereBoundPredicate),
-    /// A lifetime predicate (e.g., `'a: 'b + 'c`).
-    RegionPredicate(WhereRegionPredicate),
-    /// An equality predicate (unsupported).
-    EqPredicate(WhereEqPredicate),
-}
-
-impl WherePredicate {
-    pub fn span(&self) -> Span {
-        match self {
-            WherePredicate::BoundPredicate(p) => p.span,
-            WherePredicate::RegionPredicate(p) => p.span,
-            WherePredicate::EqPredicate(p) => p.span,
-        }
-    }
-}
-
-/// A type bound.
-///
-/// E.g., `for<'c> Foo: Send + Clone + 'c`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct WhereBoundPredicate {
-    pub span: Span,
-    /// Any generics from a `for` binding.
-    pub bound_generic_params: Vec,
-    /// The type being bounded.
-    pub bounded_ty: P,
-    /// Trait and lifetime bounds (`Clone + Send + 'static`).
-    pub bounds: GenericBounds,
-}
-
-/// A lifetime predicate.
-///
-/// E.g., `'a: 'b + 'c`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct WhereRegionPredicate {
-    pub span: Span,
-    pub lifetime: Lifetime,
-    pub bounds: GenericBounds,
-}
-
-/// An equality predicate (unsupported).
-///
-/// E.g., `T = int`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct WhereEqPredicate {
-    pub id: NodeId,
-    pub span: Span,
-    pub lhs_ty: P,
-    pub rhs_ty: P,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Crate {
-    pub module: Mod,
-    pub attrs: Vec,
-    pub span: Span,
-    /// The order of items in the HIR is unrelated to the order of
-    /// items in the AST. However, we generate proc macro harnesses
-    /// based on the AST order, and later refer to these harnesses
-    /// from the HIR. This field keeps track of the order in which
-    /// we generated proc macros harnesses, so that we can map
-    /// HIR proc macros items back to their harness items.
-    pub proc_macros: Vec,
-}
-
-/// Possible values inside of compile-time attribute lists.
-///
-/// E.g., the '..' in `#[name(..)]`.
-#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum NestedMetaItem {
-    /// A full MetaItem, for recursive meta items.
-    MetaItem(MetaItem),
-    /// A literal.
-    ///
-    /// E.g., `"foo"`, `64`, `true`.
-    Literal(Lit),
-}
-
-/// A spanned compile-time attribute item.
-///
-/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
-#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
-pub struct MetaItem {
-    pub path: Path,
-    pub kind: MetaItemKind,
-    pub span: Span,
-}
-
-/// A compile-time attribute item.
-///
-/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`.
-#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum MetaItemKind {
-    /// Word meta item.
-    ///
-    /// E.g., `test` as in `#[test]`.
-    Word,
-    /// List meta item.
-    ///
-    /// E.g., `derive(..)` as in `#[derive(..)]`.
-    List(Vec),
-    /// Name value meta item.
-    ///
-    /// E.g., `feature = "foo"` as in `#[feature = "foo"]`.
-    NameValue(Lit),
-}
-
-/// A block (`{ .. }`).
-///
-/// E.g., `{ .. }` as in `fn foo() { .. }`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Block {
-    /// The statements in the block.
-    pub stmts: Vec,
-    pub id: NodeId,
-    /// Distinguishes between `unsafe { ... }` and `{ ... }`.
-    pub rules: BlockCheckMode,
-    pub span: Span,
-    pub tokens: Option,
-}
-
-/// A match pattern.
-///
-/// Patterns appear in match statements and some other contexts, such as `let` and `if let`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Pat {
-    pub id: NodeId,
-    pub kind: PatKind,
-    pub span: Span,
-    pub tokens: Option,
-}
-
-impl Pat {
-    /// Attempt reparsing the pattern as a type.
-    /// This is intended for use by diagnostics.
-    pub fn to_ty(&self) -> Option> {
-        let kind = match &self.kind {
-            // In a type expression `_` is an inference variable.
-            PatKind::Wild => TyKind::Infer,
-            // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
-            PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
-                TyKind::Path(None, Path::from_ident(*ident))
-            }
-            PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
-            PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
-            // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
-            PatKind::Ref(pat, mutbl) => {
-                pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?
-            }
-            // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
-            // when `P` can be reparsed as a type `T`.
-            PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?,
-            // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`
-            // assuming `T0` to `Tn` are all syntactically valid as types.
-            PatKind::Tuple(pats) => {
-                let mut tys = Vec::with_capacity(pats.len());
-                // FIXME(#48994) - could just be collected into an Option
-                for pat in pats {
-                    tys.push(pat.to_ty()?);
-                }
-                TyKind::Tup(tys)
-            }
-            _ => return None,
-        };
-
-        Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
-    }
-
-    /// Walk top-down and call `it` in each place where a pattern occurs
-    /// starting with the root pattern `walk` is called on. If `it` returns
-    /// false then we will descend no further but siblings will be processed.
-    pub fn walk(&self, it: &mut impl FnMut(&Pat) -> bool) {
-        if !it(self) {
-            return;
-        }
-
-        match &self.kind {
-            // Walk into the pattern associated with `Ident` (if any).
-            PatKind::Ident(_, _, Some(p)) => p.walk(it),
-
-            // Walk into each field of struct.
-            PatKind::Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)),
-
-            // Sequence of patterns.
-            PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) | PatKind::Or(s) => {
-                s.iter().for_each(|p| p.walk(it))
-            }
-
-            // Trivial wrappers over inner patterns.
-            PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
-
-            // These patterns do not contain subpatterns, skip.
-            PatKind::Wild
-            | PatKind::Rest
-            | PatKind::Lit(_)
-            | PatKind::Range(..)
-            | PatKind::Ident(..)
-            | PatKind::Path(..)
-            | PatKind::MacCall(_) => {}
-        }
-    }
-
-    /// Is this a `..` pattern?
-    pub fn is_rest(&self) -> bool {
-        matches!(self.kind, PatKind::Rest)
-    }
-}
-
-/// A single field in a struct pattern.
-///
-/// Patterns like the fields of `Foo { x, ref y, ref mut z }`
-/// are treated the same as `x: x, y: ref y, z: ref mut z`,
-/// except when `is_shorthand` is true.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct FieldPat {
-    /// The identifier for the field.
-    pub ident: Ident,
-    /// The pattern the field is destructured to.
-    pub pat: P,
-    pub is_shorthand: bool,
-    pub attrs: AttrVec,
-    pub id: NodeId,
-    pub span: Span,
-    pub is_placeholder: bool,
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
-pub enum BindingMode {
-    ByRef(Mutability),
-    ByValue(Mutability),
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum RangeEnd {
-    Included(RangeSyntax),
-    Excluded,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum RangeSyntax {
-    /// `...`
-    DotDotDot,
-    /// `..=`
-    DotDotEq,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum PatKind {
-    /// Represents a wildcard pattern (`_`).
-    Wild,
-
-    /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),
-    /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
-    /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
-    /// during name resolution.
-    Ident(BindingMode, Ident, Option>),
-
-    /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
-    /// The `bool` is `true` in the presence of a `..`.
-    Struct(Path, Vec, /* recovered */ bool),
-
-    /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
-    TupleStruct(Path, Vec>),
-
-    /// An or-pattern `A | B | C`.
-    /// Invariant: `pats.len() >= 2`.
-    Or(Vec>),
-
-    /// A possibly qualified path pattern.
-    /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
-    /// or associated constants. Qualified path patterns `::B::C`/`::B::C` can
-    /// only legally refer to associated constants.
-    Path(Option, Path),
-
-    /// A tuple pattern (`(a, b)`).
-    Tuple(Vec>),
-
-    /// A `box` pattern.
-    Box(P),
-
-    /// A reference pattern (e.g., `&mut (a, b)`).
-    Ref(P, Mutability),
-
-    /// A literal.
-    Lit(P),
-
-    /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
-    Range(Option>, Option>, Spanned),
-
-    /// A slice pattern `[a, b, c]`.
-    Slice(Vec>),
-
-    /// A rest pattern `..`.
-    ///
-    /// Syntactically it is valid anywhere.
-    ///
-    /// Semantically however, it only has meaning immediately inside:
-    /// - a slice pattern: `[a, .., b]`,
-    /// - a binding pattern immediately inside a slice pattern: `[a, r @ ..]`,
-    /// - a tuple pattern: `(a, .., b)`,
-    /// - a tuple struct/variant pattern: `$path(a, .., b)`.
-    ///
-    /// In all of these cases, an additional restriction applies,
-    /// only one rest pattern may occur in the pattern sequences.
-    Rest,
-
-    /// Parentheses in patterns used for grouping (i.e., `(PAT)`).
-    Paren(P),
-
-    /// A macro pattern; pre-expansion.
-    MacCall(MacCall),
-}
-
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
-pub enum Mutability {
-    Mut,
-    Not,
-}
-
-impl Mutability {
-    /// Returns `MutMutable` only if both `self` and `other` are mutable.
-    pub fn and(self, other: Self) -> Self {
-        match self {
-            Mutability::Mut => other,
-            Mutability::Not => Mutability::Not,
-        }
-    }
-
-    pub fn invert(self) -> Self {
-        match self {
-            Mutability::Mut => Mutability::Not,
-            Mutability::Not => Mutability::Mut,
-        }
-    }
-
-    pub fn prefix_str(&self) -> &'static str {
-        match self {
-            Mutability::Mut => "mut ",
-            Mutability::Not => "",
-        }
-    }
-}
-
-/// The kind of borrow in an `AddrOf` expression,
-/// e.g., `&place` or `&raw const place`.
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
-pub enum BorrowKind {
-    /// A normal borrow, `&$expr` or `&mut $expr`.
-    /// The resulting type is either `&'a T` or `&'a mut T`
-    /// where `T = typeof($expr)` and `'a` is some lifetime.
-    Ref,
-    /// A raw borrow, `&raw const $expr` or `&raw mut $expr`.
-    /// The resulting type is either `*const T` or `*mut T`
-    /// where `T = typeof($expr)`.
-    Raw,
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
-pub enum BinOpKind {
-    /// The `+` operator (addition)
-    Add,
-    /// The `-` operator (subtraction)
-    Sub,
-    /// The `*` operator (multiplication)
-    Mul,
-    /// The `/` operator (division)
-    Div,
-    /// The `%` operator (modulus)
-    Rem,
-    /// The `&&` operator (logical and)
-    And,
-    /// The `||` operator (logical or)
-    Or,
-    /// The `^` operator (bitwise xor)
-    BitXor,
-    /// The `&` operator (bitwise and)
-    BitAnd,
-    /// The `|` operator (bitwise or)
-    BitOr,
-    /// The `<<` operator (shift left)
-    Shl,
-    /// The `>>` operator (shift right)
-    Shr,
-    /// The `==` operator (equality)
-    Eq,
-    /// The `<` operator (less than)
-    Lt,
-    /// The `<=` operator (less than or equal to)
-    Le,
-    /// The `!=` operator (not equal to)
-    Ne,
-    /// The `>=` operator (greater than or equal to)
-    Ge,
-    /// The `>` operator (greater than)
-    Gt,
-}
-
-impl BinOpKind {
-    pub fn to_string(&self) -> &'static str {
-        use BinOpKind::*;
-        match *self {
-            Add => "+",
-            Sub => "-",
-            Mul => "*",
-            Div => "/",
-            Rem => "%",
-            And => "&&",
-            Or => "||",
-            BitXor => "^",
-            BitAnd => "&",
-            BitOr => "|",
-            Shl => "<<",
-            Shr => ">>",
-            Eq => "==",
-            Lt => "<",
-            Le => "<=",
-            Ne => "!=",
-            Ge => ">=",
-            Gt => ">",
-        }
-    }
-    pub fn lazy(&self) -> bool {
-        matches!(self, BinOpKind::And | BinOpKind::Or)
-    }
-
-    pub fn is_comparison(&self) -> bool {
-        use BinOpKind::*;
-        // Note for developers: please keep this as is;
-        // we want compilation to fail if another variant is added.
-        match *self {
-            Eq | Lt | Le | Ne | Gt | Ge => true,
-            And | Or | Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr => false,
-        }
-    }
-}
-
-pub type BinOp = Spanned;
-
-/// Unary operator.
-///
-/// Note that `&data` is not an operator, it's an `AddrOf` expression.
-#[derive(Clone, Encodable, Decodable, Debug, Copy)]
-pub enum UnOp {
-    /// The `*` operator for dereferencing
-    Deref,
-    /// The `!` operator for logical inversion
-    Not,
-    /// The `-` operator for negation
-    Neg,
-}
-
-impl UnOp {
-    pub fn to_string(op: UnOp) -> &'static str {
-        match op {
-            UnOp::Deref => "*",
-            UnOp::Not => "!",
-            UnOp::Neg => "-",
-        }
-    }
-}
-
-/// A statement
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Stmt {
-    pub id: NodeId,
-    pub kind: StmtKind,
-    pub span: Span,
-}
-
-impl Stmt {
-    pub fn tokens(&self) -> Option<&LazyTokenStream> {
-        match self.kind {
-            StmtKind::Local(ref local) => local.tokens.as_ref(),
-            StmtKind::Item(ref item) => item.tokens.as_ref(),
-            StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.tokens.as_ref(),
-            StmtKind::Empty => None,
-            StmtKind::MacCall(ref mac) => mac.tokens.as_ref(),
-        }
-    }
-
-    pub fn tokens_mut(&mut self) -> Option<&mut LazyTokenStream> {
-        match self.kind {
-            StmtKind::Local(ref mut local) => local.tokens.as_mut(),
-            StmtKind::Item(ref mut item) => item.tokens.as_mut(),
-            StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens.as_mut(),
-            StmtKind::Empty => None,
-            StmtKind::MacCall(ref mut mac) => mac.tokens.as_mut(),
-        }
-    }
-
-    pub fn has_trailing_semicolon(&self) -> bool {
-        match &self.kind {
-            StmtKind::Semi(_) => true,
-            StmtKind::MacCall(mac) => matches!(mac.style, MacStmtStyle::Semicolon),
-            _ => false,
-        }
-    }
-
-    /// Converts a parsed `Stmt` to a `Stmt` with
-    /// a trailing semicolon.
-    ///
-    /// This only modifies the parsed AST struct, not the attached
-    /// `LazyTokenStream`. The parser is responsible for calling
-    /// `CreateTokenStream::add_trailing_semi` when there is actually
-    /// a semicolon in the tokenstream.
-    pub fn add_trailing_semicolon(mut self) -> Self {
-        self.kind = match self.kind {
-            StmtKind::Expr(expr) => StmtKind::Semi(expr),
-            StmtKind::MacCall(mac) => {
-                StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs, tokens }| {
-                    MacCallStmt { mac, style: MacStmtStyle::Semicolon, attrs, tokens }
-                }))
-            }
-            kind => kind,
-        };
-
-        self
-    }
-
-    pub fn is_item(&self) -> bool {
-        matches!(self.kind, StmtKind::Item(_))
-    }
-
-    pub fn is_expr(&self) -> bool {
-        matches!(self.kind, StmtKind::Expr(_))
-    }
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum StmtKind {
-    /// A local (let) binding.
-    Local(P),
-    /// An item definition.
-    Item(P),
-    /// Expr without trailing semi-colon.
-    Expr(P),
-    /// Expr with a trailing semi-colon.
-    Semi(P),
-    /// Just a trailing semi-colon.
-    Empty,
-    /// Macro.
-    MacCall(P),
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct MacCallStmt {
-    pub mac: MacCall,
-    pub style: MacStmtStyle,
-    pub attrs: AttrVec,
-    pub tokens: Option,
-}
-
-#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
-pub enum MacStmtStyle {
-    /// The macro statement had a trailing semicolon (e.g., `foo! { ... };`
-    /// `foo!(...);`, `foo![...];`).
-    Semicolon,
-    /// The macro statement had braces (e.g., `foo! { ... }`).
-    Braces,
-    /// The macro statement had parentheses or brackets and no semicolon (e.g.,
-    /// `foo!(...)`). All of these will end up being converted into macro
-    /// expressions.
-    NoBraces,
-}
-
-/// Local represents a `let` statement, e.g., `let : = ;`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Local {
-    pub id: NodeId,
-    pub pat: P,
-    pub ty: Option>,
-    /// Initializer expression to set the value, if any.
-    pub init: Option>,
-    pub span: Span,
-    pub attrs: AttrVec,
-    pub tokens: Option,
-}
-
-/// An arm of a 'match'.
-///
-/// E.g., `0..=10 => { println!("match!") }` as in
-///
-/// ```
-/// match 123 {
-///     0..=10 => { println!("match!") },
-///     _ => { println!("no match!") },
-/// }
-/// ```
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Arm {
-    pub attrs: Vec,
-    /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
-    pub pat: P,
-    /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
-    pub guard: Option>,
-    /// Match arm body.
-    pub body: P,
-    pub span: Span,
-    pub id: NodeId,
-    pub is_placeholder: bool,
-}
-
-/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Field {
-    pub attrs: AttrVec,
-    pub id: NodeId,
-    pub span: Span,
-    pub ident: Ident,
-    pub expr: P,
-    pub is_shorthand: bool,
-    pub is_placeholder: bool,
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
-pub enum BlockCheckMode {
-    Default,
-    Unsafe(UnsafeSource),
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
-pub enum UnsafeSource {
-    CompilerGenerated,
-    UserProvided,
-}
-
-/// A constant (expression) that's not an item or associated item,
-/// but needs its own `DefId` for type-checking, const-eval, etc.
-/// These are usually found nested inside types (e.g., array lengths)
-/// or expressions (e.g., repeat counts), and also used to define
-/// explicit discriminant values for enum variants.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct AnonConst {
-    pub id: NodeId,
-    pub value: P,
-}
-
-/// An expression.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Expr {
-    pub id: NodeId,
-    pub kind: ExprKind,
-    pub span: Span,
-    pub attrs: AttrVec,
-    pub tokens: Option,
-}
-
-// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(Expr, 120);
-
-impl Expr {
-    /// Returns `true` if this expression would be valid somewhere that expects a value;
-    /// for example, an `if` condition.
-    pub fn returns(&self) -> bool {
-        if let ExprKind::Block(ref block, _) = self.kind {
-            match block.stmts.last().map(|last_stmt| &last_stmt.kind) {
-                // Implicit return
-                Some(StmtKind::Expr(_)) => true,
-                // Last statement is an explicit return?
-                Some(StmtKind::Semi(expr)) => matches!(expr.kind, ExprKind::Ret(_)),
-                // This is a block that doesn't end in either an implicit or explicit return.
-                _ => false,
-            }
-        } else {
-            // This is not a block, it is a value.
-            true
-        }
-    }
-
-    /// Is this expr either `N`, or `{ N }`.
-    ///
-    /// If this is not the case, name resolution does not resolve `N` when using
-    /// `min_const_generics` as more complex expressions are not supported.
-    pub fn is_potential_trivial_const_param(&self) -> bool {
-        let this = if let ExprKind::Block(ref block, None) = self.kind {
-            if block.stmts.len() == 1 {
-                if let StmtKind::Expr(ref expr) = block.stmts[0].kind { expr } else { self }
-            } else {
-                self
-            }
-        } else {
-            self
-        };
-
-        if let ExprKind::Path(None, ref path) = this.kind {
-            if path.segments.len() == 1 && path.segments[0].args.is_none() {
-                return true;
-            }
-        }
-
-        false
-    }
-
-    pub fn to_bound(&self) -> Option {
-        match &self.kind {
-            ExprKind::Path(None, path) => Some(GenericBound::Trait(
-                PolyTraitRef::new(Vec::new(), path.clone(), self.span),
-                TraitBoundModifier::None,
-            )),
-            _ => None,
-        }
-    }
-
-    /// Attempts to reparse as `Ty` (for diagnostic purposes).
-    pub fn to_ty(&self) -> Option> {
-        let kind = match &self.kind {
-            // Trivial conversions.
-            ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
-            ExprKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
-
-            ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
-
-            ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => {
-                expr.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?
-            }
-
-            ExprKind::Repeat(expr, expr_len) => {
-                expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?
-            }
-
-            ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?,
-
-            ExprKind::Tup(exprs) => {
-                let tys = exprs.iter().map(|expr| expr.to_ty()).collect::>>()?;
-                TyKind::Tup(tys)
-            }
-
-            // If binary operator is `Add` and both `lhs` and `rhs` are trait bounds,
-            // then type of result is trait object.
-            // Otherwise we don't assume the result type.
-            ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {
-                if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
-                    TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
-                } else {
-                    return None;
-                }
-            }
-
-            // This expression doesn't look like a type syntactically.
-            _ => return None,
-        };
-
-        Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
-    }
-
-    pub fn precedence(&self) -> ExprPrecedence {
-        match self.kind {
-            ExprKind::Box(_) => ExprPrecedence::Box,
-            ExprKind::Array(_) => ExprPrecedence::Array,
-            ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
-            ExprKind::Call(..) => ExprPrecedence::Call,
-            ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
-            ExprKind::Tup(_) => ExprPrecedence::Tup,
-            ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node),
-            ExprKind::Unary(..) => ExprPrecedence::Unary,
-            ExprKind::Lit(_) => ExprPrecedence::Lit,
-            ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
-            ExprKind::Let(..) => ExprPrecedence::Let,
-            ExprKind::If(..) => ExprPrecedence::If,
-            ExprKind::While(..) => ExprPrecedence::While,
-            ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
-            ExprKind::Loop(..) => ExprPrecedence::Loop,
-            ExprKind::Match(..) => ExprPrecedence::Match,
-            ExprKind::Closure(..) => ExprPrecedence::Closure,
-            ExprKind::Block(..) => ExprPrecedence::Block,
-            ExprKind::TryBlock(..) => ExprPrecedence::TryBlock,
-            ExprKind::Async(..) => ExprPrecedence::Async,
-            ExprKind::Await(..) => ExprPrecedence::Await,
-            ExprKind::Assign(..) => ExprPrecedence::Assign,
-            ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
-            ExprKind::Field(..) => ExprPrecedence::Field,
-            ExprKind::Index(..) => ExprPrecedence::Index,
-            ExprKind::Range(..) => ExprPrecedence::Range,
-            ExprKind::Underscore => ExprPrecedence::Path,
-            ExprKind::Path(..) => ExprPrecedence::Path,
-            ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
-            ExprKind::Break(..) => ExprPrecedence::Break,
-            ExprKind::Continue(..) => ExprPrecedence::Continue,
-            ExprKind::Ret(..) => ExprPrecedence::Ret,
-            ExprKind::InlineAsm(..) | ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm,
-            ExprKind::MacCall(..) => ExprPrecedence::Mac,
-            ExprKind::Struct(..) => ExprPrecedence::Struct,
-            ExprKind::Repeat(..) => ExprPrecedence::Repeat,
-            ExprKind::Paren(..) => ExprPrecedence::Paren,
-            ExprKind::Try(..) => ExprPrecedence::Try,
-            ExprKind::Yield(..) => ExprPrecedence::Yield,
-            ExprKind::Err => ExprPrecedence::Err,
-        }
-    }
-}
-
-/// Limit types of a range (inclusive or exclusive)
-#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
-pub enum RangeLimits {
-    /// Inclusive at the beginning, exclusive at the end
-    HalfOpen,
-    /// Inclusive at the beginning and end
-    Closed,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum StructRest {
-    /// `..x`.
-    Base(P),
-    /// `..`.
-    Rest(Span),
-    /// No trailing `..` or expression.
-    None,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum ExprKind {
-    /// A `box x` expression.
-    Box(P),
-    /// An array (`[a, b, c, d]`)
-    Array(Vec>),
-    /// Allow anonymous constants from an inline `const` block
-    ConstBlock(AnonConst),
-    /// A function call
-    ///
-    /// The first field resolves to the function itself,
-    /// and the second field is the list of arguments.
-    /// This also represents calling the constructor of
-    /// tuple-like ADTs such as tuple structs and enum variants.
-    Call(P, Vec>),
-    /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`)
-    ///
-    /// The `PathSegment` represents the method name and its generic arguments
-    /// (within the angle brackets).
-    /// The first element of the vector of an `Expr` is the expression that evaluates
-    /// to the object on which the method is being called on (the receiver),
-    /// and the remaining elements are the rest of the arguments.
-    /// Thus, `x.foo::(a, b, c, d)` is represented as
-    /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
-    /// This `Span` is the span of the function, without the dot and receiver
-    /// (e.g. `foo(a, b)` in `x.foo(a, b)`
-    MethodCall(PathSegment, Vec>, Span),
-    /// A tuple (e.g., `(a, b, c, d)`).
-    Tup(Vec>),
-    /// A binary operation (e.g., `a + b`, `a * b`).
-    Binary(BinOp, P, P),
-    /// A unary operation (e.g., `!x`, `*x`).
-    Unary(UnOp, P),
-    /// A literal (e.g., `1`, `"foo"`).
-    Lit(Lit),
-    /// A cast (e.g., `foo as f64`).
-    Cast(P, P),
-    /// A type ascription (e.g., `42: usize`).
-    Type(P, P),
-    /// A `let pat = expr` expression that is only semantically allowed in the condition
-    /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).
-    Let(P, P),
-    /// An `if` block, with an optional `else` block.
-    ///
-    /// `if expr { block } else { expr }`
-    If(P, P, Option>),
-    /// A while loop, with an optional label.
-    ///
-    /// `'label: while expr { block }`
-    While(P, P, Option` or
-/// `A: TraitA + TraitB` in `Foo`).
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct AssocTyConstraint {
-    pub id: NodeId,
-    pub ident: Ident,
-    pub gen_args: Option,
-    pub kind: AssocTyConstraintKind,
-    pub span: Span,
-}
-
-/// The kinds of an `AssocTyConstraint`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum AssocTyConstraintKind {
-    /// E.g., `A = Bar` in `Foo`.
-    Equality { ty: P },
-    /// E.g. `A: TraitA + TraitB` in `Foo`.
-    Bound { bounds: GenericBounds },
-}
-
-#[derive(Encodable, Decodable, Debug)]
-pub struct Ty {
-    pub id: NodeId,
-    pub kind: TyKind,
-    pub span: Span,
-    pub tokens: Option,
-}
-
-impl Clone for Ty {
-    fn clone(&self) -> Self {
-        ensure_sufficient_stack(|| Self {
-            id: self.id,
-            kind: self.kind.clone(),
-            span: self.span,
-            tokens: self.tokens.clone(),
-        })
-    }
-}
-
-impl Ty {
-    pub fn peel_refs(&self) -> &Self {
-        let mut final_ty = self;
-        while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
-            final_ty = &ty;
-        }
-        final_ty
-    }
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct BareFnTy {
-    pub unsafety: Unsafe,
-    pub ext: Extern,
-    pub generic_params: Vec,
-    pub decl: P,
-}
-
-/// The various kinds of type recognized by the compiler.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum TyKind {
-    /// A variable-length slice (`[T]`).
-    Slice(P),
-    /// A fixed length array (`[T; n]`).
-    Array(P, AnonConst),
-    /// A raw pointer (`*const T` or `*mut T`).
-    Ptr(MutTy),
-    /// A reference (`&'a T` or `&'a mut T`).
-    Rptr(Option, MutTy),
-    /// A bare function (e.g., `fn(usize) -> bool`).
-    BareFn(P),
-    /// The never type (`!`).
-    Never,
-    /// A tuple (`(A, B, C, D,...)`).
-    Tup(Vec>),
-    /// A path (`module::module::...::Type`), optionally
-    /// "qualified", e.g., ` as SomeTrait>::SomeType`.
-    ///
-    /// Type parameters are stored in the `Path` itself.
-    Path(Option, Path),
-    /// A trait object type `Bound1 + Bound2 + Bound3`
-    /// where `Bound` is a trait or a lifetime.
-    TraitObject(GenericBounds, TraitObjectSyntax),
-    /// An `impl Bound1 + Bound2 + Bound3` type
-    /// where `Bound` is a trait or a lifetime.
-    ///
-    /// The `NodeId` exists to prevent lowering from having to
-    /// generate `NodeId`s on the fly, which would complicate
-    /// the generation of opaque `type Foo = impl Trait` items significantly.
-    ImplTrait(NodeId, GenericBounds),
-    /// No-op; kept solely so that we can pretty-print faithfully.
-    Paren(P),
-    /// Unused for now.
-    Typeof(AnonConst),
-    /// This means the type should be inferred instead of it having been
-    /// specified. This can appear anywhere in a type.
-    Infer,
-    /// Inferred type of a `self` or `&self` argument in a method.
-    ImplicitSelf,
-    /// A macro in the type position.
-    MacCall(MacCall),
-    /// Placeholder for a kind that has failed to be defined.
-    Err,
-    /// Placeholder for a `va_list`.
-    CVarArgs,
-}
-
-impl TyKind {
-    pub fn is_implicit_self(&self) -> bool {
-        matches!(self, TyKind::ImplicitSelf)
-    }
-
-    pub fn is_unit(&self) -> bool {
-        matches!(self, TyKind::Tup(tys) if tys.is_empty())
-    }
-}
-
-/// Syntax used to declare a trait object.
-#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
-pub enum TraitObjectSyntax {
-    Dyn,
-    None,
-}
-
-/// Inline assembly operand explicit register or register class.
-///
-/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
-#[derive(Clone, Copy, Encodable, Decodable, Debug)]
-pub enum InlineAsmRegOrRegClass {
-    Reg(Symbol),
-    RegClass(Symbol),
-}
-
-bitflags::bitflags! {
-    #[derive(Encodable, Decodable, HashStable_Generic)]
-    pub struct InlineAsmOptions: u8 {
-        const PURE = 1 << 0;
-        const NOMEM = 1 << 1;
-        const READONLY = 1 << 2;
-        const PRESERVES_FLAGS = 1 << 3;
-        const NORETURN = 1 << 4;
-        const NOSTACK = 1 << 5;
-        const ATT_SYNTAX = 1 << 6;
-    }
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum InlineAsmTemplatePiece {
-    String(String),
-    Placeholder { operand_idx: usize, modifier: Option, span: Span },
-}
-
-impl fmt::Display for InlineAsmTemplatePiece {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::String(s) => {
-                for c in s.chars() {
-                    match c {
-                        '{' => f.write_str("{{")?,
-                        '}' => f.write_str("}}")?,
-                        _ => c.fmt(f)?,
-                    }
-                }
-                Ok(())
-            }
-            Self::Placeholder { operand_idx, modifier: Some(modifier), .. } => {
-                write!(f, "{{{}:{}}}", operand_idx, modifier)
-            }
-            Self::Placeholder { operand_idx, modifier: None, .. } => {
-                write!(f, "{{{}}}", operand_idx)
-            }
-        }
-    }
-}
-
-impl InlineAsmTemplatePiece {
-    /// Rebuilds the asm template string from its pieces.
-    pub fn to_string(s: &[Self]) -> String {
-        use fmt::Write;
-        let mut out = String::new();
-        for p in s.iter() {
-            let _ = write!(out, "{}", p);
-        }
-        out
-    }
-}
-
-/// Inline assembly operand.
-///
-/// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum InlineAsmOperand {
-    In {
-        reg: InlineAsmRegOrRegClass,
-        expr: P,
-    },
-    Out {
-        reg: InlineAsmRegOrRegClass,
-        late: bool,
-        expr: Option>,
-    },
-    InOut {
-        reg: InlineAsmRegOrRegClass,
-        late: bool,
-        expr: P,
-    },
-    SplitInOut {
-        reg: InlineAsmRegOrRegClass,
-        late: bool,
-        in_expr: P,
-        out_expr: Option>,
-    },
-    Const {
-        expr: P,
-    },
-    Sym {
-        expr: P,
-    },
-}
-
-/// Inline assembly.
-///
-/// E.g., `asm!("NOP");`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct InlineAsm {
-    pub template: Vec,
-    pub operands: Vec<(InlineAsmOperand, Span)>,
-    pub options: InlineAsmOptions,
-    pub line_spans: Vec,
-}
-
-/// Inline assembly dialect.
-///
-/// E.g., `"intel"` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
-pub enum LlvmAsmDialect {
-    Att,
-    Intel,
-}
-
-/// LLVM-style inline assembly.
-///
-/// E.g., `"={eax}"(result)` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct LlvmInlineAsmOutput {
-    pub constraint: Symbol,
-    pub expr: P,
-    pub is_rw: bool,
-    pub is_indirect: bool,
-}
-
-/// LLVM-style inline assembly.
-///
-/// E.g., `llvm_asm!("NOP");`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct LlvmInlineAsm {
-    pub asm: Symbol,
-    pub asm_str_style: StrStyle,
-    pub outputs: Vec,
-    pub inputs: Vec<(Symbol, P)>,
-    pub clobbers: Vec,
-    pub volatile: bool,
-    pub alignstack: bool,
-    pub dialect: LlvmAsmDialect,
-}
-
-/// A parameter in a function header.
-///
-/// E.g., `bar: usize` as in `fn foo(bar: usize)`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Param {
-    pub attrs: AttrVec,
-    pub ty: P,
-    pub pat: P,
-    pub id: NodeId,
-    pub span: Span,
-    pub is_placeholder: bool,
-}
-
-/// Alternative representation for `Arg`s describing `self` parameter of methods.
-///
-/// E.g., `&mut self` as in `fn foo(&mut self)`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum SelfKind {
-    /// `self`, `mut self`
-    Value(Mutability),
-    /// `&'lt self`, `&'lt mut self`
-    Region(Option, Mutability),
-    /// `self: TYPE`, `mut self: TYPE`
-    Explicit(P, Mutability),
-}
-
-pub type ExplicitSelf = Spanned;
-
-impl Param {
-    /// Attempts to cast parameter to `ExplicitSelf`.
-    pub fn to_self(&self) -> Option {
-        if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.kind {
-            if ident.name == kw::SelfLower {
-                return match self.ty.kind {
-                    TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
-                    TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
-                        Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
-                    }
-                    _ => Some(respan(
-                        self.pat.span.to(self.ty.span),
-                        SelfKind::Explicit(self.ty.clone(), mutbl),
-                    )),
-                };
-            }
-        }
-        None
-    }
-
-    /// Returns `true` if parameter is `self`.
-    pub fn is_self(&self) -> bool {
-        if let PatKind::Ident(_, ident, _) = self.pat.kind {
-            ident.name == kw::SelfLower
-        } else {
-            false
-        }
-    }
-
-    /// Builds a `Param` object from `ExplicitSelf`.
-    pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
-        let span = eself.span.to(eself_ident.span);
-        let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None });
-        let param = |mutbl, ty| Param {
-            attrs,
-            pat: P(Pat {
-                id: DUMMY_NODE_ID,
-                kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
-                span,
-                tokens: None,
-            }),
-            span,
-            ty,
-            id: DUMMY_NODE_ID,
-            is_placeholder: false,
-        };
-        match eself.node {
-            SelfKind::Explicit(ty, mutbl) => param(mutbl, ty),
-            SelfKind::Value(mutbl) => param(mutbl, infer_ty),
-            SelfKind::Region(lt, mutbl) => param(
-                Mutability::Not,
-                P(Ty {
-                    id: DUMMY_NODE_ID,
-                    kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }),
-                    span,
-                    tokens: None,
-                }),
-            ),
-        }
-    }
-}
-
-/// A signature (not the body) of a function declaration.
-///
-/// E.g., `fn foo(bar: baz)`.
-///
-/// Please note that it's different from `FnHeader` structure
-/// which contains metadata about function safety, asyncness, constness and ABI.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct FnDecl {
-    pub inputs: Vec,
-    pub output: FnRetTy,
-}
-
-impl FnDecl {
-    pub fn get_self(&self) -> Option {
-        self.inputs.get(0).and_then(Param::to_self)
-    }
-    pub fn has_self(&self) -> bool {
-        self.inputs.get(0).map_or(false, Param::is_self)
-    }
-    pub fn c_variadic(&self) -> bool {
-        self.inputs.last().map_or(false, |arg| matches!(arg.ty.kind, TyKind::CVarArgs))
-    }
-}
-
-/// Is the trait definition an auto trait?
-#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum IsAuto {
-    Yes,
-    No,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug)]
-#[derive(HashStable_Generic)]
-pub enum Unsafe {
-    Yes(Span),
-    No,
-}
-
-#[derive(Copy, Clone, Encodable, Decodable, Debug)]
-pub enum Async {
-    Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
-    No,
-}
-
-impl Async {
-    pub fn is_async(self) -> bool {
-        matches!(self, Async::Yes { .. })
-    }
-
-    /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
-    pub fn opt_return_id(self) -> Option {
-        match self {
-            Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id),
-            Async::No => None,
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
-#[derive(HashStable_Generic)]
-pub enum Const {
-    Yes(Span),
-    No,
-}
-
-/// Item defaultness.
-/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
-#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum Defaultness {
-    Default(Span),
-    Final,
-}
-
-#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
-pub enum ImplPolarity {
-    /// `impl Trait for Type`
-    Positive,
-    /// `impl !Trait for Type`
-    Negative(Span),
-}
-
-impl fmt::Debug for ImplPolarity {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            ImplPolarity::Positive => "positive".fmt(f),
-            ImplPolarity::Negative(_) => "negative".fmt(f),
-        }
-    }
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum FnRetTy {
-    /// Returns type is not specified.
-    ///
-    /// Functions default to `()` and closures default to inference.
-    /// Span points to where return type would be inserted.
-    Default(Span),
-    /// Everything else.
-    Ty(P),
-}
-
-impl FnRetTy {
-    pub fn span(&self) -> Span {
-        match *self {
-            FnRetTy::Default(span) => span,
-            FnRetTy::Ty(ref ty) => ty.span,
-        }
-    }
-}
-
-/// Module declaration.
-///
-/// E.g., `mod foo;` or `mod foo { .. }`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Mod {
-    /// A span from the first token past `{` to the last token until `}`.
-    /// For `mod foo;`, the inner span ranges from the first token
-    /// to the last token in the external file.
-    pub inner: Span,
-    /// `unsafe` keyword accepted syntactically for macro DSLs, but not
-    /// semantically by Rust.
-    pub unsafety: Unsafe,
-    pub items: Vec>,
-    /// `true` for `mod foo { .. }`; `false` for `mod foo;`.
-    pub inline: bool,
-}
-
-/// Foreign module declaration.
-///
-/// E.g., `extern { .. }` or `extern "C" { .. }`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct ForeignMod {
-    /// `unsafe` keyword accepted syntactically for macro DSLs, but not
-    /// semantically by Rust.
-    pub unsafety: Unsafe,
-    pub abi: Option,
-    pub items: Vec>,
-}
-
-/// Global inline assembly.
-///
-/// Also known as "module-level assembly" or "file-scoped assembly".
-#[derive(Clone, Encodable, Decodable, Debug, Copy)]
-pub struct GlobalAsm {
-    pub asm: Symbol,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct EnumDef {
-    pub variants: Vec,
-}
-/// Enum variant.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Variant {
-    /// Attributes of the variant.
-    pub attrs: Vec,
-    /// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
-    pub id: NodeId,
-    /// Span
-    pub span: Span,
-    /// The visibility of the variant. Syntactically accepted but not semantically.
-    pub vis: Visibility,
-    /// Name of the variant.
-    pub ident: Ident,
-
-    /// Fields and constructor id of the variant.
-    pub data: VariantData,
-    /// Explicit discriminant, e.g., `Foo = 1`.
-    pub disr_expr: Option,
-    /// Is a macro placeholder
-    pub is_placeholder: bool,
-}
-
-/// Part of `use` item to the right of its prefix.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum UseTreeKind {
-    /// `use prefix` or `use prefix as rename`
-    ///
-    /// The extra `NodeId`s are for HIR lowering, when additional statements are created for each
-    /// namespace.
-    Simple(Option, NodeId, NodeId),
-    /// `use prefix::{...}`
-    Nested(Vec<(UseTree, NodeId)>),
-    /// `use prefix::*`
-    Glob,
-}
-
-/// A tree of paths sharing common prefixes.
-/// Used in `use` items both at top-level and inside of braces in import groups.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct UseTree {
-    pub prefix: Path,
-    pub kind: UseTreeKind,
-    pub span: Span,
-}
-
-impl UseTree {
-    pub fn ident(&self) -> Ident {
-        match self.kind {
-            UseTreeKind::Simple(Some(rename), ..) => rename,
-            UseTreeKind::Simple(None, ..) => {
-                self.prefix.segments.last().expect("empty prefix in a simple import").ident
-            }
-            _ => panic!("`UseTree::ident` can only be used on a simple import"),
-        }
-    }
-}
-
-/// Distinguishes between `Attribute`s that decorate items and Attributes that
-/// are contained as statements within items. These two cases need to be
-/// distinguished for pretty-printing.
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
-pub enum AttrStyle {
-    Outer,
-    Inner,
-}
-
-rustc_index::newtype_index! {
-    pub struct AttrId {
-        ENCODABLE = custom
-        DEBUG_FORMAT = "AttrId({})"
-    }
-}
-
-impl rustc_serialize::Encodable for AttrId {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_unit()
-    }
-}
-
-impl rustc_serialize::Decodable for AttrId {
-    fn decode(d: &mut D) -> Result {
-        d.read_nil().map(|_| crate::attr::mk_attr_id())
-    }
-}
-
-#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
-pub struct AttrItem {
-    pub path: Path,
-    pub args: MacArgs,
-    pub tokens: Option,
-}
-
-/// A list of attributes.
-pub type AttrVec = ThinVec;
-
-/// Metadata associated with an item.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Attribute {
-    pub kind: AttrKind,
-    pub id: AttrId,
-    /// Denotes if the attribute decorates the following construct (outer)
-    /// or the construct this attribute is contained within (inner).
-    pub style: AttrStyle,
-    pub span: Span,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum AttrKind {
-    /// A normal attribute.
-    Normal(AttrItem, Option),
-
-    /// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`).
-    /// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
-    /// variant (which is much less compact and thus more expensive).
-    DocComment(CommentKind, Symbol),
-}
-
-/// `TraitRef`s appear in impls.
-///
-/// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all
-/// that the `ref_id` is for. The `impl_id` maps to the "self type" of this impl.
-/// If this impl is an `ItemKind::Impl`, the `impl_id` is redundant (it could be the
-/// same as the impl's `NodeId`).
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TraitRef {
-    pub path: Path,
-    pub ref_id: NodeId,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct PolyTraitRef {
-    /// The `'a` in `<'a> Foo<&'a T>`.
-    pub bound_generic_params: Vec,
-
-    /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`.
-    pub trait_ref: TraitRef,
-
-    pub span: Span,
-}
-
-impl PolyTraitRef {
-    pub fn new(generic_params: Vec, path: Path, span: Span) -> Self {
-        PolyTraitRef {
-            bound_generic_params: generic_params,
-            trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID },
-            span,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum CrateSugar {
-    /// Source is `pub(crate)`.
-    PubCrate,
-
-    /// Source is (just) `crate`.
-    JustCrate,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Visibility {
-    pub kind: VisibilityKind,
-    pub span: Span,
-    pub tokens: Option,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum VisibilityKind {
-    Public,
-    Crate(CrateSugar),
-    Restricted { path: P, id: NodeId },
-    Inherited,
-}
-
-impl VisibilityKind {
-    pub fn is_pub(&self) -> bool {
-        matches!(self, VisibilityKind::Public)
-    }
-}
-
-/// Field of a struct.
-///
-/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct StructField {
-    pub attrs: Vec,
-    pub id: NodeId,
-    pub span: Span,
-    pub vis: Visibility,
-    pub ident: Option,
-
-    pub ty: P,
-    pub is_placeholder: bool,
-}
-
-/// Fields and constructor ids of enum variants and structs.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum VariantData {
-    /// Struct variant.
-    ///
-    /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
-    Struct(Vec, bool),
-    /// Tuple variant.
-    ///
-    /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
-    Tuple(Vec, NodeId),
-    /// Unit variant.
-    ///
-    /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
-    Unit(NodeId),
-}
-
-impl VariantData {
-    /// Return the fields of this variant.
-    pub fn fields(&self) -> &[StructField] {
-        match *self {
-            VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields,
-            _ => &[],
-        }
-    }
-
-    /// Return the `NodeId` of this variant's constructor, if it has one.
-    pub fn ctor_id(&self) -> Option {
-        match *self {
-            VariantData::Struct(..) => None,
-            VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
-        }
-    }
-}
-
-/// An item definition.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct Item {
-    pub attrs: Vec,
-    pub id: NodeId,
-    pub span: Span,
-    pub vis: Visibility,
-    /// The name of the item.
-    /// It might be a dummy name in case of anonymous items.
-    pub ident: Ident,
-
-    pub kind: K,
-
-    /// Original tokens this item was parsed from. This isn't necessarily
-    /// available for all items, although over time more and more items should
-    /// have this be `Some`. Right now this is primarily used for procedural
-    /// macros, notably custom attributes.
-    ///
-    /// Note that the tokens here do not include the outer attributes, but will
-    /// include inner attributes.
-    pub tokens: Option,
-}
-
-impl Item {
-    /// Return the span that encompasses the attributes.
-    pub fn span_with_attributes(&self) -> Span {
-        self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span))
-    }
-}
-
-impl> Item {
-    pub fn into_item(self) -> Item {
-        let Item { attrs, id, span, vis, ident, kind, tokens } = self;
-        Item { attrs, id, span, vis, ident, kind: kind.into(), tokens }
-    }
-}
-
-/// `extern` qualifier on a function item or function type.
-#[derive(Clone, Copy, Encodable, Decodable, Debug)]
-pub enum Extern {
-    None,
-    Implicit,
-    Explicit(StrLit),
-}
-
-impl Extern {
-    pub fn from_abi(abi: Option) -> Extern {
-        abi.map_or(Extern::Implicit, Extern::Explicit)
-    }
-}
-
-/// A function header.
-///
-/// All the information between the visibility and the name of the function is
-/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
-#[derive(Clone, Copy, Encodable, Decodable, Debug)]
-pub struct FnHeader {
-    pub unsafety: Unsafe,
-    pub asyncness: Async,
-    pub constness: Const,
-    pub ext: Extern,
-}
-
-impl FnHeader {
-    /// Does this function header have any qualifiers or is it empty?
-    pub fn has_qualifiers(&self) -> bool {
-        let Self { unsafety, asyncness, constness, ext } = self;
-        matches!(unsafety, Unsafe::Yes(_))
-            || asyncness.is_async()
-            || matches!(constness, Const::Yes(_))
-            || !matches!(ext, Extern::None)
-    }
-}
-
-impl Default for FnHeader {
-    fn default() -> FnHeader {
-        FnHeader {
-            unsafety: Unsafe::No,
-            asyncness: Async::No,
-            constness: Const::No,
-            ext: Extern::None,
-        }
-    }
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TraitKind(
-    pub IsAuto,
-    pub Unsafe,
-    pub Generics,
-    pub GenericBounds,
-    pub Vec>,
-);
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TyAliasKind(pub Defaultness, pub Generics, pub GenericBounds, pub Option>);
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct ImplKind {
-    pub unsafety: Unsafe,
-    pub polarity: ImplPolarity,
-    pub defaultness: Defaultness,
-    pub constness: Const,
-    pub generics: Generics,
-
-    /// The trait being implemented, if any.
-    pub of_trait: Option,
-
-    pub self_ty: P,
-    pub items: Vec>,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct FnKind(pub Defaultness, pub FnSig, pub Generics, pub Option>);
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum ItemKind {
-    /// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
-    ///
-    /// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
-    ExternCrate(Option),
-    /// A use declaration item (`use`).
-    ///
-    /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`.
-    Use(P),
-    /// A static item (`static`).
-    ///
-    /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`.
-    Static(P, Mutability, Option>),
-    /// A constant item (`const`).
-    ///
-    /// E.g., `const FOO: i32 = 42;`.
-    Const(Defaultness, P, Option>),
-    /// A function declaration (`fn`).
-    ///
-    /// E.g., `fn foo(bar: usize) -> usize { .. }`.
-    Fn(Box),
-    /// A module declaration (`mod`).
-    ///
-    /// E.g., `mod foo;` or `mod foo { .. }`.
-    Mod(Mod),
-    /// An external module (`extern`).
-    ///
-    /// E.g., `extern {}` or `extern "C" {}`.
-    ForeignMod(ForeignMod),
-    /// Module-level inline assembly (from `global_asm!()`).
-    GlobalAsm(P),
-    /// A type alias (`type`).
-    ///
-    /// E.g., `type Foo = Bar;`.
-    TyAlias(Box),
-    /// An enum definition (`enum`).
-    ///
-    /// E.g., `enum Foo { C, D }`.
-    Enum(EnumDef, Generics),
-    /// A struct definition (`struct`).
-    ///
-    /// E.g., `struct Foo { x: A }`.
-    Struct(VariantData, Generics),
-    /// A union definition (`union`).
-    ///
-    /// E.g., `union Foo { x: A, y: B }`.
-    Union(VariantData, Generics),
-    /// A trait declaration (`trait`).
-    ///
-    /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`.
-    Trait(Box),
-    /// Trait alias
-    ///
-    /// E.g., `trait Foo = Bar + Quux;`.
-    TraitAlias(Generics, GenericBounds),
-    /// An implementation.
-    ///
-    /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`.
-    Impl(Box),
-    /// A macro invocation.
-    ///
-    /// E.g., `foo!(..)`.
-    MacCall(MacCall),
-
-    /// A macro definition.
-    MacroDef(MacroDef),
-}
-
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(ItemKind, 112);
-
-impl ItemKind {
-    pub fn article(&self) -> &str {
-        use ItemKind::*;
-        match self {
-            Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
-            | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a",
-            ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
-        }
-    }
-
-    pub fn descr(&self) -> &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::Enum(..) => "enum",
-            ItemKind::Struct(..) => "struct",
-            ItemKind::Union(..) => "union",
-            ItemKind::Trait(..) => "trait",
-            ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::MacCall(..) => "item macro invocation",
-            ItemKind::MacroDef(..) => "macro definition",
-            ItemKind::Impl { .. } => "implementation",
-        }
-    }
-
-    pub fn generics(&self) -> Option<&Generics> {
-        match self {
-            Self::Fn(box FnKind(_, _, generics, _))
-            | Self::TyAlias(box TyAliasKind(_, generics, ..))
-            | Self::Enum(_, generics)
-            | Self::Struct(_, generics)
-            | Self::Union(_, generics)
-            | Self::Trait(box TraitKind(_, _, generics, ..))
-            | Self::TraitAlias(generics, _)
-            | Self::Impl(box ImplKind { generics, .. }) => Some(generics),
-            _ => None,
-        }
-    }
-}
-
-/// Represents associated items.
-/// These include items in `impl` and `trait` definitions.
-pub type AssocItem = Item;
-
-/// Represents associated item kinds.
-///
-/// The term "provided" in the variants below refers to the item having a default
-/// definition / body. Meanwhile, a "required" item lacks a definition / body.
-/// In an implementation, all items must be provided.
-/// The `Option`s below denote the bodies, where `Some(_)`
-/// means "provided" and conversely `None` means "required".
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum AssocItemKind {
-    /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
-    /// If `def` is parsed, then the constant is provided, and otherwise required.
-    Const(Defaultness, P, Option>),
-    /// An associated function.
-    Fn(Box),
-    /// An associated type.
-    TyAlias(Box),
-    /// A macro expanding to associated items.
-    MacCall(MacCall),
-}
-
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(AssocItemKind, 72);
-
-impl AssocItemKind {
-    pub fn defaultness(&self) -> Defaultness {
-        match *self {
-            Self::Const(def, ..)
-            | Self::Fn(box FnKind(def, ..))
-            | Self::TyAlias(box TyAliasKind(def, ..)) => def,
-            Self::MacCall(..) => Defaultness::Final,
-        }
-    }
-}
-
-impl From for ItemKind {
-    fn from(assoc_item_kind: AssocItemKind) -> ItemKind {
-        match assoc_item_kind {
-            AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
-            AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
-            AssocItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
-            AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
-        }
-    }
-}
-
-impl TryFrom for AssocItemKind {
-    type Error = ItemKind;
-
-    fn try_from(item_kind: ItemKind) -> Result {
-        Ok(match item_kind {
-            ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
-            ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
-            ItemKind::TyAlias(ty_alias_kind) => AssocItemKind::TyAlias(ty_alias_kind),
-            ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
-            _ => return Err(item_kind),
-        })
-    }
-}
-
-/// An item in `extern` block.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum ForeignItemKind {
-    /// A foreign static item (`static FOO: u8`).
-    Static(P, Mutability, Option>),
-    /// An foreign function.
-    Fn(Box),
-    /// An foreign type.
-    TyAlias(Box),
-    /// A macro expanding to foreign items.
-    MacCall(MacCall),
-}
-
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(ForeignItemKind, 72);
-
-impl From for ItemKind {
-    fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
-        match foreign_item_kind {
-            ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
-            ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
-            ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
-            ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
-        }
-    }
-}
-
-impl TryFrom for ForeignItemKind {
-    type Error = ItemKind;
-
-    fn try_from(item_kind: ItemKind) -> Result {
-        Ok(match item_kind {
-            ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
-            ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
-            ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
-            ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
-            _ => return Err(item_kind),
-        })
-    }
-}
-
-pub type ForeignItem = Item;
-
-pub trait HasTokens {
-    /// Called by `Parser::collect_tokens` to store the collected
-    /// tokens inside an AST node
-    fn finalize_tokens(&mut self, tokens: LazyTokenStream);
-}
-
-impl HasTokens for P {
-    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
-        (**self).finalize_tokens(tokens);
-    }
-}
-
-impl HasTokens for Option {
-    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
-        if let Some(inner) = self {
-            inner.finalize_tokens(tokens);
-        }
-    }
-}
-
-impl HasTokens for Attribute {
-    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
-        match &mut self.kind {
-            AttrKind::Normal(_, attr_tokens) => {
-                if attr_tokens.is_none() {
-                    *attr_tokens = Some(tokens);
-                }
-            }
-            AttrKind::DocComment(..) => {
-                panic!("Called finalize_tokens on doc comment attr {:?}", self)
-            }
-        }
-    }
-}
-
-impl HasTokens for Stmt {
-    fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
-        let stmt_tokens = match self.kind {
-            StmtKind::Local(ref mut local) => &mut local.tokens,
-            StmtKind::Item(ref mut item) => &mut item.tokens,
-            StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => &mut expr.tokens,
-            StmtKind::Empty => return,
-            StmtKind::MacCall(ref mut mac) => &mut mac.tokens,
-        };
-        if stmt_tokens.is_none() {
-            *stmt_tokens = Some(tokens);
-        }
-    }
-}
-
-macro_rules! derive_has_tokens {
-    ($($ty:path),*) => { $(
-        impl HasTokens for $ty {
-            fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
-                if self.tokens.is_none() {
-                    self.tokens = Some(tokens);
-                }
-            }
-        }
-    )* }
-}
-
-derive_has_tokens! {
-    Item, Expr, Ty, AttrItem, Visibility, Path, Block, Pat
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/ast/tests.rs b/vendor/rustc-ap-rustc_ast/src/ast/tests.rs
deleted file mode 100644
index 8ba55bf037..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/ast/tests.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-use super::*;
-
-// Are ASTs encodable?
-#[test]
-fn check_asts_encodable() {
-    fn assert_encodable<
-        T: for<'a> rustc_serialize::Encodable>,
-    >() {
-    }
-    assert_encodable::();
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/attr/mod.rs b/vendor/rustc-ap-rustc_ast/src/attr/mod.rs
deleted file mode 100644
index 4dcbe4831b..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/attr/mod.rs
+++ /dev/null
@@ -1,717 +0,0 @@
-//! Functions dealing with attributes and meta items.
-
-use crate::ast;
-use crate::ast::{AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
-use crate::ast::{Expr, GenericParam, Item, Lit, LitKind, Local, Stmt, StmtKind};
-use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
-use crate::ast::{Path, PathSegment};
-use crate::mut_visit::visit_clobber;
-use crate::ptr::P;
-use crate::token::{self, CommentKind, Token};
-use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree, TreeAndSpacing};
-
-use rustc_index::bit_set::GrowableBitSet;
-use rustc_span::source_map::{BytePos, Spanned};
-use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::Span;
-
-use std::iter;
-
-pub struct MarkedAttrs(GrowableBitSet);
-
-impl MarkedAttrs {
-    // We have no idea how many attributes there will be, so just
-    // initiate the vectors with 0 bits. We'll grow them as necessary.
-    pub fn new() -> Self {
-        MarkedAttrs(GrowableBitSet::new_empty())
-    }
-
-    pub fn mark(&mut self, attr: &Attribute) {
-        self.0.insert(attr.id);
-    }
-
-    pub fn is_marked(&self, attr: &Attribute) -> bool {
-        self.0.contains(attr.id)
-    }
-}
-
-pub fn is_known_lint_tool(m_item: Ident) -> bool {
-    [sym::clippy, sym::rustc].contains(&m_item.name)
-}
-
-impl NestedMetaItem {
-    /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
-    pub fn meta_item(&self) -> Option<&MetaItem> {
-        match *self {
-            NestedMetaItem::MetaItem(ref item) => Some(item),
-            _ => None,
-        }
-    }
-
-    /// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s.
-    pub fn literal(&self) -> Option<&Lit> {
-        match *self {
-            NestedMetaItem::Literal(ref lit) => Some(lit),
-            _ => None,
-        }
-    }
-
-    /// Returns `true` if this list item is a MetaItem with a name of `name`.
-    pub fn has_name(&self, name: Symbol) -> bool {
-        self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
-    }
-
-    /// For a single-segment meta item, returns its name; otherwise, returns `None`.
-    pub fn ident(&self) -> Option {
-        self.meta_item().and_then(|meta_item| meta_item.ident())
-    }
-    pub fn name_or_empty(&self) -> Symbol {
-        self.ident().unwrap_or_else(Ident::invalid).name
-    }
-
-    /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
-    /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
-    pub fn value_str(&self) -> Option {
-        self.meta_item().and_then(|meta_item| meta_item.value_str())
-    }
-
-    /// Returns a name and single literal value tuple of the `MetaItem`.
-    pub fn name_value_literal(&self) -> Option<(Symbol, &Lit)> {
-        self.meta_item().and_then(|meta_item| {
-            meta_item.meta_item_list().and_then(|meta_item_list| {
-                if meta_item_list.len() == 1 {
-                    if let Some(ident) = meta_item.ident() {
-                        if let Some(lit) = meta_item_list[0].literal() {
-                            return Some((ident.name, lit));
-                        }
-                    }
-                }
-                None
-            })
-        })
-    }
-
-    /// Gets a list of inner meta items from a list `MetaItem` type.
-    pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
-        self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
-    }
-
-    /// Returns `true` if the variant is `MetaItem`.
-    pub fn is_meta_item(&self) -> bool {
-        self.meta_item().is_some()
-    }
-
-    /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
-    pub fn is_word(&self) -> bool {
-        self.meta_item().map_or(false, |meta_item| meta_item.is_word())
-    }
-
-    /// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`.
-    pub fn is_value_str(&self) -> bool {
-        self.value_str().is_some()
-    }
-
-    /// Returns `true` if `self` is a `MetaItem` and the meta item is a list.
-    pub fn is_meta_item_list(&self) -> bool {
-        self.meta_item_list().is_some()
-    }
-
-    pub fn name_value_literal_span(&self) -> Option {
-        self.meta_item()?.name_value_literal_span()
-    }
-}
-
-impl Attribute {
-    pub fn has_name(&self, name: Symbol) -> bool {
-        match self.kind {
-            AttrKind::Normal(ref item, _) => item.path == name,
-            AttrKind::DocComment(..) => false,
-        }
-    }
-
-    /// For a single-segment attribute, returns its name; otherwise, returns `None`.
-    pub fn ident(&self) -> Option {
-        match self.kind {
-            AttrKind::Normal(ref item, _) => {
-                if item.path.segments.len() == 1 {
-                    Some(item.path.segments[0].ident)
-                } else {
-                    None
-                }
-            }
-            AttrKind::DocComment(..) => None,
-        }
-    }
-    pub fn name_or_empty(&self) -> Symbol {
-        self.ident().unwrap_or_else(Ident::invalid).name
-    }
-
-    pub fn value_str(&self) -> Option {
-        match self.kind {
-            AttrKind::Normal(ref item, _) => item.meta(self.span).and_then(|meta| meta.value_str()),
-            AttrKind::DocComment(..) => None,
-        }
-    }
-
-    pub fn meta_item_list(&self) -> Option> {
-        match self.kind {
-            AttrKind::Normal(ref item, _) => match item.meta(self.span) {
-                Some(MetaItem { kind: MetaItemKind::List(list), .. }) => Some(list),
-                _ => None,
-            },
-            AttrKind::DocComment(..) => None,
-        }
-    }
-
-    pub fn is_word(&self) -> bool {
-        if let AttrKind::Normal(item, _) = &self.kind {
-            matches!(item.args, MacArgs::Empty)
-        } else {
-            false
-        }
-    }
-
-    pub fn is_meta_item_list(&self) -> bool {
-        self.meta_item_list().is_some()
-    }
-
-    /// Indicates if the attribute is a `ValueString`.
-    pub fn is_value_str(&self) -> bool {
-        self.value_str().is_some()
-    }
-
-    /// This is used in case you want the value span instead of the whole attribute. Example:
-    ///
-    /// ```text
-    /// #[doc(alias = "foo")]
-    /// ```
-    ///
-    /// In here, it'll return a span for `"foo"`.
-    pub fn name_value_literal_span(&self) -> Option {
-        match self.kind {
-            AttrKind::Normal(ref item, _) => {
-                item.meta(self.span).and_then(|meta| meta.name_value_literal_span())
-            }
-            AttrKind::DocComment(..) => None,
-        }
-    }
-}
-
-impl MetaItem {
-    /// For a single-segment meta item, returns its name; otherwise, returns `None`.
-    pub fn ident(&self) -> Option {
-        if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
-    }
-    pub fn name_or_empty(&self) -> Symbol {
-        self.ident().unwrap_or_else(Ident::invalid).name
-    }
-
-    // Example:
-    //     #[attribute(name = "value")]
-    //                 ^^^^^^^^^^^^^^
-    pub fn name_value_literal(&self) -> Option<&Lit> {
-        match &self.kind {
-            MetaItemKind::NameValue(v) => Some(v),
-            _ => None,
-        }
-    }
-
-    pub fn value_str(&self) -> Option {
-        match self.kind {
-            MetaItemKind::NameValue(ref v) => match v.kind {
-                LitKind::Str(ref s, _) => Some(*s),
-                _ => None,
-            },
-            _ => None,
-        }
-    }
-
-    pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
-        match self.kind {
-            MetaItemKind::List(ref l) => Some(&l[..]),
-            _ => None,
-        }
-    }
-
-    pub fn is_word(&self) -> bool {
-        matches!(self.kind, MetaItemKind::Word)
-    }
-
-    pub fn has_name(&self, name: Symbol) -> bool {
-        self.path == name
-    }
-
-    pub fn is_value_str(&self) -> bool {
-        self.value_str().is_some()
-    }
-
-    /// This is used in case you want the value span instead of the whole attribute. Example:
-    ///
-    /// ```text
-    /// #[doc(alias = "foo")]
-    /// ```
-    ///
-    /// In here, it'll return a span for `"foo"`.
-    pub fn name_value_literal_span(&self) -> Option {
-        Some(self.name_value_literal()?.span)
-    }
-}
-
-impl AttrItem {
-    pub fn span(&self) -> Span {
-        self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
-    }
-
-    pub fn meta(&self, span: Span) -> Option {
-        Some(MetaItem {
-            path: self.path.clone(),
-            kind: MetaItemKind::from_mac_args(&self.args)?,
-            span,
-        })
-    }
-}
-
-impl Attribute {
-    pub fn is_doc_comment(&self) -> bool {
-        match self.kind {
-            AttrKind::Normal(..) => false,
-            AttrKind::DocComment(..) => true,
-        }
-    }
-
-    pub fn doc_str(&self) -> Option {
-        match self.kind {
-            AttrKind::DocComment(.., data) => Some(data),
-            AttrKind::Normal(ref item, _) if item.path == sym::doc => {
-                item.meta(self.span).and_then(|meta| meta.value_str())
-            }
-            _ => None,
-        }
-    }
-
-    pub fn get_normal_item(&self) -> &AttrItem {
-        match self.kind {
-            AttrKind::Normal(ref item, _) => item,
-            AttrKind::DocComment(..) => panic!("unexpected doc comment"),
-        }
-    }
-
-    pub fn unwrap_normal_item(self) -> AttrItem {
-        match self.kind {
-            AttrKind::Normal(item, _) => item,
-            AttrKind::DocComment(..) => panic!("unexpected doc comment"),
-        }
-    }
-
-    /// Extracts the MetaItem from inside this Attribute.
-    pub fn meta(&self) -> Option {
-        match self.kind {
-            AttrKind::Normal(ref item, _) => item.meta(self.span),
-            AttrKind::DocComment(..) => None,
-        }
-    }
-
-    pub fn tokens(&self) -> TokenStream {
-        match self.kind {
-            AttrKind::Normal(_, ref tokens) => tokens
-                .as_ref()
-                .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self))
-                .create_token_stream(),
-            AttrKind::DocComment(comment_kind, data) => TokenStream::from(TokenTree::Token(
-                Token::new(token::DocComment(comment_kind, self.style, data), self.span),
-            )),
-        }
-    }
-}
-
-/* Constructors */
-
-pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
-    let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked);
-    mk_name_value_item(ident, lit_kind, str_span)
-}
-
-pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem {
-    let lit = Lit::from_lit_kind(lit_kind, lit_span);
-    let span = ident.span.to(lit_span);
-    MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) }
-}
-
-pub fn mk_list_item(ident: Ident, items: Vec) -> MetaItem {
-    MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::List(items) }
-}
-
-pub fn mk_word_item(ident: Ident) -> MetaItem {
-    MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::Word }
-}
-
-pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
-    NestedMetaItem::MetaItem(mk_word_item(ident))
-}
-
-crate fn mk_attr_id() -> AttrId {
-    use std::sync::atomic::AtomicU32;
-    use std::sync::atomic::Ordering;
-
-    static NEXT_ATTR_ID: AtomicU32 = AtomicU32::new(0);
-
-    let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
-    assert!(id != u32::MAX);
-    AttrId::from_u32(id)
-}
-
-pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
-    mk_attr_from_item(AttrItem { path, args, tokens: None }, None, style, span)
-}
-
-pub fn mk_attr_from_item(
-    item: AttrItem,
-    tokens: Option,
-    style: AttrStyle,
-    span: Span,
-) -> Attribute {
-    Attribute { kind: AttrKind::Normal(item, tokens), id: mk_attr_id(), style, span }
-}
-
-/// Returns an inner attribute with the given value and span.
-pub fn mk_attr_inner(item: MetaItem) -> Attribute {
-    mk_attr(AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
-}
-
-/// Returns an outer attribute with the given value and span.
-pub fn mk_attr_outer(item: MetaItem) -> Attribute {
-    mk_attr(AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
-}
-
-pub fn mk_doc_comment(
-    comment_kind: CommentKind,
-    style: AttrStyle,
-    data: Symbol,
-    span: Span,
-) -> Attribute {
-    Attribute { kind: AttrKind::DocComment(comment_kind, data), id: mk_attr_id(), style, span }
-}
-
-pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
-    items.iter().any(|item| item.has_name(name))
-}
-
-impl MetaItem {
-    fn token_trees_and_spacings(&self) -> Vec {
-        let mut idents = vec![];
-        let mut last_pos = BytePos(0_u32);
-        for (i, segment) in self.path.segments.iter().enumerate() {
-            let is_first = i == 0;
-            if !is_first {
-                let mod_sep_span =
-                    Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt());
-                idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
-            }
-            idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
-            last_pos = segment.ident.span.hi();
-        }
-        idents.extend(self.kind.token_trees_and_spacings(self.span));
-        idents
-    }
-
-    fn from_tokens(tokens: &mut iter::Peekable) -> Option
-    where
-        I: Iterator,
-    {
-        // FIXME: Share code with `parse_path`.
-        let path = match tokens.next().map(TokenTree::uninterpolate) {
-            Some(TokenTree::Token(Token {
-                kind: kind @ (token::Ident(..) | token::ModSep),
-                span,
-            })) => 'arm: {
-                let mut segments = if let token::Ident(name, _) = kind {
-                    if let Some(TokenTree::Token(Token { kind: token::ModSep, .. })) = tokens.peek()
-                    {
-                        tokens.next();
-                        vec![PathSegment::from_ident(Ident::new(name, span))]
-                    } else {
-                        break 'arm Path::from_ident(Ident::new(name, span));
-                    }
-                } else {
-                    vec![PathSegment::path_root(span)]
-                };
-                loop {
-                    if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) =
-                        tokens.next().map(TokenTree::uninterpolate)
-                    {
-                        segments.push(PathSegment::from_ident(Ident::new(name, span)));
-                    } else {
-                        return None;
-                    }
-                    if let Some(TokenTree::Token(Token { kind: token::ModSep, .. })) = tokens.peek()
-                    {
-                        tokens.next();
-                    } else {
-                        break;
-                    }
-                }
-                let span = span.with_hi(segments.last().unwrap().ident.span.hi());
-                Path { span, segments, tokens: None }
-            }
-            Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt {
-                token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span),
-                token::Nonterminal::NtPath(ref path) => path.clone(),
-                _ => return None,
-            },
-            _ => return None,
-        };
-        let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi());
-        let kind = MetaItemKind::from_tokens(tokens)?;
-        let hi = match kind {
-            MetaItemKind::NameValue(ref lit) => lit.span.hi(),
-            MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()),
-            _ => path.span.hi(),
-        };
-        let span = path.span.with_hi(hi);
-        Some(MetaItem { path, kind, span })
-    }
-}
-
-impl MetaItemKind {
-    pub fn mac_args(&self, span: Span) -> MacArgs {
-        match self {
-            MetaItemKind::Word => MacArgs::Empty,
-            MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.to_token()),
-            MetaItemKind::List(list) => {
-                let mut tts = Vec::new();
-                for (i, item) in list.iter().enumerate() {
-                    if i > 0 {
-                        tts.push(TokenTree::token(token::Comma, span).into());
-                    }
-                    tts.extend(item.token_trees_and_spacings())
-                }
-                MacArgs::Delimited(
-                    DelimSpan::from_single(span),
-                    MacDelimiter::Parenthesis,
-                    TokenStream::new(tts),
-                )
-            }
-        }
-    }
-
-    fn token_trees_and_spacings(&self, span: Span) -> Vec {
-        match *self {
-            MetaItemKind::Word => vec![],
-            MetaItemKind::NameValue(ref lit) => {
-                vec![
-                    TokenTree::token(token::Eq, span).into(),
-                    TokenTree::Token(lit.to_token()).into(),
-                ]
-            }
-            MetaItemKind::List(ref list) => {
-                let mut tokens = Vec::new();
-                for (i, item) in list.iter().enumerate() {
-                    if i > 0 {
-                        tokens.push(TokenTree::token(token::Comma, span).into());
-                    }
-                    tokens.extend(item.token_trees_and_spacings())
-                }
-                vec![
-                    TokenTree::Delimited(
-                        DelimSpan::from_single(span),
-                        token::Paren,
-                        TokenStream::new(tokens),
-                    )
-                    .into(),
-                ]
-            }
-        }
-    }
-
-    fn list_from_tokens(tokens: TokenStream) -> Option {
-        let mut tokens = tokens.into_trees().peekable();
-        let mut result = Vec::new();
-        while tokens.peek().is_some() {
-            let item = NestedMetaItem::from_tokens(&mut tokens)?;
-            result.push(item);
-            match tokens.next() {
-                None | Some(TokenTree::Token(Token { kind: token::Comma, .. })) => {}
-                _ => return None,
-            }
-        }
-        Some(MetaItemKind::List(result))
-    }
-
-    fn name_value_from_tokens(
-        tokens: &mut impl Iterator,
-    ) -> Option {
-        match tokens.next() {
-            Some(TokenTree::Delimited(_, token::NoDelim, inner_tokens)) => {
-                MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees())
-            }
-            Some(TokenTree::Token(token)) => {
-                Lit::from_token(&token).ok().map(MetaItemKind::NameValue)
-            }
-            _ => None,
-        }
-    }
-
-    fn from_mac_args(args: &MacArgs) -> Option {
-        match args {
-            MacArgs::Delimited(_, MacDelimiter::Parenthesis, tokens) => {
-                MetaItemKind::list_from_tokens(tokens.clone())
-            }
-            MacArgs::Delimited(..) => None,
-            MacArgs::Eq(_, token) => Lit::from_token(token).ok().map(MetaItemKind::NameValue),
-            MacArgs::Empty => Some(MetaItemKind::Word),
-        }
-    }
-
-    fn from_tokens(
-        tokens: &mut iter::Peekable>,
-    ) -> Option {
-        match tokens.peek() {
-            Some(TokenTree::Delimited(_, token::Paren, inner_tokens)) => {
-                let inner_tokens = inner_tokens.clone();
-                tokens.next();
-                MetaItemKind::list_from_tokens(inner_tokens)
-            }
-            Some(TokenTree::Delimited(..)) => None,
-            Some(TokenTree::Token(Token { kind: token::Eq, .. })) => {
-                tokens.next();
-                MetaItemKind::name_value_from_tokens(tokens)
-            }
-            _ => Some(MetaItemKind::Word),
-        }
-    }
-}
-
-impl NestedMetaItem {
-    pub fn span(&self) -> Span {
-        match *self {
-            NestedMetaItem::MetaItem(ref item) => item.span,
-            NestedMetaItem::Literal(ref lit) => lit.span,
-        }
-    }
-
-    fn token_trees_and_spacings(&self) -> Vec {
-        match *self {
-            NestedMetaItem::MetaItem(ref item) => item.token_trees_and_spacings(),
-            NestedMetaItem::Literal(ref lit) => vec![TokenTree::Token(lit.to_token()).into()],
-        }
-    }
-
-    fn from_tokens(tokens: &mut iter::Peekable) -> Option
-    where
-        I: Iterator,
-    {
-        match tokens.peek() {
-            Some(TokenTree::Token(token)) => {
-                if let Ok(lit) = Lit::from_token(token) {
-                    tokens.next();
-                    return Some(NestedMetaItem::Literal(lit));
-                }
-            }
-            Some(TokenTree::Delimited(_, token::NoDelim, inner_tokens)) => {
-                let inner_tokens = inner_tokens.clone();
-                tokens.next();
-                return NestedMetaItem::from_tokens(&mut inner_tokens.into_trees().peekable());
-            }
-            _ => {}
-        }
-        MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem)
-    }
-}
-
-pub trait HasAttrs: Sized {
-    fn attrs(&self) -> &[Attribute];
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec));
-}
-
-impl HasAttrs for Spanned {
-    fn attrs(&self) -> &[Attribute] {
-        self.node.attrs()
-    }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) {
-        self.node.visit_attrs(f);
-    }
-}
-
-impl HasAttrs for Vec {
-    fn attrs(&self) -> &[Attribute] {
-        self
-    }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) {
-        f(self)
-    }
-}
-
-impl HasAttrs for AttrVec {
-    fn attrs(&self) -> &[Attribute] {
-        self
-    }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) {
-        visit_clobber(self, |this| {
-            let mut vec = this.into();
-            f(&mut vec);
-            vec.into()
-        });
-    }
-}
-
-impl HasAttrs for P {
-    fn attrs(&self) -> &[Attribute] {
-        (**self).attrs()
-    }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) {
-        (**self).visit_attrs(f);
-    }
-}
-
-impl HasAttrs for StmtKind {
-    fn attrs(&self) -> &[Attribute] {
-        match *self {
-            StmtKind::Local(ref local) => local.attrs(),
-            StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(),
-            StmtKind::Item(ref item) => item.attrs(),
-            StmtKind::Empty => &[],
-            StmtKind::MacCall(ref mac) => mac.attrs.attrs(),
-        }
-    }
-
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) {
-        match self {
-            StmtKind::Local(local) => local.visit_attrs(f),
-            StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
-            StmtKind::Item(item) => item.visit_attrs(f),
-            StmtKind::Empty => {}
-            StmtKind::MacCall(mac) => {
-                mac.attrs.visit_attrs(f);
-            }
-        }
-    }
-}
-
-impl HasAttrs for Stmt {
-    fn attrs(&self) -> &[ast::Attribute] {
-        self.kind.attrs()
-    }
-
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) {
-        self.kind.visit_attrs(f);
-    }
-}
-
-macro_rules! derive_has_attrs {
-    ($($ty:path),*) => { $(
-        impl HasAttrs for $ty {
-            fn attrs(&self) -> &[Attribute] {
-                &self.attrs
-            }
-
-            fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) {
-                self.attrs.visit_attrs(f);
-            }
-        }
-    )* }
-}
-
-derive_has_attrs! {
-    Item, Expr, Local, ast::AssocItem, ast::ForeignItem, ast::StructField, ast::Arm,
-    ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/crate_disambiguator.rs b/vendor/rustc-ap-rustc_ast/src/crate_disambiguator.rs
deleted file mode 100644
index bd7d851671..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/crate_disambiguator.rs
+++ /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 for CrateDisambiguator {
-    fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
-        CrateDisambiguator(fingerprint)
-    }
-}
-
-impl_stable_hash_via_hash!(CrateDisambiguator);
diff --git a/vendor/rustc-ap-rustc_ast/src/entry.rs b/vendor/rustc-ap-rustc_ast/src/entry.rs
deleted file mode 100644
index 290f6006de..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/entry.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-pub enum EntryPointType {
-    None,
-    MainNamed,
-    MainAttr,
-    Start,
-    OtherMain, // Not an entry point, but some other function named main
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/expand/allocator.rs b/vendor/rustc-ap-rustc_ast/src/expand/allocator.rs
deleted file mode 100644
index cd27f958e4..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/expand/allocator.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use rustc_span::symbol::{sym, Symbol};
-
-#[derive(Clone, Copy)]
-pub enum AllocatorKind {
-    Global,
-    Default,
-}
-
-impl AllocatorKind {
-    pub fn fn_name(&self, base: Symbol) -> String {
-        match *self {
-            AllocatorKind::Global => format!("__rg_{}", base),
-            AllocatorKind::Default => format!("__rdl_{}", base),
-        }
-    }
-}
-
-pub enum AllocatorTy {
-    Layout,
-    Ptr,
-    ResultPtr,
-    Unit,
-    Usize,
-}
-
-pub struct AllocatorMethod {
-    pub name: Symbol,
-    pub inputs: &'static [AllocatorTy],
-    pub output: AllocatorTy,
-}
-
-pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
-    AllocatorMethod {
-        name: sym::alloc,
-        inputs: &[AllocatorTy::Layout],
-        output: AllocatorTy::ResultPtr,
-    },
-    AllocatorMethod {
-        name: sym::dealloc,
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
-        output: AllocatorTy::Unit,
-    },
-    AllocatorMethod {
-        name: sym::realloc,
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
-        output: AllocatorTy::ResultPtr,
-    },
-    AllocatorMethod {
-        name: sym::alloc_zeroed,
-        inputs: &[AllocatorTy::Layout],
-        output: AllocatorTy::ResultPtr,
-    },
-];
diff --git a/vendor/rustc-ap-rustc_ast/src/expand/mod.rs b/vendor/rustc-ap-rustc_ast/src/expand/mod.rs
deleted file mode 100644
index eebfc38bdf..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/expand/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//! Definitions shared by macros / syntax extensions and e.g. librustc_middle.
-
-pub mod allocator;
diff --git a/vendor/rustc-ap-rustc_ast/src/lib.rs b/vendor/rustc-ap-rustc_ast/src/lib.rs
deleted file mode 100644
index ddf52caed0..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/lib.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-//! The Rust parser and macro expander.
-//!
-//! # Note
-//!
-//! This API is completely unstable and subject to change.
-
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
-    test(attr(deny(warnings)))
-)]
-#![feature(box_syntax)]
-#![feature(box_patterns)]
-#![feature(const_fn)] // For the `transmute` in `P::new`
-#![feature(const_fn_transmute)]
-#![feature(const_panic)]
-#![feature(crate_visibility_modifier)]
-#![feature(label_break_value)]
-#![feature(nll)]
-#![feature(or_patterns)]
-#![recursion_limit = "256"]
-
-#[macro_use]
-extern crate rustc_macros;
-
-#[macro_export]
-macro_rules! unwrap_or {
-    ($opt:expr, $default:expr) => {
-        match $opt {
-            Some(x) => x,
-            None => $default,
-        }
-    };
-}
-
-pub mod util {
-    pub mod classify;
-    pub mod comments;
-    pub mod literal;
-    pub mod parser;
-}
-
-pub mod ast;
-pub mod attr;
-pub mod crate_disambiguator;
-pub mod entry;
-pub mod expand;
-pub mod mut_visit;
-pub mod node_id;
-pub mod ptr;
-pub mod token;
-pub mod tokenstream;
-pub mod visit;
-
-pub use self::ast::*;
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-
-/// 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 librustc_middle.
-pub trait HashStableContext: rustc_span::HashStableContext {
-    fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
-}
-
-impl HashStable for ast::Attribute {
-    fn hash_stable(&self, hcx: &mut AstCtx, hasher: &mut StableHasher) {
-        hcx.hash_attr(self, hasher)
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/mut_visit.rs b/vendor/rustc-ap-rustc_ast/src/mut_visit.rs
deleted file mode 100644
index 024d9687f3..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/mut_visit.rs
+++ /dev/null
@@ -1,1366 +0,0 @@
-//! A `MutVisitor` represents an AST modification; it accepts an AST piece and
-//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor`
-//! that walks over an AST and modifies it.
-//!
-//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on
-//! an AST before macro expansion is probably a bad idea. For instance,
-//! a `MutVisitor` renaming item names in a module will miss all of those
-//! that are created by the expansion of a macro.
-
-use crate::ast::*;
-use crate::ptr::P;
-use crate::token::{self, Token};
-use crate::tokenstream::*;
-
-use rustc_data_structures::map_in_place::MapInPlace;
-use rustc_data_structures::sync::Lrc;
-use rustc_span::source_map::Spanned;
-use rustc_span::symbol::Ident;
-use rustc_span::Span;
-
-use smallvec::{smallvec, Array, SmallVec};
-use std::ops::DerefMut;
-use std::{panic, process, ptr};
-
-pub trait ExpectOne {
-    fn expect_one(self, err: &'static str) -> A::Item;
-}
-
-impl ExpectOne for SmallVec {
-    fn expect_one(self, err: &'static str) -> A::Item {
-        assert!(self.len() == 1, "{}", err);
-        self.into_iter().next().unwrap()
-    }
-}
-
-pub trait MutVisitor: Sized {
-    /// Mutable token visiting only exists for the `macro_rules` token marker and should not be
-    /// used otherwise. Token visitor would be entirely separate from the regular visitor if
-    /// the marker didn't have to visit AST fragments in nonterminal tokens.
-    fn token_visiting_enabled(&self) -> bool {
-        false
-    }
-
-    // Methods in this trait have one of three forms:
-    //
-    //   fn visit_t(&mut self, t: &mut T);                      // common
-    //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare
-    //   fn filter_map_t(&mut self, t: T) -> Option;         // rarest
-    //
-    // Any additions to this trait should happen in form of a call to a public
-    // `noop_*` function that only calls out to the visitor again, not other
-    // `noop_*` functions. This is a necessary API workaround to the problem of
-    // not being able to call out to the super default method in an overridden
-    // default method.
-    //
-    // When writing these methods, it is better to use destructuring like this:
-    //
-    //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
-    //       visit_a(a);
-    //       visit_b(b);
-    //   }
-    //
-    // than to use field access like this:
-    //
-    //   fn visit_abc(&mut self, abc: &mut ABC) {
-    //       visit_a(&mut abc.a);
-    //       visit_b(&mut abc.b);
-    //       // ignore abc.c
-    //   }
-    //
-    // As well as being more concise, the former is explicit about which fields
-    // are skipped. Furthermore, if a new field is added, the destructuring
-    // version will cause a compile error, which is good. In comparison, the
-    // field access version will continue working and it would be easy to
-    // forget to add handling for it.
-
-    fn visit_crate(&mut self, c: &mut Crate) {
-        noop_visit_crate(c, self)
-    }
-
-    fn visit_meta_list_item(&mut self, list_item: &mut NestedMetaItem) {
-        noop_visit_meta_list_item(list_item, self);
-    }
-
-    fn visit_meta_item(&mut self, meta_item: &mut MetaItem) {
-        noop_visit_meta_item(meta_item, self);
-    }
-
-    fn visit_use_tree(&mut self, use_tree: &mut UseTree) {
-        noop_visit_use_tree(use_tree, self);
-    }
-
-    fn flat_map_foreign_item(&mut self, ni: P) -> SmallVec<[P; 1]> {
-        noop_flat_map_foreign_item(ni, self)
-    }
-
-    fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> {
-        noop_flat_map_item(i, self)
-    }
-
-    fn visit_fn_header(&mut self, header: &mut FnHeader) {
-        noop_visit_fn_header(header, self);
-    }
-
-    fn flat_map_struct_field(&mut self, sf: StructField) -> SmallVec<[StructField; 1]> {
-        noop_flat_map_struct_field(sf, self)
-    }
-
-    fn visit_item_kind(&mut self, i: &mut ItemKind) {
-        noop_visit_item_kind(i, self);
-    }
-
-    fn flat_map_trait_item(&mut self, i: P) -> SmallVec<[P; 1]> {
-        noop_flat_map_assoc_item(i, self)
-    }
-
-    fn flat_map_impl_item(&mut self, i: P) -> SmallVec<[P; 1]> {
-        noop_flat_map_assoc_item(i, self)
-    }
-
-    fn visit_fn_decl(&mut self, d: &mut P) {
-        noop_visit_fn_decl(d, self);
-    }
-
-    fn visit_asyncness(&mut self, a: &mut Async) {
-        noop_visit_asyncness(a, self);
-    }
-
-    fn visit_block(&mut self, b: &mut P) {
-        noop_visit_block(b, self);
-    }
-
-    fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
-        noop_flat_map_stmt(s, self)
-    }
-
-    fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
-        noop_flat_map_arm(arm, self)
-    }
-
-    fn visit_pat(&mut self, p: &mut P) {
-        noop_visit_pat(p, self);
-    }
-
-    fn visit_anon_const(&mut self, c: &mut AnonConst) {
-        noop_visit_anon_const(c, self);
-    }
-
-    fn visit_expr(&mut self, e: &mut P) {
-        noop_visit_expr(e, self);
-    }
-
-    fn filter_map_expr(&mut self, e: P) -> Option> {
-        noop_filter_map_expr(e, self)
-    }
-
-    fn visit_generic_arg(&mut self, arg: &mut GenericArg) {
-        noop_visit_generic_arg(arg, self);
-    }
-
-    fn visit_ty(&mut self, t: &mut P) {
-        noop_visit_ty(t, self);
-    }
-
-    fn visit_lifetime(&mut self, l: &mut Lifetime) {
-        noop_visit_lifetime(l, self);
-    }
-
-    fn visit_ty_constraint(&mut self, t: &mut AssocTyConstraint) {
-        noop_visit_ty_constraint(t, self);
-    }
-
-    fn visit_mod(&mut self, m: &mut Mod) {
-        noop_visit_mod(m, self);
-    }
-
-    fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) {
-        noop_visit_foreign_mod(nm, self);
-    }
-
-    fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
-        noop_flat_map_variant(v, self)
-    }
-
-    fn visit_ident(&mut self, i: &mut Ident) {
-        noop_visit_ident(i, self);
-    }
-
-    fn visit_path(&mut self, p: &mut Path) {
-        noop_visit_path(p, self);
-    }
-
-    fn visit_qself(&mut self, qs: &mut Option) {
-        noop_visit_qself(qs, self);
-    }
-
-    fn visit_generic_args(&mut self, p: &mut GenericArgs) {
-        noop_visit_generic_args(p, self);
-    }
-
-    fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) {
-        noop_visit_angle_bracketed_parameter_data(p, self);
-    }
-
-    fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) {
-        noop_visit_parenthesized_parameter_data(p, self);
-    }
-
-    fn visit_local(&mut self, l: &mut P) {
-        noop_visit_local(l, self);
-    }
-
-    fn visit_mac_call(&mut self, mac: &mut MacCall) {
-        noop_visit_mac(mac, self);
-    }
-
-    fn visit_macro_def(&mut self, def: &mut MacroDef) {
-        noop_visit_macro_def(def, self);
-    }
-
-    fn visit_label(&mut self, label: &mut Label) {
-        noop_visit_label(label, self);
-    }
-
-    fn visit_attribute(&mut self, at: &mut Attribute) {
-        noop_visit_attribute(at, self);
-    }
-
-    fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
-        noop_flat_map_param(param, self)
-    }
-
-    fn visit_generics(&mut self, generics: &mut Generics) {
-        noop_visit_generics(generics, self);
-    }
-
-    fn visit_trait_ref(&mut self, tr: &mut TraitRef) {
-        noop_visit_trait_ref(tr, self);
-    }
-
-    fn visit_poly_trait_ref(&mut self, p: &mut PolyTraitRef) {
-        noop_visit_poly_trait_ref(p, self);
-    }
-
-    fn visit_variant_data(&mut self, vdata: &mut VariantData) {
-        noop_visit_variant_data(vdata, self);
-    }
-
-    fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
-        noop_flat_map_generic_param(param, self)
-    }
-
-    fn visit_param_bound(&mut self, tpb: &mut GenericBound) {
-        noop_visit_param_bound(tpb, self);
-    }
-
-    fn visit_mt(&mut self, mt: &mut MutTy) {
-        noop_visit_mt(mt, self);
-    }
-
-    fn flat_map_field(&mut self, f: Field) -> SmallVec<[Field; 1]> {
-        noop_flat_map_field(f, self)
-    }
-
-    fn visit_where_clause(&mut self, where_clause: &mut WhereClause) {
-        noop_visit_where_clause(where_clause, self);
-    }
-
-    fn visit_where_predicate(&mut self, where_predicate: &mut WherePredicate) {
-        noop_visit_where_predicate(where_predicate, self);
-    }
-
-    fn visit_vis(&mut self, vis: &mut Visibility) {
-        noop_visit_vis(vis, self);
-    }
-
-    fn visit_id(&mut self, _id: &mut NodeId) {
-        // Do nothing.
-    }
-
-    fn visit_span(&mut self, _sp: &mut Span) {
-        // Do nothing.
-    }
-
-    fn flat_map_field_pattern(&mut self, fp: FieldPat) -> SmallVec<[FieldPat; 1]> {
-        noop_flat_map_field_pattern(fp, self)
-    }
-}
-
-/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
-/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
-/// method. Abort the program if the closure panics.
-//
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_clobber(t: &mut T, f: F)
-where
-    F: FnOnce(T) -> T,
-{
-    unsafe {
-        // Safe because `t` is used in a read-only fashion by `read()` before
-        // being overwritten by `write()`.
-        let old_t = ptr::read(t);
-        let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t)))
-            .unwrap_or_else(|_| process::abort());
-        ptr::write(t, new_t);
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-#[inline]
-pub fn visit_vec(elems: &mut Vec, mut visit_elem: F)
-where
-    F: FnMut(&mut T),
-{
-    for elem in elems {
-        visit_elem(elem);
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-#[inline]
-pub fn visit_opt(opt: &mut Option, mut visit_elem: F)
-where
-    F: FnMut(&mut T),
-{
-    if let Some(elem) = opt {
-        visit_elem(elem);
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_attrs(attrs: &mut Vec, vis: &mut T) {
-    visit_vec(attrs, |attr| vis.visit_attribute(attr));
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_thin_attrs(attrs: &mut AttrVec, vis: &mut T) {
-    for attr in attrs.iter_mut() {
-        vis.visit_attribute(attr);
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_exprs(exprs: &mut Vec>, vis: &mut T) {
-    exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_bounds(bounds: &mut GenericBounds, vis: &mut T) {
-    visit_vec(bounds, |bound| vis.visit_param_bound(bound));
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_fn_sig(FnSig { header, decl, span }: &mut FnSig, vis: &mut T) {
-    vis.visit_fn_header(header);
-    vis.visit_fn_decl(decl);
-    vis.visit_span(span);
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_mac_args(args: &mut MacArgs, vis: &mut T) {
-    match args {
-        MacArgs::Empty => {}
-        MacArgs::Delimited(dspan, _delim, tokens) => {
-            visit_delim_span(dspan, vis);
-            visit_tts(tokens, vis);
-        }
-        MacArgs::Eq(eq_span, token) => {
-            vis.visit_span(eq_span);
-            if vis.token_visiting_enabled() {
-                visit_token(token, vis);
-            } else {
-                // The value in `#[key = VALUE]` must be visited as an expression for backward
-                // compatibility, so that macros can be expanded in that position.
-                match &mut token.kind {
-                    token::Interpolated(nt) => match Lrc::make_mut(nt) {
-                        token::NtExpr(expr) => vis.visit_expr(expr),
-                        t => panic!("unexpected token in key-value attribute: {:?}", t),
-                    },
-                    t => panic!("unexpected token in key-value attribute: {:?}", t),
-                }
-            }
-        }
-    }
-}
-
-pub fn visit_delim_span(dspan: &mut DelimSpan, vis: &mut T) {
-    vis.visit_span(&mut dspan.open);
-    vis.visit_span(&mut dspan.close);
-}
-
-pub fn noop_flat_map_field_pattern(
-    mut fp: FieldPat,
-    vis: &mut T,
-) -> SmallVec<[FieldPat; 1]> {
-    let FieldPat { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp;
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-    vis.visit_pat(pat);
-    vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
-    smallvec![fp]
-}
-
-pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) {
-    let UseTree { prefix, kind, span } = use_tree;
-    vis.visit_path(prefix);
-    match kind {
-        UseTreeKind::Simple(rename, id1, id2) => {
-            visit_opt(rename, |rename| vis.visit_ident(rename));
-            vis.visit_id(id1);
-            vis.visit_id(id2);
-        }
-        UseTreeKind::Nested(items) => {
-            for (tree, id) in items {
-                vis.visit_use_tree(tree);
-                vis.visit_id(id);
-            }
-        }
-        UseTreeKind::Glob => {}
-    }
-    vis.visit_span(span);
-}
-
-pub fn noop_flat_map_arm(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);
-    vis.visit_id(id);
-    vis.visit_pat(pat);
-    visit_opt(guard, |guard| vis.visit_expr(guard));
-    vis.visit_expr(body);
-    vis.visit_span(span);
-    smallvec![arm]
-}
-
-pub fn noop_visit_ty_constraint(
-    AssocTyConstraint { id, ident, gen_args, kind, span }: &mut AssocTyConstraint,
-    vis: &mut T,
-) {
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-    if let Some(ref mut gen_args) = gen_args {
-        vis.visit_generic_args(gen_args);
-    }
-    match kind {
-        AssocTyConstraintKind::Equality { ref mut ty } => {
-            vis.visit_ty(ty);
-        }
-        AssocTyConstraintKind::Bound { ref mut bounds } => {
-            visit_bounds(bounds, vis);
-        }
-    }
-    vis.visit_span(span);
-}
-
-pub fn noop_visit_ty(ty: &mut P, vis: &mut T) {
-    let Ty { id, kind, span, tokens } = ty.deref_mut();
-    vis.visit_id(id);
-    match kind {
-        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | TyKind::Never | TyKind::CVarArgs => {}
-        TyKind::Slice(ty) => vis.visit_ty(ty),
-        TyKind::Ptr(mt) => vis.visit_mt(mt),
-        TyKind::Rptr(lt, mt) => {
-            visit_opt(lt, |lt| noop_visit_lifetime(lt, vis));
-            vis.visit_mt(mt);
-        }
-        TyKind::BareFn(bft) => {
-            let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut();
-            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-            vis.visit_fn_decl(decl);
-        }
-        TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)),
-        TyKind::Paren(ty) => vis.visit_ty(ty),
-        TyKind::Path(qself, path) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-        }
-        TyKind::Array(ty, length) => {
-            vis.visit_ty(ty);
-            vis.visit_anon_const(length);
-        }
-        TyKind::Typeof(expr) => vis.visit_anon_const(expr),
-        TyKind::TraitObject(bounds, _syntax) => {
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound))
-        }
-        TyKind::ImplTrait(id, bounds) => {
-            vis.visit_id(id);
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound));
-        }
-        TyKind::MacCall(mac) => vis.visit_mac_call(mac),
-    }
-    vis.visit_span(span);
-    visit_lazy_tts(tokens, vis);
-}
-
-pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: &mut T) {
-    let ForeignMod { unsafety: _, abi: _, items } = foreign_mod;
-    items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
-}
-
-pub fn noop_flat_map_variant(
-    mut variant: Variant,
-    visitor: &mut T,
-) -> SmallVec<[Variant; 1]> {
-    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);
-    visitor.visit_id(id);
-    visitor.visit_variant_data(data);
-    visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
-    visitor.visit_span(span);
-    smallvec![variant]
-}
-
-pub fn noop_visit_ident(Ident { name: _, span }: &mut Ident, vis: &mut T) {
-    vis.visit_span(span);
-}
-
-pub fn noop_visit_path(Path { segments, span, tokens }: &mut Path, vis: &mut T) {
-    vis.visit_span(span);
-    for PathSegment { ident, id, args } in segments {
-        vis.visit_ident(ident);
-        vis.visit_id(id);
-        visit_opt(args, |args| vis.visit_generic_args(args));
-    }
-    visit_lazy_tts(tokens, vis);
-}
-
-pub fn noop_visit_qself(qself: &mut Option, vis: &mut T) {
-    visit_opt(qself, |QSelf { ty, path_span, position: _ }| {
-        vis.visit_ty(ty);
-        vis.visit_span(path_span);
-    })
-}
-
-pub fn noop_visit_generic_args(generic_args: &mut GenericArgs, vis: &mut T) {
-    match generic_args {
-        GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
-        GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
-    }
-}
-
-pub fn noop_visit_generic_arg(arg: &mut GenericArg, vis: &mut T) {
-    match arg {
-        GenericArg::Lifetime(lt) => vis.visit_lifetime(lt),
-        GenericArg::Type(ty) => vis.visit_ty(ty),
-        GenericArg::Const(ct) => vis.visit_anon_const(ct),
-    }
-}
-
-pub fn noop_visit_angle_bracketed_parameter_data(
-    data: &mut AngleBracketedArgs,
-    vis: &mut T,
-) {
-    let AngleBracketedArgs { args, span } = data;
-    visit_vec(args, |arg| match arg {
-        AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg),
-        AngleBracketedArg::Constraint(constraint) => vis.visit_ty_constraint(constraint),
-    });
-    vis.visit_span(span);
-}
-
-pub fn noop_visit_parenthesized_parameter_data(
-    args: &mut ParenthesizedArgs,
-    vis: &mut T,
-) {
-    let ParenthesizedArgs { inputs, output, span, .. } = args;
-    visit_vec(inputs, |input| vis.visit_ty(input));
-    noop_visit_fn_ret_ty(output, vis);
-    vis.visit_span(span);
-}
-
-pub fn noop_visit_local(local: &mut P, vis: &mut T) {
-    let Local { id, pat, ty, init, span, attrs, tokens } = local.deref_mut();
-    vis.visit_id(id);
-    vis.visit_pat(pat);
-    visit_opt(ty, |ty| vis.visit_ty(ty));
-    visit_opt(init, |init| vis.visit_expr(init));
-    vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
-    visit_lazy_tts(tokens, vis);
-}
-
-pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) {
-    let Attribute { kind, id: _, style: _, span } = attr;
-    match kind {
-        AttrKind::Normal(AttrItem { path, args, tokens }, attr_tokens) => {
-            vis.visit_path(path);
-            visit_mac_args(args, vis);
-            visit_lazy_tts(tokens, vis);
-            visit_lazy_tts(attr_tokens, vis);
-        }
-        AttrKind::DocComment(..) => {}
-    }
-    vis.visit_span(span);
-}
-
-pub fn noop_visit_mac(mac: &mut MacCall, vis: &mut T) {
-    let MacCall { path, args, prior_type_ascription: _ } = mac;
-    vis.visit_path(path);
-    visit_mac_args(args, vis);
-}
-
-pub fn noop_visit_macro_def(macro_def: &mut MacroDef, vis: &mut T) {
-    let MacroDef { body, macro_rules: _ } = macro_def;
-    visit_mac_args(body, vis);
-}
-
-pub fn noop_visit_meta_list_item(li: &mut NestedMetaItem, vis: &mut T) {
-    match li {
-        NestedMetaItem::MetaItem(mi) => vis.visit_meta_item(mi),
-        NestedMetaItem::Literal(_lit) => {}
-    }
-}
-
-pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) {
-    let MetaItem { path: _, kind, span } = mi;
-    match kind {
-        MetaItemKind::Word => {}
-        MetaItemKind::List(mis) => visit_vec(mis, |mi| vis.visit_meta_list_item(mi)),
-        MetaItemKind::NameValue(_s) => {}
-    }
-    vis.visit_span(span);
-}
-
-pub fn noop_flat_map_param(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> {
-    let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param;
-    vis.visit_id(id);
-    visit_thin_attrs(attrs, vis);
-    vis.visit_pat(pat);
-    vis.visit_span(span);
-    vis.visit_ty(ty);
-    smallvec![param]
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_tt(tt: &mut TokenTree, vis: &mut T) {
-    match tt {
-        TokenTree::Token(token) => {
-            visit_token(token, vis);
-        }
-        TokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
-            vis.visit_span(open);
-            vis.visit_span(close);
-            visit_tts(tts, vis);
-        }
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_tts(TokenStream(tts): &mut TokenStream, vis: &mut T) {
-    if vis.token_visiting_enabled() && !tts.is_empty() {
-        let tts = Lrc::make_mut(tts);
-        visit_vec(tts, |(tree, _is_joint)| visit_tt(tree, vis));
-    }
-}
-
-pub fn visit_lazy_tts(lazy_tts: &mut Option, vis: &mut T) {
-    if vis.token_visiting_enabled() {
-        visit_opt(lazy_tts, |lazy_tts| {
-            let mut tts = lazy_tts.create_token_stream();
-            visit_tts(&mut tts, vis);
-            *lazy_tts = LazyTokenStream::new(tts);
-        })
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
-// In practice the ident part is not actually used by specific visitors right now,
-// but there's a test below checking that it works.
-pub fn visit_token(t: &mut Token, vis: &mut T) {
-    let Token { kind, span } = t;
-    match kind {
-        token::Ident(name, _) | token::Lifetime(name) => {
-            let mut ident = Ident::new(*name, *span);
-            vis.visit_ident(&mut ident);
-            *name = ident.name;
-            *span = ident.span;
-            return; // Avoid visiting the span for the second time.
-        }
-        token::Interpolated(nt) => {
-            let mut nt = Lrc::make_mut(nt);
-            visit_interpolated(&mut nt, vis);
-        }
-        _ => {}
-    }
-    vis.visit_span(span);
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-/// Applies the visitor to elements of interpolated nodes.
-//
-// N.B., this can occur only when applying a visitor to partially expanded
-// code, where parsed pieces have gotten implanted ito *other* macro
-// invocations. This is relevant for macro hygiene, but possibly not elsewhere.
-//
-// One problem here occurs because the types for flat_map_item, flat_map_stmt,
-// etc., allow the visitor to return *multiple* items; this is a problem for the
-// nodes here, because they insist on having exactly one piece. One solution
-// would be to mangle the MutVisitor trait to include one-to-many and
-// one-to-one versions of these entry points, but that would probably confuse a
-// lot of people and help very few. Instead, I'm just going to put in dynamic
-// checks. I think the performance impact of this will be pretty much
-// nonexistent. The danger is that someone will apply a `MutVisitor` to a
-// partially expanded node, and will be confused by the fact that their
-// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt`
-// nodes. Hopefully they'll wind up reading this comment, and doing something
-// appropriate.
-//
-// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to
-// contain multiple items, but decided against it when I looked at
-// `parse_item_or_view_item` and tried to figure out what I would do with
-// multiple items there....
-pub fn visit_interpolated(nt: &mut token::Nonterminal, vis: &mut T) {
-    match nt {
-        token::NtItem(item) => visit_clobber(item, |item| {
-            // This is probably okay, because the only visitors likely to
-            // peek inside interpolated nodes will be renamings/markings,
-            // which map single items to single items.
-            vis.flat_map_item(item).expect_one("expected visitor to produce exactly one item")
-        }),
-        token::NtBlock(block) => vis.visit_block(block),
-        token::NtStmt(stmt) => visit_clobber(stmt, |stmt| {
-            // See reasoning above.
-            vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item")
-        }),
-        token::NtPat(pat) => vis.visit_pat(pat),
-        token::NtExpr(expr) => vis.visit_expr(expr),
-        token::NtTy(ty) => vis.visit_ty(ty),
-        token::NtIdent(ident, _is_raw) => vis.visit_ident(ident),
-        token::NtLifetime(ident) => vis.visit_ident(ident),
-        token::NtLiteral(expr) => vis.visit_expr(expr),
-        token::NtMeta(item) => {
-            let AttrItem { path, args, tokens } = item.deref_mut();
-            vis.visit_path(path);
-            visit_mac_args(args, vis);
-            visit_lazy_tts(tokens, vis);
-        }
-        token::NtPath(path) => vis.visit_path(path),
-        token::NtTT(tt) => visit_tt(tt, vis),
-        token::NtVis(visib) => vis.visit_vis(visib),
-    }
-}
-
-pub fn noop_visit_asyncness(asyncness: &mut Async, vis: &mut T) {
-    match asyncness {
-        Async::Yes { span: _, closure_id, return_impl_trait_id } => {
-            vis.visit_id(closure_id);
-            vis.visit_id(return_impl_trait_id);
-        }
-        Async::No => {}
-    }
-}
-
-pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) {
-    let FnDecl { inputs, output } = decl.deref_mut();
-    inputs.flat_map_in_place(|param| vis.flat_map_param(param));
-    noop_visit_fn_ret_ty(output, vis);
-}
-
-pub fn noop_visit_fn_ret_ty(fn_ret_ty: &mut FnRetTy, vis: &mut T) {
-    match fn_ret_ty {
-        FnRetTy::Default(span) => vis.visit_span(span),
-        FnRetTy::Ty(ty) => vis.visit_ty(ty),
-    }
-}
-
-pub fn noop_visit_param_bound(pb: &mut GenericBound, vis: &mut T) {
-    match pb {
-        GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty),
-        GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis),
-    }
-}
-
-pub fn noop_flat_map_generic_param(
-    mut param: GenericParam,
-    vis: &mut T,
-) -> SmallVec<[GenericParam; 1]> {
-    let GenericParam { id, ident, attrs, bounds, kind, is_placeholder: _ } = &mut param;
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-    visit_thin_attrs(attrs, vis);
-    visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
-    match kind {
-        GenericParamKind::Lifetime => {}
-        GenericParamKind::Type { default } => {
-            visit_opt(default, |default| vis.visit_ty(default));
-        }
-        GenericParamKind::Const { ty, kw_span: _, default } => {
-            vis.visit_ty(ty);
-            visit_opt(default, |default| vis.visit_anon_const(default));
-        }
-    }
-    smallvec![param]
-}
-
-pub fn noop_visit_label(Label { ident }: &mut Label, vis: &mut T) {
-    vis.visit_ident(ident);
-}
-
-fn noop_visit_lifetime(Lifetime { id, ident }: &mut Lifetime, vis: &mut T) {
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-}
-
-pub fn noop_visit_generics(generics: &mut Generics, vis: &mut T) {
-    let Generics { params, where_clause, span } = generics;
-    params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-    vis.visit_where_clause(where_clause);
-    vis.visit_span(span);
-}
-
-pub fn noop_visit_where_clause(wc: &mut WhereClause, vis: &mut T) {
-    let WhereClause { has_where_token: _, predicates, span } = wc;
-    visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
-    vis.visit_span(span);
-}
-
-pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: &mut T) {
-    match pred {
-        WherePredicate::BoundPredicate(bp) => {
-            let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp;
-            vis.visit_span(span);
-            bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-            vis.visit_ty(bounded_ty);
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound));
-        }
-        WherePredicate::RegionPredicate(rp) => {
-            let WhereRegionPredicate { span, lifetime, bounds } = rp;
-            vis.visit_span(span);
-            noop_visit_lifetime(lifetime, vis);
-            visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
-        }
-        WherePredicate::EqPredicate(ep) => {
-            let WhereEqPredicate { id, span, lhs_ty, rhs_ty } = ep;
-            vis.visit_id(id);
-            vis.visit_span(span);
-            vis.visit_ty(lhs_ty);
-            vis.visit_ty(rhs_ty);
-        }
-    }
-}
-
-pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) {
-    match vdata {
-        VariantData::Struct(fields, ..) => {
-            fields.flat_map_in_place(|field| vis.flat_map_struct_field(field));
-        }
-        VariantData::Tuple(fields, id) => {
-            fields.flat_map_in_place(|field| vis.flat_map_struct_field(field));
-            vis.visit_id(id);
-        }
-        VariantData::Unit(id) => vis.visit_id(id),
-    }
-}
-
-pub fn noop_visit_trait_ref(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
-    vis.visit_path(path);
-    vis.visit_id(ref_id);
-}
-
-pub fn noop_visit_poly_trait_ref(p: &mut PolyTraitRef, vis: &mut T) {
-    let PolyTraitRef { bound_generic_params, trait_ref, span } = p;
-    bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-    vis.visit_trait_ref(trait_ref);
-    vis.visit_span(span);
-}
-
-pub fn noop_flat_map_struct_field(
-    mut sf: StructField,
-    visitor: &mut T,
-) -> SmallVec<[StructField; 1]> {
-    let StructField { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut sf;
-    visitor.visit_span(span);
-    visit_opt(ident, |ident| visitor.visit_ident(ident));
-    visitor.visit_vis(vis);
-    visitor.visit_id(id);
-    visitor.visit_ty(ty);
-    visit_attrs(attrs, visitor);
-    smallvec![sf]
-}
-
-pub fn noop_flat_map_field(mut f: Field, vis: &mut T) -> SmallVec<[Field; 1]> {
-    let Field { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f;
-    vis.visit_ident(ident);
-    vis.visit_expr(expr);
-    vis.visit_id(id);
-    vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
-    smallvec![f]
-}
-
-pub fn noop_visit_mt(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mut T) {
-    vis.visit_ty(ty);
-}
-
-pub fn noop_visit_block(block: &mut P, vis: &mut T) {
-    let Block { id, stmts, rules: _, span, tokens } = block.deref_mut();
-    vis.visit_id(id);
-    stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
-    vis.visit_span(span);
-    visit_lazy_tts(tokens, vis);
-}
-
-pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) {
-    match kind {
-        ItemKind::ExternCrate(_orig_name) => {}
-        ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
-        ItemKind::Static(ty, _, expr) | ItemKind::Const(_, ty, expr) => {
-            vis.visit_ty(ty);
-            visit_opt(expr, |expr| vis.visit_expr(expr));
-        }
-        ItemKind::Fn(box FnKind(_, sig, generics, body)) => {
-            visit_fn_sig(sig, vis);
-            vis.visit_generics(generics);
-            visit_opt(body, |body| vis.visit_block(body));
-        }
-        ItemKind::Mod(m) => vis.visit_mod(m),
-        ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
-        ItemKind::GlobalAsm(_ga) => {}
-        ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
-            vis.visit_generics(generics);
-            visit_bounds(bounds, vis);
-            visit_opt(ty, |ty| vis.visit_ty(ty));
-        }
-        ItemKind::Enum(EnumDef { variants }, generics) => {
-            variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
-            vis.visit_generics(generics);
-        }
-        ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => {
-            vis.visit_variant_data(variant_data);
-            vis.visit_generics(generics);
-        }
-        ItemKind::Impl(box ImplKind {
-            unsafety: _,
-            polarity: _,
-            defaultness: _,
-            constness: _,
-            generics,
-            of_trait,
-            self_ty,
-            items,
-        }) => {
-            vis.visit_generics(generics);
-            visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
-            vis.visit_ty(self_ty);
-            items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
-        }
-        ItemKind::Trait(box TraitKind(.., generics, bounds, items)) => {
-            vis.visit_generics(generics);
-            visit_bounds(bounds, vis);
-            items.flat_map_in_place(|item| vis.flat_map_trait_item(item));
-        }
-        ItemKind::TraitAlias(generics, bounds) => {
-            vis.visit_generics(generics);
-            visit_bounds(bounds, vis);
-        }
-        ItemKind::MacCall(m) => vis.visit_mac_call(m),
-        ItemKind::MacroDef(def) => vis.visit_macro_def(def),
-    }
-}
-
-pub fn noop_flat_map_assoc_item(
-    mut item: P,
-    visitor: &mut T,
-) -> SmallVec<[P; 1]> {
-    let Item { id, ident, vis, attrs, kind, span, tokens } = item.deref_mut();
-    visitor.visit_id(id);
-    visitor.visit_ident(ident);
-    visitor.visit_vis(vis);
-    visit_attrs(attrs, visitor);
-    match kind {
-        AssocItemKind::Const(_, ty, expr) => {
-            visitor.visit_ty(ty);
-            visit_opt(expr, |expr| visitor.visit_expr(expr));
-        }
-        AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
-            visitor.visit_generics(generics);
-            visit_fn_sig(sig, visitor);
-            visit_opt(body, |body| visitor.visit_block(body));
-        }
-        AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
-            visitor.visit_generics(generics);
-            visit_bounds(bounds, visitor);
-            visit_opt(ty, |ty| visitor.visit_ty(ty));
-        }
-        AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
-    }
-    visitor.visit_span(span);
-    visit_lazy_tts(tokens, visitor);
-    smallvec![item]
-}
-
-pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) {
-    let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header;
-    vis.visit_asyncness(asyncness);
-}
-
-pub fn noop_visit_mod(module: &mut Mod, vis: &mut T) {
-    let Mod { inner, unsafety: _, items, inline: _ } = module;
-    vis.visit_span(inner);
-    items.flat_map_in_place(|item| vis.flat_map_item(item));
-}
-
-pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) {
-    visit_clobber(krate, |Crate { module, attrs, span, proc_macros }| {
-        let item_vis =
-            Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None };
-        let item = P(Item {
-            ident: Ident::invalid(),
-            attrs,
-            id: DUMMY_NODE_ID,
-            vis: item_vis,
-            span,
-            kind: ItemKind::Mod(module),
-            tokens: None,
-        });
-        let items = vis.flat_map_item(item);
-
-        let len = items.len();
-        if len == 0 {
-            let module = Mod { inner: span, unsafety: Unsafe::No, items: vec![], inline: true };
-            Crate { module, attrs: vec![], span, proc_macros }
-        } else if len == 1 {
-            let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
-            match kind {
-                ItemKind::Mod(module) => Crate { module, attrs, span, proc_macros },
-                _ => panic!("visitor converted a module to not a module"),
-            }
-        } else {
-            panic!("a crate cannot expand to more than one item");
-        }
-    });
-}
-
-// Mutates one item into possibly many items.
-pub fn noop_flat_map_item(
-    mut item: P,
-    visitor: &mut T,
-) -> SmallVec<[P; 1]> {
-    let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
-    visitor.visit_ident(ident);
-    visit_attrs(attrs, visitor);
-    visitor.visit_id(id);
-    visitor.visit_item_kind(kind);
-    visitor.visit_vis(vis);
-    visitor.visit_span(span);
-    visit_lazy_tts(tokens, visitor);
-
-    smallvec![item]
-}
-
-pub fn noop_flat_map_foreign_item(
-    mut item: P,
-    visitor: &mut T,
-) -> SmallVec<[P; 1]> {
-    let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
-    visitor.visit_id(id);
-    visitor.visit_ident(ident);
-    visitor.visit_vis(vis);
-    visit_attrs(attrs, visitor);
-    match kind {
-        ForeignItemKind::Static(ty, _, expr) => {
-            visitor.visit_ty(ty);
-            visit_opt(expr, |expr| visitor.visit_expr(expr));
-        }
-        ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
-            visitor.visit_generics(generics);
-            visit_fn_sig(sig, visitor);
-            visit_opt(body, |body| visitor.visit_block(body));
-        }
-        ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
-            visitor.visit_generics(generics);
-            visit_bounds(bounds, visitor);
-            visit_opt(ty, |ty| visitor.visit_ty(ty));
-        }
-        ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
-    }
-    visitor.visit_span(span);
-    visit_lazy_tts(tokens, visitor);
-    smallvec![item]
-}
-
-pub fn noop_visit_pat(pat: &mut P, vis: &mut T) {
-    let Pat { id, kind, span, tokens } = pat.deref_mut();
-    vis.visit_id(id);
-    match kind {
-        PatKind::Wild | PatKind::Rest => {}
-        PatKind::Ident(_binding_mode, ident, sub) => {
-            vis.visit_ident(ident);
-            visit_opt(sub, |sub| vis.visit_pat(sub));
-        }
-        PatKind::Lit(e) => vis.visit_expr(e),
-        PatKind::TupleStruct(path, elems) => {
-            vis.visit_path(path);
-            visit_vec(elems, |elem| vis.visit_pat(elem));
-        }
-        PatKind::Path(qself, path) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-        }
-        PatKind::Struct(path, fields, _etc) => {
-            vis.visit_path(path);
-            fields.flat_map_in_place(|field| vis.flat_map_field_pattern(field));
-        }
-        PatKind::Box(inner) => vis.visit_pat(inner),
-        PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
-        PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
-            visit_opt(e1, |e| vis.visit_expr(e));
-            visit_opt(e2, |e| vis.visit_expr(e));
-            vis.visit_span(span);
-        }
-        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
-            visit_vec(elems, |elem| vis.visit_pat(elem))
-        }
-        PatKind::Paren(inner) => vis.visit_pat(inner),
-        PatKind::MacCall(mac) => vis.visit_mac_call(mac),
-    }
-    vis.visit_span(span);
-    visit_lazy_tts(tokens, vis);
-}
-
-pub fn noop_visit_anon_const(AnonConst { id, value }: &mut AnonConst, vis: &mut T) {
-    vis.visit_id(id);
-    vis.visit_expr(value);
-}
-
-pub fn noop_visit_expr(
-    Expr { kind, id, span, attrs, tokens }: &mut Expr,
-    vis: &mut T,
-) {
-    match kind {
-        ExprKind::Box(expr) => vis.visit_expr(expr),
-        ExprKind::Array(exprs) => visit_exprs(exprs, vis),
-        ExprKind::ConstBlock(anon_const) => {
-            vis.visit_anon_const(anon_const);
-        }
-        ExprKind::Repeat(expr, count) => {
-            vis.visit_expr(expr);
-            vis.visit_anon_const(count);
-        }
-        ExprKind::Tup(exprs) => visit_exprs(exprs, vis),
-        ExprKind::Call(f, args) => {
-            vis.visit_expr(f);
-            visit_exprs(args, vis);
-        }
-        ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
-            vis.visit_ident(ident);
-            vis.visit_id(id);
-            visit_opt(args, |args| vis.visit_generic_args(args));
-            visit_exprs(exprs, vis);
-            vis.visit_span(span);
-        }
-        ExprKind::Binary(_binop, lhs, rhs) => {
-            vis.visit_expr(lhs);
-            vis.visit_expr(rhs);
-        }
-        ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs),
-        ExprKind::Cast(expr, ty) => {
-            vis.visit_expr(expr);
-            vis.visit_ty(ty);
-        }
-        ExprKind::Type(expr, ty) => {
-            vis.visit_expr(expr);
-            vis.visit_ty(ty);
-        }
-        ExprKind::AddrOf(_, _, ohs) => vis.visit_expr(ohs),
-        ExprKind::Let(pat, scrutinee) => {
-            vis.visit_pat(pat);
-            vis.visit_expr(scrutinee);
-        }
-        ExprKind::If(cond, tr, fl) => {
-            vis.visit_expr(cond);
-            vis.visit_block(tr);
-            visit_opt(fl, |fl| vis.visit_expr(fl));
-        }
-        ExprKind::While(cond, body, label) => {
-            vis.visit_expr(cond);
-            vis.visit_block(body);
-            visit_opt(label, |label| vis.visit_label(label));
-        }
-        ExprKind::ForLoop(pat, iter, body, label) => {
-            vis.visit_pat(pat);
-            vis.visit_expr(iter);
-            vis.visit_block(body);
-            visit_opt(label, |label| vis.visit_label(label));
-        }
-        ExprKind::Loop(body, label) => {
-            vis.visit_block(body);
-            visit_opt(label, |label| vis.visit_label(label));
-        }
-        ExprKind::Match(expr, arms) => {
-            vis.visit_expr(expr);
-            arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
-        }
-        ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => {
-            vis.visit_asyncness(asyncness);
-            vis.visit_fn_decl(decl);
-            vis.visit_expr(body);
-            vis.visit_span(span);
-        }
-        ExprKind::Block(blk, label) => {
-            vis.visit_block(blk);
-            visit_opt(label, |label| vis.visit_label(label));
-        }
-        ExprKind::Async(_capture_by, node_id, body) => {
-            vis.visit_id(node_id);
-            vis.visit_block(body);
-        }
-        ExprKind::Await(expr) => vis.visit_expr(expr),
-        ExprKind::Assign(el, er, _) => {
-            vis.visit_expr(el);
-            vis.visit_expr(er);
-        }
-        ExprKind::AssignOp(_op, el, er) => {
-            vis.visit_expr(el);
-            vis.visit_expr(er);
-        }
-        ExprKind::Field(el, ident) => {
-            vis.visit_expr(el);
-            vis.visit_ident(ident);
-        }
-        ExprKind::Index(el, er) => {
-            vis.visit_expr(el);
-            vis.visit_expr(er);
-        }
-        ExprKind::Range(e1, e2, _lim) => {
-            visit_opt(e1, |e1| vis.visit_expr(e1));
-            visit_opt(e2, |e2| vis.visit_expr(e2));
-        }
-        ExprKind::Underscore => {}
-        ExprKind::Path(qself, path) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-        }
-        ExprKind::Break(label, expr) => {
-            visit_opt(label, |label| vis.visit_label(label));
-            visit_opt(expr, |expr| vis.visit_expr(expr));
-        }
-        ExprKind::Continue(label) => {
-            visit_opt(label, |label| vis.visit_label(label));
-        }
-        ExprKind::Ret(expr) => {
-            visit_opt(expr, |expr| vis.visit_expr(expr));
-        }
-        ExprKind::InlineAsm(asm) => {
-            for (op, _) in &mut asm.operands {
-                match op {
-                    InlineAsmOperand::In { expr, .. }
-                    | InlineAsmOperand::InOut { expr, .. }
-                    | InlineAsmOperand::Const { expr, .. }
-                    | InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr),
-                    InlineAsmOperand::Out { expr, .. } => {
-                        if let Some(expr) = expr {
-                            vis.visit_expr(expr);
-                        }
-                    }
-                    InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                        vis.visit_expr(in_expr);
-                        if let Some(out_expr) = out_expr {
-                            vis.visit_expr(out_expr);
-                        }
-                    }
-                }
-            }
-        }
-        ExprKind::LlvmInlineAsm(asm) => {
-            let LlvmInlineAsm {
-                asm: _,
-                asm_str_style: _,
-                outputs,
-                inputs,
-                clobbers: _,
-                volatile: _,
-                alignstack: _,
-                dialect: _,
-            } = asm.deref_mut();
-            for out in outputs {
-                let LlvmInlineAsmOutput { constraint: _, expr, is_rw: _, is_indirect: _ } = out;
-                vis.visit_expr(expr);
-            }
-            visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr));
-        }
-        ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
-        ExprKind::Struct(path, fields, expr) => {
-            vis.visit_path(path);
-            fields.flat_map_in_place(|field| vis.flat_map_field(field));
-            match expr {
-                StructRest::Base(expr) => vis.visit_expr(expr),
-                StructRest::Rest(_span) => {}
-                StructRest::None => {}
-            }
-        }
-        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));
-        }
-        ExprKind::Try(expr) => vis.visit_expr(expr),
-        ExprKind::TryBlock(body) => vis.visit_block(body),
-        ExprKind::Lit(_) | ExprKind::Err => {}
-    }
-    vis.visit_id(id);
-    vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
-    visit_lazy_tts(tokens, vis);
-}
-
-pub fn noop_filter_map_expr(mut e: P, vis: &mut T) -> Option> {
-    Some({
-        vis.visit_expr(&mut e);
-        e
-    })
-}
-
-pub fn noop_flat_map_stmt(
-    Stmt { kind, mut span, mut id }: Stmt,
-    vis: &mut T,
-) -> SmallVec<[Stmt; 1]> {
-    vis.visit_id(&mut id);
-    vis.visit_span(&mut span);
-    noop_flat_map_stmt_kind(kind, vis).into_iter().map(|kind| Stmt { id, kind, span }).collect()
-}
-
-pub fn noop_flat_map_stmt_kind(
-    kind: StmtKind,
-    vis: &mut T,
-) -> SmallVec<[StmtKind; 1]> {
-    match kind {
-        StmtKind::Local(mut local) => smallvec![StmtKind::Local({
-            vis.visit_local(&mut local);
-            local
-        })],
-        StmtKind::Item(item) => vis.flat_map_item(item).into_iter().map(StmtKind::Item).collect(),
-        StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(),
-        StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
-        StmtKind::Empty => smallvec![StmtKind::Empty],
-        StmtKind::MacCall(mut mac) => {
-            let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
-            vis.visit_mac_call(mac_);
-            visit_thin_attrs(attrs, vis);
-            visit_lazy_tts(tokens, vis);
-            smallvec![StmtKind::MacCall(mac)]
-        }
-    }
-}
-
-pub fn noop_visit_vis(visibility: &mut Visibility, vis: &mut T) {
-    match &mut visibility.kind {
-        VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {}
-        VisibilityKind::Restricted { path, id } => {
-            vis.visit_path(path);
-            vis.visit_id(id);
-        }
-    }
-    vis.visit_span(&mut visibility.span);
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/node_id.rs b/vendor/rustc-ap-rustc_ast/src/node_id.rs
deleted file mode 100644
index 6e7d2bab28..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/node_id.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use rustc_span::ExpnId;
-use std::fmt;
-
-rustc_index::newtype_index! {
-    pub struct NodeId {
-        DEBUG_FORMAT = "NodeId({})"
-    }
-}
-
-rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId);
-
-/// `NodeId` used to represent the root of the crate.
-pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
-
-/// When parsing and doing expansions, we initially give all AST nodes this AST
-/// node value. Then later, during expansion, we renumber them to have small,
-/// positive ids.
-pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
-
-impl NodeId {
-    pub fn placeholder_from_expn_id(expn_id: ExpnId) -> Self {
-        NodeId::from_u32(expn_id.as_u32())
-    }
-
-    pub fn placeholder_to_expn_id(self) -> ExpnId {
-        ExpnId::from_u32(self.as_u32())
-    }
-}
-
-impl fmt::Display for NodeId {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.as_u32(), f)
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/ptr.rs b/vendor/rustc-ap-rustc_ast/src/ptr.rs
deleted file mode 100644
index e4a3cccb7e..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/ptr.rs
+++ /dev/null
@@ -1,219 +0,0 @@
-//! The AST pointer.
-//!
-//! Provides `P`, a frozen owned smart pointer.
-//!
-//! # Motivations and benefits
-//!
-//! * **Identity**: sharing AST nodes is problematic for the various analysis
-//!   passes (e.g., one may be able to bypass the borrow checker with a shared
-//!   `ExprKind::AddrOf` node taking a mutable borrow).
-//!
-//! * **Immutability**: `P` disallows mutating its inner `T`, unlike `Box`
-//!   (unless it contains an `Unsafe` interior, but that may be denied later).
-//!   This mainly prevents mistakes, but can also enforces a kind of "purity".
-//!
-//! * **Efficiency**: folding can reuse allocation space for `P` and `Vec`,
-//!   the latter even when the input and output types differ (as it would be the
-//!   case with arenas or a GADT AST using type parameters to toggle features).
-//!
-//! * **Maintainability**: `P` provides a fixed interface - `Deref`,
-//!   `and_then` and `map` - which can remain fully functional even if the
-//!   implementation changes (using a special thread-local heap, for example).
-//!   Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated.
-
-use std::fmt::{self, Debug, Display};
-use std::iter::FromIterator;
-use std::ops::{Deref, DerefMut};
-use std::{slice, vec};
-
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-/// An owned smart pointer.
-pub struct P {
-    ptr: Box,
-}
-
-/// Construct a `P` from a `T` value.
-#[allow(non_snake_case)]
-pub fn P(value: T) -> P {
-    P { ptr: box value }
-}
-
-impl P {
-    /// Move out of the pointer.
-    /// Intended for chaining transformations not covered by `map`.
-    pub fn and_then(self, f: F) -> U
-    where
-        F: FnOnce(T) -> U,
-    {
-        f(*self.ptr)
-    }
-
-    /// Equivalent to `and_then(|x| x)`.
-    pub fn into_inner(self) -> T {
-        *self.ptr
-    }
-
-    /// Produce a new `P` from `self` without reallocating.
-    pub fn map(mut self, f: F) -> P
-    where
-        F: FnOnce(T) -> T,
-    {
-        let x = f(*self.ptr);
-        *self.ptr = x;
-
-        self
-    }
-
-    /// Optionally produce a new `P` from `self` without reallocating.
-    pub fn filter_map(mut self, f: F) -> Option>
-    where
-        F: FnOnce(T) -> Option,
-    {
-        *self.ptr = f(*self.ptr)?;
-        Some(self)
-    }
-}
-
-impl Deref for P {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &self.ptr
-    }
-}
-
-impl DerefMut for P {
-    fn deref_mut(&mut self) -> &mut T {
-        &mut self.ptr
-    }
-}
-
-impl Clone for P {
-    fn clone(&self) -> P {
-        P((**self).clone())
-    }
-}
-
-impl Debug for P {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Debug::fmt(&self.ptr, f)
-    }
-}
-
-impl Display for P {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Display::fmt(&**self, f)
-    }
-}
-
-impl fmt::Pointer for P {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Pointer::fmt(&self.ptr, f)
-    }
-}
-
-impl> Decodable for P {
-    fn decode(d: &mut D) -> Result, D::Error> {
-        Decodable::decode(d).map(P)
-    }
-}
-
-impl> Encodable for P {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
-    }
-}
-
-impl P<[T]> {
-    pub const fn new() -> P<[T]> {
-        // HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>`
-        // (as trait methods, `default` in this case, can't be `const fn` yet).
-        P {
-            ptr: unsafe {
-                use std::ptr::NonNull;
-                std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>)
-            },
-        }
-    }
-
-    #[inline(never)]
-    pub fn from_vec(v: Vec) -> P<[T]> {
-        P { ptr: v.into_boxed_slice() }
-    }
-
-    #[inline(never)]
-    pub fn into_vec(self) -> Vec {
-        self.ptr.into_vec()
-    }
-}
-
-impl Default for P<[T]> {
-    /// Creates an empty `P<[T]>`.
-    fn default() -> P<[T]> {
-        P::new()
-    }
-}
-
-impl Clone for P<[T]> {
-    fn clone(&self) -> P<[T]> {
-        P::from_vec(self.to_vec())
-    }
-}
-
-impl From> for P<[T]> {
-    fn from(v: Vec) -> Self {
-        P::from_vec(v)
-    }
-}
-
-impl Into> for P<[T]> {
-    fn into(self) -> Vec {
-        self.into_vec()
-    }
-}
-
-impl FromIterator for P<[T]> {
-    fn from_iter>(iter: I) -> P<[T]> {
-        P::from_vec(iter.into_iter().collect())
-    }
-}
-
-impl IntoIterator for P<[T]> {
-    type Item = T;
-    type IntoIter = vec::IntoIter;
-
-    fn into_iter(self) -> Self::IntoIter {
-        self.into_vec().into_iter()
-    }
-}
-
-impl<'a, T> IntoIterator for &'a P<[T]> {
-    type Item = &'a T;
-    type IntoIter = slice::Iter<'a, T>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.ptr.into_iter()
-    }
-}
-
-impl> Encodable for P<[T]> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        Encodable::encode(&**self, s)
-    }
-}
-
-impl> Decodable for P<[T]> {
-    fn decode(d: &mut D) -> Result, D::Error> {
-        Ok(P::from_vec(Decodable::decode(d)?))
-    }
-}
-
-impl HashStable for P
-where
-    T: ?Sized + HashStable,
-{
-    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        (**self).hash_stable(hcx, hasher);
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/token.rs b/vendor/rustc-ap-rustc_ast/src/token.rs
deleted file mode 100644
index 90bfb01d6c..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/token.rs
+++ /dev/null
@@ -1,908 +0,0 @@
-pub use BinOpToken::*;
-pub use DelimToken::*;
-pub use LitKind::*;
-pub use Nonterminal::*;
-pub use TokenKind::*;
-
-use crate::ast;
-use crate::ptr::P;
-use crate::tokenstream::TokenTree;
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::Lrc;
-use rustc_macros::HashStable_Generic;
-use rustc_span::hygiene::ExpnKind;
-use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{kw, sym};
-use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, edition::Edition, FileName, RealFileName, Span, DUMMY_SP};
-use std::borrow::Cow;
-use std::{fmt, mem};
-
-#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum CommentKind {
-    Line,
-    Block,
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Hash, Debug, Copy)]
-#[derive(HashStable_Generic)]
-pub enum BinOpToken {
-    Plus,
-    Minus,
-    Star,
-    Slash,
-    Percent,
-    Caret,
-    And,
-    Or,
-    Shl,
-    Shr,
-}
-
-/// A delimiter token.
-#[derive(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, Copy)]
-#[derive(HashStable_Generic)]
-pub enum DelimToken {
-    /// A round parenthesis (i.e., `(` or `)`).
-    Paren,
-    /// A square bracket (i.e., `[` or `]`).
-    Bracket,
-    /// A curly brace (i.e., `{` or `}`).
-    Brace,
-    /// An empty delimiter.
-    NoDelim,
-}
-
-#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum LitKind {
-    Bool, // AST only, must never appear in a `Token`
-    Byte,
-    Char,
-    Integer,
-    Float,
-    Str,
-    StrRaw(u16), // raw string delimited by `n` hash symbols
-    ByteStr,
-    ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols
-    Err,
-}
-
-/// A literal token.
-#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub struct Lit {
-    pub kind: LitKind,
-    pub symbol: Symbol,
-    pub suffix: Option,
-}
-
-impl fmt::Display for Lit {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Lit { kind, symbol, suffix } = *self;
-        match kind {
-            Byte => write!(f, "b'{}'", symbol)?,
-            Char => write!(f, "'{}'", symbol)?,
-            Str => write!(f, "\"{}\"", symbol)?,
-            StrRaw(n) => write!(
-                f,
-                "r{delim}\"{string}\"{delim}",
-                delim = "#".repeat(n as usize),
-                string = symbol
-            )?,
-            ByteStr => write!(f, "b\"{}\"", symbol)?,
-            ByteStrRaw(n) => write!(
-                f,
-                "br{delim}\"{string}\"{delim}",
-                delim = "#".repeat(n as usize),
-                string = symbol
-            )?,
-            Integer | Float | Bool | Err => write!(f, "{}", symbol)?,
-        }
-
-        if let Some(suffix) = suffix {
-            write!(f, "{}", suffix)?;
-        }
-
-        Ok(())
-    }
-}
-
-impl LitKind {
-    /// An English article for the literal token kind.
-    pub fn article(self) -> &'static str {
-        match self {
-            Integer | Err => "an",
-            _ => "a",
-        }
-    }
-
-    pub fn descr(self) -> &'static str {
-        match self {
-            Bool => panic!("literal token contains `Lit::Bool`"),
-            Byte => "byte",
-            Char => "char",
-            Integer => "integer",
-            Float => "float",
-            Str | StrRaw(..) => "string",
-            ByteStr | ByteStrRaw(..) => "byte string",
-            Err => "error",
-        }
-    }
-
-    crate fn may_have_suffix(self) -> bool {
-        matches!(self, Integer | Float | Err)
-    }
-}
-
-impl Lit {
-    pub fn new(kind: LitKind, symbol: Symbol, suffix: Option) -> Lit {
-        Lit { kind, symbol, suffix }
-    }
-}
-
-pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
-    let ident_token = Token::new(Ident(name, is_raw), span);
-
-    !ident_token.is_reserved_ident()
-        || ident_token.is_path_segment_keyword()
-        || [
-            kw::Async,
-            kw::Do,
-            kw::Box,
-            kw::Break,
-            kw::Const,
-            kw::Continue,
-            kw::False,
-            kw::For,
-            kw::If,
-            kw::Let,
-            kw::Loop,
-            kw::Match,
-            kw::Move,
-            kw::Return,
-            kw::True,
-            kw::Try,
-            kw::Unsafe,
-            kw::While,
-            kw::Yield,
-            kw::Static,
-        ]
-        .contains(&name)
-}
-
-fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool {
-    let ident_token = Token::new(Ident(name, is_raw), span);
-
-    !ident_token.is_reserved_ident()
-        || ident_token.is_path_segment_keyword()
-        || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
-            .contains(&name)
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub enum TokenKind {
-    /* Expression-operator symbols. */
-    Eq,
-    Lt,
-    Le,
-    EqEq,
-    Ne,
-    Ge,
-    Gt,
-    AndAnd,
-    OrOr,
-    Not,
-    Tilde,
-    BinOp(BinOpToken),
-    BinOpEq(BinOpToken),
-
-    /* Structural symbols */
-    At,
-    Dot,
-    DotDot,
-    DotDotDot,
-    DotDotEq,
-    Comma,
-    Semi,
-    Colon,
-    ModSep,
-    RArrow,
-    LArrow,
-    FatArrow,
-    Pound,
-    Dollar,
-    Question,
-    /// Used by proc macros for representing lifetimes, not generated by lexer right now.
-    SingleQuote,
-    /// An opening delimiter (e.g., `{`).
-    OpenDelim(DelimToken),
-    /// A closing delimiter (e.g., `}`).
-    CloseDelim(DelimToken),
-
-    /* Literals */
-    Literal(Lit),
-
-    /// Identifier token.
-    /// Do not forget about `NtIdent` when you want to match on identifiers.
-    /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
-    /// treat regular and interpolated identifiers in the same way.
-    Ident(Symbol, /* is_raw */ bool),
-    /// Lifetime identifier token.
-    /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
-    /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
-    /// treat regular and interpolated lifetime identifiers in the same way.
-    Lifetime(Symbol),
-
-    Interpolated(Lrc),
-
-    /// A doc comment token.
-    /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
-    /// similarly to symbols in string literal tokens.
-    DocComment(CommentKind, ast::AttrStyle, Symbol),
-
-    Eof,
-}
-
-// `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(TokenKind, 16);
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
-pub struct Token {
-    pub kind: TokenKind,
-    pub span: Span,
-}
-
-impl TokenKind {
-    pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option) -> TokenKind {
-        Literal(Lit::new(kind, symbol, suffix))
-    }
-
-    // An approximation to proc-macro-style single-character operators used by rustc parser.
-    // If the operator token can be broken into two tokens, the first of which is single-character,
-    // then this function performs that operation, otherwise it returns `None`.
-    pub fn break_two_token_op(&self) -> Option<(TokenKind, TokenKind)> {
-        Some(match *self {
-            Le => (Lt, Eq),
-            EqEq => (Eq, Eq),
-            Ne => (Not, Eq),
-            Ge => (Gt, Eq),
-            AndAnd => (BinOp(And), BinOp(And)),
-            OrOr => (BinOp(Or), BinOp(Or)),
-            BinOp(Shl) => (Lt, Lt),
-            BinOp(Shr) => (Gt, Gt),
-            BinOpEq(Plus) => (BinOp(Plus), Eq),
-            BinOpEq(Minus) => (BinOp(Minus), Eq),
-            BinOpEq(Star) => (BinOp(Star), Eq),
-            BinOpEq(Slash) => (BinOp(Slash), Eq),
-            BinOpEq(Percent) => (BinOp(Percent), Eq),
-            BinOpEq(Caret) => (BinOp(Caret), Eq),
-            BinOpEq(And) => (BinOp(And), Eq),
-            BinOpEq(Or) => (BinOp(Or), Eq),
-            BinOpEq(Shl) => (Lt, Le),
-            BinOpEq(Shr) => (Gt, Ge),
-            DotDot => (Dot, Dot),
-            DotDotDot => (Dot, DotDot),
-            ModSep => (Colon, Colon),
-            RArrow => (BinOp(Minus), Gt),
-            LArrow => (Lt, BinOp(Minus)),
-            FatArrow => (Eq, Gt),
-            _ => return None,
-        })
-    }
-
-    /// Returns tokens that are likely to be typed accidentally instead of the current token.
-    /// Enables better error recovery when the wrong token is found.
-    pub fn similar_tokens(&self) -> Option> {
-        match *self {
-            Comma => Some(vec![Dot, Lt, Semi]),
-            Semi => Some(vec![Colon, Comma]),
-            _ => None,
-        }
-    }
-
-    pub fn should_end_const_arg(&self) -> bool {
-        matches!(self, Gt | Ge | BinOp(Shr) | BinOpEq(Shr))
-    }
-}
-
-impl Token {
-    pub fn new(kind: TokenKind, span: Span) -> Self {
-        Token { kind, span }
-    }
-
-    /// Some token that will be thrown away later.
-    pub fn dummy() -> Self {
-        Token::new(TokenKind::Question, DUMMY_SP)
-    }
-
-    /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary.
-    pub fn from_ast_ident(ident: Ident) -> Self {
-        Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
-    }
-
-    /// Return this token by value and leave a dummy token in its place.
-    pub fn take(&mut self) -> Self {
-        mem::replace(self, Token::dummy())
-    }
-
-    /// For interpolated tokens, returns a span of the fragment to which the interpolated
-    /// token refers. For all other tokens this is just a regular span.
-    /// It is particularly important to use this for identifiers and lifetimes
-    /// for which spans affect name resolution and edition checks.
-    /// Note that keywords are also identifiers, so they should use this
-    /// if they keep spans or perform edition checks.
-    pub fn uninterpolated_span(&self) -> Span {
-        match &self.kind {
-            Interpolated(nt) => nt.span(),
-            _ => self.span,
-        }
-    }
-
-    pub fn is_op(&self) -> bool {
-        !matches!(
-            self.kind,
-            OpenDelim(..)
-                | CloseDelim(..)
-                | Literal(..)
-                | DocComment(..)
-                | Ident(..)
-                | Lifetime(..)
-                | Interpolated(..)
-                | Eof
-        )
-    }
-
-    pub fn is_like_plus(&self) -> bool {
-        matches!(self.kind, BinOp(Plus) | BinOpEq(Plus))
-    }
-
-    /// Returns `true` if the token can appear at the start of an expression.
-    pub fn can_begin_expr(&self) -> bool {
-        match self.uninterpolate().kind {
-            Ident(name, is_raw)              =>
-                ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
-            OpenDelim(..)                     | // tuple, array or block
-            Literal(..)                       | // literal
-            Not                               | // operator not
-            BinOp(Minus)                      | // unary minus
-            BinOp(Star)                       | // dereference
-            BinOp(Or) | OrOr                  | // closure
-            BinOp(And)                        | // reference
-            AndAnd                            | // double reference
-            // DotDotDot is no longer supported, but we need some way to display the error
-            DotDot | DotDotDot | DotDotEq     | // range notation
-            Lt | BinOp(Shl)                   | // associated path
-            ModSep                            | // global path
-            Lifetime(..)                      | // labeled loop
-            Pound                             => true, // expression attributes
-            Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
-                NtExpr(..)    |
-                NtBlock(..)   |
-                NtPath(..)),
-            _ => false,
-        }
-    }
-
-    /// Returns `true` if the token can appear at the start of a type.
-    pub fn can_begin_type(&self) -> bool {
-        match self.uninterpolate().kind {
-            Ident(name, is_raw)        =>
-                ident_can_begin_type(name, self.span, is_raw), // type name or keyword
-            OpenDelim(Paren)            | // tuple
-            OpenDelim(Bracket)          | // array
-            Not                         | // never
-            BinOp(Star)                 | // raw pointer
-            BinOp(And)                  | // reference
-            AndAnd                      | // double reference
-            Question                    | // maybe bound in trait object
-            Lifetime(..)                | // lifetime bound in trait object
-            Lt | BinOp(Shl)             | // associated path
-            ModSep                      => true, // global path
-            Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)),
-            _ => false,
-        }
-    }
-
-    /// Returns `true` if the token can appear at the start of a const param.
-    pub fn can_begin_const_arg(&self) -> bool {
-        match self.kind {
-            OpenDelim(Brace) => true,
-            Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
-            _ => self.can_begin_literal_maybe_minus(),
-        }
-    }
-
-    /// Returns `true` if the token can appear at the start of a generic bound.
-    pub fn can_begin_bound(&self) -> bool {
-        self.is_path_start()
-            || self.is_lifetime()
-            || self.is_keyword(kw::For)
-            || self == &Question
-            || self == &OpenDelim(Paren)
-    }
-
-    /// Returns `true` if the token is any literal.
-    pub fn is_lit(&self) -> bool {
-        matches!(self.kind, Literal(..))
-    }
-
-    /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
-    /// for example a '-42', or one of the boolean idents).
-    ///
-    /// In other words, would this token be a valid start of `parse_literal_maybe_minus`?
-    ///
-    /// Keep this in sync with and `Lit::from_token`, excluding unary negation.
-    pub fn can_begin_literal_maybe_minus(&self) -> bool {
-        match self.uninterpolate().kind {
-            Literal(..) | BinOp(Minus) => true,
-            Ident(name, false) if name.is_bool_lit() => true,
-            Interpolated(ref nt) => match &**nt {
-                NtLiteral(_) => true,
-                NtExpr(e) => match &e.kind {
-                    ast::ExprKind::Lit(_) => true,
-                    ast::ExprKind::Unary(ast::UnOp::Neg, e) => {
-                        matches!(&e.kind, ast::ExprKind::Lit(_))
-                    }
-                    _ => false,
-                },
-                _ => false,
-            },
-            _ => false,
-        }
-    }
-
-    // A convenience function for matching on identifiers during parsing.
-    // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
-    // into the regular identifier or lifetime token it refers to,
-    // otherwise returns the original token.
-    pub fn uninterpolate(&self) -> Cow<'_, Token> {
-        match &self.kind {
-            Interpolated(nt) => match **nt {
-                NtIdent(ident, is_raw) => {
-                    Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
-                }
-                NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
-                _ => Cow::Borrowed(self),
-            },
-            _ => Cow::Borrowed(self),
-        }
-    }
-
-    /// Returns an identifier if this token is an identifier.
-    pub fn ident(&self) -> Option<(Ident, /* is_raw */ bool)> {
-        let token = self.uninterpolate();
-        match token.kind {
-            Ident(name, is_raw) => Some((Ident::new(name, token.span), is_raw)),
-            _ => None,
-        }
-    }
-
-    /// Returns a lifetime identifier if this token is a lifetime.
-    pub fn lifetime(&self) -> Option {
-        let token = self.uninterpolate();
-        match token.kind {
-            Lifetime(name) => Some(Ident::new(name, token.span)),
-            _ => None,
-        }
-    }
-
-    /// Returns `true` if the token is an identifier.
-    pub fn is_ident(&self) -> bool {
-        self.ident().is_some()
-    }
-
-    /// Returns `true` if the token is a lifetime.
-    pub fn is_lifetime(&self) -> bool {
-        self.lifetime().is_some()
-    }
-
-    /// Returns `true` if the token is a identifier whose name is the given
-    /// string slice.
-    pub fn is_ident_named(&self, name: Symbol) -> bool {
-        self.ident().map_or(false, |(ident, _)| ident.name == name)
-    }
-
-    /// Returns `true` if the token is an interpolated path.
-    fn is_path(&self) -> bool {
-        if let Interpolated(ref nt) = self.kind {
-            if let NtPath(..) = **nt {
-                return true;
-            }
-        }
-        false
-    }
-
-    /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
-    /// That is, is this a pre-parsed expression dropped into the token stream
-    /// (which happens while parsing the result of macro expansion)?
-    pub fn is_whole_expr(&self) -> bool {
-        if let Interpolated(ref nt) = self.kind {
-            if let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtIdent(..) | NtBlock(_) = **nt {
-                return true;
-            }
-        }
-
-        false
-    }
-
-    // Is the token an interpolated block (`$b:block`)?
-    pub fn is_whole_block(&self) -> bool {
-        if let Interpolated(ref nt) = self.kind {
-            if let NtBlock(..) = **nt {
-                return true;
-            }
-        }
-        false
-    }
-
-    /// Returns `true` if the token is either the `mut` or `const` keyword.
-    pub fn is_mutability(&self) -> bool {
-        self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
-    }
-
-    pub fn is_qpath_start(&self) -> bool {
-        self == &Lt || self == &BinOp(Shl)
-    }
-
-    pub fn is_path_start(&self) -> bool {
-        self == &ModSep
-            || self.is_qpath_start()
-            || self.is_path()
-            || self.is_path_segment_keyword()
-            || self.is_ident() && !self.is_reserved_ident()
-    }
-
-    /// Returns `true` if the token is a given keyword, `kw`.
-    pub fn is_keyword(&self, kw: Symbol) -> bool {
-        self.is_non_raw_ident_where(|id| id.name == kw)
-    }
-
-    pub fn is_path_segment_keyword(&self) -> bool {
-        self.is_non_raw_ident_where(Ident::is_path_segment_keyword)
-    }
-
-    // Returns true for reserved identifiers used internally for elided lifetimes,
-    // unnamed method parameters, crate root module, error recovery etc.
-    pub fn is_special_ident(&self) -> bool {
-        self.is_non_raw_ident_where(Ident::is_special)
-    }
-
-    /// Returns `true` if the token is a keyword used in the language.
-    pub fn is_used_keyword(&self) -> bool {
-        self.is_non_raw_ident_where(Ident::is_used_keyword)
-    }
-
-    /// Returns `true` if the token is a keyword reserved for possible future use.
-    pub fn is_unused_keyword(&self) -> bool {
-        self.is_non_raw_ident_where(Ident::is_unused_keyword)
-    }
-
-    /// Returns `true` if the token is either a special identifier or a keyword.
-    pub fn is_reserved_ident(&self) -> bool {
-        self.is_non_raw_ident_where(Ident::is_reserved)
-    }
-
-    /// Returns `true` if the token is the identifier `true` or `false`.
-    pub fn is_bool_lit(&self) -> bool {
-        self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
-    }
-
-    /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
-    pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
-        match self.ident() {
-            Some((id, false)) => pred(id),
-            _ => false,
-        }
-    }
-
-    pub fn glue(&self, joint: &Token) -> Option {
-        let kind = match self.kind {
-            Eq => match joint.kind {
-                Eq => EqEq,
-                Gt => FatArrow,
-                _ => return None,
-            },
-            Lt => match joint.kind {
-                Eq => Le,
-                Lt => BinOp(Shl),
-                Le => BinOpEq(Shl),
-                BinOp(Minus) => LArrow,
-                _ => return None,
-            },
-            Gt => match joint.kind {
-                Eq => Ge,
-                Gt => BinOp(Shr),
-                Ge => BinOpEq(Shr),
-                _ => return None,
-            },
-            Not => match joint.kind {
-                Eq => Ne,
-                _ => return None,
-            },
-            BinOp(op) => match joint.kind {
-                Eq => BinOpEq(op),
-                BinOp(And) if op == And => AndAnd,
-                BinOp(Or) if op == Or => OrOr,
-                Gt if op == Minus => RArrow,
-                _ => return None,
-            },
-            Dot => match joint.kind {
-                Dot => DotDot,
-                DotDot => DotDotDot,
-                _ => return None,
-            },
-            DotDot => match joint.kind {
-                Dot => DotDotDot,
-                Eq => DotDotEq,
-                _ => return None,
-            },
-            Colon => match joint.kind {
-                Colon => ModSep,
-                _ => return None,
-            },
-            SingleQuote => match joint.kind {
-                Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
-                _ => return None,
-            },
-
-            Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
-            | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
-            | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
-            | Lifetime(..) | Interpolated(..) | DocComment(..) | Eof => return None,
-        };
-
-        Some(Token::new(kind, self.span.to(joint.span)))
-    }
-}
-
-impl PartialEq for Token {
-    fn eq(&self, rhs: &TokenKind) -> bool {
-        self.kind == *rhs
-    }
-}
-
-#[derive(Clone, Encodable, Decodable)]
-/// For interpolation during macro expansion.
-pub enum Nonterminal {
-    NtItem(P),
-    NtBlock(P),
-    NtStmt(ast::Stmt),
-    NtPat(P),
-    NtExpr(P),
-    NtTy(P),
-    NtIdent(Ident, /* is_raw */ bool),
-    NtLifetime(Ident),
-    NtLiteral(P),
-    /// Stuff inside brackets for attributes
-    NtMeta(P),
-    NtPath(ast::Path),
-    NtVis(ast::Visibility),
-    NtTT(TokenTree),
-}
-
-// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(Nonterminal, 48);
-
-#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
-pub enum NonterminalKind {
-    Item,
-    Block,
-    Stmt,
-    Pat2018 {
-        /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the
-        /// edition of the span. This is used for diagnostics.
-        inferred: bool,
-    },
-    Pat2021 {
-        /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the
-        /// edition of the span. This is used for diagnostics.
-        inferred: bool,
-    },
-    Expr,
-    Ty,
-    Ident,
-    Lifetime,
-    Literal,
-    Meta,
-    Path,
-    Vis,
-    TT,
-}
-
-impl NonterminalKind {
-    /// The `edition` closure is used to get the edition for the given symbol. Doing
-    /// `span.edition()` is expensive, so we do it lazily.
-    pub fn from_symbol(
-        symbol: Symbol,
-        edition: impl FnOnce() -> Edition,
-    ) -> Option {
-        Some(match symbol {
-            sym::item => NonterminalKind::Item,
-            sym::block => NonterminalKind::Block,
-            sym::stmt => NonterminalKind::Stmt,
-            sym::pat => match edition() {
-                Edition::Edition2015 | Edition::Edition2018 => {
-                    NonterminalKind::Pat2018 { inferred: true }
-                }
-                Edition::Edition2021 => NonterminalKind::Pat2021 { inferred: true },
-            },
-            sym::pat2018 => NonterminalKind::Pat2018 { inferred: false },
-            sym::pat2021 => NonterminalKind::Pat2021 { inferred: false },
-            sym::expr => NonterminalKind::Expr,
-            sym::ty => NonterminalKind::Ty,
-            sym::ident => NonterminalKind::Ident,
-            sym::lifetime => NonterminalKind::Lifetime,
-            sym::literal => NonterminalKind::Literal,
-            sym::meta => NonterminalKind::Meta,
-            sym::path => NonterminalKind::Path,
-            sym::vis => NonterminalKind::Vis,
-            sym::tt => NonterminalKind::TT,
-            _ => return None,
-        })
-    }
-    fn symbol(self) -> Symbol {
-        match self {
-            NonterminalKind::Item => sym::item,
-            NonterminalKind::Block => sym::block,
-            NonterminalKind::Stmt => sym::stmt,
-            NonterminalKind::Pat2018 { inferred: false } => sym::pat2018,
-            NonterminalKind::Pat2021 { inferred: false } => sym::pat2021,
-            NonterminalKind::Pat2018 { inferred: true }
-            | NonterminalKind::Pat2021 { inferred: true } => sym::pat,
-            NonterminalKind::Expr => sym::expr,
-            NonterminalKind::Ty => sym::ty,
-            NonterminalKind::Ident => sym::ident,
-            NonterminalKind::Lifetime => sym::lifetime,
-            NonterminalKind::Literal => sym::literal,
-            NonterminalKind::Meta => sym::meta,
-            NonterminalKind::Path => sym::path,
-            NonterminalKind::Vis => sym::vis,
-            NonterminalKind::TT => sym::tt,
-        }
-    }
-}
-
-impl fmt::Display for NonterminalKind {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.symbol())
-    }
-}
-
-impl Nonterminal {
-    pub fn span(&self) -> Span {
-        match self {
-            NtItem(item) => item.span,
-            NtBlock(block) => block.span,
-            NtStmt(stmt) => stmt.span,
-            NtPat(pat) => pat.span,
-            NtExpr(expr) | NtLiteral(expr) => expr.span,
-            NtTy(ty) => ty.span,
-            NtIdent(ident, _) | NtLifetime(ident) => ident.span,
-            NtMeta(attr_item) => attr_item.span(),
-            NtPath(path) => path.span,
-            NtVis(vis) => vis.span,
-            NtTT(tt) => tt.span(),
-        }
-    }
-
-    /// 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
-    /// asserts in old versions of those crates and their wide use in the ecosystem.
-    /// See issue #73345 for more details.
-    /// FIXME(#73933): Remove this eventually.
-    pub fn pretty_printing_compatibility_hack(&self) -> bool {
-        let item = match self {
-            NtItem(item) => item,
-            NtStmt(stmt) => match &stmt.kind {
-                ast::StmtKind::Item(item) => item,
-                _ => return false,
-            },
-            _ => return false,
-        };
-
-        let name = item.ident.name;
-        if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack {
-            if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
-                if let [variant] = &*enum_def.variants {
-                    return variant.ident.name == sym::Input;
-                }
-            }
-        }
-        false
-    }
-
-    // See issue #74616 for details
-    pub fn ident_name_compatibility_hack(
-        &self,
-        orig_span: Span,
-        source_map: &SourceMap,
-    ) -> Option<(Ident, bool)> {
-        if let NtIdent(ident, is_raw) = self {
-            if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
-                let filename = source_map.span_to_filename(orig_span);
-                if let FileName::Real(RealFileName::Named(path)) = filename {
-                    let matches_prefix = |prefix, filename| {
-                        // Check for a path that ends with 'prefix*/src/'
-                        let mut iter = path.components().rev();
-                        iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename)
-                            && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
-                            && iter
-                                .next()
-                                .and_then(|p| p.as_os_str().to_str())
-                                .map_or(false, |p| p.starts_with(prefix))
-                    };
-
-                    if (macro_name == sym::impl_macros
-                        && matches_prefix("time-macros-impl", "lib.rs"))
-                        || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"))
-                    {
-                        let snippet = source_map.span_to_snippet(orig_span);
-                        if snippet.as_deref() == Ok("$name") {
-                            return Some((*ident, *is_raw));
-                        }
-                    }
-
-                    if macro_name == sym::tuple_from_req
-                        && (matches_prefix("actix-web", "extract.rs")
-                            || matches_prefix("actori-web", "extract.rs"))
-                    {
-                        let snippet = source_map.span_to_snippet(orig_span);
-                        if snippet.as_deref() == Ok("$T") {
-                            return Some((*ident, *is_raw));
-                        }
-                    }
-                }
-            }
-        }
-        None
-    }
-}
-
-impl PartialEq for Nonterminal {
-    fn eq(&self, rhs: &Self) -> bool {
-        match (self, rhs) {
-            (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) => {
-                ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
-            }
-            (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
-            (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
-            // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
-            // correctly based on data from AST. This will prevent them from matching each other
-            // in macros. The comparison will become possible only when each nonterminal has an
-            // attached token stream from which it was parsed.
-            _ => false,
-        }
-    }
-}
-
-impl fmt::Debug for Nonterminal {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            NtItem(..) => f.pad("NtItem(..)"),
-            NtBlock(..) => f.pad("NtBlock(..)"),
-            NtStmt(..) => f.pad("NtStmt(..)"),
-            NtPat(..) => f.pad("NtPat(..)"),
-            NtExpr(..) => f.pad("NtExpr(..)"),
-            NtTy(..) => f.pad("NtTy(..)"),
-            NtIdent(..) => f.pad("NtIdent(..)"),
-            NtLiteral(..) => f.pad("NtLiteral(..)"),
-            NtMeta(..) => f.pad("NtMeta(..)"),
-            NtPath(..) => f.pad("NtPath(..)"),
-            NtTT(..) => f.pad("NtTT(..)"),
-            NtVis(..) => f.pad("NtVis(..)"),
-            NtLifetime(..) => f.pad("NtLifetime(..)"),
-        }
-    }
-}
-
-impl HashStable for Nonterminal
-where
-    CTX: crate::HashStableContext,
-{
-    fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
-        panic!("interpolated tokens should not be present in the HIR")
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/tokenstream.rs b/vendor/rustc-ap-rustc_ast/src/tokenstream.rs
deleted file mode 100644
index 9ac05f316f..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/tokenstream.rs
+++ /dev/null
@@ -1,517 +0,0 @@
-//! # Token Streams
-//!
-//! `TokenStream`s represent syntactic objects before they are converted into ASTs.
-//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
-//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
-//!
-//! ## Ownership
-//!
-//! `TokenStream`s are persistent data structures constructed as ropes with reference
-//! counted-children. In general, this means that calling an operation on a `TokenStream`
-//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
-//! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
-//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
-//! ownership of the original.
-
-use crate::token::{self, DelimToken, Token, TokenKind};
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::{self, Lrc};
-use rustc_macros::HashStable_Generic;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_span::{Span, DUMMY_SP};
-use smallvec::{smallvec, SmallVec};
-
-use std::{fmt, iter, mem};
-
-/// When the main Rust parser encounters a syntax-extension invocation, it
-/// parses the arguments to the invocation as a token tree. This is a very
-/// loose structure, such that all sorts of different AST fragments can
-/// be passed to syntax extensions using a uniform type.
-///
-/// If the syntax extension is an MBE macro, it will attempt to match its
-/// LHS token tree against the provided token tree, and if it finds a
-/// match, will transcribe the RHS token tree, splicing in any captured
-/// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
-///
-/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
-/// Nothing special happens to misnamed or misplaced `SubstNt`s.
-#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
-pub enum TokenTree {
-    /// A single token.
-    Token(Token),
-    /// A delimited sequence of token trees.
-    Delimited(DelimSpan, DelimToken, TokenStream),
-}
-
-#[derive(Copy, Clone)]
-pub enum CanSynthesizeMissingTokens {
-    Yes,
-    No,
-}
-
-// Ensure all fields of `TokenTree` is `Send` and `Sync`.
-#[cfg(parallel_compiler)]
-fn _dummy()
-where
-    Token: Send + Sync,
-    DelimSpan: Send + Sync,
-    DelimToken: Send + Sync,
-    TokenStream: Send + Sync,
-{
-}
-
-impl TokenTree {
-    /// Checks if this `TokenTree` is equal to the other, regardless of span information.
-    pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
-        match (self, other) {
-            (TokenTree::Token(token), TokenTree::Token(token2)) => token.kind == token2.kind,
-            (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
-                delim == delim2 && tts.eq_unspanned(&tts2)
-            }
-            _ => false,
-        }
-    }
-
-    /// Retrieves the `TokenTree`'s span.
-    pub fn span(&self) -> Span {
-        match self {
-            TokenTree::Token(token) => token.span,
-            TokenTree::Delimited(sp, ..) => sp.entire(),
-        }
-    }
-
-    /// Modify the `TokenTree`'s span in-place.
-    pub fn set_span(&mut self, span: Span) {
-        match self {
-            TokenTree::Token(token) => token.span = span,
-            TokenTree::Delimited(dspan, ..) => *dspan = DelimSpan::from_single(span),
-        }
-    }
-
-    pub fn joint(self) -> TokenStream {
-        TokenStream::new(vec![(self, Spacing::Joint)])
-    }
-
-    pub fn token(kind: TokenKind, span: Span) -> TokenTree {
-        TokenTree::Token(Token::new(kind, span))
-    }
-
-    /// Returns the opening delimiter as a token tree.
-    pub fn open_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
-        TokenTree::token(token::OpenDelim(delim), span.open)
-    }
-
-    /// Returns the closing delimiter as a token tree.
-    pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
-        TokenTree::token(token::CloseDelim(delim), span.close)
-    }
-
-    pub fn uninterpolate(self) -> TokenTree {
-        match self {
-            TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()),
-            tt => tt,
-        }
-    }
-}
-
-impl HashStable for TokenStream
-where
-    CTX: crate::HashStableContext,
-{
-    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        for sub_tt in self.trees() {
-            sub_tt.hash_stable(hcx, hasher);
-        }
-    }
-}
-
-pub trait CreateTokenStream: sync::Send + sync::Sync {
-    fn create_token_stream(&self) -> TokenStream;
-}
-
-impl CreateTokenStream for TokenStream {
-    fn create_token_stream(&self) -> TokenStream {
-        self.clone()
-    }
-}
-
-/// A lazy version of [`TokenStream`], which defers creation
-/// of an actual `TokenStream` until it is needed.
-/// `Box` is here only to reduce the structure size.
-#[derive(Clone)]
-pub struct LazyTokenStream(Lrc>);
-
-impl LazyTokenStream {
-    pub fn new(inner: impl CreateTokenStream + 'static) -> LazyTokenStream {
-        LazyTokenStream(Lrc::new(Box::new(inner)))
-    }
-
-    pub fn create_token_stream(&self) -> TokenStream {
-        self.0.create_token_stream()
-    }
-}
-
-impl fmt::Debug for LazyTokenStream {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt("LazyTokenStream", f)
-    }
-}
-
-impl Encodable for LazyTokenStream {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        // Used by AST json printing.
-        Encodable::encode(&self.create_token_stream(), s)
-    }
-}
-
-impl Decodable for LazyTokenStream {
-    fn decode(_d: &mut D) -> Result {
-        panic!("Attempted to decode LazyTokenStream");
-    }
-}
-
-impl HashStable for LazyTokenStream {
-    fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
-        panic!("Attempted to compute stable hash for LazyTokenStream");
-    }
-}
-
-/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
-///
-/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
-/// instead of a representation of the abstract syntax tree.
-/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
-/// backwards compatability.
-#[derive(Clone, Debug, Default, Encodable, Decodable)]
-pub struct TokenStream(pub(crate) Lrc>);
-
-pub type TreeAndSpacing = (TokenTree, Spacing);
-
-// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(TokenStream, 8);
-
-#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
-pub enum Spacing {
-    Alone,
-    Joint,
-}
-
-impl TokenStream {
-    /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
-    /// separating the two arguments with a comma for diagnostic suggestions.
-    pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
-        // Used to suggest if a user writes `foo!(a b);`
-        let mut suggestion = None;
-        let mut iter = self.0.iter().enumerate().peekable();
-        while let Some((pos, ts)) = iter.next() {
-            if let Some((_, next)) = iter.peek() {
-                let sp = match (&ts, &next) {
-                    (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue,
-                    (
-                        (TokenTree::Token(token_left), Spacing::Alone),
-                        (TokenTree::Token(token_right), _),
-                    ) if ((token_left.is_ident() && !token_left.is_reserved_ident())
-                        || token_left.is_lit())
-                        && ((token_right.is_ident() && !token_right.is_reserved_ident())
-                            || token_right.is_lit()) =>
-                    {
-                        token_left.span
-                    }
-                    ((TokenTree::Delimited(sp, ..), Spacing::Alone), _) => sp.entire(),
-                    _ => continue,
-                };
-                let sp = sp.shrink_to_hi();
-                let comma = (TokenTree::token(token::Comma, sp), Spacing::Alone);
-                suggestion = Some((pos, comma, sp));
-            }
-        }
-        if let Some((pos, comma, sp)) = suggestion {
-            let mut new_stream = Vec::with_capacity(self.0.len() + 1);
-            let parts = self.0.split_at(pos + 1);
-            new_stream.extend_from_slice(parts.0);
-            new_stream.push(comma);
-            new_stream.extend_from_slice(parts.1);
-            return Some((TokenStream::new(new_stream), sp));
-        }
-        None
-    }
-}
-
-impl From for TokenStream {
-    fn from(tree: TokenTree) -> TokenStream {
-        TokenStream::new(vec![(tree, Spacing::Alone)])
-    }
-}
-
-impl From for TreeAndSpacing {
-    fn from(tree: TokenTree) -> TreeAndSpacing {
-        (tree, Spacing::Alone)
-    }
-}
-
-impl iter::FromIterator for TokenStream {
-    fn from_iter>(iter: I) -> Self {
-        TokenStream::new(iter.into_iter().map(Into::into).collect::>())
-    }
-}
-
-impl Eq for TokenStream {}
-
-impl PartialEq for TokenStream {
-    fn eq(&self, other: &TokenStream) -> bool {
-        self.trees().eq(other.trees())
-    }
-}
-
-impl TokenStream {
-    pub fn new(streams: Vec) -> TokenStream {
-        TokenStream(Lrc::new(streams))
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.0.is_empty()
-    }
-
-    pub fn len(&self) -> usize {
-        self.0.len()
-    }
-
-    pub fn span(&self) -> Option {
-        match &**self.0 {
-            [] => None,
-            [(tt, _)] => Some(tt.span()),
-            [(tt_start, _), .., (tt_end, _)] => Some(tt_start.span().to(tt_end.span())),
-        }
-    }
-
-    pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream {
-        match streams.len() {
-            0 => TokenStream::default(),
-            1 => streams.pop().unwrap(),
-            _ => {
-                // We are going to extend the first stream in `streams` with
-                // the elements from the subsequent streams. This requires
-                // using `make_mut()` on the first stream, and in practice this
-                // doesn't cause cloning 99.9% of the time.
-                //
-                // One very common use case is when `streams` has two elements,
-                // where the first stream has any number of elements within
-                // (often 1, but sometimes many more) and the second stream has
-                // a single element within.
-
-                // Determine how much the first stream will be extended.
-                // Needed to avoid quadratic blow up from on-the-fly
-                // reallocations (#57735).
-                let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
-
-                // Get the first stream. If it's `None`, create an empty
-                // stream.
-                let mut iter = streams.drain(..);
-                let mut first_stream_lrc = iter.next().unwrap().0;
-
-                // Append the elements to the first stream, after reserving
-                // space for them.
-                let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc);
-                first_vec_mut.reserve(num_appends);
-                for stream in iter {
-                    first_vec_mut.extend(stream.0.iter().cloned());
-                }
-
-                // Create the final `TokenStream`.
-                TokenStream(first_stream_lrc)
-            }
-        }
-    }
-
-    pub fn trees_ref(&self) -> CursorRef<'_> {
-        CursorRef::new(self)
-    }
-
-    pub fn trees(&self) -> Cursor {
-        self.clone().into_trees()
-    }
-
-    pub fn into_trees(self) -> Cursor {
-        Cursor::new(self)
-    }
-
-    /// Compares two `TokenStream`s, checking equality without regarding span information.
-    pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
-        let mut t1 = self.trees();
-        let mut t2 = other.trees();
-        for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
-            if !t1.eq_unspanned(&t2) {
-                return false;
-            }
-        }
-        t1.next().is_none() && t2.next().is_none()
-    }
-
-    pub fn map_enumerated TokenTree>(self, mut f: F) -> TokenStream {
-        TokenStream(Lrc::new(
-            self.0
-                .iter()
-                .enumerate()
-                .map(|(i, (tree, is_joint))| (f(i, tree), *is_joint))
-                .collect(),
-        ))
-    }
-}
-
-// 99.5%+ of the time we have 1 or 2 elements in this vector.
-#[derive(Clone)]
-pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>);
-
-impl TokenStreamBuilder {
-    pub fn new() -> TokenStreamBuilder {
-        TokenStreamBuilder(SmallVec::new())
-    }
-
-    pub fn push>(&mut self, stream: T) {
-        let mut stream = stream.into();
-
-        // If `self` is not empty and the last tree within the last stream is a
-        // token tree marked with `Joint`...
-        if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut() {
-            if let Some((TokenTree::Token(last_token), Spacing::Joint)) = last_stream_lrc.last() {
-                // ...and `stream` is not empty and the first tree within it is
-                // a token tree...
-                let TokenStream(ref mut stream_lrc) = stream;
-                if let Some((TokenTree::Token(token), spacing)) = stream_lrc.first() {
-                    // ...and the two tokens can be glued together...
-                    if let Some(glued_tok) = last_token.glue(&token) {
-                        // ...then do so, by overwriting the last token
-                        // tree in `self` and removing the first token tree
-                        // from `stream`. This requires using `make_mut()`
-                        // on the last stream in `self` and on `stream`,
-                        // and in practice this doesn't cause cloning 99.9%
-                        // of the time.
-
-                        // Overwrite the last token tree with the merged
-                        // token.
-                        let last_vec_mut = Lrc::make_mut(last_stream_lrc);
-                        *last_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
-
-                        // Remove the first token tree from `stream`. (This
-                        // is almost always the only tree in `stream`.)
-                        let stream_vec_mut = Lrc::make_mut(stream_lrc);
-                        stream_vec_mut.remove(0);
-
-                        // Don't push `stream` if it's empty -- that could
-                        // block subsequent token gluing, by getting
-                        // between two token trees that should be glued
-                        // together.
-                        if !stream.is_empty() {
-                            self.0.push(stream);
-                        }
-                        return;
-                    }
-                }
-            }
-        }
-        self.0.push(stream);
-    }
-
-    pub fn build(self) -> TokenStream {
-        TokenStream::from_streams(self.0)
-    }
-}
-
-/// By-reference iterator over a [`TokenStream`].
-#[derive(Clone)]
-pub struct CursorRef<'t> {
-    stream: &'t TokenStream,
-    index: usize,
-}
-
-impl<'t> CursorRef<'t> {
-    fn new(stream: &TokenStream) -> CursorRef<'_> {
-        CursorRef { stream, index: 0 }
-    }
-
-    fn next_with_spacing(&mut self) -> Option<&'t TreeAndSpacing> {
-        self.stream.0.get(self.index).map(|tree| {
-            self.index += 1;
-            tree
-        })
-    }
-}
-
-impl<'t> Iterator for CursorRef<'t> {
-    type Item = &'t TokenTree;
-
-    fn next(&mut self) -> Option<&'t TokenTree> {
-        self.next_with_spacing().map(|(tree, _)| tree)
-    }
-}
-
-/// Owning by-value iterator over a [`TokenStream`].
-// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
-#[derive(Clone)]
-pub struct Cursor {
-    pub stream: TokenStream,
-    index: usize,
-}
-
-impl Iterator for Cursor {
-    type Item = TokenTree;
-
-    fn next(&mut self) -> Option {
-        self.next_with_spacing().map(|(tree, _)| tree)
-    }
-}
-
-impl Cursor {
-    fn new(stream: TokenStream) -> Self {
-        Cursor { stream, index: 0 }
-    }
-
-    pub fn next_with_spacing(&mut self) -> Option {
-        if self.index < self.stream.len() {
-            self.index += 1;
-            Some(self.stream.0[self.index - 1].clone())
-        } else {
-            None
-        }
-    }
-
-    pub fn append(&mut self, new_stream: TokenStream) {
-        if new_stream.is_empty() {
-            return;
-        }
-        let index = self.index;
-        let stream = mem::take(&mut self.stream);
-        *self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees();
-        self.index = index;
-    }
-
-    pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
-        self.stream.0[self.index..].get(n).map(|(tree, _)| tree)
-    }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
-pub struct DelimSpan {
-    pub open: Span,
-    pub close: Span,
-}
-
-impl DelimSpan {
-    pub fn from_single(sp: Span) -> Self {
-        DelimSpan { open: sp, close: sp }
-    }
-
-    pub fn from_pair(open: Span, close: Span) -> Self {
-        DelimSpan { open, close }
-    }
-
-    pub fn dummy() -> Self {
-        Self::from_single(DUMMY_SP)
-    }
-
-    pub fn entire(self) -> Span {
-        self.open.with_hi(self.close.hi())
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/util/classify.rs b/vendor/rustc-ap-rustc_ast/src/util/classify.rs
deleted file mode 100644
index 90786520fe..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/util/classify.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//! Routines the parser uses to classify AST nodes
-
-// Predicates on exprs and stmts that the pretty-printer and parser use
-
-use crate::ast;
-
-/// Does this expression require a semicolon to be treated
-/// as a statement? The negation of this: 'can this expression
-/// be used as a statement without a semicolon' -- is used
-/// as an early-bail-out in the parser so that, for instance,
-///     if true {...} else {...}
-///      |x| 5
-/// isn't parsed as (if true {...} else {...} | x) | 5
-pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
-    !matches!(
-        e.kind,
-        ast::ExprKind::If(..)
-            | ast::ExprKind::Match(..)
-            | ast::ExprKind::Block(..)
-            | ast::ExprKind::While(..)
-            | ast::ExprKind::Loop(..)
-            | ast::ExprKind::ForLoop(..)
-            | ast::ExprKind::TryBlock(..)
-    )
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/util/comments.rs b/vendor/rustc-ap-rustc_ast/src/util/comments.rs
deleted file mode 100644
index 542a330a03..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/util/comments.rs
+++ /dev/null
@@ -1,222 +0,0 @@
-use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol};
-
-#[cfg(test)]
-mod tests;
-
-#[derive(Clone, Copy, PartialEq, Debug)]
-pub enum CommentStyle {
-    /// No code on either side of each line of the comment
-    Isolated,
-    /// Code exists to the left of the comment
-    Trailing,
-    /// Code before /* foo */ and after the comment
-    Mixed,
-    /// Just a manual blank line "\n\n", for layout
-    BlankLine,
-}
-
-#[derive(Clone)]
-pub struct Comment {
-    pub style: CommentStyle,
-    pub lines: Vec,
-    pub pos: BytePos,
-}
-
-/// Makes a doc string more presentable to users.
-/// Used by rustdoc and perhaps other tools, but not by rustc.
-pub fn beautify_doc_string(data: Symbol) -> Symbol {
-    fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
-        let mut i = 0;
-        let mut j = lines.len();
-        // first line of all-stars should be omitted
-        if !lines.is_empty() && lines[0].chars().all(|c| c == '*') {
-            i += 1;
-        }
-
-        while i < j && lines[i].trim().is_empty() {
-            i += 1;
-        }
-        // like the first, a last line of all stars should be omitted
-        if j > i && lines[j - 1].chars().skip(1).all(|c| c == '*') {
-            j -= 1;
-        }
-
-        while j > i && lines[j - 1].trim().is_empty() {
-            j -= 1;
-        }
-
-        if i != 0 || j != lines.len() { Some((i, j)) } else { None }
-    }
-
-    fn get_horizontal_trim(lines: &[&str]) -> Option {
-        let mut i = usize::MAX;
-        let mut first = true;
-
-        for line in lines {
-            for (j, c) in line.chars().enumerate() {
-                if j > i || !"* \t".contains(c) {
-                    return None;
-                }
-                if c == '*' {
-                    if first {
-                        i = j;
-                        first = false;
-                    } else if i != j {
-                        return None;
-                    }
-                    break;
-                }
-            }
-            if i >= line.len() {
-                return None;
-            }
-        }
-        Some(i)
-    }
-
-    let data_s = data.as_str();
-    if data_s.contains('\n') {
-        let mut lines = data_s.lines().collect::>();
-        let mut changes = false;
-        let lines = if let Some((i, j)) = get_vertical_trim(&lines) {
-            changes = true;
-            // remove whitespace-only lines from the start/end of lines
-            &mut lines[i..j]
-        } else {
-            &mut lines
-        };
-        if let Some(horizontal) = get_horizontal_trim(&lines) {
-            changes = true;
-            // remove a "[ \t]*\*" block from each line, if possible
-            for line in lines.iter_mut() {
-                *line = &line[horizontal + 1..];
-            }
-        }
-        if changes {
-            return Symbol::intern(&lines.join("\n"));
-        }
-    }
-    data
-}
-
-/// Returns `None` if the first `col` chars of `s` contain a non-whitespace char.
-/// Otherwise returns `Some(k)` where `k` is first char offset after that leading
-/// whitespace. Note that `k` may be outside bounds of `s`.
-fn all_whitespace(s: &str, col: CharPos) -> Option {
-    let mut idx = 0;
-    for (i, ch) in s.char_indices().take(col.to_usize()) {
-        if !ch.is_whitespace() {
-            return None;
-        }
-        idx = i + ch.len_utf8();
-    }
-    Some(idx)
-}
-
-fn trim_whitespace_prefix(s: &str, col: CharPos) -> &str {
-    let len = s.len();
-    match all_whitespace(&s, col) {
-        Some(col) => {
-            if col < len {
-                &s[col..]
-            } else {
-                ""
-            }
-        }
-        None => s,
-    }
-}
-
-fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec {
-    let mut res: Vec = vec![];
-    let mut lines = text.lines();
-    // just push the first line
-    res.extend(lines.next().map(|it| it.to_string()));
-    // for other lines, strip common whitespace prefix
-    for line in lines {
-        res.push(trim_whitespace_prefix(line, col).to_string())
-    }
-    res
-}
-
-// it appears this function is called only from pprust... that's
-// probably not a good thing.
-pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec {
-    let sm = SourceMap::new(sm.path_mapping().clone());
-    let source_file = sm.new_source_file(path, src);
-    let text = (*source_file.src.as_ref().unwrap()).clone();
-
-    let text: &str = text.as_str();
-    let start_bpos = source_file.start_pos;
-    let mut pos = 0;
-    let mut comments: Vec = Vec::new();
-    let mut code_to_the_left = false;
-
-    if let Some(shebang_len) = rustc_lexer::strip_shebang(text) {
-        comments.push(Comment {
-            style: CommentStyle::Isolated,
-            lines: vec![text[..shebang_len].to_string()],
-            pos: start_bpos,
-        });
-        pos += shebang_len;
-    }
-
-    for token in rustc_lexer::tokenize(&text[pos..]) {
-        let token_text = &text[pos..pos + token.len];
-        match token.kind {
-            rustc_lexer::TokenKind::Whitespace => {
-                if let Some(mut idx) = token_text.find('\n') {
-                    code_to_the_left = false;
-                    while let Some(next_newline) = &token_text[idx + 1..].find('\n') {
-                        idx = idx + 1 + next_newline;
-                        comments.push(Comment {
-                            style: CommentStyle::BlankLine,
-                            lines: vec![],
-                            pos: start_bpos + BytePos((pos + idx) as u32),
-                        });
-                    }
-                }
-            }
-            rustc_lexer::TokenKind::BlockComment { doc_style, .. } => {
-                if doc_style.is_none() {
-                    let code_to_the_right =
-                        !matches!(text[pos + token.len..].chars().next(), Some('\r' | '\n'));
-                    let style = match (code_to_the_left, code_to_the_right) {
-                        (_, true) => CommentStyle::Mixed,
-                        (false, false) => CommentStyle::Isolated,
-                        (true, false) => CommentStyle::Trailing,
-                    };
-
-                    // Count the number of chars since the start of the line by rescanning.
-                    let pos_in_file = start_bpos + BytePos(pos as u32);
-                    let line_begin_in_file = source_file.line_begin_pos(pos_in_file);
-                    let line_begin_pos = (line_begin_in_file - start_bpos).to_usize();
-                    let col = CharPos(text[line_begin_pos..pos].chars().count());
-
-                    let lines = split_block_comment_into_lines(token_text, col);
-                    comments.push(Comment { style, lines, pos: pos_in_file })
-                }
-            }
-            rustc_lexer::TokenKind::LineComment { doc_style } => {
-                if doc_style.is_none() {
-                    comments.push(Comment {
-                        style: if code_to_the_left {
-                            CommentStyle::Trailing
-                        } else {
-                            CommentStyle::Isolated
-                        },
-                        lines: vec![token_text.to_string()],
-                        pos: start_bpos + BytePos(pos as u32),
-                    })
-                }
-            }
-            _ => {
-                code_to_the_left = true;
-            }
-        }
-        pos += token.len;
-    }
-
-    comments
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/util/comments/tests.rs b/vendor/rustc-ap-rustc_ast/src/util/comments/tests.rs
deleted file mode 100644
index 98ab653e45..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/util/comments/tests.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use super::*;
-use rustc_span::with_default_session_globals;
-
-#[test]
-fn test_block_doc_comment_1() {
-    with_default_session_globals(|| {
-        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");
-    })
-}
-
-#[test]
-fn test_block_doc_comment_2() {
-    with_default_session_globals(|| {
-        let comment = "\n * Test\n *  Test\n";
-        let stripped = beautify_doc_string(Symbol::intern(comment));
-        assert_eq!(stripped.as_str(), " Test\n  Test");
-    })
-}
-
-#[test]
-fn test_block_doc_comment_3() {
-    with_default_session_globals(|| {
-        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;");
-    })
-}
-
-#[test]
-fn test_line_doc_comment() {
-    with_default_session_globals(|| {
-        let stripped = beautify_doc_string(Symbol::intern(" test"));
-        assert_eq!(stripped.as_str(), " test");
-        let stripped = beautify_doc_string(Symbol::intern("! test"));
-        assert_eq!(stripped.as_str(), "! test");
-        let stripped = beautify_doc_string(Symbol::intern("test"));
-        assert_eq!(stripped.as_str(), "test");
-        let stripped = beautify_doc_string(Symbol::intern("!test"));
-        assert_eq!(stripped.as_str(), "!test");
-    })
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/util/literal.rs b/vendor/rustc-ap-rustc_ast/src/util/literal.rs
deleted file mode 100644
index 2124f1efb9..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/util/literal.rs
+++ /dev/null
@@ -1,315 +0,0 @@
-//! Code related to parsing literals.
-
-use crate::ast::{self, Lit, LitKind};
-use crate::token::{self, Token};
-
-use rustc_lexer::unescape::{unescape_byte, unescape_char};
-use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
-use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
-
-use std::ascii;
-use tracing::debug;
-
-pub enum LitError {
-    NotLiteral,
-    LexerError,
-    InvalidSuffix,
-    InvalidIntSuffix,
-    InvalidFloatSuffix,
-    NonDecimalFloat(u32),
-    IntTooLarge,
-}
-
-impl LitKind {
-    /// Converts literal token into a semantic literal.
-    fn from_lit_token(lit: token::Lit) -> Result {
-        let token::Lit { kind, symbol, suffix } = lit;
-        if suffix.is_some() && !kind.may_have_suffix() {
-            return Err(LitError::InvalidSuffix);
-        }
-
-        Ok(match kind {
-            token::Bool => {
-                assert!(symbol.is_bool_lit());
-                LitKind::Bool(symbol == kw::True)
-            }
-            token::Byte => {
-                return unescape_byte(&symbol.as_str())
-                    .map(LitKind::Byte)
-                    .map_err(|_| LitError::LexerError);
-            }
-            token::Char => {
-                return unescape_char(&symbol.as_str())
-                    .map(LitKind::Char)
-                    .map_err(|_| LitError::LexerError);
-            }
-
-            // There are some valid suffixes for integer and float literals,
-            // so all the handling is done internally.
-            token::Integer => return integer_lit(symbol, suffix),
-            token::Float => return float_lit(symbol, suffix),
-
-            token::Str => {
-                // If there are no characters requiring special treatment we can
-                // reuse the symbol from the token. Otherwise, we must generate a
-                // new symbol because the string in the LitKind is different to the
-                // string in the token.
-                let s = symbol.as_str();
-                let symbol =
-                    if s.contains(&['\\', '\r'][..]) {
-                        let mut buf = String::with_capacity(s.len());
-                        let mut error = Ok(());
-                        unescape_literal(&s, Mode::Str, &mut |_, unescaped_char| {
-                            match unescaped_char {
-                                Ok(c) => buf.push(c),
-                                Err(_) => error = Err(LitError::LexerError),
-                            }
-                        });
-                        error?;
-                        Symbol::intern(&buf)
-                    } else {
-                        symbol
-                    };
-                LitKind::Str(symbol, ast::StrStyle::Cooked)
-            }
-            token::StrRaw(n) => {
-                // Ditto.
-                let s = symbol.as_str();
-                let symbol =
-                    if s.contains('\r') {
-                        let mut buf = String::with_capacity(s.len());
-                        let mut error = Ok(());
-                        unescape_literal(&s, Mode::RawStr, &mut |_, unescaped_char| {
-                            match unescaped_char {
-                                Ok(c) => buf.push(c),
-                                Err(_) => error = Err(LitError::LexerError),
-                            }
-                        });
-                        error?;
-                        Symbol::intern(&buf)
-                    } else {
-                        symbol
-                    };
-                LitKind::Str(symbol, ast::StrStyle::Raw(n))
-            }
-            token::ByteStr => {
-                let s = symbol.as_str();
-                let mut buf = Vec::with_capacity(s.len());
-                let mut error = Ok(());
-                unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| {
-                    match unescaped_byte {
-                        Ok(c) => buf.push(c),
-                        Err(_) => error = Err(LitError::LexerError),
-                    }
-                });
-                error?;
-                LitKind::ByteStr(buf.into())
-            }
-            token::ByteStrRaw(_) => {
-                let s = symbol.as_str();
-                let bytes = if s.contains('\r') {
-                    let mut buf = Vec::with_capacity(s.len());
-                    let mut error = Ok(());
-                    unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| {
-                        match unescaped_byte {
-                            Ok(c) => buf.push(c),
-                            Err(_) => error = Err(LitError::LexerError),
-                        }
-                    });
-                    error?;
-                    buf
-                } else {
-                    symbol.to_string().into_bytes()
-                };
-
-                LitKind::ByteStr(bytes.into())
-            }
-            token::Err => LitKind::Err(symbol),
-        })
-    }
-
-    /// Attempts to recover a token from semantic literal.
-    /// This function is used when the original token doesn't exist (e.g. the literal is created
-    /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
-    pub fn to_lit_token(&self) -> token::Lit {
-        let (kind, symbol, suffix) = match *self {
-            LitKind::Str(symbol, ast::StrStyle::Cooked) => {
-                // Don't re-intern unless the escaped string is different.
-                let s = symbol.as_str();
-                let escaped = s.escape_default().to_string();
-                let symbol = if s == escaped { symbol } else { Symbol::intern(&escaped) };
-                (token::Str, symbol, None)
-            }
-            LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None),
-            LitKind::ByteStr(ref bytes) => {
-                let string = bytes
-                    .iter()
-                    .cloned()
-                    .flat_map(ascii::escape_default)
-                    .map(Into::::into)
-                    .collect::();
-                (token::ByteStr, Symbol::intern(&string), None)
-            }
-            LitKind::Byte(byte) => {
-                let string: String = ascii::escape_default(byte).map(Into::::into).collect();
-                (token::Byte, Symbol::intern(&string), None)
-            }
-            LitKind::Char(ch) => {
-                let string: String = ch.escape_default().map(Into::::into).collect();
-                (token::Char, Symbol::intern(&string), None)
-            }
-            LitKind::Int(n, ty) => {
-                let suffix = match ty {
-                    ast::LitIntType::Unsigned(ty) => Some(ty.name()),
-                    ast::LitIntType::Signed(ty) => Some(ty.name()),
-                    ast::LitIntType::Unsuffixed => None,
-                };
-                (token::Integer, sym::integer(n), suffix)
-            }
-            LitKind::Float(symbol, ty) => {
-                let suffix = match ty {
-                    ast::LitFloatType::Suffixed(ty) => Some(ty.name()),
-                    ast::LitFloatType::Unsuffixed => None,
-                };
-                (token::Float, symbol, suffix)
-            }
-            LitKind::Bool(value) => {
-                let symbol = if value { kw::True } else { kw::False };
-                (token::Bool, symbol, None)
-            }
-            LitKind::Err(symbol) => (token::Err, symbol, None),
-        };
-
-        token::Lit::new(kind, symbol, suffix)
-    }
-}
-
-impl Lit {
-    /// Converts literal token into an AST literal.
-    pub fn from_lit_token(token: token::Lit, span: Span) -> Result {
-        Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span })
-    }
-
-    /// Converts arbitrary token into an AST literal.
-    ///
-    /// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation.
-    pub fn from_token(token: &Token) -> Result {
-        let lit = match token.uninterpolate().kind {
-            token::Ident(name, false) if name.is_bool_lit() => {
-                token::Lit::new(token::Bool, name, None)
-            }
-            token::Literal(lit) => lit,
-            token::Interpolated(ref nt) => {
-                if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt {
-                    if let ast::ExprKind::Lit(lit) = &expr.kind {
-                        return Ok(lit.clone());
-                    }
-                }
-                return Err(LitError::NotLiteral);
-            }
-            _ => return Err(LitError::NotLiteral),
-        };
-
-        Lit::from_lit_token(lit, token.span)
-    }
-
-    /// Attempts to recover an AST literal from semantic literal.
-    /// This function is used when the original token doesn't exist (e.g. the literal is created
-    /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
-    pub fn from_lit_kind(kind: LitKind, span: Span) -> Lit {
-        Lit { token: kind.to_lit_token(), kind, span }
-    }
-
-    /// Losslessly convert an AST literal into a token.
-    pub fn to_token(&self) -> Token {
-        let kind = match self.token.kind {
-            token::Bool => token::Ident(self.token.symbol, false),
-            _ => token::Literal(self.token),
-        };
-        Token::new(kind, self.span)
-    }
-}
-
-fn strip_underscores(symbol: Symbol) -> Symbol {
-    // Do not allocate a new string unless necessary.
-    let s = symbol.as_str();
-    if s.contains('_') {
-        let mut s = s.to_string();
-        s.retain(|c| c != '_');
-        return Symbol::intern(&s);
-    }
-    symbol
-}
-
-fn filtered_float_lit(
-    symbol: Symbol,
-    suffix: Option,
-    base: u32,
-) -> Result {
-    debug!("filtered_float_lit: {:?}, {:?}, {:?}", symbol, suffix, base);
-    if base != 10 {
-        return Err(LitError::NonDecimalFloat(base));
-    }
-    Ok(match suffix {
-        Some(suf) => LitKind::Float(
-            symbol,
-            ast::LitFloatType::Suffixed(match suf {
-                sym::f32 => ast::FloatTy::F32,
-                sym::f64 => ast::FloatTy::F64,
-                _ => return Err(LitError::InvalidFloatSuffix),
-            }),
-        ),
-        None => LitKind::Float(symbol, ast::LitFloatType::Unsuffixed),
-    })
-}
-
-fn float_lit(symbol: Symbol, suffix: Option) -> Result {
-    debug!("float_lit: {:?}, {:?}", symbol, suffix);
-    filtered_float_lit(strip_underscores(symbol), suffix, 10)
-}
-
-fn integer_lit(symbol: Symbol, suffix: Option) -> Result {
-    debug!("integer_lit: {:?}, {:?}", symbol, suffix);
-    let symbol = strip_underscores(symbol);
-    let s = symbol.as_str();
-
-    let base = match s.as_bytes() {
-        [b'0', b'x', ..] => 16,
-        [b'0', b'o', ..] => 8,
-        [b'0', b'b', ..] => 2,
-        _ => 10,
-    };
-
-    let ty = match suffix {
-        Some(suf) => match suf {
-            sym::isize => ast::LitIntType::Signed(ast::IntTy::Isize),
-            sym::i8 => ast::LitIntType::Signed(ast::IntTy::I8),
-            sym::i16 => ast::LitIntType::Signed(ast::IntTy::I16),
-            sym::i32 => ast::LitIntType::Signed(ast::IntTy::I32),
-            sym::i64 => ast::LitIntType::Signed(ast::IntTy::I64),
-            sym::i128 => ast::LitIntType::Signed(ast::IntTy::I128),
-            sym::usize => ast::LitIntType::Unsigned(ast::UintTy::Usize),
-            sym::u8 => ast::LitIntType::Unsigned(ast::UintTy::U8),
-            sym::u16 => ast::LitIntType::Unsigned(ast::UintTy::U16),
-            sym::u32 => ast::LitIntType::Unsigned(ast::UintTy::U32),
-            sym::u64 => ast::LitIntType::Unsigned(ast::UintTy::U64),
-            sym::u128 => ast::LitIntType::Unsigned(ast::UintTy::U128),
-            // `1f64` and `2f32` etc. are valid float literals, and
-            // `fxxx` looks more like an invalid float literal than invalid integer literal.
-            _ if suf.as_str().starts_with('f') => return filtered_float_lit(symbol, suffix, base),
-            _ => return Err(LitError::InvalidIntSuffix),
-        },
-        _ => ast::LitIntType::Unsuffixed,
-    };
-
-    let s = &s[if base != 10 { 2 } else { 0 }..];
-    u128::from_str_radix(s, base).map(|i| LitKind::Int(i, ty)).map_err(|_| {
-        // Small bases are lexed as if they were base 10, e.g, the string
-        // might be `0b10201`. This will cause the conversion above to fail,
-        // but these kinds of errors are already reported by the lexer.
-        let from_lexer =
-            base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
-        if from_lexer { LitError::LexerError } else { LitError::IntTooLarge }
-    })
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/util/parser.rs b/vendor/rustc-ap-rustc_ast/src/util/parser.rs
deleted file mode 100644
index 078dd4bd6e..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/util/parser.rs
+++ /dev/null
@@ -1,404 +0,0 @@
-use crate::ast::{self, BinOpKind};
-use crate::token::{self, BinOpToken, Token};
-use rustc_span::symbol::kw;
-
-/// Associative operator with precedence.
-///
-/// This is the enum which specifies operator precedence and fixity to the parser.
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub enum AssocOp {
-    /// `+`
-    Add,
-    /// `-`
-    Subtract,
-    /// `*`
-    Multiply,
-    /// `/`
-    Divide,
-    /// `%`
-    Modulus,
-    /// `&&`
-    LAnd,
-    /// `||`
-    LOr,
-    /// `^`
-    BitXor,
-    /// `&`
-    BitAnd,
-    /// `|`
-    BitOr,
-    /// `<<`
-    ShiftLeft,
-    /// `>>`
-    ShiftRight,
-    /// `==`
-    Equal,
-    /// `<`
-    Less,
-    /// `<=`
-    LessEqual,
-    /// `!=`
-    NotEqual,
-    /// `>`
-    Greater,
-    /// `>=`
-    GreaterEqual,
-    /// `=`
-    Assign,
-    /// `?=` where ? is one of the BinOpToken
-    AssignOp(BinOpToken),
-    /// `as`
-    As,
-    /// `..` range
-    DotDot,
-    /// `..=` range
-    DotDotEq,
-    /// `:`
-    Colon,
-}
-
-#[derive(PartialEq, Debug)]
-pub enum Fixity {
-    /// The operator is left-associative
-    Left,
-    /// The operator is right-associative
-    Right,
-    /// The operator is not associative
-    None,
-}
-
-impl AssocOp {
-    /// Creates a new AssocOP from a token
-    pub fn from_token(t: &Token) -> Option {
-        use AssocOp::*;
-        match t.kind {
-            token::BinOpEq(k) => Some(AssignOp(k)),
-            token::Eq => Some(Assign),
-            token::BinOp(BinOpToken::Star) => Some(Multiply),
-            token::BinOp(BinOpToken::Slash) => Some(Divide),
-            token::BinOp(BinOpToken::Percent) => Some(Modulus),
-            token::BinOp(BinOpToken::Plus) => Some(Add),
-            token::BinOp(BinOpToken::Minus) => Some(Subtract),
-            token::BinOp(BinOpToken::Shl) => Some(ShiftLeft),
-            token::BinOp(BinOpToken::Shr) => Some(ShiftRight),
-            token::BinOp(BinOpToken::And) => Some(BitAnd),
-            token::BinOp(BinOpToken::Caret) => Some(BitXor),
-            token::BinOp(BinOpToken::Or) => Some(BitOr),
-            token::Lt => Some(Less),
-            token::Le => Some(LessEqual),
-            token::Ge => Some(GreaterEqual),
-            token::Gt => Some(Greater),
-            token::EqEq => Some(Equal),
-            token::Ne => Some(NotEqual),
-            token::AndAnd => Some(LAnd),
-            token::OrOr => Some(LOr),
-            token::DotDot => Some(DotDot),
-            token::DotDotEq => Some(DotDotEq),
-            // DotDotDot is no longer supported, but we need some way to display the error
-            token::DotDotDot => Some(DotDotEq),
-            token::Colon => Some(Colon),
-            // `<-` should probably be `< -`
-            token::LArrow => Some(Less),
-            _ if t.is_keyword(kw::As) => Some(As),
-            _ => None,
-        }
-    }
-
-    /// Creates a new AssocOp from ast::BinOpKind.
-    pub fn from_ast_binop(op: BinOpKind) -> Self {
-        use AssocOp::*;
-        match op {
-            BinOpKind::Lt => Less,
-            BinOpKind::Gt => Greater,
-            BinOpKind::Le => LessEqual,
-            BinOpKind::Ge => GreaterEqual,
-            BinOpKind::Eq => Equal,
-            BinOpKind::Ne => NotEqual,
-            BinOpKind::Mul => Multiply,
-            BinOpKind::Div => Divide,
-            BinOpKind::Rem => Modulus,
-            BinOpKind::Add => Add,
-            BinOpKind::Sub => Subtract,
-            BinOpKind::Shl => ShiftLeft,
-            BinOpKind::Shr => ShiftRight,
-            BinOpKind::BitAnd => BitAnd,
-            BinOpKind::BitXor => BitXor,
-            BinOpKind::BitOr => BitOr,
-            BinOpKind::And => LAnd,
-            BinOpKind::Or => LOr,
-        }
-    }
-
-    /// Gets the precedence of this operator
-    pub fn precedence(&self) -> usize {
-        use AssocOp::*;
-        match *self {
-            As | Colon => 14,
-            Multiply | Divide | Modulus => 13,
-            Add | Subtract => 12,
-            ShiftLeft | ShiftRight => 11,
-            BitAnd => 10,
-            BitXor => 9,
-            BitOr => 8,
-            Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
-            LAnd => 6,
-            LOr => 5,
-            DotDot | DotDotEq => 4,
-            Assign | AssignOp(_) => 2,
-        }
-    }
-
-    /// Gets the fixity of this operator
-    pub fn fixity(&self) -> Fixity {
-        use AssocOp::*;
-        // NOTE: it is a bug to have an operators that has same precedence but different fixities!
-        match *self {
-            Assign | AssignOp(_) => Fixity::Right,
-            As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd
-            | BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual
-            | LAnd | LOr | Colon => Fixity::Left,
-            DotDot | DotDotEq => Fixity::None,
-        }
-    }
-
-    pub fn is_comparison(&self) -> bool {
-        use AssocOp::*;
-        match *self {
-            Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
-            Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract
-            | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | DotDotEq
-            | Colon => false,
-        }
-    }
-
-    pub fn is_assign_like(&self) -> bool {
-        use AssocOp::*;
-        match *self {
-            Assign | AssignOp(_) => true,
-            Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply
-            | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor
-            | BitOr | LAnd | LOr | DotDot | DotDotEq | Colon => false,
-        }
-    }
-
-    pub fn to_ast_binop(&self) -> Option {
-        use AssocOp::*;
-        match *self {
-            Less => Some(BinOpKind::Lt),
-            Greater => Some(BinOpKind::Gt),
-            LessEqual => Some(BinOpKind::Le),
-            GreaterEqual => Some(BinOpKind::Ge),
-            Equal => Some(BinOpKind::Eq),
-            NotEqual => Some(BinOpKind::Ne),
-            Multiply => Some(BinOpKind::Mul),
-            Divide => Some(BinOpKind::Div),
-            Modulus => Some(BinOpKind::Rem),
-            Add => Some(BinOpKind::Add),
-            Subtract => Some(BinOpKind::Sub),
-            ShiftLeft => Some(BinOpKind::Shl),
-            ShiftRight => Some(BinOpKind::Shr),
-            BitAnd => Some(BinOpKind::BitAnd),
-            BitXor => Some(BinOpKind::BitXor),
-            BitOr => Some(BinOpKind::BitOr),
-            LAnd => Some(BinOpKind::And),
-            LOr => Some(BinOpKind::Or),
-            Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None,
-        }
-    }
-
-    /// This operator could be used to follow a block unambiguously.
-    ///
-    /// This is used for error recovery at the moment, providing a suggestion to wrap blocks with
-    /// parentheses while having a high degree of confidence on the correctness of the suggestion.
-    pub fn can_continue_expr_unambiguously(&self) -> bool {
-        use AssocOp::*;
-        match self {
-            BitXor | // `{ 42 } ^ 3`
-            Assign | // `{ 42 } = { 42 }`
-            Divide | // `{ 42 } / 42`
-            Modulus | // `{ 42 } % 2`
-            ShiftRight | // `{ 42 } >> 2`
-            LessEqual | // `{ 42 } <= 3`
-            Greater | // `{ 42 } > 3`
-            GreaterEqual | // `{ 42 } >= 3`
-            AssignOp(_) | // `{ 42 } +=`
-            As | // `{ 42 } as usize`
-            // Equal | // `{ 42 } == { 42 }`    Accepting these here would regress incorrect
-            // NotEqual | // `{ 42 } != { 42 }  struct literals parser recovery.
-            Colon => true, // `{ 42 }: usize`
-            _ => false,
-        }
-    }
-}
-
-pub const PREC_CLOSURE: i8 = -40;
-pub const PREC_JUMP: i8 = -30;
-pub const PREC_RANGE: i8 = -10;
-// The range 2..=14 is reserved for AssocOp binary operator precedences.
-pub const PREC_PREFIX: i8 = 50;
-pub const PREC_POSTFIX: i8 = 60;
-pub const PREC_PAREN: i8 = 99;
-pub const PREC_FORCE_PAREN: i8 = 100;
-
-#[derive(Debug, Clone, Copy)]
-pub enum ExprPrecedence {
-    Closure,
-    Break,
-    Continue,
-    Ret,
-    Yield,
-
-    Range,
-
-    Binary(BinOpKind),
-
-    Cast,
-    Type,
-
-    Assign,
-    AssignOp,
-
-    Box,
-    AddrOf,
-    Let,
-    Unary,
-
-    Call,
-    MethodCall,
-    Field,
-    Index,
-    Try,
-    InlineAsm,
-    Mac,
-
-    Array,
-    Repeat,
-    Tup,
-    Lit,
-    Path,
-    Paren,
-    If,
-    While,
-    ForLoop,
-    Loop,
-    Match,
-    ConstBlock,
-    Block,
-    TryBlock,
-    Struct,
-    Async,
-    Await,
-    Err,
-}
-
-impl ExprPrecedence {
-    pub fn order(self) -> i8 {
-        match self {
-            ExprPrecedence::Closure => PREC_CLOSURE,
-
-            ExprPrecedence::Break |
-            ExprPrecedence::Continue |
-            ExprPrecedence::Ret |
-            ExprPrecedence::Yield => PREC_JUMP,
-
-            // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
-            // parse, instead of parsing as `(x .. x) = x`.  Giving `Range` a lower precedence
-            // ensures that `pprust` will add parentheses in the right places to get the desired
-            // parse.
-            ExprPrecedence::Range => PREC_RANGE,
-
-            // Binop-like expr kinds, handled by `AssocOp`.
-            ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8,
-            ExprPrecedence::Cast => AssocOp::As.precedence() as i8,
-            ExprPrecedence::Type => AssocOp::Colon.precedence() as i8,
-
-            ExprPrecedence::Assign |
-            ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
-
-            // Unary, prefix
-            ExprPrecedence::Box |
-            ExprPrecedence::AddrOf |
-            // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.
-            // However, this is not exactly right. When `let _ = a` is the LHS of a binop we
-            // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
-            // but we need to print `(let _ = a) < b` as-is with parens.
-            ExprPrecedence::Let |
-            ExprPrecedence::Unary => PREC_PREFIX,
-
-            // Unary, postfix
-            ExprPrecedence::Await |
-            ExprPrecedence::Call |
-            ExprPrecedence::MethodCall |
-            ExprPrecedence::Field |
-            ExprPrecedence::Index |
-            ExprPrecedence::Try |
-            ExprPrecedence::InlineAsm |
-            ExprPrecedence::Mac => PREC_POSTFIX,
-
-            // Never need parens
-            ExprPrecedence::Array |
-            ExprPrecedence::Repeat |
-            ExprPrecedence::Tup |
-            ExprPrecedence::Lit |
-            ExprPrecedence::Path |
-            ExprPrecedence::Paren |
-            ExprPrecedence::If |
-            ExprPrecedence::While |
-            ExprPrecedence::ForLoop |
-            ExprPrecedence::Loop |
-            ExprPrecedence::Match |
-            ExprPrecedence::ConstBlock |
-            ExprPrecedence::Block |
-            ExprPrecedence::TryBlock |
-            ExprPrecedence::Async |
-            ExprPrecedence::Struct |
-            ExprPrecedence::Err => PREC_PAREN,
-        }
-    }
-}
-
-/// In `let p = e`, operators with precedence `<=` this one requires parenthesis in `e`.
-pub fn prec_let_scrutinee_needs_par() -> usize {
-    AssocOp::LAnd.precedence()
-}
-
-/// Suppose we have `let _ = e` and the `order` of `e`.
-/// Is the `order` such that `e` in `let _ = e` needs parenthesis when it is on the RHS?
-///
-/// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`.
-/// Can we print this as `let _ = a OP b`?
-pub fn needs_par_as_let_scrutinee(order: i8) -> bool {
-    order <= prec_let_scrutinee_needs_par() as i8
-}
-
-/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any
-/// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
-/// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
-pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
-    match value.kind {
-        ast::ExprKind::Struct(..) => true,
-
-        ast::ExprKind::Assign(ref lhs, ref rhs, _)
-        | ast::ExprKind::AssignOp(_, ref lhs, ref rhs)
-        | ast::ExprKind::Binary(_, ref lhs, ref rhs) => {
-            // X { y: 1 } + X { y: 2 }
-            contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs)
-        }
-        ast::ExprKind::Await(ref x)
-        | ast::ExprKind::Unary(_, ref x)
-        | ast::ExprKind::Cast(ref x, _)
-        | ast::ExprKind::Type(ref x, _)
-        | ast::ExprKind::Field(ref x, _)
-        | ast::ExprKind::Index(ref x, _) => {
-            // &X { y: 1 }, X { y: 1 }.y
-            contains_exterior_struct_lit(&x)
-        }
-
-        ast::ExprKind::MethodCall(.., ref exprs, _) => {
-            // X { y: 1 }.bar(...)
-            contains_exterior_struct_lit(&exprs[0])
-        }
-
-        _ => false,
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast/src/visit.rs b/vendor/rustc-ap-rustc_ast/src/visit.rs
deleted file mode 100644
index c37d4cd9f7..0000000000
--- a/vendor/rustc-ap-rustc_ast/src/visit.rs
+++ /dev/null
@@ -1,915 +0,0 @@
-//! AST walker. Each overridden visit method has full control over what
-//! happens with its node, it can do its own traversal of the node's children,
-//! call `visit::walk_*` to apply the default traversal algorithm, or prevent
-//! deeper traversal by doing nothing.
-//!
-//! Note: it is an important invariant that the default visitor walks the body
-//! of a function in "execution order" (more concretely, reverse post-order
-//! with respect to the CFG implied by the AST), meaning that if AST node A may
-//! execute before AST node B, then A is visited first. The borrow checker in
-//! particular relies on this property.
-//!
-//! Note: walking an AST before macro expansion is probably a bad idea. For
-//! instance, a walker looking for item names in a module will miss all of
-//! those that are created by the expansion of a macro.
-
-use crate::ast::*;
-use crate::token;
-
-use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::Span;
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum AssocCtxt {
-    Trait,
-    Impl,
-}
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum FnCtxt {
-    Free,
-    Foreign,
-    Assoc(AssocCtxt),
-}
-
-#[derive(Copy, Clone)]
-pub enum FnKind<'a> {
-    /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
-
-    /// E.g., `|x, y| body`.
-    Closure(&'a FnDecl, &'a Expr),
-}
-
-impl<'a> FnKind<'a> {
-    pub fn header(&self) -> Option<&'a FnHeader> {
-        match *self {
-            FnKind::Fn(_, _, sig, _, _) => Some(&sig.header),
-            FnKind::Closure(_, _) => None,
-        }
-    }
-
-    pub fn ident(&self) -> Option<&Ident> {
-        match self {
-            FnKind::Fn(_, ident, ..) => Some(ident),
-            _ => None,
-        }
-    }
-
-    pub fn decl(&self) -> &'a FnDecl {
-        match self {
-            FnKind::Fn(_, _, sig, _, _) => &sig.decl,
-            FnKind::Closure(decl, _) => decl,
-        }
-    }
-
-    pub fn ctxt(&self) -> Option {
-        match self {
-            FnKind::Fn(ctxt, ..) => Some(*ctxt),
-            FnKind::Closure(..) => None,
-        }
-    }
-}
-
-/// Each method of the `Visitor` trait is a hook to be potentially
-/// overridden. Each method's default implementation recursively visits
-/// the substructure of the input via the corresponding `walk` method;
-/// e.g., the `visit_mod` method by default calls `visit::walk_mod`.
-///
-/// If you want to ensure that your code handles every variant
-/// explicitly, you need to override each method. (And you also need
-/// to monitor future changes to `Visitor` in case a new method with a
-/// new default implementation gets introduced.)
-pub trait Visitor<'ast>: Sized {
-    fn visit_name(&mut self, _span: Span, _name: Symbol) {
-        // Nothing to do.
-    }
-    fn visit_ident(&mut self, ident: Ident) {
-        walk_ident(self, ident);
-    }
-    fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) {
-        walk_mod(self, m);
-    }
-    fn visit_foreign_item(&mut self, i: &'ast ForeignItem) {
-        walk_foreign_item(self, i)
-    }
-    fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) {
-        walk_global_asm(self, ga)
-    }
-    fn visit_item(&mut self, i: &'ast Item) {
-        walk_item(self, i)
-    }
-    fn visit_local(&mut self, l: &'ast Local) {
-        walk_local(self, l)
-    }
-    fn visit_block(&mut self, b: &'ast Block) {
-        walk_block(self, b)
-    }
-    fn visit_stmt(&mut self, s: &'ast Stmt) {
-        walk_stmt(self, s)
-    }
-    fn visit_param(&mut self, param: &'ast Param) {
-        walk_param(self, param)
-    }
-    fn visit_arm(&mut self, a: &'ast Arm) {
-        walk_arm(self, a)
-    }
-    fn visit_pat(&mut self, p: &'ast Pat) {
-        walk_pat(self, p)
-    }
-    fn visit_anon_const(&mut self, c: &'ast AnonConst) {
-        walk_anon_const(self, c)
-    }
-    fn visit_expr(&mut self, ex: &'ast Expr) {
-        walk_expr(self, ex)
-    }
-    fn visit_expr_post(&mut self, _ex: &'ast Expr) {}
-    fn visit_ty(&mut self, t: &'ast Ty) {
-        walk_ty(self, t)
-    }
-    fn visit_generic_param(&mut self, param: &'ast GenericParam) {
-        walk_generic_param(self, param)
-    }
-    fn visit_generics(&mut self, g: &'ast Generics) {
-        walk_generics(self, g)
-    }
-    fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
-        walk_where_predicate(self, p)
-    }
-    fn visit_fn(&mut self, fk: FnKind<'ast>, s: Span, _: NodeId) {
-        walk_fn(self, fk, s)
-    }
-    fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) {
-        walk_assoc_item(self, i, ctxt)
-    }
-    fn visit_trait_ref(&mut self, t: &'ast TraitRef) {
-        walk_trait_ref(self, t)
-    }
-    fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
-        walk_param_bound(self, bounds)
-    }
-    fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
-        walk_poly_trait_ref(self, t, m)
-    }
-    fn visit_variant_data(&mut self, s: &'ast VariantData) {
-        walk_struct_def(self, s)
-    }
-    fn visit_struct_field(&mut self, s: &'ast StructField) {
-        walk_struct_field(self, s)
-    }
-    fn visit_enum_def(
-        &mut self,
-        enum_definition: &'ast EnumDef,
-        generics: &'ast Generics,
-        item_id: NodeId,
-        _: Span,
-    ) {
-        walk_enum_def(self, enum_definition, generics, item_id)
-    }
-    fn visit_variant(&mut self, v: &'ast Variant) {
-        walk_variant(self, v)
-    }
-    fn visit_label(&mut self, label: &'ast Label) {
-        walk_label(self, label)
-    }
-    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
-        walk_lifetime(self, lifetime)
-    }
-    fn visit_mac_call(&mut self, mac: &'ast MacCall) {
-        walk_mac(self, mac)
-    }
-    fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) {
-        // Nothing to do
-    }
-    fn visit_path(&mut self, path: &'ast Path, _id: NodeId) {
-        walk_path(self, path)
-    }
-    fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) {
-        walk_use_tree(self, use_tree, id)
-    }
-    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
-        walk_path_segment(self, path_span, path_segment)
-    }
-    fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) {
-        walk_generic_args(self, path_span, generic_args)
-    }
-    fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
-        walk_generic_arg(self, generic_arg)
-    }
-    fn visit_assoc_ty_constraint(&mut self, constraint: &'ast AssocTyConstraint) {
-        walk_assoc_ty_constraint(self, constraint)
-    }
-    fn visit_attribute(&mut self, attr: &'ast Attribute) {
-        walk_attribute(self, attr)
-    }
-    fn visit_vis(&mut self, vis: &'ast Visibility) {
-        walk_vis(self, vis)
-    }
-    fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) {
-        walk_fn_ret_ty(self, ret_ty)
-    }
-    fn visit_fn_header(&mut self, _header: &'ast FnHeader) {
-        // Nothing to do
-    }
-    fn visit_field(&mut self, f: &'ast Field) {
-        walk_field(self, f)
-    }
-    fn visit_field_pattern(&mut self, fp: &'ast FieldPat) {
-        walk_field_pattern(self, fp)
-    }
-}
-
-#[macro_export]
-macro_rules! walk_list {
-    ($visitor: expr, $method: ident, $list: expr) => {
-        for elem in $list {
-            $visitor.$method(elem)
-        }
-    };
-    ($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => {
-        for elem in $list {
-            $visitor.$method(elem, $($extra_args,)*)
-        }
-    }
-}
-
-pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, ident: Ident) {
-    visitor.visit_name(ident.span, ident.name);
-}
-
-pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
-    visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID);
-    walk_list!(visitor, visit_attribute, &krate.attrs);
-}
-
-pub fn walk_mod<'a, V: Visitor<'a>>(visitor: &mut V, module: &'a Mod) {
-    walk_list!(visitor, visit_item, &module.items);
-}
-
-pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
-    for attr in local.attrs.iter() {
-        visitor.visit_attribute(attr);
-    }
-    visitor.visit_pat(&local.pat);
-    walk_list!(visitor, visit_ty, &local.ty);
-    walk_list!(visitor, visit_expr, &local.init);
-}
-
-pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) {
-    visitor.visit_ident(label.ident);
-}
-
-pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) {
-    visitor.visit_ident(lifetime.ident);
-}
-
-pub fn walk_poly_trait_ref<'a, V>(
-    visitor: &mut V,
-    trait_ref: &'a PolyTraitRef,
-    _: &TraitBoundModifier,
-) where
-    V: Visitor<'a>,
-{
-    walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params);
-    visitor.visit_trait_ref(&trait_ref.trait_ref);
-}
-
-pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) {
-    visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
-}
-
-pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
-    visitor.visit_vis(&item.vis);
-    visitor.visit_ident(item.ident);
-    match item.kind {
-        ItemKind::ExternCrate(orig_name) => {
-            if let Some(orig_name) = orig_name {
-                visitor.visit_name(item.span, orig_name);
-            }
-        }
-        ItemKind::Use(ref use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
-        ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(_, ref typ, ref expr) => {
-            visitor.visit_ty(typ);
-            walk_list!(visitor, visit_expr, expr);
-        }
-        ItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) => {
-            visitor.visit_generics(generics);
-            let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
-            visitor.visit_fn(kind, item.span, item.id)
-        }
-        ItemKind::Mod(ref module) => visitor.visit_mod(module, item.span, &item.attrs, item.id),
-        ItemKind::ForeignMod(ref foreign_module) => {
-            walk_list!(visitor, visit_foreign_item, &foreign_module.items);
-        }
-        ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
-        ItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty)) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_ty, ty);
-        }
-        ItemKind::Enum(ref enum_definition, ref generics) => {
-            visitor.visit_generics(generics);
-            visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
-        }
-        ItemKind::Impl(box ImplKind {
-            unsafety: _,
-            polarity: _,
-            defaultness: _,
-            constness: _,
-            ref generics,
-            ref of_trait,
-            ref self_ty,
-            ref items,
-        }) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_trait_ref, of_trait);
-            visitor.visit_ty(self_ty);
-            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
-        }
-        ItemKind::Struct(ref struct_definition, ref generics)
-        | ItemKind::Union(ref struct_definition, ref generics) => {
-            visitor.visit_generics(generics);
-            visitor.visit_variant_data(struct_definition);
-        }
-        ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref items)) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
-        }
-        ItemKind::TraitAlias(ref generics, ref bounds) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
-        }
-        ItemKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
-        ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
-    }
-    walk_list!(visitor, visit_attribute, &item.attrs);
-}
-
-pub fn walk_enum_def<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    enum_definition: &'a EnumDef,
-    _: &'a Generics,
-    _: NodeId,
-) {
-    walk_list!(visitor, visit_variant, &enum_definition.variants);
-}
-
-pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant)
-where
-    V: Visitor<'a>,
-{
-    visitor.visit_ident(variant.ident);
-    visitor.visit_vis(&variant.vis);
-    visitor.visit_variant_data(&variant.data);
-    walk_list!(visitor, visit_anon_const, &variant.disr_expr);
-    walk_list!(visitor, visit_attribute, &variant.attrs);
-}
-
-pub fn walk_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a Field) {
-    visitor.visit_expr(&f.expr);
-    visitor.visit_ident(f.ident);
-    walk_list!(visitor, visit_attribute, f.attrs.iter());
-}
-
-pub fn walk_field_pattern<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a FieldPat) {
-    visitor.visit_ident(fp.ident);
-    visitor.visit_pat(&fp.pat);
-    walk_list!(visitor, visit_attribute, fp.attrs.iter());
-}
-
-pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
-    match typ.kind {
-        TyKind::Slice(ref ty) | TyKind::Paren(ref ty) => visitor.visit_ty(ty),
-        TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty),
-        TyKind::Rptr(ref opt_lifetime, ref mutable_type) => {
-            walk_list!(visitor, visit_lifetime, opt_lifetime);
-            visitor.visit_ty(&mutable_type.ty)
-        }
-        TyKind::Tup(ref tuple_element_types) => {
-            walk_list!(visitor, visit_ty, tuple_element_types);
-        }
-        TyKind::BareFn(ref function_declaration) => {
-            walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
-            walk_fn_decl(visitor, &function_declaration.decl);
-        }
-        TyKind::Path(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, typ.id);
-        }
-        TyKind::Array(ref ty, ref length) => {
-            visitor.visit_ty(ty);
-            visitor.visit_anon_const(length)
-        }
-        TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(_, ref bounds) => {
-            walk_list!(visitor, visit_param_bound, bounds);
-        }
-        TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
-        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
-        TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
-        TyKind::Never | TyKind::CVarArgs => {}
-    }
-}
-
-pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) {
-    for segment in &path.segments {
-        visitor.visit_path_segment(path.span, segment);
-    }
-}
-
-pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree, id: NodeId) {
-    visitor.visit_path(&use_tree.prefix, id);
-    match use_tree.kind {
-        UseTreeKind::Simple(rename, ..) => {
-            // The extra IDs are handled during HIR lowering.
-            if let Some(rename) = rename {
-                visitor.visit_ident(rename);
-            }
-        }
-        UseTreeKind::Glob => {}
-        UseTreeKind::Nested(ref use_trees) => {
-            for &(ref nested_tree, nested_id) in use_trees {
-                visitor.visit_use_tree(nested_tree, nested_id, true);
-            }
-        }
-    }
-}
-
-pub fn walk_path_segment<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    path_span: Span,
-    segment: &'a PathSegment,
-) {
-    visitor.visit_ident(segment.ident);
-    if let Some(ref args) = segment.args {
-        visitor.visit_generic_args(path_span, args);
-    }
-}
-
-pub fn walk_generic_args<'a, V>(visitor: &mut V, _path_span: Span, generic_args: &'a GenericArgs)
-where
-    V: Visitor<'a>,
-{
-    match *generic_args {
-        GenericArgs::AngleBracketed(ref data) => {
-            for arg in &data.args {
-                match arg {
-                    AngleBracketedArg::Arg(a) => visitor.visit_generic_arg(a),
-                    AngleBracketedArg::Constraint(c) => visitor.visit_assoc_ty_constraint(c),
-                }
-            }
-        }
-        GenericArgs::Parenthesized(ref data) => {
-            walk_list!(visitor, visit_ty, &data.inputs);
-            walk_fn_ret_ty(visitor, &data.output);
-        }
-    }
-}
-
-pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg)
-where
-    V: Visitor<'a>,
-{
-    match generic_arg {
-        GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
-        GenericArg::Type(ty) => visitor.visit_ty(ty),
-        GenericArg::Const(ct) => visitor.visit_anon_const(ct),
-    }
-}
-
-pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    constraint: &'a AssocTyConstraint,
-) {
-    visitor.visit_ident(constraint.ident);
-    if let Some(ref gen_args) = constraint.gen_args {
-        visitor.visit_generic_args(gen_args.span(), gen_args);
-    }
-    match constraint.kind {
-        AssocTyConstraintKind::Equality { ref ty } => {
-            visitor.visit_ty(ty);
-        }
-        AssocTyConstraintKind::Bound { ref bounds } => {
-            walk_list!(visitor, visit_param_bound, bounds);
-        }
-    }
-}
-
-pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
-    match pattern.kind {
-        PatKind::TupleStruct(ref path, ref elems) => {
-            visitor.visit_path(path, pattern.id);
-            walk_list!(visitor, visit_pat, elems);
-        }
-        PatKind::Path(ref opt_qself, ref path) => {
-            if let Some(ref qself) = *opt_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, pattern.id)
-        }
-        PatKind::Struct(ref path, ref fields, _) => {
-            visitor.visit_path(path, pattern.id);
-            walk_list!(visitor, visit_field_pattern, fields);
-        }
-        PatKind::Box(ref subpattern)
-        | PatKind::Ref(ref subpattern, _)
-        | PatKind::Paren(ref subpattern) => visitor.visit_pat(subpattern),
-        PatKind::Ident(_, ident, ref optional_subpattern) => {
-            visitor.visit_ident(ident);
-            walk_list!(visitor, visit_pat, optional_subpattern);
-        }
-        PatKind::Lit(ref expression) => visitor.visit_expr(expression),
-        PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            walk_list!(visitor, visit_expr, lower_bound);
-            walk_list!(visitor, visit_expr, upper_bound);
-        }
-        PatKind::Wild | PatKind::Rest => {}
-        PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => {
-            walk_list!(visitor, visit_pat, elems);
-        }
-        PatKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
-    }
-}
-
-pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
-    let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item;
-    visitor.visit_vis(vis);
-    visitor.visit_ident(ident);
-    walk_list!(visitor, visit_attribute, attrs);
-    match kind {
-        ForeignItemKind::Static(ty, _, expr) => {
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, expr);
-        }
-        ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
-            visitor.visit_generics(generics);
-            let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
-            visitor.visit_fn(kind, span, id);
-        }
-        ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_ty, ty);
-        }
-        ForeignItemKind::MacCall(mac) => {
-            visitor.visit_mac_call(mac);
-        }
-    }
-}
-
-pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
-    // Empty!
-}
-
-pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) {
-    match *bound {
-        GenericBound::Trait(ref typ, ref modifier) => visitor.visit_poly_trait_ref(typ, modifier),
-        GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
-    }
-}
-
-pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
-    visitor.visit_ident(param.ident);
-    walk_list!(visitor, visit_attribute, param.attrs.iter());
-    walk_list!(visitor, visit_param_bound, ¶m.bounds);
-    match param.kind {
-        GenericParamKind::Lifetime => (),
-        GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
-        GenericParamKind::Const { ref ty, ref default, .. } => {
-            visitor.visit_ty(ty);
-            if let Some(default) = default {
-                visitor.visit_anon_const(default);
-            }
-        }
-    }
-}
-
-pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) {
-    walk_list!(visitor, visit_generic_param, &generics.params);
-    walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
-}
-
-pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
-    match *predicate {
-        WherePredicate::BoundPredicate(WhereBoundPredicate {
-            ref bounded_ty,
-            ref bounds,
-            ref bound_generic_params,
-            ..
-        }) => {
-            visitor.visit_ty(bounded_ty);
-            walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_generic_param, bound_generic_params);
-        }
-        WherePredicate::RegionPredicate(WhereRegionPredicate {
-            ref lifetime, ref bounds, ..
-        }) => {
-            visitor.visit_lifetime(lifetime);
-            walk_list!(visitor, visit_param_bound, bounds);
-        }
-        WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
-            visitor.visit_ty(lhs_ty);
-            visitor.visit_ty(rhs_ty);
-        }
-    }
-}
-
-pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) {
-    if let FnRetTy::Ty(ref output_ty) = *ret_ty {
-        visitor.visit_ty(output_ty)
-    }
-}
-
-pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
-    for param in &function_declaration.inputs {
-        visitor.visit_param(param);
-    }
-    visitor.visit_fn_ret_ty(&function_declaration.output);
-}
-
-pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
-    match kind {
-        FnKind::Fn(_, _, sig, _, body) => {
-            visitor.visit_fn_header(&sig.header);
-            walk_fn_decl(visitor, &sig.decl);
-            walk_list!(visitor, visit_block, body);
-        }
-        FnKind::Closure(decl, body) => {
-            walk_fn_decl(visitor, decl);
-            visitor.visit_expr(body);
-        }
-    }
-}
-
-pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) {
-    let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item;
-    visitor.visit_vis(vis);
-    visitor.visit_ident(ident);
-    walk_list!(visitor, visit_attribute, attrs);
-    match kind {
-        AssocItemKind::Const(_, ty, expr) => {
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, expr);
-        }
-        AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
-            visitor.visit_generics(generics);
-            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
-            visitor.visit_fn(kind, span, id);
-        }
-        AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_ty, ty);
-        }
-        AssocItemKind::MacCall(mac) => {
-            visitor.visit_mac_call(mac);
-        }
-    }
-}
-
-pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &'a VariantData) {
-    walk_list!(visitor, visit_struct_field, struct_definition.fields());
-}
-
-pub fn walk_struct_field<'a, V: Visitor<'a>>(visitor: &mut V, struct_field: &'a StructField) {
-    visitor.visit_vis(&struct_field.vis);
-    if let Some(ident) = struct_field.ident {
-        visitor.visit_ident(ident);
-    }
-    visitor.visit_ty(&struct_field.ty);
-    walk_list!(visitor, visit_attribute, &struct_field.attrs);
-}
-
-pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) {
-    walk_list!(visitor, visit_stmt, &block.stmts);
-}
-
-pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
-    match statement.kind {
-        StmtKind::Local(ref local) => visitor.visit_local(local),
-        StmtKind::Item(ref item) => visitor.visit_item(item),
-        StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr),
-        StmtKind::Empty => {}
-        StmtKind::MacCall(ref mac) => {
-            let MacCallStmt { ref mac, style: _, ref attrs, tokens: _ } = **mac;
-            visitor.visit_mac_call(mac);
-            for attr in attrs.iter() {
-                visitor.visit_attribute(attr);
-            }
-        }
-    }
-}
-
-pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) {
-    visitor.visit_path(&mac.path, DUMMY_NODE_ID);
-}
-
-pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) {
-    visitor.visit_expr(&constant.value);
-}
-
-pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
-    walk_list!(visitor, visit_attribute, expression.attrs.iter());
-
-    match expression.kind {
-        ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression),
-        ExprKind::Array(ref subexpressions) => {
-            walk_list!(visitor, visit_expr, subexpressions);
-        }
-        ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
-        ExprKind::Repeat(ref element, ref count) => {
-            visitor.visit_expr(element);
-            visitor.visit_anon_const(count)
-        }
-        ExprKind::Struct(ref path, ref fields, ref optional_base) => {
-            visitor.visit_path(path, expression.id);
-            walk_list!(visitor, visit_field, fields);
-            match optional_base {
-                StructRest::Base(expr) => visitor.visit_expr(expr),
-                StructRest::Rest(_span) => {}
-                StructRest::None => {}
-            }
-        }
-        ExprKind::Tup(ref subexpressions) => {
-            walk_list!(visitor, visit_expr, subexpressions);
-        }
-        ExprKind::Call(ref callee_expression, ref arguments) => {
-            visitor.visit_expr(callee_expression);
-            walk_list!(visitor, visit_expr, arguments);
-        }
-        ExprKind::MethodCall(ref segment, ref arguments, _span) => {
-            visitor.visit_path_segment(expression.span, segment);
-            walk_list!(visitor, visit_expr, arguments);
-        }
-        ExprKind::Binary(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(left_expression);
-            visitor.visit_expr(right_expression)
-        }
-        ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
-            visitor.visit_expr(subexpression)
-        }
-        ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_ty(typ)
-        }
-        ExprKind::Let(ref pat, ref scrutinee) => {
-            visitor.visit_pat(pat);
-            visitor.visit_expr(scrutinee);
-        }
-        ExprKind::If(ref head_expression, ref if_block, ref optional_else) => {
-            visitor.visit_expr(head_expression);
-            visitor.visit_block(if_block);
-            walk_list!(visitor, visit_expr, optional_else);
-        }
-        ExprKind::While(ref subexpression, ref block, ref opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_expr(subexpression);
-            visitor.visit_block(block);
-        }
-        ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_pat(pattern);
-            visitor.visit_expr(subexpression);
-            visitor.visit_block(block);
-        }
-        ExprKind::Loop(ref block, ref opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_block(block);
-        }
-        ExprKind::Match(ref subexpression, ref arms) => {
-            visitor.visit_expr(subexpression);
-            walk_list!(visitor, visit_arm, arms);
-        }
-        ExprKind::Closure(_, _, _, ref decl, ref body, _decl_span) => {
-            visitor.visit_fn(FnKind::Closure(decl, body), expression.span, expression.id)
-        }
-        ExprKind::Block(ref block, ref opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_block(block);
-        }
-        ExprKind::Async(_, _, ref body) => {
-            visitor.visit_block(body);
-        }
-        ExprKind::Await(ref expr) => visitor.visit_expr(expr),
-        ExprKind::Assign(ref lhs, ref rhs, _) => {
-            visitor.visit_expr(lhs);
-            visitor.visit_expr(rhs);
-        }
-        ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(left_expression);
-            visitor.visit_expr(right_expression);
-        }
-        ExprKind::Field(ref subexpression, ident) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_ident(ident);
-        }
-        ExprKind::Index(ref main_expression, ref index_expression) => {
-            visitor.visit_expr(main_expression);
-            visitor.visit_expr(index_expression)
-        }
-        ExprKind::Range(ref start, ref end, _) => {
-            walk_list!(visitor, visit_expr, start);
-            walk_list!(visitor, visit_expr, end);
-        }
-        ExprKind::Underscore => {}
-        ExprKind::Path(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, expression.id)
-        }
-        ExprKind::Break(ref opt_label, ref opt_expr) => {
-            walk_list!(visitor, visit_label, opt_label);
-            walk_list!(visitor, visit_expr, opt_expr);
-        }
-        ExprKind::Continue(ref opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-        }
-        ExprKind::Ret(ref optional_expression) => {
-            walk_list!(visitor, visit_expr, optional_expression);
-        }
-        ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
-        ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
-        ExprKind::InlineAsm(ref ia) => {
-            for (op, _) in &ia.operands {
-                match op {
-                    InlineAsmOperand::In { expr, .. }
-                    | InlineAsmOperand::InOut { expr, .. }
-                    | InlineAsmOperand::Const { expr, .. }
-                    | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
-                    InlineAsmOperand::Out { expr, .. } => {
-                        if let Some(expr) = expr {
-                            visitor.visit_expr(expr);
-                        }
-                    }
-                    InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                        visitor.visit_expr(in_expr);
-                        if let Some(out_expr) = out_expr {
-                            visitor.visit_expr(out_expr);
-                        }
-                    }
-                }
-            }
-        }
-        ExprKind::LlvmInlineAsm(ref ia) => {
-            for &(_, ref input) in &ia.inputs {
-                visitor.visit_expr(input)
-            }
-            for output in &ia.outputs {
-                visitor.visit_expr(&output.expr)
-            }
-        }
-        ExprKind::Yield(ref optional_expression) => {
-            walk_list!(visitor, visit_expr, optional_expression);
-        }
-        ExprKind::Try(ref subexpression) => visitor.visit_expr(subexpression),
-        ExprKind::TryBlock(ref body) => visitor.visit_block(body),
-        ExprKind::Lit(_) | ExprKind::Err => {}
-    }
-
-    visitor.visit_expr_post(expression)
-}
-
-pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) {
-    walk_list!(visitor, visit_attribute, param.attrs.iter());
-    visitor.visit_pat(¶m.pat);
-    visitor.visit_ty(¶m.ty);
-}
-
-pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
-    visitor.visit_pat(&arm.pat);
-    walk_list!(visitor, visit_expr, &arm.guard);
-    visitor.visit_expr(&arm.body);
-    walk_list!(visitor, visit_attribute, &arm.attrs);
-}
-
-pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) {
-    if let VisibilityKind::Restricted { ref path, id } = vis.kind {
-        visitor.visit_path(path, id);
-    }
-}
-
-pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) {
-    match attr.kind {
-        AttrKind::Normal(ref item, ref _tokens) => walk_mac_args(visitor, &item.args),
-        AttrKind::DocComment(..) => {}
-    }
-}
-
-pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
-    match args {
-        MacArgs::Empty => {}
-        MacArgs::Delimited(_dspan, _delim, _tokens) => {}
-        // The value in `#[key = VALUE]` must be visited as an expression for backward
-        // compatibility, so that macros can be expanded in that position.
-        MacArgs::Eq(_eq_span, token) => match &token.kind {
-            token::Interpolated(nt) => match &**nt {
-                token::NtExpr(expr) => visitor.visit_expr(expr),
-                t => panic!("unexpected token in key-value attribute: {:?}", t),
-            },
-            t => panic!("unexpected token in key-value attribute: {:?}", t),
-        },
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast_passes/.cargo-checksum.json b/vendor/rustc-ap-rustc_ast_passes/.cargo-checksum.json
deleted file mode 100644
index 29e44c5b29..0000000000
--- a/vendor/rustc-ap-rustc_ast_passes/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"9a785c18e1847d1c797308072d219be2935adc182aef3d1f576562206ddc9a73","src/ast_validation.rs":"6f557cced108f9aa63e0924a06546ba5bb2487194e5f6c0172ee69b20a12970e","src/feature_gate.rs":"3679b43991b6ca7f1450d5246ebae1b419225e599c5b243082a4eda4eaf27425","src/lib.rs":"5339c88ee93575451cc1e1a20edd68039316a3fd2002cc3a45a948f08af7cfd0","src/node_count.rs":"e298c439b51b296394f52a911c8e3d2c7056d4f78a4a094728ee22d1598f5bab","src/show_span.rs":"db0cf01e76213c0c35714344b2287aeff635792c30d36ded4f325c2519a4aabb"},"package":"8e01f63e5259ee397bbe2e395d34a2e6b6b24f10c184d30fbbee1dcd7117f4f3"}
\ No newline at end of file
diff --git a/vendor/rustc-ap-rustc_ast_passes/Cargo.toml b/vendor/rustc-ap-rustc_ast_passes/Cargo.toml
deleted file mode 100644
index 95e8c56887..0000000000
--- a/vendor/rustc-ap-rustc_ast_passes/Cargo.toml
+++ /dev/null
@@ -1,61 +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 = "rustc-ap-rustc_ast_passes"
-version = "705.0.0"
-authors = ["The Rust Project Developers"]
-description = "Automatically published version of the package `rustc_ast_passes` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n            "
-license = "MIT / Apache-2.0"
-repository = "https://github.com/rust-lang/rust"
-[dependencies.itertools]
-version = "0.9"
-
-[dependencies.rustc_ast]
-version = "705.0.0"
-package = "rustc-ap-rustc_ast"
-
-[dependencies.rustc_ast_pretty]
-version = "705.0.0"
-package = "rustc-ap-rustc_ast_pretty"
-
-[dependencies.rustc_attr]
-version = "705.0.0"
-package = "rustc-ap-rustc_attr"
-
-[dependencies.rustc_data_structures]
-version = "705.0.0"
-package = "rustc-ap-rustc_data_structures"
-
-[dependencies.rustc_errors]
-version = "705.0.0"
-package = "rustc-ap-rustc_errors"
-
-[dependencies.rustc_feature]
-version = "705.0.0"
-package = "rustc-ap-rustc_feature"
-
-[dependencies.rustc_parse]
-version = "705.0.0"
-package = "rustc-ap-rustc_parse"
-
-[dependencies.rustc_session]
-version = "705.0.0"
-package = "rustc-ap-rustc_session"
-
-[dependencies.rustc_span]
-version = "705.0.0"
-package = "rustc-ap-rustc_span"
-
-[dependencies.tracing]
-version = "0.1"
diff --git a/vendor/rustc-ap-rustc_ast_passes/src/ast_validation.rs b/vendor/rustc-ap-rustc_ast_passes/src/ast_validation.rs
deleted file mode 100644
index 8defd91c68..0000000000
--- a/vendor/rustc-ap-rustc_ast_passes/src/ast_validation.rs
+++ /dev/null
@@ -1,1472 +0,0 @@
-// Validate AST before lowering it to HIR.
-//
-// This pass is supposed to catch things that fit into AST data structures,
-// but not permitted by the language. It runs after expansion when AST is frozen,
-// so it can check for erroneous constructions produced by syntax extensions.
-// This pass is supposed to perform only simple checks not requiring name resolution
-// or type checking or some other kind of complex analysis.
-
-use itertools::{Either, Itertools};
-use rustc_ast::ptr::P;
-use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
-use rustc_ast::walk_list;
-use rustc_ast::*;
-use rustc_ast_pretty::pprust;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
-use rustc_parse::validate_attr;
-use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
-use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
-use rustc_session::Session;
-use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::Span;
-use std::mem;
-use std::ops::DerefMut;
-
-const MORE_EXTERN: &str =
-    "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
-
-/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
-enum SelfSemantic {
-    Yes,
-    No,
-}
-
-/// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
-#[derive(Clone, Copy)]
-enum BoundContext {
-    ImplTrait,
-    TraitBounds,
-    TraitObject,
-}
-
-impl BoundContext {
-    fn description(&self) -> &'static str {
-        match self {
-            Self::ImplTrait => "`impl Trait`",
-            Self::TraitBounds => "supertraits",
-            Self::TraitObject => "trait objects",
-        }
-    }
-}
-
-struct AstValidator<'a> {
-    session: &'a Session,
-
-    /// The span of the `extern` in an `extern { ... }` block, if any.
-    extern_mod: Option<&'a Item>,
-
-    /// Are we inside a trait impl?
-    in_trait_impl: bool,
-
-    has_proc_macro_decls: bool,
-
-    /// Used to ban nested `impl Trait`, e.g., `impl Into`.
-    /// Nested `impl Trait` _is_ allowed in associated type position,
-    /// e.g., `impl Iterator`.
-    outer_impl_trait: Option,
-
-    /// Keeps track of the `BoundContext` as we recurse.
-    ///
-    /// This is used to forbid `?const Trait` bounds in, e.g.,
-    /// `impl Iterator`.
-    bound_context: Option,
-
-    /// Used to ban `impl Trait` in path projections like `::Item`
-    /// or `Foo::Bar`
-    is_impl_trait_banned: bool,
-
-    /// Used to ban associated type bounds (i.e., `Type`) in
-    /// certain positions.
-    is_assoc_ty_bound_banned: bool,
-
-    lint_buffer: &'a mut LintBuffer,
-}
-
-impl<'a> AstValidator<'a> {
-    fn with_in_trait_impl(&mut self, is_in: bool, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.in_trait_impl, is_in);
-        f(self);
-        self.in_trait_impl = old;
-    }
-
-    fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.is_impl_trait_banned, true);
-        f(self);
-        self.is_impl_trait_banned = old;
-    }
-
-    fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
-        f(self);
-        self.is_assoc_ty_bound_banned = old;
-    }
-
-    fn with_impl_trait(&mut self, outer: Option, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.outer_impl_trait, outer);
-        if outer.is_some() {
-            self.with_bound_context(BoundContext::ImplTrait, |this| f(this));
-        } else {
-            f(self)
-        }
-        self.outer_impl_trait = old;
-    }
-
-    fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) {
-        let old = self.bound_context.replace(ctx);
-        f(self);
-        self.bound_context = old;
-    }
-
-    fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
-        match constraint.kind {
-            AssocTyConstraintKind::Equality { .. } => {}
-            AssocTyConstraintKind::Bound { .. } => {
-                if self.is_assoc_ty_bound_banned {
-                    self.err_handler().span_err(
-                        constraint.span,
-                        "associated type bounds are not allowed within structs, enums, or unions",
-                    );
-                }
-            }
-        }
-        self.visit_assoc_ty_constraint(constraint);
-    }
-
-    // Mirrors `visit::walk_ty`, but tracks relevant state.
-    fn walk_ty(&mut self, t: &'a Ty) {
-        match t.kind {
-            TyKind::ImplTrait(..) => {
-                self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
-            }
-            TyKind::TraitObject(..) => {
-                self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t));
-            }
-            TyKind::Path(ref qself, ref path) => {
-                // We allow these:
-                //  - `Option`
-                //  - `option::Option`
-                //  - `option::Option::Foo
-                //
-                // But not these:
-                //  - `::Foo`
-                //  - `option::Option::Foo`.
-                //
-                // To implement this, we disallow `impl Trait` from `qself`
-                // (for cases like `::Foo>`)
-                // but we allow `impl Trait` in `GenericArgs`
-                // iff there are no more PathSegments.
-                if let Some(ref qself) = *qself {
-                    // `impl Trait` in `qself` is always illegal
-                    self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
-                }
-
-                // Note that there should be a call to visit_path here,
-                // so if any logic is added to process `Path`s a call to it should be
-                // added both in visit_path and here. This code mirrors visit::walk_path.
-                for (i, segment) in path.segments.iter().enumerate() {
-                    // Allow `impl Trait` iff we're on the final path segment
-                    if i == path.segments.len() - 1 {
-                        self.visit_path_segment(path.span, segment);
-                    } else {
-                        self.with_banned_impl_trait(|this| {
-                            this.visit_path_segment(path.span, segment)
-                        });
-                    }
-                }
-            }
-            _ => visit::walk_ty(self, t),
-        }
-    }
-
-    fn err_handler(&self) -> &rustc_errors::Handler {
-        &self.session.diagnostic()
-    }
-
-    fn check_lifetime(&self, ident: Ident) {
-        let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
-        if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
-            self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
-        }
-    }
-
-    fn check_label(&self, ident: Ident) {
-        if ident.without_first_quote().is_reserved() {
-            self.err_handler()
-                .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
-        }
-    }
-
-    fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
-        if let VisibilityKind::Inherited = vis.kind {
-            return;
-        }
-
-        let mut err =
-            struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
-        if vis.kind.is_pub() {
-            err.span_label(vis.span, "`pub` not permitted here because it's implied");
-        }
-        if let Some(note) = note {
-            err.note(note);
-        }
-        err.emit();
-    }
-
-    fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) {
-        for Param { pat, .. } in &decl.inputs {
-            match pat.kind {
-                PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
-                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => {
-                    report_err(pat.span, Some(ident), true)
-                }
-                _ => report_err(pat.span, None, false),
-            }
-        }
-    }
-
-    fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
-        if let Async::Yes { span, .. } = asyncness {
-            struct_span_err!(
-                self.session,
-                fn_span,
-                E0706,
-                "functions in traits cannot be declared `async`"
-            )
-            .span_label(span, "`async` because of this")
-            .note("`async` trait functions are not currently supported")
-            .note("consider using the `async-trait` crate: https://crates.io/crates/async-trait")
-            .emit();
-        }
-    }
-
-    fn check_trait_fn_not_const(&self, constness: Const) {
-        if let Const::Yes(span) = constness {
-            struct_span_err!(
-                self.session,
-                span,
-                E0379,
-                "functions in traits cannot be declared const"
-            )
-            .span_label(span, "functions in traits cannot be const")
-            .emit();
-        }
-    }
-
-    // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
-    fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
-        for bound in bounds {
-            if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
-                let mut err = self.err_handler().struct_span_err(
-                    poly.span,
-                    &format!("`?Trait` is not permitted in {}", where_),
-                );
-                if is_trait {
-                    let path_str = pprust::path_to_string(&poly.trait_ref.path);
-                    err.note(&format!("traits are `?{}` by default", path_str));
-                }
-                err.emit();
-            }
-        }
-    }
-
-    /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`,
-    /// or paths for ranges.
-    //
-    // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions?
-    // That means making this work:
-    //
-    // ```rust,ignore (FIXME)
-    // struct S;
-    // macro_rules! m {
-    //     ($a:expr) => {
-    //         let $a = S;
-    //     }
-    // }
-    // m!(S);
-    // ```
-    fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
-        match expr.kind {
-            ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {}
-            ExprKind::Path(..) if allow_paths => {}
-            ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
-            _ => self.err_handler().span_err(
-                expr.span,
-                "arbitrary expressions aren't allowed \
-                                                         in patterns",
-            ),
-        }
-    }
-
-    fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
-        // Check only lifetime parameters are present and that the lifetime
-        // parameters that are present have no bounds.
-        let non_lt_param_spans: Vec<_> = params
-            .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => {
-                    if !param.bounds.is_empty() {
-                        let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
-                        self.err_handler()
-                            .span_err(spans, "lifetime bounds cannot be used in this context");
-                    }
-                    None
-                }
-                _ => Some(param.ident.span),
-            })
-            .collect();
-        if !non_lt_param_spans.is_empty() {
-            self.err_handler().span_err(
-                non_lt_param_spans,
-                "only lifetime parameters can be used in this context",
-            );
-        }
-    }
-
-    fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
-        self.check_decl_cvaradic_pos(fn_decl);
-        self.check_decl_attrs(fn_decl);
-        self.check_decl_self_param(fn_decl, self_semantic);
-    }
-
-    fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
-        match &*fn_decl.inputs {
-            [Param { ty, span, .. }] => {
-                if let TyKind::CVarArgs = ty.kind {
-                    self.err_handler().span_err(
-                        *span,
-                        "C-variadic function must be declared with at least one named argument",
-                    );
-                }
-            }
-            [ps @ .., _] => {
-                for Param { ty, span, .. } in ps {
-                    if let TyKind::CVarArgs = ty.kind {
-                        self.err_handler().span_err(
-                            *span,
-                            "`...` must be the last argument of a C-variadic function",
-                        );
-                    }
-                }
-            }
-            _ => {}
-        }
-    }
-
-    fn check_decl_attrs(&self, fn_decl: &FnDecl) {
-        fn_decl
-            .inputs
-            .iter()
-            .flat_map(|i| i.attrs.as_ref())
-            .filter(|attr| {
-                let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn];
-                !arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
-            })
-            .for_each(|attr| {
-                if attr.is_doc_comment() {
-                    self.err_handler()
-                        .struct_span_err(
-                            attr.span,
-                            "documentation comments cannot be applied to function parameters",
-                        )
-                        .span_label(attr.span, "doc comments are not allowed here")
-                        .emit();
-                } else {
-                    self.err_handler().span_err(
-                        attr.span,
-                        "allow, cfg, cfg_attr, deny, \
-                forbid, and warn are the only allowed built-in attributes in function parameters",
-                    )
-                }
-            });
-    }
-
-    fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
-        if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
-            if param.is_self() {
-                self.err_handler()
-                    .struct_span_err(
-                        param.span,
-                        "`self` parameter is only allowed in associated functions",
-                    )
-                    .span_label(param.span, "not semantically valid as function parameter")
-                    .note("associated functions are those in `impl` or `trait` definitions")
-                    .emit();
-            }
-        }
-    }
-
-    fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
-        if let Defaultness::Default(def_span) = defaultness {
-            let span = self.session.source_map().guess_head_span(span);
-            self.err_handler()
-                .struct_span_err(span, "`default` is only allowed on items in trait impls")
-                .span_label(def_span, "`default` because of this")
-                .emit();
-        }
-    }
-
-    fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) {
-        self.err_handler()
-            .struct_span_err(sp, msg)
-            .span_suggestion(
-                self.session.source_map().end_point(sp),
-                &format!("provide a definition for the {}", ctx),
-                sugg.to_string(),
-                Applicability::HasPlaceholders,
-            )
-            .emit();
-    }
-
-    fn check_impl_item_provided(&self, sp: Span, body: &Option, ctx: &str, sugg: &str) {
-        if body.is_none() {
-            let msg = format!("associated {} in `impl` without body", ctx);
-            self.error_item_without_body(sp, ctx, &msg, sugg);
-        }
-    }
-
-    fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
-        let span = match bounds {
-            [] => return,
-            [b0] => b0.span(),
-            [b0, .., bl] => b0.span().to(bl.span()),
-        };
-        self.err_handler()
-            .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx))
-            .emit();
-    }
-
-    fn check_foreign_ty_genericless(&self, generics: &Generics) {
-        let cannot_have = |span, descr, remove_descr| {
-            self.err_handler()
-                .struct_span_err(
-                    span,
-                    &format!("`type`s inside `extern` blocks cannot have {}", descr),
-                )
-                .span_suggestion(
-                    span,
-                    &format!("remove the {}", remove_descr),
-                    String::new(),
-                    Applicability::MaybeIncorrect,
-                )
-                .span_label(self.current_extern_span(), "`extern` block begins here")
-                .note(MORE_EXTERN)
-                .emit();
-        };
-
-        if !generics.params.is_empty() {
-            cannot_have(generics.span, "generic parameters", "generic parameters");
-        }
-
-        if !generics.where_clause.predicates.is_empty() {
-            cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
-        }
-    }
-
-    fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option) {
-        let body = match body {
-            None => return,
-            Some(body) => body,
-        };
-        self.err_handler()
-            .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind))
-            .span_label(ident.span, "cannot have a body")
-            .span_label(body, "the invalid body")
-            .span_label(
-                self.current_extern_span(),
-                format!(
-                    "`extern` blocks define existing foreign {0}s and {0}s \
-                    inside of them cannot have a body",
-                    kind
-                ),
-            )
-            .note(MORE_EXTERN)
-            .emit();
-    }
-
-    /// An `fn` in `extern { ... }` cannot have a body `{ ... }`.
-    fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
-        let body = match body {
-            None => return,
-            Some(body) => body,
-        };
-        self.err_handler()
-            .struct_span_err(ident.span, "incorrect function inside `extern` block")
-            .span_label(ident.span, "cannot have a body")
-            .span_suggestion(
-                body.span,
-                "remove the invalid body",
-                ";".to_string(),
-                Applicability::MaybeIncorrect,
-            )
-            .help(
-                "you might have meant to write a function accessible through FFI, \
-                which can be done by writing `extern fn` outside of the `extern` block",
-            )
-            .span_label(
-                self.current_extern_span(),
-                "`extern` blocks define existing foreign functions and functions \
-                inside of them cannot have a body",
-            )
-            .note(MORE_EXTERN)
-            .emit();
-    }
-
-    fn current_extern_span(&self) -> Span {
-        self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
-    }
-
-    /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
-    fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
-        if header.has_qualifiers() {
-            self.err_handler()
-                .struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
-                .span_label(self.current_extern_span(), "in this `extern` block")
-                .span_suggestion_verbose(
-                    span.until(ident.span.shrink_to_lo()),
-                    "remove the qualifiers",
-                    "fn ".to_string(),
-                    Applicability::MaybeIncorrect,
-                )
-                .emit();
-        }
-    }
-
-    /// Reject C-varadic type unless the function is foreign,
-    /// or free and `unsafe extern "C"` semantically.
-    fn check_c_varadic_type(&self, fk: FnKind<'a>) {
-        match (fk.ctxt(), fk.header()) {
-            (Some(FnCtxt::Foreign), _) => return,
-            (Some(FnCtxt::Free), Some(header)) => match header.ext {
-                Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit
-                    if matches!(header.unsafety, Unsafe::Yes(_)) =>
-                {
-                    return;
-                }
-                _ => {}
-            },
-            _ => {}
-        };
-
-        for Param { ty, span, .. } in &fk.decl().inputs {
-            if let TyKind::CVarArgs = ty.kind {
-                self.err_handler()
-                    .struct_span_err(
-                        *span,
-                        "only foreign or `unsafe extern \"C\" functions may be C-variadic",
-                    )
-                    .emit();
-            }
-        }
-    }
-
-    fn check_item_named(&self, ident: Ident, kind: &str) {
-        if ident.name != kw::Underscore {
-            return;
-        }
-        self.err_handler()
-            .struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind))
-            .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
-            .emit();
-    }
-
-    fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) {
-        if ident.name.as_str().is_ascii() {
-            return;
-        }
-        let head_span = self.session.source_map().guess_head_span(item_span);
-        struct_span_err!(
-            self.session,
-            head_span,
-            E0754,
-            "`#[no_mangle]` requires ASCII identifier"
-        )
-        .emit();
-    }
-
-    fn check_mod_file_item_asciionly(&self, ident: Ident) {
-        if ident.name.as_str().is_ascii() {
-            return;
-        }
-        struct_span_err!(
-            self.session,
-            ident.span,
-            E0754,
-            "trying to load file for module `{}` with non ascii identifer name",
-            ident.name
-        )
-        .help("consider using `#[path]` attribute to specify filesystem path")
-        .emit();
-    }
-
-    fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
-        if !generics.params.is_empty() {
-            struct_span_err!(
-                self.session,
-                generics.span,
-                E0567,
-                "auto traits cannot have generic parameters"
-            )
-            .span_label(ident_span, "auto trait cannot have generic parameters")
-            .span_suggestion(
-                generics.span,
-                "remove the parameters",
-                String::new(),
-                Applicability::MachineApplicable,
-            )
-            .emit();
-        }
-    }
-
-    fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
-        if let [first @ last] | [first, .., last] = &bounds[..] {
-            let span = first.span().to(last.span());
-            struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
-                .span_label(ident_span, "auto trait cannot have super traits")
-                .span_suggestion(
-                    span,
-                    "remove the super traits",
-                    String::new(),
-                    Applicability::MachineApplicable,
-                )
-                .emit();
-        }
-    }
-
-    fn deny_items(&self, trait_items: &[P], ident_span: Span) {
-        if !trait_items.is_empty() {
-            let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
-            struct_span_err!(
-                self.session,
-                spans,
-                E0380,
-                "auto traits cannot have methods or associated items"
-            )
-            .span_label(ident_span, "auto trait cannot have items")
-            .emit();
-        }
-    }
-
-    fn correct_generic_order_suggestion(&self, data: &AngleBracketedArgs) -> String {
-        // Lifetimes always come first.
-        let lt_sugg = data.args.iter().filter_map(|arg| match arg {
-            AngleBracketedArg::Arg(lt @ GenericArg::Lifetime(_)) => {
-                Some(pprust::to_string(|s| s.print_generic_arg(lt)))
-            }
-            _ => None,
-        });
-        let args_sugg = data.args.iter().filter_map(|a| match a {
-            AngleBracketedArg::Arg(GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => {
-                None
-            }
-            AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
-        });
-        // Constraints always come last.
-        let constraint_sugg = data.args.iter().filter_map(|a| match a {
-            AngleBracketedArg::Arg(_) => None,
-            AngleBracketedArg::Constraint(c) => {
-                Some(pprust::to_string(|s| s.print_assoc_constraint(c)))
-            }
-        });
-        format!(
-            "<{}>",
-            lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::>().join(", ")
-        )
-    }
-
-    /// Enforce generic args coming before constraints in `<...>` of a path segment.
-    fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
-        // Early exit in case it's partitioned as it should be.
-        if data.args.iter().is_partitioned(|arg| matches!(arg, AngleBracketedArg::Arg(_))) {
-            return;
-        }
-        // Find all generic argument coming after the first constraint...
-        let (constraint_spans, arg_spans): (Vec, Vec) =
-            data.args.iter().partition_map(|arg| match arg {
-                AngleBracketedArg::Constraint(c) => Either::Left(c.span),
-                AngleBracketedArg::Arg(a) => Either::Right(a.span()),
-            });
-        let args_len = arg_spans.len();
-        let constraint_len = constraint_spans.len();
-        // ...and then error:
-        self.err_handler()
-            .struct_span_err(
-                arg_spans.clone(),
-                "generic arguments must come before the first constraint",
-            )
-            .span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len)))
-            .span_label(
-                *arg_spans.iter().last().unwrap(),
-                &format!("generic argument{}", pluralize!(args_len)),
-            )
-            .span_labels(constraint_spans, "")
-            .span_labels(arg_spans, "")
-            .span_suggestion_verbose(
-                data.span,
-                &format!(
-                    "move the constraint{} after the generic argument{}",
-                    pluralize!(constraint_len),
-                    pluralize!(args_len)
-                ),
-                self.correct_generic_order_suggestion(&data),
-                Applicability::MachineApplicable,
-            )
-            .emit();
-    }
-}
-
-/// Checks that generic parameters are in the correct order,
-/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
-fn validate_generic_param_order(
-    sess: &Session,
-    handler: &rustc_errors::Handler,
-    generics: &[GenericParam],
-    span: Span,
-) {
-    let mut max_param: Option = None;
-    let mut out_of_order = FxHashMap::default();
-    let mut param_idents = vec![];
-
-    for param in generics {
-        let ident = Some(param.ident.to_string());
-        let (kind, bounds, span) = (¶m.kind, Some(&*param.bounds), param.ident.span);
-        let (ord_kind, ident) = match ¶m.kind {
-            GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
-            GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
-            GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
-                let ty = pprust::ty_to_string(ty);
-                let unordered = sess.features_untracked().const_generics;
-                (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
-            }
-        };
-        if let Some(ident) = ident {
-            param_idents.push((kind, ord_kind, bounds, param_idents.len(), ident));
-        }
-        let max_param = &mut max_param;
-        match max_param {
-            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),
-        };
-    }
-
-    let mut ordered_params = "<".to_string();
-    if !out_of_order.is_empty() {
-        param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i));
-        let mut first = true;
-        for (kind, _, bounds, _, ident) in param_idents {
-            if !first {
-                ordered_params += ", ";
-            }
-            ordered_params += &ident;
-            if let Some(bounds) = bounds {
-                if !bounds.is_empty() {
-                    ordered_params += ": ";
-                    ordered_params += &pprust::bounds_to_string(&bounds);
-                }
-            }
-            match kind {
-                GenericParamKind::Type { default: Some(default) } => {
-                    ordered_params += " = ";
-                    ordered_params += &pprust::ty_to_string(default);
-                }
-                GenericParamKind::Type { default: None } => (),
-                GenericParamKind::Lifetime => (),
-                // FIXME(const_generics_defaults)
-                GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
-            }
-            first = false;
-        }
-    }
-    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().const_generics {
-                    "then consts and types"
-                } else {
-                    "then types, then consts"
-                }
-            ),
-            ordered_params.clone(),
-            Applicability::MachineApplicable,
-        );
-        err.emit();
-    }
-}
-
-impl<'a> Visitor<'a> for AstValidator<'a> {
-    fn visit_attribute(&mut self, attr: &Attribute) {
-        validate_attr::check_meta(&self.session.parse_sess, attr);
-    }
-
-    fn visit_expr(&mut self, expr: &'a Expr) {
-        match &expr.kind {
-            ExprKind::LlvmInlineAsm(..) if !self.session.target.allow_asm => {
-                struct_span_err!(
-                    self.session,
-                    expr.span,
-                    E0472,
-                    "llvm_asm! is unsupported on this target"
-                )
-                .emit();
-            }
-            _ => {}
-        }
-
-        visit::walk_expr(self, expr);
-    }
-
-    fn visit_ty(&mut self, ty: &'a Ty) {
-        match ty.kind {
-            TyKind::BareFn(ref bfty) => {
-                self.check_fn_decl(&bfty.decl, SelfSemantic::No);
-                Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
-                    struct_span_err!(
-                        self.session,
-                        span,
-                        E0561,
-                        "patterns aren't allowed in function pointer types"
-                    )
-                    .emit();
-                });
-                self.check_late_bound_lifetime_defs(&bfty.generic_params);
-            }
-            TyKind::TraitObject(ref bounds, ..) => {
-                let mut any_lifetime_bounds = false;
-                for bound in bounds {
-                    if let GenericBound::Outlives(ref lifetime) = *bound {
-                        if any_lifetime_bounds {
-                            struct_span_err!(
-                                self.session,
-                                lifetime.ident.span,
-                                E0226,
-                                "only a single explicit lifetime bound is permitted"
-                            )
-                            .emit();
-                            break;
-                        }
-                        any_lifetime_bounds = true;
-                    }
-                }
-                self.no_questions_in_bounds(bounds, "trait object types", false);
-            }
-            TyKind::ImplTrait(_, ref bounds) => {
-                if self.is_impl_trait_banned {
-                    struct_span_err!(
-                        self.session,
-                        ty.span,
-                        E0667,
-                        "`impl Trait` is not allowed in path parameters"
-                    )
-                    .emit();
-                }
-
-                if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
-                    struct_span_err!(
-                        self.session,
-                        ty.span,
-                        E0666,
-                        "nested `impl Trait` is not allowed"
-                    )
-                    .span_label(outer_impl_trait_sp, "outer `impl Trait`")
-                    .span_label(ty.span, "nested `impl Trait` here")
-                    .emit();
-                }
-
-                if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
-                    self.err_handler().span_err(ty.span, "at least one trait must be specified");
-                }
-
-                self.walk_ty(ty);
-                return;
-            }
-            _ => {}
-        }
-
-        self.walk_ty(ty)
-    }
-
-    fn visit_label(&mut self, label: &'a Label) {
-        self.check_label(label.ident);
-        visit::walk_label(self, label);
-    }
-
-    fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
-        self.check_lifetime(lifetime.ident);
-        visit::walk_lifetime(self, lifetime);
-    }
-
-    fn visit_item(&mut self, item: &'a Item) {
-        if item.attrs.iter().any(|attr| self.session.is_proc_macro_attr(attr)) {
-            self.has_proc_macro_decls = true;
-        }
-
-        if self.session.contains_name(&item.attrs, sym::no_mangle) {
-            self.check_nomangle_item_asciionly(item.ident, item.span);
-        }
-
-        match item.kind {
-            ItemKind::Impl(box ImplKind {
-                unsafety,
-                polarity,
-                defaultness: _,
-                constness: _,
-                generics: _,
-                of_trait: Some(ref t),
-                ref self_ty,
-                items: _,
-            }) => {
-                self.with_in_trait_impl(true, |this| {
-                    this.invalid_visibility(&item.vis, None);
-                    if let TyKind::Err = self_ty.kind {
-                        this.err_handler()
-                            .struct_span_err(
-                                item.span,
-                                "`impl Trait for .. {}` is an obsolete syntax",
-                            )
-                            .help("use `auto trait Trait {}` instead")
-                            .emit();
-                    }
-                    if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
-                        struct_span_err!(
-                            this.session,
-                            sp.to(t.path.span),
-                            E0198,
-                            "negative impls cannot be unsafe"
-                        )
-                        .span_label(sp, "negative because of this")
-                        .span_label(span, "unsafe because of this")
-                        .emit();
-                    }
-
-                    visit::walk_item(this, item);
-                });
-                return; // Avoid visiting again.
-            }
-            ItemKind::Impl(box ImplKind {
-                unsafety,
-                polarity,
-                defaultness,
-                constness,
-                generics: _,
-                of_trait: None,
-                ref self_ty,
-                items: _,
-            }) => {
-                let error = |annotation_span, annotation| {
-                    let mut err = self.err_handler().struct_span_err(
-                        self_ty.span,
-                        &format!("inherent impls cannot be {}", annotation),
-                    );
-                    err.span_label(annotation_span, &format!("{} because of this", annotation));
-                    err.span_label(self_ty.span, "inherent impl for this type");
-                    err
-                };
-
-                self.invalid_visibility(
-                    &item.vis,
-                    Some("place qualifiers on individual impl items instead"),
-                );
-                if let Unsafe::Yes(span) = unsafety {
-                    error(span, "unsafe").code(error_code!(E0197)).emit();
-                }
-                if let ImplPolarity::Negative(span) = polarity {
-                    error(span, "negative").emit();
-                }
-                if let Defaultness::Default(def_span) = defaultness {
-                    error(def_span, "`default`")
-                        .note("only trait implementations may be annotated with `default`")
-                        .emit();
-                }
-                if let Const::Yes(span) = constness {
-                    error(span, "`const`")
-                        .note("only trait implementations may be annotated with `const`")
-                        .emit();
-                }
-            }
-            ItemKind::Fn(box FnKind(def, _, _, ref body)) => {
-                self.check_defaultness(item.span, def);
-
-                if body.is_none() {
-                    let msg = "free function without a body";
-                    self.error_item_without_body(item.span, "function", msg, " {  }");
-                }
-            }
-            ItemKind::ForeignMod(ForeignMod { unsafety, .. }) => {
-                let old_item = mem::replace(&mut self.extern_mod, Some(item));
-                self.invalid_visibility(
-                    &item.vis,
-                    Some("place qualifiers on individual foreign items instead"),
-                );
-                if let Unsafe::Yes(span) = unsafety {
-                    self.err_handler().span_err(span, "extern block cannot be declared unsafe");
-                }
-                visit::walk_item(self, item);
-                self.extern_mod = old_item;
-                return; // Avoid visiting again.
-            }
-            ItemKind::Enum(ref def, _) => {
-                for variant in &def.variants {
-                    self.invalid_visibility(&variant.vis, None);
-                    for field in variant.data.fields() {
-                        self.invalid_visibility(&field.vis, None);
-                    }
-                }
-            }
-            ItemKind::Trait(box TraitKind(
-                is_auto,
-                _,
-                ref generics,
-                ref bounds,
-                ref trait_items,
-            )) => {
-                if is_auto == IsAuto::Yes {
-                    // Auto traits cannot have generics, super traits nor contain items.
-                    self.deny_generic_params(generics, item.ident.span);
-                    self.deny_super_traits(bounds, item.ident.span);
-                    self.deny_items(trait_items, item.ident.span);
-                }
-                self.no_questions_in_bounds(bounds, "supertraits", true);
-
-                // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
-                // context for the supertraits.
-                self.visit_vis(&item.vis);
-                self.visit_ident(item.ident);
-                self.visit_generics(generics);
-                self.with_bound_context(BoundContext::TraitBounds, |this| {
-                    walk_list!(this, visit_param_bound, bounds);
-                });
-                walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
-                walk_list!(self, visit_attribute, &item.attrs);
-                return;
-            }
-            ItemKind::Mod(Mod { inline, unsafety, .. }) => {
-                if let Unsafe::Yes(span) = unsafety {
-                    self.err_handler().span_err(span, "module cannot be declared unsafe");
-                }
-                // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
-                if !inline && !self.session.contains_name(&item.attrs, sym::path) {
-                    self.check_mod_file_item_asciionly(item.ident);
-                }
-            }
-            ItemKind::Union(ref vdata, _) => {
-                if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
-                    self.err_handler()
-                        .span_err(item.span, "tuple and unit unions are not permitted");
-                }
-                if vdata.fields().is_empty() {
-                    self.err_handler().span_err(item.span, "unions cannot have zero fields");
-                }
-            }
-            ItemKind::Const(def, .., None) => {
-                self.check_defaultness(item.span, def);
-                let msg = "free constant item without body";
-                self.error_item_without_body(item.span, "constant", msg, " = ;");
-            }
-            ItemKind::Static(.., None) => {
-                let msg = "free static item without body";
-                self.error_item_without_body(item.span, "static", msg, " = ;");
-            }
-            ItemKind::TyAlias(box TyAliasKind(def, _, ref bounds, ref body)) => {
-                self.check_defaultness(item.span, def);
-                if body.is_none() {
-                    let msg = "free type alias without body";
-                    self.error_item_without_body(item.span, "type", msg, " = ;");
-                }
-                self.check_type_no_bounds(bounds, "this context");
-            }
-            _ => {}
-        }
-
-        visit::walk_item(self, item)
-    }
-
-    fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
-        match &fi.kind {
-            ForeignItemKind::Fn(box FnKind(def, sig, _, body)) => {
-                self.check_defaultness(fi.span, *def);
-                self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
-                self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
-            }
-            ForeignItemKind::TyAlias(box TyAliasKind(def, generics, bounds, body)) => {
-                self.check_defaultness(fi.span, *def);
-                self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
-                self.check_type_no_bounds(bounds, "`extern` blocks");
-                self.check_foreign_ty_genericless(generics);
-            }
-            ForeignItemKind::Static(_, _, body) => {
-                self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
-            }
-            ForeignItemKind::MacCall(..) => {}
-        }
-
-        visit::walk_foreign_item(self, fi)
-    }
-
-    // Mirrors `visit::walk_generic_args`, but tracks relevant state.
-    fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
-        match *generic_args {
-            GenericArgs::AngleBracketed(ref data) => {
-                self.check_generic_args_before_constraints(data);
-
-                for arg in &data.args {
-                    match arg {
-                        AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
-                        // Type bindings such as `Item = impl Debug` in `Iterator`
-                        // are allowed to contain nested `impl Trait`.
-                        AngleBracketedArg::Constraint(constraint) => {
-                            self.with_impl_trait(None, |this| {
-                                this.visit_assoc_ty_constraint_from_generic_args(constraint);
-                            });
-                        }
-                    }
-                }
-            }
-            GenericArgs::Parenthesized(ref data) => {
-                walk_list!(self, visit_ty, &data.inputs);
-                if let FnRetTy::Ty(ty) = &data.output {
-                    // `-> Foo` syntax is essentially an associated type binding,
-                    // so it is also allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(None, |this| this.visit_ty(ty));
-                }
-            }
-        }
-    }
-
-    fn visit_generics(&mut self, generics: &'a Generics) {
-        let mut prev_ty_default = None;
-        for param in &generics.params {
-            match param.kind {
-                GenericParamKind::Lifetime => (),
-                GenericParamKind::Type { default: Some(_), .. } => {
-                    prev_ty_default = Some(param.ident.span);
-                }
-                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
-                    if let Some(span) = prev_ty_default {
-                        let mut err = self.err_handler().struct_span_err(
-                            span,
-                            "type parameters with a default must be trailing",
-                        );
-                        if matches!(param.kind, GenericParamKind::Const { .. }) {
-                            err.note(
-                                "using type defaults and const parameters \
-                                 in the same parameter list is currently not permitted",
-                            );
-                        }
-                        err.emit();
-                        break;
-                    }
-                }
-            }
-        }
-
-        validate_generic_param_order(
-            self.session,
-            self.err_handler(),
-            &generics.params,
-            generics.span,
-        );
-
-        for predicate in &generics.where_clause.predicates {
-            if let WherePredicate::EqPredicate(ref predicate) = *predicate {
-                deny_equality_constraints(self, predicate, generics);
-            }
-        }
-
-        visit::walk_generics(self, generics)
-    }
-
-    fn visit_generic_param(&mut self, param: &'a GenericParam) {
-        if let GenericParamKind::Lifetime { .. } = param.kind {
-            self.check_lifetime(param.ident);
-        }
-        visit::walk_generic_param(self, param);
-    }
-
-    fn visit_param_bound(&mut self, bound: &'a GenericBound) {
-        match bound {
-            GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
-                if let Some(ctx) = self.bound_context {
-                    let msg = format!("`?const` is not permitted in {}", ctx.description());
-                    self.err_handler().span_err(bound.span(), &msg);
-                }
-            }
-
-            GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
-                self.err_handler()
-                    .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
-            }
-
-            _ => {}
-        }
-
-        visit::walk_param_bound(self, bound)
-    }
-
-    fn visit_pat(&mut self, pat: &'a Pat) {
-        match &pat.kind {
-            PatKind::Lit(expr) => {
-                self.check_expr_within_pat(expr, false);
-            }
-            PatKind::Range(start, end, _) => {
-                if let Some(expr) = start {
-                    self.check_expr_within_pat(expr, true);
-                }
-                if let Some(expr) = end {
-                    self.check_expr_within_pat(expr, true);
-                }
-            }
-            _ => {}
-        }
-
-        visit::walk_pat(self, pat)
-    }
-
-    fn visit_where_predicate(&mut self, p: &'a WherePredicate) {
-        if let &WherePredicate::BoundPredicate(ref bound_predicate) = p {
-            // A type binding, eg `for<'c> Foo: Send+Clone+'c`
-            self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params);
-        }
-        visit::walk_where_predicate(self, p);
-    }
-
-    fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
-        self.check_late_bound_lifetime_defs(&t.bound_generic_params);
-        visit::walk_poly_trait_ref(self, t, m);
-    }
-
-    fn visit_variant_data(&mut self, s: &'a VariantData) {
-        self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
-    }
-
-    fn visit_enum_def(
-        &mut self,
-        enum_definition: &'a EnumDef,
-        generics: &'a Generics,
-        item_id: NodeId,
-        _: Span,
-    ) {
-        self.with_banned_assoc_ty_bound(|this| {
-            visit::walk_enum_def(this, enum_definition, generics, item_id)
-        })
-    }
-
-    fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
-        // Only associated `fn`s can have `self` parameters.
-        let self_semantic = match fk.ctxt() {
-            Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
-            _ => SelfSemantic::No,
-        };
-        self.check_fn_decl(fk.decl(), self_semantic);
-
-        self.check_c_varadic_type(fk);
-
-        // Functions cannot both be `const async`
-        if let Some(FnHeader {
-            constness: Const::Yes(cspan),
-            asyncness: Async::Yes { span: aspan, .. },
-            ..
-        }) = fk.header()
-        {
-            self.err_handler()
-                .struct_span_err(
-                    vec![*cspan, *aspan],
-                    "functions cannot be both `const` and `async`",
-                )
-                .span_label(*cspan, "`const` because of this")
-                .span_label(*aspan, "`async` because of this")
-                .span_label(span, "") // Point at the fn header.
-                .emit();
-        }
-
-        // Functions without bodies cannot have patterns.
-        if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
-            Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
-                let (code, msg, label) = match ctxt {
-                    FnCtxt::Foreign => (
-                        error_code!(E0130),
-                        "patterns aren't allowed in foreign function declarations",
-                        "pattern not allowed in foreign function",
-                    ),
-                    _ => (
-                        error_code!(E0642),
-                        "patterns aren't allowed in functions without bodies",
-                        "pattern not allowed in function without body",
-                    ),
-                };
-                if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
-                    if let Some(ident) = ident {
-                        let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
-                        self.lint_buffer.buffer_lint_with_diagnostic(
-                            PATTERNS_IN_FNS_WITHOUT_BODY,
-                            id,
-                            span,
-                            msg,
-                            diag,
-                        )
-                    }
-                } else {
-                    self.err_handler()
-                        .struct_span_err(span, msg)
-                        .span_label(span, label)
-                        .code(code)
-                        .emit();
-                }
-            });
-        }
-
-        visit::walk_fn(self, fk, span);
-    }
-
-    fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
-        if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
-            self.check_defaultness(item.span, item.kind.defaultness());
-        }
-
-        if ctxt == AssocCtxt::Impl {
-            match &item.kind {
-                AssocItemKind::Const(_, _, body) => {
-                    self.check_impl_item_provided(item.span, body, "constant", " = ;");
-                }
-                AssocItemKind::Fn(box FnKind(_, _, _, body)) => {
-                    self.check_impl_item_provided(item.span, body, "function", " {  }");
-                }
-                AssocItemKind::TyAlias(box TyAliasKind(_, _, bounds, body)) => {
-                    self.check_impl_item_provided(item.span, body, "type", " = ;");
-                    self.check_type_no_bounds(bounds, "`impl`s");
-                }
-                _ => {}
-            }
-        }
-
-        if ctxt == AssocCtxt::Trait || self.in_trait_impl {
-            self.invalid_visibility(&item.vis, None);
-            if let AssocItemKind::Fn(box FnKind(_, sig, _, _)) = &item.kind {
-                self.check_trait_fn_not_const(sig.header.constness);
-                self.check_trait_fn_not_async(item.span, sig.header.asyncness);
-            }
-        }
-
-        if let AssocItemKind::Const(..) = item.kind {
-            self.check_item_named(item.ident, "const");
-        }
-
-        self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
-    }
-}
-
-/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
-/// like it's setting an associated type, provide an appropriate suggestion.
-fn deny_equality_constraints(
-    this: &mut AstValidator<'_>,
-    predicate: &WhereEqPredicate,
-    generics: &Generics,
-) {
-    let mut err = this.err_handler().struct_span_err(
-        predicate.span,
-        "equality constraints are not yet supported in `where` clauses",
-    );
-    err.span_label(predicate.span, "not supported");
-
-    // Given `::Bar = RhsTy`, suggest `A: Foo`.
-    if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
-        if let TyKind::Path(None, path) = &qself.ty.kind {
-            match &path.segments[..] {
-                [PathSegment { ident, args: None, .. }] => {
-                    for param in &generics.params {
-                        if param.ident == *ident {
-                            let param = ident;
-                            match &full_path.segments[qself.position..] {
-                                [PathSegment { ident, args, .. }] => {
-                                    // Make a new `Path` from `foo::Bar` to `Foo`.
-                                    let mut assoc_path = full_path.clone();
-                                    // Remove `Bar` from `Foo::Bar`.
-                                    assoc_path.segments.pop();
-                                    let len = assoc_path.segments.len() - 1;
-                                    let gen_args = args.as_ref().map(|p| (**p).clone());
-                                    // Build ``.
-                                    let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
-                                        id: rustc_ast::node_id::DUMMY_NODE_ID,
-                                        ident: *ident,
-                                        gen_args,
-                                        kind: AssocTyConstraintKind::Equality {
-                                            ty: predicate.rhs_ty.clone(),
-                                        },
-                                        span: ident.span,
-                                    });
-                                    // Add `` to `Foo`.
-                                    match &mut assoc_path.segments[len].args {
-                                        Some(args) => match args.deref_mut() {
-                                            GenericArgs::Parenthesized(_) => continue,
-                                            GenericArgs::AngleBracketed(args) => {
-                                                args.args.push(arg);
-                                            }
-                                        },
-                                        empty_args => {
-                                            *empty_args = AngleBracketedArgs {
-                                                span: ident.span,
-                                                args: vec![arg],
-                                            }
-                                            .into();
-                                        }
-                                    }
-                                    err.span_suggestion_verbose(
-                                        predicate.span,
-                                        &format!(
-                                            "if `{}` is an associated type you're trying to set, \
-                                            use the associated type binding syntax",
-                                            ident
-                                        ),
-                                        format!(
-                                            "{}: {}",
-                                            param,
-                                            pprust::path_to_string(&assoc_path)
-                                        ),
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                }
-                                _ => {}
-                            };
-                        }
-                    }
-                }
-                _ => {}
-            }
-        }
-    }
-    err.note(
-        "see issue #20041  for more information",
-    );
-    err.emit();
-}
-
-pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
-    let mut validator = AstValidator {
-        session,
-        extern_mod: None,
-        in_trait_impl: false,
-        has_proc_macro_decls: false,
-        outer_impl_trait: None,
-        bound_context: None,
-        is_impl_trait_banned: false,
-        is_assoc_ty_bound_banned: false,
-        lint_buffer: lints,
-    };
-    visit::walk_crate(&mut validator, krate);
-
-    validator.has_proc_macro_decls
-}
diff --git a/vendor/rustc-ap-rustc_ast_passes/src/feature_gate.rs b/vendor/rustc-ap-rustc_ast_passes/src/feature_gate.rs
deleted file mode 100644
index 6514de2b81..0000000000
--- a/vendor/rustc-ap-rustc_ast_passes/src/feature_gate.rs
+++ /dev/null
@@ -1,748 +0,0 @@
-use rustc_ast as ast;
-use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
-use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
-use rustc_ast::{PatKind, RangeEnd, VariantData};
-use rustc_errors::struct_span_err;
-use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
-use rustc_feature::{Features, GateIssue};
-use rustc_session::parse::{feature_err, feature_err_issue};
-use rustc_session::Session;
-use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::Span;
-
-use tracing::debug;
-
-macro_rules! gate_feature_fn {
-    ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
-        let (visitor, has_feature, span, name, explain, help) =
-            (&*$visitor, $has_feature, $span, $name, $explain, $help);
-        let has_feature: bool = has_feature(visitor.features);
-        debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
-        if !has_feature && !span.allows_unstable($name) {
-            feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
-                .help(help)
-                .emit();
-        }
-    }};
-    ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
-        let (visitor, has_feature, span, name, explain) =
-            (&*$visitor, $has_feature, $span, $name, $explain);
-        let has_feature: bool = has_feature(visitor.features);
-        debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
-        if !has_feature && !span.allows_unstable($name) {
-            feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
-                .emit();
-        }
-    }};
-}
-
-macro_rules! gate_feature_post {
-    ($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
-        gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
-    };
-    ($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
-        gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
-    };
-}
-
-pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
-    PostExpansionVisitor { sess, features }.visit_attribute(attr)
-}
-
-struct PostExpansionVisitor<'a> {
-    sess: &'a Session,
-
-    // `sess` contains a `Features`, but this might not be that one.
-    features: &'a Features,
-}
-
-impl<'a> PostExpansionVisitor<'a> {
-    fn check_abi(&self, abi: ast::StrLit) {
-        let ast::StrLit { symbol_unescaped, span, .. } = abi;
-
-        match &*symbol_unescaped.as_str() {
-            // Stable
-            "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
-            | "system" => {}
-            "rust-intrinsic" => {
-                gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change");
-            }
-            "platform-intrinsic" => {
-                gate_feature_post!(
-                    &self,
-                    platform_intrinsics,
-                    span,
-                    "platform intrinsics are experimental and possibly buggy"
-                );
-            }
-            "vectorcall" => {
-                gate_feature_post!(
-                    &self,
-                    abi_vectorcall,
-                    span,
-                    "vectorcall is experimental and subject to change"
-                );
-            }
-            "thiscall" => {
-                gate_feature_post!(
-                    &self,
-                    abi_thiscall,
-                    span,
-                    "thiscall is experimental and subject to change"
-                );
-            }
-            "rust-call" => {
-                gate_feature_post!(
-                    &self,
-                    unboxed_closures,
-                    span,
-                    "rust-call ABI is subject to change"
-                );
-            }
-            "ptx-kernel" => {
-                gate_feature_post!(
-                    &self,
-                    abi_ptx,
-                    span,
-                    "PTX ABIs are experimental and subject to change"
-                );
-            }
-            "unadjusted" => {
-                gate_feature_post!(
-                    &self,
-                    abi_unadjusted,
-                    span,
-                    "unadjusted ABI is an implementation detail and perma-unstable"
-                );
-            }
-            "msp430-interrupt" => {
-                gate_feature_post!(
-                    &self,
-                    abi_msp430_interrupt,
-                    span,
-                    "msp430-interrupt ABI is experimental and subject to change"
-                );
-            }
-            "x86-interrupt" => {
-                gate_feature_post!(
-                    &self,
-                    abi_x86_interrupt,
-                    span,
-                    "x86-interrupt ABI is experimental and subject to change"
-                );
-            }
-            "amdgpu-kernel" => {
-                gate_feature_post!(
-                    &self,
-                    abi_amdgpu_kernel,
-                    span,
-                    "amdgpu-kernel ABI is experimental and subject to change"
-                );
-            }
-            "avr-interrupt" | "avr-non-blocking-interrupt" => {
-                gate_feature_post!(
-                    &self,
-                    abi_avr_interrupt,
-                    span,
-                    "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
-                );
-            }
-            "efiapi" => {
-                gate_feature_post!(
-                    &self,
-                    abi_efiapi,
-                    span,
-                    "efiapi ABI is experimental and subject to change"
-                );
-            }
-            "C-cmse-nonsecure-call" => {
-                gate_feature_post!(
-                    &self,
-                    abi_c_cmse_nonsecure_call,
-                    span,
-                    "C-cmse-nonsecure-call ABI is experimental and subject to change"
-                );
-            }
-            abi => self
-                .sess
-                .parse_sess
-                .span_diagnostic
-                .delay_span_bug(span, &format!("unrecognized ABI not caught in lowering: {}", abi)),
-        }
-    }
-
-    fn check_extern(&self, ext: ast::Extern) {
-        if let ast::Extern::Explicit(abi) = ext {
-            self.check_abi(abi);
-        }
-    }
-
-    fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
-        let has_fields = variants.iter().any(|variant| match variant.data {
-            VariantData::Tuple(..) | VariantData::Struct(..) => true,
-            VariantData::Unit(..) => false,
-        });
-
-        let discriminant_spans = variants
-            .iter()
-            .filter(|variant| match variant.data {
-                VariantData::Tuple(..) | VariantData::Struct(..) => false,
-                VariantData::Unit(..) => true,
-            })
-            .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
-            .collect::>();
-
-        if !discriminant_spans.is_empty() && has_fields {
-            let mut err = feature_err(
-                &self.sess.parse_sess,
-                sym::arbitrary_enum_discriminant,
-                discriminant_spans.clone(),
-                "custom discriminant values are not allowed in enums with tuple or struct variants",
-            );
-            for sp in discriminant_spans {
-                err.span_label(sp, "disallowed custom discriminant");
-            }
-            for variant in variants.iter() {
-                match &variant.data {
-                    VariantData::Struct(..) => {
-                        err.span_label(variant.span, "struct variant defined here");
-                    }
-                    VariantData::Tuple(..) => {
-                        err.span_label(variant.span, "tuple variant defined here");
-                    }
-                    VariantData::Unit(..) => {}
-                }
-            }
-            err.emit();
-        }
-    }
-
-    fn check_gat(&self, generics: &ast::Generics, span: Span) {
-        if !generics.params.is_empty() {
-            gate_feature_post!(
-                &self,
-                generic_associated_types,
-                span,
-                "generic associated types are unstable"
-            );
-        }
-        if !generics.where_clause.predicates.is_empty() {
-            gate_feature_post!(
-                &self,
-                generic_associated_types,
-                span,
-                "where clauses on associated types are unstable"
-            );
-        }
-    }
-
-    /// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
-    fn check_impl_trait(&self, ty: &ast::Ty) {
-        struct ImplTraitVisitor<'a> {
-            vis: &'a PostExpansionVisitor<'a>,
-        }
-        impl Visitor<'_> for ImplTraitVisitor<'_> {
-            fn visit_ty(&mut self, ty: &ast::Ty) {
-                if let ast::TyKind::ImplTrait(..) = ty.kind {
-                    gate_feature_post!(
-                        &self.vis,
-                        type_alias_impl_trait,
-                        ty.span,
-                        "`impl Trait` in type aliases is unstable"
-                    );
-                }
-                visit::walk_ty(self, ty);
-            }
-        }
-        ImplTraitVisitor { vis: self }.visit_ty(ty);
-    }
-}
-
-impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
-    fn visit_attribute(&mut self, attr: &ast::Attribute) {
-        let attr_info =
-            attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
-        // Check feature gates for built-in attributes.
-        if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info {
-            gate_feature_fn!(self, has_feature, attr.span, name, descr);
-        }
-        // Check unstable flavors of the `#[doc]` attribute.
-        if self.sess.check_name(attr, sym::doc) {
-            for nested_meta in attr.meta_item_list().unwrap_or_default() {
-                macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
-                    $(if nested_meta.has_name(sym::$name) {
-                        let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental");
-                        gate_feature_post!(self, $feature, attr.span, msg);
-                    })*
-                }}
-
-                gate_doc!(
-                    include => external_doc
-                    cfg => doc_cfg
-                    masked => doc_masked
-                    spotlight => doc_spotlight
-                    keyword => doc_keyword
-                );
-            }
-        }
-    }
-
-    fn visit_name(&mut self, sp: Span, name: Symbol) {
-        if !name.as_str().is_ascii() {
-            gate_feature_post!(
-                &self,
-                non_ascii_idents,
-                self.sess.parse_sess.source_map().guess_head_span(sp),
-                "non-ascii idents are not fully supported"
-            );
-        }
-    }
-
-    fn visit_item(&mut self, i: &'a ast::Item) {
-        match i.kind {
-            ast::ItemKind::ForeignMod(ref foreign_module) => {
-                if let Some(abi) = foreign_module.abi {
-                    self.check_abi(abi);
-                }
-            }
-
-            ast::ItemKind::Fn(..) => {
-                if self.sess.contains_name(&i.attrs[..], sym::plugin_registrar) {
-                    gate_feature_post!(
-                        &self,
-                        plugin_registrar,
-                        i.span,
-                        "compiler plugins are experimental and possibly buggy"
-                    );
-                }
-                if self.sess.contains_name(&i.attrs[..], sym::start) {
-                    gate_feature_post!(
-                        &self,
-                        start,
-                        i.span,
-                        "`#[start]` functions are experimental \
-                         and their signature may change \
-                         over time"
-                    );
-                }
-                if self.sess.contains_name(&i.attrs[..], sym::main) {
-                    gate_feature_post!(
-                        &self,
-                        main,
-                        i.span,
-                        "declaration of a non-standard `#[main]` \
-                         function may change over time, for now \
-                         a top-level `fn main()` is required"
-                    );
-                }
-            }
-
-            ast::ItemKind::Struct(..) => {
-                for attr in self.sess.filter_by_name(&i.attrs[..], sym::repr) {
-                    for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
-                        if item.has_name(sym::simd) {
-                            gate_feature_post!(
-                                &self,
-                                repr_simd,
-                                attr.span,
-                                "SIMD types are experimental and possibly buggy"
-                            );
-                        }
-                    }
-                }
-            }
-
-            ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
-                for variant in variants {
-                    match (&variant.data, &variant.disr_expr) {
-                        (ast::VariantData::Unit(..), _) => {}
-                        (_, Some(disr_expr)) => gate_feature_post!(
-                            &self,
-                            arbitrary_enum_discriminant,
-                            disr_expr.value.span,
-                            "discriminants on non-unit variants are experimental"
-                        ),
-                        _ => {}
-                    }
-                }
-
-                let has_feature = self.features.arbitrary_enum_discriminant;
-                if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
-                    self.maybe_report_invalid_custom_discriminants(&variants);
-                }
-            }
-
-            ast::ItemKind::Impl(box ast::ImplKind {
-                polarity, defaultness, ref of_trait, ..
-            }) => {
-                if let ast::ImplPolarity::Negative(span) = polarity {
-                    gate_feature_post!(
-                        &self,
-                        negative_impls,
-                        span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
-                        "negative trait bounds are not yet fully implemented; \
-                         use marker types for now"
-                    );
-                }
-
-                if let ast::Defaultness::Default(_) = defaultness {
-                    gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
-                }
-            }
-
-            ast::ItemKind::Trait(box ast::TraitKind(ast::IsAuto::Yes, ..)) => {
-                gate_feature_post!(
-                    &self,
-                    auto_traits,
-                    i.span,
-                    "auto traits are experimental and possibly buggy"
-                );
-            }
-
-            ast::ItemKind::TraitAlias(..) => {
-                gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental");
-            }
-
-            ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
-                let msg = "`macro` is experimental";
-                gate_feature_post!(&self, decl_macro, i.span, msg);
-            }
-
-            ast::ItemKind::TyAlias(box ast::TyAliasKind(_, _, _, Some(ref ty))) => {
-                self.check_impl_trait(&ty)
-            }
-
-            _ => {}
-        }
-
-        visit::walk_item(self, i);
-    }
-
-    fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
-        match i.kind {
-            ast::ForeignItemKind::Fn(..) | ast::ForeignItemKind::Static(..) => {
-                let link_name = self.sess.first_attr_value_str_by_name(&i.attrs, sym::link_name);
-                let links_to_llvm =
-                    link_name.map_or(false, |val| val.as_str().starts_with("llvm."));
-                if links_to_llvm {
-                    gate_feature_post!(
-                        &self,
-                        link_llvm_intrinsics,
-                        i.span,
-                        "linking to LLVM intrinsics is experimental"
-                    );
-                }
-            }
-            ast::ForeignItemKind::TyAlias(..) => {
-                gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
-            }
-            ast::ForeignItemKind::MacCall(..) => {}
-        }
-
-        visit::walk_foreign_item(self, i)
-    }
-
-    fn visit_ty(&mut self, ty: &'a ast::Ty) {
-        match ty.kind {
-            ast::TyKind::BareFn(ref bare_fn_ty) => {
-                self.check_extern(bare_fn_ty.ext);
-            }
-            ast::TyKind::Never => {
-                gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
-            }
-            _ => {}
-        }
-        visit::walk_ty(self, ty)
-    }
-
-    fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
-        if let ast::FnRetTy::Ty(ref output_ty) = *ret_ty {
-            if let ast::TyKind::Never = output_ty.kind {
-                // Do nothing.
-            } else {
-                self.visit_ty(output_ty)
-            }
-        }
-    }
-
-    fn visit_expr(&mut self, e: &'a ast::Expr) {
-        match e.kind {
-            ast::ExprKind::Box(_) => {
-                gate_feature_post!(
-                    &self,
-                    box_syntax,
-                    e.span,
-                    "box expression syntax is experimental; you can call `Box::new` instead"
-                );
-            }
-            ast::ExprKind::Type(..) => {
-                // To avoid noise about type ascription in common syntax errors, only emit if it
-                // is the *only* error.
-                if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
-                    gate_feature_post!(
-                        &self,
-                        type_ascription,
-                        e.span,
-                        "type ascription is experimental"
-                    );
-                }
-            }
-            ast::ExprKind::TryBlock(_) => {
-                gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
-            }
-            ast::ExprKind::Block(_, opt_label) => {
-                if let Some(label) = opt_label {
-                    gate_feature_post!(
-                        &self,
-                        label_break_value,
-                        label.ident.span,
-                        "labels on blocks are unstable"
-                    );
-                }
-            }
-            _ => {}
-        }
-        visit::walk_expr(self, e)
-    }
-
-    fn visit_pat(&mut self, pattern: &'a ast::Pat) {
-        match &pattern.kind {
-            PatKind::Box(..) => {
-                gate_feature_post!(
-                    &self,
-                    box_patterns,
-                    pattern.span,
-                    "box pattern syntax is experimental"
-                );
-            }
-            PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
-                gate_feature_post!(
-                    &self,
-                    exclusive_range_pattern,
-                    pattern.span,
-                    "exclusive range pattern syntax is experimental"
-                );
-            }
-            _ => {}
-        }
-        visit::walk_pat(self, pattern)
-    }
-
-    fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
-        if let Some(header) = fn_kind.header() {
-            // Stability of const fn methods are covered in `visit_assoc_item` below.
-            self.check_extern(header.ext);
-
-            if let (ast::Const::Yes(_), ast::Extern::Implicit)
-            | (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext)
-            {
-                gate_feature_post!(
-                    &self,
-                    const_extern_fn,
-                    span,
-                    "`const extern fn` definitions are unstable"
-                );
-            }
-        }
-
-        if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
-            gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
-        }
-
-        visit::walk_fn(self, fn_kind, span)
-    }
-
-    fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
-        if let AssocTyConstraintKind::Bound { .. } = constraint.kind {
-            gate_feature_post!(
-                &self,
-                associated_type_bounds,
-                constraint.span,
-                "associated type bounds are unstable"
-            )
-        }
-        visit::walk_assoc_ty_constraint(self, constraint)
-    }
-
-    fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
-        let is_fn = match i.kind {
-            ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => {
-                if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
-                    gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
-                }
-                true
-            }
-            ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => {
-                if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
-                    gate_feature_post!(
-                        &self,
-                        associated_type_defaults,
-                        i.span,
-                        "associated type defaults are unstable"
-                    );
-                }
-                if let Some(ty) = ty {
-                    self.check_impl_trait(ty);
-                }
-                self.check_gat(generics, i.span);
-                false
-            }
-            _ => false,
-        };
-        if let ast::Defaultness::Default(_) = i.kind.defaultness() {
-            // Limit `min_specialization` to only specializing functions.
-            gate_feature_fn!(
-                &self,
-                |x: &Features| x.specialization || (is_fn && x.min_specialization),
-                i.span,
-                sym::specialization,
-                "specialization is unstable"
-            );
-        }
-        visit::walk_assoc_item(self, i, ctxt)
-    }
-
-    fn visit_vis(&mut self, vis: &'a ast::Visibility) {
-        if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.kind {
-            gate_feature_post!(
-                &self,
-                crate_visibility_modifier,
-                vis.span,
-                "`crate` visibility modifier is experimental"
-            );
-        }
-        visit::walk_vis(self, vis)
-    }
-}
-
-pub fn check_crate(krate: &ast::Crate, sess: &Session) {
-    maybe_stage_features(sess, krate);
-    check_incompatible_features(sess);
-    let mut visitor = PostExpansionVisitor { sess, features: &sess.features_untracked() };
-
-    let spans = sess.parse_sess.gated_spans.spans.borrow();
-    macro_rules! gate_all {
-        ($gate:ident, $msg:literal, $help:literal) => {
-            if let Some(spans) = spans.get(&sym::$gate) {
-                for span in spans {
-                    gate_feature_post!(&visitor, $gate, *span, $msg, $help);
-                }
-            }
-        };
-        ($gate:ident, $msg:literal) => {
-            if let Some(spans) = spans.get(&sym::$gate) {
-                for span in spans {
-                    gate_feature_post!(&visitor, $gate, *span, $msg);
-                }
-            }
-        };
-    }
-    gate_all!(if_let_guard, "`if let` guards are experimental");
-    gate_all!(let_chains, "`let` expressions in this position are experimental");
-    gate_all!(
-        async_closure,
-        "async closures are unstable",
-        "to use an async block, remove the `||`: `async {`"
-    );
-    gate_all!(generators, "yield syntax is experimental");
-    gate_all!(or_patterns, "or-patterns syntax is experimental");
-    gate_all!(raw_ref_op, "raw address of syntax is experimental");
-    gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
-    gate_all!(const_trait_impl, "const trait impls are experimental");
-    gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
-    gate_all!(inline_const, "inline-const is experimental");
-    gate_all!(
-        extended_key_value_attributes,
-        "arbitrary expressions in key-value attributes are unstable"
-    );
-    gate_all!(
-        const_generics_defaults,
-        "default values for const generic parameters are experimental"
-    );
-    if sess.parse_sess.span_diagnostic.err_count() == 0 {
-        // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
-        // involved, so we only emit errors where there are no other parsing errors.
-        gate_all!(destructuring_assignment, "destructuring assignments are unstable");
-    }
-
-    // All uses of `gate_all!` below this point were added in #65742,
-    // and subsequently disabled (with the non-early gating readded).
-    macro_rules! gate_all {
-        ($gate:ident, $msg:literal) => {
-            // FIXME(eddyb) do something more useful than always
-            // disabling these uses of early feature-gatings.
-            if false {
-                for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
-                    gate_feature_post!(&visitor, $gate, *span, $msg);
-                }
-            }
-        };
-    }
-
-    gate_all!(trait_alias, "trait aliases are experimental");
-    gate_all!(associated_type_bounds, "associated type bounds are unstable");
-    gate_all!(crate_visibility_modifier, "`crate` visibility modifier is experimental");
-    gate_all!(const_generics, "const generics are unstable");
-    gate_all!(decl_macro, "`macro` is experimental");
-    gate_all!(box_patterns, "box pattern syntax is experimental");
-    gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
-    gate_all!(try_blocks, "`try` blocks are unstable");
-    gate_all!(label_break_value, "labels on blocks are unstable");
-    gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
-    // To avoid noise about type ascription in common syntax errors,
-    // only emit if it is the *only* error. (Also check it last.)
-    if sess.parse_sess.span_diagnostic.err_count() == 0 {
-        gate_all!(type_ascription, "type ascription is experimental");
-    }
-
-    visit::walk_crate(&mut visitor, krate);
-}
-
-fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
-    if !sess.opts.unstable_features.is_nightly_build() {
-        for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) {
-            struct_span_err!(
-                sess.parse_sess.span_diagnostic,
-                attr.span,
-                E0554,
-                "`#![feature]` may not be used on the {} release channel",
-                option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
-            )
-            .emit();
-        }
-    }
-}
-
-fn check_incompatible_features(sess: &Session) {
-    let features = sess.features_untracked();
-
-    let declared_features = features
-        .declared_lang_features
-        .iter()
-        .copied()
-        .map(|(name, span, _)| (name, span))
-        .chain(features.declared_lib_features.iter().copied());
-
-    for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
-        .iter()
-        .filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2))
-    {
-        if let Some((f1_name, f1_span)) = declared_features.clone().find(|(name, _)| name == f1) {
-            if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2)
-            {
-                let spans = vec![f1_span, f2_span];
-                sess.struct_span_err(
-                    spans.clone(),
-                    &format!(
-                        "features `{}` and `{}` are incompatible, using them at the same time \
-                        is not allowed",
-                        f1_name, f2_name
-                    ),
-                )
-                .help("remove one of these features")
-                .emit();
-            }
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast_passes/src/lib.rs b/vendor/rustc-ap-rustc_ast_passes/src/lib.rs
deleted file mode 100644
index c9e2d202da..0000000000
--- a/vendor/rustc-ap-rustc_ast_passes/src/lib.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
-//! parsed by `rustc_parse` and then lowered, after the passes in this crate,
-//! by `rustc_ast_lowering`.
-//!
-//! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
-
-#![feature(bindings_after_at)]
-#![feature(iter_is_partitioned)]
-#![feature(box_syntax)]
-#![feature(box_patterns)]
-#![recursion_limit = "256"]
-
-pub mod ast_validation;
-pub mod feature_gate;
-pub mod node_count;
-pub mod show_span;
diff --git a/vendor/rustc-ap-rustc_ast_passes/src/node_count.rs b/vendor/rustc-ap-rustc_ast_passes/src/node_count.rs
deleted file mode 100644
index 2971fa435c..0000000000
--- a/vendor/rustc-ap-rustc_ast_passes/src/node_count.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-// Simply gives a rough count of the number of nodes in an AST.
-
-use rustc_ast::visit::*;
-use rustc_ast::*;
-use rustc_span::symbol::Ident;
-use rustc_span::Span;
-
-pub struct NodeCounter {
-    pub count: usize,
-}
-
-impl NodeCounter {
-    pub fn new() -> NodeCounter {
-        NodeCounter { count: 0 }
-    }
-}
-
-impl<'ast> Visitor<'ast> for NodeCounter {
-    fn visit_ident(&mut self, ident: Ident) {
-        self.count += 1;
-        walk_ident(self, ident);
-    }
-    fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) {
-        self.count += 1;
-        walk_mod(self, m)
-    }
-    fn visit_foreign_item(&mut self, i: &ForeignItem) {
-        self.count += 1;
-        walk_foreign_item(self, i)
-    }
-    fn visit_item(&mut self, i: &Item) {
-        self.count += 1;
-        walk_item(self, i)
-    }
-    fn visit_local(&mut self, l: &Local) {
-        self.count += 1;
-        walk_local(self, l)
-    }
-    fn visit_block(&mut self, b: &Block) {
-        self.count += 1;
-        walk_block(self, b)
-    }
-    fn visit_stmt(&mut self, s: &Stmt) {
-        self.count += 1;
-        walk_stmt(self, s)
-    }
-    fn visit_arm(&mut self, a: &Arm) {
-        self.count += 1;
-        walk_arm(self, a)
-    }
-    fn visit_pat(&mut self, p: &Pat) {
-        self.count += 1;
-        walk_pat(self, p)
-    }
-    fn visit_expr(&mut self, ex: &Expr) {
-        self.count += 1;
-        walk_expr(self, ex)
-    }
-    fn visit_ty(&mut self, t: &Ty) {
-        self.count += 1;
-        walk_ty(self, t)
-    }
-    fn visit_generic_param(&mut self, param: &GenericParam) {
-        self.count += 1;
-        walk_generic_param(self, param)
-    }
-    fn visit_generics(&mut self, g: &Generics) {
-        self.count += 1;
-        walk_generics(self, g)
-    }
-    fn visit_fn(&mut self, fk: visit::FnKind<'_>, s: Span, _: NodeId) {
-        self.count += 1;
-        walk_fn(self, fk, s)
-    }
-    fn visit_assoc_item(&mut self, ti: &AssocItem, ctxt: AssocCtxt) {
-        self.count += 1;
-        walk_assoc_item(self, ti, ctxt);
-    }
-    fn visit_trait_ref(&mut self, t: &TraitRef) {
-        self.count += 1;
-        walk_trait_ref(self, t)
-    }
-    fn visit_param_bound(&mut self, bounds: &GenericBound) {
-        self.count += 1;
-        walk_param_bound(self, bounds)
-    }
-    fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) {
-        self.count += 1;
-        walk_poly_trait_ref(self, t, m)
-    }
-    fn visit_variant_data(&mut self, s: &VariantData) {
-        self.count += 1;
-        walk_struct_def(self, s)
-    }
-    fn visit_struct_field(&mut self, s: &StructField) {
-        self.count += 1;
-        walk_struct_field(self, s)
-    }
-    fn visit_enum_def(
-        &mut self,
-        enum_definition: &EnumDef,
-        generics: &Generics,
-        item_id: NodeId,
-        _: Span,
-    ) {
-        self.count += 1;
-        walk_enum_def(self, enum_definition, generics, item_id)
-    }
-    fn visit_variant(&mut self, v: &Variant) {
-        self.count += 1;
-        walk_variant(self, v)
-    }
-    fn visit_lifetime(&mut self, lifetime: &Lifetime) {
-        self.count += 1;
-        walk_lifetime(self, lifetime)
-    }
-    fn visit_mac_call(&mut self, mac: &MacCall) {
-        self.count += 1;
-        walk_mac(self, mac)
-    }
-    fn visit_path(&mut self, path: &Path, _id: NodeId) {
-        self.count += 1;
-        walk_path(self, path)
-    }
-    fn visit_use_tree(&mut self, use_tree: &UseTree, id: NodeId, _nested: bool) {
-        self.count += 1;
-        walk_use_tree(self, use_tree, id)
-    }
-    fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) {
-        self.count += 1;
-        walk_generic_args(self, path_span, generic_args)
-    }
-    fn visit_assoc_ty_constraint(&mut self, constraint: &AssocTyConstraint) {
-        self.count += 1;
-        walk_assoc_ty_constraint(self, constraint)
-    }
-    fn visit_attribute(&mut self, _attr: &Attribute) {
-        self.count += 1;
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast_passes/src/show_span.rs b/vendor/rustc-ap-rustc_ast_passes/src/show_span.rs
deleted file mode 100644
index 6cef26a13e..0000000000
--- a/vendor/rustc-ap-rustc_ast_passes/src/show_span.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-//! Span debugger
-//!
-//! This module shows spans for all expressions in the crate
-//! to help with compiler debugging.
-
-use std::str::FromStr;
-
-use rustc_ast as ast;
-use rustc_ast::visit;
-use rustc_ast::visit::Visitor;
-
-enum Mode {
-    Expression,
-    Pattern,
-    Type,
-}
-
-impl FromStr for Mode {
-    type Err = ();
-    fn from_str(s: &str) -> Result {
-        let mode = match s {
-            "expr" => Mode::Expression,
-            "pat" => Mode::Pattern,
-            "ty" => Mode::Type,
-            _ => return Err(()),
-        };
-        Ok(mode)
-    }
-}
-
-struct ShowSpanVisitor<'a> {
-    span_diagnostic: &'a rustc_errors::Handler,
-    mode: Mode,
-}
-
-impl<'a> Visitor<'a> for ShowSpanVisitor<'a> {
-    fn visit_expr(&mut self, e: &'a ast::Expr) {
-        if let Mode::Expression = self.mode {
-            self.span_diagnostic.span_warn(e.span, "expression");
-        }
-        visit::walk_expr(self, e);
-    }
-
-    fn visit_pat(&mut self, p: &'a ast::Pat) {
-        if let Mode::Pattern = self.mode {
-            self.span_diagnostic.span_warn(p.span, "pattern");
-        }
-        visit::walk_pat(self, p);
-    }
-
-    fn visit_ty(&mut self, t: &'a ast::Ty) {
-        if let Mode::Type = self.mode {
-            self.span_diagnostic.span_warn(t.span, "type");
-        }
-        visit::walk_ty(self, t);
-    }
-}
-
-pub fn run(span_diagnostic: &rustc_errors::Handler, mode: &str, krate: &ast::Crate) {
-    let mode = match mode.parse().ok() {
-        Some(mode) => mode,
-        None => return,
-    };
-    let mut v = ShowSpanVisitor { span_diagnostic, mode };
-    visit::walk_crate(&mut v, krate);
-}
diff --git a/vendor/rustc-ap-rustc_ast_pretty/.cargo-checksum.json b/vendor/rustc-ap-rustc_ast_pretty/.cargo-checksum.json
deleted file mode 100644
index a2d7415904..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"0d86ba12b7f8cc03e5b7f0c2ddc6bd01dff3eb2c9a74b442c7a7678e184cfe61","src/helpers.rs":"6ad86e432490db5e44da5c084bf3c45bceb874aa14a7a947122156e3dd5bb796","src/lib.rs":"90e6fcb7421aaff3d2e5ad0fbb0973394be9b5ca0a778186c94da783ad3ae225","src/pp.rs":"ca4f780bb91e6bb19ddaf17bcea73d899ba463cbe3225b314ffa3be66ae27f45","src/pprust/mod.rs":"914aed71289721e30b73a94515f64bead103c7f545cb467f97b3821cb8d6d923","src/pprust/state.rs":"dddf81e78fa8100ca26112e21a7f6b5b9c9ab53b0546a191d5c1a745f52a65a8","src/pprust/tests.rs":"e8c5d05e3544480edf7b960f1471275735847d63c2d18881a70d105db1441ba2"},"package":"99d644c69c55deb24257cb0cb5261265fe5134f6f545e9062e1c18b07e422c68"}
\ No newline at end of file
diff --git a/vendor/rustc-ap-rustc_ast_pretty/Cargo.toml b/vendor/rustc-ap-rustc_ast_pretty/Cargo.toml
deleted file mode 100644
index e719c89187..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/Cargo.toml
+++ /dev/null
@@ -1,33 +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 = "rustc-ap-rustc_ast_pretty"
-version = "705.0.0"
-authors = ["The Rust Project Developers"]
-description = "Automatically published version of the package `rustc_ast_pretty` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n            "
-license = "MIT / Apache-2.0"
-repository = "https://github.com/rust-lang/rust"
-
-[lib]
-doctest = false
-[dependencies.rustc_ast]
-version = "705.0.0"
-package = "rustc-ap-rustc_ast"
-
-[dependencies.rustc_span]
-version = "705.0.0"
-package = "rustc-ap-rustc_span"
-
-[dependencies.tracing]
-version = "0.1"
diff --git a/vendor/rustc-ap-rustc_ast_pretty/src/helpers.rs b/vendor/rustc-ap-rustc_ast_pretty/src/helpers.rs
deleted file mode 100644
index dce856df9c..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/src/helpers.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use crate::pp::Printer;
-use std::borrow::Cow;
-
-impl Printer {
-    pub fn word_space>>(&mut self, w: W) {
-        self.word(w);
-        self.space();
-    }
-
-    pub fn popen(&mut self) {
-        self.word("(");
-    }
-
-    pub fn pclose(&mut self) {
-        self.word(")");
-    }
-
-    pub fn hardbreak_if_not_bol(&mut self) {
-        if !self.is_beginning_of_line() {
-            self.hardbreak()
-        }
-    }
-
-    pub fn space_if_not_bol(&mut self) {
-        if !self.is_beginning_of_line() {
-            self.space();
-        }
-    }
-
-    pub fn nbsp(&mut self) {
-        self.word(" ")
-    }
-
-    pub fn word_nbsp>>(&mut self, w: S) {
-        self.word(w);
-        self.nbsp()
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast_pretty/src/lib.rs b/vendor/rustc-ap-rustc_ast_pretty/src/lib.rs
deleted file mode 100644
index d869baad01..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/src/lib.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(bool_to_option)]
-#![feature(crate_visibility_modifier)]
-#![feature(or_patterns)]
-#![feature(box_patterns)]
-#![recursion_limit = "256"]
-
-mod helpers;
-pub mod pp;
-pub mod pprust;
diff --git a/vendor/rustc-ap-rustc_ast_pretty/src/pp.rs b/vendor/rustc-ap-rustc_ast_pretty/src/pp.rs
deleted file mode 100644
index ea298d28e7..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/src/pp.rs
+++ /dev/null
@@ -1,629 +0,0 @@
-//! This pretty-printer is a direct reimplementation of Philip Karlton's
-//! Mesa pretty-printer, as described in the appendix to
-//! Derek C. Oppen, "Pretty Printing" (1979),
-//! Stanford Computer Science Department STAN-CS-79-770,
-//! .
-//!
-//! The algorithm's aim is to break a stream into as few lines as possible
-//! while respecting the indentation-consistency requirements of the enclosing
-//! block, and avoiding breaking at silly places on block boundaries, for
-//! example, between "x" and ")" in "x)".
-//!
-//! I am implementing this algorithm because it comes with 20 pages of
-//! documentation explaining its theory, and because it addresses the set of
-//! concerns I've seen other pretty-printers fall down on. Weirdly. Even though
-//! it's 32 years old. What can I say?
-//!
-//! Despite some redundancies and quirks in the way it's implemented in that
-//! paper, I've opted to keep the implementation here as similar as I can,
-//! changing only what was blatantly wrong, a typo, or sufficiently
-//! non-idiomatic rust that it really stuck out.
-//!
-//! In particular you'll see a certain amount of churn related to INTEGER vs.
-//! CARDINAL in the Mesa implementation. Mesa apparently interconverts the two
-//! somewhat readily? In any case, I've used usize for indices-in-buffers and
-//! ints for character-sizes-and-indentation-offsets. This respects the need
-//! for ints to "go negative" while carrying a pending-calculation balance, and
-//! helps differentiate all the numbers flying around internally (slightly).
-//!
-//! I also inverted the indentation arithmetic used in the print stack, since
-//! the Mesa implementation (somewhat randomly) stores the offset on the print
-//! stack in terms of margin-col rather than col itself. I store col.
-//!
-//! I also implemented a small change in the String token, in that I store an
-//! explicit length for the string. For most tokens this is just the length of
-//! the accompanying string. But it's necessary to permit it to differ, for
-//! encoding things that are supposed to "go on their own line" -- certain
-//! classes of comment and blank-line -- where relying on adjacent
-//! hardbreak-like Break tokens with long blankness indication doesn't actually
-//! work. To see why, consider when there is a "thing that should be on its own
-//! line" between two long blocks, say functions. If you put a hardbreak after
-//! each function (or before each) and the breaking algorithm decides to break
-//! there anyways (because the functions themselves are long) you wind up with
-//! extra blank lines. If you don't put hardbreaks you can wind up with the
-//! "thing which should be on its own line" not getting its own line in the
-//! rare case of "really small functions" or such. This re-occurs with comments
-//! and explicit blank lines. So in those cases we use a string with a payload
-//! we want isolated to a line and an explicit length that's huge, surrounded
-//! by two zero-length breaks. The algorithm will try its best to fit it on a
-//! line (which it can't) and so naturally place the content on its own line to
-//! avoid combining it with other lines and making matters even worse.
-//!
-//! # Explanation
-//!
-//! In case you do not have the paper, here is an explanation of what's going
-//! on.
-//!
-//! There is a stream of input tokens flowing through this printer.
-//!
-//! The printer buffers up to 3N tokens inside itself, where N is linewidth.
-//! Yes, linewidth is chars and tokens are multi-char, but in the worst
-//! case every token worth buffering is 1 char long, so it's ok.
-//!
-//! Tokens are String, Break, and Begin/End to delimit blocks.
-//!
-//! Begin tokens can carry an offset, saying "how far to indent when you break
-//! inside here", as well as a flag indicating "consistent" or "inconsistent"
-//! breaking. Consistent breaking means that after the first break, no attempt
-//! will be made to flow subsequent breaks together onto lines. Inconsistent
-//! is the opposite. Inconsistent breaking example would be, say:
-//!
-//! ```
-//! foo(hello, there, good, friends)
-//! ```
-//!
-//! breaking inconsistently to become
-//!
-//! ```
-//! foo(hello, there,
-//!     good, friends);
-//! ```
-//!
-//! whereas a consistent breaking would yield:
-//!
-//! ```
-//! foo(hello,
-//!     there,
-//!     good,
-//!     friends);
-//! ```
-//!
-//! That is, in the consistent-break blocks we value vertical alignment
-//! more than the ability to cram stuff onto a line. But in all cases if it
-//! can make a block a one-liner, it'll do so.
-//!
-//! Carrying on with high-level logic:
-//!
-//! The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
-//! 'right' indices denote the active portion of the ring buffer as well as
-//! describing hypothetical points-in-the-infinite-stream at most 3N tokens
-//! apart (i.e., "not wrapped to ring-buffer boundaries"). The paper will switch
-//! between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer
-//! and point-in-infinite-stream senses freely.
-//!
-//! There is a parallel ring buffer, `size`, that holds the calculated size of
-//! each token. Why calculated? Because for Begin/End pairs, the "size"
-//! includes everything between the pair. That is, the "size" of Begin is
-//! actually the sum of the sizes of everything between Begin and the paired
-//! End that follows. Since that is arbitrarily far in the future, `size` is
-//! being rewritten regularly while the printer runs; in fact most of the
-//! machinery is here to work out `size` entries on the fly (and give up when
-//! they're so obviously over-long that "infinity" is a good enough
-//! approximation for purposes of line breaking).
-//!
-//! The "input side" of the printer is managed as an abstract process called
-//! SCAN, which uses `scan_stack`, to manage calculating `size`. SCAN is, in
-//! other words, the process of calculating 'size' entries.
-//!
-//! The "output side" of the printer is managed by an abstract process called
-//! PRINT, which uses `print_stack`, `margin` and `space` to figure out what to
-//! do with each token/size pair it consumes as it goes. It's trying to consume
-//! the entire buffered window, but can't output anything until the size is >=
-//! 0 (sizes are set to negative while they're pending calculation).
-//!
-//! So SCAN takes input and buffers tokens and pending calculations, while
-//! PRINT gobbles up completed calculations and tokens from the buffer. The
-//! theory is that the two can never get more than 3N tokens apart, because
-//! once there's "obviously" too much data to fit on a line, in a size
-//! calculation, SCAN will write "infinity" to the size and let PRINT consume
-//! it.
-//!
-//! In this implementation (following the paper, again) the SCAN process is the
-//! methods called `Printer::scan_*`, and the 'PRINT' process is the
-//! method called `Printer::print`.
-
-use std::borrow::Cow;
-use std::collections::VecDeque;
-use std::fmt;
-use tracing::debug;
-
-/// How to break. Described in more detail in the module docs.
-#[derive(Clone, Copy, PartialEq)]
-pub enum Breaks {
-    Consistent,
-    Inconsistent,
-}
-
-#[derive(Clone, Copy)]
-pub struct BreakToken {
-    offset: isize,
-    blank_space: isize,
-}
-
-#[derive(Clone, Copy)]
-pub struct BeginToken {
-    offset: isize,
-    breaks: Breaks,
-}
-
-#[derive(Clone)]
-pub enum Token {
-    // In practice a string token contains either a `&'static str` or a
-    // `String`. `Cow` is overkill for this because we never modify the data,
-    // but it's more convenient than rolling our own more specialized type.
-    String(Cow<'static, str>),
-    Break(BreakToken),
-    Begin(BeginToken),
-    End,
-    Eof,
-}
-
-impl Token {
-    crate fn is_eof(&self) -> bool {
-        matches!(self, Token::Eof)
-    }
-
-    pub fn is_hardbreak_tok(&self) -> bool {
-        matches!(self, Token::Break(BreakToken { offset: 0, blank_space: SIZE_INFINITY }))
-    }
-}
-
-impl fmt::Display for Token {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Token::String(ref s) => write!(f, "STR({},{})", s, s.len()),
-            Token::Break(_) => f.write_str("BREAK"),
-            Token::Begin(_) => f.write_str("BEGIN"),
-            Token::End => f.write_str("END"),
-            Token::Eof => f.write_str("EOF"),
-        }
-    }
-}
-
-fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
-    let n = buf.len();
-    let mut i = left;
-    let mut l = lim;
-    let mut s = String::from("[");
-    while i != right && l != 0 {
-        l -= 1;
-        if i != left {
-            s.push_str(", ");
-        }
-        s.push_str(&format!("{}={}", buf[i].size, &buf[i].token));
-        i += 1;
-        i %= n;
-    }
-    s.push(']');
-    s
-}
-
-#[derive(Copy, Clone)]
-enum PrintStackBreak {
-    Fits,
-    Broken(Breaks),
-}
-
-#[derive(Copy, Clone)]
-struct PrintStackElem {
-    offset: isize,
-    pbreak: PrintStackBreak,
-}
-
-const SIZE_INFINITY: isize = 0xffff;
-
-pub fn mk_printer() -> Printer {
-    let linewidth = 78;
-    // Yes 55, it makes the ring buffers big enough to never fall behind.
-    let n: usize = 55 * linewidth;
-    debug!("mk_printer {}", linewidth);
-    Printer {
-        out: String::new(),
-        buf_max_len: n,
-        margin: linewidth as isize,
-        space: linewidth as isize,
-        left: 0,
-        right: 0,
-        // Initialize a single entry; advance_right() will extend it on demand
-        // up to `buf_max_len` elements.
-        buf: vec![BufEntry::default()],
-        left_total: 0,
-        right_total: 0,
-        scan_stack: VecDeque::new(),
-        print_stack: Vec::new(),
-        pending_indentation: 0,
-    }
-}
-
-pub struct Printer {
-    out: String,
-    buf_max_len: usize,
-    /// Width of lines we're constrained to
-    margin: isize,
-    /// Number of spaces left on line
-    space: isize,
-    /// Index of left side of input stream
-    left: usize,
-    /// Index of right side of input stream
-    right: usize,
-    /// Ring-buffer of tokens and calculated sizes
-    buf: Vec,
-    /// Running size of stream "...left"
-    left_total: isize,
-    /// Running size of stream "...right"
-    right_total: isize,
-    /// Pseudo-stack, really a ring too. Holds the
-    /// primary-ring-buffers index of the Begin that started the
-    /// current block, possibly with the most recent Break after that
-    /// Begin (if there is any) on top of it. Stuff is flushed off the
-    /// bottom as it becomes irrelevant due to the primary ring-buffer
-    /// advancing.
-    scan_stack: VecDeque,
-    /// Stack of blocks-in-progress being flushed by print
-    print_stack: Vec,
-    /// Buffered indentation to avoid writing trailing whitespace
-    pending_indentation: isize,
-}
-
-#[derive(Clone)]
-struct BufEntry {
-    token: Token,
-    size: isize,
-}
-
-impl Default for BufEntry {
-    fn default() -> Self {
-        BufEntry { token: Token::Eof, size: 0 }
-    }
-}
-
-impl Printer {
-    pub fn last_token(&self) -> Token {
-        self.buf[self.right].token.clone()
-    }
-
-    /// Be very careful with this!
-    pub fn replace_last_token(&mut self, t: Token) {
-        self.buf[self.right].token = t;
-    }
-
-    fn scan_eof(&mut self) {
-        if !self.scan_stack.is_empty() {
-            self.check_stack(0);
-            self.advance_left();
-        }
-    }
-
-    fn scan_begin(&mut self, b: BeginToken) {
-        if self.scan_stack.is_empty() {
-            self.left_total = 1;
-            self.right_total = 1;
-            self.left = 0;
-            self.right = 0;
-        } else {
-            self.advance_right();
-        }
-        debug!("pp Begin({})/buffer Vec<{},{}>", b.offset, self.left, self.right);
-        self.scan_push(BufEntry { token: Token::Begin(b), size: -self.right_total });
-    }
-
-    fn scan_end(&mut self) {
-        if self.scan_stack.is_empty() {
-            debug!("pp End/print Vec<{},{}>", self.left, self.right);
-            self.print_end();
-        } else {
-            debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
-            self.advance_right();
-            self.scan_push(BufEntry { token: Token::End, size: -1 });
-        }
-    }
-
-    fn scan_break(&mut self, b: BreakToken) {
-        if self.scan_stack.is_empty() {
-            self.left_total = 1;
-            self.right_total = 1;
-            self.left = 0;
-            self.right = 0;
-        } else {
-            self.advance_right();
-        }
-        debug!("pp Break({})/buffer Vec<{},{}>", b.offset, self.left, self.right);
-        self.check_stack(0);
-        self.scan_push(BufEntry { token: Token::Break(b), size: -self.right_total });
-        self.right_total += b.blank_space;
-    }
-
-    fn scan_string(&mut self, s: Cow<'static, str>) {
-        if self.scan_stack.is_empty() {
-            debug!("pp String('{}')/print Vec<{},{}>", s, self.left, self.right);
-            self.print_string(s);
-        } else {
-            debug!("pp String('{}')/buffer Vec<{},{}>", s, self.left, self.right);
-            self.advance_right();
-            let len = s.len() as isize;
-            self.buf[self.right] = BufEntry { token: Token::String(s), size: len };
-            self.right_total += len;
-            self.check_stream();
-        }
-    }
-
-    fn check_stream(&mut self) {
-        debug!(
-            "check_stream Vec<{}, {}> with left_total={}, right_total={}",
-            self.left, self.right, self.left_total, self.right_total
-        );
-        if self.right_total - self.left_total > self.space {
-            debug!(
-                "scan window is {}, longer than space on line ({})",
-                self.right_total - self.left_total,
-                self.space
-            );
-            if Some(&self.left) == self.scan_stack.back() {
-                debug!("setting {} to infinity and popping", self.left);
-                let scanned = self.scan_pop_bottom();
-                self.buf[scanned].size = SIZE_INFINITY;
-            }
-            self.advance_left();
-            if self.left != self.right {
-                self.check_stream();
-            }
-        }
-    }
-
-    fn scan_push(&mut self, entry: BufEntry) {
-        debug!("scan_push {}", self.right);
-        self.buf[self.right] = entry;
-        self.scan_stack.push_front(self.right);
-    }
-
-    fn scan_pop(&mut self) -> usize {
-        self.scan_stack.pop_front().unwrap()
-    }
-
-    fn scan_top(&self) -> usize {
-        *self.scan_stack.front().unwrap()
-    }
-
-    fn scan_pop_bottom(&mut self) -> usize {
-        self.scan_stack.pop_back().unwrap()
-    }
-
-    fn advance_right(&mut self) {
-        self.right += 1;
-        self.right %= self.buf_max_len;
-        // Extend the buf if necessary.
-        if self.right == self.buf.len() {
-            self.buf.push(BufEntry::default());
-        }
-        assert_ne!(self.right, self.left);
-    }
-
-    fn advance_left(&mut self) {
-        debug!(
-            "advance_left Vec<{},{}>, sizeof({})={}",
-            self.left, self.right, self.left, self.buf[self.left].size
-        );
-
-        let mut left_size = self.buf[self.left].size;
-
-        while left_size >= 0 {
-            let left = self.buf[self.left].token.clone();
-
-            let len = match left {
-                Token::Break(b) => b.blank_space,
-                Token::String(ref s) => {
-                    let len = s.len() as isize;
-                    assert_eq!(len, left_size);
-                    len
-                }
-                _ => 0,
-            };
-
-            self.print(left, left_size);
-
-            self.left_total += len;
-
-            if self.left == self.right {
-                break;
-            }
-
-            self.left += 1;
-            self.left %= self.buf_max_len;
-
-            left_size = self.buf[self.left].size;
-        }
-    }
-
-    fn check_stack(&mut self, k: usize) {
-        if !self.scan_stack.is_empty() {
-            let x = self.scan_top();
-            match self.buf[x].token {
-                Token::Begin(_) => {
-                    if k > 0 {
-                        self.scan_pop();
-                        self.buf[x].size += self.right_total;
-                        self.check_stack(k - 1);
-                    }
-                }
-                Token::End => {
-                    // paper says + not =, but that makes no sense.
-                    self.scan_pop();
-                    self.buf[x].size = 1;
-                    self.check_stack(k + 1);
-                }
-                _ => {
-                    self.scan_pop();
-                    self.buf[x].size += self.right_total;
-                    if k > 0 {
-                        self.check_stack(k);
-                    }
-                }
-            }
-        }
-    }
-
-    fn print_newline(&mut self, amount: isize) {
-        debug!("NEWLINE {}", amount);
-        self.out.push('\n');
-        self.pending_indentation = 0;
-        self.indent(amount);
-    }
-
-    fn indent(&mut self, amount: isize) {
-        debug!("INDENT {}", amount);
-        self.pending_indentation += amount;
-    }
-
-    fn get_top(&self) -> PrintStackElem {
-        *self.print_stack.last().unwrap_or({
-            &PrintStackElem { offset: 0, pbreak: PrintStackBreak::Broken(Breaks::Inconsistent) }
-        })
-    }
-
-    fn print_begin(&mut self, b: BeginToken, l: isize) {
-        if l > self.space {
-            let col = self.margin - self.space + b.offset;
-            debug!("print Begin -> push broken block at col {}", col);
-            self.print_stack
-                .push(PrintStackElem { offset: col, pbreak: PrintStackBreak::Broken(b.breaks) });
-        } else {
-            debug!("print Begin -> push fitting block");
-            self.print_stack.push(PrintStackElem { offset: 0, pbreak: PrintStackBreak::Fits });
-        }
-    }
-
-    fn print_end(&mut self) {
-        debug!("print End -> pop End");
-        self.print_stack.pop().unwrap();
-    }
-
-    fn print_break(&mut self, b: BreakToken, l: isize) {
-        let top = self.get_top();
-        match top.pbreak {
-            PrintStackBreak::Fits => {
-                debug!("print Break({}) in fitting block", b.blank_space);
-                self.space -= b.blank_space;
-                self.indent(b.blank_space);
-            }
-            PrintStackBreak::Broken(Breaks::Consistent) => {
-                debug!("print Break({}+{}) in consistent block", top.offset, b.offset);
-                self.print_newline(top.offset + b.offset);
-                self.space = self.margin - (top.offset + b.offset);
-            }
-            PrintStackBreak::Broken(Breaks::Inconsistent) => {
-                if l > self.space {
-                    debug!("print Break({}+{}) w/ newline in inconsistent", top.offset, b.offset);
-                    self.print_newline(top.offset + b.offset);
-                    self.space = self.margin - (top.offset + b.offset);
-                } else {
-                    debug!("print Break({}) w/o newline in inconsistent", b.blank_space);
-                    self.indent(b.blank_space);
-                    self.space -= b.blank_space;
-                }
-            }
-        }
-    }
-
-    fn print_string(&mut self, s: Cow<'static, str>) {
-        let len = s.len() as isize;
-        debug!("print String({})", s);
-        // assert!(len <= space);
-        self.space -= len;
-
-        // Write the pending indent. A more concise way of doing this would be:
-        //
-        //   write!(self.out, "{: >n$}", "", n = self.pending_indentation as usize)?;
-        //
-        // But that is significantly slower. This code is sufficiently hot, and indents can get
-        // sufficiently large, that the difference is significant on some workloads.
-        self.out.reserve(self.pending_indentation as usize);
-        self.out.extend(std::iter::repeat(' ').take(self.pending_indentation as usize));
-        self.pending_indentation = 0;
-        self.out.push_str(&s);
-    }
-
-    fn print(&mut self, token: Token, l: isize) {
-        debug!("print {} {} (remaining line space={})", token, l, self.space);
-        debug!("{}", buf_str(&self.buf, self.left, self.right, 6));
-        match token {
-            Token::Begin(b) => self.print_begin(b, l),
-            Token::End => self.print_end(),
-            Token::Break(b) => self.print_break(b, l),
-            Token::String(s) => {
-                let len = s.len() as isize;
-                assert_eq!(len, l);
-                self.print_string(s);
-            }
-            Token::Eof => panic!(), // Eof should never get here.
-        }
-    }
-
-    // Convenience functions to talk to the printer.
-
-    /// "raw box"
-    pub fn rbox(&mut self, indent: usize, b: Breaks) {
-        self.scan_begin(BeginToken { offset: indent as isize, breaks: b })
-    }
-
-    /// Inconsistent breaking box
-    pub fn ibox(&mut self, indent: usize) {
-        self.rbox(indent, Breaks::Inconsistent)
-    }
-
-    /// Consistent breaking box
-    pub fn cbox(&mut self, indent: usize) {
-        self.rbox(indent, Breaks::Consistent)
-    }
-
-    pub fn break_offset(&mut self, n: usize, off: isize) {
-        self.scan_break(BreakToken { offset: off, blank_space: n as isize })
-    }
-
-    pub fn end(&mut self) {
-        self.scan_end()
-    }
-
-    pub fn eof(mut self) -> String {
-        self.scan_eof();
-        self.out
-    }
-
-    pub fn word>>(&mut self, wrd: S) {
-        let s = wrd.into();
-        self.scan_string(s)
-    }
-
-    fn spaces(&mut self, n: usize) {
-        self.break_offset(n, 0)
-    }
-
-    crate fn zerobreak(&mut self) {
-        self.spaces(0)
-    }
-
-    pub fn space(&mut self) {
-        self.spaces(1)
-    }
-
-    pub fn hardbreak(&mut self) {
-        self.spaces(SIZE_INFINITY as usize)
-    }
-
-    pub fn is_beginning_of_line(&self) -> bool {
-        self.last_token().is_eof() || self.last_token().is_hardbreak_tok()
-    }
-
-    pub fn hardbreak_tok_offset(off: isize) -> Token {
-        Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY })
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast_pretty/src/pprust/mod.rs b/vendor/rustc-ap-rustc_ast_pretty/src/pprust/mod.rs
deleted file mode 100644
index b88699f6ee..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/src/pprust/mod.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-#[cfg(test)]
-mod tests;
-
-pub mod state;
-pub use state::{print_crate, AnnNode, Comments, PpAnn, PrintState, State};
-
-use rustc_ast as ast;
-use rustc_ast::token::{Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
-
-pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
-    State::new().nonterminal_to_string(nt)
-}
-
-/// Print the token kind precisely, without converting `$crate` into its respective crate name.
-pub fn token_kind_to_string(tok: &TokenKind) -> String {
-    State::new().token_kind_to_string(tok)
-}
-
-/// Print the token precisely, without converting `$crate` into its respective crate name.
-pub fn token_to_string(token: &Token) -> String {
-    State::new().token_to_string(token)
-}
-
-pub fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
-    State::new().token_to_string_ext(token, convert_dollar_crate)
-}
-
-pub fn ty_to_string(ty: &ast::Ty) -> String {
-    State::new().ty_to_string(ty)
-}
-
-pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
-    State::new().bounds_to_string(bounds)
-}
-
-pub fn pat_to_string(pat: &ast::Pat) -> String {
-    State::new().pat_to_string(pat)
-}
-
-pub fn expr_to_string(e: &ast::Expr) -> String {
-    State::new().expr_to_string(e)
-}
-
-pub fn tt_to_string(tt: &TokenTree) -> String {
-    State::new().tt_to_string(tt)
-}
-
-pub fn tts_to_string(tokens: &TokenStream) -> String {
-    State::new().tts_to_string(tokens)
-}
-
-pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
-    State::new().stmt_to_string(stmt)
-}
-
-pub fn item_to_string(i: &ast::Item) -> String {
-    State::new().item_to_string(i)
-}
-
-pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
-    State::new().generic_params_to_string(generic_params)
-}
-
-pub fn path_to_string(p: &ast::Path) -> String {
-    State::new().path_to_string(p)
-}
-
-pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
-    State::new().path_segment_to_string(p)
-}
-
-pub fn vis_to_string(v: &ast::Visibility) -> String {
-    State::new().vis_to_string(v)
-}
-
-pub fn block_to_string(blk: &ast::Block) -> String {
-    State::new().block_to_string(blk)
-}
-
-pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String {
-    State::new().meta_list_item_to_string(li)
-}
-
-pub fn attr_item_to_string(ai: &ast::AttrItem) -> String {
-    State::new().attr_item_to_string(ai)
-}
-
-pub fn attribute_to_string(attr: &ast::Attribute) -> String {
-    State::new().attribute_to_string(attr)
-}
-
-pub fn param_to_string(arg: &ast::Param) -> String {
-    State::new().param_to_string(arg)
-}
-
-pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
-    State::new().to_string(f)
-}
diff --git a/vendor/rustc-ap-rustc_ast_pretty/src/pprust/state.rs b/vendor/rustc-ap-rustc_ast_pretty/src/pprust/state.rs
deleted file mode 100644
index 7f4775bf41..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/src/pprust/state.rs
+++ /dev/null
@@ -1,2893 +0,0 @@
-use crate::pp::Breaks::{Consistent, Inconsistent};
-use crate::pp::{self, Breaks};
-
-use rustc_ast::attr;
-use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, CommentKind, DelimToken, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
-use rustc_ast::util::classify;
-use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
-use rustc_ast::util::parser::{self, AssocOp, Fixity};
-use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
-use rustc_ast::{GenericArg, MacArgs};
-use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
-use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
-use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_span::edition::Edition;
-use rustc_span::source_map::{SourceMap, Spanned};
-use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
-use rustc_span::{BytePos, FileName, Span};
-
-use std::borrow::Cow;
-
-pub enum MacHeader<'a> {
-    Path(&'a ast::Path),
-    Keyword(&'static str),
-}
-
-pub enum AnnNode<'a> {
-    Ident(&'a Ident),
-    Name(&'a Symbol),
-    Block(&'a ast::Block),
-    Item(&'a ast::Item),
-    SubItem(ast::NodeId),
-    Expr(&'a ast::Expr),
-    Pat(&'a ast::Pat),
-    Crate(&'a ast::Crate),
-}
-
-pub trait PpAnn {
-    fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
-    fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
-}
-
-#[derive(Copy, Clone)]
-pub struct NoAnn;
-
-impl PpAnn for NoAnn {}
-
-pub struct Comments<'a> {
-    sm: &'a SourceMap,
-    comments: Vec,
-    current: usize,
-}
-
-impl<'a> Comments<'a> {
-    pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> {
-        let comments = gather_comments(sm, filename, input);
-        Comments { sm, comments, current: 0 }
-    }
-
-    pub fn next(&self) -> Option {
-        self.comments.get(self.current).cloned()
-    }
-
-    pub fn trailing_comment(
-        &self,
-        span: rustc_span::Span,
-        next_pos: Option,
-    ) -> Option {
-        if let Some(cmnt) = self.next() {
-            if cmnt.style != CommentStyle::Trailing {
-                return None;
-            }
-            let span_line = self.sm.lookup_char_pos(span.hi());
-            let comment_line = self.sm.lookup_char_pos(cmnt.pos);
-            let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
-            if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
-                return Some(cmnt);
-            }
-        }
-
-        None
-    }
-}
-
-pub struct State<'a> {
-    pub s: pp::Printer,
-    comments: Option>,
-    ann: &'a (dyn PpAnn + 'a),
-    is_expanded: bool,
-}
-
-crate const INDENT_UNIT: usize = 4;
-
-/// Requires you to pass an input filename and reader so that
-/// it can scan the input text for comments to copy forward.
-pub fn print_crate<'a>(
-    sm: &'a SourceMap,
-    krate: &ast::Crate,
-    filename: FileName,
-    input: String,
-    ann: &'a dyn PpAnn,
-    is_expanded: bool,
-    edition: Edition,
-) -> String {
-    let mut s = State {
-        s: pp::mk_printer(),
-        comments: Some(Comments::new(sm, filename, input)),
-        ann,
-        is_expanded,
-    };
-
-    if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
-        // We need to print `#![no_std]` (and its feature gate) so that
-        // compiling pretty-printed source won't inject libstd again.
-        // However, we don't want these attributes in the AST because
-        // of the feature gate, so we fake them up here.
-
-        // `#![feature(prelude_import)]`
-        let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
-        let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
-        let fake_attr = attr::mk_attr_inner(list);
-        s.print_attribute(&fake_attr);
-
-        // Currently, in Rust 2018 we don't have `extern crate std;` at the crate
-        // root, so this is not needed, and actually breaks things.
-        if edition == Edition::Edition2015 {
-            // `#![no_std]`
-            let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
-            let fake_attr = attr::mk_attr_inner(no_std_meta);
-            s.print_attribute(&fake_attr);
-        }
-    }
-
-    s.print_mod(&krate.module, &krate.attrs);
-    s.print_remaining_comments();
-    s.ann.post(&mut s, AnnNode::Crate(krate));
-    s.s.eof()
-}
-
-// 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 let token::DocComment(comment_kind, ..) = token.kind {
-            return comment_kind != CommentKind::Line;
-        }
-    }
-    match tt {
-        TokenTree::Token(token) => token.kind != token::Comma,
-        TokenTree::Delimited(_, DelimToken::Paren, _) => {
-            !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }))
-        }
-        TokenTree::Delimited(_, DelimToken::Bracket, _) => {
-            !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }))
-        }
-        TokenTree::Delimited(..) => true,
-    }
-}
-
-fn binop_to_string(op: BinOpToken) -> &'static str {
-    match op {
-        token::Plus => "+",
-        token::Minus => "-",
-        token::Star => "*",
-        token::Slash => "/",
-        token::Percent => "%",
-        token::Caret => "^",
-        token::And => "&",
-        token::Or => "|",
-        token::Shl => "<<",
-        token::Shr => ">>",
-    }
-}
-
-fn doc_comment_to_string(
-    comment_kind: CommentKind,
-    attr_style: ast::AttrStyle,
-    data: Symbol,
-) -> String {
-    match (comment_kind, attr_style) {
-        (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{}", data),
-        (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{}", data),
-        (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{}*/", data),
-        (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{}*/", data),
-    }
-}
-
-pub fn literal_to_string(lit: token::Lit) -> String {
-    let token::Lit { kind, symbol, suffix } = lit;
-    let mut out = match kind {
-        token::Byte => format!("b'{}'", symbol),
-        token::Char => format!("'{}'", symbol),
-        token::Str => format!("\"{}\"", symbol),
-        token::StrRaw(n) => {
-            format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
-        }
-        token::ByteStr => format!("b\"{}\"", symbol),
-        token::ByteStrRaw(n) => {
-            format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
-        }
-        token::Integer | token::Float | token::Bool | token::Err => symbol.to_string(),
-    };
-
-    if let Some(suffix) = suffix {
-        out.push_str(&suffix.as_str())
-    }
-
-    out
-}
-
-fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
-    format!("{}{}", State::new().to_string(|s| s.print_visibility(vis)), s)
-}
-
-impl std::ops::Deref for State<'_> {
-    type Target = pp::Printer;
-    fn deref(&self) -> &Self::Target {
-        &self.s
-    }
-}
-
-impl std::ops::DerefMut for State<'_> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.s
-    }
-}
-
-pub trait PrintState<'a>: std::ops::Deref + std::ops::DerefMut {
-    fn comments(&mut self) -> &mut Option>;
-    fn print_ident(&mut self, ident: Ident);
-    fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
-
-    fn strsep(
-        &mut self,
-        sep: &'static str,
-        space_before: bool,
-        b: Breaks,
-        elts: &[T],
-        mut op: F,
-    ) where
-        F: FnMut(&mut Self, &T),
-    {
-        self.rbox(0, b);
-        if let Some((first, rest)) = elts.split_first() {
-            op(self, first);
-            for elt in rest {
-                if space_before {
-                    self.space();
-                }
-                self.word_space(sep);
-                op(self, elt);
-            }
-        }
-        self.end();
-    }
-
-    fn commasep(&mut self, b: Breaks, elts: &[T], op: F)
-    where
-        F: FnMut(&mut Self, &T),
-    {
-        self.strsep(",", false, b, elts, op)
-    }
-
-    fn maybe_print_comment(&mut self, pos: BytePos) {
-        while let Some(ref cmnt) = self.next_comment() {
-            if cmnt.pos < pos {
-                self.print_comment(cmnt);
-            } else {
-                break;
-            }
-        }
-    }
-
-    fn print_comment(&mut self, cmnt: &Comment) {
-        match cmnt.style {
-            CommentStyle::Mixed => {
-                if !self.is_beginning_of_line() {
-                    self.zerobreak();
-                }
-                if let Some((last, lines)) = cmnt.lines.split_last() {
-                    self.ibox(0);
-
-                    for line in lines {
-                        self.word(line.clone());
-                        self.hardbreak()
-                    }
-
-                    self.word(last.clone());
-                    self.space();
-
-                    self.end();
-                }
-                self.zerobreak()
-            }
-            CommentStyle::Isolated => {
-                self.hardbreak_if_not_bol();
-                for line in &cmnt.lines {
-                    // Don't print empty lines because they will end up as trailing
-                    // whitespace.
-                    if !line.is_empty() {
-                        self.word(line.clone());
-                    }
-                    self.hardbreak();
-                }
-            }
-            CommentStyle::Trailing => {
-                if !self.is_beginning_of_line() {
-                    self.word(" ");
-                }
-                if cmnt.lines.len() == 1 {
-                    self.word(cmnt.lines[0].clone());
-                    self.hardbreak()
-                } else {
-                    self.ibox(0);
-                    for line in &cmnt.lines {
-                        if !line.is_empty() {
-                            self.word(line.clone());
-                        }
-                        self.hardbreak();
-                    }
-                    self.end();
-                }
-            }
-            CommentStyle::BlankLine => {
-                // We need to do at least one, possibly two hardbreaks.
-                let twice = match self.last_token() {
-                    pp::Token::String(s) => ";" == s,
-                    pp::Token::Begin(_) => true,
-                    pp::Token::End => true,
-                    _ => false,
-                };
-                if twice {
-                    self.hardbreak();
-                }
-                self.hardbreak();
-            }
-        }
-        if let Some(cmnts) = self.comments() {
-            cmnts.current += 1;
-        }
-    }
-
-    fn next_comment(&mut self) -> Option {
-        self.comments().as_mut().and_then(|c| c.next())
-    }
-
-    fn print_literal(&mut self, lit: &ast::Lit) {
-        self.maybe_print_comment(lit.span.lo());
-        self.word(lit.token.to_string())
-    }
-
-    fn print_string(&mut self, st: &str, style: ast::StrStyle) {
-        let st = match style {
-            ast::StrStyle::Cooked => (format!("\"{}\"", st.escape_debug())),
-            ast::StrStyle::Raw(n) => {
-                format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = st)
-            }
-        };
-        self.word(st)
-    }
-
-    fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) {
-        self.print_string(&sym.as_str(), style);
-    }
-
-    fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) {
-        self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
-    }
-
-    fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) {
-        self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
-    }
-
-    fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) {
-        self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
-    }
-
-    fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) {
-        self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
-    }
-
-    fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) {
-        self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
-    }
-
-    fn print_either_attributes(
-        &mut self,
-        attrs: &[ast::Attribute],
-        kind: ast::AttrStyle,
-        is_inline: bool,
-        trailing_hardbreak: bool,
-    ) {
-        let mut count = 0;
-        for attr in attrs {
-            if attr.style == kind {
-                self.print_attribute_inline(attr, is_inline);
-                if is_inline {
-                    self.nbsp();
-                }
-                count += 1;
-            }
-        }
-        if count > 0 && trailing_hardbreak && !is_inline {
-            self.hardbreak_if_not_bol();
-        }
-    }
-
-    fn print_attribute(&mut self, attr: &ast::Attribute) {
-        self.print_attribute_inline(attr, false)
-    }
-
-    fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) {
-        if !is_inline {
-            self.hardbreak_if_not_bol();
-        }
-        self.maybe_print_comment(attr.span.lo());
-        match attr.kind {
-            ast::AttrKind::Normal(ref item, _) => {
-                match attr.style {
-                    ast::AttrStyle::Inner => self.word("#!["),
-                    ast::AttrStyle::Outer => self.word("#["),
-                }
-                self.print_attr_item(&item, attr.span);
-                self.word("]");
-            }
-            ast::AttrKind::DocComment(comment_kind, data) => {
-                self.word(doc_comment_to_string(comment_kind, attr.style, data));
-                self.hardbreak()
-            }
-        }
-    }
-
-    fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) {
-        self.ibox(0);
-        match &item.args {
-            MacArgs::Delimited(_, delim, tokens) => self.print_mac_common(
-                Some(MacHeader::Path(&item.path)),
-                false,
-                None,
-                delim.to_token(),
-                tokens,
-                true,
-                span,
-            ),
-            MacArgs::Empty | MacArgs::Eq(..) => {
-                self.print_path(&item.path, false, 0);
-                if let MacArgs::Eq(_, token) = &item.args {
-                    self.space();
-                    self.word_space("=");
-                    let token_str = self.token_to_string_ext(token, true);
-                    self.word(token_str);
-                }
-            }
-        }
-        self.end();
-    }
-
-    fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
-        match item {
-            ast::NestedMetaItem::MetaItem(ref mi) => self.print_meta_item(mi),
-            ast::NestedMetaItem::Literal(ref lit) => self.print_literal(lit),
-        }
-    }
-
-    fn print_meta_item(&mut self, item: &ast::MetaItem) {
-        self.ibox(INDENT_UNIT);
-        match item.kind {
-            ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
-            ast::MetaItemKind::NameValue(ref value) => {
-                self.print_path(&item.path, false, 0);
-                self.space();
-                self.word_space("=");
-                self.print_literal(value);
-            }
-            ast::MetaItemKind::List(ref items) => {
-                self.print_path(&item.path, false, 0);
-                self.popen();
-                self.commasep(Consistent, &items[..], |s, i| s.print_meta_list_item(i));
-                self.pclose();
-            }
-        }
-        self.end();
-    }
-
-    /// This doesn't deserve to be called "pretty" printing, but it should be
-    /// meaning-preserving. A quick hack that might help would be to look at the
-    /// spans embedded in the TTs to decide where to put spaces and newlines.
-    /// But it'd be better to parse these according to the grammar of the
-    /// appropriate macro, transcribe back into the grammar we just parsed from,
-    /// and then pretty-print the resulting AST nodes (so, e.g., we print
-    /// expression arguments as expressions). It can be done! I think.
-    fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) {
-        match tt {
-            TokenTree::Token(token) => {
-                let token_str = self.token_to_string_ext(&token, convert_dollar_crate);
-                self.word(token_str);
-                if let token::DocComment(..) = token.kind {
-                    self.hardbreak()
-                }
-            }
-            TokenTree::Delimited(dspan, delim, tts) => {
-                self.print_mac_common(
-                    None,
-                    false,
-                    None,
-                    *delim,
-                    tts,
-                    convert_dollar_crate,
-                    dspan.entire(),
-                );
-            }
-        }
-    }
-
-    fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) {
-        let mut iter = tts.trees().peekable();
-        while let Some(tt) = iter.next() {
-            self.print_tt(&tt, convert_dollar_crate);
-            if let Some(next) = iter.peek() {
-                if tt_prepend_space(next, &tt) {
-                    self.space();
-                }
-            }
-        }
-    }
-
-    fn print_mac_common(
-        &mut self,
-        header: Option>,
-        has_bang: bool,
-        ident: Option,
-        delim: DelimToken,
-        tts: &TokenStream,
-        convert_dollar_crate: bool,
-        span: Span,
-    ) {
-        if delim == DelimToken::Brace {
-            self.cbox(INDENT_UNIT);
-        }
-        match header {
-            Some(MacHeader::Path(path)) => self.print_path(path, false, 0),
-            Some(MacHeader::Keyword(kw)) => self.word(kw),
-            None => {}
-        }
-        if has_bang {
-            self.word("!");
-        }
-        if let Some(ident) = ident {
-            self.nbsp();
-            self.print_ident(ident);
-        }
-        match delim {
-            DelimToken::Brace => {
-                if header.is_some() || has_bang || ident.is_some() {
-                    self.nbsp();
-                }
-                self.word("{");
-                if !tts.is_empty() {
-                    self.space();
-                }
-            }
-            _ => {
-                let token_str = self.token_kind_to_string(&token::OpenDelim(delim));
-                self.word(token_str)
-            }
-        }
-        self.ibox(0);
-        self.print_tts(tts, convert_dollar_crate);
-        self.end();
-        match delim {
-            DelimToken::Brace => self.bclose(span),
-            _ => {
-                let token_str = self.token_kind_to_string(&token::CloseDelim(delim));
-                self.word(token_str)
-            }
-        }
-    }
-
-    fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, depth: usize) {
-        self.maybe_print_comment(path.span.lo());
-
-        for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() {
-            if i > 0 {
-                self.word("::")
-            }
-            self.print_path_segment(segment, colons_before_params);
-        }
-    }
-
-    fn print_path_segment(&mut self, segment: &ast::PathSegment, colons_before_params: bool) {
-        if segment.ident.name != kw::PathRoot {
-            self.print_ident(segment.ident);
-            if let Some(ref args) = segment.args {
-                self.print_generic_args(args, colons_before_params);
-            }
-        }
-    }
-
-    fn head>>(&mut self, w: S) {
-        let w = w.into();
-        // Outer-box is consistent.
-        self.cbox(INDENT_UNIT);
-        // Head-box is inconsistent.
-        self.ibox(w.len() + 1);
-        // Keyword that starts the head.
-        if !w.is_empty() {
-            self.word_nbsp(w);
-        }
-    }
-
-    fn bopen(&mut self) {
-        self.word("{");
-        self.end(); // Close the head-box.
-    }
-
-    fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) {
-        self.maybe_print_comment(span.hi());
-        self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
-        self.word("}");
-        if close_box {
-            self.end(); // Close the outer-box.
-        }
-    }
-
-    fn bclose(&mut self, span: rustc_span::Span) {
-        self.bclose_maybe_open(span, true)
-    }
-
-    fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
-        if !self.is_beginning_of_line() {
-            self.break_offset(n, off)
-        } else if off != 0 && self.last_token().is_hardbreak_tok() {
-            // We do something pretty sketchy here: tuck the nonzero
-            // offset-adjustment we were going to deposit along with the
-            // break into the previous hardbreak.
-            self.replace_last_token(pp::Printer::hardbreak_tok_offset(off));
-        }
-    }
-
-    fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
-        match *nt {
-            token::NtExpr(ref e) => self.expr_to_string(e),
-            token::NtMeta(ref e) => self.attr_item_to_string(e),
-            token::NtTy(ref e) => self.ty_to_string(e),
-            token::NtPath(ref e) => self.path_to_string(e),
-            token::NtItem(ref e) => self.item_to_string(e),
-            token::NtBlock(ref e) => self.block_to_string(e),
-            token::NtStmt(ref e) => self.stmt_to_string(e),
-            token::NtPat(ref e) => self.pat_to_string(e),
-            token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
-            token::NtLifetime(e) => e.to_string(),
-            token::NtLiteral(ref e) => self.expr_to_string(e),
-            token::NtTT(ref tree) => self.tt_to_string(tree),
-            token::NtVis(ref e) => self.vis_to_string(e),
-        }
-    }
-
-    /// Print the token kind precisely, without converting `$crate` into its respective crate name.
-    fn token_kind_to_string(&self, tok: &TokenKind) -> String {
-        self.token_kind_to_string_ext(tok, None)
-    }
-
-    fn token_kind_to_string_ext(
-        &self,
-        tok: &TokenKind,
-        convert_dollar_crate: Option,
-    ) -> String {
-        match *tok {
-            token::Eq => "=".to_string(),
-            token::Lt => "<".to_string(),
-            token::Le => "<=".to_string(),
-            token::EqEq => "==".to_string(),
-            token::Ne => "!=".to_string(),
-            token::Ge => ">=".to_string(),
-            token::Gt => ">".to_string(),
-            token::Not => "!".to_string(),
-            token::Tilde => "~".to_string(),
-            token::OrOr => "||".to_string(),
-            token::AndAnd => "&&".to_string(),
-            token::BinOp(op) => binop_to_string(op).to_string(),
-            token::BinOpEq(op) => format!("{}=", binop_to_string(op)),
-
-            /* Structural symbols */
-            token::At => "@".to_string(),
-            token::Dot => ".".to_string(),
-            token::DotDot => "..".to_string(),
-            token::DotDotDot => "...".to_string(),
-            token::DotDotEq => "..=".to_string(),
-            token::Comma => ",".to_string(),
-            token::Semi => ";".to_string(),
-            token::Colon => ":".to_string(),
-            token::ModSep => "::".to_string(),
-            token::RArrow => "->".to_string(),
-            token::LArrow => "<-".to_string(),
-            token::FatArrow => "=>".to_string(),
-            token::OpenDelim(token::Paren) => "(".to_string(),
-            token::CloseDelim(token::Paren) => ")".to_string(),
-            token::OpenDelim(token::Bracket) => "[".to_string(),
-            token::CloseDelim(token::Bracket) => "]".to_string(),
-            token::OpenDelim(token::Brace) => "{".to_string(),
-            token::CloseDelim(token::Brace) => "}".to_string(),
-            token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) => "".to_string(),
-            token::Pound => "#".to_string(),
-            token::Dollar => "$".to_string(),
-            token::Question => "?".to_string(),
-            token::SingleQuote => "'".to_string(),
-
-            /* Literals */
-            token::Literal(lit) => literal_to_string(lit),
-
-            /* Name components */
-            token::Ident(s, is_raw) => {
-                IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string()
-            }
-            token::Lifetime(s) => s.to_string(),
-
-            /* Other */
-            token::DocComment(comment_kind, attr_style, data) => {
-                doc_comment_to_string(comment_kind, attr_style, data)
-            }
-            token::Eof => "".to_string(),
-
-            token::Interpolated(ref nt) => self.nonterminal_to_string(nt),
-        }
-    }
-
-    /// Print the token precisely, without converting `$crate` into its respective crate name.
-    fn token_to_string(&self, token: &Token) -> String {
-        self.token_to_string_ext(token, false)
-    }
-
-    fn token_to_string_ext(&self, token: &Token, convert_dollar_crate: bool) -> String {
-        let convert_dollar_crate = convert_dollar_crate.then_some(token.span);
-        self.token_kind_to_string_ext(&token.kind, convert_dollar_crate)
-    }
-
-    fn ty_to_string(&self, ty: &ast::Ty) -> String {
-        self.to_string(|s| s.print_type(ty))
-    }
-
-    fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
-        self.to_string(|s| s.print_type_bounds("", bounds))
-    }
-
-    fn pat_to_string(&self, pat: &ast::Pat) -> String {
-        self.to_string(|s| s.print_pat(pat))
-    }
-
-    fn expr_to_string(&self, e: &ast::Expr) -> String {
-        self.to_string(|s| s.print_expr(e))
-    }
-
-    fn tt_to_string(&self, tt: &TokenTree) -> String {
-        self.to_string(|s| s.print_tt(tt, false))
-    }
-
-    fn tts_to_string(&self, tokens: &TokenStream) -> String {
-        self.to_string(|s| s.print_tts(tokens, false))
-    }
-
-    fn stmt_to_string(&self, stmt: &ast::Stmt) -> String {
-        self.to_string(|s| s.print_stmt(stmt))
-    }
-
-    fn item_to_string(&self, i: &ast::Item) -> String {
-        self.to_string(|s| s.print_item(i))
-    }
-
-    fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String {
-        self.to_string(|s| s.print_generic_params(generic_params))
-    }
-
-    fn path_to_string(&self, p: &ast::Path) -> String {
-        self.to_string(|s| s.print_path(p, false, 0))
-    }
-
-    fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
-        self.to_string(|s| s.print_path_segment(p, false))
-    }
-
-    fn vis_to_string(&self, v: &ast::Visibility) -> String {
-        self.to_string(|s| s.print_visibility(v))
-    }
-
-    fn block_to_string(&self, blk: &ast::Block) -> String {
-        self.to_string(|s| {
-            // Containing cbox, will be closed by `print_block` at `}`.
-            s.cbox(INDENT_UNIT);
-            // Head-ibox, will be closed by `print_block` after `{`.
-            s.ibox(0);
-            s.print_block(blk)
-        })
-    }
-
-    fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String {
-        self.to_string(|s| s.print_meta_list_item(li))
-    }
-
-    fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String {
-        self.to_string(|s| s.print_attr_item(ai, ai.path.span))
-    }
-
-    fn attribute_to_string(&self, attr: &ast::Attribute) -> String {
-        self.to_string(|s| s.print_attribute(attr))
-    }
-
-    fn param_to_string(&self, arg: &ast::Param) -> String {
-        self.to_string(|s| s.print_param(arg, false))
-    }
-
-    fn to_string(&self, f: impl FnOnce(&mut State<'_>)) -> String {
-        let mut printer = State::new();
-        f(&mut printer);
-        printer.s.eof()
-    }
-}
-
-impl<'a> PrintState<'a> for State<'a> {
-    fn comments(&mut self) -> &mut Option> {
-        &mut self.comments
-    }
-
-    fn print_ident(&mut self, ident: Ident) {
-        self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
-        self.ann.post(self, AnnNode::Ident(&ident))
-    }
-
-    fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) {
-        if colons_before_params {
-            self.s.word("::")
-        }
-
-        match *args {
-            ast::GenericArgs::AngleBracketed(ref data) => {
-                self.s.word("<");
-                self.commasep(Inconsistent, &data.args, |s, arg| match arg {
-                    ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a),
-                    ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c),
-                });
-                self.s.word(">")
-            }
-
-            ast::GenericArgs::Parenthesized(ref data) => {
-                self.s.word("(");
-                self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty));
-                self.s.word(")");
-                self.print_fn_ret_ty(&data.output);
-            }
-        }
-    }
-}
-
-impl<'a> State<'a> {
-    pub fn new() -> State<'a> {
-        State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false }
-    }
-
-    // Synthesizes a comment that was not textually present in the original source
-    // file.
-    pub fn synth_comment(&mut self, text: String) {
-        self.s.word("/*");
-        self.s.space();
-        self.s.word(text);
-        self.s.space();
-        self.s.word("*/")
-    }
-
-    crate fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)
-    where
-        F: FnMut(&mut State<'_>, &T),
-        G: FnMut(&T) -> rustc_span::Span,
-    {
-        self.rbox(0, b);
-        let len = elts.len();
-        let mut i = 0;
-        for elt in elts {
-            self.maybe_print_comment(get_span(elt).hi());
-            op(self, elt);
-            i += 1;
-            if i < len {
-                self.s.word(",");
-                self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi()));
-                self.space_if_not_bol();
-            }
-        }
-        self.end();
-    }
-
-    crate fn commasep_exprs(&mut self, b: Breaks, exprs: &[P]) {
-        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
-    }
-
-    pub fn print_mod(&mut self, _mod: &ast::Mod, attrs: &[ast::Attribute]) {
-        self.print_inner_attributes(attrs);
-        for item in &_mod.items {
-            self.print_item(item);
-        }
-    }
-
-    crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) {
-        self.print_inner_attributes(attrs);
-        for item in &nmod.items {
-            self.print_foreign_item(item);
-        }
-    }
-
-    pub fn print_opt_lifetime(&mut self, lifetime: &Option) {
-        if let Some(lt) = *lifetime {
-            self.print_lifetime(lt);
-            self.nbsp();
-        }
-    }
-
-    pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) {
-        self.print_ident(constraint.ident);
-        self.s.space();
-        match &constraint.kind {
-            ast::AssocTyConstraintKind::Equality { ty } => {
-                self.word_space("=");
-                self.print_type(ty);
-            }
-            ast::AssocTyConstraintKind::Bound { bounds } => {
-                self.print_type_bounds(":", &*bounds);
-            }
-        }
-    }
-
-    pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) {
-        match generic_arg {
-            GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
-            GenericArg::Type(ty) => self.print_type(ty),
-            GenericArg::Const(ct) => self.print_expr(&ct.value),
-        }
-    }
-
-    pub fn print_type(&mut self, ty: &ast::Ty) {
-        self.maybe_print_comment(ty.span.lo());
-        self.ibox(0);
-        match ty.kind {
-            ast::TyKind::Slice(ref ty) => {
-                self.s.word("[");
-                self.print_type(ty);
-                self.s.word("]");
-            }
-            ast::TyKind::Ptr(ref mt) => {
-                self.s.word("*");
-                self.print_mt(mt, true);
-            }
-            ast::TyKind::Rptr(ref lifetime, ref mt) => {
-                self.s.word("&");
-                self.print_opt_lifetime(lifetime);
-                self.print_mt(mt, false);
-            }
-            ast::TyKind::Never => {
-                self.s.word("!");
-            }
-            ast::TyKind::Tup(ref elts) => {
-                self.popen();
-                self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(ty));
-                if elts.len() == 1 {
-                    self.s.word(",");
-                }
-                self.pclose();
-            }
-            ast::TyKind::Paren(ref typ) => {
-                self.popen();
-                self.print_type(typ);
-                self.pclose();
-            }
-            ast::TyKind::BareFn(ref f) => {
-                self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, &f.generic_params);
-            }
-            ast::TyKind::Path(None, ref path) => {
-                self.print_path(path, false, 0);
-            }
-            ast::TyKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, false),
-            ast::TyKind::TraitObject(ref bounds, syntax) => {
-                let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" };
-                self.print_type_bounds(prefix, &bounds[..]);
-            }
-            ast::TyKind::ImplTrait(_, ref bounds) => {
-                self.print_type_bounds("impl", &bounds[..]);
-            }
-            ast::TyKind::Array(ref ty, ref length) => {
-                self.s.word("[");
-                self.print_type(ty);
-                self.s.word("; ");
-                self.print_expr(&length.value);
-                self.s.word("]");
-            }
-            ast::TyKind::Typeof(ref e) => {
-                self.s.word("typeof(");
-                self.print_expr(&e.value);
-                self.s.word(")");
-            }
-            ast::TyKind::Infer => {
-                self.s.word("_");
-            }
-            ast::TyKind::Err => {
-                self.popen();
-                self.s.word("/*ERROR*/");
-                self.pclose();
-            }
-            ast::TyKind::ImplicitSelf => {
-                self.s.word("Self");
-            }
-            ast::TyKind::MacCall(ref m) => {
-                self.print_mac(m);
-            }
-            ast::TyKind::CVarArgs => {
-                self.s.word("...");
-            }
-        }
-        self.end();
-    }
-
-    crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
-        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
-        self.ann.pre(self, AnnNode::SubItem(id));
-        self.hardbreak_if_not_bol();
-        self.maybe_print_comment(span.lo());
-        self.print_outer_attributes(attrs);
-        match kind {
-            ast::ForeignItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
-                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
-            }
-            ast::ForeignItemKind::Static(ty, mutbl, body) => {
-                let def = ast::Defaultness::Final;
-                self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
-            }
-            ast::ForeignItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
-            }
-            ast::ForeignItemKind::MacCall(m) => {
-                self.print_mac(m);
-                if m.args.need_semicolon() {
-                    self.s.word(";");
-                }
-            }
-        }
-        self.ann.post(self, AnnNode::SubItem(id))
-    }
-
-    fn print_item_const(
-        &mut self,
-        ident: Ident,
-        mutbl: Option,
-        ty: &ast::Ty,
-        body: Option<&ast::Expr>,
-        vis: &ast::Visibility,
-        defaultness: ast::Defaultness,
-    ) {
-        self.head("");
-        self.print_visibility(vis);
-        self.print_defaultness(defaultness);
-        let leading = match mutbl {
-            None => "const",
-            Some(ast::Mutability::Not) => "static",
-            Some(ast::Mutability::Mut) => "static mut",
-        };
-        self.word_space(leading);
-        self.print_ident(ident);
-        self.word_space(":");
-        self.print_type(ty);
-        self.s.space();
-        self.end(); // end the head-ibox
-        if let Some(body) = body {
-            self.word_space("=");
-            self.print_expr(body);
-        }
-        self.s.word(";");
-        self.end(); // end the outer cbox
-    }
-
-    fn print_associated_type(
-        &mut self,
-        ident: Ident,
-        generics: &ast::Generics,
-        bounds: &ast::GenericBounds,
-        ty: Option<&ast::Ty>,
-        vis: &ast::Visibility,
-        defaultness: ast::Defaultness,
-    ) {
-        self.head("");
-        self.print_visibility(vis);
-        self.print_defaultness(defaultness);
-        self.word_space("type");
-        self.print_ident(ident);
-        self.print_generic_params(&generics.params);
-        self.print_type_bounds(":", bounds);
-        self.print_where_clause(&generics.where_clause);
-        if let Some(ty) = ty {
-            self.s.space();
-            self.word_space("=");
-            self.print_type(ty);
-        }
-        self.s.word(";");
-        self.end(); // end inner head-block
-        self.end(); // end outer head-block
-    }
-
-    /// Pretty-prints an item.
-    crate fn print_item(&mut self, item: &ast::Item) {
-        self.hardbreak_if_not_bol();
-        self.maybe_print_comment(item.span.lo());
-        self.print_outer_attributes(&item.attrs);
-        self.ann.pre(self, AnnNode::Item(item));
-        match item.kind {
-            ast::ItemKind::ExternCrate(orig_name) => {
-                self.head(visibility_qualified(&item.vis, "extern crate"));
-                if let Some(orig_name) = orig_name {
-                    self.print_name(orig_name);
-                    self.s.space();
-                    self.s.word("as");
-                    self.s.space();
-                }
-                self.print_ident(item.ident);
-                self.s.word(";");
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
-            }
-            ast::ItemKind::Use(ref tree) => {
-                self.head(visibility_qualified(&item.vis, "use"));
-                self.print_use_tree(tree);
-                self.s.word(";");
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
-            }
-            ast::ItemKind::Static(ref ty, mutbl, ref body) => {
-                let def = ast::Defaultness::Final;
-                self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis, def);
-            }
-            ast::ItemKind::Const(def, ref ty, ref body) => {
-                self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
-            }
-            ast::ItemKind::Fn(box ast::FnKind(def, ref sig, ref gen, ref body)) => {
-                let body = body.as_deref();
-                self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
-            }
-            ast::ItemKind::Mod(ref _mod) => {
-                self.head(self.to_string(|s| {
-                    s.print_visibility(&item.vis);
-                    s.print_unsafety(_mod.unsafety);
-                    s.word("mod");
-                }));
-                self.print_ident(item.ident);
-
-                if _mod.inline || self.is_expanded {
-                    self.nbsp();
-                    self.bopen();
-                    self.print_mod(_mod, &item.attrs);
-                    self.bclose(item.span);
-                } else {
-                    self.s.word(";");
-                    self.end(); // end inner head-block
-                    self.end(); // end outer head-block
-                }
-            }
-            ast::ItemKind::ForeignMod(ref nmod) => {
-                self.head(self.to_string(|s| {
-                    s.print_unsafety(nmod.unsafety);
-                    s.word("extern");
-                }));
-                if let Some(abi) = nmod.abi {
-                    self.print_literal(&abi.as_lit());
-                    self.nbsp();
-                }
-                self.bopen();
-                self.print_foreign_mod(nmod, &item.attrs);
-                self.bclose(item.span);
-            }
-            ast::ItemKind::GlobalAsm(ref ga) => {
-                self.head(visibility_qualified(&item.vis, "global_asm!"));
-                self.s.word(ga.asm.to_string());
-                self.end();
-            }
-            ast::ItemKind::TyAlias(box ast::TyAliasKind(def, ref generics, ref bounds, ref ty)) => {
-                let ty = ty.as_deref();
-                self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
-            }
-            ast::ItemKind::Enum(ref enum_definition, ref params) => {
-                self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
-            }
-            ast::ItemKind::Struct(ref struct_def, ref generics) => {
-                self.head(visibility_qualified(&item.vis, "struct"));
-                self.print_struct(struct_def, generics, item.ident, item.span, true);
-            }
-            ast::ItemKind::Union(ref struct_def, ref generics) => {
-                self.head(visibility_qualified(&item.vis, "union"));
-                self.print_struct(struct_def, generics, item.ident, item.span, true);
-            }
-            ast::ItemKind::Impl(box ast::ImplKind {
-                unsafety,
-                polarity,
-                defaultness,
-                constness,
-                ref generics,
-                ref of_trait,
-                ref self_ty,
-                ref items,
-            }) => {
-                self.head("");
-                self.print_visibility(&item.vis);
-                self.print_defaultness(defaultness);
-                self.print_unsafety(unsafety);
-                self.word_nbsp("impl");
-                self.print_constness(constness);
-
-                if !generics.params.is_empty() {
-                    self.print_generic_params(&generics.params);
-                    self.s.space();
-                }
-
-                if let ast::ImplPolarity::Negative(_) = polarity {
-                    self.s.word("!");
-                }
-
-                if let Some(ref t) = *of_trait {
-                    self.print_trait_ref(t);
-                    self.s.space();
-                    self.word_space("for");
-                }
-
-                self.print_type(self_ty);
-                self.print_where_clause(&generics.where_clause);
-
-                self.s.space();
-                self.bopen();
-                self.print_inner_attributes(&item.attrs);
-                for impl_item in items {
-                    self.print_assoc_item(impl_item);
-                }
-                self.bclose(item.span);
-            }
-            ast::ItemKind::Trait(box ast::TraitKind(
-                is_auto,
-                unsafety,
-                ref generics,
-                ref bounds,
-                ref trait_items,
-            )) => {
-                self.head("");
-                self.print_visibility(&item.vis);
-                self.print_unsafety(unsafety);
-                self.print_is_auto(is_auto);
-                self.word_nbsp("trait");
-                self.print_ident(item.ident);
-                self.print_generic_params(&generics.params);
-                let mut real_bounds = Vec::with_capacity(bounds.len());
-                for b in bounds.iter() {
-                    if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
-                        self.s.space();
-                        self.word_space("for ?");
-                        self.print_trait_ref(&ptr.trait_ref);
-                    } else {
-                        real_bounds.push(b.clone());
-                    }
-                }
-                self.print_type_bounds(":", &real_bounds[..]);
-                self.print_where_clause(&generics.where_clause);
-                self.s.word(" ");
-                self.bopen();
-                self.print_inner_attributes(&item.attrs);
-                for trait_item in trait_items {
-                    self.print_assoc_item(trait_item);
-                }
-                self.bclose(item.span);
-            }
-            ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
-                self.head("");
-                self.print_visibility(&item.vis);
-                self.word_nbsp("trait");
-                self.print_ident(item.ident);
-                self.print_generic_params(&generics.params);
-                let mut real_bounds = Vec::with_capacity(bounds.len());
-                // FIXME(durka) this seems to be some quite outdated syntax
-                for b in bounds.iter() {
-                    if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
-                        self.s.space();
-                        self.word_space("for ?");
-                        self.print_trait_ref(&ptr.trait_ref);
-                    } else {
-                        real_bounds.push(b.clone());
-                    }
-                }
-                self.nbsp();
-                self.print_type_bounds("=", &real_bounds[..]);
-                self.print_where_clause(&generics.where_clause);
-                self.s.word(";");
-            }
-            ast::ItemKind::MacCall(ref mac) => {
-                self.print_mac(mac);
-                if mac.args.need_semicolon() {
-                    self.s.word(";");
-                }
-            }
-            ast::ItemKind::MacroDef(ref macro_def) => {
-                let (kw, has_bang) = if macro_def.macro_rules {
-                    ("macro_rules", true)
-                } else {
-                    self.print_visibility(&item.vis);
-                    ("macro", false)
-                };
-                self.print_mac_common(
-                    Some(MacHeader::Keyword(kw)),
-                    has_bang,
-                    Some(item.ident),
-                    macro_def.body.delim(),
-                    ¯o_def.body.inner_tokens(),
-                    true,
-                    item.span,
-                );
-            }
-        }
-        self.ann.post(self, AnnNode::Item(item))
-    }
-
-    fn print_trait_ref(&mut self, t: &ast::TraitRef) {
-        self.print_path(&t.path, false, 0)
-    }
-
-    fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
-        if !generic_params.is_empty() {
-            self.s.word("for");
-            self.print_generic_params(generic_params);
-            self.nbsp();
-        }
-    }
-
-    fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
-        self.print_formal_generic_params(&t.bound_generic_params);
-        self.print_trait_ref(&t.trait_ref)
-    }
-
-    crate fn print_enum_def(
-        &mut self,
-        enum_definition: &ast::EnumDef,
-        generics: &ast::Generics,
-        ident: Ident,
-        span: rustc_span::Span,
-        visibility: &ast::Visibility,
-    ) {
-        self.head(visibility_qualified(visibility, "enum"));
-        self.print_ident(ident);
-        self.print_generic_params(&generics.params);
-        self.print_where_clause(&generics.where_clause);
-        self.s.space();
-        self.print_variants(&enum_definition.variants, span)
-    }
-
-    crate fn print_variants(&mut self, variants: &[ast::Variant], span: rustc_span::Span) {
-        self.bopen();
-        for v in variants {
-            self.space_if_not_bol();
-            self.maybe_print_comment(v.span.lo());
-            self.print_outer_attributes(&v.attrs);
-            self.ibox(INDENT_UNIT);
-            self.print_variant(v);
-            self.s.word(",");
-            self.end();
-            self.maybe_print_trailing_comment(v.span, None);
-        }
-        self.bclose(span)
-    }
-
-    crate fn print_visibility(&mut self, vis: &ast::Visibility) {
-        match vis.kind {
-            ast::VisibilityKind::Public => self.word_nbsp("pub"),
-            ast::VisibilityKind::Crate(sugar) => match sugar {
-                ast::CrateSugar::PubCrate => self.word_nbsp("pub(crate)"),
-                ast::CrateSugar::JustCrate => self.word_nbsp("crate"),
-            },
-            ast::VisibilityKind::Restricted { ref path, .. } => {
-                let path = self.to_string(|s| s.print_path(path, false, 0));
-                if path == "self" || path == "super" {
-                    self.word_nbsp(format!("pub({})", path))
-                } else {
-                    self.word_nbsp(format!("pub(in {})", path))
-                }
-            }
-            ast::VisibilityKind::Inherited => {}
-        }
-    }
-
-    crate fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
-        if let ast::Defaultness::Default(_) = defaultness {
-            self.word_nbsp("default");
-        }
-    }
-
-    crate fn print_struct(
-        &mut self,
-        struct_def: &ast::VariantData,
-        generics: &ast::Generics,
-        ident: Ident,
-        span: rustc_span::Span,
-        print_finalizer: bool,
-    ) {
-        self.print_ident(ident);
-        self.print_generic_params(&generics.params);
-        match struct_def {
-            ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
-                if let ast::VariantData::Tuple(..) = struct_def {
-                    self.popen();
-                    self.commasep(Inconsistent, struct_def.fields(), |s, field| {
-                        s.maybe_print_comment(field.span.lo());
-                        s.print_outer_attributes(&field.attrs);
-                        s.print_visibility(&field.vis);
-                        s.print_type(&field.ty)
-                    });
-                    self.pclose();
-                }
-                self.print_where_clause(&generics.where_clause);
-                if print_finalizer {
-                    self.s.word(";");
-                }
-                self.end();
-                self.end(); // Close the outer-box.
-            }
-            ast::VariantData::Struct(..) => {
-                self.print_where_clause(&generics.where_clause);
-                self.nbsp();
-                self.bopen();
-                self.hardbreak_if_not_bol();
-
-                for field in struct_def.fields() {
-                    self.hardbreak_if_not_bol();
-                    self.maybe_print_comment(field.span.lo());
-                    self.print_outer_attributes(&field.attrs);
-                    self.print_visibility(&field.vis);
-                    self.print_ident(field.ident.unwrap());
-                    self.word_nbsp(":");
-                    self.print_type(&field.ty);
-                    self.s.word(",");
-                }
-
-                self.bclose(span)
-            }
-        }
-    }
-
-    crate fn print_variant(&mut self, v: &ast::Variant) {
-        self.head("");
-        self.print_visibility(&v.vis);
-        let generics = ast::Generics::default();
-        self.print_struct(&v.data, &generics, v.ident, v.span, false);
-        if let Some(ref d) = v.disr_expr {
-            self.s.space();
-            self.word_space("=");
-            self.print_expr(&d.value)
-        }
-    }
-
-    crate fn print_assoc_item(&mut self, item: &ast::AssocItem) {
-        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
-        self.ann.pre(self, AnnNode::SubItem(id));
-        self.hardbreak_if_not_bol();
-        self.maybe_print_comment(span.lo());
-        self.print_outer_attributes(attrs);
-        match kind {
-            ast::AssocItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
-                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
-            }
-            ast::AssocItemKind::Const(def, ty, body) => {
-                self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
-            }
-            ast::AssocItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
-            }
-            ast::AssocItemKind::MacCall(m) => {
-                self.print_mac(m);
-                if m.args.need_semicolon() {
-                    self.s.word(";");
-                }
-            }
-        }
-        self.ann.post(self, AnnNode::SubItem(id))
-    }
-
-    crate fn print_stmt(&mut self, st: &ast::Stmt) {
-        self.maybe_print_comment(st.span.lo());
-        match st.kind {
-            ast::StmtKind::Local(ref loc) => {
-                self.print_outer_attributes(&loc.attrs);
-                self.space_if_not_bol();
-                self.ibox(INDENT_UNIT);
-                self.word_nbsp("let");
-
-                self.ibox(INDENT_UNIT);
-                self.print_local_decl(loc);
-                self.end();
-                if let Some(ref init) = loc.init {
-                    self.nbsp();
-                    self.word_space("=");
-                    self.print_expr(init);
-                }
-                self.s.word(";");
-                self.end();
-            }
-            ast::StmtKind::Item(ref item) => self.print_item(item),
-            ast::StmtKind::Expr(ref expr) => {
-                self.space_if_not_bol();
-                self.print_expr_outer_attr_style(expr, false);
-                if classify::expr_requires_semi_to_be_stmt(expr) {
-                    self.s.word(";");
-                }
-            }
-            ast::StmtKind::Semi(ref expr) => {
-                self.space_if_not_bol();
-                self.print_expr_outer_attr_style(expr, false);
-                self.s.word(";");
-            }
-            ast::StmtKind::Empty => {
-                self.space_if_not_bol();
-                self.s.word(";");
-            }
-            ast::StmtKind::MacCall(ref mac) => {
-                self.space_if_not_bol();
-                self.print_outer_attributes(&mac.attrs);
-                self.print_mac(&mac.mac);
-                if mac.style == ast::MacStmtStyle::Semicolon {
-                    self.s.word(";");
-                }
-            }
-        }
-        self.maybe_print_trailing_comment(st.span, None)
-    }
-
-    crate fn print_block(&mut self, blk: &ast::Block) {
-        self.print_block_with_attrs(blk, &[])
-    }
-
-    crate fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
-        self.print_block_maybe_unclosed(blk, &[], false)
-    }
-
-    crate fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) {
-        self.print_block_maybe_unclosed(blk, attrs, true)
-    }
-
-    crate fn print_block_maybe_unclosed(
-        &mut self,
-        blk: &ast::Block,
-        attrs: &[ast::Attribute],
-        close_box: bool,
-    ) {
-        match blk.rules {
-            BlockCheckMode::Unsafe(..) => self.word_space("unsafe"),
-            BlockCheckMode::Default => (),
-        }
-        self.maybe_print_comment(blk.span.lo());
-        self.ann.pre(self, AnnNode::Block(blk));
-        self.bopen();
-
-        self.print_inner_attributes(attrs);
-
-        for (i, st) in blk.stmts.iter().enumerate() {
-            match st.kind {
-                ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => {
-                    self.maybe_print_comment(st.span.lo());
-                    self.space_if_not_bol();
-                    self.print_expr_outer_attr_style(expr, false);
-                    self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
-                }
-                _ => self.print_stmt(st),
-            }
-        }
-
-        self.bclose_maybe_open(blk.span, close_box);
-        self.ann.post(self, AnnNode::Block(blk))
-    }
-
-    /// Print a `let pat = scrutinee` expression.
-    crate fn print_let(&mut self, pat: &ast::Pat, scrutinee: &ast::Expr) {
-        self.s.word("let ");
-
-        self.print_pat(pat);
-        self.s.space();
-
-        self.word_space("=");
-        self.print_expr_cond_paren(
-            scrutinee,
-            Self::cond_needs_par(scrutinee)
-                || parser::needs_par_as_let_scrutinee(scrutinee.precedence().order()),
-        )
-    }
-
-    fn print_else(&mut self, els: Option<&ast::Expr>) {
-        if let Some(_else) = els {
-            match _else.kind {
-                // Another `else if` block.
-                ast::ExprKind::If(ref i, ref then, ref e) => {
-                    self.cbox(INDENT_UNIT - 1);
-                    self.ibox(0);
-                    self.s.word(" else if ");
-                    self.print_expr_as_cond(i);
-                    self.s.space();
-                    self.print_block(then);
-                    self.print_else(e.as_deref())
-                }
-                // Final `else` block.
-                ast::ExprKind::Block(ref b, _) => {
-                    self.cbox(INDENT_UNIT - 1);
-                    self.ibox(0);
-                    self.s.word(" else ");
-                    self.print_block(b)
-                }
-                // Constraints would be great here!
-                _ => {
-                    panic!("print_if saw if with weird alternative");
-                }
-            }
-        }
-    }
-
-    crate fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) {
-        self.head("if");
-
-        self.print_expr_as_cond(test);
-        self.s.space();
-
-        self.print_block(blk);
-        self.print_else(elseopt)
-    }
-
-    crate fn print_mac(&mut self, m: &ast::MacCall) {
-        self.print_mac_common(
-            Some(MacHeader::Path(&m.path)),
-            true,
-            None,
-            m.args.delim(),
-            &m.args.inner_tokens(),
-            true,
-            m.span(),
-        );
-    }
-
-    fn print_call_post(&mut self, args: &[P]) {
-        self.popen();
-        self.commasep_exprs(Inconsistent, args);
-        self.pclose()
-    }
-
-    crate fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) {
-        self.print_expr_cond_paren(expr, expr.precedence().order() < prec)
-    }
-
-    /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
-    /// `if cond { ... }`.
-    crate fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
-        self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
-    }
-
-    /// Does `expr` need parenthesis when printed in a condition position?
-    fn cond_needs_par(expr: &ast::Expr) -> bool {
-        match expr.kind {
-            // These cases need parens due to the parse error observed in #26461: `if return {}`
-            // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
-            ast::ExprKind::Closure(..) | ast::ExprKind::Ret(..) | ast::ExprKind::Break(..) => true,
-
-            _ => parser::contains_exterior_struct_lit(expr),
-        }
-    }
-
-    /// Prints `expr` or `(expr)` when `needs_par` holds.
-    fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
-        if needs_par {
-            self.popen();
-        }
-        self.print_expr(expr);
-        if needs_par {
-            self.pclose();
-        }
-    }
-
-    fn print_expr_vec(&mut self, exprs: &[P], attrs: &[ast::Attribute]) {
-        self.ibox(INDENT_UNIT);
-        self.s.word("[");
-        self.print_inner_attributes_inline(attrs);
-        self.commasep_exprs(Inconsistent, &exprs[..]);
-        self.s.word("]");
-        self.end();
-    }
-
-    fn print_expr_anon_const(&mut self, expr: &ast::AnonConst, attrs: &[ast::Attribute]) {
-        self.ibox(INDENT_UNIT);
-        self.s.word("const");
-        self.print_inner_attributes_inline(attrs);
-        self.print_expr(&expr.value);
-        self.end();
-    }
-
-    fn print_expr_repeat(
-        &mut self,
-        element: &ast::Expr,
-        count: &ast::AnonConst,
-        attrs: &[ast::Attribute],
-    ) {
-        self.ibox(INDENT_UNIT);
-        self.s.word("[");
-        self.print_inner_attributes_inline(attrs);
-        self.print_expr(element);
-        self.word_space(";");
-        self.print_expr(&count.value);
-        self.s.word("]");
-        self.end();
-    }
-
-    fn print_expr_struct(
-        &mut self,
-        path: &ast::Path,
-        fields: &[ast::Field],
-        rest: &ast::StructRest,
-        attrs: &[ast::Attribute],
-    ) {
-        self.print_path(path, true, 0);
-        self.s.word("{");
-        self.print_inner_attributes_inline(attrs);
-        self.commasep_cmnt(
-            Consistent,
-            &fields[..],
-            |s, field| {
-                s.print_outer_attributes(&field.attrs);
-                s.ibox(INDENT_UNIT);
-                if !field.is_shorthand {
-                    s.print_ident(field.ident);
-                    s.word_space(":");
-                }
-                s.print_expr(&field.expr);
-                s.end();
-            },
-            |f| f.span,
-        );
-        match rest {
-            ast::StructRest::Base(_) | ast::StructRest::Rest(_) => {
-                self.ibox(INDENT_UNIT);
-                if !fields.is_empty() {
-                    self.s.word(",");
-                    self.s.space();
-                }
-                self.s.word("..");
-                if let ast::StructRest::Base(ref expr) = *rest {
-                    self.print_expr(expr);
-                }
-                self.end();
-            }
-            ast::StructRest::None if !fields.is_empty() => self.s.word(","),
-            _ => {}
-        }
-        self.s.word("}");
-    }
-
-    fn print_expr_tup(&mut self, exprs: &[P], attrs: &[ast::Attribute]) {
-        self.popen();
-        self.print_inner_attributes_inline(attrs);
-        self.commasep_exprs(Inconsistent, &exprs[..]);
-        if exprs.len() == 1 {
-            self.s.word(",");
-        }
-        self.pclose()
-    }
-
-    fn print_expr_call(&mut self, func: &ast::Expr, args: &[P]) {
-        let prec = match func.kind {
-            ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
-            _ => parser::PREC_POSTFIX,
-        };
-
-        self.print_expr_maybe_paren(func, prec);
-        self.print_call_post(args)
-    }
-
-    fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P]) {
-        let base_args = &args[1..];
-        self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
-        self.s.word(".");
-        self.print_ident(segment.ident);
-        if let Some(ref args) = segment.args {
-            self.print_generic_args(args, true);
-        }
-        self.print_call_post(base_args)
-    }
-
-    fn print_expr_binary(&mut self, op: ast::BinOp, lhs: &ast::Expr, rhs: &ast::Expr) {
-        let assoc_op = AssocOp::from_ast_binop(op.node);
-        let prec = assoc_op.precedence() as i8;
-        let fixity = assoc_op.fixity();
-
-        let (left_prec, right_prec) = match fixity {
-            Fixity::Left => (prec, prec + 1),
-            Fixity::Right => (prec + 1, prec),
-            Fixity::None => (prec + 1, prec + 1),
-        };
-
-        let left_prec = match (&lhs.kind, op.node) {
-            // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
-            // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
-            // of `(x as i32) < ...`. We need to convince it _not_ to do that.
-            (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt | ast::BinOpKind::Shl) => {
-                parser::PREC_FORCE_PAREN
-            }
-            // We are given `(let _ = a) OP b`.
-            //
-            // - When `OP <= LAnd` we should print `let _ = a OP b` to avoid redundant parens
-            //   as the parser will interpret this as `(let _ = a) OP b`.
-            //
-            // - Otherwise, e.g. when we have `(let a = b) < c` in AST,
-            //   parens are required since the parser would interpret `let a = b < c` as
-            //   `let a = (b < c)`. To achieve this, we force parens.
-            (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
-                parser::PREC_FORCE_PAREN
-            }
-            _ => left_prec,
-        };
-
-        self.print_expr_maybe_paren(lhs, left_prec);
-        self.s.space();
-        self.word_space(op.node.to_string());
-        self.print_expr_maybe_paren(rhs, right_prec)
-    }
-
-    fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) {
-        self.s.word(ast::UnOp::to_string(op));
-        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
-    }
-
-    fn print_expr_addr_of(
-        &mut self,
-        kind: ast::BorrowKind,
-        mutability: ast::Mutability,
-        expr: &ast::Expr,
-    ) {
-        self.s.word("&");
-        match kind {
-            ast::BorrowKind::Ref => self.print_mutability(mutability, false),
-            ast::BorrowKind::Raw => {
-                self.word_nbsp("raw");
-                self.print_mutability(mutability, true);
-            }
-        }
-        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
-    }
-
-    pub fn print_expr(&mut self, expr: &ast::Expr) {
-        self.print_expr_outer_attr_style(expr, true)
-    }
-
-    fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
-        self.maybe_print_comment(expr.span.lo());
-
-        let attrs = &expr.attrs;
-        if is_inline {
-            self.print_outer_attributes_inline(attrs);
-        } else {
-            self.print_outer_attributes(attrs);
-        }
-
-        self.ibox(INDENT_UNIT);
-        self.ann.pre(self, AnnNode::Expr(expr));
-        match expr.kind {
-            ast::ExprKind::Box(ref expr) => {
-                self.word_space("box");
-                self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
-            }
-            ast::ExprKind::Array(ref exprs) => {
-                self.print_expr_vec(&exprs[..], attrs);
-            }
-            ast::ExprKind::ConstBlock(ref anon_const) => {
-                self.print_expr_anon_const(anon_const, attrs);
-            }
-            ast::ExprKind::Repeat(ref element, ref count) => {
-                self.print_expr_repeat(element, count, attrs);
-            }
-            ast::ExprKind::Struct(ref path, ref fields, ref rest) => {
-                self.print_expr_struct(path, &fields[..], rest, attrs);
-            }
-            ast::ExprKind::Tup(ref exprs) => {
-                self.print_expr_tup(&exprs[..], attrs);
-            }
-            ast::ExprKind::Call(ref func, ref args) => {
-                self.print_expr_call(func, &args[..]);
-            }
-            ast::ExprKind::MethodCall(ref segment, ref args, _) => {
-                self.print_expr_method_call(segment, &args[..]);
-            }
-            ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
-                self.print_expr_binary(op, lhs, rhs);
-            }
-            ast::ExprKind::Unary(op, ref expr) => {
-                self.print_expr_unary(op, expr);
-            }
-            ast::ExprKind::AddrOf(k, m, ref expr) => {
-                self.print_expr_addr_of(k, m, expr);
-            }
-            ast::ExprKind::Lit(ref lit) => {
-                self.print_literal(lit);
-            }
-            ast::ExprKind::Cast(ref expr, ref ty) => {
-                let prec = AssocOp::As.precedence() as i8;
-                self.print_expr_maybe_paren(expr, prec);
-                self.s.space();
-                self.word_space("as");
-                self.print_type(ty);
-            }
-            ast::ExprKind::Type(ref expr, ref ty) => {
-                let prec = AssocOp::Colon.precedence() as i8;
-                self.print_expr_maybe_paren(expr, prec);
-                self.word_space(":");
-                self.print_type(ty);
-            }
-            ast::ExprKind::Let(ref pat, ref scrutinee) => {
-                self.print_let(pat, scrutinee);
-            }
-            ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
-                self.print_if(test, blk, elseopt.as_deref())
-            }
-            ast::ExprKind::While(ref test, ref blk, opt_label) => {
-                if let Some(label) = opt_label {
-                    self.print_ident(label.ident);
-                    self.word_space(":");
-                }
-                self.head("while");
-                self.print_expr_as_cond(test);
-                self.s.space();
-                self.print_block_with_attrs(blk, attrs);
-            }
-            ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => {
-                if let Some(label) = opt_label {
-                    self.print_ident(label.ident);
-                    self.word_space(":");
-                }
-                self.head("for");
-                self.print_pat(pat);
-                self.s.space();
-                self.word_space("in");
-                self.print_expr_as_cond(iter);
-                self.s.space();
-                self.print_block_with_attrs(blk, attrs);
-            }
-            ast::ExprKind::Loop(ref blk, opt_label) => {
-                if let Some(label) = opt_label {
-                    self.print_ident(label.ident);
-                    self.word_space(":");
-                }
-                self.head("loop");
-                self.s.space();
-                self.print_block_with_attrs(blk, attrs);
-            }
-            ast::ExprKind::Match(ref expr, ref arms) => {
-                self.cbox(INDENT_UNIT);
-                self.ibox(INDENT_UNIT);
-                self.word_nbsp("match");
-                self.print_expr_as_cond(expr);
-                self.s.space();
-                self.bopen();
-                self.print_inner_attributes_no_trailing_hardbreak(attrs);
-                for arm in arms {
-                    self.print_arm(arm);
-                }
-                self.bclose(expr.span);
-            }
-            ast::ExprKind::Closure(
-                capture_clause,
-                asyncness,
-                movability,
-                ref decl,
-                ref body,
-                _,
-            ) => {
-                self.print_movability(movability);
-                self.print_asyncness(asyncness);
-                self.print_capture_clause(capture_clause);
-
-                self.print_fn_params_and_ret(decl, true);
-                self.s.space();
-                self.print_expr(body);
-                self.end(); // need to close a box
-
-                // a box will be closed by print_expr, but we didn't want an overall
-                // wrapper so we closed the corresponding opening. so create an
-                // empty box to satisfy the close.
-                self.ibox(0);
-            }
-            ast::ExprKind::Block(ref blk, opt_label) => {
-                if let Some(label) = opt_label {
-                    self.print_ident(label.ident);
-                    self.word_space(":");
-                }
-                // containing cbox, will be closed by print-block at }
-                self.cbox(INDENT_UNIT);
-                // head-box, will be closed by print-block after {
-                self.ibox(0);
-                self.print_block_with_attrs(blk, attrs);
-            }
-            ast::ExprKind::Async(capture_clause, _, ref blk) => {
-                self.word_nbsp("async");
-                self.print_capture_clause(capture_clause);
-                self.s.space();
-                // cbox/ibox in analogy to the `ExprKind::Block` arm above
-                self.cbox(INDENT_UNIT);
-                self.ibox(0);
-                self.print_block_with_attrs(blk, attrs);
-            }
-            ast::ExprKind::Await(ref expr) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
-                self.s.word(".await");
-            }
-            ast::ExprKind::Assign(ref lhs, ref rhs, _) => {
-                let prec = AssocOp::Assign.precedence() as i8;
-                self.print_expr_maybe_paren(lhs, prec + 1);
-                self.s.space();
-                self.word_space("=");
-                self.print_expr_maybe_paren(rhs, prec);
-            }
-            ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
-                let prec = AssocOp::Assign.precedence() as i8;
-                self.print_expr_maybe_paren(lhs, prec + 1);
-                self.s.space();
-                self.s.word(op.node.to_string());
-                self.word_space("=");
-                self.print_expr_maybe_paren(rhs, prec);
-            }
-            ast::ExprKind::Field(ref expr, ident) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
-                self.s.word(".");
-                self.print_ident(ident);
-            }
-            ast::ExprKind::Index(ref expr, ref index) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
-                self.s.word("[");
-                self.print_expr(index);
-                self.s.word("]");
-            }
-            ast::ExprKind::Range(ref start, ref end, limits) => {
-                // Special case for `Range`.  `AssocOp` claims that `Range` has higher precedence
-                // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
-                // Here we use a fake precedence value so that any child with lower precedence than
-                // a "normal" binop gets parenthesized.  (`LOr` is the lowest-precedence binop.)
-                let fake_prec = AssocOp::LOr.precedence() as i8;
-                if let Some(ref e) = *start {
-                    self.print_expr_maybe_paren(e, fake_prec);
-                }
-                if limits == ast::RangeLimits::HalfOpen {
-                    self.s.word("..");
-                } else {
-                    self.s.word("..=");
-                }
-                if let Some(ref e) = *end {
-                    self.print_expr_maybe_paren(e, fake_prec);
-                }
-            }
-            ast::ExprKind::Underscore => self.s.word("_"),
-            ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0),
-            ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true),
-            ast::ExprKind::Break(opt_label, ref opt_expr) => {
-                self.s.word("break");
-                self.s.space();
-                if let Some(label) = opt_label {
-                    self.print_ident(label.ident);
-                    self.s.space();
-                }
-                if let Some(ref expr) = *opt_expr {
-                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
-                    self.s.space();
-                }
-            }
-            ast::ExprKind::Continue(opt_label) => {
-                self.s.word("continue");
-                self.s.space();
-                if let Some(label) = opt_label {
-                    self.print_ident(label.ident);
-                    self.s.space()
-                }
-            }
-            ast::ExprKind::Ret(ref result) => {
-                self.s.word("return");
-                if let Some(ref expr) = *result {
-                    self.s.word(" ");
-                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
-                }
-            }
-            ast::ExprKind::InlineAsm(ref a) => {
-                enum AsmArg<'a> {
-                    Template(String),
-                    Operand(&'a InlineAsmOperand),
-                    Options(InlineAsmOptions),
-                }
-
-                let mut args = vec![];
-                args.push(AsmArg::Template(InlineAsmTemplatePiece::to_string(&a.template)));
-                args.extend(a.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
-                if !a.options.is_empty() {
-                    args.push(AsmArg::Options(a.options));
-                }
-
-                self.word("asm!");
-                self.popen();
-                self.commasep(Consistent, &args, |s, arg| match arg {
-                    AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked),
-                    AsmArg::Operand(op) => {
-                        let print_reg_or_class = |s: &mut Self, r: &InlineAsmRegOrRegClass| match r
-                        {
-                            InlineAsmRegOrRegClass::Reg(r) => {
-                                s.print_symbol(*r, ast::StrStyle::Cooked)
-                            }
-                            InlineAsmRegOrRegClass::RegClass(r) => s.word(r.to_string()),
-                        };
-                        match op {
-                            InlineAsmOperand::In { reg, expr } => {
-                                s.word("in");
-                                s.popen();
-                                print_reg_or_class(s, reg);
-                                s.pclose();
-                                s.space();
-                                s.print_expr(expr);
-                            }
-                            InlineAsmOperand::Out { reg, late, expr } => {
-                                s.word(if *late { "lateout" } else { "out" });
-                                s.popen();
-                                print_reg_or_class(s, reg);
-                                s.pclose();
-                                s.space();
-                                match expr {
-                                    Some(expr) => s.print_expr(expr),
-                                    None => s.word("_"),
-                                }
-                            }
-                            InlineAsmOperand::InOut { reg, late, expr } => {
-                                s.word(if *late { "inlateout" } else { "inout" });
-                                s.popen();
-                                print_reg_or_class(s, reg);
-                                s.pclose();
-                                s.space();
-                                s.print_expr(expr);
-                            }
-                            InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
-                                s.word(if *late { "inlateout" } else { "inout" });
-                                s.popen();
-                                print_reg_or_class(s, reg);
-                                s.pclose();
-                                s.space();
-                                s.print_expr(in_expr);
-                                s.space();
-                                s.word_space("=>");
-                                match out_expr {
-                                    Some(out_expr) => s.print_expr(out_expr),
-                                    None => s.word("_"),
-                                }
-                            }
-                            InlineAsmOperand::Const { expr } => {
-                                s.word("const");
-                                s.space();
-                                s.print_expr(expr);
-                            }
-                            InlineAsmOperand::Sym { expr } => {
-                                s.word("sym");
-                                s.space();
-                                s.print_expr(expr);
-                            }
-                        }
-                    }
-                    AsmArg::Options(opts) => {
-                        s.word("options");
-                        s.popen();
-                        let mut options = vec![];
-                        if opts.contains(InlineAsmOptions::PURE) {
-                            options.push("pure");
-                        }
-                        if opts.contains(InlineAsmOptions::NOMEM) {
-                            options.push("nomem");
-                        }
-                        if opts.contains(InlineAsmOptions::READONLY) {
-                            options.push("readonly");
-                        }
-                        if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
-                            options.push("preserves_flags");
-                        }
-                        if opts.contains(InlineAsmOptions::NORETURN) {
-                            options.push("noreturn");
-                        }
-                        if opts.contains(InlineAsmOptions::NOSTACK) {
-                            options.push("nostack");
-                        }
-                        if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
-                            options.push("att_syntax");
-                        }
-                        s.commasep(Inconsistent, &options, |s, &opt| {
-                            s.word(opt);
-                        });
-                        s.pclose();
-                    }
-                });
-                self.pclose();
-            }
-            ast::ExprKind::LlvmInlineAsm(ref a) => {
-                self.s.word("llvm_asm!");
-                self.popen();
-                self.print_symbol(a.asm, a.asm_str_style);
-                self.word_space(":");
-
-                self.commasep(Inconsistent, &a.outputs, |s, out| {
-                    let constraint = out.constraint.as_str();
-                    let mut ch = constraint.chars();
-                    match ch.next() {
-                        Some('=') if out.is_rw => {
-                            s.print_string(&format!("+{}", ch.as_str()), ast::StrStyle::Cooked)
-                        }
-                        _ => s.print_string(&constraint, ast::StrStyle::Cooked),
-                    }
-                    s.popen();
-                    s.print_expr(&out.expr);
-                    s.pclose();
-                });
-                self.s.space();
-                self.word_space(":");
-
-                self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| {
-                    s.print_symbol(co, ast::StrStyle::Cooked);
-                    s.popen();
-                    s.print_expr(o);
-                    s.pclose();
-                });
-                self.s.space();
-                self.word_space(":");
-
-                self.commasep(Inconsistent, &a.clobbers, |s, &co| {
-                    s.print_symbol(co, ast::StrStyle::Cooked);
-                });
-
-                let mut options = vec![];
-                if a.volatile {
-                    options.push("volatile");
-                }
-                if a.alignstack {
-                    options.push("alignstack");
-                }
-                if a.dialect == ast::LlvmAsmDialect::Intel {
-                    options.push("intel");
-                }
-
-                if !options.is_empty() {
-                    self.s.space();
-                    self.word_space(":");
-                    self.commasep(Inconsistent, &options, |s, &co| {
-                        s.print_string(co, ast::StrStyle::Cooked);
-                    });
-                }
-
-                self.pclose();
-            }
-            ast::ExprKind::MacCall(ref m) => self.print_mac(m),
-            ast::ExprKind::Paren(ref e) => {
-                self.popen();
-                self.print_inner_attributes_inline(attrs);
-                self.print_expr(e);
-                self.pclose();
-            }
-            ast::ExprKind::Yield(ref e) => {
-                self.s.word("yield");
-
-                if let Some(ref expr) = *e {
-                    self.s.space();
-                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
-                }
-            }
-            ast::ExprKind::Try(ref e) => {
-                self.print_expr_maybe_paren(e, parser::PREC_POSTFIX);
-                self.s.word("?")
-            }
-            ast::ExprKind::TryBlock(ref blk) => {
-                self.head("try");
-                self.s.space();
-                self.print_block_with_attrs(blk, attrs)
-            }
-            ast::ExprKind::Err => {
-                self.popen();
-                self.s.word("/*ERROR*/");
-                self.pclose()
-            }
-        }
-        self.ann.post(self, AnnNode::Expr(expr));
-        self.end();
-    }
-
-    crate fn print_local_decl(&mut self, loc: &ast::Local) {
-        self.print_pat(&loc.pat);
-        if let Some(ref ty) = loc.ty {
-            self.word_space(":");
-            self.print_type(ty);
-        }
-    }
-
-    pub fn print_usize(&mut self, i: usize) {
-        self.s.word(i.to_string())
-    }
-
-    crate fn print_name(&mut self, name: Symbol) {
-        self.s.word(name.to_string());
-        self.ann.post(self, AnnNode::Name(&name))
-    }
-
-    fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_params: bool) {
-        self.s.word("<");
-        self.print_type(&qself.ty);
-        if qself.position > 0 {
-            self.s.space();
-            self.word_space("as");
-            let depth = path.segments.len() - qself.position;
-            self.print_path(path, false, depth);
-        }
-        self.s.word(">");
-        for item_segment in &path.segments[qself.position..] {
-            self.s.word("::");
-            self.print_ident(item_segment.ident);
-            if let Some(ref args) = item_segment.args {
-                self.print_generic_args(args, colons_before_params)
-            }
-        }
-    }
-
-    crate fn print_pat(&mut self, pat: &ast::Pat) {
-        self.maybe_print_comment(pat.span.lo());
-        self.ann.pre(self, AnnNode::Pat(pat));
-        /* Pat isn't normalized, but the beauty of it
-        is that it doesn't matter */
-        match pat.kind {
-            PatKind::Wild => self.s.word("_"),
-            PatKind::Ident(binding_mode, ident, ref sub) => {
-                match binding_mode {
-                    ast::BindingMode::ByRef(mutbl) => {
-                        self.word_nbsp("ref");
-                        self.print_mutability(mutbl, false);
-                    }
-                    ast::BindingMode::ByValue(ast::Mutability::Not) => {}
-                    ast::BindingMode::ByValue(ast::Mutability::Mut) => {
-                        self.word_nbsp("mut");
-                    }
-                }
-                self.print_ident(ident);
-                if let Some(ref p) = *sub {
-                    self.s.space();
-                    self.s.word_space("@");
-                    self.print_pat(p);
-                }
-            }
-            PatKind::TupleStruct(ref path, ref elts) => {
-                self.print_path(path, true, 0);
-                self.popen();
-                self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
-                self.pclose();
-            }
-            PatKind::Or(ref pats) => {
-                self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(p));
-            }
-            PatKind::Path(None, ref path) => {
-                self.print_path(path, true, 0);
-            }
-            PatKind::Path(Some(ref qself), ref path) => {
-                self.print_qpath(path, qself, false);
-            }
-            PatKind::Struct(ref path, ref fields, etc) => {
-                self.print_path(path, true, 0);
-                self.nbsp();
-                self.word_space("{");
-                self.commasep_cmnt(
-                    Consistent,
-                    &fields[..],
-                    |s, f| {
-                        s.cbox(INDENT_UNIT);
-                        if !f.is_shorthand {
-                            s.print_ident(f.ident);
-                            s.word_nbsp(":");
-                        }
-                        s.print_pat(&f.pat);
-                        s.end();
-                    },
-                    |f| f.pat.span,
-                );
-                if etc {
-                    if !fields.is_empty() {
-                        self.word_space(",");
-                    }
-                    self.s.word("..");
-                }
-                self.s.space();
-                self.s.word("}");
-            }
-            PatKind::Tuple(ref elts) => {
-                self.popen();
-                self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
-                if elts.len() == 1 {
-                    self.s.word(",");
-                }
-                self.pclose();
-            }
-            PatKind::Box(ref inner) => {
-                self.s.word("box ");
-                self.print_pat(inner);
-            }
-            PatKind::Ref(ref inner, mutbl) => {
-                self.s.word("&");
-                if mutbl == ast::Mutability::Mut {
-                    self.s.word("mut ");
-                }
-                if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) =
-                    inner.kind
-                {
-                    self.popen();
-                    self.print_pat(inner);
-                    self.pclose();
-                } else {
-                    self.print_pat(inner);
-                }
-            }
-            PatKind::Lit(ref e) => self.print_expr(&**e),
-            PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
-                if let Some(e) = begin {
-                    self.print_expr(e);
-                    self.s.space();
-                }
-                match *end_kind {
-                    RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."),
-                    RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="),
-                    RangeEnd::Excluded => self.s.word(".."),
-                }
-                if let Some(e) = end {
-                    self.print_expr(e);
-                }
-            }
-            PatKind::Slice(ref elts) => {
-                self.s.word("[");
-                self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
-                self.s.word("]");
-            }
-            PatKind::Rest => self.s.word(".."),
-            PatKind::Paren(ref inner) => {
-                self.popen();
-                self.print_pat(inner);
-                self.pclose();
-            }
-            PatKind::MacCall(ref m) => self.print_mac(m),
-        }
-        self.ann.post(self, AnnNode::Pat(pat))
-    }
-
-    fn print_arm(&mut self, arm: &ast::Arm) {
-        // Note, I have no idea why this check is necessary, but here it is.
-        if arm.attrs.is_empty() {
-            self.s.space();
-        }
-        self.cbox(INDENT_UNIT);
-        self.ibox(0);
-        self.maybe_print_comment(arm.pat.span.lo());
-        self.print_outer_attributes(&arm.attrs);
-        self.print_pat(&arm.pat);
-        self.s.space();
-        if let Some(ref e) = arm.guard {
-            self.word_space("if");
-            self.print_expr(e);
-            self.s.space();
-        }
-        self.word_space("=>");
-
-        match arm.body.kind {
-            ast::ExprKind::Block(ref blk, opt_label) => {
-                if let Some(label) = opt_label {
-                    self.print_ident(label.ident);
-                    self.word_space(":");
-                }
-
-                // The block will close the pattern's ibox.
-                self.print_block_unclosed_indent(blk);
-
-                // If it is a user-provided unsafe block, print a comma after it.
-                if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
-                    self.s.word(",");
-                }
-            }
-            _ => {
-                self.end(); // Close the ibox for the pattern.
-                self.print_expr(&arm.body);
-                self.s.word(",");
-            }
-        }
-        self.end(); // Close enclosing cbox.
-    }
-
-    fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) {
-        match explicit_self.node {
-            SelfKind::Value(m) => {
-                self.print_mutability(m, false);
-                self.s.word("self")
-            }
-            SelfKind::Region(ref lt, m) => {
-                self.s.word("&");
-                self.print_opt_lifetime(lt);
-                self.print_mutability(m, false);
-                self.s.word("self")
-            }
-            SelfKind::Explicit(ref typ, m) => {
-                self.print_mutability(m, false);
-                self.s.word("self");
-                self.word_space(":");
-                self.print_type(typ)
-            }
-        }
-    }
-
-    fn print_fn_full(
-        &mut self,
-        sig: &ast::FnSig,
-        name: Ident,
-        generics: &ast::Generics,
-        vis: &ast::Visibility,
-        defaultness: ast::Defaultness,
-        body: Option<&ast::Block>,
-        attrs: &[ast::Attribute],
-    ) {
-        if body.is_some() {
-            self.head("");
-        }
-        self.print_visibility(vis);
-        self.print_defaultness(defaultness);
-        self.print_fn(&sig.decl, sig.header, Some(name), generics);
-        if let Some(body) = body {
-            self.nbsp();
-            self.print_block_with_attrs(body, attrs);
-        } else {
-            self.s.word(";");
-        }
-    }
-
-    crate fn print_fn(
-        &mut self,
-        decl: &ast::FnDecl,
-        header: ast::FnHeader,
-        name: Option,
-        generics: &ast::Generics,
-    ) {
-        self.print_fn_header_info(header);
-        if let Some(name) = name {
-            self.nbsp();
-            self.print_ident(name);
-        }
-        self.print_generic_params(&generics.params);
-        self.print_fn_params_and_ret(decl, false);
-        self.print_where_clause(&generics.where_clause)
-    }
-
-    crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
-        let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") };
-        self.word(open);
-        self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure));
-        self.word(close);
-        self.print_fn_ret_ty(&decl.output)
-    }
-
-    crate fn print_movability(&mut self, movability: ast::Movability) {
-        match movability {
-            ast::Movability::Static => self.word_space("static"),
-            ast::Movability::Movable => {}
-        }
-    }
-
-    crate fn print_asyncness(&mut self, asyncness: ast::Async) {
-        if asyncness.is_async() {
-            self.word_nbsp("async");
-        }
-    }
-
-    crate fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
-        match capture_clause {
-            ast::CaptureBy::Value => self.word_space("move"),
-            ast::CaptureBy::Ref => {}
-        }
-    }
-
-    pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound]) {
-        if !bounds.is_empty() {
-            self.s.word(prefix);
-            let mut first = true;
-            for bound in bounds {
-                if !(first && prefix.is_empty()) {
-                    self.nbsp();
-                }
-                if first {
-                    first = false;
-                } else {
-                    self.word_space("+");
-                }
-
-                match bound {
-                    GenericBound::Trait(tref, modifier) => {
-                        if modifier == &TraitBoundModifier::Maybe {
-                            self.s.word("?");
-                        }
-                        self.print_poly_trait_ref(tref);
-                    }
-                    GenericBound::Outlives(lt) => self.print_lifetime(*lt),
-                }
-            }
-        }
-    }
-
-    crate fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
-        self.print_name(lifetime.ident.name)
-    }
-
-    crate fn print_lifetime_bounds(
-        &mut self,
-        lifetime: ast::Lifetime,
-        bounds: &ast::GenericBounds,
-    ) {
-        self.print_lifetime(lifetime);
-        if !bounds.is_empty() {
-            self.s.word(": ");
-            for (i, bound) in bounds.iter().enumerate() {
-                if i != 0 {
-                    self.s.word(" + ");
-                }
-                match bound {
-                    ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt),
-                    _ => panic!(),
-                }
-            }
-        }
-    }
-
-    crate fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
-        if generic_params.is_empty() {
-            return;
-        }
-
-        self.s.word("<");
-
-        self.commasep(Inconsistent, &generic_params, |s, param| {
-            s.print_outer_attributes_inline(¶m.attrs);
-
-            match param.kind {
-                ast::GenericParamKind::Lifetime => {
-                    let lt = ast::Lifetime { id: param.id, ident: param.ident };
-                    s.print_lifetime_bounds(lt, ¶m.bounds)
-                }
-                ast::GenericParamKind::Type { ref default } => {
-                    s.print_ident(param.ident);
-                    s.print_type_bounds(":", ¶m.bounds);
-                    if let Some(ref default) = default {
-                        s.s.space();
-                        s.word_space("=");
-                        s.print_type(default)
-                    }
-                }
-                ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
-                    s.word_space("const");
-                    s.print_ident(param.ident);
-                    s.s.space();
-                    s.word_space(":");
-                    s.print_type(ty);
-                    s.print_type_bounds(":", ¶m.bounds);
-                    if let Some(ref _default) = default {
-                        // FIXME(const_generics_defaults): print the `default` value here
-                    }
-                }
-            }
-        });
-
-        self.s.word(">");
-    }
-
-    crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
-        if where_clause.predicates.is_empty() && !where_clause.has_where_token {
-            return;
-        }
-
-        self.s.space();
-        self.word_space("where");
-
-        for (i, predicate) in where_clause.predicates.iter().enumerate() {
-            if i != 0 {
-                self.word_space(",");
-            }
-
-            match *predicate {
-                ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
-                    ref bound_generic_params,
-                    ref bounded_ty,
-                    ref bounds,
-                    ..
-                }) => {
-                    self.print_formal_generic_params(bound_generic_params);
-                    self.print_type(bounded_ty);
-                    self.print_type_bounds(":", bounds);
-                }
-                ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
-                    ref lifetime,
-                    ref bounds,
-                    ..
-                }) => {
-                    self.print_lifetime_bounds(*lifetime, bounds);
-                }
-                ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
-                    ref lhs_ty,
-                    ref rhs_ty,
-                    ..
-                }) => {
-                    self.print_type(lhs_ty);
-                    self.s.space();
-                    self.word_space("=");
-                    self.print_type(rhs_ty);
-                }
-            }
-        }
-    }
-
-    crate fn print_use_tree(&mut self, tree: &ast::UseTree) {
-        match tree.kind {
-            ast::UseTreeKind::Simple(rename, ..) => {
-                self.print_path(&tree.prefix, false, 0);
-                if let Some(rename) = rename {
-                    self.s.space();
-                    self.word_space("as");
-                    self.print_ident(rename);
-                }
-            }
-            ast::UseTreeKind::Glob => {
-                if !tree.prefix.segments.is_empty() {
-                    self.print_path(&tree.prefix, false, 0);
-                    self.s.word("::");
-                }
-                self.s.word("*");
-            }
-            ast::UseTreeKind::Nested(ref items) => {
-                if tree.prefix.segments.is_empty() {
-                    self.s.word("{");
-                } else {
-                    self.print_path(&tree.prefix, false, 0);
-                    self.s.word("::{");
-                }
-                self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| {
-                    this.print_use_tree(tree)
-                });
-                self.s.word("}");
-            }
-        }
-    }
-
-    pub fn print_mutability(&mut self, mutbl: ast::Mutability, print_const: bool) {
-        match mutbl {
-            ast::Mutability::Mut => self.word_nbsp("mut"),
-            ast::Mutability::Not => {
-                if print_const {
-                    self.word_nbsp("const");
-                }
-            }
-        }
-    }
-
-    crate fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) {
-        self.print_mutability(mt.mutbl, print_const);
-        self.print_type(&mt.ty)
-    }
-
-    crate fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
-        self.ibox(INDENT_UNIT);
-
-        self.print_outer_attributes_inline(&input.attrs);
-
-        match input.ty.kind {
-            ast::TyKind::Infer if is_closure => self.print_pat(&input.pat),
-            _ => {
-                if let Some(eself) = input.to_self() {
-                    self.print_explicit_self(&eself);
-                } else {
-                    let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind {
-                        ident.name == kw::Empty
-                    } else {
-                        false
-                    };
-                    if !invalid {
-                        self.print_pat(&input.pat);
-                        self.s.word(":");
-                        self.s.space();
-                    }
-                    self.print_type(&input.ty);
-                }
-            }
-        }
-        self.end();
-    }
-
-    crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) {
-        if let ast::FnRetTy::Ty(ty) = fn_ret_ty {
-            self.space_if_not_bol();
-            self.ibox(INDENT_UNIT);
-            self.word_space("->");
-            self.print_type(ty);
-            self.end();
-            self.maybe_print_comment(ty.span.lo());
-        }
-    }
-
-    crate fn print_ty_fn(
-        &mut self,
-        ext: ast::Extern,
-        unsafety: ast::Unsafe,
-        decl: &ast::FnDecl,
-        name: Option,
-        generic_params: &[ast::GenericParam],
-    ) {
-        self.ibox(INDENT_UNIT);
-        if !generic_params.is_empty() {
-            self.s.word("for");
-            self.print_generic_params(generic_params);
-        }
-        let generics = ast::Generics {
-            params: Vec::new(),
-            where_clause: ast::WhereClause {
-                has_where_token: false,
-                predicates: Vec::new(),
-                span: rustc_span::DUMMY_SP,
-            },
-            span: rustc_span::DUMMY_SP,
-        };
-        let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
-        self.print_fn(decl, header, name, &generics);
-        self.end();
-    }
-
-    crate fn maybe_print_trailing_comment(
-        &mut self,
-        span: rustc_span::Span,
-        next_pos: Option,
-    ) {
-        if let Some(cmnts) = self.comments() {
-            if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
-                self.print_comment(&cmnt);
-            }
-        }
-    }
-
-    crate fn print_remaining_comments(&mut self) {
-        // If there aren't any remaining comments, then we need to manually
-        // make sure there is a line break at the end.
-        if self.next_comment().is_none() {
-            self.s.hardbreak();
-        }
-        while let Some(ref cmnt) = self.next_comment() {
-            self.print_comment(cmnt);
-        }
-    }
-
-    crate fn print_fn_header_info(&mut self, header: ast::FnHeader) {
-        self.print_constness(header.constness);
-        self.print_asyncness(header.asyncness);
-        self.print_unsafety(header.unsafety);
-
-        match header.ext {
-            ast::Extern::None => {}
-            ast::Extern::Implicit => {
-                self.word_nbsp("extern");
-            }
-            ast::Extern::Explicit(abi) => {
-                self.word_nbsp("extern");
-                self.print_literal(&abi.as_lit());
-                self.nbsp();
-            }
-        }
-
-        self.s.word("fn")
-    }
-
-    crate fn print_unsafety(&mut self, s: ast::Unsafe) {
-        match s {
-            ast::Unsafe::No => {}
-            ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"),
-        }
-    }
-
-    crate fn print_constness(&mut self, s: ast::Const) {
-        match s {
-            ast::Const::No => {}
-            ast::Const::Yes(_) => self.word_nbsp("const"),
-        }
-    }
-
-    crate fn print_is_auto(&mut self, s: ast::IsAuto) {
-        match s {
-            ast::IsAuto::Yes => self.word_nbsp("auto"),
-            ast::IsAuto::No => {}
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_ast_pretty/src/pprust/tests.rs b/vendor/rustc-ap-rustc_ast_pretty/src/pprust/tests.rs
deleted file mode 100644
index b1a73a0bf0..0000000000
--- a/vendor/rustc-ap-rustc_ast_pretty/src/pprust/tests.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use super::*;
-
-use rustc_ast as ast;
-use rustc_span::symbol::Ident;
-use rustc_span::with_default_session_globals;
-
-fn fun_to_string(
-    decl: &ast::FnDecl,
-    header: ast::FnHeader,
-    name: Ident,
-    generics: &ast::Generics,
-) -> String {
-    to_string(|s| {
-        s.head("");
-        s.print_fn(decl, header, Some(name), generics);
-        s.end(); // Close the head box.
-        s.end(); // Close the outer box.
-    })
-}
-
-fn variant_to_string(var: &ast::Variant) -> String {
-    to_string(|s| s.print_variant(var))
-}
-
-#[test]
-fn test_fun_to_string() {
-    with_default_session_globals(|| {
-        let abba_ident = Ident::from_str("abba");
-
-        let decl =
-            ast::FnDecl { inputs: Vec::new(), output: ast::FnRetTy::Default(rustc_span::DUMMY_SP) };
-        let generics = ast::Generics::default();
-        assert_eq!(
-            fun_to_string(&decl, ast::FnHeader::default(), abba_ident, &generics),
-            "fn abba()"
-        );
-    })
-}
-
-#[test]
-fn test_variant_to_string() {
-    with_default_session_globals(|| {
-        let ident = Ident::from_str("principal_skinner");
-
-        let var = ast::Variant {
-            ident,
-            vis: ast::Visibility {
-                span: rustc_span::DUMMY_SP,
-                kind: ast::VisibilityKind::Inherited,
-                tokens: None,
-            },
-            attrs: Vec::new(),
-            id: ast::DUMMY_NODE_ID,
-            data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
-            disr_expr: None,
-            span: rustc_span::DUMMY_SP,
-            is_placeholder: false,
-        };
-
-        let varstr = variant_to_string(&var);
-        assert_eq!(varstr, "principal_skinner");
-    })
-}
diff --git a/vendor/rustc-ap-rustc_attr/.cargo-checksum.json b/vendor/rustc-ap-rustc_attr/.cargo-checksum.json
deleted file mode 100644
index 6230d76012..0000000000
--- a/vendor/rustc-ap-rustc_attr/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"ca1378768585c828a82de747d76292238506f1980b2cce4438c0a2059b63ffb2","src/builtin.rs":"a7c7ced436ed0eccadbfe94e2d1caf4500f49b03f665637f80fc75ab9e1ecdf7","src/lib.rs":"2f9807789db9bc9f5aac5105114c07dddd4ef8491ec24295c7891ddaf6e12053"},"package":"797fc68816d5396870f04e03d35164f5275d2502403239d4caec7ce063683f41"}
\ No newline at end of file
diff --git a/vendor/rustc-ap-rustc_attr/Cargo.toml b/vendor/rustc-ap-rustc_attr/Cargo.toml
deleted file mode 100644
index 79e5f028bd..0000000000
--- a/vendor/rustc-ap-rustc_attr/Cargo.toml
+++ /dev/null
@@ -1,62 +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 = "rustc-ap-rustc_attr"
-version = "705.0.0"
-authors = ["The Rust Project Developers"]
-description = "Automatically published version of the package `rustc_attr` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n            "
-license = "MIT / Apache-2.0"
-repository = "https://github.com/rust-lang/rust"
-
-[lib]
-doctest = false
-[dependencies.rustc_ast]
-version = "705.0.0"
-package = "rustc-ap-rustc_ast"
-
-[dependencies.rustc_ast_pretty]
-version = "705.0.0"
-package = "rustc-ap-rustc_ast_pretty"
-
-[dependencies.rustc_data_structures]
-version = "705.0.0"
-package = "rustc-ap-rustc_data_structures"
-
-[dependencies.rustc_errors]
-version = "705.0.0"
-package = "rustc-ap-rustc_errors"
-
-[dependencies.rustc_feature]
-version = "705.0.0"
-package = "rustc-ap-rustc_feature"
-
-[dependencies.rustc_lexer]
-version = "705.0.0"
-package = "rustc-ap-rustc_lexer"
-
-[dependencies.rustc_macros]
-version = "705.0.0"
-package = "rustc-ap-rustc_macros"
-
-[dependencies.rustc_serialize]
-version = "705.0.0"
-package = "rustc-ap-rustc_serialize"
-
-[dependencies.rustc_session]
-version = "705.0.0"
-package = "rustc-ap-rustc_session"
-
-[dependencies.rustc_span]
-version = "705.0.0"
-package = "rustc-ap-rustc_span"
diff --git a/vendor/rustc-ap-rustc_attr/src/builtin.rs b/vendor/rustc-ap-rustc_attr/src/builtin.rs
deleted file mode 100644
index aca3fbbca1..0000000000
--- a/vendor/rustc-ap-rustc_attr/src/builtin.rs
+++ /dev/null
@@ -1,1077 +0,0 @@
-//! Parsing and validation of builtin attributes
-
-use rustc_ast::{self as ast, Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem};
-use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability};
-use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
-use rustc_macros::HashStable_Generic;
-use rustc_session::parse::{feature_err, ParseSess};
-use rustc_session::Session;
-use rustc_span::hygiene::Transparency;
-use rustc_span::{symbol::sym, symbol::Symbol, Span};
-use std::num::NonZeroU32;
-
-pub fn is_builtin_attr(attr: &Attribute) -> bool {
-    attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
-}
-
-enum AttrError {
-    MultipleItem(String),
-    UnknownMetaItem(String, &'static [&'static str]),
-    MissingSince,
-    NonIdentFeature,
-    MissingFeature,
-    MultipleStabilityLevels,
-    UnsupportedLiteral(&'static str, /* is_bytestr */ bool),
-}
-
-fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
-    let diag = &sess.span_diagnostic;
-    match error {
-        AttrError::MultipleItem(item) => {
-            struct_span_err!(diag, span, E0538, "multiple '{}' items", item).emit();
-        }
-        AttrError::UnknownMetaItem(item, expected) => {
-            let expected = expected.iter().map(|name| format!("`{}`", name)).collect::>();
-            struct_span_err!(diag, span, E0541, "unknown meta item '{}'", item)
-                .span_label(span, format!("expected one of {}", expected.join(", ")))
-                .emit();
-        }
-        AttrError::MissingSince => {
-            struct_span_err!(diag, span, E0542, "missing 'since'").emit();
-        }
-        AttrError::NonIdentFeature => {
-            struct_span_err!(diag, span, E0546, "'feature' is not an identifier").emit();
-        }
-        AttrError::MissingFeature => {
-            struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
-        }
-        AttrError::MultipleStabilityLevels => {
-            struct_span_err!(diag, span, E0544, "multiple stability levels").emit();
-        }
-        AttrError::UnsupportedLiteral(msg, is_bytestr) => {
-            let mut err = struct_span_err!(diag, span, E0565, "{}", msg);
-            if is_bytestr {
-                if let Ok(lint_str) = sess.source_map().span_to_snippet(span) {
-                    err.span_suggestion(
-                        span,
-                        "consider removing the prefix",
-                        lint_str[1..].to_string(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            }
-            err.emit();
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
-pub enum InlineAttr {
-    None,
-    Hint,
-    Always,
-    Never,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
-pub enum InstructionSetAttr {
-    ArmA32,
-    ArmT32,
-}
-
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub enum OptimizeAttr {
-    None,
-    Speed,
-    Size,
-}
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum UnwindAttr {
-    Allowed,
-    Aborts,
-}
-
-/// Determine what `#[unwind]` attribute is present in `attrs`, if any.
-pub fn find_unwind_attr(sess: &Session, attrs: &[Attribute]) -> Option {
-    attrs.iter().fold(None, |ia, attr| {
-        if sess.check_name(attr, sym::unwind) {
-            if let Some(meta) = attr.meta() {
-                if let MetaItemKind::List(items) = meta.kind {
-                    if items.len() == 1 {
-                        if items[0].has_name(sym::allowed) {
-                            return Some(UnwindAttr::Allowed);
-                        } else if items[0].has_name(sym::aborts) {
-                            return Some(UnwindAttr::Aborts);
-                        }
-                    }
-
-                    struct_span_err!(
-                        sess.diagnostic(),
-                        attr.span,
-                        E0633,
-                        "malformed `unwind` attribute input"
-                    )
-                    .span_label(attr.span, "invalid argument")
-                    .span_suggestions(
-                        attr.span,
-                        "the allowed arguments are `allowed` and `aborts`",
-                        (vec!["allowed", "aborts"])
-                            .into_iter()
-                            .map(|s| format!("#[unwind({})]", s)),
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
-                }
-            }
-        }
-
-        ia
-    })
-}
-
-/// Represents the following attributes:
-///
-/// - `#[stable]`
-/// - `#[unstable]`
-#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[derive(HashStable_Generic)]
-pub struct Stability {
-    pub level: StabilityLevel,
-    pub feature: Symbol,
-}
-
-/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
-#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[derive(HashStable_Generic)]
-pub struct ConstStability {
-    pub level: StabilityLevel,
-    pub feature: Symbol,
-    /// whether the function has a `#[rustc_promotable]` attribute
-    pub promotable: bool,
-}
-
-/// The available stability levels.
-#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
-#[derive(HashStable_Generic)]
-pub enum StabilityLevel {
-    // Reason for the current stability level and the relevant rust-lang issue
-    Unstable { reason: Option, issue: Option, is_soft: bool },
-    Stable { since: Symbol },
-}
-
-impl StabilityLevel {
-    pub fn is_unstable(&self) -> bool {
-        matches!(self, StabilityLevel::Unstable { .. })
-    }
-    pub fn is_stable(&self) -> bool {
-        matches!(self, StabilityLevel::Stable { .. })
-    }
-}
-
-/// Collects stability info from all stability attributes in `attrs`.
-/// Returns `None` if no stability attributes are found.
-pub fn find_stability(
-    sess: &Session,
-    attrs: &[Attribute],
-    item_sp: Span,
-) -> (Option, Option) {
-    find_stability_generic(sess, attrs.iter(), item_sp)
-}
-
-fn find_stability_generic<'a, I>(
-    sess: &Session,
-    attrs_iter: I,
-    item_sp: Span,
-) -> (Option, Option)
-where
-    I: Iterator,
-{
-    use StabilityLevel::*;
-
-    let mut stab: Option = None;
-    let mut const_stab: Option = None;
-    let mut promotable = false;
-    let diagnostic = &sess.parse_sess.span_diagnostic;
-
-    'outer: for attr in attrs_iter {
-        if ![
-            sym::rustc_const_unstable,
-            sym::rustc_const_stable,
-            sym::unstable,
-            sym::stable,
-            sym::rustc_promotable,
-        ]
-        .iter()
-        .any(|&s| attr.has_name(s))
-        {
-            continue; // not a stability level
-        }
-
-        sess.mark_attr_used(attr);
-
-        let meta = attr.meta();
-
-        if attr.has_name(sym::rustc_promotable) {
-            promotable = true;
-        }
-        // attributes with data
-        else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta {
-            let meta = meta.as_ref().unwrap();
-            let get = |meta: &MetaItem, item: &mut Option| {
-                if item.is_some() {
-                    handle_errors(
-                        &sess.parse_sess,
-                        meta.span,
-                        AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
-                    );
-                    return false;
-                }
-                if let Some(v) = meta.value_str() {
-                    *item = Some(v);
-                    true
-                } else {
-                    struct_span_err!(diagnostic, meta.span, E0539, "incorrect meta item").emit();
-                    false
-                }
-            };
-
-            let meta_name = meta.name_or_empty();
-            match meta_name {
-                sym::rustc_const_unstable | sym::unstable => {
-                    if meta_name == sym::unstable && stab.is_some() {
-                        handle_errors(
-                            &sess.parse_sess,
-                            attr.span,
-                            AttrError::MultipleStabilityLevels,
-                        );
-                        break;
-                    } else if meta_name == sym::rustc_const_unstable && const_stab.is_some() {
-                        handle_errors(
-                            &sess.parse_sess,
-                            attr.span,
-                            AttrError::MultipleStabilityLevels,
-                        );
-                        break;
-                    }
-
-                    let mut feature = None;
-                    let mut reason = None;
-                    let mut issue = None;
-                    let mut issue_num = None;
-                    let mut is_soft = false;
-                    for meta in metas {
-                        if let Some(mi) = meta.meta_item() {
-                            match mi.name_or_empty() {
-                                sym::feature => {
-                                    if !get(mi, &mut feature) {
-                                        continue 'outer;
-                                    }
-                                }
-                                sym::reason => {
-                                    if !get(mi, &mut reason) {
-                                        continue 'outer;
-                                    }
-                                }
-                                sym::issue => {
-                                    if !get(mi, &mut issue) {
-                                        continue 'outer;
-                                    }
-
-                                    // These unwraps are safe because `get` ensures the meta item
-                                    // is a name/value pair string literal.
-                                    issue_num = match &*issue.unwrap().as_str() {
-                                        "none" => None,
-                                        issue => {
-                                            let emit_diag = |msg: &str| {
-                                                struct_span_err!(
-                                                    diagnostic,
-                                                    mi.span,
-                                                    E0545,
-                                                    "`issue` must be a non-zero numeric string \
-                                                    or \"none\"",
-                                                )
-                                                .span_label(
-                                                    mi.name_value_literal_span().unwrap(),
-                                                    msg,
-                                                )
-                                                .emit();
-                                            };
-                                            match issue.parse() {
-                                                Ok(0) => {
-                                                    emit_diag(
-                                                        "`issue` must not be \"0\", \
-                                                        use \"none\" instead",
-                                                    );
-                                                    continue 'outer;
-                                                }
-                                                Ok(num) => NonZeroU32::new(num),
-                                                Err(err) => {
-                                                    emit_diag(&err.to_string());
-                                                    continue 'outer;
-                                                }
-                                            }
-                                        }
-                                    };
-                                }
-                                sym::soft => {
-                                    if !mi.is_word() {
-                                        let msg = "`soft` should not have any arguments";
-                                        sess.parse_sess.span_diagnostic.span_err(mi.span, msg);
-                                    }
-                                    is_soft = true;
-                                }
-                                _ => {
-                                    handle_errors(
-                                        &sess.parse_sess,
-                                        meta.span(),
-                                        AttrError::UnknownMetaItem(
-                                            pprust::path_to_string(&mi.path),
-                                            &["feature", "reason", "issue", "soft"],
-                                        ),
-                                    );
-                                    continue 'outer;
-                                }
-                            }
-                        } else {
-                            handle_errors(
-                                &sess.parse_sess,
-                                meta.span(),
-                                AttrError::UnsupportedLiteral("unsupported literal", false),
-                            );
-                            continue 'outer;
-                        }
-                    }
-
-                    match (feature, reason, issue) {
-                        (Some(feature), reason, Some(_)) => {
-                            if !rustc_lexer::is_ident(&feature.as_str()) {
-                                handle_errors(
-                                    &sess.parse_sess,
-                                    attr.span,
-                                    AttrError::NonIdentFeature,
-                                );
-                                continue;
-                            }
-                            let level = Unstable { reason, issue: issue_num, is_soft };
-                            if sym::unstable == meta_name {
-                                stab = Some(Stability { level, feature });
-                            } else {
-                                const_stab =
-                                    Some(ConstStability { level, feature, promotable: false });
-                            }
-                        }
-                        (None, _, _) => {
-                            handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
-                            continue;
-                        }
-                        _ => {
-                            struct_span_err!(diagnostic, attr.span, E0547, "missing 'issue'")
-                                .emit();
-                            continue;
-                        }
-                    }
-                }
-                sym::rustc_const_stable | sym::stable => {
-                    if meta_name == sym::stable && stab.is_some() {
-                        handle_errors(
-                            &sess.parse_sess,
-                            attr.span,
-                            AttrError::MultipleStabilityLevels,
-                        );
-                        break;
-                    } else if meta_name == sym::rustc_const_stable && const_stab.is_some() {
-                        handle_errors(
-                            &sess.parse_sess,
-                            attr.span,
-                            AttrError::MultipleStabilityLevels,
-                        );
-                        break;
-                    }
-
-                    let mut feature = None;
-                    let mut since = None;
-                    for meta in metas {
-                        match meta {
-                            NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
-                                sym::feature => {
-                                    if !get(mi, &mut feature) {
-                                        continue 'outer;
-                                    }
-                                }
-                                sym::since => {
-                                    if !get(mi, &mut since) {
-                                        continue 'outer;
-                                    }
-                                }
-                                _ => {
-                                    handle_errors(
-                                        &sess.parse_sess,
-                                        meta.span(),
-                                        AttrError::UnknownMetaItem(
-                                            pprust::path_to_string(&mi.path),
-                                            &["since", "note"],
-                                        ),
-                                    );
-                                    continue 'outer;
-                                }
-                            },
-                            NestedMetaItem::Literal(lit) => {
-                                handle_errors(
-                                    &sess.parse_sess,
-                                    lit.span,
-                                    AttrError::UnsupportedLiteral("unsupported literal", false),
-                                );
-                                continue 'outer;
-                            }
-                        }
-                    }
-
-                    match (feature, since) {
-                        (Some(feature), Some(since)) => {
-                            let level = Stable { since };
-                            if sym::stable == meta_name {
-                                stab = Some(Stability { level, feature });
-                            } else {
-                                const_stab =
-                                    Some(ConstStability { level, feature, promotable: false });
-                            }
-                        }
-                        (None, _) => {
-                            handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
-                            continue;
-                        }
-                        _ => {
-                            handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
-                            continue;
-                        }
-                    }
-                }
-                _ => unreachable!(),
-            }
-        }
-    }
-
-    // Merge the const-unstable info into the stability info
-    if promotable {
-        if let Some(ref mut stab) = const_stab {
-            stab.promotable = promotable;
-        } else {
-            struct_span_err!(
-                diagnostic,
-                item_sp,
-                E0717,
-                "`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \
-                or a `rustc_const_stable` attribute"
-            )
-            .emit();
-        }
-    }
-
-    (stab, const_stab)
-}
-
-pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option {
-    sess.first_attr_value_str_by_name(attrs, sym::crate_name)
-}
-
-/// Tests if a cfg-pattern matches the cfg set
-pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
-    eval_condition(cfg, sess, features, &mut |cfg| {
-        try_gate_cfg(cfg, sess, features);
-        let error = |span, msg| {
-            sess.span_diagnostic.span_err(span, msg);
-            true
-        };
-        if cfg.path.segments.len() != 1 {
-            return error(cfg.path.span, "`cfg` predicate key must be an identifier");
-        }
-        match &cfg.kind {
-            MetaItemKind::List(..) => {
-                error(cfg.span, "unexpected parentheses after `cfg` predicate key")
-            }
-            MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
-                handle_errors(
-                    sess,
-                    lit.span,
-                    AttrError::UnsupportedLiteral(
-                        "literal in `cfg` predicate value must be a string",
-                        lit.kind.is_bytestr(),
-                    ),
-                );
-                true
-            }
-            MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                let ident = cfg.ident().expect("multi-segment cfg predicate");
-                sess.config.contains(&(ident.name, cfg.value_str()))
-            }
-        }
-    })
-}
-
-fn try_gate_cfg(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) {
-    let gate = find_gated_cfg(|sym| cfg.has_name(sym));
-    if let (Some(feats), Some(gated_cfg)) = (features, gate) {
-        gate_cfg(&gated_cfg, cfg.span, sess, feats);
-    }
-}
-
-fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) {
-    let (cfg, feature, has_feature) = gated_cfg;
-    if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
-        let explain = format!("`cfg({})` is experimental and subject to change", cfg);
-        feature_err(sess, *feature, cfg_span, &explain).emit();
-    }
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-struct Version {
-    major: u16,
-    minor: u16,
-    patch: u16,
-}
-
-fn parse_version(s: &str, allow_appendix: bool) -> Option {
-    let mut components = s.split('-');
-    let d = components.next()?;
-    if !allow_appendix && components.next().is_some() {
-        return None;
-    }
-    let mut digits = d.splitn(3, '.');
-    let major = digits.next()?.parse().ok()?;
-    let minor = digits.next()?.parse().ok()?;
-    let patch = digits.next().unwrap_or("0").parse().ok()?;
-    Some(Version { major, minor, patch })
-}
-
-/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
-/// evaluate individual items.
-pub fn eval_condition(
-    cfg: &ast::MetaItem,
-    sess: &ParseSess,
-    features: Option<&Features>,
-    eval: &mut impl FnMut(&ast::MetaItem) -> bool,
-) -> bool {
-    match cfg.kind {
-        ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
-            try_gate_cfg(cfg, sess, features);
-            let (min_version, span) = match &mis[..] {
-                [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
-                    (sym, span)
-                }
-                [NestedMetaItem::Literal(Lit { span, .. })
-                | NestedMetaItem::MetaItem(MetaItem { span, .. })] => {
-                    sess.span_diagnostic
-                        .struct_span_err(*span, "expected a version literal")
-                        .emit();
-                    return false;
-                }
-                [..] => {
-                    sess.span_diagnostic
-                        .struct_span_err(cfg.span, "expected single version literal")
-                        .emit();
-                    return false;
-                }
-            };
-            let min_version = match parse_version(&min_version.as_str(), false) {
-                Some(ver) => ver,
-                None => {
-                    sess.span_diagnostic
-                        .struct_span_warn(
-                            *span,
-                            "unknown version literal format, assuming it refers to a future version",
-                        )
-                        .emit();
-                    return false;
-                }
-            };
-            let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap();
-
-            // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
-            if sess.assume_incomplete_release {
-                rustc_version > min_version
-            } else {
-                rustc_version >= min_version
-            }
-        }
-        ast::MetaItemKind::List(ref mis) => {
-            for mi in mis.iter() {
-                if !mi.is_meta_item() {
-                    handle_errors(
-                        sess,
-                        mi.span(),
-                        AttrError::UnsupportedLiteral("unsupported literal", false),
-                    );
-                    return false;
-                }
-            }
-
-            // The unwraps below may look dangerous, but we've already asserted
-            // that they won't fail with the loop above.
-            match cfg.name_or_empty() {
-                sym::any => mis
-                    .iter()
-                    .any(|mi| eval_condition(mi.meta_item().unwrap(), sess, features, eval)),
-                sym::all => mis
-                    .iter()
-                    .all(|mi| eval_condition(mi.meta_item().unwrap(), sess, features, eval)),
-                sym::not => {
-                    if mis.len() != 1 {
-                        struct_span_err!(
-                            sess.span_diagnostic,
-                            cfg.span,
-                            E0536,
-                            "expected 1 cfg-pattern"
-                        )
-                        .emit();
-                        return false;
-                    }
-
-                    !eval_condition(mis[0].meta_item().unwrap(), sess, features, eval)
-                }
-                _ => {
-                    struct_span_err!(
-                        sess.span_diagnostic,
-                        cfg.span,
-                        E0537,
-                        "invalid predicate `{}`",
-                        pprust::path_to_string(&cfg.path)
-                    )
-                    .emit();
-                    false
-                }
-            }
-        }
-        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => eval(cfg),
-    }
-}
-
-#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic)]
-pub struct Deprecation {
-    pub since: Option,
-    /// The note to issue a reason.
-    pub note: Option,
-    /// A text snippet used to completely replace any use of the deprecated item in an expression.
-    ///
-    /// This is currently unstable.
-    pub suggestion: Option,
-
-    /// Whether to treat the since attribute as being a Rust version identifier
-    /// (rather than an opaque string).
-    pub is_since_rustc_version: bool,
-}
-
-/// Finds the deprecation attribute. `None` if none exists.
-pub fn find_deprecation(sess: &Session, attrs: &[Attribute]) -> Option<(Deprecation, Span)> {
-    find_deprecation_generic(sess, attrs.iter())
-}
-
-fn find_deprecation_generic<'a, I>(sess: &Session, attrs_iter: I) -> Option<(Deprecation, Span)>
-where
-    I: Iterator,
-{
-    let mut depr: Option<(Deprecation, Span)> = None;
-    let diagnostic = &sess.parse_sess.span_diagnostic;
-
-    'outer: for attr in attrs_iter {
-        if !(sess.check_name(attr, sym::deprecated) || sess.check_name(attr, sym::rustc_deprecated))
-        {
-            continue;
-        }
-
-        if let Some((_, span)) = &depr {
-            struct_span_err!(diagnostic, attr.span, E0550, "multiple deprecated attributes")
-                .span_label(attr.span, "repeated deprecation attribute")
-                .span_label(*span, "first deprecation attribute")
-                .emit();
-            break;
-        }
-
-        let meta = match attr.meta() {
-            Some(meta) => meta,
-            None => continue,
-        };
-        let mut since = None;
-        let mut note = None;
-        let mut suggestion = None;
-        match &meta.kind {
-            MetaItemKind::Word => {}
-            MetaItemKind::NameValue(..) => note = meta.value_str(),
-            MetaItemKind::List(list) => {
-                let get = |meta: &MetaItem, item: &mut Option| {
-                    if item.is_some() {
-                        handle_errors(
-                            &sess.parse_sess,
-                            meta.span,
-                            AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
-                        );
-                        return false;
-                    }
-                    if let Some(v) = meta.value_str() {
-                        *item = Some(v);
-                        true
-                    } else {
-                        if let Some(lit) = meta.name_value_literal() {
-                            handle_errors(
-                                &sess.parse_sess,
-                                lit.span,
-                                AttrError::UnsupportedLiteral(
-                                    "literal in `deprecated` \
-                                    value must be a string",
-                                    lit.kind.is_bytestr(),
-                                ),
-                            );
-                        } else {
-                            struct_span_err!(diagnostic, meta.span, E0551, "incorrect meta item")
-                                .emit();
-                        }
-
-                        false
-                    }
-                };
-
-                for meta in list {
-                    match meta {
-                        NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
-                            sym::since => {
-                                if !get(mi, &mut since) {
-                                    continue 'outer;
-                                }
-                            }
-                            sym::note if sess.check_name(attr, sym::deprecated) => {
-                                if !get(mi, &mut note) {
-                                    continue 'outer;
-                                }
-                            }
-                            sym::reason if sess.check_name(attr, sym::rustc_deprecated) => {
-                                if !get(mi, &mut note) {
-                                    continue 'outer;
-                                }
-                            }
-                            sym::suggestion if sess.check_name(attr, sym::rustc_deprecated) => {
-                                if !get(mi, &mut suggestion) {
-                                    continue 'outer;
-                                }
-                            }
-                            _ => {
-                                handle_errors(
-                                    &sess.parse_sess,
-                                    meta.span(),
-                                    AttrError::UnknownMetaItem(
-                                        pprust::path_to_string(&mi.path),
-                                        if sess.check_name(attr, sym::deprecated) {
-                                            &["since", "note"]
-                                        } else {
-                                            &["since", "reason", "suggestion"]
-                                        },
-                                    ),
-                                );
-                                continue 'outer;
-                            }
-                        },
-                        NestedMetaItem::Literal(lit) => {
-                            handle_errors(
-                                &sess.parse_sess,
-                                lit.span,
-                                AttrError::UnsupportedLiteral(
-                                    "item in `deprecated` must be a key/value pair",
-                                    false,
-                                ),
-                            );
-                            continue 'outer;
-                        }
-                    }
-                }
-            }
-        }
-
-        if suggestion.is_some() && sess.check_name(attr, sym::deprecated) {
-            unreachable!("only allowed on rustc_deprecated")
-        }
-
-        if sess.check_name(attr, sym::rustc_deprecated) {
-            if since.is_none() {
-                handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
-                continue;
-            }
-
-            if note.is_none() {
-                struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'").emit();
-                continue;
-            }
-        }
-
-        sess.mark_attr_used(&attr);
-
-        let is_since_rustc_version = sess.check_name(attr, sym::rustc_deprecated);
-        depr = Some((Deprecation { since, note, suggestion, is_since_rustc_version }, attr.span));
-    }
-
-    depr
-}
-
-#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)]
-pub enum ReprAttr {
-    ReprInt(IntType),
-    ReprC,
-    ReprPacked(u32),
-    ReprSimd,
-    ReprTransparent,
-    ReprAlign(u32),
-    ReprNoNiche,
-}
-
-#[derive(Eq, PartialEq, Debug, Copy, Clone)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
-pub enum IntType {
-    SignedInt(ast::IntTy),
-    UnsignedInt(ast::UintTy),
-}
-
-impl IntType {
-    #[inline]
-    pub fn is_signed(self) -> bool {
-        use IntType::*;
-
-        match self {
-            SignedInt(..) => true,
-            UnsignedInt(..) => false,
-        }
-    }
-}
-
-/// Parse #[repr(...)] forms.
-///
-/// Valid repr contents: any of the primitive integral type names (see
-/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
-/// the same discriminant size that the corresponding C enum would or C
-/// structure layout, `packed` to remove padding, and `transparent` to elegate representation
-/// concerns to the only non-ZST field.
-pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec {
-    use ReprAttr::*;
-
-    let mut acc = Vec::new();
-    let diagnostic = &sess.parse_sess.span_diagnostic;
-    if attr.has_name(sym::repr) {
-        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() {
-                        sym::C => Some(ReprC),
-                        sym::packed => Some(ReprPacked(1)),
-                        sym::simd => Some(ReprSimd),
-                        sym::transparent => Some(ReprTransparent),
-                        sym::no_niche => Some(ReprNoNiche),
-                        name => int_type_of_word(name).map(ReprInt),
-                    };
-
-                    if let Some(h) = hint {
-                        recognised = true;
-                        acc.push(h);
-                    }
-                } else if let Some((name, value)) = item.name_value_literal() {
-                    let parse_alignment = |node: &ast::LitKind| -> Result {
-                        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;
-                        match parse_alignment(&value.kind) {
-                            Ok(literal) => acc.push(ReprAlign(literal)),
-                            Err(message) => literal_error = Some(message),
-                        };
-                    } else if name == sym::packed {
-                        recognised = true;
-                        match parse_alignment(&value.kind) {
-                            Ok(literal) => acc.push(ReprPacked(literal)),
-                            Err(message) => literal_error = Some(message),
-                        };
-                    }
-                    if let Some(literal_error) = literal_error {
-                        struct_span_err!(
-                            diagnostic,
-                            item.span(),
-                            E0589,
-                            "invalid `repr(align)` attribute: {}",
-                            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 {
-                            recognised = true;
-                            let mut err = struct_span_err!(
-                                diagnostic,
-                                item.span(),
-                                E0693,
-                                "incorrect `repr(align)` attribute format"
-                            );
-                            match value.kind {
-                                ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
-                                    err.span_suggestion(
-                                        item.span(),
-                                        "use parentheses instead",
-                                        format!("align({})", int),
-                                        Applicability::MachineApplicable,
-                                    );
-                                }
-                                ast::LitKind::Str(s, _) => {
-                                    err.span_suggestion(
-                                        item.span(),
-                                        "use parentheses instead",
-                                        format!("align({})", s),
-                                        Applicability::MachineApplicable,
-                                    );
-                                }
-                                _ => {}
-                            }
-                            err.emit();
-                        }
-                    }
-                }
-                if !recognised {
-                    // Not a word we recognize
-                    struct_span_err!(
-                        diagnostic,
-                        item.span(),
-                        E0552,
-                        "unrecognized representation hint"
-                    )
-                    .emit();
-                }
-            }
-        }
-    }
-    acc
-}
-
-fn int_type_of_word(s: Symbol) -> Option {
-    use IntType::*;
-
-    match s {
-        sym::i8 => Some(SignedInt(ast::IntTy::I8)),
-        sym::u8 => Some(UnsignedInt(ast::UintTy::U8)),
-        sym::i16 => Some(SignedInt(ast::IntTy::I16)),
-        sym::u16 => Some(UnsignedInt(ast::UintTy::U16)),
-        sym::i32 => Some(SignedInt(ast::IntTy::I32)),
-        sym::u32 => Some(UnsignedInt(ast::UintTy::U32)),
-        sym::i64 => Some(SignedInt(ast::IntTy::I64)),
-        sym::u64 => Some(UnsignedInt(ast::UintTy::U64)),
-        sym::i128 => Some(SignedInt(ast::IntTy::I128)),
-        sym::u128 => Some(UnsignedInt(ast::UintTy::U128)),
-        sym::isize => Some(SignedInt(ast::IntTy::Isize)),
-        sym::usize => Some(UnsignedInt(ast::UintTy::Usize)),
-        _ => None,
-    }
-}
-
-pub enum TransparencyError {
-    UnknownTransparency(Symbol, Span),
-    MultipleTransparencyAttrs(Span, Span),
-}
-
-pub fn find_transparency(
-    sess: &Session,
-    attrs: &[Attribute],
-    macro_rules: bool,
-) -> (Transparency, Option) {
-    let mut transparency = None;
-    let mut error = None;
-    for attr in attrs {
-        if sess.check_name(attr, sym::rustc_macro_transparency) {
-            if let Some((_, old_span)) = transparency {
-                error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span));
-                break;
-            } else if let Some(value) = attr.value_str() {
-                transparency = Some((
-                    match value {
-                        sym::transparent => Transparency::Transparent,
-                        sym::semitransparent => Transparency::SemiTransparent,
-                        sym::opaque => Transparency::Opaque,
-                        _ => {
-                            error = Some(TransparencyError::UnknownTransparency(value, attr.span));
-                            continue;
-                        }
-                    },
-                    attr.span,
-                ));
-            }
-        }
-    }
-    let fallback = if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque };
-    (transparency.map_or(fallback, |t| t.0), error)
-}
-
-pub fn allow_internal_unstable<'a>(
-    sess: &'a Session,
-    attrs: &'a [Attribute],
-) -> Option + 'a> {
-    allow_unstable(sess, attrs, sym::allow_internal_unstable)
-}
-
-pub fn rustc_allow_const_fn_unstable<'a>(
-    sess: &'a Session,
-    attrs: &'a [Attribute],
-) -> Option + 'a> {
-    allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
-}
-
-fn allow_unstable<'a>(
-    sess: &'a Session,
-    attrs: &'a [Attribute],
-    symbol: Symbol,
-) -> Option + 'a> {
-    let attrs = sess.filter_by_name(attrs, symbol);
-    let list = attrs
-        .filter_map(move |attr| {
-            attr.meta_item_list().or_else(|| {
-                sess.diagnostic().span_err(
-                    attr.span,
-                    &format!("`{}` expects a list of feature names", symbol.to_ident_string()),
-                );
-                None
-            })
-        })
-        .flatten();
-
-    Some(list.into_iter().filter_map(move |it| {
-        let name = it.ident().map(|ident| ident.name);
-        if name.is_none() {
-            sess.diagnostic().span_err(
-                it.span(),
-                &format!("`{}` expects feature names", symbol.to_ident_string()),
-            );
-        }
-        name
-    }))
-}
diff --git a/vendor/rustc-ap-rustc_attr/src/lib.rs b/vendor/rustc-ap-rustc_attr/src/lib.rs
deleted file mode 100644
index 149a950f7d..0000000000
--- a/vendor/rustc-ap-rustc_attr/src/lib.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//! Functions and types dealing with attributes and meta items.
-//!
-//! FIXME(Centril): For now being, much of the logic is still in `rustc_ast::attr`.
-//! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
-//! to this crate.
-
-#![feature(or_patterns)]
-
-#[macro_use]
-extern crate rustc_macros;
-
-mod builtin;
-
-pub use builtin::*;
-pub use IntType::*;
-pub use ReprAttr::*;
-pub use StabilityLevel::*;
-
-pub use rustc_ast::attr::*;
-
-pub(crate) use rustc_ast::HashStableContext;
diff --git a/vendor/rustc-ap-rustc_data_structures/.cargo-checksum.json b/vendor/rustc-ap-rustc_data_structures/.cargo-checksum.json
deleted file mode 100644
index 6c6143cda7..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"74bf1bfa61e7ae92140ce076dcde47fbdde9daada439182605e86e701f361b4b","src/atomic_ref.rs":"9fec5fd1b7c9b8ff668dd7533faec22e9ccfc505bf863f88d5f85e5dad828e66","src/base_n.rs":"1dc24b9f7f5973016366b8c4f6f3cb726f9ea69281ebee7ade2fdd4f3fb4159b","src/base_n/tests.rs":"0df677566f9499e5599c9b61d25f8e607c02fa9c9f5f8847401bd4daa8e90efa","src/binary_search_util/mod.rs":"bb27cbca82ced0e1f2cbc3dc1c6eb6e80d61b1c68164686028f3b6cf4b971a9e","src/binary_search_util/tests.rs":"6439fcec412b6c59802000c946aa3cd6c493df11dcfb465cf187a5e97f6fd10b","src/box_region.rs":"78ef2275b052f26bae6fad4a91513e1ee071d2ac3620371a993e81dbd9bca239","src/captures.rs":"1db1dbad2d75e5e28960d20fdbbcd753cbcfb64526ccbe972d8a5c1d6c7a482a","src/const_cstr.rs":"c7caf3a0a072cf1677e935e095c6e71015b1e60f9add22d156271c7eb302e188","src/fingerprint.rs":"50a63462a05af0950aeba41ee6998706dced95e6f3317ab292507b1b2f55fa00","src/flock.rs":"97dd27dd88664123b3ccc087e37dd82fc6452bab9e7420a84a71beffed1c88b9","src/frozen.rs":"8c34ca935f1bb5466a9cfd1a5dbe788980591ee615739397bbb8c231ee38269f","src/functor.rs":"a5c37570f2113e0fe0eaf564768fe8629fac2a281c23bc49d2894a6067ada783","src/fx.rs":"d09fc5ebe02175674bca64cb153e96d6d750cbcb355ede3ecab8f2029515f663","src/graph/dominators/mod.rs":"3e6ee1ff4c6c63f88945140794cf4c78a4065380a53e5f938f3f1c49187a9d9d","src/graph/dominators/tests.rs":"395184b44fb2a82a6257cf0b6d0f60212d34364fcef28e59569f87ef00027fa5","src/graph/implementation/mod.rs":"fecf74cb5b16a0afa458d90d125effa1752737588c905294802c25c6c2d84b15","src/graph/implementation/tests.rs":"2c04913e9c6897161ad5ad0893ef95d9b33678810af930cbe9e1fd03c6ad23e5","src/graph/iterate/mod.rs":"ad7237f64dd3d2d90fe49b26b6116221f925a136cb874316f82e60249ba6ee12","src/graph/iterate/tests.rs":"4b12309f393ab16461ef580cd14270049b4a377721ab3f7f9d657bfe4b7b378b","src/graph/mod.rs":"c379b2241543669c0a3c74b253c46de29aa04f0efcdfa103cb664417fff9dcc7","src/graph/reference.rs":"072df8327c9d45190ed36d12e633c67721b206c87769eee240e22a53544156f3","src/graph/scc/mod.rs":"5b5efb84b4c145892273ed02b382dd0dcd13e542c515f1a09a928e9bd5255b45","src/graph/scc/tests.rs":"beead673cd259183cd418d076ba883966e72b73fb0d0ab60c326c4fbbf78aa09","src/graph/tests.rs":"2dea15b9cb2c1d40554e45f3851544af53b2d4c93c391b69731a1190a3ee99c0","src/graph/vec_graph/mod.rs":"f4fc46bdc9e6894d67a6e865e4e7f8f9a47a11d363a80a84a1e5996a2a8477e3","src/graph/vec_graph/tests.rs":"037d4d7156b4cc8b39f8f34969ac122e56acf47246bdf0da37b919f8cd75274f","src/jobserver.rs":"7554f60c3d94092ef127fc0764cf17cf84383c8529379075e559a12c693a4733","src/lib.rs":"42e98297237bd30a399aeff226c33cf6758e288028a2ead86553e781e2336bbd","src/macros.rs":"30a89e009fde440754c3cc858d53e00ebde750b06b72986069e03e3c94ee103c","src/map_in_place.rs":"53cfe775155dd59e500b9f3f18e943b71927a9496639edef4666a99a96460946","src/obligation_forest/graphviz.rs":"1f38cbef72141554d48817eaf4fcec35c81a66a70b785bfec8ab6ee10f8fd386","src/obligation_forest/mod.rs":"863e3521939abc7d99b2659ab5aaa462c3c6e2e47159c9298c029d9f00d2a3d4","src/obligation_forest/tests.rs":"68aaaf48d3e3aaea10ce483431695b87fcca42ab6f468bf3e81f2d6e8b1e63db","src/owning_ref/LICENSE":"90bc15ed094593083fd129fdd1a03607be80fe8839c5564616a5961ab7f7a194","src/owning_ref/mod.rs":"8b486b5e9944512f82c12e30baa48f86c32c56e0c652ac8ae8fb2a28f787c137","src/owning_ref/tests.rs":"51a81ea31dcfc9c9d968913e772cb4afa73f78e4c8f379e8e4144189bfd13fce","src/profiling.rs":"6f180d48ecccc404041840e6d81d6ad2671a78b17e0e7896e7514e1288c6c5e7","src/ptr_key.rs":"d833f9b3b9d09bb059cfda820af65dcfa2310225fbe868f63bae160cf6b93610","src/sharded.rs":"5910d4d2fb72ac07f61b91222a44441af3ab83db28b89756677d593affbe820c","src/sip128.rs":"c34b5cf2bfccf3a161feffc78c63175c0e636c9d2577b00b99cc6dc6d7921e6c","src/sip128/tests.rs":"b71d0f4e3911c4d034c593e74ad17d64f38fe5cb67859636f6724d18290403de","src/small_c_str.rs":"26b3a631a7a0afaa64dd3547d0bfeaba2c2c284bde8a11df541ddd81d4021bc8","src/small_c_str/tests.rs":"06f29dca2eaf0f888ff002c6bc2003e323b3b4cd2e8db161b09d27c8608f22e4","src/snapshot_map/mod.rs":"8731ebe725ef4b18ac93aa721d7b956ecb1f75bae5f11f801da72fc6283efc99","src/snapshot_map/tests.rs":"c9c378d3ca16f24f72e90fe39965e97556824f487c0e62a69551177c030902b7","src/sorted_map.rs":"bc9b2566cd7150cffb79e31472d03903fe24e8f0ed2a85275bc880bdef3433d0","src/sorted_map/index_map.rs":"48c3aaa7ea5bea0d668eae26ff8e0232a341889d216e20fbc1f509462dd6cccd","src/sorted_map/tests.rs":"a40a13a48a8fd37d15da97fa36c9f156a47bf522b2bc5bc560b3d7e820b5bb62","src/sso/either_iter.rs":"ad045f110cf0592509f05f1c3e9014be41ff393e7056e96cf4e0ed29667f3657","src/sso/map.rs":"db937a9cd1b6fa6312b142df2faf8139912f41a230dd277e81ade920dc3678ee","src/sso/mod.rs":"68ba92d6f85940838a686d987f2baddee75fdcdb6a7341fe15cbdb989647f348","src/sso/set.rs":"22e035b07c95c9fd8d14b14759a58b364aa34e20948b61e5a6da7ac0f56c9bf2","src/stable_hasher.rs":"973a00bcf16a78694f4cbad83bf5268313623fb9382ec53a7f95a7a3389ca7b6","src/stable_hasher/tests.rs":"8ef1579f546fe82f94afee79e5d75ab0f454a1484404cb27c9cb4d27cac142cd","src/stable_map.rs":"1f54d6e2601a32464383d673849064dc4e7b3d89b31bab14eaf363bf50869e38","src/stable_set.rs":"e13fc37d6c14f6570b474e4dfd65a3d2b2eb41d2d34579ee0460c4c6b49a952a","src/stack.rs":"2087e7aec2bb3152bd3b04c95577f2f444ff4f82eb58846c1445ab9dd9d3e6f3","src/steal.rs":"63638debcfbd621e0aeb8235c73afabc0a4503b3bba8ea8d14fad0b701ee8fdb","src/svh.rs":"6ff1b3fdaae1ffe56127ff08cfb57a6f8b48b4688989fb18c2ad86cfa985a23f","src/sync.rs":"d9c94bc85ad8bb72f9ae03fedfdc8962c888d7f36d6bb38b9ba659df3dbefadf","src/tagged_ptr.rs":"453f1bec79fd51d866749cb035117a2c253fc8cafa2b03819daf250f6e571411","src/tagged_ptr/copy.rs":"de2a73efcaa38ceec8fe3f7d58cb9414324749564f8c8ea372e533afce02f7ce","src/tagged_ptr/drop.rs":"2de5f57a166ff8ba230bbf1c4006a3c700eba830a2c5d1aab4ce0cb19894e11e","src/temp_dir.rs":"7aa79c0e102fb17f4725b80fd4a2e90999fba19120bb9ed2b12e07bcdf944bfa","src/thin_vec.rs":"0a52b88a6d9b225005579b473fbac3bd0f05d617d6799987ede63d80cab9c94e","src/tiny_list.rs":"5fe0e32a66acacb1071550f9ca3319216f117c0782172fee31f18462e2bebe12","src/tiny_list/tests.rs":"8a382ce1ff3e832f70ecdd3d80648907623880c1fea0c39ae212fef651596e31","src/transitive_relation.rs":"a9a9e43c1a5b38799b6569ade7628c6c1f85f991996e98020888e260173a3300","src/transitive_relation/tests.rs":"7bf1712c70ac2c69076d2735d1a5319efcec445a8e7633b6969377986708b8c8","src/unhash.rs":"3b915c3b8c777be97d11ff4574cf8a2c2b84e1ca55c5e55b65a3165714d291f1","src/vec_linked_list.rs":"1e41c3ec3b57b24bd899da6132c6ad8ff6af6ccbd4f5a0ea707adc1aed3a5e0a","src/work_queue.rs":"500269078c0b4e63f10863225b235155b75eac11d67f8294fe13a41eab3290dc"},"package":"5d840c4e6198b57982a54543ae604d634c7ceb7107f0c75970b88ebaff077ac5"}
\ No newline at end of file
diff --git a/vendor/rustc-ap-rustc_data_structures/Cargo.toml b/vendor/rustc-ap-rustc_data_structures/Cargo.toml
deleted file mode 100644
index 38402a2528..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/Cargo.toml
+++ /dev/null
@@ -1,102 +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 = "rustc-ap-rustc_data_structures"
-version = "705.0.0"
-authors = ["The Rust Project Developers"]
-description = "Automatically published version of the package `rustc_data_structures` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n            "
-license = "MIT / Apache-2.0"
-repository = "https://github.com/rust-lang/rust"
-
-[lib]
-doctest = false
-[dependencies.arrayvec]
-version = "0.5.1"
-default-features = false
-
-[dependencies.bitflags]
-version = "1.2.1"
-
-[dependencies.cfg-if]
-version = "0.1.2"
-
-[dependencies.crossbeam-utils]
-version = "0.7"
-features = ["nightly"]
-
-[dependencies.ena]
-version = "0.14"
-
-[dependencies.indexmap]
-version = "1.5.1"
-
-[dependencies.jobserver_crate]
-version = "0.1.13"
-package = "jobserver"
-
-[dependencies.libc]
-version = "0.2"
-
-[dependencies.measureme]
-version = "9.0.0"
-
-[dependencies.parking_lot]
-version = "0.11"
-features = ["nightly"]
-
-[dependencies.rayon]
-version = "0.3.0"
-package = "rustc-rayon"
-
-[dependencies.rayon-core]
-version = "0.3.0"
-package = "rustc-rayon-core"
-
-[dependencies.rustc-hash]
-version = "1.1.0"
-
-[dependencies.rustc_graphviz]
-version = "705.0.0"
-package = "rustc-ap-rustc_graphviz"
-
-[dependencies.rustc_index]
-version = "705.0.0"
-package = "rustc-ap-rustc_index"
-
-[dependencies.rustc_macros]
-version = "705.0.0"
-package = "rustc-ap-rustc_macros"
-
-[dependencies.rustc_serialize]
-version = "705.0.0"
-package = "rustc-ap-rustc_serialize"
-
-[dependencies.smallvec]
-version = "1.0"
-features = ["union", "may_dangle"]
-
-[dependencies.stable_deref_trait]
-version = "1.0.0"
-
-[dependencies.stacker]
-version = "0.1.12"
-
-[dependencies.tempfile]
-version = "3.0.5"
-
-[dependencies.tracing]
-version = "0.1"
-[target."cfg(windows)".dependencies.winapi]
-version = "0.3"
-features = ["fileapi", "psapi"]
diff --git a/vendor/rustc-ap-rustc_data_structures/src/atomic_ref.rs b/vendor/rustc-ap-rustc_data_structures/src/atomic_ref.rs
deleted file mode 100644
index eeb1b30925..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/atomic_ref.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use std::marker::PhantomData;
-use std::sync::atomic::{AtomicPtr, Ordering};
-
-/// This is essentially an `AtomicPtr` but is guaranteed to always be valid
-pub struct AtomicRef(AtomicPtr, PhantomData<&'static T>);
-
-impl AtomicRef {
-    pub const fn new(initial: &'static T) -> AtomicRef {
-        AtomicRef(AtomicPtr::new(initial as *const T as *mut T), PhantomData)
-    }
-
-    pub fn swap(&self, new: &'static T) -> &'static T {
-        // We never allow storing anything but a `'static` reference so it's safe to
-        // return it for the same.
-        unsafe { &*self.0.swap(new as *const T as *mut T, Ordering::SeqCst) }
-    }
-}
-
-impl std::ops::Deref for AtomicRef {
-    type Target = T;
-    fn deref(&self) -> &Self::Target {
-        // We never allow storing anything but a `'static` reference so it's safe to lend
-        // it out for any amount of time.
-        unsafe { &*self.0.load(Ordering::SeqCst) }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/base_n.rs b/vendor/rustc-ap-rustc_data_structures/src/base_n.rs
deleted file mode 100644
index 3c7bea2712..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/base_n.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-/// Converts unsigned integers into a string representation with some base.
-/// Bases up to and including 36 can be used for case-insensitive things.
-use std::str;
-
-#[cfg(test)]
-mod tests;
-
-pub const MAX_BASE: usize = 64;
-pub const ALPHANUMERIC_ONLY: usize = 62;
-pub const CASE_INSENSITIVE: usize = 36;
-
-const BASE_64: &[u8; MAX_BASE as usize] =
-    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
-
-#[inline]
-pub fn push_str(mut n: u128, base: usize, output: &mut String) {
-    debug_assert!(base >= 2 && base <= MAX_BASE);
-    let mut s = [0u8; 128];
-    let mut index = 0;
-
-    let base = base as u128;
-
-    loop {
-        s[index] = BASE_64[(n % base) as usize];
-        index += 1;
-        n /= base;
-
-        if n == 0 {
-            break;
-        }
-    }
-    s[0..index].reverse();
-
-    output.push_str(str::from_utf8(&s[0..index]).unwrap());
-}
-
-#[inline]
-pub fn encode(n: u128, base: usize) -> String {
-    let mut s = String::new();
-    push_str(n, base, &mut s);
-    s
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/base_n/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/base_n/tests.rs
deleted file mode 100644
index b68ef1eb7f..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/base_n/tests.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use super::*;
-
-#[test]
-fn test_encode() {
-    fn test(n: u128, base: usize) {
-        assert_eq!(Ok(n), u128::from_str_radix(&encode(n, base), base as u32));
-    }
-
-    for base in 2..37 {
-        test(0, base);
-        test(1, base);
-        test(35, base);
-        test(36, base);
-        test(37, base);
-        test(u64::MAX as u128, base);
-        test(u128::MAX, base);
-
-        for i in 0..1_000 {
-            test(i * 983, base);
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/binary_search_util/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/binary_search_util/mod.rs
deleted file mode 100644
index ede5757a47..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/binary_search_util/mod.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-#[cfg(test)]
-mod tests;
-
-/// Uses a sorted slice `data: &[E]` as a kind of "multi-map". The
-/// `key_fn` extracts a key of type `K` from the data, and this
-/// function finds the range of elements that match the key. `data`
-/// must have been sorted as if by a call to `sort_by_key` for this to
-/// work.
-pub fn binary_search_slice(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E]
-where
-    K: Ord,
-{
-    let mid = match data.binary_search_by_key(key, &key_fn) {
-        Ok(mid) => mid,
-        Err(_) => return &[],
-    };
-    let size = data.len();
-
-    // We get back *some* element with the given key -- so do
-    // a galloping search backwards to find the *first* one.
-    let mut start = mid;
-    let mut previous = mid;
-    let mut step = 1;
-    loop {
-        start = start.saturating_sub(step);
-        if start == 0 || key_fn(&data[start]) != *key {
-            break;
-        }
-        previous = start;
-        step *= 2;
-    }
-    step = previous - start;
-    while step > 1 {
-        let half = step / 2;
-        let mid = start + half;
-        if key_fn(&data[mid]) != *key {
-            start = mid;
-        }
-        step -= half;
-    }
-    // adjust by one if we have overshot
-    if start < size && key_fn(&data[start]) != *key {
-        start += 1;
-    }
-
-    // Now search forward to find the *last* one.
-    let mut end = mid;
-    let mut previous = mid;
-    let mut step = 1;
-    loop {
-        end = end.saturating_add(step).min(size);
-        if end == size || key_fn(&data[end]) != *key {
-            break;
-        }
-        previous = end;
-        step *= 2;
-    }
-    step = end - previous;
-    while step > 1 {
-        let half = step / 2;
-        let mid = end - half;
-        if key_fn(&data[mid]) != *key {
-            end = mid;
-        }
-        step -= half;
-    }
-
-    &data[start..end]
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/binary_search_util/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/binary_search_util/tests.rs
deleted file mode 100644
index d74febb5c0..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/binary_search_util/tests.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use super::*;
-
-type Element = (usize, &'static str);
-
-fn test_map() -> Vec {
-    let mut data = vec![(3, "three-a"), (0, "zero"), (3, "three-b"), (22, "twenty-two")];
-    data.sort_by_key(get_key);
-    data
-}
-
-fn get_key(data: &Element) -> usize {
-    data.0
-}
-
-#[test]
-fn binary_search_slice_test() {
-    let map = test_map();
-    assert_eq!(binary_search_slice(&map, get_key, &0), &[(0, "zero")]);
-    assert_eq!(binary_search_slice(&map, get_key, &1), &[]);
-    assert_eq!(binary_search_slice(&map, get_key, &3), &[(3, "three-a"), (3, "three-b")]);
-    assert_eq!(binary_search_slice(&map, get_key, &22), &[(22, "twenty-two")]);
-    assert_eq!(binary_search_slice(&map, get_key, &23), &[]);
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/box_region.rs b/vendor/rustc-ap-rustc_data_structures/src/box_region.rs
deleted file mode 100644
index eb6f4e8213..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/box_region.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-//! This module provides a way to deal with self-referential data.
-//!
-//! The main idea is to allocate such data in a generator frame and then
-//! give access to it by executing user-provided closures inside that generator.
-//! The module provides a safe abstraction for the latter task.
-//!
-//! The interface consists of two exported macros meant to be used together:
-//! * `declare_box_region_type` wraps a generator inside a struct with `access`
-//!   method which accepts closures.
-//! * `box_region_allow_access` is a helper which should be called inside
-//!   a generator to actually execute those closures.
-
-use std::marker::PhantomData;
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-#[derive(Copy, Clone)]
-pub struct AccessAction(*mut dyn FnMut());
-
-impl AccessAction {
-    pub fn get(self) -> *mut dyn FnMut() {
-        self.0
-    }
-}
-
-#[derive(Copy, Clone)]
-pub enum Action {
-    Initial,
-    Access(AccessAction),
-    Complete,
-}
-
-pub struct PinnedGenerator {
-    generator: Pin, Return = R>>>,
-}
-
-impl PinnedGenerator {
-    pub fn new, Return = R> + 'static>(
-        generator: T,
-    ) -> (I, Self) {
-        let mut result = PinnedGenerator { generator: Box::pin(generator) };
-
-        // Run it to the first yield to set it up
-        let init = match Pin::new(&mut result.generator).resume(Action::Initial) {
-            GeneratorState::Yielded(YieldType::Initial(y)) => y,
-            _ => panic!(),
-        };
-
-        (init, result)
-    }
-
-    pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
-        // Call the generator, which in turn will call the closure
-        if let GeneratorState::Complete(_) =
-            Pin::new(&mut self.generator).resume(Action::Access(AccessAction(closure)))
-        {
-            panic!()
-        }
-    }
-
-    pub fn complete(&mut self) -> R {
-        // Tell the generator we want it to complete, consuming it and yielding a result
-        let result = Pin::new(&mut self.generator).resume(Action::Complete);
-        if let GeneratorState::Complete(r) = result { r } else { panic!() }
-    }
-}
-
-#[derive(PartialEq)]
-pub struct Marker(PhantomData);
-
-impl Marker {
-    pub unsafe fn new() -> Self {
-        Marker(PhantomData)
-    }
-}
-
-pub enum YieldType {
-    Initial(I),
-    Accessor(Marker),
-}
-
-#[macro_export]
-#[allow_internal_unstable(fn_traits)]
-macro_rules! declare_box_region_type {
-    (impl $v:vis
-     $name: ident,
-     $yield_type:ty,
-     for($($lifetimes:tt)*),
-     ($($args:ty),*) -> ($reti:ty, $retc:ty)
-    ) => {
-        $v struct $name($crate::box_region::PinnedGenerator<
-            $reti,
-            for<$($lifetimes)*> fn(($($args,)*)),
-            $retc
-        >);
-
-        impl $name {
-            fn new + 'static>(
-                generator: T
-            ) -> ($reti, Self) {
-                let (initial, pinned) = $crate::box_region::PinnedGenerator::new(generator);
-                (initial, $name(pinned))
-            }
-
-            $v fn access FnOnce($($args,)*) -> R, R>(&mut self, f: F) -> R {
-                // Turn the FnOnce closure into *mut dyn FnMut()
-                // so we can pass it in to the generator
-                let mut r = None;
-                let mut f = Some(f);
-                let mut_f: &mut dyn for<$($lifetimes)*> FnMut(($($args,)*)) =
-                    &mut |args| {
-                        let f = f.take().unwrap();
-                        r = Some(FnOnce::call_once(f, args));
-                };
-                let mut_f = mut_f as *mut dyn for<$($lifetimes)*> FnMut(($($args,)*));
-
-                // Get the generator to call our closure
-                unsafe {
-                    self.0.access(::std::mem::transmute(mut_f));
-                }
-
-                // Unwrap the result
-                r.unwrap()
-            }
-
-            $v fn complete(mut self) -> $retc {
-                self.0.complete()
-            }
-
-            fn initial_yield(value: $reti) -> $yield_type {
-                $crate::box_region::YieldType::Initial(value)
-            }
-        }
-    };
-
-    ($v:vis $name: ident, for($($lifetimes:tt)*), ($($args:ty),*) -> ($reti:ty, $retc:ty)) => {
-        declare_box_region_type!(
-            impl $v $name,
-            $crate::box_region::YieldType<$reti, for<$($lifetimes)*> fn(($($args,)*))>,
-            for($($lifetimes)*),
-            ($($args),*) -> ($reti, $retc)
-        );
-    };
-}
-
-#[macro_export]
-#[allow_internal_unstable(fn_traits)]
-macro_rules! box_region_allow_access {
-    (for($($lifetimes:tt)*), ($($args:ty),*), ($($exprs:expr),*), $action:ident) => {
-        loop {
-            match $action {
-                $crate::box_region::Action::Access(accessor) => {
-                    let accessor: &mut dyn for<$($lifetimes)*> FnMut($($args),*) = unsafe {
-                        ::std::mem::transmute(accessor.get())
-                    };
-                    (*accessor)(($($exprs),*));
-                    unsafe {
-                        let marker = $crate::box_region::Marker::<
-                            for<$($lifetimes)*> fn(($($args,)*))
-                        >::new();
-                        $action = yield $crate::box_region::YieldType::Accessor(marker);
-                    };
-                }
-                $crate::box_region::Action::Complete => break,
-                $crate::box_region::Action::Initial => panic!("unexpected box_region action: Initial"),
-            }
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/captures.rs b/vendor/rustc-ap-rustc_data_structures/src/captures.rs
deleted file mode 100644
index 26b90ebfd5..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/captures.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-/// "Signaling" trait used in impl trait to tag lifetimes that you may
-/// need to capture but don't really need for other reasons.
-/// 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 {}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/const_cstr.rs b/vendor/rustc-ap-rustc_data_structures/src/const_cstr.rs
deleted file mode 100644
index 1ebcb87818..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/const_cstr.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-/// This macro creates a zero-overhead &CStr by adding a NUL terminator to
-/// the string literal passed into it at compile-time. Use it like:
-///
-/// ```
-///     let some_const_cstr = const_cstr!("abc");
-/// ```
-///
-/// The above is roughly equivalent to:
-///
-/// ```
-///     let some_const_cstr = CStr::from_bytes_with_nul(b"abc\0").unwrap()
-/// ```
-///
-/// Note that macro only checks the string literal for internal NULs if
-/// debug-assertions are enabled in order to avoid runtime overhead in release
-/// builds.
-#[macro_export]
-macro_rules! const_cstr {
-    ($s:expr) => {{
-        use std::ffi::CStr;
-
-        let str_plus_nul = concat!($s, "\0");
-
-        if cfg!(debug_assertions) {
-            CStr::from_bytes_with_nul(str_plus_nul.as_bytes()).unwrap()
-        } else {
-            unsafe { CStr::from_bytes_with_nul_unchecked(str_plus_nul.as_bytes()) }
-        }
-    }};
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/fingerprint.rs b/vendor/rustc-ap-rustc_data_structures/src/fingerprint.rs
deleted file mode 100644
index 08c3419a84..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/fingerprint.rs
+++ /dev/null
@@ -1,219 +0,0 @@
-use crate::stable_hasher;
-use rustc_serialize::{
-    opaque::{self, EncodeResult, FileEncodeResult},
-    Decodable, Encodable,
-};
-use std::hash::{Hash, Hasher};
-use std::mem::{self, MaybeUninit};
-
-#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
-pub struct Fingerprint(u64, u64);
-
-impl Fingerprint {
-    pub const ZERO: Fingerprint = Fingerprint(0, 0);
-
-    #[inline]
-    pub fn from_smaller_hash(hash: u64) -> Fingerprint {
-        Fingerprint(hash, hash)
-    }
-
-    #[inline]
-    pub fn to_smaller_hash(&self) -> u64 {
-        self.0
-    }
-
-    #[inline]
-    pub fn as_value(&self) -> (u64, u64) {
-        (self.0, self.1)
-    }
-
-    #[inline]
-    pub fn combine(self, other: Fingerprint) -> Fingerprint {
-        // See https://stackoverflow.com/a/27952689 on why this function is
-        // implemented this way.
-        Fingerprint(
-            self.0.wrapping_mul(3).wrapping_add(other.0),
-            self.1.wrapping_mul(3).wrapping_add(other.1),
-        )
-    }
-
-    // Combines two hashes in an order independent way. Make sure this is what
-    // you want.
-    #[inline]
-    pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
-        let a = u128::from(self.1) << 64 | u128::from(self.0);
-        let b = u128::from(other.1) << 64 | u128::from(other.0);
-
-        let c = a.wrapping_add(b);
-
-        Fingerprint((c >> 64) as u64, c as u64)
-    }
-
-    pub fn to_hex(&self) -> String {
-        format!("{:x}{:x}", self.0, self.1)
-    }
-
-    pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result {
-        let mut bytes: [MaybeUninit; 16] = MaybeUninit::uninit_array();
-
-        decoder.read_raw_bytes(&mut bytes)?;
-
-        let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
-
-        Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
-    }
-}
-
-impl std::fmt::Display for Fingerprint {
-    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(formatter, "{:x}-{:x}", self.0, self.1)
-    }
-}
-
-impl Hash for Fingerprint {
-    #[inline]
-    fn hash(&self, state: &mut H) {
-        state.write_fingerprint(self);
-    }
-}
-
-trait FingerprintHasher {
-    fn write_fingerprint(&mut self, fingerprint: &Fingerprint);
-}
-
-impl FingerprintHasher for H {
-    #[inline]
-    default fn write_fingerprint(&mut self, fingerprint: &Fingerprint) {
-        self.write_u64(fingerprint.0);
-        self.write_u64(fingerprint.1);
-    }
-}
-
-impl FingerprintHasher for crate::unhash::Unhasher {
-    #[inline]
-    fn write_fingerprint(&mut self, fingerprint: &Fingerprint) {
-        // `Unhasher` only wants a single `u64`
-        self.write_u64(fingerprint.0);
-    }
-}
-
-impl stable_hasher::StableHasherResult for Fingerprint {
-    #[inline]
-    fn finish(hasher: stable_hasher::StableHasher) -> Self {
-        let (_0, _1) = hasher.finalize();
-        Fingerprint(_0, _1)
-    }
-}
-
-impl_stable_hash_via_hash!(Fingerprint);
-
-impl Encodable for Fingerprint {
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.encode_fingerprint(self)
-    }
-}
-
-impl Decodable for Fingerprint {
-    fn decode(d: &mut D) -> Result {
-        d.decode_fingerprint()
-    }
-}
-
-pub trait FingerprintEncoder: rustc_serialize::Encoder {
-    fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>;
-}
-
-pub trait FingerprintDecoder: rustc_serialize::Decoder {
-    fn decode_fingerprint(&mut self) -> Result;
-}
-
-impl FingerprintEncoder for E {
-    default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> {
-        panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::());
-    }
-}
-
-impl FingerprintEncoder for opaque::Encoder {
-    fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult {
-        let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) };
-        self.emit_raw_bytes(&bytes);
-        Ok(())
-    }
-}
-
-impl FingerprintEncoder for opaque::FileEncoder {
-    fn encode_fingerprint(&mut self, f: &Fingerprint) -> FileEncodeResult {
-        let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) };
-        self.emit_raw_bytes(&bytes)
-    }
-}
-
-impl FingerprintDecoder for D {
-    default fn decode_fingerprint(&mut self) -> Result {
-        panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::());
-    }
-}
-
-impl FingerprintDecoder for opaque::Decoder<'_> {
-    fn decode_fingerprint(&mut self) -> Result {
-        Fingerprint::decode_opaque(self)
-    }
-}
-
-// `PackedFingerprint` wraps a `Fingerprint`. Its purpose is to, on certain
-// architectures, behave like a `Fingerprint` without alignment requirements.
-// This behavior is only enabled on x86 and x86_64, where the impact of
-// unaligned accesses is tolerable in small doses.
-//
-// This may be preferable to use in large collections of structs containing
-// fingerprints, as it can reduce memory consumption by preventing the padding
-// that the more strictly-aligned `Fingerprint` can introduce. An application of
-// this is in the query dependency graph, which contains a large collection of
-// `DepNode`s. As of this writing, the size of a `DepNode` decreases by ~30%
-// (from 24 bytes to 17) by using the packed representation here, which
-// noticeably decreases total memory usage when compiling large crates.
-//
-// The wrapped `Fingerprint` is private to reduce the chance of a client
-// invoking undefined behavior by taking a reference to the packed field.
-#[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))]
-#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
-pub struct PackedFingerprint(Fingerprint);
-
-impl std::fmt::Display for PackedFingerprint {
-    #[inline]
-    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        // Copy to avoid taking reference to packed field.
-        let copy = self.0;
-        copy.fmt(formatter)
-    }
-}
-
-impl Encodable for PackedFingerprint {
-    #[inline]
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        // Copy to avoid taking reference to packed field.
-        let copy = self.0;
-        copy.encode(s)
-    }
-}
-
-impl Decodable for PackedFingerprint {
-    #[inline]
-    fn decode(d: &mut D) -> Result {
-        Fingerprint::decode(d).map(PackedFingerprint)
-    }
-}
-
-impl From for PackedFingerprint {
-    #[inline]
-    fn from(f: Fingerprint) -> PackedFingerprint {
-        PackedFingerprint(f)
-    }
-}
-
-impl From for Fingerprint {
-    #[inline]
-    fn from(f: PackedFingerprint) -> Fingerprint {
-        f.0
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/flock.rs b/vendor/rustc-ap-rustc_data_structures/src/flock.rs
deleted file mode 100644
index 9383be474f..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/flock.rs
+++ /dev/null
@@ -1,214 +0,0 @@
-//! Simple file-locking apis for each OS.
-//!
-//! This is not meant to be in the standard library, it does nothing with
-//! green/native threading. This is just a bare-bones enough solution for
-//! librustdoc, it is not production quality at all.
-
-#![allow(non_camel_case_types)]
-#![allow(nonstandard_style)]
-
-use std::fs::{File, OpenOptions};
-use std::io;
-use std::path::Path;
-
-cfg_if! {
-    // We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
-    // `fcntl`-style advisory locks properly (rust-lang/rust#72157).
-    //
-    // For other Unix targets we still use `fcntl` because it's more portable than
-    // `flock`.
-    if #[cfg(target_os = "linux")] {
-        use std::os::unix::prelude::*;
-
-        #[derive(Debug)]
-        pub struct Lock {
-            _file: File,
-        }
-
-        impl Lock {
-            pub fn new(p: &Path,
-                       wait: bool,
-                       create: bool,
-                       exclusive: bool)
-                       -> io::Result {
-                let file = OpenOptions::new()
-                    .read(true)
-                    .write(true)
-                    .create(create)
-                    .mode(libc::S_IRWXU as u32)
-                    .open(p)?;
-
-                let mut operation = if exclusive {
-                    libc::LOCK_EX
-                } else {
-                    libc::LOCK_SH
-                };
-                if !wait {
-                    operation |= libc::LOCK_NB
-                }
-
-                let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
-                if ret == -1 {
-                    Err(io::Error::last_os_error())
-                } else {
-                    Ok(Lock { _file: file })
-                }
-            }
-        }
-
-        // Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
-        // `flock` is associated with the file descriptor and closing the file release it
-        // automatically.
-    } else if #[cfg(unix)] {
-        use std::mem;
-        use std::os::unix::prelude::*;
-
-        #[derive(Debug)]
-        pub struct Lock {
-            file: File,
-        }
-
-        impl Lock {
-            pub fn new(p: &Path,
-                       wait: bool,
-                       create: bool,
-                       exclusive: bool)
-                       -> io::Result {
-                let file = OpenOptions::new()
-                    .read(true)
-                    .write(true)
-                    .create(create)
-                    .mode(libc::S_IRWXU as u32)
-                    .open(p)?;
-
-                let lock_type = if exclusive {
-                    libc::F_WRLCK
-                } else {
-                    libc::F_RDLCK
-                };
-
-                let mut flock: libc::flock = unsafe { mem::zeroed() };
-                flock.l_type = lock_type as libc::c_short;
-                flock.l_whence = libc::SEEK_SET as libc::c_short;
-                flock.l_start = 0;
-                flock.l_len = 0;
-
-                let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
-                let ret = unsafe {
-                    libc::fcntl(file.as_raw_fd(), cmd, &flock)
-                };
-                if ret == -1 {
-                    Err(io::Error::last_os_error())
-                } else {
-                    Ok(Lock { file })
-                }
-            }
-        }
-
-        impl Drop for Lock {
-            fn drop(&mut self) {
-                let mut flock: libc::flock = unsafe { mem::zeroed() };
-                flock.l_type = libc::F_UNLCK as libc::c_short;
-                flock.l_whence = libc::SEEK_SET as libc::c_short;
-                flock.l_start = 0;
-                flock.l_len = 0;
-
-                unsafe {
-                    libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
-                }
-            }
-        }
-    } else if #[cfg(windows)] {
-        use std::mem;
-        use std::os::windows::prelude::*;
-
-        use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
-        use winapi::um::fileapi::LockFileEx;
-        use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
-
-        #[derive(Debug)]
-        pub struct Lock {
-            _file: File,
-        }
-
-        impl Lock {
-            pub fn new(p: &Path,
-                       wait: bool,
-                       create: bool,
-                       exclusive: bool)
-                       -> io::Result {
-                assert!(p.parent().unwrap().exists(),
-                    "Parent directory of lock-file must exist: {}",
-                    p.display());
-
-                let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-
-                let mut open_options = OpenOptions::new();
-                open_options.read(true)
-                            .share_mode(share_mode);
-
-                if create {
-                    open_options.create(true)
-                                .write(true);
-                }
-
-                debug!("attempting to open lock file `{}`", p.display());
-                let file = match open_options.open(p) {
-                    Ok(file) => {
-                        debug!("lock file opened successfully");
-                        file
-                    }
-                    Err(err) => {
-                        debug!("error opening lock file: {}", err);
-                        return Err(err)
-                    }
-                };
-
-                let ret = unsafe {
-                    let mut overlapped: OVERLAPPED = mem::zeroed();
-
-                    let mut dwFlags = 0;
-                    if !wait {
-                        dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
-                    }
-
-                    if exclusive {
-                        dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
-                    }
-
-                    debug!("attempting to acquire lock on lock file `{}`",
-                           p.display());
-                    LockFileEx(file.as_raw_handle(),
-                               dwFlags,
-                               0,
-                               0xFFFF_FFFF,
-                               0xFFFF_FFFF,
-                               &mut overlapped)
-                };
-                if ret == 0 {
-                    let err = io::Error::last_os_error();
-                    debug!("failed acquiring file lock: {}", err);
-                    Err(err)
-                } else {
-                    debug!("successfully acquired lock");
-                    Ok(Lock { _file: file })
-                }
-            }
-        }
-
-        // Note that we don't need a Drop impl on the Windows: The file is unlocked
-        // automatically when it's closed.
-    } else {
-        #[derive(Debug)]
-        pub struct Lock(());
-
-        impl Lock {
-            pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
-                -> io::Result
-            {
-                let msg = "file locks not supported on this platform";
-                Err(io::Error::new(io::ErrorKind::Other, msg))
-            }
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/frozen.rs b/vendor/rustc-ap-rustc_data_structures/src/frozen.rs
deleted file mode 100644
index 2daf5b0414..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/frozen.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-//! An immutable, owned value (except for interior mutability).
-//!
-//! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example,
-//! suppose we have the following:
-//!
-//! ```rust
-//! struct Bar { /* some data */ }
-//!
-//! struct Foo {
-//!     /// Some computed data that should never change after construction.
-//!     pub computed: Bar,
-//!
-//!     /* some other fields */
-//! }
-//!
-//! impl Bar {
-//!     /// Mutate the `Bar`.
-//!     pub fn mutate(&mut self) { }
-//! }
-//! ```
-//!
-//! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that
-//! `computed` does not change accidentally (e.g. somebody might accidentally call
-//! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following:
-//!
-//! ```rust
-//! use rustc_data_structures::frozen::Frozen;
-//!
-//! struct Foo {
-//!     /// Some computed data that should never change after construction.
-//!     pub computed: Frozen,
-//!
-//!     /* some other fields */
-//! }
-//! ```
-//!
-//! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl
-//! DerefMut`.  Now calling `foo.compute.mutate()` will result in a compile-time error stating that
-//! `mutate` requires a mutable reference but we don't have one.
-//!
-//! # Caveats
-//!
-//! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen>`).
-//! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed =
-//!    Frozen::freeze(new_bar)`).
-
-/// An owned immutable value.
-#[derive(Debug)]
-pub struct Frozen(T);
-
-impl Frozen {
-    pub fn freeze(val: T) -> Self {
-        Frozen(val)
-    }
-}
-
-impl std::ops::Deref for Frozen {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &self.0
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/functor.rs b/vendor/rustc-ap-rustc_data_structures/src/functor.rs
deleted file mode 100644
index fe7a256d21..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/functor.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-use rustc_index::vec::{Idx, IndexVec};
-use std::mem;
-use std::ptr;
-
-pub trait IdFunctor {
-    type Inner;
-
-    fn map_id(self, f: F) -> Self
-    where
-        F: FnMut(Self::Inner) -> Self::Inner;
-}
-
-impl IdFunctor for Box {
-    type Inner = T;
-
-    #[inline]
-    fn map_id(self, mut f: F) -> Self
-    where
-        F: FnMut(Self::Inner) -> Self::Inner,
-    {
-        let raw = Box::into_raw(self);
-        unsafe {
-            // SAFETY: The raw pointer points to a valid value of type `T`.
-            let value = ptr::read(raw);
-            // SAFETY: Converts `Box` to `Box>` which is the
-            // inverse of `Box::assume_init()` and should be safe.
-            let mut raw: Box> = Box::from_raw(raw.cast());
-            // SAFETY: Write the mapped value back into the `Box`.
-            ptr::write(raw.as_mut_ptr(), f(value));
-            // SAFETY: We just initialized `raw`.
-            raw.assume_init()
-        }
-    }
-}
-
-impl IdFunctor for Vec {
-    type Inner = T;
-
-    #[inline]
-    fn map_id(mut self, mut f: F) -> Self
-    where
-        F: FnMut(Self::Inner) -> Self::Inner,
-    {
-        // FIXME: We don't really care about panics here and leak
-        // far more than we should, but that should be fine for now.
-        let len = self.len();
-        unsafe {
-            self.set_len(0);
-            let start = self.as_mut_ptr();
-            for i in 0..len {
-                let p = start.add(i);
-                ptr::write(p, f(ptr::read(p)));
-            }
-            self.set_len(len);
-        }
-        self
-    }
-}
-
-impl IdFunctor for Box<[T]> {
-    type Inner = T;
-
-    #[inline]
-    fn map_id(self, f: F) -> Self
-    where
-        F: FnMut(Self::Inner) -> Self::Inner,
-    {
-        Vec::from(self).map_id(f).into()
-    }
-}
-
-impl IdFunctor for IndexVec {
-    type Inner = T;
-
-    #[inline]
-    fn map_id(self, f: F) -> Self
-    where
-        F: FnMut(Self::Inner) -> Self::Inner,
-    {
-        IndexVec::from_raw(self.raw.map_id(f))
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/fx.rs b/vendor/rustc-ap-rustc_data_structures/src/fx.rs
deleted file mode 100644
index bbeb193dba..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/fx.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use std::hash::BuildHasherDefault;
-
-pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
-
-pub type FxIndexMap = indexmap::IndexMap>;
-pub type FxIndexSet = indexmap::IndexSet>;
-
-#[macro_export]
-macro_rules! define_id_collections {
-    ($map_name:ident, $set_name:ident, $key:ty) => {
-        pub type $map_name = $crate::fx::FxHashMap<$key, T>;
-        pub type $set_name = $crate::fx::FxHashSet<$key>;
-    };
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/dominators/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/dominators/mod.rs
deleted file mode 100644
index ad62e3c9fc..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/dominators/mod.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-//! Finding the dominators in a control-flow graph.
-//!
-//! Algorithm based on Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy,
-//! "A Simple, Fast Dominance Algorithm",
-//! Rice Computer Science TS-06-33870,
-//! .
-
-use super::iterate::reverse_post_order;
-use super::ControlFlowGraph;
-use rustc_index::vec::{Idx, IndexVec};
-use std::cmp::Ordering;
-
-#[cfg(test)]
-mod tests;
-
-pub fn dominators(graph: G) -> Dominators {
-    let start_node = graph.start_node();
-    let rpo = reverse_post_order(&graph, start_node);
-    dominators_given_rpo(graph, &rpo)
-}
-
-fn dominators_given_rpo(graph: G, rpo: &[G::Node]) -> Dominators {
-    let start_node = graph.start_node();
-    assert_eq!(rpo[0], start_node);
-
-    // compute the post order index (rank) for each node
-    let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes());
-    for (index, node) in rpo.iter().rev().cloned().enumerate() {
-        post_order_rank[node] = index;
-    }
-
-    let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes());
-    immediate_dominators[start_node] = Some(start_node);
-
-    let mut changed = true;
-    while changed {
-        changed = false;
-
-        for &node in &rpo[1..] {
-            let mut new_idom = None;
-            for pred in graph.predecessors(node) {
-                if immediate_dominators[pred].is_some() {
-                    // (*) dominators for `pred` have been calculated
-                    new_idom = Some(if let Some(new_idom) = new_idom {
-                        intersect(&post_order_rank, &immediate_dominators, new_idom, pred)
-                    } else {
-                        pred
-                    });
-                }
-            }
-
-            if new_idom != immediate_dominators[node] {
-                immediate_dominators[node] = new_idom;
-                changed = true;
-            }
-        }
-    }
-
-    Dominators { post_order_rank, immediate_dominators }
-}
-
-fn intersect(
-    post_order_rank: &IndexVec,
-    immediate_dominators: &IndexVec>,
-    mut node1: Node,
-    mut node2: Node,
-) -> Node {
-    while node1 != node2 {
-        while post_order_rank[node1] < post_order_rank[node2] {
-            node1 = immediate_dominators[node1].unwrap();
-        }
-
-        while post_order_rank[node2] < post_order_rank[node1] {
-            node2 = immediate_dominators[node2].unwrap();
-        }
-    }
-
-    node1
-}
-
-#[derive(Clone, Debug)]
-pub struct Dominators {
-    post_order_rank: IndexVec,
-    immediate_dominators: IndexVec>,
-}
-
-impl Dominators {
-    pub fn is_reachable(&self, node: Node) -> bool {
-        self.immediate_dominators[node].is_some()
-    }
-
-    pub fn immediate_dominator(&self, node: Node) -> Node {
-        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
-        self.immediate_dominators[node].unwrap()
-    }
-
-    pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
-        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
-        Iter { dominators: self, node: Some(node) }
-    }
-
-    pub fn is_dominated_by(&self, node: Node, dom: Node) -> bool {
-        // FIXME -- could be optimized by using post-order-rank
-        self.dominators(node).any(|n| n == dom)
-    }
-
-    /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
-    /// relationship, the dominator will always precede the dominated. (The relative ordering
-    /// of two unrelated nodes will also be consistent, but otherwise the order has no
-    /// meaning.) This method cannot be used to determine if either Node dominates the other.
-    pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option {
-        self.post_order_rank[lhs].partial_cmp(&self.post_order_rank[rhs])
-    }
-}
-
-pub struct Iter<'dom, Node: Idx> {
-    dominators: &'dom Dominators,
-    node: Option,
-}
-
-impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
-    type Item = Node;
-
-    fn next(&mut self) -> Option {
-        if let Some(node) = self.node {
-            let dom = self.dominators.immediate_dominator(node);
-            if dom == node {
-                self.node = None; // reached the root
-            } else {
-                self.node = Some(dom);
-            }
-            Some(node)
-        } else {
-            None
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/dominators/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/dominators/tests.rs
deleted file mode 100644
index 1160df5186..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/dominators/tests.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use super::*;
-
-use super::super::tests::TestGraph;
-
-#[test]
-fn diamond() {
-    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
-
-    let dominators = dominators(&graph);
-    let immediate_dominators = &dominators.immediate_dominators;
-    assert_eq!(immediate_dominators[0], Some(0));
-    assert_eq!(immediate_dominators[1], Some(0));
-    assert_eq!(immediate_dominators[2], Some(0));
-    assert_eq!(immediate_dominators[3], Some(0));
-}
-
-#[test]
-fn paper() {
-    // example from the paper:
-    let graph = TestGraph::new(
-        6,
-        &[(6, 5), (6, 4), (5, 1), (4, 2), (4, 3), (1, 2), (2, 3), (3, 2), (2, 1)],
-    );
-
-    let dominators = dominators(&graph);
-    let immediate_dominators = &dominators.immediate_dominators;
-    assert_eq!(immediate_dominators[0], None); // <-- note that 0 is not in graph
-    assert_eq!(immediate_dominators[1], Some(6));
-    assert_eq!(immediate_dominators[2], Some(6));
-    assert_eq!(immediate_dominators[3], Some(6));
-    assert_eq!(immediate_dominators[4], Some(6));
-    assert_eq!(immediate_dominators[5], Some(6));
-    assert_eq!(immediate_dominators[6], Some(6));
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/implementation/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/implementation/mod.rs
deleted file mode 100644
index 1aa7ac024d..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/implementation/mod.rs
+++ /dev/null
@@ -1,366 +0,0 @@
-//! A graph module for use in dataflow, region resolution, and elsewhere.
-//!
-//! # Interface details
-//!
-//! You customize the graph by specifying a "node data" type `N` and an
-//! "edge data" type `E`. You can then later gain access (mutable or
-//! immutable) to these "user-data" bits. Currently, you can only add
-//! nodes or edges to the graph. You cannot remove or modify them once
-//! added. This could be changed if we have a need.
-//!
-//! # Implementation details
-//!
-//! The main tricky thing about this code is the way that edges are
-//! stored. The edges are stored in a central array, but they are also
-//! threaded onto two linked lists for each node, one for incoming edges
-//! and one for outgoing edges. Note that every edge is a member of some
-//! incoming list and some outgoing list. Basically you can load the
-//! first index of the linked list from the node data structures (the
-//! field `first_edge`) and then, for each edge, load the next index from
-//! the field `next_edge`). Each of those fields is an array that should
-//! be indexed by the direction (see the type `Direction`).
-
-use crate::snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
-use rustc_index::bit_set::BitSet;
-use std::fmt::Debug;
-
-#[cfg(test)]
-mod tests;
-
-pub struct Graph {
-    nodes: SnapshotVec>,
-    edges: SnapshotVec>,
-}
-
-pub struct Node {
-    first_edge: [EdgeIndex; 2], // see module comment
-    pub data: N,
-}
-
-#[derive(Debug)]
-pub struct Edge {
-    next_edge: [EdgeIndex; 2], // see module comment
-    source: NodeIndex,
-    target: NodeIndex,
-    pub data: E,
-}
-
-impl SnapshotVecDelegate for Node {
-    type Value = Node;
-    type Undo = ();
-
-    fn reverse(_: &mut Vec>, _: ()) {}
-}
-
-impl SnapshotVecDelegate for Edge {
-    type Value = Edge;
-    type Undo = ();
-
-    fn reverse(_: &mut Vec>, _: ()) {}
-}
-
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub struct NodeIndex(pub usize);
-
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub struct EdgeIndex(pub usize);
-
-pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);
-
-// Use a private field here to guarantee no more instances are created:
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub struct Direction {
-    repr: usize,
-}
-
-pub const OUTGOING: Direction = Direction { repr: 0 };
-
-pub const INCOMING: Direction = Direction { repr: 1 };
-
-impl NodeIndex {
-    /// Returns unique ID (unique with respect to the graph holding associated node).
-    pub fn node_id(self) -> usize {
-        self.0
-    }
-}
-
-impl Graph {
-    pub fn new() -> Graph {
-        Graph { nodes: SnapshotVec::new(), edges: SnapshotVec::new() }
-    }
-
-    pub fn with_capacity(nodes: usize, edges: usize) -> Graph {
-        Graph { nodes: SnapshotVec::with_capacity(nodes), edges: SnapshotVec::with_capacity(edges) }
-    }
-
-    // # Simple accessors
-
-    #[inline]
-    pub fn all_nodes(&self) -> &[Node] {
-        &self.nodes
-    }
-
-    #[inline]
-    pub fn len_nodes(&self) -> usize {
-        self.nodes.len()
-    }
-
-    #[inline]
-    pub fn all_edges(&self) -> &[Edge] {
-        &self.edges
-    }
-
-    #[inline]
-    pub fn len_edges(&self) -> usize {
-        self.edges.len()
-    }
-
-    // # Node construction
-
-    pub fn next_node_index(&self) -> NodeIndex {
-        NodeIndex(self.nodes.len())
-    }
-
-    pub fn add_node(&mut self, data: N) -> NodeIndex {
-        let idx = self.next_node_index();
-        self.nodes.push(Node { first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX], data });
-        idx
-    }
-
-    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
-        &mut self.nodes[idx.0].data
-    }
-
-    pub fn node_data(&self, idx: NodeIndex) -> &N {
-        &self.nodes[idx.0].data
-    }
-
-    pub fn node(&self, idx: NodeIndex) -> &Node {
-        &self.nodes[idx.0]
-    }
-
-    // # Edge construction and queries
-
-    pub fn next_edge_index(&self) -> EdgeIndex {
-        EdgeIndex(self.edges.len())
-    }
-
-    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
-        debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);
-
-        let idx = self.next_edge_index();
-
-        // read current first of the list of edges from each node
-        let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
-        let target_first = self.nodes[target.0].first_edge[INCOMING.repr];
-
-        // create the new edge, with the previous firsts from each node
-        // as the next pointers
-        self.edges.push(Edge { next_edge: [source_first, target_first], source, target, data });
-
-        // adjust the firsts for each node target be the next object.
-        self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
-        self.nodes[target.0].first_edge[INCOMING.repr] = idx;
-
-        idx
-    }
-
-    pub fn edge(&self, idx: EdgeIndex) -> &Edge {
-        &self.edges[idx.0]
-    }
-
-    // # Iterating over nodes, edges
-
-    pub fn enumerated_nodes(&self) -> impl Iterator)> {
-        self.nodes.iter().enumerate().map(|(idx, n)| (NodeIndex(idx), n))
-    }
-
-    pub fn enumerated_edges(&self) -> impl Iterator)> {
-        self.edges.iter().enumerate().map(|(idx, e)| (EdgeIndex(idx), e))
-    }
-
-    pub fn each_node<'a>(&'a self, mut f: impl FnMut(NodeIndex, &'a Node) -> bool) -> bool {
-        //! Iterates over all edges defined in the graph.
-        self.enumerated_nodes().all(|(node_idx, node)| f(node_idx, node))
-    }
-
-    pub fn each_edge<'a>(&'a self, mut f: impl FnMut(EdgeIndex, &'a Edge) -> bool) -> bool {
-        //! Iterates over all edges defined in the graph
-        self.enumerated_edges().all(|(edge_idx, edge)| f(edge_idx, edge))
-    }
-
-    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<'_, N, E> {
-        self.adjacent_edges(source, OUTGOING)
-    }
-
-    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<'_, N, E> {
-        self.adjacent_edges(source, INCOMING)
-    }
-
-    pub fn adjacent_edges(
-        &self,
-        source: NodeIndex,
-        direction: Direction,
-    ) -> AdjacentEdges<'_, N, E> {
-        let first_edge = self.node(source).first_edge[direction.repr];
-        AdjacentEdges { graph: self, direction, next: first_edge }
-    }
-
-    pub fn successor_nodes<'a>(
-        &'a self,
-        source: NodeIndex,
-    ) -> impl Iterator + 'a {
-        self.outgoing_edges(source).targets()
-    }
-
-    pub fn predecessor_nodes<'a>(
-        &'a self,
-        target: NodeIndex,
-    ) -> impl Iterator + 'a {
-        self.incoming_edges(target).sources()
-    }
-
-    pub fn depth_traverse(
-        &self,
-        start: NodeIndex,
-        direction: Direction,
-    ) -> DepthFirstTraversal<'_, N, E> {
-        DepthFirstTraversal::with_start_node(self, start, direction)
-    }
-
-    pub fn nodes_in_postorder(
-        &self,
-        direction: Direction,
-        entry_node: NodeIndex,
-    ) -> Vec {
-        let mut visited = BitSet::new_empty(self.len_nodes());
-        let mut stack = vec![];
-        let mut result = Vec::with_capacity(self.len_nodes());
-        let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
-            if visited.insert(node.0) {
-                stack.push((node, self.adjacent_edges(node, direction)));
-            }
-        };
-
-        for node in
-            Some(entry_node).into_iter().chain(self.enumerated_nodes().map(|(node, _)| node))
-        {
-            push_node(&mut stack, node);
-            while let Some((node, mut iter)) = stack.pop() {
-                if let Some((_, child)) = iter.next() {
-                    let target = child.source_or_target(direction);
-                    // the current node needs more processing, so
-                    // add it back to the stack
-                    stack.push((node, iter));
-                    // and then push the new node
-                    push_node(&mut stack, target);
-                } else {
-                    result.push(node);
-                }
-            }
-        }
-
-        assert_eq!(result.len(), self.len_nodes());
-        result
-    }
-}
-
-// # Iterators
-
-pub struct AdjacentEdges<'g, N, E> {
-    graph: &'g Graph,
-    direction: Direction,
-    next: EdgeIndex,
-}
-
-impl<'g, N: Debug, E: Debug> AdjacentEdges<'g, N, E> {
-    fn targets(self) -> impl Iterator + 'g {
-        self.map(|(_, edge)| edge.target)
-    }
-
-    fn sources(self) -> impl Iterator + 'g {
-        self.map(|(_, edge)| edge.source)
-    }
-}
-
-impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
-    type Item = (EdgeIndex, &'g Edge);
-
-    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge)> {
-        let edge_index = self.next;
-        if edge_index == INVALID_EDGE_INDEX {
-            return None;
-        }
-
-        let edge = self.graph.edge(edge_index);
-        self.next = edge.next_edge[self.direction.repr];
-        Some((edge_index, edge))
-    }
-
-    fn size_hint(&self) -> (usize, Option) {
-        // At most, all the edges in the graph.
-        (0, Some(self.graph.len_edges()))
-    }
-}
-
-pub struct DepthFirstTraversal<'g, N, E> {
-    graph: &'g Graph,
-    stack: Vec,
-    visited: BitSet,
-    direction: Direction,
-}
-
-impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
-    pub fn with_start_node(
-        graph: &'g Graph,
-        start_node: NodeIndex,
-        direction: Direction,
-    ) -> Self {
-        let mut visited = BitSet::new_empty(graph.len_nodes());
-        visited.insert(start_node.node_id());
-        DepthFirstTraversal { graph, stack: vec![start_node], visited, direction }
-    }
-
-    fn visit(&mut self, node: NodeIndex) {
-        if self.visited.insert(node.node_id()) {
-            self.stack.push(node);
-        }
-    }
-}
-
-impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
-    type Item = NodeIndex;
-
-    fn next(&mut self) -> Option {
-        let next = self.stack.pop();
-        if let Some(idx) = next {
-            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
-                let target = edge.source_or_target(self.direction);
-                self.visit(target);
-            }
-        }
-        next
-    }
-
-    fn size_hint(&self) -> (usize, Option) {
-        // We will visit every node in the graph exactly once.
-        let remaining = self.graph.len_nodes() - self.visited.count();
-        (remaining, Some(remaining))
-    }
-}
-
-impl<'g, N: Debug, E: Debug> ExactSizeIterator for DepthFirstTraversal<'g, N, E> {}
-
-impl Edge {
-    pub fn source(&self) -> NodeIndex {
-        self.source
-    }
-
-    pub fn target(&self) -> NodeIndex {
-        self.target
-    }
-
-    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
-        if direction == OUTGOING { self.target } else { self.source }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/implementation/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/implementation/tests.rs
deleted file mode 100644
index e4e4d0d44b..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/implementation/tests.rs
+++ /dev/null
@@ -1,131 +0,0 @@
-use crate::graph::implementation::*;
-use std::fmt::Debug;
-
-type TestGraph = Graph<&'static str, &'static str>;
-
-fn create_graph() -> TestGraph {
-    let mut graph = Graph::new();
-
-    // Create a simple graph
-    //
-    //          F
-    //          |
-    //          V
-    //    A --> B --> C
-    //          |     ^
-    //          v     |
-    //          D --> E
-
-    let a = graph.add_node("A");
-    let b = graph.add_node("B");
-    let c = graph.add_node("C");
-    let d = graph.add_node("D");
-    let e = graph.add_node("E");
-    let f = graph.add_node("F");
-
-    graph.add_edge(a, b, "AB");
-    graph.add_edge(b, c, "BC");
-    graph.add_edge(b, d, "BD");
-    graph.add_edge(d, e, "DE");
-    graph.add_edge(e, c, "EC");
-    graph.add_edge(f, b, "FB");
-
-    return graph;
-}
-
-#[test]
-fn each_node() {
-    let graph = create_graph();
-    let expected = ["A", "B", "C", "D", "E", "F"];
-    graph.each_node(|idx, node| {
-        assert_eq!(&expected[idx.0], graph.node_data(idx));
-        assert_eq!(expected[idx.0], node.data);
-        true
-    });
-}
-
-#[test]
-fn each_edge() {
-    let graph = create_graph();
-    let expected = ["AB", "BC", "BD", "DE", "EC", "FB"];
-    graph.each_edge(|idx, edge| {
-        assert_eq!(expected[idx.0], edge.data);
-        true
-    });
-}
-
-fn test_adjacent_edges(
-    graph: &Graph,
-    start_index: NodeIndex,
-    start_data: N,
-    expected_incoming: &[(E, N)],
-    expected_outgoing: &[(E, N)],
-) {
-    assert!(graph.node_data(start_index) == &start_data);
-
-    let mut counter = 0;
-    for (edge_index, edge) in graph.incoming_edges(start_index) {
-        assert!(counter < expected_incoming.len());
-        debug!(
-            "counter={:?} expected={:?} edge_index={:?} edge={:?}",
-            counter, expected_incoming[counter], edge_index, edge
-        );
-        match expected_incoming[counter] {
-            (ref e, ref n) => {
-                assert!(e == &edge.data);
-                assert!(n == graph.node_data(edge.source()));
-                assert!(start_index == edge.target);
-            }
-        }
-        counter += 1;
-    }
-    assert_eq!(counter, expected_incoming.len());
-
-    let mut counter = 0;
-    for (edge_index, edge) in graph.outgoing_edges(start_index) {
-        assert!(counter < expected_outgoing.len());
-        debug!(
-            "counter={:?} expected={:?} edge_index={:?} edge={:?}",
-            counter, expected_outgoing[counter], edge_index, edge
-        );
-        match expected_outgoing[counter] {
-            (ref e, ref n) => {
-                assert!(e == &edge.data);
-                assert!(start_index == edge.source);
-                assert!(n == graph.node_data(edge.target));
-            }
-        }
-        counter += 1;
-    }
-    assert_eq!(counter, expected_outgoing.len());
-}
-
-#[test]
-fn each_adjacent_from_a() {
-    let graph = create_graph();
-    test_adjacent_edges(&graph, NodeIndex(0), "A", &[], &[("AB", "B")]);
-}
-
-#[test]
-fn each_adjacent_from_b() {
-    let graph = create_graph();
-    test_adjacent_edges(
-        &graph,
-        NodeIndex(1),
-        "B",
-        &[("FB", "F"), ("AB", "A")],
-        &[("BD", "D"), ("BC", "C")],
-    );
-}
-
-#[test]
-fn each_adjacent_from_c() {
-    let graph = create_graph();
-    test_adjacent_edges(&graph, NodeIndex(2), "C", &[("EC", "E"), ("BC", "B")], &[]);
-}
-
-#[test]
-fn each_adjacent_from_d() {
-    let graph = create_graph();
-    test_adjacent_edges(&graph, NodeIndex(3), "D", &[("BD", "B")], &[("DE", "E")]);
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/iterate/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/iterate/mod.rs
deleted file mode 100644
index 09b91083a6..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/iterate/mod.rs
+++ /dev/null
@@ -1,303 +0,0 @@
-use super::{DirectedGraph, WithNumNodes, WithStartNode, WithSuccessors};
-use rustc_index::bit_set::BitSet;
-use rustc_index::vec::IndexVec;
-use std::ops::ControlFlow;
-
-#[cfg(test)]
-mod tests;
-
-pub fn post_order_from(
-    graph: &G,
-    start_node: G::Node,
-) -> Vec {
-    post_order_from_to(graph, start_node, None)
-}
-
-pub fn post_order_from_to(
-    graph: &G,
-    start_node: G::Node,
-    end_node: Option,
-) -> Vec {
-    let mut visited: IndexVec = IndexVec::from_elem_n(false, graph.num_nodes());
-    let mut result: Vec = Vec::with_capacity(graph.num_nodes());
-    if let Some(end_node) = end_node {
-        visited[end_node] = true;
-    }
-    post_order_walk(graph, start_node, &mut result, &mut visited);
-    result
-}
-
-fn post_order_walk(
-    graph: &G,
-    node: G::Node,
-    result: &mut Vec,
-    visited: &mut IndexVec,
-) {
-    struct PostOrderFrame {
-        node: Node,
-        iter: Iter,
-    }
-
-    if visited[node] {
-        return;
-    }
-
-    let mut stack = vec![PostOrderFrame { node, iter: graph.successors(node) }];
-
-    'recurse: while let Some(frame) = stack.last_mut() {
-        let node = frame.node;
-        visited[node] = true;
-
-        while let Some(successor) = frame.iter.next() {
-            if !visited[successor] {
-                stack.push(PostOrderFrame { node: successor, iter: graph.successors(successor) });
-                continue 'recurse;
-            }
-        }
-
-        let _ = stack.pop();
-        result.push(node);
-    }
-}
-
-pub fn reverse_post_order(
-    graph: &G,
-    start_node: G::Node,
-) -> Vec {
-    let mut vec = post_order_from(graph, start_node);
-    vec.reverse();
-    vec
-}
-
-/// A "depth-first search" iterator for a directed graph.
-pub struct DepthFirstSearch<'graph, G>
-where
-    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
-{
-    graph: &'graph G,
-    stack: Vec,
-    visited: BitSet,
-}
-
-impl DepthFirstSearch<'graph, G>
-where
-    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
-{
-    pub fn new(graph: &'graph G, start_node: G::Node) -> Self {
-        Self { graph, stack: vec![start_node], visited: BitSet::new_empty(graph.num_nodes()) }
-    }
-}
-
-impl Iterator for DepthFirstSearch<'_, G>
-where
-    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
-{
-    type Item = G::Node;
-
-    fn next(&mut self) -> Option {
-        let DepthFirstSearch { stack, visited, graph } = self;
-        let n = stack.pop()?;
-        stack.extend(graph.successors(n).filter(|&m| visited.insert(m)));
-        Some(n)
-    }
-}
-
-/// The status of a node in the depth-first search.
-///
-/// See the documentation of `TriColorDepthFirstSearch` to see how a node's status is updated
-/// during DFS.
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum NodeStatus {
-    /// This node has been examined by the depth-first search but is not yet `Settled`.
-    ///
-    /// Also referred to as "gray" or "discovered" nodes in [CLR].
-    ///
-    /// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms
-    Visited,
-
-    /// This node and all nodes reachable from it have been examined by the depth-first search.
-    ///
-    /// Also referred to as "black" or "finished" nodes in [CLR].
-    ///
-    /// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms
-    Settled,
-}
-
-struct Event {
-    node: N,
-    becomes: NodeStatus,
-}
-
-/// A depth-first search that also tracks when all successors of a node have been examined.
-///
-/// This is based on the DFS described in [Introduction to Algorithms (1st ed.)][CLR], hereby
-/// referred to as **CLR**. However, we use the terminology in [`NodeStatus`] above instead of
-/// "discovered"/"finished" or "white"/"grey"/"black". Each node begins the search with no status,
-/// becomes `Visited` when it is first examined by the DFS and is `Settled` when all nodes
-/// reachable from it have been examined. This allows us to differentiate between "tree", "back"
-/// and "forward" edges (see [`TriColorVisitor::node_examined`]).
-///
-/// Unlike the pseudocode in [CLR], this implementation is iterative and does not use timestamps.
-/// We accomplish this by storing `Event`s on the stack that result in a (possible) state change
-/// for each node. A `Visited` event signifies that we should examine this node if it has not yet
-/// been `Visited` or `Settled`. When a node is examined for the first time, we mark it as
-/// `Visited` and push a `Settled` event for it on stack followed by `Visited` events for all of
-/// its predecessors, scheduling them for examination. Multiple `Visited` events for a single node
-/// may exist on the stack simultaneously if a node has multiple predecessors, but only one
-/// `Settled` event will ever be created for each node. After all `Visited` events for a node's
-/// successors have been popped off the stack (as well as any new events triggered by visiting
-/// those successors), we will pop off that node's `Settled` event.
-///
-/// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms
-pub struct TriColorDepthFirstSearch<'graph, G>
-where
-    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
-{
-    graph: &'graph G,
-    stack: Vec>,
-    visited: BitSet,
-    settled: BitSet,
-}
-
-impl TriColorDepthFirstSearch<'graph, G>
-where
-    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
-{
-    pub fn new(graph: &'graph G) -> Self {
-        TriColorDepthFirstSearch {
-            graph,
-            stack: vec![],
-            visited: BitSet::new_empty(graph.num_nodes()),
-            settled: BitSet::new_empty(graph.num_nodes()),
-        }
-    }
-
-    /// Performs a depth-first search, starting from the given `root`.
-    ///
-    /// This won't visit nodes that are not reachable from `root`.
-    pub fn run_from(mut self, root: G::Node, visitor: &mut V) -> Option
-    where
-        V: TriColorVisitor,
-    {
-        use NodeStatus::{Settled, Visited};
-
-        self.stack.push(Event { node: root, becomes: Visited });
-
-        loop {
-            match self.stack.pop()? {
-                Event { node, becomes: Settled } => {
-                    let not_previously_settled = self.settled.insert(node);
-                    assert!(not_previously_settled, "A node should be settled exactly once");
-                    if let ControlFlow::Break(val) = visitor.node_settled(node) {
-                        return Some(val);
-                    }
-                }
-
-                Event { node, becomes: Visited } => {
-                    let not_previously_visited = self.visited.insert(node);
-                    let prior_status = if not_previously_visited {
-                        None
-                    } else if self.settled.contains(node) {
-                        Some(Settled)
-                    } else {
-                        Some(Visited)
-                    };
-
-                    if let ControlFlow::Break(val) = visitor.node_examined(node, prior_status) {
-                        return Some(val);
-                    }
-
-                    // If this node has already been examined, we are done.
-                    if prior_status.is_some() {
-                        continue;
-                    }
-
-                    // Otherwise, push a `Settled` event for this node onto the stack, then
-                    // schedule its successors for examination.
-                    self.stack.push(Event { node, becomes: Settled });
-                    for succ in self.graph.successors(node) {
-                        if !visitor.ignore_edge(node, succ) {
-                            self.stack.push(Event { node: succ, becomes: Visited });
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-impl TriColorDepthFirstSearch<'graph, G>
-where
-    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors + WithStartNode,
-{
-    /// Performs a depth-first search, starting from `G::start_node()`.
-    ///
-    /// This won't visit nodes that are not reachable from the start node.
-    pub fn run_from_start(self, visitor: &mut V) -> Option
-    where
-        V: TriColorVisitor,
-    {
-        let root = self.graph.start_node();
-        self.run_from(root, visitor)
-    }
-}
-
-/// What to do when a node is examined or becomes `Settled` during DFS.
-pub trait TriColorVisitor
-where
-    G: ?Sized + DirectedGraph,
-{
-    /// The value returned by this search.
-    type BreakVal;
-
-    /// Called when a node is examined by the depth-first search.
-    ///
-    /// By checking the value of `prior_status`, this visitor can determine whether the edge
-    /// leading to this node was a tree edge (`None`), forward edge (`Some(Settled)`) or back edge
-    /// (`Some(Visited)`). For a full explanation of each edge type, see the "Depth-first Search"
-    /// chapter in [CLR] or [wikipedia].
-    ///
-    /// If you want to know *both* nodes linked by each edge, you'll need to modify
-    /// `TriColorDepthFirstSearch` to store a `source` node for each `Visited` event.
-    ///
-    /// [wikipedia]: https://en.wikipedia.org/wiki/Depth-first_search#Output_of_a_depth-first_search
-    /// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms
-    fn node_examined(
-        &mut self,
-        _node: G::Node,
-        _prior_status: Option,
-    ) -> ControlFlow {
-        ControlFlow::CONTINUE
-    }
-
-    /// Called after all nodes reachable from this one have been examined.
-    fn node_settled(&mut self, _node: G::Node) -> ControlFlow {
-        ControlFlow::CONTINUE
-    }
-
-    /// Behave as if no edges exist from `source` to `target`.
-    fn ignore_edge(&mut self, _source: G::Node, _target: G::Node) -> bool {
-        false
-    }
-}
-
-/// This `TriColorVisitor` looks for back edges in a graph, which indicate that a cycle exists.
-pub struct CycleDetector;
-
-impl TriColorVisitor for CycleDetector
-where
-    G: ?Sized + DirectedGraph,
-{
-    type BreakVal = ();
-
-    fn node_examined(
-        &mut self,
-        _node: G::Node,
-        prior_status: Option,
-    ) -> ControlFlow {
-        match prior_status {
-            Some(NodeStatus::Visited) => ControlFlow::BREAK,
-            _ => ControlFlow::CONTINUE,
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/iterate/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/iterate/tests.rs
deleted file mode 100644
index 0e038e88b2..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/iterate/tests.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use super::super::tests::TestGraph;
-
-use super::*;
-
-#[test]
-fn diamond_post_order() {
-    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
-
-    let result = post_order_from(&graph, 0);
-    assert_eq!(result, vec![3, 1, 2, 0]);
-}
-
-#[test]
-fn is_cyclic() {
-    use super::super::is_cyclic;
-
-    let diamond_acyclic = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
-    let diamond_cyclic = TestGraph::new(0, &[(0, 1), (1, 2), (2, 3), (3, 0)]);
-
-    assert!(!is_cyclic(&diamond_acyclic));
-    assert!(is_cyclic(&diamond_cyclic));
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/mod.rs
deleted file mode 100644
index e0903e4324..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/mod.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-use rustc_index::vec::Idx;
-
-pub mod dominators;
-pub mod implementation;
-pub mod iterate;
-mod reference;
-pub mod scc;
-pub mod vec_graph;
-
-#[cfg(test)]
-mod tests;
-
-pub trait DirectedGraph {
-    type Node: Idx;
-}
-
-pub trait WithNumNodes: DirectedGraph {
-    fn num_nodes(&self) -> usize;
-}
-
-pub trait WithNumEdges: DirectedGraph {
-    fn num_edges(&self) -> usize;
-}
-
-pub trait WithSuccessors: DirectedGraph
-where
-    Self: for<'graph> GraphSuccessors<'graph, Item = ::Node>,
-{
-    fn successors(&self, node: Self::Node) -> >::Iter;
-
-    fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
-    where
-        Self: WithNumNodes,
-    {
-        iterate::DepthFirstSearch::new(self, from)
-    }
-}
-
-#[allow(unused_lifetimes)]
-pub trait GraphSuccessors<'graph> {
-    type Item;
-    type Iter: Iterator;
-}
-
-pub trait WithPredecessors: DirectedGraph
-where
-    Self: for<'graph> GraphPredecessors<'graph, Item = ::Node>,
-{
-    fn predecessors(&self, node: Self::Node) -> >::Iter;
-}
-
-#[allow(unused_lifetimes)]
-pub trait GraphPredecessors<'graph> {
-    type Item;
-    type Iter: Iterator;
-}
-
-pub trait WithStartNode: DirectedGraph {
-    fn start_node(&self) -> Self::Node;
-}
-
-pub trait ControlFlowGraph:
-    DirectedGraph + WithStartNode + WithPredecessors + WithStartNode + WithSuccessors + WithNumNodes
-{
-    // convenient trait
-}
-
-impl ControlFlowGraph for T where
-    T: DirectedGraph
-        + WithStartNode
-        + WithPredecessors
-        + WithStartNode
-        + WithSuccessors
-        + WithNumNodes
-{
-}
-
-/// Returns `true` if the graph has a cycle that is reachable from the start node.
-pub fn is_cyclic(graph: &G) -> bool
-where
-    G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
-{
-    iterate::TriColorDepthFirstSearch::new(graph)
-        .run_from_start(&mut iterate::CycleDetector)
-        .is_some()
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/reference.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/reference.rs
deleted file mode 100644
index c259fe56c1..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/reference.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-use super::*;
-
-impl<'graph, G: DirectedGraph> DirectedGraph for &'graph G {
-    type Node = G::Node;
-}
-
-impl<'graph, G: WithNumNodes> WithNumNodes for &'graph G {
-    fn num_nodes(&self) -> usize {
-        (**self).num_nodes()
-    }
-}
-
-impl<'graph, G: WithStartNode> WithStartNode for &'graph G {
-    fn start_node(&self) -> Self::Node {
-        (**self).start_node()
-    }
-}
-
-impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G {
-    fn successors(&self, node: Self::Node) -> >::Iter {
-        (**self).successors(node)
-    }
-}
-
-impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G {
-    fn predecessors(&self, node: Self::Node) -> >::Iter {
-        (**self).predecessors(node)
-    }
-}
-
-impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph G {
-    type Item = G::Node;
-    type Iter = >::Iter;
-}
-
-impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph G {
-    type Item = G::Node;
-    type Iter = >::Iter;
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/scc/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/scc/mod.rs
deleted file mode 100644
index e2cbb09ce5..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/scc/mod.rs
+++ /dev/null
@@ -1,574 +0,0 @@
-//! Routine to compute the strongly connected components (SCCs) of a graph.
-//!
-//! Also computes as the resulting DAG if each SCC is replaced with a
-//! node in the graph. This uses [Tarjan's algorithm](
-//! https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm)
-//! that completes in *O(n)* time.
-
-use crate::fx::FxHashSet;
-use crate::graph::vec_graph::VecGraph;
-use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
-use rustc_index::vec::{Idx, IndexVec};
-use std::ops::Range;
-
-#[cfg(test)]
-mod tests;
-
-/// Strongly connected components (SCC) of a graph. The type `N` is
-/// the index type for the graph nodes and `S` is the index type for
-/// the SCCs. We can map from each node to the SCC that it
-/// participates in, and we also have the successors of each SCC.
-pub struct Sccs {
-    /// For each node, what is the SCC index of the SCC to which it
-    /// belongs.
-    scc_indices: IndexVec,
-
-    /// Data about each SCC.
-    scc_data: SccData,
-}
-
-struct SccData {
-    /// For each SCC, the range of `all_successors` where its
-    /// successors can be found.
-    ranges: IndexVec>,
-
-    /// Contains the successors for all the Sccs, concatenated. The
-    /// range of indices corresponding to a given SCC is found in its
-    /// SccData.
-    all_successors: Vec,
-}
-
-impl Sccs {
-    pub fn new(graph: &(impl DirectedGraph + WithNumNodes + WithSuccessors)) -> Self {
-        SccsConstruction::construct(graph)
-    }
-
-    /// Returns the number of SCCs in the graph.
-    pub fn num_sccs(&self) -> usize {
-        self.scc_data.len()
-    }
-
-    /// Returns an iterator over the SCCs in the graph.
-    ///
-    /// The SCCs will be iterated in **dependency order** (or **post order**),
-    /// meaning that if `S1 -> S2`, we will visit `S2` first and `S1` after.
-    /// This is convenient when the edges represent dependencies: when you visit
-    /// `S1`, the value for `S2` will already have been computed.
-    pub fn all_sccs(&self) -> impl Iterator {
-        (0..self.scc_data.len()).map(S::new)
-    }
-
-    /// Returns the SCC to which a node `r` belongs.
-    pub fn scc(&self, r: N) -> S {
-        self.scc_indices[r]
-    }
-
-    /// Returns the successors of the given SCC.
-    pub fn successors(&self, scc: S) -> &[S] {
-        self.scc_data.successors(scc)
-    }
-
-    /// Construct the reverse graph of the SCC graph.
-    pub fn reverse(&self) -> VecGraph {
-        VecGraph::new(
-            self.num_sccs(),
-            self.all_sccs()
-                .flat_map(|source| {
-                    self.successors(source).iter().map(move |&target| (target, source))
-                })
-                .collect(),
-        )
-    }
-}
-
-impl DirectedGraph for Sccs {
-    type Node = S;
-}
-
-impl WithNumNodes for Sccs {
-    fn num_nodes(&self) -> usize {
-        self.num_sccs()
-    }
-}
-
-impl WithNumEdges for Sccs {
-    fn num_edges(&self) -> usize {
-        self.scc_data.all_successors.len()
-    }
-}
-
-impl GraphSuccessors<'graph> for Sccs {
-    type Item = S;
-
-    type Iter = std::iter::Cloned>;
-}
-
-impl WithSuccessors for Sccs {
-    fn successors(&self, node: S) -> >::Iter {
-        self.successors(node).iter().cloned()
-    }
-}
-
-impl SccData {
-    /// Number of SCCs,
-    fn len(&self) -> usize {
-        self.ranges.len()
-    }
-
-    /// Returns the successors of the given SCC.
-    fn successors(&self, scc: S) -> &[S] {
-        // Annoyingly, `range` does not implement `Copy`, so we have
-        // to do `range.start..range.end`:
-        let range = &self.ranges[scc];
-        &self.all_successors[range.start..range.end]
-    }
-
-    /// Creates a new SCC with `successors` as its successors and
-    /// returns the resulting index.
-    fn create_scc(&mut self, successors: impl IntoIterator) -> S {
-        // Store the successors on `scc_successors_vec`, remembering
-        // the range of indices.
-        let all_successors_start = self.all_successors.len();
-        self.all_successors.extend(successors);
-        let all_successors_end = self.all_successors.len();
-
-        debug!(
-            "create_scc({:?}) successors={:?}",
-            self.ranges.len(),
-            &self.all_successors[all_successors_start..all_successors_end],
-        );
-
-        self.ranges.push(all_successors_start..all_successors_end)
-    }
-}
-
-struct SccsConstruction<'c, G: DirectedGraph + WithNumNodes + WithSuccessors, S: Idx> {
-    graph: &'c G,
-
-    /// The state of each node; used during walk to record the stack
-    /// and after walk to record what cycle each node ended up being
-    /// in.
-    node_states: IndexVec>,
-
-    /// The stack of nodes that we are visiting as part of the DFS.
-    node_stack: Vec,
-
-    /// The stack of successors: as we visit a node, we mark our
-    /// position in this stack, and when we encounter a successor SCC,
-    /// we push it on the stack. When we complete an SCC, we can pop
-    /// everything off the stack that was found along the way.
-    successors_stack: Vec,
-
-    /// A set used to strip duplicates. As we accumulate successors
-    /// into the successors_stack, we sometimes get duplicate entries.
-    /// We use this set to remove those -- we also keep its storage
-    /// around between successors to amortize memory allocation costs.
-    duplicate_set: FxHashSet,
-
-    scc_data: SccData,
-}
-
-#[derive(Copy, Clone, Debug)]
-enum NodeState {
-    /// This node has not yet been visited as part of the DFS.
-    ///
-    /// After SCC construction is complete, this state ought to be
-    /// impossible.
-    NotVisited,
-
-    /// This node is currently being walk as part of our DFS. It is on
-    /// the stack at the depth `depth`.
-    ///
-    /// After SCC construction is complete, this state ought to be
-    /// impossible.
-    BeingVisited { depth: usize },
-
-    /// Indicates that this node is a member of the given cycle.
-    InCycle { scc_index: S },
-
-    /// Indicates that this node is a member of whatever cycle
-    /// `parent` is a member of. This state is transient: whenever we
-    /// see it, we try to overwrite it with the current state of
-    /// `parent` (this is the "path compression" step of a union-find
-    /// algorithm).
-    InCycleWith { parent: N },
-}
-
-#[derive(Copy, Clone, Debug)]
-enum WalkReturn {
-    Cycle { min_depth: usize },
-    Complete { scc_index: S },
-}
-
-impl<'c, G, S> SccsConstruction<'c, G, S>
-where
-    G: DirectedGraph + WithNumNodes + WithSuccessors,
-    S: Idx,
-{
-    /// Identifies SCCs in the graph `G` and computes the resulting
-    /// DAG. This uses a variant of [Tarjan's
-    /// algorithm][wikipedia]. The high-level summary of the algorithm
-    /// is that we do a depth-first search. Along the way, we keep a
-    /// stack of each node whose successors are being visited. We
-    /// track the depth of each node on this stack (there is no depth
-    /// if the node is not on the stack). When we find that some node
-    /// N with depth D can reach some other node N' with lower depth
-    /// D' (i.e., D' < D), we know that N, N', and all nodes in
-    /// between them on the stack are part of an SCC.
-    ///
-    /// [wikipedia]: https://bit.ly/2EZIx84
-    fn construct(graph: &'c G) -> Sccs {
-        let num_nodes = graph.num_nodes();
-
-        let mut this = Self {
-            graph,
-            node_states: IndexVec::from_elem_n(NodeState::NotVisited, num_nodes),
-            node_stack: Vec::with_capacity(num_nodes),
-            successors_stack: Vec::new(),
-            scc_data: SccData { ranges: IndexVec::new(), all_successors: Vec::new() },
-            duplicate_set: FxHashSet::default(),
-        };
-
-        let scc_indices = (0..num_nodes)
-            .map(G::Node::new)
-            .map(|node| match this.start_walk_from(node) {
-                WalkReturn::Complete { scc_index } => scc_index,
-                WalkReturn::Cycle { min_depth } => panic!(
-                    "`start_walk_node({:?})` returned cycle with depth {:?}",
-                    node, min_depth
-                ),
-            })
-            .collect();
-
-        Sccs { scc_indices, scc_data: this.scc_data }
-    }
-
-    fn start_walk_from(&mut self, node: G::Node) -> WalkReturn {
-        if let Some(result) = self.inspect_node(node) {
-            result
-        } else {
-            self.walk_unvisited_node(node)
-        }
-    }
-
-    /// Inspect a node during the DFS. We first examine its current
-    /// state -- if it is not yet visited (`NotVisited`), return `None` so
-    /// that the caller might push it onto the stack and start walking its
-    /// successors.
-    ///
-    /// If it is already on the DFS stack it will be in the state
-    /// `BeingVisited`. In that case, we have found a cycle and we
-    /// return the depth from the stack.
-    ///
-    /// Otherwise, we are looking at a node that has already been
-    /// completely visited. We therefore return `WalkReturn::Complete`
-    /// with its associated SCC index.
-    fn inspect_node(&mut self, node: G::Node) -> Option> {
-        Some(match self.find_state(node) {
-            NodeState::InCycle { scc_index } => WalkReturn::Complete { scc_index },
-
-            NodeState::BeingVisited { depth: min_depth } => WalkReturn::Cycle { min_depth },
-
-            NodeState::NotVisited => return None,
-
-            NodeState::InCycleWith { parent } => panic!(
-                "`find_state` returned `InCycleWith({:?})`, which ought to be impossible",
-                parent
-            ),
-        })
-    }
-
-    /// Fetches the state of the node `r`. If `r` is recorded as being
-    /// in a cycle with some other node `r2`, then fetches the state
-    /// of `r2` (and updates `r` to reflect current result). This is
-    /// basically the "find" part of a standard union-find algorithm
-    /// (with path compression).
-    fn find_state(&mut self, mut node: G::Node) -> NodeState {
-        // To avoid recursion we temporarily reuse the `parent` of each
-        // InCycleWith link to encode a downwards link while compressing
-        // the path. After we have found the root or deepest node being
-        // visited, we traverse the reverse links and correct the node
-        // states on the way.
-        //
-        // **Note**: This mutation requires that this is a leaf function
-        // or at least that none of the called functions inspects the
-        // current node states. Luckily, we are a leaf.
-
-        // Remember one previous link. The termination condition when
-        // following links downwards is then simply as soon as we have
-        // found the initial self-loop.
-        let mut previous_node = node;
-
-        // Ultimately assigned by the parent when following
-        // `InCycleWith` upwards.
-        let node_state = loop {
-            debug!("find_state(r = {:?} in state {:?})", node, self.node_states[node]);
-            match self.node_states[node] {
-                NodeState::InCycle { scc_index } => break NodeState::InCycle { scc_index },
-                NodeState::BeingVisited { depth } => break NodeState::BeingVisited { depth },
-                NodeState::NotVisited => break NodeState::NotVisited,
-                NodeState::InCycleWith { parent } => {
-                    // We test this, to be extremely sure that we never
-                    // ever break our termination condition for the
-                    // reverse iteration loop.
-                    assert!(node != parent, "Node can not be in cycle with itself");
-                    // Store the previous node as an inverted list link
-                    self.node_states[node] = NodeState::InCycleWith { parent: previous_node };
-                    // Update to parent node.
-                    previous_node = node;
-                    node = parent;
-                }
-            }
-        };
-
-        // The states form a graph where up to one outgoing link is stored at
-        // each node. Initially in general,
-        //
-        //                                                  E
-        //                                                  ^
-        //                                                  |
-        //                                InCycleWith/BeingVisited/NotVisited
-        //                                                  |
-        //   A-InCycleWith->B-InCycleWith…>C-InCycleWith->D-+
-        //   |
-        //   = node, previous_node
-        //
-        // After the first loop, this will look like
-        //                                                  E
-        //                                                  ^
-        //                                                  |
-        //                                InCycleWith/BeingVisited/NotVisited
-        //                                                  |
-        // +>A<-InCycleWith-B<…InCycleWith-C<-InCycleWith-D-+
-        // | |                             |              |
-        // | InCycleWith                   |              = node
-        // +-+                             =previous_node
-        //
-        // Note in particular that A will be linked to itself in a self-cycle
-        // and no other self-cycles occur due to how InCycleWith is assigned in
-        // the find phase implemented by `walk_unvisited_node`.
-        //
-        // We now want to compress the path, that is assign the state of the
-        // link D-E to all other links.
-        //
-        // We can then walk backwards, starting from `previous_node`, and assign
-        // each node in the list with the updated state. The loop terminates
-        // when we reach the self-cycle.
-
-        // Move backwards until we found the node where we started. We
-        // will know when we hit the state where previous_node == node.
-        loop {
-            // Back at the beginning, we can return.
-            if previous_node == node {
-                return node_state;
-            }
-            // Update to previous node in the link.
-            match self.node_states[previous_node] {
-                NodeState::InCycleWith { parent: previous } => {
-                    node = previous_node;
-                    previous_node = previous;
-                }
-                // Only InCycleWith nodes were added to the reverse linked list.
-                other => panic!("Invalid previous link while compressing cycle: {:?}", other),
-            }
-
-            debug!("find_state: parent_state = {:?}", node_state);
-
-            // Update the node state from the parent state. The assigned
-            // state is actually a loop invariant but it will only be
-            // evaluated if there is at least one backlink to follow.
-            // Fully trusting llvm here to find this loop optimization.
-            match node_state {
-                // Path compression, make current node point to the same root.
-                NodeState::InCycle { .. } => {
-                    self.node_states[node] = node_state;
-                }
-                // Still visiting nodes, compress to cycle to the node
-                // at that depth.
-                NodeState::BeingVisited { depth } => {
-                    self.node_states[node] =
-                        NodeState::InCycleWith { parent: self.node_stack[depth] };
-                }
-                // These are never allowed as parent nodes. InCycleWith
-                // should have been followed to a real parent and
-                // NotVisited can not be part of a cycle since it should
-                // have instead gotten explored.
-                NodeState::NotVisited | NodeState::InCycleWith { .. } => {
-                    panic!("invalid parent state: {:?}", node_state)
-                }
-            }
-        }
-    }
-
-    /// Walks a node that has never been visited before.
-    ///
-    /// Call this method when `inspect_node` has returned `None`. Having the
-    /// caller decide avoids mutual recursion between the two methods and allows
-    /// us to maintain an allocated stack for nodes on the path between calls.
-    fn walk_unvisited_node(&mut self, initial: G::Node) -> WalkReturn {
-        struct VisitingNodeFrame {
-            node: G::Node,
-            iter: Option,
-            depth: usize,
-            min_depth: usize,
-            successors_len: usize,
-            min_cycle_root: G::Node,
-            successor_node: G::Node,
-        }
-
-        // Move the stack to a local variable. We want to utilize the existing allocation and
-        // mutably borrow it without borrowing self at the same time.
-        let mut successors_stack = core::mem::take(&mut self.successors_stack);
-        debug_assert_eq!(successors_stack.len(), 0);
-
-        let mut stack: Vec> = vec![VisitingNodeFrame {
-            node: initial,
-            depth: 0,
-            min_depth: 0,
-            iter: None,
-            successors_len: 0,
-            min_cycle_root: initial,
-            successor_node: initial,
-        }];
-
-        let mut return_value = None;
-
-        'recurse: while let Some(frame) = stack.last_mut() {
-            let VisitingNodeFrame {
-                node,
-                depth,
-                iter,
-                successors_len,
-                min_depth,
-                min_cycle_root,
-                successor_node,
-            } = frame;
-
-            let node = *node;
-            let depth = *depth;
-
-            let successors = match iter {
-                Some(iter) => iter,
-                None => {
-                    // This None marks that we still have the initialize this node's frame.
-                    debug!("walk_unvisited_node(depth = {:?}, node = {:?})", depth, node);
-
-                    debug_assert!(matches!(self.node_states[node], NodeState::NotVisited));
-
-                    // Push `node` onto the stack.
-                    self.node_states[node] = NodeState::BeingVisited { depth };
-                    self.node_stack.push(node);
-
-                    // Walk each successor of the node, looking to see if any of
-                    // them can reach a node that is presently on the stack. If
-                    // so, that means they can also reach us.
-                    *successors_len = successors_stack.len();
-                    // Set and return a reference, this is currently empty.
-                    iter.get_or_insert(self.graph.successors(node))
-                }
-            };
-
-            // Now that iter is initialized, this is a constant for this frame.
-            let successors_len = *successors_len;
-
-            // Construct iterators for the nodes and walk results. There are two cases:
-            // * The walk of a successor node returned.
-            // * The remaining successor nodes.
-            let returned_walk =
-                return_value.take().into_iter().map(|walk| (*successor_node, Some(walk)));
-
-            let successor_walk = successors.by_ref().map(|successor_node| {
-                debug!(
-                    "walk_unvisited_node: node = {:?} successor_ode = {:?}",
-                    node, successor_node
-                );
-                (successor_node, self.inspect_node(successor_node))
-            });
-
-            for (successor_node, walk) in returned_walk.chain(successor_walk) {
-                match walk {
-                    Some(WalkReturn::Cycle { min_depth: successor_min_depth }) => {
-                        // Track the minimum depth we can reach.
-                        assert!(successor_min_depth <= depth);
-                        if successor_min_depth < *min_depth {
-                            debug!(
-                                "walk_unvisited_node: node = {:?} successor_min_depth = {:?}",
-                                node, successor_min_depth
-                            );
-                            *min_depth = successor_min_depth;
-                            *min_cycle_root = successor_node;
-                        }
-                    }
-
-                    Some(WalkReturn::Complete { scc_index: successor_scc_index }) => {
-                        // Push the completed SCC indices onto
-                        // the `successors_stack` for later.
-                        debug!(
-                            "walk_unvisited_node: node = {:?} successor_scc_index = {:?}",
-                            node, successor_scc_index
-                        );
-                        successors_stack.push(successor_scc_index);
-                    }
-
-                    None => {
-                        let depth = depth + 1;
-                        debug!("walk_node(depth = {:?}, node = {:?})", depth, successor_node);
-                        // Remember which node the return value will come from.
-                        frame.successor_node = successor_node;
-                        // Start a new stack frame the step into it.
-                        stack.push(VisitingNodeFrame {
-                            node: successor_node,
-                            depth,
-                            iter: None,
-                            successors_len: 0,
-                            min_depth: depth,
-                            min_cycle_root: successor_node,
-                            successor_node,
-                        });
-                        continue 'recurse;
-                    }
-                }
-            }
-
-            // Completed walk, remove `node` from the stack.
-            let r = self.node_stack.pop();
-            debug_assert_eq!(r, Some(node));
-
-            // Remove the frame, it's done.
-            let frame = stack.pop().unwrap();
-
-            // If `min_depth == depth`, then we are the root of the
-            // cycle: we can't reach anyone further down the stack.
-
-            // Pass the 'return value' down the stack.
-            // We return one frame at a time so there can't be another return value.
-            debug_assert!(return_value.is_none());
-            return_value = Some(if frame.min_depth == depth {
-                // Note that successor stack may have duplicates, so we
-                // want to remove those:
-                let deduplicated_successors = {
-                    let duplicate_set = &mut self.duplicate_set;
-                    duplicate_set.clear();
-                    successors_stack
-                        .drain(successors_len..)
-                        .filter(move |&i| duplicate_set.insert(i))
-                };
-                let scc_index = self.scc_data.create_scc(deduplicated_successors);
-                self.node_states[node] = NodeState::InCycle { scc_index };
-                WalkReturn::Complete { scc_index }
-            } else {
-                // We are not the head of the cycle. Return back to our
-                // caller. They will take ownership of the
-                // `self.successors` data that we pushed.
-                self.node_states[node] = NodeState::InCycleWith { parent: frame.min_cycle_root };
-                WalkReturn::Cycle { min_depth: frame.min_depth }
-            });
-        }
-
-        // Keep the allocation we used for successors_stack.
-        self.successors_stack = successors_stack;
-        debug_assert_eq!(self.successors_stack.len(), 0);
-
-        return_value.unwrap()
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/scc/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/scc/tests.rs
deleted file mode 100644
index 364005e67e..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/scc/tests.rs
+++ /dev/null
@@ -1,213 +0,0 @@
-extern crate test;
-
-use super::*;
-use crate::graph::tests::TestGraph;
-
-#[test]
-fn diamond() {
-    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
-    assert_eq!(sccs.num_sccs(), 4);
-    assert_eq!(sccs.num_sccs(), 4);
-}
-
-#[test]
-fn test_big_scc() {
-    // The order in which things will be visited is important to this
-    // test.
-    //
-    // We will visit:
-    //
-    // 0 -> 1 -> 2 -> 0
-    //
-    // and at this point detect a cycle. 2 will return back to 1 which
-    // will visit 3. 3 will visit 2 before the cycle is complete, and
-    // hence it too will return a cycle.
-
-    /*
-    +-> 0
-    |   |
-    |   v
-    |   1 -> 3
-    |   |    |
-    |   v    |
-    +-- 2 <--+
-         */
-    let graph = TestGraph::new(0, &[(0, 1), (1, 2), (1, 3), (2, 0), (3, 2)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
-    assert_eq!(sccs.num_sccs(), 1);
-}
-
-#[test]
-fn test_three_sccs() {
-    /*
-        0
-        |
-        v
-    +-> 1    3
-    |   |    |
-    |   v    |
-    +-- 2 <--+
-         */
-    let graph = TestGraph::new(0, &[(0, 1), (1, 2), (2, 1), (3, 2)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
-    assert_eq!(sccs.num_sccs(), 3);
-    assert_eq!(sccs.scc(0), 1);
-    assert_eq!(sccs.scc(1), 0);
-    assert_eq!(sccs.scc(2), 0);
-    assert_eq!(sccs.scc(3), 2);
-    assert_eq!(sccs.successors(0), &[]);
-    assert_eq!(sccs.successors(1), &[0]);
-    assert_eq!(sccs.successors(2), &[0]);
-}
-
-#[test]
-fn test_find_state_2() {
-    // The order in which things will be visited is important to this
-    // test. It tests part of the `find_state` behavior. Here is the
-    // graph:
-    //
-    //
-    //       /----+
-    //     0 <--+ |
-    //     |    | |
-    //     v    | |
-    // +-> 1 -> 3 4
-    // |   |      |
-    // |   v      |
-    // +-- 2 <----+
-
-    let graph = TestGraph::new(0, &[(0, 1), (0, 4), (1, 2), (1, 3), (2, 1), (3, 0), (4, 2)]);
-
-    // For this graph, we will start in our DFS by visiting:
-    //
-    // 0 -> 1 -> 2 -> 1
-    //
-    // and at this point detect a cycle. The state of 2 will thus be
-    // `InCycleWith { 1 }`.  We will then visit the 1 -> 3 edge, which
-    // will attempt to visit 0 as well, thus going to the state
-    // `InCycleWith { 0 }`. Finally, node 1 will complete; the lowest
-    // depth of any successor was 3 which had depth 0, and thus it
-    // will be in the state `InCycleWith { 3 }`.
-    //
-    // When we finally traverse the `0 -> 4` edge and then visit node 2,
-    // the states of the nodes are:
-    //
-    // 0 BeingVisited { 0 }
-    // 1 InCycleWith { 3 }
-    // 2 InCycleWith { 1 }
-    // 3 InCycleWith { 0 }
-    //
-    // and hence 4 will traverse the links, finding an ultimate depth of 0.
-    // If will also collapse the states to the following:
-    //
-    // 0 BeingVisited { 0 }
-    // 1 InCycleWith { 3 }
-    // 2 InCycleWith { 1 }
-    // 3 InCycleWith { 0 }
-
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
-    assert_eq!(sccs.num_sccs(), 1);
-    assert_eq!(sccs.scc(0), 0);
-    assert_eq!(sccs.scc(1), 0);
-    assert_eq!(sccs.scc(2), 0);
-    assert_eq!(sccs.scc(3), 0);
-    assert_eq!(sccs.scc(4), 0);
-    assert_eq!(sccs.successors(0), &[]);
-}
-
-#[test]
-fn test_find_state_3() {
-    /*
-          /----+
-        0 <--+ |
-        |    | |
-        v    | |
-    +-> 1 -> 3 4 5
-    |   |      | |
-    |   v      | |
-    +-- 2 <----+-+
-         */
-    let graph =
-        TestGraph::new(0, &[(0, 1), (0, 4), (1, 2), (1, 3), (2, 1), (3, 0), (4, 2), (5, 2)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
-    assert_eq!(sccs.num_sccs(), 2);
-    assert_eq!(sccs.scc(0), 0);
-    assert_eq!(sccs.scc(1), 0);
-    assert_eq!(sccs.scc(2), 0);
-    assert_eq!(sccs.scc(3), 0);
-    assert_eq!(sccs.scc(4), 0);
-    assert_eq!(sccs.scc(5), 1);
-    assert_eq!(sccs.successors(0), &[]);
-    assert_eq!(sccs.successors(1), &[0]);
-}
-
-#[test]
-fn test_deep_linear() {
-    /*
-    0
-    |
-    v
-    1
-    |
-    v
-    2
-    |
-    v
-    …
-     */
-    const NR_NODES: usize = 1 << 14;
-    let mut nodes = vec![];
-    for i in 1..NR_NODES {
-        nodes.push((i - 1, i));
-    }
-    let graph = TestGraph::new(0, nodes.as_slice());
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
-    assert_eq!(sccs.num_sccs(), NR_NODES);
-    assert_eq!(sccs.scc(0), NR_NODES - 1);
-    assert_eq!(sccs.scc(NR_NODES - 1), 0);
-}
-
-#[bench]
-fn bench_sccc(b: &mut test::Bencher) {
-    // Like `test_three_sccs` but each state is replaced by a group of
-    // three or four to have some amount of test data.
-    /*
-       0-3
-        |
-        v
-    +->4-6 11-14
-    |   |    |
-    |   v    |
-    +--7-10<-+
-         */
-    fn make_3_clique(slice: &mut [(usize, usize)], base: usize) {
-        slice[0] = (base + 0, base + 1);
-        slice[1] = (base + 1, base + 2);
-        slice[2] = (base + 2, base + 0);
-    }
-    // Not actually a clique but strongly connected.
-    fn make_4_clique(slice: &mut [(usize, usize)], base: usize) {
-        slice[0] = (base + 0, base + 1);
-        slice[1] = (base + 1, base + 2);
-        slice[2] = (base + 2, base + 3);
-        slice[3] = (base + 3, base + 0);
-        slice[4] = (base + 1, base + 3);
-        slice[5] = (base + 2, base + 1);
-    }
-
-    let mut graph = [(0, 0); 6 + 3 + 6 + 3 + 4];
-    make_4_clique(&mut graph[0..6], 0);
-    make_3_clique(&mut graph[6..9], 4);
-    make_4_clique(&mut graph[9..15], 7);
-    make_3_clique(&mut graph[15..18], 11);
-    graph[18] = (0, 4);
-    graph[19] = (5, 7);
-    graph[20] = (11, 10);
-    graph[21] = (7, 4);
-    let graph = TestGraph::new(0, &graph[..]);
-    b.iter(|| {
-        let sccs: Sccs<_, usize> = Sccs::new(&graph);
-        assert_eq!(sccs.num_sccs(), 3);
-    });
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/tests.rs
deleted file mode 100644
index 7f4ef906b3..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/tests.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-use crate::fx::FxHashMap;
-use std::cmp::max;
-use std::iter;
-use std::slice;
-
-use super::*;
-
-pub struct TestGraph {
-    num_nodes: usize,
-    start_node: usize,
-    successors: FxHashMap>,
-    predecessors: FxHashMap>,
-}
-
-impl TestGraph {
-    pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self {
-        let mut graph = TestGraph {
-            num_nodes: start_node + 1,
-            start_node,
-            successors: FxHashMap::default(),
-            predecessors: FxHashMap::default(),
-        };
-        for &(source, target) in edges {
-            graph.num_nodes = max(graph.num_nodes, source + 1);
-            graph.num_nodes = max(graph.num_nodes, target + 1);
-            graph.successors.entry(source).or_default().push(target);
-            graph.predecessors.entry(target).or_default().push(source);
-        }
-        for node in 0..graph.num_nodes {
-            graph.successors.entry(node).or_default();
-            graph.predecessors.entry(node).or_default();
-        }
-        graph
-    }
-}
-
-impl DirectedGraph for TestGraph {
-    type Node = usize;
-}
-
-impl WithStartNode for TestGraph {
-    fn start_node(&self) -> usize {
-        self.start_node
-    }
-}
-
-impl WithNumNodes for TestGraph {
-    fn num_nodes(&self) -> usize {
-        self.num_nodes
-    }
-}
-
-impl WithPredecessors for TestGraph {
-    fn predecessors(&self, node: usize) -> >::Iter {
-        self.predecessors[&node].iter().cloned()
-    }
-}
-
-impl WithSuccessors for TestGraph {
-    fn successors(&self, node: usize) -> >::Iter {
-        self.successors[&node].iter().cloned()
-    }
-}
-
-impl<'graph> GraphPredecessors<'graph> for TestGraph {
-    type Item = usize;
-    type Iter = iter::Cloned>;
-}
-
-impl<'graph> GraphSuccessors<'graph> for TestGraph {
-    type Item = usize;
-    type Iter = iter::Cloned>;
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/mod.rs
deleted file mode 100644
index 4ed8887841..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/mod.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
-use rustc_index::vec::{Idx, IndexVec};
-
-#[cfg(test)]
-mod tests;
-
-pub struct VecGraph {
-    /// Maps from a given node to an index where the set of successors
-    /// for that node starts. The index indexes into the `edges`
-    /// vector. To find the range for a given node, we look up the
-    /// start for that node and then the start for the next node
-    /// (i.e., with an index 1 higher) and get the range between the
-    /// two. This vector always has an extra entry so that this works
-    /// even for the max element.
-    node_starts: IndexVec,
-
-    edge_targets: Vec,
-}
-
-impl VecGraph {
-    pub fn new(num_nodes: usize, mut edge_pairs: Vec<(N, N)>) -> Self {
-        // Sort the edges by the source -- this is important.
-        edge_pairs.sort();
-
-        let num_edges = edge_pairs.len();
-
-        // Store the *target* of each edge into `edge_targets`.
-        let edge_targets: Vec = edge_pairs.iter().map(|&(_, target)| target).collect();
-
-        // Create the *edge starts* array. We are iterating over over
-        // the (sorted) edge pairs. We maintain the invariant that the
-        // length of the `node_starts` array is enough to store the
-        // current source node -- so when we see that the source node
-        // for an edge is greater than the current length, we grow the
-        // edge-starts array by just enough.
-        let mut node_starts = IndexVec::with_capacity(num_edges);
-        for (index, &(source, _)) in edge_pairs.iter().enumerate() {
-            // If we have a list like `[(0, x), (2, y)]`:
-            //
-            // - Start out with `node_starts` of `[]`
-            // - Iterate to `(0, x)` at index 0:
-            //   - Push one entry because `node_starts.len()` (0) is <= the source (0)
-            //   - Leaving us with `node_starts` of `[0]`
-            // - Iterate to `(2, y)` at index 1:
-            //   - Push one entry because `node_starts.len()` (1) is <= the source (2)
-            //   - Push one entry because `node_starts.len()` (2) is <= the source (2)
-            //   - Leaving us with `node_starts` of `[0, 1, 1]`
-            // - Loop terminates
-            while node_starts.len() <= source.index() {
-                node_starts.push(index);
-            }
-        }
-
-        // Pad out the `node_starts` array so that it has `num_nodes +
-        // 1` entries. Continuing our example above, if `num_nodes` is
-        // be `3`, we would push one more index: `[0, 1, 1, 2]`.
-        //
-        // Interpretation of that vector:
-        //
-        // [0, 1, 1, 2]
-        //        ---- range for N=2
-        //     ---- range for N=1
-        //  ---- range for N=0
-        while node_starts.len() <= num_nodes {
-            node_starts.push(edge_targets.len());
-        }
-
-        assert_eq!(node_starts.len(), num_nodes + 1);
-
-        Self { node_starts, edge_targets }
-    }
-
-    /// Gets the successors for `source` as a slice.
-    pub fn successors(&self, source: N) -> &[N] {
-        let start_index = self.node_starts[source];
-        let end_index = self.node_starts[source.plus(1)];
-        &self.edge_targets[start_index..end_index]
-    }
-}
-
-impl DirectedGraph for VecGraph {
-    type Node = N;
-}
-
-impl WithNumNodes for VecGraph {
-    fn num_nodes(&self) -> usize {
-        self.node_starts.len() - 1
-    }
-}
-
-impl WithNumEdges for VecGraph {
-    fn num_edges(&self) -> usize {
-        self.edge_targets.len()
-    }
-}
-
-impl GraphSuccessors<'graph> for VecGraph {
-    type Item = N;
-
-    type Iter = std::iter::Cloned>;
-}
-
-impl WithSuccessors for VecGraph {
-    fn successors(&self, node: N) -> >::Iter {
-        self.successors(node).iter().cloned()
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/tests.rs
deleted file mode 100644
index c8f9792671..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/graph/vec_graph/tests.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-use super::*;
-
-fn create_graph() -> VecGraph {
-    // Create a simple graph
-    //
-    //          5
-    //          |
-    //          V
-    //    0 --> 1 --> 2
-    //          |
-    //          v
-    //          3 --> 4
-    //
-    //    6
-
-    VecGraph::new(7, vec![(0, 1), (1, 2), (1, 3), (3, 4), (5, 1)])
-}
-
-#[test]
-fn num_nodes() {
-    let graph = create_graph();
-    assert_eq!(graph.num_nodes(), 7);
-}
-
-#[test]
-fn successors() {
-    let graph = create_graph();
-    assert_eq!(graph.successors(0), &[1]);
-    assert_eq!(graph.successors(1), &[2, 3]);
-    assert_eq!(graph.successors(2), &[]);
-    assert_eq!(graph.successors(3), &[4]);
-    assert_eq!(graph.successors(4), &[]);
-    assert_eq!(graph.successors(5), &[1]);
-    assert_eq!(graph.successors(6), &[]);
-}
-
-#[test]
-fn dfs() {
-    let graph = create_graph();
-    let dfs: Vec<_> = graph.depth_first_search(0).collect();
-    assert_eq!(dfs, vec![0, 1, 3, 4, 2]);
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/jobserver.rs b/vendor/rustc-ap-rustc_data_structures/src/jobserver.rs
deleted file mode 100644
index 41605afb44..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/jobserver.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-pub use jobserver_crate::Client;
-use std::lazy::SyncLazy;
-
-// We can only call `from_env` once per process
-
-// Note that this is unsafe because it may misinterpret file descriptors
-// on Unix as jobserver file descriptors. We hopefully execute this near
-// the beginning of the process though to ensure we don't get false
-// positives, or in other words we try to execute this before we open
-// any file descriptors ourselves.
-//
-// Pick a "reasonable maximum" if we don't otherwise have
-// a jobserver in our environment, capping out at 32 so we
-// don't take everything down by hogging the process run queue.
-// The fixed number is used to have deterministic compilation
-// across machines.
-//
-// Also note that we stick this in a global because there could be
-// multiple rustc instances in this process, and the jobserver is
-// per-process.
-static GLOBAL_CLIENT: SyncLazy = SyncLazy::new(|| unsafe {
-    Client::from_env().unwrap_or_else(|| {
-        let client = Client::new(32).expect("failed to create jobserver");
-        // Acquire a token for the main thread which we can release later
-        client.acquire_raw().ok();
-        client
-    })
-});
-
-pub fn client() -> Client {
-    GLOBAL_CLIENT.clone()
-}
-
-pub fn acquire_thread() {
-    GLOBAL_CLIENT.acquire_raw().ok();
-}
-
-pub fn release_thread() {
-    GLOBAL_CLIENT.release_raw().ok();
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/lib.rs b/vendor/rustc-ap-rustc_data_structures/src/lib.rs
deleted file mode 100644
index 5880bbd3de..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/lib.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-//! Various data structures used by the Rust compiler. The intention
-//! is that code in here should be not be *specific* to rustc, so that
-//! it can be easily unit tested and so forth.
-//!
-//! # Note
-//!
-//! This API is completely unstable and subject to change.
-
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(array_windows)]
-#![feature(control_flow_enum)]
-#![feature(in_band_lifetimes)]
-#![feature(unboxed_closures)]
-#![feature(generator_trait)]
-#![feature(fn_traits)]
-#![feature(int_bits_const)]
-#![feature(min_specialization)]
-#![feature(auto_traits)]
-#![feature(nll)]
-#![feature(allow_internal_unstable)]
-#![feature(hash_raw_entry)]
-#![feature(stmt_expr_attributes)]
-#![feature(core_intrinsics)]
-#![feature(test)]
-#![feature(associated_type_bounds)]
-#![feature(thread_id_value)]
-#![feature(extend_one)]
-#![feature(const_panic)]
-#![cfg_attr(bootstrap, feature(min_const_generics))]
-#![feature(new_uninit)]
-#![feature(once_cell)]
-#![feature(maybe_uninit_uninit_array)]
-#![allow(rustc::default_hash_types)]
-#![deny(unaligned_references)]
-
-#[macro_use]
-extern crate tracing;
-#[macro_use]
-extern crate cfg_if;
-#[macro_use]
-extern crate rustc_macros;
-
-#[inline(never)]
-#[cold]
-pub fn cold_path R, R>(f: F) -> R {
-    f()
-}
-
-#[macro_export]
-macro_rules! likely {
-    ($e:expr) => {
-        match $e {
-            #[allow(unused_unsafe)]
-            e => unsafe { std::intrinsics::likely(e) },
-        }
-    };
-}
-
-#[macro_export]
-macro_rules! unlikely {
-    ($e:expr) => {
-        match $e {
-            #[allow(unused_unsafe)]
-            e => unsafe { std::intrinsics::unlikely(e) },
-        }
-    };
-}
-
-pub mod base_n;
-pub mod binary_search_util;
-pub mod box_region;
-pub mod captures;
-pub mod const_cstr;
-pub mod flock;
-pub mod functor;
-pub mod fx;
-pub mod graph;
-pub mod jobserver;
-pub mod macros;
-pub mod map_in_place;
-pub mod obligation_forest;
-pub mod owning_ref;
-pub mod ptr_key;
-pub mod sip128;
-pub mod small_c_str;
-pub mod snapshot_map;
-pub mod stable_map;
-pub mod svh;
-pub use ena::snapshot_vec;
-pub mod sorted_map;
-pub mod stable_set;
-#[macro_use]
-pub mod stable_hasher;
-mod atomic_ref;
-pub mod fingerprint;
-pub mod profiling;
-pub mod sharded;
-pub mod stack;
-pub mod sync;
-pub mod thin_vec;
-pub mod tiny_list;
-pub mod transitive_relation;
-pub mod vec_linked_list;
-pub mod work_queue;
-pub use atomic_ref::AtomicRef;
-pub mod frozen;
-pub mod sso;
-pub mod steal;
-pub mod tagged_ptr;
-pub mod temp_dir;
-pub mod unhash;
-
-pub use ena::undo_log;
-pub use ena::unify;
-
-pub struct OnDrop(pub F);
-
-impl OnDrop {
-    /// Forgets the function which prevents it from running.
-    /// Ensure that the function owns no memory, otherwise it will be leaked.
-    #[inline]
-    pub fn disable(self) {
-        std::mem::forget(self);
-    }
-}
-
-impl Drop for OnDrop {
-    #[inline]
-    fn drop(&mut self) {
-        (self.0)();
-    }
-}
-
-// See comments in src/librustc_middle/lib.rs
-#[doc(hidden)]
-pub fn __noop_fix_for_27438() {}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/macros.rs b/vendor/rustc-ap-rustc_data_structures/src/macros.rs
deleted file mode 100644
index b918ed9458..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/macros.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-/// Type size assertion. The first argument is a type and the second argument is its expected size.
-#[macro_export]
-macro_rules! static_assert_size {
-    ($ty:ty, $size:expr) => {
-        const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
-    };
-}
-
-#[macro_export]
-macro_rules! enum_from_u32 {
-    ($(#[$attr:meta])* pub enum $name:ident {
-        $($variant:ident = $e:expr,)*
-    }) => {
-        $(#[$attr])*
-        pub enum $name {
-            $($variant = $e),*
-        }
-
-        impl $name {
-            pub fn from_u32(u: u32) -> Option<$name> {
-                $(if u == $name::$variant as u32 {
-                    return Some($name::$variant)
-                })*
-                None
-            }
-        }
-    };
-    ($(#[$attr:meta])* pub enum $name:ident {
-        $($variant:ident,)*
-    }) => {
-        $(#[$attr])*
-        pub enum $name {
-            $($variant,)*
-        }
-
-        impl $name {
-            pub fn from_u32(u: u32) -> Option<$name> {
-                $(if u == $name::$variant as u32 {
-                    return Some($name::$variant)
-                })*
-                None
-            }
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/map_in_place.rs b/vendor/rustc-ap-rustc_data_structures/src/map_in_place.rs
deleted file mode 100644
index 5dd9fc6e8b..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/map_in_place.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-use smallvec::{Array, SmallVec};
-use std::ptr;
-
-pub trait MapInPlace: Sized {
-    fn map_in_place(&mut self, mut f: F)
-    where
-        F: FnMut(T) -> T,
-    {
-        self.flat_map_in_place(|e| Some(f(e)))
-    }
-
-    fn flat_map_in_place(&mut self, f: F)
-    where
-        F: FnMut(T) -> I,
-        I: IntoIterator;
-}
-
-impl MapInPlace for Vec {
-    fn flat_map_in_place(&mut self, mut f: F)
-    where
-        F: FnMut(T) -> I,
-        I: IntoIterator,
-    {
-        let mut read_i = 0;
-        let mut write_i = 0;
-        unsafe {
-            let mut old_len = self.len();
-            self.set_len(0); // make sure we just leak elements in case of panic
-
-            while read_i < old_len {
-                // move the read_i'th item out of the vector and map it
-                // to an iterator
-                let e = ptr::read(self.get_unchecked(read_i));
-                let iter = f(e).into_iter();
-                read_i += 1;
-
-                for e in iter {
-                    if write_i < read_i {
-                        ptr::write(self.get_unchecked_mut(write_i), e);
-                        write_i += 1;
-                    } else {
-                        // If this is reached we ran out of space
-                        // in the middle of the vector.
-                        // However, the vector is in a valid state here,
-                        // so we just do a somewhat inefficient insert.
-                        self.set_len(old_len);
-                        self.insert(write_i, e);
-
-                        old_len = self.len();
-                        self.set_len(0);
-
-                        read_i += 1;
-                        write_i += 1;
-                    }
-                }
-            }
-
-            // write_i tracks the number of actually written new items.
-            self.set_len(write_i);
-        }
-    }
-}
-
-impl> MapInPlace for SmallVec {
-    fn flat_map_in_place(&mut self, mut f: F)
-    where
-        F: FnMut(T) -> I,
-        I: IntoIterator,
-    {
-        let mut read_i = 0;
-        let mut write_i = 0;
-        unsafe {
-            let mut old_len = self.len();
-            self.set_len(0); // make sure we just leak elements in case of panic
-
-            while read_i < old_len {
-                // move the read_i'th item out of the vector and map it
-                // to an iterator
-                let e = ptr::read(self.get_unchecked(read_i));
-                let iter = f(e).into_iter();
-                read_i += 1;
-
-                for e in iter {
-                    if write_i < read_i {
-                        ptr::write(self.get_unchecked_mut(write_i), e);
-                        write_i += 1;
-                    } else {
-                        // If this is reached we ran out of space
-                        // in the middle of the vector.
-                        // However, the vector is in a valid state here,
-                        // so we just do a somewhat inefficient insert.
-                        self.set_len(old_len);
-                        self.insert(write_i, e);
-
-                        old_len = self.len();
-                        self.set_len(0);
-
-                        read_i += 1;
-                        write_i += 1;
-                    }
-                }
-            }
-
-            // write_i tracks the number of actually written new items.
-            self.set_len(write_i);
-        }
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/graphviz.rs b/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/graphviz.rs
deleted file mode 100644
index 3a268e4b4f..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/graphviz.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-use crate::obligation_forest::{ForestObligation, ObligationForest};
-use rustc_graphviz as dot;
-use std::env::var_os;
-use std::fs::File;
-use std::io::BufWriter;
-use std::path::Path;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
-
-impl ObligationForest {
-    /// Creates a graphviz representation of the obligation forest. Given a directory this will
-    /// create files with name of the format `_.gv`. The counter is
-    /// global and is maintained internally.
-    ///
-    /// Calling this will do nothing unless the environment variable
-    /// `DUMP_OBLIGATION_FOREST_GRAPHVIZ` is defined.
-    ///
-    /// A few post-processing that you might want to do make the forest easier to visualize:
-    ///
-    ///  * `sed 's,std::[a-z]*::,,g'` — Deletes the `std::::` prefix of paths.
-    ///  * `sed 's,"Binder(TraitPredicate(<\(.*\)>)) (\([^)]*\))","\1 (\2)",'` — Transforms
-    ///    `Binder(TraitPredicate())` into just ``.
-    #[allow(dead_code)]
-    pub fn dump_graphviz>(&self, dir: P, description: &str) {
-        static COUNTER: AtomicUsize = AtomicUsize::new(0);
-
-        if var_os("DUMP_OBLIGATION_FOREST_GRAPHVIZ").is_none() {
-            return;
-        }
-
-        let counter = COUNTER.fetch_add(1, Ordering::AcqRel);
-
-        let file_path = dir.as_ref().join(format!("{:010}_{}.gv", counter, description));
-
-        let mut gv_file = BufWriter::new(File::create(file_path).unwrap());
-
-        dot::render(&self, &mut gv_file).unwrap();
-    }
-}
-
-impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest {
-    type Node = usize;
-    type Edge = (usize, usize);
-
-    fn graph_id(&self) -> dot::Id<'_> {
-        dot::Id::new("trait_obligation_forest").unwrap()
-    }
-
-    fn node_id(&self, index: &Self::Node) -> dot::Id<'_> {
-        dot::Id::new(format!("obligation_{}", index)).unwrap()
-    }
-
-    fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> {
-        let node = &self.nodes[*index];
-        let label = format!("{:?} ({:?})", node.obligation.as_cache_key(), node.state.get());
-
-        dot::LabelText::LabelStr(label.into())
-    }
-
-    fn edge_label(&self, (_index_source, _index_target): &Self::Edge) -> dot::LabelText<'_> {
-        dot::LabelText::LabelStr("".into())
-    }
-}
-
-impl<'a, O: ForestObligation + 'a> dot::GraphWalk<'a> for &'a ObligationForest {
-    type Node = usize;
-    type Edge = (usize, usize);
-
-    fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
-        (0..self.nodes.len()).collect()
-    }
-
-    fn edges(&self) -> dot::Edges<'_, Self::Edge> {
-        (0..self.nodes.len())
-            .flat_map(|i| {
-                let node = &self.nodes[i];
-
-                node.dependents.iter().map(move |&d| (d, i))
-            })
-            .collect()
-    }
-
-    fn source(&self, (s, _): &Self::Edge) -> Self::Node {
-        *s
-    }
-
-    fn target(&self, (_, t): &Self::Edge) -> Self::Node {
-        *t
-    }
-}
diff --git a/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/mod.rs
deleted file mode 100644
index a5b2df1da5..0000000000
--- a/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/mod.rs
+++ /dev/null
@@ -1,723 +0,0 @@
-//! The `ObligationForest` is a utility data structure used in trait
-//! matching to track the set of outstanding obligations (those not yet
-//! resolved to success or error). It also tracks the "backtrace" of each
-//! pending obligation (why we are trying to figure this out in the first
-//! place).
-//!
-//! ### External view
-//!
-//! `ObligationForest` supports two main public operations (there are a
-//! few others not discussed here):
-//!
-//! 1. Add a new root obligations (`register_obligation`).
-//! 2. Process the pending obligations (`process_obligations`).
-//!
-//! When a new obligation `N` is added, it becomes the root of an
-//! obligation tree. This tree can also carry some per-tree state `T`,
-//! which is given at the same time. This tree is a singleton to start, so
-//! `N` is both the root and the only leaf. Each time the
-//! `process_obligations` method is called, it will invoke its callback
-//! with every pending obligation (so that will include `N`, the first
-//! time). The callback also receives a (mutable) reference to the
-//! per-tree state `T`. The callback should process the obligation `O`
-//! that it is given and return a `ProcessResult`:
-//!
-//! - `Unchanged` -> ambiguous result. Obligation was neither a success
-//!   nor a failure. It is assumed that further attempts to process the
-//!   obligation will yield the same result unless something in the
-//!   surrounding environment changes.
-//! - `Changed(C)` - the obligation was *shallowly successful*. The
-//!   vector `C` is a list of subobligations. The meaning of this is that
-//!   `O` was successful on the assumption that all the obligations in `C`
-//!   are also successful. Therefore, `O` is only considered a "true"
-//!   success if `C` is empty. Otherwise, `O` is put into a suspended
-//!   state and the obligations in `C` become the new pending
-//!   obligations. They will be processed the next time you call
-//!   `process_obligations`.
-//! - `Error(E)` -> obligation failed with error `E`. We will collect this
-//!   error and return it from `process_obligations`, along with the
-//!   "backtrace" of obligations (that is, the list of obligations up to
-//!   and including the root of the failed obligation). No further
-//!   obligations from that same tree will be processed, since the tree is
-//!   now considered to be in error.
-//!
-//! When the call to `process_obligations` completes, you get back an `Outcome`,
-//! which includes three bits of information:
-//!
-//! - `completed`: a list of obligations where processing was fully
-//!   completed without error (meaning that all transitive subobligations
-//!   have also been completed). So, for example, if the callback from
-//!   `process_obligations` returns `Changed(C)` for some obligation `O`,
-//!   then `O` will be considered completed right away if `C` is the
-//!   empty vector. Otherwise it will only be considered completed once
-//!   all the obligations in `C` have been found completed.
-//! - `errors`: a list of errors that occurred and associated backtraces
-//!   at the time of error, which can be used to give context to the user.
-//! - `stalled`: if true, then none of the existing obligations were
-//!   *shallowly successful* (that is, no callback returned `Changed(_)`).
-//!   This implies that all obligations were either errors or returned an
-//!   ambiguous result, which means that any further calls to
-//!   `process_obligations` would simply yield back further ambiguous
-//!   results. This is used by the `FulfillmentContext` to decide when it
-//!   has reached a steady state.
-//!
-//! ### Implementation details
-//!
-//! For the most part, comments specific to the implementation are in the
-//! code. This file only contains a very high-level overview. Basically,
-//! the forest is stored in a vector. Each element of the vector is a node
-//! in some tree. Each node in the vector has the index of its dependents,
-//! including the first dependent which is known as the parent. It also
-//! has a current state, described by `NodeState`. After each processing
-//! step, we compress the vector to remove completed and error nodes, which
-//! aren't needed anymore.
-
-use crate::fx::{FxHashMap, FxHashSet};
-
-use std::cell::Cell;
-use std::collections::hash_map::Entry;
-use std::fmt::Debug;
-use std::hash;
-use std::marker::PhantomData;
-
-mod graphviz;
-
-#[cfg(test)]
-mod tests;
-
-pub trait ForestObligation: Clone + Debug {
-    type CacheKey: Clone + hash::Hash + Eq + Debug;
-
-    /// Converts this `ForestObligation` suitable for use as a cache key.
-    /// If two distinct `ForestObligations`s return the same cache key,
-    /// then it must be sound to use the result of processing one obligation
-    /// (e.g. success for error) for the other obligation
-    fn as_cache_key(&self) -> Self::CacheKey;
-}
-
-pub trait ObligationProcessor {
-    type Obligation: ForestObligation;
-    type Error: Debug;
-
-    fn process_obligation(
-        &mut self,
-        obligation: &mut Self::Obligation,
-    ) -> ProcessResult;
-
-    /// As we do the cycle check, we invoke this callback when we
-    /// encounter an actual cycle. `cycle` is an iterator that starts
-    /// at the start of the cycle in the stack and walks **toward the
-    /// top**.
-    ///
-    /// In other words, if we had O1 which required O2 which required
-    /// O3 which required O1, we would give an iterator yielding O1,
-    /// O2, O3 (O1 is not yielded twice).
-    fn process_backedge<'c, I>(&mut self, cycle: I, _marker: PhantomData<&'c Self::Obligation>)
-    where
-        I: Clone + Iterator;
-}
-
-/// The result type used by `process_obligation`.
-#[derive(Debug)]
-pub enum ProcessResult {
-    Unchanged,
-    Changed(Vec),
-    Error(E),
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-struct ObligationTreeId(usize);
-
-type ObligationTreeIdGenerator =
-    std::iter::Map, fn(usize) -> ObligationTreeId>;
-
-pub struct ObligationForest {
-    /// The list of obligations. In between calls to `process_obligations`,
-    /// this list only contains nodes in the `Pending` or `Waiting` state.
-    ///
-    /// `usize` indices are used here and throughout this module, rather than
-    /// `rustc_index::newtype_index!` indices, because this code is hot enough
-    /// that the `u32`-to-`usize` conversions that would be required are
-    /// significant, and space considerations are not important.
-    nodes: Vec>,
-
-    /// A cache of predicates that have been successfully completed.
-    done_cache: FxHashSet,
-
-    /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
-    /// its contents are not guaranteed to match those of `nodes`. See the
-    /// comments in `process_obligation` for details.
-    active_cache: FxHashMap,
-
-    /// A vector reused in compress() and find_cycles_from_node(), to avoid allocating new vectors.
-    reused_node_vec: Vec,
-
-    obligation_tree_id_generator: ObligationTreeIdGenerator,
-
-    /// Per tree error cache. This is used to deduplicate errors,
-    /// which is necessary to avoid trait resolution overflow in
-    /// some cases.
-    ///
-    /// See [this][details] for details.
-    ///
-    /// [details]: https://github.com/rust-lang/rust/pull/53255#issuecomment-421184780
-    error_cache: FxHashMap>,
-}
-
-#[derive(Debug)]
-struct Node {
-    obligation: O,
-    state: Cell,
-
-    /// Obligations that depend on this obligation for their completion. They
-    /// must all be in a non-pending state.
-    dependents: Vec,
-
-    /// If true, `dependents[0]` points to a "parent" node, which requires
-    /// special treatment upon error but is otherwise treated the same.
-    /// (It would be more idiomatic to store the parent node in a separate
-    /// `Option` field, but that slows down the common case of
-    /// iterating over the parent and other descendants together.)
-    has_parent: bool,
-
-    /// Identifier of the obligation tree to which this node belongs.
-    obligation_tree_id: ObligationTreeId,
-}
-
-impl Node {
-    fn new(parent: Option, obligation: O, obligation_tree_id: ObligationTreeId) -> Node {
-        Node {
-            obligation,
-            state: Cell::new(NodeState::Pending),
-            dependents: if let Some(parent_index) = parent { vec![parent_index] } else { vec![] },
-            has_parent: parent.is_some(),
-            obligation_tree_id,
-        }
-    }
-}
-
-/// The state of one node in some tree within the forest. This represents the
-/// current state of processing for the obligation (of type `O`) associated
-/// with this node.
-///
-/// The non-`Error` state transitions are as follows.
-/// ```
-/// (Pre-creation)
-///  |
-///  |     register_obligation_at() (called by process_obligations() and
-///  v                               from outside the crate)
-/// Pending
-///  |
-///  |     process_obligations()
-///  v
-/// Success
-///  |  ^
-///  |  |  mark_successes()
-///  |  v
-///  |  Waiting
-///  |
-///  |     process_cycles()
-///  v
-/// Done
-///  |
-///  |     compress()
-///  v
-/// (Removed)
-/// ```
-/// The `Error` state can be introduced in several places, via `error_at()`.
-///
-/// Outside of `ObligationForest` methods, nodes should be either `Pending` or
-/// `Waiting`.
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-enum NodeState {
-    /// This obligation has not yet been selected successfully. Cannot have
-    /// subobligations.
-    Pending,
-
-    /// This obligation was selected successfully, but may or may not have
-    /// subobligations.
-    Success,
-
-    /// This obligation was selected successfully, but it has a pending
-    /// subobligation.
-    Waiting,
-
-    /// This obligation, along with its subobligations, are complete, and will
-    /// be removed in the next collection.
-    Done,
-
-    /// This obligation was resolved to an error. It will be removed by the
-    /// next compression step.
-    Error,
-}
-
-/// This trait allows us to have two different Outcome types:
-///  - the normal one that does as little as possible
-///  - one for tests that does some additional work and checking
-pub trait OutcomeTrait {
-    type Error;
-    type Obligation;
-
-    fn new() -> Self;
-    fn mark_not_stalled(&mut self);
-    fn is_stalled(&self) -> bool;
-    fn record_completed(&mut self, outcome: &Self::Obligation);
-    fn record_error(&mut self, error: Self::Error);
-}
-
-#[derive(Debug)]
-pub struct Outcome {
-    /// Backtrace of obligations that were found to be in error.
-    pub errors: Vec>,
-
-    /// If true, then we saw no successful obligations, which means
-    /// there is no point in further iteration. This is based on the
-    /// assumption that when trait matching returns `Error` or
-    /// `Unchanged`, those results do not affect environmental
-    /// inference state. (Note that if we invoke `process_obligations`
-    /// with no pending obligations, stalled will be true.)
-    pub stalled: bool,
-}
-
-impl OutcomeTrait for Outcome {
-    type Error = Error;
-    type Obligation = O;
-
-    fn new() -> Self {
-        Self { stalled: true, errors: vec![] }
-    }
-
-    fn mark_not_stalled(&mut self) {
-        self.stalled = false;
-    }
-
-    fn is_stalled(&self) -> bool {
-        self.stalled
-    }
-
-    fn record_completed(&mut self, _outcome: &Self::Obligation) {
-        // do nothing
-    }
-
-    fn record_error(&mut self, error: Self::Error) {
-        self.errors.push(error)
-    }
-}
-
-#[derive(Debug, PartialEq, Eq)]
-pub struct Error {
-    pub error: E,
-    pub backtrace: Vec,
-}
-
-impl ObligationForest {
-    pub fn new() -> ObligationForest {
-        ObligationForest {
-            nodes: vec![],
-            done_cache: Default::default(),
-            active_cache: Default::default(),
-            reused_node_vec: vec![],
-            obligation_tree_id_generator: (0..).map(ObligationTreeId),
-            error_cache: Default::default(),
-        }
-    }
-
-    /// Returns the total number of nodes in the forest that have not
-    /// yet been fully resolved.
-    pub fn len(&self) -> usize {
-        self.nodes.len()
-    }
-
-    /// Registers an obligation.
-    pub fn register_obligation(&mut self, obligation: O) {
-        // Ignore errors here - there is no guarantee of success.
-        let _ = self.register_obligation_at(obligation, None);
-    }
-
-    // Returns Err(()) if we already know this obligation failed.
-    fn register_obligation_at(&mut self, obligation: O, parent: Option) -> Result<(), ()> {
-        if self.done_cache.contains(&obligation.as_cache_key()) {
-            debug!("register_obligation_at: ignoring already done obligation: {:?}", obligation);
-            return Ok(());
-        }
-
-        match self.active_cache.entry(obligation.as_cache_key()) {
-            Entry::Occupied(o) => {
-                let node = &mut self.nodes[*o.get()];
-                if let Some(parent_index) = parent {
-                    // If the node is already in `active_cache`, it has already
-                    // had its chance to be marked with a parent. So if it's
-                    // not already present, just dump `parent` into the
-                    // dependents as a non-parent.
-                    if !node.dependents.contains(&parent_index) {
-                        node.dependents.push(parent_index);
-                    }
-                }
-                if let NodeState::Error = node.state.get() { Err(()) } else { Ok(()) }
-            }
-            Entry::Vacant(v) => {
-                let obligation_tree_id = match parent {
-                    Some(parent_index) => self.nodes[parent_index].obligation_tree_id,
-                    None => self.obligation_tree_id_generator.next().unwrap(),
-                };
-
-                let already_failed = parent.is_some()
-                    && self
-                        .error_cache
-                        .get(&obligation_tree_id)
-                        .map(|errors| errors.contains(&obligation.as_cache_key()))
-                        .unwrap_or(false);
-
-                if already_failed {
-                    Err(())
-                } else {
-                    let new_index = self.nodes.len();
-                    v.insert(new_index);
-                    self.nodes.push(Node::new(parent, obligation, obligation_tree_id));
-                    Ok(())
-                }
-            }
-        }
-    }
-
-    /// Converts all remaining obligations to the given error.
-    pub fn to_errors(&mut self, error: E) -> Vec> {
-        let errors = self
-            .nodes
-            .iter()
-            .enumerate()
-            .filter(|(_index, node)| node.state.get() == NodeState::Pending)
-            .map(|(index, _node)| Error { error: error.clone(), backtrace: self.error_at(index) })
-            .collect();
-
-        self.compress(|_| assert!(false));
-        errors
-    }
-
-    /// Returns the set of obligations that are in a pending state.
-    pub fn map_pending_obligations(&self, f: F) -> Vec

- where - F: Fn(&O) -> P, - { - self.nodes - .iter() - .filter(|node| node.state.get() == NodeState::Pending) - .map(|node| f(&node.obligation)) - .collect() - } - - fn insert_into_error_cache(&mut self, index: usize) { - let node = &self.nodes[index]; - self.error_cache - .entry(node.obligation_tree_id) - .or_default() - .insert(node.obligation.as_cache_key()); - } - - /// Performs a pass through the obligation list. This must - /// be called in a loop until `outcome.stalled` is false. - /// - /// This _cannot_ be unrolled (presently, at least). - pub fn process_obligations(&mut self, processor: &mut P) -> OUT - where - P: ObligationProcessor, - OUT: OutcomeTrait>, - { - let mut outcome = OUT::new(); - - // Note that the loop body can append new nodes, and those new nodes - // will then be processed by subsequent iterations of the loop. - // - // We can't use an iterator for the loop because `self.nodes` is - // appended to and the borrow checker would complain. We also can't use - // `for index in 0..self.nodes.len() { ... }` because the range would - // be computed with the initial length, and we would miss the appended - // nodes. Therefore we use a `while` loop. - let mut index = 0; - while let Some(node) = self.nodes.get_mut(index) { - // `processor.process_obligation` can modify the predicate within - // `node.obligation`, and that predicate is the key used for - // `self.active_cache`. This means that `self.active_cache` can get - // out of sync with `nodes`. It's not very common, but it does - // happen, and code in `compress` has to allow for it. - if node.state.get() != NodeState::Pending { - index += 1; - continue; - } - - match processor.process_obligation(&mut node.obligation) { - ProcessResult::Unchanged => { - // No change in state. - } - ProcessResult::Changed(children) => { - // We are not (yet) stalled. - outcome.mark_not_stalled(); - node.state.set(NodeState::Success); - - for child in children { - let st = self.register_obligation_at(child, Some(index)); - if let Err(()) = st { - // Error already reported - propagate it - // to our node. - self.error_at(index); - } - } - } - ProcessResult::Error(err) => { - outcome.mark_not_stalled(); - outcome.record_error(Error { error: err, backtrace: self.error_at(index) }); - } - } - index += 1; - } - - // There's no need to perform marking, cycle processing and compression when nothing - // changed. - if !outcome.is_stalled() { - self.mark_successes(); - self.process_cycles(processor); - self.compress(|obl| outcome.record_completed(obl)); - } - - outcome - } - - /// Returns a vector of obligations for `p` and all of its - /// ancestors, putting them into the error state in the process. - fn error_at(&self, mut index: usize) -> Vec { - let mut error_stack: Vec = vec![]; - let mut trace = vec![]; - - loop { - let node = &self.nodes[index]; - node.state.set(NodeState::Error); - trace.push(node.obligation.clone()); - if node.has_parent { - // The first dependent is the parent, which is treated - // specially. - error_stack.extend(node.dependents.iter().skip(1)); - index = node.dependents[0]; - } else { - // No parent; treat all dependents non-specially. - error_stack.extend(node.dependents.iter()); - break; - } - } - - while let Some(index) = error_stack.pop() { - let node = &self.nodes[index]; - if node.state.get() != NodeState::Error { - node.state.set(NodeState::Error); - error_stack.extend(node.dependents.iter()); - } - } - - trace - } - - /// Mark all `Waiting` nodes as `Success`, except those that depend on a - /// pending node. - fn mark_successes(&self) { - // Convert all `Waiting` nodes to `Success`. - for node in &self.nodes { - if node.state.get() == NodeState::Waiting { - node.state.set(NodeState::Success); - } - } - - // Convert `Success` nodes that depend on a pending node back to - // `Waiting`. - for node in &self.nodes { - if node.state.get() == NodeState::Pending { - // This call site is hot. - self.inlined_mark_dependents_as_waiting(node); - } - } - } - - // This always-inlined function is for the hot call site. - #[inline(always)] - fn inlined_mark_dependents_as_waiting(&self, node: &Node) { - for &index in node.dependents.iter() { - let node = &self.nodes[index]; - let state = node.state.get(); - if state == NodeState::Success { - // This call site is cold. - self.uninlined_mark_dependents_as_waiting(node); - } else { - debug_assert!(state == NodeState::Waiting || state == NodeState::Error) - } - } - } - - // This never-inlined function is for the cold call site. - #[inline(never)] - fn uninlined_mark_dependents_as_waiting(&self, node: &Node) { - // Mark node Waiting in the cold uninlined code instead of the hot inlined - node.state.set(NodeState::Waiting); - self.inlined_mark_dependents_as_waiting(node) - } - - /// Report cycles between all `Success` nodes, and convert all `Success` - /// nodes to `Done`. This must be called after `mark_successes`. - fn process_cycles

(&mut self, processor: &mut P) - where - P: ObligationProcessor, - { - let mut stack = std::mem::take(&mut self.reused_node_vec); - for (index, node) in self.nodes.iter().enumerate() { - // For some benchmarks this state test is extremely hot. It's a win - // to handle the no-op cases immediately to avoid the cost of the - // function call. - if node.state.get() == NodeState::Success { - self.find_cycles_from_node(&mut stack, processor, index); - } - } - - debug_assert!(stack.is_empty()); - self.reused_node_vec = stack; - } - - fn find_cycles_from_node

(&self, stack: &mut Vec, processor: &mut P, index: usize) - where - P: ObligationProcessor, - { - let node = &self.nodes[index]; - if node.state.get() == NodeState::Success { - match stack.iter().rposition(|&n| n == index) { - None => { - stack.push(index); - for &dep_index in node.dependents.iter() { - self.find_cycles_from_node(stack, processor, dep_index); - } - stack.pop(); - node.state.set(NodeState::Done); - } - Some(rpos) => { - // Cycle detected. - processor.process_backedge( - stack[rpos..].iter().map(GetObligation(&self.nodes)), - PhantomData, - ); - } - } - } - } - - /// Compresses the vector, removing all popped nodes. This adjusts the - /// indices and hence invalidates any outstanding indices. `process_cycles` - /// must be run beforehand to remove any cycles on `Success` nodes. - #[inline(never)] - fn compress(&mut self, mut outcome_cb: impl FnMut(&O)) { - let orig_nodes_len = self.nodes.len(); - let mut node_rewrites: Vec<_> = std::mem::take(&mut self.reused_node_vec); - debug_assert!(node_rewrites.is_empty()); - node_rewrites.extend(0..orig_nodes_len); - let mut dead_nodes = 0; - - // Move removable nodes to the end, preserving the order of the - // remaining nodes. - // - // LOOP INVARIANT: - // self.nodes[0..index - dead_nodes] are the first remaining nodes - // self.nodes[index - dead_nodes..index] are all dead - // self.nodes[index..] are unchanged - for index in 0..orig_nodes_len { - let node = &self.nodes[index]; - match node.state.get() { - NodeState::Pending | NodeState::Waiting => { - if dead_nodes > 0 { - self.nodes.swap(index, index - dead_nodes); - node_rewrites[index] -= dead_nodes; - } - } - NodeState::Done => { - // This lookup can fail because the contents of - // `self.active_cache` are not guaranteed to match those of - // `self.nodes`. See the comment in `process_obligation` - // for more details. - if let Some((predicate, _)) = - self.active_cache.remove_entry(&node.obligation.as_cache_key()) - { - self.done_cache.insert(predicate); - } else { - self.done_cache.insert(node.obligation.as_cache_key().clone()); - } - // Extract the success stories. - outcome_cb(&node.obligation); - node_rewrites[index] = orig_nodes_len; - dead_nodes += 1; - } - NodeState::Error => { - // We *intentionally* remove the node from the cache at this point. Otherwise - // tests must come up with a different type on every type error they - // check against. - self.active_cache.remove(&node.obligation.as_cache_key()); - self.insert_into_error_cache(index); - node_rewrites[index] = orig_nodes_len; - dead_nodes += 1; - } - NodeState::Success => unreachable!(), - } - } - - if dead_nodes > 0 { - // Remove the dead nodes and rewrite indices. - self.nodes.truncate(orig_nodes_len - dead_nodes); - self.apply_rewrites(&node_rewrites); - } - - node_rewrites.truncate(0); - self.reused_node_vec = node_rewrites; - } - - fn apply_rewrites(&mut self, node_rewrites: &[usize]) { - let orig_nodes_len = node_rewrites.len(); - - for node in &mut self.nodes { - let mut i = 0; - while let Some(dependent) = node.dependents.get_mut(i) { - let new_index = node_rewrites[*dependent]; - if new_index >= orig_nodes_len { - node.dependents.swap_remove(i); - if i == 0 && node.has_parent { - // We just removed the parent. - node.has_parent = false; - } - } else { - *dependent = new_index; - i += 1; - } - } - } - - // This updating of `self.active_cache` is necessary because the - // removal of nodes within `compress` can fail. See above. - self.active_cache.retain(|_predicate, index| { - let new_index = node_rewrites[*index]; - if new_index >= orig_nodes_len { - false - } else { - *index = new_index; - true - } - }); - } -} - -// I need a Clone closure. -#[derive(Clone)] -struct GetObligation<'a, O>(&'a [Node]); - -impl<'a, 'b, O> FnOnce<(&'b usize,)> for GetObligation<'a, O> { - type Output = &'a O; - extern "rust-call" fn call_once(self, args: (&'b usize,)) -> &'a O { - &self.0[*args.0].obligation - } -} - -impl<'a, 'b, O> FnMut<(&'b usize,)> for GetObligation<'a, O> { - extern "rust-call" fn call_mut(&mut self, args: (&'b usize,)) -> &'a O { - &self.0[*args.0].obligation - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/tests.rs deleted file mode 100644 index 371c62c063..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/obligation_forest/tests.rs +++ /dev/null @@ -1,484 +0,0 @@ -use super::*; - -use std::fmt; -use std::marker::PhantomData; - -impl<'a> super::ForestObligation for &'a str { - type CacheKey = &'a str; - - fn as_cache_key(&self) -> Self::CacheKey { - self - } -} - -struct ClosureObligationProcessor { - process_obligation: OF, - _process_backedge: BF, - marker: PhantomData<(O, E)>, -} - -struct TestOutcome { - pub completed: Vec, - pub errors: Vec>, - pub stalled: bool, -} - -impl OutcomeTrait for TestOutcome -where - O: Clone, -{ - type Error = Error; - type Obligation = O; - - fn new() -> Self { - Self { errors: vec![], stalled: false, completed: vec![] } - } - - fn mark_not_stalled(&mut self) { - self.stalled = false; - } - - fn is_stalled(&self) -> bool { - self.stalled - } - - fn record_completed(&mut self, outcome: &Self::Obligation) { - self.completed.push(outcome.clone()) - } - - fn record_error(&mut self, error: Self::Error) { - self.errors.push(error) - } -} - -#[allow(non_snake_case)] -fn C(of: OF, bf: BF) -> ClosureObligationProcessor -where - OF: FnMut(&mut O) -> ProcessResult, - BF: FnMut(&[O]), -{ - ClosureObligationProcessor { - process_obligation: of, - _process_backedge: bf, - marker: PhantomData, - } -} - -impl ObligationProcessor for ClosureObligationProcessor -where - O: super::ForestObligation + fmt::Debug, - E: fmt::Debug, - OF: FnMut(&mut O) -> ProcessResult, - BF: FnMut(&[O]), -{ - type Obligation = O; - type Error = E; - - fn process_obligation( - &mut self, - obligation: &mut Self::Obligation, - ) -> ProcessResult { - (self.process_obligation)(obligation) - } - - fn process_backedge<'c, I>(&mut self, _cycle: I, _marker: PhantomData<&'c Self::Obligation>) - where - I: Clone + Iterator, - { - } -} - -#[test] -fn push_pop() { - let mut forest = ObligationForest::new(); - forest.register_obligation("A"); - forest.register_obligation("B"); - forest.register_obligation("C"); - - // first round, B errors out, A has subtasks, and C completes, creating this: - // A |-> A.1 - // |-> A.2 - // |-> A.3 - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), - "B" => ProcessResult::Error("B is for broken"), - "C" => ProcessResult::Changed(vec![]), - "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok, vec!["C"]); - assert_eq!(err, vec![Error { error: "B is for broken", backtrace: vec!["B"] }]); - - // second round: two delays, one success, creating an uneven set of subtasks: - // A |-> A.1 - // |-> A.2 - // |-> A.3 |-> A.3.i - // D |-> D.1 - // |-> D.2 - forest.register_obligation("D"); - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A.1" => ProcessResult::Unchanged, - "A.2" => ProcessResult::Unchanged, - "A.3" => ProcessResult::Changed(vec!["A.3.i"]), - "D" => ProcessResult::Changed(vec!["D.1", "D.2"]), - "A.3.i" | "D.1" | "D.2" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok, Vec::<&'static str>::new()); - assert_eq!(err, Vec::new()); - - // third round: ok in A.1 but trigger an error in A.2. Check that it - // propagates to A, but not D.1 or D.2. - // D |-> D.1 |-> D.1.i - // |-> D.2 |-> D.2.i - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A.1" => ProcessResult::Changed(vec![]), - "A.2" => ProcessResult::Error("A is for apple"), - "A.3.i" => ProcessResult::Changed(vec![]), - "D.1" => ProcessResult::Changed(vec!["D.1.i"]), - "D.2" => ProcessResult::Changed(vec!["D.2.i"]), - "D.1.i" | "D.2.i" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - let mut ok = ok; - ok.sort(); - assert_eq!(ok, vec!["A.1", "A.3", "A.3.i"]); - assert_eq!(err, vec![Error { error: "A is for apple", backtrace: vec!["A.2", "A"] }]); - - // fourth round: error in D.1.i - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "D.1.i" => ProcessResult::Error("D is for dumb"), - "D.2.i" => ProcessResult::Changed(vec![]), - _ => panic!("unexpected obligation {:?}", obligation), - }, - |_| {}, - )); - let mut ok = ok; - ok.sort(); - assert_eq!(ok, vec!["D.2", "D.2.i"]); - assert_eq!(err, vec![Error { error: "D is for dumb", backtrace: vec!["D.1.i", "D.1", "D"] }]); -} - -// Test that if a tree with grandchildren succeeds, everything is -// reported as expected: -// A -// A.1 -// A.2 -// A.2.i -// A.2.ii -// A.3 -#[test] -fn success_in_grandchildren() { - let mut forest = ObligationForest::new(); - forest.register_obligation("A"); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), - "A.1" => ProcessResult::Changed(vec![]), - "A.2" => ProcessResult::Changed(vec!["A.2.i", "A.2.ii"]), - "A.3" => ProcessResult::Changed(vec![]), - "A.2.i" | "A.2.ii" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - let mut ok = ok; - ok.sort(); - assert_eq!(ok, vec!["A.1", "A.3"]); - assert!(err.is_empty()); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A.2.i" => ProcessResult::Unchanged, - "A.2.ii" => ProcessResult::Changed(vec![]), - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok, vec!["A.2.ii"]); - assert!(err.is_empty()); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A.2.i" => ProcessResult::Changed(vec!["A.2.i.a"]), - "A.2.i.a" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert!(ok.is_empty()); - assert!(err.is_empty()); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A.2.i.a" => ProcessResult::Changed(vec![]), - _ => unreachable!(), - }, - |_| {}, - )); - let mut ok = ok; - ok.sort(); - assert_eq!(ok, vec!["A", "A.2", "A.2.i", "A.2.i.a"]); - assert!(err.is_empty()); - - let TestOutcome { completed: ok, errors: err, .. } = - forest.process_obligations(&mut C(|_| unreachable!(), |_| {})); - - assert!(ok.is_empty()); - assert!(err.is_empty()); -} - -#[test] -fn to_errors_no_throw() { - // check that converting multiple children with common parent (A) - // yields to correct errors (and does not panic, in particular). - let mut forest = ObligationForest::new(); - forest.register_obligation("A"); - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), - "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err.len(), 0); - let errors = forest.to_errors(()); - assert_eq!(errors[0].backtrace, vec!["A.1", "A"]); - assert_eq!(errors[1].backtrace, vec!["A.2", "A"]); - assert_eq!(errors[2].backtrace, vec!["A.3", "A"]); - assert_eq!(errors.len(), 3); -} - -#[test] -fn diamond() { - // check that diamond dependencies are handled correctly - let mut forest = ObligationForest::new(); - forest.register_obligation("A"); - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["A.1", "A.2"]), - "A.1" | "A.2" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err.len(), 0); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A.1" => ProcessResult::Changed(vec!["D"]), - "A.2" => ProcessResult::Changed(vec!["D"]), - "D" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err.len(), 0); - - let mut d_count = 0; - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "D" => { - d_count += 1; - ProcessResult::Changed(vec![]) - } - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(d_count, 1); - let mut ok = ok; - ok.sort(); - assert_eq!(ok, vec!["A", "A.1", "A.2", "D"]); - assert_eq!(err.len(), 0); - - let errors = forest.to_errors(()); - assert_eq!(errors.len(), 0); - - forest.register_obligation("A'"); - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A'" => ProcessResult::Changed(vec!["A'.1", "A'.2"]), - "A'.1" | "A'.2" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err.len(), 0); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A'.1" => ProcessResult::Changed(vec!["D'", "A'"]), - "A'.2" => ProcessResult::Changed(vec!["D'"]), - "D'" | "A'" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err.len(), 0); - - let mut d_count = 0; - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "D'" => { - d_count += 1; - ProcessResult::Error("operation failed") - } - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(d_count, 1); - assert_eq!(ok.len(), 0); - assert_eq!( - err, - vec![super::Error { error: "operation failed", backtrace: vec!["D'", "A'.1", "A'"] }] - ); - - let errors = forest.to_errors(()); - assert_eq!(errors.len(), 0); -} - -#[test] -fn done_dependency() { - // check that the local cache works - let mut forest = ObligationForest::new(); - forest.register_obligation("A: Sized"); - forest.register_obligation("B: Sized"); - forest.register_obligation("C: Sized"); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A: Sized" | "B: Sized" | "C: Sized" => ProcessResult::Changed(vec![]), - _ => unreachable!(), - }, - |_| {}, - )); - let mut ok = ok; - ok.sort(); - assert_eq!(ok, vec!["A: Sized", "B: Sized", "C: Sized"]); - assert_eq!(err.len(), 0); - - forest.register_obligation("(A,B,C): Sized"); - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "(A,B,C): Sized" => ProcessResult::Changed(vec!["A: Sized", "B: Sized", "C: Sized"]), - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok, vec!["(A,B,C): Sized"]); - assert_eq!(err.len(), 0); -} - -#[test] -fn orphan() { - // check that orphaned nodes are handled correctly - let mut forest = ObligationForest::new(); - forest.register_obligation("A"); - forest.register_obligation("B"); - forest.register_obligation("C1"); - forest.register_obligation("C2"); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A" => ProcessResult::Changed(vec!["D", "E"]), - "B" => ProcessResult::Unchanged, - "C1" => ProcessResult::Changed(vec![]), - "C2" => ProcessResult::Changed(vec![]), - "D" | "E" => ProcessResult::Unchanged, - _ => unreachable!(), - }, - |_| {}, - )); - let mut ok = ok; - ok.sort(); - assert_eq!(ok, vec!["C1", "C2"]); - assert_eq!(err.len(), 0); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "D" | "E" => ProcessResult::Unchanged, - "B" => ProcessResult::Changed(vec!["D"]), - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err.len(), 0); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "D" => ProcessResult::Unchanged, - "E" => ProcessResult::Error("E is for error"), - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err, vec![super::Error { error: "E is for error", backtrace: vec!["E", "A"] }]); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "D" => ProcessResult::Error("D is dead"), - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err, vec![super::Error { error: "D is dead", backtrace: vec!["D"] }]); - - let errors = forest.to_errors(()); - assert_eq!(errors.len(), 0); -} - -#[test] -fn simultaneous_register_and_error() { - // check that registering a failed obligation works correctly - let mut forest = ObligationForest::new(); - forest.register_obligation("A"); - forest.register_obligation("B"); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A" => ProcessResult::Error("An error"), - "B" => ProcessResult::Changed(vec!["A"]), - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err, vec![super::Error { error: "An error", backtrace: vec!["A"] }]); - - let mut forest = ObligationForest::new(); - forest.register_obligation("B"); - forest.register_obligation("A"); - - let TestOutcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C( - |obligation| match *obligation { - "A" => ProcessResult::Error("An error"), - "B" => ProcessResult::Changed(vec!["A"]), - _ => unreachable!(), - }, - |_| {}, - )); - assert_eq!(ok.len(), 0); - assert_eq!(err, vec![super::Error { error: "An error", backtrace: vec!["A"] }]); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/owning_ref/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/owning_ref/mod.rs deleted file mode 100644 index ad4b79de23..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/owning_ref/mod.rs +++ /dev/null @@ -1,1233 +0,0 @@ -#![warn(missing_docs)] - -/*! -# An owning reference. - -This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut` -that enables it to bundle a reference together with the owner of the data it points to. -This allows moving and dropping of a `OwningRef` without needing to recreate the reference. - -This can sometimes be useful because Rust borrowing rules normally prevent -moving a type that has been moved from. For example, this kind of code gets rejected: - -```compile_fail,E0515 -fn return_owned_and_referenced<'a>() -> (Vec, &'a [u8]) { - let v = vec![1, 2, 3, 4]; - let s = &v[1..3]; - (v, s) -} -``` - -Even though, from a memory-layout point of view, this can be entirely safe -if the new location of the vector still lives longer than the lifetime `'a` -of the reference because the backing allocation of the vector does not change. - -This library enables this safe usage by keeping the owner and the reference -bundled together in a wrapper type that ensure that lifetime constraint: - -```rust -# extern crate owning_ref; -# use owning_ref::OwningRef; -# fn main() { -fn return_owned_and_referenced() -> OwningRef, [u8]> { - let v = vec![1, 2, 3, 4]; - let or = OwningRef::new(v); - let or = or.map(|v| &v[1..3]); - or -} -# } -``` - -It works by requiring owner types to dereference to stable memory locations -and preventing mutable access to root containers, which in practice requires heap allocation -as provided by `Box`, `Rc`, etc. - -Also provided are typedefs for common owner type combinations, -which allow for less verbose type signatures. -For example, `BoxRef` instead of `OwningRef, T>`. - -The crate also provides the more advanced `OwningHandle` type, -which allows more freedom in bundling a dependent handle object -along with the data it depends on, at the cost of some unsafe needed in the API. -See the documentation around `OwningHandle` for more details. - -# Examples - -## Basics - -``` -extern crate owning_ref; -use owning_ref::BoxRef; - -fn main() { - // Create an array owned by a Box. - let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>; - - // Transfer into a BoxRef. - let arr: BoxRef<[i32]> = BoxRef::new(arr); - assert_eq!(&*arr, &[1, 2, 3, 4]); - - // We can slice the array without losing ownership or changing type. - let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]); - assert_eq!(&*arr, &[2, 3]); - - // Also works for Arc, Rc, String and Vec! -} -``` - -## Caching a reference to a struct field - -``` -extern crate owning_ref; -use owning_ref::BoxRef; - -fn main() { - struct Foo { - tag: u32, - x: u16, - y: u16, - z: u16, - } - let foo = Foo { tag: 1, x: 100, y: 200, z: 300 }; - - let or = BoxRef::new(Box::new(foo)).map(|foo| { - match foo.tag { - 0 => &foo.x, - 1 => &foo.y, - 2 => &foo.z, - _ => panic!(), - } - }); - - assert_eq!(*or, 200); -} -``` - -## Caching a reference to an entry in a vector - -``` -extern crate owning_ref; -use owning_ref::VecRef; - -fn main() { - let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]); - assert_eq!(*v, 4); -} -``` - -## Caching a subslice of a String - -``` -extern crate owning_ref; -use owning_ref::StringRef; - -fn main() { - let s = StringRef::new("hello world".to_owned()) - .map(|s| s.split(' ').nth(1).unwrap()); - - assert_eq!(&*s, "world"); -} -``` - -## Reference counted slices that share ownership of the backing storage - -``` -extern crate owning_ref; -use owning_ref::RcRef; -use std::rc::Rc; - -fn main() { - let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>); - assert_eq!(&*rc, &[1, 2, 3, 4]); - - let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]); - let rc_b = rc.clone().map(|s| &s[1..3]); - let rc_c = rc.clone().map(|s| &s[2..4]); - assert_eq!(&*rc_a, &[1, 2]); - assert_eq!(&*rc_b, &[2, 3]); - assert_eq!(&*rc_c, &[3, 4]); - - let rc_c_a = rc_c.clone().map(|s| &s[1]); - assert_eq!(&*rc_c_a, &4); -} -``` - -## Atomic reference counted slices that share ownership of the backing storage - -``` -extern crate owning_ref; -use owning_ref::ArcRef; -use std::sync::Arc; - -fn main() { - use std::thread; - - fn par_sum(rc: ArcRef<[i32]>) -> i32 { - if rc.len() == 0 { - return 0; - } else if rc.len() == 1 { - return rc[0]; - } - let mid = rc.len() / 2; - let left = rc.clone().map(|s| &s[..mid]); - let right = rc.map(|s| &s[mid..]); - - let left = thread::spawn(move || par_sum(left)); - let right = thread::spawn(move || par_sum(right)); - - left.join().unwrap() + right.join().unwrap() - } - - let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]); - let rc: ArcRef<[i32]> = rc.into(); - - assert_eq!(par_sum(rc), 10); -} -``` - -## References into RAII locks - -``` -extern crate owning_ref; -use owning_ref::RefRef; -use std::cell::{RefCell, Ref}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - // Also works with Mutex and RwLock - - let refref = { - let refref = RefRef::new(refcell.borrow()).map(|x| &x.3); - assert_eq!(*refref, 4); - - // We move the RAII lock and the reference to one of - // the subfields in the data it guards here: - refref - }; - - assert_eq!(*refref, 4); - - drop(refref); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 4)); -} -``` - -## Mutable reference - -When the owned container implements `DerefMut`, it is also possible to make -a _mutable owning reference_. (e.g., with `Box`, `RefMut`, `MutexGuard`) - -``` -extern crate owning_ref; -use owning_ref::RefMutRefMut; -use std::cell::{RefCell, RefMut}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - - let mut refmut_refmut = { - let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3); - assert_eq!(*refmut_refmut, 4); - *refmut_refmut *= 2; - - refmut_refmut - }; - - assert_eq!(*refmut_refmut, 8); - *refmut_refmut *= 2; - - drop(refmut_refmut); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 16)); -} -``` -*/ - -pub use stable_deref_trait::{ - CloneStableDeref as CloneStableAddress, StableDeref as StableAddress, -}; -use std::mem; - -/// An owning reference. -/// -/// This wraps an owner `O` and a reference `&T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRef { - owner: O, - reference: *const T, -} - -/// An mutable owning reference. -/// -/// This wraps an owner `O` and a reference `&mut T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRefMut { - owner: O, - reference: *mut T, -} - -/// Helper trait for an erased concrete type an owner dereferences to. -/// This is used in form of a trait object for keeping -/// something around to (virtually) call the destructor. -pub trait Erased {} -impl Erased for T {} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box -> Box`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErased<'a> { - /// Owner with the dereference type substituted to `Erased`. - type Erased; - /// Performs the type erasure. - fn into_erased(self) -> Self::Erased; -} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box -> Box`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErasedSend<'a> { - /// Owner with the dereference type substituted to `Erased + Send`. - type Erased: Send; - /// Performs the type erasure. - fn into_erased_send(self) -> Self::Erased; -} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box -> Box`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErasedSendSync<'a> { - /// Owner with the dereference type substituted to `Erased + Send + Sync`. - type Erased: Send + Sync; - /// Performs the type erasure. - fn into_erased_send_sync(self) -> Self::Erased; -} - -///////////////////////////////////////////////////////////////////////////// -// OwningRef -///////////////////////////////////////////////////////////////////////////// - -impl OwningRef { - /// Creates a new owning reference from a owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new(42)); - /// assert_eq!(*owning_ref, 42); - /// } - /// ``` - pub fn new(o: O) -> Self - where - O: StableAddress, - O: Deref, - { - OwningRef { reference: &*o, owner: o } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(o: O) -> Self - where - O: Deref, - { - OwningRef { reference: &*o, owner: o } - } - - /// Converts `self` into a new owning reference that points at something reachable - /// from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map(self, f: F) -> OwningRef - where - O: StableAddress, - F: FnOnce(&T) -> &U, - { - OwningRef { reference: f(&self), owner: self.owner } - } - - /// Tries to convert `self` into a new owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map(self, f: F) -> Result, E> - where - O: StableAddress, - F: FnOnce(&T) -> Result<&U, E>, - { - Ok(OwningRef { reference: f(&self)?, owner: self.owner }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner(self, f: F) -> OwningRef - where - O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P, - { - OwningRef { reference: self.reference, owner: f(self.owner) } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box`. - /// - /// This can be used to safely erase the owner of any `OwningRef` - /// to a `OwningRef, T>`. - pub fn map_owner_box(self) -> OwningRef, T> { - OwningRef { reference: self.reference, owner: Box::new(self.owner) } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::{OwningRef, Erased}; - /// - /// fn main() { - /// // N.B., using the concrete types here for explicitness. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_a: OwningRef, [i32; 4]> - /// = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_b: OwningRef>, Vec<(i32, bool)>> - /// = OwningRef::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_a: OwningRef, i32> - /// = owning_ref_a.map(|a| &a[0]); - /// - /// let owning_ref_b: OwningRef>, i32> - /// = owning_ref_b.map(|a| &a[1].0); - /// - /// let owning_refs: [OwningRef, i32>; 2] - /// = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs[0], 1); - /// assert_eq!(*owning_refs[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRef - where - O: IntoErased<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased() } - } - - /// Erases the concrete base type of the owner with a trait object which implements `Send`. - /// - /// This allows mixing of owned references with different owner base types. - pub fn erase_send_owner<'a>(self) -> OwningRef - where - O: IntoErasedSend<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased_send() } - } - - /// Erases the concrete base type of the owner with a trait object - /// which implements `Send` and `Sync`. - /// - /// This allows mixing of owned references with different owner base types. - pub fn erase_send_sync_owner<'a>(self) -> OwningRef - where - O: IntoErasedSendSync<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased_send_sync() } - } - - // UNIMPLEMENTED: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -impl OwningRefMut { - /// Creates a new owning reference from a owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new(42)); - /// assert_eq!(*owning_ref_mut, 42); - /// } - /// ``` - pub fn new(mut o: O) -> Self - where - O: StableAddress, - O: DerefMut, - { - OwningRefMut { reference: &mut *o, owner: o } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(mut o: O) -> Self - where - O: DerefMut, - { - OwningRefMut { reference: &mut *o, owner: o } - } - - /// Converts `self` into a new _shared_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map(mut self, f: F) -> OwningRef - where - O: StableAddress, - F: FnOnce(&mut T) -> &U, - { - OwningRef { reference: f(&mut self), owner: self.owner } - } - - /// Converts `self` into a new _mutable_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]); - /// assert_eq!(*owning_ref_mut, 3); - /// } - /// ``` - pub fn map_mut(mut self, f: F) -> OwningRefMut - where - O: StableAddress, - F: FnOnce(&mut T) -> &mut U, - { - OwningRefMut { reference: f(&mut self), owner: self.owner } - } - - /// Tries to convert `self` into a new _shared_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map(mut self, f: F) -> Result, E> - where - O: StableAddress, - F: FnOnce(&mut T) -> Result<&U, E>, - { - Ok(OwningRef { reference: f(&mut self)?, owner: self.owner }) - } - - /// Tries to convert `self` into a new _mutable_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create a owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.try_map_mut(|array| { - /// if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref_mut.unwrap(), 3); - /// } - /// ``` - pub fn try_map_mut(mut self, f: F) -> Result, E> - where - O: StableAddress, - F: FnOnce(&mut T) -> Result<&mut U, E>, - { - Ok(OwningRefMut { reference: f(&mut self)?, owner: self.owner }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner(self, f: F) -> OwningRefMut - where - O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P, - { - OwningRefMut { reference: self.reference, owner: f(self.owner) } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box`. - /// - /// This can be used to safely erase the owner of any `OwningRefMut` - /// to a `OwningRefMut, T>`. - pub fn map_owner_box(self) -> OwningRefMut, T> { - OwningRefMut { reference: self.reference, owner: Box::new(self.owner) } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// extern crate owning_ref; - /// use owning_ref::{OwningRefMut, Erased}; - /// - /// fn main() { - /// // N.B., using the concrete types here for explicitness. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_mut_a: OwningRefMut, [i32; 4]> - /// = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_mut_b: OwningRefMut>, Vec<(i32, bool)>> - /// = OwningRefMut::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_mut_a: OwningRefMut, i32> - /// = owning_ref_mut_a.map_mut(|a| &mut a[0]); - /// - /// let owning_ref_mut_b: OwningRefMut>, i32> - /// = owning_ref_mut_b.map_mut(|a| &mut a[1].0); - /// - /// let owning_refs_mut: [OwningRefMut, i32>; 2] - /// = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs_mut[0], 1); - /// assert_eq!(*owning_refs_mut[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRefMut - where - O: IntoErased<'a>, - { - OwningRefMut { reference: self.reference, owner: self.owner.into_erased() } - } - - // UNIMPLEMENTED: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -///////////////////////////////////////////////////////////////////////////// -// OwningHandle -///////////////////////////////////////////////////////////////////////////// - -use std::ops::{Deref, DerefMut}; - -/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows -/// consumers to pass around an owned object and a dependent reference, -/// `OwningHandle` contains an owned object and a dependent _object_. -/// -/// `OwningHandle` can encapsulate a `RefMut` along with its associated -/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`. -/// However, the API is completely generic and there are no restrictions on -/// what types of owning and dependent objects may be used. -/// -/// `OwningHandle` is created by passing an owner object (which dereferences -/// to a stable address) along with a callback which receives a pointer to -/// that stable location. The callback may then dereference the pointer and -/// mint a dependent object, with the guarantee that the returned object will -/// not outlive the referent of the pointer. -/// -/// Since the callback needs to dereference a raw pointer, it requires `unsafe` -/// code. To avoid forcing this unsafety on most callers, the `ToHandle` trait is -/// implemented for common data structures. Types that implement `ToHandle` can -/// be wrapped into an `OwningHandle` without passing a callback. -pub struct OwningHandle -where - O: StableAddress, - H: Deref, -{ - handle: H, - _owner: O, -} - -impl Deref for OwningHandle -where - O: StableAddress, - H: Deref, -{ - type Target = H::Target; - fn deref(&self) -> &H::Target { - self.handle.deref() - } -} - -unsafe impl StableAddress for OwningHandle -where - O: StableAddress, - H: StableAddress, -{ -} - -impl DerefMut for OwningHandle -where - O: StableAddress, - H: DerefMut, -{ - fn deref_mut(&mut self) -> &mut H::Target { - self.handle.deref_mut() - } -} - -/// Trait to implement the conversion of owner to handle for common types. -pub trait ToHandle { - /// The type of handle to be encapsulated by the OwningHandle. - type Handle: Deref; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle(x: *const Self) -> Self::Handle; -} - -/// Trait to implement the conversion of owner to mutable handle for common types. -pub trait ToHandleMut { - /// The type of handle to be encapsulated by the OwningHandle. - type HandleMut: DerefMut; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// mutable handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut; -} - -impl OwningHandle -where - O: StableAddress>, - H: Deref, -{ - /// Creates a new `OwningHandle` for a type that implements `ToHandle`. For types - /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts - /// a callback to perform the conversion. - pub fn new(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) }) - } -} - -impl OwningHandle -where - O: StableAddress>, - H: DerefMut, -{ - /// Creates a new mutable `OwningHandle` for a type that implements `ToHandleMut`. - pub fn new_mut(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) }) - } -} - -impl OwningHandle -where - O: StableAddress, - H: Deref, -{ - /// Creates a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn new_with_fn(o: O, f: F) -> Self - where - F: FnOnce(*const O::Target) -> H, - { - let h: H; - { - h = f(o.deref() as *const O::Target); - } - - OwningHandle { handle: h, _owner: o } - } - - /// Creates a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn try_new(o: O, f: F) -> Result - where - F: FnOnce(*const O::Target) -> Result, - { - let h: H; - { - h = f(o.deref() as *const O::Target)?; - } - - Ok(OwningHandle { handle: h, _owner: o }) - } -} - -///////////////////////////////////////////////////////////////////////////// -// std traits -///////////////////////////////////////////////////////////////////////////// - -use std::borrow::Borrow; -use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; -use std::convert::From; -use std::fmt::{self, Debug}; -use std::hash::{Hash, Hasher}; -use std::marker::{Send, Sync}; - -impl Deref for OwningRef { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.reference } - } -} - -impl Deref for OwningRefMut { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.reference } - } -} - -impl DerefMut for OwningRefMut { - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.reference } - } -} - -unsafe impl StableAddress for OwningRef {} - -impl AsRef for OwningRef { - fn as_ref(&self) -> &T { - &*self - } -} - -impl AsRef for OwningRefMut { - fn as_ref(&self) -> &T { - &*self - } -} - -impl AsMut for OwningRefMut { - fn as_mut(&mut self) -> &mut T { - &mut *self - } -} - -impl Borrow for OwningRef { - fn borrow(&self) -> &T { - &*self - } -} - -impl From for OwningRef -where - O: StableAddress, - O: Deref, -{ - fn from(owner: O) -> Self { - OwningRef::new(owner) - } -} - -impl From for OwningRefMut -where - O: StableAddress, - O: DerefMut, -{ - fn from(owner: O) -> Self { - OwningRefMut::new(owner) - } -} - -impl From> for OwningRef -where - O: StableAddress, - O: DerefMut, -{ - fn from(other: OwningRefMut) -> Self { - OwningRef { owner: other.owner, reference: other.reference } - } -} - -// ^ FIXME: Is a Into impl for calling into_inner() possible as well? - -impl Debug for OwningRef -where - O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self) - } -} - -impl Debug for OwningRefMut -where - O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "OwningRefMut {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self) - } -} - -impl Clone for OwningRef -where - O: CloneStableAddress, -{ - fn clone(&self) -> Self { - OwningRef { owner: self.owner.clone(), reference: self.reference } - } -} - -unsafe impl CloneStableAddress for OwningRef where O: CloneStableAddress {} - -unsafe impl Send for OwningRef -where - O: Send, - for<'a> &'a T: Send, -{ -} -unsafe impl Sync for OwningRef -where - O: Sync, - for<'a> &'a T: Sync, -{ -} - -unsafe impl Send for OwningRefMut -where - O: Send, - for<'a> &'a mut T: Send, -{ -} -unsafe impl Sync for OwningRefMut -where - O: Sync, - for<'a> &'a mut T: Sync, -{ -} - -impl Debug for dyn Erased { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "",) - } -} - -impl PartialEq for OwningRef -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - (&*self as &T).eq(&*other as &T) - } -} - -impl Eq for OwningRef where T: Eq {} - -impl PartialOrd for OwningRef -where - T: PartialOrd, -{ - fn partial_cmp(&self, other: &Self) -> Option { - (&*self as &T).partial_cmp(&*other as &T) - } -} - -impl Ord for OwningRef -where - T: Ord, -{ - fn cmp(&self, other: &Self) -> Ordering { - (&*self as &T).cmp(&*other as &T) - } -} - -impl Hash for OwningRef -where - T: Hash, -{ - fn hash(&self, state: &mut H) { - (&*self as &T).hash(state); - } -} - -impl PartialEq for OwningRefMut -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - (&*self as &T).eq(&*other as &T) - } -} - -impl Eq for OwningRefMut where T: Eq {} - -impl PartialOrd for OwningRefMut -where - T: PartialOrd, -{ - fn partial_cmp(&self, other: &Self) -> Option { - (&*self as &T).partial_cmp(&*other as &T) - } -} - -impl Ord for OwningRefMut -where - T: Ord, -{ - fn cmp(&self, other: &Self) -> Ordering { - (&*self as &T).cmp(&*other as &T) - } -} - -impl Hash for OwningRefMut -where - T: Hash, -{ - fn hash(&self, state: &mut H) { - (&*self as &T).hash(state); - } -} - -///////////////////////////////////////////////////////////////////////////// -// std types integration and convenience type defs -///////////////////////////////////////////////////////////////////////////// - -use std::boxed::Box; -use std::cell::{Ref, RefCell, RefMut}; -use std::rc::Rc; -use std::sync::Arc; -use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard}; - -impl ToHandle for RefCell { - type Handle = Ref<'static, T>; - unsafe fn to_handle(x: *const Self) -> Self::Handle { - (*x).borrow() - } -} - -impl ToHandleMut for RefCell { - type HandleMut = RefMut<'static, T>; - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { - (*x).borrow_mut() - } -} - -// N.B., implementing ToHandle{,Mut} for Mutex and RwLock requires a decision -// about which handle creation to use (i.e., read() vs try_read()) as well as -// what to do with error results. - -/// Typedef of a owning reference that uses a `Box` as the owner. -pub type BoxRef = OwningRef, U>; -/// Typedef of a owning reference that uses a `Vec` as the owner. -pub type VecRef = OwningRef, U>; -/// Typedef of a owning reference that uses a `String` as the owner. -pub type StringRef = OwningRef; - -/// Typedef of a owning reference that uses a `Rc` as the owner. -pub type RcRef = OwningRef, U>; -/// Typedef of a owning reference that uses a `Arc` as the owner. -pub type ArcRef = OwningRef, U>; - -/// Typedef of a owning reference that uses a `Ref` as the owner. -pub type RefRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `RefMut` as the owner. -pub type RefMutRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `RwLockReadGuard` as the owner. -pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of a owning reference that uses a `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef, U>; - -/// Typedef of a mutable owning reference that uses a `Box` as the owner. -pub type BoxRefMut = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `Vec` as the owner. -pub type VecRefMut = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `String` as the owner. -pub type StringRefMut = OwningRefMut; - -/// Typedef of a mutable owning reference that uses a `RefMut` as the owner. -pub type RefMutRefMut<'a, T, U = T> = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef, U>; - -unsafe impl<'a, T: 'a> IntoErased<'a> for Box { - type Erased = Box; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Rc { - type Erased = Rc; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Arc { - type Erased = Arc; - fn into_erased(self) -> Self::Erased { - self - } -} - -unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box { - type Erased = Box; - fn into_erased_send(self) -> Self::Erased { - self - } -} - -unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box { - type Erased = Box; - fn into_erased_send_sync(self) -> Self::Erased { - let result: Box = self; - // This is safe since Erased can always implement Sync - // Only the destructor is available and it takes &mut self - unsafe { mem::transmute(result) } - } -} - -unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc { - type Erased = Arc; - fn into_erased_send_sync(self) -> Self::Erased { - self - } -} - -/// Typedef of a owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRef = OwningRef, U>; -/// Typedef of a owning reference that uses an erased `Rc` as the owner. -pub type ErasedRcRef = OwningRef, U>; -/// Typedef of a owning reference that uses an erased `Arc` as the owner. -pub type ErasedArcRef = OwningRef, U>; - -/// Typedef of a mutable owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRefMut = OwningRefMut, U>; - -#[cfg(test)] -mod tests; diff --git a/vendor/rustc-ap-rustc_data_structures/src/owning_ref/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/owning_ref/tests.rs deleted file mode 100644 index 7b8179e90b..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/owning_ref/tests.rs +++ /dev/null @@ -1,707 +0,0 @@ -mod owning_ref { - use super::super::OwningRef; - use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef}; - use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::hash::{Hash, Hasher}; - use std::rc::Rc; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRef, ()> = OwningRef::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn into() { - let or: OwningRef, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &x.0); - assert_eq!(&*or, &42); - - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRef = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRef<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_chained() { - let or: BoxRef = Box::new(example().1).into(); - let or: BoxRef<_, str> = or.map(|x| &x[1..5]); - let or: BoxRef<_, str> = or.map(|x| &x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRef::new(Box::new(example().1)).map(|x| &x[..5]).map(|x| &x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn owner() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRef = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRef = BoxRef::new(Box::new(example())).map(|x| &x.1[..]); - - let o2: BoxRef = BoxRef::new(Box::new(example().1)).map(|x| &x[..]); - - let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef}; - use super::super::{RefMutRef, RefRef}; - use std::cell::RefCell; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefRef::new(a.borrow()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RefCell::new(1); - let a = { - let a = RefMutRef::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRef::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockReadGuardRef::new(a.read().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRef::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key = RcRef::::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]); - - hash.insert(key.clone().map(|s| &s[..3]), 42); - hash.insert(key.clone().map(|s| &s[4..]), 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRef, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef, [u8]> = - OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef>, [u8]> = unsafe { a.map_owner(Rc::new) }; - let d: OwningRef>, [u8]> = unsafe { b.map_owner(Rc::new) }; - - let e: OwningRef, [u8]> = c.erase_owner(); - let f: OwningRef, [u8]> = d.erase_owner(); - - let _g = e.clone(); - let _h = f.clone(); - } - - #[test] - fn total_erase_box() { - let a: OwningRef, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef, [u8]> = - OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef>, [u8]> = a.map_owner_box(); - let d: OwningRef>, [u8]> = b.map_owner_box(); - - let _e: OwningRef, [u8]> = c.erase_owner(); - let _f: OwningRef, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(!OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_err()); - } -} - -mod owning_handle { - use super::super::OwningHandle; - use super::super::RcRef; - use std::cell::RefCell; - use std::rc::Rc; - use std::sync::Arc; - use std::sync::RwLock; - - #[test] - fn owning_handle() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = - OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_ok() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()) - }) - .unwrap(); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_err() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - if false { - return Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()); - } - Err(()) - }); - assert!(handle.is_err()); - } - - #[test] - fn nested() { - use std::cell::RefCell; - use std::sync::{Arc, RwLock}; - - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = - OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| { - unsafe { x.as_ref() }.unwrap().try_write().unwrap() - }); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } - - #[test] - fn owning_handle_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::new(cell_ref); - assert_eq!(*handle, 2); - } - - #[test] - fn owning_handle_mut_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_mut(cell_ref); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn owning_handle_safe_2() { - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = - OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| { - unsafe { x.as_ref() }.unwrap().try_write().unwrap() - }); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } -} - -mod owning_ref_mut { - use super::super::BoxRef; - use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut}; - use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::hash::{Hash, Hasher}; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn new_deref_mut() { - let mut or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&mut *or, &mut ()); - } - - #[test] - fn mutate() { - let mut or: OwningRefMut, usize> = OwningRefMut::new(Box::new(0)); - assert_eq!(&*or, &0); - *or = 1; - assert_eq!(&*or, &1); - } - - #[test] - fn into() { - let or: OwningRefMut, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_offset_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_mut_heap_ref() { - let or: BoxRefMut = Box::new(example()).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_static_ref() { - static mut MUT_S: [u8; 5] = *b"hello"; - - let mut_s: &'static mut [u8] = unsafe { &mut MUT_S }; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s); - assert_eq!(&*or, b"hello"); - } - - #[test] - fn map_mut_chained() { - let or: BoxRefMut = Box::new(example().1).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRefMut::new(Box::new(example().1)) - .map_mut(|x| &mut x[..5]) - .map_mut(|x| &mut x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn try_map_mut() { - let or: BoxRefMut = Box::new(example().1).into(); - let or: Result, ()> = or.try_map_mut(|x| Ok(&mut x[1..5])); - assert_eq!(&*or.unwrap(), "ello"); - - let or: BoxRefMut = Box::new(example().1).into(); - let or: Result, ()> = or.try_map_mut(|_| Err(())); - assert!(or.is_err()); - } - - #[test] - fn owner() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRefMut = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRefMut { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRefMut = - BoxRefMut::new(Box::new(example())).map_mut(|x| &mut x.1[..]); - - let o2: BoxRefMut = - BoxRefMut::new(Box::new(example().1)).map_mut(|x| &mut x[..]); - - let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::RefMutRefMut; - use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut}; - use std::cell::RefCell; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefMutRefMut::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRefMut::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRefMut::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key1 = BoxRefMut::::new(Box::new("foo".to_string())).map(|s| &s[..]); - let key2 = BoxRefMut::::new(Box::new("bar".to_string())).map(|s| &s[..]); - - hash.insert(key1, 42); - hash.insert(key2, 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRefMut, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut, [u8]> = - OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut>, [u8]> = unsafe { a.map_owner(Box::new) }; - let d: OwningRefMut>, [u8]> = unsafe { b.map_owner(Box::new) }; - - let _e: OwningRefMut, [u8]> = c.erase_owner(); - let _f: OwningRefMut, [u8]> = d.erase_owner(); - } - - #[test] - fn total_erase_box() { - let a: OwningRefMut, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut, [u8]> = - OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut>, [u8]> = a.map_owner_box(); - let d: OwningRefMut>, [u8]> = b.map_owner_box(); - - let _e: OwningRefMut, [u8]> = c.erase_owner(); - let _f: OwningRefMut, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(!OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).is_err()); - } - - #[test] - fn try_map3() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_ok()); - } - - #[test] - fn try_map4() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box = x; - - assert!(!OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).is_err()); - } - - #[test] - fn into_owning_ref() { - use super::super::BoxRef; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<()> = or.into(); - assert_eq!(&*or, &()); - } - - struct Foo { - u: u32, - } - struct Bar { - f: Foo, - } - - #[test] - fn ref_mut() { - use std::cell::RefCell; - - let a = RefCell::new(Bar { f: Foo { u: 42 } }); - let mut b = OwningRefMut::new(a.borrow_mut()); - assert_eq!(b.f.u, 42); - b.f.u = 43; - let mut c = b.map_mut(|x| &mut x.f); - assert_eq!(c.u, 43); - c.u = 44; - let mut d = c.map_mut(|x| &mut x.u); - assert_eq!(*d, 44); - *d = 45; - assert_eq!(*d, 45); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/profiling.rs b/vendor/rustc-ap-rustc_data_structures/src/profiling.rs deleted file mode 100644 index f0b413c795..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/profiling.rs +++ /dev/null @@ -1,654 +0,0 @@ -//! # Rust Compiler Self-Profiling -//! -//! This module implements the basic framework for the compiler's self- -//! profiling support. It provides the `SelfProfiler` type which enables -//! recording "events". An event is something that starts and ends at a given -//! point in time and has an ID and a kind attached to it. This allows for -//! tracing the compiler's activity. -//! -//! Internally this module uses the custom tailored [measureme][mm] crate for -//! efficiently recording events to disk in a compact format that can be -//! post-processed and analyzed by the suite of tools in the `measureme` -//! project. The highest priority for the tracing framework is on incurring as -//! little overhead as possible. -//! -//! -//! ## Event Overview -//! -//! Events have a few properties: -//! -//! - The `event_kind` designates the broad category of an event (e.g. does it -//! correspond to the execution of a query provider or to loading something -//! from the incr. comp. on-disk cache, etc). -//! - The `event_id` designates the query invocation or function call it -//! corresponds to, possibly including the query key or function arguments. -//! - Each event stores the ID of the thread it was recorded on. -//! - The timestamp stores beginning and end of the event, or the single point -//! in time it occurred at for "instant" events. -//! -//! -//! ## Event Filtering -//! -//! Event generation can be filtered by event kind. Recording all possible -//! events generates a lot of data, much of which is not needed for most kinds -//! of analysis. So, in order to keep overhead as low as possible for a given -//! use case, the `SelfProfiler` will only record the kinds of events that -//! pass the filter specified as a command line argument to the compiler. -//! -//! -//! ## `event_id` Assignment -//! -//! As far as `measureme` is concerned, `event_id`s are just strings. However, -//! it would incur too much overhead to generate and persist each `event_id` -//! string at the point where the event is recorded. In order to make this more -//! efficient `measureme` has two features: -//! -//! - Strings can share their content, so that re-occurring parts don't have to -//! be copied over and over again. One allocates a string in `measureme` and -//! gets back a `StringId`. This `StringId` is then used to refer to that -//! string. `measureme` strings are actually DAGs of string components so that -//! arbitrary sharing of substrings can be done efficiently. This is useful -//! because `event_id`s contain lots of redundant text like query names or -//! def-path components. -//! -//! - `StringId`s can be "virtual" which means that the client picks a numeric -//! ID according to some application-specific scheme and can later make that -//! ID be mapped to an actual string. This is used to cheaply generate -//! `event_id`s while the events actually occur, causing little timing -//! distortion, and then later map those `StringId`s, in bulk, to actual -//! `event_id` strings. This way the largest part of the tracing overhead is -//! localized to one contiguous chunk of time. -//! -//! How are these `event_id`s generated in the compiler? For things that occur -//! infrequently (e.g. "generic activities"), we just allocate the string the -//! first time it is used and then keep the `StringId` in a hash table. This -//! is implemented in `SelfProfiler::get_or_alloc_cached_string()`. -//! -//! For queries it gets more interesting: First we need a unique numeric ID for -//! each query invocation (the `QueryInvocationId`). This ID is used as the -//! virtual `StringId` we use as `event_id` for a given event. This ID has to -//! be available both when the query is executed and later, together with the -//! query key, when we allocate the actual `event_id` strings in bulk. -//! -//! We could make the compiler generate and keep track of such an ID for each -//! query invocation but luckily we already have something that fits all the -//! the requirements: the query's `DepNodeIndex`. So we use the numeric value -//! of the `DepNodeIndex` as `event_id` when recording the event and then, -//! just before the query context is dropped, we walk the entire query cache -//! (which stores the `DepNodeIndex` along with the query key for each -//! invocation) and allocate the corresponding strings together with a mapping -//! for `DepNodeIndex as StringId`. -//! -//! [mm]: https://github.com/rust-lang/measureme/ - -use crate::cold_path; -use crate::fx::FxHashMap; - -use std::borrow::Borrow; -use std::collections::hash_map::Entry; -use std::convert::Into; -use std::error::Error; -use std::fs; -use std::path::Path; -use std::process; -use std::sync::Arc; -use std::time::{Duration, Instant}; - -use measureme::{EventId, 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 QUERY_KEYS = 1 << 5; - const FUNCTION_ARGS = 1 << 6; - const LLVM = 1 << 7; - - const DEFAULT = Self::GENERIC_ACTIVITIES.bits | - Self::QUERY_PROVIDERS.bits | - Self::QUERY_BLOCKED.bits | - Self::INCR_CACHE_LOADS.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 -const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ - ("none", EventFilter::empty()), - ("all", EventFilter::all()), - ("default", EventFilter::DEFAULT), - ("generic-activity", EventFilter::GENERIC_ACTIVITIES), - ("query-provider", EventFilter::QUERY_PROVIDERS), - ("query-cache-hit", EventFilter::QUERY_CACHE_HITS), - ("query-blocked", EventFilter::QUERY_BLOCKED), - ("incr-cache-load", EventFilter::INCR_CACHE_LOADS), - ("query-keys", EventFilter::QUERY_KEYS), - ("function-args", EventFilter::FUNCTION_ARGS), - ("args", EventFilter::ARGS), - ("llvm", EventFilter::LLVM), -]; - -/// Something that uniquely identifies a query invocation. -pub struct QueryInvocationId(pub u32); - -/// A reference to the SelfProfiler. It can be cloned and sent across thread -/// boundaries at will. -#[derive(Clone)] -pub struct SelfProfilerRef { - // This field is `None` if self-profiling is disabled for the current - // compilation session. - profiler: Option>, - - // We store the filter mask directly in the reference because that doesn't - // cost anything and allows for filtering with checking if the profiler is - // actually enabled. - event_filter_mask: EventFilter, - - // Print verbose generic activities to stdout - print_verbose_generic_activities: bool, - - // Print extra verbose generic activities to stdout - print_extra_verbose_generic_activities: bool, -} - -impl SelfProfilerRef { - pub fn new( - profiler: Option>, - print_verbose_generic_activities: bool, - print_extra_verbose_generic_activities: bool, - ) -> SelfProfilerRef { - // If there is no SelfProfiler then the filter mask is set to NONE, - // ensuring that nothing ever tries to actually access it. - let event_filter_mask = - profiler.as_ref().map_or(EventFilter::empty(), |p| p.event_filter_mask); - - SelfProfilerRef { - profiler, - event_filter_mask, - print_verbose_generic_activities, - print_extra_verbose_generic_activities, - } - } - - // This shim makes sure that calls only get executed if the filter mask - // lets them pass. It also contains some trickery to make sure that - // code is optimized for non-profiling compilation sessions, i.e. anything - // past the filter check is never inlined so it doesn't clutter the fast - // path. - #[inline(always)] - fn exec(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_> - where - F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>, - { - #[inline(never)] - fn cold_call(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_> - where - F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>, - { - let profiler = profiler_ref.profiler.as_ref().unwrap(); - f(&**profiler) - } - - if unlikely!(self.event_filter_mask.contains(event_filter)) { - cold_call(self, f) - } else { - TimingGuard::none() - } - } - - /// Start profiling a verbose generic activity. Profiling continues until the - /// VerboseTimingGuard returned from this call is dropped. In addition to recording - /// a measureme event, "verbose" generic activities also print a timing entry to - /// stdout if the compiler is invoked with -Ztime or -Ztime-passes. - pub fn verbose_generic_activity<'a>( - &'a self, - event_label: &'static str, - ) -> VerboseTimingGuard<'a> { - let message = - if self.print_verbose_generic_activities { Some(event_label.to_owned()) } else { None }; - - VerboseTimingGuard::start(message, self.generic_activity(event_label)) - } - - /// Start profiling a extra verbose generic activity. Profiling continues until the - /// VerboseTimingGuard returned from this call is dropped. In addition to recording - /// a measureme event, "extra verbose" generic activities also print a timing entry to - /// stdout if the compiler is invoked with -Ztime-passes. - pub fn extra_verbose_generic_activity<'a, A>( - &'a self, - event_label: &'static str, - event_arg: A, - ) -> VerboseTimingGuard<'a> - where - A: Borrow + Into, - { - let message = if self.print_extra_verbose_generic_activities { - Some(format!("{}({})", event_label, event_arg.borrow())) - } else { - None - }; - - VerboseTimingGuard::start(message, self.generic_activity_with_arg(event_label, event_arg)) - } - - /// Start profiling a generic activity. Profiling continues until the - /// TimingGuard returned from this call is dropped. - #[inline(always)] - pub fn generic_activity(&self, event_label: &'static str) -> TimingGuard<'_> { - self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| { - let event_label = profiler.get_or_alloc_cached_string(event_label); - let event_id = EventId::from_label(event_label); - 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)] - pub fn generic_activity_with_arg( - &self, - event_label: &'static str, - event_arg: A, - ) -> TimingGuard<'_> - where - A: Borrow + Into, - { - self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| { - let builder = EventIdBuilder::new(&profiler.profiler); - let event_label = profiler.get_or_alloc_cached_string(event_label); - let event_id = if profiler.event_filter_mask.contains(EventFilter::FUNCTION_ARGS) { - let event_arg = profiler.get_or_alloc_cached_string(event_arg); - builder.from_label_and_arg(event_label, event_arg) - } else { - builder.from_label(event_label) - }; - TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id) - }) - } - - #[inline(always)] - pub fn generic_activity_with_args( - &self, - event_label: &'static str, - event_args: &[String], - ) -> TimingGuard<'_> { - self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| { - let builder = EventIdBuilder::new(&profiler.profiler); - let event_label = profiler.get_or_alloc_cached_string(event_label); - let event_id = if profiler.event_filter_mask.contains(EventFilter::FUNCTION_ARGS) { - let event_args: Vec<_> = event_args - .iter() - .map(|s| profiler.get_or_alloc_cached_string(&s[..])) - .collect(); - builder.from_label_and_args(event_label, &event_args) - } else { - builder.from_label(event_label) - }; - TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id) - }) - } - - /// Start profiling a query provider. Profiling continues until the - /// TimingGuard returned from this call is dropped. - #[inline(always)] - pub fn query_provider(&self) -> TimingGuard<'_> { - self.exec(EventFilter::QUERY_PROVIDERS, |profiler| { - TimingGuard::start(profiler, profiler.query_event_kind, EventId::INVALID) - }) - } - - /// Record a query in-memory cache hit. - #[inline(always)] - pub fn query_cache_hit(&self, query_invocation_id: QueryInvocationId) { - self.instant_query_event( - |profiler| profiler.query_cache_hit_event_kind, - query_invocation_id, - EventFilter::QUERY_CACHE_HITS, - ); - } - - /// Start profiling a query being blocked on a concurrent execution. - /// Profiling continues until the TimingGuard returned from this call is - /// dropped. - #[inline(always)] - pub fn query_blocked(&self) -> TimingGuard<'_> { - self.exec(EventFilter::QUERY_BLOCKED, |profiler| { - TimingGuard::start(profiler, profiler.query_blocked_event_kind, EventId::INVALID) - }) - } - - /// Start profiling how long it takes to load a query result from the - /// incremental compilation on-disk cache. Profiling continues until the - /// TimingGuard returned from this call is dropped. - #[inline(always)] - pub fn incr_cache_loading(&self) -> TimingGuard<'_> { - self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| { - TimingGuard::start( - profiler, - profiler.incremental_load_result_event_kind, - EventId::INVALID, - ) - }) - } - - #[inline(always)] - fn instant_query_event( - &self, - event_kind: fn(&SelfProfiler) -> StringId, - query_invocation_id: QueryInvocationId, - event_filter: EventFilter, - ) { - drop(self.exec(event_filter, |profiler| { - let event_id = StringId::new_virtual(query_invocation_id.0); - let thread_id = std::thread::current().id().as_u64().get() as u32; - - profiler.profiler.record_instant_event( - event_kind(profiler), - EventId::from_virtual(event_id), - thread_id, - ); - - TimingGuard::none() - })); - } - - pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) { - if let Some(profiler) = &self.profiler { - f(&profiler) - } - } - - #[inline] - pub fn enabled(&self) -> bool { - self.profiler.is_some() - } - - #[inline] - pub fn llvm_recording_enabled(&self) -> bool { - self.event_filter_mask.contains(EventFilter::LLVM) - } - #[inline] - pub fn get_self_profiler(&self) -> Option> { - self.profiler.clone() - } -} - -pub struct SelfProfiler { - profiler: Profiler, - event_filter_mask: EventFilter, - - string_cache: RwLock>, - - query_event_kind: StringId, - generic_activity_event_kind: StringId, - incremental_load_result_event_kind: StringId, - query_blocked_event_kind: StringId, - query_cache_hit_event_kind: StringId, -} - -impl SelfProfiler { - pub fn new( - output_directory: &Path, - crate_name: Option<&str>, - event_filters: &Option>, - ) -> Result> { - fs::create_dir_all(output_directory)?; - - let crate_name = crate_name.unwrap_or("unknown-crate"); - let filename = format!("{}-{}.rustc_profile", crate_name, process::id()); - let path = output_directory.join(&filename); - let profiler = Profiler::new(&path)?; - - 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 query_blocked_event_kind = profiler.alloc_string("QueryBlocked"); - let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit"); - - let mut event_filter_mask = EventFilter::empty(); - - if let Some(ref event_filters) = *event_filters { - let mut unknown_events = vec![]; - for item in event_filters { - if let Some(&(_, mask)) = - EVENT_FILTERS_BY_NAME.iter().find(|&(name, _)| name == item) - { - event_filter_mask |= mask; - } else { - unknown_events.push(item.clone()); - } - } - - // Warn about any unknown event names - if !unknown_events.is_empty() { - unknown_events.sort(); - unknown_events.dedup(); - - warn!( - "Unknown self-profiler events specified: {}. Available options are: {}.", - unknown_events.join(", "), - EVENT_FILTERS_BY_NAME - .iter() - .map(|&(name, _)| name.to_string()) - .collect::>() - .join(", ") - ); - } - } else { - event_filter_mask = EventFilter::DEFAULT; - } - - Ok(SelfProfiler { - profiler, - event_filter_mask, - string_cache: RwLock::new(FxHashMap::default()), - query_event_kind, - generic_activity_event_kind, - incremental_load_result_event_kind, - query_blocked_event_kind, - query_cache_hit_event_kind, - }) - } - - /// Allocates a new string in the profiling data. Does not do any caching - /// or deduplication. - pub fn alloc_string(&self, s: &STR) -> StringId { - self.profiler.alloc_string(s) - } - - /// 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. - pub fn get_or_alloc_cached_string(&self, s: A) -> StringId - where - A: Borrow + Into, - { - // Only acquire a read-lock first since we assume that the string is - // already present in the common case. - { - let string_cache = self.string_cache.read(); - - if let Some(&id) = string_cache.get(s.borrow()) { - return id; - } - } - - let mut string_cache = self.string_cache.write(); - // Check if the string has already been added in the small time window - // between dropping the read lock and acquiring the write lock. - match string_cache.entry(s.into()) { - Entry::Occupied(e) => *e.get(), - Entry::Vacant(e) => { - let string_id = self.profiler.alloc_string(&e.key()[..]); - *e.insert(string_id) - } - } - } - - pub fn map_query_invocation_id_to_string(&self, from: QueryInvocationId, to: StringId) { - let from = StringId::new_virtual(from.0); - self.profiler.map_virtual_to_concrete_string(from, to); - } - - pub fn bulk_map_query_invocation_id_to_single_string(&self, from: I, to: StringId) - where - I: Iterator + ExactSizeIterator, - { - let from = from.map(|qid| StringId::new_virtual(qid.0)); - self.profiler.bulk_map_virtual_to_single_concrete_string(from, to); - } - - pub fn query_key_recording_enabled(&self) -> bool { - self.event_filter_mask.contains(EventFilter::QUERY_KEYS) - } - - pub fn event_id_builder(&self) -> EventIdBuilder<'_> { - EventIdBuilder::new(&self.profiler) - } -} - -#[must_use] -pub struct TimingGuard<'a>(Option>); - -impl<'a> TimingGuard<'a> { - #[inline] - pub fn start( - profiler: &'a SelfProfiler, - event_kind: StringId, - event_id: EventId, - ) -> TimingGuard<'a> { - let thread_id = std::thread::current().id().as_u64().get() as u32; - let raw_profiler = &profiler.profiler; - let timing_guard = - raw_profiler.start_recording_interval_event(event_kind, event_id, thread_id); - TimingGuard(Some(timing_guard)) - } - - #[inline] - pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) { - if let Some(guard) = self.0 { - cold_path(|| { - let event_id = StringId::new_virtual(query_invocation_id.0); - let event_id = EventId::from_virtual(event_id); - guard.finish_with_override_event_id(event_id); - }); - } - } - - #[inline] - pub fn none() -> TimingGuard<'a> { - TimingGuard(None) - } - - #[inline(always)] - pub fn run(self, f: impl FnOnce() -> R) -> R { - let _timer = self; - f() - } -} - -#[must_use] -pub struct VerboseTimingGuard<'a> { - start_and_message: Option<(Instant, Option, String)>, - _guard: TimingGuard<'a>, -} - -impl<'a> VerboseTimingGuard<'a> { - pub fn start(message: Option, _guard: TimingGuard<'a>) -> Self { - VerboseTimingGuard { - _guard, - start_and_message: message.map(|msg| (Instant::now(), get_resident_set_size(), msg)), - } - } - - #[inline(always)] - pub fn run(self, f: impl FnOnce() -> R) -> R { - let _timer = self; - f() - } -} - -impl Drop for VerboseTimingGuard<'_> { - fn drop(&mut self) { - if let Some((start_time, start_rss, ref message)) = self.start_and_message { - let end_rss = get_resident_set_size(); - print_time_passes_entry(&message[..], start_time.elapsed(), start_rss, end_rss); - } - } -} - -pub fn print_time_passes_entry( - what: &str, - dur: Duration, - start_rss: Option, - end_rss: Option, -) { - let rss_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as usize; - let rss_change_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as i128; - - let mem_string = match (start_rss, end_rss) { - (Some(start_rss), Some(end_rss)) => { - let change_rss = end_rss as i128 - start_rss as i128; - - format!( - "; rss: {:>4}MB -> {:>4}MB ({:>+5}MB)", - rss_to_mb(start_rss), - rss_to_mb(end_rss), - rss_change_to_mb(change_rss), - ) - } - (Some(start_rss), None) => format!("; rss start: {:>4}MB", rss_to_mb(start_rss)), - (None, Some(end_rss)) => format!("; rss end: {:>4}MB", rss_to_mb(end_rss)), - (None, None) => String::new(), - }; - - println!("time: {:>7}{}\t{}", duration_to_secs_str(dur), mem_string, what); -} - -// Hack up our own formatting for the duration to make it easier for scripts -// to parse (always use the same number of decimal places and the same unit). -pub fn duration_to_secs_str(dur: std::time::Duration) -> String { - format!("{:.3}", dur.as_secs_f64()) -} - -// Memory reporting -cfg_if! { - if #[cfg(windows)] { - pub fn get_resident_set_size() -> Option { - use std::mem::{self, MaybeUninit}; - use winapi::shared::minwindef::DWORD; - use winapi::um::processthreadsapi::GetCurrentProcess; - use winapi::um::psapi::{GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS}; - - let mut pmc = MaybeUninit::::uninit(); - match unsafe { - GetProcessMemoryInfo(GetCurrentProcess(), pmc.as_mut_ptr(), mem::size_of_val(&pmc) as DWORD) - } { - 0 => None, - _ => { - let pmc = unsafe { pmc.assume_init() }; - Some(pmc.WorkingSetSize as usize) - } - } - } - } else if #[cfg(unix)] { - pub fn get_resident_set_size() -> Option { - let field = 1; - let contents = fs::read("/proc/self/statm").ok()?; - let contents = String::from_utf8(contents).ok()?; - let s = contents.split_whitespace().nth(field)?; - let npages = s.parse::().ok()?; - Some(npages * 4096) - } - } else { - pub fn get_resident_set_size() -> Option { - None - } - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/ptr_key.rs b/vendor/rustc-ap-rustc_data_structures/src/ptr_key.rs deleted file mode 100644 index 440ccb05d8..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/ptr_key.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::ops::Deref; -use std::{hash, ptr}; - -/// A wrapper around reference that compares and hashes like a pointer. -/// Can be used as a key in sets/maps indexed by pointers to avoid `unsafe`. -#[derive(Debug)] -pub struct PtrKey<'a, T>(pub &'a T); - -impl<'a, T> Clone for PtrKey<'a, T> { - fn clone(&self) -> Self { - *self - } -} - -impl<'a, T> Copy for PtrKey<'a, T> {} - -impl<'a, T> PartialEq for PtrKey<'a, T> { - fn eq(&self, rhs: &Self) -> bool { - ptr::eq(self.0, rhs.0) - } -} - -impl<'a, T> Eq for PtrKey<'a, T> {} - -impl<'a, T> hash::Hash for PtrKey<'a, T> { - fn hash(&self, hasher: &mut H) { - (self.0 as *const T).hash(hasher) - } -} - -impl<'a, T> Deref for PtrKey<'a, T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - self.0 - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sharded.rs b/vendor/rustc-ap-rustc_data_structures/src/sharded.rs deleted file mode 100644 index 485719c517..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sharded.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::fx::{FxHashMap, FxHasher}; -use crate::sync::{Lock, LockGuard}; -use smallvec::SmallVec; -use std::borrow::Borrow; -use std::collections::hash_map::RawEntryMut; -use std::hash::{Hash, Hasher}; -use std::mem; - -#[derive(Clone, Default)] -#[cfg_attr(parallel_compiler, repr(align(64)))] -struct CacheAligned(T); - -#[cfg(parallel_compiler)] -// 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700, -// but this should be tested on higher core count CPUs. How the `Sharded` type gets used -// may also affect the ideal number of shards. -const SHARD_BITS: usize = 5; - -#[cfg(not(parallel_compiler))] -const SHARD_BITS: usize = 0; - -pub const SHARDS: usize = 1 << SHARD_BITS; - -/// An array of cache-line aligned inner locked structures with convenience methods. -#[derive(Clone)] -pub struct Sharded { - shards: [CacheAligned>; SHARDS], -} - -impl Default for Sharded { - #[inline] - fn default() -> Self { - Self::new(T::default) - } -} - -impl Sharded { - #[inline] - pub fn new(mut value: impl FnMut() -> T) -> Self { - // Create a vector of the values we want - let mut values: SmallVec<[_; SHARDS]> = - (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect(); - - // Create an uninitialized array - let mut shards: mem::MaybeUninit<[CacheAligned>; SHARDS]> = - mem::MaybeUninit::uninit(); - - unsafe { - // Copy the values into our array - let first = shards.as_mut_ptr() as *mut CacheAligned>; - values.as_ptr().copy_to_nonoverlapping(first, SHARDS); - - // Ignore the content of the vector - values.set_len(0); - - Sharded { shards: shards.assume_init() } - } - } - - /// The shard is selected by hashing `val` with `FxHasher`. - #[inline] - pub fn get_shard_by_value(&self, val: &K) -> &Lock { - if SHARDS == 1 { &self.shards[0].0 } else { self.get_shard_by_hash(make_hash(val)) } - } - - /// Get a shard with a pre-computed hash value. If `get_shard_by_value` is - /// ever used in combination with `get_shard_by_hash` on a single `Sharded` - /// instance, then `hash` must be computed with `FxHasher`. Otherwise, - /// `hash` can be computed with any hasher, so long as that hasher is used - /// consistently for each `Sharded` instance. - #[inline] - pub fn get_shard_index_by_hash(&self, hash: u64) -> usize { - let hash_len = mem::size_of::(); - // Ignore the top 7 bits as hashbrown uses these and get the next SHARD_BITS highest bits. - // hashbrown also uses the lowest bits, so we can't use those - let bits = (hash >> (hash_len * 8 - 7 - SHARD_BITS)) as usize; - bits % SHARDS - } - - #[inline] - pub fn get_shard_by_hash(&self, hash: u64) -> &Lock { - &self.shards[self.get_shard_index_by_hash(hash)].0 - } - - #[inline] - pub fn get_shard_by_index(&self, i: usize) -> &Lock { - &self.shards[i].0 - } - - pub fn lock_shards(&self) -> Vec> { - (0..SHARDS).map(|i| self.shards[i].0.lock()).collect() - } - - pub fn try_lock_shards(&self) -> Option>> { - (0..SHARDS).map(|i| self.shards[i].0.try_lock()).collect() - } -} - -pub type ShardedHashMap = Sharded>; - -impl ShardedHashMap { - pub fn len(&self) -> usize { - self.lock_shards().iter().map(|shard| shard.len()).sum() - } -} - -impl ShardedHashMap { - #[inline] - pub fn intern_ref(&self, value: &Q, make: impl FnOnce() -> K) -> K - where - K: Borrow, - Q: Hash + Eq, - { - let hash = make_hash(value); - let mut shard = self.get_shard_by_hash(hash).lock(); - let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, value); - - match entry { - RawEntryMut::Occupied(e) => *e.key(), - RawEntryMut::Vacant(e) => { - let v = make(); - e.insert_hashed_nocheck(hash, v, ()); - v - } - } - } - - #[inline] - pub fn intern(&self, value: Q, make: impl FnOnce(Q) -> K) -> K - where - K: Borrow, - Q: Hash + Eq, - { - let hash = make_hash(&value); - let mut shard = self.get_shard_by_hash(hash).lock(); - let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, &value); - - match entry { - RawEntryMut::Occupied(e) => *e.key(), - RawEntryMut::Vacant(e) => { - let v = make(value); - e.insert_hashed_nocheck(hash, v, ()); - v - } - } - } -} - -pub trait IntoPointer { - /// Returns a pointer which outlives `self`. - fn into_pointer(&self) -> *const (); -} - -impl ShardedHashMap { - pub fn contains_pointer_to(&self, value: &T) -> bool { - let hash = make_hash(&value); - let shard = self.get_shard_by_hash(hash).lock(); - let value = value.into_pointer(); - shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some() - } -} - -#[inline] -fn make_hash(val: &K) -> u64 { - let mut state = FxHasher::default(); - val.hash(&mut state); - state.finish() -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sip128.rs b/vendor/rustc-ap-rustc_data_structures/src/sip128.rs deleted file mode 100644 index 53062b9c20..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sip128.rs +++ /dev/null @@ -1,490 +0,0 @@ -//! This is a copy of `core::hash::sip` adapted to providing 128 bit hashes. - -use std::hash::Hasher; -use std::mem::{self, MaybeUninit}; -use std::ptr; - -#[cfg(test)] -mod tests; - -// The SipHash algorithm operates on 8-byte chunks. -const ELEM_SIZE: usize = mem::size_of::(); - -// Size of the buffer in number of elements, not including the spill. -// -// The selection of this size was guided by rustc-perf benchmark comparisons of -// different buffer sizes. It should be periodically reevaluated as the compiler -// implementation and input characteristics change. -// -// Using the same-sized buffer for everything we hash is a performance versus -// complexity tradeoff. The ideal buffer size, and whether buffering should even -// be used, depends on what is being hashed. It may be worth it to size the -// buffer appropriately (perhaps by making SipHasher128 generic over the buffer -// size) or disable buffering depending on what is being hashed. But at this -// time, we use the same buffer size for everything. -const BUFFER_CAPACITY: usize = 8; - -// Size of the buffer in bytes, not including the spill. -const BUFFER_SIZE: usize = BUFFER_CAPACITY * ELEM_SIZE; - -// Size of the buffer in number of elements, including the spill. -const BUFFER_WITH_SPILL_CAPACITY: usize = BUFFER_CAPACITY + 1; - -// Size of the buffer in bytes, including the spill. -const BUFFER_WITH_SPILL_SIZE: usize = BUFFER_WITH_SPILL_CAPACITY * ELEM_SIZE; - -// Index of the spill element in the buffer. -const BUFFER_SPILL_INDEX: usize = BUFFER_WITH_SPILL_CAPACITY - 1; - -#[derive(Debug, Clone)] -#[repr(C)] -pub struct SipHasher128 { - // The access pattern during hashing consists of accesses to `nbuf` and - // `buf` until the buffer is full, followed by accesses to `state` and - // `processed`, and then repetition of that pattern until hashing is done. - // This is the basis for the ordering of fields below. However, in practice - // the cache miss-rate for data access is extremely low regardless of order. - nbuf: usize, // how many bytes in buf are valid - buf: [MaybeUninit; BUFFER_WITH_SPILL_CAPACITY], // unprocessed bytes le - state: State, // hash State - processed: usize, // how many bytes we've processed -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -struct State { - // v0, v2 and v1, v3 show up in pairs in the algorithm, - // and simd implementations of SipHash will use vectors - // of v02 and v13. By placing them in this order in the struct, - // the compiler can pick up on just a few simd optimizations by itself. - v0: u64, - v2: u64, - v1: u64, - v3: u64, -} - -macro_rules! compress { - ($state:expr) => {{ compress!($state.v0, $state.v1, $state.v2, $state.v3) }}; - ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{ - $v0 = $v0.wrapping_add($v1); - $v1 = $v1.rotate_left(13); - $v1 ^= $v0; - $v0 = $v0.rotate_left(32); - $v2 = $v2.wrapping_add($v3); - $v3 = $v3.rotate_left(16); - $v3 ^= $v2; - $v0 = $v0.wrapping_add($v3); - $v3 = $v3.rotate_left(21); - $v3 ^= $v0; - $v2 = $v2.wrapping_add($v1); - $v1 = $v1.rotate_left(17); - $v1 ^= $v2; - $v2 = $v2.rotate_left(32); - }}; -} - -// Copies up to 8 bytes from source to destination. This performs better than -// `ptr::copy_nonoverlapping` on microbenchmarks and may perform better on real -// workloads since all of the copies have fixed sizes and avoid calling memcpy. -// -// This is specifically designed for copies of up to 8 bytes, because that's the -// maximum of number bytes needed to fill an 8-byte-sized element on which -// SipHash operates. Note that for variable-sized copies which are known to be -// less than 8 bytes, this function will perform more work than necessary unless -// the compiler is able to optimize the extra work away. -#[inline] -unsafe fn copy_nonoverlapping_small(src: *const u8, dst: *mut u8, count: usize) { - debug_assert!(count <= 8); - - if count == 8 { - ptr::copy_nonoverlapping(src, dst, 8); - return; - } - - let mut i = 0; - if i + 3 < count { - ptr::copy_nonoverlapping(src.add(i), dst.add(i), 4); - i += 4; - } - - if i + 1 < count { - ptr::copy_nonoverlapping(src.add(i), dst.add(i), 2); - i += 2 - } - - if i < count { - *dst.add(i) = *src.add(i); - i += 1; - } - - debug_assert_eq!(i, count); -} - -// # Implementation -// -// This implementation uses buffering to reduce the hashing cost for inputs -// consisting of many small integers. Buffering simplifies the integration of -// integer input--the integer write function typically just appends to the -// buffer with a statically sized write, updates metadata, and returns. -// -// Buffering also prevents alternating between writes that do and do not trigger -// the hashing process. Only when the entire buffer is full do we transition -// into hashing. This allows us to keep the hash state in registers for longer, -// instead of loading and storing it before and after processing each element. -// -// When a write fills the buffer, a buffer processing function is invoked to -// hash all of the buffered input. The buffer processing functions are marked -// `#[inline(never)]` so that they aren't inlined into the append functions, -// which ensures the more frequently called append functions remain inlineable -// and don't include register pushing/popping that would only be made necessary -// by inclusion of the complex buffer processing path which uses those -// registers. -// -// The buffer includes a "spill"--an extra element at the end--which simplifies -// the integer write buffer processing path. The value that fills the buffer can -// be written with a statically sized write that may spill over into the spill. -// After the buffer is processed, the part of the value that spilled over can be -// written from the spill to the beginning of the buffer with another statically -// sized write. This write may copy more bytes than actually spilled over, but -// we maintain the metadata such that any extra copied bytes will be ignored by -// subsequent processing. Due to the static sizes, this scheme performs better -// than copying the exact number of bytes needed into the end and beginning of -// the buffer. -// -// The buffer is uninitialized, which improves performance, but may preclude -// efficient implementation of alternative approaches. The improvement is not so -// large that an alternative approach should be disregarded because it cannot be -// efficiently implemented with an uninitialized buffer. On the other hand, an -// uninitialized buffer may become more important should a larger one be used. -// -// # Platform Dependence -// -// The SipHash algorithm operates on byte sequences. It parses the input stream -// as 8-byte little-endian integers. Therefore, given the same byte sequence, it -// produces the same result on big- and little-endian hardware. -// -// However, the Hasher trait has methods which operate on multi-byte integers. -// How they are converted into byte sequences can be endian-dependent (by using -// native byte order) or independent (by consistently using either LE or BE byte -// order). It can also be `isize` and `usize` size dependent (by using the -// native size), or independent (by converting to a common size), supposing the -// values can be represented in 32 bits. -// -// In order to make `SipHasher128` consistent with `SipHasher` in libstd, we -// choose to do the integer to byte sequence conversion in the platform- -// dependent way. Clients can achieve platform-independent hashing by widening -// `isize` and `usize` integers to 64 bits on 32-bit systems and byte-swapping -// integers on big-endian systems before passing them to the writing functions. -// This causes the input byte sequence to look identical on big- and little- -// endian systems (supposing `isize` and `usize` values can be represented in 32 -// bits), which ensures platform-independent results. -impl SipHasher128 { - #[inline] - pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher128 { - let mut hasher = SipHasher128 { - nbuf: 0, - buf: MaybeUninit::uninit_array(), - state: State { - v0: key0 ^ 0x736f6d6570736575, - // The XOR with 0xee is only done on 128-bit algorithm version. - v1: key1 ^ (0x646f72616e646f6d ^ 0xee), - v2: key0 ^ 0x6c7967656e657261, - v3: key1 ^ 0x7465646279746573, - }, - processed: 0, - }; - - unsafe { - // Initialize spill because we read from it in `short_write_process_buffer`. - *hasher.buf.get_unchecked_mut(BUFFER_SPILL_INDEX) = MaybeUninit::zeroed(); - } - - hasher - } - - // A specialized write function for values with size <= 8. - #[inline] - fn short_write(&mut self, x: T) { - let size = mem::size_of::(); - let nbuf = self.nbuf; - debug_assert!(size <= 8); - debug_assert!(nbuf < BUFFER_SIZE); - debug_assert!(nbuf + size < BUFFER_WITH_SPILL_SIZE); - - if nbuf + size < BUFFER_SIZE { - unsafe { - // The memcpy call is optimized away because the size is known. - let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - ptr::copy_nonoverlapping(&x as *const _ as *const u8, dst, size); - } - - self.nbuf = nbuf + size; - - return; - } - - unsafe { self.short_write_process_buffer(x) } - } - - // A specialized write function for values with size <= 8 that should only - // be called when the write would cause the buffer to fill. - // - // SAFETY: the write of `x` into `self.buf` starting at byte offset - // `self.nbuf` must cause `self.buf` to become fully initialized (and not - // overflow) if it wasn't already. - #[inline(never)] - unsafe fn short_write_process_buffer(&mut self, x: T) { - let size = mem::size_of::(); - let nbuf = self.nbuf; - debug_assert!(size <= 8); - debug_assert!(nbuf < BUFFER_SIZE); - debug_assert!(nbuf + size >= BUFFER_SIZE); - debug_assert!(nbuf + size < BUFFER_WITH_SPILL_SIZE); - - // Copy first part of input into end of buffer, possibly into spill - // element. The memcpy call is optimized away because the size is known. - let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - ptr::copy_nonoverlapping(&x as *const _ as *const u8, dst, size); - - // Process buffer. - for i in 0..BUFFER_CAPACITY { - let elem = self.buf.get_unchecked(i).assume_init().to_le(); - self.state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut self.state); - self.state.v0 ^= elem; - } - - // Copy remaining input into start of buffer by copying size - 1 - // elements from spill (at most size - 1 bytes could have overflowed - // into the spill). The memcpy call is optimized away because the size - // is known. And the whole copy is optimized away for size == 1. - let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8; - ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr() as *mut u8, size - 1); - - // This function should only be called when the write fills the buffer. - // Therefore, when size == 1, the new `self.nbuf` must be zero. The size - // is statically known, so the branch is optimized away. - self.nbuf = if size == 1 { 0 } else { nbuf + size - BUFFER_SIZE }; - self.processed += BUFFER_SIZE; - } - - // A write function for byte slices. - #[inline] - fn slice_write(&mut self, msg: &[u8]) { - let length = msg.len(); - let nbuf = self.nbuf; - debug_assert!(nbuf < BUFFER_SIZE); - - if nbuf + length < BUFFER_SIZE { - unsafe { - let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - - if length <= 8 { - copy_nonoverlapping_small(msg.as_ptr(), dst, length); - } else { - // This memcpy is *not* optimized away. - ptr::copy_nonoverlapping(msg.as_ptr(), dst, length); - } - } - - self.nbuf = nbuf + length; - - return; - } - - unsafe { self.slice_write_process_buffer(msg) } - } - - // A write function for byte slices that should only be called when the - // write would cause the buffer to fill. - // - // SAFETY: `self.buf` must be initialized up to the byte offset `self.nbuf`, - // and `msg` must contain enough bytes to initialize the rest of the element - // containing the byte offset `self.nbuf`. - #[inline(never)] - unsafe fn slice_write_process_buffer(&mut self, msg: &[u8]) { - let length = msg.len(); - let nbuf = self.nbuf; - debug_assert!(nbuf < BUFFER_SIZE); - debug_assert!(nbuf + length >= BUFFER_SIZE); - - // Always copy first part of input into current element of buffer. - // This function should only be called when the write fills the buffer, - // so we know that there is enough input to fill the current element. - let valid_in_elem = nbuf % ELEM_SIZE; - let needed_in_elem = ELEM_SIZE - valid_in_elem; - - let src = msg.as_ptr(); - let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - copy_nonoverlapping_small(src, dst, needed_in_elem); - - // Process buffer. - - // Using `nbuf / ELEM_SIZE + 1` rather than `(nbuf + needed_in_elem) / - // ELEM_SIZE` to show the compiler that this loop's upper bound is > 0. - // We know that is true, because last step ensured we have a full - // element in the buffer. - let last = nbuf / ELEM_SIZE + 1; - - for i in 0..last { - let elem = self.buf.get_unchecked(i).assume_init().to_le(); - self.state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut self.state); - self.state.v0 ^= elem; - } - - // Process the remaining element-sized chunks of input. - let mut processed = needed_in_elem; - let input_left = length - processed; - let elems_left = input_left / ELEM_SIZE; - let extra_bytes_left = input_left % ELEM_SIZE; - - for _ in 0..elems_left { - let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le(); - self.state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut self.state); - self.state.v0 ^= elem; - processed += ELEM_SIZE; - } - - // Copy remaining input into start of buffer. - let src = msg.as_ptr().add(processed); - let dst = self.buf.as_mut_ptr() as *mut u8; - copy_nonoverlapping_small(src, dst, extra_bytes_left); - - self.nbuf = extra_bytes_left; - self.processed += nbuf + processed; - } - - #[inline] - pub fn finish128(mut self) -> (u64, u64) { - debug_assert!(self.nbuf < BUFFER_SIZE); - - // Process full elements in buffer. - let last = self.nbuf / ELEM_SIZE; - - // Since we're consuming self, avoid updating members for a potential - // performance gain. - let mut state = self.state; - - for i in 0..last { - let elem = unsafe { self.buf.get_unchecked(i).assume_init().to_le() }; - state.v3 ^= elem; - Sip24Rounds::c_rounds(&mut state); - state.v0 ^= elem; - } - - // Get remaining partial element. - let elem = if self.nbuf % ELEM_SIZE != 0 { - unsafe { - // Ensure element is initialized by writing zero bytes. At most - // `ELEM_SIZE - 1` are required given the above check. It's safe - // to write this many because we have the spill and we maintain - // `self.nbuf` such that this write will start before the spill. - let dst = (self.buf.as_mut_ptr() as *mut u8).add(self.nbuf); - ptr::write_bytes(dst, 0, ELEM_SIZE - 1); - self.buf.get_unchecked(last).assume_init().to_le() - } - } else { - 0 - }; - - // Finalize the hash. - let length = self.processed + self.nbuf; - let b: u64 = ((length as u64 & 0xff) << 56) | elem; - - state.v3 ^= b; - Sip24Rounds::c_rounds(&mut state); - state.v0 ^= b; - - state.v2 ^= 0xee; - Sip24Rounds::d_rounds(&mut state); - let _0 = state.v0 ^ state.v1 ^ state.v2 ^ state.v3; - - state.v1 ^= 0xdd; - Sip24Rounds::d_rounds(&mut state); - let _1 = state.v0 ^ state.v1 ^ state.v2 ^ state.v3; - - (_0, _1) - } -} - -impl Hasher for SipHasher128 { - #[inline] - fn write_u8(&mut self, i: u8) { - self.short_write(i); - } - - #[inline] - fn write_u16(&mut self, i: u16) { - self.short_write(i); - } - - #[inline] - fn write_u32(&mut self, i: u32) { - self.short_write(i); - } - - #[inline] - fn write_u64(&mut self, i: u64) { - self.short_write(i); - } - - #[inline] - fn write_usize(&mut self, i: usize) { - self.short_write(i); - } - - #[inline] - fn write_i8(&mut self, i: i8) { - self.short_write(i as u8); - } - - #[inline] - fn write_i16(&mut self, i: i16) { - self.short_write(i as u16); - } - - #[inline] - fn write_i32(&mut self, i: i32) { - self.short_write(i as u32); - } - - #[inline] - fn write_i64(&mut self, i: i64) { - self.short_write(i as u64); - } - - #[inline] - fn write_isize(&mut self, i: isize) { - self.short_write(i as usize); - } - - #[inline] - fn write(&mut self, msg: &[u8]) { - self.slice_write(msg); - } - - fn finish(&self) -> u64 { - panic!("SipHasher128 cannot provide valid 64 bit hashes") - } -} - -#[derive(Debug, Clone, Default)] -struct Sip24Rounds; - -impl Sip24Rounds { - #[inline] - fn c_rounds(state: &mut State) { - compress!(state); - compress!(state); - } - - #[inline] - fn d_rounds(state: &mut State) { - compress!(state); - compress!(state); - compress!(state); - compress!(state); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sip128/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/sip128/tests.rs deleted file mode 100644 index 5fe967c415..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sip128/tests.rs +++ /dev/null @@ -1,497 +0,0 @@ -use super::*; - -use std::hash::{Hash, Hasher}; - -// Hash just the bytes of the slice, without length prefix -struct Bytes<'a>(&'a [u8]); - -impl<'a> Hash for Bytes<'a> { - #[allow(unused_must_use)] - fn hash(&self, state: &mut H) { - for byte in self.0 { - state.write_u8(*byte); - } - } -} - -fn hash_with(mut st: SipHasher128, x: &T) -> (u64, u64) { - x.hash(&mut st); - st.finish128() -} - -fn hash(x: &T) -> (u64, u64) { - hash_with(SipHasher128::new_with_keys(0, 0), x) -} - -const TEST_VECTOR: [[u8; 16]; 64] = [ - [ - 0xa3, 0x81, 0x7f, 0x04, 0xba, 0x25, 0xa8, 0xe6, 0x6d, 0xf6, 0x72, 0x14, 0xc7, 0x55, 0x02, - 0x93, - ], - [ - 0xda, 0x87, 0xc1, 0xd8, 0x6b, 0x99, 0xaf, 0x44, 0x34, 0x76, 0x59, 0x11, 0x9b, 0x22, 0xfc, - 0x45, - ], - [ - 0x81, 0x77, 0x22, 0x8d, 0xa4, 0xa4, 0x5d, 0xc7, 0xfc, 0xa3, 0x8b, 0xde, 0xf6, 0x0a, 0xff, - 0xe4, - ], - [ - 0x9c, 0x70, 0xb6, 0x0c, 0x52, 0x67, 0xa9, 0x4e, 0x5f, 0x33, 0xb6, 0xb0, 0x29, 0x85, 0xed, - 0x51, - ], - [ - 0xf8, 0x81, 0x64, 0xc1, 0x2d, 0x9c, 0x8f, 0xaf, 0x7d, 0x0f, 0x6e, 0x7c, 0x7b, 0xcd, 0x55, - 0x79, - ], - [ - 0x13, 0x68, 0x87, 0x59, 0x80, 0x77, 0x6f, 0x88, 0x54, 0x52, 0x7a, 0x07, 0x69, 0x0e, 0x96, - 0x27, - ], - [ - 0x14, 0xee, 0xca, 0x33, 0x8b, 0x20, 0x86, 0x13, 0x48, 0x5e, 0xa0, 0x30, 0x8f, 0xd7, 0xa1, - 0x5e, - ], - [ - 0xa1, 0xf1, 0xeb, 0xbe, 0xd8, 0xdb, 0xc1, 0x53, 0xc0, 0xb8, 0x4a, 0xa6, 0x1f, 0xf0, 0x82, - 0x39, - ], - [ - 0x3b, 0x62, 0xa9, 0xba, 0x62, 0x58, 0xf5, 0x61, 0x0f, 0x83, 0xe2, 0x64, 0xf3, 0x14, 0x97, - 0xb4, - ], - [ - 0x26, 0x44, 0x99, 0x06, 0x0a, 0xd9, 0xba, 0xab, 0xc4, 0x7f, 0x8b, 0x02, 0xbb, 0x6d, 0x71, - 0xed, - ], - [ - 0x00, 0x11, 0x0d, 0xc3, 0x78, 0x14, 0x69, 0x56, 0xc9, 0x54, 0x47, 0xd3, 0xf3, 0xd0, 0xfb, - 0xba, - ], - [ - 0x01, 0x51, 0xc5, 0x68, 0x38, 0x6b, 0x66, 0x77, 0xa2, 0xb4, 0xdc, 0x6f, 0x81, 0xe5, 0xdc, - 0x18, - ], - [ - 0xd6, 0x26, 0xb2, 0x66, 0x90, 0x5e, 0xf3, 0x58, 0x82, 0x63, 0x4d, 0xf6, 0x85, 0x32, 0xc1, - 0x25, - ], - [ - 0x98, 0x69, 0xe2, 0x47, 0xe9, 0xc0, 0x8b, 0x10, 0xd0, 0x29, 0x93, 0x4f, 0xc4, 0xb9, 0x52, - 0xf7, - ], - [ - 0x31, 0xfc, 0xef, 0xac, 0x66, 0xd7, 0xde, 0x9c, 0x7e, 0xc7, 0x48, 0x5f, 0xe4, 0x49, 0x49, - 0x02, - ], - [ - 0x54, 0x93, 0xe9, 0x99, 0x33, 0xb0, 0xa8, 0x11, 0x7e, 0x08, 0xec, 0x0f, 0x97, 0xcf, 0xc3, - 0xd9, - ], - [ - 0x6e, 0xe2, 0xa4, 0xca, 0x67, 0xb0, 0x54, 0xbb, 0xfd, 0x33, 0x15, 0xbf, 0x85, 0x23, 0x05, - 0x77, - ], - [ - 0x47, 0x3d, 0x06, 0xe8, 0x73, 0x8d, 0xb8, 0x98, 0x54, 0xc0, 0x66, 0xc4, 0x7a, 0xe4, 0x77, - 0x40, - ], - [ - 0xa4, 0x26, 0xe5, 0xe4, 0x23, 0xbf, 0x48, 0x85, 0x29, 0x4d, 0xa4, 0x81, 0xfe, 0xae, 0xf7, - 0x23, - ], - [ - 0x78, 0x01, 0x77, 0x31, 0xcf, 0x65, 0xfa, 0xb0, 0x74, 0xd5, 0x20, 0x89, 0x52, 0x51, 0x2e, - 0xb1, - ], - [ - 0x9e, 0x25, 0xfc, 0x83, 0x3f, 0x22, 0x90, 0x73, 0x3e, 0x93, 0x44, 0xa5, 0xe8, 0x38, 0x39, - 0xeb, - ], - [ - 0x56, 0x8e, 0x49, 0x5a, 0xbe, 0x52, 0x5a, 0x21, 0x8a, 0x22, 0x14, 0xcd, 0x3e, 0x07, 0x1d, - 0x12, - ], - [ - 0x4a, 0x29, 0xb5, 0x45, 0x52, 0xd1, 0x6b, 0x9a, 0x46, 0x9c, 0x10, 0x52, 0x8e, 0xff, 0x0a, - 0xae, - ], - [ - 0xc9, 0xd1, 0x84, 0xdd, 0xd5, 0xa9, 0xf5, 0xe0, 0xcf, 0x8c, 0xe2, 0x9a, 0x9a, 0xbf, 0x69, - 0x1c, - ], - [ - 0x2d, 0xb4, 0x79, 0xae, 0x78, 0xbd, 0x50, 0xd8, 0x88, 0x2a, 0x8a, 0x17, 0x8a, 0x61, 0x32, - 0xad, - ], - [ - 0x8e, 0xce, 0x5f, 0x04, 0x2d, 0x5e, 0x44, 0x7b, 0x50, 0x51, 0xb9, 0xea, 0xcb, 0x8d, 0x8f, - 0x6f, - ], - [ - 0x9c, 0x0b, 0x53, 0xb4, 0xb3, 0xc3, 0x07, 0xe8, 0x7e, 0xae, 0xe0, 0x86, 0x78, 0x14, 0x1f, - 0x66, - ], - [ - 0xab, 0xf2, 0x48, 0xaf, 0x69, 0xa6, 0xea, 0xe4, 0xbf, 0xd3, 0xeb, 0x2f, 0x12, 0x9e, 0xeb, - 0x94, - ], - [ - 0x06, 0x64, 0xda, 0x16, 0x68, 0x57, 0x4b, 0x88, 0xb9, 0x35, 0xf3, 0x02, 0x73, 0x58, 0xae, - 0xf4, - ], - [ - 0xaa, 0x4b, 0x9d, 0xc4, 0xbf, 0x33, 0x7d, 0xe9, 0x0c, 0xd4, 0xfd, 0x3c, 0x46, 0x7c, 0x6a, - 0xb7, - ], - [ - 0xea, 0x5c, 0x7f, 0x47, 0x1f, 0xaf, 0x6b, 0xde, 0x2b, 0x1a, 0xd7, 0xd4, 0x68, 0x6d, 0x22, - 0x87, - ], - [ - 0x29, 0x39, 0xb0, 0x18, 0x32, 0x23, 0xfa, 0xfc, 0x17, 0x23, 0xde, 0x4f, 0x52, 0xc4, 0x3d, - 0x35, - ], - [ - 0x7c, 0x39, 0x56, 0xca, 0x5e, 0xea, 0xfc, 0x3e, 0x36, 0x3e, 0x9d, 0x55, 0x65, 0x46, 0xeb, - 0x68, - ], - [ - 0x77, 0xc6, 0x07, 0x71, 0x46, 0xf0, 0x1c, 0x32, 0xb6, 0xb6, 0x9d, 0x5f, 0x4e, 0xa9, 0xff, - 0xcf, - ], - [ - 0x37, 0xa6, 0x98, 0x6c, 0xb8, 0x84, 0x7e, 0xdf, 0x09, 0x25, 0xf0, 0xf1, 0x30, 0x9b, 0x54, - 0xde, - ], - [ - 0xa7, 0x05, 0xf0, 0xe6, 0x9d, 0xa9, 0xa8, 0xf9, 0x07, 0x24, 0x1a, 0x2e, 0x92, 0x3c, 0x8c, - 0xc8, - ], - [ - 0x3d, 0xc4, 0x7d, 0x1f, 0x29, 0xc4, 0x48, 0x46, 0x1e, 0x9e, 0x76, 0xed, 0x90, 0x4f, 0x67, - 0x11, - ], - [ - 0x0d, 0x62, 0xbf, 0x01, 0xe6, 0xfc, 0x0e, 0x1a, 0x0d, 0x3c, 0x47, 0x51, 0xc5, 0xd3, 0x69, - 0x2b, - ], - [ - 0x8c, 0x03, 0x46, 0x8b, 0xca, 0x7c, 0x66, 0x9e, 0xe4, 0xfd, 0x5e, 0x08, 0x4b, 0xbe, 0xe7, - 0xb5, - ], - [ - 0x52, 0x8a, 0x5b, 0xb9, 0x3b, 0xaf, 0x2c, 0x9c, 0x44, 0x73, 0xcc, 0xe5, 0xd0, 0xd2, 0x2b, - 0xd9, - ], - [ - 0xdf, 0x6a, 0x30, 0x1e, 0x95, 0xc9, 0x5d, 0xad, 0x97, 0xae, 0x0c, 0xc8, 0xc6, 0x91, 0x3b, - 0xd8, - ], - [ - 0x80, 0x11, 0x89, 0x90, 0x2c, 0x85, 0x7f, 0x39, 0xe7, 0x35, 0x91, 0x28, 0x5e, 0x70, 0xb6, - 0xdb, - ], - [ - 0xe6, 0x17, 0x34, 0x6a, 0xc9, 0xc2, 0x31, 0xbb, 0x36, 0x50, 0xae, 0x34, 0xcc, 0xca, 0x0c, - 0x5b, - ], - [ - 0x27, 0xd9, 0x34, 0x37, 0xef, 0xb7, 0x21, 0xaa, 0x40, 0x18, 0x21, 0xdc, 0xec, 0x5a, 0xdf, - 0x89, - ], - [ - 0x89, 0x23, 0x7d, 0x9d, 0xed, 0x9c, 0x5e, 0x78, 0xd8, 0xb1, 0xc9, 0xb1, 0x66, 0xcc, 0x73, - 0x42, - ], - [ - 0x4a, 0x6d, 0x80, 0x91, 0xbf, 0x5e, 0x7d, 0x65, 0x11, 0x89, 0xfa, 0x94, 0xa2, 0x50, 0xb1, - 0x4c, - ], - [ - 0x0e, 0x33, 0xf9, 0x60, 0x55, 0xe7, 0xae, 0x89, 0x3f, 0xfc, 0x0e, 0x3d, 0xcf, 0x49, 0x29, - 0x02, - ], - [ - 0xe6, 0x1c, 0x43, 0x2b, 0x72, 0x0b, 0x19, 0xd1, 0x8e, 0xc8, 0xd8, 0x4b, 0xdc, 0x63, 0x15, - 0x1b, - ], - [ - 0xf7, 0xe5, 0xae, 0xf5, 0x49, 0xf7, 0x82, 0xcf, 0x37, 0x90, 0x55, 0xa6, 0x08, 0x26, 0x9b, - 0x16, - ], - [ - 0x43, 0x8d, 0x03, 0x0f, 0xd0, 0xb7, 0xa5, 0x4f, 0xa8, 0x37, 0xf2, 0xad, 0x20, 0x1a, 0x64, - 0x03, - ], - [ - 0xa5, 0x90, 0xd3, 0xee, 0x4f, 0xbf, 0x04, 0xe3, 0x24, 0x7e, 0x0d, 0x27, 0xf2, 0x86, 0x42, - 0x3f, - ], - [ - 0x5f, 0xe2, 0xc1, 0xa1, 0x72, 0xfe, 0x93, 0xc4, 0xb1, 0x5c, 0xd3, 0x7c, 0xae, 0xf9, 0xf5, - 0x38, - ], - [ - 0x2c, 0x97, 0x32, 0x5c, 0xbd, 0x06, 0xb3, 0x6e, 0xb2, 0x13, 0x3d, 0xd0, 0x8b, 0x3a, 0x01, - 0x7c, - ], - [ - 0x92, 0xc8, 0x14, 0x22, 0x7a, 0x6b, 0xca, 0x94, 0x9f, 0xf0, 0x65, 0x9f, 0x00, 0x2a, 0xd3, - 0x9e, - ], - [ - 0xdc, 0xe8, 0x50, 0x11, 0x0b, 0xd8, 0x32, 0x8c, 0xfb, 0xd5, 0x08, 0x41, 0xd6, 0x91, 0x1d, - 0x87, - ], - [ - 0x67, 0xf1, 0x49, 0x84, 0xc7, 0xda, 0x79, 0x12, 0x48, 0xe3, 0x2b, 0xb5, 0x92, 0x25, 0x83, - 0xda, - ], - [ - 0x19, 0x38, 0xf2, 0xcf, 0x72, 0xd5, 0x4e, 0xe9, 0x7e, 0x94, 0x16, 0x6f, 0xa9, 0x1d, 0x2a, - 0x36, - ], - [ - 0x74, 0x48, 0x1e, 0x96, 0x46, 0xed, 0x49, 0xfe, 0x0f, 0x62, 0x24, 0x30, 0x16, 0x04, 0x69, - 0x8e, - ], - [ - 0x57, 0xfc, 0xa5, 0xde, 0x98, 0xa9, 0xd6, 0xd8, 0x00, 0x64, 0x38, 0xd0, 0x58, 0x3d, 0x8a, - 0x1d, - ], - [ - 0x9f, 0xec, 0xde, 0x1c, 0xef, 0xdc, 0x1c, 0xbe, 0xd4, 0x76, 0x36, 0x74, 0xd9, 0x57, 0x53, - 0x59, - ], - [ - 0xe3, 0x04, 0x0c, 0x00, 0xeb, 0x28, 0xf1, 0x53, 0x66, 0xca, 0x73, 0xcb, 0xd8, 0x72, 0xe7, - 0x40, - ], - [ - 0x76, 0x97, 0x00, 0x9a, 0x6a, 0x83, 0x1d, 0xfe, 0xcc, 0xa9, 0x1c, 0x59, 0x93, 0x67, 0x0f, - 0x7a, - ], - [ - 0x58, 0x53, 0x54, 0x23, 0x21, 0xf5, 0x67, 0xa0, 0x05, 0xd5, 0x47, 0xa4, 0xf0, 0x47, 0x59, - 0xbd, - ], - [ - 0x51, 0x50, 0xd1, 0x77, 0x2f, 0x50, 0x83, 0x4a, 0x50, 0x3e, 0x06, 0x9a, 0x97, 0x3f, 0xbd, - 0x7c, - ], -]; - -// Test vector from reference implementation -#[test] -fn test_siphash_2_4_test_vector() { - let k0 = 0x_07_06_05_04_03_02_01_00; - let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; - - let mut input: Vec = Vec::new(); - - for i in 0..64 { - let out = hash_with(SipHasher128::new_with_keys(k0, k1), &Bytes(&input[..])); - let expected = ( - ((TEST_VECTOR[i][0] as u64) << 0) - | ((TEST_VECTOR[i][1] as u64) << 8) - | ((TEST_VECTOR[i][2] as u64) << 16) - | ((TEST_VECTOR[i][3] as u64) << 24) - | ((TEST_VECTOR[i][4] as u64) << 32) - | ((TEST_VECTOR[i][5] as u64) << 40) - | ((TEST_VECTOR[i][6] as u64) << 48) - | ((TEST_VECTOR[i][7] as u64) << 56), - ((TEST_VECTOR[i][8] as u64) << 0) - | ((TEST_VECTOR[i][9] as u64) << 8) - | ((TEST_VECTOR[i][10] as u64) << 16) - | ((TEST_VECTOR[i][11] as u64) << 24) - | ((TEST_VECTOR[i][12] as u64) << 32) - | ((TEST_VECTOR[i][13] as u64) << 40) - | ((TEST_VECTOR[i][14] as u64) << 48) - | ((TEST_VECTOR[i][15] as u64) << 56), - ); - - assert_eq!(out, expected); - input.push(i as u8); - } -} - -#[test] -#[cfg(target_arch = "arm")] -fn test_hash_usize() { - let val = 0xdeadbeef_deadbeef_u64; - assert!(hash(&(val as u64)) != hash(&(val as usize))); - assert_eq!(hash(&(val as u32)), hash(&(val as usize))); -} -#[test] -#[cfg(target_arch = "x86_64")] -fn test_hash_usize() { - let val = 0xdeadbeef_deadbeef_u64; - assert_eq!(hash(&(val as u64)), hash(&(val as usize))); - assert!(hash(&(val as u32)) != hash(&(val as usize))); -} -#[test] -#[cfg(target_arch = "x86")] -fn test_hash_usize() { - let val = 0xdeadbeef_deadbeef_u64; - assert!(hash(&(val as u64)) != hash(&(val as usize))); - assert_eq!(hash(&(val as u32)), hash(&(val as usize))); -} - -#[test] -fn test_hash_idempotent() { - let val64 = 0xdeadbeef_deadbeef_u64; - assert_eq!(hash(&val64), hash(&val64)); - let val32 = 0xdeadbeef_u32; - assert_eq!(hash(&val32), hash(&val32)); -} - -#[test] -fn test_hash_no_bytes_dropped_64() { - let val = 0xdeadbeef_deadbeef_u64; - - assert!(hash(&val) != hash(&zero_byte(val, 0))); - assert!(hash(&val) != hash(&zero_byte(val, 1))); - assert!(hash(&val) != hash(&zero_byte(val, 2))); - assert!(hash(&val) != hash(&zero_byte(val, 3))); - assert!(hash(&val) != hash(&zero_byte(val, 4))); - assert!(hash(&val) != hash(&zero_byte(val, 5))); - assert!(hash(&val) != hash(&zero_byte(val, 6))); - assert!(hash(&val) != hash(&zero_byte(val, 7))); - - fn zero_byte(val: u64, byte: usize) -> u64 { - assert!(byte < 8); - val & !(0xff << (byte * 8)) - } -} - -#[test] -fn test_hash_no_bytes_dropped_32() { - let val = 0xdeadbeef_u32; - - assert!(hash(&val) != hash(&zero_byte(val, 0))); - assert!(hash(&val) != hash(&zero_byte(val, 1))); - assert!(hash(&val) != hash(&zero_byte(val, 2))); - assert!(hash(&val) != hash(&zero_byte(val, 3))); - - fn zero_byte(val: u32, byte: usize) -> u32 { - assert!(byte < 4); - val & !(0xff << (byte * 8)) - } -} - -#[test] -fn test_hash_no_concat_alias() { - let s = ("aa", "bb"); - let t = ("aabb", ""); - let u = ("a", "abb"); - - assert!(s != t && t != u); - assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u)); - - let u = [1, 0, 0, 0]; - let v = (&u[..1], &u[1..3], &u[3..]); - let w = (&u[..], &u[4..4], &u[4..4]); - - assert!(v != w); - assert!(hash(&v) != hash(&w)); -} - -#[test] -fn test_short_write_works() { - let test_u8 = 0xFF_u8; - let test_u16 = 0x1122_u16; - let test_u32 = 0x22334455_u32; - let test_u64 = 0x33445566_778899AA_u64; - let test_u128 = 0x11223344_55667788_99AABBCC_DDEEFF77_u128; - let test_usize = 0xD0C0B0A0_usize; - - let test_i8 = -1_i8; - let test_i16 = -2_i16; - let test_i32 = -3_i32; - let test_i64 = -4_i64; - let test_i128 = -5_i128; - let test_isize = -6_isize; - - let mut h1 = SipHasher128::new_with_keys(0, 0); - h1.write(b"bytes"); - h1.write(b"string"); - h1.write_u8(test_u8); - h1.write_u16(test_u16); - h1.write_u32(test_u32); - h1.write_u64(test_u64); - h1.write_u128(test_u128); - h1.write_usize(test_usize); - h1.write_i8(test_i8); - h1.write_i16(test_i16); - h1.write_i32(test_i32); - h1.write_i64(test_i64); - h1.write_i128(test_i128); - h1.write_isize(test_isize); - - let mut h2 = SipHasher128::new_with_keys(0, 0); - h2.write(b"bytes"); - h2.write(b"string"); - h2.write(&test_u8.to_ne_bytes()); - h2.write(&test_u16.to_ne_bytes()); - h2.write(&test_u32.to_ne_bytes()); - h2.write(&test_u64.to_ne_bytes()); - h2.write(&test_u128.to_ne_bytes()); - h2.write(&test_usize.to_ne_bytes()); - h2.write(&test_i8.to_ne_bytes()); - h2.write(&test_i16.to_ne_bytes()); - h2.write(&test_i32.to_ne_bytes()); - h2.write(&test_i64.to_ne_bytes()); - h2.write(&test_i128.to_ne_bytes()); - h2.write(&test_isize.to_ne_bytes()); - - let h1_hash = h1.finish128(); - let h2_hash = h2.finish128(); - - assert_eq!(h1_hash, h2_hash); -} - -macro_rules! test_fill_buffer { - ($type:ty, $write_method:ident) => {{ - // Test filling and overfilling the buffer from all possible offsets - // for a given integer type and its corresponding write method. - const SIZE: usize = std::mem::size_of::<$type>(); - let input = [42; BUFFER_SIZE]; - let x = 0x01234567_89ABCDEF_76543210_FEDCBA98_u128 as $type; - let x_bytes = &x.to_ne_bytes(); - - for i in 1..=SIZE { - let s = &input[..BUFFER_SIZE - i]; - - let mut h1 = SipHasher128::new_with_keys(7, 13); - h1.write(s); - h1.$write_method(x); - - let mut h2 = SipHasher128::new_with_keys(7, 13); - h2.write(s); - h2.write(x_bytes); - - let h1_hash = h1.finish128(); - let h2_hash = h2.finish128(); - - assert_eq!(h1_hash, h2_hash); - } - }}; -} - -#[test] -fn test_fill_buffer() { - test_fill_buffer!(u8, write_u8); - test_fill_buffer!(u16, write_u16); - test_fill_buffer!(u32, write_u32); - test_fill_buffer!(u64, write_u64); - test_fill_buffer!(u128, write_u128); - test_fill_buffer!(usize, write_usize); - - test_fill_buffer!(i8, write_i8); - test_fill_buffer!(i16, write_i16); - test_fill_buffer!(i32, write_i32); - test_fill_buffer!(i64, write_i64); - test_fill_buffer!(i128, write_i128); - test_fill_buffer!(isize, write_isize); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/small_c_str.rs b/vendor/rustc-ap-rustc_data_structures/src/small_c_str.rs deleted file mode 100644 index 4a089398ce..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/small_c_str.rs +++ /dev/null @@ -1,68 +0,0 @@ -use std::ffi; -use std::ops::Deref; - -use smallvec::SmallVec; - -#[cfg(test)] -mod tests; - -const SIZE: usize = 36; - -/// Like SmallVec but for C strings. -#[derive(Clone)] -pub struct SmallCStr { - data: SmallVec<[u8; SIZE]>, -} - -impl SmallCStr { - #[inline] - pub fn new(s: &str) -> SmallCStr { - let len = s.len(); - let len1 = len + 1; - let data = if len < SIZE { - let mut buf = [0; SIZE]; - buf[..len].copy_from_slice(s.as_bytes()); - SmallVec::from_buf_and_len(buf, len1) - } else { - let mut data = Vec::with_capacity(len1); - data.extend_from_slice(s.as_bytes()); - data.push(0); - SmallVec::from_vec(data) - }; - if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) { - panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); - } - SmallCStr { data } - } - - #[inline] - pub fn new_with_nul(s: &str) -> SmallCStr { - let b = s.as_bytes(); - if let Err(e) = ffi::CStr::from_bytes_with_nul(b) { - panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); - } - SmallCStr { data: SmallVec::from_slice(s.as_bytes()) } - } - - #[inline] - pub fn as_c_str(&self) -> &ffi::CStr { - unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..]) } - } - - #[inline] - pub fn len_with_nul(&self) -> usize { - self.data.len() - } - - pub fn spilled(&self) -> bool { - self.data.spilled() - } -} - -impl Deref for SmallCStr { - type Target = ffi::CStr; - - fn deref(&self) -> &ffi::CStr { - self.as_c_str() - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/small_c_str/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/small_c_str/tests.rs deleted file mode 100644 index 47277604b2..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/small_c_str/tests.rs +++ /dev/null @@ -1,45 +0,0 @@ -use super::*; - -#[test] -fn short() { - const TEXT: &str = "abcd"; - let reference = ffi::CString::new(TEXT.to_string()).unwrap(); - - let scs = SmallCStr::new(TEXT); - - assert_eq!(scs.len_with_nul(), TEXT.len() + 1); - assert_eq!(scs.as_c_str(), reference.as_c_str()); - assert!(!scs.spilled()); -} - -#[test] -fn empty() { - const TEXT: &str = ""; - let reference = ffi::CString::new(TEXT.to_string()).unwrap(); - - let scs = SmallCStr::new(TEXT); - - assert_eq!(scs.len_with_nul(), TEXT.len() + 1); - assert_eq!(scs.as_c_str(), reference.as_c_str()); - assert!(!scs.spilled()); -} - -#[test] -fn long() { - const TEXT: &str = "01234567890123456789012345678901234567890123456789\ - 01234567890123456789012345678901234567890123456789\ - 01234567890123456789012345678901234567890123456789"; - let reference = ffi::CString::new(TEXT.to_string()).unwrap(); - - let scs = SmallCStr::new(TEXT); - - assert_eq!(scs.len_with_nul(), TEXT.len() + 1); - assert_eq!(scs.as_c_str(), reference.as_c_str()); - assert!(scs.spilled()); -} - -#[test] -#[should_panic] -fn internal_nul() { - let _ = SmallCStr::new("abcd\0def"); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/snapshot_map/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/snapshot_map/mod.rs deleted file mode 100644 index b4cc85293f..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/snapshot_map/mod.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::fx::FxHashMap; -use crate::undo_log::{Rollback, Snapshots, UndoLogs, VecLog}; -use std::borrow::{Borrow, BorrowMut}; -use std::hash::Hash; -use std::marker::PhantomData; -use std::ops; - -pub use crate::undo_log::Snapshot; - -#[cfg(test)] -mod tests; - -pub type SnapshotMapStorage = SnapshotMap, ()>; -pub type SnapshotMapRef<'a, K, V, L> = SnapshotMap, &'a mut L>; - -pub struct SnapshotMap, L = VecLog>> { - map: M, - undo_log: L, - _marker: PhantomData<(K, V)>, -} - -// HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`. -impl Default for SnapshotMap -where - M: Default, - L: Default, -{ - fn default() -> Self { - SnapshotMap { map: Default::default(), undo_log: Default::default(), _marker: PhantomData } - } -} - -pub enum UndoLog { - Inserted(K), - Overwrite(K, V), - Purged, -} - -impl SnapshotMap { - #[inline] - pub fn with_log(&mut self, undo_log: L2) -> SnapshotMap { - SnapshotMap { map: &mut self.map, undo_log, _marker: PhantomData } - } -} - -impl SnapshotMap -where - K: Hash + Clone + Eq, - M: BorrowMut> + Borrow>, - L: UndoLogs>, -{ - pub fn clear(&mut self) { - self.map.borrow_mut().clear(); - self.undo_log.clear(); - } - - pub fn insert(&mut self, key: K, value: V) -> bool { - match self.map.borrow_mut().insert(key.clone(), value) { - None => { - self.undo_log.push(UndoLog::Inserted(key)); - true - } - Some(old_value) => { - self.undo_log.push(UndoLog::Overwrite(key, old_value)); - false - } - } - } - - pub fn remove(&mut self, key: K) -> bool { - match self.map.borrow_mut().remove(&key) { - Some(old_value) => { - self.undo_log.push(UndoLog::Overwrite(key, old_value)); - true - } - None => false, - } - } - - pub fn get(&self, key: &K) -> Option<&V> { - self.map.borrow().get(key) - } -} - -impl SnapshotMap -where - K: Hash + Clone + Eq, -{ - pub fn snapshot(&mut self) -> Snapshot { - self.undo_log.start_snapshot() - } - - pub fn commit(&mut self, snapshot: Snapshot) { - self.undo_log.commit(snapshot) - } - - pub fn rollback_to(&mut self, snapshot: Snapshot) { - let map = &mut self.map; - self.undo_log.rollback_to(|| map, snapshot) - } -} - -impl<'k, K, V, M, L> ops::Index<&'k K> for SnapshotMap -where - K: Hash + Clone + Eq, - M: Borrow>, -{ - type Output = V; - fn index(&self, key: &'k K) -> &V { - &self.map.borrow()[key] - } -} - -impl Rollback> for SnapshotMap -where - K: Eq + Hash, - M: Rollback>, -{ - fn reverse(&mut self, undo: UndoLog) { - self.map.reverse(undo) - } -} - -impl Rollback> for FxHashMap -where - K: Eq + Hash, -{ - fn reverse(&mut self, undo: UndoLog) { - match undo { - UndoLog::Inserted(key) => { - self.remove(&key); - } - - UndoLog::Overwrite(key, old_value) => { - self.insert(key, old_value); - } - - UndoLog::Purged => {} - } - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/snapshot_map/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/snapshot_map/tests.rs deleted file mode 100644 index 72ca53c2be..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/snapshot_map/tests.rs +++ /dev/null @@ -1,43 +0,0 @@ -use super::SnapshotMap; - -#[test] -fn basic() { - let mut map = SnapshotMap::default(); - map.insert(22, "twenty-two"); - let snapshot = map.snapshot(); - map.insert(22, "thirty-three"); - assert_eq!(map[&22], "thirty-three"); - map.insert(44, "forty-four"); - assert_eq!(map[&44], "forty-four"); - assert_eq!(map.get(&33), None); - map.rollback_to(snapshot); - assert_eq!(map[&22], "twenty-two"); - assert_eq!(map.get(&33), None); - assert_eq!(map.get(&44), None); -} - -#[test] -#[should_panic] -fn out_of_order() { - let mut map = SnapshotMap::default(); - map.insert(22, "twenty-two"); - let snapshot1 = map.snapshot(); - map.insert(33, "thirty-three"); - let snapshot2 = map.snapshot(); - map.insert(44, "forty-four"); - map.rollback_to(snapshot1); // bogus, but accepted - map.rollback_to(snapshot2); // asserts -} - -#[test] -fn nested_commit_then_rollback() { - let mut map = SnapshotMap::default(); - map.insert(22, "twenty-two"); - let snapshot1 = map.snapshot(); - let snapshot2 = map.snapshot(); - map.insert(22, "thirty-three"); - map.commit(snapshot2); - assert_eq!(map[&22], "thirty-three"); - map.rollback_to(snapshot1); - assert_eq!(map[&22], "twenty-two"); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sorted_map.rs b/vendor/rustc-ap-rustc_data_structures/src/sorted_map.rs deleted file mode 100644 index 9a28f8f4e2..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sorted_map.rs +++ /dev/null @@ -1,285 +0,0 @@ -use std::borrow::Borrow; -use std::cmp::Ordering; -use std::iter::FromIterator; -use std::mem; -use std::ops::{Bound, Index, IndexMut, RangeBounds}; - -mod index_map; - -pub use index_map::SortedIndexMultiMap; - -/// `SortedMap` is a data structure with similar characteristics as BTreeMap but -/// slightly different trade-offs: lookup, insertion, and removal are O(log(N)) -/// and elements can be iterated in order cheaply. -/// -/// `SortedMap` can be faster than a `BTreeMap` for small sizes (<50) since it -/// stores data in a more compact way. It also supports accessing contiguous -/// ranges of elements as a slice, and slices of already sorted elements can be -/// inserted efficiently. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)] -pub struct SortedMap { - data: Vec<(K, V)>, -} - -impl SortedMap { - #[inline] - pub fn new() -> SortedMap { - SortedMap { data: vec![] } - } - - /// Construct a `SortedMap` from a presorted set of elements. This is faster - /// than creating an empty map and then inserting the elements individually. - /// - /// It is up to the caller to make sure that the elements are sorted by key - /// and that there are no duplicates. - #[inline] - pub fn from_presorted_elements(elements: Vec<(K, V)>) -> SortedMap { - debug_assert!(elements.array_windows().all(|[fst, snd]| fst.0 < snd.0)); - - SortedMap { data: elements } - } - - #[inline] - pub fn insert(&mut self, key: K, mut value: V) -> Option { - match self.lookup_index_for(&key) { - Ok(index) => { - let slot = unsafe { self.data.get_unchecked_mut(index) }; - mem::swap(&mut slot.1, &mut value); - Some(value) - } - Err(index) => { - self.data.insert(index, (key, value)); - None - } - } - } - - #[inline] - pub fn remove(&mut self, key: &K) -> Option { - match self.lookup_index_for(key) { - Ok(index) => Some(self.data.remove(index).1), - Err(_) => None, - } - } - - #[inline] - pub fn get(&self, key: &Q) -> Option<&V> - where - K: Borrow, - Q: Ord + ?Sized, - { - match self.lookup_index_for(key) { - Ok(index) => unsafe { Some(&self.data.get_unchecked(index).1) }, - Err(_) => None, - } - } - - #[inline] - pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> - where - K: Borrow, - Q: Ord + ?Sized, - { - match self.lookup_index_for(key) { - Ok(index) => unsafe { Some(&mut self.data.get_unchecked_mut(index).1) }, - Err(_) => None, - } - } - - #[inline] - pub fn clear(&mut self) { - self.data.clear(); - } - - /// Iterate over elements, sorted by key - #[inline] - pub fn iter(&self) -> std::slice::Iter<'_, (K, V)> { - self.data.iter() - } - - /// Iterate over the keys, sorted - #[inline] - pub fn keys(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { - self.data.iter().map(|&(ref k, _)| k) - } - - /// Iterate over values, sorted by key - #[inline] - pub fn values(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { - self.data.iter().map(|&(_, ref v)| v) - } - - #[inline] - pub fn len(&self) -> usize { - self.data.len() - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - #[inline] - pub fn range(&self, range: R) -> &[(K, V)] - where - R: RangeBounds, - { - let (start, end) = self.range_slice_indices(range); - &self.data[start..end] - } - - #[inline] - pub fn remove_range(&mut self, range: R) - where - R: RangeBounds, - { - let (start, end) = self.range_slice_indices(range); - self.data.splice(start..end, std::iter::empty()); - } - - /// Mutate all keys with the given function `f`. This mutation must not - /// change the sort-order of keys. - #[inline] - pub fn offset_keys(&mut self, f: F) - where - F: Fn(&mut K), - { - self.data.iter_mut().map(|&mut (ref mut k, _)| k).for_each(f); - } - - /// Inserts a presorted range of elements into the map. If the range can be - /// inserted as a whole in between to existing elements of the map, this - /// will be faster than inserting the elements individually. - /// - /// It is up to the caller to make sure that the elements are sorted by key - /// and that there are no duplicates. - #[inline] - pub fn insert_presorted(&mut self, mut elements: Vec<(K, V)>) { - if elements.is_empty() { - return; - } - - debug_assert!(elements.array_windows().all(|[fst, snd]| fst.0 < snd.0)); - - let start_index = self.lookup_index_for(&elements[0].0); - - let drain = match start_index { - Ok(index) => { - let mut drain = elements.drain(..); - self.data[index] = drain.next().unwrap(); - drain - } - Err(index) => { - if index == self.data.len() || elements.last().unwrap().0 < self.data[index].0 { - // We can copy the whole range without having to mix with - // existing elements. - self.data.splice(index..index, elements.drain(..)); - return; - } - - let mut drain = elements.drain(..); - self.data.insert(index, drain.next().unwrap()); - drain - } - }; - - // Insert the rest - for (k, v) in drain { - self.insert(k, v); - } - } - - /// Looks up the key in `self.data` via `slice::binary_search()`. - #[inline(always)] - fn lookup_index_for(&self, key: &Q) -> Result - where - K: Borrow, - Q: Ord + ?Sized, - { - self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key)) - } - - #[inline] - fn range_slice_indices(&self, range: R) -> (usize, usize) - where - R: RangeBounds, - { - let start = match range.start_bound() { - Bound::Included(ref k) => match self.lookup_index_for(k) { - Ok(index) | Err(index) => index, - }, - Bound::Excluded(ref k) => match self.lookup_index_for(k) { - Ok(index) => index + 1, - Err(index) => index, - }, - Bound::Unbounded => 0, - }; - - let end = match range.end_bound() { - Bound::Included(ref k) => match self.lookup_index_for(k) { - Ok(index) => index + 1, - Err(index) => index, - }, - Bound::Excluded(ref k) => match self.lookup_index_for(k) { - Ok(index) | Err(index) => index, - }, - Bound::Unbounded => self.data.len(), - }; - - (start, end) - } - - #[inline] - pub fn contains_key(&self, key: &Q) -> bool - where - K: Borrow, - Q: Ord + ?Sized, - { - self.get(key).is_some() - } -} - -impl IntoIterator for SortedMap { - type Item = (K, V); - type IntoIter = std::vec::IntoIter<(K, V)>; - - fn into_iter(self) -> Self::IntoIter { - self.data.into_iter() - } -} - -impl<'a, K, Q, V> Index<&'a Q> for SortedMap -where - K: Ord + Borrow, - Q: Ord + ?Sized, -{ - type Output = V; - - fn index(&self, key: &Q) -> &Self::Output { - self.get(key).expect("no entry found for key") - } -} - -impl<'a, K, Q, V> IndexMut<&'a Q> for SortedMap -where - K: Ord + Borrow, - Q: Ord + ?Sized, -{ - fn index_mut(&mut self, key: &Q) -> &mut Self::Output { - self.get_mut(key).expect("no entry found for key") - } -} - -impl FromIterator<(K, V)> for SortedMap { - fn from_iter>(iter: T) -> Self { - let mut data: Vec<(K, V)> = iter.into_iter().collect(); - - data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2)); - data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| k1.cmp(k2) == Ordering::Equal); - - SortedMap { data } - } -} - -#[cfg(test)] -mod tests; diff --git a/vendor/rustc-ap-rustc_data_structures/src/sorted_map/index_map.rs b/vendor/rustc-ap-rustc_data_structures/src/sorted_map/index_map.rs deleted file mode 100644 index 01cd1cec92..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sorted_map/index_map.rs +++ /dev/null @@ -1,217 +0,0 @@ -//! A variant of `SortedMap` that preserves insertion order. - -use std::borrow::Borrow; -use std::hash::{Hash, Hasher}; -use std::iter::FromIterator; - -use crate::stable_hasher::{HashStable, StableHasher}; -use rustc_index::vec::{Idx, IndexVec}; - -/// An indexed multi-map that preserves insertion order while permitting both *O*(log *n*) lookup of -/// an item by key and *O*(1) lookup by index. -/// -/// This data structure is a hybrid of an [`IndexVec`] and a [`SortedMap`]. Like `IndexVec`, -/// `SortedIndexMultiMap` assigns a typed index to each item while preserving insertion order. -/// Like `SortedMap`, `SortedIndexMultiMap` has efficient lookup of items by key. However, this -/// is accomplished by sorting an array of item indices instead of the items themselves. -/// -/// Unlike `SortedMap`, this data structure can hold multiple equivalent items at once, so the -/// `get_by_key` method and its variants return an iterator instead of an `Option`. Equivalent -/// items will be yielded in insertion order. -/// -/// Unlike a general-purpose map like `BTreeSet` or `HashSet`, `SortedMap` and -/// `SortedIndexMultiMap` require *O*(*n*) time to insert a single item. This is because we may need -/// to insert into the middle of the sorted array. Users should avoid mutating this data structure -/// in-place. -/// -/// [`SortedMap`]: super::SortedMap -#[derive(Clone, Debug)] -pub struct SortedIndexMultiMap { - /// The elements of the map in insertion order. - items: IndexVec, - - /// Indices of the items in the set, sorted by the item's key. - idx_sorted_by_item_key: Vec, -} - -impl SortedIndexMultiMap { - pub fn new() -> Self { - SortedIndexMultiMap { items: IndexVec::new(), idx_sorted_by_item_key: Vec::new() } - } - - pub fn len(&self) -> usize { - self.items.len() - } - - pub fn is_empty(&self) -> bool { - self.items.is_empty() - } - - /// Returns an iterator over the items in the map in insertion order. - pub fn into_iter(self) -> impl DoubleEndedIterator { - self.items.into_iter() - } - - /// Returns an iterator over the items in the map in insertion order along with their indices. - pub fn into_iter_enumerated(self) -> impl DoubleEndedIterator { - self.items.into_iter_enumerated() - } - - /// Returns an iterator over the items in the map in insertion order. - pub fn iter(&self) -> impl '_ + DoubleEndedIterator { - self.items.iter().map(|(ref k, ref v)| (k, v)) - } - - /// Returns an iterator over the items in the map in insertion order along with their indices. - pub fn iter_enumerated(&self) -> impl '_ + DoubleEndedIterator { - self.items.iter_enumerated().map(|(i, (ref k, ref v))| (i, (k, v))) - } - - /// Returns the item in the map with the given index. - pub fn get(&self, idx: I) -> Option<&(K, V)> { - self.items.get(idx) - } - - /// Returns an iterator over the items in the map that are equal to `key`. - /// - /// If there are multiple items that are equivalent to `key`, they will be yielded in - /// insertion order. - pub fn get_by_key(&'a self, key: &Q) -> impl 'a + Iterator - where - Q: Ord + ?Sized, - K: Borrow, - { - self.get_by_key_enumerated(key).map(|(_, v)| v) - } - - /// Returns an iterator over the items in the map that are equal to `key` along with their - /// indices. - /// - /// If there are multiple items that are equivalent to `key`, they will be yielded in - /// insertion order. - pub fn get_by_key_enumerated(&self, key: &Q) -> impl '_ + Iterator - where - Q: Ord + ?Sized, - K: Borrow, - { - // 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(&self, key: &Q) -> Result - where - Q: Ord + ?Sized, - K: Borrow, - { - 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(&self, key: &Q, initial: usize) -> usize - where - Q: Ord + ?Sized, - K: Borrow, - { - 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(&self, key: &Q, initial: usize) -> usize - where - Q: Ord + ?Sized, - K: Borrow, - { - 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 { - idxs.iter().map(move |&idx| (idx, &self.items[idx].1)) - } -} - -impl Eq for SortedIndexMultiMap {} -impl PartialEq for SortedIndexMultiMap { - fn eq(&self, other: &Self) -> bool { - // No need to compare the sorted index. If the items are the same, the index will be too. - self.items == other.items - } -} - -impl Hash for SortedIndexMultiMap -where - K: Hash, - V: Hash, -{ - fn hash(&self, hasher: &mut H) { - self.items.hash(hasher) - } -} -impl HashStable for SortedIndexMultiMap -where - K: HashStable, - V: HashStable, -{ - fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) { - self.items.hash_stable(ctx, hasher) - } -} - -impl FromIterator<(K, V)> for SortedIndexMultiMap { - fn from_iter(iter: J) -> Self - where - J: IntoIterator, - { - let items = IndexVec::from_iter(iter); - let mut idx_sorted_by_item_key: Vec<_> = items.indices().collect(); - - // `sort_by_key` is stable, so insertion order is preserved for duplicate items. - idx_sorted_by_item_key.sort_by_key(|&idx| &items[idx].0); - - SortedIndexMultiMap { items, idx_sorted_by_item_key } - } -} - -impl std::ops::Index for SortedIndexMultiMap { - type Output = V; - - fn index(&self, idx: I) -> &Self::Output { - &self.items[idx].1 - } -} - -#[cfg(tests)] -mod tests; diff --git a/vendor/rustc-ap-rustc_data_structures/src/sorted_map/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/sorted_map/tests.rs deleted file mode 100644 index 7d91e1fdce..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sorted_map/tests.rs +++ /dev/null @@ -1,222 +0,0 @@ -use super::{SortedIndexMultiMap, SortedMap}; - -#[test] -fn test_sorted_index_multi_map() { - let entries: Vec<_> = vec![(2, 0), (1, 0), (2, 1), (3, 0), (2, 2)]; - let set: SortedIndexMultiMap = entries.iter().copied().collect(); - - // Insertion order is preserved. - assert!(entries.iter().map(|(ref k, ref v)| (k, v)).eq(set.iter())); - - // Indexing - for (i, expect) in entries.iter().enumerate() { - assert_eq!(set[i], expect.1); - } - - // `get_by_key` works. - assert_eq!(set.get_by_key(&3).copied().collect::>(), 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 idxs: Vec = twos.iter().map(|(i, _)| *i).collect(); - let values: Vec = twos.iter().map(|(_, &v)| v).collect(); - - assert_eq!(idxs, vec![0, 2, 4]); - assert_eq!(values, vec![0, 1, 2]); -} - -#[test] -fn test_insert_and_iter() { - let mut map = SortedMap::new(); - let mut expected = Vec::new(); - - for x in 0..100 { - assert_eq!(map.iter().cloned().collect::>(), expected); - - let x = 1000 - x * 2; - map.insert(x, x); - expected.insert(0, (x, x)); - } -} - -#[test] -fn test_get_and_index() { - let mut map = SortedMap::new(); - let mut expected = Vec::new(); - - for x in 0..100 { - let x = 1000 - x; - if x & 1 == 0 { - map.insert(x, x); - } - expected.push(x); - } - - for mut x in expected { - if x & 1 == 0 { - assert_eq!(map.get(&x), Some(&x)); - assert_eq!(map.get_mut(&x), Some(&mut x)); - assert_eq!(map[&x], x); - assert_eq!(&mut map[&x], &mut x); - } else { - assert_eq!(map.get(&x), None); - assert_eq!(map.get_mut(&x), None); - } - } -} - -#[test] -fn test_range() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(3, 3); - map.insert(6, 6); - map.insert(9, 9); - - let keys = |s: &[(_, _)]| s.into_iter().map(|e| e.0).collect::>(); - - for start in 0..11 { - for end in 0..11 { - if end < start { - continue; - } - - let mut expected = vec![1, 3, 6, 9]; - expected.retain(|&x| x >= start && x < end); - - assert_eq!(keys(map.range(start..end)), expected, "range = {}..{}", start, end); - } - } -} - -#[test] -fn test_offset_keys() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(3, 3); - map.insert(6, 6); - - map.offset_keys(|k| *k += 1); - - let mut expected = SortedMap::new(); - expected.insert(2, 1); - expected.insert(4, 3); - expected.insert(7, 6); - - assert_eq!(map, expected); -} - -fn keys(s: SortedMap) -> Vec { - s.into_iter().map(|(k, _)| k).collect::>() -} - -fn elements(s: SortedMap) -> Vec<(u32, u32)> { - s.into_iter().collect::>() -} - -#[test] -fn test_remove_range() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(3, 3); - map.insert(6, 6); - map.insert(9, 9); - - for start in 0..11 { - for end in 0..11 { - if end < start { - continue; - } - - let mut expected = vec![1, 3, 6, 9]; - expected.retain(|&x| x < start || x >= end); - - let mut map = map.clone(); - map.remove_range(start..end); - - assert_eq!(keys(map), expected, "range = {}..{}", start, end); - } - } -} - -#[test] -fn test_remove() { - let mut map = SortedMap::new(); - let mut expected = Vec::new(); - - for x in 0..10 { - map.insert(x, x); - expected.push((x, x)); - } - - for x in 0..10 { - let mut map = map.clone(); - let mut expected = expected.clone(); - - assert_eq!(map.remove(&x), Some(x)); - expected.remove(x as usize); - - assert_eq!(map.iter().cloned().collect::>(), expected); - } -} - -#[test] -fn test_insert_presorted_non_overlapping() { - let mut map = SortedMap::new(); - map.insert(2, 0); - map.insert(8, 0); - - map.insert_presorted(vec![(3, 0), (7, 0)]); - - let expected = vec![2, 3, 7, 8]; - assert_eq!(keys(map), expected); -} - -#[test] -fn test_insert_presorted_first_elem_equal() { - let mut map = SortedMap::new(); - map.insert(2, 2); - map.insert(8, 8); - - map.insert_presorted(vec![(2, 0), (7, 7)]); - - let expected = vec![(2, 0), (7, 7), (8, 8)]; - assert_eq!(elements(map), expected); -} - -#[test] -fn test_insert_presorted_last_elem_equal() { - let mut map = SortedMap::new(); - map.insert(2, 2); - map.insert(8, 8); - - map.insert_presorted(vec![(3, 3), (8, 0)]); - - let expected = vec![(2, 2), (3, 3), (8, 0)]; - assert_eq!(elements(map), expected); -} - -#[test] -fn test_insert_presorted_shuffle() { - let mut map = SortedMap::new(); - map.insert(2, 2); - map.insert(7, 7); - - map.insert_presorted(vec![(1, 1), (3, 3), (8, 8)]); - - let expected = vec![(1, 1), (2, 2), (3, 3), (7, 7), (8, 8)]; - assert_eq!(elements(map), expected); -} - -#[test] -fn test_insert_presorted_at_end() { - let mut map = SortedMap::new(); - map.insert(1, 1); - map.insert(2, 2); - - map.insert_presorted(vec![(3, 3), (8, 8)]); - - let expected = vec![(1, 1), (2, 2), (3, 3), (8, 8)]; - assert_eq!(elements(map), expected); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sso/either_iter.rs b/vendor/rustc-ap-rustc_data_structures/src/sso/either_iter.rs deleted file mode 100644 index af8ffcf4c1..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sso/either_iter.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::fmt; -use std::iter::ExactSizeIterator; -use std::iter::FusedIterator; -use std::iter::Iterator; - -/// Iterator which may contain instance of -/// one of two specific implementations. -/// -/// Note: For most methods providing custom -/// implementation may margianlly -/// improve performance by avoiding -/// doing Left/Right match on every step -/// and doing it only once instead. -#[derive(Clone)] -pub enum EitherIter { - Left(L), - Right(R), -} - -impl Iterator for EitherIter -where - L: Iterator, - R: Iterator, -{ - type Item = L::Item; - - fn next(&mut self) -> Option { - match self { - EitherIter::Left(l) => l.next(), - EitherIter::Right(r) => r.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match self { - EitherIter::Left(l) => l.size_hint(), - EitherIter::Right(r) => r.size_hint(), - } - } -} - -impl ExactSizeIterator for EitherIter -where - L: ExactSizeIterator, - R: ExactSizeIterator, - EitherIter: Iterator, -{ - fn len(&self) -> usize { - match self { - EitherIter::Left(l) => l.len(), - EitherIter::Right(r) => r.len(), - } - } -} - -impl FusedIterator for EitherIter -where - L: FusedIterator, - R: FusedIterator, - EitherIter: Iterator, -{ -} - -impl fmt::Debug for EitherIter -where - L: fmt::Debug, - R: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - EitherIter::Left(l) => l.fmt(f), - EitherIter::Right(r) => r.fmt(f), - } - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sso/map.rs b/vendor/rustc-ap-rustc_data_structures/src/sso/map.rs deleted file mode 100644 index 06e8442d47..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sso/map.rs +++ /dev/null @@ -1,560 +0,0 @@ -use super::either_iter::EitherIter; -use crate::fx::FxHashMap; -use arrayvec::ArrayVec; -use std::fmt; -use std::hash::Hash; -use std::iter::FromIterator; -use std::ops::Index; - -// For pointer-sized arguments arrays -// are faster than set/map for up to 64 -// arguments. -// -// On the other hand such a big array -// hurts cache performance, makes passing -// sso structures around very expensive. -// -// Biggest performance benefit is gained -// for reasonably small arrays that stay -// small in vast majority of cases. -// -// '8' is choosen as a sane default, to be -// reevaluated later. -// -// Note: As of now ArrayVec design prevents -// us from making it user-customizable. -const SSO_ARRAY_SIZE: usize = 8; - -/// Small-storage-optimized implementation of a map. -/// -/// Stores elements in a small array up to a certain length -/// and switches to `HashMap` when that length is exceeded. -// -// FIXME: Implements subset of HashMap API. -// -// Missing HashMap API: -// all hasher-related -// try_reserve (unstable) -// shrink_to (unstable) -// drain_filter (unstable) -// into_keys/into_values (unstable) -// all raw_entry-related -// PartialEq/Eq (requires sorting the array) -// Entry::or_insert_with_key -// Vacant/Occupied entries and related -// -// FIXME: In HashMap most methods accepting key reference -// accept reference to generic `Q` where `K: Borrow`. -// -// However, using this approach in `HashMap::get` apparently -// breaks inlining and noticeably reduces performance. -// -// Performance *should* be the same given that borrow is -// a NOP in most cases, but in practice that's not the case. -// -// Further investigation is required. -// -// Affected methods: -// SsoHashMap::get -// SsoHashMap::get_mut -// SsoHashMap::get_entry -// SsoHashMap::get_key_value -// SsoHashMap::contains_key -// SsoHashMap::remove -// SsoHashMap::remove_entry -// Index::index -// SsoHashSet::take -// SsoHashSet::get -// SsoHashSet::remove -// SsoHashSet::contains - -#[derive(Clone)] -pub enum SsoHashMap { - Array(ArrayVec<[(K, V); SSO_ARRAY_SIZE]>), - Map(FxHashMap), -} - -impl SsoHashMap { - /// Creates an empty `SsoHashMap`. - #[inline] - pub fn new() -> Self { - SsoHashMap::Array(ArrayVec::new()) - } - - /// Creates an empty `SsoHashMap` with the specified capacity. - pub fn with_capacity(cap: usize) -> Self { - if cap <= SSO_ARRAY_SIZE { - Self::new() - } else { - SsoHashMap::Map(FxHashMap::with_capacity_and_hasher(cap, Default::default())) - } - } - - /// Clears the map, removing all key-value pairs. Keeps the allocated memory - /// for reuse. - pub fn clear(&mut self) { - match self { - SsoHashMap::Array(array) => array.clear(), - SsoHashMap::Map(map) => map.clear(), - } - } - - /// Returns the number of elements the map can hold without reallocating. - pub fn capacity(&self) -> usize { - match self { - SsoHashMap::Array(_) => SSO_ARRAY_SIZE, - SsoHashMap::Map(map) => map.capacity(), - } - } - - /// Returns the number of elements in the map. - pub fn len(&self) -> usize { - match self { - SsoHashMap::Array(array) => array.len(), - SsoHashMap::Map(map) => map.len(), - } - } - - /// Returns `true` if the map contains no elements. - pub fn is_empty(&self) -> bool { - match self { - SsoHashMap::Array(array) => array.is_empty(), - SsoHashMap::Map(map) => map.is_empty(), - } - } - - /// An iterator visiting all key-value pairs in arbitrary order. - /// The iterator element type is `(&'a K, &'a V)`. - #[inline] - pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { - self.into_iter() - } - - /// 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)`. - #[inline] - pub fn iter_mut(&mut self) -> impl Iterator { - self.into_iter() - } - - /// An iterator visiting all keys in arbitrary order. - /// The iterator element type is `&'a K`. - pub fn keys(&self) -> impl Iterator { - match self { - SsoHashMap::Array(array) => EitherIter::Left(array.iter().map(|(k, _v)| k)), - SsoHashMap::Map(map) => EitherIter::Right(map.keys()), - } - } - - /// An iterator visiting all values in arbitrary order. - /// The iterator element type is `&'a V`. - pub fn values(&self) -> impl Iterator { - match self { - SsoHashMap::Array(array) => EitherIter::Left(array.iter().map(|(_k, v)| v)), - SsoHashMap::Map(map) => EitherIter::Right(map.values()), - } - } - - /// An iterator visiting all values mutably in arbitrary order. - /// The iterator element type is `&'a mut V`. - pub fn values_mut(&mut self) -> impl Iterator { - match self { - SsoHashMap::Array(array) => EitherIter::Left(array.iter_mut().map(|(_k, v)| v)), - SsoHashMap::Map(map) => EitherIter::Right(map.values_mut()), - } - } - - /// Clears the map, returning all key-value pairs as an iterator. Keeps the - /// allocated memory for reuse. - pub fn drain(&mut self) -> impl Iterator + '_ { - match self { - SsoHashMap::Array(array) => EitherIter::Left(array.drain(..)), - SsoHashMap::Map(map) => EitherIter::Right(map.drain()), - } - } -} - -impl SsoHashMap { - /// Changes underlying storage from array to hashmap - /// if array is full. - fn migrate_if_full(&mut self) { - if let SsoHashMap::Array(array) = self { - if array.is_full() { - *self = SsoHashMap::Map(array.drain(..).collect()); - } - } - } - - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `SsoHashMap`. The collection may reserve more space to avoid - /// frequent reallocations. - pub fn reserve(&mut self, additional: usize) { - match self { - SsoHashMap::Array(array) => { - if SSO_ARRAY_SIZE < (array.len() + additional) { - let mut map: FxHashMap = array.drain(..).collect(); - map.reserve(additional); - *self = SsoHashMap::Map(map); - } - } - SsoHashMap::Map(map) => map.reserve(additional), - } - } - - /// 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. - pub fn shrink_to_fit(&mut self) { - if let SsoHashMap::Map(map) = self { - if map.len() <= SSO_ARRAY_SIZE { - *self = SsoHashMap::Array(map.drain().collect()); - } else { - map.shrink_to_fit(); - } - } - } - - /// Retains only the elements specified by the predicate. - pub fn retain(&mut self, mut f: F) - where - F: FnMut(&K, &mut V) -> bool, - { - match self { - SsoHashMap::Array(array) => array.retain(|(k, v)| f(k, v)), - SsoHashMap::Map(map) => map.retain(f), - } - } - - /// 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. - pub fn insert(&mut self, key: K, value: V) -> Option { - match self { - SsoHashMap::Array(array) => { - for (k, v) in array.iter_mut() { - if *k == key { - let old_value = std::mem::replace(v, value); - return Some(old_value); - } - } - if let Err(error) = array.try_push((key, value)) { - let mut map: FxHashMap = array.drain(..).collect(); - let (key, value) = error.element(); - map.insert(key, value); - *self = SsoHashMap::Map(map); - } - None - } - SsoHashMap::Map(map) => map.insert(key, value), - } - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - pub fn remove(&mut self, key: &K) -> Option { - match self { - SsoHashMap::Array(array) => { - if let Some(index) = array.iter().position(|(k, _v)| k == key) { - Some(array.swap_remove(index).1) - } else { - None - } - } - SsoHashMap::Map(map) => map.remove(key), - } - } - - /// Removes a key from the map, returning the stored key and value if the - /// key was previously in the map. - pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> { - match self { - SsoHashMap::Array(array) => { - if let Some(index) = array.iter().position(|(k, _v)| k == key) { - Some(array.swap_remove(index)) - } else { - None - } - } - SsoHashMap::Map(map) => map.remove_entry(key), - } - } - - /// Returns a reference to the value corresponding to the key. - pub fn get(&self, key: &K) -> Option<&V> { - match self { - SsoHashMap::Array(array) => { - for (k, v) in array { - if k == key { - return Some(v); - } - } - None - } - SsoHashMap::Map(map) => map.get(key), - } - } - - /// Returns a mutable reference to the value corresponding to the key. - pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { - match self { - SsoHashMap::Array(array) => { - for (k, v) in array { - if k == key { - return Some(v); - } - } - None - } - SsoHashMap::Map(map) => map.get_mut(key), - } - } - - /// Returns the key-value pair corresponding to the supplied key. - pub fn get_key_value(&self, key: &K) -> Option<(&K, &V)> { - match self { - SsoHashMap::Array(array) => { - for (k, v) in array { - if k == key { - return Some((k, v)); - } - } - None - } - SsoHashMap::Map(map) => map.get_key_value(key), - } - } - - /// Returns `true` if the map contains a value for the specified key. - pub fn contains_key(&self, key: &K) -> bool { - match self { - SsoHashMap::Array(array) => array.iter().any(|(k, _v)| k == key), - SsoHashMap::Map(map) => map.contains_key(key), - } - } - - /// Gets the given key's corresponding entry in the map for in-place manipulation. - #[inline] - pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { - Entry { ssomap: self, key } - } -} - -impl Default for SsoHashMap { - #[inline] - fn default() -> Self { - Self::new() - } -} - -impl FromIterator<(K, V)> for SsoHashMap { - fn from_iter>(iter: I) -> SsoHashMap { - let mut map: SsoHashMap = Default::default(); - map.extend(iter); - map - } -} - -impl Extend<(K, V)> for SsoHashMap { - fn extend(&mut self, iter: I) - where - I: IntoIterator, - { - for (key, value) in iter.into_iter() { - self.insert(key, value); - } - } - - #[inline] - fn extend_one(&mut self, (k, v): (K, V)) { - self.insert(k, v); - } - - fn extend_reserve(&mut self, additional: usize) { - match self { - SsoHashMap::Array(array) => { - if SSO_ARRAY_SIZE < (array.len() + additional) { - let mut map: FxHashMap = array.drain(..).collect(); - map.extend_reserve(additional); - *self = SsoHashMap::Map(map); - } - } - SsoHashMap::Map(map) => map.extend_reserve(additional), - } - } -} - -impl<'a, K, V> Extend<(&'a K, &'a V)> for SsoHashMap -where - K: Eq + Hash + Copy, - V: Copy, -{ - fn extend>(&mut self, iter: T) { - self.extend(iter.into_iter().map(|(k, v)| (*k, *v))) - } - - #[inline] - fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) { - self.insert(k, v); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - Extend::<(K, V)>::extend_reserve(self, additional) - } -} - -impl IntoIterator for SsoHashMap { - type IntoIter = EitherIter< - as IntoIterator>::IntoIter, - as IntoIterator>::IntoIter, - >; - type Item = ::Item; - - fn into_iter(self) -> Self::IntoIter { - match self { - SsoHashMap::Array(array) => EitherIter::Left(array.into_iter()), - SsoHashMap::Map(map) => EitherIter::Right(map.into_iter()), - } - } -} - -/// adapts Item of array reference iterator to Item of hashmap reference iterator. -#[inline(always)] -fn adapt_array_ref_it(pair: &'a (K, V)) -> (&'a K, &'a V) { - let (a, b) = pair; - (a, b) -} - -/// adapts Item of array mut reference iterator to Item of hashmap mut reference iterator. -#[inline(always)] -fn adapt_array_mut_it(pair: &'a mut (K, V)) -> (&'a K, &'a mut V) { - let (a, b) = pair; - (a, b) -} - -impl<'a, K, V> IntoIterator for &'a SsoHashMap { - type IntoIter = EitherIter< - std::iter::Map< - <&'a ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter, - fn(&'a (K, V)) -> (&'a K, &'a V), - >, - <&'a FxHashMap as IntoIterator>::IntoIter, - >; - type Item = ::Item; - - fn into_iter(self) -> Self::IntoIter { - match self { - SsoHashMap::Array(array) => EitherIter::Left(array.into_iter().map(adapt_array_ref_it)), - SsoHashMap::Map(map) => EitherIter::Right(map.iter()), - } - } -} - -impl<'a, K, V> IntoIterator for &'a mut SsoHashMap { - type IntoIter = EitherIter< - std::iter::Map< - <&'a mut ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter, - fn(&'a mut (K, V)) -> (&'a K, &'a mut V), - >, - <&'a mut FxHashMap as IntoIterator>::IntoIter, - >; - type Item = ::Item; - - fn into_iter(self) -> Self::IntoIter { - match self { - SsoHashMap::Array(array) => EitherIter::Left(array.into_iter().map(adapt_array_mut_it)), - SsoHashMap::Map(map) => EitherIter::Right(map.iter_mut()), - } - } -} - -impl fmt::Debug for SsoHashMap -where - K: fmt::Debug, - V: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_map().entries(self.iter()).finish() - } -} - -impl<'a, K, V> Index<&'a K> for SsoHashMap -where - K: Eq + Hash, -{ - type Output = V; - - #[inline] - fn index(&self, key: &K) -> &V { - self.get(key).expect("no entry found for key") - } -} - -/// A view into a single entry in a map. -pub struct Entry<'a, K, V> { - ssomap: &'a mut SsoHashMap, - key: K, -} - -impl<'a, K: Eq + Hash, V> Entry<'a, K, V> { - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - pub fn and_modify(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - if let Some(value) = self.ssomap.get_mut(&self.key) { - f(value); - } - self - } - - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - #[inline] - pub fn or_insert(self, value: V) -> &'a mut V { - self.or_insert_with(|| value) - } - - /// 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. - pub fn or_insert_with V>(self, default: F) -> &'a mut V { - self.ssomap.migrate_if_full(); - match self.ssomap { - SsoHashMap::Array(array) => { - let key_ref = &self.key; - let found_index = array.iter().position(|(k, _v)| k == key_ref); - let index = if let Some(index) = found_index { - index - } else { - let index = array.len(); - array.try_push((self.key, default())).unwrap(); - index - }; - &mut array[index].1 - } - SsoHashMap::Map(map) => map.entry(self.key).or_insert_with(default), - } - } - - /// Returns a reference to this entry's key. - #[inline] - pub fn key(&self) -> &K { - &self.key - } -} - -impl<'a, K: Eq + Hash, V: Default> Entry<'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. - #[inline] - pub fn or_default(self) -> &'a mut V { - self.or_insert_with(Default::default) - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sso/mod.rs b/vendor/rustc-ap-rustc_data_structures/src/sso/mod.rs deleted file mode 100644 index dd21bc8e69..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sso/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod either_iter; -mod map; -mod set; - -pub use map::SsoHashMap; -pub use set::SsoHashSet; diff --git a/vendor/rustc-ap-rustc_data_structures/src/sso/set.rs b/vendor/rustc-ap-rustc_data_structures/src/sso/set.rs deleted file mode 100644 index 23cff0206c..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sso/set.rs +++ /dev/null @@ -1,237 +0,0 @@ -use std::fmt; -use std::hash::Hash; -use std::iter::FromIterator; - -use super::map::SsoHashMap; - -/// Small-storage-optimized implementation of a set. -/// -/// Stores elements in a small array up to a certain length -/// and switches to `HashSet` when that length is exceeded. -// -// FIXME: Implements subset of HashSet API. -// -// Missing HashSet API: -// all hasher-related -// try_reserve (unstable) -// shrink_to (unstable) -// drain_filter (unstable) -// replace -// get_or_insert/get_or_insert_owned/get_or_insert_with (unstable) -// difference/symmetric_difference/intersection/union -// is_disjoint/is_subset/is_superset -// PartialEq/Eq (requires SsoHashMap implementation) -// BitOr/BitAnd/BitXor/Sub -#[derive(Clone)] -pub struct SsoHashSet { - map: SsoHashMap, -} - -/// Adapter function used ot return -/// result if SsoHashMap functions into -/// result SsoHashSet should return. -#[inline(always)] -fn entry_to_key((k, _v): (K, V)) -> K { - k -} - -impl SsoHashSet { - /// Creates an empty `SsoHashSet`. - #[inline] - pub fn new() -> Self { - Self { map: SsoHashMap::new() } - } - - /// Creates an empty `SsoHashSet` with the specified capacity. - #[inline] - pub fn with_capacity(cap: usize) -> Self { - Self { map: SsoHashMap::with_capacity(cap) } - } - - /// Clears the set, removing all values. - #[inline] - pub fn clear(&mut self) { - self.map.clear() - } - - /// Returns the number of elements the set can hold without reallocating. - #[inline] - pub fn capacity(&self) -> usize { - self.map.capacity() - } - - /// Returns the number of elements in the set. - #[inline] - pub fn len(&self) -> usize { - self.map.len() - } - - /// Returns `true` if the set contains no elements. - #[inline] - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - /// An iterator visiting all elements in arbitrary order. - /// The iterator element type is `&'a T`. - #[inline] - pub fn iter(&'a self) -> impl Iterator { - self.into_iter() - } - - /// Clears the set, returning all elements in an iterator. - #[inline] - pub fn drain(&mut self) -> impl Iterator + '_ { - self.map.drain().map(entry_to_key) - } -} - -impl SsoHashSet { - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `SsoHashSet`. The collection may reserve more space to avoid - /// frequent reallocations. - #[inline] - pub fn reserve(&mut self, additional: usize) { - self.map.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. - #[inline] - pub fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit() - } - - /// Retains only the elements specified by the predicate. - #[inline] - pub fn retain(&mut self, mut f: F) - where - F: FnMut(&T) -> bool, - { - self.map.retain(|k, _v| f(k)) - } - - /// Removes and returns the value in the set, if any, that is equal to the given one. - #[inline] - pub fn take(&mut self, value: &T) -> Option { - self.map.remove_entry(value).map(entry_to_key) - } - - /// Returns a reference to the value in the set, if any, that is equal to the given value. - #[inline] - pub fn get(&self, value: &T) -> Option<&T> { - self.map.get_key_value(value).map(entry_to_key) - } - - /// 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. - #[inline] - pub fn insert(&mut self, elem: T) -> bool { - self.map.insert(elem, ()).is_none() - } - - /// Removes a value from the set. Returns whether the value was - /// present in the set. - #[inline] - pub fn remove(&mut self, value: &T) -> bool { - self.map.remove(value).is_some() - } - - /// Returns `true` if the set contains a value. - #[inline] - pub fn contains(&self, value: &T) -> bool { - self.map.contains_key(value) - } -} - -impl FromIterator for SsoHashSet { - fn from_iter>(iter: I) -> SsoHashSet { - let mut set: SsoHashSet = Default::default(); - set.extend(iter); - set - } -} - -impl Default for SsoHashSet { - #[inline] - fn default() -> Self { - Self::new() - } -} - -impl Extend for SsoHashSet { - fn extend(&mut self, iter: I) - where - I: IntoIterator, - { - for val in iter.into_iter() { - self.insert(val); - } - } - - #[inline] - fn extend_one(&mut self, item: T) { - self.insert(item); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.map.extend_reserve(additional) - } -} - -impl<'a, T> Extend<&'a T> for SsoHashSet -where - T: 'a + Eq + Hash + Copy, -{ - #[inline] - fn extend>(&mut self, iter: I) { - self.extend(iter.into_iter().cloned()); - } - - #[inline] - fn extend_one(&mut self, &item: &'a T) { - self.insert(item); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - Extend::::extend_reserve(self, additional) - } -} - -impl IntoIterator for SsoHashSet { - type IntoIter = std::iter::Map< as IntoIterator>::IntoIter, fn((T, ())) -> T>; - type Item = ::Item; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.map.into_iter().map(entry_to_key) - } -} - -impl<'a, T> IntoIterator for &'a SsoHashSet { - type IntoIter = std::iter::Map< - <&'a SsoHashMap as IntoIterator>::IntoIter, - fn((&'a T, &'a ())) -> &'a T, - >; - type Item = ::Item; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.map.iter().map(entry_to_key) - } -} - -impl fmt::Debug for SsoHashSet -where - T: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_set().entries(self.iter()).finish() - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/stable_hasher.rs b/vendor/rustc-ap-rustc_data_structures/src/stable_hasher.rs deleted file mode 100644 index 3850c9b74f..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/stable_hasher.rs +++ /dev/null @@ -1,583 +0,0 @@ -use crate::sip128::SipHasher128; -use rustc_index::bit_set; -use rustc_index::vec; -use smallvec::SmallVec; -use std::hash::{BuildHasher, Hash, Hasher}; -use std::mem; - -#[cfg(test)] -mod tests; - -/// When hashing something that ends up affecting properties like symbol names, -/// we want these symbol names to be calculated independently of other factors -/// like what architecture you're compiling *from*. -/// -/// To that end we always convert integers to little-endian format before -/// hashing and the architecture dependent `isize` and `usize` types are -/// extended to 64 bits if needed. -pub struct StableHasher { - state: SipHasher128, -} - -impl ::std::fmt::Debug for StableHasher { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.state) - } -} - -pub trait StableHasherResult: Sized { - fn finish(hasher: StableHasher) -> Self; -} - -impl StableHasher { - #[inline] - pub fn new() -> Self { - StableHasher { state: SipHasher128::new_with_keys(0, 0) } - } - - pub fn finish(self) -> W { - W::finish(self) - } -} - -impl StableHasherResult for u128 { - fn finish(hasher: StableHasher) -> Self { - let (_0, _1) = hasher.finalize(); - u128::from(_0) | (u128::from(_1) << 64) - } -} - -impl StableHasherResult for u64 { - fn finish(hasher: StableHasher) -> Self { - hasher.finalize().0 - } -} - -impl StableHasher { - #[inline] - pub fn finalize(self) -> (u64, u64) { - self.state.finish128() - } -} - -impl Hasher for StableHasher { - fn finish(&self) -> u64 { - panic!("use StableHasher::finalize instead"); - } - - #[inline] - fn write(&mut self, bytes: &[u8]) { - self.state.write(bytes); - } - - #[inline] - fn write_u8(&mut self, i: u8) { - self.state.write_u8(i); - } - - #[inline] - fn write_u16(&mut self, i: u16) { - self.state.write_u16(i.to_le()); - } - - #[inline] - fn write_u32(&mut self, i: u32) { - self.state.write_u32(i.to_le()); - } - - #[inline] - fn write_u64(&mut self, i: u64) { - self.state.write_u64(i.to_le()); - } - - #[inline] - fn write_u128(&mut self, i: u128) { - self.state.write_u128(i.to_le()); - } - - #[inline] - fn write_usize(&mut self, i: usize) { - // Always treat usize as u64 so we get the same results on 32 and 64 bit - // platforms. This is important for symbol hashes when cross compiling, - // for example. - self.state.write_u64((i as u64).to_le()); - } - - #[inline] - fn write_i8(&mut self, i: i8) { - self.state.write_i8(i); - } - - #[inline] - fn write_i16(&mut self, i: i16) { - self.state.write_i16(i.to_le()); - } - - #[inline] - fn write_i32(&mut self, i: i32) { - self.state.write_i32(i.to_le()); - } - - #[inline] - fn write_i64(&mut self, i: i64) { - self.state.write_i64(i.to_le()); - } - - #[inline] - fn write_i128(&mut self, i: i128) { - self.state.write_i128(i.to_le()); - } - - #[inline] - fn write_isize(&mut self, i: isize) { - // Always treat isize as i64 so we get the same results on 32 and 64 bit - // platforms. This is important for symbol hashes when cross compiling, - // for example. Sign extending here is preferable as it means that the - // same negative number hashes the same on both 32 and 64 bit platforms. - self.state.write_i64((i as i64).to_le()); - } -} - -/// Something that implements `HashStable` can be hashed in a way that is -/// stable across multiple compilation sessions. -/// -/// Note that `HashStable` imposes rather more strict requirements than usual -/// hash functions: -/// -/// - Stable hashes are sometimes used as identifiers. Therefore they must -/// conform to the corresponding `PartialEq` implementations: -/// -/// - `x == y` implies `hash_stable(x) == hash_stable(y)`, and -/// - `x != y` implies `hash_stable(x) != hash_stable(y)`. -/// -/// That second condition is usually not required for hash functions -/// (e.g. `Hash`). In practice this means that `hash_stable` must feed any -/// information into the hasher that a `PartialEq` comparison takes into -/// account. See [#49300](https://github.com/rust-lang/rust/issues/49300) -/// for an example where violating this invariant has caused trouble in the -/// past. -/// -/// - `hash_stable()` must be independent of the current -/// compilation session. E.g. they must not hash memory addresses or other -/// things that are "randomly" assigned per compilation session. -/// -/// - `hash_stable()` must be independent of the host architecture. The -/// `StableHasher` takes care of endianness and `isize`/`usize` platform -/// differences. -pub trait HashStable { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher); -} - -/// Implement this for types that can be turned into stable keys like, for -/// example, for DefId that can be converted to a DefPathHash. This is used for -/// bringing maps into a predictable order before hashing them. -pub trait ToStableHashKey { - type KeyType: Ord + Sized + HashStable; - fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType; -} - -// Implement HashStable by just calling `Hash::hash()`. This works fine for -// self-contained values that don't depend on the hashing context `CTX`. -#[macro_export] -macro_rules! impl_stable_hash_via_hash { - ($t:ty) => { - impl $crate::stable_hasher::HashStable for $t { - #[inline] - fn hash_stable(&self, _: &mut CTX, hasher: &mut $crate::stable_hasher::StableHasher) { - ::std::hash::Hash::hash(self, hasher); - } - } - }; -} - -impl_stable_hash_via_hash!(i8); -impl_stable_hash_via_hash!(i16); -impl_stable_hash_via_hash!(i32); -impl_stable_hash_via_hash!(i64); -impl_stable_hash_via_hash!(isize); - -impl_stable_hash_via_hash!(u8); -impl_stable_hash_via_hash!(u16); -impl_stable_hash_via_hash!(u32); -impl_stable_hash_via_hash!(u64); -impl_stable_hash_via_hash!(usize); - -impl_stable_hash_via_hash!(u128); -impl_stable_hash_via_hash!(i128); - -impl_stable_hash_via_hash!(char); -impl_stable_hash_via_hash!(()); - -impl HashStable for ::std::num::NonZeroU32 { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.get().hash_stable(ctx, hasher) - } -} - -impl HashStable for ::std::num::NonZeroUsize { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.get().hash_stable(ctx, hasher) - } -} - -impl HashStable for f32 { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u32 = unsafe { ::std::mem::transmute(*self) }; - val.hash_stable(ctx, hasher); - } -} - -impl HashStable for f64 { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u64 = unsafe { ::std::mem::transmute(*self) }; - val.hash_stable(ctx, hasher); - } -} - -impl HashStable for ::std::cmp::Ordering { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (*self as i8).hash_stable(ctx, hasher); - } -} - -impl, CTX> HashStable for (T1,) { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let (ref _0,) = *self; - _0.hash_stable(ctx, hasher); - } -} - -impl, T2: HashStable, CTX> HashStable for (T1, T2) { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let (ref _0, ref _1) = *self; - _0.hash_stable(ctx, hasher); - _1.hash_stable(ctx, hasher); - } -} - -impl HashStable for (T1, T2, T3) -where - T1: HashStable, - T2: HashStable, - T3: HashStable, -{ - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let (ref _0, ref _1, ref _2) = *self; - _0.hash_stable(ctx, hasher); - _1.hash_stable(ctx, hasher); - _2.hash_stable(ctx, hasher); - } -} - -impl HashStable for (T1, T2, T3, T4) -where - T1: HashStable, - T2: HashStable, - T3: HashStable, - T4: HashStable, -{ - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let (ref _0, ref _1, ref _2, ref _3) = *self; - _0.hash_stable(ctx, hasher); - _1.hash_stable(ctx, hasher); - _2.hash_stable(ctx, hasher); - _3.hash_stable(ctx, hasher); - } -} - -impl, CTX> HashStable for [T] { - default fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.len().hash_stable(ctx, hasher); - for item in self { - item.hash_stable(ctx, hasher); - } - } -} - -impl, CTX> HashStable for Vec { - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (&self[..]).hash_stable(ctx, hasher); - } -} - -impl HashStable for indexmap::IndexMap -where - K: HashStable + Eq + Hash, - V: HashStable, - R: BuildHasher, -{ - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.len().hash_stable(ctx, hasher); - for kv in self { - kv.hash_stable(ctx, hasher); - } - } -} - -impl HashStable for indexmap::IndexSet -where - K: HashStable + Eq + Hash, - R: BuildHasher, -{ - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.len().hash_stable(ctx, hasher); - for key in self { - key.hash_stable(ctx, hasher); - } - } -} - -impl HashStable for SmallVec<[A; 1]> -where - A: HashStable, -{ - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (&self[..]).hash_stable(ctx, hasher); - } -} - -impl, CTX> HashStable for Box { - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (**self).hash_stable(ctx, hasher); - } -} - -impl, CTX> HashStable for ::std::rc::Rc { - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (**self).hash_stable(ctx, hasher); - } -} - -impl, CTX> HashStable for ::std::sync::Arc { - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (**self).hash_stable(ctx, hasher); - } -} - -impl HashStable for str { - #[inline] - fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { - self.len().hash(hasher); - self.as_bytes().hash(hasher); - } -} - -impl HashStable for String { - #[inline] - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - (&self[..]).hash_stable(hcx, hasher); - } -} - -impl ToStableHashKey for String { - type KeyType = String; - #[inline] - fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { - self.clone() - } -} - -impl HashStable for bool { - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (if *self { 1u8 } else { 0u8 }).hash_stable(ctx, hasher); - } -} - -impl HashStable for Option -where - T: HashStable, -{ - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - if let Some(ref value) = *self { - 1u8.hash_stable(ctx, hasher); - value.hash_stable(ctx, hasher); - } else { - 0u8.hash_stable(ctx, hasher); - } - } -} - -impl HashStable for Result -where - T1: HashStable, - T2: HashStable, -{ - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(ctx, hasher); - match *self { - Ok(ref x) => x.hash_stable(ctx, hasher), - Err(ref x) => x.hash_stable(ctx, hasher), - } - } -} - -impl<'a, T, CTX> HashStable for &'a T -where - T: HashStable + ?Sized, -{ - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - (**self).hash_stable(ctx, hasher); - } -} - -impl HashStable for ::std::mem::Discriminant { - #[inline] - fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { - ::std::hash::Hash::hash(self, hasher); - } -} - -impl HashStable for ::std::ops::RangeInclusive -where - T: HashStable, -{ - #[inline] - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.start().hash_stable(ctx, hasher); - self.end().hash_stable(ctx, hasher); - } -} - -impl HashStable for vec::IndexVec -where - T: HashStable, -{ - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.len().hash_stable(ctx, hasher); - for v in &self.raw { - v.hash_stable(ctx, hasher); - } - } -} - -impl HashStable for bit_set::BitSet { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.words().hash_stable(ctx, hasher); - } -} - -impl HashStable for bit_set::BitMatrix { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.words().hash_stable(ctx, hasher); - } -} - -impl HashStable for bit_set::FiniteBitSet -where - T: HashStable + bit_set::FiniteBitSetTy, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - self.0.hash_stable(hcx, hasher); - } -} - -impl_stable_hash_via_hash!(::std::path::Path); -impl_stable_hash_via_hash!(::std::path::PathBuf); - -impl HashStable for ::std::collections::HashMap -where - K: ToStableHashKey + Eq, - V: HashStable, - R: BuildHasher, -{ - #[inline] - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - hash_stable_hashmap(hcx, hasher, self, ToStableHashKey::to_stable_hash_key); - } -} - -impl HashStable for ::std::collections::HashSet -where - K: ToStableHashKey + Eq, - R: BuildHasher, -{ - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect(); - keys.sort_unstable(); - keys.hash_stable(hcx, hasher); - } -} - -impl HashStable for ::std::collections::BTreeMap -where - K: ToStableHashKey, - V: HashStable, -{ - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut entries: Vec<_> = - self.iter().map(|(k, v)| (k.to_stable_hash_key(hcx), v)).collect(); - entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2)); - entries.hash_stable(hcx, hasher); - } -} - -impl HashStable for ::std::collections::BTreeSet -where - K: ToStableHashKey, -{ - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect(); - keys.sort_unstable(); - keys.hash_stable(hcx, hasher); - } -} - -pub fn hash_stable_hashmap( - hcx: &mut HCX, - hasher: &mut StableHasher, - map: &::std::collections::HashMap, - to_stable_hash_key: F, -) where - K: Eq, - V: HashStable, - R: BuildHasher, - SK: HashStable + Ord, - F: Fn(&K, &HCX) -> SK, -{ - let mut entries: Vec<_> = map.iter().map(|(k, v)| (to_stable_hash_key(k, hcx), v)).collect(); - entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2)); - entries.hash_stable(hcx, hasher); -} - -/// A vector container that makes sure that its items are hashed in a stable -/// order. -#[derive(Debug)] -pub struct StableVec(Vec); - -impl StableVec { - pub fn new(v: Vec) -> Self { - StableVec(v) - } -} - -impl ::std::ops::Deref for StableVec { - type Target = Vec; - - fn deref(&self) -> &Vec { - &self.0 - } -} - -impl HashStable for StableVec -where - T: HashStable + ToStableHashKey, -{ - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let StableVec(ref v) = *self; - - let mut sorted: Vec<_> = v.iter().map(|x| x.to_stable_hash_key(hcx)).collect(); - sorted.sort_unstable(); - sorted.hash_stable(hcx, hasher); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/stable_hasher/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/stable_hasher/tests.rs deleted file mode 100644 index cd6ff96a55..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/stable_hasher/tests.rs +++ /dev/null @@ -1,73 +0,0 @@ -use super::*; - -// The tests below compare the computed hashes to particular expected values -// in order to test that we produce the same results on different platforms, -// regardless of endianness and `usize` and `isize` size differences (this -// of course assumes we run these tests on platforms that differ in those -// ways). The expected values depend on the hashing algorithm used, so they -// need to be updated whenever StableHasher changes its hashing algorithm. - -#[test] -fn test_hash_integers() { - // Test that integers are handled consistently across platforms. - let test_u8 = 0xAB_u8; - let test_u16 = 0xFFEE_u16; - let test_u32 = 0x445577AA_u32; - let test_u64 = 0x01234567_13243546_u64; - let test_u128 = 0x22114433_66557788_99AACCBB_EEDDFF77_u128; - let test_usize = 0xD0C0B0A0_usize; - - let test_i8 = -100_i8; - let test_i16 = -200_i16; - let test_i32 = -300_i32; - let test_i64 = -400_i64; - let test_i128 = -500_i128; - let test_isize = -600_isize; - - let mut h = StableHasher::new(); - test_u8.hash(&mut h); - test_u16.hash(&mut h); - test_u32.hash(&mut h); - test_u64.hash(&mut h); - test_u128.hash(&mut h); - test_usize.hash(&mut h); - test_i8.hash(&mut h); - test_i16.hash(&mut h); - test_i32.hash(&mut h); - test_i64.hash(&mut h); - test_i128.hash(&mut h); - test_isize.hash(&mut h); - - // This depends on the hashing algorithm. See note at top of file. - let expected = (2736651863462566372, 8121090595289675650); - - assert_eq!(h.finalize(), expected); -} - -#[test] -fn test_hash_usize() { - // Test that usize specifically is handled consistently across platforms. - let test_usize = 0xABCDEF01_usize; - - let mut h = StableHasher::new(); - test_usize.hash(&mut h); - - // This depends on the hashing algorithm. See note at top of file. - let expected = (5798740672699530587, 11186240177685111648); - - assert_eq!(h.finalize(), expected); -} - -#[test] -fn test_hash_isize() { - // Test that isize specifically is handled consistently across platforms. - let test_isize = -7_isize; - - let mut h = StableHasher::new(); - test_isize.hash(&mut h); - - // This depends on the hashing algorithm. See note at top of file. - let expected = (14721296605626097289, 11385941877786388409); - - assert_eq!(h.finalize(), expected); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/stable_map.rs b/vendor/rustc-ap-rustc_data_structures/src/stable_map.rs deleted file mode 100644 index 670452d0d8..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/stable_map.rs +++ /dev/null @@ -1,100 +0,0 @@ -pub use rustc_hash::FxHashMap; -use std::borrow::Borrow; -use std::collections::hash_map::Entry; -use std::fmt; -use std::hash::Hash; - -/// A deterministic wrapper around FxHashMap that does not provide iteration support. -/// -/// It supports insert, remove, get and get_mut functions from FxHashMap. -/// It also allows to convert hashmap to a sorted vector with the method `into_sorted_vector()`. -#[derive(Clone)] -pub struct StableMap { - base: FxHashMap, -} - -impl Default for StableMap -where - K: Eq + Hash, -{ - fn default() -> StableMap { - StableMap::new() - } -} - -impl fmt::Debug for StableMap -where - K: Eq + Hash + fmt::Debug, - V: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self.base) - } -} - -impl PartialEq for StableMap -where - K: Eq + Hash, - V: PartialEq, -{ - fn eq(&self, other: &StableMap) -> bool { - self.base == other.base - } -} - -impl Eq for StableMap -where - K: Eq + Hash, - V: Eq, -{ -} - -impl StableMap -where - K: Eq + Hash, -{ - pub fn new() -> StableMap { - StableMap { base: FxHashMap::default() } - } - - pub fn into_sorted_vector(self) -> Vec<(K, V)> - where - K: Ord + Copy, - { - let mut vector = self.base.into_iter().collect::>(); - vector.sort_unstable_by_key(|pair| pair.0); - vector - } - - pub fn entry(&mut self, k: K) -> Entry<'_, K, V> { - self.base.entry(k) - } - - pub fn get(&self, k: &Q) -> Option<&V> - where - K: Borrow, - Q: Hash + Eq, - { - self.base.get(k) - } - - pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> - where - K: Borrow, - Q: Hash + Eq, - { - self.base.get_mut(k) - } - - pub fn insert(&mut self, k: K, v: V) -> Option { - self.base.insert(k, v) - } - - pub fn remove(&mut self, k: &Q) -> Option - where - K: Borrow, - Q: Hash + Eq, - { - self.base.remove(k) - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/stable_set.rs b/vendor/rustc-ap-rustc_data_structures/src/stable_set.rs deleted file mode 100644 index c7ca74f5fb..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/stable_set.rs +++ /dev/null @@ -1,77 +0,0 @@ -pub use rustc_hash::FxHashSet; -use std::borrow::Borrow; -use std::fmt; -use std::hash::Hash; - -/// A deterministic wrapper around FxHashSet that does not provide iteration support. -/// -/// It supports insert, remove, get functions from FxHashSet. -/// It also allows to convert hashset to a sorted vector with the method `into_sorted_vector()`. -#[derive(Clone)] -pub struct StableSet { - base: FxHashSet, -} - -impl Default for StableSet -where - T: Eq + Hash, -{ - fn default() -> StableSet { - StableSet::new() - } -} - -impl fmt::Debug for StableSet -where - T: Eq + Hash + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self.base) - } -} - -impl PartialEq> for StableSet -where - T: Eq + Hash, -{ - fn eq(&self, other: &StableSet) -> bool { - self.base == other.base - } -} - -impl Eq for StableSet where T: Eq + Hash {} - -impl StableSet { - pub fn new() -> StableSet { - StableSet { base: FxHashSet::default() } - } - - pub fn into_sorted_vector(self) -> Vec - where - T: Ord, - { - let mut vector = self.base.into_iter().collect::>(); - vector.sort_unstable(); - vector - } - - pub fn get(&self, value: &Q) -> Option<&T> - where - T: Borrow, - Q: Hash + Eq, - { - self.base.get(value) - } - - pub fn insert(&mut self, value: T) -> bool { - self.base.insert(value) - } - - pub fn remove(&mut self, value: &Q) -> bool - where - T: Borrow, - Q: Hash + Eq, - { - self.base.remove(value) - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/stack.rs b/vendor/rustc-ap-rustc_data_structures/src/stack.rs deleted file mode 100644 index a4964b7aa0..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/stack.rs +++ /dev/null @@ -1,17 +0,0 @@ -// This is the amount of bytes that need to be left on the stack before increasing the size. -// It must be at least as large as the stack required by any code that does not call -// `ensure_sufficient_stack`. -const RED_ZONE: usize = 100 * 1024; // 100k - -// Only the first stack that is pushed, grows exponentially (2^n * STACK_PER_RECURSION) from then -// on. This flag has performance relevant characteristics. Don't set it too high. -const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB - -/// Grows the stack on demand to prevent stack overflow. Call this in strategic locations -/// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit -/// from this. -/// -/// Should not be sprinkled around carelessly, as it causes a little bit of overhead. -pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { - stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f) -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/steal.rs b/vendor/rustc-ap-rustc_data_structures/src/steal.rs deleted file mode 100644 index 30f659c2f7..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/steal.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::stable_hasher::{HashStable, StableHasher}; -use crate::sync::{MappedReadGuard, ReadGuard, RwLock}; - -/// The `Steal` struct is intended to used as the value for a query. -/// Specifically, we sometimes have queries (*cough* MIR *cough*) -/// where we create a large, complex value that we want to iteratively -/// update (e.g., optimize). We could clone the value for each -/// optimization, but that'd be expensive. And yet we don't just want -/// to mutate it in place, because that would spoil the idea that -/// queries are these pure functions that produce an immutable value -/// (since if you did the query twice, you could observe the mutations). -/// So instead we have the query produce a `&'tcx Steal>` -/// (to be very specific). Now we can read from this -/// as much as we want (using `borrow()`), but you can also -/// `steal()`. Once you steal, any further attempt to read will panic. -/// Therefore, we know that -- assuming no ICE -- nobody is observing -/// the fact that the MIR was updated. -/// -/// Obviously, whenever you have a query that yields a `Steal` value, -/// you must treat it with caution, and make sure that you know that -/// -- once the value is stolen -- it will never be read from again. -// -// FIXME(#41710): what is the best way to model linear queries? -#[derive(Debug)] -pub struct Steal { - value: RwLock>, -} - -impl Steal { - pub fn new(value: T) -> Self { - Steal { value: RwLock::new(Some(value)) } - } - - #[track_caller] - pub fn borrow(&self) -> MappedReadGuard<'_, T> { - ReadGuard::map(self.value.borrow(), |opt| match *opt { - None => panic!("attempted to read from stolen value"), - Some(ref v) => v, - }) - } - - #[track_caller] - pub fn steal(&self) -> T { - let value_ref = &mut *self.value.try_write().expect("stealing value which is locked"); - let value = value_ref.take(); - value.expect("attempt to steal from stolen value") - } -} - -impl> HashStable for Steal { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - self.borrow().hash_stable(hcx, hasher); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/svh.rs b/vendor/rustc-ap-rustc_data_structures/src/svh.rs deleted file mode 100644 index 02103de2e8..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/svh.rs +++ /dev/null @@ -1,69 +0,0 @@ -//! Calculation and management of a Strict Version Hash for crates -//! -//! The SVH is used for incremental compilation to track when HIR -//! nodes have changed between compilations, and also to detect -//! mismatches where we have two versions of the same crate that were -//! compiled from distinct sources. - -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use std::fmt; -use std::hash::{Hash, Hasher}; - -use crate::stable_hasher; - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct Svh { - hash: u64, -} - -impl Svh { - /// Creates a new `Svh` given the hash. If you actually want to - /// compute the SVH from some HIR, you want the `calculate_svh` - /// function found in `librustc_incremental`. - pub fn new(hash: u64) -> Svh { - Svh { hash } - } - - pub fn as_u64(&self) -> u64 { - self.hash - } - - pub fn to_string(&self) -> String { - format!("{:016x}", self.hash) - } -} - -impl Hash for Svh { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.hash.to_le().hash(state); - } -} - -impl fmt::Display for Svh { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad(&self.to_string()) - } -} - -impl Encodable for Svh { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_u64(self.as_u64().to_le()) - } -} - -impl Decodable for Svh { - fn decode(d: &mut D) -> Result { - d.read_u64().map(u64::from_le).map(Svh::new) - } -} - -impl stable_hasher::HashStable for Svh { - #[inline] - fn hash_stable(&self, ctx: &mut T, hasher: &mut stable_hasher::StableHasher) { - let Svh { hash } = *self; - hash.hash_stable(ctx, hasher); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/sync.rs b/vendor/rustc-ap-rustc_data_structures/src/sync.rs deleted file mode 100644 index 26706cd2b1..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/sync.rs +++ /dev/null @@ -1,658 +0,0 @@ -//! This module defines types which are thread safe if cfg!(parallel_compiler) is true. -//! -//! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise. -//! -//! `Lock` is a mutex. -//! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true, -//! `RefCell` otherwise. -//! -//! `RwLock` is a read-write lock. -//! It internally uses `parking_lot::RwLock` if cfg!(parallel_compiler) is true, -//! `RefCell` otherwise. -//! -//! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false. -//! -//! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise. -//! -//! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync -//! depending on the value of cfg!(parallel_compiler). - -use crate::owning_ref::{Erased, OwningRef}; -use std::collections::HashMap; -use std::hash::{BuildHasher, Hash}; -use std::ops::{Deref, DerefMut}; - -pub use std::sync::atomic::Ordering; -pub use std::sync::atomic::Ordering::SeqCst; - -cfg_if! { - if #[cfg(not(parallel_compiler))] { - pub auto trait Send {} - pub auto trait Sync {} - - impl Send for T {} - impl Sync for T {} - - #[macro_export] - macro_rules! rustc_erase_owner { - ($v:expr) => { - $v.erase_owner() - } - } - - use std::ops::Add; - use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe}; - - /// This is a single threaded variant of AtomicCell provided by crossbeam. - /// Unlike `Atomic` this is intended for all `Copy` types, - /// but it lacks the explicit ordering arguments. - #[derive(Debug)] - pub struct AtomicCell(Cell); - - impl AtomicCell { - #[inline] - pub fn new(v: T) -> Self { - AtomicCell(Cell::new(v)) - } - - #[inline] - pub fn get_mut(&mut self) -> &mut T { - self.0.get_mut() - } - } - - impl AtomicCell { - #[inline] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline] - pub fn load(&self) -> T { - self.0.get() - } - - #[inline] - pub fn store(&self, val: T) { - self.0.set(val) - } - - #[inline] - pub fn swap(&self, val: T) -> T { - self.0.replace(val) - } - } - - /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc. - /// It differs from `AtomicCell` in that it has explicit ordering arguments - /// and is only intended for use with the native atomic types. - /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases - /// as it's not intended to be used separately. - #[derive(Debug)] - pub struct Atomic(Cell); - - impl Atomic { - #[inline] - pub fn new(v: T) -> Self { - Atomic(Cell::new(v)) - } - } - - impl Atomic { - #[inline] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline] - pub fn load(&self, _: Ordering) -> T { - self.0.get() - } - - #[inline] - pub fn store(&self, val: T, _: Ordering) { - self.0.set(val) - } - - #[inline] - pub fn swap(&self, val: T, _: Ordering) -> T { - self.0.replace(val) - } - } - - impl Atomic { - #[inline] - pub fn compare_exchange(&self, - current: T, - new: T, - _: Ordering, - _: Ordering) - -> Result { - let read = self.0.get(); - if read == current { - self.0.set(new); - Ok(read) - } else { - Err(read) - } - } - } - - impl + Copy> Atomic { - #[inline] - pub fn fetch_add(&self, val: T, _: Ordering) -> T { - let old = self.0.get(); - self.0.set(old + val); - old - } - } - - pub type AtomicUsize = Atomic; - pub type AtomicBool = Atomic; - pub type AtomicU32 = Atomic; - pub type AtomicU64 = Atomic; - - pub fn join(oper_a: A, oper_b: B) -> (RA, RB) - where A: FnOnce() -> RA, - B: FnOnce() -> RB - { - (oper_a(), oper_b()) - } - - pub struct SerialScope; - - impl SerialScope { - pub fn spawn(&self, f: F) - where F: FnOnce(&SerialScope) - { - f(self) - } - } - - pub fn scope(f: F) -> R - where F: FnOnce(&SerialScope) -> R - { - f(&SerialScope) - } - - #[macro_export] - macro_rules! parallel { - ($($blocks:tt),*) => { - // We catch panics here ensuring that all the blocks execute. - // This makes behavior consistent with the parallel compiler. - let mut panic = None; - $( - if let Err(p) = ::std::panic::catch_unwind( - ::std::panic::AssertUnwindSafe(|| $blocks) - ) { - if panic.is_none() { - panic = Some(p); - } - } - )* - if let Some(panic) = panic { - ::std::panic::resume_unwind(panic); - } - } - } - - pub use std::iter::Iterator as ParallelIterator; - - pub fn par_iter(t: T) -> T::IntoIter { - t.into_iter() - } - - pub fn par_for_each_in(t: T, for_each: impl Fn(T::Item) + Sync + Send) { - // We catch panics here ensuring that all the loop iterations execute. - // This makes behavior consistent with the parallel compiler. - let mut panic = None; - t.into_iter().for_each(|i| { - if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) { - if panic.is_none() { - panic = Some(p); - } - } - }); - if let Some(panic) = panic { - resume_unwind(panic); - } - } - - pub type MetadataRef = OwningRef, [u8]>; - - pub use std::rc::Rc as Lrc; - pub use std::rc::Weak as Weak; - pub use std::cell::Ref as ReadGuard; - pub use std::cell::Ref as MappedReadGuard; - pub use std::cell::RefMut as WriteGuard; - pub use std::cell::RefMut as MappedWriteGuard; - pub use std::cell::RefMut as LockGuard; - pub use std::cell::RefMut as MappedLockGuard; - - pub use std::lazy::OnceCell; - - use std::cell::RefCell as InnerRwLock; - use std::cell::RefCell as InnerLock; - - use std::cell::Cell; - - #[derive(Debug)] - pub struct WorkerLocal(OneThread); - - impl WorkerLocal { - /// Creates a new worker local where the `initial` closure computes the - /// value this worker local should take for each thread in the thread pool. - #[inline] - pub fn new T>(mut f: F) -> WorkerLocal { - WorkerLocal(OneThread::new(f(0))) - } - - /// Returns the worker-local value for each thread - #[inline] - pub fn into_inner(self) -> Vec { - vec![OneThread::into_inner(self.0)] - } - } - - impl Deref for WorkerLocal { - type Target = T; - - #[inline(always)] - fn deref(&self) -> &T { - &*self.0 - } - } - - pub type MTRef<'a, T> = &'a mut T; - - #[derive(Debug, Default)] - pub struct MTLock(T); - - impl MTLock { - #[inline(always)] - pub fn new(inner: T) -> Self { - MTLock(inner) - } - - #[inline(always)] - pub fn into_inner(self) -> T { - self.0 - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - &mut self.0 - } - - #[inline(always)] - pub fn lock(&self) -> &T { - &self.0 - } - - #[inline(always)] - pub fn lock_mut(&mut self) -> &mut T { - &mut self.0 - } - } - - // FIXME: Probably a bad idea (in the threaded case) - impl Clone for MTLock { - #[inline] - fn clone(&self) -> Self { - MTLock(self.0.clone()) - } - } - } else { - pub use std::marker::Send as Send; - pub use std::marker::Sync as Sync; - - pub use parking_lot::RwLockReadGuard as ReadGuard; - pub use parking_lot::MappedRwLockReadGuard as MappedReadGuard; - pub use parking_lot::RwLockWriteGuard as WriteGuard; - pub use parking_lot::MappedRwLockWriteGuard as MappedWriteGuard; - - pub use parking_lot::MutexGuard as LockGuard; - pub use parking_lot::MappedMutexGuard as MappedLockGuard; - - pub use std::lazy::SyncOnceCell as OnceCell; - - pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; - - pub use crossbeam_utils::atomic::AtomicCell; - - pub use std::sync::Arc as Lrc; - pub use std::sync::Weak as Weak; - - pub type MTRef<'a, T> = &'a T; - - #[derive(Debug, Default)] - pub struct MTLock(Lock); - - impl MTLock { - #[inline(always)] - pub fn new(inner: T) -> Self { - MTLock(Lock::new(inner)) - } - - #[inline(always)] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - self.0.get_mut() - } - - #[inline(always)] - pub fn lock(&self) -> LockGuard<'_, T> { - self.0.lock() - } - - #[inline(always)] - pub fn lock_mut(&self) -> LockGuard<'_, T> { - self.lock() - } - } - - use parking_lot::Mutex as InnerLock; - use parking_lot::RwLock as InnerRwLock; - - use std::thread; - pub use rayon::{join, scope}; - - /// Runs a list of blocks in parallel. The first block is executed immediately on - /// the current thread. Use that for the longest running block. - #[macro_export] - macro_rules! parallel { - (impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => { - parallel!(impl $fblock [$block, $($c,)*] [$($rest),*]) - }; - (impl $fblock:tt [$($blocks:tt,)*] []) => { - ::rustc_data_structures::sync::scope(|s| { - $( - s.spawn(|_| $blocks); - )* - $fblock; - }) - }; - ($fblock:tt, $($blocks:tt),*) => { - // Reverse the order of the later blocks since Rayon executes them in reverse order - // when using a single thread. This ensures the execution order matches that - // of a single threaded rustc - parallel!(impl $fblock [] [$($blocks),*]); - }; - } - - pub use rayon_core::WorkerLocal; - - pub use rayon::iter::ParallelIterator; - use rayon::iter::IntoParallelIterator; - - pub fn par_iter(t: T) -> T::Iter { - t.into_par_iter() - } - - pub fn par_for_each_in( - t: T, - for_each: impl Fn(T::Item) + Sync + Send, - ) { - t.into_par_iter().for_each(for_each) - } - - pub type MetadataRef = OwningRef, [u8]>; - - /// This makes locks panic if they are already held. - /// It is only useful when you are running in a single thread - const ERROR_CHECKING: bool = false; - - #[macro_export] - macro_rules! rustc_erase_owner { - ($v:expr) => {{ - let v = $v; - ::rustc_data_structures::sync::assert_send_val(&v); - v.erase_send_sync_owner() - }} - } - } -} - -pub fn assert_sync() {} -pub fn assert_send() {} -pub fn assert_send_val(_t: &T) {} -pub fn assert_send_sync_val(_t: &T) {} - -pub trait HashMapExt { - /// Same as HashMap::insert, but it may panic if there's already an - /// entry for `key` with a value not equal to `value` - fn insert_same(&mut self, key: K, value: V); -} - -impl HashMapExt for HashMap { - fn insert_same(&mut self, key: K, value: V) { - self.entry(key).and_modify(|old| assert!(*old == value)).or_insert(value); - } -} - -#[derive(Debug)] -pub struct Lock(InnerLock); - -impl Lock { - #[inline(always)] - pub fn new(inner: T) -> Self { - Lock(InnerLock::new(inner)) - } - - #[inline(always)] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - self.0.get_mut() - } - - #[cfg(parallel_compiler)] - #[inline(always)] - pub fn try_lock(&self) -> Option> { - self.0.try_lock() - } - - #[cfg(not(parallel_compiler))] - #[inline(always)] - pub fn try_lock(&self) -> Option> { - self.0.try_borrow_mut().ok() - } - - #[cfg(parallel_compiler)] - #[inline(always)] - pub fn lock(&self) -> LockGuard<'_, T> { - if ERROR_CHECKING { - self.0.try_lock().expect("lock was already held") - } else { - self.0.lock() - } - } - - #[cfg(not(parallel_compiler))] - #[inline(always)] - pub fn lock(&self) -> LockGuard<'_, T> { - self.0.borrow_mut() - } - - #[inline(always)] - pub fn with_lock R, R>(&self, f: F) -> R { - f(&mut *self.lock()) - } - - #[inline(always)] - pub fn borrow(&self) -> LockGuard<'_, T> { - self.lock() - } - - #[inline(always)] - pub fn borrow_mut(&self) -> LockGuard<'_, T> { - self.lock() - } -} - -impl Default for Lock { - #[inline] - fn default() -> Self { - Lock::new(T::default()) - } -} - -// FIXME: Probably a bad idea -impl Clone for Lock { - #[inline] - fn clone(&self) -> Self { - Lock::new(self.borrow().clone()) - } -} - -#[derive(Debug, Default)] -pub struct RwLock(InnerRwLock); - -impl RwLock { - #[inline(always)] - pub fn new(inner: T) -> Self { - RwLock(InnerRwLock::new(inner)) - } - - #[inline(always)] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - self.0.get_mut() - } - - #[cfg(not(parallel_compiler))] - #[inline(always)] - pub fn read(&self) -> ReadGuard<'_, T> { - self.0.borrow() - } - - #[cfg(parallel_compiler)] - #[inline(always)] - pub fn read(&self) -> ReadGuard<'_, T> { - if ERROR_CHECKING { - self.0.try_read().expect("lock was already held") - } else { - self.0.read() - } - } - - #[inline(always)] - pub fn with_read_lock R, R>(&self, f: F) -> R { - f(&*self.read()) - } - - #[cfg(not(parallel_compiler))] - #[inline(always)] - pub fn try_write(&self) -> Result, ()> { - self.0.try_borrow_mut().map_err(|_| ()) - } - - #[cfg(parallel_compiler)] - #[inline(always)] - pub fn try_write(&self) -> Result, ()> { - self.0.try_write().ok_or(()) - } - - #[cfg(not(parallel_compiler))] - #[inline(always)] - pub fn write(&self) -> WriteGuard<'_, T> { - self.0.borrow_mut() - } - - #[cfg(parallel_compiler)] - #[inline(always)] - pub fn write(&self) -> WriteGuard<'_, T> { - if ERROR_CHECKING { - self.0.try_write().expect("lock was already held") - } else { - self.0.write() - } - } - - #[inline(always)] - pub fn with_write_lock R, R>(&self, f: F) -> R { - f(&mut *self.write()) - } - - #[inline(always)] - pub fn borrow(&self) -> ReadGuard<'_, T> { - self.read() - } - - #[inline(always)] - pub fn borrow_mut(&self) -> WriteGuard<'_, T> { - self.write() - } -} - -// FIXME: Probably a bad idea -impl Clone for RwLock { - #[inline] - fn clone(&self) -> Self { - RwLock::new(self.borrow().clone()) - } -} - -/// A type which only allows its inner value to be used in one thread. -/// It will panic if it is used on multiple threads. -#[derive(Debug)] -pub struct OneThread { - #[cfg(parallel_compiler)] - thread: thread::ThreadId, - inner: T, -} - -#[cfg(parallel_compiler)] -unsafe impl std::marker::Sync for OneThread {} -#[cfg(parallel_compiler)] -unsafe impl std::marker::Send for OneThread {} - -impl OneThread { - #[inline(always)] - fn check(&self) { - #[cfg(parallel_compiler)] - assert_eq!(thread::current().id(), self.thread); - } - - #[inline(always)] - pub fn new(inner: T) -> Self { - OneThread { - #[cfg(parallel_compiler)] - thread: thread::current().id(), - inner, - } - } - - #[inline(always)] - pub fn into_inner(value: Self) -> T { - value.check(); - value.inner - } -} - -impl Deref for OneThread { - type Target = T; - - fn deref(&self) -> &T { - self.check(); - &self.inner - } -} - -impl DerefMut for OneThread { - fn deref_mut(&mut self) -> &mut T { - self.check(); - &mut self.inner - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr.rs b/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr.rs deleted file mode 100644 index cd1e12ca45..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! This module implements tagged pointers. -//! -//! In order to utilize the pointer packing, you must have two types: a pointer, -//! and a tag. -//! -//! The pointer must implement the `Pointer` trait, with the primary requirement -//! being conversion to and from a usize. Note that the pointer must be -//! dereferenceable, so raw pointers generally cannot implement the `Pointer` -//! trait. This implies that the pointer must also be nonzero. -//! -//! Many common pointer types already implement the `Pointer` trait. -//! -//! The tag must implement the `Tag` trait. We assert that the tag and `Pointer` -//! are compatible at compile time. - -use std::mem::ManuallyDrop; -use std::ops::Deref; -use std::rc::Rc; -use std::sync::Arc; - -mod copy; -mod drop; - -pub use copy::CopyTaggedPtr; -pub use drop::TaggedPtr; - -/// This describes the pointer type encapsulated by TaggedPtr. -/// -/// # Safety -/// -/// The usize returned from `into_usize` must be a valid, dereferenceable, -/// pointer to `::Target`. Note that pointers to `Pointee` must -/// be thin, even though `Pointee` may not be sized. -/// -/// Note that the returned pointer from `into_usize` should be castable to `&mut -/// ::Target` if `Pointer: DerefMut`. -/// -/// The BITS constant must be correct. At least `BITS` bits, least-significant, -/// must be zero on all returned pointers from `into_usize`. -/// -/// For example, if the alignment of `Pointee` is 2, then `BITS` should be 1. -pub unsafe trait Pointer: Deref { - /// Most likely the value you want to use here is the following, unless - /// your Pointee type is unsized (e.g., `ty::List` in rustc) in which - /// case you'll need to manually figure out what the right type to pass to - /// align_of is. - /// - /// ```rust - /// std::mem::align_of::<::Target>().trailing_zeros() as usize; - /// ``` - const BITS: usize; - fn into_usize(self) -> usize; - - /// # Safety - /// - /// The passed `ptr` must be returned from `into_usize`. - /// - /// This acts as `ptr::read` semantically, it should not be called more than - /// once on non-`Copy` `Pointer`s. - unsafe fn from_usize(ptr: usize) -> Self; - - /// This provides a reference to the `Pointer` itself, rather than the - /// `Deref::Target`. It is used for cases where we want to call methods that - /// may be implement differently for the Pointer than the Pointee (e.g., - /// `Rc::clone` vs cloning the inner value). - /// - /// # Safety - /// - /// The passed `ptr` must be returned from `into_usize`. - unsafe fn with_ref R>(ptr: usize, f: F) -> R; -} - -/// This describes tags that the `TaggedPtr` struct can hold. -/// -/// # Safety -/// -/// The BITS constant must be correct. -/// -/// No more than `BITS` least significant bits may be set in the returned usize. -pub unsafe trait Tag: Copy { - const BITS: usize; - - fn into_usize(self) -> usize; - - /// # Safety - /// - /// The passed `tag` must be returned from `into_usize`. - unsafe fn from_usize(tag: usize) -> Self; -} - -unsafe impl Pointer for Box { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - fn into_usize(self) -> usize { - Box::into_raw(self) as usize - } - unsafe fn from_usize(ptr: usize) -> Self { - Box::from_raw(ptr as *mut T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - let raw = ManuallyDrop::new(Self::from_usize(ptr)); - f(&raw) - } -} - -unsafe impl Pointer for Rc { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - fn into_usize(self) -> usize { - Rc::into_raw(self) as usize - } - unsafe fn from_usize(ptr: usize) -> Self { - Rc::from_raw(ptr as *const T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - let raw = ManuallyDrop::new(Self::from_usize(ptr)); - f(&raw) - } -} - -unsafe impl Pointer for Arc { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - fn into_usize(self) -> usize { - Arc::into_raw(self) as usize - } - unsafe fn from_usize(ptr: usize) -> Self { - Arc::from_raw(ptr as *const T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - let raw = ManuallyDrop::new(Self::from_usize(ptr)); - f(&raw) - } -} - -unsafe impl<'a, T: 'a> Pointer for &'a T { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - fn into_usize(self) -> usize { - self as *const T as usize - } - unsafe fn from_usize(ptr: usize) -> Self { - &*(ptr as *const T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - f(&*(&ptr as *const usize as *const Self)) - } -} - -unsafe impl<'a, T: 'a> Pointer for &'a mut T { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - fn into_usize(self) -> usize { - self as *mut T as usize - } - unsafe fn from_usize(ptr: usize) -> Self { - &mut *(ptr as *mut T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - f(&*(&ptr as *const usize as *const Self)) - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/copy.rs b/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/copy.rs deleted file mode 100644 index d63bcdb3c2..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/copy.rs +++ /dev/null @@ -1,183 +0,0 @@ -use super::{Pointer, Tag}; -use crate::stable_hasher::{HashStable, StableHasher}; -use std::fmt; -use std::marker::PhantomData; -use std::num::NonZeroUsize; - -/// A `Copy` TaggedPtr. -/// -/// You should use this instead of the `TaggedPtr` type in all cases where -/// `P: Copy`. -/// -/// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without -/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that, -/// wrap the TaggedPtr. -pub struct CopyTaggedPtr -where - P: Pointer, - T: Tag, -{ - packed: NonZeroUsize, - data: PhantomData<(P, T)>, -} - -impl Copy for CopyTaggedPtr -where - P: Pointer, - T: Tag, - P: Copy, -{ -} - -impl Clone for CopyTaggedPtr -where - P: Pointer, - T: Tag, - P: Copy, -{ - fn clone(&self) -> Self { - *self - } -} - -// We pack the tag into the *upper* bits of the pointer to ease retrieval of the -// value; a left shift is a multiplication and those are embeddable in -// instruction encoding. -impl CopyTaggedPtr -where - P: Pointer, - T: Tag, -{ - const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS; - const ASSERTION: () = { - assert!(T::BITS <= P::BITS); - // Used for the transmute_copy's below - assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::()); - }; - - pub fn new(pointer: P, tag: T) -> Self { - // Trigger assert! - let () = Self::ASSERTION; - let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT; - - Self { - // SAFETY: We know that the pointer is non-null, as it must be - // dereferenceable per `Pointer` safety contract. - packed: unsafe { - NonZeroUsize::new_unchecked((P::into_usize(pointer) >> T::BITS) | packed_tag) - }, - data: PhantomData, - } - } - - pub(super) fn pointer_raw(&self) -> usize { - self.packed.get() << T::BITS - } - pub fn pointer(self) -> P - where - P: Copy, - { - // SAFETY: pointer_raw returns the original pointer - // - // Note that this isn't going to double-drop or anything because we have - // P: Copy - unsafe { P::from_usize(self.pointer_raw()) } - } - pub fn pointer_ref(&self) -> &P::Target { - // SAFETY: pointer_raw returns the original pointer - unsafe { std::mem::transmute_copy(&self.pointer_raw()) } - } - pub fn pointer_mut(&mut self) -> &mut P::Target - where - P: std::ops::DerefMut, - { - // SAFETY: pointer_raw returns the original pointer - unsafe { std::mem::transmute_copy(&self.pointer_raw()) } - } - pub fn tag(&self) -> T { - unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) } - } - pub fn set_tag(&mut self, tag: T) { - let mut packed = self.packed.get(); - let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT; - let tag_mask = (1 << T::BITS) - 1; - packed &= !(tag_mask << Self::TAG_BIT_SHIFT); - packed |= new_tag; - self.packed = unsafe { NonZeroUsize::new_unchecked(packed) }; - } -} - -impl std::ops::Deref for CopyTaggedPtr -where - P: Pointer, - T: Tag, -{ - type Target = P::Target; - fn deref(&self) -> &Self::Target { - self.pointer_ref() - } -} - -impl std::ops::DerefMut for CopyTaggedPtr -where - P: Pointer + std::ops::DerefMut, - T: Tag, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - self.pointer_mut() - } -} - -impl fmt::Debug for CopyTaggedPtr -where - P: Pointer, - P::Target: fmt::Debug, - T: Tag + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CopyTaggedPtr") - .field("pointer", &self.pointer_ref()) - .field("tag", &self.tag()) - .finish() - } -} - -impl PartialEq for CopyTaggedPtr -where - P: Pointer, - T: Tag, -{ - fn eq(&self, other: &Self) -> bool { - self.packed == other.packed - } -} - -impl Eq for CopyTaggedPtr -where - P: Pointer, - T: Tag, -{ -} - -impl std::hash::Hash for CopyTaggedPtr -where - P: Pointer, - T: Tag, -{ - fn hash(&self, state: &mut H) { - self.packed.hash(state); - } -} - -impl HashStable for CopyTaggedPtr -where - P: Pointer + HashStable, - T: Tag + HashStable, -{ - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - unsafe { - Pointer::with_ref(self.pointer_raw(), |p: &P| p.hash_stable(hcx, hasher)); - } - self.tag().hash_stable(hcx, hasher); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/drop.rs b/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/drop.rs deleted file mode 100644 index 63f64beae5..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/tagged_ptr/drop.rs +++ /dev/null @@ -1,142 +0,0 @@ -use super::{Pointer, Tag}; -use crate::stable_hasher::{HashStable, StableHasher}; -use std::fmt; - -use super::CopyTaggedPtr; - -/// A TaggedPtr implementing `Drop`. -/// -/// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without -/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that, -/// wrap the TaggedPtr. -pub struct TaggedPtr -where - P: Pointer, - T: Tag, -{ - raw: CopyTaggedPtr, -} - -impl Clone for TaggedPtr -where - P: Pointer + Clone, - T: Tag, -{ - fn clone(&self) -> Self { - unsafe { Self::new(P::with_ref(self.raw.pointer_raw(), |p| p.clone()), self.raw.tag()) } - } -} - -// We pack the tag into the *upper* bits of the pointer to ease retrieval of the -// value; a right shift is a multiplication and those are embeddable in -// instruction encoding. -impl TaggedPtr -where - P: Pointer, - T: Tag, -{ - pub fn new(pointer: P, tag: T) -> Self { - TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) } - } - - pub fn pointer_ref(&self) -> &P::Target { - self.raw.pointer_ref() - } - pub fn pointer_mut(&mut self) -> &mut P::Target - where - P: std::ops::DerefMut, - { - self.raw.pointer_mut() - } - pub fn tag(&self) -> T { - self.raw.tag() - } - pub fn set_tag(&mut self, tag: T) { - self.raw.set_tag(tag); - } -} - -impl std::ops::Deref for TaggedPtr -where - P: Pointer, - T: Tag, -{ - type Target = P::Target; - fn deref(&self) -> &Self::Target { - self.raw.pointer_ref() - } -} - -impl std::ops::DerefMut for TaggedPtr -where - P: Pointer + std::ops::DerefMut, - T: Tag, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - self.raw.pointer_mut() - } -} - -impl Drop for TaggedPtr -where - P: Pointer, - T: Tag, -{ - fn drop(&mut self) { - // No need to drop the tag, as it's Copy - unsafe { - std::mem::drop(P::from_usize(self.raw.pointer_raw())); - } - } -} - -impl fmt::Debug for TaggedPtr -where - P: Pointer, - P::Target: fmt::Debug, - T: Tag + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("TaggedPtr") - .field("pointer", &self.pointer_ref()) - .field("tag", &self.tag()) - .finish() - } -} - -impl PartialEq for TaggedPtr -where - P: Pointer, - T: Tag, -{ - fn eq(&self, other: &Self) -> bool { - self.raw.eq(&other.raw) - } -} - -impl Eq for TaggedPtr -where - P: Pointer, - T: Tag, -{ -} - -impl std::hash::Hash for TaggedPtr -where - P: Pointer, - T: Tag, -{ - fn hash(&self, state: &mut H) { - self.raw.hash(state); - } -} - -impl HashStable for TaggedPtr -where - P: Pointer + HashStable, - T: Tag + HashStable, -{ - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - self.raw.hash_stable(hcx, hasher); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/temp_dir.rs b/vendor/rustc-ap-rustc_data_structures/src/temp_dir.rs deleted file mode 100644 index a780d2386a..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/temp_dir.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::mem::ManuallyDrop; -use std::path::Path; -use tempfile::TempDir; - -/// This is used to avoid TempDir being dropped on error paths unintentionally. -#[derive(Debug)] -pub struct MaybeTempDir { - dir: ManuallyDrop, - // Whether the TempDir should be deleted on drop. - keep: bool, -} - -impl Drop for MaybeTempDir { - fn drop(&mut self) { - // SAFETY: We are in the destructor, and no further access will - // occur. - let dir = unsafe { ManuallyDrop::take(&mut self.dir) }; - if self.keep { - dir.into_path(); - } - } -} - -impl AsRef for MaybeTempDir { - fn as_ref(&self) -> &Path { - self.dir.path() - } -} - -impl MaybeTempDir { - pub fn new(dir: TempDir, keep_on_drop: bool) -> MaybeTempDir { - MaybeTempDir { dir: ManuallyDrop::new(dir), keep: keep_on_drop } - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/thin_vec.rs b/vendor/rustc-ap-rustc_data_structures/src/thin_vec.rs deleted file mode 100644 index 4d673fd5cf..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/thin_vec.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::stable_hasher::{HashStable, StableHasher}; - -/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). -/// The `Option>` wrapping allows us to represent a zero sized vector with `None`, -/// which uses only a single (null) pointer. -#[derive(Clone, Encodable, Decodable, Debug)] -pub struct ThinVec(Option>>); - -impl ThinVec { - pub fn new() -> Self { - ThinVec(None) - } -} - -impl From> for ThinVec { - fn from(vec: Vec) -> Self { - if vec.is_empty() { ThinVec(None) } else { ThinVec(Some(Box::new(vec))) } - } -} - -impl Into> for ThinVec { - fn into(self) -> Vec { - match self { - ThinVec(None) => Vec::new(), - ThinVec(Some(vec)) => *vec, - } - } -} - -impl ::std::ops::Deref for ThinVec { - type Target = [T]; - fn deref(&self) -> &[T] { - match *self { - ThinVec(None) => &[], - ThinVec(Some(ref vec)) => vec, - } - } -} - -impl ::std::ops::DerefMut for ThinVec { - fn deref_mut(&mut self) -> &mut [T] { - match *self { - ThinVec(None) => &mut [], - ThinVec(Some(ref mut vec)) => vec, - } - } -} - -impl Extend for ThinVec { - fn extend>(&mut self, iter: I) { - match *self { - ThinVec(Some(ref mut vec)) => vec.extend(iter), - ThinVec(None) => *self = iter.into_iter().collect::>().into(), - } - } - - fn extend_one(&mut self, item: T) { - match *self { - ThinVec(Some(ref mut vec)) => vec.push(item), - ThinVec(None) => *self = vec![item].into(), - } - } - - fn extend_reserve(&mut self, additional: usize) { - match *self { - ThinVec(Some(ref mut vec)) => vec.reserve(additional), - ThinVec(None) => *self = Vec::with_capacity(additional).into(), - } - } -} - -impl, CTX> HashStable for ThinVec { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - (**self).hash_stable(hcx, hasher) - } -} - -impl Default for ThinVec { - fn default() -> Self { - Self(None) - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/tiny_list.rs b/vendor/rustc-ap-rustc_data_structures/src/tiny_list.rs deleted file mode 100644 index e94a0c6eb5..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/tiny_list.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! A singly-linked list. -//! -//! Using this data structure only makes sense under very specific -//! circumstances: -//! -//! - If you have a list that rarely stores more than one element, then this -//! data-structure can store the element without allocating and only uses as -//! much space as a `Option<(T, usize)>`. If T can double as the `Option` -//! discriminant, it will even only be as large as `T, usize`. -//! -//! If you expect to store more than 1 element in the common case, steer clear -//! and use a `Vec`, `Box<[T]>`, or a `SmallVec`. - -#[cfg(test)] -mod tests; - -#[derive(Clone)] -pub struct TinyList { - head: Option>, -} - -impl TinyList { - #[inline] - pub fn new() -> TinyList { - TinyList { head: None } - } - - #[inline] - pub fn new_single(data: T) -> TinyList { - TinyList { head: Some(Element { data, next: None }) } - } - - #[inline] - pub fn insert(&mut self, data: T) { - self.head = Some(Element { data, next: self.head.take().map(Box::new) }); - } - - #[inline] - pub fn remove(&mut self, data: &T) -> bool { - self.head = match self.head { - Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x), - Some(ref mut head) => return head.remove_next(data), - None => return false, - }; - true - } - - #[inline] - pub fn contains(&self, data: &T) -> bool { - let mut elem = self.head.as_ref(); - while let Some(ref e) = elem { - if &e.data == data { - return true; - } - elem = e.next.as_deref(); - } - false - } - - #[inline] - pub fn len(&self) -> usize { - let (mut elem, mut count) = (self.head.as_ref(), 0); - while let Some(ref e) = elem { - count += 1; - elem = e.next.as_deref(); - } - count - } -} - -#[derive(Clone)] -struct Element { - data: T, - next: Option>>, -} - -impl Element { - fn remove_next(&mut self, data: &T) -> bool { - let mut n = self; - loop { - match n.next { - Some(ref mut next) if next.data == *data => { - n.next = next.next.take(); - return true; - } - Some(ref mut next) => n = next, - None => return false, - } - } - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/tiny_list/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/tiny_list/tests.rs deleted file mode 100644 index a8ae2bc872..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/tiny_list/tests.rs +++ /dev/null @@ -1,144 +0,0 @@ -use super::*; - -extern crate test; -use test::{black_box, Bencher}; - -#[test] -fn test_contains_and_insert() { - fn do_insert(i: u32) -> bool { - i % 2 == 0 - } - - let mut list = TinyList::new(); - - for i in 0..10 { - for j in 0..i { - if do_insert(j) { - assert!(list.contains(&j)); - } else { - assert!(!list.contains(&j)); - } - } - - assert!(!list.contains(&i)); - - if do_insert(i) { - list.insert(i); - assert!(list.contains(&i)); - } - } -} - -#[test] -fn test_remove_first() { - let mut list = TinyList::new(); - list.insert(1); - list.insert(2); - list.insert(3); - list.insert(4); - assert_eq!(list.len(), 4); - - assert!(list.remove(&4)); - assert!(!list.contains(&4)); - - assert_eq!(list.len(), 3); - assert!(list.contains(&1)); - assert!(list.contains(&2)); - assert!(list.contains(&3)); -} - -#[test] -fn test_remove_last() { - let mut list = TinyList::new(); - list.insert(1); - list.insert(2); - list.insert(3); - list.insert(4); - assert_eq!(list.len(), 4); - - assert!(list.remove(&1)); - assert!(!list.contains(&1)); - - assert_eq!(list.len(), 3); - assert!(list.contains(&2)); - assert!(list.contains(&3)); - assert!(list.contains(&4)); -} - -#[test] -fn test_remove_middle() { - let mut list = TinyList::new(); - list.insert(1); - list.insert(2); - list.insert(3); - list.insert(4); - assert_eq!(list.len(), 4); - - assert!(list.remove(&2)); - assert!(!list.contains(&2)); - - assert_eq!(list.len(), 3); - assert!(list.contains(&1)); - assert!(list.contains(&3)); - assert!(list.contains(&4)); -} - -#[test] -fn test_remove_single() { - let mut list = TinyList::new(); - list.insert(1); - assert_eq!(list.len(), 1); - - assert!(list.remove(&1)); - assert!(!list.contains(&1)); - - assert_eq!(list.len(), 0); -} - -#[bench] -fn bench_insert_empty(b: &mut Bencher) { - b.iter(|| { - let mut list = black_box(TinyList::new()); - list.insert(1); - list - }) -} - -#[bench] -fn bench_insert_one(b: &mut Bencher) { - b.iter(|| { - let mut list = black_box(TinyList::new_single(0)); - list.insert(1); - list - }) -} - -#[bench] -fn bench_contains_empty(b: &mut Bencher) { - b.iter(|| black_box(TinyList::new()).contains(&1)); -} - -#[bench] -fn bench_contains_unknown(b: &mut Bencher) { - b.iter(|| black_box(TinyList::new_single(0)).contains(&1)); -} - -#[bench] -fn bench_contains_one(b: &mut Bencher) { - b.iter(|| black_box(TinyList::new_single(1)).contains(&1)); -} - -#[bench] -fn bench_remove_empty(b: &mut Bencher) { - b.iter(|| black_box(TinyList::new()).remove(&1)); -} - -#[bench] -fn bench_remove_unknown(b: &mut Bencher) { - b.iter(|| black_box(TinyList::new_single(0)).remove(&1)); -} - -#[bench] -fn bench_remove_one(b: &mut Bencher) { - b.iter(|| black_box(TinyList::new_single(1)).remove(&1)); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/transitive_relation.rs b/vendor/rustc-ap-rustc_data_structures/src/transitive_relation.rs deleted file mode 100644 index 2e1512b392..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/transitive_relation.rs +++ /dev/null @@ -1,402 +0,0 @@ -use crate::fx::FxIndexSet; -use crate::sync::Lock; -use rustc_index::bit_set::BitMatrix; -use std::fmt::Debug; -use std::hash::Hash; -use std::mem; - -#[cfg(test)] -mod tests; - -#[derive(Clone, Debug)] -pub struct TransitiveRelation { - // List of elements. This is used to map from a T to a usize. - elements: FxIndexSet, - - // List of base edges in the graph. Require to compute transitive - // closure. - edges: Vec, - - // This is a cached transitive closure derived from the edges. - // Currently, we build it lazily and just throw out any existing - // copy whenever a new edge is added. (The Lock is to permit - // the lazy computation.) This is kind of silly, except for the - // fact its size is tied to `self.elements.len()`, so I wanted to - // wait before building it up to avoid reallocating as new edges - // are added with new elements. Perhaps better would be to ask the - // user for a batch of edges to minimize this effect, but I - // already wrote the code this way. :P -nmatsakis - closure: Lock>>, -} - -// HACK(eddyb) manual impl avoids `Default` bound on `T`. -impl Default for TransitiveRelation { - fn default() -> Self { - TransitiveRelation { - elements: Default::default(), - edges: Default::default(), - closure: Default::default(), - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)] -struct Index(usize); - -#[derive(Clone, PartialEq, Eq, Debug)] -struct Edge { - source: Index, - target: Index, -} - -impl TransitiveRelation { - pub fn is_empty(&self) -> bool { - self.edges.is_empty() - } - - pub fn elements(&self) -> impl Iterator { - self.elements.iter() - } - - fn index(&self, a: &T) -> Option { - self.elements.get_index_of(a).map(Index) - } - - fn add_index(&mut self, a: T) -> Index { - let (index, added) = self.elements.insert_full(a); - if added { - // if we changed the dimensions, clear the cache - *self.closure.get_mut() = None; - } - Index(index) - } - - /// Applies the (partial) function to each edge and returns a new - /// relation. If `f` returns `None` for any end-point, returns - /// `None`. - pub fn maybe_map(&self, mut f: F) -> Option> - where - F: FnMut(&T) -> Option, - U: Clone + Debug + Eq + Hash + Clone, - { - let mut result = TransitiveRelation::default(); - for edge in &self.edges { - result.add(f(&self.elements[edge.source.0])?, f(&self.elements[edge.target.0])?); - } - Some(result) - } - - /// Indicate that `a < b` (where `<` is this relation) - pub fn add(&mut self, a: T, b: T) { - let a = self.add_index(a); - let b = self.add_index(b); - let edge = Edge { source: a, target: b }; - if !self.edges.contains(&edge) { - self.edges.push(edge); - - // added an edge, clear the cache - *self.closure.get_mut() = None; - } - } - - /// Checks whether `a < target` (transitively) - pub fn contains(&self, a: &T, b: &T) -> bool { - match (self.index(a), self.index(b)) { - (Some(a), Some(b)) => self.with_closure(|closure| closure.contains(a.0, b.0)), - (None, _) | (_, None) => false, - } - } - - /// Thinking of `x R y` as an edge `x -> y` in a graph, this - /// returns all things reachable from `a`. - /// - /// Really this probably ought to be `impl Iterator`, but - /// I'm too lazy to make that work, and -- given the caching - /// strategy -- it'd be a touch tricky anyhow. - pub fn reachable_from(&self, a: &T) -> Vec<&T> { - match self.index(a) { - Some(a) => { - self.with_closure(|closure| closure.iter(a.0).map(|i| &self.elements[i]).collect()) - } - None => vec![], - } - } - - /// Picks what I am referring to as the "postdominating" - /// upper-bound for `a` and `b`. This is usually the least upper - /// bound, but in cases where there is no single least upper - /// bound, it is the "mutual immediate postdominator", if you - /// imagine a graph where `a < b` means `a -> b`. - /// - /// This function is needed because region inference currently - /// requires that we produce a single "UB", and there is no best - /// choice for the LUB. Rather than pick arbitrarily, I pick a - /// less good, but predictable choice. This should help ensure - /// that region inference yields predictable results (though it - /// itself is not fully sufficient). - /// - /// Examples are probably clearer than any prose I could write - /// (there are corresponding tests below, btw). In each case, - /// the query is `postdom_upper_bound(a, b)`: - /// - /// ```text - /// // Returns Some(x), which is also LUB. - /// a -> a1 -> x - /// ^ - /// | - /// b -> b1 ---+ - /// - /// // Returns `Some(x)`, which is not LUB (there is none) - /// // diagonal edges run left-to-right. - /// a -> a1 -> x - /// \/ ^ - /// /\ | - /// b -> b1 ---+ - /// - /// // Returns `None`. - /// a -> a1 - /// b -> b1 - /// ``` - pub fn postdom_upper_bound(&self, a: &T, b: &T) -> Option<&T> { - let mubs = self.minimal_upper_bounds(a, b); - self.mutual_immediate_postdominator(mubs) - } - - /// Viewing the relation as a graph, computes the "mutual - /// immediate postdominator" of a set of points (if one - /// exists). See `postdom_upper_bound` for details. - pub fn mutual_immediate_postdominator<'a>(&'a self, mut mubs: Vec<&'a T>) -> Option<&'a T> { - loop { - match mubs.len() { - 0 => return None, - 1 => return Some(mubs[0]), - _ => { - let m = mubs.pop().unwrap(); - let n = mubs.pop().unwrap(); - mubs.extend(self.minimal_upper_bounds(n, m)); - } - } - } - } - - /// Returns the set of bounds `X` such that: - /// - /// - `a < X` and `b < X` - /// - there is no `Y != X` such that `a < Y` and `Y < X` - /// - except for the case where `X < a` (i.e., a strongly connected - /// component in the graph). In that case, the smallest - /// representative of the SCC is returned (as determined by the - /// internal indices). - /// - /// Note that this set can, in principle, have any size. - pub fn minimal_upper_bounds(&self, a: &T, b: &T) -> Vec<&T> { - let (mut a, mut b) = match (self.index(a), self.index(b)) { - (Some(a), Some(b)) => (a, b), - (None, _) | (_, None) => { - return vec![]; - } - }; - - // in some cases, there are some arbitrary choices to be made; - // it doesn't really matter what we pick, as long as we pick - // the same thing consistently when queried, so ensure that - // (a, b) are in a consistent relative order - if a > b { - mem::swap(&mut a, &mut b); - } - - let lub_indices = self.with_closure(|closure| { - // Easy case is when either a < b or b < a: - if closure.contains(a.0, b.0) { - return vec![b.0]; - } - if closure.contains(b.0, a.0) { - return vec![a.0]; - } - - // Otherwise, the tricky part is that there may be some c - // where a < c and b < c. In fact, there may be many such - // values. So here is what we do: - // - // 1. Find the vector `[X | a < X && b < X]` of all values - // `X` where `a < X` and `b < X`. In terms of the - // graph, this means all values reachable from both `a` - // and `b`. Note that this vector is also a set, but we - // use the term vector because the order matters - // to the steps below. - // - This vector contains upper bounds, but they are - // not minimal upper bounds. So you may have e.g. - // `[x, y, tcx, z]` where `x < tcx` and `y < tcx` and - // `z < x` and `z < y`: - // - // z --+---> x ----+----> tcx - // | | - // | | - // +---> y ----+ - // - // In this case, we really want to return just `[z]`. - // The following steps below achieve this by gradually - // reducing the list. - // 2. Pare down the vector using `pare_down`. This will - // remove elements from the vector that can be reached - // by an earlier element. - // - In the example above, this would convert `[x, y, - // tcx, z]` to `[x, y, z]`. Note that `x` and `y` are - // still in the vector; this is because while `z < x` - // (and `z < y`) holds, `z` comes after them in the - // vector. - // 3. Reverse the vector and repeat the pare down process. - // - In the example above, we would reverse to - // `[z, y, x]` and then pare down to `[z]`. - // 4. Reverse once more just so that we yield a vector in - // increasing order of index. Not necessary, but why not. - // - // I believe this algorithm yields a minimal set. The - // argument is that, after step 2, we know that no element - // can reach its successors (in the vector, not the graph). - // After step 3, we know that no element can reach any of - // its predecessors (because of step 2) nor successors - // (because we just called `pare_down`) - // - // This same algorithm is used in `parents` below. - - let mut candidates = closure.intersect_rows(a.0, b.0); // (1) - pare_down(&mut candidates, closure); // (2) - candidates.reverse(); // (3a) - pare_down(&mut candidates, closure); // (3b) - candidates - }); - - lub_indices - .into_iter() - .rev() // (4) - .map(|i| &self.elements[i]) - .collect() - } - - /// Given an element A, returns the maximal set {B} of elements B - /// such that - /// - /// - A != B - /// - A R B is true - /// - for each i, j: `B[i]` R `B[j]` does not hold - /// - /// The intuition is that this moves "one step up" through a lattice - /// (where the relation is encoding the `<=` relation for the lattice). - /// So e.g., if the relation is `->` and we have - /// - /// ``` - /// a -> b -> d -> f - /// | ^ - /// +--> c -> e ---+ - /// ``` - /// - /// then `parents(a)` returns `[b, c]`. The `postdom_parent` function - /// would further reduce this to just `f`. - pub fn parents(&self, a: &T) -> Vec<&T> { - let a = match self.index(a) { - Some(a) => a, - None => return vec![], - }; - - // Steal the algorithm for `minimal_upper_bounds` above, but - // with a slight tweak. In the case where `a R a`, we remove - // that from the set of candidates. - let ancestors = self.with_closure(|closure| { - let mut ancestors = closure.intersect_rows(a.0, a.0); - - // Remove anything that can reach `a`. If this is a - // reflexive relation, this will include `a` itself. - ancestors.retain(|&e| !closure.contains(e, a.0)); - - pare_down(&mut ancestors, closure); // (2) - ancestors.reverse(); // (3a) - pare_down(&mut ancestors, closure); // (3b) - ancestors - }); - - ancestors - .into_iter() - .rev() // (4) - .map(|i| &self.elements[i]) - .collect() - } - - /// A "best" parent in some sense. See `parents` and - /// `postdom_upper_bound` for more details. - pub fn postdom_parent(&self, a: &T) -> Option<&T> { - self.mutual_immediate_postdominator(self.parents(a)) - } - - fn with_closure(&self, op: OP) -> R - where - OP: FnOnce(&BitMatrix) -> R, - { - let mut closure_cell = self.closure.borrow_mut(); - let mut closure = closure_cell.take(); - if closure.is_none() { - closure = Some(self.compute_closure()); - } - let result = op(closure.as_ref().unwrap()); - *closure_cell = closure; - result - } - - fn compute_closure(&self) -> BitMatrix { - let mut matrix = BitMatrix::new(self.elements.len(), self.elements.len()); - let mut changed = true; - while changed { - changed = false; - for edge in &self.edges { - // add an edge from S -> T - changed |= matrix.insert(edge.source.0, edge.target.0); - - // add all outgoing edges from T into S - changed |= matrix.union_rows(edge.target.0, edge.source.0); - } - } - matrix - } - - /// Lists all the base edges in the graph: the initial _non-transitive_ set of element - /// relations, which will be later used as the basis for the transitive closure computation. - pub fn base_edges(&self) -> impl Iterator { - self.edges - .iter() - .map(move |edge| (&self.elements[edge.source.0], &self.elements[edge.target.0])) - } -} - -/// Pare down is used as a step in the LUB computation. It edits the -/// candidates array in place by removing any element j for which -/// there exists an earlier element i j. That is, -/// after you run `pare_down`, you know that for all elements that -/// remain in candidates, they cannot reach any of the elements that -/// come after them. -/// -/// Examples follow. Assume that a -> b -> c and x -> y -> z. -/// -/// - Input: `[a, b, x]`. Output: `[a, x]`. -/// - Input: `[b, a, x]`. Output: `[b, a, x]`. -/// - Input: `[a, x, b, y]`. Output: `[a, x]`. -fn pare_down(candidates: &mut Vec, closure: &BitMatrix) { - let mut i = 0; - while let Some(&candidate_i) = candidates.get(i) { - i += 1; - - let mut j = i; - let mut dead = 0; - while let Some(&candidate_j) = candidates.get(j) { - if closure.contains(candidate_i, candidate_j) { - // If `i` can reach `j`, then we can remove `j`. So just - // mark it as dead and move on; subsequent indices will be - // shifted into its place. - dead += 1; - } else { - candidates[j - dead] = candidate_j; - } - j += 1; - } - candidates.truncate(j - dead); - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/transitive_relation/tests.rs b/vendor/rustc-ap-rustc_data_structures/src/transitive_relation/tests.rs deleted file mode 100644 index ca90ba176a..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/transitive_relation/tests.rs +++ /dev/null @@ -1,354 +0,0 @@ -use super::*; - -#[test] -fn test_one_step() { - let mut relation = TransitiveRelation::default(); - relation.add("a", "b"); - relation.add("a", "c"); - assert!(relation.contains(&"a", &"c")); - assert!(relation.contains(&"a", &"b")); - assert!(!relation.contains(&"b", &"a")); - assert!(!relation.contains(&"a", &"d")); -} - -#[test] -fn test_many_steps() { - let mut relation = TransitiveRelation::default(); - relation.add("a", "b"); - relation.add("a", "c"); - relation.add("a", "f"); - - relation.add("b", "c"); - relation.add("b", "d"); - relation.add("b", "e"); - - relation.add("e", "g"); - - assert!(relation.contains(&"a", &"b")); - assert!(relation.contains(&"a", &"c")); - assert!(relation.contains(&"a", &"d")); - assert!(relation.contains(&"a", &"e")); - assert!(relation.contains(&"a", &"f")); - assert!(relation.contains(&"a", &"g")); - - assert!(relation.contains(&"b", &"g")); - - assert!(!relation.contains(&"a", &"x")); - assert!(!relation.contains(&"b", &"f")); -} - -#[test] -fn mubs_triangle() { - // a -> tcx - // ^ - // | - // b - let mut relation = TransitiveRelation::default(); - relation.add("a", "tcx"); - relation.add("b", "tcx"); - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"tcx"]); - assert_eq!(relation.parents(&"a"), vec![&"tcx"]); - assert_eq!(relation.parents(&"b"), vec![&"tcx"]); -} - -#[test] -fn mubs_best_choice1() { - // 0 -> 1 <- 3 - // | ^ | - // | | | - // +--> 2 <--+ - // - // mubs(0,3) = [1] - - // This tests a particular state in the algorithm, in which we - // need the second pare down call to get the right result (after - // intersection, we have [1, 2], but 2 -> 1). - - let mut relation = TransitiveRelation::default(); - relation.add("0", "1"); - relation.add("0", "2"); - - relation.add("2", "1"); - - relation.add("3", "1"); - relation.add("3", "2"); - - assert_eq!(relation.minimal_upper_bounds(&"0", &"3"), vec![&"2"]); - assert_eq!(relation.parents(&"0"), vec![&"2"]); - assert_eq!(relation.parents(&"2"), vec![&"1"]); - assert!(relation.parents(&"1").is_empty()); -} - -#[test] -fn mubs_best_choice2() { - // 0 -> 1 <- 3 - // | | | - // | v | - // +--> 2 <--+ - // - // mubs(0,3) = [2] - - // Like the precedecing test, but in this case intersection is [2, - // 1], and hence we rely on the first pare down call. - - let mut relation = TransitiveRelation::default(); - relation.add("0", "1"); - relation.add("0", "2"); - - relation.add("1", "2"); - - relation.add("3", "1"); - relation.add("3", "2"); - - assert_eq!(relation.minimal_upper_bounds(&"0", &"3"), vec![&"1"]); - assert_eq!(relation.parents(&"0"), vec![&"1"]); - assert_eq!(relation.parents(&"1"), vec![&"2"]); - assert!(relation.parents(&"2").is_empty()); -} - -#[test] -fn mubs_no_best_choice() { - // in this case, the intersection yields [1, 2], and the "pare - // down" calls find nothing to remove. - let mut relation = TransitiveRelation::default(); - relation.add("0", "1"); - relation.add("0", "2"); - - relation.add("3", "1"); - relation.add("3", "2"); - - assert_eq!(relation.minimal_upper_bounds(&"0", &"3"), vec![&"1", &"2"]); - assert_eq!(relation.parents(&"0"), vec![&"1", &"2"]); - assert_eq!(relation.parents(&"3"), vec![&"1", &"2"]); -} - -#[test] -fn mubs_best_choice_scc() { - // in this case, 1 and 2 form a cycle; we pick arbitrarily (but - // consistently). - - let mut relation = TransitiveRelation::default(); - relation.add("0", "1"); - relation.add("0", "2"); - - relation.add("1", "2"); - relation.add("2", "1"); - - relation.add("3", "1"); - relation.add("3", "2"); - - assert_eq!(relation.minimal_upper_bounds(&"0", &"3"), vec![&"1"]); - assert_eq!(relation.parents(&"0"), vec![&"1"]); -} - -#[test] -fn pdub_crisscross() { - // diagonal edges run left-to-right - // a -> a1 -> x - // \/ ^ - // /\ | - // b -> b1 ---+ - - let mut relation = TransitiveRelation::default(); - relation.add("a", "a1"); - relation.add("a", "b1"); - relation.add("b", "a1"); - relation.add("b", "b1"); - relation.add("a1", "x"); - relation.add("b1", "x"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"a1", &"b1"]); - assert_eq!(relation.postdom_upper_bound(&"a", &"b"), Some(&"x")); - assert_eq!(relation.postdom_parent(&"a"), Some(&"x")); - assert_eq!(relation.postdom_parent(&"b"), Some(&"x")); -} - -#[test] -fn pdub_crisscross_more() { - // diagonal edges run left-to-right - // a -> a1 -> a2 -> a3 -> x - // \/ \/ ^ - // /\ /\ | - // b -> b1 -> b2 ---------+ - - let mut relation = TransitiveRelation::default(); - relation.add("a", "a1"); - relation.add("a", "b1"); - relation.add("b", "a1"); - relation.add("b", "b1"); - - relation.add("a1", "a2"); - relation.add("a1", "b2"); - relation.add("b1", "a2"); - relation.add("b1", "b2"); - - relation.add("a2", "a3"); - - relation.add("a3", "x"); - relation.add("b2", "x"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"a1", &"b1"]); - assert_eq!(relation.minimal_upper_bounds(&"a1", &"b1"), vec![&"a2", &"b2"]); - assert_eq!(relation.postdom_upper_bound(&"a", &"b"), Some(&"x")); - - assert_eq!(relation.postdom_parent(&"a"), Some(&"x")); - assert_eq!(relation.postdom_parent(&"b"), Some(&"x")); -} - -#[test] -fn pdub_lub() { - // a -> a1 -> x - // ^ - // | - // b -> b1 ---+ - - let mut relation = TransitiveRelation::default(); - relation.add("a", "a1"); - relation.add("b", "b1"); - relation.add("a1", "x"); - relation.add("b1", "x"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"x"]); - assert_eq!(relation.postdom_upper_bound(&"a", &"b"), Some(&"x")); - - assert_eq!(relation.postdom_parent(&"a"), Some(&"a1")); - assert_eq!(relation.postdom_parent(&"b"), Some(&"b1")); - assert_eq!(relation.postdom_parent(&"a1"), Some(&"x")); - assert_eq!(relation.postdom_parent(&"b1"), Some(&"x")); -} - -#[test] -fn mubs_intermediate_node_on_one_side_only() { - // a -> c -> d - // ^ - // | - // b - - // "digraph { a -> c -> d; b -> d; }", - let mut relation = TransitiveRelation::default(); - relation.add("a", "c"); - relation.add("c", "d"); - relation.add("b", "d"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"d"]); -} - -#[test] -fn mubs_scc_1() { - // +-------------+ - // | +----+ | - // | v | | - // a -> c -> d <-+ - // ^ - // | - // b - - // "digraph { a -> c -> d; d -> c; a -> d; b -> d; }", - let mut relation = TransitiveRelation::default(); - relation.add("a", "c"); - relation.add("c", "d"); - relation.add("d", "c"); - relation.add("a", "d"); - relation.add("b", "d"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); -} - -#[test] -fn mubs_scc_2() { - // +----+ - // v | - // a -> c -> d - // ^ ^ - // | | - // +--- b - - // "digraph { a -> c -> d; d -> c; b -> d; b -> c; }", - let mut relation = TransitiveRelation::default(); - relation.add("a", "c"); - relation.add("c", "d"); - relation.add("d", "c"); - relation.add("b", "d"); - relation.add("b", "c"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); -} - -#[test] -fn mubs_scc_3() { - // +---------+ - // v | - // a -> c -> d -> e - // ^ ^ - // | | - // b ---+ - - // "digraph { a -> c -> d -> e -> c; b -> d; b -> e; }", - let mut relation = TransitiveRelation::default(); - relation.add("a", "c"); - relation.add("c", "d"); - relation.add("d", "e"); - relation.add("e", "c"); - relation.add("b", "d"); - relation.add("b", "e"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); -} - -#[test] -fn mubs_scc_4() { - // +---------+ - // v | - // a -> c -> d -> e - // | ^ ^ - // +---------+ | - // | - // b ---+ - - // "digraph { a -> c -> d -> e -> c; a -> d; b -> e; }" - let mut relation = TransitiveRelation::default(); - relation.add("a", "c"); - relation.add("c", "d"); - relation.add("d", "e"); - relation.add("e", "c"); - relation.add("a", "d"); - relation.add("b", "e"); - - assert_eq!(relation.minimal_upper_bounds(&"a", &"b"), vec![&"c"]); -} - -#[test] -fn parent() { - // An example that was misbehaving in the compiler. - // - // 4 -> 1 -> 3 - // \ | / - // \ v / - // 2 -> 0 - // - // plus a bunch of self-loops - // - // Here `->` represents `<=` and `0` is `'static`. - - let pairs = vec![ - (2, /*->*/ 0), - (2, /*->*/ 2), - (0, /*->*/ 0), - (0, /*->*/ 0), - (1, /*->*/ 0), - (1, /*->*/ 1), - (3, /*->*/ 0), - (3, /*->*/ 3), - (4, /*->*/ 0), - (4, /*->*/ 1), - (1, /*->*/ 3), - ]; - - let mut relation = TransitiveRelation::default(); - for (a, b) in pairs { - relation.add(a, b); - } - - let p = relation.postdom_parent(&3); - assert_eq!(p, Some(&0)); -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/unhash.rs b/vendor/rustc-ap-rustc_data_structures/src/unhash.rs deleted file mode 100644 index 48e21a9dab..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/unhash.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::hash::{BuildHasherDefault, Hasher}; - -pub type UnhashMap = HashMap>; -pub type UnhashSet = HashSet>; - -/// This no-op hasher expects only a single `write_u64` call. It's intended for -/// map keys that already have hash-like quality, like `Fingerprint`. -#[derive(Default)] -pub struct Unhasher { - value: u64, -} - -impl Hasher for Unhasher { - #[inline] - fn finish(&self) -> u64 { - self.value - } - - fn write(&mut self, _bytes: &[u8]) { - unimplemented!("use write_u64"); - } - - #[inline] - fn write_u64(&mut self, value: u64) { - debug_assert_eq!(0, self.value, "Unhasher doesn't mix values!"); - self.value = value; - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/vec_linked_list.rs b/vendor/rustc-ap-rustc_data_structures/src/vec_linked_list.rs deleted file mode 100644 index 1cf030d852..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/vec_linked_list.rs +++ /dev/null @@ -1,70 +0,0 @@ -use rustc_index::vec::{Idx, IndexVec}; - -pub fn iter( - first: Option, - links: &'a Ls, -) -> impl Iterator + 'a -where - Ls: Links, -{ - VecLinkedListIterator { links, current: first } -} - -pub struct VecLinkedListIterator -where - Ls: Links, -{ - links: Ls, - current: Option, -} - -impl Iterator for VecLinkedListIterator -where - Ls: Links, -{ - type Item = Ls::LinkIndex; - - fn next(&mut self) -> Option { - if let Some(c) = self.current { - self.current = ::next(&self.links, c); - Some(c) - } else { - None - } - } -} - -pub trait Links { - type LinkIndex: Copy; - - fn next(links: &Self, index: Self::LinkIndex) -> Option; -} - -impl Links for &Ls -where - Ls: Links, -{ - type LinkIndex = Ls::LinkIndex; - - fn next(links: &Self, index: Ls::LinkIndex) -> Option { - ::next(links, index) - } -} - -pub trait LinkElem { - type LinkIndex: Copy; - - fn next(elem: &Self) -> Option; -} - -impl Links for IndexVec -where - E: LinkElem, - L: Idx, -{ - type LinkIndex = L; - - fn next(links: &Self, index: L) -> Option { - ::next(&links[index]) - } -} diff --git a/vendor/rustc-ap-rustc_data_structures/src/work_queue.rs b/vendor/rustc-ap-rustc_data_structures/src/work_queue.rs deleted file mode 100644 index cc562bc1e4..0000000000 --- a/vendor/rustc-ap-rustc_data_structures/src/work_queue.rs +++ /dev/null @@ -1,50 +0,0 @@ -use rustc_index::bit_set::BitSet; -use rustc_index::vec::Idx; -use std::collections::VecDeque; - -/// A work queue is a handy data structure for tracking work left to -/// do. (For example, basic blocks left to process.) It is basically a -/// de-duplicating queue; so attempting to insert X if X is already -/// enqueued has no effect. This implementation assumes that the -/// elements are dense indices, so it can allocate the queue to size -/// and also use a bit set to track occupancy. -pub struct WorkQueue { - deque: VecDeque, - set: BitSet, -} - -impl WorkQueue { - /// Creates a new work queue that starts empty, where elements range from (0..len). - #[inline] - pub fn with_none(len: usize) -> Self { - WorkQueue { deque: VecDeque::with_capacity(len), set: BitSet::new_empty(len) } - } - - /// Attempt to enqueue `element` in the work queue. Returns false if it was already present. - #[inline] - pub fn insert(&mut self, element: T) -> bool { - if self.set.insert(element) { - self.deque.push_back(element); - true - } else { - false - } - } - - /// Attempt to pop an element from the work queue. - #[inline] - pub fn pop(&mut self) -> Option { - if let Some(element) = self.deque.pop_front() { - self.set.remove(element); - Some(element) - } else { - None - } - } - - /// Returns `true` if nothing is enqueued. - #[inline] - pub fn is_empty(&self) -> bool { - self.deque.is_empty() - } -} diff --git a/vendor/rustc-ap-rustc_errors/.cargo-checksum.json b/vendor/rustc-ap-rustc_errors/.cargo-checksum.json deleted file mode 100644 index 93e35964fb..0000000000 --- a/vendor/rustc-ap-rustc_errors/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"417db01ac0ed2fa19f58c31c8404c9ca2632b6796971279dd1c21cdc6f1abaf0","src/annotate_snippet_emitter_writer.rs":"e810e96a9569771f98a0079702f42cbfb5244b717637131624788852d0b5b468","src/diagnostic.rs":"e3332fb9e441fa87f17b255290370df2b53866e1d48e88a4cd175002713cb9e3","src/diagnostic_builder.rs":"6e4ec25ff27e36479b255fc7de5928f04a7cddb5062a50e8a5460f24ade51a1f","src/emitter.rs":"23c8c5bb45d3fd7505ae7e374de4331a16624d5e3a259e499bc81afed1dd0b14","src/json.rs":"3a2325cf143e2a7eaf7ede74dc17290f44d1011c5f1a5655322e6a2fde3d4b83","src/json/tests.rs":"6a5117514ecdd5d4f1d7ff9fcc7ada8567a27706cbc46e29b82b3ce788e86f6e","src/lib.rs":"75e0bee7b43b7b9e26750cb70bd2144d3ee12d476343e2f52bea91ec5fd191e6","src/lock.rs":"d32dea5da13c3a19a6b1c5b41d467d99b807db2e4a027e2164a16e823c99ae64","src/registry.rs":"00d756139daa45c9bff3af0ff3e82ec71fe98f3d07dc3e26032770a917c25175","src/snippet.rs":"ddb98a98624aad8513eb9cb83793882217187245e4f3a761cb5c3e77c604cd06","src/styled_buffer.rs":"e7336836011ec6102445f799aa11b5181c54aa34e7acae5205fef7f91e3c4e40"},"package":"2f2f99bdc828ad417636d9016611dc9047b641fadcb7f533b8b0e9616d81f90b"} \ No newline at end of file diff --git a/vendor/rustc-ap-rustc_errors/Cargo.toml b/vendor/rustc-ap-rustc_errors/Cargo.toml deleted file mode 100644 index 0193133a6a..0000000000 --- a/vendor/rustc-ap-rustc_errors/Cargo.toml +++ /dev/null @@ -1,63 +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 = "rustc-ap-rustc_errors" -version = "705.0.0" -authors = ["The Rust Project Developers"] -description = "Automatically published version of the package `rustc_errors` in the rust-lang/rust repository from commit 37d067f5d71331d909102d142ecc50f577e07ae4 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n " -license = "MIT / Apache-2.0" -repository = "https://github.com/rust-lang/rust" - -[lib] -doctest = false -[dependencies.annotate-snippets] -version = "0.8.0" - -[dependencies.atty] -version = "0.2" - -[dependencies.rustc_data_structures] -version = "705.0.0" -package = "rustc-ap-rustc_data_structures" - -[dependencies.rustc_lint_defs] -version = "705.0.0" -package = "rustc-ap-rustc_lint_defs" - -[dependencies.rustc_macros] -version = "705.0.0" -package = "rustc-ap-rustc_macros" - -[dependencies.rustc_serialize] -version = "705.0.0" -package = "rustc-ap-rustc_serialize" - -[dependencies.rustc_span] -version = "705.0.0" -package = "rustc-ap-rustc_span" - -[dependencies.termcolor] -version = "1.0" - -[dependencies.termize] -version = "0.1.1" - -[dependencies.tracing] -version = "0.1" - -[dependencies.unicode-width] -version = "0.1.4" -[target."cfg(windows)".dependencies.winapi] -version = "0.3" -features = ["handleapi", "synchapi", "winbase"] diff --git a/vendor/rustc-ap-rustc_errors/src/annotate_snippet_emitter_writer.rs b/vendor/rustc-ap-rustc_errors/src/annotate_snippet_emitter_writer.rs deleted file mode 100644 index 6f365c07f6..0000000000 --- a/vendor/rustc-ap-rustc_errors/src/annotate_snippet_emitter_writer.rs +++ /dev/null @@ -1,182 +0,0 @@ -//! Emit diagnostics using the `annotate-snippets` library -//! -//! This is the equivalent of `./emitter.rs` but making use of the -//! [`annotate-snippets`][annotate_snippets] library instead of building the output ourselves. -//! -//! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/ - -use crate::emitter::FileWithAnnotatedLines; -use crate::snippet::Line; -use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Emitter, Level, SubDiagnostic}; -use annotate_snippets::display_list::{DisplayList, FormatOptions}; -use annotate_snippets::snippet::*; -use rustc_data_structures::sync::Lrc; -use rustc_span::source_map::SourceMap; -use rustc_span::{MultiSpan, SourceFile}; - -/// Generates diagnostics using annotate-snippet -pub struct AnnotateSnippetEmitterWriter { - source_map: Option>, - /// If true, hides the longer explanation text - short_message: bool, - /// If true, will normalize line numbers with `LL` to prevent noise in UI test diffs. - ui_testing: bool, - - macro_backtrace: bool, -} - -impl Emitter for AnnotateSnippetEmitterWriter { - /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, diag: &Diagnostic) { - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); - - self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.source_map, - &mut primary_span, - &mut children, - &diag.level, - self.macro_backtrace, - ); - - self.emit_messages_default( - &diag.level, - diag.message(), - &diag.code, - &primary_span, - &children, - &suggestions, - ); - } - - fn source_map(&self) -> Option<&Lrc> { - self.source_map.as_ref() - } - - fn should_show_explain(&self) -> bool { - !self.short_message - } -} - -/// Provides the source string for the given `line` of `file` -fn source_string(file: Lrc, line: &Line) -> String { - file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default() -} - -/// Maps `Diagnostic::Level` to `snippet::AnnotationType` -fn annotation_type_for_level(level: Level) -> AnnotationType { - match level { - Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error, - Level::Warning => AnnotationType::Warning, - Level::Note => AnnotationType::Note, - Level::Help => AnnotationType::Help, - // FIXME(#59346): Not sure how to map these two levels - Level::Cancelled | Level::FailureNote => AnnotationType::Error, - Level::Allow => panic!("Should not call with Allow"), - } -} - -impl AnnotateSnippetEmitterWriter { - pub fn new( - source_map: Option>, - short_message: bool, - macro_backtrace: bool, - ) -> Self { - Self { source_map, short_message, ui_testing: false, macro_backtrace } - } - - /// Allows to modify `Self` to enable or disable the `ui_testing` flag. - /// - /// If this is set to true, line numbers will be normalized as `LL` in the output. - pub fn ui_testing(mut self, ui_testing: bool) -> Self { - self.ui_testing = ui_testing; - self - } - - fn emit_messages_default( - &mut self, - level: &Level, - message: String, - code: &Option, - msp: &MultiSpan, - _children: &[SubDiagnostic], - _suggestions: &[CodeSuggestion], - ) { - if let Some(source_map) = &self.source_map { - // Make sure our primary file comes first - let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() { - if primary_span.is_dummy() { - // FIXME(#59346): Not sure when this is the case and what - // should be done if it happens - return; - } else { - source_map.lookup_char_pos(primary_span.lo()) - } - } else { - // FIXME(#59346): Not sure when this is the case and what - // should be done if it happens - return; - }; - let mut annotated_files = - FileWithAnnotatedLines::collect_annotations(msp, &self.source_map); - if let Ok(pos) = - annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name)) - { - annotated_files.swap(0, pos); - } - // owned: line source, line index, annotations - type Owned = (String, usize, Vec); - let origin = primary_lo.file.name.to_string(); - let annotated_files: Vec = annotated_files - .into_iter() - .flat_map(|annotated_file| { - let file = annotated_file.file; - annotated_file - .lines - .into_iter() - .map(|line| { - (source_string(file.clone(), &line), line.line_index, line.annotations) - }) - .collect::>() - }) - .collect(); - let snippet = Snippet { - 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(), - }), - annotation_type: annotation_type_for_level(*level), - }), - footer: vec![], - opt: FormatOptions { color: true, anonymized_line_numbers: self.ui_testing }, - slices: annotated_files - .iter() - .map(|(source, line_index, annotations)| { - Slice { - source, - line_start: *line_index, - origin: Some(&origin), - // FIXME(#59346): Not really sure when `fold` should be true or false - fold: false, - annotations: annotations - .iter() - .map(|annotation| SourceAnnotation { - range: (annotation.start_col, annotation.end_col), - label: annotation.label.as_deref().unwrap_or_default(), - annotation_type: annotation_type_for_level(*level), - }) - .collect(), - } - }) - .collect(), - }; - // FIXME(#59346): Figure out if we can _always_ print to stderr or not. - // `emitter.rs` has the `Destination` enum that lists various possible output - // destinations. - eprintln!("{}", DisplayList::from(snippet)) - } - // FIXME(#59346): Is it ok to return None if there's no source_map? - } -} diff --git a/vendor/rustc-ap-rustc_errors/src/diagnostic.rs b/vendor/rustc-ap-rustc_errors/src/diagnostic.rs deleted file mode 100644 index e61476bf23..0000000000 --- a/vendor/rustc-ap-rustc_errors/src/diagnostic.rs +++ /dev/null @@ -1,593 +0,0 @@ -use crate::snippet::Style; -use crate::CodeSuggestion; -use crate::Level; -use crate::Substitution; -use crate::SubstitutionPart; -use crate::SuggestionStyle; -use rustc_lint_defs::Applicability; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; -use std::fmt; - -#[must_use] -#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] -pub struct Diagnostic { - pub level: Level, - pub message: Vec<(String, Style)>, - pub code: Option, - pub span: MultiSpan, - pub children: Vec, - pub suggestions: Vec, - - /// This is not used for highlighting or rendering any error message. Rather, it can be used - /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of - /// `span` if there is one. Otherwise, it is `DUMMY_SP`. - pub sort_span: Span, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] -pub enum DiagnosticId { - Error(String), - Lint { name: String, has_future_breakage: bool }, -} - -/// A "sub"-diagnostic attached to a parent diagnostic. -/// For example, a note attached to an error. -#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] -pub struct SubDiagnostic { - pub level: Level, - pub message: Vec<(String, Style)>, - pub span: MultiSpan, - pub render_span: Option, -} - -#[derive(Debug, PartialEq, Eq)] -pub struct DiagnosticStyledString(pub Vec); - -impl DiagnosticStyledString { - pub fn new() -> DiagnosticStyledString { - DiagnosticStyledString(vec![]) - } - pub fn push_normal>(&mut self, t: S) { - self.0.push(StringPart::Normal(t.into())); - } - pub fn push_highlighted>(&mut self, t: S) { - self.0.push(StringPart::Highlighted(t.into())); - } - pub fn push>(&mut self, t: S, highlight: bool) { - if highlight { - self.push_highlighted(t); - } else { - self.push_normal(t); - } - } - pub fn normal>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::Normal(t.into())]) - } - - pub fn highlighted>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::Highlighted(t.into())]) - } - - pub fn content(&self) -> String { - self.0.iter().map(|x| x.content()).collect::() - } -} - -#[derive(Debug, PartialEq, Eq)] -pub enum StringPart { - Normal(String), - Highlighted(String), -} - -impl StringPart { - pub fn content(&self) -> &str { - match self { - &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s, - } - } -} - -impl Diagnostic { - pub fn new(level: Level, message: &str) -> Self { - Diagnostic::new_with_code(level, None, message) - } - - pub fn new_with_code(level: Level, code: Option, message: &str) -> Self { - Diagnostic { - level, - message: vec![(message.to_owned(), Style::NoStyle)], - code, - span: MultiSpan::new(), - children: vec![], - suggestions: vec![], - sort_span: DUMMY_SP, - } - } - - pub fn is_error(&self) -> bool { - match self.level { - Level::Bug | Level::Fatal | Level::Error | Level::FailureNote => true, - - Level::Warning | Level::Note | Level::Help | Level::Cancelled | Level::Allow => false, - } - } - - pub fn has_future_breakage(&self) -> bool { - match self.code { - Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage, - _ => false, - } - } - - /// Cancel the diagnostic (a structured diagnostic must either be emitted or - /// canceled or it will panic when dropped). - pub fn cancel(&mut self) { - self.level = Level::Cancelled; - } - - /// Check if this diagnostic [was cancelled][Self::cancel()]. - pub fn cancelled(&self) -> bool { - self.level == Level::Cancelled - } - - /// Adds a span/label to be included in the resulting snippet. - /// - /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic - /// was first built. That means it will be shown together with the original - /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods. - /// - /// This span is *not* considered a ["primary span"][`MultiSpan`]; only - /// the `Span` supplied when creating the diagnostic is primary. - pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self { - self.span.push_span_label(span, label.into()); - self - } - - pub fn replace_span_with(&mut self, after: Span) -> &mut Self { - let before = self.span.clone(); - self.set_span(after); - for span_label in before.span_labels() { - if let Some(label) = span_label.label { - self.span_label(after, label); - } - } - self - } - - pub fn note_expected_found( - &mut self, - expected_label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found_label: &dyn fmt::Display, - found: DiagnosticStyledString, - ) -> &mut Self { - self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") - } - - pub fn note_unsuccessful_coercion( - &mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - ) -> &mut Self { - let mut msg: Vec<_> = - vec![("required when trying to coerce from type `".to_string(), Style::NoStyle)]; - msg.extend(expected.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push(("` to type '".to_string(), Style::NoStyle)); - msg.extend(found.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push(("`".to_string(), Style::NoStyle)); - - // For now, just attach these as notes - self.highlighted_note(msg); - self - } - - pub fn note_expected_found_extra( - &mut self, - expected_label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found_label: &dyn fmt::Display, - found: DiagnosticStyledString, - expected_extra: &dyn fmt::Display, - found_extra: &dyn fmt::Display, - ) -> &mut Self { - let expected_label = expected_label.to_string(); - let expected_label = if expected_label.is_empty() { - "expected".to_string() - } else { - format!("expected {}", expected_label) - }; - let found_label = found_label.to_string(); - let found_label = if found_label.is_empty() { - "found".to_string() - } else { - format!("found {}", found_label) - }; - let (found_padding, expected_padding) = if expected_label.len() > found_label.len() { - (expected_label.len() - found_label.len(), 0) - } else { - (0, found_label.len() - expected_label.len()) - }; - let mut msg: Vec<_> = - vec![(format!("{}{} `", " ".repeat(expected_padding), expected_label), Style::NoStyle)]; - msg.extend(expected.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push((format!("`{}\n", expected_extra), Style::NoStyle)); - msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle)); - msg.extend(found.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push((format!("`{}", found_extra), Style::NoStyle)); - - // For now, just attach these as notes. - self.highlighted_note(msg); - self - } - - pub fn note_trait_signature(&mut self, name: String, signature: String) -> &mut Self { - self.highlighted_note(vec![ - (format!("`{}` from trait: `", name), Style::NoStyle), - (signature, Style::Highlight), - ("`".to_string(), Style::NoStyle), - ]); - self - } - - /// Add a note attached to this diagnostic. - pub fn note(&mut self, msg: &str) -> &mut Self { - self.sub(Level::Note, msg, MultiSpan::new(), None); - self - } - - pub fn highlighted_note(&mut self, msg: Vec<(String, Style)>) -> &mut Self { - self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None); - self - } - - /// Prints the span with a note above it. - /// This is like [`Diagnostic::note()`], but it gets its own span. - pub fn span_note>(&mut self, sp: S, msg: &str) -> &mut Self { - self.sub(Level::Note, msg, sp.into(), None); - self - } - - /// Add a warning attached to this diagnostic. - pub fn warn(&mut self, msg: &str) -> &mut Self { - self.sub(Level::Warning, msg, MultiSpan::new(), None); - self - } - - /// Prints the span with a warning above it. - /// This is like [`Diagnostic::warn()`], but it gets its own span. - pub fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self { - self.sub(Level::Warning, msg, sp.into(), None); - self - } - - /// Add a help message attached to this diagnostic. - pub fn help(&mut self, msg: &str) -> &mut Self { - self.sub(Level::Help, msg, MultiSpan::new(), None); - self - } - - /// Prints the span with some help above it. - /// This is like [`Diagnostic::help()`], but it gets its own span. - pub fn span_help>(&mut self, sp: S, msg: &str) -> &mut Self { - self.sub(Level::Help, msg, sp.into(), None); - self - } - - /// Show a suggestion that has multiple parts to it. - /// In other words, multiple changes need to be applied as part of this suggestion. - pub fn multipart_suggestion( - &mut self, - msg: &str, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: suggestion - .into_iter() - .map(|(span, snippet)| SubstitutionPart { snippet, span }) - .collect(), - }], - msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, - applicability, - }); - self - } - - /// Show multiple suggestions that have multiple parts. - /// See also [`Diagnostic::multipart_suggestion()`]. - pub fn multipart_suggestions( - &mut self, - msg: &str, - suggestions: Vec>, - applicability: Applicability, - ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: suggestions - .into_iter() - .map(|suggestion| Substitution { - parts: suggestion - .into_iter() - .map(|(span, snippet)| SubstitutionPart { snippet, span }) - .collect(), - }) - .collect(), - msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, - applicability, - }); - self - } - - /// Prints out a message with for a multipart suggestion without showing the suggested code. - /// - /// This is intended to be used for suggestions that are obvious in what the changes need to - /// be from the message, showing the span label inline would be visually unpleasant - /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't - /// improve understandability. - pub fn tool_only_multipart_suggestion( - &mut self, - msg: &str, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: suggestion - .into_iter() - .map(|(span, snippet)| SubstitutionPart { snippet, span }) - .collect(), - }], - msg: msg.to_owned(), - style: SuggestionStyle::CompletelyHidden, - applicability, - }); - self - } - - /// Prints out a message with a suggested edit of the code. - /// - /// In case of short messages and a simple suggestion, rustc displays it as a label: - /// - /// ```text - /// try adding parentheses: `(tup.0).1` - /// ``` - /// - /// The message - /// - /// * should not end in any punctuation (a `:` is added automatically) - /// * should not be a question (avoid language like "did you mean") - /// * should not contain any phrases like "the following", "as shown", etc. - /// * may look like "to do xyz, use" or "to do xyz, use abc" - /// * may contain a name of a function, variable, or type, but not whole expressions - /// - /// See `CodeSuggestion` for more information. - pub fn span_suggestion( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, - applicability, - SuggestionStyle::ShowCode, - ); - self - } - - /// [`Diagnostic::span_suggestion()`] but you can set the [`SuggestionStyle`]. - pub fn span_suggestion_with_style( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - style: SuggestionStyle, - ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { snippet: suggestion, span: sp }], - }], - msg: msg.to_owned(), - style, - applicability, - }); - self - } - - /// Always show the suggested change. - pub fn span_suggestion_verbose( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, - applicability, - SuggestionStyle::ShowAlways, - ); - self - } - - /// Prints out a message with multiple suggested edits of the code. - /// See also [`Diagnostic::span_suggestion()`]. - pub fn span_suggestions( - &mut self, - sp: Span, - msg: &str, - suggestions: impl Iterator, - applicability: Applicability, - ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: suggestions - .map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] }) - .collect(), - msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, - applicability, - }); - self - } - - /// Prints out a message with a suggested edit of the code. If the suggestion is presented - /// inline, it will only show the message and not the suggestion. - /// - /// See `CodeSuggestion` for more information. - pub fn span_suggestion_short( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, - applicability, - SuggestionStyle::HideCodeInline, - ); - self - } - - /// Prints out a message for a suggestion without showing the suggested code. - /// - /// This is intended to be used for suggestions that are obvious in what the changes need to - /// be from the message, showing the span label inline would be visually unpleasant - /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't - /// improve understandability. - pub fn span_suggestion_hidden( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, - applicability, - SuggestionStyle::HideCodeAlways, - ); - self - } - - /// Adds a suggestion to the JSON output that will not be shown in the CLI. - /// - /// This is intended to be used for suggestions that are *very* obvious in what the changes - /// need to be from the message, but we still want other tools to be able to apply them. - pub fn tool_only_span_suggestion( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - self.span_suggestion_with_style( - sp, - msg, - suggestion, - applicability, - SuggestionStyle::CompletelyHidden, - ); - self - } - - pub fn set_span>(&mut self, sp: S) -> &mut Self { - self.span = sp.into(); - if let Some(span) = self.span.primary_span() { - self.sort_span = span; - } - self - } - - pub fn code(&mut self, s: DiagnosticId) -> &mut Self { - self.code = Some(s); - self - } - - pub fn clear_code(&mut self) -> &mut Self { - self.code = None; - self - } - - pub fn get_code(&self) -> Option { - self.code.clone() - } - - pub fn set_primary_message>(&mut self, msg: M) -> &mut Self { - self.message[0] = (msg.into(), Style::NoStyle); - self - } - - pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.as_str()).collect::() - } - - pub fn styled_message(&self) -> &Vec<(String, Style)> { - &self.message - } - - /// Convenience function for internal use, clients should use one of the - /// public methods above. - pub fn sub( - &mut self, - level: Level, - message: &str, - span: MultiSpan, - render_span: Option, - ) { - let sub = SubDiagnostic { - level, - message: vec![(message.to_owned(), Style::NoStyle)], - span, - render_span, - }; - self.children.push(sub); - } - - /// Convenience function for internal use, clients should use one of the - /// public methods above. - fn sub_with_highlights( - &mut self, - level: Level, - message: Vec<(String, Style)>, - span: MultiSpan, - render_span: Option, - ) { - let sub = SubDiagnostic { level, message, span, render_span }; - self.children.push(sub); - } -} - -impl SubDiagnostic { - pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.as_str()).collect::() - } - - pub fn styled_message(&self) -> &Vec<(String, Style)> { - &self.message - } -} diff --git a/vendor/rustc-ap-rustc_errors/src/diagnostic_builder.rs b/vendor/rustc-ap-rustc_errors/src/diagnostic_builder.rs deleted file mode 100644 index c09cce21bf..0000000000 --- a/vendor/rustc-ap-rustc_errors/src/diagnostic_builder.rs +++ /dev/null @@ -1,479 +0,0 @@ -use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString}; -use crate::{Handler, Level, StashKey}; -use rustc_lint_defs::Applicability; - -use rustc_span::{MultiSpan, Span}; -use std::fmt::{self, Debug}; -use std::ops::{Deref, DerefMut}; -use std::thread::panicking; -use tracing::debug; - -/// Used for emitting structured error messages and other diagnostic information. -/// -/// If there is some state in a downstream crate you would like to -/// access in the methods of `DiagnosticBuilder` here, consider -/// extending `HandlerFlags`, accessed via `self.handler.flags`. -#[must_use] -#[derive(Clone)] -pub struct DiagnosticBuilder<'a>(Box>); - -/// This is a large type, and often used as a return value, especially within -/// the frequently-used `PResult` type. In theory, return value optimization -/// (RVO) should avoid unnecessary copying. In practice, it does not (at the -/// time of writing). The split between `DiagnosticBuilder` and -/// `DiagnosticBuilderInner` exists to avoid many `memcpy` calls. -#[must_use] -#[derive(Clone)] -struct DiagnosticBuilderInner<'a> { - handler: &'a Handler, - diagnostic: Diagnostic, - allow_suggestions: bool, -} - -/// This is a helper macro for [`forward!`] that allows automatically adding documentation -/// that uses tokens from [`forward!`]'s input. -macro_rules! forward_inner_docs { - ($e:expr => $i:item) => { - #[doc = $e] - $i - }; -} - -/// In general, the `DiagnosticBuilder` uses deref to allow access to -/// the fields and methods of the embedded `diagnostic` in a -/// transparent way. *However,* many of the methods are intended to -/// be used in a chained way, and hence ought to return `self`. In -/// that case, we can't just naively forward to the method on the -/// `diagnostic`, because the return type would be a `&Diagnostic` -/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes -/// it easy to declare such methods on the builder. -macro_rules! forward { - // Forward pattern for &self -> &Self - ( - $(#[$attrs:meta])* - pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)?) -> &Self - ) => { - $(#[$attrs])* - forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") => - pub fn $n(&self, $($name: $ty),*) -> &Self { - self.diagnostic.$n($($name),*); - self - }); - }; - - // Forward pattern for &mut self -> &mut Self - ( - $(#[$attrs:meta])* - pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)?) -> &mut Self - ) => { - $(#[$attrs])* - forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") => - pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { - self.0.diagnostic.$n($($name),*); - self - }); - }; - - // Forward pattern for &mut self -> &mut Self, with generic parameters. - ( - $(#[$attrs:meta])* - pub fn $n:ident<$($generic:ident: $bound:path),*>( - &mut self, - $($name:ident: $ty:ty),* - $(,)? - ) -> &mut Self - ) => { - $(#[$attrs])* - forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") => - pub fn $n<$($generic: $bound),*>(&mut self, $($name: $ty),*) -> &mut Self { - self.0.diagnostic.$n($($name),*); - self - }); - }; -} - -impl<'a> Deref for DiagnosticBuilder<'a> { - type Target = Diagnostic; - - fn deref(&self) -> &Diagnostic { - &self.0.diagnostic - } -} - -impl<'a> DerefMut for DiagnosticBuilder<'a> { - fn deref_mut(&mut self) -> &mut Diagnostic { - &mut self.0.diagnostic - } -} - -impl<'a> DiagnosticBuilder<'a> { - /// Emit the diagnostic. - pub fn emit(&mut self) { - self.0.handler.emit_diagnostic(&self); - self.cancel(); - } - - /// Emit the diagnostic unless `delay` is true, - /// in which case the emission will be delayed as a bug. - /// - /// See `emit` and `delay_as_bug` for details. - pub fn emit_unless(&mut self, delay: bool) { - if delay { - self.delay_as_bug(); - } else { - self.emit(); - } - } - - /// Stashes diagnostic for possible later improvement in a different, - /// later stage of the compiler. The diagnostic can be accessed with - /// the provided `span` and `key` through [`Handler::steal_diagnostic()`]. - /// - /// As with `buffer`, this is unless the handler has disabled such buffering. - pub fn stash(self, span: Span, key: StashKey) { - if let Some((diag, handler)) = self.into_diagnostic() { - handler.stash_diagnostic(span, key, diag); - } - } - - /// Converts the builder to a `Diagnostic` for later emission, - /// unless handler has disabled such buffering. - pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> { - if self.0.handler.flags.dont_buffer_diagnostics - || self.0.handler.flags.treat_err_as_bug.is_some() - { - self.emit(); - return None; - } - - let handler = self.0.handler; - - // We must use `Level::Cancelled` for `dummy` to avoid an ICE about an - // unused diagnostic. - let dummy = Diagnostic::new(Level::Cancelled, ""); - let diagnostic = std::mem::replace(&mut self.0.diagnostic, dummy); - - // Logging here is useful to help track down where in logs an error was - // actually emitted. - debug!("buffer: diagnostic={:?}", diagnostic); - - Some((diagnostic, handler)) - } - - /// Buffers the diagnostic for later emission, - /// unless handler has disabled such buffering. - pub fn buffer(self, buffered_diagnostics: &mut Vec) { - buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); - } - - /// Convenience function for internal use, clients should use one of the - /// span_* methods instead. - pub fn sub>( - &mut self, - level: Level, - message: &str, - span: Option, - ) -> &mut Self { - let span = span.map(|s| s.into()).unwrap_or_else(MultiSpan::new); - self.0.diagnostic.sub(level, message, span, None); - self - } - - /// Delay emission of this diagnostic as a bug. - /// - /// This can be useful in contexts where an error indicates a bug but - /// typically this only happens when other compilation errors have already - /// happened. In those cases this can be used to defer emission of this - /// diagnostic as a bug in the compiler only if no other errors have been - /// emitted. - /// - /// In the meantime, though, callsites are required to deal with the "bug" - /// locally in whichever way makes the most sense. - pub fn delay_as_bug(&mut self) { - self.level = Level::Bug; - self.0.handler.delay_as_bug(self.0.diagnostic.clone()); - self.cancel(); - } - - /// Appends a labeled span to the diagnostic. - /// - /// Labels are used to convey additional context for the diagnostic's primary span. They will - /// be shown together with the original diagnostic's span, *not* with spans added by - /// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because - /// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed - /// either. - /// - /// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when - /// the diagnostic was constructed. However, the label span is *not* considered a - /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is - /// primary. - pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { - self.0.diagnostic.span_label(span, label); - self - } - - /// Labels all the given spans with the provided label. - /// See [`Diagnostic::span_label()`] for more information. - pub fn span_labels( - &mut self, - spans: impl IntoIterator, - label: impl AsRef, - ) -> &mut Self { - let label = label.as_ref(); - for span in spans { - self.0.diagnostic.span_label(span, label); - } - self - } - - forward!(pub fn note_expected_found( - &mut self, - expected_label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found_label: &dyn fmt::Display, - found: DiagnosticStyledString, - ) -> &mut Self); - - forward!(pub fn note_expected_found_extra( - &mut self, - expected_label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found_label: &dyn fmt::Display, - found: DiagnosticStyledString, - expected_extra: &dyn fmt::Display, - found_extra: &dyn fmt::Display, - ) -> &mut Self); - - forward!(pub fn note_unsuccessful_coercion( - &mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - ) -> &mut Self); - - forward!(pub fn note(&mut self, msg: &str) -> &mut Self); - forward!(pub fn span_note>( - &mut self, - sp: S, - msg: &str, - ) -> &mut Self); - forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); - forward!(pub fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self); - forward!(pub fn help(&mut self, msg: &str) -> &mut Self); - forward!(pub fn span_help>( - &mut self, - sp: S, - msg: &str, - ) -> &mut Self); - - /// See [`Diagnostic::multipart_suggestion()`]. - pub fn multipart_suggestion( - &mut self, - msg: &str, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.multipart_suggestion(msg, suggestion, applicability); - self - } - - /// See [`Diagnostic::multipart_suggestions()`]. - pub fn multipart_suggestions( - &mut self, - msg: &str, - suggestions: Vec>, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability); - self - } - - /// See [`Diagnostic::tool_only_multipart_suggestion()`]. - pub fn tool_only_multipart_suggestion( - &mut self, - msg: &str, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.tool_only_multipart_suggestion(msg, suggestion, applicability); - self - } - - /// See [`Diagnostic::span_suggestion()`]. - pub fn span_suggestion( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.span_suggestion(sp, msg, suggestion, applicability); - self - } - - /// See [`Diagnostic::span_suggestions()`]. - pub fn span_suggestions( - &mut self, - sp: Span, - msg: &str, - suggestions: impl Iterator, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.span_suggestions(sp, msg, suggestions, applicability); - self - } - - /// See [`Diagnostic::span_suggestion_short()`]. - pub fn span_suggestion_short( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.span_suggestion_short(sp, msg, suggestion, applicability); - self - } - - /// See [`Diagnostic::span_suggestion_verbose()`]. - pub fn span_suggestion_verbose( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.span_suggestion_verbose(sp, msg, suggestion, applicability); - self - } - - /// See [`Diagnostic::span_suggestion_hidden()`]. - pub fn span_suggestion_hidden( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.span_suggestion_hidden(sp, msg, suggestion, applicability); - self - } - - /// See [`Diagnostic::tool_only_span_suggestion()`] for more information. - pub fn tool_only_span_suggestion( - &mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability, - ) -> &mut Self { - if !self.0.allow_suggestions { - return self; - } - self.0.diagnostic.tool_only_span_suggestion(sp, msg, suggestion, applicability); - self - } - - forward!(pub fn set_primary_message>(&mut self, msg: M) -> &mut Self); - forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); - forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); - - /// Allow attaching suggestions this diagnostic. - /// If this is set to `false`, then any suggestions attached with the `span_suggestion_*` - /// methods after this is set to `false` will be ignored. - pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self { - self.0.allow_suggestions = allow; - self - } - - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - crate fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { - DiagnosticBuilder::new_with_code(handler, level, None, message) - } - - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - crate fn new_with_code( - handler: &'a Handler, - level: Level, - code: Option, - message: &str, - ) -> DiagnosticBuilder<'a> { - let diagnostic = Diagnostic::new_with_code(level, code, message); - DiagnosticBuilder::new_diagnostic(handler, diagnostic) - } - - /// Creates a new `DiagnosticBuilder` with an already constructed - /// diagnostic. - crate fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> { - debug!("Created new diagnostic"); - DiagnosticBuilder(Box::new(DiagnosticBuilderInner { - handler, - diagnostic, - allow_suggestions: true, - })) - } -} - -impl<'a> Debug for DiagnosticBuilder<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.diagnostic.fmt(f) - } -} - -/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or canceled -/// or we emit a bug. -impl<'a> Drop for DiagnosticBuilder<'a> { - fn drop(&mut self) { - if !panicking() && !self.cancelled() { - let mut db = DiagnosticBuilder::new( - self.0.handler, - Level::Bug, - "the following error was constructed but not emitted", - ); - db.emit(); - self.emit(); - panic!(); - } - } -} - -#[macro_export] -macro_rules! struct_span_err { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - $session.struct_span_err_with_code( - $span, - &format!($($message)*), - $crate::error_code!($code), - ) - }) -} - -#[macro_export] -macro_rules! error_code { - ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }}; -} diff --git a/vendor/rustc-ap-rustc_errors/src/emitter.rs b/vendor/rustc-ap-rustc_errors/src/emitter.rs deleted file mode 100644 index ea62e21523..0000000000 --- a/vendor/rustc-ap-rustc_errors/src/emitter.rs +++ /dev/null @@ -1,2207 +0,0 @@ -//! The current rustc diagnostics emitter. -//! -//! An `Emitter` takes care of generating the output from a `DiagnosticBuilder` struct. -//! -//! There are various `Emitter` implementations that generate different output formats such as -//! JSON and human readable output. -//! -//! The output types are defined in `rustc_session::config::ErrorOutputType`. - -use Destination::*; - -use rustc_lint_defs::FutureBreakage; -use rustc_span::source_map::SourceMap; -use rustc_span::{MultiSpan, SourceFile, Span}; - -use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; -use crate::styled_buffer::StyledBuffer; -use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle}; - -use rustc_lint_defs::pluralize; - -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; -use rustc_span::hygiene::{ExpnKind, MacroKind}; -use std::borrow::Cow; -use std::cmp::{max, min, Reverse}; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::path::Path; -use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream}; -use termcolor::{Buffer, Color, WriteColor}; -use tracing::*; - -/// Default column width, used in tests and when terminal dimensions cannot be determined. -const DEFAULT_COLUMN_WIDTH: usize = 140; - -/// Describes the way the content of the `rendered` field of the json output is generated -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum HumanReadableErrorType { - Default(ColorConfig), - AnnotateSnippet(ColorConfig), - Short(ColorConfig), -} - -impl HumanReadableErrorType { - /// Returns a (`short`, `color`) tuple - pub fn unzip(self) -> (bool, ColorConfig) { - match self { - HumanReadableErrorType::Default(cc) => (false, cc), - HumanReadableErrorType::Short(cc) => (true, cc), - HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc), - } - } - pub fn new_emitter( - self, - dst: Box, - source_map: Option>, - teach: bool, - terminal_width: Option, - macro_backtrace: bool, - ) -> EmitterWriter { - let (short, color_config) = self.unzip(); - let color = color_config.suggests_using_colors(); - EmitterWriter::new(dst, source_map, short, teach, color, terminal_width, macro_backtrace) - } -} - -#[derive(Clone, Copy, Debug)] -struct Margin { - /// The available whitespace in the left that can be consumed when centering. - pub whitespace_left: usize, - /// The column of the beginning of left-most span. - pub span_left: usize, - /// The column of the end of right-most span. - pub span_right: usize, - /// The beginning of the line to be displayed. - pub computed_left: usize, - /// The end of the line to be displayed. - pub computed_right: usize, - /// The current width of the terminal. Uses value of `DEFAULT_COLUMN_WIDTH` constant by default - /// and in tests. - pub column_width: usize, - /// The end column of a span label, including the span. Doesn't account for labels not in the - /// same line as the span. - pub label_right: usize, -} - -impl Margin { - fn new( - whitespace_left: usize, - span_left: usize, - span_right: usize, - label_right: usize, - column_width: usize, - max_line_len: usize, - ) -> Self { - // The 6 is padding to give a bit of room for `...` when displaying: - // ``` - // error: message - // --> file.rs:16:58 - // | - // 16 | ... fn foo(self) -> Self::Bar { - // | ^^^^^^^^^ - // ``` - - let mut m = Margin { - whitespace_left: whitespace_left.saturating_sub(6), - span_left: span_left.saturating_sub(6), - span_right: span_right + 6, - computed_left: 0, - computed_right: 0, - column_width, - label_right: label_right + 6, - }; - m.compute(max_line_len); - m - } - - fn was_cut_left(&self) -> bool { - self.computed_left > 0 - } - - fn was_cut_right(&self, line_len: usize) -> bool { - let right = - if self.computed_right == self.span_right || self.computed_right == self.label_right { - // Account for the "..." padding given above. Otherwise we end up with code lines that - // do fit but end in "..." as if they were trimmed. - self.computed_right - 6 - } else { - self.computed_right - }; - right < line_len && self.computed_left + self.column_width < line_len - } - - fn compute(&mut self, max_line_len: usize) { - // When there's a lot of whitespace (>20), we want to trim it as it is useless. - self.computed_left = if self.whitespace_left > 20 { - self.whitespace_left - 16 // We want some padding. - } else { - 0 - }; - // We want to show as much as possible, max_line_len is the right-most boundary for the - // relevant code. - self.computed_right = max(max_line_len, self.computed_left); - - if self.computed_right - self.computed_left > self.column_width { - // Trimming only whitespace isn't enough, let's get craftier. - if self.label_right - self.whitespace_left <= self.column_width { - // Attempt to fit the code window only trimming whitespace. - self.computed_left = self.whitespace_left; - self.computed_right = self.computed_left + self.column_width; - } else if self.label_right - self.span_left <= self.column_width { - // Attempt to fit the code window considering only the spans and labels. - let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2; - self.computed_left = self.span_left.saturating_sub(padding_left); - self.computed_right = self.computed_left + self.column_width; - } else if self.span_right - self.span_left <= self.column_width { - // Attempt to fit the code window considering the spans and labels plus padding. - let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2; - self.computed_left = self.span_left.saturating_sub(padding_left); - self.computed_right = self.computed_left + self.column_width; - } else { - // Mostly give up but still don't show the full line. - self.computed_left = self.span_left; - self.computed_right = self.span_right; - } - } - } - - fn left(&self, line_len: usize) -> usize { - min(self.computed_left, line_len) - } - - fn right(&self, line_len: usize) -> usize { - if line_len.saturating_sub(self.computed_left) <= self.column_width { - line_len - } else { - min(line_len, self.computed_right) - } - } -} - -const ANONYMIZED_LINE_NUM: &str = "LL"; - -/// Emitter trait for emitting errors. -pub trait Emitter { - /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, diag: &Diagnostic); - - /// Emit a notification that an artifact has been output. - /// This is currently only supported for the JSON format, - /// 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)>) {} - - /// Checks if should show explanations about "rustc --explain" - fn should_show_explain(&self) -> bool { - true - } - - /// Checks if we can use colors in the current output stream. - fn supports_color(&self) -> bool { - false - } - - fn source_map(&self) -> Option<&Lrc>; - - /// Formats the substitutions of the primary_span - /// - /// The are a lot of conditions to this method, but in short: - /// - /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, - /// we format the `help` suggestion depending on the content of the - /// substitutions. In that case, we return the modified span only. - /// - /// * If the current `Diagnostic` has multiple suggestions, - /// we return the original `primary_span` and the original suggestions. - fn primary_span_formatted<'a>( - &mut self, - diag: &'a Diagnostic, - ) -> (MultiSpan, &'a [CodeSuggestion]) { - let mut primary_span = diag.span.clone(); - if let Some((sugg, rest)) = diag.suggestions.split_first() { - if rest.is_empty() && - // ^ if there is only one suggestion - // don't display multi-suggestions as labels - sugg.substitutions.len() == 1 && - // don't display multipart suggestions as labels - sugg.substitutions[0].parts.len() == 1 && - // don't display long messages as labels - sugg.msg.split_whitespace().count() < 10 && - // don't display multiline suggestions as labels - !sugg.substitutions[0].parts[0].snippet.contains('\n') && - ![ - // when this style is set we want the suggestion to be a message, not inline - SuggestionStyle::HideCodeAlways, - // trivial suggestion for tooling's sake, never shown - SuggestionStyle::CompletelyHidden, - // subtle suggestion, never shown inline - SuggestionStyle::ShowAlways, - ].contains(&sugg.style) - { - let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); - let msg = if substitution.is_empty() || sugg.style.hide_inline() { - // This substitution is only removal OR we explicitly don't want to show the - // code inline (`hide_inline`). Therefore, we don't show the substitution. - format!("help: {}", sugg.msg) - } else { - // Show the default suggestion text with the substitution - format!( - "help: {}{}: `{}`", - sugg.msg, - if self - .source_map() - .map(|sm| is_case_difference( - &**sm, - substitution, - sugg.substitutions[0].parts[0].span, - )) - .unwrap_or(false) - { - " (notice the capitalization)" - } else { - "" - }, - substitution, - ) - }; - primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); - - // We return only the modified primary_span - (primary_span, &[]) - } else { - // if there are multiple suggestions, print them all in full - // to be consistent. We could try to figure out if we can - // make one (or the first one) inline, but that would give - // undue importance to a semi-random suggestion - (primary_span, &diag.suggestions) - } - } else { - (primary_span, &diag.suggestions) - } - } - - fn fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self, - source_map: &Option>, - span: &mut MultiSpan, - children: &mut Vec, - level: &Level, - backtrace: bool, - ) { - // Check for spans in macros, before `fix_multispans_in_extern_macros` - // has a chance to replace them. - let has_macro_spans = iter::once(&*span) - .chain(children.iter().map(|child| &child.span)) - .flat_map(|span| span.primary_spans()) - .flat_map(|sp| sp.macro_backtrace()) - .find_map(|expn_data| { - match expn_data.kind { - ExpnKind::Root => None, - - // Skip past non-macro entries, just in case there - // are some which do actually involve macros. - ExpnKind::Inlined | ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None, - - ExpnKind::Macro(macro_kind, _) => Some(macro_kind), - } - }); - - if !backtrace { - self.fix_multispans_in_extern_macros(source_map, span, children); - } - - self.render_multispans_macro_backtrace(span, children, backtrace); - - if !backtrace { - if let Some(macro_kind) = has_macro_spans { - let msg = format!( - "this {} originates in {} {} \ - (in Nightly builds, run with -Z macro-backtrace for more info)", - level, - macro_kind.article(), - macro_kind.descr(), - ); - - children.push(SubDiagnostic { - level: Level::Note, - message: vec![(msg, Style::NoStyle)], - span: MultiSpan::new(), - render_span: None, - }); - } - } - } - - fn render_multispans_macro_backtrace( - &self, - span: &mut MultiSpan, - children: &mut Vec, - backtrace: bool, - ) { - for span in iter::once(span).chain(children.iter_mut().map(|child| &mut child.span)) { - self.render_multispan_macro_backtrace(span, backtrace); - } - } - - fn render_multispan_macro_backtrace(&self, span: &mut MultiSpan, always_backtrace: bool) { - let mut new_labels: Vec<(Span, String)> = vec![]; - - for &sp in span.primary_spans() { - if sp.is_dummy() { - continue; - } - - // FIXME(eddyb) use `retain` on `macro_backtrace` to remove all the - // entries we don't want to print, to make sure the indices being - // printed are contiguous (or omitted if there's only one entry). - let macro_backtrace: Vec<_> = sp.macro_backtrace().collect(); - for (i, trace) in macro_backtrace.iter().rev().enumerate() { - if trace.def_site.is_dummy() { - 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 { - new_labels.push(( - trace.def_site, - format!( - "in this expansion of `{}`{}", - trace.kind.descr(), - if macro_backtrace.len() > 1 { - // if macro_backtrace.len() == 1 it'll be - // pointed at by "in this macro invocation" - format!(" (#{})", i + 1) - } else { - String::new() - }, - ), - )); - } - - // Don't add a label on the call site if the diagnostic itself - // already points to (a part of) that call site, as the label - // is meant for showing the relevant invocation when the actual - // diagnostic is pointing to some part of macro definition. - // - // This also handles the case where an external span got replaced - // with the call site span by `fix_multispans_in_extern_macros`. - // - // NB: `-Zmacro-backtrace` overrides this, for uniformity, as the - // "in this expansion of" label above is always added in that mode, - // 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(MacroKind::Bang, _)) - || always_backtrace - { - new_labels.push(( - trace.call_site, - format!( - "in this macro invocation{}", - if macro_backtrace.len() > 1 && always_backtrace { - // only specify order when the macro - // backtrace is multiple levels deep - format!(" (#{})", i + 1) - } else { - String::new() - }, - ), - )); - } - if !always_backtrace { - break; - } - } - } - - for (label_span, label_text) in new_labels { - span.push_span_label(label_span, label_text); - } - } - - // This does a small "fix" for multispans by looking to see if it can find any that - // point directly at external macros. Since these are often difficult to read, - // this will change the span to point at the use site. - fn fix_multispans_in_extern_macros( - &self, - source_map: &Option>, - span: &mut MultiSpan, - children: &mut Vec, - ) { - debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); - for span in iter::once(&mut *span).chain(children.iter_mut().map(|child| &mut child.span)) { - self.fix_multispan_in_extern_macros(source_map, span); - } - debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children); - } - - // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. - // Since these locations are often difficult to read, - // we move these spans from the external macros to their corresponding use site. - fn fix_multispan_in_extern_macros( - &self, - source_map: &Option>, - span: &mut MultiSpan, - ) { - let sm = match source_map { - Some(ref sm) => sm, - None => return, - }; - - // First, find all the spans in external macros and point instead at their use site. - let replacements: Vec<(Span, Span)> = span - .primary_spans() - .iter() - .copied() - .chain(span.span_labels().iter().map(|sp_label| sp_label.span)) - .filter_map(|sp| { - if !sp.is_dummy() && sm.is_imported(sp) { - let maybe_callsite = sp.source_callsite(); - if sp != maybe_callsite { - return Some((sp, maybe_callsite)); - } - } - None - }) - .collect(); - - // After we have them, make sure we replace these 'bad' def sites with their use sites. - for (from, to) in replacements { - span.replace(from, to); - } - } -} - -impl Emitter for EmitterWriter { - fn source_map(&self) -> Option<&Lrc> { - self.sm.as_ref() - } - - fn emit_diagnostic(&mut self, diag: &Diagnostic) { - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); - debug!("emit_diagnostic: suggestions={:?}", suggestions); - - self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.sm, - &mut primary_span, - &mut children, - &diag.level, - self.macro_backtrace, - ); - - self.emit_messages_default( - &diag.level, - &diag.styled_message(), - &diag.code, - &primary_span, - &children, - &suggestions, - ); - } - - fn should_show_explain(&self) -> bool { - !self.short_message - } - - fn supports_color(&self) -> bool { - self.dst.supports_color() - } -} - -/// An emitter that does nothing when emitting a diagnostic. -pub struct SilentEmitter; - -impl Emitter for SilentEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } - fn emit_diagnostic(&mut self, _: &Diagnostic) {} -} - -/// Maximum number of lines we will print for a multiline suggestion; arbitrary. -/// -/// This should be replaced with a more involved mechanism to output multiline suggestions that -/// more closely mimics the regular diagnostic output, where irrelevant code lines are elided. -pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 6; -/// Maximum number of suggestions to be shown -/// -/// Arbitrary, but taken from trait import suggestion limit -pub const MAX_SUGGESTIONS: usize = 4; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum ColorConfig { - Auto, - Always, - Never, -} - -impl ColorConfig { - fn to_color_choice(self) -> ColorChoice { - match self { - ColorConfig::Always => { - if atty::is(atty::Stream::Stderr) { - ColorChoice::Always - } else { - ColorChoice::AlwaysAnsi - } - } - ColorConfig::Never => ColorChoice::Never, - ColorConfig::Auto if atty::is(atty::Stream::Stderr) => ColorChoice::Auto, - ColorConfig::Auto => ColorChoice::Never, - } - } - fn suggests_using_colors(self) -> bool { - match self { - ColorConfig::Always | ColorConfig::Auto => true, - ColorConfig::Never => false, - } - } -} - -/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` -pub struct EmitterWriter { - dst: Destination, - sm: Option>, - short_message: bool, - teach: bool, - ui_testing: bool, - terminal_width: Option, - - macro_backtrace: bool, -} - -#[derive(Debug)] -pub struct FileWithAnnotatedLines { - pub file: Lrc, - pub lines: Vec, - multiline_depth: usize, -} - -impl EmitterWriter { - pub fn stderr( - color_config: ColorConfig, - source_map: Option>, - short_message: bool, - teach: bool, - terminal_width: Option, - macro_backtrace: bool, - ) -> EmitterWriter { - let dst = Destination::from_stderr(color_config); - EmitterWriter { - dst, - sm: source_map, - short_message, - teach, - ui_testing: false, - terminal_width, - macro_backtrace, - } - } - - pub fn new( - dst: Box, - source_map: Option>, - short_message: bool, - teach: bool, - colored: bool, - terminal_width: Option, - macro_backtrace: bool, - ) -> EmitterWriter { - EmitterWriter { - dst: Raw(dst, colored), - sm: source_map, - short_message, - teach, - ui_testing: false, - terminal_width, - macro_backtrace, - } - } - - pub fn ui_testing(mut self, ui_testing: bool) -> Self { - self.ui_testing = ui_testing; - self - } - - fn maybe_anonymized(&self, line_num: usize) -> String { - if self.ui_testing { ANONYMIZED_LINE_NUM.to_string() } else { line_num.to_string() } - } - - fn draw_line( - &self, - buffer: &mut StyledBuffer, - source_string: &str, - line_index: usize, - line_offset: usize, - width_offset: usize, - code_offset: usize, - margin: Margin, - ) { - // Tabs are assumed to have been replaced by spaces in calling code. - debug_assert!(!source_string.contains('\t')); - let line_len = source_string.len(); - // Create the source line we will highlight. - let left = margin.left(line_len); - let right = margin.right(line_len); - // On long lines, we strip the source line, accounting for unicode. - let mut taken = 0; - let code: String = source_string - .chars() - .skip(left) - .take_while(|ch| { - // Make sure that the trimming on the right will fall within the terminal width. - // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. - // For now, just accept that sometimes the code line will be longer than desired. - let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); - if taken + next > right - left { - return false; - } - taken += next; - true - }) - .collect(); - buffer.puts(line_offset, code_offset, &code, Style::Quotation); - if margin.was_cut_left() { - // We have stripped some code/whitespace from the beginning, make it clear. - buffer.puts(line_offset, code_offset, "...", Style::LineNumber); - } - if margin.was_cut_right(line_len) { - // We have stripped some code after the right-most span end, make it clear we did so. - buffer.puts(line_offset, code_offset + taken - 3, "...", Style::LineNumber); - } - buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber); - - draw_col_separator(buffer, line_offset, width_offset - 2); - } - - fn render_source_line( - &self, - buffer: &mut StyledBuffer, - file: Lrc, - line: &Line, - width_offset: usize, - code_offset: usize, - margin: Margin, - ) -> Vec<(usize, Style)> { - // Draw: - // - // LL | ... code ... - // | ^^-^ span label - // | | - // | secondary span label - // - // ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it - // | | | | - // | | | actual code found in your source code and the spans we use to mark it - // | | when there's too much wasted space to the left, trim it - // | vertical divider between the column number and the code - // column number - - if line.line_index == 0 { - return Vec::new(); - } - - let source_string = match file.get_line(line.line_index - 1) { - Some(s) => replace_tabs(&*s), - None => return Vec::new(), - }; - - let line_offset = buffer.num_lines(); - - let left = margin.left(source_string.len()); // Left trim - // Account for unicode characters of width !=0 that were removed. - let left = source_string - .chars() - .take(left) - .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) - .sum(); - - self.draw_line( - buffer, - &source_string, - line.line_index, - line_offset, - width_offset, - code_offset, - margin, - ); - - // Special case when there's only one annotation involved, it is the start of a multiline - // span and there's no text at the beginning of the code line. Instead of doing the whole - // graph: - // - // 2 | fn foo() { - // | _^ - // 3 | | - // 4 | | } - // | |_^ test - // - // we simplify the output to: - // - // 2 | / fn foo() { - // 3 | | - // 4 | | } - // | |_^ test - if let [ann] = &line.annotations[..] { - if let AnnotationType::MultilineStart(depth) = ann.annotation_type { - if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) { - let style = if ann.is_primary { - Style::UnderlinePrimary - } else { - Style::UnderlineSecondary - }; - buffer.putc(line_offset, width_offset + depth - 1, '/', style); - return vec![(depth, style)]; - } - } - } - - // We want to display like this: - // - // vec.push(vec.pop().unwrap()); - // --- ^^^ - previous borrow ends here - // | | - // | error occurs here - // previous borrow of `vec` occurs here - // - // But there are some weird edge cases to be aware of: - // - // vec.push(vec.pop().unwrap()); - // -------- - previous borrow ends here - // || - // |this makes no sense - // previous borrow of `vec` occurs here - // - // For this reason, we group the lines into "highlight lines" - // and "annotations lines", where the highlight lines have the `^`. - - // Sort the annotations by (start, end col) - // The labels are reversed, sort and then reversed again. - // Consider a list of annotations (A1, A2, C1, C2, B1, B2) where - // the letter signifies the span. Here we are only sorting by the - // span and hence, the order of the elements with the same span will - // not change. On reversing the ordering (|a, b| but b.cmp(a)), you get - // (C1, C2, B1, B2, A1, A2). All the elements with the same span are - // still ordered first to last, but all the elements with different - // spans are ordered by their spans in last to first order. Last to - // first order is important, because the jiggly lines and | are on - // the left, so the rightmost span needs to be rendered first, - // otherwise the lines would end up needing to go over a message. - - let mut annotations = line.annotations.clone(); - annotations.sort_by_key(|a| Reverse(a.start_col)); - - // First, figure out where each label will be positioned. - // - // In the case where you have the following annotations: - // - // vec.push(vec.pop().unwrap()); - // -------- - previous borrow ends here [C] - // || - // |this makes no sense [B] - // previous borrow of `vec` occurs here [A] - // - // `annotations_position` will hold [(2, A), (1, B), (0, C)]. - // - // We try, when possible, to stick the rightmost annotation at the end - // of the highlight line: - // - // vec.push(vec.pop().unwrap()); - // --- --- - previous borrow ends here - // - // But sometimes that's not possible because one of the other - // annotations overlaps it. For example, from the test - // `span_overlap_label`, we have the following annotations - // (written on distinct lines for clarity): - // - // fn foo(x: u32) { - // -------------- - // - - // - // In this case, we can't stick the rightmost-most label on - // the highlight line, or we would get: - // - // fn foo(x: u32) { - // -------- x_span - // | - // fn_span - // - // which is totally weird. Instead we want: - // - // fn foo(x: u32) { - // -------------- - // | | - // | x_span - // fn_span - // - // which is...less weird, at least. In fact, in general, if - // the rightmost span overlaps with any other span, we should - // use the "hang below" version, so we can at least make it - // clear where the span *starts*. There's an exception for this - // logic, when the labels do not have a message: - // - // fn foo(x: u32) { - // -------------- - // | - // x_span - // - // instead of: - // - // fn foo(x: u32) { - // -------------- - // | | - // | x_span - // - // - let mut annotations_position = vec![]; - let mut line_len = 0; - let mut p = 0; - for (i, annotation) in annotations.iter().enumerate() { - for (j, next) in annotations.iter().enumerate() { - if overlaps(next, annotation, 0) // This label overlaps with another one and both - && annotation.has_label() // take space (they have text and are not - && j > i // multiline lines). - && p == 0 - // We're currently on the first line, move the label one line down - { - // If we're overlapping with an un-labelled annotation with the same span - // we can just merge them in the output - if next.start_col == annotation.start_col - && next.end_col == annotation.end_col - && !next.has_label() - { - continue; - } - - // This annotation needs a new line in the output. - p += 1; - break; - } - } - annotations_position.push((p, annotation)); - for (j, next) in annotations.iter().enumerate() { - if j > i { - let l = next.label.as_ref().map_or(0, |label| label.len() + 2); - if (overlaps(next, annotation, l) // Do not allow two labels to be in the same - // line if they overlap including padding, to - // avoid situations like: - // - // fn foo(x: u32) { - // -------^------ - // | | - // fn_spanx_span - // - && annotation.has_label() // Both labels must have some text, otherwise - && next.has_label()) // they are not overlapping. - // Do not add a new line if this annotation - // or the next are vertical line placeholders. - || (annotation.takes_space() // If either this or the next annotation is - && next.has_label()) // multiline start/end, move it to a new line - || (annotation.has_label() // so as not to overlap the horizontal lines. - && next.takes_space()) - || (annotation.takes_space() && next.takes_space()) - || (overlaps(next, annotation, l) - && next.end_col <= annotation.end_col - && next.has_label() - && p == 0) - // Avoid #42595. - { - // This annotation needs a new line in the output. - p += 1; - break; - } - } - } - line_len = max(line_len, p); - } - - if line_len != 0 { - line_len += 1; - } - - // If there are no annotations or the only annotations on this line are - // MultilineLine, then there's only code being shown, stop processing. - if line.annotations.iter().all(|a| a.is_line()) { - return vec![]; - } - - // Write the column separator. - // - // After this we will have: - // - // 2 | fn foo() { - // | - // | - // | - // 3 | - // 4 | } - // | - for pos in 0..=line_len { - draw_col_separator(buffer, line_offset + pos + 1, width_offset - 2); - buffer.putc(line_offset + pos + 1, width_offset - 2, '|', Style::LineNumber); - } - - // Write the horizontal lines for multiline annotations - // (only the first and last lines need this). - // - // After this we will have: - // - // 2 | fn foo() { - // | __________ - // | - // | - // 3 | - // 4 | } - // | _ - for &(pos, annotation) in &annotations_position { - let style = if annotation.is_primary { - Style::UnderlinePrimary - } else { - Style::UnderlineSecondary - }; - let pos = pos + 1; - match annotation.annotation_type { - AnnotationType::MultilineStart(depth) | AnnotationType::MultilineEnd(depth) => { - draw_range( - buffer, - '_', - line_offset + pos, - width_offset + depth, - (code_offset + annotation.start_col).saturating_sub(left), - style, - ); - } - _ if self.teach => { - buffer.set_style_range( - line_offset, - (code_offset + annotation.start_col).saturating_sub(left), - (code_offset + annotation.end_col).saturating_sub(left), - style, - annotation.is_primary, - ); - } - _ => {} - } - } - - // Write the vertical lines for labels that are on a different line as the underline. - // - // After this we will have: - // - // 2 | fn foo() { - // | __________ - // | | | - // | | - // 3 | | - // 4 | | } - // | |_ - for &(pos, annotation) in &annotations_position { - let style = if annotation.is_primary { - Style::UnderlinePrimary - } else { - Style::UnderlineSecondary - }; - let pos = pos + 1; - - if pos > 1 && (annotation.has_label() || annotation.takes_space()) { - for p in line_offset + 1..=line_offset + pos { - buffer.putc( - p, - (code_offset + annotation.start_col).saturating_sub(left), - '|', - style, - ); - } - } - match annotation.annotation_type { - AnnotationType::MultilineStart(depth) => { - for p in line_offset + pos + 1..line_offset + line_len + 2 { - buffer.putc(p, width_offset + depth - 1, '|', style); - } - } - AnnotationType::MultilineEnd(depth) => { - for p in line_offset..=line_offset + pos { - buffer.putc(p, width_offset + depth - 1, '|', style); - } - } - _ => (), - } - } - - // Write the labels on the annotations that actually have a label. - // - // After this we will have: - // - // 2 | fn foo() { - // | __________ - // | | - // | something about `foo` - // 3 | - // 4 | } - // | _ test - for &(pos, annotation) in &annotations_position { - let style = - if annotation.is_primary { Style::LabelPrimary } else { Style::LabelSecondary }; - let (pos, col) = if pos == 0 { - (pos + 1, (annotation.end_col + 1).saturating_sub(left)) - } else { - (pos + 2, annotation.start_col.saturating_sub(left)) - }; - if let Some(ref label) = annotation.label { - buffer.puts(line_offset + pos, code_offset + col, &label, style); - } - } - - // Sort from biggest span to smallest span so that smaller spans are - // represented in the output: - // - // x | fn foo() - // | ^^^---^^ - // | | | - // | | something about `foo` - // | something about `fn foo()` - annotations_position.sort_by_key(|(_, ann)| { - // Decreasing order. When annotations share the same length, prefer `Primary`. - (Reverse(ann.len()), ann.is_primary) - }); - - // Write the underlines. - // - // After this we will have: - // - // 2 | fn foo() { - // | ____-_____^ - // | | - // | something about `foo` - // 3 | - // 4 | } - // | _^ test - for &(_, annotation) in &annotations_position { - let (underline, style) = if annotation.is_primary { - ('^', Style::UnderlinePrimary) - } else { - ('-', Style::UnderlineSecondary) - }; - for p in annotation.start_col..annotation.end_col { - buffer.putc( - line_offset + 1, - (code_offset + p).saturating_sub(left), - underline, - style, - ); - } - } - annotations_position - .iter() - .filter_map(|&(_, annotation)| match annotation.annotation_type { - AnnotationType::MultilineStart(p) | AnnotationType::MultilineEnd(p) => { - let style = if annotation.is_primary { - Style::LabelPrimary - } else { - Style::LabelSecondary - }; - Some((p, style)) - } - _ => None, - }) - .collect::>() - } - - fn get_multispan_max_line_num(&mut self, msp: &MultiSpan) -> usize { - let sm = match self.sm { - Some(ref sm) => sm, - None => return 0, - }; - - let mut max = 0; - for primary_span in msp.primary_spans() { - if !primary_span.is_dummy() { - let hi = sm.lookup_char_pos(primary_span.hi()); - max = (hi.line).max(max); - } - } - if !self.short_message { - for span_label in msp.span_labels() { - if !span_label.span.is_dummy() { - let hi = sm.lookup_char_pos(span_label.span.hi()); - max = (hi.line).max(max); - } - } - } - - max - } - - fn get_max_line_num(&mut self, span: &MultiSpan, children: &[SubDiagnostic]) -> usize { - let primary = self.get_multispan_max_line_num(span); - children - .iter() - .map(|sub| self.get_multispan_max_line_num(&sub.span)) - .max() - .unwrap_or(0) - .max(primary) - } - - /// Adds a left margin to every line but the first, given a padding length and the label being - /// displayed, keeping the provided highlighting. - fn msg_to_buffer( - &self, - buffer: &mut StyledBuffer, - msg: &[(String, Style)], - padding: usize, - label: &str, - override_style: Option

`] where `P` is one of the types above + * Does not have a `where Self: Sized` bound (reciever type of `Self` (i.e. `self`) implies this). + * Explicitly non-dispatchable functions require: + * Have a `where Self: Sized` bound (reciever type of `Self` (i.e. `self`) implies this). ```rust # use std::rc::Rc; @@ -325,6 +325,7 @@ fn main() { [RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md [associated items]: associated-items.md [method]: associated-items.md#methods +[supertraits]: #supertraits [implementations]: implementations.md [generics]: generics.md [where clauses]: generics.md#where-clauses diff --git a/src/doc/reference/src/items/type-aliases.md b/src/doc/reference/src/items/type-aliases.md index c471f7a6a8..3d555d5630 100644 --- a/src/doc/reference/src/items/type-aliases.md +++ b/src/doc/reference/src/items/type-aliases.md @@ -3,7 +3,7 @@ > **Syntax**\ > _TypeAlias_ :\ >    `type` [IDENTIFIER] [_GenericParams_]? -> [_WhereClause_]? ( `=` [_Type_] ) `;` +> [_WhereClause_]? ( `=` [_Type_] )? `;` A _type alias_ defines a new name for an existing [type]. Type aliases are declared with the keyword `type`. Every value has a single, specific type, but diff --git a/src/doc/reference/src/keywords.md b/src/doc/reference/src/keywords.md index e303b449e3..67f1089d8c 100644 --- a/src/doc/reference/src/keywords.md +++ b/src/doc/reference/src/keywords.md @@ -95,6 +95,7 @@ The following keywords are reserved beginning in the 2018 edition. These keywords have special meaning only in certain contexts. For example, it is possible to declare a variable or method with the name `union`. +* `macro_rules` is used to create custom [macros]. * `union` is used to declare a [union] and is only a keyword when used in a union declaration. * `'static` is used for the static lifetime and cannot be used as a [generic diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md index 2e91099e74..2ffc05231f 100644 --- a/src/doc/reference/src/linkage.md +++ b/src/doc/reference/src/linkage.md @@ -18,7 +18,8 @@ be ignored in favor of only building the artifacts specified by command line. * `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be produced. This requires that there is a `main` function in the crate which will be run when the program begins executing. This will link in all Rust and - native dependencies, producing a distributable binary. + native dependencies, producing a single distributable binary. + This is the default crate type. * `--crate-type=lib`, `#[crate_type = "lib"]` - A Rust library will be produced. This is an ambiguous concept as to what exactly is produced because a library @@ -33,17 +34,17 @@ be ignored in favor of only building the artifacts specified by command line. be produced. This is different from the `lib` output type in that this forces dynamic library generation. The resulting dynamic library can be used as a dependency for other libraries and/or executables. This output type will - create `*.so` files on linux, `*.dylib` files on osx, and `*.dll` files on - windows. + create `*.so` files on Linux, `*.dylib` files on macOS, and `*.dll` files on + Windows. * `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system library will be produced. This is different from other library outputs in that the compiler will never attempt to link to `staticlib` outputs. The purpose of this output type is to create a static library containing all of - the local crate's code along with all upstream dependencies. The static - library is actually a `*.a` archive on linux and osx and windows(MinGW), and - a `*.lib` file on windows(MSVC). This format is recommended for use in - situations such as linking Rust code into an existing non-Rust application + the local crate's code along with all upstream dependencies. This output type + will create `*.a` files on Linux, macOS and Windows (MinGW), and `*.lib` files + on Windows (MSVC). This format is recommended for use in situations such as + linking Rust code into an existing non-Rust application because it will not have dynamic dependencies on other Rust code. * `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system diff --git a/src/doc/reference/src/macros-by-example.md b/src/doc/reference/src/macros-by-example.md index e97455d0b2..2682059dda 100644 --- a/src/doc/reference/src/macros-by-example.md +++ b/src/doc/reference/src/macros-by-example.md @@ -122,7 +122,7 @@ fragment specifiers are: * `block`: a [_BlockExpression_] * `stmt`: a [_Statement_] without the trailing semicolon (except for item statements that require semicolons) - * `pat`: a [_Pattern_] + * `pat`: a [_PatternNoTopAlt_] * `expr`: an [_Expression_] * `ty`: a [_Type_] * `ident`: an [IDENTIFIER_OR_KEYWORD] @@ -174,9 +174,9 @@ compiler knows how to expand them properly: 2. Each repetition in the transcriber must contain at least one metavariable to decide how many times to expand it. If multiple metavariables appear in the same repetition, they must be bound to the same number of fragments. For - instance, `( $( $i:ident ),* ; $( $j:ident ),* ) =>( $( ($i,$j) ),*` must + instance, `( $( $i:ident ),* ; $( $j:ident ),* ) => (( $( ($i,$j) ),* ))` must bind the same number of `$i` fragments as `$j` fragments. This means that - invoking the macro with `(a, b, c; d, e, f`) is legal and expands to + invoking the macro with `(a, b, c; d, e, f)` is legal and expands to `((a,d), (b,e), (c,f))`, but `(a, b, c; d, e)` is illegal because it does not have the same number. This requirement applies to every layer of nested repetitions. @@ -488,7 +488,7 @@ For more detail, see the [formal specification]. [_Item_]: items.md [_LiteralExpression_]: expressions/literal-expr.md [_MetaListIdents_]: attributes.md#meta-item-attribute-syntax -[_Pattern_]: patterns.md +[_PatternNoTopAlt_]: patterns.md [_Statement_]: statements.md [_TokenTree_]: macros.md#macro-invocation [_Token_]: tokens.md diff --git a/src/doc/reference/src/patterns.md b/src/doc/reference/src/patterns.md index 121b825d13..7676d5255b 100644 --- a/src/doc/reference/src/patterns.md +++ b/src/doc/reference/src/patterns.md @@ -2,6 +2,9 @@ > **Syntax**\ > _Pattern_ :\ +>       `|`? _PatternNoTopAlt_ ( `|` _PatternNoTopAlt_ )\* +> +> _PatternNoTopAlt_ :\ >       _PatternWithoutRange_\ >    | [_RangePattern_] > @@ -756,6 +759,63 @@ Path patterns are irrefutable when they refer to structs or an enum variant when has only one variant or a constant whose type is irrefutable. They are refutable when they refer to refutable constants or enum variants for enums with multiple variants. +## Or-patterns + +_Or-patterns_ are patterns that match on one of two or more sub-patterns (e.g. +`A | B | C`). They can nest arbitrarily. Syntactically, or-patterns are allowed +in any of the places where other patterns are allowed (represented by the +_Pattern_ production), with the exceptions of `let`-bindings and function and +closure arguments (represented by the _PatternNoTopAlt_ production). + +### Static semantics + +1. Given a pattern `p | q` at some depth for some arbitrary patterns `p` and `q`, + the pattern is considered ill-formed if: + + + the type inferred for `p` does not unify with the type inferred for `q`, or + + the same set of bindings are not introduced in `p` and `q`, or + + the type of any two bindings with the same name in `p` and `q` do not unify + with respect to types or binding modes. + + Unification of types is in all instances aforementioned exact and + implicit [type coercions] do not apply. + +2. When type checking an expression `match e_s { a_1 => e_1, ... a_n => e_n }`, + for each match arm `a_i` which contains a pattern of form `p_i | q_i`, + the pattern `p_i | q_i` is considered ill formed if, + at the depth `d` where it exists the fragment of `e_s` at depth `d`, + the type of the expression fragment does not unify with `p_i | q_i`. + +3. With respect to exhaustiveness checking, a pattern `p | q` is + considered to cover `p` as well as `q`. For some constructor `c(x, ..)` + the distributive law applies such that `c(p | q, ..rest)` covers the same + set of value as `c(p, ..rest) | c(q, ..rest)` does. This can be applied + recursively until there are no more nested patterns of form `p | q` other + than those that exist at the top level. + + Note that by *"constructor"* we do not refer to tuple struct patterns, + but rather we refer to a pattern for any product type. + This includes enum variants, tuple structs, structs with named fields, + arrays, tuples, and slices. + +### Dynamic semantics + +1. The dynamic semantics of pattern matching a scrutinee expression `e_s` + against a pattern `c(p | q, ..rest)` at depth `d` where `c` is some constructor, + `p` and `q` are arbitrary patterns, and `rest` is optionally any remaining + potential factors in `c`, is defined as being the same as that of + `c(p, ..rest) | c(q, ..rest)`. + +### Precedence with other undelimited patterns + +As shown elsewhere in this chapter, there are several types of patterns that +are syntactically undelimited, including identifier patterns, reference +patterns, and or-patterns. Or-patterns always have the lowest-precedence. This +allows us to reserve syntactic space for a possible future type ascription +feature and also to reduce ambiguity. For example, `x @ A(..) | B(..)` will +result in an error that `x` is not bound in all patterns, `&A(x) | B(x)` will +result in a type mismatch between `x` in the different subpatterns. + [_GroupedPattern_]: #grouped-patterns [_IdentifierPattern_]: #identifier-patterns [_LiteralPattern_]: #literal-patterns @@ -782,3 +842,4 @@ refer to refutable constants or enum variants for enums with multiple variants. [structs]: items/structs.md [tuples]: types/tuple.md [scrutinee]: glossary.md#scrutinee +[type coercions]: type-coercions.md diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md index 5d8e0e95d7..06cd9513e5 100644 --- a/src/doc/reference/src/statements.md +++ b/src/doc/reference/src/statements.md @@ -53,7 +53,7 @@ fn outer() { > **Syntax**\ > _LetStatement_ :\ ->    [_OuterAttribute_]\* `let` [_Pattern_] +>    [_OuterAttribute_]\* `let` [_PatternNoTopAlt_] > ( `:` [_Type_] )? (`=` [_Expression_] )? `;` A *`let` statement* introduces a new set of [variables], given by an @@ -133,5 +133,5 @@ statement are [`cfg`], and [the lint check attributes]. [_LetStatement_]: #let-statements [_MacroInvocationSemi_]: macros.md#macro-invocation [_OuterAttribute_]: attributes.md -[_Pattern_]: patterns.md +[_PatternNoTopAlt_]: patterns.md [_Type_]: types.md diff --git a/src/doc/reference/src/types/pointer.md b/src/doc/reference/src/types/pointer.md index 7cbb1f1738..47bda4f82d 100644 --- a/src/doc/reference/src/types/pointer.md +++ b/src/doc/reference/src/types/pointer.md @@ -1,7 +1,7 @@ # Pointer types -All pointers in Rust are explicit first-class values. They can be moved or -copied, stored into data structs, and returned from functions. +All pointers in Rust are explicit first-class values. +They can be moved or copied, stored into data structs, and returned from functions. ## References (`&` and `&mut`) @@ -11,21 +11,20 @@ copied, stored into data structs, and returned from functions. ### Shared references (`&`) -These point to memory _owned by some other value_. When a shared reference to -a value is created it prevents direct mutation of the value. [Interior -mutability] provides an exception for this in certain circumstances. As the -name suggests, any number of shared references to a value may exist. A shared -reference type is written `&type`, or `&'a type` when you need to specify an -explicit lifetime. Copying a reference is a "shallow" operation: it involves -only copying the pointer itself, that is, pointers are `Copy`. Releasing a -reference has no effect on the value it points to, but referencing of a -[temporary value] will keep it alive during the scope of the reference itself. +These point to memory _owned by some other value_. +When a shared reference to a value is created it prevents direct mutation of the value. +[Interior mutability] provides an exception for this in certain circumstances. +As the name suggests, any number of shared references to a value may exist. +A shared reference type is written `&type`, or `&'a type` when you need to specify an explicit lifetime. +Copying a reference is a "shallow" operation: +it involves only copying the pointer itself, that is, pointers are `Copy`. +Releasing a reference has no effect on the value it points to, but referencing of a [temporary value] will keep it alive during the scope of the reference itself. ### Mutable references (`&mut`) -These also point to memory owned by some other value. A mutable reference type -is written `&mut type` or `&'a mut type`. A mutable reference (that hasn't been -borrowed) is the only way to access the value it points to, so is not `Copy`. +These also point to memory owned by some other value. +A mutable reference type is written `&mut type` or `&'a mut type`. +A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`. ## Raw pointers (`*const` and `*mut`) @@ -33,24 +32,26 @@ borrowed) is the only way to access the value it points to, so is not `Copy`. > _RawPointerType_ :\ >    `*` ( `mut` | `const` ) [_TypeNoBounds_] -Raw pointers are pointers without safety or liveness guarantees. Raw pointers -are written as `*const T` or `*mut T`, for example `*const i32` means a raw -pointer to a 32-bit integer. Copying or dropping a raw pointer has no effect -on the lifecycle of any other value. Dereferencing a raw pointer is an -[`unsafe` operation], this can also be used to convert a raw pointer to a -reference by reborrowing it (`&*` or `&mut *`). Raw pointers are generally -discouraged in Rust code; they exist to support interoperability with foreign -code, and writing performance-critical or low-level functions. +Raw pointers are pointers without safety or liveness guarantees. +Raw pointers are written as `*const T` or `*mut T`. +For example `*const i32` means a raw pointer to a 32-bit integer. +Copying or dropping a raw pointer has no effect on the lifecycle of any other value. +Dereferencing a raw pointer is an [`unsafe` operation]. +This can also be used to convert a raw pointer to a reference by reborrowing it (`&*` or `&mut *`). +Raw pointers are generally discouraged in Rust code; +they exist to support interoperability with foreign code, and writing performance-critical or low-level functions. -When comparing raw pointers they are compared by their address, rather than by -what they point to. When comparing raw pointers to [dynamically sized types] they -also have their additional data compared. +When comparing raw pointers they are compared by their address, rather than by what they point to. +When comparing raw pointers to [dynamically sized types] they also have their additional data compared. + +Raw pointers can be created directly using [`core::ptr::addr_of!`] for `*const` pointers and [`core::ptr::addr_of_mut!`] for `*mut` pointers. ## Smart Pointers -The standard library contains additional 'smart pointer' types beyond references -and raw pointers. +The standard library contains additional 'smart pointer' types beyond references and raw pointers. +[`core::ptr::addr_of!`]: ../../core/ptr/macro.addr_of.html +[`core::ptr::addr_of_mut!`]: ../../core/ptr/macro.addr_of_mut.html [Interior mutability]: ../interior-mutability.md [_Lifetime_]: ../trait-bounds.md [_TypeNoBounds_]: ../types.md#type-expressions diff --git a/src/doc/reference/src/types/tuple.md b/src/doc/reference/src/types/tuple.md index bfef430531..3877a2672f 100644 --- a/src/doc/reference/src/types/tuple.md +++ b/src/doc/reference/src/types/tuple.md @@ -5,21 +5,24 @@ >       `(` `)`\ >    | `(` ( [_Type_] `,` )+ [_Type_]? `)` -The *tuple type* is a structural type[^1] for heterogeneous lists of other -types. Each entry in the list is an *element*[^2] of the tuple. The position of -the element makes it the *nth element* using zero (`0`) as the initial index. +*Tuple types* are a family of structural types[^1] for heterogeneous lists of other types. -The number of elements determines the arity of the tuple. A tuple with `n` -elements is called an `n-ary tuple`. For example, a tuple with 2 elements is a -2-ary tuple. +The syntax for a tuple type is a parenthesized, comma-separated list of types. +1-ary tuples require a comma after their element type to be disambiguated with a [parenthesized type]. -For convenience and historical reasons, the tuple type with no elements (`()`) -is often called *unit* or *the unit type*. It's one value is also called *unit* -or *the unit value*. +A tuple type has a number of fields equal to the length of the list of types. +This number of fields determines the *arity* of the tuple. +A tuple with `n` fields is called an *n-ary tuple*. +For example, a tuple with 2 fields is a 2-ary tuple. -Tuple types are written by listing the types of their elements in a -parenthesized, comma-separated list. 1-ary tuples require a comma after their -element type to be disambiguated with a [parenthesized type]. +Fields of tuples are named using increasing numeric names matching their position in the list of types. +The first field is `0`. +The second field is `1`. +And so on. +The type of each field is the type of the same position in the tuple's list of types. + +For convenience and historical reasons, the tuple type with no fields (`()`) is often called *unit* or *the unit type*. +It's one value is also called *unit* or *the unit value*. Some examples of tuple types: @@ -29,16 +32,12 @@ Some examples of tuple types: * `(i32, String)` (different type from the previous example) * `(i32, f64, Vec, Option)` -Values of this type are constructed using a [tuple expression]. Furthermore, -various expressions will produce the unit value if there is no other meaningful -value for it to evaluate to. Tuple elements can be accessed by either a [tuple -index expression] or [pattern matching]. - -[^1]: Structural types are always equivalent if their internal types are - equivalent. For a nominal version of tuples, see [tuple structs]. +Values of this type are constructed using a [tuple expression]. +Furthermore, various expressions will produce the unit value if there is no other meaningful value for it to evaluate to. +Tuple fields can be accessed by either a [tuple index expression] or [pattern matching]. -[^2]: Element is equivalent to field, except numerical indexes instead of - identifiers +[^1]: Structural types are always equivalent if their internal types are equivalent. + For a nominal version of tuples, see [tuple structs]. [_Type_]: ../types.md#type-expressions [parenthesized type]: ../types.md#parenthesized-types diff --git a/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md b/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md index 84855d1c54..b07adecf6b 100644 --- a/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md +++ b/src/doc/rust-by-example/src/custom_types/enum/testcase_linked_list.md @@ -32,6 +32,9 @@ impl List { // depends on the variant of `self` // `self` has type `&List`, and `*self` has type `List`, matching on a // concrete type `T` is preferred over a match on a reference `&T` + // after Rust 2018 you can use self here and tail (with no ref) below as well, + // rust will infer &s and ref tail. + // See https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/default-match-bindings.html match *self { // Can't take ownership of the tail, because `self` is borrowed; // instead take a reference to the tail diff --git a/src/doc/rust-by-example/src/custom_types/structs.md b/src/doc/rust-by-example/src/custom_types/structs.md index 0dfc261292..227a261fb5 100644 --- a/src/doc/rust-by-example/src/custom_types/structs.md +++ b/src/doc/rust-by-example/src/custom_types/structs.md @@ -3,8 +3,7 @@ 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 @@ -86,7 +85,7 @@ fn main() { ### Activity -1. Add a function `rect_area` which calculates the area of a rectangle (try +1. Add a function `rect_area` which calculates the area of a `Rectangle` (try using nested destructuring). 2. Add a function `square` which takes a `Point` and a `f32` as arguments, and returns a `Rectangle` with its lower left corner on the point, and a width and diff --git a/src/doc/rust-by-example/src/error/option_unwrap.md b/src/doc/rust-by-example/src/error/option_unwrap.md index df02b8c113..5192767fcc 100644 --- a/src/doc/rust-by-example/src/error/option_unwrap.md +++ b/src/doc/rust-by-example/src/error/option_unwrap.md @@ -1,13 +1,13 @@ # `Option` & `unwrap` In the last example, we showed that we can induce program failure at will. -We told our program to `panic` if the royal received an inappropriate -gift - a snake. But what if the royal expected a gift and didn't receive -one? That case would be just as bad, so it needs to be handled! +We told our program to `panic` if we drink a sugary lemonade. +But what if we expect _some_ drink but don't receive one? +That case would be just as bad, so it needs to be handled! -We *could* test this against the null string (`""`) as we do with a snake. +We *could* test this against the null string (`""`) as we do with a lemonade. Since we're using Rust, let's instead have the compiler point out cases -where there's no gift. +where there's no drink. An `enum` called `Option` in the `std` library is used when absence is a possibility. It manifests itself as one of two "options": @@ -24,41 +24,41 @@ handling. In the following example, explicit handling yields a more controlled result while retaining the option to `panic` if desired. ```rust,editable,ignore,mdbook-runnable -// The commoner has seen it all, and can handle any gift well. -// All gifts are handled explicitly using `match`. -fn give_commoner(gift: Option<&str>) { +// The adult has seen it all, and can handle any drink well. +// All drinks are handled explicitly using `match`. +fn give_adult(drink: Option<&str>) { // Specify a course of action for each case. - match gift { - Some("snake") => println!("Yuck! I'm putting this snake back in the forest."), + match drink { + Some("lemonade") => println!("Yuck! Too sugary."), Some(inner) => println!("{}? How nice.", inner), - None => println!("No gift? Oh well."), + None => println!("No drink? Oh well."), } } -// Our sheltered royal will `panic` at the sight of snakes. -// All gifts are handled implicitly using `unwrap`. -fn give_royal(gift: Option<&str>) { +// Others will `panic` before drinking sugary drinks. +// All drinks are handled implicitly using `unwrap`. +fn drink(drink: Option<&str>) { // `unwrap` returns a `panic` when it receives a `None`. - let inside = gift.unwrap(); - if inside == "snake" { panic!("AAAaaaaa!!!!"); } + let inside = drink.unwrap(); + if inside == "lemonade" { panic!("AAAaaaaa!!!!"); } println!("I love {}s!!!!!", inside); } fn main() { - let food = Some("cabbage"); - let snake = Some("snake"); + let water = Some("water"); + let lemonade = Some("lemonade"); let void = None; - give_commoner(food); - give_commoner(snake); - give_commoner(void); + give_adult(water); + give_adult(lemonade); + give_adult(void); - let bird = Some("robin"); + let coffee = Some("coffee"); let nothing = None; - give_royal(bird); - give_royal(nothing); + drink(coffee); + drink(nothing); } ``` diff --git a/src/doc/rust-by-example/src/expression.md b/src/doc/rust-by-example/src/expression.md index 467bc10646..27a278d027 100644 --- a/src/doc/rust-by-example/src/expression.md +++ b/src/doc/rust-by-example/src/expression.md @@ -2,7 +2,7 @@ A Rust program is (mostly) made up of a series of statements: -``` +```rust,editable fn main() { // statement // statement @@ -13,7 +13,7 @@ fn main() { There are a few kinds of statements in Rust. The most common two are declaring a variable binding, and using a `;` with an expression: -``` +```rust,editable fn main() { // variable binding let x = 5; diff --git a/src/doc/rust-by-example/src/generics/multi_bounds.md b/src/doc/rust-by-example/src/generics/multi_bounds.md index 5f51a6c24b..969ba6417e 100644 --- a/src/doc/rust-by-example/src/generics/multi_bounds.md +++ b/src/doc/rust-by-example/src/generics/multi_bounds.md @@ -1,6 +1,6 @@ # Multiple bounds -Multiple bounds can be applied with a `+`. Like normal, different types are +Multiple bounds for a single type can be applied with a `+`. Like normal, different types are separated with `,`. ```rust,editable diff --git a/src/doc/rust-by-example/src/generics/new_types.md b/src/doc/rust-by-example/src/generics/new_types.md index ccbbbb03cf..c819002c28 100644 --- a/src/doc/rust-by-example/src/generics/new_types.md +++ b/src/doc/rust-by-example/src/generics/new_types.md @@ -40,13 +40,14 @@ fn main() { Uncomment the last print statement to observe that the type supplied must be `Years`. -To obtain the `newtype`'s value as the base type, you may use tuple syntax like so: +To obtain the `newtype`'s value as the base type, you may use the tuple or destructuring syntax like so: ```rust, editable struct Years(i64); fn main() { let years = Years(42); - let years_as_primitive: i64 = years.0; + let years_as_primitive_1: i64 = years.0; // Tuple + let Years(years_as_primitive_2) = years; // Destructuring } ``` diff --git a/src/doc/rust-by-example/src/hello/print/print_display.md b/src/doc/rust-by-example/src/hello/print/print_display.md index 1ff31f27ac..fdae9648a9 100644 --- a/src/doc/rust-by-example/src/hello/print/print_display.md +++ b/src/doc/rust-by-example/src/hello/print/print_display.md @@ -108,7 +108,7 @@ each requires its own implementation. This is detailed further in ### Activity After checking the output of the above example, use the `Point2D` struct as a -guide to add a Complex struct to the example. When printed in the same +guide to add a `Complex` struct to the example. When printed in the same way, the output should be: ```txt @@ -125,5 +125,5 @@ Debug: Complex { real: 3.3, imag: 7.2 } [fmt]: https://doc.rust-lang.org/std/fmt/ [macros]: ../../macros.md [structs]: ../../custom_types/structs.md -[traits]: ../../trait.md +[traits]: https://doc.rust-lang.org/std/fmt/#formatting-traits [use]: ../../mod/use.md diff --git a/src/doc/rust-by-example/src/primitives/tuples.md b/src/doc/rust-by-example/src/primitives/tuples.md index 7e29ef22c7..82f4083fc9 100644 --- a/src/doc/rust-by-example/src/primitives/tuples.md +++ b/src/doc/rust-by-example/src/primitives/tuples.md @@ -64,7 +64,7 @@ fn main() { ### Activity - 1. *Recap*: Add the `fmt::Display` trait to the Matrix `struct` in the above example, + 1. *Recap*: Add the `fmt::Display` trait to the `Matrix` struct in the above example, so that if you switch from printing the debug format `{:?}` to the display format `{}`, you see the following output: diff --git a/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md b/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md index c9a9d095c8..3f31693faa 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md +++ b/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md @@ -85,7 +85,7 @@ fn main() { print_it(i); // oops, &i only has the lifetime defined by the scope of - // use_it(), so it's not 'static: + // main(), so it's not 'static: print_it(&i); } ``` diff --git a/src/doc/rust-by-example/src/scope/lifetime/trait.md b/src/doc/rust-by-example/src/scope/lifetime/trait.md index 0f56f5b4c1..3c26df1194 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/trait.md +++ b/src/doc/rust-by-example/src/scope/lifetime/trait.md @@ -6,9 +6,9 @@ Note that `impl` may have annotation of lifetimes too. ```rust,editable // A struct with annotation of lifetimes. #[derive(Debug)] - struct Borrowed<'a> { - x: &'a i32, - } +struct Borrowed<'a> { + x: &'a i32, +} // Annotate lifetimes to impl. impl<'a> Default for Borrowed<'a> { diff --git a/src/doc/rust-by-example/src/scope/move/partial_move.md b/src/doc/rust-by-example/src/scope/move/partial_move.md index 7afa7e5419..98c6c8dc81 100644 --- a/src/doc/rust-by-example/src/scope/move/partial_move.md +++ b/src/doc/rust-by-example/src/scope/move/partial_move.md @@ -1,11 +1,12 @@ # Partial moves -Pattern bindings can have `by-move` and `by-reference` bindings at -the same time which is used in [destructuring]. Using these pattern -will result in partial move for the variable, which means that part -of the variable is moved while other parts stayed. In this case, the -parent variable cannot be used afterwards as a whole. However, parts -of it that are referenced and not moved can be used. +Within the [destructuring] of a single variable, both `by-move` and +`by-reference` pattern bindings can be used at the same time. Doing +this will result in a _partial move_ of the variable, which means +that parts of the variable will be moved while other parts stay. In +such a case, the parent variable cannot be used afterwards as a +whole, however the parts that are only referenced (and not moved) +can still be used. ```rust,editable fn main() { @@ -37,4 +38,4 @@ fn main() { ### See also: [destructuring][destructuring] -[destructuring]: ../../flow_control/match/destructuring.md \ No newline at end of file +[destructuring]: ../../flow_control/match/destructuring.md diff --git a/src/doc/rust-by-example/src/std/result/question_mark.md b/src/doc/rust-by-example/src/std/result/question_mark.md index c51cc638f6..a1f7706840 100644 --- a/src/doc/rust-by-example/src/std/result/question_mark.md +++ b/src/doc/rust-by-example/src/std/result/question_mark.md @@ -54,7 +54,7 @@ mod checked { pub fn op(x: f64, y: f64) { match op_(x, y) { - Err(why) => panic!(match why { + Err(why) => panic!("{}", match why { MathError::NonPositiveLogarithm => "logarithm of non-positive number", MathError::DivisionByZero diff --git a/src/doc/rust-by-example/src/trait/iter.md b/src/doc/rust-by-example/src/trait/iter.md index 9c9540985b..2af4fcb784 100644 --- a/src/doc/rust-by-example/src/trait/iter.md +++ b/src/doc/rust-by-example/src/trait/iter.md @@ -18,13 +18,16 @@ struct Fibonacci { // Implement `Iterator` for `Fibonacci`. // The `Iterator` trait only requires a method to be defined for the `next` element. impl Iterator for Fibonacci { + // We can refer to this type using Self::Item type Item = u32; // Here, we define the sequence using `.curr` and `.next`. // The return type is `Option`: // * When the `Iterator` is finished, `None` is returned. // * Otherwise, the next value is wrapped in `Some` and returned. - fn next(&mut self) -> Option { + // We use Self::Item in the return type, so we can change + // the type without having to update the function signatures. + fn next(&mut self) -> Option { let new_next = self.curr + self.next; self.curr = self.next; diff --git a/src/doc/rust-by-example/src/types/cast.md b/src/doc/rust-by-example/src/types/cast.md index 2ca18c1784..79e070d375 100644 --- a/src/doc/rust-by-example/src/types/cast.md +++ b/src/doc/rust-by-example/src/types/cast.md @@ -22,7 +22,8 @@ fn main() { let integer = decimal as u8; let character = integer as char; - // Error! There are limitations in conversion rules. A float cannot be directly converted to a char. + // Error! There are limitations in conversion rules. + // A float cannot be directly converted to a char. let character = decimal as char; // FIXME ^ Comment out this line @@ -60,8 +61,10 @@ fn main() { // and the two's complement of 232 is -24 println!(" 232 as a i8 is : {}", 232 as i8); - // Since Rust 1.45, the `as` keyword performs a *saturating cast* when casting from float to int. - // If the floating point value exceeds the upper bound or is less than the lower bound, the returned value will be equal to the bound crossed. + // Since Rust 1.45, the `as` keyword performs a *saturating cast* + // when casting from float to int. If the floating point value exceeds + // the upper bound or is less than the lower bound, the returned value + // will be equal to the bound crossed. // 300.0 is 255 println!("300.0 is {}", 300.0_f32 as u8); @@ -70,7 +73,9 @@ fn main() { // nan as u8 is 0 println!("nan as u8 is {}", f32::NAN as u8); - // This behavior incures a small runtime cost and can be avoided with unsafe methods, however the results might overflow and return **unsound values**. Use these methods wisely: + // This behavior incurs a small runtime cost and can be avoided + // with unsafe methods, however the results might overflow and + // return **unsound values**. Use these methods wisely: unsafe { // 300.0 is 44 println!("300.0 is {}", 300.0_f32.to_int_unchecked::()); diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index c3307bb74d..a2b9cc30d7 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -11,6 +11,7 @@ on: jobs: ci: + if: github.repository == 'rust-lang/rustc-dev-guide' runs-on: ubuntu-latest env: MDBOOK_VERSION: 0.4.7 @@ -63,7 +64,7 @@ jobs: run: mdbook build - name: Deploy to gh-pages - if: github.event_name == 'push' && github.repository == 'rust-lang/rustc-dev-guide' + if: github.event_name == 'push' run: | touch "${{ env.DEPLOY_DIR }}/.nojekyll" cp CNAME "${{ env.DEPLOY_DIR }}" diff --git a/src/doc/rustc-dev-guide/.github/workflows/date-check.yml b/src/doc/rustc-dev-guide/.github/workflows/date-check.yml index 4111172358..c787da0712 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/date-check.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/date-check.yml @@ -10,6 +10,7 @@ on: jobs: date-check: + if: github.repository == 'rust-lang/rustc-dev-guide' runs-on: ubuntu-latest steps: diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index 4595643640..99502bcc66 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -1,4 +1,4 @@ -[![Travis CI badge](https://api.travis-ci.com/rust-lang/rustc-dev-guide.svg?branch=master)](https://travis-ci.com/github/rust-lang/rustc-dev-guide) +[![CI](https://github.com/rust-lang/rustc-dev-guide/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-lang/rustc-dev-guide/actions/workflows/ci.yml) This is a collaborative effort to build a guide that explains how rustc diff --git a/src/doc/rustc-dev-guide/ci/linkcheck.sh b/src/doc/rustc-dev-guide/ci/linkcheck.sh index 8848235480..5d49d13372 100755 --- a/src/doc/rustc-dev-guide/ci/linkcheck.sh +++ b/src/doc/rustc-dev-guide/ci/linkcheck.sh @@ -28,4 +28,4 @@ else # running locally echo "Checking files changed in $COMMIT_RANGE: $CHANGED_FILES" fi -exec mdbook-linkcheck $FLAGS -- $TRAVIS_BUILD_DIR +exec mdbook-linkcheck $FLAGS diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index f01072b7be..51af6f5aab 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -3,6 +3,8 @@ // NOTE: For the example to compile, you will need to first run the following: // rustup component add rustc-dev +// version: 1.53.0-nightly (9b0edb7fd 2021-03-27) + extern crate rustc_error_codes; extern crate rustc_errors; extern crate rustc_hash; @@ -46,8 +48,9 @@ fn main() { diagnostic_output: rustc_session::DiagnosticOutput::Default, // Set to capture stderr output during compiler execution stderr: None, // Option>>> - crate_name: None, // Option lint_caps: FxHashMap::default(), // FxHashMap + // This is a callback from the driver that is called when [`ParseSess`] is created. + parse_sess_created: None, //Option> // This is a callback from the driver that is called when we're registering lints; // it is called during plugin registration when we have the LintStore in a non-shared state. // @@ -61,6 +64,7 @@ fn main() { override_queries: None, // Option, &mut ty::query::Providers<'_>)> // Registry of diagnostics codes. registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS), + make_codegen_backend: None, }; rustc_interface::run_compiler(config, |compiler| { compiler.enter(|queries| { @@ -73,7 +77,7 @@ fn main() { match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { let name = item.ident; - let ty = tcx.type_of(tcx.hir().local_def_id(item.hir_id)); + let ty = tcx.type_of(tcx.hir().local_def_id(item.hir_id())); println!("{:?}:\t{:?}", name, ty) } _ => (), diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs index e1caab326b..ee9a20c059 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs @@ -3,6 +3,8 @@ // NOTE: For the example to compile, you will need to first run the following: // rustup component add rustc-dev +// version: 1.53.0-nightly (9b0edb7fd 2021-03-27) + extern crate rustc_error_codes; extern crate rustc_errors; extern crate rustc_hash; @@ -68,11 +70,12 @@ fn main() { output_file: None, file_loader: None, stderr: None, - crate_name: None, lint_caps: rustc_hash::FxHashMap::default(), + parse_sess_created: None, register_lints: None, override_queries: None, registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS), + make_codegen_backend: None, }; rustc_interface::run_compiler(config, |compiler| { compiler.enter(|queries| { diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 8ee38206f7..2c75334980 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -3,6 +3,8 @@ // NOTE: For the example to compile, you will need to first run the following: // rustup component add rustc-dev llvm-tools-preview +// version: 1.53.0-nightly (9b0edb7fd 2021-03-27) + extern crate rustc_ast_pretty; extern crate rustc_error_codes; extern crate rustc_errors; @@ -15,8 +17,6 @@ extern crate rustc_span; use rustc_ast_pretty::pprust::item_to_string; use rustc_errors::registry; use rustc_session::config; -use rustc_session::config::PpMode::PpmSource; -use rustc_session::config::PpSourceMode::PpmExpanded; use rustc_span::source_map; use std::path; use std::process; @@ -46,8 +46,8 @@ fn main() { output_file: None, file_loader: None, stderr: None, - crate_name: None, lint_caps: rustc_hash::FxHashMap::default(), + parse_sess_created: None, register_lints: None, override_queries: None, make_codegen_backend: None, @@ -57,8 +57,7 @@ fn main() { compiler.enter(|queries| { // TODO: add this to -Z unpretty let ast_krate = queries.parse().unwrap().take(); - let ast_krate_mod = ast_krate.module; - for item in ast_krate_mod.items { + for item in ast_krate.items { println!("{}", item_to_string(&item)); } @@ -75,7 +74,7 @@ fn main() { if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind { if let Some(expr) = local.init { let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!" - let def_id = tcx.hir().local_def_id(item.hir_id); // def_id identifies the main function + let def_id = tcx.hir().local_def_id(item.hir_id()); // def_id identifies the main function let ty = tcx.typeck(def_id).node_type(hir_id); println!("{:?}: {:?}", expr, ty); // prints expr(HirId { owner: DefIndex(3), local_id: 4 }: "Hello, world!"): &'static str } diff --git a/src/doc/rustc-dev-guide/src/appendix/bibliography.md b/src/doc/rustc-dev-guide/src/appendix/bibliography.md index c8b4a23b34..0caed3fafb 100644 --- a/src/doc/rustc-dev-guide/src/appendix/bibliography.md +++ b/src/doc/rustc-dev-guide/src/appendix/bibliography.md @@ -89,3 +89,4 @@ Rust, as well as publications about Rust. * [The Case for Writing a Kernel in Rust](https://www.tockos.org/assets/papers/rust-kernel-apsys2017.pdf) * [RustBelt: Securing the Foundations of the Rust Programming Language](https://plv.mpi-sws.org/rustbelt/popl18/) * [Oxide: The Essence of Rust](https://arxiv.org/abs/1903.00982). By Aaron Weiss, Olek Gierczak, Daniel Patterson, Nicholas D. Matsakis, and Amal Ahmed. +* [Polymorphisation: Improving Rust compilation times through intelligent monomorphisation](https://davidtw.co/media/masters_dissertation.pdf). David Wood's master's thesis. diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index a9c3b45c41..9deff62dd6 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -67,7 +67,7 @@ Example PRs look like: ## Feature updates > Note that this information is as of the time of this writing (December 2018). The process for updating LLVM changes with +2021-04 --> (April 2021). The process for updating LLVM changes with practically all LLVM updates, so this may be out of date! Unlike bugfixes, updating to pick up a new feature of LLVM typically requires a @@ -75,7 +75,7 @@ lot more work. This is where we can't reasonably cherry-pick commits backwards so we need to do a full update. There's a lot of stuff to do here, so let's go through each in detail. -1. Create a new branch in the rust-lang/llvm-project repository. This branch +1. Create a new branch in the [rust-lang/llvm-project repository]. This branch should be named `rustc/a.b-yyyy-mm-dd` where `a.b` is the current version number of LLVM in-tree at the time of the branch and the remaining part is today's date. Move this branch to the commit in LLVM that you'd like, which @@ -119,12 +119,12 @@ through each in detail. Ideally, build LLVM and test it on a few platforms: * Linux - * OSX + * macOS * Windows and afterwards run some docker containers that CI also does: - * `./src/ci/docker/run.sh wasm32-unknown` + * `./src/ci/docker/run.sh wasm32` * `./src/ci/docker/run.sh arm-android` * `./src/ci/docker/run.sh dist-various-1` * `./src/ci/docker/run.sh dist-various-2` @@ -136,15 +136,17 @@ through each in detail. `src/llvm-project` and will likely also change [`llvm-wrapper`] as well. For prior art, previous LLVM updates look like -[#55835](https://github.com/rust-lang/rust/pull/55835) -[#47828](https://github.com/rust-lang/rust/pull/47828) [#62474](https://github.com/rust-lang/rust/pull/62474) -[#62592](https://github.com/rust-lang/rust/pull/62592). Note that sometimes it's +[#62592](https://github.com/rust-lang/rust/pull/62592) +[#67759](https://github.com/rust-lang/rust/pull/67759) +[#73526](https://github.com/rust-lang/rust/pull/73526) +[#81451](https://github.com/rust-lang/rust/pull/81451). Note that sometimes it's easiest to land [`llvm-wrapper`] compatibility as a PR before actually updating `src/llvm-project`. This way while you're working through LLVM issues others interested in trying out the new LLVM can benefit from work you've done to update the C++ bindings. +[rust-lang/llvm-project repository]: https://github.com/rust-lang/llvm-project [`llvm-wrapper`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_llvm/llvm-wrapper ### Caveats and gotchas @@ -155,10 +157,12 @@ keep in mind while going through them: * LLVM bugs are hard to find, don't hesitate to ask for help! Bisection is definitely your friend here (yes LLVM takes forever to build, yet bisection is still your friend) -* If you've got general questions, @alexcrichton can help you out. +* If you've got general questions, [wg-llvm] can help you out. * Creating branches is a privileged operation on GitHub, so you'll need someone with write access to create the branches for you most likely. +[wg-llvm]: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm + ## New LLVM Release Updates Updating to a new release of LLVM is very similar to the "feature updates" diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index a97568e6eb..49c2e8b664 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -20,19 +20,16 @@ cd rust ## Create a `config.toml` -To start, copy [`config.toml.example`] to `config.toml`: +To start, run `x.py setup`. This will create a `config.toml` with reasonable defaults. -[`config.toml.example`]: https://github.com/rust-lang/rust/blob/master/config.toml.example - -```bash -cp config.toml.example config.toml -``` - -Then you will want to open up the file and change the following -settings (and possibly others, such as `llvm.ccache`): +You may also want to change some of the following settings (and possibly others, such as +`llvm.ccache`): ```toml [llvm] +# Whether to use Rust CI built LLVM instead of locally building it. +download-ci-llvm = true + # Indicates whether the LLVM assertions are enabled or not assertions = true @@ -51,10 +48,9 @@ debug-logging = true incremental = true ``` -If you have already built `rustc`, then you may have to execute `rm -rf build` for subsequent -configuration changes to take effect. Note that `./x.py clean` will not cause a -rebuild of LLVM, so if your configuration change affects LLVM, you will need to -manually `rm -rf build/` before rebuilding. +If you have already built `rustc` and you change settings related to LLVM, then you may have to +execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x.py +clean` will not cause a rebuild of LLVM. ## What is `x.py`? diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 6e0f830c65..f27793140d 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -34,7 +34,9 @@ you can write: "rust-analyzer.rustfmt.overrideCommand": [ "./build/TARGET_TRIPLE/stage0/bin/rustfmt" ], - "editor.formatOnSave": true + "editor.formatOnSave": true, + "rust-analyzer.cargo.runBuildScripts": false, + "rust-analyzer.procMacro.enable": false } ``` @@ -201,3 +203,74 @@ git worktree add -b my-feature ../rust2 master You can then use that rust2 folder as a separate workspace for modifying and building `rustc`! + +## Using nix-shell + +If you're using nix, you can use the following nix-shell to work on Rust: + +```nix +{ pkgs ? import {} }: + +# This file contains a development shell for working on rustc. +let + # Build configuration for rust-lang/rust. Based on `config.toml.example` from + # `1bd30ce2aac40c7698aa4a1b9520aa649ff2d1c5`. + config = pkgs.writeText "rustc-config" '' + profile = "compiler" # you may want to choose a different profile, like `library` or `tools` + changelog-seen = 2 + + [build] + # The path to (or name of) the GDB executable to use. This is only used for + # executing the debuginfo test suite. + gdb = "${pkgs.gdb}/bin/gdb" + python = "${pkgs.python3Full}/bin/python" + + [rust] + debug = true + incremental = true + deny-warnings = false + + # Indicates whether some LLVM tools, like llvm-objdump, will be made available in the + # sysroot. + llvm-tools = true + + # Print backtrace on internal compiler errors during bootstrap + backtrace-on-ice = true + ''; + + ripgrepConfig = + let + # Files that are ignored by ripgrep when searching. + ignoreFile = pkgs.writeText "rustc-rgignore" '' + configure + config.toml.example + x.py + LICENSE-MIT + LICENSE-APACHE + COPYRIGHT + **/*.txt + **/*.toml + **/*.yml + **/*.nix + *.md + src/ci + src/etc/ + src/llvm-emscripten/ + src/llvm-project/ + src/rtstartup/ + src/rustllvm/ + src/stdsimd/ + src/tools/rls/rls-analysis/test_data/ + ''; + in + pkgs.writeText "rustc-ripgreprc" "--ignore-file=${ignoreFile}"; +in +pkgs.mkShell { + name = "rustc"; + nativeBuildInputs = with pkgs; [ + gcc9 binutils cmake ninja openssl pkgconfig python39 git curl cacert patchelf nix psutils + ]; + RIPGREP_CONFIG_PATH = ripgrepConfig; + RUST_BOOTSTRAP_CONFIG = config; +} +``` diff --git a/src/doc/rustc-dev-guide/src/compiler-team.md b/src/doc/rustc-dev-guide/src/compiler-team.md index ebb8cbc166..8cfcc5bb66 100644 --- a/src/doc/rustc-dev-guide/src/compiler-team.md +++ b/src/doc/rustc-dev-guide/src/compiler-team.md @@ -30,32 +30,38 @@ who are experts on each one. ## Rust compiler meeting The compiler team has a weekly meeting where we do triage and try to -generally stay on top of new bugs, regressions, and other things. -They are held on [Zulip][zulip]. It works roughly as follows: - -- **Review P-high bugs:** P-high bugs are those that are sufficiently - important for us to actively track progress. P-high bugs should - ideally always have an assignee. -- **Look over new regressions:** we then look for new cases where the - compiler broke previously working code in the wild. Regressions are - almost always marked as P-high; the major exception would be bug - fixes (though even there we often [aim to give warnings first][procedure]). -- **Check I-nominated issues:** These are issues where feedback from +generally stay on top of new bugs, regressions, and discuss important +things in general. +They are held on [Zulip][zulip-meetings]. It works roughly as follows: + +- **Announcements, MCPs/FCPs, and WG-check-ins:** We share some + announcements with the rest of the team about important things we want + everyone to be aware of. We also share the status of MCPs and FCPs and we + use the opportunity to have a couple of WGs giving us an update about + their work. +- **Check for beta and stable nominations:** These are nominations of things to + backport to beta and stable respectively. + We then look for new cases where the compiler broke previously working + code in the wild. Regressions are important issues to fix, so it's + likely that they are tagged as P-critical or P-high; the major + exception would be bug fixes (though even there we often [aim to give + warnings first][procedure]). +- **Review P-critical and P-high bugs:** P-critical and P-high bugs are + those that are sufficiently important for us to actively track + progress. P-critical and P-high bugs should ideally always have an + assignee. +- **Check S-waiting-on-team and I-nominated issues:** These are issues where feedback from the team is desired. -- **Check for beta nominations:** These are nominations of things to - backport to beta. -- **Possibly WG checking:** A WG may give an update at this point, if there is - time. +- **Look over the performance triage report:** We check for PRs that made the + performance worse and try to decide if it's worth reverting the performance regression or if + the regression can be addressed in a future PR. The meeting currently takes place on Thursdays at 10am Boston time (UTC-4 typically, but daylight savings time sometimes makes things complicated). -The meeting is held over a "chat medium", currently on [zulip]. -[etherpad]: https://public.etherpad-mozilla.org/p/rust-compiler-meeting [procedure]: ./bug-fix-procedure.md -[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler [zulip-help]: https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp [zulip-meetings]: https://rust-lang.zulipchat.com/#narrow/stream/238009-t-compiler.2Fmeetings diff --git a/src/doc/rustc-dev-guide/src/generics.md b/src/doc/rustc-dev-guide/src/generics.md index cdbf63b930..c7a0be0935 100644 --- a/src/doc/rustc-dev-guide/src/generics.md +++ b/src/doc/rustc-dev-guide/src/generics.md @@ -7,7 +7,7 @@ that one type is equal to another type and want to swap one out for the other an for another type and so on until we eventually get some concrete types (or an error). In rustc this is done using the `SubstsRef` that we mentioned above (“substs” = “substitutions”). -Conceptually, you can think of `SubstsRef` of a list of types that are to be substituted for the +Conceptually, you can think of `SubstsRef` as a list of types that are to be substituted for the generic type parameters of the ADT. `SubstsRef` is a type alias of `List>` (see [`List` rustdocs][list]). diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index e533426cfc..e1b0e02926 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -217,6 +217,7 @@ there are no glaring errors. Once you're all done fixing the conflicts, you need to stage the files that had conflicts in them via `git add`. Afterwards, run `git rebase --continue` to let Git know that you've resolved the conflicts and it should finish the rebase. + Once the rebase has succeeded, you'll want to update the associated branch on your fork with `git push --force-with-lease`. @@ -263,6 +264,65 @@ You also may want to squash just the last few commits together, possibly because they only represent "fixups" and not real changes. For example, `git rebase --interactive HEAD~2` will allow you to edit the two commits only. +### `git range-diff` + +After completing a rebase, and before pushing up your changes, you may want to +review the changes between your old branch and your new one. You can do that +with `git range-diff master @{upstream} HEAD`. + +The first argument to `range-diff`, `master` in this case, is the base revision +that you're comparing your old and new branch against. The second argument is +the old version of your branch; in this case, `@upstream` means the version that +you've pushed to GitHub, which is the same as what people will see in your pull +request. Finally, the third argument to `range-diff` is the *new* version of +your branch; in this case, it is `HEAD`, which is the commit that is currently +checked-out in your local repo. + +Note that you can also use the equivalent, abbreviated form `git range-diff +master @{u} HEAD`. + +Unlike in regular Git diffs, you'll see a `-` or `+` next to another `-` or `+` +in the range-diff output. The marker on the left indicates a change between the +old branch and the new branch, and the marker on the right indicates a change +you've committed. So, you can think of a range-diff as a "diff of diffs" since +it shows you the differences between your old diff and your new diff. + +Here's an example of `git range-diff` output (taken from [Git's +docs][range-diff-example-docs]): + +``` +-: ------- > 1: 0ddba11 Prepare for the inevitable! +1: c0debee = 2: cab005e Add a helpful message at the start +2: f00dbal ! 3: decafe1 Describe a bug + @@ -1,3 +1,3 @@ + Author: A U Thor + + -TODO: Describe a bug + +Describe a bug + @@ -324,5 +324,6 + This is expected. + + -+What is unexpected is that it will also crash. + ++Unexpectedly, it also crashes. This is a bug, and the jury is + ++still out there how to fix it best. See ticket #314 for details. + + Contact +3: bedead < -: ------- TO-UNDO +``` + +(Note that `git range-diff` output in your terminal will probably be easier to +read than in this example because it will have colors.) + +Another feature of `git range-diff` is that, unlike `git diff`, it will also +diff commit messages. This feature can be useful when amending several commit +messages so you can make sure you changed the right parts. + +`git range-diff` is a very useful command, but note that it can take some time +to get used to its output format. You may also find Git's documentation on the +command useful, especially their ["Examples" section][range-diff-example-docs]. + +[range-diff-example-docs]: https://git-scm.com/docs/git-range-diff#_examples + ## No-Merge Policy The rust-lang/rust repo uses what is known as a "rebase workflow." This means diff --git a/src/doc/rustc-dev-guide/src/method-lookup.md b/src/doc/rustc-dev-guide/src/method-lookup.md index 5aafb6abf0..250eea034f 100644 --- a/src/doc/rustc-dev-guide/src/method-lookup.md +++ b/src/doc/rustc-dev-guide/src/method-lookup.md @@ -6,18 +6,11 @@ file provides an overview of the process. More detailed notes are in the code itself, naturally. One way to think of method lookup is that we convert an expression of -the form: +the form `receiver.method(...)` into a more explicit [fully-qualified syntax][] +(formerly called [UFCS][]): -```rust,ignore -receiver.method(...) -``` - -into a more explicit [UFCS] form: - -```rust,ignore -Trait::method(ADJ(receiver), ...) // for a trait call -ReceiverType::method(ADJ(receiver), ...) // for an inherent method call -``` +- `Trait::method(ADJ(receiver), ...)` for a trait call +- `ReceiverType::method(ADJ(receiver), ...)` for an inherent method call Here `ADJ` is some kind of adjustment, which is typically a series of autoderefs and then possibly an autoref (e.g., `&**receiver`). However @@ -37,6 +30,7 @@ probe phase produces a "pick" (`probe::Pick`), which is designed to be cacheable across method-call sites. Therefore, it does not include inference variables or other information. +[fully-qualified syntax]: https://doc.rust-lang.org/nightly/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name [UFCS]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md [probe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/probe/ [confirm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/confirm/ @@ -51,12 +45,10 @@ until it cannot be deref'd anymore, as well as applying an optional "unsize" step. So if the receiver has type `Rc>`, this might yield: -```rust,ignore -Rc> -Box<[T; 3]> -[T; 3] -[T] -``` +1. `Rc>` +2. `Box<[T; 3]>` +3. `[T; 3]` +4. `[T]` ### Candidate assembly @@ -73,7 +65,7 @@ nominal type `Foo` (e.g., a struct), any methods defined within an impl like `impl Foo` are inherent methods. Nothing needs to be imported to use an inherent method, they are associated with the type itself (note that inherent impls can only be defined in the same -module as the type itself). +crate as the type itself). FIXME: Inherent candidates are not always derived from impls. If you have a trait object, such as a value of type `Box`, then the @@ -90,7 +82,7 @@ TODO: Is this FIXME still accurate? the trait `ToString` imported, and I call `to_string()` on a value of type `T`, then we will go off to find out whether there is an impl of `ToString` for `T`. These kinds of method calls are called "extension -methods". They can be defined in any module, not only the one that +methods". They can be defined in any crate, not only the one that defined `T`. Furthermore, you must import the trait to call such a method. @@ -99,10 +91,9 @@ So, let's continue our example. Imagine that we were calling a method that defines it with `&self` for the type `Rc` as well as a method on the type `Box` that defines `Foo` but with `&mut self`. Then we might have two candidates: -```text -&Rc> from the impl of `Foo` for `Rc` where `U=Box -&mut Box<[T; 3]>> from the inherent impl on `Box` where `U=[T; 3]` -``` + +- `&Rc>` from the impl of `Foo` for `Rc` where `U=Box<[T; 3]>` +- `&mut Box<[T; 3]>>` from the inherent impl on `Box` where `U=[T; 3]` ### Candidate search diff --git a/src/doc/rustc-dev-guide/src/mir/debugging.md b/src/doc/rustc-dev-guide/src/mir/debugging.md index c6734f8aaa..b7182fa900 100644 --- a/src/doc/rustc-dev-guide/src/mir/debugging.md +++ b/src/doc/rustc-dev-guide/src/mir/debugging.md @@ -88,6 +88,11 @@ rustc.main.002-006.NoLandingPads.before.mir (Here, the `main-promoted[0]` files refer to the MIR for "promoted constants" that appeared within the `main` function.) +The `-Z unpretty=mir-cfg` flag can be used to create a graphviz MIR +control-flow diagram for the whole crate: + +![A control-flow diagram](mir_cfg.svg) + TODO: anything else? [dataflow state]: ./dataflow.html#graphviz-diagrams diff --git a/src/doc/rustc-dev-guide/src/mir/mir_cfg.svg b/src/doc/rustc-dev-guide/src/mir/mir_cfg.svg new file mode 100644 index 0000000000..70705ec043 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/mir/mir_cfg.svg @@ -0,0 +1,270 @@ + + + + + + +__crate__ + + +cluster_Mir_0_4 + +fn main() -> () +let _1: i32; +let mut _2: i32; +let mut _3: bool; +let mut _4: i32; +let mut _5: i32; +debug x => _1; +debug y => _2; + + +cluster_Mir_0_3 + +fn incr() -> i32 +let mut _1: i32; +let mut _2: bool; +let mut _3: bool; +debug ret => _1; + + + +bb0__0_4 + + +0 + +StorageLive(_1) +_1 = const 5_i32 +StorageLive(_2) +_2 = const 3_i32 +StorageLive(_3) +StorageLive(_4) +_4 = _1 +_3 = Gt(move _4, const 3_i32) +StorageDead(_4) + +switchInt(move _3) + + + +bb1__0_4 + + +1 + +_2 = const 4_i32 +_0 = const () + +goto + + + +bb0__0_4->bb1__0_4 + + +otherwise + + + +bb2__0_4 + + +2 + +StorageLive(_5) + +_5 = incr() + + + +bb0__0_4->bb2__0_4 + + +false + + + +bb4__0_4 + + +4 + +StorageDead(_3) +StorageDead(_2) +StorageDead(_1) + +return + + + +bb1__0_4->bb4__0_4 + + + + + +bb3__0_4 + + +3 + +_2 = Add(_2, move _5) +StorageDead(_5) +_0 = const () + +goto + + + +bb2__0_4->bb3__0_4 + + +return + + + +bb3__0_4->bb4__0_4 + + + + + +bb0__0_3 + + +0 + +StorageLive(_1) +StorageLive(_2) +_2 = const true + +switchInt(move _2) + + + +bb1__0_3 + + +1 + +_1 = const 7_i32 + +goto + + + +bb0__0_3->bb1__0_3 + + +otherwise + + + +bb2__0_3 + + +2 + +StorageLive(_3) +_3 = const true + +switchInt(move _3) + + + +bb0__0_3->bb2__0_3 + + +false + + + +bb6__0_3 + + +6 + +StorageDead(_2) +_1 = Add(_1, const 1_i32) +_0 = _1 +StorageDead(_1) + +return + + + +bb1__0_3->bb6__0_3 + + + + + +bb3__0_3 + + +3 + +_1 = const 8_i32 + +goto + + + +bb2__0_3->bb3__0_3 + + +otherwise + + + +bb4__0_3 + + +4 + +_1 = const 9_i32 + +goto + + + +bb2__0_3->bb4__0_3 + + +false + + + +bb5__0_3 + + +5 + +StorageDead(_3) + +goto + + + +bb3__0_3->bb5__0_3 + + + + + +bb4__0_3->bb5__0_3 + + + + + +bb5__0_3->bb6__0_3 + + + + + diff --git a/src/doc/rustc-dev-guide/src/mir/optimizations.md b/src/doc/rustc-dev-guide/src/mir/optimizations.md index 080c8fd3fb..50e06960ed 100644 --- a/src/doc/rustc-dev-guide/src/mir/optimizations.md +++ b/src/doc/rustc-dev-guide/src/mir/optimizations.md @@ -26,6 +26,55 @@ optimizes it, and returns the improved MIR. [defid]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#def-id [steal]: https://rustc-dev-guide.rust-lang.org/mir/passes.html?highlight=steal#stealing +## Quickstart for adding a new optimization + +1. Make a Rust source file in `src/test/mir-opt` that shows the code you want to + optimize. This should be kept simple, so avoid `println!` or other formatting + code if it's not necessary for the optimization. The reason for this is that + `println!`, `format!`, etc. generate a lot of MIR that can make it harder to + understand what the optimization does to the test. + +2. Run `./x.py test --bless src/test/mir-opt/.rs` to generate a MIR + dump. Read [this README][mir-opt-test-readme] for instructions on how to dump + things. + +3. Commit the current working directory state. The reason you should commit the + test output before you implement the optimization is so that you (and your + reviewers) can see a before/after diff of what the optimization changed. + +4. Implement a new optimization in [`compiler/rustc_mir/src/transform`]. + The fastest and easiest way to do this is to + + 1. pick a small optimization (such as [`no_landing_pads`]) and copy it + to a new file, + 2. add your optimization to one of the lists in the + [`run_optimization_passes()`] function, + 3. and then start modifying the copied optimization. + +5. Rerun `./x.py test --bless src/test/mir-opt/.rs` to regenerate the + MIR dumps. Look at the diffs to see if they are what you expect. + +6. Run `./x.py test src/test/ui` to see if your optimization broke anything. + +7. If there are issues with your optimization, experiment with it a bit and + repeat steps 5 and 6. + +8. Commit and open a PR. You can do this at any point, even if things aren't + working yet, so that you can ask for feedback on the PR. Open a "WIP" PR + (just prefix your PR title with `[WIP]` or otherwise note that it is a + work in progress) in that case. + + Make sure to commit the blessed test output as well! It's necessary for CI to + pass and it's very helpful to reviewers. + +If you have any questions along the way, feel free to ask in +`#t-compiler/wg-mir-opt` on Zulip. + +[mir-opt-test-readme]: https://github.com/rust-lang/rust/blob/master/src/test/mir-opt/README.md +[`compiler/rustc_mir/src/transform`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir/src/transform +[`no_landing_pads`]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir/src/transform/no_landing_pads.rs +[`run_optimization_passes()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.run_optimization_passes.html + ## Defining optimization passes The list of passes run and the order in which they are run is defined by the diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md index 27ca2ca12b..fa5ce0750e 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md @@ -4,12 +4,15 @@ ## Getting diagnostics -To get diagnostics from the compiler, -configure `rustc_interface::Config` to output diagnostic to a buffer, -and run `TyCtxt.analysis`: +To get diagnostics from the compiler, +configure `rustc_interface::Config` to output diagnostic to a buffer, +and run `TyCtxt.analysis`. The following should be compiled +with `nightly-2021-03-28` (See [here][example] +for the complete example): + +[example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-getting-diagnostics.rs ```rust -// See https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-getting-diagnostics.rs for complete program. let buffer = sync::Arc::new(sync::Mutex::new(Vec::new())); let config = rustc_interface::Config { opts: config::Options { diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md index 21d03bbb74..7cb53187b2 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md @@ -4,10 +4,13 @@ ## Getting the type of an expression -To get the type of an expression, use the `global_ctxt` to get a `TyCtxt`: +To get the type of an expression, use the `global_ctxt` to get a `TyCtxt`. +The following should be compiled with `nightly-2021-03-28` +(see [here][example] for the complete example): + +[example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-interacting-with-the-ast.rs ```rust -// See https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-interacting-with-the-ast.rs for complete program. let config = rustc_interface::Config { input: config::Input::Str { name: source_map::FileName::Custom("main.rs".to_string()), @@ -21,9 +24,9 @@ rustc_interface::run_compiler(config, |compiler| { // Analyze the crate and inspect the types under the cursor. queries.global_ctxt().unwrap().take().enter(|tcx| { // Every compilation contains a single crate. - let krate = tcx.hir().krate(); + let hir_krate = tcx.hir().krate(); // Iterate over the top-level items in the crate, looking for the main function. - for (_, item) in &krate.items { + for (_, item) in &hir_krate.items { // Use pattern-matching to find a specific node inside the main function. if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind { let expr = &tcx.hir().body(body_id).value; @@ -31,7 +34,7 @@ rustc_interface::run_compiler(config, |compiler| { if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind { if let Some(expr) = local.init { let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!" - let def_id = tcx.hir().local_def_id(item.hir_id); // def_id identifies the main function + let def_id = tcx.hir().local_def_id(item.hir_id()); // def_id identifies the main function let ty = tcx.typeck(def_id).node_type(hir_id); println!("{:?}: {:?}", expr, ty); // prints expr(HirId { owner: DefIndex(3), local_id: 4 }: "Hello, world!"): &'static str } diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 33f2c5f357..88177ccba8 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -4,9 +4,10 @@ Rustdoc actually uses the rustc internals directly. It lives in-tree with the compiler and standard library. This chapter is about how it works. For information about Rustdoc's features and how to use them, see the [Rustdoc book](https://doc.rust-lang.org/nightly/rustdoc/). -For more details about how rustdoc works, see the ["Rustdoc internals" chapter]. +For more details about how rustdoc works, see the +["Rustdoc internals" chapter][Rustdoc internals]. -["Rustdoc internals" chapter]: ./rustdoc-internals.md +[Rustdoc internals]: ./rustdoc-internals.md Rustdoc is implemented entirely within the crate [`librustdoc`][rd]. It runs the compiler up to the point where we have an internal representation of a @@ -46,8 +47,8 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) * The completed docs will be available in `build/$TARGET/doc/std`, though the bundle is meant to be used as though you would copy out the `doc` folder to a web server, since that's where the CSS/JS and landing page are. -* Use `x.py test src/test/rustdoc*` to run the tests using a stage1 rustdoc. - * See [rustdoc internals] for more information about tests. +* Use `./x.py test src/test/rustdoc*` to run the tests using a stage1 rustdoc. + * See [Rustdoc internals] for more information about tests. * Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. It's in a bunch of `fmt::Display` implementations and supplementary functions. diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index 944b895b52..8508c2f206 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -425,7 +425,7 @@ you can even run the resulting program. Just add one of the following - `// run-pass` – compilation should succeed and we should run the resulting binary -### Normalization +### Output Normalization The compiler output is normalized to eliminate output difference between platforms, mainly about filenames. @@ -500,3 +500,23 @@ Besides `normalize-stderr-32bit` and `-64bit`, one may use any target information or stage supported by [`ignore-X`](#ignoring-tests) here as well (e.g. `normalize-stderr-windows` or simply `normalize-stderr-test` for unconditional replacement). + +## Input Normalization + +Sometimes, you want to normalize the inputs to a test. For example, you may +want to pass `// compile-flags: --x=y.rs`, where y.rs is some file in the test +directory. In this case you can use input normalization. The following strings +are replaced in header inputs: + +- {{cwd}}: The directory where compiletest is run from. This may not be the + root of the checkout, so you should avoid using it where possible. + - Examples: `/path/to/rust`, `/path/to/build/root` +- {{src-base}}: The directory where the test is defined. This is equivalent to + `$DIR` for output normalization. + - Example: `/path/to/rust/src/test/ui/error-codes` +- {{build-base}}: The base directory where the test's output goes. This is + equivalent to `$TEST_BUILD_DIR` for output normalization. + - Example: `/path/to/rust/build/x86_64-unknown-linux-gnu/test/ui` + +See [`src/test/ui/commandline-argfile.rs`](https://github.com/rust-lang/rust/blob/a5029ac0ab372aec515db2e718da6d7787f3d122/src/test/ui/commandline-argfile.rs) +for an example of a test that uses input normalization. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index af5834525f..b269aab981 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -13,6 +13,7 @@ - [JSON Output](json.md) - [Tests](tests/index.md) - [Platform Support](platform-support.md) +- [Target Tier Policy](target-tier-policy.md) - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) - [Custom Targets](targets/custom.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 4eb2aa9917..d9083a5c4a 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -500,19 +500,19 @@ point instructions in software. It takes one of the following values: This option controls the emission of "split debuginfo" for debug information that `rustc` generates. The default behavior of this option is platform-specific, and not all possible values for this option work on all -platform. Possible values are: +platforms. Possible values are: * `off` - This is the default for platforms with ELF binaries and windows-gnu - (not Windows MSVC and not macOS). This typically means that dwarf debug + (not Windows MSVC and not macOS). This typically means that DWARF debug information can be found in the final artifact in sections of the executable. This option is not supported on Windows MSVC. On macOS this options prevents the final execution of `dsymutil` to generate debuginfo. -* `packed` - This is the default for Windows MSVC and macOS platforms. The term +* `packed` - This is the default for Windows MSVC and macOS. The term "packed" here means that all the debug information is packed into a separate file from the main executable. On Windows MSVC this is a `*.pdb` file, on macOS this is a `*.dSYM` folder, and on other platforms this is a `*.dwp` - files. + file. * `unpacked` - This means that debug information will be found in separate files for each compilation unit (object file). This is not supported on @@ -520,7 +520,7 @@ platform. Possible values are: debug information. On other Unix platforms this means that `*.dwo` files will contain debug information. -Note that `packed` and `unpacked` gated behind `-Zunstable-options` on +Note that `packed` and `unpacked` are gated behind `-Z unstable-options` on non-macOS platforms at this time. ## target-cpu diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index ee17fcac45..7f57d476aa 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -7,7 +7,8 @@ Support for different platforms are organized into three tiers, each with a -different set of guarantees. +different set of guarantees. For more information on the policies for targets +at each tier, see the [Target Tier Policy](target-tier-policy.md). Platforms are identified by their "target triple" which is the string to inform the compiler what kind of output should be produced. The columns in the @@ -179,7 +180,7 @@ target | std | host | notes `i386-apple-ios` | ✓ | | 32-bit x86 iOS `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+) `i686-pc-windows-msvc` | ✓ | | 32-bit Windows XP support -`i686-unknown-uefi` | ? | | 32-bit UEFI +`i686-unknown-uefi` | * | | 32-bit UEFI `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 `i686-unknown-openbsd` | ✓ | ✓ | 32-bit OpenBSD @@ -216,6 +217,7 @@ target | std | host | notes `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL `thumbv4t-none-eabi` | * | | ARMv4T T32 +`wasm64-unknown-unknown` | * | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS `x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules @@ -227,7 +229,7 @@ target | std | host | notes `x86_64-unknown-none-hermitkernel` | ? | | HermitCore kernel `x86_64-unknown-l4re-uclibc` | ? | | `x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD -`x86_64-unknown-uefi` | ? | | +`x86_64-unknown-uefi` | * | | 64-bit UEFI `x86_64-uwp-windows-gnu` | ✓ | | `x86_64-uwp-windows-msvc` | ✓ | | `x86_64-wrs-vxworks` | ? | | diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md new file mode 100644 index 0000000000..463f56099f --- /dev/null +++ b/src/doc/rustc/src/target-tier-policy.md @@ -0,0 +1,639 @@ +# Target Tier Policy + +Rust provides three tiers of target support: + +- Rust provides no guarantees about tier 3 targets; they exist in the codebase, + but may or may not build. +- Rust's continuous integration checks that tier 2 targets will always build, + but they may or may not pass tests. +- Rust's continuous integration checks that tier 1 targets will always build + and pass tests. + +Adding a new tier 3 target imposes minimal requirements; we focus primarily on +avoiding disruption to other ongoing Rust development. + +Tier 2 and tier 1 targets place work on Rust project developers as a whole, to +avoid breaking the target. The broader Rust community may also feel more +inclined to support higher-tier targets in their crates (though they are not +obligated to do so). Thus, these tiers require commensurate and ongoing efforts +from the maintainers of the target, to demonstrate value and to minimize any +disruptions to ongoing Rust development. + +This policy defines the requirements for accepting a proposed target at a given +level of support. + +Each tier builds on all the requirements from the previous tier, unless +overridden by a stronger requirement. Targets at tier 2 and tier 1 may also +provide *host tools* (such as `rustc` and `cargo`); each of those tiers +includes a set of supplementary requirements that must be met if supplying host +tools for the target. A target at tier 2 or tier 1 is not required to supply +host tools, but if it does, it must meet the corresponding additional +requirements for host tools. + +The policy for each tier also documents the Rust governance teams that must +approve the addition of any target at that tier. Those teams are responsible +for reviewing and evaluating the target, based on these requirements and their +own judgment. Those teams may apply additional requirements, including +subjective requirements, such as to deal with issues not foreseen by this +policy. (Such requirements may subsequently motivate additions to this policy.) + +While these criteria attempt to document the policy, that policy still involves +human judgment. Targets must fulfill the spirit of the requirements as well, as +determined by the judgment of the approving teams. Reviewers and team members +evaluating targets and target-specific patches should always use their own best +judgment regarding the quality of work, and the suitability of a target for the +Rust project. Neither this policy nor any decisions made regarding targets +shall create any binding agreement or estoppel by any party. + +Before filing an issue or pull request (PR) to introduce or promote a target, +the target should already meet the corresponding tier requirements. This does +not preclude an existing target's maintainers using issues (on the Rust +repository or otherwise) to track requirements that have not yet been met, as +appropriate; however, before officially proposing the introduction or promotion +of a target, it should meet all of the necessary requirements. A target +proposal is encouraged to quote the corresponding requirements verbatim as part +of explaining how the target meets those requirements. + +For a list of all supported targets and their corresponding tiers ("tier 3", +"tier 2", "tier 2 with host tools", "tier 1", or "tier 1 with host tools"), see +[platform support](platform-support.md). + +Note that a target must have already received approval for the next lower tier, +and spent a reasonable amount of time at that tier, before making a proposal +for promotion to the next higher tier; this is true even if a target meets the +requirements for several tiers at once. This policy leaves the precise +interpretation of "reasonable amount of time" up to the approving teams; those +teams may scale the amount of time required based on their confidence in the +target and its demonstrated track record at its current tier. At a minimum, +multiple stable releases of Rust should typically occur between promotions of a +target. + +The availability or tier of a target in stable Rust is not a hard stability +guarantee about the future availability or tier of that target. Higher-level +target tiers are an increasing commitment to the support of a target, and we +will take that commitment and potential disruptions into account when +evaluating the potential demotion or removal of a target that has been part of +a stable release. The promotion or demotion of a target will not generally +affect existing stable releases, only current development and future releases. + +In this policy, the words "must" and "must not" specify absolute requirements +that a target must meet to qualify for a tier. The words "should" and "should +not" specify requirements that apply in almost all cases, but for which the +approving teams may grant an exception for good reason. The word "may" +indicates something entirely optional, and does not indicate guidance or +recommendations. This language is based on [IETF RFC +2119](https://tools.ietf.org/html/rfc2119). + +## Tier 3 target policy + +At this tier, the Rust project provides no official support for a target, so we +place minimal requirements on the introduction of targets. + +A proposed new tier 3 target must be reviewed and approved by a member of the +compiler team based on these requirements. The reviewer may choose to gauge +broader compiler team consensus via a Major Change Proposal (MCP). + +A proposed target or target-specific patch that substantially changes code +shared with other targets (not just target-specific code) must be reviewed and +approved by the appropriate team for that shared code before acceptance. + +- A tier 3 target must have a designated developer or developers (the "target + maintainers") on record to be CCed when issues arise regarding the target. + (The mechanism to track and CC such developers may evolve over time.) +- Targets must use naming consistent with any existing targets; for instance, a + target for the same CPU or OS as an existing Rust target should use the same + name for that CPU or OS. Targets should normally use the same names and + naming conventions as used elsewhere in the broader ecosystem beyond Rust + (such as in other toolchains), unless they have a very good reason to + diverge. Changing the name of a target can be highly disruptive, especially + once the target reaches a higher tier, so getting the name right is important + even for a tier 3 target. + - Target names should not introduce undue confusion or ambiguity unless + absolutely necessary to maintain ecosystem compatibility. For example, if + the name of the target makes people extremely likely to form incorrect + beliefs about what it targets, the name should be changed or augmented to + disambiguate it. +- Tier 3 targets may have unusual requirements to build or use, but must not + create legal issues or impose onerous legal terms for the Rust project or for + Rust developers or users. + - The target must not introduce license incompatibilities. + - Anything added to the Rust repository must be under the standard Rust + license (`MIT OR Apache-2.0`). + - The target must not cause the Rust tools or libraries built for any other + host (even when supporting cross-compilation to the target) to depend + on any new dependency less permissive than the Rust licensing policy. This + applies whether the dependency is a Rust crate that would require adding + new license exceptions (as specified by the `tidy` tool in the + rust-lang/rust repository), or whether the dependency is a native library + or binary. In other words, the introduction of the target must not cause a + user installing or running a version of Rust or the Rust tools to be + subject to any new license requirements. + - If the target supports building host tools (such as `rustc` or `cargo`), + those host tools must not depend on proprietary (non-FOSS) libraries, other + than ordinary runtime libraries supplied by the platform and commonly used + by other binaries built for the target. For instance, `rustc` built for the + target may depend on a common proprietary C runtime library or console + output library, but must not depend on a proprietary code generation + library or code optimization library. Rust's license permits such + combinations, but the Rust project has no interest in maintaining such + combinations within the scope of Rust itself, even at tier 3. + - Targets should not require proprietary (non-FOSS) components to link a + functional binary or library. + - "onerous" here is an intentionally subjective term. At a minimum, "onerous" + legal/licensing terms include but are *not* limited to: non-disclosure + requirements, non-compete requirements, contributor license agreements + (CLAs) or equivalent, "non-commercial"/"research-only"/etc terms, + requirements conditional on the employer or employment of any particular + Rust developers, revocable terms, any requirements that create liability + for the Rust project or its developers or users, or any requirements that + adversely affect the livelihood or prospects of the Rust project or its + developers or users. +- Neither this policy nor any decisions made regarding targets shall create any + binding agreement or estoppel by any party. If any member of an approving + Rust team serves as one of the maintainers of a target, or has any legal or + employment requirement (explicit or implicit) that might affect their + decisions regarding a target, they must recuse themselves from any approval + decisions regarding the target's tier status, though they may otherwise + participate in discussions. + - This requirement does not prevent part or all of this policy from being + cited in an explicit contract or work agreement (e.g. to implement or + maintain support for a target). This requirement exists to ensure that a + developer or team responsible for reviewing and approving a target does not + face any legal threats or obligations that would prevent them from freely + exercising their judgment in such approval, even if such judgment involves + subjective matters or goes beyond the letter of these requirements. +- Tier 3 targets should attempt to implement as much of the standard libraries + as possible and appropriate (`core` for most targets, `alloc` for targets + that can support dynamic memory allocation, `std` for targets with an + operating system or equivalent layer of system-provided functionality), but + may leave some code unimplemented (either unavailable or stubbed out as + appropriate), whether because the target makes it impossible to implement or + challenging to implement. The authors of pull requests are not obligated to + avoid calling any portions of the standard library on the basis of a tier 3 + target not implementing those portions. +- The target must provide documentation for the Rust community explaining how + to build for the target, using cross-compilation if possible. If the target + supports running tests (even if they do not pass), the documentation must + explain how to run tests for the target, using emulation if possible or + dedicated hardware if necessary. +- Tier 3 targets must not impose burden on the authors of pull requests, or + other developers in the community, to maintain the target. In particular, + do not post comments (automated or manual) on a PR that derail or suggest a + block on the PR based on a tier 3 target. Do not send automated messages or + notifications (via any medium, including via `@`) to a PR author or others + involved with a PR regarding a tier 3 target, unless they have opted into + such messages. + - Backlinks such as those generated by the issue/PR tracker when linking to + an issue or PR are not considered a violation of this policy, within + reason. However, such messages (even on a separate repository) must not + generate notifications to anyone involved with a PR who has not requested + such notifications. +- Patches adding or updating tier 3 targets must not break any existing tier 2 + or tier 1 target, and must not knowingly break another tier 3 target without + approval of either the compiler team or the maintainers of the other tier 3 + target. + - In particular, this may come up when working on closely related targets, + such as variations of the same architecture with different features. Avoid + introducing unconditional uses of features that another variation of the + target may not have; use conditional compilation or runtime detection, as + appropriate, to let each target run code supported by that target. + +If a tier 3 target stops meeting these requirements, or the target maintainers +no longer have interest or time, or the target shows no signs of activity and +has not built for some time, or removing the target would improve the quality +of the Rust codebase, we may post a PR to remove it; any such PR will be CCed +to the target maintainers (and potentially other people who have previously +worked on the target), to check potential interest in improving the situation. + +## Tier 2 target policy + +At this tier, the Rust project guarantees that a target builds, and will reject +patches that fail to build on a target. Thus, we place requirements that ensure +the target will not block forward progress of the Rust project. + +A proposed new tier 2 target must be reviewed and approved by the compiler team +based on these requirements. Such review and approval may occur via a Major +Change Proposal (MCP). + +In addition, the infrastructure team must approve the integration of the target +into Continuous Integration (CI), and the tier 2 CI-related requirements. This +review and approval may take place in a PR adding the target to CI, or simply +by an infrastructure team member reporting the outcome of a team discussion. + +- A tier 2 target must have value to people other than its maintainers. (It may + still be a niche target, but it must not be exclusively useful for an + inherently closed group.) +- A tier 2 target must have a designated team of developers (the "target + maintainers") available to consult on target-specific build-breaking issues, + or if necessary to develop target-specific language or library implementation + details. This team must have at least 2 developers. + - The target maintainers should not only fix target-specific issues, but + should use any such issue as an opportunity to educate the Rust community + about portability to their target, and enhance documentation of the target. +- The target must not place undue burden on Rust developers not specifically + concerned with that target. Rust developers are expected to not gratuitously + break a tier 2 target, but are not expected to become experts in every tier 2 + target, and are not expected to provide target-specific implementations for + every tier 2 target. +- The target must provide documentation for the Rust community explaining how + to build for the target using cross-compilation, and explaining how to run + tests for the target. If at all possible, this documentation should show how + to run Rust programs and tests for the target using emulation, to allow + anyone to do so. If the target cannot be feasibly emulated, the documentation + should explain how to obtain and work with physical hardware, cloud systems, + or equivalent. +- The target must document its baseline expectations for the features or + versions of CPUs, operating systems, libraries, runtime environments, and + similar. +- If introducing a new tier 2 or higher target that is identical to an existing + Rust target except for the baseline expectations for the features or versions + of CPUs, operating systems, libraries, runtime environments, and similar, + then the proposed target must document to the satisfaction of the approving + teams why the specific difference in baseline expectations provides + sufficient value to justify a separate target. + - Note that in some cases, based on the usage of existing targets within the + Rust community, Rust developers or a target's maintainers may wish to + modify the baseline expectations of a target, or split an existing target + into multiple targets with different baseline expectations. A proposal to + do so will be treated similarly to the analogous promotion, demotion, or + removal of a target, according to this policy, with the same team approvals + required. + - For instance, if an OS version has become obsolete and unsupported, a + target for that OS may raise its baseline expectations for OS version + (treated as though removing a target corresponding to the older + versions), or a target for that OS may split out support for older OS + versions into a lower-tier target (treated as though demoting a target + corresponding to the older versions, and requiring justification for a + new target at a lower tier for the older OS versions). +- Tier 2 targets must not leave any significant portions of `core` or the + standard library unimplemented or stubbed out, unless they cannot possibly be + supported on the target. + - The right approach to handling a missing feature from a target may depend + on whether the target seems likely to develop the feature in the future. In + some cases, a target may be co-developed along with Rust support, and Rust + may gain new features on the target as that target gains the capabilities + to support those features. + - As an exception, a target identical to an existing tier 1 target except for + lower baseline expectations for the OS, CPU, or similar, may propose to + qualify as tier 2 (but not higher) without support for `std` if the target + will primarily be used in `no_std` applications, to reduce the support + burden for the standard library. In this case, evaluation of the proposed + target's value will take this limitation into account. +- The code generation backend for the target should not have deficiencies that + invalidate Rust safety properties, as evaluated by the Rust compiler team. + (This requirement does not apply to arbitrary security enhancements or + mitigations provided by code generation backends, only to those properties + needed to ensure safe Rust code cannot cause undefined behavior or other + unsoundness.) If this requirement does not hold, the target must clearly and + prominently document any such limitations as part of the target's entry in + the target tier list, and ideally also via a failing test in the testsuite. + The Rust compiler team must be satisfied with the balance between these + limitations and the difficulty of implementing the necessary features. + - For example, if Rust relies on a specific code generation feature to ensure + that safe code cannot overflow the stack, the code generation for the + target should support that feature. + - If the Rust compiler introduces new safety properties (such as via new + capabilities of a compiler backend), the Rust compiler team will determine + if they consider those new safety properties a best-effort improvement for + specific targets, or a required property for all Rust targets. In the + latter case, the compiler team may require the maintainers of existing + targets to either implement and confirm support for the property or update + the target tier list with documentation of the missing property. +- If the target supports C code, and the target has an interoperable calling + convention for C code, the Rust target must support that C calling convention + for the platform via `extern "C"`. The C calling convention does not need to + be the default Rust calling convention for the target, however. +- The target must build reliably in CI, for all components that Rust's CI + considers mandatory. +- The approving teams may additionally require that a subset of tests pass in + CI, such as enough to build a functional "hello world" program, `./x.py test + --no-run`, or equivalent "smoke tests". In particular, this requirement may + apply if the target builds host tools, or if the tests in question provide + substantial value via early detection of critical problems. +- Building the target in CI must not take substantially longer than the current + slowest target in CI, and should not substantially raise the maintenance + burden of the CI infrastructure. This requirement is subjective, to be + evaluated by the infrastructure team, and will take the community importance + of the target into account. +- Tier 2 targets should, if at all possible, support cross-compiling. Tier 2 + targets should not require using the target as the host for builds, even if + the target supports host tools. +- In addition to the legal requirements for all targets (specified in the tier + 3 requirements), because a tier 2 target typically involves the Rust project + building and supplying various compiled binaries, incorporating the target + and redistributing any resulting compiled binaries (e.g. built libraries, + host tools if any) must not impose any onerous license requirements on any + members of the Rust project, including infrastructure team members and those + operating CI systems. This is a subjective requirement, to be evaluated by + the approving teams. + - As an exception to this, if the target's primary purpose is to build + components for a Free and Open Source Software (FOSS) project licensed + under "copyleft" terms (terms which require licensing other code under + compatible FOSS terms), such as kernel modules or plugins, then the + standard libraries for the target may potentially be subject to copyleft + terms, as long as such terms are satisfied by Rust's existing practices of + providing full corresponding source code. Note that anything added to the + Rust repository itself must still use Rust's standard license terms. +- Tier 2 targets must not impose burden on the authors of pull requests, or + other developers in the community, to ensure that tests pass for the target. + In particular, do not post comments (automated or manual) on a PR that derail + or suggest a block on the PR based on tests failing for the target. Do not + send automated messages or notifications (via any medium, including via `@`) + to a PR author or others involved with a PR regarding the PR breaking tests + on a tier 2 target, unless they have opted into such messages. + - Backlinks such as those generated by the issue/PR tracker when linking to + an issue or PR are not considered a violation of this policy, within + reason. However, such messages (even on a separate repository) must not + generate notifications to anyone involved with a PR who has not requested + such notifications. +- The target maintainers should regularly run the testsuite for the target, and + should fix any test failures in a reasonably timely fashion. +- All requirements for tier 3 apply. + +A tier 2 target may be demoted or removed if it no longer meets these +requirements. Any proposal for demotion or removal will be CCed to the target +maintainers, and will be communicated widely to the Rust community before being +dropped from a stable release. (The amount of time between such communication +and the next stable release may depend on the nature and severity of the failed +requirement, the timing of its discovery, whether the target has been part of a +stable release yet, and whether the demotion or removal can be a planned and +scheduled action.) + +In some circumstances, especially if the target maintainers do not respond in a +timely fashion, Rust teams may land pull requests that temporarily disable some +targets in the nightly compiler, in order to implement a feature not yet +supported by those targets. (As an example, this happened when introducing the +128-bit types `u128` and `i128`.) Such a pull request will include notification +and coordination with the maintainers of such targets, and will ideally happen +towards the beginning of a new development cycle to give maintainers time to +update their targets. The maintainers of such targets will then be expected to +implement the corresponding target-specific support in order to re-enable the +target. If the maintainers of such targets cannot provide such support in time +for the next stable release, this may result in demoting or removing the +targets. + +### Tier 2 with host tools + +Some tier 2 targets may additionally have binaries built to run on them as a +host (such as `rustc` and `cargo`). This allows the target to be used as a +development platform, not just a compilation target. + +A proposed new tier 2 target with host tools must be reviewed and approved by +the compiler team based on these requirements. Such review and approval may +occur via a Major Change Proposal (MCP). + +In addition, the infrastructure team must approve the integration of the +target's host tools into Continuous Integration (CI), and the CI-related +requirements for host tools. This review and approval may take place in a PR +adding the target's host tools to CI, or simply by an infrastructure team +member reporting the outcome of a team discussion. + +- Depending on the target, its capabilities, its performance, and the + likelihood of use for any given tool, the host tools provided for a tier 2 + target may include only `rustc` and `cargo`, or may include additional tools + such as `clippy` and `rustfmt`. +- Approval of host tools will take into account the additional time required to + build the host tools, and the substantial additional storage required for the + host tools. +- The host tools must have direct value to people other than the target's + maintainers. (It may still be a niche target, but the host tools must not be + exclusively useful for an inherently closed group.) This requirement will be + evaluated independently from the corresponding tier 2 requirement. + - The requirement to provide "direct value" means that it does not suffice to + argue that having host tools will help the target's maintainers more easily + provide the target to others. The tools themselves must provide value to + others. +- There must be a reasonable expectation that the host tools will be used, for + purposes other than to prove that they can be used. +- The host tools must build and run reliably in CI (for all components that + Rust's CI considers mandatory), though they may or may not pass tests. +- Building host tools for the target must not take substantially longer than + building host tools for other targets, and should not substantially raise the + maintenance burden of the CI infrastructure. +- The host tools must provide a substantively similar experience as on other + targets, subject to reasonable target limitations. + - Adding a substantively different interface to an existing tool, or a + target-specific interface to the functionality of an existing tool, + requires design and implementation approval (e.g. RFC/MCP) from the + appropriate approving teams for that tool. + - Such an interface should have a design that could potentially work for + other targets with similar properties. + - This should happen separately from the review and approval of the target, + to simplify the target review and approval processes, and to simplify the + review and approval processes for the proposed new interface. + - By way of example, a target that runs within a sandbox may need to modify + the handling of files, tool invocation, and similar to meet the + expectations and conventions of the sandbox, but must not introduce a + separate "sandboxed compilation" interface separate from the CLI interface + without going through the normal approval process for such an interface. + Such an interface should take into account potential other targets with + similar sandboxes. +- If the host tools for the platform would normally be expected to be signed or + equivalent (e.g. if running unsigned binaries or similar involves a + "developer mode" or an additional prompt), it must be possible for the Rust + project's automated builds to apply the appropriate signature process, + without any manual intervention by either Rust developers, target + maintainers, or a third party. This process must meet the approval of the + infrastructure team. + - This process may require one-time or semi-regular manual steps by the + infrastructure team, such as registration or renewal of a signing key. Any + such manual process must meet the approval of the infrastructure team. + - This process may require the execution of a legal agreement with the + signature provider. Such a legal agreement may be revocable, and may + potentially require a nominal fee, but must not be otherwise onerous. Any + such legal agreement must meet the approval of the infrastructure team. + (The infrastructure team is not expected or required to sign binding legal + agreements on behalf of the Rust project; this review and approval exists + to ensure no terms are onerous or cause problems for infrastructure, + especially if such terms may impose requirements or obligations on people + who have access to target-specific infrastructure.) + - Changes to this process, or to any legal agreements involved, may + cause a target to stop meeting this requirement. + - This process involved must be available under substantially similar + non-onerous terms to the general public. Making it available exclusively to + the Rust project does not suffice. + - This requirement exists to ensure that Rust builds, including nightly + builds, can meet the necessary requirements to allow users to smoothly run + the host tools. +- Providing host tools does not exempt a target from requirements to support + cross-compilation if at all possible. +- All requirements for tier 2 apply. + +A target may be promoted directly from tier 3 to tier 2 with host tools if it +meets all the necessary requirements, but doing so may introduce substantial +additional complexity. If in doubt, the target should qualify for tier 2 +without host tools first. + +## Tier 1 target policy + +At this tier, the Rust project guarantees that a target builds and passes all +tests, and will reject patches that fail to build or pass the testsuite on a +target. We hold tier 1 targets to our highest standard of requirements. + +A proposed new tier 1 target must be reviewed and approved by the compiler team +based on these requirements. In addition, the release team must approve the +viability and value of supporting the target. For a tier 1 target, this will +typically take place via a full RFC proposing the target, to be jointly +reviewed and approved by the compiler team and release team. + +In addition, the infrastructure team must approve the integration of the target +into Continuous Integration (CI), and the tier 1 CI-related requirements. This +review and approval may take place in a PR adding the target to CI, by an +infrastructure team member reporting the outcome of a team discussion, or by +including the infrastructure team in the RFC proposing the target. + +- Tier 1 targets must have substantial, widespread interest within the + developer community, and must serve the ongoing needs of multiple production + users of Rust across multiple organizations or projects. These requirements + are subjective, and determined by consensus of the approving teams. A tier 1 + target may be demoted or removed if it becomes obsolete or no longer meets + this requirement. +- The target maintainer team must include at least 3 developers. +- The target must build and pass tests reliably in CI, for all components that + Rust's CI considers mandatory. + - The target must not disable an excessive number of tests or pieces of tests + in the testsuite in order to do so. This is a subjective requirement. + - If the target does not have host tools support, or if the target has low + performance, the infrastructure team may choose to have CI cross-compile + the testsuite from another platform, and then run the compiled tests + either natively or via accurate emulation. However, the approving teams may + take such performance considerations into account when determining the + viability of the target or of its host tools. +- The target must provide as much of the Rust standard library as is feasible + and appropriate to provide. For instance, if the target can support dynamic + memory allocation, it must provide an implementation of `alloc` and the + associated data structures. +- Building the target and running the testsuite for the target must not take + substantially longer than other targets, and should not substantially raise + the maintenance burden of the CI infrastructure. + - In particular, if building the target takes a reasonable amount of time, + but the target cannot run the testsuite in a timely fashion due to low + performance of either native code or accurate emulation, that alone may + prevent the target from qualifying as tier 1. +- If running the testsuite requires additional infrastructure (such as physical + systems running the target), the target maintainers must arrange to provide + such resources to the Rust project, to the satisfaction and approval of the + Rust infrastructure team. + - Such resources may be provided via cloud systems, via emulation, or via + physical hardware. + - If the target requires the use of emulation to meet any of the tier + requirements, the approving teams for those requirements must have high + confidence in the accuracy of the emulation, such that discrepancies + between emulation and native operation that affect test results will + constitute a high-priority bug in either the emulation or the + implementation of the target. + - If it is not possible to run the target via emulation, these resources must + additionally be sufficient for the Rust infrastructure team to make them + available for access by Rust team members, for the purposes of development + and testing. (Note that the responsibility for doing target-specific + development to keep the target well maintained remains with the target + maintainers. This requirement ensures that it is possible for other + Rust developers to test the target, but does not obligate other Rust + developers to make target-specific fixes.) + - Resources provided for CI and similar infrastructure must be available for + continuous exclusive use by the Rust project. Resources provided + for access by Rust team members for development and testing must be + available on an exclusive basis when in use, but need not be available on a + continuous basis when not in use. +- Tier 1 targets must not have a hard requirement for signed, verified, or + otherwise "approved" binaries. Developers must be able to build, run, and + test binaries for the target on systems they control, or provide such + binaries for others to run. (Doing so may require enabling some appropriate + "developer mode" on such systems, but must not require the payment of any + additional fee or other consideration, or agreement to any onerous legal + agreements.) + - The Rust project may decide to supply appropriately signed binaries if + doing so provides a smoother experience for developers using the target, + and a tier 2 target with host tools already requires providing appropriate + mechanisms that enable our infrastructure to provide such signed binaries. + However, this additional tier 1 requirement ensures that Rust developers + can develop and test Rust software for the target (including Rust itself), + and that development or testing for the target is not limited. +- All requirements for tier 2 apply. + +A tier 1 target may be demoted if it no longer meets these requirements but +still meets the requirements for a lower tier. Any proposal for demotion of a +tier 1 target requires a full RFC process, with approval by the compiler and +release teams. Any such proposal will be communicated widely to the Rust +community, both when initially proposed and before being dropped from a stable +release. A tier 1 target is highly unlikely to be directly removed without +first being demoted to tier 2 or tier 3. (The amount of time between such +communication and the next stable release may depend on the nature and severity +of the failed requirement, the timing of its discovery, whether the target has +been part of a stable release yet, and whether the demotion or removal can be a +planned and scheduled action.) + +Raising the baseline expectations of a tier 1 target (such as the minimum CPU +features or OS version required) requires the approval of the compiler and +release teams, and should be widely communicated as well, but does not +necessarily require a full RFC. + +### Tier 1 with host tools + +Some tier 1 targets may additionally have binaries built to run on them as a +host (such as `rustc` and `cargo`). This allows the target to be used as a +development platform, not just a compilation target. + +A proposed new tier 1 target with host tools must be reviewed and approved by +the compiler team based on these requirements. In addition, the release team +must approve the viability and value of supporting host tools for the target. +For a tier 1 target, this will typically take place via a full RFC proposing +the target, to be jointly reviewed and approved by the compiler team and +release team. + +In addition, the infrastructure team must approve the integration of the +target's host tools into Continuous Integration (CI), and the CI-related +requirements for host tools. This review and approval may take place in a PR +adding the target's host tools to CI, by an infrastructure team member +reporting the outcome of a team discussion, or by including the infrastructure +team in the RFC proposing the target. + +- Tier 1 targets with host tools should typically include all of the additional + tools such as `clippy` and `rustfmt`, unless there is a target-specific + reason why a tool cannot possibly make sense for the target. + - Unlike with tier 2, for tier 1 we will not exclude specific tools on the + sole basis of them being less likely to be used; rather, we'll take that + into account when considering whether the target should be at tier 1 with + host tools. In general, on any tier 1 target with host tools, people + should be able to expect to find and install all the same components that + they would for any other tier 1 target with host tools. +- Approval of host tools will take into account the additional time required to + build the host tools, and the substantial additional storage required for the + host tools. +- Host tools for the target must have substantial, widespread interest within + the developer community, and must serve the ongoing needs of multiple + production users of Rust across multiple organizations or projects. These + requirements are subjective, and determined by consensus of the approving + teams. This requirement will be evaluated independently from the + corresponding tier 1 requirement; it is possible for a target to have + sufficient interest for cross-compilation, but not have sufficient interest + for native compilation. The host tools may be dropped if they no longer meet + this requirement, even if the target otherwise qualifies as tier 1. +- The host tools must build, run, and pass tests reliably in CI, for all + components that Rust's CI considers mandatory. + - The target must not disable an excessive number of tests or pieces of tests + in the testsuite in order to do so. This is a subjective requirement. +- Building the host tools and running the testsuite for the host tools must not + take substantially longer than other targets, and should not substantially raise + the maintenance burden of the CI infrastructure. + - In particular, if building the target's host tools takes a reasonable + amount of time, but the target cannot run the testsuite in a timely fashion + due to low performance of either native code or accurate emulation, that + alone may prevent the target from qualifying as tier 1 with host tools. +- Providing host tools does not exempt a target from requirements to support + cross-compilation if at all possible. +- All requirements for tier 2 targets with host tools apply. +- All requirements for tier 1 apply. + +A target seeking promotion to tier 1 with host tools should typically either be +tier 2 with host tools or tier 1 without host tools, to reduce the number of +requirements to simultaneously review and approve. + +In addition to the general process for demoting a tier 1 target, a tier 1 +target with host tools may be demoted (including having its host tools dropped, +or being demoted to tier 2 with host tools) if it no longer meets these +requirements but still meets the requirements for a lower tier. Any proposal +for demotion of a tier 1 target (with or without host tools) requires a full +RFC process, with approval by the compiler and release teams. Any such proposal +will be communicated widely to the Rust community, both when initially proposed +and before being dropped from a stable release. diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md index c33b506cda..344048ee4a 100644 --- a/src/doc/rustc/src/targets/built-in.md +++ b/src/doc/rustc/src/targets/built-in.md @@ -12,4 +12,4 @@ library built by the official Rust distributions. Most targets will need a system linker, and possibly other things. [rustup]: https://github.com/rust-lang/rustup -[rustup-cross]: https://github.com/rust-lang/rustup#cross-compilation +[rustup-cross]: https://rust-lang.github.io/rustup/cross-compilation.html diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index 174db711bc..a6626679a7 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -294,17 +294,14 @@ warning: unclosed HTML tag `h1` warning: 2 warnings emitted ``` -## non_autolinks +## bare_urls -This lint is **nightly-only** and **warns by default**. It detects links which -could use the "automatic" link syntax. For example: +This lint is **warn-by-default**. It detects URLs which are not links. +For example: ```rust /// http://example.org -/// [http://example.com](http://example.com) /// [http://example.net] -/// -/// [http://example.com]: http://example.com pub fn foo() {} ``` @@ -312,22 +309,18 @@ Which will give: ```text warning: this URL is not a hyperlink - --> foo.rs:1:5 + --> links.rs:1:5 | 1 | /// http://example.org | ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` | - = note: `#[warn(rustdoc::non_autolinks)]` on by default - -warning: unneeded long form for URL - --> foo.rs:2:5 - | -2 | /// [http://example.com](http://example.com) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + = note: `#[warn(rustdoc::bare_urls)]` on by default warning: this URL is not a hyperlink - --> foo.rs:3:6 + --> links.rs:3:6 | 3 | /// [http://example.net] | ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + +warning: 2 warnings emitted ``` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 7d1845dc95..28b81a4026 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -88,26 +88,28 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg]. [unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html [issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781 -### Adding your trait to the "Important Traits" dialog - -Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when -implemented on it. These traits are intended to be the primary interface for their types, and are -often the only thing available to be documented on their types. For this reason, Rustdoc will track -when a given type implements one of these traits and call special attention to it when a function -returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next -to the function, which, when clicked, shows the dialog. - -In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and -`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a -special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this -attribute to your own trait to include it in the "Important Traits" dialog in documentation. - -The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate. -For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking -issue][issue-spotlight]. - -[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html -[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040 +### Adding your trait to the "Notable traits" dialog + +Rustdoc keeps a list of a few traits that are believed to be "fundamental" to +types that implement them. These traits are intended to be the primary interface +for their implementers, and are often most of the API available to be documented +on their types. For this reason, Rustdoc will track when a given type implements +one of these traits and call special attention to it when a function returns one +of these types. This is the "Notable traits" dialog, accessible as a circled `i` +button next to the function, which, when clicked, shows the dialog. + +In the standard library, some of the traits that are part of this list are +`Iterator`, `Future`, `io::Read`, and `io::Write`. However, rather than being +implemented as a hard-coded list, these traits have a special marker attribute +on them: `#[doc(notable_trait)]`. This means that you can apply this attribute +to your own trait to include it in the "Notable traits" dialog in documentation. + +The `#[doc(notable_trait)]` attribute currently requires the `#![feature(doc_notable_trait)]` +feature gate. For more information, see [its chapter in the Unstable Book][unstable-notable_trait] +and [its tracking issue][issue-notable_trait]. + +[unstable-notable_trait]: ../unstable-book/language-features/doc-notable-trait.html +[issue-notable_trait]: https://github.com/rust-lang/rust/issues/45040 ### Exclude certain dependencies from documentation diff --git a/src/doc/unstable-book/src/language-features/doc-notable-trait.md b/src/doc/unstable-book/src/language-features/doc-notable-trait.md new file mode 100644 index 0000000000..dc402ed425 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/doc-notable-trait.md @@ -0,0 +1,33 @@ +# `doc_notable_trait` + +The tracking issue for this feature is: [#45040] + +The `doc_notable_trait` feature allows the use of the `#[doc(notable_trait)]` +attribute, which will display the trait in a "Notable traits" dialog for +functions returning types that implement the trait. For example, this attribute +is applied to the `Iterator`, `Future`, `io::Read`, and `io::Write` traits in +the standard library. + +You can do this on your own traits like so: + +``` +#![feature(doc_notable_trait)] + +#[doc(notable_trait)] +pub trait MyTrait {} + +pub struct MyStruct; +impl MyTrait for MyStruct {} + +/// The docs for this function will have a button that displays a dialog about +/// `MyStruct` implementing `MyTrait`. +pub fn my_fn() -> MyStruct { MyStruct } +``` + +This feature was originally implemented in PR [#45039]. + +See also its documentation in [the rustdoc book][rustdoc-book-notable_trait]. + +[#45040]: https://github.com/rust-lang/rust/issues/45040 +[#45039]: https://github.com/rust-lang/rust/pull/45039 +[rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog diff --git a/src/doc/unstable-book/src/language-features/doc-spotlight.md b/src/doc/unstable-book/src/language-features/doc-spotlight.md deleted file mode 100644 index 75eff16331..0000000000 --- a/src/doc/unstable-book/src/language-features/doc-spotlight.md +++ /dev/null @@ -1,30 +0,0 @@ -# `doc_spotlight` - -The tracking issue for this feature is: [#45040] - -The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute, -to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]` -attribute to a trait definition will make rustdoc print extra information for functions which return -a type that implements that trait. For example, this attribute is applied to the `Iterator`, -`io::Read`, `io::Write`, and `Future` traits in the standard library. - -You can do this on your own traits, like this: - -``` -#![feature(doc_spotlight)] - -#[doc(spotlight)] -pub trait MyTrait {} - -pub struct MyStruct; -impl MyTrait for MyStruct {} - -/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`, -/// without having to write that yourself! -pub fn my_fn() -> MyStruct { MyStruct } -``` - -This feature was originally implemented in PR [#45039]. - -[#45040]: https://github.com/rust-lang/rust/issues/45040 -[#45039]: https://github.com/rust-lang/rust/pull/45039 diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 2278080461..86bedb5153 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -191,7 +191,7 @@ mechanisms of the compiler. This is often mapped to GCC's personality function which do not trigger a panic can be assured that this function is never called. The language item's name is `eh_personality`. -[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs +[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs The second function, `rust_begin_panic`, is also used by the failure mechanisms of the compiler. When a panic happens, this controls the message that's displayed on diff --git a/src/doc/unstable-book/src/language-features/link-args.md b/src/doc/unstable-book/src/language-features/link-args.md deleted file mode 100644 index da36e15800..0000000000 --- a/src/doc/unstable-book/src/language-features/link-args.md +++ /dev/null @@ -1,32 +0,0 @@ -# `link_args` - -The tracking issue for this feature is: [#29596] - -[#29596]: https://github.com/rust-lang/rust/issues/29596 - ------------------------- - -You can tell `rustc` how to customize linking, and that is via the `link_args` -attribute. This attribute is applied to `extern` blocks and specifies raw flags -which need to get passed to the linker when producing an artifact. An example -usage would be: - -```rust,no_run -#![feature(link_args)] - -#[link_args = "-foo -bar -baz"] -extern "C" {} -# fn main() {} -``` - -Note that this feature is currently hidden behind the `feature(link_args)` gate -because this is not a sanctioned way of performing linking. Right now `rustc` -shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC), so -it makes sense to provide extra command line arguments, but this will not -always be the case. In the future `rustc` may use LLVM directly to link native -libraries, in which case `link_args` will have no meaning. You can achieve the -same effect as the `link_args` attribute with the `-C link-args` argument to -`rustc`. - -It is highly recommended to *not* use this attribute, and rather use the more -formal `#[link(...)]` attribute on `extern` blocks instead. diff --git a/src/doc/unstable-book/src/language-features/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md deleted file mode 100644 index 847f25ecab..0000000000 --- a/src/doc/unstable-book/src/language-features/non-ascii-idents.md +++ /dev/null @@ -1,48 +0,0 @@ -# `non_ascii_idents` - -The tracking issue for this feature is: [#55467] - -[#55467]: https://github.com/rust-lang/rust/issues/55467 - ------------------------- - -The `non_ascii_idents` feature adds support for non-ASCII identifiers. - -## Examples - -```rust -#![feature(non_ascii_idents)] - -const ε: f64 = 0.00001f64; -const Π: f64 = 3.14f64; -``` - -## Changes to the language reference - -> **Lexer:**\ -> IDENTIFIER :\ ->       XID_start XID_continue\*\ ->    | `_` XID_continue+ - -An identifier is any nonempty Unicode string of the following form: - -Either - - * The first character has property [`XID_start`] - * The remaining characters have property [`XID_continue`] - -Or - - * The first character is `_` - * The identifier is more than one character, `_` alone is not an identifier - * The remaining characters have property [`XID_continue`] - -that does _not_ occur in the set of [strict keywords]. - -> **Note**: [`XID_start`] and [`XID_continue`] as character properties cover the -> character ranges used to form the more familiar C and Java language-family -> identifiers. - -[`XID_start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i= -[`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i= -[strict keywords]: ../../reference/keywords.md#strict-keywords diff --git a/src/doc/unstable-book/src/language-features/or-patterns.md b/src/doc/unstable-book/src/language-features/or-patterns.md deleted file mode 100644 index 55c31add26..0000000000 --- a/src/doc/unstable-book/src/language-features/or-patterns.md +++ /dev/null @@ -1,36 +0,0 @@ -# `or_patterns` - -The tracking issue for this feature is: [#54883] - -[#54883]: https://github.com/rust-lang/rust/issues/54883 - ------------------------- - -The `or_pattern` language feature allows `|` to be arbitrarily nested within -a pattern, for example, `Some(A(0) | B(1 | 2))` becomes a valid pattern. - -## Examples - -```rust,no_run -#![feature(or_patterns)] - -pub enum Foo { - Bar, - Baz, - Quux, -} - -pub fn example(maybe_foo: Option) { - match maybe_foo { - Some(Foo::Bar | Foo::Baz) => { - println!("The value contained `Bar` or `Baz`"); - } - Some(_) => { - println!("The value did not contain `Bar` or `Baz`"); - } - None => { - println!("The value was `None`"); - } - } -} -``` diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index c0e23b834d..4f9033cedc 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -35,7 +35,7 @@ Inline assembly is currently supported on the following architectures: Let us start with the simplest possible example: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] unsafe { asm!("nop"); } @@ -52,7 +52,7 @@ Now inserting an instruction that does nothing is rather boring. Let us do somet actually acts on data: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let x: u64; unsafe { asm!("mov {}, 5", out(reg) x); @@ -74,7 +74,7 @@ the template and will read the variable from there after the inline assembly fin Let us see another example that also uses an input: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let i: u64 = 3; let o: u64; unsafe { @@ -114,7 +114,7 @@ readability, and allows reordering instructions without changing the argument or We can further refine the above example to avoid the `mov` instruction: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let mut x: u64 = 3; unsafe { asm!("add {0}, {number}", inout(reg) x, number = const 5); @@ -128,7 +128,7 @@ This is different from specifying an input and output separately in that it is g It is also possible to specify different variables for the input and output parts of an `inout` operand: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let x: u64 = 3; let y: u64; unsafe { @@ -150,7 +150,7 @@ There is also a `inlateout` variant of this specifier. Here is an example where `inlateout` *cannot* be used: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let mut a: u64 = 4; let b: u64 = 4; let c: u64 = 4; @@ -171,7 +171,7 @@ Here the compiler is free to allocate the same register for inputs `b` and `c` s However the following example can use `inlateout` since the output is only modified after all input registers have been read: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let mut a: u64 = 4; let b: u64 = 4; unsafe { @@ -190,7 +190,7 @@ While `reg` is generally available on any architecture, these are highly archite among others can be addressed by their name. ```rust,allow_fail,no_run -# #![feature(asm)] +#![feature(asm)] let cmd = 0xd1; unsafe { asm!("out 0x64, eax", in("eax") cmd); @@ -206,7 +206,7 @@ Note that unlike other operand types, explicit register operands cannot be used Consider this example which uses the x86 `mul` instruction: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] fn mul(a: u64, b: u64) -> u128 { let lo: u64; let hi: u64; @@ -242,7 +242,7 @@ We need to tell the compiler about this since it may need to save and restore th around the inline assembly block. ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let ebx: u32; let ecx: u32; @@ -272,7 +272,7 @@ However we still need to tell the compiler that `eax` and `edx` have been modifi This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] // Multiply x by 6 using shifts and adds let mut x: u64 = 4; unsafe { @@ -294,7 +294,7 @@ A special operand type, `sym`, allows you to use the symbol name of a `fn` or `s This allows you to call a function or access a global variable without needing to keep its address in a register. ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] extern "C" fn foo(arg: i32) { println!("arg = {}", arg); } @@ -306,13 +306,19 @@ fn call_foo(arg: i32) { sym foo, // 1st argument in rdi, which is caller-saved inout("rdi") arg => _, - // All caller-saved registers must be marked as clobberred + // All caller-saved registers must be marked as clobbered out("rax") _, out("rcx") _, out("rdx") _, out("rsi") _, out("r8") _, out("r9") _, out("r10") _, out("r11") _, out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _, out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _, out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _, out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _, + // Also mark AVX-512 registers as clobbered. This is accepted by the + // compiler even if AVX-512 is not enabled on the current target. + out("xmm16") _, out("xmm17") _, out("xmm18") _, out("xmm19") _, + out("xmm20") _, out("xmm21") _, out("xmm22") _, out("xmm23") _, + out("xmm24") _, out("xmm25") _, out("xmm26") _, out("xmm27") _, + out("xmm28") _, out("xmm29") _, out("xmm30") _, out("xmm31") _, ) } } @@ -330,7 +336,7 @@ By default the compiler will always choose the name that refers to the full regi This default can be overriden by using modifiers on the template string operands, just like you would with format strings: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let mut x: u16 = 0xab; unsafe { @@ -355,7 +361,7 @@ For example, in x86/x86_64 and intel assembly syntax, you should wrap inputs/out to indicate they are memory operands: ```rust,allow_fail -# #![feature(asm, llvm_asm)] +#![feature(asm, llvm_asm)] # fn load_fpu_control_word(control: u16) { unsafe { asm!("fldcw [{}]", in(reg) &control, options(nostack)); @@ -366,6 +372,43 @@ unsafe { # } ``` +## Labels + +The compiler is allowed to instantiate multiple copies an `asm!` block, for example when the function containing it is inlined in multiple places. As a consequence, you should only use GNU assembler [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions. + +Moreover, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. + +```rust,allow_fail +#![feature(asm)] + +let mut a = 0; +unsafe { + asm!( + "mov {0}, 10", + "2:", + "sub {0}, 1", + "cmp {0}, 3", + "jle 2f", + "jmp 2b", + "2:", + "add {0}, 2", + out(reg) a + ); +} +assert_eq!(a, 5); +``` + +This will decrement the `{0}` register value from 10 to 3, then add 2 and store it in `a`. + +This example show a few thing: + +First that the same number can be used as a label multiple times in the same inline block. + +Second, that when a numeric label is used as a reference (as an instruction operand, for example), the suffixes b (“backward”) or f (“forward”) should be added to the numeric label. It will then refer to the nearest label defined by this number in this direction. + +[local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels +[an llvm bug]: https://bugs.llvm.org/show_bug.cgi?id=36144 + ## Options By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better. @@ -373,7 +416,7 @@ By default, an inline assembly block is treated the same way as an external FFI Let's take our previous example of an `add` instruction: ```rust,allow_fail -# #![feature(asm)] +#![feature(asm)] let mut a: u64 = 4; let b: u64 = 4; unsafe { @@ -495,7 +538,7 @@ Here is the list of currently supported register classes: | x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `r[8-15]` (x86-64 only) | `r` | | x86 | `reg_abcd` | `ax`, `bx`, `cx`, `dx` | `Q` | | x86-32 | `reg_byte` | `al`, `bl`, `cl`, `dl`, `ah`, `bh`, `ch`, `dh` | `q` | -| x86-64 | `reg_byte` | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `r[8-15]b`, `ah`\*, `bh`\*, `ch`\*, `dh`\* | `q` | +| x86-64 | `reg_byte`\* | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `r[8-15]b` | `q` | | x86 | `xmm_reg` | `xmm[0-7]` (x86) `xmm[0-15]` (x86-64) | `x` | | 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` | @@ -526,7 +569,7 @@ Here is the list of currently supported register classes: > **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register. > -> Note #2: On x86-64 the high byte registers (e.g. `ah`) are only available when used as an explicit register. Specifying the `reg_byte` register class for an operand will always allocate a low byte register. +> Note #2: On x86-64 the high byte registers (e.g. `ah`) are not available in the `reg_byte` register class. > > Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported. > @@ -781,8 +824,5 @@ The compiler performs some additional checks on options: - You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds). - The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited. - You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places. - - As a consequence, you should only use [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions. > **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call. - -[local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 702f2e82e4..86dcc335e3 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -527,20 +527,22 @@ class StdHashMapSyntheticProvider: def update(self): # type: () -> None table = self.table() - capacity = table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1 - ctrl = table.GetChildMemberWithName("ctrl").GetChildAtIndex(0) + inner_table = table.GetChildMemberWithName("table") - self.size = table.GetChildMemberWithName("items").GetValueAsUnsigned() + capacity = inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1 + ctrl = inner_table.GetChildMemberWithName("ctrl").GetChildAtIndex(0) + + self.size = inner_table.GetChildMemberWithName("items").GetValueAsUnsigned() self.pair_type = table.type.template_args[0] if self.pair_type.IsTypedefType(): self.pair_type = self.pair_type.GetTypedefedType() self.pair_type_size = self.pair_type.GetByteSize() - self.new_layout = not table.GetChildMemberWithName("data").IsValid() + self.new_layout = not inner_table.GetChildMemberWithName("data").IsValid() if self.new_layout: self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType()) else: - self.data_ptr = table.GetChildMemberWithName("data").GetChildAtIndex(0) + self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(0) u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar) u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize() @@ -563,7 +565,7 @@ class StdHashMapSyntheticProvider: # HashSet wraps either std HashMap or hashbrown::HashSet, which both # wrap hashbrown::HashMap, so either way we "unwrap" twice. hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0) - return hashbrown_hashmap.GetChildMemberWithName("table").GetChildMemberWithName("table") + return hashbrown_hashmap.GetChildMemberWithName("table") def has_children(self): # type: () -> bool diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 2d0722396f..b816b9d718 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" path = "lib.rs" [dependencies] -arrayvec = { version = "0.5.1", default-features = false } +arrayvec = { version = "0.7", default-features = false } pulldown-cmark = { version = "0.8", default-features = false } minifier = "0.0.39" rayon = { version = "0.3.0", package = "rustc-rayon" } @@ -29,3 +29,9 @@ features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] [dev-dependencies] expect-test = "1.0" + +[features] +jemalloc = [] + +[package.metadata.rust-analyzer] +rustc_private = true diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index d0e058c7dd..92eb6214f7 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -110,12 +110,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { }; Some(Item { - source: Span::dummy(), name: None, attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(item_def_id.krate), kind: box ImplItem(Impl { + span: Span::dummy(), unsafety: hir::Unsafety::Normal, generics: new_generics, provided_trait_methods: Default::default(), @@ -126,6 +126,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { synthetic: true, blanket_impl: None, }), + cfg: None, }) } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 4e4e1e5cbc..3a14a1d23f 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -26,18 +26,16 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { { continue; } - self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { + // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls + let trait_impls = self.cx.tcx.trait_impls_of(trait_def_id); + for &impl_def_id in trait_impls.blanket_impls() { debug!( "get_blanket_impls: Considering impl for trait '{:?}' {:?}", trait_def_id, impl_def_id ); let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap(); - let may_apply = self.cx.tcx.infer_ctxt().enter(|infcx| { - match trait_ref.self_ty().kind() { - ty::Param(_) => {} - _ => return false, - } - + let is_param = matches!(trait_ref.self_ty().kind(), ty::Param(_)); + let may_apply = is_param && self.cx.tcx.infer_ctxt().enter(|infcx| { let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id); let ty = ty.subst(infcx.tcx, substs); let param_env = param_env.subst(infcx.tcx, substs); @@ -90,7 +88,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { may_apply, trait_ref, ty ); if !may_apply { - return; + continue; } self.cx.generated_synthetics.insert((ty, trait_def_id)); @@ -102,12 +100,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .collect(); impls.push(Item { - source: self.cx.tcx.def_span(impl_def_id).clean(self.cx), name: None, attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(impl_def_id.krate), kind: box ImplItem(Impl { + span: self.cx.tcx.def_span(impl_def_id).clean(self.cx), unsafety: hir::Unsafety::Normal, generics: ( self.cx.tcx.generics_of(impl_def_id), @@ -130,8 +128,9 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { synthetic: false, blanket_impl: Some(trait_ref.self_ty().clean(self.cx)), }), + cfg: None, }); - }); + } } impls } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 02adccef59..592aefb6a4 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -498,7 +498,7 @@ impl<'a> fmt::Display for Display<'a> { "powerpc64" => "PowerPC-64", "s390x" => "s390x", "sparc64" => "SPARC64", - "wasm32" => "WebAssembly", + "wasm32" | "wasm64" => "WebAssembly", "x86" => "x86", "x86_64" => "x86-64", _ => "", diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 47a74238a7..3e89c1ac4c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -1,21 +1,21 @@ //! Support for inlining external documentation into the current AST. use std::iter::once; +use std::sync::Arc; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::DefId; use rustc_hir::Mutability; use rustc_metadata::creader::LoadedMacro; -use rustc_middle::ty; -use rustc_mir::const_eval::is_min_const_fn; +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, GetDefId, ToSource, TypeKind}; +use crate::clean::{self, Attributes, AttributesExt, GetDefId, ToSource}; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -56,36 +56,36 @@ crate fn try_inline( let kind = match res { Res::Def(DefKind::Trait, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Trait); + record_extern_fqn(cx, did, ItemType::Trait); build_impls(cx, Some(parent_module), did, attrs, &mut ret); clean::TraitItem(build_external_trait(cx, did)) } Res::Def(DefKind::Fn, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Function); + record_extern_fqn(cx, did, ItemType::Function); clean::FunctionItem(build_external_function(cx, did)) } Res::Def(DefKind::Struct, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Struct); + record_extern_fqn(cx, did, ItemType::Struct); build_impls(cx, Some(parent_module), did, attrs, &mut ret); clean::StructItem(build_struct(cx, did)) } Res::Def(DefKind::Union, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Union); + record_extern_fqn(cx, did, ItemType::Union); build_impls(cx, Some(parent_module), did, attrs, &mut ret); clean::UnionItem(build_union(cx, did)) } Res::Def(DefKind::TyAlias, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Typedef); + record_extern_fqn(cx, did, ItemType::Typedef); build_impls(cx, Some(parent_module), did, attrs, &mut ret); clean::TypedefItem(build_type_alias(cx, did), false) } Res::Def(DefKind::Enum, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Enum); + record_extern_fqn(cx, did, ItemType::Enum); build_impls(cx, Some(parent_module), did, attrs, &mut ret); clean::EnumItem(build_enum(cx, did)) } Res::Def(DefKind::ForeignTy, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Foreign); + record_extern_fqn(cx, did, ItemType::ForeignType); build_impls(cx, Some(parent_module), did, attrs, &mut ret); clean::ForeignTypeItem } @@ -95,24 +95,24 @@ crate fn try_inline( // their constructors. Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => return Some(Vec::new()), Res::Def(DefKind::Mod, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Module); + record_extern_fqn(cx, did, ItemType::Module); clean::ModuleItem(build_module(cx, did, visited)) } Res::Def(DefKind::Static, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Static); + record_extern_fqn(cx, did, ItemType::Static); clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did))) } Res::Def(DefKind::Const, did) => { - record_extern_fqn(cx, did, clean::TypeKind::Const); + record_extern_fqn(cx, did, ItemType::Constant); clean::ConstantItem(build_const(cx, did)) } Res::Def(DefKind::Macro(kind), did) => { let mac = build_macro(cx, did, name); let type_kind = match kind { - MacroKind::Bang => TypeKind::Macro, - MacroKind::Attr => TypeKind::Attr, - MacroKind::Derive => TypeKind::Derive, + MacroKind::Bang => ItemType::Macro, + MacroKind::Attr => ItemType::ProcAttribute, + MacroKind::Derive => ItemType::ProcDerive, }; record_extern_fqn(cx, did, type_kind); mac @@ -120,12 +120,16 @@ crate fn try_inline( _ => return None, }; - let target_attrs = load_attrs(cx, did); - let attrs = box merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone); - + let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone); cx.inlined.insert(did); - let what_rustc_thinks = clean::Item::from_def_id_and_parts(did, Some(name), kind, cx); - ret.push(clean::Item { attrs, ..what_rustc_thinks }); + ret.push(clean::Item::from_def_id_and_attrs_and_parts( + did, + Some(name), + kind, + box attrs, + cx, + cfg, + )); Some(ret) } @@ -157,7 +161,7 @@ crate fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> { /// /// These names are used later on by HTML rendering to generate things like /// source links back to the original item. -crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: clean::TypeKind) { +crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) { let crate_name = cx.tcx.crate_name(did.krate).to_string(); let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| { @@ -165,7 +169,7 @@ crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: clean::Typ let s = elem.data.to_string(); if !s.is_empty() { Some(s) } else { None } }); - let fqn = if let clean::TypeKind::Macro = kind { + let fqn = if let ItemType::Macro = kind { // Check to see if it is a macro 2.0 or built-in macro if matches!( cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())), @@ -210,7 +214,7 @@ fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Functi let sig = cx.tcx.fn_sig(did); let constness = - if is_min_const_fn(cx.tcx, did) { hir::Constness::Const } else { hir::Constness::NotConst }; + if cx.tcx.is_const_fn_raw(did) { hir::Constness::Const } else { hir::Constness::NotConst }; let asyncness = cx.tcx.asyncness(did); let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, |cx| { @@ -289,22 +293,24 @@ fn merge_attrs( parent_module: Option, old_attrs: Attrs<'_>, new_attrs: Option>, -) -> clean::Attributes { +) -> (clean::Attributes, Option>) { // NOTE: If we have additional attributes (from a re-export), // always insert them first. This ensure that re-export // doc comments show up before the original doc comments // when we render them. if let Some(inner) = new_attrs { - if let Some(new_id) = parent_module { - let diag = cx.sess().diagnostic(); - Attributes::from_ast(diag, old_attrs, Some((inner, new_id))) - } else { - let mut both = inner.to_vec(); - both.extend_from_slice(old_attrs); - both.clean(cx) - } + let mut both = inner.to_vec(); + both.extend_from_slice(old_attrs); + ( + if let Some(new_id) = parent_module { + Attributes::from_ast(old_attrs, Some((inner, new_id))) + } else { + Attributes::from_ast(&both, None) + }, + both.cfg(cx.sess().diagnostic()), + ) } else { - old_attrs.clean(cx) + (old_attrs.clean(cx), old_attrs.cfg(cx.sess().diagnostic())) } } @@ -415,13 +421,14 @@ crate fn build_impl( debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); - let attrs = box merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs); - debug!("merged_attrs={:?}", attrs); + let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs); + debug!("merged_attrs={:?}", merged_attrs); ret.push(clean::Item::from_def_id_and_attrs_and_parts( did, None, clean::ImplItem(clean::Impl { + span: clean::types::rustc_span(did, cx.tcx), unsafety: hir::Unsafety::Normal, generics, provided_trait_methods: provided, @@ -432,8 +439,9 @@ crate fn build_impl( synthetic: false, blanket_impl: None, }), - attrs, + box merged_attrs, cx, + cfg, )); } @@ -459,8 +467,7 @@ fn build_module( items.push(clean::Item { name: None, attrs: box clean::Attributes::default(), - source: clean::Span::dummy(), - def_id: DefId::local(CRATE_DEF_INDEX), + def_id: cx.next_def_id(did.krate), visibility: clean::Public, kind: box clean::ImportItem(clean::Import::new_simple( item.ident.name, @@ -480,6 +487,7 @@ fn build_module( }, true, )), + cfg: None, }); } else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) { items.extend(i) @@ -487,26 +495,23 @@ fn build_module( } } - clean::Module { items, is_crate: false } + let span = clean::Span::from_rustc_span(cx.tcx.def_span(did)); + clean::Module { items, span } } -crate fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String { +crate fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String { if let Some(did) = did.as_local() { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(did); - rustc_hir_pretty::id_to_string(&cx.tcx.hir(), hir_id) + let hir_id = tcx.hir().local_def_id_to_hir_id(did); + rustc_hir_pretty::id_to_string(&tcx.hir(), hir_id) } else { - cx.tcx.rendered_const(did) + tcx.rendered_const(did) } } -fn build_const(cx: &mut DocContext<'_>, did: DefId) -> clean::Constant { +fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant { clean::Constant { - type_: cx.tcx.type_of(did).clean(cx), - expr: print_inlined_const(cx, did), - value: clean::utils::print_evaluated_const(cx, did), - is_literal: did.as_local().map_or(false, |did| { - clean::utils::is_literal_expr(cx, cx.tcx.hir().local_def_id_to_hir_id(did)) - }), + type_: cx.tcx.type_of(def_id).clean(cx), + kind: clean::ConstantKind::Extern { def_id }, } } @@ -628,7 +633,7 @@ crate fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) { let trait_ = clean::TraitWithExtraInfo { trait_, - is_spotlight: clean::utils::has_doc_flag(cx.tcx.get_attrs(did), sym::spotlight), + is_notable: clean::utils::has_doc_flag(cx.tcx.get_attrs(did), sym::notable_trait), }; cx.external_traits.borrow_mut().insert(did, trait_); cx.active_extern_traits.remove(&did); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 17a961a5f6..6563f398ed 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -22,7 +22,7 @@ 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_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn}; +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}; @@ -36,6 +36,7 @@ use std::{mem, vec}; use crate::core::{self, DocContext, ImplTraitParam}; use crate::doctree; +use crate::formats::item_type::ItemType; use utils::*; @@ -83,126 +84,8 @@ impl, U> Clean> for Option { } impl Clean for CrateNum { - fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate { - let tcx = cx.tcx; - let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; - let krate_span = tcx.def_span(root); - let krate_src = cx.sess().source_map().span_to_filename(krate_span); - - // Collect all inner modules which are tagged as implementations of - // primitives. - // - // Note that this loop only searches the top-level items of the crate, - // and this is intentional. If we were to search the entire crate for an - // item tagged with `#[doc(primitive)]` then we would also have to - // search the entirety of external modules for items tagged - // `#[doc(primitive)]`, which is a pretty inefficient process (decoding - // all that metadata unconditionally). - // - // In order to keep the metadata load under control, the - // `#[doc(primitive)]` feature is explicitly designed to only allow the - // primitive tags to show up as the top level items in a crate. - // - // Also note that this does not attempt to deal with modules tagged - // duplicately for the same primitive. This is handled later on when - // rendering by delegating everything to a hash map. - let mut as_primitive = |res: Res| { - if let Res::Def(DefKind::Mod, def_id) = res { - let attrs = cx.tcx.get_attrs(def_id).clean(cx); - let mut prim = None; - for attr in attrs.lists(sym::doc) { - if let Some(v) = attr.value_str() { - if attr.has_name(sym::primitive) { - prim = PrimitiveType::from_symbol(v); - if prim.is_some() { - break; - } - // FIXME: should warn on unknown primitives? - } - } - } - return prim.map(|p| (def_id, p)); - } - None - }; - let primitives = if root.is_local() { - tcx.hir() - .krate() - .item - .module - .item_ids - .iter() - .filter_map(|&id| { - let item = tcx.hir().item(id); - match item.kind { - hir::ItemKind::Mod(_) => { - as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id())) - } - hir::ItemKind::Use(ref path, hir::UseKind::Single) - if item.vis.node.is_pub() => - { - as_primitive(path.res).map(|(_, prim)| { - // Pretend the primitive is local. - (id.def_id.to_def_id(), prim) - }) - } - _ => None, - } - }) - .collect() - } else { - tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect() - }; - - let mut as_keyword = |res: Res| { - if let Res::Def(DefKind::Mod, def_id) = res { - let attrs = tcx.get_attrs(def_id).clean(cx); - let mut keyword = None; - for attr in attrs.lists(sym::doc) { - if attr.has_name(sym::keyword) { - if let Some(v) = attr.value_str() { - keyword = Some(v); - break; - } - } - } - return keyword.map(|p| (def_id, p)); - } - None - }; - let keywords = if root.is_local() { - tcx.hir() - .krate() - .item - .module - .item_ids - .iter() - .filter_map(|&id| { - let item = tcx.hir().item(id); - match item.kind { - hir::ItemKind::Mod(_) => { - as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id())) - } - hir::ItemKind::Use(ref path, hir::UseKind::Single) - if item.vis.node.is_pub() => - { - as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim)) - } - _ => None, - } - }) - .collect() - } else { - tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect() - }; - - ExternalCrate { - name: tcx.crate_name(*self), - src: krate_src, - attrs: tcx.get_attrs(root).clean(cx), - primitives, - keywords, - } + fn clean(&self, _cx: &mut DocContext<'_>) -> ExternalCrate { + ExternalCrate { crate_num: *self } } } @@ -216,7 +99,7 @@ impl Clean for doctree::Module<'_> { // determine if we should display the inner contents or // the outer `mod` item for the source code. - let span = { + let span = Span::from_rustc_span({ let sm = cx.sess().source_map(); let outer = sm.lookup_char_pos(self.where_outer.lo()); let inner = sm.lookup_char_pos(self.where_inner.lo()); @@ -227,21 +110,20 @@ impl Clean for doctree::Module<'_> { // mod foo; (and a separate SourceFile for the contents) self.where_inner } - }; + }); - let what_rustc_thinks = Item::from_hir_id_and_parts( + Item::from_hir_id_and_parts( self.id, - self.name, - ModuleItem(Module { is_crate: self.is_crate, items }), + Some(self.name), + ModuleItem(Module { items, span }), cx, - ); - Item { source: span.clean(cx), ..what_rustc_thinks } + ) } } impl Clean for [ast::Attribute] { - fn clean(&self, cx: &mut DocContext<'_>) -> Attributes { - Attributes::from_ast(cx.sess().diagnostic(), self, None) + fn clean(&self, _cx: &mut DocContext<'_>) -> Attributes { + Attributes::from_ast(self, None) } } @@ -275,7 +157,7 @@ impl Clean for hir::GenericBound<'_> { impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { fn clean(&self, cx: &mut DocContext<'_>) -> Type { let (trait_ref, bounds) = *self; - inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait); + inline::record_extern_fqn(cx, trait_ref.def_id, ItemType::Trait); let path = external_path( cx, cx.tcx.item_name(trait_ref.def_id), @@ -354,7 +236,7 @@ impl Clean for hir::Lifetime { match def { Some( rl::Region::EarlyBound(_, node_id, _) - | rl::Region::LateBound(_, node_id, _) + | rl::Region::LateBound(_, _, node_id, _) | rl::Region::Free(_, node_id), ) => { if let Some(lt) = cx.lt_substs.get(&node_id).cloned() { @@ -398,9 +280,7 @@ impl Clean for hir::ConstArg { .tcx .type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id()) .clean(cx), - expr: print_const_expr(cx.tcx, self.value.body), - value: None, - is_literal: is_literal_expr(cx, self.value.body.hir_id), + kind: ConstantKind::Anonymous { body: self.value.body }, } } } @@ -415,7 +295,7 @@ impl Clean> for ty::RegionKind { fn clean(&self, _cx: &mut DocContext<'_>) -> Option { match *self { ty::ReStatic => Some(Lifetime::statik()), - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) => { + ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => { Some(Lifetime(name)) } ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)), @@ -969,7 +849,6 @@ where inputs: (self.0.inputs, self.1).clean(cx), output: self.0.output.clean(cx), c_variadic: self.0.c_variadic, - attrs: Attributes::default(), } } } @@ -981,7 +860,6 @@ impl<'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { FnDecl { output: Return(sig.skip_binder().output().clean(cx)), - attrs: Attributes::default(), c_variadic: sig.skip_binder().c_variadic, inputs: Arguments { values: sig @@ -1032,12 +910,6 @@ impl Clean for hir::PolyTraitRef<'_> { } } -impl Clean for hir::def::DefKind { - fn clean(&self, _: &mut DocContext<'_>) -> TypeKind { - (*self).into() - } -} - impl Clean for hir::TraitItem<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let local_did = self.def_id.to_def_id(); @@ -1135,7 +1007,7 @@ impl Clean for ty::AssocItem { ty::AssocKind::Const => { let ty = tcx.type_of(self.def_id); let default = if self.defaultness.has_value() { - Some(inline::print_inlined_const(cx, self.def_id)) + Some(inline::print_inlined_const(tcx, self.def_id)) } else { None }; @@ -1173,7 +1045,7 @@ impl Clean for ty::AssocItem { ty::TraitContainer(_) => self.defaultness.has_value(), }; if provided { - let constness = if is_min_const_fn(tcx, self.def_id) { + let constness = if tcx.is_const_fn_raw(self.def_id) { hir::Constness::Const } else { hir::Constness::NotConst @@ -1572,16 +1444,16 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Adt(def, substs) => { let did = def.did; let kind = match def.adt_kind() { - AdtKind::Struct => TypeKind::Struct, - AdtKind::Union => TypeKind::Union, - AdtKind::Enum => TypeKind::Enum, + AdtKind::Struct => ItemType::Struct, + AdtKind::Union => ItemType::Union, + AdtKind::Enum => ItemType::Enum, }; 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 } } ty::Foreign(did) => { - inline::record_extern_fqn(cx, did, TypeKind::Foreign); + inline::record_extern_fqn(cx, did, ItemType::ForeignType); let path = external_path( cx, cx.tcx.item_name(did), @@ -1606,7 +1478,7 @@ impl<'tcx> Clean for Ty<'tcx> { _ => cx.tcx.intern_substs(&[]), }; - inline::record_extern_fqn(cx, did, TypeKind::Trait); + inline::record_extern_fqn(cx, did, ItemType::Trait); let mut param_names = vec![]; if let Some(b) = reg.clean(cx) { @@ -1616,7 +1488,7 @@ impl<'tcx> Clean for Ty<'tcx> { 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, TypeKind::Trait); + inline::record_extern_fqn(cx, did, ItemType::Trait); let bound = GenericBound::TraitBound( PolyTrait { trait_: ResolvedPath { @@ -1745,11 +1617,10 @@ impl<'tcx> Clean for Ty<'tcx> { impl<'tcx> Clean for ty::Const<'tcx> { fn clean(&self, cx: &mut DocContext<'_>) -> Constant { + // FIXME: instead of storing the stringified expression, store `self` directly instead. Constant { type_: self.ty.clean(cx), - expr: format!("{}", self), - value: None, - is_literal: false, + kind: ConstantKind::TyConst { expr: self.to_string() }, } } } @@ -1953,9 +1824,7 @@ impl Clean> for (&hir::Item<'_>, Option) { } ItemKind::Const(ty, body_id) => ConstantItem(Constant { type_: ty.clean(cx), - expr: print_const_expr(cx.tcx, body_id), - value: print_evaluated_const(cx, def_id), - is_literal: is_literal_expr(cx, body_id.hir_id), + kind: ConstantKind::Local { body: body_id, def_id }, }), ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { bounds: ty.bounds.clean(cx), @@ -2073,6 +1942,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> }); let mut make_item = |trait_: Option, for_: Type, items: Vec| { let kind = ImplItem(Impl { + span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx), unsafety: impl_.unsafety, generics: impl_.generics.clean(cx), provided_trait_methods: provided.clone(), @@ -2128,14 +1998,15 @@ fn clean_extern_crate( return items; } } + // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason vec![Item { name: Some(name), attrs: box attrs.clean(cx), - source: krate.span.clean(cx), def_id: crate_def_id, visibility: krate.vis.clean(cx), kind: box ExternCrateItem { src: orig_name }, + cfg: attrs.cfg(cx.sess().diagnostic()), }] } @@ -2294,14 +2165,14 @@ impl Clean for (&hir::MacroDef<'_>, Option) { if matchers.len() <= 1 { format!( "{}macro {}{} {{\n ...\n}}", - vis.print_with_space(cx.tcx, def_id, &cx.cache), + vis.to_src_with_space(cx.tcx, def_id), name, matchers.iter().map(|span| span.to_src(cx)).collect::(), ) } else { format!( "{}macro {} {{\n{}}}", - vis.print_with_space(cx.tcx, def_id, &cx.cache), + vis.to_src_with_space(cx.tcx, def_id), name, matchers .iter() diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 840a42c2b8..ad4a09d45f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -9,15 +9,16 @@ use std::sync::Arc; use std::{slice, vec}; use arrayvec::ArrayVec; + use rustc_ast::attr; use rustc_ast::util::comments::beautify_doc_string; use rustc_ast::{self as ast, AttrStyle}; use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_feature::UnstableFeatures; +use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex}; +use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyId, Mutability}; use rustc_index::vec::IndexVec; @@ -32,13 +33,15 @@ use rustc_target::spec::abi::Abi; use crate::clean::cfg::Cfg; use crate::clean::external_path; -use crate::clean::inline; +use crate::clean::inline::{self, print_inlined_const}; use crate::clean::types::Type::{QPath, ResolvedPath}; +use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const}; use crate::clean::Clean; use crate::core::DocContext; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::render::cache::ExternalLocation; +use crate::html::render::Context; use self::FnRetTy::*; use self::ItemKind::*; @@ -51,9 +54,9 @@ thread_local!(crate static MAX_DEF_IDX: RefCell> = crate struct Crate { crate name: Symbol, crate src: FileName, - crate module: Option, + crate module: Item, crate externs: Vec<(CrateNum, ExternalCrate)>, - crate primitives: Vec<(DefId, PrimitiveType)>, + 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. crate external_traits: Rc>>, @@ -64,16 +67,142 @@ crate struct Crate { #[derive(Clone, Debug)] crate struct TraitWithExtraInfo { crate trait_: Trait, - crate is_spotlight: bool, + crate is_notable: bool, } #[derive(Clone, Debug)] crate struct ExternalCrate { - crate name: Symbol, - crate src: FileName, - crate attrs: Attributes, - crate primitives: Vec<(DefId, PrimitiveType)>, - crate keywords: Vec<(DefId, Symbol)>, + crate crate_num: CrateNum, +} + +impl ExternalCrate { + #[inline] + fn def_id(&self) -> DefId { + DefId { krate: self.crate_num, index: CRATE_DEF_INDEX } + } + + crate fn src(&self, tcx: TyCtxt<'_>) -> FileName { + let krate_span = tcx.def_span(self.def_id()); + tcx.sess.source_map().span_to_filename(krate_span) + } + + crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol { + tcx.crate_name(self.crate_num) + } + + crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> { + let root = self.def_id(); + + let as_keyword = |res: Res| { + if let Res::Def(DefKind::Mod, def_id) = res { + let attrs = tcx.get_attrs(def_id); + let mut keyword = None; + for attr in attrs.lists(sym::doc) { + if attr.has_name(sym::keyword) { + if let Some(v) = attr.value_str() { + keyword = Some(v); + break; + } + } + } + return keyword.map(|p| (def_id, p)); + } + None + }; + if root.is_local() { + tcx.hir() + .krate() + .item + .item_ids + .iter() + .filter_map(|&id| { + let item = tcx.hir().item(id); + match item.kind { + hir::ItemKind::Mod(_) => { + as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id())) + } + hir::ItemKind::Use(ref path, hir::UseKind::Single) + if item.vis.node.is_pub() => + { + as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim)) + } + _ => None, + } + }) + .collect() + } else { + tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect() + } + } + + crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> { + let root = self.def_id(); + + // Collect all inner modules which are tagged as implementations of + // primitives. + // + // Note that this loop only searches the top-level items of the crate, + // and this is intentional. If we were to search the entire crate for an + // item tagged with `#[doc(primitive)]` then we would also have to + // search the entirety of external modules for items tagged + // `#[doc(primitive)]`, which is a pretty inefficient process (decoding + // all that metadata unconditionally). + // + // In order to keep the metadata load under control, the + // `#[doc(primitive)]` feature is explicitly designed to only allow the + // primitive tags to show up as the top level items in a crate. + // + // Also note that this does not attempt to deal with modules tagged + // duplicately for the same primitive. This is handled later on when + // rendering by delegating everything to a hash map. + let as_primitive = |res: Res| { + if let Res::Def(DefKind::Mod, def_id) = res { + let attrs = tcx.get_attrs(def_id); + let mut prim = None; + for attr in attrs.lists(sym::doc) { + if let Some(v) = attr.value_str() { + if attr.has_name(sym::primitive) { + prim = PrimitiveType::from_symbol(v); + if prim.is_some() { + break; + } + // FIXME: should warn on unknown primitives? + } + } + } + return prim.map(|p| (def_id, p)); + } + None + }; + + if root.is_local() { + tcx.hir() + .krate() + .item + .item_ids + .iter() + .filter_map(|&id| { + let item = tcx.hir().item(id); + match item.kind { + hir::ItemKind::Mod(_) => { + as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id())) + } + hir::ItemKind::Use(ref path, hir::UseKind::Single) + if item.vis.node.is_pub() => + { + as_primitive(path.res).map(|(_, prim)| { + // Pretend the primitive is local. + (id.def_id.to_def_id(), prim) + }) + } + _ => None, + } + }) + .collect() + } else { + tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect() + } + } } /// Anything with a source location and set of attributes and, optionally, a @@ -81,14 +210,17 @@ crate struct ExternalCrate { /// directly to the AST's concept of an item; it's a strict superset. #[derive(Clone)] crate struct Item { - /// Stringified span - crate source: Span, - /// Not everything has a name. E.g., impls + /// The name of this item. + /// Optional because not every item has a name, e.g. impls. crate name: Option, crate attrs: Box, crate visibility: Visibility, + /// Information about this item that is specific to what kind of item it is. + /// E.g., struct vs enum vs function. crate kind: Box, crate def_id: DefId, + + crate cfg: Option>, } // `Item` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -100,16 +232,26 @@ impl fmt::Debug for Item { let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id }; fmt.debug_struct("Item") - .field("source", &self.source) .field("name", &self.name) .field("attrs", &self.attrs) .field("kind", &self.kind) .field("visibility", &self.visibility) .field("def_id", def_id) + .field("cfg", &self.cfg) .finish() } } +crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span { + Span::from_rustc_span(def_id.as_local().map_or_else( + || tcx.def_span(def_id), + |local| { + let hir = tcx.hir(); + hir.span_with_body(hir.local_def_id_to_hir_id(local)) + }, + )) +} + 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) } @@ -123,6 +265,30 @@ impl Item { if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) } } + crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool { + if self.is_fake() { false } else { tcx.get_attrs(self.def_id).inner_docs() } + } + + crate fn span(&self, tcx: TyCtxt<'_>) -> Span { + let kind = match &*self.kind { + ItemKind::StrippedItem(k) => k, + _ => &*self.kind, + }; + if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) = + kind + { + *span + } else if self.is_fake() { + Span::dummy() + } else { + rustc_span(self.def_id, tcx) + } + } + + crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span { + crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner()) + } + /// Finds the `doc` attribute as a NameValue and returns the corresponding /// value found. crate fn doc_value(&self) -> Option { @@ -146,12 +312,15 @@ impl Item { kind: ItemKind, cx: &mut DocContext<'_>, ) -> Item { + let ast_attrs = cx.tcx.get_attrs(def_id); + Self::from_def_id_and_attrs_and_parts( def_id, name, kind, - box cx.tcx.get_attrs(def_id).clean(cx), + box ast_attrs.clean(cx), cx, + ast_attrs.cfg(cx.sess().diagnostic()), ) } @@ -161,25 +330,17 @@ impl Item { kind: ItemKind, attrs: Box, cx: &mut DocContext<'_>, + cfg: Option>, ) -> Item { debug!("name={:?}, def_id={:?}", name, def_id); - // `span_if_local()` lies about functions and only gives the span of the function signature - let source = def_id.as_local().map_or_else( - || cx.tcx.def_span(def_id), - |local| { - let hir = cx.tcx.hir(); - hir.span_with_body(hir.local_def_id_to_hir_id(local)) - }, - ); - Item { def_id, kind: box kind, name, - source: source.clean(cx), attrs, visibility: cx.tcx.visibility(def_id).clean(cx), + cfg, } } @@ -189,17 +350,78 @@ impl Item { self.attrs.collapsed_doc_value() } - crate fn links(&self, cache: &Cache) -> Vec { - self.attrs.links(self.def_id.krate, cache) + crate fn links(&self, cx: &Context<'_>) -> Vec { + use crate::html::format::href; + + cx.cache() + .intra_doc_links + .get(&self.def_id) + .map_or(&[][..], |v| v.as_slice()) + .iter() + .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| { + match *did { + Some(did) => { + if let Some((mut href, ..)) = href(did, cx) { + if let Some(ref fragment) = *fragment { + href.push('#'); + href.push_str(fragment); + } + Some(RenderedLink { + original_text: s.clone(), + new_text: link_text.clone(), + href, + }) + } else { + None + } + } + // FIXME(83083): using fragments as a side-channel for + // primitive names is very unfortunate + None => { + let relative_to = &cx.current; + if let Some(ref fragment) = *fragment { + let url = match cx.cache().extern_locations.get(&self.def_id.krate) { + Some(&(_, _, ExternalLocation::Local)) => { + if relative_to[0] == "std" { + let depth = relative_to.len() - 1; + "../".repeat(depth) + } else { + let depth = relative_to.len(); + format!("{}std/", "../".repeat(depth)) + } + } + Some(&(_, _, ExternalLocation::Remote(ref s))) => { + format!("{}/std/", s.trim_end_matches('/')) + } + Some(&(_, _, ExternalLocation::Unknown)) | None => { + "https://doc.rust-lang.org/nightly/std/".to_string() + } + }; + // This is a primitive so the url is done "by hand". + let tail = fragment.find('#').unwrap_or_else(|| fragment.len()); + Some(RenderedLink { + original_text: s.clone(), + new_text: link_text.clone(), + href: format!( + "{}primitive.{}.html{}", + url, + &fragment[..tail], + &fragment[tail..] + ), + }) + } else { + panic!("This isn't a primitive?!"); + } + } + } + }) + .collect() } crate fn is_crate(&self) -> bool { - matches!( - *self.kind, - StrippedItem(box ModuleItem(Module { is_crate: true, .. })) - | ModuleItem(Module { is_crate: true, .. }) - ) + self.is_mod() && self.def_id.index == CRATE_DEF_INDEX } + crate fn is_mod(&self) -> bool { self.type_() == ItemType::Module } @@ -411,7 +633,7 @@ impl ItemKind { #[derive(Clone, Debug)] crate struct Module { crate items: Vec, - crate is_crate: bool, + crate span: Span, } crate struct ListAttributesIter<'a> { @@ -451,12 +673,72 @@ impl<'a> Iterator for ListAttributesIter<'a> { crate trait AttributesExt { /// Finds an attribute as List and returns the list of attributes nested inside. fn lists(&self, name: Symbol) -> ListAttributesIter<'_>; + + fn span(&self) -> Option; + + fn inner_docs(&self) -> bool; + + fn other_attrs(&self) -> Vec; + + fn cfg(&self, diagnostic: &::rustc_errors::Handler) -> Option>; } impl AttributesExt for [ast::Attribute] { fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name } } + + /// Return the span of the first doc-comment, if it exists. + fn span(&self) -> Option { + self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span) + } + + /// Returns whether the first doc-comment is an inner attribute. + /// + //// If there are no doc-comments, return true. + /// FIXME(#78591): Support both inner and outer attributes on the same item. + fn inner_docs(&self) -> bool { + self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner) + } + + fn other_attrs(&self) -> Vec { + self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect() + } + + fn cfg(&self, diagnostic: &::rustc_errors::Handler) -> Option> { + let mut cfg = Cfg::True; + + for attr in self.iter() { + if attr.doc_str().is_none() && attr.has_name(sym::doc) { + if let Some(mi) = attr.meta() { + if let Some(cfg_mi) = Attributes::extract_cfg(&mi) { + // Extracted #[doc(cfg(...))] + match Cfg::parse(cfg_mi) { + Ok(new_cfg) => cfg &= new_cfg, + Err(e) => diagnostic.span_err(e.span, e.msg), + } + } + } + } + } + + for attr in self.lists(sym::target_feature) { + if attr.has_name(sym::enable) { + if let Some(feat) = attr.value_str() { + let meta = attr::mk_name_value_item_str( + Ident::with_dummy_span(sym::target_feature), + feat, + DUMMY_SP, + ); + if let Ok(feat_cfg) = Cfg::parse(&meta) { + cfg &= feat_cfg; + } + } + } + } + + if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) } + } } crate trait NestedAttributesExt { @@ -559,21 +841,18 @@ impl<'a> FromIterator<&'a DocFragment> for String { } } +/// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`, +/// as well as doc comments. #[derive(Clone, Debug, Default)] crate struct Attributes { crate doc_strings: Vec, crate other_attrs: Vec, - crate cfg: Option>, - crate span: Option, - /// map from Rust paths to resolved defs and potential URL fragments - crate links: Vec, - crate inner_docs: bool, } #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] /// A link that has not yet been rendered. /// -/// This link will be turned into a rendered link by [`Attributes::links`] +/// This link will be turned into a rendered link by [`Item::links`]. crate struct ItemLink { /// The original link written in the markdown pub(crate) link: String, @@ -599,6 +878,10 @@ pub struct RenderedLink { } impl Attributes { + crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { + self.other_attrs.lists(name) + } + /// Extracts the content from an attribute `#[doc(cfg(content))]`. crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> { use rustc_ast::NestedMetaItem::MetaItem; @@ -678,13 +961,10 @@ impl Attributes { } crate fn from_ast( - diagnostic: &::rustc_errors::Handler, attrs: &[ast::Attribute], additional_attrs: Option<(&[ast::Attribute], DefId)>, ) -> Attributes { let mut doc_strings: Vec = vec![]; - let mut sp = None; - let mut cfg = Cfg::True; let mut doc_line = 0; fn update_need_backline(doc_strings: &mut Vec, frag: &DocFragment) { @@ -728,21 +1008,11 @@ impl Attributes { doc_strings.push(frag); - if sp.is_none() { - sp = Some(attr.span); - } None } else { if attr.has_name(sym::doc) { if let Some(mi) = attr.meta() { - if let Some(cfg_mi) = Attributes::extract_cfg(&mi) { - // Extracted #[doc(cfg(...))] - match Cfg::parse(cfg_mi) { - Ok(new_cfg) => cfg &= new_cfg, - Err(e) => diagnostic.span_err(e.span, e.msg), - } - } else if let Some((filename, contents)) = Attributes::extract_include(&mi) - { + if let Some((filename, contents)) = Attributes::extract_include(&mi) { let line = doc_line; doc_line += contents.as_str().lines().count(); let frag = DocFragment { @@ -772,36 +1042,7 @@ impl Attributes { .filter_map(clean_attr) .collect(); - // treat #[target_feature(enable = "feat")] attributes as if they were - // #[doc(cfg(target_feature = "feat"))] attributes as well - for attr in attrs.lists(sym::target_feature) { - if attr.has_name(sym::enable) { - if let Some(feat) = attr.value_str() { - let meta = attr::mk_name_value_item_str( - Ident::with_dummy_span(sym::target_feature), - feat, - DUMMY_SP, - ); - if let Ok(feat_cfg) = Cfg::parse(&meta) { - cfg &= feat_cfg; - } - } - } - } - - let inner_docs = attrs - .iter() - .find(|a| a.doc_str().is_some()) - .map_or(true, |a| a.style == AttrStyle::Inner); - - Attributes { - doc_strings, - other_attrs, - cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }, - span: sp, - links: vec![], - inner_docs, - } + Attributes { doc_strings, other_attrs } } /// Finds the `doc` attribute as a NameValue and returns the corresponding @@ -843,73 +1084,7 @@ impl Attributes { if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) } } - /// Gets links as a vector - /// - /// Cache must be populated before call - crate fn links(&self, krate: CrateNum, cache: &Cache) -> Vec { - use crate::html::format::href; - use crate::html::render::CURRENT_DEPTH; - - self.links - .iter() - .filter_map(|ItemLink { link: s, link_text, did, fragment }| { - match *did { - Some(did) => { - if let Some((mut href, ..)) = href(did, cache) { - if let Some(ref fragment) = *fragment { - href.push('#'); - href.push_str(fragment); - } - Some(RenderedLink { - original_text: s.clone(), - new_text: link_text.clone(), - href, - }) - } else { - None - } - } - None => { - if let Some(ref fragment) = *fragment { - let url = match cache.extern_locations.get(&krate) { - Some(&(_, _, ExternalLocation::Local)) => { - let depth = CURRENT_DEPTH.with(|l| l.get()); - "../".repeat(depth) - } - Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(), - Some(&(_, _, ExternalLocation::Unknown)) | None => String::from( - // NOTE: intentionally doesn't pass crate name to avoid having - // different primitive links between crates - if UnstableFeatures::from_environment(None).is_nightly_build() { - "https://doc.rust-lang.org/nightly" - } else { - "https://doc.rust-lang.org" - }, - ), - }; - // This is a primitive so the url is done "by hand". - let tail = fragment.find('#').unwrap_or_else(|| fragment.len()); - Some(RenderedLink { - original_text: s.clone(), - new_text: link_text.clone(), - href: format!( - "{}{}std/primitive.{}.html{}", - url, - if !url.ends_with('/') { "/" } else { "" }, - &fragment[..tail], - &fragment[tail..] - ), - }) - } else { - panic!("This isn't a primitive?!"); - } - } - } - }) - .collect() - } - - crate fn get_doc_aliases(&self) -> FxHashSet { + crate fn get_doc_aliases(&self) -> Box<[String]> { let mut aliases = FxHashSet::default(); for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) { @@ -926,16 +1101,13 @@ impl Attributes { aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap()); } } - aliases + aliases.into_iter().collect::>().into() } } impl PartialEq for Attributes { fn eq(&self, rhs: &Self) -> bool { self.doc_strings == rhs.doc_strings - && self.cfg == rhs.cfg - && self.span == rhs.span - && self.links == rhs.links && self .other_attrs .iter() @@ -949,21 +1121,12 @@ impl Eq for Attributes {} impl Hash for Attributes { fn hash(&self, hasher: &mut H) { self.doc_strings.hash(hasher); - self.cfg.hash(hasher); - self.span.hash(hasher); - self.links.hash(hasher); for attr in &self.other_attrs { attr.id.hash(hasher); } } } -impl AttributesExt for Attributes { - fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { - self.other_attrs.lists(name) - } -} - #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum GenericBound { TraitBound(PolyTrait, hir::TraitBoundModifier), @@ -975,7 +1138,7 @@ impl GenericBound { let did = cx.tcx.require_lang_item(LangItem::Sized, None); 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, TypeKind::Trait); + inline::record_extern_fqn(cx, did, ItemType::Trait); GenericBound::TraitBound( PolyTrait { trait_: ResolvedPath { path, param_names: None, did, is_generic: false }, @@ -1126,7 +1289,6 @@ crate struct FnDecl { crate inputs: Arguments, crate output: FnRetTy, crate c_variadic: bool, - crate attrs: Attributes, } impl FnDecl { @@ -1314,62 +1476,6 @@ crate enum PrimitiveType { Never, } -#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] -crate enum TypeKind { - Enum, - Function, - Module, - Const, - Static, - Struct, - Union, - Trait, - Typedef, - Foreign, - Macro, - Attr, - Derive, - TraitAlias, - Primitive, -} - -impl From for TypeKind { - fn from(other: hir::def::DefKind) -> Self { - match other { - hir::def::DefKind::Enum => Self::Enum, - hir::def::DefKind::Fn => Self::Function, - hir::def::DefKind::Mod => Self::Module, - hir::def::DefKind::Const => Self::Const, - hir::def::DefKind::Static => Self::Static, - hir::def::DefKind::Struct => Self::Struct, - hir::def::DefKind::Union => Self::Union, - hir::def::DefKind::Trait => Self::Trait, - hir::def::DefKind::TyAlias => Self::Typedef, - hir::def::DefKind::TraitAlias => Self::TraitAlias, - hir::def::DefKind::Macro(_) => Self::Macro, - hir::def::DefKind::ForeignTy - | hir::def::DefKind::Variant - | hir::def::DefKind::AssocTy - | hir::def::DefKind::TyParam - | hir::def::DefKind::ConstParam - | hir::def::DefKind::Ctor(..) - | hir::def::DefKind::AssocFn - | hir::def::DefKind::AssocConst - | hir::def::DefKind::ExternCrate - | hir::def::DefKind::Use - | hir::def::DefKind::ForeignMod - | hir::def::DefKind::AnonConst - | hir::def::DefKind::OpaqueTy - | hir::def::DefKind::Field - | hir::def::DefKind::LifetimeParam - | hir::def::DefKind::GlobalAsm - | hir::def::DefKind::Impl - | hir::def::DefKind::Closure - | hir::def::DefKind::Generator => Self::Foreign, - } - } -} - crate trait GetDefId { /// Use this method to get the [`DefId`] of a [`clean`] AST node. /// This will return [`None`] when called on a primitive [`clean::Type`]. @@ -1615,18 +1721,18 @@ impl PrimitiveType { } } - crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<[DefId; 4]> { + crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec { Self::all_impls(tcx).get(self).expect("missing impl for primitive type") } - crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap> { - static CELL: OnceCell>> = OnceCell::new(); + crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap> { + static CELL: OnceCell>> = OnceCell::new(); CELL.get_or_init(move || { use self::PrimitiveType::*; let single = |a: Option| a.into_iter().collect(); - let both = |a: Option, b: Option| -> ArrayVec<_> { + let both = |a: Option, b: Option| -> ArrayVec<_, 4> { a.into_iter().chain(b).collect() }; @@ -1798,8 +1904,13 @@ impl From for PrimitiveType { #[derive(Copy, Clone, Debug)] crate enum Visibility { + /// `pub` Public, + /// Visibility inherited from parent. + /// + /// For example, this is the visibility of private items and of enum variants. Inherited, + /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)` Restricted(DefId), } @@ -1848,8 +1959,9 @@ crate enum Variant { Struct(VariantStruct), } -/// Small wrapper around `rustc_span::Span` that adds helper methods and enforces calling `source_callsite`. -#[derive(Clone, Debug)] +/// Small wrapper around [`rustc_span::Span]` that adds helper methods +/// and enforces calling [`rustc_span::Span::source_callsite()`]. +#[derive(Copy, Clone, Debug)] crate struct Span(rustc_span::Span); impl Span { @@ -1860,12 +1972,12 @@ impl Span { Self(sp.source_callsite()) } - crate fn dummy() -> Self { - Self(rustc_span::DUMMY_SP) + crate fn inner(&self) -> rustc_span::Span { + self.0 } - crate fn span(&self) -> rustc_span::Span { - self.0 + crate fn dummy() -> Self { + Self(rustc_span::DUMMY_SP) } crate fn is_dummy(&self) -> bool { @@ -1978,13 +2090,63 @@ crate struct Static { #[derive(Clone, PartialEq, Eq, Hash, Debug)] crate struct Constant { crate type_: Type, - crate expr: String, - crate value: Option, - crate is_literal: bool, + crate kind: ConstantKind, +} + +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +crate enum ConstantKind { + /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a + /// `BodyId`, we need to handle it on its own. + /// + /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified + /// by a DefId. So this field must be different from `Extern`. + TyConst { expr: String }, + /// A constant (expression) that's not an item or associated item. These are usually found + /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also + /// used to define explicit discriminant values for enum variants. + Anonymous { body: BodyId }, + /// A constant from a different crate. + Extern { def_id: DefId }, + /// `const FOO: u32 = ...;` + Local { def_id: DefId, body: BodyId }, +} + +impl Constant { + crate fn expr(&self, tcx: TyCtxt<'_>) -> String { + match self.kind { + ConstantKind::TyConst { ref expr } => expr.clone(), + ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), + ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { + print_const_expr(tcx, body) + } + } + } + + crate fn value(&self, tcx: TyCtxt<'_>) -> Option { + match self.kind { + ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None, + ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { + print_evaluated_const(tcx, def_id) + } + } + } + + crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool { + match self.kind { + ConstantKind::TyConst { .. } => false, + ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| { + is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id)) + }), + ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { + is_literal_expr(tcx, body.hir_id) + } + } + } } #[derive(Clone, Debug)] crate struct Impl { + crate span: Span, crate unsafety: hir::Unsafety, crate generics: Generics, crate provided_trait_methods: FxHashSet, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 8b5f5b66c4..b5953d2dc4 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -1,11 +1,11 @@ use crate::clean::auto_trait::AutoTraitFinder; use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::{ - inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, - ItemKind, Lifetime, MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, - TypeBinding, TypeKind, + inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, + MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, }; use crate::core::DocContext; +use crate::formats::item_type::ItemType; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -54,7 +54,11 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { _ => unreachable!(), } - let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); + let local_crate = LOCAL_CRATE.clean(cx); + let src = local_crate.src(cx.tcx); + let name = local_crate.name(cx.tcx); + let primitives = local_crate.primitives(cx.tcx); + let keywords = local_crate.keywords(cx.tcx); { let m = match *module.kind { ItemKind::ModuleItem(ref mut m) => m, @@ -76,7 +80,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { Crate { name, src, - module: Some(module), + module, externs, primitives, external_traits: cx.external_traits.clone(), @@ -97,7 +101,7 @@ fn external_generic_args( .iter() .filter_map(|kind| match kind.unpack() { GenericArgKind::Lifetime(lt) => match lt { - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_) }) => { + ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_), .. }) => { Some(GenericArg::Lifetime(Lifetime::elided())) } _ => lt.clean(cx).map(GenericArg::Lifetime), @@ -251,19 +255,9 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { debug!("trying to get a name from pattern: {:?}", p); Symbol::intern(&match p.kind { - PatKind::Wild => return kw::Underscore, + 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::Struct(ref name, ref fields, etc) => format!( - "{} {{ {}{} }}", - qpath_to_string(name), - fields - .iter() - .map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat))) - .collect::>() - .join(", "), - if etc { ", .." } else { "" } - ), PatKind::Or(ref pats) => pats .iter() .map(|p| name_from_pat(&**p).to_string()) @@ -296,12 +290,12 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { match n.val { - ty::ConstKind::Unevaluated(def, _, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => { let mut s = if let Some(def) = def.as_local() { let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did); print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id)) } else { - inline::print_inlined_const(cx, def.did) + inline::print_inlined_const(cx.tcx, def.did) }; if let Some(promoted) = promoted { s.push_str(&format!("::{:?}", promoted)) @@ -324,15 +318,15 @@ crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { } } -crate fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option { - cx.tcx.const_eval_poly(def_id).ok().and_then(|val| { - let ty = cx.tcx.type_of(def_id); +crate fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + tcx.const_eval_poly(def_id).ok().and_then(|val| { + let ty = tcx.type_of(def_id); match (val, ty.kind()) { (_, &ty::Ref(..)) => None, (ConstValue::Scalar(_), &ty::Adt(_, _)) => None, (ConstValue::Scalar(_), _) => { - let const_ = ty::Const::from_value(cx.tcx, val, ty); - Some(print_const_with_custom_print_scalar(cx, const_)) + let const_ = ty::Const::from_value(tcx, val, ty); + Some(print_const_with_custom_print_scalar(tcx, const_)) } _ => None, } @@ -349,7 +343,7 @@ fn format_integer_with_underscore_sep(num: &str) -> String { .collect() } -fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const<'tcx>) -> String { +fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tcx>) -> String { // Use a slightly different format for integer types which always shows the actual value. // For all other types, fallback to the original `pretty_print_const`. match (ct.val, ct.ty.kind()) { @@ -357,8 +351,8 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str()) } (ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => { - let ty = cx.tcx.lift(ct.ty).unwrap(); - let size = cx.tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; + let ty = tcx.lift(ct.ty).unwrap(); + let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; let data = int.assert_bits(size); let sign_extended_data = size.sign_extend(data) as i128; @@ -372,8 +366,8 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const } } -crate fn is_literal_expr(cx: &DocContext<'_>, hir_id: hir::HirId) -> bool { - if let hir::Node::Expr(expr) = cx.tcx.hir().get(hir_id) { +crate fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { + if let hir::Node::Expr(expr) = tcx.hir().get(hir_id) { if let hir::ExprKind::Lit(_) = &expr.kind { return true; } @@ -411,7 +405,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty return Generic(kw::SelfUpper); } Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => { - return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache)))); + return Generic(Symbol::intern(&path.whole_name())); } Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true, _ => false, @@ -441,29 +435,29 @@ crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { debug!("register_res({:?})", res); let (did, kind) = match res { - Res::Def(DefKind::Fn, i) => (i, TypeKind::Function), - Res::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef), - Res::Def(DefKind::Enum, i) => (i, TypeKind::Enum), - Res::Def(DefKind::Trait, i) => (i, TypeKind::Trait), + Res::Def(DefKind::Fn, i) => (i, ItemType::Function), + Res::Def(DefKind::TyAlias, i) => (i, ItemType::Typedef), + Res::Def(DefKind::Enum, i) => (i, ItemType::Enum), + Res::Def(DefKind::Trait, i) => (i, ItemType::Trait), Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => { - (cx.tcx.parent(i).unwrap(), TypeKind::Trait) + (cx.tcx.parent(i).unwrap(), ItemType::Trait) } - Res::Def(DefKind::Struct, i) => (i, TypeKind::Struct), - Res::Def(DefKind::Union, i) => (i, TypeKind::Union), - Res::Def(DefKind::Mod, i) => (i, TypeKind::Module), - Res::Def(DefKind::ForeignTy, i) => (i, TypeKind::Foreign), - Res::Def(DefKind::Const, i) => (i, TypeKind::Const), - Res::Def(DefKind::Static, i) => (i, TypeKind::Static), + Res::Def(DefKind::Struct, i) => (i, ItemType::Struct), + Res::Def(DefKind::Union, i) => (i, ItemType::Union), + Res::Def(DefKind::Mod, i) => (i, ItemType::Module), + Res::Def(DefKind::ForeignTy, i) => (i, ItemType::ForeignType), + Res::Def(DefKind::Const, i) => (i, ItemType::Constant), + Res::Def(DefKind::Static, i) => (i, ItemType::Static), Res::Def(DefKind::Variant, i) => { - (cx.tcx.parent(i).expect("cannot get parent def id"), TypeKind::Enum) + (cx.tcx.parent(i).expect("cannot get parent def id"), ItemType::Enum) } Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind { - MacroKind::Bang => (i, TypeKind::Macro), - MacroKind::Attr => (i, TypeKind::Attr), - MacroKind::Derive => (i, TypeKind::Derive), + MacroKind::Bang => (i, ItemType::Macro), + MacroKind::Attr => (i, ItemType::ProcAttribute), + MacroKind::Derive => (i, ItemType::ProcDerive), }, - Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias), - Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait), + Res::Def(DefKind::TraitAlias, i) => (i, ItemType::TraitAlias), + Res::SelfTy(Some(def_id), _) => (def_id, ItemType::Trait), Res::SelfTy(_, Some((impl_def_id, _))) => return impl_def_id, _ => return res.def_id(), }; @@ -471,7 +465,7 @@ crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { return did; } inline::record_extern_fqn(cx, did, kind); - if let TypeKind::Trait = kind { + if let ItemType::Trait = kind { inline::record_extern_trait(cx, did); } did diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index ecb6378f31..8f10ab2d3a 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -3,6 +3,7 @@ use std::convert::TryFrom; use std::ffi::OsStr; use std::fmt; use std::path::PathBuf; +use std::str::FromStr; use rustc_data_structures::fx::FxHashMap; use rustc_session::config::{self, parse_crate_types_from_list, parse_externs, CrateType}; @@ -96,8 +97,7 @@ crate struct Options { crate maybe_sysroot: Option, /// Lint information passed over the command-line. crate lint_opts: Vec<(String, Level)>, - /// Whether to ask rustc to describe the lints it knows. Practically speaking, this will not be - /// used, since we abort if we have no input file, but it's included for completeness. + /// Whether to ask rustc to describe the lints it knows. crate describe_lints: bool, /// What level to cap lints at. crate lint_cap: Option, @@ -153,6 +153,8 @@ crate struct Options { /// If this option is set to `true`, rustdoc will only run checks and not generate /// documentation. crate run_check: bool, + /// Whether doctests should emit unused externs + crate json_unused_externs: bool, } impl fmt::Debug for Options { @@ -266,6 +268,34 @@ crate struct RenderOptions { /// If `true`, generate a JSON file in the crate folder instead of HTML redirection files. crate generate_redirect_map: bool, crate unstable_features: rustc_feature::UnstableFeatures, + crate emit: Vec, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +crate enum EmitType { + Unversioned, + Toolchain, + InvocationSpecific, +} + +impl FromStr for EmitType { + type Err = (); + + fn from_str(s: &str) -> Result { + use EmitType::*; + match s { + "unversioned-shared-resources" => Ok(Unversioned), + "toolchain-shared-resources" => Ok(Toolchain), + "invocation-specific" => Ok(InvocationSpecific), + _ => Err(()), + } + } +} + +impl RenderOptions { + crate fn should_emit_crate(&self) -> bool { + self.emit.is_empty() || self.emit.contains(&EmitType::InvocationSpecific) + } } impl Options { @@ -323,7 +353,8 @@ impl Options { } let color = config::parse_color(&matches); - let (json_rendered, _artifacts) = config::parse_json(&matches); + let config::JsonConfig { json_rendered, json_unused_externs, .. } = + config::parse_json(&matches); let error_format = config::parse_error_format(&matches, color, json_rendered); let codegen_options = build_codegen_options(matches, error_format); @@ -334,6 +365,30 @@ impl Options { // check for deprecated options check_deprecated_options(&matches, &diag); + let mut emit = Vec::new(); + for list in matches.opt_strs("emit") { + for kind in list.split(',') { + match kind.parse() { + Ok(kind) => emit.push(kind), + Err(()) => { + diag.err(&format!("unrecognized emission type: {}", kind)); + return Err(1); + } + } + } + } + + // check for `--output-format=json` + if !matches!(matches.opt_str("output-format").as_deref(), None | Some("html")) + && !matches.opt_present("show-coverage") + && !nightly_options::is_unstable_enabled(matches) + { + rustc_session::early_error( + error_format, + "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)", + ); + } + let to_check = matches.opt_strs("check-theme"); if !to_check.is_empty() { let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes()); @@ -439,7 +494,9 @@ impl Options { return Err(1); } if theme_file.extension() != Some(OsStr::new("css")) { - diag.struct_err(&format!("invalid argument: \"{}\"", theme_s)).emit(); + diag.struct_err(&format!("invalid argument: \"{}\"", theme_s)) + .help("arguments to --theme must have a .css extension") + .emit(); return Err(1); } let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag); @@ -465,7 +522,6 @@ impl Options { let edition = config::parse_crate_edition(&matches); let mut id_map = html::markdown::IdMap::new(); - id_map.populate(&html::render::INITIAL_IDS); let external_html = match ExternalHtml::load( &matches.opt_strs("html-in-header"), &matches.opt_strs("html-before-content"), @@ -529,13 +585,7 @@ impl Options { let output_format = match matches.opt_str("output-format") { Some(s) => match OutputFormat::try_from(s.as_str()) { Ok(out_fmt) => { - if out_fmt.is_json() - && !(show_coverage || nightly_options::match_is_nightly_build(matches)) - { - diag.struct_err("json output format isn't supported for doc generation") - .emit(); - return Err(1); - } else if !out_fmt.is_json() && show_coverage { + if !out_fmt.is_json() && show_coverage { diag.struct_err( "html output format isn't supported for the --show-coverage option", ) @@ -641,9 +691,11 @@ impl Options { unstable_features: rustc_feature::UnstableFeatures::from_environment( crate_name.as_deref(), ), + emit, }, crate_name, output_format, + json_unused_externs, }) } @@ -655,16 +707,10 @@ impl Options { /// Prints deprecation warnings for deprecated options fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Handler) { - let deprecated_flags = ["input-format", "output-format", "no-defaults", "passes"]; + let deprecated_flags = ["input-format", "no-defaults", "passes"]; for flag in deprecated_flags.iter() { if matches.opt_present(flag) { - if *flag == "output-format" - && (matches.opt_present("show-coverage") - || nightly_options::match_is_nightly_build(matches)) - { - continue; - } let mut err = diag.struct_warn(&format!("the `{}` flag is deprecated", flag)); err.note( "see issue #44136 \ diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c5b5ab0f3d..1ec4757a91 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,11 +1,12 @@ +use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; use rustc_driver::abort_on_err; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::json::JsonEmitter; use rustc_feature::UnstableFeatures; -use rustc_hir::def::{Namespace::TypeNS, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def::Res; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; use rustc_hir::HirId; use rustc_hir::{ intravisit::{self, NestedVisitorMap, Visitor}, @@ -22,7 +23,7 @@ use rustc_session::DiagnosticOutput; use rustc_session::Session; use rustc_span::source_map; use rustc_span::symbol::sym; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use std::cell::RefCell; use std::collections::hash_map::Entry; @@ -31,7 +32,7 @@ use std::rc::Rc; use crate::clean; use crate::clean::inline::build_external_trait; -use crate::clean::{AttributesExt, TraitWithExtraInfo, MAX_DEF_IDX}; +use crate::clean::{TraitWithExtraInfo, MAX_DEF_IDX}; use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions}; use crate::formats::cache::Cache; use crate::passes::{self, Condition::*, ConditionalPass}; @@ -348,42 +349,17 @@ crate fn create_config( } crate fn create_resolver<'a>( - externs: config::Externs, queries: &Queries<'a>, sess: &Session, ) -> Rc> { - let extern_names: Vec = externs - .iter() - .filter(|(_, entry)| entry.add_prelude) - .map(|(name, _)| name) - .cloned() - .collect(); - let parts = abort_on_err(queries.expansion(), sess).peek(); - let resolver = parts.1.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 - // intra-doc links - resolver.borrow_mut().access(|resolver| { - sess.time("load_extern_crates", || { - for extern_name in &extern_names { - debug!("loading extern crate {}", extern_name); - if let Err(()) = resolver - .resolve_str_path_error( - DUMMY_SP, - extern_name, - TypeNS, - LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(), - ) { - warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name) - } - } - }); - }); + let (krate, resolver, _) = &*parts; + let resolver = resolver.borrow().clone(); + + let mut loader = crate::passes::collect_intra_doc_links::IntraLinkCrateLoader::new(resolver); + ast::visit::walk_crate(&mut loader, krate); - // Now we're good to clone the resolver because everything should be loaded - resolver.clone() + loader.resolver } crate fn run_global_ctxt( @@ -464,31 +440,28 @@ crate fn run_global_ctxt( if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() { let mut sized_trait = build_external_trait(&mut ctxt, sized_trait_did); sized_trait.is_auto = true; - ctxt.external_traits.borrow_mut().insert( - sized_trait_did, - TraitWithExtraInfo { trait_: sized_trait, is_spotlight: false }, - ); + ctxt.external_traits + .borrow_mut() + .insert(sized_trait_did, TraitWithExtraInfo { trait_: sized_trait, is_notable: false }); } debug!("crate: {:?}", tcx.hir().krate()); let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt)); - if let Some(ref m) = krate.module { - if m.doc_value().map(|d| d.is_empty()).unwrap_or(true) { - let help = "The following guide may be of use:\n\ + if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) { + let help = "The following guide may be of use:\n\ https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html"; - tcx.struct_lint_node( - crate::lint::MISSING_CRATE_LEVEL_DOCS, - DocContext::as_local_hir_id(tcx, m.def_id).unwrap(), - |lint| { - let mut diag = - lint.build("no documentation found for this crate's top-level module"); - diag.help(help); - diag.emit(); - }, - ); - } + tcx.struct_lint_node( + crate::lint::MISSING_CRATE_LEVEL_DOCS, + DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(), + |lint| { + let mut diag = + lint.build("no documentation found for this crate's top-level module"); + diag.help(help); + diag.emit(); + }, + ); } fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) { @@ -531,7 +504,7 @@ crate fn run_global_ctxt( // Process all of the crate attributes, extracting plugin metadata along // with the passes which we are supposed to run. - for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { + for attr in krate.module.attrs.lists(sym::doc) { let diag = ctxt.sess().diagnostic(); let name = attr.name_or_empty(); diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index d9e97e02a1..466d1b6540 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1,5 +1,5 @@ use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_errors::{ColorConfig, ErrorReported}; use rustc_hir as hir; @@ -23,8 +23,10 @@ use std::panic; use std::path::PathBuf; use std::process::{self, Command, Stdio}; use std::str; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{Arc, Mutex}; -use crate::clean::Attributes; +use crate::clean::{types::AttributesExt, Attributes}; use crate::config::Options; use crate::html::markdown::{self, ErrorCodes, Ignore, LangString}; use crate::lint::init_lints; @@ -104,8 +106,10 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { let mut test_args = options.test_args.clone(); let display_warnings = options.display_warnings; + let externs = options.externs.clone(); + let json_unused_externs = options.json_unused_externs; - let tests = interface::run_compiler(config, |compiler| { + let res = interface::run_compiler(config, |compiler| { compiler.enter(|queries| { let _lower_to_hir = queries.lower_to_hir()?; @@ -141,7 +145,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { hir_collector.visit_testable( "".to_string(), CRATE_HIR_ID, - krate.item.span, + krate.item.inner, |this| { intravisit::walk_crate(this, krate); }, @@ -151,12 +155,15 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { }); compiler.session().abort_if_errors(); - let ret: Result<_, ErrorReported> = Ok(collector.tests); + let unused_extern_reports = collector.unused_extern_reports.clone(); + let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst); + let ret: Result<_, ErrorReported> = + Ok((collector.tests, unused_extern_reports, compiling_test_count)); ret }) }); - let tests = match tests { - Ok(tests) => tests, + let (tests, unused_extern_reports, compiling_test_count) = match res { + Ok(res) => res, Err(ErrorReported) => return Err(ErrorReported), }; @@ -168,6 +175,44 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { Some(testing::Options::new().display_output(display_warnings)), ); + // Collect and warn about unused externs, but only if we've gotten + // reports for each doctest + if json_unused_externs { + let unused_extern_reports: Vec<_> = + std::mem::take(&mut unused_extern_reports.lock().unwrap()); + if unused_extern_reports.len() == compiling_test_count { + let extern_names = externs.iter().map(|(name, _)| name).collect::>(); + let mut unused_extern_names = unused_extern_reports + .iter() + .map(|uexts| uexts.unused_extern_names.iter().collect::>()) + .fold(extern_names, |uextsa, uextsb| { + uextsa.intersection(&uextsb).map(|v| *v).collect::>() + }) + .iter() + .map(|v| (*v).clone()) + .collect::>(); + unused_extern_names.sort(); + // Take the most severe lint level + let lint_level = unused_extern_reports + .iter() + .map(|uexts| uexts.lint_level.as_str()) + .max_by_key(|v| match *v { + "warn" => 1, + "deny" => 2, + "forbid" => 3, + // The allow lint level is not expected, + // as if allow is specified, no message + // is to be emitted. + v => unreachable!("Invalid lint level '{}'", v), + }) + .unwrap_or("warn") + .to_string(); + let uext = UnusedExterns { lint_level, unused_extern_names }; + let unused_extern_json = serde_json::to_string(&uext).unwrap(); + eprintln!("{}", unused_extern_json); + } + } + Ok(()) } @@ -235,6 +280,18 @@ impl DirState { } } +// NOTE: Keep this in sync with the equivalent structs in rustc +// and cargo. +// We could unify this struct the one in rustc but they have different +// ownership semantics, so doing so would create wasteful allocations. +#[derive(serde::Serialize, serde::Deserialize)] +struct UnusedExterns { + /// Lint level of the unused_crate_dependencies lint + lint_level: String, + /// List of unused externs by their names. + unused_extern_names: Vec, +} + fn run_test( test: &str, cratename: &str, @@ -253,6 +310,7 @@ fn run_test( outdir: DirState, path: PathBuf, test_id: &str, + 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)); @@ -278,6 +336,12 @@ fn run_test( if as_test_harness { compiler.arg("--test"); } + if options.json_unused_externs && !compile_fail { + compiler.arg("--error-format=json"); + compiler.arg("--json").arg("unused-externs"); + compiler.arg("-Z").arg("unstable-options"); + compiler.arg("-W").arg("unused_crate_dependencies"); + } for lib_str in &options.lib_strs { compiler.arg("-L").arg(&lib_str); } @@ -337,7 +401,26 @@ fn run_test( eprint!("{}", self.0); } } - let out = str::from_utf8(&output.stderr).unwrap(); + let mut out_lines = str::from_utf8(&output.stderr) + .unwrap() + .lines() + .filter(|l| { + if let Ok(uext) = serde_json::from_str::(l) { + report_unused_externs(uext); + false + } else { + true + } + }) + .collect::>(); + + // Add a \n to the end to properly terminate the last line, + // but only if there was output to be printed + if out_lines.len() > 0 { + out_lines.push(""); + } + + let out = out_lines.join("\n"); let _bomb = Bomb(&out); match (output.status.success(), compile_fail) { (true, true) => { @@ -721,6 +804,8 @@ crate struct Collector { source_map: Option>, filename: Option, visited_tests: FxHashMap<(String, usize), usize>, + unused_extern_reports: Arc>>, + compiling_test_count: AtomicUsize, } impl Collector { @@ -745,6 +830,8 @@ impl Collector { source_map, filename, visited_tests: FxHashMap::default(), + unused_extern_reports: Default::default(), + compiling_test_count: AtomicUsize::new(0), } } @@ -791,6 +878,10 @@ impl Tester for Collector { let runtool_args = self.options.runtool_args.clone(); let target = self.options.target.clone(); let target_str = target.to_string(); + let unused_externs = self.unused_extern_reports.clone(); + if !config.compile_fail { + self.compiling_test_count.fetch_add(1, Ordering::SeqCst); + } // FIXME(#44940): if doctests ever support path remapping, then this filename // needs to be the result of `SourceMap::span_to_unmapped_path`. @@ -846,6 +937,9 @@ impl Tester for Collector { test_type: testing::TestType::DocTest, }, testfn: testing::DynTestFn(box move || { + let report_unused_externs = |uext| { + unused_externs.lock().unwrap().push(uext); + }; let res = run_test( &test, &cratename, @@ -864,6 +958,7 @@ impl Tester for Collector { outdir, path, &test_id, + report_unused_externs, ); if let Err(err) = res { @@ -997,9 +1092,10 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { sp: Span, nested: F, ) { - let attrs = self.tcx.hir().attrs(hir_id); - let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None); - if let Some(ref cfg) = attrs.cfg { + let ast_attrs = self.tcx.hir().attrs(hir_id); + let mut attrs = Attributes::from_ast(ast_attrs, None); + + if let Some(ref cfg) = ast_attrs.cfg(self.sess.diagnostic()) { if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) { return; } @@ -1015,8 +1111,8 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { // anything else, this will combine them for us. if let Some(doc) = attrs.collapsed_doc_value() { // Use the outermost invocation, so that doctest names come from where the docs were written. - let span = attrs - .span + let span = ast_attrs + .span() .map(|span| span.ctxt().outer_expn().expansion_cause().unwrap_or(span)) .unwrap_or(DUMMY_SP); self.collector.set_position(span); diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 645b2bb193..d3f4353a58 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -5,7 +5,7 @@ use rustc_span::{self, Span, Symbol}; use rustc_hir as hir; crate struct Module<'hir> { - crate name: Option, + crate name: Symbol, crate where_outer: Span, crate where_inner: Span, crate mods: Vec>, @@ -14,11 +14,10 @@ crate struct Module<'hir> { crate items: Vec<(&'hir hir::Item<'hir>, Option)>, crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option)>, - crate is_crate: bool, } impl Module<'hir> { - crate fn new(name: Option) -> Module<'hir> { + crate fn new(name: Symbol) -> Module<'hir> { Module { name, id: hir::CRATE_HIR_ID, @@ -28,7 +27,6 @@ impl Module<'hir> { items: Vec::new(), foreigns: Vec::new(), macros: Vec::new(), - is_crate: false, } } } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 2b980ebe59..37d11d4ed4 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -81,13 +81,13 @@ crate trait DocFolder: Sized { fn fold_mod(&mut self, m: Module) -> Module { Module { - is_crate: m.is_crate, + span: m.span, items: m.items.into_iter().filter_map(|i| self.fold_item(i)).collect(), } } fn fold_crate(&mut self, mut c: Crate) -> Crate { - c.module = c.module.take().and_then(|module| self.fold_item(module)); + c.module = self.fold_item(c.module).unwrap(); { let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) }; diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 9415caf8b6..8f8bca64e1 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -116,14 +116,15 @@ crate struct Cache { // even though the trait itself is not exported. This can happen if a trait // was defined in function/expression scope, since the impl will be picked // up by `collect-trait-impls` but the trait won't be scraped out in the HIR - // crawl. In order to prevent crashes when looking for spotlight traits or + // crawl. In order to prevent crashes when looking for notable traits or // when gathering trait documentation on a type, hold impls here while // folding and add them to the cache later on if we find the trait. orphan_trait_impls: Vec<(DefId, FxHashSet, Impl)>, - /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, - /// we need the alias element to have an array of items. - crate aliases: BTreeMap>, + /// All intra-doc links resolved so far. + /// + /// Links are indexed by the DefId of the item they document. + crate intra_doc_links: BTreeMap>, } /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`. @@ -154,19 +155,22 @@ 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 { - let src_root = match e.src { + let src_root = match e.src(tcx) { FileName::Real(ref p) => match p.local_path().parent() { Some(p) => p.to_path_buf(), None => PathBuf::new(), }, _ => PathBuf::new(), }; - let extern_url = extern_html_root_urls.get(&*e.name.as_str()).map(|u| &**u); - self.extern_locations - .insert(n, (e.name, src_root, extern_location(e, extern_url, &dst))); - + 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.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module)); + self.extern_locations.insert( + n, + (name, src_root, extern_location(e, extern_url, tcx.get_attrs(did), &dst, tcx)), + ); + + self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module)); } // Cache where all known primitives have their documentation located. @@ -174,7 +178,7 @@ impl Cache { // 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 &(def_id, prim) in &e.primitives { + for &(def_id, prim) in &e.primitives(tcx) { self.primitive_locations.insert(prim, def_id); } } @@ -182,8 +186,6 @@ impl Cache { self.primitive_locations.insert(prim, def_id); } - self.stack.push(krate.name.to_string()); - krate = CacheBuilder { tcx, cache: self, empty_cache: Cache::default() }.fold_crate(krate); for (trait_did, dids, impl_) in self.orphan_trait_impls.drain(..) { @@ -229,7 +231,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { if let clean::TraitItem(ref t) = *item.kind { self.cache.traits.entry(item.def_id).or_insert_with(|| clean::TraitWithExtraInfo { trait_: t.clone(), - is_spotlight: item.attrs.has_doc_flag(sym::spotlight), + is_notable: item.attrs.has_doc_flag(sym::notable_trait), }); } @@ -311,15 +313,8 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { parent, parent_idx: None, search_type: get_index_search_type(&item, &self.empty_cache, self.tcx), + aliases: item.attrs.get_doc_aliases(), }); - - for alias in item.attrs.get_doc_aliases() { - self.cache - .aliases - .entry(alias.to_lowercase()) - .or_insert(Vec::new()) - .push(self.cache.search_index.len() - 1); - } } } (Some(parent), None) if is_inherent_impl_item => { diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 460d4b907c..955de57dc0 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -4,6 +4,7 @@ use std::fmt; use serde::{Serialize, Serializer}; +use rustc_hir::def::DefKind; use rustc_span::hygiene::MacroKind; use crate::clean; @@ -19,7 +20,7 @@ use crate::clean; /// module headings. If you are adding to this enum and want to ensure that the sidebar also prints /// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an /// ordering based on a helper function inside `item_module`, in the same file. -#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord)] +#[derive(Copy, PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)] crate enum ItemType { Module = 0, ExternCrate = 1, @@ -102,24 +103,43 @@ impl<'a> From<&'a clean::Item> for ItemType { } } -impl From for ItemType { - fn from(kind: clean::TypeKind) -> ItemType { - match kind { - clean::TypeKind::Struct => ItemType::Struct, - clean::TypeKind::Union => ItemType::Union, - clean::TypeKind::Enum => ItemType::Enum, - clean::TypeKind::Function => ItemType::Function, - clean::TypeKind::Trait => ItemType::Trait, - clean::TypeKind::Module => ItemType::Module, - clean::TypeKind::Static => ItemType::Static, - clean::TypeKind::Const => ItemType::Constant, - clean::TypeKind::Typedef => ItemType::Typedef, - clean::TypeKind::Foreign => ItemType::ForeignType, - clean::TypeKind::Macro => ItemType::Macro, - clean::TypeKind::Attr => ItemType::ProcAttribute, - clean::TypeKind::Derive => ItemType::ProcDerive, - clean::TypeKind::TraitAlias => ItemType::TraitAlias, - clean::TypeKind::Primitive => ItemType::Primitive, +impl From for ItemType { + fn from(other: DefKind) -> Self { + match other { + DefKind::Enum => Self::Enum, + DefKind::Fn => Self::Function, + DefKind::Mod => Self::Module, + DefKind::Const => Self::Constant, + DefKind::Static => Self::Static, + DefKind::Struct => Self::Struct, + DefKind::Union => Self::Union, + DefKind::Trait => Self::Trait, + DefKind::TyAlias => Self::Typedef, + DefKind::TraitAlias => Self::TraitAlias, + DefKind::Macro(kind) => match kind { + MacroKind::Bang => ItemType::Macro, + MacroKind::Attr => ItemType::ProcAttribute, + MacroKind::Derive => ItemType::ProcDerive, + }, + DefKind::ForeignTy + | DefKind::Variant + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::ConstParam + | DefKind::Ctor(..) + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::OpaqueTy + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Impl + | DefKind::Closure + | DefKind::Generator => Self::ForeignType, } } } diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 9095faf676..b8ef3384c5 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,5 +1,5 @@ use rustc_middle::ty::TyCtxt; -use rustc_span::edition::Edition; +use rustc_span::Symbol; use crate::clean; use crate::config::RenderOptions; @@ -13,12 +13,16 @@ crate trait FormatRenderer<'tcx>: Sized { /// Gives a description of the renderer. Used for performance profiling. fn descr() -> &'static str; + /// Whether to call `item` recursivly for modules + /// + /// This is true for html, and false for json. See #80664 + const RUN_ON_MODULE: bool; + /// Sets up any state required for the renderer. When this is called the cache has already been /// populated. fn init( krate: clean::Crate, options: RenderOptions, - edition: Edition, cache: Cache, tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error>; @@ -30,19 +34,15 @@ crate trait FormatRenderer<'tcx>: Sized { fn item(&mut self, item: clean::Item) -> Result<(), Error>; /// Renders a module (should not handle recursing into children). - fn mod_item_in(&mut self, item: &clean::Item, item_name: &str) -> Result<(), Error>; + fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error>; /// Runs after recursively rendering all sub-items of a module. - fn mod_item_out(&mut self, item_name: &str) -> Result<(), Error>; + fn mod_item_out(&mut self) -> Result<(), Error> { + Ok(()) + } /// Post processing hook for cleanup and dumping output to files. - /// - /// A handler is available if the renderer wants to report errors. - fn after_krate( - &mut self, - krate: &clean::Crate, - diag: &rustc_errors::Handler, - ) -> Result<(), Error>; + fn after_krate(&mut self) -> Result<(), Error>; fn cache(&self) -> &Cache; } @@ -52,38 +52,31 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( krate: clean::Crate, options: RenderOptions, cache: Cache, - diag: &rustc_errors::Handler, - edition: Edition, tcx: TyCtxt<'tcx>, ) -> Result<(), Error> { let prof = &tcx.sess.prof; - let (mut format_renderer, mut krate) = prof + let emit_crate = options.should_emit_crate(); + let (mut format_renderer, krate) = prof .extra_verbose_generic_activity("create_renderer", T::descr()) - .run(|| T::init(krate, options, edition, cache, tcx))?; + .run(|| T::init(krate, options, cache, tcx))?; - let mut item = match krate.module.take() { - Some(i) => i, - None => return Ok(()), - }; - - item.name = Some(krate.name); + if !emit_crate { + return Ok(()); + } // Render the crate documentation - let mut work = vec![(format_renderer.make_child_renderer(), item)]; + let mut work = vec![(format_renderer.make_child_renderer(), krate.module)]; - let unknown = rustc_span::Symbol::intern(""); + let unknown = Symbol::intern(""); while let Some((mut cx, item)) = work.pop() { - if item.is_mod() { + if item.is_mod() && T::RUN_ON_MODULE { // modules are special because they add a namespace. We also need to // recurse into the items of the module as well. - let name = item.name.as_ref().unwrap().to_string(); - if name.is_empty() { - panic!("Unexpected module with empty name"); - } - let _timer = prof.generic_activity_with_arg("render_mod_item", name.as_str()); + let _timer = + prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string()); - cx.mod_item_in(&item, &name)?; + cx.mod_item_in(&item)?; let module = match *item.kind { clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m, _ => unreachable!(), @@ -93,7 +86,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( work.push((cx.make_child_renderer(), it)); } - cx.mod_item_out(&name)?; + cx.mod_item_out()?; // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special // cases. Use an explicit match instead. } else if item.name.is_some() && !item.is_extern_crate() { @@ -102,5 +95,5 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( } } prof.extra_verbose_generic_activity("renderer_after_krate", T::descr()) - .run(|| format_renderer.after_krate(&krate, diag)) + .run(|| format_renderer.after_krate()) } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bea0e75832..45412f55c1 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -5,10 +5,11 @@ //! assume that HTML output is desired, although it may be possible to redesign //! them in the future to instead emit any format desired. -use std::borrow::Cow; use std::cell::Cell; use std::fmt; +use std::iter; +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_middle::ty::TyCtxt; @@ -16,11 +17,10 @@ use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_target::spec::abi::Abi; use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType}; -use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::render::cache::ExternalLocation; -use crate::html::render::CURRENT_DEPTH; +use crate::html::render::Context; crate trait Print { fn print(self, buffer: &mut Buffer); @@ -82,6 +82,10 @@ impl Buffer { self.buffer.push_str(s); } + crate fn push_buffer(&mut self, other: Buffer) { + self.buffer.push_str(&other.buffer); + } + // Intended for consumption by write! and writeln! (std::fmt) but without // the fmt::Result return type imposed by fmt::Write (and avoiding the trait // import). @@ -105,31 +109,10 @@ impl Buffer { crate fn is_for_html(&self) -> bool { self.for_html } -} -/// Wrapper struct for properly emitting a function or method declaration. -crate struct Function<'a> { - /// The declaration to emit. - crate decl: &'a clean::FnDecl, - /// The length of the function header and name. In other words, the number of characters in the - /// function declaration up to but not including the parentheses. - /// - /// Used to determine line-wrapping. - crate header_len: usize, - /// The number of spaces to indent each successive line with, if line-wrapping is necessary. - crate indent: usize, - /// Whether the function is async or not. - crate asyncness: hir::IsAsync, -} - -/// Wrapper struct for emitting a where-clause from Generics. -crate struct WhereClause<'a> { - /// The Generics from which to emit a where-clause. - crate gens: &'a clean::Generics, - /// The number of spaces to indent each line with. - crate indent: usize, - /// Whether the where-clause needs to add a comma and newline after the last bound. - crate end_newline: bool, + crate fn reserve(&mut self, additional: usize) { + self.buffer.reserve(additional) + } } fn comma_sep(items: impl Iterator) -> impl fmt::Display { @@ -144,27 +127,30 @@ fn comma_sep(items: impl Iterator) -> impl fmt::Displ }) } -crate fn print_generic_bounds<'a>( +crate fn print_generic_bounds<'a, 'tcx: 'a>( bounds: &'a [clean::GenericBound], - cache: &'a Cache, -) -> impl fmt::Display + 'a { + cx: &'a Context<'tcx>, +) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { let mut bounds_dup = FxHashSet::default(); for (i, bound) in - bounds.iter().filter(|b| bounds_dup.insert(b.print(cache).to_string())).enumerate() + bounds.iter().filter(|b| bounds_dup.insert(b.print(cx).to_string())).enumerate() { if i > 0 { f.write_str(" + ")?; } - fmt::Display::fmt(&bound.print(cache), f)?; + fmt::Display::fmt(&bound.print(cx), f)?; } Ok(()) }) } impl clean::GenericParamDef { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match self.kind { clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name), clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => { @@ -172,17 +158,17 @@ impl clean::GenericParamDef { if !bounds.is_empty() { if f.alternate() { - write!(f, ": {:#}", print_generic_bounds(bounds, cache))?; + write!(f, ": {:#}", print_generic_bounds(bounds, cx))?; } else { - write!(f, ": {}", print_generic_bounds(bounds, cache))?; + write!(f, ": {}", print_generic_bounds(bounds, cx))?; } } if let Some(ref ty) = default { if f.alternate() { - write!(f, " = {:#}", ty.print(cache))?; + write!(f, " = {:#}", ty.print(cx))?; } else { - write!(f, " = {}", ty.print(cache))?; + write!(f, " = {}", ty.print(cx))?; } } @@ -190,9 +176,9 @@ impl clean::GenericParamDef { } clean::GenericParamDefKind::Const { ref ty, .. } => { if f.alternate() { - write!(f, "const {}: {:#}", self.name, ty.print(cache)) + write!(f, "const {}: {:#}", self.name, ty.print(cx)) } else { - write!(f, "const {}: {}", self.name, ty.print(cache)) + write!(f, "const {}: {}", self.name, ty.print(cx)) } } }) @@ -200,7 +186,10 @@ impl clean::GenericParamDef { } impl clean::Generics { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { let real_params = self.params.iter().filter(|p| !p.is_synthetic_type_param()).collect::>(); @@ -208,109 +197,106 @@ impl clean::Generics { return Ok(()); } if f.alternate() { - write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache)))) + write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cx)))) } else { - write!(f, "<{}>", comma_sep(real_params.iter().map(|g| g.print(cache)))) + write!(f, "<{}>", comma_sep(real_params.iter().map(|g| g.print(cx)))) } }) } } -impl<'a> WhereClause<'a> { - crate fn print<'b>(&'b self, cache: &'b Cache) -> impl fmt::Display + 'b { - display_fn(move |f| { - let &WhereClause { gens, indent, end_newline } = self; - if gens.where_predicates.is_empty() { - return Ok(()); +/// * The Generics from which to emit a where-clause. +/// * The number of spaces to indent each line with. +/// * Whether the where-clause needs to add a comma and newline after the last bound. +crate fn print_where_clause<'a, 'tcx: 'a>( + gens: &'a clean::Generics, + cx: &'a Context<'tcx>, + indent: usize, + end_newline: bool, +) -> impl fmt::Display + 'a + Captures<'tcx> { + display_fn(move |f| { + if gens.where_predicates.is_empty() { + return Ok(()); + } + let mut clause = String::new(); + if f.alternate() { + clause.push_str(" where"); + } else { + if end_newline { + clause.push_str(" where"); + } else { + clause.push_str(" where"); } - let mut clause = String::new(); + } + for (i, pred) in gens.where_predicates.iter().enumerate() { if f.alternate() { - clause.push_str(" where"); + clause.push(' '); } else { - if end_newline { - clause.push_str(" where"); - } else { - clause.push_str(" where"); - } + clause.push_str("
"); } - for (i, pred) in gens.where_predicates.iter().enumerate() { - if f.alternate() { - clause.push(' '); - } else { - clause.push_str("
"); - } - match pred { - clean::WherePredicate::BoundPredicate { ty, bounds } => { - let bounds = bounds; - if f.alternate() { - clause.push_str(&format!( - "{:#}: {:#}", - ty.print(cache), - print_generic_bounds(bounds, cache) - )); - } else { - clause.push_str(&format!( - "{}: {}", - ty.print(cache), - print_generic_bounds(bounds, cache) - )); - } - } - clean::WherePredicate::RegionPredicate { lifetime, bounds } => { + match pred { + clean::WherePredicate::BoundPredicate { ty, bounds } => { + let bounds = bounds; + if f.alternate() { + clause.push_str(&format!( + "{:#}: {:#}", + ty.print(cx), + print_generic_bounds(bounds, cx) + )); + } else { clause.push_str(&format!( "{}: {}", - lifetime.print(), - bounds - .iter() - .map(|b| b.print(cache).to_string()) - .collect::>() - .join(" + ") + ty.print(cx), + print_generic_bounds(bounds, cx) )); } - clean::WherePredicate::EqPredicate { lhs, rhs } => { - if f.alternate() { - clause.push_str(&format!( - "{:#} == {:#}", - lhs.print(cache), - rhs.print(cache) - )); - } else { - clause.push_str(&format!( - "{} == {}", - lhs.print(cache), - rhs.print(cache) - )); - } + } + clean::WherePredicate::RegionPredicate { lifetime, bounds } => { + clause.push_str(&format!( + "{}: {}", + lifetime.print(), + bounds + .iter() + .map(|b| b.print(cx).to_string()) + .collect::>() + .join(" + ") + )); + } + clean::WherePredicate::EqPredicate { lhs, rhs } => { + if f.alternate() { + clause.push_str(&format!("{:#} == {:#}", lhs.print(cx), rhs.print(cx),)); + } else { + clause.push_str(&format!("{} == {}", lhs.print(cx), rhs.print(cx),)); } } + } - if i < gens.where_predicates.len() - 1 || end_newline { - clause.push(','); - } + if i < gens.where_predicates.len() - 1 || end_newline { + clause.push(','); } + } - if end_newline { - // add a space so stripping
tags and breaking spaces still renders properly - if f.alternate() { - clause.push(' '); - } else { - clause.push_str(" "); - } + if end_newline { + // add a space so stripping
tags and breaking spaces still renders properly + if f.alternate() { + clause.push(' '); + } else { + clause.push_str(" "); } + } - if !f.alternate() { - clause.push_str("
"); - let padding = " ".repeat(indent + 4); - clause = clause.replace("
", &format!("
{}", padding)); - clause.insert_str(0, &" ".repeat(indent.saturating_sub(1))); - if !end_newline { - clause.insert_str(0, "
"); - } + if !f.alternate() { + clause.push_str("
"); + let padding = " ".repeat(indent + 4); + clause = clause.replace("
", &format!("
{}", padding)); + clause.insert_str(0, &" ".repeat(indent.saturating_sub(1))); + if !end_newline { + clause.insert_str(0, "
"); } - write!(f, "{}", clause) - }) - } + } + write!(f, "{}", clause) + }) } impl clean::Lifetime { @@ -320,46 +306,51 @@ impl clean::Lifetime { } impl clean::Constant { - crate fn print(&self) -> impl fmt::Display + '_ { - display_fn(move |f| { - if f.alternate() { - f.write_str(&self.expr) - } else { - write!(f, "{}", Escape(&self.expr)) - } - }) + crate fn print(&self, tcx: TyCtxt<'_>) -> impl fmt::Display + '_ { + let expr = self.expr(tcx); + display_fn( + move |f| { + if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) } + }, + ) } } impl clean::PolyTrait { - fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { if !self.generic_params.is_empty() { if f.alternate() { write!( f, "for<{:#}> ", - comma_sep(self.generic_params.iter().map(|g| g.print(cache))) + comma_sep(self.generic_params.iter().map(|g| g.print(cx))) )?; } else { write!( f, "for<{}> ", - comma_sep(self.generic_params.iter().map(|g| g.print(cache))) + comma_sep(self.generic_params.iter().map(|g| g.print(cx))) )?; } } if f.alternate() { - write!(f, "{:#}", self.trait_.print(cache)) + write!(f, "{:#}", self.trait_.print(cx)) } else { - write!(f, "{}", self.trait_.print(cache)) + write!(f, "{}", self.trait_.print(cx)) } }) } } impl clean::GenericBound { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match self { clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()), clean::GenericBound::TraitBound(ty, modifier) => { @@ -369,9 +360,9 @@ impl clean::GenericBound { hir::TraitBoundModifier::MaybeConst => "?const", }; if f.alternate() { - write!(f, "{}{:#}", modifier_str, ty.print(cache)) + write!(f, "{}{:#}", modifier_str, ty.print(cx)) } else { - write!(f, "{}{}", modifier_str, ty.print(cache)) + write!(f, "{}{}", modifier_str, ty.print(cx)) } } }) @@ -379,7 +370,10 @@ impl clean::GenericBound { } impl clean::GenericArgs { - fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { match self { clean::GenericArgs::AngleBracketed { args, bindings } => { @@ -396,9 +390,9 @@ impl clean::GenericArgs { } comma = true; if f.alternate() { - write!(f, "{:#}", arg.print(cache))?; + write!(f, "{:#}", arg.print(cx))?; } else { - write!(f, "{}", arg.print(cache))?; + write!(f, "{}", arg.print(cx))?; } } for binding in bindings { @@ -407,9 +401,9 @@ impl clean::GenericArgs { } comma = true; if f.alternate() { - write!(f, "{:#}", binding.print(cache))?; + write!(f, "{:#}", binding.print(cx))?; } else { - write!(f, "{}", binding.print(cache))?; + write!(f, "{}", binding.print(cx))?; } } if f.alternate() { @@ -428,17 +422,17 @@ impl clean::GenericArgs { } comma = true; if f.alternate() { - write!(f, "{:#}", ty.print(cache))?; + write!(f, "{:#}", ty.print(cx))?; } else { - write!(f, "{}", ty.print(cache))?; + write!(f, "{}", ty.print(cx))?; } } f.write_str(")")?; if let Some(ref ty) = *output { if f.alternate() { - write!(f, " -> {:#}", ty.print(cache))?; + write!(f, " -> {:#}", ty.print(cx))?; } else { - write!(f, " -> {}", ty.print(cache))?; + write!(f, " -> {}", ty.print(cx))?; } } } @@ -448,89 +442,89 @@ impl clean::GenericArgs { } } -impl clean::PathSegment { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { - display_fn(move |f| { - if f.alternate() { - write!(f, "{}{:#}", self.name, self.args.print(cache)) - } else { - write!(f, "{}{}", self.name, self.args.print(cache)) - } - }) - } -} - -impl clean::Path { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { - display_fn(move |f| { - if self.global { - f.write_str("::")? - } - - for (i, seg) in self.segments.iter().enumerate() { - if i > 0 { - f.write_str("::")? - } - if f.alternate() { - write!(f, "{:#}", seg.print(cache))?; - } else { - write!(f, "{}", seg.print(cache))?; - } - } - Ok(()) - }) +crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec)> { + let cache = &cx.cache(); + let relative_to = &cx.current; + fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] { + if shortty == ItemType::Module { &fqp[..] } else { &fqp[..fqp.len() - 1] } } -} -crate fn href(did: DefId, cache: &Cache) -> Option<(String, ItemType, Vec)> { if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private { return None; } - let depth = CURRENT_DEPTH.with(|l| l.get()); - let (fqp, shortty, mut url) = match cache.paths.get(&did) { - Some(&(ref fqp, shortty)) => (fqp, shortty, "../".repeat(depth)), + let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) { + Some(&(ref fqp, shortty)) => (fqp, shortty, { + let module_fqp = to_module_fqp(shortty, fqp); + 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)) => s.to_string(), - (.., ExternalLocation::Local) => "../".repeat(depth), + (.., 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, }, ) } }; - for component in &fqp[..fqp.len() - 1] { - url.push_str(component); - url.push('/'); - } + let last = &fqp.last().unwrap()[..]; + let filename; match shortty { ItemType::Module => { - url.push_str(fqp.last().unwrap()); - url.push_str("/index.html"); + url_parts.push("index.html"); } _ => { - url.push_str(shortty.as_str()); - url.push('.'); - url.push_str(fqp.last().unwrap()); - url.push_str(".html"); + filename = format!("{}.{}.html", shortty.as_str(), last); + url_parts.push(&filename); } } - Some((url, shortty, fqp.to_vec())) + Some((url_parts.join("/"), shortty, fqp.to_vec())) +} + +/// Both paths should only be modules. +/// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will +/// both need `../iter/trait.Iterator.html` to get at the iterator trait. +crate fn href_relative_parts<'a>(fqp: &'a [String], relative_to_fqp: &'a [String]) -> Vec<&'a str> { + for (i, (f, r)) in fqp.iter().zip(relative_to_fqp.iter()).enumerate() { + // e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1) + if f != r { + let dissimilar_part_count = relative_to_fqp.len() - i; + let fqp_module = fqp[i..fqp.len()].iter().map(String::as_str); + return iter::repeat("..").take(dissimilar_part_count).chain(fqp_module).collect(); + } + } + // e.g. linking to std::sync::atomic from std::sync + if relative_to_fqp.len() < fqp.len() { + fqp[relative_to_fqp.len()..fqp.len()].iter().map(String::as_str).collect() + // e.g. linking to std::sync from std::sync::atomic + } else if fqp.len() < relative_to_fqp.len() { + let dissimilar_part_count = relative_to_fqp.len() - fqp.len(); + iter::repeat("..").take(dissimilar_part_count).collect() + // linking to the same module + } else { + Vec::new() + } } /// Used when rendering a `ResolvedPath` structure. This invokes the `path` /// rendering function with the necessary arguments for linking to a local path. -fn resolved_path( +fn resolved_path<'a, 'cx: 'a>( w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, print_all: bool, use_absolute: bool, - cache: &Cache, + cx: &'cx Context<'_>, ) -> fmt::Result { let last = path.segments.last().unwrap(); @@ -540,22 +534,22 @@ fn resolved_path( } } if w.alternate() { - write!(w, "{}{:#}", &last.name, last.args.print(cache))?; + write!(w, "{}{:#}", &last.name, last.args.print(cx))?; } else { let path = if use_absolute { - if let Some((_, _, fqp)) = href(did, cache) { + if let Some((_, _, fqp)) = href(did, cx) { format!( "{}::{}", fqp[..fqp.len() - 1].join("::"), - anchor(did, fqp.last().unwrap(), cache) + anchor(did, fqp.last().unwrap(), cx) ) } else { last.name.to_string() } } else { - anchor(did, &*last.name.as_str(), cache).to_string() + anchor(did, &*last.name.as_str(), cx).to_string() }; - write!(w, "{}{}", path, last.args.print(cache))?; + write!(w, "{}{}", path, last.args.print(cx))?; } Ok(()) } @@ -564,13 +558,14 @@ fn primitive_link( f: &mut fmt::Formatter<'_>, prim: clean::PrimitiveType, name: &str, - m: &Cache, + cx: &Context<'_>, ) -> fmt::Result { + let m = &cx.cache(); let mut needs_termination = false; if !f.alternate() { match m.primitive_locations.get(&prim) { Some(&def_id) if def_id.is_local() => { - let len = CURRENT_DEPTH.with(|s| s.get()); + let len = cx.current.len(); let len = if len == 0 { 0 } else { len - 1 }; write!( f, @@ -581,20 +576,28 @@ fn primitive_link( needs_termination = true; } Some(&def_id) => { + let cname_str; let loc = match m.extern_locations[&def_id.krate] { - (ref cname, _, ExternalLocation::Remote(ref s)) => Some((cname, s.to_string())), + (ref cname, _, ExternalLocation::Remote(ref s)) => { + cname_str = cname.as_str(); + Some(vec![s.trim_end_matches('/'), &cname_str[..]]) + } (ref cname, _, ExternalLocation::Local) => { - let len = CURRENT_DEPTH.with(|s| s.get()); - Some((cname, "../".repeat(len))) + cname_str = cname.as_str(); + Some(if cx.current.first().map(|x| &x[..]) == Some(&cname_str[..]) { + iter::repeat("..").take(cx.current.len() - 1).collect() + } else { + let cname = iter::once(&cname_str[..]); + iter::repeat("..").take(cx.current.len()).chain(cname).collect() + }) } (.., ExternalLocation::Unknown) => None, }; - if let Some((cname, root)) = loc { + if let Some(loc) = loc { write!( f, - "
", - root, - cname, + "", + loc.join("/"), prim.to_url_str() )?; needs_termination = true; @@ -611,15 +614,15 @@ fn primitive_link( } /// Helper to render type parameters -fn tybounds<'a>( +fn tybounds<'a, 'tcx: 'a>( param_names: &'a Option>, - cache: &'a Cache, -) -> impl fmt::Display + 'a { + cx: &'a Context<'tcx>, +) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match *param_names { Some(ref params) => { for param in params { write!(f, " + ")?; - fmt::Display::fmt(¶m.print(cache), f)?; + fmt::Display::fmt(¶m.print(cx), f)?; } Ok(()) } @@ -627,9 +630,14 @@ fn tybounds<'a>( }) } -crate fn anchor<'a>(did: DefId, text: &'a str, cache: &'a Cache) -> impl fmt::Display + 'a { +crate fn anchor<'a, 'cx: 'a>( + did: DefId, + text: &'a str, + cx: &'cx Context<'_>, +) -> impl fmt::Display + 'a { + let parts = href(did, cx); display_fn(move |f| { - if let Some((url, short_ty, fqp)) = href(did, cache) { + if let Some((url, short_ty, fqp)) = parts { write!( f, r#"{}"#, @@ -645,11 +653,11 @@ crate fn anchor<'a>(did: DefId, text: &'a str, cache: &'a Cache) -> impl fmt::Di }) } -fn fmt_type( +fn fmt_type<'cx>( t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool, - cache: &Cache, + cx: &'cx Context<'_>, ) -> fmt::Result { debug!("fmt_type(t = {:?})", t); @@ -660,69 +668,69 @@ fn fmt_type( f.write_str("dyn ")?; } // Paths like `T::Output` and `Self::Output` should be rendered with all segments. - resolved_path(f, did, path, is_generic, use_absolute, cache)?; - fmt::Display::fmt(&tybounds(param_names, cache), f) + resolved_path(f, did, path, is_generic, use_absolute, cx)?; + fmt::Display::fmt(&tybounds(param_names, cx), f) } clean::Infer => write!(f, "_"), - clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cache), + clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cx), clean::BareFunction(ref decl) => { if f.alternate() { write!( f, "{:#}{}{:#}fn{:#}", - decl.print_hrtb_with_space(cache), + decl.print_hrtb_with_space(cx), decl.unsafety.print_with_space(), print_abi_with_space(decl.abi), - decl.decl.print(cache) + decl.decl.print(cx), ) } else { write!( f, "{}{}{}", - decl.print_hrtb_with_space(cache), + decl.print_hrtb_with_space(cx), decl.unsafety.print_with_space(), print_abi_with_space(decl.abi) )?; - primitive_link(f, PrimitiveType::Fn, "fn", cache)?; - write!(f, "{}", decl.decl.print(cache)) + primitive_link(f, PrimitiveType::Fn, "fn", cx)?; + write!(f, "{}", decl.decl.print(cx)) } } clean::Tuple(ref typs) => { match &typs[..] { - &[] => primitive_link(f, PrimitiveType::Unit, "()", cache), + &[] => primitive_link(f, PrimitiveType::Unit, "()", cx), &[ref one] => { - primitive_link(f, PrimitiveType::Tuple, "(", cache)?; + primitive_link(f, PrimitiveType::Tuple, "(", cx)?; // Carry `f.alternate()` into this display w/o branching manually. - fmt::Display::fmt(&one.print(cache), f)?; - primitive_link(f, PrimitiveType::Tuple, ",)", cache) + fmt::Display::fmt(&one.print(cx), f)?; + primitive_link(f, PrimitiveType::Tuple, ",)", cx) } many => { - primitive_link(f, PrimitiveType::Tuple, "(", cache)?; + primitive_link(f, PrimitiveType::Tuple, "(", cx)?; for (i, item) in many.iter().enumerate() { if i != 0 { write!(f, ", ")?; } - fmt::Display::fmt(&item.print(cache), f)?; + fmt::Display::fmt(&item.print(cx), f)?; } - primitive_link(f, PrimitiveType::Tuple, ")", cache) + primitive_link(f, PrimitiveType::Tuple, ")", cx) } } } clean::Slice(ref t) => { - primitive_link(f, PrimitiveType::Slice, "[", cache)?; - fmt::Display::fmt(&t.print(cache), f)?; - primitive_link(f, PrimitiveType::Slice, "]", cache) + primitive_link(f, PrimitiveType::Slice, "[", cx)?; + fmt::Display::fmt(&t.print(cx), f)?; + primitive_link(f, PrimitiveType::Slice, "]", cx) } clean::Array(ref t, ref n) => { - primitive_link(f, PrimitiveType::Array, "[", cache)?; - fmt::Display::fmt(&t.print(cache), f)?; + primitive_link(f, PrimitiveType::Array, "[", cx)?; + fmt::Display::fmt(&t.print(cx), f)?; if f.alternate() { - primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cache) + primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cx) } else { - primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)), cache) + primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)), cx) } } - clean::Never => primitive_link(f, PrimitiveType::Never, "!", cache), + clean::Never => primitive_link(f, PrimitiveType::Never, "!", cx), clean::RawPointer(m, ref t) => { let m = match m { hir::Mutability::Mut => "mut", @@ -734,26 +742,21 @@ fn fmt_type( primitive_link( f, clean::PrimitiveType::RawPointer, - &format!("*{} {:#}", m, t.print(cache)), - cache, + &format!("*{} {:#}", m, t.print(cx)), + cx, ) } else { primitive_link( f, clean::PrimitiveType::RawPointer, - &format!("*{} {}", m, t.print(cache)), - cache, + &format!("*{} {}", m, t.print(cx)), + cx, ) } } _ => { - primitive_link( - f, - clean::PrimitiveType::RawPointer, - &format!("*{} ", m), - cache, - )?; - fmt::Display::fmt(&t.print(cache), f) + primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?; + fmt::Display::fmt(&t.print(cx), f) } } } @@ -773,15 +776,15 @@ fn fmt_type( primitive_link( f, PrimitiveType::Slice, - &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache)), - cache, + &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cx)), + cx, ) } else { primitive_link( f, PrimitiveType::Slice, - &format!("{}{}{}[{}]", amp, lt, m, bt.print(cache)), - cache, + &format!("{}{}{}[{}]", amp, lt, m, bt.print(cx)), + cx, ) } } @@ -790,20 +793,20 @@ fn fmt_type( f, PrimitiveType::Slice, &format!("{}{}{}[", amp, lt, m), - cache, + cx, )?; if f.alternate() { - write!(f, "{:#}", bt.print(cache))?; + write!(f, "{:#}", bt.print(cx))?; } else { - write!(f, "{}", bt.print(cache))?; + write!(f, "{}", bt.print(cx))?; } - primitive_link(f, PrimitiveType::Slice, "]", cache) + primitive_link(f, PrimitiveType::Slice, "]", cx) } } } clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => { write!(f, "{}{}{}(", amp, lt, m)?; - fmt_type(&ty, f, use_absolute, cache)?; + fmt_type(&ty, f, use_absolute, cx)?; write!(f, ")") } clean::Generic(..) => { @@ -811,21 +814,21 @@ fn fmt_type( f, PrimitiveType::Reference, &format!("{}{}{}", amp, lt, m), - cache, + cx, )?; - fmt_type(&ty, f, use_absolute, cache) + fmt_type(&ty, f, use_absolute, cx) } _ => { write!(f, "{}{}{}", amp, lt, m)?; - fmt_type(&ty, f, use_absolute, cache) + fmt_type(&ty, f, use_absolute, cx) } } } clean::ImplTrait(ref bounds) => { if f.alternate() { - write!(f, "impl {:#}", print_generic_bounds(bounds, cache)) + write!(f, "impl {:#}", print_generic_bounds(bounds, cx)) } else { - write!(f, "impl {}", print_generic_bounds(bounds, cache)) + write!(f, "impl {}", print_generic_bounds(bounds, cx)) } } clean::QPath { ref name, ref self_type, ref trait_ } => { @@ -837,15 +840,15 @@ fn fmt_type( }; if f.alternate() { if should_show_cast { - write!(f, "<{:#} as {:#}>::", self_type.print(cache), trait_.print(cache))? + write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? } else { - write!(f, "{:#}::", self_type.print(cache))? + write!(f, "{:#}::", self_type.print(cx))? } } else { if should_show_cast { - write!(f, "<{} as {}>::", self_type.print(cache), trait_.print(cache))? + write!(f, "<{} as {}>::", self_type.print(cx), trait_.print(cx))? } else { - write!(f, "{}::", self_type.print(cache))? + write!(f, "{}::", self_type.print(cx))? } }; match *trait_ { @@ -860,7 +863,7 @@ fn fmt_type( // everything comes in as a fully resolved QPath (hard to // look at). box clean::ResolvedPath { did, ref param_names, .. } => { - match href(did, cache) { + match href(did, cx) { Some((ref url, _, ref path)) if !f.alternate() => { write!( f, @@ -886,52 +889,61 @@ fn fmt_type( } impl clean::Type { - crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { - display_fn(move |f| fmt_type(self, f, false, cache)) + crate fn print<'b, 'a: 'b, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'b + Captures<'tcx> { + display_fn(move |f| fmt_type(self, f, false, cx)) } } impl clean::Impl { - crate fn print<'a>(&'a self, cache: &'a Cache, use_absolute: bool) -> impl fmt::Display + 'a { + crate fn print<'a, 'tcx: 'a>( + &'a self, + use_absolute: bool, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { if f.alternate() { - write!(f, "impl{:#} ", self.generics.print(cache))?; + write!(f, "impl{:#} ", self.generics.print(cx))?; } else { - write!(f, "impl{} ", self.generics.print(cache))?; + write!(f, "impl{} ", self.generics.print(cx))?; } if let Some(ref ty) = self.trait_ { if self.negative_polarity { write!(f, "!")?; } - fmt::Display::fmt(&ty.print(cache), f)?; + fmt::Display::fmt(&ty.print(cx), f)?; write!(f, " for ")?; } if let Some(ref ty) = self.blanket_impl { - fmt_type(ty, f, use_absolute, cache)?; + fmt_type(ty, f, use_absolute, cx)?; } else { - fmt_type(&self.for_, f, use_absolute, cache)?; + fmt_type(&self.for_, f, use_absolute, cx)?; } - let where_clause = WhereClause { gens: &self.generics, indent: 0, end_newline: true }; - fmt::Display::fmt(&where_clause.print(cache), f)?; + fmt::Display::fmt(&print_where_clause(&self.generics, cx, 0, true), f)?; Ok(()) }) } } impl clean::Arguments { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { for (i, input) in self.values.iter().enumerate() { if !input.name.is_empty() { write!(f, "{}: ", input.name)?; } if f.alternate() { - write!(f, "{:#}", input.type_.print(cache))?; + write!(f, "{:#}", input.type_.print(cx))?; } else { - write!(f, "{}", input.type_.print(cache))?; + write!(f, "{}", input.type_.print(cx))?; } if i + 1 < self.values.len() { write!(f, ", ")?; @@ -943,21 +955,29 @@ impl clean::Arguments { } impl clean::FnRetTy { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match self { clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()), - clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache)), - clean::Return(ty) => write!(f, " -> {}", ty.print(cache)), + clean::Return(ty) if f.alternate() => { + write!(f, " -> {:#}", ty.print(cx)) + } + clean::Return(ty) => write!(f, " -> {}", ty.print(cx)), clean::DefaultReturn => Ok(()), }) } } impl clean::BareFunctionDecl { - fn print_hrtb_with_space<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + fn print_hrtb_with_space<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { if !self.generic_params.is_empty() { - write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cache)))) + write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cx)))) } else { Ok(()) } @@ -966,149 +986,164 @@ impl clean::BareFunctionDecl { } impl clean::FnDecl { - crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + crate fn print<'b, 'a: 'b, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'b + Captures<'tcx> { display_fn(move |f| { let ellipsis = if self.c_variadic { ", ..." } else { "" }; if f.alternate() { write!( f, "({args:#}{ellipsis}){arrow:#}", - args = self.inputs.print(cache), + args = self.inputs.print(cx), ellipsis = ellipsis, - arrow = self.output.print(cache) + arrow = self.output.print(cx) ) } else { write!( f, "({args}{ellipsis}){arrow}", - args = self.inputs.print(cache), + args = self.inputs.print(cx), ellipsis = ellipsis, - arrow = self.output.print(cache) + arrow = self.output.print(cx) ) } }) } -} -impl Function<'_> { - crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { - display_fn(move |f| { - let &Function { decl, header_len, indent, asyncness } = self; - let amp = if f.alternate() { "&" } else { "&" }; - let mut args = String::new(); - let mut args_plain = String::new(); - for (i, input) in decl.inputs.values.iter().enumerate() { - if i == 0 { - args.push_str("
"); - } + /// * `header_len`: The length of the function header and name. In other words, the number of + /// characters in the function declaration up to but not including the parentheses. + ///
Used to determine line-wrapping. + /// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is + /// necessary. + /// * `asyncness`: Whether the function is async or not. + crate fn full_print<'a, 'tcx: 'a>( + &'a self, + header_len: usize, + indent: usize, + asyncness: hir::IsAsync, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { + display_fn(move |f| self.inner_full_print(header_len, indent, asyncness, f, cx)) + } - if let Some(selfty) = input.to_self() { - match selfty { - clean::SelfValue => { - args.push_str("self"); - args_plain.push_str("self"); - } - clean::SelfBorrowed(Some(ref lt), mtbl) => { - args.push_str(&format!( - "{}{} {}self", - amp, - lt.print(), - mtbl.print_with_space() - )); - args_plain.push_str(&format!( - "&{} {}self", - lt.print(), - mtbl.print_with_space() - )); - } - clean::SelfBorrowed(None, mtbl) => { - args.push_str(&format!("{}{}self", amp, mtbl.print_with_space())); - args_plain.push_str(&format!("&{}self", mtbl.print_with_space())); - } - clean::SelfExplicit(ref typ) => { - if f.alternate() { - args.push_str(&format!("self: {:#}", typ.print(cache))); - } else { - args.push_str(&format!("self: {}", typ.print(cache))); - } - args_plain.push_str(&format!("self: {:#}", typ.print(cache))); - } + fn inner_full_print( + &self, + header_len: usize, + indent: usize, + asyncness: hir::IsAsync, + f: &mut fmt::Formatter<'_>, + cx: &Context<'_>, + ) -> fmt::Result { + let amp = if f.alternate() { "&" } else { "&" }; + let mut args = String::new(); + let mut args_plain = String::new(); + for (i, input) in self.inputs.values.iter().enumerate() { + if i == 0 { + args.push_str("
"); + } + + if let Some(selfty) = input.to_self() { + match selfty { + clean::SelfValue => { + args.push_str("self"); + args_plain.push_str("self"); } - } else { - if i > 0 { - args.push_str("
"); - args_plain.push(' '); + clean::SelfBorrowed(Some(ref lt), mtbl) => { + args.push_str(&format!( + "{}{} {}self", + amp, + lt.print(), + mtbl.print_with_space() + )); + args_plain.push_str(&format!( + "&{} {}self", + lt.print(), + mtbl.print_with_space() + )); } - if !input.name.is_empty() { - args.push_str(&format!("{}: ", input.name)); - args_plain.push_str(&format!("{}: ", input.name)); + clean::SelfBorrowed(None, mtbl) => { + args.push_str(&format!("{}{}self", amp, mtbl.print_with_space())); + args_plain.push_str(&format!("&{}self", mtbl.print_with_space())); } - - if f.alternate() { - args.push_str(&format!("{:#}", input.type_.print(cache))); - } else { - args.push_str(&input.type_.print(cache).to_string()); + clean::SelfExplicit(ref typ) => { + if f.alternate() { + args.push_str(&format!("self: {:#}", typ.print(cx))); + } else { + args.push_str(&format!("self: {}", typ.print(cx))); + } + args_plain.push_str(&format!("self: {:#}", typ.print(cx))); } - args_plain.push_str(&format!("{:#}", input.type_.print(cache))); } - if i + 1 < decl.inputs.values.len() { - args.push(','); - args_plain.push(','); + } else { + if i > 0 { + args.push_str("
"); + args_plain.push(' '); + } + if !input.name.is_empty() { + args.push_str(&format!("{}: ", input.name)); + args_plain.push_str(&format!("{}: ", input.name)); } - } - - let mut args_plain = format!("({})", args_plain); - if decl.c_variadic { - args.push_str(",
..."); - args_plain.push_str(", ..."); + if f.alternate() { + args.push_str(&format!("{:#}", input.type_.print(cx))); + } else { + args.push_str(&input.type_.print(cx).to_string()); + } + args_plain.push_str(&format!("{:#}", input.type_.print(cx))); } + if i + 1 < self.inputs.values.len() { + args.push(','); + args_plain.push(','); + } + } - let output = if let hir::IsAsync::Async = asyncness { - Cow::Owned(decl.sugared_async_return_type()) - } else { - Cow::Borrowed(&decl.output) - }; + let mut args_plain = format!("({})", args_plain); - let arrow_plain = format!("{:#}", &output.print(cache)); - let arrow = if f.alternate() { - format!("{:#}", &output.print(cache)) - } else { - output.print(cache).to_string() - }; + if self.c_variadic { + args.push_str(",
..."); + args_plain.push_str(", ..."); + } - let declaration_len = header_len + args_plain.len() + arrow_plain.len(); - let output = if declaration_len > 80 { - let full_pad = format!("
{}", " ".repeat(indent + 4)); - let close_pad = format!("
{}", " ".repeat(indent)); - format!( - "({args}{close}){arrow}", - args = args.replace("
", &full_pad), - close = close_pad, - arrow = arrow - ) - } else { - format!("({args}){arrow}", args = args.replace("
", ""), arrow = arrow) - }; + let arrow_plain; + let arrow = if let hir::IsAsync::Async = asyncness { + let output = self.sugared_async_return_type(); + arrow_plain = format!("{:#}", output.print(cx)); + if f.alternate() { arrow_plain.clone() } else { format!("{}", output.print(cx)) } + } else { + arrow_plain = format!("{:#}", self.output.print(cx)); + if f.alternate() { arrow_plain.clone() } else { format!("{}", self.output.print(cx)) } + }; - if f.alternate() { - write!(f, "{}", output.replace("
", "\n")) - } else { - write!(f, "{}", output) - } - }) + let declaration_len = header_len + args_plain.len() + arrow_plain.len(); + let output = if declaration_len > 80 { + let full_pad = format!("
{}", " ".repeat(indent + 4)); + let close_pad = format!("
{}", " ".repeat(indent)); + format!( + "({args}{close}){arrow}", + args = args.replace("
", &full_pad), + close = close_pad, + arrow = arrow + ) + } else { + format!("({args}){arrow}", args = args.replace("
", ""), arrow = arrow) + }; + + if f.alternate() { + write!(f, "{}", output.replace("
", "\n")) + } else { + write!(f, "{}", output) + } } } impl clean::Visibility { - crate fn print_with_space<'tcx>( + crate fn print_with_space<'a, 'tcx: 'a>( self, - tcx: TyCtxt<'tcx>, item_did: DefId, - cache: &Cache, - ) -> impl fmt::Display + 'tcx { - use rustc_span::symbol::kw; - + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { let to_print = match self { clean::Public => "pub ".to_owned(), clean::Inherited => String::new(), @@ -1116,7 +1151,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(tcx, item_did); + let parent_module = find_nearest_parent_module(cx.tcx(), item_did); if vis_did.index == CRATE_DEF_INDEX { "pub(crate) ".to_owned() @@ -1125,26 +1160,19 @@ impl clean::Visibility { // is the same as no visibility modifier String::new() } else if parent_module - .map(|parent| find_nearest_parent_module(tcx, parent)) + .map(|parent| find_nearest_parent_module(cx.tcx(), parent)) .flatten() == Some(vis_did) { "pub(super) ".to_owned() } else { - let path = tcx.def_path(vis_did); + let path = cx.tcx().def_path(vis_did); debug!("path={:?}", path); - let first_name = - path.data[0].data.get_opt_name().expect("modules are always named"); // modified from `resolved_path()` to work with `DefPathData` let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); - let anchor = anchor(vis_did, &last_name.as_str(), cache).to_string(); + let anchor = anchor(vis_did, &last_name.as_str(), cx).to_string(); - let mut s = "pub(".to_owned(); - if path.data.len() != 1 - || (first_name != kw::SelfLower && first_name != kw::Super) - { - s.push_str("in "); - } + let mut s = "pub(in ".to_owned(); for seg in &path.data[..path.data.len() - 1] { s.push_str(&format!("{}::", seg.data.get_opt_name().unwrap())); } @@ -1155,6 +1183,43 @@ impl clean::Visibility { }; display_fn(move |f| f.write_str(&to_print)) } + + /// This function is the same as print_with_space, except that it renders no links. + /// It's used for macros' rendered source view, which is syntax highlighted and cannot have + /// any HTML in it. + crate fn to_src_with_space<'a, 'tcx: 'a>( + self, + tcx: TyCtxt<'tcx>, + item_did: DefId, + ) -> impl fmt::Display + 'a + Captures<'tcx> { + let to_print = match self { + clean::Public => "pub ".to_owned(), + clean::Inherited => String::new(), + clean::Visibility::Restricted(vis_did) => { + // 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(tcx, item_did); + + if vis_did.index == CRATE_DEF_INDEX { + "pub(crate) ".to_owned() + } else if parent_module == Some(vis_did) { + // `pub(in foo)` where `foo` is the parent module + // is the same as no visibility modifier + String::new() + } else if parent_module + .map(|parent| find_nearest_parent_module(tcx, parent)) + .flatten() + == Some(vis_did) + { + "pub(super) ".to_owned() + } else { + format!("pub(in {}) ", tcx.def_path_str(vis_did)) + } + } + }; + display_fn(move |f| f.write_str(&to_print)) + } } crate trait PrintWithSpace { @@ -1198,20 +1263,23 @@ impl PrintWithSpace for hir::Mutability { } impl clean::Import { - crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match self.kind { clean::ImportKind::Simple(name) => { if name == self.source.path.last() { - write!(f, "use {};", self.source.print(cache)) + write!(f, "use {};", self.source.print(cx)) } else { - write!(f, "use {} as {};", self.source.print(cache), name) + write!(f, "use {} as {};", self.source.print(cx), name) } } clean::ImportKind::Glob => { if self.source.path.segments.is_empty() { write!(f, "use *;") } else { - write!(f, "use {}::*;", self.source.print(cache)) + write!(f, "use {}::*;", self.source.print(cx)) } } }) @@ -1219,16 +1287,19 @@ impl clean::Import { } impl clean::ImportSource { - crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match self.did { - Some(did) => resolved_path(f, did, &self.path, true, false, cache), + Some(did) => resolved_path(f, did, &self.path, true, false, cx), _ => { for seg in &self.path.segments[..self.path.segments.len() - 1] { write!(f, "{}::", seg.name)?; } let name = self.path.last_name(); if let hir::def::Res::PrimTy(p) = self.path.res { - primitive_link(f, PrimitiveType::from(p), &*name, cache)?; + primitive_link(f, PrimitiveType::from(p), &*name, cx)?; } else { write!(f, "{}", name)?; } @@ -1239,23 +1310,26 @@ impl clean::ImportSource { } impl clean::TypeBinding { - crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { f.write_str(&*self.name.as_str())?; match self.kind { clean::TypeBindingKind::Equality { ref ty } => { if f.alternate() { - write!(f, " = {:#}", ty.print(cache))?; + write!(f, " = {:#}", ty.print(cx))?; } else { - write!(f, " = {}", ty.print(cache))?; + write!(f, " = {}", ty.print(cx))?; } } clean::TypeBindingKind::Constraint { ref bounds } => { if !bounds.is_empty() { if f.alternate() { - write!(f, ": {:#}", print_generic_bounds(bounds, cache))?; + write!(f, ": {:#}", print_generic_bounds(bounds, cx))?; } else { - write!(f, ": {}", print_generic_bounds(bounds, cache))?; + write!(f, ": {}", print_generic_bounds(bounds, cx))?; } } } @@ -1280,11 +1354,14 @@ crate fn print_default_space<'a>(v: bool) -> &'a str { } impl clean::GenericArg { - crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match self { clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(<.print(), f), - clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache), f), - clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(), f), + clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cx), f), + clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(cx.tcx()), f), }) } } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 7e50d72e60..0030ef67c0 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -136,6 +136,16 @@ impl Iterator for TokenIter<'a> { } } +fn get_real_ident_class(text: &str, edition: Edition) -> Class { + match text { + "ref" | "mut" => Class::RefKeyWord, + "self" | "Self" => Class::Self_, + "false" | "true" => Class::Bool, + _ if Symbol::intern(text).is_reserved(|| edition) => Class::KeyWord, + _ => Class::Ident, + } +} + /// Processes program tokens, classifying strings of text by highlighting /// category (`Class`). struct Classifier<'a> { @@ -144,6 +154,8 @@ struct Classifier<'a> { in_macro: bool, in_macro_nonterminal: bool, edition: Edition, + byte_pos: u32, + src: &'a str, } impl<'a> Classifier<'a> { @@ -155,6 +167,68 @@ impl<'a> Classifier<'a> { in_macro: false, in_macro_nonterminal: false, edition, + byte_pos: 0, + src, + } + } + + /// Concatenate colons and idents as one when possible. + fn get_full_ident_path(&mut self) -> Vec<(TokenKind, usize, usize)> { + let start = self.byte_pos as usize; + let mut pos = start; + let mut has_ident = false; + let edition = self.edition; + + loop { + let mut nb = 0; + while let Some((TokenKind::Colon, _)) = self.tokens.peek() { + self.tokens.next(); + nb += 1; + } + // Ident path can start with "::" but if we already have content in the ident path, + // the "::" is mandatory. + if has_ident && nb == 0 { + return vec![(TokenKind::Ident, start, pos)]; + } else if nb != 0 && nb != 2 { + if has_ident { + return vec![(TokenKind::Ident, start, pos), (TokenKind::Colon, pos, pos + nb)]; + } else { + return vec![(TokenKind::Colon, pos, pos + nb)]; + } + } + + if let Some((Class::Ident, text)) = self.tokens.peek().map(|(token, text)| { + if *token == TokenKind::Ident { + let class = get_real_ident_class(text, edition); + (class, text) + } else { + // Doesn't matter which Class we put in here... + (Class::Comment, text) + } + }) { + // We only "add" the colon if there is an ident behind. + pos += text.len() + nb; + has_ident = true; + self.tokens.next(); + } else if nb > 0 && has_ident { + return vec![(TokenKind::Ident, start, pos), (TokenKind::Colon, pos, pos + nb)]; + } else if nb > 0 { + return vec![(TokenKind::Colon, pos, pos + nb)]; + } else if has_ident { + return vec![(TokenKind::Ident, start, pos)]; + } else { + return Vec::new(); + } + } + } + + /// Wraps the tokens iteration to ensure that the byte_pos is always correct. + fn next(&mut self) -> Option<(TokenKind, &'a str)> { + if let Some((kind, text)) = self.tokens.next() { + self.byte_pos += text.len() as u32; + Some((kind, text)) + } else { + None } } @@ -165,8 +239,25 @@ impl<'a> Classifier<'a> { /// token is used. fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) { with_default_session_globals(|| { - while let Some((token, text)) = self.tokens.next() { - self.advance(token, text, sink); + loop { + if self + .tokens + .peek() + .map(|t| matches!(t.0, TokenKind::Colon | TokenKind::Ident)) + .unwrap_or(false) + { + let tokens = self.get_full_ident_path(); + for (token, start, end) in tokens { + let text = &self.src[start..end]; + self.advance(token, text, sink); + self.byte_pos += text.len() as u32; + } + } + if let Some((token, text)) = self.next() { + self.advance(token, text, sink); + } else { + break; + } } }) } @@ -189,7 +280,9 @@ impl<'a> Classifier<'a> { // leading identifier. TokenKind::Bang if self.in_macro => { self.in_macro = false; - Class::Macro + sink(Highlight::Token { text, class: None }); + sink(Highlight::ExitSpan); + return; } // Assume that '&' or '*' is the reference or dereference operator @@ -201,12 +294,12 @@ impl<'a> Classifier<'a> { }, TokenKind::And => match lookahead { Some(TokenKind::And) => { - let _and = self.tokens.next(); + self.next(); sink(Highlight::Token { text: "&&", class: Some(Class::Op) }); return; } Some(TokenKind::Eq) => { - let _eq = self.tokens.next(); + self.next(); sink(Highlight::Token { text: "&=", class: Some(Class::Op) }); return; } @@ -258,7 +351,7 @@ impl<'a> Classifier<'a> { match lookahead { // Case 1: #![inner_attribute] Some(TokenKind::Bang) => { - let _not = self.tokens.next().unwrap(); + self.next(); if let Some(TokenKind::OpenBracket) = self.peek() { self.in_attribute = true; sink(Highlight::EnterSpan { class: Class::Attribute }); @@ -298,21 +391,21 @@ impl<'a> Classifier<'a> { }, TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => { self.in_macro = true; - Class::Macro + sink(Highlight::EnterSpan { class: Class::Macro }); + sink(Highlight::Token { text, class: None }); + return; } - TokenKind::Ident => match text { - "ref" | "mut" => Class::RefKeyWord, - "self" | "Self" => Class::Self_, - "false" | "true" => Class::Bool, - "Option" | "Result" => Class::PreludeTy, - "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, - // Keywords are also included in the identifier set. - _ if Symbol::intern(text).is_reserved(|| self.edition) => Class::KeyWord, - _ if self.in_macro_nonterminal => { - self.in_macro_nonterminal = false; - Class::MacroNonTerminal - } - _ => Class::Ident, + TokenKind::Ident => match get_real_ident_class(text, self.edition) { + Class::Ident => match text { + "Option" | "Result" => Class::PreludeTy, + "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, + _ if self.in_macro_nonterminal => { + self.in_macro_nonterminal = false; + Class::MacroNonTerminal + } + _ => Class::Ident, + }, + c => c, }, TokenKind::RawIdent => Class::Ident, TokenKind::Lifetime { .. } => Class::Lifetime, diff --git a/src/librustdoc/html/highlight/fixtures/dos_line.html b/src/librustdoc/html/highlight/fixtures/dos_line.html index 4400f85681..1c8dbffe78 100644 --- a/src/librustdoc/html/highlight/fixtures/dos_line.html +++ b/src/librustdoc/html/highlight/fixtures/dos_line.html @@ -1,3 +1,3 @@ pub fn foo() { -println!("foo"); +println!("foo"); } diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html index d937246f46..8d23477bbc 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.html +++ b/src/librustdoc/html/highlight/fixtures/sample.html @@ -10,6 +10,8 @@

(&self, mut pred: P) -> usize + where + P: FnMut(&T) -> bool, + { + let (front, back) = self.as_slices(); + + if let Some(true) = back.first().map(|v| pred(v)) { + back.partition_point(pred) + front.len() + } else { + front.partition_point(pred) + } + } } impl VecDeque { diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index f9424b1d74..3ef55f06e5 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -19,6 +19,10 @@ //! format!("{value}", value=4); // => "4" //! format!("{} {}", 1, 2); // => "1 2" //! format!("{:04}", 42); // => "0042" with leading zeros +//! format!("{:#?}", (100, 200)); // => "( +//! // 100, +//! // 200, +//! // )" //! ``` //! //! From these, you can see that the first argument is a format string. It is @@ -157,13 +161,12 @@ //! //! * `+` - This is intended for numeric types and indicates that the sign //! should always be printed. Positive signs are never printed by -//! default, and the negative sign is only printed by default for the -//! `Signed` trait. This flag indicates that the correct sign (`+` or `-`) -//! should always be printed. +//! default, and the negative sign is only printed by default for signed values. +//! This flag indicates that the correct sign (`+` or `-`) should always be printed. //! * `-` - Currently not used //! * `#` - This flag indicates that the "alternate" form of printing should //! be used. The alternate forms are: -//! * `#?` - pretty-print the [`Debug`] formatting +//! * `#?` - pretty-print the [`Debug`] formatting (adds linebreaks and indentation) //! * `#x` - precedes the argument with a `0x` //! * `#X` - precedes the argument with a `0x` //! * `#b` - precedes the argument with a `0b` diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index bde75031f6..15308a4469 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -76,7 +76,6 @@ #![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(new_uninit))] #![feature(allocator_api)] -#![feature(vec_extend_from_within)] #![feature(array_chunks)] #![feature(array_methods)] #![feature(array_windows)] @@ -89,7 +88,8 @@ #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] #![feature(const_btree_new)] -#![feature(const_fn)] +#![cfg_attr(bootstrap, feature(const_fn))] +#![cfg_attr(not(bootstrap), feature(const_fn_trait_bound))] #![feature(cow_is_borrowed)] #![feature(const_cow_is_borrowed)] #![feature(destructuring_assignment)] @@ -103,12 +103,12 @@ #![feature(fn_traits)] #![feature(fundamental)] #![feature(inplace_iteration)] -#![feature(int_bits_const)] // Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]` // blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad // that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] +#![feature(iter_zip)] #![feature(lang_items)] #![feature(layout_for_ptr)] #![feature(maybe_uninit_ref)] @@ -118,7 +118,7 @@ #![feature(nonnull_slice_from_raw_parts)] #![feature(auto_traits)] #![feature(option_result_unwrap_unchecked)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(pattern)] #![feature(ptr_internals)] #![feature(rustc_attrs)] @@ -133,7 +133,6 @@ #![feature(trusted_len)] #![feature(unboxed_closures)] #![feature(unicode_internals)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] #![feature(unsize)] #![feature(unsized_fn_params)] #![feature(allocator_internals)] @@ -142,8 +141,7 @@ #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] #![feature(try_trait)] -#![cfg_attr(bootstrap, feature(type_alias_impl_trait))] -#![cfg_attr(not(bootstrap), feature(min_type_alias_impl_trait))] +#![feature(min_type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] #![feature(decl_macro)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 56f4ebe57f..fe87a97bac 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -53,17 +53,11 @@ pub struct RawVec { } impl RawVec { - /// HACK(Centril): This exists because `#[unstable]` `const fn`s needn't conform - /// to `min_const_fn` and so they cannot be called in `min_const_fn`s either. + /// HACK(Centril): This exists because stable `const fn` can only call stable `const fn`, so + /// they cannot call `Self::new()`. /// - /// If you change `RawVec::new` or dependencies, please take care to not - /// introduce anything that would truly violate `min_const_fn`. - /// - /// NOTE: We could avoid this hack and check conformance with some - /// `#[rustc_force_min_const_fn]` attribute which requires conformance - /// with `min_const_fn` but does not necessarily allow calling it in - /// `stable(...) const fn` / user code not enabling `foo` when - /// `#[rustc_const_unstable(feature = "foo", issue = "01234")]` is present. + /// If you change `RawVec::new` or dependencies, please take care to not introduce anything + /// that would truly const-call something unstable. pub const NEW: Self = Self::new(); /// Creates the biggest possible `RawVec` (on the system heap) @@ -315,8 +309,24 @@ impl RawVec { /// # vector.push_all(&[1, 3, 5, 7, 9]); /// # } /// ``` + #[inline] pub fn reserve(&mut self, len: usize, additional: usize) { - handle_reserve(self.try_reserve(len, additional)); + // Callers expect this function to be very cheap when there is already sufficient capacity. + // Therefore, we move all the resizing and error-handling logic from grow_amortized and + // handle_reserve behind a call, while making sure that the this function is likely to be + // inlined as just a comparison and a call if the comparison fails. + #[cold] + fn do_reserve_and_handle( + slf: &mut RawVec, + len: usize, + additional: usize, + ) { + handle_reserve(slf.grow_amortized(len, additional)); + } + + if self.needs_to_grow(len, additional) { + do_reserve_and_handle(self, len, additional); + } } /// The same as `reserve`, but returns on errors instead of panicking or aborting. diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index dac4acc469..cb4af7c5cd 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -910,6 +910,73 @@ impl Rc { this.inner().strong() } + /// Increments the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, and the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count(ptr); + /// + /// let five = Rc::from_raw(ptr); + /// assert_eq!(2, Rc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] + pub unsafe fn increment_strong_count(ptr: *const T) { + // Retain Rc, but don't touch refcount by wrapping in ManuallyDrop + let rc = unsafe { mem::ManuallyDrop::new(Rc::::from_raw(ptr)) }; + // Now increase refcount, but don't drop new refcount either + let _rc_clone: mem::ManuallyDrop<_> = rc.clone(); + } + + /// Decrements the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, and the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method. This method can be used to release + /// the final `Rc` and backing storage, but **should not** be called after + /// the final `Rc` has been released. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count(ptr); + /// + /// let five = Rc::from_raw(ptr); + /// assert_eq!(2, Rc::strong_count(&five)); + /// Rc::decrement_strong_count(ptr); + /// assert_eq!(1, Rc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] + pub unsafe fn decrement_strong_count(ptr: *const T) { + unsafe { mem::drop(Rc::from_raw(ptr)) }; + } + /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to /// this allocation. #[inline] @@ -1848,8 +1915,11 @@ impl> ToRcSlice for I { Rc::from_iter_exact(self, low) } } else { - // Fall back to normal implementation. - self.collect::>().into() + // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); } } } @@ -2260,8 +2330,8 @@ impl fmt::Debug for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { - /// Constructs a new `Weak`, allocating memory for `T` without initializing - /// it. Calling [`upgrade`] on the return value always gives [`None`]. + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. /// /// [`None`]: Option /// [`upgrade`]: Weak::upgrade diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 8cd4ef7a14..f5d0e911b6 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -222,7 +222,6 @@ mod hack { } #[lang = "slice_alloc"] -#[cfg_attr(not(test), rustc_diagnostic_item = "slice")] #[cfg(not(test))] impl [T] { /// Sorts the slice. @@ -642,7 +641,7 @@ impl [u8] { /// /// To uppercase the value in-place, use [`make_ascii_uppercase`]. /// - /// [`make_ascii_uppercase`]: u8::make_ascii_uppercase + /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> Vec { @@ -659,7 +658,7 @@ impl [u8] { /// /// To lowercase the value in-place, use [`make_ascii_lowercase`]. /// - /// [`make_ascii_lowercase`]: u8::make_ascii_lowercase + /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> Vec { diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 73401fcc8a..879af7cf4d 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -46,6 +46,8 @@ pub use core::str::pattern; pub use core::str::EncodeUtf16; #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] pub use core::str::SplitAsciiWhitespace; +#[stable(feature = "split_inclusive", since = "1.53.0")] +pub use core::str::SplitInclusive; #[stable(feature = "rust1", since = "1.0.0")] pub use core::str::SplitWhitespace; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 019b17a594..f4ec4a36ff 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -360,7 +360,7 @@ impl String { /// let s = String::new(); /// ``` #[inline] - #[rustc_const_stable(feature = "const_string_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] pub const fn new() -> String { String { vec: Vec::new() } @@ -1289,37 +1289,44 @@ impl String { where F: FnMut(char) -> bool, { - let len = self.len(); - let mut del_bytes = 0; - let mut idx = 0; + struct SetLenOnDrop<'a> { + s: &'a mut String, + idx: usize, + del_bytes: usize, + } - unsafe { - self.vec.set_len(0); + impl<'a> Drop for SetLenOnDrop<'a> { + fn drop(&mut self) { + let new_len = self.idx - self.del_bytes; + debug_assert!(new_len <= self.s.len()); + unsafe { self.s.vec.set_len(new_len) }; + } } - while idx < len { - let ch = unsafe { self.get_unchecked(idx..len).chars().next().unwrap() }; + let len = self.len(); + let mut guard = SetLenOnDrop { s: self, idx: 0, del_bytes: 0 }; + + while guard.idx < len { + let ch = unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap() }; let ch_len = ch.len_utf8(); if !f(ch) { - del_bytes += ch_len; - } else if del_bytes > 0 { + guard.del_bytes += ch_len; + } else if guard.del_bytes > 0 { unsafe { ptr::copy( - self.vec.as_ptr().add(idx), - self.vec.as_mut_ptr().add(idx - del_bytes), + guard.s.vec.as_ptr().add(guard.idx), + guard.s.vec.as_mut_ptr().add(guard.idx - guard.del_bytes), ch_len, ); } } // Point idx to the next char - idx += ch_len; + guard.idx += ch_len; } - unsafe { - self.vec.set_len(len - del_bytes); - } + drop(guard); } /// Inserts a character into this `String` at a byte position. diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index aeae888ddd..1b7e656cef 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2481,8 +2481,11 @@ impl> ToArcSlice for I { Arc::from_iter_exact(self, low) } } else { - // Fall back to normal implementation. - self.collect::>().into() + // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); } } } diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 58a9ae7724..528ee4ff15 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -87,6 +87,9 @@ pub trait Wake { #[stable(feature = "wake_trait", since = "1.51.0")] impl From> for Waker { + /// Use a `Wake`-able type as a `Waker`. + /// + /// No heap allocations or atomic operations are used for this conversion. fn from(waker: Arc) -> Waker { // SAFETY: This is safe because raw_waker safely constructs // a RawWaker from Arc. @@ -96,6 +99,9 @@ impl From> for Waker { #[stable(feature = "wake_trait", since = "1.51.0")] impl From> for RawWaker { + /// Use a `Wake`-able type as a `RawWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. fn from(waker: Arc) -> RawWaker { raw_waker(waker) } diff --git a/library/alloc/src/tests.rs b/library/alloc/src/tests.rs index bddaab0c76..b4741c35c5 100644 --- a/library/alloc/src/tests.rs +++ b/library/alloc/src/tests.rs @@ -49,17 +49,17 @@ fn test_show() { let b = Box::new(Test) as Box; let a_str = format!("{:?}", a); let b_str = format!("{:?}", b); - assert_eq!(a_str, "Any"); - assert_eq!(b_str, "Any"); + assert_eq!(a_str, "Any { .. }"); + assert_eq!(b_str, "Any { .. }"); static EIGHT: usize = 8; static TEST: Test = Test; let a = &EIGHT as &dyn Any; let b = &TEST as &dyn Any; let s = format!("{:?}", a); - assert_eq!(s, "Any"); + assert_eq!(s, "Any { .. }"); let s = format!("{:?}", b); - assert_eq!(s, "Any"); + assert_eq!(s, "Any { .. }"); } #[test] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 135279874b..85c9446689 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -58,7 +58,7 @@ use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; -use core::iter::FromIterator; +use core::iter::{self, FromIterator}; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; @@ -267,12 +267,12 @@ mod spec_extend; /// unspecified, and you should use the appropriate methods to modify these. /// The pointer will never be null, so this type is null-pointer-optimized. /// -/// However, the pointer may not actually point to allocated memory. In particular, +/// However, the pointer might not actually point to allocated memory. In particular, /// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], /// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case -/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// the `Vec` might not report a [`capacity`] of 0*. `Vec` will allocate if and only /// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation /// details are very subtle — if you intend to allocate memory using a `Vec` /// and use it for something else (either to pass to unsafe code, or to build your @@ -347,7 +347,7 @@ mod spec_extend; /// whatever is most efficient or otherwise easy to implement. Do not rely on /// removed data to be erased for security purposes. Even if you drop a `Vec`, its /// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory -/// first, that may not actually happen because the optimizer does not consider +/// first, that might not actually happen because the optimizer does not consider /// this a side-effect that must be preserved. There is one case which we will /// not break, however: using `unsafe` code to write to the excess capacity, /// and then increasing the length to match, is always valid. @@ -410,6 +410,10 @@ impl Vec { /// /// [Capacity and reallocation]: #capacity-and-reallocation /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// /// # Examples /// /// ``` @@ -541,6 +545,10 @@ impl Vec { /// /// [Capacity and reallocation]: #capacity-and-reallocation /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// /// # Examples /// /// ``` @@ -2033,7 +2041,7 @@ impl Vec { /// Safety: changing returned .2 (&mut usize) is considered the same as calling `.set_len(_)`. /// - /// This method is used to have unique access to all vec parts at once in `extend_from_within`. + /// This method provides unique access to all vec parts at once in `extend_from_within`. unsafe fn split_at_spare_mut_with_len( &mut self, ) -> (&mut [T], &mut [MaybeUninit], &mut usize) { @@ -2116,8 +2124,6 @@ impl Vec { /// ## Examples /// /// ``` - /// #![feature(vec_extend_from_within)] - /// /// let mut vec = vec![0, 1, 2, 3, 4]; /// /// vec.extend_from_within(2..); @@ -2129,7 +2135,7 @@ impl Vec { /// vec.extend_from_within(4..8); /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]); /// ``` - #[unstable(feature = "vec_extend_from_within", issue = "81656")] + #[stable(feature = "vec_extend_from_within", since = "1.53.0")] pub fn extend_from_within(&mut self, src: R) where R: RangeBounds, @@ -2268,13 +2274,10 @@ impl ExtendFromWithinSpec for Vec { // - caller guaratees that src is a valid index let to_clone = unsafe { this.get_unchecked(src) }; - to_clone - .iter() - .cloned() - .zip(spare.iter_mut()) - .map(|(src, dst)| dst.write(src)) + iter::zip(to_clone, spare) + .map(|(src, dst)| dst.write(src.clone())) // Note: - // - Element was just initialized with `MaybeUninit::write`, so it's ok to increace len + // - Element was just initialized with `MaybeUninit::write`, so it's ok to increase len // - len is increased after each element to prevent leaks (see issue #82533) .for_each(|_| *len += 1); } @@ -2562,7 +2565,7 @@ impl Vec { /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; /// let mut i = 0; - /// while i != vec.len() { + /// while i < vec.len() { /// if some_predicate(&mut vec[i]) { /// let val = vec.remove(i); /// // your code here @@ -2712,6 +2715,13 @@ impl AsMut<[T]> for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl From<&[T]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]); + /// ``` #[cfg(not(test))] fn from(s: &[T]) -> Vec { s.to_vec() @@ -2724,6 +2734,13 @@ impl From<&[T]> for Vec { #[stable(feature = "vec_from_mut", since = "1.19.0")] impl From<&mut [T]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]); + /// ``` #[cfg(not(test))] fn from(s: &mut [T]) -> Vec { s.to_vec() @@ -2740,6 +2757,13 @@ impl From<[T; N]> for Vec { fn from(s: [T; N]) -> Vec { <[T]>::into_vec(box s) } + /// Allocate a `Vec` and move `s`'s items into it. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); + /// ``` #[cfg(test)] fn from(s: [T; N]) -> Vec { crate::slice::into_vec(box s) @@ -2751,6 +2775,20 @@ impl<'a, T> From> for Vec where [T]: ToOwned>, { + /// Convert a clone-on-write slice into a vector. + /// + /// If `s` already owns a `Vec`, it will be returned directly. + /// If `s` is borrowing a slice, a new `Vec` will be allocated and + /// filled by cloning `s`'s items into it. + /// + /// # Examples + /// + /// ``` + /// # use std::borrow::Cow; + /// let o: Cow<[i32]> = Cow::Owned(vec![1, 2, 3]); + /// let b: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]); + /// assert_eq!(Vec::from(o), Vec::from(b)); + /// ``` fn from(s: Cow<'a, [T]>) -> Vec { s.into_owned() } @@ -2760,9 +2798,17 @@ where #[cfg(not(test))] #[stable(feature = "vec_from_box", since = "1.18.0")] impl From> for Vec { + /// Convert a boxed slice into a vector by transferring ownership of + /// the existing heap allocation. + /// + /// # Examples + /// + /// ``` + /// let b: Box<[i32]> = vec![1, 2, 3].into_boxed_slice(); + /// assert_eq!(Vec::from(b), vec![1, 2, 3]); + /// ``` fn from(s: Box<[T], A>) -> Self { - let len = s.len(); - Self { buf: RawVec::from_box(s), len } + s.into_vec() } } @@ -2770,6 +2816,16 @@ impl From> for Vec { #[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] impl From> for Box<[T], A> { + /// Convert a vector into a boxed slice. + /// + /// If `v` has excess capacity, its items will be moved into a + /// newly-allocated buffer with exactly the right capacity. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Box::from(vec![1, 2, 3]), vec![1, 2, 3].into_boxed_slice()); + /// ``` fn from(v: Vec) -> Self { v.into_boxed_slice() } @@ -2777,6 +2833,13 @@ impl From> for Box<[T], A> { #[stable(feature = "rust1", since = "1.0.0")] impl From<&str> for Vec { + /// Allocate a `Vec` and fill it with a UTF-8 string. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from("123"), vec![b'1', b'2', b'3']); + /// ``` fn from(s: &str) -> Vec { From::from(s.as_bytes()) } diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index 9301f7a518..e857d284d3 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -1,4 +1,4 @@ -use core::iter::{InPlaceIterable, SourceIter}; +use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccess}; use core::mem::{self, ManuallyDrop}; use core::ptr::{self}; @@ -52,16 +52,7 @@ where ) }; - // use try-fold since - // - it vectorizes better for some iterator adapters - // - unlike most internal iteration methods, it only takes a &mut self - // - it lets us thread the write pointer through its innards and get it back in the end - let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; - let sink = iterator - .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) - .unwrap(); - // iteration succeeded, don't drop head - let dst = ManuallyDrop::new(sink).dst; + let len = SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end); let src = unsafe { iterator.as_inner().as_into_iter() }; // check if SourceIter contract was upheld @@ -72,7 +63,7 @@ where // then the source pointer will stay in its initial position and we can't use it as reference if src.ptr != src_ptr { debug_assert!( - dst as *const _ <= src.ptr, + unsafe { dst_buf.add(len) as *const _ } <= src.ptr, "InPlaceIterable contract violation, write pointer advanced beyond read pointer" ); } @@ -82,10 +73,7 @@ where // if the drop panics then we also leak any elements collected into dst_buf src.forget_allocation_drop_remaining(); - let vec = unsafe { - let len = dst.offset_from(dst_buf) as usize; - Vec::from_raw_parts(dst_buf, len, cap) - }; + let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) }; vec } @@ -106,3 +94,52 @@ fn write_in_place_with_drop( Ok(sink) } } + +/// Helper trait to hold specialized implementations of the in-place iterate-collect loop +trait SpecInPlaceCollect: Iterator { + /// Collects an iterator (`self`) into the destination buffer (`dst`) and returns the number of items + /// collected. `end` is the last writable element of the allocation and used for bounds checks. + fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize; +} + +impl SpecInPlaceCollect for I +where + I: Iterator, +{ + #[inline] + default fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + // use try-fold since + // - it vectorizes better for some iterator adapters + // - unlike most internal iteration methods, it only takes a &mut self + // - it lets us thread the write pointer through its innards and get it back in the end + let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + let sink = + self.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(end)).unwrap(); + // iteration succeeded, don't drop head + unsafe { ManuallyDrop::new(sink).dst.offset_from(dst_buf) as usize } + } +} + +impl SpecInPlaceCollect for I +where + I: Iterator + TrustedRandomAccess, +{ + #[inline] + fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + let len = self.size(); + let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + for i in 0..len { + // Safety: InplaceIterable contract guarantees that for every element we read + // one slot in the underlying storage will have been freed up and we can immediately + // write back the result. + unsafe { + 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)); + drop_guard.dst = dst.add(1); + } + } + mem::forget(drop_guard); + len + } +} diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index b6186a7eba..c6f4f22a01 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -26,15 +26,13 @@ where default fn spec_extend(&mut self, iterator: I) { // This is the case for a TrustedLen iterator. let (low, high) = iterator.size_hint(); - if let Some(high_value) = high { + if let Some(additional) = high { debug_assert_eq!( low, - high_value, + additional, "TrustedLen iterator's size hint is not exact: {:?}", (low, high) ); - } - if let Some(additional) = high { self.reserve(additional); unsafe { let mut ptr = self.as_mut_ptr().add(self.len()); @@ -47,7 +45,12 @@ where }); } } else { - self.extend_desugared(iterator) + // Per TrustedLen contract a `None` upper bound means that the iterator length + // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway. + // Since the other branch already panics eagerly (via `reserve()`) we do the same here. + // This avoids additional codegen for a fallback code path which would eventually + // panic anyway. + panic!("capacity overflow"); } } } diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs index ec390c6216..948cf04419 100644 --- a/library/alloc/src/vec/spec_from_iter_nested.rs +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -46,10 +46,13 @@ where fn from_iter(iterator: I) -> Self { let mut vector = match iterator.size_hint() { (_, Some(upper)) => Vec::with_capacity(upper), - _ => Vec::new(), + // TrustedLen contract guarantees that `size_hint() == (_, None)` means that there + // are more than `usize::MAX` elements. + // Since the previous branch would eagerly panic if the capacity is too large + // (via `with_capacity`) we do the same here. + _ => panic!("capacity overflow"), }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs + // reuse extend specialization for TrustedLen vector.spec_extend(iterator); vector } diff --git a/library/alloc/tests/binary_heap.rs b/library/alloc/tests/binary_heap.rs index ce794a9a4a..a7913dcd28 100644 --- a/library/alloc/tests/binary_heap.rs +++ b/library/alloc/tests/binary_heap.rs @@ -386,10 +386,23 @@ fn assert_covariance() { #[test] fn test_retain() { - let mut a = BinaryHeap::from(vec![-10, -5, 1, 2, 4, 13]); - a.retain(|x| x % 2 == 0); + let mut a = BinaryHeap::from(vec![100, 10, 50, 1, 2, 20, 30]); + a.retain(|&x| x != 2); - assert_eq!(a.into_sorted_vec(), [-10, 2, 4]) + // Check that 20 moved into 10's place. + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|_| true); + + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|&x| x < 50); + + assert_eq!(a.clone().into_vec(), [30, 20, 10, 1]); + + a.retain(|_| false); + + assert!(a.is_empty()); } // old binaryheap failed this test diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs index 757fddd241..27ab6c07e4 100644 --- a/library/alloc/tests/fmt.rs +++ b/library/alloc/tests/fmt.rs @@ -68,10 +68,7 @@ fn test_format_macro_interface() { t!(format!("{:?}", 10_usize), "10"); t!(format!("{:?}", "true"), "\"true\""); t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\""); - t!( - format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), - r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""# - ); + t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), r#""foo\n\"bar\"\r\n'baz'\t\\qux\\""#); t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\u{0}bar\u{1}baz\u{7f}qux""#); t!(format!("{:o}", 10_usize), "12"); t!(format!("{:x}", 10_usize), "a"); @@ -154,8 +151,7 @@ fn test_format_macro_interface() { t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6"); // Float edge cases - t!(format!("{}", -0.0), "0"); - t!(format!("{:?}", -0.0), "-0.0"); + t!(format!("{}", -0.0), "-0"); t!(format!("{:?}", 0.0), "0.0"); // sign aware zero padding diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 06874bff44..25a83a0b01 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -14,13 +14,12 @@ #![feature(binary_heap_drain_sorted)] #![feature(slice_ptr_get)] #![feature(binary_heap_retain)] +#![feature(binary_heap_as_slice)] #![feature(inplace_iteration)] #![feature(iter_map_while)] -#![feature(int_bits_const)] #![feature(vecdeque_binary_search)] #![feature(slice_group_by)] #![feature(slice_partition_dedup)] -#![feature(vec_extend_from_within)] #![feature(vec_spare_capacity)] #![feature(string_remove_matches)] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index b926c697d5..ad69234403 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1002,11 +1002,10 @@ fn test_from_iter_specialization_with_iterator_adapters() { .zip(std::iter::repeat(1usize)) .map(|(a, b)| a + b) .map_while(Option::Some) - .peekable() .skip(1) - .map(|e| std::num::NonZeroUsize::new(e)); + .map(|e| if e != usize::MAX { Ok(std::num::NonZeroUsize::new(e)) } else { Err(()) }); assert_in_place_trait(&iter); - let sink = iter.collect::>(); + let sink = iter.collect::, _>>().unwrap(); let sinkptr = sink.as_ptr(); assert_eq!(srcptr, sinkptr as *const usize); } @@ -1078,14 +1077,35 @@ fn test_from_iter_specialization_panic_during_drop_leaks() { } } + let mut to_free: *mut Droppable = core::ptr::null_mut(); + let mut cap = 0; + let _ = std::panic::catch_unwind(AssertUnwindSafe(|| { - let v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop]; + let mut v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop]; + to_free = v.as_mut_ptr(); + cap = v.capacity(); let _ = v.into_iter().take(0).collect::>(); })); assert_eq!(unsafe { DROP_COUNTER }, 1); + // clean up the leak to keep miri happy + unsafe { + drop(Vec::from_raw_parts(to_free, 0, cap)); + } } +// regression test for issue #85322. Peekable previously implemented InPlaceIterable, +// but due to an interaction with IntoIter's current Clone implementation it failed to uphold +// the contract. +#[test] +fn test_collect_after_iterator_clone() { + let v = vec![0; 5]; + let mut i = v.into_iter().map(|i| i + 1).peekable(); + i.peek(); + let v = i.clone().collect::>(); + assert_eq!(v, [1, 1, 1, 1, 1]); + assert!(v.len() <= v.capacity()); +} #[test] fn test_cow_from() { let borrowed: &[_] = &["borrowed", "(slice)"]; diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index 0919b1325b..d7140cf975 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1699,6 +1699,24 @@ fn test_binary_search_by_key() { assert_eq!(deque.binary_search_by_key(&4, |&(v,)| v), Err(3)); } +#[test] +fn test_partition_point() { + // Contiguous (front only) search: + let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into(); + assert!(deque.as_slices().1.is_empty()); + assert_eq!(deque.partition_point(|&v| v <= 3), 3); + + // Split search (both front & back non-empty): + let mut deque: VecDeque<_> = vec![5, 6].into(); + deque.push_front(3); + deque.push_front(2); + deque.push_front(1); + deque.push_back(10); + assert!(!deque.as_slices().0.is_empty()); + assert!(!deque.as_slices().1.is_empty()); + assert_eq!(deque.partition_point(|&v| v <= 5), 4); +} + #[test] fn test_zero_sized_push() { const N: usize = 8; diff --git a/library/backtrace/.github/workflows/main.yml b/library/backtrace/.github/workflows/main.yml index d6e39b1c33..08899a0109 100644 --- a/library/backtrace/.github/workflows/main.yml +++ b/library/backtrace/.github/workflows/main.yml @@ -14,36 +14,26 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - thing: [stable, beta, nightly, macos, macos-nightly, windows-msvc64, windows-msvc32, windows-gnu64, windows-gnu32] include: - - thing: stable - os: ubuntu-latest + - os: ubuntu-latest rust: stable - - thing: beta - os: ubuntu-latest + - os: ubuntu-latest rust: beta - - thing: nightly - os: ubuntu-latest + - os: ubuntu-latest rust: nightly - - thing: macos - os: macos-latest + - os: macos-latest rust: stable - - thing: macos-nightly - os: macos-latest + - os: macos-latest rust: nightly # Note that these are on nightly due to rust-lang/rust#63700 not being # on stable yet - - thing: windows-msvc64 - os: windows-latest + - os: windows-latest rust: stable-x86_64-msvc - - thing: windows-msvc32 - os: windows-latest + - os: windows-latest rust: stable-i686-msvc - - thing: windows-gnu64 - os: windows-latest + - os: windows-latest rust: stable-x86_64-gnu - - thing: windows-gnu32 - os: windows-latest + - os: windows-latest rust: stable-i686-gnu steps: - uses: actions/checkout@v1 @@ -54,18 +44,28 @@ jobs: shell: bash - run: echo RUSTFLAGS=-Dwarnings >> $GITHUB_ENV shell: bash + # full fidelity of backtraces on 32-bit msvc requires frame pointers, so # enable that for our tests - name: Force frame pointers run: echo RUSTFLAGS="-Cforce-frame-pointers $RUSTFLAGS" >> $GITHUB_ENV shell: bash - if: matrix.thing == 'windows-msvc32' + if: matrix.rust == 'stable-i686-msvc' + + # Force packed debuginfo on macOS because libbacktrace only works with + # packed debuginfo. We specifically test later that both packed and + # unpacked work. + - run: | + echo CARGO_PROFILE_DEV_SPLIT_DEBUGINFO=packed >> $GITHUB_ENV + echo CARGO_PROFILE_TEST_SPLIT_DEBUGINFO=packed >> $GITHUB_ENV + if: matrix.os == 'macos-latest' + - run: cargo build --manifest-path crates/backtrace-sys/Cargo.toml - run: cargo build - run: cargo test - run: cargo test --features "gimli-symbolize" - run: cargo test --features "libbacktrace" - - run: cargo test --features "libbacktrace gimli-symbolize" + - run: cargo check --features "libbacktrace gimli-symbolize" - run: cargo test --features "serialize-rustc" - run: cargo test --features "serialize-serde" - run: cargo test --features "verify-winapi" @@ -83,12 +83,41 @@ jobs: - run: cargo test --features gimli-symbolize --manifest-path crates/without_debuginfo/Cargo.toml - run: cargo test --manifest-path crates/line-tables-only/Cargo.toml --features libbacktrace - run: cargo test --manifest-path crates/line-tables-only/Cargo.toml --features gimli-symbolize - - run: RUSTFLAGS="-C link-arg=-Wl,--compress-debug-sections=zlib-gabi" cargo test --features gimli-symbolize + + # Test that if debuginfo is compressed gimli still works + - run: cargo test if: contains(matrix.os, 'ubuntu') - - run: RUSTFLAGS="-C link-arg=-Wl,--compress-debug-sections=zlib-gnu" cargo test --features gimli-symbolize + env: + RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zlib-gabi" + - run: cargo test if: contains(matrix.os, 'ubuntu') - - run: cargo clean && RUSTFLAGS="-Z run-dsymutil=no" cargo test --features gimli-symbolize - if: matrix.thing == 'macos-nightly' + env: + RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zlib-gnu" + + # Test that, on macOS, packed/unpacked debuginfo both work + - run: cargo clean && cargo test + # Test that, on macOS, packed/unpacked debuginfo both work + if: matrix.os == 'macos-latest' + env: + CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: unpacked + CARGO_PROFILE_TEST_SPLIT_DEBUGINFO: unpacked + - run: cargo clean && cargo test + if: matrix.os == 'macos-latest' + env: + CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: packed + CARGO_PROFILE_TEST_SPLIT_DEBUGINFO: packed + + # Test that, on Linux, packed/unpacked debuginfo both work + - run: cargo clean && cargo test + if: matrix.rust == 'nightly' + env: + RUSTFLAGS: "-C split-debuginfo=unpacked -Zunstable-options" + - run: cargo clean && cargo test + if: matrix.rust == 'nightly' + env: + RUSTFLAGS: "-C split-debuginfo=packed -Zunstable-options" + + # Test that including as a submodule will still work - run: cargo build --manifest-path crates/as-if-std/Cargo.toml windows_arm64: @@ -112,9 +141,6 @@ jobs: runs-on: macos-latest strategy: matrix: - target: - - aarch64-apple-ios - - x86_64-apple-ios include: - target: aarch64-apple-ios sdk: iphoneos @@ -181,7 +207,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - target: [wasm32-unknown-unknown, wasm32-wasi, x86_64-fuchsia, x86_64-fortanix-unknown-sgx] + target: + - wasm32-unknown-unknown + - wasm32-wasi + - x86_64-fuchsia + - x86_64-fortanix-unknown-sgx + - x86_64-unknown-illumos steps: - uses: actions/checkout@v1 with: @@ -192,6 +223,7 @@ jobs: - run: echo RUSTFLAGS=-Dwarnings >> $GITHUB_ENV shell: bash - run: cargo build --target ${{ matrix.target }} + - run: cargo build --manifest-path crates/as-if-std/Cargo.toml --target ${{ matrix.target }} msrv: name: MSRV @@ -201,7 +233,7 @@ jobs: with: submodules: true - name: Install Rust - run: rustup update 1.40.0 && rustup default 1.40.0 + run: rustup update 1.42.0 && rustup default 1.42.0 - run: cargo build miri: diff --git a/library/backtrace/Cargo.toml b/library/backtrace/Cargo.toml index f1b6b15d7f..71db617fa6 100644 --- a/library/backtrace/Cargo.toml +++ b/library/backtrace/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "backtrace" -version = "0.3.55" +version = "0.3.57" authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" @@ -22,7 +22,7 @@ exclude = ['crates/without_debuginfo', 'crates/macos_frames_test', 'crates/line- cfg-if = "1.0" rustc-demangle = "0.1.4" backtrace-sys = { path = "crates/backtrace-sys", version = "0.1.35", optional = true, default_features = false } -libc = { version = "0.2.45", default-features = false } +libc = { version = "0.2.87", default-features = false } # Optionally enable the ability to serialize a `Backtrace`, controlled through # the `serialize-*` features below. @@ -35,10 +35,10 @@ cpp_demangle = { default-features = false, version = "0.3.0", optional = true } # Optional dependencies enabled through the `gimli-symbolize` feature, do not # use these features directly. -addr2line = { version = "0.14.0", optional = true, default-features = false } +addr2line = { version = "0.14.1", optional = true, default-features = false } miniz_oxide = { version = "0.4.0", optional = true, default-features = false } [dependencies.object] -version = "0.22" +version = "0.23" optional = true default-features = false features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] diff --git a/library/backtrace/README.md b/library/backtrace/README.md index c685d96837..cd80a697cb 100644 --- a/library/backtrace/README.md +++ b/library/backtrace/README.md @@ -60,9 +60,9 @@ fn main() { 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) + https://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) + https://opensource.org/licenses/MIT) at your option. diff --git a/library/backtrace/crates/as-if-std/Cargo.toml b/library/backtrace/crates/as-if-std/Cargo.toml index 5871a882f4..b7cb2a8301 100644 --- a/library/backtrace/crates/as-if-std/Cargo.toml +++ b/library/backtrace/crates/as-if-std/Cargo.toml @@ -15,7 +15,7 @@ bench = false cfg-if = "1.0" rustc-demangle = "0.1.4" libc = { version = "0.2.45", default-features = false } -addr2line = { version = "0.14.0", default-features = false } +addr2line = { version = "0.14.1", default-features = false } miniz_oxide = { version = "0.4.0", default-features = false } [dependencies.object] diff --git a/library/backtrace/crates/backtrace-sys/Cargo.toml b/library/backtrace/crates/backtrace-sys/Cargo.toml index c8e414c8d3..f337ebd80e 100644 --- a/library/backtrace/crates/backtrace-sys/Cargo.toml +++ b/library/backtrace/crates/backtrace-sys/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.37" authors = ["Alex Crichton "] build = "build.rs" license = "MIT/Apache-2.0" -repository = "https://github.com/alexcrichton/backtrace-rs" -homepage = "https://github.com/alexcrichton/backtrace-rs" -documentation = "http://alexcrichton.com/backtrace-rs" +repository = "https://github.com/rust-lang/backtrace-rs" +homepage = "https://github.com/rust-lang/backtrace-rs" +documentation = "https://docs.rs/backtrace-sys" description = """ Bindings to the libbacktrace gcc library """ diff --git a/library/backtrace/crates/macos_frames_test/tests/main.rs b/library/backtrace/crates/macos_frames_test/tests/main.rs index 1d28f20221..f0e905b24d 100644 --- a/library/backtrace/crates/macos_frames_test/tests/main.rs +++ b/library/backtrace/crates/macos_frames_test/tests/main.rs @@ -8,7 +8,7 @@ #[test] #[cfg(target_os = "macos")] fn backtrace_no_dsym() { - use std::{env, fs, panic}; + use std::{env, fs}; // Find our dSYM and replace the DWARF binary with an empty file let mut dsym_path = env::current_exe().unwrap(); diff --git a/library/backtrace/src/lib.rs b/library/backtrace/src/lib.rs index 9d4153bb9c..89081ffbe5 100644 --- a/library/backtrace/src/lib.rs +++ b/library/backtrace/src/lib.rs @@ -40,6 +40,51 @@ //! } //! # } //! ``` +//! +//! # Backtrace accuracy +//! +//! This crate implements best-effort attempts to get the native backtrace. This +//! is not always guaranteed to work, and some platforms don't return any +//! backtrace at all. If your application requires accurate backtraces then it's +//! recommended to closely evaluate this crate to see whether it's suitable +//! for your use case on your target platforms. +//! +//! Even on supported platforms, there's a number of reasons that backtraces may +//! be less-than-accurate, including but not limited to: +//! +//! * Unwind information may not be available. This crate primarily implements +//! backtraces by unwinding the stack, but not all functions may have +//! unwinding information (e.g. DWARF unwinding information). +//! +//! * Rust code may be compiled without unwinding information for some +//! functions. This can also happen for Rust code compiled with +//! `-Cpanic=abort`. You can remedy this, however, with +//! `-Cforce-unwind-tables` as a compiler option. +//! +//! * Unwind information may be inaccurate or corrupt. In the worst case +//! inaccurate unwind information can lead this library to segfault. In the +//! best case inaccurate information will result in a truncated stack trace. +//! +//! * Backtraces may not report filenames/line numbers correctly due to missing +//! or corrupt debug information. This won't lead to segfaults unlike corrupt +//! unwinding information, but missing or malformed debug information will +//! mean that filenames and line numbers will not be available. This may be +//! because debug information wasn't generated by the compiler, or it's just +//! missing on the filesystem. +//! +//! * Not all platforms are supported. For example there's no way to get a +//! backtrace on WebAssembly at the moment. +//! +//! * Crate features may be disabled. Currently this crate supports using Gimli +//! libbacktrace on non-Windows platforms for reading debuginfo for +//! backtraces. If both crate features are disabled, however, then these +//! platforms will generate a backtrace but be unable to generate symbols for +//! it. +//! +//! In most standard workflows for most standard platforms you generally don't +//! need to worry about these caveats. We'll try to fix ones where we can over +//! time, but otherwise it's important to be aware of the limitations of +//! unwinding-based backtraces! #![doc(html_root_url = "https://docs.rs/backtrace")] #![deny(missing_docs)] @@ -53,6 +98,8 @@ // irrelevant as this crate is developed out-of-tree. #![cfg_attr(backtrace_in_libstd, allow(warnings))] #![cfg_attr(not(feature = "std"), allow(dead_code))] +// We know this is deprecated, it's only here for back-compat reasons. +#![cfg_attr(feature = "rustc-serialize", allow(deprecated))] #[cfg(feature = "std")] #[macro_use] diff --git a/library/backtrace/src/symbolize/gimli.rs b/library/backtrace/src/symbolize/gimli.rs index 2330c4f0bc..bcd362cebc 100644 --- a/library/backtrace/src/symbolize/gimli.rs +++ b/library/backtrace/src/symbolize/gimli.rs @@ -34,11 +34,13 @@ cfg_if::cfg_if! { target_os = "android", target_os = "freebsd", target_os = "fuchsia", + target_os = "haiku", target_os = "ios", target_os = "linux", target_os = "macos", target_os = "openbsd", target_os = "solaris", + target_os = "illumos", ))] { #[path = "gimli/mmap_unix.rs"] mod mmap; @@ -116,341 +118,55 @@ fn mmap(path: &Path) -> Option { cfg_if::cfg_if! { if #[cfg(windows)] { - use core::mem::MaybeUninit; - use super::super::windows::*; - use mystd::os::windows::prelude::*; - use alloc::vec; - mod coff; use self::coff::Object; - - // For loading native libraries on Windows, see some discussion on - // rust-lang/rust#71060 for the various strategies here. - fn native_libraries() -> Vec { - let mut ret = Vec::new(); - unsafe { add_loaded_images(&mut ret); } - return ret; - } - - unsafe fn add_loaded_images(ret: &mut Vec) { - let snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); - if snap == INVALID_HANDLE_VALUE { - return; - } - - let mut me = MaybeUninit::::zeroed().assume_init(); - me.dwSize = mem::size_of_val(&me) as DWORD; - if Module32FirstW(snap, &mut me) == TRUE { - loop { - if let Some(lib) = load_library(&me) { - ret.push(lib); - } - - if Module32NextW(snap, &mut me) != TRUE { - break; - } - } - - } - - CloseHandle(snap); - } - - unsafe fn load_library(me: &MODULEENTRY32W) -> Option { - let pos = me - .szExePath - .iter() - .position(|i| *i == 0) - .unwrap_or(me.szExePath.len()); - let name = OsString::from_wide(&me.szExePath[..pos]); - - // MinGW libraries currently don't support ASLR - // (rust-lang/rust#16514), but DLLs can still be relocated around in - // the address space. It appears that addresses in debug info are - // all as-if this library was loaded at its "image base", which is a - // field in its COFF file headers. Since this is what debuginfo - // seems to list we parse the symbol table and store addresses as if - // the library was loaded at "image base" as well. - // - // The library may not be loaded at "image base", however. - // (presumably something else may be loaded there?) This is where - // the `bias` field comes into play, and we need to figure out the - // value of `bias` here. Unfortunately though it's not clear how to - // acquire this from a loaded module. What we do have, however, is - // the actual load address (`modBaseAddr`). - // - // As a bit of a cop-out for now we mmap the file, read the file - // header information, then drop the mmap. This is wasteful because - // we'll probably reopen the mmap later, but this should work well - // enough for now. - // - // Once we have the `image_base` (desired load location) and the - // `base_addr` (actual load location) we can fill in the `bias` - // (difference between the actual and desired) and then the stated - // address of each segment is the `image_base` since that's what the - // file says. - // - // For now it appears that unlike ELF/MachO we can make do with one - // segment per library, using `modBaseSize` as the whole size. - let mmap = mmap(name.as_ref())?; - let image_base = coff::get_image_base(&mmap)?; - let base_addr = me.modBaseAddr as usize; - Some(Library { - name, - bias: base_addr.wrapping_sub(image_base), - segments: vec![LibrarySegment { - stated_virtual_memory_address: image_base, - len: me.modBaseSize as usize, - }], - }) - } } else if #[cfg(any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", ))] { - // macOS uses the Mach-O file format and uses DYLD-specific APIs to - // load a list of native libraries that are part of the application. - - use mystd::os::unix::prelude::*; - use mystd::ffi::{OsStr, CStr}; - mod macho; use self::macho::Object; - - #[allow(deprecated)] - fn native_libraries() -> Vec { - let mut ret = Vec::new(); - let images = unsafe { libc::_dyld_image_count() }; - for i in 0..images { - ret.extend(native_library(i)); - } - return ret; - } - - #[allow(deprecated)] - fn native_library(i: u32) -> Option { - use object::macho; - use object::read::macho::{MachHeader, Segment}; - use object::{Bytes, NativeEndian}; - - // Fetch the name of this library which corresponds to the path of - // where to load it as well. - let name = unsafe { - let name = libc::_dyld_get_image_name(i); - if name.is_null() { - return None; - } - CStr::from_ptr(name) - }; - - // Load the image header of this library and delegate to `object` to - // parse all the load commands so we can figure out all the segments - // involved here. - let (mut load_commands, endian) = unsafe { - let header = libc::_dyld_get_image_header(i); - if header.is_null() { - return None; - } - match (*header).magic { - macho::MH_MAGIC => { - let endian = NativeEndian; - let header = &*(header as *const macho::MachHeader32); - let data = core::slice::from_raw_parts( - header as *const _ as *const u8, - mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize - ); - (header.load_commands(endian, Bytes(data)).ok()?, endian) - } - macho::MH_MAGIC_64 => { - let endian = NativeEndian; - let header = &*(header as *const macho::MachHeader64); - let data = core::slice::from_raw_parts( - header as *const _ as *const u8, - mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize - ); - (header.load_commands(endian, Bytes(data)).ok()?, endian) - } - _ => return None, - } - }; - - // Iterate over the segments and register known regions for segments - // that we find. Additionally record information bout text segments - // for processing later, see comments below. - let mut segments = Vec::new(); - let mut first_text = 0; - let mut text_fileoff_zero = false; - while let Some(cmd) = load_commands.next().ok()? { - if let Some((seg, _)) = cmd.segment_32().ok()? { - if seg.name() == b"__TEXT" { - first_text = segments.len(); - if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { - text_fileoff_zero = true; - } - } - segments.push(LibrarySegment { - len: seg.vmsize(endian).try_into().ok()?, - stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, - }); - } - if let Some((seg, _)) = cmd.segment_64().ok()? { - if seg.name() == b"__TEXT" { - first_text = segments.len(); - if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { - text_fileoff_zero = true; - } - } - segments.push(LibrarySegment { - len: seg.vmsize(endian).try_into().ok()?, - stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, - }); - } - } - - // Determine the "slide" for this library which ends up being the - // bias we use to figure out where in memory objects are loaded. - // This is a bit of a weird computation though and is the result of - // trying a few things in the wild and seeing what sticks. - // - // The general idea is that the `bias` plus a segment's - // `stated_virtual_memory_address` is going to be where in the - // actual address space the segment resides. The other thing we rely - // on though is that a real address minus the `bias` is the index to - // look up in the symbol table and debuginfo. - // - // It turns out, though, that for system loaded libraries these - // calculations are incorrect. For native executables, however, it - // appears correct. Lifting some logic from LLDB's source it has - // some special-casing for the first `__TEXT` section loaded from - // file offset 0 with a nonzero size. For whatever reason when this - // is present it appears to mean that the symbol table is relative - // to just the vmaddr slide for the library. If it's *not* present - // then the symbol table is relative to the the vmaddr slide plus - // the segment's stated address. - // - // To handle this situation if we *don't* find a text section at - // file offset zero then we increase the bias by the first text - // sections's stated address and decrease all stated addresses by - // that amount as well. That way the symbol table is always appears - // relative to the library's bias amount. This appears to have the - // right results for symbolizing via the symbol table. - // - // Honestly I'm not entirely sure whether this is right or if - // there's something else that should indicate how to do this. For - // now though this seems to work well enough (?) and we should - // always be able to tweak this over time if necessary. - // - // For some more information see #318 - let mut slide = unsafe { libc::_dyld_get_image_vmaddr_slide(i) as usize }; - if !text_fileoff_zero { - let adjust = segments[first_text].stated_virtual_memory_address; - for segment in segments.iter_mut() { - segment.stated_virtual_memory_address -= adjust; - } - slide += adjust; - } - - Some(Library { - name: OsStr::from_bytes(name.to_bytes()).to_owned(), - segments, - bias: slide, - }) - } - } else if #[cfg(any( - target_os = "linux", - target_os = "fuchsia", - ))] { - // Other Unix (e.g. Linux) platforms use ELF as an object file format - // and typically implement an API called `dl_iterate_phdr` to load - // native libraries. - - use mystd::os::unix::prelude::*; - use mystd::ffi::{OsStr, CStr}; - + } else { mod elf; use self::elf::Object; + } +} - fn native_libraries() -> Vec { - let mut ret = Vec::new(); - unsafe { - libc::dl_iterate_phdr(Some(callback), &mut ret as *mut Vec<_> as *mut _); - } - return ret; - } - - // `info` should be a valid pointers. - // `vec` should be a valid pointer to a `std::Vec`. - unsafe extern "C" fn callback( - info: *mut libc::dl_phdr_info, - _size: libc::size_t, - vec: *mut libc::c_void, - ) -> libc::c_int { - let info = &*info; - let libs = &mut *(vec as *mut Vec); - let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0; - let name = if is_main_prog { - if libs.is_empty() { - mystd::env::current_exe().map(|e| e.into()).unwrap_or_default() - } else { - OsString::new() - } - } else { - let bytes = CStr::from_ptr(info.dlpi_name).to_bytes(); - OsStr::from_bytes(bytes).to_owned() - }; - let headers = core::slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize); - libs.push(Library { - name, - segments: headers - .iter() - .map(|header| LibrarySegment { - len: (*header).p_memsz as usize, - stated_virtual_memory_address: (*header).p_vaddr as usize, - }) - .collect(), - bias: info.dlpi_addr as usize, - }); - 0 - } +cfg_if::cfg_if! { + if #[cfg(windows)] { + mod libs_windows; + use libs_windows::native_libraries; + } else if #[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", + ))] { + mod libs_macos; + use libs_macos::native_libraries; + } else if #[cfg(target_os = "illumos")] { + mod libs_illumos; + use libs_illumos::native_libraries; + } else if #[cfg(all( + any( + target_os = "linux", + target_os = "fuchsia", + target_os = "freebsd", + ), + not(target_env = "uclibc"), + ))] { + mod libs_dl_iterate_phdr; + use libs_dl_iterate_phdr::native_libraries; } else if #[cfg(target_env = "libnx")] { - // DevkitA64 doesn't natively support debug info, but the build system will place debug - // info at the path `romfs:/debug_info.elf`. - mod elf; - use self::elf::Object; - - fn native_libraries() -> Vec { - extern "C" { - static __start__: u8; - } - - let bias = unsafe { &__start__ } as *const u8 as usize; - - let mut ret = Vec::new(); - let mut segments = Vec::new(); - segments.push(LibrarySegment { - stated_virtual_memory_address: 0, - len: usize::max_value() - bias, - }); - - let path = "romfs:/debug_info.elf"; - ret.push(Library { - name: path.into(), - segments, - bias, - }); - - ret - } + mod libs_libnx; + use libs_libnx::native_libraries; + } else if #[cfg(target_os = "haiku")] { + mod libs_haiku; + use libs_haiku::native_libraries; } else { - // Everything else should use ELF, but doesn't know how to load native - // libraries. - - use mystd::os::unix::prelude::*; - mod elf; - use self::elf::Object; - + // Everything else should doesn't know how to load native libraries. fn native_libraries() -> Vec { Vec::new() } @@ -618,10 +334,14 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol)) if let Ok(mut frames) = cx.dwarf.find_frames(addr as u64) { while let Ok(Some(frame)) = frames.next() { any_frames = true; + let name = match frame.function { + Some(f) => Some(f.name.slice()), + None => cx.object.search_symtab(addr as u64), + }; call(Symbol::Frame { addr: addr as *mut c_void, location: frame.location, - name: frame.function.map(|f| f.name.slice()), + name, }); } } diff --git a/library/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs b/library/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs new file mode 100644 index 0000000000..a011e60801 --- /dev/null +++ b/library/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs @@ -0,0 +1,53 @@ +// Other Unix (e.g. Linux) platforms use ELF as an object file format +// and typically implement an API called `dl_iterate_phdr` to load +// native libraries. + +use super::mystd::borrow::ToOwned; +use super::mystd::env; +use super::mystd::ffi::{CStr, OsStr}; +use super::mystd::os::unix::prelude::*; +use super::{Library, LibrarySegment, OsString, Vec}; +use core::slice; + +pub(super) fn native_libraries() -> Vec { + let mut ret = Vec::new(); + unsafe { + libc::dl_iterate_phdr(Some(callback), &mut ret as *mut Vec<_> as *mut _); + } + return ret; +} + +// `info` should be a valid pointers. +// `vec` should be a valid pointer to a `std::Vec`. +unsafe extern "C" fn callback( + info: *mut libc::dl_phdr_info, + _size: libc::size_t, + vec: *mut libc::c_void, +) -> libc::c_int { + let info = &*info; + let libs = &mut *(vec as *mut Vec); + let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0; + let name = if is_main_prog { + if libs.is_empty() { + env::current_exe().map(|e| e.into()).unwrap_or_default() + } else { + OsString::new() + } + } else { + let bytes = CStr::from_ptr(info.dlpi_name).to_bytes(); + OsStr::from_bytes(bytes).to_owned() + }; + let headers = slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize); + libs.push(Library { + name, + segments: headers + .iter() + .map(|header| LibrarySegment { + len: (*header).p_memsz as usize, + stated_virtual_memory_address: (*header).p_vaddr as usize, + }) + .collect(), + bias: info.dlpi_addr as usize, + }); + 0 +} diff --git a/library/backtrace/src/symbolize/gimli/libs_haiku.rs b/library/backtrace/src/symbolize/gimli/libs_haiku.rs new file mode 100644 index 0000000000..f80686a168 --- /dev/null +++ b/library/backtrace/src/symbolize/gimli/libs_haiku.rs @@ -0,0 +1,47 @@ +// Haiku implements the image_info struct and the get_next_image_info() +// functions to iterate through the loaded executable images. The +// image_info struct contains a pointer to the start of the .text +// section within the virtual address space, as well as the size of +// that section. All the read-only segments of the ELF-binary are in +// that part of the address space. + +use super::mystd::borrow::ToOwned; +use super::mystd::ffi::{CStr, OsStr}; +use super::mystd::os::unix::prelude::*; +use super::{Library, LibrarySegment, Vec}; + +pub(super) fn native_libraries() -> Vec { + let mut libraries: Vec = Vec::new(); + + unsafe { + let mut info = mem::MaybeUninit::::zeroed(); + let mut cookie: i32 = 0; + // Load the first image to get a valid info struct + let mut status = + libc::get_next_image_info(libc::B_CURRENT_TEAM, &mut cookie, info.as_mut_ptr()); + if status != libc::B_OK { + return libraries; + } + let mut info = info.assume_init(); + + while status == libc::B_OK { + let mut segments = Vec::new(); + segments.push(LibrarySegment { + stated_virtual_memory_address: 0, + len: info.text_size as usize, + }); + + let bytes = CStr::from_ptr(info.name.as_ptr()).to_bytes(); + let name = OsStr::from_bytes(bytes).to_owned(); + libraries.push(Library { + name: name, + segments: segments, + bias: info.text as usize, + }); + + status = libc::get_next_image_info(libc::B_CURRENT_TEAM, &mut cookie, &mut info); + } + } + + libraries +} diff --git a/library/backtrace/src/symbolize/gimli/libs_illumos.rs b/library/backtrace/src/symbolize/gimli/libs_illumos.rs new file mode 100644 index 0000000000..e64975e0cc --- /dev/null +++ b/library/backtrace/src/symbolize/gimli/libs_illumos.rs @@ -0,0 +1,99 @@ +use super::mystd::borrow::ToOwned; +use super::mystd::ffi::{CStr, OsStr}; +use super::mystd::os::unix::prelude::*; +use super::{Library, LibrarySegment, Vec}; +use core::mem; +use object::NativeEndian; + +#[cfg(target_pointer_width = "64")] +use object::elf::{FileHeader64 as FileHeader, ProgramHeader64 as ProgramHeader}; + +type EHdr = FileHeader; +type PHdr = ProgramHeader; + +#[repr(C)] +struct LinkMap { + l_addr: libc::c_ulong, + l_name: *const libc::c_char, + l_ld: *const libc::c_void, + l_next: *const LinkMap, + l_prev: *const LinkMap, + l_refname: *const libc::c_char, +} + +const RTLD_SELF: *const libc::c_void = -3isize as *const libc::c_void; +const RTLD_DI_LINKMAP: libc::c_int = 2; + +extern "C" { + fn dlinfo( + handle: *const libc::c_void, + request: libc::c_int, + p: *mut libc::c_void, + ) -> libc::c_int; +} + +pub(super) fn native_libraries() -> Vec { + let mut libs = Vec::new(); + + // Request the current link map from the runtime linker: + let map = unsafe { + let mut map: *const LinkMap = mem::zeroed(); + if dlinfo( + RTLD_SELF, + RTLD_DI_LINKMAP, + (&mut map) as *mut *const LinkMap as *mut libc::c_void, + ) != 0 + { + return libs; + } + map + }; + + // Each entry in the link map represents a loaded object: + let mut l = map; + while !l.is_null() { + // Fetch the fully qualified path of the loaded object: + let bytes = unsafe { CStr::from_ptr((*l).l_name) }.to_bytes(); + let name = OsStr::from_bytes(bytes).to_owned(); + + // The base address of the object loaded into memory: + let addr = unsafe { (*l).l_addr }; + + // Use the ELF header for this object to locate the program + // header: + let e: *const EHdr = unsafe { (*l).l_addr as *const EHdr }; + let phoff = unsafe { (*e).e_phoff }.get(NativeEndian); + let phnum = unsafe { (*e).e_phnum }.get(NativeEndian); + let etype = unsafe { (*e).e_type }.get(NativeEndian); + + let phdr: *const PHdr = (addr + phoff) as *const PHdr; + let phdr = unsafe { core::slice::from_raw_parts(phdr, phnum as usize) }; + + libs.push(Library { + name, + segments: phdr + .iter() + .map(|p| { + let memsz = p.p_memsz.get(NativeEndian); + let vaddr = p.p_vaddr.get(NativeEndian); + LibrarySegment { + len: memsz as usize, + stated_virtual_memory_address: vaddr as usize, + } + }) + .collect(), + bias: if etype == object::elf::ET_EXEC { + // Program header addresses for the base executable are + // already absolute. + 0 + } else { + // Other addresses are relative to the object base. + addr as usize + }, + }); + + l = unsafe { (*l).l_next }; + } + + libs +} diff --git a/library/backtrace/src/symbolize/gimli/libs_libnx.rs b/library/backtrace/src/symbolize/gimli/libs_libnx.rs new file mode 100644 index 0000000000..93b5ba17ea --- /dev/null +++ b/library/backtrace/src/symbolize/gimli/libs_libnx.rs @@ -0,0 +1,27 @@ +use super::{Library, LibrarySegment, Vec}; + +// DevkitA64 doesn't natively support debug info, but the build system will +// place debug info at the path `romfs:/debug_info.elf`. +pub(super) fn native_libraries() -> Vec { + extern "C" { + static __start__: u8; + } + + let bias = unsafe { &__start__ } as *const u8 as usize; + + let mut ret = Vec::new(); + let mut segments = Vec::new(); + segments.push(LibrarySegment { + stated_virtual_memory_address: 0, + len: usize::max_value() - bias, + }); + + let path = "romfs:/debug_info.elf"; + ret.push(Library { + name: path.into(), + segments, + bias, + }); + + ret +} diff --git a/library/backtrace/src/symbolize/gimli/libs_macos.rs b/library/backtrace/src/symbolize/gimli/libs_macos.rs new file mode 100644 index 0000000000..2b6b6716f2 --- /dev/null +++ b/library/backtrace/src/symbolize/gimli/libs_macos.rs @@ -0,0 +1,146 @@ +#![allow(deprecated)] + +use super::mystd::ffi::{CStr, OsStr}; +use super::mystd::os::unix::prelude::*; +use super::mystd::prelude::v1::*; +use super::{Library, LibrarySegment}; +use core::convert::TryInto; +use core::mem; + +pub(super) fn native_libraries() -> Vec { + let mut ret = Vec::new(); + let images = unsafe { libc::_dyld_image_count() }; + for i in 0..images { + ret.extend(native_library(i)); + } + return ret; +} + +fn native_library(i: u32) -> Option { + use object::macho; + use object::read::macho::{MachHeader, Segment}; + use object::{Bytes, NativeEndian}; + + // Fetch the name of this library which corresponds to the path of + // where to load it as well. + let name = unsafe { + let name = libc::_dyld_get_image_name(i); + if name.is_null() { + return None; + } + CStr::from_ptr(name) + }; + + // Load the image header of this library and delegate to `object` to + // parse all the load commands so we can figure out all the segments + // involved here. + let (mut load_commands, endian) = unsafe { + let header = libc::_dyld_get_image_header(i); + if header.is_null() { + return None; + } + match (*header).magic { + macho::MH_MAGIC => { + let endian = NativeEndian; + let header = &*(header as *const macho::MachHeader32); + let data = core::slice::from_raw_parts( + header as *const _ as *const u8, + mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize, + ); + (header.load_commands(endian, Bytes(data)).ok()?, endian) + } + macho::MH_MAGIC_64 => { + let endian = NativeEndian; + let header = &*(header as *const macho::MachHeader64); + let data = core::slice::from_raw_parts( + header as *const _ as *const u8, + mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize, + ); + (header.load_commands(endian, Bytes(data)).ok()?, endian) + } + _ => return None, + } + }; + + // Iterate over the segments and register known regions for segments + // that we find. Additionally record information bout text segments + // for processing later, see comments below. + let mut segments = Vec::new(); + let mut first_text = 0; + let mut text_fileoff_zero = false; + while let Some(cmd) = load_commands.next().ok()? { + if let Some((seg, _)) = cmd.segment_32().ok()? { + if seg.name() == b"__TEXT" { + first_text = segments.len(); + if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { + text_fileoff_zero = true; + } + } + segments.push(LibrarySegment { + len: seg.vmsize(endian).try_into().ok()?, + stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, + }); + } + if let Some((seg, _)) = cmd.segment_64().ok()? { + if seg.name() == b"__TEXT" { + first_text = segments.len(); + if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { + text_fileoff_zero = true; + } + } + segments.push(LibrarySegment { + len: seg.vmsize(endian).try_into().ok()?, + stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, + }); + } + } + + // Determine the "slide" for this library which ends up being the + // bias we use to figure out where in memory objects are loaded. + // This is a bit of a weird computation though and is the result of + // trying a few things in the wild and seeing what sticks. + // + // The general idea is that the `bias` plus a segment's + // `stated_virtual_memory_address` is going to be where in the + // actual address space the segment resides. The other thing we rely + // on though is that a real address minus the `bias` is the index to + // look up in the symbol table and debuginfo. + // + // It turns out, though, that for system loaded libraries these + // calculations are incorrect. For native executables, however, it + // appears correct. Lifting some logic from LLDB's source it has + // some special-casing for the first `__TEXT` section loaded from + // file offset 0 with a nonzero size. For whatever reason when this + // is present it appears to mean that the symbol table is relative + // to just the vmaddr slide for the library. If it's *not* present + // then the symbol table is relative to the the vmaddr slide plus + // the segment's stated address. + // + // To handle this situation if we *don't* find a text section at + // file offset zero then we increase the bias by the first text + // sections's stated address and decrease all stated addresses by + // that amount as well. That way the symbol table is always appears + // relative to the library's bias amount. This appears to have the + // right results for symbolizing via the symbol table. + // + // Honestly I'm not entirely sure whether this is right or if + // there's something else that should indicate how to do this. For + // now though this seems to work well enough (?) and we should + // always be able to tweak this over time if necessary. + // + // For some more information see #318 + let mut slide = unsafe { libc::_dyld_get_image_vmaddr_slide(i) as usize }; + if !text_fileoff_zero { + let adjust = segments[first_text].stated_virtual_memory_address; + for segment in segments.iter_mut() { + segment.stated_virtual_memory_address -= adjust; + } + slide += adjust; + } + + Some(Library { + name: OsStr::from_bytes(name.to_bytes()).to_owned(), + segments, + bias: slide, + }) +} diff --git a/library/backtrace/src/symbolize/gimli/libs_windows.rs b/library/backtrace/src/symbolize/gimli/libs_windows.rs new file mode 100644 index 0000000000..b47ed42459 --- /dev/null +++ b/library/backtrace/src/symbolize/gimli/libs_windows.rs @@ -0,0 +1,89 @@ +use super::super::super::windows::*; +use super::mystd::os::windows::prelude::*; +use super::{coff, mmap, Library, LibrarySegment, OsString}; +use alloc::vec; +use alloc::vec::Vec; +use core::mem; +use core::mem::MaybeUninit; + +// For loading native libraries on Windows, see some discussion on +// rust-lang/rust#71060 for the various strategies here. +pub(super) fn native_libraries() -> Vec { + let mut ret = Vec::new(); + unsafe { + add_loaded_images(&mut ret); + } + return ret; +} + +unsafe fn add_loaded_images(ret: &mut Vec) { + let snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); + if snap == INVALID_HANDLE_VALUE { + return; + } + + let mut me = MaybeUninit::::zeroed().assume_init(); + me.dwSize = mem::size_of_val(&me) as DWORD; + if Module32FirstW(snap, &mut me) == TRUE { + loop { + if let Some(lib) = load_library(&me) { + ret.push(lib); + } + + if Module32NextW(snap, &mut me) != TRUE { + break; + } + } + } + + CloseHandle(snap); +} + +unsafe fn load_library(me: &MODULEENTRY32W) -> Option { + let pos = me + .szExePath + .iter() + .position(|i| *i == 0) + .unwrap_or(me.szExePath.len()); + let name = OsString::from_wide(&me.szExePath[..pos]); + + // MinGW libraries currently don't support ASLR + // (rust-lang/rust#16514), but DLLs can still be relocated around in + // the address space. It appears that addresses in debug info are + // all as-if this library was loaded at its "image base", which is a + // field in its COFF file headers. Since this is what debuginfo + // seems to list we parse the symbol table and store addresses as if + // the library was loaded at "image base" as well. + // + // The library may not be loaded at "image base", however. + // (presumably something else may be loaded there?) This is where + // the `bias` field comes into play, and we need to figure out the + // value of `bias` here. Unfortunately though it's not clear how to + // acquire this from a loaded module. What we do have, however, is + // the actual load address (`modBaseAddr`). + // + // As a bit of a cop-out for now we mmap the file, read the file + // header information, then drop the mmap. This is wasteful because + // we'll probably reopen the mmap later, but this should work well + // enough for now. + // + // Once we have the `image_base` (desired load location) and the + // `base_addr` (actual load location) we can fill in the `bias` + // (difference between the actual and desired) and then the stated + // address of each segment is the `image_base` since that's what the + // file says. + // + // For now it appears that unlike ELF/MachO we can make do with one + // segment per library, using `modBaseSize` as the whole size. + let mmap = mmap(name.as_ref())?; + let image_base = coff::get_image_base(&mmap)?; + let base_addr = me.modBaseAddr as usize; + Some(Library { + name, + bias: base_addr.wrapping_sub(image_base), + segments: vec![LibrarySegment { + stated_virtual_memory_address: image_base, + len: me.modBaseSize as usize, + }], + }) +} diff --git a/library/backtrace/src/symbolize/gimli/mmap_unix.rs b/library/backtrace/src/symbolize/gimli/mmap_unix.rs index d730ef1c3d..5806c9f7e5 100644 --- a/library/backtrace/src/symbolize/gimli/mmap_unix.rs +++ b/library/backtrace/src/symbolize/gimli/mmap_unix.rs @@ -1,4 +1,5 @@ -use super::{AsRawFd, File}; +use super::mystd::fs::File; +use super::mystd::os::unix::prelude::*; use core::ops::Deref; use core::ptr; use core::slice; diff --git a/library/backtrace/src/symbolize/gimli/mmap_windows.rs b/library/backtrace/src/symbolize/gimli/mmap_windows.rs index cda61e1b38..22f53fe03d 100644 --- a/library/backtrace/src/symbolize/gimli/mmap_windows.rs +++ b/library/backtrace/src/symbolize/gimli/mmap_windows.rs @@ -1,5 +1,6 @@ use super::super::super::windows::*; -use super::{AsRawHandle, File}; +use super::mystd::fs::File; +use super::mystd::os::windows::prelude::*; use core::ops::Deref; use core::ptr; use core::slice; diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index c1596012ea..b6aaf078cf 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "core" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "The Rust Core Library" autotests = false autobenches = false edition = "2018" @@ -25,3 +28,6 @@ rand = "0.7" [features] # Make panics and failed asserts immediately abort without formatting any message panic_immediate_abort = [] +# Make `RefCell` store additional debugging information, which is printed out when +# a borrow error occurs +debug_refcell = [] diff --git a/library/core/benches/fmt.rs b/library/core/benches/fmt.rs index 2792181acc..9df6626345 100644 --- a/library/core/benches/fmt.rs +++ b/library/core/benches/fmt.rs @@ -112,7 +112,7 @@ fn write_str_macro_debug(bh: &mut Bencher) { #[bench] fn write_u128_max(bh: &mut Bencher) { bh.iter(|| { - std::hint::black_box(format!("{}", u128::MAX)); + test::black_box(format!("{}", u128::MAX)); }); } @@ -120,20 +120,20 @@ fn write_u128_max(bh: &mut Bencher) { fn write_u128_min(bh: &mut Bencher) { bh.iter(|| { let s = format!("{}", 0u128); - std::hint::black_box(s); + test::black_box(s); }); } #[bench] fn write_u64_max(bh: &mut Bencher) { bh.iter(|| { - std::hint::black_box(format!("{}", u64::MAX)); + test::black_box(format!("{}", u64::MAX)); }); } #[bench] fn write_u64_min(bh: &mut Bencher) { bh.iter(|| { - std::hint::black_box(format!("{}", 0u64)); + test::black_box(format!("{}", 0u64)); }); } diff --git a/library/core/benches/slice.rs b/library/core/benches/slice.rs index dbab008568..04efa52078 100644 --- a/library/core/benches/slice.rs +++ b/library/core/benches/slice.rs @@ -114,3 +114,16 @@ rotate!(rotate_16_usize_4, 16, |i| [i; 4]); rotate!(rotate_16_usize_5, 16, |i| [i; 5]); rotate!(rotate_64_usize_4, 64, |i| [i; 4]); rotate!(rotate_64_usize_5, 64, |i| [i; 5]); + +#[bench] +fn fill_byte_sized(b: &mut Bencher) { + #[derive(Copy, Clone)] + struct NewType(u8); + + let mut ary = [NewType(0); 1024]; + + b.iter(|| { + let slice = &mut ary[..]; + black_box(slice.fill(black_box(NewType(42)))); + }); +} diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 8b95b70396..0e7667dd89 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -93,7 +93,7 @@ impl Layout { /// This function is unsafe as it does not verify the preconditions from /// [`Layout::from_size_align`]. #[stable(feature = "alloc_layout", since = "1.28.0")] - #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "alloc_layout", since = "1.36.0")] #[inline] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { // SAFETY: the caller must ensure that `align` is greater than zero. diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 98c34f3442..5e1725cfc7 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -141,7 +141,7 @@ impl Any for T { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for dyn Any { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Any") + f.debug_struct("Any").finish_non_exhaustive() } } @@ -151,14 +151,14 @@ impl fmt::Debug for dyn Any { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for dyn Any + Send { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Any") + f.debug_struct("Any").finish_non_exhaustive() } } #[stable(feature = "any_send_sync_methods", since = "1.28.0")] impl fmt::Debug for dyn Any + Send + Sync { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Any") + f.debug_struct("Any").finish_non_exhaustive() } } diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 4472fba26b..61ab1b1faf 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -2,7 +2,7 @@ use crate::{ fmt, - iter::{ExactSizeIterator, FusedIterator, TrustedLen}, + iter::{self, ExactSizeIterator, FusedIterator, TrustedLen}, mem::{self, MaybeUninit}, ops::Range, ptr, @@ -192,7 +192,7 @@ impl Clone for IntoIter { let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 }; // Clone all alive elements. - for (src, dst) in self.as_slice().iter().zip(&mut new.data) { + for (src, dst) in iter::zip(self.as_slice(), &mut new.data) { // Write a clone into the new array, then update its alive range. // If cloning panics, we'll correctly drop the previous items. dst.write(src.clone()); diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 8f52985d1d..8b56c9560a 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -12,7 +12,6 @@ use crate::convert::{Infallible, TryFrom}; use crate::fmt; use crate::hash::{self, Hash}; use crate::iter::TrustedLen; -use crate::marker::Unsize; use crate::mem::{self, MaybeUninit}; use crate::ops::{Index, IndexMut}; use crate::slice::{Iter, IterMut}; @@ -23,54 +22,19 @@ mod iter; pub use iter::IntoIter; /// Converts a reference to `T` into a reference to an array of length 1 (without copying). -#[unstable(feature = "array_from_ref", issue = "77101")] +#[stable(feature = "array_from_ref", since = "1.53.0")] pub fn from_ref(s: &T) -> &[T; 1] { // SAFETY: Converting `&T` to `&[T; 1]` is sound. unsafe { &*(s as *const T).cast::<[T; 1]>() } } /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). -#[unstable(feature = "array_from_ref", issue = "77101")] +#[stable(feature = "array_from_ref", since = "1.53.0")] pub fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } } -/// Utility trait implemented only on arrays of fixed size -/// -/// This trait can be used to implement other traits on fixed-size arrays -/// without causing much metadata bloat. -/// -/// The trait is marked unsafe in order to restrict implementors to fixed-size -/// arrays. A user of this trait can assume that implementors have the exact -/// layout in memory of a fixed size array (for example, for unsafe -/// initialization). -/// -/// Note that the traits [`AsRef`] and [`AsMut`] provide similar methods for types that -/// may not be fixed-size arrays. Implementors should prefer those traits -/// instead. -#[unstable(feature = "fixed_size_array", issue = "27778")] -pub unsafe trait FixedSizeArray { - /// Converts the array to immutable slice - #[unstable(feature = "fixed_size_array", issue = "27778")] - fn as_slice(&self) -> &[T]; - /// Converts the array to mutable slice - #[unstable(feature = "fixed_size_array", issue = "27778")] - fn as_mut_slice(&mut self) -> &mut [T]; -} - -#[unstable(feature = "fixed_size_array", issue = "27778")] -unsafe impl> FixedSizeArray for A { - #[inline] - fn as_slice(&self) -> &[T] { - self - } - #[inline] - fn as_mut_slice(&mut self) -> &mut [T] { - self - } -} - /// The error type returned when a conversion from a slice to an array fails. #[stable(feature = "try_from", since = "1.34.0")] #[derive(Debug, Copy, Clone)] @@ -191,6 +155,28 @@ impl fmt::Debug for [T; N] { } } +// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator` +// hides this implementation from explicit `.into_iter()` calls on editions < 2021, +// so those calls will still resolve to the slice implementation, by reference. +#[cfg(not(bootstrap))] +#[stable(feature = "array_into_iter_impl", since = "1.53.0")] +impl IntoIterator for [T; N] { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the array (from start to end). The array cannot be used after calling + /// this unless `T` implements `Copy`, so the whole array is copied. + /// + /// Arrays have special behavior when calling `.into_iter()` prior to the + /// 2021 edition -- see the [array] Editions section for more information. + /// + /// [array]: prim@array + fn into_iter(self) -> Self::IntoIter { + IntoIter::new(self) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, const N: usize> IntoIterator for &'a [T; N] { type Item = &'a T; diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index a8a25f9271..4780d8dc78 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -145,6 +145,6 @@ impl fmt::Display for EscapeDefault { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("EscapeDefault { .. }") + f.debug_struct("EscapeDefault").finish_non_exhaustive() } } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2fbbeb35e1..4820588df2 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -188,7 +188,7 @@ //! [`Rc`]: ../../std/rc/struct.Rc.html //! [`RwLock`]: ../../std/sync/struct.RwLock.html //! [`Mutex`]: ../../std/sync/struct.Mutex.html -//! [`atomic`]: ../../core/sync/atomic/index.html +//! [`atomic`]: crate::sync::atomic #![stable(feature = "rust1", since = "1.0.0")] @@ -325,7 +325,7 @@ impl Cell { /// let c = Cell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_cell_new", since = "1.24.0")] #[inline] pub const fn new(value: T) -> Cell { Cell { value: UnsafeCell::new(value) } @@ -575,6 +575,12 @@ impl Cell<[T]> { #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell { borrow: Cell, + // 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` + #[cfg(feature = "debug_refcell")] + borrowed_at: Cell>>, value: UnsafeCell, } @@ -582,12 +588,19 @@ pub struct RefCell { #[stable(feature = "try_borrow", since = "1.13.0")] pub struct BorrowError { _private: (), + #[cfg(feature = "debug_refcell")] + location: &'static crate::panic::Location<'static>, } #[stable(feature = "try_borrow", since = "1.13.0")] impl Debug for BorrowError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("BorrowError").finish() + let mut builder = f.debug_struct("BorrowError"); + + #[cfg(feature = "debug_refcell")] + builder.field("location", self.location); + + builder.finish() } } @@ -602,12 +615,19 @@ impl Display for BorrowError { #[stable(feature = "try_borrow", since = "1.13.0")] pub struct BorrowMutError { _private: (), + #[cfg(feature = "debug_refcell")] + location: &'static crate::panic::Location<'static>, } #[stable(feature = "try_borrow", since = "1.13.0")] impl Debug for BorrowMutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("BorrowMutError").finish() + let mut builder = f.debug_struct("BorrowMutError"); + + #[cfg(feature = "debug_refcell")] + builder.field("location", self.location); + + builder.finish() } } @@ -655,10 +675,15 @@ impl RefCell { /// let c = RefCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_refcell_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_refcell_new", since = "1.24.0")] #[inline] pub const fn new(value: T) -> RefCell { - RefCell { value: UnsafeCell::new(value), borrow: Cell::new(UNUSED) } + RefCell { + value: UnsafeCell::new(value), + borrow: Cell::new(UNUSED), + #[cfg(feature = "debug_refcell")] + borrowed_at: Cell::new(None), + } } /// Consumes the `RefCell`, returning the wrapped value. @@ -823,12 +848,29 @@ impl RefCell { /// ``` #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] + #[cfg_attr(feature = "debug_refcell", track_caller)] pub fn try_borrow(&self) -> Result, BorrowError> { match BorrowRef::new(&self.borrow) { - // SAFETY: `BorrowRef` ensures that there is only immutable access - // to the value while borrowed. - Some(b) => Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }), - None => Err(BorrowError { _private: () }), + Some(b) => { + #[cfg(feature = "debug_refcell")] + { + // `borrowed_at` is always the *first* active borrow + if b.borrow.get() == 1 { + self.borrowed_at.set(Some(crate::panic::Location::caller())); + } + } + + // SAFETY: `BorrowRef` ensures that there is only immutable access + // to the value while borrowed. + 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")] + location: self.borrowed_at.get().unwrap(), + }), } } @@ -896,11 +938,25 @@ impl RefCell { /// ``` #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] + #[cfg_attr(feature = "debug_refcell", track_caller)] pub fn try_borrow_mut(&self) -> Result, BorrowMutError> { match BorrowRefMut::new(&self.borrow) { - // SAFETY: `BorrowRef` guarantees unique access. - Some(b) => Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }), - None => Err(BorrowMutError { _private: () }), + Some(b) => { + #[cfg(feature = "debug_refcell")] + { + self.borrowed_at.set(Some(crate::panic::Location::caller())); + } + + // SAFETY: `BorrowRef` guarantees unique access. + 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")] + location: self.borrowed_at.get().unwrap(), + }), } } @@ -1016,7 +1072,13 @@ impl RefCell { // and is thus guaranteed to be valid for the lifetime of `self`. Ok(unsafe { &*self.value.get() }) } else { - Err(BorrowError { _private: () }) + 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")] + location: self.borrowed_at.get().unwrap(), + }) } } } @@ -1753,7 +1815,7 @@ impl UnsafeCell { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_unsafe_cell_new", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn new(value: T) -> UnsafeCell { UnsafeCell { value } } @@ -1769,7 +1831,7 @@ impl UnsafeCell { /// /// let five = uc.into_inner(); /// ``` - #[inline] + #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] pub const fn into_inner(self) -> T { @@ -1794,7 +1856,7 @@ impl UnsafeCell { /// /// let five = uc.get(); /// ``` - #[inline] + #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] pub const fn get(&self) -> *mut T { @@ -1819,7 +1881,7 @@ impl UnsafeCell { /// /// assert_eq!(*c.get_mut(), 6); /// ``` - #[inline] + #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] pub fn get_mut(&mut self) -> &mut T { &mut self.value @@ -1852,7 +1914,7 @@ impl UnsafeCell { /// /// assert_eq!(uc.into_inner(), 5); /// ``` - #[inline] + #[inline(always)] #[unstable(feature = "unsafe_cell_raw_get", issue = "66358")] pub const fn raw_get(this: *const Self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 87a3d375a6..dcab2cd2d9 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -403,16 +403,20 @@ impl char { } /// An extended version of `escape_debug` that optionally permits escaping - /// Extended Grapheme codepoints. This allows us to format characters like - /// nonspacing marks better when they're at the start of a string. + /// Extended Grapheme codepoints, single quotes, and double quotes. This + /// allows us to format characters like nonspacing marks better when they're + /// at the start of a string, and allows escaping single quotes in + /// characters, and double quotes in strings. #[inline] - pub(crate) fn escape_debug_ext(self, escape_grapheme_extended: bool) -> EscapeDebug { + pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug { let init_state = match self { '\t' => EscapeDefaultState::Backslash('t'), '\r' => EscapeDefaultState::Backslash('r'), '\n' => EscapeDefaultState::Backslash('n'), - '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self), - _ if escape_grapheme_extended && self.is_grapheme_extended() => { + '\\' => EscapeDefaultState::Backslash(self), + '"' if args.escape_double_quote => EscapeDefaultState::Backslash(self), + '\'' if args.escape_single_quote => EscapeDefaultState::Backslash(self), + _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { EscapeDefaultState::Unicode(self.escape_unicode()) } _ if is_printable(self) => EscapeDefaultState::Char(self), @@ -458,7 +462,7 @@ impl char { #[stable(feature = "char_escape_debug", since = "1.20.0")] #[inline] pub fn escape_debug(self) -> EscapeDebug { - self.escape_debug_ext(true) + self.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL) } /// Returns an iterator that yields the literal escape code of a character @@ -1565,6 +1569,25 @@ impl char { } } +pub(crate) struct EscapeDebugExtArgs { + /// Escape Extended Grapheme codepoints? + pub(crate) escape_grapheme_extended: bool, + + /// Escape single quotes? + pub(crate) escape_single_quote: bool, + + /// Escape double quotes? + pub(crate) escape_double_quote: bool, +} + +impl EscapeDebugExtArgs { + pub(crate) const ESCAPE_ALL: Self = Self { + escape_grapheme_extended: true, + escape_single_quote: true, + escape_double_quote: true, + }; +} + #[inline] const fn len_utf8(code: u32) -> usize { if code < MAX_ONE_B { diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 788fafa0ad..25a7c1de9d 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -45,6 +45,8 @@ pub use self::methods::encode_utf8_raw; use crate::fmt::{self, Write}; use crate::iter::FusedIterator; +pub(crate) use self::methods::EscapeDebugExtArgs; + // UTF-8 ranges and tags for encoding characters const TAG_CONT: u8 = 0b1000_0000; const TAG_TWO_B: u8 = 0b1100_0000; diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 5bab1fb93d..f8b16b6f92 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -274,6 +274,7 @@ pub trait Eq: PartialEq { // // This should never be implemented by hand. #[doc(hidden)] + #[cfg_attr(not(bootstrap), no_coverage)] // rust-lang/rust#84605 #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn assert_receiver_is_total_eq(&self) {} @@ -282,7 +283,7 @@ pub trait Eq: PartialEq { /// Derive macro generating an impl of the trait `Eq`. #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)] +#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match, no_coverage)] pub macro Eq($item:item) { /* compiler built-in */ } @@ -334,7 +335,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_helpers)] /// use std::cmp::Ordering; /// /// assert_eq!(Ordering::Less.is_eq(), false); @@ -343,7 +343,8 @@ impl Ordering { /// ``` #[inline] #[must_use] - #[unstable(feature = "ordering_helpers", issue = "79885")] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_eq(self) -> bool { matches!(self, Equal) } @@ -353,7 +354,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_helpers)] /// use std::cmp::Ordering; /// /// assert_eq!(Ordering::Less.is_ne(), true); @@ -362,7 +362,8 @@ impl Ordering { /// ``` #[inline] #[must_use] - #[unstable(feature = "ordering_helpers", issue = "79885")] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_ne(self) -> bool { !matches!(self, Equal) } @@ -372,7 +373,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_helpers)] /// use std::cmp::Ordering; /// /// assert_eq!(Ordering::Less.is_lt(), true); @@ -381,7 +381,8 @@ impl Ordering { /// ``` #[inline] #[must_use] - #[unstable(feature = "ordering_helpers", issue = "79885")] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_lt(self) -> bool { matches!(self, Less) } @@ -391,7 +392,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_helpers)] /// use std::cmp::Ordering; /// /// assert_eq!(Ordering::Less.is_gt(), false); @@ -400,7 +400,8 @@ impl Ordering { /// ``` #[inline] #[must_use] - #[unstable(feature = "ordering_helpers", issue = "79885")] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_gt(self) -> bool { matches!(self, Greater) } @@ -410,7 +411,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_helpers)] /// use std::cmp::Ordering; /// /// assert_eq!(Ordering::Less.is_le(), true); @@ -419,7 +419,8 @@ impl Ordering { /// ``` #[inline] #[must_use] - #[unstable(feature = "ordering_helpers", issue = "79885")] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_le(self) -> bool { !matches!(self, Greater) } @@ -429,7 +430,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_helpers)] /// use std::cmp::Ordering; /// /// assert_eq!(Ordering::Less.is_ge(), false); @@ -438,7 +438,8 @@ impl Ordering { /// ``` #[inline] #[must_use] - #[unstable(feature = "ordering_helpers", issue = "79885")] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_ge(self) -> bool { !matches!(self, Less) } @@ -981,7 +982,11 @@ pub trait PartialOrd: PartialEq { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn le(&self, other: &Rhs) -> bool { - matches!(self.partial_cmp(other), Some(Less | Equal)) + // Pattern `Some(Less | Eq)` optimizes worse than negating `None | Some(Greater)`. + // FIXME: The root cause was fixed upstream in LLVM with: + // https://github.com/llvm/llvm-project/commit/9bad7de9a3fb844f1ca2965f35d0c2a3d1e11775 + // Revert this workaround once support for LLVM 12 gets dropped. + !matches!(self.partial_cmp(other), None | Some(Greater)) } /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. @@ -1058,8 +1063,6 @@ pub fn min(v1: T, v2: T) -> T { /// # Examples /// /// ``` -/// #![feature(cmp_min_max_by)] -/// /// use std::cmp; /// /// assert_eq!(cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 1); @@ -1067,7 +1070,7 @@ pub fn min(v1: T, v2: T) -> T { /// ``` #[inline] #[must_use] -#[unstable(feature = "cmp_min_max_by", issue = "64460")] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v1, @@ -1082,8 +1085,6 @@ pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { /// # Examples /// /// ``` -/// #![feature(cmp_min_max_by)] -/// /// use std::cmp; /// /// assert_eq!(cmp::min_by_key(-2, 1, |x: &i32| x.abs()), 1); @@ -1091,7 +1092,7 @@ pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { /// ``` #[inline] #[must_use] -#[unstable(feature = "cmp_min_max_by", issue = "64460")] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) } @@ -1124,8 +1125,6 @@ pub fn max(v1: T, v2: T) -> T { /// # Examples /// /// ``` -/// #![feature(cmp_min_max_by)] -/// /// use std::cmp; /// /// assert_eq!(cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2); @@ -1133,7 +1132,7 @@ pub fn max(v1: T, v2: T) -> T { /// ``` #[inline] #[must_use] -#[unstable(feature = "cmp_min_max_by", issue = "64460")] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v2, @@ -1148,8 +1147,6 @@ pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { /// # Examples /// /// ``` -/// #![feature(cmp_min_max_by)] -/// /// use std::cmp; /// /// assert_eq!(cmp::max_by_key(-2, 1, |x: &i32| x.abs()), -2); @@ -1157,7 +1154,7 @@ pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { /// ``` #[inline] #[must_use] -#[unstable(feature = "cmp_min_max_by", issue = "64460")] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) } diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 5b113610a5..a522b7da3b 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -45,8 +45,10 @@ impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize); macro_rules! impl_from { ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { #[$attr] - #[doc = $doc] impl From<$Small> for $Large { + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = $doc] #[inline] fn from(small: $Small) -> Self { small as Self @@ -383,8 +385,10 @@ use crate::num::NonZeroUsize; macro_rules! nzint_impl_from { ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { #[$attr] - #[doc = $doc] impl From<$Small> for $Large { + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = $doc] #[inline] fn from(small: $Small) -> Self { // SAFETY: input type guarantees the value is non-zero @@ -450,10 +454,12 @@ nzint_impl_from! { NonZeroU64, NonZeroI128, #[stable(feature = "nz_int_conv", si macro_rules! nzint_impl_try_from_int { ($Int: ty, $NonZeroInt: ty, #[$attr:meta], $doc: expr) => { #[$attr] - #[doc = $doc] impl TryFrom<$Int> for $NonZeroInt { type Error = TryFromIntError; + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = $doc] #[inline] fn try_from(value: $Int) -> Result { Self::new(value).ok_or(TryFromIntError(())) @@ -489,10 +495,12 @@ nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_fr macro_rules! nzint_impl_try_from_nzint { ($From:ty => $To:ty, $doc: expr) => { #[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")] - #[doc = $doc] impl TryFrom<$From> for $To { type Error = TryFromIntError; + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = $doc] #[inline] fn try_from(value: $From) -> Result { TryFrom::try_from(value.get()).map(|v| { diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs index 9302baa823..b208ddd4b2 100644 --- a/library/core/src/ffi.rs +++ b/library/core/src/ffi.rs @@ -53,7 +53,7 @@ pub enum c_void { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for c_void { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("c_void") + f.debug_struct("c_void").finish() } } diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index d95d43f085..b660788c05 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -165,7 +165,6 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// # Examples /// /// ``` - /// # #![feature(debug_non_exhaustive)] /// use std::fmt; /// /// struct Bar { @@ -186,31 +185,22 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// "Bar { bar: 10, .. }", /// ); /// ``` - #[unstable(feature = "debug_non_exhaustive", issue = "67364")] + #[stable(feature = "debug_non_exhaustive", since = "1.53.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { - // Draw non-exhaustive dots (`..`), and open brace if necessary (no fields). - if self.is_pretty() { - if !self.has_fields { - self.fmt.write_str(" {\n")?; - } - let mut slot = None; - let mut state = Default::default(); - let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state); - writer.write_str("..\n")?; - } else { - if self.has_fields { - self.fmt.write_str(", ..")?; + if self.has_fields { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str("}") } else { - self.fmt.write_str(" { ..")?; + self.fmt.write_str(", .. }") } - } - if self.is_pretty() { - self.fmt.write_str("}")? } else { - self.fmt.write_str(" }")?; + self.fmt.write_str(" { .. }") } - Ok(()) }); self.result } diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index 5908da477e..ece3cde001 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -54,21 +54,14 @@ where } // Common code of floating point Debug and Display. -fn float_to_decimal_common( - fmt: &mut Formatter<'_>, - num: &T, - negative_zero: bool, - min_precision: usize, -) -> Result +fn float_to_decimal_common(fmt: &mut Formatter<'_>, num: &T, min_precision: usize) -> Result where T: flt2dec::DecodableFloat, { let force_sign = fmt.sign_plus(); - let sign = match (force_sign, negative_zero) { - (false, false) => flt2dec::Sign::Minus, - (false, true) => flt2dec::Sign::MinusRaw, - (true, false) => flt2dec::Sign::MinusPlus, - (true, true) => flt2dec::Sign::MinusPlusRaw, + let sign = match force_sign { + false => flt2dec::Sign::Minus, + true => flt2dec::Sign::MinusPlus, }; if let Some(precision) = fmt.precision { @@ -156,14 +149,14 @@ macro_rules! floating { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for $ty { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_decimal_common(fmt, self, true, 1) + float_to_decimal_common(fmt, self, 1) } } #[stable(feature = "rust1", since = "1.0.0")] impl Display for $ty { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { - float_to_decimal_common(fmt, self, false, 0) + float_to_decimal_common(fmt, self, 0) } } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 2df5e56274..87042d95fb 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -3,6 +3,8 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; +use crate::char::EscapeDebugExtArgs; +use crate::iter; use crate::marker::PhantomData; use crate::mem; use crate::num::flt2dec; @@ -1087,7 +1089,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { match args.fmt { None => { // We can use default formatting parameters for all arguments. - for (arg, piece) in args.args.iter().zip(args.pieces.iter()) { + for (arg, piece) in iter::zip(args.args, args.pieces) { formatter.buf.write_str(*piece)?; (arg.formatter)(arg.value, &mut formatter)?; idx += 1; @@ -1096,7 +1098,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { Some(fmt) => { // Every spec has a corresponding argument that is preceded by // a string piece. - for (arg, piece) in fmt.iter().zip(args.pieces.iter()) { + for (arg, piece) in iter::zip(fmt, args.pieces) { formatter.buf.write_str(*piece)?; // SAFETY: arg and args.args come from the same Arguments, // which guarantees the indexes are always within bounds. @@ -2054,7 +2056,11 @@ impl Debug for str { f.write_char('"')?; let mut from = 0; for (i, c) in self.char_indices() { - let esc = c.escape_debug(); + let esc = c.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: true, + escape_single_quote: false, + escape_double_quote: true, + }); // If char needs escaping, flush backlog so far and write, else skip if esc.len() != 1 { f.write_str(&self[from..i])?; @@ -2080,7 +2086,11 @@ impl Display for str { impl Debug for char { fn fmt(&self, f: &mut Formatter<'_>) -> Result { f.write_char('\'')?; - for c in self.escape_debug() { + for c in self.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: true, + escape_single_quote: true, + escape_double_quote: false, + }) { f.write_char(c)? } f.write_char('\'') @@ -2210,7 +2220,7 @@ impl Debug for () { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for PhantomData { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - f.pad("PhantomData") + f.debug_struct("PhantomData").finish() } } @@ -2258,9 +2268,9 @@ impl Debug for RefMut<'_, T> { } #[stable(feature = "core_impl_debug", since = "1.9.0")] -impl Debug for UnsafeCell { +impl Debug for UnsafeCell { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - f.pad("UnsafeCell") + f.debug_struct("UnsafeCell").finish_non_exhaustive() } } diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index e9a99ddb6b..cc4cf54a2f 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -24,7 +24,8 @@ use crate::task::{Context, Poll}; /// `.await` the value. /// /// [`Waker`]: crate::task::Waker -#[doc(spotlight)] +#[cfg_attr(bootstrap, doc(spotlight))] +#[cfg_attr(not(bootstrap), doc(notable_trait))] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 7bfa58d34e..77d3a35b26 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -175,6 +175,21 @@ pub trait Hash { /// Feeds a slice of this type into the given [`Hasher`]. /// + /// This method is meant as a convenience, but its implementation is + /// also explicitly left unspecified. It isn't guaranteed to be + /// equivalent to repeated calls of [`hash`] and implementations of + /// [`Hash`] should keep that in mind and call [`hash`] themselves + /// if the slice isn't treated as a whole unit in the [`PartialEq`] + /// implementation. + /// + /// For example, a [`VecDeque`] implementation might naïvely call + /// [`as_slices`] and then [`hash_slice`] on each slice, but this + /// is wrong since the two slices can change with a call to + /// [`make_contiguous`] without affecting the [`PartialEq`] + /// result. Since these slices aren't treated as singular + /// units, and instead part of a larger deque, this method cannot + /// be used. + /// /// # Examples /// /// ``` @@ -186,6 +201,12 @@ pub trait Hash { /// Hash::hash_slice(&numbers, &mut hasher); /// println!("Hash is {:x}!", hasher.finish()); /// ``` + /// + /// [`VecDeque`]: ../../std/collections/struct.VecDeque.html + /// [`as_slices`]: ../../std/collections/struct.VecDeque.html#method.as_slices + /// [`make_contiguous`]: ../../std/collections/struct.VecDeque.html#method.make_contiguous + /// [`hash`]: Hash::hash + /// [`hash_slice`]: Hash::hash_slice #[stable(feature = "hash_slice", since = "1.3.0")] fn hash_slice(data: &[Self], state: &mut H) where @@ -221,6 +242,11 @@ pub use macros::Hash; /// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher` /// instances are used in conjunction with the [`Hash`] trait. /// +/// This trait makes no assumptions about how the various `write_*` methods are +/// defined and implementations of [`Hash`] should not assume that they work one +/// way or another. You cannot assume, for example, that a [`write_u32`] call is +/// equivalent to four calls of [`write_u8`]. +/// /// # Examples /// /// ``` @@ -240,6 +266,7 @@ pub use macros::Hash; /// [`finish`]: Hasher::finish /// [`write`]: Hasher::write /// [`write_u8`]: Hasher::write_u8 +/// [`write_u32`]: Hasher::write_u32 #[stable(feature = "rust1", since = "1.0.0")] pub trait Hasher { /// Returns the hash value for the values written so far. @@ -507,7 +534,7 @@ pub struct BuildHasherDefault(marker::PhantomData); #[stable(since = "1.9.0", feature = "core_impl_debug")] impl fmt::Debug for BuildHasherDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("BuildHasherDefault") + f.debug_struct("BuildHasherDefault").finish() } } @@ -691,29 +718,9 @@ mod impls { impl Hash for *const T { #[inline] fn hash(&self, state: &mut H) { - #[cfg(not(bootstrap))] - { - let (address, metadata) = self.to_raw_parts(); - state.write_usize(address as usize); - metadata.hash(state); - } - #[cfg(bootstrap)] - { - if mem::size_of::() == mem::size_of::() { - // Thin pointer - state.write_usize(*self as *const () as usize); - } else { - // Fat pointer - // SAFETY: we are accessing the memory occupied by `self` - // which is guaranteed to be valid. - // This assumes a fat pointer can be represented by a `(usize, usize)`, - // which is safe to do in `std` because it is shipped and kept in sync - // with the implementation of fat pointers in `rustc`. - let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; - state.write_usize(a); - state.write_usize(b); - } - } + let (address, metadata) = self.to_raw_parts(); + state.write_usize(address as usize); + metadata.hash(state); } } @@ -721,29 +728,9 @@ mod impls { impl Hash for *mut T { #[inline] fn hash(&self, state: &mut H) { - #[cfg(not(bootstrap))] - { - let (address, metadata) = self.to_raw_parts(); - state.write_usize(address as usize); - metadata.hash(state); - } - #[cfg(bootstrap)] - { - if mem::size_of::() == mem::size_of::() { - // Thin pointer - state.write_usize(*self as *const () as usize); - } else { - // Fat pointer - // SAFETY: we are accessing the memory occupied by `self` - // which is guaranteed to be valid. - // This assumes a fat pointer can be represented by a `(usize, usize)`, - // which is safe to do in `std` because it is shipped and kept in sync - // with the implementation of fat pointers in `rustc`. - let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; - state.write_usize(a); - state.write_usize(b); - } - } + let (address, metadata) = self.to_raw_parts(); + state.write_usize(address as usize); + metadata.hash(state); } } } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 313729581a..f7aec73644 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -154,7 +154,7 @@ pub fn spin_loop() { /// [`std::convert::identity`]: crate::convert::identity #[cfg_attr(not(miri), inline)] #[cfg_attr(miri, inline(never))] -#[unstable(feature = "test", issue = "50297")] +#[unstable(feature = "bench_black_box", issue = "64102")] #[cfg_attr(miri, allow(unused_mut))] pub fn black_box(mut dummy: T) -> T { // We need to "use" the argument in some way LLVM can't introspect, and on diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 073210c5b6..175fc2e04c 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1543,7 +1543,7 @@ extern "rust-intrinsic" { /// let num_trailing = unsafe { cttz_nonzero(x) }; /// assert_eq!(num_trailing, 3); /// ``` - #[rustc_const_unstable(feature = "const_cttz", issue = "none")] + #[rustc_const_stable(feature = "const_cttz", since = "1.53.0")] pub fn cttz_nonzero(x: T) -> T; /// Reverses the bytes in an integer type `T`. @@ -1843,7 +1843,7 @@ pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] - fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } // FIXME: Perform these checks only at run time diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 41a7b13232..61d8351d59 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -51,6 +51,9 @@ pub use self::map_while::MapWhile; #[unstable(feature = "trusted_random_access", issue = "none")] 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 /// under the conditions that /// * the iterator source `S` itself implements `SourceIter` @@ -191,3 +194,26 @@ where self.try_fold(init, ok(fold)).unwrap() } } + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for ResultShunt<'_, I, E> +where + I: SourceIter, +{ + type Source = S; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut S { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +// SAFETY: ResultShunt::next calls I::find, which has to advance `iter` in order to +// return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's guaranteed that +// at least one item will be moved out from the underlying source. +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for ResultShunt<'_, I, E> where + I: Iterator> + InPlaceIterable +{ +} diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 43301444e3..0d860aec49 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -1,4 +1,4 @@ -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen}; +use crate::iter::{adapters::SourceIter, FusedIterator, TrustedLen}; use crate::ops::Try; /// An iterator with a `peek()` that returns an optional reference to the next @@ -233,7 +233,6 @@ impl Peekable { /// Basic usage: /// /// ``` - /// #![feature(peekable_peek_mut)] /// let mut iter = [1, 2, 3].iter().peekable(); /// /// // Like with `peek()`, we can see into the future without advancing the iterator. @@ -251,7 +250,7 @@ impl Peekable { /// assert_eq!(iter.collect::>(), vec![&5, &3]); /// ``` #[inline] - #[unstable(feature = "peekable_peek_mut", issue = "78302")] + #[stable(feature = "peekable_peek_mut", since = "1.53.0")] pub fn peek_mut(&mut self) -> Option<&mut I::Item> { let iter = &mut self.iter; self.peeked.get_or_insert_with(|| iter.next()).as_mut() @@ -334,6 +333,3 @@ where unsafe { SourceIter::as_inner(&mut self.iter) } } } - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Peekable {} diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index ea7a809c6b..2f8f504d8f 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -5,8 +5,8 @@ use crate::iter::{InPlaceIterable, SourceIter, TrustedLen}; /// An iterator that iterates two other iterators simultaneously. /// -/// This `struct` is created by [`Iterator::zip`]. See its documentation -/// for more. +/// This `struct` is created by [`zip`] or [`Iterator::zip`]. +/// See their documentation for more. #[derive(Clone)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -33,6 +33,37 @@ impl Zip { } } +/// Converts the arguments to iterators and zips them. +/// +/// See the documentation of [`Iterator::zip`] for more. +/// +/// # Examples +/// +/// ``` +/// #![feature(iter_zip)] +/// use std::iter::zip; +/// +/// let xs = [1, 2, 3]; +/// let ys = [4, 5, 6]; +/// for (x, y) in zip(&xs, &ys) { +/// println!("x:{}, y:{}", x, y); +/// } +/// +/// // Nested zips are also possible: +/// let zs = [7, 8, 9]; +/// for ((x, y), z) in zip(zip(&xs, &ys), &zs) { +/// println!("x:{}, y:{}, z:{}", x, y, z); +/// } +/// ``` +#[unstable(feature = "iter_zip", issue = "83574")] +pub fn zip(a: A, b: B) -> Zip +where + A: IntoIterator, + B: IntoIterator, +{ + ZipImpl::new(a.into_iter(), b.into_iter()) +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Zip where diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index c57ba2bf62..2a179f0b1d 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -389,6 +389,8 @@ pub use self::traits::{ DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum, }; +#[unstable(feature = "iter_zip", issue = "83574")] +pub use self::adapters::zip; #[stable(feature = "iter_cloned", since = "1.1.0")] pub use self::adapters::Cloned; #[stable(feature = "iter_copied", since = "1.36.0")] diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index cc80e06dec..4b293c596e 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -3,7 +3,7 @@ use crate::convert::TryFrom; use crate::mem; use crate::ops::{self, Try}; -use super::{FusedIterator, TrustedLen}; +use super::{FusedIterator, TrustedLen, TrustedRandomAccess}; /// Objects that have a notion of *successor* and *predecessor* operations. /// @@ -493,6 +493,18 @@ macro_rules! range_exact_iter_impl { )*) } +/// Safety: This macro must only be used on types that are `Copy` and result in ranges +/// which have an exact `size_hint()` where the upper bound must not be `None`. +macro_rules! unsafe_range_trusted_random_access_impl { + ($($t:ty)*) => ($( + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccess for ops::Range<$t> { + const MAY_HAVE_SIDE_EFFECT: bool = false; + } + )*) +} + macro_rules! range_incl_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "inclusive_range", since = "1.26.0")] @@ -553,6 +565,18 @@ impl Iterator for ops::Range { fn max(mut self) -> Option { self.next_back() } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + // Additionally Self: TrustedRandomAccess is only implemented for Copy types + // which means even repeated reads of the same index would be safe. + unsafe { Step::forward_unchecked(self.start.clone(), idx) } + } } // These macros generate `ExactSizeIterator` impls for various range types. @@ -574,6 +598,23 @@ range_exact_iter_impl! { u32 i32 } + +unsafe_range_trusted_random_access_impl! { + usize u8 u16 + isize i8 i16 +} + +#[cfg(target_pointer_width = "32")] +unsafe_range_trusted_random_access_impl! { + u32 i32 +} + +#[cfg(target_pointer_width = "64")] +unsafe_range_trusted_random_access_impl! { + u32 i32 + u64 i64 +} + range_incl_exact_iter_impl! { u8 i8 diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs index 5d4a9fe8c6..919c564f28 100644 --- a/library/core/src/iter/sources/empty.rs +++ b/library/core/src/iter/sources/empty.rs @@ -36,7 +36,7 @@ unsafe impl Sync for Empty {} #[stable(feature = "core_impl_debug", since = "1.9.0")] impl fmt::Debug for Empty { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Empty") + f.debug_struct("Empty").finish() } } diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 1ae6d15c12..13a2e24cad 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -198,6 +198,7 @@ pub trait FromIterator: Sized { /// } /// ``` #[rustc_diagnostic_item = "IntoIterator"] +#[cfg_attr(not(bootstrap), rustc_skip_array_during_method_dispatch)] #[stable(feature = "rust1", since = "1.0.0")] pub trait IntoIterator { /// The type of the elements being iterated over. diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index a07750f4ad..da9e5fde7c 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -81,8 +81,8 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} ), on( _Self = "[]", - label = "borrow the array with `&` or call `.iter()` on it to iterate over it", - note = "arrays are not iterators, but slices like the following are: `&[1, 2, 3]`" + label = "arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`", + note = "see for more details" ), on( _Self = "{integral}", @@ -92,7 +92,8 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} label = "`{Self}` is not an iterator", message = "`{Self}` is not an iterator" )] -#[doc(spotlight)] +#[cfg_attr(bootstrap, doc(spotlight))] +#[cfg_attr(not(bootstrap), doc(notable_trait))] #[rustc_diagnostic_item = "Iterator"] #[must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator { @@ -936,20 +937,16 @@ pub trait Iterator { Enumerate::new(self) } - /// Creates an iterator which can use [`peek`] to look at the next element of - /// the iterator without consuming it. + /// Creates an iterator which can use the [`peek`] and [`peek_mut`] methods + /// to look at the next element of the iterator without consuming it. See + /// their documentation for more information. /// - /// Adds a [`peek`] method to an iterator. See its documentation for - /// more information. + /// Note that the underlying iterator is still advanced when [`peek`] or + /// [`peek_mut`] are called for the first time: In order to retrieve the + /// next element, [`next`] is called on the underlying iterator, hence any + /// side effects (i.e. anything other than fetching the next value) of + /// the [`next`] method will occur. /// - /// Note that the underlying iterator is still advanced when [`peek`] is - /// called for the first time: In order to retrieve the next element, - /// [`next`] is called on the underlying iterator, hence any side effects (i.e. - /// anything other than fetching the next value) of the [`next`] method - /// will occur. - /// - /// [`peek`]: Peekable::peek - /// [`next`]: Iterator::next /// /// # Examples /// @@ -976,6 +973,32 @@ pub trait Iterator { /// assert_eq!(iter.peek(), None); /// assert_eq!(iter.next(), None); /// ``` + /// + /// Using [`peek_mut`] to mutate the next item without advancing the + /// iterator: + /// + /// ``` + /// let xs = [1, 2, 3]; + /// + /// let mut iter = xs.iter().peekable(); + /// + /// // `peek_mut()` lets us see into the future + /// assert_eq!(iter.peek_mut(), Some(&mut &1)); + /// assert_eq!(iter.peek_mut(), Some(&mut &1)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// if let Some(mut p) = iter.peek_mut() { + /// assert_eq!(*p, &2); + /// // put a value into the iterator + /// *p = &1000; + /// } + /// + /// // The value reappears as the iterator continues + /// assert_eq!(iter.collect::>(), vec![&1000, &3]); + /// ``` + /// [`peek`]: Peekable::peek + /// [`peek_mut`]: Peekable::peek_mut + /// [`next`]: Iterator::next #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn peekable(self) -> Peekable @@ -1228,7 +1251,11 @@ pub trait Iterator { /// Creates an iterator that skips the first `n` elements. /// - /// After they have been consumed, the rest of the elements are yielded. + /// `skip(n)` skips elements until `n` elements are skipped or the end of the + /// iterator is reached (whichever happens first). After that, all the remaining + /// elements are yielded. In particular, if the original iterator is too short, + /// then the returned iterator is empty. + /// /// Rather than overriding this method directly, instead override the `nth` method. /// /// # Examples @@ -1252,7 +1279,14 @@ pub trait Iterator { Skip::new(self, n) } - /// Creates an iterator that yields its first `n` elements. + /// Creates an iterator that yields the first `n` elements, or fewer + /// if the underlying iterator ends sooner. + /// + /// `take(n)` yields elements until `n` elements are yielded or the end of + /// the iterator is reached (whichever happens first). + /// The returned iterator is a prefix of length `n` if the original iterator + /// contains at least `n` elements, otherwise it contains all of the + /// (fewer than `n`) elements of the original iterator. /// /// # Examples /// @@ -1461,7 +1495,12 @@ pub trait Iterator { /// [`Some(T)`] again. `fuse()` adapts an iterator, ensuring that after a /// [`None`] is given, it will always return [`None`] forever. /// + /// Note that the [`Fuse`] wrapper is a no-op on iterators that implement + /// the [`FusedIterator`] trait. `fuse()` may therefore behave incorrectly + /// if the [`FusedIterator`] trait is improperly implemented. + /// /// [`Some(T)`]: Some + /// [`FusedIterator`]: crate::iter::FusedIterator /// /// # Examples /// @@ -1612,31 +1651,16 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// let a = [1, 2, 3]; - /// - /// let iter = a.iter(); - /// - /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i); - /// - /// assert_eq!(sum, 6); + /// let mut words = vec!["hello", "world", "of", "Rust"].into_iter(); /// - /// // if we try to use iter again, it won't work. The following line - /// // gives "error: use of moved value: `iter` - /// // assert_eq!(iter.next(), None); + /// // Take the first two words. + /// let hello_world: Vec<_> = words.by_ref().take(2).collect(); + /// assert_eq!(hello_world, vec!["hello", "world"]); /// - /// // let's try that again - /// let a = [1, 2, 3]; - /// - /// let mut iter = a.iter(); - /// - /// // instead, we add in a .by_ref() - /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i); - /// - /// assert_eq!(sum, 3); - /// - /// // now this is just fine: - /// assert_eq!(iter.next(), Some(&3)); - /// assert_eq!(iter.next(), None); + /// // Collect the rest of the words. + /// // We can only do this because we used `by_ref` earlier. + /// let of_rust: Vec<_> = words.collect(); + /// assert_eq!(of_rust, vec!["of", "Rust"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self @@ -2109,7 +2133,6 @@ pub trait Iterator { /// ``` /// /// [`reduce()`]: Iterator::reduce - #[doc(alias = "reduce")] #[doc(alias = "inject")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 8e35adcbd9..d1329b8f22 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -79,14 +79,14 @@ #![feature(const_int_unchecked_arith)] #![feature(const_mut_refs)] #![feature(const_refs_to_cell)] -#![feature(const_cttz)] #![feature(const_panic)] #![feature(const_pin)] -#![feature(const_fn)] +#![cfg_attr(bootstrap, feature(const_fn))] #![feature(const_fn_union)] #![feature(const_impl_trait)] #![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] +#![cfg_attr(not(bootstrap), feature(const_fn_trait_bound))] #![feature(const_option)] #![feature(const_precise_live_drops)] #![feature(const_ptr_offset)] @@ -109,9 +109,9 @@ #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] -#![feature(doc_spotlight)] +#![cfg_attr(bootstrap, feature(doc_spotlight))] +#![cfg_attr(not(bootstrap), feature(doc_notable_trait))] #![feature(duration_consts_2)] -#![feature(duration_saturating_ops)] #![feature(extended_key_value_attributes)] #![feature(extern_types)] #![feature(fundamental)] @@ -126,9 +126,9 @@ #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(auto_traits)] -#![feature(or_patterns)] +#![cfg_attr(bootstrap, feature(or_patterns))] #![feature(prelude_import)] -#![cfg_attr(not(bootstrap), feature(ptr_metadata))] +#![feature(ptr_metadata)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] #![feature(simd_ffi)] @@ -138,6 +138,7 @@ #![feature(stmt_expr_attributes)] #![feature(str_split_as_str)] #![feature(str_split_inclusive_as_str)] +#![feature(char_indices_offset)] #![feature(trait_alias)] #![feature(transparent_unions)] #![feature(try_blocks)] @@ -165,8 +166,8 @@ #![feature(const_caller_location)] #![feature(slice_ptr_get)] #![feature(no_niche)] // rust-lang/rust#68303 +#![cfg_attr(not(bootstrap), feature(no_coverage))] // rust-lang/rust#84605 #![feature(int_error_matching)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] #![deny(unsafe_op_in_unsafe_fn)] #[prelude_import] @@ -298,8 +299,8 @@ pub mod primitive; unused_imports, unsafe_op_in_unsafe_fn )] -#[cfg_attr(bootstrap, allow(non_autolinks))] -#[cfg_attr(not(bootstrap), allow(rustdoc::non_autolinks))] +#[cfg_attr(bootstrap, allow(rustdoc::non_autolinks))] +#[cfg_attr(not(bootstrap), allow(rustdoc::bare_urls))] // FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is // merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. #[allow(clashing_extern_declarations)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index a0a8eecbc2..66efa3c20b 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1301,7 +1301,6 @@ pub(crate) mod builtin { } /// Attribute macro used to apply derive macros. - #[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] pub macro derive($item:item) { @@ -1363,7 +1362,6 @@ pub(crate) mod builtin { } /// Expands all `#[cfg]` and `#[cfg_attr]` attributes in the code fragment it's applied to. - #[cfg(not(bootstrap))] #[unstable( feature = "cfg_eval", issue = "82679", diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 85e0e72008..fb957348be 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -765,7 +765,7 @@ unsafe impl Freeze for &mut T {} /// [`pin` module]: crate::pin #[stable(feature = "pin", since = "1.33.0")] #[rustc_on_unimplemented( - on(_Self = "std::future::Future", note = "consider using `Box::pin`",), + note = "consider using `Box::pin`", message = "`{Self}` cannot be unpinned" )] #[lang = "unpin"] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index cb07293123..4d7d47579e 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -190,6 +190,8 @@ use crate::ptr; /// let ptr = uninit.as_mut_ptr(); /// /// // Initializing the `name` field +/// // Using `write` instead of assignment via `=` to not call `drop` on the +/// // old, uninitialized value. /// unsafe { addr_of_mut!((*ptr).name).write("Bob".to_string()); } /// /// // Initializing the `list` field @@ -319,9 +321,9 @@ impl MaybeUninit { /// Create a new array of `MaybeUninit` items, in an uninitialized state. /// /// Note: in a future Rust version this method may become unnecessary - /// when array literal syntax allows - /// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147). - /// The example below could then use `let mut buf = [MaybeUninit::::uninit(); 32];`. + /// when Rust allows + /// [inline const expressions](https://github.com/rust-lang/rust/issues/76001). + /// The example below could then use `let mut buf = [const { MaybeUninit::::uninit() }; 32];`. /// /// # Examples /// @@ -734,22 +736,22 @@ impl MaybeUninit { /// #![feature(maybe_uninit_ref)] /// use std::mem::MaybeUninit; /// - /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] } + /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] } /// # #[cfg(FALSE)] /// extern "C" { /// /// Initializes *all* the bytes of the input buffer. - /// fn initialize_buffer(buf: *mut [u8; 2048]); + /// fn initialize_buffer(buf: *mut [u8; 1024]); /// } /// - /// let mut buf = MaybeUninit::<[u8; 2048]>::uninit(); + /// let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); /// /// // Initialize `buf`: /// unsafe { initialize_buffer(buf.as_mut_ptr()); } /// // Now we know that `buf` has been initialized, so we could `.assume_init()` it. - /// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes. + /// // However, using `.assume_init()` may trigger a `memcpy` of the 1024 bytes. /// // To assert our buffer has been initialized without copying it, we upgrade - /// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`: - /// let buf: &mut [u8; 2048] = unsafe { + /// // the `&mut MaybeUninit<[u8; 1024]>` to a `&mut [u8; 1024]`: + /// let buf: &mut [u8; 1024] = unsafe { /// // SAFETY: `buf` has been initialized. /// buf.assume_init_mut() /// }; diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index c4f0d91767..c6750c52d1 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -297,7 +297,7 @@ pub fn forget_unsized(t: T) { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_size_of", since = "1.32.0")] +#[rustc_const_stable(feature = "const_size_of", since = "1.24.0")] pub const fn size_of() -> usize { intrinsics::size_of::() } @@ -440,7 +440,7 @@ pub fn min_align_of_val(val: &T) -> usize { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_align_of", since = "1.32.0")] +#[rustc_const_stable(feature = "const_align_of", since = "1.24.0")] pub const fn align_of() -> usize { intrinsics::min_align_of::() } @@ -884,7 +884,6 @@ pub fn replace(dest: &mut T, src: T) -> T { /// ``` /// /// [`RefCell`]: crate::cell::RefCell -#[doc(alias = "delete")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn drop(_x: T) {} diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs index 6a1a1e1976..197b85fba1 100644 --- a/library/core/src/num/bignum.rs +++ b/library/core/src/num/bignum.rs @@ -181,11 +181,12 @@ macro_rules! define_bignum { /// Adds `other` to itself and returns its own mutable reference. pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; + use crate::iter; use crate::num::bignum::FullOps; let mut sz = cmp::max(self.size, other.size); let mut carry = false; - for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) { + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { let (c, v) = (*a).full_add(*b, carry); *a = v; carry = c; @@ -219,11 +220,12 @@ macro_rules! define_bignum { /// Subtracts `other` from itself and returns its own mutable reference. pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; + use crate::iter; use crate::num::bignum::FullOps; let sz = cmp::max(self.size, other.size); let mut noborrow = true; - for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) { + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { let (c, v) = (*a).full_add(!*b, noborrow); *a = v; noborrow = c; diff --git a/library/core/src/num/dec2flt/algorithm.rs b/library/core/src/num/dec2flt/algorithm.rs index a5fbdc6ee2..313b6870ac 100644 --- a/library/core/src/num/dec2flt/algorithm.rs +++ b/library/core/src/num/dec2flt/algorithm.rs @@ -62,10 +62,9 @@ mod fpu_precision { // any `u16` unsafe { asm!( - "fldcw ({})", + "fldcw word ptr [{}]", in(reg) &cw, - // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9. - options(att_syntax, nostack), + options(nostack), ) } } @@ -87,10 +86,9 @@ mod fpu_precision { // any `u16` unsafe { asm!( - "fnstcw ({})", + "fnstcw word ptr [{}]", in(reg) &mut cw, - // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9. - options(att_syntax, nostack), + options(nostack), ) } diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index 20ac165c6c..f008a64ffe 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -239,13 +239,15 @@ fn dec2flt(s: &str) -> Result { ParseResult::Valid(decimal) => convert(decimal)?, ParseResult::ShortcutToInf => T::INFINITY, ParseResult::ShortcutToZero => T::ZERO, - ParseResult::Invalid => match s { - "inf" => T::INFINITY, - "NaN" => T::NAN, - _ => { + 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 + } else { return Err(pfe_invalid()); } - }, + } }; match sign { diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 690247bc96..0d6d919d99 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -500,7 +500,6 @@ impl f32 { /// Returns `true` if the number is [subnormal]. /// /// ``` - /// #![feature(is_subnormal)] /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 /// let max = f32::MAX; /// let lower_than_min = 1.0e-40_f32; @@ -516,7 +515,7 @@ impl f32 { /// assert!(lower_than_min.is_subnormal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number - #[unstable(feature = "is_subnormal", issue = "79288")] + #[stable(feature = "is_subnormal", since = "1.53.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] pub const fn is_subnormal(self) -> bool { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 6d3737224c..42214e7b50 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -499,7 +499,6 @@ impl f64 { /// Returns `true` if the number is [subnormal]. /// /// ``` - /// #![feature(is_subnormal)] /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64 /// let max = f64::MAX; /// let lower_than_min = 1.0e-308_f64; @@ -515,7 +514,7 @@ impl f64 { /// assert!(lower_than_min.is_subnormal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number - #[unstable(feature = "is_subnormal", issue = "79288")] + #[stable(feature = "is_subnormal", since = "1.53.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] pub const fn is_subnormal(self) -> bool { diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs index e8f9d6574e..93bdf5040e 100644 --- a/library/core/src/num/flt2dec/mod.rs +++ b/library/core/src/num/flt2dec/mod.rs @@ -399,14 +399,10 @@ fn digits_to_exp_str<'a>( /// Sign formatting options. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Sign { - /// Prints `-` only for the negative non-zero values. - Minus, // -inf -1 0 0 1 inf nan - /// Prints `-` only for any negative values (including the negative zero). - MinusRaw, // -inf -1 -0 0 1 inf nan - /// Prints `-` for the negative non-zero values, or `+` otherwise. - MinusPlus, // -inf -1 +0 +0 +1 +inf nan - /// Prints `-` for any negative values (including the negative zero), or `+` otherwise. - MinusPlusRaw, // -inf -1 -0 +0 +1 +inf nan + /// Prints `-` for any negative value. + Minus, // -inf -1 -0 0 1 inf nan + /// Prints `-` for any negative value, or `+` otherwise. + MinusPlus, // -inf -1 -0 +0 +1 +inf nan } /// Returns the static byte string corresponding to the sign to be formatted. @@ -414,30 +410,14 @@ pub enum Sign { fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str { match (*decoded, sign) { (FullDecoded::Nan, _) => "", - (FullDecoded::Zero, Sign::Minus) => "", - (FullDecoded::Zero, Sign::MinusRaw) => { + (_, Sign::Minus) => { if negative { "-" } else { "" } } - (FullDecoded::Zero, Sign::MinusPlus) => "+", - (FullDecoded::Zero, Sign::MinusPlusRaw) => { - if negative { - "-" - } else { - "+" - } - } - (_, Sign::Minus | Sign::MinusRaw) => { - if negative { - "-" - } else { - "" - } - } - (_, Sign::MinusPlus | Sign::MinusPlusRaw) => { + (_, Sign::MinusPlus) => { if negative { "-" } else { diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index ce9dca39d0..4b341132e3 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -32,10 +32,9 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(int_bits_const)] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] /// ``` - #[unstable(feature = "int_bits_const", issue = "76904")] + #[stable(feature = "int_bits_const", since = "1.53.0")] pub const BITS: u32 = $BITS; /// Converts a string slice in a given base to an integer. @@ -80,7 +79,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] - #[inline] + #[inline(always)] pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } /// Returns the number of zeros in the binary representation of `self`. @@ -94,7 +93,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn count_zeros(self) -> u32 { (!self).count_ones() } @@ -112,7 +111,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn leading_zeros(self) -> u32 { (self as $UnsignedT).leading_zeros() } @@ -130,7 +129,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn trailing_zeros(self) -> u32 { (self as $UnsignedT).trailing_zeros() } @@ -148,7 +147,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] + #[inline(always)] pub const fn leading_ones(self) -> u32 { (self as $UnsignedT).leading_ones() } @@ -166,7 +165,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] + #[inline(always)] pub const fn trailing_ones(self) -> u32 { (self as $UnsignedT).trailing_ones() } @@ -190,7 +189,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn rotate_left(self, n: u32) -> Self { (self as $UnsignedT).rotate_left(n) as Self } @@ -215,7 +214,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn rotate_right(self, n: u32) -> Self { (self as $UnsignedT).rotate_right(n) as Self } @@ -235,7 +234,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn swap_bytes(self) -> Self { (self as $UnsignedT).swap_bytes() as Self } @@ -255,8 +254,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] + #[rustc_const_stable(feature = "const_int_methods", since = "1.37.0")] + #[inline(always)] #[must_use] pub const fn reverse_bits(self) -> Self { (self as $UnsignedT).reverse_bits() as Self @@ -417,7 +416,7 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub unsafe fn unchecked_add(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_add`. @@ -455,7 +454,7 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_sub`. @@ -493,7 +492,7 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_mul`. @@ -742,7 +741,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn saturating_add(self, rhs: Self) -> Self { intrinsics::saturating_add(self, rhs) } @@ -763,7 +762,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn saturating_sub(self, rhs: Self) -> Self { intrinsics::saturating_sub(self, rhs) } @@ -784,7 +783,7 @@ macro_rules! int_impl { #[stable(feature = "saturating_neg", since = "1.45.0")] #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[inline] + #[inline(always)] pub const fn saturating_neg(self) -> Self { intrinsics::saturating_sub(0, self) } @@ -884,7 +883,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_add(self, rhs: Self) -> Self { intrinsics::wrapping_add(self, rhs) } @@ -904,7 +903,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_sub(self, rhs: Self) -> Self { intrinsics::wrapping_sub(self, rhs) } @@ -924,7 +923,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_mul(self, rhs: Self) -> Self { intrinsics::wrapping_mul(self, rhs) } @@ -1082,7 +1081,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -1111,7 +1110,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -1226,7 +1225,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); (a as Self, b) @@ -1250,7 +1249,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); (a as Self, b) @@ -1273,7 +1272,7 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT); (a as Self, b) @@ -1589,11 +1588,11 @@ macro_rules! int_impl { /// Calculates the quotient of Euclidean division of `self` by `rhs`. /// - /// This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, - /// with `0 <= self.rem_euclid(rhs) < rhs`. + /// This computes the integer `q` such that `self = q * rhs + r`, with + /// `r = self.rem_euclid(rhs)` and `0 <= r < abs(rhs)`. /// - /// In other words, the result is `self / rhs` rounded to the integer `n` - /// such that `self >= n * rhs`. + /// In other words, the result is `self / rhs` rounded to the integer `q` + /// such that `self >= q * rhs`. /// If `self > 0`, this is equal to round towards zero (the default in Rust); /// if `self < 0`, this is equal to round towards +/- infinity. /// @@ -1726,7 +1725,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")] - #[inline] + #[inline(always)] pub const fn signum(self) -> Self { match self { n if n > 0 => 1, @@ -1748,7 +1747,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn is_positive(self) -> bool { self > 0 } /// Returns `true` if `self` is negative and `false` if the number is zero or @@ -1764,7 +1763,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn is_negative(self) -> bool { self < 0 } /// Return the memory representation of this integer as a byte array in diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f0bd976ba8..6032dc9a2d 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -2,6 +2,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::ascii; use crate::intrinsics; use crate::mem; use crate::str::FromStr; @@ -661,6 +662,31 @@ impl u8 { pub const fn is_ascii_control(&self) -> bool { matches!(*self, b'\0'..=b'\x1F' | b'\x7F') } + + /// Returns an iterator that produces an escaped version of a `u8`, + /// treating it as an ASCII character. + /// + /// The behavior is identical to [`ascii::escape_default`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(inherent_ascii_escape)] + /// + /// assert_eq!("0", b'0'.escape_ascii().to_string()); + /// assert_eq!("\\t", b'\t'.escape_ascii().to_string()); + /// assert_eq!("\\r", b'\r'.escape_ascii().to_string()); + /// assert_eq!("\\n", b'\n'.escape_ascii().to_string()); + /// assert_eq!("\\'", b'\''.escape_ascii().to_string()); + /// assert_eq!("\\\"", b'"'.escape_ascii().to_string()); + /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string()); + /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string()); + /// ``` + #[unstable(feature = "inherent_ascii_escape", issue = "77174")] + #[inline] + pub fn escape_ascii(&self) -> ascii::EscapeDefault { + ascii::escape_default(*self) + } } #[lang = "u16"] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 111feb7dbe..6b9b435d47 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -23,7 +23,7 @@ macro_rules! impl_nonzero_fmt { } macro_rules! nonzero_integers { - ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => { + ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => { $( /// An integer that is known not to equal zero. /// @@ -48,7 +48,7 @@ macro_rules! nonzero_integers { /// /// The value must not be zero. #[$stability] - #[rustc_const_stable(feature = "nonzero", since = "1.34.0")] + #[$const_new_unchecked_stability] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { // SAFETY: this is guaranteed to be safe by the caller. @@ -146,18 +146,18 @@ macro_rules! nonzero_integers { } nonzero_integers! { - #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); - #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); - #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); - #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); - #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); - #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); - #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); - #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); - #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); - #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); - #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); - #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } macro_rules! from_str_radix_nzint_impl { @@ -191,13 +191,12 @@ macro_rules! nonzero_leading_trailing_zeros { /// Basic usage: /// /// ``` - /// #![feature(nonzero_leading_trailing_zeros)] #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")] /// /// assert_eq!(n.leading_zeros(), 0); /// ``` - #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] - #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] #[inline] pub const fn leading_zeros(self) -> u32 { // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero @@ -214,13 +213,12 @@ macro_rules! nonzero_leading_trailing_zeros { /// Basic usage: /// /// ``` - /// #![feature(nonzero_leading_trailing_zeros)] #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] /// /// assert_eq!(n.trailing_zeros(), 3); /// ``` - #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] - #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] #[inline] pub const fn trailing_zeros(self) -> u32 { // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 7393e7f923..08d9161eff 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -32,10 +32,9 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_bits_const)] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] /// ``` - #[unstable(feature = "int_bits_const", issue = "76904")] + #[stable(feature = "int_bits_const", since = "1.53.0")] pub const BITS: u32 = $BITS; /// Converts a string slice in a given base to an integer. @@ -80,7 +79,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_math", since = "1.32.0")] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] - #[inline] + #[inline(always)] pub const fn count_ones(self) -> u32 { intrinsics::ctpop(self as $ActualT) as u32 } @@ -96,7 +95,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn count_zeros(self) -> u32 { (!self).count_ones() } @@ -114,7 +113,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn leading_zeros(self) -> u32 { intrinsics::ctlz(self as $ActualT) as u32 } @@ -133,7 +132,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn trailing_zeros(self) -> u32 { intrinsics::cttz(self) as u32 } @@ -151,7 +150,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] + #[inline(always)] pub const fn leading_ones(self) -> u32 { (!self).leading_zeros() } @@ -170,7 +169,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] - #[inline] + #[inline(always)] pub const fn trailing_ones(self) -> u32 { (!self).trailing_zeros() } @@ -194,7 +193,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn rotate_left(self, n: u32) -> Self { intrinsics::rotate_left(self, n as $SelfT) } @@ -219,7 +218,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn rotate_right(self, n: u32) -> Self { intrinsics::rotate_right(self, n as $SelfT) } @@ -238,7 +237,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn swap_bytes(self) -> Self { intrinsics::bswap(self as $ActualT) as Self } @@ -258,8 +257,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[rustc_const_stable(feature = "const_math", since = "1.37.0")] + #[inline(always)] #[must_use] pub const fn reverse_bits(self) -> Self { intrinsics::bitreverse(self as $ActualT) as Self @@ -285,7 +284,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn from_be(x: Self) -> Self { #[cfg(target_endian = "big")] { @@ -317,7 +316,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn from_le(x: Self) -> Self { #[cfg(target_endian = "little")] { @@ -349,7 +348,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn to_be(self) -> Self { // or not to be? #[cfg(target_endian = "big")] { @@ -381,7 +380,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn to_le(self) -> Self { #[cfg(target_endian = "little")] { @@ -427,7 +426,7 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub unsafe fn unchecked_add(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_add`. @@ -465,7 +464,7 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_sub`. @@ -503,7 +502,7 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { // SAFETY: the caller must uphold the safety contract for // `unchecked_mul`. @@ -728,7 +727,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[inline] + #[inline(always)] pub const fn saturating_add(self, rhs: Self) -> Self { intrinsics::saturating_add(self, rhs) } @@ -748,7 +747,7 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] - #[inline] + #[inline(always)] pub const fn saturating_sub(self, rhs: Self) -> Self { intrinsics::saturating_sub(self, rhs) } @@ -814,7 +813,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_add(self, rhs: Self) -> Self { intrinsics::wrapping_add(self, rhs) } @@ -834,7 +833,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_sub(self, rhs: Self) -> Self { intrinsics::wrapping_sub(self, rhs) } @@ -857,7 +856,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_mul(self, rhs: Self) -> Self { intrinsics::wrapping_mul(self, rhs) } @@ -879,7 +878,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_div(self, rhs: Self) -> Self { self / rhs } @@ -904,7 +903,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } @@ -927,7 +926,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_rem(self, rhs: Self) -> Self { self % rhs } @@ -953,7 +952,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } @@ -1009,7 +1008,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -1041,7 +1040,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -1107,7 +1106,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); (a as Self, b) @@ -1132,7 +1131,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); (a as Self, b) @@ -1159,7 +1158,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT); (a as Self, b) @@ -1183,7 +1182,7 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")] /// ``` - #[inline] + #[inline(always)] #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ @@ -1213,7 +1212,7 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")] /// ``` - #[inline] + #[inline(always)] #[stable(feature = "euclidean_division", since = "1.38.0")] #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ @@ -1240,7 +1239,7 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")] /// ``` - #[inline] + #[inline(always)] #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ @@ -1270,7 +1269,7 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")] /// ``` - #[inline] + #[inline(always)] #[stable(feature = "euclidean_division", since = "1.38.0")] #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ @@ -1294,7 +1293,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false));")] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!($SelfT), ", true));")] /// ``` - #[inline] + #[inline(always)] #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] pub const fn overflowing_neg(self) -> (Self, bool) { @@ -1321,7 +1320,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) } @@ -1346,7 +1345,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) } @@ -1459,7 +1458,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] #[rustc_inherit_overflow_checks] pub const fn div_euclid(self, rhs: Self) -> Self { self / rhs @@ -1487,7 +1486,7 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[inline] + #[inline(always)] #[rustc_inherit_overflow_checks] pub const fn rem_euclid(self, rhs: Self) -> Self { self % rhs @@ -1505,7 +1504,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")] - #[inline] + #[inline(always)] pub const fn is_power_of_two(self) -> bool { self.count_ones() == 1 } diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 92090d8e6f..a0577b287c 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -456,9 +456,13 @@ pub trait Div { } macro_rules! div_impl_integer { - ($($t:ty)*) => ($( + ($(($($t:ty)*) => $panic:expr),*) => ($($( /// This operation rounds towards zero, truncating any /// fractional part of the exact result. + /// + /// # Panics + /// + #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] impl Div for $t { type Output = $t; @@ -468,10 +472,13 @@ macro_rules! div_impl_integer { } forward_ref_binop! { impl Div, div for $t, $t } - )*) + )*)*) } -div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } +div_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or the division results in overflow." +} macro_rules! div_impl_float { ($($t:ty)*) => ($( @@ -549,9 +556,13 @@ pub trait Rem { } macro_rules! rem_impl_integer { - ($($t:ty)*) => ($( + ($(($($t:ty)*) => $panic:expr),*) => ($($( /// This operation satisfies `n % d == n - (n / d) * d`. The /// result has the same sign as the left operand. + /// + /// # Panics + /// + #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] impl Rem for $t { type Output = $t; @@ -561,10 +572,13 @@ macro_rules! rem_impl_integer { } forward_ref_binop! { impl Rem, rem for $t, $t } - )*) + )*)*) } -rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } +rem_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or if `self / other` results in overflow." +} macro_rules! rem_impl_float { ($($t:ty)*) => ($( diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 2f78ba8f28..ecaff053bd 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -1,4 +1,5 @@ -use crate::ops::Try; +use crate::convert; +use crate::ops::{self, Try}; /// Used to tell an operation whether it should exit early or go on as usual. /// @@ -81,6 +82,35 @@ impl Try for ControlFlow { } } +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::TryV2 for ControlFlow { + type Output = C; + type Residual = ControlFlow; + + #[inline] + fn from_output(output: Self::Output) -> Self { + ControlFlow::Continue(output) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + ControlFlow::Continue(c) => ControlFlow::Continue(c), + ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::FromResidual for ControlFlow { + #[inline] + fn from_residual(residual: ControlFlow) -> Self { + match residual { + ControlFlow::Break(b) => ControlFlow::Break(b), + } + } +} + impl ControlFlow { /// Returns `true` if this is a `Break` variant. /// diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 10e3ce6744..dcf3ce070e 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -65,7 +65,7 @@ pub trait Deref { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "deref_target"] - #[cfg_attr(not(bootstrap), lang = "deref_target")] + #[lang = "deref_target"] type Target: ?Sized; /// Dereferences the value. diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index ce7d1c3d06..f4b1ec377d 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -78,7 +78,7 @@ /// /// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error. /// -/// If you'd like explicitly call the destructor of a value, [`mem::drop`] can be used instead. +/// If you'd like to explicitly call the destructor of a value, [`mem::drop`] can be used instead. /// /// [`mem::drop`]: drop /// diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index a8dea4e9b4..964378cc9c 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -61,6 +61,10 @@ pub trait Index { type Output: ?Sized; /// Performs the indexing (`container[index]`) operation. + /// + /// # Panics + /// + /// May panic if the index is out of bounds. #[stable(feature = "rust1", since = "1.0.0")] #[track_caller] fn index(&self, index: Idx) -> &Self::Output; @@ -161,6 +165,10 @@ see chapter in The Book : Index { /// Performs the mutable indexing (`container[index]`) operation. + /// + /// # Panics + /// + /// May panic if the index is out of bounds. #[stable(feature = "rust1", since = "1.0.0")] #[track_caller] fn index_mut(&mut self, index: Idx) -> &mut Self::Output; diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 354ad6b7b7..1b07936ccd 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -148,6 +148,7 @@ mod generator; mod index; mod range; mod r#try; +mod try_trait; mod unsize; #[stable(feature = "rust1", since = "1.0.0")] @@ -184,6 +185,12 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; #[unstable(feature = "try_trait", issue = "42327")] pub use self::r#try::Try; +#[unstable(feature = "try_trait_v2", issue = "84277")] +pub use self::try_trait::FromResidual; + +#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] +pub use self::try_trait::Try as TryV2; + #[unstable(feature = "generator_trait", issue = "43122")] pub use self::generator::{Generator, GeneratorState}; diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs new file mode 100644 index 0000000000..0c819b000a --- /dev/null +++ b/library/core/src/ops/try_trait.rs @@ -0,0 +1,243 @@ +use crate::ops::ControlFlow; + +/// The `?` operator and `try {}` blocks. +/// +/// `try_*` methods typically involve a type implementing this trait. For +/// example, the closures passed to [`Iterator::try_fold`] and +/// [`Iterator::try_for_each`] must return such a type. +/// +/// `Try` types are typically those containing two or more categories of values, +/// some subset of which are so commonly handled via early returns that it's +/// worth providing a terse (but still visible) syntax to make that easy. +/// +/// This is most often seen for error handling with [`Result`] and [`Option`]. +/// The quintessential implementation of this trait is on [`ControlFlow`]. +/// +/// # Using `Try` in Generic Code +/// +/// `Iterator::try_fold` was stabilized to call back in Rust 1.27, but +/// this trait is much newer. To illustrate the various associated types and +/// methods, let's implement our own version. +/// +/// As a reminder, an infallible version of a fold looks something like this: +/// ``` +/// fn simple_fold( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> A, +/// ) -> A { +/// for x in iter { +/// accum = f(accum, x); +/// } +/// accum +/// } +/// ``` +/// +/// So instead of `f` returning just an `A`, we'll need it to return some other +/// type that produces an `A` in the "don't short circuit" path. Conveniently, +/// that's also the type we need to return from the function. +/// +/// Let's add a new generic parameter `R` for that type, and bound it to the +/// output type that we want: +/// ``` +/// # #![feature(try_trait_v2)] +/// # #![feature(try_trait_transition)] +/// # use std::ops::TryV2 as Try; +/// fn simple_try_fold_1>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// todo!() +/// } +/// ``` +/// +/// If we get through the entire iterator, we need to wrap up the accumulator +/// into the return type using [`Try::from_output`]: +/// ``` +/// # #![feature(try_trait_v2)] +/// # #![feature(try_trait_transition)] +/// # #![feature(control_flow_enum)] +/// # use std::ops::{ControlFlow, TryV2 as Try}; +/// fn simple_try_fold_2>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// let cf = f(accum, x).branch(); +/// match cf { +/// ControlFlow::Continue(a) => accum = a, +/// ControlFlow::Break(_) => todo!(), +/// } +/// } +/// R::from_output(accum) +/// } +/// ``` +/// +/// We'll also need [`FromResidual::from_residual`] to turn the residual back +/// into the original type. But because it's a supertrait of `Try`, we don't +/// need to mention it in the bounds. All types which implement `Try` can be +/// recreated from their corresponding residual, so we'll just call it: +/// ``` +/// # #![feature(try_trait_v2)] +/// # #![feature(try_trait_transition)] +/// # #![feature(control_flow_enum)] +/// # use std::ops::{ControlFlow, TryV2 as Try}; +/// pub fn simple_try_fold_3>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// let cf = f(accum, x).branch(); +/// match cf { +/// ControlFlow::Continue(a) => accum = a, +/// ControlFlow::Break(r) => return R::from_residual(r), +/// } +/// } +/// R::from_output(accum) +/// } +/// ``` +/// +/// But this "call `branch`, then `match` on it, and `return` if it was a +/// `Break`" is exactly what happens inside the `?` operator. So rather than +/// do all this manually, we can just use `?` instead: +/// ```compile_fail (enable again once ? converts to the new trait) +/// # #![feature(try_trait_v2)] +/// # #![feature(try_trait_transition)] +/// # use std::ops::TryV2 as Try; +/// fn simple_try_fold>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// accum = f(accum, x)?; +/// } +/// R::from_output(accum) +/// } +/// ``` +#[unstable(feature = "try_trait_v2", issue = "84277")] +pub trait Try: FromResidual { + /// The type of the value produced by `?` when *not* short-circuiting. + #[unstable(feature = "try_trait_v2", issue = "84277")] + type Output; + + /// The type of the value passed to [`FromResidual::from_residual`] + /// as part of `?` when short-circuiting. + /// + /// This represents the possible values of the `Self` type which are *not* + /// represented by the `Output` type. + /// + /// # Note to Implementors + /// + /// The choice of this type is critical to interconversion. + /// Unlike the `Output` type, which will often be a raw generic type, + /// this type is typically a newtype of some sort to "color" the type + /// so that it's distinguishable from the residuals of other types. + /// + /// This is why `Result::Residual` is not `E`, but `Result`. + /// That way it's distinct from `ControlFlow::Residual`, for example, + /// and thus `?` on `ControlFlow` cannot be used in a method returning `Result`. + /// + /// If you're making a generic type `Foo` that implements `Try`, + /// then typically you can use `Foo` as its `Residual` + /// type: that type will have a "hole" in the correct place, and will maintain the + /// "foo-ness" of the residual so other types need to opt-in to interconversion. + #[unstable(feature = "try_trait_v2", issue = "84277")] + type Residual; + + /// Constructs the type from its `Output` type. + /// + /// This should be implemented consistently with the `branch` method + /// such that applying the `?` operator will get back the original value: + /// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// #![feature(control_flow_enum)] + /// #![feature(try_trait_transition)] + /// use std::ops::TryV2 as Try; + /// + /// assert_eq!( as Try>::from_output(3), Ok(3)); + /// assert_eq!( as Try>::from_output(4), Some(4)); + /// assert_eq!( + /// as Try>::from_output(5), + /// std::ops::ControlFlow::Continue(5), + /// ); + /// + /// # fn make_question_mark_work() -> Option<()> { + /// assert_eq!(Option::from_output(4)?, 4); + /// # None } + /// # make_question_mark_work(); + /// + /// // This is used, for example, on the accumulator in `try_fold`: + /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() }); + /// assert_eq!(r, Some(4)); + /// ``` + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn from_output(output: Self::Output) -> Self; + + /// Used in `?` to decide whether the operator should produce a value + /// (because this returned [`ControlFlow::Continue`]) + /// or propagate a value back to the caller + /// (because this returned [`ControlFlow::Break`]). + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// #![feature(control_flow_enum)] + /// #![feature(try_trait_transition)] + /// use std::ops::{ControlFlow, TryV2 as Try}; + /// + /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!(Err::(3).branch(), ControlFlow::Break(Err(3))); + /// + /// assert_eq!(Some(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!(None::.branch(), ControlFlow::Break(None)); + /// + /// assert_eq!(ControlFlow::::Continue(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!( + /// ControlFlow::<_, String>::Break(3).branch(), + /// ControlFlow::Break(ControlFlow::Break(3)), + /// ); + /// ``` + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn branch(self) -> ControlFlow; +} + +/// Used to specify which residuals can be converted into which [`Try`] types. +/// +/// Every `Try` type needs to be recreatable from its own associated +/// `Residual` type, but can also have additional `FromResidual` implementations +/// to support interconversion with other `Try` types. +#[unstable(feature = "try_trait_v2", issue = "84277")] +pub trait FromResidual::Residual> { + /// Constructs the type from a compatible `Residual` type. + /// + /// This should be implemented consistently with the `branch` method such + /// that applying the `?` operator will get back an equivalent residual: + /// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`. + /// (It may not be an *identical* residual when interconversion is involved.) + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// #![feature(control_flow_enum)] + /// use std::ops::{ControlFlow, FromResidual}; + /// + /// assert_eq!(Result::::from_residual(Err(3_u8)), Err(3)); + /// assert_eq!(Option::::from_residual(None), None); + /// assert_eq!( + /// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)), + /// ControlFlow::Break(5), + /// ); + /// ``` + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn from_residual(residual: R) -> Self; +} diff --git a/library/core/src/option.rs b/library/core/src/option.rs index f1a0f455cd..04551dded8 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -150,8 +150,8 @@ use crate::iter::{FromIterator, FusedIterator, TrustedLen}; use crate::pin::Pin; use crate::{ - fmt, hint, mem, - ops::{self, Deref, DerefMut}, + convert, hint, mem, + ops::{self, ControlFlow, Deref, DerefMut}, }; /// The `Option` type. See [the module level documentation](self) for more. @@ -489,8 +489,8 @@ impl Option { } } - /// Applies a function to the contained value (if any), - /// or returns the provided default (if not). + /// Returns the provided default result (if none), + /// or applies a function to the contained value (if any). /// /// Arguments passed to `map_or` are eagerly evaluated; if you are passing /// the result of a function call, it is recommended to use [`map_or_else`], @@ -516,8 +516,8 @@ impl Option { } } - /// Applies a function to the contained value (if any), - /// or computes a default (if not). + /// Computes a default function result (if none), or + /// applies a different function to the contained value (if any). /// /// # Examples /// @@ -594,36 +594,6 @@ impl Option { } } - /// Inserts `value` into the option then returns a mutable reference to it. - /// - /// If the option already contains a value, the old value is dropped. - /// - /// # Example - /// - /// ``` - /// #![feature(option_insert)] - /// - /// let mut opt = None; - /// let val = opt.insert(1); - /// assert_eq!(*val, 1); - /// assert_eq!(opt.unwrap(), 1); - /// let val = opt.insert(2); - /// assert_eq!(*val, 2); - /// *val = 3; - /// assert_eq!(opt.unwrap(), 3); - /// ``` - #[inline] - #[unstable(feature = "option_insert", reason = "newly added", issue = "78271")] - pub fn insert(&mut self, value: T) -> &mut T { - *self = Some(value); - - match self { - Some(v) => v, - // SAFETY: the code above just filled the option - None => unsafe { hint::unreachable_unchecked() }, - } - } - ///////////////////////////////////////////////////////////////////////// // Iterator constructors ///////////////////////////////////////////////////////////////////////// @@ -851,12 +821,46 @@ impl Option { } ///////////////////////////////////////////////////////////////////////// - // Entry-like operations to insert if None and return a reference + // Entry-like operations to insert a value and return a reference ///////////////////////////////////////////////////////////////////////// + /// Inserts `value` into the option then returns a mutable reference to it. + /// + /// If the option already contains a value, the old value is dropped. + /// + /// See also [`Option::get_or_insert`], which doesn't update the value if + /// the option already contains [`Some`]. + /// + /// # Example + /// + /// ``` + /// let mut opt = None; + /// let val = opt.insert(1); + /// assert_eq!(*val, 1); + /// assert_eq!(opt.unwrap(), 1); + /// let val = opt.insert(2); + /// assert_eq!(*val, 2); + /// *val = 3; + /// assert_eq!(opt.unwrap(), 3); + /// ``` + #[inline] + #[stable(feature = "option_insert", since = "1.53.0")] + pub fn insert(&mut self, value: T) -> &mut T { + *self = Some(value); + + match self { + Some(v) => v, + // SAFETY: the code above just filled the option + None => unsafe { hint::unreachable_unchecked() }, + } + } + /// Inserts `value` into the option if it is [`None`], then /// returns a mutable reference to the contained value. /// + /// See also [`Option::insert`], which updates the value even if + /// the option already contains [`Some`]. + /// /// # Examples /// /// ``` @@ -1121,90 +1125,6 @@ impl Option<&mut T> { } } -impl Option { - /// Consumes `self` while expecting [`None`] and returning nothing. - /// - /// # Panics - /// - /// Panics if the value is a [`Some`], with a panic message including the - /// passed message, and the content of the [`Some`]. - /// - /// # Examples - /// - /// ``` - /// #![feature(option_expect_none)] - /// - /// use std::collections::HashMap; - /// let mut squares = HashMap::new(); - /// for i in -10..=10 { - /// // This will not panic, since all keys are unique. - /// squares.insert(i, i * i).expect_none("duplicate key"); - /// } - /// ``` - /// - /// ```should_panic - /// #![feature(option_expect_none)] - /// - /// use std::collections::HashMap; - /// let mut sqrts = HashMap::new(); - /// for i in -10..=10 { - /// // This will panic, since both negative and positive `i` will - /// // insert the same `i * i` key, returning the old `Some(i)`. - /// sqrts.insert(i * i, i).expect_none("duplicate key"); - /// } - /// ``` - #[inline] - #[track_caller] - #[unstable(feature = "option_expect_none", reason = "newly added", issue = "62633")] - pub fn expect_none(self, msg: &str) { - if let Some(val) = self { - expect_none_failed(msg, &val); - } - } - - /// Consumes `self` while expecting [`None`] and returning nothing. - /// - /// # Panics - /// - /// Panics if the value is a [`Some`], with a custom panic message provided - /// by the [`Some`]'s value. - /// - /// [`Some(v)`]: Some - /// - /// # Examples - /// - /// ``` - /// #![feature(option_unwrap_none)] - /// - /// use std::collections::HashMap; - /// let mut squares = HashMap::new(); - /// for i in -10..=10 { - /// // This will not panic, since all keys are unique. - /// squares.insert(i, i * i).unwrap_none(); - /// } - /// ``` - /// - /// ```should_panic - /// #![feature(option_unwrap_none)] - /// - /// use std::collections::HashMap; - /// let mut sqrts = HashMap::new(); - /// for i in -10..=10 { - /// // This will panic, since both negative and positive `i` will - /// // insert the same `i * i` key, returning the old `Some(i)`. - /// sqrts.insert(i * i, i).unwrap_none(); - /// } - /// ``` - #[inline] - #[track_caller] - #[unstable(feature = "option_unwrap_none", reason = "newly added", issue = "62633")] - pub fn unwrap_none(self) { - if let Some(val) = self { - expect_none_failed("called `Option::unwrap_none()` on a `Some` value", &val); - } - } -} - impl Option { /// Returns the contained [`Some`] value or a default /// @@ -1321,14 +1241,6 @@ fn expect_failed(msg: &str) -> ! { panic!("{}", msg) } -// This is a separate function to reduce the code size of .expect_none() itself. -#[inline(never)] -#[cold] -#[track_caller] -fn expect_none_failed(msg: &str, value: &dyn fmt::Debug) -> ! { - panic!("{}: {:?}", msg, value) -} - ///////////////////////////////////////////////////////////////////////////// // Trait implementations ///////////////////////////////////////////////////////////////////////////// @@ -1752,6 +1664,35 @@ impl ops::Try for Option { } } +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::TryV2 for Option { + type Output = T; + type Residual = Option; + + #[inline] + fn from_output(output: Self::Output) -> Self { + Some(output) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Some(v) => ControlFlow::Continue(v), + None => ControlFlow::Break(None), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::FromResidual for Option { + #[inline] + fn from_residual(residual: Option) -> Self { + match residual { + None => None, + } + } +} + impl Option> { /// Converts from `Option>` to `Option` /// diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index b2de0e16a1..3d88829948 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -6,7 +6,7 @@ //! as moving an object with pointers to itself will invalidate them, which could cause undefined //! behavior. //! -//! At a high level, a [`Pin